From 6d6db12c79a449443d177cf9a94727aaca804394 Mon Sep 17 00:00:00 2001 From: Sergey Matyunin Date: Sat, 22 Aug 2026 20:23:20 +0300 Subject: [PATCH] fix(openings): center symbols across wall depth Issue: #242 User-Visible: yes --- .../houseplan/frontend/houseplan-card.js | 152 +++++++++--------- demo/golden/matrix.mjs | 4 +- demo/smoke_wall_thickness.mjs | 18 ++- demo/srv/assets/houseplan-card.js | 152 +++++++++--------- dist/houseplan-card.js | 152 +++++++++--------- docs/ARCHITECTURE.md | 6 +- docs/CHANGELOG.md | 7 + docs/CHANGELOG.ru.md | 8 + docs/ISOMETRIC.md | 4 + docs/USER-GUIDE.ru.md | 9 +- docs/WALL-THICKNESS.md | 14 +- scripts/mutation-gate.mjs | 36 +++++ src/iso-openings.ts | 4 +- src/opening-symbol-placement.ts | 36 +++++ src/render/opening-symbol.ts | 22 +-- src/wall-thickness.ts | 25 +-- test/iso-openings.test.mjs | 29 ++++ test/opening-symbol-placement.test.mjs | 30 ++++ test/opening-symbol.test.mjs | 30 +++- test/wall-thickness.test.mjs | 12 +- 20 files changed, 470 insertions(+), 280 deletions(-) create mode 100644 src/opening-symbol-placement.ts create mode 100644 test/opening-symbol-placement.test.mjs diff --git a/custom_components/houseplan/frontend/houseplan-card.js b/custom_components/houseplan/frontend/houseplan-card.js index 45dc4d94..c9e48e35 100755 --- a/custom_components/houseplan/frontend/houseplan-card.js +++ b/custom_components/houseplan/frontend/houseplan-card.js @@ -1,4 +1,4 @@ -globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="5ca433d2ee8bf92a41f4597ac53777315a9c203b421d7f256fe783d065d2a7fa";const t=globalThis,e=t.ShadowRoot&&(void 0===t.ShadyCSS||t.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,i=Symbol(),s=new WeakMap;let n=class{constructor(t,e,s){if(this._$cssResult$=!0,s!==i)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=t,this.t=e}get styleSheet(){let t=this.o;const i=this.t;if(e&&void 0===t){const e=void 0!==i&&1===i.length;e&&(t=s.get(i)),void 0===t&&((this.o=t=new CSSStyleSheet).replaceSync(this.cssText),e&&s.set(i,t))}return t}toString(){return this.cssText}};const o=(t,...e)=>{const s=1===t.length?t[0]:e.reduce((e,i,s)=>e+(t=>{if(!0===t._$cssResult$)return t.cssText;if("number"==typeof t)return t;throw Error("Value passed to 'css' function must be a 'css' function result: "+t+". Use 'unsafeCSS' to pass non-literal values, but take care to ensure page security.")})(i)+t[s+1],t[0]);return new n(s,t,i)},a=e?t=>t:t=>t instanceof CSSStyleSheet?(t=>{let e="";for(const i of t.cssRules)e+=i.cssText;return(t=>new n("string"==typeof t?t:t+"",void 0,i))(e)})(t):t,{is:r,defineProperty:l,getOwnPropertyDescriptor:c,getOwnPropertyNames:h,getOwnPropertySymbols:d,getPrototypeOf:u}=Object,p=globalThis,_=p.trustedTypes,g=_?_.emptyScript:"",m=p.reactiveElementPolyfillSupport,f=(t,e)=>t,v={toAttribute(t,e){switch(e){case Boolean:t=t?g:null;break;case Object:case Array:t=null==t?t:JSON.stringify(t)}return t},fromAttribute(t,e){let i=t;switch(e){case Boolean:i=null!==t;break;case Number:i=null===t?null:Number(t);break;case Object:case Array:try{i=JSON.parse(t)}catch(t){i=null}}return i}},y=(t,e)=>!r(t,e),b={attribute:!0,type:String,converter:v,reflect:!1,useDefault:!1,hasChanged:y};Symbol.metadata??=Symbol("metadata"),p.litPropertyMetadata??=new WeakMap;let w=class extends HTMLElement{static addInitializer(t){this._$Ei(),(this.l??=[]).push(t)}static get observedAttributes(){return this.finalize(),this._$Eh&&[...this._$Eh.keys()]}static createProperty(t,e=b){if(e.state&&(e.attribute=!1),this._$Ei(),this.prototype.hasOwnProperty(t)&&((e=Object.create(e)).wrapped=!0),this.elementProperties.set(t,e),!e.noAccessor){const i=Symbol(),s=this.getPropertyDescriptor(t,i,e);void 0!==s&&l(this.prototype,t,s)}}static getPropertyDescriptor(t,e,i){const{get:s,set:n}=c(this.prototype,t)??{get(){return this[e]},set(t){this[e]=t}};return{get:s,set(e){const o=s?.call(this);n?.call(this,e),this.requestUpdate(t,o,i)},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)??b}static _$Ei(){if(this.hasOwnProperty(f("elementProperties")))return;const t=u(this);t.finalize(),void 0!==t.l&&(this.l=[...t.l]),this.elementProperties=new Map(t.elementProperties)}static finalize(){if(this.hasOwnProperty(f("finalized")))return;if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(f("properties"))){const t=this.properties,e=[...h(t),...d(t)];for(const i of e)this.createProperty(i,t[i])}const t=this[Symbol.metadata];if(null!==t){const e=litPropertyMetadata.get(t);if(void 0!==e)for(const[t,i]of e)this.elementProperties.set(t,i)}this._$Eh=new Map;for(const[t,e]of this.elementProperties){const i=this._$Eu(t,e);void 0!==i&&this._$Eh.set(i,t)}this.elementStyles=this.finalizeStyles(this.styles)}static finalizeStyles(t){const e=[];if(Array.isArray(t)){const i=new Set(t.flat(1/0).reverse());for(const t of i)e.unshift(a(t))}else void 0!==t&&e.push(a(t));return e}static _$Eu(t,e){const i=e.attribute;return!1===i?void 0:"string"==typeof i?i:"string"==typeof t?t.toLowerCase():void 0}constructor(){super(),this._$Ep=void 0,this.isUpdatePending=!1,this.hasUpdated=!1,this._$Em=null,this._$Ev()}_$Ev(){this._$ES=new Promise(t=>this.enableUpdating=t),this._$AL=new Map,this._$E_(),this.requestUpdate(),this.constructor.l?.forEach(t=>t(this))}addController(t){(this._$EO??=new Set).add(t),void 0!==this.renderRoot&&this.isConnected&&t.hostConnected?.()}removeController(t){this._$EO?.delete(t)}_$E_(){const t=new Map,e=this.constructor.elementProperties;for(const i of e.keys())this.hasOwnProperty(i)&&(t.set(i,this[i]),delete this[i]);t.size>0&&(this._$Ep=t)}createRenderRoot(){const i=this.shadowRoot??this.attachShadow(this.constructor.shadowRootOptions);return((i,s)=>{if(e)i.adoptedStyleSheets=s.map(t=>t instanceof CSSStyleSheet?t:t.styleSheet);else for(const e of s){const s=document.createElement("style"),n=t.litNonce;void 0!==n&&s.setAttribute("nonce",n),s.textContent=e.cssText,i.appendChild(s)}})(i,this.constructor.elementStyles),i}connectedCallback(){this.renderRoot??=this.createRenderRoot(),this.enableUpdating(!0),this._$EO?.forEach(t=>t.hostConnected?.())}enableUpdating(t){}disconnectedCallback(){this._$EO?.forEach(t=>t.hostDisconnected?.())}attributeChangedCallback(t,e,i){this._$AK(t,i)}_$ET(t,e){const i=this.constructor.elementProperties.get(t),s=this.constructor._$Eu(t,i);if(void 0!==s&&!0===i.reflect){const n=(void 0!==i.converter?.toAttribute?i.converter:v).toAttribute(e,i.type);this._$Em=t,null==n?this.removeAttribute(s):this.setAttribute(s,n),this._$Em=null}}_$AK(t,e){const i=this.constructor,s=i._$Eh.get(t);if(void 0!==s&&this._$Em!==s){const t=i.getPropertyOptions(s),n="function"==typeof t.converter?{fromAttribute:t.converter}:void 0!==t.converter?.fromAttribute?t.converter:v;this._$Em=s;const o=n.fromAttribute(e,t.type);this[s]=o??this._$Ej?.get(s)??o,this._$Em=null}}requestUpdate(t,e,i,s=!1,n){if(void 0!==t){const o=this.constructor;if(!1===s&&(n=this[t]),i??=o.getPropertyOptions(t),!((i.hasChanged??y)(n,e)||i.useDefault&&i.reflect&&n===this._$Ej?.get(t)&&!this.hasAttribute(o._$Eu(t,i))))return;this.C(t,e,i)}!1===this.isUpdatePending&&(this._$ES=this._$EP())}C(t,e,{useDefault:i,reflect:s,wrapped:n},o){i&&!(this._$Ej??=new Map).has(t)&&(this._$Ej.set(t,o??e??this[t]),!0!==n||void 0!==o)||(this._$AL.has(t)||(this.hasUpdated||i||(e=void 0),this._$AL.set(t,e)),!0===s&&this._$Em!==t&&(this._$Eq??=new Set).add(t))}async _$EP(){this.isUpdatePending=!0;try{await this._$ES}catch(t){Promise.reject(t)}const t=this.scheduleUpdate();return null!=t&&await t,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){if(!this.isUpdatePending)return;if(!this.hasUpdated){if(this.renderRoot??=this.createRenderRoot(),this._$Ep){for(const[t,e]of this._$Ep)this[t]=e;this._$Ep=void 0}const t=this.constructor.elementProperties;if(t.size>0)for(const[e,i]of t){const{wrapped:t}=i,s=this[e];!0!==t||this._$AL.has(e)||void 0===s||this.C(e,void 0,i,s)}}let t=!1;const e=this._$AL;try{t=this.shouldUpdate(e),t?(this.willUpdate(e),this._$EO?.forEach(t=>t.hostUpdate?.()),this.update(e)):this._$EM()}catch(e){throw t=!1,this._$EM(),e}t&&this._$AE(e)}willUpdate(t){}_$AE(t){this._$EO?.forEach(t=>t.hostUpdated?.()),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(t)),this.updated(t)}_$EM(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$ES}shouldUpdate(t){return!0}update(t){this._$Eq&&=this._$Eq.forEach(t=>this._$ET(t,this[t])),this._$EM()}updated(t){}firstUpdated(t){}};w.elementStyles=[],w.shadowRootOptions={mode:"open"},w[f("elementProperties")]=new Map,w[f("finalized")]=new Map,m?.({ReactiveElement:w}),(p.reactiveElementVersions??=[]).push("2.1.2");const k=globalThis,x=t=>t,$=k.trustedTypes,S=$?$.createPolicy("lit-html",{createHTML:t=>t}):void 0,M="$lit$",C=`lit$${Math.random().toFixed(9).slice(2)}$`,D="?"+C,T=`<${D}>`,P=document,R=()=>P.createComment(""),I=t=>null===t||"object"!=typeof t&&"function"!=typeof t,A=Array.isArray,F="[ \t\n\f\r]",E=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,z=/-->/g,O=/>/g,N=RegExp(`>|${F}(?:([^\\s"'>=/]+)(${F}*=${F}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),H=/'/g,L=/"/g,B=/^(?:script|style|textarea|title)$/i,q=t=>(e,...i)=>({_$litType$:t,strings:e,values:i}),W=q(1),j=q(2),U=Symbol.for("lit-noChange"),G=Symbol.for("lit-nothing"),V=new WeakMap,K=P.createTreeWalker(P,129);function Y(t,e){if(!A(t)||!t.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==S?S.createHTML(e):e}const X=(t,e)=>{const i=t.length-1,s=[];let n,o=2===e?"":3===e?"":"",a=E;for(let e=0;e"===l[0]?(a=n??E,c=-1):void 0===l[1]?c=-2:(c=a.lastIndex-l[2].length,r=l[1],a=void 0===l[3]?N:'"'===l[3]?L:H):a===L||a===H?a=N:a===z||a===O?a=E:(a=N,n=void 0);const d=a===N&&t[e+1].startsWith("/>")?" ":"";o+=a===E?i+T:c>=0?(s.push(r),i.slice(0,c)+M+i.slice(c)+C+d):i+C+(-2===c?e:d)}return[Y(t,o+(t[i]||"")+(2===e?"":3===e?"":"")),s]};class J{constructor({strings:t,_$litType$:e},i){let s;this.parts=[];let n=0,o=0;const a=t.length-1,r=this.parts,[l,c]=X(t,e);if(this.el=J.createElement(l,i),K.currentNode=this.el.content,2===e||3===e){const t=this.el.content.firstChild;t.replaceWith(...t.childNodes)}for(;null!==(s=K.nextNode())&&r.length0){s.textContent=$?$.emptyScript:"";for(let i=0;iA(t)||"function"==typeof t?.[Symbol.iterator])(t)?this.k(t):this._(t)}O(t){return this._$AA.parentNode.insertBefore(t,this._$AB)}T(t){this._$AH!==t&&(this._$AR(),this._$AH=this.O(t))}_(t){this._$AH!==G&&I(this._$AH)?this._$AA.nextSibling.data=t:this.T(P.createTextNode(t)),this._$AH=t}$(t){const{values:e,_$litType$:i}=t,s="number"==typeof i?this._$AC(t):(void 0===i.el&&(i.el=J.createElement(Y(i.h,i.h[0]),this.options)),i);if(this._$AH?._$AD===s)this._$AH.p(e);else{const t=new Q(s,this),i=t.u(this.options);t.p(e),this.T(i),this._$AH=t}}_$AC(t){let e=V.get(t.strings);return void 0===e&&V.set(t.strings,e=new J(t)),e}k(t){A(this._$AH)||(this._$AH=[],this._$AR());const e=this._$AH;let i,s=0;for(const n of t)s===e.length?e.push(i=new tt(this.O(R()),this.O(R()),this,this.options)):i=e[s],i._$AI(n),s++;s2||""!==i[0]||""!==i[1]?(this._$AH=Array(i.length-1).fill(new String),this.strings=i):this._$AH=G}_$AI(t,e=this,i,s){const n=this.strings;let o=!1;if(void 0===n)t=Z(this,t,e,0),o=!I(t)||t!==this._$AH&&t!==U,o&&(this._$AH=t);else{const s=t;let a,r;for(t=n[0],a=0;a{const s=i?.renderBefore??e;let n=s._$litPart$;if(void 0===n){const t=i?.renderBefore??null;s._$litPart$=n=new tt(e.insertBefore(R(),t),t,void 0,i??{})}return n._$AI(t),n},ct=globalThis;let ht=class extends w{constructor(){super(...arguments),this.renderOptions={host:this},this._$Do=void 0}createRenderRoot(){const t=super.createRenderRoot();return this.renderOptions.renderBefore??=t.firstChild,t}update(t){const e=this.render();this.hasUpdated||(this.renderOptions.isConnected=this.isConnected),super.update(t),this._$Do=lt(e,this.renderRoot,this.renderOptions)}connectedCallback(){super.connectedCallback(),this._$Do?.setConnected(!0)}disconnectedCallback(){super.disconnectedCallback(),this._$Do?.setConnected(!1)}render(){return U}};ht._$litElement$=!0,ht.finalized=!0,ct.litElementHydrateSupport?.({LitElement:ht});const dt=ct.litElementPolyfillSupport;dt?.({LitElement:ht}),(ct.litElementVersions??=[]).push("4.2.2");const ut=2,pt=t=>(...e)=>({_$litDirective$:t,values:e});let _t=class{constructor(t){}get _$AU(){return this._$AM._$AU}_$AT(t,e,i){this._$Ct=t,this._$AM=e,this._$Ci=i}_$AS(t,e){return this.update(t,e)}update(t,e){return this.render(...e)}};const gt={},mt=pt(class extends _t{constructor(){super(...arguments),this.ot=gt}render(t,e){return e()}update(t,[e,i]){if(Array.isArray(e)){if(Array.isArray(this.ot)&&this.ot.length===e.length&&e.every((t,e)=>t===this.ot[e]))return U}else if(this.ot===e)return U;return this.ot=Array.isArray(e)?Array.from(e):e,this.render(e,i)}}),{I:ft}=at,vt=t=>t,yt=()=>document.createComment(""),bt=(t,e,i)=>{const s=t._$AA.parentNode,n=void 0===e?t._$AB:e._$AA;if(void 0===i){const e=s.insertBefore(yt(),n),o=s.insertBefore(yt(),n);i=new ft(e,o,t,t.options)}else{const e=i._$AB.nextSibling,o=i._$AM,a=o!==t;if(a){let e;i._$AQ?.(t),i._$AM=t,void 0!==i._$AP&&(e=t._$AU)!==o._$AU&&i._$AP(e)}if(e!==n||a){let t=i._$AA;for(;t!==e;){const e=vt(t).nextSibling;vt(s).insertBefore(t,n),t=e}}}return i},wt=(t,e,i=t)=>(t._$AI(e,i),t),kt={},xt=(t,e=kt)=>t._$AH=e,$t=t=>{t._$AR(),t._$AA.remove()},St=(t,e,i)=>{const s=new Map;for(let n=e;n<=i;n++)s.set(t[n],n);return s},Mt=pt(class extends _t{constructor(t){if(super(t),t.type!==ut)throw Error("repeat() can only be used in text expressions")}dt(t,e,i){let s;void 0===i?i=e:void 0!==e&&(s=e);const n=[],o=[];let a=0;for(const e of t)n[a]=s?s(e,a):a,o[a]=i(e,a),a++;return{values:o,keys:n}}render(t,e,i){return this.dt(t,e,i).values}update(t,[e,i,s]){const n=(t=>t._$AH)(t),{values:o,keys:a}=this.dt(e,i,s);if(!Array.isArray(n))return this.ut=a,o;const r=this.ut??=[],l=[];let c,h,d=0,u=n.length-1,p=0,_=o.length-1;for(;d<=u&&p<=_;)if(null===n[d])d++;else if(null===n[u])u--;else if(r[d]===a[p])l[p]=wt(n[d],o[p]),d++,p++;else if(r[u]===a[_])l[_]=wt(n[u],o[_]),u--,_--;else if(r[d]===a[_])l[_]=wt(n[d],o[_]),bt(t,l[_+1],n[d]),d++,_--;else if(r[u]===a[p])l[p]=wt(n[u],o[p]),bt(t,n[d],n[u]),u--,p++;else if(void 0===c&&(c=St(a,p,_),h=St(r,d,u)),c.has(r[d]))if(c.has(r[u])){const e=h.get(a[p]),i=void 0!==e?n[e]:null;if(null===i){const e=bt(t,n[d]);wt(e,o[p]),l[p]=e}else l[p]=wt(i,o[p]),bt(t,n[d],i),n[e]=null;p++}else $t(n[u]),u--;else $t(n[d]),d++;for(;p<=_;){const e=bt(t,l[_+1]);wt(e,o[p]),l[p++]=e}for(;d<=u;){const t=n[d++];null!==t&&$t(t)}return this.ut=a,xt(t,l),U}}),Ct=new WeakMap;let Dt=0;class Tt extends ht{constructor(){super(...arguments),this.title="",this.icon="",this.wide=!1,this.dismissOnScrim=!1,this.hass=null,this._opener=null,this._focusRoot=null,this._useHaDialog=!1,this._closing=!1,this._overlays=[],this._titleId="hp-dialog-title-"+ ++Dt,this._focusInitial=()=>{const t=this._focusableElements(),e=t.find(t=>t.hasAttribute("autofocus"))||t[0]||(this._useHaDialog?null:this.renderRoot.querySelector(".close"))||this.renderRoot.querySelector(".surface")||this.renderRoot.querySelector("ha-dialog");e?.focus({preventScroll:!0})},this._requestClose=()=>{this._closing||(this._closing=!0,this.dispatchEvent(new CustomEvent("hp-close",{bubbles:!0,composed:!0})))},this._onKeyDown=t=>{if("Escape"===t.key){t.preventDefault(),t.stopImmediatePropagation(),this._pruneOverlays();const e=this._overlays[this._overlays.length-1];return e?void this._closeOverlay(e,"escape"):void this._requestClose()}if("Tab"!==t.key||this._useHaDialog)return;const e=this.renderRoot.querySelector(".close"),i=e?[e,...this._focusableElements()]:this._focusableElements();if(!i.length)return t.preventDefault(),void this.renderRoot.querySelector(".surface")?.focus({preventScroll:!0});const s=this._deepActiveElement(),n=i[0],o=i[i.length-1];!t.shiftKey||s!==n&&i.includes(s)?t.shiftKey||s!==o||(t.preventDefault(),n.focus()):(t.preventDefault(),o.focus())},this._onFallbackCancel=t=>{t.preventDefault(),this._requestClose()},this._onFallbackClick=t=>{this.dismissOnScrim&&t.target===t.currentTarget&&this._requestClose()}}connectedCallback(){super.connectedCallback(),this._opener=this._deepActiveElement();const t=this.getRootNode();this._focusRoot=t;const e=Ct.get(t)||{dialogs:new Set,opener:this._opener};e.dialogs.add(this),Ct.set(t,e),this._useHaDialog=!!customElements.get("ha-dialog"),this.addEventListener("keydown",this._onKeyDown,!0)}disconnectedCallback(){this.removeEventListener("keydown",this._onKeyDown,!0);const t=[...this._overlays];this._overlays=[];for(const e of t.reverse())e.close("disconnect");const e=this._focusRoot,i=this._opener;this._opener=null,this._focusRoot=null;const s=e?Ct.get(e):void 0;s?.dialogs.delete(this),super.disconnectedCallback(),e&&s&&requestAnimationFrame(()=>{const t=Ct.get(e);if(!t)return;if(!t.dialogs.size)return t.opener?.isConnected&&t.opener.focus({preventScroll:!0}),void Ct.delete(e);const s=i?.closest("hp-dialog");i?.isConnected&&s&&t.dialogs.has(s)&&i.focus({preventScroll:!0})})}firstUpdated(t){if(super.firstUpdated(t),!this._useHaDialog){const t=this.renderRoot.querySelector("dialog");t&&!t.open&&t.showModal()}queueMicrotask(()=>this._focusInitial())}_deepActiveElement(){let t=document.activeElement;for(;t?.shadowRoot?.activeElement;)t=t.shadowRoot.activeElement;return t&&t!==document.body?t:null}_focusableElements(){const t=["[autofocus]","a[href]","button:not([disabled])",'input:not([disabled]):not([type="hidden"])',"select:not([disabled])","textarea:not([disabled])",'[contenteditable="true"]','[tabindex]:not([tabindex="-1"])'].join(","),e=[],i=new Set,s=n=>{if(!i.has(n)){if(i.add(n),n instanceof HTMLElement){if(n.matches(t)&&e.push(n),n instanceof HTMLSlotElement){for(const t of n.assignedNodes({flatten:!0}))s(t);return}if(n.shadowRoot){for(const t of n.shadowRoot.childNodes)s(t);return}}for(const t of n.childNodes)s(t)}};for(const t of this.childNodes)s(t);const n=this.overlayPortal();return n&&s(n),e.filter(t=>{let e=t;for(;e;){const t=getComputedStyle(e);if(e.hidden||e.inert||"true"===e.getAttribute("aria-hidden")||"none"===t.display||"hidden"===t.visibility)return!1;if(e=e.assignedSlot||e.parentElement||(e.getRootNode()instanceof ShadowRoot?e.getRootNode().host:null),e===this)break}return!0})}_pruneOverlays(){this._overlays=this._overlays.filter(t=>t.owner.isConnected)}_closeOverlay(t,e){const i=this._overlays.findIndex(e=>e.token===t.token);i>=0&&this._overlays.splice(i,1),t.close(e)}registerOverlay(t){this._pruneOverlays();const e=this._overlays.find(e=>e.owner===t.owner);e&&this._overlays.splice(this._overlays.indexOf(e),1);const i=t.group||"transient";for(const t of[...this._overlays].reverse())t.group===i&&this._closeOverlay(t,"exclusive");const s={...t,group:i,token:Symbol("hp-overlay")};this._overlays.push(s);let n=!1;return()=>{if(n)return;n=!0;const t=this._overlays.findIndex(t=>t.token===s.token);t>=0&&this._overlays.splice(t,1)}}closeTransientOverlays(t="outside"){this._pruneOverlays();const e=[...this._overlays].filter(t=>"transient"===(t.group||"transient"));for(const i of e.reverse())this._closeOverlay(i,t);return e.length>0}overlayPortal(){return this.renderRoot.querySelector(".overlay-portal")}render(){const t=W` +globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="a41c150a1b62182dc562da55eab08f6254f93b087f869a4f42157479aae9d405";const t=globalThis,e=t.ShadowRoot&&(void 0===t.ShadyCSS||t.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,i=Symbol(),s=new WeakMap;let n=class{constructor(t,e,s){if(this._$cssResult$=!0,s!==i)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=t,this.t=e}get styleSheet(){let t=this.o;const i=this.t;if(e&&void 0===t){const e=void 0!==i&&1===i.length;e&&(t=s.get(i)),void 0===t&&((this.o=t=new CSSStyleSheet).replaceSync(this.cssText),e&&s.set(i,t))}return t}toString(){return this.cssText}};const o=(t,...e)=>{const s=1===t.length?t[0]:e.reduce((e,i,s)=>e+(t=>{if(!0===t._$cssResult$)return t.cssText;if("number"==typeof t)return t;throw Error("Value passed to 'css' function must be a 'css' function result: "+t+". Use 'unsafeCSS' to pass non-literal values, but take care to ensure page security.")})(i)+t[s+1],t[0]);return new n(s,t,i)},a=e?t=>t:t=>t instanceof CSSStyleSheet?(t=>{let e="";for(const i of t.cssRules)e+=i.cssText;return(t=>new n("string"==typeof t?t:t+"",void 0,i))(e)})(t):t,{is:r,defineProperty:l,getOwnPropertyDescriptor:c,getOwnPropertyNames:h,getOwnPropertySymbols:d,getPrototypeOf:u}=Object,p=globalThis,_=p.trustedTypes,g=_?_.emptyScript:"",m=p.reactiveElementPolyfillSupport,f=(t,e)=>t,v={toAttribute(t,e){switch(e){case Boolean:t=t?g:null;break;case Object:case Array:t=null==t?t:JSON.stringify(t)}return t},fromAttribute(t,e){let i=t;switch(e){case Boolean:i=null!==t;break;case Number:i=null===t?null:Number(t);break;case Object:case Array:try{i=JSON.parse(t)}catch(t){i=null}}return i}},y=(t,e)=>!r(t,e),b={attribute:!0,type:String,converter:v,reflect:!1,useDefault:!1,hasChanged:y};Symbol.metadata??=Symbol("metadata"),p.litPropertyMetadata??=new WeakMap;let w=class extends HTMLElement{static addInitializer(t){this._$Ei(),(this.l??=[]).push(t)}static get observedAttributes(){return this.finalize(),this._$Eh&&[...this._$Eh.keys()]}static createProperty(t,e=b){if(e.state&&(e.attribute=!1),this._$Ei(),this.prototype.hasOwnProperty(t)&&((e=Object.create(e)).wrapped=!0),this.elementProperties.set(t,e),!e.noAccessor){const i=Symbol(),s=this.getPropertyDescriptor(t,i,e);void 0!==s&&l(this.prototype,t,s)}}static getPropertyDescriptor(t,e,i){const{get:s,set:n}=c(this.prototype,t)??{get(){return this[e]},set(t){this[e]=t}};return{get:s,set(e){const o=s?.call(this);n?.call(this,e),this.requestUpdate(t,o,i)},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)??b}static _$Ei(){if(this.hasOwnProperty(f("elementProperties")))return;const t=u(this);t.finalize(),void 0!==t.l&&(this.l=[...t.l]),this.elementProperties=new Map(t.elementProperties)}static finalize(){if(this.hasOwnProperty(f("finalized")))return;if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(f("properties"))){const t=this.properties,e=[...h(t),...d(t)];for(const i of e)this.createProperty(i,t[i])}const t=this[Symbol.metadata];if(null!==t){const e=litPropertyMetadata.get(t);if(void 0!==e)for(const[t,i]of e)this.elementProperties.set(t,i)}this._$Eh=new Map;for(const[t,e]of this.elementProperties){const i=this._$Eu(t,e);void 0!==i&&this._$Eh.set(i,t)}this.elementStyles=this.finalizeStyles(this.styles)}static finalizeStyles(t){const e=[];if(Array.isArray(t)){const i=new Set(t.flat(1/0).reverse());for(const t of i)e.unshift(a(t))}else void 0!==t&&e.push(a(t));return e}static _$Eu(t,e){const i=e.attribute;return!1===i?void 0:"string"==typeof i?i:"string"==typeof t?t.toLowerCase():void 0}constructor(){super(),this._$Ep=void 0,this.isUpdatePending=!1,this.hasUpdated=!1,this._$Em=null,this._$Ev()}_$Ev(){this._$ES=new Promise(t=>this.enableUpdating=t),this._$AL=new Map,this._$E_(),this.requestUpdate(),this.constructor.l?.forEach(t=>t(this))}addController(t){(this._$EO??=new Set).add(t),void 0!==this.renderRoot&&this.isConnected&&t.hostConnected?.()}removeController(t){this._$EO?.delete(t)}_$E_(){const t=new Map,e=this.constructor.elementProperties;for(const i of e.keys())this.hasOwnProperty(i)&&(t.set(i,this[i]),delete this[i]);t.size>0&&(this._$Ep=t)}createRenderRoot(){const i=this.shadowRoot??this.attachShadow(this.constructor.shadowRootOptions);return((i,s)=>{if(e)i.adoptedStyleSheets=s.map(t=>t instanceof CSSStyleSheet?t:t.styleSheet);else for(const e of s){const s=document.createElement("style"),n=t.litNonce;void 0!==n&&s.setAttribute("nonce",n),s.textContent=e.cssText,i.appendChild(s)}})(i,this.constructor.elementStyles),i}connectedCallback(){this.renderRoot??=this.createRenderRoot(),this.enableUpdating(!0),this._$EO?.forEach(t=>t.hostConnected?.())}enableUpdating(t){}disconnectedCallback(){this._$EO?.forEach(t=>t.hostDisconnected?.())}attributeChangedCallback(t,e,i){this._$AK(t,i)}_$ET(t,e){const i=this.constructor.elementProperties.get(t),s=this.constructor._$Eu(t,i);if(void 0!==s&&!0===i.reflect){const n=(void 0!==i.converter?.toAttribute?i.converter:v).toAttribute(e,i.type);this._$Em=t,null==n?this.removeAttribute(s):this.setAttribute(s,n),this._$Em=null}}_$AK(t,e){const i=this.constructor,s=i._$Eh.get(t);if(void 0!==s&&this._$Em!==s){const t=i.getPropertyOptions(s),n="function"==typeof t.converter?{fromAttribute:t.converter}:void 0!==t.converter?.fromAttribute?t.converter:v;this._$Em=s;const o=n.fromAttribute(e,t.type);this[s]=o??this._$Ej?.get(s)??o,this._$Em=null}}requestUpdate(t,e,i,s=!1,n){if(void 0!==t){const o=this.constructor;if(!1===s&&(n=this[t]),i??=o.getPropertyOptions(t),!((i.hasChanged??y)(n,e)||i.useDefault&&i.reflect&&n===this._$Ej?.get(t)&&!this.hasAttribute(o._$Eu(t,i))))return;this.C(t,e,i)}!1===this.isUpdatePending&&(this._$ES=this._$EP())}C(t,e,{useDefault:i,reflect:s,wrapped:n},o){i&&!(this._$Ej??=new Map).has(t)&&(this._$Ej.set(t,o??e??this[t]),!0!==n||void 0!==o)||(this._$AL.has(t)||(this.hasUpdated||i||(e=void 0),this._$AL.set(t,e)),!0===s&&this._$Em!==t&&(this._$Eq??=new Set).add(t))}async _$EP(){this.isUpdatePending=!0;try{await this._$ES}catch(t){Promise.reject(t)}const t=this.scheduleUpdate();return null!=t&&await t,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){if(!this.isUpdatePending)return;if(!this.hasUpdated){if(this.renderRoot??=this.createRenderRoot(),this._$Ep){for(const[t,e]of this._$Ep)this[t]=e;this._$Ep=void 0}const t=this.constructor.elementProperties;if(t.size>0)for(const[e,i]of t){const{wrapped:t}=i,s=this[e];!0!==t||this._$AL.has(e)||void 0===s||this.C(e,void 0,i,s)}}let t=!1;const e=this._$AL;try{t=this.shouldUpdate(e),t?(this.willUpdate(e),this._$EO?.forEach(t=>t.hostUpdate?.()),this.update(e)):this._$EM()}catch(e){throw t=!1,this._$EM(),e}t&&this._$AE(e)}willUpdate(t){}_$AE(t){this._$EO?.forEach(t=>t.hostUpdated?.()),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(t)),this.updated(t)}_$EM(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$ES}shouldUpdate(t){return!0}update(t){this._$Eq&&=this._$Eq.forEach(t=>this._$ET(t,this[t])),this._$EM()}updated(t){}firstUpdated(t){}};w.elementStyles=[],w.shadowRootOptions={mode:"open"},w[f("elementProperties")]=new Map,w[f("finalized")]=new Map,m?.({ReactiveElement:w}),(p.reactiveElementVersions??=[]).push("2.1.2");const k=globalThis,x=t=>t,$=k.trustedTypes,S=$?$.createPolicy("lit-html",{createHTML:t=>t}):void 0,M="$lit$",C=`lit$${Math.random().toFixed(9).slice(2)}$`,D="?"+C,T=`<${D}>`,P=document,R=()=>P.createComment(""),I=t=>null===t||"object"!=typeof t&&"function"!=typeof t,A=Array.isArray,F="[ \t\n\f\r]",E=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,z=/-->/g,O=/>/g,N=RegExp(`>|${F}(?:([^\\s"'>=/]+)(${F}*=${F}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),H=/'/g,L=/"/g,B=/^(?:script|style|textarea|title)$/i,q=t=>(e,...i)=>({_$litType$:t,strings:e,values:i}),W=q(1),j=q(2),U=Symbol.for("lit-noChange"),G=Symbol.for("lit-nothing"),V=new WeakMap,K=P.createTreeWalker(P,129);function Y(t,e){if(!A(t)||!t.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==S?S.createHTML(e):e}const X=(t,e)=>{const i=t.length-1,s=[];let n,o=2===e?"":3===e?"":"",a=E;for(let e=0;e"===l[0]?(a=n??E,c=-1):void 0===l[1]?c=-2:(c=a.lastIndex-l[2].length,r=l[1],a=void 0===l[3]?N:'"'===l[3]?L:H):a===L||a===H?a=N:a===z||a===O?a=E:(a=N,n=void 0);const d=a===N&&t[e+1].startsWith("/>")?" ":"";o+=a===E?i+T:c>=0?(s.push(r),i.slice(0,c)+M+i.slice(c)+C+d):i+C+(-2===c?e:d)}return[Y(t,o+(t[i]||"")+(2===e?"":3===e?"":"")),s]};class J{constructor({strings:t,_$litType$:e},i){let s;this.parts=[];let n=0,o=0;const a=t.length-1,r=this.parts,[l,c]=X(t,e);if(this.el=J.createElement(l,i),K.currentNode=this.el.content,2===e||3===e){const t=this.el.content.firstChild;t.replaceWith(...t.childNodes)}for(;null!==(s=K.nextNode())&&r.length0){s.textContent=$?$.emptyScript:"";for(let i=0;iA(t)||"function"==typeof t?.[Symbol.iterator])(t)?this.k(t):this._(t)}O(t){return this._$AA.parentNode.insertBefore(t,this._$AB)}T(t){this._$AH!==t&&(this._$AR(),this._$AH=this.O(t))}_(t){this._$AH!==G&&I(this._$AH)?this._$AA.nextSibling.data=t:this.T(P.createTextNode(t)),this._$AH=t}$(t){const{values:e,_$litType$:i}=t,s="number"==typeof i?this._$AC(t):(void 0===i.el&&(i.el=J.createElement(Y(i.h,i.h[0]),this.options)),i);if(this._$AH?._$AD===s)this._$AH.p(e);else{const t=new Q(s,this),i=t.u(this.options);t.p(e),this.T(i),this._$AH=t}}_$AC(t){let e=V.get(t.strings);return void 0===e&&V.set(t.strings,e=new J(t)),e}k(t){A(this._$AH)||(this._$AH=[],this._$AR());const e=this._$AH;let i,s=0;for(const n of t)s===e.length?e.push(i=new tt(this.O(R()),this.O(R()),this,this.options)):i=e[s],i._$AI(n),s++;s2||""!==i[0]||""!==i[1]?(this._$AH=Array(i.length-1).fill(new String),this.strings=i):this._$AH=G}_$AI(t,e=this,i,s){const n=this.strings;let o=!1;if(void 0===n)t=Z(this,t,e,0),o=!I(t)||t!==this._$AH&&t!==U,o&&(this._$AH=t);else{const s=t;let a,r;for(t=n[0],a=0;a{const s=i?.renderBefore??e;let n=s._$litPart$;if(void 0===n){const t=i?.renderBefore??null;s._$litPart$=n=new tt(e.insertBefore(R(),t),t,void 0,i??{})}return n._$AI(t),n},ct=globalThis;let ht=class extends w{constructor(){super(...arguments),this.renderOptions={host:this},this._$Do=void 0}createRenderRoot(){const t=super.createRenderRoot();return this.renderOptions.renderBefore??=t.firstChild,t}update(t){const e=this.render();this.hasUpdated||(this.renderOptions.isConnected=this.isConnected),super.update(t),this._$Do=lt(e,this.renderRoot,this.renderOptions)}connectedCallback(){super.connectedCallback(),this._$Do?.setConnected(!0)}disconnectedCallback(){super.disconnectedCallback(),this._$Do?.setConnected(!1)}render(){return U}};ht._$litElement$=!0,ht.finalized=!0,ct.litElementHydrateSupport?.({LitElement:ht});const dt=ct.litElementPolyfillSupport;dt?.({LitElement:ht}),(ct.litElementVersions??=[]).push("4.2.2");const ut=2,pt=t=>(...e)=>({_$litDirective$:t,values:e});let _t=class{constructor(t){}get _$AU(){return this._$AM._$AU}_$AT(t,e,i){this._$Ct=t,this._$AM=e,this._$Ci=i}_$AS(t,e){return this.update(t,e)}update(t,e){return this.render(...e)}};const gt={},mt=pt(class extends _t{constructor(){super(...arguments),this.ot=gt}render(t,e){return e()}update(t,[e,i]){if(Array.isArray(e)){if(Array.isArray(this.ot)&&this.ot.length===e.length&&e.every((t,e)=>t===this.ot[e]))return U}else if(this.ot===e)return U;return this.ot=Array.isArray(e)?Array.from(e):e,this.render(e,i)}}),{I:ft}=at,vt=t=>t,yt=()=>document.createComment(""),bt=(t,e,i)=>{const s=t._$AA.parentNode,n=void 0===e?t._$AB:e._$AA;if(void 0===i){const e=s.insertBefore(yt(),n),o=s.insertBefore(yt(),n);i=new ft(e,o,t,t.options)}else{const e=i._$AB.nextSibling,o=i._$AM,a=o!==t;if(a){let e;i._$AQ?.(t),i._$AM=t,void 0!==i._$AP&&(e=t._$AU)!==o._$AU&&i._$AP(e)}if(e!==n||a){let t=i._$AA;for(;t!==e;){const e=vt(t).nextSibling;vt(s).insertBefore(t,n),t=e}}}return i},wt=(t,e,i=t)=>(t._$AI(e,i),t),kt={},xt=(t,e=kt)=>t._$AH=e,$t=t=>{t._$AR(),t._$AA.remove()},St=(t,e,i)=>{const s=new Map;for(let n=e;n<=i;n++)s.set(t[n],n);return s},Mt=pt(class extends _t{constructor(t){if(super(t),t.type!==ut)throw Error("repeat() can only be used in text expressions")}dt(t,e,i){let s;void 0===i?i=e:void 0!==e&&(s=e);const n=[],o=[];let a=0;for(const e of t)n[a]=s?s(e,a):a,o[a]=i(e,a),a++;return{values:o,keys:n}}render(t,e,i){return this.dt(t,e,i).values}update(t,[e,i,s]){const n=(t=>t._$AH)(t),{values:o,keys:a}=this.dt(e,i,s);if(!Array.isArray(n))return this.ut=a,o;const r=this.ut??=[],l=[];let c,h,d=0,u=n.length-1,p=0,_=o.length-1;for(;d<=u&&p<=_;)if(null===n[d])d++;else if(null===n[u])u--;else if(r[d]===a[p])l[p]=wt(n[d],o[p]),d++,p++;else if(r[u]===a[_])l[_]=wt(n[u],o[_]),u--,_--;else if(r[d]===a[_])l[_]=wt(n[d],o[_]),bt(t,l[_+1],n[d]),d++,_--;else if(r[u]===a[p])l[p]=wt(n[u],o[p]),bt(t,n[d],n[u]),u--,p++;else if(void 0===c&&(c=St(a,p,_),h=St(r,d,u)),c.has(r[d]))if(c.has(r[u])){const e=h.get(a[p]),i=void 0!==e?n[e]:null;if(null===i){const e=bt(t,n[d]);wt(e,o[p]),l[p]=e}else l[p]=wt(i,o[p]),bt(t,n[d],i),n[e]=null;p++}else $t(n[u]),u--;else $t(n[d]),d++;for(;p<=_;){const e=bt(t,l[_+1]);wt(e,o[p]),l[p++]=e}for(;d<=u;){const t=n[d++];null!==t&&$t(t)}return this.ut=a,xt(t,l),U}}),Ct=new WeakMap;let Dt=0;class Tt extends ht{constructor(){super(...arguments),this.title="",this.icon="",this.wide=!1,this.dismissOnScrim=!1,this.hass=null,this._opener=null,this._focusRoot=null,this._useHaDialog=!1,this._closing=!1,this._overlays=[],this._titleId="hp-dialog-title-"+ ++Dt,this._focusInitial=()=>{const t=this._focusableElements(),e=t.find(t=>t.hasAttribute("autofocus"))||t[0]||(this._useHaDialog?null:this.renderRoot.querySelector(".close"))||this.renderRoot.querySelector(".surface")||this.renderRoot.querySelector("ha-dialog");e?.focus({preventScroll:!0})},this._requestClose=()=>{this._closing||(this._closing=!0,this.dispatchEvent(new CustomEvent("hp-close",{bubbles:!0,composed:!0})))},this._onKeyDown=t=>{if("Escape"===t.key){t.preventDefault(),t.stopImmediatePropagation(),this._pruneOverlays();const e=this._overlays[this._overlays.length-1];return e?void this._closeOverlay(e,"escape"):void this._requestClose()}if("Tab"!==t.key||this._useHaDialog)return;const e=this.renderRoot.querySelector(".close"),i=e?[e,...this._focusableElements()]:this._focusableElements();if(!i.length)return t.preventDefault(),void this.renderRoot.querySelector(".surface")?.focus({preventScroll:!0});const s=this._deepActiveElement(),n=i[0],o=i[i.length-1];!t.shiftKey||s!==n&&i.includes(s)?t.shiftKey||s!==o||(t.preventDefault(),n.focus()):(t.preventDefault(),o.focus())},this._onFallbackCancel=t=>{t.preventDefault(),this._requestClose()},this._onFallbackClick=t=>{this.dismissOnScrim&&t.target===t.currentTarget&&this._requestClose()}}connectedCallback(){super.connectedCallback(),this._opener=this._deepActiveElement();const t=this.getRootNode();this._focusRoot=t;const e=Ct.get(t)||{dialogs:new Set,opener:this._opener};e.dialogs.add(this),Ct.set(t,e),this._useHaDialog=!!customElements.get("ha-dialog"),this.addEventListener("keydown",this._onKeyDown,!0)}disconnectedCallback(){this.removeEventListener("keydown",this._onKeyDown,!0);const t=[...this._overlays];this._overlays=[];for(const e of t.reverse())e.close("disconnect");const e=this._focusRoot,i=this._opener;this._opener=null,this._focusRoot=null;const s=e?Ct.get(e):void 0;s?.dialogs.delete(this),super.disconnectedCallback(),e&&s&&requestAnimationFrame(()=>{const t=Ct.get(e);if(!t)return;if(!t.dialogs.size)return t.opener?.isConnected&&t.opener.focus({preventScroll:!0}),void Ct.delete(e);const s=i?.closest("hp-dialog");i?.isConnected&&s&&t.dialogs.has(s)&&i.focus({preventScroll:!0})})}firstUpdated(t){if(super.firstUpdated(t),!this._useHaDialog){const t=this.renderRoot.querySelector("dialog");t&&!t.open&&t.showModal()}queueMicrotask(()=>this._focusInitial())}_deepActiveElement(){let t=document.activeElement;for(;t?.shadowRoot?.activeElement;)t=t.shadowRoot.activeElement;return t&&t!==document.body?t:null}_focusableElements(){const t=["[autofocus]","a[href]","button:not([disabled])",'input:not([disabled]):not([type="hidden"])',"select:not([disabled])","textarea:not([disabled])",'[contenteditable="true"]','[tabindex]:not([tabindex="-1"])'].join(","),e=[],i=new Set,s=n=>{if(!i.has(n)){if(i.add(n),n instanceof HTMLElement){if(n.matches(t)&&e.push(n),n instanceof HTMLSlotElement){for(const t of n.assignedNodes({flatten:!0}))s(t);return}if(n.shadowRoot){for(const t of n.shadowRoot.childNodes)s(t);return}}for(const t of n.childNodes)s(t)}};for(const t of this.childNodes)s(t);const n=this.overlayPortal();return n&&s(n),e.filter(t=>{let e=t;for(;e;){const t=getComputedStyle(e);if(e.hidden||e.inert||"true"===e.getAttribute("aria-hidden")||"none"===t.display||"hidden"===t.visibility)return!1;if(e=e.assignedSlot||e.parentElement||(e.getRootNode()instanceof ShadowRoot?e.getRootNode().host:null),e===this)break}return!0})}_pruneOverlays(){this._overlays=this._overlays.filter(t=>t.owner.isConnected)}_closeOverlay(t,e){const i=this._overlays.findIndex(e=>e.token===t.token);i>=0&&this._overlays.splice(i,1),t.close(e)}registerOverlay(t){this._pruneOverlays();const e=this._overlays.find(e=>e.owner===t.owner);e&&this._overlays.splice(this._overlays.indexOf(e),1);const i=t.group||"transient";for(const t of[...this._overlays].reverse())t.group===i&&this._closeOverlay(t,"exclusive");const s={...t,group:i,token:Symbol("hp-overlay")};this._overlays.push(s);let n=!1;return()=>{if(n)return;n=!0;const t=this._overlays.findIndex(t=>t.token===s.token);t>=0&&this._overlays.splice(t,1)}}closeTransientOverlays(t="outside"){this._pruneOverlays();const e=[...this._overlays].filter(t=>"transient"===(t.group||"transient"));for(const i of e.reverse())this._closeOverlay(i,t);return e.length>0}overlayPortal(){return this.renderRoot.querySelector(".overlay-portal")}render(){const t=W` ${this.icon?W``:G} ${this.title} `;return this._useHaDialog?W` `})} - `}const or={color:"#607d8b",opacity:1,widthCm:3.6,fill:!1,fillColor:"#607d8b",fillOpacity:.25},ar=(t,e=1)=>{const i=Number(t);return Number.isFinite(i)?Math.min(1,Math.max(0,i)):e},rr=t=>{let e=Number(t);return Number.isFinite(e)?(e=(e%360+360)%360,e>180?e-360:e):0};function lr(t,e,i){return rr(e)?[t.x,t.y]:i([t.x,t.y])}const cr=(t,e,i)=>{const s=Number(t),n=Number.isFinite(e)&&e>0?e:5;return Number.isFinite(s)&&s>0?s/n*i:0},hr=(t,e,i)=>{const s=Number(t),n=Number.isFinite(e)&&e>0?e:5;return Number.isFinite(s)&&i>0?s/i*n:0},dr=(t,e,i,s=or.widthCm)=>{const n=Number(t?.width_cm);if(Number.isFinite(n)&&n>0)return n;const o=Number(t?.width);return Number.isFinite(o)&&o>0?hr(o,e,i):s};function ur(t,e){return{color:t.color,opacity:ar(t.opacity),width_cm:Math.max(.1,Math.min(100,Number(t.widthCm)||.1)),...e?{fill:t.fill,fill_color:t.fillColor,fill_opacity:ar(t.fillOpacity,.25)}:{}}}function pr(t){const e=t.x+t.w/2,i=t.y+t.h/2,s=rr(t.angle)*Math.PI/180,n=Math.cos(s),o=Math.sin(s),a=(t,s)=>{const a=t-e,r=s-i;return[e+a*n-r*o,i+a*o+r*n]};return[a(t.x,t.y),a(t.x+t.w,t.y),a(t.x+t.w,t.y+t.h),a(t.x,t.y+t.h)]}function _r(t){const e=pr(t),i=(t,e)=>[(t[0]+e[0])/2,(t[1]+e[1])/2],s=[(e[0][0]+e[2][0])/2,(e[0][1]+e[2][1])/2];return{points:[...e,i(e[0],e[1]),i(e[1],e[2]),i(e[2],e[3]),i(e[3],e[0]),s],segments:e.map((t,i)=>({a:t,b:e[(i+1)%4]}))}}function gr(t,e,i,s,n,o,a,r){const l=rr(t.angle)*Math.PI/180,c=Math.cos(l),h=Math.sin(l),d=-Math.sin(l),u=Math.cos(l),p=t.x+t.w/2,_=t.y+t.h/2,g=e>0?-t.w/2:t.w/2,m=i>0?-t.h/2:t.h/2,f=p+g*c+m*d,v=_+g*h+m*u,y=s-f,b=n-v;let w=(y*c+b*h)*(e>0?1:-1),k=(y*d+b*u)*(i>0?1:-1),x=null;if(o){const e=w/Math.max(t.w,r),i=k/Math.max(t.h,r);x=Math.max(r/Math.max(t.w,r),r/Math.max(t.h,r),e,i),w=t.w*x,k=t.h*x}if(a>0)if(o){const e=Math.max(1,Math.round(t.w/a)),i=Math.max(1,Math.round(t.h/a));if(Math.abs(t.w-e*a)<1e-6&&Math.abs(t.h-i*a)<1e-6){const s=(t,e)=>{let i=Math.abs(t),s=Math.abs(e);for(;s;)[i,s]=[s,i%s];return Math.max(1,i)},n=1/s(e,i),o=Math.max(r/t.w,r/t.h),a=Math.max(o,Math.round((x??1)/n)*n);w=t.w*a,k=t.h*a}else{t.w>=t.h?(w=Math.round(w/a)*a,k=w*(t.h/Math.max(t.w,r))):(k=Math.round(k/a)*a,w=k*(t.w/Math.max(t.h,r)))}}else w=Math.round(w/a)*a,k=Math.round(k/a)*a;w=Math.max(r,w),k=Math.max(r,k);return{x:f+(e>0?w/2:-w/2)*c+(i>0?k/2:-k/2)*d-w/2,y:v+(e>0?w/2:-w/2)*h+(i>0?k/2:-k/2)*u-k/2,w:w,h:k,angle:rr(t.angle)||void 0}}const mr=(t,e,i)=>{const s=i[0]-e[0],n=i[1]-e[1],o=s*s+n*n;if(o<1e-12)return[...e];const a=Math.max(0,Math.min(1,((t[0]-e[0])*s+(t[1]-e[1])*n)/o));return[e[0]+s*a,e[1]+n*a]};const fr=15;function vr(t,e){return Number.isFinite(t)&&t>0&&Number.isFinite(e)&&e>0&&t*e<3}function yr(t){const e=Number(t)>0?Number(t):5;if(5===e)return 8;const i=5/e*8;return Math.min(80,Math.max(.5,i))}function br(t,e){return Number.isFinite(t)&&t>0&&Number.isFinite(e)&&e>0&&t*e<2}function wr(t){return Number.isFinite(t)?Math.max(1,Math.min(100,t)):1}function kr(t,e){return!Number.isFinite(t)||t<=0?"":String(e?Math.round(t/2.54*100)/100:Math.round(100*t)/100)}function xr(t,e,i){const s=Number(e)>0?Number(e):5;return wr(t)/s*i}function $r(t,e){return e>0&&Number.isFinite(t)?Math.round(t/e)*e:t}function Sr(t,e){let i=e[0]-t[0],s=e[1]-t[1];const n=Math.hypot(i,s);return n<1e-12?[1,0]:(i/=n,s/=n,(i<-1e-12||Math.abs(i)<=1e-12&&s<0)&&(i=-i,s=-s),[i,s])}function Mr(t,e,i){const s=$r((t[0]+e[0])/2,i),n=$r((t[1]+e[1])/2,i),[o,a]=Sr(t,e);let r=Math.atan2(a,o);r<0&&(r+=Math.PI);const l=Math.round(1800*r)/1800,c=i>0&&i<.01?6:i<1?4:2;return`${s.toFixed(c)},${n.toFixed(c)}@${l.toFixed(4)}`}function Cr(t,e,i,s){return 1===s?Mr(t,e,i):Mr([t[0]/s,t[1]/s],[e[0]/s,e[1]/s],i)}function Dr(t,e){if(!Array.isArray(t.a)||!Array.isArray(t.b)||t.a.length<2||t.b.length<2)return null;const i=[Number(t.a[0]),Number(t.a[1]),Number(t.b[0]),Number(t.b[1])];if(!i.every(Number.isFinite))return null;const s=e>0?e:1;return[[i[0]*s,i[1]*s],[i[2]*s,i[3]*s]]}function Tr(t,e,i,s,n){const o=n>0?n:1;return{key:Cr(t,e,s,o),cm:wr(i),a:[t[0]/o,t[1]/o],b:[e[0]/o,e[1]/o]}}function Pr(t,e){const i=e>0?e:1,s=[];for(const e of t){const t=e.key.lastIndexOf("@");if(t<0)continue;const[n,o]=e.key.slice(0,t).split(",").map(Number),a=Number(e.key.slice(t+1));[n,o,a].every(Number.isFinite)&&s.push({w:e,x:n*i,y:o*i,ang:a})}return s}function Rr(t,e){const[i,s]=Sr(t,e);let n=Math.atan2(s,i);return n<0&&(n+=Math.PI),n}function Ir(t,e){let i=Math.abs(t-e);return i>Math.PI/2&&(i=Math.PI-i),i<.02}function Ar(t,e,i,s,n=1){if(!t?.length)return null;const o=Cr(e,i,s,n),a=t.find(t=>t.key===o);if(a)return a;const r=n>0?n:1,l=(e[0]+i[0])/2,c=(e[1]+i[1])/2,h=Rr(e,i),d=Math.max(.5*s,1e-9)*r;for(const e of Pr(t,r))if(Ir(e.ang,h)&&Math.hypot(e.x-l,e.y-c)<=d)return e.w;return null}function Fr(t,e,i,s,n=1){const o=Ar(t,e,i,s,n);if(o&&o.cm>0)return wr(o.cm);const a=function(t,e,i,s,n){if(!t?.length)return null;const o=n>0?n:1,a=Math.hypot(i[0]-e[0],i[1]-e[1]);if(a<1e-12)return null;const r=Rr(e,i),l=Math.max(.5*s,1e-9)*o;let c=null;for(const s of t){if(!(s.cm>0))continue;const t=Dr(s,o);if(!t)continue;const n=Math.hypot(t[1][0]-t[0][0],t[1][1]-t[0][1]);if(n<1e-12||!Ir(Rr(t[0],t[1]),r))continue;if(cl(e[0],e[1],t[0][0],t[0][1],t[1][0],t[1][1])>l||cl(i[0],i[1],t[0][0],t[0][1],t[1][0],t[1][1])>l)continue;if(n+l(o.has(t.key)||(t=>{const e=Dr(t,s);if(!e)return!1;const[i,o]=e,r=o[0]-i[0],c=o[1]-i[1],h=Math.hypot(r,c);if(h<=l)return!1;if(!a.some(t=>{const e=[t[0],t[1]],s=[t[2],t[3]];return Ir(Rr(i,o),Rr(e,s))&&cl(i[0],i[1],e[0],e[1],s[0],s[1])<=l&&cl(o[0],o[1],e[0],e[1],s[0],s[1])<=l}))return!1;const d=(n||[]).some(t=>{const e=[t[0],t[1]],s=[t[2],t[3]];if(!Ir(Rr(i,o),Rr(e,s)))return!1;const n=t=>Math.abs((t[0]-i[0])*c-(t[1]-i[1])*r)/h;if(n(e)>l||n(s)>l)return!1;const a=h*h,d=((e[0]-i[0])*r+(e[1]-i[1])*c)/a,u=((s[0]-i[0])*r+(s[1]-i[1])*c)/a;return Math.min(1,Math.max(d,u))-Math.max(0,Math.min(d,u))>l/h});return!d})(t))&&t.cm>=1&&t.cm<=100)}function zr(t,e,i,s=8){const[n,o]=Sr(t,e);let a=Math.atan2(o,n);a<0&&(a+=Math.PI);let r=i*Math.PI/180%Math.PI;r<0&&(r+=Math.PI);let l=Math.abs(a-r);return l>Math.PI/2&&(l=Math.PI-l),l<=s*Math.PI/180}function Or(t,e,i,s,n=1){if(!t?.length)return[];if(e.length!==i.length)return t.slice();const o=new Map;for(let t=0;t0?n:1,r=Math.max(.5*s,1e-9)*a,l=new Set,c=[];for(const n of t){let t="",h=null;const d=Dr(n,a);if(d)for(let n=0;nr||cl(d[1][0],d[1][1],o[0],o[1],l[0],l[1])>r)continue;const p=l[0]-o[0],_=l[1]-o[1],g=p*p+_*_;if(g<1e-18)continue;const m=t=>{const e=Math.max(0,Math.min(1,((t[0]-o[0])*p+(t[1]-o[1])*_)/g));return[c[0]+(u[0]-c[0])*e,c[1]+(u[1]-c[1])*e]};h=[m(d[0]),m(d[1])],t=Cr(h[0],h[1],s,a);break}if(d||(t=o.get(n.key)||""),!t){const o=Pr([n],a)[0];if(o)for(let n=0;n1.000001)continue;if(cl(o.x,o.y,l[0],l[1],c[0],c[1])>r)continue;const m=h[0]+(d[0]-h[0])*Math.max(0,Math.min(1,g)),f=h[1]+(d[1]-h[1])*Math.max(0,Math.min(1,g)),[v,y]=Sr(h,d),b=Math.max(s*a,1e-6);t=Cr([m-v*b,f-y*b],[m+v*b,f+y*b],s,a);break}}t||(t=n.key),l.has(t)||(l.add(t),c.push(h?Tr(h[0],h[1],n.cm,s,a):{...n,key:t,cm:wr(n.cm)}))}return c}function Nr(t,e,i,s,n,o=1){const a=Cr(e,i,n,o),r=(t||[]).filter(t=>t.key!==a);return null==s||s<1?r:[...r,Tr(e,i,s,n,o)]}function Hr(t,e,i,s,n,o=[],a=1){let r=t?t.slice():[];for(const t of function(t,e,i,s,n=1,o=[]){const a=il(t,e,i,s,n,o);if(!a)return[];const r=[];for(let t=0;t0||(c=Nr(c,e,i,s,n,a)))}return c}function Br(t){const{a:e,b:i,halfDepth:s}=t;if(!Array.isArray(e)||!Array.isArray(i)||e.length<2||i.length<2||![e[0],e[1],i[0],i[1]].every(Number.isFinite))return null;const n=i[0]-e[0],o=i[1]-e[1],a=Math.hypot(n,o);if(!(a>1e-9&&s>0&&Number.isFinite(s)))return null;const r=-o/a*s,l=n/a*s;return[[e[0]+r,e[1]+l],[i[0]+r,i[1]+l],[i[0]-r,i[1]-l],[e[0]-r,e[1]-l]]}function qr(t,e,i){return Math.hypot(t[0]-e[0],t[1]-e[1])<=i}function Wr(t,e,i){const s=e.b[0]-e.a[0],n=e.b[1]-e.a[1],o=s*s+n*n;if(!(o>i*i))return!1;const a=((t[0]-e.a[0])*s+(t[1]-e.a[1])*n)/o;if(!(a>0&&a<1))return!1;const r=[e.a[0]+s*a,e.a[1]+n*a];return Math.hypot(t[0]-r[0],t[1]-r[1])<=i}function jr(t,e,i,s){const n=Math.hypot(e,i);if(!(n>1e-9&&s>0))return;const o=[e/n,i/n],a=t.find(t=>Math.abs(t.u[0]*o[1]-t.u[1]*o[0])<1e-9&&t.u[0]*o[0]+t.u[1]*o[1]>1-1e-9);a?a.halfDepth=Math.max(a.halfDepth,s):t.push({u:o,halfDepth:s})}function Ur(t,e=1e-6){const i=(t||[]).filter(t=>t&&Array.isArray(t.a)&&Array.isArray(t.b)&&t.a.length>=2&&t.b.length>=2&&t.a.every(Number.isFinite)&&t.b.every(Number.isFinite)&&Number.isFinite(t.halfDepth)&&t.halfDepth>0&&Math.hypot(t.b[0]-t.a[0],t.b[1]-t.a[1])>1e-9);if(i.length<2)return[];const s=Math.max(Number.isFinite(e)?e:0,1e-9),n=i.flatMap(t=>[t.a,t.b]).map(t=>[t[0],t[1]]).sort((t,e)=>t[0]-e[0]||t[1]-e[1]),o=[];for(const t of n)o.some(e=>qr(e,t,s))||o.push(t);const a=[];for(const t of o){const e=[];for(const n of i)qr(t,n.a,s)?jr(e,n.b[0]-n.a[0],n.b[1]-n.a[1],n.halfDepth):qr(t,n.b,s)?jr(e,n.a[0]-n.b[0],n.a[1]-n.b[1],n.halfDepth):Wr(t,n,s)&&(jr(e,n.a[0]-t[0],n.a[1]-t[1],n.halfDepth),jr(e,n.b[0]-t[0],n.b[1]-t[1],n.halfDepth));if(!(e.length<2)){e.sort((t,e)=>Math.atan2(t.u[1],t.u[0])-Math.atan2(e.u[1],e.u[0])||t.halfDepth-e.halfDepth);for(let i=0;is*s&&a.push(m)}}}return a}function Gr(t,e,i,s){if(!(e>0)||!t||t.length<2)return"";if(i&&t.length>=3){let i=t;const n=t[t.length-1];if(t.length>=4&&Math.hypot(t[0][0]-n[0],t[0][1]-n[1])<1e-9&&(i=t.slice(0,-1)),i.length>=3){const t=i.map((t,i)=>s?.[i]||e),n=wl(i,t),o=Qr(i,t);if(n&&o)return`${tl(n)} ${tl(el(o))}`}}const n=[];for(let i=0;i=1e-9&&r>0&&n.push({a:o,b:a,halfDepth:r})}const o=[...n.map(Br).filter(t=>!!t),...Ur(n)],a=function(t){let e=null;try{for(const i of t){if(i.length<3)continue;const t=dl(i);e=e?si(e,t):[t]}return e}catch{return null}}(o);return a?fl(a):o.map(t=>tl(t)).join(" ")}function Vr(t,e,i,s,n=1){if(!i.length)return!1;const o=Kr(s,n),a=(t[0]+e[0])/2,r=(t[1]+e[1])/2,[l,c]=Sr(t,e);for(const t of i){const[e,i]=Sr([t[0],t[1]],[t[2],t[3]]);if(!(Math.abs(l*i-c*e)>.05)&&cl(a,r,t[0],t[1],t[2],t[3])<=o)return!0}return!1}function Kr(t,e){return Math.max(t*(e>0?e:1)*.04,1e-9)}function Yr(t){let e=0;for(let i=0;it[1]!=l>t[1]&&t[0]<(r-o)*(t[1]-a)/(l-a+0)+o&&(i=!i)}return i}([c[0]+.001*r,c[1]+.001*l],t)||(r=-r,l=-l),[r,l]}function Jr(t,e){const i=t[0]*e[1]-t[1]*e[0],s=t[0]*e[0]+t[1]*e[1];return Math.abs(i)<1e-9&&s>0}function Zr(t,e,i,s){const n=e[0]*s[1]-e[1]*s[0];if(Math.abs(n)<1e-12)return null;const o=[i[0]-t[0],i[1]-t[1]],a=(o[0]*s[1]-o[1]*s[0])/n;return[t[0]+a*e[0],t[1]+a*e[1]]}function Qr(t,e){const i=t?.length||0;if(i<3||e.length!==i)return null;if(e.every(t=>!(t>0)))return t.map(t=>[t[0],t[1]]);const s=[];for(let n=0;n0||d>0)){s.push([t[n][0],t[n][1]]);continue}if(h>0!=d>0){const e=t[n],i=h>0?[e[0]+u*h,e[1]+p*h]:[e[0],e[1]],o=d>0?[e[0]+_*d,e[1]+g*d]:[e[0],e[1]];s.push(i),Math.hypot(o[0]-i[0],o[1]-i[1])>1e-9&&s.push(o);continue}if(Jr(b,w)){const e=t[n],i=[e[0]+u*h,e[1]+p*h],o=[e[0]+_*d,e[1]+g*d];s.push(i),Math.hypot(o[0]-i[0],o[1]-i[1])>1e-9&&s.push(o);continue}const $=Zr(k,b,x,w),S=Math.max(h,d,1e-9);if($){if(Math.hypot($[0]-t[n][0],$[1]-t[n][1])<=4*S){s.push($);continue}}h>0&&s.push([t[n][0]+u*h,t[n][1]+p*h]),d>0&&s.push([t[n][0]+_*d,t[n][1]+g*d]),h>0||d>0||s.push([t[n][0],t[n][1]])}return s.length>=3?s:null}function tl(t,e=!0){if(!t.length)return"";let i=`M ${t[0][0]} ${t[0][1]}`;for(let e=1;et?.id===e),r=hi(a);if(!r||r.length<3)return null;const l=Kr(s,n),c=[];for(const i of t||[]){if(!i||i.id===e)continue;const t=hi(i);if(t)for(const e of Cs(r,t,l))c.push([e[0],e[1]],[e[2],e[3]])}for(const t of i||[])c.push([t[0],t[1]],[t[2],t[3]]);for(const t of o||[]){const e=Dr(t,n);e&&c.push(e[0],e[1])}const h=[],d=[];for(let t=0;tl)continue;const a=((t[0]-e[0])*(i[0]-e[0])+(t[1]-e[1])*(i[1]-e[1]))/(s*s);a<=n||a>=1-n||(o.some(t=>Math.abs(t-a)*s<=2*l)||o.push(a))}o.sort((t,e)=>t-e);for(const s of o)h.push([e[0]+(i[0]-e[0])*s,e[1]+(i[1]-e[1])*s]),d.push(t)}return{poly:h,parent:d,orig:r}}function sl(t,e,i,s){const n=e.poly.length,o=new Array(n).fill(0);if(!t?.length)return o;const a=new Set,r=[];for(let l=0;l0?(o[l]=wr(c.cm),a.add(c.key)):r.push(l)}if(!r.length)return o;const l=s>0?s:1,c=Math.max(.5*i,1e-9)*l,h=Pr(t,l).filter(t=>t.w.cm>0);for(let t=r.length-1;t>=0;t--){const i=r[t],s=e.poly[i],a=e.poly[(i+1)%n],d=Rr(s,a);let u=null;for(const t of h){const e=Dr(t.w,l);if(!e||!Ir(Rr(e[0],e[1]),d))continue;if(cl(s[0],s[1],e[0][0],e[0][1],e[1][0],e[1][1])>c||cl(a[0],a[1],e[0][0],e[0][1],e[1][0],e[1][1])>c)continue;const i=Math.hypot(a[0]-s[0],a[1]-s[1]),n=Math.hypot(e[1][0]-e[0][0],e[1][1]-e[0][1]),o=Math.max(0,n-i);(!u||oc||cl(n[0],n[1],e[0][0],e[0][1],e[1][0],e[1][1])>c)continue;i=!0,o=Math.max(0,Math.hypot(e[1][0]-e[0][0],e[1][1]-e[0][1])-_)}else{if(cl(t.x,t.y,s[0],s[1],n[0],n[1])>c)continue;o=Math.hypot(t.x-d,t.y-u)}(!p||i&&!p.exact||i===p.exact&&ot?.id===e),n=hi(s);if(!n)return[];const o=[];for(const s of t||[]){if(!s||s.id===e)continue;const t=hi(s);if(t)for(const e of Cs(n,t,i))o.push(e)}return o}(t,e,Kr(n,r)),h=function(t,e,i,s,n){const o=Kr(s,n),a=[];for(let r=0;rcl(h,d,t[0],t[1],t[2],t[3])<=o);a.push(u?"shared":"outer")}return a}(l.poly,c,s,n,r),d=sl(i,l,n,r),u=d.map((t,e)=>h[e]&&t>0?xr(t,o,a)/2:0);return{...l,kinds:h,cms:d,offsets:u}}function ol(t,e,i,s,n,o,a=1){const r=[];for(const l of t||[]){if(!l?.id)continue;const c=nl(t,l.id,e,i,s,n,o,a);if(c)for(let t=0;t0&&(r=Nr(r,t.a,t.b,t.cm,s,a));return r}function rl(t,e,i,s,n,o,a=1){if(!e?.length)return[];const r=[],l=new Set;for(const c of ol(t,e,i,s,n,o,a))!c.open&&c.cm>0&&!l.has(c.key)&&(l.add(c.key),r.push(c));const c=[];for(const r of t||[]){if(!r?.id)continue;const l=nl(t,r.id,e,i,s,n,o,a);if(l)for(let t=0;t0)||null===l.kinds[i]){t++;continue}let o=t;for(;o+10&&c.push({a:[h[0],h[1]],b:[d[0],d[1]],key:Cr(h,d,s,a),cm:n,len:u}),t=o+1}}}c.sort((t,e)=>e.len-t.len||t.key.localeCompare(e.key));const h=[],d=new Set,u=new Set,p=4*Kr(s,a);for(const t of c){const e=r.filter(e=>!u.has(e.key)&&e.cm===t.cm&&Ir(Rr(e.a,e.b),Rr(t.a,t.b))&&cl(e.a[0],e.a[1],t.a[0],t.a[1],t.b[0],t.b[1])<=p&&cl(e.b[0],e.b[1],t.a[0],t.a[1],t.b[0],t.b[1])<=p);if(e.length){for(const t of e)u.add(t.key);d.has(t.key)||(d.add(t.key),h.push(Tr(t.a,t.b,t.cm,s,a)))}}for(const t of r)u.has(t.key)||d.has(t.key)||(d.add(t.key),h.push(Tr(t.a,t.b,t.cm,s,a)));return h}function ll(t,e,i,s,n,o,a,r=1){const l=Kr(n,r),c=(s[0]+s[2])/2,h=(s[1]+s[3])/2,d=Rr([s[0],s[1]],[s[2],s[3]]);let u=null;for(const s of ol(t,e,i,n,o,a,r)){if(!Ir(Rr(s.a,s.b),d))continue;const t=cl(c,h,s.a[0],s.a[1],s.b[0],s.b[1]);t>4*l||(!u||tt?.id===e),c=hi(l);if(!c||c.length<3)return null;if(!i?.length)return c.map(t=>[t[0],t[1]]);const h=nl(t,e,i,s,n,o,a,r);return h&&h.offsets.some(t=>t>0)&&Qr(h.poly,h.offsets)||c.map(t=>[t[0],t[1]])}function dl(t){const e=t.map(t=>[t[0],t[1]]);return e.push([t[0][0],t[0][1]]),[e]}function ul(t,e=1){if(!Array.isArray(t)||t.length<3)return null;const i=Number.isFinite(e)&&e>0?e:1,s=1e-12*Math.max(1,i),n=[];for(const e of t){if(!Array.isArray(e)||e.length<2)return null;const t=Number(e[0]),i=Number(e[1]);if(!Number.isFinite(t)||!Number.isFinite(i))return null;const o=Math.round(t/s)*s,a=Math.round(i/s)*s;if(!Number.isFinite(o)||!Number.isFinite(a))return null;n.push([Object.is(o,-0)?0:o,Object.is(a,-0)?0:a])}return Math.abs(Yr(n))>s*s?n:null}function pl(t,e,i,s){if(cl(t[0],t[1],e[0],e[1],i[0],i[1])>s)return!1;const n=i[0]-e[0],o=i[1]-e[1],a=(t[0]-e[0])*n+(t[1]-e[1])*o,r=n*n+o*o,l=s*Math.sqrt(r);return a>=-l&&a<=r+l}function _l(t,e,i){const s=[],n=[];for(let o=0;oi*i))continue;const d=i/Math.sqrt(h),u=[0,1];for(const t of e)for(const e of[t.a,t.b]){if(!pl(e,a,r,i))continue;const t=((e[0]-a[0])*l+(e[1]-a[1])*c)/h;t>d&&t<1-d&&u.push(t)}u.sort((t,e)=>t-e);const p=u.filter((t,e)=>0===e||Math.abs(t-u[e-1])>d);for(let t=0;t=3&&n.length===s.length?{poly:s,offsets:n}:null}function gl(t,e,i,s,n,o,a){const r=(t||[]).map(hi).filter(t=>!!t&&t.length>=3);if(!r.length)return null;let l=si(dl(r[0]));for(let t=1;t"outer"===t.kind&&t.half>0),h=4*Kr(s,a);let d=null;for(const t of function(t){const e=[];for(const i of Array.isArray(t)?t:[])if(Array.isArray(i))for(const t of i){if(!Array.isArray(t)||t.length<4)continue;const i=t.slice(0,-1).map(t=>[t[0],t[1]]);i.length>=3&&e.push(i)}return e}(l)){const e=_l(t,c,h);if(!e||!e.offsets.some(t=>t>0))continue;const i=wl(e.poly,e.offsets),s=Qr(e.poly,e.offsets);if(!i||!s)continue;const n=oi(dl(i),dl(s));d=d?si(d,n):n}return{centre:l,shell:d||[]}}function ml(t,e,i,s,n,o,a=1){try{const r=gl(t,e,i,s,n,o,a);return r?r.shell?.length?si(r.centre,r.shell):r.centre:[]}catch{return null}}function fl(t){if(!t)return"";let e="";for(const i of t)if(Array.isArray(i))for(const t of i){if(!Array.isArray(t)||t.length<4)continue;const i=t.slice(0,t.length-1);i.length<3||(e+=(e?" ":"")+tl(i.map(t=>[t[0],t[1]])))}return e}function vl(t,e,i,s=[],n,o,a,r=1,l=[]){if(!e?.length&&!l.length)return null;const c=[];let h=0;for(const s of t||[]){if(!s?.id)continue;const l=nl(t,s.id,e,i,n,o,a,r);if(!l||l.poly.length<3||!l.offsets.some(t=>t>0))continue;for(const t of l.offsets)t>0&&(h=Math.max(h,2*t));const d=wl(l.poly,l.offsets),u=Qr(l.poly,l.offsets);d&&c.push({outset:d,inset:u})}for(const t of l){const e=t.map(t=>t[0]),i=t.map(t=>t[1]);if(e.length){const s=Math.min(Math.max(...e)-Math.min(...e),Math.max(...i)-Math.min(...i)),n=Math.min(...t.map((e,i)=>{const s=t[(i+1)%t.length];return Math.hypot(s[0]-e[0],s[1]-e[1])}));h=Math.max(h,t.length>16?s:n)}}const d=function(t,e,i,s,n,o,a){if(!e?.length||!i?.length)return[];const r=4*Kr(s,a),l=new Map;for(const r of ol(t,e,i,s,n,o,a))!r.open&&r.half>0&&!l.has(r.key)&&l.set(r.key,r);const c=[...l.values()];if(c.length<2)return[];const h=[];for(const t of i)for(const e of[[t[0],t[1]],[t[2],t[3]]])h.some(t=>Math.hypot(t[0]-e[0],t[1]-e[1])<=r)||h.push(e);const d=[],u=(t,e)=>{let i=0,s=0;if(Math.hypot(t.a[0]-e[0],t.a[1]-e[1])<=r)i=t.b[0]-t.a[0],s=t.b[1]-t.a[1];else{if(!(Math.hypot(t.b[0]-e[0],t.b[1]-e[1])<=r))return null;i=t.a[0]-t.b[0],s=t.a[1]-t.b[1]}const n=Math.hypot(i,s);return n>r?[i/n,s/n]:null};for(const t of h){const e=c.map(e=>({iv:e,u:u(e,t)})).filter(t=>!!t.u);for(let i=0;i4*_||d.push(a>0?[t.slice(),h,p,u]:[t.slice(),u,p,h])}}return d}(t,e,i,n,o,a,r),u=s.length?kl(t,e,i,n,o,a,r):null;try{const p=gl(t,e,i,n,o,a,r),_=p?p.shell?.length?si(p.centre,p.shell):p.centre:[],g=t=>{const e=dl(t.outset);return t.inset?oi(e,dl(t.inset)):e};let m=null;for(const t of c)try{const e=g(t);m=m?si(m,e):e}catch{}if(p)for(const s of bl(t,e,i,n,o,a,r))try{const t=ni(dl(s.quad),p.centre);m=m?si(m,t):t}catch{}m=function(t,e,i=1,s=si){let n=t;for(const t of e||[]){const e=ul(t,i);if(e)try{const t=dl(e);n=n?s(n,t):t}catch{}}return n}(m,d,r),m&&p&&(m=ni(m,p.centre)),p?.shell?.length&&(m=m?si(m,p.shell):p.shell);for(const t of s){if(!(t.length>0))continue;const e=Sl(u,t,!0);if(!e.negative&&!e.positive)continue;const i=t.angle*Math.PI/180,s=Math.cos(i),o=Math.sin(i),a=-o,l=s,c=t.length/2,d=1.25*Math.max(h,n*r),p=[[t.x-s*c-a*d,t.y-o*c-l*d],[t.x+s*c-a*d,t.y+o*c-l*d],[t.x+s*c+a*d,t.y+o*c+l*d],[t.x-s*c+a*d,t.y-o*c+l*d]];m&&(m=oi(m,dl(p)))}for(const t of l)t.length<3||(m=m?si(m,dl(t)):[dl(t)]);return{geom:m||[],paperGeom:_,depthUnits:h,openingIndex:u}}catch{return null}}function yl(t,e,i,s=[],n,o,a,r=1,l=[]){if(!e?.length&&!l.length)return null;const c=vl(t,e,i,s,n,o,a,r,l),h=c?fl(c.geom):"",d=c?fl(c.paperGeom):"";return c&&h?{d:h,paperD:d,depthUnits:c.depthUnits,fillRule:"evenodd"}:null}function bl(t,e,i,s,n,o,a=1){if(!e?.length)return[];const r=new Set,l=[];for(const c of t||[]){if(!c?.id)continue;const h=nl(t,c.id,e,i,s,n,o,a);if(!h)continue;const d=h.poly;for(let t=0;t0))continue;const p=Cr(e,i,s,a);if(r.has(p))continue;r.add(p);const _=xr(u,n,o),[g,m]=Xr(d,t),f=-g,v=-m,y=_/2,b=[[e[0]+f*y,e[1]+v*y],[i[0]+f*y,i[1]+v*y],[i[0]+g*y,i[1]+m*y],[e[0]+g*y,e[1]+m*y]];l.push({key:p,kind:c,cm:u,quad:b,a:[e[0],e[1]],b:[i[0],i[1]],depthUnits:_})}}return l}function wl(t,e){const i=t?.length||0;if(i<3||e.length!==i)return null;if(e.every(t=>!(t>0)))return t.map(t=>[t[0],t[1]]);el(t),e.slice().reverse();const s=[];for(let n=0;n0||r>0)){s.push([t[n][0],t[n][1]]);continue}if(a>0!=r>0){const e=t[n],i=a>0?[e[0]-l*a,e[1]-c*a]:[e[0],e[1]],o=r>0?[e[0]-h*r,e[1]-d*r]:[e[0],e[1]];s.push(i),Math.hypot(o[0]-i[0],o[1]-i[1])>1e-9&&s.push(o);continue}if(Jr(b,w)){const e=t[n],i=[e[0]-l*a,e[1]-c*a],o=[e[0]-h*r,e[1]-d*r];s.push(i),Math.hypot(o[0]-i[0],o[1]-i[1])>1e-9&&s.push(o);continue}const $=Zr(k,b,x,w),S=Math.max(a,r,1e-9);if($){if(Math.hypot($[0]-t[n][0],$[1]-t[n][1])<=4*S){s.push($);continue}}a>0&&s.push([t[n][0]-l*a,t[n][1]-c*a]),r>0&&s.push([t[n][0]-h*r,t[n][1]-d*r])}return s.length>=3?s:null}function kl(t,e,i,s,n,o,a=1){const r=[];for(const l of t||[]){if(!l?.id)continue;const c=nl(t,l.id,e,i,s,n,o,a);if(!c)continue;const h=Math.abs(Pi(c.poly));for(let t=0;t[Math.max(e,t.x0),Math.min(i,t.x1)]).filter(t=>t[1]-t[0]>s).sort((t,e)=>t[0]-e[0]||t[1]-e[1]);if(!n.length)return{coverage:0,full:!1};let o=n[0][0],a=n[0][1],r=0,l=o<=e+s;for(let t=1;t=i-s,{coverage:r,full:l}}function $l(t,e){return Number(e.full)-Number(t.full)||t.faceDistance-e.faceDistance||t.area-e.area||t.roomId.localeCompare(e.roomId)}function Sl(t,e,i=!1){const s=Number(e?.x),n=Number(e?.y),o=Number(e?.angle),a=Number(e?.length);if(!([s,n,o,a].every(Number.isFinite)&&a>0))return{negative:null,positive:null};const r=o*Math.PI/180,l=Math.cos(r),c=Math.sin(r),h=-c,d=l,u=a/2,p=Math.max(1e-9,t.adjacencyEps),_=new Map;let g=0;for(const e of t.edges){if(i&&!(e.half>0))continue;if(!zr(e.a,e.b,o))continue;const[t,a]=Sr(e.a,e.b);if(Math.abs((s-e.a[0])*a-(n-e.a[1])*t)>p)continue;const r=(e.a[0]-s)*l+(e.a[1]-n)*c,m=(e.b[0]-s)*l+(e.b[1]-n)*c,f=Math.max(-u,Math.min(r,m)),v=Math.min(u,Math.max(r,m));if(v-f<=p)continue;const y=e.inward[0]*h+e.inward[1]*d>=0?1:-1,b=((e.a[0]+e.b[0])/2-s)*h+((e.a[1]+e.b[1])/2-n)*d,w=Math.abs(b+y*e.half),k=`${y}|${e.roomId}`,x={x0:f,x1:v,half:e.half,cm:e.cm,key:e.key,axis:[t,a]},$=_.get(k);$?($.pieces.push(x),$.faceDistance=Math.min($.faceDistance,w)):_.set(k,{roomId:e.roomId,side:y,order:g++,pieces:[x],faceDistance:w,area:e.area,coverage:0,full:!1})}for(const t of _.values()){const e=xl(t.pieces,-u,u,p);t.coverage=e.coverage,t.full=e.full}const m=t=>{const e=[..._.values()].filter(e=>e.side===t&&e.coverage>p);return e.sort($l),e[0]||null};return{negative:m(-1),positive:m(1)}}function Ml(t,e){const i=Sl(t,e),s=[i.negative,i.positive].filter(t=>!!t).sort((t,e)=>t.order-e.order);if(!s.length)return{ox:0,oy:0,cm:0,side:-1};const n=s[0],o=e.flip_v?-n.side:n.side,a=(-1===o?i.negative:i.positive)||n,r=[...a.pieces].sort((t,e)=>(t.x0<=0&&t.x1>=0?0:Math.min(Math.abs(t.x0),Math.abs(t.x1)))-(e.x0<=0&&e.x1>=0?0:Math.min(Math.abs(e.x0),Math.abs(e.x1)))||e.x1-e.x0-(t.x1-t.x0)||t.key.localeCompare(e.key))[0];if(!(r.half>0&&r.cm>0))return{ox:0,oy:0,cm:0,side:o};const l=e.angle*Math.PI/180,c=-Math.sin(l),h=Math.cos(l);return{ox:c*o*r.half,oy:h*o*r.half,cm:r.cm,side:o}}function Cl(t,e){const i=1e-9,s=e.filter(t=>Number.isFinite(t.x0)&&Number.isFinite(t.x1)&&Number.isFinite(t.half)&&t.x1>t.x0&&t.half>0);if(!s.length)return"";const n=s.flatMap(t=>[t.x0,t.x1]).sort((t,e)=>t-e),o=[];for(const t of n){const e=o[o.length-1];(void 0===e||t>e+i)&&o.push(t)}const a=[];for(let t=0;t+1e+i))continue;const r=(e+n)/2,l=s.reduce((t,e)=>r>=e.x0-i&&r<=e.x1+i?Math.max(t,e.half):t,0);if(!(l>0))continue;const c=a[a.length-1];c&&e<=c.x1+i&&Math.abs(l-c.half)<=i?c.x1=n:a.push({x0:e,x1:n,half:l})}const r=[];for(const t of a){const e=r[r.length-1],s=e?.[e.length-1];s&&t.x0<=s.x1+i?(t.x0=s.x1,e.push(t)):r.push([t])}return r.map(e=>{const i=e[0],s=e[e.length-1],n=Math.min(.25*Math.min(...e.map(t=>t.half)),.75),o=-t*n,a=[];if(1===t){a.push(`M ${i.x0} ${o} L ${s.x1} ${o}`);for(let t=e.length-1;t>=0;t--){const i=e[t];a.push(`L ${i.x1} ${i.half} L ${i.x0} ${i.half}`)}}else{a.push(`M ${s.x1} ${o} L ${i.x0} ${o}`);for(const t of e)a.push(`L ${t.x0} ${-t.half} L ${t.x1} ${-t.half}`)}return a.push("Z"),a.join(" ")}).join(" ")}function Dl(t,e,i,s){if(!s)return i;const n=t.angle*Math.PI/180,o=Math.cos(n),a=Math.sin(n),r=[],l=1e-9;for(const n of i){const[i,c]=n.axis,h=o*i+a*c;if(Math.abs(h)<=l)continue;const d=t.x*i+t.y*c,u=d+h*n.x0,p=d+h*n.x1,_=Math.min(u,p),g=Math.max(u,p),m=`${n.key}|${e}`,f=s.get(m)||[];let v=[[_,g]];for(const[t,e]of f){const i=[];for(const[s,n]of v)e<=s+l||t>=n-l?i.push([s,n]):(t>s+l&&i.push([s,Math.min(n,t)]),et[0]-e[0]||t[1]-e[1]),b=[];for(const t of y){const e=b[b.length-1];e&&t[0]<=e[1]+l?e[1]=Math.max(e[1],t[1]):b.push([t[0],t[1]])}s.set(m,b)}return r}function Tl(t,e){const i=new Map;return e.map(e=>function(t,e,i){const s=Sl(t,e,!0),n=s.negative,o=s.positive;if(!n&&!o)return null;let a;if(n&&o)a=[{candidate:n,side:-1},{candidate:o,side:1}];else{const t=n||o;a=[{candidate:t,side:-1},{candidate:t,side:1}]}const r=a.map(({candidate:t,side:s})=>({candidate:t,side:s,pieces:Dl(e,s,t.pieces,i)})),l=r.map(({candidate:t,side:e,pieces:i})=>({side:e,roomId:t.roomId,d:Cl(e,i)})),c=r.flatMap(({pieces:t})=>t);if(!c.length)return null;const h=Math.max(...c.map(t=>t.half));return{faces:l,minY:-h,maxY:h,wallKey:[...new Set(c.map(t=>t.key))].sort().join("|")}}(t,e,i))}const Pl=150,Rl=1e-6;function Il(t){return Number.isFinite(t)?Math.max(1,Math.min(Pl,t)):1}function Al(t){return((Number.isFinite(Number(t))?Number(t):0)%90+90)%90}const Fl=t=>{const e=t.map(t=>[t[0],t[1]]);return!e.length||e[0][0]===e[e.length-1][0]&&e[0][1]===e[e.length-1][1]||e.push([...e[0]]),[e]},El=(t,e)=>t[0]===e[0]&&t[1]===e[1];function zl(t,e=1e-6){const i=Number.isFinite(e)&&e>0?e:Rl,s=[];for(const e of t||[]){if(!Array.isArray(e)||e.length<2)return null;const t=Number(e[0]),n=Number(e[1]);if(!Number.isFinite(t)||!Number.isFinite(n))return null;const o=Math.round(t/i)*i,a=Math.round(n/i)*i;if(!Number.isFinite(o)||!Number.isFinite(a))return null;const r=[Object.is(o,-0)?0:o,Object.is(a,-0)?0:a];s.length&&El(s[s.length-1],r)||s.push(r)}return s.length>1&&El(s[0],s[s.length-1])&&s.pop(),s.length<3||new Set(s.map(t=>`${t[0]},${t[1]}`)).size<3?null:Pi(s)>i*i?s:null}function Ol(t){const e=[];for(const i of t||[])for(const t of i||[]){const i=(t||[]).filter(t=>Array.isArray(t)&&t.length>=2);i.length<4||e.push(`M ${i.slice(0,-1).map(t=>`${t[0]} ${t[1]}`).join(" L ")} Z`)}return e.join(" ")}function Nl(t,e,i,s,n){return Br({a:t,b:e,halfDepth:xr(i,s,n)/2})}function Hl(t,e,i){const s=Number(e)>0?Number(e):5,n=Il(t.cm)/s*i,o=t.center[0],a=t.center[1];if("circle"===t.shape){const t=n/2;return Array.from({length:96},(e,i)=>{const s=i/96*Math.PI*2;return[o+Math.cos(s)*t,a+Math.sin(s)*t]})}const r=n/2,l=Al(t.angle)*Math.PI/180,c=Math.cos(l),h=Math.sin(l);return[[-r,-r],[r,-r],[r,r],[-r,r]].map(([t,e])=>[o+t*c-e*h,a+t*h+e*c])}function Ll(t,e,i=1e-9){if(!e.length)return[t];let s=[Fl(t)];try{for(const t of e){const e=t.b[0]-t.a[0],n=t.b[1]-t.a[1],o=Math.hypot(e,n);if(!(o>i))continue;const a=e/o,r=n/o,l=-r,c=a,h=1.25*Math.max(Number(t.depth)||0,4*i),d=Math.max(2*i,1e-9*o),u=[[t.a[0]-a*d-l*h,t.a[1]-r*d-c*h],[t.b[0]+a*d-l*h,t.b[1]+r*d-c*h],[t.b[0]+a*d+l*h,t.b[1]+r*d+c*h],[t.a[0]-a*d+l*h,t.a[1]-r*d+c*h]];s=oi(s,Fl(u))}return Kl(s)}catch{return[t]}}function Bl(t,e,i,s=Math.max(2e-4*i,1e-9),n=[]){const o=[],a=[],r=new Map;for(const t of n){const e=r.get(t.hostId)||[];e.push(t),r.set(t.hostId,e)}const l=[],c=[],h=[];for(const s of t.room_drafts||[])for(let t=0;t+1Hl(t,e,i)),u=Ur([...o,...a],s).flatMap(t=>Ll(t,n,s));return{drafts:l,partitions:c,columns:d,patches:u,all:[...l,...h,...u,...d]}}function ql(t){try{const e=t.map(t=>zl(t)).filter(t=>!!t).map(t=>Fl(t));return e.length?si(e[0],...e.slice(1)):null}catch{return null}}const Wl=t=>`M ${t.map(t=>`${t[0]} ${t[1]}`).join(" L ")} Z`;function jl(t){const e=[];for(const i of t||[]){if(Vl([i])<=1e-6)continue;const t=[];for(const e of i||[]){const i=(e||[]).filter(t=>Array.isArray(t)&&t.length>=2);i.length<4||t.push(Wl(i.slice(0,-1)))}t.length&&e.push(t.join(" "))}return e}function Ul(t,e,i={}){const s=ql(t.filter(t=>t.length>=3)),n=e.some(t=>!zl(t))?null:ql(e);if(!s)return[];if(n)try{return jl(ni(s,n))}catch{}return function(t,e,i){let s=null;for(let n=0;n=4&&e.push(t.slice(0,-1).map(t=>[t[0],t[1]]))}return e}function Yl(t,e){let i=!1;for(let s=0,n=e.length-1;st[1]!=l>t[1]&&t[0]<(r-o)*(t[1]-a)/(l-a||1e-12)+o&&(i=!i)}return i}function Xl(t,e,i){return function(t,e){for(const i of e||[]){const e=i?.[0];if(!e?.length||!Yl(t,e))continue;let s=!1;for(let e=1;eYl(t,e))}function Jl(t,e,i){if(Math.hypot(t.center[0]-e.center[0],t.center[1]-e.center[1])>i)return!1;if(Math.abs(Il(t.cm)-Il(e.cm))>1e-6)return!1;if(t.shape!==e.shape)return!0;if("circle"===t.shape||"circle"===e.shape)return!0;const s=Math.abs(Al(t.angle)-Al(e.angle));return Math.min(s,90-s)<=1e-6}const Zl=2.54;function Ql(t){const e="number"==typeof t?t:NaN;return!Number.isFinite(e)||e<=0||5===e?1:5/e}function tc(t,e){return t*Ql(e)}function ec(t){return t?Zl:1}function ic(t,e){if(!e)return String(t);const i=t/Zl;return String(Math.round(1e6*i)/1e6)}const sc=1e3;function nc(t,e){const i=Number(t),s=Number.isFinite(i)&&i>0?i:1,n=s>=1?e:e*s,o=s>=1?e/s:e;return{x:(e-n)/2,y:(e-o)/2,w:n,h:o}}const oc=.01,ac=100;function rc(t,e=1e3){const i=nc(t?.plan_aspect,e),s=Number(t?.plan_scale),n=Number.isFinite(s)&&s>0?Math.min(ac,Math.max(oc,s)):1,o=Number(t?.plan_scale_x),a=Number(t?.plan_scale_y),r=Number.isFinite(o)&&o>0?Math.min(ac,Math.max(oc,o)):n,l=Number.isFinite(a)&&a>0?Math.min(ac,Math.max(oc,a)):n,c=Number(t?.plan_x),h=Number(t?.plan_y),d=rr(t?.plan_angle);return{x:i.x+(Number.isFinite(c)?vc(c):0)*e,y:i.y+(Number.isFinite(h)?vc(h):0)*e,w:i.w*r,h:i.h*l,...d?{angle:d}:{}}}function lc(t){if(null==t.x||null==t.y)return{x:t.x,y:t.y,w:t.w,h:t.h};const e=Number(t.w)||0,i=Number(t.h)||0;return{x:e<0?t.x+e:t.x,y:i<0?t.y+i:t.y,w:Math.abs(e),h:Math.abs(i)}}function cc(t){return t&&Array.isArray(t.spaces)?t.spaces.map(t=>{const e=sc,i=function(t){return Array.isArray(t)&&4===t.length&&t.every(t=>Number.isFinite(t))&&t[2]>1e-6&&t[3]>1e-6?t:[0,0,1,1]}(t.view_box);return{id:t.id,title:t.title,cellCm:Number.isFinite(Number(t.cell_cm))&&Number(t.cell_cm)>0?Number(t.cell_cm):5,vb:[i[0]*sc,i[1]*e,i[2]*sc,i[3]*e],bg:t.plan_url?{href:As(t.plan_url),...rc(t,sc)}:null,rooms:(t.rooms||[]).map(t=>{const i={...t,...lc(t)};return{id:i.id,name:i.name,area:i.area??null,open_to:i.open_to||void 0,settings:i.settings||void 0,x:null!=i.x?i.x*sc:void 0,y:null!=i.y?i.y*e:void 0,w:null!=i.w?i.w*sc:void 0,h:null!=i.h?i.h*e:void 0,poly:i.poly?i.poly.map(t=>[t[0]*sc,t[1]*e]):void 0}}),room_drafts:(t.room_drafts||[]).map(t=>({id:t.id,points:(t.points||[]).map(t=>[t[0]*sc,t[1]*e]),segments:(t.segments||[]).map(t=>({cm:Number(t.cm)}))})),partitions:(t.partitions||[]).map(t=>({id:t.id,a:[t.a[0]*sc,t.a[1]*e],b:[t.b[0]*sc,t.b[1]*e],cm:Number(t.cm)})),wall_columns:(t.wall_columns||[]).map(t=>({id:t.id,shape:"circle"===t.shape?"circle":"square",center:[t.center[0]*sc,t.center[1]*e],cm:Number(t.cm),..."circle"===t.shape?{}:{angle:Al(t.angle)}}))}}):[]}const hc=5e3,dc=hc*sc,uc=240,pc=sc/uc,_c=1/uc;function gc(t){if(!Number.isFinite(t))return t;const e=Math.round(t*uc/sc)*sc/uc;return Math.abs(e-t)<=1e-9*pc?t:e}function mc(t){return{x:gc(t.x),y:gc(t.y)}}function fc(t){return Number.isFinite(t)?Math.min(dc,Math.max(-dc,t)):0}function vc(t){return Number.isFinite(t)?Math.min(hc,Math.max(-hc,t)):0}const yc=1/3,bc=200;function wc(t){let e=1/0,i=1/0,s=-1/0,n=-1/0;for(const o of t){const t=Number(o[0]),a=Number(o[1]);Number.isFinite(t)&&Number.isFinite(a)&&(ts&&(s=t),a>n&&(n=a))}return e>s?null:{minX:e,minY:i,maxX:s,maxY:n}}function kc(t){return t.poly&&t.poly.length?wc(t.poly):null==t.x||null==t.y?null:wc([[t.x,t.y],[t.x+(t.w||0),t.y+(t.h||0)]])}function xc(t,e){const i=[];for(const e of t.rooms||[]){const t=kc(e);t&&i.push(t)}if(t.bg){const e=wc(pr(t.bg));e&&i.push(e)}for(const t of e||[])if(Array.isArray(t)){const e=wc([t]);e&&i.push(e)}else i.push(t);return i}const $c=t=>{if(!t.length)return 0;const e=[...t].sort((t,e)=>t-e),i=e.length>>1;return e.length%2?e[i]:(e[i-1]+e[i])/2},Sc=t=>{let e=1/0,i=1/0,s=-1/0,n=-1/0;for(const o of t)o.minXs&&(s=o.maxX),o.maxY>n&&(n=o.maxY);return e>s||i>n?null:{x:e,y:i,w:s-e,h:n-i}};function Mc(t,e){let{x:i,y:s,w:n,h:o}=t;n<30&&(i=i+n/2-100,n=bc),o<30&&(s=s+o/2-100,o=bc);const a=Math.max(n,o)*e;return{x:i-a,y:s-a,w:n+2*a,h:o+2*a}}function Cc(t,e={}){const i=e.pad??.05,s=e.k??10,n=e.minSpread??50,o=t.filter(t=>Number.isFinite(t.minX)&&Number.isFinite(t.minY)&&Number.isFinite(t.maxX)&&Number.isFinite(t.maxY)&&Math.abs(t.minX)<=dc&&Math.abs(t.maxX)<=dc&&Math.abs(t.minY)<=dc&&Math.abs(t.maxY)<=dc);if(!o.length)return{core:null,all:null,outliers:0};const a=Sc(o);if(o.length<4){const t=Mc(a,i);return{core:t,all:t,outliers:0}}const r=o.map(t=>(t.minX+t.maxX)/2),l=o.map(t=>(t.minY+t.maxY)/2),c=$c(r),h=$c(l),d=o.map((t,e)=>Math.max(Math.abs(r[e]-c),Math.abs(l[e]-h))),u=Math.max(((t,e)=>t.length?t[Math.min(t.length-1,Math.max(0,Math.round(e*(t.length-1))))]:0)([...d].sort((t,e)=>t-e),.75),n),p=d.map(t=>t>s*u),_=p.filter(Boolean).length,g=_&&_<=o.length*yc?o.filter((t,e)=>!p[e]):o;return{core:Mc(Sc(g)||a,i),all:Mc(a,i),outliers:g===o?0:_}}function Dc(t,e,i=.05){const s=Cc(xc(t,e),{pad:i});if(s.core)return s.core;const n=t.vb&&4===t.vb.length&&t.vb[2]>0&&t.vb[3]>0?t.vb:[0,0,sc,sc];return{x:n[0],y:n[1],w:n[2],h:n[3]}}function Tc(t){const e=Dc(t);return{x:e.x+e.w/2,y:e.y+e.h/2}}function Pc(t){const e=[];for(const i of t.rooms||[]){const t=kc(i);t&&e.push(t)}const i=Cc(e,{pad:0}).core,s=sc*Ql(t.cellCm??5);return i?Math.max(s,Math.min(dc,Math.max(i.w,i.h))):s}function Rc(t,e,i,s=1){const n=Number(i),o=Number.isFinite(s)&&s>0?s:1;return!Number.isFinite(n)||n<=0?t*o:t*Pc(e)*o/n}const Ic=[1,2,5,10,20,50,100,200,500,1e3];function Ac(t){if(t.poly&&t.poly.length){const e=t.poly.map(t=>t[0]),i=t.poly.map(t=>t[1]),s=Math.min(...e),n=Math.min(...i);return{x:s,y:n,w:Math.max(...e)-s,h:Math.max(...i)-n}}return{x:t.x??0,y:t.y??0,w:t.w??0,h:t.h??0}}function Fc(t,e,i,s){const n=i["rl_"+(t.id||"")];if(n&&n.s===e)return{x:n.x*sc,y:n.y*sc};const o=function(t){if(t.poly){const e=t.poly.length;return[t.poly.reduce((t,e)=>t+e[0],0)/e,t.poly.reduce((t,e)=>t+e[1],0)/e]}return[t.x+t.w/2,t.y+.1*Math.min(t.w,t.h)]}(t);return mc({x:o[0],y:o[1]})}const Ec=["furniture","appliance","sanitary","other"],zc=[{id:"sofa",group:"furniture",w:220,h:90,g:[["r",0,0,1,1],["l",.09,.26,.91,.26],["l",.09,.26,.09,1],["l",.91,.26,.91,1],["l",.5,.26,.5,1]]},{id:"armchair",group:"furniture",w:90,h:85,g:[["r",0,0,1,1],["l",.14,.28,.86,.28],["l",.14,.28,.14,1],["l",.86,.28,.86,1]]},{id:"coffee_table",group:"furniture",w:110,h:60,g:[["r",0,0,1,1],["r",.08,.14,.84,.72]]},{id:"table_dining",group:"furniture",w:140,h:80,g:[["r",0,0,1,1],["r",.06,.11,.88,.78]]},{id:"table_round",group:"furniture",w:120,h:120,g:[["e",.5,.5,.5,.5],["e",.5,.5,.41,.41]]},{id:"chair",group:"furniture",w:45,h:45,g:[["r",0,0,1,.18],["r",.06,.18,.88,.8]]},{id:"desk",group:"furniture",w:120,h:60,g:[["r",0,0,1,1],["r",.63,.07,.31,.86],["l",.63,.5,.94,.5]]},{id:"bed_double",group:"furniture",w:160,h:200,g:[["r",0,0,1,1],["r",0,0,1,.07],["r",.06,.1,.4,.15],["r",.54,.1,.4,.15],["l",0,.33,1,.33]]},{id:"bed_single",group:"furniture",w:90,h:200,g:[["r",0,0,1,1],["r",0,0,1,.07],["r",.15,.1,.7,.15],["l",0,.33,1,.33]]},{id:"nightstand",group:"furniture",w:45,h:40,g:[["r",0,0,1,1],["r",.12,.14,.76,.33],["r",.12,.53,.76,.33]]},{id:"wardrobe",group:"furniture",w:100,h:60,g:[["r",0,0,1,1],["l",0,.72,1,.72],["l",.5,.72,.5,1]]},{id:"bookshelf",group:"furniture",w:80,h:30,g:[["r",0,0,1,1],["l",.34,0,.34,1],["l",.67,0,.67,1]]},{id:"fridge",group:"appliance",w:60,h:65,g:[["r",0,0,1,1],["l",0,.36,1,.36],["l",.83,.44,.83,.64]]},{id:"stove",group:"appliance",w:60,h:60,g:[["r",0,0,1,1],["e",.29,.31,.15,.15],["e",.71,.31,.15,.15],["e",.29,.71,.15,.15],["e",.71,.71,.15,.15]]},{id:"dishwasher",group:"appliance",w:60,h:60,g:[["r",0,0,1,1],["r",.1,.12,.8,.76],["e",.5,.5,.27,.27],["e",.5,.5,.13,.13]]},{id:"washer",group:"appliance",w:60,h:60,g:[["r",0,0,1,1],["l",.08,.17,.92,.17],["e",.5,.57,.3,.3],["e",.5,.57,.14,.14]]},{id:"dryer",group:"appliance",w:60,h:60,g:[["r",0,0,1,1],["l",.08,.17,.92,.17],["e",.5,.57,.3,.3],["p",.36,.5,.5,.64,.64,.5]]},{id:"tv",group:"appliance",w:120,h:30,g:[["r",0,0,1,.42],["l",.5,.42,.5,.72],["l",.3,.72,.7,.72]]},{id:"ac",group:"appliance",w:90,h:25,g:[["r",0,0,1,1],["l",.05,.55,.95,.55],["l",.05,.79,.95,.79]]},{id:"water_heater",group:"appliance",w:45,h:45,g:[["e",.5,.5,.5,.5],["e",.5,.5,.31,.31]]},{id:"toilet",group:"sanitary",w:40,h:70,g:[["r",.06,0,.88,.2],["e",.5,.58,.37,.35],["e",.5,.58,.22,.2]]},{id:"bathtub",group:"sanitary",w:170,h:75,g:[["r",0,0,1,1],["r",.05,.11,.77,.78],["e",.89,.5,.045,.1]]},{id:"shower",group:"sanitary",w:90,h:90,g:[["r",0,0,1,1],["l",0,0,1,1],["l",1,0,0,1],["e",.5,.5,.08,.08]]},{id:"sink",group:"sanitary",w:60,h:45,g:[["r",0,0,1,1],["e",.5,.6,.34,.3],["e",.5,.15,.07,.07]]},{id:"kitchen_sink",group:"sanitary",w:80,h:60,g:[["r",0,0,1,1],["r",.06,.24,.44,.64],["r",.54,.24,.4,.64],["e",.5,.12,.06,.06]]},{id:"bidet",group:"sanitary",w:40,h:55,g:[["e",.5,.5,.44,.5],["e",.5,.5,.26,.3]]},{id:"stairs",group:"other",w:100,h:280,g:[["r",0,0,1,1],["l",0,.111,1,.111],["l",0,.222,1,.222],["l",0,.333,1,.333],["l",0,.444,1,.444],["l",0,.556,1,.556],["l",0,.667,1,.667],["l",0,.778,1,.778],["l",0,.889,1,.889],["l",.5,.93,.5,.06],["p",.38,.16,.5,.06,.62,.16]]},{id:"fireplace",group:"other",w:120,h:40,g:[["r",0,0,1,1],["p",.22,1,.22,.42,.78,.42,.78,1]]},{id:"plant",group:"other",w:40,h:40,g:[["e",.5,.5,.22,.22],["l",.5,.28,.5,.02],["l",.5,.72,.5,.98],["l",.28,.5,.02,.5],["l",.72,.5,.98,.5],["l",.34,.34,.13,.13],["l",.66,.66,.87,.87],["l",.66,.34,.87,.13],["l",.34,.66,.13,.87]]},{id:"rug",group:"other",w:200,h:140,g:[["r",0,0,1,1],["r",.06,.09,.88,.82]]}],Oc=new Map(zc.map(t=>[t.id,t]));function Nc(t){return t&&Oc.get(t)||null}function Hc(t){return zc.filter(e=>e.group===t)}function Lc(t,e,i=pc,s=1e3){const n=Number(e)>0?Number(e):5;return(Number(t)||0)/n*i/s}const Bc=5e-4,qc=hc;function Wc(t){return Number.isFinite(t)?Math.max(Bc,Math.min(qc,t)):Bc}const jc=t=>{const e=Math.round(1e3*t)/1e3;return Object.is(e,-0)?"0":String(e)};function Uc(t,e,i){const s=Nc(t);if(!(s&&e>0&&i>0))return"";const n=t=>jc(t*e),o=t=>jc(t*i),a=[];for(const t of s.g)if("r"===t[0]){const[,e,i,s,r]=t;a.push(`M${n(e)} ${o(i)}H${n(e+s)}V${o(i+r)}H${n(e)}Z`)}else if("l"===t[0]){const[,e,i,s,r]=t;a.push(`M${n(e)} ${o(i)}L${n(s)} ${o(r)}`)}else if("e"===t[0]){const[,s,r,l,c]=t;a.push(`M${n(s-l)} ${o(r)}A${jc(l*e)} ${jc(c*i)} 0 0 1 ${n(s+l)} ${o(r)}A${jc(l*e)} ${jc(c*i)} 0 0 1 ${n(s-l)} ${o(r)}Z`)}else{const e=t.slice(1);if(e.length<4)continue;let i=`M${n(e[0])} ${o(e[1])}`;for(let t=2;t+1{let e=(t%360+360)%360;return e>180&&(e-=360),e};function Vc(t,e,i,s,n,o=0){let a=null,r=n;for(const n of s){const[s,l,c,h]=n,d=c-s,u=h-l,p=d*d+u*u;if(!p)continue;const _=Math.sqrt(p);let g=((t-s)*d+(e-l)*u)/p;g=Math.max(0,Math.min(1,g));let m=s+g*d,f=l+g*u;const v=Math.hypot(t-m,e-f);if(!(v0){const t=Math.round(g*_/o)*o;m=s+t/_*d,f=l+t/_*u}a={cx:m+y*(i/2),cy:f+b*(i/2),angle:Gc(180*Math.atan2(-y,b)/Math.PI),dist:v}}return a}function Kc(t,e,i){const s=i>0?i:1;return{a:[t[0]/s,t[1]/s],b:[e[0]/s,e[1]/s]}}function Yc(t,e){const i=e>0?e:1;return[t.a[0]*i,t.a[1]*i,t.b[0]*i,t.b[1]*i]}function Xc(t){return Array.isArray(t)&&t.length>=2&&Number.isFinite(Number(t[0]))&&Number.isFinite(Number(t[1]))}function Jc(t){if(!Array.isArray(t))return[];const e=[];for(const i of t){if(!i||"object"!=typeof i)continue;const t=i;if(!Xc(t.a)||!Xc(t.b))continue;const s=[Number(t.a[0]),Number(t.a[1])],n=[Number(t.b[0]),Number(t.b[1])];Math.hypot(n[0]-s[0],n[1]-s[1])<.001||e.push({a:s,b:n})}return e}function Zc(t,e){const i=e[0],s=e[1],n=e[2]-i,o=e[3]-s,a=n*n+o*o;if(a<1e-18){return{q:[i,s],t:0,d:Math.hypot(t[0]-i,t[1]-s)}}let r=((t[0]-i)*n+(t[1]-s)*o)/a;r=Math.max(0,Math.min(1,r));const l=[i+r*n,s+r*o];return{q:l,t:r,d:Math.hypot(t[0]-l[0],t[1]-l[1])}}function Qc(t,e){return Zc(t,e).q}function th(t,e,i,s,n){const o=Zc(t,e).q;let a=o,r=1/0;for(const t of i){const e=Math.hypot(o[0]-t[0],o[1]-t[1]);e<=n&&e0?s:1,g=Math.round(p/_)*_,m=Math.max(0,Math.min(u,g))/u;return[l+h*m,c+d*m]}function eh(t,e){const i=[],s=(t||[]).filter(t=>t?.id);for(let t=0;tt?.id),a=Jc(e);if(a.length)return hh(a,t,i,s).map(t=>Yc(t,i));if(!n)return[];const r=[],l=(t,e)=>(t.open_to||[]).includes(e.id)||(e.open_to||[]).includes(t.id);for(let t=0;tKc([t[0],t[1]],[t[2],t[3]],e))}function nh(t,e,i,s){for(const e of t||[])e.open_to&&delete e.open_to;if(!i.length)return;const n=(e||[]).filter(t=>t?.id);new Map(n.map(t=>[t.id,t]));const o=new Map((t||[]).filter(t=>t?.id).map(t=>[t.id,t])),a=(t,e)=>{const i=o.get(t),s=o.get(e);i&&s&&((i.open_to||[]).includes(e)||(i.open_to=[...i.open_to||[],e]),(s.open_to||[]).includes(t)||(s.open_to=[...s.open_to||[],t]))};for(let t=0;tHs(i,t)<4*s)){a(n[t].id,n[e].id);break}}}for(const e of t||[])e.open_to&&!e.open_to.length&&delete e.open_to}function oh(t,e,i,s=0){const n=e[2]-e[0],o=e[3]-e[1],a=Math.hypot(n,o);if(!(a>1e-9))return null;const r=n/a,l=o/a,c=(t[0]-e[0])*r+(t[1]-e[1])*l;if(c<-s||c>a+s)return null;return Math.abs((t[0]-e[0])*l-(t[1]-e[1])*r)>i?null:Hs(t,e)}function ah(t,e,i){const s=t[2]-t[0],n=t[3]-t[1],o=e[2]-e[0],a=e[3]-e[1],r=Math.hypot(s,n),l=Math.hypot(o,a);return r>1e-9&&l>1e-9&&(!(Math.abs(s/r*(a/l)-n/r*(o/l))>1e-6)&&(Hs([e[0],e[1]],t)<=4*i||Hs([t[0],t[1]],e)<=4*i))}function rh(t,e,i){if(!t.length)return null;t.sort((t,e)=>t.distance-e.distance);const s=t[0];for(let n=1;ne)break;if(o.semantic!==s.semantic||!ah(s.seg,o.seg,i))return"ambiguous"}return s}function lh(t,e,i,s,n=1,o=15){const a=function(t,e,i,s,n=1,o=15){const[a,r]=Sr([e[0],e[1]],[e[2],e[3]]);let l=0,c=1/0;const h=[(e[0]+e[2])/2,(e[1]+e[3])/2];for(const e of i){const[i,o]=Sr([e[0],e[1]],[e[2],e[3]]);if(Math.abs(a*o-r*i)>.05)continue;const d=Fr(t,[e[0],e[1]],[e[2],e[3]],s,n);if(!(d>0))continue;const u=[(e[0]+e[2])/2,(e[1]+e[3])/2],p=Math.hypot(u[0]-h[0],u[1]-h[1]);p0?l:o}(t,e,i,s,n,o);return Nr(t,[e[0],e[1]],[e[2],e[3]],a,s,n)}function ch(t,e,i){const s=[[t[0],t[1]],[t[2],t[3]]],n=[(t[0]+t[2])/2,(t[1]+t[3])/2];for(const o of e)if(!(Hs(n,o)>Math.hypot(t[2]-t[0],t[3]-t[1])&&Hs([o[0],o[1]],t)>i))for(const e of[[o[0],o[1]],[o[2],o[3]]])Hs(e,t)<=2*i&&s.push(e);return s}function hh(t,e,i,s){const n=Jc(t);if(!n.length)return[];const o=eh(e,s);if(!o.length)return[];const a=[],r=Math.max(4*s,1e-6);for(const t of n){const e=Yc(t,i),n=e[0],l=e[1],c=e[2]-n,h=e[3]-l,d=Math.hypot(c,h);if(d4*s||o>4*s)continue;const a=(t[0]-n)*u+(t[1]-l)*p,c=(t[2]-n)*u+(t[3]-l)*p,h=Math.max(0,Math.min(a,c)),g=Math.min(d,Math.max(a,c));if(g-ht.lo-e.lo||t.hi-e.hi);const i=[];for(const t of e){const e=i[i.length-1];e&&t.lo<=e.hi+r?e.hi=Math.max(e.hi,t.hi):i.push({...t})}for(const e of i){const i=[n+u*e.lo,l+p*e.lo],s=[n+u*e.hi,l+p*e.hi];Math.hypot(s[0]-i[0],s[1]-i[1])i.pair===t&&Math.abs(i.ux*a-i.uy*o)<=1e-6&&Math.abs((e[0]-i.origin[0])*i.uy-(e[1]-i.origin[1])*i.ux)<=c&&Math.abs((e[2]-i.origin[0])*i.uy-(e[3]-i.origin[1])*i.ux)<=c);h||(h={pair:t,origin:[e[0],e[1]],ux:o,uy:a,ranges:[]},l.push(h));const d=(e[0]-h.origin[0])*h.ux+(e[1]-h.origin[1])*h.uy,u=(e[2]-h.origin[0])*h.ux+(e[3]-h.origin[1])*h.uy;h.ranges.push({lo:Math.min(d,u),hi:Math.max(d,u)})}const h=[];for(const t of l){t.ranges.sort((t,e)=>t.lo-e.lo||t.hi-e.hi);const e=[];for(const i of t.ranges){const t=e[e.length-1];t&&i.lo<=t.hi+r?t.hi=Math.max(t.hi,i.hi):e.push({...i})}for(const s of e){const e=[t.origin[0]+t.ux*s.lo,t.origin[1]+t.uy*s.lo],n=[t.origin[0]+t.ux*s.hi,t.origin[1]+t.uy*s.hi];Math.hypot(n[0]-e[0],n[1]-e[1])>=r&&h.push(Kc(e,n,i))}}return h}function dh(t,e,i,s){const n=Jc(t);if(!n.length)return[];if(e.length!==i.length)return n;const o=[];for(const t of n){const n=Yc(t,s),a=[n[0],n[1]],r=[n[2],n[3]];let l=a,c=r;for(let t=0;t{const e=Zc(t,[s[0],s[1],n[0],n[1]]);if(e.d>.001)return t;const i=h[0]-o[0],a=h[1]-o[1];return[o[0]+i*e.t,o[1]+a*e.t]};if(Zc([(a[0]+r[0])/2,(a[1]+r[1])/2],[s[0],s[1],n[0],n[1]]).d<.01){l=d(a),c=d(r);break}}o.push(Kc(l,c,s))}return o}const uh=15e3,ph=2e3,_h=new WeakMap;function gh(t,e){let i=_h.get(t);if(!i){const e=new Set;i={hiddenAt:"hidden"===t.visibilityState?Date.now():0,token:0,subscribers:e,onVisibility:()=>{const e=_h.get(t);if(!e)return;const i=Date.now();if("hidden"===t.visibilityState){e.hiddenAt||(e.hiddenAt=i);const t={kind:"hidden",token:e.token,at:i,hiddenFor:0,long:!1};for(const i of[...e.subscribers])i(t);return}const s=e.hiddenAt?Math.max(0,i-e.hiddenAt):0;e.hiddenAt=0,e.token++;const n={kind:"visible",token:e.token,at:i,hiddenFor:s,long:s>=uh};for(const t of[...e.subscribers])t(n)},onPageShow:e=>{const i=_h.get(t);if(!i)return;const s=Date.now();i.token++;const n={kind:"pageshow",token:i.token,at:s,hiddenFor:0,long:!!e.persisted,persisted:!!e.persisted};for(const t of[...i.subscribers])t(n)}},_h.set(t,i),t.addEventListener("visibilitychange",i.onVisibility),t.defaultView?.addEventListener("pageshow",i.onPageShow)}return i.subscribers.add(e),()=>{const i=_h.get(t);i&&(i.subscribers.delete(e),i.subscribers.size||(t.removeEventListener("visibilitychange",i.onVisibility),t.defaultView?.removeEventListener("pageshow",i.onPageShow),_h.delete(t)))}}const mh={now:()=>Date.now(),setTimeout:(t,e)=>window.setTimeout(t,e),clearTimeout:t=>window.clearTimeout(t),requestAnimationFrame:t=>window.requestAnimationFrame(t),cancelAnimationFrame:t=>window.cancelAnimationFrame(t)};class fh{constructor(t,e=mh){this.onChange=t,this.clock=e,this._state="steady",this._token=0,this._frameFingerprint="",this._hasCompleteFrame=!1,this._overlayPhase="none",this._recoveryReason=null,this._overlayTimer=0,this._overlayRaf=0,this._overlayOpaqueAt=0,this._barrierRafs=new Set,this._trace=[],this._disposed=!1}get state(){return this._state}get token(){return this._token}get frameFingerprint(){return this._frameFingerprint}get hasCompleteFrame(){return this._hasCompleteFrame}get overlayPhase(){return this._overlayPhase}get overlayVisible(){return"none"!==this._overlayPhase}get overlayBlocksInteraction(){return this.overlayVisible}get recoveryReason(){return this._recoveryReason}get trace(){return this._trace.map(t=>({...t,...t.stage?{stage:[...t.stage]}:{}}))}note(t,e={}){this.record(t,void 0,e)}record(t,e,i={}){this._trace.push({at:this.clock.now(),token:this._token,event:t,state:this._state,...e?{reason:e}:{},...i}),this._trace.length>80&&this._trace.splice(0,this._trace.length-80)}changed(){this._disposed||this.onChange()}adoptCompleteFrame(t){t&&(this._hasCompleteFrame=!0,this._frameFingerprint=t,this._state="steady",this._recoveryReason=null,this.clearOverlay(),this.record("frame-adopted"),this.changed())}markCompleteFrame(t){t&&(this._hasCompleteFrame=!0,this._frameFingerprint=t,this._state="steady",this._recoveryReason=null,this.clearOverlay(),this.record("frame-complete"),this.changed())}refreshCompleteFrame(t){!this._disposed&&this._hasCompleteFrame&&"steady"===this._state&&t&&t!==this._frameFingerprint&&(this._frameFingerprint=t,this.record("frame-refreshed"))}visibility(t){return"hidden"===t.kind?(this.record("visibility-hidden"),this._token):t.long||"visible"!==t.kind&&"pageshow"!==t.kind?this.beginCandidate("pageshow"===t.kind?"pageshow":"long-resume"):(this.record("pageshow"===t.kind?"pageshow-noop":"visibility-visible-quick"),this._token)}beginCandidate(t,e="plan"){return this._token++,this._recoveryReason=e,this._hasCompleteFrame?(this._state="connection"===e?"offline-stale":"holding",this.clearOverlay()):this.overlayVisible?this._state="overlay-visible":(this._state="overlay-pending",this.scheduleOverlay(e)),this.record("candidate-start",t),this.changed(),this._token}connectionLost(){return this.beginCandidate("connection-lost","connection")}candidateReady(t){return!this._disposed&&t===this._token&&(this._state="candidate-ready",this.record("candidate-ready"),this.changed(),!0)}async commitAfterPaint(t,e){if(this._disposed||t!==this._token)return!1;let i=!0;const s=(async()=>{for(await e.updateComplete();i&&!this._disposed&&t===this._token;)if(e.stageValid()&&e.assetsReady()){if(await this.nextFrame(),t!==this._token||!e.stageValid()||!e.assetsReady())continue;if(await this.nextFrame(),t===this._token&&e.stageValid()&&e.assetsReady())return!0}else await this.nextFrame();return!1})();let n=0;const o=new Promise(t=>{n=this.clock.setTimeout(()=>t({ready:!1,timedOut:!0}),ph)}),a=await Promise.race([s.then(t=>({ready:t,timedOut:!1})),o]);return i=!1,this.clock.clearTimeout(n),!this._disposed&&t===this._token&&(!(!a.ready&&!a.timedOut)&&(a.ready?(this._hasCompleteFrame=!0,this._frameFingerprint=e.frameFingerprint(),this.record("paint-barrier"),this.finishOverlayAfterCommit(),!0):(this.record("paint-barrier-timeout"),this._hasCompleteFrame?(this._state="connection"===this._recoveryReason?"offline-stale":"steady",this.clearOverlay()):(this._state="recovery-error","opaque"!==this._overlayPhase&&this.showOverlayNow()),this.changed(),!1)))}retry(t=this._recoveryReason||"plan"){return this.beginCandidate("retry",t)}nextFrame(){return new Promise(t=>{const e=this.clock.requestAnimationFrame(()=>{this._barrierRafs.delete(e),t()});this._barrierRafs.add(e)})}scheduleOverlay(t){this.clearOverlayTimer(),this._recoveryReason=t,this._overlayTimer=this.clock.setTimeout(()=>{this._overlayTimer=0,this._hasCompleteFrame||"overlay-pending"!==this._state&&"candidate-ready"!==this._state||(this._state="overlay-visible",this._overlayPhase="entering",this.record("overlay-enter"),this.changed(),this._overlayRaf=this.clock.requestAnimationFrame(()=>{this._overlayRaf=0,"entering"===this._overlayPhase&&(this._overlayPhase="fading-in",this.changed(),this._overlayTimer=this.clock.setTimeout(()=>{this._overlayTimer=0,"fading-in"===this._overlayPhase&&(this._overlayPhase="opaque",this._overlayOpaqueAt=this.clock.now(),this.record("overlay-opaque"),this.changed())},150))}))},150)}showOverlayNow(){this.clearOverlayTimer(),this._overlayPhase="opaque",this._overlayOpaqueAt=this.clock.now(),this.record("overlay-error")}finishOverlayAfterCommit(){if(this.clearOverlayTimer(),"none"===this._overlayPhase||"entering"===this._overlayPhase||"fading-in"===this._overlayPhase)return this.clearOverlay(),this._state="steady",this._recoveryReason=null,this.record("candidate-committed"),void this.changed();const t=Math.max(0,this._overlayOpaqueAt+250-this.clock.now());this._overlayTimer=this.clock.setTimeout(()=>{this._overlayTimer=0,this._overlayPhase="leaving",this.record("overlay-leave"),this.changed(),this._overlayTimer=this.clock.setTimeout(()=>{this._overlayTimer=0,this._overlayPhase="none",this._state="steady",this._recoveryReason=null,this.record("candidate-committed"),this.changed()},180)},t)}clearOverlayTimer(){this._overlayTimer&&this.clock.clearTimeout(this._overlayTimer),this._overlayTimer=0}clearOverlay(){this.clearOverlayTimer(),this._overlayRaf&&this.clock.cancelAnimationFrame(this._overlayRaf),this._overlayRaf=0,this._overlayPhase="none",this._overlayOpaqueAt=0}dispose(){this._disposed=!0,this._token++,this.clearOverlay();for(const t of this._barrierRafs)this.clock.cancelAnimationFrame(t);this._barrierRafs.clear()}}function vh(t){let e=2166136261,i=2654435769;const s=new WeakSet,n=t=>{for(let s=0;s>>0)+(i>>>2)}},o=t=>{if(null===t)return void n("n");const e=typeof t;if("string"===e)return void n(`s${t.length}:${t}`);if("number"===e)return void n(`d${Number.isNaN(t)?"NaN":String(t)}`);if("boolean"===e)return void n(t?"t":"f");if("undefined"===e)return void n("u");if("object"!==e)return void n(`${e}:${String(t)}`);const i=t;if(s.has(i))n("[cycle]");else{if(s.add(i),Array.isArray(t)){n("[");for(const e of t)o(e);return n("]"),void s.delete(i)}n("{");for(const e of Object.keys(t).sort())n(e),o(t[e]);n("}"),s.delete(i)}};return o(t),`${(e>>>0).toString(16).padStart(8,"0")}${(i>>>0).toString(16).padStart(8,"0")}`}function yh(t){return vh(t)}const bh=new WeakMap;class wh{constructor(t,e=()=>Date.now()){this.onUpdate=t,this.now=e,this.fallbackAuthority={},this.referenceOwner={},this.referenced=new Set,this.queued=new Set,this.disposed=!1,this.sharedUpdate=()=>{this.disposed||this.onUpdate()}}bind(t){const e=((t,e)=>{const i=t?.connection||t?.callWS||e;return!i||"object"!=typeof i&&"function"!=typeof i?e:i})(t,this.fallbackAuthority);return this.shared&&this.authority===e||(this.shared&&(this.shared.listeners.delete(this.sharedUpdate),this.shared.references.delete(this.referenceOwner)),this.authority=e,this.shared=(t=>{let e=bh.get(t);return e||(e={signed:{},queued:new Set,inFlight:new Map,retry:new Map,listeners:new Set,settlers:new Set,references:new Map},bh.set(t,e)),e})(e),this.disposed||(this.shared.listeners.add(this.sharedUpdate),this.shared.references.set(this.referenceOwner,new Set(this.referenced)))),this.shared}start(t,e){this.disposed=!1,this.referenced=new Set(e());const i=this.bind(t());i.listeners.add(this.sharedUpdate),i.references.set(this.referenceOwner,new Set(this.referenced)),this.stopTimer(),this.resignTimer=setInterval(()=>this.resign(t(),e()),288e5)}dispose(){if(this.disposed=!0,this.stopTimer(),clearTimeout(this.batchTimer),this.shared){this.shared.listeners.delete(this.sharedUpdate),this.shared.references.delete(this.referenceOwner);for(const t of this.queued)this.shared.queued.delete(t)}this.queued.clear()}invalidate(t){const e=this.bind(t);clearTimeout(this.batchTimer),this.queued.clear(),e.queued.clear(),e.inFlight.clear(),e.retry.clear(),e.signed={}}stopTimer(){void 0!==this.resignTimer&&clearInterval(this.resignTimer),this.resignTimer=void 0}display(t,e){const i=As(e);if(!i.startsWith("/api/houseplan/content/"))return i;const s=this.bind(t);this.referenced.add(i),s.references.set(this.referenceOwner,new Set(this.referenced));const n=s.signed[i],o=n?this.now()-n.at:1/0;return o{const e=[...this.queued];this.queued.clear();for(const t of e)i.queued.delete(t);this.sign(t,e)},30))}sign(t,e){if(!e.length||!t?.callWS)return;const i=this.bind(t);for(const s of function(t,e){const i=Math.max(1,Math.floor(e)),s=[];for(let e=0;e{const s=i.inFlight.get(t);return!(void 0!==s&&e-s<15e3)&&(i.inFlight.set(t,e),!0)});n.length&&t.callWS({type:"houseplan/content/sign",paths:n}).then(t=>{const e=this.now();let s=0,o=!1;for(const a of n){const n=t?.urls?.[a];if("string"==typeof n&&n){const t=i.signed[a];t?.loaded&&t.url!==n?(t.pending={url:n,at:e},this.preloadReplacement(i,a,n,e)):(i.signed[a]={url:n,at:e,loaded:t?.url===n&&!!t.loaded},o=!0),i.retry.delete(a),s++}else this.backOff(i,a)}if(s&&(this.trimShared(i),o))for(const t of[...i.listeners])t()}).catch(()=>{for(const t of n)this.backOff(i,t)}).finally(()=>{for(const t of n)i.inFlight.get(t)===e&&i.inFlight.delete(t);for(const t of[...i.settlers])t()})}}preloadReplacement(t,e,i,s){const n=()=>{const n=t.signed[e];if(n?.pending?.url===i){t.signed[e]={url:i,at:s,loaded:!0},t.retry.delete(e),this.trimShared(t);for(const e of[...t.listeners])e()}},o=()=>{const s=t.signed[e];s?.pending?.url===i&&(delete s.pending,this.backOff(t,e))};if("undefined"==typeof Image)return void n();const a=new Image;a.onload=()=>{("function"==typeof a.decode?a.decode():Promise.resolve()).then(n).catch(o)},a.onerror=o,a.src=i}preloadCurrentImage(t,e,i){if(i.loaded)return Promise.resolve(!0);if(i.preload)return i.preload;if("undefined"==typeof Image)return i.loaded=!0,Promise.resolve(!0);const s=i.url;return i.preload=new Promise(n=>{const o=new Image;let a=!1;const r=o=>{if(a)return;a=!0,clearTimeout(l);const r=t.signed[e];if(r===i&&delete r.preload,o&&r===i&&r.url===s){r.loaded=!0;for(const e of[...t.listeners])e();n(!0)}else o||r!==i||this.backOff(t,e),n(!1)};o.onload=()=>{("function"==typeof o.decode?o.decode():Promise.resolve()).then(()=>r(!0)).catch(()=>r(!1))},o.onerror=()=>r(!1);const l=setTimeout(()=>r(!1),ph);o.src=s}),i.preload}prepareImage(t,e){const i=As(e);if(!i.startsWith("/api/houseplan/content/"))return Promise.resolve(!0);const s=this.bind(t),n=()=>{const e=s.signed[i];if(e&&this.now()-e.atthis.now()&&!s.inFlight.has(i)&&!s.queued.has(i)?Promise.resolve(!1):null},o=n();return o?(a=o,new Promise(t=>{let e=!1;const i=i=>{e||(e=!0,clearTimeout(s),t(i))},s=setTimeout(()=>i(!1),ph);a.then(i).catch(()=>i(!1))})):new Promise(t=>{let e=!1,i=null;const o=i=>{e||(e=!0,clearTimeout(r),s.settlers.delete(a),t(i))},a=()=>{e||i||(i=n(),i&&i.then(o).catch(()=>o(!1)))},r=setTimeout(()=>o(!1),ph);s.settlers.add(a),a()});var a}backOff(t,e){const i=t.retry.get(e)?.delay||0,s=Math.min(6e4,i?2*i:2e3);t.retry.set(e,{notBefore:this.now()+s,delay:s})}trimShared(t){const e=Object.entries(t.signed);if(e.length<=512)return;const i=new Set(t.inFlight.keys());for(const e of t.references.values())for(const t of e)i.add(t);for(const[t,s]of e)(s.pending||s.preload)&&i.add(t);e.sort((t,e)=>e[1].at-t[1].at);const s=e.filter(([t])=>i.has(t));for(const t of e){if(s.length>=512)break;i.has(t[0])||s.push(t)}t.signed=Object.fromEntries(s)}resign(t,e){const i=this.bind(t);this.referenced=new Set(e),i.references.set(this.referenceOwner,new Set(this.referenced));const s=this.now(),n=new Set;for(const t of i.references.values())for(const e of t)n.add(e);const o={};for(const[t,e]of Object.entries(i.signed))n.has(t)&&s-e.at!!o[t]&&!o[t].pending))}markLoaded(t,e,i){const s=As(e);if(!s.startsWith("/api/houseplan/content/"))return;const n=this.bind(t).signed[s];if(n&&(!i||n.url===i)&&!n.loaded){n.loaded=!0;for(const e of[...this.bind(t).listeners])e()}}isReady(t,e){const i=As(e);if(!i.startsWith("/api/houseplan/content/"))return!0;const s=this.bind(t).signed[i];return!!s&&this.now()-s.att.id===e)}function xh(t="file"){const e="draw"===t;return{source:t,showBorders:e,showNames:e,displayTouched:!1}}function $h(t,e){if(t.displayTouched)return{...t,source:e};const i="draw"===e;return{...t,source:e,showBorders:i,showNames:i}}function Sh(t,e,i){return{...t,[e]:i,displayTouched:!0}}function Mh(t,e,i){return[t[0]*e+t[1]*i+t[2],t[3]*e+t[4]*i+t[5]]}function Ch(t,e){let i=0;for(const[s,n]of e){const e=Mh(t,s[0],s[1]);i=Math.max(i,Math.hypot(e[0]-n[0],e[1]-n[1]))}return i}const Dh=t=>{if(null==t||""===t)return null;const e=Number(t);return Number.isFinite(e)?e:null},Th=t=>{const e=t,i=Dh(Array.isArray(e)?e[0]:e?.x),s=Dh(Array.isArray(e)?e[1]:e?.y);return null==i||null==s?null:[i,s]};function Ph(t){if(!Array.isArray(t))return null;const e=[];for(const i of t){const t=Th(i);if(!t)return null;e.push(t)}if(e.length>1){const t=e[0],i=e[e.length-1];t[0]===i[0]&&t[1]===i[1]&&e.pop()}if(e.length<3)return null;let i=0,s=0,n=0;for(let t=0;tt+e[0],0)/e.length,e.reduce((t,e)=>t+e[1],0)/e.length]:[s/(3*i),n/(3*i)]}function Rh(t){if(!Array.isArray(t))return null;const e=[];for(const i of t){const t=Th(i);if(!t)return null;e.push(t)}if(e.length>1){const t=e[0],i=e[e.length-1];t[0]===i[0]&&t[1]===i[1]&&e.pop()}const i=Ph(e);if(!i)return null;const s=e.map(t=>t[0]),n=e.map(t=>t[1]);return{centroid:i,bbox:[Math.min(...s),Math.min(...n),Math.max(...s),Math.max(...n)]}}function Ih(t){let e=t;if(e&&"object"==typeof e&&!Array.isArray(e)){const t=e;e=t.path??t.points??e}if(!Array.isArray(e)||!e.length)return[];let i=(e.some(t=>(t=>Array.isArray(t)?t.length>=2&&!Array.isArray(t[0])&&("object"!=typeof t[0]||null==t[0]):!!t&&"object"==typeof t&&("x"in t||"y"in t))(t))?[e]:e.filter(Array.isArray)).map(t=>t.map(Th).filter(t=>null!=t)).filter(t=>t.length>=2);i.length>64&&(i=i.slice(-64));if(i.reduce((t,e)=>t+e.length,0)<=4e3)return i.map(t=>t.slice());const s=4e3-2*i.length,n=i.map(t=>t.length-2),o=n.reduce((t,e)=>t+e,0),a=n.map(t=>s*t/o),r=a.map(Math.floor);let l=s-r.reduce((t,e)=>t+e,0);const c=a.map((t,e)=>({index:e,fraction:t-Math.floor(t)})).sort((t,e)=>e.fraction-t.fraction||t.index-e.index);for(let t=0;tfunction(t,e){if(e>=t.length)return t.slice();if(e<=2)return[t[0],t[t.length-1]];const i=[];for(let s=0;st.slice()),i=e[e.length-1];return i?(i.length>2?i.pop():e.pop(),e):[]}function Eh(t){if(!t)return null;const e=t.vacuum_position||t.robot_position||null,i=e&&null!=Dh(e.x)&&null!=Dh(e.y)?{x:Dh(e.x),y:Dh(e.y),a:Dh(e.a??e.angle??e.theta)}:null,s=Ih(t.path?.path??t.path?.points??t.path),n=[],o=t.rooms,a=Array.isArray(o)?o.map((t,e)=>[String(t?.id??e),t]):o&&"object"==typeof o?Object.entries(o):[];for(const[t,e]of a){if(!e||"object"!=typeof e)continue;const i=String(e.name??e.label??"").trim(),s=[[Dh(e.cx),Dh(e.cy)],[Dh(e.center?.x),Dh(e.center?.y)],[Dh(e.x),Dh(e.y)]].find(([t,e])=>null!=t&&null!=e);let o=s?.[0]??null,a=s?.[1]??null;const r=Rh(e.outline),l=Dh(e.x0),c=Dh(e.y0),h=Dh(e.x1),d=Dh(e.y1),u=(null!=l&&null!=c&&null!=h&&null!=d?[Math.min(l,h),Math.min(c,d),Math.max(l,h),Math.max(c,d)]:null)||r?.bbox||null;if(null!=o&&null!=a||!r||([o,a]=r.centroid),null!=o&&null!=a||!u||(o=(u[0]+u[2])/2,a=(u[1]+u[3])/2),i&&null!=o&&null!=a){const e={id:t,name:i,cx:o,cy:a};u&&([e.x0,e.y0,e.x1,e.y1]=u),n.push(e)}}const r=function(t){return String(t.map_name??t.current_map??t.map_index??t.selected_map??"default")}(t);return i||n.length||s.length?{pos:i,path:s,rooms:n,mapId:r}:null}function zh(t,e,i){if(!t||!e)return null;const s=e.attributes||{},n=t.split(".")[0]||"",o=null!=i?.platform?String(i.platform):null,a=!!Th(s.vacuum_position??s.robot_position),r=!(!s.rooms||"object"!=typeof s.rooms),l=Ih(s.path?.path??s.path?.points??s.path).length>0,c=[s.map_name,s.current_map,s.map_index,s.selected_map].some(t=>null!=t),h="xiaomi_cloud_map_extractor"===o,d=r||l||c;let u=null;if(a?u="compatible":h?u="known_xcme_incomplete":d?u="partial":"camera"===n&&(u="camera"),!u)return null;const p=a?"camera"===n?300:200:h?100:d?50:0;return{entityId:t,name:String(s.friendly_name||t),platform:o,category:u,hasPosition:a,hasRooms:r,hasPath:l,hasMapId:c,score:p}}const Oh=t=>t.toLowerCase().replace(/[\s_\-.,]+/g,"");function Nh(t,e){const i=new Map(e.map(t=>[Oh(t.name),t])),s=[],n=[];for(const e of t){const t=i.get(Oh(e.name));t&&(s.push([[e.cx,e.cy],[t.cx,t.cy]]),n.push(e.name))}if(s.length<3)return null;const o=function(t){if(t.length<3)return null;let e=0,i=0,s=0,n=0,o=0,a=0,r=0,l=0,c=0,h=0,d=0,u=0;for(const[[p,_],[g,m]]of t){if(![p,_,g,m].every(Number.isFinite))return null;e+=p*p,i+=p*_,s+=p,n+=_*_,o+=_,a+=1,r+=p*g,l+=_*g,c+=g,h+=p*m,d+=_*m,u+=m}const p=[e,i,s,i,n,o,s,o,a],_=t=>{const[e,i,s,n,o,a,r,l,c]=p,h=e*(o*c-a*l)-i*(n*c-a*r)+s*(n*l-o*r);if(!Number.isFinite(h)||Math.abs(h)<1e-9)return null;const d=[(o*c-a*l)/h,(s*l-i*c)/h,(i*a-s*o)/h,(a*r-n*c)/h,(e*c-s*r)/h,(s*n-e*a)/h,(n*l-o*r)/h,(i*r-e*l)/h,(e*o-i*n)/h];return[d[0]*t[0]+d[1]*t[1]+d[2]*t[2],d[3]*t[0]+d[4]*t[1]+d[5]*t[2],d[6]*t[0]+d[7]*t[1]+d[8]*t[2]]},g=_([r,l,c]),m=_([h,d,u]);if(!g||!m)return null;const f=[g[0],g[1],g[2],m[0],m[1],m[2]];return f.every(Number.isFinite)?f:null}(s);return o?{matrix:o,matched:n,residual:Ch(o,s)}:null}function Hh(t,e,i){const s=t[t.length-1];if(s&&s[0]===e[0]&&s[1]===e[1])return t;if(t.push(e),t.length<=600)return t;let n=function(t,e){if(t.length<3)return t.slice();const i=new Uint8Array(t.length);i[0]=i[t.length-1]=1;const s=[[0,t.length-1]];for(;s.length;){const[n,o]=s.pop(),[a,r]=t[n],[l,c]=t[o],h=l-a,d=c-r,u=Math.hypot(h,d)||1e-9;let p=0,_=-1;for(let e=n+1;ep&&(p=i,_=e)}_>0&&p>e&&(i[_]=1,s.push([n,_],[_,o]))}const n=[];for(let e=0;e600&&(n=n.filter((t,e)=>e%2==0||e===n.length-1)),n}function Lh(t){return"cleaning"===t||"returning"===t||"on"===t}const Bh={0:[1,0],90:[0,1],180:[-1,0],270:[0,-1]};function qh(t){const[e,i]=Bh[t.rot]||[1,0],s=t.mir?-1:1;return[t.s*e*s,-t.s*i,t.ox,t.s*i*s,t.s*e,t.oy]}function Wh(t){const e=t[0]*t[4]-t[1]*t[3];if(!Number.isFinite(e)||Math.abs(e)<1e-12)return null;const i=e<0,s=Math.sqrt(Math.abs(e));let n=180*Math.atan2(-t[1],t[4])/Math.PI;return n=(90*Math.round(n/90)%360+360)%360,{ox:t[2],oy:t[5],s:s,rot:n,mir:i}}function jh(t,e,i,s){const[n,o]=Mh(qh(e),i,s),a=qh({...t,ox:0,oy:0}),[r,l]=Mh(a,i,s);return{...t,ox:n-r,oy:o-l}}function Uh(t){const e=t?.trail_mode;return"never"===e||"cleaning"===e||"always"===e?e:!1===t?.trail?"never":"cleaning"}const Gh={offStates:["off"],unknownUsesToggle:!0},Vh={light:Gh,switch:Gh,fan:Gh,humidifier:Gh,input_boolean:Gh,automation:Gh,remote:Gh,group:Gh,climate:{...Gh,featureMasks:{turn_on:256,turn_off:128,toggle:384}},media_player:{...Gh,featureMasks:{turn_on:128,turn_off:256,toggle:384}},siren:{...Gh,featureMasks:{turn_on:1,turn_off:2,toggle:3}},vacuum:{...Gh,featureMasks:{turn_on:1,turn_off:2,toggle:3}},water_heater:{...Gh,featureMasks:{turn_on:8,turn_off:8,toggle:8}},camera:{...Gh,featureMasks:{turn_on:1,turn_off:1,toggle:1}}};function Kh(t){return t.slice(0,t.indexOf("."))}function Yh(t,e,i){if(!t?.services||"object"!=typeof t.services)return!1;const s=t.services?.[e];return!!s&&Object.prototype.hasOwnProperty.call(s,i)}function Xh(t,e,i){return Yh(t,e,i)?{domain:e,service:i}:Yh(t,"homeassistant",i)?{domain:"homeassistant",service:i}:null}function Jh(t,e){return t?.entities?.[e]||null}function Zh(t,e,i){const s=t?.states?.[i],n=Jh(e,i);return s?.attributes?.friendly_name||n?.name||n?.original_name||i}function Qh(t,e){const i=Jh(t,e);if(null!=i?.disabled_by)return!0;const s=i?.device_id?t?.devices?.[i.device_id]:null;return null!=s?.disabled_by}function td(t,e){const i=t?.attributes?.supported_features;if(null==i||""===i)return!1;const s=Number(i);return Number.isFinite(s)&&(s&e)===e}function ed(t,e,i){const s=Kh(i);if("lock"===s||"alarm_control_panel"===s)return!0;if("cover"!==s)return!1;const n=t?.states?.[i],o=Jh(e,i),a=String(n?.attributes?.device_class||o?.device_class||o?.original_device_class||"");return Ui.has(a)}function id(t,e,i,s,n){return{ref:i,entityId:s,name:s?Zh(t,e,s):null,reason:n}}function sd(t,e,i,s,n,o=null){return{target:null,skipped:id(t,e,i,s,n),semantics:o,nextEffect:null,command:null}}function nd(t,e,i,s,n=i){const o=Kh(i);if("cover"!==o&&"valve"!==o)return function(t,e,i,s,n=i){const o=Kh(i),a=t?.states?.[i];if(Qh(e,i))return sd(t,e,n,i,"ha-disabled","power");if(ed(t,e,i))return sd(t,e,n,i,"secure");if(!a)return sd(t,e,n,i,"missing","power");if("unavailable"===a.state)return sd(t,e,n,i,"unavailable","power");const r=Vh[o];if(!r)return sd(t,e,n,i,"unsupported");let l,c;if("unknown"===a.state||""===a.state){if(!r.unknownUsesToggle)return sd(t,e,n,i,"unsupported","power");l="toggle",c="toggle"}else r.offStates.includes(String(a.state))?(l="turn-on",c="turn_on"):(l="turn-off",c="turn_off");const h=r.featureMasks?.[c];if(h&&!td(a,h))return sd(t,e,n,i,"unsupported","power");const d=Xh(t,o,c);return d?{target:{entityId:i,name:Zh(t,e,i),state:String(a.state||""),via:s},skipped:null,semantics:"power",nextEffect:l,command:{...d,data:{entity_id:i}}}:sd(t,e,n,i,"unsupported","power")}(t,e,i,s,n);if(Qh(e,i))return sd(t,e,n,i,"ha-disabled",o);if(ed(t,e,i))return sd(t,e,n,i,"secure",o);const a=t?.states?.[i];if(!a)return sd(t,e,n,i,"missing",o);if("unavailable"===a.state)return sd(t,e,n,i,"unavailable",o);const r=function(t,e,i){const s=String(i?.state||""),n="closed"===s?{service:`open_${e}`,effect:"open",feature:1}:"open"===s?{service:`close_${e}`,effect:"close",feature:2}:"opening"===s||"closing"===s?{service:`stop_${e}`,effect:"stop",feature:8}:null;return n&&td(i,n.feature)&&Yh(t,e,n.service)?n:td(i,3)&&Yh(t,e,"toggle")?{service:"toggle",effect:"toggle"}:null}(t,o,a);if(!r)return sd(t,e,n,i,"unsupported",o);return{target:{entityId:i,name:Zh(t,e,i),state:String(a.state||""),via:s},skipped:null,semantics:o,nextEffect:r.effect,command:{domain:o,service:r.service,data:{entity_id:i}}}}function od(t){return"entity"===t.bindingKind?t.bindingRef&&Ms(t.bindingRef)?[t.bindingRef]:[]:"virtual"===t.bindingKind?[]:to(t)}function ad(t){const e=t.marker?.toggle_entity;return e&&od(t).includes(e)?e:null}function rd(t,e,i){const s=function(t,e){if("entity"===t.bindingKind&&t.bindingRef){const e=t.marker?.light_entity?eo(t):null;return[...new Set([e,t.bindingRef].filter(t=>!!t))]}const i=t.entities.length?t.entities:t.allEntities||[],s=t.marker?.light_entity||t.primary&&Ms(t.primary)?eo(t):null;return[...new Set([s,...Yn(e,i)].filter(t=>!!t))]}(i,e);if(!s.length)return null;const n="entity"===i.bindingKind?"binding":"device-role";if("binding"===n)return nd(t,e,s[0],n);let o=null,a=null;for(const i of s){const s=nd(t,e,i,n);if(s.command)return s;const r=s.skipped?.reason;if("missing"===r||"unavailable"===r||"secure"===r)return s;"ha-disabled"!==r?o||=s:a||=s}return o||a}function ld(t){const e=t.skipped?.reason;return"missing"===e?"unavailable":e||"unsupported"}function cd(t,e){return{origin:t,kind:"none",semantics:null,targets:[],skippedTargets:[],noneReason:e,nextEffect:null,command:null}}function hd(t,e){return"cover"===t||"toggle"===t?"toggle":"more-info"===t||"run"===t||"info"===t?t:(null==t||""===t)&&"light"===e?"toggle":"info"}function dd(t,e){return{origin:t,kind:"single",semantics:e.semantics,targets:e.target?[e.target]:[],skippedTargets:e.skipped?[e.skipped]:[],noneReason:e.command?null:ld(e),nextEffect:e.nextEffect,command:e.command}}function ud(t,e,i,s=[]){const n=new Map,o=[],a=new Set,r=t=>{const e=`${t.ref}\n${t.entityId||""}\n${t.reason}`;a.has(e)||(a.add(e),o.push(t))};for(const t of s)r(t);for(const s of i){const i=nd(t,e,s.entityId,s.via,s.ref);i.target?n.set(s.entityId,n.get(s.entityId)||i.target):i.skipped&&r(i.skipped)}const l=[...n.values()];if(!l.length)return{origin:"explicit-toggle",kind:"group",semantics:"group-power",targets:l,skippedTargets:o,noneReason:o.length&&o.every(t=>"secure"===t.reason)?"secure":"configured-targets-missing",nextEffect:null,command:null};const c=l.some(t=>"on"===t.state)?"turn_off":"turn_on",h=Xh(t,"homeassistant",c);return h?{origin:"explicit-toggle",kind:"group",semantics:"group-power",targets:l,skippedTargets:o,noneReason:null,nextEffect:"turn_on"===c?"turn-on":"turn-off",command:{...h,data:{entity_id:l.map(t=>t.entityId)}}}:{origin:"explicit-toggle",kind:"group",semantics:"group-power",targets:[],skippedTargets:[...o,...l.map(i=>id(t,e,i.entityId,i.entityId,"unsupported"))],noneReason:"unsupported",nextEffect:null,command:null}}function pd(t){return String(t.marker?.id||t.id||"")}function _d(t){const{hass:e,device:i}=t,s=t.registryHass||e,n=function(t){return"toggle"===t.tapAction?"explicit-toggle":"cover"===t.tapAction?"legacy-cover":!t.tapAction&&t.primary?.startsWith("light.")?"default-light":null}(i);if(!n)return null;const o=i.marker;if("explicit-toggle"===n&&yn(o)){const e=String(o?.id||i.id||""),s=ro(t.devices).get(e);if(s)return function(t,e){const i=t.registryHass||t.hass;return ud(t.hass,i,e.driverEids.map(t=>({entityId:t,via:"control-marker-driver",ref:`marker:${e.markerId}`})))}(t,s);const a=bn(o,t.virtualLights);return{origin:n,kind:"single",semantics:"power",targets:[{entityId:"",name:i.name,state:a?"on":"off",via:"virtual-light"}],skippedTargets:[],noneReason:null,nextEffect:a?"turn-off":"turn-on",command:null,operation:{kind:"virtual-light",markerId:o.id}}}if("explicit-toggle"===n){if(Zn(i.marker?.binding,i.marker?.controls??i.controls,i.entities).length)return function(t,e=null){const{hass:i,device:s,devices:n}=t,o=t.registryHass||i,a=Zn(s.marker?.binding,s.marker?.controls??s.controls,s.entities),r=t.lightSources||ho(i,n,null,t.virtualLights),l=new Map;for(const t of r){if(!t.key.startsWith("marker:"))continue;const e=l.get(t.key)||[];e.push(t),l.set(t.key,e)}const c=ro(n),h=new Map;for(const t of n){const e=String(t.marker?.id||t.id||"");e&&h.set(e,t)}const d=[],u=[];e&&d.push({entityId:e,via:"entity"===s.bindingKind?"binding":"device-role",ref:e});for(const t of a){if(!t.startsWith("marker:")){Ms(t)?d.push({entityId:t,via:"control-entity",ref:t}):u.push(id(i,o,t,t.includes(".")?t:null,"unsupported"));continue}const e=l.get(t)||[];if(!e.length){const e=h.get(t.slice(7));if("ha_disabled"===e?.bindingStatus?.kind){const s=e.bindingStatus.allEntityIds[0]||null;u.push({ref:t,entityId:s,name:e.name||(s?Zh(i,o,s):null),reason:"ha-disabled"})}else u.push(id(i,o,t,null,"missing"));continue}const n=[...new Set(e.flatMap(t=>t.serviceEids))];if(n.length){for(const e of n)d.push({entityId:e,via:"control-entity",ref:t});continue}const a=e.some(t=>t.passive),r=t.slice(7),p=pd(s),_=c.get(r)?.controllers.find(t=>pd(t.device)===p);if(a&&_?.driverEids.length)for(const e of _.driverEids)d.push({entityId:e,via:"control-marker-driver",ref:t});else u.push(id(i,o,t,null,a?"missing":"unsupported"))}return ud(i,o,d,u)}(t,ad(i))}if("legacy-cover"===n){const t=i.entities.find(t=>t.startsWith("cover."))||i.allEntities?.find(t=>t.startsWith("cover."));return t?dd(n,nd(e,s,t,"device-role")):cd(n,"no-actionable-entity")}const a=ad(i),r=a?nd(e,s,a,"entity"===i.bindingKind?"binding":"device-role"):rd(e,s,i);return r?dd(n,r):cd(n,i.virtual||"virtual"===i.bindingKind?"no-actionable-entity":"no-binding")}function gd(t){if(!t)return[];const e=Array.isArray(t.data.entity_id)?t.data.entity_id:[t.data.entity_id];return[...new Set(e)].sort()}function md(t){return t?t.operation?t.operation:t.command?{kind:"ha-service",command:t.command}:null:null}function fd(t,e){const i=md(t),s=md(e);return!(!i||!s||i.kind!==s.kind)&&("virtual-light"===i.kind&&"virtual-light"===s.kind?i.markerId===s.markerId:"ha-service"===i.kind&&"ha-service"===s.kind&&function(t,e){const i=gd(t),s=gd(e);return i.length===s.length&&i.every((t,e)=>t===s[e])}(i.command,s.command))}const vd=t=>!!t&&t.length>=2&&Number.isFinite(t[0])&&Number.isFinite(t[1]);function yd(t,e=5,i=5){return xr(t.cm,e,i)/2}function bd(t,e,i=1,s=5,n=5,o=0){const a=t.host;if(!a||"partition"!==a.kind||"string"!=typeof a.id||!a.id)return{resolved:null,reason:"invalid-host"};const r=e.find(t=>t.id===a.id);if(!r)return{resolved:null,reason:"missing-partition"};if(!vd(r.a)||!vd(r.b)||!Number.isFinite(a.t)||a.t<0||a.t>1)return{resolved:null,reason:"invalid-position"};const l=r.b[0]-r.a[0],c=r.b[1]-r.a[1],h=Math.hypot(l,c),d=Number(t.length)*i;if(!(h>1e-9&&d>0&&Number.isFinite(d)))return{resolved:null,reason:"invalid-length"};const u=a.t*h;if(u-d/2h-o+1e-9)return{resolved:null,reason:"does-not-fit"};const p=l/h,_=c/h;let g=180*Math.atan2(c,l)/Math.PI;return g>=90?g-=180:g<-90&&(g+=180),{reason:null,resolved:{opening:t,host:a,partition:r,center:[r.a[0]+l*a.t,r.a[1]+c*a.t],angle:g,length:d,depth:xr(r.cm,s,n),t:a.t,axis:{a:[r.a[0],r.a[1]],b:[r.b[0],r.b[1]],ux:p,uy:_,length:h}}}}function wd(t,e,i=1,s=5,n=5){return bd(t,e,i,s,n,0)}function kd(t,e,i=1,s=5,n=5){const o=t.host,a="partition"===o?.kind?e.find(t=>t.id===o.id):void 0;if(!a)return wd(t,e,i,s,n);const r=bd(t,e,i,s,n,yd(a,s,n));return"does-not-fit"===r.reason?{resolved:null,reason:"does-not-fit-jamb"}:r}function xd(t,e){return!t||(t.length!==e.length||t.host?.kind!==e.host?.kind||t.host?.id!==e.host?.id||t.host?.t!==e.host?.t)}function $d(t){const{center:e,length:i,axis:s,host:n}=t,o=i/2;return{hostId:n.id,a:[e[0]-s.ux*o,e[1]-s.uy*o],b:[e[0]+s.ux*o,e[1]+s.uy*o],depth:t.depth}}function Sd(t,e=!1){const i=e?1:-1,s=t.depth/2;return{ox:-t.axis.uy*i*s,oy:t.axis.ux*i*s,cm:t.partition.cm,side:i}}function Md(t,e,i){const{center:s,length:n,axis:o}=t,a=n/2,r=e.flatMap(t=>{if(!t.kind||t.open)return[];const e=t.b[0]-t.a[0],n=t.b[1]-t.a[1],r=Math.hypot(e,n);if(!(r>i))return[];const l=e/r,c=n/r;if(Math.abs(o.ux*c-o.uy*l)>1e-6)return[];if(Math.abs((s[0]-t.a[0])*c-(s[1]-t.a[1])*l)>i)return[];const h=t=>(t[0]-s[0])*o.ux+(t[1]-s[1])*o.uy,d=h(t.a),u=h(t.b),p=Math.max(-a,Math.min(d,u)),_=Math.min(a,Math.max(d,u));return _>=p-i?[[p,_]]:[]});if(!r.length)return!1;r.sort((t,e)=>t[0]-e[0]||t[1]-e[1]);let l=-a;for(const[t,e]of r){if(t>l+i)return!1;if(l=Math.max(l,e),l>=a-i)return!0}return!1}function Cd(t,e,i){return{...t,x:e.center[0]/i,y:e.center[1]/i,angle:e.angle}}const Dd=.001;function Td(t){return!!t&&t.length>=2&&Number.isFinite(t[0])&&Number.isFinite(t[1])}function Pd(t){return`${t[0].toFixed(6)},${t[1].toFixed(6)}`}function Rd(t,e,i){return Math.abs(t[0]-e[0])Ed(s,t,e)))continue;const t=Pd(s);a.has(t)||a.set(t,{point:[s[0],s[1]],key:t})}}}return{segments:[...o.values()].sort((t,e)=>t.key.localeCompare(e.key)),endpoints:[...a.values()].sort((t,e)=>t.key.localeCompare(e.key))}}function Od(t,e,i){return e.some(e=>Td(e)&&Rd(t,e,i))}function Nd(t,e,i){if(!i)return!0;const s=t-i.distance;return s<-1e-9||Math.abs(s)<=1e-9&&e.localeCompare(i.key)<0}function Hd(t,e,i){const s=i.epsilon??Dd,n=i.excludePoints||[],o=[...t.endpoints,...(i.extraEndpoints||[]).filter(t=>Td(t.point)).map(t=>({point:[t.point[0],t.point[1]],key:t.key}))],a=new Map;for(const t of o){if(Od(t.point,n,s))continue;const e=Pd(t.point),i=a.get(e);(!i||t.key.localeCompare(i.key)<0)&&a.set(e,t)}return[...a.values()].map(t=>({kind:"endpoint",point:[...t.point],key:t.key,distance:Math.hypot(e[0]-t.point[0],e[1]-t.point[1])})).filter(t=>t.distance<=i.tolerance).sort((t,e)=>t.distance-e.distance||t.key.localeCompare(e.key))}function Ld(t,e){if(!t.length)return null;if(e>0){const i=new Set;for(let s=0;s1)return{kind:"ambiguous",candidate:null,conflicts:t.filter(t=>i.has(t.key)).map(t=>({point:[...t.point],key:t.key}))}}return{kind:"resolved",candidate:t[0],conflicts:[]}}function Bd(t,e,i){const s=t.b[0]-t.a[0],n=t.b[1]-t.a[1],o=Math.hypot(s,n);if(!(o>0))return[...t.a];const a=s/o,r=n/o,l=Math.max(0,Math.min(o,(e[0]-t.a[0])*a+(e[1]-t.a[1])*r)),c=i>0?Math.max(0,Math.min(o,Math.round(l/i)*i)):l;return[t.a[0]+a*c,t.a[1]+r*c]}function qd(t,e,i){if(!(Td(e)&&Td(i.anchor)&&i.tolerance>=0))return{kind:"none",candidate:null,conflicts:[]};const s=i.epsilon??Dd,n=function(t,e){const i=e[0]-t[0],s=e[1]-t[1];if(!(Math.hypot(i,s)>Number.EPSILON))return null;const n=Math.round(Math.atan2(s,i)/(Math.PI/4))*(Math.PI/4);return[Math.cos(n),Math.sin(n)]}(i.anchor,e);if(!n)return{kind:"none",candidate:null,conflicts:[]};const o=Hd(t,e,i).filter(t=>function(t,e,i,s){const n=t[0]-e[0],o=t[1]-e[1];return n*i[0]+o*i[1]>s&&Math.abs(n*i[1]-o*i[0])<=s*Math.max(Math.hypot(n,o),1)}(t.point,i.anchor,n,s)),a=Ld(o,i.distinguishTolerance||0);if(a)return a;let r=null;for(const o of t.segments){const t=o.b[0]-o.a[0],a=o.b[1]-o.a[1],l=o.a[0]-i.anchor[0],c=o.a[1]-i.anchor[1],h=n[0]*a-n[1]*t;let d=null;if(Math.abs(h)<=s*Math.max(Math.hypot(t,a),1)){if(Math.abs(l*n[1]-c*n[0])>s*Math.max(Math.hypot(l,c),1))continue;const t=[o.a,o.b].map(t=>({point:t,along:(t[0]-i.anchor[0])*n[0]+(t[1]-i.anchor[1])*n[1]})).filter(t=>t.along>s).sort((t,e)=>t.along-e.along);t.length&&(d=[...t[0].point])}else{const e=(l*a-c*t)/h,o=(l*n[1]-c*n[0])/h;e>s&&o>=-s&&o<=1+s&&(d=[i.anchor[0]+n[0]*e,i.anchor[1]+n[1]*e])}if(!d)continue;const u=Math.hypot(e[0]-d[0],e[1]-d[1]);u>i.tolerance||Od(d,i.excludePoints||[],s)||!Nd(u,o.key,r)||(r={kind:"line",point:d,key:o.key,distance:u,segment:o})}return r?{kind:"resolved",candidate:r,conflicts:[]}:{kind:"none",candidate:null,conflicts:[]}}const Wd=.001;function jd(t,e,i,s){const n=Number.isFinite(t)&&t>0?Math.floor(t):0,o=t=>"number"==typeof t&&Number.isFinite(t)&&t>0?t:null,a=o(i),r=o(s)??1,l=[];let c=null;for(let t=0;t=2&&Number.isFinite(t[0])&&Number.isFinite(t[1])}function Vd(t,e,i,s){return t*s-e*i}function Kd(t){let e=0;for(let i=0;it.localeCompare(e)),e[0]}function Qd(t,e,i){const s=[...t];for(let t=!0;t&&s.length>=3;){t=!1;for(let n=0;n=0){s.splice(n,1),t=!0;break}}}return s}function tu(t,e){const i=t.map(t=>Math.max(0,Math.min(1,t))).sort((t,e)=>t-e),s=[];for(const t of i)(!s.length||Math.abs(t-s[s.length-1])>e)&&s.push(t);return s}function eu(t,e){return[t.a[0]+(t.b[0]-t.a[0])*e,t.a[1]+(t.b[1]-t.a[1])*e]}function iu(t,e,i){const s=function(t,e){const i=e.b[0]-e.a[0],s=e.b[1]-e.a[1],n=i*i+s*s;return n>0?((t[0]-e.a[0])*i+(t[1]-e.a[1])*s)/n:0}(t,e);if(s<-i||s>1+i)return null;const n=eu(e,s);return Math.hypot(n[0]-t[0],n[1]-t[1])<=i?Math.max(0,Math.min(1,s)):null}function su(t,e,i,s,n){const o=t.b[0]-t.a[0],a=t.b[1]-t.a[1],r=e.b[0]-e.a[0],l=e.b[1]-e.a[1],c=e.a[0]-t.a[0],h=e.a[1]-t.a[1],d=Vd(o,a,r,l),u=Math.max(Math.hypot(o,a),Math.hypot(r,l),1);if(Math.abs(d)>n*u){const t=Vd(c,h,r,l)/d,e=Vd(c,h,o,a)/d;return void(t>=-n&&t<=1+n&&e>=-n&&e<=1+n&&(i.push(Math.max(0,Math.min(1,t))),s.push(Math.max(0,Math.min(1,e)))))}if(!(Math.abs(Vd(c,h,o,a))>n*u)){for(const s of[e.a,e.b]){const e=iu(s,t,n);null!=e&&i.push(e)}for(const i of[t.a,t.b]){const t=iu(i,e,n);null!=t&&s.push(t)}}}function nu(t){let e=t+1|0;return e^=e<<13,e^=e>>>17,e^=e<<5,e>>>0}function ou(t,e){return t.minY-e.minY||t.index-e.index}function au(t){return t.subtreeMaxY=Math.max(t.item.maxY,t.left?.subtreeMaxY??-1/0,t.right?.subtreeMaxY??-1/0),t}function ru(t){const e=t.right;return t.right=e.left,e.left=au(t),au(e)}function lu(t){const e=t.left;return t.left=e.right,e.right=au(t),au(e)}function cu(t,e){return t?(ou(e,t.item)<0?(t.left=cu(t.left,e),t.left.priority0)t.right=hu(t.right,e);else{if(!t.left)return t.right;if(!t.right)return t.left;t.left.priority=e&&du(t.left,e,i,s),t.item.minY<=i&&t.item.maxY>=e&&s.push(t.item),t.item.minY<=i&&du(t.right,e,i,s))}function uu(t,e=.001){const i=Number.isFinite(e)&&e>0?e:Wd,s=t.filter(t=>Gd(t.a)&&Gd(t.b)&&"string"==typeof t.key&&t.key.length>0&&Math.hypot(t.b[0]-t.a[0],t.b[1]-t.a[1])>i),n=s.map(()=>[0,1]);!function(t,e,i){const s=t.map((t,e)=>({index:e,minX:Math.min(t.a[0],t.b[0])-i,maxX:Math.max(t.a[0],t.b[0])+i,minY:Math.min(t.a[1],t.b[1])-i,maxY:Math.max(t.a[1],t.b[1])+i})),n=[...s].sort((t,e)=>t.minX-e.minX||t.minY-e.minY||t.index-e.index),o=[...s].sort((t,e)=>t.maxX-e.maxX||t.index-e.index),a=new Set;let r=null,l=0;for(const s of n){for(;lt.index-e.index);for(const o of n)su(t[o.index],t[s.index],e[o.index],e[s.index],i);a.add(s.index),r=cu(r,s)}}(s,n,i);const o=new Map;for(let t=0;t({key:t,a:e.a,b:e.b,sourceKeys:[...e.sourceKeys].sort((t,e)=>t.localeCompare(e))})).sort((t,e)=>t.key.localeCompare(e.key))}function pu(t,e=.001){const i=Number.isFinite(e)&&e>0?e:Wd,s=uu(t,i),n=new Map,o=new Map,a=new Map(s.map(t=>[t.key,t]));for(const t of s){const e=Xd(t.a,i),s=Xd(t.b,i);n.set(e,t.a),n.set(s,t.b),o.has(e)||o.set(e,new Set),o.has(s)||o.set(s,new Set),o.get(e).add(s),o.get(s).add(e)}const r=new Map;for(const[t,e]of o){const i=n.get(t);r.set(t,[...e].sort((t,e)=>{const s=n.get(t),o=n.get(e);return Math.atan2(s[1]-i[1],s[0]-i[0])-Math.atan2(o[1]-i[1],o[0]-i[0])||t.localeCompare(e)}))}const l=new Set,c=new Map,h=(t,e)=>`${t}>${e}`;for(const t of s){const e=[Xd(t.a,i),Xd(t.b,i)];for(const[t,o]of[e,[e[1],e[0]]]){if(l.has(h(t,o)))continue;const e=[],d=[];let u=t,p=o,_=!1;for(let i=0;i<=2*s.length+2;i++){const i=h(u,p);if(l.has(i)){_=u===t&&p===o;break}l.add(i),e.push(u),d.push(Jd(u,p));const s=r.get(p)||[],n=s.indexOf(u);if(n<0||!s.length)break;if(u=p,p=s[(n-1+s.length)%s.length],u===t&&p===o){_=!0;break}}if(!_||new Set(e).size<3||new Set(e).size!==e.length)continue;const g=e.map(t=>n.get(t)),m=Kd(g);if(!(m>i*i))continue;const f=Zd(Qd(e,n,i)),v=new Set;for(const t of d)for(const e of a.get(t)?.sourceKeys||[])v.add(e);const y={ring:g,key:f,area:m,atomKeys:[...d],sourceKeys:[...v].sort((t,e)=>t.localeCompare(e))};c.has(f)||c.set(f,y)}}return{atoms:s,faces:[...c.values()].sort((t,e)=>t.area-e.area||t.key.localeCompare(e.key))}}function _u(t,e,i=.001){if(!Gd(e))return null;const s=t.faces.filter(t=>{if(t.ring.some((s,n)=>function(t,e,i,s){const n=i[0]-e[0],o=i[1]-e[1],a=n*n+o*o;if(!(a>0))return Math.hypot(t[0]-e[0],t[1]-e[1])<=s;const r=((t[0]-e[0])*n+(t[1]-e[1])*o)/a;return!(r<0||r>1)&&Math.hypot(e[0]+n*r-t[0],e[1]+o*r-t[1])<=s}(e,s,t.ring[(n+1)%t.ring.length],i)))return!1;let s=!1;for(let i=0,n=t.ring.length-1;ie[1]!=a[1]>e[1]&&e[0]<(a[0]-o[0])*(e[1]-o[1])/(a[1]-o[1])+o[0]&&(s=!s)}return s});return[...s].sort((t,e)=>t.area-e.area||t.key.localeCompare(e.key))[0]||null}function gu(t,e,i){const s=i[0]-e[0],n=i[1]-e[1],o=s*s+n*n,a=o>0?Math.max(0,Math.min(1,((t[0]-e[0])*s+(t[1]-e[1])*n)/o)):0;return Math.hypot(e[0]+s*a-t[0],e[1]+n*a-t[1])}function mu(t,e,i=.5){let s=Math.abs(t-e)%180;return s>90&&(s=180-s),s<=i}function fu(t,e,i,s){const n=t.filter(t=>"outer"===t.kind&&!t.open&&t.cm>0).map(t=>({interval:t,reusePartitionId:e.find(e=>function(t,e,i){return!(Math.abs(t.cm-e.cm)>1e-6)&&(mu(180*Math.atan2(t.b[1]-t.a[1],t.b[0]-t.a[0])/Math.PI,180*Math.atan2(e.b[1]-e.a[1],e.b[0]-e.a[0])/Math.PI,.001)&&gu(e.a,t.a,t.b)<=i&&gu(e.b,t.a,t.b)<=i)}(e,t,s))?.id||null})),o=new Map;for(const e of i){if("partition"===e.host?.kind)continue;const i=t.map(t=>{const i=180*Math.atan2(t.b[1]-t.a[1],t.b[0]-t.a[0])/Math.PI;return{interval:t,distance:mu(e.angle,i)?gu([e.x,e.y],t.a,t.b):1/0}}).filter(t=>t.distance<=s).sort((t,e)=>t.distance-e.distance||t.interval.key.localeCompare(e.interval.key)),n=i[0]?.interval;"outer"===n?.kind&&!n.open&&n.cm>0&&o.set(e.id,n.key)}return{materialize:n,openingIntervals:o,removeOpeningIds:[...o.keys()].sort((t,e)=>t.localeCompare(e))}}function vu(t,e){const i=e.b[0]-e.a[0],s=e.b[1]-e.a[1],n=i*i+s*s;return n>0?Math.max(0,Math.min(1,((t[0]-e.a[0])*i+(t[1]-e.a[1])*s)/n)):0}const yu=t=>!t.key.startsWith("static:room|");function bu(t,e){const i=e.b[0]-e.a[0],s=e.b[1]-e.a[1],n=i*i+s*s;if(!(n>0))return null;const o=((t[0]-e.a[0])*i+(t[1]-e.a[1])*s)/n,a=[e.a[0]+i*o,e.a[1]+s*o];return{point:a,t:o,distance:Math.hypot(a[0]-t[0],a[1]-t[1])}}function wu(t,e){return e>0?Math.hypot(t[0]-Math.round(t[0]/e)*e,t[1]-Math.round(t[1]/e)*e):0}function ku(t,e,i){if(yu(t.source)!==yu(e.source))return yu(t.source)?t:e;const s=wu(t.point,i),n=wu(e.point,i);return Math.abs(s-n)>1e-9?s>n?t:e:function(t,e){return t[0]-e[0]||t[1]-e[1]}(t.point,e.point)>0?t:e}function xu(t){return[t.from[0],t.from[1],t.to[0],t.to[1],t.targetKind].map(t=>"number"==typeof t?t.toFixed(6):t).join("|")}function $u(t,e){return t.map(t=>t.key!==e.sourceKey?t:{...t,[e.endpoint]:[...e.to]})}function Su(t,e){const i=e.epsilon??.001;if(!(e.maxDistance>=0)||!e.point&&!e.requiredSourceKey)return{kind:"none"};const s=new Map,n=t.flatMap(t=>[{source:t,endpoint:"a",point:t.a},{source:t,endpoint:"b",point:t.b}]);for(let t=0;ti)||l>e.maxDistance)continue;const c=ku(a,r,e.gridStep||0),h=c===a?r:a;if(!yu(c.source))continue;const d={sourceKey:c.source.key,endpoint:c.endpoint,from:[c.point[0],c.point[1]],to:[h.point[0],h.point[1]],targetSourceKey:h.source.key,targetKind:"endpoint",distance:l};s.set(xu(d),d)}for(const o of n)if(yu(o.source))for(const n of t){if(n===o.source)continue;const t=bu(o.point,n);if(!t||t.t<=i||t.t>=1-i||!(t.distance>i)||t.distance>e.maxDistance)continue;const a={sourceKey:o.source.key,endpoint:o.endpoint,from:[o.point[0],o.point[1]],to:t.point,targetSourceKey:n.key,targetKind:"line",distance:t.distance};s.set(xu(a),a)}const o=[];for(const n of s.values()){const s=pu($u(t,n),i),a=e.point?_u(s,e.point,i):s.faces.find(t=>!e.requiredSourceKey||t.sourceKeys.includes(e.requiredSourceKey))||null;a&&o.push({proposal:n,face:a})}if(o.sort((t,e)=>t.proposal.distance-e.proposal.distance||xu(t.proposal).localeCompare(xu(e.proposal))),!o.length)return{kind:"none"};return new Set(o.map(t=>`${xu(t.proposal)}|${t.face.key}`)).size>1?{kind:"ambiguous",proposals:o.map(t=>t.proposal)}:{kind:"repair",...o[0]}}const Mu=1e-5;function Cu(t){const e=t.map(()=>[]);for(let i=0;i=1-1e-9||u<=1e-9||u>=1-1e-9||(e[i].push(d),e[a].push(u))}}const i=[];for(let s=0;st-e),1];for(let t=1;t{const i=e[2]-e[0],s=e[3]-e[1],n=i*i+s*s;if(!(n>0))return Math.hypot(t[0]-e[0],t[1]-e[1]);const o=Math.max(0,Math.min(1,((t[0]-e[0])*i+(t[1]-e[1])*s)/n));return Math.hypot(t[0]-(e[0]+o*i),t[1]-(e[1]+o*s))},Pu=(t,e,i,s)=>{const n=s[2]-s[0],o=s[3]-s[1],a=e*o-i*n;if(Math.abs(a)<1e-12)return 1/0;const r=s[0]-t[0],l=s[1]-t[1],c=(r*o-l*n)/a;if(!(c>1e-9))return 1/0;const h=(r*i-l*e)/a;return h<-1e-9||h>1+1e-9?1/0:c};function Ru(t,e,i,s=96){if(!(e>0&&Number.isFinite(t[0])&&Number.isFinite(t[1])))return[];const n=[];for(const s of i){if(!s||s.length<4)continue;if(![s[0],s[1],s[2],s[3]].every(Number.isFinite))continue;const i=Tu(t,s);if(i<1e-7)return[];i>e||n.push(s)}const o=[],a=Math.max(12,Math.round(s));for(let t=0;tt-e);const l=[];let c=Number.NEGATIVE_INFINITY;for(const i of o){if(i-c<1e-9)continue;c=i;const s=Math.cos(i),o=Math.sin(i);let a=e;for(const e of n){const i=Pu(t,s,o,e);i=3?l:[]}class Iu extends ht{constructor(){super(...arguments),this._spaces=null,this._spacesLoading=!1}setConfig(t){this._config=t}async _loadSpaces(){if(!this._spaces&&!this._spacesLoading&&this.hass){this._spacesLoading=!0;try{const t=await this.hass.callWS({type:"houseplan/config/get"});this._spaces=(t?.config?.spaces||[]).map(t=>({value:t.id,label:t.title||t.id}))}catch{this._spaces=[]}finally{this._spacesLoading=!1}}}get _lang(){return ra(this.hass,this._config?.language)}get _floorToken(){const t=this._config?.floor;return"number"==typeof t?`__houseplan_yaml_floor_index__:${String(t)}`:null}get _formData(){const t={...this._config},e=this._floorToken;return e?t.floor=e:Object.prototype.hasOwnProperty.call(t,"floor")||(t.floor=""),t}get _schema(){const t=this._spaces||[],e=this._lang,i=[{value:"",label:la(e,"editor.floor_none")}],s=this._floorToken;s&&i.push({value:s,label:la(e,"editor.floor_index",{index:String(this._config?.floor)})});const n="string"==typeof this._config?.floor?this._config.floor:"";return n&&!t.some(t=>t.value===n)&&i.push({value:n,label:n}),i.push(...t),[{name:"title",selector:{text:{}}},{name:"floor",selector:{select:{mode:"dropdown",options:i}}},t.length?{name:"default_floor",selector:{select:{mode:"dropdown",options:t}}}:{name:"default_floor",selector:{text:{}}},{name:"language",selector:{select:{mode:"dropdown",options:[{value:"",label:la(e,"editor.lang_auto")},{value:"en",label:la(e,"editor.lang_en")},{value:"ru",label:la(e,"editor.lang_ru")}]}}},{name:"icon_size",selector:{number:{min:1,max:6,step:.1,mode:"box"}}},{name:"show_temperature",selector:{boolean:{}}},{name:"live_states",selector:{boolean:{}}},{name:"show_signal",selector:{boolean:{}}},{name:"kiosk",selector:{boolean:{}}},{name:"cycle",selector:{number:{min:0,max:3600,step:5,mode:"box"}}}]}render(){if(!this.hass||!this._config)return G;this._loadSpaces();const t=this._lang,e={title:la(t,"editor.title"),floor:la(t,"editor.floor"),default_floor:la(t,"editor.default_floor"),language:la(t,"editor.language"),icon_size:la(t,"editor.icon_size"),show_temperature:la(t,"editor.show_temperature"),live_states:la(t,"editor.live_states"),show_signal:la(t,"editor.show_signal"),kiosk:la(t,"editor.kiosk"),cycle:la(t,"editor.cycle")};return W``}const or={color:"#607d8b",opacity:1,widthCm:3.6,fill:!1,fillColor:"#607d8b",fillOpacity:.25},ar=(t,e=1)=>{const i=Number(t);return Number.isFinite(i)?Math.min(1,Math.max(0,i)):e},rr=t=>{let e=Number(t);return Number.isFinite(e)?(e=(e%360+360)%360,e>180?e-360:e):0};function lr(t,e,i){return rr(e)?[t.x,t.y]:i([t.x,t.y])}const cr=(t,e,i)=>{const s=Number(t),n=Number.isFinite(e)&&e>0?e:5;return Number.isFinite(s)&&s>0?s/n*i:0},hr=(t,e,i)=>{const s=Number(t),n=Number.isFinite(e)&&e>0?e:5;return Number.isFinite(s)&&i>0?s/i*n:0},dr=(t,e,i,s=or.widthCm)=>{const n=Number(t?.width_cm);if(Number.isFinite(n)&&n>0)return n;const o=Number(t?.width);return Number.isFinite(o)&&o>0?hr(o,e,i):s};function ur(t,e){return{color:t.color,opacity:ar(t.opacity),width_cm:Math.max(.1,Math.min(100,Number(t.widthCm)||.1)),...e?{fill:t.fill,fill_color:t.fillColor,fill_opacity:ar(t.fillOpacity,.25)}:{}}}function pr(t){const e=t.x+t.w/2,i=t.y+t.h/2,s=rr(t.angle)*Math.PI/180,n=Math.cos(s),o=Math.sin(s),a=(t,s)=>{const a=t-e,r=s-i;return[e+a*n-r*o,i+a*o+r*n]};return[a(t.x,t.y),a(t.x+t.w,t.y),a(t.x+t.w,t.y+t.h),a(t.x,t.y+t.h)]}function _r(t){const e=pr(t),i=(t,e)=>[(t[0]+e[0])/2,(t[1]+e[1])/2],s=[(e[0][0]+e[2][0])/2,(e[0][1]+e[2][1])/2];return{points:[...e,i(e[0],e[1]),i(e[1],e[2]),i(e[2],e[3]),i(e[3],e[0]),s],segments:e.map((t,i)=>({a:t,b:e[(i+1)%4]}))}}function gr(t,e,i,s,n,o,a,r){const l=rr(t.angle)*Math.PI/180,c=Math.cos(l),h=Math.sin(l),d=-Math.sin(l),u=Math.cos(l),p=t.x+t.w/2,_=t.y+t.h/2,g=e>0?-t.w/2:t.w/2,m=i>0?-t.h/2:t.h/2,f=p+g*c+m*d,v=_+g*h+m*u,y=s-f,b=n-v;let w=(y*c+b*h)*(e>0?1:-1),k=(y*d+b*u)*(i>0?1:-1),x=null;if(o){const e=w/Math.max(t.w,r),i=k/Math.max(t.h,r);x=Math.max(r/Math.max(t.w,r),r/Math.max(t.h,r),e,i),w=t.w*x,k=t.h*x}if(a>0)if(o){const e=Math.max(1,Math.round(t.w/a)),i=Math.max(1,Math.round(t.h/a));if(Math.abs(t.w-e*a)<1e-6&&Math.abs(t.h-i*a)<1e-6){const s=(t,e)=>{let i=Math.abs(t),s=Math.abs(e);for(;s;)[i,s]=[s,i%s];return Math.max(1,i)},n=1/s(e,i),o=Math.max(r/t.w,r/t.h),a=Math.max(o,Math.round((x??1)/n)*n);w=t.w*a,k=t.h*a}else{t.w>=t.h?(w=Math.round(w/a)*a,k=w*(t.h/Math.max(t.w,r))):(k=Math.round(k/a)*a,w=k*(t.w/Math.max(t.h,r)))}}else w=Math.round(w/a)*a,k=Math.round(k/a)*a;w=Math.max(r,w),k=Math.max(r,k);return{x:f+(e>0?w/2:-w/2)*c+(i>0?k/2:-k/2)*d-w/2,y:v+(e>0?w/2:-w/2)*h+(i>0?k/2:-k/2)*u-k/2,w:w,h:k,angle:rr(t.angle)||void 0}}const mr=(t,e,i)=>{const s=i[0]-e[0],n=i[1]-e[1],o=s*s+n*n;if(o<1e-12)return[...e];const a=Math.max(0,Math.min(1,((t[0]-e[0])*s+(t[1]-e[1])*n)/o));return[e[0]+s*a,e[1]+n*a]};const fr=15;function vr(t,e){return Number.isFinite(t)&&t>0&&Number.isFinite(e)&&e>0&&t*e<3}function yr(t){const e=Number(t)>0?Number(t):5;if(5===e)return 8;const i=5/e*8;return Math.min(80,Math.max(.5,i))}function br(t,e){return Number.isFinite(t)&&t>0&&Number.isFinite(e)&&e>0&&t*e<2}function wr(t){return Number.isFinite(t)?Math.max(1,Math.min(100,t)):1}function kr(t,e){return!Number.isFinite(t)||t<=0?"":String(e?Math.round(t/2.54*100)/100:Math.round(100*t)/100)}function xr(t,e,i){const s=Number(e)>0?Number(e):5;return wr(t)/s*i}function $r(t,e){return e>0&&Number.isFinite(t)?Math.round(t/e)*e:t}function Sr(t,e){let i=e[0]-t[0],s=e[1]-t[1];const n=Math.hypot(i,s);return n<1e-12?[1,0]:(i/=n,s/=n,(i<-1e-12||Math.abs(i)<=1e-12&&s<0)&&(i=-i,s=-s),[i,s])}function Mr(t,e,i){const s=$r((t[0]+e[0])/2,i),n=$r((t[1]+e[1])/2,i),[o,a]=Sr(t,e);let r=Math.atan2(a,o);r<0&&(r+=Math.PI);const l=Math.round(1800*r)/1800,c=i>0&&i<.01?6:i<1?4:2;return`${s.toFixed(c)},${n.toFixed(c)}@${l.toFixed(4)}`}function Cr(t,e,i,s){return 1===s?Mr(t,e,i):Mr([t[0]/s,t[1]/s],[e[0]/s,e[1]/s],i)}function Dr(t,e){if(!Array.isArray(t.a)||!Array.isArray(t.b)||t.a.length<2||t.b.length<2)return null;const i=[Number(t.a[0]),Number(t.a[1]),Number(t.b[0]),Number(t.b[1])];if(!i.every(Number.isFinite))return null;const s=e>0?e:1;return[[i[0]*s,i[1]*s],[i[2]*s,i[3]*s]]}function Tr(t,e,i,s,n){const o=n>0?n:1;return{key:Cr(t,e,s,o),cm:wr(i),a:[t[0]/o,t[1]/o],b:[e[0]/o,e[1]/o]}}function Pr(t,e){const i=e>0?e:1,s=[];for(const e of t){const t=e.key.lastIndexOf("@");if(t<0)continue;const[n,o]=e.key.slice(0,t).split(",").map(Number),a=Number(e.key.slice(t+1));[n,o,a].every(Number.isFinite)&&s.push({w:e,x:n*i,y:o*i,ang:a})}return s}function Rr(t,e){const[i,s]=Sr(t,e);let n=Math.atan2(s,i);return n<0&&(n+=Math.PI),n}function Ir(t,e){let i=Math.abs(t-e);return i>Math.PI/2&&(i=Math.PI-i),i<.02}function Ar(t,e,i,s,n=1){if(!t?.length)return null;const o=Cr(e,i,s,n),a=t.find(t=>t.key===o);if(a)return a;const r=n>0?n:1,l=(e[0]+i[0])/2,c=(e[1]+i[1])/2,h=Rr(e,i),d=Math.max(.5*s,1e-9)*r;for(const e of Pr(t,r))if(Ir(e.ang,h)&&Math.hypot(e.x-l,e.y-c)<=d)return e.w;return null}function Fr(t,e,i,s,n=1){const o=Ar(t,e,i,s,n);if(o&&o.cm>0)return wr(o.cm);const a=function(t,e,i,s,n){if(!t?.length)return null;const o=n>0?n:1,a=Math.hypot(i[0]-e[0],i[1]-e[1]);if(a<1e-12)return null;const r=Rr(e,i),l=Math.max(.5*s,1e-9)*o;let c=null;for(const s of t){if(!(s.cm>0))continue;const t=Dr(s,o);if(!t)continue;const n=Math.hypot(t[1][0]-t[0][0],t[1][1]-t[0][1]);if(n<1e-12||!Ir(Rr(t[0],t[1]),r))continue;if(cl(e[0],e[1],t[0][0],t[0][1],t[1][0],t[1][1])>l||cl(i[0],i[1],t[0][0],t[0][1],t[1][0],t[1][1])>l)continue;if(n+l(o.has(t.key)||(t=>{const e=Dr(t,s);if(!e)return!1;const[i,o]=e,r=o[0]-i[0],c=o[1]-i[1],h=Math.hypot(r,c);if(h<=l)return!1;if(!a.some(t=>{const e=[t[0],t[1]],s=[t[2],t[3]];return Ir(Rr(i,o),Rr(e,s))&&cl(i[0],i[1],e[0],e[1],s[0],s[1])<=l&&cl(o[0],o[1],e[0],e[1],s[0],s[1])<=l}))return!1;const d=(n||[]).some(t=>{const e=[t[0],t[1]],s=[t[2],t[3]];if(!Ir(Rr(i,o),Rr(e,s)))return!1;const n=t=>Math.abs((t[0]-i[0])*c-(t[1]-i[1])*r)/h;if(n(e)>l||n(s)>l)return!1;const a=h*h,d=((e[0]-i[0])*r+(e[1]-i[1])*c)/a,u=((s[0]-i[0])*r+(s[1]-i[1])*c)/a;return Math.min(1,Math.max(d,u))-Math.max(0,Math.min(d,u))>l/h});return!d})(t))&&t.cm>=1&&t.cm<=100)}function zr(t,e,i,s=8){const[n,o]=Sr(t,e);let a=Math.atan2(o,n);a<0&&(a+=Math.PI);let r=i*Math.PI/180%Math.PI;r<0&&(r+=Math.PI);let l=Math.abs(a-r);return l>Math.PI/2&&(l=Math.PI-l),l<=s*Math.PI/180}function Or(t,e,i,s,n=1){if(!t?.length)return[];if(e.length!==i.length)return t.slice();const o=new Map;for(let t=0;t0?n:1,r=Math.max(.5*s,1e-9)*a,l=new Set,c=[];for(const n of t){let t="",h=null;const d=Dr(n,a);if(d)for(let n=0;nr||cl(d[1][0],d[1][1],o[0],o[1],l[0],l[1])>r)continue;const p=l[0]-o[0],_=l[1]-o[1],g=p*p+_*_;if(g<1e-18)continue;const m=t=>{const e=Math.max(0,Math.min(1,((t[0]-o[0])*p+(t[1]-o[1])*_)/g));return[c[0]+(u[0]-c[0])*e,c[1]+(u[1]-c[1])*e]};h=[m(d[0]),m(d[1])],t=Cr(h[0],h[1],s,a);break}if(d||(t=o.get(n.key)||""),!t){const o=Pr([n],a)[0];if(o)for(let n=0;n1.000001)continue;if(cl(o.x,o.y,l[0],l[1],c[0],c[1])>r)continue;const m=h[0]+(d[0]-h[0])*Math.max(0,Math.min(1,g)),f=h[1]+(d[1]-h[1])*Math.max(0,Math.min(1,g)),[v,y]=Sr(h,d),b=Math.max(s*a,1e-6);t=Cr([m-v*b,f-y*b],[m+v*b,f+y*b],s,a);break}}t||(t=n.key),l.has(t)||(l.add(t),c.push(h?Tr(h[0],h[1],n.cm,s,a):{...n,key:t,cm:wr(n.cm)}))}return c}function Nr(t,e,i,s,n,o=1){const a=Cr(e,i,n,o),r=(t||[]).filter(t=>t.key!==a);return null==s||s<1?r:[...r,Tr(e,i,s,n,o)]}function Hr(t,e,i,s,n,o=[],a=1){let r=t?t.slice():[];for(const t of function(t,e,i,s,n=1,o=[]){const a=il(t,e,i,s,n,o);if(!a)return[];const r=[];for(let t=0;t0||(c=Nr(c,e,i,s,n,a)))}return c}function Br(t){const{a:e,b:i,halfDepth:s}=t;if(!Array.isArray(e)||!Array.isArray(i)||e.length<2||i.length<2||![e[0],e[1],i[0],i[1]].every(Number.isFinite))return null;const n=i[0]-e[0],o=i[1]-e[1],a=Math.hypot(n,o);if(!(a>1e-9&&s>0&&Number.isFinite(s)))return null;const r=-o/a*s,l=n/a*s;return[[e[0]+r,e[1]+l],[i[0]+r,i[1]+l],[i[0]-r,i[1]-l],[e[0]-r,e[1]-l]]}function qr(t,e,i){return Math.hypot(t[0]-e[0],t[1]-e[1])<=i}function Wr(t,e,i){const s=e.b[0]-e.a[0],n=e.b[1]-e.a[1],o=s*s+n*n;if(!(o>i*i))return!1;const a=((t[0]-e.a[0])*s+(t[1]-e.a[1])*n)/o;if(!(a>0&&a<1))return!1;const r=[e.a[0]+s*a,e.a[1]+n*a];return Math.hypot(t[0]-r[0],t[1]-r[1])<=i}function jr(t,e,i,s){const n=Math.hypot(e,i);if(!(n>1e-9&&s>0))return;const o=[e/n,i/n],a=t.find(t=>Math.abs(t.u[0]*o[1]-t.u[1]*o[0])<1e-9&&t.u[0]*o[0]+t.u[1]*o[1]>1-1e-9);a?a.halfDepth=Math.max(a.halfDepth,s):t.push({u:o,halfDepth:s})}function Ur(t,e=1e-6){const i=(t||[]).filter(t=>t&&Array.isArray(t.a)&&Array.isArray(t.b)&&t.a.length>=2&&t.b.length>=2&&t.a.every(Number.isFinite)&&t.b.every(Number.isFinite)&&Number.isFinite(t.halfDepth)&&t.halfDepth>0&&Math.hypot(t.b[0]-t.a[0],t.b[1]-t.a[1])>1e-9);if(i.length<2)return[];const s=Math.max(Number.isFinite(e)?e:0,1e-9),n=i.flatMap(t=>[t.a,t.b]).map(t=>[t[0],t[1]]).sort((t,e)=>t[0]-e[0]||t[1]-e[1]),o=[];for(const t of n)o.some(e=>qr(e,t,s))||o.push(t);const a=[];for(const t of o){const e=[];for(const n of i)qr(t,n.a,s)?jr(e,n.b[0]-n.a[0],n.b[1]-n.a[1],n.halfDepth):qr(t,n.b,s)?jr(e,n.a[0]-n.b[0],n.a[1]-n.b[1],n.halfDepth):Wr(t,n,s)&&(jr(e,n.a[0]-t[0],n.a[1]-t[1],n.halfDepth),jr(e,n.b[0]-t[0],n.b[1]-t[1],n.halfDepth));if(!(e.length<2)){e.sort((t,e)=>Math.atan2(t.u[1],t.u[0])-Math.atan2(e.u[1],e.u[0])||t.halfDepth-e.halfDepth);for(let i=0;is*s&&a.push(m)}}}return a}function Gr(t,e,i,s){if(!(e>0)||!t||t.length<2)return"";if(i&&t.length>=3){let i=t;const n=t[t.length-1];if(t.length>=4&&Math.hypot(t[0][0]-n[0],t[0][1]-n[1])<1e-9&&(i=t.slice(0,-1)),i.length>=3){const t=i.map((t,i)=>s?.[i]||e),n=wl(i,t),o=Qr(i,t);if(n&&o)return`${tl(n)} ${tl(el(o))}`}}const n=[];for(let i=0;i=1e-9&&r>0&&n.push({a:o,b:a,halfDepth:r})}const o=[...n.map(Br).filter(t=>!!t),...Ur(n)],a=function(t){let e=null;try{for(const i of t){if(i.length<3)continue;const t=dl(i);e=e?si(e,t):[t]}return e}catch{return null}}(o);return a?fl(a):o.map(t=>tl(t)).join(" ")}function Vr(t,e,i,s,n=1){if(!i.length)return!1;const o=Kr(s,n),a=(t[0]+e[0])/2,r=(t[1]+e[1])/2,[l,c]=Sr(t,e);for(const t of i){const[e,i]=Sr([t[0],t[1]],[t[2],t[3]]);if(!(Math.abs(l*i-c*e)>.05)&&cl(a,r,t[0],t[1],t[2],t[3])<=o)return!0}return!1}function Kr(t,e){return Math.max(t*(e>0?e:1)*.04,1e-9)}function Yr(t){let e=0;for(let i=0;it[1]!=l>t[1]&&t[0]<(r-o)*(t[1]-a)/(l-a+0)+o&&(i=!i)}return i}([c[0]+.001*r,c[1]+.001*l],t)||(r=-r,l=-l),[r,l]}function Jr(t,e){const i=t[0]*e[1]-t[1]*e[0],s=t[0]*e[0]+t[1]*e[1];return Math.abs(i)<1e-9&&s>0}function Zr(t,e,i,s){const n=e[0]*s[1]-e[1]*s[0];if(Math.abs(n)<1e-12)return null;const o=[i[0]-t[0],i[1]-t[1]],a=(o[0]*s[1]-o[1]*s[0])/n;return[t[0]+a*e[0],t[1]+a*e[1]]}function Qr(t,e){const i=t?.length||0;if(i<3||e.length!==i)return null;if(e.every(t=>!(t>0)))return t.map(t=>[t[0],t[1]]);const s=[];for(let n=0;n0||d>0)){s.push([t[n][0],t[n][1]]);continue}if(h>0!=d>0){const e=t[n],i=h>0?[e[0]+u*h,e[1]+p*h]:[e[0],e[1]],o=d>0?[e[0]+_*d,e[1]+g*d]:[e[0],e[1]];s.push(i),Math.hypot(o[0]-i[0],o[1]-i[1])>1e-9&&s.push(o);continue}if(Jr(b,w)){const e=t[n],i=[e[0]+u*h,e[1]+p*h],o=[e[0]+_*d,e[1]+g*d];s.push(i),Math.hypot(o[0]-i[0],o[1]-i[1])>1e-9&&s.push(o);continue}const $=Zr(k,b,x,w),S=Math.max(h,d,1e-9);if($){if(Math.hypot($[0]-t[n][0],$[1]-t[n][1])<=4*S){s.push($);continue}}h>0&&s.push([t[n][0]+u*h,t[n][1]+p*h]),d>0&&s.push([t[n][0]+_*d,t[n][1]+g*d]),h>0||d>0||s.push([t[n][0],t[n][1]])}return s.length>=3?s:null}function tl(t,e=!0){if(!t.length)return"";let i=`M ${t[0][0]} ${t[0][1]}`;for(let e=1;et?.id===e),r=hi(a);if(!r||r.length<3)return null;const l=Kr(s,n),c=[];for(const i of t||[]){if(!i||i.id===e)continue;const t=hi(i);if(t)for(const e of Cs(r,t,l))c.push([e[0],e[1]],[e[2],e[3]])}for(const t of i||[])c.push([t[0],t[1]],[t[2],t[3]]);for(const t of o||[]){const e=Dr(t,n);e&&c.push(e[0],e[1])}const h=[],d=[];for(let t=0;tl)continue;const a=((t[0]-e[0])*(i[0]-e[0])+(t[1]-e[1])*(i[1]-e[1]))/(s*s);a<=n||a>=1-n||(o.some(t=>Math.abs(t-a)*s<=2*l)||o.push(a))}o.sort((t,e)=>t-e);for(const s of o)h.push([e[0]+(i[0]-e[0])*s,e[1]+(i[1]-e[1])*s]),d.push(t)}return{poly:h,parent:d,orig:r}}function sl(t,e,i,s){const n=e.poly.length,o=new Array(n).fill(0);if(!t?.length)return o;const a=new Set,r=[];for(let l=0;l0?(o[l]=wr(c.cm),a.add(c.key)):r.push(l)}if(!r.length)return o;const l=s>0?s:1,c=Math.max(.5*i,1e-9)*l,h=Pr(t,l).filter(t=>t.w.cm>0);for(let t=r.length-1;t>=0;t--){const i=r[t],s=e.poly[i],a=e.poly[(i+1)%n],d=Rr(s,a);let u=null;for(const t of h){const e=Dr(t.w,l);if(!e||!Ir(Rr(e[0],e[1]),d))continue;if(cl(s[0],s[1],e[0][0],e[0][1],e[1][0],e[1][1])>c||cl(a[0],a[1],e[0][0],e[0][1],e[1][0],e[1][1])>c)continue;const i=Math.hypot(a[0]-s[0],a[1]-s[1]),n=Math.hypot(e[1][0]-e[0][0],e[1][1]-e[0][1]),o=Math.max(0,n-i);(!u||oc||cl(n[0],n[1],e[0][0],e[0][1],e[1][0],e[1][1])>c)continue;i=!0,o=Math.max(0,Math.hypot(e[1][0]-e[0][0],e[1][1]-e[0][1])-_)}else{if(cl(t.x,t.y,s[0],s[1],n[0],n[1])>c)continue;o=Math.hypot(t.x-d,t.y-u)}(!p||i&&!p.exact||i===p.exact&&ot?.id===e),n=hi(s);if(!n)return[];const o=[];for(const s of t||[]){if(!s||s.id===e)continue;const t=hi(s);if(t)for(const e of Cs(n,t,i))o.push(e)}return o}(t,e,Kr(n,r)),h=function(t,e,i,s,n){const o=Kr(s,n),a=[];for(let r=0;rcl(h,d,t[0],t[1],t[2],t[3])<=o);a.push(u?"shared":"outer")}return a}(l.poly,c,s,n,r),d=sl(i,l,n,r),u=d.map((t,e)=>h[e]&&t>0?xr(t,o,a)/2:0);return{...l,kinds:h,cms:d,offsets:u}}function ol(t,e,i,s,n,o,a=1){const r=[];for(const l of t||[]){if(!l?.id)continue;const c=nl(t,l.id,e,i,s,n,o,a);if(c)for(let t=0;t0&&(r=Nr(r,t.a,t.b,t.cm,s,a));return r}function rl(t,e,i,s,n,o,a=1){if(!e?.length)return[];const r=[],l=new Set;for(const c of ol(t,e,i,s,n,o,a))!c.open&&c.cm>0&&!l.has(c.key)&&(l.add(c.key),r.push(c));const c=[];for(const r of t||[]){if(!r?.id)continue;const l=nl(t,r.id,e,i,s,n,o,a);if(l)for(let t=0;t0)||null===l.kinds[i]){t++;continue}let o=t;for(;o+10&&c.push({a:[h[0],h[1]],b:[d[0],d[1]],key:Cr(h,d,s,a),cm:n,len:u}),t=o+1}}}c.sort((t,e)=>e.len-t.len||t.key.localeCompare(e.key));const h=[],d=new Set,u=new Set,p=4*Kr(s,a);for(const t of c){const e=r.filter(e=>!u.has(e.key)&&e.cm===t.cm&&Ir(Rr(e.a,e.b),Rr(t.a,t.b))&&cl(e.a[0],e.a[1],t.a[0],t.a[1],t.b[0],t.b[1])<=p&&cl(e.b[0],e.b[1],t.a[0],t.a[1],t.b[0],t.b[1])<=p);if(e.length){for(const t of e)u.add(t.key);d.has(t.key)||(d.add(t.key),h.push(Tr(t.a,t.b,t.cm,s,a)))}}for(const t of r)u.has(t.key)||d.has(t.key)||(d.add(t.key),h.push(Tr(t.a,t.b,t.cm,s,a)));return h}function ll(t,e,i,s,n,o,a,r=1){const l=Kr(n,r),c=(s[0]+s[2])/2,h=(s[1]+s[3])/2,d=Rr([s[0],s[1]],[s[2],s[3]]);let u=null;for(const s of ol(t,e,i,n,o,a,r)){if(!Ir(Rr(s.a,s.b),d))continue;const t=cl(c,h,s.a[0],s.a[1],s.b[0],s.b[1]);t>4*l||(!u||tt?.id===e),c=hi(l);if(!c||c.length<3)return null;if(!i?.length)return c.map(t=>[t[0],t[1]]);const h=nl(t,e,i,s,n,o,a,r);return h&&h.offsets.some(t=>t>0)&&Qr(h.poly,h.offsets)||c.map(t=>[t[0],t[1]])}function dl(t){const e=t.map(t=>[t[0],t[1]]);return e.push([t[0][0],t[0][1]]),[e]}function ul(t,e=1){if(!Array.isArray(t)||t.length<3)return null;const i=Number.isFinite(e)&&e>0?e:1,s=1e-12*Math.max(1,i),n=[];for(const e of t){if(!Array.isArray(e)||e.length<2)return null;const t=Number(e[0]),i=Number(e[1]);if(!Number.isFinite(t)||!Number.isFinite(i))return null;const o=Math.round(t/s)*s,a=Math.round(i/s)*s;if(!Number.isFinite(o)||!Number.isFinite(a))return null;n.push([Object.is(o,-0)?0:o,Object.is(a,-0)?0:a])}return Math.abs(Yr(n))>s*s?n:null}function pl(t,e,i,s){if(cl(t[0],t[1],e[0],e[1],i[0],i[1])>s)return!1;const n=i[0]-e[0],o=i[1]-e[1],a=(t[0]-e[0])*n+(t[1]-e[1])*o,r=n*n+o*o,l=s*Math.sqrt(r);return a>=-l&&a<=r+l}function _l(t,e,i){const s=[],n=[];for(let o=0;oi*i))continue;const d=i/Math.sqrt(h),u=[0,1];for(const t of e)for(const e of[t.a,t.b]){if(!pl(e,a,r,i))continue;const t=((e[0]-a[0])*l+(e[1]-a[1])*c)/h;t>d&&t<1-d&&u.push(t)}u.sort((t,e)=>t-e);const p=u.filter((t,e)=>0===e||Math.abs(t-u[e-1])>d);for(let t=0;t=3&&n.length===s.length?{poly:s,offsets:n}:null}function gl(t,e,i,s,n,o,a){const r=(t||[]).map(hi).filter(t=>!!t&&t.length>=3);if(!r.length)return null;let l=si(dl(r[0]));for(let t=1;t"outer"===t.kind&&t.half>0),h=4*Kr(s,a);let d=null;for(const t of function(t){const e=[];for(const i of Array.isArray(t)?t:[])if(Array.isArray(i))for(const t of i){if(!Array.isArray(t)||t.length<4)continue;const i=t.slice(0,-1).map(t=>[t[0],t[1]]);i.length>=3&&e.push(i)}return e}(l)){const e=_l(t,c,h);if(!e||!e.offsets.some(t=>t>0))continue;const i=wl(e.poly,e.offsets),s=Qr(e.poly,e.offsets);if(!i||!s)continue;const n=oi(dl(i),dl(s));d=d?si(d,n):n}return{centre:l,shell:d||[]}}function ml(t,e,i,s,n,o,a=1){try{const r=gl(t,e,i,s,n,o,a);return r?r.shell?.length?si(r.centre,r.shell):r.centre:[]}catch{return null}}function fl(t){if(!t)return"";let e="";for(const i of t)if(Array.isArray(i))for(const t of i){if(!Array.isArray(t)||t.length<4)continue;const i=t.slice(0,t.length-1);i.length<3||(e+=(e?" ":"")+tl(i.map(t=>[t[0],t[1]])))}return e}function vl(t,e,i,s=[],n,o,a,r=1,l=[]){if(!e?.length&&!l.length)return null;const c=[];let h=0;for(const s of t||[]){if(!s?.id)continue;const l=nl(t,s.id,e,i,n,o,a,r);if(!l||l.poly.length<3||!l.offsets.some(t=>t>0))continue;for(const t of l.offsets)t>0&&(h=Math.max(h,2*t));const d=wl(l.poly,l.offsets),u=Qr(l.poly,l.offsets);d&&c.push({outset:d,inset:u})}for(const t of l){const e=t.map(t=>t[0]),i=t.map(t=>t[1]);if(e.length){const s=Math.min(Math.max(...e)-Math.min(...e),Math.max(...i)-Math.min(...i)),n=Math.min(...t.map((e,i)=>{const s=t[(i+1)%t.length];return Math.hypot(s[0]-e[0],s[1]-e[1])}));h=Math.max(h,t.length>16?s:n)}}const d=function(t,e,i,s,n,o,a){if(!e?.length||!i?.length)return[];const r=4*Kr(s,a),l=new Map;for(const r of ol(t,e,i,s,n,o,a))!r.open&&r.half>0&&!l.has(r.key)&&l.set(r.key,r);const c=[...l.values()];if(c.length<2)return[];const h=[];for(const t of i)for(const e of[[t[0],t[1]],[t[2],t[3]]])h.some(t=>Math.hypot(t[0]-e[0],t[1]-e[1])<=r)||h.push(e);const d=[],u=(t,e)=>{let i=0,s=0;if(Math.hypot(t.a[0]-e[0],t.a[1]-e[1])<=r)i=t.b[0]-t.a[0],s=t.b[1]-t.a[1];else{if(!(Math.hypot(t.b[0]-e[0],t.b[1]-e[1])<=r))return null;i=t.a[0]-t.b[0],s=t.a[1]-t.b[1]}const n=Math.hypot(i,s);return n>r?[i/n,s/n]:null};for(const t of h){const e=c.map(e=>({iv:e,u:u(e,t)})).filter(t=>!!t.u);for(let i=0;i4*_||d.push(a>0?[t.slice(),h,p,u]:[t.slice(),u,p,h])}}return d}(t,e,i,n,o,a,r),u=s.length?kl(t,e,i,n,o,a,r):null;try{const p=gl(t,e,i,n,o,a,r),_=p?p.shell?.length?si(p.centre,p.shell):p.centre:[],g=t=>{const e=dl(t.outset);return t.inset?oi(e,dl(t.inset)):e};let m=null;for(const t of c)try{const e=g(t);m=m?si(m,e):e}catch{}if(p)for(const s of bl(t,e,i,n,o,a,r))try{const t=ni(dl(s.quad),p.centre);m=m?si(m,t):t}catch{}m=function(t,e,i=1,s=si){let n=t;for(const t of e||[]){const e=ul(t,i);if(e)try{const t=dl(e);n=n?s(n,t):t}catch{}}return n}(m,d,r),m&&p&&(m=ni(m,p.centre)),p?.shell?.length&&(m=m?si(m,p.shell):p.shell);for(const t of s){if(!(t.length>0))continue;const e=Sl(u,t,!0);if(!e.negative&&!e.positive)continue;const i=t.angle*Math.PI/180,s=Math.cos(i),o=Math.sin(i),a=-o,l=s,c=t.length/2,d=1.25*Math.max(h,n*r),p=[[t.x-s*c-a*d,t.y-o*c-l*d],[t.x+s*c-a*d,t.y+o*c-l*d],[t.x+s*c+a*d,t.y+o*c+l*d],[t.x-s*c+a*d,t.y-o*c+l*d]];m&&(m=oi(m,dl(p)))}for(const t of l)t.length<3||(m=m?si(m,dl(t)):[dl(t)]);return{geom:m||[],paperGeom:_,depthUnits:h,openingIndex:u}}catch{return null}}function yl(t,e,i,s=[],n,o,a,r=1,l=[]){if(!e?.length&&!l.length)return null;const c=vl(t,e,i,s,n,o,a,r,l),h=c?fl(c.geom):"",d=c?fl(c.paperGeom):"";return c&&h?{d:h,paperD:d,depthUnits:c.depthUnits,fillRule:"evenodd"}:null}function bl(t,e,i,s,n,o,a=1){if(!e?.length)return[];const r=new Set,l=[];for(const c of t||[]){if(!c?.id)continue;const h=nl(t,c.id,e,i,s,n,o,a);if(!h)continue;const d=h.poly;for(let t=0;t0))continue;const p=Cr(e,i,s,a);if(r.has(p))continue;r.add(p);const _=xr(u,n,o),[g,m]=Xr(d,t),f=-g,v=-m,y=_/2,b=[[e[0]+f*y,e[1]+v*y],[i[0]+f*y,i[1]+v*y],[i[0]+g*y,i[1]+m*y],[e[0]+g*y,e[1]+m*y]];l.push({key:p,kind:c,cm:u,quad:b,a:[e[0],e[1]],b:[i[0],i[1]],depthUnits:_})}}return l}function wl(t,e){const i=t?.length||0;if(i<3||e.length!==i)return null;if(e.every(t=>!(t>0)))return t.map(t=>[t[0],t[1]]);el(t),e.slice().reverse();const s=[];for(let n=0;n0||r>0)){s.push([t[n][0],t[n][1]]);continue}if(a>0!=r>0){const e=t[n],i=a>0?[e[0]-l*a,e[1]-c*a]:[e[0],e[1]],o=r>0?[e[0]-h*r,e[1]-d*r]:[e[0],e[1]];s.push(i),Math.hypot(o[0]-i[0],o[1]-i[1])>1e-9&&s.push(o);continue}if(Jr(b,w)){const e=t[n],i=[e[0]-l*a,e[1]-c*a],o=[e[0]-h*r,e[1]-d*r];s.push(i),Math.hypot(o[0]-i[0],o[1]-i[1])>1e-9&&s.push(o);continue}const $=Zr(k,b,x,w),S=Math.max(a,r,1e-9);if($){if(Math.hypot($[0]-t[n][0],$[1]-t[n][1])<=4*S){s.push($);continue}}a>0&&s.push([t[n][0]-l*a,t[n][1]-c*a]),r>0&&s.push([t[n][0]-h*r,t[n][1]-d*r])}return s.length>=3?s:null}function kl(t,e,i,s,n,o,a=1){const r=[];for(const l of t||[]){if(!l?.id)continue;const c=nl(t,l.id,e,i,s,n,o,a);if(!c)continue;const h=Math.abs(Pi(c.poly));for(let t=0;t[Math.max(e,t.x0),Math.min(i,t.x1)]).filter(t=>t[1]-t[0]>s).sort((t,e)=>t[0]-e[0]||t[1]-e[1]);if(!n.length)return{coverage:0,full:!1};let o=n[0][0],a=n[0][1],r=0,l=o<=e+s;for(let t=1;t=i-s,{coverage:r,full:l}}function $l(t,e){return Number(e.full)-Number(t.full)||t.faceDistance-e.faceDistance||t.area-e.area||t.roomId.localeCompare(e.roomId)}function Sl(t,e,i=!1){const s=Number(e?.x),n=Number(e?.y),o=Number(e?.angle),a=Number(e?.length);if(!([s,n,o,a].every(Number.isFinite)&&a>0))return{negative:null,positive:null};const r=o*Math.PI/180,l=Math.cos(r),c=Math.sin(r),h=-c,d=l,u=a/2,p=Math.max(1e-9,t.adjacencyEps),_=new Map;let g=0;for(const e of t.edges){if(i&&!(e.half>0))continue;if(!zr(e.a,e.b,o))continue;const[t,a]=Sr(e.a,e.b);if(Math.abs((s-e.a[0])*a-(n-e.a[1])*t)>p)continue;const r=(e.a[0]-s)*l+(e.a[1]-n)*c,m=(e.b[0]-s)*l+(e.b[1]-n)*c,f=Math.max(-u,Math.min(r,m)),v=Math.min(u,Math.max(r,m));if(v-f<=p)continue;const y=e.inward[0]*h+e.inward[1]*d>=0?1:-1,b=((e.a[0]+e.b[0])/2-s)*h+((e.a[1]+e.b[1])/2-n)*d,w=Math.abs(b+y*e.half),k=`${y}|${e.roomId}`,x={x0:f,x1:v,half:e.half,cm:e.cm,key:e.key,axis:[t,a]},$=_.get(k);$?($.pieces.push(x),$.faceDistance=Math.min($.faceDistance,w)):_.set(k,{roomId:e.roomId,side:y,order:g++,pieces:[x],faceDistance:w,area:e.area,coverage:0,full:!1})}for(const t of _.values()){const e=xl(t.pieces,-u,u,p);t.coverage=e.coverage,t.full=e.full}const m=t=>{const e=[..._.values()].filter(e=>e.side===t&&e.coverage>p);return e.sort($l),e[0]||null};return{negative:m(-1),positive:m(1)}}function Ml(t,e){const i=Sl(t,e),s=[i.negative,i.positive].filter(t=>!!t);if(!s.length)return{ox:0,oy:0,cm:0,side:-1};const n=i.negative&&i.positive?-1:s[0].side,o=e.flip_v?-n:n,a=(-1===o?i.negative:i.positive)||s[0],r=[...a.pieces].sort((t,e)=>(t.x0<=0&&t.x1>=0?0:Math.min(Math.abs(t.x0),Math.abs(t.x1)))-(e.x0<=0&&e.x1>=0?0:Math.min(Math.abs(e.x0),Math.abs(e.x1)))||e.x1-e.x0-(t.x1-t.x0)||t.key.localeCompare(e.key))[0];if(!(r.half>0&&r.cm>0))return{ox:0,oy:0,cm:0,side:o};const l=e.angle*Math.PI/180,c=-Math.sin(l),h=Math.cos(l);return{ox:c*o*r.half,oy:h*o*r.half,cm:r.cm,side:o}}function Cl(t,e){const i=1e-9,s=e.filter(t=>Number.isFinite(t.x0)&&Number.isFinite(t.x1)&&Number.isFinite(t.half)&&t.x1>t.x0&&t.half>0);if(!s.length)return"";const n=s.flatMap(t=>[t.x0,t.x1]).sort((t,e)=>t-e),o=[];for(const t of n){const e=o[o.length-1];(void 0===e||t>e+i)&&o.push(t)}const a=[];for(let t=0;t+1e+i))continue;const r=(e+n)/2,l=s.reduce((t,e)=>r>=e.x0-i&&r<=e.x1+i?Math.max(t,e.half):t,0);if(!(l>0))continue;const c=a[a.length-1];c&&e<=c.x1+i&&Math.abs(l-c.half)<=i?c.x1=n:a.push({x0:e,x1:n,half:l})}const r=[];for(const t of a){const e=r[r.length-1],s=e?.[e.length-1];s&&t.x0<=s.x1+i?(t.x0=s.x1,e.push(t)):r.push([t])}return r.map(e=>{const i=e[0],s=e[e.length-1],n=Math.min(.25*Math.min(...e.map(t=>t.half)),.75),o=-t*n,a=[];if(1===t){a.push(`M ${i.x0} ${o} L ${s.x1} ${o}`);for(let t=e.length-1;t>=0;t--){const i=e[t];a.push(`L ${i.x1} ${i.half} L ${i.x0} ${i.half}`)}}else{a.push(`M ${s.x1} ${o} L ${i.x0} ${o}`);for(const t of e)a.push(`L ${t.x0} ${-t.half} L ${t.x1} ${-t.half}`)}return a.push("Z"),a.join(" ")}).join(" ")}function Dl(t,e,i,s){if(!s)return i;const n=t.angle*Math.PI/180,o=Math.cos(n),a=Math.sin(n),r=[],l=1e-9;for(const n of i){const[i,c]=n.axis,h=o*i+a*c;if(Math.abs(h)<=l)continue;const d=t.x*i+t.y*c,u=d+h*n.x0,p=d+h*n.x1,_=Math.min(u,p),g=Math.max(u,p),m=`${n.key}|${e}`,f=s.get(m)||[];let v=[[_,g]];for(const[t,e]of f){const i=[];for(const[s,n]of v)e<=s+l||t>=n-l?i.push([s,n]):(t>s+l&&i.push([s,Math.min(n,t)]),et[0]-e[0]||t[1]-e[1]),b=[];for(const t of y){const e=b[b.length-1];e&&t[0]<=e[1]+l?e[1]=Math.max(e[1],t[1]):b.push([t[0],t[1]])}s.set(m,b)}return r}function Tl(t,e){const i=new Map;return e.map(e=>function(t,e,i){const s=Sl(t,e,!0),n=s.negative,o=s.positive;if(!n&&!o)return null;let a;if(n&&o)a=[{candidate:n,side:-1},{candidate:o,side:1}];else{const t=n||o;a=[{candidate:t,side:-1},{candidate:t,side:1}]}const r=a.map(({candidate:t,side:s})=>({candidate:t,side:s,pieces:Dl(e,s,t.pieces,i)})),l=r.map(({candidate:t,side:e,pieces:i})=>({side:e,roomId:t.roomId,d:Cl(e,i)})),c=r.flatMap(({pieces:t})=>t);if(!c.length)return null;const h=Math.max(...c.map(t=>t.half));return{faces:l,minY:-h,maxY:h,wallKey:[...new Set(c.map(t=>t.key))].sort().join("|")}}(t,e,i))}const Pl=150,Rl=1e-6;function Il(t){return Number.isFinite(t)?Math.max(1,Math.min(Pl,t)):1}function Al(t){return((Number.isFinite(Number(t))?Number(t):0)%90+90)%90}const Fl=t=>{const e=t.map(t=>[t[0],t[1]]);return!e.length||e[0][0]===e[e.length-1][0]&&e[0][1]===e[e.length-1][1]||e.push([...e[0]]),[e]},El=(t,e)=>t[0]===e[0]&&t[1]===e[1];function zl(t,e=1e-6){const i=Number.isFinite(e)&&e>0?e:Rl,s=[];for(const e of t||[]){if(!Array.isArray(e)||e.length<2)return null;const t=Number(e[0]),n=Number(e[1]);if(!Number.isFinite(t)||!Number.isFinite(n))return null;const o=Math.round(t/i)*i,a=Math.round(n/i)*i;if(!Number.isFinite(o)||!Number.isFinite(a))return null;const r=[Object.is(o,-0)?0:o,Object.is(a,-0)?0:a];s.length&&El(s[s.length-1],r)||s.push(r)}return s.length>1&&El(s[0],s[s.length-1])&&s.pop(),s.length<3||new Set(s.map(t=>`${t[0]},${t[1]}`)).size<3?null:Pi(s)>i*i?s:null}function Ol(t){const e=[];for(const i of t||[])for(const t of i||[]){const i=(t||[]).filter(t=>Array.isArray(t)&&t.length>=2);i.length<4||e.push(`M ${i.slice(0,-1).map(t=>`${t[0]} ${t[1]}`).join(" L ")} Z`)}return e.join(" ")}function Nl(t,e,i,s,n){return Br({a:t,b:e,halfDepth:xr(i,s,n)/2})}function Hl(t,e,i){const s=Number(e)>0?Number(e):5,n=Il(t.cm)/s*i,o=t.center[0],a=t.center[1];if("circle"===t.shape){const t=n/2;return Array.from({length:96},(e,i)=>{const s=i/96*Math.PI*2;return[o+Math.cos(s)*t,a+Math.sin(s)*t]})}const r=n/2,l=Al(t.angle)*Math.PI/180,c=Math.cos(l),h=Math.sin(l);return[[-r,-r],[r,-r],[r,r],[-r,r]].map(([t,e])=>[o+t*c-e*h,a+t*h+e*c])}function Ll(t,e,i=1e-9){if(!e.length)return[t];let s=[Fl(t)];try{for(const t of e){const e=t.b[0]-t.a[0],n=t.b[1]-t.a[1],o=Math.hypot(e,n);if(!(o>i))continue;const a=e/o,r=n/o,l=-r,c=a,h=1.25*Math.max(Number(t.depth)||0,4*i),d=Math.max(2*i,1e-9*o),u=[[t.a[0]-a*d-l*h,t.a[1]-r*d-c*h],[t.b[0]+a*d-l*h,t.b[1]+r*d-c*h],[t.b[0]+a*d+l*h,t.b[1]+r*d+c*h],[t.a[0]-a*d+l*h,t.a[1]-r*d+c*h]];s=oi(s,Fl(u))}return Kl(s)}catch{return[t]}}function Bl(t,e,i,s=Math.max(2e-4*i,1e-9),n=[]){const o=[],a=[],r=new Map;for(const t of n){const e=r.get(t.hostId)||[];e.push(t),r.set(t.hostId,e)}const l=[],c=[],h=[];for(const s of t.room_drafts||[])for(let t=0;t+1Hl(t,e,i)),u=Ur([...o,...a],s).flatMap(t=>Ll(t,n,s));return{drafts:l,partitions:c,columns:d,patches:u,all:[...l,...h,...u,...d]}}function ql(t){try{const e=t.map(t=>zl(t)).filter(t=>!!t).map(t=>Fl(t));return e.length?si(e[0],...e.slice(1)):null}catch{return null}}const Wl=t=>`M ${t.map(t=>`${t[0]} ${t[1]}`).join(" L ")} Z`;function jl(t){const e=[];for(const i of t||[]){if(Vl([i])<=1e-6)continue;const t=[];for(const e of i||[]){const i=(e||[]).filter(t=>Array.isArray(t)&&t.length>=2);i.length<4||t.push(Wl(i.slice(0,-1)))}t.length&&e.push(t.join(" "))}return e}function Ul(t,e,i={}){const s=ql(t.filter(t=>t.length>=3)),n=e.some(t=>!zl(t))?null:ql(e);if(!s)return[];if(n)try{return jl(ni(s,n))}catch{}return function(t,e,i){let s=null;for(let n=0;n=4&&e.push(t.slice(0,-1).map(t=>[t[0],t[1]]))}return e}function Yl(t,e){let i=!1;for(let s=0,n=e.length-1;st[1]!=l>t[1]&&t[0]<(r-o)*(t[1]-a)/(l-a||1e-12)+o&&(i=!i)}return i}function Xl(t,e,i){return function(t,e){for(const i of e||[]){const e=i?.[0];if(!e?.length||!Yl(t,e))continue;let s=!1;for(let e=1;eYl(t,e))}function Jl(t,e,i){if(Math.hypot(t.center[0]-e.center[0],t.center[1]-e.center[1])>i)return!1;if(Math.abs(Il(t.cm)-Il(e.cm))>1e-6)return!1;if(t.shape!==e.shape)return!0;if("circle"===t.shape||"circle"===e.shape)return!0;const s=Math.abs(Al(t.angle)-Al(e.angle));return Math.min(s,90-s)<=1e-6}const Zl=2.54;function Ql(t){const e="number"==typeof t?t:NaN;return!Number.isFinite(e)||e<=0||5===e?1:5/e}function tc(t,e){return t*Ql(e)}function ec(t){return t?Zl:1}function ic(t,e){if(!e)return String(t);const i=t/Zl;return String(Math.round(1e6*i)/1e6)}const sc=1e3;function nc(t,e){const i=Number(t),s=Number.isFinite(i)&&i>0?i:1,n=s>=1?e:e*s,o=s>=1?e/s:e;return{x:(e-n)/2,y:(e-o)/2,w:n,h:o}}const oc=.01,ac=100;function rc(t,e=1e3){const i=nc(t?.plan_aspect,e),s=Number(t?.plan_scale),n=Number.isFinite(s)&&s>0?Math.min(ac,Math.max(oc,s)):1,o=Number(t?.plan_scale_x),a=Number(t?.plan_scale_y),r=Number.isFinite(o)&&o>0?Math.min(ac,Math.max(oc,o)):n,l=Number.isFinite(a)&&a>0?Math.min(ac,Math.max(oc,a)):n,c=Number(t?.plan_x),h=Number(t?.plan_y),d=rr(t?.plan_angle);return{x:i.x+(Number.isFinite(c)?vc(c):0)*e,y:i.y+(Number.isFinite(h)?vc(h):0)*e,w:i.w*r,h:i.h*l,...d?{angle:d}:{}}}function lc(t){if(null==t.x||null==t.y)return{x:t.x,y:t.y,w:t.w,h:t.h};const e=Number(t.w)||0,i=Number(t.h)||0;return{x:e<0?t.x+e:t.x,y:i<0?t.y+i:t.y,w:Math.abs(e),h:Math.abs(i)}}function cc(t){return t&&Array.isArray(t.spaces)?t.spaces.map(t=>{const e=sc,i=function(t){return Array.isArray(t)&&4===t.length&&t.every(t=>Number.isFinite(t))&&t[2]>1e-6&&t[3]>1e-6?t:[0,0,1,1]}(t.view_box);return{id:t.id,title:t.title,cellCm:Number.isFinite(Number(t.cell_cm))&&Number(t.cell_cm)>0?Number(t.cell_cm):5,vb:[i[0]*sc,i[1]*e,i[2]*sc,i[3]*e],bg:t.plan_url?{href:As(t.plan_url),...rc(t,sc)}:null,rooms:(t.rooms||[]).map(t=>{const i={...t,...lc(t)};return{id:i.id,name:i.name,area:i.area??null,open_to:i.open_to||void 0,settings:i.settings||void 0,x:null!=i.x?i.x*sc:void 0,y:null!=i.y?i.y*e:void 0,w:null!=i.w?i.w*sc:void 0,h:null!=i.h?i.h*e:void 0,poly:i.poly?i.poly.map(t=>[t[0]*sc,t[1]*e]):void 0}}),room_drafts:(t.room_drafts||[]).map(t=>({id:t.id,points:(t.points||[]).map(t=>[t[0]*sc,t[1]*e]),segments:(t.segments||[]).map(t=>({cm:Number(t.cm)}))})),partitions:(t.partitions||[]).map(t=>({id:t.id,a:[t.a[0]*sc,t.a[1]*e],b:[t.b[0]*sc,t.b[1]*e],cm:Number(t.cm)})),wall_columns:(t.wall_columns||[]).map(t=>({id:t.id,shape:"circle"===t.shape?"circle":"square",center:[t.center[0]*sc,t.center[1]*e],cm:Number(t.cm),..."circle"===t.shape?{}:{angle:Al(t.angle)}}))}}):[]}const hc=5e3,dc=hc*sc,uc=240,pc=sc/uc,_c=1/uc;function gc(t){if(!Number.isFinite(t))return t;const e=Math.round(t*uc/sc)*sc/uc;return Math.abs(e-t)<=1e-9*pc?t:e}function mc(t){return{x:gc(t.x),y:gc(t.y)}}function fc(t){return Number.isFinite(t)?Math.min(dc,Math.max(-dc,t)):0}function vc(t){return Number.isFinite(t)?Math.min(hc,Math.max(-hc,t)):0}const yc=1/3,bc=200;function wc(t){let e=1/0,i=1/0,s=-1/0,n=-1/0;for(const o of t){const t=Number(o[0]),a=Number(o[1]);Number.isFinite(t)&&Number.isFinite(a)&&(ts&&(s=t),a>n&&(n=a))}return e>s?null:{minX:e,minY:i,maxX:s,maxY:n}}function kc(t){return t.poly&&t.poly.length?wc(t.poly):null==t.x||null==t.y?null:wc([[t.x,t.y],[t.x+(t.w||0),t.y+(t.h||0)]])}function xc(t,e){const i=[];for(const e of t.rooms||[]){const t=kc(e);t&&i.push(t)}if(t.bg){const e=wc(pr(t.bg));e&&i.push(e)}for(const t of e||[])if(Array.isArray(t)){const e=wc([t]);e&&i.push(e)}else i.push(t);return i}const $c=t=>{if(!t.length)return 0;const e=[...t].sort((t,e)=>t-e),i=e.length>>1;return e.length%2?e[i]:(e[i-1]+e[i])/2},Sc=t=>{let e=1/0,i=1/0,s=-1/0,n=-1/0;for(const o of t)o.minXs&&(s=o.maxX),o.maxY>n&&(n=o.maxY);return e>s||i>n?null:{x:e,y:i,w:s-e,h:n-i}};function Mc(t,e){let{x:i,y:s,w:n,h:o}=t;n<30&&(i=i+n/2-100,n=bc),o<30&&(s=s+o/2-100,o=bc);const a=Math.max(n,o)*e;return{x:i-a,y:s-a,w:n+2*a,h:o+2*a}}function Cc(t,e={}){const i=e.pad??.05,s=e.k??10,n=e.minSpread??50,o=t.filter(t=>Number.isFinite(t.minX)&&Number.isFinite(t.minY)&&Number.isFinite(t.maxX)&&Number.isFinite(t.maxY)&&Math.abs(t.minX)<=dc&&Math.abs(t.maxX)<=dc&&Math.abs(t.minY)<=dc&&Math.abs(t.maxY)<=dc);if(!o.length)return{core:null,all:null,outliers:0};const a=Sc(o);if(o.length<4){const t=Mc(a,i);return{core:t,all:t,outliers:0}}const r=o.map(t=>(t.minX+t.maxX)/2),l=o.map(t=>(t.minY+t.maxY)/2),c=$c(r),h=$c(l),d=o.map((t,e)=>Math.max(Math.abs(r[e]-c),Math.abs(l[e]-h))),u=Math.max(((t,e)=>t.length?t[Math.min(t.length-1,Math.max(0,Math.round(e*(t.length-1))))]:0)([...d].sort((t,e)=>t-e),.75),n),p=d.map(t=>t>s*u),_=p.filter(Boolean).length,g=_&&_<=o.length*yc?o.filter((t,e)=>!p[e]):o;return{core:Mc(Sc(g)||a,i),all:Mc(a,i),outliers:g===o?0:_}}function Dc(t,e,i=.05){const s=Cc(xc(t,e),{pad:i});if(s.core)return s.core;const n=t.vb&&4===t.vb.length&&t.vb[2]>0&&t.vb[3]>0?t.vb:[0,0,sc,sc];return{x:n[0],y:n[1],w:n[2],h:n[3]}}function Tc(t){const e=Dc(t);return{x:e.x+e.w/2,y:e.y+e.h/2}}function Pc(t){const e=[];for(const i of t.rooms||[]){const t=kc(i);t&&e.push(t)}const i=Cc(e,{pad:0}).core,s=sc*Ql(t.cellCm??5);return i?Math.max(s,Math.min(dc,Math.max(i.w,i.h))):s}function Rc(t,e,i,s=1){const n=Number(i),o=Number.isFinite(s)&&s>0?s:1;return!Number.isFinite(n)||n<=0?t*o:t*Pc(e)*o/n}const Ic=[1,2,5,10,20,50,100,200,500,1e3];function Ac(t){if(t.poly&&t.poly.length){const e=t.poly.map(t=>t[0]),i=t.poly.map(t=>t[1]),s=Math.min(...e),n=Math.min(...i);return{x:s,y:n,w:Math.max(...e)-s,h:Math.max(...i)-n}}return{x:t.x??0,y:t.y??0,w:t.w??0,h:t.h??0}}function Fc(t,e,i,s){const n=i["rl_"+(t.id||"")];if(n&&n.s===e)return{x:n.x*sc,y:n.y*sc};const o=function(t){if(t.poly){const e=t.poly.length;return[t.poly.reduce((t,e)=>t+e[0],0)/e,t.poly.reduce((t,e)=>t+e[1],0)/e]}return[t.x+t.w/2,t.y+.1*Math.min(t.w,t.h)]}(t);return mc({x:o[0],y:o[1]})}const Ec=["furniture","appliance","sanitary","other"],zc=[{id:"sofa",group:"furniture",w:220,h:90,g:[["r",0,0,1,1],["l",.09,.26,.91,.26],["l",.09,.26,.09,1],["l",.91,.26,.91,1],["l",.5,.26,.5,1]]},{id:"armchair",group:"furniture",w:90,h:85,g:[["r",0,0,1,1],["l",.14,.28,.86,.28],["l",.14,.28,.14,1],["l",.86,.28,.86,1]]},{id:"coffee_table",group:"furniture",w:110,h:60,g:[["r",0,0,1,1],["r",.08,.14,.84,.72]]},{id:"table_dining",group:"furniture",w:140,h:80,g:[["r",0,0,1,1],["r",.06,.11,.88,.78]]},{id:"table_round",group:"furniture",w:120,h:120,g:[["e",.5,.5,.5,.5],["e",.5,.5,.41,.41]]},{id:"chair",group:"furniture",w:45,h:45,g:[["r",0,0,1,.18],["r",.06,.18,.88,.8]]},{id:"desk",group:"furniture",w:120,h:60,g:[["r",0,0,1,1],["r",.63,.07,.31,.86],["l",.63,.5,.94,.5]]},{id:"bed_double",group:"furniture",w:160,h:200,g:[["r",0,0,1,1],["r",0,0,1,.07],["r",.06,.1,.4,.15],["r",.54,.1,.4,.15],["l",0,.33,1,.33]]},{id:"bed_single",group:"furniture",w:90,h:200,g:[["r",0,0,1,1],["r",0,0,1,.07],["r",.15,.1,.7,.15],["l",0,.33,1,.33]]},{id:"nightstand",group:"furniture",w:45,h:40,g:[["r",0,0,1,1],["r",.12,.14,.76,.33],["r",.12,.53,.76,.33]]},{id:"wardrobe",group:"furniture",w:100,h:60,g:[["r",0,0,1,1],["l",0,.72,1,.72],["l",.5,.72,.5,1]]},{id:"bookshelf",group:"furniture",w:80,h:30,g:[["r",0,0,1,1],["l",.34,0,.34,1],["l",.67,0,.67,1]]},{id:"fridge",group:"appliance",w:60,h:65,g:[["r",0,0,1,1],["l",0,.36,1,.36],["l",.83,.44,.83,.64]]},{id:"stove",group:"appliance",w:60,h:60,g:[["r",0,0,1,1],["e",.29,.31,.15,.15],["e",.71,.31,.15,.15],["e",.29,.71,.15,.15],["e",.71,.71,.15,.15]]},{id:"dishwasher",group:"appliance",w:60,h:60,g:[["r",0,0,1,1],["r",.1,.12,.8,.76],["e",.5,.5,.27,.27],["e",.5,.5,.13,.13]]},{id:"washer",group:"appliance",w:60,h:60,g:[["r",0,0,1,1],["l",.08,.17,.92,.17],["e",.5,.57,.3,.3],["e",.5,.57,.14,.14]]},{id:"dryer",group:"appliance",w:60,h:60,g:[["r",0,0,1,1],["l",.08,.17,.92,.17],["e",.5,.57,.3,.3],["p",.36,.5,.5,.64,.64,.5]]},{id:"tv",group:"appliance",w:120,h:30,g:[["r",0,0,1,.42],["l",.5,.42,.5,.72],["l",.3,.72,.7,.72]]},{id:"ac",group:"appliance",w:90,h:25,g:[["r",0,0,1,1],["l",.05,.55,.95,.55],["l",.05,.79,.95,.79]]},{id:"water_heater",group:"appliance",w:45,h:45,g:[["e",.5,.5,.5,.5],["e",.5,.5,.31,.31]]},{id:"toilet",group:"sanitary",w:40,h:70,g:[["r",.06,0,.88,.2],["e",.5,.58,.37,.35],["e",.5,.58,.22,.2]]},{id:"bathtub",group:"sanitary",w:170,h:75,g:[["r",0,0,1,1],["r",.05,.11,.77,.78],["e",.89,.5,.045,.1]]},{id:"shower",group:"sanitary",w:90,h:90,g:[["r",0,0,1,1],["l",0,0,1,1],["l",1,0,0,1],["e",.5,.5,.08,.08]]},{id:"sink",group:"sanitary",w:60,h:45,g:[["r",0,0,1,1],["e",.5,.6,.34,.3],["e",.5,.15,.07,.07]]},{id:"kitchen_sink",group:"sanitary",w:80,h:60,g:[["r",0,0,1,1],["r",.06,.24,.44,.64],["r",.54,.24,.4,.64],["e",.5,.12,.06,.06]]},{id:"bidet",group:"sanitary",w:40,h:55,g:[["e",.5,.5,.44,.5],["e",.5,.5,.26,.3]]},{id:"stairs",group:"other",w:100,h:280,g:[["r",0,0,1,1],["l",0,.111,1,.111],["l",0,.222,1,.222],["l",0,.333,1,.333],["l",0,.444,1,.444],["l",0,.556,1,.556],["l",0,.667,1,.667],["l",0,.778,1,.778],["l",0,.889,1,.889],["l",.5,.93,.5,.06],["p",.38,.16,.5,.06,.62,.16]]},{id:"fireplace",group:"other",w:120,h:40,g:[["r",0,0,1,1],["p",.22,1,.22,.42,.78,.42,.78,1]]},{id:"plant",group:"other",w:40,h:40,g:[["e",.5,.5,.22,.22],["l",.5,.28,.5,.02],["l",.5,.72,.5,.98],["l",.28,.5,.02,.5],["l",.72,.5,.98,.5],["l",.34,.34,.13,.13],["l",.66,.66,.87,.87],["l",.66,.34,.87,.13],["l",.34,.66,.13,.87]]},{id:"rug",group:"other",w:200,h:140,g:[["r",0,0,1,1],["r",.06,.09,.88,.82]]}],Oc=new Map(zc.map(t=>[t.id,t]));function Nc(t){return t&&Oc.get(t)||null}function Hc(t){return zc.filter(e=>e.group===t)}function Lc(t,e,i=pc,s=1e3){const n=Number(e)>0?Number(e):5;return(Number(t)||0)/n*i/s}const Bc=5e-4,qc=hc;function Wc(t){return Number.isFinite(t)?Math.max(Bc,Math.min(qc,t)):Bc}const jc=t=>{const e=Math.round(1e3*t)/1e3;return Object.is(e,-0)?"0":String(e)};function Uc(t,e,i){const s=Nc(t);if(!(s&&e>0&&i>0))return"";const n=t=>jc(t*e),o=t=>jc(t*i),a=[];for(const t of s.g)if("r"===t[0]){const[,e,i,s,r]=t;a.push(`M${n(e)} ${o(i)}H${n(e+s)}V${o(i+r)}H${n(e)}Z`)}else if("l"===t[0]){const[,e,i,s,r]=t;a.push(`M${n(e)} ${o(i)}L${n(s)} ${o(r)}`)}else if("e"===t[0]){const[,s,r,l,c]=t;a.push(`M${n(s-l)} ${o(r)}A${jc(l*e)} ${jc(c*i)} 0 0 1 ${n(s+l)} ${o(r)}A${jc(l*e)} ${jc(c*i)} 0 0 1 ${n(s-l)} ${o(r)}Z`)}else{const e=t.slice(1);if(e.length<4)continue;let i=`M${n(e[0])} ${o(e[1])}`;for(let t=2;t+1{let e=(t%360+360)%360;return e>180&&(e-=360),e};function Vc(t,e,i,s,n,o=0){let a=null,r=n;for(const n of s){const[s,l,c,h]=n,d=c-s,u=h-l,p=d*d+u*u;if(!p)continue;const _=Math.sqrt(p);let g=((t-s)*d+(e-l)*u)/p;g=Math.max(0,Math.min(1,g));let m=s+g*d,f=l+g*u;const v=Math.hypot(t-m,e-f);if(!(v0){const t=Math.round(g*_/o)*o;m=s+t/_*d,f=l+t/_*u}a={cx:m+y*(i/2),cy:f+b*(i/2),angle:Gc(180*Math.atan2(-y,b)/Math.PI),dist:v}}return a}function Kc(t,e,i){const s=i>0?i:1;return{a:[t[0]/s,t[1]/s],b:[e[0]/s,e[1]/s]}}function Yc(t,e){const i=e>0?e:1;return[t.a[0]*i,t.a[1]*i,t.b[0]*i,t.b[1]*i]}function Xc(t){return Array.isArray(t)&&t.length>=2&&Number.isFinite(Number(t[0]))&&Number.isFinite(Number(t[1]))}function Jc(t){if(!Array.isArray(t))return[];const e=[];for(const i of t){if(!i||"object"!=typeof i)continue;const t=i;if(!Xc(t.a)||!Xc(t.b))continue;const s=[Number(t.a[0]),Number(t.a[1])],n=[Number(t.b[0]),Number(t.b[1])];Math.hypot(n[0]-s[0],n[1]-s[1])<.001||e.push({a:s,b:n})}return e}function Zc(t,e){const i=e[0],s=e[1],n=e[2]-i,o=e[3]-s,a=n*n+o*o;if(a<1e-18){return{q:[i,s],t:0,d:Math.hypot(t[0]-i,t[1]-s)}}let r=((t[0]-i)*n+(t[1]-s)*o)/a;r=Math.max(0,Math.min(1,r));const l=[i+r*n,s+r*o];return{q:l,t:r,d:Math.hypot(t[0]-l[0],t[1]-l[1])}}function Qc(t,e){return Zc(t,e).q}function th(t,e,i,s,n){const o=Zc(t,e).q;let a=o,r=1/0;for(const t of i){const e=Math.hypot(o[0]-t[0],o[1]-t[1]);e<=n&&e0?s:1,g=Math.round(p/_)*_,m=Math.max(0,Math.min(u,g))/u;return[l+h*m,c+d*m]}function eh(t,e){const i=[],s=(t||[]).filter(t=>t?.id);for(let t=0;tt?.id),a=Jc(e);if(a.length)return hh(a,t,i,s).map(t=>Yc(t,i));if(!n)return[];const r=[],l=(t,e)=>(t.open_to||[]).includes(e.id)||(e.open_to||[]).includes(t.id);for(let t=0;tKc([t[0],t[1]],[t[2],t[3]],e))}function nh(t,e,i,s){for(const e of t||[])e.open_to&&delete e.open_to;if(!i.length)return;const n=(e||[]).filter(t=>t?.id);new Map(n.map(t=>[t.id,t]));const o=new Map((t||[]).filter(t=>t?.id).map(t=>[t.id,t])),a=(t,e)=>{const i=o.get(t),s=o.get(e);i&&s&&((i.open_to||[]).includes(e)||(i.open_to=[...i.open_to||[],e]),(s.open_to||[]).includes(t)||(s.open_to=[...s.open_to||[],t]))};for(let t=0;tHs(i,t)<4*s)){a(n[t].id,n[e].id);break}}}for(const e of t||[])e.open_to&&!e.open_to.length&&delete e.open_to}function oh(t,e,i,s=0){const n=e[2]-e[0],o=e[3]-e[1],a=Math.hypot(n,o);if(!(a>1e-9))return null;const r=n/a,l=o/a,c=(t[0]-e[0])*r+(t[1]-e[1])*l;if(c<-s||c>a+s)return null;return Math.abs((t[0]-e[0])*l-(t[1]-e[1])*r)>i?null:Hs(t,e)}function ah(t,e,i){const s=t[2]-t[0],n=t[3]-t[1],o=e[2]-e[0],a=e[3]-e[1],r=Math.hypot(s,n),l=Math.hypot(o,a);return r>1e-9&&l>1e-9&&(!(Math.abs(s/r*(a/l)-n/r*(o/l))>1e-6)&&(Hs([e[0],e[1]],t)<=4*i||Hs([t[0],t[1]],e)<=4*i))}function rh(t,e,i){if(!t.length)return null;t.sort((t,e)=>t.distance-e.distance);const s=t[0];for(let n=1;ne)break;if(o.semantic!==s.semantic||!ah(s.seg,o.seg,i))return"ambiguous"}return s}function lh(t,e,i,s,n=1,o=15){const a=function(t,e,i,s,n=1,o=15){const[a,r]=Sr([e[0],e[1]],[e[2],e[3]]);let l=0,c=1/0;const h=[(e[0]+e[2])/2,(e[1]+e[3])/2];for(const e of i){const[i,o]=Sr([e[0],e[1]],[e[2],e[3]]);if(Math.abs(a*o-r*i)>.05)continue;const d=Fr(t,[e[0],e[1]],[e[2],e[3]],s,n);if(!(d>0))continue;const u=[(e[0]+e[2])/2,(e[1]+e[3])/2],p=Math.hypot(u[0]-h[0],u[1]-h[1]);p0?l:o}(t,e,i,s,n,o);return Nr(t,[e[0],e[1]],[e[2],e[3]],a,s,n)}function ch(t,e,i){const s=[[t[0],t[1]],[t[2],t[3]]],n=[(t[0]+t[2])/2,(t[1]+t[3])/2];for(const o of e)if(!(Hs(n,o)>Math.hypot(t[2]-t[0],t[3]-t[1])&&Hs([o[0],o[1]],t)>i))for(const e of[[o[0],o[1]],[o[2],o[3]]])Hs(e,t)<=2*i&&s.push(e);return s}function hh(t,e,i,s){const n=Jc(t);if(!n.length)return[];const o=eh(e,s);if(!o.length)return[];const a=[],r=Math.max(4*s,1e-6);for(const t of n){const e=Yc(t,i),n=e[0],l=e[1],c=e[2]-n,h=e[3]-l,d=Math.hypot(c,h);if(d4*s||o>4*s)continue;const a=(t[0]-n)*u+(t[1]-l)*p,c=(t[2]-n)*u+(t[3]-l)*p,h=Math.max(0,Math.min(a,c)),g=Math.min(d,Math.max(a,c));if(g-ht.lo-e.lo||t.hi-e.hi);const i=[];for(const t of e){const e=i[i.length-1];e&&t.lo<=e.hi+r?e.hi=Math.max(e.hi,t.hi):i.push({...t})}for(const e of i){const i=[n+u*e.lo,l+p*e.lo],s=[n+u*e.hi,l+p*e.hi];Math.hypot(s[0]-i[0],s[1]-i[1])i.pair===t&&Math.abs(i.ux*a-i.uy*o)<=1e-6&&Math.abs((e[0]-i.origin[0])*i.uy-(e[1]-i.origin[1])*i.ux)<=c&&Math.abs((e[2]-i.origin[0])*i.uy-(e[3]-i.origin[1])*i.ux)<=c);h||(h={pair:t,origin:[e[0],e[1]],ux:o,uy:a,ranges:[]},l.push(h));const d=(e[0]-h.origin[0])*h.ux+(e[1]-h.origin[1])*h.uy,u=(e[2]-h.origin[0])*h.ux+(e[3]-h.origin[1])*h.uy;h.ranges.push({lo:Math.min(d,u),hi:Math.max(d,u)})}const h=[];for(const t of l){t.ranges.sort((t,e)=>t.lo-e.lo||t.hi-e.hi);const e=[];for(const i of t.ranges){const t=e[e.length-1];t&&i.lo<=t.hi+r?t.hi=Math.max(t.hi,i.hi):e.push({...i})}for(const s of e){const e=[t.origin[0]+t.ux*s.lo,t.origin[1]+t.uy*s.lo],n=[t.origin[0]+t.ux*s.hi,t.origin[1]+t.uy*s.hi];Math.hypot(n[0]-e[0],n[1]-e[1])>=r&&h.push(Kc(e,n,i))}}return h}function dh(t,e,i,s){const n=Jc(t);if(!n.length)return[];if(e.length!==i.length)return n;const o=[];for(const t of n){const n=Yc(t,s),a=[n[0],n[1]],r=[n[2],n[3]];let l=a,c=r;for(let t=0;t{const e=Zc(t,[s[0],s[1],n[0],n[1]]);if(e.d>.001)return t;const i=h[0]-o[0],a=h[1]-o[1];return[o[0]+i*e.t,o[1]+a*e.t]};if(Zc([(a[0]+r[0])/2,(a[1]+r[1])/2],[s[0],s[1],n[0],n[1]]).d<.01){l=d(a),c=d(r);break}}o.push(Kc(l,c,s))}return o}const uh=15e3,ph=2e3,_h=new WeakMap;function gh(t,e){let i=_h.get(t);if(!i){const e=new Set;i={hiddenAt:"hidden"===t.visibilityState?Date.now():0,token:0,subscribers:e,onVisibility:()=>{const e=_h.get(t);if(!e)return;const i=Date.now();if("hidden"===t.visibilityState){e.hiddenAt||(e.hiddenAt=i);const t={kind:"hidden",token:e.token,at:i,hiddenFor:0,long:!1};for(const i of[...e.subscribers])i(t);return}const s=e.hiddenAt?Math.max(0,i-e.hiddenAt):0;e.hiddenAt=0,e.token++;const n={kind:"visible",token:e.token,at:i,hiddenFor:s,long:s>=uh};for(const t of[...e.subscribers])t(n)},onPageShow:e=>{const i=_h.get(t);if(!i)return;const s=Date.now();i.token++;const n={kind:"pageshow",token:i.token,at:s,hiddenFor:0,long:!!e.persisted,persisted:!!e.persisted};for(const t of[...i.subscribers])t(n)}},_h.set(t,i),t.addEventListener("visibilitychange",i.onVisibility),t.defaultView?.addEventListener("pageshow",i.onPageShow)}return i.subscribers.add(e),()=>{const i=_h.get(t);i&&(i.subscribers.delete(e),i.subscribers.size||(t.removeEventListener("visibilitychange",i.onVisibility),t.defaultView?.removeEventListener("pageshow",i.onPageShow),_h.delete(t)))}}const mh={now:()=>Date.now(),setTimeout:(t,e)=>window.setTimeout(t,e),clearTimeout:t=>window.clearTimeout(t),requestAnimationFrame:t=>window.requestAnimationFrame(t),cancelAnimationFrame:t=>window.cancelAnimationFrame(t)};class fh{constructor(t,e=mh){this.onChange=t,this.clock=e,this._state="steady",this._token=0,this._frameFingerprint="",this._hasCompleteFrame=!1,this._overlayPhase="none",this._recoveryReason=null,this._overlayTimer=0,this._overlayRaf=0,this._overlayOpaqueAt=0,this._barrierRafs=new Set,this._trace=[],this._disposed=!1}get state(){return this._state}get token(){return this._token}get frameFingerprint(){return this._frameFingerprint}get hasCompleteFrame(){return this._hasCompleteFrame}get overlayPhase(){return this._overlayPhase}get overlayVisible(){return"none"!==this._overlayPhase}get overlayBlocksInteraction(){return this.overlayVisible}get recoveryReason(){return this._recoveryReason}get trace(){return this._trace.map(t=>({...t,...t.stage?{stage:[...t.stage]}:{}}))}note(t,e={}){this.record(t,void 0,e)}record(t,e,i={}){this._trace.push({at:this.clock.now(),token:this._token,event:t,state:this._state,...e?{reason:e}:{},...i}),this._trace.length>80&&this._trace.splice(0,this._trace.length-80)}changed(){this._disposed||this.onChange()}adoptCompleteFrame(t){t&&(this._hasCompleteFrame=!0,this._frameFingerprint=t,this._state="steady",this._recoveryReason=null,this.clearOverlay(),this.record("frame-adopted"),this.changed())}markCompleteFrame(t){t&&(this._hasCompleteFrame=!0,this._frameFingerprint=t,this._state="steady",this._recoveryReason=null,this.clearOverlay(),this.record("frame-complete"),this.changed())}refreshCompleteFrame(t){!this._disposed&&this._hasCompleteFrame&&"steady"===this._state&&t&&t!==this._frameFingerprint&&(this._frameFingerprint=t,this.record("frame-refreshed"))}visibility(t){return"hidden"===t.kind?(this.record("visibility-hidden"),this._token):t.long||"visible"!==t.kind&&"pageshow"!==t.kind?this.beginCandidate("pageshow"===t.kind?"pageshow":"long-resume"):(this.record("pageshow"===t.kind?"pageshow-noop":"visibility-visible-quick"),this._token)}beginCandidate(t,e="plan"){return this._token++,this._recoveryReason=e,this._hasCompleteFrame?(this._state="connection"===e?"offline-stale":"holding",this.clearOverlay()):this.overlayVisible?this._state="overlay-visible":(this._state="overlay-pending",this.scheduleOverlay(e)),this.record("candidate-start",t),this.changed(),this._token}connectionLost(){return this.beginCandidate("connection-lost","connection")}candidateReady(t){return!this._disposed&&t===this._token&&(this._state="candidate-ready",this.record("candidate-ready"),this.changed(),!0)}async commitAfterPaint(t,e){if(this._disposed||t!==this._token)return!1;let i=!0;const s=(async()=>{for(await e.updateComplete();i&&!this._disposed&&t===this._token;)if(e.stageValid()&&e.assetsReady()){if(await this.nextFrame(),t!==this._token||!e.stageValid()||!e.assetsReady())continue;if(await this.nextFrame(),t===this._token&&e.stageValid()&&e.assetsReady())return!0}else await this.nextFrame();return!1})();let n=0;const o=new Promise(t=>{n=this.clock.setTimeout(()=>t({ready:!1,timedOut:!0}),ph)}),a=await Promise.race([s.then(t=>({ready:t,timedOut:!1})),o]);return i=!1,this.clock.clearTimeout(n),!this._disposed&&t===this._token&&(!(!a.ready&&!a.timedOut)&&(a.ready?(this._hasCompleteFrame=!0,this._frameFingerprint=e.frameFingerprint(),this.record("paint-barrier"),this.finishOverlayAfterCommit(),!0):(this.record("paint-barrier-timeout"),this._hasCompleteFrame?(this._state="connection"===this._recoveryReason?"offline-stale":"steady",this.clearOverlay()):(this._state="recovery-error","opaque"!==this._overlayPhase&&this.showOverlayNow()),this.changed(),!1)))}retry(t=this._recoveryReason||"plan"){return this.beginCandidate("retry",t)}nextFrame(){return new Promise(t=>{const e=this.clock.requestAnimationFrame(()=>{this._barrierRafs.delete(e),t()});this._barrierRafs.add(e)})}scheduleOverlay(t){this.clearOverlayTimer(),this._recoveryReason=t,this._overlayTimer=this.clock.setTimeout(()=>{this._overlayTimer=0,this._hasCompleteFrame||"overlay-pending"!==this._state&&"candidate-ready"!==this._state||(this._state="overlay-visible",this._overlayPhase="entering",this.record("overlay-enter"),this.changed(),this._overlayRaf=this.clock.requestAnimationFrame(()=>{this._overlayRaf=0,"entering"===this._overlayPhase&&(this._overlayPhase="fading-in",this.changed(),this._overlayTimer=this.clock.setTimeout(()=>{this._overlayTimer=0,"fading-in"===this._overlayPhase&&(this._overlayPhase="opaque",this._overlayOpaqueAt=this.clock.now(),this.record("overlay-opaque"),this.changed())},150))}))},150)}showOverlayNow(){this.clearOverlayTimer(),this._overlayPhase="opaque",this._overlayOpaqueAt=this.clock.now(),this.record("overlay-error")}finishOverlayAfterCommit(){if(this.clearOverlayTimer(),"none"===this._overlayPhase||"entering"===this._overlayPhase||"fading-in"===this._overlayPhase)return this.clearOverlay(),this._state="steady",this._recoveryReason=null,this.record("candidate-committed"),void this.changed();const t=Math.max(0,this._overlayOpaqueAt+250-this.clock.now());this._overlayTimer=this.clock.setTimeout(()=>{this._overlayTimer=0,this._overlayPhase="leaving",this.record("overlay-leave"),this.changed(),this._overlayTimer=this.clock.setTimeout(()=>{this._overlayTimer=0,this._overlayPhase="none",this._state="steady",this._recoveryReason=null,this.record("candidate-committed"),this.changed()},180)},t)}clearOverlayTimer(){this._overlayTimer&&this.clock.clearTimeout(this._overlayTimer),this._overlayTimer=0}clearOverlay(){this.clearOverlayTimer(),this._overlayRaf&&this.clock.cancelAnimationFrame(this._overlayRaf),this._overlayRaf=0,this._overlayPhase="none",this._overlayOpaqueAt=0}dispose(){this._disposed=!0,this._token++,this.clearOverlay();for(const t of this._barrierRafs)this.clock.cancelAnimationFrame(t);this._barrierRafs.clear()}}function vh(t){let e=2166136261,i=2654435769;const s=new WeakSet,n=t=>{for(let s=0;s>>0)+(i>>>2)}},o=t=>{if(null===t)return void n("n");const e=typeof t;if("string"===e)return void n(`s${t.length}:${t}`);if("number"===e)return void n(`d${Number.isNaN(t)?"NaN":String(t)}`);if("boolean"===e)return void n(t?"t":"f");if("undefined"===e)return void n("u");if("object"!==e)return void n(`${e}:${String(t)}`);const i=t;if(s.has(i))n("[cycle]");else{if(s.add(i),Array.isArray(t)){n("[");for(const e of t)o(e);return n("]"),void s.delete(i)}n("{");for(const e of Object.keys(t).sort())n(e),o(t[e]);n("}"),s.delete(i)}};return o(t),`${(e>>>0).toString(16).padStart(8,"0")}${(i>>>0).toString(16).padStart(8,"0")}`}function yh(t){return vh(t)}const bh=new WeakMap;class wh{constructor(t,e=()=>Date.now()){this.onUpdate=t,this.now=e,this.fallbackAuthority={},this.referenceOwner={},this.referenced=new Set,this.queued=new Set,this.disposed=!1,this.sharedUpdate=()=>{this.disposed||this.onUpdate()}}bind(t){const e=((t,e)=>{const i=t?.connection||t?.callWS||e;return!i||"object"!=typeof i&&"function"!=typeof i?e:i})(t,this.fallbackAuthority);return this.shared&&this.authority===e||(this.shared&&(this.shared.listeners.delete(this.sharedUpdate),this.shared.references.delete(this.referenceOwner)),this.authority=e,this.shared=(t=>{let e=bh.get(t);return e||(e={signed:{},queued:new Set,inFlight:new Map,retry:new Map,listeners:new Set,settlers:new Set,references:new Map},bh.set(t,e)),e})(e),this.disposed||(this.shared.listeners.add(this.sharedUpdate),this.shared.references.set(this.referenceOwner,new Set(this.referenced)))),this.shared}start(t,e){this.disposed=!1,this.referenced=new Set(e());const i=this.bind(t());i.listeners.add(this.sharedUpdate),i.references.set(this.referenceOwner,new Set(this.referenced)),this.stopTimer(),this.resignTimer=setInterval(()=>this.resign(t(),e()),288e5)}dispose(){if(this.disposed=!0,this.stopTimer(),clearTimeout(this.batchTimer),this.shared){this.shared.listeners.delete(this.sharedUpdate),this.shared.references.delete(this.referenceOwner);for(const t of this.queued)this.shared.queued.delete(t)}this.queued.clear()}invalidate(t){const e=this.bind(t);clearTimeout(this.batchTimer),this.queued.clear(),e.queued.clear(),e.inFlight.clear(),e.retry.clear(),e.signed={}}stopTimer(){void 0!==this.resignTimer&&clearInterval(this.resignTimer),this.resignTimer=void 0}display(t,e){const i=As(e);if(!i.startsWith("/api/houseplan/content/"))return i;const s=this.bind(t);this.referenced.add(i),s.references.set(this.referenceOwner,new Set(this.referenced));const n=s.signed[i],o=n?this.now()-n.at:1/0;return o{const e=[...this.queued];this.queued.clear();for(const t of e)i.queued.delete(t);this.sign(t,e)},30))}sign(t,e){if(!e.length||!t?.callWS)return;const i=this.bind(t);for(const s of function(t,e){const i=Math.max(1,Math.floor(e)),s=[];for(let e=0;e{const s=i.inFlight.get(t);return!(void 0!==s&&e-s<15e3)&&(i.inFlight.set(t,e),!0)});n.length&&t.callWS({type:"houseplan/content/sign",paths:n}).then(t=>{const e=this.now();let s=0,o=!1;for(const a of n){const n=t?.urls?.[a];if("string"==typeof n&&n){const t=i.signed[a];t?.loaded&&t.url!==n?(t.pending={url:n,at:e},this.preloadReplacement(i,a,n,e)):(i.signed[a]={url:n,at:e,loaded:t?.url===n&&!!t.loaded},o=!0),i.retry.delete(a),s++}else this.backOff(i,a)}if(s&&(this.trimShared(i),o))for(const t of[...i.listeners])t()}).catch(()=>{for(const t of n)this.backOff(i,t)}).finally(()=>{for(const t of n)i.inFlight.get(t)===e&&i.inFlight.delete(t);for(const t of[...i.settlers])t()})}}preloadReplacement(t,e,i,s){const n=()=>{const n=t.signed[e];if(n?.pending?.url===i){t.signed[e]={url:i,at:s,loaded:!0},t.retry.delete(e),this.trimShared(t);for(const e of[...t.listeners])e()}},o=()=>{const s=t.signed[e];s?.pending?.url===i&&(delete s.pending,this.backOff(t,e))};if("undefined"==typeof Image)return void n();const a=new Image;a.onload=()=>{("function"==typeof a.decode?a.decode():Promise.resolve()).then(n).catch(o)},a.onerror=o,a.src=i}preloadCurrentImage(t,e,i){if(i.loaded)return Promise.resolve(!0);if(i.preload)return i.preload;if("undefined"==typeof Image)return i.loaded=!0,Promise.resolve(!0);const s=i.url;return i.preload=new Promise(n=>{const o=new Image;let a=!1;const r=o=>{if(a)return;a=!0,clearTimeout(l);const r=t.signed[e];if(r===i&&delete r.preload,o&&r===i&&r.url===s){r.loaded=!0;for(const e of[...t.listeners])e();n(!0)}else o||r!==i||this.backOff(t,e),n(!1)};o.onload=()=>{("function"==typeof o.decode?o.decode():Promise.resolve()).then(()=>r(!0)).catch(()=>r(!1))},o.onerror=()=>r(!1);const l=setTimeout(()=>r(!1),ph);o.src=s}),i.preload}prepareImage(t,e){const i=As(e);if(!i.startsWith("/api/houseplan/content/"))return Promise.resolve(!0);const s=this.bind(t),n=()=>{const e=s.signed[i];if(e&&this.now()-e.atthis.now()&&!s.inFlight.has(i)&&!s.queued.has(i)?Promise.resolve(!1):null},o=n();return o?(a=o,new Promise(t=>{let e=!1;const i=i=>{e||(e=!0,clearTimeout(s),t(i))},s=setTimeout(()=>i(!1),ph);a.then(i).catch(()=>i(!1))})):new Promise(t=>{let e=!1,i=null;const o=i=>{e||(e=!0,clearTimeout(r),s.settlers.delete(a),t(i))},a=()=>{e||i||(i=n(),i&&i.then(o).catch(()=>o(!1)))},r=setTimeout(()=>o(!1),ph);s.settlers.add(a),a()});var a}backOff(t,e){const i=t.retry.get(e)?.delay||0,s=Math.min(6e4,i?2*i:2e3);t.retry.set(e,{notBefore:this.now()+s,delay:s})}trimShared(t){const e=Object.entries(t.signed);if(e.length<=512)return;const i=new Set(t.inFlight.keys());for(const e of t.references.values())for(const t of e)i.add(t);for(const[t,s]of e)(s.pending||s.preload)&&i.add(t);e.sort((t,e)=>e[1].at-t[1].at);const s=e.filter(([t])=>i.has(t));for(const t of e){if(s.length>=512)break;i.has(t[0])||s.push(t)}t.signed=Object.fromEntries(s)}resign(t,e){const i=this.bind(t);this.referenced=new Set(e),i.references.set(this.referenceOwner,new Set(this.referenced));const s=this.now(),n=new Set;for(const t of i.references.values())for(const e of t)n.add(e);const o={};for(const[t,e]of Object.entries(i.signed))n.has(t)&&s-e.at!!o[t]&&!o[t].pending))}markLoaded(t,e,i){const s=As(e);if(!s.startsWith("/api/houseplan/content/"))return;const n=this.bind(t).signed[s];if(n&&(!i||n.url===i)&&!n.loaded){n.loaded=!0;for(const e of[...this.bind(t).listeners])e()}}isReady(t,e){const i=As(e);if(!i.startsWith("/api/houseplan/content/"))return!0;const s=this.bind(t).signed[i];return!!s&&this.now()-s.att.id===e)}function xh(t="file"){const e="draw"===t;return{source:t,showBorders:e,showNames:e,displayTouched:!1}}function $h(t,e){if(t.displayTouched)return{...t,source:e};const i="draw"===e;return{...t,source:e,showBorders:i,showNames:i}}function Sh(t,e,i){return{...t,[e]:i,displayTouched:!0}}function Mh(t,e,i){return[t[0]*e+t[1]*i+t[2],t[3]*e+t[4]*i+t[5]]}function Ch(t,e){let i=0;for(const[s,n]of e){const e=Mh(t,s[0],s[1]);i=Math.max(i,Math.hypot(e[0]-n[0],e[1]-n[1]))}return i}const Dh=t=>{if(null==t||""===t)return null;const e=Number(t);return Number.isFinite(e)?e:null},Th=t=>{const e=t,i=Dh(Array.isArray(e)?e[0]:e?.x),s=Dh(Array.isArray(e)?e[1]:e?.y);return null==i||null==s?null:[i,s]};function Ph(t){if(!Array.isArray(t))return null;const e=[];for(const i of t){const t=Th(i);if(!t)return null;e.push(t)}if(e.length>1){const t=e[0],i=e[e.length-1];t[0]===i[0]&&t[1]===i[1]&&e.pop()}if(e.length<3)return null;let i=0,s=0,n=0;for(let t=0;tt+e[0],0)/e.length,e.reduce((t,e)=>t+e[1],0)/e.length]:[s/(3*i),n/(3*i)]}function Rh(t){if(!Array.isArray(t))return null;const e=[];for(const i of t){const t=Th(i);if(!t)return null;e.push(t)}if(e.length>1){const t=e[0],i=e[e.length-1];t[0]===i[0]&&t[1]===i[1]&&e.pop()}const i=Ph(e);if(!i)return null;const s=e.map(t=>t[0]),n=e.map(t=>t[1]);return{centroid:i,bbox:[Math.min(...s),Math.min(...n),Math.max(...s),Math.max(...n)]}}function Ih(t){let e=t;if(e&&"object"==typeof e&&!Array.isArray(e)){const t=e;e=t.path??t.points??e}if(!Array.isArray(e)||!e.length)return[];let i=(e.some(t=>(t=>Array.isArray(t)?t.length>=2&&!Array.isArray(t[0])&&("object"!=typeof t[0]||null==t[0]):!!t&&"object"==typeof t&&("x"in t||"y"in t))(t))?[e]:e.filter(Array.isArray)).map(t=>t.map(Th).filter(t=>null!=t)).filter(t=>t.length>=2);i.length>64&&(i=i.slice(-64));if(i.reduce((t,e)=>t+e.length,0)<=4e3)return i.map(t=>t.slice());const s=4e3-2*i.length,n=i.map(t=>t.length-2),o=n.reduce((t,e)=>t+e,0),a=n.map(t=>s*t/o),r=a.map(Math.floor);let l=s-r.reduce((t,e)=>t+e,0);const c=a.map((t,e)=>({index:e,fraction:t-Math.floor(t)})).sort((t,e)=>e.fraction-t.fraction||t.index-e.index);for(let t=0;tfunction(t,e){if(e>=t.length)return t.slice();if(e<=2)return[t[0],t[t.length-1]];const i=[];for(let s=0;st.slice()),i=e[e.length-1];return i?(i.length>2?i.pop():e.pop(),e):[]}function Eh(t){if(!t)return null;const e=t.vacuum_position||t.robot_position||null,i=e&&null!=Dh(e.x)&&null!=Dh(e.y)?{x:Dh(e.x),y:Dh(e.y),a:Dh(e.a??e.angle??e.theta)}:null,s=Ih(t.path?.path??t.path?.points??t.path),n=[],o=t.rooms,a=Array.isArray(o)?o.map((t,e)=>[String(t?.id??e),t]):o&&"object"==typeof o?Object.entries(o):[];for(const[t,e]of a){if(!e||"object"!=typeof e)continue;const i=String(e.name??e.label??"").trim(),s=[[Dh(e.cx),Dh(e.cy)],[Dh(e.center?.x),Dh(e.center?.y)],[Dh(e.x),Dh(e.y)]].find(([t,e])=>null!=t&&null!=e);let o=s?.[0]??null,a=s?.[1]??null;const r=Rh(e.outline),l=Dh(e.x0),c=Dh(e.y0),h=Dh(e.x1),d=Dh(e.y1),u=(null!=l&&null!=c&&null!=h&&null!=d?[Math.min(l,h),Math.min(c,d),Math.max(l,h),Math.max(c,d)]:null)||r?.bbox||null;if(null!=o&&null!=a||!r||([o,a]=r.centroid),null!=o&&null!=a||!u||(o=(u[0]+u[2])/2,a=(u[1]+u[3])/2),i&&null!=o&&null!=a){const e={id:t,name:i,cx:o,cy:a};u&&([e.x0,e.y0,e.x1,e.y1]=u),n.push(e)}}const r=function(t){return String(t.map_name??t.current_map??t.map_index??t.selected_map??"default")}(t);return i||n.length||s.length?{pos:i,path:s,rooms:n,mapId:r}:null}function zh(t,e,i){if(!t||!e)return null;const s=e.attributes||{},n=t.split(".")[0]||"",o=null!=i?.platform?String(i.platform):null,a=!!Th(s.vacuum_position??s.robot_position),r=!(!s.rooms||"object"!=typeof s.rooms),l=Ih(s.path?.path??s.path?.points??s.path).length>0,c=[s.map_name,s.current_map,s.map_index,s.selected_map].some(t=>null!=t),h="xiaomi_cloud_map_extractor"===o,d=r||l||c;let u=null;if(a?u="compatible":h?u="known_xcme_incomplete":d?u="partial":"camera"===n&&(u="camera"),!u)return null;const p=a?"camera"===n?300:200:h?100:d?50:0;return{entityId:t,name:String(s.friendly_name||t),platform:o,category:u,hasPosition:a,hasRooms:r,hasPath:l,hasMapId:c,score:p}}const Oh=t=>t.toLowerCase().replace(/[\s_\-.,]+/g,"");function Nh(t,e){const i=new Map(e.map(t=>[Oh(t.name),t])),s=[],n=[];for(const e of t){const t=i.get(Oh(e.name));t&&(s.push([[e.cx,e.cy],[t.cx,t.cy]]),n.push(e.name))}if(s.length<3)return null;const o=function(t){if(t.length<3)return null;let e=0,i=0,s=0,n=0,o=0,a=0,r=0,l=0,c=0,h=0,d=0,u=0;for(const[[p,_],[g,m]]of t){if(![p,_,g,m].every(Number.isFinite))return null;e+=p*p,i+=p*_,s+=p,n+=_*_,o+=_,a+=1,r+=p*g,l+=_*g,c+=g,h+=p*m,d+=_*m,u+=m}const p=[e,i,s,i,n,o,s,o,a],_=t=>{const[e,i,s,n,o,a,r,l,c]=p,h=e*(o*c-a*l)-i*(n*c-a*r)+s*(n*l-o*r);if(!Number.isFinite(h)||Math.abs(h)<1e-9)return null;const d=[(o*c-a*l)/h,(s*l-i*c)/h,(i*a-s*o)/h,(a*r-n*c)/h,(e*c-s*r)/h,(s*n-e*a)/h,(n*l-o*r)/h,(i*r-e*l)/h,(e*o-i*n)/h];return[d[0]*t[0]+d[1]*t[1]+d[2]*t[2],d[3]*t[0]+d[4]*t[1]+d[5]*t[2],d[6]*t[0]+d[7]*t[1]+d[8]*t[2]]},g=_([r,l,c]),m=_([h,d,u]);if(!g||!m)return null;const f=[g[0],g[1],g[2],m[0],m[1],m[2]];return f.every(Number.isFinite)?f:null}(s);return o?{matrix:o,matched:n,residual:Ch(o,s)}:null}function Hh(t,e,i){const s=t[t.length-1];if(s&&s[0]===e[0]&&s[1]===e[1])return t;if(t.push(e),t.length<=600)return t;let n=function(t,e){if(t.length<3)return t.slice();const i=new Uint8Array(t.length);i[0]=i[t.length-1]=1;const s=[[0,t.length-1]];for(;s.length;){const[n,o]=s.pop(),[a,r]=t[n],[l,c]=t[o],h=l-a,d=c-r,u=Math.hypot(h,d)||1e-9;let p=0,_=-1;for(let e=n+1;ep&&(p=i,_=e)}_>0&&p>e&&(i[_]=1,s.push([n,_],[_,o]))}const n=[];for(let e=0;e600&&(n=n.filter((t,e)=>e%2==0||e===n.length-1)),n}function Lh(t){return"cleaning"===t||"returning"===t||"on"===t}const Bh={0:[1,0],90:[0,1],180:[-1,0],270:[0,-1]};function qh(t){const[e,i]=Bh[t.rot]||[1,0],s=t.mir?-1:1;return[t.s*e*s,-t.s*i,t.ox,t.s*i*s,t.s*e,t.oy]}function Wh(t){const e=t[0]*t[4]-t[1]*t[3];if(!Number.isFinite(e)||Math.abs(e)<1e-12)return null;const i=e<0,s=Math.sqrt(Math.abs(e));let n=180*Math.atan2(-t[1],t[4])/Math.PI;return n=(90*Math.round(n/90)%360+360)%360,{ox:t[2],oy:t[5],s:s,rot:n,mir:i}}function jh(t,e,i,s){const[n,o]=Mh(qh(e),i,s),a=qh({...t,ox:0,oy:0}),[r,l]=Mh(a,i,s);return{...t,ox:n-r,oy:o-l}}function Uh(t){const e=t?.trail_mode;return"never"===e||"cleaning"===e||"always"===e?e:!1===t?.trail?"never":"cleaning"}const Gh={offStates:["off"],unknownUsesToggle:!0},Vh={light:Gh,switch:Gh,fan:Gh,humidifier:Gh,input_boolean:Gh,automation:Gh,remote:Gh,group:Gh,climate:{...Gh,featureMasks:{turn_on:256,turn_off:128,toggle:384}},media_player:{...Gh,featureMasks:{turn_on:128,turn_off:256,toggle:384}},siren:{...Gh,featureMasks:{turn_on:1,turn_off:2,toggle:3}},vacuum:{...Gh,featureMasks:{turn_on:1,turn_off:2,toggle:3}},water_heater:{...Gh,featureMasks:{turn_on:8,turn_off:8,toggle:8}},camera:{...Gh,featureMasks:{turn_on:1,turn_off:1,toggle:1}}};function Kh(t){return t.slice(0,t.indexOf("."))}function Yh(t,e,i){if(!t?.services||"object"!=typeof t.services)return!1;const s=t.services?.[e];return!!s&&Object.prototype.hasOwnProperty.call(s,i)}function Xh(t,e,i){return Yh(t,e,i)?{domain:e,service:i}:Yh(t,"homeassistant",i)?{domain:"homeassistant",service:i}:null}function Jh(t,e){return t?.entities?.[e]||null}function Zh(t,e,i){const s=t?.states?.[i],n=Jh(e,i);return s?.attributes?.friendly_name||n?.name||n?.original_name||i}function Qh(t,e){const i=Jh(t,e);if(null!=i?.disabled_by)return!0;const s=i?.device_id?t?.devices?.[i.device_id]:null;return null!=s?.disabled_by}function td(t,e){const i=t?.attributes?.supported_features;if(null==i||""===i)return!1;const s=Number(i);return Number.isFinite(s)&&(s&e)===e}function ed(t,e,i){const s=Kh(i);if("lock"===s||"alarm_control_panel"===s)return!0;if("cover"!==s)return!1;const n=t?.states?.[i],o=Jh(e,i),a=String(n?.attributes?.device_class||o?.device_class||o?.original_device_class||"");return Ui.has(a)}function id(t,e,i,s,n){return{ref:i,entityId:s,name:s?Zh(t,e,s):null,reason:n}}function sd(t,e,i,s,n,o=null){return{target:null,skipped:id(t,e,i,s,n),semantics:o,nextEffect:null,command:null}}function nd(t,e,i,s,n=i){const o=Kh(i);if("cover"!==o&&"valve"!==o)return function(t,e,i,s,n=i){const o=Kh(i),a=t?.states?.[i];if(Qh(e,i))return sd(t,e,n,i,"ha-disabled","power");if(ed(t,e,i))return sd(t,e,n,i,"secure");if(!a)return sd(t,e,n,i,"missing","power");if("unavailable"===a.state)return sd(t,e,n,i,"unavailable","power");const r=Vh[o];if(!r)return sd(t,e,n,i,"unsupported");let l,c;if("unknown"===a.state||""===a.state){if(!r.unknownUsesToggle)return sd(t,e,n,i,"unsupported","power");l="toggle",c="toggle"}else r.offStates.includes(String(a.state))?(l="turn-on",c="turn_on"):(l="turn-off",c="turn_off");const h=r.featureMasks?.[c];if(h&&!td(a,h))return sd(t,e,n,i,"unsupported","power");const d=Xh(t,o,c);return d?{target:{entityId:i,name:Zh(t,e,i),state:String(a.state||""),via:s},skipped:null,semantics:"power",nextEffect:l,command:{...d,data:{entity_id:i}}}:sd(t,e,n,i,"unsupported","power")}(t,e,i,s,n);if(Qh(e,i))return sd(t,e,n,i,"ha-disabled",o);if(ed(t,e,i))return sd(t,e,n,i,"secure",o);const a=t?.states?.[i];if(!a)return sd(t,e,n,i,"missing",o);if("unavailable"===a.state)return sd(t,e,n,i,"unavailable",o);const r=function(t,e,i){const s=String(i?.state||""),n="closed"===s?{service:`open_${e}`,effect:"open",feature:1}:"open"===s?{service:`close_${e}`,effect:"close",feature:2}:"opening"===s||"closing"===s?{service:`stop_${e}`,effect:"stop",feature:8}:null;return n&&td(i,n.feature)&&Yh(t,e,n.service)?n:td(i,3)&&Yh(t,e,"toggle")?{service:"toggle",effect:"toggle"}:null}(t,o,a);if(!r)return sd(t,e,n,i,"unsupported",o);return{target:{entityId:i,name:Zh(t,e,i),state:String(a.state||""),via:s},skipped:null,semantics:o,nextEffect:r.effect,command:{domain:o,service:r.service,data:{entity_id:i}}}}function od(t){return"entity"===t.bindingKind?t.bindingRef&&Ms(t.bindingRef)?[t.bindingRef]:[]:"virtual"===t.bindingKind?[]:to(t)}function ad(t){const e=t.marker?.toggle_entity;return e&&od(t).includes(e)?e:null}function rd(t,e,i){const s=function(t,e){if("entity"===t.bindingKind&&t.bindingRef){const e=t.marker?.light_entity?eo(t):null;return[...new Set([e,t.bindingRef].filter(t=>!!t))]}const i=t.entities.length?t.entities:t.allEntities||[],s=t.marker?.light_entity||t.primary&&Ms(t.primary)?eo(t):null;return[...new Set([s,...Yn(e,i)].filter(t=>!!t))]}(i,e);if(!s.length)return null;const n="entity"===i.bindingKind?"binding":"device-role";if("binding"===n)return nd(t,e,s[0],n);let o=null,a=null;for(const i of s){const s=nd(t,e,i,n);if(s.command)return s;const r=s.skipped?.reason;if("missing"===r||"unavailable"===r||"secure"===r)return s;"ha-disabled"!==r?o||=s:a||=s}return o||a}function ld(t){const e=t.skipped?.reason;return"missing"===e?"unavailable":e||"unsupported"}function cd(t,e){return{origin:t,kind:"none",semantics:null,targets:[],skippedTargets:[],noneReason:e,nextEffect:null,command:null}}function hd(t,e){return"cover"===t||"toggle"===t?"toggle":"more-info"===t||"run"===t||"info"===t?t:(null==t||""===t)&&"light"===e?"toggle":"info"}function dd(t,e){return{origin:t,kind:"single",semantics:e.semantics,targets:e.target?[e.target]:[],skippedTargets:e.skipped?[e.skipped]:[],noneReason:e.command?null:ld(e),nextEffect:e.nextEffect,command:e.command}}function ud(t,e,i,s=[]){const n=new Map,o=[],a=new Set,r=t=>{const e=`${t.ref}\n${t.entityId||""}\n${t.reason}`;a.has(e)||(a.add(e),o.push(t))};for(const t of s)r(t);for(const s of i){const i=nd(t,e,s.entityId,s.via,s.ref);i.target?n.set(s.entityId,n.get(s.entityId)||i.target):i.skipped&&r(i.skipped)}const l=[...n.values()];if(!l.length)return{origin:"explicit-toggle",kind:"group",semantics:"group-power",targets:l,skippedTargets:o,noneReason:o.length&&o.every(t=>"secure"===t.reason)?"secure":"configured-targets-missing",nextEffect:null,command:null};const c=l.some(t=>"on"===t.state)?"turn_off":"turn_on",h=Xh(t,"homeassistant",c);return h?{origin:"explicit-toggle",kind:"group",semantics:"group-power",targets:l,skippedTargets:o,noneReason:null,nextEffect:"turn_on"===c?"turn-on":"turn-off",command:{...h,data:{entity_id:l.map(t=>t.entityId)}}}:{origin:"explicit-toggle",kind:"group",semantics:"group-power",targets:[],skippedTargets:[...o,...l.map(i=>id(t,e,i.entityId,i.entityId,"unsupported"))],noneReason:"unsupported",nextEffect:null,command:null}}function pd(t){return String(t.marker?.id||t.id||"")}function _d(t){const{hass:e,device:i}=t,s=t.registryHass||e,n=function(t){return"toggle"===t.tapAction?"explicit-toggle":"cover"===t.tapAction?"legacy-cover":!t.tapAction&&t.primary?.startsWith("light.")?"default-light":null}(i);if(!n)return null;const o=i.marker;if("explicit-toggle"===n&&yn(o)){const e=String(o?.id||i.id||""),s=ro(t.devices).get(e);if(s)return function(t,e){const i=t.registryHass||t.hass;return ud(t.hass,i,e.driverEids.map(t=>({entityId:t,via:"control-marker-driver",ref:`marker:${e.markerId}`})))}(t,s);const a=bn(o,t.virtualLights);return{origin:n,kind:"single",semantics:"power",targets:[{entityId:"",name:i.name,state:a?"on":"off",via:"virtual-light"}],skippedTargets:[],noneReason:null,nextEffect:a?"turn-off":"turn-on",command:null,operation:{kind:"virtual-light",markerId:o.id}}}if("explicit-toggle"===n){if(Zn(i.marker?.binding,i.marker?.controls??i.controls,i.entities).length)return function(t,e=null){const{hass:i,device:s,devices:n}=t,o=t.registryHass||i,a=Zn(s.marker?.binding,s.marker?.controls??s.controls,s.entities),r=t.lightSources||ho(i,n,null,t.virtualLights),l=new Map;for(const t of r){if(!t.key.startsWith("marker:"))continue;const e=l.get(t.key)||[];e.push(t),l.set(t.key,e)}const c=ro(n),h=new Map;for(const t of n){const e=String(t.marker?.id||t.id||"");e&&h.set(e,t)}const d=[],u=[];e&&d.push({entityId:e,via:"entity"===s.bindingKind?"binding":"device-role",ref:e});for(const t of a){if(!t.startsWith("marker:")){Ms(t)?d.push({entityId:t,via:"control-entity",ref:t}):u.push(id(i,o,t,t.includes(".")?t:null,"unsupported"));continue}const e=l.get(t)||[];if(!e.length){const e=h.get(t.slice(7));if("ha_disabled"===e?.bindingStatus?.kind){const s=e.bindingStatus.allEntityIds[0]||null;u.push({ref:t,entityId:s,name:e.name||(s?Zh(i,o,s):null),reason:"ha-disabled"})}else u.push(id(i,o,t,null,"missing"));continue}const n=[...new Set(e.flatMap(t=>t.serviceEids))];if(n.length){for(const e of n)d.push({entityId:e,via:"control-entity",ref:t});continue}const a=e.some(t=>t.passive),r=t.slice(7),p=pd(s),_=c.get(r)?.controllers.find(t=>pd(t.device)===p);if(a&&_?.driverEids.length)for(const e of _.driverEids)d.push({entityId:e,via:"control-marker-driver",ref:t});else u.push(id(i,o,t,null,a?"missing":"unsupported"))}return ud(i,o,d,u)}(t,ad(i))}if("legacy-cover"===n){const t=i.entities.find(t=>t.startsWith("cover."))||i.allEntities?.find(t=>t.startsWith("cover."));return t?dd(n,nd(e,s,t,"device-role")):cd(n,"no-actionable-entity")}const a=ad(i),r=a?nd(e,s,a,"entity"===i.bindingKind?"binding":"device-role"):rd(e,s,i);return r?dd(n,r):cd(n,i.virtual||"virtual"===i.bindingKind?"no-actionable-entity":"no-binding")}function gd(t){if(!t)return[];const e=Array.isArray(t.data.entity_id)?t.data.entity_id:[t.data.entity_id];return[...new Set(e)].sort()}function md(t){return t?t.operation?t.operation:t.command?{kind:"ha-service",command:t.command}:null:null}function fd(t,e){const i=md(t),s=md(e);return!(!i||!s||i.kind!==s.kind)&&("virtual-light"===i.kind&&"virtual-light"===s.kind?i.markerId===s.markerId:"ha-service"===i.kind&&"ha-service"===s.kind&&function(t,e){const i=gd(t),s=gd(e);return i.length===s.length&&i.every((t,e)=>t===s[e])}(i.command,s.command))}const vd=t=>!!t&&t.length>=2&&Number.isFinite(t[0])&&Number.isFinite(t[1]);function yd(t,e=5,i=5){return xr(t.cm,e,i)/2}function bd(t,e,i=1,s=5,n=5,o=0){const a=t.host;if(!a||"partition"!==a.kind||"string"!=typeof a.id||!a.id)return{resolved:null,reason:"invalid-host"};const r=e.find(t=>t.id===a.id);if(!r)return{resolved:null,reason:"missing-partition"};if(!vd(r.a)||!vd(r.b)||!Number.isFinite(a.t)||a.t<0||a.t>1)return{resolved:null,reason:"invalid-position"};const l=r.b[0]-r.a[0],c=r.b[1]-r.a[1],h=Math.hypot(l,c),d=Number(t.length)*i;if(!(h>1e-9&&d>0&&Number.isFinite(d)))return{resolved:null,reason:"invalid-length"};const u=a.t*h;if(u-d/2h-o+1e-9)return{resolved:null,reason:"does-not-fit"};const p=l/h,_=c/h;let g=180*Math.atan2(c,l)/Math.PI;return g>=90?g-=180:g<-90&&(g+=180),{reason:null,resolved:{opening:t,host:a,partition:r,center:[r.a[0]+l*a.t,r.a[1]+c*a.t],angle:g,length:d,depth:xr(r.cm,s,n),t:a.t,axis:{a:[r.a[0],r.a[1]],b:[r.b[0],r.b[1]],ux:p,uy:_,length:h}}}}function wd(t,e,i=1,s=5,n=5){return bd(t,e,i,s,n,0)}function kd(t,e,i=1,s=5,n=5){const o=t.host,a="partition"===o?.kind?e.find(t=>t.id===o.id):void 0;if(!a)return wd(t,e,i,s,n);const r=bd(t,e,i,s,n,yd(a,s,n));return"does-not-fit"===r.reason?{resolved:null,reason:"does-not-fit-jamb"}:r}function xd(t,e){return!t||(t.length!==e.length||t.host?.kind!==e.host?.kind||t.host?.id!==e.host?.id||t.host?.t!==e.host?.t)}function $d(t){const{center:e,length:i,axis:s,host:n}=t,o=i/2;return{hostId:n.id,a:[e[0]-s.ux*o,e[1]-s.uy*o],b:[e[0]+s.ux*o,e[1]+s.uy*o],depth:t.depth}}function Sd(t,e=!1){const i=e?1:-1,s=t.depth/2;return{ox:-t.axis.uy*i*s,oy:t.axis.ux*i*s,cm:t.partition.cm,side:i}}function Md(t,e,i){const{center:s,length:n,axis:o}=t,a=n/2,r=e.flatMap(t=>{if(!t.kind||t.open)return[];const e=t.b[0]-t.a[0],n=t.b[1]-t.a[1],r=Math.hypot(e,n);if(!(r>i))return[];const l=e/r,c=n/r;if(Math.abs(o.ux*c-o.uy*l)>1e-6)return[];if(Math.abs((s[0]-t.a[0])*c-(s[1]-t.a[1])*l)>i)return[];const h=t=>(t[0]-s[0])*o.ux+(t[1]-s[1])*o.uy,d=h(t.a),u=h(t.b),p=Math.max(-a,Math.min(d,u)),_=Math.min(a,Math.max(d,u));return _>=p-i?[[p,_]]:[]});if(!r.length)return!1;r.sort((t,e)=>t[0]-e[0]||t[1]-e[1]);let l=-a;for(const[t,e]of r){if(t>l+i)return!1;if(l=Math.max(l,e),l>=a-i)return!0}return!1}function Cd(t,e,i){return{...t,x:e.center[0]/i,y:e.center[1]/i,angle:e.angle}}const Dd=.001;function Td(t){return!!t&&t.length>=2&&Number.isFinite(t[0])&&Number.isFinite(t[1])}function Pd(t){return`${t[0].toFixed(6)},${t[1].toFixed(6)}`}function Rd(t,e,i){return Math.abs(t[0]-e[0])Ed(s,t,e)))continue;const t=Pd(s);a.has(t)||a.set(t,{point:[s[0],s[1]],key:t})}}}return{segments:[...o.values()].sort((t,e)=>t.key.localeCompare(e.key)),endpoints:[...a.values()].sort((t,e)=>t.key.localeCompare(e.key))}}function Od(t,e,i){return e.some(e=>Td(e)&&Rd(t,e,i))}function Nd(t,e,i){if(!i)return!0;const s=t-i.distance;return s<-1e-9||Math.abs(s)<=1e-9&&e.localeCompare(i.key)<0}function Hd(t,e,i){const s=i.epsilon??Dd,n=i.excludePoints||[],o=[...t.endpoints,...(i.extraEndpoints||[]).filter(t=>Td(t.point)).map(t=>({point:[t.point[0],t.point[1]],key:t.key}))],a=new Map;for(const t of o){if(Od(t.point,n,s))continue;const e=Pd(t.point),i=a.get(e);(!i||t.key.localeCompare(i.key)<0)&&a.set(e,t)}return[...a.values()].map(t=>({kind:"endpoint",point:[...t.point],key:t.key,distance:Math.hypot(e[0]-t.point[0],e[1]-t.point[1])})).filter(t=>t.distance<=i.tolerance).sort((t,e)=>t.distance-e.distance||t.key.localeCompare(e.key))}function Ld(t,e){if(!t.length)return null;if(e>0){const i=new Set;for(let s=0;s1)return{kind:"ambiguous",candidate:null,conflicts:t.filter(t=>i.has(t.key)).map(t=>({point:[...t.point],key:t.key}))}}return{kind:"resolved",candidate:t[0],conflicts:[]}}function Bd(t,e,i){const s=t.b[0]-t.a[0],n=t.b[1]-t.a[1],o=Math.hypot(s,n);if(!(o>0))return[...t.a];const a=s/o,r=n/o,l=Math.max(0,Math.min(o,(e[0]-t.a[0])*a+(e[1]-t.a[1])*r)),c=i>0?Math.max(0,Math.min(o,Math.round(l/i)*i)):l;return[t.a[0]+a*c,t.a[1]+r*c]}function qd(t,e,i){if(!(Td(e)&&Td(i.anchor)&&i.tolerance>=0))return{kind:"none",candidate:null,conflicts:[]};const s=i.epsilon??Dd,n=function(t,e){const i=e[0]-t[0],s=e[1]-t[1];if(!(Math.hypot(i,s)>Number.EPSILON))return null;const n=Math.round(Math.atan2(s,i)/(Math.PI/4))*(Math.PI/4);return[Math.cos(n),Math.sin(n)]}(i.anchor,e);if(!n)return{kind:"none",candidate:null,conflicts:[]};const o=Hd(t,e,i).filter(t=>function(t,e,i,s){const n=t[0]-e[0],o=t[1]-e[1];return n*i[0]+o*i[1]>s&&Math.abs(n*i[1]-o*i[0])<=s*Math.max(Math.hypot(n,o),1)}(t.point,i.anchor,n,s)),a=Ld(o,i.distinguishTolerance||0);if(a)return a;let r=null;for(const o of t.segments){const t=o.b[0]-o.a[0],a=o.b[1]-o.a[1],l=o.a[0]-i.anchor[0],c=o.a[1]-i.anchor[1],h=n[0]*a-n[1]*t;let d=null;if(Math.abs(h)<=s*Math.max(Math.hypot(t,a),1)){if(Math.abs(l*n[1]-c*n[0])>s*Math.max(Math.hypot(l,c),1))continue;const t=[o.a,o.b].map(t=>({point:t,along:(t[0]-i.anchor[0])*n[0]+(t[1]-i.anchor[1])*n[1]})).filter(t=>t.along>s).sort((t,e)=>t.along-e.along);t.length&&(d=[...t[0].point])}else{const e=(l*a-c*t)/h,o=(l*n[1]-c*n[0])/h;e>s&&o>=-s&&o<=1+s&&(d=[i.anchor[0]+n[0]*e,i.anchor[1]+n[1]*e])}if(!d)continue;const u=Math.hypot(e[0]-d[0],e[1]-d[1]);u>i.tolerance||Od(d,i.excludePoints||[],s)||!Nd(u,o.key,r)||(r={kind:"line",point:d,key:o.key,distance:u,segment:o})}return r?{kind:"resolved",candidate:r,conflicts:[]}:{kind:"none",candidate:null,conflicts:[]}}const Wd=.001;function jd(t,e,i,s){const n=Number.isFinite(t)&&t>0?Math.floor(t):0,o=t=>"number"==typeof t&&Number.isFinite(t)&&t>0?t:null,a=o(i),r=o(s)??1,l=[];let c=null;for(let t=0;t=2&&Number.isFinite(t[0])&&Number.isFinite(t[1])}function Vd(t,e,i,s){return t*s-e*i}function Kd(t){let e=0;for(let i=0;it.localeCompare(e)),e[0]}function Qd(t,e,i){const s=[...t];for(let t=!0;t&&s.length>=3;){t=!1;for(let n=0;n=0){s.splice(n,1),t=!0;break}}}return s}function tu(t,e){const i=t.map(t=>Math.max(0,Math.min(1,t))).sort((t,e)=>t-e),s=[];for(const t of i)(!s.length||Math.abs(t-s[s.length-1])>e)&&s.push(t);return s}function eu(t,e){return[t.a[0]+(t.b[0]-t.a[0])*e,t.a[1]+(t.b[1]-t.a[1])*e]}function iu(t,e,i){const s=function(t,e){const i=e.b[0]-e.a[0],s=e.b[1]-e.a[1],n=i*i+s*s;return n>0?((t[0]-e.a[0])*i+(t[1]-e.a[1])*s)/n:0}(t,e);if(s<-i||s>1+i)return null;const n=eu(e,s);return Math.hypot(n[0]-t[0],n[1]-t[1])<=i?Math.max(0,Math.min(1,s)):null}function su(t,e,i,s,n){const o=t.b[0]-t.a[0],a=t.b[1]-t.a[1],r=e.b[0]-e.a[0],l=e.b[1]-e.a[1],c=e.a[0]-t.a[0],h=e.a[1]-t.a[1],d=Vd(o,a,r,l),u=Math.max(Math.hypot(o,a),Math.hypot(r,l),1);if(Math.abs(d)>n*u){const t=Vd(c,h,r,l)/d,e=Vd(c,h,o,a)/d;return void(t>=-n&&t<=1+n&&e>=-n&&e<=1+n&&(i.push(Math.max(0,Math.min(1,t))),s.push(Math.max(0,Math.min(1,e)))))}if(!(Math.abs(Vd(c,h,o,a))>n*u)){for(const s of[e.a,e.b]){const e=iu(s,t,n);null!=e&&i.push(e)}for(const i of[t.a,t.b]){const t=iu(i,e,n);null!=t&&s.push(t)}}}function nu(t){let e=t+1|0;return e^=e<<13,e^=e>>>17,e^=e<<5,e>>>0}function ou(t,e){return t.minY-e.minY||t.index-e.index}function au(t){return t.subtreeMaxY=Math.max(t.item.maxY,t.left?.subtreeMaxY??-1/0,t.right?.subtreeMaxY??-1/0),t}function ru(t){const e=t.right;return t.right=e.left,e.left=au(t),au(e)}function lu(t){const e=t.left;return t.left=e.right,e.right=au(t),au(e)}function cu(t,e){return t?(ou(e,t.item)<0?(t.left=cu(t.left,e),t.left.priority0)t.right=hu(t.right,e);else{if(!t.left)return t.right;if(!t.right)return t.left;t.left.priority=e&&du(t.left,e,i,s),t.item.minY<=i&&t.item.maxY>=e&&s.push(t.item),t.item.minY<=i&&du(t.right,e,i,s))}function uu(t,e=.001){const i=Number.isFinite(e)&&e>0?e:Wd,s=t.filter(t=>Gd(t.a)&&Gd(t.b)&&"string"==typeof t.key&&t.key.length>0&&Math.hypot(t.b[0]-t.a[0],t.b[1]-t.a[1])>i),n=s.map(()=>[0,1]);!function(t,e,i){const s=t.map((t,e)=>({index:e,minX:Math.min(t.a[0],t.b[0])-i,maxX:Math.max(t.a[0],t.b[0])+i,minY:Math.min(t.a[1],t.b[1])-i,maxY:Math.max(t.a[1],t.b[1])+i})),n=[...s].sort((t,e)=>t.minX-e.minX||t.minY-e.minY||t.index-e.index),o=[...s].sort((t,e)=>t.maxX-e.maxX||t.index-e.index),a=new Set;let r=null,l=0;for(const s of n){for(;lt.index-e.index);for(const o of n)su(t[o.index],t[s.index],e[o.index],e[s.index],i);a.add(s.index),r=cu(r,s)}}(s,n,i);const o=new Map;for(let t=0;t({key:t,a:e.a,b:e.b,sourceKeys:[...e.sourceKeys].sort((t,e)=>t.localeCompare(e))})).sort((t,e)=>t.key.localeCompare(e.key))}function pu(t,e=.001){const i=Number.isFinite(e)&&e>0?e:Wd,s=uu(t,i),n=new Map,o=new Map,a=new Map(s.map(t=>[t.key,t]));for(const t of s){const e=Xd(t.a,i),s=Xd(t.b,i);n.set(e,t.a),n.set(s,t.b),o.has(e)||o.set(e,new Set),o.has(s)||o.set(s,new Set),o.get(e).add(s),o.get(s).add(e)}const r=new Map;for(const[t,e]of o){const i=n.get(t);r.set(t,[...e].sort((t,e)=>{const s=n.get(t),o=n.get(e);return Math.atan2(s[1]-i[1],s[0]-i[0])-Math.atan2(o[1]-i[1],o[0]-i[0])||t.localeCompare(e)}))}const l=new Set,c=new Map,h=(t,e)=>`${t}>${e}`;for(const t of s){const e=[Xd(t.a,i),Xd(t.b,i)];for(const[t,o]of[e,[e[1],e[0]]]){if(l.has(h(t,o)))continue;const e=[],d=[];let u=t,p=o,_=!1;for(let i=0;i<=2*s.length+2;i++){const i=h(u,p);if(l.has(i)){_=u===t&&p===o;break}l.add(i),e.push(u),d.push(Jd(u,p));const s=r.get(p)||[],n=s.indexOf(u);if(n<0||!s.length)break;if(u=p,p=s[(n-1+s.length)%s.length],u===t&&p===o){_=!0;break}}if(!_||new Set(e).size<3||new Set(e).size!==e.length)continue;const g=e.map(t=>n.get(t)),m=Kd(g);if(!(m>i*i))continue;const f=Zd(Qd(e,n,i)),v=new Set;for(const t of d)for(const e of a.get(t)?.sourceKeys||[])v.add(e);const y={ring:g,key:f,area:m,atomKeys:[...d],sourceKeys:[...v].sort((t,e)=>t.localeCompare(e))};c.has(f)||c.set(f,y)}}return{atoms:s,faces:[...c.values()].sort((t,e)=>t.area-e.area||t.key.localeCompare(e.key))}}function _u(t,e,i=.001){if(!Gd(e))return null;const s=t.faces.filter(t=>{if(t.ring.some((s,n)=>function(t,e,i,s){const n=i[0]-e[0],o=i[1]-e[1],a=n*n+o*o;if(!(a>0))return Math.hypot(t[0]-e[0],t[1]-e[1])<=s;const r=((t[0]-e[0])*n+(t[1]-e[1])*o)/a;return!(r<0||r>1)&&Math.hypot(e[0]+n*r-t[0],e[1]+o*r-t[1])<=s}(e,s,t.ring[(n+1)%t.ring.length],i)))return!1;let s=!1;for(let i=0,n=t.ring.length-1;ie[1]!=a[1]>e[1]&&e[0]<(a[0]-o[0])*(e[1]-o[1])/(a[1]-o[1])+o[0]&&(s=!s)}return s});return[...s].sort((t,e)=>t.area-e.area||t.key.localeCompare(e.key))[0]||null}function gu(t,e,i){const s=i[0]-e[0],n=i[1]-e[1],o=s*s+n*n,a=o>0?Math.max(0,Math.min(1,((t[0]-e[0])*s+(t[1]-e[1])*n)/o)):0;return Math.hypot(e[0]+s*a-t[0],e[1]+n*a-t[1])}function mu(t,e,i=.5){let s=Math.abs(t-e)%180;return s>90&&(s=180-s),s<=i}function fu(t,e,i,s){const n=t.filter(t=>"outer"===t.kind&&!t.open&&t.cm>0).map(t=>({interval:t,reusePartitionId:e.find(e=>function(t,e,i){return!(Math.abs(t.cm-e.cm)>1e-6)&&(mu(180*Math.atan2(t.b[1]-t.a[1],t.b[0]-t.a[0])/Math.PI,180*Math.atan2(e.b[1]-e.a[1],e.b[0]-e.a[0])/Math.PI,.001)&&gu(e.a,t.a,t.b)<=i&&gu(e.b,t.a,t.b)<=i)}(e,t,s))?.id||null})),o=new Map;for(const e of i){if("partition"===e.host?.kind)continue;const i=t.map(t=>{const i=180*Math.atan2(t.b[1]-t.a[1],t.b[0]-t.a[0])/Math.PI;return{interval:t,distance:mu(e.angle,i)?gu([e.x,e.y],t.a,t.b):1/0}}).filter(t=>t.distance<=s).sort((t,e)=>t.distance-e.distance||t.interval.key.localeCompare(e.interval.key)),n=i[0]?.interval;"outer"===n?.kind&&!n.open&&n.cm>0&&o.set(e.id,n.key)}return{materialize:n,openingIntervals:o,removeOpeningIds:[...o.keys()].sort((t,e)=>t.localeCompare(e))}}function vu(t,e){const i=e.b[0]-e.a[0],s=e.b[1]-e.a[1],n=i*i+s*s;return n>0?Math.max(0,Math.min(1,((t[0]-e.a[0])*i+(t[1]-e.a[1])*s)/n)):0}const yu=t=>!t.key.startsWith("static:room|");function bu(t,e){const i=e.b[0]-e.a[0],s=e.b[1]-e.a[1],n=i*i+s*s;if(!(n>0))return null;const o=((t[0]-e.a[0])*i+(t[1]-e.a[1])*s)/n,a=[e.a[0]+i*o,e.a[1]+s*o];return{point:a,t:o,distance:Math.hypot(a[0]-t[0],a[1]-t[1])}}function wu(t,e){return e>0?Math.hypot(t[0]-Math.round(t[0]/e)*e,t[1]-Math.round(t[1]/e)*e):0}function ku(t,e,i){if(yu(t.source)!==yu(e.source))return yu(t.source)?t:e;const s=wu(t.point,i),n=wu(e.point,i);return Math.abs(s-n)>1e-9?s>n?t:e:function(t,e){return t[0]-e[0]||t[1]-e[1]}(t.point,e.point)>0?t:e}function xu(t){return[t.from[0],t.from[1],t.to[0],t.to[1],t.targetKind].map(t=>"number"==typeof t?t.toFixed(6):t).join("|")}function $u(t,e){return t.map(t=>t.key!==e.sourceKey?t:{...t,[e.endpoint]:[...e.to]})}function Su(t,e){const i=e.epsilon??.001;if(!(e.maxDistance>=0)||!e.point&&!e.requiredSourceKey)return{kind:"none"};const s=new Map,n=t.flatMap(t=>[{source:t,endpoint:"a",point:t.a},{source:t,endpoint:"b",point:t.b}]);for(let t=0;ti)||l>e.maxDistance)continue;const c=ku(a,r,e.gridStep||0),h=c===a?r:a;if(!yu(c.source))continue;const d={sourceKey:c.source.key,endpoint:c.endpoint,from:[c.point[0],c.point[1]],to:[h.point[0],h.point[1]],targetSourceKey:h.source.key,targetKind:"endpoint",distance:l};s.set(xu(d),d)}for(const o of n)if(yu(o.source))for(const n of t){if(n===o.source)continue;const t=bu(o.point,n);if(!t||t.t<=i||t.t>=1-i||!(t.distance>i)||t.distance>e.maxDistance)continue;const a={sourceKey:o.source.key,endpoint:o.endpoint,from:[o.point[0],o.point[1]],to:t.point,targetSourceKey:n.key,targetKind:"line",distance:t.distance};s.set(xu(a),a)}const o=[];for(const n of s.values()){const s=pu($u(t,n),i),a=e.point?_u(s,e.point,i):s.faces.find(t=>!e.requiredSourceKey||t.sourceKeys.includes(e.requiredSourceKey))||null;a&&o.push({proposal:n,face:a})}if(o.sort((t,e)=>t.proposal.distance-e.proposal.distance||xu(t.proposal).localeCompare(xu(e.proposal))),!o.length)return{kind:"none"};return new Set(o.map(t=>`${xu(t.proposal)}|${t.face.key}`)).size>1?{kind:"ambiguous",proposals:o.map(t=>t.proposal)}:{kind:"repair",...o[0]}}const Mu=1e-5;function Cu(t){const e=t.map(()=>[]);for(let i=0;i=1-1e-9||u<=1e-9||u>=1-1e-9||(e[i].push(d),e[a].push(u))}}const i=[];for(let s=0;st-e),1];for(let t=1;t{const i=e[2]-e[0],s=e[3]-e[1],n=i*i+s*s;if(!(n>0))return Math.hypot(t[0]-e[0],t[1]-e[1]);const o=Math.max(0,Math.min(1,((t[0]-e[0])*i+(t[1]-e[1])*s)/n));return Math.hypot(t[0]-(e[0]+o*i),t[1]-(e[1]+o*s))},Pu=(t,e,i,s)=>{const n=s[2]-s[0],o=s[3]-s[1],a=e*o-i*n;if(Math.abs(a)<1e-12)return 1/0;const r=s[0]-t[0],l=s[1]-t[1],c=(r*o-l*n)/a;if(!(c>1e-9))return 1/0;const h=(r*i-l*e)/a;return h<-1e-9||h>1+1e-9?1/0:c};function Ru(t,e,i,s=96){if(!(e>0&&Number.isFinite(t[0])&&Number.isFinite(t[1])))return[];const n=[];for(const s of i){if(!s||s.length<4)continue;if(![s[0],s[1],s[2],s[3]].every(Number.isFinite))continue;const i=Tu(t,s);if(i<1e-7)return[];i>e||n.push(s)}const o=[],a=Math.max(12,Math.round(s));for(let t=0;tt-e);const l=[];let c=Number.NEGATIVE_INFINITY;for(const i of o){if(i-c<1e-9)continue;c=i;const s=Math.cos(i),o=Math.sin(i);let a=e;for(const e of n){const i=Pu(t,s,o,e);i=3?l:[]}class Iu extends ht{constructor(){super(...arguments),this._spaces=null,this._spacesLoading=!1}setConfig(t){this._config=t}async _loadSpaces(){if(!this._spaces&&!this._spacesLoading&&this.hass){this._spacesLoading=!0;try{const t=await this.hass.callWS({type:"houseplan/config/get"});this._spaces=(t?.config?.spaces||[]).map(t=>({value:t.id,label:t.title||t.id}))}catch{this._spaces=[]}finally{this._spacesLoading=!1}}}get _lang(){return ra(this.hass,this._config?.language)}get _floorToken(){const t=this._config?.floor;return"number"==typeof t?`__houseplan_yaml_floor_index__:${String(t)}`:null}get _formData(){const t={...this._config},e=this._floorToken;return e?t.floor=e:Object.prototype.hasOwnProperty.call(t,"floor")||(t.floor=""),t}get _schema(){const t=this._spaces||[],e=this._lang,i=[{value:"",label:la(e,"editor.floor_none")}],s=this._floorToken;s&&i.push({value:s,label:la(e,"editor.floor_index",{index:String(this._config?.floor)})});const n="string"==typeof this._config?.floor?this._config.floor:"";return n&&!t.some(t=>t.value===n)&&i.push({value:n,label:n}),i.push(...t),[{name:"title",selector:{text:{}}},{name:"floor",selector:{select:{mode:"dropdown",options:i}}},t.length?{name:"default_floor",selector:{select:{mode:"dropdown",options:t}}}:{name:"default_floor",selector:{text:{}}},{name:"language",selector:{select:{mode:"dropdown",options:[{value:"",label:la(e,"editor.lang_auto")},{value:"en",label:la(e,"editor.lang_en")},{value:"ru",label:la(e,"editor.lang_ru")}]}}},{name:"icon_size",selector:{number:{min:1,max:6,step:.1,mode:"box"}}},{name:"show_temperature",selector:{boolean:{}}},{name:"live_states",selector:{boolean:{}}},{name:"show_signal",selector:{boolean:{}}},{name:"kiosk",selector:{boolean:{}}},{name:"cycle",selector:{number:{min:0,max:3600,step:5,mode:"box"}}}]}render(){if(!this.hass||!this._config)return G;this._loadSpaces();const t=this._lang,e={title:la(t,"editor.title"),floor:la(t,"editor.floor"),default_floor:la(t,"editor.default_floor"),language:la(t,"editor.language"),icon_size:la(t,"editor.icon_size"),show_temperature:la(t,"editor.show_temperature"),live_states:la(t,"editor.live_states"),show_signal:la(t,"editor.show_signal"),kiosk:la(t,"editor.kiosk"),cycle:la(t,"editor.cycle")};return W`e[t.name]||t.name} @value-changed=${this._valueChanged} - >`}_valueChanged(t){const e={...this._config,...t.detail.value};""===e.floor?delete e.floor:e.floor===this._floorToken&&(e.floor=this._config?.floor);const i=new Event("config-changed",{bubbles:!0,composed:!0});i.detail={config:e},this.dispatchEvent(i)}}function Au(t){const e=t.length/2,i=t.face.cm>0?t.face.cm/t.cellCm*t.gridPitch/2:tc(4,t.cellCm),s="gate"===t.type?Math.sin(10*Math.PI/180)*e:0;return{half:e,jambHalf:i,gateDepth:s,outlineHalf:Math.max(tc(16,t.cellCm),i+tc(8,t.cellCm),s+tc(8,t.cellCm)),hitHalf:Math.max(tc(20,t.cellCm),i+tc(10,t.cellCm),s+tc(12,t.cellCm))}}function Fu(t){if("passage"===t.type)return j``;const e=Math.max(0,Math.min(1,t.amount)),{half:i,jambHalf:s}=Au(t),n=Ql(t.cellCm),o=1.75*n,a=t.flipH?-1:1,r=t.flipV?-1:1;let l,c=0,h=0;if(t.face.cm>0&&(t.face.ox||t.face.oy)){const e=-t.angle*Math.PI/180,i=Math.cos(e),s=Math.sin(e);c=t.face.ox*i-t.face.oy*s,h=t.face.ox*s+t.face.oy*i,c*=a,h*=r}if("window"===t.type){const o=Math.PI/2*i,a=t.face.cm>0?j``:j``;l=j` - + >`}_valueChanged(t){const e={...this._config,...t.detail.value};""===e.floor?delete e.floor:e.floor===this._floorToken&&(e.floor=this._config?.floor);const i=new Event("config-changed",{bubbles:!0,composed:!0});i.detail={config:e},this.dispatchEvent(i)}}function Au(t,e,i,s){if(!e||"gate"===t||"passage"===t)return{ox:0,oy:0};const n=Math.hypot(s.ox,s.oy);if(!(n>0&&Number.isFinite(i)))return{ox:0,oy:0};const o=i*Math.PI/180,a=-Math.sin(o)*n,r=Math.cos(o)*n;return{ox:Math.abs(a)<1e-12?0:a,oy:Math.abs(r)<1e-12?0:r}}function Fu(t){const e=t.length/2,i=t.face.cm>0?t.face.cm/t.cellCm*t.gridPitch/2:tc(4,t.cellCm),s="gate"===t.type?Math.sin(10*Math.PI/180)*e:0;return{half:e,jambHalf:i,gateDepth:s,outlineHalf:Math.max(tc(16,t.cellCm),i+tc(8,t.cellCm),s+tc(8,t.cellCm)),hitHalf:Math.max(tc(20,t.cellCm),i+tc(10,t.cellCm),s+tc(12,t.cellCm))}}function Eu(t){if("passage"===t.type)return j``;const e=Math.max(0,Math.min(1,t.amount)),{half:i,jambHalf:s}=Fu(t),n=Ql(t.cellCm),o=1.75*n,a=t.flipH?-1:1,r=t.flipV?-1:1,l=Au(t.type,t.flipV,t.angle,t.face);let c,h=0,d=0;if(l.ox||l.oy){const e=-t.angle*Math.PI/180,i=Math.cos(e),s=Math.sin(e);h=l.ox*i-l.oy*s,d=l.ox*s+l.oy*i,h*=a,d*=r}if("window"===t.type){const o=Math.PI/2*i,a=t.face.cm>0?j``:j``;c=j` + + `}else if("gate"===t.type){const s=t.face.side*r*10*e;c=j` + @@ -4479,8 +4479,8 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="5ca433d2ee8bf92a41f4597ac53777315a9c - `}else{const s=Math.PI/2*t.length;l=j` - + `}else{const s=Math.PI/2*t.length;c=j` + @@ -4493,8 +4493,8 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="5ca433d2ee8bf92a41f4597ac53777315a9c stroke="${t.base}" stroke-width="${2.5*n}"> - ${l} - `}function Eu(t){return t<=40?"low":t<180?"mid":"high"}function zu(t){return ai(t)}function Ou(t){return"static_icon"===t.display?"neutral":"alarm"===t.visual.status?"alarm":"unavailable"===t.visual.availability?"unavailable":t.lockState?t.lockState:"working"===t.visual.status?"working":"open"===t.visual.status?"open":"neutral"}Iu.properties={hass:{attribute:!1},_config:{state:!0},_spaces:{state:!0}},customElements.get("houseplan-card-editor")||customElements.define("houseplan-card-editor",Iu);const Nu={sourceKind:"none",visualSources:[],criticalSources:[],samples:[]};function Hu(t,e){const i=t?.entities?.[e],s=t?.states?.[e];return String(i?.name||i?.original_name||s?.attributes?.friendly_name||e)}function Lu(t,e){const i=t?.states?.[e];if(!i)return"";if("function"==typeof t?.formatEntityState)try{const e=t.formatEntityState(i);if("string"==typeof e&&e)return e}catch{}return String(i.state??"")}function Bu(t,e,i,s){return{eid:e,role:i,name:Hu(t,e),state:String(t?.states?.[e]?.state??""),stateText:Lu(t,e),integrationDomain:t?.entities?.[e]?.platform||null,sample:s||cn(t,e)}}function qu(t,e,i=[e],s,n=t){const o=e.hidden&&e.userHidden?{...e,hidden:!1}:e;let a="none",r=[];const l=[...o.entities,...o.allEntities||[]].some(t=>t.startsWith("cover."))?{...o,tapAction:"cover"}:o,c=(h=_d({hass:t,devices:i,device:l,lightSources:s,registryHass:n}),"cover"!==h?.semantics?null:h.targets[0]?.entityId||h.skippedTargets[0]?.entityId||null);var h;const d=ho(t,[o]),u=Zn(o.marker?.binding,o.marker?.controls??o.controls,o.entities),p=new Set(u.filter(t=>t.startsWith("marker:"))),_=!0===o.marker?.is_light||p.size>0?s||ho(t,i):d,g=_.filter(t=>t.device.id===o.id&&"controls"!==t.via),m=d.filter(t=>"controls"!==t.via),f=g.length?g:m,v=yn(o.marker),y=v?[...f]:[...d.filter(t=>"controls"===t.via),...f];if(p.size)for(const t of _){if(!p.has(t.key))continue;t.stateEids.length>0&&y.some(e=>e.stateEids.some(e=>t.stateEids.includes(e)))||y.some(e=>e.key===t.key)||y.push({...t,via:"controls",castsGlow:!1})}const b=Yn(n,o.entities);if(!!c&&("cover"===o.tapAction||o.primary?.startsWith("cover.")||b.some(t=>t.startsWith("cover."))))a="cover",r=[Bu(t,c,"cover")];else if(y.length)a=!v&&y.some(t=>"controls"===t.via)?"controls":"light",r=y.map(i=>{const s="controls"===i.via?"control":"forced"===i.via?"forced_light":"light";if(!i.passive)return Bu(t,i.eid,s);const n=i.on?"on":"off";return{eid:i.key,role:s,name:e.name,state:n,stateText:n,integrationDomain:null,sample:{eid:i.key,state:n,availability:"available",status:i.on?"working":"neutral",activity:"none",edge:"none"}}});else{const e=Yn(n,o.entities),i=e.length?e:o.entities.filter(e=>!!t?.states?.[e]);if(i.length){a="device_role";const e=hn(n===t?t:{...n,states:t?.states||{}},i,o.entities),s=i.some(t=>an(n,t));r=e.map(e=>{const i=s?rn(n,e.eid)?"power_gate":an(n,e.eid)?"lifecycle":"device_role":"device_role";return Bu(t,e.eid,i,e)})}else o.primary&&(a="primary",r=[Bu(t,o.primary,"primary")])}const w=[];for(const e of o.entities||[]){const i=cn(t,e);"alarm"!==i.status||r.some(t=>t.eid===e)||w.push(Bu(t,e,"critical",i))}return{sourceKind:a,visualSources:r,criticalSources:w,samples:[...r,...w].map(t=>t.sample)}}function Wu(t,e,i,s){if(e.virtual)return{source:null,text:null,fallback:"value_virtual"};if(s){const i=function(t,e){if(!0!==e.marker?.use_climate_temp)return null;for(const i of e.entities){if(!i.startsWith("climate."))continue;const e=Number(t?.states?.[i]?.attributes?.current_temperature);if(Number.isFinite(e))return{eid:i,text:Math.round(10*e)/10+"°"}}return null}(t,e);if(i)return{source:{kind:"temperature",eid:i.eid,attribute:"current_temperature",text:i.text},text:i.text,fallback:null};const s=function(t,e){if("mdi:thermometer"!==e.icon&&"mdi:air-filter"!==e.icon)return null;for(const i of e.entities){if(!Gn(t,i))continue;const e=Number(t?.states?.[i]?.state);if(Number.isFinite(e))return{eid:i,text:Math.round(10*e)/10+"°"}}return null}(t,e);if(s)return{source:{kind:"temperature",eid:s.eid,text:s.text},text:s.text,fallback:null};const n=function(t,e){if(!e.primary||!fo(t,e.primary))return null;const i=Number(t?.states?.[e.primary]?.state);return Number.isFinite(i)?{eid:e.primary,text:`${Math.round(i)}%`}:null}(t,e);if(n)return{source:{kind:"humidity",eid:n.eid,text:n.text},text:n.text,fallback:null}}const n=i.visualSources.filter(t=>!t.eid.startsWith("marker:"));let o=n.map(t=>t.eid);const a=n.find(t=>"power_gate"===t.role);if(a&&(o=[a.eid]),!o.length&&i.visualSources.some(t=>t.eid.startsWith("marker:"))&&(o=Yn(t,e.entities),!o.length&&e.primary&&t?.states?.[e.primary]&&(o=[e.primary])),o=[...new Set(o)],1!==o.length)return{source:null,text:null,fallback:o.length?"value_ambiguous_sources":"value_no_state"};const r=o[0],l=function(t,e){const i=t?.states?.[e];if(!i||null==i.state||""===String(i.state).trim())return{text:"",fallback:"value_no_state"};const s=i.state;if(!["string","number","boolean"].includes(typeof s))return{text:"",fallback:"value_non_scalar"};const n=String(s).trim().toLowerCase();if("unknown"===n||"unavailable"===n)return{text:"",fallback:"value_no_state"};const o=Ji(t,e);return o?{text:Zi(o,String(i.attributes?.unit_of_measurement||"")),fallback:null}:{text:"",fallback:"value_no_state"}}(t,r);return l.fallback?{source:null,text:null,fallback:l.fallback}:{source:{kind:"entity",eid:r,text:l.text},text:l.text,fallback:null}}function ju(t,e,i){const s=t.marker?.binding||(t.bindingKind&&t.bindingRef?`${t.bindingKind}:${t.bindingRef}`:t.virtual?"virtual":""),n=[...e.visualSources.map(t=>`${t.role}:${t.eid}`),...e.criticalSources.map(t=>`critical:${t.eid}`)].sort(),o=i?`${i.kind}:${i.eid}:${i.attribute||""}`:"none";return[s,e.sourceKind,...n,`value:${o}`].join("\n")}function Uu(t,e,i){return ju(e,i||qu(t,e),null).replace(/\nvalue:none$/,"")}function Gu(t){if(t.effectiveHidden)return[];if("static_icon"===t.display)return["static-icon"];const e=[],{visual:i}=t;return"alarm"===t.pulse.kind?e.push("alarm"):"unavailable"===i.availability?e.push("unavail"):"working"===i.status?e.push("on"):"open"===i.status&&e.push("open"),t.lockState&&e.push(`lock-${t.lockState}`),"none"!==t.pulse.reason&&"alarm"!==t.pulse.reason&&e.push("activity-"+t.pulse.reason),t.pulse.generation%2==0&&(e.push("pulse-gen2"),"short"===t.pulse.kind&&e.push("activity-gen2")),e}function Vu(t,e,i){const s=Bi(e.marker?.display),n="static_icon"===s,o=n&&!1===i.sourceDetails?Nu:qu(t,e,i.lightDevices||[e],i.lightSources,i.registryHass||t),a=e.bindingStatus,r="ha_disabled"===a?.kind,l="orphaned"===a?.kind,c=!0===e.userHidden||!0===e.marker?.hidden,h=r||c&&!i.designPreview,d=dn(o.samples),u=o.visualSources.find(t=>t.eid.startsWith("lock.")),p=u?["unlocked","open"].includes(u.state.toLowerCase())?"unlocked":"locked"===u.state.toLowerCase()?"locked":null:null;let _=d;h||n?_={availability:"available",status:"neutral",activity:"none"}:"alarm"===d.status||i.liveStates||(_={availability:"available",status:"neutral",activity:"none"});const g=n&&!1===i.sourceDetails?{source:null,text:null,fallback:null}:Wu(t,e,o,i.showTemperature),m=ju(e,o,g.source),f=Uu(t,e,o),v=i.activityRuntime,y=i.now??Date.now(),b=v?.expiresAt||(v?.flashTs?v.flashTs+3300:0);!n&&!h&&i.liveStates&&"alarm"!==d.status&&v?.sources===f&&v.flashTs&&v.flashKind&&b>y&&(_={..._,activity:v.flashKind});const w="icon_ripple"===s&&!h&&i.liveStates&&"alarm"!==_.status?_.activity:"none",k=n||h||!i.showTemperature?null:!0===e.marker?.use_climate_temp?mo(t,e.entities):"mdi:thermometer"===e.icon||"mdi:air-filter"===e.icon?go(t,e.entities):null,x=!n&&!h&&i.showTemperature&&e.primary&&fo(t,e.primary)?vo(t,e.entities):null,$=n||h||!i.showSignal||e.virtual?null:_o(t,e.entities),S=i.lightSources||("derived_marker_state"===e.marker?.value_badge?.source?.kind?ho(t,i.lightDevices||[e]):[]),M=function(t,e,i){const s=null!=e.marker?.value_badge;if(i.effectiveHidden||"static_icon"===i.display)return null;const n=e.marker?.value_badge;if(s)return n?.enabled?n.source?{configured:!0,enabled:!0,position:n.position||"right",...Ho(t,e,n.source,i.markerStates)}:{configured:!0,enabled:!0,source:null,sourceLabel:"",text:"—",fullText:t?.localize?.("state.default.unavailable")||"Unavailable",position:n.position||"right",availability:"missing",isLqi:!1,tone:"default"}:null;if(!i.showTemperature||"value"===i.display)return null;const o=Lo(t,e);if(!o)return null;let a=null,r="default";if("entity_attribute"===o.kind&&"current_temperature"===o.attribute){const i=mo(t,e.entities);null!=i&&(a=`${i}°`),r="temperature"}else if("mdi:thermometer"===e.icon||"mdi:air-filter"===e.icon){const i=go(t,e.entities);null!=i&&(a=`${i}°`),r="temperature"}else{const i=vo(t,e.entities);null!=i&&(a=`${i}%`),r="humidity"}return null==a?null:{configured:!1,enabled:!0,source:o,position:"right",sourceLabel:"entity_attribute"===o.kind?`${zo(o.attribute)} · ${Eo(t,o.entity_id)}`:"entity_state"===o.kind?Eo(t,o.entity_id):"",text:a,fullText:a,availability:"available",isLqi:!1,tone:r}}(t,e,{showTemperature:i.showTemperature,showSignal:i.showSignal,display:s,effectiveHidden:h,markerStates:S.filter(t=>t.key.startsWith("marker:")).map(t=>({ref:t.key,on:t.on,name:t.device.name}))}),C=o.visualSources.find(t=>!t.eid.startsWith("marker:")),D="cover"===o.sourceKind?C?.eid:e.primary||C?.eid,T=D?t?.states?.[D]:null,P=!i.liveStates||n||h?e.icon:vs(e.icon,D?.split(".")[0],T?.attributes?.device_class,T?.state,!!e.marker?.icon),R=!i.liveStates||n||h?null:o.visualSources.filter(t=>!t.eid.startsWith("marker:")).map(e=>function(t){return t&&"on"===t.state?Ft(t.attributes?.rgb_color):null}(t?.states?.[e.eid])).find(t=>!!t)||null,I=Number(e.marker?.size)>0?Number(e.marker.size):1,A=Number(e.marker?.angle)||0,F=Number(e.marker?.ripple_size)>0?Number(e.marker.ripple_size):1.5,E=Rt(e.marker?.ripple_color,null),z=n?null:E||R||null,O=function(t){const{display:e,visual:i,semanticActivity:s,liveStates:n,effectiveHidden:o,bindingUnavailable:a=!1,reducedMotion:r=!1}=t,l=Math.max(1,Math.trunc(t.shortGeneration||1)),c=Number.isFinite(t.diameterScale)?Math.max(1,Number(t.diameterScale)):1.5,h=t.color||function(t,e){return"presence"===e?"#1DC21D":"running"===e||"working"===t.status||"open"===t.status?"#F0A00C":"#0C82F0"}(i,s);if(o||a||"unavailable"===i.availability||"static_icon"===e)return Yo(l,h,c);if("alarm"===i.status)return{kind:"alarm",reason:"alarm",generation:l,expiresAt:null,color:"#F0410C",diameterScale:1.5,animated:!r,reducedMotionIndicator:"none"};if(!n||"icon_ripple"!==e)return Yo(l,h,c);const d=t.now??Date.now(),u=t.shortExpiresAt||null;return t.shortReason&&null!=u&&u>d?{kind:"short",reason:t.shortReason,generation:l,expiresAt:u,color:h,diameterScale:r?1:c,animated:!r,reducedMotionIndicator:r?"dot":"none"}:"presence"===s||"transition"===s||"running"===s?{kind:"continuous",reason:s,generation:l,expiresAt:null,color:h,diameterScale:r?1:c,animated:!r,reducedMotionIndicator:r?"dot":"none"}:Yo(l,h,c)}({display:s,visual:_,semanticActivity:d.activity,shortReason:v?.sources===f?v?.flashKind:null,shortGeneration:v?.gen,shortExpiresAt:v?.sources===f?b:null,now:y,liveStates:i.liveStates,effectiveHidden:h,bindingUnavailable:r||l,reducedMotion:i.reducedMotion,color:z,diameterScale:F}),N="value"!==s||h?null:g.text,H="ha_disabled"===a?.kind?a.reason:null,L=function(t,e,i,s,n,o,a,r){return o?"ha_disabled":a?"orphaned":"static_icon"===r?"static_icon":"alarm"===e.status?"alarm":n?"unavailable"===e.availability?"unavailable":"cover"===s?"cover_icon_state":"presence"===i?"presence":"event"===i?"event":"transition"===i?"transition":"working"===e.status?"icon_ripple"===r&&"none"!==i?"working_activity":"working":"open"===e.status?"open":(t.primary||"").startsWith("media_player.")?"media_neutral":"neutral":"live_states_disabled"}(e,_,w,o.sourceKind,i.liveStates,r,l,s),B=[];i.designPreview&&c&&B.push("hidden_design_preview"),n||!0!==e.marker?.vacuum?.live||B.push("vacuum_live_plan_only");const q=o.visualSources.some(e=>"power_gate"===e.role||rn(t,e.eid)),W=e.entities.filter(e=>e.startsWith("switch.")&&!t?.entities?.[e]?.entity_category).length;q&&W>1&&B.push("composite_power_source"),"icon_ripple"!==s&&"static_icon"!==s&&"alarm"!==d.status&&"none"!==d.activity&&B.push("activity_display_disabled");const j={binding:e.marker?.binding||(e.bindingKind&&e.bindingRef?`${e.bindingKind}:${e.bindingRef}`:e.virtual?"virtual":""),sourceKind:o.sourceKind,visualSources:o.visualSources,criticalSources:o.criticalSources,valueSource:g.source,sourceSignature:m,visual:_,lockState:p,display:s,icon:P,valueText:N,valueFullText:N,fallbackReason:"value"!==s||N?null:g.fallback,activity:w,activityGeneration:v?.gen||1,pulse:O,classes:[],tempText:null==k?null:String(k),humText:null==x?null:String(x),valueBadge:M,lqiText:null==$||M?.isLqi?null:String($),lqiColor:null==$?null:zu($),lqiBand:null==$?null:Eu($),lightColor:R,scale:I,angle:A,rippleScale:F,rippleColor:z,userHidden:c,effectiveHidden:h,haDisabled:r,disabledReason:H,orphaned:l,vacuumLive:!n&&!0===e.marker?.vacuum?.live,explanation:{reason:L,notices:B}};return{...j,classes:Gu(j)}}function Ku(t,e=new WeakMap){if(null===t||"object"!=typeof t)return t;const i=t,s=e.get(i);if(s)return s;if(Array.isArray(t)){const s=[];e.set(i,s);for(const i of t)s.push(Ku(i,e));return Object.freeze(s)}const n={};e.set(i,n);for(const[i,s]of Object.entries(t))"function"!=typeof s&&(n[i]=Ku(s,e));return Object.freeze(n)}function Yu(t){const e=new Map(t);let i;return i=Object.freeze({get size(){return e.size},get:t=>e.get(t),has:t=>e.has(t),entries:()=>e.entries(),keys:()=>e.keys(),values:()=>e.values(),forEach:(t,s)=>e.forEach((e,n)=>t.call(s,e,n,i)),[Symbol.iterator]:()=>e[Symbol.iterator]()}),i}function Xu(t){const e=new Set(t.entityIds||[]),i=new Set(t.deviceIds||[]),s=new Set(t.areaIds||[]);for(const s of t.devices){for(const t of s.entities||[])e.add(t);s.primary&&e.add(s.primary);for(const t of s.controls||[])e.add(t);s.marker?.vacuum?.source&&e.add(s.marker.vacuum.source),"device"===s.bindingKind&&s.bindingRef&&i.add(s.bindingRef),"entity"===s.bindingKind&&s.bindingRef&&e.add(s.bindingRef)}const n={},o={};for(const[o,a]of Object.entries(t.hass?.entities||{})){const r=a?.device_id?t.hass?.devices?.[a.device_id]:null;(e.has(o)||a?.device_id&&i.has(a.device_id)||s.has(a?.area_id)||s.has(r?.area_id))&&(e.add(o),n[o]=a,a?.device_id&&i.add(a.device_id))}for(const e of i){const i=t.hass?.devices?.[e];i&&(o[e]=i)}const a={};for(const i of e){const e=t.hass?.states?.[i];e&&(a[i]=e)}const r=Object.freeze({states:Ku(a),entities:Ku(n),devices:Ku(o),config:Ku(t.hass?.config),locale:Ku(t.hass?.locale),themes:Ku(t.hass?.themes)});return Object.freeze({sourceSequence:t.sourceSequence,capturedAt:t.capturedAt??Date.now(),hass:r,devices:Ku([...t.devices]),positions:Yu([...t.positions||[]].map(([t,e])=>[t,Object.freeze({x:e.x,y:e.y})])),presentations:Yu([...t.presentations].map(([t,e])=>[t,Ku(e)])),facts:Yu([...t.facts||[]].map(([t,e])=>[t,Ku(e)]))})}const Ju=(t,e)=>`${t}:${e?1:0}`;function Zu(t){return!Number.isFinite(t)||t<=0?2.25:t/2.5*2.25}function Qu({openings:t,geometries:e,fillsByRoomId:i,idPrefix:s="data",groupClass:n="opening-tunnels",dataLayer:o="data"}){const a=t.map((t,n)=>{const o=e[n];if(!o)return G;const a=o.faces.find(t=>-1===t.side),r=o.faces.find(t=>1===t.side);if(!a||!r)return G;const l=i.get(a.roomId)||null,c=i.get(r.roomId)||null;if(!l&&!c)return G;const h=`${a.d} ${r.d}`,d=!!l&&!!c&&l.color===c.color&&l.opacity===c.opacity,u=`translate(${t.rx} ${t.ry}) rotate(${t.angle})`;if(d)return j``}function zu(t){return t<=40?"low":t<180?"mid":"high"}function Ou(t){return ai(t)}function Nu(t){return"static_icon"===t.display?"neutral":"alarm"===t.visual.status?"alarm":"unavailable"===t.visual.availability?"unavailable":t.lockState?t.lockState:"working"===t.visual.status?"working":"open"===t.visual.status?"open":"neutral"}Iu.properties={hass:{attribute:!1},_config:{state:!0},_spaces:{state:!0}},customElements.get("houseplan-card-editor")||customElements.define("houseplan-card-editor",Iu);const Hu={sourceKind:"none",visualSources:[],criticalSources:[],samples:[]};function Lu(t,e){const i=t?.entities?.[e],s=t?.states?.[e];return String(i?.name||i?.original_name||s?.attributes?.friendly_name||e)}function Bu(t,e){const i=t?.states?.[e];if(!i)return"";if("function"==typeof t?.formatEntityState)try{const e=t.formatEntityState(i);if("string"==typeof e&&e)return e}catch{}return String(i.state??"")}function qu(t,e,i,s){return{eid:e,role:i,name:Lu(t,e),state:String(t?.states?.[e]?.state??""),stateText:Bu(t,e),integrationDomain:t?.entities?.[e]?.platform||null,sample:s||cn(t,e)}}function Wu(t,e,i=[e],s,n=t){const o=e.hidden&&e.userHidden?{...e,hidden:!1}:e;let a="none",r=[];const l=[...o.entities,...o.allEntities||[]].some(t=>t.startsWith("cover."))?{...o,tapAction:"cover"}:o,c=(h=_d({hass:t,devices:i,device:l,lightSources:s,registryHass:n}),"cover"!==h?.semantics?null:h.targets[0]?.entityId||h.skippedTargets[0]?.entityId||null);var h;const d=ho(t,[o]),u=Zn(o.marker?.binding,o.marker?.controls??o.controls,o.entities),p=new Set(u.filter(t=>t.startsWith("marker:"))),_=!0===o.marker?.is_light||p.size>0?s||ho(t,i):d,g=_.filter(t=>t.device.id===o.id&&"controls"!==t.via),m=d.filter(t=>"controls"!==t.via),f=g.length?g:m,v=yn(o.marker),y=v?[...f]:[...d.filter(t=>"controls"===t.via),...f];if(p.size)for(const t of _){if(!p.has(t.key))continue;t.stateEids.length>0&&y.some(e=>e.stateEids.some(e=>t.stateEids.includes(e)))||y.some(e=>e.key===t.key)||y.push({...t,via:"controls",castsGlow:!1})}const b=Yn(n,o.entities);if(!!c&&("cover"===o.tapAction||o.primary?.startsWith("cover.")||b.some(t=>t.startsWith("cover."))))a="cover",r=[qu(t,c,"cover")];else if(y.length)a=!v&&y.some(t=>"controls"===t.via)?"controls":"light",r=y.map(i=>{const s="controls"===i.via?"control":"forced"===i.via?"forced_light":"light";if(!i.passive)return qu(t,i.eid,s);const n=i.on?"on":"off";return{eid:i.key,role:s,name:e.name,state:n,stateText:n,integrationDomain:null,sample:{eid:i.key,state:n,availability:"available",status:i.on?"working":"neutral",activity:"none",edge:"none"}}});else{const e=Yn(n,o.entities),i=e.length?e:o.entities.filter(e=>!!t?.states?.[e]);if(i.length){a="device_role";const e=hn(n===t?t:{...n,states:t?.states||{}},i,o.entities),s=i.some(t=>an(n,t));r=e.map(e=>{const i=s?rn(n,e.eid)?"power_gate":an(n,e.eid)?"lifecycle":"device_role":"device_role";return qu(t,e.eid,i,e)})}else o.primary&&(a="primary",r=[qu(t,o.primary,"primary")])}const w=[];for(const e of o.entities||[]){const i=cn(t,e);"alarm"!==i.status||r.some(t=>t.eid===e)||w.push(qu(t,e,"critical",i))}return{sourceKind:a,visualSources:r,criticalSources:w,samples:[...r,...w].map(t=>t.sample)}}function ju(t,e,i,s){if(e.virtual)return{source:null,text:null,fallback:"value_virtual"};if(s){const i=function(t,e){if(!0!==e.marker?.use_climate_temp)return null;for(const i of e.entities){if(!i.startsWith("climate."))continue;const e=Number(t?.states?.[i]?.attributes?.current_temperature);if(Number.isFinite(e))return{eid:i,text:Math.round(10*e)/10+"°"}}return null}(t,e);if(i)return{source:{kind:"temperature",eid:i.eid,attribute:"current_temperature",text:i.text},text:i.text,fallback:null};const s=function(t,e){if("mdi:thermometer"!==e.icon&&"mdi:air-filter"!==e.icon)return null;for(const i of e.entities){if(!Gn(t,i))continue;const e=Number(t?.states?.[i]?.state);if(Number.isFinite(e))return{eid:i,text:Math.round(10*e)/10+"°"}}return null}(t,e);if(s)return{source:{kind:"temperature",eid:s.eid,text:s.text},text:s.text,fallback:null};const n=function(t,e){if(!e.primary||!fo(t,e.primary))return null;const i=Number(t?.states?.[e.primary]?.state);return Number.isFinite(i)?{eid:e.primary,text:`${Math.round(i)}%`}:null}(t,e);if(n)return{source:{kind:"humidity",eid:n.eid,text:n.text},text:n.text,fallback:null}}const n=i.visualSources.filter(t=>!t.eid.startsWith("marker:"));let o=n.map(t=>t.eid);const a=n.find(t=>"power_gate"===t.role);if(a&&(o=[a.eid]),!o.length&&i.visualSources.some(t=>t.eid.startsWith("marker:"))&&(o=Yn(t,e.entities),!o.length&&e.primary&&t?.states?.[e.primary]&&(o=[e.primary])),o=[...new Set(o)],1!==o.length)return{source:null,text:null,fallback:o.length?"value_ambiguous_sources":"value_no_state"};const r=o[0],l=function(t,e){const i=t?.states?.[e];if(!i||null==i.state||""===String(i.state).trim())return{text:"",fallback:"value_no_state"};const s=i.state;if(!["string","number","boolean"].includes(typeof s))return{text:"",fallback:"value_non_scalar"};const n=String(s).trim().toLowerCase();if("unknown"===n||"unavailable"===n)return{text:"",fallback:"value_no_state"};const o=Ji(t,e);return o?{text:Zi(o,String(i.attributes?.unit_of_measurement||"")),fallback:null}:{text:"",fallback:"value_no_state"}}(t,r);return l.fallback?{source:null,text:null,fallback:l.fallback}:{source:{kind:"entity",eid:r,text:l.text},text:l.text,fallback:null}}function Uu(t,e,i){const s=t.marker?.binding||(t.bindingKind&&t.bindingRef?`${t.bindingKind}:${t.bindingRef}`:t.virtual?"virtual":""),n=[...e.visualSources.map(t=>`${t.role}:${t.eid}`),...e.criticalSources.map(t=>`critical:${t.eid}`)].sort(),o=i?`${i.kind}:${i.eid}:${i.attribute||""}`:"none";return[s,e.sourceKind,...n,`value:${o}`].join("\n")}function Gu(t,e,i){return Uu(e,i||Wu(t,e),null).replace(/\nvalue:none$/,"")}function Vu(t){if(t.effectiveHidden)return[];if("static_icon"===t.display)return["static-icon"];const e=[],{visual:i}=t;return"alarm"===t.pulse.kind?e.push("alarm"):"unavailable"===i.availability?e.push("unavail"):"working"===i.status?e.push("on"):"open"===i.status&&e.push("open"),t.lockState&&e.push(`lock-${t.lockState}`),"none"!==t.pulse.reason&&"alarm"!==t.pulse.reason&&e.push("activity-"+t.pulse.reason),t.pulse.generation%2==0&&(e.push("pulse-gen2"),"short"===t.pulse.kind&&e.push("activity-gen2")),e}function Ku(t,e,i){const s=Bi(e.marker?.display),n="static_icon"===s,o=n&&!1===i.sourceDetails?Hu:Wu(t,e,i.lightDevices||[e],i.lightSources,i.registryHass||t),a=e.bindingStatus,r="ha_disabled"===a?.kind,l="orphaned"===a?.kind,c=!0===e.userHidden||!0===e.marker?.hidden,h=r||c&&!i.designPreview,d=dn(o.samples),u=o.visualSources.find(t=>t.eid.startsWith("lock.")),p=u?["unlocked","open"].includes(u.state.toLowerCase())?"unlocked":"locked"===u.state.toLowerCase()?"locked":null:null;let _=d;h||n?_={availability:"available",status:"neutral",activity:"none"}:"alarm"===d.status||i.liveStates||(_={availability:"available",status:"neutral",activity:"none"});const g=n&&!1===i.sourceDetails?{source:null,text:null,fallback:null}:ju(t,e,o,i.showTemperature),m=Uu(e,o,g.source),f=Gu(t,e,o),v=i.activityRuntime,y=i.now??Date.now(),b=v?.expiresAt||(v?.flashTs?v.flashTs+3300:0);!n&&!h&&i.liveStates&&"alarm"!==d.status&&v?.sources===f&&v.flashTs&&v.flashKind&&b>y&&(_={..._,activity:v.flashKind});const w="icon_ripple"===s&&!h&&i.liveStates&&"alarm"!==_.status?_.activity:"none",k=n||h||!i.showTemperature?null:!0===e.marker?.use_climate_temp?mo(t,e.entities):"mdi:thermometer"===e.icon||"mdi:air-filter"===e.icon?go(t,e.entities):null,x=!n&&!h&&i.showTemperature&&e.primary&&fo(t,e.primary)?vo(t,e.entities):null,$=n||h||!i.showSignal||e.virtual?null:_o(t,e.entities),S=i.lightSources||("derived_marker_state"===e.marker?.value_badge?.source?.kind?ho(t,i.lightDevices||[e]):[]),M=function(t,e,i){const s=null!=e.marker?.value_badge;if(i.effectiveHidden||"static_icon"===i.display)return null;const n=e.marker?.value_badge;if(s)return n?.enabled?n.source?{configured:!0,enabled:!0,position:n.position||"right",...Ho(t,e,n.source,i.markerStates)}:{configured:!0,enabled:!0,source:null,sourceLabel:"",text:"—",fullText:t?.localize?.("state.default.unavailable")||"Unavailable",position:n.position||"right",availability:"missing",isLqi:!1,tone:"default"}:null;if(!i.showTemperature||"value"===i.display)return null;const o=Lo(t,e);if(!o)return null;let a=null,r="default";if("entity_attribute"===o.kind&&"current_temperature"===o.attribute){const i=mo(t,e.entities);null!=i&&(a=`${i}°`),r="temperature"}else if("mdi:thermometer"===e.icon||"mdi:air-filter"===e.icon){const i=go(t,e.entities);null!=i&&(a=`${i}°`),r="temperature"}else{const i=vo(t,e.entities);null!=i&&(a=`${i}%`),r="humidity"}return null==a?null:{configured:!1,enabled:!0,source:o,position:"right",sourceLabel:"entity_attribute"===o.kind?`${zo(o.attribute)} · ${Eo(t,o.entity_id)}`:"entity_state"===o.kind?Eo(t,o.entity_id):"",text:a,fullText:a,availability:"available",isLqi:!1,tone:r}}(t,e,{showTemperature:i.showTemperature,showSignal:i.showSignal,display:s,effectiveHidden:h,markerStates:S.filter(t=>t.key.startsWith("marker:")).map(t=>({ref:t.key,on:t.on,name:t.device.name}))}),C=o.visualSources.find(t=>!t.eid.startsWith("marker:")),D="cover"===o.sourceKind?C?.eid:e.primary||C?.eid,T=D?t?.states?.[D]:null,P=!i.liveStates||n||h?e.icon:vs(e.icon,D?.split(".")[0],T?.attributes?.device_class,T?.state,!!e.marker?.icon),R=!i.liveStates||n||h?null:o.visualSources.filter(t=>!t.eid.startsWith("marker:")).map(e=>function(t){return t&&"on"===t.state?Ft(t.attributes?.rgb_color):null}(t?.states?.[e.eid])).find(t=>!!t)||null,I=Number(e.marker?.size)>0?Number(e.marker.size):1,A=Number(e.marker?.angle)||0,F=Number(e.marker?.ripple_size)>0?Number(e.marker.ripple_size):1.5,E=Rt(e.marker?.ripple_color,null),z=n?null:E||R||null,O=function(t){const{display:e,visual:i,semanticActivity:s,liveStates:n,effectiveHidden:o,bindingUnavailable:a=!1,reducedMotion:r=!1}=t,l=Math.max(1,Math.trunc(t.shortGeneration||1)),c=Number.isFinite(t.diameterScale)?Math.max(1,Number(t.diameterScale)):1.5,h=t.color||function(t,e){return"presence"===e?"#1DC21D":"running"===e||"working"===t.status||"open"===t.status?"#F0A00C":"#0C82F0"}(i,s);if(o||a||"unavailable"===i.availability||"static_icon"===e)return Yo(l,h,c);if("alarm"===i.status)return{kind:"alarm",reason:"alarm",generation:l,expiresAt:null,color:"#F0410C",diameterScale:1.5,animated:!r,reducedMotionIndicator:"none"};if(!n||"icon_ripple"!==e)return Yo(l,h,c);const d=t.now??Date.now(),u=t.shortExpiresAt||null;return t.shortReason&&null!=u&&u>d?{kind:"short",reason:t.shortReason,generation:l,expiresAt:u,color:h,diameterScale:r?1:c,animated:!r,reducedMotionIndicator:r?"dot":"none"}:"presence"===s||"transition"===s||"running"===s?{kind:"continuous",reason:s,generation:l,expiresAt:null,color:h,diameterScale:r?1:c,animated:!r,reducedMotionIndicator:r?"dot":"none"}:Yo(l,h,c)}({display:s,visual:_,semanticActivity:d.activity,shortReason:v?.sources===f?v?.flashKind:null,shortGeneration:v?.gen,shortExpiresAt:v?.sources===f?b:null,now:y,liveStates:i.liveStates,effectiveHidden:h,bindingUnavailable:r||l,reducedMotion:i.reducedMotion,color:z,diameterScale:F}),N="value"!==s||h?null:g.text,H="ha_disabled"===a?.kind?a.reason:null,L=function(t,e,i,s,n,o,a,r){return o?"ha_disabled":a?"orphaned":"static_icon"===r?"static_icon":"alarm"===e.status?"alarm":n?"unavailable"===e.availability?"unavailable":"cover"===s?"cover_icon_state":"presence"===i?"presence":"event"===i?"event":"transition"===i?"transition":"working"===e.status?"icon_ripple"===r&&"none"!==i?"working_activity":"working":"open"===e.status?"open":(t.primary||"").startsWith("media_player.")?"media_neutral":"neutral":"live_states_disabled"}(e,_,w,o.sourceKind,i.liveStates,r,l,s),B=[];i.designPreview&&c&&B.push("hidden_design_preview"),n||!0!==e.marker?.vacuum?.live||B.push("vacuum_live_plan_only");const q=o.visualSources.some(e=>"power_gate"===e.role||rn(t,e.eid)),W=e.entities.filter(e=>e.startsWith("switch.")&&!t?.entities?.[e]?.entity_category).length;q&&W>1&&B.push("composite_power_source"),"icon_ripple"!==s&&"static_icon"!==s&&"alarm"!==d.status&&"none"!==d.activity&&B.push("activity_display_disabled");const j={binding:e.marker?.binding||(e.bindingKind&&e.bindingRef?`${e.bindingKind}:${e.bindingRef}`:e.virtual?"virtual":""),sourceKind:o.sourceKind,visualSources:o.visualSources,criticalSources:o.criticalSources,valueSource:g.source,sourceSignature:m,visual:_,lockState:p,display:s,icon:P,valueText:N,valueFullText:N,fallbackReason:"value"!==s||N?null:g.fallback,activity:w,activityGeneration:v?.gen||1,pulse:O,classes:[],tempText:null==k?null:String(k),humText:null==x?null:String(x),valueBadge:M,lqiText:null==$||M?.isLqi?null:String($),lqiColor:null==$?null:Ou($),lqiBand:null==$?null:zu($),lightColor:R,scale:I,angle:A,rippleScale:F,rippleColor:z,userHidden:c,effectiveHidden:h,haDisabled:r,disabledReason:H,orphaned:l,vacuumLive:!n&&!0===e.marker?.vacuum?.live,explanation:{reason:L,notices:B}};return{...j,classes:Vu(j)}}function Yu(t,e=new WeakMap){if(null===t||"object"!=typeof t)return t;const i=t,s=e.get(i);if(s)return s;if(Array.isArray(t)){const s=[];e.set(i,s);for(const i of t)s.push(Yu(i,e));return Object.freeze(s)}const n={};e.set(i,n);for(const[i,s]of Object.entries(t))"function"!=typeof s&&(n[i]=Yu(s,e));return Object.freeze(n)}function Xu(t){const e=new Map(t);let i;return i=Object.freeze({get size(){return e.size},get:t=>e.get(t),has:t=>e.has(t),entries:()=>e.entries(),keys:()=>e.keys(),values:()=>e.values(),forEach:(t,s)=>e.forEach((e,n)=>t.call(s,e,n,i)),[Symbol.iterator]:()=>e[Symbol.iterator]()}),i}function Ju(t){const e=new Set(t.entityIds||[]),i=new Set(t.deviceIds||[]),s=new Set(t.areaIds||[]);for(const s of t.devices){for(const t of s.entities||[])e.add(t);s.primary&&e.add(s.primary);for(const t of s.controls||[])e.add(t);s.marker?.vacuum?.source&&e.add(s.marker.vacuum.source),"device"===s.bindingKind&&s.bindingRef&&i.add(s.bindingRef),"entity"===s.bindingKind&&s.bindingRef&&e.add(s.bindingRef)}const n={},o={};for(const[o,a]of Object.entries(t.hass?.entities||{})){const r=a?.device_id?t.hass?.devices?.[a.device_id]:null;(e.has(o)||a?.device_id&&i.has(a.device_id)||s.has(a?.area_id)||s.has(r?.area_id))&&(e.add(o),n[o]=a,a?.device_id&&i.add(a.device_id))}for(const e of i){const i=t.hass?.devices?.[e];i&&(o[e]=i)}const a={};for(const i of e){const e=t.hass?.states?.[i];e&&(a[i]=e)}const r=Object.freeze({states:Yu(a),entities:Yu(n),devices:Yu(o),config:Yu(t.hass?.config),locale:Yu(t.hass?.locale),themes:Yu(t.hass?.themes)});return Object.freeze({sourceSequence:t.sourceSequence,capturedAt:t.capturedAt??Date.now(),hass:r,devices:Yu([...t.devices]),positions:Xu([...t.positions||[]].map(([t,e])=>[t,Object.freeze({x:e.x,y:e.y})])),presentations:Xu([...t.presentations].map(([t,e])=>[t,Yu(e)])),facts:Xu([...t.facts||[]].map(([t,e])=>[t,Yu(e)]))})}const Zu=(t,e)=>`${t}:${e?1:0}`;function Qu(t){return!Number.isFinite(t)||t<=0?2.25:t/2.5*2.25}function tp({openings:t,geometries:e,fillsByRoomId:i,idPrefix:s="data",groupClass:n="opening-tunnels",dataLayer:o="data"}){const a=t.map((t,n)=>{const o=e[n];if(!o)return G;const a=o.faces.find(t=>-1===t.side),r=o.faces.find(t=>1===t.side);if(!a||!r)return G;const l=i.get(a.roomId)||null,c=i.get(r.roomId)||null;if(!l&&!c)return G;const h=`${a.d} ${r.d}`,d=!!l&&!!c&&l.color===c.color&&l.opacity===c.opacity,u=`translate(${t.rx} ${t.ry}) rotate(${t.angle})`;if(d)return j``;const p=o.maxY-o.minY;if(!(p>0))return G;const _=`${(100*Math.max(0,Math.min(1,-o.minY/p))).toFixed(6)}%`,g=l||{color:"#000000",opacity:0},m=c||{color:"#000000",opacity:0},f=`hp-opening-tunnel-${s.replace(/[^a-zA-Z0-9_-]/g,"-")}-${n}`;return j` - `});return j``}const tp=new WeakMap,ep=new WeakMap;function ip(t){const e=cc(t.cfg),i={};for(const e of t.cfg.spaces||[])for(const t of e.rooms||[])t.area&&(i[t.area]=e.id);const s=t.cfg.settings?.exclude_integrations?new Set(t.cfg.settings.exclude_integrations):Yt,n=Jt(t.cfg.settings?.icon_rules?.length?t.cfg.settings.icon_rules:Xt);return So({hass:t.hass,registry:t.registry,areaToSpace:i,markers:t.cfg.markers||[],settings:t.cfg.settings||{},excluded:s,showAll:!!t.cfg.settings?.show_all,firstSpaceId:e[0]?.id||"",loc:e=>la(t.lang,e),iconRules:n})}function sp(t){const e=cc(t.cfg).find(e=>e.id===t.spaceId);if(!e)return null;const i=cs(t.cfg.spaces.find(e=>e.id===t.spaceId)),s=us(t.cfg.settings),n=t.iconSize??2.5,o=n>8?2.5:n,a=Zu(o),r=t.registry?On(t.hass,t.registry):t.hass,l=t.registry?Nn(t.hass,t.registry):t.hass,c=(t.devices||ip(t)).filter(e=>e.space===t.spaceId),h=c.filter(t=>!t.hidden),d=function(t,e,i){const s={},n=i/100*Pc(e)*1.3;for(const i of e.rooms){if(!i.area)continue;const e=t.filter(t=>t.area===i.area);if(!e.length)continue;const o=Ac(i),a=.1*Math.min(o.w,o.h),r=o.w-2*a,l=o.h-2*a,c=Math.max(1,Math.round(Math.sqrt(e.length*r/Math.max(l,1)))),h=r/c,d=l/Math.max(Math.ceil(e.length/c),1),u=e.map((t,e)=>({x:o.x+a+h*(e%c+.5),y:o.y+a+d*(Math.floor(e/c)+.5)}));Ni(u,o,n,.5*a),e.forEach((t,e)=>s[t.id]=mc(u[e]))}return s}(c,e,o),u=[];for(const e of h){const i=t.layout[e.id];if(i&&i.s===t.spaceId){const t=i.x*sc,e=i.y*sc;u.push({minX:t,minY:e,maxX:t,maxY:e})}}const p=t.cfg.spaces.find(e=>e.id===t.spaceId)||{},_=Array.isArray(p.walls)?p.walls:[],g=Number(p.cell_cm)>0?Number(p.cell_cm):5,m=(p.openings||[]).flatMap(t=>{if(!t.host)return[];const i=wd(t,e.partitions,sc,g,pc).resolved;return i?[i]:[]}),f=vh({partitions:e.partitions,roomDrafts:e.room_drafts,columns:e.wall_columns,cellCm:g,hostedOpenings:m.map(t=>({id:t.opening.id,host:t.host,length:t.length,type:t.opening.type}))}),v=function(t,e,i,s){let n=ep.get(t);n||(n=new Map,ep.set(t,n));const o=n.get(e);if(o?.fingerprint===i)return o.value;const a=s();return n.set(e,{fingerprint:i,value:a}),a}(t.cfg,e.id,f,()=>Bl(e,g,pc,2e-4*pc,m.map($d)).all);for(const t of v){const e=t.map(t=>t[0]),i=t.map(t=>t[1]);e.length&&u.push({minX:Math.min(...e),minY:Math.min(...i),maxX:Math.max(...e),maxY:Math.max(...i)})}const y=Dc(e,u),b=[y.x,y.y,y.w,y.h],w=new Map(e.rooms.map(e=>{const n=Fs(i.fill,e);return[e,_s(n,"lqi"===n&&e.area?Do(r,c,e.area):null,"light"===n?po(ho(r,c,e,t.virtualLights)):"none","temp"===n&&e.area?To(r,c,e.area):null,i.tempMin,i.tempMax,s,ls(i.customFill,e))]})),k=new Map;for(const t of e.rooms)t.id&&k.set(t.id,w.get(t)||null);const x=function(t,e=1e3){const i=[];for(const[s,n]of(t||[]).entries()){if("passage"!==n?.type)continue;const t={...n,id:String(n.id||`passage-${s}`),type:"passage",rx:Number(n.x)*e,ry:Number(n.y)*e,rlen:Number(n.length)*e};[t.rx,t.ry,t.rlen,t.angle].every(Number.isFinite)&&t.rlen>0&&i.push(t)}return i}((p.openings||[]).flatMap(t=>{if(!t.host)return[t];const e=m.find(e=>e.opening.id===t.id);return e?[Cd(t,e,sc)]:[]}),sc),$=ol(e.rooms,_,[],_c,g,pc,sc),S=m.filter(t=>Md(t,$,2e-4*pc)).map(t=>({x:t.center[0],y:t.center[1],angle:t.angle,length:t.length})),M=e.rooms.filter(t=>t.area||i.showBorders||"none"!==Fs(i.fill,t)).map(t=>{let s="room "+(e.bg?"overlay":"yard"),n="";const o=Fs(i.fill,t);if(i.showBorders||"none"!==o){s+=" styled";const e=[`--room-stroke:${i.color}`,`--room-stroke-op:${i.showBorders?i.opacity:0}`],o=w.get(t)||null;o?(s+=" filled",e.push(`--room-fill:${o.color}`,`--room-fill-op:${o.opacity.toFixed(3)}`)):e.push("--room-fill:transparent","--room-fill-op:0"),n=e.join(";")}const a=t.id||G,r=t.area||G,l=t.poly?j``});return j``}const ep=new WeakMap,ip=new WeakMap;function sp(t){const e=cc(t.cfg),i={};for(const e of t.cfg.spaces||[])for(const t of e.rooms||[])t.area&&(i[t.area]=e.id);const s=t.cfg.settings?.exclude_integrations?new Set(t.cfg.settings.exclude_integrations):Yt,n=Jt(t.cfg.settings?.icon_rules?.length?t.cfg.settings.icon_rules:Xt);return So({hass:t.hass,registry:t.registry,areaToSpace:i,markers:t.cfg.markers||[],settings:t.cfg.settings||{},excluded:s,showAll:!!t.cfg.settings?.show_all,firstSpaceId:e[0]?.id||"",loc:e=>la(t.lang,e),iconRules:n})}function np(t){const e=cc(t.cfg).find(e=>e.id===t.spaceId);if(!e)return null;const i=cs(t.cfg.spaces.find(e=>e.id===t.spaceId)),s=us(t.cfg.settings),n=t.iconSize??2.5,o=n>8?2.5:n,a=Qu(o),r=t.registry?On(t.hass,t.registry):t.hass,l=t.registry?Nn(t.hass,t.registry):t.hass,c=(t.devices||sp(t)).filter(e=>e.space===t.spaceId),h=c.filter(t=>!t.hidden),d=function(t,e,i){const s={},n=i/100*Pc(e)*1.3;for(const i of e.rooms){if(!i.area)continue;const e=t.filter(t=>t.area===i.area);if(!e.length)continue;const o=Ac(i),a=.1*Math.min(o.w,o.h),r=o.w-2*a,l=o.h-2*a,c=Math.max(1,Math.round(Math.sqrt(e.length*r/Math.max(l,1)))),h=r/c,d=l/Math.max(Math.ceil(e.length/c),1),u=e.map((t,e)=>({x:o.x+a+h*(e%c+.5),y:o.y+a+d*(Math.floor(e/c)+.5)}));Ni(u,o,n,.5*a),e.forEach((t,e)=>s[t.id]=mc(u[e]))}return s}(c,e,o),u=[];for(const e of h){const i=t.layout[e.id];if(i&&i.s===t.spaceId){const t=i.x*sc,e=i.y*sc;u.push({minX:t,minY:e,maxX:t,maxY:e})}}const p=t.cfg.spaces.find(e=>e.id===t.spaceId)||{},_=Array.isArray(p.walls)?p.walls:[],g=Number(p.cell_cm)>0?Number(p.cell_cm):5,m=(p.openings||[]).flatMap(t=>{if(!t.host)return[];const i=wd(t,e.partitions,sc,g,pc).resolved;return i?[i]:[]}),f=vh({partitions:e.partitions,roomDrafts:e.room_drafts,columns:e.wall_columns,cellCm:g,hostedOpenings:m.map(t=>({id:t.opening.id,host:t.host,length:t.length,type:t.opening.type}))}),v=function(t,e,i,s){let n=ip.get(t);n||(n=new Map,ip.set(t,n));const o=n.get(e);if(o?.fingerprint===i)return o.value;const a=s();return n.set(e,{fingerprint:i,value:a}),a}(t.cfg,e.id,f,()=>Bl(e,g,pc,2e-4*pc,m.map($d)).all);for(const t of v){const e=t.map(t=>t[0]),i=t.map(t=>t[1]);e.length&&u.push({minX:Math.min(...e),minY:Math.min(...i),maxX:Math.max(...e),maxY:Math.max(...i)})}const y=Dc(e,u),b=[y.x,y.y,y.w,y.h],w=new Map(e.rooms.map(e=>{const n=Fs(i.fill,e);return[e,_s(n,"lqi"===n&&e.area?Do(r,c,e.area):null,"light"===n?po(ho(r,c,e,t.virtualLights)):"none","temp"===n&&e.area?To(r,c,e.area):null,i.tempMin,i.tempMax,s,ls(i.customFill,e))]})),k=new Map;for(const t of e.rooms)t.id&&k.set(t.id,w.get(t)||null);const x=function(t,e=1e3){const i=[];for(const[s,n]of(t||[]).entries()){if("passage"!==n?.type)continue;const t={...n,id:String(n.id||`passage-${s}`),type:"passage",rx:Number(n.x)*e,ry:Number(n.y)*e,rlen:Number(n.length)*e};[t.rx,t.ry,t.rlen,t.angle].every(Number.isFinite)&&t.rlen>0&&i.push(t)}return i}((p.openings||[]).flatMap(t=>{if(!t.host)return[t];const e=m.find(e=>e.opening.id===t.id);return e?[Cd(t,e,sc)]:[]}),sc),$=ol(e.rooms,_,[],_c,g,pc,sc),S=m.filter(t=>Md(t,$,2e-4*pc)).map(t=>({x:t.center[0],y:t.center[1],angle:t.angle,length:t.length})),M=e.rooms.filter(t=>t.area||i.showBorders||"none"!==Fs(i.fill,t)).map(t=>{let s="room "+(e.bg?"overlay":"yard"),n="";const o=Fs(i.fill,t);if(i.showBorders||"none"!==o){s+=" styled";const e=[`--room-stroke:${i.color}`,`--room-stroke-op:${i.showBorders?i.opacity:0}`],o=w.get(t)||null;o?(s+=" filled",e.push(`--room-fill:${o.color}`,`--room-fill-op:${o.opacity.toFixed(3)}`)):e.push("--room-fill:transparent","--room-fill-op:0"),n=e.join(";")}const a=t.id||G,r=t.area||G,l=t.poly?j``:j``;return l}),C=e.rooms.filter(t=>{const e=w.get(t);return Es(i.glow,t)&&(!e||e.opacity<=0)}).map(t=>t.poly?j``}_isoDecorationLayers(t){const e="undefined"==typeof CSS||"function"!=typeof CSS.supports||CSS.supports("filter","blur(1px)"),i="function"==typeof matchMedia&&matchMedia("(forced-colors: active)").matches;return function(t){const e=!!t.showBorders;return{structural:e,panels:e&&!t.hideOpenings,shadows:e&&t.filtersSupported&&!t.forcedColors,materialNuance:e&&!t.forcedColors,floorSymbols:!t.hideOpenings&&!e}}({showBorders:t.showBorders,hideOpenings:t.hideOpenings,filtersSupported:e,forcedColors:i})}_isoOpeningPanels(t){if(!t.panels)return[];const e=this._isoScene();if(!e)return[];return e.openings.flatMap(t=>{const e=this._openingsR[t.sourceIndex];return e?rg(t,this._openingAmt(e)):[]}).sort((t,e)=>t.depth-e.depth||t.sourceIndex-e.sourceIndex||t.leaf-e.leaf)}_renderIsoDefs(t,e){const i=Ql(this._cellCm);return j` + `}_isoDecorationLayers(t){const e="undefined"==typeof CSS||"function"!=typeof CSS.supports||CSS.supports("filter","blur(1px)"),i="function"==typeof matchMedia&&matchMedia("(forced-colors: active)").matches;return function(t){const e=!!t.showBorders;return{structural:e,panels:e&&!t.hideOpenings,shadows:e&&t.filtersSupported&&!t.forcedColors,materialNuance:e&&!t.forcedColors,floorSymbols:!t.hideOpenings&&!e}}({showBorders:t.showBorders,hideOpenings:t.hideOpenings,filtersSupported:e,forcedColors:i})}_isoOpeningPanels(t){if(!t.panels)return[];const e=this._isoScene();if(!e)return[];return e.openings.flatMap(t=>{const e=this._openingsR[t.sourceIndex];return e?lg(t,this._openingAmt(e)):[]}).sort((t,e)=>t.depth-e.depth||t.sourceIndex-e.sourceIndex||t.leaf-e.leaf)}_renderIsoDefs(t,e){const i=Ql(this._cellCm);return j` ${"walls"===e&&t.materialNuance?j` @@ -5311,7 +5311,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="5ca433d2ee8bf92a41f4597ac53777315a9c ${t.panels?j``:G} - `:j``}_roomHoverPaths(t){const e=this._hoverRoom;if("view"!==this._mode||!e||e.space!==t.id)return null;const i=t.rooms.find(t=>t===e.room||!!t.id&&t.id===e.room.id);if(!i)return null;const s=hi(i);if(!s)return null;const n=t.rooms.filter(t=>t!==i).map(t=>({room:t,poly:hi(t)})).filter(t=>!!t.poly),o=Ti(s,n.map(t=>t.poly)),a=this._openPairs(),r=a.flatMap(t=>t.segs),l=i.id?a.filter(t=>t.a.id===i.id||t.b.id===i.id).flatMap(t=>t.segs):a.flatMap(t=>t.segs),c=this._spaceWalls,h=c.length&&i.id&&hl(t.rooms,i.id,c,r,this._wallKeyPitch,this._cellCm,this._gridPitch,Jg)||s,d=[{axis:s,face:h}];for(const e of o){const i=n.find(t=>t.poly===e)?.room;let s=e;if(c.length&&i?.id){const n=nl(t.rooms,i.id,c,r,this._wallKeyPitch,this._cellCm,this._gridPitch,Jg);n&&(s=wl(n.poly,n.offsets)||e)}d.push({axis:e,face:s})}const u=this._roomWallOpeningInputs(this._openingsR,t).map(t=>{const e=t.angle*Math.PI/180,i=Math.cos(e)*t.length/2,s=Math.sin(e)*t.length/2;return[t.x-i,t.y-s,t.x+i,t.y+s]}),p=.02*this._gridPitch,_=l.concat(u),g=d.map(({axis:t,face:e})=>{const i=_.map(i=>((t,e,i)=>{const s=t[2]-t[0],n=t[3]-t[1],o=Math.hypot(s,n);if(o.05)&&Hs([l,c],[i[0],i[1],s[0],s[1]])<=4*p){h=!0;break}}if(!h)return null;let d=null;for(let t=0;t.05)continue;const u=Hs([l,c],[e[0],e[1],s[0],s[1]]);(!d||u!!t);return i.length?Ts(e,i,p).map(t=>`M ${t[0]} ${t[1]} L ${t[2]} ${t[3]}`).join(" "):`M ${e.map(t=>`${t[0]} ${t[1]}`).join(" L ")} Z`}).filter(Boolean).join(" ");if(!g)return null;const m=t=>`M ${t.map(t=>`${t[0]} ${t[1]}`).join(" L ")} Z`;return{fillD:[this._cleanFloor(i,h,t).path||m(h),...o.map(m)].join(" "),outlineD:g}}_renderRoomHoverFill(t){return t?j` + `:j``}_roomHoverPaths(t){const e=this._hoverRoom;if("view"!==this._mode||!e||e.space!==t.id)return null;const i=t.rooms.find(t=>t===e.room||!!t.id&&t.id===e.room.id);if(!i)return null;const s=hi(i);if(!s)return null;const n=t.rooms.filter(t=>t!==i).map(t=>({room:t,poly:hi(t)})).filter(t=>!!t.poly),o=Ti(s,n.map(t=>t.poly)),a=this._openPairs(),r=a.flatMap(t=>t.segs),l=i.id?a.filter(t=>t.a.id===i.id||t.b.id===i.id).flatMap(t=>t.segs):a.flatMap(t=>t.segs),c=this._spaceWalls,h=c.length&&i.id&&hl(t.rooms,i.id,c,r,this._wallKeyPitch,this._cellCm,this._gridPitch,Zg)||s,d=[{axis:s,face:h}];for(const e of o){const i=n.find(t=>t.poly===e)?.room;let s=e;if(c.length&&i?.id){const n=nl(t.rooms,i.id,c,r,this._wallKeyPitch,this._cellCm,this._gridPitch,Zg);n&&(s=wl(n.poly,n.offsets)||e)}d.push({axis:e,face:s})}const u=this._roomWallOpeningInputs(this._openingsR,t).map(t=>{const e=t.angle*Math.PI/180,i=Math.cos(e)*t.length/2,s=Math.sin(e)*t.length/2;return[t.x-i,t.y-s,t.x+i,t.y+s]}),p=.02*this._gridPitch,_=l.concat(u),g=d.map(({axis:t,face:e})=>{const i=_.map(i=>((t,e,i)=>{const s=t[2]-t[0],n=t[3]-t[1],o=Math.hypot(s,n);if(o.05)&&Hs([l,c],[i[0],i[1],s[0],s[1]])<=4*p){h=!0;break}}if(!h)return null;let d=null;for(let t=0;t.05)continue;const u=Hs([l,c],[e[0],e[1],s[0],s[1]]);(!d||u!!t);return i.length?Ts(e,i,p).map(t=>`M ${t[0]} ${t[1]} L ${t[2]} ${t[3]}`).join(" "):`M ${e.map(t=>`${t[0]} ${t[1]}`).join(" L ")} Z`}).filter(Boolean).join(" ");if(!g)return null;const m=t=>`M ${t.map(t=>`${t[0]} ${t[1]}`).join(" L ")} Z`;return{fillD:[this._cleanFloor(i,h,t).path||m(h),...o.map(m)].join(" "),outlineD:g}}_renderRoomHoverFill(t){return t?j` `:j``}_renderRoomHoverOutline(t){return t?j` @@ -5335,7 +5335,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="5ca433d2ee8bf92a41f4597ac53777315a9c - `:W``}_openingAt(t){if(!this._openingsR.length)return null;const e=this._openingsR.flatMap(e=>{const i=e.angle*Math.PI/180,s=t[0]-e.rx,n=t[1]-e.ry,o=s*Math.cos(i)+n*Math.sin(i);return Math.abs(o)>e.rlen/2+tc(12,this._cellCm)?[]:[{o:e,localY:-s*Math.sin(i)+n*Math.cos(i)}]});if(!e.length)return null;const i=this._spaceModel();if(!i)return null;const s=this._openPairs().flatMap(t=>t.segs),n=this._openingWallIndexFor(i,s).value;return e.find(({o:t,localY:e})=>{const i="gate"===t.type?!t.flip_v:t.flip_v,s=t.partitionHost||this._spaceWalls.length||"gate"===t.type?this._openingFace(t,n,!!i):{ox:0,oy:0,cm:0,side:-1},o=Au({type:t.type,length:t.rlen,angle:t.angle,amount:this._openingAmt(t),flipH:!!t.flip_h,flipV:!!t.flip_v,cellCm:this._cellCm,gridPitch:this._gridPitch,face:s});return Math.abs(e)<=o.hitHalf})?.o||null}_resolveOpeningPlacement(t){const e=this._openingPreset;if("opening"!==this._tool||!e)return null;const i=this._spaceModel();if(!i)return null;const s=this._openCuts(),n=this._openingWallIndexFor(i,s),o=`${n.key}|partitions:${this._cfgEpoch}`;var a,r,l;this._openingPlacementIntervalsCache&&this._openingPlacementIntervalsCache.key===o||(this._openingPlacementIntervalsCache={key:o,value:[...ol(i.rooms,this._spaceWalls,s,this._wallKeyPitch,this._cellCm,this._gridPitch,Jg),...(a=i.partitions,r=this._cellCm,l=this._gridPitch,a.flatMap(t=>!vd(t.a)||!vd(t.b)||Math.hypot(t.b[0]-t.a[0],t.b[1]-t.a[1])<=1e-9?[]:[{roomId:"",a:[t.a[0],t.a[1]],b:[t.b[0],t.b[1]],key:`partition:${t.id}`,kind:"outer",cm:t.cm,open:!1,half:xr(t.cm,r,l)/2,partitionHost:{kind:"partition",id:t.id}}]))]}),this._openingDimensionContextCache&&this._openingDimensionContextCache.key===o||(this._openingDimensionContextCache={key:o,value:kg({rooms:i.rooms,walls:this._spaceWalls,openCuts:s,partitions:i.partitions,roomOpenings:this._roomWallOpeningInputs(),partitionCuts:this._partitionOpeningCuts(i),pitch:this._wallKeyPitch,cellCm:this._cellCm,gridPitch:this._gridPitch,coordScale:Jg,epsilon:2e-4*this._gridPitch})});const c=pg({pointer:[t[0],t[1]],preset:e,geometryRevision:this._cfgEpoch,renderedLength:this._cmToUnits(e.lengthCm),intervals:this._openingPlacementIntervalsCache.value,baseTolerance:1.5*this._gridPitch,bodyPointerPadding:this._cssPxToRender(this._boundaryCoarse?10:6),gridStep:this._gridPitch});this._openingJambBlockCm=c.jambBlockedTarget?c.jambBlockedTarget.physicalHalfWidth/this._gridPitch*this._cellCm:null;const h=c.candidate;if(!h)return null;const d="gate"===h.type?!h.flipV:h.flipV;let u;if(h.host){const t=wd({id:"preview",type:h.type,x:h.x/Jg,y:h.y/Jg,angle:h.angle,length:h.renderedLength/Jg,host:h.host},i.partitions,Jg,this._cellCm,this._gridPitch).resolved;u=t?Sd(t,d):{ox:0,oy:0,cm:0,side:-1}}else u=Ml(n.value,{x:h.x,y:h.y,angle:h.angle,length:h.renderedLength,flip_v:d});const p="mi"===this.hass?.config?.unit_system?.length,_=Tg(h,this._openingDimensionContextCache.value).map(t=>({x:t.label[0],y:t.label[1],text:li(t.distance/this._gridPitch*this._cellCm,p),dimension:t}));return{...h,face:u,measure:{labels:_,guide:h.measure.guide}}}_activateOpeningPlacement(t){this._activateMarkupTool("opening"),"opening"===this._tool&&(this._openingPreset=function(t,e){return{type:t,lengthCm:cg(t),flipH:!1,flipV:!1,revision:e}}(t,++this._openingPresetRevision),this._openingHoverCandidate=null,this._cursorPt=null)}_clearOpeningPlacement(t){this._openingHoverCandidate=null,this._openingJambBlockCm=null,t&&(this._openingPreset=null,this._openingRebindId=null)}_openingClick(t){const e=this._spaceModel();if(!e)return;const i=this._openingRebindId?null:this._openingAt(t);if(i)return void this._editOpening(i);const s=this._openingPreset;if(!s)return;const n=this._openingHoverCandidate,o=n&&_g(n,[t[0],t[1]],s.revision,this._cfgEpoch)?n:this._resolveOpeningPlacement(t);if(!o){if(null!=this._openingJambBlockCm)return void this._showToast(this._t("opening.partition_jamb_margin",{distance:li(this._openingJambBlockCm,this._imperial)}));const i=1.5*this._gridPitch,s=pi(t,e.rooms,i);return s&&function(t,e,i,s,n){for(const o of s)if(!(Hs([t,e],o)>n)&&zr([o[0],o[1]],[o[2],o[3]],i))return!0;return!1}(s.x,s.y,s.angle,this._openCuts(),i)?void this._showToast(this._t("toast.opening_on_virtual")):void this._showToast(this._t("toast.opening_no_wall"))}const a=this._openingRebindId?this._curSpaceCfg?.openings?.find(t=>t.id===this._openingRebindId):null;this._openingDialog={...a?{id:a.id,type:a.type,lengthCm:Math.round(a.length*Jg/this._gridPitch*this._cellCm),lengthTouched:!1,contact:a.contact||"",lock:a.lock||"",invert:!!a.invert,flipH:!!a.flip_h,flipV:!!a.flip_v}:{type:o.type,lengthCm:o.lengthCm,contact:"",lock:"",invert:!1,flipH:o.flipH,flipV:o.flipV},...o.host?{host:o.host}:{},x:o.x,y:o.y,angle:o.angle},this._openingRebindId=null,this._openingHoverCandidate=null,this._cursorPt=null}_editOpening(t){this._openingDialog={id:t.id,type:t.type,lengthCm:Math.round(t.rlen/this._gridPitch*this._cellCm),lengthTouched:!1,contact:t.contact||"",lock:t.lock||"",invert:!!t.invert,flipH:!!t.flip_h,flipV:!!t.flip_v,...t.host?{host:{...t.host}}:{},x:t.rx,y:t.ry,angle:t.angle}}_opPointerDown(t,e){if("plan"===this._mode&&this._spaceModel()&&"resize"!==this._tool){t.preventDefault(),t.stopPropagation();try{om(t)}catch{}this._opDrag={id:e.id,moved:!1,sx:t.clientX,sy:t.clientY,dirty:!1,before:this._geometrySnapshot()}}}_opPointerMove(t,e){if(!this._opDrag||this._opDrag.id!==e.id)return;if(Math.abs(t.clientX-this._opDrag.sx)+Math.abs(t.clientY-this._opDrag.sy)<=3)return;const i=this._spaceModel();if(!i)return;const s=this._svgPoint(t),n=this._curSpaceCfg,o=n?.openings?.find(t=>t.id===e.id);if(!o)return;if("partition"===o.host?.kind){const t=i.partitions.find(t=>t.id===o.host.id);if(!t)return;const e=t.b[0]-t.a[0],n=t.b[1]-t.a[1],a=Math.hypot(e,n);if(!(a>1e-9))return;const r=e/a,l=n/a;if(Math.abs((s[0]-t.a[0])*l-(s[1]-t.a[1])*r)>4*this._gridPitch)return;const c=o.length*Jg/2+yd(t,this._cellCm,this._gridPitch);let h=(s[0]-t.a[0])*r+(s[1]-t.a[1])*l;if(h=Math.round(h/this._gridPitch)*this._gridPitch,h=Math.max(c,Math.min(a-c,h)),a<2*c-1e-9)return;const d=h/a,u=(t.a[0]+r*h)/Jg,p=(t.a[1]+l*h)/this._spaceH;let _=180*Math.atan2(n,e)/Math.PI;_>=90?_-=180:_<-90&&(_+=180);const g=o.host.t!==d||o.x!==u||o.y!==p||o.angle!==_;return this._opDrag.moved=!0,g&&(this._opDrag.dirty=!0),o.host={...o.host,t:d},o.x=u,o.y=p,o.angle=_,this._opMeasure=null,g&&this._cfgEpoch++,void this.requestUpdate()}const a=pi(s,i.rooms,4*this._gridPitch);if(!a)return;this._opDrag.moved=!0;const r=this._opRuler(a,o.length*Jg);this._opMeasure=r.measure;const l=r.x/Jg,c=r.y/this._spaceH,h=o.x!==l||o.y!==c||o.angle!==a.angle;h&&(this._opDrag.dirty=!0),o.x=l,o.y=c,o.angle=a.angle,h&&this._cfgEpoch++,this.requestUpdate()}_opRuler(t,e){const i=this._spaceModel()?.rooms||[],s=this._gridPitch/2;let n=t.x,o=t.y,a=_i([n,o],t.angle,e,i,s);if(a&&a.centered&&(n!==a.wallCenter[0]||o!==a.wallCenter[1]))[n,o]=a.wallCenter,a=_i([n,o],t.angle,e,i,s);else if(a){const[r,l]=a.wallA,[c,h]=a.wallB,d=c-r,u=h-l,p=Math.hypot(d,u);if(p>0){const c=this._gridPitch,h=Math.min(e/2,p/2);let _=Math.round(((n-r)*d+(o-l)*u)/p/c)*c;_=Math.max(h,Math.min(p-h,_)),n=r+_/p*d,o=l+_/p*u,a=_i([n,o],t.angle,e,i,s)||a}}if(!a)return{x:n,y:o,angle:t.angle,measure:null};const r="mi"===this.hass?.config?.unit_system?.length,l=(t,e)=>({x:e[0],y:e[1],text:li(t/this._gridPitch*this._cellCm,r)});return{x:n,y:o,angle:t.angle,measure:{labels:[l(a.sideA,a.midA),l(a.sideB,a.midB)],guide:a.centered?{x:a.wallCenter[0],y:a.wallCenter[1],angle:t.angle}:null}}}_opPointerUp(t,e){if(!this._opDrag||this._opDrag.id!==e.id)return;const i=this._opDrag,s=i.moved;this._opMeasure=null,s&&i.dirty&&(this._recordGeometry(this._t("history.move_opening"),i.before),this._saveConfig()),s?window.setTimeout(()=>this._opDrag=null,0):this._opDrag=null}_opClick(t,e){"plan"===this._mode&&"resize"===this._tool||(t.stopPropagation(),this._opDrag?.moved||"plan"===this._mode&&this._editOpening(e))}_saveOpening(){const t=this._openingDialog,e=this._curSpaceCfg,i=this._spaceModel();if(!t||!e||!i)return;const s=this._geometrySnapshot(),n=this._spaceH,o=(e.openings||[]).find(e=>e.id===t.id),a={...o||{},id:t.id||"o"+Date.now().toString(36),type:t.type,x:t.x/Jg,y:t.y/n,angle:t.angle,length:o&&!t.lengthTouched?o.length:this._cmToUnits(Math.max(20,t.lengthCm))/Jg,...t.host?{host:{...t.host}}:{}};if(a.host){const t=xd(o,a)?kd(a,i.partitions,Jg,this._cellCm,this._gridPitch):wd(a,i.partitions,Jg,this._cellCm,this._gridPitch);if(!t.resolved){const e=i.partitions.find(t=>t.id===a.host.id);if("does-not-fit-jamb"===t.reason&&e){const t=yd(e,this._cellCm,this._gridPitch);this._showToast(this._t("opening.partition_jamb_margin",{distance:li(t/this._gridPitch*this._cellCm,this._imperial)}))}else this._showToast(this._t("opening.partition_orphan"));return}const s=(e.openings||[]).flatMap(t=>{if(!t.host||t.id===a.id)return[];const e=wd(t,i.partitions,Jg,this._cellCm,this._gridPitch).resolved;return e?[e]:[]});if(function(t,e,i=1e-9){const s=t.length/(2*t.axis.length),n=t.t-s,o=t.t+s;return e.some(e=>{if(e.host.id!==t.host.id||e.opening.id===t.opening.id)return!1;const s=e.length/(2*e.axis.length);return Math.max(n,e.t-s)t.id===a.id);r>=0?e.openings[r]=a:e.openings.push(a),this._recordGeometry(this._t(t.id?"history.edit_opening":"history.add_opening"),s),this._saveConfig(),this._openingDialog=null,this.requestUpdate()}_deleteOpening(){const t=this._openingDialog,e=this._curSpaceCfg;if(!t?.id||!e?.openings)return;const i=this._geometrySnapshot();e.openings=e.openings.filter(e=>e.id!==t.id),this._recordGeometry(this._t("history.delete_opening"),i),this._saveConfig(),this._openingDialog=null,this.requestUpdate()}_contactCandidates(){const t=[];for(const e of Object.keys(this.hass.states)){if(!this._openingEntityAvailable(e))continue;const i=e.split(".")[0];if("binary_sensor"!==i&&"cover"!==i)continue;const s=this.hass.states[e],n=["door","window","opening","garage_door","garage"].includes(s?.attributes?.device_class||"");("cover"!==i||n)&&t.push([e,s?.attributes?.friendly_name||e,n?0:1])}return t.sort((t,e)=>t[2]-e[2]||t[1].localeCompare(e[1])).map(([t,e])=>({value:t,label:e}))}_lockCandidates(){return Object.keys(this.hass.states).filter(t=>t.startsWith("lock.")&&this._openingEntityAvailable(t)).map(t=>({value:t,label:this.hass.states[t]?.attributes?.friendly_name||t})).sort((t,e)=>t.label.localeCompare(e.label))}_mergeClick(t){const e=this._spaceModel();if(!e)return;const i=e.rooms,s=[...i].reverse().find(e=>this._pointInRoom(t,e));if(!s?.id)return;const n=s.id;if(!this._mergeSel||this._mergeSel===n)return void(this._mergeSel=this._mergeSel===n?null:n);const o=i.find(t=>t.id===this._mergeSel),a=o?hi(o):null,r=hi(s),l=a&&r?function(t,e){if(!t||!e||t.length<3||e.length<3)return null;const i=si(Ri(t),Ri(e));if(1!==i.length)return null;if(1!==i[0].length)return null;const s=i[0][0].slice(0,-1).map(t=>[t[0],t[1]]);return s.length>=3?s:null}(a,r):null;if(!l)return this._showToast(this._t("toast.merge_not_adjacent")),void(this._mergeSel=null);this._mergeDialog={aId:this._mergeSel,bId:n,poly:l,pick:"a"},this._mergeSel=null}_commitMerge(){const t=this._mergeDialog,e=this._curSpaceCfg;if(!t||!e||!this._spaceModel())return;const i=this._geometrySnapshot(),s=this._spaceH,n="a"===t.pick?t.aId:t.bId,o="a"===t.pick?t.bId:t.aId,a=e.rooms.find(t=>t.id===n);a?(a.poly=t.poly.map(t=>[t[0]/Jg,t[1]/s]),delete a.x,delete a.y,delete a.w,delete a.h,e.rooms=e.rooms.filter(t=>t.id!==o),this._commitOpenSpans(),this._recordGeometry(this._t("history.merge_rooms"),i),this._saveConfig(),this._mergeDialog=null,this._regSignature="",this._maybeRebuildDevices(),this._showToast(this._t("toast.rooms_merged",{name:a.name||""}))):this._mergeDialog=null}_splitClick(t){const e=this._spaceModel();if(!e)return;const i=e.rooms;if(!this._splitSel){const e=[...i].reverse().find(e=>this._pointInRoom(t,e));if(!e?.id)return;return void(this._splitSel={roomId:e.id,pts:[]})}const s=i.find(t=>t.id===this._splitSel.roomId),n=s?hi(s):null;if(!s||!n)return void(this._splitSel=null);const o=.02*this._gridPitch,a=6*this._gridPitch,r=function(t,e){if(!e||e.length<2)return null;let i=null,s=1/0;for(let n=0;n=n)continue;n=_;const g=Math.sqrt(u),m=(i>0?Math.max(0,Math.min(g,Math.round(p*g/i)*i)):p*g)/g;s=[a+m*h,r+m*d]}return s}(r,n,this._gridPitch)||r,c=r&&l&&Math.hypot(r[0]-t[0],r[1]-t[1])<=a?l:null,h=!!c&&bi(c,n,o),d=this._splitSel.pts;if(!d.length)return h?void(this._splitSel={...this._splitSel,pts:[c]}):void this._showToast(this._t("toast.split_pick_wall"));if(!h){const e=this._snap(t);return wi(e,n,o)?void(this._splitSel={...this._splitSel,pts:[...d,e]}):void this._showToast(this._t("toast.split_pick_inside"))}const u=Fi(n,[...d,c],o);if(!u)return void this._showToast(this._t("toast.split_bad_cut"));this._resetRoomDialogFields();const[p,_]=u,g=Pi(p)>=Pi(_)?p:_,m=g===p?_:p;this._pendingSplit={roomId:s.id,mainPoly:g,newPoly:m},this._cursorPt=null,this._nameSel="",this._areaSel="",this._roomDialog=!0}get _contourClosed(){return this._path.length>=4&&this._samePt(this._path[0],this._path[this._path.length-1])&&(null!=this._closingWallCm||!this._activeDraftId)}_markupMove(t){if(!this._markup)return;const e=t.pointerType;if(e&&(this._boundaryPointerType=e),"column"===this._tool)return void(this._cursorPt=this._snap(this._svgPoint(t)));if("opening"===this._tool||"boundary"===this._tool||"wallthick"===this._tool)return void(this._cursorPt=this._svgPoint(t));const i="draw"===this._tool&&!this._contourClosed,s="split"===this._tool&&!!this._splitSel?.pts?.length;if(!i&&!s)return;const n=this._svgPoint(t);if(i){const e=this._resolvePlanDrawPoint(n,t.shiftKey);return this._planSnapHover={contextKey:e.contextKey,candidate:e.candidate,conflicts:e.conflicts},this._syncPlanSnapConflictMarkers(e.conflicts),this._path.length?void(this._cursorPt=e.point):void this._syncPlanSnapActiveMarker(e.candidate)}this._cursorPt=this._snap(n)}get _openingPreview(){const t=this._openingPreset;if("opening"!==this._tool||!t||!this._cursorPt)return null;const e=this._cursorPt,i=this._openingHoverCandidate;if(i&&_g(i,[e[0],e[1]],t.revision,this._cfgEpoch))return i;if(this._openingAt(e))return this._openingHoverCandidate=null,null;const s=this._resolveOpeningPlacement(e);return this._openingHoverCandidate=s,s}get _opMeasureView(){return this._opMeasure||this._openingPreview?.measure||null}_saveRoom(){(this._areaSel||this._nameSel.trim())&&(this._wallFaceBatch?this._decideWallFace(!0):this._commitRoom())}_decideWallFace(t){const e=this._wallFaceBatch;if(!e)return;const i=e.candidates[e.index];if(!i)return;if(!t&&(i.existing||i.repair)&&1===e.candidates.length)return this._wallFaceBatch=null,this._roomDialog=!1,this._nameSel="",this._areaSel="",void this.requestUpdate();const s=t?{candidate:i,create:!0,name:this._nameSel.trim(),area:this._areaSel||null,settings:this._roomSettingsFromDialog()?JSON.parse(JSON.stringify(this._roomSettingsFromDialog())):null}:{candidate:i,create:!1},n=[...e.decisions,s],o=e.index+1;if(o"number"==typeof t&&Number.isFinite(t)&&t>=0?t:null,n=.02*this._gridPitch,o=this._spaceModel();if(!o)return fr;for(const e of this._planSnapGeometrySnapshot().value.segments){if("room"===e.sourceKind||Hs(t,[e.a[0],e.a[1],e.b[0],e.b[1]])>n)continue;if("partition"===e.sourceKind)return s(o.partitions.find(t=>t.id===e.sourceId)?.cm)??fr;const i=e.sourceId.lastIndexOf(":"),a=i>=0?e.sourceId.slice(0,i):e.sourceId,r=i>=0?Number(e.sourceId.slice(i+1)):-1;return s(o.room_drafts.find(t=>t.id===a)?.segments[r]?.cm)??fr}const a=jd(Math.max(0,e.length-1),i,this._drawWallCm,fr);for(let i=0;i+1[...t]);if(!e?.sourceKey.startsWith("active:"))return i;const s=/:(\d+)$/.exec(e.sourceKey),n=s?Number(s[1])+("b"===e.endpoint?1:0):-1;return n>=0&&ne.key===t.sourceKey),o=s.find(e=>e.key===t.targetSourceKey);if(!n||!o)return!1;const a="a"===t.endpoint?n.a:n.b;return!(Math.hypot(a[0]-t.from[0],a[1]-t.from[1])>i)&&(!(Hs(t.to,[o.a[0],o.a[1],o.b[0],o.b[1]])>i)&&!function(t,e){if(!t.sourceKey.startsWith("static:partition|"))return!1;const i=t.sourceKey.slice(17).split("|")[0];return!!i&&e.some(t=>"partition"===t.host?.kind&&t.host.id===i)}(t,this._curSpaceCfg?.openings||[]))}_applyWallRepair(t,e){const i=this._curSpaceCfg;if(!i||!this._validateWallRepair(t,e.activePath))return!1;const s=e=>{e[0]=t.to[0]/Jg,e[1]=t.to[1]/Jg};if(t.sourceKey.startsWith("active:")){const n=/:(\d+)$/.exec(t.sourceKey),o=n?Number(n[1])+("b"===t.endpoint?1:0):-1;if(o<0||o>=e.activePath.length)return!1;e.activePath[o]=[...t.to];const a=(i.room_drafts||[]).find(t=>t.id===e.activeDraftId);return a?.points?.[o]&&s(a.points[o]),!0}if(!t.sourceKey.startsWith("static:"))return!1;const[n,o]=t.sourceKey.slice(7).split("|");if("partition"===n){const e=(i.partitions||[]).find(t=>t.id===o);if(!e)return!1;const n=[e.a[0]*Jg,e.a[1]*Jg],a=[e.b[0]*Jg,e.b[1]*Jg],r=Math.hypot(n[0]-t.from[0],n[1]-t.from[1])<=2e-4*this._gridPitch?e.a:Math.hypot(a[0]-t.from[0],a[1]-t.from[1])<=2e-4*this._gridPitch?e.b:null;return!!r&&(s(r),!0)}if("draft"===n){const e=o.lastIndexOf(":"),n=e>=0?o.slice(0,e):"",a=e>=0?Number(o.slice(e+1)):-1,r=(i.room_drafts||[]).find(t=>t.id===n);if(!r?.points?.[a]||!r?.points?.[a+1])return!1;const l=[a,a+1].find(e=>Math.hypot(r.points[e][0]*Jg-t.from[0],r.points[e][1]*Jg-t.from[1])<=2e-4*this._gridPitch);return null!=l&&(s(r.points[l]),!0)}return!1}_applyWallFaceBatch(){const t=this._wallFaceBatch,e=this._curSpaceCfg,i=this._spaceModel();if(!t||!e||!i)return;const s=(t,e)=>{this._showToast(this._t(t,e)),this._roomDialogCancel()},n=t.decisions.filter(t=>t.create),o=n.map(t=>t.candidate.ring),a=i.rooms;for(let t=0;ti.id!==e&&!!hi(i)&&Di(o[t],hi(i)));if(i)return void s("toast.room_overlap",{name:i.name||""})}if((e.rooms||[]).length+n.length>400)return void s("toast.physical_limit");if(n.some(t=>t.candidate.split&&!e.rooms.some(e=>e.id===t.candidate.split.roomId)))return void s("toast.contour_cannot_close");const r=n.map(t=>t.candidate.repair).filter(t=>!!t);if(r.length>1||r[0]&&!this._validateWallRepair(r[0],t.activePath))return void s("toast.wall_repair_changed");const l=this._activePathWithRepair(t.activePath,r[0]),c=2e-4*this._gridPitch,h=new Map;for(let e=0;et.candidate.atomKeys)),e=n.some(t=>t.candidate.consumeAllActive);for(const i of uu(this._wallGraphSources(l),c)){const s=i.sourceKeys.find(t=>h.has(t));!s||e||t.has(i.key)||d.push({a:i.a,b:i.b,cm:h.get(s)})}}else d.push(...Ud(l,jd(l.length-1,t.activeCms,this._drawWallCm,fr)));if((e.partitions||[]).length+d.length>em)return void s("toast.physical_limit");const u=this._geometrySnapshot();if(r[0]&&!this._applyWallRepair(r[0],t))return void s("toast.wall_repair_changed");const p=n.some(t=>!!t.candidate.split),_=p?al(i.rooms,e.walls,this._openCuts(),this._wallKeyPitch,this._cellCm,this._gridPitch,Jg):null,g=p&&Array.isArray(e.walls)?e.walls:null;for(const t of n){const i=t.candidate.split;if(!i)continue;const n=e.rooms.find(t=>t.id===i.roomId);if(!n)return void s("toast.contour_cannot_close");n.poly=i.mainPoly.map(t=>[t[0]/Jg,t[1]/this._spaceH]),delete n.x,delete n.y,delete n.w,delete n.h}const m=Date.now().toString(36),f=[];if(n.forEach((t,i)=>{const s=t.area?this.hass.areas[t.area]?.name:"",n={id:`r${m}-${i}`,name:t.name||s||this._t("room.default_name"),area:t.area||null,poly:t.candidate.ring.map(t=>[t[0]/Jg,t[1]/this._spaceH]),...t.settings?{settings:JSON.parse(JSON.stringify(t.settings))}:{}};e.rooms.push(n),f.push({room:n,decision:t})}),t.activeDraftId&&Array.isArray(e.room_drafts)&&(e.room_drafts=e.room_drafts.filter(e=>e.id!==t.activeDraftId),e.room_drafts.length||delete e.room_drafts),d.length&&(e.partitions||=[],d.forEach((t,i)=>e.partitions.push({id:`partition-${m}-${i}`,a:[t.a[0]/Jg,t.a[1]/Jg],b:[t.b[0]/Jg,t.b[1]/Jg],cm:t.cm}))),p){this._commitOpenSpans();const t=this._normalizeWalls(_,this._openCuts());t.length?e.walls=t:g?.length?e.walls=g:delete e.walls}if(f.length){this._cfgEpoch++;const i=this._openCuts(),s=this._spaceModel();if(!s)return;let n=e.walls;for(const{room:e,decision:o}of f){const a=o.candidate.ring,r=this._wallSourceCmAt(a[0],t.activePath,t.activeCms);n=Lr(n,s.rooms,e.id,r,this._wallKeyPitch,i,Jg);for(const o of ol(s.rooms,n,i,this._wallKeyPitch,this._cellCm,this._gridPitch,Jg)){if(o.roomId!==e.id||"outer"!==o.kind)continue;const i=[(o.a[0]+o.b[0])/2,(o.a[1]+o.b[1])/2];n=Nr(n,o.a,o.b,this._wallSourceCmAt(i,t.activePath,t.activeCms),this._wallKeyPitch,Jg)}}const o=this._normalizeWalls(n,i);o.length?e.walls=o:delete e.walls}this._recordGeometry(this._t("history.wall_face_batch"),u),this._saveConfig(),delete this._resumeDraftBySpace[this._space],this._path=[],this._activeDraftId=null,this._draftSegmentCms=[],this._closingWallCm=null,this._wallFaceBatch=null,this._roomDialog=!1,this._nameSel="",this._areaSel="",this._regSignature="",this._maybeRebuildDevices();const v=new Set(n.map(t=>t.area).filter(t=>!!t));if(v.size){const t={...this._layout};for(const e of this._devices){if(!v.has(e.area||"")||e.space!==this._space)continue;if(this._layout[e.id])continue;const i=this._defPos[e.id];i&&(t[e.id]={s:this._space,x:i.x/Jg,y:i.y/Jg},this._dirtyPos.add(e.id))}this._layout=t,this._persistLayout()}this._showToast(this._t(n.length?"toast.wall_rooms_saved":"toast.wall_chain_saved",{n:n.length}))}_commitRoom(){const t=this._curSpaceCfg,e=this._spaceModel();if(!t||!e)return;const i=this._geometrySnapshot(),s=this._spaceH,n=!!this._pendingSplit,o=n?al(e.rooms,t.walls,this._openCuts(),this._wallKeyPitch,this._cellCm,this._gridPitch,Jg):null,a=n&&Array.isArray(t.walls)?t.walls:null;let r;if(this._pendingSplit){const e=t.rooms.find(t=>t.id===this._pendingSplit.roomId);if(!e)return this._pendingSplit=null,this._splitSel=null,void(this._roomDialog=!1);e.poly=this._pendingSplit.mainPoly.map(t=>[t[0]/Jg,t[1]/s]),delete e.x,delete e.y,delete e.w,delete e.h,r=this._pendingSplit.newPoly}else{if(!this._contourClosed)return;r=this._path.slice(0,-1)}const l=this._areaSel?this.hass.areas[this._areaSel]?.name:"",c={id:"r"+Date.now().toString(36),name:this._nameSel||l||this._t("room.default_name"),area:this._areaSel||null,poly:r.map(t=>[t[0]/Jg,t[1]/s]),...this._roomSettingsFromDialog()?{settings:this._roomSettingsFromDialog()}:{}};if(t.rooms.push(c),!n&&this._activeDraftId&&Array.isArray(t.room_drafts)&&(t.room_drafts=t.room_drafts.filter(t=>t.id!==this._activeDraftId),t.room_drafts.length||delete t.room_drafts),n){this._commitOpenSpans();const e=this._normalizeWalls(o,this._openCuts());e.length?t.walls=e:a?.length?t.walls=a:delete t.walls}if(!n){const e=jd(r.length,[...this._draftSegmentCms,this._closingWallCm??void 0],this._drawWallCm,fr),i=e[0];if(null!=i){this._cfgEpoch++;const s=this._openCuts(),n=this._spaceModel();if(!n)return;let o=Lr(t.walls,n.rooms,c.id,i,this._wallKeyPitch,s,Jg);for(const t of ol(n.rooms,o,s,this._wallKeyPitch,this._cellCm,this._gridPitch,Jg)){if(t.roomId!==c.id||"outer"!==t.kind)continue;const i=[(t.a[0]+t.b[0])/2,(t.a[1]+t.b[1])/2],s=r.findIndex((t,e)=>{const s=r[(e+1)%r.length];return Hs(i,[t[0],t[1],s[0],s[1]])<=.02*this._gridPitch});s>=0&&(o=Nr(o,t.a,t.b,e[s],this._wallKeyPitch,Jg))}o=this._normalizeWalls(o,s),o.length?t.walls=o:delete t.walls}}this._recordGeometry(this._t(n?"history.split_room":"history.add_room"),i),this._saveConfig(),this._path=[],delete this._resumeDraftBySpace[this._space],this._activeDraftId=null,this._draftSegmentCms=[],this._closingWallCm=null,this._pendingSplit=null,this._splitSel=null;const h=this._areaSel;this._areaSel="",this._nameSel="",this._roomDialog=!1,this._regSignature="",this._maybeRebuildDevices();let d=0;if(h){const t=Jg,e={...this._layout};for(const i of this._devices){if(i.area!==h||i.space!==this._space)continue;if(d++,this._layout[i.id])continue;const s=this._defPos[i.id];s&&(e[i.id]={s:this._space,x:s.x/Jg,y:s.y/t},this._dirtyPos.add(i.id))}this._layout=e,this._persistLayout()}const u=this._model.find(t=>t.id===this._space)?.rooms.length||0;this._showToast(h?this._t("toast.room_saved",{n:u,added:d}):this._t("toast.room_saved_no_area",{n:u}))}_cancelPath(){this._wallRepairDiagnostic=null,this._activeDraftId&&(this._resumeDraftBySpace[this._space]=this._activeDraftId),this._path=[],this._activeDraftId=null,this._draftSegmentCms=[],this._closingWallCm=null,this._clearPlanSnapHover(),this._roomDialog=!1,this._pendingSplit=null,this._wallFaceBatch=null,this._splitSel=null,this._mergeSel=null,this._mergeDialog=null,this._openWallAnchor=null,this._boundaryRestoreGuard=null,this._physicalSel=null,this._physicalDrag=null,this._physicalRotate=null,this._clearOpeningPlacement(!0)}_resumeLastDraft(){const t=this._resumeDraftBySpace[this._space];if(!t)return;const e=this._spaceModel()?.room_drafts.find(e=>e.id===t);e?(this._activeDraftId=t,this._path=e.points.map(t=>[...t]),this._draftSegmentCms=this._adoptDraftCms(this._path,e.segments.map(t=>t.cm),e.id),this._clearPlanSnapHover()):delete this._resumeDraftBySpace[this._space]}_roomDialogCancel(){if(this._roomDialog=!1,this._roomEditId)return this._roomEditId=null,this._nameSel="",void(this._areaSel="");if(this._wallFaceBatch){const t=this._wallFaceBatch;return this._wallFaceBatch=null,this._path=t.activePath.map(t=>[...t]),this._draftSegmentCms=[...t.activeCms],this._activeDraftId=t.activeDraftId,this._nameSel="",this._areaSel="",void this.requestUpdate()}if(this._pendingSplit)return this._pendingSplit=null,void(this._splitSel=null);this._undoPoint()}get _freeAreas(){const t=new Set;for(const e of this._serverCfg?.spaces||[])for(const i of e.rooms||[])i.area&&t.add(i.area);for(const e of this._wallFaceBatch?.decisions||[])e.create&&e.area&&t.add(e.area);return Object.values(this.hass?.areas||{}).filter(e=>!t.has(e.area_id)).sort((t,e)=>(t.name||"").localeCompare(e.name||""))}_openMarkerDialog(t){if(this._vacAllCamerasFor=null,this._vacAllCameraCache=null,t&&this._ackNewDevice(t.id),this._norm)if(t){const e=t.marker,i=Object.prototype.hasOwnProperty.call(e||{},"is_light"),s=Object.prototype.hasOwnProperty.call(e||{},"light_entity"),n=Object.prototype.hasOwnProperty.call(e||{},"glow_color"),o=Object.prototype.hasOwnProperty.call(e||{},"value_badge"),a=Object.prototype.hasOwnProperty.call(e||{},"tap_action"),r=Object.prototype.hasOwnProperty.call(e||{},"toggle_entity"),l=ks(e?.glow_color),c=this._devicePresentation(t,!0).valueBadge,h=Wo(this._planHass,t,this._devices),d=jo(this._planHass,t,h);this._markerDialog={devId:t.id,name:t.name,binding:"virtual"===t.bindingKind?"virtual":t.bindingKind+":"+t.bindingRef,bindingMode:"virtual"===t.bindingKind?"virtual":"ha",bindingOpen:!1,showEntities:"entity"===t.bindingKind&&!!this._fullRegistryHass.entities[t.bindingRef||""]?.device_id,bindingFilter:"",icon:t.marker?.icon||"",autoIcon:t.icon||"",display:Bi(t.marker?.display),rippleColor:Rt(t.marker?.ripple_color,""),rippleSize:Number(t.marker?.ripple_size)>0?Number(t.marker.ripple_size):1.5,size:Number(t.marker?.size)>0?Number(t.marker.size):1,angle:Number(t.marker?.angle)||0,tapAction:hd(t.marker?.tap_action,t.primary?.split(".")[0]),tapActionTouched:!1,originalHasTapAction:a,originalTapAction:t.marker?.tap_action,tapHintAnnouncement:"",toggleEntity:e?.toggle_entity||"",toggleEntityTouched:!1,originalHasToggleEntity:r,originalToggleEntity:e?.toggle_entity,tapTarget:t.marker?.tap_target||"",tapConfirm:!0===t.marker?.tap_confirm,runFilter:"",controls:Zn(t.marker?.binding,t.marker?.controls,t.entities),controlsFilter:"",lightRole:!0===e?.is_light?"always":!1===e?.is_light?"never":"auto",lightRoleTouched:!1,originalHasIsLight:i,originalIsLight:e?.is_light,lightEntity:e?.light_entity||"",lightEntityTouched:!1,originalHasLightEntity:s,originalLightEntity:e?.light_entity,glowMode:null!=l?.bri?"fixed":l?"color":"auto",glowColor:l?.c||this._fillColors.glow_light.c,glowBrightness:Math.max(1,Math.round(100*(l?.bri??1))),glowColorDrafted:!!l,glowBrightnessDrafted:null!=l?.bri,glowTouched:!1,originalHasGlowColor:n&&(!!l||null===e?.glow_color),originalGlowColor:l||(null===e?.glow_color?null:void 0),valueBadgeEnabled:o?!0===e?.value_badge?.enabled:!!c,valueBadgeSource:e?.value_badge?.source||c?.source||d,valueBadgePosition:e?.value_badge?.position||c?.position||"right",valueBadgeTouched:!1,originalHasValueBadge:o,originalValueBadge:e?.value_badge,useClimateTemp:!0===t.marker?.use_climate_temp,glowRadius:Number(t.marker?.glow_radius_cm)>0?String(this._imperial?Math.round(Number(t.marker.glow_radius_cm)/30.48*10)/10:Math.round(Number(t.marker.glow_radius_cm))/100):"",model:t.model||"",link:t.link||"",description:t.description||"",pdfs:[...t.pdfs||[]],room:t.marker?.room_id?t.space+"#@"+t.marker.room_id:t.space&&t.area?t.space+"#"+t.area:"",hideFromPlan:!0===t.marker?.hidden,busy:!1}}else this._markerDialog={name:"",binding:"virtual",bindingMode:"virtual",bindingOpen:!1,showEntities:!1,bindingFilter:"",icon:"",autoIcon:"",display:"badge",rippleColor:"",rippleSize:1.5,size:1,angle:0,tapAction:"info",tapActionTouched:!1,originalHasTapAction:!1,originalTapAction:void 0,tapHintAnnouncement:"",toggleEntity:"",toggleEntityTouched:!1,originalHasToggleEntity:!1,originalToggleEntity:void 0,tapTarget:"",tapConfirm:!1,runFilter:"",controls:[],controlsFilter:"",lightRole:"auto",lightRoleTouched:!1,originalHasIsLight:!1,originalIsLight:void 0,lightEntity:"",lightEntityTouched:!1,originalHasLightEntity:!1,originalLightEntity:void 0,glowMode:"auto",glowColor:this._fillColors.glow_light.c,glowBrightness:100,glowColorDrafted:!1,glowBrightnessDrafted:!1,glowTouched:!1,originalHasGlowColor:!1,originalGlowColor:void 0,valueBadgeEnabled:!1,valueBadgeSource:null,valueBadgePosition:"right",valueBadgeTouched:!1,originalHasValueBadge:!1,originalValueBadge:void 0,useClimateTemp:!1,glowRadius:"",model:"",link:"",description:"",pdfs:[],room:"",hideFromPlan:!1,busy:!1,uploadId:"up_"+Date.now().toString(36)+Math.random().toString(36).slice(2,6)};else this._showToast(this._t("toast.marker_needs_server"))}_runCandidates(){const t=[];for(const e of Gi)for(const[i,s]of Object.entries(this.hass.states))i.startsWith(e+".")&&this._planEntityAvailable(i)&&t.push({value:i,label:s?.attributes?.friendly_name||i,sub:this._t("run."+e)});return t.sort((t,e)=>t.sub.localeCompare(e.sub)||t.label.localeCompare(e.label))}_bindingCandidates(){const t=this._planHass,e=wo(this._markers),i=new Set(this._markers.filter(t=>t.removed).map(t=>t.binding)),s=new Set;for(const t of this._devices)t.id!==this._markerDialog?.devId&&("device"===t.bindingKind&&t.bindingRef&&s.add("device:"+t.bindingRef),"entity"===t.bindingKind&&t.bindingRef&&s.add("entity:"+t.bindingRef));const n=new Set;for(const t of this._devices)"device"===t.bindingKind&&t.name&&n.add(t.name.trim()+"|"+(t.area||""));const o=[];for(const e of Object.values(t.devices)){if("service"===e.entry_type)continue;const t="device:"+e.id;if(s.has(t))continue;const a=(e.name_by_user||e.name||e.id).trim();t!==this._markerDialog?.binding&&!i.has(t)&&n.has(a+"|"+(e.area_id||""))||o.push({value:t,label:a,sub:(e.model||this._t("marker.sub_device"))+("Group"===e.model?this._t("marker.sub_z2m_group"):"")})}const a=new Set(["group","template","derivative","min_max","threshold","integration","statistics","trend","utility_meter","tod","switch_as_x","schedule"]);for(const[n,r]of Object.entries(t.entities)){const l="entity:"+n;if(s.has(l))continue;if(ko(t,n,e)&&!i.has(l))continue;const c=a.has(r.platform),h="group"===r.platform;if(!c&&!h)continue;if(r.hidden&&!i.has(l))continue;const d=t.states[n];o.push({value:l,label:r.name||d?.attributes?.friendly_name||n,sub:n.split(".")[0]+" · "+("group"===r.platform?this._t("marker.sub_group"):this._t("marker.sub_helper"))})}if(this._markerDialog?.showEntities){const n=new Set(o.map(t=>t.value));for(const[a,r]of Object.entries(t.entities)){const l="entity:"+a;if(s.has(l)||n.has(l)||r.hidden&&!i.has(l))continue;if(ko(t,a,e)&&!i.has(l))continue;const c=t.states[a],h=r.name||c?.attributes?.friendly_name||a,d=r.device_id?t.devices[r.device_id]:null,u=d&&(d.name_by_user||d.name)||"";o.push({value:l,label:h,sub:a.split(".")[0]+" · "+this._t("marker.sub_entity")+(u?" · "+u:"")})}}const r=(this._markerDialog?.bindingFilter||"").toLowerCase().trim(),l=r?o.filter(t=>(t.label+" "+t.sub+" "+t.value).toLowerCase().includes(r)):o;return l.sort((t,e)=>t.label.localeCompare(e.label)),l.slice(0,200)}_physicalBodiesR(t=this._spaceModel()){if(!t)return[];const e=`${t.id}|${this._cfgEpoch}|${this._cellCm}|${this._gridPitch}`;if(this._physicalBodiesCache?.key===e)return this._physicalBodiesCache.all;const i=Bl(t,this._cellCm,this._gridPitch,2e-4*this._gridPitch,this._partitionOpeningCuts(t));return this._physicalBodiesCache={key:e,...i},i.all}_rawPhysicalBodiesR(t=this._spaceModel()){if(!t)return[];this._physicalBodiesR(t);const e=this._physicalBodiesCache;return e?[...e.drafts,...e.partitions,...e.columns]:[]}_cleanFloor(t,e,i=this._spaceModel()){if(!i)return{floor:e,geom:null,path:"",area:Vl([[[...e,e[0]]]])};const s=t.id||`#${i.rooms.indexOf(t)}`,n=`${i.id}|${this._cfgEpoch}|${s}`;if(!this._rszPreview){const t=Ng(this._cleanFloorCache,n);if(t.hit)return t.value}const o=e.map(t=>t[0]),a=e.map(t=>t[1]),r=[Math.min(...o),Math.min(...a),Math.max(...o),Math.max(...a)],l=this._physicalBodiesR(i).filter(t=>{const e=t.map(t=>t[0]),i=t.map(t=>t[1]);return Math.max(...e)>=r[0]&&Math.min(...e)<=r[2]&&Math.max(...i)>=r[1]&&Math.min(...i)<=r[3]}),c=l.length?Gl(e,l):null,h={floor:e,geom:c,path:c?Ol(c):"",area:Vl(c||[[[...e,e[0]]]])};return this._rszPreview||Hg(this._cleanFloorCache,n,h,600),h}_autoIconForBinding(t){if("virtual"===t)return"mdi:map-marker";const[e,i]=t.split(":");if(!i)return"";const s=this._fullRegistryHass,n=this._bindingStatus(t),o="active"===n.kind?n.enabledEntityIds:n.allEntityIds;if("device"===e){const t=s.devices?.[i];if(!t)return"mdi:help-circle";const e=o;return e.some(t=>t.startsWith("lock."))?"mdi:lock":bo(s,t.name_by_user||t.name||"",t.model,e,this._iconRules)}if("entity"===e){const t=s.entities?.[i],e=this.hass.states?.[i],n=t?.name||e?.attributes?.friendly_name||i;return i.startsWith("lock.")?"mdi:lock":bo(s,n,"",[i],this._iconRules)}return""}_allRoomsFlat(){const t=[];for(const e of this._serverCfg?.spaces||[])for(const i of e.rooms||[])i.area?t.push({value:e.id+"#"+i.area,label:(e.title||e.id)+" · "+i.name}):i.id&&t.push({value:e.id+"#@"+i.id,label:(e.title||e.id)+" · "+i.name+" · "+this._t("marker.subarea")});return t}_errText(t){if(!t)return this._t("err.unknown");if("string"==typeof t)return t;if("invalid_passage_fields"===t.code){const e=String(t.message||t.error||"").match(/space=([^;]*);\s*opening=([^;]*);\s*fields=([^;]*)/);if(e){const t=this._serverCfg?.spaces?.find(t=>String(t.id)===e[1]),i={contact:"opening.contact_label",lock:"opening.lock_label",invert:"opening.invert",flip_h:"opening.flip_h",flip_v:"opening.flip_v"},s=e[3].split(",").filter(Boolean).map(t=>i[t]?this._t(i[t]):t).join(", ");return this._t("opening.invalid_passage_fields",{room:t?.title||e[1],fields:s})}}if("invalid_partition_opening_jamb_margin"===t.code){const e=String(t.message||t.error||"").match(/margin_cm=([^;]*)/),i=e?Number(e[1]):NaN;if(Number.isFinite(i))return this._t("opening.partition_jamb_margin",{distance:li(i,this._imperial)})}if(t.message)return t.message;if(t.error)return t.error;if(null!=t.code)return this._t("err.code",{code:t.code});try{return JSON.stringify(t)}catch{return String(t)}}_backupErrorText(t){const e=t?.code??t?.error;if("string"==typeof e){const t=`backup.error.${e}`,i=this._t(t);if(i!==t)return i}return this._errText(t)}async _pickMarkerFiles(t){const e=t.target,i=e.files?[...e.files]:[];if(e.value="",!i.length||!this._markerDialog)return;const s=this._markerDialog.uploadId||this._markerDialog.devId||"new",n=[];for(const t of i)try{const e=new FormData;e.append("marker_id",s),e.append("file",t,t.name);const i=this.hass?.fetchWithAuth?await this.hass.fetchWithAuth("/api/houseplan/upload",{method:"POST",body:e}):await fetch("/api/houseplan/upload",{method:"POST",body:e,headers:this.hass?.auth?.data?.access_token?{authorization:`Bearer ${this.hass.auth.data.access_token}`}:{}}),o=await i.json().catch(()=>({}));if(!i.ok||o.error){const t={too_large:this._t("err.too_large",{mb:o.max_mb||50}),bad_ext:this._t("err.bad_ext"),unauthorized:this._t("err.unauthorized")};throw new Error(t[o.error]||o.error||"HTTP "+i.status)}n.push({name:o.name||t.name,url:o.url})}catch(e){this._showToast(this._t("toast.file_failed",{name:t.name,err:this._errText(e)}))}n.length&&this._markerDialog&&(this._markerDialog={...this._markerDialog,pdfs:[...this._markerDialog.pdfs,...n]},this._showToast(this._t("toast.files_attached",{n:n.length})))}_removeMarkerPdf(t){this._markerDialog&&(this._markerDialog={...this._markerDialog,pdfs:this._markerDialog.pdfs.filter(e=>e.url!==t)})}_markerLightFields(t){const e={};if(t.lightRoleTouched?"always"===t.lightRole?e.is_light=!0:"never"===t.lightRole&&(e.is_light=!1):t.originalHasIsLight&&(e.is_light=t.originalIsLight??null),t.lightEntityTouched?t.lightEntity&&(e.light_entity=t.lightEntity):t.originalHasLightEntity&&(e.light_entity=t.originalLightEntity??null),t.glowTouched){if("auto"!==t.glowMode){const i={c:Rt(t.glowColor,this._fillColors.glow_light.c)};"fixed"===t.glowMode&&(i.bri=Math.max(.01,Math.min(1,Math.round(t.glowBrightness)/100))),e.glow_color=i}}else t.originalHasGlowColor&&(e.glow_color=t.originalGlowColor??null);return e}_markerTapActionFields(t){return t.tapActionTouched?{tap_action:t.tapAction||null}:t.originalHasTapAction?{tap_action:t.originalTapAction??null}:{}}_markerToggleEntityFields(t){return(e={touched:t.toggleEntityTouched,originalHas:t.originalHasToggleEntity,original:t.originalToggleEntity,value:t.toggleEntity}).touched?e.value?{toggle_entity:e.value}:{}:e.originalHas?{toggle_entity:e.original??null}:{};var e}async _saveMarker(){const t=this._markerDialog;if(!t||t.busy)return;const e=this._effectiveMarkerTapAction(t);if("ha"===t.bindingMode&&(!t.binding||"virtual"===t.binding))return;if("virtual"===t.binding&&!t.name.trim())return void this._showToast(this._t("toast.virtual_name_required"));if("run"===e&&!t.tapTarget)return void this._showToast(this._t("toast.run_target_required"));if(t.valueBadgeTouched&&t.valueBadgeEnabled&&!t.valueBadgeSource)return void this._showToast(this._t("toast.value_badge_source_required"));if("ha"===t.bindingMode){const e=this._bindingStatus(t.binding),i=t.devId?this._markers.find(e=>e.id===t.devId):null,s=!i||i.binding!==t.binding;if("active"!==e.kind&&s)return void this._showToast(this._t("ha_disabled"===e.kind?"toast.ha_disabled_add":"toast.ha_binding_unverified"));if("ha_disabled"===e.kind&&!0===i?.hidden&&!t.hideFromPlan)return this._markerDialog={...t,hideFromPlan:!0},void this._showToast(this._t("entity"===e.reason?"toast.ha_disabled_show_entity":"toast.ha_disabled_show_device"))}const i=this._serverCfg;if(!i)return;const s=i.markers||[],n=qs(t.room);let o=n?.space||null;const a=n?.area||null,r=n?.roomId||null,l=Ei(t.binding,t.devId,()=>"v_"+Date.now().toString(36)),c=t.devId,h=c?this._devices.find(t=>t.id===c):null,d=n?.space||h?.space||null,u=d?this._spaceModelById(d):this._spaceModel();if(!u)return;const p=u.id;"virtual"!==t.binding||o||(o=p),this._markerDialog={...t,busy:!0};try{const n="virtual"===t.binding?[]:s.filter(e=>e.removed&&e.binding===t.binding).map(t=>t.id),d=n.length>0,_=Zn(t.binding,t.controls,this._bindingEntities(t.binding)),g=s.find(t=>t.id===l||t.id===c)?.vacuum||null,m={id:l,vacuum:g,binding:t.binding,name:t.name.trim()||null,icon:t.icon||null,display:"badge"!==t.display?t.display:null,ripple_color:"icon_ripple"===t.display&&t.rippleColor?t.rippleColor:null,ripple_size:"icon_ripple"===t.display&&1.5!==t.rippleSize?t.rippleSize:null,size:1!==t.size?t.size:null,angle:t.angle?t.angle:null,...this._markerTapActionFields(t),...this._markerToggleEntityFields(t),tap_target:"run"===e&&t.tapTarget||null,tap_confirm:!!t.tapConfirm||null,controls:_.length?_:null,...this._markerLightFields(t),...this._markerValueBadgeFields(t),use_climate_temp:!!t.useClimateTemp||null,glow_radius_cm:(()=>{const e=Og(t.glowRadius);return null==e||e<=0?null:Math.round(this._imperial?30.48*e:100*e)})(),model:t.model.trim()||null,link:t.link.trim()||null,description:t.description.trim()||null,pdfs:t.pdfs,hidden:!!t.hideFromPlan};("virtual"===t.binding||t.room)&&(m.space=o,m.area=a,m.room_id=r);const f=h?.marker?.room_id??null,v=!!t.room&&null!=h&&(h.space!==o||h.area!==a||f!==r);let y=!1;const b=t.uploadId||c;if(b&&b!==l&&m.pdfs?.length)try{const t=await this.hass.callWS({type:"houseplan/files/migrate",from_id:b,to_id:l}),e=t?.mapping||{};m.pdfs=function(t,e,i,s){if(!e||!i||e===i)return t;const n="/files/"+e+"/",o="/files/"+i+"/";return t.map(t=>{if(!t.url.includes(n))return t;const e=t.url.split(n)[1]||"",[i,a]=[e.split("?")[0],e.includes("?")?"?"+e.split("?")[1]:""];if(s){const e=s[decodeURIComponent(i)]??s[i];return e?{...t,url:t.url.split(n+i)[0]+o+encodeURIComponent(e)+a}:t}return{...t,url:t.url.split(n).join(o)}})}(m.pdfs,b,l,e),y=Object.keys(e).length>0}catch(t){this._showToast(this._t("toast.files_migrate_failed",{err:this._errText(t)}))}i.markers=s,c&&c!==l&&(i.markers=function(t,e,i){if(!e||!i||e===i)return[...t];const s=`marker:${e}`,n=`marker:${i}`;return t.map(t=>{const e=Array.isArray(t.controls)?t.controls.map(t=>t===s?n:t):t.controls,i="derived_marker_state"===t.value_badge?.source?.kind&&t.value_badge.source.ref===s?{...t.value_badge,source:{...t.value_badge.source,ref:n}}:t.value_badge;return e===t.controls&&i===t.value_badge?t:{...t,controls:e,value_badge:i}})}(i.markers,c,l)),c&&c!==l&&"derived_marker_state"===m.value_badge?.source?.kind&&m.value_badge.source.ref===`marker:${c}`&&(m.value_badge.source={kind:"derived_marker_state",ref:`marker:${l}`}),i.markers=i.markers.filter(t=>t.id!==l&&t.id!==c&&("virtual"===m.binding||t.binding!==m.binding)),i.markers.push(m);let w=null;const k=c?this._layout[c]:null,x=k?{s:k.s||h?.space||this._space,x:k.x,y:k.y}:c&&h&&this._defPos[c]?this._normPos(h.space,this._defPos[c].x,this._defPos[c].y):null;if(!d&&x&&x.s===p)l===c&&this._layout[l]&&!v||(w={s:x.s,x:x.x,y:x.y},this._layout={...this._layout,[l]:w});else if(d||!this._layout[l]||v){let t=u.vb[0]+u.vb[2]/2,e=u.vb[1]+u.vb[3]/2;const i=r?u.rooms.find(t=>t.id===r):a?u.rooms.find(t=>t.area===a):void 0;i&&([t,e]=this._roomCenter(i)),w=this._normPos(p,t,e),this._layout={...this._layout,[l]:w}}await this._saveConfigNow(),w&&this._noteLayoutRev(await this.hass.callWS({type:"houseplan/layout/update",device_id:l,pos:w}));const $=new Set(n);c&&c!==l&&$.add(c),$.delete(l);for(const t of $)delete this._layout[t],await this.hass.callWS({type:"houseplan/layout/delete",device_id:t}).then(t=>this._noteLayoutRev(t)).catch(()=>{});y&&b&&await this.hass.callWS({type:"houseplan/files/cleanup",marker_id:b}).catch(()=>{}),this._markerDialog=null,this._regSignature="",this._maybeRebuildDevices(),this._showToast(this._t("toast.marker_saved"))}catch(t){this._markerDialog&&(this._markerDialog={...this._markerDialog,busy:!1}),this._showToast(this._t("toast.error",{err:this._errText(t)}))}}async _deleteMarker(){const t=this._markerDialog;if(!t||t.busy||!t.devId)return;const e=t.devId?this._devices.find(e=>e.id===t.devId):null;if(!e)return;const i=t.name||this._t("device.fallback");if(!confirm(this._t("confirm.remove_marker",{name:i})))return;const s=this._serverCfg;s.markers=s.markers||[];const n=s.markers,o="virtual"===e.bindingKind?"virtual":e.bindingKind&&e.bindingRef?`${e.bindingKind}:${e.bindingRef}`:"";if(!o)return;const a=function(t,e,i,s){const n=new Set([e]),o=t.filter(t=>{const o=t.id===e||!s&&t.binding===i;return o&&n.add(t.id),!o});return{markers:s?o:[...o,{id:e,binding:i,removed:!0,hidden:!0}],cleanupIds:n}}(s.markers,e.id,o,"virtual"===e.bindingKind);var r,l;s.markers=(r=a.markers,l=a.cleanupIds,r.map(t=>{if(!Array.isArray(t.controls))return t;const e=t.controls.filter(t=>!("string"==typeof t&&t.startsWith("marker:")&&l.has(t.slice(7))));return e.length===t.controls.length?t:{...t,controls:e.length?e:null}}));const c=a.cleanupIds;this._markerDialog={...t,busy:!0};try{await this._saveConfigNow();for(const t of c){delete this._layout[t],delete this._defPos[t],this._dirtyPos.delete(t),this._sentPos.delete(t);const e=this._activityRt.get(t);e&&clearTimeout(e.timer),this._activityRt.delete(t),this._vacRt.delete(t),delete this._vacSrvTrails[t],await this.hass.callWS({type:"houseplan/layout/delete",device_id:t}).then(t=>this._noteLayoutRev(t)).catch(()=>{}),await this.hass.callWS({type:"houseplan/files/cleanup",marker_id:t}).catch(()=>{}),await this.hass.callWS({type:"houseplan/trail/delete",marker_id:t}).catch(()=>{})}this._markerDialog=null,this._infoCard?.id===e.id&&this._closeInfoCard(),this._selId===e.id&&(this._selId=null),this._drag?.id===e.id&&(this._drag=null),this._regSignature="",this._maybeRebuildDevices(),this._showToast(this._t("toast.marker_removed"))}catch(t){this._serverCfg===s&&(s.markers=n),this._markerDialog&&(this._markerDialog={...this._markerDialog,busy:!1}),this._showToast(this._t("toast.error",{err:this._errText(t)}))}}_normPos(t,e,i){return{s:t,x:e/Jg,y:i/Jg}}_openSpaceDialog(t,e){if(this._serverStorage&&this._serverCfg)if("edit"===t){const i=this._serverCfg.spaces.find(t=>t.id===e);if(!i)return;const s=cs(i),n=i.settings?.custom_fill&&"object"==typeof i.settings.custom_fill?rs(i.settings.custom_fill):null,o="none"===s.fill?{...n||as,a:0}:n;this._spaceDialog={mode:t,spaceId:e,title:i.title,planUrl:i.plan_url||null,planFile:null,source:i.plan_url?"file":"draw",showBorders:s.showBorders,showNames:s.showNames,displayTouched:!0,hideDecor:s.hideDecor,hideOpenings:s.hideOpenings,roomColor:s.color,roomOpacity:s.opacity,fillMode:"none"===s.fill?"custom":s.fill,customFill:o,glowEnabled:s.glow,bgColor:s.bgColor,bgMode:"static"===i.settings?.bg_mode||"daynight"===i.settings?.bg_mode?i.settings.bg_mode:null,northDeg:Za({},i.settings),sunRays:"boolean"==typeof i.settings?.sun_rays?i.settings.sun_rays:null,tempMin:s.tempMin,tempMax:s.tempMax,showLqi:s.showLqi??this._config?.show_signal??!0,cardFontScale:s.cardFontScale,labelTemp:s.labelTemp,labelHum:s.labelHum,labelLqi:s.labelLqi,labelLight:s.labelLight,cellCm:Number(i.cell_cm)>0?Number(i.cell_cm):5,cellCmInput:ic(Number(i.cell_cm)>0?Number(i.cell_cm):5,this._imperial),cellCmTouched:!1,busy:!1}}else this._spaceDialog={mode:t,title:"",planUrl:null,planFile:null,...xh(),hideDecor:!1,hideOpenings:!1,roomColor:ns,roomOpacity:os,fillMode:"custom",customFill:{...as,a:0},glowEnabled:!0,bgColor:null,bgMode:"daynight",northDeg:null,sunRays:null,tempMin:20,tempMax:25,showLqi:this._config?.show_signal??!0,cardFontScale:1,labelTemp:!1,labelHum:!1,labelLqi:!1,labelLight:!1,cellCm:ec(this._imperial),cellCmInput:ic(ec(this._imperial),this._imperial),cellCmTouched:!1,busy:!1};else this._showToast(this._t("toast.integration_missing"))}async _pickPlanFile(t){const e=t.target,i=e.files?.[0];if(!i||!this._spaceDialog)return;const s={"image/svg+xml":"svg","image/png":"png","image/jpeg":"jpg","image/webp":"webp"}[i.type]||(i.name.toLowerCase().endsWith(".svg")?"svg":"");if(!s)return void this._showToast(this._t("toast.plan_formats"));const n=new Uint8Array(await i.arrayBuffer());let o="";for(let t=0;t{const e=new Image;e.onload=()=>t(e.naturalWidth&&e.naturalHeight?e.naturalWidth/e.naturalHeight:1.414),e.onerror=()=>t(1.414),e.src=r});URL.revokeObjectURL(r),this._spaceDialog={...this._spaceDialog,planFile:{ext:s,b64:a,aspect:l,name:i.name}}}_useServerPlan(t){const e=this._spaceDialog;e&&(this._spaceDialog={...e,planUrl:t,planFile:null,pickSaved:!1,savedAspect:void 0},this._aspectJob=this._readPlanAspect(t))}async _readPlanAspect(t){for(let e=0;e<40;e++){const e=this._display(t);if(e){const i=await new Promise(t=>{const i=new Image;i.onload=()=>t(i.naturalWidth&&i.naturalHeight?i.naturalWidth/i.naturalHeight:0),i.onerror=()=>t(0),i.src=e}),s=this._spaceDialog;return s&&s.planUrl===t&&Number.isFinite(i)&&i>0?(this._spaceDialog={...s,savedAspect:i},i):0}if(await new Promise(t=>setTimeout(t,150)),this._spaceDialog?.planUrl!==t)return 0}return 0}async _deleteServerPlan(t){if(confirm(this._t("confirm.delete_plan",{name:t})))try{await this.hass.callWS({type:"houseplan/plans/delete",name:t});const e=this._spaceDialog;e?.saved&&(this._spaceDialog={...e,saved:e.saved.filter(e=>e.name!==t)})}catch(t){this._showToast(this._t("toast.plan_delete_failed",{err:this._errText(t)}))}}_renderServerPlans(t){if(t.savedBusy)return W`
${this._t("space.loading")}
`;const e=t.saved||[];if(!e.length)return W`
${this._t("space.no_saved")}
`;return W`
+
`:W``}_openingAt(t){if(!this._openingsR.length)return null;const e=this._openingsR.flatMap(e=>{const i=e.angle*Math.PI/180,s=t[0]-e.rx,n=t[1]-e.ry,o=s*Math.cos(i)+n*Math.sin(i);return Math.abs(o)>e.rlen/2+tc(12,this._cellCm)?[]:[{o:e,localY:-s*Math.sin(i)+n*Math.cos(i)}]});if(!e.length)return null;const i=this._spaceModel();if(!i)return null;const s=this._openPairs().flatMap(t=>t.segs),n=this._openingWallIndexFor(i,s).value;return e.find(({o:t,localY:e})=>{const i="gate"===t.type?!t.flip_v:t.flip_v,s=t.partitionHost||this._spaceWalls.length||"gate"===t.type?this._openingFace(t,n,!!i):{ox:0,oy:0,cm:0,side:-1},o=Fu({type:t.type,length:t.rlen,angle:t.angle,amount:this._openingAmt(t),flipH:!!t.flip_h,flipV:!!t.flip_v,cellCm:this._cellCm,gridPitch:this._gridPitch,face:s});return Math.abs(e)<=o.hitHalf})?.o||null}_resolveOpeningPlacement(t){const e=this._openingPreset;if("opening"!==this._tool||!e)return null;const i=this._spaceModel();if(!i)return null;const s=this._openCuts(),n=this._openingWallIndexFor(i,s),o=`${n.key}|partitions:${this._cfgEpoch}`;var a,r,l;this._openingPlacementIntervalsCache&&this._openingPlacementIntervalsCache.key===o||(this._openingPlacementIntervalsCache={key:o,value:[...ol(i.rooms,this._spaceWalls,s,this._wallKeyPitch,this._cellCm,this._gridPitch,Zg),...(a=i.partitions,r=this._cellCm,l=this._gridPitch,a.flatMap(t=>!vd(t.a)||!vd(t.b)||Math.hypot(t.b[0]-t.a[0],t.b[1]-t.a[1])<=1e-9?[]:[{roomId:"",a:[t.a[0],t.a[1]],b:[t.b[0],t.b[1]],key:`partition:${t.id}`,kind:"outer",cm:t.cm,open:!1,half:xr(t.cm,r,l)/2,partitionHost:{kind:"partition",id:t.id}}]))]}),this._openingDimensionContextCache&&this._openingDimensionContextCache.key===o||(this._openingDimensionContextCache={key:o,value:xg({rooms:i.rooms,walls:this._spaceWalls,openCuts:s,partitions:i.partitions,roomOpenings:this._roomWallOpeningInputs(),partitionCuts:this._partitionOpeningCuts(i),pitch:this._wallKeyPitch,cellCm:this._cellCm,gridPitch:this._gridPitch,coordScale:Zg,epsilon:2e-4*this._gridPitch})});const c=_g({pointer:[t[0],t[1]],preset:e,geometryRevision:this._cfgEpoch,renderedLength:this._cmToUnits(e.lengthCm),intervals:this._openingPlacementIntervalsCache.value,baseTolerance:1.5*this._gridPitch,bodyPointerPadding:this._cssPxToRender(this._boundaryCoarse?10:6),gridStep:this._gridPitch});this._openingJambBlockCm=c.jambBlockedTarget?c.jambBlockedTarget.physicalHalfWidth/this._gridPitch*this._cellCm:null;const h=c.candidate;if(!h)return null;const d="gate"===h.type?!h.flipV:h.flipV;let u;if(h.host){const t=wd({id:"preview",type:h.type,x:h.x/Zg,y:h.y/Zg,angle:h.angle,length:h.renderedLength/Zg,host:h.host},i.partitions,Zg,this._cellCm,this._gridPitch).resolved;u=t?Sd(t,d):{ox:0,oy:0,cm:0,side:-1}}else u=Ml(n.value,{x:h.x,y:h.y,angle:h.angle,length:h.renderedLength,flip_v:d});const p="mi"===this.hass?.config?.unit_system?.length,_=Pg(h,this._openingDimensionContextCache.value).map(t=>({x:t.label[0],y:t.label[1],text:li(t.distance/this._gridPitch*this._cellCm,p),dimension:t}));return{...h,face:u,measure:{labels:_,guide:h.measure.guide}}}_activateOpeningPlacement(t){this._activateMarkupTool("opening"),"opening"===this._tool&&(this._openingPreset=function(t,e){return{type:t,lengthCm:hg(t),flipH:!1,flipV:!1,revision:e}}(t,++this._openingPresetRevision),this._openingHoverCandidate=null,this._cursorPt=null)}_clearOpeningPlacement(t){this._openingHoverCandidate=null,this._openingJambBlockCm=null,t&&(this._openingPreset=null,this._openingRebindId=null)}_openingClick(t){const e=this._spaceModel();if(!e)return;const i=this._openingRebindId?null:this._openingAt(t);if(i)return void this._editOpening(i);const s=this._openingPreset;if(!s)return;const n=this._openingHoverCandidate,o=n&&gg(n,[t[0],t[1]],s.revision,this._cfgEpoch)?n:this._resolveOpeningPlacement(t);if(!o){if(null!=this._openingJambBlockCm)return void this._showToast(this._t("opening.partition_jamb_margin",{distance:li(this._openingJambBlockCm,this._imperial)}));const i=1.5*this._gridPitch,s=pi(t,e.rooms,i);return s&&function(t,e,i,s,n){for(const o of s)if(!(Hs([t,e],o)>n)&&zr([o[0],o[1]],[o[2],o[3]],i))return!0;return!1}(s.x,s.y,s.angle,this._openCuts(),i)?void this._showToast(this._t("toast.opening_on_virtual")):void this._showToast(this._t("toast.opening_no_wall"))}const a=this._openingRebindId?this._curSpaceCfg?.openings?.find(t=>t.id===this._openingRebindId):null;this._openingDialog={...a?{id:a.id,type:a.type,lengthCm:Math.round(a.length*Zg/this._gridPitch*this._cellCm),lengthTouched:!1,contact:a.contact||"",lock:a.lock||"",invert:!!a.invert,flipH:!!a.flip_h,flipV:!!a.flip_v}:{type:o.type,lengthCm:o.lengthCm,contact:"",lock:"",invert:!1,flipH:o.flipH,flipV:o.flipV},...o.host?{host:o.host}:{},x:o.x,y:o.y,angle:o.angle},this._openingRebindId=null,this._openingHoverCandidate=null,this._cursorPt=null}_editOpening(t){this._openingDialog={id:t.id,type:t.type,lengthCm:Math.round(t.rlen/this._gridPitch*this._cellCm),lengthTouched:!1,contact:t.contact||"",lock:t.lock||"",invert:!!t.invert,flipH:!!t.flip_h,flipV:!!t.flip_v,...t.host?{host:{...t.host}}:{},x:t.rx,y:t.ry,angle:t.angle}}_opPointerDown(t,e){if("plan"===this._mode&&this._spaceModel()&&"resize"!==this._tool){t.preventDefault(),t.stopPropagation();try{am(t)}catch{}this._opDrag={id:e.id,moved:!1,sx:t.clientX,sy:t.clientY,dirty:!1,before:this._geometrySnapshot()}}}_opPointerMove(t,e){if(!this._opDrag||this._opDrag.id!==e.id)return;if(Math.abs(t.clientX-this._opDrag.sx)+Math.abs(t.clientY-this._opDrag.sy)<=3)return;const i=this._spaceModel();if(!i)return;const s=this._svgPoint(t),n=this._curSpaceCfg,o=n?.openings?.find(t=>t.id===e.id);if(!o)return;if("partition"===o.host?.kind){const t=i.partitions.find(t=>t.id===o.host.id);if(!t)return;const e=t.b[0]-t.a[0],n=t.b[1]-t.a[1],a=Math.hypot(e,n);if(!(a>1e-9))return;const r=e/a,l=n/a;if(Math.abs((s[0]-t.a[0])*l-(s[1]-t.a[1])*r)>4*this._gridPitch)return;const c=o.length*Zg/2+yd(t,this._cellCm,this._gridPitch);let h=(s[0]-t.a[0])*r+(s[1]-t.a[1])*l;if(h=Math.round(h/this._gridPitch)*this._gridPitch,h=Math.max(c,Math.min(a-c,h)),a<2*c-1e-9)return;const d=h/a,u=(t.a[0]+r*h)/Zg,p=(t.a[1]+l*h)/this._spaceH;let _=180*Math.atan2(n,e)/Math.PI;_>=90?_-=180:_<-90&&(_+=180);const g=o.host.t!==d||o.x!==u||o.y!==p||o.angle!==_;return this._opDrag.moved=!0,g&&(this._opDrag.dirty=!0),o.host={...o.host,t:d},o.x=u,o.y=p,o.angle=_,this._opMeasure=null,g&&this._cfgEpoch++,void this.requestUpdate()}const a=pi(s,i.rooms,4*this._gridPitch);if(!a)return;this._opDrag.moved=!0;const r=this._opRuler(a,o.length*Zg);this._opMeasure=r.measure;const l=r.x/Zg,c=r.y/this._spaceH,h=o.x!==l||o.y!==c||o.angle!==a.angle;h&&(this._opDrag.dirty=!0),o.x=l,o.y=c,o.angle=a.angle,h&&this._cfgEpoch++,this.requestUpdate()}_opRuler(t,e){const i=this._spaceModel()?.rooms||[],s=this._gridPitch/2;let n=t.x,o=t.y,a=_i([n,o],t.angle,e,i,s);if(a&&a.centered&&(n!==a.wallCenter[0]||o!==a.wallCenter[1]))[n,o]=a.wallCenter,a=_i([n,o],t.angle,e,i,s);else if(a){const[r,l]=a.wallA,[c,h]=a.wallB,d=c-r,u=h-l,p=Math.hypot(d,u);if(p>0){const c=this._gridPitch,h=Math.min(e/2,p/2);let _=Math.round(((n-r)*d+(o-l)*u)/p/c)*c;_=Math.max(h,Math.min(p-h,_)),n=r+_/p*d,o=l+_/p*u,a=_i([n,o],t.angle,e,i,s)||a}}if(!a)return{x:n,y:o,angle:t.angle,measure:null};const r="mi"===this.hass?.config?.unit_system?.length,l=(t,e)=>({x:e[0],y:e[1],text:li(t/this._gridPitch*this._cellCm,r)});return{x:n,y:o,angle:t.angle,measure:{labels:[l(a.sideA,a.midA),l(a.sideB,a.midB)],guide:a.centered?{x:a.wallCenter[0],y:a.wallCenter[1],angle:t.angle}:null}}}_opPointerUp(t,e){if(!this._opDrag||this._opDrag.id!==e.id)return;const i=this._opDrag,s=i.moved;this._opMeasure=null,s&&i.dirty&&(this._recordGeometry(this._t("history.move_opening"),i.before),this._saveConfig()),s?window.setTimeout(()=>this._opDrag=null,0):this._opDrag=null}_opClick(t,e){"plan"===this._mode&&"resize"===this._tool||(t.stopPropagation(),this._opDrag?.moved||"plan"===this._mode&&this._editOpening(e))}_saveOpening(){const t=this._openingDialog,e=this._curSpaceCfg,i=this._spaceModel();if(!t||!e||!i)return;const s=this._geometrySnapshot(),n=this._spaceH,o=(e.openings||[]).find(e=>e.id===t.id),a={...o||{},id:t.id||"o"+Date.now().toString(36),type:t.type,x:t.x/Zg,y:t.y/n,angle:t.angle,length:o&&!t.lengthTouched?o.length:this._cmToUnits(Math.max(20,t.lengthCm))/Zg,...t.host?{host:{...t.host}}:{}};if(a.host){const t=xd(o,a)?kd(a,i.partitions,Zg,this._cellCm,this._gridPitch):wd(a,i.partitions,Zg,this._cellCm,this._gridPitch);if(!t.resolved){const e=i.partitions.find(t=>t.id===a.host.id);if("does-not-fit-jamb"===t.reason&&e){const t=yd(e,this._cellCm,this._gridPitch);this._showToast(this._t("opening.partition_jamb_margin",{distance:li(t/this._gridPitch*this._cellCm,this._imperial)}))}else this._showToast(this._t("opening.partition_orphan"));return}const s=(e.openings||[]).flatMap(t=>{if(!t.host||t.id===a.id)return[];const e=wd(t,i.partitions,Zg,this._cellCm,this._gridPitch).resolved;return e?[e]:[]});if(function(t,e,i=1e-9){const s=t.length/(2*t.axis.length),n=t.t-s,o=t.t+s;return e.some(e=>{if(e.host.id!==t.host.id||e.opening.id===t.opening.id)return!1;const s=e.length/(2*e.axis.length);return Math.max(n,e.t-s)t.id===a.id);r>=0?e.openings[r]=a:e.openings.push(a),this._recordGeometry(this._t(t.id?"history.edit_opening":"history.add_opening"),s),this._saveConfig(),this._openingDialog=null,this.requestUpdate()}_deleteOpening(){const t=this._openingDialog,e=this._curSpaceCfg;if(!t?.id||!e?.openings)return;const i=this._geometrySnapshot();e.openings=e.openings.filter(e=>e.id!==t.id),this._recordGeometry(this._t("history.delete_opening"),i),this._saveConfig(),this._openingDialog=null,this.requestUpdate()}_contactCandidates(){const t=[];for(const e of Object.keys(this.hass.states)){if(!this._openingEntityAvailable(e))continue;const i=e.split(".")[0];if("binary_sensor"!==i&&"cover"!==i)continue;const s=this.hass.states[e],n=["door","window","opening","garage_door","garage"].includes(s?.attributes?.device_class||"");("cover"!==i||n)&&t.push([e,s?.attributes?.friendly_name||e,n?0:1])}return t.sort((t,e)=>t[2]-e[2]||t[1].localeCompare(e[1])).map(([t,e])=>({value:t,label:e}))}_lockCandidates(){return Object.keys(this.hass.states).filter(t=>t.startsWith("lock.")&&this._openingEntityAvailable(t)).map(t=>({value:t,label:this.hass.states[t]?.attributes?.friendly_name||t})).sort((t,e)=>t.label.localeCompare(e.label))}_mergeClick(t){const e=this._spaceModel();if(!e)return;const i=e.rooms,s=[...i].reverse().find(e=>this._pointInRoom(t,e));if(!s?.id)return;const n=s.id;if(!this._mergeSel||this._mergeSel===n)return void(this._mergeSel=this._mergeSel===n?null:n);const o=i.find(t=>t.id===this._mergeSel),a=o?hi(o):null,r=hi(s),l=a&&r?function(t,e){if(!t||!e||t.length<3||e.length<3)return null;const i=si(Ri(t),Ri(e));if(1!==i.length)return null;if(1!==i[0].length)return null;const s=i[0][0].slice(0,-1).map(t=>[t[0],t[1]]);return s.length>=3?s:null}(a,r):null;if(!l)return this._showToast(this._t("toast.merge_not_adjacent")),void(this._mergeSel=null);this._mergeDialog={aId:this._mergeSel,bId:n,poly:l,pick:"a"},this._mergeSel=null}_commitMerge(){const t=this._mergeDialog,e=this._curSpaceCfg;if(!t||!e||!this._spaceModel())return;const i=this._geometrySnapshot(),s=this._spaceH,n="a"===t.pick?t.aId:t.bId,o="a"===t.pick?t.bId:t.aId,a=e.rooms.find(t=>t.id===n);a?(a.poly=t.poly.map(t=>[t[0]/Zg,t[1]/s]),delete a.x,delete a.y,delete a.w,delete a.h,e.rooms=e.rooms.filter(t=>t.id!==o),this._commitOpenSpans(),this._recordGeometry(this._t("history.merge_rooms"),i),this._saveConfig(),this._mergeDialog=null,this._regSignature="",this._maybeRebuildDevices(),this._showToast(this._t("toast.rooms_merged",{name:a.name||""}))):this._mergeDialog=null}_splitClick(t){const e=this._spaceModel();if(!e)return;const i=e.rooms;if(!this._splitSel){const e=[...i].reverse().find(e=>this._pointInRoom(t,e));if(!e?.id)return;return void(this._splitSel={roomId:e.id,pts:[]})}const s=i.find(t=>t.id===this._splitSel.roomId),n=s?hi(s):null;if(!s||!n)return void(this._splitSel=null);const o=.02*this._gridPitch,a=6*this._gridPitch,r=function(t,e){if(!e||e.length<2)return null;let i=null,s=1/0;for(let n=0;n=n)continue;n=_;const g=Math.sqrt(u),m=(i>0?Math.max(0,Math.min(g,Math.round(p*g/i)*i)):p*g)/g;s=[a+m*h,r+m*d]}return s}(r,n,this._gridPitch)||r,c=r&&l&&Math.hypot(r[0]-t[0],r[1]-t[1])<=a?l:null,h=!!c&&bi(c,n,o),d=this._splitSel.pts;if(!d.length)return h?void(this._splitSel={...this._splitSel,pts:[c]}):void this._showToast(this._t("toast.split_pick_wall"));if(!h){const e=this._snap(t);return wi(e,n,o)?void(this._splitSel={...this._splitSel,pts:[...d,e]}):void this._showToast(this._t("toast.split_pick_inside"))}const u=Fi(n,[...d,c],o);if(!u)return void this._showToast(this._t("toast.split_bad_cut"));this._resetRoomDialogFields();const[p,_]=u,g=Pi(p)>=Pi(_)?p:_,m=g===p?_:p;this._pendingSplit={roomId:s.id,mainPoly:g,newPoly:m},this._cursorPt=null,this._nameSel="",this._areaSel="",this._roomDialog=!0}get _contourClosed(){return this._path.length>=4&&this._samePt(this._path[0],this._path[this._path.length-1])&&(null!=this._closingWallCm||!this._activeDraftId)}_markupMove(t){if(!this._markup)return;const e=t.pointerType;if(e&&(this._boundaryPointerType=e),"column"===this._tool)return void(this._cursorPt=this._snap(this._svgPoint(t)));if("opening"===this._tool||"boundary"===this._tool||"wallthick"===this._tool)return void(this._cursorPt=this._svgPoint(t));const i="draw"===this._tool&&!this._contourClosed,s="split"===this._tool&&!!this._splitSel?.pts?.length;if(!i&&!s)return;const n=this._svgPoint(t);if(i){const e=this._resolvePlanDrawPoint(n,t.shiftKey);return this._planSnapHover={contextKey:e.contextKey,candidate:e.candidate,conflicts:e.conflicts},this._syncPlanSnapConflictMarkers(e.conflicts),this._path.length?void(this._cursorPt=e.point):void this._syncPlanSnapActiveMarker(e.candidate)}this._cursorPt=this._snap(n)}get _openingPreview(){const t=this._openingPreset;if("opening"!==this._tool||!t||!this._cursorPt)return null;const e=this._cursorPt,i=this._openingHoverCandidate;if(i&&gg(i,[e[0],e[1]],t.revision,this._cfgEpoch))return i;if(this._openingAt(e))return this._openingHoverCandidate=null,null;const s=this._resolveOpeningPlacement(e);return this._openingHoverCandidate=s,s}get _opMeasureView(){return this._opMeasure||this._openingPreview?.measure||null}_saveRoom(){(this._areaSel||this._nameSel.trim())&&(this._wallFaceBatch?this._decideWallFace(!0):this._commitRoom())}_decideWallFace(t){const e=this._wallFaceBatch;if(!e)return;const i=e.candidates[e.index];if(!i)return;if(!t&&(i.existing||i.repair)&&1===e.candidates.length)return this._wallFaceBatch=null,this._roomDialog=!1,this._nameSel="",this._areaSel="",void this.requestUpdate();const s=t?{candidate:i,create:!0,name:this._nameSel.trim(),area:this._areaSel||null,settings:this._roomSettingsFromDialog()?JSON.parse(JSON.stringify(this._roomSettingsFromDialog())):null}:{candidate:i,create:!1},n=[...e.decisions,s],o=e.index+1;if(o"number"==typeof t&&Number.isFinite(t)&&t>=0?t:null,n=.02*this._gridPitch,o=this._spaceModel();if(!o)return fr;for(const e of this._planSnapGeometrySnapshot().value.segments){if("room"===e.sourceKind||Hs(t,[e.a[0],e.a[1],e.b[0],e.b[1]])>n)continue;if("partition"===e.sourceKind)return s(o.partitions.find(t=>t.id===e.sourceId)?.cm)??fr;const i=e.sourceId.lastIndexOf(":"),a=i>=0?e.sourceId.slice(0,i):e.sourceId,r=i>=0?Number(e.sourceId.slice(i+1)):-1;return s(o.room_drafts.find(t=>t.id===a)?.segments[r]?.cm)??fr}const a=jd(Math.max(0,e.length-1),i,this._drawWallCm,fr);for(let i=0;i+1[...t]);if(!e?.sourceKey.startsWith("active:"))return i;const s=/:(\d+)$/.exec(e.sourceKey),n=s?Number(s[1])+("b"===e.endpoint?1:0):-1;return n>=0&&ne.key===t.sourceKey),o=s.find(e=>e.key===t.targetSourceKey);if(!n||!o)return!1;const a="a"===t.endpoint?n.a:n.b;return!(Math.hypot(a[0]-t.from[0],a[1]-t.from[1])>i)&&(!(Hs(t.to,[o.a[0],o.a[1],o.b[0],o.b[1]])>i)&&!function(t,e){if(!t.sourceKey.startsWith("static:partition|"))return!1;const i=t.sourceKey.slice(17).split("|")[0];return!!i&&e.some(t=>"partition"===t.host?.kind&&t.host.id===i)}(t,this._curSpaceCfg?.openings||[]))}_applyWallRepair(t,e){const i=this._curSpaceCfg;if(!i||!this._validateWallRepair(t,e.activePath))return!1;const s=e=>{e[0]=t.to[0]/Zg,e[1]=t.to[1]/Zg};if(t.sourceKey.startsWith("active:")){const n=/:(\d+)$/.exec(t.sourceKey),o=n?Number(n[1])+("b"===t.endpoint?1:0):-1;if(o<0||o>=e.activePath.length)return!1;e.activePath[o]=[...t.to];const a=(i.room_drafts||[]).find(t=>t.id===e.activeDraftId);return a?.points?.[o]&&s(a.points[o]),!0}if(!t.sourceKey.startsWith("static:"))return!1;const[n,o]=t.sourceKey.slice(7).split("|");if("partition"===n){const e=(i.partitions||[]).find(t=>t.id===o);if(!e)return!1;const n=[e.a[0]*Zg,e.a[1]*Zg],a=[e.b[0]*Zg,e.b[1]*Zg],r=Math.hypot(n[0]-t.from[0],n[1]-t.from[1])<=2e-4*this._gridPitch?e.a:Math.hypot(a[0]-t.from[0],a[1]-t.from[1])<=2e-4*this._gridPitch?e.b:null;return!!r&&(s(r),!0)}if("draft"===n){const e=o.lastIndexOf(":"),n=e>=0?o.slice(0,e):"",a=e>=0?Number(o.slice(e+1)):-1,r=(i.room_drafts||[]).find(t=>t.id===n);if(!r?.points?.[a]||!r?.points?.[a+1])return!1;const l=[a,a+1].find(e=>Math.hypot(r.points[e][0]*Zg-t.from[0],r.points[e][1]*Zg-t.from[1])<=2e-4*this._gridPitch);return null!=l&&(s(r.points[l]),!0)}return!1}_applyWallFaceBatch(){const t=this._wallFaceBatch,e=this._curSpaceCfg,i=this._spaceModel();if(!t||!e||!i)return;const s=(t,e)=>{this._showToast(this._t(t,e)),this._roomDialogCancel()},n=t.decisions.filter(t=>t.create),o=n.map(t=>t.candidate.ring),a=i.rooms;for(let t=0;ti.id!==e&&!!hi(i)&&Di(o[t],hi(i)));if(i)return void s("toast.room_overlap",{name:i.name||""})}if((e.rooms||[]).length+n.length>400)return void s("toast.physical_limit");if(n.some(t=>t.candidate.split&&!e.rooms.some(e=>e.id===t.candidate.split.roomId)))return void s("toast.contour_cannot_close");const r=n.map(t=>t.candidate.repair).filter(t=>!!t);if(r.length>1||r[0]&&!this._validateWallRepair(r[0],t.activePath))return void s("toast.wall_repair_changed");const l=this._activePathWithRepair(t.activePath,r[0]),c=2e-4*this._gridPitch,h=new Map;for(let e=0;et.candidate.atomKeys)),e=n.some(t=>t.candidate.consumeAllActive);for(const i of uu(this._wallGraphSources(l),c)){const s=i.sourceKeys.find(t=>h.has(t));!s||e||t.has(i.key)||d.push({a:i.a,b:i.b,cm:h.get(s)})}}else d.push(...Ud(l,jd(l.length-1,t.activeCms,this._drawWallCm,fr)));if((e.partitions||[]).length+d.length>im)return void s("toast.physical_limit");const u=this._geometrySnapshot();if(r[0]&&!this._applyWallRepair(r[0],t))return void s("toast.wall_repair_changed");const p=n.some(t=>!!t.candidate.split),_=p?al(i.rooms,e.walls,this._openCuts(),this._wallKeyPitch,this._cellCm,this._gridPitch,Zg):null,g=p&&Array.isArray(e.walls)?e.walls:null;for(const t of n){const i=t.candidate.split;if(!i)continue;const n=e.rooms.find(t=>t.id===i.roomId);if(!n)return void s("toast.contour_cannot_close");n.poly=i.mainPoly.map(t=>[t[0]/Zg,t[1]/this._spaceH]),delete n.x,delete n.y,delete n.w,delete n.h}const m=Date.now().toString(36),f=[];if(n.forEach((t,i)=>{const s=t.area?this.hass.areas[t.area]?.name:"",n={id:`r${m}-${i}`,name:t.name||s||this._t("room.default_name"),area:t.area||null,poly:t.candidate.ring.map(t=>[t[0]/Zg,t[1]/this._spaceH]),...t.settings?{settings:JSON.parse(JSON.stringify(t.settings))}:{}};e.rooms.push(n),f.push({room:n,decision:t})}),t.activeDraftId&&Array.isArray(e.room_drafts)&&(e.room_drafts=e.room_drafts.filter(e=>e.id!==t.activeDraftId),e.room_drafts.length||delete e.room_drafts),d.length&&(e.partitions||=[],d.forEach((t,i)=>e.partitions.push({id:`partition-${m}-${i}`,a:[t.a[0]/Zg,t.a[1]/Zg],b:[t.b[0]/Zg,t.b[1]/Zg],cm:t.cm}))),p){this._commitOpenSpans();const t=this._normalizeWalls(_,this._openCuts());t.length?e.walls=t:g?.length?e.walls=g:delete e.walls}if(f.length){this._cfgEpoch++;const i=this._openCuts(),s=this._spaceModel();if(!s)return;let n=e.walls;for(const{room:e,decision:o}of f){const a=o.candidate.ring,r=this._wallSourceCmAt(a[0],t.activePath,t.activeCms);n=Lr(n,s.rooms,e.id,r,this._wallKeyPitch,i,Zg);for(const o of ol(s.rooms,n,i,this._wallKeyPitch,this._cellCm,this._gridPitch,Zg)){if(o.roomId!==e.id||"outer"!==o.kind)continue;const i=[(o.a[0]+o.b[0])/2,(o.a[1]+o.b[1])/2];n=Nr(n,o.a,o.b,this._wallSourceCmAt(i,t.activePath,t.activeCms),this._wallKeyPitch,Zg)}}const o=this._normalizeWalls(n,i);o.length?e.walls=o:delete e.walls}this._recordGeometry(this._t("history.wall_face_batch"),u),this._saveConfig(),delete this._resumeDraftBySpace[this._space],this._path=[],this._activeDraftId=null,this._draftSegmentCms=[],this._closingWallCm=null,this._wallFaceBatch=null,this._roomDialog=!1,this._nameSel="",this._areaSel="",this._regSignature="",this._maybeRebuildDevices();const v=new Set(n.map(t=>t.area).filter(t=>!!t));if(v.size){const t={...this._layout};for(const e of this._devices){if(!v.has(e.area||"")||e.space!==this._space)continue;if(this._layout[e.id])continue;const i=this._defPos[e.id];i&&(t[e.id]={s:this._space,x:i.x/Zg,y:i.y/Zg},this._dirtyPos.add(e.id))}this._layout=t,this._persistLayout()}this._showToast(this._t(n.length?"toast.wall_rooms_saved":"toast.wall_chain_saved",{n:n.length}))}_commitRoom(){const t=this._curSpaceCfg,e=this._spaceModel();if(!t||!e)return;const i=this._geometrySnapshot(),s=this._spaceH,n=!!this._pendingSplit,o=n?al(e.rooms,t.walls,this._openCuts(),this._wallKeyPitch,this._cellCm,this._gridPitch,Zg):null,a=n&&Array.isArray(t.walls)?t.walls:null;let r;if(this._pendingSplit){const e=t.rooms.find(t=>t.id===this._pendingSplit.roomId);if(!e)return this._pendingSplit=null,this._splitSel=null,void(this._roomDialog=!1);e.poly=this._pendingSplit.mainPoly.map(t=>[t[0]/Zg,t[1]/s]),delete e.x,delete e.y,delete e.w,delete e.h,r=this._pendingSplit.newPoly}else{if(!this._contourClosed)return;r=this._path.slice(0,-1)}const l=this._areaSel?this.hass.areas[this._areaSel]?.name:"",c={id:"r"+Date.now().toString(36),name:this._nameSel||l||this._t("room.default_name"),area:this._areaSel||null,poly:r.map(t=>[t[0]/Zg,t[1]/s]),...this._roomSettingsFromDialog()?{settings:this._roomSettingsFromDialog()}:{}};if(t.rooms.push(c),!n&&this._activeDraftId&&Array.isArray(t.room_drafts)&&(t.room_drafts=t.room_drafts.filter(t=>t.id!==this._activeDraftId),t.room_drafts.length||delete t.room_drafts),n){this._commitOpenSpans();const e=this._normalizeWalls(o,this._openCuts());e.length?t.walls=e:a?.length?t.walls=a:delete t.walls}if(!n){const e=jd(r.length,[...this._draftSegmentCms,this._closingWallCm??void 0],this._drawWallCm,fr),i=e[0];if(null!=i){this._cfgEpoch++;const s=this._openCuts(),n=this._spaceModel();if(!n)return;let o=Lr(t.walls,n.rooms,c.id,i,this._wallKeyPitch,s,Zg);for(const t of ol(n.rooms,o,s,this._wallKeyPitch,this._cellCm,this._gridPitch,Zg)){if(t.roomId!==c.id||"outer"!==t.kind)continue;const i=[(t.a[0]+t.b[0])/2,(t.a[1]+t.b[1])/2],s=r.findIndex((t,e)=>{const s=r[(e+1)%r.length];return Hs(i,[t[0],t[1],s[0],s[1]])<=.02*this._gridPitch});s>=0&&(o=Nr(o,t.a,t.b,e[s],this._wallKeyPitch,Zg))}o=this._normalizeWalls(o,s),o.length?t.walls=o:delete t.walls}}this._recordGeometry(this._t(n?"history.split_room":"history.add_room"),i),this._saveConfig(),this._path=[],delete this._resumeDraftBySpace[this._space],this._activeDraftId=null,this._draftSegmentCms=[],this._closingWallCm=null,this._pendingSplit=null,this._splitSel=null;const h=this._areaSel;this._areaSel="",this._nameSel="",this._roomDialog=!1,this._regSignature="",this._maybeRebuildDevices();let d=0;if(h){const t=Zg,e={...this._layout};for(const i of this._devices){if(i.area!==h||i.space!==this._space)continue;if(d++,this._layout[i.id])continue;const s=this._defPos[i.id];s&&(e[i.id]={s:this._space,x:s.x/Zg,y:s.y/t},this._dirtyPos.add(i.id))}this._layout=e,this._persistLayout()}const u=this._model.find(t=>t.id===this._space)?.rooms.length||0;this._showToast(h?this._t("toast.room_saved",{n:u,added:d}):this._t("toast.room_saved_no_area",{n:u}))}_cancelPath(){this._wallRepairDiagnostic=null,this._activeDraftId&&(this._resumeDraftBySpace[this._space]=this._activeDraftId),this._path=[],this._activeDraftId=null,this._draftSegmentCms=[],this._closingWallCm=null,this._clearPlanSnapHover(),this._roomDialog=!1,this._pendingSplit=null,this._wallFaceBatch=null,this._splitSel=null,this._mergeSel=null,this._mergeDialog=null,this._openWallAnchor=null,this._boundaryRestoreGuard=null,this._physicalSel=null,this._physicalDrag=null,this._physicalRotate=null,this._clearOpeningPlacement(!0)}_resumeLastDraft(){const t=this._resumeDraftBySpace[this._space];if(!t)return;const e=this._spaceModel()?.room_drafts.find(e=>e.id===t);e?(this._activeDraftId=t,this._path=e.points.map(t=>[...t]),this._draftSegmentCms=this._adoptDraftCms(this._path,e.segments.map(t=>t.cm),e.id),this._clearPlanSnapHover()):delete this._resumeDraftBySpace[this._space]}_roomDialogCancel(){if(this._roomDialog=!1,this._roomEditId)return this._roomEditId=null,this._nameSel="",void(this._areaSel="");if(this._wallFaceBatch){const t=this._wallFaceBatch;return this._wallFaceBatch=null,this._path=t.activePath.map(t=>[...t]),this._draftSegmentCms=[...t.activeCms],this._activeDraftId=t.activeDraftId,this._nameSel="",this._areaSel="",void this.requestUpdate()}if(this._pendingSplit)return this._pendingSplit=null,void(this._splitSel=null);this._undoPoint()}get _freeAreas(){const t=new Set;for(const e of this._serverCfg?.spaces||[])for(const i of e.rooms||[])i.area&&t.add(i.area);for(const e of this._wallFaceBatch?.decisions||[])e.create&&e.area&&t.add(e.area);return Object.values(this.hass?.areas||{}).filter(e=>!t.has(e.area_id)).sort((t,e)=>(t.name||"").localeCompare(e.name||""))}_openMarkerDialog(t){if(this._vacAllCamerasFor=null,this._vacAllCameraCache=null,t&&this._ackNewDevice(t.id),this._norm)if(t){const e=t.marker,i=Object.prototype.hasOwnProperty.call(e||{},"is_light"),s=Object.prototype.hasOwnProperty.call(e||{},"light_entity"),n=Object.prototype.hasOwnProperty.call(e||{},"glow_color"),o=Object.prototype.hasOwnProperty.call(e||{},"value_badge"),a=Object.prototype.hasOwnProperty.call(e||{},"tap_action"),r=Object.prototype.hasOwnProperty.call(e||{},"toggle_entity"),l=ks(e?.glow_color),c=this._devicePresentation(t,!0).valueBadge,h=Wo(this._planHass,t,this._devices),d=jo(this._planHass,t,h);this._markerDialog={devId:t.id,name:t.name,binding:"virtual"===t.bindingKind?"virtual":t.bindingKind+":"+t.bindingRef,bindingMode:"virtual"===t.bindingKind?"virtual":"ha",bindingOpen:!1,showEntities:"entity"===t.bindingKind&&!!this._fullRegistryHass.entities[t.bindingRef||""]?.device_id,bindingFilter:"",icon:t.marker?.icon||"",autoIcon:t.icon||"",display:Bi(t.marker?.display),rippleColor:Rt(t.marker?.ripple_color,""),rippleSize:Number(t.marker?.ripple_size)>0?Number(t.marker.ripple_size):1.5,size:Number(t.marker?.size)>0?Number(t.marker.size):1,angle:Number(t.marker?.angle)||0,tapAction:hd(t.marker?.tap_action,t.primary?.split(".")[0]),tapActionTouched:!1,originalHasTapAction:a,originalTapAction:t.marker?.tap_action,tapHintAnnouncement:"",toggleEntity:e?.toggle_entity||"",toggleEntityTouched:!1,originalHasToggleEntity:r,originalToggleEntity:e?.toggle_entity,tapTarget:t.marker?.tap_target||"",tapConfirm:!0===t.marker?.tap_confirm,runFilter:"",controls:Zn(t.marker?.binding,t.marker?.controls,t.entities),controlsFilter:"",lightRole:!0===e?.is_light?"always":!1===e?.is_light?"never":"auto",lightRoleTouched:!1,originalHasIsLight:i,originalIsLight:e?.is_light,lightEntity:e?.light_entity||"",lightEntityTouched:!1,originalHasLightEntity:s,originalLightEntity:e?.light_entity,glowMode:null!=l?.bri?"fixed":l?"color":"auto",glowColor:l?.c||this._fillColors.glow_light.c,glowBrightness:Math.max(1,Math.round(100*(l?.bri??1))),glowColorDrafted:!!l,glowBrightnessDrafted:null!=l?.bri,glowTouched:!1,originalHasGlowColor:n&&(!!l||null===e?.glow_color),originalGlowColor:l||(null===e?.glow_color?null:void 0),valueBadgeEnabled:o?!0===e?.value_badge?.enabled:!!c,valueBadgeSource:e?.value_badge?.source||c?.source||d,valueBadgePosition:e?.value_badge?.position||c?.position||"right",valueBadgeTouched:!1,originalHasValueBadge:o,originalValueBadge:e?.value_badge,useClimateTemp:!0===t.marker?.use_climate_temp,glowRadius:Number(t.marker?.glow_radius_cm)>0?String(this._imperial?Math.round(Number(t.marker.glow_radius_cm)/30.48*10)/10:Math.round(Number(t.marker.glow_radius_cm))/100):"",model:t.model||"",link:t.link||"",description:t.description||"",pdfs:[...t.pdfs||[]],room:t.marker?.room_id?t.space+"#@"+t.marker.room_id:t.space&&t.area?t.space+"#"+t.area:"",hideFromPlan:!0===t.marker?.hidden,busy:!1}}else this._markerDialog={name:"",binding:"virtual",bindingMode:"virtual",bindingOpen:!1,showEntities:!1,bindingFilter:"",icon:"",autoIcon:"",display:"badge",rippleColor:"",rippleSize:1.5,size:1,angle:0,tapAction:"info",tapActionTouched:!1,originalHasTapAction:!1,originalTapAction:void 0,tapHintAnnouncement:"",toggleEntity:"",toggleEntityTouched:!1,originalHasToggleEntity:!1,originalToggleEntity:void 0,tapTarget:"",tapConfirm:!1,runFilter:"",controls:[],controlsFilter:"",lightRole:"auto",lightRoleTouched:!1,originalHasIsLight:!1,originalIsLight:void 0,lightEntity:"",lightEntityTouched:!1,originalHasLightEntity:!1,originalLightEntity:void 0,glowMode:"auto",glowColor:this._fillColors.glow_light.c,glowBrightness:100,glowColorDrafted:!1,glowBrightnessDrafted:!1,glowTouched:!1,originalHasGlowColor:!1,originalGlowColor:void 0,valueBadgeEnabled:!1,valueBadgeSource:null,valueBadgePosition:"right",valueBadgeTouched:!1,originalHasValueBadge:!1,originalValueBadge:void 0,useClimateTemp:!1,glowRadius:"",model:"",link:"",description:"",pdfs:[],room:"",hideFromPlan:!1,busy:!1,uploadId:"up_"+Date.now().toString(36)+Math.random().toString(36).slice(2,6)};else this._showToast(this._t("toast.marker_needs_server"))}_runCandidates(){const t=[];for(const e of Gi)for(const[i,s]of Object.entries(this.hass.states))i.startsWith(e+".")&&this._planEntityAvailable(i)&&t.push({value:i,label:s?.attributes?.friendly_name||i,sub:this._t("run."+e)});return t.sort((t,e)=>t.sub.localeCompare(e.sub)||t.label.localeCompare(e.label))}_bindingCandidates(){const t=this._planHass,e=wo(this._markers),i=new Set(this._markers.filter(t=>t.removed).map(t=>t.binding)),s=new Set;for(const t of this._devices)t.id!==this._markerDialog?.devId&&("device"===t.bindingKind&&t.bindingRef&&s.add("device:"+t.bindingRef),"entity"===t.bindingKind&&t.bindingRef&&s.add("entity:"+t.bindingRef));const n=new Set;for(const t of this._devices)"device"===t.bindingKind&&t.name&&n.add(t.name.trim()+"|"+(t.area||""));const o=[];for(const e of Object.values(t.devices)){if("service"===e.entry_type)continue;const t="device:"+e.id;if(s.has(t))continue;const a=(e.name_by_user||e.name||e.id).trim();t!==this._markerDialog?.binding&&!i.has(t)&&n.has(a+"|"+(e.area_id||""))||o.push({value:t,label:a,sub:(e.model||this._t("marker.sub_device"))+("Group"===e.model?this._t("marker.sub_z2m_group"):"")})}const a=new Set(["group","template","derivative","min_max","threshold","integration","statistics","trend","utility_meter","tod","switch_as_x","schedule"]);for(const[n,r]of Object.entries(t.entities)){const l="entity:"+n;if(s.has(l))continue;if(ko(t,n,e)&&!i.has(l))continue;const c=a.has(r.platform),h="group"===r.platform;if(!c&&!h)continue;if(r.hidden&&!i.has(l))continue;const d=t.states[n];o.push({value:l,label:r.name||d?.attributes?.friendly_name||n,sub:n.split(".")[0]+" · "+("group"===r.platform?this._t("marker.sub_group"):this._t("marker.sub_helper"))})}if(this._markerDialog?.showEntities){const n=new Set(o.map(t=>t.value));for(const[a,r]of Object.entries(t.entities)){const l="entity:"+a;if(s.has(l)||n.has(l)||r.hidden&&!i.has(l))continue;if(ko(t,a,e)&&!i.has(l))continue;const c=t.states[a],h=r.name||c?.attributes?.friendly_name||a,d=r.device_id?t.devices[r.device_id]:null,u=d&&(d.name_by_user||d.name)||"";o.push({value:l,label:h,sub:a.split(".")[0]+" · "+this._t("marker.sub_entity")+(u?" · "+u:"")})}}const r=(this._markerDialog?.bindingFilter||"").toLowerCase().trim(),l=r?o.filter(t=>(t.label+" "+t.sub+" "+t.value).toLowerCase().includes(r)):o;return l.sort((t,e)=>t.label.localeCompare(e.label)),l.slice(0,200)}_physicalBodiesR(t=this._spaceModel()){if(!t)return[];const e=`${t.id}|${this._cfgEpoch}|${this._cellCm}|${this._gridPitch}`;if(this._physicalBodiesCache?.key===e)return this._physicalBodiesCache.all;const i=Bl(t,this._cellCm,this._gridPitch,2e-4*this._gridPitch,this._partitionOpeningCuts(t));return this._physicalBodiesCache={key:e,...i},i.all}_rawPhysicalBodiesR(t=this._spaceModel()){if(!t)return[];this._physicalBodiesR(t);const e=this._physicalBodiesCache;return e?[...e.drafts,...e.partitions,...e.columns]:[]}_cleanFloor(t,e,i=this._spaceModel()){if(!i)return{floor:e,geom:null,path:"",area:Vl([[[...e,e[0]]]])};const s=t.id||`#${i.rooms.indexOf(t)}`,n=`${i.id}|${this._cfgEpoch}|${s}`;if(!this._rszPreview){const t=Hg(this._cleanFloorCache,n);if(t.hit)return t.value}const o=e.map(t=>t[0]),a=e.map(t=>t[1]),r=[Math.min(...o),Math.min(...a),Math.max(...o),Math.max(...a)],l=this._physicalBodiesR(i).filter(t=>{const e=t.map(t=>t[0]),i=t.map(t=>t[1]);return Math.max(...e)>=r[0]&&Math.min(...e)<=r[2]&&Math.max(...i)>=r[1]&&Math.min(...i)<=r[3]}),c=l.length?Gl(e,l):null,h={floor:e,geom:c,path:c?Ol(c):"",area:Vl(c||[[[...e,e[0]]]])};return this._rszPreview||Lg(this._cleanFloorCache,n,h,600),h}_autoIconForBinding(t){if("virtual"===t)return"mdi:map-marker";const[e,i]=t.split(":");if(!i)return"";const s=this._fullRegistryHass,n=this._bindingStatus(t),o="active"===n.kind?n.enabledEntityIds:n.allEntityIds;if("device"===e){const t=s.devices?.[i];if(!t)return"mdi:help-circle";const e=o;return e.some(t=>t.startsWith("lock."))?"mdi:lock":bo(s,t.name_by_user||t.name||"",t.model,e,this._iconRules)}if("entity"===e){const t=s.entities?.[i],e=this.hass.states?.[i],n=t?.name||e?.attributes?.friendly_name||i;return i.startsWith("lock.")?"mdi:lock":bo(s,n,"",[i],this._iconRules)}return""}_allRoomsFlat(){const t=[];for(const e of this._serverCfg?.spaces||[])for(const i of e.rooms||[])i.area?t.push({value:e.id+"#"+i.area,label:(e.title||e.id)+" · "+i.name}):i.id&&t.push({value:e.id+"#@"+i.id,label:(e.title||e.id)+" · "+i.name+" · "+this._t("marker.subarea")});return t}_errText(t){if(!t)return this._t("err.unknown");if("string"==typeof t)return t;if("invalid_passage_fields"===t.code){const e=String(t.message||t.error||"").match(/space=([^;]*);\s*opening=([^;]*);\s*fields=([^;]*)/);if(e){const t=this._serverCfg?.spaces?.find(t=>String(t.id)===e[1]),i={contact:"opening.contact_label",lock:"opening.lock_label",invert:"opening.invert",flip_h:"opening.flip_h",flip_v:"opening.flip_v"},s=e[3].split(",").filter(Boolean).map(t=>i[t]?this._t(i[t]):t).join(", ");return this._t("opening.invalid_passage_fields",{room:t?.title||e[1],fields:s})}}if("invalid_partition_opening_jamb_margin"===t.code){const e=String(t.message||t.error||"").match(/margin_cm=([^;]*)/),i=e?Number(e[1]):NaN;if(Number.isFinite(i))return this._t("opening.partition_jamb_margin",{distance:li(i,this._imperial)})}if(t.message)return t.message;if(t.error)return t.error;if(null!=t.code)return this._t("err.code",{code:t.code});try{return JSON.stringify(t)}catch{return String(t)}}_backupErrorText(t){const e=t?.code??t?.error;if("string"==typeof e){const t=`backup.error.${e}`,i=this._t(t);if(i!==t)return i}return this._errText(t)}async _pickMarkerFiles(t){const e=t.target,i=e.files?[...e.files]:[];if(e.value="",!i.length||!this._markerDialog)return;const s=this._markerDialog.uploadId||this._markerDialog.devId||"new",n=[];for(const t of i)try{const e=new FormData;e.append("marker_id",s),e.append("file",t,t.name);const i=this.hass?.fetchWithAuth?await this.hass.fetchWithAuth("/api/houseplan/upload",{method:"POST",body:e}):await fetch("/api/houseplan/upload",{method:"POST",body:e,headers:this.hass?.auth?.data?.access_token?{authorization:`Bearer ${this.hass.auth.data.access_token}`}:{}}),o=await i.json().catch(()=>({}));if(!i.ok||o.error){const t={too_large:this._t("err.too_large",{mb:o.max_mb||50}),bad_ext:this._t("err.bad_ext"),unauthorized:this._t("err.unauthorized")};throw new Error(t[o.error]||o.error||"HTTP "+i.status)}n.push({name:o.name||t.name,url:o.url})}catch(e){this._showToast(this._t("toast.file_failed",{name:t.name,err:this._errText(e)}))}n.length&&this._markerDialog&&(this._markerDialog={...this._markerDialog,pdfs:[...this._markerDialog.pdfs,...n]},this._showToast(this._t("toast.files_attached",{n:n.length})))}_removeMarkerPdf(t){this._markerDialog&&(this._markerDialog={...this._markerDialog,pdfs:this._markerDialog.pdfs.filter(e=>e.url!==t)})}_markerLightFields(t){const e={};if(t.lightRoleTouched?"always"===t.lightRole?e.is_light=!0:"never"===t.lightRole&&(e.is_light=!1):t.originalHasIsLight&&(e.is_light=t.originalIsLight??null),t.lightEntityTouched?t.lightEntity&&(e.light_entity=t.lightEntity):t.originalHasLightEntity&&(e.light_entity=t.originalLightEntity??null),t.glowTouched){if("auto"!==t.glowMode){const i={c:Rt(t.glowColor,this._fillColors.glow_light.c)};"fixed"===t.glowMode&&(i.bri=Math.max(.01,Math.min(1,Math.round(t.glowBrightness)/100))),e.glow_color=i}}else t.originalHasGlowColor&&(e.glow_color=t.originalGlowColor??null);return e}_markerTapActionFields(t){return t.tapActionTouched?{tap_action:t.tapAction||null}:t.originalHasTapAction?{tap_action:t.originalTapAction??null}:{}}_markerToggleEntityFields(t){return(e={touched:t.toggleEntityTouched,originalHas:t.originalHasToggleEntity,original:t.originalToggleEntity,value:t.toggleEntity}).touched?e.value?{toggle_entity:e.value}:{}:e.originalHas?{toggle_entity:e.original??null}:{};var e}async _saveMarker(){const t=this._markerDialog;if(!t||t.busy)return;const e=this._effectiveMarkerTapAction(t);if("ha"===t.bindingMode&&(!t.binding||"virtual"===t.binding))return;if("virtual"===t.binding&&!t.name.trim())return void this._showToast(this._t("toast.virtual_name_required"));if("run"===e&&!t.tapTarget)return void this._showToast(this._t("toast.run_target_required"));if(t.valueBadgeTouched&&t.valueBadgeEnabled&&!t.valueBadgeSource)return void this._showToast(this._t("toast.value_badge_source_required"));if("ha"===t.bindingMode){const e=this._bindingStatus(t.binding),i=t.devId?this._markers.find(e=>e.id===t.devId):null,s=!i||i.binding!==t.binding;if("active"!==e.kind&&s)return void this._showToast(this._t("ha_disabled"===e.kind?"toast.ha_disabled_add":"toast.ha_binding_unverified"));if("ha_disabled"===e.kind&&!0===i?.hidden&&!t.hideFromPlan)return this._markerDialog={...t,hideFromPlan:!0},void this._showToast(this._t("entity"===e.reason?"toast.ha_disabled_show_entity":"toast.ha_disabled_show_device"))}const i=this._serverCfg;if(!i)return;const s=i.markers||[],n=qs(t.room);let o=n?.space||null;const a=n?.area||null,r=n?.roomId||null,l=Ei(t.binding,t.devId,()=>"v_"+Date.now().toString(36)),c=t.devId,h=c?this._devices.find(t=>t.id===c):null,d=n?.space||h?.space||null,u=d?this._spaceModelById(d):this._spaceModel();if(!u)return;const p=u.id;"virtual"!==t.binding||o||(o=p),this._markerDialog={...t,busy:!0};try{const n="virtual"===t.binding?[]:s.filter(e=>e.removed&&e.binding===t.binding).map(t=>t.id),d=n.length>0,_=Zn(t.binding,t.controls,this._bindingEntities(t.binding)),g=s.find(t=>t.id===l||t.id===c)?.vacuum||null,m={id:l,vacuum:g,binding:t.binding,name:t.name.trim()||null,icon:t.icon||null,display:"badge"!==t.display?t.display:null,ripple_color:"icon_ripple"===t.display&&t.rippleColor?t.rippleColor:null,ripple_size:"icon_ripple"===t.display&&1.5!==t.rippleSize?t.rippleSize:null,size:1!==t.size?t.size:null,angle:t.angle?t.angle:null,...this._markerTapActionFields(t),...this._markerToggleEntityFields(t),tap_target:"run"===e&&t.tapTarget||null,tap_confirm:!!t.tapConfirm||null,controls:_.length?_:null,...this._markerLightFields(t),...this._markerValueBadgeFields(t),use_climate_temp:!!t.useClimateTemp||null,glow_radius_cm:(()=>{const e=Ng(t.glowRadius);return null==e||e<=0?null:Math.round(this._imperial?30.48*e:100*e)})(),model:t.model.trim()||null,link:t.link.trim()||null,description:t.description.trim()||null,pdfs:t.pdfs,hidden:!!t.hideFromPlan};("virtual"===t.binding||t.room)&&(m.space=o,m.area=a,m.room_id=r);const f=h?.marker?.room_id??null,v=!!t.room&&null!=h&&(h.space!==o||h.area!==a||f!==r);let y=!1;const b=t.uploadId||c;if(b&&b!==l&&m.pdfs?.length)try{const t=await this.hass.callWS({type:"houseplan/files/migrate",from_id:b,to_id:l}),e=t?.mapping||{};m.pdfs=function(t,e,i,s){if(!e||!i||e===i)return t;const n="/files/"+e+"/",o="/files/"+i+"/";return t.map(t=>{if(!t.url.includes(n))return t;const e=t.url.split(n)[1]||"",[i,a]=[e.split("?")[0],e.includes("?")?"?"+e.split("?")[1]:""];if(s){const e=s[decodeURIComponent(i)]??s[i];return e?{...t,url:t.url.split(n+i)[0]+o+encodeURIComponent(e)+a}:t}return{...t,url:t.url.split(n).join(o)}})}(m.pdfs,b,l,e),y=Object.keys(e).length>0}catch(t){this._showToast(this._t("toast.files_migrate_failed",{err:this._errText(t)}))}i.markers=s,c&&c!==l&&(i.markers=function(t,e,i){if(!e||!i||e===i)return[...t];const s=`marker:${e}`,n=`marker:${i}`;return t.map(t=>{const e=Array.isArray(t.controls)?t.controls.map(t=>t===s?n:t):t.controls,i="derived_marker_state"===t.value_badge?.source?.kind&&t.value_badge.source.ref===s?{...t.value_badge,source:{...t.value_badge.source,ref:n}}:t.value_badge;return e===t.controls&&i===t.value_badge?t:{...t,controls:e,value_badge:i}})}(i.markers,c,l)),c&&c!==l&&"derived_marker_state"===m.value_badge?.source?.kind&&m.value_badge.source.ref===`marker:${c}`&&(m.value_badge.source={kind:"derived_marker_state",ref:`marker:${l}`}),i.markers=i.markers.filter(t=>t.id!==l&&t.id!==c&&("virtual"===m.binding||t.binding!==m.binding)),i.markers.push(m);let w=null;const k=c?this._layout[c]:null,x=k?{s:k.s||h?.space||this._space,x:k.x,y:k.y}:c&&h&&this._defPos[c]?this._normPos(h.space,this._defPos[c].x,this._defPos[c].y):null;if(!d&&x&&x.s===p)l===c&&this._layout[l]&&!v||(w={s:x.s,x:x.x,y:x.y},this._layout={...this._layout,[l]:w});else if(d||!this._layout[l]||v){let t=u.vb[0]+u.vb[2]/2,e=u.vb[1]+u.vb[3]/2;const i=r?u.rooms.find(t=>t.id===r):a?u.rooms.find(t=>t.area===a):void 0;i&&([t,e]=this._roomCenter(i)),w=this._normPos(p,t,e),this._layout={...this._layout,[l]:w}}await this._saveConfigNow(),w&&this._noteLayoutRev(await this.hass.callWS({type:"houseplan/layout/update",device_id:l,pos:w}));const $=new Set(n);c&&c!==l&&$.add(c),$.delete(l);for(const t of $)delete this._layout[t],await this.hass.callWS({type:"houseplan/layout/delete",device_id:t}).then(t=>this._noteLayoutRev(t)).catch(()=>{});y&&b&&await this.hass.callWS({type:"houseplan/files/cleanup",marker_id:b}).catch(()=>{}),this._markerDialog=null,this._regSignature="",this._maybeRebuildDevices(),this._showToast(this._t("toast.marker_saved"))}catch(t){this._markerDialog&&(this._markerDialog={...this._markerDialog,busy:!1}),this._showToast(this._t("toast.error",{err:this._errText(t)}))}}async _deleteMarker(){const t=this._markerDialog;if(!t||t.busy||!t.devId)return;const e=t.devId?this._devices.find(e=>e.id===t.devId):null;if(!e)return;const i=t.name||this._t("device.fallback");if(!confirm(this._t("confirm.remove_marker",{name:i})))return;const s=this._serverCfg;s.markers=s.markers||[];const n=s.markers,o="virtual"===e.bindingKind?"virtual":e.bindingKind&&e.bindingRef?`${e.bindingKind}:${e.bindingRef}`:"";if(!o)return;const a=function(t,e,i,s){const n=new Set([e]),o=t.filter(t=>{const o=t.id===e||!s&&t.binding===i;return o&&n.add(t.id),!o});return{markers:s?o:[...o,{id:e,binding:i,removed:!0,hidden:!0}],cleanupIds:n}}(s.markers,e.id,o,"virtual"===e.bindingKind);var r,l;s.markers=(r=a.markers,l=a.cleanupIds,r.map(t=>{if(!Array.isArray(t.controls))return t;const e=t.controls.filter(t=>!("string"==typeof t&&t.startsWith("marker:")&&l.has(t.slice(7))));return e.length===t.controls.length?t:{...t,controls:e.length?e:null}}));const c=a.cleanupIds;this._markerDialog={...t,busy:!0};try{await this._saveConfigNow();for(const t of c){delete this._layout[t],delete this._defPos[t],this._dirtyPos.delete(t),this._sentPos.delete(t);const e=this._activityRt.get(t);e&&clearTimeout(e.timer),this._activityRt.delete(t),this._vacRt.delete(t),delete this._vacSrvTrails[t],await this.hass.callWS({type:"houseplan/layout/delete",device_id:t}).then(t=>this._noteLayoutRev(t)).catch(()=>{}),await this.hass.callWS({type:"houseplan/files/cleanup",marker_id:t}).catch(()=>{}),await this.hass.callWS({type:"houseplan/trail/delete",marker_id:t}).catch(()=>{})}this._markerDialog=null,this._infoCard?.id===e.id&&this._closeInfoCard(),this._selId===e.id&&(this._selId=null),this._drag?.id===e.id&&(this._drag=null),this._regSignature="",this._maybeRebuildDevices(),this._showToast(this._t("toast.marker_removed"))}catch(t){this._serverCfg===s&&(s.markers=n),this._markerDialog&&(this._markerDialog={...this._markerDialog,busy:!1}),this._showToast(this._t("toast.error",{err:this._errText(t)}))}}_normPos(t,e,i){return{s:t,x:e/Zg,y:i/Zg}}_openSpaceDialog(t,e){if(this._serverStorage&&this._serverCfg)if("edit"===t){const i=this._serverCfg.spaces.find(t=>t.id===e);if(!i)return;const s=cs(i),n=i.settings?.custom_fill&&"object"==typeof i.settings.custom_fill?rs(i.settings.custom_fill):null,o="none"===s.fill?{...n||as,a:0}:n;this._spaceDialog={mode:t,spaceId:e,title:i.title,planUrl:i.plan_url||null,planFile:null,source:i.plan_url?"file":"draw",showBorders:s.showBorders,showNames:s.showNames,displayTouched:!0,hideDecor:s.hideDecor,hideOpenings:s.hideOpenings,roomColor:s.color,roomOpacity:s.opacity,fillMode:"none"===s.fill?"custom":s.fill,customFill:o,glowEnabled:s.glow,bgColor:s.bgColor,bgMode:"static"===i.settings?.bg_mode||"daynight"===i.settings?.bg_mode?i.settings.bg_mode:null,northDeg:Za({},i.settings),sunRays:"boolean"==typeof i.settings?.sun_rays?i.settings.sun_rays:null,tempMin:s.tempMin,tempMax:s.tempMax,showLqi:s.showLqi??this._config?.show_signal??!0,cardFontScale:s.cardFontScale,labelTemp:s.labelTemp,labelHum:s.labelHum,labelLqi:s.labelLqi,labelLight:s.labelLight,cellCm:Number(i.cell_cm)>0?Number(i.cell_cm):5,cellCmInput:ic(Number(i.cell_cm)>0?Number(i.cell_cm):5,this._imperial),cellCmTouched:!1,busy:!1}}else this._spaceDialog={mode:t,title:"",planUrl:null,planFile:null,...xh(),hideDecor:!1,hideOpenings:!1,roomColor:ns,roomOpacity:os,fillMode:"custom",customFill:{...as,a:0},glowEnabled:!0,bgColor:null,bgMode:"daynight",northDeg:null,sunRays:null,tempMin:20,tempMax:25,showLqi:this._config?.show_signal??!0,cardFontScale:1,labelTemp:!1,labelHum:!1,labelLqi:!1,labelLight:!1,cellCm:ec(this._imperial),cellCmInput:ic(ec(this._imperial),this._imperial),cellCmTouched:!1,busy:!1};else this._showToast(this._t("toast.integration_missing"))}async _pickPlanFile(t){const e=t.target,i=e.files?.[0];if(!i||!this._spaceDialog)return;const s={"image/svg+xml":"svg","image/png":"png","image/jpeg":"jpg","image/webp":"webp"}[i.type]||(i.name.toLowerCase().endsWith(".svg")?"svg":"");if(!s)return void this._showToast(this._t("toast.plan_formats"));const n=new Uint8Array(await i.arrayBuffer());let o="";for(let t=0;t{const e=new Image;e.onload=()=>t(e.naturalWidth&&e.naturalHeight?e.naturalWidth/e.naturalHeight:1.414),e.onerror=()=>t(1.414),e.src=r});URL.revokeObjectURL(r),this._spaceDialog={...this._spaceDialog,planFile:{ext:s,b64:a,aspect:l,name:i.name}}}_useServerPlan(t){const e=this._spaceDialog;e&&(this._spaceDialog={...e,planUrl:t,planFile:null,pickSaved:!1,savedAspect:void 0},this._aspectJob=this._readPlanAspect(t))}async _readPlanAspect(t){for(let e=0;e<40;e++){const e=this._display(t);if(e){const i=await new Promise(t=>{const i=new Image;i.onload=()=>t(i.naturalWidth&&i.naturalHeight?i.naturalWidth/i.naturalHeight:0),i.onerror=()=>t(0),i.src=e}),s=this._spaceDialog;return s&&s.planUrl===t&&Number.isFinite(i)&&i>0?(this._spaceDialog={...s,savedAspect:i},i):0}if(await new Promise(t=>setTimeout(t,150)),this._spaceDialog?.planUrl!==t)return 0}return 0}async _deleteServerPlan(t){if(confirm(this._t("confirm.delete_plan",{name:t})))try{await this.hass.callWS({type:"houseplan/plans/delete",name:t});const e=this._spaceDialog;e?.saved&&(this._spaceDialog={...e,saved:e.saved.filter(e=>e.name!==t)})}catch(t){this._showToast(this._t("toast.plan_delete_failed",{err:this._errText(t)}))}}_renderServerPlans(t){if(t.savedBusy)return W`
${this._t("space.loading")}
`;const e=t.saved||[];if(!e.length)return W`
${this._t("space.no_saved")}
`;return W`
${e.map(e=>W`
@@ -5352,7 +5352,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="5ca433d2ee8bf92a41f4597ac53777315a9c
`)} -
`}async _saveSpaceDialog(){const t=this._spaceDialog;if(!t||t.busy||!t.title.trim())return;if("file"===t.source&&!t.planFile&&!t.planUrl)return void this._showToast(this._t("toast.plan_required"));const e="create"===t.mode&&0===(this._serverCfg?.spaces.length||0);this._spaceDialog={...t,busy:!0};try{const i="create"===t.mode?"s"+Date.now().toString(36):t.spaceId;let s=null;if("file"===t.source&&t.planFile){s={url:(await this.hass.callWS({type:"houseplan/plan/set",space_id:i,ext:t.planFile.ext,data:t.planFile.b64})).url,aspect:t.planFile.aspect}}let n=t.savedAspect||null;!s&&"file"===t.source&&t.planUrl&&!n&&this._aspectJob&&(n=await this._aspectJob||null);const o=this._serverCfg;let a;if("create"===t.mode)a={id:i,title:t.title.trim(),plan_url:null,view_box:[0,0,1,1],rooms:[]},o.spaces.push(a);else{if(a=o.spaces.find(t=>t.id===i),!a)throw new Error("space "+i+" is gone from the config");a.title=t.title.trim()}s?(a.plan_url=s.url,a.plan_aspect=s.aspect):"file"===t.source&&t.planUrl&&t.planUrl!==a.plan_url&&(a.plan_url=t.planUrl,a.plan_aspect=n),"draw"===t.source&&(a.plan_url=null,a.plan_aspect=null,delete a.plan_x,delete a.plan_y,delete a.plan_scale,delete a.plan_scale_x,delete a.plan_scale_y,delete a.plan_angle),a.settings={...a.settings||{},show_borders:t.showBorders,show_names:t.showNames,hide_decor:t.hideDecor||void 0,hide_openings:t.hideOpenings||void 0,room_color:t.roomColor,room_opacity:t.roomOpacity,bg_color:t.bgColor||void 0,bg_mode:t.bgMode||void 0,north_deg:t.northDeg??void 0,sun_rays:t.sunRays??void 0,fill_mode:t.fillMode,custom_fill:t.customFill||void 0,glow_enabled:t.glowEnabled,temp_min:Number.isFinite(t.tempMin)?Math.min(t.tempMin,t.tempMax):20,temp_max:Number.isFinite(t.tempMax)?Math.max(t.tempMin,t.tempMax):25,show_lqi:t.showLqi,card_font_scale:1!==t.cardFontScale?t.cardFontScale:void 0,label_temp:t.labelTemp,label_hum:t.labelHum,label_lqi:t.labelLqi,label_light:t.labelLight},a.cell_cm=Number.isFinite(t.cellCm)&&t.cellCm>0?Math.max(.1,Math.min(Eg,t.cellCm)):5,await this._saveConfigNow(),this._spaceDialog=null,"create"===t.mode&&this._commitSpace(a.id),this._regSignature="",this._maybeRebuildDevices(),this._importQueue.length?this._openNextImport():e||this._importTotal>0?(this._importTotal=0,this._commitSpace(this._serverCfg.spaces[0]?.id||this._space),this._setMode("plan"),this._tool="draw",this._path=[],this._cursorPt=null,this._primeDrawWallField(),this._showToast(this._t(e&&!this._importTotal?"toast.space_added_onboard":"import.done"))):(this._showToast("create"===t.mode?this._t("toast.space_added"):this._t("toast.space_saved")),"create"===t.mode&&("plan"!==this._mode?this._setMode("plan"):(this._tool="draw",this._path=[],this._cursorPt=null,this._primeDrawWallField(),this._saveNav())))}catch(t){this._spaceDialog&&(this._spaceDialog={...this._spaceDialog,busy:!1}),this._showToast(this._t("toast.error",{err:this._errText(t)}))}}async _deleteSpace(){const t=this._spaceDialog;if(!t||"edit"!==t.mode)return;const e=this._serverCfg.spaces.find(e=>e.id===t.spaceId);if(confirm(this._t("confirm.delete_space",{title:e.title}))){this._serverCfg.spaces=this._serverCfg.spaces.filter(e=>e.id!==t.spaceId);try{await this._saveConfigNow(),this._spaceDialog=null,this._space===t.spaceId&&this._commitSpace(this._serverCfg.spaces[0]?.id||""),this._regSignature="",this._maybeRebuildDevices(),this._showToast(this._t("toast.space_deleted"))}catch(t){this._showToast(this._t("toast.delete_failed",{err:this._errText(t)}))}}}async _saveConfigNow(){this._cfgEpoch++;try{await this._writeConfig()}catch(t){throw"conflict"===t?.code&&await this._reloadConfigOnly(),t}}_startImport(){const t=this._importDialog;if(!t)return;const e=t.floors.filter(t=>t.checked).map(t=>t.name);this._importDialog=null,e.length?(this._importQueue=e,this._importTotal=e.length,this._openNextImport()):this._openSpaceDialog("create")}_openNextImport(){const t=this._importQueue.shift();void 0!==t&&(this._spaceDialog={mode:"create",title:t,planUrl:null,planFile:null,...xh(),hideDecor:!1,hideOpenings:!1,roomColor:ns,roomOpacity:os,fillMode:"custom",customFill:null,glowEnabled:!0,bgColor:null,bgMode:"daynight",northDeg:null,sunRays:null,tempMin:20,tempMax:25,showLqi:this._config?.show_signal??!0,cardFontScale:1,labelTemp:!1,labelHum:!1,labelLqi:!1,labelLight:!1,cellCm:ec(this._imperial),cellCmInput:ic(ec(this._imperial),this._imperial),cellCmTouched:!1,busy:!1})}_skipImport(){this._spaceDialog=null,this._importQueue.length?this._openNextImport():this._importTotal>0&&this._model.length&&(this._importTotal=0,this._commitSpace(this._serverCfg.spaces[0]?.id||this._space),this._setMode("plan"),this._showToast(this._t("import.done")))}_renderImportDialog(){const t=this._importDialog,e=t.floors.filter(t=>t.checked).length;return W``}async _saveSpaceDialog(){const t=this._spaceDialog;if(!t||t.busy||!t.title.trim())return;if("file"===t.source&&!t.planFile&&!t.planUrl)return void this._showToast(this._t("toast.plan_required"));const e="create"===t.mode&&0===(this._serverCfg?.spaces.length||0);this._spaceDialog={...t,busy:!0};try{const i="create"===t.mode?"s"+Date.now().toString(36):t.spaceId;let s=null;if("file"===t.source&&t.planFile){s={url:(await this.hass.callWS({type:"houseplan/plan/set",space_id:i,ext:t.planFile.ext,data:t.planFile.b64})).url,aspect:t.planFile.aspect}}let n=t.savedAspect||null;!s&&"file"===t.source&&t.planUrl&&!n&&this._aspectJob&&(n=await this._aspectJob||null);const o=this._serverCfg;let a;if("create"===t.mode)a={id:i,title:t.title.trim(),plan_url:null,view_box:[0,0,1,1],rooms:[]},o.spaces.push(a);else{if(a=o.spaces.find(t=>t.id===i),!a)throw new Error("space "+i+" is gone from the config");a.title=t.title.trim()}s?(a.plan_url=s.url,a.plan_aspect=s.aspect):"file"===t.source&&t.planUrl&&t.planUrl!==a.plan_url&&(a.plan_url=t.planUrl,a.plan_aspect=n),"draw"===t.source&&(a.plan_url=null,a.plan_aspect=null,delete a.plan_x,delete a.plan_y,delete a.plan_scale,delete a.plan_scale_x,delete a.plan_scale_y,delete a.plan_angle),a.settings={...a.settings||{},show_borders:t.showBorders,show_names:t.showNames,hide_decor:t.hideDecor||void 0,hide_openings:t.hideOpenings||void 0,room_color:t.roomColor,room_opacity:t.roomOpacity,bg_color:t.bgColor||void 0,bg_mode:t.bgMode||void 0,north_deg:t.northDeg??void 0,sun_rays:t.sunRays??void 0,fill_mode:t.fillMode,custom_fill:t.customFill||void 0,glow_enabled:t.glowEnabled,temp_min:Number.isFinite(t.tempMin)?Math.min(t.tempMin,t.tempMax):20,temp_max:Number.isFinite(t.tempMax)?Math.max(t.tempMin,t.tempMax):25,show_lqi:t.showLqi,card_font_scale:1!==t.cardFontScale?t.cardFontScale:void 0,label_temp:t.labelTemp,label_hum:t.labelHum,label_lqi:t.labelLqi,label_light:t.labelLight},a.cell_cm=Number.isFinite(t.cellCm)&&t.cellCm>0?Math.max(.1,Math.min(zg,t.cellCm)):5,await this._saveConfigNow(),this._spaceDialog=null,"create"===t.mode&&this._commitSpace(a.id),this._regSignature="",this._maybeRebuildDevices(),this._importQueue.length?this._openNextImport():e||this._importTotal>0?(this._importTotal=0,this._commitSpace(this._serverCfg.spaces[0]?.id||this._space),this._setMode("plan"),this._tool="draw",this._path=[],this._cursorPt=null,this._primeDrawWallField(),this._showToast(this._t(e&&!this._importTotal?"toast.space_added_onboard":"import.done"))):(this._showToast("create"===t.mode?this._t("toast.space_added"):this._t("toast.space_saved")),"create"===t.mode&&("plan"!==this._mode?this._setMode("plan"):(this._tool="draw",this._path=[],this._cursorPt=null,this._primeDrawWallField(),this._saveNav())))}catch(t){this._spaceDialog&&(this._spaceDialog={...this._spaceDialog,busy:!1}),this._showToast(this._t("toast.error",{err:this._errText(t)}))}}async _deleteSpace(){const t=this._spaceDialog;if(!t||"edit"!==t.mode)return;const e=this._serverCfg.spaces.find(e=>e.id===t.spaceId);if(confirm(this._t("confirm.delete_space",{title:e.title}))){this._serverCfg.spaces=this._serverCfg.spaces.filter(e=>e.id!==t.spaceId);try{await this._saveConfigNow(),this._spaceDialog=null,this._space===t.spaceId&&this._commitSpace(this._serverCfg.spaces[0]?.id||""),this._regSignature="",this._maybeRebuildDevices(),this._showToast(this._t("toast.space_deleted"))}catch(t){this._showToast(this._t("toast.delete_failed",{err:this._errText(t)}))}}}async _saveConfigNow(){this._cfgEpoch++;try{await this._writeConfig()}catch(t){throw"conflict"===t?.code&&await this._reloadConfigOnly(),t}}_startImport(){const t=this._importDialog;if(!t)return;const e=t.floors.filter(t=>t.checked).map(t=>t.name);this._importDialog=null,e.length?(this._importQueue=e,this._importTotal=e.length,this._openNextImport()):this._openSpaceDialog("create")}_openNextImport(){const t=this._importQueue.shift();void 0!==t&&(this._spaceDialog={mode:"create",title:t,planUrl:null,planFile:null,...xh(),hideDecor:!1,hideOpenings:!1,roomColor:ns,roomOpacity:os,fillMode:"custom",customFill:null,glowEnabled:!0,bgColor:null,bgMode:"daynight",northDeg:null,sunRays:null,tempMin:20,tempMax:25,showLqi:this._config?.show_signal??!0,cardFontScale:1,labelTemp:!1,labelHum:!1,labelLqi:!1,labelLight:!1,cellCm:ec(this._imperial),cellCmInput:ic(ec(this._imperial),this._imperial),cellCmTouched:!1,busy:!1})}_skipImport(){this._spaceDialog=null,this._importQueue.length?this._openNextImport():this._importTotal>0&&this._model.length&&(this._importTotal=0,this._commitSpace(this._serverCfg.spaces[0]?.id||this._space),this._setMode("plan"),this._showToast(this._t("import.done")))}_renderImportDialog(){const t=this._importDialog,e=t.floors.filter(t=>t.checked).length;return W`this._importDialog=null}>
${this._t("import.hint")}
@@ -5372,7 +5372,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="5ca433d2ee8bf92a41f4597ac53777315a9c ${this._t("import.start",{n:e})}
-
`}_sunGlobal(){const t=this._settingsDialog;return t?{...this._settings,north_deg:t.northDeg??void 0,bg_mode:t.bgMode,sun_rays:t.sunRays}:this._settings}_sunSpace(){const t=this._spaceDialog,e=this._curSpaceCfg?.settings||{};return t&&"edit"===t.mode&&t.spaceId===this._space?{...e,north_deg:t.northDeg??void 0,bg_mode:t.bgMode??void 0,sun_rays:t.sunRays??void 0}:e}_effNorth(){return Za(this._sunGlobal(),this._sunSpace())}_effBgMode(){return Qa(this._sunGlobal(),this._sunSpace())}_dayCycleState(t=new Date){return(this._modeTransitionVisual?.viewWeight??("view"===this._mode?1:0))<=0||"daynight"!==this._effBgMode()?null:qa(this._renderPlanHass,t)}_syncDayCycleClock(){const t=this._dayCycleState();this._dayCycleClockKey=t?Wa(t):"";const e="clock"===t?.source&&"hidden"!==this.ownerDocument.visibilityState&&this.isConnected;e&&!this._dayCycleTimer?this._dayCycleTimer=window.setInterval(this._dayCycleTick,3e4):!e&&this._dayCycleTimer&&(clearInterval(this._dayCycleTimer),this._dayCycleTimer=0)}_dayCycleVisibility(t){"hidden"!==t.kind?(this._dayCycleTick(),this._syncDayCycleClock()):this._dayCycleTimer&&(clearInterval(this._dayCycleTimer),this._dayCycleTimer=0)}_effSunRays(){return tr(this._sunGlobal(),this._sunSpace())}_sunNow(){return null!==this._effNorth()?er(this._renderPlanHass):null}_renderSunRays(t){const e=j``,i=this._modeTransitionVisual?.viewWeight??0;if(this._editing&&i<=0||!this._effSunRays())return this._sunFadeReset(),e;const s=this._effNorth(),n=null!==s?er(this._renderPlanHass):null;if(!n||n.elevation<=0)return this._sunFadeReset(),e;if(o=n.elevation,Number(o)>=3)this._sunOutTimer&&(clearTimeout(this._sunOutTimer),this._sunOutTimer=0),this._sunOut=!1,this._sunShown=!0;else{if(!this._sunShown)return e;this._sunOut||(this._sunOut=!0,this._sunOutTimer=window.setTimeout(()=>{this._sunOutTimer=0,this._sunShown=!1,this._sunOut=!1,this.requestUpdate()},2e3))}var o;const a=`${t.id}|${n.azimuth}|${n.elevation}|${s}|${this._cfgEpoch}`;if(!this._sunRaysCache||this._sunRaysCache.key!==a){const e=t.rooms.map(t=>({id:t.id||"",poly:hi(t)})).filter(t=>!!t.id&&!!t.poly),i=this._openingsR.filter(t=>"window"===t.type&&!t.host).map(t=>({id:t.id,x:t.rx,y:t.ry,angle:t.angle,length:t.rlen})),o=this._spaceWalls,r=this._openPairs().flatMap(t=>t.segs),l=this._openingWallIndexFor(t,r).value,c={},h={};if(o.length){for(const i of e){const e=hl(t.rooms,i.id,o,r,this._wallKeyPitch,this._cellCm,this._gridPitch,Jg);e&&(c[i.id]=e)}for(const t of i){const e=Ml(l,{x:t.x,y:t.y,angle:t.angle,length:t.length});e.cm>0&&(h[t.id]=xr(e.cm,this._cellCm,this._gridPitch))}}let d=Xa(e,i,n.azimuth,n.elevation,s,o.length?c:void 0,o.length?h:void 0);const u=this._physicalBodiesR(t);u.length&&(d=d.map(t=>{const e=function(t,e,i){return i>0?t.map(t=>function(t){const e=[...t].sort((t,e)=>t[0]-e[0]||t[1]-e[1]);if(e.length<=2)return e;const i=(t,e,i)=>(e[0]-t[0])*(i[1]-t[1])-(e[1]-t[1])*(i[0]-t[0]),s=[];for(const t of e){for(;s.length>=2&&i(s[s.length-2],s[s.length-1],t)<=0;)s.pop();s.push(t)}const n=[];for(let t=e.length-1;t>=0;t--){const s=e[t];for(;n.length>=2&&i(n[n.length-2],n[n.length-1],s)<=0;)n.pop();n.push(s)}return s.slice(0,-1).concat(n.slice(0,-1))}([...t,...t.map(t=>[t[0]+e[0]*i,t[1]+e[1]*i])])).filter(t=>t.length>=3):t}(u,t.dir,t.len),i=t.polys.map(t=>Gl(t,e));return{...t,paths:i.map(Ol).filter(Boolean),polys:i.flatMap(Kl)}}).filter(t=>t.paths?.length||t.polys.length)),this._sunRaysCache={key:a,rays:d,rims:d.map(t=>function(t,e=1e-4){const[i,s]=t.dir,n=-s,o=i,a=[];for(const r of[t.a,t.b]){const l=[];for(const a of t.polys)for(let t=0;te)continue;if(Math.abs((h[0]-r[0])*n+(h[1]-r[1])*o)>e)continue;const d=(c[0]-r[0])*i+(c[1]-r[1])*s,u=(h[0]-r[0])*i+(h[1]-r[1])*s;Math.abs(u-d)<=e||l.push(dt[0]-e[0]);const c=[];for(const t of l){const i=c[c.length-1];i&&t[0]<=i[1]+e?i[1]=Math.max(i[1],t[1]):c.push([t[0],t[1]])}for(const[t,e]of c)a.push([[r[0]+i*t,r[1]+s*t],[r[0]+i*e,r[1]+s*e]])}return a}(t))}}const r=this._sunRaysCache.rays,l=this._sunRaysCache.rims;if(!r.length)return e;const c=(h=function(t){const e=Math.min(90,Math.max(-90,Number(t)||0));let i=ja[ja.length-1][1];for(let t=1;t +
`}_sunGlobal(){const t=this._settingsDialog;return t?{...this._settings,north_deg:t.northDeg??void 0,bg_mode:t.bgMode,sun_rays:t.sunRays}:this._settings}_sunSpace(){const t=this._spaceDialog,e=this._curSpaceCfg?.settings||{};return t&&"edit"===t.mode&&t.spaceId===this._space?{...e,north_deg:t.northDeg??void 0,bg_mode:t.bgMode??void 0,sun_rays:t.sunRays??void 0}:e}_effNorth(){return Za(this._sunGlobal(),this._sunSpace())}_effBgMode(){return Qa(this._sunGlobal(),this._sunSpace())}_dayCycleState(t=new Date){return(this._modeTransitionVisual?.viewWeight??("view"===this._mode?1:0))<=0||"daynight"!==this._effBgMode()?null:qa(this._renderPlanHass,t)}_syncDayCycleClock(){const t=this._dayCycleState();this._dayCycleClockKey=t?Wa(t):"";const e="clock"===t?.source&&"hidden"!==this.ownerDocument.visibilityState&&this.isConnected;e&&!this._dayCycleTimer?this._dayCycleTimer=window.setInterval(this._dayCycleTick,3e4):!e&&this._dayCycleTimer&&(clearInterval(this._dayCycleTimer),this._dayCycleTimer=0)}_dayCycleVisibility(t){"hidden"!==t.kind?(this._dayCycleTick(),this._syncDayCycleClock()):this._dayCycleTimer&&(clearInterval(this._dayCycleTimer),this._dayCycleTimer=0)}_effSunRays(){return tr(this._sunGlobal(),this._sunSpace())}_sunNow(){return null!==this._effNorth()?er(this._renderPlanHass):null}_renderSunRays(t){const e=j``,i=this._modeTransitionVisual?.viewWeight??0;if(this._editing&&i<=0||!this._effSunRays())return this._sunFadeReset(),e;const s=this._effNorth(),n=null!==s?er(this._renderPlanHass):null;if(!n||n.elevation<=0)return this._sunFadeReset(),e;if(o=n.elevation,Number(o)>=3)this._sunOutTimer&&(clearTimeout(this._sunOutTimer),this._sunOutTimer=0),this._sunOut=!1,this._sunShown=!0;else{if(!this._sunShown)return e;this._sunOut||(this._sunOut=!0,this._sunOutTimer=window.setTimeout(()=>{this._sunOutTimer=0,this._sunShown=!1,this._sunOut=!1,this.requestUpdate()},2e3))}var o;const a=`${t.id}|${n.azimuth}|${n.elevation}|${s}|${this._cfgEpoch}`;if(!this._sunRaysCache||this._sunRaysCache.key!==a){const e=t.rooms.map(t=>({id:t.id||"",poly:hi(t)})).filter(t=>!!t.id&&!!t.poly),i=this._openingsR.filter(t=>"window"===t.type&&!t.host).map(t=>({id:t.id,x:t.rx,y:t.ry,angle:t.angle,length:t.rlen})),o=this._spaceWalls,r=this._openPairs().flatMap(t=>t.segs),l=this._openingWallIndexFor(t,r).value,c={},h={};if(o.length){for(const i of e){const e=hl(t.rooms,i.id,o,r,this._wallKeyPitch,this._cellCm,this._gridPitch,Zg);e&&(c[i.id]=e)}for(const t of i){const e=Ml(l,{x:t.x,y:t.y,angle:t.angle,length:t.length});e.cm>0&&(h[t.id]=xr(e.cm,this._cellCm,this._gridPitch))}}let d=Xa(e,i,n.azimuth,n.elevation,s,o.length?c:void 0,o.length?h:void 0);const u=this._physicalBodiesR(t);u.length&&(d=d.map(t=>{const e=function(t,e,i){return i>0?t.map(t=>function(t){const e=[...t].sort((t,e)=>t[0]-e[0]||t[1]-e[1]);if(e.length<=2)return e;const i=(t,e,i)=>(e[0]-t[0])*(i[1]-t[1])-(e[1]-t[1])*(i[0]-t[0]),s=[];for(const t of e){for(;s.length>=2&&i(s[s.length-2],s[s.length-1],t)<=0;)s.pop();s.push(t)}const n=[];for(let t=e.length-1;t>=0;t--){const s=e[t];for(;n.length>=2&&i(n[n.length-2],n[n.length-1],s)<=0;)n.pop();n.push(s)}return s.slice(0,-1).concat(n.slice(0,-1))}([...t,...t.map(t=>[t[0]+e[0]*i,t[1]+e[1]*i])])).filter(t=>t.length>=3):t}(u,t.dir,t.len),i=t.polys.map(t=>Gl(t,e));return{...t,paths:i.map(Ol).filter(Boolean),polys:i.flatMap(Kl)}}).filter(t=>t.paths?.length||t.polys.length)),this._sunRaysCache={key:a,rays:d,rims:d.map(t=>function(t,e=1e-4){const[i,s]=t.dir,n=-s,o=i,a=[];for(const r of[t.a,t.b]){const l=[];for(const a of t.polys)for(let t=0;te)continue;if(Math.abs((h[0]-r[0])*n+(h[1]-r[1])*o)>e)continue;const d=(c[0]-r[0])*i+(c[1]-r[1])*s,u=(h[0]-r[0])*i+(h[1]-r[1])*s;Math.abs(u-d)<=e||l.push(dt[0]-e[0]);const c=[];for(const t of l){const i=c[c.length-1];i&&t[0]<=i[1]+e?i[1]=Math.max(i[1],t[1]):c.push([t[0],t[1]])}for(const[t,e]of c)a.push([[r[0]+i*t,r[1]+s*t],[r[0]+i*e,r[1]+s*e]])}return a}(t))}}const r=this._sunRaysCache.rays,l=this._sunRaysCache.rims;if(!r.length)return e;const c=(h=function(t){const e=Math.min(90,Math.max(-90,Number(t)||0));let i=ja[ja.length-1][1];for(let t=1;t ${r.map((t,e)=>{const i=(t.a[0]+t.b[0])/2,s=(t.a[1]+t.b[1])/2,n=i+t.normal[0]*t.depth,o=s+t.normal[1]*t.depth;return j` ${d.map(([t,e])=>j`${this._t("gs.north_letter")}
${null===t?"—":t+"°"} - `}_stageBg(t){const e=this._settingsDialog,i=this._spaceDialog,s=e?e.bgColor||"":hs(this._settings,{bgColor:null});return(i&&"edit"===i.mode&&i.spaceId===this._space?i.bgColor||"":t.bgColor||"")||s}_stageBgHex(){const t=this._stageEl;if(t){const e=getComputedStyle(t).backgroundColor.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/);if(e)return"#"+e.slice(1,4).map(t=>(+t).toString(16).padStart(2,"0")).join("")}return"#111111"}_checkOptimizeGeometry(t){return function(t,e={}){const i=(e.fingerprint||vh)(t),s=Array.isArray(t?.spaces)?t.spaces:[],n=e.fallbackSpaceName||(t=>`Space ${t}`),o=e.prepareSpace||e_,a=e.wallPass||vl,r=e.floorPass||ml,l=[];for(let e=0;e0||h.physicalBodies.length>0;if(!h.space.rooms.length&&!d){l.push({...c,status:"not-applicable"});continue}let u=null;if(d){try{u=a(h.space.rooms,h.walls,h.openCuts,h.roomOpenings,h.wallKeyPitch,h.cellCm,h.gridPitch,h.coordScale,h.physicalBodies)}catch{l.push({...c,status:"failed",reason:"wall-exception"});continue}if(null==u){l.push({...c,status:"failed",reason:"wall-null"});continue}}if(h.space.rooms.length&&null==u?.paperGeom){let t;try{t=r(h.space.rooms,h.walls,h.openCuts,h.wallKeyPitch,h.cellCm,h.gridPitch,h.coordScale)}catch{l.push({...c,status:"failed",reason:"floor-exception"});continue}if(null==t){l.push({...c,status:"failed",reason:"floor-null"});continue}}l.push({...c,status:"ok"})}const c=l.filter(t=>"failed"===t.status);return{fingerprint:i,spaces:l,failures:c,ok:0===c.length}}(t,{fallbackSpaceName:t=>this._t("gs.align_preflight_space",{n:String(t)})})}async _runAlignToGrid(){let t=this._alignDialog;if(!t||t.busy||!this._serverCfg||!t.changed||!t.preflight?.ok)return;const e=vh(t.config);if(t.preflight.fingerprint!==e){const e=this._checkOptimizeGeometry(t.config);if(t={...t,preflight:e},this._alignDialog=t,!e.ok)return}this._clearGeometryGesture(),this._alignDialog={...t,busy:!0};try{this._saveConfigDebounced.pending()&&this._saveConfigDebounced.flush(),await this._writeChain;const e=await this.hass.callWS({type:"houseplan/plan/optimize",config:t.config,layout:t.layout,expected_config_rev:this._cfgRev,expected_layout_rev:this._layoutRev});this._serverCfg=t.config,this._layout=t.layout,this._geometryHistory.clear(),this._cfgRev=e?.config_rev??this._cfgRev+1,this._layoutRev=e?.layout_rev??this._layoutRev+1,this._canOptimizeUndo=!!e?.can_undo,this._undoKind=e?.can_undo?"optimize":null,this._dirtyPos.clear(),this._sentPos.clear(),this._cfgEpoch++,this._modelCache=null,this._frame=null,this._cacheSnapshot(),this._alignDialog=null,this.requestUpdate(),this._showToast(this._t("gs.align_done",{n:String(t.report.moved),m:String(t.report.migrated+t.report.canonicalized+t.report.coordsCanonicalized+t.report.wallsMerged+t.report.spansMerged+t.report.partitionsMerged)}))}catch(t){this._alignDialog&&(this._alignDialog={...this._alignDialog,busy:!1}),"conflict"===t?.code&&await Promise.all([this._reloadConfigOnly(!0),this._reloadLayoutOnly()]),this._showToast(this._t("toast.error",{err:this._errText(t)}))}}async _undoPlanOptimization(){if(!this._canOptimizeUndo||this._optimizeUndoBusy)return;const t=this._undoKind;this._clearGeometryGesture(),this._optimizeUndoBusy=!0,this.requestUpdate();try{await this.hass.callWS({type:"houseplan/plan/optimize_undo",expected_config_rev:this._cfgRev,expected_layout_rev:this._layoutRev});const[e,i]=await Promise.all([this.hass.callWS({type:"houseplan/config/get"}),this.hass.callWS({type:"houseplan/layout/get"})]);this._serverCfg=e?.config||this._serverCfg,this._cfgRev=e?.rev??this._cfgRev,this._layout=i?.layout||this._layout,this._geometryHistory.clear(),this._layoutRev=i?.rev??this._layoutRev,this._canOptimizeUndo=!1,this._undoKind=null,this._cfgEpoch++,this._modelCache=null,this._frame=null,this._cacheSnapshot(),this.requestUpdate(),this._showToast(this._t("import"===t?"backup.import_undone":"gs.optimize_undone"))}catch(t){this._canOptimizeUndo=!1,this._undoKind=null,this._showToast(this._t("toast.error",{err:this._errText(t)}))}finally{this._optimizeUndoBusy=!1,this.requestUpdate()}}async _runBackupExport(){const t=this._backupExportDialog;if(t&&!t.busy){this._backupExportDialog={...t,busy:!0,error:""};try{const e=await this.hass.callWS({type:"houseplan/export/create",kind:t.kind,space_id:"space"===t.kind?this._space:void 0,..."space"===t.kind&&t.planOnly?{plan_only:!0}:{},card_version:Rg}),i=new Blob([JSON.stringify(e.document,null,2)+"\n"],{type:"application/json;charset=utf-8"}),s=URL.createObjectURL(i),n=document.createElement("a");n.href=s,n.download=e.filename||`houseplan-${t.kind}.json`,n.style.display="none",document.body.append(n),n.click(),n.remove(),window.setTimeout(()=>URL.revokeObjectURL(s),0),this._backupExportDialog=null,this._showToast(this._t("backup.export_done"))}catch(t){this._backupExportDialog&&(this._backupExportDialog={...this._backupExportDialog,busy:!1,error:this._backupErrorText(t)})}}}async _pickBackupImport(t){const e=t.target,i=e.files?.[0];if(e.value="",i){this._settingsDialog=null,this._backupImportDialog={filename:i.name,size:i.size,token:"",preview:null,expectedConfigRev:this._cfgRev,expectedLayoutRev:this._layoutRev,duplicatePolicy:"skip",confirmMissing:!1,busy:!0,error:""};try{this._saveConfigDebounced.pending()&&this._saveConfigDebounced.flush(),await this._writeChain,this._persistLayout.pending()&&this._persistLayout.flush();const t="/api/houseplan/import/preview?duplicate_policy=skip",e={method:"POST",body:i,headers:{"content-type":"application/json"}},s=this.hass?.fetchWithAuth?await this.hass.fetchWithAuth(t,e):await fetch(t,{...e,headers:{...e.headers,...this.hass?.auth?.data?.access_token?{authorization:`Bearer ${this.hass.auth.data.access_token}`}:{}}}),n=await s.json().catch(()=>({}));if(!s.ok||n.error)throw Object.assign(new Error(n.message||n.error||`HTTP ${s.status}`),{code:n.error});this._backupImportDialog&&(this._backupImportDialog={...this._backupImportDialog,token:n.token,preview:n.preview,expectedConfigRev:n.expected_config_rev,expectedLayoutRev:n.expected_layout_rev,busy:!1})}catch(t){this._backupImportDialog&&(this._backupImportDialog={...this._backupImportDialog,busy:!1,error:this._backupErrorText(t)})}}}async _setBackupDuplicatePolicy(t){const e=this._backupImportDialog;if(e&&!e.busy&&e.token&&t!==e.duplicatePolicy){this._backupImportDialog={...e,duplicatePolicy:t,busy:!0,error:""};try{const i=await this.hass.callWS({type:"houseplan/import/revalidate",token:e.token,duplicate_policy:t});this._backupImportDialog&&(this._backupImportDialog={...this._backupImportDialog,preview:{...e.preview,...i.preview},expectedConfigRev:i.expected_config_rev,expectedLayoutRev:i.expected_layout_rev,confirmMissing:!1,busy:!1})}catch(t){this._backupImportDialog&&(this._backupImportDialog={...this._backupImportDialog,duplicatePolicy:e.duplicatePolicy,preview:e.preview,confirmMissing:e.confirmMissing,busy:!1,error:this._backupErrorText(t)})}}}async _applyBackupImport(){const t=this._backupImportDialog;if(!t||t.busy||!t.token||!t.preview)return;if(t.preview.confirmation_required&&!t.confirmMissing)return;this._backupImportDialog={...t,busy:!0,error:""};const e=this._space;try{const i=await this.hass.callWS({type:"houseplan/import/apply",token:t.token,expected_config_rev:t.expectedConfigRev,expected_layout_rev:t.expectedLayoutRev,duplicate_policy:t.duplicatePolicy,confirm_missing_content:t.confirmMissing}),[s,n]=await Promise.all([this.hass.callWS({type:"houseplan/config/get"}),this.hass.callWS({type:"houseplan/layout/get"})]);this._adoptStructuralResponses(s,n),this._geometryHistory.clear(),this._dirtyPos.clear(),this._sentPos.clear(),this._defPos={},this._cfgEpoch++,this._modelCache=null,this._frame=null,this._visibleDeviceSnapshot=null,this._candidateDeviceSnapshot=null,this._stagedDeviceSnapshotToken=-1,this._capturedSnapshotConfigEpoch=-1,this._regSignature="",this._signer.invalidate(this.hass),this._resign(),this._maybeRebuildDevices();const o=this._serverCfg?.spaces||[],a="space"===i.kind&&i.space_id?i.space_id:o.some(t=>t.id===e)?e:o[0]?.id||this._space;this._hasFixedFloor?this._adoptInitialSpace(this._model,!0):this._commitSpace(a),this._backupImportDialog=null,this._cacheSnapshot(),this.requestUpdate();const r="space"===i.kind?t.preview.counts:i.counts;this._showToast(this._t("space"===i.kind?"backup.space_done":"backup.full_done",{spaces:String(r?.spaces||0),rooms:String(r?.rooms||0),markers:String(r?.markers||0)}))}catch(t){if("conflict"===t?.code&&this._backupImportDialog?.token)try{const t=this._backupImportDialog,e=await this.hass.callWS({type:"houseplan/import/revalidate",token:t.token,duplicate_policy:t.duplicatePolicy});return void(this._backupImportDialog={...t,preview:{...t.preview,...e.preview},expectedConfigRev:e.expected_config_rev,expectedLayoutRev:e.expected_layout_rev,confirmMissing:!1,busy:!1,error:this._t("backup.revalidated")})}catch(e){t=e}this._backupImportDialog&&(this._backupImportDialog={...this._backupImportDialog,busy:!1,error:this._backupErrorText(t)})}}_renderBackupExportDialog(){const t=this._backupExportDialog,e=(this._serverCfg?.spaces||[]).find(t=>t.id===this._space);return W``}_stageBg(t){const e=this._settingsDialog,i=this._spaceDialog,s=e?e.bgColor||"":hs(this._settings,{bgColor:null});return(i&&"edit"===i.mode&&i.spaceId===this._space?i.bgColor||"":t.bgColor||"")||s}_stageBgHex(){const t=this._stageEl;if(t){const e=getComputedStyle(t).backgroundColor.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/);if(e)return"#"+e.slice(1,4).map(t=>(+t).toString(16).padStart(2,"0")).join("")}return"#111111"}_checkOptimizeGeometry(t){return function(t,e={}){const i=(e.fingerprint||vh)(t),s=Array.isArray(t?.spaces)?t.spaces:[],n=e.fallbackSpaceName||(t=>`Space ${t}`),o=e.prepareSpace||i_,a=e.wallPass||vl,r=e.floorPass||ml,l=[];for(let e=0;e0||h.physicalBodies.length>0;if(!h.space.rooms.length&&!d){l.push({...c,status:"not-applicable"});continue}let u=null;if(d){try{u=a(h.space.rooms,h.walls,h.openCuts,h.roomOpenings,h.wallKeyPitch,h.cellCm,h.gridPitch,h.coordScale,h.physicalBodies)}catch{l.push({...c,status:"failed",reason:"wall-exception"});continue}if(null==u){l.push({...c,status:"failed",reason:"wall-null"});continue}}if(h.space.rooms.length&&null==u?.paperGeom){let t;try{t=r(h.space.rooms,h.walls,h.openCuts,h.wallKeyPitch,h.cellCm,h.gridPitch,h.coordScale)}catch{l.push({...c,status:"failed",reason:"floor-exception"});continue}if(null==t){l.push({...c,status:"failed",reason:"floor-null"});continue}}l.push({...c,status:"ok"})}const c=l.filter(t=>"failed"===t.status);return{fingerprint:i,spaces:l,failures:c,ok:0===c.length}}(t,{fallbackSpaceName:t=>this._t("gs.align_preflight_space",{n:String(t)})})}async _runAlignToGrid(){let t=this._alignDialog;if(!t||t.busy||!this._serverCfg||!t.changed||!t.preflight?.ok)return;const e=vh(t.config);if(t.preflight.fingerprint!==e){const e=this._checkOptimizeGeometry(t.config);if(t={...t,preflight:e},this._alignDialog=t,!e.ok)return}this._clearGeometryGesture(),this._alignDialog={...t,busy:!0};try{this._saveConfigDebounced.pending()&&this._saveConfigDebounced.flush(),await this._writeChain;const e=await this.hass.callWS({type:"houseplan/plan/optimize",config:t.config,layout:t.layout,expected_config_rev:this._cfgRev,expected_layout_rev:this._layoutRev});this._serverCfg=t.config,this._layout=t.layout,this._geometryHistory.clear(),this._cfgRev=e?.config_rev??this._cfgRev+1,this._layoutRev=e?.layout_rev??this._layoutRev+1,this._canOptimizeUndo=!!e?.can_undo,this._undoKind=e?.can_undo?"optimize":null,this._dirtyPos.clear(),this._sentPos.clear(),this._cfgEpoch++,this._modelCache=null,this._frame=null,this._cacheSnapshot(),this._alignDialog=null,this.requestUpdate(),this._showToast(this._t("gs.align_done",{n:String(t.report.moved),m:String(t.report.migrated+t.report.canonicalized+t.report.coordsCanonicalized+t.report.wallsMerged+t.report.spansMerged+t.report.partitionsMerged)}))}catch(t){this._alignDialog&&(this._alignDialog={...this._alignDialog,busy:!1}),"conflict"===t?.code&&await Promise.all([this._reloadConfigOnly(!0),this._reloadLayoutOnly()]),this._showToast(this._t("toast.error",{err:this._errText(t)}))}}async _undoPlanOptimization(){if(!this._canOptimizeUndo||this._optimizeUndoBusy)return;const t=this._undoKind;this._clearGeometryGesture(),this._optimizeUndoBusy=!0,this.requestUpdate();try{await this.hass.callWS({type:"houseplan/plan/optimize_undo",expected_config_rev:this._cfgRev,expected_layout_rev:this._layoutRev});const[e,i]=await Promise.all([this.hass.callWS({type:"houseplan/config/get"}),this.hass.callWS({type:"houseplan/layout/get"})]);this._serverCfg=e?.config||this._serverCfg,this._cfgRev=e?.rev??this._cfgRev,this._layout=i?.layout||this._layout,this._geometryHistory.clear(),this._layoutRev=i?.rev??this._layoutRev,this._canOptimizeUndo=!1,this._undoKind=null,this._cfgEpoch++,this._modelCache=null,this._frame=null,this._cacheSnapshot(),this.requestUpdate(),this._showToast(this._t("import"===t?"backup.import_undone":"gs.optimize_undone"))}catch(t){this._canOptimizeUndo=!1,this._undoKind=null,this._showToast(this._t("toast.error",{err:this._errText(t)}))}finally{this._optimizeUndoBusy=!1,this.requestUpdate()}}async _runBackupExport(){const t=this._backupExportDialog;if(t&&!t.busy){this._backupExportDialog={...t,busy:!0,error:""};try{const e=await this.hass.callWS({type:"houseplan/export/create",kind:t.kind,space_id:"space"===t.kind?this._space:void 0,..."space"===t.kind&&t.planOnly?{plan_only:!0}:{},card_version:Ig}),i=new Blob([JSON.stringify(e.document,null,2)+"\n"],{type:"application/json;charset=utf-8"}),s=URL.createObjectURL(i),n=document.createElement("a");n.href=s,n.download=e.filename||`houseplan-${t.kind}.json`,n.style.display="none",document.body.append(n),n.click(),n.remove(),window.setTimeout(()=>URL.revokeObjectURL(s),0),this._backupExportDialog=null,this._showToast(this._t("backup.export_done"))}catch(t){this._backupExportDialog&&(this._backupExportDialog={...this._backupExportDialog,busy:!1,error:this._backupErrorText(t)})}}}async _pickBackupImport(t){const e=t.target,i=e.files?.[0];if(e.value="",i){this._settingsDialog=null,this._backupImportDialog={filename:i.name,size:i.size,token:"",preview:null,expectedConfigRev:this._cfgRev,expectedLayoutRev:this._layoutRev,duplicatePolicy:"skip",confirmMissing:!1,busy:!0,error:""};try{this._saveConfigDebounced.pending()&&this._saveConfigDebounced.flush(),await this._writeChain,this._persistLayout.pending()&&this._persistLayout.flush();const t="/api/houseplan/import/preview?duplicate_policy=skip",e={method:"POST",body:i,headers:{"content-type":"application/json"}},s=this.hass?.fetchWithAuth?await this.hass.fetchWithAuth(t,e):await fetch(t,{...e,headers:{...e.headers,...this.hass?.auth?.data?.access_token?{authorization:`Bearer ${this.hass.auth.data.access_token}`}:{}}}),n=await s.json().catch(()=>({}));if(!s.ok||n.error)throw Object.assign(new Error(n.message||n.error||`HTTP ${s.status}`),{code:n.error});this._backupImportDialog&&(this._backupImportDialog={...this._backupImportDialog,token:n.token,preview:n.preview,expectedConfigRev:n.expected_config_rev,expectedLayoutRev:n.expected_layout_rev,busy:!1})}catch(t){this._backupImportDialog&&(this._backupImportDialog={...this._backupImportDialog,busy:!1,error:this._backupErrorText(t)})}}}async _setBackupDuplicatePolicy(t){const e=this._backupImportDialog;if(e&&!e.busy&&e.token&&t!==e.duplicatePolicy){this._backupImportDialog={...e,duplicatePolicy:t,busy:!0,error:""};try{const i=await this.hass.callWS({type:"houseplan/import/revalidate",token:e.token,duplicate_policy:t});this._backupImportDialog&&(this._backupImportDialog={...this._backupImportDialog,preview:{...e.preview,...i.preview},expectedConfigRev:i.expected_config_rev,expectedLayoutRev:i.expected_layout_rev,confirmMissing:!1,busy:!1})}catch(t){this._backupImportDialog&&(this._backupImportDialog={...this._backupImportDialog,duplicatePolicy:e.duplicatePolicy,preview:e.preview,confirmMissing:e.confirmMissing,busy:!1,error:this._backupErrorText(t)})}}}async _applyBackupImport(){const t=this._backupImportDialog;if(!t||t.busy||!t.token||!t.preview)return;if(t.preview.confirmation_required&&!t.confirmMissing)return;this._backupImportDialog={...t,busy:!0,error:""};const e=this._space;try{const i=await this.hass.callWS({type:"houseplan/import/apply",token:t.token,expected_config_rev:t.expectedConfigRev,expected_layout_rev:t.expectedLayoutRev,duplicate_policy:t.duplicatePolicy,confirm_missing_content:t.confirmMissing}),[s,n]=await Promise.all([this.hass.callWS({type:"houseplan/config/get"}),this.hass.callWS({type:"houseplan/layout/get"})]);this._adoptStructuralResponses(s,n),this._geometryHistory.clear(),this._dirtyPos.clear(),this._sentPos.clear(),this._defPos={},this._cfgEpoch++,this._modelCache=null,this._frame=null,this._visibleDeviceSnapshot=null,this._candidateDeviceSnapshot=null,this._stagedDeviceSnapshotToken=-1,this._capturedSnapshotConfigEpoch=-1,this._regSignature="",this._signer.invalidate(this.hass),this._resign(),this._maybeRebuildDevices();const o=this._serverCfg?.spaces||[],a="space"===i.kind&&i.space_id?i.space_id:o.some(t=>t.id===e)?e:o[0]?.id||this._space;this._hasFixedFloor?this._adoptInitialSpace(this._model,!0):this._commitSpace(a),this._backupImportDialog=null,this._cacheSnapshot(),this.requestUpdate();const r="space"===i.kind?t.preview.counts:i.counts;this._showToast(this._t("space"===i.kind?"backup.space_done":"backup.full_done",{spaces:String(r?.spaces||0),rooms:String(r?.rooms||0),markers:String(r?.markers||0)}))}catch(t){if("conflict"===t?.code&&this._backupImportDialog?.token)try{const t=this._backupImportDialog,e=await this.hass.callWS({type:"houseplan/import/revalidate",token:t.token,duplicate_policy:t.duplicatePolicy});return void(this._backupImportDialog={...t,preview:{...t.preview,...e.preview},expectedConfigRev:e.expected_config_rev,expectedLayoutRev:e.expected_layout_rev,confirmMissing:!1,busy:!1,error:this._t("backup.revalidated")})}catch(e){t=e}this._backupImportDialog&&(this._backupImportDialog={...this._backupImportDialog,busy:!1,error:this._backupErrorText(t)})}}_renderBackupExportDialog(){const t=this._backupExportDialog,e=(this._serverCfg?.spaces||[]).find(t=>t.id===this._space);return W`this._backupExportDialog=null}>
${this._t("backup.export_hint")}
@@ -5499,12 +5499,12 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="5ca433d2ee8bf92a41f4597ac53777315a9c .pickerLabels=${this._colorPickerLabels} .color=${i.c} .opacity=${i.a} .showOpacity=${!0} @hp-color-opacity-change=${e=>{this._setFillColor(t,{c:e.detail.color,a:e.detail.opacity})}}> -
`}get _glowRadiusCm(){const t=Number(this._settings.glow_radius_cm);return Number.isFinite(t)&&t>0?t:300}get _imperial(){return"mi"===this.hass?.config?.unit_system?.length}get _glowRadiusPlaceholder(){const t=this._glowRadiusCm;return this._imperial?String(Math.round(t/30.48*10)/10):String(t/100)}_glowTransition(t,e){let i=this._glowRenderedSources.get(t);if(e){const e=this._glowFadeTimers.get(t);if(null!=e&&(clearTimeout(e),this._glowFadeTimers.delete(t)),null==i){this._suspendGlowFeatherForTransition(),i=++this._glowSourceSeq,this._glowRenderedSources.set(t,i),this._glowEnteringSources.add(t);const e=requestAnimationFrame(()=>{this._glowEnterRafs.get(t)===e&&(this._glowEnterRafs.delete(t),this._glowEnteringSources.delete(t),this.isConnected&&this.requestUpdate())});this._glowEnterRafs.set(t,e)}return{domId:i,entering:this._glowEnteringSources.has(t),leaving:!1}}if(null==i)return null;const s=this._glowEnterRafs.get(t);if(null!=s&&cancelAnimationFrame(s),this._glowEnterRafs.delete(t),this._glowEnteringSources.delete(t),!this._glowFadeTimers.has(t)){this._suspendGlowFeatherForTransition();const e=window.setTimeout(()=>{this._glowFadeTimers.get(t)===e&&(this._glowFadeTimers.delete(t),this._glowRenderedSources.delete(t),this._glowLastAppearance.delete(t),this.isConnected&&this.requestUpdate())},534);this._glowFadeTimers.set(t,e)}return{domId:i,entering:!1,leaving:!0}}_suspendGlowFeatherForTransition(){if(window.matchMedia?.("(prefers-reduced-motion: reduce)").matches)return;this._glowFeatherSuspendUntil=Math.max(this._glowFeatherSuspendUntil,Date.now()+500),clearTimeout(this._glowFeatherResumeTimer);const t=Math.max(0,this._glowFeatherSuspendUntil-Date.now())+17,e=()=>{this._glowFeatherResumeTimer=0,Date.now()=128){const t=this._glowGeometryWarnings.values().next().value;t&&this._glowGeometryWarnings.delete(t)}this._glowGeometryWarnings.add(n),console.warn(`HOUSEPLAN GLOW GEOMETRY FALLBACK: #218, space ${t}, room ${i}, phase ${s}`)}}_lightBarriers(t,e){const i=this._openPairs().flatMap(t=>t.segs),s=[...i],n=Math.max(this._cmToUnits(10),.5*this._gridPitch),o=t=>e.some(e=>this._pointInRoom(t,e.r)),a=this._openingsR.filter(t=>{if("door"!==(e=String(t.type))&&"gate"!==e&&"passage"!==e)return!1;var e;const i=t.angle*Math.PI/180,s=-Math.sin(i),a=Math.cos(i);return o([t.rx+s*n,t.ry+a*n])&&o([t.rx-s*n,t.ry-a*n])}),r=this._roomWallOpeningInputs(a,t);for(const t of r){const e=t.angle*Math.PI/180,i=Math.cos(e)*t.length/2,n=Math.sin(e)*t.length/2;s.push([t.x-i,t.y-n,t.x+i,t.y+n])}const l=new Set(a.filter(t=>t.partitionHost).map(t=>t.id)),c=[t.id,this._cfgEpoch,this._cellCm,this._gridPitch,[...l].sort().join(",")].join("|");this._lightPhysicalBodiesCache?.key!==c&&(this._lightPhysicalBodiesCache={key:c,all:Bl(t,this._cellCm,this._gridPitch,2e-4*this._gridPitch,this._partitionOpeningCuts(t,t=>l.has(t.id))).all});const h=this._lightPhysicalBodiesCache.all;let d=2166136261;const u=t=>{d^=Math.round(64*(Number.isFinite(t)?t:0)),d=Math.imul(d,16777619)>>>0},p=this._spaceWalls;u(this._cellCm),u(this._gridPitch),u(this._wallKeyPitch);for(const{poly:t}of e){u(t.length);for(const e of t)u(e[0]),u(e[1])}for(const t of s)for(const e of t)u(e);for(const t of h){u(t.length);for(const e of t)u(e[0]),u(e[1])}for(const t of p)u(t.cm),u(t.a?.[0]??0),u(t.a?.[1]??0),u(t.b?.[0]??0),u(t.b?.[1]??0);const _=d.toString(36),g=`${t.id}|${_}`;if(this._lightBarrierCache?.key===g)return this._lightBarrierCache.value;const m=.02*this._gridPitch,f=[],v=p.length||h.length?vl(t.rooms,p,i,r,this._wallKeyPitch,this._cellCm,this._gridPitch,Jg,h):null;if(v)for(const t of function(t){const e=[];for(const i of t||[])for(const t of i||[])t?.length>=4&&e.push(t.slice(0,-1).map(t=>[t[0],t[1]]));return e}(v.geom))f.push(...Du(t));else for(const t of h)f.push(...Du(t));for(const{poly:t}of e)for(const e of s.length?Ts(t,s,m):Du(t))f.push(e);const y={occluders:Cu(f),floor:e.map(t=>t.poly),fingerprint:_,masonryGeometry:v?.geom||[],opaqueBodies:h};return this._lightBarrierCache={key:g,value:y},y}_renderGlowLayer(t,e){const i=this._fillColors,s=this._glowRadiusCm/this._cellCm*this._gridPitch,n=t.rooms.map(t=>({r:t,poly:hi(t)})).filter(t=>!!t.poly),o=n.filter(({r:t})=>Es(e.glow,t));if(!o.length)return this._forgetGlowSpace(t.id),j``;const{occluders:a,floor:r,fingerprint:l,masonryGeometry:c,opaqueBodies:h}=this._lightBarriers(t,n),d=ho(this._renderPlanHass,this._renderDevices,null,this._virtualLights).filter(e=>e.device.space===t.id),u=new Map;for(const t of d){if(!t.device.id)continue;const e=u.get(t.device.id)||[];e.push(t),u.set(t.device.id,e)}const p=[],_=new Set;for(const e of this._renderDevices){if(e.space!==t.id)continue;const o=uo(u.get(e.id)||[]);if(!o)continue;const d=`${t.id}|${e.id}`;_.add(d);const g=$s(o.passive?{state:o.on?"on":"off",attributes:{}}:this._renderPlanHass.states[o.eid],e.marker?.glow_color,i.glow_light.c),m=Number(e.marker?.glow_radius_cm),f=Number.isFinite(m)&&m>0?m/this._cellCm*this._gridPitch:s,v=this._pos(e);if(Xl([v.x,v.y],c,h)){this._forgetGlowSource(d);continue}const y=this._glowTransition(d,!!g);if(!y)continue;g&&this._glowLastAppearance.set(d,{c:g.c,alpha:Ss(g.bri,i.glow_light.a)});const b=this._glowLastAppearance.get(d);if(!b)continue;let w=null;const k=`${t.id}|${l}|${v.x.toFixed(4)},${v.y.toFixed(4)}|${f.toFixed(4)}`,x=Ng(this._glowClipCache,k);if(x.hit)w=x.value;else{const e=Ru([v.x,v.y],f,a,96);w={lit:e.length>=3?Ul([e],r,{onBoundsFailure:({boundIndex:e,phase:i})=>{const s=n[e]?.r;this._warnGlowGeometryFallback(t.id,l,s?.id||`#${e}`,i)}}):[]},Hg(this._glowClipCache,k,w,256)}p.push({key:d,sourceEid:o.eid,domId:y.domId,entering:y.entering,leaving:y.leaving,pos:v,c:b.c,alpha:b.alpha,geometry:w,r:f})}const g=`${t.id}|`;for(const t of this._glowRenderedSources.keys())t.startsWith(g)&&!_.has(t)&&this._forgetGlowSource(t);if(!p.length)return j``;const m=this._spaceWalls,f=o.length===n.length?[]:this._openPairs().flatMap(t=>t.segs),v=o.length===n.length?null:o.map(({r:e,poly:i})=>{const s=m.length&&e.id&&hl(t.rooms,e.id,m,f,this._wallKeyPitch,this._cellCm,this._gridPitch,Jg)||i,o=this._cleanFloor(e,s,t).path,a=Ti(s,n.filter(t=>t.r!==e).map(t=>t.poly)),r=t=>"M "+t.map(t=>t[0]+" "+t[1]).join(" L ")+" Z";return[o||r(s),...a.map(r)].join(" ")}),y=this._viewOr(this._baseVb()),b=this._stageEl?.clientWidth&&y.w?this._stageEl.clientWidth/y.w:1,w=1/(b>0?b:1),k=!this._pinchStart&&!this._panStart&&Date.now()>=this._glowFeatherSuspendUntil;(null==this._glowFeatherUnits||k)&&(this._glowFeatherUnits=w);const x=this._glowFeatherUnits??w,$=4*x,S=p.reduce((t,e)=>({x:Math.min(t.x,e.pos.x-e.r-$),y:Math.min(t.y,e.pos.y-e.r-$),maxX:Math.max(t.maxX,e.pos.x+e.r+$),maxY:Math.max(t.maxY,e.pos.y+e.r+$),w:0,h:0}),{x:1/0,y:1/0,maxX:-1/0,maxY:-1/0,w:0,h:0});return S.w=S.maxX-S.x,S.h=S.maxY-S.y,j` + `}get _glowRadiusCm(){const t=Number(this._settings.glow_radius_cm);return Number.isFinite(t)&&t>0?t:300}get _imperial(){return"mi"===this.hass?.config?.unit_system?.length}get _glowRadiusPlaceholder(){const t=this._glowRadiusCm;return this._imperial?String(Math.round(t/30.48*10)/10):String(t/100)}_glowTransition(t,e){let i=this._glowRenderedSources.get(t);if(e){const e=this._glowFadeTimers.get(t);if(null!=e&&(clearTimeout(e),this._glowFadeTimers.delete(t)),null==i){this._suspendGlowFeatherForTransition(),i=++this._glowSourceSeq,this._glowRenderedSources.set(t,i),this._glowEnteringSources.add(t);const e=requestAnimationFrame(()=>{this._glowEnterRafs.get(t)===e&&(this._glowEnterRafs.delete(t),this._glowEnteringSources.delete(t),this.isConnected&&this.requestUpdate())});this._glowEnterRafs.set(t,e)}return{domId:i,entering:this._glowEnteringSources.has(t),leaving:!1}}if(null==i)return null;const s=this._glowEnterRafs.get(t);if(null!=s&&cancelAnimationFrame(s),this._glowEnterRafs.delete(t),this._glowEnteringSources.delete(t),!this._glowFadeTimers.has(t)){this._suspendGlowFeatherForTransition();const e=window.setTimeout(()=>{this._glowFadeTimers.get(t)===e&&(this._glowFadeTimers.delete(t),this._glowRenderedSources.delete(t),this._glowLastAppearance.delete(t),this.isConnected&&this.requestUpdate())},534);this._glowFadeTimers.set(t,e)}return{domId:i,entering:!1,leaving:!0}}_suspendGlowFeatherForTransition(){if(window.matchMedia?.("(prefers-reduced-motion: reduce)").matches)return;this._glowFeatherSuspendUntil=Math.max(this._glowFeatherSuspendUntil,Date.now()+500),clearTimeout(this._glowFeatherResumeTimer);const t=Math.max(0,this._glowFeatherSuspendUntil-Date.now())+17,e=()=>{this._glowFeatherResumeTimer=0,Date.now()=128){const t=this._glowGeometryWarnings.values().next().value;t&&this._glowGeometryWarnings.delete(t)}this._glowGeometryWarnings.add(n),console.warn(`HOUSEPLAN GLOW GEOMETRY FALLBACK: #218, space ${t}, room ${i}, phase ${s}`)}}_lightBarriers(t,e){const i=this._openPairs().flatMap(t=>t.segs),s=[...i],n=Math.max(this._cmToUnits(10),.5*this._gridPitch),o=t=>e.some(e=>this._pointInRoom(t,e.r)),a=this._openingsR.filter(t=>{if("door"!==(e=String(t.type))&&"gate"!==e&&"passage"!==e)return!1;var e;const i=t.angle*Math.PI/180,s=-Math.sin(i),a=Math.cos(i);return o([t.rx+s*n,t.ry+a*n])&&o([t.rx-s*n,t.ry-a*n])}),r=this._roomWallOpeningInputs(a,t);for(const t of r){const e=t.angle*Math.PI/180,i=Math.cos(e)*t.length/2,n=Math.sin(e)*t.length/2;s.push([t.x-i,t.y-n,t.x+i,t.y+n])}const l=new Set(a.filter(t=>t.partitionHost).map(t=>t.id)),c=[t.id,this._cfgEpoch,this._cellCm,this._gridPitch,[...l].sort().join(",")].join("|");this._lightPhysicalBodiesCache?.key!==c&&(this._lightPhysicalBodiesCache={key:c,all:Bl(t,this._cellCm,this._gridPitch,2e-4*this._gridPitch,this._partitionOpeningCuts(t,t=>l.has(t.id))).all});const h=this._lightPhysicalBodiesCache.all;let d=2166136261;const u=t=>{d^=Math.round(64*(Number.isFinite(t)?t:0)),d=Math.imul(d,16777619)>>>0},p=this._spaceWalls;u(this._cellCm),u(this._gridPitch),u(this._wallKeyPitch);for(const{poly:t}of e){u(t.length);for(const e of t)u(e[0]),u(e[1])}for(const t of s)for(const e of t)u(e);for(const t of h){u(t.length);for(const e of t)u(e[0]),u(e[1])}for(const t of p)u(t.cm),u(t.a?.[0]??0),u(t.a?.[1]??0),u(t.b?.[0]??0),u(t.b?.[1]??0);const _=d.toString(36),g=`${t.id}|${_}`;if(this._lightBarrierCache?.key===g)return this._lightBarrierCache.value;const m=.02*this._gridPitch,f=[],v=p.length||h.length?vl(t.rooms,p,i,r,this._wallKeyPitch,this._cellCm,this._gridPitch,Zg,h):null;if(v)for(const t of function(t){const e=[];for(const i of t||[])for(const t of i||[])t?.length>=4&&e.push(t.slice(0,-1).map(t=>[t[0],t[1]]));return e}(v.geom))f.push(...Du(t));else for(const t of h)f.push(...Du(t));for(const{poly:t}of e)for(const e of s.length?Ts(t,s,m):Du(t))f.push(e);const y={occluders:Cu(f),floor:e.map(t=>t.poly),fingerprint:_,masonryGeometry:v?.geom||[],opaqueBodies:h};return this._lightBarrierCache={key:g,value:y},y}_renderGlowLayer(t,e){const i=this._fillColors,s=this._glowRadiusCm/this._cellCm*this._gridPitch,n=t.rooms.map(t=>({r:t,poly:hi(t)})).filter(t=>!!t.poly),o=n.filter(({r:t})=>Es(e.glow,t));if(!o.length)return this._forgetGlowSpace(t.id),j``;const{occluders:a,floor:r,fingerprint:l,masonryGeometry:c,opaqueBodies:h}=this._lightBarriers(t,n),d=ho(this._renderPlanHass,this._renderDevices,null,this._virtualLights).filter(e=>e.device.space===t.id),u=new Map;for(const t of d){if(!t.device.id)continue;const e=u.get(t.device.id)||[];e.push(t),u.set(t.device.id,e)}const p=[],_=new Set;for(const e of this._renderDevices){if(e.space!==t.id)continue;const o=uo(u.get(e.id)||[]);if(!o)continue;const d=`${t.id}|${e.id}`;_.add(d);const g=$s(o.passive?{state:o.on?"on":"off",attributes:{}}:this._renderPlanHass.states[o.eid],e.marker?.glow_color,i.glow_light.c),m=Number(e.marker?.glow_radius_cm),f=Number.isFinite(m)&&m>0?m/this._cellCm*this._gridPitch:s,v=this._pos(e);if(Xl([v.x,v.y],c,h)){this._forgetGlowSource(d);continue}const y=this._glowTransition(d,!!g);if(!y)continue;g&&this._glowLastAppearance.set(d,{c:g.c,alpha:Ss(g.bri,i.glow_light.a)});const b=this._glowLastAppearance.get(d);if(!b)continue;let w=null;const k=`${t.id}|${l}|${v.x.toFixed(4)},${v.y.toFixed(4)}|${f.toFixed(4)}`,x=Hg(this._glowClipCache,k);if(x.hit)w=x.value;else{const e=Ru([v.x,v.y],f,a,96);w={lit:e.length>=3?Ul([e],r,{onBoundsFailure:({boundIndex:e,phase:i})=>{const s=n[e]?.r;this._warnGlowGeometryFallback(t.id,l,s?.id||`#${e}`,i)}}):[]},Lg(this._glowClipCache,k,w,256)}p.push({key:d,sourceEid:o.eid,domId:y.domId,entering:y.entering,leaving:y.leaving,pos:v,c:b.c,alpha:b.alpha,geometry:w,r:f})}const g=`${t.id}|`;for(const t of this._glowRenderedSources.keys())t.startsWith(g)&&!_.has(t)&&this._forgetGlowSource(t);if(!p.length)return j``;const m=this._spaceWalls,f=o.length===n.length?[]:this._openPairs().flatMap(t=>t.segs),v=o.length===n.length?null:o.map(({r:e,poly:i})=>{const s=m.length&&e.id&&hl(t.rooms,e.id,m,f,this._wallKeyPitch,this._cellCm,this._gridPitch,Zg)||i,o=this._cleanFloor(e,s,t).path,a=Ti(s,n.filter(t=>t.r!==e).map(t=>t.poly)),r=t=>"M "+t.map(t=>t[0]+" "+t[1]).join(" L ")+" Z";return[o||r(s),...a.map(r)].join(" ")}),y=this._viewOr(this._baseVb()),b=this._stageEl?.clientWidth&&y.w?this._stageEl.clientWidth/y.w:1,w=1/(b>0?b:1),k=!this._pinchStart&&!this._panStart&&Date.now()>=this._glowFeatherSuspendUntil;(null==this._glowFeatherUnits||k)&&(this._glowFeatherUnits=w);const x=this._glowFeatherUnits??w,$=4*x,S=p.reduce((t,e)=>({x:Math.min(t.x,e.pos.x-e.r-$),y:Math.min(t.y,e.pos.y-e.r-$),maxX:Math.max(t.maxX,e.pos.x+e.r+$),maxY:Math.max(t.maxY,e.pos.y+e.r+$),w:0,h:0}),{x:1/0,y:1/0,maxX:-1/0,maxY:-1/0,w:0,h:0});return S.w=S.maxX-S.x,S.h=S.maxY-S.y,j` ${Mt(p,t=>t.key,t=>{const e=t.domId,i=t.geometry;return j` ${""} - ${Zg.map(([e,i])=>j` + ${Qg.map(([e,i])=>j` `)} @@ -5585,7 +5585,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="5ca433d2ee8bf92a41f4597ac53777315a9c ${this._t("gs.glow_radius")} {const e=Og(t.target.value);null!=e&&e>0&&(this._settingsDialog={...this._settingsDialog,glowRadius:e})}} /> + @input=${t=>{const e=Ng(t.target.value);null!=e&&e>0&&(this._settingsDialog={...this._settingsDialog,glowRadius:e})}} /> ${this._imperial?this._t("gs.unit_ft"):this._t("gs.unit_m")} @@ -5660,7 +5660,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="5ca433d2ee8bf92a41f4597ac53777315a9c `:G} -
${this._t("gs.about_version",{v:Rg})}
+
${this._t("gs.about_version",{v:Ig})}
${this._t("gs.about_github")} @@ -5717,7 +5717,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="5ca433d2ee8bf92a41f4597ac53777315a9c ${t.busy?"…":this._t("btn.save")} -
`}_saveKioskScale(t){this._kioskScale={...this._kioskScale,...t};try{localStorage.setItem(Kg,JSON.stringify(this._kioskScale))}catch{}this.requestUpdate()}_renderKioskDialog(){const t=this._kioskScale,e=(e,i)=>W` +
`}_saveKioskScale(t){this._kioskScale={...this._kioskScale,...t};try{localStorage.setItem(Yg,JSON.stringify(this._kioskScale))}catch{}this.requestUpdate()}_renderKioskDialog(){const t=this._kioskScale,e=(e,i)=>W`
${this._rangeInput(50,300,5,Math.round(100*t[e]),t=>this._saveKioskScale({[e]:t/100}))} ${Math.round(100*t[e])}% @@ -5774,7 +5774,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="5ca433d2ee8bf92a41f4597ac53777315a9c ${this._spaceDialog?this._renderSpaceDialog():G} ${this._importDialog?this._renderImportDialog():G} ${this._toast?W``:G} - `;const s=this._spaceModel();if(!s)return G;const n="valid"===i.kind?[s]:t,o=s.vb,a=this._effectiveProjection();this._renderProjection=a,this._labs.active.length&&function(t){O_||W_(t);const e=z_,i=e.active.join(",");if(!i||i===H_)return;H_=i;const s=new Map(C_.map(t=>[t.id,t])),n=e.active.map(t=>{const e=s.get(t);return`${t} (#${e.issue}, expires ${e.expires})`}).join(", ");console.info(`HOUSEPLAN LABS: ${n}`)}(Rg);const r="iso"===a,l="devices"===this._mode&&this._showAll,c=this._renderDevices.filter(t=>t.space===s.id&&(!t.hidden||l)),h=this._renderDeviceSnapshot,d=this._spaceDisplayForRender(),u=r?this._isoDecorationLayers(d):null,p=u?this._isoOpeningPanels(u):[],_=this._resolvedRoomFills(s,d),g=this._resolvedGlowBase(s,d,_),m=d.showLqi??this._config.show_signal??!0,f=this._config.icon_size??2.5,v=f>8?2.5:f,y=Zu(v),b=this._viewOr(this._baseVb()),w=this._floorView(b),k=this._editing?"":this._stageBg(d),x=this._opMeasureView,$=this._decorMeasure,S=this._bdLive,M=this._furnLive,C="view"===this._mode?this._editorChromeMode:this._mode,D=this._roomHoverPaths(s),T=s.bg?this._display(s.bg.href):"",P=this._continuity.overlayVisible||"recovery-error"===this._continuity.state?this._continuity.recoveryReason:null,R=this._modeTransitionVisual,I=this._dayCycleState(),A=R?.viewWeight??("view"===this._mode?1:0),F=this._modeTransition.state?.from.presentedMode,E=!this._markup||!!R&&("view"===R.presentedMode||"devices"===R.presentedMode||"view"===F||"devices"===F),z=R?.stageColor||k,O=R?.sceneBrightness??1;return W` + `;const s=this._spaceModel();if(!s)return G;const n="valid"===i.kind?[s]:t,o=s.vb,a=this._effectiveProjection();this._renderProjection=a,this._labs.active.length&&function(t){N_||j_(t);const e=O_,i=e.active.join(",");if(!i||i===L_)return;L_=i;const s=new Map(D_.map(t=>[t.id,t])),n=e.active.map(t=>{const e=s.get(t);return`${t} (#${e.issue}, expires ${e.expires})`}).join(", ");console.info(`HOUSEPLAN LABS: ${n}`)}(Ig);const r="iso"===a,l="devices"===this._mode&&this._showAll,c=this._renderDevices.filter(t=>t.space===s.id&&(!t.hidden||l)),h=this._renderDeviceSnapshot,d=this._spaceDisplayForRender(),u=r?this._isoDecorationLayers(d):null,p=u?this._isoOpeningPanels(u):[],_=this._resolvedRoomFills(s,d),g=this._resolvedGlowBase(s,d,_),m=d.showLqi??this._config.show_signal??!0,f=this._config.icon_size??2.5,v=f>8?2.5:f,y=Qu(v),b=this._viewOr(this._baseVb()),w=this._floorView(b),k=this._editing?"":this._stageBg(d),x=this._opMeasureView,$=this._decorMeasure,S=this._bdLive,M=this._furnLive,C="view"===this._mode?this._editorChromeMode:this._mode,D=this._roomHoverPaths(s),T=s.bg?this._display(s.bg.href):"",P=this._continuity.overlayVisible||"recovery-error"===this._continuity.state?this._continuity.recoveryReason:null,R=this._modeTransitionVisual,I=this._dayCycleState(),A=R?.viewWeight??("view"===this._mode?1:0),F=this._modeTransition.state?.from.presentedMode,E=!this._markup||!!R&&("view"===R.presentedMode||"devices"===R.presentedMode||"view"===F||"devices"===F),z=R?.stageColor||k,O=R?.sceneBrightness??1;return W` + transform=${u?.structural?Y_():G}> ${""} ${this._wallHatchDefs(d.color)}${j`${this._paperShapes(s.rooms).map(t=>"path"in t?j``:"poly"in t?j``:j``)}`} ${this._editing?this._renderMarkupDefs(o):G} @@ -5895,7 +5895,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="5ca433d2ee8bf92a41f4597ac53777315a9c transform=${s.bg.angle?`rotate(${s.bg.angle} ${s.bg.x+s.bg.w/2} ${s.bg.y+s.bg.h/2})`:G} @dblclick=${t=>this._openBackdropDialog(t)} preserveAspectRatio="none" />`:G} - ${(()=>{const t=this._openPairs(),e=new Map,i=t=>(e.has(t)||e.set(t,hi(t)),e.get(t));return s.rooms.filter(t=>t.area||"view"===this._mode||this._markup||d.showBorders).map(e=>{let n="room "+(s.bg?"overlay":"yard")+(this._markup?" outlined":"");!this._markup||e.id!==this._mergeSel&&e.id!==this._splitSel?.roomId||(n+=" picked");let o="";const a=Fs(d.fill,e);if(!this._markup&&(d.showBorders||"none"!==a)){n+=" styled";const t=[];t.push(`--room-stroke:${d.color}`,`--room-stroke-op:${d.showBorders?d.opacity:0}`);const i=_.byRoom.get(e)||null;i?(n+=" filled",t.push(`--room-fill:${i.color}`,`--room-fill-op:${i.opacity}`)):t.push("--room-fill:transparent","--room-fill-op:0"),o=t.join(";")}let r;const l=t=>{"view"===this._mode&&(void 0===r&&(r=this._roomArea(e)),this._showTip(t,e.name||this._t("room.unnamed"),r?this._t("tip.area",{value:r}):"",m?this._roomLqi(e.area):null,this._roomTemp(e),this._roomHum(e)))},c=this._markup&&(e.id===this._mergeSel||e.id===this._splitSel?.roomId),h=e.id&&!c?t.filter(t=>t.a.id===e.id||t.b.id===e.id).flatMap(t=>t.segs):[],u=c?[]:this._thickWallCuts(),p=h.concat(u);p.length&&(n+=" noedge");const g=i(e),f=this._spaceWalls,v=f.length&&e.id&&g&&hl(s.rooms,e.id,f,this._openPairs().flatMap(t=>t.segs),this._wallKeyPitch,this._cellCm,this._gridPitch,Jg)||g,y=v?Ti(v,(b=e,s.rooms.filter(t=>t!==b).map(i).filter(Boolean))):[];var b;const w=t=>"M "+t.map(t=>t[0]+" "+t[1]).join(" L ")+" Z",k=v?this._cleanFloor(e,v,s).path:"",x=e.id||G,$=e.area||G,S=k&&v?j`{const t=this._openPairs(),e=new Map,i=t=>(e.has(t)||e.set(t,hi(t)),e.get(t));return s.rooms.filter(t=>t.area||"view"===this._mode||this._markup||d.showBorders).map(e=>{let n="room "+(s.bg?"overlay":"yard")+(this._markup?" outlined":"");!this._markup||e.id!==this._mergeSel&&e.id!==this._splitSel?.roomId||(n+=" picked");let o="";const a=Fs(d.fill,e);if(!this._markup&&(d.showBorders||"none"!==a)){n+=" styled";const t=[];t.push(`--room-stroke:${d.color}`,`--room-stroke-op:${d.showBorders?d.opacity:0}`);const i=_.byRoom.get(e)||null;i?(n+=" filled",t.push(`--room-fill:${i.color}`,`--room-fill-op:${i.opacity}`)):t.push("--room-fill:transparent","--room-fill-op:0"),o=t.join(";")}let r;const l=t=>{"view"===this._mode&&(void 0===r&&(r=this._roomArea(e)),this._showTip(t,e.name||this._t("room.unnamed"),r?this._t("tip.area",{value:r}):"",m?this._roomLqi(e.area):null,this._roomTemp(e),this._roomHum(e)))},c=this._markup&&(e.id===this._mergeSel||e.id===this._splitSel?.roomId),h=e.id&&!c?t.filter(t=>t.a.id===e.id||t.b.id===e.id).flatMap(t=>t.segs):[],u=c?[]:this._thickWallCuts(),p=h.concat(u);p.length&&(n+=" noedge");const g=i(e),f=this._spaceWalls,v=f.length&&e.id&&g&&hl(s.rooms,e.id,f,this._openPairs().flatMap(t=>t.segs),this._wallKeyPitch,this._cellCm,this._gridPitch,Zg)||g,y=v?Ti(v,(b=e,s.rooms.filter(t=>t!==b).map(i).filter(Boolean))):[];var b;const w=t=>"M "+t.map(t=>t[0]+" "+t[1]).join(" L ")+" Z",k=v?this._cleanFloor(e,v,s).path:"",x=e.id||G,$=e.area||G,S=k&&v?j`{this._notePointer(t),this._pointerModality.hoverEnabled&&(this._hoverRoom={space:s.id,room:e})}} @@ -6072,7 +6072,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="5ca433d2ee8bf92a41f4597ac53777315a9c `:G} ${this._toast?W``:G} - `}_vacCandidateStatus(t,e,i=this._planHass){const s=this._bindingStatus("entity:"+t);if("ha_disabled"===s.kind)return"disabled";if("orphaned"===s.kind)return"missing";if("unverified"===s.kind)return"unverified";const n=i?.states?.[t];return"unavailable"===n?.state?"unavailable":e?.hasPosition?"ok":"unsupported"}_vacOpenAllCameras(t){const e=this._haRegistry.entities||{},i=[];for(const[t,s]of Object.entries(this.hass?.states||{})){if(!t.startsWith("camera."))continue;const n=zh(t,s,e[t]);n&&i.push(n)}this._vacAllCameraCache={devId:t.id,candidates:i},this._vacAllCamerasFor=t.id}_vacSourceResolution(t,e=!1,i=this._planHass){const s=t.marker?.vacuum,n="string"==typeof s?.source&&!!s.source,o=new Set(t.entities||[]),a=new Set(o);n&&a.add(s.source);const r=i?.entities||{},l=[];for(const t of a){const e=i?.states?.[t],o=zh(t,e,r[t]);o?l.push(o):n&&t===s.source&&l.push({entityId:t,name:String(e?.attributes?.friendly_name||t),platform:r[t]?.platform?String(r[t].platform):null,category:t.startsWith("camera.")?"camera":"partial",hasPosition:!1,hasRooms:!1,hasPath:!1,hasMapId:!1,score:0})}if(e&&this._vacAllCameraCache?.devId===t.id){const t=new Set(l.map(t=>t.entityId));for(const e of this._vacAllCameraCache.candidates)t.has(e.entityId)||l.push(e)}const c={};for(const t of l)c[t.entityId]=this._vacCandidateStatus(t.entityId,t,i);return function(t,e,i,s){const n="string"==typeof t&&t.length>0,o=new Set(e),a=Array.from(i).sort((e,i)=>n&&e.entityId===t?-1:n&&i.entityId===t?1:i.score-e.score||e.entityId.localeCompare(i.entityId));if(n){const e=a.find(e=>e.entityId===t);return{entityId:t,status:s[t]||(e?.hasPosition?"ok":"unverified"),pinned:!0,candidates:a}}const r=a.find(t=>o.has(t.entityId)&&t.hasPosition&&"ok"===s[t.entityId]);return r?{entityId:r.entityId,status:"ok",pinned:!1,candidates:a}:{entityId:null,status:"none",pinned:!1,candidates:a}}(s?.source,o,l,c)}_vacSource(t,e=this._planHass){if(!1===t.marker?.vacuum?.live)return null;const i=this._vacSourceResolution(t,!1,e);return"ok"===i.status||"unsupported"===i.status?i.entityId:null}_vacEntity(t){return t.primary?.startsWith("vacuum.")?t.primary:(t.entities||[]).find(t=>t.startsWith("vacuum."))||null}_isVacDev(t){return!!this._vacEntity(t)}_activitySourceKey(t){return this._activitySnapshot(t).sourceKey}_activitySnapshot(t,e=ho(this._planHass,this._devices,null,this._virtualLights)){const i=qu(this._planHass,t,this._devices,e,this._fullRegistryHass);return{samples:i.samples,sourceKey:Uu(this._planHass,t,i)}}_stampActivity(t,e,i){let s=this._activityRt.get(t);s||(s=gp(i||"",[]),this._activityRt.set(t,s)),null!=i&&(s.sources=i),fp(s,e,Date.now(),window.clearTimeout.bind(window),t=>window.setTimeout(()=>this.requestUpdate(),t))}_syncActivityRuntime(){const t=new Map;if(!this.hass)return t;if(!1===this._config?.live_states){for(const t of this._activityRt.values())clearTimeout(t.timer);return this._activityRt.clear(),t}const e=new Set,i=ho(this._planHass,this._devices,null,this._virtualLights);for(const s of this._devices){if(s.hidden)continue;if("icon_ripple"!==Bi(s.marker?.display))continue;e.add(s.id);const n=this._activitySnapshot(s,i);t.set(s.id,n);const{samples:o,sourceKey:a}=n;let r=this._activityRt.get(s.id);r?r.sources!==a&&mp(r,a,o,window.clearTimeout.bind(window)):(r=gp(a,o),this._activityRt.set(s.id,r))}for(const[t,i]of this._activityRt)e.has(t)||(clearTimeout(i.timer),this._activityRt.delete(t));return t}_activityTick(){if(!this.hass)return;const t=this._syncActivityRuntime();for(const e of this._devices){if(e.hidden)continue;if("icon_ripple"!==Bi(e.marker?.display))continue;const i=t.get(e.id)||this._activitySnapshot(e),{samples:s,sourceKey:n}=i,o=this._activityRt.get(e.id);if(!o||o.sources!==n)continue;const a=vp(o,s,window.clearTimeout.bind(window));a&&this._stampActivity(e.id,a,n)}}_vacTick(){if(this.hass)for(const t of this._devices){if(t.hidden||!this._isVacDev(t))continue;if("static_icon"===Bi(t.marker?.display)){this._vacRt.delete(t.id);continue}const e=this._vacSource(t);if(!e)continue;const i=this._vacEntity(t),s=Lh(this.hass.states[i||""]?.state),n=Eh(this.hass.states[e]?.attributes);let o=this._vacRt.get(t.id);o||(o={trail:[],lastKey:"",lastTs:0,moving:!1,jump:!1,endedTs:0,lastPos:null},this._vacRt.set(t.id,o)),s&&!o.moving&&(o.trail=[],o.lastPos=null);const a="never"!==Uh(t.marker?.vacuum)&&!n?.path.length;!s&&o.moving&&(o.endedTs=Date.now(),a&&o.lastPos&&(o.trail=Hh(o.trail,o.lastPos,40)),o.lastPos=null),o.moving=s;const r=n?.pos;if(s&&r){const t=r.x+":"+r.y;if(t!==o.lastKey){const e=Date.now();o.jump=o.lastTs>0&&e-o.lastTs>1e4,o.lastKey=t,o.lastTs=e,a&&o.lastPos&&(o.trail=Hh(o.trail,o.lastPos,40)),o.lastPos=[r.x,r.y]}}}}_vacEnsureMarker(t){const e=this._serverCfg;if(!e)return null;e.markers=e.markers||[];const i=e.markers.find(e=>e.id===t.id);if(i)return i;if("device"!==t.bindingKind&&"entity"!==t.bindingKind||!t.bindingRef)return null;const s={id:t.id,binding:t.bindingKind+":"+t.bindingRef,space:t.space||null,area:t.area||null,hidden:!!t.hidden};return e.markers.push(s),s}_renderVacSection(t){const e=this._devices.find(e=>e.id===t.devId);if(!e||!this._isVacDev(e))return G;const i=e.marker?.vacuum||{},s=this._vacAllCamerasFor===e.id,n=this._vacSourceResolution(e,s),o=n.entityId,a=n.candidates.find(t=>t.entityId===o)||null,r=o?Eh(this.hass?.states[o]?.attributes):null,l=!1!==i.live&&("ok"===n.status||"unsupported"===n.status),c=this._vacPlanRoomAnchors(e.space),h=r?function(t,e){const i=new Set(e.map(Oh).filter(Boolean)),s=new Set;for(const e of t){const t=Oh(e.name||"");t&&i.has(t)&&s.add(t)}return s.size}(r.rooms,c.map(t=>t.name)):0,d=!!(l&&r&&h>=3),u=Object.keys(i.calibration||{}),p=t=>{const i=this._vacEnsureMarker(e);i&&(i.vacuum={...i.vacuum||{},...t},this._regSignature="",this._maybeRebuildDevices(),this._saveConfig(),this.requestUpdate())},_=new Set(e.entities||[]),g=n.candidates.filter(t=>_.has(t.entityId)||t.entityId===i.source),m=s?n.candidates.filter(t=>t.entityId.startsWith("camera.")&&!g.some(e=>e.entityId===t.entityId)):[],f=t=>[t.hasPosition?this._t("vac.cap_position"):"",t.hasRooms?this._t("vac.cap_rooms_short"):"",t.hasPath?this._t("vac.cap_path"):"",t.hasMapId?this._t("vac.cap_map"):""].filter(Boolean).join(" · ")||this._t("vac.cap_none"),v=t=>W` + `}_vacCandidateStatus(t,e,i=this._planHass){const s=this._bindingStatus("entity:"+t);if("ha_disabled"===s.kind)return"disabled";if("orphaned"===s.kind)return"missing";if("unverified"===s.kind)return"unverified";const n=i?.states?.[t];return"unavailable"===n?.state?"unavailable":e?.hasPosition?"ok":"unsupported"}_vacOpenAllCameras(t){const e=this._haRegistry.entities||{},i=[];for(const[t,s]of Object.entries(this.hass?.states||{})){if(!t.startsWith("camera."))continue;const n=zh(t,s,e[t]);n&&i.push(n)}this._vacAllCameraCache={devId:t.id,candidates:i},this._vacAllCamerasFor=t.id}_vacSourceResolution(t,e=!1,i=this._planHass){const s=t.marker?.vacuum,n="string"==typeof s?.source&&!!s.source,o=new Set(t.entities||[]),a=new Set(o);n&&a.add(s.source);const r=i?.entities||{},l=[];for(const t of a){const e=i?.states?.[t],o=zh(t,e,r[t]);o?l.push(o):n&&t===s.source&&l.push({entityId:t,name:String(e?.attributes?.friendly_name||t),platform:r[t]?.platform?String(r[t].platform):null,category:t.startsWith("camera.")?"camera":"partial",hasPosition:!1,hasRooms:!1,hasPath:!1,hasMapId:!1,score:0})}if(e&&this._vacAllCameraCache?.devId===t.id){const t=new Set(l.map(t=>t.entityId));for(const e of this._vacAllCameraCache.candidates)t.has(e.entityId)||l.push(e)}const c={};for(const t of l)c[t.entityId]=this._vacCandidateStatus(t.entityId,t,i);return function(t,e,i,s){const n="string"==typeof t&&t.length>0,o=new Set(e),a=Array.from(i).sort((e,i)=>n&&e.entityId===t?-1:n&&i.entityId===t?1:i.score-e.score||e.entityId.localeCompare(i.entityId));if(n){const e=a.find(e=>e.entityId===t);return{entityId:t,status:s[t]||(e?.hasPosition?"ok":"unverified"),pinned:!0,candidates:a}}const r=a.find(t=>o.has(t.entityId)&&t.hasPosition&&"ok"===s[t.entityId]);return r?{entityId:r.entityId,status:"ok",pinned:!1,candidates:a}:{entityId:null,status:"none",pinned:!1,candidates:a}}(s?.source,o,l,c)}_vacSource(t,e=this._planHass){if(!1===t.marker?.vacuum?.live)return null;const i=this._vacSourceResolution(t,!1,e);return"ok"===i.status||"unsupported"===i.status?i.entityId:null}_vacEntity(t){return t.primary?.startsWith("vacuum.")?t.primary:(t.entities||[]).find(t=>t.startsWith("vacuum."))||null}_isVacDev(t){return!!this._vacEntity(t)}_activitySourceKey(t){return this._activitySnapshot(t).sourceKey}_activitySnapshot(t,e=ho(this._planHass,this._devices,null,this._virtualLights)){const i=Wu(this._planHass,t,this._devices,e,this._fullRegistryHass);return{samples:i.samples,sourceKey:Gu(this._planHass,t,i)}}_stampActivity(t,e,i){let s=this._activityRt.get(t);s||(s=mp(i||"",[]),this._activityRt.set(t,s)),null!=i&&(s.sources=i),vp(s,e,Date.now(),window.clearTimeout.bind(window),t=>window.setTimeout(()=>this.requestUpdate(),t))}_syncActivityRuntime(){const t=new Map;if(!this.hass)return t;if(!1===this._config?.live_states){for(const t of this._activityRt.values())clearTimeout(t.timer);return this._activityRt.clear(),t}const e=new Set,i=ho(this._planHass,this._devices,null,this._virtualLights);for(const s of this._devices){if(s.hidden)continue;if("icon_ripple"!==Bi(s.marker?.display))continue;e.add(s.id);const n=this._activitySnapshot(s,i);t.set(s.id,n);const{samples:o,sourceKey:a}=n;let r=this._activityRt.get(s.id);r?r.sources!==a&&fp(r,a,o,window.clearTimeout.bind(window)):(r=mp(a,o),this._activityRt.set(s.id,r))}for(const[t,i]of this._activityRt)e.has(t)||(clearTimeout(i.timer),this._activityRt.delete(t));return t}_activityTick(){if(!this.hass)return;const t=this._syncActivityRuntime();for(const e of this._devices){if(e.hidden)continue;if("icon_ripple"!==Bi(e.marker?.display))continue;const i=t.get(e.id)||this._activitySnapshot(e),{samples:s,sourceKey:n}=i,o=this._activityRt.get(e.id);if(!o||o.sources!==n)continue;const a=yp(o,s,window.clearTimeout.bind(window));a&&this._stampActivity(e.id,a,n)}}_vacTick(){if(this.hass)for(const t of this._devices){if(t.hidden||!this._isVacDev(t))continue;if("static_icon"===Bi(t.marker?.display)){this._vacRt.delete(t.id);continue}const e=this._vacSource(t);if(!e)continue;const i=this._vacEntity(t),s=Lh(this.hass.states[i||""]?.state),n=Eh(this.hass.states[e]?.attributes);let o=this._vacRt.get(t.id);o||(o={trail:[],lastKey:"",lastTs:0,moving:!1,jump:!1,endedTs:0,lastPos:null},this._vacRt.set(t.id,o)),s&&!o.moving&&(o.trail=[],o.lastPos=null);const a="never"!==Uh(t.marker?.vacuum)&&!n?.path.length;!s&&o.moving&&(o.endedTs=Date.now(),a&&o.lastPos&&(o.trail=Hh(o.trail,o.lastPos,40)),o.lastPos=null),o.moving=s;const r=n?.pos;if(s&&r){const t=r.x+":"+r.y;if(t!==o.lastKey){const e=Date.now();o.jump=o.lastTs>0&&e-o.lastTs>1e4,o.lastKey=t,o.lastTs=e,a&&o.lastPos&&(o.trail=Hh(o.trail,o.lastPos,40)),o.lastPos=[r.x,r.y]}}}}_vacEnsureMarker(t){const e=this._serverCfg;if(!e)return null;e.markers=e.markers||[];const i=e.markers.find(e=>e.id===t.id);if(i)return i;if("device"!==t.bindingKind&&"entity"!==t.bindingKind||!t.bindingRef)return null;const s={id:t.id,binding:t.bindingKind+":"+t.bindingRef,space:t.space||null,area:t.area||null,hidden:!!t.hidden};return e.markers.push(s),s}_renderVacSection(t){const e=this._devices.find(e=>e.id===t.devId);if(!e||!this._isVacDev(e))return G;const i=e.marker?.vacuum||{},s=this._vacAllCamerasFor===e.id,n=this._vacSourceResolution(e,s),o=n.entityId,a=n.candidates.find(t=>t.entityId===o)||null,r=o?Eh(this.hass?.states[o]?.attributes):null,l=!1!==i.live&&("ok"===n.status||"unsupported"===n.status),c=this._vacPlanRoomAnchors(e.space),h=r?function(t,e){const i=new Set(e.map(Oh).filter(Boolean)),s=new Set;for(const e of t){const t=Oh(e.name||"");t&&i.has(t)&&s.add(t)}return s.size}(r.rooms,c.map(t=>t.name)):0,d=!!(l&&r&&h>=3),u=Object.keys(i.calibration||{}),p=t=>{const i=this._vacEnsureMarker(e);i&&(i.vacuum={...i.vacuum||{},...t},this._regSignature="",this._maybeRebuildDevices(),this._saveConfig(),this.requestUpdate())},_=new Set(e.entities||[]),g=n.candidates.filter(t=>_.has(t.entityId)||t.entityId===i.source),m=s?n.candidates.filter(t=>t.entityId.startsWith("camera.")&&!g.some(e=>e.entityId===t.entityId)):[],f=t=>[t.hasPosition?this._t("vac.cap_position"):"",t.hasRooms?this._t("vac.cap_rooms_short"):"",t.hasPath?this._t("vac.cap_path"):"",t.hasMapId?this._t("vac.cap_map"):""].filter(Boolean).join(" · ")||this._t("vac.cap_none"),v=t=>W`
`)}return this._vacLastView=e,n.length&&!this._vacRaf&&this._vacRafLoop(),n.length||o.length?W` ${o.length?j`${o}`:G} - ${n}`:G}_renderDevice(t,e,i=!0){const s=this._pos(t),n=this._scenePoint([s.x,s.y]),o=(n[0]-e.x)/e.w*100,a=(n[1]-e.y)/e.h*100,r=this._devicePresentation(t,i),l=[`left:${o}%`,`top:${a}%`,...Go(r)],c=r.disabledReason,h=r.haDisabled?this._t(`marker.ha_disabled_${c}`):t.userHidden?this._t("marker.hidden_ghost"):t.name,d=Ou(r),u="view"===this._mode||"devices"===this._mode,p=[h,r.haDisabled?"":this._t(`marker.state_a11y_${d}`),"none"!==r.pulse.kind?this._t(`marker.pulse_a11y_${r.pulse.reason}`):"",r.valueFullText||r.valueText||"",Ro(r.valueBadge),null!=r.lqiText&&r.lqiBand?this._t(`marker.lqi_a11y_${r.lqiBand}`,{value:r.lqiText}):""].filter(Boolean).join(", "),_=[t.model,r.valueBadge?.fullText||"",null!=r.lqiText?"LQI "+r.lqiText:""].filter(Boolean).join(" · ");return W`
`}_roomArea(t){const e=hi(t);if(!e)return null;const i=this._spaceModel();if(!i)return null;const s=this._spaceWalls,n=s.length&&t.id&&hl(i.rooms,t.id,s,this._openPairs().flatMap(t=>t.segs),this._wallKeyPitch,this._cellCm,this._gridPitch,Jg)||e,o=this._cleanFloor(t,n),a=this._cellCm/this._gridPitch;return Ia(o.area*a*a/1e4,"mi"===this._renderPlanHass?.config?.unit_system?.length)}_roomTemp(t){const e=t.settings?.temp_source;return e?Mo(this._renderPlanHass,e,"temp",this._markers):t.area?this._climate().get(t.area)?.temp??null:null}_roomHum(t){const e=t.settings?.hum_source;return e?Mo(this._renderPlanHass,e,"hum",this._markers):t.area?this._climate().get(t.area)?.hum??null:null}_climate(){const t=this._serverCfg?.markers,e=this._renderPlanHass,i=this._climateCache;if(i&&i.h===e&&i.r===this._iconRules&&i.mk===t)return i.m;const s=function(t,e,i){const s=new Map;if(!t?.entities)return s;const n=wo(i),o=new Set;for(const t of i||[]){if(t?.removed||!0!==t?.use_climate_temp)continue;const e=(t.binding||"").indexOf(":");e>0&&o.add(t.binding.slice(e+1))}const a=new Map;for(const[e,i]of Object.entries(t.entities)){if(i.device_id&&n.devices.has(i.device_id)||!i.device_id&&n.entities.has(e))continue;const s=i.device_id?t.devices?.[i.device_id]:null,r=i.area_id||s?.area_id||null;if(!r)continue;if(i.entity_category)continue;if(!(o.size>0&&e.startsWith("climate.")&&(o.has(e)||i.device_id&&o.has(i.device_id)))){if(Yt.has(i.platform))continue;if(Co.test(e))continue}let l=a.get(r);l||(l=new Map,a.set(r,l));const c=i.device_id||e;let h=l.get(c);if(!h){const n=t.states?.[e];h={name:(s?s.name_by_user||s.name:i.name||n?.attributes?.friendly_name||e)||e,model:s?.model,ents:[]},l.set(c,h)}h.ents.push(e)}for(const[i,n]of a){const a=[],r=[];for(const[i,s]of n){const n=bo(t,s.name,s.model,s.ents,e),l="mdi:thermometer"===n||"mdi:air-filter"===n;if(l){const e=go(t,s.ents);null!=e&&a.push(e)}if(o.size>0&&(o.has(i)||s.ents.some(t=>o.has(t)))){const e=mo(t,s.ents);null!=e&&a.push(e)}if(l||"mdi:water-percent"===n){const e=vo(t,s.ents);null!=e&&r.push(e)}}(a.length||r.length)&&s.set(i,{temp:a.length?Math.round(a.reduce((t,e)=>t+e,0)/a.length*10)/10:null,hum:r.length?Math.round(r.reduce((t,e)=>t+e,0)/r.length):null})}return s}(e,this._iconRules,t);return this._climateCache={h:e,r:this._iconRules,mk:t,m:s},s}_resetRoomDialogFields(){this._roomEditId=null,this._roomFill="",this._roomCustomFill=null,this._roomTempSrc="",this._roomHumSrc="",this._roomSrcOpen=null,this._roomSrcFilter="",this._roomNameScale=1,this._roomLabelScale=1}_openRoomEdit(t){if(!t.id)return;this._roomEditId=t.id,this._nameSel=t.name||"",this._areaSel=t.area||"",this._roomFill="glow"===t.settings?.fill_mode?"":t.settings?.fill_mode||"";const e=t.settings?.custom_fill;this._roomCustomFill=e&&"object"==typeof e?rs(e,cs(this._curSpaceCfg).customFill):null,this._roomTempSrc=t.settings?.temp_source||"",this._roomHumSrc=t.settings?.hum_source||"",this._roomNameScale=zs(t.settings?.name_scale),this._roomLabelScale=zs(t.settings?.label_scale),this._roomSrcOpen=null,this._roomSrcFilter="",this._roomDialog=!0}_roomSettingsFromDialog(){const t={};return this._roomFill&&(t.fill_mode=this._roomFill),this._roomCustomFill&&(t.custom_fill=this._roomCustomFill),this._roomTempSrc&&(t.temp_source=this._roomTempSrc),this._roomHumSrc&&(t.hum_source=this._roomHumSrc),1!==this._roomNameScale&&(t.name_scale=this._roomNameScale),1!==this._roomLabelScale&&(t.label_scale=this._roomLabelScale),Object.keys(t).length?t:null}_saveRoomEdit(){const t=this._curSpaceCfg,e=t?.rooms.find(t=>t.id===this._roomEditId);if(!e)return this._roomDialog=!1,void(this._roomEditId=null);e.name=this._nameSel.trim()||e.name,e.area=this._areaSel||null;const i=e.settings||{},s={...i};this._roomFill?s.fill_mode=this._roomFill:delete s.fill_mode,this._roomCustomFill?s.custom_fill=this._roomCustomFill:delete s.custom_fill,"glow"===i.fill_mode&&"boolean"!=typeof i.glow&&(s.glow=!0),this._roomTempSrc?s.temp_source=this._roomTempSrc:delete s.temp_source,this._roomHumSrc?s.hum_source=this._roomHumSrc:delete s.hum_source,1!==this._roomNameScale?s.name_scale=this._roomNameScale:delete s.name_scale,1!==this._roomLabelScale?s.label_scale=this._roomLabelScale:delete s.label_scale,Object.keys(s).length?e.settings=s:delete e.settings,this._saveConfig(),this._roomDialog=!1,this._roomEditId=null,this._nameSel="",this._areaSel="",this._regSignature="",this._maybeRebuildDevices(),this.requestUpdate(),this._showToast(this._t("toast.room_updated"))}_roomSrcCandidates(){const t=this._planHass,e=wo(this._markers),i=this._roomSrcFilter.trim().toLowerCase(),s=[];for(const n of Object.values(t.devices)){if("service"===n.entry_type)continue;if(e.devices.has(n.id))continue;const t=(n.name_by_user||n.name||n.id).trim();i&&!t.toLowerCase().includes(i)||s.push({value:"device:"+n.id,label:t,sub:n.model||this._t("marker.sub_device")})}for(const[n,o]of Object.entries(t.entities)){if(!n.startsWith("sensor.")||o.hidden)continue;if(ko(t,n,e))continue;const a=o.name||t.states[n]?.attributes?.friendly_name||n;i&&!(a+" "+n).toLowerCase().includes(i)||s.push({value:"entity:"+n,label:a,sub:n})}return s.sort((t,e)=>t.label.localeCompare(e.label)),s.slice(0,200)}_roomSrcLabel(t){const e=t.indexOf(":"),i=t.slice(0,e),s=t.slice(e+1);return"device"===i?this._fullRegistryHass.devices[s]?.name_by_user||this._fullRegistryHass.devices[s]?.name||s:this._fullRegistryHass.entities[s]?.name||this.hass.states[s]?.attributes?.friendly_name||s}_labelPos(t,e){const i=this._layout["rl_"+(t.id||"")];if(i&&i.s===e)return{x:i.x*Jg,y:i.y*Jg};const s=this._snap(this._roomCenter(t));return{x:s[0],y:s[1]}}_labelDown(t,e,i){if("plan"!==this._mode)return;t.preventDefault(),t.stopPropagation();const s=this._labelPos(e,i);this._drag={id:"rl_"+(e.id||""),sx:t.clientX,sy:t.clientY,ox:s.x,oy:s.y,moved:!1},om(t),this._tip=null}_labelMove(t,e,i){const s="rl_"+(e.id||"");if(!this._drag||this._drag.id!==s)return;const n=this._stageEl;if(!n)return;const o=this._spaceModelById(i);if(!o)return;const a=o.vb,r=n.getBoundingClientRect(),l=this._viewOr(a),c=(t.clientX-this._drag.sx)/r.width*l.w,h=(t.clientY-this._drag.sy)/r.height*l.h;Math.abs(t.clientX-this._drag.sx)+Math.abs(t.clientY-this._drag.sy)>3&&(this._drag.moved=!0);const d=fc(this._drag.ox+c),u=fc(this._drag.oy+h);this._savePos({id:s,space:i},d,u)}_labelUp(t){const e="rl_"+(t.id||"");if(!this._drag||this._drag.id!==e)return;const i=this._drag.moved;this._drag=i?this._drag:null,i&&window.setTimeout(()=>this._drag=null,0)}_labelScale(t){const e=this._layout["rl_"+(t.id||"")]?.k;return"number"==typeof e&&Number.isFinite(e)?Math.min(3,Math.max(.5,e)):1}_rlResizeDown(t,e,i){if("plan"!==this._mode)return;t.preventDefault(),t.stopPropagation();const s=t.target.closest(".roomlabel");if(!s)return;const n=s.getBoundingClientRect(),o=n.left+n.width/2,a=n.top+n.height/2,r=Math.max(8,Math.hypot(t.clientX-o,t.clientY-a));this._rlResize={id:"rl_"+(e.id||""),space:i,k0:this._labelScale(e),cx:o,cy:a,d0:r},om(t)}_rlResizeMove(t){const e=this._rlResize;if(!e)return;t.stopPropagation();const i=Math.max(8,Math.hypot(t.clientX-e.cx,t.clientY-e.cy)),s=Math.min(3,Math.max(.5,e.k0*(i/e.d0))),n=this._layout[e.id];if(n)this._layout={...this._layout,[e.id]:{...n,k:s}};else{const t=e.id.slice(3),i=this._spaceModelById(e.space);if(!i)return;const n=i.rooms.find(e=>e.id===t);if(!n)return;const o=this._labelPos(n,e.space);this._layout={...this._layout,[e.id]:{s:e.space,x:o.x/Jg,y:o.y/Jg,k:s}}}this._dirtyPos.add(e.id)}_rlResizeUp(){this._rlResize&&(this._rlResize=null,this._persistLayout())}_renderRoomGear(t,e,i){if(!t.id)return G;let s=null;if(t.poly?(s=this._gearPtCache.get(t.poly)||null,s||(s=$i(t.poly),this._gearPtCache.set(t.poly,s))):null!=t.x&&null!=t.y&&(s=[t.x+(t.w||0)/2,t.y+(t.h||0)/2]),!s)return G;const n=(s[0]-i.x)/i.w*100,o=(s[1]-i.y)/i.h*100;return W`
`}get _measureAnchor(){return this._markup&&this._cursorPt?"draw"===this._tool&&this._path.length&&!this._contourClosed?this._path[this._path.length-1]:"split"===this._tool&&this._splitSel?.pts?.length?this._splitSel.pts[this._splitSel.pts.length-1]:null:null}_renderMeasureLabel(t){const e=this._measureAnchor,i=this._cursorPt,s=(i[0]-t.x)/t.w*100,n=(i[1]-t.y)/t.h*100,o=Os(e,i),a=Math.round(10*o)/10,r=function(t,e,i=.001){if(t.length<2||e.length<2)return!1;const s=Math.abs(e[0]-t[0]),n=Math.abs(e[1]-t[1]);if(!Number.isFinite(s)||!Number.isFinite(n)||Math.hypot(s,n)<=i)return!1;const o=Math.max(s,n,1);return s<=i*o||n<=i*o||Math.abs(s-n)<=i*o}(e,i,2e-4*this._gridPitch);return W`
- ${this._fmtLen(e,i)} · ${a}°
`}get _decorMeasure(){const t=this._decorDraft;if(!t||"decor"!==this._mode)return null;const[e,i]=t.a,[s,n]=t.b;if(Math.abs(e-s)<1e-6&&Math.abs(i-n)<1e-6)return null;const o=(e+s)/2,a=(i+n)/2;if("line"===t.kind){const e=Os(t.a,t.b);return{x:o,y:a,on45:Ns(e),text:`${this._fmtLen(t.a,t.b)} · ${Math.round(10*e)/10}°`}}const r=this._fmtLen([e,i],[s,i]),l=this._fmtLen([s,i],[s,n]);if("ellipse"===t.kind){const t=this._fmtLen([0,0],[Math.abs(s-e)/2,0]),r=this._fmtLen([0,0],[0,Math.abs(n-i)/2]);return{x:o,y:a,on45:!1,text:Math.abs(Math.abs(s-e)-Math.abs(n-i))<1e-6?`R ${t}`:`Rx ${t} × Ry ${r}`}}return{x:o,y:a,on45:!1,text:`${r} × ${l} · ${Ia(hr(Math.abs(s-e),this._cellCm,this._gridPitch)*hr(Math.abs(n-i),this._cellCm,this._gridPitch)/1e4,this._imperial)}`}}get _alignPoint(){if(this._markup){if("draw"===this._tool&&this._path.length&&!this._contourClosed&&this._cursorPt)return this._cursorPt;if("split"===this._tool&&this._splitSel?.pts?.length&&this._cursorPt)return this._cursorPt;if(this._drag?.id.startsWith("rl_")&&this._drag.moved){const t=this._drag.id.slice(3),e=this._spaceModel()?.rooms.find(e=>e.id===t);return e?(()=>{const t=this._labelPos(e,this._space);return[t.x,t.y]})():null}return null}if("devices"===this._mode&&this._drag?.moved){const t=this._devices.find(t=>t.id===this._drag.id);return t?(()=>{const e=this._pos(t);return[e.x,e.y]})():null}if("decor"===this._mode){if(this._decorDraft)return this._decorDraft.b;if(this._decorMove){const t=this._decorList.find(t=>t.id===this._decorMove.id);if(!t)return null;const e=Jg,i=this._decorH;return"line"===t.kind?[t.x1*e,t.y1*i]:[t.x*e,t.y*i]}return null}return null}_alignCandidates(){const t=[],e=this._spaceModel();if(this._markup){if(!e)return t;if(this._drag?.id.startsWith("rl_")){const i=this._drag.id.slice(3);for(const s of e.rooms){if(!s.name||s.id===i)continue;const e=this._labelPos(s,this._space);t.push([e.x,e.y])}return t}for(const i of e.rooms){const e=hi(i);if(e)for(const i of e)t.push(i)}if("draw"===this._tool)for(const e of this._path)t.push(e);if("split"===this._tool&&this._splitSel?.pts)for(const e of this._splitSel.pts)t.push(e);return t}if("devices"===this._mode){for(const e of this._devices){if(e.space!==this._space||e.id===this._drag?.id||"ha_disabled"===e.bindingStatus?.kind)continue;const i=this._pos(e);t.push([i.x,i.y])}return t}if("decor"===this._mode){const e=this._decorMove?.id;return t.push(...this._decorSnapGeometry(e).points),this._decorDraft&&t.push(this._decorDraft.a),t}return t}_renderAlignGuides(){const t=this._alignPoint;if(!t)return j``;const e=this._drag?.id.startsWith("rl_")?.5*this._gridPitch:.05*this._gridPitch,i=function(t,e,i){let s=null,n=null;for(const o of e)if(!(Math.abs(o[0]-t[0])<1e-6&&Math.abs(o[1]-t[1])<1e-6)){if(Math.abs(o[0]-t[0])<=i){const e=Math.abs(o[1]-t[1]);e>1e-6&&(!s||e1e-6&&(!n||e + ${this._fmtLen(e,i)} · ${a}°`}get _decorMeasure(){const t=this._decorDraft;if(!t||"decor"!==this._mode)return null;const[e,i]=t.a,[s,n]=t.b;if(Math.abs(e-s)<1e-6&&Math.abs(i-n)<1e-6)return null;const o=(e+s)/2,a=(i+n)/2;if("line"===t.kind){const e=Os(t.a,t.b);return{x:o,y:a,on45:Ns(e),text:`${this._fmtLen(t.a,t.b)} · ${Math.round(10*e)/10}°`}}const r=this._fmtLen([e,i],[s,i]),l=this._fmtLen([s,i],[s,n]);if("ellipse"===t.kind){const t=this._fmtLen([0,0],[Math.abs(s-e)/2,0]),r=this._fmtLen([0,0],[0,Math.abs(n-i)/2]);return{x:o,y:a,on45:!1,text:Math.abs(Math.abs(s-e)-Math.abs(n-i))<1e-6?`R ${t}`:`Rx ${t} × Ry ${r}`}}return{x:o,y:a,on45:!1,text:`${r} × ${l} · ${Ia(hr(Math.abs(s-e),this._cellCm,this._gridPitch)*hr(Math.abs(n-i),this._cellCm,this._gridPitch)/1e4,this._imperial)}`}}get _alignPoint(){if(this._markup){if("draw"===this._tool&&this._path.length&&!this._contourClosed&&this._cursorPt)return this._cursorPt;if("split"===this._tool&&this._splitSel?.pts?.length&&this._cursorPt)return this._cursorPt;if(this._drag?.id.startsWith("rl_")&&this._drag.moved){const t=this._drag.id.slice(3),e=this._spaceModel()?.rooms.find(e=>e.id===t);return e?(()=>{const t=this._labelPos(e,this._space);return[t.x,t.y]})():null}return null}if("devices"===this._mode&&this._drag?.moved){const t=this._devices.find(t=>t.id===this._drag.id);return t?(()=>{const e=this._pos(t);return[e.x,e.y]})():null}if("decor"===this._mode){if(this._decorDraft)return this._decorDraft.b;if(this._decorMove){const t=this._decorList.find(t=>t.id===this._decorMove.id);if(!t)return null;const e=Zg,i=this._decorH;return"line"===t.kind?[t.x1*e,t.y1*i]:[t.x*e,t.y*i]}return null}return null}_alignCandidates(){const t=[],e=this._spaceModel();if(this._markup){if(!e)return t;if(this._drag?.id.startsWith("rl_")){const i=this._drag.id.slice(3);for(const s of e.rooms){if(!s.name||s.id===i)continue;const e=this._labelPos(s,this._space);t.push([e.x,e.y])}return t}for(const i of e.rooms){const e=hi(i);if(e)for(const i of e)t.push(i)}if("draw"===this._tool)for(const e of this._path)t.push(e);if("split"===this._tool&&this._splitSel?.pts)for(const e of this._splitSel.pts)t.push(e);return t}if("devices"===this._mode){for(const e of this._devices){if(e.space!==this._space||e.id===this._drag?.id||"ha_disabled"===e.bindingStatus?.kind)continue;const i=this._pos(e);t.push([i.x,i.y])}return t}if("decor"===this._mode){const e=this._decorMove?.id;return t.push(...this._decorSnapGeometry(e).points),this._decorDraft&&t.push(this._decorDraft.a),t}return t}_renderAlignGuides(){const t=this._alignPoint;if(!t)return j``;const e=this._drag?.id.startsWith("rl_")?.5*this._gridPitch:.05*this._gridPitch,i=function(t,e,i){let s=null,n=null;for(const o of e)if(!(Math.abs(o[0]-t[0])<1e-6&&Math.abs(o[1]-t[1])<1e-6)){if(Math.abs(o[0]-t[0])<=i){const e=Math.abs(o[1]-t[1]);e>1e-6&&(!s||e1e-6&&(!n||e ${i.map(e=>{const[i,o,a,r]="x"===e.axis?[e.at,e.from[1],e.at,t[1]+Math.sign(t[1]-e.from[1])*n]:[e.from[0],e.at,t[0]+Math.sign(t[0]-e.from[0])*n,e.at];return j` `})} @@ -6231,7 +6231,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="5ca433d2ee8bf92a41f4597ac53777315a9c `)} - `:Fu(e)} + `:Eu(e)}
- `});return j``}const tp=new WeakMap,ep=new WeakMap;function ip(t){const e=cc(t.cfg),i={};for(const e of t.cfg.spaces||[])for(const t of e.rooms||[])t.area&&(i[t.area]=e.id);const s=t.cfg.settings?.exclude_integrations?new Set(t.cfg.settings.exclude_integrations):Yt,n=Jt(t.cfg.settings?.icon_rules?.length?t.cfg.settings.icon_rules:Xt);return So({hass:t.hass,registry:t.registry,areaToSpace:i,markers:t.cfg.markers||[],settings:t.cfg.settings||{},excluded:s,showAll:!!t.cfg.settings?.show_all,firstSpaceId:e[0]?.id||"",loc:e=>la(t.lang,e),iconRules:n})}function sp(t){const e=cc(t.cfg).find(e=>e.id===t.spaceId);if(!e)return null;const i=cs(t.cfg.spaces.find(e=>e.id===t.spaceId)),s=us(t.cfg.settings),n=t.iconSize??2.5,o=n>8?2.5:n,a=Zu(o),r=t.registry?On(t.hass,t.registry):t.hass,l=t.registry?Nn(t.hass,t.registry):t.hass,c=(t.devices||ip(t)).filter(e=>e.space===t.spaceId),h=c.filter(t=>!t.hidden),d=function(t,e,i){const s={},n=i/100*Pc(e)*1.3;for(const i of e.rooms){if(!i.area)continue;const e=t.filter(t=>t.area===i.area);if(!e.length)continue;const o=Ac(i),a=.1*Math.min(o.w,o.h),r=o.w-2*a,l=o.h-2*a,c=Math.max(1,Math.round(Math.sqrt(e.length*r/Math.max(l,1)))),h=r/c,d=l/Math.max(Math.ceil(e.length/c),1),u=e.map((t,e)=>({x:o.x+a+h*(e%c+.5),y:o.y+a+d*(Math.floor(e/c)+.5)}));Ni(u,o,n,.5*a),e.forEach((t,e)=>s[t.id]=mc(u[e]))}return s}(c,e,o),u=[];for(const e of h){const i=t.layout[e.id];if(i&&i.s===t.spaceId){const t=i.x*sc,e=i.y*sc;u.push({minX:t,minY:e,maxX:t,maxY:e})}}const p=t.cfg.spaces.find(e=>e.id===t.spaceId)||{},_=Array.isArray(p.walls)?p.walls:[],g=Number(p.cell_cm)>0?Number(p.cell_cm):5,m=(p.openings||[]).flatMap(t=>{if(!t.host)return[];const i=wd(t,e.partitions,sc,g,pc).resolved;return i?[i]:[]}),f=vh({partitions:e.partitions,roomDrafts:e.room_drafts,columns:e.wall_columns,cellCm:g,hostedOpenings:m.map(t=>({id:t.opening.id,host:t.host,length:t.length,type:t.opening.type}))}),v=function(t,e,i,s){let n=ep.get(t);n||(n=new Map,ep.set(t,n));const o=n.get(e);if(o?.fingerprint===i)return o.value;const a=s();return n.set(e,{fingerprint:i,value:a}),a}(t.cfg,e.id,f,()=>Bl(e,g,pc,2e-4*pc,m.map($d)).all);for(const t of v){const e=t.map(t=>t[0]),i=t.map(t=>t[1]);e.length&&u.push({minX:Math.min(...e),minY:Math.min(...i),maxX:Math.max(...e),maxY:Math.max(...i)})}const y=Dc(e,u),b=[y.x,y.y,y.w,y.h],w=new Map(e.rooms.map(e=>{const n=Fs(i.fill,e);return[e,_s(n,"lqi"===n&&e.area?Do(r,c,e.area):null,"light"===n?po(ho(r,c,e,t.virtualLights)):"none","temp"===n&&e.area?To(r,c,e.area):null,i.tempMin,i.tempMax,s,ls(i.customFill,e))]})),k=new Map;for(const t of e.rooms)t.id&&k.set(t.id,w.get(t)||null);const x=function(t,e=1e3){const i=[];for(const[s,n]of(t||[]).entries()){if("passage"!==n?.type)continue;const t={...n,id:String(n.id||`passage-${s}`),type:"passage",rx:Number(n.x)*e,ry:Number(n.y)*e,rlen:Number(n.length)*e};[t.rx,t.ry,t.rlen,t.angle].every(Number.isFinite)&&t.rlen>0&&i.push(t)}return i}((p.openings||[]).flatMap(t=>{if(!t.host)return[t];const e=m.find(e=>e.opening.id===t.id);return e?[Cd(t,e,sc)]:[]}),sc),$=ol(e.rooms,_,[],_c,g,pc,sc),S=m.filter(t=>Md(t,$,2e-4*pc)).map(t=>({x:t.center[0],y:t.center[1],angle:t.angle,length:t.length})),M=e.rooms.filter(t=>t.area||i.showBorders||"none"!==Fs(i.fill,t)).map(t=>{let s="room "+(e.bg?"overlay":"yard"),n="";const o=Fs(i.fill,t);if(i.showBorders||"none"!==o){s+=" styled";const e=[`--room-stroke:${i.color}`,`--room-stroke-op:${i.showBorders?i.opacity:0}`],o=w.get(t)||null;o?(s+=" filled",e.push(`--room-fill:${o.color}`,`--room-fill-op:${o.opacity.toFixed(3)}`)):e.push("--room-fill:transparent","--room-fill-op:0"),n=e.join(";")}const a=t.id||G,r=t.area||G,l=t.poly?j``});return j``}const ep=new WeakMap,ip=new WeakMap;function sp(t){const e=cc(t.cfg),i={};for(const e of t.cfg.spaces||[])for(const t of e.rooms||[])t.area&&(i[t.area]=e.id);const s=t.cfg.settings?.exclude_integrations?new Set(t.cfg.settings.exclude_integrations):Yt,n=Jt(t.cfg.settings?.icon_rules?.length?t.cfg.settings.icon_rules:Xt);return So({hass:t.hass,registry:t.registry,areaToSpace:i,markers:t.cfg.markers||[],settings:t.cfg.settings||{},excluded:s,showAll:!!t.cfg.settings?.show_all,firstSpaceId:e[0]?.id||"",loc:e=>la(t.lang,e),iconRules:n})}function np(t){const e=cc(t.cfg).find(e=>e.id===t.spaceId);if(!e)return null;const i=cs(t.cfg.spaces.find(e=>e.id===t.spaceId)),s=us(t.cfg.settings),n=t.iconSize??2.5,o=n>8?2.5:n,a=Qu(o),r=t.registry?On(t.hass,t.registry):t.hass,l=t.registry?Nn(t.hass,t.registry):t.hass,c=(t.devices||sp(t)).filter(e=>e.space===t.spaceId),h=c.filter(t=>!t.hidden),d=function(t,e,i){const s={},n=i/100*Pc(e)*1.3;for(const i of e.rooms){if(!i.area)continue;const e=t.filter(t=>t.area===i.area);if(!e.length)continue;const o=Ac(i),a=.1*Math.min(o.w,o.h),r=o.w-2*a,l=o.h-2*a,c=Math.max(1,Math.round(Math.sqrt(e.length*r/Math.max(l,1)))),h=r/c,d=l/Math.max(Math.ceil(e.length/c),1),u=e.map((t,e)=>({x:o.x+a+h*(e%c+.5),y:o.y+a+d*(Math.floor(e/c)+.5)}));Ni(u,o,n,.5*a),e.forEach((t,e)=>s[t.id]=mc(u[e]))}return s}(c,e,o),u=[];for(const e of h){const i=t.layout[e.id];if(i&&i.s===t.spaceId){const t=i.x*sc,e=i.y*sc;u.push({minX:t,minY:e,maxX:t,maxY:e})}}const p=t.cfg.spaces.find(e=>e.id===t.spaceId)||{},_=Array.isArray(p.walls)?p.walls:[],g=Number(p.cell_cm)>0?Number(p.cell_cm):5,m=(p.openings||[]).flatMap(t=>{if(!t.host)return[];const i=wd(t,e.partitions,sc,g,pc).resolved;return i?[i]:[]}),f=vh({partitions:e.partitions,roomDrafts:e.room_drafts,columns:e.wall_columns,cellCm:g,hostedOpenings:m.map(t=>({id:t.opening.id,host:t.host,length:t.length,type:t.opening.type}))}),v=function(t,e,i,s){let n=ip.get(t);n||(n=new Map,ip.set(t,n));const o=n.get(e);if(o?.fingerprint===i)return o.value;const a=s();return n.set(e,{fingerprint:i,value:a}),a}(t.cfg,e.id,f,()=>Bl(e,g,pc,2e-4*pc,m.map($d)).all);for(const t of v){const e=t.map(t=>t[0]),i=t.map(t=>t[1]);e.length&&u.push({minX:Math.min(...e),minY:Math.min(...i),maxX:Math.max(...e),maxY:Math.max(...i)})}const y=Dc(e,u),b=[y.x,y.y,y.w,y.h],w=new Map(e.rooms.map(e=>{const n=Fs(i.fill,e);return[e,_s(n,"lqi"===n&&e.area?Do(r,c,e.area):null,"light"===n?po(ho(r,c,e,t.virtualLights)):"none","temp"===n&&e.area?To(r,c,e.area):null,i.tempMin,i.tempMax,s,ls(i.customFill,e))]})),k=new Map;for(const t of e.rooms)t.id&&k.set(t.id,w.get(t)||null);const x=function(t,e=1e3){const i=[];for(const[s,n]of(t||[]).entries()){if("passage"!==n?.type)continue;const t={...n,id:String(n.id||`passage-${s}`),type:"passage",rx:Number(n.x)*e,ry:Number(n.y)*e,rlen:Number(n.length)*e};[t.rx,t.ry,t.rlen,t.angle].every(Number.isFinite)&&t.rlen>0&&i.push(t)}return i}((p.openings||[]).flatMap(t=>{if(!t.host)return[t];const e=m.find(e=>e.opening.id===t.id);return e?[Cd(t,e,sc)]:[]}),sc),$=ol(e.rooms,_,[],_c,g,pc,sc),S=m.filter(t=>Md(t,$,2e-4*pc)).map(t=>({x:t.center[0],y:t.center[1],angle:t.angle,length:t.length})),M=e.rooms.filter(t=>t.area||i.showBorders||"none"!==Fs(i.fill,t)).map(t=>{let s="room "+(e.bg?"overlay":"yard"),n="";const o=Fs(i.fill,t);if(i.showBorders||"none"!==o){s+=" styled";const e=[`--room-stroke:${i.color}`,`--room-stroke-op:${i.showBorders?i.opacity:0}`],o=w.get(t)||null;o?(s+=" filled",e.push(`--room-fill:${o.color}`,`--room-fill-op:${o.opacity.toFixed(3)}`)):e.push("--room-fill:transparent","--room-fill-op:0"),n=e.join(";")}const a=t.id||G,r=t.area||G,l=t.poly?j``:j``;return l}),C=e.rooms.filter(t=>{const e=w.get(t);return Es(i.glow,t)&&(!e||e.opacity<=0)}).map(t=>t.poly?j` ${this._t("gs.about_github")} @@ -5717,7 +5717,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="5ca433d2ee8bf92a41f4597ac53777315a9c ${t.busy?"…":this._t("btn.save")} - `}_saveKioskScale(t){this._kioskScale={...this._kioskScale,...t};try{localStorage.setItem(Kg,JSON.stringify(this._kioskScale))}catch{}this.requestUpdate()}_renderKioskDialog(){const t=this._kioskScale,e=(e,i)=>W` + `}_saveKioskScale(t){this._kioskScale={...this._kioskScale,...t};try{localStorage.setItem(Yg,JSON.stringify(this._kioskScale))}catch{}this.requestUpdate()}_renderKioskDialog(){const t=this._kioskScale,e=(e,i)=>W`
${this._rangeInput(50,300,5,Math.round(100*t[e]),t=>this._saveKioskScale({[e]:t/100}))} ${Math.round(100*t[e])}% @@ -5774,7 +5774,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="5ca433d2ee8bf92a41f4597ac53777315a9c ${this._spaceDialog?this._renderSpaceDialog():G} ${this._importDialog?this._renderImportDialog():G} ${this._toast?W``:G} - `;const s=this._spaceModel();if(!s)return G;const n="valid"===i.kind?[s]:t,o=s.vb,a=this._effectiveProjection();this._renderProjection=a,this._labs.active.length&&function(t){O_||W_(t);const e=z_,i=e.active.join(",");if(!i||i===H_)return;H_=i;const s=new Map(C_.map(t=>[t.id,t])),n=e.active.map(t=>{const e=s.get(t);return`${t} (#${e.issue}, expires ${e.expires})`}).join(", ");console.info(`HOUSEPLAN LABS: ${n}`)}(Rg);const r="iso"===a,l="devices"===this._mode&&this._showAll,c=this._renderDevices.filter(t=>t.space===s.id&&(!t.hidden||l)),h=this._renderDeviceSnapshot,d=this._spaceDisplayForRender(),u=r?this._isoDecorationLayers(d):null,p=u?this._isoOpeningPanels(u):[],_=this._resolvedRoomFills(s,d),g=this._resolvedGlowBase(s,d,_),m=d.showLqi??this._config.show_signal??!0,f=this._config.icon_size??2.5,v=f>8?2.5:f,y=Zu(v),b=this._viewOr(this._baseVb()),w=this._floorView(b),k=this._editing?"":this._stageBg(d),x=this._opMeasureView,$=this._decorMeasure,S=this._bdLive,M=this._furnLive,C="view"===this._mode?this._editorChromeMode:this._mode,D=this._roomHoverPaths(s),T=s.bg?this._display(s.bg.href):"",P=this._continuity.overlayVisible||"recovery-error"===this._continuity.state?this._continuity.recoveryReason:null,R=this._modeTransitionVisual,I=this._dayCycleState(),A=R?.viewWeight??("view"===this._mode?1:0),F=this._modeTransition.state?.from.presentedMode,E=!this._markup||!!R&&("view"===R.presentedMode||"devices"===R.presentedMode||"view"===F||"devices"===F),z=R?.stageColor||k,O=R?.sceneBrightness??1;return W` + `;const s=this._spaceModel();if(!s)return G;const n="valid"===i.kind?[s]:t,o=s.vb,a=this._effectiveProjection();this._renderProjection=a,this._labs.active.length&&function(t){N_||j_(t);const e=O_,i=e.active.join(",");if(!i||i===L_)return;L_=i;const s=new Map(D_.map(t=>[t.id,t])),n=e.active.map(t=>{const e=s.get(t);return`${t} (#${e.issue}, expires ${e.expires})`}).join(", ");console.info(`HOUSEPLAN LABS: ${n}`)}(Ig);const r="iso"===a,l="devices"===this._mode&&this._showAll,c=this._renderDevices.filter(t=>t.space===s.id&&(!t.hidden||l)),h=this._renderDeviceSnapshot,d=this._spaceDisplayForRender(),u=r?this._isoDecorationLayers(d):null,p=u?this._isoOpeningPanels(u):[],_=this._resolvedRoomFills(s,d),g=this._resolvedGlowBase(s,d,_),m=d.showLqi??this._config.show_signal??!0,f=this._config.icon_size??2.5,v=f>8?2.5:f,y=Qu(v),b=this._viewOr(this._baseVb()),w=this._floorView(b),k=this._editing?"":this._stageBg(d),x=this._opMeasureView,$=this._decorMeasure,S=this._bdLive,M=this._furnLive,C="view"===this._mode?this._editorChromeMode:this._mode,D=this._roomHoverPaths(s),T=s.bg?this._display(s.bg.href):"",P=this._continuity.overlayVisible||"recovery-error"===this._continuity.state?this._continuity.recoveryReason:null,R=this._modeTransitionVisual,I=this._dayCycleState(),A=R?.viewWeight??("view"===this._mode?1:0),F=this._modeTransition.state?.from.presentedMode,E=!this._markup||!!R&&("view"===R.presentedMode||"devices"===R.presentedMode||"view"===F||"devices"===F),z=R?.stageColor||k,O=R?.sceneBrightness??1;return W` + transform=${u?.structural?Y_():G}> ${""} ${this._wallHatchDefs(d.color)}${j`${this._paperShapes(s.rooms).map(t=>"path"in t?j``:"poly"in t?j``:j``)}`} ${this._editing?this._renderMarkupDefs(o):G} @@ -5895,7 +5895,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="5ca433d2ee8bf92a41f4597ac53777315a9c transform=${s.bg.angle?`rotate(${s.bg.angle} ${s.bg.x+s.bg.w/2} ${s.bg.y+s.bg.h/2})`:G} @dblclick=${t=>this._openBackdropDialog(t)} preserveAspectRatio="none" />`:G} - ${(()=>{const t=this._openPairs(),e=new Map,i=t=>(e.has(t)||e.set(t,hi(t)),e.get(t));return s.rooms.filter(t=>t.area||"view"===this._mode||this._markup||d.showBorders).map(e=>{let n="room "+(s.bg?"overlay":"yard")+(this._markup?" outlined":"");!this._markup||e.id!==this._mergeSel&&e.id!==this._splitSel?.roomId||(n+=" picked");let o="";const a=Fs(d.fill,e);if(!this._markup&&(d.showBorders||"none"!==a)){n+=" styled";const t=[];t.push(`--room-stroke:${d.color}`,`--room-stroke-op:${d.showBorders?d.opacity:0}`);const i=_.byRoom.get(e)||null;i?(n+=" filled",t.push(`--room-fill:${i.color}`,`--room-fill-op:${i.opacity}`)):t.push("--room-fill:transparent","--room-fill-op:0"),o=t.join(";")}let r;const l=t=>{"view"===this._mode&&(void 0===r&&(r=this._roomArea(e)),this._showTip(t,e.name||this._t("room.unnamed"),r?this._t("tip.area",{value:r}):"",m?this._roomLqi(e.area):null,this._roomTemp(e),this._roomHum(e)))},c=this._markup&&(e.id===this._mergeSel||e.id===this._splitSel?.roomId),h=e.id&&!c?t.filter(t=>t.a.id===e.id||t.b.id===e.id).flatMap(t=>t.segs):[],u=c?[]:this._thickWallCuts(),p=h.concat(u);p.length&&(n+=" noedge");const g=i(e),f=this._spaceWalls,v=f.length&&e.id&&g&&hl(s.rooms,e.id,f,this._openPairs().flatMap(t=>t.segs),this._wallKeyPitch,this._cellCm,this._gridPitch,Jg)||g,y=v?Ti(v,(b=e,s.rooms.filter(t=>t!==b).map(i).filter(Boolean))):[];var b;const w=t=>"M "+t.map(t=>t[0]+" "+t[1]).join(" L ")+" Z",k=v?this._cleanFloor(e,v,s).path:"",x=e.id||G,$=e.area||G,S=k&&v?j`{const t=this._openPairs(),e=new Map,i=t=>(e.has(t)||e.set(t,hi(t)),e.get(t));return s.rooms.filter(t=>t.area||"view"===this._mode||this._markup||d.showBorders).map(e=>{let n="room "+(s.bg?"overlay":"yard")+(this._markup?" outlined":"");!this._markup||e.id!==this._mergeSel&&e.id!==this._splitSel?.roomId||(n+=" picked");let o="";const a=Fs(d.fill,e);if(!this._markup&&(d.showBorders||"none"!==a)){n+=" styled";const t=[];t.push(`--room-stroke:${d.color}`,`--room-stroke-op:${d.showBorders?d.opacity:0}`);const i=_.byRoom.get(e)||null;i?(n+=" filled",t.push(`--room-fill:${i.color}`,`--room-fill-op:${i.opacity}`)):t.push("--room-fill:transparent","--room-fill-op:0"),o=t.join(";")}let r;const l=t=>{"view"===this._mode&&(void 0===r&&(r=this._roomArea(e)),this._showTip(t,e.name||this._t("room.unnamed"),r?this._t("tip.area",{value:r}):"",m?this._roomLqi(e.area):null,this._roomTemp(e),this._roomHum(e)))},c=this._markup&&(e.id===this._mergeSel||e.id===this._splitSel?.roomId),h=e.id&&!c?t.filter(t=>t.a.id===e.id||t.b.id===e.id).flatMap(t=>t.segs):[],u=c?[]:this._thickWallCuts(),p=h.concat(u);p.length&&(n+=" noedge");const g=i(e),f=this._spaceWalls,v=f.length&&e.id&&g&&hl(s.rooms,e.id,f,this._openPairs().flatMap(t=>t.segs),this._wallKeyPitch,this._cellCm,this._gridPitch,Zg)||g,y=v?Ti(v,(b=e,s.rooms.filter(t=>t!==b).map(i).filter(Boolean))):[];var b;const w=t=>"M "+t.map(t=>t[0]+" "+t[1]).join(" L ")+" Z",k=v?this._cleanFloor(e,v,s).path:"",x=e.id||G,$=e.area||G,S=k&&v?j`{this._notePointer(t),this._pointerModality.hoverEnabled&&(this._hoverRoom={space:s.id,room:e})}} @@ -6072,7 +6072,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="5ca433d2ee8bf92a41f4597ac53777315a9c `:G} ${this._toast?W``:G} - `}_vacCandidateStatus(t,e,i=this._planHass){const s=this._bindingStatus("entity:"+t);if("ha_disabled"===s.kind)return"disabled";if("orphaned"===s.kind)return"missing";if("unverified"===s.kind)return"unverified";const n=i?.states?.[t];return"unavailable"===n?.state?"unavailable":e?.hasPosition?"ok":"unsupported"}_vacOpenAllCameras(t){const e=this._haRegistry.entities||{},i=[];for(const[t,s]of Object.entries(this.hass?.states||{})){if(!t.startsWith("camera."))continue;const n=zh(t,s,e[t]);n&&i.push(n)}this._vacAllCameraCache={devId:t.id,candidates:i},this._vacAllCamerasFor=t.id}_vacSourceResolution(t,e=!1,i=this._planHass){const s=t.marker?.vacuum,n="string"==typeof s?.source&&!!s.source,o=new Set(t.entities||[]),a=new Set(o);n&&a.add(s.source);const r=i?.entities||{},l=[];for(const t of a){const e=i?.states?.[t],o=zh(t,e,r[t]);o?l.push(o):n&&t===s.source&&l.push({entityId:t,name:String(e?.attributes?.friendly_name||t),platform:r[t]?.platform?String(r[t].platform):null,category:t.startsWith("camera.")?"camera":"partial",hasPosition:!1,hasRooms:!1,hasPath:!1,hasMapId:!1,score:0})}if(e&&this._vacAllCameraCache?.devId===t.id){const t=new Set(l.map(t=>t.entityId));for(const e of this._vacAllCameraCache.candidates)t.has(e.entityId)||l.push(e)}const c={};for(const t of l)c[t.entityId]=this._vacCandidateStatus(t.entityId,t,i);return function(t,e,i,s){const n="string"==typeof t&&t.length>0,o=new Set(e),a=Array.from(i).sort((e,i)=>n&&e.entityId===t?-1:n&&i.entityId===t?1:i.score-e.score||e.entityId.localeCompare(i.entityId));if(n){const e=a.find(e=>e.entityId===t);return{entityId:t,status:s[t]||(e?.hasPosition?"ok":"unverified"),pinned:!0,candidates:a}}const r=a.find(t=>o.has(t.entityId)&&t.hasPosition&&"ok"===s[t.entityId]);return r?{entityId:r.entityId,status:"ok",pinned:!1,candidates:a}:{entityId:null,status:"none",pinned:!1,candidates:a}}(s?.source,o,l,c)}_vacSource(t,e=this._planHass){if(!1===t.marker?.vacuum?.live)return null;const i=this._vacSourceResolution(t,!1,e);return"ok"===i.status||"unsupported"===i.status?i.entityId:null}_vacEntity(t){return t.primary?.startsWith("vacuum.")?t.primary:(t.entities||[]).find(t=>t.startsWith("vacuum."))||null}_isVacDev(t){return!!this._vacEntity(t)}_activitySourceKey(t){return this._activitySnapshot(t).sourceKey}_activitySnapshot(t,e=ho(this._planHass,this._devices,null,this._virtualLights)){const i=qu(this._planHass,t,this._devices,e,this._fullRegistryHass);return{samples:i.samples,sourceKey:Uu(this._planHass,t,i)}}_stampActivity(t,e,i){let s=this._activityRt.get(t);s||(s=gp(i||"",[]),this._activityRt.set(t,s)),null!=i&&(s.sources=i),fp(s,e,Date.now(),window.clearTimeout.bind(window),t=>window.setTimeout(()=>this.requestUpdate(),t))}_syncActivityRuntime(){const t=new Map;if(!this.hass)return t;if(!1===this._config?.live_states){for(const t of this._activityRt.values())clearTimeout(t.timer);return this._activityRt.clear(),t}const e=new Set,i=ho(this._planHass,this._devices,null,this._virtualLights);for(const s of this._devices){if(s.hidden)continue;if("icon_ripple"!==Bi(s.marker?.display))continue;e.add(s.id);const n=this._activitySnapshot(s,i);t.set(s.id,n);const{samples:o,sourceKey:a}=n;let r=this._activityRt.get(s.id);r?r.sources!==a&&mp(r,a,o,window.clearTimeout.bind(window)):(r=gp(a,o),this._activityRt.set(s.id,r))}for(const[t,i]of this._activityRt)e.has(t)||(clearTimeout(i.timer),this._activityRt.delete(t));return t}_activityTick(){if(!this.hass)return;const t=this._syncActivityRuntime();for(const e of this._devices){if(e.hidden)continue;if("icon_ripple"!==Bi(e.marker?.display))continue;const i=t.get(e.id)||this._activitySnapshot(e),{samples:s,sourceKey:n}=i,o=this._activityRt.get(e.id);if(!o||o.sources!==n)continue;const a=vp(o,s,window.clearTimeout.bind(window));a&&this._stampActivity(e.id,a,n)}}_vacTick(){if(this.hass)for(const t of this._devices){if(t.hidden||!this._isVacDev(t))continue;if("static_icon"===Bi(t.marker?.display)){this._vacRt.delete(t.id);continue}const e=this._vacSource(t);if(!e)continue;const i=this._vacEntity(t),s=Lh(this.hass.states[i||""]?.state),n=Eh(this.hass.states[e]?.attributes);let o=this._vacRt.get(t.id);o||(o={trail:[],lastKey:"",lastTs:0,moving:!1,jump:!1,endedTs:0,lastPos:null},this._vacRt.set(t.id,o)),s&&!o.moving&&(o.trail=[],o.lastPos=null);const a="never"!==Uh(t.marker?.vacuum)&&!n?.path.length;!s&&o.moving&&(o.endedTs=Date.now(),a&&o.lastPos&&(o.trail=Hh(o.trail,o.lastPos,40)),o.lastPos=null),o.moving=s;const r=n?.pos;if(s&&r){const t=r.x+":"+r.y;if(t!==o.lastKey){const e=Date.now();o.jump=o.lastTs>0&&e-o.lastTs>1e4,o.lastKey=t,o.lastTs=e,a&&o.lastPos&&(o.trail=Hh(o.trail,o.lastPos,40)),o.lastPos=[r.x,r.y]}}}}_vacEnsureMarker(t){const e=this._serverCfg;if(!e)return null;e.markers=e.markers||[];const i=e.markers.find(e=>e.id===t.id);if(i)return i;if("device"!==t.bindingKind&&"entity"!==t.bindingKind||!t.bindingRef)return null;const s={id:t.id,binding:t.bindingKind+":"+t.bindingRef,space:t.space||null,area:t.area||null,hidden:!!t.hidden};return e.markers.push(s),s}_renderVacSection(t){const e=this._devices.find(e=>e.id===t.devId);if(!e||!this._isVacDev(e))return G;const i=e.marker?.vacuum||{},s=this._vacAllCamerasFor===e.id,n=this._vacSourceResolution(e,s),o=n.entityId,a=n.candidates.find(t=>t.entityId===o)||null,r=o?Eh(this.hass?.states[o]?.attributes):null,l=!1!==i.live&&("ok"===n.status||"unsupported"===n.status),c=this._vacPlanRoomAnchors(e.space),h=r?function(t,e){const i=new Set(e.map(Oh).filter(Boolean)),s=new Set;for(const e of t){const t=Oh(e.name||"");t&&i.has(t)&&s.add(t)}return s.size}(r.rooms,c.map(t=>t.name)):0,d=!!(l&&r&&h>=3),u=Object.keys(i.calibration||{}),p=t=>{const i=this._vacEnsureMarker(e);i&&(i.vacuum={...i.vacuum||{},...t},this._regSignature="",this._maybeRebuildDevices(),this._saveConfig(),this.requestUpdate())},_=new Set(e.entities||[]),g=n.candidates.filter(t=>_.has(t.entityId)||t.entityId===i.source),m=s?n.candidates.filter(t=>t.entityId.startsWith("camera.")&&!g.some(e=>e.entityId===t.entityId)):[],f=t=>[t.hasPosition?this._t("vac.cap_position"):"",t.hasRooms?this._t("vac.cap_rooms_short"):"",t.hasPath?this._t("vac.cap_path"):"",t.hasMapId?this._t("vac.cap_map"):""].filter(Boolean).join(" · ")||this._t("vac.cap_none"),v=t=>W` + `}_vacCandidateStatus(t,e,i=this._planHass){const s=this._bindingStatus("entity:"+t);if("ha_disabled"===s.kind)return"disabled";if("orphaned"===s.kind)return"missing";if("unverified"===s.kind)return"unverified";const n=i?.states?.[t];return"unavailable"===n?.state?"unavailable":e?.hasPosition?"ok":"unsupported"}_vacOpenAllCameras(t){const e=this._haRegistry.entities||{},i=[];for(const[t,s]of Object.entries(this.hass?.states||{})){if(!t.startsWith("camera."))continue;const n=zh(t,s,e[t]);n&&i.push(n)}this._vacAllCameraCache={devId:t.id,candidates:i},this._vacAllCamerasFor=t.id}_vacSourceResolution(t,e=!1,i=this._planHass){const s=t.marker?.vacuum,n="string"==typeof s?.source&&!!s.source,o=new Set(t.entities||[]),a=new Set(o);n&&a.add(s.source);const r=i?.entities||{},l=[];for(const t of a){const e=i?.states?.[t],o=zh(t,e,r[t]);o?l.push(o):n&&t===s.source&&l.push({entityId:t,name:String(e?.attributes?.friendly_name||t),platform:r[t]?.platform?String(r[t].platform):null,category:t.startsWith("camera.")?"camera":"partial",hasPosition:!1,hasRooms:!1,hasPath:!1,hasMapId:!1,score:0})}if(e&&this._vacAllCameraCache?.devId===t.id){const t=new Set(l.map(t=>t.entityId));for(const e of this._vacAllCameraCache.candidates)t.has(e.entityId)||l.push(e)}const c={};for(const t of l)c[t.entityId]=this._vacCandidateStatus(t.entityId,t,i);return function(t,e,i,s){const n="string"==typeof t&&t.length>0,o=new Set(e),a=Array.from(i).sort((e,i)=>n&&e.entityId===t?-1:n&&i.entityId===t?1:i.score-e.score||e.entityId.localeCompare(i.entityId));if(n){const e=a.find(e=>e.entityId===t);return{entityId:t,status:s[t]||(e?.hasPosition?"ok":"unverified"),pinned:!0,candidates:a}}const r=a.find(t=>o.has(t.entityId)&&t.hasPosition&&"ok"===s[t.entityId]);return r?{entityId:r.entityId,status:"ok",pinned:!1,candidates:a}:{entityId:null,status:"none",pinned:!1,candidates:a}}(s?.source,o,l,c)}_vacSource(t,e=this._planHass){if(!1===t.marker?.vacuum?.live)return null;const i=this._vacSourceResolution(t,!1,e);return"ok"===i.status||"unsupported"===i.status?i.entityId:null}_vacEntity(t){return t.primary?.startsWith("vacuum.")?t.primary:(t.entities||[]).find(t=>t.startsWith("vacuum."))||null}_isVacDev(t){return!!this._vacEntity(t)}_activitySourceKey(t){return this._activitySnapshot(t).sourceKey}_activitySnapshot(t,e=ho(this._planHass,this._devices,null,this._virtualLights)){const i=Wu(this._planHass,t,this._devices,e,this._fullRegistryHass);return{samples:i.samples,sourceKey:Gu(this._planHass,t,i)}}_stampActivity(t,e,i){let s=this._activityRt.get(t);s||(s=mp(i||"",[]),this._activityRt.set(t,s)),null!=i&&(s.sources=i),vp(s,e,Date.now(),window.clearTimeout.bind(window),t=>window.setTimeout(()=>this.requestUpdate(),t))}_syncActivityRuntime(){const t=new Map;if(!this.hass)return t;if(!1===this._config?.live_states){for(const t of this._activityRt.values())clearTimeout(t.timer);return this._activityRt.clear(),t}const e=new Set,i=ho(this._planHass,this._devices,null,this._virtualLights);for(const s of this._devices){if(s.hidden)continue;if("icon_ripple"!==Bi(s.marker?.display))continue;e.add(s.id);const n=this._activitySnapshot(s,i);t.set(s.id,n);const{samples:o,sourceKey:a}=n;let r=this._activityRt.get(s.id);r?r.sources!==a&&fp(r,a,o,window.clearTimeout.bind(window)):(r=mp(a,o),this._activityRt.set(s.id,r))}for(const[t,i]of this._activityRt)e.has(t)||(clearTimeout(i.timer),this._activityRt.delete(t));return t}_activityTick(){if(!this.hass)return;const t=this._syncActivityRuntime();for(const e of this._devices){if(e.hidden)continue;if("icon_ripple"!==Bi(e.marker?.display))continue;const i=t.get(e.id)||this._activitySnapshot(e),{samples:s,sourceKey:n}=i,o=this._activityRt.get(e.id);if(!o||o.sources!==n)continue;const a=yp(o,s,window.clearTimeout.bind(window));a&&this._stampActivity(e.id,a,n)}}_vacTick(){if(this.hass)for(const t of this._devices){if(t.hidden||!this._isVacDev(t))continue;if("static_icon"===Bi(t.marker?.display)){this._vacRt.delete(t.id);continue}const e=this._vacSource(t);if(!e)continue;const i=this._vacEntity(t),s=Lh(this.hass.states[i||""]?.state),n=Eh(this.hass.states[e]?.attributes);let o=this._vacRt.get(t.id);o||(o={trail:[],lastKey:"",lastTs:0,moving:!1,jump:!1,endedTs:0,lastPos:null},this._vacRt.set(t.id,o)),s&&!o.moving&&(o.trail=[],o.lastPos=null);const a="never"!==Uh(t.marker?.vacuum)&&!n?.path.length;!s&&o.moving&&(o.endedTs=Date.now(),a&&o.lastPos&&(o.trail=Hh(o.trail,o.lastPos,40)),o.lastPos=null),o.moving=s;const r=n?.pos;if(s&&r){const t=r.x+":"+r.y;if(t!==o.lastKey){const e=Date.now();o.jump=o.lastTs>0&&e-o.lastTs>1e4,o.lastKey=t,o.lastTs=e,a&&o.lastPos&&(o.trail=Hh(o.trail,o.lastPos,40)),o.lastPos=[r.x,r.y]}}}}_vacEnsureMarker(t){const e=this._serverCfg;if(!e)return null;e.markers=e.markers||[];const i=e.markers.find(e=>e.id===t.id);if(i)return i;if("device"!==t.bindingKind&&"entity"!==t.bindingKind||!t.bindingRef)return null;const s={id:t.id,binding:t.bindingKind+":"+t.bindingRef,space:t.space||null,area:t.area||null,hidden:!!t.hidden};return e.markers.push(s),s}_renderVacSection(t){const e=this._devices.find(e=>e.id===t.devId);if(!e||!this._isVacDev(e))return G;const i=e.marker?.vacuum||{},s=this._vacAllCamerasFor===e.id,n=this._vacSourceResolution(e,s),o=n.entityId,a=n.candidates.find(t=>t.entityId===o)||null,r=o?Eh(this.hass?.states[o]?.attributes):null,l=!1!==i.live&&("ok"===n.status||"unsupported"===n.status),c=this._vacPlanRoomAnchors(e.space),h=r?function(t,e){const i=new Set(e.map(Oh).filter(Boolean)),s=new Set;for(const e of t){const t=Oh(e.name||"");t&&i.has(t)&&s.add(t)}return s.size}(r.rooms,c.map(t=>t.name)):0,d=!!(l&&r&&h>=3),u=Object.keys(i.calibration||{}),p=t=>{const i=this._vacEnsureMarker(e);i&&(i.vacuum={...i.vacuum||{},...t},this._regSignature="",this._maybeRebuildDevices(),this._saveConfig(),this.requestUpdate())},_=new Set(e.entities||[]),g=n.candidates.filter(t=>_.has(t.entityId)||t.entityId===i.source),m=s?n.candidates.filter(t=>t.entityId.startsWith("camera.")&&!g.some(e=>e.entityId===t.entityId)):[],f=t=>[t.hasPosition?this._t("vac.cap_position"):"",t.hasRooms?this._t("vac.cap_rooms_short"):"",t.hasPath?this._t("vac.cap_path"):"",t.hasMapId?this._t("vac.cap_map"):""].filter(Boolean).join(" · ")||this._t("vac.cap_none"),v=t=>W`
`)}return this._vacLastView=e,n.length&&!this._vacRaf&&this._vacRafLoop(),n.length||o.length?W` ${o.length?j`${o}`:G} - ${n}`:G}_renderDevice(t,e,i=!0){const s=this._pos(t),n=this._scenePoint([s.x,s.y]),o=(n[0]-e.x)/e.w*100,a=(n[1]-e.y)/e.h*100,r=this._devicePresentation(t,i),l=[`left:${o}%`,`top:${a}%`,...Go(r)],c=r.disabledReason,h=r.haDisabled?this._t(`marker.ha_disabled_${c}`):t.userHidden?this._t("marker.hidden_ghost"):t.name,d=Ou(r),u="view"===this._mode||"devices"===this._mode,p=[h,r.haDisabled?"":this._t(`marker.state_a11y_${d}`),"none"!==r.pulse.kind?this._t(`marker.pulse_a11y_${r.pulse.reason}`):"",r.valueFullText||r.valueText||"",Ro(r.valueBadge),null!=r.lqiText&&r.lqiBand?this._t(`marker.lqi_a11y_${r.lqiBand}`,{value:r.lqiText}):""].filter(Boolean).join(", "),_=[t.model,r.valueBadge?.fullText||"",null!=r.lqiText?"LQI "+r.lqiText:""].filter(Boolean).join(" · ");return W`
`}_roomArea(t){const e=hi(t);if(!e)return null;const i=this._spaceModel();if(!i)return null;const s=this._spaceWalls,n=s.length&&t.id&&hl(i.rooms,t.id,s,this._openPairs().flatMap(t=>t.segs),this._wallKeyPitch,this._cellCm,this._gridPitch,Jg)||e,o=this._cleanFloor(t,n),a=this._cellCm/this._gridPitch;return Ia(o.area*a*a/1e4,"mi"===this._renderPlanHass?.config?.unit_system?.length)}_roomTemp(t){const e=t.settings?.temp_source;return e?Mo(this._renderPlanHass,e,"temp",this._markers):t.area?this._climate().get(t.area)?.temp??null:null}_roomHum(t){const e=t.settings?.hum_source;return e?Mo(this._renderPlanHass,e,"hum",this._markers):t.area?this._climate().get(t.area)?.hum??null:null}_climate(){const t=this._serverCfg?.markers,e=this._renderPlanHass,i=this._climateCache;if(i&&i.h===e&&i.r===this._iconRules&&i.mk===t)return i.m;const s=function(t,e,i){const s=new Map;if(!t?.entities)return s;const n=wo(i),o=new Set;for(const t of i||[]){if(t?.removed||!0!==t?.use_climate_temp)continue;const e=(t.binding||"").indexOf(":");e>0&&o.add(t.binding.slice(e+1))}const a=new Map;for(const[e,i]of Object.entries(t.entities)){if(i.device_id&&n.devices.has(i.device_id)||!i.device_id&&n.entities.has(e))continue;const s=i.device_id?t.devices?.[i.device_id]:null,r=i.area_id||s?.area_id||null;if(!r)continue;if(i.entity_category)continue;if(!(o.size>0&&e.startsWith("climate.")&&(o.has(e)||i.device_id&&o.has(i.device_id)))){if(Yt.has(i.platform))continue;if(Co.test(e))continue}let l=a.get(r);l||(l=new Map,a.set(r,l));const c=i.device_id||e;let h=l.get(c);if(!h){const n=t.states?.[e];h={name:(s?s.name_by_user||s.name:i.name||n?.attributes?.friendly_name||e)||e,model:s?.model,ents:[]},l.set(c,h)}h.ents.push(e)}for(const[i,n]of a){const a=[],r=[];for(const[i,s]of n){const n=bo(t,s.name,s.model,s.ents,e),l="mdi:thermometer"===n||"mdi:air-filter"===n;if(l){const e=go(t,s.ents);null!=e&&a.push(e)}if(o.size>0&&(o.has(i)||s.ents.some(t=>o.has(t)))){const e=mo(t,s.ents);null!=e&&a.push(e)}if(l||"mdi:water-percent"===n){const e=vo(t,s.ents);null!=e&&r.push(e)}}(a.length||r.length)&&s.set(i,{temp:a.length?Math.round(a.reduce((t,e)=>t+e,0)/a.length*10)/10:null,hum:r.length?Math.round(r.reduce((t,e)=>t+e,0)/r.length):null})}return s}(e,this._iconRules,t);return this._climateCache={h:e,r:this._iconRules,mk:t,m:s},s}_resetRoomDialogFields(){this._roomEditId=null,this._roomFill="",this._roomCustomFill=null,this._roomTempSrc="",this._roomHumSrc="",this._roomSrcOpen=null,this._roomSrcFilter="",this._roomNameScale=1,this._roomLabelScale=1}_openRoomEdit(t){if(!t.id)return;this._roomEditId=t.id,this._nameSel=t.name||"",this._areaSel=t.area||"",this._roomFill="glow"===t.settings?.fill_mode?"":t.settings?.fill_mode||"";const e=t.settings?.custom_fill;this._roomCustomFill=e&&"object"==typeof e?rs(e,cs(this._curSpaceCfg).customFill):null,this._roomTempSrc=t.settings?.temp_source||"",this._roomHumSrc=t.settings?.hum_source||"",this._roomNameScale=zs(t.settings?.name_scale),this._roomLabelScale=zs(t.settings?.label_scale),this._roomSrcOpen=null,this._roomSrcFilter="",this._roomDialog=!0}_roomSettingsFromDialog(){const t={};return this._roomFill&&(t.fill_mode=this._roomFill),this._roomCustomFill&&(t.custom_fill=this._roomCustomFill),this._roomTempSrc&&(t.temp_source=this._roomTempSrc),this._roomHumSrc&&(t.hum_source=this._roomHumSrc),1!==this._roomNameScale&&(t.name_scale=this._roomNameScale),1!==this._roomLabelScale&&(t.label_scale=this._roomLabelScale),Object.keys(t).length?t:null}_saveRoomEdit(){const t=this._curSpaceCfg,e=t?.rooms.find(t=>t.id===this._roomEditId);if(!e)return this._roomDialog=!1,void(this._roomEditId=null);e.name=this._nameSel.trim()||e.name,e.area=this._areaSel||null;const i=e.settings||{},s={...i};this._roomFill?s.fill_mode=this._roomFill:delete s.fill_mode,this._roomCustomFill?s.custom_fill=this._roomCustomFill:delete s.custom_fill,"glow"===i.fill_mode&&"boolean"!=typeof i.glow&&(s.glow=!0),this._roomTempSrc?s.temp_source=this._roomTempSrc:delete s.temp_source,this._roomHumSrc?s.hum_source=this._roomHumSrc:delete s.hum_source,1!==this._roomNameScale?s.name_scale=this._roomNameScale:delete s.name_scale,1!==this._roomLabelScale?s.label_scale=this._roomLabelScale:delete s.label_scale,Object.keys(s).length?e.settings=s:delete e.settings,this._saveConfig(),this._roomDialog=!1,this._roomEditId=null,this._nameSel="",this._areaSel="",this._regSignature="",this._maybeRebuildDevices(),this.requestUpdate(),this._showToast(this._t("toast.room_updated"))}_roomSrcCandidates(){const t=this._planHass,e=wo(this._markers),i=this._roomSrcFilter.trim().toLowerCase(),s=[];for(const n of Object.values(t.devices)){if("service"===n.entry_type)continue;if(e.devices.has(n.id))continue;const t=(n.name_by_user||n.name||n.id).trim();i&&!t.toLowerCase().includes(i)||s.push({value:"device:"+n.id,label:t,sub:n.model||this._t("marker.sub_device")})}for(const[n,o]of Object.entries(t.entities)){if(!n.startsWith("sensor.")||o.hidden)continue;if(ko(t,n,e))continue;const a=o.name||t.states[n]?.attributes?.friendly_name||n;i&&!(a+" "+n).toLowerCase().includes(i)||s.push({value:"entity:"+n,label:a,sub:n})}return s.sort((t,e)=>t.label.localeCompare(e.label)),s.slice(0,200)}_roomSrcLabel(t){const e=t.indexOf(":"),i=t.slice(0,e),s=t.slice(e+1);return"device"===i?this._fullRegistryHass.devices[s]?.name_by_user||this._fullRegistryHass.devices[s]?.name||s:this._fullRegistryHass.entities[s]?.name||this.hass.states[s]?.attributes?.friendly_name||s}_labelPos(t,e){const i=this._layout["rl_"+(t.id||"")];if(i&&i.s===e)return{x:i.x*Jg,y:i.y*Jg};const s=this._snap(this._roomCenter(t));return{x:s[0],y:s[1]}}_labelDown(t,e,i){if("plan"!==this._mode)return;t.preventDefault(),t.stopPropagation();const s=this._labelPos(e,i);this._drag={id:"rl_"+(e.id||""),sx:t.clientX,sy:t.clientY,ox:s.x,oy:s.y,moved:!1},om(t),this._tip=null}_labelMove(t,e,i){const s="rl_"+(e.id||"");if(!this._drag||this._drag.id!==s)return;const n=this._stageEl;if(!n)return;const o=this._spaceModelById(i);if(!o)return;const a=o.vb,r=n.getBoundingClientRect(),l=this._viewOr(a),c=(t.clientX-this._drag.sx)/r.width*l.w,h=(t.clientY-this._drag.sy)/r.height*l.h;Math.abs(t.clientX-this._drag.sx)+Math.abs(t.clientY-this._drag.sy)>3&&(this._drag.moved=!0);const d=fc(this._drag.ox+c),u=fc(this._drag.oy+h);this._savePos({id:s,space:i},d,u)}_labelUp(t){const e="rl_"+(t.id||"");if(!this._drag||this._drag.id!==e)return;const i=this._drag.moved;this._drag=i?this._drag:null,i&&window.setTimeout(()=>this._drag=null,0)}_labelScale(t){const e=this._layout["rl_"+(t.id||"")]?.k;return"number"==typeof e&&Number.isFinite(e)?Math.min(3,Math.max(.5,e)):1}_rlResizeDown(t,e,i){if("plan"!==this._mode)return;t.preventDefault(),t.stopPropagation();const s=t.target.closest(".roomlabel");if(!s)return;const n=s.getBoundingClientRect(),o=n.left+n.width/2,a=n.top+n.height/2,r=Math.max(8,Math.hypot(t.clientX-o,t.clientY-a));this._rlResize={id:"rl_"+(e.id||""),space:i,k0:this._labelScale(e),cx:o,cy:a,d0:r},om(t)}_rlResizeMove(t){const e=this._rlResize;if(!e)return;t.stopPropagation();const i=Math.max(8,Math.hypot(t.clientX-e.cx,t.clientY-e.cy)),s=Math.min(3,Math.max(.5,e.k0*(i/e.d0))),n=this._layout[e.id];if(n)this._layout={...this._layout,[e.id]:{...n,k:s}};else{const t=e.id.slice(3),i=this._spaceModelById(e.space);if(!i)return;const n=i.rooms.find(e=>e.id===t);if(!n)return;const o=this._labelPos(n,e.space);this._layout={...this._layout,[e.id]:{s:e.space,x:o.x/Jg,y:o.y/Jg,k:s}}}this._dirtyPos.add(e.id)}_rlResizeUp(){this._rlResize&&(this._rlResize=null,this._persistLayout())}_renderRoomGear(t,e,i){if(!t.id)return G;let s=null;if(t.poly?(s=this._gearPtCache.get(t.poly)||null,s||(s=$i(t.poly),this._gearPtCache.set(t.poly,s))):null!=t.x&&null!=t.y&&(s=[t.x+(t.w||0)/2,t.y+(t.h||0)/2]),!s)return G;const n=(s[0]-i.x)/i.w*100,o=(s[1]-i.y)/i.h*100;return W`
`}get _measureAnchor(){return this._markup&&this._cursorPt?"draw"===this._tool&&this._path.length&&!this._contourClosed?this._path[this._path.length-1]:"split"===this._tool&&this._splitSel?.pts?.length?this._splitSel.pts[this._splitSel.pts.length-1]:null:null}_renderMeasureLabel(t){const e=this._measureAnchor,i=this._cursorPt,s=(i[0]-t.x)/t.w*100,n=(i[1]-t.y)/t.h*100,o=Os(e,i),a=Math.round(10*o)/10,r=function(t,e,i=.001){if(t.length<2||e.length<2)return!1;const s=Math.abs(e[0]-t[0]),n=Math.abs(e[1]-t[1]);if(!Number.isFinite(s)||!Number.isFinite(n)||Math.hypot(s,n)<=i)return!1;const o=Math.max(s,n,1);return s<=i*o||n<=i*o||Math.abs(s-n)<=i*o}(e,i,2e-4*this._gridPitch);return W`
- ${this._fmtLen(e,i)} · ${a}°
`}get _decorMeasure(){const t=this._decorDraft;if(!t||"decor"!==this._mode)return null;const[e,i]=t.a,[s,n]=t.b;if(Math.abs(e-s)<1e-6&&Math.abs(i-n)<1e-6)return null;const o=(e+s)/2,a=(i+n)/2;if("line"===t.kind){const e=Os(t.a,t.b);return{x:o,y:a,on45:Ns(e),text:`${this._fmtLen(t.a,t.b)} · ${Math.round(10*e)/10}°`}}const r=this._fmtLen([e,i],[s,i]),l=this._fmtLen([s,i],[s,n]);if("ellipse"===t.kind){const t=this._fmtLen([0,0],[Math.abs(s-e)/2,0]),r=this._fmtLen([0,0],[0,Math.abs(n-i)/2]);return{x:o,y:a,on45:!1,text:Math.abs(Math.abs(s-e)-Math.abs(n-i))<1e-6?`R ${t}`:`Rx ${t} × Ry ${r}`}}return{x:o,y:a,on45:!1,text:`${r} × ${l} · ${Ia(hr(Math.abs(s-e),this._cellCm,this._gridPitch)*hr(Math.abs(n-i),this._cellCm,this._gridPitch)/1e4,this._imperial)}`}}get _alignPoint(){if(this._markup){if("draw"===this._tool&&this._path.length&&!this._contourClosed&&this._cursorPt)return this._cursorPt;if("split"===this._tool&&this._splitSel?.pts?.length&&this._cursorPt)return this._cursorPt;if(this._drag?.id.startsWith("rl_")&&this._drag.moved){const t=this._drag.id.slice(3),e=this._spaceModel()?.rooms.find(e=>e.id===t);return e?(()=>{const t=this._labelPos(e,this._space);return[t.x,t.y]})():null}return null}if("devices"===this._mode&&this._drag?.moved){const t=this._devices.find(t=>t.id===this._drag.id);return t?(()=>{const e=this._pos(t);return[e.x,e.y]})():null}if("decor"===this._mode){if(this._decorDraft)return this._decorDraft.b;if(this._decorMove){const t=this._decorList.find(t=>t.id===this._decorMove.id);if(!t)return null;const e=Jg,i=this._decorH;return"line"===t.kind?[t.x1*e,t.y1*i]:[t.x*e,t.y*i]}return null}return null}_alignCandidates(){const t=[],e=this._spaceModel();if(this._markup){if(!e)return t;if(this._drag?.id.startsWith("rl_")){const i=this._drag.id.slice(3);for(const s of e.rooms){if(!s.name||s.id===i)continue;const e=this._labelPos(s,this._space);t.push([e.x,e.y])}return t}for(const i of e.rooms){const e=hi(i);if(e)for(const i of e)t.push(i)}if("draw"===this._tool)for(const e of this._path)t.push(e);if("split"===this._tool&&this._splitSel?.pts)for(const e of this._splitSel.pts)t.push(e);return t}if("devices"===this._mode){for(const e of this._devices){if(e.space!==this._space||e.id===this._drag?.id||"ha_disabled"===e.bindingStatus?.kind)continue;const i=this._pos(e);t.push([i.x,i.y])}return t}if("decor"===this._mode){const e=this._decorMove?.id;return t.push(...this._decorSnapGeometry(e).points),this._decorDraft&&t.push(this._decorDraft.a),t}return t}_renderAlignGuides(){const t=this._alignPoint;if(!t)return j``;const e=this._drag?.id.startsWith("rl_")?.5*this._gridPitch:.05*this._gridPitch,i=function(t,e,i){let s=null,n=null;for(const o of e)if(!(Math.abs(o[0]-t[0])<1e-6&&Math.abs(o[1]-t[1])<1e-6)){if(Math.abs(o[0]-t[0])<=i){const e=Math.abs(o[1]-t[1]);e>1e-6&&(!s||e1e-6&&(!n||e + ${this._fmtLen(e,i)} · ${a}°`}get _decorMeasure(){const t=this._decorDraft;if(!t||"decor"!==this._mode)return null;const[e,i]=t.a,[s,n]=t.b;if(Math.abs(e-s)<1e-6&&Math.abs(i-n)<1e-6)return null;const o=(e+s)/2,a=(i+n)/2;if("line"===t.kind){const e=Os(t.a,t.b);return{x:o,y:a,on45:Ns(e),text:`${this._fmtLen(t.a,t.b)} · ${Math.round(10*e)/10}°`}}const r=this._fmtLen([e,i],[s,i]),l=this._fmtLen([s,i],[s,n]);if("ellipse"===t.kind){const t=this._fmtLen([0,0],[Math.abs(s-e)/2,0]),r=this._fmtLen([0,0],[0,Math.abs(n-i)/2]);return{x:o,y:a,on45:!1,text:Math.abs(Math.abs(s-e)-Math.abs(n-i))<1e-6?`R ${t}`:`Rx ${t} × Ry ${r}`}}return{x:o,y:a,on45:!1,text:`${r} × ${l} · ${Ia(hr(Math.abs(s-e),this._cellCm,this._gridPitch)*hr(Math.abs(n-i),this._cellCm,this._gridPitch)/1e4,this._imperial)}`}}get _alignPoint(){if(this._markup){if("draw"===this._tool&&this._path.length&&!this._contourClosed&&this._cursorPt)return this._cursorPt;if("split"===this._tool&&this._splitSel?.pts?.length&&this._cursorPt)return this._cursorPt;if(this._drag?.id.startsWith("rl_")&&this._drag.moved){const t=this._drag.id.slice(3),e=this._spaceModel()?.rooms.find(e=>e.id===t);return e?(()=>{const t=this._labelPos(e,this._space);return[t.x,t.y]})():null}return null}if("devices"===this._mode&&this._drag?.moved){const t=this._devices.find(t=>t.id===this._drag.id);return t?(()=>{const e=this._pos(t);return[e.x,e.y]})():null}if("decor"===this._mode){if(this._decorDraft)return this._decorDraft.b;if(this._decorMove){const t=this._decorList.find(t=>t.id===this._decorMove.id);if(!t)return null;const e=Zg,i=this._decorH;return"line"===t.kind?[t.x1*e,t.y1*i]:[t.x*e,t.y*i]}return null}return null}_alignCandidates(){const t=[],e=this._spaceModel();if(this._markup){if(!e)return t;if(this._drag?.id.startsWith("rl_")){const i=this._drag.id.slice(3);for(const s of e.rooms){if(!s.name||s.id===i)continue;const e=this._labelPos(s,this._space);t.push([e.x,e.y])}return t}for(const i of e.rooms){const e=hi(i);if(e)for(const i of e)t.push(i)}if("draw"===this._tool)for(const e of this._path)t.push(e);if("split"===this._tool&&this._splitSel?.pts)for(const e of this._splitSel.pts)t.push(e);return t}if("devices"===this._mode){for(const e of this._devices){if(e.space!==this._space||e.id===this._drag?.id||"ha_disabled"===e.bindingStatus?.kind)continue;const i=this._pos(e);t.push([i.x,i.y])}return t}if("decor"===this._mode){const e=this._decorMove?.id;return t.push(...this._decorSnapGeometry(e).points),this._decorDraft&&t.push(this._decorDraft.a),t}return t}_renderAlignGuides(){const t=this._alignPoint;if(!t)return j``;const e=this._drag?.id.startsWith("rl_")?.5*this._gridPitch:.05*this._gridPitch,i=function(t,e,i){let s=null,n=null;for(const o of e)if(!(Math.abs(o[0]-t[0])<1e-6&&Math.abs(o[1]-t[1])<1e-6)){if(Math.abs(o[0]-t[0])<=i){const e=Math.abs(o[1]-t[1]);e>1e-6&&(!s||e1e-6&&(!n||e ${i.map(e=>{const[i,o,a,r]="x"===e.axis?[e.at,e.from[1],e.at,t[1]+Math.sign(t[1]-e.from[1])*n]:[e.from[0],e.at,t[0]+Math.sign(t[0]-e.from[0])*n,e.at];return j` `})} @@ -6231,7 +6231,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="5ca433d2ee8bf92a41f4597ac53777315a9c `)} - `:Fu(e)} + `:Eu(e)}
- `});return j``}const tp=new WeakMap,ep=new WeakMap;function ip(t){const e=cc(t.cfg),i={};for(const e of t.cfg.spaces||[])for(const t of e.rooms||[])t.area&&(i[t.area]=e.id);const s=t.cfg.settings?.exclude_integrations?new Set(t.cfg.settings.exclude_integrations):Yt,n=Jt(t.cfg.settings?.icon_rules?.length?t.cfg.settings.icon_rules:Xt);return So({hass:t.hass,registry:t.registry,areaToSpace:i,markers:t.cfg.markers||[],settings:t.cfg.settings||{},excluded:s,showAll:!!t.cfg.settings?.show_all,firstSpaceId:e[0]?.id||"",loc:e=>la(t.lang,e),iconRules:n})}function sp(t){const e=cc(t.cfg).find(e=>e.id===t.spaceId);if(!e)return null;const i=cs(t.cfg.spaces.find(e=>e.id===t.spaceId)),s=us(t.cfg.settings),n=t.iconSize??2.5,o=n>8?2.5:n,a=Zu(o),r=t.registry?On(t.hass,t.registry):t.hass,l=t.registry?Nn(t.hass,t.registry):t.hass,c=(t.devices||ip(t)).filter(e=>e.space===t.spaceId),h=c.filter(t=>!t.hidden),d=function(t,e,i){const s={},n=i/100*Pc(e)*1.3;for(const i of e.rooms){if(!i.area)continue;const e=t.filter(t=>t.area===i.area);if(!e.length)continue;const o=Ac(i),a=.1*Math.min(o.w,o.h),r=o.w-2*a,l=o.h-2*a,c=Math.max(1,Math.round(Math.sqrt(e.length*r/Math.max(l,1)))),h=r/c,d=l/Math.max(Math.ceil(e.length/c),1),u=e.map((t,e)=>({x:o.x+a+h*(e%c+.5),y:o.y+a+d*(Math.floor(e/c)+.5)}));Ni(u,o,n,.5*a),e.forEach((t,e)=>s[t.id]=mc(u[e]))}return s}(c,e,o),u=[];for(const e of h){const i=t.layout[e.id];if(i&&i.s===t.spaceId){const t=i.x*sc,e=i.y*sc;u.push({minX:t,minY:e,maxX:t,maxY:e})}}const p=t.cfg.spaces.find(e=>e.id===t.spaceId)||{},_=Array.isArray(p.walls)?p.walls:[],g=Number(p.cell_cm)>0?Number(p.cell_cm):5,m=(p.openings||[]).flatMap(t=>{if(!t.host)return[];const i=wd(t,e.partitions,sc,g,pc).resolved;return i?[i]:[]}),f=vh({partitions:e.partitions,roomDrafts:e.room_drafts,columns:e.wall_columns,cellCm:g,hostedOpenings:m.map(t=>({id:t.opening.id,host:t.host,length:t.length,type:t.opening.type}))}),v=function(t,e,i,s){let n=ep.get(t);n||(n=new Map,ep.set(t,n));const o=n.get(e);if(o?.fingerprint===i)return o.value;const a=s();return n.set(e,{fingerprint:i,value:a}),a}(t.cfg,e.id,f,()=>Bl(e,g,pc,2e-4*pc,m.map($d)).all);for(const t of v){const e=t.map(t=>t[0]),i=t.map(t=>t[1]);e.length&&u.push({minX:Math.min(...e),minY:Math.min(...i),maxX:Math.max(...e),maxY:Math.max(...i)})}const y=Dc(e,u),b=[y.x,y.y,y.w,y.h],w=new Map(e.rooms.map(e=>{const n=Fs(i.fill,e);return[e,_s(n,"lqi"===n&&e.area?Do(r,c,e.area):null,"light"===n?po(ho(r,c,e,t.virtualLights)):"none","temp"===n&&e.area?To(r,c,e.area):null,i.tempMin,i.tempMax,s,ls(i.customFill,e))]})),k=new Map;for(const t of e.rooms)t.id&&k.set(t.id,w.get(t)||null);const x=function(t,e=1e3){const i=[];for(const[s,n]of(t||[]).entries()){if("passage"!==n?.type)continue;const t={...n,id:String(n.id||`passage-${s}`),type:"passage",rx:Number(n.x)*e,ry:Number(n.y)*e,rlen:Number(n.length)*e};[t.rx,t.ry,t.rlen,t.angle].every(Number.isFinite)&&t.rlen>0&&i.push(t)}return i}((p.openings||[]).flatMap(t=>{if(!t.host)return[t];const e=m.find(e=>e.opening.id===t.id);return e?[Cd(t,e,sc)]:[]}),sc),$=ol(e.rooms,_,[],_c,g,pc,sc),S=m.filter(t=>Md(t,$,2e-4*pc)).map(t=>({x:t.center[0],y:t.center[1],angle:t.angle,length:t.length})),M=e.rooms.filter(t=>t.area||i.showBorders||"none"!==Fs(i.fill,t)).map(t=>{let s="room "+(e.bg?"overlay":"yard"),n="";const o=Fs(i.fill,t);if(i.showBorders||"none"!==o){s+=" styled";const e=[`--room-stroke:${i.color}`,`--room-stroke-op:${i.showBorders?i.opacity:0}`],o=w.get(t)||null;o?(s+=" filled",e.push(`--room-fill:${o.color}`,`--room-fill-op:${o.opacity.toFixed(3)}`)):e.push("--room-fill:transparent","--room-fill-op:0"),n=e.join(";")}const a=t.id||G,r=t.area||G,l=t.poly?j``});return j``}const ep=new WeakMap,ip=new WeakMap;function sp(t){const e=cc(t.cfg),i={};for(const e of t.cfg.spaces||[])for(const t of e.rooms||[])t.area&&(i[t.area]=e.id);const s=t.cfg.settings?.exclude_integrations?new Set(t.cfg.settings.exclude_integrations):Yt,n=Jt(t.cfg.settings?.icon_rules?.length?t.cfg.settings.icon_rules:Xt);return So({hass:t.hass,registry:t.registry,areaToSpace:i,markers:t.cfg.markers||[],settings:t.cfg.settings||{},excluded:s,showAll:!!t.cfg.settings?.show_all,firstSpaceId:e[0]?.id||"",loc:e=>la(t.lang,e),iconRules:n})}function np(t){const e=cc(t.cfg).find(e=>e.id===t.spaceId);if(!e)return null;const i=cs(t.cfg.spaces.find(e=>e.id===t.spaceId)),s=us(t.cfg.settings),n=t.iconSize??2.5,o=n>8?2.5:n,a=Qu(o),r=t.registry?On(t.hass,t.registry):t.hass,l=t.registry?Nn(t.hass,t.registry):t.hass,c=(t.devices||sp(t)).filter(e=>e.space===t.spaceId),h=c.filter(t=>!t.hidden),d=function(t,e,i){const s={},n=i/100*Pc(e)*1.3;for(const i of e.rooms){if(!i.area)continue;const e=t.filter(t=>t.area===i.area);if(!e.length)continue;const o=Ac(i),a=.1*Math.min(o.w,o.h),r=o.w-2*a,l=o.h-2*a,c=Math.max(1,Math.round(Math.sqrt(e.length*r/Math.max(l,1)))),h=r/c,d=l/Math.max(Math.ceil(e.length/c),1),u=e.map((t,e)=>({x:o.x+a+h*(e%c+.5),y:o.y+a+d*(Math.floor(e/c)+.5)}));Ni(u,o,n,.5*a),e.forEach((t,e)=>s[t.id]=mc(u[e]))}return s}(c,e,o),u=[];for(const e of h){const i=t.layout[e.id];if(i&&i.s===t.spaceId){const t=i.x*sc,e=i.y*sc;u.push({minX:t,minY:e,maxX:t,maxY:e})}}const p=t.cfg.spaces.find(e=>e.id===t.spaceId)||{},_=Array.isArray(p.walls)?p.walls:[],g=Number(p.cell_cm)>0?Number(p.cell_cm):5,m=(p.openings||[]).flatMap(t=>{if(!t.host)return[];const i=wd(t,e.partitions,sc,g,pc).resolved;return i?[i]:[]}),f=vh({partitions:e.partitions,roomDrafts:e.room_drafts,columns:e.wall_columns,cellCm:g,hostedOpenings:m.map(t=>({id:t.opening.id,host:t.host,length:t.length,type:t.opening.type}))}),v=function(t,e,i,s){let n=ip.get(t);n||(n=new Map,ip.set(t,n));const o=n.get(e);if(o?.fingerprint===i)return o.value;const a=s();return n.set(e,{fingerprint:i,value:a}),a}(t.cfg,e.id,f,()=>Bl(e,g,pc,2e-4*pc,m.map($d)).all);for(const t of v){const e=t.map(t=>t[0]),i=t.map(t=>t[1]);e.length&&u.push({minX:Math.min(...e),minY:Math.min(...i),maxX:Math.max(...e),maxY:Math.max(...i)})}const y=Dc(e,u),b=[y.x,y.y,y.w,y.h],w=new Map(e.rooms.map(e=>{const n=Fs(i.fill,e);return[e,_s(n,"lqi"===n&&e.area?Do(r,c,e.area):null,"light"===n?po(ho(r,c,e,t.virtualLights)):"none","temp"===n&&e.area?To(r,c,e.area):null,i.tempMin,i.tempMax,s,ls(i.customFill,e))]})),k=new Map;for(const t of e.rooms)t.id&&k.set(t.id,w.get(t)||null);const x=function(t,e=1e3){const i=[];for(const[s,n]of(t||[]).entries()){if("passage"!==n?.type)continue;const t={...n,id:String(n.id||`passage-${s}`),type:"passage",rx:Number(n.x)*e,ry:Number(n.y)*e,rlen:Number(n.length)*e};[t.rx,t.ry,t.rlen,t.angle].every(Number.isFinite)&&t.rlen>0&&i.push(t)}return i}((p.openings||[]).flatMap(t=>{if(!t.host)return[t];const e=m.find(e=>e.opening.id===t.id);return e?[Cd(t,e,sc)]:[]}),sc),$=ol(e.rooms,_,[],_c,g,pc,sc),S=m.filter(t=>Md(t,$,2e-4*pc)).map(t=>({x:t.center[0],y:t.center[1],angle:t.angle,length:t.length})),M=e.rooms.filter(t=>t.area||i.showBorders||"none"!==Fs(i.fill,t)).map(t=>{let s="room "+(e.bg?"overlay":"yard"),n="";const o=Fs(i.fill,t);if(i.showBorders||"none"!==o){s+=" styled";const e=[`--room-stroke:${i.color}`,`--room-stroke-op:${i.showBorders?i.opacity:0}`],o=w.get(t)||null;o?(s+=" filled",e.push(`--room-fill:${o.color}`,`--room-fill-op:${o.opacity.toFixed(3)}`)):e.push("--room-fill:transparent","--room-fill-op:0"),n=e.join(";")}const a=t.id||G,r=t.area||G,l=t.poly?j``:j``;return l}),C=e.rooms.filter(t=>{const e=w.get(t);return Es(i.glow,t)&&(!e||e.opacity<=0)}).map(t=>t.poly?j` ${this._t("gs.about_github")} @@ -5717,7 +5717,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="5ca433d2ee8bf92a41f4597ac53777315a9c ${t.busy?"…":this._t("btn.save")} - `}_saveKioskScale(t){this._kioskScale={...this._kioskScale,...t};try{localStorage.setItem(Kg,JSON.stringify(this._kioskScale))}catch{}this.requestUpdate()}_renderKioskDialog(){const t=this._kioskScale,e=(e,i)=>W` + `}_saveKioskScale(t){this._kioskScale={...this._kioskScale,...t};try{localStorage.setItem(Yg,JSON.stringify(this._kioskScale))}catch{}this.requestUpdate()}_renderKioskDialog(){const t=this._kioskScale,e=(e,i)=>W`
${this._rangeInput(50,300,5,Math.round(100*t[e]),t=>this._saveKioskScale({[e]:t/100}))} ${Math.round(100*t[e])}% @@ -5774,7 +5774,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="5ca433d2ee8bf92a41f4597ac53777315a9c ${this._spaceDialog?this._renderSpaceDialog():G} ${this._importDialog?this._renderImportDialog():G} ${this._toast?W``:G} - `;const s=this._spaceModel();if(!s)return G;const n="valid"===i.kind?[s]:t,o=s.vb,a=this._effectiveProjection();this._renderProjection=a,this._labs.active.length&&function(t){O_||W_(t);const e=z_,i=e.active.join(",");if(!i||i===H_)return;H_=i;const s=new Map(C_.map(t=>[t.id,t])),n=e.active.map(t=>{const e=s.get(t);return`${t} (#${e.issue}, expires ${e.expires})`}).join(", ");console.info(`HOUSEPLAN LABS: ${n}`)}(Rg);const r="iso"===a,l="devices"===this._mode&&this._showAll,c=this._renderDevices.filter(t=>t.space===s.id&&(!t.hidden||l)),h=this._renderDeviceSnapshot,d=this._spaceDisplayForRender(),u=r?this._isoDecorationLayers(d):null,p=u?this._isoOpeningPanels(u):[],_=this._resolvedRoomFills(s,d),g=this._resolvedGlowBase(s,d,_),m=d.showLqi??this._config.show_signal??!0,f=this._config.icon_size??2.5,v=f>8?2.5:f,y=Zu(v),b=this._viewOr(this._baseVb()),w=this._floorView(b),k=this._editing?"":this._stageBg(d),x=this._opMeasureView,$=this._decorMeasure,S=this._bdLive,M=this._furnLive,C="view"===this._mode?this._editorChromeMode:this._mode,D=this._roomHoverPaths(s),T=s.bg?this._display(s.bg.href):"",P=this._continuity.overlayVisible||"recovery-error"===this._continuity.state?this._continuity.recoveryReason:null,R=this._modeTransitionVisual,I=this._dayCycleState(),A=R?.viewWeight??("view"===this._mode?1:0),F=this._modeTransition.state?.from.presentedMode,E=!this._markup||!!R&&("view"===R.presentedMode||"devices"===R.presentedMode||"view"===F||"devices"===F),z=R?.stageColor||k,O=R?.sceneBrightness??1;return W` + `;const s=this._spaceModel();if(!s)return G;const n="valid"===i.kind?[s]:t,o=s.vb,a=this._effectiveProjection();this._renderProjection=a,this._labs.active.length&&function(t){N_||j_(t);const e=O_,i=e.active.join(",");if(!i||i===L_)return;L_=i;const s=new Map(D_.map(t=>[t.id,t])),n=e.active.map(t=>{const e=s.get(t);return`${t} (#${e.issue}, expires ${e.expires})`}).join(", ");console.info(`HOUSEPLAN LABS: ${n}`)}(Ig);const r="iso"===a,l="devices"===this._mode&&this._showAll,c=this._renderDevices.filter(t=>t.space===s.id&&(!t.hidden||l)),h=this._renderDeviceSnapshot,d=this._spaceDisplayForRender(),u=r?this._isoDecorationLayers(d):null,p=u?this._isoOpeningPanels(u):[],_=this._resolvedRoomFills(s,d),g=this._resolvedGlowBase(s,d,_),m=d.showLqi??this._config.show_signal??!0,f=this._config.icon_size??2.5,v=f>8?2.5:f,y=Qu(v),b=this._viewOr(this._baseVb()),w=this._floorView(b),k=this._editing?"":this._stageBg(d),x=this._opMeasureView,$=this._decorMeasure,S=this._bdLive,M=this._furnLive,C="view"===this._mode?this._editorChromeMode:this._mode,D=this._roomHoverPaths(s),T=s.bg?this._display(s.bg.href):"",P=this._continuity.overlayVisible||"recovery-error"===this._continuity.state?this._continuity.recoveryReason:null,R=this._modeTransitionVisual,I=this._dayCycleState(),A=R?.viewWeight??("view"===this._mode?1:0),F=this._modeTransition.state?.from.presentedMode,E=!this._markup||!!R&&("view"===R.presentedMode||"devices"===R.presentedMode||"view"===F||"devices"===F),z=R?.stageColor||k,O=R?.sceneBrightness??1;return W` + transform=${u?.structural?Y_():G}> ${""} ${this._wallHatchDefs(d.color)}${j`${this._paperShapes(s.rooms).map(t=>"path"in t?j``:"poly"in t?j``:j``)}`} ${this._editing?this._renderMarkupDefs(o):G} @@ -5895,7 +5895,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="5ca433d2ee8bf92a41f4597ac53777315a9c transform=${s.bg.angle?`rotate(${s.bg.angle} ${s.bg.x+s.bg.w/2} ${s.bg.y+s.bg.h/2})`:G} @dblclick=${t=>this._openBackdropDialog(t)} preserveAspectRatio="none" />`:G} - ${(()=>{const t=this._openPairs(),e=new Map,i=t=>(e.has(t)||e.set(t,hi(t)),e.get(t));return s.rooms.filter(t=>t.area||"view"===this._mode||this._markup||d.showBorders).map(e=>{let n="room "+(s.bg?"overlay":"yard")+(this._markup?" outlined":"");!this._markup||e.id!==this._mergeSel&&e.id!==this._splitSel?.roomId||(n+=" picked");let o="";const a=Fs(d.fill,e);if(!this._markup&&(d.showBorders||"none"!==a)){n+=" styled";const t=[];t.push(`--room-stroke:${d.color}`,`--room-stroke-op:${d.showBorders?d.opacity:0}`);const i=_.byRoom.get(e)||null;i?(n+=" filled",t.push(`--room-fill:${i.color}`,`--room-fill-op:${i.opacity}`)):t.push("--room-fill:transparent","--room-fill-op:0"),o=t.join(";")}let r;const l=t=>{"view"===this._mode&&(void 0===r&&(r=this._roomArea(e)),this._showTip(t,e.name||this._t("room.unnamed"),r?this._t("tip.area",{value:r}):"",m?this._roomLqi(e.area):null,this._roomTemp(e),this._roomHum(e)))},c=this._markup&&(e.id===this._mergeSel||e.id===this._splitSel?.roomId),h=e.id&&!c?t.filter(t=>t.a.id===e.id||t.b.id===e.id).flatMap(t=>t.segs):[],u=c?[]:this._thickWallCuts(),p=h.concat(u);p.length&&(n+=" noedge");const g=i(e),f=this._spaceWalls,v=f.length&&e.id&&g&&hl(s.rooms,e.id,f,this._openPairs().flatMap(t=>t.segs),this._wallKeyPitch,this._cellCm,this._gridPitch,Jg)||g,y=v?Ti(v,(b=e,s.rooms.filter(t=>t!==b).map(i).filter(Boolean))):[];var b;const w=t=>"M "+t.map(t=>t[0]+" "+t[1]).join(" L ")+" Z",k=v?this._cleanFloor(e,v,s).path:"",x=e.id||G,$=e.area||G,S=k&&v?j`{const t=this._openPairs(),e=new Map,i=t=>(e.has(t)||e.set(t,hi(t)),e.get(t));return s.rooms.filter(t=>t.area||"view"===this._mode||this._markup||d.showBorders).map(e=>{let n="room "+(s.bg?"overlay":"yard")+(this._markup?" outlined":"");!this._markup||e.id!==this._mergeSel&&e.id!==this._splitSel?.roomId||(n+=" picked");let o="";const a=Fs(d.fill,e);if(!this._markup&&(d.showBorders||"none"!==a)){n+=" styled";const t=[];t.push(`--room-stroke:${d.color}`,`--room-stroke-op:${d.showBorders?d.opacity:0}`);const i=_.byRoom.get(e)||null;i?(n+=" filled",t.push(`--room-fill:${i.color}`,`--room-fill-op:${i.opacity}`)):t.push("--room-fill:transparent","--room-fill-op:0"),o=t.join(";")}let r;const l=t=>{"view"===this._mode&&(void 0===r&&(r=this._roomArea(e)),this._showTip(t,e.name||this._t("room.unnamed"),r?this._t("tip.area",{value:r}):"",m?this._roomLqi(e.area):null,this._roomTemp(e),this._roomHum(e)))},c=this._markup&&(e.id===this._mergeSel||e.id===this._splitSel?.roomId),h=e.id&&!c?t.filter(t=>t.a.id===e.id||t.b.id===e.id).flatMap(t=>t.segs):[],u=c?[]:this._thickWallCuts(),p=h.concat(u);p.length&&(n+=" noedge");const g=i(e),f=this._spaceWalls,v=f.length&&e.id&&g&&hl(s.rooms,e.id,f,this._openPairs().flatMap(t=>t.segs),this._wallKeyPitch,this._cellCm,this._gridPitch,Zg)||g,y=v?Ti(v,(b=e,s.rooms.filter(t=>t!==b).map(i).filter(Boolean))):[];var b;const w=t=>"M "+t.map(t=>t[0]+" "+t[1]).join(" L ")+" Z",k=v?this._cleanFloor(e,v,s).path:"",x=e.id||G,$=e.area||G,S=k&&v?j`{this._notePointer(t),this._pointerModality.hoverEnabled&&(this._hoverRoom={space:s.id,room:e})}} @@ -6072,7 +6072,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="5ca433d2ee8bf92a41f4597ac53777315a9c `:G} ${this._toast?W``:G} - `}_vacCandidateStatus(t,e,i=this._planHass){const s=this._bindingStatus("entity:"+t);if("ha_disabled"===s.kind)return"disabled";if("orphaned"===s.kind)return"missing";if("unverified"===s.kind)return"unverified";const n=i?.states?.[t];return"unavailable"===n?.state?"unavailable":e?.hasPosition?"ok":"unsupported"}_vacOpenAllCameras(t){const e=this._haRegistry.entities||{},i=[];for(const[t,s]of Object.entries(this.hass?.states||{})){if(!t.startsWith("camera."))continue;const n=zh(t,s,e[t]);n&&i.push(n)}this._vacAllCameraCache={devId:t.id,candidates:i},this._vacAllCamerasFor=t.id}_vacSourceResolution(t,e=!1,i=this._planHass){const s=t.marker?.vacuum,n="string"==typeof s?.source&&!!s.source,o=new Set(t.entities||[]),a=new Set(o);n&&a.add(s.source);const r=i?.entities||{},l=[];for(const t of a){const e=i?.states?.[t],o=zh(t,e,r[t]);o?l.push(o):n&&t===s.source&&l.push({entityId:t,name:String(e?.attributes?.friendly_name||t),platform:r[t]?.platform?String(r[t].platform):null,category:t.startsWith("camera.")?"camera":"partial",hasPosition:!1,hasRooms:!1,hasPath:!1,hasMapId:!1,score:0})}if(e&&this._vacAllCameraCache?.devId===t.id){const t=new Set(l.map(t=>t.entityId));for(const e of this._vacAllCameraCache.candidates)t.has(e.entityId)||l.push(e)}const c={};for(const t of l)c[t.entityId]=this._vacCandidateStatus(t.entityId,t,i);return function(t,e,i,s){const n="string"==typeof t&&t.length>0,o=new Set(e),a=Array.from(i).sort((e,i)=>n&&e.entityId===t?-1:n&&i.entityId===t?1:i.score-e.score||e.entityId.localeCompare(i.entityId));if(n){const e=a.find(e=>e.entityId===t);return{entityId:t,status:s[t]||(e?.hasPosition?"ok":"unverified"),pinned:!0,candidates:a}}const r=a.find(t=>o.has(t.entityId)&&t.hasPosition&&"ok"===s[t.entityId]);return r?{entityId:r.entityId,status:"ok",pinned:!1,candidates:a}:{entityId:null,status:"none",pinned:!1,candidates:a}}(s?.source,o,l,c)}_vacSource(t,e=this._planHass){if(!1===t.marker?.vacuum?.live)return null;const i=this._vacSourceResolution(t,!1,e);return"ok"===i.status||"unsupported"===i.status?i.entityId:null}_vacEntity(t){return t.primary?.startsWith("vacuum.")?t.primary:(t.entities||[]).find(t=>t.startsWith("vacuum."))||null}_isVacDev(t){return!!this._vacEntity(t)}_activitySourceKey(t){return this._activitySnapshot(t).sourceKey}_activitySnapshot(t,e=ho(this._planHass,this._devices,null,this._virtualLights)){const i=qu(this._planHass,t,this._devices,e,this._fullRegistryHass);return{samples:i.samples,sourceKey:Uu(this._planHass,t,i)}}_stampActivity(t,e,i){let s=this._activityRt.get(t);s||(s=gp(i||"",[]),this._activityRt.set(t,s)),null!=i&&(s.sources=i),fp(s,e,Date.now(),window.clearTimeout.bind(window),t=>window.setTimeout(()=>this.requestUpdate(),t))}_syncActivityRuntime(){const t=new Map;if(!this.hass)return t;if(!1===this._config?.live_states){for(const t of this._activityRt.values())clearTimeout(t.timer);return this._activityRt.clear(),t}const e=new Set,i=ho(this._planHass,this._devices,null,this._virtualLights);for(const s of this._devices){if(s.hidden)continue;if("icon_ripple"!==Bi(s.marker?.display))continue;e.add(s.id);const n=this._activitySnapshot(s,i);t.set(s.id,n);const{samples:o,sourceKey:a}=n;let r=this._activityRt.get(s.id);r?r.sources!==a&&mp(r,a,o,window.clearTimeout.bind(window)):(r=gp(a,o),this._activityRt.set(s.id,r))}for(const[t,i]of this._activityRt)e.has(t)||(clearTimeout(i.timer),this._activityRt.delete(t));return t}_activityTick(){if(!this.hass)return;const t=this._syncActivityRuntime();for(const e of this._devices){if(e.hidden)continue;if("icon_ripple"!==Bi(e.marker?.display))continue;const i=t.get(e.id)||this._activitySnapshot(e),{samples:s,sourceKey:n}=i,o=this._activityRt.get(e.id);if(!o||o.sources!==n)continue;const a=vp(o,s,window.clearTimeout.bind(window));a&&this._stampActivity(e.id,a,n)}}_vacTick(){if(this.hass)for(const t of this._devices){if(t.hidden||!this._isVacDev(t))continue;if("static_icon"===Bi(t.marker?.display)){this._vacRt.delete(t.id);continue}const e=this._vacSource(t);if(!e)continue;const i=this._vacEntity(t),s=Lh(this.hass.states[i||""]?.state),n=Eh(this.hass.states[e]?.attributes);let o=this._vacRt.get(t.id);o||(o={trail:[],lastKey:"",lastTs:0,moving:!1,jump:!1,endedTs:0,lastPos:null},this._vacRt.set(t.id,o)),s&&!o.moving&&(o.trail=[],o.lastPos=null);const a="never"!==Uh(t.marker?.vacuum)&&!n?.path.length;!s&&o.moving&&(o.endedTs=Date.now(),a&&o.lastPos&&(o.trail=Hh(o.trail,o.lastPos,40)),o.lastPos=null),o.moving=s;const r=n?.pos;if(s&&r){const t=r.x+":"+r.y;if(t!==o.lastKey){const e=Date.now();o.jump=o.lastTs>0&&e-o.lastTs>1e4,o.lastKey=t,o.lastTs=e,a&&o.lastPos&&(o.trail=Hh(o.trail,o.lastPos,40)),o.lastPos=[r.x,r.y]}}}}_vacEnsureMarker(t){const e=this._serverCfg;if(!e)return null;e.markers=e.markers||[];const i=e.markers.find(e=>e.id===t.id);if(i)return i;if("device"!==t.bindingKind&&"entity"!==t.bindingKind||!t.bindingRef)return null;const s={id:t.id,binding:t.bindingKind+":"+t.bindingRef,space:t.space||null,area:t.area||null,hidden:!!t.hidden};return e.markers.push(s),s}_renderVacSection(t){const e=this._devices.find(e=>e.id===t.devId);if(!e||!this._isVacDev(e))return G;const i=e.marker?.vacuum||{},s=this._vacAllCamerasFor===e.id,n=this._vacSourceResolution(e,s),o=n.entityId,a=n.candidates.find(t=>t.entityId===o)||null,r=o?Eh(this.hass?.states[o]?.attributes):null,l=!1!==i.live&&("ok"===n.status||"unsupported"===n.status),c=this._vacPlanRoomAnchors(e.space),h=r?function(t,e){const i=new Set(e.map(Oh).filter(Boolean)),s=new Set;for(const e of t){const t=Oh(e.name||"");t&&i.has(t)&&s.add(t)}return s.size}(r.rooms,c.map(t=>t.name)):0,d=!!(l&&r&&h>=3),u=Object.keys(i.calibration||{}),p=t=>{const i=this._vacEnsureMarker(e);i&&(i.vacuum={...i.vacuum||{},...t},this._regSignature="",this._maybeRebuildDevices(),this._saveConfig(),this.requestUpdate())},_=new Set(e.entities||[]),g=n.candidates.filter(t=>_.has(t.entityId)||t.entityId===i.source),m=s?n.candidates.filter(t=>t.entityId.startsWith("camera.")&&!g.some(e=>e.entityId===t.entityId)):[],f=t=>[t.hasPosition?this._t("vac.cap_position"):"",t.hasRooms?this._t("vac.cap_rooms_short"):"",t.hasPath?this._t("vac.cap_path"):"",t.hasMapId?this._t("vac.cap_map"):""].filter(Boolean).join(" · ")||this._t("vac.cap_none"),v=t=>W` + `}_vacCandidateStatus(t,e,i=this._planHass){const s=this._bindingStatus("entity:"+t);if("ha_disabled"===s.kind)return"disabled";if("orphaned"===s.kind)return"missing";if("unverified"===s.kind)return"unverified";const n=i?.states?.[t];return"unavailable"===n?.state?"unavailable":e?.hasPosition?"ok":"unsupported"}_vacOpenAllCameras(t){const e=this._haRegistry.entities||{},i=[];for(const[t,s]of Object.entries(this.hass?.states||{})){if(!t.startsWith("camera."))continue;const n=zh(t,s,e[t]);n&&i.push(n)}this._vacAllCameraCache={devId:t.id,candidates:i},this._vacAllCamerasFor=t.id}_vacSourceResolution(t,e=!1,i=this._planHass){const s=t.marker?.vacuum,n="string"==typeof s?.source&&!!s.source,o=new Set(t.entities||[]),a=new Set(o);n&&a.add(s.source);const r=i?.entities||{},l=[];for(const t of a){const e=i?.states?.[t],o=zh(t,e,r[t]);o?l.push(o):n&&t===s.source&&l.push({entityId:t,name:String(e?.attributes?.friendly_name||t),platform:r[t]?.platform?String(r[t].platform):null,category:t.startsWith("camera.")?"camera":"partial",hasPosition:!1,hasRooms:!1,hasPath:!1,hasMapId:!1,score:0})}if(e&&this._vacAllCameraCache?.devId===t.id){const t=new Set(l.map(t=>t.entityId));for(const e of this._vacAllCameraCache.candidates)t.has(e.entityId)||l.push(e)}const c={};for(const t of l)c[t.entityId]=this._vacCandidateStatus(t.entityId,t,i);return function(t,e,i,s){const n="string"==typeof t&&t.length>0,o=new Set(e),a=Array.from(i).sort((e,i)=>n&&e.entityId===t?-1:n&&i.entityId===t?1:i.score-e.score||e.entityId.localeCompare(i.entityId));if(n){const e=a.find(e=>e.entityId===t);return{entityId:t,status:s[t]||(e?.hasPosition?"ok":"unverified"),pinned:!0,candidates:a}}const r=a.find(t=>o.has(t.entityId)&&t.hasPosition&&"ok"===s[t.entityId]);return r?{entityId:r.entityId,status:"ok",pinned:!1,candidates:a}:{entityId:null,status:"none",pinned:!1,candidates:a}}(s?.source,o,l,c)}_vacSource(t,e=this._planHass){if(!1===t.marker?.vacuum?.live)return null;const i=this._vacSourceResolution(t,!1,e);return"ok"===i.status||"unsupported"===i.status?i.entityId:null}_vacEntity(t){return t.primary?.startsWith("vacuum.")?t.primary:(t.entities||[]).find(t=>t.startsWith("vacuum."))||null}_isVacDev(t){return!!this._vacEntity(t)}_activitySourceKey(t){return this._activitySnapshot(t).sourceKey}_activitySnapshot(t,e=ho(this._planHass,this._devices,null,this._virtualLights)){const i=Wu(this._planHass,t,this._devices,e,this._fullRegistryHass);return{samples:i.samples,sourceKey:Gu(this._planHass,t,i)}}_stampActivity(t,e,i){let s=this._activityRt.get(t);s||(s=mp(i||"",[]),this._activityRt.set(t,s)),null!=i&&(s.sources=i),vp(s,e,Date.now(),window.clearTimeout.bind(window),t=>window.setTimeout(()=>this.requestUpdate(),t))}_syncActivityRuntime(){const t=new Map;if(!this.hass)return t;if(!1===this._config?.live_states){for(const t of this._activityRt.values())clearTimeout(t.timer);return this._activityRt.clear(),t}const e=new Set,i=ho(this._planHass,this._devices,null,this._virtualLights);for(const s of this._devices){if(s.hidden)continue;if("icon_ripple"!==Bi(s.marker?.display))continue;e.add(s.id);const n=this._activitySnapshot(s,i);t.set(s.id,n);const{samples:o,sourceKey:a}=n;let r=this._activityRt.get(s.id);r?r.sources!==a&&fp(r,a,o,window.clearTimeout.bind(window)):(r=mp(a,o),this._activityRt.set(s.id,r))}for(const[t,i]of this._activityRt)e.has(t)||(clearTimeout(i.timer),this._activityRt.delete(t));return t}_activityTick(){if(!this.hass)return;const t=this._syncActivityRuntime();for(const e of this._devices){if(e.hidden)continue;if("icon_ripple"!==Bi(e.marker?.display))continue;const i=t.get(e.id)||this._activitySnapshot(e),{samples:s,sourceKey:n}=i,o=this._activityRt.get(e.id);if(!o||o.sources!==n)continue;const a=yp(o,s,window.clearTimeout.bind(window));a&&this._stampActivity(e.id,a,n)}}_vacTick(){if(this.hass)for(const t of this._devices){if(t.hidden||!this._isVacDev(t))continue;if("static_icon"===Bi(t.marker?.display)){this._vacRt.delete(t.id);continue}const e=this._vacSource(t);if(!e)continue;const i=this._vacEntity(t),s=Lh(this.hass.states[i||""]?.state),n=Eh(this.hass.states[e]?.attributes);let o=this._vacRt.get(t.id);o||(o={trail:[],lastKey:"",lastTs:0,moving:!1,jump:!1,endedTs:0,lastPos:null},this._vacRt.set(t.id,o)),s&&!o.moving&&(o.trail=[],o.lastPos=null);const a="never"!==Uh(t.marker?.vacuum)&&!n?.path.length;!s&&o.moving&&(o.endedTs=Date.now(),a&&o.lastPos&&(o.trail=Hh(o.trail,o.lastPos,40)),o.lastPos=null),o.moving=s;const r=n?.pos;if(s&&r){const t=r.x+":"+r.y;if(t!==o.lastKey){const e=Date.now();o.jump=o.lastTs>0&&e-o.lastTs>1e4,o.lastKey=t,o.lastTs=e,a&&o.lastPos&&(o.trail=Hh(o.trail,o.lastPos,40)),o.lastPos=[r.x,r.y]}}}}_vacEnsureMarker(t){const e=this._serverCfg;if(!e)return null;e.markers=e.markers||[];const i=e.markers.find(e=>e.id===t.id);if(i)return i;if("device"!==t.bindingKind&&"entity"!==t.bindingKind||!t.bindingRef)return null;const s={id:t.id,binding:t.bindingKind+":"+t.bindingRef,space:t.space||null,area:t.area||null,hidden:!!t.hidden};return e.markers.push(s),s}_renderVacSection(t){const e=this._devices.find(e=>e.id===t.devId);if(!e||!this._isVacDev(e))return G;const i=e.marker?.vacuum||{},s=this._vacAllCamerasFor===e.id,n=this._vacSourceResolution(e,s),o=n.entityId,a=n.candidates.find(t=>t.entityId===o)||null,r=o?Eh(this.hass?.states[o]?.attributes):null,l=!1!==i.live&&("ok"===n.status||"unsupported"===n.status),c=this._vacPlanRoomAnchors(e.space),h=r?function(t,e){const i=new Set(e.map(Oh).filter(Boolean)),s=new Set;for(const e of t){const t=Oh(e.name||"");t&&i.has(t)&&s.add(t)}return s.size}(r.rooms,c.map(t=>t.name)):0,d=!!(l&&r&&h>=3),u=Object.keys(i.calibration||{}),p=t=>{const i=this._vacEnsureMarker(e);i&&(i.vacuum={...i.vacuum||{},...t},this._regSignature="",this._maybeRebuildDevices(),this._saveConfig(),this.requestUpdate())},_=new Set(e.entities||[]),g=n.candidates.filter(t=>_.has(t.entityId)||t.entityId===i.source),m=s?n.candidates.filter(t=>t.entityId.startsWith("camera.")&&!g.some(e=>e.entityId===t.entityId)):[],f=t=>[t.hasPosition?this._t("vac.cap_position"):"",t.hasRooms?this._t("vac.cap_rooms_short"):"",t.hasPath?this._t("vac.cap_path"):"",t.hasMapId?this._t("vac.cap_map"):""].filter(Boolean).join(" · ")||this._t("vac.cap_none"),v=t=>W`
`)}return this._vacLastView=e,n.length&&!this._vacRaf&&this._vacRafLoop(),n.length||o.length?W` ${o.length?j`${o}`:G} - ${n}`:G}_renderDevice(t,e,i=!0){const s=this._pos(t),n=this._scenePoint([s.x,s.y]),o=(n[0]-e.x)/e.w*100,a=(n[1]-e.y)/e.h*100,r=this._devicePresentation(t,i),l=[`left:${o}%`,`top:${a}%`,...Go(r)],c=r.disabledReason,h=r.haDisabled?this._t(`marker.ha_disabled_${c}`):t.userHidden?this._t("marker.hidden_ghost"):t.name,d=Ou(r),u="view"===this._mode||"devices"===this._mode,p=[h,r.haDisabled?"":this._t(`marker.state_a11y_${d}`),"none"!==r.pulse.kind?this._t(`marker.pulse_a11y_${r.pulse.reason}`):"",r.valueFullText||r.valueText||"",Ro(r.valueBadge),null!=r.lqiText&&r.lqiBand?this._t(`marker.lqi_a11y_${r.lqiBand}`,{value:r.lqiText}):""].filter(Boolean).join(", "),_=[t.model,r.valueBadge?.fullText||"",null!=r.lqiText?"LQI "+r.lqiText:""].filter(Boolean).join(" · ");return W`
`}_roomArea(t){const e=hi(t);if(!e)return null;const i=this._spaceModel();if(!i)return null;const s=this._spaceWalls,n=s.length&&t.id&&hl(i.rooms,t.id,s,this._openPairs().flatMap(t=>t.segs),this._wallKeyPitch,this._cellCm,this._gridPitch,Jg)||e,o=this._cleanFloor(t,n),a=this._cellCm/this._gridPitch;return Ia(o.area*a*a/1e4,"mi"===this._renderPlanHass?.config?.unit_system?.length)}_roomTemp(t){const e=t.settings?.temp_source;return e?Mo(this._renderPlanHass,e,"temp",this._markers):t.area?this._climate().get(t.area)?.temp??null:null}_roomHum(t){const e=t.settings?.hum_source;return e?Mo(this._renderPlanHass,e,"hum",this._markers):t.area?this._climate().get(t.area)?.hum??null:null}_climate(){const t=this._serverCfg?.markers,e=this._renderPlanHass,i=this._climateCache;if(i&&i.h===e&&i.r===this._iconRules&&i.mk===t)return i.m;const s=function(t,e,i){const s=new Map;if(!t?.entities)return s;const n=wo(i),o=new Set;for(const t of i||[]){if(t?.removed||!0!==t?.use_climate_temp)continue;const e=(t.binding||"").indexOf(":");e>0&&o.add(t.binding.slice(e+1))}const a=new Map;for(const[e,i]of Object.entries(t.entities)){if(i.device_id&&n.devices.has(i.device_id)||!i.device_id&&n.entities.has(e))continue;const s=i.device_id?t.devices?.[i.device_id]:null,r=i.area_id||s?.area_id||null;if(!r)continue;if(i.entity_category)continue;if(!(o.size>0&&e.startsWith("climate.")&&(o.has(e)||i.device_id&&o.has(i.device_id)))){if(Yt.has(i.platform))continue;if(Co.test(e))continue}let l=a.get(r);l||(l=new Map,a.set(r,l));const c=i.device_id||e;let h=l.get(c);if(!h){const n=t.states?.[e];h={name:(s?s.name_by_user||s.name:i.name||n?.attributes?.friendly_name||e)||e,model:s?.model,ents:[]},l.set(c,h)}h.ents.push(e)}for(const[i,n]of a){const a=[],r=[];for(const[i,s]of n){const n=bo(t,s.name,s.model,s.ents,e),l="mdi:thermometer"===n||"mdi:air-filter"===n;if(l){const e=go(t,s.ents);null!=e&&a.push(e)}if(o.size>0&&(o.has(i)||s.ents.some(t=>o.has(t)))){const e=mo(t,s.ents);null!=e&&a.push(e)}if(l||"mdi:water-percent"===n){const e=vo(t,s.ents);null!=e&&r.push(e)}}(a.length||r.length)&&s.set(i,{temp:a.length?Math.round(a.reduce((t,e)=>t+e,0)/a.length*10)/10:null,hum:r.length?Math.round(r.reduce((t,e)=>t+e,0)/r.length):null})}return s}(e,this._iconRules,t);return this._climateCache={h:e,r:this._iconRules,mk:t,m:s},s}_resetRoomDialogFields(){this._roomEditId=null,this._roomFill="",this._roomCustomFill=null,this._roomTempSrc="",this._roomHumSrc="",this._roomSrcOpen=null,this._roomSrcFilter="",this._roomNameScale=1,this._roomLabelScale=1}_openRoomEdit(t){if(!t.id)return;this._roomEditId=t.id,this._nameSel=t.name||"",this._areaSel=t.area||"",this._roomFill="glow"===t.settings?.fill_mode?"":t.settings?.fill_mode||"";const e=t.settings?.custom_fill;this._roomCustomFill=e&&"object"==typeof e?rs(e,cs(this._curSpaceCfg).customFill):null,this._roomTempSrc=t.settings?.temp_source||"",this._roomHumSrc=t.settings?.hum_source||"",this._roomNameScale=zs(t.settings?.name_scale),this._roomLabelScale=zs(t.settings?.label_scale),this._roomSrcOpen=null,this._roomSrcFilter="",this._roomDialog=!0}_roomSettingsFromDialog(){const t={};return this._roomFill&&(t.fill_mode=this._roomFill),this._roomCustomFill&&(t.custom_fill=this._roomCustomFill),this._roomTempSrc&&(t.temp_source=this._roomTempSrc),this._roomHumSrc&&(t.hum_source=this._roomHumSrc),1!==this._roomNameScale&&(t.name_scale=this._roomNameScale),1!==this._roomLabelScale&&(t.label_scale=this._roomLabelScale),Object.keys(t).length?t:null}_saveRoomEdit(){const t=this._curSpaceCfg,e=t?.rooms.find(t=>t.id===this._roomEditId);if(!e)return this._roomDialog=!1,void(this._roomEditId=null);e.name=this._nameSel.trim()||e.name,e.area=this._areaSel||null;const i=e.settings||{},s={...i};this._roomFill?s.fill_mode=this._roomFill:delete s.fill_mode,this._roomCustomFill?s.custom_fill=this._roomCustomFill:delete s.custom_fill,"glow"===i.fill_mode&&"boolean"!=typeof i.glow&&(s.glow=!0),this._roomTempSrc?s.temp_source=this._roomTempSrc:delete s.temp_source,this._roomHumSrc?s.hum_source=this._roomHumSrc:delete s.hum_source,1!==this._roomNameScale?s.name_scale=this._roomNameScale:delete s.name_scale,1!==this._roomLabelScale?s.label_scale=this._roomLabelScale:delete s.label_scale,Object.keys(s).length?e.settings=s:delete e.settings,this._saveConfig(),this._roomDialog=!1,this._roomEditId=null,this._nameSel="",this._areaSel="",this._regSignature="",this._maybeRebuildDevices(),this.requestUpdate(),this._showToast(this._t("toast.room_updated"))}_roomSrcCandidates(){const t=this._planHass,e=wo(this._markers),i=this._roomSrcFilter.trim().toLowerCase(),s=[];for(const n of Object.values(t.devices)){if("service"===n.entry_type)continue;if(e.devices.has(n.id))continue;const t=(n.name_by_user||n.name||n.id).trim();i&&!t.toLowerCase().includes(i)||s.push({value:"device:"+n.id,label:t,sub:n.model||this._t("marker.sub_device")})}for(const[n,o]of Object.entries(t.entities)){if(!n.startsWith("sensor.")||o.hidden)continue;if(ko(t,n,e))continue;const a=o.name||t.states[n]?.attributes?.friendly_name||n;i&&!(a+" "+n).toLowerCase().includes(i)||s.push({value:"entity:"+n,label:a,sub:n})}return s.sort((t,e)=>t.label.localeCompare(e.label)),s.slice(0,200)}_roomSrcLabel(t){const e=t.indexOf(":"),i=t.slice(0,e),s=t.slice(e+1);return"device"===i?this._fullRegistryHass.devices[s]?.name_by_user||this._fullRegistryHass.devices[s]?.name||s:this._fullRegistryHass.entities[s]?.name||this.hass.states[s]?.attributes?.friendly_name||s}_labelPos(t,e){const i=this._layout["rl_"+(t.id||"")];if(i&&i.s===e)return{x:i.x*Jg,y:i.y*Jg};const s=this._snap(this._roomCenter(t));return{x:s[0],y:s[1]}}_labelDown(t,e,i){if("plan"!==this._mode)return;t.preventDefault(),t.stopPropagation();const s=this._labelPos(e,i);this._drag={id:"rl_"+(e.id||""),sx:t.clientX,sy:t.clientY,ox:s.x,oy:s.y,moved:!1},om(t),this._tip=null}_labelMove(t,e,i){const s="rl_"+(e.id||"");if(!this._drag||this._drag.id!==s)return;const n=this._stageEl;if(!n)return;const o=this._spaceModelById(i);if(!o)return;const a=o.vb,r=n.getBoundingClientRect(),l=this._viewOr(a),c=(t.clientX-this._drag.sx)/r.width*l.w,h=(t.clientY-this._drag.sy)/r.height*l.h;Math.abs(t.clientX-this._drag.sx)+Math.abs(t.clientY-this._drag.sy)>3&&(this._drag.moved=!0);const d=fc(this._drag.ox+c),u=fc(this._drag.oy+h);this._savePos({id:s,space:i},d,u)}_labelUp(t){const e="rl_"+(t.id||"");if(!this._drag||this._drag.id!==e)return;const i=this._drag.moved;this._drag=i?this._drag:null,i&&window.setTimeout(()=>this._drag=null,0)}_labelScale(t){const e=this._layout["rl_"+(t.id||"")]?.k;return"number"==typeof e&&Number.isFinite(e)?Math.min(3,Math.max(.5,e)):1}_rlResizeDown(t,e,i){if("plan"!==this._mode)return;t.preventDefault(),t.stopPropagation();const s=t.target.closest(".roomlabel");if(!s)return;const n=s.getBoundingClientRect(),o=n.left+n.width/2,a=n.top+n.height/2,r=Math.max(8,Math.hypot(t.clientX-o,t.clientY-a));this._rlResize={id:"rl_"+(e.id||""),space:i,k0:this._labelScale(e),cx:o,cy:a,d0:r},om(t)}_rlResizeMove(t){const e=this._rlResize;if(!e)return;t.stopPropagation();const i=Math.max(8,Math.hypot(t.clientX-e.cx,t.clientY-e.cy)),s=Math.min(3,Math.max(.5,e.k0*(i/e.d0))),n=this._layout[e.id];if(n)this._layout={...this._layout,[e.id]:{...n,k:s}};else{const t=e.id.slice(3),i=this._spaceModelById(e.space);if(!i)return;const n=i.rooms.find(e=>e.id===t);if(!n)return;const o=this._labelPos(n,e.space);this._layout={...this._layout,[e.id]:{s:e.space,x:o.x/Jg,y:o.y/Jg,k:s}}}this._dirtyPos.add(e.id)}_rlResizeUp(){this._rlResize&&(this._rlResize=null,this._persistLayout())}_renderRoomGear(t,e,i){if(!t.id)return G;let s=null;if(t.poly?(s=this._gearPtCache.get(t.poly)||null,s||(s=$i(t.poly),this._gearPtCache.set(t.poly,s))):null!=t.x&&null!=t.y&&(s=[t.x+(t.w||0)/2,t.y+(t.h||0)/2]),!s)return G;const n=(s[0]-i.x)/i.w*100,o=(s[1]-i.y)/i.h*100;return W`
`}get _measureAnchor(){return this._markup&&this._cursorPt?"draw"===this._tool&&this._path.length&&!this._contourClosed?this._path[this._path.length-1]:"split"===this._tool&&this._splitSel?.pts?.length?this._splitSel.pts[this._splitSel.pts.length-1]:null:null}_renderMeasureLabel(t){const e=this._measureAnchor,i=this._cursorPt,s=(i[0]-t.x)/t.w*100,n=(i[1]-t.y)/t.h*100,o=Os(e,i),a=Math.round(10*o)/10,r=function(t,e,i=.001){if(t.length<2||e.length<2)return!1;const s=Math.abs(e[0]-t[0]),n=Math.abs(e[1]-t[1]);if(!Number.isFinite(s)||!Number.isFinite(n)||Math.hypot(s,n)<=i)return!1;const o=Math.max(s,n,1);return s<=i*o||n<=i*o||Math.abs(s-n)<=i*o}(e,i,2e-4*this._gridPitch);return W`
- ${this._fmtLen(e,i)} · ${a}°
`}get _decorMeasure(){const t=this._decorDraft;if(!t||"decor"!==this._mode)return null;const[e,i]=t.a,[s,n]=t.b;if(Math.abs(e-s)<1e-6&&Math.abs(i-n)<1e-6)return null;const o=(e+s)/2,a=(i+n)/2;if("line"===t.kind){const e=Os(t.a,t.b);return{x:o,y:a,on45:Ns(e),text:`${this._fmtLen(t.a,t.b)} · ${Math.round(10*e)/10}°`}}const r=this._fmtLen([e,i],[s,i]),l=this._fmtLen([s,i],[s,n]);if("ellipse"===t.kind){const t=this._fmtLen([0,0],[Math.abs(s-e)/2,0]),r=this._fmtLen([0,0],[0,Math.abs(n-i)/2]);return{x:o,y:a,on45:!1,text:Math.abs(Math.abs(s-e)-Math.abs(n-i))<1e-6?`R ${t}`:`Rx ${t} × Ry ${r}`}}return{x:o,y:a,on45:!1,text:`${r} × ${l} · ${Ia(hr(Math.abs(s-e),this._cellCm,this._gridPitch)*hr(Math.abs(n-i),this._cellCm,this._gridPitch)/1e4,this._imperial)}`}}get _alignPoint(){if(this._markup){if("draw"===this._tool&&this._path.length&&!this._contourClosed&&this._cursorPt)return this._cursorPt;if("split"===this._tool&&this._splitSel?.pts?.length&&this._cursorPt)return this._cursorPt;if(this._drag?.id.startsWith("rl_")&&this._drag.moved){const t=this._drag.id.slice(3),e=this._spaceModel()?.rooms.find(e=>e.id===t);return e?(()=>{const t=this._labelPos(e,this._space);return[t.x,t.y]})():null}return null}if("devices"===this._mode&&this._drag?.moved){const t=this._devices.find(t=>t.id===this._drag.id);return t?(()=>{const e=this._pos(t);return[e.x,e.y]})():null}if("decor"===this._mode){if(this._decorDraft)return this._decorDraft.b;if(this._decorMove){const t=this._decorList.find(t=>t.id===this._decorMove.id);if(!t)return null;const e=Jg,i=this._decorH;return"line"===t.kind?[t.x1*e,t.y1*i]:[t.x*e,t.y*i]}return null}return null}_alignCandidates(){const t=[],e=this._spaceModel();if(this._markup){if(!e)return t;if(this._drag?.id.startsWith("rl_")){const i=this._drag.id.slice(3);for(const s of e.rooms){if(!s.name||s.id===i)continue;const e=this._labelPos(s,this._space);t.push([e.x,e.y])}return t}for(const i of e.rooms){const e=hi(i);if(e)for(const i of e)t.push(i)}if("draw"===this._tool)for(const e of this._path)t.push(e);if("split"===this._tool&&this._splitSel?.pts)for(const e of this._splitSel.pts)t.push(e);return t}if("devices"===this._mode){for(const e of this._devices){if(e.space!==this._space||e.id===this._drag?.id||"ha_disabled"===e.bindingStatus?.kind)continue;const i=this._pos(e);t.push([i.x,i.y])}return t}if("decor"===this._mode){const e=this._decorMove?.id;return t.push(...this._decorSnapGeometry(e).points),this._decorDraft&&t.push(this._decorDraft.a),t}return t}_renderAlignGuides(){const t=this._alignPoint;if(!t)return j``;const e=this._drag?.id.startsWith("rl_")?.5*this._gridPitch:.05*this._gridPitch,i=function(t,e,i){let s=null,n=null;for(const o of e)if(!(Math.abs(o[0]-t[0])<1e-6&&Math.abs(o[1]-t[1])<1e-6)){if(Math.abs(o[0]-t[0])<=i){const e=Math.abs(o[1]-t[1]);e>1e-6&&(!s||e1e-6&&(!n||e + ${this._fmtLen(e,i)} · ${a}°`}get _decorMeasure(){const t=this._decorDraft;if(!t||"decor"!==this._mode)return null;const[e,i]=t.a,[s,n]=t.b;if(Math.abs(e-s)<1e-6&&Math.abs(i-n)<1e-6)return null;const o=(e+s)/2,a=(i+n)/2;if("line"===t.kind){const e=Os(t.a,t.b);return{x:o,y:a,on45:Ns(e),text:`${this._fmtLen(t.a,t.b)} · ${Math.round(10*e)/10}°`}}const r=this._fmtLen([e,i],[s,i]),l=this._fmtLen([s,i],[s,n]);if("ellipse"===t.kind){const t=this._fmtLen([0,0],[Math.abs(s-e)/2,0]),r=this._fmtLen([0,0],[0,Math.abs(n-i)/2]);return{x:o,y:a,on45:!1,text:Math.abs(Math.abs(s-e)-Math.abs(n-i))<1e-6?`R ${t}`:`Rx ${t} × Ry ${r}`}}return{x:o,y:a,on45:!1,text:`${r} × ${l} · ${Ia(hr(Math.abs(s-e),this._cellCm,this._gridPitch)*hr(Math.abs(n-i),this._cellCm,this._gridPitch)/1e4,this._imperial)}`}}get _alignPoint(){if(this._markup){if("draw"===this._tool&&this._path.length&&!this._contourClosed&&this._cursorPt)return this._cursorPt;if("split"===this._tool&&this._splitSel?.pts?.length&&this._cursorPt)return this._cursorPt;if(this._drag?.id.startsWith("rl_")&&this._drag.moved){const t=this._drag.id.slice(3),e=this._spaceModel()?.rooms.find(e=>e.id===t);return e?(()=>{const t=this._labelPos(e,this._space);return[t.x,t.y]})():null}return null}if("devices"===this._mode&&this._drag?.moved){const t=this._devices.find(t=>t.id===this._drag.id);return t?(()=>{const e=this._pos(t);return[e.x,e.y]})():null}if("decor"===this._mode){if(this._decorDraft)return this._decorDraft.b;if(this._decorMove){const t=this._decorList.find(t=>t.id===this._decorMove.id);if(!t)return null;const e=Zg,i=this._decorH;return"line"===t.kind?[t.x1*e,t.y1*i]:[t.x*e,t.y*i]}return null}return null}_alignCandidates(){const t=[],e=this._spaceModel();if(this._markup){if(!e)return t;if(this._drag?.id.startsWith("rl_")){const i=this._drag.id.slice(3);for(const s of e.rooms){if(!s.name||s.id===i)continue;const e=this._labelPos(s,this._space);t.push([e.x,e.y])}return t}for(const i of e.rooms){const e=hi(i);if(e)for(const i of e)t.push(i)}if("draw"===this._tool)for(const e of this._path)t.push(e);if("split"===this._tool&&this._splitSel?.pts)for(const e of this._splitSel.pts)t.push(e);return t}if("devices"===this._mode){for(const e of this._devices){if(e.space!==this._space||e.id===this._drag?.id||"ha_disabled"===e.bindingStatus?.kind)continue;const i=this._pos(e);t.push([i.x,i.y])}return t}if("decor"===this._mode){const e=this._decorMove?.id;return t.push(...this._decorSnapGeometry(e).points),this._decorDraft&&t.push(this._decorDraft.a),t}return t}_renderAlignGuides(){const t=this._alignPoint;if(!t)return j``;const e=this._drag?.id.startsWith("rl_")?.5*this._gridPitch:.05*this._gridPitch,i=function(t,e,i){let s=null,n=null;for(const o of e)if(!(Math.abs(o[0]-t[0])<1e-6&&Math.abs(o[1]-t[1])<1e-6)){if(Math.abs(o[0]-t[0])<=i){const e=Math.abs(o[1]-t[1]);e>1e-6&&(!s||e1e-6&&(!n||e ${i.map(e=>{const[i,o,a,r]="x"===e.axis?[e.at,e.from[1],e.at,t[1]+Math.sign(t[1]-e.from[1])*n]:[e.from[0],e.at,t[0]+Math.sign(t[0]-e.from[0])*n,e.at];return j` `})} @@ -6231,7 +6231,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="5ca433d2ee8bf92a41f4597ac53777315a9c `)} - `:Fu(e)} + `:Eu(e)}