diff --git a/custom_components/houseplan/frontend/houseplan-card.js b/custom_components/houseplan/frontend/houseplan-card.js index 95824be3..a08e73f8 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__="67351f8b3fc2bcc5d5432c7156df5bb015c8921aeec392e69d7c511f35bace06";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)},r=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:a,defineProperty:l,getOwnPropertyDescriptor:c,getOwnPropertyNames:h,getOwnPropertySymbols:d,getPrototypeOf:p}=Object,u=globalThis,_=u.trustedTypes,g=_?_.emptyScript:"",m=u.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)=>!a(t,e),b={attribute:!0,type:String,converter:v,reflect:!1,useDefault:!1,hasChanged:y};Symbol.metadata??=Symbol("metadata"),u.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=p(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(r(t))}else void 0!==t&&e.push(r(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}),(u.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?"":"",r=E;for(let e=0;e"===l[0]?(r=n??E,c=-1):void 0===l[1]?c=-2:(c=r.lastIndex-l[2].length,a=l[1],r=void 0===l[3]?N:'"'===l[3]?L:H):r===L||r===H?r=N:r===z||r===O?r=E:(r=N,n=void 0);const d=r===N&&t[e+1].startsWith("/>")?" ":"";o+=r===E?i+T:c>=0?(s.push(a),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 r=t.length-1,a=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())&&a.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 r,a;for(t=n[0],r=0;r{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 pt=2,ut=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=ut(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}=rt,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,r=o!==t;if(r){let e;i._$AQ?.(t),i._$AM=t,void 0!==i._$AP&&(e=t._$AU)!==o._$AU&&i._$AP(e)}if(e!==n||r){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=ut(class extends _t{constructor(t){if(super(t),t.type!==pt)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 r=0;for(const e of t)n[r]=s?s(e,r):r,o[r]=i(e,r),r++;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:r}=this.dt(e,i,s);if(!Array.isArray(n))return this.ut=r,o;const a=this.ut??=[],l=[];let c,h,d=0,p=n.length-1,u=0,_=o.length-1;for(;d<=p&&u<=_;)if(null===n[d])d++;else if(null===n[p])p--;else if(a[d]===r[u])l[u]=wt(n[d],o[u]),d++,u++;else if(a[p]===r[_])l[_]=wt(n[p],o[_]),p--,_--;else if(a[d]===r[_])l[_]=wt(n[d],o[_]),bt(t,l[_+1],n[d]),d++,_--;else if(a[p]===r[u])l[u]=wt(n[p],o[u]),bt(t,n[d],n[p]),p--,u++;else if(void 0===c&&(c=St(r,u,_),h=St(a,d,p)),c.has(a[d]))if(c.has(a[p])){const e=h.get(r[u]),i=void 0!==e?n[e]:null;if(null===i){const e=bt(t,n[d]);wt(e,o[u]),l[u]=e}else l[u]=wt(i,o[u]),bt(t,n[d],i),n[e]=null;u++}else $t(n[p]),p--;else $t(n[d]),d++;for(;u<=_;){const e=bt(t,l[_+1]);wt(e,o[u]),l[u++]=e}for(;d<=p;){const t=n[d++];null!==t&&$t(t)}return this.ut=r,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__="9332b8278ae9e2f3a2e9ab4f07e3bf1b56fe0cb818a0a1c67d41e365ad74da43";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:p}=Object,u=globalThis,_=u.trustedTypes,g=_?_.emptyScript:"",m=u.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"),u.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=p(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}),(u.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 pt=2,ut=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=ut(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=ut(class extends _t{constructor(t){if(super(t),t.type!==pt)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,p=n.length-1,u=0,_=o.length-1;for(;d<=p&&u<=_;)if(null===n[d])d++;else if(null===n[p])p--;else if(r[d]===a[u])l[u]=wt(n[d],o[u]),d++,u++;else if(r[p]===a[_])l[_]=wt(n[p],o[_]),p--,_--;else if(r[d]===a[_])l[_]=wt(n[d],o[_]),bt(t,l[_+1],n[d]),d++,_--;else if(r[p]===a[u])l[u]=wt(n[p],o[u]),bt(t,n[d],n[p]),p--,u++;else if(void 0===c&&(c=St(a,u,_),h=St(r,d,p)),c.has(r[d]))if(c.has(r[p])){const e=h.get(a[u]),i=void 0!==e?n[e]:null;if(null===i){const e=bt(t,n[d]);wt(e,o[u]),l[u]=e}else l[u]=wt(i,o[u]),bt(t,n[d],i),n[e]=null;u++}else $t(n[p]),p--;else $t(n[d]),d++;for(;u<=_;){const e=bt(t,l[_+1]);wt(e,o[u]),l[u++]=e}for(;d<=p;){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`"number"==typeof t&&Number.isFinite(t)))return null;const[i,s,n]=e.map(t=>Math.round(Math.min(255,Math.max(0,t))));return`rgb(${i}, ${s}, ${n})`}const Et=(t,e,i)=>Math.min(i,Math.max(e,Number.isFinite(t)?t:e));function zt(t){return Number.isFinite(t)?(t%360+360)%360:0}function Ot(t){if("string"!=typeof t)return null;const e=t.trim().replace(/^#/,""),i=/^[0-9a-fA-F]{3}$/.test(e)?e.split("").map(t=>`${t}${t}`).join(""):e;return/^[0-9a-fA-F]{6}$/.test(i)?`#${i.toLowerCase()}`:null}function Nt(t){const e=Ot(t);return e?{r:Number.parseInt(e.slice(1,3),16),g:Number.parseInt(e.slice(3,5),16),b:Number.parseInt(e.slice(5,7),16)}:null}function Ht(t){const e=Et(t.r,0,255)/255,i=Et(t.g,0,255)/255,s=Et(t.b,0,255)/255,n=Math.max(e,i,s),o=n-Math.min(e,i,s);let r=0;return o>0&&(r=n===e?(i-s)/o%6*60:n===i?60*((s-e)/o+2):60*((e-i)/o+4)),{h:zt(r),s:0===n?0:o/n*100,v:100*n}}function Lt(t){return function(t){const e=t=>Math.round(Et(t,0,255)).toString(16).padStart(2,"0");return`#${e(t.r)}${e(t.g)}${e(t.b)}`}(function(t){const e=zt(t.h),i=Et(t.s,0,100)/100,s=Et(t.v,0,100)/100,n=s*i,o=n*(1-Math.abs(e/60%2-1)),r=s-n;let a;return a=e<60?[n,o,0]:e<120?[o,n,0]:e<180?[0,n,o]:e<240?[0,o,n]:e<300?[o,0,n]:[n,0,o],{r:Math.round(255*(a[0]+r)),g:Math.round(255*(a[1]+r)),b:Math.round(255*(a[2]+r))}}(t))}function Bt(t){const e=t.visualViewport;return e&&Number.isFinite(e.width)&&Number.isFinite(e.height)?{left:Number(e.offsetLeft)||0,top:Number(e.offsetTop)||0,width:Math.max(0,Number(e.width)||0),height:Math.max(0,Number(e.height)||0)}:{left:0,top:0,width:t.innerWidth,height:t.innerHeight}}function qt(t,e,i,s=7,n=8){const o=i.left+n,r=i.top+n,a=Math.max(o,i.left+i.width-n),l=Math.max(r,i.top+i.height-n),c=Math.max(0,a-o),h=Math.max(0,l-r),d=Math.min(Math.max(0,e.width),c),p=Math.min(Math.max(0,e.height),h);let u=t.left;u+d>a&&(u=t.right-d),u=Math.min(Math.max(o,u),Math.max(o,a-d));const _=t.bottom+s,g=t.top-s-p;let m="bottom",f=_;return _+p>l&&g>=r?(m="top",f=Math.min(Math.max(r,g),Math.max(r,l-p))):f=Math.min(Math.max(r,_),Math.max(r,l-p)),{left:Math.round(u),top:Math.round(f),side:m,maxWidth:Math.round(c),maxHeight:Math.round(h)}}class Wt{constructor(t,e,i){this.owner=t,this.name=e,this.keydown=i,this.host=null,this.root=null}window(){return this.owner.ownerDocument.defaultView}dialog(){return this.owner.closest("hp-dialog")}usesPopover(t=!1){const e=this.window();return!t&&!!e&&function(t){const e=t.HTMLElement?.prototype;return"function"==typeof e?.showPopover&&"function"==typeof e?.hidePopover}(e)}get hasFallback(){return!!this.host}containsPath(t){return t.includes(this.owner)||!!this.host&&t.includes(this.host)}ownsActiveElement(){let t=this.owner.ownerDocument.activeElement;for(;t?.shadowRoot?.activeElement;)t=t.shadowRoot.activeElement;return!(!t||t!==this.owner&&!this.owner.shadowRoot?.contains(t)&&!this.root?.contains(t))}renderFallback(t,e){const i=this.ensureFallback();return i?(lt(W`${t}`,i),i):null}surface(t,e){return e?this.owner.shadowRoot?.querySelector(t)||null:this.root?.querySelector(t)||null}destroy(){this.root&<(G,this.root),this.host?.remove(),this.host=null,this.root=null}ensureFallback(){if(this.root?.isConnected)return this.root;const t=this.dialog()?.overlayPortal()||this.owner.ownerDocument.body;if(!t)return null;const e=this.owner.ownerDocument.createElement("div");return e.dataset.hpOverlay=this.name,e.style.display="contents",this.keydown&&e.addEventListener("keydown",this.keydown,!0),t.append(e),this.host=e,this.root=e.attachShadow({mode:"open"}),this.root}}const jt={title:"Color picker",hue:"Hue",saturation:"Saturation",value:"Brightness",hex:"Hex color",invalidHex:"Enter a 3- or 6-digit hex color"};class Ut extends ht{constructor(){super(...arguments),this.label="",this.opacityLabel="Opacity",this.color="#607d8b",this.opacity=1,this.disabled=!1,this.showOpacity=!0,this.pickerLabels=jt,this._open=!1,this._pickerRaf=0,this._emitRaf=0,this._forceFallback=!1,this._overlayDispose=null,this._hue=0,this._saturation=0,this._value=0,this._hexDraft="#607d8b",this._hexInvalid=!1,this._lastValidColor="#607d8b",this._activePointerId=null,this._outsidePointerDown=t=>{if(!this._open)return;const e=t.composedPath();this._floating.containsPath(e)||this._closePicker(!1,"outside")},this._keyDown=t=>{this._open&&"Escape"===t.key&&(t.preventDefault(),t.stopImmediatePropagation(),this._closePicker(this._floating.ownsActiveElement(),"escape"))},this._floating=new Wt(this,"color-opacity",this._keyDown),this._queuePickerPosition=()=>{if(!this._open)return;this._pickerRaf&&cancelAnimationFrame(this._pickerRaf);const t=this._window();t&&(this._pickerRaf=t.requestAnimationFrame(()=>{this._pickerRaf=0,this._positionPicker()||this._closePicker()}))}}connectedCallback(){super.connectedCallback(),this._syncFromColor(this.color,!1),this.ownerDocument.addEventListener("pointerdown",this._outsidePointerDown,!0),this.ownerDocument.addEventListener("scroll",this._queuePickerPosition,!0);const t=this.ownerDocument.defaultView;t?.addEventListener("resize",this._queuePickerPosition),t?.addEventListener("orientationchange",this._queuePickerPosition),t?.visualViewport?.addEventListener("resize",this._queuePickerPosition),t?.visualViewport?.addEventListener("scroll",this._queuePickerPosition),this.addEventListener("keydown",this._keyDown,!0)}disconnectedCallback(){this.ownerDocument.removeEventListener("pointerdown",this._outsidePointerDown,!0),this.ownerDocument.removeEventListener("scroll",this._queuePickerPosition,!0);const t=this.ownerDocument.defaultView;t?.removeEventListener("resize",this._queuePickerPosition),t?.removeEventListener("orientationchange",this._queuePickerPosition),t?.visualViewport?.removeEventListener("resize",this._queuePickerPosition),t?.visualViewport?.removeEventListener("scroll",this._queuePickerPosition),this.removeEventListener("keydown",this._keyDown,!0),this._pickerRaf&&cancelAnimationFrame(this._pickerRaf),this._emitRaf&&cancelAnimationFrame(this._emitRaf),this._pickerRaf=0,this._emitRaf=0,this._closePicker(!1,"disconnect"),super.disconnectedCallback()}updated(t){if(t.has("color")){const t=Ot(this.color);t&&t!==this._lastValidColor&&this._syncFromColor(t,this._open)}this.disabled&&this._open?this._closePicker():this._open&&(this._supportsPopover()||this._renderFallback(),(t.has("color")||t.has("opacity")||t.has("showOpacity")||t.has("label")||t.has("opacityLabel")||t.has("pickerLabels"))&&this._queuePickerPosition())}_window(){return this._floating.window()}_supportsPopover(){return this._floating.usesPopover(this._forceFallback)}_dialog(){return this._floating.dialog()}async _toggle(){this.disabled||(this._open?this._closePicker():(this._forceFallback=!1,this._syncFromColor(this.color,!1),this._hexInvalid=!1,this._activePointerId=null,this._open=!0,await this.updateComplete,this._open&&(this._supportsPopover()||this._renderFallback(),this._positionPicker()?this._overlayDispose=this._dialog()?.registerOverlay({owner:this,group:"transient",close:t=>this._closePicker("escape"===t&&this._floating.ownsActiveElement(),t)})||null:this._closePicker())))}_closePicker(t=!1,e="exclusive"){if(!this._open&&!this._floating.hasFallback)return;const i=this._overlayDispose;this._overlayDispose=null,i?.();const s=this.renderRoot.querySelector(".picker");if(s?.hidePopover)try{s.matches(":popover-open")&&s.hidePopover()}catch{}this._open=!1,this._cancelQueuedEmit(),this._activePointerId=null,this._floating.destroy(),t&&this.updateComplete.then(()=>this.renderRoot.querySelector(".trigger")?.focus())}_surface(){return this._floating.surface(".picker",this._supportsPopover())}_renderFallback(){const t=Ut.styles.cssText;this._floating.renderFallback(this._pickerTemplate(!1),t)}_positionPicker(){if(!this._open)return!1;const t=this._window(),e=this.renderRoot.querySelector(".trigger");let i=this._surface();if(!t||!e?.isConnected||!i?.isConnected)return!1;const s=Bt(t);if(i.style.maxWidth=`${Math.max(0,s.width-16)}px`,i.style.maxHeight=`${Math.max(0,s.height-16)}px`,i.style.visibility="hidden",this._supportsPopover()&&i.showPopover)try{i.matches(":popover-open")||i.showPopover()}catch{if(this._forceFallback=!0,this._renderFallback(),i=this._surface(),!i?.isConnected)return!1;i.style.maxWidth=`${Math.max(0,s.width-16)}px`,i.style.maxHeight=`${Math.max(0,s.height-16)}px`,i.style.visibility="hidden"}const n=e.getBoundingClientRect(),o=i.getBoundingClientRect();if(!(n.width&&n.height&&o.width&&o.height))return!1;const r=qt(n,o,s);return i.style.left=`${r.left}px`,i.style.top=`${r.top}px`,i.dataset.side=r.side,i.style.visibility="",!0}_labels(){const t=this.pickerLabels||jt;return{title:t.title||jt.title,hue:t.hue||jt.hue,saturation:t.saturation||jt.saturation,value:t.value||jt.value,hex:t.hex||jt.hex,invalidHex:t.invalidHex||jt.invalidHex}}_syncFromColor(t,e){const i=Ot(Rt(t,"#607d8b"))||"#607d8b",s=Nt(i);if(!s)return;const n=Ht(s);(!e||n.s>1e-4)&&(this._hue=n.h),this._saturation=n.s,this._value=n.v,this._hexDraft=i,this._hexInvalid=!1,this._lastValidColor=i}_cancelQueuedEmit(t=!1){this._emitRaf&&cancelAnimationFrame(this._emitRaf),this._emitRaf=0,t&&this._syncFromColor(this._lastValidColor,!0)}_queueHsvEmit(){if(this._emitRaf)return;const t=this._window();t?this._emitRaf=t.requestAnimationFrame(()=>{this._emitRaf=0,this._emitHsv()}):this._emitHsv()}_emitHsv(){this._emit(Lt({h:this._hue,s:this._saturation,v:this._value}),this.opacity)}_setHue(t){this._hue=Math.min(359,Math.max(0,Number.isFinite(t)?t:0)),this._emitHsv()}_setSaturation(t){this._saturation=Math.min(100,Math.max(0,Number.isFinite(t)?t:0)),this._emitHsv()}_setValue(t){this._value=Math.min(100,Math.max(0,Number.isFinite(t)?t:0)),this._emitHsv()}_setOpacity(t){this._emit(this._lastValidColor,t)}_shiftRangeKey(t,e,i,s,n){if(!t.shiftKey)return;const o="ArrowRight"===t.key||"ArrowUp"===t.key?10:"ArrowLeft"===t.key||"ArrowDown"===t.key?-10:0;o&&(t.preventDefault(),t.stopPropagation(),n(Math.min(s,Math.max(i,e+o))))}_setSvFromPointer(t,e){const i=t.currentTarget.getBoundingClientRect();i.width&&i.height&&(this._saturation=Math.min(100,Math.max(0,(t.clientX-i.left)/i.width*100)),this._value=Math.min(100,Math.max(0,100*(1-(t.clientY-i.top)/i.height))),e?(this._cancelQueuedEmit(),this._emitHsv()):this._queueHsvEmit())}_svPointerDown(t){if(t.preventDefault(),t.stopPropagation(),null===this._activePointerId){this._activePointerId=t.pointerId;try{t.currentTarget.setPointerCapture(t.pointerId)}catch{}this._setSvFromPointer(t,!0)}}_svPointerMove(t){t.pointerId===this._activePointerId&&(t.preventDefault(),t.stopPropagation(),this._setSvFromPointer(t,!1))}_svPointerUp(t){if(t.pointerId===this._activePointerId){t.preventDefault(),t.stopPropagation(),this._setSvFromPointer(t,!0),this._activePointerId=null;try{t.currentTarget.releasePointerCapture(t.pointerId)}catch{}}}_svPointerCancel(t){t.pointerId===this._activePointerId&&(t.preventDefault(),t.stopPropagation(),this._activePointerId=null,this._cancelQueuedEmit(!0))}_svLostPointerCapture(t){t.pointerId===this._activePointerId&&(this._activePointerId=null,this._cancelQueuedEmit(!0))}_hexInput(t){const e=t.target.value;this._hexDraft=e,this._hexInvalid=!1;const i=Ot(e),s=i?Nt(i):null;if(!i||!s)return;const n=Ht(s);n.s>1e-4&&(this._hue=n.h),this._saturation=n.s,this._value=n.v,this._emit(i,this.opacity,!0)}_commitHex(){const t=Ot(this._hexDraft);if(!t)return this._hexDraft=this._lastValidColor,void(this._hexInvalid=!0);this._hexDraft=t,this._hexInvalid=!1,t!==this._lastValidColor&&this._emit(t,this.opacity)}_hexKeyDown(t){"Enter"===t.key&&(t.preventDefault(),t.stopPropagation(),this._commitHex())}_emit(t,e,i=!1){const s=Ot(t)||this._lastValidColor,n=Number.isFinite(e)?e:Number(this.opacity)||0,o=Math.min(1,Math.max(0,n));this.color=s,this.opacity=o,this._lastValidColor=s,i||(this._hexDraft=s),this._hexInvalid=!1,this.dispatchEvent(new CustomEvent("hp-color-opacity-change",{detail:{color:s,opacity:o},bubbles:!0,composed:!0}))}_pickerTemplate(t){const e=Math.round(100*Math.min(1,Math.max(0,Number(this.opacity)||0))),i=Lt({h:this._hue,s:this._saturation,v:this._value}),s=Lt({h:this._hue,s:100,v:100}),n=this._labels(),o=Math.round(this._hue),r=Math.round(this._saturation),a=Math.round(this._value);return W` + `,customElements.get("hp-dialog")||customElements.define("hp-dialog",Tt);const Pt=/^#[0-9a-fA-F]{6}$/;function Rt(t,e){return"string"==typeof t&&Pt.test(t)?t:e}const It="(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])",At=new RegExp(`^rgb\\(${It}, ${It}, ${It}\\)$`);function Ft(t){if(!Array.isArray(t)||t.length<3)return null;const e=t.slice(0,3);if(!e.every(t=>"number"==typeof t&&Number.isFinite(t)))return null;const[i,s,n]=e.map(t=>Math.round(Math.min(255,Math.max(0,t))));return`rgb(${i}, ${s}, ${n})`}const Et=(t,e,i)=>Math.min(i,Math.max(e,Number.isFinite(t)?t:e));function zt(t){return Number.isFinite(t)?(t%360+360)%360:0}function Ot(t){if("string"!=typeof t)return null;const e=t.trim().replace(/^#/,""),i=/^[0-9a-fA-F]{3}$/.test(e)?e.split("").map(t=>`${t}${t}`).join(""):e;return/^[0-9a-fA-F]{6}$/.test(i)?`#${i.toLowerCase()}`:null}function Nt(t){const e=Ot(t);return e?{r:Number.parseInt(e.slice(1,3),16),g:Number.parseInt(e.slice(3,5),16),b:Number.parseInt(e.slice(5,7),16)}:null}function Ht(t){const e=Et(t.r,0,255)/255,i=Et(t.g,0,255)/255,s=Et(t.b,0,255)/255,n=Math.max(e,i,s),o=n-Math.min(e,i,s);let a=0;return o>0&&(a=n===e?(i-s)/o%6*60:n===i?60*((s-e)/o+2):60*((e-i)/o+4)),{h:zt(a),s:0===n?0:o/n*100,v:100*n}}function Lt(t){return function(t){const e=t=>Math.round(Et(t,0,255)).toString(16).padStart(2,"0");return`#${e(t.r)}${e(t.g)}${e(t.b)}`}(function(t){const e=zt(t.h),i=Et(t.s,0,100)/100,s=Et(t.v,0,100)/100,n=s*i,o=n*(1-Math.abs(e/60%2-1)),a=s-n;let r;return r=e<60?[n,o,0]:e<120?[o,n,0]:e<180?[0,n,o]:e<240?[0,o,n]:e<300?[o,0,n]:[n,0,o],{r:Math.round(255*(r[0]+a)),g:Math.round(255*(r[1]+a)),b:Math.round(255*(r[2]+a))}}(t))}function Bt(t){const e=t.visualViewport;return e&&Number.isFinite(e.width)&&Number.isFinite(e.height)?{left:Number(e.offsetLeft)||0,top:Number(e.offsetTop)||0,width:Math.max(0,Number(e.width)||0),height:Math.max(0,Number(e.height)||0)}:{left:0,top:0,width:t.innerWidth,height:t.innerHeight}}function qt(t,e,i,s=7,n=8){const o=i.left+n,a=i.top+n,r=Math.max(o,i.left+i.width-n),l=Math.max(a,i.top+i.height-n),c=Math.max(0,r-o),h=Math.max(0,l-a),d=Math.min(Math.max(0,e.width),c),p=Math.min(Math.max(0,e.height),h);let u=t.left;u+d>r&&(u=t.right-d),u=Math.min(Math.max(o,u),Math.max(o,r-d));const _=t.bottom+s,g=t.top-s-p;let m="bottom",f=_;return _+p>l&&g>=a?(m="top",f=Math.min(Math.max(a,g),Math.max(a,l-p))):f=Math.min(Math.max(a,_),Math.max(a,l-p)),{left:Math.round(u),top:Math.round(f),side:m,maxWidth:Math.round(c),maxHeight:Math.round(h)}}class Wt{constructor(t,e,i){this.owner=t,this.name=e,this.keydown=i,this.host=null,this.root=null}window(){return this.owner.ownerDocument.defaultView}dialog(){return this.owner.closest("hp-dialog")}usesPopover(t=!1){const e=this.window();return!t&&!!e&&function(t){const e=t.HTMLElement?.prototype;return"function"==typeof e?.showPopover&&"function"==typeof e?.hidePopover}(e)}get hasFallback(){return!!this.host}containsPath(t){return t.includes(this.owner)||!!this.host&&t.includes(this.host)}ownsActiveElement(){let t=this.owner.ownerDocument.activeElement;for(;t?.shadowRoot?.activeElement;)t=t.shadowRoot.activeElement;return!(!t||t!==this.owner&&!this.owner.shadowRoot?.contains(t)&&!this.root?.contains(t))}renderFallback(t,e){const i=this.ensureFallback();return i?(lt(W`${t}`,i),i):null}surface(t,e){return e?this.owner.shadowRoot?.querySelector(t)||null:this.root?.querySelector(t)||null}destroy(){this.root&<(G,this.root),this.host?.remove(),this.host=null,this.root=null}ensureFallback(){if(this.root?.isConnected)return this.root;const t=this.dialog()?.overlayPortal()||this.owner.ownerDocument.body;if(!t)return null;const e=this.owner.ownerDocument.createElement("div");return e.dataset.hpOverlay=this.name,e.style.display="contents",this.keydown&&e.addEventListener("keydown",this.keydown,!0),t.append(e),this.host=e,this.root=e.attachShadow({mode:"open"}),this.root}}const jt={title:"Color picker",hue:"Hue",saturation:"Saturation",value:"Brightness",hex:"Hex color",invalidHex:"Enter a 3- or 6-digit hex color"};class Ut extends ht{constructor(){super(...arguments),this.label="",this.opacityLabel="Opacity",this.color="#607d8b",this.opacity=1,this.disabled=!1,this.showOpacity=!0,this.pickerLabels=jt,this._open=!1,this._pickerRaf=0,this._emitRaf=0,this._forceFallback=!1,this._overlayDispose=null,this._hue=0,this._saturation=0,this._value=0,this._hexDraft="#607d8b",this._hexInvalid=!1,this._lastValidColor="#607d8b",this._activePointerId=null,this._outsidePointerDown=t=>{if(!this._open)return;const e=t.composedPath();this._floating.containsPath(e)||this._closePicker(!1,"outside")},this._keyDown=t=>{this._open&&"Escape"===t.key&&(t.preventDefault(),t.stopImmediatePropagation(),this._closePicker(this._floating.ownsActiveElement(),"escape"))},this._floating=new Wt(this,"color-opacity",this._keyDown),this._queuePickerPosition=()=>{if(!this._open)return;this._pickerRaf&&cancelAnimationFrame(this._pickerRaf);const t=this._window();t&&(this._pickerRaf=t.requestAnimationFrame(()=>{this._pickerRaf=0,this._positionPicker()||this._closePicker()}))}}connectedCallback(){super.connectedCallback(),this._syncFromColor(this.color,!1),this.ownerDocument.addEventListener("pointerdown",this._outsidePointerDown,!0),this.ownerDocument.addEventListener("scroll",this._queuePickerPosition,!0);const t=this.ownerDocument.defaultView;t?.addEventListener("resize",this._queuePickerPosition),t?.addEventListener("orientationchange",this._queuePickerPosition),t?.visualViewport?.addEventListener("resize",this._queuePickerPosition),t?.visualViewport?.addEventListener("scroll",this._queuePickerPosition),this.addEventListener("keydown",this._keyDown,!0)}disconnectedCallback(){this.ownerDocument.removeEventListener("pointerdown",this._outsidePointerDown,!0),this.ownerDocument.removeEventListener("scroll",this._queuePickerPosition,!0);const t=this.ownerDocument.defaultView;t?.removeEventListener("resize",this._queuePickerPosition),t?.removeEventListener("orientationchange",this._queuePickerPosition),t?.visualViewport?.removeEventListener("resize",this._queuePickerPosition),t?.visualViewport?.removeEventListener("scroll",this._queuePickerPosition),this.removeEventListener("keydown",this._keyDown,!0),this._pickerRaf&&cancelAnimationFrame(this._pickerRaf),this._emitRaf&&cancelAnimationFrame(this._emitRaf),this._pickerRaf=0,this._emitRaf=0,this._closePicker(!1,"disconnect"),super.disconnectedCallback()}updated(t){if(t.has("color")){const t=Ot(this.color);t&&t!==this._lastValidColor&&this._syncFromColor(t,this._open)}this.disabled&&this._open?this._closePicker():this._open&&(this._supportsPopover()||this._renderFallback(),(t.has("color")||t.has("opacity")||t.has("showOpacity")||t.has("label")||t.has("opacityLabel")||t.has("pickerLabels"))&&this._queuePickerPosition())}_window(){return this._floating.window()}_supportsPopover(){return this._floating.usesPopover(this._forceFallback)}_dialog(){return this._floating.dialog()}async _toggle(){this.disabled||(this._open?this._closePicker():(this._forceFallback=!1,this._syncFromColor(this.color,!1),this._hexInvalid=!1,this._activePointerId=null,this._open=!0,await this.updateComplete,this._open&&(this._supportsPopover()||this._renderFallback(),this._positionPicker()?this._overlayDispose=this._dialog()?.registerOverlay({owner:this,group:"transient",close:t=>this._closePicker("escape"===t&&this._floating.ownsActiveElement(),t)})||null:this._closePicker())))}_closePicker(t=!1,e="exclusive"){if(!this._open&&!this._floating.hasFallback)return;const i=this._overlayDispose;this._overlayDispose=null,i?.();const s=this.renderRoot.querySelector(".picker");if(s?.hidePopover)try{s.matches(":popover-open")&&s.hidePopover()}catch{}this._open=!1,this._cancelQueuedEmit(),this._activePointerId=null,this._floating.destroy(),t&&this.updateComplete.then(()=>this.renderRoot.querySelector(".trigger")?.focus())}_surface(){return this._floating.surface(".picker",this._supportsPopover())}_renderFallback(){const t=Ut.styles.cssText;this._floating.renderFallback(this._pickerTemplate(!1),t)}_positionPicker(){if(!this._open)return!1;const t=this._window(),e=this.renderRoot.querySelector(".trigger");let i=this._surface();if(!t||!e?.isConnected||!i?.isConnected)return!1;const s=Bt(t);if(i.style.maxWidth=`${Math.max(0,s.width-16)}px`,i.style.maxHeight=`${Math.max(0,s.height-16)}px`,i.style.visibility="hidden",this._supportsPopover()&&i.showPopover)try{i.matches(":popover-open")||i.showPopover()}catch{if(this._forceFallback=!0,this._renderFallback(),i=this._surface(),!i?.isConnected)return!1;i.style.maxWidth=`${Math.max(0,s.width-16)}px`,i.style.maxHeight=`${Math.max(0,s.height-16)}px`,i.style.visibility="hidden"}const n=e.getBoundingClientRect(),o=i.getBoundingClientRect();if(!(n.width&&n.height&&o.width&&o.height))return!1;const a=qt(n,o,s);return i.style.left=`${a.left}px`,i.style.top=`${a.top}px`,i.dataset.side=a.side,i.style.visibility="",!0}_labels(){const t=this.pickerLabels||jt;return{title:t.title||jt.title,hue:t.hue||jt.hue,saturation:t.saturation||jt.saturation,value:t.value||jt.value,hex:t.hex||jt.hex,invalidHex:t.invalidHex||jt.invalidHex}}_syncFromColor(t,e){const i=Ot(Rt(t,"#607d8b"))||"#607d8b",s=Nt(i);if(!s)return;const n=Ht(s);(!e||n.s>1e-4)&&(this._hue=n.h),this._saturation=n.s,this._value=n.v,this._hexDraft=i,this._hexInvalid=!1,this._lastValidColor=i}_cancelQueuedEmit(t=!1){this._emitRaf&&cancelAnimationFrame(this._emitRaf),this._emitRaf=0,t&&this._syncFromColor(this._lastValidColor,!0)}_queueHsvEmit(){if(this._emitRaf)return;const t=this._window();t?this._emitRaf=t.requestAnimationFrame(()=>{this._emitRaf=0,this._emitHsv()}):this._emitHsv()}_emitHsv(){this._emit(Lt({h:this._hue,s:this._saturation,v:this._value}),this.opacity)}_setHue(t){this._hue=Math.min(359,Math.max(0,Number.isFinite(t)?t:0)),this._emitHsv()}_setSaturation(t){this._saturation=Math.min(100,Math.max(0,Number.isFinite(t)?t:0)),this._emitHsv()}_setValue(t){this._value=Math.min(100,Math.max(0,Number.isFinite(t)?t:0)),this._emitHsv()}_setOpacity(t){this._emit(this._lastValidColor,t)}_shiftRangeKey(t,e,i,s,n){if(!t.shiftKey)return;const o="ArrowRight"===t.key||"ArrowUp"===t.key?10:"ArrowLeft"===t.key||"ArrowDown"===t.key?-10:0;o&&(t.preventDefault(),t.stopPropagation(),n(Math.min(s,Math.max(i,e+o))))}_setSvFromPointer(t,e){const i=t.currentTarget.getBoundingClientRect();i.width&&i.height&&(this._saturation=Math.min(100,Math.max(0,(t.clientX-i.left)/i.width*100)),this._value=Math.min(100,Math.max(0,100*(1-(t.clientY-i.top)/i.height))),e?(this._cancelQueuedEmit(),this._emitHsv()):this._queueHsvEmit())}_svPointerDown(t){if(t.preventDefault(),t.stopPropagation(),null===this._activePointerId){this._activePointerId=t.pointerId;try{t.currentTarget.setPointerCapture(t.pointerId)}catch{}this._setSvFromPointer(t,!0)}}_svPointerMove(t){t.pointerId===this._activePointerId&&(t.preventDefault(),t.stopPropagation(),this._setSvFromPointer(t,!1))}_svPointerUp(t){if(t.pointerId===this._activePointerId){t.preventDefault(),t.stopPropagation(),this._setSvFromPointer(t,!0),this._activePointerId=null;try{t.currentTarget.releasePointerCapture(t.pointerId)}catch{}}}_svPointerCancel(t){t.pointerId===this._activePointerId&&(t.preventDefault(),t.stopPropagation(),this._activePointerId=null,this._cancelQueuedEmit(!0))}_svLostPointerCapture(t){t.pointerId===this._activePointerId&&(this._activePointerId=null,this._cancelQueuedEmit(!0))}_hexInput(t){const e=t.target.value;this._hexDraft=e,this._hexInvalid=!1;const i=Ot(e),s=i?Nt(i):null;if(!i||!s)return;const n=Ht(s);n.s>1e-4&&(this._hue=n.h),this._saturation=n.s,this._value=n.v,this._emit(i,this.opacity,!0)}_commitHex(){const t=Ot(this._hexDraft);if(!t)return this._hexDraft=this._lastValidColor,void(this._hexInvalid=!0);this._hexDraft=t,this._hexInvalid=!1,t!==this._lastValidColor&&this._emit(t,this.opacity)}_hexKeyDown(t){"Enter"===t.key&&(t.preventDefault(),t.stopPropagation(),this._commitHex())}_emit(t,e,i=!1){const s=Ot(t)||this._lastValidColor,n=Number.isFinite(e)?e:Number(this.opacity)||0,o=Math.min(1,Math.max(0,n));this.color=s,this.opacity=o,this._lastValidColor=s,i||(this._hexDraft=s),this._hexInvalid=!1,this.dispatchEvent(new CustomEvent("hp-color-opacity-change",{detail:{color:s,opacity:o},bubbles:!0,composed:!0}))}_pickerTemplate(t){const e=Math.round(100*Math.min(1,Math.max(0,Number(this.opacity)||0))),i=Lt({h:this._hue,s:this._saturation,v:this._value}),s=Lt({h:this._hue,s:100,v:100}),n=this._labels(),o=Math.round(this._hue),a=Math.round(this._saturation),r=Math.round(this._value);return W` `:G} - `}}hr.properties={hass:{attribute:!1},presentation:{attribute:!1},registry:{attribute:!1},deviceName:{attribute:!1}},hr.styles=[Kt,o` + `}}ha.properties={hass:{attribute:!1},presentation:{attribute:!1},registry:{attribute:!1},deviceName:{attribute:!1}},ha.styles=[Kt,o` :host { display: block; min-width: 0; } .devicepreview { margin: 4px 0 14px; @@ -4436,14 +4436,14 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8 .previewstage { min-height: 142px; } .previewfacts > div { grid-template-columns: minmax(0, 1fr); gap: 2px; } } - `],customElements.get("hp-device-preview")||customElements.define("hp-device-preview",hr);const dr=(t,e)=>[t[0]-e[0],t[1]-e[1]],pr=(t,e)=>[t[0]+e[0],t[1]+e[1]],ur=(t,e)=>t[0]*e[0]+t[1]*e[1],_r=t=>Math.hypot(t[0],t[1]);function gr(t){let e=0;for(let i=0;it[1]!=l>t[1]&&t[0]<(a-o)*(t[1]-r)/(l-r)+o&&(i=!i)}return i}([a[0]+r[0]*l,a[1]+r[1]*l],t)&&(r=[-r[0],-r[1]]),r}function vr(t,e,i,s){const n=s||fr(t,e),o=(e+1)%t.length;return t.map((t,s)=>s===e||s===o?[t[0]+n[0]*i,t[1]+n[1]*i]:[...t])}function yr(t,e,i,s){const n=[],o=dr(i,e),r=_r(o);if(rs||h>s)continue;const d=ur(dr(o,e),a),p=ur(dr(l,e),a),u=Math.max(0,Math.min(d,p)),_=Math.min(r,Math.max(d,p));_-u>s&&n.push([[e[0]+a[0]*u,e[1]+a[1]*u],[e[0]+a[0]*_,e[1]+a[1]*_]])}return n}function br(t,e,i,s,n){const o=yr(t,e,i,n);if(!o.length)return null;const r=t=>o.some(([e,i])=>mr(t,e,i)<=n),a=t.length,l=[];for(let o=0;on||f>n)continue;const v=ur(dr(e,c),u),y=ur(dr(i,c),u),b=Math.max(0,Math.min(v,y)),w=Math.min(p,Math.max(v,y));if(!(w-b<=n)){if(b>n&&bn&&w_r(dr(i,t[(s+1)%t.length]))>e);for(let t=0;t<2;t++)i=i.filter((t,s)=>{const n=i[(s-1+i.length)%i.length],o=i[(s+1)%i.length],r=(t[0]-n[0])*(o[1]-n[1])-(t[1]-n[1])*(o[0]-n[0]),a=_r(dr(o,n))||1;return Math.abs(r)/a>e});return i.length>=3?i:t}function kr(t){const e=t.length;if(e<3)return!1;for(let i=0;i(t[0]-n[0])*a[1]-(t[1]-n[1])*a[0],c=t=>(t[0]-n[0])*a[0]+(t[1]-n[1])*a[1],h=i,d=r-i;for(const e of t){const t=Math.abs(l(e));if(t<=i)continue;const n=c(e);n<=h||n>=d||tMath.abs(r+(t-p)/m*(a-r));s=Math.min(s,f(_),f(g))}}return s}function $r(t,e,i){if(Di(t,e,i))return!0;if(Ci(t,e,i)||Ci(e,t,i))return!1;let s=0;try{const i=ni([[...t.map(t=>[t[0],t[1]]),[t[0][0],t[0][1]]]],[[...e.map(t=>[t[0],t[1]]),[e[0][0],e[0][1]]]]);for(const t of i)t?.[0]&&(s+=Pi(t[0]))}catch{return!1}return s>Math.max(1e-7,i*i)}function Sr(t,e,i,s,n){const o=[i.n[0]*s,i.n[1]*s],r={polys:{},openings:{},movedSpans:{}};if(Math.abs(s)<1e-9)return r;for(const e of t){if(e.id===i.roomId){r.polys[e.id]=vr(e.poly,i.edge,s,i.n),r.movedSpans[e.id]=[[pr(i.a,o),pr(i.b,o)]];continue}const t=yr(e.poly,i.a,i.b,n);if(!t.length)continue;const a=br(e.poly,i.a,i.b,o,n);a&&(r.polys[e.id]=a,r.movedSpans[e.id]=t.map(([t,e])=>[pr(t,o),pr(e,o)]))}for(const t of e)mr([t.x,t.y],i.a,i.b)<=n&&(r.openings[t.id]=[t.x+o[0],t.y+o[1]]);return r}function Mr(t,e,i){for(const s of e)for(let e=0;ei)continue;const c=(t.x-n[0])*l[0]+(t.y-n[1])*l[1];if(c-t.length/2>=-i&&c+t.length/2<=a+i)return!0}return!1}function Cr(t,e,i){return t.filter(t=>e.some(e=>{for(let s=0;sa.polys[t.id]||t.poly;for(const e of l){const s=t.find(t=>t.id===e),n=a.polys[e];if(!kr(n))return!1;const l=gr(s.poly),h=gr(n);if(Math.abs(h)t.find(t=>t.id===e).poly),d=t.map(c);for(const t of Cr(e,h,2*r)){const e=a.openings[t.id];if(!Mr(e?{...t,x:e[0],y:e[1]}:t,d,2*r))return!1}return!0}function Tr(t,e,i,s,n,o){const r=t=>[s[0]+(t[0]-s[0])*n,s[1]+(t[1]-s[1])*n],a={poly:t.poly.map(r),openings:{}};for(const s of e){let e=!1;for(let i=0;i{for(let e=0;et.id===i);if(!l)return!1;const c=t.filter(t=>t.id!==i).map(t=>t.poly),h=Tr(l,e,c,s,n,2*a),d=h.poly,p=function(t){const e=function(t){const e=[...t].sort((t,e)=>t[0]-e[0]||t[1]-e[1]);if(e.length<3)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.pop(),n.pop(),s.concat(n)}(t);if(e.length<3)return 0;let i=1/0;for(let t=0;tt.id===i?d:t.poly);for(const t of Cr(e,[l.poly],2*a)){const e=h.openings[t.id];if(!Mr(e?{...t,x:e[0],y:e[1]}:t,u,2*a))return!1}return!0}function Rr(t,e,i){const s=i/e;return Pi(t)*s*s/1e4}function Ir(t,e){return e?`${Math.round(10.7639*t)} ft²`:`${(Math.round(10*t)/10).toFixed(1)} m²`}function Ar(t){const e=t%360;return e<0?e+360:e}function Fr(t,e){const i=function(t,e){return Ar(t+e)}(t,e)*Math.PI/180;return[Math.sin(i),-Math.cos(i)]}const Er=Object.freeze({dawn:Object.freeze({top:"#aabdd1",bottom:"#e8c8b7",horizon:"rgba(255,201,156,.56)",sun:"rgba(255,188,125,.78)",vignette:"rgba(65,72,99,.21)",outlineNear:"rgba(74,57,61,.25)",outlineMid:"rgba(255,238,224,.40)",outlineFar:"rgba(255,224,202,.18)"}),day:Object.freeze({top:"#dce9ef",bottom:"#cbdce3",horizon:"rgba(255,245,220,.45)",sun:"rgba(255,239,190,.72)",vignette:"rgba(65,91,105,.16)",outlineNear:"rgba(45,62,71,.28)",outlineMid:"rgba(255,255,255,.42)",outlineFar:"rgba(255,255,255,.20)"}),dusk:Object.freeze({top:"#48536c",bottom:"#9a7380",horizon:"rgba(242,156,114,.34)",sun:"rgba(255,167,113,.55)",vignette:"rgba(20,26,44,.39)",outlineNear:"rgba(238,219,225,.40)",outlineMid:"rgba(229,207,218,.26)",outlineFar:"rgba(215,190,205,.12)"}),night:Object.freeze({top:"#111a27",bottom:"#1f2f3e",horizon:"rgba(79,120,151,.16)",sun:"rgba(169,208,231,0)",vignette:"rgba(3,8,14,.58)",outlineNear:"rgba(218,238,249,.56)",outlineMid:"rgba(174,215,238,.30)",outlineFar:"rgba(136,194,226,.14)"})}),zr=t=>"number"==typeof t&&Number.isFinite(t),Or=(t,e,i)=>Math.min(i,Math.max(e,t));function Nr(t){return t.elevation<=-6?"night":t.elevation>=6?"day":t.rising?"dawn":"dusk"}function Hr(t){const e=(Math.floor(Number(t)||0)%1440+1440)%1440;return e>=300&&e<480?"dawn":e>=480&&e<1080?"day":e>=1080&&e<1260?"dusk":"night"}function Lr(t){const e=Nr(t),i=t.azimuth*Math.PI/180;return{sunX:50-42*Math.sin(i),sunY:78-Or(t.elevation,0,90)/90*64,sunOpacity:"night"===e?0:Or((t.elevation+6)/12,0,1)}}function Br(t){const e=(Math.floor(Number(t)||0)%1440+1440)%1440;if(e<300||e>=1260)return{sunX:50,sunY:78,sunOpacity:0};const i=(e-300)/960,s=(e-300)/120,n=(1260-e)/120;return{sunX:8+84*i,sunY:78-64*Math.sin(i*Math.PI),sunOpacity:Math.max(.18,Math.min(s,n,1))}}function qr(t,e=new Date){const i=function(t){const e=t?.states?.["sun.sun"]?.attributes;return e&&zr(e.azimuth)&&zr(e.elevation)&&"boolean"==typeof e.rising?{azimuth:Ar(e.azimuth),elevation:e.elevation,rising:e.rising}:null}(t);if(i)return{phase:Nr(i),source:"sun",...Lr(i)};const s="number"==typeof e?e:function(t=new Date){return 60*t.getHours()+t.getMinutes()}(e);return{phase:Hr(s),source:"clock",...Br(s)}}function Wr(t){return`${t.source}|${t.phase}|${t.sunX.toFixed(2)}|${t.sunY.toFixed(2)}|`+t.sunOpacity.toFixed(3)}const jr=[[-90,"#070c14"],[-12,"#070c14"],[-4,"#131a28"],[0,"#4a3527"],[10,"#e8ddcf"],[30,"#ffffff"],[90,"#ffffff"]],Ur=t=>Math.min(1,Math.max(0,t));function Gr(t,e,i=6){const s=t.angle*Math.PI/180,n=[Math.sin(s),-Math.cos(s)],o=s=>{const o=[t.x+n[0]*i*s,t.y+n[1]*i*s];return e.find(t=>t.poly.length>=3&&vi(o,t.poly))||null},r=o(1),a=o(-1);return r&&a?null:r||a?r?{normal:[-n[0],-n[1]],roomId:r.id}:{normal:n,roomId:a.id}:null}function Vr(t,e,i){return i>0&&t[0]*e[0]+t[1]*e[1]>.05}function Kr(t,e,i,s){return[[t[0],t[1]],[e[0],e[1]],[e[0]+i[0]*s,e[1]+i[1]*s],[t[0]+i[0]*s,t[1]+i[1]*s]]}function Yr(t,e){try{const i=ni([[...t.map(t=>[t[0],t[1]]),[t[0][0],t[0][1]]]],[[...e.map(t=>[t[0],t[1]]),[e[0][0],e[0][1]]]]),s=[];for(const t of i){const e=t?.[0];!Array.isArray(e)||e.length<4||s.push(e.slice(0,e.length-1).map(t=>[t[0],t[1]]))}return s}catch{return[]}}function Xr(t,e,i,s,n,o,r){if(!(s>0))return[];const a=Fr(i,n),l=[-a[0],-a[1]],c=function(t){const e=Math.min(90,Math.max(0,t));return.7*(.8+1.7*Math.pow(1-e/90,1.6))}(s),h=[];for(const i of e){if(!(i.length>0))continue;const e=Gr(i,t);if(!e||!Vr(e.normal,a,s))continue;const n=t.find(t=>t.id===e.roomId);if(!n)continue;const d=o&&o[e.roomId]||n.poly,p=i.angle*Math.PI/180,u=i.length/2,_=[-e.normal[0],-e.normal[1]],g=Math.max(0,r?.[i.id]||0),m=i.x+_[0]*g/2,f=i.y+_[1]*g/2,v=Math.cos(p)*u,y=Math.sin(p)*u,b=[m-v,f-y],w=[m+v,f+y],k=c*i.length,x=Yr(Kr(b,w,l,k),d);if(!x.length)continue;const $=l[0]*_[0]+l[1]*_[1];h.push({openingId:i.id,roomId:e.roomId,polys:x,a:b,b:w,dir:l,len:k,normal:_,depth:k*$})}return h}const Jr=t=>"number"==typeof t&&Number.isInteger(t)&&t>=0&&t<=359?t:null;function Zr(t,e){const i=Jr(e?.north_deg);return null!==i?i:Jr(t?.north_deg)}function Qr(t,e){const i=t=>"static"===t||"daynight"===t?t:null;return i(e?.bg_mode)??i(t?.bg_mode)??"static"}function ta(t,e){const i=e?.sun_rays;return"boolean"==typeof i?i:!0===t?.sun_rays}function ea(t){const e=t?.states?.["sun.sun"]?.attributes,i=Number(e?.azimuth),s=Number(e?.elevation);return Number.isFinite(i)&&Number.isFinite(s)?{azimuth:i,elevation:s}:null}const ia=["dawn","day","dusk","night"];function sa(t){if(!t)return"";const e=Er[t.phase];return[`--hp-day-cycle-outline-near:${e.outlineNear}`,`--hp-day-cycle-outline-mid:${e.outlineMid}`,`--hp-day-cycle-outline-far:${e.outlineFar}`].join(";")}function na(t,e=1){if(!t)return G;const i=[`--hp-day-cycle-sun-x:${t.sunX.toFixed(2)}%`,`--hp-day-cycle-sun-y:${t.sunY.toFixed(2)}%`,`--hp-day-cycle-sun-opacity:${t.sunOpacity.toFixed(3)}`,`opacity:${Math.min(1,Math.max(0,e)).toFixed(4)}`].join(";");return W``}houseplanContinuityTrace(){return[...this._continuityHistory,...this._continuity.trace].slice(-80).map(t=>({...t,...t.stage?{stage:[...t.stage]}:{}}))}render(){if(!this._config)return G;const t=this._snap?.config;if(!t)return this._errorCard(la(this._lang,"space_card.loading"));const e=this._config.space,i=this._renderDeviceSnapshot,s=uu({hass:i?.hass||this.hass,cfg:t,layout:this._snap?.layout||{},spaceId:e,iconSize:this._config.icon_size,stageWidth:this._stageWidth,lang:this._lang,displayUrl:t=>this._signer.display(this.hass,t),assetLoaded:this._onAssetLoaded,registry:i?{revision:i.sourceSequence,authoritative:!1,access:"limited",entities:{...i.hass.entities},devices:{...i.hass.devices},lastSuccess:i.capturedAt}:An(this.hass),devices:[...i?.devices||this._devices],presentations:i?.presentations,activityRuntime:this._activityRuntime,reducedMotion:this._reducedMotion,virtualLights:this._snap?.virtualLights,liveStates:!1!==this._config.live_states,showTemperature:!1!==this._config.show_temperature,showSignal:!1!==this._config.show_signal,inert:this._continuity.overlayBlocksInteraction});if(!s)return this._errorCard(la(this._lang,"space_card.not_found",{id:e}));const n=yc(t).find(t=>t.id===e),o=void 0!==this._config.title?this._config.title:n?.title||"",a=!1!==this._config.show_button,r=this._config.button_label||la(this._lang,"space_card.button"),l=this._continuity.overlayVisible||"recovery-error"===this._continuity.state?this._continuity.recoveryReason:null;return W` - + ${a?W`
+
`:G}
- `}}Ru.properties={hass:{attribute:!1},_config:{state:!0},_snap:{state:!0},_continuityEpoch:{state:!0}},Ru.styles=[Kt,o` + `}}Iu.properties={hass:{attribute:!1},_config:{state:!0},_snap:{state:!0},_continuityEpoch:{state:!0}},Iu.styles=[Kt,o` .hp-static-title { font-weight: 700; padding: 10px 14px 6px; @@ -4690,7 +4690,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8 text-align: center; color: var(--secondary-text-color, #9aa4ad); } - `],customElements.get("houseplan-space-card")||customElements.define("houseplan-space-card",Ru),window.customCards=window.customCards||[],window.customCards.find(t=>"houseplan-space-card"===t.type)||window.customCards.push({type:"houseplan-space-card",name:"House Plan — Space (static)",description:"Read-only live schematic of a single houseplan space, with a deep-link button.",preview:!1,documentation:"https://github.com/Matysh/houseplan-card"});const Iu=o` + `],customElements.get("houseplan-space-card")||customElements.define("houseplan-space-card",Iu),window.customCards=window.customCards||[],window.customCards.find(t=>"houseplan-space-card"===t.type)||window.customCards.push({type:"houseplan-space-card",name:"House Plan — Space (static)",description:"Read-only live schematic of a single houseplan space, with a deep-link button.",preview:!1,documentation:"https://github.com/Matysh/houseplan-card"});const Au=o` :host { --hp-editor-tray-bg-fallback: color-mix(in srgb, var(--card-background-color, var(--hp-bg)) 94%, var(--hp-line)); --hp-editor-tray-bg: color-mix(in srgb, var(--card-background-color, var(--hp-bg)) 86%, transparent); @@ -4861,7 +4861,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8 .editor-secondary { transition: none; } .editor-group-launcher .group-chevron { transition: none; } } -`,Au=(t,e)=>(t.composedPath?.()||[t.target]).some(t=>(t=>!!t&&"function"==typeof t.matches)(t)&&e(t));class Fu{constructor(t){this.host=t,this._openGroupId=null,this._groupGeneration=0,this._renderedContext="",this._focusOwned=!1,this._currentModel=null,this._blocked=!1,this._dismissPointerTarget=null,this._globalDismissListening=!1,this._globalDismissGuard=t=>{this.handleOutsideDismiss(t)}}get hasOpenGroup(){return null!==this._openGroupId}get groupGeneration(){return this._groupGeneration}activeGroup(t){return this._openGroupId&&t.find(t=>t.id===this._openGroupId)||null}reset(){this._openGroupId=null,this._contentAnimation?.cancel(),this._contentAnimation=void 0,this._renderedContext="",this._focusOwned=!1,this._currentModel=null,this._blocked=!1,this._dismissPointerTarget=null,clearTimeout(this._dismissTimer),this._dismissTimer=void 0,this._syncGlobalDismissListener()}closeForNavigation(){const t="palette"===this._currentModel?.kind?this._currentModel.dismiss:void 0,e=!!this._openGroupId||!!t;this._openGroupId=null,t?.(),t&&(this._currentModel=null),this._clearDismissClick(),e&&this.host.requestUpdate(),this._syncGlobalDismissListener()}openPalette(){this._openGroupId&&this.closeGroup(!1)}toggleGroup(t,e){this._openGroupId!==e?t.some(t=>t.id===e)&&("palette"===this._currentModel?.kind&&this._currentModel.dismiss?.(),this._groupGeneration+=1,this._openGroupId=e,this.host.clearTip(),this.host.requestUpdate(),this._syncGlobalDismissListener()):this.closeGroup(!1)}closeGroup(t){const e=this._openGroupId;this._openGroupId=null,this.host.requestUpdate(),this._syncGlobalDismissListener(),t&&e&&this.host.updateComplete().then(()=>{const t=this.host.root(),i=[...t.querySelectorAll("[data-editor-group]")].find(t=>t.dataset.editorGroup===e&&null!==t.offsetParent);(i||t.querySelector(".editbar-tools"))?.focus?.()})}renderGroupLauncher(t,e,i){const s=this._openGroupId===t.id,n=t.items.find(e=>e.id===t.activeItemId&&!e.disabled);return W``:G} - `}houseplanContinuityTrace(){return[...this._continuityHistory,...this._continuity.trace].slice(-80).map(t=>({...t,...t.stage?{stage:[...t.stage]}:{}}))}getCardSize(){return 12}get _norm(){return!(!this._serverCfg||!this._serverCfg.spaces.length)}_cfgFingerprint(){const t=this._serverCfg?.spaces||[];let e=t.length+":";for(const i of t){e+=(i.id||"")+","+(i.plan_aspect||"")+","+(i.plan_url||"").length+","+(i.plan_x??"")+","+(i.plan_y??"")+","+(i.plan_scale??"")+","+(i.plan_scale_x??"")+","+(i.plan_scale_y??"")+","+(i.plan_angle??"")+","+(i.rooms?.length||0)+","+(i.openings?.length||0)+","+(i.decor?.length||0)+";";for(const t of i.rooms||[]){const i=t.poly?.[0],s=t.poly?.[t.poly.length-1];e+=(t.poly?.length||0)+"."+(t.id||"")+"."+(t.open_to||[]).join("+")+"."+(t.area||"")+"."+JSON.stringify(t.settings||0)+"."+(t.x??"")+","+(t.y??"")+","+(t.w??"")+","+(t.h??"")+","+(i?i[0]+"/"+i[1]:"")+","+(s?s[0]+"/"+s[1]:"")+";"}}return e}get _model(){if(!this._serverCfg)return[];const t=this._cfgEpoch+"|"+this._cfgFingerprint();if(this._modelCache&&this._modelCache.key===t)return this._modelCache.model;const e=this._buildModel();return this._modelCache={key:t,model:e},e}_buildModel(){if(!this._serverCfg)return[];const t=this._renderCfg;return vc(t).map((e,i)=>{const s=t.spaces[i]?.plan_url;return e.bg&&s?{...e,bg:{...e.bg,href:s}}:e})}_spaceModel(){return this._hasFixedFloor?Rh(this._model,this._space):(t=this._model,e=this._space,t.find(t=>t.id===e)??t[0]);var t,e}_spaceModelById(t){return Rh(this._model,t)}_syncEmptySpaceState(){if(!!this._serverCfg&&0===this._serverCfg.spaces.length){if(!this._emptySpaceStateActive){this._emptySpaceStateActive=!0;for(const t of this._pointers.keys())for(const e of this.renderRoot.querySelectorAll("*"))try{e.hasPointerCapture?.(t)&&e.releasePointerCapture(t)}catch{}this._pointers.clear(),this._panStart=null,this._panLock=null,this._pinchStart=null,this._swipeStart=null,this._drag=null,this._rlResize=null,this._vacFit=null,this._compassDrag=!1,this._cancelModeTransition(!1),this._mode="view",this._clearGeometryGesture(),this._geometryHistory.clear(),this._resumeDraftBySpace={},this._tip=null,this._hoverRoom=null,this._openingInfo=null,this._closeInfoCard(),this._markerDialog=null,this._physicalDialog=null,this._backdropDialog=null,this._decorShapeDialog=null,this._decorTextDialog=null,this._roomDialog=!1,"edit"===this._spaceDialog?.mode&&(this._spaceDialog=null),this._editorSecondary.closeForNavigation(),this._saveConfigDebounced.cancel(),this._frame=null,this._planSnapGeometryCache=null,this._decorSnapCache=null,this._commitSpace("",!0)}}else this._emptySpaceStateActive=!1}get _areaToSpace(){const t={};for(const e of this._model)for(const i of e.rooms)i.area&&(t[i.area]={space:e.id,room:i});return t}get _settings(){return this._serverCfg?.settings||{}}get _showAll(){return this._settings.filter_seeded?this._showHidden:!!this._settings.show_all}_toggleShowAll(){if(this._serverCfg){if(this._settings.filter_seeded)return this._showHidden=!this._showHidden,void this.requestUpdate();this._serverCfg={...this._serverCfg,settings:{...this._serverCfg.settings,show_all:!this._settings.show_all}},this._regSignature="",this._maybeRebuildDevices(),this._saveConfig(),this.requestUpdate()}}_seedHiddenDevices(){if(!this._serverCfg||!this._norm||!this._canEdit)return;const t=this._serverCfg,e=function(t){const e=t.hass,i=t.registry||An(e),s=On(e,i),n=Nn(e,i),{areaToSpace:o,markers:r,settings:a,excluded:l,iconRules:c}=t,h=!1!==a.group_lights,d=wo(r),p=yo(s,h).filter(t=>!ko(s,t.eid,d)),u=new Set(p.map(t=>t.area)),_=qn(s),g=Wn(r,n),m=new Set(r.map(t=>t.binding)),f=[];for(const t of Object.values(s.devices)){const n=t.area_id;if(!n||!o[n])continue;if("service"===t.entry_type)continue;if(m.has("device:"+t.id))continue;if("active"!==Bn(e,"device:"+t.id,i).kind)continue;const r=jn(s,t.id,_[t.id]||[],g);if(r.partial&&!r.entityIds.length)continue;const a=r.entityIds,d=Un(s,t,a);let p=l.has(d)||"Group"===t.model||/scene/i.test(t.model||"")||/bridge/i.test((t.model||"")+(t.name||""))||"myheat"===d&&!!t.via_device_id;if(!p&&h&&u.has(n)){const e=(t.name_by_user||t.name||"").trim();"mdi:lightbulb"===bo(s,e,t.model,a,c)&&(p=!0)}p&&f.push("device:"+t.id)}return f}({hass:this.hass,registry:this._haRegistry,areaToSpace:Object.fromEntries(Object.entries(this._areaToSpace).map(([t,e])=>[t,e.space])),markers:this._markers,settings:this._settings,excluded:this._excluded,firstSpaceId:this._model[0]?.id||"",iconRules:this._iconRules});if(!e.length&&t.settings?.filter_seeded)return;t.markers=t.markers||[];const i=[];for(const s of e){const e="h"+s.slice(s.indexOf(":")+1);t.markers.push({id:e,binding:s,hidden:!0}),i.push(s.slice(s.indexOf(":")+1))}const s={...t.settings||{},filter_seeded:!0};delete s.show_all,i.length&&Array.isArray(s.new_device_ids)&&(s.new_device_ids=s.new_device_ids.filter(t=>!i.includes(t))),t.settings=s,this._regSignature="",this._maybeRebuildDevices(),this._saveConfig(),this.requestUpdate()}get _iconRules(){const t=this._settings.icon_rules;if(!t||!Array.isArray(t)||!t.length)return;const e=JSON.stringify(t);return e!==this._rulesCompiledSrc&&(this._rulesCompiledSrc=e,this._rulesCompiled=Jt(t)),this._rulesCompiled}get _fillColors(){return ps(this._settings)}get _excluded(){const t=this._settings.exclude_integrations;return t?new Set(t):Yt}willUpdate(t){t.has("_serverCfg")&&this._cfgEpoch++,this._syncEmptySpaceState(),t.has("hass")&&this.hass&&(this._hassSequence++,this._renderSnapshotAt=Date.now(),this._continuity.note("hass-snapshot"),this._ensureHaRegistryAuthority(),this._planHassMemo=null,this._hookConnection(),!this._loadOk&&!this._loading&&this._loadTries<8&&this._loadFromServer(),this._maybeRebuildDevices(),this._vacTick(),this._activityTick()),this._continuity.hasCompleteFrame&&"steady"===this._continuity.state&&this._continuity.refreshCompleteFrame(this._visualFrameFingerprint()),this._captureRenderDeviceSnapshot()}updated(){this._pruneDevicePressFeedback(),this._syncDayCycleClock(),this._warmSnapshot(),this._dtMeasure();const t=this._stageEl;t&&!this._roViewport&&(this._roViewport=new ResizeObserver(()=>this._refitView()),this._roViewport.observe(t)),t&&this._booting&&!this._bootTimer&&this._bootWatch();const e=this.renderRoot.querySelector(".hdr");if(e&&t&&!this._roHdr){const i=()=>{const e=this.renderRoot.querySelector("ha-card");if(!e)return;const i=t.getBoundingClientRect().top-e.getBoundingClientRect().top,s=Math.min(Math.max(e.getBoundingClientRect().top,0),120),n=Math.round(i+s);n>=0&&n!==this._hdrH&&(this._hdrH=n),n>=0&&!this._booting&&!this._config?.kiosk&&t.clientHeight>0&&this._warmPatch({hdrH:n,stageH:t.clientHeight})};this._roHdr=new ResizeObserver(()=>requestAnimationFrame(i)),this._roHdr.observe(e),this._onWinResize=()=>requestAnimationFrame(i),window.addEventListener("resize",this._onWinResize),i()}if(t&&!this._view&&this._refitView(),this._editorSecondary.afterRender(),this._settleContinuityFrame(),this._serverStorage&&this._loadOk&&0===this._model.length&&!this._spaceDialog&&!this._importDialog&&!this._onboardingShown){this._onboardingShown=!0;const t=function(t){const e=t?.floors;if(!e||"object"!=typeof e)return[];const i=[];for(const t of Object.values(e))t&&t.floor_id&&i.push({id:t.floor_id,name:t.name||t.floor_id,level:t.level??null});return i.sort((t,e)=>{const i=t.level??1e9,s=e.level??1e9;return i!==s?i-s:t.name.localeCompare(e.name)}),i}(this.hass);t.length?this._importDialog={floors:t.map(t=>({...t,checked:!0}))}:this._openSpaceDialog("create")}}_adoptStructuralResponses(t,e,i){const s=t?.config,n=s&&Array.isArray(s.spaces)?s:null,o=Ch(n),r=o!==(this._cfgContentFingerprint||Ch(this._serverCfg));if(r&&(this._geometryHistory.clear(),this._serverCfg&&this._clearGeometryGesture(),this._serverCfg=n,this._cfgContentFingerprint=o),this._cfgRev=t?.rev??this._cfgRev,t&&("virtual_lights"in t||"config"in t)){const e=mn(this._virtualLights,t.virtual_lights,this._cfgRev,"virtual_lights"in t);vn(e)!==vn(this._virtualLights)&&(this._virtualLights=e,this._capturedSnapshotVirtual="")}let a=!1;if(void 0!==e||void 0!==i){const t=i??e?.layout??{},s=Ch(t);a=s!==(this._layoutContentFingerprint||Ch(this._layout)),a&&(this._layout=t,this._layoutContentFingerprint=s),this._layoutRev=e?.rev??this._layoutRev}return this._canOptimizeUndo=!(!t?.can_optimize_undo&&!e?.can_optimize_undo),this._undoKind=t?.undo_kind||e?.undo_kind||null,"boolean"==typeof t?.can_write&&(this._serverCanWrite=t.can_write),r&&this._continuity.note("config-candidate",{configRev:this._cfgRev}),a&&this._continuity.note("layout-candidate",{layoutRev:this._layoutRev}),{configChanged:r,layoutChanged:a}}_resumePendingNavMode(){if(!this._pendingNavMode||!this._canEdit||this._config?.kiosk)return!1;const t=this._pendingNavMode;return this._pendingNavMode=null,this._setMode(t,!1),!0}async _loadFromServer(){this._loading=!0,this._loadTries++;const t=this._space,e=!!this._view;try{const[i,s]=await Promise.all([this.hass.callWS({type:"houseplan/config/get"}),this.hass.callWS({type:"houseplan/layout/get"})]),n=i?.config&&Array.isArray(i.config.spaces)?i.config:null,o=Ch(n)!==(this._cfgContentFingerprint||Ch(this._serverCfg))||Ch(s?.layout??{})!==(this._layoutContentFingerprint||Ch(this._layout));if(o){if(!await this._signer.prepareImage(this.hass,this._candidateBackdrop(n)))return this._continuity.note("asset-failed"),void this._scheduleLoadRetry(!0)}o&&this._continuity.hasCompleteFrame&&"steady"===this._continuity.state&&this._beginContinuityCandidate("structural-response",!0),this._connectionWasLost=!1,this._serverStorage=!0,"boolean"==typeof i?.can_write&&(this._serverCanWrite=i.can_write),this._canOptimizeUndo=!(!i?.can_optimize_undo&&!s?.can_optimize_undo),this._adoptStructuralResponses(i,s),this._adoptInitialSpace(this._model,!0),this._resumePendingNavMode(),this._cacheSnapshot(),this._warmVpArmed&&this._space===this._warmVp?.space?this._warmVpArmed=!1:e&&this._space===t||this._restoreZoom(),this._loadOk=!0,this.hass.callWS({type:"houseplan/trail/get"}).then(t=>{this._vacSrvTrails=t?.trails||{},this.requestUpdate()}).catch(()=>{}),this._ensureLiveSyncSubscriptions()}catch(t){if(this._serverCfg)this._scheduleLoadRetry(!0);else if(this._loadTries>=8){this._serverStorage=!1;try{this._layout=JSON.parse(localStorage.getItem(om)||"{}")||{}}catch{this._layout={}}}}finally{this._loading=!1,this._continuityDataReady=!0,this._regSignature="",this._maybeRebuildDevices(),this.requestUpdate()}}_ensureLiveSyncSubscriptions(){const t=this.hass?.connection;if(!t)return;if(t!==this._liveSyncConnection&&(this._unsubCfg?.(),this._unsubCfg=null,this._unsubLayout?.(),this._unsubLayout=null,this._unsubTrail?.(),this._unsubTrail=void 0,this._unsubVirtual?.(),this._unsubVirtual=null,this._liveSyncGeneration++,this._liveSyncAttempt=null,this._liveSyncConnection=t),this._liveSyncAttempt)return;const e=this._liveSyncGeneration,i=[],s=(s,n,o,r)=>{s()||i.push(async()=>{const i=await t.subscribeEvents(r,o);e===this._liveSyncGeneration&&this.isConnected&&this.hass?.connection===t&&!s()?n(i):i?.()})};if(s(()=>this._unsubCfg,t=>{this._unsubCfg=t},"houseplan_config_updated",t=>{const e=Number(t?.data?.rev??-1);e!==this._cfgRev&&this._reloadConfigOnly(!1,e)}),s(()=>this._unsubTrail,t=>{this._unsubTrail=t},"houseplan_trail_updated",async()=>{try{const t=await this.hass.callWS({type:"houseplan/trail/get"});this._vacSrvTrails=t?.trails||{},this.requestUpdate()}catch{}}),s(()=>this._unsubLayout,t=>{this._unsubLayout=t},"houseplan_layout_updated",t=>this._onLayoutEvent(Number(t?.data?.rev??-1))),s(()=>this._unsubVirtual,t=>{this._unsubVirtual=t},"houseplan_virtual_light_updated",t=>{const e=wn(this._virtualLights,t?.data);e!==this._virtualLights&&(this._virtualLights=e,this._capturedSnapshotVirtual="",this._cacheSnapshot(),this.requestUpdate())}),!i.length)return;const n=function(t){return Promise.allSettled(t.map(t=>Promise.resolve().then(t)))}(i).then(()=>{});this._liveSyncAttempt=n,n.finally(()=>{this._liveSyncAttempt===n&&(this._liveSyncAttempt=null)})}async _reloadConfigOnly(t=!1,e){if(!t){if(void 0!==e&&e<=this._cfgRev)return;if(this._saveConfigDebounced.pending()&&this._saveConfigDebounced.flush(),this._cfgWriting)return clearTimeout(this._reloadRetry),void(this._reloadRetry=window.setTimeout(()=>this._reloadConfigOnly(!1,e),400))}this._beginContinuityCandidate("config-reload",!1);try{const t=await this.hass.callWS({type:"houseplan/config/get"}),e=t?.config&&Array.isArray(t.config.spaces)?t.config:null;if(Ch(e)!==(this._cfgContentFingerprint||Ch(this._serverCfg))&&!await this._signer.prepareImage(this.hass,this._candidateBackdrop(e)))return this._continuity.note("asset-failed"),void this._scheduleLoadRetry(!0);const i=this._space;this._adoptStructuralResponses(t),this._adoptInitialSpace(this._model,!0),this._resumePendingNavMode(),this._cacheSnapshot(),this._space!==i&&this._restoreZoom(),this._regSignature="",this._maybeRebuildDevices(),this.requestUpdate()}catch(t){this._showToast(this._t("toast.cfg_reload_failed",{err:this._errText(t)}))}finally{this._continuityDataReady=!0,this.requestUpdate()}}_scheduleLoadRetry(t=!1){if(void 0!==this._loadRetryTimer)return;const e=Math.min(8e3,500*2**Math.min(4,Math.max(1,this._loadTries-7)));this._loadRetryTimer=window.setTimeout(()=>{this._loadRetryTimer=void 0,!t&&this._loadOk||this._loading||!this.hass||this._loadFromServer()},e)}_ensureHaRegistryAuthority(){const t=this.hass?.connection||null;t&&t!==this._haRegistryConnection&&(this._haRegistryRelease?.(),this._haRegistryConnection=t,this._haRegistryRev=-1,this._haBindingCacheKey="",this._planHassMemo=null,this._haRegistryRelease=In(this.hass,this._onHaRegistryUpdate),this._onHaRegistryUpdate())}get _haRegistry(){return An(this.hass)}get _planHass(){const t=this._haRegistry,e=En(this.hass,t),i=this._planHassMemo;if(i&&i.hass===this.hass&&i.sig===e)return i.active;const s=On(this.hass,t),n=Nn(this.hass,t);return this._planHassMemo={hass:this.hass,sig:e,active:s,full:n},s}_captureRenderDeviceSnapshot(){if(!this.hass)return;const t=Date.now(),e=[...this._activityRt.entries()].map(([e,i])=>`${e}:${i.gen}:${i.flashTs}:`+(i.flashKind&&(i.expiresAt||i.flashTs+xu)>t?1:0)).join("|"),i=vn(this._virtualLights);if(this._capturedSnapshotSequence===this._hassSequence&&this._capturedSnapshotDevices===this._devices&&this._capturedSnapshotLayout===this._layout&&this._capturedSnapshotConfigEpoch===this._cfgEpoch&&this._capturedSnapshotVirtual===i&&this._capturedSnapshotActivity===e)return;const s=this._planHass,n=new Map,o=new Map,r=new Set(["sun.sun"]);this._vacFit?.source&&r.add(this._vacFit.source);const a=new Set,l=new Set,c=t=>{if(!t)return;const e=t.indexOf(":");if(e<0)return void r.add(t);const i=t.slice(0,e),s=t.slice(e+1);"device"===i?a.add(s):"entity"===i&&r.add(s)};for(const t of this._model)for(const e of t.rooms)e.area&&l.add(e.area),c(e.settings?.temp_source),c(e.settings?.hum_source);for(const t of this._serverCfg?.spaces||[])for(const e of t.openings||[])for(const t of mi(e))r.add(t);for(const t of this._serverCfg?.spaces||[])for(const e of t.decor||[])if("text"===e.kind){for(const t of String(e.text||"").matchAll(/\{([^{}\r\n]+)\}/g)){const e=Yi(t[1]);e?.entity&&r.add(e.entity)}e.entity&&r.add(e.entity),o.set(`decor:${t.id}:${e.id}`,ts(e.text,e,s,t=>!!s.entities?.[t]&&!!s.states?.[t]&&!ko(s,t,wo(this._markers))))}const h=ho(s,this._devices,null,this._virtualLights);for(const t of this._devices){for(const e of[!1,!0])n.set(ru(t.id,e),iu(s,t,{liveStates:!1!==this._config?.live_states,showTemperature:!1!==this._config?.show_temperature,showSignal:e,activityRuntime:this._activityRt.get(t.id),sourceDetails:!1,lightDevices:this._devices,lightSources:h,registryHass:this._fullRegistryHass,reducedMotion:this._reducedMotion}));if(this._isVacDev(t)){const e=this._vacSource(t,s),i=e?jh(s?.states?.[e]?.attributes):null,n=this._vacRt.get(t.id);o.set(`vacuum:${t.id}`,{source:e,telemetry:i,mapId:i?this._vacMapId(t,i,s):null,runtime:n?{trail:n.trail,lastTs:n.lastTs,moving:n.moving,jump:n.jump}:null,server:this._vacSrvTrails[t.id]||null})}}const d=ou({sourceSequence:this._hassSequence,hass:s,devices:this._devices,presentations:n,positions:(p=this._model.length>0,u=this._devices,_=t=>this._livePos(t),p?new Map(u.map(t=>[t.id,_(t)])):new Map),facts:o,entityIds:r,deviceIds:a,areaIds:l});var p,u,_;this._capturedSnapshotSequence=this._hassSequence,this._capturedSnapshotDevices=this._devices,this._capturedSnapshotLayout=this._layout,this._capturedSnapshotActivity=e,this._capturedSnapshotConfigEpoch=this._cfgEpoch,this._capturedSnapshotVirtual=i,this._visibleDeviceSnapshot&&"steady"!==this._continuity.state?this._candidateDeviceSnapshot=d:(this._visibleDeviceSnapshot=d,this._candidateDeviceSnapshot=null)}get _renderDeviceSnapshot(){return this._stagedDeviceSnapshotToken===this._continuity.token?this._candidateDeviceSnapshot||this._visibleDeviceSnapshot:this._visibleDeviceSnapshot||this._candidateDeviceSnapshot}get _renderPlanHass(){return this._renderDeviceSnapshot?.hass||this._planHass}get _renderDevices(){return this._renderDeviceSnapshot?.devices||this._devices}get _fullRegistryHass(){return this._planHass,this._planHassMemo?.full||this.hass}_bindingStatus(t){return Bn(this.hass,t,this._haRegistry)}houseplanDiagnostics(){const t=function(t){const e=An(t);return{access:e.access,authoritative:e.authoritative,revision:e.revision,lastSuccess:e.lastSuccess,error:e.error}}(this.hass),e={active:0,ha_disabled:0,orphaned:0,unverified:0};for(const t of this._markers)t.removed||"virtual"===t.binding||e[this._bindingStatus(t.binding).kind]++;return{registry:{...t,lastSuccessAgeMs:t.lastSuccess?Math.max(0,Date.now()-t.lastSuccess):null},bindings:e}}_openBindingInHa(t){const[e,i]=t.split(":");if(i)if("device"!==e){if("entity"===e){const t=this._fullRegistryHass.entities?.[i];t?.device_id&&vm("/config/devices/device/"+encodeURIComponent(t.device_id))}}else vm("/config/devices/device/"+encodeURIComponent(i))}_bindingHasHaPage(t){const[e,i]=t.split(":");return!!i&&("device"===e||"entity"===e&&!!this._fullRegistryHass.entities?.[i]?.device_id)}_toggleMarkerDialogVisibility(){const t=this._markerDialog;if(!t)return;const e="ha"===t.bindingMode?this._bindingStatus(t.binding):null,i=t.hideFromPlan||"ha_disabled"===e?.kind;i&&"ha_disabled"===e?.kind?this._showToast(this._t("entity"===e.reason?"toast.ha_disabled_show_entity":"toast.ha_disabled_show_device")):i&&"unverified"===e?.kind?this._showToast(this._t("toast.ha_binding_unverified")):this._markerDialog={...t,hideFromPlan:!i}}_hookConnection(){const t=this.hass?.connection;t&&t!==this._connHooked&&(this._connHooked?.removeEventListener?.("ready",this._onConnReady),this._connHooked?.removeEventListener?.("disconnected",this._onConnLost),this._connHooked?.removeEventListener?.("reconnect-error",this._onConnLost),t.addEventListener?.("ready",this._onConnReady),t.addEventListener?.("disconnected",this._onConnLost),t.addEventListener?.("reconnect-error",this._onConnLost),this._connHooked=t)}_display(t){return this._signer.display(this.hass,t)}_resign(){this._signer.resign(this.hass,Is(this._serverCfg))}_onLayoutEvent(t){t<=this._layoutRev||(clearTimeout(this._layoutSyncTimer),this._layoutSyncTimer=window.setTimeout(()=>{t<=this._layoutRev||this._reloadLayoutOnly()},200))}_noteLayoutRev(t){const e=t?.rev;"number"==typeof e&&e>this._layoutRev&&(this._layoutRev=e)}async _reloadLayoutOnly(){if(!this._serverStorage||!this.hass?.callWS)return;this._beginContinuityCandidate("layout-reload",!1);const t=new Map;for(const e of this._dirtyPos)this._layout[e]&&t.set(e,this._layout[e]);this._persistLayout.pending()&&this._persistLayout.flush();for(const[e,i]of this._sentPos)t.set(e,i);try{const e=await this.hass.callWS({type:"houseplan/layout/get"}),i={...e?.layout||{}};for(const[e,s]of t)i[e]=s;const s=Ch(i);s!==(this._layoutContentFingerprint||Ch(this._layout))&&(this._layout=i,this._layoutContentFingerprint=s),this._layoutRev=e?.rev??this._layoutRev,this._canOptimizeUndo=!!e?.can_optimize_undo,this._undoKind=e?.undo_kind||null,this._cacheSnapshot(),this.requestUpdate()}catch{}finally{this._continuityDataReady=!0,this.requestUpdate()}}_maybeRebuildDevices(){const t=this.hass;if(!t?.devices||!t?.entities||!t?.areas)return;const e=this._haRegistry,i=En(t,e)+":"+Object.keys(t.areas).length+":"+(this._norm?"n":"l")+":"+ar(t,this._config?.language);if(i===this._regSignature&&this._devices.length)return;this._regSignature=i;const s=new Map(this._devices.map(t=>[t.id,t.bindingStatus?.kind||"active"]));this._devices=So({hass:t,registry:e,areaToSpace:Object.fromEntries(Object.entries(this._areaToSpace).map(([t,e])=>[t,e.space])),markers:this._markers,settings:this._settings,excluded:this._excluded,showAll:this._showAll,firstSpaceId:this._model[0]?.id||"",loc:t=>this._t(t),iconRules:this._iconRules});const n=this._markers.filter(t=>!t.removed&&"virtual"!==t.binding).map(t=>t.binding).sort(),o=e.revision+":"+n.join("|");if(e.authoritative&&o!==this._haBindingCacheKey){const i=new Map;for(const s of n)i.set(s,Bn(t,s,e));!function(t){if("undefined"==typeof localStorage||!t.size)return;const e=Ln(),i=Date.now();for(const[s,n]of t)"active"===n.kind?e[s]={kind:"active",ts:i}:"ha_disabled"===n.kind&&(e[s]={kind:"ha_disabled",reason:n.reason,ts:i});const s=Object.fromEntries(Object.entries(e).sort((t,e)=>e[1].ts-t[1].ts).slice(0,1500));Mn=s;try{localStorage.setItem(Sn,JSON.stringify(s))}catch{}}(i),this._haBindingCacheKey=o}this._defPos=this._defaultPositions(),this._syncNewDevices(),this._seedHiddenDevices(),this._syncActivityRuntime();const r=new Set(this._devices.filter(t=>!t.hidden).map(t=>t.id));for(const t of this._vacRt.keys())r.has(t)||this._vacRt.delete(t);if(this._infoCard){const t=this._devices.find(t=>t.id===this._infoCard.id);this._infoCard=t&&"ha_disabled"!==t.bindingStatus?.kind?t:null}const a=this._devices.some(t=>"ha_disabled"===t.bindingStatus?.kind&&"ha_disabled"!==s.get(t.id));a&&("ha_disabled"!==this._infoCard?.bindingStatus?.kind&&"ha_disabled"!==this._devices.find(t=>t.id===this._infoCard?.id)?.bindingStatus?.kind||this._closeInfoCard(),this._drag&&"ha_disabled"===this._devices.find(t=>t.id===this._drag.id)?.bindingStatus?.kind&&(this._drag=null),clearTimeout(this._holdTimer),this._holdFired=!1,this._tip=null,this._tapConfirm=null),this._nativeMoreInfoEntity&&!this._planEntityAvailable(this._nativeMoreInfoEntity)&&(fm(this,"hass-more-info",{entityId:null}),this._nativeMoreInfoEntity=null)}_syncNewDevices(){if(!this._norm||!this._loadOk||!this._serverCfg)return;const t=this._devices.filter(t=>!t.marker&&!t.virtual).map(t=>t.id).sort(),e=t.join(",");if(e===this._newSyncKey)return;this._newSyncKey=e;const i=this._settings,{fresh:s,known:n}=function(t,e){if(!Array.isArray(e))return{fresh:[],known:[...t]};const i=new Set(e),s=t.filter(t=>!i.has(t));return{fresh:s,known:s.length?[...e,...s]:e}}(t,i.known_devices);if(!Array.isArray(i.known_devices)||s.length){const t=[...new Set([...i.new_device_ids||[],...s])];this._serverCfg={...this._serverCfg,settings:{...i,known_devices:n,new_device_ids:t}},this._saveConfig()}}get _newIds(){const t=this._settings.new_device_ids;return new Set(Array.isArray(t)?t:[])}_ackNewDevice(t){if(!this._newIds.has(t)||!this._serverCfg)return;const e=this._settings;this._serverCfg={...this._serverCfg,settings:{...e,new_device_ids:(e.new_device_ids||[]).filter(e=>e!==t)}},this._saveConfig(),this.requestUpdate()}get _markers(){return this._serverCfg?.markers||[]}_roomLqi(t){if(!t)return null;const e=[];for(const i of this._renderDevices){if(i.area!==t||i.virtual)continue;const s=_o(this._renderPlanHass,i.entities);null!=s&&e.push(s)}return zi(e)}_roomBounds(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}}_defaultPositions(){const t={},e=this._config?.icon_size??2.5;for(const i of this._model){const s=e/100*Hc(i)*1.3;for(const e of i.rooms){if(!e.area)continue;const n=this._devices.filter(t=>t.area===e.area&&t.space===i.id);if(!n.length)continue;const o=this._roomBounds(e),r=.1*Math.min(o.w,o.h),a=o.w-2*r,l=o.h-2*r,c=Math.max(1,Math.round(Math.sqrt(n.length*a/Math.max(l,1)))),h=Math.ceil(n.length/c),d=a/c,p=l/Math.max(h,1),u=n.map((t,e)=>({x:o.x+r+d*(e%c+.5),y:o.y+r+p*(Math.floor(e/c)+.5)}));Ni(u,o,s,.5*r),n.forEach((e,i)=>t[e.id]=Sc(u[i]))}}return t}_pos(t){const e=this._renderDeviceSnapshot?.positions.get(t.id);return e?{x:e.x,y:e.y}:this._livePos(t)}_livePos(t){const e=this._spaceModelById(t.space),i=this._layout[t.id];if(i)if(this._norm){if(i.s===t.space)return{x:i.x*pm,y:i.y*pm}}else if(void 0===i.s)return{x:i.x,y:i.y};return this._defPos[t.id]?this._defPos[t.id]:e?Sc(Nc(e)):{x:500,y:500}}_savePos(t,e,i){if(this._spaceModelById(t.space)){if(this._norm){const s=this._gridPitch,n=Math.round(e/s)*s,o=Math.round(i/s)*s,r=this._layout[t.id]?.k;this._layout={...this._layout,[t.id]:{s:t.space,x:Cc(n/pm),y:Cc(o/pm),...r?{k:r}:{}}}}else this._layout={...this._layout,[t.id]:{x:Math.round(e),y:Math.round(i)}};this._dirtyPos.add(t.id),this._persistLayout()}}_visualSamples(t){return Jp(this._renderPlanHass,t,this._renderDevices,void 0,this._fullRegistryHass).samples}_devicePresentation(t,e=!1!==this._config?.show_signal,i=!1){const s=i?null:this._renderDeviceSnapshot?.presentations.get(ru(t.id,e));return s||iu(this._renderPlanHass,t,{liveStates:!1!==this._config?.live_states,showTemperature:!1!==this._config?.show_temperature,showSignal:e,designPreview:i,activityRuntime:this._activityRt.get(t.id),sourceDetails:!1,lightDevices:this._renderDevices,registryHass:this._fullRegistryHass,reducedMotion:this._reducedMotion})}_deviceVisual(t){return this._devicePresentation(t).visual}_stateClass(t,e=this._deviceVisual(t)){const i=this._devicePresentation(t);return i.effectiveHidden?"":("icon_ripple"!==i.display||!1===this._config?.live_states||"alarm"===e.status||e.activity,eu({...i,visual:e}).join(" "))}_liveTemp(t){if(!this._config?.show_temperature)return null;if(!0===t.marker?.use_climate_temp){const e=mo(this._renderPlanHass,t.entities);if(null!=e)return e}return"mdi:thermometer"!==t.icon&&"mdi:air-filter"!==t.icon?null:go(this._renderPlanHass,t.entities)}_bindingEntities(t){if("virtual"===t||!t)return[];const e=this._bindingStatus(t);return"active"===e.kind?e.enabledEntityIds:e.allEntityIds}_bindingHasClimate(t){return this._bindingEntities(t).some(t=>t.startsWith("climate."))}_bindingHasAlarm(t){return this._bindingEntities(t).some(t=>{const e=this._planHass?.states?.[t]||this.hass?.states?.[t],i=this._fullRegistryHass.entities[t]||this.hass?.entities?.[t];return Bs(t.split(".")[0],e?.attributes?.device_class||i?.device_class||i?.original_device_class)})}_liveHum(t){return this._config?.show_temperature&&t.primary&&fo(this.hass,t.primary)?vo(this.hass,t.entities):null}_deviceBindingActive(t,e=!0){if(t.virtual||"virtual"===t.bindingKind)return!0;if(!t.bindingKind||!t.bindingRef)return!1;const i=this._bindingStatus(`${t.bindingKind}:${t.bindingRef}`);return"active"===i.kind||(e&&this._showToast(this._t("ha_disabled"===i.kind?"toast.ha_disabled_action":"toast.ha_binding_unverified")),!1)}_openMoreInfo(t){t?this._planEntityAvailable(t)?(this._nativeMoreInfoEntity=t,fm(this,"hass-more-info",{entityId:t})):this._showToast(this._t("toast.ha_disabled_action")):this._showToast(this._t("toast.no_entity"))}_interruptViewGesture(t,e){if(clearTimeout(this._holdTimer),clearTimeout(this._kioskHoldTimer),void 0!==t)for(const i of[e,this._stageEl])try{i?.hasPointerCapture?.(t)&&i.releasePointerCapture(t)}catch{}this._pointers.clear(),this._panStart=null,this._panLock=null,this._pinchStart=null,this._swipeStart=null}_closeInfoCard(){this._interruptViewGesture(),this._holdFired=!1,this._infoCard=null}_ctxDevice(t,e){"view"===this._mode&&(t.preventDefault(),t.stopPropagation(),this._deviceBindingActive(e)&&(e.primary?this._openMoreInfo(e.primary):this._infoCard=e))}_clickDevice(t,e){if(t.stopPropagation(),this._drag?.moved||this._suppressClick||this._holdFired)return;if("plan"===this._mode)return;if("devices"===this._mode)return void this._openMarkerDialog(e);const i=this._devices.find(t=>t.id===e.id);if(!i)return;const s=yd(i.tapAction,i.primary?.split(".")[0]),n=(t,e)=>{i.marker?.tap_confirm?this._tapConfirm={kind:"run",text:t,exec:e}:e()};if("toggle"===s){const t=this._toggleIntent(i);if(!t||!Sd(t))return;const e=t=>{const e=Sd(t);if(!e)return;if("virtual-light"===e.kind)return this._startDevicePressFeedback(i.id),void this.hass.callWS({type:"houseplan/virtual_light/toggle",marker_id:e.markerId}).then(t=>{const e=wn(this._virtualLights,t);e!==this._virtualLights&&(this._virtualLights=e,this._capturedSnapshotVirtual="",this._cacheSnapshot(),this.requestUpdate())}).catch(t=>this._showToast(this._t("toast.virtual_light_toggle_failed",{err:this._errText(t)})));const{command:s}=e;this._startDevicePressFeedback(i.id),this.hass.callService(s.domain,s.service,s.data).catch(t=>this._showToast(this._t("toast.error",{err:this._errText(t)})))},s=((o=t).targets.length?o.targets:o.skippedTargets).map(t=>t.name||t.entityId||t.ref).join(", ")||i.name;if(i.marker?.tap_confirm){const n=this._toggleConfirmationLines(t);if(!n.length)return;this._tapConfirm={kind:"toggle",text:this._t("confirm.tap_toggle",{name:s}),lines:n,initialIntent:t,deviceId:i.id,exec:()=>{const s=this._devices.find(t=>t.id===i.id),n=s?this._toggleIntent(s):null;n&&Md(t,n)?e(n):this._showToast(this._t("toast.tap_target_changed"))}}}else e(t);return}var o;if("info"===s)return this._interruptViewGesture(),void(this._infoCard=i);if(this._deviceBindingActive(i)){if("run"===s){const t=i.marker?.tap_target||"",e=function(t){const e=String(t||"").split(".")[0];return"automation"===e?{domain:"automation",service:"trigger"}:"script"===e?{domain:"script",service:"turn_on"}:"scene"===e?{domain:"scene",service:"turn_on"}:null}(t),s=this.hass.states[t];if(!e||!s)return void this._showToast(this._t("toast.run_target_missing"));const o=s.attributes?.friendly_name||t;return void n(this._t("confirm.tap_run",{name:o}),()=>{this._deviceBindingActive(i)&&this._planEntityAvailable(t)&&(this._startDevicePressFeedback(i.id),this.hass.callService(e.domain,e.service,{entity_id:t}).then(()=>{this._stampActivity(i.id,"event",this._activitySourceKey(i)),this.requestUpdate(),this._showToast(this._t("toast.run_started",{name:o}))}).catch(t=>this._showToast(this._t("toast.error",{err:this._errText(t)}))))})}"more-info"===s&&i.primary?this._openMoreInfo(i.primary):this._infoCard=i}}_keyDevice(t,e){"Enter"!==t.key&&" "!==t.key||"view"!==this._mode&&"devices"!==this._mode||(t.preventDefault(),this._clickDevice(t,e))}_startDevicePressFeedback(t){const e=[...this.renderRoot.querySelectorAll(".dev[data-id]")].find(e=>e.dataset.id===t),i=e?.querySelector(".device-shell");if(!i||"function"!=typeof i.animate)return;const s=Number.parseFloat(this.ownerDocument.defaultView?.getComputedStyle(i).scale||""),n=Number.isFinite(s)?Math.max(.95,Math.min(1,s)):1;this._devicePressAnimations.get(t)?.cancel();const o=this._reducedMotion?[{outlineColor:"transparent",outlineStyle:"solid",outlineWidth:"0px"},{outlineColor:"var(--hp-accent, #3ea6ff)",outlineStyle:"solid",outlineWidth:"2px",outlineOffset:"2px",offset:.5},{outlineColor:"transparent",outlineStyle:"solid",outlineWidth:"0px"}]:[{scale:String(n)},{scale:"0.95",offset:.5},{scale:"1"}],r=i.animate(o,{duration:200,easing:"cubic-bezier(.22,.61,.36,1)"});this._devicePressAnimations.set(t,r);const a=()=>{this._devicePressAnimations.get(t)===r&&this._devicePressAnimations.delete(t)};r.addEventListener("finish",a,{once:!0}),r.addEventListener("cancel",a,{once:!0})}_cancelDevicePressFeedback(){for(const t of this._devicePressAnimations.values())t.cancel();this._devicePressAnimations.clear()}_pruneDevicePressFeedback(){if(!this._devicePressAnimations.size)return;const t=new Set([...this.renderRoot.querySelectorAll(".dev[data-id]")].map(t=>t.dataset.id||""));for(const[e,i]of this._devicePressAnimations)t.has(e)||(i.cancel(),this._devicePressAnimations.delete(e))}_t(t,e){return lr(ar(this.hass,this._config?.language),t,e)}get _colorPickerLabels(){return{title:this._t("color_picker.title"),hue:this._t("color_picker.hue"),saturation:this._t("color_picker.saturation"),value:this._t("color_picker.value"),hex:this._t("color_picker.hex"),invalidHex:this._t("color_picker.invalid_hex")}}_help(t){const e=`${t}.aria`,i=ar(this.hass,this._config?.language);return cr(i,t)&&cr(i,e)?W``:G}get _stageEl(){return this.renderRoot.querySelector(".stage")}_contentItems(t){const e=[];for(const i of this._devices){if(i.space!==t.id||i.hidden)continue;const s=this._pos(i);e.push({minX:s.x,minY:s.y,maxX:s.x,maxY:s.y})}if(t.id===this._space){for(const t of this._openingsR){const i=Number(t.angle)*Math.PI/180,s=Math.cos(i)*t.rlen/2,n=Math.sin(i)*t.rlen/2,o=Pc([[t.rx-s,t.ry-n],[t.rx+s,t.ry+n]]);o&&e.push(o)}const i=this._decorH;for(const t of this._decorList){const s=Pc("line"===t.kind?[[t.x1*pm,t.y1*i],[t.x2*pm,t.y2*i]]:"text"===t.kind?[[t.x*pm,t.y*i]]:ua({x:t.x*pm,y:t.y*i,w:t.w*pm,h:t.h*i,angle:t.angle}));s&&e.push(s)}for(const i of this._physicalBodiesR(t)){const t=Pc(i);t&&e.push(t)}}return Ic(t,e)}_frameOf(){const t=this._spaceModel();if(!t){this._frame=null;const t={x:0,y:0,w:pm,h:pm};return{rect:t,all:t,outliers:0}}const e=this._frame,i="view"!==this._mode;if(e&&e.id===t.id&&this._bdDrag)return e;if(e&&e.id===t.id&&e.model===t&&e.layout===this._layout&&e.devs===this._devices&&e.far===this._showFar&&e.grow===i)return e;const s=zc(this._contentItems(t));let n=s.all||Oc(t),o=this._showFar?n:s.core||Oc(t);return e&&e.id===t.id&&i&&e.grow&&(o=_m(e.rect,o),n=_m(e.all,n)),this._frame={id:t.id,model:t,layout:this._layout,devs:this._devices,far:this._showFar,grow:i,rect:o,all:n,outliers:s.outliers},this._frame}_isoSource(){const t=this._spaceModel();if(!t)return null;const e=this._spaceWalls,i=this._openPairs().flatMap(t=>t.segs),s=this._openingsR.map((t,e)=>({id:String(t.id||e),sourceIndex:e,type:t.type,x:t.rx,y:t.ry,angle:Number(t.angle)||0,length:t.rlen>0?t.rlen:900,flipH:!!t.flip_h,flipV:!!t.flip_v})),n=cc(64,this._cellCm),o=cc(10,this._cellCm),r=`${t.id}|${function(t){let e=2166136261;const i=t=>{if("number"!=typeof t)if("string"!=typeof t)if("boolean"!=typeof t)if(Array.isArray(t)){e=fg(e,t.length);for(const e of t)i(e)}else{if(t&&"object"==typeof t){const e=t;for(const t of Object.keys(e).sort())i(t),i(e[t]);return}e=fg(e,-1)}else e=fg(e,t?1:0);else for(const i of t)e=fg(e,i.codePointAt(0)||0);else e=fg(e,t)};return i(t),e.toString(36)}({rooms:t.rooms,walls:e,openCuts:i,openings:s,partitions:t.partitions,roomDrafts:t.room_drafts,columns:t.wall_columns,cellCm:this._cellCm,gridPitch:this._gridPitch,wallKeyPitch:this._wallKeyPitch,camera:og,wallHeight:n,floorEdgeHeight:o,algorithm:3})}`;return{key:r,build:()=>{const o=Xl(t,this._cellCm,this._gridPitch,2e-4*this._gridPitch,this._partitionOpeningCuts(t)).all,r=this._roomWallOpeningInputs(this._openingsR,t),a=e.length||o.length?Cl(t.rooms,e,i,r,this._wallKeyPitch,this._cellCm,this._gridPitch,pm,o):null;if((e.length||o.length)&&!a)throw new Error("wall boolean geometry failed");const l=a?.paperGeom??Sl(t.rooms,e,i,this._wallKeyPitch,this._cellCm,this._gridPitch,pm);if(!l)throw new Error("floor boolean geometry failed");const c=a?.openingIndex||Rl(t.rooms,e,i,this._wallKeyPitch,this._cellCm,this._gridPitch,pm),h=s.map(t=>{const i=this._openingsR[t.sourceIndex],s="gate"===t.type?!t.flipV:t.flipV,o=i?.partitionHost?Fd(i.partitionHost,s):e.length||"gate"===t.type?El(c,{x:t.x,y:t.y,angle:t.angle,length:t.length,flip_v:s}):{ox:0,oy:0,cm:0,side:-1};return function(t,e=64){if(!(vg([t.x,t.y,t.angle,t.length,t.face.ox,t.face.oy,e])&&t.length>0&&e>0))throw new Error("invalid isometric opening input");const i=t.length/2;let s;if("passage"===t.type)s=[];else if("gate"===t.type){const n=10*t.face.side;s=[bg(t,0,[-i,0],[i,0],n,0,.88*e),bg(t,1,[i,0],[-i,0],-n,0,.88*e)]}else s="window"===t.type?[bg(t,0,[-i,0],[i,0],-90,.27*e,.78*e),bg(t,1,[i,0],[-i,0],90,.27*e,.78*e)]:[bg(t,0,[-i,0],[t.length,0],-90,0,.92*e)];return{id:t.id,sourceIndex:t.sourceIndex,type:t.type,leaves:Object.freeze(s.map(t=>Object.freeze(t)))}}({...t,face:o},n)});return{walls:a?.geom||[],floor:l,openings:Object.freeze(h)}}}}_isoSceneKey(){if(!this._labsIso||"view"!==this._mode)return null;try{return this._isoSource()?.key??null}catch{return`${this._space}|invalid`}}_isoScene(){const t=this._isoSource();if(!t)return null;const e=this._isoGeometryCache.get(t.key);if(e)return{key:t.key,...e};const i=this._frameOf().rect,s=t.build(),n=cc(64,this._cellCm),o=cc(10,this._cellCm),r=function(t){let e=1/0,i=1/0,s=-1/0,n=-1/0;for(const o of t)for(const t of o.leaves){const o=Math.hypot(t.closedVector[0],t.closedVector[1]);e=Math.min(e,t.hinge[0]-o),i=Math.min(i,t.hinge[1]-o),s=Math.max(s,t.hinge[0]+o),n=Math.max(n,t.hinge[1]+o)}return vg([e,i,s,n])?{x:e,y:i,w:s-e,h:n-i}:null}(s.openings),a=hg({rect:r?_m(i,r):i,wallHeight:n,openingHeight:n,floorDepth:o}),l=function(t,e=og,i=64){if(!Number.isFinite(i)||i<0)throw new Error("invalid wall height");const s=[],n=[],o=[];let r=0;for(let a=0;a<(t||[]).length;a++){const l=t[a];for(let t=0;t<(l||[]).length;t++){const c=ug(l[t],t>0);if(!(c.length<3||Math.abs(pg(c))<1e-9)){s.push(_g(c,e,i)),r+=c.length;for(let s=0;st.depth-e.depth||t.polygon-e.polygon||t.ring-e.ring||t.edge-e.edge),{topPath:s.join(" "),sides:n,contactPath:o.join(" "),edgeCount:r}}(s.walls,og,n),c={geometry:l,floor:mg(s.floor,o),openings:s.openings,frame:a};return tm(this._isoGeometryCache,t.key,c,8),{key:t.key,...c}}_effectiveProjection(){if("iso"!==this._desiredProjection||!this._model.length)return"flat";const t=this._isoSceneKey()||`${this._space}|invalid`;if(this._isoFallback.has(t))return"flat";try{const t=this._isoScene();return t?(e="iso",i=t.key,s=this._isoFallback,"iso"===e&&i&&!s.has(i)?"iso":"flat"):"flat"}catch(e){if(!this._isoFallback.has(t)){this._isoFallback.add(t);const i=t.split("|");console.warn(`HOUSEPLAN ISO FALLBACK: #89, space ${this._space}, fingerprint ${i[i.length-1]}, ${e instanceof Error?e.message:"renderer error"}`)}return"flat"}var e,i,s}_scenePoint(t){return"iso"===this._renderProjection?ag(t,0):t}_floorView(t){if("iso"!==this._renderProjection)return t;const e=lg([t.x,t.y]),i=lg([t.x+t.w,t.y+t.h]);return{x:e[0],y:e[1],w:i[0]-e[0],h:i[1]-e[1]}}_baseVb(){if("iso"===this._effectiveProjection()){if(!this._spaceDisplayForRender().showBorders){const t=hg({rect:this._frameOf().rect,wallHeight:cc(64,this._cellCm)});return[t.x,t.y,t.w,t.h]}const t=this._isoScene()?.frame??this._frameOf().rect;return[t.x,t.y,t.w,t.h]}const t=this._frameOf().rect;return[t.x,t.y,t.w,t.h]}get _outliers(){return this._showFar?0:this._frameOf().outliers}_fitFar(){this._showFar=!0,this._frame=null,this._resetZoom()}_fitAll(){this._showFar=!0,this._frame=null,this._resetZoom()}_renderFarHint(){return this._kiosk||"view"!==this._mode||this._booting||!this._outliers?G:W`
+
`}houseplanContinuityTrace(){return[...this._continuityHistory,...this._continuity.trace].slice(-80).map(t=>({...t,...t.stage?{stage:[...t.stage]}:{}}))}getCardSize(){return 12}get _norm(){return!(!this._serverCfg||!this._serverCfg.spaces.length)}_cfgFingerprint(){const t=this._serverCfg?.spaces||[];let e=t.length+":";for(const i of t){e+=(i.id||"")+","+(i.plan_aspect||"")+","+(i.plan_url||"").length+","+(i.plan_x??"")+","+(i.plan_y??"")+","+(i.plan_scale??"")+","+(i.plan_scale_x??"")+","+(i.plan_scale_y??"")+","+(i.plan_angle??"")+","+(i.rooms?.length||0)+","+(i.openings?.length||0)+","+(i.decor?.length||0)+";";for(const t of i.rooms||[]){const i=t.poly?.[0],s=t.poly?.[t.poly.length-1];e+=(t.poly?.length||0)+"."+(t.id||"")+"."+(t.open_to||[]).join("+")+"."+(t.area||"")+"."+JSON.stringify(t.settings||0)+"."+(t.x??"")+","+(t.y??"")+","+(t.w??"")+","+(t.h??"")+","+(i?i[0]+"/"+i[1]:"")+","+(s?s[0]+"/"+s[1]:"")+";"}}return e}get _model(){if(!this._serverCfg)return[];const t=this._cfgEpoch+"|"+this._cfgFingerprint();if(this._modelCache&&this._modelCache.key===t)return this._modelCache.model;const e=this._buildModel();return this._modelCache={key:t,model:e},e}_buildModel(){if(!this._serverCfg)return[];const t=this._renderCfg;return yc(t).map((e,i)=>{const s=t.spaces[i]?.plan_url;return e.bg&&s?{...e,bg:{...e.bg,href:s}}:e})}_spaceModel(){return this._hasFixedFloor?Ih(this._model,this._space):(t=this._model,e=this._space,t.find(t=>t.id===e)??t[0]);var t,e}_spaceModelById(t){return Ih(this._model,t)}_syncEmptySpaceState(){if(!!this._serverCfg&&0===this._serverCfg.spaces.length){if(!this._emptySpaceStateActive){this._emptySpaceStateActive=!0;for(const t of this._pointers.keys())for(const e of this.renderRoot.querySelectorAll("*"))try{e.hasPointerCapture?.(t)&&e.releasePointerCapture(t)}catch{}this._pointers.clear(),this._panStart=null,this._panLock=null,this._pinchStart=null,this._swipeStart=null,this._drag=null,this._rlResize=null,this._vacFit=null,this._compassDrag=!1,this._cancelModeTransition(!1),this._mode="view",this._clearGeometryGesture(),this._geometryHistory.clear(),this._resumeDraftBySpace={},this._tip=null,this._hoverRoom=null,this._openingInfo=null,this._closeInfoCard(),this._markerDialog=null,this._physicalDialog=null,this._backdropDialog=null,this._decorShapeDialog=null,this._decorTextDialog=null,this._roomDialog=!1,"edit"===this._spaceDialog?.mode&&(this._spaceDialog=null),this._editorSecondary.closeForNavigation(),this._saveConfigDebounced.cancel(),this._frame=null,this._planSnapGeometryCache=null,this._decorSnapCache=null,this._commitSpace("",!0)}}else this._emptySpaceStateActive=!1}get _areaToSpace(){const t={};for(const e of this._model)for(const i of e.rooms)i.area&&(t[i.area]={space:e.id,room:i});return t}get _settings(){return this._serverCfg?.settings||{}}get _showAll(){return this._settings.filter_seeded?this._showHidden:!!this._settings.show_all}_toggleShowAll(){if(this._serverCfg){if(this._settings.filter_seeded)return this._showHidden=!this._showHidden,void this.requestUpdate();this._serverCfg={...this._serverCfg,settings:{...this._serverCfg.settings,show_all:!this._settings.show_all}},this._regSignature="",this._maybeRebuildDevices(),this._saveConfig(),this.requestUpdate()}}_seedHiddenDevices(){if(!this._serverCfg||!this._norm||!this._canEdit)return;const t=this._serverCfg,e=function(t){const e=t.hass,i=t.registry||An(e),s=On(e,i),n=Nn(e,i),{areaToSpace:o,markers:a,settings:r,excluded:l,iconRules:c}=t,h=!1!==r.group_lights,d=wo(a),p=yo(s,h).filter(t=>!ko(s,t.eid,d)),u=new Set(p.map(t=>t.area)),_=qn(s),g=Wn(a,n),m=new Set(a.map(t=>t.binding)),f=[];for(const t of Object.values(s.devices)){const n=t.area_id;if(!n||!o[n])continue;if("service"===t.entry_type)continue;if(m.has("device:"+t.id))continue;if("active"!==Bn(e,"device:"+t.id,i).kind)continue;const a=jn(s,t.id,_[t.id]||[],g);if(a.partial&&!a.entityIds.length)continue;const r=a.entityIds,d=Un(s,t,r);let p=l.has(d)||"Group"===t.model||/scene/i.test(t.model||"")||/bridge/i.test((t.model||"")+(t.name||""))||"myheat"===d&&!!t.via_device_id;if(!p&&h&&u.has(n)){const e=(t.name_by_user||t.name||"").trim();"mdi:lightbulb"===bo(s,e,t.model,r,c)&&(p=!0)}p&&f.push("device:"+t.id)}return f}({hass:this.hass,registry:this._haRegistry,areaToSpace:Object.fromEntries(Object.entries(this._areaToSpace).map(([t,e])=>[t,e.space])),markers:this._markers,settings:this._settings,excluded:this._excluded,firstSpaceId:this._model[0]?.id||"",iconRules:this._iconRules});if(!e.length&&t.settings?.filter_seeded)return;t.markers=t.markers||[];const i=[];for(const s of e){const e="h"+s.slice(s.indexOf(":")+1);t.markers.push({id:e,binding:s,hidden:!0}),i.push(s.slice(s.indexOf(":")+1))}const s={...t.settings||{},filter_seeded:!0};delete s.show_all,i.length&&Array.isArray(s.new_device_ids)&&(s.new_device_ids=s.new_device_ids.filter(t=>!i.includes(t))),t.settings=s,this._regSignature="",this._maybeRebuildDevices(),this._saveConfig(),this.requestUpdate()}get _iconRules(){const t=this._settings.icon_rules;if(!t||!Array.isArray(t)||!t.length)return;const e=JSON.stringify(t);return e!==this._rulesCompiledSrc&&(this._rulesCompiledSrc=e,this._rulesCompiled=Jt(t)),this._rulesCompiled}get _fillColors(){return ps(this._settings)}get _excluded(){const t=this._settings.exclude_integrations;return t?new Set(t):Yt}willUpdate(t){t.has("_serverCfg")&&this._cfgEpoch++,this._syncEmptySpaceState(),t.has("hass")&&this.hass&&(this._hassSequence++,this._renderSnapshotAt=Date.now(),this._continuity.note("hass-snapshot"),this._ensureHaRegistryAuthority(),this._planHassMemo=null,this._hookConnection(),!this._loadOk&&!this._loading&&this._loadTries<8&&this._loadFromServer(),this._maybeRebuildDevices(),this._vacTick(),this._activityTick()),this._continuity.hasCompleteFrame&&"steady"===this._continuity.state&&this._continuity.refreshCompleteFrame(this._visualFrameFingerprint()),this._captureRenderDeviceSnapshot()}updated(){this._pruneDevicePressFeedback(),this._syncDayCycleClock(),this._warmSnapshot(),this._dtMeasure();const t=this._stageEl;t&&!this._roViewport&&(this._roViewport=new ResizeObserver(()=>this._refitView()),this._roViewport.observe(t)),t&&this._booting&&!this._bootTimer&&this._bootWatch();const e=this.renderRoot.querySelector(".hdr");if(e&&t&&!this._roHdr){const i=()=>{const e=this.renderRoot.querySelector("ha-card");if(!e)return;const i=t.getBoundingClientRect().top-e.getBoundingClientRect().top,s=Math.min(Math.max(e.getBoundingClientRect().top,0),120),n=Math.round(i+s);n>=0&&n!==this._hdrH&&(this._hdrH=n),n>=0&&!this._booting&&!this._config?.kiosk&&t.clientHeight>0&&this._warmPatch({hdrH:n,stageH:t.clientHeight})};this._roHdr=new ResizeObserver(()=>requestAnimationFrame(i)),this._roHdr.observe(e),this._onWinResize=()=>requestAnimationFrame(i),window.addEventListener("resize",this._onWinResize),i()}if(t&&!this._view&&this._refitView(),this._editorSecondary.afterRender(),this._settleContinuityFrame(),this._serverStorage&&this._loadOk&&0===this._model.length&&!this._spaceDialog&&!this._importDialog&&!this._onboardingShown){this._onboardingShown=!0;const t=function(t){const e=t?.floors;if(!e||"object"!=typeof e)return[];const i=[];for(const t of Object.values(e))t&&t.floor_id&&i.push({id:t.floor_id,name:t.name||t.floor_id,level:t.level??null});return i.sort((t,e)=>{const i=t.level??1e9,s=e.level??1e9;return i!==s?i-s:t.name.localeCompare(e.name)}),i}(this.hass);t.length?this._importDialog={floors:t.map(t=>({...t,checked:!0}))}:this._openSpaceDialog("create")}}_adoptStructuralResponses(t,e,i){const s=t?.config,n=s&&Array.isArray(s.spaces)?s:null,o=Dh(n),a=o!==(this._cfgContentFingerprint||Dh(this._serverCfg));if(a&&(this._geometryHistory.clear(),this._serverCfg&&this._clearGeometryGesture(),this._serverCfg=n,this._cfgContentFingerprint=o),this._cfgRev=t?.rev??this._cfgRev,t&&("virtual_lights"in t||"config"in t)){const e=mn(this._virtualLights,t.virtual_lights,this._cfgRev,"virtual_lights"in t);vn(e)!==vn(this._virtualLights)&&(this._virtualLights=e,this._capturedSnapshotVirtual="")}let r=!1;if(void 0!==e||void 0!==i){const t=i??e?.layout??{},s=Dh(t);r=s!==(this._layoutContentFingerprint||Dh(this._layout)),r&&(this._layout=t,this._layoutContentFingerprint=s),this._layoutRev=e?.rev??this._layoutRev}return this._canOptimizeUndo=!(!t?.can_optimize_undo&&!e?.can_optimize_undo),this._undoKind=t?.undo_kind||e?.undo_kind||null,"boolean"==typeof t?.can_write&&(this._serverCanWrite=t.can_write),a&&this._continuity.note("config-candidate",{configRev:this._cfgRev}),r&&this._continuity.note("layout-candidate",{layoutRev:this._layoutRev}),{configChanged:a,layoutChanged:r}}_resumePendingNavMode(){if(!this._pendingNavMode||!this._canEdit||this._config?.kiosk)return!1;const t=this._pendingNavMode;return this._pendingNavMode=null,this._setMode(t,!1),!0}async _loadFromServer(){this._loading=!0,this._loadTries++;const t=this._space,e=!!this._view;try{const[i,s]=await Promise.all([this.hass.callWS({type:"houseplan/config/get"}),this.hass.callWS({type:"houseplan/layout/get"})]),n=i?.config&&Array.isArray(i.config.spaces)?i.config:null,o=Dh(n)!==(this._cfgContentFingerprint||Dh(this._serverCfg))||Dh(s?.layout??{})!==(this._layoutContentFingerprint||Dh(this._layout));if(o){if(!await this._signer.prepareImage(this.hass,this._candidateBackdrop(n)))return this._continuity.note("asset-failed"),void this._scheduleLoadRetry(!0)}o&&this._continuity.hasCompleteFrame&&"steady"===this._continuity.state&&this._beginContinuityCandidate("structural-response",!0),this._connectionWasLost=!1,this._serverStorage=!0,"boolean"==typeof i?.can_write&&(this._serverCanWrite=i.can_write),this._canOptimizeUndo=!(!i?.can_optimize_undo&&!s?.can_optimize_undo),this._adoptStructuralResponses(i,s),this._adoptInitialSpace(this._model,!0),this._resumePendingNavMode(),this._cacheSnapshot(),this._warmVpArmed&&this._space===this._warmVp?.space?this._warmVpArmed=!1:e&&this._space===t||this._restoreZoom(),this._loadOk=!0,this.hass.callWS({type:"houseplan/trail/get"}).then(t=>{this._vacSrvTrails=t?.trails||{},this.requestUpdate()}).catch(()=>{}),this._ensureLiveSyncSubscriptions()}catch(t){if(this._serverCfg)this._scheduleLoadRetry(!0);else if(this._loadTries>=8){this._serverStorage=!1;try{this._layout=JSON.parse(localStorage.getItem(am)||"{}")||{}}catch{this._layout={}}}}finally{this._loading=!1,this._continuityDataReady=!0,this._regSignature="",this._maybeRebuildDevices(),this.requestUpdate()}}_ensureLiveSyncSubscriptions(){const t=this.hass?.connection;if(!t)return;if(t!==this._liveSyncConnection&&(this._unsubCfg?.(),this._unsubCfg=null,this._unsubLayout?.(),this._unsubLayout=null,this._unsubTrail?.(),this._unsubTrail=void 0,this._unsubVirtual?.(),this._unsubVirtual=null,this._liveSyncGeneration++,this._liveSyncAttempt=null,this._liveSyncConnection=t),this._liveSyncAttempt)return;const e=this._liveSyncGeneration,i=[],s=(s,n,o,a)=>{s()||i.push(async()=>{const i=await t.subscribeEvents(a,o);e===this._liveSyncGeneration&&this.isConnected&&this.hass?.connection===t&&!s()?n(i):i?.()})};if(s(()=>this._unsubCfg,t=>{this._unsubCfg=t},"houseplan_config_updated",t=>{const e=Number(t?.data?.rev??-1);e!==this._cfgRev&&this._reloadConfigOnly(!1,e)}),s(()=>this._unsubTrail,t=>{this._unsubTrail=t},"houseplan_trail_updated",async()=>{try{const t=await this.hass.callWS({type:"houseplan/trail/get"});this._vacSrvTrails=t?.trails||{},this.requestUpdate()}catch{}}),s(()=>this._unsubLayout,t=>{this._unsubLayout=t},"houseplan_layout_updated",t=>this._onLayoutEvent(Number(t?.data?.rev??-1))),s(()=>this._unsubVirtual,t=>{this._unsubVirtual=t},"houseplan_virtual_light_updated",t=>{const e=wn(this._virtualLights,t?.data);e!==this._virtualLights&&(this._virtualLights=e,this._capturedSnapshotVirtual="",this._cacheSnapshot(),this.requestUpdate())}),!i.length)return;const n=function(t){return Promise.allSettled(t.map(t=>Promise.resolve().then(t)))}(i).then(()=>{});this._liveSyncAttempt=n,n.finally(()=>{this._liveSyncAttempt===n&&(this._liveSyncAttempt=null)})}async _reloadConfigOnly(t=!1,e){if(!t){if(void 0!==e&&e<=this._cfgRev)return;if(this._saveConfigDebounced.pending()&&this._saveConfigDebounced.flush(),this._cfgWriting)return clearTimeout(this._reloadRetry),void(this._reloadRetry=window.setTimeout(()=>this._reloadConfigOnly(!1,e),400))}this._beginContinuityCandidate("config-reload",!1);try{const t=await this.hass.callWS({type:"houseplan/config/get"}),e=t?.config&&Array.isArray(t.config.spaces)?t.config:null;if(Dh(e)!==(this._cfgContentFingerprint||Dh(this._serverCfg))&&!await this._signer.prepareImage(this.hass,this._candidateBackdrop(e)))return this._continuity.note("asset-failed"),void this._scheduleLoadRetry(!0);const i=this._space;this._adoptStructuralResponses(t),this._adoptInitialSpace(this._model,!0),this._resumePendingNavMode(),this._cacheSnapshot(),this._space!==i&&this._restoreZoom(),this._regSignature="",this._maybeRebuildDevices(),this.requestUpdate()}catch(t){this._showToast(this._t("toast.cfg_reload_failed",{err:this._errText(t)}))}finally{this._continuityDataReady=!0,this.requestUpdate()}}_scheduleLoadRetry(t=!1){if(void 0!==this._loadRetryTimer)return;const e=Math.min(8e3,500*2**Math.min(4,Math.max(1,this._loadTries-7)));this._loadRetryTimer=window.setTimeout(()=>{this._loadRetryTimer=void 0,!t&&this._loadOk||this._loading||!this.hass||this._loadFromServer()},e)}_ensureHaRegistryAuthority(){const t=this.hass?.connection||null;t&&t!==this._haRegistryConnection&&(this._haRegistryRelease?.(),this._haRegistryConnection=t,this._haRegistryRev=-1,this._haBindingCacheKey="",this._planHassMemo=null,this._haRegistryRelease=In(this.hass,this._onHaRegistryUpdate),this._onHaRegistryUpdate())}get _haRegistry(){return An(this.hass)}get _planHass(){const t=this._haRegistry,e=En(this.hass,t),i=this._planHassMemo;if(i&&i.hass===this.hass&&i.sig===e)return i.active;const s=On(this.hass,t),n=Nn(this.hass,t);return this._planHassMemo={hass:this.hass,sig:e,active:s,full:n},s}_captureRenderDeviceSnapshot(){if(!this.hass)return;const t=Date.now(),e=[...this._activityRt.entries()].map(([e,i])=>`${e}:${i.gen}:${i.flashTs}:`+(i.flashKind&&(i.expiresAt||i.flashTs+$u)>t?1:0)).join("|"),i=vn(this._virtualLights);if(this._capturedSnapshotSequence===this._hassSequence&&this._capturedSnapshotDevices===this._devices&&this._capturedSnapshotLayout===this._layout&&this._capturedSnapshotConfigEpoch===this._cfgEpoch&&this._capturedSnapshotVirtual===i&&this._capturedSnapshotActivity===e)return;const s=this._planHass,n=new Map,o=new Map,a=new Set(["sun.sun"]);this._vacFit?.source&&a.add(this._vacFit.source);const r=new Set,l=new Set,c=t=>{if(!t)return;const e=t.indexOf(":");if(e<0)return void a.add(t);const i=t.slice(0,e),s=t.slice(e+1);"device"===i?r.add(s):"entity"===i&&a.add(s)};for(const t of this._model)for(const e of t.rooms)e.area&&l.add(e.area),c(e.settings?.temp_source),c(e.settings?.hum_source);for(const t of this._serverCfg?.spaces||[])for(const e of t.openings||[])for(const t of mi(e))a.add(t);for(const t of this._serverCfg?.spaces||[])for(const e of t.decor||[])if("text"===e.kind){for(const t of String(e.text||"").matchAll(/\{([^{}\r\n]+)\}/g)){const e=Yi(t[1]);e?.entity&&a.add(e.entity)}e.entity&&a.add(e.entity),o.set(`decor:${t.id}:${e.id}`,ts(e.text,e,s,t=>!!s.entities?.[t]&&!!s.states?.[t]&&!ko(s,t,wo(this._markers))))}const h=ho(s,this._devices,null,this._virtualLights);for(const t of this._devices){for(const e of[!1,!0])n.set(ru(t.id,e),su(s,t,{liveStates:!1!==this._config?.live_states,showTemperature:!1!==this._config?.show_temperature,showSignal:e,activityRuntime:this._activityRt.get(t.id),sourceDetails:!1,lightDevices:this._devices,lightSources:h,registryHass:this._fullRegistryHass,reducedMotion:this._reducedMotion}));if(this._isVacDev(t)){const e=this._vacSource(t,s),i=e?Uh(s?.states?.[e]?.attributes):null,n=this._vacRt.get(t.id);o.set(`vacuum:${t.id}`,{source:e,telemetry:i,mapId:i?this._vacMapId(t,i,s):null,runtime:n?{trail:n.trail,lastTs:n.lastTs,moving:n.moving,jump:n.jump}:null,server:this._vacSrvTrails[t.id]||null})}}const d=au({sourceSequence:this._hassSequence,hass:s,devices:this._devices,presentations:n,positions:(p=this._model.length>0,u=this._devices,_=t=>this._livePos(t),p?new Map(u.map(t=>[t.id,_(t)])):new Map),facts:o,entityIds:a,deviceIds:r,areaIds:l});var p,u,_;this._capturedSnapshotSequence=this._hassSequence,this._capturedSnapshotDevices=this._devices,this._capturedSnapshotLayout=this._layout,this._capturedSnapshotActivity=e,this._capturedSnapshotConfigEpoch=this._cfgEpoch,this._capturedSnapshotVirtual=i,this._visibleDeviceSnapshot&&"steady"!==this._continuity.state?this._candidateDeviceSnapshot=d:(this._visibleDeviceSnapshot=d,this._candidateDeviceSnapshot=null)}get _renderDeviceSnapshot(){return this._stagedDeviceSnapshotToken===this._continuity.token?this._candidateDeviceSnapshot||this._visibleDeviceSnapshot:this._visibleDeviceSnapshot||this._candidateDeviceSnapshot}get _renderPlanHass(){return this._renderDeviceSnapshot?.hass||this._planHass}get _renderDevices(){return this._renderDeviceSnapshot?.devices||this._devices}get _fullRegistryHass(){return this._planHass,this._planHassMemo?.full||this.hass}_bindingStatus(t){return Bn(this.hass,t,this._haRegistry)}houseplanDiagnostics(){const t=function(t){const e=An(t);return{access:e.access,authoritative:e.authoritative,revision:e.revision,lastSuccess:e.lastSuccess,error:e.error}}(this.hass),e={active:0,ha_disabled:0,orphaned:0,unverified:0};for(const t of this._markers)t.removed||"virtual"===t.binding||e[this._bindingStatus(t.binding).kind]++;return{registry:{...t,lastSuccessAgeMs:t.lastSuccess?Math.max(0,Date.now()-t.lastSuccess):null},bindings:e}}_openBindingInHa(t){const[e,i]=t.split(":");if(i)if("device"!==e){if("entity"===e){const t=this._fullRegistryHass.entities?.[i];t?.device_id&&ym("/config/devices/device/"+encodeURIComponent(t.device_id))}}else ym("/config/devices/device/"+encodeURIComponent(i))}_bindingHasHaPage(t){const[e,i]=t.split(":");return!!i&&("device"===e||"entity"===e&&!!this._fullRegistryHass.entities?.[i]?.device_id)}_toggleMarkerDialogVisibility(){const t=this._markerDialog;if(!t)return;const e="ha"===t.bindingMode?this._bindingStatus(t.binding):null,i=t.hideFromPlan||"ha_disabled"===e?.kind;i&&"ha_disabled"===e?.kind?this._showToast(this._t("entity"===e.reason?"toast.ha_disabled_show_entity":"toast.ha_disabled_show_device")):i&&"unverified"===e?.kind?this._showToast(this._t("toast.ha_binding_unverified")):this._markerDialog={...t,hideFromPlan:!i}}_hookConnection(){const t=this.hass?.connection;t&&t!==this._connHooked&&(this._connHooked?.removeEventListener?.("ready",this._onConnReady),this._connHooked?.removeEventListener?.("disconnected",this._onConnLost),this._connHooked?.removeEventListener?.("reconnect-error",this._onConnLost),t.addEventListener?.("ready",this._onConnReady),t.addEventListener?.("disconnected",this._onConnLost),t.addEventListener?.("reconnect-error",this._onConnLost),this._connHooked=t)}_display(t){return this._signer.display(this.hass,t)}_resign(){this._signer.resign(this.hass,Is(this._serverCfg))}_onLayoutEvent(t){t<=this._layoutRev||(clearTimeout(this._layoutSyncTimer),this._layoutSyncTimer=window.setTimeout(()=>{t<=this._layoutRev||this._reloadLayoutOnly()},200))}_noteLayoutRev(t){const e=t?.rev;"number"==typeof e&&e>this._layoutRev&&(this._layoutRev=e)}async _reloadLayoutOnly(){if(!this._serverStorage||!this.hass?.callWS)return;this._beginContinuityCandidate("layout-reload",!1);const t=new Map;for(const e of this._dirtyPos)this._layout[e]&&t.set(e,this._layout[e]);this._persistLayout.pending()&&this._persistLayout.flush();for(const[e,i]of this._sentPos)t.set(e,i);try{const e=await this.hass.callWS({type:"houseplan/layout/get"}),i={...e?.layout||{}};for(const[e,s]of t)i[e]=s;const s=Dh(i);s!==(this._layoutContentFingerprint||Dh(this._layout))&&(this._layout=i,this._layoutContentFingerprint=s),this._layoutRev=e?.rev??this._layoutRev,this._canOptimizeUndo=!!e?.can_optimize_undo,this._undoKind=e?.undo_kind||null,this._cacheSnapshot(),this.requestUpdate()}catch{}finally{this._continuityDataReady=!0,this.requestUpdate()}}_maybeRebuildDevices(){const t=this.hass;if(!t?.devices||!t?.entities||!t?.areas)return;const e=this._haRegistry,i=En(t,e)+":"+Object.keys(t.areas).length+":"+(this._norm?"n":"l")+":"+ra(t,this._config?.language);if(i===this._regSignature&&this._devices.length)return;this._regSignature=i;const s=new Map(this._devices.map(t=>[t.id,t.bindingStatus?.kind||"active"]));this._devices=So({hass:t,registry:e,areaToSpace:Object.fromEntries(Object.entries(this._areaToSpace).map(([t,e])=>[t,e.space])),markers:this._markers,settings:this._settings,excluded:this._excluded,showAll:this._showAll,firstSpaceId:this._model[0]?.id||"",loc:t=>this._t(t),iconRules:this._iconRules});const n=this._markers.filter(t=>!t.removed&&"virtual"!==t.binding).map(t=>t.binding).sort(),o=e.revision+":"+n.join("|");if(e.authoritative&&o!==this._haBindingCacheKey){const i=new Map;for(const s of n)i.set(s,Bn(t,s,e));!function(t){if("undefined"==typeof localStorage||!t.size)return;const e=Ln(),i=Date.now();for(const[s,n]of t)"active"===n.kind?e[s]={kind:"active",ts:i}:"ha_disabled"===n.kind&&(e[s]={kind:"ha_disabled",reason:n.reason,ts:i});const s=Object.fromEntries(Object.entries(e).sort((t,e)=>e[1].ts-t[1].ts).slice(0,1500));Mn=s;try{localStorage.setItem(Sn,JSON.stringify(s))}catch{}}(i),this._haBindingCacheKey=o}this._defPos=this._defaultPositions(),this._syncNewDevices(),this._seedHiddenDevices(),this._syncActivityRuntime();const a=new Set(this._devices.filter(t=>!t.hidden).map(t=>t.id));for(const t of this._vacRt.keys())a.has(t)||this._vacRt.delete(t);if(this._infoCard){const t=this._devices.find(t=>t.id===this._infoCard.id);this._infoCard=t&&"ha_disabled"!==t.bindingStatus?.kind?t:null}const r=this._devices.some(t=>"ha_disabled"===t.bindingStatus?.kind&&"ha_disabled"!==s.get(t.id));r&&("ha_disabled"!==this._infoCard?.bindingStatus?.kind&&"ha_disabled"!==this._devices.find(t=>t.id===this._infoCard?.id)?.bindingStatus?.kind||this._closeInfoCard(),this._drag&&"ha_disabled"===this._devices.find(t=>t.id===this._drag.id)?.bindingStatus?.kind&&(this._drag=null),clearTimeout(this._holdTimer),this._holdFired=!1,this._tip=null,this._tapConfirm=null),this._nativeMoreInfoEntity&&!this._planEntityAvailable(this._nativeMoreInfoEntity)&&(vm(this,"hass-more-info",{entityId:null}),this._nativeMoreInfoEntity=null)}_syncNewDevices(){if(!this._norm||!this._loadOk||!this._serverCfg)return;const t=this._devices.filter(t=>!t.marker&&!t.virtual).map(t=>t.id).sort(),e=t.join(",");if(e===this._newSyncKey)return;this._newSyncKey=e;const i=this._settings,{fresh:s,known:n}=function(t,e){if(!Array.isArray(e))return{fresh:[],known:[...t]};const i=new Set(e),s=t.filter(t=>!i.has(t));return{fresh:s,known:s.length?[...e,...s]:e}}(t,i.known_devices);if(!Array.isArray(i.known_devices)||s.length){const t=[...new Set([...i.new_device_ids||[],...s])];this._serverCfg={...this._serverCfg,settings:{...i,known_devices:n,new_device_ids:t}},this._saveConfig()}}get _newIds(){const t=this._settings.new_device_ids;return new Set(Array.isArray(t)?t:[])}_ackNewDevice(t){if(!this._newIds.has(t)||!this._serverCfg)return;const e=this._settings;this._serverCfg={...this._serverCfg,settings:{...e,new_device_ids:(e.new_device_ids||[]).filter(e=>e!==t)}},this._saveConfig(),this.requestUpdate()}get _markers(){return this._serverCfg?.markers||[]}_roomLqi(t){if(!t)return null;const e=[];for(const i of this._renderDevices){if(i.area!==t||i.virtual)continue;const s=_o(this._renderPlanHass,i.entities);null!=s&&e.push(s)}return zi(e)}_roomBounds(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}}_defaultPositions(){const t={},e=this._config?.icon_size??2.5;for(const i of this._model){const s=e/100*Lc(i)*1.3;for(const e of i.rooms){if(!e.area)continue;const n=this._devices.filter(t=>t.area===e.area&&t.space===i.id);if(!n.length)continue;const o=this._roomBounds(e),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(n.length*r/Math.max(l,1)))),h=Math.ceil(n.length/c),d=r/c,p=l/Math.max(h,1),u=n.map((t,e)=>({x:o.x+a+d*(e%c+.5),y:o.y+a+p*(Math.floor(e/c)+.5)}));Ni(u,o,s,.5*a),n.forEach((e,i)=>t[e.id]=Mc(u[i]))}}return t}_pos(t){const e=this._renderDeviceSnapshot?.positions.get(t.id);return e?{x:e.x,y:e.y}:this._livePos(t)}_livePos(t){const e=this._spaceModelById(t.space),i=this._layout[t.id];if(i)if(this._norm){if(i.s===t.space)return{x:i.x*um,y:i.y*um}}else if(void 0===i.s)return{x:i.x,y:i.y};return this._defPos[t.id]?this._defPos[t.id]:e?Mc(Hc(e)):{x:500,y:500}}_savePos(t,e,i){if(this._spaceModelById(t.space)){if(this._norm){const s=this._gridPitch,n=Math.round(e/s)*s,o=Math.round(i/s)*s,a=this._layout[t.id]?.k;this._layout={...this._layout,[t.id]:{s:t.space,x:Dc(n/um),y:Dc(o/um),...a?{k:a}:{}}}}else this._layout={...this._layout,[t.id]:{x:Math.round(e),y:Math.round(i)}};this._dirtyPos.add(t.id),this._persistLayout()}}_visualSamples(t){return Zp(this._renderPlanHass,t,this._renderDevices,void 0,this._fullRegistryHass).samples}_devicePresentation(t,e=!1!==this._config?.show_signal,i=!1){const s=i?null:this._renderDeviceSnapshot?.presentations.get(ru(t.id,e));return s||su(this._renderPlanHass,t,{liveStates:!1!==this._config?.live_states,showTemperature:!1!==this._config?.show_temperature,showSignal:e,designPreview:i,activityRuntime:this._activityRt.get(t.id),sourceDetails:!1,lightDevices:this._renderDevices,registryHass:this._fullRegistryHass,reducedMotion:this._reducedMotion})}_deviceVisual(t){return this._devicePresentation(t).visual}_stateClass(t,e=this._deviceVisual(t)){const i=this._devicePresentation(t);return i.effectiveHidden?"":("icon_ripple"!==i.display||!1===this._config?.live_states||"alarm"===e.status||e.activity,iu({...i,visual:e}).join(" "))}_liveTemp(t){if(!this._config?.show_temperature)return null;if(!0===t.marker?.use_climate_temp){const e=mo(this._renderPlanHass,t.entities);if(null!=e)return e}return"mdi:thermometer"!==t.icon&&"mdi:air-filter"!==t.icon?null:go(this._renderPlanHass,t.entities)}_bindingEntities(t){if("virtual"===t||!t)return[];const e=this._bindingStatus(t);return"active"===e.kind?e.enabledEntityIds:e.allEntityIds}_bindingHasClimate(t){return this._bindingEntities(t).some(t=>t.startsWith("climate."))}_bindingHasAlarm(t){return this._bindingEntities(t).some(t=>{const e=this._planHass?.states?.[t]||this.hass?.states?.[t],i=this._fullRegistryHass.entities[t]||this.hass?.entities?.[t];return Bs(t.split(".")[0],e?.attributes?.device_class||i?.device_class||i?.original_device_class)})}_liveHum(t){return this._config?.show_temperature&&t.primary&&fo(this.hass,t.primary)?vo(this.hass,t.entities):null}_deviceBindingActive(t,e=!0){if(t.virtual||"virtual"===t.bindingKind)return!0;if(!t.bindingKind||!t.bindingRef)return!1;const i=this._bindingStatus(`${t.bindingKind}:${t.bindingRef}`);return"active"===i.kind||(e&&this._showToast(this._t("ha_disabled"===i.kind?"toast.ha_disabled_action":"toast.ha_binding_unverified")),!1)}_openMoreInfo(t){t?this._planEntityAvailable(t)?(this._nativeMoreInfoEntity=t,vm(this,"hass-more-info",{entityId:t})):this._showToast(this._t("toast.ha_disabled_action")):this._showToast(this._t("toast.no_entity"))}_interruptViewGesture(t,e){if(clearTimeout(this._holdTimer),clearTimeout(this._kioskHoldTimer),void 0!==t)for(const i of[e,this._stageEl])try{i?.hasPointerCapture?.(t)&&i.releasePointerCapture(t)}catch{}this._pointers.clear(),this._panStart=null,this._panLock=null,this._pinchStart=null,this._swipeStart=null}_closeInfoCard(){this._interruptViewGesture(),this._holdFired=!1,this._infoCard=null}_ctxDevice(t,e){"view"===this._mode&&(t.preventDefault(),t.stopPropagation(),this._deviceBindingActive(e)&&(e.primary?this._openMoreInfo(e.primary):this._infoCard=e))}_clickDevice(t,e){if(t.stopPropagation(),this._drag?.moved||this._suppressClick||this._holdFired)return;if("plan"===this._mode)return;if("devices"===this._mode)return void this._openMarkerDialog(e);const i=this._devices.find(t=>t.id===e.id);if(!i)return;const s=bd(i.tapAction,i.primary?.split(".")[0]),n=(t,e)=>{i.marker?.tap_confirm?this._tapConfirm={kind:"run",text:t,exec:e}:e()};if("toggle"===s){const t=this._toggleIntent(i);if(!t||!Md(t))return;const e=t=>{const e=Md(t);if(!e)return;if("virtual-light"===e.kind)return this._startDevicePressFeedback(i.id),void this.hass.callWS({type:"houseplan/virtual_light/toggle",marker_id:e.markerId}).then(t=>{const e=wn(this._virtualLights,t);e!==this._virtualLights&&(this._virtualLights=e,this._capturedSnapshotVirtual="",this._cacheSnapshot(),this.requestUpdate())}).catch(t=>this._showToast(this._t("toast.virtual_light_toggle_failed",{err:this._errText(t)})));const{command:s}=e;this._startDevicePressFeedback(i.id),this.hass.callService(s.domain,s.service,s.data).catch(t=>this._showToast(this._t("toast.error",{err:this._errText(t)})))},s=((o=t).targets.length?o.targets:o.skippedTargets).map(t=>t.name||t.entityId||t.ref).join(", ")||i.name;if(i.marker?.tap_confirm){const n=this._toggleConfirmationLines(t);if(!n.length)return;this._tapConfirm={kind:"toggle",text:this._t("confirm.tap_toggle",{name:s}),lines:n,initialIntent:t,deviceId:i.id,exec:()=>{const s=this._devices.find(t=>t.id===i.id),n=s?this._toggleIntent(s):null;n&&Cd(t,n)?e(n):this._showToast(this._t("toast.tap_target_changed"))}}}else e(t);return}var o;if("info"===s)return this._interruptViewGesture(),void(this._infoCard=i);if(this._deviceBindingActive(i)){if("run"===s){const t=i.marker?.tap_target||"",e=function(t){const e=String(t||"").split(".")[0];return"automation"===e?{domain:"automation",service:"trigger"}:"script"===e?{domain:"script",service:"turn_on"}:"scene"===e?{domain:"scene",service:"turn_on"}:null}(t),s=this.hass.states[t];if(!e||!s)return void this._showToast(this._t("toast.run_target_missing"));const o=s.attributes?.friendly_name||t;return void n(this._t("confirm.tap_run",{name:o}),()=>{this._deviceBindingActive(i)&&this._planEntityAvailable(t)&&(this._startDevicePressFeedback(i.id),this.hass.callService(e.domain,e.service,{entity_id:t}).then(()=>{this._stampActivity(i.id,"event",this._activitySourceKey(i)),this.requestUpdate(),this._showToast(this._t("toast.run_started",{name:o}))}).catch(t=>this._showToast(this._t("toast.error",{err:this._errText(t)}))))})}"more-info"===s&&i.primary?this._openMoreInfo(i.primary):this._infoCard=i}}_keyDevice(t,e){"Enter"!==t.key&&" "!==t.key||"view"!==this._mode&&"devices"!==this._mode||(t.preventDefault(),this._clickDevice(t,e))}_startDevicePressFeedback(t){const e=[...this.renderRoot.querySelectorAll(".dev[data-id]")].find(e=>e.dataset.id===t),i=e?.querySelector(".device-shell");if(!i||"function"!=typeof i.animate)return;const s=Number.parseFloat(this.ownerDocument.defaultView?.getComputedStyle(i).scale||""),n=Number.isFinite(s)?Math.max(.95,Math.min(1,s)):1;this._devicePressAnimations.get(t)?.cancel();const o=this._reducedMotion?[{outlineColor:"transparent",outlineStyle:"solid",outlineWidth:"0px"},{outlineColor:"var(--hp-accent, #3ea6ff)",outlineStyle:"solid",outlineWidth:"2px",outlineOffset:"2px",offset:.5},{outlineColor:"transparent",outlineStyle:"solid",outlineWidth:"0px"}]:[{scale:String(n)},{scale:"0.95",offset:.5},{scale:"1"}],a=i.animate(o,{duration:200,easing:"cubic-bezier(.22,.61,.36,1)"});this._devicePressAnimations.set(t,a);const r=()=>{this._devicePressAnimations.get(t)===a&&this._devicePressAnimations.delete(t)};a.addEventListener("finish",r,{once:!0}),a.addEventListener("cancel",r,{once:!0})}_cancelDevicePressFeedback(){for(const t of this._devicePressAnimations.values())t.cancel();this._devicePressAnimations.clear()}_pruneDevicePressFeedback(){if(!this._devicePressAnimations.size)return;const t=new Set([...this.renderRoot.querySelectorAll(".dev[data-id]")].map(t=>t.dataset.id||""));for(const[e,i]of this._devicePressAnimations)t.has(e)||(i.cancel(),this._devicePressAnimations.delete(e))}_t(t,e){return la(ra(this.hass,this._config?.language),t,e)}get _colorPickerLabels(){return{title:this._t("color_picker.title"),hue:this._t("color_picker.hue"),saturation:this._t("color_picker.saturation"),value:this._t("color_picker.value"),hex:this._t("color_picker.hex"),invalidHex:this._t("color_picker.invalid_hex")}}_help(t){const e=`${t}.aria`,i=ra(this.hass,this._config?.language);return ca(i,t)&&ca(i,e)?W``:G}get _stageEl(){return this.renderRoot.querySelector(".stage")}_contentItems(t){const e=[];for(const i of this._devices){if(i.space!==t.id||i.hidden)continue;const s=this._pos(i);e.push({minX:s.x,minY:s.y,maxX:s.x,maxY:s.y})}if(t.id===this._space){for(const t of this._openingsR){const i=Number(t.angle)*Math.PI/180,s=Math.cos(i)*t.rlen/2,n=Math.sin(i)*t.rlen/2,o=Rc([[t.rx-s,t.ry-n],[t.rx+s,t.ry+n]]);o&&e.push(o)}const i=this._decorH;for(const t of this._decorList){const s=Rc("line"===t.kind?[[t.x1*um,t.y1*i],[t.x2*um,t.y2*i]]:"text"===t.kind?[[t.x*um,t.y*i]]:ur({x:t.x*um,y:t.y*i,w:t.w*um,h:t.h*i,angle:t.angle}));s&&e.push(s)}for(const i of this._physicalBodiesR(t)){const t=Rc(i);t&&e.push(t)}}return Ac(t,e)}_frameOf(){const t=this._spaceModel();if(!t){this._frame=null;const t={x:0,y:0,w:um,h:um};return{rect:t,all:t,outliers:0}}const e=this._frame,i="view"!==this._mode;if(e&&e.id===t.id&&this._bdDrag)return e;if(e&&e.id===t.id&&e.model===t&&e.layout===this._layout&&e.devs===this._devices&&e.far===this._showFar&&e.grow===i)return e;const s=Oc(this._contentItems(t));let n=s.all||Nc(t),o=this._showFar?n:s.core||Nc(t);return e&&e.id===t.id&&i&&e.grow&&(o=gm(e.rect,o),n=gm(e.all,n)),this._frame={id:t.id,model:t,layout:this._layout,devs:this._devices,far:this._showFar,grow:i,rect:o,all:n,outliers:s.outliers},this._frame}_isoSource(){const t=this._spaceModel();if(!t)return null;const e=this._spaceWalls,i=this._openPairs().flatMap(t=>t.segs),s=this._openingsR.map((t,e)=>({id:String(t.id||e),sourceIndex:e,type:t.type,x:t.rx,y:t.ry,angle:Number(t.angle)||0,length:t.rlen>0?t.rlen:900,flipH:!!t.flip_h,flipV:!!t.flip_v})),n=hc(64,this._cellCm),o=hc(10,this._cellCm),a=`${t.id}|${function(t){let e=2166136261;const i=t=>{if("number"!=typeof t)if("string"!=typeof t)if("boolean"!=typeof t)if(Array.isArray(t)){e=vg(e,t.length);for(const e of t)i(e)}else{if(t&&"object"==typeof t){const e=t;for(const t of Object.keys(e).sort())i(t),i(e[t]);return}e=vg(e,-1)}else e=vg(e,t?1:0);else for(const i of t)e=vg(e,i.codePointAt(0)||0);else e=vg(e,t)};return i(t),e.toString(36)}({rooms:t.rooms,walls:e,openCuts:i,openings:s,partitions:t.partitions,roomDrafts:t.room_drafts,columns:t.wall_columns,cellCm:this._cellCm,gridPitch:this._gridPitch,wallKeyPitch:this._wallKeyPitch,camera:ag,wallHeight:n,floorEdgeHeight:o,algorithm:3})}`;return{key:a,build:()=>{const o=Jl(t,this._cellCm,this._gridPitch,2e-4*this._gridPitch,this._partitionOpeningCuts(t)).all,a=this._roomWallOpeningInputs(this._openingsR,t),r=e.length||o.length?Dl(t.rooms,e,i,a,this._wallKeyPitch,this._cellCm,this._gridPitch,um,o):null;if((e.length||o.length)&&!r)throw new Error("wall boolean geometry failed");const l=r?.paperGeom??Ml(t.rooms,e,i,this._wallKeyPitch,this._cellCm,this._gridPitch,um);if(!l)throw new Error("floor boolean geometry failed");const c=r?.openingIndex||Il(t.rooms,e,i,this._wallKeyPitch,this._cellCm,this._gridPitch,um),h=s.map(t=>{const i=this._openingsR[t.sourceIndex],s="gate"===t.type?!t.flipV:t.flipV,o=i?.partitionHost?Ed(i.partitionHost,s):e.length||"gate"===t.type?zl(c,{x:t.x,y:t.y,angle:t.angle,length:t.length,flip_v:s}):{ox:0,oy:0,cm:0,side:-1};return function(t,e=64){if(!(yg([t.x,t.y,t.angle,t.length,t.face.ox,t.face.oy,e])&&t.length>0&&e>0))throw new Error("invalid isometric opening input");const i=t.length/2;let s;if("passage"===t.type)s=[];else if("gate"===t.type){const n=10*t.face.side;s=[wg(t,0,[-i,0],[i,0],n,0,.88*e),wg(t,1,[i,0],[-i,0],-n,0,.88*e)]}else s="window"===t.type?[wg(t,0,[-i,0],[i,0],-90,.27*e,.78*e),wg(t,1,[i,0],[-i,0],90,.27*e,.78*e)]:[wg(t,0,[-i,0],[t.length,0],-90,0,.92*e)];return{id:t.id,sourceIndex:t.sourceIndex,type:t.type,leaves:Object.freeze(s.map(t=>Object.freeze(t)))}}({...t,face:o},n)});return{walls:r?.geom||[],floor:l,openings:Object.freeze(h)}}}}_isoSceneKey(){if(!this._labsIso||"view"!==this._mode)return null;try{return this._isoSource()?.key??null}catch{return`${this._space}|invalid`}}_isoScene(){const t=this._isoSource();if(!t)return null;const e=this._isoGeometryCache.get(t.key);if(e)return{key:t.key,...e};const i=this._frameOf().rect,s=t.build(),n=hc(64,this._cellCm),o=hc(10,this._cellCm),a=function(t){let e=1/0,i=1/0,s=-1/0,n=-1/0;for(const o of t)for(const t of o.leaves){const o=Math.hypot(t.closedVector[0],t.closedVector[1]);e=Math.min(e,t.hinge[0]-o),i=Math.min(i,t.hinge[1]-o),s=Math.max(s,t.hinge[0]+o),n=Math.max(n,t.hinge[1]+o)}return yg([e,i,s,n])?{x:e,y:i,w:s-e,h:n-i}:null}(s.openings),r=dg({rect:a?gm(i,a):i,wallHeight:n,openingHeight:n,floorDepth:o}),l=function(t,e=ag,i=64){if(!Number.isFinite(i)||i<0)throw new Error("invalid wall height");const s=[],n=[],o=[];let a=0;for(let r=0;r<(t||[]).length;r++){const l=t[r];for(let t=0;t<(l||[]).length;t++){const c=_g(l[t],t>0);if(!(c.length<3||Math.abs(ug(c))<1e-9)){s.push(gg(c,e,i)),a+=c.length;for(let s=0;st.depth-e.depth||t.polygon-e.polygon||t.ring-e.ring||t.edge-e.edge),{topPath:s.join(" "),sides:n,contactPath:o.join(" "),edgeCount:a}}(s.walls,ag,n),c={geometry:l,floor:fg(s.floor,o),openings:s.openings,frame:r};return em(this._isoGeometryCache,t.key,c,8),{key:t.key,...c}}_effectiveProjection(){if("iso"!==this._desiredProjection||!this._model.length)return"flat";const t=this._isoSceneKey()||`${this._space}|invalid`;if(this._isoFallback.has(t))return"flat";try{const t=this._isoScene();return t?(e="iso",i=t.key,s=this._isoFallback,"iso"===e&&i&&!s.has(i)?"iso":"flat"):"flat"}catch(e){if(!this._isoFallback.has(t)){this._isoFallback.add(t);const i=t.split("|");console.warn(`HOUSEPLAN ISO FALLBACK: #89, space ${this._space}, fingerprint ${i[i.length-1]}, ${e instanceof Error?e.message:"renderer error"}`)}return"flat"}var e,i,s}_scenePoint(t){return"iso"===this._renderProjection?lg(t,0):t}_floorView(t){if("iso"!==this._renderProjection)return t;const e=cg([t.x,t.y]),i=cg([t.x+t.w,t.y+t.h]);return{x:e[0],y:e[1],w:i[0]-e[0],h:i[1]-e[1]}}_baseVb(){if("iso"===this._effectiveProjection()){if(!this._spaceDisplayForRender().showBorders){const t=dg({rect:this._frameOf().rect,wallHeight:hc(64,this._cellCm)});return[t.x,t.y,t.w,t.h]}const t=this._isoScene()?.frame??this._frameOf().rect;return[t.x,t.y,t.w,t.h]}const t=this._frameOf().rect;return[t.x,t.y,t.w,t.h]}get _outliers(){return this._showFar?0:this._frameOf().outliers}_fitFar(){this._showFar=!0,this._frame=null,this._resetZoom()}_fitAll(){this._showFar=!0,this._frame=null,this._resetZoom()}_renderFarHint(){return this._kiosk||"view"!==this._mode||this._booting||!this._outliers?G:W`
${this._t("canvas.far_objects",{n:this._outliers})} -
`}_renderHomeArrow(){if(this._booting)return G;const t=this._view;if(!t||!t.w||!t.h)return G;const e=this._baseVb(),i=e[0],s=e[1],n=e[2],o=e[3];if(!(i+n<=t.x||i>=t.x+t.w||s+o<=t.y||s>=t.y+t.h))return G;const r=Math.atan2(s+o/2-(t.y+t.h/2),i+n/2-(t.x+t.w/2)),a=50+38*Math.cos(r),l=50+38*Math.sin(r);return W``}_stageAspect(){const t=this._stageEl,e=this._baseVb();return t&&t.clientHeight?t.clientWidth/t.clientHeight:e[2]/e[3]}_viewOr(t){return this._view&&this._view.w?this._view:Oi(t,this._stageAspect())}_roomLabelReferenceViewWidth(t){if(!this._markup)return t.w;const e=this._stageEl,i=this.renderRoot.querySelector(".editorchrome");if(!e||e.clientWidth<=0||e.clientHeight<=0)return t.w;const s=e.clientHeight+(i?.getBoundingClientRect().height||0);return s<=0?t.w:this._viewForModeTarget(this._zoom,void 0,void 0,e.clientWidth,s).w}_screenToVb(t,e){const i=this._stageEl,s=this._viewOr(this._baseVb()),n=i?.clientWidth||1,o=i?.clientHeight||1;return[s.x+t/n*s.w,s.y+e/o*s.h]}_clampView(t,e){const i=(t,e,i,s)=>{const n=1*Math.max(e,s),o=i-n,r=i+s-e+n;return Math.max(Math.min(o,r),Math.min(Math.max(o,r),t))};return{w:t.w,h:t.h,x:i(t.x,t.w,e.x,e.w),y:i(t.y,t.h,e.y,e.h)}}_applyView(t,e,i){const s=this._baseVb(),n=Oi(s,this._stageAspect()),o=Math.min(wm.ZOOM_MAX,Math.max(wm.ZOOM_MIN,t)),r=n.w/o,a=n.h/o,l=this._viewOr(s),c=e??l.x+l.w/2,h=i??l.y+l.h/2,d=this._clampView({x:c-r/2,y:h-a/2,w:r,h:a},n);return!(this._view&&Math.abs(this._zoom-o)<1e-9&&Math.abs(this._view.x-d.x)<1e-6&&Math.abs(this._view.y-d.y)<1e-6&&Math.abs(this._view.w-d.w)<1e-6&&Math.abs(this._view.h-d.h)<1e-6)&&("opening"===this._tool&&(this._cursorPt=null,this._clearOpeningPlacement(!1)),this._zoom=o,this._view=d,!0)}_bootWatch(){clearTimeout(this._bootTimer),this._bootStart=Date.now(),this._bootLastH=-1,this._bootLastChange=this._bootStart;const t=()=>{if(!this._booting)return;const e=Date.now(),i=this._stageEl?this._stageEl.clientHeight:0;i!==this._bootLastH&&(this._bootLastH=i,this._bootLastChange=e);const s=e-this._bootStart;s>=1200||s>=700&&i>0&&e-this._bootLastChange>=250?this._bootSettled():this._bootTimer=window.setTimeout(t,100)};this._bootTimer=window.setTimeout(t,100)}_bootSettled(){this._booting&&!this._bootSettling&&(this._bootSettling=!0,this._refitView(),this._bootSettleRaf=requestAnimationFrame(()=>{this._bootSettleRaf=0,this._finishBootSettled()}))}_finishBootSettled(){if(!this._booting)return;this._refitView(),this._booting=!1,this._bootSettling=!1;const t=this._stageEl?.clientHeight??0;!this._config?.kiosk&&t>0&&this._warmPatch({hdrH:this._hdrH,stageH:t,vp:this._warmViewportState()},!0),this._bootFading=!0,this._bootTimer=window.setTimeout(()=>{this._bootFading=!1},220),this._bootSoft=!0,clearTimeout(this._bootSoftTimer),this._bootSoftTimer=window.setTimeout(()=>{this._bootSoft=!1},Jg)}_bootSoftCancel(){this._bootSoft&&(clearTimeout(this._bootSoftTimer),this._bootSoft=!1)}_beginResumeSettle(){this._booting||this._resumeSettling||(this._modeTransitionPreparing?this._modeTransitionForceAtomic=!0:this._cancelModeTransition(!0),this._viewportInvalidAt=0,this._beginContinuityCandidate("warm-resume",!1),this._loading?this.requestUpdate():this._loadFromServer())}_refitView(){if(this._modeTransitionBusy)return;const t=this._stageEl;if(!t||"visible"!==document.visibilityState||t.clientWidth<=0||t.clientHeight<=0)return void(this._viewportInvalidAt||(this._viewportInvalidAt=Date.now()));const e=[t.clientWidth,t.clientHeight],i=this._lastValidStageSize,s=!!i&&Math.abs(i[0]-e[0])<=.5&&Math.abs(i[1]-e[1])<=.5,n=this._viewportInvalidAt?Date.now()-this._viewportInvalidAt:0;if(this._viewportInvalidAt=0,!i)return this._lastValidStageSize=e,void(this._view||this._applyView(this._zoom));s?this._pendingRefitSize=null:(this._pendingRefitSize=e,this._refitRaf||(this._refitRaf=requestAnimationFrame(()=>{this._refitRaf=0;const t=this._pendingRefitSize;this._pendingRefitSize=null;const e=this._stageEl;if(!t||!e||e.clientWidth<=0||e.clientHeight<=0)return;if(Math.abs(e.clientWidth-t[0])>.5||Math.abs(e.clientHeight-t[1])>.5)return void this._refitView();const i=this._lastValidStageSize;if(i&&Math.abs(i[0]-t[0])<=.5&&Math.abs(i[1]-t[1])<=.5)return;this._lastValidStageSize=t;const s=this._view;n>=wh?this._beginContinuityCandidate("stage-size-restored",!0,"stage-size"):this._continuity.hasCompleteFrame&&this._beginContinuityCandidate("stage-resize",!0,"stage-size"),this._applyView(this._zoom,s?s.x+s.w/2:void 0,s?s.y+s.h/2:void 0)})))}_zoomAt(t,e,i){const s=this._stageEl;if(!s)return;const n=Oi(this._baseVb(),this._stageAspect()),o=Math.min(wm.ZOOM_MAX,Math.max(wm.ZOOM_MIN,i));"opening"===this._tool&&(this._cursorPt=null,this._clearOpeningPlacement(!1));const r=s.clientWidth,a=s.clientHeight,l=this._screenToVb(t,e),c=n.w/o,h=n.h/o;this._zoom=o,this._view=this._clampView({x:l[0]-t/r*c,y:l[1]-e/a*h,w:c,h:h},n)}_onWheel(t){const e=this._stageEl;if(!e)return;t.preventDefault();const i=e.getBoundingClientRect(),s=t.deltaY<0?1.15:1/1.15;this._zoomAt(t.clientX-i.left,t.clientY-i.top,this._zoom*s),this._saveZoom()}_stepZoom(t){const e=this._stageEl;e&&(this._zoomAt(e.clientWidth/2,e.clientHeight/2,this._zoom*(t>0?1.4:1/1.4)),this._saveZoom())}_resetZoom(){const t=this._baseVb();"opening"===this._tool&&(this._cursorPt=null,this._clearOpeningPlacement(!1)),this._zoom=1,this._view=Oi(t,this._stageAspect()),this._saveZoom()}_saveZoom(){if("view"===this._mode){this._zoomBySpace={...this._zoomBySpace,[this._space]:this._zoom};try{localStorage.setItem(am,JSON.stringify(this._zoomBySpace))}catch{}}}_restoreZoom(){const t=this._zoomBySpace[this._space]||1;this._zoom=t;const e=this._stageEl;if(e&&e.clientHeight){const e=this._baseVb();return this._applyView(t,e[0]+e[2]/2,e[1]+e[3]/2),void this.requestUpdate()}this._view=null,requestAnimationFrame(()=>{if(!this._stageEl)return;const e=this._baseVb();this._applyView(t,e[0]+e[2]/2,e[1]+e[3]/2),this.requestUpdate()})}_stagePointerDown(t){if(this._vacFit)return;if(this._kiosk&&(this._cyclePausedUntil=Date.now()+6e4,0===this._pointers.size?(this._swipeStart={x:t.clientX,y:t.clientY,id:t.pointerId},t.target.closest?.(".dev, .roomlabel, .oplock")||(clearTimeout(this._kioskHoldTimer),this._kioskHoldTimer=window.setTimeout(()=>{this._kioskDialog=!0,this._swipeStart=null},3e3))):(this._swipeStart=null,clearTimeout(this._kioskHoldTimer))),this._drag)return;if(this._markup&&t.target.closest?.(".roomlabel, .rlhandle, .rszhandle, .dev, .oplock, .op-hit, button"))return;if("devices"===this._mode&&t.target.closest(".dev"))return;if("decor"===this._mode&&this._decorPointerDown(t))return;this._pointers.set(t.pointerId,{x:t.clientX,y:t.clientY});const e=this._viewOr(this._baseVb());if(1===this._pointers.size)this._panStart={sx:t.clientX,sy:t.clientY,vx:e.x,vy:e.y},this._panLock=null,this._suppressClick=!1;else if(2===this._pointers.size){this._cancelBoundaryAnchor(),"opening"===this._tool?(this._cursorPt=null,this._clearOpeningPlacement(!1)):"draw"===this._tool&&this._clearPlanSnapHover();const t=[...this._pointers.values()],e=Math.hypot(t[0].x-t[1].x,t[0].y-t[1].y);this._pinchStart={dist:e,zoom:this._zoom},this._panStart=null,this._panLock=null}}get _swipeZone(){return!this._hasFixedFloor&&this._kiosk&&this._zoom<=1.001&&this._model.length>1}_stagePointerMove(t){if(this._physicalRotate?.pid!==t.pointerId)if(this._physicalDrag?.pid!==t.pointerId)if(this._dtDrag?.pid!==t.pointerId)if(this._bdDrag?.pid!==t.pointerId){if(this._decorDraft?.pid===t.pointerId){const e=this._decorDraft;let i=this._decorSnap(this._svgPoint(t),t.pointerType);if(t.shiftKey&&("rect"===e.kind||"ellipse"===e.kind)){const t=i[0]-e.a[0],s=i[1]-e.a[1],n=Math.max(Math.abs(t),Math.abs(s));i=this._snap([e.a[0]+(t<0?-n:n),e.a[1]+(s<0?-n:n)])}return void(this._decorDraft={...e,b:i})}if(this._decorMove?.pid!==t.pointerId)if(this._pointers.has(t.pointerId)){if(this._pointers.set(t.pointerId,{x:t.clientX,y:t.clientY}),this._markup&&1===this._pointers.size&&this._markupMove(t),this._pinchStart&&this._pointers.size>=2){"opening"===this._tool?(this._cursorPt=null,this._clearOpeningPlacement(!1)):"draw"===this._tool&&this._clearPlanSnapHover();const t=[...this._pointers.values()],e=Math.hypot(t[0].x-t[1].x,t[0].y-t[1].y)/(this._pinchStart.dist||1),i=this._stageEl.getBoundingClientRect(),s=(t[0].x+t[1].x)/2-i.left,n=(t[0].y+t[1].y)/2-i.top;this._zoomAt(s,n,this._pinchStart.zoom*e),this._suppressClick=!0,this._saveZoom()}else if(this._panStart){const e=t.clientX-this._panStart.sx,i=t.clientY-this._panStart.sy;Math.abs(e)+Math.abs(i)>4&&(this._suppressClick=!0,clearTimeout(this._holdTimer),"opening"===this._tool?(this._cursorPt=null,this._clearOpeningPlacement(!1)):"draw"===this._tool&&this._clearPlanSnapHover()),null===this._panLock&&Math.abs(e)+Math.abs(i)>8&&(this._panLock=this._swipeZone&&Math.abs(e)>1.5*Math.abs(i)?"swipe":"pan");const s=this._stageEl;if("pan"===this._panLock&&s){const t=this._baseVb(),n=this._viewOr(t),o=Oi(t,this._stageAspect());this._view=this._clampView({x:this._panStart.vx-e/(s.clientWidth||1)*n.w,y:this._panStart.vy-i/(s.clientHeight||1)*n.h,w:n.w,h:n.h},o)}}}else this._markupMove(t);else this._decorMoveUpdate(t)}else this._bdMove(t);else this._dtMove(t);else this._physicalMove(t);else this._physicalRotateMove(t)}_stagePointerLeave(t){this._markup&&("opening"===this._tool?(this._cursorPt=null,this._clearOpeningPlacement(!1)):"draw"===this._tool&&this._clearPlanSnapHover())}_stagePointerUp(t){if(this._kiosk){clearTimeout(this._kioskHoldTimer);const e=this._swipeStart;if(this._swipeStart=null,e&&e.id===t.pointerId){const i=t.clientX-e.x,s=t.clientY-e.y;if(Math.abs(i)+Math.abs(s)<8){const t=Date.now();t-this._lastTap<350&&this._resetZoom(),this._lastTap=t}const n="pan"===this._panLock?null:function(t,e,i,s,n,o=60){if(i>1.001||s.length<2)return null;if(Math.abs(t)t.id),this._space);n&&this._slideTo(n,i<0?"left":"right")&&(this._saveNav(),this._suppressClick=!0,setTimeout(()=>this._suppressClick=!1,0),this._showKioskDots())}}if(this._physicalDrag?.pid===t.pointerId)return void this._physicalUp(t);if(this._physicalRotate?.pid===t.pointerId)return void this._physicalRotateUp(t);if(this._dtDrag?.pid===t.pointerId)return void this._dtUp();if(this._bdDrag?.pid===t.pointerId)return void this._bdUp();if(this._decorDraft?.pid===t.pointerId)return void this._decorCommitDraft();if(this._decorMove?.pid===t.pointerId)return this._decorMove.moved&&(this._recordGeometry(this._t("history.decor_move"),this._decorMove.before),this._saveConfig()),void(this._decorMove=null);const e=!!this._pinchStart||!!this._panStart;this._pointers.delete(t.pointerId),this._pointers.size<2&&(this._pinchStart=null),0===this._pointers.size&&(this._panStart=null,this._panLock=null,setTimeout(()=>this._suppressClick=!1,0)),e&&0===this._pointers.size&&this.requestUpdate()}_clickRoom(t){!this._suppressClick&&t.area&&vm("/config/areas/area/"+t.area)}_pointerDown(t,e){if("plan"===this._mode)return;if("view"===this._mode){this._holdFired=!1,clearTimeout(this._holdTimer);const i=t.pointerId,s=t.currentTarget;return void(this._holdTimer=window.setTimeout(()=>{this._holdFired=!0,this._interruptViewGesture(i,s),this._infoCard=e},600))}if("ha_disabled"===e.bindingStatus?.kind)return;t.preventDefault();const i=this._pos(e);this._drag={id:e.id,sx:t.clientX,sy:t.clientY,ox:i.x,oy:i.y,moved:!1},bm(t),this._tip=null}_pointerMove(t,e){if(!this._drag||this._drag.id!==e.id)return;const i=this.renderRoot.querySelector(".stage");if(!i)return;const s=this._baseVb(),n=i.getBoundingClientRect(),o=this._viewOr(s),r=(t.clientX-this._drag.sx)/n.width*o.w,a=(t.clientY-this._drag.sy)/n.height*o.h;Math.abs(t.clientX-this._drag.sx)+Math.abs(t.clientY-this._drag.sy)>3&&(this._drag.moved=!0,clearTimeout(this._holdTimer));const l=Mc(this._drag.ox+r),c=Mc(this._drag.oy+a);this._savePos(e,l,c)}_pointerUp(t,e){if(clearTimeout(this._holdTimer),!this._drag||this._drag.id!==e.id)return;const i=this._drag.moved;this._drag=i?this._drag:null,i&&(this._selId=e.id,window.setTimeout(()=>this._drag=null,0))}_showToast(t){for(const t of this.renderRoot.querySelectorAll("hp-dialog"))t.closeTransientOverlays("toast");this._toast=t,clearTimeout(this._toastTimer),this._toastTimer=window.setTimeout(()=>{this._toast=""},3500)}_syncPointerHoverTargets(){const t=this._pointerModality.hoverEnabled;for(const e of this.renderRoot.querySelectorAll(dm))e.toggleAttribute("data-pointer-hover",t)}_syncPointerHoverSubtree(t){if(t.nodeType!==Node.ELEMENT_NODE)return;const e=t,i=this._pointerModality.hoverEnabled;e.matches(dm)&&e.toggleAttribute("data-pointer-hover",i);for(const t of e.querySelectorAll(dm))t.toggleAttribute("data-pointer-hover",i)}_clearTransientHover(t=!1){t&&this._pointerModality.suspend(),this._tip&&(this._tip=null),this._hoverRoom&&(this._hoverRoom=null)}_notePointer(t){this._boundaryPointerType=t.pointerType||"mouse";const e=this._pointerModality.modality,i=this._pointerModality.note(t);"touch"!==i&&"pen"!==i||e===i&&!this._tip&&!this._hoverRoom||this._clearTransientHover()}_guardTouchGesture(t){if(this._editorSecondary.handleOutsideDismiss(t))return;if("click"===t.type){if(!this._suppressClick&&!this._touchSequenceMultitouch&&Date.now()>this._touchClickBlockUntil)return;return t.preventDefault(),void t.stopImmediatePropagation()}const e=t;if(this._notePointer(e),"touch"===e.pointerType)if("pointerdown"!==t.type){if("pointermove"===t.type){const t=this._touchContacts.get(e.pointerId);if(!t)return;const i={...t,x:e.clientX,y:e.clientY};if(this._touchContacts.set(e.pointerId,i),this._touchSequenceMultitouch&&"view"===this._mode&&!this._vacFit&&this._pinchStart&&[...this._touchContacts.values()].every(t=>t.inStage)){this._pointers.set(e.pointerId,{x:e.clientX,y:e.clientY});const t=[...this._touchContacts.values()];if(t.length>=2&&this._stageEl){const[e,i]=t,s=Math.hypot(e.x-i.x,e.y-i.y)/(this._pinchStart.dist||1),n=this._stageEl.getBoundingClientRect();this._zoomAt((e.x+i.x)/2-n.left,(e.y+i.y)/2-n.top,this._pinchStart.zoom*s),this._saveZoom()}}return}if("pointerup"===t.type||"pointercancel"===t.type||"lostpointercapture"===t.type){if(this._clearTransientHover(),this._touchContacts.delete(e.pointerId),this._touchSequenceMultitouch){if(this._touchClickBlockUntil=Date.now()+500,this._pointers.delete(e.pointerId),!this._vacFit&&this._pointers.size>=2){const[t,e]=[...this._pointers.values()];this._pinchStart={dist:Math.hypot(t.x-e.x,t.y-e.y),zoom:this._zoom}}else this._pinchStart=null;0===this._pointers.size&&(this._panStart=null,this._panLock=null)}0===this._touchContacts.size&&(this._touchSequenceMultitouch=!1)}}else if(this._touchContacts.set(e.pointerId,{x:e.clientX,y:e.clientY,inStage:!!e.target?.closest?.(".stage")}),this._touchContacts.size>=2){this._clearTransientHover(),this._touchSequenceMultitouch=!0,this._touchClickBlockUntil=Number.POSITIVE_INFINITY,clearTimeout(this._holdTimer),clearTimeout(this._kioskHoldTimer),this._swipeStart=null;const t=[...this._touchContacts.values()];if("view"===this._mode&&!this._vacFit&&t.every(t=>t.inStage)){this._pointers=new Map([...this._touchContacts].map(([t,e])=>[t,{x:e.x,y:e.y}]));const[e,i]=t;this._pinchStart={dist:Math.hypot(e.x-i.x,e.y-i.y),zoom:this._zoom},this._panStart=null,this._panLock=null}else this._vacFit&&(this._pointers.clear(),this._pinchStart=null,this._panStart=null,this._panLock=null)}}_showTip(t,e,i,s,n,o){this._notePointer(t),this._pointerModality.hoverEnabled&&(this._drag||(this._tip={x:t.clientX,y:t.clientY,title:e,meta:i,lqi:s,temp:n,hum:o}))}get _gridPitch(){return kc}get _cellCm(){const t=Number(this._curSpaceCfg?.cell_cm);return Number.isFinite(t)&&t>0?t:5}_fmtLen(t,e){const i=function(t,e,i,s){return Math.hypot(e[0]-t[0],e[1]-t[1])/i*s}(t,e,this._gridPitch,this._cellCm);return li(i,"mi"===this.hass?.config?.unit_system?.length)}get _curSpaceCfg(){const t=this._rszPreview;return t&&t.space===this._space?t.sp:this._serverCfg?.spaces.find(t=>t.id===this._space)}get _renderCfg(){const t=this._rszPreview;return t&&this._serverCfg?{...this._serverCfg,spaces:this._serverCfg.spaces.map(e=>e.id===t.space?t.sp:e)}:this._serverCfg}get _spaceH(){return this._curSpaceCfg,pm}get _segments(){const t=this._curSpaceCfg,e=this._spaceH;return pi(t?.rooms||[]).map(t=>[t[0]*pm,t[1]*e,t[2]*pm,t[3]*e])}_savedNav(){if(this._hasFixedFloor)return null;try{return JSON.parse(localStorage.getItem(lm)||"null")}catch{return null}}_saveNav(){if(!this._hasFixedFloor)try{localStorage.setItem(lm,JSON.stringify({space:this._space}))}catch{}}_leaveCardRoute(){if(this._routeDepartureHandled)return;this._routeDepartureHandled=!0,"view"!==this._mode&&this._setMode("view",!1),this._pendingNavMode=null,this._geometryHistory.clear(),this._activeDraftId=null,this._resumeDraftBySpace={},this._draftSegmentCms=[],this._closingWallCm=null,this._drawWallField=null,this._showHidden=!1,this._tapConfirm=null,this._vacCalConfirm=null,this._decorEraseConfirm=null,this._openingInfo=null,this._closeInfoCard(),this._rulesDialog=null,this._alignDialog=null,this._backupImportDialog=null,this._backupExportDialog=null,this._settingsDialog=null,this._markerDialog=null,this._openingDialog=null,this._physicalDialog=null,this._wallDialog=null,this._backdropDialog=null,this._decorShapeDialog=null,this._decorTextDialog=null,this._mergeDialog=null,this._roomDialog=!1,this._spaceDialog=null,this._importDialog=null;const t=this._warmSlot;t?.owner===this._warmGen&&(t.vp=this._warmViewportState(),t.dlg=null,t.frameFingerprint="",clearTimeout(t.evict),t.evict=0),this._saveNav()}_setMode(t,e=!0){this._endTabDrag(),this._pendingNavMode=null;const i=this._spaceModel();if(!i)return this._cancelModeTransition(!1),void(this._mode="view");if(this._kiosk&&"view"!==t)return;if(this._mode===t){if(!e&&"view"===t&&this._modeTransitionBusy){const e=this._currentModeVisual(t),i=this._modeTransitionTargetZoom,s=this._modeTransitionTargetCenterX,n=this._modeTransitionTargetCenterY;this._cancelModeTransition(!1),this._commitViewModeAtomic(e,i,s,n)}return}if(this._bootSoftCancel(),("plan"===t||"decor"===t)&&!this._norm)return void this._showToast(this._t("toast.markup_needs_server"));if(this._wallFaceBatch&&this._roomDialogCancel(),"plan"===this._mode&&"draw"===this._tool&&!this._finishWallChain())return;this._clearTransientHover(!0),this._cancelDevicePressFeedback();const s=this._mode,n=this._effectiveProjection(),o=this._currentModeVisual(s),r=this._modeTransitionBusy,a=o&&"view"!==s&&"view"!==t?{...o,toolbarContentOpacity:this._reducedMotion?1:.35}:o;this._cancelModeTransition(!1),this._editorSecondary.closeForNavigation(),(this._decorMove||this._dtDrag||this._bdDrag)&&this._cancelDecorGesture();const l=!i.bg&&"view"===t!=("view"===s),c=r&&"view"===s&&"view"!==t?this._modeTransitionEditorCamera:null;let h=c?.zoom??(r?this._modeTransitionTargetZoom:this._zoom),d=c?c.centerX:r?this._modeTransitionTargetCenterX:a?.viewport.centerX,p=c?c.centerY:r?this._modeTransitionTargetCenterY:a?.viewport.centerY;if("view"===s&&"view"!==t&&!r){const e=this._view;if(this._viewModeSnap={space:this._space,zoom:this._zoom,cx:e?this._logicalViewCenter(n)?.x:void 0,cy:e?this._logicalViewCenter(n)?.y:void 0},"iso"===n){const e=this._logicalViewCenter("iso");d=e?.x,p=e?.y,this._view=null,this._mode=t,this._applyView(this._zoom,e?.x,e?.y)}l&&(h=1,d=void 0,p=void 0)}if("plan"===s&&this._activeDraftId&&(this._resumeDraftBySpace[this._space]=this._activeDraftId),this._mode=t,this._editorChromeMode="view"===t?s:t,"view"===t){"view"===s||r||(this._modeTransitionEditorCamera={zoom:this._zoom,centerX:a?.viewport.centerX,centerY:a?.viewport.centerY});const t=this._viewModeSnap;if(t&&t.space===this._space){h=t.zoom;const e=this._labsIso&&"iso"===this._viewPreference[this._space]?"iso":"flat",i=null!=t.cx&&null!=t.cy&&"iso"===e?ag([t.cx,t.cy],0):null;d=i?.[0]??t.cx,p=i?.[1]??t.cy}else t&&(h=this._zoomBySpace[this._space]||1,d=void 0,p=void 0)}else this._modeTransitionEditorCamera={zoom:h,centerX:d,centerY:p};this._modeTransitionTargetZoom=h,this._modeTransitionTargetCenterX=d,this._modeTransitionTargetCenterY=p,("iso"===n||"view"===t&&this._labsIso&&"iso"===this._viewPreference[this._space])&&(this._modeTransitionForceAtomic=!0);const u=++this._modeTransitionRequest;e?a?(this._modeTransitionPreparing=!0,this._modeTransitionVisual=a,this._prepareModeTransition(u,a,t,h,d,p)):(this._modeTransitionPreparing=!1,this._modeTransitionVisual=null,this._zoom=h,this._view=null,requestAnimationFrame(()=>{this.isConnected&&u===this._modeTransitionRequest&&this._mode===t&&(this._applyView(h,d,p),"view"===t&&(this._viewModeSnap=null,this._modeTransitionEditorCamera=null),this.requestUpdate())})):"view"===t&&this._commitViewModeAtomic(a,h,d,p),this._path=[],this._clearPlanSnapHover(),this._clearOpeningPlacement(!0),this._openWallAnchor=null,this._boundaryRestoreGuard=null,this._tool="draw",this._mergeSel=null,this._mergeDialog=null,this._splitSel=null,this._pendingSplit=null,this._selId=null,this._physicalSel=null,this._physicalDialog=null,this._physicalDrag=null,this._rszSel=null,this._rszDrag=null,this._rszLive=null,this._rszPreview=null,this._tip=null,this._hoverRoom=null,this._decorDraft=null,this._decorSel=null,this._decorMove=null,this._backdropDialog=null,this._decorTool="select",this._bdDrag=null,this._dtDrag=null,this._dtBox=null,"plan"===t&&(this._primeDrawWallField(),this._resumeLastDraft()),this._saveNav()}_primeDrawWallField(){null===this._drawWallField&&(this._drawWallField=ka(fa,this._imperial))}get _drawWallFieldValue(){return null===this._drawWallField?ka(fa,this._imperial):this._drawWallField}get _drawWallCm(){const t=Zg(this._drawWallFieldValue);if(null==t||t<=0)return null;const e=this._imperial?2.54*t:t,i="column"===this._tool?Hl:100;return e>=1&&e<=i?e:null}get _drawWallMaxCm(){return"column"===this._tool?Hl:100}_showPhysicalRange(t=this._drawWallMaxCm){this._showToast(this._t("toast.physical_range",{max:ka(t,this._imperial),unit:this._t(this._imperial?"wallthick.unit_in":"wallthick.unit_cm")}))}_draftSegmentCount(t=this._curSpaceCfg){return(t?.room_drafts||[]).reduce((t,e)=>t+(Array.isArray(e.segments)?e.segments.length:0),0)}_mergeSpacePartitions(t,e){const i=t?.partitions||[];if(i.length<2)return 0;const s=o_(i,{pitch:xc,seedIds:e,geometry:a_(t,{excludeDraftId:this._activeDraftId})});return s.merged?(t.partitions=s.partitions,r_(t.openings,t.partitions,s.openingMoves,{coordScale:pm,cellCm:this._cellCm,gridPitch:this._gridPitch}),s.merged):0}_finishWallChain(){if("draw"!==this._tool||this._wallFaceBatch||this._roomDialog)return!0;const t=this._curSpaceCfg;if(!t||this._path.length<2)return this._path=[],this._activeDraftId=null,this._draftSegmentCms=[],this._closingWallCm=null,this._clearPlanSnapHover(),!0;const e=tp(this._path,Qd(this._path.length-1,this._draftSegmentCms,this._drawWallCm,fa)),i=e.length;if((t.partitions||[]).length+i>mm)return this._showToast(this._t("toast.physical_limit")),!1;const s=this._geometrySnapshot();t.partitions||=[];const n=Date.now().toString(36),o=[];for(let s=0;st.id!==this._activeDraftId),t.room_drafts.length||delete t.room_drafts),this._recordGeometry(this._t("history.wall_chain_finish"),s),this._saveConfig(),delete this._resumeDraftBySpace[this._space],this._path=[],this._activeDraftId=null,this._draftSegmentCms=[],this._closingWallCm=null,this._clearPlanSnapHover(),!0}_activateMarkupTool(t){t!==this._tool&&(this._wallFaceBatch&&this._roomDialogCancel(),("draw"!==this._tool||this._finishWallChain())&&(this._cancelPath(),this._tool=t,"draw"===t&&this._resumeLastDraft(),"resize"===t&&(this._rszSel=null),"boundary"!==t&&"wallthick"!==t||(this._wallDialog=null)))}_limitReached(t){const e=this._curSpaceCfg;if(!e)return!0;const i="draft"===t?(e.room_drafts||[]).length>=200:"partition"===t?(e.partitions||[]).length>=mm:(e.wall_columns||[]).length>=500;return i&&this._showToast(this._t("toast.physical_limit")),i}_svgPoint(t){const e=this.renderRoot.querySelector(".stage").getBoundingClientRect();return this._screenToVb(t.clientX-e.left,t.clientY-e.top)}_snap(t){const e=this._gridPitch;return[Mc(ai(t[0],e)),Mc(ai(t[1],e))]}_snapDrawPoint(t,e=!1){const i=this._path[this._path.length-1],s=e&&i?function(t,e,i,s=1/0){if(!(i>0&&t?.every(Number.isFinite)&&e?.every(Number.isFinite)))return[e[0],e[1]];const n=e[0]-t[0],o=e[1]-t[1];if(Math.abs(n)+Math.abs(o)<=1e-12)return[t[0],t[1]];const r=Math.PI/4;let a=Math.atan2(o,n);a<0&&(a+=2*Math.PI);const l=Math.floor(a/r+.5)%8,[c,h]=[[1,0],[1,1],[0,1],[-1,1],[-1,0],[-1,-1],[0,-1],[1,-1]][l],d=c*c+h*h;let p=Math.max(0,Math.round((n*c+o*h)/(i*d)));if(Number.isFinite(s)&&s>=0){const e=(t,e)=>{if(!e)return 1/0;const n=e>0?s-t:t+s;return Math.max(0,Math.floor((n+1e-9*i)/i))};p=Math.min(p,e(t[0],c),e(t[1],h))}return[t[0]+c*p*i,t[1]+h*p*i]}(i,t,this._gridPitch,bc):t;return this._snap(s)}_planSnapOpeningCuts(t,e){if(!this._openingsR.length)return[];const i=this._openingWallIndexFor(t,e).value,s=[];for(const e of this._roomWallOpeningInputs(this._openingsR,t)){const t=Fl(i,e);if(!t.negative&&!t.positive)continue;const n=e.angle*Math.PI/180,o=Math.cos(n)*e.length/2,r=Math.sin(n)*e.length/2;s.push([e.x-o,e.y-r,e.x+o,e.y+r])}return s}_planSnapGeometrySnapshot(){const t=this._spaceModel();if(!t)return{key:`${this._space}|empty`,value:{segments:[],endpoints:[]}};const e=[this._space,this._cfgEpoch,this._activeDraftId||"",t.rooms.length,t.room_drafts.length,t.partitions.length].join("|");if(this._planSnapGeometryCache?.key===e)return this._planSnapGeometryCache;const i=this._openCuts(),s=Ud({space:t,activeDraftId:this._activeDraftId,roomCuts:[...i,...this._planSnapOpeningCuts(t,i)],partitionCuts:this._partitionOpeningCuts(t),epsilon:2e-4*this._gridPitch});return this._planSnapGeometryCache={key:e,value:s},this._planSnapGeometryCache}_planStructuralGeometrySnapshot(){const t=this._spaceModel();if(!t)return{key:`${this._space}|structural-empty`,value:{segments:[],endpoints:[]}};const e=["structural",this._space,this._cfgEpoch,this._activeDraftId||"",t.rooms.length,t.room_drafts.length,t.partitions.length].join("|");if(this._planStructuralGeometryCache?.key===e)return this._planStructuralGeometryCache;const i=Ud({space:t,activeDraftId:this._activeDraftId,roomCuts:this._openCuts(),epsilon:2e-4*this._gridPitch});return this._planStructuralGeometryCache={key:e,value:i},this._planStructuralGeometryCache}_planSnapContextKey(t){const e=this._path[0],i=this._path[this._path.length-1];return[t,this._tool,this._path.length,e?`${e[0]},${e[1]}`:"",i?`${i[0]},${i[1]}`:""].join("|")}_resolvePlanDrawPoint(t,e){const i=this._planSnapGeometrySnapshot(),s=this._path[this._path.length-1],n="draw"===this._tool&&this._path.length>=3?[{point:this._path[0],key:"closure:first-point"}]:[],o={tolerance:this._cssPxToRender(12),distinguishTolerance:this._cssPxToRender(8),gridStep:this._gridPitch,excludePoints:s?[s]:[],extraEndpoints:n,epsilon:2e-4*this._gridPitch},r=e&&s?Jd(i.value,t,{...o,anchor:s}):function(t,e,i){if(!(Nd(e)&&i.tolerance>=0))return{kind:"none",candidate:null,conflicts:[]};const s=i.epsilon??Od,n=i.excludePoints||[],o=Yd(Kd(t,e,i),i.distinguishTolerance||0);if(o)return o;let r=null;for(const o of t.segments){const t=[o.a[0],o.a[1],o.b[0],o.b[1]],a=Hs([e[0],e[1]],t);if(a>i.tolerance)continue;const l=Xd(o,e,i.gridStep);!Gd(l,n,s)&&Vd(a,o.key,r)&&(r={kind:"line",point:l,key:o.key,distance:a,segment:o})}return r?{kind:"resolved",candidate:r,conflicts:[]}:{kind:"none",candidate:null,conflicts:[]}}(i.value,t,o),a="resolved"===r.kind?r.candidate:null;return{point:a?[...a.point]:this._snapDrawPoint(t,e),candidate:a,conflicts:"ambiguous"===r.kind?r.conflicts:[],ambiguous:"ambiguous"===r.kind,contextKey:this._planSnapContextKey(i.key)}}get _activePlanSnapCandidate(){if(!this._markup||"draw"!==this._tool)return null;const t=this._planSnapHover;if(!t)return null;const e=this._planSnapGeometrySnapshot();return t.contextKey===this._planSnapContextKey(e.key)?t.candidate:null}get _activePlanSnapConflicts(){if(!this._markup||"draw"!==this._tool)return[];const t=this._planSnapHover;if(!t)return[];const e=this._planSnapGeometrySnapshot();return t.contextKey===this._planSnapContextKey(e.key)?t.conflicts:[]}_clearPlanSnapHover(t=!0){this._planSnapHover=null,this._syncPlanSnapActiveMarker(null),this._syncPlanSnapConflictMarkers([]),t&&(this._cursorPt=null)}_samePt(t,e){return fi(t,e)}_dropLegacySegments(){for(const t of this._serverCfg?.markers||[])"ripple"===t.display&&(t.display="icon_ripple");for(const t of this._serverCfg?.spaces||[]){delete t.segments;const e=new Set,i=t=>"string"==typeof t&&t.length>=1&&t.length<=64&&!e.has(t),s=t=>(e.add(t),!0),n=t=>Array.isArray(t)&&2===t.length&&t.every(t=>Number.isFinite(Number(t))&&Math.abs(Number(t))<=yc);if(Array.isArray(t.partitions)&&(t.partitions=t.partitions.filter(t=>t&&i(t.id)&&n(t.a)&&n(t.b)&&Math.hypot(t.a[0]-t.b[0],t.a[1]-t.b[1])>1e-9&&s(t.id)).map(t=>({...t,cm:Math.max(1,Math.min(100,Number(t.cm)||15))})),t.partitions.length||delete t.partitions),Array.isArray(t.wall_columns)&&(t.wall_columns=t.wall_columns.filter(t=>t&&i(t.id)&&n(t.center)&&s(t.id)).map(t=>({id:t.id,shape:"circle"===t.shape?"circle":"square",center:[Number(t.center[0]),Number(t.center[1])],cm:Bl(Number(t.cm)||15),..."circle"===t.shape?{}:{angle:ql(t.angle)}})),t.wall_columns.length||delete t.wall_columns),Array.isArray(t.room_drafts)&&(t.room_drafts=t.room_drafts.filter(t=>t&&i(t.id)&&Array.isArray(t.points)&&t.points.length>=2&&t.points.every(n)&&s(t.id)).map(t=>{const e=[[Number(t.points[0][0]),Number(t.points[0][1])]],i=[];for(let s=1;st.points.length>=2),t.room_drafts.length||delete t.room_drafts),Array.isArray(t.walls)){const e=rh(t.open_spans).map(t=>[t.a[0],t.a[1],t.b[0],t.b[1]]);t.walls=Ea(t.walls,t.rooms||[],xc,1,e),t.walls.length||delete t.walls}}}get _cfgWriting(){return this._writesPending>0}_writeConfig(){var t,e;this._writesPending++,this._writeChain=(t=this._writeChain,e=async()=>{if(!this._serverCfg)return;this._dropLegacySegments();const t=Zu(this._serverCfg),e=Ch(t);e!==Ch(this._serverCfg)&&(this._serverCfg=t),this._cfgContentFingerprint=e;const i=await this.hass.callWS({type:"houseplan/config/set",config:t,expected_rev:this._cfgRev});this._cfgRev=i?.rev??this._cfgRev+1},t.catch(()=>{}).then(e));return this._writeChain.finally(()=>{this._writesPending--})}_saveConfig(){this._cfgEpoch++,this._saveConfigDebounced()}_geometrySnapshot(t=this._space){const e=this._serverCfg?.spaces.find(e=>e.id===t);if(!e)return null;const i=t=>JSON.parse(JSON.stringify(t)),s={};for(const t of["plan_x","plan_y","plan_scale","plan_scale_x","plan_scale_y","plan_angle"])void 0!==e[t]&&(s[t]=e[t]);return{spaceId:t,rooms:i(e.rooms||[]),...Array.isArray(e.openings)?{openings:i(e.openings)}:{},...Array.isArray(e.walls)?{walls:i(e.walls)}:{},...Array.isArray(e.open_spans)?{open_spans:i(e.open_spans)}:{},...Array.isArray(e.room_drafts)?{room_drafts:i(e.room_drafts)}:{},...Array.isArray(e.partitions)?{partitions:i(e.partitions)}:{},...Array.isArray(e.wall_columns)?{wall_columns:i(e.wall_columns)}:{},...Array.isArray(e.decor)?{decor:i(e.decor)}:{},plan_transform:s}}_recordGeometry(t,e){if(!e)return;const i=this._geometrySnapshot(e.spaceId);i&&JSON.stringify(e)!==JSON.stringify(i)&&(this._geometryHistory.push({name:t,before:e,after:i}),this.requestUpdate())}_clearGeometryGesture(){this._path=[],this._clearPlanSnapHover(),this._clearOpeningPlacement(!1),this._mergeSel=null,this._mergeDialog=null,this._splitSel=null,this._pendingSplit=null,this._wallFaceBatch=null,this._wallRepairDiagnostic=null,this._roomDeleteDialog=null,this._openWallAnchor=null,this._boundaryRestoreGuard=null,this._wallDialog=null,this._physicalDialog=null,this._physicalSel=null,this._physicalDrag=null,this._physicalRotate=null,this._activeDraftId=null,this._draftSegmentCms=[],this._closingWallCm=null,this._openingDialog=null,this._rszSel=null,this._rszDrag=null,this._rszPreview=null,this._rszLive=null,this._decorDraft=null,this._decorMove=null,this._dtDrag=null,this._bdDrag=null}_cancelBoundaryAnchor(){return!("boundary"!==this._tool||!this._openWallAnchor)&&(this._openWallAnchor=null,this._boundaryRestoreGuard=null,this._clearPlanSnapHover(),this.requestUpdate(),!0)}_stagePointerCancel(t){if(clearTimeout(this._kioskHoldTimer),this._swipeStart?.id===t.pointerId&&(this._swipeStart=null),this._physicalDrag?.pid===t.pointerId||this._physicalRotate?.pid===t.pointerId)return void this._cancelPhysicalGesture();if(this._decorDraft?.pid===t.pointerId)return this._decorDraft=null,void this.requestUpdate();if(this._decorMove?.pid===t.pointerId||this._dtDrag?.pid===t.pointerId||this._bdDrag?.pid===t.pointerId)return void this._cancelDecorGesture();this._cancelBoundaryAnchor(),"opening"===this._tool?(this._cursorPt=null,this._clearOpeningPlacement(!1)):"draw"===this._tool&&this._clearPlanSnapHover();const e=!!this._pinchStart||!!this._panStart;this._pointers.delete(t.pointerId),this._pointers.size<2&&(this._pinchStart=null),0===this._pointers.size&&(this._panStart=null,this._panLock=null),e&&0===this._pointers.size&&this.requestUpdate()}_applyGeometryState(t){if(!this._canCommitSpace(t.spaceId))return!1;const e=this._serverCfg?.spaces.find(e=>e.id===t.spaceId);if(!e)return!1;const i=t=>JSON.parse(JSON.stringify(t));e.rooms=i(t.rooms),void 0!==t.openings?e.openings=i(t.openings):delete e.openings,void 0!==t.walls?e.walls=i(t.walls):delete e.walls,void 0!==t.open_spans?e.open_spans=i(t.open_spans):delete e.open_spans,void 0!==t.room_drafts?e.room_drafts=i(t.room_drafts):delete e.room_drafts,void 0!==t.partitions?e.partitions=i(t.partitions):delete e.partitions,void 0!==t.wall_columns?e.wall_columns=i(t.wall_columns):delete e.wall_columns,void 0!==t.decor?e.decor=i(t.decor):delete e.decor;for(const t of["plan_x","plan_y","plan_scale","plan_scale_x","plan_scale_y","plan_angle"])delete e[t];return Object.assign(e,i(t.plan_transform||{})),this._clearGeometryGesture(),this._space!==t.spaceId&&(this._commitSpace(t.spaceId),this._saveNav(),this._restoreZoom()),this._modelCache=null,this._frame=null,this._regSignature="",this._maybeRebuildDevices(),this._saveConfig(),this.requestUpdate(),!0}_roomAt(t){return this._spaceModel()?.rooms.find(e=>{const i=hi(e);return!!i&&wi(t,i)})}_overlapRoom(t){return this._spaceModel()?.rooms.find(e=>{const i=hi(e);return!!i&&Di(t,i)})}_pointInRoom(t,e){return e.poly?vi(t,e.poly):null!=e.x&&t[0]>=e.x&&t[0]<=e.x+e.w&&t[1]>=e.y&&t[1]<=e.y+e.h}_contourSelfIntersects(t){if(!kr(t))return!0;const e=t.length,i=.001;for(let s=0;s=500)return this._showToast(this._t("toast.physical_limit")),!1;const t=this._curSpaceCfg;return!(!this._activeDraftId&&(t?.room_drafts||[]).length>=200||this._draftSegmentCount(t)>=2e3||(t?.partitions||[]).length+this._path.length>mm)||(this._showToast(this._t("toast.physical_limit")),!1)}_markupClick(t){if(this._vacFit)return;if(!this._markup)return;const e=this._spaceModel();if(!e)return void this._clearGeometryGesture();if(this._suppressClick)return;if(this._drag||this._rlResize)return;const i=t.composedPath?.()||[];if(i.some(t=>t?.classList?.contains?.("roomlabel")||t?.classList?.contains?.("rlhandle")))return;if(i.some(t=>t?.classList?.contains?.("physical-hit")))return void("boundary"===this._tool&&this._showToast(this._t("toast.boundary_blocked")));const s=this._svgPoint(t);if("select"===this._tool)return void(this._physicalSel=null);if("resize"===this._tool){if(this._rszDrag||i.some(t=>t?.classList?.contains?.("rszhandle")))return;const t=[...e.rooms].reverse().find(t=>this._pointInRoom(s,t));return void(this._rszSel=t?.id||null)}if("delroom"===this._tool)return void this._deleteRoomClick(s);if("opening"===this._tool)return void this._openingClick(s);if("merge"===this._tool)return void this._mergeClick(s);if("wallthick"===this._tool)return void this._wallThickClick(s);if("boundary"===this._tool)return void this._boundaryClick(s);if("split"===this._tool)return void this._splitClick(s);if("column"===this._tool)return void this._columnClick(s);this._wallRepairDiagnostic=null;const n=this._resolvePlanDrawPoint(s,t.shiftKey);if(n.ambiguous)return this._planSnapHover={contextKey:n.contextKey,candidate:null,conflicts:n.conflicts},this._syncPlanSnapActiveMarker(null),this._syncPlanSnapConflictMarkers(n.conflicts),void this._showToast(this._t("toast.plan_snap_ambiguous"));let o=n.point;if(t.ctrlKey||t.metaKey){if(t.preventDefault(),this._path.length<3)return;o=[...this._path[0]]}if(!this._path.length){if(!t.shiftKey&&!n.candidate&&this._offerExistingWallFace(s))return;const e=this._draftEndAt(o);return e?(this._activeDraftId=e.draft.id,this._resumeDraftBySpace[this._space]=e.draft.id,this._path=e.reverse?[...e.draft.points].reverse().map(t=>[...t]):e.draft.points.map(t=>[...t]),void(this._draftSegmentCms=this._adoptDraftCms(this._path,e.reverse?[...e.draft.segments].reverse().map(t=>t.cm):e.draft.segments.map(t=>t.cm),e.draft.id))):(this._activeDraftId=null,this._draftSegmentCms=[],void(this._path=[o]))}const r=this._path[this._path.length-1];if(this._samePt(o,r))return;const a=this._draftEndAt(o,this._activeDraftId||void 0);if(a)return void this._mergeDraftEndpoint(a);if(!this._canAppendRoomDraftPoint())return;const l=this._drawWallCm;if(null==l)return void this._showPhysicalRange(100);const c=this._path.map(t=>[...t]);this._path=[...this._path,o],this._draftSegmentCms=[...this._draftSegmentCms,l],this._persistActiveDraftSegment(),this._offerWallFaces(c)}_draftEndAt(t,e){const i=this._spaceModel();if(!i)return null;const s=this._viewOr(this._baseVb()),n=Math.max(.15*this._gridPitch,this._stageEl?.clientWidth?s.w/this._stageEl.clientWidth*12:0);for(const s of i.room_drafts||[]){if(s.id===e)continue;if(s.points.length<2)continue;const i=s.points[0],o=s.points[s.points.length-1];if(Math.hypot(t[0]-o[0],t[1]-o[1])<=n)return{draft:s,reverse:!1};if(Math.hypot(t[0]-i[0],t[1]-i[1])<=n)return{draft:s,reverse:!0}}return null}_mergeDraftEndpoint(t){const e=this._curSpaceCfg;if(!e||!this._path.length)return;const i=this._path.map(t=>[...t]),s=this._wallGraphSources(i),n=Array.isArray(e.room_drafts)?e.room_drafts:[],o=this._activeDraftId?n.find(t=>t.id===this._activeDraftId):null,r=n.find(e=>e.id===t.draft.id);if(!r)return;const a=t.reverse?t.draft.points.map(t=>[...t]):[...t.draft.points].reverse().map(t=>[...t]),l=t.reverse?(r.segments||[]).map(t=>({...t})):[...r.segments||[]].reverse().map(t=>({...t})),c=this._path[this._path.length-1],h=this._samePt(c,a[0]),d=h?null:this._drawWallCm;if(!h&&null==d)return void this._showPhysicalRange(100);const p=this._draftSegmentCms.map((t,e)=>({...o?.segments?.[e]||{},cm:t})),u=[...this._path.map(t=>[...t]),...h?a.slice(1):a],_=[...p,...null==d?[]:[{cm:d}],...l],g=u.length>=4&&this._samePt(u[0],u[u.length-1]),m=u,f=_;if(m.length>500)return void this._showToast(this._t("toast.physical_limit"));const v=(o?.segments?.length||0)+(r.segments?.length||0);if(this._draftSegmentCount(e)-v+f.length>2e3)return void this._showToast(this._t("toast.physical_limit"));if(g){const t=m.slice(0,-1);if(this._contourSelfIntersects(t)||Pi(t)<=1e-6)return void this._showToast(this._t("toast.contour_cannot_close"));const e=this._overlapRoom(t);if(e)return void this._showToast(this._t("toast.room_overlap",{name:e.name||""}))}const y=this._geometrySnapshot(),b=this._activeDraftId||t.draft.id,w={...o||r,id:b,points:m.map(t=>[t[0]/pm,t[1]/pm]),segments:f};e.room_drafts=n.filter(e=>e.id!==t.draft.id&&(!this._activeDraftId||e.id!==this._activeDraftId)),e.room_drafts.push(w),this._activeDraftId=b,this._resumeDraftBySpace[this._space]=b,this._path=m,this._draftSegmentCms=this._adoptDraftCms(m,f.map(t=>Number(t.cm)),b),this._physicalSel=null,this._recordGeometry(this._t("history.draft_merge"),y),this._saveConfig(),null!=d&&this._offerWallFaces(i,i.length-1,s)}_adoptDraftCms(t,e,i){const s=Math.max(0,t.length-1),n=Qd(s,e,this._drawWallCm,fa);return e.length!==s&&console.debug(`[houseplan] draft ${i??"?"}: восстановлено толщин ${s-e.length} (#234)`),n}_persistActiveDraftSegment(){if(this._path.length<2||!this._curSpaceCfg)return;const t=this._geometrySnapshot(),e=this._curSpaceCfg;e.room_drafts||=[],this._activeDraftId||(this._activeDraftId="draft-"+Date.now().toString(36)),this._resumeDraftBySpace[this._space]=this._activeDraftId;const i=e.room_drafts.findIndex(t=>t.id===this._activeDraftId),s={...i>=0?e.room_drafts[i]:{},id:this._activeDraftId,points:this._path.map(t=>[t[0]/pm,t[1]/pm]),segments:this._draftSegmentCms.map((t,s)=>({...i>=0?e.room_drafts[i]?.segments?.[s]:{},cm:t}))};i>=0?e.room_drafts[i]=s:e.room_drafts.push(s),this._recordGeometry(this._t("history.draft_segment"),t),this._saveConfig()}_activeWallSourceKey(t){return`active:${this._activeDraftId||"session"}:${t}`}_wallGraphSources(t){const e=this._planStructuralGeometrySnapshot().value.segments.map(t=>({a:t.a,b:t.b,key:`static:${t.key}`}));for(let i=0;i+1t.key===i);if(s>=0){const[t]=this._wallFaceGraphCache.splice(s,1);return this._wallFaceGraphCache.push(t),t.value}const n=kp(t,e);return this._wallFaceGraphCache.push({key:i,value:n}),this._wallFaceGraphCache.length>4&&this._wallFaceGraphCache.shift(),n}_offerWallFaces(t,e=this._path.length-2,i){if(this._path.length<2||this._wallFaceBatch||this._roomDialog)return;const s=this._spaceModel();if(!s)return;const n=this._activeWallSourceKey(e),o=2e-4*this._gridPitch;let r,a;try{const e=i||this._wallGraphSources(t);a=this._wallGraphSources(this._path),r=function(t,e,i){const s=new Set(t.faces.map(t=>t.key));return e.faces.filter(t=>!s.has(t.key)&&t.sourceKeys.includes(i))}(this._wallFaceGraph(e,o),this._wallFaceGraph(a,o),n)}catch{return}if(!r.length){const t=Fp(a,{requiredSourceKey:n,maxDistance:xa(2,this._cellCm,this._gridPitch),gridStep:this._gridPitch,epsilon:o});return"ambiguous"===t.kind?(this._wallRepairDiagnostic=t.proposals[0]||null,void this._showToast(this._t("toast.wall_repair_ambiguous"))):void("repair"!==t.kind||this._overlapRoom(t.face.ring)||this._beginWallFaceBatch([{...t.face,repair:t.proposal}]))}for(const t of s.rooms){const e=hi(t);if(!t.id||!e)continue;const i=Fi(e,this._path,.02*this._gridPitch);if(!i)continue;const[s,n]=i,o=Pi(s)>=Pi(n)?s:n,a=o===s?n:s,l=[...r].sort((t,e)=>Math.abs(t.area-Pi(a))-Math.abs(e.area-Pi(a))||t.key.localeCompare(e.key))[0];if(!l)return;return void this._beginWallFaceBatch([{...l,ring:a.map(t=>[t[0],t[1]]),split:{roomId:t.id,mainPoly:o,newPoly:a},consumeAllActive:!0}])}const l=r.filter(t=>!(t.ring.length<3||this._contourSelfIntersects(t.ring))&&!this._overlapRoom(t.ring));l.length&&this._beginWallFaceBatch(l)}_beginWallFaceBatch(t){this._wallRepairDiagnostic=null,this._wallFaceBatch={candidates:[...t].sort((t,e)=>t.area-e.area||t.key.localeCompare(e.key)),index:0,decisions:[],activePath:this._path.map(t=>[...t]),activeCms:[...this._draftSegmentCms],activeDraftId:this._activeDraftId},this._clearPlanSnapHover(),this._nameSel="",this._areaSel="",this._resetRoomDialogFields(),this._roomDialog=!0}_offerExistingWallFace(t){if(this._path.length||this._wallFaceBatch||this._roomDialog)return!1;const e=2e-4*this._gridPitch;try{let i,s=xp(this._wallFaceGraph(this._wallGraphSources([]),e),t,e);if(!s){const n=Fp(this._wallGraphSources([]),{point:t,maxDistance:xa(2,this._cellCm,this._gridPitch),gridStep:this._gridPitch,epsilon:e});if("ambiguous"===n.kind)return this._wallRepairDiagnostic=n.proposals[0]||null,this._showToast(this._t("toast.wall_repair_ambiguous")),!0;if("repair"===n.kind)s=n.face,i=n.proposal;else if("none"===n.kind){const i=Fp(this._wallGraphSources([]),{point:t,maxDistance:this._cssPxToRender(12),gridStep:this._gridPitch,epsilon:e});if("repair"===i.kind)return this._wallRepairDiagnostic=i.proposal,this._showToast(this._t("toast.wall_repair_too_large")),!0}}return!(!s||s.ring.length<3||this._contourSelfIntersects(s.ring)||this._overlapRoom(s.ring))&&(this._beginWallFaceBatch([{...s,existing:!i,repair:i}]),!0)}catch{return!1}}_columnClick(t){const e=this._snap(t),i=this._drawWallCm;if(null==i)return void this._showPhysicalRange(Hl);if(!this._curSpaceCfg||this._limitReached("column"))return;const s=this._spaceModel();if(!s)return;const n={id:"column-"+Date.now().toString(36),shape:"square",center:e,cm:Bl(i),angle:0},o=(s.wall_columns||[]).find(t=>rc(t,n,.02*this._gridPitch));if(o)return clearTimeout(this._duplicateColumnTimer),this._duplicateColumnId=o.id,this._duplicateColumnTimer=window.setTimeout(()=>{this._duplicateColumnId=null},900),void this._showToast(this._t("toast.column_duplicate"));const r=this._geometrySnapshot(),a=this._curSpaceCfg;a.wall_columns||=[],a.wall_columns.push({...n,center:[e[0]/pm,e[1]/pm]}),this._recordGeometry(this._t("history.column_add"),r),this._saveConfig()}_openPhysicalDialog(t,e,i){const s=this._spaceModel();if(s)if("partition"===t){const i=s.partitions.find(t=>t.id===e);i&&(this._physicalDialog={kind:t,id:e,cm:ka(i.cm,this._imperial),length:this._fmtLen(i.a,i.b)})}else if("column"===t){const i=s.wall_columns.find(t=>t.id===e);i&&(this._physicalDialog={kind:t,id:e,cm:ka(i.cm,this._imperial),shape:i.shape,angle:this._angleField("square"===i.shape?ql(i.angle):0)})}else{const n=s.room_drafts.find(t=>t.id===e),o=Math.max(0,Math.min(n?.segments.length?n.segments.length-1:0,i||0));n?.segments[o]&&(this._physicalDialog={kind:t,id:e,segment:o,cm:ka(n.segments[o].cm,this._imperial),length:this._fmtLen(n.points[o],n.points[o+1])})}}_physicalDown(t,e,i){const s=this._spaceModel();if(!s)return;t.stopPropagation(),bm(t);const n=this._svgPoint(t),o=[];for(const t of[...s.wall_columns].reverse())nc(n,Kl(t,this._cellCm,this._gridPitch))&&o.push({kind:"column",id:t.id});for(const t of[...s.partitions].reverse()){const e=Vl(t.a,t.b,t.cm,this._cellCm,this._gridPitch);e&&nc(n,e)&&o.push({kind:"partition",id:t.id})}o.some(t=>t.kind===e&&t.id===i)||o.unshift({kind:e,id:i});const r=o.map(t=>`${t.kind}:${t.id}`).sort().join("|"),a=performance.now(),l=this._physicalPickCycle,c=o.length>1&&l?.signature===r&&a-l.at>380&&a-l.at<=1200&&Math.hypot(t.clientX-l.x,t.clientY-l.y)<=10?(l.index+1)%o.length:Math.max(0,o.findIndex(t=>t.kind===e&&t.id===i));this._physicalPickCycle={signature:r,index:c,x:t.clientX,y:t.clientY,at:a},e=o[c].kind,i=o[c].id;const h="partition"===e?s.partitions.find(t=>t.id===i):s.wall_columns.find(t=>t.id===i);h&&(this._physicalSel={kind:e,id:i},this._physicalDrag={pid:t.pointerId,kind:e,id:i,start:this._svgPoint(t),startClient:[t.clientX,t.clientY],before:this._geometrySnapshot(),moved:!1,base:JSON.parse(JSON.stringify(h)),delta:[0,0]})}_clampPhysicalDelta(t,e,i){const s="partition"===t?[e.a,e.b]:[e.center],n=s.map(t=>t[0]),o=s.map(t=>t[1]);return[Math.max(-yc*pm-Math.min(...n),Math.min(yc*pm-Math.max(...n),i[0])),Math.max(-yc*pm-Math.min(...o),Math.min(yc*pm-Math.max(...o),i[1]))]}_physicalMove(t){const e=this._physicalDrag;if(!e||e.pid!==t.pointerId)return;t.stopPropagation();const i=this._svgPoint(t),s="partition"===e.kind?e.base.a:e.base.center,n=this._snap([s[0]+i[0]-e.start[0],s[1]+i[1]-e.start[1]]),o=this._clampPhysicalDelta(e.kind,e.base,[n[0]-s[0],n[1]-s[1]]);this._physicalDrag={...e,delta:o,moved:e.moved||Math.hypot(t.clientX-e.startClient[0],t.clientY-e.startClient[1])>=5}}_physicalUp(t){const e=this._physicalDrag;if(!e||e.pid!==t.pointerId)return;if(t.stopPropagation(),this._physicalDrag=null,!e.moved)return void this._registerPhysicalTap(e.kind,e.id);const i=this._spaceModel();if(!this._curSpaceCfg||!i)return;const s=this._curSpaceCfg;if("partition"===e.kind){const t=(s.partitions||[]).find(t=>t.id===e.id),i=e.base;if(t){const n={...i,a:[i.a[0]+e.delta[0],i.a[1]+e.delta[1]],b:[i.b[0]+e.delta[0],i.b[1]+e.delta[1]]};t.a=[n.a[0]/pm,n.a[1]/pm],t.b=[n.b[0]/pm,n.b[1]/pm];for(const t of s.openings||[]){if("partition"!==t.host?.kind||t.host.id!==e.id)continue;const i=Pd(t,[n],pm,this._cellCm,this._gridPitch).resolved;i&&Object.assign(t,zd(t,i,pm))}}}else{const t=(s.wall_columns||[]).find(t=>t.id===e.id),n=e.base,o={...n,center:[n.center[0]+e.delta[0],n.center[1]+e.delta[1]]};if(i.wall_columns.some(t=>t.id!==e.id&&rc(t,o,.02*this._gridPitch)))return void this._showToast(this._t("toast.column_duplicate"));t&&(t.center=[(n.center[0]+e.delta[0])/pm,(n.center[1]+e.delta[1])/pm])}this._recordGeometry(this._t("history.physical_move"),e.before),this._saveConfig()}_registerPhysicalTap(t,e,i){const s=performance.now(),n=this._physicalLastTap?.kind===t&&this._physicalLastTap.id===e&&this._physicalLastTap.segment===i&&s-this._physicalLastTap.at<=360;this._physicalLastTap={kind:t,id:e,segment:i,at:s},n&&(this._physicalLastTap=null,this._openPhysicalDialog(t,e,i))}_cancelPhysicalGesture(){this._physicalDrag=null,this._physicalRotate=null,this.requestUpdate()}_physicalRotateDown(t,e){if("square"!==e.shape||!this._spaceModel())return;t.preventDefault(),t.stopPropagation(),bm(t);const i=this._svgPoint(t);this._physicalSel={kind:"column",id:e.id},this._physicalRotate={pid:t.pointerId,id:e.id,center:[...e.center],startAngle:180*Math.atan2(i[1]-e.center[1],i[0]-e.center[0])/Math.PI,baseAngle:ql(e.angle),angle:ql(e.angle),before:this._geometrySnapshot(),moved:!1}}_physicalRotateMove(t){const e=this._physicalRotate;if(!e||e.pid!==t.pointerId)return;t.preventDefault(),t.stopPropagation();const i=this._svgPoint(t),s=180*Math.atan2(i[1]-e.center[1],i[0]-e.center[0])/Math.PI,n=e.baseAngle+s-e.startAngle,o=ql(t.shiftKey?n:5*Math.round(n/5));this._physicalRotate={...e,angle:o,moved:e.moved||Math.abs(n-e.baseAngle)>=.5}}_physicalRotateUp(t){const e=this._physicalRotate;if(!e||e.pid!==t.pointerId)return;t.preventDefault(),t.stopPropagation(),this._physicalRotate=null;const i=this._spaceModel();if(!e.moved||!this._curSpaceCfg||!i)return;const s=i.wall_columns.find(t=>t.id===e.id);if(!s||"square"!==s.shape)return;const n={...s,angle:e.angle};if(i.wall_columns.some(t=>t.id!==e.id&&rc(t,n,.02*this._gridPitch)))return void this._showToast(this._t("toast.column_duplicate"));const o=this._curSpaceCfg.wall_columns?.find(t=>t.id===e.id);o&&(o.angle=e.angle,this._recordGeometry(this._t("history.physical_edit"),e.before),this._saveConfig())}_rszRooms(){const t=[],e=this._spaceModel();if(!e)return t;for(const i of e.rooms){const e=i.id?hi(i):null;e&&t.push({id:i.id,poly:e})}return t}_rszOpenings(){return this._openingsR.map(t=>({id:t.id,x:t.rx,y:t.ry,length:t.rlen}))}_rszOpts(){return{minDim:this._cmToUnits(30),eps:.05*this._gridPitch}}_rszSnapshot(){return JSON.stringify(this._geometrySnapshot()||{spaceId:this._space,rooms:[],openings:[],walls:[],open_spans:[]})}_rszApplyPreview(t,e){const i=this._rszDrag,s=this._serverCfg?.spaces.find(t=>t.id===this._space);if(!i||!s)return;const n=JSON.parse(i.snap),o={...s,rooms:n.rooms,openings:n.openings,walls:n.walls,open_spans:n.open_spans};Array.isArray(n.open_spans)&&n.open_spans.length||delete o.open_spans;const r=this._spaceH;for(const[e,i]of Object.entries(t)){const t=o.rooms.find(t=>t.id===e);t&&(t.poly=i.map(t=>[t[0]/pm,t[1]/r]),delete t.x,delete t.y,delete t.w,delete t.h)}for(const[t,i]of Object.entries(e)){const e=(o.openings||[]).find(e=>e.id===t);e&&(e.x=i[0]/pm,e.y=i[1]/r)}const a=[],l=[];for(const t of i.changed){const e=i.rooms.find(e=>e.id===t),s=o.rooms.find(e=>e.id===t);if(!e||!s?.poly)continue;const n=s.poly.map(t=>[t[0]*pm,t[1]*r]);if(e.poly.length===n.length)for(let t=0;tt.id===e);if(!s||!s.poly||s.poly.length<3)return null;if(i<0||i>=s.poly.length)return null;const n=[...s.poly[i]],o=[...s.poly[(i+1)%s.poly.length]];return{roomId:e,edge:i,a:n,b:o,n:fr(s.poly,i)}}(s,e,i);n&&(this._rszDrag={kind:"edge",pid:t.pointerId,roomId:e,plan:n,rooms:s,openings:this._rszOpenings(),snap:this._rszSnapshot(),moved:!1,d:0,k:1,changed:[]})}_rszCornerDown(t,e,i,s){"resize"!==this._tool||this._rszDrag||(t.stopPropagation(),t.preventDefault(),bm(t),this._rszDrag={kind:"scale",pid:t.pointerId,roomId:e,fixed:s,span0:Math.hypot(i[0]-s[0],i[1]-s[1])||1,rooms:this._rszRooms(),openings:this._rszOpenings(),snap:this._rszSnapshot(),moved:!1,d:0,k:1,changed:[]})}_rszMove(t){const e=this._rszDrag;if(!e||e.pid!==t.pointerId)return;t.stopPropagation();const i=this._svgPoint(t);if("edge"===e.kind){const t=e.plan,s=(i[0]-t.a[0])*t.n[0]+(i[1]-t.a[1])*t.n[1],n=this._snap([t.a[0]+t.n[0]*s,t.a[1]+t.n[1]*s]);let o=(n[0]-t.a[0])*t.n[0]+(n[1]-t.a[1])*t.n[1];if(o=function(t,e,i,s,n,o){if(!Number.isFinite(s)||Math.abs(s)<1e-9)return 0;const r=Math.sign(s);let a=Math.abs(s);const l=Math.max(n,1e-6);for(let s=0;s<4096&&a>1e-9;s++,a-=l){const s=r*a;if(Dr(t,e,i,s,o))return s}return 0}(e.rooms,e.openings,t,o,this._gridPitch,this._rszOpts()),o===e.d&&e.moved)return;e.d=o,e.moved=!0;const r=Sr(e.rooms,e.openings,t,o,this._rszOpts().eps);e.changed=Object.keys(r.polys),this._rszApplyPreview(r.polys,r.openings),this._rszLive=this._rszEdgeLabels(r,t)}else{const t=e.fixed,s=this._snap(i);let n=Math.hypot(s[0]-t[0],s[1]-t[1])/(e.span0||1);if(n=Math.max(.05,Math.min(20,n)),n=function(t,e,i,s,n,o){if(!Number.isFinite(n)||n<=0)return 1;if(Pr(t,e,i,s,n,o))return n;let r=1,a=n;for(let n=0;n<28;n++){const n=(r+a)/2;Pr(t,e,i,s,n,o)?r=n:a=n}return r}(e.rooms,e.openings,e.roomId,t,n,this._rszOpts()),n===e.k&&e.moved)return;e.k=n,e.moved=!0;const o=e.rooms.find(t=>t.id===e.roomId),r=e.rooms.filter(t=>t.id!==e.roomId).map(t=>t.poly),a=Tr(o,e.openings,r,t,n,2*this._rszOpts().eps);e.changed=[e.roomId],this._rszApplyPreview({[e.roomId]:a.poly},a.openings),this._rszLive=this._rszScaleLabels(a.poly)}this.requestUpdate()}_rszUp(t){const e=this._rszDrag;if(!e||e.pid!==t.pointerId)return;t.stopPropagation();const i=this._rszPreview;this._rszDrag=null,this._rszLive=null,this._rszPreview=null;if(!(e.moved&&("edge"===e.kind?Math.abs(e.d)>1e-9:Math.abs(e.k-1)>1e-9))||!i)return this._cfgEpoch++,void this.requestUpdate();const s=JSON.parse(e.snap),n=this._curSpaceCfg;if(n){n.rooms=i.sp.rooms,n.openings=i.sp.openings,Array.isArray(i.sp.walls)&&(i.sp.walls.length?n.walls=i.sp.walls:delete n.walls),Array.isArray(i.sp.open_spans)&&i.sp.open_spans.length?n.open_spans=i.sp.open_spans:delete n.open_spans;for(const t of e.changed){const e=n.rooms.find(e=>e.id===t);e?.poly&&(e.poly=wr(e.poly,1e-9))}this._commitOpenSpans(),Array.isArray(n.walls)&&n.walls.length&&(n.walls=Ea(n.walls,n.rooms||[],xc,1,this._cfgOpenCuts()),n.walls.length||delete n.walls)}this._suppressClick=!0,setTimeout(()=>this._suppressClick=!1,0),this._recordGeometry(this._t("history.resize_room"),s),this._saveConfig(),this.requestUpdate()}_rszCancelDrag(){this._rszDrag&&(this._rszDrag=null,this._rszLive=null,this._rszPreview=null,this._cfgEpoch++,this.requestUpdate())}_rszPointerCancel(t){const e=this._rszDrag;e&&e.pid===t.pointerId&&(t.stopPropagation(),this._rszCancelDrag())}_rszEdgeLabels(t,e){const i=this._rszDrag,s=[],n=t.polys[e.roomId]||i.rooms.find(t=>t.id===e.roomId).poly,o=n.length,r=e.edge,a=(r+1)%o,l=this._rszInnerSpanCms(e.roomId,n,t.polys);for(const t of[(r-1+o)%o,r,a]){const e=n[t],i=n[(t+1)%o],r=l?.[t];s.push({x:(e[0]+i[0])/2,y:(e[1]+i[1])/2,text:null==r?this._fmtLen(e,i):li(r,"mi"===this.hass?.config?.unit_system?.length)})}const c="mi"===this.hass?.config?.unit_system?.length,h=Object.keys(t.polys).length?Object.keys(t.polys):[e.roomId],d=this._spaceWalls,p=this._openPairs().flatMap(t=>t.segs),u=this._physicalBodiesR();for(const e of h){const n=t.polys[e]||i.rooms.find(t=>t.id===e).poly,o=d.length&&ml(Object.entries(t.polys).map(([t,e])=>({id:t,poly:e})),e,d,p,this._wallKeyPitch,this._cellCm,this._gridPitch,pm)||n,r=$i(o),a=u.length?ic(ec(o,u))*Math.pow(this._cellCm/this._gridPitch,2)/1e4:Rr(o,this._gridPitch,this._cellCm);s.push({x:r[0],y:r[1],text:Ir(a,c),area:!0})}return s}_rszInnerSpanCms(t,e,i){const s=Object.keys(i).length?Object.entries(i).map(([t,e])=>({id:t,poly:e})):this._spaceModel()?.rooms;if(!s?.length)return null;const n=this._spaceWalls;if(!n.length)return null;const o=function(t,e,i,s,n,o,r,a=1){const l=(t||[]).find(t=>t?.id===e),c=hi(l);if(!c||c.length<3)return null;const h=hl(t,e,i,s,n,o,r,a);if(!h)return c.map(()=>0);const d=4*Ka(n,a);return c.map((t,e)=>{const i=c[(e+1)%c.length],s=[(t[0]+i[0])/2,(t[1]+i[1])/2];for(let t=0;tt.segs),this._wallKeyPitch,this._cellCm,this._gridPitch,pm);if(!o||o.length!==e.length)return null;const r=this._cellCm/this._gridPitch;return e.map((t,i)=>function(t,e,i){const s=t?.length||0;if(s<3||!Array.isArray(i)||i.length!==s)return 0;const n=(Math.trunc(e)%s+s)%s,o=t[n],r=t[(n+1)%s],a=r[0]-o[0],l=r[1]-o[1],c=Math.hypot(a,l);if(!(c>0))return 0;const h=Math.max(0,Number(i[n])||0);if(!(h>0))return c;const d=[a/c,l/c],p=Xa(t,n),u=[o[0]+p[0]*h,o[1]+p[1]*h],_=e=>{const n=Math.max(0,Number(i[e])||0);if(!(n>0))return null;const r=t[e],a=t[(e+1)%s],l=a[0]-r[0],c=a[1]-r[1],h=Math.hypot(l,c);if(!(h>0))return null;const p=Xa(t,e),_=Za(u,d,[r[0]+p[0]*n,r[1]+p[1]*n],[l/h,c/h]);return _?(_[0]-o[0])*d[0]+(_[1]-o[1])*d[1]:null},g=_((n-1+s)%s)??0,m=(_((n+1)%s)??c)-g;return m>0?m:0}(e,i,o)*r)}_rszScaleLabels(t){const e="mi"===this.hass?.config?.unit_system?.length,i=t.map(t=>t[0]),s=t.map(t=>t[1]),n=this._spaceWalls,o=n.length&&this._rszSel&&ml([{id:this._rszSel,poly:t}],this._rszSel,n,[],this._wallKeyPitch,this._cellCm,this._gridPitch,pm)||t,r=$i(o),a=this._physicalBodiesR(),l=a.length?ic(ec(o,a))*Math.pow(this._cellCm/this._gridPitch,2)/1e4:Rr(o,this._gridPitch,this._cellCm),c=o.map(t=>t[0]),h=o.map(t=>t[1]),d=Math.max(...c)-Math.min(...c),p=Math.max(...h)-Math.min(...h);return[{x:Math.min(...i),y:Math.min(...s),text:`${this._fmtLen([0,0],[d,0])} × ${this._fmtLen([0,0],[p,0])}`},{x:r[0],y:r[1],text:Ir(l,e),area:!0}]}_renderResizeLayer(t){const e=Math.max(.013*t.w,5),i=e/2,s=t=>t.toFixed(1),n=`M ${s(-.7*i)} 0 H ${s(.7*i)} M 0 ${s(-.22*i)} V ${s(-i)} M ${s(-.32*i)} ${s(-.6*i)} L 0 ${s(-i)} L ${s(.32*i)} ${s(-.6*i)} M 0 ${s(.22*i)} V ${s(i)} M ${s(-.32*i)} ${s(.6*i)} L 0 ${s(i)} L ${s(.32*i)} ${s(.6*i)}`,o=[],r=this._rszRooms();for(const t of r)for(let i=0;i + `}_stageAspect(){const t=this._stageEl,e=this._baseVb();return t&&t.clientHeight?t.clientWidth/t.clientHeight:e[2]/e[3]}_viewOr(t){return this._view&&this._view.w?this._view:Oi(t,this._stageAspect())}_roomLabelReferenceViewWidth(t){if(!this._markup)return t.w;const e=this._stageEl,i=this.renderRoot.querySelector(".editorchrome");if(!e||e.clientWidth<=0||e.clientHeight<=0)return t.w;const s=e.clientHeight+(i?.getBoundingClientRect().height||0);return s<=0?t.w:this._viewForModeTarget(this._zoom,void 0,void 0,e.clientWidth,s).w}_screenToVb(t,e){const i=this._stageEl,s=this._viewOr(this._baseVb()),n=i?.clientWidth||1,o=i?.clientHeight||1;return[s.x+t/n*s.w,s.y+e/o*s.h]}_clampView(t,e){const i=(t,e,i,s)=>{const n=1*Math.max(e,s),o=i-n,a=i+s-e+n;return Math.max(Math.min(o,a),Math.min(Math.max(o,a),t))};return{w:t.w,h:t.h,x:i(t.x,t.w,e.x,e.w),y:i(t.y,t.h,e.y,e.h)}}_applyView(t,e,i){const s=this._baseVb(),n=Oi(s,this._stageAspect()),o=Math.min(km.ZOOM_MAX,Math.max(km.ZOOM_MIN,t)),a=n.w/o,r=n.h/o,l=this._viewOr(s),c=e??l.x+l.w/2,h=i??l.y+l.h/2,d=this._clampView({x:c-a/2,y:h-r/2,w:a,h:r},n);return!(this._view&&Math.abs(this._zoom-o)<1e-9&&Math.abs(this._view.x-d.x)<1e-6&&Math.abs(this._view.y-d.y)<1e-6&&Math.abs(this._view.w-d.w)<1e-6&&Math.abs(this._view.h-d.h)<1e-6)&&("opening"===this._tool&&(this._cursorPt=null,this._clearOpeningPlacement(!1)),this._zoom=o,this._view=d,!0)}_bootWatch(){clearTimeout(this._bootTimer),this._bootStart=Date.now(),this._bootLastH=-1,this._bootLastChange=this._bootStart;const t=()=>{if(!this._booting)return;const e=Date.now(),i=this._stageEl?this._stageEl.clientHeight:0;i!==this._bootLastH&&(this._bootLastH=i,this._bootLastChange=e);const s=e-this._bootStart;s>=1200||s>=700&&i>0&&e-this._bootLastChange>=250?this._bootSettled():this._bootTimer=window.setTimeout(t,100)};this._bootTimer=window.setTimeout(t,100)}_bootSettled(){this._booting&&!this._bootSettling&&(this._bootSettling=!0,this._refitView(),this._bootSettleRaf=requestAnimationFrame(()=>{this._bootSettleRaf=0,this._finishBootSettled()}))}_finishBootSettled(){if(!this._booting)return;this._refitView(),this._booting=!1,this._bootSettling=!1;const t=this._stageEl?.clientHeight??0;!this._config?.kiosk&&t>0&&this._warmPatch({hdrH:this._hdrH,stageH:t,vp:this._warmViewportState()},!0),this._bootFading=!0,this._bootTimer=window.setTimeout(()=>{this._bootFading=!1},220),this._bootSoft=!0,clearTimeout(this._bootSoftTimer),this._bootSoftTimer=window.setTimeout(()=>{this._bootSoft=!1},Zg)}_bootSoftCancel(){this._bootSoft&&(clearTimeout(this._bootSoftTimer),this._bootSoft=!1)}_beginResumeSettle(){this._booting||this._resumeSettling||(this._modeTransitionPreparing?this._modeTransitionForceAtomic=!0:this._cancelModeTransition(!0),this._viewportInvalidAt=0,this._beginContinuityCandidate("warm-resume",!1),this._loading?this.requestUpdate():this._loadFromServer())}_refitView(){if(this._modeTransitionBusy)return;const t=this._stageEl;if(!t||"visible"!==document.visibilityState||t.clientWidth<=0||t.clientHeight<=0)return void(this._viewportInvalidAt||(this._viewportInvalidAt=Date.now()));const e=[t.clientWidth,t.clientHeight],i=this._lastValidStageSize,s=!!i&&Math.abs(i[0]-e[0])<=.5&&Math.abs(i[1]-e[1])<=.5,n=this._viewportInvalidAt?Date.now()-this._viewportInvalidAt:0;if(this._viewportInvalidAt=0,!i)return this._lastValidStageSize=e,void(this._view||this._applyView(this._zoom));s?this._pendingRefitSize=null:(this._pendingRefitSize=e,this._refitRaf||(this._refitRaf=requestAnimationFrame(()=>{this._refitRaf=0;const t=this._pendingRefitSize;this._pendingRefitSize=null;const e=this._stageEl;if(!t||!e||e.clientWidth<=0||e.clientHeight<=0)return;if(Math.abs(e.clientWidth-t[0])>.5||Math.abs(e.clientHeight-t[1])>.5)return void this._refitView();const i=this._lastValidStageSize;if(i&&Math.abs(i[0]-t[0])<=.5&&Math.abs(i[1]-t[1])<=.5)return;this._lastValidStageSize=t;const s=this._view;n>=kh?this._beginContinuityCandidate("stage-size-restored",!0,"stage-size"):this._continuity.hasCompleteFrame&&this._beginContinuityCandidate("stage-resize",!0,"stage-size"),this._applyView(this._zoom,s?s.x+s.w/2:void 0,s?s.y+s.h/2:void 0)})))}_zoomAt(t,e,i){const s=this._stageEl;if(!s)return;const n=Oi(this._baseVb(),this._stageAspect()),o=Math.min(km.ZOOM_MAX,Math.max(km.ZOOM_MIN,i));"opening"===this._tool&&(this._cursorPt=null,this._clearOpeningPlacement(!1));const a=s.clientWidth,r=s.clientHeight,l=this._screenToVb(t,e),c=n.w/o,h=n.h/o;this._zoom=o,this._view=this._clampView({x:l[0]-t/a*c,y:l[1]-e/r*h,w:c,h:h},n)}_onWheel(t){const e=this._stageEl;if(!e)return;t.preventDefault();const i=e.getBoundingClientRect(),s=t.deltaY<0?1.15:1/1.15;this._zoomAt(t.clientX-i.left,t.clientY-i.top,this._zoom*s),this._saveZoom()}_stepZoom(t){const e=this._stageEl;e&&(this._zoomAt(e.clientWidth/2,e.clientHeight/2,this._zoom*(t>0?1.4:1/1.4)),this._saveZoom())}_resetZoom(){const t=this._baseVb();"opening"===this._tool&&(this._cursorPt=null,this._clearOpeningPlacement(!1)),this._zoom=1,this._view=Oi(t,this._stageAspect()),this._saveZoom()}_saveZoom(){if("view"===this._mode){this._zoomBySpace={...this._zoomBySpace,[this._space]:this._zoom};try{localStorage.setItem(lm,JSON.stringify(this._zoomBySpace))}catch{}}}_restoreZoom(){const t=this._zoomBySpace[this._space]||1;this._zoom=t;const e=this._stageEl;if(e&&e.clientHeight){const e=this._baseVb();return this._applyView(t,e[0]+e[2]/2,e[1]+e[3]/2),void this.requestUpdate()}this._view=null,requestAnimationFrame(()=>{if(!this._stageEl)return;const e=this._baseVb();this._applyView(t,e[0]+e[2]/2,e[1]+e[3]/2),this.requestUpdate()})}_stagePointerDown(t){if(this._vacFit)return;if(this._kiosk&&(this._cyclePausedUntil=Date.now()+6e4,0===this._pointers.size?(this._swipeStart={x:t.clientX,y:t.clientY,id:t.pointerId},t.target.closest?.(".dev, .roomlabel, .oplock")||(clearTimeout(this._kioskHoldTimer),this._kioskHoldTimer=window.setTimeout(()=>{this._kioskDialog=!0,this._swipeStart=null},3e3))):(this._swipeStart=null,clearTimeout(this._kioskHoldTimer))),this._drag)return;if(this._markup&&t.target.closest?.(".roomlabel, .rlhandle, .rszhandle, .dev, .oplock, .op-hit, button"))return;if("devices"===this._mode&&t.target.closest(".dev"))return;if("decor"===this._mode&&this._decorPointerDown(t))return;this._pointers.set(t.pointerId,{x:t.clientX,y:t.clientY});const e=this._viewOr(this._baseVb());if(1===this._pointers.size)this._panStart={sx:t.clientX,sy:t.clientY,vx:e.x,vy:e.y},this._panLock=null,this._suppressClick=!1;else if(2===this._pointers.size){this._cancelBoundaryAnchor(),"opening"===this._tool?(this._cursorPt=null,this._clearOpeningPlacement(!1)):"draw"===this._tool&&this._clearPlanSnapHover();const t=[...this._pointers.values()],e=Math.hypot(t[0].x-t[1].x,t[0].y-t[1].y);this._pinchStart={dist:e,zoom:this._zoom},this._panStart=null,this._panLock=null}}get _swipeZone(){return!this._hasFixedFloor&&this._kiosk&&this._zoom<=1.001&&this._model.length>1}_stagePointerMove(t){if(this._physicalRotate?.pid!==t.pointerId)if(this._physicalDrag?.pid!==t.pointerId)if(this._dtDrag?.pid!==t.pointerId)if(this._bdDrag?.pid!==t.pointerId){if(this._decorDraft?.pid===t.pointerId){const e=this._decorDraft;let i=this._decorSnap(this._svgPoint(t),t.pointerType);if(t.shiftKey&&("rect"===e.kind||"ellipse"===e.kind)){const t=i[0]-e.a[0],s=i[1]-e.a[1],n=Math.max(Math.abs(t),Math.abs(s));i=this._snap([e.a[0]+(t<0?-n:n),e.a[1]+(s<0?-n:n)])}return void(this._decorDraft={...e,b:i})}if(this._decorMove?.pid!==t.pointerId)if(this._pointers.has(t.pointerId)){if(this._pointers.set(t.pointerId,{x:t.clientX,y:t.clientY}),this._markup&&1===this._pointers.size&&this._markupMove(t),this._pinchStart&&this._pointers.size>=2){"opening"===this._tool?(this._cursorPt=null,this._clearOpeningPlacement(!1)):"draw"===this._tool&&this._clearPlanSnapHover();const t=[...this._pointers.values()],e=Math.hypot(t[0].x-t[1].x,t[0].y-t[1].y)/(this._pinchStart.dist||1),i=this._stageEl.getBoundingClientRect(),s=(t[0].x+t[1].x)/2-i.left,n=(t[0].y+t[1].y)/2-i.top;this._zoomAt(s,n,this._pinchStart.zoom*e),this._suppressClick=!0,this._saveZoom()}else if(this._panStart){const e=t.clientX-this._panStart.sx,i=t.clientY-this._panStart.sy;Math.abs(e)+Math.abs(i)>4&&(this._suppressClick=!0,clearTimeout(this._holdTimer),"opening"===this._tool?(this._cursorPt=null,this._clearOpeningPlacement(!1)):"draw"===this._tool&&this._clearPlanSnapHover()),null===this._panLock&&Math.abs(e)+Math.abs(i)>8&&(this._panLock=this._swipeZone&&Math.abs(e)>1.5*Math.abs(i)?"swipe":"pan");const s=this._stageEl;if("pan"===this._panLock&&s){const t=this._baseVb(),n=this._viewOr(t),o=Oi(t,this._stageAspect());this._view=this._clampView({x:this._panStart.vx-e/(s.clientWidth||1)*n.w,y:this._panStart.vy-i/(s.clientHeight||1)*n.h,w:n.w,h:n.h},o)}}}else this._markupMove(t);else this._decorMoveUpdate(t)}else this._bdMove(t);else this._dtMove(t);else this._physicalMove(t);else this._physicalRotateMove(t)}_stagePointerLeave(t){this._markup&&("opening"===this._tool?(this._cursorPt=null,this._clearOpeningPlacement(!1)):"draw"===this._tool&&this._clearPlanSnapHover())}_stagePointerUp(t){if(this._kiosk){clearTimeout(this._kioskHoldTimer);const e=this._swipeStart;if(this._swipeStart=null,e&&e.id===t.pointerId){const i=t.clientX-e.x,s=t.clientY-e.y;if(Math.abs(i)+Math.abs(s)<8){const t=Date.now();t-this._lastTap<350&&this._resetZoom(),this._lastTap=t}const n="pan"===this._panLock?null:function(t,e,i,s,n,o=60){if(i>1.001||s.length<2)return null;if(Math.abs(t)t.id),this._space);n&&this._slideTo(n,i<0?"left":"right")&&(this._saveNav(),this._suppressClick=!0,setTimeout(()=>this._suppressClick=!1,0),this._showKioskDots())}}if(this._physicalDrag?.pid===t.pointerId)return void this._physicalUp(t);if(this._physicalRotate?.pid===t.pointerId)return void this._physicalRotateUp(t);if(this._dtDrag?.pid===t.pointerId)return void this._dtUp();if(this._bdDrag?.pid===t.pointerId)return void this._bdUp();if(this._decorDraft?.pid===t.pointerId)return void this._decorCommitDraft();if(this._decorMove?.pid===t.pointerId)return this._decorMove.moved&&(this._recordGeometry(this._t("history.decor_move"),this._decorMove.before),this._saveConfig()),void(this._decorMove=null);const e=!!this._pinchStart||!!this._panStart;this._pointers.delete(t.pointerId),this._pointers.size<2&&(this._pinchStart=null),0===this._pointers.size&&(this._panStart=null,this._panLock=null,setTimeout(()=>this._suppressClick=!1,0)),e&&0===this._pointers.size&&this.requestUpdate()}_clickRoom(t){!this._suppressClick&&t.area&&ym("/config/areas/area/"+t.area)}_pointerDown(t,e){if("plan"===this._mode)return;if("view"===this._mode){this._holdFired=!1,clearTimeout(this._holdTimer);const i=t.pointerId,s=t.currentTarget;return void(this._holdTimer=window.setTimeout(()=>{this._holdFired=!0,this._interruptViewGesture(i,s),this._infoCard=e},600))}if("ha_disabled"===e.bindingStatus?.kind)return;t.preventDefault();const i=this._pos(e);this._drag={id:e.id,sx:t.clientX,sy:t.clientY,ox:i.x,oy:i.y,moved:!1},wm(t),this._tip=null}_pointerMove(t,e){if(!this._drag||this._drag.id!==e.id)return;const i=this.renderRoot.querySelector(".stage");if(!i)return;const s=this._baseVb(),n=i.getBoundingClientRect(),o=this._viewOr(s),a=(t.clientX-this._drag.sx)/n.width*o.w,r=(t.clientY-this._drag.sy)/n.height*o.h;Math.abs(t.clientX-this._drag.sx)+Math.abs(t.clientY-this._drag.sy)>3&&(this._drag.moved=!0,clearTimeout(this._holdTimer));const l=Cc(this._drag.ox+a),c=Cc(this._drag.oy+r);this._savePos(e,l,c)}_pointerUp(t,e){if(clearTimeout(this._holdTimer),!this._drag||this._drag.id!==e.id)return;const i=this._drag.moved;this._drag=i?this._drag:null,i&&(this._selId=e.id,window.setTimeout(()=>this._drag=null,0))}_showToast(t){for(const t of this.renderRoot.querySelectorAll("hp-dialog"))t.closeTransientOverlays("toast");this._toast=t,clearTimeout(this._toastTimer),this._toastTimer=window.setTimeout(()=>{this._toast=""},3500)}_syncPointerHoverTargets(){const t=this._pointerModality.hoverEnabled;for(const e of this.renderRoot.querySelectorAll(pm))e.toggleAttribute("data-pointer-hover",t)}_syncPointerHoverSubtree(t){if(t.nodeType!==Node.ELEMENT_NODE)return;const e=t,i=this._pointerModality.hoverEnabled;e.matches(pm)&&e.toggleAttribute("data-pointer-hover",i);for(const t of e.querySelectorAll(pm))t.toggleAttribute("data-pointer-hover",i)}_clearTransientHover(t=!1){t&&this._pointerModality.suspend(),this._tip&&(this._tip=null),this._hoverRoom&&(this._hoverRoom=null)}_notePointer(t){this._boundaryPointerType=t.pointerType||"mouse";const e=this._pointerModality.modality,i=this._pointerModality.note(t);"touch"!==i&&"pen"!==i||e===i&&!this._tip&&!this._hoverRoom||this._clearTransientHover()}_guardTouchGesture(t){if(this._editorSecondary.handleOutsideDismiss(t))return;if("click"===t.type){if(!this._suppressClick&&!this._touchSequenceMultitouch&&Date.now()>this._touchClickBlockUntil)return;return t.preventDefault(),void t.stopImmediatePropagation()}const e=t;if(this._notePointer(e),"touch"===e.pointerType)if("pointerdown"!==t.type){if("pointermove"===t.type){const t=this._touchContacts.get(e.pointerId);if(!t)return;const i={...t,x:e.clientX,y:e.clientY};if(this._touchContacts.set(e.pointerId,i),this._touchSequenceMultitouch&&"view"===this._mode&&!this._vacFit&&this._pinchStart&&[...this._touchContacts.values()].every(t=>t.inStage)){this._pointers.set(e.pointerId,{x:e.clientX,y:e.clientY});const t=[...this._touchContacts.values()];if(t.length>=2&&this._stageEl){const[e,i]=t,s=Math.hypot(e.x-i.x,e.y-i.y)/(this._pinchStart.dist||1),n=this._stageEl.getBoundingClientRect();this._zoomAt((e.x+i.x)/2-n.left,(e.y+i.y)/2-n.top,this._pinchStart.zoom*s),this._saveZoom()}}return}if("pointerup"===t.type||"pointercancel"===t.type||"lostpointercapture"===t.type){if(this._clearTransientHover(),this._touchContacts.delete(e.pointerId),this._touchSequenceMultitouch){if(this._touchClickBlockUntil=Date.now()+500,this._pointers.delete(e.pointerId),!this._vacFit&&this._pointers.size>=2){const[t,e]=[...this._pointers.values()];this._pinchStart={dist:Math.hypot(t.x-e.x,t.y-e.y),zoom:this._zoom}}else this._pinchStart=null;0===this._pointers.size&&(this._panStart=null,this._panLock=null)}0===this._touchContacts.size&&(this._touchSequenceMultitouch=!1)}}else if(this._touchContacts.set(e.pointerId,{x:e.clientX,y:e.clientY,inStage:!!e.target?.closest?.(".stage")}),this._touchContacts.size>=2){this._clearTransientHover(),this._touchSequenceMultitouch=!0,this._touchClickBlockUntil=Number.POSITIVE_INFINITY,clearTimeout(this._holdTimer),clearTimeout(this._kioskHoldTimer),this._swipeStart=null;const t=[...this._touchContacts.values()];if("view"===this._mode&&!this._vacFit&&t.every(t=>t.inStage)){this._pointers=new Map([...this._touchContacts].map(([t,e])=>[t,{x:e.x,y:e.y}]));const[e,i]=t;this._pinchStart={dist:Math.hypot(e.x-i.x,e.y-i.y),zoom:this._zoom},this._panStart=null,this._panLock=null}else this._vacFit&&(this._pointers.clear(),this._pinchStart=null,this._panStart=null,this._panLock=null)}}_showTip(t,e,i,s,n,o){this._notePointer(t),this._pointerModality.hoverEnabled&&(this._drag||(this._tip={x:t.clientX,y:t.clientY,title:e,meta:i,lqi:s,temp:n,hum:o}))}get _gridPitch(){return xc}get _cellCm(){const t=Number(this._curSpaceCfg?.cell_cm);return Number.isFinite(t)&&t>0?t:5}_fmtLen(t,e){const i=function(t,e,i,s){return Math.hypot(e[0]-t[0],e[1]-t[1])/i*s}(t,e,this._gridPitch,this._cellCm);return li(i,"mi"===this.hass?.config?.unit_system?.length)}get _curSpaceCfg(){const t=this._rszPreview;return t&&t.space===this._space?t.sp:this._serverCfg?.spaces.find(t=>t.id===this._space)}get _renderCfg(){const t=this._rszPreview;return t&&this._serverCfg?{...this._serverCfg,spaces:this._serverCfg.spaces.map(e=>e.id===t.space?t.sp:e)}:this._serverCfg}get _spaceH(){return this._curSpaceCfg,um}get _segments(){const t=this._curSpaceCfg,e=this._spaceH;return pi(t?.rooms||[]).map(t=>[t[0]*um,t[1]*e,t[2]*um,t[3]*e])}_savedNav(){if(this._hasFixedFloor)return null;try{return JSON.parse(localStorage.getItem(cm)||"null")}catch{return null}}_saveNav(){if(!this._hasFixedFloor)try{localStorage.setItem(cm,JSON.stringify({space:this._space}))}catch{}}_leaveCardRoute(){if(this._routeDepartureHandled)return;this._routeDepartureHandled=!0,"view"!==this._mode&&this._setMode("view",!1),this._pendingNavMode=null,this._geometryHistory.clear(),this._activeDraftId=null,this._resumeDraftBySpace={},this._draftSegmentCms=[],this._closingWallCm=null,this._drawWallField=null,this._showHidden=!1,this._tapConfirm=null,this._vacCalConfirm=null,this._decorEraseConfirm=null,this._openingInfo=null,this._closeInfoCard(),this._rulesDialog=null,this._alignDialog=null,this._backupImportDialog=null,this._backupExportDialog=null,this._settingsDialog=null,this._markerDialog=null,this._openingDialog=null,this._physicalDialog=null,this._wallDialog=null,this._backdropDialog=null,this._decorShapeDialog=null,this._decorTextDialog=null,this._mergeDialog=null,this._roomDialog=!1,this._spaceDialog=null,this._importDialog=null;const t=this._warmSlot;t?.owner===this._warmGen&&(t.vp=this._warmViewportState(),t.dlg=null,t.frameFingerprint="",clearTimeout(t.evict),t.evict=0),this._saveNav()}_setMode(t,e=!0){this._endTabDrag(),this._pendingNavMode=null;const i=this._spaceModel();if(!i)return this._cancelModeTransition(!1),void(this._mode="view");if(this._kiosk&&"view"!==t)return;if(this._mode===t){if(!e&&"view"===t&&this._modeTransitionBusy){const e=this._currentModeVisual(t),i=this._modeTransitionTargetZoom,s=this._modeTransitionTargetCenterX,n=this._modeTransitionTargetCenterY;this._cancelModeTransition(!1),this._commitViewModeAtomic(e,i,s,n)}return}if(this._bootSoftCancel(),("plan"===t||"decor"===t)&&!this._norm)return void this._showToast(this._t("toast.markup_needs_server"));if(this._wallFaceBatch&&this._roomDialogCancel(),"plan"===this._mode&&"draw"===this._tool&&!this._finishWallChain())return;this._clearTransientHover(!0),this._cancelDevicePressFeedback();const s=this._mode,n=this._effectiveProjection(),o=this._currentModeVisual(s),a=this._modeTransitionBusy,r=o&&"view"!==s&&"view"!==t?{...o,toolbarContentOpacity:this._reducedMotion?1:.35}:o;this._cancelModeTransition(!1),this._editorSecondary.closeForNavigation(),(this._decorMove||this._dtDrag||this._bdDrag)&&this._cancelDecorGesture();const l=!i.bg&&"view"===t!=("view"===s),c=a&&"view"===s&&"view"!==t?this._modeTransitionEditorCamera:null;let h=c?.zoom??(a?this._modeTransitionTargetZoom:this._zoom),d=c?c.centerX:a?this._modeTransitionTargetCenterX:r?.viewport.centerX,p=c?c.centerY:a?this._modeTransitionTargetCenterY:r?.viewport.centerY;if("view"===s&&"view"!==t&&!a){const e=this._view;if(this._viewModeSnap={space:this._space,zoom:this._zoom,cx:e?this._logicalViewCenter(n)?.x:void 0,cy:e?this._logicalViewCenter(n)?.y:void 0},"iso"===n){const e=this._logicalViewCenter("iso");d=e?.x,p=e?.y,this._view=null,this._mode=t,this._applyView(this._zoom,e?.x,e?.y)}l&&(h=1,d=void 0,p=void 0)}if("plan"===s&&this._activeDraftId&&(this._resumeDraftBySpace[this._space]=this._activeDraftId),this._mode=t,this._editorChromeMode="view"===t?s:t,"view"===t){"view"===s||a||(this._modeTransitionEditorCamera={zoom:this._zoom,centerX:r?.viewport.centerX,centerY:r?.viewport.centerY});const t=this._viewModeSnap;if(t&&t.space===this._space){h=t.zoom;const e=this._labsIso&&"iso"===this._viewPreference[this._space]?"iso":"flat",i=null!=t.cx&&null!=t.cy&&"iso"===e?lg([t.cx,t.cy],0):null;d=i?.[0]??t.cx,p=i?.[1]??t.cy}else t&&(h=this._zoomBySpace[this._space]||1,d=void 0,p=void 0)}else this._modeTransitionEditorCamera={zoom:h,centerX:d,centerY:p};this._modeTransitionTargetZoom=h,this._modeTransitionTargetCenterX=d,this._modeTransitionTargetCenterY=p,("iso"===n||"view"===t&&this._labsIso&&"iso"===this._viewPreference[this._space])&&(this._modeTransitionForceAtomic=!0);const u=++this._modeTransitionRequest;e?r?(this._modeTransitionPreparing=!0,this._modeTransitionVisual=r,this._prepareModeTransition(u,r,t,h,d,p)):(this._modeTransitionPreparing=!1,this._modeTransitionVisual=null,this._zoom=h,this._view=null,requestAnimationFrame(()=>{this.isConnected&&u===this._modeTransitionRequest&&this._mode===t&&(this._applyView(h,d,p),"view"===t&&(this._viewModeSnap=null,this._modeTransitionEditorCamera=null),this.requestUpdate())})):"view"===t&&this._commitViewModeAtomic(r,h,d,p),this._path=[],this._clearPlanSnapHover(),this._clearOpeningPlacement(!0),this._openWallAnchor=null,this._boundaryRestoreGuard=null,this._tool="draw",this._mergeSel=null,this._mergeDialog=null,this._splitSel=null,this._pendingSplit=null,this._selId=null,this._physicalSel=null,this._physicalDialog=null,this._physicalDrag=null,this._rszSel=null,this._rszDrag=null,this._rszLive=null,this._rszPreview=null,this._tip=null,this._hoverRoom=null,this._decorDraft=null,this._decorSel=null,this._decorMove=null,this._backdropDialog=null,this._decorTool="select",this._bdDrag=null,this._dtDrag=null,this._dtBox=null,"plan"===t&&(this._primeDrawWallField(),this._resumeLastDraft()),this._saveNav()}_primeDrawWallField(){null===this._drawWallField&&(this._drawWallField=kr(fr,this._imperial))}get _drawWallFieldValue(){return null===this._drawWallField?kr(fr,this._imperial):this._drawWallField}get _drawWallCm(){const t=Qg(this._drawWallFieldValue);if(null==t||t<=0)return null;const e=this._imperial?2.54*t:t,i="column"===this._tool?Ll:100;return e>=1&&e<=i?e:null}get _drawWallMaxCm(){return"column"===this._tool?Ll:100}_showPhysicalRange(t=this._drawWallMaxCm){this._showToast(this._t("toast.physical_range",{max:kr(t,this._imperial),unit:this._t(this._imperial?"wallthick.unit_in":"wallthick.unit_cm")}))}_draftSegmentCount(t=this._curSpaceCfg){return(t?.room_drafts||[]).reduce((t,e)=>t+(Array.isArray(e.segments)?e.segments.length:0),0)}_mergeSpacePartitions(t,e){const i=t?.partitions||[];if(i.length<2)return 0;const s=a_(i,{pitch:$c,seedIds:e,geometry:l_(t,{excludeDraftId:this._activeDraftId})});return s.merged?(t.partitions=s.partitions,r_(t.openings,t.partitions,s.openingMoves,{coordScale:um,cellCm:this._cellCm,gridPitch:this._gridPitch}),s.merged):0}_finishWallChain(){if("draw"!==this._tool||this._wallFaceBatch||this._roomDialog)return!0;const t=this._curSpaceCfg;if(!t||this._path.length<2)return this._path=[],this._activeDraftId=null,this._draftSegmentCms=[],this._closingWallCm=null,this._clearPlanSnapHover(),!0;const e=ep(this._path,tp(this._path.length-1,this._draftSegmentCms,this._drawWallCm,fr)),i=e.length;if((t.partitions||[]).length+i>fm)return this._showToast(this._t("toast.physical_limit")),!1;const s=this._geometrySnapshot();t.partitions||=[];const n=Date.now().toString(36),o=[];for(let s=0;st.id!==this._activeDraftId),t.room_drafts.length||delete t.room_drafts),this._recordGeometry(this._t("history.wall_chain_finish"),s),this._saveConfig(),delete this._resumeDraftBySpace[this._space],this._path=[],this._activeDraftId=null,this._draftSegmentCms=[],this._closingWallCm=null,this._clearPlanSnapHover(),!0}_activateMarkupTool(t){t!==this._tool&&(this._wallFaceBatch&&this._roomDialogCancel(),("draw"!==this._tool||this._finishWallChain())&&(this._cancelPath(),this._tool=t,"draw"===t&&this._resumeLastDraft(),"resize"===t&&(this._rszSel=null),"boundary"!==t&&"wallthick"!==t||(this._wallDialog=null)))}_limitReached(t){const e=this._curSpaceCfg;if(!e)return!0;const i="draft"===t?(e.room_drafts||[]).length>=200:"partition"===t?(e.partitions||[]).length>=fm:(e.wall_columns||[]).length>=500;return i&&this._showToast(this._t("toast.physical_limit")),i}_svgPoint(t){const e=this.renderRoot.querySelector(".stage").getBoundingClientRect();return this._screenToVb(t.clientX-e.left,t.clientY-e.top)}_snap(t){const e=this._gridPitch;return[Cc(ri(t[0],e)),Cc(ri(t[1],e))]}_snapDrawPoint(t,e=!1){const i=this._path[this._path.length-1],s=e&&i?function(t,e,i,s=1/0){if(!(i>0&&t?.every(Number.isFinite)&&e?.every(Number.isFinite)))return[e[0],e[1]];const n=e[0]-t[0],o=e[1]-t[1];if(Math.abs(n)+Math.abs(o)<=1e-12)return[t[0],t[1]];const a=Math.PI/4;let r=Math.atan2(o,n);r<0&&(r+=2*Math.PI);const l=Math.floor(r/a+.5)%8,[c,h]=[[1,0],[1,1],[0,1],[-1,1],[-1,0],[-1,-1],[0,-1],[1,-1]][l],d=c*c+h*h;let p=Math.max(0,Math.round((n*c+o*h)/(i*d)));if(Number.isFinite(s)&&s>=0){const e=(t,e)=>{if(!e)return 1/0;const n=e>0?s-t:t+s;return Math.max(0,Math.floor((n+1e-9*i)/i))};p=Math.min(p,e(t[0],c),e(t[1],h))}return[t[0]+c*p*i,t[1]+h*p*i]}(i,t,this._gridPitch,wc):t;return this._snap(s)}_planSnapOpeningCuts(t,e){if(!this._openingsR.length)return[];const i=this._openingWallIndexFor(t,e).value,s=[];for(const e of this._roomWallOpeningInputs(this._openingsR,t)){const t=El(i,e);if(!t.negative&&!t.positive)continue;const n=e.angle*Math.PI/180,o=Math.cos(n)*e.length/2,a=Math.sin(n)*e.length/2;s.push([e.x-o,e.y-a,e.x+o,e.y+a])}return s}_planSnapGeometrySnapshot(){const t=this._spaceModel();if(!t)return{key:`${this._space}|empty`,value:{segments:[],endpoints:[]}};const e=[this._space,this._cfgEpoch,this._activeDraftId||"",t.rooms.length,t.room_drafts.length,t.partitions.length].join("|");if(this._planSnapGeometryCache?.key===e)return this._planSnapGeometryCache;const i=this._openCuts(),s=Gd({space:t,activeDraftId:this._activeDraftId,roomCuts:[...i,...this._planSnapOpeningCuts(t,i)],partitionCuts:this._partitionOpeningCuts(t),epsilon:2e-4*this._gridPitch});return this._planSnapGeometryCache={key:e,value:s},this._planSnapGeometryCache}_planStructuralGeometrySnapshot(){const t=this._spaceModel();if(!t)return{key:`${this._space}|structural-empty`,value:{segments:[],endpoints:[]}};const e=["structural",this._space,this._cfgEpoch,this._activeDraftId||"",t.rooms.length,t.room_drafts.length,t.partitions.length].join("|");if(this._planStructuralGeometryCache?.key===e)return this._planStructuralGeometryCache;const i=Gd({space:t,activeDraftId:this._activeDraftId,roomCuts:this._openCuts(),epsilon:2e-4*this._gridPitch});return this._planStructuralGeometryCache={key:e,value:i},this._planStructuralGeometryCache}_planSnapContextKey(t){const e=this._path[0],i=this._path[this._path.length-1];return[t,this._tool,this._path.length,e?`${e[0]},${e[1]}`:"",i?`${i[0]},${i[1]}`:""].join("|")}_resolvePlanDrawPoint(t,e){const i=this._planSnapGeometrySnapshot(),s=this._path[this._path.length-1],n="draw"===this._tool&&this._path.length>=3?[{point:this._path[0],key:"closure:first-point"}]:[],o={tolerance:this._cssPxToRender(12),distinguishTolerance:this._cssPxToRender(8),gridStep:this._gridPitch,excludePoints:s?[s]:[],extraEndpoints:n,epsilon:2e-4*this._gridPitch},a=e&&s?Zd(i.value,t,{...o,anchor:s}):function(t,e,i){if(!(Hd(e)&&i.tolerance>=0))return{kind:"none",candidate:null,conflicts:[]};const s=i.epsilon??Nd,n=i.excludePoints||[],o=Xd(Yd(t,e,i),i.distinguishTolerance||0);if(o)return o;let a=null;for(const o of t.segments){const t=[o.a[0],o.a[1],o.b[0],o.b[1]],r=Hs([e[0],e[1]],t);if(r>i.tolerance)continue;const l=Jd(o,e,i.gridStep);!Vd(l,n,s)&&Kd(r,o.key,a)&&(a={kind:"line",point:l,key:o.key,distance:r,segment:o})}return a?{kind:"resolved",candidate:a,conflicts:[]}:{kind:"none",candidate:null,conflicts:[]}}(i.value,t,o),r="resolved"===a.kind?a.candidate:null;return{point:r?[...r.point]:this._snapDrawPoint(t,e),candidate:r,conflicts:"ambiguous"===a.kind?a.conflicts:[],ambiguous:"ambiguous"===a.kind,contextKey:this._planSnapContextKey(i.key)}}get _activePlanSnapCandidate(){if(!this._markup||"draw"!==this._tool)return null;const t=this._planSnapHover;if(!t)return null;const e=this._planSnapGeometrySnapshot();return t.contextKey===this._planSnapContextKey(e.key)?t.candidate:null}get _activePlanSnapConflicts(){if(!this._markup||"draw"!==this._tool)return[];const t=this._planSnapHover;if(!t)return[];const e=this._planSnapGeometrySnapshot();return t.contextKey===this._planSnapContextKey(e.key)?t.conflicts:[]}_clearPlanSnapHover(t=!0){this._planSnapHover=null,this._syncPlanSnapActiveMarker(null),this._syncPlanSnapConflictMarkers([]),t&&(this._cursorPt=null)}_samePt(t,e){return fi(t,e)}_dropLegacySegments(){for(const t of this._serverCfg?.markers||[])"ripple"===t.display&&(t.display="icon_ripple");for(const t of this._serverCfg?.spaces||[]){delete t.segments;const e=new Set,i=t=>"string"==typeof t&&t.length>=1&&t.length<=64&&!e.has(t),s=t=>(e.add(t),!0),n=t=>Array.isArray(t)&&2===t.length&&t.every(t=>Number.isFinite(Number(t))&&Math.abs(Number(t))<=bc);if(Array.isArray(t.partitions)&&(t.partitions=t.partitions.filter(t=>t&&i(t.id)&&n(t.a)&&n(t.b)&&Math.hypot(t.a[0]-t.b[0],t.a[1]-t.b[1])>1e-9&&s(t.id)).map(t=>({...t,cm:Math.max(1,Math.min(100,Number(t.cm)||15))})),t.partitions.length||delete t.partitions),Array.isArray(t.wall_columns)&&(t.wall_columns=t.wall_columns.filter(t=>t&&i(t.id)&&n(t.center)&&s(t.id)).map(t=>({id:t.id,shape:"circle"===t.shape?"circle":"square",center:[Number(t.center[0]),Number(t.center[1])],cm:ql(Number(t.cm)||15),..."circle"===t.shape?{}:{angle:Wl(t.angle)}})),t.wall_columns.length||delete t.wall_columns),Array.isArray(t.room_drafts)&&(t.room_drafts=t.room_drafts.filter(t=>t&&i(t.id)&&Array.isArray(t.points)&&t.points.length>=2&&t.points.every(n)&&s(t.id)).map(t=>{const e=[[Number(t.points[0][0]),Number(t.points[0][1])]],i=[];for(let s=1;st.points.length>=2),t.room_drafts.length||delete t.room_drafts),Array.isArray(t.walls)){const e=rh(t.open_spans).map(t=>[t.a[0],t.a[1],t.b[0],t.b[1]]);t.walls=Er(t.walls,t.rooms||[],$c,1,e),t.walls.length||delete t.walls}}}get _cfgWriting(){return this._writesPending>0}_writeConfig(){var t,e;this._writesPending++,this._writeChain=(t=this._writeChain,e=async()=>{if(!this._serverCfg)return;this._dropLegacySegments();const t=Qu(this._serverCfg),e=Dh(t);e!==Dh(this._serverCfg)&&(this._serverCfg=t),this._cfgContentFingerprint=e;const i=await this.hass.callWS({type:"houseplan/config/set",config:t,expected_rev:this._cfgRev});this._cfgRev=i?.rev??this._cfgRev+1},t.catch(()=>{}).then(e));return this._writeChain.finally(()=>{this._writesPending--})}_saveConfig(){this._cfgEpoch++,this._saveConfigDebounced()}_geometrySnapshot(t=this._space){const e=this._serverCfg?.spaces.find(e=>e.id===t);if(!e)return null;const i=t=>JSON.parse(JSON.stringify(t)),s={};for(const t of["plan_x","plan_y","plan_scale","plan_scale_x","plan_scale_y","plan_angle"])void 0!==e[t]&&(s[t]=e[t]);return{spaceId:t,rooms:i(e.rooms||[]),...Array.isArray(e.openings)?{openings:i(e.openings)}:{},...Array.isArray(e.walls)?{walls:i(e.walls)}:{},...Array.isArray(e.open_spans)?{open_spans:i(e.open_spans)}:{},...Array.isArray(e.room_drafts)?{room_drafts:i(e.room_drafts)}:{},...Array.isArray(e.partitions)?{partitions:i(e.partitions)}:{},...Array.isArray(e.wall_columns)?{wall_columns:i(e.wall_columns)}:{},...Array.isArray(e.decor)?{decor:i(e.decor)}:{},plan_transform:s}}_recordGeometry(t,e){if(!e)return;const i=this._geometrySnapshot(e.spaceId);i&&JSON.stringify(e)!==JSON.stringify(i)&&(this._geometryHistory.push({name:t,before:e,after:i}),this.requestUpdate())}_clearGeometryGesture(){this._path=[],this._clearPlanSnapHover(),this._clearOpeningPlacement(!1),this._mergeSel=null,this._mergeDialog=null,this._splitSel=null,this._pendingSplit=null,this._wallFaceBatch=null,this._wallRepairDiagnostic=null,this._roomDeleteDialog=null,this._openWallAnchor=null,this._boundaryRestoreGuard=null,this._wallDialog=null,this._physicalDialog=null,this._physicalSel=null,this._physicalDrag=null,this._physicalRotate=null,this._activeDraftId=null,this._draftSegmentCms=[],this._closingWallCm=null,this._openingDialog=null,this._rszSel=null,this._rszDrag=null,this._rszPreview=null,this._rszLive=null,this._decorDraft=null,this._decorMove=null,this._dtDrag=null,this._bdDrag=null}_cancelBoundaryAnchor(){return!("boundary"!==this._tool||!this._openWallAnchor)&&(this._openWallAnchor=null,this._boundaryRestoreGuard=null,this._clearPlanSnapHover(),this.requestUpdate(),!0)}_stagePointerCancel(t){if(clearTimeout(this._kioskHoldTimer),this._swipeStart?.id===t.pointerId&&(this._swipeStart=null),this._physicalDrag?.pid===t.pointerId||this._physicalRotate?.pid===t.pointerId)return void this._cancelPhysicalGesture();if(this._decorDraft?.pid===t.pointerId)return this._decorDraft=null,void this.requestUpdate();if(this._decorMove?.pid===t.pointerId||this._dtDrag?.pid===t.pointerId||this._bdDrag?.pid===t.pointerId)return void this._cancelDecorGesture();this._cancelBoundaryAnchor(),"opening"===this._tool?(this._cursorPt=null,this._clearOpeningPlacement(!1)):"draw"===this._tool&&this._clearPlanSnapHover();const e=!!this._pinchStart||!!this._panStart;this._pointers.delete(t.pointerId),this._pointers.size<2&&(this._pinchStart=null),0===this._pointers.size&&(this._panStart=null,this._panLock=null),e&&0===this._pointers.size&&this.requestUpdate()}_applyGeometryState(t){if(!this._canCommitSpace(t.spaceId))return!1;const e=this._serverCfg?.spaces.find(e=>e.id===t.spaceId);if(!e)return!1;const i=t=>JSON.parse(JSON.stringify(t));e.rooms=i(t.rooms),void 0!==t.openings?e.openings=i(t.openings):delete e.openings,void 0!==t.walls?e.walls=i(t.walls):delete e.walls,void 0!==t.open_spans?e.open_spans=i(t.open_spans):delete e.open_spans,void 0!==t.room_drafts?e.room_drafts=i(t.room_drafts):delete e.room_drafts,void 0!==t.partitions?e.partitions=i(t.partitions):delete e.partitions,void 0!==t.wall_columns?e.wall_columns=i(t.wall_columns):delete e.wall_columns,void 0!==t.decor?e.decor=i(t.decor):delete e.decor;for(const t of["plan_x","plan_y","plan_scale","plan_scale_x","plan_scale_y","plan_angle"])delete e[t];return Object.assign(e,i(t.plan_transform||{})),this._clearGeometryGesture(),this._space!==t.spaceId&&(this._commitSpace(t.spaceId),this._saveNav(),this._restoreZoom()),this._modelCache=null,this._frame=null,this._regSignature="",this._maybeRebuildDevices(),this._saveConfig(),this.requestUpdate(),!0}_roomAt(t){return this._spaceModel()?.rooms.find(e=>{const i=hi(e);return!!i&&wi(t,i)})}_overlapRoom(t){return this._spaceModel()?.rooms.find(e=>{const i=hi(e);return!!i&&Di(t,i)})}_pointInRoom(t,e){return e.poly?vi(t,e.poly):null!=e.x&&t[0]>=e.x&&t[0]<=e.x+e.w&&t[1]>=e.y&&t[1]<=e.y+e.h}_contourSelfIntersects(t){if(!ka(t))return!0;const e=t.length,i=.001;for(let s=0;s=500)return this._showToast(this._t("toast.physical_limit")),!1;const t=this._curSpaceCfg;return!(!this._activeDraftId&&(t?.room_drafts||[]).length>=200||this._draftSegmentCount(t)>=2e3||(t?.partitions||[]).length+this._path.length>fm)||(this._showToast(this._t("toast.physical_limit")),!1)}_markupClick(t){if(this._vacFit)return;if(!this._markup)return;const e=this._spaceModel();if(!e)return void this._clearGeometryGesture();if(this._suppressClick)return;if(this._drag||this._rlResize)return;const i=t.composedPath?.()||[];if(i.some(t=>t?.classList?.contains?.("roomlabel")||t?.classList?.contains?.("rlhandle")))return;if(i.some(t=>t?.classList?.contains?.("physical-hit")))return void("boundary"===this._tool&&this._showToast(this._t("toast.boundary_blocked")));const s=this._svgPoint(t);if("select"===this._tool)return void(this._physicalSel=null);if("resize"===this._tool){if(this._rszDrag||i.some(t=>t?.classList?.contains?.("rszhandle")))return;const t=[...e.rooms].reverse().find(t=>this._pointInRoom(s,t));return void(this._rszSel=t?.id||null)}if("delroom"===this._tool)return void this._deleteRoomClick(s);if("opening"===this._tool)return void this._openingClick(s);if("merge"===this._tool)return void this._mergeClick(s);if("wallthick"===this._tool)return void this._wallThickClick(s);if("boundary"===this._tool)return void this._boundaryClick(s);if("split"===this._tool)return void this._splitClick(s);if("column"===this._tool)return void this._columnClick(s);this._wallRepairDiagnostic=null;const n=this._resolvePlanDrawPoint(s,t.shiftKey);if(n.ambiguous)return this._planSnapHover={contextKey:n.contextKey,candidate:null,conflicts:n.conflicts},this._syncPlanSnapActiveMarker(null),this._syncPlanSnapConflictMarkers(n.conflicts),void this._showToast(this._t("toast.plan_snap_ambiguous"));let o=n.point;if(t.ctrlKey||t.metaKey){if(t.preventDefault(),this._path.length<3)return;o=[...this._path[0]]}if(!this._path.length){if(!t.shiftKey&&!n.candidate&&this._offerExistingWallFace(s))return;const e=this._draftEndAt(o);return e?(this._activeDraftId=e.draft.id,this._resumeDraftBySpace[this._space]=e.draft.id,this._path=e.reverse?[...e.draft.points].reverse().map(t=>[...t]):e.draft.points.map(t=>[...t]),void(this._draftSegmentCms=this._adoptDraftCms(this._path,e.reverse?[...e.draft.segments].reverse().map(t=>t.cm):e.draft.segments.map(t=>t.cm),e.draft.id))):(this._activeDraftId=null,this._draftSegmentCms=[],void(this._path=[o]))}const a=this._path[this._path.length-1];if(this._samePt(o,a))return;const r=this._draftEndAt(o,this._activeDraftId||void 0);if(r)return void this._mergeDraftEndpoint(r);if(!this._canAppendRoomDraftPoint())return;const l=this._drawWallCm;if(null==l)return void this._showPhysicalRange(100);const c=this._path.map(t=>[...t]);this._path=[...this._path,o],this._draftSegmentCms=[...this._draftSegmentCms,l],this._persistActiveDraftSegment(),this._offerWallFaces(c)}_draftEndAt(t,e){const i=this._spaceModel();if(!i)return null;const s=this._viewOr(this._baseVb()),n=Math.max(.15*this._gridPitch,this._stageEl?.clientWidth?s.w/this._stageEl.clientWidth*12:0);for(const s of i.room_drafts||[]){if(s.id===e)continue;if(s.points.length<2)continue;const i=s.points[0],o=s.points[s.points.length-1];if(Math.hypot(t[0]-o[0],t[1]-o[1])<=n)return{draft:s,reverse:!1};if(Math.hypot(t[0]-i[0],t[1]-i[1])<=n)return{draft:s,reverse:!0}}return null}_mergeDraftEndpoint(t){const e=this._curSpaceCfg;if(!e||!this._path.length)return;const i=this._path.map(t=>[...t]),s=this._wallGraphSources(i),n=Array.isArray(e.room_drafts)?e.room_drafts:[],o=this._activeDraftId?n.find(t=>t.id===this._activeDraftId):null,a=n.find(e=>e.id===t.draft.id);if(!a)return;const r=t.reverse?t.draft.points.map(t=>[...t]):[...t.draft.points].reverse().map(t=>[...t]),l=t.reverse?(a.segments||[]).map(t=>({...t})):[...a.segments||[]].reverse().map(t=>({...t})),c=this._path[this._path.length-1],h=this._samePt(c,r[0]),d=h?null:this._drawWallCm;if(!h&&null==d)return void this._showPhysicalRange(100);const p=this._draftSegmentCms.map((t,e)=>({...o?.segments?.[e]||{},cm:t})),u=[...this._path.map(t=>[...t]),...h?r.slice(1):r],_=[...p,...null==d?[]:[{cm:d}],...l],g=u.length>=4&&this._samePt(u[0],u[u.length-1]),m=u,f=_;if(m.length>500)return void this._showToast(this._t("toast.physical_limit"));const v=(o?.segments?.length||0)+(a.segments?.length||0);if(this._draftSegmentCount(e)-v+f.length>2e3)return void this._showToast(this._t("toast.physical_limit"));if(g){const t=m.slice(0,-1);if(this._contourSelfIntersects(t)||Pi(t)<=1e-6)return void this._showToast(this._t("toast.contour_cannot_close"));const e=this._overlapRoom(t);if(e)return void this._showToast(this._t("toast.room_overlap",{name:e.name||""}))}const y=this._geometrySnapshot(),b=this._activeDraftId||t.draft.id,w={...o||a,id:b,points:m.map(t=>[t[0]/um,t[1]/um]),segments:f};e.room_drafts=n.filter(e=>e.id!==t.draft.id&&(!this._activeDraftId||e.id!==this._activeDraftId)),e.room_drafts.push(w),this._activeDraftId=b,this._resumeDraftBySpace[this._space]=b,this._path=m,this._draftSegmentCms=this._adoptDraftCms(m,f.map(t=>Number(t.cm)),b),this._physicalSel=null,this._recordGeometry(this._t("history.draft_merge"),y),this._saveConfig(),null!=d&&this._offerWallFaces(i,i.length-1,s)}_adoptDraftCms(t,e,i){const s=Math.max(0,t.length-1),n=tp(s,e,this._drawWallCm,fr);return e.length!==s&&console.debug(`[houseplan] draft ${i??"?"}: восстановлено толщин ${s-e.length} (#234)`),n}_persistActiveDraftSegment(){if(this._path.length<2||!this._curSpaceCfg)return;const t=this._geometrySnapshot(),e=this._curSpaceCfg;e.room_drafts||=[],this._activeDraftId||(this._activeDraftId="draft-"+Date.now().toString(36)),this._resumeDraftBySpace[this._space]=this._activeDraftId;const i=e.room_drafts.findIndex(t=>t.id===this._activeDraftId),s={...i>=0?e.room_drafts[i]:{},id:this._activeDraftId,points:this._path.map(t=>[t[0]/um,t[1]/um]),segments:this._draftSegmentCms.map((t,s)=>({...i>=0?e.room_drafts[i]?.segments?.[s]:{},cm:t}))};i>=0?e.room_drafts[i]=s:e.room_drafts.push(s),this._recordGeometry(this._t("history.draft_segment"),t),this._saveConfig()}_activeWallSourceKey(t){return`active:${this._activeDraftId||"session"}:${t}`}_wallGraphSources(t){const e=this._planStructuralGeometrySnapshot().value.segments.map(t=>({a:t.a,b:t.b,key:`static:${t.key}`}));for(let i=0;i+1t.key===i);if(s>=0){const[t]=this._wallFaceGraphCache.splice(s,1);return this._wallFaceGraphCache.push(t),t.value}const n=xp(t,e);return this._wallFaceGraphCache.push({key:i,value:n}),this._wallFaceGraphCache.length>4&&this._wallFaceGraphCache.shift(),n}_offerWallFaces(t,e=this._path.length-2,i){if(this._path.length<2||this._wallFaceBatch||this._roomDialog)return;const s=this._spaceModel();if(!s)return;const n=this._activeWallSourceKey(e),o=2e-4*this._gridPitch;let a,r;try{const e=i||this._wallGraphSources(t);r=this._wallGraphSources(this._path),a=function(t,e,i){const s=new Set(t.faces.map(t=>t.key));return e.faces.filter(t=>!s.has(t.key)&&t.sourceKeys.includes(i))}(this._wallFaceGraph(e,o),this._wallFaceGraph(r,o),n)}catch{return}if(!a.length){const t=Ep(r,{requiredSourceKey:n,maxDistance:xr(2,this._cellCm,this._gridPitch),gridStep:this._gridPitch,epsilon:o});return"ambiguous"===t.kind?(this._wallRepairDiagnostic=t.proposals[0]||null,void this._showToast(this._t("toast.wall_repair_ambiguous"))):void("repair"!==t.kind||this._overlapRoom(t.face.ring)||this._beginWallFaceBatch([{...t.face,repair:t.proposal}]))}for(const t of s.rooms){const e=hi(t);if(!t.id||!e)continue;const i=Fi(e,this._path,.02*this._gridPitch);if(!i)continue;const[s,n]=i,o=Pi(s)>=Pi(n)?s:n,r=o===s?n:s,l=[...a].sort((t,e)=>Math.abs(t.area-Pi(r))-Math.abs(e.area-Pi(r))||t.key.localeCompare(e.key))[0];if(!l)return;return void this._beginWallFaceBatch([{...l,ring:r.map(t=>[t[0],t[1]]),split:{roomId:t.id,mainPoly:o,newPoly:r},consumeAllActive:!0}])}const l=a.filter(t=>!(t.ring.length<3||this._contourSelfIntersects(t.ring))&&!this._overlapRoom(t.ring));l.length&&this._beginWallFaceBatch(l)}_beginWallFaceBatch(t){this._wallRepairDiagnostic=null,this._wallFaceBatch={candidates:[...t].sort((t,e)=>t.area-e.area||t.key.localeCompare(e.key)),index:0,decisions:[],activePath:this._path.map(t=>[...t]),activeCms:[...this._draftSegmentCms],activeDraftId:this._activeDraftId},this._clearPlanSnapHover(),this._nameSel="",this._areaSel="",this._resetRoomDialogFields(),this._roomDialog=!0}_offerExistingWallFace(t){if(this._path.length||this._wallFaceBatch||this._roomDialog)return!1;const e=2e-4*this._gridPitch;try{let i,s=$p(this._wallFaceGraph(this._wallGraphSources([]),e),t,e);if(!s){const n=Ep(this._wallGraphSources([]),{point:t,maxDistance:xr(2,this._cellCm,this._gridPitch),gridStep:this._gridPitch,epsilon:e});if("ambiguous"===n.kind)return this._wallRepairDiagnostic=n.proposals[0]||null,this._showToast(this._t("toast.wall_repair_ambiguous")),!0;if("repair"===n.kind)s=n.face,i=n.proposal;else if("none"===n.kind){const i=Ep(this._wallGraphSources([]),{point:t,maxDistance:this._cssPxToRender(12),gridStep:this._gridPitch,epsilon:e});if("repair"===i.kind)return this._wallRepairDiagnostic=i.proposal,this._showToast(this._t("toast.wall_repair_too_large")),!0}}return!(!s||s.ring.length<3||this._contourSelfIntersects(s.ring)||this._overlapRoom(s.ring))&&(this._beginWallFaceBatch([{...s,existing:!i,repair:i}]),!0)}catch{return!1}}_columnClick(t){const e=this._snap(t),i=this._drawWallCm;if(null==i)return void this._showPhysicalRange(Ll);if(!this._curSpaceCfg||this._limitReached("column"))return;const s=this._spaceModel();if(!s)return;const n={id:"column-"+Date.now().toString(36),shape:"square",center:e,cm:ql(i),angle:0},o=(s.wall_columns||[]).find(t=>rc(t,n,.02*this._gridPitch));if(o)return clearTimeout(this._duplicateColumnTimer),this._duplicateColumnId=o.id,this._duplicateColumnTimer=window.setTimeout(()=>{this._duplicateColumnId=null},900),void this._showToast(this._t("toast.column_duplicate"));const a=this._geometrySnapshot(),r=this._curSpaceCfg;r.wall_columns||=[],r.wall_columns.push({...n,center:[e[0]/um,e[1]/um]}),this._recordGeometry(this._t("history.column_add"),a),this._saveConfig()}_openPhysicalDialog(t,e,i){const s=this._spaceModel();if(s)if("partition"===t){const i=s.partitions.find(t=>t.id===e);i&&(this._physicalDialog={kind:t,id:e,cm:kr(i.cm,this._imperial),length:this._fmtLen(i.a,i.b)})}else if("column"===t){const i=s.wall_columns.find(t=>t.id===e);i&&(this._physicalDialog={kind:t,id:e,cm:kr(i.cm,this._imperial),shape:i.shape,angle:this._angleField("square"===i.shape?Wl(i.angle):0)})}else{const n=s.room_drafts.find(t=>t.id===e),o=Math.max(0,Math.min(n?.segments.length?n.segments.length-1:0,i||0));n?.segments[o]&&(this._physicalDialog={kind:t,id:e,segment:o,cm:kr(n.segments[o].cm,this._imperial),length:this._fmtLen(n.points[o],n.points[o+1])})}}_physicalDown(t,e,i){const s=this._spaceModel();if(!s)return;t.stopPropagation(),wm(t);const n=this._svgPoint(t),o=[];for(const t of[...s.wall_columns].reverse())oc(n,Yl(t,this._cellCm,this._gridPitch))&&o.push({kind:"column",id:t.id});for(const t of[...s.partitions].reverse()){const e=Kl(t.a,t.b,t.cm,this._cellCm,this._gridPitch);e&&oc(n,e)&&o.push({kind:"partition",id:t.id})}o.some(t=>t.kind===e&&t.id===i)||o.unshift({kind:e,id:i});const a=o.map(t=>`${t.kind}:${t.id}`).sort().join("|"),r=performance.now(),l=this._physicalPickCycle,c=o.length>1&&l?.signature===a&&r-l.at>380&&r-l.at<=1200&&Math.hypot(t.clientX-l.x,t.clientY-l.y)<=10?(l.index+1)%o.length:Math.max(0,o.findIndex(t=>t.kind===e&&t.id===i));this._physicalPickCycle={signature:a,index:c,x:t.clientX,y:t.clientY,at:r},e=o[c].kind,i=o[c].id;const h="partition"===e?s.partitions.find(t=>t.id===i):s.wall_columns.find(t=>t.id===i);h&&(this._physicalSel={kind:e,id:i},this._physicalDrag={pid:t.pointerId,kind:e,id:i,start:this._svgPoint(t),startClient:[t.clientX,t.clientY],before:this._geometrySnapshot(),moved:!1,base:JSON.parse(JSON.stringify(h)),delta:[0,0]})}_clampPhysicalDelta(t,e,i){const s="partition"===t?[e.a,e.b]:[e.center],n=s.map(t=>t[0]),o=s.map(t=>t[1]);return[Math.max(-bc*um-Math.min(...n),Math.min(bc*um-Math.max(...n),i[0])),Math.max(-bc*um-Math.min(...o),Math.min(bc*um-Math.max(...o),i[1]))]}_physicalMove(t){const e=this._physicalDrag;if(!e||e.pid!==t.pointerId)return;t.stopPropagation();const i=this._svgPoint(t),s="partition"===e.kind?e.base.a:e.base.center,n=this._snap([s[0]+i[0]-e.start[0],s[1]+i[1]-e.start[1]]),o=this._clampPhysicalDelta(e.kind,e.base,[n[0]-s[0],n[1]-s[1]]);this._physicalDrag={...e,delta:o,moved:e.moved||Math.hypot(t.clientX-e.startClient[0],t.clientY-e.startClient[1])>=5}}_physicalUp(t){const e=this._physicalDrag;if(!e||e.pid!==t.pointerId)return;if(t.stopPropagation(),this._physicalDrag=null,!e.moved)return void this._registerPhysicalTap(e.kind,e.id);const i=this._spaceModel();if(!this._curSpaceCfg||!i)return;const s=this._curSpaceCfg;if("partition"===e.kind){const t=(s.partitions||[]).find(t=>t.id===e.id),i=e.base;if(t){const n={...i,a:[i.a[0]+e.delta[0],i.a[1]+e.delta[1]],b:[i.b[0]+e.delta[0],i.b[1]+e.delta[1]]};t.a=[n.a[0]/um,n.a[1]/um],t.b=[n.b[0]/um,n.b[1]/um];for(const t of s.openings||[]){if("partition"!==t.host?.kind||t.host.id!==e.id)continue;const i=Rd(t,[n],um,this._cellCm,this._gridPitch).resolved;i&&Object.assign(t,Od(t,i,um))}}}else{const t=(s.wall_columns||[]).find(t=>t.id===e.id),n=e.base,o={...n,center:[n.center[0]+e.delta[0],n.center[1]+e.delta[1]]};if(i.wall_columns.some(t=>t.id!==e.id&&rc(t,o,.02*this._gridPitch)))return void this._showToast(this._t("toast.column_duplicate"));t&&(t.center=[(n.center[0]+e.delta[0])/um,(n.center[1]+e.delta[1])/um])}this._recordGeometry(this._t("history.physical_move"),e.before),this._saveConfig()}_registerPhysicalTap(t,e,i){const s=performance.now(),n=this._physicalLastTap?.kind===t&&this._physicalLastTap.id===e&&this._physicalLastTap.segment===i&&s-this._physicalLastTap.at<=360;this._physicalLastTap={kind:t,id:e,segment:i,at:s},n&&(this._physicalLastTap=null,this._openPhysicalDialog(t,e,i))}_cancelPhysicalGesture(){this._physicalDrag=null,this._physicalRotate=null,this.requestUpdate()}_physicalRotateDown(t,e){if("square"!==e.shape||!this._spaceModel())return;t.preventDefault(),t.stopPropagation(),wm(t);const i=this._svgPoint(t);this._physicalSel={kind:"column",id:e.id},this._physicalRotate={pid:t.pointerId,id:e.id,center:[...e.center],startAngle:180*Math.atan2(i[1]-e.center[1],i[0]-e.center[0])/Math.PI,baseAngle:Wl(e.angle),angle:Wl(e.angle),before:this._geometrySnapshot(),moved:!1}}_physicalRotateMove(t){const e=this._physicalRotate;if(!e||e.pid!==t.pointerId)return;t.preventDefault(),t.stopPropagation();const i=this._svgPoint(t),s=180*Math.atan2(i[1]-e.center[1],i[0]-e.center[0])/Math.PI,n=e.baseAngle+s-e.startAngle,o=Wl(t.shiftKey?n:5*Math.round(n/5));this._physicalRotate={...e,angle:o,moved:e.moved||Math.abs(n-e.baseAngle)>=.5}}_physicalRotateUp(t){const e=this._physicalRotate;if(!e||e.pid!==t.pointerId)return;t.preventDefault(),t.stopPropagation(),this._physicalRotate=null;const i=this._spaceModel();if(!e.moved||!this._curSpaceCfg||!i)return;const s=i.wall_columns.find(t=>t.id===e.id);if(!s||"square"!==s.shape)return;const n={...s,angle:e.angle};if(i.wall_columns.some(t=>t.id!==e.id&&rc(t,n,.02*this._gridPitch)))return void this._showToast(this._t("toast.column_duplicate"));const o=this._curSpaceCfg.wall_columns?.find(t=>t.id===e.id);o&&(o.angle=e.angle,this._recordGeometry(this._t("history.physical_edit"),e.before),this._saveConfig())}_rszRooms(){const t=[],e=this._spaceModel();if(!e)return t;for(const i of e.rooms){const e=i.id?hi(i):null;e&&t.push({id:i.id,poly:e})}return t}_rszOpenings(){return this._openingsR.map(t=>({id:t.id,x:t.rx,y:t.ry,length:t.rlen}))}_rszOpts(){return{minDim:this._cmToUnits(30),eps:.05*this._gridPitch}}_rszSnapshot(){return JSON.stringify(this._geometrySnapshot()||{spaceId:this._space,rooms:[],openings:[],walls:[],open_spans:[]})}_rszApplyPreview(t,e){const i=this._rszDrag,s=this._serverCfg?.spaces.find(t=>t.id===this._space);if(!i||!s)return;const n=JSON.parse(i.snap),o={...s,rooms:n.rooms,openings:n.openings,walls:n.walls,open_spans:n.open_spans};Array.isArray(n.open_spans)&&n.open_spans.length||delete o.open_spans;const a=this._spaceH;for(const[e,i]of Object.entries(t)){const t=o.rooms.find(t=>t.id===e);t&&(t.poly=i.map(t=>[t[0]/um,t[1]/a]),delete t.x,delete t.y,delete t.w,delete t.h)}for(const[t,i]of Object.entries(e)){const e=(o.openings||[]).find(e=>e.id===t);e&&(e.x=i[0]/um,e.y=i[1]/a)}const r=[],l=[];for(const t of i.changed){const e=i.rooms.find(e=>e.id===t),s=o.rooms.find(e=>e.id===t);if(!e||!s?.poly)continue;const n=s.poly.map(t=>[t[0]*um,t[1]*a]);if(e.poly.length===n.length)for(let t=0;tt.id===e);if(!s||!s.poly||s.poly.length<3)return null;if(i<0||i>=s.poly.length)return null;const n=[...s.poly[i]],o=[...s.poly[(i+1)%s.poly.length]];return{roomId:e,edge:i,a:n,b:o,n:fa(s.poly,i)}}(s,e,i);n&&(this._rszDrag={kind:"edge",pid:t.pointerId,roomId:e,plan:n,rooms:s,openings:this._rszOpenings(),snap:this._rszSnapshot(),moved:!1,d:0,k:1,changed:[]})}_rszCornerDown(t,e,i,s){"resize"!==this._tool||this._rszDrag||(t.stopPropagation(),t.preventDefault(),wm(t),this._rszDrag={kind:"scale",pid:t.pointerId,roomId:e,fixed:s,span0:Math.hypot(i[0]-s[0],i[1]-s[1])||1,rooms:this._rszRooms(),openings:this._rszOpenings(),snap:this._rszSnapshot(),moved:!1,d:0,k:1,changed:[]})}_rszMove(t){const e=this._rszDrag;if(!e||e.pid!==t.pointerId)return;t.stopPropagation();const i=this._svgPoint(t);if("edge"===e.kind){const t=e.plan,s=(i[0]-t.a[0])*t.n[0]+(i[1]-t.a[1])*t.n[1],n=this._snap([t.a[0]+t.n[0]*s,t.a[1]+t.n[1]*s]);let o=(n[0]-t.a[0])*t.n[0]+(n[1]-t.a[1])*t.n[1];if(o=function(t,e,i,s,n,o){if(!Number.isFinite(s)||Math.abs(s)<1e-9)return 0;const a=Math.sign(s);let r=Math.abs(s);const l=Math.max(n,1e-6);for(let s=0;s<4096&&r>1e-9;s++,r-=l){const s=a*r;if(Da(t,e,i,s,o))return s}return 0}(e.rooms,e.openings,t,o,this._gridPitch,this._rszOpts()),o===e.d&&e.moved)return;e.d=o,e.moved=!0;const a=Sa(e.rooms,e.openings,t,o,this._rszOpts().eps);e.changed=Object.keys(a.polys),this._rszApplyPreview(a.polys,a.openings),this._rszLive=this._rszEdgeLabels(a,t)}else{const t=e.fixed,s=this._snap(i);let n=Math.hypot(s[0]-t[0],s[1]-t[1])/(e.span0||1);if(n=Math.max(.05,Math.min(20,n)),n=function(t,e,i,s,n,o){if(!Number.isFinite(n)||n<=0)return 1;if(Pa(t,e,i,s,n,o))return n;let a=1,r=n;for(let n=0;n<28;n++){const n=(a+r)/2;Pa(t,e,i,s,n,o)?a=n:r=n}return a}(e.rooms,e.openings,e.roomId,t,n,this._rszOpts()),n===e.k&&e.moved)return;e.k=n,e.moved=!0;const o=e.rooms.find(t=>t.id===e.roomId),a=e.rooms.filter(t=>t.id!==e.roomId).map(t=>t.poly),r=Ta(o,e.openings,a,t,n,2*this._rszOpts().eps);e.changed=[e.roomId],this._rszApplyPreview({[e.roomId]:r.poly},r.openings),this._rszLive=this._rszScaleLabels(r.poly)}this.requestUpdate()}_rszUp(t){const e=this._rszDrag;if(!e||e.pid!==t.pointerId)return;t.stopPropagation();const i=this._rszPreview;this._rszDrag=null,this._rszLive=null,this._rszPreview=null;if(!(e.moved&&("edge"===e.kind?Math.abs(e.d)>1e-9:Math.abs(e.k-1)>1e-9))||!i)return this._cfgEpoch++,void this.requestUpdate();const s=JSON.parse(e.snap),n=this._curSpaceCfg;if(n){n.rooms=i.sp.rooms,n.openings=i.sp.openings,Array.isArray(i.sp.walls)&&(i.sp.walls.length?n.walls=i.sp.walls:delete n.walls),Array.isArray(i.sp.open_spans)&&i.sp.open_spans.length?n.open_spans=i.sp.open_spans:delete n.open_spans;for(const t of e.changed){const e=n.rooms.find(e=>e.id===t);e?.poly&&(e.poly=wa(e.poly,1e-9))}this._commitOpenSpans(),Array.isArray(n.walls)&&n.walls.length&&(n.walls=Er(n.walls,n.rooms||[],$c,1,this._cfgOpenCuts()),n.walls.length||delete n.walls)}this._suppressClick=!0,setTimeout(()=>this._suppressClick=!1,0),this._recordGeometry(this._t("history.resize_room"),s),this._saveConfig(),this.requestUpdate()}_rszCancelDrag(){this._rszDrag&&(this._rszDrag=null,this._rszLive=null,this._rszPreview=null,this._cfgEpoch++,this.requestUpdate())}_rszPointerCancel(t){const e=this._rszDrag;e&&e.pid===t.pointerId&&(t.stopPropagation(),this._rszCancelDrag())}_rszEdgeLabels(t,e){const i=this._rszDrag,s=[],n=t.polys[e.roomId]||i.rooms.find(t=>t.id===e.roomId).poly,o=n.length,a=e.edge,r=(a+1)%o,l=this._rszInnerSpanCms(e.roomId,n,t.polys);for(const t of[(a-1+o)%o,a,r]){const e=n[t],i=n[(t+1)%o],a=l?.[t];s.push({x:(e[0]+i[0])/2,y:(e[1]+i[1])/2,text:null==a?this._fmtLen(e,i):li(a,"mi"===this.hass?.config?.unit_system?.length)})}const c="mi"===this.hass?.config?.unit_system?.length,h=Object.keys(t.polys).length?Object.keys(t.polys):[e.roomId],d=this._spaceWalls,p=this._openPairs().flatMap(t=>t.segs),u=this._physicalBodiesR();for(const e of h){const n=t.polys[e]||i.rooms.find(t=>t.id===e).poly,o=d.length&&fl(Object.entries(t.polys).map(([t,e])=>({id:t,poly:e})),e,d,p,this._wallKeyPitch,this._cellCm,this._gridPitch,um)||n,a=$i(o),r=u.length?sc(ic(o,u))*Math.pow(this._cellCm/this._gridPitch,2)/1e4:Ra(o,this._gridPitch,this._cellCm);s.push({x:a[0],y:a[1],text:Ia(r,c),area:!0})}return s}_rszInnerSpanCms(t,e,i){const s=Object.keys(i).length?Object.entries(i).map(([t,e])=>({id:t,poly:e})):this._spaceModel()?.rooms;if(!s?.length)return null;const n=this._spaceWalls;if(!n.length)return null;const o=function(t,e,i,s,n,o,a,r=1){const l=(t||[]).find(t=>t?.id===e),c=hi(l);if(!c||c.length<3)return null;const h=hl(t,e,i,s,n,o,a,r);if(!h)return c.map(()=>0);const d=4*Kr(n,r);return c.map((t,e)=>{const i=c[(e+1)%c.length],s=[(t[0]+i[0])/2,(t[1]+i[1])/2];for(let t=0;tt.segs),this._wallKeyPitch,this._cellCm,this._gridPitch,um);if(!o||o.length!==e.length)return null;const a=this._cellCm/this._gridPitch;return e.map((t,i)=>function(t,e,i){const s=t?.length||0;if(s<3||!Array.isArray(i)||i.length!==s)return 0;const n=(Math.trunc(e)%s+s)%s,o=t[n],a=t[(n+1)%s],r=a[0]-o[0],l=a[1]-o[1],c=Math.hypot(r,l);if(!(c>0))return 0;const h=Math.max(0,Number(i[n])||0);if(!(h>0))return c;const d=[r/c,l/c],p=Xr(t,n),u=[o[0]+p[0]*h,o[1]+p[1]*h],_=e=>{const n=Math.max(0,Number(i[e])||0);if(!(n>0))return null;const a=t[e],r=t[(e+1)%s],l=r[0]-a[0],c=r[1]-a[1],h=Math.hypot(l,c);if(!(h>0))return null;const p=Xr(t,e),_=Zr(u,d,[a[0]+p[0]*n,a[1]+p[1]*n],[l/h,c/h]);return _?(_[0]-o[0])*d[0]+(_[1]-o[1])*d[1]:null},g=_((n-1+s)%s)??0,m=(_((n+1)%s)??c)-g;return m>0?m:0}(e,i,o)*a)}_rszScaleLabels(t){const e="mi"===this.hass?.config?.unit_system?.length,i=t.map(t=>t[0]),s=t.map(t=>t[1]),n=this._spaceWalls,o=n.length&&this._rszSel&&fl([{id:this._rszSel,poly:t}],this._rszSel,n,[],this._wallKeyPitch,this._cellCm,this._gridPitch,um)||t,a=$i(o),r=this._physicalBodiesR(),l=r.length?sc(ic(o,r))*Math.pow(this._cellCm/this._gridPitch,2)/1e4:Ra(o,this._gridPitch,this._cellCm),c=o.map(t=>t[0]),h=o.map(t=>t[1]),d=Math.max(...c)-Math.min(...c),p=Math.max(...h)-Math.min(...h);return[{x:Math.min(...i),y:Math.min(...s),text:`${this._fmtLen([0,0],[d,0])} × ${this._fmtLen([0,0],[p,0])}`},{x:a[0],y:a[1],text:Ia(l,e),area:!0}]}_renderResizeLayer(t){const e=Math.max(.013*t.w,5),i=e/2,s=t=>t.toFixed(1),n=`M ${s(-.7*i)} 0 H ${s(.7*i)} M 0 ${s(-.22*i)} V ${s(-i)} M ${s(-.32*i)} ${s(-.6*i)} L 0 ${s(-i)} L ${s(.32*i)} ${s(-.6*i)} M 0 ${s(.22*i)} V ${s(i)} M ${s(-.32*i)} ${s(.6*i)} L 0 ${s(i)} L ${s(.32*i)} ${s(.6*i)}`,o=[],a=this._rszRooms();for(const t of a)for(let i=0;ithis._rszEdgeDown(e,t.id,i)} @pointermove=${t=>this._rszMove(t)} @pointerup=${t=>this._rszUp(t)} @pointercancel=${t=>this._rszPointerCancel(t)} - @lostpointercapture=${t=>this._rszPointerCancel(t)}>`),o.push(j``)}const a=this._rszSel?r.find(t=>t.id===this._rszSel):null;if(a){const t=a.poly.map(t=>t[0]),i=a.poly.map(t=>t[1]),s=Math.min(...t),n=Math.max(...t),r=Math.min(...i),l=Math.max(...i);o.push(j``);for(const[t,i,c,h]of[[s,r,n,l],[n,r,s,l],[n,l,s,r],[s,l,n,r]])o.push(j`this._rszCornerDown(e,a.id,[t,i],[c,h])} + @lostpointercapture=${t=>this._rszPointerCancel(t)}>`),o.push(j``)}const r=this._rszSel?a.find(t=>t.id===this._rszSel):null;if(r){const t=r.poly.map(t=>t[0]),i=r.poly.map(t=>t[1]),s=Math.min(...t),n=Math.max(...t),a=Math.min(...i),l=Math.max(...i);o.push(j``);for(const[t,i,c,h]of[[s,a,n,l],[n,a,s,l],[n,l,s,a],[s,l,n,a]])o.push(j`this._rszCornerDown(e,r.id,[t,i],[c,h])} @pointermove=${t=>this._rszMove(t)} @pointerup=${t=>this._rszUp(t)} @pointercancel=${t=>this._rszPointerCancel(t)} - @lostpointercapture=${t=>this._rszPointerCancel(t)}>`),o.push(j``)}return j`${o}`}get _openingsR(){const t=this._curSpaceCfg,e=this._spaceH,i=this._spaceModel();return i?(t?.openings||[]).flatMap(t=>{const s={...t,rx:t.x*pm,ry:t.y*e,rlen:t.length*pm};if(!t.host)return[s];const n=Pd(t,i.partitions,pm,this._cellCm,this._gridPitch);if(!n.resolved)return"plan"===this._mode?[{...s,orphanReason:n.reason||"invalid-host"}]:[];let[o,r]=n.resolved.center;const a=this._physicalDrag;return a?.moved&&"partition"===a.kind&&a.id===t.host.id&&(o+=a.delta[0],r+=a.delta[1]),[{...t,rx:o,ry:r,rlen:n.resolved.length,angle:n.resolved.angle,partitionHost:n.resolved}]}):[]}_partitionOpeningCuts(t=this._spaceModel(),e=()=>!0){if(!t)return[];return x_(k_(this._curSpaceCfg?.id===t.id?this._curSpaceCfg:null,t,this._cellCm,this._gridPitch,pm),e)}_roomWallOpeningInputs(t=this._openingsR,e=this._spaceModel()){if(!e)return[];const i=this._openPairs().flatMap(t=>t.segs);return $_(t,e,this._spaceWalls,i,this._wallKeyPitch,this._cellCm,this._gridPitch,pm)}_openingFace(t,e,i){return t.partitionHost?Fd(t.partitionHost,i):El(e,{x:t.rx,y:t.ry,angle:t.angle,length:t.rlen,flip_v:i})}_cmToUnits(t){return t/this._cellCm*this._gridPitch}get _decorList(){const t=this._curSpaceCfg;return Array.isArray(t?.decor)?t.decor:[]}get _decorH(){return pm}_decorResolvedStyle(t){return function(t,e,i,s=oa){const n="rect"===t?.kind||"ellipse"===t?.kind,o=t,r=Rt(o?.color,s.color);return{color:r,opacity:ra(o?.opacity,s.opacity),widthCm:da(t,e,i,s.widthCm),fill:!!n&&!0===o?.fill,fillColor:Rt(o?.fill_color,o?.fill?r:s.fillColor),fillOpacity:n&&o?.fill?ra(o?.fill_opacity,.25):s.fillOpacity}}(t,this._cellCm,this._gridPitch,oa)}_decorWidthUnits(t){return((t,e,i,s=oa.widthCm)=>{const n=Number(t?.width_cm);if(Number.isFinite(n)&&n>0)return ca(n,e,i);const o=Number(t?.width);return Number.isFinite(o)&&o>0?o:ca(s,e,i)})(t,this._cellCm,this._gridPitch,oa.widthCm)}_decorTextSizeCm(t){if("text"===t?.kind){const e=Number(t.size_cm);return Number.isFinite(e)&&e>0?e:ha(es*is(t),this._cellCm,this._gridPitch)}return ha(es,this._cellCm,this._gridPitch)}_decorTextUnits(t){if("text"!==t.kind)return es;const e=Number(t.size_cm);return Number.isFinite(e)&&e>0?ca(e,this._cellCm,this._gridPitch):es*is(t)}_decorSmallField(t){return Math.round(100*(this._imperial?t/2.54:t))/100}_decorSmallCm(t){const e=this._imperial?2.54*t:t;return Number.isFinite(e)?Math.max(.1,Math.min(100,e)):.1}_decorTextCm(t){const e=this._imperial?2.54*t:t;return Number.isFinite(e)?Math.max(.1,Math.min(Yg,e)):.1}_decorLargeField(t){return Math.round(100*(this._imperial?t/30.48:t/100))/100}_decorLargeCm(t){const e=this._imperial?30.48*t:100*t;return Number.isFinite(e)?Math.max(.1,Math.min(yc*this._cellCm,e)):.1}_angleField(t){const e=Number(t);return Number.isFinite(e)?String(Number(e.toFixed(3))):"0"}_decorBoxOf(t){return"rect"!==t.kind&&"ellipse"!==t.kind&&"furniture"!==t.kind?null:{x:t.x*pm,y:t.y*this._decorH,w:t.w*pm,h:t.h*this._decorH,angle:aa(t.angle)||void 0}}_decorSnapGeometry(t){const e=this._spaceModel();if(!e)return{points:[],segments:[]};const i=t||"",s=this._decorSnapCache;if(s&&s.epoch===this._cfgEpoch&&s.space===this._space&&s.height===this._decorH&&s.exclude===i)return s.geometry;const n=[];for(const e of this._decorList)if(e.id!==t)if("line"===e.kind){const t=[e.x1*pm,e.y1*this._decorH],i=[e.x2*pm,e.y2*this._decorH];n.push({points:[t,i,[(t[0]+i[0])/2,(t[1]+i[1])/2]],segments:[{a:t,b:i}]})}else if("text"===e.kind)n.push({points:[[e.x*pm,e.y*this._decorH]],segments:[]});else{const t=this._decorBoxOf(e);t&&n.push(_a(t))}for(const t of e.rooms){const e=hi(t);e?.length&&n.push({points:e.flatMap((t,i)=>{const s=e[(i+1)%e.length];return[t,[(t[0]+s[0])/2,(t[1]+s[1])/2]]}),segments:e.map((t,i)=>({a:t,b:e[(i+1)%e.length]}))})}const o=function(t){return{points:t.flatMap(t=>t.points),segments:t.flatMap(t=>t.segments)}}(n);return this._decorSnapCache={epoch:this._cfgEpoch,space:this._space,height:this._decorH,exclude:i,geometry:o},o}_decorSnap(t,e="mouse",i){const s=this._stageEl,n=this._viewOr(this._baseVb()),o="touch"===e||"pen"===e?14:8,r=s?n.w/Math.max(1,s.clientWidth)*o:this._gridPitch;return function(t,e,i,s){const n=s(t);let o=null;for(const n of e.points){const e=s(n),r=Math.hypot(e[0]-t[0],e[1]-t[1]);r<=i&&(!o||rthis._snap(t)).point}_replaceDecor(t,e){const i=this._curSpaceCfg;i&&(i.decor=this._decorList.map(i=>i.id===t?{...i,...e}:i),this.requestUpdate())}_cancelDecorGesture(){const t=this._decorMove?.before||this._dtDrag?.before||this._bdDrag?.before,e=t&&this._serverCfg?.spaces.find(e=>e.id===t.spaceId);if(t&&e){const i=t=>JSON.parse(JSON.stringify(t));void 0!==t.decor?e.decor=i(t.decor):delete e.decor;for(const t of["plan_x","plan_y","plan_scale","plan_scale_x","plan_scale_y","plan_angle"])delete e[t];Object.assign(e,i(t.plan_transform||{})),this._cfgEpoch++}this._decorMove=null,this._dtDrag=null,this._bdDrag=null,this.requestUpdate()}_decorPointerDown(t){const e=this._decorTool;if("select"===e||"erase"===e?t.target.closest?.(".dshape"):null)return!0;if("line"===e||"rect"===e||"ellipse"===e){t.preventDefault();const i=this._decorSnap(this._svgPoint(t),t.pointerType);return this._decorDraft={kind:e,a:i,b:i,pid:t.pointerId},bm(t),!0}if("text"===e){const e=this._decorSnap(this._svgPoint(t),t.pointerType);return this._decorTextDialog={x:Cc(e[0]/pm),y:Cc(e[1]/this._decorH),text:"",color:this._decorStyle.color,opacity:this._decorStyle.opacity,angle:"0",sizeCm:ha(es,this._cellCm,this._gridPitch)},this._decorTextSelection={start:0,end:0},!0}if("furniture"===e)return!!this._furnPalette&&(t.preventDefault(),this._furnPlace(this._svgPoint(t),t.shiftKey),!0);if("select"===e&&(this._decorSel=null),this._bdMovable){const e=this._bdRect,i=this._svgPoint(t),s=e.x+e.w/2,n=e.y+e.h/2,o=-aa(e.angle)*Math.PI/180,r=i[0]-s,a=i[1]-n,l=[s+r*Math.cos(o)-a*Math.sin(o),n+r*Math.sin(o)+a*Math.cos(o)];if(l[0]>=e.x&&l[0]<=e.x+e.w&&l[1]>=e.y&&l[1]<=e.y+e.h)return t.preventDefault(),this._bdStart(t)}return!1}_decorCommitDraft(){const t=this._decorDraft;if(this._decorDraft=null,!t)return;const e=.5*this._gridPitch;if(!function(t,e,i,s){const n=Math.abs(i[0]-e[0]),o=Math.abs(i[1]-e[1]);return"line"===t?Math.hypot(n,o)>=s:n>=s&&o>=s}(t.kind,t.a,t.b,e))return;const i=pm,s=this._decorH,n=this._decorStyle,o=this._geometrySnapshot(),r="dc"+Date.now().toString(36)+Math.random().toString(36).slice(2,5),a=Cc;let l;if("line"===t.kind)l={id:r,kind:"line",x1:a(t.a[0]/i),y1:a(t.a[1]/s),x2:a(t.b[0]/i),y2:a(t.b[1]/s),...pa(n,!1)};else{const e=a(Math.min(t.a[0],t.b[0])/i),o=a(Math.min(t.a[1],t.b[1])/s),c=Math.abs(t.b[0]-t.a[0])/i,h=Math.abs(t.b[1]-t.a[1])/s;l={id:r,kind:t.kind,x:e,y:o,w:c,h:h,...pa(n,!0)}}this._curSpaceCfg.decor=[...this._decorList,l],this._decorSel=r,this._recordGeometry(this._t("history.decor_add"),o),this._saveConfig(),this.requestUpdate()}_decorShapeDown(t,e){if("decor"!==this._mode)return;const i=this._decorTool;if("text"===i){if("text"!==e.kind)return;return t.stopPropagation(),t.preventDefault(),void this._decorOpenText(e)}"select"!==i&&"erase"!==i||(t.stopPropagation(),t.preventDefault(),"erase"!==i?(this._decorSel=e.id,this._decorMove={id:e.id,start:this._svgPoint(t),orig:JSON.parse(JSON.stringify(e)),pid:t.pointerId,moved:!1,before:this._geometrySnapshot()},bm(t)):this._decorEraseConfirm={id:e.id,kind:e.kind})}_decorMoveUpdate(t){const e=this._decorMove;if("furniture"===e.orig?.kind)return void this._furnMoveUpdate(t);const i=this._svgPoint(t),s=e.orig,n=("line"===s.kind?s.x1:s.x)*pm,o=("line"===s.kind?s.y1:s.y)*this._decorH,r=this._decorSnap([n+(i[0]-e.start[0]),o+(i[1]-e.start[1])],t.pointerType,e.id);let a=(r[0]-n)/pm,l=(r[1]-o)/this._decorH;const c=e.orig,h="line"===c.kind?Math.min(c.x1,c.x2):c.x,d="line"===c.kind?Math.min(c.y1,c.y2):c.y,p="line"===c.kind?Math.abs(c.x2-c.x1):c.w||0,u="line"===c.kind?Math.abs(c.y2-c.y1):c.h||0,_=yc;a=Math.max(-_-h,Math.min(_-h-p,a)),l=Math.max(-_-d,Math.min(_-d-u,l)),(a||l)&&(e.moved=!0);this._curSpaceCfg.decor=this._decorList.map(t=>{if(t.id!==e.id)return t;const i=e.orig;return"line"===t.kind?{...t,x1:i.x1+a,y1:i.y1+l,x2:i.x2+a,y2:i.y2+l}:{...t,x:i.x+a,y:i.y+l}}),this.requestUpdate()}_decorShapeDbl(t,e){"decor"===this._mode&&"select"===this._decorTool&&(t.preventDefault(),t.stopPropagation(),this._decorMove=null,this._decorSel=e.id,this._openDecorProperties(e))}_openDecorProperties(t){if("decor"!==this._mode||"select"!==this._decorTool)return;if("text"===t.kind)return void this._decorOpenText(t);if(!["line","rect","ellipse","furniture"].includes(t.kind))return;const e=this._decorResolvedStyle(t),i="line"===t.kind?t:null,s=this._decorBoxOf(t);this._decorShapeDialog={id:t.id,kind:t.kind,color:e.color,opacity:e.opacity,widthCm:e.widthCm,angle:this._angleField(aa(i?Os([i.x1*pm,i.y1*this._decorH],[i.x2*pm,i.y2*this._decorH]):t.angle)),...i?{lengthCm:ha(Math.hypot((i.x2-i.x1)*pm,(i.y2-i.y1)*this._decorH),this._cellCm,this._gridPitch),lineStyle:"dashed"===i.line_style?"dashed":"solid"}:{},...s?{sizeWCm:ha(s.w,this._cellCm,this._gridPitch),sizeHCm:ha(s.h,this._cellCm,this._gridPitch)}:{},..."furniture"===t.kind?{symbol:t.symbol}:{},..."rect"===t.kind||"ellipse"===t.kind?{fill:e.fill,fillColor:e.fillColor,fillOpacity:e.fillOpacity}:{}}}_decorOpenText(t){if("text"!==t.kind)return;let e=String(t.text??"");const i=[...e.matchAll(/\{([^{}\r\n]+)\}/g)].some(t=>!!Yi(t[1])),s=String(t.unit??"").trim(),n="state"===String(t.attr??"").trim().toLowerCase()?null:t.attr,o=i||s?"":Xi(t.entity,n),r=!(!String(t.entity??"").trim()||i||o&&!s);if(o&&!r){const t=e.indexOf("{}");e=t>=0?e.slice(0,t)+o+e.slice(t+2):`${e}${e?" ":""}${o}`}this._decorTextDialog={id:t.id,x:t.x,y:t.y,text:e,color:Rt(t.color,this._decorStyle.color),opacity:ra(t.opacity,this._decorStyle.opacity),angle:this._angleField(t.angle),sizeCm:this._decorTextSizeCm(t),pickerEntity:t.entity||"",preserveLegacy:r||void 0},this._decorTextSelection={start:e.length,end:e.length}}_decorRememberTextSelection(t){this._decorTextSelection={start:t.selectionStart??t.value.length,end:t.selectionEnd??t.value.length}}_decorInsertLiveVariable(t){const e=this._decorTextDialog;if(!e)return;const i=Xi(e.pickerEntity,t);if(!i)return;const s=e.text,n=Math.max(0,Math.min(s.length,this._decorTextSelection.start)),o=Math.max(n,Math.min(s.length,this._decorTextSelection.end));if(s.length-(o-n)+i.length>200)return;const r=s.slice(0,n)+i+s.slice(o),a=n+i.length;this._decorTextSelection={start:a,end:a},this._decorTextDialog={...e,text:r,preserveLegacy:void 0},this.updateComplete.then(()=>{const t=this.renderRoot.querySelector("textarea.dtarea");t&&(t.focus(),t.setSelectionRange(a,a))})}_decorSaveText(){const t=this._decorTextDialog,e=String(t?.text??"").replace(/\r\n?/g,"\n").trim();if(!t||!e)return void(this._decorTextDialog=null);const i=this._geometrySnapshot(),s=this._curSpaceCfg,n={color:t.color,opacity:ra(t.opacity),size_cm:Number(Math.max(.1,Math.min(Yg,t.sizeCm)).toFixed(4)),...aa(t.angle)?{angle:aa(t.angle)}:{}};if(t.id)s.decor=this._decorList.map(i=>{if(i.id!==t.id)return i;if("text"!==i.kind)return i;if(t.preserveLegacy){const{angle:t,size:s,scale:o,...r}=i;return{...r,text:e,...n}}const{entity:s,attr:o,unit:r,...a}=i,{angle:l,size:c,scale:h,...d}=a;return{...d,text:e,...n}});else{const i="dc"+Date.now().toString(36)+Math.random().toString(36).slice(2,5);s.decor=[...this._decorList,{id:i,kind:"text",x:t.x,y:t.y,text:e,...n}],this._decorSel=i}this._decorTextDialog=null,this._recordGeometry(this._t(t.id?"history.decor_edit":"history.decor_add"),i),this._saveConfig(),this.requestUpdate()}_decorSaveShape(){const t=this._decorShapeDialog;if(!t)return;const e=this._geometrySnapshot(),i={color:t.color,opacity:ra(t.opacity),widthCm:Math.max(.1,Math.min(100,Number(t.widthCm)||.1)),fill:!!t.fill,fillColor:t.fillColor||t.color,fillOpacity:ra(t.fillOpacity,.25)};this._curSpaceCfg.decor=this._decorList.map(e=>{if(e.id!==t.id)return e;const s="rect"===t.kind||"ellipse"===t.kind,n=pa(i,s);if("line"===e.kind){const i=(e.x1+e.x2)/2*pm,s=(e.y1+e.y2)/2*this._decorH,o=ca(Math.max(.1,Number(t.lengthCm)||.1),this._cellCm,this._gridPitch),r=aa(t.angle)*Math.PI/180,a=Math.cos(r)*o/2,l=Math.sin(r)*o/2,c=this._snap([i-a,s-l]),h=this._snap([i+a,s+l]),{width:d,line_style:p,...u}=e;return{...u,...n,x1:Cc(c[0]/pm),y1:Cc(c[1]/this._decorH),x2:Cc(h[0]/pm),y2:Cc(h[1]/this._decorH),..."dashed"===t.lineStyle?{line_style:"dashed"}:{}}}if("rect"===e.kind||"ellipse"===e.kind||"furniture"===e.kind){const i=e.w*pm,s=e.h*this._decorH,o=Math.max(this._gridPitch,ai(ca(Number(t.sizeWCm),this._cellCm,this._gridPitch),this._gridPitch)),r=Math.max(this._gridPitch,ai(ca(Number(t.sizeHCm),this._cellCm,this._gridPitch),this._gridPitch)),a=e.x*pm+i/2,l=e.y*this._decorH+s/2,c=aa(t.angle),h=la({x:a-o/2,y:l-r/2},c,t=>this._snap(t)),{width:d,angle:p,...u}=e;return{...u,...n,x:Cc(h[0]/pm),y:Cc(h[1]/this._decorH),w:o/pm,h:r/this._decorH,..."furniture"===e.kind&&t.symbol?{symbol:t.symbol}:{},...c?{angle:c}:{}}}return e}),this._decorStyle={...i,fill:"rect"===t.kind||"ellipse"===t.kind?i.fill:this._decorStyle.fill,fillColor:"rect"===t.kind||"ellipse"===t.kind?i.fillColor:this._decorStyle.fillColor,fillOpacity:"rect"===t.kind||"ellipse"===t.kind?i.fillOpacity:this._decorStyle.fillOpacity},this._decorShapeDialog=null,this._recordGeometry(this._t("history.decor_edit"),e),this._saveConfig(),this.requestUpdate()}get _dtSel(){return"decor"===this._mode&&"select"===this._decorTool&&this._decorSel&&this._decorList.find(t=>t.id===this._decorSel)||null}_dtPivot(t){return"line"===t.kind?[(t.x1+t.x2)/2*pm,(t.y1+t.y2)/2*this._decorH]:"furniture"===t.kind||"rect"===t.kind||"ellipse"===t.kind?[(t.x+t.w/2)*pm,(t.y+t.h/2)*this._decorH]:[t.x*pm,t.y*this._decorH]}_dtApply(t,e){const i=this._curSpaceCfg;i&&(i.decor=this._decorList.map(i=>{if(i.id!==t)return i;const s={...i};"text"===i.kind&&void 0!==e.textSizeCm&&(delete s.size,delete s.scale);const n={...s};return void 0!==e.textSizeCm&&(n.size_cm=Number(Math.max(.1,Math.min(Yg,e.textSizeCm)).toFixed(4))),void 0!==e.angle&&(e.angle?n.angle=Number(e.angle.toFixed(2)):delete n.angle),n}),this._cfgEpoch++,this.requestUpdate())}_dtStart(t,e,i,s){const n=this._dtSel;if(!n)return;t.stopPropagation(),t.preventDefault();const[o,r]=this._dtPivot(n),a=this._svgPoint(t),l=this._decorBoxOf(n);this._dtDrag={id:n.id,kind:e,pid:t.pointerId,ax:o,ay:r,r0:Math.hypot(a[0]-o,a[1]-r),a0:180*Math.atan2(a[1]-r,a[0]-o)/Math.PI,textSizeCm0:"text"===n.kind?this._decorTextSizeCm(n):1,angle0:"line"===n.kind?0:Number(n.angle)||0,sgx:i?.[0],sgy:i?.[1],orig:l||void 0,origShape:JSON.parse(JSON.stringify(n)),before:this._geometrySnapshot(),lineEnd:s,moved:!1},bm(t)}_dtMove(t){const e=this._dtDrag;if(!e)return;const i=this._svgPoint(t);if(void 0!==e.lineEnd&&"line"===e.origShape.kind){const s=this._decorSnap(i,t.pointerType,e.id),n=Cc(s[0]/pm),o=Cc(s[1]/this._decorH),r=e.origShape,a=0===e.lineEnd?r.x1:r.x2,l=0===e.lineEnd?r.y1:r.y2;return(Math.abs(n-a)>1e-9||Math.abs(o-l)>1e-9)&&(e.moved=!0),void this._replaceDecor(e.id,0===e.lineEnd?{x1:n,y1:o}:{x2:n,y2:o})}if("scale"===e.kind&&e.orig){const s=ga(e.orig,e.sgx??1,e.sgy??1,i[0],i[1],!t.shiftKey,this._gridPitch,this._gridPitch),n=Math.abs(s.x-e.orig.x)>1e-6||Math.abs(s.y-e.orig.y)>1e-6||Math.abs(s.w-e.orig.w)>1e-6||Math.abs(s.h-e.orig.h)>1e-6;if(!n&&!e.moved)return;return e.moved||=n,void this._decorApplyBox(e.id,s)}if("scale"===e.kind){const t=Math.hypot(i[0]-e.ax,i[1]-e.ay);if(e.r0<1e-6)return;const s=Math.max(.1,Math.min(Yg,e.textSizeCm0*(t/e.r0))),n=Math.abs(s-e.textSizeCm0)>1e-6;if(!n&&!e.moved)return;return e.moved||=n,void this._dtApply(e.id,{textSizeCm:s})}const s=180*Math.atan2(i[1]-e.ay,i[0]-e.ax)/Math.PI;let n=e.angle0+(s-e.a0);t.shiftKey||(n=5*Math.round(n/5)),n=(n%360+360)%360,n>180&&(n-=360);const o=Math.abs(n-e.angle0)>1e-6;(o||e.moved)&&(e.moved||=o,this._dtApply(e.id,{angle:n}))}_dtUp(){const t=this._dtDrag;this._dtDrag=null,t?.moved&&(this._recordGeometry(this._t("history.decor_transform"),t.before),this._saveConfig()),this.requestUpdate()}_dtMeasure(){const t=this._dtSel;if(!t)return void(this._dtBox&&(this._dtBox=null,this.requestUpdate()));let e;if("line"===t.kind){const i=t.x1*pm,s=t.y1*this._decorH,n=t.x2*pm,o=t.y2*this._decorH;e={id:t.id,x:Math.min(i,n),y:Math.min(s,o),w:Math.abs(n-i),h:Math.abs(o-s)}}else if("furniture"===t.kind||"rect"===t.kind||"ellipse"===t.kind)e={id:t.id,x:t.x*pm,y:t.y*this._decorH,w:t.w*pm,h:t.h*this._decorH};else{const i=this.renderRoot.querySelector(`text.dtext[data-id="${t.id}"]`);if(!i||"function"!=typeof i.getBBox)return;let s;try{s=i.getBBox()}catch{return}if(!s||!s.width&&!s.height)return;e={id:t.id,x:s.x,y:s.y,w:s.width,h:s.height}}const i=this._dtBox;i&&i.id===e.id&&Math.abs(i.x-e.x)<.01&&Math.abs(i.y-e.y)<.01&&Math.abs(i.w-e.w)<.01&&Math.abs(i.h-e.h)<.01||(this._dtBox=e,this.requestUpdate())}_deleteDecor(t){if(!this._decorList.some(e=>e.id===t))return;const e=this._geometrySnapshot();this._curSpaceCfg.decor=this._decorList.filter(e=>e.id!==t),this._decorSel===t&&(this._decorSel=null),this._recordGeometry(this._t("history.decor_delete"),e),this._saveConfig(),this.requestUpdate()}_decorDeleteSel(){this._decorSel&&this._deleteDecor(this._decorSel)}_confirmDecorErase(){const t=this._decorEraseConfirm;this._decorEraseConfirm=null,t&&this._deleteDecor(t.id)}get _furnWalls(){const t=this._rawPhysicalBodiesR().flatMap(t=>t.map((e,i)=>{const s=t[(i+1)%t.length];return[e[0],e[1],s[0],s[1]]}));return[...this._segments,...t]}get _furnWallReach(){return 6*this._gridPitch}_furnFieldValue(t){return Math.round(100*(this._imperial?t/30.48:t/100))/100}_furnFieldToCm(t){return e=this._imperial?30.48*t:100*t,Number.isFinite(e)?Math.max(1,Math.min(1e4,e)):1;var e}_furnPick(t){const e=function(t){const e=Vc(t);return e?{w:e.w,h:e.h}:{w:60,h:60}}(t);this._furnPalette={symbol:t,w:e.w,h:e.h}}_furnPlace(t,e=!1){const i=this._furnPalette,s=this._curSpaceCfg;if(!i||!s)return;const n=pm,o=this._decorH,r=Zc(Yc(i.w,this._cellCm,this._gridPitch,n)),a=Zc(Yc(i.h,this._cellCm,this._gridPitch,n)),l=this._geometrySnapshot(),c=this._decorSnap(t);let h=c[0],d=c[1],p=0;const u=e?null:ih(h,d,a*o,this._furnWalls,this._furnWallReach,this._gridPitch);u&&(h=u.cx,d=u.cy,p=u.angle);const _="df"+Date.now().toString(36)+Math.random().toString(36).slice(2,5),g={id:_,kind:"furniture",symbol:i.symbol,x:Cc(h/n-r/2),y:Cc(d/o-a/2),w:r,h:a,...pa(this._decorStyle,!1)};p&&(g.angle=Number(p.toFixed(2))),s.decor=[...this._decorList,g],this._decorSel=_,this._decorTool="select",this._furnPalette=null,this._recordGeometry(this._t("history.decor_add"),l),this._saveConfig(),this.requestUpdate()}_furnMoveUpdate(t){const e=this._decorMove;if("furniture"!==e.orig.kind)return;const i=e.orig,s=this._curSpaceCfg;if(!s)return;const n=pm,o=this._decorH,r=this._svgPoint(t),a=(i.x+i.w/2)*n+(r[0]-e.start[0]),l=(i.y+i.h/2)*o+(r[1]-e.start[1]);let c,h,d=Number(i.angle)||0;const p=t.shiftKey?null:ih(a,l,i.h*o,this._furnWalls,this._furnWallReach,this._gridPitch);if(p)c=p.cx/n-i.w/2,h=p.cy/o-i.h/2,d=p.angle;else{const s=this._decorSnap([a-i.w/2*n,l-i.h/2*o],t.pointerType,e.id);c=s[0]/n,h=s[1]/o}c=Cc(c),h=Cc(h),(Math.abs(c-i.x)>1e-9||Math.abs(h-i.y)>1e-9||Math.abs(d-(Number(i.angle)||0))>1e-9)&&(e.moved=!0),s.decor=this._decorList.map(t=>{if(t.id!==e.id)return t;const i={...t,x:c,y:h};return d?i.angle=Number(d.toFixed(2)):delete i.angle,i}),this.requestUpdate()}_decorApplyBox(t,e){const i=this._curSpaceCfg;if(!i)return;const s=pm,n=this._decorH;i.decor=this._decorList.map(i=>{if(i.id!==t)return i;const o=la(e,i.angle,t=>this._snap(t));return{...i,x:Cc(o[0]/s),y:Cc(o[1]/n),w:Math.max(this._gridPitch/s,Math.min(2*yc,e.w/s)),h:Math.max(this._gridPitch/n,Math.min(2*yc,e.h/n))}}),this._cfgEpoch++,this.requestUpdate()}get _furnLive(){const t=this._dtDrag;if(!t||"scale"!==t.kind||!t.orig)return null;const e=this._decorList.find(e=>e.id===t.id);if(!e||"furniture"!==e.kind)return null;const i=pm,s=this._decorH,n=e.w*i,o=e.h*s,r=function(t,e,i,s,n){const o=t+i/2,r=e+s/2,a=(Number(n)||0)*Math.PI/180,l=Math.cos(a),c=Math.sin(a),h=(t,e)=>{const i=t-o,s=e-r;return[o+i*l-s*c,r+i*c+s*l]};return[h(t,e),h(t+i,e),h(t+i,e+s),h(t,e+s)]}(e.x*i,e.y*s,n,o,Number(e.angle)||0),a=(t,e)=>[(t[0]+e[0])/2,(t[1]+e[1])/2],l=a(r[0],r[1]),c=a(r[0],r[3]);return[{x:l[0],y:l[1],text:this._fmtLen([0,0],[n,0])},{x:c[0],y:c[1],text:this._fmtLen([0,0],[0,o])}]}_renderFurnPalette(){const t=this._furnPalette,e=this._t(this._imperial?"gs.unit_ft":"gs.unit_m");return W`
t.stopPropagation()}> + @lostpointercapture=${t=>this._rszPointerCancel(t)}>`),o.push(j``)}return j`${o}`}get _openingsR(){const t=this._curSpaceCfg,e=this._spaceH,i=this._spaceModel();return i?(t?.openings||[]).flatMap(t=>{const s={...t,rx:t.x*um,ry:t.y*e,rlen:t.length*um};if(!t.host)return[s];const n=Rd(t,i.partitions,um,this._cellCm,this._gridPitch);if(!n.resolved)return"plan"===this._mode?[{...s,orphanReason:n.reason||"invalid-host"}]:[];let[o,a]=n.resolved.center;const r=this._physicalDrag;return r?.moved&&"partition"===r.kind&&r.id===t.host.id&&(o+=r.delta[0],a+=r.delta[1]),[{...t,rx:o,ry:a,rlen:n.resolved.length,angle:n.resolved.angle,partitionHost:n.resolved}]}):[]}_partitionOpeningCuts(t=this._spaceModel(),e=()=>!0){if(!t)return[];return $_(x_(this._curSpaceCfg?.id===t.id?this._curSpaceCfg:null,t,this._cellCm,this._gridPitch,um),e)}_roomWallOpeningInputs(t=this._openingsR,e=this._spaceModel()){if(!e)return[];const i=this._openPairs().flatMap(t=>t.segs);return S_(t,e,this._spaceWalls,i,this._wallKeyPitch,this._cellCm,this._gridPitch,um)}_openingFace(t,e,i){return t.partitionHost?Ed(t.partitionHost,i):zl(e,{x:t.rx,y:t.ry,angle:t.angle,length:t.rlen,flip_v:i})}_cmToUnits(t){return t/this._cellCm*this._gridPitch}get _decorList(){const t=this._curSpaceCfg;return Array.isArray(t?.decor)?t.decor:[]}get _decorH(){return um}_decorResolvedStyle(t){return function(t,e,i,s=or){const n="rect"===t?.kind||"ellipse"===t?.kind,o=t,a=Rt(o?.color,s.color);return{color:a,opacity:ar(o?.opacity,s.opacity),widthCm:dr(t,e,i,s.widthCm),fill:!!n&&!0===o?.fill,fillColor:Rt(o?.fill_color,o?.fill?a:s.fillColor),fillOpacity:n&&o?.fill?ar(o?.fill_opacity,.25):s.fillOpacity}}(t,this._cellCm,this._gridPitch,or)}_decorWidthUnits(t){return((t,e,i,s=or.widthCm)=>{const n=Number(t?.width_cm);if(Number.isFinite(n)&&n>0)return cr(n,e,i);const o=Number(t?.width);return Number.isFinite(o)&&o>0?o:cr(s,e,i)})(t,this._cellCm,this._gridPitch,or.widthCm)}_decorTextSizeCm(t){if("text"===t?.kind){const e=Number(t.size_cm);return Number.isFinite(e)&&e>0?e:hr(es*is(t),this._cellCm,this._gridPitch)}return hr(es,this._cellCm,this._gridPitch)}_decorTextUnits(t){if("text"!==t.kind)return es;const e=Number(t.size_cm);return Number.isFinite(e)&&e>0?cr(e,this._cellCm,this._gridPitch):es*is(t)}_decorSmallField(t){return Math.round(100*(this._imperial?t/2.54:t))/100}_decorSmallCm(t){const e=this._imperial?2.54*t:t;return Number.isFinite(e)?Math.max(.1,Math.min(100,e)):.1}_decorTextCm(t){const e=this._imperial?2.54*t:t;return Number.isFinite(e)?Math.max(.1,Math.min(Xg,e)):.1}_decorLargeField(t){return Math.round(100*(this._imperial?t/30.48:t/100))/100}_decorLargeCm(t){const e=this._imperial?30.48*t:100*t;return Number.isFinite(e)?Math.max(.1,Math.min(bc*this._cellCm,e)):.1}_angleField(t){const e=Number(t);return Number.isFinite(e)?String(Number(e.toFixed(3))):"0"}_decorBoxOf(t){return"rect"!==t.kind&&"ellipse"!==t.kind&&"furniture"!==t.kind?null:{x:t.x*um,y:t.y*this._decorH,w:t.w*um,h:t.h*this._decorH,angle:rr(t.angle)||void 0}}_decorSnapGeometry(t){const e=this._spaceModel();if(!e)return{points:[],segments:[]};const i=t||"",s=this._decorSnapCache;if(s&&s.epoch===this._cfgEpoch&&s.space===this._space&&s.height===this._decorH&&s.exclude===i)return s.geometry;const n=[];for(const e of this._decorList)if(e.id!==t)if("line"===e.kind){const t=[e.x1*um,e.y1*this._decorH],i=[e.x2*um,e.y2*this._decorH];n.push({points:[t,i,[(t[0]+i[0])/2,(t[1]+i[1])/2]],segments:[{a:t,b:i}]})}else if("text"===e.kind)n.push({points:[[e.x*um,e.y*this._decorH]],segments:[]});else{const t=this._decorBoxOf(e);t&&n.push(_r(t))}for(const t of e.rooms){const e=hi(t);e?.length&&n.push({points:e.flatMap((t,i)=>{const s=e[(i+1)%e.length];return[t,[(t[0]+s[0])/2,(t[1]+s[1])/2]]}),segments:e.map((t,i)=>({a:t,b:e[(i+1)%e.length]}))})}const o=function(t){return{points:t.flatMap(t=>t.points),segments:t.flatMap(t=>t.segments)}}(n);return this._decorSnapCache={epoch:this._cfgEpoch,space:this._space,height:this._decorH,exclude:i,geometry:o},o}_decorSnap(t,e="mouse",i){const s=this._stageEl,n=this._viewOr(this._baseVb()),o="touch"===e||"pen"===e?14:8,a=s?n.w/Math.max(1,s.clientWidth)*o:this._gridPitch;return function(t,e,i,s){const n=s(t);let o=null;for(const n of e.points){const e=s(n),a=Math.hypot(e[0]-t[0],e[1]-t[1]);a<=i&&(!o||athis._snap(t)).point}_replaceDecor(t,e){const i=this._curSpaceCfg;i&&(i.decor=this._decorList.map(i=>i.id===t?{...i,...e}:i),this.requestUpdate())}_cancelDecorGesture(){const t=this._decorMove?.before||this._dtDrag?.before||this._bdDrag?.before,e=t&&this._serverCfg?.spaces.find(e=>e.id===t.spaceId);if(t&&e){const i=t=>JSON.parse(JSON.stringify(t));void 0!==t.decor?e.decor=i(t.decor):delete e.decor;for(const t of["plan_x","plan_y","plan_scale","plan_scale_x","plan_scale_y","plan_angle"])delete e[t];Object.assign(e,i(t.plan_transform||{})),this._cfgEpoch++}this._decorMove=null,this._dtDrag=null,this._bdDrag=null,this.requestUpdate()}_decorPointerDown(t){const e=this._decorTool;if("select"===e||"erase"===e?t.target.closest?.(".dshape"):null)return!0;if("line"===e||"rect"===e||"ellipse"===e){t.preventDefault();const i=this._decorSnap(this._svgPoint(t),t.pointerType);return this._decorDraft={kind:e,a:i,b:i,pid:t.pointerId},wm(t),!0}if("text"===e){const e=this._decorSnap(this._svgPoint(t),t.pointerType);return this._decorTextDialog={x:Dc(e[0]/um),y:Dc(e[1]/this._decorH),text:"",color:this._decorStyle.color,opacity:this._decorStyle.opacity,angle:"0",sizeCm:hr(es,this._cellCm,this._gridPitch)},this._decorTextSelection={start:0,end:0},!0}if("furniture"===e)return!!this._furnPalette&&(t.preventDefault(),this._furnPlace(this._svgPoint(t),t.shiftKey),!0);if("select"===e&&(this._decorSel=null),this._bdMovable){const e=this._bdRect,i=this._svgPoint(t),s=e.x+e.w/2,n=e.y+e.h/2,o=-rr(e.angle)*Math.PI/180,a=i[0]-s,r=i[1]-n,l=[s+a*Math.cos(o)-r*Math.sin(o),n+a*Math.sin(o)+r*Math.cos(o)];if(l[0]>=e.x&&l[0]<=e.x+e.w&&l[1]>=e.y&&l[1]<=e.y+e.h)return t.preventDefault(),this._bdStart(t)}return!1}_decorCommitDraft(){const t=this._decorDraft;if(this._decorDraft=null,!t)return;const e=.5*this._gridPitch;if(!function(t,e,i,s){const n=Math.abs(i[0]-e[0]),o=Math.abs(i[1]-e[1]);return"line"===t?Math.hypot(n,o)>=s:n>=s&&o>=s}(t.kind,t.a,t.b,e))return;const i=um,s=this._decorH,n=this._decorStyle,o=this._geometrySnapshot(),a="dc"+Date.now().toString(36)+Math.random().toString(36).slice(2,5),r=Dc;let l;if("line"===t.kind)l={id:a,kind:"line",x1:r(t.a[0]/i),y1:r(t.a[1]/s),x2:r(t.b[0]/i),y2:r(t.b[1]/s),...pr(n,!1)};else{const e=r(Math.min(t.a[0],t.b[0])/i),o=r(Math.min(t.a[1],t.b[1])/s),c=Math.abs(t.b[0]-t.a[0])/i,h=Math.abs(t.b[1]-t.a[1])/s;l={id:a,kind:t.kind,x:e,y:o,w:c,h:h,...pr(n,!0)}}this._curSpaceCfg.decor=[...this._decorList,l],this._decorSel=a,this._recordGeometry(this._t("history.decor_add"),o),this._saveConfig(),this.requestUpdate()}_decorShapeDown(t,e){if("decor"!==this._mode)return;const i=this._decorTool;if("text"===i){if("text"!==e.kind)return;return t.stopPropagation(),t.preventDefault(),void this._decorOpenText(e)}"select"!==i&&"erase"!==i||(t.stopPropagation(),t.preventDefault(),"erase"!==i?(this._decorSel=e.id,this._decorMove={id:e.id,start:this._svgPoint(t),orig:JSON.parse(JSON.stringify(e)),pid:t.pointerId,moved:!1,before:this._geometrySnapshot()},wm(t)):this._decorEraseConfirm={id:e.id,kind:e.kind})}_decorMoveUpdate(t){const e=this._decorMove;if("furniture"===e.orig?.kind)return void this._furnMoveUpdate(t);const i=this._svgPoint(t),s=e.orig,n=("line"===s.kind?s.x1:s.x)*um,o=("line"===s.kind?s.y1:s.y)*this._decorH,a=this._decorSnap([n+(i[0]-e.start[0]),o+(i[1]-e.start[1])],t.pointerType,e.id);let r=(a[0]-n)/um,l=(a[1]-o)/this._decorH;const c=e.orig,h="line"===c.kind?Math.min(c.x1,c.x2):c.x,d="line"===c.kind?Math.min(c.y1,c.y2):c.y,p="line"===c.kind?Math.abs(c.x2-c.x1):c.w||0,u="line"===c.kind?Math.abs(c.y2-c.y1):c.h||0,_=bc;r=Math.max(-_-h,Math.min(_-h-p,r)),l=Math.max(-_-d,Math.min(_-d-u,l)),(r||l)&&(e.moved=!0);this._curSpaceCfg.decor=this._decorList.map(t=>{if(t.id!==e.id)return t;const i=e.orig;return"line"===t.kind?{...t,x1:i.x1+r,y1:i.y1+l,x2:i.x2+r,y2:i.y2+l}:{...t,x:i.x+r,y:i.y+l}}),this.requestUpdate()}_decorShapeDbl(t,e){"decor"===this._mode&&"select"===this._decorTool&&(t.preventDefault(),t.stopPropagation(),this._decorMove=null,this._decorSel=e.id,this._openDecorProperties(e))}_openDecorProperties(t){if("decor"!==this._mode||"select"!==this._decorTool)return;if("text"===t.kind)return void this._decorOpenText(t);if(!["line","rect","ellipse","furniture"].includes(t.kind))return;const e=this._decorResolvedStyle(t),i="line"===t.kind?t:null,s=this._decorBoxOf(t);this._decorShapeDialog={id:t.id,kind:t.kind,color:e.color,opacity:e.opacity,widthCm:e.widthCm,angle:this._angleField(rr(i?Os([i.x1*um,i.y1*this._decorH],[i.x2*um,i.y2*this._decorH]):t.angle)),...i?{lengthCm:hr(Math.hypot((i.x2-i.x1)*um,(i.y2-i.y1)*this._decorH),this._cellCm,this._gridPitch),lineStyle:"dashed"===i.line_style?"dashed":"solid"}:{},...s?{sizeWCm:hr(s.w,this._cellCm,this._gridPitch),sizeHCm:hr(s.h,this._cellCm,this._gridPitch)}:{},..."furniture"===t.kind?{symbol:t.symbol}:{},..."rect"===t.kind||"ellipse"===t.kind?{fill:e.fill,fillColor:e.fillColor,fillOpacity:e.fillOpacity}:{}}}_decorOpenText(t){if("text"!==t.kind)return;let e=String(t.text??"");const i=[...e.matchAll(/\{([^{}\r\n]+)\}/g)].some(t=>!!Yi(t[1])),s=String(t.unit??"").trim(),n="state"===String(t.attr??"").trim().toLowerCase()?null:t.attr,o=i||s?"":Xi(t.entity,n),a=!(!String(t.entity??"").trim()||i||o&&!s);if(o&&!a){const t=e.indexOf("{}");e=t>=0?e.slice(0,t)+o+e.slice(t+2):`${e}${e?" ":""}${o}`}this._decorTextDialog={id:t.id,x:t.x,y:t.y,text:e,color:Rt(t.color,this._decorStyle.color),opacity:ar(t.opacity,this._decorStyle.opacity),angle:this._angleField(t.angle),sizeCm:this._decorTextSizeCm(t),pickerEntity:t.entity||"",preserveLegacy:a||void 0},this._decorTextSelection={start:e.length,end:e.length}}_decorRememberTextSelection(t){this._decorTextSelection={start:t.selectionStart??t.value.length,end:t.selectionEnd??t.value.length}}_decorInsertLiveVariable(t){const e=this._decorTextDialog;if(!e)return;const i=Xi(e.pickerEntity,t);if(!i)return;const s=e.text,n=Math.max(0,Math.min(s.length,this._decorTextSelection.start)),o=Math.max(n,Math.min(s.length,this._decorTextSelection.end));if(s.length-(o-n)+i.length>200)return;const a=s.slice(0,n)+i+s.slice(o),r=n+i.length;this._decorTextSelection={start:r,end:r},this._decorTextDialog={...e,text:a,preserveLegacy:void 0},this.updateComplete.then(()=>{const t=this.renderRoot.querySelector("textarea.dtarea");t&&(t.focus(),t.setSelectionRange(r,r))})}_decorSaveText(){const t=this._decorTextDialog,e=String(t?.text??"").replace(/\r\n?/g,"\n").trim();if(!t||!e)return void(this._decorTextDialog=null);const i=this._geometrySnapshot(),s=this._curSpaceCfg,n={color:t.color,opacity:ar(t.opacity),size_cm:Number(Math.max(.1,Math.min(Xg,t.sizeCm)).toFixed(4)),...rr(t.angle)?{angle:rr(t.angle)}:{}};if(t.id)s.decor=this._decorList.map(i=>{if(i.id!==t.id)return i;if("text"!==i.kind)return i;if(t.preserveLegacy){const{angle:t,size:s,scale:o,...a}=i;return{...a,text:e,...n}}const{entity:s,attr:o,unit:a,...r}=i,{angle:l,size:c,scale:h,...d}=r;return{...d,text:e,...n}});else{const i="dc"+Date.now().toString(36)+Math.random().toString(36).slice(2,5);s.decor=[...this._decorList,{id:i,kind:"text",x:t.x,y:t.y,text:e,...n}],this._decorSel=i}this._decorTextDialog=null,this._recordGeometry(this._t(t.id?"history.decor_edit":"history.decor_add"),i),this._saveConfig(),this.requestUpdate()}_decorSaveShape(){const t=this._decorShapeDialog;if(!t)return;const e=this._geometrySnapshot(),i={color:t.color,opacity:ar(t.opacity),widthCm:Math.max(.1,Math.min(100,Number(t.widthCm)||.1)),fill:!!t.fill,fillColor:t.fillColor||t.color,fillOpacity:ar(t.fillOpacity,.25)};this._curSpaceCfg.decor=this._decorList.map(e=>{if(e.id!==t.id)return e;const s="rect"===t.kind||"ellipse"===t.kind,n=pr(i,s);if("line"===e.kind){const i=(e.x1+e.x2)/2*um,s=(e.y1+e.y2)/2*this._decorH,o=cr(Math.max(.1,Number(t.lengthCm)||.1),this._cellCm,this._gridPitch),a=rr(t.angle)*Math.PI/180,r=Math.cos(a)*o/2,l=Math.sin(a)*o/2,c=this._snap([i-r,s-l]),h=this._snap([i+r,s+l]),{width:d,line_style:p,...u}=e;return{...u,...n,x1:Dc(c[0]/um),y1:Dc(c[1]/this._decorH),x2:Dc(h[0]/um),y2:Dc(h[1]/this._decorH),..."dashed"===t.lineStyle?{line_style:"dashed"}:{}}}if("rect"===e.kind||"ellipse"===e.kind||"furniture"===e.kind){const i=e.w*um,s=e.h*this._decorH,o=Math.max(this._gridPitch,ri(cr(Number(t.sizeWCm),this._cellCm,this._gridPitch),this._gridPitch)),a=Math.max(this._gridPitch,ri(cr(Number(t.sizeHCm),this._cellCm,this._gridPitch),this._gridPitch)),r=e.x*um+i/2,l=e.y*this._decorH+s/2,c=rr(t.angle),h=lr({x:r-o/2,y:l-a/2},c,t=>this._snap(t)),{width:d,angle:p,...u}=e;return{...u,...n,x:Dc(h[0]/um),y:Dc(h[1]/this._decorH),w:o/um,h:a/this._decorH,..."furniture"===e.kind&&t.symbol?{symbol:t.symbol}:{},...c?{angle:c}:{}}}return e}),this._decorStyle={...i,fill:"rect"===t.kind||"ellipse"===t.kind?i.fill:this._decorStyle.fill,fillColor:"rect"===t.kind||"ellipse"===t.kind?i.fillColor:this._decorStyle.fillColor,fillOpacity:"rect"===t.kind||"ellipse"===t.kind?i.fillOpacity:this._decorStyle.fillOpacity},this._decorShapeDialog=null,this._recordGeometry(this._t("history.decor_edit"),e),this._saveConfig(),this.requestUpdate()}get _dtSel(){return"decor"===this._mode&&"select"===this._decorTool&&this._decorSel&&this._decorList.find(t=>t.id===this._decorSel)||null}_dtPivot(t){return"line"===t.kind?[(t.x1+t.x2)/2*um,(t.y1+t.y2)/2*this._decorH]:"furniture"===t.kind||"rect"===t.kind||"ellipse"===t.kind?[(t.x+t.w/2)*um,(t.y+t.h/2)*this._decorH]:[t.x*um,t.y*this._decorH]}_dtApply(t,e){const i=this._curSpaceCfg;i&&(i.decor=this._decorList.map(i=>{if(i.id!==t)return i;const s={...i};"text"===i.kind&&void 0!==e.textSizeCm&&(delete s.size,delete s.scale);const n={...s};return void 0!==e.textSizeCm&&(n.size_cm=Number(Math.max(.1,Math.min(Xg,e.textSizeCm)).toFixed(4))),void 0!==e.angle&&(e.angle?n.angle=Number(e.angle.toFixed(2)):delete n.angle),n}),this._cfgEpoch++,this.requestUpdate())}_dtStart(t,e,i,s){const n=this._dtSel;if(!n)return;t.stopPropagation(),t.preventDefault();const[o,a]=this._dtPivot(n),r=this._svgPoint(t),l=this._decorBoxOf(n);this._dtDrag={id:n.id,kind:e,pid:t.pointerId,ax:o,ay:a,r0:Math.hypot(r[0]-o,r[1]-a),a0:180*Math.atan2(r[1]-a,r[0]-o)/Math.PI,textSizeCm0:"text"===n.kind?this._decorTextSizeCm(n):1,angle0:"line"===n.kind?0:Number(n.angle)||0,sgx:i?.[0],sgy:i?.[1],orig:l||void 0,origShape:JSON.parse(JSON.stringify(n)),before:this._geometrySnapshot(),lineEnd:s,moved:!1},wm(t)}_dtMove(t){const e=this._dtDrag;if(!e)return;const i=this._svgPoint(t);if(void 0!==e.lineEnd&&"line"===e.origShape.kind){const s=this._decorSnap(i,t.pointerType,e.id),n=Dc(s[0]/um),o=Dc(s[1]/this._decorH),a=e.origShape,r=0===e.lineEnd?a.x1:a.x2,l=0===e.lineEnd?a.y1:a.y2;return(Math.abs(n-r)>1e-9||Math.abs(o-l)>1e-9)&&(e.moved=!0),void this._replaceDecor(e.id,0===e.lineEnd?{x1:n,y1:o}:{x2:n,y2:o})}if("scale"===e.kind&&e.orig){const s=gr(e.orig,e.sgx??1,e.sgy??1,i[0],i[1],!t.shiftKey,this._gridPitch,this._gridPitch),n=Math.abs(s.x-e.orig.x)>1e-6||Math.abs(s.y-e.orig.y)>1e-6||Math.abs(s.w-e.orig.w)>1e-6||Math.abs(s.h-e.orig.h)>1e-6;if(!n&&!e.moved)return;return e.moved||=n,void this._decorApplyBox(e.id,s)}if("scale"===e.kind){const t=Math.hypot(i[0]-e.ax,i[1]-e.ay);if(e.r0<1e-6)return;const s=Math.max(.1,Math.min(Xg,e.textSizeCm0*(t/e.r0))),n=Math.abs(s-e.textSizeCm0)>1e-6;if(!n&&!e.moved)return;return e.moved||=n,void this._dtApply(e.id,{textSizeCm:s})}const s=180*Math.atan2(i[1]-e.ay,i[0]-e.ax)/Math.PI;let n=e.angle0+(s-e.a0);t.shiftKey||(n=5*Math.round(n/5)),n=(n%360+360)%360,n>180&&(n-=360);const o=Math.abs(n-e.angle0)>1e-6;(o||e.moved)&&(e.moved||=o,this._dtApply(e.id,{angle:n}))}_dtUp(){const t=this._dtDrag;this._dtDrag=null,t?.moved&&(this._recordGeometry(this._t("history.decor_transform"),t.before),this._saveConfig()),this.requestUpdate()}_dtMeasure(){const t=this._dtSel;if(!t)return void(this._dtBox&&(this._dtBox=null,this.requestUpdate()));let e;if("line"===t.kind){const i=t.x1*um,s=t.y1*this._decorH,n=t.x2*um,o=t.y2*this._decorH;e={id:t.id,x:Math.min(i,n),y:Math.min(s,o),w:Math.abs(n-i),h:Math.abs(o-s)}}else if("furniture"===t.kind||"rect"===t.kind||"ellipse"===t.kind)e={id:t.id,x:t.x*um,y:t.y*this._decorH,w:t.w*um,h:t.h*this._decorH};else{const i=this.renderRoot.querySelector(`text.dtext[data-id="${t.id}"]`);if(!i||"function"!=typeof i.getBBox)return;let s;try{s=i.getBBox()}catch{return}if(!s||!s.width&&!s.height)return;e={id:t.id,x:s.x,y:s.y,w:s.width,h:s.height}}const i=this._dtBox;i&&i.id===e.id&&Math.abs(i.x-e.x)<.01&&Math.abs(i.y-e.y)<.01&&Math.abs(i.w-e.w)<.01&&Math.abs(i.h-e.h)<.01||(this._dtBox=e,this.requestUpdate())}_deleteDecor(t){if(!this._decorList.some(e=>e.id===t))return;const e=this._geometrySnapshot();this._curSpaceCfg.decor=this._decorList.filter(e=>e.id!==t),this._decorSel===t&&(this._decorSel=null),this._recordGeometry(this._t("history.decor_delete"),e),this._saveConfig(),this.requestUpdate()}_decorDeleteSel(){this._decorSel&&this._deleteDecor(this._decorSel)}_confirmDecorErase(){const t=this._decorEraseConfirm;this._decorEraseConfirm=null,t&&this._deleteDecor(t.id)}get _furnWalls(){const t=this._rawPhysicalBodiesR().flatMap(t=>t.map((e,i)=>{const s=t[(i+1)%t.length];return[e[0],e[1],s[0],s[1]]}));return[...this._segments,...t]}get _furnWallReach(){return 6*this._gridPitch}_furnFieldValue(t){return Math.round(100*(this._imperial?t/30.48:t/100))/100}_furnFieldToCm(t){return e=this._imperial?30.48*t:100*t,Number.isFinite(e)?Math.max(1,Math.min(1e4,e)):1;var e}_furnPick(t){const e=function(t){const e=Kc(t);return e?{w:e.w,h:e.h}:{w:60,h:60}}(t);this._furnPalette={symbol:t,w:e.w,h:e.h}}_furnPlace(t,e=!1){const i=this._furnPalette,s=this._curSpaceCfg;if(!i||!s)return;const n=um,o=this._decorH,a=Qc(Xc(i.w,this._cellCm,this._gridPitch,n)),r=Qc(Xc(i.h,this._cellCm,this._gridPitch,n)),l=this._geometrySnapshot(),c=this._decorSnap(t);let h=c[0],d=c[1],p=0;const u=e?null:sh(h,d,r*o,this._furnWalls,this._furnWallReach,this._gridPitch);u&&(h=u.cx,d=u.cy,p=u.angle);const _="df"+Date.now().toString(36)+Math.random().toString(36).slice(2,5),g={id:_,kind:"furniture",symbol:i.symbol,x:Dc(h/n-a/2),y:Dc(d/o-r/2),w:a,h:r,...pr(this._decorStyle,!1)};p&&(g.angle=Number(p.toFixed(2))),s.decor=[...this._decorList,g],this._decorSel=_,this._decorTool="select",this._furnPalette=null,this._recordGeometry(this._t("history.decor_add"),l),this._saveConfig(),this.requestUpdate()}_furnMoveUpdate(t){const e=this._decorMove;if("furniture"!==e.orig.kind)return;const i=e.orig,s=this._curSpaceCfg;if(!s)return;const n=um,o=this._decorH,a=this._svgPoint(t),r=(i.x+i.w/2)*n+(a[0]-e.start[0]),l=(i.y+i.h/2)*o+(a[1]-e.start[1]);let c,h,d=Number(i.angle)||0;const p=t.shiftKey?null:sh(r,l,i.h*o,this._furnWalls,this._furnWallReach,this._gridPitch);if(p)c=p.cx/n-i.w/2,h=p.cy/o-i.h/2,d=p.angle;else{const s=this._decorSnap([r-i.w/2*n,l-i.h/2*o],t.pointerType,e.id);c=s[0]/n,h=s[1]/o}c=Dc(c),h=Dc(h),(Math.abs(c-i.x)>1e-9||Math.abs(h-i.y)>1e-9||Math.abs(d-(Number(i.angle)||0))>1e-9)&&(e.moved=!0),s.decor=this._decorList.map(t=>{if(t.id!==e.id)return t;const i={...t,x:c,y:h};return d?i.angle=Number(d.toFixed(2)):delete i.angle,i}),this.requestUpdate()}_decorApplyBox(t,e){const i=this._curSpaceCfg;if(!i)return;const s=um,n=this._decorH;i.decor=this._decorList.map(i=>{if(i.id!==t)return i;const o=lr(e,i.angle,t=>this._snap(t));return{...i,x:Dc(o[0]/s),y:Dc(o[1]/n),w:Math.max(this._gridPitch/s,Math.min(2*bc,e.w/s)),h:Math.max(this._gridPitch/n,Math.min(2*bc,e.h/n))}}),this._cfgEpoch++,this.requestUpdate()}get _furnLive(){const t=this._dtDrag;if(!t||"scale"!==t.kind||!t.orig)return null;const e=this._decorList.find(e=>e.id===t.id);if(!e||"furniture"!==e.kind)return null;const i=um,s=this._decorH,n=e.w*i,o=e.h*s,a=function(t,e,i,s,n){const o=t+i/2,a=e+s/2,r=(Number(n)||0)*Math.PI/180,l=Math.cos(r),c=Math.sin(r),h=(t,e)=>{const i=t-o,s=e-a;return[o+i*l-s*c,a+i*c+s*l]};return[h(t,e),h(t+i,e),h(t+i,e+s),h(t,e+s)]}(e.x*i,e.y*s,n,o,Number(e.angle)||0),r=(t,e)=>[(t[0]+e[0])/2,(t[1]+e[1])/2],l=r(a[0],a[1]),c=r(a[0],a[3]);return[{x:l[0],y:l[1],text:this._fmtLen([0,0],[n,0])},{x:c[0],y:c[1],text:this._fmtLen([0,0],[0,o])}]}_renderFurnPalette(){const t=this._furnPalette,e=this._t(this._imperial?"gs.unit_ft":"gs.unit_m");return W`
t.stopPropagation()}>
${this._t("furn.title")} @@ -4936,16 +4936,16 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8
- ${jc.map(e=>W` + ${Uc.map(e=>W`
${this._t(`furn.group_${e}`)}
- ${Kc(e).map(e=>W``)}
`)} @@ -4961,22 +4961,22 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8 @input=${e=>this._furnPalette={...t,h:this._furnFieldToCm(Number(e.target.value))}} /> ${this._t("furn.place_hint")}
`:W`
${this._t("furn.pick_hint")}
`} -
`}get _bdBase(){const t=this._curSpaceCfg;return t?.plan_url?{...uc(t.plan_aspect,pm)}:null}get _bdRect(){const t=this._curSpaceCfg;return t?.plan_url?mc(t,pm):null}get _bdParams(){const t=this._curSpaceCfg,e=Number(t?.plan_x),i=Number(t?.plan_y),s=Number(t?.plan_scale),n=Number(t?.plan_scale_x),o=Number(t?.plan_scale_y),r=Number.isFinite(s)&&s>0?s:1;return{dx:Number.isFinite(e)?e:0,dy:Number.isFinite(i)?i:0,sx:Number.isFinite(n)&&n>0?n:r,sy:Number.isFinite(o)&&o>0?o:r,angle:aa(t?.plan_angle)}}_openBackdropDialog(t){if(!this._bdMovable||!this._bdRect)return;t?.preventDefault(),t?.stopPropagation(),this._bdDrag=null;const e=this._bdRect;this._backdropDialog={widthCm:ha(e.w,this._cellCm,this._gridPitch),heightCm:ha(e.h,this._cellCm,this._gridPitch),angle:this._angleField(e.angle)}}_saveBackdropDialog(){const t=this._backdropDialog,e=this._bdBase,i=this._bdRect;if(!t||!e||!i)return;const s=aa(t.angle),n=this._geometrySnapshot(),o=Math.min(e.w*gc,Math.max(e.w*_c,ai(ca(t.widthCm,this._cellCm,this._gridPitch),this._gridPitch))),r=Math.min(e.h*gc,Math.max(e.h*_c,ai(ca(t.heightCm,this._cellCm,this._gridPitch),this._gridPitch))),a=la({x:i.x+i.w/2-o/2,y:i.y+i.h/2-r/2},s,t=>this._snap(t));this._bdApply((a[0]-e.x)/pm,(a[1]-e.y)/pm,o/e.w,r/e.h,s),this._backdropDialog=null,this._recordGeometry(this._t("history.backdrop_transform"),n),this._saveConfig()}get _bdActive(){return"decor"===this._mode&&!!this._bdRect&&"backdrop"===this._decorTool}get _bdMovable(){return"decor"===this._mode&&"backdrop"===this._decorTool&&!!this._bdRect}_bdApply(t,e,i,s,n){const o=this._curSpaceCfg;if(!o)return;o.plan_x=Number(Cc(t).toFixed(6)),o.plan_y=Number(Cc(e).toFixed(6)),delete o.plan_scale,o.plan_scale_x=Number(Math.min(gc,Math.max(_c,i)).toFixed(6)),o.plan_scale_y=Number(Math.min(gc,Math.max(_c,s)).toFixed(6));const r=aa(n);r?o.plan_angle=Number(r.toFixed(2)):delete o.plan_angle,this._cfgEpoch++,this.requestUpdate()}_bdStart(t,e,i=!1){const s=this._bdBase,n=this._bdRect;if(!s||!n)return!1;const o=this._svgPoint(t),r=e?e[0]:0,a=e?e[1]:0,l=r>0?n.x:n.x+n.w,c=a>0?n.y:n.y+n.h;return this._bdDrag={kind:i?"rotate":e?"scale":"move",pid:t.pointerId,sx:o[0],sy:o[1],base:s,p0:this._bdParams,fx:l,fy:c,sgx:r,sgy:a,rect0:{x:n.x,y:n.y,w:n.w,h:n.h,angle:n.angle},before:this._geometrySnapshot(),moved:!1},bm(t),!0}_bdMove(t){const e=this._bdDrag;if(!e)return;const i=this._svgPoint(t),s=e.base;if("move"===e.kind){const t=e.rect0.x,n=e.rect0.y,o=this._snap([t+(i[0]-e.sx),n+(i[1]-e.sy)]),r=Math.abs(o[0]-t)>1e-9||Math.abs(o[1]-n)>1e-9;if(!r&&!e.moved)return;return e.moved||=r,void this._bdApply((o[0]-s.x)/pm,(o[1]-s.y)/pm,e.p0.sx,e.p0.sy,e.p0.angle)}if("rotate"===e.kind){const s=e.rect0.x+e.rect0.w/2,n=e.rect0.y+e.rect0.h/2,o=180*Math.atan2(e.sy-n,e.sx-s)/Math.PI;let r=e.p0.angle+(180*Math.atan2(i[1]-n,i[0]-s)/Math.PI-o);t.shiftKey||(r=5*Math.round(r/5)),r=aa(r);const a=Math.abs(r-e.p0.angle)>1e-9;if(!a&&!e.moved)return;return e.moved||=a,void this._bdApply(e.p0.dx,e.p0.dy,e.p0.sx,e.p0.sy,r)}const n=ga(e.rect0,e.sgx,e.sgy,i[0],i[1],!t.shiftKey,this._gridPitch,Math.min(s.w,s.h)*_c),o=n.w/Math.max(1e-9,s.w),r=n.h/Math.max(1e-9,s.h),a=Math.abs(o-e.p0.sx)>1e-9||Math.abs(r-e.p0.sy)>1e-9||Math.abs(n.x-e.rect0.x)>1e-9||Math.abs(n.y-e.rect0.y)>1e-9;if(!a&&!e.moved)return;e.moved||=a;const l=la(n,e.p0.angle,t=>this._snap(t));this._bdApply((l[0]-s.x)/pm,(l[1]-s.y)/pm,o,r,e.p0.angle)}get _bdMoved(){if("decor"!==this._mode||!this._bdRect)return!1;const t=this._bdParams;return 0!==t.dx||0!==t.dy||1!==t.sx||1!==t.sy||0!==t.angle}_bdReset(){const t=this._curSpaceCfg;if(!t)return;const e=this._geometrySnapshot();delete t.plan_x,delete t.plan_y,delete t.plan_scale,delete t.plan_scale_x,delete t.plan_scale_y,delete t.plan_angle,this._bdDrag=null,this._recordGeometry(this._t("history.backdrop_transform"),e),this._saveConfig(),this._showToast(this._t("decor.backdrop_reset_done")),this.requestUpdate()}_bdUp(){const t=this._bdDrag;this._bdDrag=null,t?.moved&&(this._recordGeometry(this._t("history.backdrop_transform"),t.before),this._saveConfig()),this.requestUpdate()}get _bdLive(){if(!this._bdDrag)return null;const t=this._bdRect;return t?{x:t.x+t.w/2,y:t.y+t.h/2,text:`${this._fmtLen([0,0],[t.w,0])} × ${this._fmtLen([0,0],[0,t.h])}`}:null}_renderBackdropFrame(t){const e=this._bdRect;if(!this._bdActive||!e)return G;const i=.02*Math.max(t.w,t.h),s=i/4,n=e.x+e.w/2,o=e.y+e.h/2,r=aa(e.angle),a=2.2*i;return j` +
`}get _bdBase(){const t=this._curSpaceCfg;return t?.plan_url?{..._c(t.plan_aspect,um)}:null}get _bdRect(){const t=this._curSpaceCfg;return t?.plan_url?fc(t,um):null}get _bdParams(){const t=this._curSpaceCfg,e=Number(t?.plan_x),i=Number(t?.plan_y),s=Number(t?.plan_scale),n=Number(t?.plan_scale_x),o=Number(t?.plan_scale_y),a=Number.isFinite(s)&&s>0?s:1;return{dx:Number.isFinite(e)?e:0,dy:Number.isFinite(i)?i:0,sx:Number.isFinite(n)&&n>0?n:a,sy:Number.isFinite(o)&&o>0?o:a,angle:rr(t?.plan_angle)}}_openBackdropDialog(t){if(!this._bdMovable||!this._bdRect)return;t?.preventDefault(),t?.stopPropagation(),this._bdDrag=null;const e=this._bdRect;this._backdropDialog={widthCm:hr(e.w,this._cellCm,this._gridPitch),heightCm:hr(e.h,this._cellCm,this._gridPitch),angle:this._angleField(e.angle)}}_saveBackdropDialog(){const t=this._backdropDialog,e=this._bdBase,i=this._bdRect;if(!t||!e||!i)return;const s=rr(t.angle),n=this._geometrySnapshot(),o=Math.min(e.w*mc,Math.max(e.w*gc,ri(cr(t.widthCm,this._cellCm,this._gridPitch),this._gridPitch))),a=Math.min(e.h*mc,Math.max(e.h*gc,ri(cr(t.heightCm,this._cellCm,this._gridPitch),this._gridPitch))),r=lr({x:i.x+i.w/2-o/2,y:i.y+i.h/2-a/2},s,t=>this._snap(t));this._bdApply((r[0]-e.x)/um,(r[1]-e.y)/um,o/e.w,a/e.h,s),this._backdropDialog=null,this._recordGeometry(this._t("history.backdrop_transform"),n),this._saveConfig()}get _bdActive(){return"decor"===this._mode&&!!this._bdRect&&"backdrop"===this._decorTool}get _bdMovable(){return"decor"===this._mode&&"backdrop"===this._decorTool&&!!this._bdRect}_bdApply(t,e,i,s,n){const o=this._curSpaceCfg;if(!o)return;o.plan_x=Number(Dc(t).toFixed(6)),o.plan_y=Number(Dc(e).toFixed(6)),delete o.plan_scale,o.plan_scale_x=Number(Math.min(mc,Math.max(gc,i)).toFixed(6)),o.plan_scale_y=Number(Math.min(mc,Math.max(gc,s)).toFixed(6));const a=rr(n);a?o.plan_angle=Number(a.toFixed(2)):delete o.plan_angle,this._cfgEpoch++,this.requestUpdate()}_bdStart(t,e,i=!1){const s=this._bdBase,n=this._bdRect;if(!s||!n)return!1;const o=this._svgPoint(t),a=e?e[0]:0,r=e?e[1]:0,l=a>0?n.x:n.x+n.w,c=r>0?n.y:n.y+n.h;return this._bdDrag={kind:i?"rotate":e?"scale":"move",pid:t.pointerId,sx:o[0],sy:o[1],base:s,p0:this._bdParams,fx:l,fy:c,sgx:a,sgy:r,rect0:{x:n.x,y:n.y,w:n.w,h:n.h,angle:n.angle},before:this._geometrySnapshot(),moved:!1},wm(t),!0}_bdMove(t){const e=this._bdDrag;if(!e)return;const i=this._svgPoint(t),s=e.base;if("move"===e.kind){const t=e.rect0.x,n=e.rect0.y,o=this._snap([t+(i[0]-e.sx),n+(i[1]-e.sy)]),a=Math.abs(o[0]-t)>1e-9||Math.abs(o[1]-n)>1e-9;if(!a&&!e.moved)return;return e.moved||=a,void this._bdApply((o[0]-s.x)/um,(o[1]-s.y)/um,e.p0.sx,e.p0.sy,e.p0.angle)}if("rotate"===e.kind){const s=e.rect0.x+e.rect0.w/2,n=e.rect0.y+e.rect0.h/2,o=180*Math.atan2(e.sy-n,e.sx-s)/Math.PI;let a=e.p0.angle+(180*Math.atan2(i[1]-n,i[0]-s)/Math.PI-o);t.shiftKey||(a=5*Math.round(a/5)),a=rr(a);const r=Math.abs(a-e.p0.angle)>1e-9;if(!r&&!e.moved)return;return e.moved||=r,void this._bdApply(e.p0.dx,e.p0.dy,e.p0.sx,e.p0.sy,a)}const n=gr(e.rect0,e.sgx,e.sgy,i[0],i[1],!t.shiftKey,this._gridPitch,Math.min(s.w,s.h)*gc),o=n.w/Math.max(1e-9,s.w),a=n.h/Math.max(1e-9,s.h),r=Math.abs(o-e.p0.sx)>1e-9||Math.abs(a-e.p0.sy)>1e-9||Math.abs(n.x-e.rect0.x)>1e-9||Math.abs(n.y-e.rect0.y)>1e-9;if(!r&&!e.moved)return;e.moved||=r;const l=lr(n,e.p0.angle,t=>this._snap(t));this._bdApply((l[0]-s.x)/um,(l[1]-s.y)/um,o,a,e.p0.angle)}get _bdMoved(){if("decor"!==this._mode||!this._bdRect)return!1;const t=this._bdParams;return 0!==t.dx||0!==t.dy||1!==t.sx||1!==t.sy||0!==t.angle}_bdReset(){const t=this._curSpaceCfg;if(!t)return;const e=this._geometrySnapshot();delete t.plan_x,delete t.plan_y,delete t.plan_scale,delete t.plan_scale_x,delete t.plan_scale_y,delete t.plan_angle,this._bdDrag=null,this._recordGeometry(this._t("history.backdrop_transform"),e),this._saveConfig(),this._showToast(this._t("decor.backdrop_reset_done")),this.requestUpdate()}_bdUp(){const t=this._bdDrag;this._bdDrag=null,t?.moved&&(this._recordGeometry(this._t("history.backdrop_transform"),t.before),this._saveConfig()),this.requestUpdate()}get _bdLive(){if(!this._bdDrag)return null;const t=this._bdRect;return t?{x:t.x+t.w/2,y:t.y+t.h/2,text:`${this._fmtLen([0,0],[t.w,0])} × ${this._fmtLen([0,0],[0,t.h])}`}:null}_renderBackdropFrame(t){const e=this._bdRect;if(!this._bdActive||!e)return G;const i=.02*Math.max(t.w,t.h),s=i/4,n=e.x+e.w/2,o=e.y+e.h/2,a=rr(e.angle),r=2.2*i;return j` - - + {t.stopPropagation(),t.preventDefault(),this._bdStart(t,void 0,!0)}}> - - ${[[-1,-1,"nwse"],[1,-1,"nesw"],[1,1,"nwse"],[-1,1,"nesw"]].map(([t,n,o])=>{const r=t<0?e.x:e.x+e.w,a=n<0?e.y:e.y+e.h;return j` + ${[[-1,-1,"nwse"],[1,-1,"nesw"],[1,1,"nwse"],[-1,1,"nesw"]].map(([t,n,o])=>{const a=t<0?e.x:e.x+e.w,r=n<0?e.y:e.y+e.h;return j`{e.stopPropagation(),e.preventDefault(),this._bdStart(e,[t,n])}}>`})} - `}_renderTextFrame(t){const e=this._dtSel,i=this._dtBox;if(!e||!i||i.id!==e.id)return G;const s=.018*Math.max(t.w,t.h),n=s/4;if("line"===e.kind){const t=[e.x1*pm,e.y1*this._decorH],i=[e.x2*pm,e.y2*this._decorH];return j` + cx="${a}" cy="${r}" r="${i.toFixed(1)}" + @pointerdown=${e=>{e.stopPropagation(),e.preventDefault(),this._bdStart(e,[t,n])}}>`})} + `}_renderTextFrame(t){const e=this._dtSel,i=this._dtBox;if(!e||!i||i.id!==e.id)return G;const s=.018*Math.max(t.w,t.h),n=s/4;if("line"===e.kind){const t=[e.x1*um,e.y1*this._decorH],i=[e.x2*um,e.y2*this._decorH];return j` ${[t,i].map((t,e)=>j`this._dtStart(t,"scale",void 0,e)}> `)} - `}const[o,r]=this._dtPivot(e),a=Number(e.angle)||0,l=2.2*s;return j` + `}const[o,a]=this._dtPivot(e),r=Number(e.angle)||0,l=2.2*s;return j` this._dtStart(i,"scale",[t,e])}>`)} - `}_renderDecorLayer(){const t=pm,e=this._decorH,i="decor"===this._mode,s=i&&"erase"===this._decorTool,n=this._decorList.map(n=>{const o="dshape"+(i&&this._decorSel===n.id?" dsel":""),r=this._decorResolvedStyle(n),a=this._decorWidthUnits(n),l=t=>this._decorShapeDown(t,n),c=t=>this._decorShapeDbl(t,n);if("line"===n.kind)return j``}_renderDecorLayer(){const t=um,e=this._decorH,i="decor"===this._mode,s=i&&"erase"===this._decorTool,n=this._decorList.map(n=>{const o="dshape"+(i&&this._decorSel===n.id?" dsel":""),a=this._decorResolvedStyle(n),r=this._decorWidthUnits(n),l=t=>this._decorShapeDown(t,n),c=t=>this._decorShapeDbl(t,n);if("line"===n.kind)return j` ${i&&"select"===this._decorTool?j``:G}`;if("rect"===n.kind){const i=(n.x+n.w/2)*t,h=(n.y+n.h/2)*e,d=aa(n.angle);return j``:G}`;if("rect"===n.kind){const i=(n.x+n.w/2)*t,h=(n.y+n.h/2)*e,d=rr(n.angle);return j` ${s?j``:G}`}if("ellipse"===n.kind){const i=(n.x+n.w/2)*t,h=(n.y+n.h/2)*e,d=aa(n.angle);return j``:G}`}if("ellipse"===n.kind){const i=(n.x+n.w/2)*t,h=(n.y+n.h/2)*e,d=rr(n.angle);return j` ${s?j``:G}`}if("furniture"===n.kind){const i=n.w*t,h=n.h*e,d=th(n.symbol,i,h);if(!d)return G;const p=Number(n.angle)||0,u=n.x*t+i/2,_=n.y*e+h/2,g=`${p?`rotate(${p} ${u} ${_}) `:""}translate(${n.x*t} ${n.y*e})`;return j``:G}`}if("furniture"===n.kind){const i=n.w*t,h=n.h*e,d=eh(n.symbol,i,h);if(!d)return G;const p=Number(n.angle)||0,u=n.x*t+i/2,_=n.y*e+h/2,g=`${p?`rotate(${p} ${u} ${_}) `:""}translate(${n.x*t} ${n.y*e})`;return j` ${s?j``:G}`}if("text"===n.kind){const i=this._decorTextUnits(n),s=this._renderDeviceSnapshot?.facts.get(`decor:${this._space}:${n.id}`),a=function(t){return String(t??"").replace(/\r\n?/g,"\n").split("\n")}("string"==typeof s?s:ts(n.text,n,this._renderPlanHass,t=>this._renderEntityAvailable(t))),h=n.x*t,d=n.y*e,p=Number(n.angle)||0,u=d-(a.length-1)*i*1.2/2;return j``:G}`}if("text"===n.kind){const i=this._decorTextUnits(n),s=this._renderDeviceSnapshot?.facts.get(`decor:${this._space}:${n.id}`),r=function(t){return String(t??"").replace(/\r\n?/g,"\n").split("\n")}("string"==typeof s?s:ts(n.text,n,this._renderPlanHass,t=>this._renderEntityAvailable(t))),h=n.x*t,d=n.y*e,p=Number(n.angle)||0,u=d-(r.length-1)*i*1.2/2;return j`${a.map((t,e)=>j`${t}`)}`}return G});let o=G;const r=this._decorDraft;if(r){const t=this._decorStyle,e=ca(t.widthCm,this._cellCm,this._gridPitch);if("line"===r.kind)o=j``;else{const i=Math.min(r.a[0],r.b[0]),s=Math.min(r.a[1],r.b[1]),n=Math.abs(r.b[0]-r.a[0]),a=Math.abs(r.b[1]-r.a[1]);o="rect"===r.kind?j``:j`${r.map((t,e)=>j`${t}`)}`}return G});let o=G;const a=this._decorDraft;if(a){const t=this._decorStyle,e=cr(t.widthCm,this._cellCm,this._gridPitch);if("line"===a.kind)o=j``;else{const i=Math.min(a.a[0],a.b[0]),s=Math.min(a.a[1],a.b[1]),n=Math.abs(a.b[0]-a.a[0]),r=Math.abs(a.b[1]-a.a[1]);o="rect"===a.kind?j``:j``}}return j`${n}${o}`}get _editorToolbarGroups(){return"plan"!==this._mode?[]:[{id:"opening",label:this._t("markup.opening"),icon:"mdi:door",activeItemId:"opening"===this._tool?this._openingPreset?.type:void 0,items:[{id:"window",label:this._t("opening.window"),icon:"mdi:window-closed-variant",role:"tool",invoke:()=>this._activateOpeningPlacement("window")},{id:"door",label:this._t("opening.door"),icon:"mdi:door-open",role:"tool",invoke:()=>this._activateOpeningPlacement("door")},{id:"passage",label:this._t("opening.passage"),icon:"mdi:arch",role:"tool",invoke:()=>this._activateOpeningPlacement("passage")},{id:"gate",label:this._t("opening.gate"),icon:"mdi:gate",role:"tool",invoke:()=>this._activateOpeningPlacement("gate")}]}]}_renderEditorGroupLauncher(t){return this._editorSecondary.renderGroupLauncher(t,this._editorToolbarGroups,this._editorSecondaryCopy)}get _editorSecondaryContextId(){const t=`editor:${this._mode}:${this._space}:${this._cfgEpoch}`,e=this._editorSecondary.activeGroup(this._editorToolbarGroups);if(e)return`${t}:group:${e.id}:${this._editorSecondary.groupGeneration}`;if("plan"===this._mode){const e=this._physicalSel;return e?`${t}:selection:${e.kind}:${e.id}:${e.segment??""}`:`${t}:tool:${this._tool}:${this._path.length}:${this._openWallAnchor?1:0}`}return"decor"===this._mode?"furniture"===this._decorTool?`${t}:palette:furniture:${this._furnPalette?.symbol||"none"}`:"select"===this._decorTool&&this._decorSel?`${t}:selection:decor:${this._decorSel}`:`${t}:tool:${this._decorTool}:${this._bdMoved?1:0}:${this._bdDrag?1:0}`:`${t}:none`}_runEditorContext(t,e){this._editorSecondary.runContext(t,this._editorSecondaryContextId,e)}_renderEditorGroupModel(t){return this._editorSecondary.renderGroupModel(t,this._editorSecondaryContextId,this._editorSecondaryCopy)}_renderDrawWallControl(){return W``}_renderPlanSecondary(){const t=this._editorSecondaryContextId,e=this._physicalSel;if(e){if(!("partition"===e.kind?!!this._curSpaceCfg.partitions?.some(t=>t.id===e.id):"column"===e.kind?!!this._curSpaceCfg.wall_columns?.some(t=>t.id===e.id):!!this._curSpaceCfg.room_drafts?.some(t=>t.id===e.id)))return null;const i="partition"===e.kind?this._t("markup.partition"):"column"===e.kind?this._t("markup.column"):this._t("markup.add");return{contextId:t,kind:"selection",ariaLabel:this._t("editor.context_actions",{object:i}),visibleLabel:i,content:W` `:W`${this._t("gs.bg_theme")}`} `:W`
${this._t("gs.bg_daynight_hint")}
`} - ${ea(this.hass)?G:W`
${this._t("gs.sun_missing")}
`} + ${er(this.hass)?G:W`
${this._t("gs.sun_missing")}
`}
${this._renderCompass()}
@@ -5670,7 +5670,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8
`:G} -
${this._t("gs.about_version",{v:Gg})}
+
${this._t("gs.about_version",{v:Vg})}
${this._t("gs.about_github")} @@ -5727,7 +5727,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8 ${t.busy?"…":this._t("btn.save")}
- `}_saveKioskScale(t){this._kioskScale={...this._kioskScale,...t};try{localStorage.setItem(cm,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(hm,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])}% @@ -5784,7 +5784,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8 ${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,r=this._effectiveProjection();this._renderProjection=r,this._labs.active.length&&function(t){Z_||ng(t);const e=J_,i=e.active.join(",");if(!i||i===tg)return;tg=i;const s=new Map(q_.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}`)}(Gg);const a="iso"===r,l="devices"===this._mode&&this._showAll,c=this._renderDevices.filter(t=>t.space===s.id&&(!t.hidden||l)),h=this._renderDeviceSnapshot,d=this._spaceDisplayForRender(),p=a?this._isoDecorationLayers(d):null,u=p?this._isoOpeningPanels(p):[],_=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=au(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){Q_||og(t);const e=Z_,i=e.active.join(",");if(!i||i===eg)return;eg=i;const s=new Map(W_.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}`)}(Vg);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(),p=r?this._isoDecorationLayers(d):null,u=p?this._isoOpeningPanels(p):[],_=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=lu(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` ${this._t("count.devices",{n:c.filter(t=>!t.hidden).length})} - ${this._labsIso&&"view"===this._mode&&!this._kiosk?W``:G}
@@ -5871,7 +5871,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8
this._markupClick(t)} @wheel=${t=>this._onWheel(t)} @pointerdown=${t=>{this._notePointer(t),this._stagePointerDown(t)}} @@ -5879,21 +5879,21 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8 @pointerleave=${t=>this._stagePointerLeave(t)} @pointerup=${t=>this._stagePointerUp(t)} @pointercancel=${t=>this._stagePointerCancel(t)}> - ${na(I,A)} + ${nr(I,A)} ${this._renderEditorSecondary()}
- ${a&&p?.structural?j``:G} + preserveAspectRatio=${p?.structural||!r?"xMidYMid meet":"none"}> + transform=${p?.structural?hg():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} @@ -5905,7 +5905,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8 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 r=Fs(d.fill,e);if(!this._markup&&(d.showBorders||"none"!==r)){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 a;const l=t=>{"view"===this._mode&&(void 0===a&&(a=this._roomArea(e)),this._showTip(t,e.name||this._t("room.unnamed"),a?this._t("tip.area",{value:a}):"",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):[],p=c?[]:this._thickWallCuts(),u=h.concat(p);u.length&&(n+=" noedge");const g=i(e),f=this._spaceWalls,v=f.length&&e.id&&g&&ml(s.rooms,e.id,f,this._openPairs().flatMap(t=>t.segs),this._wallKeyPitch,this._cellCm,this._gridPitch,pm)||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):[],p=c?[]:this._thickWallCuts(),u=h.concat(p);u.length&&(n+=" noedge");const g=i(e),f=this._spaceWalls,v=f.length&&e.id&&g&&fl(s.rooms,e.id,f,this._openPairs().flatMap(t=>t.segs),this._wallKeyPitch,this._cellCm,this._gridPitch,um,this._wallUnionGeometry()?.roomGeom)||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})}} @@ -5964,7 +5964,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8 ${this._renderTextFrame(b)} - ${a&&p?.structural?j``:G} ${""} -
+
${c.map(t=>this._renderDevice(t,b,m))} ${this._renderVacuums(c,b)} ${this._renderVacFit(b)} @@ -6051,7 +6051,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8 ${null!=this._tip.temp?W`${this._t("tip.temp_avg")} ${this._tip.temp}°`:G} ${null!=this._tip.hum?W`${this._t("tip.hum_avg")} ${this._tip.hum}%`:G} ${null!=this._tip.lqi?W`${this._t("tip.lqi")} - ${this._tip.lqi}`:G} + ${this._tip.lqi}`:G}
`:G} ${this._kiosk&&!this._hasFixedFloor&&this._kioskDots&&this._model.length>1?W`
${this._model.map(t=>W``)} @@ -6082,22 +6082,22 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8 `: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=Uh(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||[]),r=new Set(o);n&&r.add(s.source);const a=i?.entities||{},l=[];for(const t of r){const e=i?.states?.[t],o=Uh(t,e,a[t]);o?l.push(o):n&&t===s.source&&l.push({entityId:t,name:String(e?.attributes?.friendly_name||t),platform:a[t]?.platform?String(a[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),r=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=r.find(e=>e.entityId===t);return{entityId:t,status:s[t]||(e?.hasPosition?"ok":"unverified"),pinned:!0,candidates:r}}const a=r.find(t=>o.has(t.entityId)&&t.hasPosition&&"ok"===s[t.entityId]);return a?{entityId:a.entityId,status:"ok",pinned:!1,candidates:r}:{entityId:null,status:"none",pinned:!1,candidates:r}}(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=Jp(this._planHass,t,this._devices,e,this._fullRegistryHass);return{samples:i.samples,sourceKey:tu(this._planHass,t,i)}}_stampActivity(t,e,i){let s=this._activityRt.get(t);s||(s=$u(i||"",[]),this._activityRt.set(t,s)),null!=i&&(s.sources=i),Mu(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:r}=n;let a=this._activityRt.get(s.id);a?a.sources!==r&&Su(a,r,o,window.clearTimeout.bind(window)):(a=$u(r,o),this._activityRt.set(s.id,a))}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 r=Cu(o,s,window.clearTimeout.bind(window));r&&this._stampActivity(e.id,r,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=Yh(this.hass.states[i||""]?.state),n=jh(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 r="never"!==td(t.marker?.vacuum)&&!n?.path.length;!s&&o.moving&&(o.endedTs=Date.now(),r&&o.lastPos&&(o.trail=Kh(o.trail,o.lastPos,40)),o.lastPos=null),o.moving=s;const a=n?.pos;if(s&&a){const t=a.x+":"+a.y;if(t!==o.lastKey){const e=Date.now();o.jump=o.lastTs>0&&e-o.lastTs>1e4,o.lastKey=t,o.lastTs=e,r&&o.lastPos&&(o.trail=Kh(o.trail,o.lastPos,40)),o.lastPos=[a.x,a.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,r=n.candidates.find(t=>t.entityId===o)||null,a=o?jh(this.hass?.states[o]?.attributes):null,l=!1!==i.live&&("ok"===n.status||"unsupported"===n.status),c=this._vacPlanRoomAnchors(e.space),h=a?function(t,e){const i=new Set(e.map(Gh).filter(Boolean)),s=new Set;for(const e of t){const t=Gh(e.name||"");t&&i.has(t)&&s.add(t)}return s.size}(a.rooms,c.map(t=>t.name)):0,d=!!(l&&a&&h>=3),p=Object.keys(i.calibration||{}),u=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=Gh(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=Gh(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=Zp(this._planHass,t,this._devices,e,this._fullRegistryHass);return{samples:i.samples,sourceKey:eu(this._planHass,t,i)}}_stampActivity(t,e,i){let s=this._activityRt.get(t);s||(s=Su(i||"",[]),this._activityRt.set(t,s)),null!=i&&(s.sources=i),Cu(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&&Mu(r,a,o,window.clearTimeout.bind(window)):(r=Su(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=Du(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=Xh(this.hass.states[i||""]?.state),n=Uh(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"!==ed(t.marker?.vacuum)&&!n?.path.length;!s&&o.moving&&(o.endedTs=Date.now(),a&&o.lastPos&&(o.trail=Yh(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=Yh(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?Uh(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(Vh).filter(Boolean)),s=new Set;for(const e of t){const t=Vh(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),p=Object.keys(i.calibration||{}),u=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` `,y=n.candidates.some(t=>_.has(t.entityId)&&"known_xcme_incomplete"===t.category)||!!n.pinned&&!!o?.startsWith("camera.")&&!r?.hasPosition;return W` + `,y=n.candidates.some(t=>_.has(t.entityId)&&"known_xcme_incomplete"===t.category)||!!n.pinned&&!!o?.startsWith("camera.")&&!a?.hasPosition;return W`
${this._t("vac.diag_source")}${o||this._t("vac.source_none")}
- ${r?.platform?W`
${this._t("vac.diag_platform")}${r.platform}
`:G} + ${a?.platform?W`
${this._t("vac.diag_platform")}${a.platform}
`:G}
${this._t("vac.diag_status")}${this._t(`vac.source_status_${n.status}`)}
-
${this._t("vac.diag_position")}${a?.pos?this._t("common.yes"):this._t("common.no")}
-
${this._t("vac.diag_rooms")}${ss(this._t("vac.diag_rooms_value"),{total:String(a?.rooms.length||0),matched:String(h),readiness:this._t(h>=3?"vac.autocal_ready":"vac.autocal_not_ready")})}
-
${this._t("vac.diag_path")}${a?.path.length?this._t("common.yes"):this._t("common.no")}
-
${this._t("vac.diag_map")}${a?.mapId??"default"}
+
${this._t("vac.diag_position")}${r?.pos?this._t("common.yes"):this._t("common.no")}
+
${this._t("vac.diag_rooms")}${ss(this._t("vac.diag_rooms_value"),{total:String(r?.rooms.length||0),matched:String(h),readiness:this._t(h>=3?"vac.autocal_ready":"vac.autocal_not_ready")})}
+
${this._t("vac.diag_path")}${r?.path.length?this._t("common.yes"):this._t("common.no")}
+
${this._t("vac.diag_map")}${r?.mapId??"default"}
${"missing"===n.status||"disabled"===n.status||"unverified"===n.status?W`
- ${a?W` + ${r?W`
`}_vacMapId(t,e,i=this._planHass){const s=this._vacEntity(t),n=s?i?.states?.[s]?.attributes?.selected_map:null;return o=e.mapId,r=n,"default"!==o?o:null!=r?String(r):"default";var o,r}_vacSaveMatrix(t,e,i,s){const n=this._devices.find(e=>e.id===t),o=n?this._vacEnsureMarker(n):this._serverCfg?.markers?.find(e=>e.id===t);if(!o)return!1;const r={...o.vacuum||{}};return r.source=e,r.calibration={...r.calibration||{},[i]:s.map(t=>Number(t.toFixed(6)))},o.vacuum=r,this._regSignature="",this._maybeRebuildDevices(),this._saveConfig(),this.requestUpdate(),!0}_vacPlanRoomAnchors(t){return(this._spaceModelById(t)?.rooms||[]).map(t=>({room:t,poly:hi(t)})).filter(({room:t,poly:e})=>t.name&&e).map(({room:t,poly:e})=>{const i=Hh(e);return i?{name:String(t.name),cx:i[0],cy:i[1]}:null}).filter(Boolean)}_vacAutoCalibrate(t){const e=this._vacSource(t),i=e?jh(this.hass?.states[e]?.attributes):null;if(!e||!i||i.rooms.length<3)return void this._showToast(this._t("vac.autocal_no_rooms"));const s=this._vacPlanRoomAnchors(t.space),n=Vh(i.rooms,s);if(!n)return void this._showToast(this._t("vac.autocal_no_match"));const o=this._serverCfg?.spaces?.find(e=>e.id===t.space),r=Number(o?.cell_cm),a=Number.isFinite(r)&&r>0?r:5,l=function(t,e,i){return![t,e,i].every(Number.isFinite)||t<0||e<=0||i<=0?Number.POSITIVE_INFINITY:t/e*i}(n.residual,this._gridPitch,a),c=this._vacMapId(t,i);l>40?this._vacCalConfirm={markerId:t.id,source:e,mapId:c,matrix:n.matrix,rooms:n.matched.length,error:li(l,"mi"===this.hass?.config?.unit_system?.length)}:this._vacSaveMatrix(t.id,e,c,n.matrix)&&this._showToast(ss(this._t("vac.autocal_done"),{rooms:String(n.matched.length)}))}_vacApplyCalibrationProposal(t){const e=this._vacCalConfirm;if(e){if(this._vacCalConfirm=null,t){const t=this._devices.find(t=>t.id===e.markerId),i=Zh(e.matrix);if(!t||!i)return;if(this._markerDialog=null,t.space!==this._space&&!this._commitSpace(t.space))return;return void(this._vacFit={markerId:e.markerId,source:e.source,mapId:e.mapId,p:i,drag:null})}this._vacSaveMatrix(e.markerId,e.source,e.mapId,e.matrix)&&this._showToast(ss(this._t("vac.autocal_done"),{rooms:String(e.rooms)}))}}_vacStartFit(t){const e=this._vacSource(t),i=e?jh(this.hass?.states[e]?.attributes):null;if(!e||!i)return void this._showToast(this._t("vac.cal_need_pos"));const s=this._vacMapId(t,i),n=t.marker?.vacuum?.calibration?.[s],o=this._spaceModelById(t.space);if(!o)return;const r=o.vb,a=n&&6===n.length&&Zh(n)||function(t,e){const i=[],s=[];for(const e of t)null!=e.x0?(i.push(e.x0,e.x1),s.push(e.y0,e.y1)):(i.push(e.cx),s.push(e.cy));if(!i.length)return{ox:e[0]+e[2]/2,oy:e[1]+e[3]/2,s:e[2]/1e4,rot:0,mir:!0};const n=Math.min(...i),o=Math.max(...i),r=Math.min(...s),a=Math.max(...s),l=Math.max(o-n,a-r)||1,c={ox:0,oy:0,s:.6*Math.min(e[2],e[3])/l,rot:0,mir:!0},h=Jh(c),[d,p]=Eh(h,(n+o)/2,(r+a)/2);return c.ox=e[0]+e[2]/2-d,c.oy=e[1]+e[3]/2-p,c}(i.rooms,r);this._markerDialog=null,(t.space===this._space||this._commitSpace(t.space))&&(this._vacFit={markerId:t.id,source:e,mapId:s,p:a,drag:null})}_vacFitSave(){const t=this._vacFit;if(!t)return;const e=this._vacSaveMatrix(t.markerId,t.source,t.mapId,Jh(t.p));this._vacFit=null,e&&this._showToast(this._t("vac.cal_done"))}_vacFitTurn(t){const e=this._vacFit;if(!e)return;const i=jh(this.hass?.states[e.source]?.attributes),s=this._vacGhostCentre(i?.rooms||[]),n={...e.p,...t};this._vacFit={...e,p:Qh(n,e.p,s[0],s[1])}}_vacGhostCentre(t){const e=[],i=[];for(const s of t)e.push(s.x0??s.cx,s.x1??s.cx),i.push(s.y0??s.cy,s.y1??s.cy);return e.length?[(Math.min(...e)+Math.max(...e))/2,(Math.min(...i)+Math.max(...i))/2]:[0,0]}_vacDelta(t,e,i){const s=this._stageEl,n=s?.clientWidth||1,o=s?.clientHeight||1;return[e/n*t.w,i/o*t.h]}_vacFitPointer(t,e){const i=this._vacFit;if(!i)return;if(t.stopPropagation(),"pointerdown"===t.type){const e=t.target,s=e.getAttribute?.("data-corner");try{t.currentTarget.setPointerCapture?.(t.pointerId)}catch{}return void(this._vacFit={...i,drag:s?{kind:"scale",sx:t.clientX,sy:t.clientY,p0:{...i.p},fx:Number(s.split(",")[0]),fy:Number(s.split(",")[1])}:{kind:"move",sx:t.clientX,sy:t.clientY,p0:{...i.p},fx:0,fy:0}})}const s=i.drag;if(s){if("pointermove"===t.type){const[n,o]=this._vacDelta(e,t.clientX-s.sx,t.clientY-s.sy);if("move"===s.kind)this._vacFit={...i,p:{...s.p0,ox:s.p0.ox+n,oy:s.p0.oy+o}};else{const t=jh(this.hass?.states[i.source]?.attributes),e=this._vacGhostCentre(t?.rooms||[]),r=Jh(s.p0),[a,l]=Eh(r,e[0],e[1]),[c,h]=Eh(r,s.fx,s.fy),d=Math.hypot(a-c,l-h)||1,[p,u]=[2*a-c,2*l-h],_=Math.hypot(p+2*n-c,u+2*o-h)/2,g=Math.max(.05,_/d),m={...s.p0,s:s.p0.s*g};this._vacFit={...i,p:Qh(m,s.p0,s.fx,s.fy)}}return}"pointerup"!==t.type&&"pointercancel"!==t.type||(this._vacFit={...i,drag:null})}}_renderVacFit(t){const e=this._vacFit;if(!e)return G;const i=jh(this._renderPlanHass?.states?.[e.source]?.attributes);if(!i)return G;const s=Jh(e.p),n=[],o=[],r=[];for(const t of i.rooms){if(null==t.x0)continue;const e=[[t.x0,t.y0],[t.x1,t.y0],[t.x1,t.y1],[t.x0,t.y1]].map(([t,e])=>Eh(s,t,e));e.forEach(([t,e])=>{o.push(t),r.push(e)});const[i,a]=Eh(s,t.cx,t.cy);n.push(j` - ${t.name}`)}let a=G;if(i.pos){const[e,n]=Eh(s,i.pos.x,i.pos.y);a=j``}const l=[];if(o.length){const e=(()=>{const t=s[0]*s[4]-s[1]*s[3];return(e,i)=>[(s[4]*(e-s[2])-s[1]*(i-s[5]))/t,(-s[3]*(e-s[2])+s[0]*(i-s[5]))/t]})(),i=Math.min(...o),n=Math.max(...o),a=Math.min(...r),c=Math.max(...r),h=.022*t.w,d=h/4;for(const[t,s,o,r]of[[i,a,n,c],[n,a,i,c],[n,c,i,a],[i,c,n,a]]){const i=e(o,r);l.push(j``}_vacMapId(t,e,i=this._planHass){const s=this._vacEntity(t),n=s?i?.states?.[s]?.attributes?.selected_map:null;return o=e.mapId,a=n,"default"!==o?o:null!=a?String(a):"default";var o,a}_vacSaveMatrix(t,e,i,s){const n=this._devices.find(e=>e.id===t),o=n?this._vacEnsureMarker(n):this._serverCfg?.markers?.find(e=>e.id===t);if(!o)return!1;const a={...o.vacuum||{}};return a.source=e,a.calibration={...a.calibration||{},[i]:s.map(t=>Number(t.toFixed(6)))},o.vacuum=a,this._regSignature="",this._maybeRebuildDevices(),this._saveConfig(),this.requestUpdate(),!0}_vacPlanRoomAnchors(t){return(this._spaceModelById(t)?.rooms||[]).map(t=>({room:t,poly:hi(t)})).filter(({room:t,poly:e})=>t.name&&e).map(({room:t,poly:e})=>{const i=Lh(e);return i?{name:String(t.name),cx:i[0],cy:i[1]}:null}).filter(Boolean)}_vacAutoCalibrate(t){const e=this._vacSource(t),i=e?Uh(this.hass?.states[e]?.attributes):null;if(!e||!i||i.rooms.length<3)return void this._showToast(this._t("vac.autocal_no_rooms"));const s=this._vacPlanRoomAnchors(t.space),n=Kh(i.rooms,s);if(!n)return void this._showToast(this._t("vac.autocal_no_match"));const o=this._serverCfg?.spaces?.find(e=>e.id===t.space),a=Number(o?.cell_cm),r=Number.isFinite(a)&&a>0?a:5,l=function(t,e,i){return![t,e,i].every(Number.isFinite)||t<0||e<=0||i<=0?Number.POSITIVE_INFINITY:t/e*i}(n.residual,this._gridPitch,r),c=this._vacMapId(t,i);l>40?this._vacCalConfirm={markerId:t.id,source:e,mapId:c,matrix:n.matrix,rooms:n.matched.length,error:li(l,"mi"===this.hass?.config?.unit_system?.length)}:this._vacSaveMatrix(t.id,e,c,n.matrix)&&this._showToast(ss(this._t("vac.autocal_done"),{rooms:String(n.matched.length)}))}_vacApplyCalibrationProposal(t){const e=this._vacCalConfirm;if(e){if(this._vacCalConfirm=null,t){const t=this._devices.find(t=>t.id===e.markerId),i=Qh(e.matrix);if(!t||!i)return;if(this._markerDialog=null,t.space!==this._space&&!this._commitSpace(t.space))return;return void(this._vacFit={markerId:e.markerId,source:e.source,mapId:e.mapId,p:i,drag:null})}this._vacSaveMatrix(e.markerId,e.source,e.mapId,e.matrix)&&this._showToast(ss(this._t("vac.autocal_done"),{rooms:String(e.rooms)}))}}_vacStartFit(t){const e=this._vacSource(t),i=e?Uh(this.hass?.states[e]?.attributes):null;if(!e||!i)return void this._showToast(this._t("vac.cal_need_pos"));const s=this._vacMapId(t,i),n=t.marker?.vacuum?.calibration?.[s],o=this._spaceModelById(t.space);if(!o)return;const a=o.vb,r=n&&6===n.length&&Qh(n)||function(t,e){const i=[],s=[];for(const e of t)null!=e.x0?(i.push(e.x0,e.x1),s.push(e.y0,e.y1)):(i.push(e.cx),s.push(e.cy));if(!i.length)return{ox:e[0]+e[2]/2,oy:e[1]+e[3]/2,s:e[2]/1e4,rot:0,mir:!0};const n=Math.min(...i),o=Math.max(...i),a=Math.min(...s),r=Math.max(...s),l=Math.max(o-n,r-a)||1,c={ox:0,oy:0,s:.6*Math.min(e[2],e[3])/l,rot:0,mir:!0},h=Zh(c),[d,p]=zh(h,(n+o)/2,(a+r)/2);return c.ox=e[0]+e[2]/2-d,c.oy=e[1]+e[3]/2-p,c}(i.rooms,a);this._markerDialog=null,(t.space===this._space||this._commitSpace(t.space))&&(this._vacFit={markerId:t.id,source:e,mapId:s,p:r,drag:null})}_vacFitSave(){const t=this._vacFit;if(!t)return;const e=this._vacSaveMatrix(t.markerId,t.source,t.mapId,Zh(t.p));this._vacFit=null,e&&this._showToast(this._t("vac.cal_done"))}_vacFitTurn(t){const e=this._vacFit;if(!e)return;const i=Uh(this.hass?.states[e.source]?.attributes),s=this._vacGhostCentre(i?.rooms||[]),n={...e.p,...t};this._vacFit={...e,p:td(n,e.p,s[0],s[1])}}_vacGhostCentre(t){const e=[],i=[];for(const s of t)e.push(s.x0??s.cx,s.x1??s.cx),i.push(s.y0??s.cy,s.y1??s.cy);return e.length?[(Math.min(...e)+Math.max(...e))/2,(Math.min(...i)+Math.max(...i))/2]:[0,0]}_vacDelta(t,e,i){const s=this._stageEl,n=s?.clientWidth||1,o=s?.clientHeight||1;return[e/n*t.w,i/o*t.h]}_vacFitPointer(t,e){const i=this._vacFit;if(!i)return;if(t.stopPropagation(),"pointerdown"===t.type){const e=t.target,s=e.getAttribute?.("data-corner");try{t.currentTarget.setPointerCapture?.(t.pointerId)}catch{}return void(this._vacFit={...i,drag:s?{kind:"scale",sx:t.clientX,sy:t.clientY,p0:{...i.p},fx:Number(s.split(",")[0]),fy:Number(s.split(",")[1])}:{kind:"move",sx:t.clientX,sy:t.clientY,p0:{...i.p},fx:0,fy:0}})}const s=i.drag;if(s){if("pointermove"===t.type){const[n,o]=this._vacDelta(e,t.clientX-s.sx,t.clientY-s.sy);if("move"===s.kind)this._vacFit={...i,p:{...s.p0,ox:s.p0.ox+n,oy:s.p0.oy+o}};else{const t=Uh(this.hass?.states[i.source]?.attributes),e=this._vacGhostCentre(t?.rooms||[]),a=Zh(s.p0),[r,l]=zh(a,e[0],e[1]),[c,h]=zh(a,s.fx,s.fy),d=Math.hypot(r-c,l-h)||1,[p,u]=[2*r-c,2*l-h],_=Math.hypot(p+2*n-c,u+2*o-h)/2,g=Math.max(.05,_/d),m={...s.p0,s:s.p0.s*g};this._vacFit={...i,p:td(m,s.p0,s.fx,s.fy)}}return}"pointerup"!==t.type&&"pointercancel"!==t.type||(this._vacFit={...i,drag:null})}}_renderVacFit(t){const e=this._vacFit;if(!e)return G;const i=Uh(this._renderPlanHass?.states?.[e.source]?.attributes);if(!i)return G;const s=Zh(e.p),n=[],o=[],a=[];for(const t of i.rooms){if(null==t.x0)continue;const e=[[t.x0,t.y0],[t.x1,t.y0],[t.x1,t.y1],[t.x0,t.y1]].map(([t,e])=>zh(s,t,e));e.forEach(([t,e])=>{o.push(t),a.push(e)});const[i,r]=zh(s,t.cx,t.cy);n.push(j` + ${t.name}`)}let r=G;if(i.pos){const[e,n]=zh(s,i.pos.x,i.pos.y);r=j``}const l=[];if(o.length){const e=(()=>{const t=s[0]*s[4]-s[1]*s[3];return(e,i)=>[(s[4]*(e-s[2])-s[1]*(i-s[5]))/t,(-s[3]*(e-s[2])+s[0]*(i-s[5]))/t]})(),i=Math.min(...o),n=Math.max(...o),r=Math.min(...a),c=Math.max(...a),h=.022*t.w,d=h/4;for(const[t,s,o,a]of[[i,r,n,c],[n,r,i,c],[n,c,i,r],[i,c,n,r]]){const i=e(o,a);l.push(j` `)}}return W`this._vacFitPointer(e,t)} @pointermove=${e=>this._vacFitPointer(e,t)} @pointerup=${e=>this._vacFitPointer(e,t)} - @pointercancel=${e=>this._vacFitPointer(e,t)}>${n}${a}${l}`}_vacRafLoop(){this._vacRaf=requestAnimationFrame(()=>{const t=this.renderRoot,e=this._stageEl,i=this._vacLastView,s=t?.querySelectorAll?.(".vacpuck")||[];if(!e||!i||!s.length)return void(this._vacRaf=0);const n=e.getBoundingClientRect();for(const e of s){const s=e.getAttribute("data-mid"),o=e.getBoundingClientRect(),r=i.x+(o.left+o.width/2-n.left)/n.width*i.w,a=i.y+(o.top+o.height/2-n.top)/n.height*i.h;for(const e of t.querySelectorAll(`line.tip[data-mid="${s}"]`))e.setAttribute("x2",r.toFixed(1)),e.setAttribute("y2",a.toFixed(1))}this._vacRafLoop()})}_renderVacuums(t,e){if(this._markup||"decor"===this._mode)return G;const i=this._space+"|"+e.x+"|"+e.y+"|"+e.w+"|"+e.h,s=this._vacJumpOnce||i!==this._vacViewKey;this._vacViewKey=i,this._vacJumpOnce=!1;const n=[],o=[];for(const i of t){if(i.hidden||!this._isVacDev(i))continue;if("static_icon"===Bi(i.marker?.display))continue;const t=this._renderDeviceSnapshot?.facts.get(`vacuum:${i.id}`),r=t?.source??this._vacSource(i,this._renderPlanHass);if(!r)continue;const a=t?.telemetry??jh(this._renderPlanHass?.states[r]?.attributes);if(!a)continue;const l=String(t?.mapId??this._vacMapId(i,a,this._renderPlanHass)),c=i.marker?.vacuum?.calibration?.[l];if(!c||6!==c.length)continue;const h=t?.runtime??this._vacRt.get(i.id),d=h?.moving??!1,p=td(i.marker?.vacuum),u="always"===p||"cleaning"===p&&d,_=t?.server??this._vacSrvTrails[i.id],g=_?.current?.map_id===l&&Array.isArray(_.current.points)?_.current:null,m=_?.previous?.map_id===l&&Array.isArray(_.previous.points)?_.previous:null;if("always"===p&&m&&m.points.length>1){const t=m.points.map(([t,e])=>{const[i,s]=Eh(c,t,e),n=this._scenePoint([i,s]);return n[0].toFixed(1)+","+n[1].toFixed(1)}).join(" ");o.push(j``)}if(u){const t=qh(a,g,h?.trail||[]),e=!d||"integration"!==t.source&&"server"!==t.source?t.path:Wh(t.path);if(e.length){const t=e.map(t=>t.map(([t,e],i)=>{const[s,n]=Eh(c,t,e),o=this._scenePoint([s,n]);return`${i?"L":"M"} ${o[0].toFixed(1)} ${o[1].toFixed(1)}`}).join(" ")).join(" ");o.push(j``);const s=e[e.length-1];if(d&&s?.length>=2){const t=s[s.length-1],[e,n]=Eh(c,t[0],t[1]),r=this._scenePoint([e,n]),a=r[0].toFixed(1),l=r[1].toFixed(1);o.push(j``)}}}if(!d||!a.pos)continue;const[f,v]=Eh(c,a.pos.x,a.pos.y),y=this._scenePoint([f,v]),b=(y[0]-e.x)/e.w*100,w=(y[1]-e.y)/e.h*100,k=h&&h.lastTs>0&&Date.now()-h.lastTs>6e4,x=i.marker?.icon||i.icon||"mdi:robot-vacuum";n.push(W`
this._vacFitPointer(e,t)}>${n}${r}${l}`}_vacRafLoop(){this._vacRaf=requestAnimationFrame(()=>{const t=this.renderRoot,e=this._stageEl,i=this._vacLastView,s=t?.querySelectorAll?.(".vacpuck")||[];if(!e||!i||!s.length)return void(this._vacRaf=0);const n=e.getBoundingClientRect();for(const e of s){const s=e.getAttribute("data-mid"),o=e.getBoundingClientRect(),a=i.x+(o.left+o.width/2-n.left)/n.width*i.w,r=i.y+(o.top+o.height/2-n.top)/n.height*i.h;for(const e of t.querySelectorAll(`line.tip[data-mid="${s}"]`))e.setAttribute("x2",a.toFixed(1)),e.setAttribute("y2",r.toFixed(1))}this._vacRafLoop()})}_renderVacuums(t,e){if(this._markup||"decor"===this._mode)return G;const i=this._space+"|"+e.x+"|"+e.y+"|"+e.w+"|"+e.h,s=this._vacJumpOnce||i!==this._vacViewKey;this._vacViewKey=i,this._vacJumpOnce=!1;const n=[],o=[];for(const i of t){if(i.hidden||!this._isVacDev(i))continue;if("static_icon"===Bi(i.marker?.display))continue;const t=this._renderDeviceSnapshot?.facts.get(`vacuum:${i.id}`),a=t?.source??this._vacSource(i,this._renderPlanHass);if(!a)continue;const r=t?.telemetry??Uh(this._renderPlanHass?.states[a]?.attributes);if(!r)continue;const l=String(t?.mapId??this._vacMapId(i,r,this._renderPlanHass)),c=i.marker?.vacuum?.calibration?.[l];if(!c||6!==c.length)continue;const h=t?.runtime??this._vacRt.get(i.id),d=h?.moving??!1,p=ed(i.marker?.vacuum),u="always"===p||"cleaning"===p&&d,_=t?.server??this._vacSrvTrails[i.id],g=_?.current?.map_id===l&&Array.isArray(_.current.points)?_.current:null,m=_?.previous?.map_id===l&&Array.isArray(_.previous.points)?_.previous:null;if("always"===p&&m&&m.points.length>1){const t=m.points.map(([t,e])=>{const[i,s]=zh(c,t,e),n=this._scenePoint([i,s]);return n[0].toFixed(1)+","+n[1].toFixed(1)}).join(" ");o.push(j``)}if(u){const t=Wh(r,g,h?.trail||[]),e=!d||"integration"!==t.source&&"server"!==t.source?t.path:jh(t.path);if(e.length){const t=e.map(t=>t.map(([t,e],i)=>{const[s,n]=zh(c,t,e),o=this._scenePoint([s,n]);return`${i?"L":"M"} ${o[0].toFixed(1)} ${o[1].toFixed(1)}`}).join(" ")).join(" ");o.push(j``);const s=e[e.length-1];if(d&&s?.length>=2){const t=s[s.length-1],[e,n]=zh(c,t[0],t[1]),a=this._scenePoint([e,n]),r=a[0].toFixed(1),l=a[1].toFixed(1);o.push(j``)}}}if(!d||!r.pos)continue;const[f,v]=zh(c,r.pos.x,r.pos.y),y=this._scenePoint([f,v]),b=(y[0]-e.x)/e.w*100,w=(y[1]-e.y)/e.h*100,k=h&&h.lastTs>0&&Date.now()-h.lastTs>6e4,x=i.marker?.icon||i.icon||"mdi:robot-vacuum";n.push(W`
${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,r=(n[1]-e.y)/e.h*100,a=this._devicePresentation(t,i),l=[`left:${o}%`,`top:${r}%`,...Go(a)],c=a.disabledReason,h=a.haDisabled?this._t(`marker.ha_disabled_${c}`):t.userHidden?this._t("marker.hidden_ghost"):t.name,d=Gp(a),p="view"===this._mode||"devices"===this._mode,u=[h,a.haDisabled?"":this._t(`marker.state_a11y_${d}`),"none"!==a.pulse.kind?this._t(`marker.pulse_a11y_${a.pulse.reason}`):"",a.valueFullText||a.valueText||"",Ro(a.valueBadge),null!=a.lqiText&&a.lqiBand?this._t(`marker.lqi_a11y_${a.lqiBand}`,{value:a.lqiText}):""].filter(Boolean).join(", "),_=[t.model,a.valueBadge?.fullText||"",null!=a.lqiText?"LQI "+a.lqiText:""].filter(Boolean).join(" · ");return W`
this._clickDevice(e,t)} @keydown=${e=>this._keyDevice(e,t)} @contextmenu=${e=>this._ctxDevice(e,t)} - @pointerover=${e=>this._showTip(e,t.name,a.haDisabled?h:_)} + @pointerover=${e=>this._showTip(e,t.name,r.haDisabled?h:_)} @pointerleave=${()=>this._clearTransientHover()} @pointerdown=${e=>this._pointerDown(e,t)} - @pointermove=${e=>{this._pointerMove(e,t),this._showTip(e,t.name,a.haDisabled?h:_)}} + @pointermove=${e=>{this._pointerMove(e,t),this._showTip(e,t.name,r.haDisabled?h:_)}} @pointerup=${e=>this._pointerUp(e,t)} @pointercancel=${e=>this._pointerUp(e,t)} > - ${Ko(a,{newDevice:this._newIds.has(t.id),newDeviceTitle:this._t("device.new"),disabledTitle:a.haDisabled?h:""})} -
`}_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&&ml(i.rooms,t.id,s,this._openPairs().flatMap(t=>t.segs),this._wallKeyPitch,this._cellCm,this._gridPitch,pm)||e,o=this._cleanFloor(t,n),r=this._cellCm/this._gridPitch;return Ir(o.area*r*r/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 r=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,a=i.area_id||s?.area_id||null;if(!a)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=r.get(a);l||(l=new Map,r.set(a,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 r){const r=[],a=[];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&&r.push(e)}if(o.size>0&&(o.has(i)||s.ents.some(t=>o.has(t)))){const e=mo(t,s.ents);null!=e&&r.push(e)}if(l||"mdi:water-percent"===n){const e=vo(t,s.ents);null!=e&&a.push(e)}}(r.length||a.length)&&s.set(i,{temp:r.length?Math.round(r.reduce((t,e)=>t+e,0)/r.length*10)/10:null,hum:a.length?Math.round(a.reduce((t,e)=>t+e,0)/a.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?as(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 r=o.name||t.states[n]?.attributes?.friendly_name||n;i&&!(r+" "+n).toLowerCase().includes(i)||s.push({value:"entity:"+n,label:r,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*pm,y:i.y*pm};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},bm(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 r=o.vb,a=n.getBoundingClientRect(),l=this._viewOr(r),c=(t.clientX-this._drag.sx)/a.width*l.w,h=(t.clientY-this._drag.sy)/a.height*l.h;Math.abs(t.clientX-this._drag.sx)+Math.abs(t.clientY-this._drag.sy)>3&&(this._drag.moved=!0);const d=Mc(this._drag.ox+c),p=Mc(this._drag.oy+h);this._savePos({id:s,space:i},d,p)}_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,r=n.top+n.height/2,a=Math.max(8,Math.hypot(t.clientX-o,t.clientY-r));this._rlResize={id:"rl_"+(e.id||""),space:i,k0:this._labelScale(e),cx:o,cy:r,d0:a},bm(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/pm,y:o.y/pm,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``}_renderRoomLabel(t,e,i,s){if(!t.name&&!this._markup)return G;const n=this._labelPos(t,e.id),o=this._scenePoint([n.x,n.y]),r=(o[0]-i.x)/i.w*100,a=(o[1]-i.y)/i.h*100,l=Math.min(1,s.opacity+.25),c=this._labelScale(t),h=[];if(t.area||t.settings?.temp_source||t.settings?.hum_source||s.labelLight){if(s.labelTemp){const e=this._roomTemp(t);null!=e&&h.push(W`${e}°`)}if(s.labelHum){const e=this._roomHum(t);null!=e&&h.push(W`${e}%`)}if(s.labelLqi&&t.area){const e=this._roomLqi(t.area);null!=e&&h.push(W`${e}`)}if(s.labelLight){const e=(d=ho(this._renderPlanHass,this._renderDevices,t,this._virtualLights)).length?{on:d.filter(t=>t.on).length,total:d.length}:null;if(e){const t=0===e.on?this._t("roomcard.light_off"):e.on===e.total?this._t("roomcard.light_on"):this._t("roomcard.light_partial",{on:e.on,total:e.total});h.push(W`${t}`)}}}var d;const p=!!t.area,u=!this._markup;return W`
`}_renderRoomLabel(t,e,i,s){if(!t.name&&!this._markup)return G;const n=this._labelPos(t,e.id),o=this._scenePoint([n.x,n.y]),a=(o[0]-i.x)/i.w*100,r=(o[1]-i.y)/i.h*100,l=Math.min(1,s.opacity+.25),c=this._labelScale(t),h=[];if(t.area||t.settings?.temp_source||t.settings?.hum_source||s.labelLight){if(s.labelTemp){const e=this._roomTemp(t);null!=e&&h.push(W`${e}°`)}if(s.labelHum){const e=this._roomHum(t);null!=e&&h.push(W`${e}%`)}if(s.labelLqi&&t.area){const e=this._roomLqi(t.area);null!=e&&h.push(W`${e}`)}if(s.labelLight){const e=(d=ho(this._renderPlanHass,this._renderDevices,t,this._virtualLights)).length?{on:d.filter(t=>t.on).length,total:d.length}:null;if(e){const t=0===e.on?this._t("roomcard.light_off"):e.on===e.total?this._t("roomcard.light_on"):this._t("roomcard.light_partial",{on:e.on,total:e.total});h.push(W`${t}`)}}}var d;const p=!!t.area,u=!this._markup;return W`
this._labelDown(i,t,e.id)} @pointermove=${i=>this._labelMove(i,t,e.id)} @pointerup=${()=>this._labelUp(t)} @@ -6212,12 +6212,12 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8 @pointermove=${t=>this._rlResizeMove(t)} @pointerup=${()=>this._rlResizeUp()} @pointercancel=${()=>this._rlResizeUp()}>`):G} -
`}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),r=Math.round(10*o)/10,a=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)} · ${r}°
`}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,r=(i+n)/2;if("line"===t.kind){const e=Os(t.a,t.b);return{x:o,y:r,on45:Ns(e),text:`${this._fmtLen(t.a,t.b)} · ${Math.round(10*e)/10}°`}}const a=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]),a=this._fmtLen([0,0],[0,Math.abs(n-i)/2]);return{x:o,y:r,on45:!1,text:Math.abs(Math.abs(s-e)-Math.abs(n-i))<1e-6?`R ${t}`:`Rx ${t} × Ry ${a}`}}return{x:o,y:r,on45:!1,text:`${a} × ${l} · ${Ir(ha(Math.abs(s-e),this._cellCm,this._gridPitch)*ha(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=pm,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,r,a]="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` +
`}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=um,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` `})} - `}_renderOpeningCenterTick(t){const e=(t.angle+90)*Math.PI/180,i=cc(15,this._cellCm);return j``})} + `}_renderOpeningCenterTick(t){const e=(t.angle+90)*Math.PI/180,i=hc(15,this._cellCm);return j``}_renderOpeningDimensionGuides(t){const e=t.labels.flatMap(t=>t.dimension?[t.dimension]:[]);if(!e.length)return j``;const i=this._cssPxToRender(4);return j``}_roomCenter(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)]}_openingAmt(t){const e=t.contact&&this._renderOpeningEntityAvailable(t.contact)?this._renderPlanHass.states[t.contact]?.state:null;return gi(t.type,e,!!t.invert)}_planEntityAvailable(t){return!!t&&(!ko(this._fullRegistryHass,t,wo(this._markers))&&"active"===this._bindingStatus("entity:"+t).kind)}_renderEntityAvailable(t){return!!t&&(!ko(this._renderPlanHass,t,wo(this._markers))&&(!!this._renderPlanHass.entities?.[t]&&!!this._renderPlanHass.states?.[t]))}_openingEntityAvailable(t){return function(t,e,i=An(t)){return!!e&&"active"===Bn(t,`entity:${e}`,i).kind}(this.hass,t,this._haRegistry)}_renderOpeningEntityAvailable(t){return e=this._renderPlanHass,!!(i=t)&&!!e?.states?.[i];var e,i}_renderOpeningPlacementPreview(){const t=this._openingPreview;if(!t)return j``;const e={type:t.type,length:t.renderedLength,angle:t.angle,amount:gi(t.type,null),flipH:t.flipH,flipV:t.flipV,base:"var(--hp-open)",tone:"var(--hp-open)",cellCm:this._cellCm,gridPitch:this._gridPitch,face:t.face},i="passage"===t.type?function(t,e){const i=Math.max(0,t.renderedLength)/2,s=Math.max(0,t.target.physicalHalfWidth),n=s+.18*Math.max(0,e),o=t=>({x1:t,y1:-n,x2:t,y2:n});return{rect:{x:-i,y:s?-s:0,width:2*i,height:2*s},boundaries:[o(-i),o(i)]}}(t,cc(this._gridPitch,this._cellCm)):null;return j``}_roomCenter(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)]}_openingAmt(t){const e=t.contact&&this._renderOpeningEntityAvailable(t.contact)?this._renderPlanHass.states[t.contact]?.state:null;return gi(t.type,e,!!t.invert)}_planEntityAvailable(t){return!!t&&(!ko(this._fullRegistryHass,t,wo(this._markers))&&"active"===this._bindingStatus("entity:"+t).kind)}_renderEntityAvailable(t){return!!t&&(!ko(this._renderPlanHass,t,wo(this._markers))&&(!!this._renderPlanHass.entities?.[t]&&!!this._renderPlanHass.states?.[t]))}_openingEntityAvailable(t){return function(t,e,i=An(t)){return!!e&&"active"===Bn(t,`entity:${e}`,i).kind}(this.hass,t,this._haRegistry)}_renderOpeningEntityAvailable(t){return e=this._renderPlanHass,!!(i=t)&&!!e?.states?.[i];var e,i}_renderOpeningPlacementPreview(){const t=this._openingPreview;if(!t)return j``;const e={type:t.type,length:t.renderedLength,angle:t.angle,amount:gi(t.type,null),flipH:t.flipH,flipV:t.flipV,base:"var(--hp-open)",tone:"var(--hp-open)",cellCm:this._cellCm,gridPitch:this._gridPitch,face:t.face},i="passage"===t.type?function(t,e){const i=Math.max(0,t.renderedLength)/2,s=Math.max(0,t.target.physicalHalfWidth),n=s+.18*Math.max(0,e),o=t=>({x1:t,y1:-n,x2:t,y2:n});return{rect:{x:-i,y:s?-s:0,width:2*i,height:2*s},boundaries:[o(-i),o(i)]}}(t,hc(this._gridPitch,this._cellCm)):null;return j` `}_renderOpenings(t){const e=this._openingsR;if(!e.length)return j``;const i=this._spaceModel();if(!i)return j``;const s=t.color,n=this._spaceWalls,o=this._openPairs().flatMap(t=>t.segs),r=this._openingWallIndexFor(i,o).value;return j`${e.map(t=>{if(t.orphanReason)return j``}_renderOpenings(t){const e=this._openingsR;if(!e.length)return j``;const i=this._spaceModel();if(!i)return j``;const s=t.color,n=this._spaceWalls,o=this._openPairs().flatMap(t=>t.segs),a=this._openingWallIndexFor(i,o).value;return j`${e.map(t=>{if(t.orphanReason)return j`{e.stopPropagation(),this._editOpening(t)}}> - + ! - `;const e=this._openingAmt(t),i=e>0&&!!t.contact&&this._renderOpeningEntityAvailable(t.contact)?"var(--hp-open)":s,o="gate"===t.type?!t.flip_v:t.flip_v,a=t.partitionHost||n.length||"gate"===t.type?this._openingFace(t,r,!!o):{ox:0,oy:0,cm:0,side:-1},l={type:t.type,length:t.rlen,angle:t.angle,amount:e,flipH:!!t.flip_h,flipV:!!t.flip_v,base:s,tone:i,cellCm:this._cellCm,gridPitch:this._gridPitch,face:a},{half:c,outlineHalf:h,hitHalf:d}=qp(l),p=cc(10,this._cellCm),u=cc(12,this._cellCm);return j``;const e=this._openingAmt(t),i=e>0&&!!t.contact&&this._renderOpeningEntityAvailable(t.contact)?"var(--hp-open)":s,o="gate"===t.type?!t.flip_v:t.flip_v,r=t.partitionHost||n.length||"gate"===t.type?this._openingFace(t,a,!!o):{ox:0,oy:0,cm:0,side:-1},l={type:t.type,length:t.rlen,angle:t.angle,amount:e,flipH:!!t.flip_h,flipV:!!t.flip_v,base:s,tone:i,cellCm:this._cellCm,gridPitch:this._gridPitch,face:r},{half:c,outlineHalf:h,hitHalf:d}=Wp(l),p=hc(10,this._cellCm),u=hc(12,this._cellCm);return j` - ${Wp(l)} + ${jp(l)} + rx="${hc(6,this._cellCm)}"> this._opClick(e,t)} @@ -6265,7 +6265,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8 @pointermove=${e=>this._opPointerMove(e,t)} @pointerup=${e=>this._opPointerUp(e,t)} @pointercancel=${e=>this._opPointerUp(e,t)}> - `})}`}_renderOpeningLocks(t){const e=this._openingsR.filter(t=>!t.orphanReason&&("door"===t.type||"gate"===t.type)&&t.lock&&this._renderOpeningEntityAvailable(t.lock));if(!e.length)return W``;const i=this._spaceModel();if(!i)return W``;const s=this._openPairs().flatMap(t=>t.segs),n=this._openingWallIndexFor(i,s).value;return W`${e.map(e=>{const i=this._renderPlanHass.states[e.lock]?.state,s="locked"===i,o=s||["unlocked","open","opening","unlocking","locking"].includes(String(i)),r=(e.angle+90)*Math.PI/180,a="gate"===e.type?this._openingFace(e,n,!e.flip_v):null,l=cc(16,this._cellCm),c=a?-l*a.side:l*(e.flip_v?-1:1),h=e.rx+Math.cos(r)*c,d=e.ry+Math.sin(r)*c,p=this._scenePoint([h,d]),u=(p[0]-t.x)/t.w*100,_=(p[1]-t.y)/t.h*100;return W`
`})}`}_renderOpeningLocks(t){const e=this._openingsR.filter(t=>!t.orphanReason&&("door"===t.type||"gate"===t.type)&&t.lock&&this._renderOpeningEntityAvailable(t.lock));if(!e.length)return W``;const i=this._spaceModel();if(!i)return W``;const s=this._openPairs().flatMap(t=>t.segs),n=this._openingWallIndexFor(i,s).value;return W`${e.map(e=>{const i=this._renderPlanHass.states[e.lock]?.state,s="locked"===i,o=s||["unlocked","open","opening","unlocking","locking"].includes(String(i)),a=(e.angle+90)*Math.PI/180,r="gate"===e.type?this._openingFace(e,n,!e.flip_v):null,l=hc(16,this._cellCm),c=r?-l*r.side:l*(e.flip_v?-1:1),h=e.rx+Math.cos(a)*c,d=e.ry+Math.sin(a)*c,p=this._scenePoint([h,d]),u=(p[0]-t.x)/t.w*100,_=(p[1]-t.y)/t.h*100;return W`
{t.stopPropagation(),"view"===this._mode&&(this._openingInfo=e)}}> -
`})}`}_lockAction(t,e){if(this._openingEntityAvailable(t)){if("unlock"===e){const e=this.hass?.states?.[t]?.attributes?.friendly_name||t;if(!confirm(this._t("confirm.unlock",{name:e})))return}this.hass?.callService?.("lock",e,{entity_id:t})}}_renderOpeningInfoCard(){const t=this._openingInfo,e="passage"!==t.type&&t.contact&&this._openingEntityAvailable(t.contact)?t.contact:null,i=("door"===t.type||"gate"===t.type)&&t.lock&&this._openingEntityAvailable(t.lock)?t.lock:null,s=e?this.hass.states[e]?.state:null,n=this._openingAmt(t),o=i?this.hass.states[i]?.state:null,r="door"===t.type?"opening.door":"gate"===t.type?"opening.gate":"passage"===t.type?"opening.passage":"opening.window",a="door"===t.type?"mdi:door":"gate"===t.type?"mdi:gate":"passage"===t.type?"mdi:arch":"mdi:window-closed-variant",l="gate"===t.type?n>0?"mdi:gate-open":"mdi:gate":n>0?"mdi:door-open":"mdi:door-closed",c=(t,e,i,s="")=>W`
${e}${i}
`;return W``})}`}_lockAction(t,e){if(this._openingEntityAvailable(t)){if("unlock"===e){const e=this.hass?.states?.[t]?.attributes?.friendly_name||t;if(!confirm(this._t("confirm.unlock",{name:e})))return}this.hass?.callService?.("lock",e,{entity_id:t})}}_renderOpeningInfoCard(){const t=this._openingInfo,e="passage"!==t.type&&t.contact&&this._openingEntityAvailable(t.contact)?t.contact:null,i=("door"===t.type||"gate"===t.type)&&t.lock&&this._openingEntityAvailable(t.lock)?t.lock:null,s=e?this.hass.states[e]?.state:null,n=this._openingAmt(t),o=i?this.hass.states[i]?.state:null,a="door"===t.type?"opening.door":"gate"===t.type?"opening.gate":"passage"===t.type?"opening.passage":"opening.window",r="door"===t.type?"mdi:door":"gate"===t.type?"mdi:gate":"passage"===t.type?"mdi:arch":"mdi:window-closed-variant",l="gate"===t.type?n>0?"mdi:gate-open":"mdi:gate":n>0?"mdi:door-open":"mdi:door-closed",c=(t,e,i,s="")=>W`
${e}${i}
`;return W`this._openingInfo=null}>
${e?c(l,this._t("opening.contact_label"),"unavailable"===s||null==s?this._t("opening.state_unknown"):this._t(n>0?"opening.open":"opening.closed"),n>0?"warn":"ok"):G} @@ -6293,7 +6293,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8
-
`}_renderOpeningDialog(){const t=this._openingDialog,e=this._spaceModel()?.partitions||[],i=t.id?this._curSpaceCfg?.openings?.find(e=>e.id===t.id):null,s={id:t.id||"preview",type:t.type,x:t.x/pm,y:t.y/this._spaceH,angle:t.angle,length:i&&!t.lengthTouched?i.length:this._cmToUnits(Math.max(20,t.lengthCm))/pm,...t.host?{host:t.host}:{}},n=Id(i,s),o=t.host?n?Rd(s,e,pm,this._cellCm,this._gridPitch):Pd(s,e,pm,this._cellCm,this._gridPitch):null,r="does-not-fit-jamb"===o?.reason,a=t.host?e.find(e=>e.id===t.host.id):null,l=a?li(a.cm/2,this._imperial):"",c=!!t.host&&!o?.resolved&&!r,h="gate"===t.type?"mdi:gate":"window"===t.type?"mdi:window-closed-variant":"passage"===t.type?"mdi:arch":"mdi:door",d=(t,e,i)=>W`i(t.target.value)}> ${t.map(t=>W``)} `;return W` ${t.host?W` -
- ${c||r?W``:G} - ${c?this._t("opening.partition_orphan"):r?this._t("opening.partition_jamb_margin",{distance:l}):this._t("opening.host_partition")} +
+ ${c||a?W``:G} + ${c?this._t("opening.partition_orphan"):a?this._t("opening.partition_jamb_margin",{distance:l}):this._t("opening.host_partition")}
`:G} {const i=Zg(e.target.value);null!=i&&(this._openingDialog={...t,lengthCm:i,lengthTouched:!0})}} /> + @input=${e=>{const i=Qg(e.target.value);null!=i&&(this._openingDialog={...t,lengthCm:i,lengthTouched:!0})}} /> ${"passage"===t.type&&(t.contact||t.lock)?W`
@@ -6358,7 +6358,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8
-
`}_gridLevels(){const t=this._stageEl,e=this._viewOr(this._baseVb()),i=t&&t.clientWidth&&e.w?t.clientWidth/e.w:1;return function(t,e,i=7){if(!(t>0&&e>0&&Number.isFinite(e)))return null;const s=Bc.find(s=>t*s*e>=i);if(void 0===s)return null;const n=Bc.find(t=>t>=5*s)??5*s;return{fine:s,coarse:n}}(this._gridPitch,i)}_renderMarkupDefs(t){const e=this._gridLevels();if(!e)return j``;const i=this._gridPitch*e.fine,s=this._gridPitch*e.coarse,n=this._gridPitch*e.fine*.14;return j` +
`}_gridLevels(){const t=this._stageEl,e=this._viewOr(this._baseVb()),i=t&&t.clientWidth&&e.w?t.clientWidth/e.w:1;return function(t,e,i=7){if(!(t>0&&e>0&&Number.isFinite(e)))return null;const s=qc.find(s=>t*s*e>=i);if(void 0===s)return null;const n=qc.find(t=>t>=5*s)??5*s;return{fine:s,coarse:n}}(this._gridPitch,i)}_renderMarkupDefs(t){const e=this._gridLevels();if(!e)return j``;const i=this._gridPitch*e.fine,s=this._gridPitch*e.coarse,n=this._gridPitch*e.fine*.14;return j` @@ -6372,42 +6372,42 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8 - `}_renderPhysicalEditorLayer(){const t=this._spaceModel();if(!t)return j``;const e=this._gridPitch,i=this._viewOr(this._baseVb()),s=this._stageEl,n=s?.clientWidth?i.w/s.clientWidth:e/8,o=Math.max(.22*e,8*n),r=Math.max(o,12*n),a=t=>`M ${t.map(t=>`${t[0]} ${t[1]}`).join(" L ")} Z`,l=(t,e)=>this._physicalSel?.kind===t&&this._physicalSel.id===e||"column"===t&&this._duplicateColumnId===e,c=(t.room_drafts||[]).flatMap(t=>t.points.slice(0,-1).map((e,i)=>{const s=t.points[i+1],o=xa(t.segments[i]?.cm||15,this._cellCm,this._gridPitch);return j``}_renderPhysicalEditorLayer(){const t=this._spaceModel();if(!t)return j``;const e=this._gridPitch,i=this._viewOr(this._baseVb()),s=this._stageEl,n=s?.clientWidth?i.w/s.clientWidth:e/8,o=Math.max(.22*e,8*n),a=Math.max(o,12*n),r=t=>`M ${t.map(t=>`${t[0]} ${t[1]}`).join(" L ")} Z`,l=(t,e)=>this._physicalSel?.kind===t&&this._physicalSel.id===e||"column"===t&&this._duplicateColumnId===e,c=(t.room_drafts||[]).flatMap(t=>t.points.slice(0,-1).map((e,i)=>{const s=t.points[i+1],o=xr(t.segments[i]?.cm||15,this._cellCm,this._gridPitch);return j`{this._physicalSel={kind:"draft",id:t.id,segment:i},this._registerPhysicalTap("draft",t.id,i)}}>`})),h=(t.partitions||[]).map(t=>{const e=Vl(t.a,t.b,t.cm,this._cellCm,this._gridPitch);return e?j`{this._physicalSel={kind:"draft",id:t.id,segment:i},this._registerPhysicalTap("draft",t.id,i)}}>`})),h=(t.partitions||[]).map(t=>{const e=Kl(t.a,t.b,t.cm,this._cellCm,this._gridPitch);return e?j`this._physicalDown(e,"partition",t.id)} @pointermove=${t=>this._physicalMove(t)} - @pointerup=${t=>this._physicalUp(t)}>`:G}),d=(t.wall_columns||[]).map(t=>{const e=Kl(this._physicalRotate?.id===t.id?{...t,angle:this._physicalRotate.angle}:t,this._cellCm,this._gridPitch);return j`this._physicalUp(t)}>`:G}),d=(t.wall_columns||[]).map(t=>{const e=Yl(this._physicalRotate?.id===t.id?{...t,angle:this._physicalRotate.angle}:t,this._cellCm,this._gridPitch);return j`this._physicalDown(e,"column",t.id)} @pointermove=${t=>this._physicalMove(t)} - @pointerup=${t=>this._physicalUp(t)}>`}),p=this._physicalDrag,u=(()=>{if(!p?.moved)return G;const t="partition"===p.kind?Vl(p.base.a,p.base.b,p.base.cm,this._cellCm,this._gridPitch):Kl(p.base,this._cellCm,this._gridPitch);return t?j`this._physicalUp(t)}>`}),p=this._physicalDrag,u=(()=>{if(!p?.moved)return G;const t="partition"===p.kind?Kl(p.base.a,p.base.b,p.base.cm,this._cellCm,this._gridPitch):Yl(p.base,this._cellCm,this._gridPitch);return t?j``:G})(),_=(()=>{const i=this._physicalSel;if(!i)return G;if("draft"===i.kind){const e=t.room_drafts.find(t=>t.id===i.id);return e?j` t.join(",")).join(" ")}> ${e.points.map(t=>j``)} - `:G}if("partition"===i.kind){const e=t.partitions.find(t=>t.id===i.id);if(!e)return G;const s=Vl(e.a,e.b,e.cm,this._cellCm,this._gridPitch);if(!s)return G;const n=(e.a[0]+e.b[0])/2,r=(e.a[1]+e.b[1])/2;return j` - + `:G}if("partition"===i.kind){const e=t.partitions.find(t=>t.id===i.id);if(!e)return G;const s=Kl(e.a,e.b,e.cm,this._cellCm,this._gridPitch);if(!s)return G;const n=(e.a[0]+e.b[0])/2,a=(e.a[1]+e.b[1])/2;return j` + - - `}const s=t.wall_columns.find(t=>t.id===i.id);if(!s)return G;const l=this._physicalRotate?.id===s.id?{...s,angle:this._physicalRotate.angle}:s,c=Kl(l,this._cellCm,this._gridPitch);if("square"!==l.shape)return j` - + + `}const s=t.wall_columns.find(t=>t.id===i.id);if(!s)return G;const l=this._physicalRotate?.id===s.id?{...s,angle:this._physicalRotate.angle}:s,c=Yl(l,this._cellCm,this._gridPitch);if("square"!==l.shape)return j` + - `;const h=xa(l.cm,this._cellCm,this._gridPitch),d=ql(l.angle)*Math.PI/180,p=Math.sin(d),u=-Math.cos(d),_=[l.center[0]+p*h/2,l.center[1]+u*h/2],g=[_[0]+p*Math.max(e,24*n),_[1]+u*Math.max(e,24*n)];return j` - + `;const h=xr(l.cm,this._cellCm,this._gridPitch),d=Wl(l.angle)*Math.PI/180,p=Math.sin(d),u=-Math.cos(d),_=[l.center[0]+p*h/2,l.center[1]+u*h/2],g=[_[0]+p*Math.max(e,24*n),_[1]+u*Math.max(e,24*n)];return j` + - this._physicalRotateDown(t,s)} @pointermove=${t=>this._physicalRotateMove(t)} @pointerup=${t=>this._physicalRotateUp(t)}> - `})();return j`${c}${h}${d}${u}${_}`}_renderPlanSnapOverlay(){if(!this._markup||"draw"!==this._tool)return j``;const t=this._planSnapGeometrySnapshot().value,e=this._activePlanSnapCandidate,i=new Set(this._activePlanSnapConflicts.map(t=>t.key)),s=xa(5,this._cellCm,this._gridPitch),n=xa(10,this._cellCm,this._gridPitch);return j``})();return j`${c}${h}${d}${u}${_}`}_renderPlanSnapOverlay(){if(!this._markup||"draw"!==this._tool)return j``;const t=this._planSnapGeometrySnapshot().value,e=this._activePlanSnapCandidate,i=new Set(this._activePlanSnapConflicts.map(t=>t.key)),s=xr(5,this._cellCm,this._gridPitch),n=xr(10,this._cellCm,this._gridPitch);return j``}_syncPlanSnapActiveMarker(t){const e=this.renderRoot?.querySelector('[data-hp="plan-snap-active-marker"]');if(e){if(e.setAttribute("class",`plan-snap-node${t?" active":""}${"line"===t?.kind?" dynamic":""}`),e.setAttribute("data-active",t?"true":"false"),e.setAttribute("visibility",t?"visible":"hidden"),!t)return e.removeAttribute("data-kind"),void e.removeAttribute("data-key");e.setAttribute("data-kind",t.kind),e.setAttribute("data-key",t.key),e.setAttribute("cx",String(t.point[0])),e.setAttribute("cy",String(t.point[1])),e.setAttribute("r",String(xa(10,this._cellCm,this._gridPitch)))}}_syncPlanSnapConflictMarkers(t){const e=new Set(t.map(t=>t.key));for(const t of this.renderRoot?.querySelectorAll('.plan-snap-node[data-kind="endpoint"]')||[])t.setAttribute("class","plan-snap-node"+(e.has(t.dataset.key||"")?" conflict":""))}_planSnapPhysicalSegment(t){let e=0;const i=this._spaceModel();if(!i)return null;if("partition"===t.sourceKind)e=Number(i.partitions.find(e=>e.id===t.sourceId)?.cm)||0;else if("draft"===t.sourceKind){const s=/^(.*):(\d+)$/.exec(t.sourceId),n=s?i.room_drafts.find(t=>t.id===s[1]):null;e=n&&s&&Number(n.segments[Number(s[2])]?.cm)||0}else e=_l(i.rooms,this._spaceWalls,this._openCuts(),[t.a[0],t.a[1],t.b[0],t.b[1]],this._wallKeyPitch,this._cellCm,this._gridPitch,pm);return e>0?{a:[...t.a],b:[...t.b],halfDepth:xa(e,this._cellCm,this._gridPitch)/2}:null}_drawPreviewJoinPatchD(t,e){if(t.length<2)return"";const i=[];for(let s=0;s+10&&i.push({a:t[s],b:t[s+1],halfDepth:e[s]});if(!i.length)return"";const s=2e-4*this._gridPitch,n=this._planSnapGeometrySnapshot().value.segments.filter(e=>t.some(t=>Hs(t,[e.a[0],e.a[1],e.b[0],e.b[1]])<=s)).map(t=>this._planSnapPhysicalSegment(t)).filter(t=>!!t);return Ua([...i,...n],s).map(t=>`M ${t.map(t=>`${t[0]} ${t[1]}`).join(" L ")} Z`).join(" ")}_renderMarkupLayer(t){const e=this._openPairs().flatMap(t=>t.segs),i=this._thickWallCuts(),s=e.concat(i),n=s.length?Ds(this._segments,s,.02*this._gridPitch):this._segments,o=this._path,r=this._gridPitch,a=this._viewOr(this._baseVb()),l="draw"===this._tool?this._drawWallCm:null,c=(()=>"draw"===this._tool&&o.length&&null!=l&&l>0?this._contourClosed?o:this._cursorPt?[...o,this._cursorPt]:o.length>=2?o:null:null)(),h=c?Qd(c.length-1,this._contourClosed?[...this._draftSegmentCms,this._closingWallCm??void 0]:this._draftSegmentCms,l,fa).map(t=>xa(t,this._cellCm,this._gridPitch)/2):[],d=c?Ga(c,xa(l,this._cellCm,this._gridPitch)/2,this._contourClosed,h):"",p=c?this._drawPreviewJoinPatchD(c,h):"",u=this._wallFaceBatch?.candidates[this._wallFaceBatch.index]?.repair||this._wallRepairDiagnostic;return j` - ${this._gridLevels()?j``:G} + `}_syncPlanSnapActiveMarker(t){const e=this.renderRoot?.querySelector('[data-hp="plan-snap-active-marker"]');if(e){if(e.setAttribute("class",`plan-snap-node${t?" active":""}${"line"===t?.kind?" dynamic":""}`),e.setAttribute("data-active",t?"true":"false"),e.setAttribute("visibility",t?"visible":"hidden"),!t)return e.removeAttribute("data-kind"),void e.removeAttribute("data-key");e.setAttribute("data-kind",t.kind),e.setAttribute("data-key",t.key),e.setAttribute("cx",String(t.point[0])),e.setAttribute("cy",String(t.point[1])),e.setAttribute("r",String(xr(10,this._cellCm,this._gridPitch)))}}_syncPlanSnapConflictMarkers(t){const e=new Set(t.map(t=>t.key));for(const t of this.renderRoot?.querySelectorAll('.plan-snap-node[data-kind="endpoint"]')||[])t.setAttribute("class","plan-snap-node"+(e.has(t.dataset.key||"")?" conflict":""))}_planSnapPhysicalSegment(t){let e=0;const i=this._spaceModel();if(!i)return null;if("partition"===t.sourceKind)e=Number(i.partitions.find(e=>e.id===t.sourceId)?.cm)||0;else if("draft"===t.sourceKind){const s=/^(.*):(\d+)$/.exec(t.sourceId),n=s?i.room_drafts.find(t=>t.id===s[1]):null;e=n&&s&&Number(n.segments[Number(s[2])]?.cm)||0}else e=_l(i.rooms,this._spaceWalls,this._openCuts(),[t.a[0],t.a[1],t.b[0],t.b[1]],this._wallKeyPitch,this._cellCm,this._gridPitch,um);return e>0?{a:[...t.a],b:[...t.b],halfDepth:xr(e,this._cellCm,this._gridPitch)/2}:null}_drawPreviewJoinPatchD(t,e){if(t.length<2)return"";const i=[];for(let s=0;s+10&&i.push({a:t[s],b:t[s+1],halfDepth:e[s]});if(!i.length)return"";const s=2e-4*this._gridPitch,n=this._planSnapGeometrySnapshot().value.segments.filter(e=>t.some(t=>Hs(t,[e.a[0],e.a[1],e.b[0],e.b[1]])<=s)).map(t=>this._planSnapPhysicalSegment(t)).filter(t=>!!t);return Ur([...i,...n],s).map(t=>`M ${t.map(t=>`${t[0]} ${t[1]}`).join(" L ")} Z`).join(" ")}_renderMarkupLayer(t){const e=this._openPairs().flatMap(t=>t.segs),i=this._thickWallCuts(),s=e.concat(i),n=s.length?Ds(this._segments,s,.02*this._gridPitch):this._segments,o=this._path,a=this._gridPitch,r=this._viewOr(this._baseVb()),l="draw"===this._tool?this._drawWallCm:null,c=(()=>"draw"===this._tool&&o.length&&null!=l&&l>0?this._contourClosed?o:this._cursorPt?[...o,this._cursorPt]:o.length>=2?o:null:null)(),h=c?tp(c.length-1,this._contourClosed?[...this._draftSegmentCms,this._closingWallCm??void 0]:this._draftSegmentCms,l,fr).map(t=>xr(t,this._cellCm,this._gridPitch)/2):[],d=c?Gr(c,xr(l,this._cellCm,this._gridPitch)/2,this._contourClosed,h):"",p=c?this._drawPreviewJoinPatchD(c,h):"",u=this._wallFaceBatch?.candidates[this._wallFaceBatch.index]?.repair||this._wallRepairDiagnostic;return j` + ${this._gridLevels()?j``:G} ${n.map(t=>j``)} ${this._renderPhysicalEditorLayer()} - ${"column"===this._tool&&this._cursorPt&&this._drawWallCm?j``M ${Kl({shape:"square",center:this._cursorPt,cm:this._drawWallCm},this._cellCm,this._gridPitch).map(t=>`${t[0]} ${t[1]}`).join(" L ")} Z`)()}>`:G} + ${"column"===this._tool&&this._cursorPt&&this._drawWallCm?j``M ${Yl({shape:"square",center:this._cursorPt,cm:this._drawWallCm},this._cellCm,this._gridPitch).map(t=>`${t[0]} ${t[1]}`).join(" L ")} Z`)()}>`:G} ${d?j` `:G} ${p?j` @@ -6444,12 +6444,12 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8 ${o.length&&this._cursorPt&&"draw"===this._tool&&!this._contourClosed?j` ${this._activePlanSnapCandidate||this._activePlanSnapConflicts.length?G:j``}`:G} + r="${hc(.22*a,this._cellCm)}" aria-hidden="true">`}`:G} ${o.map((t,e)=>j``)} + cx="${t[0]}" cy="${t[1]}" r="${hc(.22*a,this._cellCm)}">`)} ${"split"===this._tool&&this._splitSel?.pts?.length?j`${this._splitSel.pts.length>1?j``:G} ${this._splitSel.pts.map((t,e)=>j``)} + cx="${t[0]}" cy="${t[1]}" r="${hc(.22*a,this._cellCm)}">`)} ${this._cursorPt?j``:G}`:G} `}_renderPartitionDeleteDialog(){const t=this._partitionDeleteDialog,e="mi"===this.hass?.config?.unit_system?.length;return W`

${this._t("confirm.delete_partition_openings_body",{count:t.openings.length})}

    - ${t.openings.map(t=>W`
  • ${this._t("confirm.delete_partition_openings_item",{type:this._t(`opening.${t.type}`),length:li(t.length*pm/this._gridPitch*this._cellCm,e)})}
  • `)} + ${t.openings.map(t=>W`
  • ${this._t("confirm.delete_partition_openings_item",{type:this._t(`opening.${t.type}`),length:li(t.length*um/this._gridPitch*this._cellCm,e)})}
  • `)}
@@ -6502,8 +6502,8 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8 `:G}
this._physicalDialog={...t,cm:e.target.value}} /> ${this._t(this._imperial?"wallthick.unit_in":"wallthick.unit_cm")}
${e&&"square"===t.shape?W` @@ -6663,7 +6663,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8 `:G}
- `}_markerValueBadgeFields(t){return(e={touched:t.valueBadgeTouched,originalHas:t.originalHasValueBadge,original:t.originalValueBadge,enabled:t.valueBadgeEnabled,source:t.valueBadgeSource,position:t.valueBadgePosition}).touched?{value_badge:{enabled:e.enabled,source:e.source,position:e.position}}:e.originalHas?{value_badge:e.original}:{};var e}_markerDraft(t){if("ha"===t.bindingMode&&(!t.binding||"virtual"===t.binding))return null;const e=qs(t.room),i=Ei(t.binding,t.devId,()=>"__hp_device_preview__"),s=this._markers.find(e=>e.id===i||e.id===t.devId),n=Zn(t.binding,t.controls,this._bindingEntities(t.binding)),o=this._effectiveStoredTapAction(t),r={id:i,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||null,...this._markerTapActionFields(t),...this._markerToggleEntityFields(t),tap_target:"run"===o&&t.tapTarget||null,tap_confirm:!!t.tapConfirm||null,controls:n.length?n:null,...this._markerLightFields(t),...this._markerValueBadgeFields(t),use_climate_temp:!!t.useClimateTemp||null,glow_radius_cm:(()=>{const e=Zg(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,vacuum:s?.vacuum||null};return("virtual"===t.binding||t.room)&&(r.space=e?.space||("virtual"===t.binding?this._space:null),r.area=e?.area||null,r.room_id=e?.roomId||null),r}_markerPreviewDevice(t){const e=this._markerDraft(t);if(!e)return null;const i=`${this._haRegistry.revision}\n${JSON.stringify(e)}`;if(this._markerPreviewMemo?.key===i)return this._markerPreviewMemo.device;const s=function(t){const{marker:e,...i}=t;return So({...i,markers:[e]}).find(t=>t.id===e.id)||null}({hass:this.hass,registry:this._haRegistry,areaToSpace:Object.fromEntries(Object.entries(this._areaToSpace).map(([t,e])=>[t,e.space])),marker:e,settings:this._settings,excluded:this._excluded,showAll:this._showAll,firstSpaceId:this._model[0]?.id||this._space,loc:t=>this._t(t),iconRules:this._iconRules});return this._markerPreviewMemo={key:i,device:s},s}_markerPreviewDevices(t){const e=this._markerPreviewDevicesMemo;if(e?.base===this._devices&&e.preview===t)return e.devices;const i=[...this._devices.filter(e=>e.id!==t.id),t];return this._markerPreviewDevicesMemo={base:this._devices,preview:t,devices:i},i}_toggleIntent(t,e=this._devices){return xd({hass:this._planHass,registryHass:this._fullRegistryHass,devices:e,device:t,virtualLights:this._virtualLights})}_toggleIntentForDialog(t){const e=this._markerPreviewDevice(t);if(!e)return null;const i=this._markerPreviewDevices(e);return this._toggleIntent(e,i)}_toggleStateText(t,e){const i=this._planHass?.states?.[t]||this.hass?.states?.[t];try{return i&&"function"==typeof this.hass?.formatEntityState?this.hass.formatEntityState(i):e}catch{return e}}_toggleConfirmationStateText(t){const e=String(t.state||"unknown"),i=t.entityId?this._toggleStateText(t.entityId,e):e;if(i.trim().toLocaleLowerCase()!==e.trim().toLocaleLowerCase())return i;const s={on:"confirm.state_on",off:"confirm.state_off",open:"confirm.state_open",closed:"confirm.state_closed",opening:"confirm.state_opening",closing:"confirm.state_closing",unknown:"confirm.state_unknown"}[e];return s?this._t(s):e.replaceAll("_"," ").replaceAll("-"," ")}_toggleConfirmationLines(t){const e={"turn-on":"confirm.state_on","turn-off":"confirm.state_off",open:"confirm.state_open",close:"confirm.state_closed",stop:"confirm.state_stopped"};return function(t,e){if(!Sd(t)||!t.nextEffect||!t.targets.length)return[];const i="group"===t.kind,s=i?t.targets.filter(t=>"on"===t.state).length:0,n=i?0===s?e.groupAllOff():e.groupCurrent(s,t.targets.length):e.state(t.targets[0]);let o;return o="toggle"===t.nextEffect?e.expectedByHa():i&&"turn-on"===t.nextEffect?e.groupAllOn():i&&"turn-off"===t.nextEffect?e.groupAllOff():e.effect(t.nextEffect),[e.current(n),e.expected(o),...t.skippedTargets.length?[e.unavailable(t.skippedTargets.length)]:[]]}(t,{state:t=>this._toggleConfirmationStateText(t),current:t=>this._t("confirm.current_state",{state:t}),expected:t=>this._t("confirm.expected_state",{state:t}),groupCurrent:(t,e)=>this._t("confirm.group_current",{on:t,total:e}),groupAllOn:()=>this._t("confirm.group_all_on"),groupAllOff:()=>this._t("confirm.group_all_off"),unavailable:t=>this._t("confirm.unavailable_targets",{count:t}),effect:t=>this._t(e[t]),expectedByHa:()=>this._t("confirm.expected_by_ha")})}_toggleHintLines(t){if(!t)return[];const e=t=>this._t(`marker.toggle_effect_${t.replace("-","_")}`),i=t=>this._t(`marker.toggle_skip_${t.replace("-","_")}`);return function(t,e){const i=t.targets[0]||t.skippedTargets[0],s=[];return"group"===t.kind?t.targets.length&&s.push(e.group(t.targets)):i&&s.push(e.single(i)),t.nextEffect&&t.targets.length&&s.push("group"===t.kind?e.groupCurrentNext(t.targets,t.nextEffect):e.currentNext(t.targets[0],t.nextEffect)),t.skippedTargets.length&&s.push(e.skipped(t.skippedTargets)),!t.command&&t.noneReason&&s.push(e.none(t.noneReason)),s}(t,{single:t=>{if("via"in t&&"virtual-light"===t.via)return this._t("marker.virtual_light_target",{name:t.name});const e=t.entityId||("ref"in t?t.ref:""),i=t.name||e;return this._t("marker.toggle_hint_single",{name:i,id:e})},group:t=>this._t("marker.toggle_hint_group",{count:t.length,names:t.map(t=>`${t.name} (${t.entityId})`).join(", ")}),currentNext:(t,i)=>"virtual-light"===t.via?this._t("marker.virtual_light_current",{state:this._t("on"===t.state?"marker.virtual_light_state_on":"marker.virtual_light_state_off"),effect:e(i)}):this._t("marker.toggle_hint_current",{state:this._toggleStateText(t.entityId,t.state),effect:e(i)}),groupCurrentNext:(t,i)=>this._t("marker.toggle_hint_group_current",{on:t.filter(t=>"on"===t.state).length,count:t.length,effect:e(i)}),skipped:t=>this._t("marker.toggle_hint_skipped",{count:t.length,targets:t.map(t=>{const e=t.entityId||t.ref;return`${t.name||e} (${e}: ${i(t.reason)})`}).join(", ")}),none:t=>this._t(`marker.toggle_none_${t.replaceAll("-","_")}`)})}_effectiveStoredTapAction(t,e){return t.tapActionTouched?t.tapAction:yd(t.originalHasTapAction?t.originalTapAction:null,e)}_effectiveMarkerTapAction(t,e=this._markerPreviewDevice(t)){return this._effectiveStoredTapAction(t,e?.primary?.split(".")[0])}_announceToggleDraft(t){const e=this._markerPreviewDevice(t),i=t.tapActionTouched?t:{...t,tapAction:this._effectiveMarkerTapAction(t,e)},s="toggle"===i.tapAction?this._toggleHintLines(this._toggleIntentForDialog(i)).join(" "):"";return{...i,tapHintAnnouncement:s}}_valueBadgeForBinding(t,e){const i={...t,binding:e,valueBadgeEnabled:!1,valueBadgeSource:null,valueBadgeTouched:!0},s=this._markerPreviewDevice(i);if(!s)return{valueBadgeEnabled:!1,valueBadgeSource:null,valueBadgeTouched:!0};const n=[...this._devices.filter(t=>t.id!==s.id),s],o=Wo(this._planHass,s,n),r=jo(this._planHass,s,o);return{valueBadgeEnabled:t.valueBadgeEnabled&&!!r,valueBadgeSource:r,valueBadgeTouched:!0}}_markerSpatialSource(t){const e=this._markerPreviewDevice(t);if(!e)return null;const i={...e,hidden:!1};return po(ho(this._planHass,[...this._devices.filter(t=>t.id!==i.id),i],null,this._virtualLights).filter(t=>t.device.id===i.id))}_markerAutoHasSpatialSource(t){const e={...t,lightRole:"auto",lightRoleTouched:!0},i=this._markerPreviewDevice(e);return!!i&&lo(this._planHass,{...i})}_setMarkerLightRole(t){const e=this._markerDialog;e&&(this._markerDialog={...e,lightRole:t,lightRoleTouched:!0})}_controlRefInfo(t){if(!t.startsWith("marker:"))return{label:this.hass.states[t]?.attributes?.friendly_name||t,sub:t,icon:t.startsWith("light.")?"mdi:lightbulb":"mdi:toggle-switch",warning:!this._planEntityAvailable(t)};const e=t.slice(7),i=this._markers.find(t=>t.id===e),s=this._devices.find(t=>t.id===e);if(!i||i.removed||!0!==i.is_light)return{label:this._t("marker.control_missing_label"),sub:`${this._t("marker.control_broken")} (${t})`,icon:"mdi:alert-outline",warning:!0};const n=this._serverCfg?.spaces.find(t=>t.id===(s?.space||i.space)),o=!!s&&to(s).length>0;return{label:i.name||s?.name||e,sub:[n?.title||s?.space||i.space,i.room_id||s?.area,o?"":this._t("marker.control_passive")].filter(Boolean).join(" · "),icon:i.icon||s?.icon||"mdi:lightbulb-outline",warning:!0===i.hidden||!0===s?.hidden}}_valueBadgeCandidateLabel(t){const e=t.source;if("derived_lqi"===e.kind)return this._t("marker.value_badge_lqi");if("derived_marker_state"===e.kind)return this._t("marker.value_badge_marker_state",{name:t.label});if("entity_state"===e.kind)return this._t("marker.value_badge_state",{name:t.label});const i=this.hass.states[e.entity_id]?.attributes?.friendly_name||this._fullRegistryHass.entities[e.entity_id]?.name||e.entity_id;return this._t(`marker.value_badge_attr_${e.attribute}`,{name:i})}_controlCandidates(t){const e=this._markerDraft(t)?.id||t.devId||"",i=[],s=new Set;for(const t of this._markers){if(t.id===e||t.removed||t.hidden||!0!==t.is_light)continue;if("virtual"!==t.binding&&"active"!==this._bindingStatus(t.binding).kind)continue;const n=this._devices.find(e=>e.id===t.id);if(!n||n.hidden)continue;const o=this._controlRefInfo(`marker:${t.id}`);for(const t of to(n))s.add(t);i.push({value:`marker:${t.id}`,label:o.label,sub:o.sub,icon:o.icon,search:`${o.label} ${o.sub} ${t.id} ${to(n).join(" ")}`.toLowerCase()})}const n=Object.keys(this.hass.states||{}).filter(e=>Ms(e)&&!s.has(e)&&Jn(t.binding,[e],this._bindingEntities(t.binding)).length>0&&this._planEntityAvailable(e)).map(t=>{const e=this._controlRefInfo(t);return{value:t,label:e.label,sub:t,icon:e.icon,search:`${e.label} ${t}`.toLowerCase()}}),o=t.controlsFilter.trim().toLowerCase();return[...i,...n].filter(e=>!t.controls.includes(e.value)&&(!o||e.search.includes(o))).slice(0,12).map(({search:t,...e})=>e)}_addControlRef(t,e){if(e.startsWith("marker:")){const i=this._markerDraft(t)?.id||t.devId||"";if(!i)return void this._showToast(this._t("toast.marker_binding_required"));const s=e.slice(7),n=this._markerDraft(t);if(function(t,e,i){if(!e||e===i)return!0;const s=new Map;for(const e of t)s.set(e.id,(e.controls||[]).filter(t=>"string"==typeof t&&t.startsWith("marker:")).map(t=>t.slice(7)));const n=new Set,o=[i];for(;o.length;){const t=o.pop();if(t===e)return!0;n.has(t)||(n.add(t),o.push(...s.get(t)||[]))}return!1}(n?[...this._markers.filter(t=>t.id!==i),n]:this._markers,i,s))return void this._showToast(this._t("toast.marker_control_cycle"))}this._markerDialog=this._announceToggleDraft({...t,controls:[...t.controls,e],controlsFilter:""})}_setMarkerGlowMode(t){const e=this._markerDialog;if(!e)return;if("auto"===t)return void(this._markerDialog={...e,glowMode:t,glowTouched:!0});const i=this._markerSpatialSource(e),s=xs(i?this._planHass.states[i.eid]:void 0,null,this._fillColors.glow_light.c),n=!e.glowColorDrafted,o="fixed"===t&&!e.glowBrightnessDrafted;this._markerDialog={...e,glowMode:t,glowColor:n?s.c:e.glowColor,glowBrightness:o?Math.max(1,Math.round(100*s.bri)):e.glowBrightness,glowColorDrafted:!0,glowBrightnessDrafted:e.glowBrightnessDrafted||"fixed"===t,glowTouched:!0}}_renderMarkerDialog(){const t=this._markerDialog,e="virtual"===t.bindingMode,i=this._bindingCandidates();this._bindingEntities(t.binding);const s=e?null:this._bindingStatus(t.binding),n=!e&&this._bindingHasHaPage(t.binding),o=this._markerPreviewDevice(t),r=this._effectiveMarkerTapAction(t,o),a=o?cs(this._serverCfg?.spaces.find(t=>t.id===o.space)):null,l=o?this._markerPreviewDevices(o):this._devices,c="toggle"===r&&o?this._toggleIntent(o,l):null,h=this._toggleHintLines(c),d=o?iu(this._planHass,o,{liveStates:!1!==this._config?.live_states,showTemperature:!1!==this._config?.show_temperature,showSignal:a?.showLqi??!1!==this._config?.show_signal,designPreview:!0,activityRuntime:this._activityRt.get(o.id),lightDevices:l,registryHass:this._fullRegistryHass,reducedMotion:this._reducedMotion}):null,p=o?Wo(this._planHass,o,l):[],u=o?jo(this._planHass,o,p):null,_=t.valueBadgeTouched?t.valueBadgeEnabled:!!d?.valueBadge,g=t.valueBadgeTouched?t.valueBadgeSource:d?.valueBadge?.source||t.valueBadgeSource,m=t.valueBadgeTouched?t.valueBadgePosition:d?.valueBadge?.position||t.valueBadgePosition,f=Ao(g),v=!!g&&!p.some(t=>t.key===f),y=p.find(t=>t.key===f),b=d?.valueSource?d.valueSource.attribute?`attr:${d.valueSource.eid}:${d.valueSource.attribute}`:`state:${d.valueSource.eid}`:"",w=this._markerAutoHasSpatialSource(t),k=!!o&&function(t,e){return io(t,e).some(t=>!!t.eid)}(this._planHass,{...o}),x=function(t,e,i,s){const n="always"===t||"auto"===t&&e,o=n&&!i;return{sourceExists:n,fromSourceEnabled:n&&i,manualEnabled:n,radiusEnabled:n,passive:o,effectiveMode:o&&"auto"===s?"fixed":s}}(t.lightRole,w,k,t.glowMode),$=!x.sourceExists,S=!x.fromSourceEnabled,M=x.passive,C=x.effectiveMode,D="never"===t.lightRole?this._t("marker.glow_disabled_never"):"auto"!==t.lightRole||w?M?this._t("marker.glow_passive_hint"):this._t("marker.glow_disabled_no_entity"):this._t("marker.glow_disabled_auto"),T=o?to(o):[],P=o&&eo(o)||"",R=!!t.lightEntity&&!T.includes(t.lightEntity),I=o?_d(o):[],A=!!t.toggleEntity&&!I.includes(t.toggleEntity),F="toggle"===r?this._toggleIntentForDialog({...t,toggleEntity:"",toggleEntityTouched:!0}):null,E=F?[...F.targets,...F.skippedTargets].map(t=>t.entityId||("ref"in t?t.ref:"")).filter(Boolean).join(", "):"",z=(()=>{if(e)return null;const s=i.find(e=>e.value===t.binding);if(s)return s.label;const[n,o]=t.binding.split(":");return"device"===n?this._fullRegistryHass.devices[o]?.name_by_user||this._fullRegistryHass.devices[o]?.name||o:this._fullRegistryHass.entities[o]?.name||this.hass.states[o]?.attributes?.friendly_name||o})();return W``}_markerValueBadgeFields(t){return(e={touched:t.valueBadgeTouched,originalHas:t.originalHasValueBadge,original:t.originalValueBadge,enabled:t.valueBadgeEnabled,source:t.valueBadgeSource,position:t.valueBadgePosition}).touched?{value_badge:{enabled:e.enabled,source:e.source,position:e.position}}:e.originalHas?{value_badge:e.original}:{};var e}_markerDraft(t){if("ha"===t.bindingMode&&(!t.binding||"virtual"===t.binding))return null;const e=qs(t.room),i=Ei(t.binding,t.devId,()=>"__hp_device_preview__"),s=this._markers.find(e=>e.id===i||e.id===t.devId),n=Zn(t.binding,t.controls,this._bindingEntities(t.binding)),o=this._effectiveStoredTapAction(t),a={id:i,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||null,...this._markerTapActionFields(t),...this._markerToggleEntityFields(t),tap_target:"run"===o&&t.tapTarget||null,tap_confirm:!!t.tapConfirm||null,controls:n.length?n:null,...this._markerLightFields(t),...this._markerValueBadgeFields(t),use_climate_temp:!!t.useClimateTemp||null,glow_radius_cm:(()=>{const e=Qg(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,vacuum:s?.vacuum||null};return("virtual"===t.binding||t.room)&&(a.space=e?.space||("virtual"===t.binding?this._space:null),a.area=e?.area||null,a.room_id=e?.roomId||null),a}_markerPreviewDevice(t){const e=this._markerDraft(t);if(!e)return null;const i=`${this._haRegistry.revision}\n${JSON.stringify(e)}`;if(this._markerPreviewMemo?.key===i)return this._markerPreviewMemo.device;const s=function(t){const{marker:e,...i}=t;return So({...i,markers:[e]}).find(t=>t.id===e.id)||null}({hass:this.hass,registry:this._haRegistry,areaToSpace:Object.fromEntries(Object.entries(this._areaToSpace).map(([t,e])=>[t,e.space])),marker:e,settings:this._settings,excluded:this._excluded,showAll:this._showAll,firstSpaceId:this._model[0]?.id||this._space,loc:t=>this._t(t),iconRules:this._iconRules});return this._markerPreviewMemo={key:i,device:s},s}_markerPreviewDevices(t){const e=this._markerPreviewDevicesMemo;if(e?.base===this._devices&&e.preview===t)return e.devices;const i=[...this._devices.filter(e=>e.id!==t.id),t];return this._markerPreviewDevicesMemo={base:this._devices,preview:t,devices:i},i}_toggleIntent(t,e=this._devices){return $d({hass:this._planHass,registryHass:this._fullRegistryHass,devices:e,device:t,virtualLights:this._virtualLights})}_toggleIntentForDialog(t){const e=this._markerPreviewDevice(t);if(!e)return null;const i=this._markerPreviewDevices(e);return this._toggleIntent(e,i)}_toggleStateText(t,e){const i=this._planHass?.states?.[t]||this.hass?.states?.[t];try{return i&&"function"==typeof this.hass?.formatEntityState?this.hass.formatEntityState(i):e}catch{return e}}_toggleConfirmationStateText(t){const e=String(t.state||"unknown"),i=t.entityId?this._toggleStateText(t.entityId,e):e;if(i.trim().toLocaleLowerCase()!==e.trim().toLocaleLowerCase())return i;const s={on:"confirm.state_on",off:"confirm.state_off",open:"confirm.state_open",closed:"confirm.state_closed",opening:"confirm.state_opening",closing:"confirm.state_closing",unknown:"confirm.state_unknown"}[e];return s?this._t(s):e.replaceAll("_"," ").replaceAll("-"," ")}_toggleConfirmationLines(t){const e={"turn-on":"confirm.state_on","turn-off":"confirm.state_off",open:"confirm.state_open",close:"confirm.state_closed",stop:"confirm.state_stopped"};return function(t,e){if(!Md(t)||!t.nextEffect||!t.targets.length)return[];const i="group"===t.kind,s=i?t.targets.filter(t=>"on"===t.state).length:0,n=i?0===s?e.groupAllOff():e.groupCurrent(s,t.targets.length):e.state(t.targets[0]);let o;return o="toggle"===t.nextEffect?e.expectedByHa():i&&"turn-on"===t.nextEffect?e.groupAllOn():i&&"turn-off"===t.nextEffect?e.groupAllOff():e.effect(t.nextEffect),[e.current(n),e.expected(o),...t.skippedTargets.length?[e.unavailable(t.skippedTargets.length)]:[]]}(t,{state:t=>this._toggleConfirmationStateText(t),current:t=>this._t("confirm.current_state",{state:t}),expected:t=>this._t("confirm.expected_state",{state:t}),groupCurrent:(t,e)=>this._t("confirm.group_current",{on:t,total:e}),groupAllOn:()=>this._t("confirm.group_all_on"),groupAllOff:()=>this._t("confirm.group_all_off"),unavailable:t=>this._t("confirm.unavailable_targets",{count:t}),effect:t=>this._t(e[t]),expectedByHa:()=>this._t("confirm.expected_by_ha")})}_toggleHintLines(t){if(!t)return[];const e=t=>this._t(`marker.toggle_effect_${t.replace("-","_")}`),i=t=>this._t(`marker.toggle_skip_${t.replace("-","_")}`);return function(t,e){const i=t.targets[0]||t.skippedTargets[0],s=[];return"group"===t.kind?t.targets.length&&s.push(e.group(t.targets)):i&&s.push(e.single(i)),t.nextEffect&&t.targets.length&&s.push("group"===t.kind?e.groupCurrentNext(t.targets,t.nextEffect):e.currentNext(t.targets[0],t.nextEffect)),t.skippedTargets.length&&s.push(e.skipped(t.skippedTargets)),!t.command&&t.noneReason&&s.push(e.none(t.noneReason)),s}(t,{single:t=>{if("via"in t&&"virtual-light"===t.via)return this._t("marker.virtual_light_target",{name:t.name});const e=t.entityId||("ref"in t?t.ref:""),i=t.name||e;return this._t("marker.toggle_hint_single",{name:i,id:e})},group:t=>this._t("marker.toggle_hint_group",{count:t.length,names:t.map(t=>`${t.name} (${t.entityId})`).join(", ")}),currentNext:(t,i)=>"virtual-light"===t.via?this._t("marker.virtual_light_current",{state:this._t("on"===t.state?"marker.virtual_light_state_on":"marker.virtual_light_state_off"),effect:e(i)}):this._t("marker.toggle_hint_current",{state:this._toggleStateText(t.entityId,t.state),effect:e(i)}),groupCurrentNext:(t,i)=>this._t("marker.toggle_hint_group_current",{on:t.filter(t=>"on"===t.state).length,count:t.length,effect:e(i)}),skipped:t=>this._t("marker.toggle_hint_skipped",{count:t.length,targets:t.map(t=>{const e=t.entityId||t.ref;return`${t.name||e} (${e}: ${i(t.reason)})`}).join(", ")}),none:t=>this._t(`marker.toggle_none_${t.replaceAll("-","_")}`)})}_effectiveStoredTapAction(t,e){return t.tapActionTouched?t.tapAction:bd(t.originalHasTapAction?t.originalTapAction:null,e)}_effectiveMarkerTapAction(t,e=this._markerPreviewDevice(t)){return this._effectiveStoredTapAction(t,e?.primary?.split(".")[0])}_announceToggleDraft(t){const e=this._markerPreviewDevice(t),i=t.tapActionTouched?t:{...t,tapAction:this._effectiveMarkerTapAction(t,e)},s="toggle"===i.tapAction?this._toggleHintLines(this._toggleIntentForDialog(i)).join(" "):"";return{...i,tapHintAnnouncement:s}}_valueBadgeForBinding(t,e){const i={...t,binding:e,valueBadgeEnabled:!1,valueBadgeSource:null,valueBadgeTouched:!0},s=this._markerPreviewDevice(i);if(!s)return{valueBadgeEnabled:!1,valueBadgeSource:null,valueBadgeTouched:!0};const n=[...this._devices.filter(t=>t.id!==s.id),s],o=Wo(this._planHass,s,n),a=jo(this._planHass,s,o);return{valueBadgeEnabled:t.valueBadgeEnabled&&!!a,valueBadgeSource:a,valueBadgeTouched:!0}}_markerSpatialSource(t){const e=this._markerPreviewDevice(t);if(!e)return null;const i={...e,hidden:!1};return po(ho(this._planHass,[...this._devices.filter(t=>t.id!==i.id),i],null,this._virtualLights).filter(t=>t.device.id===i.id))}_markerAutoHasSpatialSource(t){const e={...t,lightRole:"auto",lightRoleTouched:!0},i=this._markerPreviewDevice(e);return!!i&&lo(this._planHass,{...i})}_setMarkerLightRole(t){const e=this._markerDialog;e&&(this._markerDialog={...e,lightRole:t,lightRoleTouched:!0})}_controlRefInfo(t){if(!t.startsWith("marker:"))return{label:this.hass.states[t]?.attributes?.friendly_name||t,sub:t,icon:t.startsWith("light.")?"mdi:lightbulb":"mdi:toggle-switch",warning:!this._planEntityAvailable(t)};const e=t.slice(7),i=this._markers.find(t=>t.id===e),s=this._devices.find(t=>t.id===e);if(!i||i.removed||!0!==i.is_light)return{label:this._t("marker.control_missing_label"),sub:`${this._t("marker.control_broken")} (${t})`,icon:"mdi:alert-outline",warning:!0};const n=this._serverCfg?.spaces.find(t=>t.id===(s?.space||i.space)),o=!!s&&to(s).length>0;return{label:i.name||s?.name||e,sub:[n?.title||s?.space||i.space,i.room_id||s?.area,o?"":this._t("marker.control_passive")].filter(Boolean).join(" · "),icon:i.icon||s?.icon||"mdi:lightbulb-outline",warning:!0===i.hidden||!0===s?.hidden}}_valueBadgeCandidateLabel(t){const e=t.source;if("derived_lqi"===e.kind)return this._t("marker.value_badge_lqi");if("derived_marker_state"===e.kind)return this._t("marker.value_badge_marker_state",{name:t.label});if("entity_state"===e.kind)return this._t("marker.value_badge_state",{name:t.label});const i=this.hass.states[e.entity_id]?.attributes?.friendly_name||this._fullRegistryHass.entities[e.entity_id]?.name||e.entity_id;return this._t(`marker.value_badge_attr_${e.attribute}`,{name:i})}_controlCandidates(t){const e=this._markerDraft(t)?.id||t.devId||"",i=[],s=new Set;for(const t of this._markers){if(t.id===e||t.removed||t.hidden||!0!==t.is_light)continue;if("virtual"!==t.binding&&"active"!==this._bindingStatus(t.binding).kind)continue;const n=this._devices.find(e=>e.id===t.id);if(!n||n.hidden)continue;const o=this._controlRefInfo(`marker:${t.id}`);for(const t of to(n))s.add(t);i.push({value:`marker:${t.id}`,label:o.label,sub:o.sub,icon:o.icon,search:`${o.label} ${o.sub} ${t.id} ${to(n).join(" ")}`.toLowerCase()})}const n=Object.keys(this.hass.states||{}).filter(e=>Ms(e)&&!s.has(e)&&Jn(t.binding,[e],this._bindingEntities(t.binding)).length>0&&this._planEntityAvailable(e)).map(t=>{const e=this._controlRefInfo(t);return{value:t,label:e.label,sub:t,icon:e.icon,search:`${e.label} ${t}`.toLowerCase()}}),o=t.controlsFilter.trim().toLowerCase();return[...i,...n].filter(e=>!t.controls.includes(e.value)&&(!o||e.search.includes(o))).slice(0,12).map(({search:t,...e})=>e)}_addControlRef(t,e){if(e.startsWith("marker:")){const i=this._markerDraft(t)?.id||t.devId||"";if(!i)return void this._showToast(this._t("toast.marker_binding_required"));const s=e.slice(7),n=this._markerDraft(t);if(function(t,e,i){if(!e||e===i)return!0;const s=new Map;for(const e of t)s.set(e.id,(e.controls||[]).filter(t=>"string"==typeof t&&t.startsWith("marker:")).map(t=>t.slice(7)));const n=new Set,o=[i];for(;o.length;){const t=o.pop();if(t===e)return!0;n.has(t)||(n.add(t),o.push(...s.get(t)||[]))}return!1}(n?[...this._markers.filter(t=>t.id!==i),n]:this._markers,i,s))return void this._showToast(this._t("toast.marker_control_cycle"))}this._markerDialog=this._announceToggleDraft({...t,controls:[...t.controls,e],controlsFilter:""})}_setMarkerGlowMode(t){const e=this._markerDialog;if(!e)return;if("auto"===t)return void(this._markerDialog={...e,glowMode:t,glowTouched:!0});const i=this._markerSpatialSource(e),s=xs(i?this._planHass.states[i.eid]:void 0,null,this._fillColors.glow_light.c),n=!e.glowColorDrafted,o="fixed"===t&&!e.glowBrightnessDrafted;this._markerDialog={...e,glowMode:t,glowColor:n?s.c:e.glowColor,glowBrightness:o?Math.max(1,Math.round(100*s.bri)):e.glowBrightness,glowColorDrafted:!0,glowBrightnessDrafted:e.glowBrightnessDrafted||"fixed"===t,glowTouched:!0}}_renderMarkerDialog(){const t=this._markerDialog,e="virtual"===t.bindingMode,i=this._bindingCandidates();this._bindingEntities(t.binding);const s=e?null:this._bindingStatus(t.binding),n=!e&&this._bindingHasHaPage(t.binding),o=this._markerPreviewDevice(t),a=this._effectiveMarkerTapAction(t,o),r=o?cs(this._serverCfg?.spaces.find(t=>t.id===o.space)):null,l=o?this._markerPreviewDevices(o):this._devices,c="toggle"===a&&o?this._toggleIntent(o,l):null,h=this._toggleHintLines(c),d=o?su(this._planHass,o,{liveStates:!1!==this._config?.live_states,showTemperature:!1!==this._config?.show_temperature,showSignal:r?.showLqi??!1!==this._config?.show_signal,designPreview:!0,activityRuntime:this._activityRt.get(o.id),lightDevices:l,registryHass:this._fullRegistryHass,reducedMotion:this._reducedMotion}):null,p=o?Wo(this._planHass,o,l):[],u=o?jo(this._planHass,o,p):null,_=t.valueBadgeTouched?t.valueBadgeEnabled:!!d?.valueBadge,g=t.valueBadgeTouched?t.valueBadgeSource:d?.valueBadge?.source||t.valueBadgeSource,m=t.valueBadgeTouched?t.valueBadgePosition:d?.valueBadge?.position||t.valueBadgePosition,f=Ao(g),v=!!g&&!p.some(t=>t.key===f),y=p.find(t=>t.key===f),b=d?.valueSource?d.valueSource.attribute?`attr:${d.valueSource.eid}:${d.valueSource.attribute}`:`state:${d.valueSource.eid}`:"",w=this._markerAutoHasSpatialSource(t),k=!!o&&function(t,e){return io(t,e).some(t=>!!t.eid)}(this._planHass,{...o}),x=function(t,e,i,s){const n="always"===t||"auto"===t&&e,o=n&&!i;return{sourceExists:n,fromSourceEnabled:n&&i,manualEnabled:n,radiusEnabled:n,passive:o,effectiveMode:o&&"auto"===s?"fixed":s}}(t.lightRole,w,k,t.glowMode),$=!x.sourceExists,S=!x.fromSourceEnabled,M=x.passive,C=x.effectiveMode,D="never"===t.lightRole?this._t("marker.glow_disabled_never"):"auto"!==t.lightRole||w?M?this._t("marker.glow_passive_hint"):this._t("marker.glow_disabled_no_entity"):this._t("marker.glow_disabled_auto"),T=o?to(o):[],P=o&&eo(o)||"",R=!!t.lightEntity&&!T.includes(t.lightEntity),I=o?gd(o):[],A=!!t.toggleEntity&&!I.includes(t.toggleEntity),F="toggle"===a?this._toggleIntentForDialog({...t,toggleEntity:"",toggleEntityTouched:!0}):null,E=F?[...F.targets,...F.skippedTargets].map(t=>t.entityId||("ref"in t?t.ref:"")).filter(Boolean).join(", "):"",z=(()=>{if(e)return null;const s=i.find(e=>e.value===t.binding);if(s)return s.label;const[n,o]=t.binding.split(":");return"device"===n?this._fullRegistryHass.devices[o]?.name_by_user||this._fullRegistryHass.devices[o]?.name||o:this._fullRegistryHass.entities[o]?.name||this.hass.states[o]?.attributes?.friendly_name||o})();return W`this._markerDialog=null}>
@@ -6732,13 +6732,13 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8 - ${"toggle"===r&&(I.length>1||A)?W`
+ ${"toggle"===a&&(I.length>1||A)?W`
${this._help("marker.toggle_entity.help")} @@ -6758,11 +6758,11 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8 ${this._t("marker.toggle_entity_missing",{entity:t.toggleEntity,fallback:E||this._t("marker.toggle_entity_none")})}

`:G}
`:G} - ${"toggle"===r?W`
+ ${"toggle"===a?W`
${h.map(t=>W`
${t}
`)}
${t.tapHintAnnouncement}
`:G} - ${"run"===r?(()=>{const e=t.runFilter.trim().toLowerCase(),i=this._runCandidates().filter(t=>!e||t.label.toLowerCase().includes(e)||t.value.includes(e)),s=t.tapTarget?this._runCandidates().find(e=>e.value===t.tapTarget):null;return W` + ${"run"===a?(()=>{const e=t.runFilter.trim().toLowerCase(),i=this._runCandidates().filter(t=>!e||t.label.toLowerCase().includes(e)||t.value.includes(e)),s=t.tapTarget?this._runCandidates().find(e=>e.value===t.tapTarget):null;return W` ${t.tapTarget&&!s?W`
${this._t("marker.run_target_gone",{id:t.tapTarget})}
`:G} ${this._t("marker.nothing_found")}
`}
`}`})():G} - ${"run"===r||"toggle"===r?W`
- `}}wm.properties={_tabDrag:{state:!0},_hdrH:{state:!0},_booting:{state:!0},_bootFading:{state:!0},_bootSoft:{state:!0},_continuityEpoch:{state:!0},_tapConfirm:{state:!0},hass:{attribute:!1},_config:{state:!0},_space:{state:!0},_layout:{state:!0},_devices:{state:!0},_tip:{state:!0},_hoverRoom:{state:!0},_selId:{state:!0},_toast:{state:!0},_serverCfg:{state:!0},_mode:{state:!0},_tool:{state:!0},_wallDialog:{state:!0},_drawWallField:{state:!0},_activeDraftId:{state:!0},_physicalSel:{state:!0},_physicalDialog:{state:!0},_partitionDeleteDialog:{state:!0},_roomDeleteDialog:{state:!0},_physicalDrag:{state:!0},_physicalRotate:{state:!0},_duplicateColumnId:{state:!0},_rszSel:{state:!0},_rszLive:{state:!0},_opMeasure:{state:!0},_path:{state:!0},_cursorPt:{state:!0},_mergeSel:{state:!0},_openingPreset:{state:!0},_openingDialog:{state:!0},_openingInfo:{state:!0},_mergeDialog:{state:!0},_openWallAnchor:{state:!0},_splitSel:{state:!0},_decorTool:{state:!0},_decorStyle:{state:!0},_decorDraft:{state:!0},_decorSel:{state:!0},_decorEraseConfirm:{state:!0},_decorTextDialog:{state:!0},_decorShapeDialog:{state:!0},_backdropDialog:{state:!0},_furnPalette:{state:!0},_bdDrag:{state:!0},_dtBox:{state:!0},_dtDrag:{state:!0},_kioskDialog:{state:!0},_vacFit:{state:!0},_vacAllCamerasFor:{state:!0},_vacCalConfirm:{state:!0},_kioskDots:{state:!0},_areaSel:{state:!0},_nameSel:{state:!0},_roomDialog:{state:!0},_roomEditId:{state:!0},_roomFill:{state:!0},_roomCustomFill:{state:!0},_roomTempSrc:{state:!0},_roomHumSrc:{state:!0},_roomSrcOpen:{state:!0},_roomSrcFilter:{state:!0},_roomNameScale:{state:!0},_roomLabelScale:{state:!0},_spaceDialog:{state:!0},_infoCard:{state:!0},_rulesDialog:{state:!0},_settingsDialog:{state:!0},_alignDialog:{state:!0},_backupExportDialog:{state:!0},_backupImportDialog:{state:!0},_importDialog:{state:!0},_markerDialog:{state:!0},_zoom:{state:!0},_view:{state:!0}},wm.ZOOM_MAX=8,wm.ZOOM_MIN=1/3,wm.styles=[Kt,Iu],customElements.get("houseplan-card")||customElements.define("houseplan-card",wm),window.customCards=window.customCards||[],window.customCards.find(t=>"houseplan-card"===t.type)||window.customCards.push({type:"houseplan-card",name:"House Plan Card",description:"Interactive house plan: spaces, rooms and devices with live states and drag layout."}),console.info(`%c HOUSEPLAN-CARD %c v${Gg} `,"background:#3ea6ff;color:#04121f;font-weight:700",""); + `}}km.properties={_tabDrag:{state:!0},_hdrH:{state:!0},_booting:{state:!0},_bootFading:{state:!0},_bootSoft:{state:!0},_continuityEpoch:{state:!0},_tapConfirm:{state:!0},hass:{attribute:!1},_config:{state:!0},_space:{state:!0},_layout:{state:!0},_devices:{state:!0},_tip:{state:!0},_hoverRoom:{state:!0},_selId:{state:!0},_toast:{state:!0},_serverCfg:{state:!0},_mode:{state:!0},_tool:{state:!0},_wallDialog:{state:!0},_drawWallField:{state:!0},_activeDraftId:{state:!0},_physicalSel:{state:!0},_physicalDialog:{state:!0},_partitionDeleteDialog:{state:!0},_roomDeleteDialog:{state:!0},_physicalDrag:{state:!0},_physicalRotate:{state:!0},_duplicateColumnId:{state:!0},_rszSel:{state:!0},_rszLive:{state:!0},_opMeasure:{state:!0},_path:{state:!0},_cursorPt:{state:!0},_mergeSel:{state:!0},_openingPreset:{state:!0},_openingDialog:{state:!0},_openingInfo:{state:!0},_mergeDialog:{state:!0},_openWallAnchor:{state:!0},_splitSel:{state:!0},_decorTool:{state:!0},_decorStyle:{state:!0},_decorDraft:{state:!0},_decorSel:{state:!0},_decorEraseConfirm:{state:!0},_decorTextDialog:{state:!0},_decorShapeDialog:{state:!0},_backdropDialog:{state:!0},_furnPalette:{state:!0},_bdDrag:{state:!0},_dtBox:{state:!0},_dtDrag:{state:!0},_kioskDialog:{state:!0},_vacFit:{state:!0},_vacAllCamerasFor:{state:!0},_vacCalConfirm:{state:!0},_kioskDots:{state:!0},_areaSel:{state:!0},_nameSel:{state:!0},_roomDialog:{state:!0},_roomEditId:{state:!0},_roomFill:{state:!0},_roomCustomFill:{state:!0},_roomTempSrc:{state:!0},_roomHumSrc:{state:!0},_roomSrcOpen:{state:!0},_roomSrcFilter:{state:!0},_roomNameScale:{state:!0},_roomLabelScale:{state:!0},_spaceDialog:{state:!0},_infoCard:{state:!0},_rulesDialog:{state:!0},_settingsDialog:{state:!0},_alignDialog:{state:!0},_backupExportDialog:{state:!0},_backupImportDialog:{state:!0},_importDialog:{state:!0},_markerDialog:{state:!0},_zoom:{state:!0},_view:{state:!0}},km.ZOOM_MAX=8,km.ZOOM_MIN=1/3,km.styles=[Kt,Au],customElements.get("houseplan-card")||customElements.define("houseplan-card",km),window.customCards=window.customCards||[],window.customCards.find(t=>"houseplan-card"===t.type)||window.customCards.push({type:"houseplan-card",name:"House Plan Card",description:"Interactive house plan: spaces, rooms and devices with live states and drag layout."}),console.info(`%c HOUSEPLAN-CARD %c v${Vg} `,"background:#3ea6ff;color:#04121f;font-weight:700",""); diff --git a/demo/smoke_multiwall_junction.mjs b/demo/smoke_multiwall_junction.mjs index 3a4d47c2..6482dcd6 100644 --- a/demo/smoke_multiwall_junction.mjs +++ b/demo/smoke_multiwall_junction.mjs @@ -58,8 +58,8 @@ const result = await page.evaluate(async (source) => { const planD = path?.getAttribute('d') || ''; const canonical = card._wallUnionGeometry(); const node = new DOMPoint(source.node[0] * 1000, source.node[1] * 1000); - // Midpoint between the approved bevel and the old 1.80×H mitre. - const discardedWedge = new DOMPoint(330.0011713041353, 146.99331561935776); + // Midpoint between the R-bounded straight bevel and the old 1.80×H mitre. + const discardedWedge = new DOMPoint(330.3808442725, 148.8560107825); out.fixtureLoaded = card._spaceModel()?.rooms.length === 2 && card._spaceWalls.length === 7; out.planUsesCanonicalPath = !!planD && canonical?.d === planD; diff --git a/demo/srv/assets/houseplan-card.js b/demo/srv/assets/houseplan-card.js index 95824be3..a08e73f8 100755 --- a/demo/srv/assets/houseplan-card.js +++ b/demo/srv/assets/houseplan-card.js @@ -1,4 +1,4 @@ -globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8921aeec392e69d7c511f35bace06";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)},r=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:a,defineProperty:l,getOwnPropertyDescriptor:c,getOwnPropertyNames:h,getOwnPropertySymbols:d,getPrototypeOf:p}=Object,u=globalThis,_=u.trustedTypes,g=_?_.emptyScript:"",m=u.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)=>!a(t,e),b={attribute:!0,type:String,converter:v,reflect:!1,useDefault:!1,hasChanged:y};Symbol.metadata??=Symbol("metadata"),u.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=p(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(r(t))}else void 0!==t&&e.push(r(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}),(u.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?"":"",r=E;for(let e=0;e"===l[0]?(r=n??E,c=-1):void 0===l[1]?c=-2:(c=r.lastIndex-l[2].length,a=l[1],r=void 0===l[3]?N:'"'===l[3]?L:H):r===L||r===H?r=N:r===z||r===O?r=E:(r=N,n=void 0);const d=r===N&&t[e+1].startsWith("/>")?" ":"";o+=r===E?i+T:c>=0?(s.push(a),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 r=t.length-1,a=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())&&a.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 r,a;for(t=n[0],r=0;r{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 pt=2,ut=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=ut(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}=rt,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,r=o!==t;if(r){let e;i._$AQ?.(t),i._$AM=t,void 0!==i._$AP&&(e=t._$AU)!==o._$AU&&i._$AP(e)}if(e!==n||r){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=ut(class extends _t{constructor(t){if(super(t),t.type!==pt)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 r=0;for(const e of t)n[r]=s?s(e,r):r,o[r]=i(e,r),r++;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:r}=this.dt(e,i,s);if(!Array.isArray(n))return this.ut=r,o;const a=this.ut??=[],l=[];let c,h,d=0,p=n.length-1,u=0,_=o.length-1;for(;d<=p&&u<=_;)if(null===n[d])d++;else if(null===n[p])p--;else if(a[d]===r[u])l[u]=wt(n[d],o[u]),d++,u++;else if(a[p]===r[_])l[_]=wt(n[p],o[_]),p--,_--;else if(a[d]===r[_])l[_]=wt(n[d],o[_]),bt(t,l[_+1],n[d]),d++,_--;else if(a[p]===r[u])l[u]=wt(n[p],o[u]),bt(t,n[d],n[p]),p--,u++;else if(void 0===c&&(c=St(r,u,_),h=St(a,d,p)),c.has(a[d]))if(c.has(a[p])){const e=h.get(r[u]),i=void 0!==e?n[e]:null;if(null===i){const e=bt(t,n[d]);wt(e,o[u]),l[u]=e}else l[u]=wt(i,o[u]),bt(t,n[d],i),n[e]=null;u++}else $t(n[p]),p--;else $t(n[d]),d++;for(;u<=_;){const e=bt(t,l[_+1]);wt(e,o[u]),l[u++]=e}for(;d<=p;){const t=n[d++];null!==t&&$t(t)}return this.ut=r,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__="9332b8278ae9e2f3a2e9ab4f07e3bf1b56fe0cb818a0a1c67d41e365ad74da43";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:p}=Object,u=globalThis,_=u.trustedTypes,g=_?_.emptyScript:"",m=u.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"),u.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=p(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}),(u.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 pt=2,ut=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=ut(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=ut(class extends _t{constructor(t){if(super(t),t.type!==pt)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,p=n.length-1,u=0,_=o.length-1;for(;d<=p&&u<=_;)if(null===n[d])d++;else if(null===n[p])p--;else if(r[d]===a[u])l[u]=wt(n[d],o[u]),d++,u++;else if(r[p]===a[_])l[_]=wt(n[p],o[_]),p--,_--;else if(r[d]===a[_])l[_]=wt(n[d],o[_]),bt(t,l[_+1],n[d]),d++,_--;else if(r[p]===a[u])l[u]=wt(n[p],o[u]),bt(t,n[d],n[p]),p--,u++;else if(void 0===c&&(c=St(a,u,_),h=St(r,d,p)),c.has(r[d]))if(c.has(r[p])){const e=h.get(a[u]),i=void 0!==e?n[e]:null;if(null===i){const e=bt(t,n[d]);wt(e,o[u]),l[u]=e}else l[u]=wt(i,o[u]),bt(t,n[d],i),n[e]=null;u++}else $t(n[p]),p--;else $t(n[d]),d++;for(;u<=_;){const e=bt(t,l[_+1]);wt(e,o[u]),l[u++]=e}for(;d<=p;){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`"number"==typeof t&&Number.isFinite(t)))return null;const[i,s,n]=e.map(t=>Math.round(Math.min(255,Math.max(0,t))));return`rgb(${i}, ${s}, ${n})`}const Et=(t,e,i)=>Math.min(i,Math.max(e,Number.isFinite(t)?t:e));function zt(t){return Number.isFinite(t)?(t%360+360)%360:0}function Ot(t){if("string"!=typeof t)return null;const e=t.trim().replace(/^#/,""),i=/^[0-9a-fA-F]{3}$/.test(e)?e.split("").map(t=>`${t}${t}`).join(""):e;return/^[0-9a-fA-F]{6}$/.test(i)?`#${i.toLowerCase()}`:null}function Nt(t){const e=Ot(t);return e?{r:Number.parseInt(e.slice(1,3),16),g:Number.parseInt(e.slice(3,5),16),b:Number.parseInt(e.slice(5,7),16)}:null}function Ht(t){const e=Et(t.r,0,255)/255,i=Et(t.g,0,255)/255,s=Et(t.b,0,255)/255,n=Math.max(e,i,s),o=n-Math.min(e,i,s);let r=0;return o>0&&(r=n===e?(i-s)/o%6*60:n===i?60*((s-e)/o+2):60*((e-i)/o+4)),{h:zt(r),s:0===n?0:o/n*100,v:100*n}}function Lt(t){return function(t){const e=t=>Math.round(Et(t,0,255)).toString(16).padStart(2,"0");return`#${e(t.r)}${e(t.g)}${e(t.b)}`}(function(t){const e=zt(t.h),i=Et(t.s,0,100)/100,s=Et(t.v,0,100)/100,n=s*i,o=n*(1-Math.abs(e/60%2-1)),r=s-n;let a;return a=e<60?[n,o,0]:e<120?[o,n,0]:e<180?[0,n,o]:e<240?[0,o,n]:e<300?[o,0,n]:[n,0,o],{r:Math.round(255*(a[0]+r)),g:Math.round(255*(a[1]+r)),b:Math.round(255*(a[2]+r))}}(t))}function Bt(t){const e=t.visualViewport;return e&&Number.isFinite(e.width)&&Number.isFinite(e.height)?{left:Number(e.offsetLeft)||0,top:Number(e.offsetTop)||0,width:Math.max(0,Number(e.width)||0),height:Math.max(0,Number(e.height)||0)}:{left:0,top:0,width:t.innerWidth,height:t.innerHeight}}function qt(t,e,i,s=7,n=8){const o=i.left+n,r=i.top+n,a=Math.max(o,i.left+i.width-n),l=Math.max(r,i.top+i.height-n),c=Math.max(0,a-o),h=Math.max(0,l-r),d=Math.min(Math.max(0,e.width),c),p=Math.min(Math.max(0,e.height),h);let u=t.left;u+d>a&&(u=t.right-d),u=Math.min(Math.max(o,u),Math.max(o,a-d));const _=t.bottom+s,g=t.top-s-p;let m="bottom",f=_;return _+p>l&&g>=r?(m="top",f=Math.min(Math.max(r,g),Math.max(r,l-p))):f=Math.min(Math.max(r,_),Math.max(r,l-p)),{left:Math.round(u),top:Math.round(f),side:m,maxWidth:Math.round(c),maxHeight:Math.round(h)}}class Wt{constructor(t,e,i){this.owner=t,this.name=e,this.keydown=i,this.host=null,this.root=null}window(){return this.owner.ownerDocument.defaultView}dialog(){return this.owner.closest("hp-dialog")}usesPopover(t=!1){const e=this.window();return!t&&!!e&&function(t){const e=t.HTMLElement?.prototype;return"function"==typeof e?.showPopover&&"function"==typeof e?.hidePopover}(e)}get hasFallback(){return!!this.host}containsPath(t){return t.includes(this.owner)||!!this.host&&t.includes(this.host)}ownsActiveElement(){let t=this.owner.ownerDocument.activeElement;for(;t?.shadowRoot?.activeElement;)t=t.shadowRoot.activeElement;return!(!t||t!==this.owner&&!this.owner.shadowRoot?.contains(t)&&!this.root?.contains(t))}renderFallback(t,e){const i=this.ensureFallback();return i?(lt(W`${t}`,i),i):null}surface(t,e){return e?this.owner.shadowRoot?.querySelector(t)||null:this.root?.querySelector(t)||null}destroy(){this.root&<(G,this.root),this.host?.remove(),this.host=null,this.root=null}ensureFallback(){if(this.root?.isConnected)return this.root;const t=this.dialog()?.overlayPortal()||this.owner.ownerDocument.body;if(!t)return null;const e=this.owner.ownerDocument.createElement("div");return e.dataset.hpOverlay=this.name,e.style.display="contents",this.keydown&&e.addEventListener("keydown",this.keydown,!0),t.append(e),this.host=e,this.root=e.attachShadow({mode:"open"}),this.root}}const jt={title:"Color picker",hue:"Hue",saturation:"Saturation",value:"Brightness",hex:"Hex color",invalidHex:"Enter a 3- or 6-digit hex color"};class Ut extends ht{constructor(){super(...arguments),this.label="",this.opacityLabel="Opacity",this.color="#607d8b",this.opacity=1,this.disabled=!1,this.showOpacity=!0,this.pickerLabels=jt,this._open=!1,this._pickerRaf=0,this._emitRaf=0,this._forceFallback=!1,this._overlayDispose=null,this._hue=0,this._saturation=0,this._value=0,this._hexDraft="#607d8b",this._hexInvalid=!1,this._lastValidColor="#607d8b",this._activePointerId=null,this._outsidePointerDown=t=>{if(!this._open)return;const e=t.composedPath();this._floating.containsPath(e)||this._closePicker(!1,"outside")},this._keyDown=t=>{this._open&&"Escape"===t.key&&(t.preventDefault(),t.stopImmediatePropagation(),this._closePicker(this._floating.ownsActiveElement(),"escape"))},this._floating=new Wt(this,"color-opacity",this._keyDown),this._queuePickerPosition=()=>{if(!this._open)return;this._pickerRaf&&cancelAnimationFrame(this._pickerRaf);const t=this._window();t&&(this._pickerRaf=t.requestAnimationFrame(()=>{this._pickerRaf=0,this._positionPicker()||this._closePicker()}))}}connectedCallback(){super.connectedCallback(),this._syncFromColor(this.color,!1),this.ownerDocument.addEventListener("pointerdown",this._outsidePointerDown,!0),this.ownerDocument.addEventListener("scroll",this._queuePickerPosition,!0);const t=this.ownerDocument.defaultView;t?.addEventListener("resize",this._queuePickerPosition),t?.addEventListener("orientationchange",this._queuePickerPosition),t?.visualViewport?.addEventListener("resize",this._queuePickerPosition),t?.visualViewport?.addEventListener("scroll",this._queuePickerPosition),this.addEventListener("keydown",this._keyDown,!0)}disconnectedCallback(){this.ownerDocument.removeEventListener("pointerdown",this._outsidePointerDown,!0),this.ownerDocument.removeEventListener("scroll",this._queuePickerPosition,!0);const t=this.ownerDocument.defaultView;t?.removeEventListener("resize",this._queuePickerPosition),t?.removeEventListener("orientationchange",this._queuePickerPosition),t?.visualViewport?.removeEventListener("resize",this._queuePickerPosition),t?.visualViewport?.removeEventListener("scroll",this._queuePickerPosition),this.removeEventListener("keydown",this._keyDown,!0),this._pickerRaf&&cancelAnimationFrame(this._pickerRaf),this._emitRaf&&cancelAnimationFrame(this._emitRaf),this._pickerRaf=0,this._emitRaf=0,this._closePicker(!1,"disconnect"),super.disconnectedCallback()}updated(t){if(t.has("color")){const t=Ot(this.color);t&&t!==this._lastValidColor&&this._syncFromColor(t,this._open)}this.disabled&&this._open?this._closePicker():this._open&&(this._supportsPopover()||this._renderFallback(),(t.has("color")||t.has("opacity")||t.has("showOpacity")||t.has("label")||t.has("opacityLabel")||t.has("pickerLabels"))&&this._queuePickerPosition())}_window(){return this._floating.window()}_supportsPopover(){return this._floating.usesPopover(this._forceFallback)}_dialog(){return this._floating.dialog()}async _toggle(){this.disabled||(this._open?this._closePicker():(this._forceFallback=!1,this._syncFromColor(this.color,!1),this._hexInvalid=!1,this._activePointerId=null,this._open=!0,await this.updateComplete,this._open&&(this._supportsPopover()||this._renderFallback(),this._positionPicker()?this._overlayDispose=this._dialog()?.registerOverlay({owner:this,group:"transient",close:t=>this._closePicker("escape"===t&&this._floating.ownsActiveElement(),t)})||null:this._closePicker())))}_closePicker(t=!1,e="exclusive"){if(!this._open&&!this._floating.hasFallback)return;const i=this._overlayDispose;this._overlayDispose=null,i?.();const s=this.renderRoot.querySelector(".picker");if(s?.hidePopover)try{s.matches(":popover-open")&&s.hidePopover()}catch{}this._open=!1,this._cancelQueuedEmit(),this._activePointerId=null,this._floating.destroy(),t&&this.updateComplete.then(()=>this.renderRoot.querySelector(".trigger")?.focus())}_surface(){return this._floating.surface(".picker",this._supportsPopover())}_renderFallback(){const t=Ut.styles.cssText;this._floating.renderFallback(this._pickerTemplate(!1),t)}_positionPicker(){if(!this._open)return!1;const t=this._window(),e=this.renderRoot.querySelector(".trigger");let i=this._surface();if(!t||!e?.isConnected||!i?.isConnected)return!1;const s=Bt(t);if(i.style.maxWidth=`${Math.max(0,s.width-16)}px`,i.style.maxHeight=`${Math.max(0,s.height-16)}px`,i.style.visibility="hidden",this._supportsPopover()&&i.showPopover)try{i.matches(":popover-open")||i.showPopover()}catch{if(this._forceFallback=!0,this._renderFallback(),i=this._surface(),!i?.isConnected)return!1;i.style.maxWidth=`${Math.max(0,s.width-16)}px`,i.style.maxHeight=`${Math.max(0,s.height-16)}px`,i.style.visibility="hidden"}const n=e.getBoundingClientRect(),o=i.getBoundingClientRect();if(!(n.width&&n.height&&o.width&&o.height))return!1;const r=qt(n,o,s);return i.style.left=`${r.left}px`,i.style.top=`${r.top}px`,i.dataset.side=r.side,i.style.visibility="",!0}_labels(){const t=this.pickerLabels||jt;return{title:t.title||jt.title,hue:t.hue||jt.hue,saturation:t.saturation||jt.saturation,value:t.value||jt.value,hex:t.hex||jt.hex,invalidHex:t.invalidHex||jt.invalidHex}}_syncFromColor(t,e){const i=Ot(Rt(t,"#607d8b"))||"#607d8b",s=Nt(i);if(!s)return;const n=Ht(s);(!e||n.s>1e-4)&&(this._hue=n.h),this._saturation=n.s,this._value=n.v,this._hexDraft=i,this._hexInvalid=!1,this._lastValidColor=i}_cancelQueuedEmit(t=!1){this._emitRaf&&cancelAnimationFrame(this._emitRaf),this._emitRaf=0,t&&this._syncFromColor(this._lastValidColor,!0)}_queueHsvEmit(){if(this._emitRaf)return;const t=this._window();t?this._emitRaf=t.requestAnimationFrame(()=>{this._emitRaf=0,this._emitHsv()}):this._emitHsv()}_emitHsv(){this._emit(Lt({h:this._hue,s:this._saturation,v:this._value}),this.opacity)}_setHue(t){this._hue=Math.min(359,Math.max(0,Number.isFinite(t)?t:0)),this._emitHsv()}_setSaturation(t){this._saturation=Math.min(100,Math.max(0,Number.isFinite(t)?t:0)),this._emitHsv()}_setValue(t){this._value=Math.min(100,Math.max(0,Number.isFinite(t)?t:0)),this._emitHsv()}_setOpacity(t){this._emit(this._lastValidColor,t)}_shiftRangeKey(t,e,i,s,n){if(!t.shiftKey)return;const o="ArrowRight"===t.key||"ArrowUp"===t.key?10:"ArrowLeft"===t.key||"ArrowDown"===t.key?-10:0;o&&(t.preventDefault(),t.stopPropagation(),n(Math.min(s,Math.max(i,e+o))))}_setSvFromPointer(t,e){const i=t.currentTarget.getBoundingClientRect();i.width&&i.height&&(this._saturation=Math.min(100,Math.max(0,(t.clientX-i.left)/i.width*100)),this._value=Math.min(100,Math.max(0,100*(1-(t.clientY-i.top)/i.height))),e?(this._cancelQueuedEmit(),this._emitHsv()):this._queueHsvEmit())}_svPointerDown(t){if(t.preventDefault(),t.stopPropagation(),null===this._activePointerId){this._activePointerId=t.pointerId;try{t.currentTarget.setPointerCapture(t.pointerId)}catch{}this._setSvFromPointer(t,!0)}}_svPointerMove(t){t.pointerId===this._activePointerId&&(t.preventDefault(),t.stopPropagation(),this._setSvFromPointer(t,!1))}_svPointerUp(t){if(t.pointerId===this._activePointerId){t.preventDefault(),t.stopPropagation(),this._setSvFromPointer(t,!0),this._activePointerId=null;try{t.currentTarget.releasePointerCapture(t.pointerId)}catch{}}}_svPointerCancel(t){t.pointerId===this._activePointerId&&(t.preventDefault(),t.stopPropagation(),this._activePointerId=null,this._cancelQueuedEmit(!0))}_svLostPointerCapture(t){t.pointerId===this._activePointerId&&(this._activePointerId=null,this._cancelQueuedEmit(!0))}_hexInput(t){const e=t.target.value;this._hexDraft=e,this._hexInvalid=!1;const i=Ot(e),s=i?Nt(i):null;if(!i||!s)return;const n=Ht(s);n.s>1e-4&&(this._hue=n.h),this._saturation=n.s,this._value=n.v,this._emit(i,this.opacity,!0)}_commitHex(){const t=Ot(this._hexDraft);if(!t)return this._hexDraft=this._lastValidColor,void(this._hexInvalid=!0);this._hexDraft=t,this._hexInvalid=!1,t!==this._lastValidColor&&this._emit(t,this.opacity)}_hexKeyDown(t){"Enter"===t.key&&(t.preventDefault(),t.stopPropagation(),this._commitHex())}_emit(t,e,i=!1){const s=Ot(t)||this._lastValidColor,n=Number.isFinite(e)?e:Number(this.opacity)||0,o=Math.min(1,Math.max(0,n));this.color=s,this.opacity=o,this._lastValidColor=s,i||(this._hexDraft=s),this._hexInvalid=!1,this.dispatchEvent(new CustomEvent("hp-color-opacity-change",{detail:{color:s,opacity:o},bubbles:!0,composed:!0}))}_pickerTemplate(t){const e=Math.round(100*Math.min(1,Math.max(0,Number(this.opacity)||0))),i=Lt({h:this._hue,s:this._saturation,v:this._value}),s=Lt({h:this._hue,s:100,v:100}),n=this._labels(),o=Math.round(this._hue),r=Math.round(this._saturation),a=Math.round(this._value);return W` + `,customElements.get("hp-dialog")||customElements.define("hp-dialog",Tt);const Pt=/^#[0-9a-fA-F]{6}$/;function Rt(t,e){return"string"==typeof t&&Pt.test(t)?t:e}const It="(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])",At=new RegExp(`^rgb\\(${It}, ${It}, ${It}\\)$`);function Ft(t){if(!Array.isArray(t)||t.length<3)return null;const e=t.slice(0,3);if(!e.every(t=>"number"==typeof t&&Number.isFinite(t)))return null;const[i,s,n]=e.map(t=>Math.round(Math.min(255,Math.max(0,t))));return`rgb(${i}, ${s}, ${n})`}const Et=(t,e,i)=>Math.min(i,Math.max(e,Number.isFinite(t)?t:e));function zt(t){return Number.isFinite(t)?(t%360+360)%360:0}function Ot(t){if("string"!=typeof t)return null;const e=t.trim().replace(/^#/,""),i=/^[0-9a-fA-F]{3}$/.test(e)?e.split("").map(t=>`${t}${t}`).join(""):e;return/^[0-9a-fA-F]{6}$/.test(i)?`#${i.toLowerCase()}`:null}function Nt(t){const e=Ot(t);return e?{r:Number.parseInt(e.slice(1,3),16),g:Number.parseInt(e.slice(3,5),16),b:Number.parseInt(e.slice(5,7),16)}:null}function Ht(t){const e=Et(t.r,0,255)/255,i=Et(t.g,0,255)/255,s=Et(t.b,0,255)/255,n=Math.max(e,i,s),o=n-Math.min(e,i,s);let a=0;return o>0&&(a=n===e?(i-s)/o%6*60:n===i?60*((s-e)/o+2):60*((e-i)/o+4)),{h:zt(a),s:0===n?0:o/n*100,v:100*n}}function Lt(t){return function(t){const e=t=>Math.round(Et(t,0,255)).toString(16).padStart(2,"0");return`#${e(t.r)}${e(t.g)}${e(t.b)}`}(function(t){const e=zt(t.h),i=Et(t.s,0,100)/100,s=Et(t.v,0,100)/100,n=s*i,o=n*(1-Math.abs(e/60%2-1)),a=s-n;let r;return r=e<60?[n,o,0]:e<120?[o,n,0]:e<180?[0,n,o]:e<240?[0,o,n]:e<300?[o,0,n]:[n,0,o],{r:Math.round(255*(r[0]+a)),g:Math.round(255*(r[1]+a)),b:Math.round(255*(r[2]+a))}}(t))}function Bt(t){const e=t.visualViewport;return e&&Number.isFinite(e.width)&&Number.isFinite(e.height)?{left:Number(e.offsetLeft)||0,top:Number(e.offsetTop)||0,width:Math.max(0,Number(e.width)||0),height:Math.max(0,Number(e.height)||0)}:{left:0,top:0,width:t.innerWidth,height:t.innerHeight}}function qt(t,e,i,s=7,n=8){const o=i.left+n,a=i.top+n,r=Math.max(o,i.left+i.width-n),l=Math.max(a,i.top+i.height-n),c=Math.max(0,r-o),h=Math.max(0,l-a),d=Math.min(Math.max(0,e.width),c),p=Math.min(Math.max(0,e.height),h);let u=t.left;u+d>r&&(u=t.right-d),u=Math.min(Math.max(o,u),Math.max(o,r-d));const _=t.bottom+s,g=t.top-s-p;let m="bottom",f=_;return _+p>l&&g>=a?(m="top",f=Math.min(Math.max(a,g),Math.max(a,l-p))):f=Math.min(Math.max(a,_),Math.max(a,l-p)),{left:Math.round(u),top:Math.round(f),side:m,maxWidth:Math.round(c),maxHeight:Math.round(h)}}class Wt{constructor(t,e,i){this.owner=t,this.name=e,this.keydown=i,this.host=null,this.root=null}window(){return this.owner.ownerDocument.defaultView}dialog(){return this.owner.closest("hp-dialog")}usesPopover(t=!1){const e=this.window();return!t&&!!e&&function(t){const e=t.HTMLElement?.prototype;return"function"==typeof e?.showPopover&&"function"==typeof e?.hidePopover}(e)}get hasFallback(){return!!this.host}containsPath(t){return t.includes(this.owner)||!!this.host&&t.includes(this.host)}ownsActiveElement(){let t=this.owner.ownerDocument.activeElement;for(;t?.shadowRoot?.activeElement;)t=t.shadowRoot.activeElement;return!(!t||t!==this.owner&&!this.owner.shadowRoot?.contains(t)&&!this.root?.contains(t))}renderFallback(t,e){const i=this.ensureFallback();return i?(lt(W`${t}`,i),i):null}surface(t,e){return e?this.owner.shadowRoot?.querySelector(t)||null:this.root?.querySelector(t)||null}destroy(){this.root&<(G,this.root),this.host?.remove(),this.host=null,this.root=null}ensureFallback(){if(this.root?.isConnected)return this.root;const t=this.dialog()?.overlayPortal()||this.owner.ownerDocument.body;if(!t)return null;const e=this.owner.ownerDocument.createElement("div");return e.dataset.hpOverlay=this.name,e.style.display="contents",this.keydown&&e.addEventListener("keydown",this.keydown,!0),t.append(e),this.host=e,this.root=e.attachShadow({mode:"open"}),this.root}}const jt={title:"Color picker",hue:"Hue",saturation:"Saturation",value:"Brightness",hex:"Hex color",invalidHex:"Enter a 3- or 6-digit hex color"};class Ut extends ht{constructor(){super(...arguments),this.label="",this.opacityLabel="Opacity",this.color="#607d8b",this.opacity=1,this.disabled=!1,this.showOpacity=!0,this.pickerLabels=jt,this._open=!1,this._pickerRaf=0,this._emitRaf=0,this._forceFallback=!1,this._overlayDispose=null,this._hue=0,this._saturation=0,this._value=0,this._hexDraft="#607d8b",this._hexInvalid=!1,this._lastValidColor="#607d8b",this._activePointerId=null,this._outsidePointerDown=t=>{if(!this._open)return;const e=t.composedPath();this._floating.containsPath(e)||this._closePicker(!1,"outside")},this._keyDown=t=>{this._open&&"Escape"===t.key&&(t.preventDefault(),t.stopImmediatePropagation(),this._closePicker(this._floating.ownsActiveElement(),"escape"))},this._floating=new Wt(this,"color-opacity",this._keyDown),this._queuePickerPosition=()=>{if(!this._open)return;this._pickerRaf&&cancelAnimationFrame(this._pickerRaf);const t=this._window();t&&(this._pickerRaf=t.requestAnimationFrame(()=>{this._pickerRaf=0,this._positionPicker()||this._closePicker()}))}}connectedCallback(){super.connectedCallback(),this._syncFromColor(this.color,!1),this.ownerDocument.addEventListener("pointerdown",this._outsidePointerDown,!0),this.ownerDocument.addEventListener("scroll",this._queuePickerPosition,!0);const t=this.ownerDocument.defaultView;t?.addEventListener("resize",this._queuePickerPosition),t?.addEventListener("orientationchange",this._queuePickerPosition),t?.visualViewport?.addEventListener("resize",this._queuePickerPosition),t?.visualViewport?.addEventListener("scroll",this._queuePickerPosition),this.addEventListener("keydown",this._keyDown,!0)}disconnectedCallback(){this.ownerDocument.removeEventListener("pointerdown",this._outsidePointerDown,!0),this.ownerDocument.removeEventListener("scroll",this._queuePickerPosition,!0);const t=this.ownerDocument.defaultView;t?.removeEventListener("resize",this._queuePickerPosition),t?.removeEventListener("orientationchange",this._queuePickerPosition),t?.visualViewport?.removeEventListener("resize",this._queuePickerPosition),t?.visualViewport?.removeEventListener("scroll",this._queuePickerPosition),this.removeEventListener("keydown",this._keyDown,!0),this._pickerRaf&&cancelAnimationFrame(this._pickerRaf),this._emitRaf&&cancelAnimationFrame(this._emitRaf),this._pickerRaf=0,this._emitRaf=0,this._closePicker(!1,"disconnect"),super.disconnectedCallback()}updated(t){if(t.has("color")){const t=Ot(this.color);t&&t!==this._lastValidColor&&this._syncFromColor(t,this._open)}this.disabled&&this._open?this._closePicker():this._open&&(this._supportsPopover()||this._renderFallback(),(t.has("color")||t.has("opacity")||t.has("showOpacity")||t.has("label")||t.has("opacityLabel")||t.has("pickerLabels"))&&this._queuePickerPosition())}_window(){return this._floating.window()}_supportsPopover(){return this._floating.usesPopover(this._forceFallback)}_dialog(){return this._floating.dialog()}async _toggle(){this.disabled||(this._open?this._closePicker():(this._forceFallback=!1,this._syncFromColor(this.color,!1),this._hexInvalid=!1,this._activePointerId=null,this._open=!0,await this.updateComplete,this._open&&(this._supportsPopover()||this._renderFallback(),this._positionPicker()?this._overlayDispose=this._dialog()?.registerOverlay({owner:this,group:"transient",close:t=>this._closePicker("escape"===t&&this._floating.ownsActiveElement(),t)})||null:this._closePicker())))}_closePicker(t=!1,e="exclusive"){if(!this._open&&!this._floating.hasFallback)return;const i=this._overlayDispose;this._overlayDispose=null,i?.();const s=this.renderRoot.querySelector(".picker");if(s?.hidePopover)try{s.matches(":popover-open")&&s.hidePopover()}catch{}this._open=!1,this._cancelQueuedEmit(),this._activePointerId=null,this._floating.destroy(),t&&this.updateComplete.then(()=>this.renderRoot.querySelector(".trigger")?.focus())}_surface(){return this._floating.surface(".picker",this._supportsPopover())}_renderFallback(){const t=Ut.styles.cssText;this._floating.renderFallback(this._pickerTemplate(!1),t)}_positionPicker(){if(!this._open)return!1;const t=this._window(),e=this.renderRoot.querySelector(".trigger");let i=this._surface();if(!t||!e?.isConnected||!i?.isConnected)return!1;const s=Bt(t);if(i.style.maxWidth=`${Math.max(0,s.width-16)}px`,i.style.maxHeight=`${Math.max(0,s.height-16)}px`,i.style.visibility="hidden",this._supportsPopover()&&i.showPopover)try{i.matches(":popover-open")||i.showPopover()}catch{if(this._forceFallback=!0,this._renderFallback(),i=this._surface(),!i?.isConnected)return!1;i.style.maxWidth=`${Math.max(0,s.width-16)}px`,i.style.maxHeight=`${Math.max(0,s.height-16)}px`,i.style.visibility="hidden"}const n=e.getBoundingClientRect(),o=i.getBoundingClientRect();if(!(n.width&&n.height&&o.width&&o.height))return!1;const a=qt(n,o,s);return i.style.left=`${a.left}px`,i.style.top=`${a.top}px`,i.dataset.side=a.side,i.style.visibility="",!0}_labels(){const t=this.pickerLabels||jt;return{title:t.title||jt.title,hue:t.hue||jt.hue,saturation:t.saturation||jt.saturation,value:t.value||jt.value,hex:t.hex||jt.hex,invalidHex:t.invalidHex||jt.invalidHex}}_syncFromColor(t,e){const i=Ot(Rt(t,"#607d8b"))||"#607d8b",s=Nt(i);if(!s)return;const n=Ht(s);(!e||n.s>1e-4)&&(this._hue=n.h),this._saturation=n.s,this._value=n.v,this._hexDraft=i,this._hexInvalid=!1,this._lastValidColor=i}_cancelQueuedEmit(t=!1){this._emitRaf&&cancelAnimationFrame(this._emitRaf),this._emitRaf=0,t&&this._syncFromColor(this._lastValidColor,!0)}_queueHsvEmit(){if(this._emitRaf)return;const t=this._window();t?this._emitRaf=t.requestAnimationFrame(()=>{this._emitRaf=0,this._emitHsv()}):this._emitHsv()}_emitHsv(){this._emit(Lt({h:this._hue,s:this._saturation,v:this._value}),this.opacity)}_setHue(t){this._hue=Math.min(359,Math.max(0,Number.isFinite(t)?t:0)),this._emitHsv()}_setSaturation(t){this._saturation=Math.min(100,Math.max(0,Number.isFinite(t)?t:0)),this._emitHsv()}_setValue(t){this._value=Math.min(100,Math.max(0,Number.isFinite(t)?t:0)),this._emitHsv()}_setOpacity(t){this._emit(this._lastValidColor,t)}_shiftRangeKey(t,e,i,s,n){if(!t.shiftKey)return;const o="ArrowRight"===t.key||"ArrowUp"===t.key?10:"ArrowLeft"===t.key||"ArrowDown"===t.key?-10:0;o&&(t.preventDefault(),t.stopPropagation(),n(Math.min(s,Math.max(i,e+o))))}_setSvFromPointer(t,e){const i=t.currentTarget.getBoundingClientRect();i.width&&i.height&&(this._saturation=Math.min(100,Math.max(0,(t.clientX-i.left)/i.width*100)),this._value=Math.min(100,Math.max(0,100*(1-(t.clientY-i.top)/i.height))),e?(this._cancelQueuedEmit(),this._emitHsv()):this._queueHsvEmit())}_svPointerDown(t){if(t.preventDefault(),t.stopPropagation(),null===this._activePointerId){this._activePointerId=t.pointerId;try{t.currentTarget.setPointerCapture(t.pointerId)}catch{}this._setSvFromPointer(t,!0)}}_svPointerMove(t){t.pointerId===this._activePointerId&&(t.preventDefault(),t.stopPropagation(),this._setSvFromPointer(t,!1))}_svPointerUp(t){if(t.pointerId===this._activePointerId){t.preventDefault(),t.stopPropagation(),this._setSvFromPointer(t,!0),this._activePointerId=null;try{t.currentTarget.releasePointerCapture(t.pointerId)}catch{}}}_svPointerCancel(t){t.pointerId===this._activePointerId&&(t.preventDefault(),t.stopPropagation(),this._activePointerId=null,this._cancelQueuedEmit(!0))}_svLostPointerCapture(t){t.pointerId===this._activePointerId&&(this._activePointerId=null,this._cancelQueuedEmit(!0))}_hexInput(t){const e=t.target.value;this._hexDraft=e,this._hexInvalid=!1;const i=Ot(e),s=i?Nt(i):null;if(!i||!s)return;const n=Ht(s);n.s>1e-4&&(this._hue=n.h),this._saturation=n.s,this._value=n.v,this._emit(i,this.opacity,!0)}_commitHex(){const t=Ot(this._hexDraft);if(!t)return this._hexDraft=this._lastValidColor,void(this._hexInvalid=!0);this._hexDraft=t,this._hexInvalid=!1,t!==this._lastValidColor&&this._emit(t,this.opacity)}_hexKeyDown(t){"Enter"===t.key&&(t.preventDefault(),t.stopPropagation(),this._commitHex())}_emit(t,e,i=!1){const s=Ot(t)||this._lastValidColor,n=Number.isFinite(e)?e:Number(this.opacity)||0,o=Math.min(1,Math.max(0,n));this.color=s,this.opacity=o,this._lastValidColor=s,i||(this._hexDraft=s),this._hexInvalid=!1,this.dispatchEvent(new CustomEvent("hp-color-opacity-change",{detail:{color:s,opacity:o},bubbles:!0,composed:!0}))}_pickerTemplate(t){const e=Math.round(100*Math.min(1,Math.max(0,Number(this.opacity)||0))),i=Lt({h:this._hue,s:this._saturation,v:this._value}),s=Lt({h:this._hue,s:100,v:100}),n=this._labels(),o=Math.round(this._hue),a=Math.round(this._saturation),r=Math.round(this._value);return W` `:G} - `}}hr.properties={hass:{attribute:!1},presentation:{attribute:!1},registry:{attribute:!1},deviceName:{attribute:!1}},hr.styles=[Kt,o` + `}}ha.properties={hass:{attribute:!1},presentation:{attribute:!1},registry:{attribute:!1},deviceName:{attribute:!1}},ha.styles=[Kt,o` :host { display: block; min-width: 0; } .devicepreview { margin: 4px 0 14px; @@ -4436,14 +4436,14 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8 .previewstage { min-height: 142px; } .previewfacts > div { grid-template-columns: minmax(0, 1fr); gap: 2px; } } - `],customElements.get("hp-device-preview")||customElements.define("hp-device-preview",hr);const dr=(t,e)=>[t[0]-e[0],t[1]-e[1]],pr=(t,e)=>[t[0]+e[0],t[1]+e[1]],ur=(t,e)=>t[0]*e[0]+t[1]*e[1],_r=t=>Math.hypot(t[0],t[1]);function gr(t){let e=0;for(let i=0;it[1]!=l>t[1]&&t[0]<(a-o)*(t[1]-r)/(l-r)+o&&(i=!i)}return i}([a[0]+r[0]*l,a[1]+r[1]*l],t)&&(r=[-r[0],-r[1]]),r}function vr(t,e,i,s){const n=s||fr(t,e),o=(e+1)%t.length;return t.map((t,s)=>s===e||s===o?[t[0]+n[0]*i,t[1]+n[1]*i]:[...t])}function yr(t,e,i,s){const n=[],o=dr(i,e),r=_r(o);if(rs||h>s)continue;const d=ur(dr(o,e),a),p=ur(dr(l,e),a),u=Math.max(0,Math.min(d,p)),_=Math.min(r,Math.max(d,p));_-u>s&&n.push([[e[0]+a[0]*u,e[1]+a[1]*u],[e[0]+a[0]*_,e[1]+a[1]*_]])}return n}function br(t,e,i,s,n){const o=yr(t,e,i,n);if(!o.length)return null;const r=t=>o.some(([e,i])=>mr(t,e,i)<=n),a=t.length,l=[];for(let o=0;on||f>n)continue;const v=ur(dr(e,c),u),y=ur(dr(i,c),u),b=Math.max(0,Math.min(v,y)),w=Math.min(p,Math.max(v,y));if(!(w-b<=n)){if(b>n&&bn&&w_r(dr(i,t[(s+1)%t.length]))>e);for(let t=0;t<2;t++)i=i.filter((t,s)=>{const n=i[(s-1+i.length)%i.length],o=i[(s+1)%i.length],r=(t[0]-n[0])*(o[1]-n[1])-(t[1]-n[1])*(o[0]-n[0]),a=_r(dr(o,n))||1;return Math.abs(r)/a>e});return i.length>=3?i:t}function kr(t){const e=t.length;if(e<3)return!1;for(let i=0;i(t[0]-n[0])*a[1]-(t[1]-n[1])*a[0],c=t=>(t[0]-n[0])*a[0]+(t[1]-n[1])*a[1],h=i,d=r-i;for(const e of t){const t=Math.abs(l(e));if(t<=i)continue;const n=c(e);n<=h||n>=d||tMath.abs(r+(t-p)/m*(a-r));s=Math.min(s,f(_),f(g))}}return s}function $r(t,e,i){if(Di(t,e,i))return!0;if(Ci(t,e,i)||Ci(e,t,i))return!1;let s=0;try{const i=ni([[...t.map(t=>[t[0],t[1]]),[t[0][0],t[0][1]]]],[[...e.map(t=>[t[0],t[1]]),[e[0][0],e[0][1]]]]);for(const t of i)t?.[0]&&(s+=Pi(t[0]))}catch{return!1}return s>Math.max(1e-7,i*i)}function Sr(t,e,i,s,n){const o=[i.n[0]*s,i.n[1]*s],r={polys:{},openings:{},movedSpans:{}};if(Math.abs(s)<1e-9)return r;for(const e of t){if(e.id===i.roomId){r.polys[e.id]=vr(e.poly,i.edge,s,i.n),r.movedSpans[e.id]=[[pr(i.a,o),pr(i.b,o)]];continue}const t=yr(e.poly,i.a,i.b,n);if(!t.length)continue;const a=br(e.poly,i.a,i.b,o,n);a&&(r.polys[e.id]=a,r.movedSpans[e.id]=t.map(([t,e])=>[pr(t,o),pr(e,o)]))}for(const t of e)mr([t.x,t.y],i.a,i.b)<=n&&(r.openings[t.id]=[t.x+o[0],t.y+o[1]]);return r}function Mr(t,e,i){for(const s of e)for(let e=0;ei)continue;const c=(t.x-n[0])*l[0]+(t.y-n[1])*l[1];if(c-t.length/2>=-i&&c+t.length/2<=a+i)return!0}return!1}function Cr(t,e,i){return t.filter(t=>e.some(e=>{for(let s=0;sa.polys[t.id]||t.poly;for(const e of l){const s=t.find(t=>t.id===e),n=a.polys[e];if(!kr(n))return!1;const l=gr(s.poly),h=gr(n);if(Math.abs(h)t.find(t=>t.id===e).poly),d=t.map(c);for(const t of Cr(e,h,2*r)){const e=a.openings[t.id];if(!Mr(e?{...t,x:e[0],y:e[1]}:t,d,2*r))return!1}return!0}function Tr(t,e,i,s,n,o){const r=t=>[s[0]+(t[0]-s[0])*n,s[1]+(t[1]-s[1])*n],a={poly:t.poly.map(r),openings:{}};for(const s of e){let e=!1;for(let i=0;i{for(let e=0;et.id===i);if(!l)return!1;const c=t.filter(t=>t.id!==i).map(t=>t.poly),h=Tr(l,e,c,s,n,2*a),d=h.poly,p=function(t){const e=function(t){const e=[...t].sort((t,e)=>t[0]-e[0]||t[1]-e[1]);if(e.length<3)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.pop(),n.pop(),s.concat(n)}(t);if(e.length<3)return 0;let i=1/0;for(let t=0;tt.id===i?d:t.poly);for(const t of Cr(e,[l.poly],2*a)){const e=h.openings[t.id];if(!Mr(e?{...t,x:e[0],y:e[1]}:t,u,2*a))return!1}return!0}function Rr(t,e,i){const s=i/e;return Pi(t)*s*s/1e4}function Ir(t,e){return e?`${Math.round(10.7639*t)} ft²`:`${(Math.round(10*t)/10).toFixed(1)} m²`}function Ar(t){const e=t%360;return e<0?e+360:e}function Fr(t,e){const i=function(t,e){return Ar(t+e)}(t,e)*Math.PI/180;return[Math.sin(i),-Math.cos(i)]}const Er=Object.freeze({dawn:Object.freeze({top:"#aabdd1",bottom:"#e8c8b7",horizon:"rgba(255,201,156,.56)",sun:"rgba(255,188,125,.78)",vignette:"rgba(65,72,99,.21)",outlineNear:"rgba(74,57,61,.25)",outlineMid:"rgba(255,238,224,.40)",outlineFar:"rgba(255,224,202,.18)"}),day:Object.freeze({top:"#dce9ef",bottom:"#cbdce3",horizon:"rgba(255,245,220,.45)",sun:"rgba(255,239,190,.72)",vignette:"rgba(65,91,105,.16)",outlineNear:"rgba(45,62,71,.28)",outlineMid:"rgba(255,255,255,.42)",outlineFar:"rgba(255,255,255,.20)"}),dusk:Object.freeze({top:"#48536c",bottom:"#9a7380",horizon:"rgba(242,156,114,.34)",sun:"rgba(255,167,113,.55)",vignette:"rgba(20,26,44,.39)",outlineNear:"rgba(238,219,225,.40)",outlineMid:"rgba(229,207,218,.26)",outlineFar:"rgba(215,190,205,.12)"}),night:Object.freeze({top:"#111a27",bottom:"#1f2f3e",horizon:"rgba(79,120,151,.16)",sun:"rgba(169,208,231,0)",vignette:"rgba(3,8,14,.58)",outlineNear:"rgba(218,238,249,.56)",outlineMid:"rgba(174,215,238,.30)",outlineFar:"rgba(136,194,226,.14)"})}),zr=t=>"number"==typeof t&&Number.isFinite(t),Or=(t,e,i)=>Math.min(i,Math.max(e,t));function Nr(t){return t.elevation<=-6?"night":t.elevation>=6?"day":t.rising?"dawn":"dusk"}function Hr(t){const e=(Math.floor(Number(t)||0)%1440+1440)%1440;return e>=300&&e<480?"dawn":e>=480&&e<1080?"day":e>=1080&&e<1260?"dusk":"night"}function Lr(t){const e=Nr(t),i=t.azimuth*Math.PI/180;return{sunX:50-42*Math.sin(i),sunY:78-Or(t.elevation,0,90)/90*64,sunOpacity:"night"===e?0:Or((t.elevation+6)/12,0,1)}}function Br(t){const e=(Math.floor(Number(t)||0)%1440+1440)%1440;if(e<300||e>=1260)return{sunX:50,sunY:78,sunOpacity:0};const i=(e-300)/960,s=(e-300)/120,n=(1260-e)/120;return{sunX:8+84*i,sunY:78-64*Math.sin(i*Math.PI),sunOpacity:Math.max(.18,Math.min(s,n,1))}}function qr(t,e=new Date){const i=function(t){const e=t?.states?.["sun.sun"]?.attributes;return e&&zr(e.azimuth)&&zr(e.elevation)&&"boolean"==typeof e.rising?{azimuth:Ar(e.azimuth),elevation:e.elevation,rising:e.rising}:null}(t);if(i)return{phase:Nr(i),source:"sun",...Lr(i)};const s="number"==typeof e?e:function(t=new Date){return 60*t.getHours()+t.getMinutes()}(e);return{phase:Hr(s),source:"clock",...Br(s)}}function Wr(t){return`${t.source}|${t.phase}|${t.sunX.toFixed(2)}|${t.sunY.toFixed(2)}|`+t.sunOpacity.toFixed(3)}const jr=[[-90,"#070c14"],[-12,"#070c14"],[-4,"#131a28"],[0,"#4a3527"],[10,"#e8ddcf"],[30,"#ffffff"],[90,"#ffffff"]],Ur=t=>Math.min(1,Math.max(0,t));function Gr(t,e,i=6){const s=t.angle*Math.PI/180,n=[Math.sin(s),-Math.cos(s)],o=s=>{const o=[t.x+n[0]*i*s,t.y+n[1]*i*s];return e.find(t=>t.poly.length>=3&&vi(o,t.poly))||null},r=o(1),a=o(-1);return r&&a?null:r||a?r?{normal:[-n[0],-n[1]],roomId:r.id}:{normal:n,roomId:a.id}:null}function Vr(t,e,i){return i>0&&t[0]*e[0]+t[1]*e[1]>.05}function Kr(t,e,i,s){return[[t[0],t[1]],[e[0],e[1]],[e[0]+i[0]*s,e[1]+i[1]*s],[t[0]+i[0]*s,t[1]+i[1]*s]]}function Yr(t,e){try{const i=ni([[...t.map(t=>[t[0],t[1]]),[t[0][0],t[0][1]]]],[[...e.map(t=>[t[0],t[1]]),[e[0][0],e[0][1]]]]),s=[];for(const t of i){const e=t?.[0];!Array.isArray(e)||e.length<4||s.push(e.slice(0,e.length-1).map(t=>[t[0],t[1]]))}return s}catch{return[]}}function Xr(t,e,i,s,n,o,r){if(!(s>0))return[];const a=Fr(i,n),l=[-a[0],-a[1]],c=function(t){const e=Math.min(90,Math.max(0,t));return.7*(.8+1.7*Math.pow(1-e/90,1.6))}(s),h=[];for(const i of e){if(!(i.length>0))continue;const e=Gr(i,t);if(!e||!Vr(e.normal,a,s))continue;const n=t.find(t=>t.id===e.roomId);if(!n)continue;const d=o&&o[e.roomId]||n.poly,p=i.angle*Math.PI/180,u=i.length/2,_=[-e.normal[0],-e.normal[1]],g=Math.max(0,r?.[i.id]||0),m=i.x+_[0]*g/2,f=i.y+_[1]*g/2,v=Math.cos(p)*u,y=Math.sin(p)*u,b=[m-v,f-y],w=[m+v,f+y],k=c*i.length,x=Yr(Kr(b,w,l,k),d);if(!x.length)continue;const $=l[0]*_[0]+l[1]*_[1];h.push({openingId:i.id,roomId:e.roomId,polys:x,a:b,b:w,dir:l,len:k,normal:_,depth:k*$})}return h}const Jr=t=>"number"==typeof t&&Number.isInteger(t)&&t>=0&&t<=359?t:null;function Zr(t,e){const i=Jr(e?.north_deg);return null!==i?i:Jr(t?.north_deg)}function Qr(t,e){const i=t=>"static"===t||"daynight"===t?t:null;return i(e?.bg_mode)??i(t?.bg_mode)??"static"}function ta(t,e){const i=e?.sun_rays;return"boolean"==typeof i?i:!0===t?.sun_rays}function ea(t){const e=t?.states?.["sun.sun"]?.attributes,i=Number(e?.azimuth),s=Number(e?.elevation);return Number.isFinite(i)&&Number.isFinite(s)?{azimuth:i,elevation:s}:null}const ia=["dawn","day","dusk","night"];function sa(t){if(!t)return"";const e=Er[t.phase];return[`--hp-day-cycle-outline-near:${e.outlineNear}`,`--hp-day-cycle-outline-mid:${e.outlineMid}`,`--hp-day-cycle-outline-far:${e.outlineFar}`].join(";")}function na(t,e=1){if(!t)return G;const i=[`--hp-day-cycle-sun-x:${t.sunX.toFixed(2)}%`,`--hp-day-cycle-sun-y:${t.sunY.toFixed(2)}%`,`--hp-day-cycle-sun-opacity:${t.sunOpacity.toFixed(3)}`,`opacity:${Math.min(1,Math.max(0,e)).toFixed(4)}`].join(";");return W``}houseplanContinuityTrace(){return[...this._continuityHistory,...this._continuity.trace].slice(-80).map(t=>({...t,...t.stage?{stage:[...t.stage]}:{}}))}render(){if(!this._config)return G;const t=this._snap?.config;if(!t)return this._errorCard(la(this._lang,"space_card.loading"));const e=this._config.space,i=this._renderDeviceSnapshot,s=uu({hass:i?.hass||this.hass,cfg:t,layout:this._snap?.layout||{},spaceId:e,iconSize:this._config.icon_size,stageWidth:this._stageWidth,lang:this._lang,displayUrl:t=>this._signer.display(this.hass,t),assetLoaded:this._onAssetLoaded,registry:i?{revision:i.sourceSequence,authoritative:!1,access:"limited",entities:{...i.hass.entities},devices:{...i.hass.devices},lastSuccess:i.capturedAt}:An(this.hass),devices:[...i?.devices||this._devices],presentations:i?.presentations,activityRuntime:this._activityRuntime,reducedMotion:this._reducedMotion,virtualLights:this._snap?.virtualLights,liveStates:!1!==this._config.live_states,showTemperature:!1!==this._config.show_temperature,showSignal:!1!==this._config.show_signal,inert:this._continuity.overlayBlocksInteraction});if(!s)return this._errorCard(la(this._lang,"space_card.not_found",{id:e}));const n=yc(t).find(t=>t.id===e),o=void 0!==this._config.title?this._config.title:n?.title||"",a=!1!==this._config.show_button,r=this._config.button_label||la(this._lang,"space_card.button"),l=this._continuity.overlayVisible||"recovery-error"===this._continuity.state?this._continuity.recoveryReason:null;return W` - + ${a?W`
+
`:G}
- `}}Ru.properties={hass:{attribute:!1},_config:{state:!0},_snap:{state:!0},_continuityEpoch:{state:!0}},Ru.styles=[Kt,o` + `}}Iu.properties={hass:{attribute:!1},_config:{state:!0},_snap:{state:!0},_continuityEpoch:{state:!0}},Iu.styles=[Kt,o` .hp-static-title { font-weight: 700; padding: 10px 14px 6px; @@ -4690,7 +4690,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8 text-align: center; color: var(--secondary-text-color, #9aa4ad); } - `],customElements.get("houseplan-space-card")||customElements.define("houseplan-space-card",Ru),window.customCards=window.customCards||[],window.customCards.find(t=>"houseplan-space-card"===t.type)||window.customCards.push({type:"houseplan-space-card",name:"House Plan — Space (static)",description:"Read-only live schematic of a single houseplan space, with a deep-link button.",preview:!1,documentation:"https://github.com/Matysh/houseplan-card"});const Iu=o` + `],customElements.get("houseplan-space-card")||customElements.define("houseplan-space-card",Iu),window.customCards=window.customCards||[],window.customCards.find(t=>"houseplan-space-card"===t.type)||window.customCards.push({type:"houseplan-space-card",name:"House Plan — Space (static)",description:"Read-only live schematic of a single houseplan space, with a deep-link button.",preview:!1,documentation:"https://github.com/Matysh/houseplan-card"});const Au=o` :host { --hp-editor-tray-bg-fallback: color-mix(in srgb, var(--card-background-color, var(--hp-bg)) 94%, var(--hp-line)); --hp-editor-tray-bg: color-mix(in srgb, var(--card-background-color, var(--hp-bg)) 86%, transparent); @@ -4861,7 +4861,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8 .editor-secondary { transition: none; } .editor-group-launcher .group-chevron { transition: none; } } -`,Au=(t,e)=>(t.composedPath?.()||[t.target]).some(t=>(t=>!!t&&"function"==typeof t.matches)(t)&&e(t));class Fu{constructor(t){this.host=t,this._openGroupId=null,this._groupGeneration=0,this._renderedContext="",this._focusOwned=!1,this._currentModel=null,this._blocked=!1,this._dismissPointerTarget=null,this._globalDismissListening=!1,this._globalDismissGuard=t=>{this.handleOutsideDismiss(t)}}get hasOpenGroup(){return null!==this._openGroupId}get groupGeneration(){return this._groupGeneration}activeGroup(t){return this._openGroupId&&t.find(t=>t.id===this._openGroupId)||null}reset(){this._openGroupId=null,this._contentAnimation?.cancel(),this._contentAnimation=void 0,this._renderedContext="",this._focusOwned=!1,this._currentModel=null,this._blocked=!1,this._dismissPointerTarget=null,clearTimeout(this._dismissTimer),this._dismissTimer=void 0,this._syncGlobalDismissListener()}closeForNavigation(){const t="palette"===this._currentModel?.kind?this._currentModel.dismiss:void 0,e=!!this._openGroupId||!!t;this._openGroupId=null,t?.(),t&&(this._currentModel=null),this._clearDismissClick(),e&&this.host.requestUpdate(),this._syncGlobalDismissListener()}openPalette(){this._openGroupId&&this.closeGroup(!1)}toggleGroup(t,e){this._openGroupId!==e?t.some(t=>t.id===e)&&("palette"===this._currentModel?.kind&&this._currentModel.dismiss?.(),this._groupGeneration+=1,this._openGroupId=e,this.host.clearTip(),this.host.requestUpdate(),this._syncGlobalDismissListener()):this.closeGroup(!1)}closeGroup(t){const e=this._openGroupId;this._openGroupId=null,this.host.requestUpdate(),this._syncGlobalDismissListener(),t&&e&&this.host.updateComplete().then(()=>{const t=this.host.root(),i=[...t.querySelectorAll("[data-editor-group]")].find(t=>t.dataset.editorGroup===e&&null!==t.offsetParent);(i||t.querySelector(".editbar-tools"))?.focus?.()})}renderGroupLauncher(t,e,i){const s=this._openGroupId===t.id,n=t.items.find(e=>e.id===t.activeItemId&&!e.disabled);return W`
-
`}afterRender(){const t=this.host.root();this._blocked&&(this._openGroupId?this.closeGroup(!1):"palette"===this._currentModel?.kind&&this._currentModel.dismiss?.()),this._syncGlobalDismissListener();const e=t.querySelector(".editor-secondary"),i=this._renderedContext,s=e?.dataset.contextId||"";if(s&&i&&s!==i&&!window.matchMedia?.("(prefers-reduced-motion: reduce)")?.matches&&(this._contentAnimation?.cancel(),this._contentAnimation=e?.querySelector(".editor-secondary-content")?.animate([{opacity:.35,transform:"translateY(-4px)"},{opacity:1,transform:"translateY(0)"}],{duration:100,easing:"ease-out"})),this._renderedContext=s,i&&s!==i&&this._focusOwned){const i=s?e?.querySelector('[tabindex="0"], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled])'):t.querySelector(".editbar-tools");i?.focus?.(),this._focusOwned=!!s}if("palette"===this._currentModel?.kind&&this._currentModel.launcherId){const e=[...t.querySelectorAll("[data-editor-palette]")].find(t=>t.dataset.editorPalette===this._currentModel?.launcherId);e&&null!==e.offsetParent||this._currentModel.dismiss?.()}if(!this._openGroupId)return;const n=[...t.querySelectorAll("[data-editor-group]")].find(t=>t.dataset.editorGroup===this._openGroupId);n&&null!==n.offsetParent||this.closeGroup(!0)}handleOutsideDismiss(t){if(Au(t,t=>t.hasAttribute("data-editor-navigation")))return"pointerdown"===t.type?this.closeForNavigation():"click"===t.type&&this._dismissPointerTarget&&this._clearDismissClick(),!1;if("click"===t.type&&this._dismissPointerTarget){return!!(t.composedPath?.()||[t.target]).includes(this._dismissPointerTarget)&&(this._clearDismissClick(),t.preventDefault(),t.stopImmediatePropagation(),!0)}const e=this._openGroupId||this._blocked||"palette"!==this._currentModel?.kind?null:this._currentModel;if("pointerdown"===t.type&&(this._openGroupId||e)){const i=Au(t,t=>t.classList.contains("editor-secondary")),s=Au(t,t=>!!t.dataset.editorGroup),n=Au(t,t=>!!t.dataset.editorPalette),o=Au(t,t=>t.classList.contains("stage"));if(!(i||s||n||"stay-open-on-canvas"===e?.dismissPolicy&&o))return t.preventDefault(),t.stopImmediatePropagation(),this._dismissPointerTarget=t.target,clearTimeout(this._dismissTimer),this._dismissTimer=window.setTimeout(()=>{this._clearDismissClick()},800),this._openGroupId?this.closeGroup(!1):e?.dismiss?.(),this._syncGlobalDismissListener(),!0}return!1}_activateGroupItem(t,e,i){if(t.id!==this._openGroupId)return;const s=t.items.find(t=>t.id===e);if(!s||s.disabled)return;const n="toggle"===s.role&&"stay-open"===s.closePolicy,o=0===i.detail;n||(this._openGroupId=null,this.host.requestUpdate(),this._syncGlobalDismissListener()),s.invoke(),!n&&o&&this.host.updateComplete().then(()=>{const e=[...this.host.root().querySelectorAll("[data-editor-group]")].find(e=>e.dataset.editorGroup===t.id&&null!==e.offsetParent);e?.focus()})}_groupKeydown(t){if(!["ArrowLeft","ArrowRight","Home","End"].includes(t.key))return;const e=[...t.currentTarget.querySelectorAll(".editor-group-item:not([disabled])")];if(!e.length)return;t.preventDefault();const i=e.indexOf(this.host.root().activeElement),s="Home"===t.key?0:"End"===t.key?e.length-1:"ArrowLeft"===t.key?i<=0?e.length-1:i-1:(i+1)%e.length;e[s]?.focus()}_clearDismissClick(){this._dismissPointerTarget=null,clearTimeout(this._dismissTimer),this._dismissTimer=void 0,this._syncGlobalDismissListener()}_syncGlobalDismissListener(){const t=!this._blocked&&"palette"===this._currentModel?.kind,e=!!this._openGroupId||t||!!this._dismissPointerTarget;e!==this._globalDismissListening&&(this._globalDismissListening=e,e?(window.addEventListener("pointerdown",this._globalDismissGuard,!0),window.addEventListener("click",this._globalDismissGuard,!0)):(window.removeEventListener("pointerdown",this._globalDismissGuard,!0),window.removeEventListener("click",this._globalDismissGuard,!0)))}}const Eu=t=>t.stopPropagation(),zu=4.166666666666667e-9;function Ou(t){return Number.isFinite(t)?Math.round(t/xc)*xc:t}const Nu=(t,e,i,s)=>Math.hypot(i-t,s-e),Hu=(t,e,i,s,n,o,r,a)=>Math.hypot(Math.max(Math.abs(n-t),Math.abs(n+r-(t+i))),Math.max(Math.abs(o-e),Math.abs(o+a-(e+s)))),Lu=(t,e,i,s,n,o,r)=>{const a=Math.max(Number(s)||0,0)/2,l=Math.PI/180,c=Math.cos(i*l)*a,h=Math.sin(i*l)*a,d=Math.cos(r*l)*a,p=Math.sin(r*l)*a,u=Math.max(Nu(t+c,e+h,n+d,o+p),Nu(t-c,e-h,n-d,o-p)),_=Math.max(Nu(t+c,e+h,n-d,o-p),Nu(t-c,e-h,n+d,o+p));return Math.min(u,_)},Bu=t=>{const e=Number(t?.cell_cm);return e>0?e:5};const qu=10**9;function Wu(t){if(Array.isArray(t))return t.map(t=>Wu(t));if(null!==t&&"object"==typeof t){const e={};for(const[i,s]of Object.entries(t))e[i]=Wu(s);return e}return t}function ju(t){if("number"!=typeof t||!Number.isFinite(t))return t;const e=(t<0||Object.is(t,-0)?-1:1)*(Math.floor(Math.abs(t)*qu+.5)/qu);return 0===e?0:e}function Uu(t){return null===t||"object"!=typeof t||Array.isArray(t)?null:t}function Gu(t){return Array.isArray(t)?t.filter(t=>null!==Uu(t)):[]}function Vu(t,e){for(const i of e)Object.prototype.hasOwnProperty.call(t,i)&&(t[i]=ju(t[i]))}function Ku(t){if(Array.isArray(t))for(let e=0;eArray.isArray(t)&&t.length>=2&&Number.isFinite(t[0])&&Number.isFinite(t[1]),e_=(t,e)=>Math.hypot(t[0]-e[0],t[1]-e[1]);function i_(t,e,i){const s=i[0]-e[0],n=i[1]-e[1],o=s*s+n*n;if(o<=0)return e_(t,e);let r=((t[0]-e[0])*s+(t[1]-e[1])*n)/o;return r=Math.max(0,Math.min(1,r)),Math.hypot(t[0]-(e[0]+s*r),t[1]-(e[1]+n*r))}function s_(t,e,i,s,n){for(const s of e)if(s&&!i.has(s.id)&&t_(s.a)&&t_(s.b)&&(e_(t,s.a)<=n||e_(t,s.b)<=n))return!0;for(const e of s?.roomPolygons||[])for(let i=0;i0&&a>0))return null;if(Math.abs(n[0]/r*(o[1]/a)-n[1]/r*(o[0]/a))>i)return null;for(const[i,n]of[[t.a,e.a],[t.a,e.b],[t.b,e.a],[t.b,e.b]])if(e_(i,n)<=s)return[(i[0]+n[0])/2,(i[1]+n[1])/2];return null}function o_(t,e){const i=.05*(Number(e.pitch)>0?Number(e.pitch):1),s=new Map;let n=(t||[]).filter(t=>!!t&&"string"==typeof t.id&&t_(t.a)&&t_(t.b));if(n.length<2)return{partitions:[...t||[]],merged:0,openingMoves:[]};const o=e.seedIds&&e.seedIds.length?new Set(e.seedIds):null;let r=0;for(let t=0;te_(e,t.at)>i);let h=c[0]??a.a,d=c[c.length-1]??l.b;if(c.length<2&&(h=a.a,d=l.b),d[0]0?(d[0]-h[0])/u:0,g=u>0?(d[1]-h[1])/u:0,m=t=>u>0?((t[0]-h[0])*_+(t[1]-h[1])*g)/u:0;for(const t of[a,l]){const e=m(t.a),i=m(t.b)-e;for(const[n,o]of s)o.toId===t.id&&s.set(n,{fromId:o.fromId,toId:p.id,base:e+o.base*i,span:o.span*i});s.set(t.id,{fromId:t.id,toId:p.id,base:e,span:i})}o&&o.add(p.id),n=n.filter((e,i)=>i!==t.i&&i!==t.j),n.splice(t.i,0,p),r++}return{partitions:n,merged:r,openingMoves:[...s.values()]}}function r_(t,e,i,s){if(!t?.length||!i.length)return 0;const n=new Map(i.map(t=>[t.fromId,t]));let o=0;for(const i of t){const t=i?.host;if(!t||"partition"!==t.kind)continue;const r=n.get(t.id);if(!r)continue;i.host={...t,id:r.toId,t:Qu(t.t,r)},o++;const a=Pd(i,e,s.coordScale,s.cellCm,s.gridPitch).resolved;a&&Object.assign(i,zd(i,a,s.coordScale))}return o}function a_(t,e){const i=e?.excludeDraftId||null;return{roomPolygons:(t?.rooms||[]).map(t=>hi(t)).filter(t=>!!t),columns:t?.wall_columns||[],draftEnds:(t?.room_drafts||[]).flatMap(t=>{if(i&&t?.id===i)return[];const e=t?.points||[];return e.length?[e[0],e[e.length-1]]:[]})}}const l_=t=>JSON.parse(JSON.stringify(t)),c_=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),h_=(t,e)=>e.length>0&&e.length<=35&&("space"===t?/^[a-z0-9_-]+$/.test(e):/^[A-Za-z0-9_-]+$/.test(e)),d_=(t,e,i)=>{const s=t.get(e)||[];s.push(i),t.set(e,s)};const p_=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),u_=(t,e,i)=>Math.min(i,Math.max(e,t)),__=t=>vc({spaces:[t]})[0],g_=(t,e,i)=>{const s=i>0?i:1,n=t=>`${(t[0]/s).toFixed(12)},${(t[1]/s).toFixed(12)}`,o=n(t),r=n(e);return o0?r:1,l=Math.max(s*a*.02,1e-9),c=[];for(const e of t||[])for(const t of hi(e)||[])c.push([t[0],t[1]]);for(const t of i||[])Array.isArray(t)&&t.length>=4&&t.slice(0,4).every(Number.isFinite)&&c.push([t[0],t[1]],[t[2],t[3]]);const h=t=>c.some(e=>Math.hypot(t[0]-e[0],t[1]-e[1])<=2*l),d=new Map;for(const r of t||[]){if(!r?.id)continue;const c=hl(t,r.id,e,i,s,n,o,a);if(c)for(let t=0;t0&&p>0&&r===u&&p!==r))continue;const _=c.poly[s],g=c.poly[(s+1)%c.poly.length],m=Math.hypot(g[0]-_[0],g[1]-_[1]);if(!(m>l&&m<.5*o-1e-9*o))continue;if(h(_)||h(g))continue;const f=g_(_,g,a),v=d.get(f);v?v.targets.add(r):d.set(f,{a:[_[0],_[1]],b:[g[0],g[1]],targets:new Set([r])})}}}let p=e.slice();const u=(t,e)=>Math.hypot(t[0]-e[0],t[1]-e[1])<=2*l,_=(t,e)=>{if(!Array.isArray(t.a)||!Array.isArray(t.b)||t.a.length<2||t.b.length<2)return!1;const i=[Number(t.a[0])*a,Number(t.a[1])*a],s=[Number(t.b[0])*a,Number(t.b[1])*a];return!![...i,...s].every(Number.isFinite)&&(u(i,e.a)&&u(s,e.b)||u(i,e.b)&&u(s,e.a))};for(const t of[...d.values()].filter(t=>1===t.targets.size).sort((t,e)=>g_(t.a,t.b,a).localeCompare(g_(e.a,e.b,a)))){const e=[...t.targets][0],i=p.filter(e=>_(e,t));if(new Set(i.map(t=>t.cm)).size>1)continue;let n=!1;p=p.map(i=>_(i,t)?(n=!0,i.cm===e?i:{...i,cm:e}):i),n||(p=Na(p,t.a,t.b,e,s,a))}return p}const f_=t=>{const e=[];for(const i of t||[]){const t=hi(i);if(t?.length)for(let i=0;i"string"==typeof t?.id?t.id:"").filter(Boolean),h=new Set(c),d=new Map;for(const t of c){const e=/^space_(.+)_([0-9a-f]{8})$/.exec(t);e&&d_(d,e[1],t)}const p=new Map,u=new Map,_=new Map;for(const t of a){const e="string"==typeof t?.id?t.id:"";if(!e)continue;const i=new Map;for(const s of Array.isArray(t.rooms)?t.rooms:[]){const t="string"==typeof s?.id?s.id:"";if(!t)continue;const n=/^room_(.+)_([0-9a-f]{8})$/.exec(t);n&&d_(i,n[1],t),u.has(t)||u.set(t,e);const o="string"==typeof s.area?s.area:"";if(o){const i=_.get(o)||[];i.push({spaceId:e,roomId:t}),_.set(o,i)}}p.set(e,i)}const g=new Set(u.keys()),m=new Set,f=new Set;for(const t of l)"string"==typeof t?.id&&t.id&&(!0===t.removed?f:m).add(t.id);const v={spaceRefsRemapped:0,roomRefsRemapped:0,positionsRemapped:0,markersDetached:0,positionsUnresolved:0,nestedRefsUnresolved:0,deadSpaceIds:[]},y=new Set,b=t=>h.has(t)||!h_("space",t)?null:1===d.get(t)?.length?d.get(t)[0]:null,w=(t,e)=>{if(!h_("room",t))return null;const i=p.get(e)?.get(t)||[];return 1===i.length?i[0]:null},k=t=>{const e=i.effectiveAreaByMarker?.[t]||"",s=e&&_.get(e)||[];return 1===s.length?s[0]:null},x=(t,e,i)=>{if("string"==typeof t.room_id&&t.room_id&&!g.has(t.room_id)){const s=e?w(t.room_id,e):null;s?(t.room_id=s,v.roomRefsRemapped++):i?(t.room_id=i.roomId,v.roomRefsRemapped++):!0!==t.removed&&delete t.room_id}const s=t.vacuum?.segment_map;if(s&&"object"==typeof s&&!Array.isArray(s))for(const t of Object.keys(s)){const i=s[t];if("string"!=typeof i||!i||g.has(i))continue;const n=e?w(i,e):null;n?(s[t]=n,v.roomRefsRemapped++):v.nestedRefsUnresolved++}};for(const t of l){const e="string"==typeof t?.id?t.id:"";if(!e)continue;const i="string"==typeof t.space?t.space:"",s=i&&!h.has(i),o=n[e],r="string"==typeof o?.s?o.s:"",a=r&&!h.has(r),l=!0===t.removed;let c=i&&h.has(i)?i:null,d=null,p=!1;if(s){const s=b(i);s?(t.space=s,c=s,p=!0,v.spaceRefsRemapped++):l||"virtual"===t.binding?l||(delete t.space,c=null,v.markersDetached++):(d=k(e),d?(t.space=d.spaceId,c=d.spaceId,v.spaceRefsRemapped++):(delete t.space,c=null,v.markersDetached++))}l&&!p||x(t,c,d),a&&(p&&r===i&&c?(n[e]={...o,s:c},v.positionsRemapped++,y.add(e)):l||(delete n[e],y.add(e)))}for(const t of Object.keys(n)){if(y.has(t))continue;const e=n[t],i="string"==typeof e?.s?e.s:"";if(!i||h.has(i))continue;const s=b(i);if(s){if(t.startsWith("rl_")){const i=t.slice(3),o=w(i,s);if(o){const i=`rl_${o}`;c_(n,i)||(n[i]={...e,s:s}),delete n[t],v.roomRefsRemapped++,v.positionsRemapped++;continue}}n[t]={...e,s:s},v.positionsRemapped++}}const $=new Set;for(const t of l){const e="string"==typeof t?.space?t.space:"";e&&!h.has(e)&&$.add(e)}for(const[t,e]of Object.entries(n)){const i="string"==typeof e?.s?e.s:"";i&&!h.has(i)&&($.add(i),m.has(t)&&!f.has(t)||v.positionsUnresolved++)}return v.deadSpaceIds=[...$].sort((t,e)=>t.localeCompare(e)),{config:s,layout:n,report:v,changed:JSON.stringify(s)!==o||JSON.stringify(n)!==r}}(t,e,i),n=s.config,o=JSON.stringify(t||{}),r=JSON.stringify(e||{}),a=Number.isInteger(Number(n.model_version))?Number(n.model_version):0,l=(t=>{let e=0,i=0,s=0;for(const i of t.markers||[]){if("ripple"===i.display&&(i.display="icon_ripple",e++),Array.isArray(i.controls)){const t="string"==typeof i.binding&&i.binding.startsWith("entity:")?i.binding.slice(7):"",s=t?i.controls.filter(e=>e!==t):i.controls;JSON.stringify(s)!==JSON.stringify(i.controls)&&(i.controls=s.length?s:null,e++)}const t=i.vacuum;t&&p_(t,"trail")&&(["never","cleaning","always"].includes(t.trail_mode)||(t.trail_mode=!1===t.trail?"never":"cleaning"),delete t.trail,e++)}for(const n of t.spaces||[]){const t=n.settings;"glow"===t?.fill_mode&&("boolean"!=typeof t.glow_enabled&&(t.glow_enabled=!0),t.fill_mode="none",e++,i++);for(const t of n.rooms||[]){const i=t.settings;"glow"===i?.fill_mode&&("boolean"!=typeof i.glow&&(i.glow=!0),delete i.fill_mode,e++,s++)}if(p_(n,"segments")&&(delete n.segments,e++),p_(n,"plan_scale")){const t=Number(n.plan_scale);Number.isFinite(t)&&t>=_c&&t<=gc&&(p_(n,"plan_scale_x")||(n.plan_scale_x=t),p_(n,"plan_scale_y")||(n.plan_scale_y=t),delete n.plan_scale,e++)}const o=Number(n.cell_cm);p_(n,"cell_cm")&&(!Number.isFinite(o)||o<.1||o>1e3)&&(n.cell_cm=Number.isFinite(o)&&o>0?u_(o,.1,1e3):5,e++);const r=Number(n.cell_cm),a=Number.isFinite(r)&&r>0?r:5;for(const t of n.wall_columns||[])if("circle"===t.shape)p_(t,"angle")&&(delete t.angle,e++);else if("square"===t.shape&&p_(t,"angle")){const i=((Number(t.angle)||0)%90+90)%90;t.angle!==i&&(t.angle=i,e++)}for(const t of n.decor||[]){if(p_(t,"width")){const i=Number(t.width);(p_(t,"width_cm")||Number.isFinite(i))&&(p_(t,"width_cm")||(t.width_cm=Number(u_(i/kc*a,.1,100).toFixed(6))),delete t.width,e++)}if("rect"!==t?.kind&&"ellipse"!==t?.kind||!0!==t.fill||(p_(t,"fill_color")||(t.fill_color=t.color||"#607d8b",e++),p_(t,"fill_opacity")||(t.fill_opacity=.25,e++)),"text"!==t?.kind)continue;void 0===t.size_cm?(t.size_cm=Number(u_(es*is(t)/kc*a,.1,2e3).toFixed(6)),delete t.scale,delete t.size,e++):(p_(t,"scale")||p_(t,"size"))&&(delete t.scale,delete t.size,e++);let i=String(t.text??"");const s=[...i.matchAll(/\{([^{}\r\n]+)\}/g)].some(t=>!!Yi(t[1]));if(!(p_(t,"entity")||p_(t,"attr")||p_(t,"unit")))continue;const n=String(t.unit??"").trim(),o="state"===String(t.attr??"").trim().toLowerCase()?null:t.attr,r=s||n?"":Xi(t.entity,o);if(s||r){if(r){const e=i.indexOf("{}");i=e>=0?i.slice(0,e)+r+i.slice(e+2):`${i}${i?" ":""}${r}`,t.text=i}delete t.entity,delete t.attr,delete t.unit,e++}}}return{total:e,glowSpaces:i,glowRooms:s}})(n);let c=l.total;for(const t of n.spaces||[]){const e=__(t);if(!e)continue;if(!rh(t.open_spans).length){const i=dh(e.rooms,null,pc,.02*kc,!0);i.length&&(t.open_spans=ph(i,pc),c++)}}const h=(d=n.spaces||[],JSON.parse(JSON.stringify(d)));var d;const p=function(t,e){const i=JSON.parse(JSON.stringify(t||[])),s=JSON.parse(JSON.stringify(e||{}));let n=0,o=0,r=0,a=0,l="",c=0,h=0,d=0;const p=(t,e)=>{Number.isFinite(t)&&Number.isFinite(e)&&t!==e&&Math.abs(e-t)<=zu&&h++},u=(t,e)=>{p(t[0],e[0]),p(t[1],e[1])},_={};let g=5;for(const t of i){const e=Bu(t);null!=t?.id&&(_[String(t.id)]=e),e>g&&(g=e)}const m=(t,e,i,s=!1)=>{if(!(t>zu||s))return;n++,t>r&&(r=t);const o=t*wc*e;o>a&&(a=o,l=i)};for(const t of i){const e=Bu(t),i=null!=t?.id?String(t.id):"";for(const s of t.rooms||[]){o++;let t=0;if(s.poly?.length)s.poly=s.poly.map(e=>{const i=[Ou(e[0]),Ou(e[1])];return t=Math.max(t,Nu(e[0],e[1],i[0],i[1])),u(e,i),i});else if(null!=s.x&&null!=s.y){const e=s.x,i=s.y,n=s.w||0,o=s.h||0,r=Ou(e+n),a=Ou(i+o),l=Ou(e),c=Ou(i),h=Math.max(xc,r-l),d=Math.max(xc,a-c);t=Hu(e,i,n,o,l,c,h,d),s.x=l,s.y=c,s.w=h,s.h=d,p(e,l),p(i,c),p(e+n,l+h),p(i+o,c+d)}m(t,e,i)}for(const s of t.room_drafts||[]){o++;let t=0;const n=s.points||[],r=n.map(e=>{const i=[Ou(e[0]),Ou(e[1])];return t=Math.max(t,Nu(e[0],e[1],i[0],i[1])),i}),a=r.length?[r[0]]:[],l=r.length?[[n[0],r[0]]]:[],c=[];for(let t=0;t+1=2)for(const[t,e]of l)u(t,e);m(t,e,i)}if(Array.isArray(t.room_drafts)){const e=t.room_drafts.length;t.room_drafts=t.room_drafts.filter(t=>t.points?.length>=2),d+=e-t.room_drafts.length,t.room_drafts.length||delete t.room_drafts}for(const s of t.partitions||[]){o++;const n=[s.a[0],s.a[1]],r=[s.b[0],s.b[1]],a=[Ou(n[0]),Ou(n[1])],l=[Ou(r[0]),Ou(r[1])];let c=Math.max(Nu(n[0],n[1],a[0],a[1]),Nu(r[0],r[1],l[0],l[1]));const h=Nu(a[0],a[1],l[0],l[1]),d=(t.openings||[]).filter(t=>"partition"===t.host?.kind&&t.host.id===s.id).every(t=>{const e=Number(t.length),i=Number(t.host.t),s=i*h;return Number.isFinite(e)&&e>0&&Number.isFinite(i)&&i>=0&&i<=1&&s-e/2>=-zu&&s+e/2<=h+zu});h>zu&&d?(s.a=a,s.b=l,u(n,a),u(r,l)):c=0,m(c,e,i)}for(const s of t.wall_columns||[]){o++;const t=[s.center[0],s.center[1]],n=[Ou(t[0]),Ou(t[1])],r=Nu(t[0],t[1],n[0],n[1]);s.center=n,u(t,n),m(r,e,i)}for(const s of t.decor||[]){o++;let t=0;if("line"===s.kind){const e=[s.x1,s.y1],i=[s.x2,s.y2],n=[Ou(e[0]),Ou(e[1])],o=[Ou(i[0]),Ou(i[1])];t=Math.max(Nu(e[0],e[1],n[0],n[1]),Nu(i[0],i[1],o[0],o[1])),s.x1=n[0],s.y1=n[1],s.x2=o[0],s.y2=o[1],u(e,n),u(i,o)}else{const e=s.x,i=s.y,n=s.w,o=s.h,r=Ou(e),a=Ou(i);if(null!=s.w&&null!=s.h){const l=Ou(e+n),c=Ou(i+o),h=Math.max(xc,l-r),d=Math.max(xc,c-a);t=Hu(e,i,n,o,r,a,h,d),s.w=h,s.h=d,p(e+n,r+h),p(i+o,a+d)}else t=Nu(e,i,r,a);s.x=r,s.y=a,p(e,r),p(i,a)}m(t,e,i)}for(const s of t.openings||[]){if(o++,"partition"===s.host?.kind){const n=(t.partitions||[]).find(t=>t.id===s.host.id),o=Number(s.host.t);if(!n||!Number.isFinite(o)||o<0||o>1)continue;const r=n.b[0]-n.a[0],a=n.b[1]-n.a[1];if(Math.hypot(r,a)<=zu)continue;const l=n.a[0]+r*o,h=n.a[1]+a*o;let d=180*Math.atan2(a,r)/Math.PI;d>=90?d-=180:d<-90&&(d+=180);const p=Number(s.angle),u=!(Number.isFinite(p)&&p===d),_=Lu(s.x,s.y,Number.isFinite(p)?p:d,Number(s.length)||0,l,h,d);s.x=l,s.y=h,s.angle=d,u&&c++,m(_,e,i,u);continue}const n=ui([s.x,s.y],t.rooms||[],.025,{step:xc,length:Number(s.length)||0});if(!n)continue;const r=Number(s.angle),a=!(Number.isFinite(r)&&r===n.angle),l=Lu(s.x,s.y,Number.isFinite(r)?r:n.angle,Number(s.length)||0,n.x,n.y,n.angle);s.x=n.x,s.y=n.y,s.angle=n.angle,a&&c++,m(l,e,i,a)}}for(const[t,e]of Object.entries(s)){if(!e||"object"!=typeof e)continue;const i=e;if("number"!=typeof i.x||"number"!=typeof i.y)continue;o++;const n=Ou(i.x),r=Ou(i.y),a=Nu(i.x,i.y,n,r);s[t]={...i,x:n,y:r},p(i.x,n),p(i.y,r);const l="string"==typeof i.s?i.s:"";m(a,_[l]??g,l)}return{spaces:i,layout:s,report:{moved:n,coordsCanonicalized:h,total:o,maxShift:r,maxShiftCm:a,maxSpace:l,rotated:c,removedDrafts:d},changed:n>0||h>0}}(n.spaces||[],s.layout);n.spaces=p.spaces;const u={...p.report};let _=0,g=0,m=0,f=0;for(let t=0;t[t.id,t.open_to||[]]),walls:e.walls||[]}),o=__(e),r=__(i);if(!o||!r)continue;const a=f_(o.rooms),l=f_(r.rooms),c=.02*kc;let d=bh(rh(e.open_spans),a,l,pc);const p=d.length;d=yh(d,r.rooms,pc,c),d=d.map(t=>{const e=nh(t,pc),s=[e[0],e[1]],n=[e[2],e[3]],o=[(e[0]+e[2])/2,(e[1]+e[3])/2],r=e[2]-e[0],a=e[3]-e[1],h=Math.hypot(r,a)||1,d=l.map(([t,e])=>[t[0],t[1],e[0],e[1]]).filter(t=>{const e=t[2]-t[0],i=t[3]-t[1],l=Math.hypot(e,i)||1;return Math.abs(r*i-a*e)/(h*l)<=1e-6&&ah(o,t).d<=4*c&&ah(s,t).d<=4*c&&ah(n,t).d<=4*c}).sort((t,e)=>Math.hypot(e[2]-e[0],e[3]-e[1])-Math.hypot(t[2]-t[0],t[3]-t[1]))[0];if(u.total++,!d)return t;const p=[[d[0],d[1]],[d[2],d[3]]],_=ch(s,d,p,kc,2*c),g=ch(n,d,p,kc,2*c);if(Math.hypot(g[0]-_[0],g[1]-_[1])<.5*kc)return t;const m=Math.max(Math.hypot(_[0]-s[0],_[1]-s[1]),Math.hypot(g[0]-n[0],g[1]-n[1]));if(m>1e-6*kc){u.moved++;const t=m/pc;t>u.maxShift&&(u.maxShift=t);const e=m/kc*(Number(i.cell_cm)>0?Number(i.cell_cm):5);e>u.maxShiftCm&&(u.maxShiftCm=e,u.maxSpace=String(i.id||""))}return sh(_,g,pc)}),d=yh(d,r.rooms,pc,c),g+=Math.max(0,p-d.length);const v=d.map(t=>nh(t,pc));d.length?i.open_spans=d:delete i.open_spans,uh(i.rooms||[],r.rooms,v,c);const y=Array.isArray(e.walls)?e.walls.length:0;let b=Oa(e.walls,a,l,xc,pc);b=m_(r.rooms,b,v,xc,Number(i.cell_cm)>0?Number(i.cell_cm):5,kc,pc),b=ul(r.rooms,b,v,xc,Number(i.cell_cm)>0?Number(i.cell_cm):5,kc,pc),b=Ea(b,i.rooms||[],xc,1,v.map(t=>[t[0]/pc,t[1]/pc,t[2]/pc,t[3]/pc])),_+=Math.max(0,y-b.length),b.length?i.walls=b:delete i.walls;const w=o_(i.partitions||[],{pitch:xc,geometry:a_(i)});w.merged&&(m+=w.merged,i.partitions=w.partitions,r_(i.openings,i.partitions,w.openingMoves,{coordScale:pc,cellCm:Number(i.cell_cm)>0?Number(i.cell_cm):5,gridPitch:kc}));const k=JSON.stringify({spans:i.open_spans||[],links:(i.rooms||[]).map(t=>[t.id,t.open_to||[]]),walls:i.walls||[]});k!==s&&f++}const v=Zu(n),y=Ju(p.layout),b=JSON.stringify(v)!==o||JSON.stringify(y)!==r;a<7&&b&&(v.model_version=7);const w=JSON.stringify(v)!==o||JSON.stringify(y)!==r,k=Number.isInteger(Number(v.model_version))?Number(v.model_version):a,x=w?u:{...u,moved:0,coordsCanonicalized:0,maxShift:0,maxShiftCm:0,maxSpace:"",rotated:0,removedDrafts:0},$=w?s.report:{...s.report,spaceRefsRemapped:0,roomRefsRemapped:0,positionsRemapped:0,markersDetached:0};return{config:v,layout:y,report:{...x,modelFrom:a,modelTo:k,migrated:w?c:0,glowSpacesMigrated:w?l.glowSpaces:0,glowRoomsMigrated:w?l.glowRooms:0,canonicalized:w?f:0,wallsMerged:w?_:0,spansMerged:w?g:0,partitionsMerged:w?m:0,...$},changed:w}}function y_(t,e,i){const s=(t?.spaces||[]).find(t=>t?.id===i),n=new Set((s?.rooms||[]).map(t=>String(t?.id||"")).filter(Boolean)),o=[...new Set((t?.markers||[]).filter(t=>!0!==t?.removed&&"string"==typeof t?.id).filter(t=>t.space===i||"string"==typeof t.room_id&&n.has(t.room_id)||e?.[t.id]?.s===i).map(t=>t.id))].sort((t,e)=>t.localeCompare(e));return{markerIds:o,count:o.length}}function b_(t,e,i=kc,s=1e3){return dh(e.rooms,t?.open_spans,s,.02*i)}function w_(t,e,i=kc){if(!e.length)return[];const s=t.filter(t=>t?.id),n=.02*i,o=[];for(let t=0;t{const e=[(t[0]+t[2])/2,(t[1]+t[3])/2];return h.some(t=>Hs(e,t)<4*n)}).map(t=>[...t]);d.length&&o.push({a:r,b:a,segs:d})}return o}function k_(t,e,i,s=kc,n=1e3){return(Array.isArray(t?.openings)?t.openings:[]).flatMap(t=>{const o={...t,rx:Number(t.x)*n,ry:Number(t.y)*n,rlen:Number(t.length)*n};if(!t.host)return[o];const r=Pd(t,e.partitions,n,i,s);return r.resolved?[{...t,rx:r.resolved.center[0],ry:r.resolved.center[1],rlen:r.resolved.length,angle:r.resolved.angle,partitionHost:r.resolved}]:[]})}function x_(t,e=()=>!0){return t.flatMap(t=>t.host&&t.partitionHost&&e(t)?[Ad(t.partitionHost)]:[])}function $_(t,e,i,s,n,o,r=kc,a=1e3){const l=dl(e.rooms,[...i],s,n,o,r,a);return t.flatMap(t=>{const e={x:t.rx,y:t.ry,angle:Number(t.angle)||0,length:t.rlen};return t.host?t.partitionHost&&Ed(t.partitionHost,l,2e-4*r)?[e]:[]:[e]})}function S_(t,e){const i=xc,s=kc,n=pc,o=Number.isFinite(Number(e.cellCm))&&Number(e.cellCm)>0?Number(e.cellCm):5,r=Array.isArray(t?.walls)?t.walls:[],a=b_(t,e,s,n),l=w_(e.rooms,a,s).flatMap(t=>t.segs),c=k_(t,e,o,s,n),h=x_(c),d=Xl(e,o,s,2e-4*s,h).all;return{space:e,walls:r,openCuts:l,openings:c,roomOpenings:$_(c,e,r,l,i,o,s,n),partitionCuts:h,physicalBodies:d,wallKeyPitch:i,cellCm:o,gridPitch:s,coordScale:n}}function M_(t,e,i){const s="string"==typeof t?.title?t.title.trim():"",n=null==t?.id?"":String(t.id).trim();return{spaceId:n,displayName:s||n||i(e+1)}}class C_{constructor(t=50){this._undo=[],this._redo=[],this._limit=Math.max(30,Math.floor(t))}get canUndo(){return this._undo.length>0}get canRedo(){return this._redo.length>0}get undoName(){return this._undo[this._undo.length-1]?.name??null}get redoName(){return this._redo[this._redo.length-1]?.name??null}get size(){return this._undo.length}push(t){this._undo.push(t),this._undo.length>this._limit&&this._undo.splice(0,this._undo.length-this._limit),this._redo=[]}undo(){const t=this._undo.pop()??null;return t&&this._redo.push(t),t}redo(){const t=this._redo.pop()??null;return t&&this._undo.push(t),t}clear(){this._undo=[],this._redo=[]}}const D_=new WeakMap;const T_=(t,e,i)=>255===t[i+3]&&e.every((e,s)=>Math.abs(t[i+s]-e)<=2);async function P_(t){const e=t.defaultView;if(!e||!e.CSS?.supports?.("mix-blend-mode","screen"))return!1;const i=[128,32,16],s=[16,64,128],n=[9,19,29],o=`\n \n \n \n \n \n `,r=e.URL.createObjectURL(new Blob([o],{type:"image/svg+xml"}));try{const o=await new Promise((t,i)=>{const s=new e.Image,n=e.setTimeout(()=>i(new Error("SVG blend probe timeout")),1e3);s.onload=()=>{e.clearTimeout(n),t(s)},s.onerror=()=>{e.clearTimeout(n),i(new Error("SVG blend probe failed"))},s.src=r}),a=t.createElement("canvas");a.width=4,a.height=1;const l=a.getContext("2d",{willReadFrequently:!0});if(!l)return!1;l.drawImage(o,0,0,4,1);const c=l.getImageData(0,0,4,1).data;return T_(c,i,0)&&T_(c,function(t,e){return[0,1,2].map(i=>Math.round(255-(255-t[i])*(255-e[i])/255))}(i,s),4)&&T_(c,s,8)&&T_(c,n,12)}catch{return!1}finally{e.URL.revokeObjectURL(r)}}const R_={now:()=>performance.now(),requestFrame:t=>requestAnimationFrame(t),cancelFrame:t=>cancelAnimationFrame(t)},I_=t=>Math.max(0,Math.min(1,t)),A_=(t,e,i)=>t+(e-t)*i,F_=(t,e,i)=>{const s=1-t;return 3*s*s*t*e+3*s*t*t*i+t*t*t};function E_(t,e){return{centerX:t.x+t.w/2,centerY:t.y+t.h/2,pixelsPerUnit:e>0&&t.w>0?e/t.w:1,viewBox:{...t}}}function z_(t,e,i){const s=Math.max(1e-9,t.pixelsPerUnit),n=Math.max(1e-9,e/s),o=Math.max(1e-9,i/s);return{x:t.centerX-n/2,y:t.centerY-o/2,w:n,h:o}}function O_(t){const e=t.trim(),i=/^rgba?\(\s*([\d.]+)[, ]+([\d.]+)[, ]+([\d.]+)(?:\s*[,/]\s*([\d.]+))?\s*\)$/i.exec(e);if(i)return[Number(i[1]),Number(i[2]),Number(i[3]),null==i[4]?1:Number(i[4])];const s=/^#([0-9a-f]{6}|[0-9a-f]{8})$/i.exec(e)?.[1];return s?[parseInt(s.slice(0,2),16),parseInt(s.slice(2,4),16),parseInt(s.slice(4,6),16),8===s.length?parseInt(s.slice(6,8),16)/255:1]:null}function N_(t,e,i){const s=O_(t),n=O_(e);if(!s||!n)return i<.5?t:e;const o=I_(i);return`rgba(${Math.round(A_(s[0],n[0],o))}, ${Math.round(A_(s[1],n[1],o))}, ${Math.round(A_(s[2],n[2],o))}, ${A_(s[3],n[3],o).toFixed(3)})`}function H_(t,e,i){const s=(t=>{const e=I_(t);if(0===e||1===e)return e;let i=0,s=1,n=e;for(let t=0;t<12;t++)n=(i+s)/2,F_(n,.2,.2){const e=this._state;if(!e||e.token!==n)return;const i=I_((t-e.startedAt)/e.duration);e.presented=i>=1?e.to:H_(e.from,e.to,i),e.phase=i>=1?"settling":"running",this._hooks.frame(e),i<1?this._raf=this._clock.requestFrame(r):(this._raf=0,this._hooks.settled(e),this._state?.token===n&&(this._state=null))};return this._raf=this._clock.requestFrame(r),n}cancel(t=!0){this._raf&&this._clock.cancelFrame(this._raf),this._raf=0;const e=this._state;this._state=null,this._token++,e&&t&&(e.phase="settling",e.presented=e.to,this._hooks.frame(e),this._hooks.settled(e))}dispose(){this.cancel(!1)}}const B_="houseplan_card_labs_v1",q_=Object.freeze([Object.freeze({id:"iso",issue:89,since:"1.62.0",expires:"1.65.0",summary:"Volumetric plan renderer"})]);function W_(t){const e=/^(\d+)\.(\d+)\.(\d+)(?:-[0-9A-Za-z.-]+)?$/.exec(String(t||"").trim());if(!e)return null;const i=e.slice(1).map(Number);return i.every(t=>Number.isSafeInteger(t))?i:null}function j_(t,e){for(let i=0;i<3;i++)if(t[i]!==e[i])return t[i]t.split(",")).map(t=>t.trim()).filter(Boolean)}function X_(t,e,i,s=q_){const n=function(t,e=q_){const i=W_(t),s=new Map;if(!i||!G_(e))return s;for(const t of e){const e=W_(t.since),n=W_(t.expires);j_(i,e)>=0&&j_(i,n)<0&&s.set(t.id,t)}return s}(i,s),o=new Set(G_(s)?s.map(t=>t.id):[]),r=new Set(function(t){if(!t)return[];try{const e=JSON.parse(t);return Array.isArray(e)?e.filter(t=>"string"==typeof t):[]}catch{return[]}}(e).filter(t=>n.has(t)));let a=!1;const l=t=>{if("off"===t)return r.clear(),void(a=!0);const e=t.startsWith("-"),i=e?t.slice(1):t;o.has(i)&&(a=!0,e||!n.has(i)?r.delete(i):r.add(i))};for(const e of Y_(new URLSearchParams(String(t.search||"").replace(/^\?/,""))))l(e);for(const e of Y_(V_(t.hash)))l(e);const c=Object.freeze([...r].sort());return{active:c,space:K_(t.hash),persist:a?JSON.stringify(c):void 0,knownUrlOperation:a}}let J_={active:Object.freeze([]),space:""},Z_="",Q_=!1,tg="";const eg=new Set;function ig(){if("undefined"==typeof window)return J_;const t=X_(window.location,function(){try{return window.localStorage.getItem(B_)}catch{return null}}(),Z_);void 0!==t.persist&&function(t){try{window.localStorage.setItem(B_,t)}catch{}}(t.persist),J_={active:t.active,space:t.space},window.__hpLabs=t.active;for(const t of eg)t(J_);return J_}function sg(){ig()}function ng(t){return Z_=t,"undefined"==typeof window?J_:(Q_||(Q_=!0,window.addEventListener("hashchange",sg),window.addEventListener("popstate",sg)),ig())}const og=Object.freeze({rotDeg:0,tiltDeg:20,xyScale:1,zScale:1,origin:Object.freeze([500,500])});function rg(t){return[t.rotDeg,t.tiltDeg,t.xyScale,t.zScale,t.origin[0],t.origin[1]].every(Number.isFinite)&&Math.abs(t.xyScale)>1e-12&&Math.abs(Math.cos(t.tiltDeg*Math.PI/180))>1e-12}function ag(t,e,i=og){if(!(rg(i)&&Number.isFinite(t[0])&&Number.isFinite(t[1])&&Number.isFinite(e)))throw new Error("invalid isometric projection input");const s=i.rotDeg*Math.PI/180,n=i.tiltDeg*Math.PI/180,o=t[0]-i.origin[0],r=t[1]-i.origin[1],a=(o*Math.cos(s)-r*Math.sin(s))*i.xyScale,l=(o*Math.sin(s)+r*Math.cos(s))*i.xyScale;return[i.origin[0]+a,i.origin[1]+l*Math.cos(n)-e*i.zScale*Math.sin(n)]}function lg(t,e=og){if(!rg(e)||!Number.isFinite(t[0])||!Number.isFinite(t[1]))throw new Error("invalid isometric projection input");const i=e.rotDeg*Math.PI/180,s=e.tiltDeg*Math.PI/180,n=(t[0]-e.origin[0])/e.xyScale,o=(t[1]-e.origin[1])/(e.xyScale*Math.cos(s));return[e.origin[0]+n*Math.cos(i)+o*Math.sin(i),e.origin[1]-n*Math.sin(i)+o*Math.cos(i)]}function cg(t=og){return`matrix(${function(t=og){if(!rg(t))throw new Error("invalid isometric camera");const e=t.rotDeg*Math.PI/180,i=t.tiltDeg*Math.PI/180,s=t.xyScale*Math.cos(e),n=-t.xyScale*Math.sin(e),o=t.xyScale*Math.sin(e)*Math.cos(i),r=t.xyScale*Math.cos(e)*Math.cos(i);return[s,o,n,r,t.origin[0]-s*t.origin[0]-n*t.origin[1],t.origin[1]-o*t.origin[0]-r*t.origin[1]]}(t).map(t=>Number(t.toFixed(12))).join(" ")})`}function hg(t,e=og){const{rect:i,wallHeight:s}=t,n=t.openingHeight??s,o=t.floorDepth??0;if(!(i.w>=0)||!(i.h>=0)||!Number.isFinite(s)||!Number.isFinite(n)||!Number.isFinite(o)||s<0||n<0||o<0)throw new Error("invalid isometric frame");const r=[[i.x,i.y],[i.x+i.w,i.y],[i.x+i.w,i.y+i.h],[i.x,i.y+i.h]],a=Math.max(s,n),l=r.flatMap(t=>[ag(t,-o,e),ag(t,a,e)]),c=l.map(t=>t[0]),h=l.map(t=>t[1]),d=Math.min(...c),p=Math.min(...h);return{x:d,y:p,w:Math.max(...c)-d,h:Math.max(...h)-p}}const dg=t=>`${Number(t[0].toFixed(4))} ${Number(t[1].toFixed(4))}`;function pg(t){let e=0;for(let i=0;iArray.isArray(t)&&Number.isFinite(t[0])&&Number.isFinite(t[1])).map(t=>[Number(t[0]),Number(t[1])]),i=e[e.length-1];return e.length>1&&e[0][0]===i[0]&&e[0][1]===i[1]&&e.pop(),e}(t);if(i.length<3)return[];const s=!e;return pg(i)>0===s?i:[...i].reverse()}function _g(t,e,i){return t.length?`M ${t.map(t=>dg(ag(t,i,e))).join(" L ")} Z`:""}function gg(t,e,i){const s=e[1]-t[1],n=-(e[0]-t[0]),o=i.rotDeg*Math.PI/180;return s*Math.sin(o)+n*Math.cos(o)}function mg(t,e,i=og){if(!Number.isFinite(e)||e<0)throw new Error("invalid floor edge height");const s=(t||[]).map(t=>{const e=(t||[]).map((t,e)=>function(t,e){const i=ug(t,e);if(!i.length)return i;let s=0;for(let t=1;t0)).filter(t=>t.length>=3&&Math.abs(pg(t))>=1e-9);return e}).filter(t=>t.length&&pg(t[0])>0);s.sort((t,e)=>{const i=t[0][0],s=e[0][0];return i[0]-s[0]||i[1]-s[1]||Math.abs(pg(e[0]))-Math.abs(pg(t[0]))});const n=[],o=[];let r=0;for(let t=0;tt.depth-e.depth||t.component-e.component||t.edge-e.edge),{footprintPath:n.join(" "),sides:o,componentCount:s.length,edgeCount:r}}function fg(t,e){return t^=Math.round(64*(Number.isFinite(e)?e:0)),Math.imul(t,16777619)>>>0}const vg=t=>t.every(Number.isFinite);function yg(t,e,i,s){const n=t[0]*i,o=t[1]*s,r=e*Math.PI/180;return[n*Math.cos(r)-o*Math.sin(r),n*Math.sin(r)+o*Math.cos(r)]}function bg(t,e,i,s,n,o,r){const a=t.flipH?-1:1,l="gate"===t.type?1:t.flipV?-1:1,c=(t.type,t.flipV,t.angle,t.face,{ox:0,oy:0}),h=function(t,e){return[t[0]+e[0],t[1]+e[1]]}([t.x+c.ox,t.y+c.oy],yg(i,t.angle,a,l));return{leaf:e,hinge:h,closedVector:yg(s,t.angle,a,l),quarterVector:yg([-s[1],s[0]],t.angle,a,l),turnDeg:n,bottom:o,top:r}}const wg=t=>`${Number(t[0].toFixed(4))} ${Number(t[1].toFixed(4))}`;function kg(t,e,i=og){const s=Math.max(0,Math.min(1,Number.isFinite(e)?e:0));return t.leaves.map(e=>{const n=function(t,e){const i=t.turnDeg*e*Math.PI/180;return[t.hinge[0]+t.closedVector[0]*Math.cos(i)+t.quarterVector[0]*Math.sin(i),t.hinge[1]+t.closedVector[1]*Math.cos(i)+t.quarterVector[1]*Math.sin(i)]}(e,s),o=ag(e.hinge,e.bottom,i),r=ag(n,e.bottom,i),a=ag(n,e.top,i),l=ag(e.hinge,e.top,i);return{id:t.id,sourceIndex:t.sourceIndex,type:t.type,leaf:e.leaf,d:`M ${wg(o)} L ${wg(r)} L ${wg(a)} L ${wg(l)} Z`,shadowD:`M ${wg(ag(e.hinge,0,i))} L ${wg(ag(n,0,i))}`,depth:Math.max(o[1],r[1])}})}const xg={window:120,door:90,passage:90,gate:300};function $g(t){return xg[t]}function Sg(t,e){const i=[t[0],t[1]],s=[e[0],e[1]];return function(t,e){return t[0]-e[0]||t[1]-e[1]}(i,s)<=0?{a:i,b:s}:{a:s,b:i}}function Mg(t){const e=new Map;return t.forEach((t,i)=>{if(!t.kind||t.open)return;const s=Sg(t.a,t.b);if(Math.hypot(s.b[0]-s.a[0],s.b[1]-s.a[1])<=1e-9)return;const n=function(t,e){const i=t=>(Math.abs(t)<=5e-10?0:Math.round(1e6*t)/1e6).toFixed(6);return`${i(t[0])},${i(t[1])}>${i(e[0])},${i(e[1])}`}(s.a,s.b),o=e.get(n);if(o)return o.physicalHalfWidth=Math.max(o.physicalHalfWidth,t.half||0),o.sourceOrder=Math.min(o.sourceOrder,i),void(t.partitionHost&&(o.partitionHost&&o.partitionHost.id!==t.partitionHost.id?o.ambiguousPartitionHost=!0:o.partitionHost=t.partitionHost));e.set(n,{segmentKey:n,a:s.a,b:s.b,physicalHalfWidth:Math.max(0,t.half||0),sourceOrder:i,...t.partitionHost?{partitionHost:t.partitionHost}:{}})}),[...e.values()]}function Cg(t,e){if(Math.abs(t.distance-e.distance)>1e-9)return t.distance-e.distance;if(Math.abs(t.perpendicular-e.perpendicular)>1e-9)return t.perpendicular-e.perpendicular;return(t.target.segmentKeye.target.segmentKey?1:0)||t.target.sourceOrder-e.target.sourceOrder}function Dg(t){const e=Mg(t.intervals).map(e=>{const i=function(t,e){const i=e.b[0]-e.a[0],s=e.b[1]-e.a[1],n=Math.hypot(i,s),o=i/n,r=s/n,a=(t[0]-e.a[0])*o+(t[1]-e.a[1])*r,l=Math.max(0,Math.min(n,a)),c=e.a[0]+l*o,h=e.a[1]+l*r;return{along:l,length:n,x:c,y:h,distance:Math.hypot(t[0]-c,t[1]-h),perpendicular:Math.abs((t[0]-e.a[0])*r-(t[1]-e.a[1])*o)}}(t.pointer,e);return{target:e,...i,envelope:Math.max(t.baseTolerance,e.physicalHalfWidth+t.bodyPointerPadding)}}).filter(t=>t.distance<=t.envelope+1e-9).filter(e=>!function(t,e,i,s,n){const o=e.b[0]-e.a[0],r=e.b[1]-e.a[1],a=Math.hypot(o,r);if(!(a>1e-9))return!1;const l=o/a,c=r/a;for(const o of i){if(!o.open&&o.kind)continue;const i=Sg(o.a,o.b),r=i.b[0]-i.a[0],a=i.b[1]-i.a[1],h=Math.hypot(r,a);if(!(h>1e-9))continue;const d=r/h,p=a/h;if(Math.abs(l*p-c*d)>1e-6)continue;if(Math.abs((i.a[0]-e.a[0])*c-(i.a[1]-e.a[1])*l)>n)continue;const u=(t[0]-i.a[0])*d+(t[1]-i.a[1])*p,_=1e-9;if(!(u<=_||u>=h-_)&&Math.abs((t[0]-i.a[0])*p-(t[1]-i.a[1])*d)<=s+1e-9)return!0}return!1}(t.pointer,e.target,t.intervals,e.envelope,Math.max(1e-9,Math.min(t.baseTolerance,.04*t.gridStep)))),i=e.filter(e=>!!e.target.partitionHost&&t.renderedLength+2*e.target.physicalHalfWidth>e.length+1e-9).sort(Cg),s=e.filter(e=>!e.target.partitionHost||t.renderedLength+2*e.target.physicalHalfWidth<=e.length+1e-9).sort(Cg);let n=s[0];if(!n)return{candidate:null,jambBlockedTarget:i[0]?.target||null};const o=s.filter(t=>Math.abs(t.distance-n.distance)<=1e-9&&Math.abs(t.perpendicular-n.perpendicular)<=1e-9),r=o.filter(t=>t.target.partitionHost);if(r.length){if(1!==new Set(r.map(t=>t.target.partitionHost.id)).size||r.some(t=>t.target.ambiguousPartitionHost))return{candidate:null,jambBlockedTarget:null};const t=r[0],e=t.target.b[0]-t.target.a[0],i=t.target.b[1]-t.target.a[1],s=Math.hypot(e,i),a=e/s,l=i/s,c=o.every(e=>{const i=e.target.b[0]-e.target.a[0],s=e.target.b[1]-e.target.a[1],n=Math.hypot(i,s),o=i/n,r=s/n,c=Math.abs(a*r-l*o)<=1e-6,h=Math.abs((e.target.a[0]-t.target.a[0])*l-(e.target.a[1]-t.target.a[1])*a);return c&&h<=1e-9});if(!c)return{candidate:null,jambBlockedTarget:null};n=t}if(n.target.ambiguousPartitionHost)return{candidate:null,jambBlockedTarget:null};const{target:a,length:l}=n,c=a.b[0]-a.a[0],h=a.b[1]-a.a[1],d=c/l,p=h/l,u=a.partitionHost?a.physicalHalfWidth:0,_=Math.min(Math.max(0,t.renderedLength)/2+u,l/2);let g=n.along;const m=Math.max(t.gridStep,1e-9),f=l/2;g=Math.abs(g-f)<=m/2?f:Math.round(g/m)*m,g=Math.max(_,Math.min(l-_,g));const v=a.a[0]+d*g,y=a.a[1]+p*g,b=Math.max(0,t.renderedLength)/2,w=g-b,k=g+b,x=Math.max(0,w),$=Math.max(0,l-k),S=[a.a[0]+d*(w-x/2),a.a[1]+p*(w-x/2)],M=[a.a[0]+d*(k+$/2),a.a[1]+p*(k+$/2)];let C=180*Math.atan2(h,c)/Math.PI;C>=90?C-=180:C<-90&&(C+=180);const D=Math.abs(g-f)<=1e-9;return{candidate:{presetRevision:t.preset.revision,geometryRevision:t.geometryRevision,pointer:[t.pointer[0],t.pointer[1]],type:t.preset.type,lengthCm:t.preset.lengthCm,flipH:t.preset.flipH,flipV:t.preset.flipV,x:v,y:y,angle:C,renderedLength:t.renderedLength,target:a,...a.partitionHost?{host:{...a.partitionHost,t:l>0?g/l:0}}:{},measure:{labels:[{distance:x,midpoint:S},{distance:$,midpoint:M}],guide:D?{x:v,y:y,angle:C}:null}},jambBlockedTarget:null}}function Tg(t,e,i,s,n=1e-6){return t.presetRevision===i&&t.geometryRevision===s&&Math.hypot(t.pointer[0]-e[0],t.pointer[1]-e[1])<=n}const Pg=(t,e)=>t[0]*e[1]-t[1]*e[0],Rg=(t,e)=>t[0]*e[0]+t[1]*e[1],Ig=(t,e)=>[t[0]-e[0],t[1]-e[1]],Ag=(t,e,i)=>[t[0]+e[0]*i,t[1]+e[1]*i];function Fg(t,e,i){return Math.abs(Pg(t,e))<=i}function Eg(t,e,i){return Math.abs(Pg(Ig(t,e),i))}function zg(t,e,i,s,n){const o=e[0]-t[0],r=e[1]-t[1],a=Math.hypot(o,r);if(!(a>n&&i>0))return[];const l=[o/a,r/a];return function(t,e,i){const s=e.map(([e,i])=>[Math.max(0,Math.min(e,i)),Math.min(t,Math.max(e,i))]).filter(([t,e])=>e>t+i).sort((t,e)=>t[0]-e[0]||t[1]-e[1]),n=[];for(const t of s){const e=n[n.length-1];!e||t[0]>e[1]+i?n.push([...t]):e[1]=Math.max(e[1],t[1])}const o=[];let r=0;for(const[t,e]of n)t>r+i&&o.push([r,t]),r=Math.max(r,e);return t>r+i&&o.push([r,t]),o}(a,s.flatMap(e=>{const s=e.b[0]-e.a[0],o=e.b[1]-e.a[1],r=Math.hypot(s,o);if(!(r>n&&Fg(l,[s/r,o/r],1e-6)))return[];if(Eg(e.a,t,l)>1.1*Math.max(i,n)||Eg(e.b,t,l)>1.1*Math.max(i,n))return[];return[[Rg(Ig(e.a,t),l),Rg(Ig(e.b,t),l)]]}),n).flatMap(([e,s])=>{const n=Ba({a:Ag(t,l,e),b:Ag(t,l,s),halfDepth:i});return n?[n]:[]})}function Og(t){const e=t.coordScale??1,i=Math.max(t.epsilon??2e-4*t.gridPitch,1e-9),s=[];for(const i of t.rooms||[]){if(!i?.id)continue;const n=hl(t.rooms,i.id,t.walls,t.openCuts,t.pitch,t.cellCm,t.gridPitch,e);if(!n||n.poly.length<3)continue;const o=Qa(n.poly,n.offsets);!o||o.length<3||s.push({roomId:i.id,profile:n,inner:o})}s.sort((t,e)=>t.roomId.localeCompare(e.roomId));const n=(t.roomOpenings||[]).map(t=>{const e=t.angle*Math.PI/180,i=[Math.cos(e),Math.sin(e)],s=Math.max(0,t.length)/2;return{a:Ag([t.x,t.y],i,-s),b:Ag([t.x,t.y],i,s)}}),o=[];for(const s of Tl(t.rooms,t.walls,t.openCuts,t.pitch,t.cellCm,t.gridPitch,e))for(const t of zg(s.a,s.b,s.depthUnits/2,n,i))o.push({body:t});const r=new Map;for(const e of t.partitionCuts||[]){const t=r.get(e.hostId)||[];t.push(e),r.set(e.hostId,t)}for(const e of t.partitions||[]){const s=xa(e.cm,t.cellCm,t.gridPitch)/2;for(const t of zg(e.a,e.b,s,r.get(e.id)||[],i))o.push({body:t,partitionId:e.id})}return{rooms:s,boundaries:o,epsilon:i}}function Ng(t,e,i,s){const n=t.profile.offsets[e];if(!(n>0))return null;const o=function(t,e){const i=t[e],s=t[(e+1)%t.length],n=s[0]-i[0],o=s[1]-i[1],r=Math.hypot(n,o)||1;return function(t){let e=0;for(let i=0;i=0?[-o/r,n/r]:[o/r,-n/r]}(t.profile.poly,e),r=Ag(i.center,o,n),a=[];for(let e=0;es&&Fg(i.axis,[l[0]/c,l[1]/c],1e-6)))continue;if(Eg(n,r,i.axis)>s||Eg(o,r,i.axis)>s)continue;const h=Rg(Ig(n,r),i.axis),d=Rg(Ig(o,r),i.axis);a.push([Math.min(h,d),Math.max(h,d)])}const l=function(t,e){t.sort((t,e)=>t[0]-e[0]||t[1]-e[1]);const i=[];for(const s of t){const t=i[i.length-1];!t||s[0]>t[1]+e?i.push([...s]):t[1]=Math.max(t[1],s[1])}return i}(a,s).find(([t,e])=>t<=s&&e>=-s);if(!l)return null;const[c,h]=l,d=Ag(r,i.axis,-i.half),p=Ag(r,i.axis,i.half),u=Math.max(0,-i.half-c),_=Math.max(0,h-i.half),g=u>0?Ag(r,i.axis,c):d,m=_>0?Ag(r,i.axis,h):p,f=Rg(o,i.normal)>=0?1:-1,v=(e,s,n)=>({from:e,to:s,label:[(e[0]+s[0])/2,(e[1]+s[1])/2],axis:i.axis,labelNormal:o,distance:n,roomId:t.roomId,roomSide:f,source:"room-face"});return{left:v(d,g,u),right:v(p,m,_)}}function Hg(t){const e=Ag(t.center,t.axis,-t.half),i=Ag(t.center,t.axis,t.half),s=Ag(t.center,t.axis,Math.min(-t.half,t.targetLo)),n=Ag(t.center,t.axis,Math.max(t.half,t.targetHi)),o=(e,i)=>({from:e,to:i,label:[(e[0]+i[0])/2,(e[1]+i[1])/2],axis:t.axis,labelNormal:t.normal,distance:Math.hypot(i[0]-e[0],i[1]-e[1]),source:"host-end"});return[o(e,s),o(i,n)]}function Lg(t,e,i,s){const n=Ig(i,e),o=Rg(n,n);if(!(o>s*s))return Math.hypot(...Ig(t,e))<=s;const r=Rg(Ig(t,e),n)/o;if(r<-s||r>1+s)return!1;const a=Ag(e,n,Math.max(0,Math.min(1,r)));return Math.hypot(...Ig(t,a))<=s}function Bg(t,e,i){let s=!1;for(let n=0,o=e.length-1;nt[1]!=c>t[1]&&t[0]<(l-r)*(t[1]-a)/(c-a)+r&&(s=!s)}return s}function qg(t,e,i,s,n,o){const r=Ig(s,i),a=Pg(e,r);if(Math.abs(a)<=o)return null;const l=Ig(i,t),c=Pg(l,r)/a,h=Pg(l,e)/a;return c<-o||c>n+o||h<-o||h>1+o?null:Math.max(0,Math.min(n,c))}function Wg(t,e,i){const s=Hg(i),n="partition"===t.host?.kind?t.host.id:void 0;return[{base:s[0],direction:[-i.axis[0],-i.axis[1]]},{base:s[1],direction:i.axis}].map(({base:t,direction:i})=>{const s=t.distance,o=function(t,e,i,s,n,o){let r=null;for(const a of s)if(!n||a.partitionId!==n){if(Bg(t,a.body,o))return 0;for(let s=0;sRg(Ig(t,n),i));return{center:n,axis:i,normal:s,half:Math.max(0,t.renderedLength)/2,targetLo:Math.min(...o),targetHi:Math.max(...o)}}(t),s=e.rooms.flatMap(t=>{const s=function(t,e,i){const{profile:s}=t;let n=null;for(let t=0;t0))continue;const o=s.poly[t],r=s.poly[(t+1)%s.poly.length],a=Ig(r,o),l=Math.hypot(a[0],a[1]);if(!(l>i&&Fg(e.axis,[a[0]/l,a[1]/l],1e-6)))continue;if(Eg(o,e.center,e.axis)>i||Eg(r,e.center,e.axis)>i)continue;const c=Rg(Ig(o,e.center),e.axis),h=Rg(Ig(r,e.center),e.axis),d=Math.min(c,h),p=Math.max(c,h);if(d>-e.half+i||p0?d:p<0?-p:0);(!n||u2)return Hg(i);if(s.length){const t=s.map(({room:t,edge:s})=>Ng(t,s,i,e.epsilon));if(t.some(t=>!t))return Hg(i);const n=t;return[...n.map(t=>t.left),...n.map(t=>t.right)]}return Wg(t,e,i)}function Ug(t){return!(!t.canEdit||t.kiosk||t.fixedFloor)&&("view"!==t.mode&&("mouse"===t.pointerType&&t.spaceCount>1))}const Gg="1.67.0-beta.3",Vg={badge:"display.badge",icon_ripple:"display.icon_ripple",value:"display.value",static_icon:"display.static_icon"},Kg={badge:"marker.display_hint_badge",icon_ripple:"marker.display_hint_icon_ripple",value:"marker.display_hint_value",static_icon:"marker.display_hint_static_icon"},Yg=2e3,Xg=1e3,Jg=1500,Zg=t=>{const e=String(t??"").trim().replace(",",".");if(!/^[+-]?(?:\d+(?:\.\d*)?|\.\d+)$/.test(e))return null;const i=Number(e);return Number.isFinite(i)?i:null},Qg=(t,e)=>{if(!t.has(e))return{hit:!1};const i=t.get(e);return t.delete(e),t.set(e,i),{hit:!0,value:i}},tm=(t,e,i,s)=>{for(t.delete(e),t.set(e,i);t.size>s;){const e=t.keys().next().value;if(void 0===e)break;t.delete(e)}},em=new Map;let im=0;const sm=t=>`${window.innerWidth}x${window.innerHeight}|${location.pathname}|${JSON.stringify(t??{})}`;let nm=1e4;const om="houseplan_card_layout_v1",rm="houseplan_card_cfg_v1",am="houseplan_card_zoom_v1",lm="houseplan_card_nav_v1",cm="houseplan_card_kiosk_v1",hm="houseplan_card_view_v1",dm="hp-dialog, hp-help, hp-color-opacity, hp-device-preview",pm=1e3,um=[[0,1],[45,.88],[70,.62],[86,.32],[100,0]],_m=(t,e)=>{const i=Math.min(t.x,e.x),s=Math.min(t.y,e.y);return{x:i,y:s,w:Math.max(t.x+t.w,e.x+e.w)-i,h:Math.max(t.y+t.h,e.y+e.h)-s}},gm=new Set(["select","draw","column","merge","split","resize","opening","boundary","wallthick","delroom"]),mm=2e3,fm=(t,e,i)=>{const s=new Event(e,{bubbles:!0,composed:!0});s.detail=i??{},t.dispatchEvent(s)},vm=t=>{history.pushState(null,"",t),fm(window,"location-changed",{replace:!1})},ym=(t,e)=>{let i,s=null;const n=(...n)=>{clearTimeout(i),s=n,i=window.setTimeout(()=>{i=void 0;const e=s;s=null,e&&t(...e)},e)};return n.flush=()=>{if(void 0===i)return;clearTimeout(i),i=void 0;const e=s;s=null,e&&t(...e)},n.cancel=()=>{clearTimeout(i),i=void 0,s=null},n.pending=()=>void 0!==i,n},bm=t=>{try{t.target?.setPointerCapture?.(t.pointerId)}catch{}};class wm extends ht{constructor(){super(...arguments),this._space="f1",this._layout={},this._serverStorage=!1,this._loadOk=!1,this._serverCanWrite=null,this._loading=!1,this._loadTries=0,this._serverCfg=null,this._cfgRev=0,this._cfgContentFingerprint="",this._unsubCfg=null,this._unsubLayout=null,this._unsubVirtual=null,this._liveSyncAttempt=null,this._liveSyncGeneration=0,this._liveSyncConnection=null,this._layoutRev=0,this._layoutContentFingerprint="",this._virtualLights=gn(null),this._canOptimizeUndo=!1,this._undoKind=null,this._devices=[],this._regSignature="",this._defPos={},this._newSyncKey="",this._tip=null,this._hoverRoom=null,this._pointerModality=new Du(this,()=>this._syncPointerHoverTargets()),this._devicePressAnimations=new Map,this._selId=null,this._toast="",this._mode="view",this._pendingNavMode=null,this._decorTool="select",this._decorStyle={...oa},this._decorDraft=null,this._decorMove=null,this._decorSel=null,this._decorEraseConfirm=null,this._decorTextDialog=null,this._decorShapeDialog=null,this._backdropDialog=null,this._decorTextSelection={start:0,end:0},this._furnPalette=null,this._dtBox=null,this._dtDrag=null,this._bdDrag=null,this._slide="",this._reducedMotion=!1,this._onMotionChange=t=>{this._reducedMotion=t.matches,this._cancelDevicePressFeedback(),t.matches&&this._modeTransitionPreparing?this._modeTransitionForceAtomic=!0:t.matches&&this._modeTransition.active&&this._cancelModeTransition(!0),this.requestUpdate()},this._editorChromeMode="plan",this._modeTransitionVisual=null,this._modeTransitionPreparing=!1,this._modeTransitionForceAtomic=!1,this._modeTransitionRequest=0,this._modeTransitionTargetZoom=1,this._modeTransitionEditorCamera=null,this._modeTransition=new L_({frame:t=>this._applyModeTransitionFrame(t),settled:t=>this._settleModeTransition(t)}),this._editorSecondary=new Fu({root:()=>this.renderRoot,requestUpdate:()=>this.requestUpdate(),updateComplete:()=>this.updateComplete,clearTip:()=>{this._tip=null}}),this._editorSecondaryCopy={groupActive:(t,e)=>this._t("editor.group_active",{group:t,item:e}),openGroup:t=>this._t("editor.open_group",{group:t}),disabledAction:(t,e)=>this._t("editor.disabled_action",{action:t,reason:e})},this._tool="draw",this._geometryHistory=new C_(50),this._wallDialog=null,this._drawWallField=null,this._activeDraftId=null,this._resumeDraftBySpace={},this._physicalSel=null,this._physicalDialog=null,this._partitionDeleteDialog=null,this._roomDeleteDialog=null,this._physicalDrag=null,this._physicalRotate=null,this._physicalLastTap=null,this._physicalPickCycle=null,this._wallUnionCache=null,this._isoGeometryCache=new Map,this._isoFallback=new Set,this._openingTunnelCache=null,this._openingWallIndexCache=new Map,this._openingPlacementIntervalsCache=null,this._openingDimensionContextCache=null,this._planSnapGeometryCache=null,this._planStructuralGeometryCache=null,this._physicalBodiesCache=null,this._lightPhysicalBodiesCache=null,this._cleanFloorCache=new Map,this._glowClipCache=new Map,this._glowGeometryWarnings=new Set,this._lightBarrierCache=null,this._glowFeatherUnits=null,this._glowRenderedSources=new Map,this._glowLastAppearance=new Map,this._glowEnteringSources=new Set,this._glowEnterRafs=new Map,this._glowFadeTimers=new Map,this._glowFeatherSuspendUntil=0,this._glowFeatherResumeTimer=0,this._glowSourceSeq=0,this._glowScreenBlend=!1,this._duplicateColumnId=null,this._duplicateColumnTimer=0,this._rszSel=null,this._rszDrag=null,this._rszPreview=null,this._rszLive=null,this._path=[],this._cursorPt=null,this._planSnapHover=null,this._mergeSel=null,this._openingPreset=null,this._openingRebindId=null,this._openingPresetRevision=0,this._openingHoverCandidate=null,this._openingJambBlockCm=null,this._openingDialog=null,this._openingInfo=null,this._opDrag=null,this._opMeasure=null,this._mergeDialog=null,this._openWallAnchor=null,this._boundaryPointerType="mouse",this._boundaryRestoreGuard=null,this._boundaryTargetMemo=null,this._boundaryPreviewMemo=null,this._splitSel=null,this._pendingSplit=null,this._wallFaceBatch=null,this._wallRepairDiagnostic=null,this._wallFaceGraphCache=[],this._areaSel="",this._nameSel="",this._roomDialog=!1,this._roomEditId=null,this._roomFill="",this._roomCustomFill=null,this._roomTempSrc="",this._roomHumSrc="",this._roomSrcOpen=null,this._roomSrcFilter="",this._roomNameScale=1,this._roomLabelScale=1,this._zoom=1,this._view=null,this._zoomBySpace={},this._viewModeSnap=null,this._pointers=new Map,this._panStart=null,this._panLock=null,this._pinchStart=null,this._suppressClick=!1,this._touchContacts=new Map,this._touchSequenceMultitouch=!1,this._touchClickBlockUntil=0,this._connectedPath="",this._routeDepartureHandled=!1,this._onLocationChanged=()=>{this._connectedPath&&location.pathname!==this._connectedPath?this._leaveCardRoute():location.pathname===this._connectedPath&&(this._routeDepartureHandled=!1)},this._touchGestureGuard={capture:!0,handleEvent:t=>this._guardTouchGesture(t)},this._hdrH=118,this._booting=!0,this._bootFading=!1,this._bootSettling=!1,this._bootSettleRaf=0,this._bootLastH=-1,this._bootStart=0,this._bootLastChange=0,this._bootSoft=!1,this._tapConfirm=null,this._onboardingShown=!1,this._rulesDialog=null,this._alignDialog=null,this._settingsDialog=null,this._backupExportDialog=null,this._backupImportDialog=null,this._sunRaysCache=null,this._dayCycleTimer=0,this._dayCycleClockKey="",this._compassDrag=!1,this._importDialog=null,this._importQueue=[],this._importTotal=0,this._rulesCompiledSrc="",this._infoCard=null,this._nativeMoreInfoEntity=null,this._markerDialog=null,this._spaceDialog=null,this._keyHandler=t=>this._onKey(t),this._warmVp=null,this._warmVpArmed=!1,this._warmLongReturn=!1,this._warmRevivePending=!1,this._warmGen=++im,this._warmKey=null,this._warmSlot=null,this._hashApplied=!1,this._navApplied=!1,this._labs={active:Object.freeze([]),space:""},this._viewPreference={},this._renderProjection="flat",this._kioskScale={icon:1,font:1},this._kioskDialog=!1,this._activityRt=new Map,this._vacRt=new Map,this._vacViewKey="",this._vacLastView=null,this._vacRaf=0,this._vacSrvTrails={},this._vacJumpOnce=!1,this._continuity=this._newContinuityController(),this._continuityHistory=[],this._continuityEpoch=0,this._continuityDataReady=!0,this._continuityPaintToken=-1,this._continuityDisposed=!1,this._renderSnapshotAt=Date.now(),this._hassSequence=0,this._visibleDeviceSnapshot=null,this._candidateDeviceSnapshot=null,this._stagedDeviceSnapshotToken=-1,this._capturedSnapshotSequence=-1,this._capturedSnapshotDevices=null,this._capturedSnapshotLayout=null,this._capturedSnapshotActivity="",this._capturedSnapshotConfigEpoch=-1,this._capturedSnapshotVirtual="",this._lastValidStageSize=null,this._pendingRefitSize=null,this._refitRaf=0,this._pageVisibility=t=>{if(this._continuity.visibility(t),this._dayCycleVisibility(t),"hidden"===t.kind)return this._clearTransientHover(!0),this._cancelDevicePressFeedback(),void(this._modeTransitionPreparing?this._modeTransitionForceAtomic=!0:this._cancelModeTransition(!0));if(this._vacJumpOnce=!0,!t.long){const t=Date.now();let e=!1;for(const i of this._activityRt.values())!i.flashKind||(i.expiresAt||i.flashTs+xu)>t||(i.flashTs=0,i.flashKind=null,i.expiresAt=0,e=!0);return void(e&&this.requestUpdate())}Date.now()-this._renderSnapshotAt>1e3&&this._continuity.note("device-snapshot-stale"),this._continuityDataReady=!1,this._continuityPaintToken=-1,this._resumeSettling=!0,this._loading?this.requestUpdate():this._loadFromServer()},this._resumeSettling=!1,this._viewportInvalidAt=0,this._vacFit=null,this._vacAllCamerasFor=null,this._vacAllCameraCache=null,this._vacCalConfirm=null,this._kioskDots=!1,this._cyclePausedUntil=0,this._swipeStart=null,this._tabDrag=null,this._tabDragRelease=null,this._tabSuppressClick=!1,this._tabOrderWarned=!1,this._lastTap=0,this._onLabsSnapshot=t=>{const e=this._effectiveProjection();this._labs=t;const i=this._effectiveProjection();this._convertProjectionView(e,i),this.requestUpdate()},this._onHashChange=()=>{if(this._hasFixedFloor)return;const t=this._hashSpace();if(t&&this._model.find(e=>e.id===t)&&t!==this._space){if(this._wallFaceBatch&&this._roomDialogCancel(),"plan"===this._mode&&"draw"===this._tool&&!this._finishWallChain())return;this._activeDraftId&&(this._resumeDraftBySpace[this._space]=this._activeDraftId),this._commitSpace(t),this._selId=null,this._path=[],this._clearPlanSnapHover(),this._clearOpeningPlacement(!0),this._tool="draw",this._openWallAnchor=null,this._boundaryRestoreGuard=null,this._activeDraftId=null,this._draftSegmentCms=[],this._closingWallCm=null,"plan"===this._mode&&"draw"===this._tool&&this._resumeLastDraft(),this._restoreZoom(),this.requestUpdate()}},this._drag=null,this._rlResize=null,this._holdFired=!1,this._retryContinuity=()=>{this._continuityDataReady=!1,this._continuityPaintToken=-1,this._continuity.retry(this._continuity.recoveryReason||"plan"),this._loading||this._loadFromServer()},this._cfgEpoch=0,this._modelCache=null,this._emptySpaceStateActive=!1,this._decorSnapCache=null,this._markerPreviewMemo=null,this._markerPreviewDevicesMemo=null,this._showHidden=!1,this._connHooked=null,this._connectionWasLost=!1,this._haRegistryConnection=null,this._haRegistryRev=-1,this._haBindingCacheKey="",this._planHassMemo=null,this._onHaRegistryUpdate=()=>{const t=An(this.hass);t.revision===this._haRegistryRev&&this._devices.length||(this._haRegistryRev=t.revision,this._planHassMemo=null,this._regSignature="",this._maybeRebuildDevices(),this.requestUpdate())},this._onConnReady=()=>{if(this._loadTries=0,clearTimeout(this._loadRetryTimer),this._loadRetryTimer=void 0,function(t){const e=Cn(t);e&&(Pn(t,e),Rn(t,e))}(this.hass),this._saveConfigDebounced.pending()&&this._saveConfigDebounced.flush(),this._cfgWriting)return clearTimeout(this._reloadRetry),void(this._reloadRetry=window.setTimeout(this._onConnReady,400));!this._connectionWasLost&&this._continuity.hasCompleteFrame?this._beginContinuityCandidate("connection-ready",!1,"plan"):(this._continuityDataReady=!1,this._continuityPaintToken=-1),this._loading||this._loadFromServer()},this._onConnLost=()=>{this._booting&&!this._continuity.hasCompleteFrame||(this._connectionWasLost=!0,this._continuityDataReady=!1,this._continuityPaintToken=-1,this._continuity.connectionLost())},this._signer=new Ph(()=>this.requestUpdate()),this._dirtyPos=new Set,this._sentPos=new Map,this._persistLayout=ym(()=>{if(this._serverStorage){const t=[...this._dirtyPos];this._dirtyPos.clear();for(const e of t){const t=Xu(this._layout[e]);t&&(this._layout={...this._layout,[e]:t},this._sentPos.set(e,t),this.hass.callWS({type:"houseplan/layout/update",device_id:e,pos:t}).then(t=>this._noteLayoutRev(t)).catch(t=>this._showToast(this._t("toast.pos_save_failed",{err:this._errText(t)}))).finally(()=>{this._sentPos.get(e)===t&&this._sentPos.delete(e)}))}this._cacheSnapshot()}else this._layout=Ju(this._layout),localStorage.setItem(om,JSON.stringify(this._layout))},600),this._frame=null,this._showFar=!1,this._writesPending=0,this._writeChain=Promise.resolve(),this._undoGeometry=()=>{if(this._cancelBoundaryAnchor())return;if(this._physicalDrag||this._physicalRotate)return void this._cancelPhysicalGesture();if(this._decorDraft)return this._decorDraft=null,void this.requestUpdate();if(this._decorMove||this._dtDrag||this._bdDrag)return void this._cancelDecorGesture();if(this._rszDrag)return void this._rszCancelDrag();const t=this._geometryHistory.undo();t&&(this._applyGeometryState(t.before)?this._showToast(this._t("history.undone",{name:t.name})):this._geometryHistory.clear())},this._redoGeometry=()=>{if(this._cancelBoundaryAnchor())return;if(this._physicalDrag||this._physicalRotate)return void this._cancelPhysicalGesture();if(this._decorDraft)return this._decorDraft=null,void this.requestUpdate();if(this._decorMove||this._dtDrag||this._bdDrag)return void this._cancelDecorGesture();if(this._rszDrag)return void this._rszCancelDrag();const t=this._geometryHistory.redo();t&&(this._applyGeometryState(t.after)?this._showToast(this._t("history.redone",{name:t.name})):this._geometryHistory.clear())},this._saveConfigDebounced=ym(()=>{this._serverCfg&&this._writeConfig().catch(t=>{"conflict"===t?.code?(this._showToast(this._t("toast.conflict")),this._cancelPath(),this._reloadConfigOnly(!0)):this._showToast(this._t("toast.cfg_save_failed",{err:this._errText(t)}))})},500),this._draftSegmentCms=[],this._closingWallCm=null,this._savePhysicalDialog=()=>{const t=this._physicalDialog,e=this._curSpaceCfg,i=this._spaceModel();if(!t||!e||!i)return;const s=Zg(t.cm);if(null==s)return void this._showPhysicalRange("column"===t.kind?Hl:100);const n=this._imperial?2.54*s:s,o="column"===t.kind?Hl:100;if(!Number.isFinite(n)||n<1||n>o)return void this._showPhysicalRange(o);if("column"===t.kind){const e=i.wall_columns.find(e=>e.id===t.id);if(!e)return;const s=Zg(t.angle||"0");if("circle"!==t.shape&&(null==s||s<0||s>=90))return void this._showToast(this._t("toast.physical_angle"));const o="circle"===t.shape?{id:t.id,shape:"circle",center:e.center,cm:n}:{id:t.id,shape:"square",center:e.center,cm:n,angle:s};if(i.wall_columns.some(e=>e.id!==t.id&&rc(e,o,.02*this._gridPitch)))return void this._showToast(this._t("toast.column_duplicate"))}const r=this._geometrySnapshot();if("partition"===t.kind){const i=(e.partitions||[]).find(e=>e.id===t.id);i&&(i.cm=n)}else if("column"===t.kind){const i=(e.wall_columns||[]).find(e=>e.id===t.id);i&&(i.cm=Bl(n),i.shape="circle"===t.shape?"circle":"square","square"===i.shape?i.angle=Zg(t.angle||"0"):delete i.angle)}else{const i=(e.room_drafts||[]).find(e=>e.id===t.id);i?.segments?.[t.segment||0]&&(i.segments[t.segment||0].cm=n)}this._recordGeometry(this._t("history.physical_edit"),r),this._physicalDialog=null,this._saveConfig()},this._deletePhysicalSelection=()=>{const t=this._physicalSel,e=this._curSpaceCfg;if(!t||!e)return;if("draft"===t.kind)return void this._deleteDraftWhole();const i=this._geometrySnapshot();if("partition"===t.kind){const i=(e.openings||[]).filter(e=>"partition"===e.host?.kind&&e.host.id===t.id).sort((t,e)=>(t.host?.t||0)-(e.host?.t||0));if(i.length)return void(this._partitionDeleteDialog={id:t.id,openings:i.map(t=>JSON.parse(JSON.stringify(t)))})}const s="partition"===t.kind?"partitions":"column"===t.kind?"wall_columns":"room_drafts";e[s]=(e[s]||[]).filter(e=>e.id!==t.id),e[s].length||delete e[s],this._activeDraftId===t.id&&this._cancelPath(),this._physicalSel=null,this._physicalDialog=null,this._recordGeometry(this._t("history.physical_delete"),i),this._saveConfig()},this._confirmPartitionDelete=()=>{const t=this._partitionDeleteDialog,e=this._curSpaceCfg;if(!t||!e)return;const i=this._geometrySnapshot();e.partitions=(e.partitions||[]).filter(e=>e.id!==t.id),e.partitions.length||delete e.partitions,e.openings=(e.openings||[]).filter(e=>"partition"!==e.host?.kind||e.host.id!==t.id),e.openings.length||delete e.openings,this._partitionDeleteDialog=null,this._physicalSel=null,this._physicalDialog=null,this._recordGeometry(this._t("history.physical_delete"),i),this._saveConfig()},this._deleteDraftWhole=()=>{const t="draft"===this._physicalDialog?.kind?this._physicalDialog.id:"draft"===this._physicalSel?.kind?this._physicalSel.id:null,e=this._curSpaceCfg;if(!t||!e||!confirm(this._t("confirm.delete_draft")))return;const i=this._geometrySnapshot();e.room_drafts=(e.room_drafts||[]).filter(e=>e.id!==t),e.room_drafts.length||delete e.room_drafts,this._activeDraftId===t&&this._cancelPath(),this._physicalSel=null,this._physicalDialog=null,this._recordGeometry(this._t("history.physical_delete"),i),this._saveConfig()},this._deleteDraftSegment=()=>{const t=this._physicalDialog,e=this._curSpaceCfg;if(!t||"draft"!==t.kind||!e)return;if(!confirm(this._t("confirm.delete_draft_segment")))return;const i=(e.room_drafts||[]).findIndex(e=>e.id===t.id);if(i<0)return;const s=e.room_drafts[i],n=Math.max(0,Math.min(s.segments.length-1,t.segment||0)),o=[],r=s.points.slice(0,n+1),a=s.points.slice(n+1);if(r.length>=2&&o.push({id:s.id,points:r,segments:s.segments.slice(0,n)}),a.length>=2&&o.push({id:o.length?`${s.id}-${Date.now().toString(36)}`:s.id,points:a,segments:s.segments.slice(n+1)}),2===o.length&&e.room_drafts.length>=200)return void this._showToast(this._t("toast.physical_limit"));const l=this._geometrySnapshot();e.room_drafts.splice(i,1,...o),e.room_drafts.length||delete e.room_drafts,this._activeDraftId===s.id&&this._cancelPath(),this._physicalDialog=null,this._physicalSel=o.length?{kind:"draft",id:o[0].id}:null,this._recordGeometry(this._t("history.draft_segment_delete"),l),this._saveConfig()},this._confirmRoomDelete=t=>{const e=this._roomDeleteDialog,i=this._curSpaceCfg,s=this._spaceModel();if(!e||!i||!s)return;const n=s.rooms.find(t=>t.id===e.roomId);if(!n)return void(this._roomDeleteDialog=null);const o=this._openCuts(),r=Mp(dl(s.rooms,this._spaceWalls,o,this._wallKeyPitch,this._cellCm,this._gridPitch,pm).filter(t=>t.roomId===n.id),s.partitions,this._openingsR.map(t=>({...t,x:t.rx,y:t.ry})),.02*this._gridPitch),a=new Set(r.materialize.filter(t=>!t.reusePartitionId).map(t=>t.interval.key)).size;if(t&&(i.partitions||[]).length+a>mm)return void this._showToast(this._t("toast.physical_limit"));const l=this._geometrySnapshot(),c=pl(s.rooms,this._spaceWalls,o,this._wallKeyPitch,this._cellCm,this._gridPitch,pm);if(t){i.partitions||=[];const t=new Map,e=new Map,s=Date.now().toString(36);for(const n of r.materialize){let o=n.reusePartitionId?i.partitions.find(t=>t.id===n.reusePartitionId):e.get(n.interval.key);o||(o={id:`partition-room-${s}-${e.size}`,a:[n.interval.a[0]/pm,n.interval.a[1]/pm],b:[n.interval.b[0]/pm,n.interval.b[1]/pm],cm:n.interval.cm},i.partitions.push(o),e.set(n.interval.key,o)),t.set(n.interval.key,o)}for(const e of i.openings||[]){const i=r.openingIntervals.get(e.id),s=i?t.get(i):null,n=this._openingsR.find(t=>t.id===e.id);if(!s||!n)continue;const o={a:[s.a[0]*pm,s.a[1]*pm],b:[s.b[0]*pm,s.b[1]*pm]};e.host={kind:"partition",id:s.id,t:Cp([n.rx,n.ry],o)}}}else if(r.removeOpeningIds.length){const t=new Set(r.removeOpeningIds);i.openings=(i.openings||[]).filter(e=>!t.has(e.id)),i.openings.length||delete i.openings}i.rooms=i.rooms.filter(t=>t.id!==n.id),this._cfgEpoch++,this._commitOpenSpans();const h=this._normalizeWalls(c,this._openCuts());h.length?i.walls=h:delete i.walls,this._roomDeleteDialog=null,this._recordGeometry(this._t(t?"history.delete_room_keep_walls":"history.delete_room_with_walls"),l),this._saveConfig(),this._regSignature="",this._maybeRebuildDevices(),this.requestUpdate()},this._rebindPartitionOpening=()=>{const t=this._openingDialog;if(!t?.id)return;const e=t.id;this._activateMarkupTool("opening"),"opening"===this._tool&&(this._openingRebindId=e,this._openingPreset={type:t.type,lengthCm:t.lengthCm,flipH:t.flipH,flipV:t.flipV,revision:++this._openingPresetRevision},this._openingDialog=null,this._openingHoverCandidate=null)},this._keepClosedAsPartitions=()=>{if(this._wallFaceBatch)return void this._decideWallFace(!1);if(!this._contourClosed||this._pendingSplit||!this._curSpaceCfg)return;const t=this._curSpaceCfg,e=this._path.slice(0,-1);if((t.partitions||[]).length+e.length>mm)return void this._showToast(this._t("toast.physical_limit"));const i=this._geometrySnapshot(),s=Qd(e.length,[...this._draftSegmentCms,this._closingWallCm??void 0],this._drawWallCm,fa);t.partitions||=[];const n=Date.now().toString(36);for(let i=0;it.id!==this._activeDraftId),t.room_drafts.length||delete t.room_drafts),this._recordGeometry(this._t("history.contour_to_partitions"),i),this._saveConfig(),this._roomDialog=!1,this._path=[],delete this._resumeDraftBySpace[this._space],this._activeDraftId=null,this._draftSegmentCms=[],this._closingWallCm=null},this._toggleServerPlans=async()=>{const t=this._spaceDialog;if(t)if(t.pickSaved)this._spaceDialog={...t,pickSaved:!1};else{this._spaceDialog={...t,pickSaved:!0,savedBusy:!0};try{const t=await this.hass.callWS({type:"houseplan/plans/list"}),e=this._spaceDialog;e&&(this._spaceDialog={...e,saved:t?.plans||[],savedBusy:!1})}catch(t){const e=this._spaceDialog;e&&(this._spaceDialog={...e,saved:[],savedBusy:!1}),this._showToast(this._t("toast.plans_list_failed",{err:this._errText(t)}))}}},this._aspectJob=null,this._dayCycleTick=()=>{if(!this.isConnected||"hidden"===this.ownerDocument.visibilityState)return;const t=this._dayCycleState();if(!t)return this._dayCycleTimer&&(clearInterval(this._dayCycleTimer),this._dayCycleTimer=0),void(this._dayCycleClockKey="");const e=Wr(t);e!==this._dayCycleClockKey&&(this._dayCycleClockKey=e,this.requestUpdate())},this._sunShown=!1,this._sunOut=!1,this._sunOutTimer=0,this._openSettingsDialog=()=>{if(!this._norm)return;const t=this._glowRadiusCm,e=this._imperial?Math.round(t/30.48*10)/10:Math.round(t)/100;this._settingsDialog={colors:JSON.parse(JSON.stringify(this._fillColors)),glowRadius:e,bgColor:hs(this._settings,{bgColor:null})||null,northDeg:Zr(this._settings,{}),bgMode:Qr(this._settings,{}),sunRays:ta(this._settings,{}),busy:!1}},this._openAlignDialog=()=>{if(!this._norm||!this._serverCfg)return;const t=this._serverCfg.spaces||[],e=Object.fromEntries(this._devices.filter(t=>!t.virtual&&!!t.area).map(t=>[t.id,t.area])),i=v_(this._serverCfg,this._layout||{},{effectiveAreaByMarker:e}),s=i.changed?this._checkOptimizeGeometry(i.config):null,n=Math.ceil(10*i.report.maxShiftCm)/10,o=t.find(t=>null!=t?.id&&String(t.id)===i.report.maxSpace),r=t.length>1&&o?String(o.title||o.id):"";this._alignDialog={report:i.report,config:i.config,layout:i.layout,cm:n,where:r,preflight:s,changed:i.changed,busy:!1}},this._optimizeUndoBusy=!1,this._openBackupExport=()=>{this._settingsDialog=null,this._backupExportDialog={kind:"full",planOnly:!1,busy:!1,error:""}},this._openRulesDialog=()=>{if(!this._norm)return;const t=this._settings.icon_rules,e=(t&&t.length?t:Xt).map(t=>({...t}));this._rulesDialog={rules:e,test:"",busy:!1}},this._climateCache=null,this._gearPtCache=new WeakMap}get _canEdit(){return!!this._norm&&(!0===this._serverCanWrite||!1!==this._serverCanWrite&&!0===this.hass?.user?.is_admin)}get _kiosk(){return!!this._config?.kiosk}_showKioskDots(){this._kioskDots=!0,clearTimeout(this._kioskDotsTimer),this._kioskDotsTimer=window.setTimeout(()=>this._kioskDots=!1,2500)}get _modeTransitionBusy(){return this._modeTransitionPreparing||this._modeTransition.active}_cssColor(t,e){const i=String(t||"").trim();if(!i)return e;const s=document.createElement("span");s.style.cssText=`position:absolute;visibility:hidden;color:${i}`,this.renderRoot.append(s);const n=getComputedStyle(s).color||e;return s.remove(),n}_currentModeVisual(t=this._mode){const e=this._modeTransition.presented||this._modeTransitionVisual;if(e)return{...e,viewport:{...e.viewport,viewBox:{...e.viewport.viewBox}}};const i=this._stageEl;if(!i||i.clientWidth<=0||i.clientHeight<=0)return null;const s=this.renderRoot.querySelector(".editorchrome"),n=this._viewOr(this._baseVb()),o=this.renderRoot.querySelector(".hp-paper"),r=this.renderRoot.querySelector(".hp-backdrop"),a=this.renderRoot.querySelector(".zoomwrap"),l=a?getComputedStyle(a).filter:"",c=Number(/brightness\(([^)]+)\)/.exec(l)?.[1]);return{presentedMode:t,editorChromeHeight:"view"===t?0:s?.getBoundingClientRect().height||0,stageWidth:i.clientWidth,stageHeight:i.clientHeight,viewport:E_(n,i.clientWidth),stageColor:getComputedStyle(i).backgroundColor||"rgb(255, 255, 255)",paperColor:o?getComputedStyle(o).fill:"rgb(255, 255, 255)",sceneBrightness:Number.isFinite(c)?c:1,architectureOpacity:"decor"===t?.35:1,backdropOpacity:r&&Number(getComputedStyle(r).opacity)||1,viewWeight:"view"===t?1:0,editorWeight:"view"===t?0:1,toolbarContentOpacity:"view"===t?0:1}}_viewForModeTarget(t,e,i,s,n){const o=Oi(this._baseVb(),s/Math.max(1,n)),r=Math.min(wm.ZOOM_MAX,Math.max(wm.ZOOM_MIN,t)),a=o.w/r,l=o.h/r,c=e??o.x+o.w/2,h=i??o.y+o.h/2;return this._clampView({x:c-a/2,y:h-l/2,w:a,h:l},o)}_targetStageColor(t){return"view"!==t?"rgb(255, 255, 255)":this._cssColor(this._stageBg(this._spaceDisplayForRender()),this._cssColor("var(--ha-card-background, var(--card-background-color, #111))","rgb(17, 17, 17)"))}_targetPaperColor(t){return"view"===t&&this._spaceModel()?.bg?this._cssColor("var(--ha-card-background, var(--card-background-color, #111))","rgb(17, 17, 17)"):"rgb(255, 255, 255)"}_targetBrightness(t){return 1}_applyModeTransitionFrame(t){t.targetMode===this._mode&&(this._modeTransitionVisual=t.presented,this._view={...t.presented.viewport.viewBox},this.requestUpdate())}_settleModeTransition(t){if(t.targetMode!==this._mode)return;const e=this._modeTransitionRequest;this._view={...t.to.viewport.viewBox},this._zoom=this._modeTransitionTargetZoom,this._modeTransitionVisual=null,this._modeTransitionPreparing=!1,this._lastValidStageSize=[t.to.stageWidth,t.to.stageHeight],"view"===this._mode&&(this._saveZoom(),this._viewModeSnap=null,this._modeTransitionEditorCamera=null),this.requestUpdate(),this.updateComplete.then(()=>{if(!this.isConnected||e!==this._modeTransitionRequest||this._modeTransitionBusy||t.targetMode!==this._mode)return;const i=this._stageEl;if(i&&i.clientWidth>0&&i.clientHeight>0&&(Math.abs(i.clientWidth-t.to.stageWidth)>.5||Math.abs(i.clientHeight-t.to.stageHeight)>.5)){const t=this._view;this._lastValidStageSize=[i.clientWidth,i.clientHeight],this._applyView(this._zoom,t?t.x+t.w/2:void 0,t?t.y+t.h/2:void 0),this.requestUpdate()}const s=this.renderRoot.activeElement;(!s||!s.isConnected||!!s.closest?.(".editorchrome, .stage"))&&this.renderRoot.querySelector(".modetab.active")?.focus?.({preventScroll:!0})})}_cancelModeTransition(t=!0){const e=!!this._modeTransition.state;this._modeTransitionRequest++,this._modeTransitionPreparing=!1,this._modeTransitionForceAtomic=!1,this._modeTransition.cancel(t),t&&e||(this._modeTransitionVisual=null)}_adoptMode(t){this._cancelModeTransition(!1),this._mode=t,"view"!==t&&(this._editorChromeMode=t)}_commitViewModeAtomic(t,e,i,s){if(this._modeTransitionPreparing=!1,this._modeTransitionVisual=null,this._modeTransitionForceAtomic=!1,this._zoom=e,t){const n=this._stageEl?.clientWidth||t.stageWidth,o=Math.max(1,t.stageHeight+t.editorChromeHeight);this._view=this._viewForModeTarget(e,i,s,n,o),this._lastValidStageSize=[n,o]}else this._view=null;this._viewModeSnap=null,this._modeTransitionEditorCamera=null,this._saveZoom(),this.requestUpdate()}_prepareModeTransition(t,e,i,s,n,o){this.updateComplete.then(()=>{if(!this.isConnected||t!==this._modeTransitionRequest||this._mode!==i)return void(t===this._modeTransitionRequest&&(this._modeTransitionPreparing=!1,this._modeTransitionVisual=null,this._modeTransitionForceAtomic=!1,this.requestUpdate()));const r=this.renderRoot.querySelector(".editorchrome"),a=r?.querySelector(".editorchrome-inner"),l="view"===i?0:a?.scrollHeight||a?.getBoundingClientRect().height||0,c=Math.max(1,e.stageHeight+e.editorChromeHeight),h=Math.max(1,c-l),d=this._stageEl?.clientWidth||e.stageWidth;if(d<=0||h<=0)return this._modeTransitionPreparing=!1,this._modeTransitionVisual=null,this._applyView(s,n,o),void this.requestUpdate();const p=this._viewForModeTarget(s,n,o,d,h),u={presentedMode:i,editorChromeHeight:l,stageWidth:d,stageHeight:h,viewport:E_(p,d),stageColor:this._targetStageColor(i),paperColor:this._targetPaperColor(i),sceneBrightness:this._targetBrightness(i),architectureOpacity:"decor"===i?.35:1,backdropOpacity:"decor"===i&&"backdrop"!==this._decorTool?.5:1,viewWeight:"view"===i?1:0,editorWeight:"view"===i?0:1,toolbarContentOpacity:"view"===i?0:1};this._modeTransitionPreparing=!1;const _=this._modeTransitionForceAtomic;this._modeTransitionForceAtomic=!1,this._modeTransition.start(e,u,i,this._reducedMotion||_?0:220)})}get _hasFixedFloor(){return!!this._config&&Object.prototype.hasOwnProperty.call(this._config,"floor")}_fixedFloorState(t=this._model,e=this._loadOk){const i=this._config?.floor,s=function(t){if(!t.hasFloor)return{kind:"absent"};const e=t.floor;if("string"==typeof e)return e.length?t.spaceIds.includes(e)?{kind:"valid",id:e,source:"id"}:{kind:"invalid",reason:"unknown-id",value:e}:{kind:"invalid",reason:"empty-id",value:e};if("number"==typeof e){if(!Number.isFinite(e))return{kind:"invalid",reason:"non-finite-index",value:e};if(!Number.isInteger(e))return{kind:"invalid",reason:"fractional-index",value:e};if(e<0)return{kind:"invalid",reason:"negative-index",value:e};const i=t.spaceIds[e];return void 0===i?{kind:"invalid",reason:"out-of-range-index",value:e}:{kind:"valid",id:i,source:"index"}}return{kind:"invalid",reason:"invalid-type",value:e}}({spaceIds:t.map(t=>t.id),hasFloor:this._hasFixedFloor,floor:i});return!this._hasFixedFloor||e?s:"number"==typeof i?"valid"===s.kind||"invalid"===s.kind&&"out-of-range-index"===s.reason?{kind:"pending",value:i}:s:"valid"===s.kind||"invalid"===s.kind&&"unknown-id"!==s.reason?s:{kind:"pending",value:i}}_canCommitSpace(t,e=!1){if(e||!this._hasFixedFloor)return!0;const i=this._fixedFloorState();return"valid"===i.kind&&i.id===t}_commitSpace(t,e=!1){return!!this._canCommitSpace(t,e)&&(t!==this._space&&(this._clearTransientHover(!0),this._cancelDevicePressFeedback()),this._space=t,!0)}_slideTo(t,e){if(t===this._space)return!0;if(!this._canCommitSpace(t))return!1;if(this._wallFaceBatch&&this._roomDialogCancel(),"plan"===this._mode&&"draw"===this._tool&&!this._finishWallChain())return!1;this._cancelModeTransition(!0);const i=window.matchMedia?.("(prefers-reduced-motion: reduce)")?.matches;return this._activeDraftId&&(this._resumeDraftBySpace[this._space]=this._activeDraftId),this._commitSpace(t),this._path=[],this._clearPlanSnapHover(),this._clearOpeningPlacement(!0),this._tool="draw",this._openWallAnchor=null,this._boundaryRestoreGuard=null,this._activeDraftId=null,this._draftSegmentCms=[],this._closingWallCm=null,this._selId=null,this._physicalSel=null,this._editorSecondary.closeForNavigation(),this._physicalDialog=null,this._physicalDrag=null,"plan"===this._mode&&"draw"===this._tool&&this._resumeLastDraft(),this._restoreZoom(),i||(this._slide=e,clearTimeout(this._slideTimer),this._slideTimer=window.setTimeout(()=>{this._slideTimer=void 0,this._slide="",this.requestUpdate()},190),this.requestUpdate()),!0}get _canReorderTabs(){return Ug({canEdit:this._canEdit,kiosk:this._kiosk,mode:this._mode,pointerType:"mouse",spaceCount:this._model.length,fixedFloor:this._hasFixedFloor})}_tabPointerDown(t,e){Ug({canEdit:this._canEdit,kiosk:this._kiosk,mode:this._mode,pointerType:t.pointerType,spaceCount:this._model.length,fixedFloor:this._hasFixedFloor})&&(bm(t),this._tabDragRelease=t=>this._tabPointerUp(t),window.addEventListener("pointerup",this._tabDragRelease),window.addEventListener("pointercancel",this._tabDragRelease),this._tabDrag={id:e,pointerId:t.pointerId,x:t.clientX,y:t.clientY,moved:!1,targetId:null,placement:null})}_tabDropTargetAt(t,e,i){const s=this._model.map(t=>t.id),n=s.indexOf(i);if(n<0)return null;const o=this.renderRoot.querySelectorAll('[data-hp="space-tab"]');for(const r of o){const o=r.dataset.id||"";if(!o||o===i)continue;const a=r.getBoundingClientRect();if(ta.right||ea.bottom)continue;const l=s.indexOf(o);return l<0?null:{targetId:o,placement:l=4)))return;var i,s;const n=this._tabDropTargetAt(t.clientX,t.clientY,e.id);e.moved&&e.targetId===n?.targetId&&e.placement===n?.placement||(this._tabDrag={...e,moved:!0,targetId:n?.targetId||null,placement:n?.placement||null})}_tabPointerUp(t){const e=this._tabDrag;if(e&&e.pointerId!==t.pointerId)return;const i="pointerup"===t.type&&e?.moved?this._tabDropTargetAt(t.clientX,t.clientY,e.id):null;"pointerup"===t.type&&e?.moved&&this._suppressNextTabClick(),this._endTabDrag(),e?.moved&&i&&this._commitTabOrder(e.id,i.targetId)}_endTabDrag(){this._tabDrag=null,this._tabDragRelease&&(window.removeEventListener("pointerup",this._tabDragRelease),window.removeEventListener("pointercancel",this._tabDragRelease),this._tabDragRelease=null)}_tabClick(t){if(this._tabSuppressClick)return this._tabSuppressClick=!1,clearTimeout(this._tabSuppressClickTimer),void(this._tabSuppressClickTimer=void 0);this._pickSpace(t)}_suppressNextTabClick(){this._tabSuppressClick=!0,clearTimeout(this._tabSuppressClickTimer),this._tabSuppressClickTimer=window.setTimeout(()=>{this._tabSuppressClick=!1,this._tabSuppressClickTimer=void 0},0)}_commitTabOrder(t,e){const i=this._serverCfg;if(!i||!this._canReorderTabs)return;const s=this._model.map(t=>t.id),n=function(t,e,i){const s=t.indexOf(e),n=t.indexOf(i);if(s<0||n<0||s===n)return t;const o=t.slice();return o.splice(s,1),o.splice(n,0,e),o}(s,t,e);if(n===s)return;const o=new Map(this._devices.map(t=>[String(t.id),String(t.area||"")])),r=function(t,e,i,s=()=>""){if(!i)return[];const n=[];for(const o of t){if(!o||!0===o.removed)continue;const t="string"==typeof o.id?o.id:"";if(!t)continue;if("string"==typeof o.space&&o.space)continue;const r=("string"==typeof o.area?o.area:"")||s(t)||"";r&&e[r]||n.push({id:t,space:i})}return n}(i.markers||[],Object.fromEntries(Object.entries(this._areaToSpace).map(([t,e])=>[t,e.space])),s[0]||"",t=>o.get(t)||"");if(r.length){const t=new Map(r.map(t=>[t.id,t.space]));for(const e of i.markers||[]){const i=t.get(String(e.id));i&&(e.space=i)}}i.spaces=function(t,e){const i=new Map(e.map((t,e)=>[t,e]));return t.map((t,e)=>({space:t,index:e})).sort((t,e)=>(i.get(String(t.space?.id))??Number.MAX_SAFE_INTEGER)-(i.get(String(e.space?.id))??Number.MAX_SAFE_INTEGER)||t.index-e.index).map(t=>t.space)}(i.spaces||[],n),this._saveConfig(),this._tabOrderWarned||(this._tabOrderWarned=!0,this._showToast(this._t("toast.space_order_changed")))}_pickSpace(t){if(this._endTabDrag(),t===this._space)return;const e=this._model.map(t=>t.id),i=e.indexOf(this._space),s=e.indexOf(t);this._navApplied=!0,this._showFar=!1,this._frame=null,this._slideTo(t,i>=0&&s0&&Date.now()>=this._cyclePausedUntil&&this._model.length>1&&this._zoom<=1.001){const t=this._model.map(t=>t.id),e=t.indexOf(this._space);this._slideTo(t[(e+1)%t.length],"left"),this._showKioskDots()}}_syncCycleTimer(){clearInterval(this._cycleTimer),this._cycleTimer=void 0,this.isConnected&&!this._hasFixedFloor&&this._config?.kiosk&&Number(this._config.cycle)>0&&(this._cycleTimer=window.setInterval(()=>this._cycleTick(),1e3*Number(this._config.cycle)))}get _editing(){return"plan"===this._mode||"devices"===this._mode||"decor"===this._mode}get _markup(){return"plan"===this._mode}_newContinuityController(){return new Mh(()=>{this._resumeSettling="steady"!==this._continuity.state,this._continuityEpoch++,this.isConnected&&this.requestUpdate()})}get _labsIso(){return this._labs.active.includes("iso")}get _desiredProjection(){return"view"===this._mode&&this._labsIso&&"iso"===this._viewPreference[this._space]?"iso":"flat"}_saveViewPreference(){try{localStorage.setItem(hm,JSON.stringify(this._viewPreference))}catch{}}_logicalViewCenter(t){const e=this._view;if(!e)return null;const i=[e.x+e.w/2,e.y+e.h/2],s="iso"===t?lg(i):i;return{x:s[0],y:s[1]}}_convertProjectionView(t,e){if(t===e)return;const i=this._logicalViewCenter(t);this._view=null;const s=i?"iso"===e?ag([i.x,i.y],0):[i.x,i.y]:null;this._applyView(this._zoom,s?.[0],s?.[1]),this._warmPatch({vp:this._warmViewportState()}),this.requestUpdate()}_setProjection(t){if(!this._labsIso||"view"!==this._mode)return;const e=this._effectiveProjection();if(this._viewPreference={...this._viewPreference,[this._space]:t},"iso"===t){const t=this._isoSceneKey();t&&this._isoFallback.delete(t)}this._saveViewPreference();const i=this._effectiveProjection();this._convertProjectionView(e,i)}_hashSpace(){return K_(window.location.hash||"")}connectedCallback(){this._connectedPath=location.pathname,this._routeDepartureHandled=!1,window.addEventListener("location-changed",this._onLocationChanged),window.addEventListener("popstate",this._onLocationChanged),this._continuityDisposed&&(this._continuity=this._newContinuityController(),this._continuityDisposed=!1,this._continuityPaintToken=-1);const t=(e=this.ownerDocument,D_.get(e)?.resolved);var e;void 0!==t&&(this._glowScreenBlend=t),this._continuityUnsub?.(),this._continuityUnsub=$h(this.ownerDocument,this._pageVisibility),super.connectedCallback(),this._pointerModality.connect(this.ownerDocument.defaultView);const i=this.ownerDocument.defaultView?.MutationObserver;i&&(this._pointerHoverObserver=new i(t=>{for(const e of t)for(const t of e.addedNodes)this._syncPointerHoverSubtree(t)}),this._pointerHoverObserver.observe(this.renderRoot,{childList:!0,subtree:!0})),this._motionMedia=window.matchMedia?.("(prefers-reduced-motion: reduce)"),this._reducedMotion=!!this._motionMedia?.matches,this._motionMedia?.addEventListener?.("change",this._onMotionChange),function(t){const e=D_.get(t);if(e)return e.promise;const i={promise:Promise.resolve(!1)};return i.promise=P_(t).catch(()=>!1).then(t=>(i.resolved=t,t)),D_.set(t,i),i.promise}(this.ownerDocument).then(t=>{t!==this._glowScreenBlend&&(this._glowScreenBlend=t,this.isConnected&&this.requestUpdate())}),this.hass&&this._ensureHaRegistryAuthority(),window.addEventListener("keydown",this._keyHandler),this._signer.start(()=>this.hass,()=>Is(this._serverCfg)),this._syncCycleTimer(),window.addEventListener("hashchange",this._onHashChange),this._labsUnsub?.(),this._labsUnsub=function(t,e){eg.add(e);const i=ng(t);return"undefined"==typeof window&&e(i),()=>{eg.delete(e)}}(Gg,this._onLabsSnapshot),this._booting?this._bootWatch():this._bootFading&&(clearTimeout(this._bootTimer),this._bootTimer=window.setTimeout(()=>{this._bootFading=!1},220)),this._bootSoft&&(clearTimeout(this._bootSoftTimer),this._bootSoftTimer=window.setTimeout(()=>{this._bootSoft=!1},Jg)),!this._loadOk&&this._serverCfg&&this.hass&&this._scheduleLoadRetry(),!this._warmSlot&&this._config&&this._warmAdopt(),this._loadOk&&this._ensureLiveSyncSubscriptions(),this._warmVp&&!this._warmRevivePending&&void 0===this._warmReviveTimer&&(this._warmRevivePending=!0,this._warmReviveTimer=window.setTimeout(()=>this._warmReviveDialog(),0)),this._warmLongReturn&&this._beginResumeSettle(),this._warmLongReturn=!1,this.requestUpdate()}disconnectedCallback(){this._connectedPath&&location.pathname!==this._connectedPath&&this._leaveCardRoute(),window.removeEventListener("location-changed",this._onLocationChanged),window.removeEventListener("popstate",this._onLocationChanged),this._continuityUnsub?.(),this._continuityUnsub=void 0,this._motionMedia?.removeEventListener?.("change",this._onMotionChange),this._motionMedia=void 0,this._vacRaf&&(cancelAnimationFrame(this._vacRaf),this._vacRaf=0),this._refitRaf&&(cancelAnimationFrame(this._refitRaf),this._refitRaf=0),this._dayCycleTimer&&(clearInterval(this._dayCycleTimer),this._dayCycleTimer=0),this._dayCycleClockKey="",this._bootSettleRaf&&(cancelAnimationFrame(this._bootSettleRaf),this._bootSettleRaf=0),this._bootSettling=!1;for(const t of this._activityRt.values())clearTimeout(t.timer);window.removeEventListener("keydown",this._keyHandler),this._endTabDrag(),clearTimeout(this._tabSuppressClickTimer),this._tabSuppressClickTimer=void 0,this._tabSuppressClick=!1,clearInterval(this._cycleTimer),clearTimeout(this._kioskDotsTimer),clearTimeout(this._kioskHoldTimer),clearTimeout(this._reloadRetry),clearTimeout(this._loadRetryTimer),this._loadRetryTimer=void 0,this._connHooked?.removeEventListener?.("ready",this._onConnReady),this._connHooked?.removeEventListener?.("disconnected",this._onConnLost),this._connHooked?.removeEventListener?.("reconnect-error",this._onConnLost),this._connHooked=null,this._haRegistryRelease?.(),this._haRegistryRelease=void 0,this._haRegistryConnection=null,this._signer.dispose(),clearTimeout(this._toastTimer),clearTimeout(this._slideTimer),this._modeTransition.dispose(),this._modeTransitionVisual=null,this._modeTransitionPreparing=!1,this._modeTransitionForceAtomic=!1,this._modeTransitionRequest++,this._slideTimer=void 0,this._slide="",clearTimeout(this._bootTimer),this._bootTimer=void 0,clearTimeout(this._bootSoftTimer),this._saveConfigDebounced.flush(),window.removeEventListener("hashchange",this._onHashChange),this._labsUnsub?.(),this._labsUnsub=void 0,clearTimeout(this._holdTimer),this._roViewport?.disconnect(),this._roViewport=void 0,this._roHdr?.disconnect(),this._roHdr=void 0,this._onWinResize&&(window.removeEventListener("resize",this._onWinResize),this._onWinResize=void 0),this._unsubCfg&&(this._unsubCfg(),this._unsubCfg=null),this._unsubLayout&&(this._unsubLayout(),this._unsubLayout=null),this._unsubVirtual&&(this._unsubVirtual(),this._unsubVirtual=null),this._unsubTrail&&(this._unsubTrail(),this._unsubTrail=void 0),this._liveSyncGeneration++,this._liveSyncAttempt=null,this._liveSyncConnection=null,clearTimeout(this._layoutSyncTimer),clearTimeout(this._duplicateColumnTimer);for(const t of this._glowFadeTimers.values())clearTimeout(t);for(const t of this._glowEnterRafs.values())cancelAnimationFrame(t);clearTimeout(this._glowFeatherResumeTimer),this._glowFeatherResumeTimer=0,this._glowFeatherSuspendUntil=0,this._glowFadeTimers.clear(),this._glowEnterRafs.clear(),this._glowEnteringSources.clear(),this._glowRenderedSources.clear(),this._glowLastAppearance.clear(),this._glowSourceSeq=0,this._warmSnapshot(),this._warmRevivePending=!1,clearTimeout(this._warmReviveTimer),this._warmReviveTimer=void 0,this._warmRelease(),this._openWallAnchor=null,this._boundaryRestoreGuard=null,this._clearPlanSnapHover(),this._clearOpeningPlacement(!0),this._touchContacts.clear(),this._touchSequenceMultitouch=!1,this._touchClickBlockUntil=0,this._clearTransientHover(!0),this._cancelDevicePressFeedback(),this._pointerHoverObserver?.disconnect(),this._pointerHoverObserver=void 0,this._pointerModality.disconnect(),this._editorSecondary.reset(),this._resumeSettling=!1,this._continuityHistory=[...this._continuityHistory,...this._continuity.trace].slice(-80),this._continuity.dispose(),this._continuityDisposed=!0,super.disconnectedCallback()}_onKey(t){if("Escape"===t.key&&this._vacFit)return this._vacFit=null,this._showToast(this._t("vac.cal_cancelled")),void t.stopPropagation();if("Escape"===t.key){if(this._tapConfirm)return void(this._tapConfirm=null);if(this._vacCalConfirm)return void(this._vacCalConfirm=null);if(this._decorEraseConfirm)return void(this._decorEraseConfirm=null);if(this._openingInfo)return void(this._openingInfo=null);if(this._infoCard)return void this._closeInfoCard();if(this._rulesDialog)return void(this._rulesDialog=null);if(this._alignDialog)return void(this._alignDialog=null);if(this._backupImportDialog)return void(this._backupImportDialog=null);if(this._backupExportDialog)return void(this._backupExportDialog=null);if(this._settingsDialog)return void(this._settingsDialog=null);if(this._markerDialog)return void(this._markerDialog=null);if(this._openingDialog)return void(this._openingDialog=null);if(this._physicalDialog)return void(this._physicalDialog=null);if(this._backdropDialog)return void(this._backdropDialog=null);if(this._decorShapeDialog)return void(this._decorShapeDialog=null);if(this._decorTextDialog)return void(this._decorTextDialog=null);if(this._spaceDialog&&!this._roomDialog)return this._spaceDialog=null,this._importQueue=[],void(this._importTotal=0);if(this._editorSecondary.hasOpenGroup)return t.preventDefault(),void this._editorSecondary.closeGroup(!0)}const e=t.composedPath?.()||[t.target],i=e.some(t=>t?.matches?.('input, textarea, select, [contenteditable="true"]')),s=e.some(t=>t?.classList?.contains?.("editor-secondary")),n=t.ctrlKey||t.metaKey,o=t.key.toLowerCase(),r=/^[a-z]$/.test(o),a="z"===o||!r&&"KeyZ"===t.code,l="y"===o||!r&&"KeyY"===t.code,c=n&&(a&&t.shiftKey||l),h=n&&a&&!t.shiftKey;if("decor"===this._mode){if((h||c)&&i)return;return c?(t.preventDefault(),void this._redoGeometry()):h?(t.preventDefault(),this._decorDraft?void(this._decorDraft=null):this._decorMove||this._dtDrag||this._bdDrag?void this._cancelDecorGesture():void this._undoGeometry()):"Delete"!==t.key&&"Backspace"!==t.key||!this._decorSel||i||s?void("Escape"===t.key&&(t.preventDefault(),this._decorDraft?this._decorDraft=null:this._decorMove||this._dtDrag||this._bdDrag?this._cancelDecorGesture():"furniture"===this._decorTool?(this._furnPalette=null,this._decorTool="select"):this._decorSel?this._decorSel=null:"select"!==this._decorTool?this._decorTool="select":this._setMode("view"))):(t.preventDefault(),void this._decorDeleteSel())}if(this._markup&&(!h&&!c||!i)){if(("Delete"===t.key||"Backspace"===t.key)&&this._physicalSel&&!i&&!s)return t.preventDefault(),void this._deletePhysicalSelection();if(c)return t.preventDefault(),void this._redoGeometry();if(h)return t.preventDefault(),this._rszDrag?void this._rszCancelDrag():this._wallFaceBatch?(this._roomDialogCancel(),void(this._activeDraftId&&this._path.length>1?this._undoActiveDraftPoint():this._undoPoint())):"draw"===this._tool&&this._path.length?void(this._activeDraftId&&this._path.length>1?this._undoActiveDraftPoint():this._undoPoint()):"split"===this._tool&&this._splitSel?.pts?.length?(this._splitSel={...this._splitSel,pts:this._splitSel.pts.slice(0,-1)},void(this._splitSel.pts.length||(this._cursorPt=null))):void this._undoGeometry();if("Escape"===t.key)return this._physicalDrag||this._physicalRotate?(t.preventDefault(),void this._cancelPhysicalGesture()):this._roomDialog?(t.preventDefault(),void this._roomDialogCancel()):"draw"===this._tool&&this._path.length?(t.preventDefault(),void this._undoPoint()):this._physicalSel?(t.preventDefault(),void(this._physicalSel=null)):"resize"===this._tool?(t.preventDefault(),this._rszDrag?void this._rszCancelDrag():void(this._rszSel?this._rszSel=null:this._tool="draw")):"split"===this._tool?(t.preventDefault(),void(this._splitSel?.pts?.length?(this._splitSel={...this._splitSel,pts:this._splitSel.pts.slice(0,-1)},this._splitSel.pts.length||(this._cursorPt=null)):this._splitSel?this._splitSel=null:this._tool="draw")):"merge"===this._tool?(t.preventDefault(),void(this._mergeSel?this._mergeSel=null:this._tool="draw")):this._wallDialog?(t.preventDefault(),void(this._wallDialog=null)):"boundary"===this._tool?(t.preventDefault(),void(this._openWallAnchor?this._cancelBoundaryAnchor():this._tool="draw")):void("opening"!==this._tool&&"wallthick"!==this._tool&&"delroom"!==this._tool&&"column"!==this._tool||(t.preventDefault(),"opening"===this._tool&&this._clearOpeningPlacement(!0),this._tool="draw"))}}_undoPoint(){if(this._path.length){if(this._contourClosed)return this._path=this._path.slice(0,-1),void(this._closingWallCm=null);if(this._activeDraftId&&this._path.length>1&&this._curSpaceCfg){const t=this._geometrySnapshot();this._path=this._path.slice(0,-1),this._draftSegmentCms=this._draftSegmentCms.slice(0,-1);const e=this._curSpaceCfg,i=(e.room_drafts||[]).findIndex(t=>t.id===this._activeDraftId);return void(i>=0&&(this._path.length<2?(e.room_drafts.splice(i,1),e.room_drafts.length||delete e.room_drafts,this._activeDraftId=null):e.room_drafts[i]={id:this._activeDraftId,points:this._path.map(t=>[t[0]/pm,t[1]/pm]),segments:this._draftSegmentCms.map(t=>({cm:t}))},this._recordGeometry(this._t("history.draft_segment_delete"),t),this._saveConfig()))}this._path=this._path.slice(0,-1)}}_undoActiveDraftPoint(){const t=this._activeDraftId,e=this._path[0]?[...this._path[0]]:null,i=this._geometryHistory.undo();if(!i)return void this._undoPoint();if(!this._applyGeometryState(i.before))return void this._geometryHistory.clear();const s=t?this._spaceModel()?.room_drafts.find(e=>e.id===t):null;s?(this._activeDraftId=s.id,this._path=s.points.map(t=>[...t]),this._draftSegmentCms=this._adoptDraftCms(this._path,s.segments.map(t=>t.cm),s.id),this._resumeDraftBySpace[this._space]=s.id):(this._activeDraftId=null,this._path=e?[e]:[],this._draftSegmentCms=[],t&&this._resumeDraftBySpace[this._space]===t&&delete this._resumeDraftBySpace[this._space]),this._clearPlanSnapHover(),this._showToast(this._t("history.undone",{name:i.name}))}static getConfigElement(){return document.createElement("houseplan-card-editor")}static getStubConfig(){return{type:"custom:houseplan-card"}}static _warmBootReset(t){for(const t of em.values())for(const e of t)clearTimeout(e.evict);em.clear(),nm=t&&t>0?t:1e4}static _warmBootStats(){let t=0,e=0;const i=[];for(const s of em.values())for(const n of s)t++,n.dlg&&(e++,i.push(n.dlg.kind));return{keys:em.size,slots:t,dlgs:e,drafts:i}}setConfig(t){const e=this._config,i=!!e&&Object.prototype.hasOwnProperty.call(e,"floor");this._config={icon_size:2.5,show_temperature:!0,live_states:!0,show_signal:!0,...t};(i!==this._hasFixedFloor||e?.floor!==this._config.floor)&&(this._hashApplied=!1,this._navApplied=!1,this._warmVpArmed=!1),this._config.kiosk&&(this._booting=!1,this._bootFading=!1),!this._hasFixedFloor&&t.default_floor&&this._commitSpace(t.default_floor,!0);try{this._zoomBySpace=JSON.parse(localStorage.getItem(am)||"{}")||{}}catch{this._zoomBySpace={}}try{const t=JSON.parse(localStorage.getItem(hm)||"{}")||{};this._viewPreference=Object.fromEntries(Object.entries(t).filter(t=>"flat"===t[1]||"iso"===t[1]))}catch{this._viewPreference={}}this._labs=ng(Gg);try{const t=JSON.parse(localStorage.getItem(cm)||"null");this._kioskScale={icon:zs(t?.icon),font:zs(t?.font)}}catch{}try{const t=JSON.parse(localStorage.getItem(rm)||"null");t&&t.config&&Array.isArray(t.config.spaces)&&(this._serverCfg=t.config,this._cfgEpoch++,this._cfgRev=t.rev||0,this._cfgContentFingerprint=t.config_fingerprint||Ch(t.config),this._layout=t.layout||{},this._layoutRev=t.layout_rev||0,this._layoutContentFingerprint=t.layout_fingerprint||Ch(this._layout),this._virtualLights=gn(t.virtual_lights,this._cfgRev),this._serverStorage=!0)}catch{}this._adoptInitialSpace(this._model,this._loadOk),"view"!==this._mode||this._view||(this._zoom=this._zoomBySpace[this._space]||1),this.isConnected&&(this._syncCycleTimer(),this._warmAdopt(),this._warmLongReturn&&this._beginResumeSettle(),this._warmLongReturn=!1)}_warmAdopt(){if(this._config?.kiosk)return;const t=sm(this._config);if(this._warmKey===t&&this._warmSlot)return;this._warmSlot&&this._warmRelease();const e=this.parentNode,i=this._warmIdx(e),s=em.get(t);if(!s||!s.length)return;const n=s.find(t=>t.owner===this._warmGen);if(n)return this._warmLongReturn=!!n.freed&&Date.now()-n.freed>=wh,clearTimeout(n.evict),n.evict=0,n.freed=0,n.live=!0,this._warmSlot=n,this._warmKey=t,n.frameFingerprint&&this._continuity.adoptCompleteFrame(n.frameFingerprint),void(!this._devices.length&&n.devices?.length&&(this._devices=[...n.devices]));const{slot:o,sure:r}=((t,e,i,s)=>{const n=t=>{const e=!!i&&t.place?.deref()===i;return e&&t.idx===s?4:t.live?0:e?3:2};let o=null,r=0,a=0,l=null;for(const i of t){if(i.owner===e)continue;l=i;const t=n(i);t<=0||(t>r?(o=i,r=t,a=1):t===r&&a++)}return!o||a>1?{slot:o||l,sure:!1}:{slot:o,sure:!0}})(s,this._warmGen,e,i);o&&(this._warmLongReturn=!!o.freed&&Date.now()-o.freed>=wh,this._booting=!1,this._bootFading=!1,this._hdrH=o.hdrH,this._bootSoft=!0,this.isConnected&&(clearTimeout(this._bootSoftTimer),this._bootSoftTimer=window.setTimeout(()=>{this._bootSoft=!1},Jg)),this._warmKey=t,r?(clearTimeout(o.evict),o.evict=0,o.owner=this._warmGen,o.place=e?new WeakRef(e):null,o.idx=i,o.live=!0,this._warmSlot=o,this._warmVp=o.vp,o.frameFingerprint&&this._continuity.adoptCompleteFrame(o.frameFingerprint),!this._devices.length&&o.devices?.length&&(this._devices=[...o.devices]),this._warmAdoptViewport(this._config)):(this._warmSlot={owner:this._warmGen,path:location.pathname,place:e?new WeakRef(e):null,idx:i,live:!0,hdrH:o.hdrH,stageH:o.stageH,vp:null,frameFingerprint:"",devices:null,dlg:null,freed:0,evict:0},s.push(this._warmSlot),this._warmTrim(s)))}_warmIdx(t){const e=t?.children;if(!e)return-1;for(let t=0;t4;){const e=t.findIndex(t=>!t.live);if(e<0)break;clearTimeout(t[e].evict),t.splice(e,1)}}_warmScheduleEvict(t,e){if(clearTimeout(t.evict),!(t.dlg||t.vp&&"view"!==t.vp.mode))return;const i=t.freed,s=t.owner;t.evict=window.setTimeout(()=>{if(t.evict=0,t.freed!==i||t.owner!==s)return;var n;t.dlg=null,t.vp=(n=t.vp)&&"view"!==n.mode?{...n,mode:"view",zoom:n.snap?.space===n.space?n.snap.zoom:n.zoom,view:null,snap:null,tool:"draw",decorTool:"select",showHidden:!1,selId:null,rszSel:null,decorSel:null}:n,t.frameFingerprint="";const o=em.get(e);if(!t.live&&o&&o.length>1){const e=o.indexOf(t);e>=0&&o.splice(e,1)}},nm+250)}_warmAdoptViewport(t){const e=this._warmVp;if(!e||this._warmSlot?.path!==location.pathname)return void(this._warmVp=null);const i=this._fixedFloorState();if(this._hashApplied||!this._model.find(t=>t.id===e.space)||"valid"===i.kind&&i.id!==e.space||this._hasFixedFloor&&"valid"!==i.kind)return void(this._warmVp=null);this._commitSpace(e.space,!0),this._navApplied=!0,this._adoptMode("view"!==e.mode&&this._canEdit&&!t.kiosk?e.mode:"view"),this._pendingNavMode="view"===e.mode||this._canEdit||t.kiosk?null:e.mode,this._zoom=e.zoom;const s=this._effectiveProjection(),n=s===e.projection&&this._labsIso===e.activeLabsIso;if(this._view=n&&e.view?{...e.view}:null,this._viewModeSnap=n&&e.snap?{...e.snap}:null,!n&&e.logicalCenter){const t="iso"===s?ag([e.logicalCenter.x,e.logicalCenter.y],0):[e.logicalCenter.x,e.logicalCenter.y];this._applyView(e.zoom,t[0],t[1])}var o;this._tool="openwall"===(o=e.tool)||"closewall"===o?"boundary":"opening"===(o=function(t){return"partition"===t?"draw":t}(o))?"draw":"string"==typeof o&&gm.has(o)?o:"draw",this._decorTool=e.decorTool,this._showHidden=e.showHidden,this._showFar!==e.showFar&&(this._showFar=e.showFar,this._frame=null),this._selId=e.selId,this._rszSel=e.rszSel,this._decorSel=e.decorSel,this._warmVpArmed=!0}_warmPatch(t,e=!1){if(this._config?.kiosk)return;const i=sm(this._config);if(!this._warmSlot||this._warmKey===i){if(!this._warmSlot){if(!e)return;const t=this.parentNode;this._warmKey=i,this._warmSlot={owner:this._warmGen,path:location.pathname,place:t?new WeakRef(t):null,idx:this._warmIdx(t),live:!0,hdrH:this._hdrH,stageH:0,vp:null,frameFingerprint:"",devices:null,dlg:null,freed:0,evict:0};const s=em.get(i)||[];for(s.push(this._warmSlot),em.set(i,s),this._warmTrim(s);em.size>8;){const t=em.keys().next().value;if(void 0===t||t===i)break;for(const e of em.get(t)||[])clearTimeout(e.evict);em.delete(t)}}Object.assign(this._warmSlot,t)}}_warmViewportState(){const t=this._effectiveProjection();return{space:this._space,mode:this._mode,projection:t,activeLabsIso:this._labsIso,logicalCenter:this._logicalViewCenter(t),zoom:this._zoom,view:this._view?{...this._view}:null,snap:this._viewModeSnap?{...this._viewModeSnap}:null,tool:this._tool,decorTool:this._decorTool,showHidden:this._showHidden,showFar:this._showFar,selId:this._selId,rszSel:this._rszSel,decorSel:this._decorSel}}_warmDialogState(){const t=(t,e)=>({kind:t,space:this._space,mode:this._mode,data:e});return this._tapConfirm||this._alignDialog||this._mergeDialog||this._importDialog||this._backupExportDialog||this._backupImportDialog?null:this._openingInfo?t("openingInfo",this._openingInfo.id):this._infoCard?t("info",this._infoCard.id):this._rulesDialog?this._rulesDialog.busy?null:t("rules",this._rulesDialog):this._settingsDialog?this._settingsDialog.busy?null:t("settings",this._settingsDialog):this._markerDialog?this._markerDialog.busy?null:t("marker",this._markerDialog):this._openingDialog?t("opening",this._openingDialog):this._backdropDialog?t("backdrop",this._backdropDialog):this._decorShapeDialog?t("decorShape",this._decorShapeDialog):this._decorTextDialog?t("decorText",this._decorTextDialog):this._roomDialog?t("room",{editId:this._roomEditId,fill:this._roomFill,customFill:this._roomCustomFill,tempSrc:this._roomTempSrc,humSrc:this._roomHumSrc,srcOpen:this._roomSrcOpen,srcFilter:this._roomSrcFilter,nameScale:this._roomNameScale,labelScale:this._roomLabelScale,areaSel:this._areaSel,nameSel:this._nameSel,pendingSplit:this._pendingSplit,wallFaceBatch:this._wallFaceBatch,path:this._path}):this._spaceDialog?this._spaceDialog.busy?null:t("space",this._spaceDialog):null}_warmSnapshot(){if(this._booting||this._config?.kiosk||"steady"!==this._continuity.state)return;const t={vp:this._warmViewportState(),frameFingerprint:this._continuity.frameFingerprint,devices:this._devices};if(this._warmRevivePending||(t.dlg=this._warmDialogState()),this.isConnected&&this._warmSlot?.owner===this._warmGen){const e=this.parentNode;t.place=e?new WeakRef(e):null,t.idx=this._warmIdx(e)}this._warmPatch(t)}_warmReviveDialog(){this._warmRevivePending=!1;const t=this._warmSlot;if(this._warmReviveTimer=void 0,!t||!t.dlg)return;const e=t.dlg,i=t.freed;if(t.dlg=null,t.freed=0,clearTimeout(t.evict),t.evict=0,i&&!(Date.now()-i>nm)&&e.space===this._space&&e.mode===this._mode){switch(e.kind){case"space":this._spaceDialog={...e.data,busy:!1,savedBusy:!1};break;case"marker":this._markerDialog={...e.data,busy:!1};break;case"settings":this._settingsDialog={...e.data,busy:!1};break;case"rules":this._rulesDialog={...e.data,busy:!1};break;case"opening":this._openingDialog={...e.data};break;case"backdrop":this._backdropDialog={...e.data};break;case"decorShape":this._decorShapeDialog={...e.data};break;case"decorText":{this._decorTextDialog={...e.data};const t=String(this._decorTextDialog?.text??"").length;this._decorTextSelection={start:t,end:t};break}case"room":{const t=e.data;this._roomEditId=t.editId,this._roomFill=t.fill,this._roomCustomFill=t.customFill||null,this._roomTempSrc=t.tempSrc,this._roomHumSrc=t.humSrc,this._roomSrcOpen=t.srcOpen,this._roomSrcFilter=t.srcFilter,this._roomNameScale=t.nameScale,this._roomLabelScale=t.labelScale,this._areaSel=t.areaSel,this._nameSel=t.nameSel,this._pendingSplit=t.pendingSplit,this._wallFaceBatch=t.wallFaceBatch||null,this._path=t.path,this._wallFaceBatch&&(this._activeDraftId=this._wallFaceBatch.activeDraftId,this._draftSegmentCms=[...this._wallFaceBatch.activeCms]),this._roomDialog=!0;break}case"info":{const t=this._devices.find(t=>t.id===e.data);t&&(this._infoCard=t);break}case"openingInfo":{const t=(this._curSpaceCfg?.openings||[]).find(t=>t.id===e.data);t&&(this._openingInfo=t);break}}this.requestUpdate()}}_cacheSnapshot(){if(this._serverCfg)try{this._cfgContentFingerprint=Ch(this._serverCfg),this._layoutContentFingerprint=Ch(this._layout),this._virtualLights=function(t,e,i){if(t.configRev===i)return t;const s=new Set((Array.isArray(e?.markers)?e.markers:[]).filter(yn).map(t=>t.id));return{...t,configRev:i,off:new Set([...t.off].filter(t=>s.has(t)))}}(this._virtualLights,this._serverCfg,this._cfgRev),localStorage.setItem(rm,JSON.stringify({config:this._serverCfg,rev:this._cfgRev,config_fingerprint:this._cfgContentFingerprint,layout:this._layout,layout_rev:this._layoutRev,layout_fingerprint:this._layoutContentFingerprint,virtual_lights:fn(this._virtualLights)}))}catch{}}_beginContinuityCandidate(t,e,i="plan"){return this._booting&&!this._continuity.hasCompleteFrame?this._continuity.token:(this._continuityDataReady=e,this._continuityPaintToken=-1,this._stagedDeviceSnapshotToken=-1,this._resumeSettling=!0,this._continuity.beginCandidate(t,i))}_continuityStageValid(){const t=this._stageEl;return!!t&&t.clientWidth>0&&t.clientHeight>0}_continuityAssetsReady(){if(!this._model.length)return!1;const t=this._model.length?this._spaceModel():null;return!t?.bg?.href||this._signer.isReady(this.hass,t.bg.href)}_initialSpaceSelection(t,e=this._loadOk){const i=this._fixedFloorState(t,e);return"valid"===i.kind?{id:i.id,source:"fixed"}:this._hasFixedFloor?{id:null,source:"none"}:function(t){const e=new Set(t.spaceIds.filter(t=>!!t));if(!e.size)return{id:null,source:"none"};const i=[["hash",!1===t.acceptHash?null:t.hashSpace],["current",t.preserveCurrent?t.currentSpace:null],["saved",t.savedSpace],["default",t.defaultSpace],["first",t.spaceIds[0]]];for(const[t,s]of i)if(s&&e.has(s))return{id:s,source:t};return{id:null,source:"none"}}({spaceIds:t.map(t=>t.id),hashSpace:this._hashSpace(),acceptHash:!this._hashApplied,currentSpace:this._space,preserveCurrent:this._hashApplied||this._navApplied||this._warmVpArmed,savedSpace:this._savedNav()?.space,defaultSpace:this._config?.default_floor})}_adoptInitialSpace(t,e=this._loadOk){const i=this._initialSpaceSelection(t,e);return i.id?(this._commitSpace(i.id,!0),"hash"===i.source&&(this._hashApplied=!0),"saved"===i.source&&(this._navApplied=!0),i):i}_candidateBackdrop(t,e=this._space){const i=vc(t),s=this._fixedFloorState(i,!0);if(this._hasFixedFloor&&"valid"!==s.kind)return"";const n=this._initialSpaceSelection(i,!0).id||(i.some(t=>t.id===e)?e:i[0]?.id);return i.find(t=>t.id===n)?.bg?.href||""}_visualFrameFingerprint(){const t=this._stageEl,e=t?[t.clientWidth,t.clientHeight]:[0,0];return Dh([this._cfgRev,this._cfgContentFingerprint||Ch(this._serverCfg),this._layoutRev,this._layoutContentFingerprint||Ch(this._layout),this._space,this._mode,this._view,e,this._glowScreenBlend?"screen":"normal",this.hass?.themes?.darkMode??this.hass?.themes?.default_theme??""])}_settleContinuityFrame(){if(this._booting||!this._continuityStageValid())return;if(!this._continuity.hasCompleteFrame&&"steady"===this._continuity.state)return void(this._continuityAssetsReady()&&(this._renderSnapshotAt=Date.now(),this._continuity.markCompleteFrame(this._visualFrameFingerprint())));if(!this._continuityDataReady)return;if(!["holding","offline-stale","overlay-pending","overlay-visible","candidate-ready"].includes(this._continuity.state))return;const t=this._continuity.token;if(this._candidateDeviceSnapshot&&this._candidateDeviceSnapshot!==this._visibleDeviceSnapshot&&this._stagedDeviceSnapshotToken!==t)return this._stagedDeviceSnapshotToken=t,void this.requestUpdate();this._continuityPaintToken!==t&&(this._continuityPaintToken=t,this._continuity.candidateReady(t)&&this._continuity.commitAfterPaint(t,{updateComplete:()=>this.updateComplete,stageValid:()=>this.isConnected&&this._continuityStageValid(),assetsReady:()=>this._continuityAssetsReady(),frameFingerprint:()=>this._visualFrameFingerprint()}).then(e=>{e&&t===this._continuity.token?(this._resumeSettling=!1,this._renderSnapshotAt=Date.now(),this._candidateDeviceSnapshot&&(this._visibleDeviceSnapshot=this._candidateDeviceSnapshot),this._candidateDeviceSnapshot=null,this._stagedDeviceSnapshotToken=-1,this._warmSnapshot()):t===this._continuity.token&&(this._continuityPaintToken=-1,this._stagedDeviceSnapshotToken=-1,this._candidateDeviceSnapshot=null,this.requestUpdate())}))}_onBackdropLoaded(t,e){this._signer.markLoaded(this.hass,t,e),this._continuity.note("asset-ready"),this._continuityPaintToken=-1,"steady"!==this._continuity.state&&this.requestUpdate()}_renderRecoveryOverlay(){if(!this._continuity.overlayVisible&&"recovery-error"!==this._continuity.state)return G;const t="connection"===this._continuity.recoveryReason;return W`
`}afterRender(){const t=this.host.root();this._blocked&&(this._openGroupId?this.closeGroup(!1):"palette"===this._currentModel?.kind&&this._currentModel.dismiss?.()),this._syncGlobalDismissListener();const e=t.querySelector(".editor-secondary"),i=this._renderedContext,s=e?.dataset.contextId||"";if(s&&i&&s!==i&&!window.matchMedia?.("(prefers-reduced-motion: reduce)")?.matches&&(this._contentAnimation?.cancel(),this._contentAnimation=e?.querySelector(".editor-secondary-content")?.animate([{opacity:.35,transform:"translateY(-4px)"},{opacity:1,transform:"translateY(0)"}],{duration:100,easing:"ease-out"})),this._renderedContext=s,i&&s!==i&&this._focusOwned){const i=s?e?.querySelector('[tabindex="0"], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled])'):t.querySelector(".editbar-tools");i?.focus?.(),this._focusOwned=!!s}if("palette"===this._currentModel?.kind&&this._currentModel.launcherId){const e=[...t.querySelectorAll("[data-editor-palette]")].find(t=>t.dataset.editorPalette===this._currentModel?.launcherId);e&&null!==e.offsetParent||this._currentModel.dismiss?.()}if(!this._openGroupId)return;const n=[...t.querySelectorAll("[data-editor-group]")].find(t=>t.dataset.editorGroup===this._openGroupId);n&&null!==n.offsetParent||this.closeGroup(!0)}handleOutsideDismiss(t){if(Fu(t,t=>t.hasAttribute("data-editor-navigation")))return"pointerdown"===t.type?this.closeForNavigation():"click"===t.type&&this._dismissPointerTarget&&this._clearDismissClick(),!1;if("click"===t.type&&this._dismissPointerTarget){return!!(t.composedPath?.()||[t.target]).includes(this._dismissPointerTarget)&&(this._clearDismissClick(),t.preventDefault(),t.stopImmediatePropagation(),!0)}const e=this._openGroupId||this._blocked||"palette"!==this._currentModel?.kind?null:this._currentModel;if("pointerdown"===t.type&&(this._openGroupId||e)){const i=Fu(t,t=>t.classList.contains("editor-secondary")),s=Fu(t,t=>!!t.dataset.editorGroup),n=Fu(t,t=>!!t.dataset.editorPalette),o=Fu(t,t=>t.classList.contains("stage"));if(!(i||s||n||"stay-open-on-canvas"===e?.dismissPolicy&&o))return t.preventDefault(),t.stopImmediatePropagation(),this._dismissPointerTarget=t.target,clearTimeout(this._dismissTimer),this._dismissTimer=window.setTimeout(()=>{this._clearDismissClick()},800),this._openGroupId?this.closeGroup(!1):e?.dismiss?.(),this._syncGlobalDismissListener(),!0}return!1}_activateGroupItem(t,e,i){if(t.id!==this._openGroupId)return;const s=t.items.find(t=>t.id===e);if(!s||s.disabled)return;const n="toggle"===s.role&&"stay-open"===s.closePolicy,o=0===i.detail;n||(this._openGroupId=null,this.host.requestUpdate(),this._syncGlobalDismissListener()),s.invoke(),!n&&o&&this.host.updateComplete().then(()=>{const e=[...this.host.root().querySelectorAll("[data-editor-group]")].find(e=>e.dataset.editorGroup===t.id&&null!==e.offsetParent);e?.focus()})}_groupKeydown(t){if(!["ArrowLeft","ArrowRight","Home","End"].includes(t.key))return;const e=[...t.currentTarget.querySelectorAll(".editor-group-item:not([disabled])")];if(!e.length)return;t.preventDefault();const i=e.indexOf(this.host.root().activeElement),s="Home"===t.key?0:"End"===t.key?e.length-1:"ArrowLeft"===t.key?i<=0?e.length-1:i-1:(i+1)%e.length;e[s]?.focus()}_clearDismissClick(){this._dismissPointerTarget=null,clearTimeout(this._dismissTimer),this._dismissTimer=void 0,this._syncGlobalDismissListener()}_syncGlobalDismissListener(){const t=!this._blocked&&"palette"===this._currentModel?.kind,e=!!this._openGroupId||t||!!this._dismissPointerTarget;e!==this._globalDismissListening&&(this._globalDismissListening=e,e?(window.addEventListener("pointerdown",this._globalDismissGuard,!0),window.addEventListener("click",this._globalDismissGuard,!0)):(window.removeEventListener("pointerdown",this._globalDismissGuard,!0),window.removeEventListener("click",this._globalDismissGuard,!0)))}}const zu=t=>t.stopPropagation(),Ou=4.166666666666667e-9;function Nu(t){return Number.isFinite(t)?Math.round(t/$c)*$c:t}const Hu=(t,e,i,s)=>Math.hypot(i-t,s-e),Lu=(t,e,i,s,n,o,a,r)=>Math.hypot(Math.max(Math.abs(n-t),Math.abs(n+a-(t+i))),Math.max(Math.abs(o-e),Math.abs(o+r-(e+s)))),Bu=(t,e,i,s,n,o,a)=>{const r=Math.max(Number(s)||0,0)/2,l=Math.PI/180,c=Math.cos(i*l)*r,h=Math.sin(i*l)*r,d=Math.cos(a*l)*r,p=Math.sin(a*l)*r,u=Math.max(Hu(t+c,e+h,n+d,o+p),Hu(t-c,e-h,n-d,o-p)),_=Math.max(Hu(t+c,e+h,n-d,o-p),Hu(t-c,e-h,n+d,o+p));return Math.min(u,_)},qu=t=>{const e=Number(t?.cell_cm);return e>0?e:5};const Wu=10**9;function ju(t){if(Array.isArray(t))return t.map(t=>ju(t));if(null!==t&&"object"==typeof t){const e={};for(const[i,s]of Object.entries(t))e[i]=ju(s);return e}return t}function Uu(t){if("number"!=typeof t||!Number.isFinite(t))return t;const e=(t<0||Object.is(t,-0)?-1:1)*(Math.floor(Math.abs(t)*Wu+.5)/Wu);return 0===e?0:e}function Gu(t){return null===t||"object"!=typeof t||Array.isArray(t)?null:t}function Vu(t){return Array.isArray(t)?t.filter(t=>null!==Gu(t)):[]}function Ku(t,e){for(const i of e)Object.prototype.hasOwnProperty.call(t,i)&&(t[i]=Uu(t[i]))}function Yu(t){if(Array.isArray(t))for(let e=0;eArray.isArray(t)&&t.length>=2&&Number.isFinite(t[0])&&Number.isFinite(t[1]),i_=(t,e)=>Math.hypot(t[0]-e[0],t[1]-e[1]);function s_(t,e,i){const s=i[0]-e[0],n=i[1]-e[1],o=s*s+n*n;if(o<=0)return i_(t,e);let a=((t[0]-e[0])*s+(t[1]-e[1])*n)/o;return a=Math.max(0,Math.min(1,a)),Math.hypot(t[0]-(e[0]+s*a),t[1]-(e[1]+n*a))}function n_(t,e,i,s,n){for(const s of e)if(s&&!i.has(s.id)&&e_(s.a)&&e_(s.b)&&(i_(t,s.a)<=n||i_(t,s.b)<=n))return!0;for(const e of s?.roomPolygons||[])for(let i=0;i0&&r>0))return null;if(Math.abs(n[0]/a*(o[1]/r)-n[1]/a*(o[0]/r))>i)return null;for(const[i,n]of[[t.a,e.a],[t.a,e.b],[t.b,e.a],[t.b,e.b]])if(i_(i,n)<=s)return[(i[0]+n[0])/2,(i[1]+n[1])/2];return null}function a_(t,e){const i=.05*(Number(e.pitch)>0?Number(e.pitch):1),s=new Map;let n=(t||[]).filter(t=>!!t&&"string"==typeof t.id&&e_(t.a)&&e_(t.b));if(n.length<2)return{partitions:[...t||[]],merged:0,openingMoves:[]};const o=e.seedIds&&e.seedIds.length?new Set(e.seedIds):null;let a=0;for(let t=0;ti_(e,t.at)>i);let h=c[0]??r.a,d=c[c.length-1]??l.b;if(c.length<2&&(h=r.a,d=l.b),d[0]0?(d[0]-h[0])/u:0,g=u>0?(d[1]-h[1])/u:0,m=t=>u>0?((t[0]-h[0])*_+(t[1]-h[1])*g)/u:0;for(const t of[r,l]){const e=m(t.a),i=m(t.b)-e;for(const[n,o]of s)o.toId===t.id&&s.set(n,{fromId:o.fromId,toId:p.id,base:e+o.base*i,span:o.span*i});s.set(t.id,{fromId:t.id,toId:p.id,base:e,span:i})}o&&o.add(p.id),n=n.filter((e,i)=>i!==t.i&&i!==t.j),n.splice(t.i,0,p),a++}return{partitions:n,merged:a,openingMoves:[...s.values()]}}function r_(t,e,i,s){if(!t?.length||!i.length)return 0;const n=new Map(i.map(t=>[t.fromId,t]));let o=0;for(const i of t){const t=i?.host;if(!t||"partition"!==t.kind)continue;const a=n.get(t.id);if(!a)continue;i.host={...t,id:a.toId,t:t_(t.t,a)},o++;const r=Rd(i,e,s.coordScale,s.cellCm,s.gridPitch).resolved;r&&Object.assign(i,Od(i,r,s.coordScale))}return o}function l_(t,e){const i=e?.excludeDraftId||null;return{roomPolygons:(t?.rooms||[]).map(t=>hi(t)).filter(t=>!!t),columns:t?.wall_columns||[],draftEnds:(t?.room_drafts||[]).flatMap(t=>{if(i&&t?.id===i)return[];const e=t?.points||[];return e.length?[e[0],e[e.length-1]]:[]})}}const c_=t=>JSON.parse(JSON.stringify(t)),h_=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),d_=(t,e)=>e.length>0&&e.length<=35&&("space"===t?/^[a-z0-9_-]+$/.test(e):/^[A-Za-z0-9_-]+$/.test(e)),p_=(t,e,i)=>{const s=t.get(e)||[];s.push(i),t.set(e,s)};const u_=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),__=(t,e,i)=>Math.min(i,Math.max(e,t)),g_=t=>yc({spaces:[t]})[0],m_=(t,e,i)=>{const s=i>0?i:1,n=t=>`${(t[0]/s).toFixed(12)},${(t[1]/s).toFixed(12)}`,o=n(t),a=n(e);return o0?a:1,l=Math.max(s*r*.02,1e-9),c=[];for(const e of t||[])for(const t of hi(e)||[])c.push([t[0],t[1]]);for(const t of i||[])Array.isArray(t)&&t.length>=4&&t.slice(0,4).every(Number.isFinite)&&c.push([t[0],t[1]],[t[2],t[3]]);const h=t=>c.some(e=>Math.hypot(t[0]-e[0],t[1]-e[1])<=2*l),d=new Map;for(const a of t||[]){if(!a?.id)continue;const c=hl(t,a.id,e,i,s,n,o,r);if(c)for(let t=0;t0&&p>0&&a===u&&p!==a))continue;const _=c.poly[s],g=c.poly[(s+1)%c.poly.length],m=Math.hypot(g[0]-_[0],g[1]-_[1]);if(!(m>l&&m<.5*o-1e-9*o))continue;if(h(_)||h(g))continue;const f=m_(_,g,r),v=d.get(f);v?v.targets.add(a):d.set(f,{a:[_[0],_[1]],b:[g[0],g[1]],targets:new Set([a])})}}}let p=e.slice();const u=(t,e)=>Math.hypot(t[0]-e[0],t[1]-e[1])<=2*l,_=(t,e)=>{if(!Array.isArray(t.a)||!Array.isArray(t.b)||t.a.length<2||t.b.length<2)return!1;const i=[Number(t.a[0])*r,Number(t.a[1])*r],s=[Number(t.b[0])*r,Number(t.b[1])*r];return!![...i,...s].every(Number.isFinite)&&(u(i,e.a)&&u(s,e.b)||u(i,e.b)&&u(s,e.a))};for(const t of[...d.values()].filter(t=>1===t.targets.size).sort((t,e)=>m_(t.a,t.b,r).localeCompare(m_(e.a,e.b,r)))){const e=[...t.targets][0],i=p.filter(e=>_(e,t));if(new Set(i.map(t=>t.cm)).size>1)continue;let n=!1;p=p.map(i=>_(i,t)?(n=!0,i.cm===e?i:{...i,cm:e}):i),n||(p=Nr(p,t.a,t.b,e,s,r))}return p}const v_=t=>{const e=[];for(const i of t||[]){const t=hi(i);if(t?.length)for(let i=0;i"string"==typeof t?.id?t.id:"").filter(Boolean),h=new Set(c),d=new Map;for(const t of c){const e=/^space_(.+)_([0-9a-f]{8})$/.exec(t);e&&p_(d,e[1],t)}const p=new Map,u=new Map,_=new Map;for(const t of r){const e="string"==typeof t?.id?t.id:"";if(!e)continue;const i=new Map;for(const s of Array.isArray(t.rooms)?t.rooms:[]){const t="string"==typeof s?.id?s.id:"";if(!t)continue;const n=/^room_(.+)_([0-9a-f]{8})$/.exec(t);n&&p_(i,n[1],t),u.has(t)||u.set(t,e);const o="string"==typeof s.area?s.area:"";if(o){const i=_.get(o)||[];i.push({spaceId:e,roomId:t}),_.set(o,i)}}p.set(e,i)}const g=new Set(u.keys()),m=new Set,f=new Set;for(const t of l)"string"==typeof t?.id&&t.id&&(!0===t.removed?f:m).add(t.id);const v={spaceRefsRemapped:0,roomRefsRemapped:0,positionsRemapped:0,markersDetached:0,positionsUnresolved:0,nestedRefsUnresolved:0,deadSpaceIds:[]},y=new Set,b=t=>h.has(t)||!d_("space",t)?null:1===d.get(t)?.length?d.get(t)[0]:null,w=(t,e)=>{if(!d_("room",t))return null;const i=p.get(e)?.get(t)||[];return 1===i.length?i[0]:null},k=t=>{const e=i.effectiveAreaByMarker?.[t]||"",s=e&&_.get(e)||[];return 1===s.length?s[0]:null},x=(t,e,i)=>{if("string"==typeof t.room_id&&t.room_id&&!g.has(t.room_id)){const s=e?w(t.room_id,e):null;s?(t.room_id=s,v.roomRefsRemapped++):i?(t.room_id=i.roomId,v.roomRefsRemapped++):!0!==t.removed&&delete t.room_id}const s=t.vacuum?.segment_map;if(s&&"object"==typeof s&&!Array.isArray(s))for(const t of Object.keys(s)){const i=s[t];if("string"!=typeof i||!i||g.has(i))continue;const n=e?w(i,e):null;n?(s[t]=n,v.roomRefsRemapped++):v.nestedRefsUnresolved++}};for(const t of l){const e="string"==typeof t?.id?t.id:"";if(!e)continue;const i="string"==typeof t.space?t.space:"",s=i&&!h.has(i),o=n[e],a="string"==typeof o?.s?o.s:"",r=a&&!h.has(a),l=!0===t.removed;let c=i&&h.has(i)?i:null,d=null,p=!1;if(s){const s=b(i);s?(t.space=s,c=s,p=!0,v.spaceRefsRemapped++):l||"virtual"===t.binding?l||(delete t.space,c=null,v.markersDetached++):(d=k(e),d?(t.space=d.spaceId,c=d.spaceId,v.spaceRefsRemapped++):(delete t.space,c=null,v.markersDetached++))}l&&!p||x(t,c,d),r&&(p&&a===i&&c?(n[e]={...o,s:c},v.positionsRemapped++,y.add(e)):l||(delete n[e],y.add(e)))}for(const t of Object.keys(n)){if(y.has(t))continue;const e=n[t],i="string"==typeof e?.s?e.s:"";if(!i||h.has(i))continue;const s=b(i);if(s){if(t.startsWith("rl_")){const i=t.slice(3),o=w(i,s);if(o){const i=`rl_${o}`;h_(n,i)||(n[i]={...e,s:s}),delete n[t],v.roomRefsRemapped++,v.positionsRemapped++;continue}}n[t]={...e,s:s},v.positionsRemapped++}}const $=new Set;for(const t of l){const e="string"==typeof t?.space?t.space:"";e&&!h.has(e)&&$.add(e)}for(const[t,e]of Object.entries(n)){const i="string"==typeof e?.s?e.s:"";i&&!h.has(i)&&($.add(i),m.has(t)&&!f.has(t)||v.positionsUnresolved++)}return v.deadSpaceIds=[...$].sort((t,e)=>t.localeCompare(e)),{config:s,layout:n,report:v,changed:JSON.stringify(s)!==o||JSON.stringify(n)!==a}}(t,e,i),n=s.config,o=JSON.stringify(t||{}),a=JSON.stringify(e||{}),r=Number.isInteger(Number(n.model_version))?Number(n.model_version):0,l=(t=>{let e=0,i=0,s=0;for(const i of t.markers||[]){if("ripple"===i.display&&(i.display="icon_ripple",e++),Array.isArray(i.controls)){const t="string"==typeof i.binding&&i.binding.startsWith("entity:")?i.binding.slice(7):"",s=t?i.controls.filter(e=>e!==t):i.controls;JSON.stringify(s)!==JSON.stringify(i.controls)&&(i.controls=s.length?s:null,e++)}const t=i.vacuum;t&&u_(t,"trail")&&(["never","cleaning","always"].includes(t.trail_mode)||(t.trail_mode=!1===t.trail?"never":"cleaning"),delete t.trail,e++)}for(const n of t.spaces||[]){const t=n.settings;"glow"===t?.fill_mode&&("boolean"!=typeof t.glow_enabled&&(t.glow_enabled=!0),t.fill_mode="none",e++,i++);for(const t of n.rooms||[]){const i=t.settings;"glow"===i?.fill_mode&&("boolean"!=typeof i.glow&&(i.glow=!0),delete i.fill_mode,e++,s++)}if(u_(n,"segments")&&(delete n.segments,e++),u_(n,"plan_scale")){const t=Number(n.plan_scale);Number.isFinite(t)&&t>=gc&&t<=mc&&(u_(n,"plan_scale_x")||(n.plan_scale_x=t),u_(n,"plan_scale_y")||(n.plan_scale_y=t),delete n.plan_scale,e++)}const o=Number(n.cell_cm);u_(n,"cell_cm")&&(!Number.isFinite(o)||o<.1||o>1e3)&&(n.cell_cm=Number.isFinite(o)&&o>0?__(o,.1,1e3):5,e++);const a=Number(n.cell_cm),r=Number.isFinite(a)&&a>0?a:5;for(const t of n.wall_columns||[])if("circle"===t.shape)u_(t,"angle")&&(delete t.angle,e++);else if("square"===t.shape&&u_(t,"angle")){const i=((Number(t.angle)||0)%90+90)%90;t.angle!==i&&(t.angle=i,e++)}for(const t of n.decor||[]){if(u_(t,"width")){const i=Number(t.width);(u_(t,"width_cm")||Number.isFinite(i))&&(u_(t,"width_cm")||(t.width_cm=Number(__(i/xc*r,.1,100).toFixed(6))),delete t.width,e++)}if("rect"!==t?.kind&&"ellipse"!==t?.kind||!0!==t.fill||(u_(t,"fill_color")||(t.fill_color=t.color||"#607d8b",e++),u_(t,"fill_opacity")||(t.fill_opacity=.25,e++)),"text"!==t?.kind)continue;void 0===t.size_cm?(t.size_cm=Number(__(es*is(t)/xc*r,.1,2e3).toFixed(6)),delete t.scale,delete t.size,e++):(u_(t,"scale")||u_(t,"size"))&&(delete t.scale,delete t.size,e++);let i=String(t.text??"");const s=[...i.matchAll(/\{([^{}\r\n]+)\}/g)].some(t=>!!Yi(t[1]));if(!(u_(t,"entity")||u_(t,"attr")||u_(t,"unit")))continue;const n=String(t.unit??"").trim(),o="state"===String(t.attr??"").trim().toLowerCase()?null:t.attr,a=s||n?"":Xi(t.entity,o);if(s||a){if(a){const e=i.indexOf("{}");i=e>=0?i.slice(0,e)+a+i.slice(e+2):`${i}${i?" ":""}${a}`,t.text=i}delete t.entity,delete t.attr,delete t.unit,e++}}}return{total:e,glowSpaces:i,glowRooms:s}})(n);let c=l.total;for(const t of n.spaces||[]){const e=g_(t);if(!e)continue;if(!rh(t.open_spans).length){const i=ph(e.rooms,null,uc,.02*xc,!0);i.length&&(t.open_spans=uh(i,uc),c++)}}const h=(d=n.spaces||[],JSON.parse(JSON.stringify(d)));var d;const p=function(t,e){const i=JSON.parse(JSON.stringify(t||[])),s=JSON.parse(JSON.stringify(e||{}));let n=0,o=0,a=0,r=0,l="",c=0,h=0,d=0;const p=(t,e)=>{Number.isFinite(t)&&Number.isFinite(e)&&t!==e&&Math.abs(e-t)<=Ou&&h++},u=(t,e)=>{p(t[0],e[0]),p(t[1],e[1])},_={};let g=5;for(const t of i){const e=qu(t);null!=t?.id&&(_[String(t.id)]=e),e>g&&(g=e)}const m=(t,e,i,s=!1)=>{if(!(t>Ou||s))return;n++,t>a&&(a=t);const o=t*kc*e;o>r&&(r=o,l=i)};for(const t of i){const e=qu(t),i=null!=t?.id?String(t.id):"";for(const s of t.rooms||[]){o++;let t=0;if(s.poly?.length)s.poly=s.poly.map(e=>{const i=[Nu(e[0]),Nu(e[1])];return t=Math.max(t,Hu(e[0],e[1],i[0],i[1])),u(e,i),i});else if(null!=s.x&&null!=s.y){const e=s.x,i=s.y,n=s.w||0,o=s.h||0,a=Nu(e+n),r=Nu(i+o),l=Nu(e),c=Nu(i),h=Math.max($c,a-l),d=Math.max($c,r-c);t=Lu(e,i,n,o,l,c,h,d),s.x=l,s.y=c,s.w=h,s.h=d,p(e,l),p(i,c),p(e+n,l+h),p(i+o,c+d)}m(t,e,i)}for(const s of t.room_drafts||[]){o++;let t=0;const n=s.points||[],a=n.map(e=>{const i=[Nu(e[0]),Nu(e[1])];return t=Math.max(t,Hu(e[0],e[1],i[0],i[1])),i}),r=a.length?[a[0]]:[],l=a.length?[[n[0],a[0]]]:[],c=[];for(let t=0;t+1=2)for(const[t,e]of l)u(t,e);m(t,e,i)}if(Array.isArray(t.room_drafts)){const e=t.room_drafts.length;t.room_drafts=t.room_drafts.filter(t=>t.points?.length>=2),d+=e-t.room_drafts.length,t.room_drafts.length||delete t.room_drafts}for(const s of t.partitions||[]){o++;const n=[s.a[0],s.a[1]],a=[s.b[0],s.b[1]],r=[Nu(n[0]),Nu(n[1])],l=[Nu(a[0]),Nu(a[1])];let c=Math.max(Hu(n[0],n[1],r[0],r[1]),Hu(a[0],a[1],l[0],l[1]));const h=Hu(r[0],r[1],l[0],l[1]),d=(t.openings||[]).filter(t=>"partition"===t.host?.kind&&t.host.id===s.id).every(t=>{const e=Number(t.length),i=Number(t.host.t),s=i*h;return Number.isFinite(e)&&e>0&&Number.isFinite(i)&&i>=0&&i<=1&&s-e/2>=-Ou&&s+e/2<=h+Ou});h>Ou&&d?(s.a=r,s.b=l,u(n,r),u(a,l)):c=0,m(c,e,i)}for(const s of t.wall_columns||[]){o++;const t=[s.center[0],s.center[1]],n=[Nu(t[0]),Nu(t[1])],a=Hu(t[0],t[1],n[0],n[1]);s.center=n,u(t,n),m(a,e,i)}for(const s of t.decor||[]){o++;let t=0;if("line"===s.kind){const e=[s.x1,s.y1],i=[s.x2,s.y2],n=[Nu(e[0]),Nu(e[1])],o=[Nu(i[0]),Nu(i[1])];t=Math.max(Hu(e[0],e[1],n[0],n[1]),Hu(i[0],i[1],o[0],o[1])),s.x1=n[0],s.y1=n[1],s.x2=o[0],s.y2=o[1],u(e,n),u(i,o)}else{const e=s.x,i=s.y,n=s.w,o=s.h,a=Nu(e),r=Nu(i);if(null!=s.w&&null!=s.h){const l=Nu(e+n),c=Nu(i+o),h=Math.max($c,l-a),d=Math.max($c,c-r);t=Lu(e,i,n,o,a,r,h,d),s.w=h,s.h=d,p(e+n,a+h),p(i+o,r+d)}else t=Hu(e,i,a,r);s.x=a,s.y=r,p(e,a),p(i,r)}m(t,e,i)}for(const s of t.openings||[]){if(o++,"partition"===s.host?.kind){const n=(t.partitions||[]).find(t=>t.id===s.host.id),o=Number(s.host.t);if(!n||!Number.isFinite(o)||o<0||o>1)continue;const a=n.b[0]-n.a[0],r=n.b[1]-n.a[1];if(Math.hypot(a,r)<=Ou)continue;const l=n.a[0]+a*o,h=n.a[1]+r*o;let d=180*Math.atan2(r,a)/Math.PI;d>=90?d-=180:d<-90&&(d+=180);const p=Number(s.angle),u=!(Number.isFinite(p)&&p===d),_=Bu(s.x,s.y,Number.isFinite(p)?p:d,Number(s.length)||0,l,h,d);s.x=l,s.y=h,s.angle=d,u&&c++,m(_,e,i,u);continue}const n=ui([s.x,s.y],t.rooms||[],.025,{step:$c,length:Number(s.length)||0});if(!n)continue;const a=Number(s.angle),r=!(Number.isFinite(a)&&a===n.angle),l=Bu(s.x,s.y,Number.isFinite(a)?a:n.angle,Number(s.length)||0,n.x,n.y,n.angle);s.x=n.x,s.y=n.y,s.angle=n.angle,r&&c++,m(l,e,i,r)}}for(const[t,e]of Object.entries(s)){if(!e||"object"!=typeof e)continue;const i=e;if("number"!=typeof i.x||"number"!=typeof i.y)continue;o++;const n=Nu(i.x),a=Nu(i.y),r=Hu(i.x,i.y,n,a);s[t]={...i,x:n,y:a},p(i.x,n),p(i.y,a);const l="string"==typeof i.s?i.s:"";m(r,_[l]??g,l)}return{spaces:i,layout:s,report:{moved:n,coordsCanonicalized:h,total:o,maxShift:a,maxShiftCm:r,maxSpace:l,rotated:c,removedDrafts:d},changed:n>0||h>0}}(n.spaces||[],s.layout);n.spaces=p.spaces;const u={...p.report};let _=0,g=0,m=0,f=0;for(let t=0;t[t.id,t.open_to||[]]),walls:e.walls||[]}),o=g_(e),a=g_(i);if(!o||!a)continue;const r=v_(o.rooms),l=v_(a.rooms),c=.02*xc;let d=wh(rh(e.open_spans),r,l,uc);const p=d.length;d=bh(d,a.rooms,uc,c),d=d.map(t=>{const e=oh(t,uc),s=[e[0],e[1]],n=[e[2],e[3]],o=[(e[0]+e[2])/2,(e[1]+e[3])/2],a=e[2]-e[0],r=e[3]-e[1],h=Math.hypot(a,r)||1,d=l.map(([t,e])=>[t[0],t[1],e[0],e[1]]).filter(t=>{const e=t[2]-t[0],i=t[3]-t[1],l=Math.hypot(e,i)||1;return Math.abs(a*i-r*e)/(h*l)<=1e-6&&lh(o,t).d<=4*c&&lh(s,t).d<=4*c&&lh(n,t).d<=4*c}).sort((t,e)=>Math.hypot(e[2]-e[0],e[3]-e[1])-Math.hypot(t[2]-t[0],t[3]-t[1]))[0];if(u.total++,!d)return t;const p=[[d[0],d[1]],[d[2],d[3]]],_=hh(s,d,p,xc,2*c),g=hh(n,d,p,xc,2*c);if(Math.hypot(g[0]-_[0],g[1]-_[1])<.5*xc)return t;const m=Math.max(Math.hypot(_[0]-s[0],_[1]-s[1]),Math.hypot(g[0]-n[0],g[1]-n[1]));if(m>1e-6*xc){u.moved++;const t=m/uc;t>u.maxShift&&(u.maxShift=t);const e=m/xc*(Number(i.cell_cm)>0?Number(i.cell_cm):5);e>u.maxShiftCm&&(u.maxShiftCm=e,u.maxSpace=String(i.id||""))}return nh(_,g,uc)}),d=bh(d,a.rooms,uc,c),g+=Math.max(0,p-d.length);const v=d.map(t=>oh(t,uc));d.length?i.open_spans=d:delete i.open_spans,_h(i.rooms||[],a.rooms,v,c);const y=Array.isArray(e.walls)?e.walls.length:0;let b=Or(e.walls,r,l,$c,uc);b=f_(a.rooms,b,v,$c,Number(i.cell_cm)>0?Number(i.cell_cm):5,xc,uc),b=ul(a.rooms,b,v,$c,Number(i.cell_cm)>0?Number(i.cell_cm):5,xc,uc),b=Er(b,i.rooms||[],$c,1,v.map(t=>[t[0]/uc,t[1]/uc,t[2]/uc,t[3]/uc])),_+=Math.max(0,y-b.length),b.length?i.walls=b:delete i.walls;const w=a_(i.partitions||[],{pitch:$c,geometry:l_(i)});w.merged&&(m+=w.merged,i.partitions=w.partitions,r_(i.openings,i.partitions,w.openingMoves,{coordScale:uc,cellCm:Number(i.cell_cm)>0?Number(i.cell_cm):5,gridPitch:xc}));const k=JSON.stringify({spans:i.open_spans||[],links:(i.rooms||[]).map(t=>[t.id,t.open_to||[]]),walls:i.walls||[]});k!==s&&f++}const v=Qu(n),y=Zu(p.layout),b=JSON.stringify(v)!==o||JSON.stringify(y)!==a;r<7&&b&&(v.model_version=7);const w=JSON.stringify(v)!==o||JSON.stringify(y)!==a,k=Number.isInteger(Number(v.model_version))?Number(v.model_version):r,x=w?u:{...u,moved:0,coordsCanonicalized:0,maxShift:0,maxShiftCm:0,maxSpace:"",rotated:0,removedDrafts:0},$=w?s.report:{...s.report,spaceRefsRemapped:0,roomRefsRemapped:0,positionsRemapped:0,markersDetached:0};return{config:v,layout:y,report:{...x,modelFrom:r,modelTo:k,migrated:w?c:0,glowSpacesMigrated:w?l.glowSpaces:0,glowRoomsMigrated:w?l.glowRooms:0,canonicalized:w?f:0,wallsMerged:w?_:0,spansMerged:w?g:0,partitionsMerged:w?m:0,...$},changed:w}}function b_(t,e,i){const s=(t?.spaces||[]).find(t=>t?.id===i),n=new Set((s?.rooms||[]).map(t=>String(t?.id||"")).filter(Boolean)),o=[...new Set((t?.markers||[]).filter(t=>!0!==t?.removed&&"string"==typeof t?.id).filter(t=>t.space===i||"string"==typeof t.room_id&&n.has(t.room_id)||e?.[t.id]?.s===i).map(t=>t.id))].sort((t,e)=>t.localeCompare(e));return{markerIds:o,count:o.length}}function w_(t,e,i=xc,s=1e3){return ph(e.rooms,t?.open_spans,s,.02*i)}function k_(t,e,i=xc){if(!e.length)return[];const s=t.filter(t=>t?.id),n=.02*i,o=[];for(let t=0;t{const e=[(t[0]+t[2])/2,(t[1]+t[3])/2];return h.some(t=>Hs(e,t)<4*n)}).map(t=>[...t]);d.length&&o.push({a:a,b:r,segs:d})}return o}function x_(t,e,i,s=xc,n=1e3){return(Array.isArray(t?.openings)?t.openings:[]).flatMap(t=>{const o={...t,rx:Number(t.x)*n,ry:Number(t.y)*n,rlen:Number(t.length)*n};if(!t.host)return[o];const a=Rd(t,e.partitions,n,i,s);return a.resolved?[{...t,rx:a.resolved.center[0],ry:a.resolved.center[1],rlen:a.resolved.length,angle:a.resolved.angle,partitionHost:a.resolved}]:[]})}function $_(t,e=()=>!0){return t.flatMap(t=>t.host&&t.partitionHost&&e(t)?[Fd(t.partitionHost)]:[])}function S_(t,e,i,s,n,o,a=xc,r=1e3){const l=dl(e.rooms,[...i],s,n,o,a,r);return t.flatMap(t=>{const e={x:t.rx,y:t.ry,angle:Number(t.angle)||0,length:t.rlen};return t.host?t.partitionHost&&zd(t.partitionHost,l,2e-4*a)?[e]:[]:[e]})}function M_(t,e){const i=$c,s=xc,n=uc,o=Number.isFinite(Number(e.cellCm))&&Number(e.cellCm)>0?Number(e.cellCm):5,a=Array.isArray(t?.walls)?t.walls:[],r=w_(t,e,s,n),l=k_(e.rooms,r,s).flatMap(t=>t.segs),c=x_(t,e,o,s,n),h=$_(c),d=Jl(e,o,s,2e-4*s,h).all;return{space:e,walls:a,openCuts:l,openings:c,roomOpenings:S_(c,e,a,l,i,o,s,n),partitionCuts:h,physicalBodies:d,wallKeyPitch:i,cellCm:o,gridPitch:s,coordScale:n}}function C_(t,e,i){const s="string"==typeof t?.title?t.title.trim():"",n=null==t?.id?"":String(t.id).trim();return{spaceId:n,displayName:s||n||i(e+1)}}class D_{constructor(t=50){this._undo=[],this._redo=[],this._limit=Math.max(30,Math.floor(t))}get canUndo(){return this._undo.length>0}get canRedo(){return this._redo.length>0}get undoName(){return this._undo[this._undo.length-1]?.name??null}get redoName(){return this._redo[this._redo.length-1]?.name??null}get size(){return this._undo.length}push(t){this._undo.push(t),this._undo.length>this._limit&&this._undo.splice(0,this._undo.length-this._limit),this._redo=[]}undo(){const t=this._undo.pop()??null;return t&&this._redo.push(t),t}redo(){const t=this._redo.pop()??null;return t&&this._undo.push(t),t}clear(){this._undo=[],this._redo=[]}}const T_=new WeakMap;const P_=(t,e,i)=>255===t[i+3]&&e.every((e,s)=>Math.abs(t[i+s]-e)<=2);async function R_(t){const e=t.defaultView;if(!e||!e.CSS?.supports?.("mix-blend-mode","screen"))return!1;const i=[128,32,16],s=[16,64,128],n=[9,19,29],o=`\n \n \n \n \n \n `,a=e.URL.createObjectURL(new Blob([o],{type:"image/svg+xml"}));try{const o=await new Promise((t,i)=>{const s=new e.Image,n=e.setTimeout(()=>i(new Error("SVG blend probe timeout")),1e3);s.onload=()=>{e.clearTimeout(n),t(s)},s.onerror=()=>{e.clearTimeout(n),i(new Error("SVG blend probe failed"))},s.src=a}),r=t.createElement("canvas");r.width=4,r.height=1;const l=r.getContext("2d",{willReadFrequently:!0});if(!l)return!1;l.drawImage(o,0,0,4,1);const c=l.getImageData(0,0,4,1).data;return P_(c,i,0)&&P_(c,function(t,e){return[0,1,2].map(i=>Math.round(255-(255-t[i])*(255-e[i])/255))}(i,s),4)&&P_(c,s,8)&&P_(c,n,12)}catch{return!1}finally{e.URL.revokeObjectURL(a)}}const I_={now:()=>performance.now(),requestFrame:t=>requestAnimationFrame(t),cancelFrame:t=>cancelAnimationFrame(t)},A_=t=>Math.max(0,Math.min(1,t)),F_=(t,e,i)=>t+(e-t)*i,E_=(t,e,i)=>{const s=1-t;return 3*s*s*t*e+3*s*t*t*i+t*t*t};function z_(t,e){return{centerX:t.x+t.w/2,centerY:t.y+t.h/2,pixelsPerUnit:e>0&&t.w>0?e/t.w:1,viewBox:{...t}}}function O_(t,e,i){const s=Math.max(1e-9,t.pixelsPerUnit),n=Math.max(1e-9,e/s),o=Math.max(1e-9,i/s);return{x:t.centerX-n/2,y:t.centerY-o/2,w:n,h:o}}function N_(t){const e=t.trim(),i=/^rgba?\(\s*([\d.]+)[, ]+([\d.]+)[, ]+([\d.]+)(?:\s*[,/]\s*([\d.]+))?\s*\)$/i.exec(e);if(i)return[Number(i[1]),Number(i[2]),Number(i[3]),null==i[4]?1:Number(i[4])];const s=/^#([0-9a-f]{6}|[0-9a-f]{8})$/i.exec(e)?.[1];return s?[parseInt(s.slice(0,2),16),parseInt(s.slice(2,4),16),parseInt(s.slice(4,6),16),8===s.length?parseInt(s.slice(6,8),16)/255:1]:null}function H_(t,e,i){const s=N_(t),n=N_(e);if(!s||!n)return i<.5?t:e;const o=A_(i);return`rgba(${Math.round(F_(s[0],n[0],o))}, ${Math.round(F_(s[1],n[1],o))}, ${Math.round(F_(s[2],n[2],o))}, ${F_(s[3],n[3],o).toFixed(3)})`}function L_(t,e,i){const s=(t=>{const e=A_(t);if(0===e||1===e)return e;let i=0,s=1,n=e;for(let t=0;t<12;t++)n=(i+s)/2,E_(n,.2,.2){const e=this._state;if(!e||e.token!==n)return;const i=A_((t-e.startedAt)/e.duration);e.presented=i>=1?e.to:L_(e.from,e.to,i),e.phase=i>=1?"settling":"running",this._hooks.frame(e),i<1?this._raf=this._clock.requestFrame(a):(this._raf=0,this._hooks.settled(e),this._state?.token===n&&(this._state=null))};return this._raf=this._clock.requestFrame(a),n}cancel(t=!0){this._raf&&this._clock.cancelFrame(this._raf),this._raf=0;const e=this._state;this._state=null,this._token++,e&&t&&(e.phase="settling",e.presented=e.to,this._hooks.frame(e),this._hooks.settled(e))}dispose(){this.cancel(!1)}}const q_="houseplan_card_labs_v1",W_=Object.freeze([Object.freeze({id:"iso",issue:89,since:"1.62.0",expires:"1.65.0",summary:"Volumetric plan renderer"})]);function j_(t){const e=/^(\d+)\.(\d+)\.(\d+)(?:-[0-9A-Za-z.-]+)?$/.exec(String(t||"").trim());if(!e)return null;const i=e.slice(1).map(Number);return i.every(t=>Number.isSafeInteger(t))?i:null}function U_(t,e){for(let i=0;i<3;i++)if(t[i]!==e[i])return t[i]t.split(",")).map(t=>t.trim()).filter(Boolean)}function J_(t,e,i,s=W_){const n=function(t,e=W_){const i=j_(t),s=new Map;if(!i||!V_(e))return s;for(const t of e){const e=j_(t.since),n=j_(t.expires);U_(i,e)>=0&&U_(i,n)<0&&s.set(t.id,t)}return s}(i,s),o=new Set(V_(s)?s.map(t=>t.id):[]),a=new Set(function(t){if(!t)return[];try{const e=JSON.parse(t);return Array.isArray(e)?e.filter(t=>"string"==typeof t):[]}catch{return[]}}(e).filter(t=>n.has(t)));let r=!1;const l=t=>{if("off"===t)return a.clear(),void(r=!0);const e=t.startsWith("-"),i=e?t.slice(1):t;o.has(i)&&(r=!0,e||!n.has(i)?a.delete(i):a.add(i))};for(const e of X_(new URLSearchParams(String(t.search||"").replace(/^\?/,""))))l(e);for(const e of X_(K_(t.hash)))l(e);const c=Object.freeze([...a].sort());return{active:c,space:Y_(t.hash),persist:r?JSON.stringify(c):void 0,knownUrlOperation:r}}let Z_={active:Object.freeze([]),space:""},Q_="",tg=!1,eg="";const ig=new Set;function sg(){if("undefined"==typeof window)return Z_;const t=J_(window.location,function(){try{return window.localStorage.getItem(q_)}catch{return null}}(),Q_);void 0!==t.persist&&function(t){try{window.localStorage.setItem(q_,t)}catch{}}(t.persist),Z_={active:t.active,space:t.space},window.__hpLabs=t.active;for(const t of ig)t(Z_);return Z_}function ng(){sg()}function og(t){return Q_=t,"undefined"==typeof window?Z_:(tg||(tg=!0,window.addEventListener("hashchange",ng),window.addEventListener("popstate",ng)),sg())}const ag=Object.freeze({rotDeg:0,tiltDeg:20,xyScale:1,zScale:1,origin:Object.freeze([500,500])});function rg(t){return[t.rotDeg,t.tiltDeg,t.xyScale,t.zScale,t.origin[0],t.origin[1]].every(Number.isFinite)&&Math.abs(t.xyScale)>1e-12&&Math.abs(Math.cos(t.tiltDeg*Math.PI/180))>1e-12}function lg(t,e,i=ag){if(!(rg(i)&&Number.isFinite(t[0])&&Number.isFinite(t[1])&&Number.isFinite(e)))throw new Error("invalid isometric projection input");const s=i.rotDeg*Math.PI/180,n=i.tiltDeg*Math.PI/180,o=t[0]-i.origin[0],a=t[1]-i.origin[1],r=(o*Math.cos(s)-a*Math.sin(s))*i.xyScale,l=(o*Math.sin(s)+a*Math.cos(s))*i.xyScale;return[i.origin[0]+r,i.origin[1]+l*Math.cos(n)-e*i.zScale*Math.sin(n)]}function cg(t,e=ag){if(!rg(e)||!Number.isFinite(t[0])||!Number.isFinite(t[1]))throw new Error("invalid isometric projection input");const i=e.rotDeg*Math.PI/180,s=e.tiltDeg*Math.PI/180,n=(t[0]-e.origin[0])/e.xyScale,o=(t[1]-e.origin[1])/(e.xyScale*Math.cos(s));return[e.origin[0]+n*Math.cos(i)+o*Math.sin(i),e.origin[1]-n*Math.sin(i)+o*Math.cos(i)]}function hg(t=ag){return`matrix(${function(t=ag){if(!rg(t))throw new Error("invalid isometric camera");const e=t.rotDeg*Math.PI/180,i=t.tiltDeg*Math.PI/180,s=t.xyScale*Math.cos(e),n=-t.xyScale*Math.sin(e),o=t.xyScale*Math.sin(e)*Math.cos(i),a=t.xyScale*Math.cos(e)*Math.cos(i);return[s,o,n,a,t.origin[0]-s*t.origin[0]-n*t.origin[1],t.origin[1]-o*t.origin[0]-a*t.origin[1]]}(t).map(t=>Number(t.toFixed(12))).join(" ")})`}function dg(t,e=ag){const{rect:i,wallHeight:s}=t,n=t.openingHeight??s,o=t.floorDepth??0;if(!(i.w>=0)||!(i.h>=0)||!Number.isFinite(s)||!Number.isFinite(n)||!Number.isFinite(o)||s<0||n<0||o<0)throw new Error("invalid isometric frame");const a=[[i.x,i.y],[i.x+i.w,i.y],[i.x+i.w,i.y+i.h],[i.x,i.y+i.h]],r=Math.max(s,n),l=a.flatMap(t=>[lg(t,-o,e),lg(t,r,e)]),c=l.map(t=>t[0]),h=l.map(t=>t[1]),d=Math.min(...c),p=Math.min(...h);return{x:d,y:p,w:Math.max(...c)-d,h:Math.max(...h)-p}}const pg=t=>`${Number(t[0].toFixed(4))} ${Number(t[1].toFixed(4))}`;function ug(t){let e=0;for(let i=0;iArray.isArray(t)&&Number.isFinite(t[0])&&Number.isFinite(t[1])).map(t=>[Number(t[0]),Number(t[1])]),i=e[e.length-1];return e.length>1&&e[0][0]===i[0]&&e[0][1]===i[1]&&e.pop(),e}(t);if(i.length<3)return[];const s=!e;return ug(i)>0===s?i:[...i].reverse()}function gg(t,e,i){return t.length?`M ${t.map(t=>pg(lg(t,i,e))).join(" L ")} Z`:""}function mg(t,e,i){const s=e[1]-t[1],n=-(e[0]-t[0]),o=i.rotDeg*Math.PI/180;return s*Math.sin(o)+n*Math.cos(o)}function fg(t,e,i=ag){if(!Number.isFinite(e)||e<0)throw new Error("invalid floor edge height");const s=(t||[]).map(t=>{const e=(t||[]).map((t,e)=>function(t,e){const i=_g(t,e);if(!i.length)return i;let s=0;for(let t=1;t0)).filter(t=>t.length>=3&&Math.abs(ug(t))>=1e-9);return e}).filter(t=>t.length&&ug(t[0])>0);s.sort((t,e)=>{const i=t[0][0],s=e[0][0];return i[0]-s[0]||i[1]-s[1]||Math.abs(ug(e[0]))-Math.abs(ug(t[0]))});const n=[],o=[];let a=0;for(let t=0;tt.depth-e.depth||t.component-e.component||t.edge-e.edge),{footprintPath:n.join(" "),sides:o,componentCount:s.length,edgeCount:a}}function vg(t,e){return t^=Math.round(64*(Number.isFinite(e)?e:0)),Math.imul(t,16777619)>>>0}const yg=t=>t.every(Number.isFinite);function bg(t,e,i,s){const n=t[0]*i,o=t[1]*s,a=e*Math.PI/180;return[n*Math.cos(a)-o*Math.sin(a),n*Math.sin(a)+o*Math.cos(a)]}function wg(t,e,i,s,n,o,a){const r=t.flipH?-1:1,l="gate"===t.type?1:t.flipV?-1:1,c=(t.type,t.flipV,t.angle,t.face,{ox:0,oy:0}),h=function(t,e){return[t[0]+e[0],t[1]+e[1]]}([t.x+c.ox,t.y+c.oy],bg(i,t.angle,r,l));return{leaf:e,hinge:h,closedVector:bg(s,t.angle,r,l),quarterVector:bg([-s[1],s[0]],t.angle,r,l),turnDeg:n,bottom:o,top:a}}const kg=t=>`${Number(t[0].toFixed(4))} ${Number(t[1].toFixed(4))}`;function xg(t,e,i=ag){const s=Math.max(0,Math.min(1,Number.isFinite(e)?e:0));return t.leaves.map(e=>{const n=function(t,e){const i=t.turnDeg*e*Math.PI/180;return[t.hinge[0]+t.closedVector[0]*Math.cos(i)+t.quarterVector[0]*Math.sin(i),t.hinge[1]+t.closedVector[1]*Math.cos(i)+t.quarterVector[1]*Math.sin(i)]}(e,s),o=lg(e.hinge,e.bottom,i),a=lg(n,e.bottom,i),r=lg(n,e.top,i),l=lg(e.hinge,e.top,i);return{id:t.id,sourceIndex:t.sourceIndex,type:t.type,leaf:e.leaf,d:`M ${kg(o)} L ${kg(a)} L ${kg(r)} L ${kg(l)} Z`,shadowD:`M ${kg(lg(e.hinge,0,i))} L ${kg(lg(n,0,i))}`,depth:Math.max(o[1],a[1])}})}const $g={window:120,door:90,passage:90,gate:300};function Sg(t){return $g[t]}function Mg(t,e){const i=[t[0],t[1]],s=[e[0],e[1]];return function(t,e){return t[0]-e[0]||t[1]-e[1]}(i,s)<=0?{a:i,b:s}:{a:s,b:i}}function Cg(t){const e=new Map;return t.forEach((t,i)=>{if(!t.kind||t.open)return;const s=Mg(t.a,t.b);if(Math.hypot(s.b[0]-s.a[0],s.b[1]-s.a[1])<=1e-9)return;const n=function(t,e){const i=t=>(Math.abs(t)<=5e-10?0:Math.round(1e6*t)/1e6).toFixed(6);return`${i(t[0])},${i(t[1])}>${i(e[0])},${i(e[1])}`}(s.a,s.b),o=e.get(n);if(o)return o.physicalHalfWidth=Math.max(o.physicalHalfWidth,t.half||0),o.sourceOrder=Math.min(o.sourceOrder,i),void(t.partitionHost&&(o.partitionHost&&o.partitionHost.id!==t.partitionHost.id?o.ambiguousPartitionHost=!0:o.partitionHost=t.partitionHost));e.set(n,{segmentKey:n,a:s.a,b:s.b,physicalHalfWidth:Math.max(0,t.half||0),sourceOrder:i,...t.partitionHost?{partitionHost:t.partitionHost}:{}})}),[...e.values()]}function Dg(t,e){if(Math.abs(t.distance-e.distance)>1e-9)return t.distance-e.distance;if(Math.abs(t.perpendicular-e.perpendicular)>1e-9)return t.perpendicular-e.perpendicular;return(t.target.segmentKeye.target.segmentKey?1:0)||t.target.sourceOrder-e.target.sourceOrder}function Tg(t){const e=Cg(t.intervals).map(e=>{const i=function(t,e){const i=e.b[0]-e.a[0],s=e.b[1]-e.a[1],n=Math.hypot(i,s),o=i/n,a=s/n,r=(t[0]-e.a[0])*o+(t[1]-e.a[1])*a,l=Math.max(0,Math.min(n,r)),c=e.a[0]+l*o,h=e.a[1]+l*a;return{along:l,length:n,x:c,y:h,distance:Math.hypot(t[0]-c,t[1]-h),perpendicular:Math.abs((t[0]-e.a[0])*a-(t[1]-e.a[1])*o)}}(t.pointer,e);return{target:e,...i,envelope:Math.max(t.baseTolerance,e.physicalHalfWidth+t.bodyPointerPadding)}}).filter(t=>t.distance<=t.envelope+1e-9).filter(e=>!function(t,e,i,s,n){const o=e.b[0]-e.a[0],a=e.b[1]-e.a[1],r=Math.hypot(o,a);if(!(r>1e-9))return!1;const l=o/r,c=a/r;for(const o of i){if(!o.open&&o.kind)continue;const i=Mg(o.a,o.b),a=i.b[0]-i.a[0],r=i.b[1]-i.a[1],h=Math.hypot(a,r);if(!(h>1e-9))continue;const d=a/h,p=r/h;if(Math.abs(l*p-c*d)>1e-6)continue;if(Math.abs((i.a[0]-e.a[0])*c-(i.a[1]-e.a[1])*l)>n)continue;const u=(t[0]-i.a[0])*d+(t[1]-i.a[1])*p,_=1e-9;if(!(u<=_||u>=h-_)&&Math.abs((t[0]-i.a[0])*p-(t[1]-i.a[1])*d)<=s+1e-9)return!0}return!1}(t.pointer,e.target,t.intervals,e.envelope,Math.max(1e-9,Math.min(t.baseTolerance,.04*t.gridStep)))),i=e.filter(e=>!!e.target.partitionHost&&t.renderedLength+2*e.target.physicalHalfWidth>e.length+1e-9).sort(Dg),s=e.filter(e=>!e.target.partitionHost||t.renderedLength+2*e.target.physicalHalfWidth<=e.length+1e-9).sort(Dg);let n=s[0];if(!n)return{candidate:null,jambBlockedTarget:i[0]?.target||null};const o=s.filter(t=>Math.abs(t.distance-n.distance)<=1e-9&&Math.abs(t.perpendicular-n.perpendicular)<=1e-9),a=o.filter(t=>t.target.partitionHost);if(a.length){if(1!==new Set(a.map(t=>t.target.partitionHost.id)).size||a.some(t=>t.target.ambiguousPartitionHost))return{candidate:null,jambBlockedTarget:null};const t=a[0],e=t.target.b[0]-t.target.a[0],i=t.target.b[1]-t.target.a[1],s=Math.hypot(e,i),r=e/s,l=i/s,c=o.every(e=>{const i=e.target.b[0]-e.target.a[0],s=e.target.b[1]-e.target.a[1],n=Math.hypot(i,s),o=i/n,a=s/n,c=Math.abs(r*a-l*o)<=1e-6,h=Math.abs((e.target.a[0]-t.target.a[0])*l-(e.target.a[1]-t.target.a[1])*r);return c&&h<=1e-9});if(!c)return{candidate:null,jambBlockedTarget:null};n=t}if(n.target.ambiguousPartitionHost)return{candidate:null,jambBlockedTarget:null};const{target:r,length:l}=n,c=r.b[0]-r.a[0],h=r.b[1]-r.a[1],d=c/l,p=h/l,u=r.partitionHost?r.physicalHalfWidth:0,_=Math.min(Math.max(0,t.renderedLength)/2+u,l/2);let g=n.along;const m=Math.max(t.gridStep,1e-9),f=l/2;g=Math.abs(g-f)<=m/2?f:Math.round(g/m)*m,g=Math.max(_,Math.min(l-_,g));const v=r.a[0]+d*g,y=r.a[1]+p*g,b=Math.max(0,t.renderedLength)/2,w=g-b,k=g+b,x=Math.max(0,w),$=Math.max(0,l-k),S=[r.a[0]+d*(w-x/2),r.a[1]+p*(w-x/2)],M=[r.a[0]+d*(k+$/2),r.a[1]+p*(k+$/2)];let C=180*Math.atan2(h,c)/Math.PI;C>=90?C-=180:C<-90&&(C+=180);const D=Math.abs(g-f)<=1e-9;return{candidate:{presetRevision:t.preset.revision,geometryRevision:t.geometryRevision,pointer:[t.pointer[0],t.pointer[1]],type:t.preset.type,lengthCm:t.preset.lengthCm,flipH:t.preset.flipH,flipV:t.preset.flipV,x:v,y:y,angle:C,renderedLength:t.renderedLength,target:r,...r.partitionHost?{host:{...r.partitionHost,t:l>0?g/l:0}}:{},measure:{labels:[{distance:x,midpoint:S},{distance:$,midpoint:M}],guide:D?{x:v,y:y,angle:C}:null}},jambBlockedTarget:null}}function Pg(t,e,i,s,n=1e-6){return t.presetRevision===i&&t.geometryRevision===s&&Math.hypot(t.pointer[0]-e[0],t.pointer[1]-e[1])<=n}const Rg=(t,e)=>t[0]*e[1]-t[1]*e[0],Ig=(t,e)=>t[0]*e[0]+t[1]*e[1],Ag=(t,e)=>[t[0]-e[0],t[1]-e[1]],Fg=(t,e,i)=>[t[0]+e[0]*i,t[1]+e[1]*i];function Eg(t,e,i){return Math.abs(Rg(t,e))<=i}function zg(t,e,i){return Math.abs(Rg(Ag(t,e),i))}function Og(t,e,i,s,n){const o=e[0]-t[0],a=e[1]-t[1],r=Math.hypot(o,a);if(!(r>n&&i>0))return[];const l=[o/r,a/r];return function(t,e,i){const s=e.map(([e,i])=>[Math.max(0,Math.min(e,i)),Math.min(t,Math.max(e,i))]).filter(([t,e])=>e>t+i).sort((t,e)=>t[0]-e[0]||t[1]-e[1]),n=[];for(const t of s){const e=n[n.length-1];!e||t[0]>e[1]+i?n.push([...t]):e[1]=Math.max(e[1],t[1])}const o=[];let a=0;for(const[t,e]of n)t>a+i&&o.push([a,t]),a=Math.max(a,e);return t>a+i&&o.push([a,t]),o}(r,s.flatMap(e=>{const s=e.b[0]-e.a[0],o=e.b[1]-e.a[1],a=Math.hypot(s,o);if(!(a>n&&Eg(l,[s/a,o/a],1e-6)))return[];if(zg(e.a,t,l)>1.1*Math.max(i,n)||zg(e.b,t,l)>1.1*Math.max(i,n))return[];return[[Ig(Ag(e.a,t),l),Ig(Ag(e.b,t),l)]]}),n).flatMap(([e,s])=>{const n=Br({a:Fg(t,l,e),b:Fg(t,l,s),halfDepth:i});return n?[n]:[]})}function Ng(t){const e=t.coordScale??1,i=Math.max(t.epsilon??2e-4*t.gridPitch,1e-9),s=[];for(const i of t.rooms||[]){if(!i?.id)continue;const n=hl(t.rooms,i.id,t.walls,t.openCuts,t.pitch,t.cellCm,t.gridPitch,e);if(!n||n.poly.length<3)continue;const o=Qr(n.poly,n.offsets);!o||o.length<3||s.push({roomId:i.id,profile:n,inner:o})}s.sort((t,e)=>t.roomId.localeCompare(e.roomId));const n=(t.roomOpenings||[]).map(t=>{const e=t.angle*Math.PI/180,i=[Math.cos(e),Math.sin(e)],s=Math.max(0,t.length)/2;return{a:Fg([t.x,t.y],i,-s),b:Fg([t.x,t.y],i,s)}}),o=[];for(const s of Pl(t.rooms,t.walls,t.openCuts,t.pitch,t.cellCm,t.gridPitch,e))for(const t of Og(s.a,s.b,s.depthUnits/2,n,i))o.push({body:t});const a=new Map;for(const e of t.partitionCuts||[]){const t=a.get(e.hostId)||[];t.push(e),a.set(e.hostId,t)}for(const e of t.partitions||[]){const s=xr(e.cm,t.cellCm,t.gridPitch)/2;for(const t of Og(e.a,e.b,s,a.get(e.id)||[],i))o.push({body:t,partitionId:e.id})}return{rooms:s,boundaries:o,epsilon:i}}function Hg(t,e,i,s){const n=t.profile.offsets[e];if(!(n>0))return null;const o=function(t,e){const i=t[e],s=t[(e+1)%t.length],n=s[0]-i[0],o=s[1]-i[1],a=Math.hypot(n,o)||1;return function(t){let e=0;for(let i=0;i=0?[-o/a,n/a]:[o/a,-n/a]}(t.profile.poly,e),a=Fg(i.center,o,n),r=[];for(let e=0;es&&Eg(i.axis,[l[0]/c,l[1]/c],1e-6)))continue;if(zg(n,a,i.axis)>s||zg(o,a,i.axis)>s)continue;const h=Ig(Ag(n,a),i.axis),d=Ig(Ag(o,a),i.axis);r.push([Math.min(h,d),Math.max(h,d)])}const l=function(t,e){t.sort((t,e)=>t[0]-e[0]||t[1]-e[1]);const i=[];for(const s of t){const t=i[i.length-1];!t||s[0]>t[1]+e?i.push([...s]):t[1]=Math.max(t[1],s[1])}return i}(r,s).find(([t,e])=>t<=s&&e>=-s);if(!l)return null;const[c,h]=l,d=Fg(a,i.axis,-i.half),p=Fg(a,i.axis,i.half),u=Math.max(0,-i.half-c),_=Math.max(0,h-i.half),g=u>0?Fg(a,i.axis,c):d,m=_>0?Fg(a,i.axis,h):p,f=Ig(o,i.normal)>=0?1:-1,v=(e,s,n)=>({from:e,to:s,label:[(e[0]+s[0])/2,(e[1]+s[1])/2],axis:i.axis,labelNormal:o,distance:n,roomId:t.roomId,roomSide:f,source:"room-face"});return{left:v(d,g,u),right:v(p,m,_)}}function Lg(t){const e=Fg(t.center,t.axis,-t.half),i=Fg(t.center,t.axis,t.half),s=Fg(t.center,t.axis,Math.min(-t.half,t.targetLo)),n=Fg(t.center,t.axis,Math.max(t.half,t.targetHi)),o=(e,i)=>({from:e,to:i,label:[(e[0]+i[0])/2,(e[1]+i[1])/2],axis:t.axis,labelNormal:t.normal,distance:Math.hypot(i[0]-e[0],i[1]-e[1]),source:"host-end"});return[o(e,s),o(i,n)]}function Bg(t,e,i,s){const n=Ag(i,e),o=Ig(n,n);if(!(o>s*s))return Math.hypot(...Ag(t,e))<=s;const a=Ig(Ag(t,e),n)/o;if(a<-s||a>1+s)return!1;const r=Fg(e,n,Math.max(0,Math.min(1,a)));return Math.hypot(...Ag(t,r))<=s}function qg(t,e,i){let s=!1;for(let n=0,o=e.length-1;nt[1]!=c>t[1]&&t[0]<(l-a)*(t[1]-r)/(c-r)+a&&(s=!s)}return s}function Wg(t,e,i,s,n,o){const a=Ag(s,i),r=Rg(e,a);if(Math.abs(r)<=o)return null;const l=Ag(i,t),c=Rg(l,a)/r,h=Rg(l,e)/r;return c<-o||c>n+o||h<-o||h>1+o?null:Math.max(0,Math.min(n,c))}function jg(t,e,i){const s=Lg(i),n="partition"===t.host?.kind?t.host.id:void 0;return[{base:s[0],direction:[-i.axis[0],-i.axis[1]]},{base:s[1],direction:i.axis}].map(({base:t,direction:i})=>{const s=t.distance,o=function(t,e,i,s,n,o){let a=null;for(const r of s)if(!n||r.partitionId!==n){if(qg(t,r.body,o))return 0;for(let s=0;sIg(Ag(t,n),i));return{center:n,axis:i,normal:s,half:Math.max(0,t.renderedLength)/2,targetLo:Math.min(...o),targetHi:Math.max(...o)}}(t),s=e.rooms.flatMap(t=>{const s=function(t,e,i){const{profile:s}=t;let n=null;for(let t=0;t0))continue;const o=s.poly[t],a=s.poly[(t+1)%s.poly.length],r=Ag(a,o),l=Math.hypot(r[0],r[1]);if(!(l>i&&Eg(e.axis,[r[0]/l,r[1]/l],1e-6)))continue;if(zg(o,e.center,e.axis)>i||zg(a,e.center,e.axis)>i)continue;const c=Ig(Ag(o,e.center),e.axis),h=Ig(Ag(a,e.center),e.axis),d=Math.min(c,h),p=Math.max(c,h);if(d>-e.half+i||p0?d:p<0?-p:0);(!n||u2)return Lg(i);if(s.length){const t=s.map(({room:t,edge:s})=>Hg(t,s,i,e.epsilon));if(t.some(t=>!t))return Lg(i);const n=t;return[...n.map(t=>t.left),...n.map(t=>t.right)]}return jg(t,e,i)}function Gg(t){return!(!t.canEdit||t.kiosk||t.fixedFloor)&&("view"!==t.mode&&("mouse"===t.pointerType&&t.spaceCount>1))}const Vg="1.67.0-beta.3",Kg={badge:"display.badge",icon_ripple:"display.icon_ripple",value:"display.value",static_icon:"display.static_icon"},Yg={badge:"marker.display_hint_badge",icon_ripple:"marker.display_hint_icon_ripple",value:"marker.display_hint_value",static_icon:"marker.display_hint_static_icon"},Xg=2e3,Jg=1e3,Zg=1500,Qg=t=>{const e=String(t??"").trim().replace(",",".");if(!/^[+-]?(?:\d+(?:\.\d*)?|\.\d+)$/.test(e))return null;const i=Number(e);return Number.isFinite(i)?i:null},tm=(t,e)=>{if(!t.has(e))return{hit:!1};const i=t.get(e);return t.delete(e),t.set(e,i),{hit:!0,value:i}},em=(t,e,i,s)=>{for(t.delete(e),t.set(e,i);t.size>s;){const e=t.keys().next().value;if(void 0===e)break;t.delete(e)}},im=new Map;let sm=0;const nm=t=>`${window.innerWidth}x${window.innerHeight}|${location.pathname}|${JSON.stringify(t??{})}`;let om=1e4;const am="houseplan_card_layout_v1",rm="houseplan_card_cfg_v1",lm="houseplan_card_zoom_v1",cm="houseplan_card_nav_v1",hm="houseplan_card_kiosk_v1",dm="houseplan_card_view_v1",pm="hp-dialog, hp-help, hp-color-opacity, hp-device-preview",um=1e3,_m=[[0,1],[45,.88],[70,.62],[86,.32],[100,0]],gm=(t,e)=>{const i=Math.min(t.x,e.x),s=Math.min(t.y,e.y);return{x:i,y:s,w:Math.max(t.x+t.w,e.x+e.w)-i,h:Math.max(t.y+t.h,e.y+e.h)-s}},mm=new Set(["select","draw","column","merge","split","resize","opening","boundary","wallthick","delroom"]),fm=2e3,vm=(t,e,i)=>{const s=new Event(e,{bubbles:!0,composed:!0});s.detail=i??{},t.dispatchEvent(s)},ym=t=>{history.pushState(null,"",t),vm(window,"location-changed",{replace:!1})},bm=(t,e)=>{let i,s=null;const n=(...n)=>{clearTimeout(i),s=n,i=window.setTimeout(()=>{i=void 0;const e=s;s=null,e&&t(...e)},e)};return n.flush=()=>{if(void 0===i)return;clearTimeout(i),i=void 0;const e=s;s=null,e&&t(...e)},n.cancel=()=>{clearTimeout(i),i=void 0,s=null},n.pending=()=>void 0!==i,n},wm=t=>{try{t.target?.setPointerCapture?.(t.pointerId)}catch{}};class km extends ht{constructor(){super(...arguments),this._space="f1",this._layout={},this._serverStorage=!1,this._loadOk=!1,this._serverCanWrite=null,this._loading=!1,this._loadTries=0,this._serverCfg=null,this._cfgRev=0,this._cfgContentFingerprint="",this._unsubCfg=null,this._unsubLayout=null,this._unsubVirtual=null,this._liveSyncAttempt=null,this._liveSyncGeneration=0,this._liveSyncConnection=null,this._layoutRev=0,this._layoutContentFingerprint="",this._virtualLights=gn(null),this._canOptimizeUndo=!1,this._undoKind=null,this._devices=[],this._regSignature="",this._defPos={},this._newSyncKey="",this._tip=null,this._hoverRoom=null,this._pointerModality=new Tu(this,()=>this._syncPointerHoverTargets()),this._devicePressAnimations=new Map,this._selId=null,this._toast="",this._mode="view",this._pendingNavMode=null,this._decorTool="select",this._decorStyle={...or},this._decorDraft=null,this._decorMove=null,this._decorSel=null,this._decorEraseConfirm=null,this._decorTextDialog=null,this._decorShapeDialog=null,this._backdropDialog=null,this._decorTextSelection={start:0,end:0},this._furnPalette=null,this._dtBox=null,this._dtDrag=null,this._bdDrag=null,this._slide="",this._reducedMotion=!1,this._onMotionChange=t=>{this._reducedMotion=t.matches,this._cancelDevicePressFeedback(),t.matches&&this._modeTransitionPreparing?this._modeTransitionForceAtomic=!0:t.matches&&this._modeTransition.active&&this._cancelModeTransition(!0),this.requestUpdate()},this._editorChromeMode="plan",this._modeTransitionVisual=null,this._modeTransitionPreparing=!1,this._modeTransitionForceAtomic=!1,this._modeTransitionRequest=0,this._modeTransitionTargetZoom=1,this._modeTransitionEditorCamera=null,this._modeTransition=new B_({frame:t=>this._applyModeTransitionFrame(t),settled:t=>this._settleModeTransition(t)}),this._editorSecondary=new Eu({root:()=>this.renderRoot,requestUpdate:()=>this.requestUpdate(),updateComplete:()=>this.updateComplete,clearTip:()=>{this._tip=null}}),this._editorSecondaryCopy={groupActive:(t,e)=>this._t("editor.group_active",{group:t,item:e}),openGroup:t=>this._t("editor.open_group",{group:t}),disabledAction:(t,e)=>this._t("editor.disabled_action",{action:t,reason:e})},this._tool="draw",this._geometryHistory=new D_(50),this._wallDialog=null,this._drawWallField=null,this._activeDraftId=null,this._resumeDraftBySpace={},this._physicalSel=null,this._physicalDialog=null,this._partitionDeleteDialog=null,this._roomDeleteDialog=null,this._physicalDrag=null,this._physicalRotate=null,this._physicalLastTap=null,this._physicalPickCycle=null,this._wallUnionCache=null,this._isoGeometryCache=new Map,this._isoFallback=new Set,this._openingTunnelCache=null,this._openingWallIndexCache=new Map,this._openingPlacementIntervalsCache=null,this._openingDimensionContextCache=null,this._planSnapGeometryCache=null,this._planStructuralGeometryCache=null,this._physicalBodiesCache=null,this._lightPhysicalBodiesCache=null,this._cleanFloorCache=new Map,this._glowClipCache=new Map,this._glowGeometryWarnings=new Set,this._lightBarrierCache=null,this._glowFeatherUnits=null,this._glowRenderedSources=new Map,this._glowLastAppearance=new Map,this._glowEnteringSources=new Set,this._glowEnterRafs=new Map,this._glowFadeTimers=new Map,this._glowFeatherSuspendUntil=0,this._glowFeatherResumeTimer=0,this._glowSourceSeq=0,this._glowScreenBlend=!1,this._duplicateColumnId=null,this._duplicateColumnTimer=0,this._rszSel=null,this._rszDrag=null,this._rszPreview=null,this._rszLive=null,this._path=[],this._cursorPt=null,this._planSnapHover=null,this._mergeSel=null,this._openingPreset=null,this._openingRebindId=null,this._openingPresetRevision=0,this._openingHoverCandidate=null,this._openingJambBlockCm=null,this._openingDialog=null,this._openingInfo=null,this._opDrag=null,this._opMeasure=null,this._mergeDialog=null,this._openWallAnchor=null,this._boundaryPointerType="mouse",this._boundaryRestoreGuard=null,this._boundaryTargetMemo=null,this._boundaryPreviewMemo=null,this._splitSel=null,this._pendingSplit=null,this._wallFaceBatch=null,this._wallRepairDiagnostic=null,this._wallFaceGraphCache=[],this._areaSel="",this._nameSel="",this._roomDialog=!1,this._roomEditId=null,this._roomFill="",this._roomCustomFill=null,this._roomTempSrc="",this._roomHumSrc="",this._roomSrcOpen=null,this._roomSrcFilter="",this._roomNameScale=1,this._roomLabelScale=1,this._zoom=1,this._view=null,this._zoomBySpace={},this._viewModeSnap=null,this._pointers=new Map,this._panStart=null,this._panLock=null,this._pinchStart=null,this._suppressClick=!1,this._touchContacts=new Map,this._touchSequenceMultitouch=!1,this._touchClickBlockUntil=0,this._connectedPath="",this._routeDepartureHandled=!1,this._onLocationChanged=()=>{this._connectedPath&&location.pathname!==this._connectedPath?this._leaveCardRoute():location.pathname===this._connectedPath&&(this._routeDepartureHandled=!1)},this._touchGestureGuard={capture:!0,handleEvent:t=>this._guardTouchGesture(t)},this._hdrH=118,this._booting=!0,this._bootFading=!1,this._bootSettling=!1,this._bootSettleRaf=0,this._bootLastH=-1,this._bootStart=0,this._bootLastChange=0,this._bootSoft=!1,this._tapConfirm=null,this._onboardingShown=!1,this._rulesDialog=null,this._alignDialog=null,this._settingsDialog=null,this._backupExportDialog=null,this._backupImportDialog=null,this._sunRaysCache=null,this._dayCycleTimer=0,this._dayCycleClockKey="",this._compassDrag=!1,this._importDialog=null,this._importQueue=[],this._importTotal=0,this._rulesCompiledSrc="",this._infoCard=null,this._nativeMoreInfoEntity=null,this._markerDialog=null,this._spaceDialog=null,this._keyHandler=t=>this._onKey(t),this._warmVp=null,this._warmVpArmed=!1,this._warmLongReturn=!1,this._warmRevivePending=!1,this._warmGen=++sm,this._warmKey=null,this._warmSlot=null,this._hashApplied=!1,this._navApplied=!1,this._labs={active:Object.freeze([]),space:""},this._viewPreference={},this._renderProjection="flat",this._kioskScale={icon:1,font:1},this._kioskDialog=!1,this._activityRt=new Map,this._vacRt=new Map,this._vacViewKey="",this._vacLastView=null,this._vacRaf=0,this._vacSrvTrails={},this._vacJumpOnce=!1,this._continuity=this._newContinuityController(),this._continuityHistory=[],this._continuityEpoch=0,this._continuityDataReady=!0,this._continuityPaintToken=-1,this._continuityDisposed=!1,this._renderSnapshotAt=Date.now(),this._hassSequence=0,this._visibleDeviceSnapshot=null,this._candidateDeviceSnapshot=null,this._stagedDeviceSnapshotToken=-1,this._capturedSnapshotSequence=-1,this._capturedSnapshotDevices=null,this._capturedSnapshotLayout=null,this._capturedSnapshotActivity="",this._capturedSnapshotConfigEpoch=-1,this._capturedSnapshotVirtual="",this._lastValidStageSize=null,this._pendingRefitSize=null,this._refitRaf=0,this._pageVisibility=t=>{if(this._continuity.visibility(t),this._dayCycleVisibility(t),"hidden"===t.kind)return this._clearTransientHover(!0),this._cancelDevicePressFeedback(),void(this._modeTransitionPreparing?this._modeTransitionForceAtomic=!0:this._cancelModeTransition(!0));if(this._vacJumpOnce=!0,!t.long){const t=Date.now();let e=!1;for(const i of this._activityRt.values())!i.flashKind||(i.expiresAt||i.flashTs+$u)>t||(i.flashTs=0,i.flashKind=null,i.expiresAt=0,e=!0);return void(e&&this.requestUpdate())}Date.now()-this._renderSnapshotAt>1e3&&this._continuity.note("device-snapshot-stale"),this._continuityDataReady=!1,this._continuityPaintToken=-1,this._resumeSettling=!0,this._loading?this.requestUpdate():this._loadFromServer()},this._resumeSettling=!1,this._viewportInvalidAt=0,this._vacFit=null,this._vacAllCamerasFor=null,this._vacAllCameraCache=null,this._vacCalConfirm=null,this._kioskDots=!1,this._cyclePausedUntil=0,this._swipeStart=null,this._tabDrag=null,this._tabDragRelease=null,this._tabSuppressClick=!1,this._tabOrderWarned=!1,this._lastTap=0,this._onLabsSnapshot=t=>{const e=this._effectiveProjection();this._labs=t;const i=this._effectiveProjection();this._convertProjectionView(e,i),this.requestUpdate()},this._onHashChange=()=>{if(this._hasFixedFloor)return;const t=this._hashSpace();if(t&&this._model.find(e=>e.id===t)&&t!==this._space){if(this._wallFaceBatch&&this._roomDialogCancel(),"plan"===this._mode&&"draw"===this._tool&&!this._finishWallChain())return;this._activeDraftId&&(this._resumeDraftBySpace[this._space]=this._activeDraftId),this._commitSpace(t),this._selId=null,this._path=[],this._clearPlanSnapHover(),this._clearOpeningPlacement(!0),this._tool="draw",this._openWallAnchor=null,this._boundaryRestoreGuard=null,this._activeDraftId=null,this._draftSegmentCms=[],this._closingWallCm=null,"plan"===this._mode&&"draw"===this._tool&&this._resumeLastDraft(),this._restoreZoom(),this.requestUpdate()}},this._drag=null,this._rlResize=null,this._holdFired=!1,this._retryContinuity=()=>{this._continuityDataReady=!1,this._continuityPaintToken=-1,this._continuity.retry(this._continuity.recoveryReason||"plan"),this._loading||this._loadFromServer()},this._cfgEpoch=0,this._modelCache=null,this._emptySpaceStateActive=!1,this._decorSnapCache=null,this._markerPreviewMemo=null,this._markerPreviewDevicesMemo=null,this._showHidden=!1,this._connHooked=null,this._connectionWasLost=!1,this._haRegistryConnection=null,this._haRegistryRev=-1,this._haBindingCacheKey="",this._planHassMemo=null,this._onHaRegistryUpdate=()=>{const t=An(this.hass);t.revision===this._haRegistryRev&&this._devices.length||(this._haRegistryRev=t.revision,this._planHassMemo=null,this._regSignature="",this._maybeRebuildDevices(),this.requestUpdate())},this._onConnReady=()=>{if(this._loadTries=0,clearTimeout(this._loadRetryTimer),this._loadRetryTimer=void 0,function(t){const e=Cn(t);e&&(Pn(t,e),Rn(t,e))}(this.hass),this._saveConfigDebounced.pending()&&this._saveConfigDebounced.flush(),this._cfgWriting)return clearTimeout(this._reloadRetry),void(this._reloadRetry=window.setTimeout(this._onConnReady,400));!this._connectionWasLost&&this._continuity.hasCompleteFrame?this._beginContinuityCandidate("connection-ready",!1,"plan"):(this._continuityDataReady=!1,this._continuityPaintToken=-1),this._loading||this._loadFromServer()},this._onConnLost=()=>{this._booting&&!this._continuity.hasCompleteFrame||(this._connectionWasLost=!0,this._continuityDataReady=!1,this._continuityPaintToken=-1,this._continuity.connectionLost())},this._signer=new Rh(()=>this.requestUpdate()),this._dirtyPos=new Set,this._sentPos=new Map,this._persistLayout=bm(()=>{if(this._serverStorage){const t=[...this._dirtyPos];this._dirtyPos.clear();for(const e of t){const t=Ju(this._layout[e]);t&&(this._layout={...this._layout,[e]:t},this._sentPos.set(e,t),this.hass.callWS({type:"houseplan/layout/update",device_id:e,pos:t}).then(t=>this._noteLayoutRev(t)).catch(t=>this._showToast(this._t("toast.pos_save_failed",{err:this._errText(t)}))).finally(()=>{this._sentPos.get(e)===t&&this._sentPos.delete(e)}))}this._cacheSnapshot()}else this._layout=Zu(this._layout),localStorage.setItem(am,JSON.stringify(this._layout))},600),this._frame=null,this._showFar=!1,this._writesPending=0,this._writeChain=Promise.resolve(),this._undoGeometry=()=>{if(this._cancelBoundaryAnchor())return;if(this._physicalDrag||this._physicalRotate)return void this._cancelPhysicalGesture();if(this._decorDraft)return this._decorDraft=null,void this.requestUpdate();if(this._decorMove||this._dtDrag||this._bdDrag)return void this._cancelDecorGesture();if(this._rszDrag)return void this._rszCancelDrag();const t=this._geometryHistory.undo();t&&(this._applyGeometryState(t.before)?this._showToast(this._t("history.undone",{name:t.name})):this._geometryHistory.clear())},this._redoGeometry=()=>{if(this._cancelBoundaryAnchor())return;if(this._physicalDrag||this._physicalRotate)return void this._cancelPhysicalGesture();if(this._decorDraft)return this._decorDraft=null,void this.requestUpdate();if(this._decorMove||this._dtDrag||this._bdDrag)return void this._cancelDecorGesture();if(this._rszDrag)return void this._rszCancelDrag();const t=this._geometryHistory.redo();t&&(this._applyGeometryState(t.after)?this._showToast(this._t("history.redone",{name:t.name})):this._geometryHistory.clear())},this._saveConfigDebounced=bm(()=>{this._serverCfg&&this._writeConfig().catch(t=>{"conflict"===t?.code?(this._showToast(this._t("toast.conflict")),this._cancelPath(),this._reloadConfigOnly(!0)):this._showToast(this._t("toast.cfg_save_failed",{err:this._errText(t)}))})},500),this._draftSegmentCms=[],this._closingWallCm=null,this._savePhysicalDialog=()=>{const t=this._physicalDialog,e=this._curSpaceCfg,i=this._spaceModel();if(!t||!e||!i)return;const s=Qg(t.cm);if(null==s)return void this._showPhysicalRange("column"===t.kind?Ll:100);const n=this._imperial?2.54*s:s,o="column"===t.kind?Ll:100;if(!Number.isFinite(n)||n<1||n>o)return void this._showPhysicalRange(o);if("column"===t.kind){const e=i.wall_columns.find(e=>e.id===t.id);if(!e)return;const s=Qg(t.angle||"0");if("circle"!==t.shape&&(null==s||s<0||s>=90))return void this._showToast(this._t("toast.physical_angle"));const o="circle"===t.shape?{id:t.id,shape:"circle",center:e.center,cm:n}:{id:t.id,shape:"square",center:e.center,cm:n,angle:s};if(i.wall_columns.some(e=>e.id!==t.id&&rc(e,o,.02*this._gridPitch)))return void this._showToast(this._t("toast.column_duplicate"))}const a=this._geometrySnapshot();if("partition"===t.kind){const i=(e.partitions||[]).find(e=>e.id===t.id);i&&(i.cm=n)}else if("column"===t.kind){const i=(e.wall_columns||[]).find(e=>e.id===t.id);i&&(i.cm=ql(n),i.shape="circle"===t.shape?"circle":"square","square"===i.shape?i.angle=Qg(t.angle||"0"):delete i.angle)}else{const i=(e.room_drafts||[]).find(e=>e.id===t.id);i?.segments?.[t.segment||0]&&(i.segments[t.segment||0].cm=n)}this._recordGeometry(this._t("history.physical_edit"),a),this._physicalDialog=null,this._saveConfig()},this._deletePhysicalSelection=()=>{const t=this._physicalSel,e=this._curSpaceCfg;if(!t||!e)return;if("draft"===t.kind)return void this._deleteDraftWhole();const i=this._geometrySnapshot();if("partition"===t.kind){const i=(e.openings||[]).filter(e=>"partition"===e.host?.kind&&e.host.id===t.id).sort((t,e)=>(t.host?.t||0)-(e.host?.t||0));if(i.length)return void(this._partitionDeleteDialog={id:t.id,openings:i.map(t=>JSON.parse(JSON.stringify(t)))})}const s="partition"===t.kind?"partitions":"column"===t.kind?"wall_columns":"room_drafts";e[s]=(e[s]||[]).filter(e=>e.id!==t.id),e[s].length||delete e[s],this._activeDraftId===t.id&&this._cancelPath(),this._physicalSel=null,this._physicalDialog=null,this._recordGeometry(this._t("history.physical_delete"),i),this._saveConfig()},this._confirmPartitionDelete=()=>{const t=this._partitionDeleteDialog,e=this._curSpaceCfg;if(!t||!e)return;const i=this._geometrySnapshot();e.partitions=(e.partitions||[]).filter(e=>e.id!==t.id),e.partitions.length||delete e.partitions,e.openings=(e.openings||[]).filter(e=>"partition"!==e.host?.kind||e.host.id!==t.id),e.openings.length||delete e.openings,this._partitionDeleteDialog=null,this._physicalSel=null,this._physicalDialog=null,this._recordGeometry(this._t("history.physical_delete"),i),this._saveConfig()},this._deleteDraftWhole=()=>{const t="draft"===this._physicalDialog?.kind?this._physicalDialog.id:"draft"===this._physicalSel?.kind?this._physicalSel.id:null,e=this._curSpaceCfg;if(!t||!e||!confirm(this._t("confirm.delete_draft")))return;const i=this._geometrySnapshot();e.room_drafts=(e.room_drafts||[]).filter(e=>e.id!==t),e.room_drafts.length||delete e.room_drafts,this._activeDraftId===t&&this._cancelPath(),this._physicalSel=null,this._physicalDialog=null,this._recordGeometry(this._t("history.physical_delete"),i),this._saveConfig()},this._deleteDraftSegment=()=>{const t=this._physicalDialog,e=this._curSpaceCfg;if(!t||"draft"!==t.kind||!e)return;if(!confirm(this._t("confirm.delete_draft_segment")))return;const i=(e.room_drafts||[]).findIndex(e=>e.id===t.id);if(i<0)return;const s=e.room_drafts[i],n=Math.max(0,Math.min(s.segments.length-1,t.segment||0)),o=[],a=s.points.slice(0,n+1),r=s.points.slice(n+1);if(a.length>=2&&o.push({id:s.id,points:a,segments:s.segments.slice(0,n)}),r.length>=2&&o.push({id:o.length?`${s.id}-${Date.now().toString(36)}`:s.id,points:r,segments:s.segments.slice(n+1)}),2===o.length&&e.room_drafts.length>=200)return void this._showToast(this._t("toast.physical_limit"));const l=this._geometrySnapshot();e.room_drafts.splice(i,1,...o),e.room_drafts.length||delete e.room_drafts,this._activeDraftId===s.id&&this._cancelPath(),this._physicalDialog=null,this._physicalSel=o.length?{kind:"draft",id:o[0].id}:null,this._recordGeometry(this._t("history.draft_segment_delete"),l),this._saveConfig()},this._confirmRoomDelete=t=>{const e=this._roomDeleteDialog,i=this._curSpaceCfg,s=this._spaceModel();if(!e||!i||!s)return;const n=s.rooms.find(t=>t.id===e.roomId);if(!n)return void(this._roomDeleteDialog=null);const o=this._openCuts(),a=Cp(dl(s.rooms,this._spaceWalls,o,this._wallKeyPitch,this._cellCm,this._gridPitch,um).filter(t=>t.roomId===n.id),s.partitions,this._openingsR.map(t=>({...t,x:t.rx,y:t.ry})),.02*this._gridPitch),r=new Set(a.materialize.filter(t=>!t.reusePartitionId).map(t=>t.interval.key)).size;if(t&&(i.partitions||[]).length+r>fm)return void this._showToast(this._t("toast.physical_limit"));const l=this._geometrySnapshot(),c=pl(s.rooms,this._spaceWalls,o,this._wallKeyPitch,this._cellCm,this._gridPitch,um);if(t){i.partitions||=[];const t=new Map,e=new Map,s=Date.now().toString(36);for(const n of a.materialize){let o=n.reusePartitionId?i.partitions.find(t=>t.id===n.reusePartitionId):e.get(n.interval.key);o||(o={id:`partition-room-${s}-${e.size}`,a:[n.interval.a[0]/um,n.interval.a[1]/um],b:[n.interval.b[0]/um,n.interval.b[1]/um],cm:n.interval.cm},i.partitions.push(o),e.set(n.interval.key,o)),t.set(n.interval.key,o)}for(const e of i.openings||[]){const i=a.openingIntervals.get(e.id),s=i?t.get(i):null,n=this._openingsR.find(t=>t.id===e.id);if(!s||!n)continue;const o={a:[s.a[0]*um,s.a[1]*um],b:[s.b[0]*um,s.b[1]*um]};e.host={kind:"partition",id:s.id,t:Dp([n.rx,n.ry],o)}}}else if(a.removeOpeningIds.length){const t=new Set(a.removeOpeningIds);i.openings=(i.openings||[]).filter(e=>!t.has(e.id)),i.openings.length||delete i.openings}i.rooms=i.rooms.filter(t=>t.id!==n.id),this._cfgEpoch++,this._commitOpenSpans();const h=this._normalizeWalls(c,this._openCuts());h.length?i.walls=h:delete i.walls,this._roomDeleteDialog=null,this._recordGeometry(this._t(t?"history.delete_room_keep_walls":"history.delete_room_with_walls"),l),this._saveConfig(),this._regSignature="",this._maybeRebuildDevices(),this.requestUpdate()},this._rebindPartitionOpening=()=>{const t=this._openingDialog;if(!t?.id)return;const e=t.id;this._activateMarkupTool("opening"),"opening"===this._tool&&(this._openingRebindId=e,this._openingPreset={type:t.type,lengthCm:t.lengthCm,flipH:t.flipH,flipV:t.flipV,revision:++this._openingPresetRevision},this._openingDialog=null,this._openingHoverCandidate=null)},this._keepClosedAsPartitions=()=>{if(this._wallFaceBatch)return void this._decideWallFace(!1);if(!this._contourClosed||this._pendingSplit||!this._curSpaceCfg)return;const t=this._curSpaceCfg,e=this._path.slice(0,-1);if((t.partitions||[]).length+e.length>fm)return void this._showToast(this._t("toast.physical_limit"));const i=this._geometrySnapshot(),s=tp(e.length,[...this._draftSegmentCms,this._closingWallCm??void 0],this._drawWallCm,fr);t.partitions||=[];const n=Date.now().toString(36);for(let i=0;it.id!==this._activeDraftId),t.room_drafts.length||delete t.room_drafts),this._recordGeometry(this._t("history.contour_to_partitions"),i),this._saveConfig(),this._roomDialog=!1,this._path=[],delete this._resumeDraftBySpace[this._space],this._activeDraftId=null,this._draftSegmentCms=[],this._closingWallCm=null},this._toggleServerPlans=async()=>{const t=this._spaceDialog;if(t)if(t.pickSaved)this._spaceDialog={...t,pickSaved:!1};else{this._spaceDialog={...t,pickSaved:!0,savedBusy:!0};try{const t=await this.hass.callWS({type:"houseplan/plans/list"}),e=this._spaceDialog;e&&(this._spaceDialog={...e,saved:t?.plans||[],savedBusy:!1})}catch(t){const e=this._spaceDialog;e&&(this._spaceDialog={...e,saved:[],savedBusy:!1}),this._showToast(this._t("toast.plans_list_failed",{err:this._errText(t)}))}}},this._aspectJob=null,this._dayCycleTick=()=>{if(!this.isConnected||"hidden"===this.ownerDocument.visibilityState)return;const t=this._dayCycleState();if(!t)return this._dayCycleTimer&&(clearInterval(this._dayCycleTimer),this._dayCycleTimer=0),void(this._dayCycleClockKey="");const e=Wa(t);e!==this._dayCycleClockKey&&(this._dayCycleClockKey=e,this.requestUpdate())},this._sunShown=!1,this._sunOut=!1,this._sunOutTimer=0,this._openSettingsDialog=()=>{if(!this._norm)return;const t=this._glowRadiusCm,e=this._imperial?Math.round(t/30.48*10)/10:Math.round(t)/100;this._settingsDialog={colors:JSON.parse(JSON.stringify(this._fillColors)),glowRadius:e,bgColor:hs(this._settings,{bgColor:null})||null,northDeg:Za(this._settings,{}),bgMode:Qa(this._settings,{}),sunRays:tr(this._settings,{}),busy:!1}},this._openAlignDialog=()=>{if(!this._norm||!this._serverCfg)return;const t=this._serverCfg.spaces||[],e=Object.fromEntries(this._devices.filter(t=>!t.virtual&&!!t.area).map(t=>[t.id,t.area])),i=y_(this._serverCfg,this._layout||{},{effectiveAreaByMarker:e}),s=i.changed?this._checkOptimizeGeometry(i.config):null,n=Math.ceil(10*i.report.maxShiftCm)/10,o=t.find(t=>null!=t?.id&&String(t.id)===i.report.maxSpace),a=t.length>1&&o?String(o.title||o.id):"";this._alignDialog={report:i.report,config:i.config,layout:i.layout,cm:n,where:a,preflight:s,changed:i.changed,busy:!1}},this._optimizeUndoBusy=!1,this._openBackupExport=()=>{this._settingsDialog=null,this._backupExportDialog={kind:"full",planOnly:!1,busy:!1,error:""}},this._openRulesDialog=()=>{if(!this._norm)return;const t=this._settings.icon_rules,e=(t&&t.length?t:Xt).map(t=>({...t}));this._rulesDialog={rules:e,test:"",busy:!1}},this._climateCache=null,this._gearPtCache=new WeakMap}get _canEdit(){return!!this._norm&&(!0===this._serverCanWrite||!1!==this._serverCanWrite&&!0===this.hass?.user?.is_admin)}get _kiosk(){return!!this._config?.kiosk}_showKioskDots(){this._kioskDots=!0,clearTimeout(this._kioskDotsTimer),this._kioskDotsTimer=window.setTimeout(()=>this._kioskDots=!1,2500)}get _modeTransitionBusy(){return this._modeTransitionPreparing||this._modeTransition.active}_cssColor(t,e){const i=String(t||"").trim();if(!i)return e;const s=document.createElement("span");s.style.cssText=`position:absolute;visibility:hidden;color:${i}`,this.renderRoot.append(s);const n=getComputedStyle(s).color||e;return s.remove(),n}_currentModeVisual(t=this._mode){const e=this._modeTransition.presented||this._modeTransitionVisual;if(e)return{...e,viewport:{...e.viewport,viewBox:{...e.viewport.viewBox}}};const i=this._stageEl;if(!i||i.clientWidth<=0||i.clientHeight<=0)return null;const s=this.renderRoot.querySelector(".editorchrome"),n=this._viewOr(this._baseVb()),o=this.renderRoot.querySelector(".hp-paper"),a=this.renderRoot.querySelector(".hp-backdrop"),r=this.renderRoot.querySelector(".zoomwrap"),l=r?getComputedStyle(r).filter:"",c=Number(/brightness\(([^)]+)\)/.exec(l)?.[1]);return{presentedMode:t,editorChromeHeight:"view"===t?0:s?.getBoundingClientRect().height||0,stageWidth:i.clientWidth,stageHeight:i.clientHeight,viewport:z_(n,i.clientWidth),stageColor:getComputedStyle(i).backgroundColor||"rgb(255, 255, 255)",paperColor:o?getComputedStyle(o).fill:"rgb(255, 255, 255)",sceneBrightness:Number.isFinite(c)?c:1,architectureOpacity:"decor"===t?.35:1,backdropOpacity:a&&Number(getComputedStyle(a).opacity)||1,viewWeight:"view"===t?1:0,editorWeight:"view"===t?0:1,toolbarContentOpacity:"view"===t?0:1}}_viewForModeTarget(t,e,i,s,n){const o=Oi(this._baseVb(),s/Math.max(1,n)),a=Math.min(km.ZOOM_MAX,Math.max(km.ZOOM_MIN,t)),r=o.w/a,l=o.h/a,c=e??o.x+o.w/2,h=i??o.y+o.h/2;return this._clampView({x:c-r/2,y:h-l/2,w:r,h:l},o)}_targetStageColor(t){return"view"!==t?"rgb(255, 255, 255)":this._cssColor(this._stageBg(this._spaceDisplayForRender()),this._cssColor("var(--ha-card-background, var(--card-background-color, #111))","rgb(17, 17, 17)"))}_targetPaperColor(t){return"view"===t&&this._spaceModel()?.bg?this._cssColor("var(--ha-card-background, var(--card-background-color, #111))","rgb(17, 17, 17)"):"rgb(255, 255, 255)"}_targetBrightness(t){return 1}_applyModeTransitionFrame(t){t.targetMode===this._mode&&(this._modeTransitionVisual=t.presented,this._view={...t.presented.viewport.viewBox},this.requestUpdate())}_settleModeTransition(t){if(t.targetMode!==this._mode)return;const e=this._modeTransitionRequest;this._view={...t.to.viewport.viewBox},this._zoom=this._modeTransitionTargetZoom,this._modeTransitionVisual=null,this._modeTransitionPreparing=!1,this._lastValidStageSize=[t.to.stageWidth,t.to.stageHeight],"view"===this._mode&&(this._saveZoom(),this._viewModeSnap=null,this._modeTransitionEditorCamera=null),this.requestUpdate(),this.updateComplete.then(()=>{if(!this.isConnected||e!==this._modeTransitionRequest||this._modeTransitionBusy||t.targetMode!==this._mode)return;const i=this._stageEl;if(i&&i.clientWidth>0&&i.clientHeight>0&&(Math.abs(i.clientWidth-t.to.stageWidth)>.5||Math.abs(i.clientHeight-t.to.stageHeight)>.5)){const t=this._view;this._lastValidStageSize=[i.clientWidth,i.clientHeight],this._applyView(this._zoom,t?t.x+t.w/2:void 0,t?t.y+t.h/2:void 0),this.requestUpdate()}const s=this.renderRoot.activeElement;(!s||!s.isConnected||!!s.closest?.(".editorchrome, .stage"))&&this.renderRoot.querySelector(".modetab.active")?.focus?.({preventScroll:!0})})}_cancelModeTransition(t=!0){const e=!!this._modeTransition.state;this._modeTransitionRequest++,this._modeTransitionPreparing=!1,this._modeTransitionForceAtomic=!1,this._modeTransition.cancel(t),t&&e||(this._modeTransitionVisual=null)}_adoptMode(t){this._cancelModeTransition(!1),this._mode=t,"view"!==t&&(this._editorChromeMode=t)}_commitViewModeAtomic(t,e,i,s){if(this._modeTransitionPreparing=!1,this._modeTransitionVisual=null,this._modeTransitionForceAtomic=!1,this._zoom=e,t){const n=this._stageEl?.clientWidth||t.stageWidth,o=Math.max(1,t.stageHeight+t.editorChromeHeight);this._view=this._viewForModeTarget(e,i,s,n,o),this._lastValidStageSize=[n,o]}else this._view=null;this._viewModeSnap=null,this._modeTransitionEditorCamera=null,this._saveZoom(),this.requestUpdate()}_prepareModeTransition(t,e,i,s,n,o){this.updateComplete.then(()=>{if(!this.isConnected||t!==this._modeTransitionRequest||this._mode!==i)return void(t===this._modeTransitionRequest&&(this._modeTransitionPreparing=!1,this._modeTransitionVisual=null,this._modeTransitionForceAtomic=!1,this.requestUpdate()));const a=this.renderRoot.querySelector(".editorchrome"),r=a?.querySelector(".editorchrome-inner"),l="view"===i?0:r?.scrollHeight||r?.getBoundingClientRect().height||0,c=Math.max(1,e.stageHeight+e.editorChromeHeight),h=Math.max(1,c-l),d=this._stageEl?.clientWidth||e.stageWidth;if(d<=0||h<=0)return this._modeTransitionPreparing=!1,this._modeTransitionVisual=null,this._applyView(s,n,o),void this.requestUpdate();const p=this._viewForModeTarget(s,n,o,d,h),u={presentedMode:i,editorChromeHeight:l,stageWidth:d,stageHeight:h,viewport:z_(p,d),stageColor:this._targetStageColor(i),paperColor:this._targetPaperColor(i),sceneBrightness:this._targetBrightness(i),architectureOpacity:"decor"===i?.35:1,backdropOpacity:"decor"===i&&"backdrop"!==this._decorTool?.5:1,viewWeight:"view"===i?1:0,editorWeight:"view"===i?0:1,toolbarContentOpacity:"view"===i?0:1};this._modeTransitionPreparing=!1;const _=this._modeTransitionForceAtomic;this._modeTransitionForceAtomic=!1,this._modeTransition.start(e,u,i,this._reducedMotion||_?0:220)})}get _hasFixedFloor(){return!!this._config&&Object.prototype.hasOwnProperty.call(this._config,"floor")}_fixedFloorState(t=this._model,e=this._loadOk){const i=this._config?.floor,s=function(t){if(!t.hasFloor)return{kind:"absent"};const e=t.floor;if("string"==typeof e)return e.length?t.spaceIds.includes(e)?{kind:"valid",id:e,source:"id"}:{kind:"invalid",reason:"unknown-id",value:e}:{kind:"invalid",reason:"empty-id",value:e};if("number"==typeof e){if(!Number.isFinite(e))return{kind:"invalid",reason:"non-finite-index",value:e};if(!Number.isInteger(e))return{kind:"invalid",reason:"fractional-index",value:e};if(e<0)return{kind:"invalid",reason:"negative-index",value:e};const i=t.spaceIds[e];return void 0===i?{kind:"invalid",reason:"out-of-range-index",value:e}:{kind:"valid",id:i,source:"index"}}return{kind:"invalid",reason:"invalid-type",value:e}}({spaceIds:t.map(t=>t.id),hasFloor:this._hasFixedFloor,floor:i});return!this._hasFixedFloor||e?s:"number"==typeof i?"valid"===s.kind||"invalid"===s.kind&&"out-of-range-index"===s.reason?{kind:"pending",value:i}:s:"valid"===s.kind||"invalid"===s.kind&&"unknown-id"!==s.reason?s:{kind:"pending",value:i}}_canCommitSpace(t,e=!1){if(e||!this._hasFixedFloor)return!0;const i=this._fixedFloorState();return"valid"===i.kind&&i.id===t}_commitSpace(t,e=!1){return!!this._canCommitSpace(t,e)&&(t!==this._space&&(this._clearTransientHover(!0),this._cancelDevicePressFeedback()),this._space=t,!0)}_slideTo(t,e){if(t===this._space)return!0;if(!this._canCommitSpace(t))return!1;if(this._wallFaceBatch&&this._roomDialogCancel(),"plan"===this._mode&&"draw"===this._tool&&!this._finishWallChain())return!1;this._cancelModeTransition(!0);const i=window.matchMedia?.("(prefers-reduced-motion: reduce)")?.matches;return this._activeDraftId&&(this._resumeDraftBySpace[this._space]=this._activeDraftId),this._commitSpace(t),this._path=[],this._clearPlanSnapHover(),this._clearOpeningPlacement(!0),this._tool="draw",this._openWallAnchor=null,this._boundaryRestoreGuard=null,this._activeDraftId=null,this._draftSegmentCms=[],this._closingWallCm=null,this._selId=null,this._physicalSel=null,this._editorSecondary.closeForNavigation(),this._physicalDialog=null,this._physicalDrag=null,"plan"===this._mode&&"draw"===this._tool&&this._resumeLastDraft(),this._restoreZoom(),i||(this._slide=e,clearTimeout(this._slideTimer),this._slideTimer=window.setTimeout(()=>{this._slideTimer=void 0,this._slide="",this.requestUpdate()},190),this.requestUpdate()),!0}get _canReorderTabs(){return Gg({canEdit:this._canEdit,kiosk:this._kiosk,mode:this._mode,pointerType:"mouse",spaceCount:this._model.length,fixedFloor:this._hasFixedFloor})}_tabPointerDown(t,e){Gg({canEdit:this._canEdit,kiosk:this._kiosk,mode:this._mode,pointerType:t.pointerType,spaceCount:this._model.length,fixedFloor:this._hasFixedFloor})&&(wm(t),this._tabDragRelease=t=>this._tabPointerUp(t),window.addEventListener("pointerup",this._tabDragRelease),window.addEventListener("pointercancel",this._tabDragRelease),this._tabDrag={id:e,pointerId:t.pointerId,x:t.clientX,y:t.clientY,moved:!1,targetId:null,placement:null})}_tabDropTargetAt(t,e,i){const s=this._model.map(t=>t.id),n=s.indexOf(i);if(n<0)return null;const o=this.renderRoot.querySelectorAll('[data-hp="space-tab"]');for(const a of o){const o=a.dataset.id||"";if(!o||o===i)continue;const r=a.getBoundingClientRect();if(tr.right||er.bottom)continue;const l=s.indexOf(o);return l<0?null:{targetId:o,placement:l=4)))return;var i,s;const n=this._tabDropTargetAt(t.clientX,t.clientY,e.id);e.moved&&e.targetId===n?.targetId&&e.placement===n?.placement||(this._tabDrag={...e,moved:!0,targetId:n?.targetId||null,placement:n?.placement||null})}_tabPointerUp(t){const e=this._tabDrag;if(e&&e.pointerId!==t.pointerId)return;const i="pointerup"===t.type&&e?.moved?this._tabDropTargetAt(t.clientX,t.clientY,e.id):null;"pointerup"===t.type&&e?.moved&&this._suppressNextTabClick(),this._endTabDrag(),e?.moved&&i&&this._commitTabOrder(e.id,i.targetId)}_endTabDrag(){this._tabDrag=null,this._tabDragRelease&&(window.removeEventListener("pointerup",this._tabDragRelease),window.removeEventListener("pointercancel",this._tabDragRelease),this._tabDragRelease=null)}_tabClick(t){if(this._tabSuppressClick)return this._tabSuppressClick=!1,clearTimeout(this._tabSuppressClickTimer),void(this._tabSuppressClickTimer=void 0);this._pickSpace(t)}_suppressNextTabClick(){this._tabSuppressClick=!0,clearTimeout(this._tabSuppressClickTimer),this._tabSuppressClickTimer=window.setTimeout(()=>{this._tabSuppressClick=!1,this._tabSuppressClickTimer=void 0},0)}_commitTabOrder(t,e){const i=this._serverCfg;if(!i||!this._canReorderTabs)return;const s=this._model.map(t=>t.id),n=function(t,e,i){const s=t.indexOf(e),n=t.indexOf(i);if(s<0||n<0||s===n)return t;const o=t.slice();return o.splice(s,1),o.splice(n,0,e),o}(s,t,e);if(n===s)return;const o=new Map(this._devices.map(t=>[String(t.id),String(t.area||"")])),a=function(t,e,i,s=()=>""){if(!i)return[];const n=[];for(const o of t){if(!o||!0===o.removed)continue;const t="string"==typeof o.id?o.id:"";if(!t)continue;if("string"==typeof o.space&&o.space)continue;const a=("string"==typeof o.area?o.area:"")||s(t)||"";a&&e[a]||n.push({id:t,space:i})}return n}(i.markers||[],Object.fromEntries(Object.entries(this._areaToSpace).map(([t,e])=>[t,e.space])),s[0]||"",t=>o.get(t)||"");if(a.length){const t=new Map(a.map(t=>[t.id,t.space]));for(const e of i.markers||[]){const i=t.get(String(e.id));i&&(e.space=i)}}i.spaces=function(t,e){const i=new Map(e.map((t,e)=>[t,e]));return t.map((t,e)=>({space:t,index:e})).sort((t,e)=>(i.get(String(t.space?.id))??Number.MAX_SAFE_INTEGER)-(i.get(String(e.space?.id))??Number.MAX_SAFE_INTEGER)||t.index-e.index).map(t=>t.space)}(i.spaces||[],n),this._saveConfig(),this._tabOrderWarned||(this._tabOrderWarned=!0,this._showToast(this._t("toast.space_order_changed")))}_pickSpace(t){if(this._endTabDrag(),t===this._space)return;const e=this._model.map(t=>t.id),i=e.indexOf(this._space),s=e.indexOf(t);this._navApplied=!0,this._showFar=!1,this._frame=null,this._slideTo(t,i>=0&&s0&&Date.now()>=this._cyclePausedUntil&&this._model.length>1&&this._zoom<=1.001){const t=this._model.map(t=>t.id),e=t.indexOf(this._space);this._slideTo(t[(e+1)%t.length],"left"),this._showKioskDots()}}_syncCycleTimer(){clearInterval(this._cycleTimer),this._cycleTimer=void 0,this.isConnected&&!this._hasFixedFloor&&this._config?.kiosk&&Number(this._config.cycle)>0&&(this._cycleTimer=window.setInterval(()=>this._cycleTick(),1e3*Number(this._config.cycle)))}get _editing(){return"plan"===this._mode||"devices"===this._mode||"decor"===this._mode}get _markup(){return"plan"===this._mode}_newContinuityController(){return new Ch(()=>{this._resumeSettling="steady"!==this._continuity.state,this._continuityEpoch++,this.isConnected&&this.requestUpdate()})}get _labsIso(){return this._labs.active.includes("iso")}get _desiredProjection(){return"view"===this._mode&&this._labsIso&&"iso"===this._viewPreference[this._space]?"iso":"flat"}_saveViewPreference(){try{localStorage.setItem(dm,JSON.stringify(this._viewPreference))}catch{}}_logicalViewCenter(t){const e=this._view;if(!e)return null;const i=[e.x+e.w/2,e.y+e.h/2],s="iso"===t?cg(i):i;return{x:s[0],y:s[1]}}_convertProjectionView(t,e){if(t===e)return;const i=this._logicalViewCenter(t);this._view=null;const s=i?"iso"===e?lg([i.x,i.y],0):[i.x,i.y]:null;this._applyView(this._zoom,s?.[0],s?.[1]),this._warmPatch({vp:this._warmViewportState()}),this.requestUpdate()}_setProjection(t){if(!this._labsIso||"view"!==this._mode)return;const e=this._effectiveProjection();if(this._viewPreference={...this._viewPreference,[this._space]:t},"iso"===t){const t=this._isoSceneKey();t&&this._isoFallback.delete(t)}this._saveViewPreference();const i=this._effectiveProjection();this._convertProjectionView(e,i)}_hashSpace(){return Y_(window.location.hash||"")}connectedCallback(){this._connectedPath=location.pathname,this._routeDepartureHandled=!1,window.addEventListener("location-changed",this._onLocationChanged),window.addEventListener("popstate",this._onLocationChanged),this._continuityDisposed&&(this._continuity=this._newContinuityController(),this._continuityDisposed=!1,this._continuityPaintToken=-1);const t=(e=this.ownerDocument,T_.get(e)?.resolved);var e;void 0!==t&&(this._glowScreenBlend=t),this._continuityUnsub?.(),this._continuityUnsub=Sh(this.ownerDocument,this._pageVisibility),super.connectedCallback(),this._pointerModality.connect(this.ownerDocument.defaultView);const i=this.ownerDocument.defaultView?.MutationObserver;i&&(this._pointerHoverObserver=new i(t=>{for(const e of t)for(const t of e.addedNodes)this._syncPointerHoverSubtree(t)}),this._pointerHoverObserver.observe(this.renderRoot,{childList:!0,subtree:!0})),this._motionMedia=window.matchMedia?.("(prefers-reduced-motion: reduce)"),this._reducedMotion=!!this._motionMedia?.matches,this._motionMedia?.addEventListener?.("change",this._onMotionChange),function(t){const e=T_.get(t);if(e)return e.promise;const i={promise:Promise.resolve(!1)};return i.promise=R_(t).catch(()=>!1).then(t=>(i.resolved=t,t)),T_.set(t,i),i.promise}(this.ownerDocument).then(t=>{t!==this._glowScreenBlend&&(this._glowScreenBlend=t,this.isConnected&&this.requestUpdate())}),this.hass&&this._ensureHaRegistryAuthority(),window.addEventListener("keydown",this._keyHandler),this._signer.start(()=>this.hass,()=>Is(this._serverCfg)),this._syncCycleTimer(),window.addEventListener("hashchange",this._onHashChange),this._labsUnsub?.(),this._labsUnsub=function(t,e){ig.add(e);const i=og(t);return"undefined"==typeof window&&e(i),()=>{ig.delete(e)}}(Vg,this._onLabsSnapshot),this._booting?this._bootWatch():this._bootFading&&(clearTimeout(this._bootTimer),this._bootTimer=window.setTimeout(()=>{this._bootFading=!1},220)),this._bootSoft&&(clearTimeout(this._bootSoftTimer),this._bootSoftTimer=window.setTimeout(()=>{this._bootSoft=!1},Zg)),!this._loadOk&&this._serverCfg&&this.hass&&this._scheduleLoadRetry(),!this._warmSlot&&this._config&&this._warmAdopt(),this._loadOk&&this._ensureLiveSyncSubscriptions(),this._warmVp&&!this._warmRevivePending&&void 0===this._warmReviveTimer&&(this._warmRevivePending=!0,this._warmReviveTimer=window.setTimeout(()=>this._warmReviveDialog(),0)),this._warmLongReturn&&this._beginResumeSettle(),this._warmLongReturn=!1,this.requestUpdate()}disconnectedCallback(){this._connectedPath&&location.pathname!==this._connectedPath&&this._leaveCardRoute(),window.removeEventListener("location-changed",this._onLocationChanged),window.removeEventListener("popstate",this._onLocationChanged),this._continuityUnsub?.(),this._continuityUnsub=void 0,this._motionMedia?.removeEventListener?.("change",this._onMotionChange),this._motionMedia=void 0,this._vacRaf&&(cancelAnimationFrame(this._vacRaf),this._vacRaf=0),this._refitRaf&&(cancelAnimationFrame(this._refitRaf),this._refitRaf=0),this._dayCycleTimer&&(clearInterval(this._dayCycleTimer),this._dayCycleTimer=0),this._dayCycleClockKey="",this._bootSettleRaf&&(cancelAnimationFrame(this._bootSettleRaf),this._bootSettleRaf=0),this._bootSettling=!1;for(const t of this._activityRt.values())clearTimeout(t.timer);window.removeEventListener("keydown",this._keyHandler),this._endTabDrag(),clearTimeout(this._tabSuppressClickTimer),this._tabSuppressClickTimer=void 0,this._tabSuppressClick=!1,clearInterval(this._cycleTimer),clearTimeout(this._kioskDotsTimer),clearTimeout(this._kioskHoldTimer),clearTimeout(this._reloadRetry),clearTimeout(this._loadRetryTimer),this._loadRetryTimer=void 0,this._connHooked?.removeEventListener?.("ready",this._onConnReady),this._connHooked?.removeEventListener?.("disconnected",this._onConnLost),this._connHooked?.removeEventListener?.("reconnect-error",this._onConnLost),this._connHooked=null,this._haRegistryRelease?.(),this._haRegistryRelease=void 0,this._haRegistryConnection=null,this._signer.dispose(),clearTimeout(this._toastTimer),clearTimeout(this._slideTimer),this._modeTransition.dispose(),this._modeTransitionVisual=null,this._modeTransitionPreparing=!1,this._modeTransitionForceAtomic=!1,this._modeTransitionRequest++,this._slideTimer=void 0,this._slide="",clearTimeout(this._bootTimer),this._bootTimer=void 0,clearTimeout(this._bootSoftTimer),this._saveConfigDebounced.flush(),window.removeEventListener("hashchange",this._onHashChange),this._labsUnsub?.(),this._labsUnsub=void 0,clearTimeout(this._holdTimer),this._roViewport?.disconnect(),this._roViewport=void 0,this._roHdr?.disconnect(),this._roHdr=void 0,this._onWinResize&&(window.removeEventListener("resize",this._onWinResize),this._onWinResize=void 0),this._unsubCfg&&(this._unsubCfg(),this._unsubCfg=null),this._unsubLayout&&(this._unsubLayout(),this._unsubLayout=null),this._unsubVirtual&&(this._unsubVirtual(),this._unsubVirtual=null),this._unsubTrail&&(this._unsubTrail(),this._unsubTrail=void 0),this._liveSyncGeneration++,this._liveSyncAttempt=null,this._liveSyncConnection=null,clearTimeout(this._layoutSyncTimer),clearTimeout(this._duplicateColumnTimer);for(const t of this._glowFadeTimers.values())clearTimeout(t);for(const t of this._glowEnterRafs.values())cancelAnimationFrame(t);clearTimeout(this._glowFeatherResumeTimer),this._glowFeatherResumeTimer=0,this._glowFeatherSuspendUntil=0,this._glowFadeTimers.clear(),this._glowEnterRafs.clear(),this._glowEnteringSources.clear(),this._glowRenderedSources.clear(),this._glowLastAppearance.clear(),this._glowSourceSeq=0,this._warmSnapshot(),this._warmRevivePending=!1,clearTimeout(this._warmReviveTimer),this._warmReviveTimer=void 0,this._warmRelease(),this._openWallAnchor=null,this._boundaryRestoreGuard=null,this._clearPlanSnapHover(),this._clearOpeningPlacement(!0),this._touchContacts.clear(),this._touchSequenceMultitouch=!1,this._touchClickBlockUntil=0,this._clearTransientHover(!0),this._cancelDevicePressFeedback(),this._pointerHoverObserver?.disconnect(),this._pointerHoverObserver=void 0,this._pointerModality.disconnect(),this._editorSecondary.reset(),this._resumeSettling=!1,this._continuityHistory=[...this._continuityHistory,...this._continuity.trace].slice(-80),this._continuity.dispose(),this._continuityDisposed=!0,super.disconnectedCallback()}_onKey(t){if("Escape"===t.key&&this._vacFit)return this._vacFit=null,this._showToast(this._t("vac.cal_cancelled")),void t.stopPropagation();if("Escape"===t.key){if(this._tapConfirm)return void(this._tapConfirm=null);if(this._vacCalConfirm)return void(this._vacCalConfirm=null);if(this._decorEraseConfirm)return void(this._decorEraseConfirm=null);if(this._openingInfo)return void(this._openingInfo=null);if(this._infoCard)return void this._closeInfoCard();if(this._rulesDialog)return void(this._rulesDialog=null);if(this._alignDialog)return void(this._alignDialog=null);if(this._backupImportDialog)return void(this._backupImportDialog=null);if(this._backupExportDialog)return void(this._backupExportDialog=null);if(this._settingsDialog)return void(this._settingsDialog=null);if(this._markerDialog)return void(this._markerDialog=null);if(this._openingDialog)return void(this._openingDialog=null);if(this._physicalDialog)return void(this._physicalDialog=null);if(this._backdropDialog)return void(this._backdropDialog=null);if(this._decorShapeDialog)return void(this._decorShapeDialog=null);if(this._decorTextDialog)return void(this._decorTextDialog=null);if(this._spaceDialog&&!this._roomDialog)return this._spaceDialog=null,this._importQueue=[],void(this._importTotal=0);if(this._editorSecondary.hasOpenGroup)return t.preventDefault(),void this._editorSecondary.closeGroup(!0)}const e=t.composedPath?.()||[t.target],i=e.some(t=>t?.matches?.('input, textarea, select, [contenteditable="true"]')),s=e.some(t=>t?.classList?.contains?.("editor-secondary")),n=t.ctrlKey||t.metaKey,o=t.key.toLowerCase(),a=/^[a-z]$/.test(o),r="z"===o||!a&&"KeyZ"===t.code,l="y"===o||!a&&"KeyY"===t.code,c=n&&(r&&t.shiftKey||l),h=n&&r&&!t.shiftKey;if("decor"===this._mode){if((h||c)&&i)return;return c?(t.preventDefault(),void this._redoGeometry()):h?(t.preventDefault(),this._decorDraft?void(this._decorDraft=null):this._decorMove||this._dtDrag||this._bdDrag?void this._cancelDecorGesture():void this._undoGeometry()):"Delete"!==t.key&&"Backspace"!==t.key||!this._decorSel||i||s?void("Escape"===t.key&&(t.preventDefault(),this._decorDraft?this._decorDraft=null:this._decorMove||this._dtDrag||this._bdDrag?this._cancelDecorGesture():"furniture"===this._decorTool?(this._furnPalette=null,this._decorTool="select"):this._decorSel?this._decorSel=null:"select"!==this._decorTool?this._decorTool="select":this._setMode("view"))):(t.preventDefault(),void this._decorDeleteSel())}if(this._markup&&(!h&&!c||!i)){if(("Delete"===t.key||"Backspace"===t.key)&&this._physicalSel&&!i&&!s)return t.preventDefault(),void this._deletePhysicalSelection();if(c)return t.preventDefault(),void this._redoGeometry();if(h)return t.preventDefault(),this._rszDrag?void this._rszCancelDrag():this._wallFaceBatch?(this._roomDialogCancel(),void(this._activeDraftId&&this._path.length>1?this._undoActiveDraftPoint():this._undoPoint())):"draw"===this._tool&&this._path.length?void(this._activeDraftId&&this._path.length>1?this._undoActiveDraftPoint():this._undoPoint()):"split"===this._tool&&this._splitSel?.pts?.length?(this._splitSel={...this._splitSel,pts:this._splitSel.pts.slice(0,-1)},void(this._splitSel.pts.length||(this._cursorPt=null))):void this._undoGeometry();if("Escape"===t.key)return this._physicalDrag||this._physicalRotate?(t.preventDefault(),void this._cancelPhysicalGesture()):this._roomDialog?(t.preventDefault(),void this._roomDialogCancel()):"draw"===this._tool&&this._path.length?(t.preventDefault(),void this._undoPoint()):this._physicalSel?(t.preventDefault(),void(this._physicalSel=null)):"resize"===this._tool?(t.preventDefault(),this._rszDrag?void this._rszCancelDrag():void(this._rszSel?this._rszSel=null:this._tool="draw")):"split"===this._tool?(t.preventDefault(),void(this._splitSel?.pts?.length?(this._splitSel={...this._splitSel,pts:this._splitSel.pts.slice(0,-1)},this._splitSel.pts.length||(this._cursorPt=null)):this._splitSel?this._splitSel=null:this._tool="draw")):"merge"===this._tool?(t.preventDefault(),void(this._mergeSel?this._mergeSel=null:this._tool="draw")):this._wallDialog?(t.preventDefault(),void(this._wallDialog=null)):"boundary"===this._tool?(t.preventDefault(),void(this._openWallAnchor?this._cancelBoundaryAnchor():this._tool="draw")):void("opening"!==this._tool&&"wallthick"!==this._tool&&"delroom"!==this._tool&&"column"!==this._tool||(t.preventDefault(),"opening"===this._tool&&this._clearOpeningPlacement(!0),this._tool="draw"))}}_undoPoint(){if(this._path.length){if(this._contourClosed)return this._path=this._path.slice(0,-1),void(this._closingWallCm=null);if(this._activeDraftId&&this._path.length>1&&this._curSpaceCfg){const t=this._geometrySnapshot();this._path=this._path.slice(0,-1),this._draftSegmentCms=this._draftSegmentCms.slice(0,-1);const e=this._curSpaceCfg,i=(e.room_drafts||[]).findIndex(t=>t.id===this._activeDraftId);return void(i>=0&&(this._path.length<2?(e.room_drafts.splice(i,1),e.room_drafts.length||delete e.room_drafts,this._activeDraftId=null):e.room_drafts[i]={id:this._activeDraftId,points:this._path.map(t=>[t[0]/um,t[1]/um]),segments:this._draftSegmentCms.map(t=>({cm:t}))},this._recordGeometry(this._t("history.draft_segment_delete"),t),this._saveConfig()))}this._path=this._path.slice(0,-1)}}_undoActiveDraftPoint(){const t=this._activeDraftId,e=this._path[0]?[...this._path[0]]:null,i=this._geometryHistory.undo();if(!i)return void this._undoPoint();if(!this._applyGeometryState(i.before))return void this._geometryHistory.clear();const s=t?this._spaceModel()?.room_drafts.find(e=>e.id===t):null;s?(this._activeDraftId=s.id,this._path=s.points.map(t=>[...t]),this._draftSegmentCms=this._adoptDraftCms(this._path,s.segments.map(t=>t.cm),s.id),this._resumeDraftBySpace[this._space]=s.id):(this._activeDraftId=null,this._path=e?[e]:[],this._draftSegmentCms=[],t&&this._resumeDraftBySpace[this._space]===t&&delete this._resumeDraftBySpace[this._space]),this._clearPlanSnapHover(),this._showToast(this._t("history.undone",{name:i.name}))}static getConfigElement(){return document.createElement("houseplan-card-editor")}static getStubConfig(){return{type:"custom:houseplan-card"}}static _warmBootReset(t){for(const t of im.values())for(const e of t)clearTimeout(e.evict);im.clear(),om=t&&t>0?t:1e4}static _warmBootStats(){let t=0,e=0;const i=[];for(const s of im.values())for(const n of s)t++,n.dlg&&(e++,i.push(n.dlg.kind));return{keys:im.size,slots:t,dlgs:e,drafts:i}}setConfig(t){const e=this._config,i=!!e&&Object.prototype.hasOwnProperty.call(e,"floor");this._config={icon_size:2.5,show_temperature:!0,live_states:!0,show_signal:!0,...t};(i!==this._hasFixedFloor||e?.floor!==this._config.floor)&&(this._hashApplied=!1,this._navApplied=!1,this._warmVpArmed=!1),this._config.kiosk&&(this._booting=!1,this._bootFading=!1),!this._hasFixedFloor&&t.default_floor&&this._commitSpace(t.default_floor,!0);try{this._zoomBySpace=JSON.parse(localStorage.getItem(lm)||"{}")||{}}catch{this._zoomBySpace={}}try{const t=JSON.parse(localStorage.getItem(dm)||"{}")||{};this._viewPreference=Object.fromEntries(Object.entries(t).filter(t=>"flat"===t[1]||"iso"===t[1]))}catch{this._viewPreference={}}this._labs=og(Vg);try{const t=JSON.parse(localStorage.getItem(hm)||"null");this._kioskScale={icon:zs(t?.icon),font:zs(t?.font)}}catch{}try{const t=JSON.parse(localStorage.getItem(rm)||"null");t&&t.config&&Array.isArray(t.config.spaces)&&(this._serverCfg=t.config,this._cfgEpoch++,this._cfgRev=t.rev||0,this._cfgContentFingerprint=t.config_fingerprint||Dh(t.config),this._layout=t.layout||{},this._layoutRev=t.layout_rev||0,this._layoutContentFingerprint=t.layout_fingerprint||Dh(this._layout),this._virtualLights=gn(t.virtual_lights,this._cfgRev),this._serverStorage=!0)}catch{}this._adoptInitialSpace(this._model,this._loadOk),"view"!==this._mode||this._view||(this._zoom=this._zoomBySpace[this._space]||1),this.isConnected&&(this._syncCycleTimer(),this._warmAdopt(),this._warmLongReturn&&this._beginResumeSettle(),this._warmLongReturn=!1)}_warmAdopt(){if(this._config?.kiosk)return;const t=nm(this._config);if(this._warmKey===t&&this._warmSlot)return;this._warmSlot&&this._warmRelease();const e=this.parentNode,i=this._warmIdx(e),s=im.get(t);if(!s||!s.length)return;const n=s.find(t=>t.owner===this._warmGen);if(n)return this._warmLongReturn=!!n.freed&&Date.now()-n.freed>=kh,clearTimeout(n.evict),n.evict=0,n.freed=0,n.live=!0,this._warmSlot=n,this._warmKey=t,n.frameFingerprint&&this._continuity.adoptCompleteFrame(n.frameFingerprint),void(!this._devices.length&&n.devices?.length&&(this._devices=[...n.devices]));const{slot:o,sure:a}=((t,e,i,s)=>{const n=t=>{const e=!!i&&t.place?.deref()===i;return e&&t.idx===s?4:t.live?0:e?3:2};let o=null,a=0,r=0,l=null;for(const i of t){if(i.owner===e)continue;l=i;const t=n(i);t<=0||(t>a?(o=i,a=t,r=1):t===a&&r++)}return!o||r>1?{slot:o||l,sure:!1}:{slot:o,sure:!0}})(s,this._warmGen,e,i);o&&(this._warmLongReturn=!!o.freed&&Date.now()-o.freed>=kh,this._booting=!1,this._bootFading=!1,this._hdrH=o.hdrH,this._bootSoft=!0,this.isConnected&&(clearTimeout(this._bootSoftTimer),this._bootSoftTimer=window.setTimeout(()=>{this._bootSoft=!1},Zg)),this._warmKey=t,a?(clearTimeout(o.evict),o.evict=0,o.owner=this._warmGen,o.place=e?new WeakRef(e):null,o.idx=i,o.live=!0,this._warmSlot=o,this._warmVp=o.vp,o.frameFingerprint&&this._continuity.adoptCompleteFrame(o.frameFingerprint),!this._devices.length&&o.devices?.length&&(this._devices=[...o.devices]),this._warmAdoptViewport(this._config)):(this._warmSlot={owner:this._warmGen,path:location.pathname,place:e?new WeakRef(e):null,idx:i,live:!0,hdrH:o.hdrH,stageH:o.stageH,vp:null,frameFingerprint:"",devices:null,dlg:null,freed:0,evict:0},s.push(this._warmSlot),this._warmTrim(s)))}_warmIdx(t){const e=t?.children;if(!e)return-1;for(let t=0;t4;){const e=t.findIndex(t=>!t.live);if(e<0)break;clearTimeout(t[e].evict),t.splice(e,1)}}_warmScheduleEvict(t,e){if(clearTimeout(t.evict),!(t.dlg||t.vp&&"view"!==t.vp.mode))return;const i=t.freed,s=t.owner;t.evict=window.setTimeout(()=>{if(t.evict=0,t.freed!==i||t.owner!==s)return;var n;t.dlg=null,t.vp=(n=t.vp)&&"view"!==n.mode?{...n,mode:"view",zoom:n.snap?.space===n.space?n.snap.zoom:n.zoom,view:null,snap:null,tool:"draw",decorTool:"select",showHidden:!1,selId:null,rszSel:null,decorSel:null}:n,t.frameFingerprint="";const o=im.get(e);if(!t.live&&o&&o.length>1){const e=o.indexOf(t);e>=0&&o.splice(e,1)}},om+250)}_warmAdoptViewport(t){const e=this._warmVp;if(!e||this._warmSlot?.path!==location.pathname)return void(this._warmVp=null);const i=this._fixedFloorState();if(this._hashApplied||!this._model.find(t=>t.id===e.space)||"valid"===i.kind&&i.id!==e.space||this._hasFixedFloor&&"valid"!==i.kind)return void(this._warmVp=null);this._commitSpace(e.space,!0),this._navApplied=!0,this._adoptMode("view"!==e.mode&&this._canEdit&&!t.kiosk?e.mode:"view"),this._pendingNavMode="view"===e.mode||this._canEdit||t.kiosk?null:e.mode,this._zoom=e.zoom;const s=this._effectiveProjection(),n=s===e.projection&&this._labsIso===e.activeLabsIso;if(this._view=n&&e.view?{...e.view}:null,this._viewModeSnap=n&&e.snap?{...e.snap}:null,!n&&e.logicalCenter){const t="iso"===s?lg([e.logicalCenter.x,e.logicalCenter.y],0):[e.logicalCenter.x,e.logicalCenter.y];this._applyView(e.zoom,t[0],t[1])}var o;this._tool="openwall"===(o=e.tool)||"closewall"===o?"boundary":"opening"===(o=function(t){return"partition"===t?"draw":t}(o))?"draw":"string"==typeof o&&mm.has(o)?o:"draw",this._decorTool=e.decorTool,this._showHidden=e.showHidden,this._showFar!==e.showFar&&(this._showFar=e.showFar,this._frame=null),this._selId=e.selId,this._rszSel=e.rszSel,this._decorSel=e.decorSel,this._warmVpArmed=!0}_warmPatch(t,e=!1){if(this._config?.kiosk)return;const i=nm(this._config);if(!this._warmSlot||this._warmKey===i){if(!this._warmSlot){if(!e)return;const t=this.parentNode;this._warmKey=i,this._warmSlot={owner:this._warmGen,path:location.pathname,place:t?new WeakRef(t):null,idx:this._warmIdx(t),live:!0,hdrH:this._hdrH,stageH:0,vp:null,frameFingerprint:"",devices:null,dlg:null,freed:0,evict:0};const s=im.get(i)||[];for(s.push(this._warmSlot),im.set(i,s),this._warmTrim(s);im.size>8;){const t=im.keys().next().value;if(void 0===t||t===i)break;for(const e of im.get(t)||[])clearTimeout(e.evict);im.delete(t)}}Object.assign(this._warmSlot,t)}}_warmViewportState(){const t=this._effectiveProjection();return{space:this._space,mode:this._mode,projection:t,activeLabsIso:this._labsIso,logicalCenter:this._logicalViewCenter(t),zoom:this._zoom,view:this._view?{...this._view}:null,snap:this._viewModeSnap?{...this._viewModeSnap}:null,tool:this._tool,decorTool:this._decorTool,showHidden:this._showHidden,showFar:this._showFar,selId:this._selId,rszSel:this._rszSel,decorSel:this._decorSel}}_warmDialogState(){const t=(t,e)=>({kind:t,space:this._space,mode:this._mode,data:e});return this._tapConfirm||this._alignDialog||this._mergeDialog||this._importDialog||this._backupExportDialog||this._backupImportDialog?null:this._openingInfo?t("openingInfo",this._openingInfo.id):this._infoCard?t("info",this._infoCard.id):this._rulesDialog?this._rulesDialog.busy?null:t("rules",this._rulesDialog):this._settingsDialog?this._settingsDialog.busy?null:t("settings",this._settingsDialog):this._markerDialog?this._markerDialog.busy?null:t("marker",this._markerDialog):this._openingDialog?t("opening",this._openingDialog):this._backdropDialog?t("backdrop",this._backdropDialog):this._decorShapeDialog?t("decorShape",this._decorShapeDialog):this._decorTextDialog?t("decorText",this._decorTextDialog):this._roomDialog?t("room",{editId:this._roomEditId,fill:this._roomFill,customFill:this._roomCustomFill,tempSrc:this._roomTempSrc,humSrc:this._roomHumSrc,srcOpen:this._roomSrcOpen,srcFilter:this._roomSrcFilter,nameScale:this._roomNameScale,labelScale:this._roomLabelScale,areaSel:this._areaSel,nameSel:this._nameSel,pendingSplit:this._pendingSplit,wallFaceBatch:this._wallFaceBatch,path:this._path}):this._spaceDialog?this._spaceDialog.busy?null:t("space",this._spaceDialog):null}_warmSnapshot(){if(this._booting||this._config?.kiosk||"steady"!==this._continuity.state)return;const t={vp:this._warmViewportState(),frameFingerprint:this._continuity.frameFingerprint,devices:this._devices};if(this._warmRevivePending||(t.dlg=this._warmDialogState()),this.isConnected&&this._warmSlot?.owner===this._warmGen){const e=this.parentNode;t.place=e?new WeakRef(e):null,t.idx=this._warmIdx(e)}this._warmPatch(t)}_warmReviveDialog(){this._warmRevivePending=!1;const t=this._warmSlot;if(this._warmReviveTimer=void 0,!t||!t.dlg)return;const e=t.dlg,i=t.freed;if(t.dlg=null,t.freed=0,clearTimeout(t.evict),t.evict=0,i&&!(Date.now()-i>om)&&e.space===this._space&&e.mode===this._mode){switch(e.kind){case"space":this._spaceDialog={...e.data,busy:!1,savedBusy:!1};break;case"marker":this._markerDialog={...e.data,busy:!1};break;case"settings":this._settingsDialog={...e.data,busy:!1};break;case"rules":this._rulesDialog={...e.data,busy:!1};break;case"opening":this._openingDialog={...e.data};break;case"backdrop":this._backdropDialog={...e.data};break;case"decorShape":this._decorShapeDialog={...e.data};break;case"decorText":{this._decorTextDialog={...e.data};const t=String(this._decorTextDialog?.text??"").length;this._decorTextSelection={start:t,end:t};break}case"room":{const t=e.data;this._roomEditId=t.editId,this._roomFill=t.fill,this._roomCustomFill=t.customFill||null,this._roomTempSrc=t.tempSrc,this._roomHumSrc=t.humSrc,this._roomSrcOpen=t.srcOpen,this._roomSrcFilter=t.srcFilter,this._roomNameScale=t.nameScale,this._roomLabelScale=t.labelScale,this._areaSel=t.areaSel,this._nameSel=t.nameSel,this._pendingSplit=t.pendingSplit,this._wallFaceBatch=t.wallFaceBatch||null,this._path=t.path,this._wallFaceBatch&&(this._activeDraftId=this._wallFaceBatch.activeDraftId,this._draftSegmentCms=[...this._wallFaceBatch.activeCms]),this._roomDialog=!0;break}case"info":{const t=this._devices.find(t=>t.id===e.data);t&&(this._infoCard=t);break}case"openingInfo":{const t=(this._curSpaceCfg?.openings||[]).find(t=>t.id===e.data);t&&(this._openingInfo=t);break}}this.requestUpdate()}}_cacheSnapshot(){if(this._serverCfg)try{this._cfgContentFingerprint=Dh(this._serverCfg),this._layoutContentFingerprint=Dh(this._layout),this._virtualLights=function(t,e,i){if(t.configRev===i)return t;const s=new Set((Array.isArray(e?.markers)?e.markers:[]).filter(yn).map(t=>t.id));return{...t,configRev:i,off:new Set([...t.off].filter(t=>s.has(t)))}}(this._virtualLights,this._serverCfg,this._cfgRev),localStorage.setItem(rm,JSON.stringify({config:this._serverCfg,rev:this._cfgRev,config_fingerprint:this._cfgContentFingerprint,layout:this._layout,layout_rev:this._layoutRev,layout_fingerprint:this._layoutContentFingerprint,virtual_lights:fn(this._virtualLights)}))}catch{}}_beginContinuityCandidate(t,e,i="plan"){return this._booting&&!this._continuity.hasCompleteFrame?this._continuity.token:(this._continuityDataReady=e,this._continuityPaintToken=-1,this._stagedDeviceSnapshotToken=-1,this._resumeSettling=!0,this._continuity.beginCandidate(t,i))}_continuityStageValid(){const t=this._stageEl;return!!t&&t.clientWidth>0&&t.clientHeight>0}_continuityAssetsReady(){if(!this._model.length)return!1;const t=this._model.length?this._spaceModel():null;return!t?.bg?.href||this._signer.isReady(this.hass,t.bg.href)}_initialSpaceSelection(t,e=this._loadOk){const i=this._fixedFloorState(t,e);return"valid"===i.kind?{id:i.id,source:"fixed"}:this._hasFixedFloor?{id:null,source:"none"}:function(t){const e=new Set(t.spaceIds.filter(t=>!!t));if(!e.size)return{id:null,source:"none"};const i=[["hash",!1===t.acceptHash?null:t.hashSpace],["current",t.preserveCurrent?t.currentSpace:null],["saved",t.savedSpace],["default",t.defaultSpace],["first",t.spaceIds[0]]];for(const[t,s]of i)if(s&&e.has(s))return{id:s,source:t};return{id:null,source:"none"}}({spaceIds:t.map(t=>t.id),hashSpace:this._hashSpace(),acceptHash:!this._hashApplied,currentSpace:this._space,preserveCurrent:this._hashApplied||this._navApplied||this._warmVpArmed,savedSpace:this._savedNav()?.space,defaultSpace:this._config?.default_floor})}_adoptInitialSpace(t,e=this._loadOk){const i=this._initialSpaceSelection(t,e);return i.id?(this._commitSpace(i.id,!0),"hash"===i.source&&(this._hashApplied=!0),"saved"===i.source&&(this._navApplied=!0),i):i}_candidateBackdrop(t,e=this._space){const i=yc(t),s=this._fixedFloorState(i,!0);if(this._hasFixedFloor&&"valid"!==s.kind)return"";const n=this._initialSpaceSelection(i,!0).id||(i.some(t=>t.id===e)?e:i[0]?.id);return i.find(t=>t.id===n)?.bg?.href||""}_visualFrameFingerprint(){const t=this._stageEl,e=t?[t.clientWidth,t.clientHeight]:[0,0];return Th([this._cfgRev,this._cfgContentFingerprint||Dh(this._serverCfg),this._layoutRev,this._layoutContentFingerprint||Dh(this._layout),this._space,this._mode,this._view,e,this._glowScreenBlend?"screen":"normal",this.hass?.themes?.darkMode??this.hass?.themes?.default_theme??""])}_settleContinuityFrame(){if(this._booting||!this._continuityStageValid())return;if(!this._continuity.hasCompleteFrame&&"steady"===this._continuity.state)return void(this._continuityAssetsReady()&&(this._renderSnapshotAt=Date.now(),this._continuity.markCompleteFrame(this._visualFrameFingerprint())));if(!this._continuityDataReady)return;if(!["holding","offline-stale","overlay-pending","overlay-visible","candidate-ready"].includes(this._continuity.state))return;const t=this._continuity.token;if(this._candidateDeviceSnapshot&&this._candidateDeviceSnapshot!==this._visibleDeviceSnapshot&&this._stagedDeviceSnapshotToken!==t)return this._stagedDeviceSnapshotToken=t,void this.requestUpdate();this._continuityPaintToken!==t&&(this._continuityPaintToken=t,this._continuity.candidateReady(t)&&this._continuity.commitAfterPaint(t,{updateComplete:()=>this.updateComplete,stageValid:()=>this.isConnected&&this._continuityStageValid(),assetsReady:()=>this._continuityAssetsReady(),frameFingerprint:()=>this._visualFrameFingerprint()}).then(e=>{e&&t===this._continuity.token?(this._resumeSettling=!1,this._renderSnapshotAt=Date.now(),this._candidateDeviceSnapshot&&(this._visibleDeviceSnapshot=this._candidateDeviceSnapshot),this._candidateDeviceSnapshot=null,this._stagedDeviceSnapshotToken=-1,this._warmSnapshot()):t===this._continuity.token&&(this._continuityPaintToken=-1,this._stagedDeviceSnapshotToken=-1,this._candidateDeviceSnapshot=null,this.requestUpdate())}))}_onBackdropLoaded(t,e){this._signer.markLoaded(this.hass,t,e),this._continuity.note("asset-ready"),this._continuityPaintToken=-1,"steady"!==this._continuity.state&&this.requestUpdate()}_renderRecoveryOverlay(){if(!this._continuity.overlayVisible&&"recovery-error"!==this._continuity.state)return G;const t="connection"===this._continuity.recoveryReason;return W`
t.stopPropagation()} @click=${t=>t.stopPropagation()} @@ -4907,26 +4907,26 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8 ${this._t(t?"continuity.restore_connection":"continuity.restore_plan")} ${"recovery-error"===this._continuity.state?W``:G} -
`}houseplanContinuityTrace(){return[...this._continuityHistory,...this._continuity.trace].slice(-80).map(t=>({...t,...t.stage?{stage:[...t.stage]}:{}}))}getCardSize(){return 12}get _norm(){return!(!this._serverCfg||!this._serverCfg.spaces.length)}_cfgFingerprint(){const t=this._serverCfg?.spaces||[];let e=t.length+":";for(const i of t){e+=(i.id||"")+","+(i.plan_aspect||"")+","+(i.plan_url||"").length+","+(i.plan_x??"")+","+(i.plan_y??"")+","+(i.plan_scale??"")+","+(i.plan_scale_x??"")+","+(i.plan_scale_y??"")+","+(i.plan_angle??"")+","+(i.rooms?.length||0)+","+(i.openings?.length||0)+","+(i.decor?.length||0)+";";for(const t of i.rooms||[]){const i=t.poly?.[0],s=t.poly?.[t.poly.length-1];e+=(t.poly?.length||0)+"."+(t.id||"")+"."+(t.open_to||[]).join("+")+"."+(t.area||"")+"."+JSON.stringify(t.settings||0)+"."+(t.x??"")+","+(t.y??"")+","+(t.w??"")+","+(t.h??"")+","+(i?i[0]+"/"+i[1]:"")+","+(s?s[0]+"/"+s[1]:"")+";"}}return e}get _model(){if(!this._serverCfg)return[];const t=this._cfgEpoch+"|"+this._cfgFingerprint();if(this._modelCache&&this._modelCache.key===t)return this._modelCache.model;const e=this._buildModel();return this._modelCache={key:t,model:e},e}_buildModel(){if(!this._serverCfg)return[];const t=this._renderCfg;return vc(t).map((e,i)=>{const s=t.spaces[i]?.plan_url;return e.bg&&s?{...e,bg:{...e.bg,href:s}}:e})}_spaceModel(){return this._hasFixedFloor?Rh(this._model,this._space):(t=this._model,e=this._space,t.find(t=>t.id===e)??t[0]);var t,e}_spaceModelById(t){return Rh(this._model,t)}_syncEmptySpaceState(){if(!!this._serverCfg&&0===this._serverCfg.spaces.length){if(!this._emptySpaceStateActive){this._emptySpaceStateActive=!0;for(const t of this._pointers.keys())for(const e of this.renderRoot.querySelectorAll("*"))try{e.hasPointerCapture?.(t)&&e.releasePointerCapture(t)}catch{}this._pointers.clear(),this._panStart=null,this._panLock=null,this._pinchStart=null,this._swipeStart=null,this._drag=null,this._rlResize=null,this._vacFit=null,this._compassDrag=!1,this._cancelModeTransition(!1),this._mode="view",this._clearGeometryGesture(),this._geometryHistory.clear(),this._resumeDraftBySpace={},this._tip=null,this._hoverRoom=null,this._openingInfo=null,this._closeInfoCard(),this._markerDialog=null,this._physicalDialog=null,this._backdropDialog=null,this._decorShapeDialog=null,this._decorTextDialog=null,this._roomDialog=!1,"edit"===this._spaceDialog?.mode&&(this._spaceDialog=null),this._editorSecondary.closeForNavigation(),this._saveConfigDebounced.cancel(),this._frame=null,this._planSnapGeometryCache=null,this._decorSnapCache=null,this._commitSpace("",!0)}}else this._emptySpaceStateActive=!1}get _areaToSpace(){const t={};for(const e of this._model)for(const i of e.rooms)i.area&&(t[i.area]={space:e.id,room:i});return t}get _settings(){return this._serverCfg?.settings||{}}get _showAll(){return this._settings.filter_seeded?this._showHidden:!!this._settings.show_all}_toggleShowAll(){if(this._serverCfg){if(this._settings.filter_seeded)return this._showHidden=!this._showHidden,void this.requestUpdate();this._serverCfg={...this._serverCfg,settings:{...this._serverCfg.settings,show_all:!this._settings.show_all}},this._regSignature="",this._maybeRebuildDevices(),this._saveConfig(),this.requestUpdate()}}_seedHiddenDevices(){if(!this._serverCfg||!this._norm||!this._canEdit)return;const t=this._serverCfg,e=function(t){const e=t.hass,i=t.registry||An(e),s=On(e,i),n=Nn(e,i),{areaToSpace:o,markers:r,settings:a,excluded:l,iconRules:c}=t,h=!1!==a.group_lights,d=wo(r),p=yo(s,h).filter(t=>!ko(s,t.eid,d)),u=new Set(p.map(t=>t.area)),_=qn(s),g=Wn(r,n),m=new Set(r.map(t=>t.binding)),f=[];for(const t of Object.values(s.devices)){const n=t.area_id;if(!n||!o[n])continue;if("service"===t.entry_type)continue;if(m.has("device:"+t.id))continue;if("active"!==Bn(e,"device:"+t.id,i).kind)continue;const r=jn(s,t.id,_[t.id]||[],g);if(r.partial&&!r.entityIds.length)continue;const a=r.entityIds,d=Un(s,t,a);let p=l.has(d)||"Group"===t.model||/scene/i.test(t.model||"")||/bridge/i.test((t.model||"")+(t.name||""))||"myheat"===d&&!!t.via_device_id;if(!p&&h&&u.has(n)){const e=(t.name_by_user||t.name||"").trim();"mdi:lightbulb"===bo(s,e,t.model,a,c)&&(p=!0)}p&&f.push("device:"+t.id)}return f}({hass:this.hass,registry:this._haRegistry,areaToSpace:Object.fromEntries(Object.entries(this._areaToSpace).map(([t,e])=>[t,e.space])),markers:this._markers,settings:this._settings,excluded:this._excluded,firstSpaceId:this._model[0]?.id||"",iconRules:this._iconRules});if(!e.length&&t.settings?.filter_seeded)return;t.markers=t.markers||[];const i=[];for(const s of e){const e="h"+s.slice(s.indexOf(":")+1);t.markers.push({id:e,binding:s,hidden:!0}),i.push(s.slice(s.indexOf(":")+1))}const s={...t.settings||{},filter_seeded:!0};delete s.show_all,i.length&&Array.isArray(s.new_device_ids)&&(s.new_device_ids=s.new_device_ids.filter(t=>!i.includes(t))),t.settings=s,this._regSignature="",this._maybeRebuildDevices(),this._saveConfig(),this.requestUpdate()}get _iconRules(){const t=this._settings.icon_rules;if(!t||!Array.isArray(t)||!t.length)return;const e=JSON.stringify(t);return e!==this._rulesCompiledSrc&&(this._rulesCompiledSrc=e,this._rulesCompiled=Jt(t)),this._rulesCompiled}get _fillColors(){return ps(this._settings)}get _excluded(){const t=this._settings.exclude_integrations;return t?new Set(t):Yt}willUpdate(t){t.has("_serverCfg")&&this._cfgEpoch++,this._syncEmptySpaceState(),t.has("hass")&&this.hass&&(this._hassSequence++,this._renderSnapshotAt=Date.now(),this._continuity.note("hass-snapshot"),this._ensureHaRegistryAuthority(),this._planHassMemo=null,this._hookConnection(),!this._loadOk&&!this._loading&&this._loadTries<8&&this._loadFromServer(),this._maybeRebuildDevices(),this._vacTick(),this._activityTick()),this._continuity.hasCompleteFrame&&"steady"===this._continuity.state&&this._continuity.refreshCompleteFrame(this._visualFrameFingerprint()),this._captureRenderDeviceSnapshot()}updated(){this._pruneDevicePressFeedback(),this._syncDayCycleClock(),this._warmSnapshot(),this._dtMeasure();const t=this._stageEl;t&&!this._roViewport&&(this._roViewport=new ResizeObserver(()=>this._refitView()),this._roViewport.observe(t)),t&&this._booting&&!this._bootTimer&&this._bootWatch();const e=this.renderRoot.querySelector(".hdr");if(e&&t&&!this._roHdr){const i=()=>{const e=this.renderRoot.querySelector("ha-card");if(!e)return;const i=t.getBoundingClientRect().top-e.getBoundingClientRect().top,s=Math.min(Math.max(e.getBoundingClientRect().top,0),120),n=Math.round(i+s);n>=0&&n!==this._hdrH&&(this._hdrH=n),n>=0&&!this._booting&&!this._config?.kiosk&&t.clientHeight>0&&this._warmPatch({hdrH:n,stageH:t.clientHeight})};this._roHdr=new ResizeObserver(()=>requestAnimationFrame(i)),this._roHdr.observe(e),this._onWinResize=()=>requestAnimationFrame(i),window.addEventListener("resize",this._onWinResize),i()}if(t&&!this._view&&this._refitView(),this._editorSecondary.afterRender(),this._settleContinuityFrame(),this._serverStorage&&this._loadOk&&0===this._model.length&&!this._spaceDialog&&!this._importDialog&&!this._onboardingShown){this._onboardingShown=!0;const t=function(t){const e=t?.floors;if(!e||"object"!=typeof e)return[];const i=[];for(const t of Object.values(e))t&&t.floor_id&&i.push({id:t.floor_id,name:t.name||t.floor_id,level:t.level??null});return i.sort((t,e)=>{const i=t.level??1e9,s=e.level??1e9;return i!==s?i-s:t.name.localeCompare(e.name)}),i}(this.hass);t.length?this._importDialog={floors:t.map(t=>({...t,checked:!0}))}:this._openSpaceDialog("create")}}_adoptStructuralResponses(t,e,i){const s=t?.config,n=s&&Array.isArray(s.spaces)?s:null,o=Ch(n),r=o!==(this._cfgContentFingerprint||Ch(this._serverCfg));if(r&&(this._geometryHistory.clear(),this._serverCfg&&this._clearGeometryGesture(),this._serverCfg=n,this._cfgContentFingerprint=o),this._cfgRev=t?.rev??this._cfgRev,t&&("virtual_lights"in t||"config"in t)){const e=mn(this._virtualLights,t.virtual_lights,this._cfgRev,"virtual_lights"in t);vn(e)!==vn(this._virtualLights)&&(this._virtualLights=e,this._capturedSnapshotVirtual="")}let a=!1;if(void 0!==e||void 0!==i){const t=i??e?.layout??{},s=Ch(t);a=s!==(this._layoutContentFingerprint||Ch(this._layout)),a&&(this._layout=t,this._layoutContentFingerprint=s),this._layoutRev=e?.rev??this._layoutRev}return this._canOptimizeUndo=!(!t?.can_optimize_undo&&!e?.can_optimize_undo),this._undoKind=t?.undo_kind||e?.undo_kind||null,"boolean"==typeof t?.can_write&&(this._serverCanWrite=t.can_write),r&&this._continuity.note("config-candidate",{configRev:this._cfgRev}),a&&this._continuity.note("layout-candidate",{layoutRev:this._layoutRev}),{configChanged:r,layoutChanged:a}}_resumePendingNavMode(){if(!this._pendingNavMode||!this._canEdit||this._config?.kiosk)return!1;const t=this._pendingNavMode;return this._pendingNavMode=null,this._setMode(t,!1),!0}async _loadFromServer(){this._loading=!0,this._loadTries++;const t=this._space,e=!!this._view;try{const[i,s]=await Promise.all([this.hass.callWS({type:"houseplan/config/get"}),this.hass.callWS({type:"houseplan/layout/get"})]),n=i?.config&&Array.isArray(i.config.spaces)?i.config:null,o=Ch(n)!==(this._cfgContentFingerprint||Ch(this._serverCfg))||Ch(s?.layout??{})!==(this._layoutContentFingerprint||Ch(this._layout));if(o){if(!await this._signer.prepareImage(this.hass,this._candidateBackdrop(n)))return this._continuity.note("asset-failed"),void this._scheduleLoadRetry(!0)}o&&this._continuity.hasCompleteFrame&&"steady"===this._continuity.state&&this._beginContinuityCandidate("structural-response",!0),this._connectionWasLost=!1,this._serverStorage=!0,"boolean"==typeof i?.can_write&&(this._serverCanWrite=i.can_write),this._canOptimizeUndo=!(!i?.can_optimize_undo&&!s?.can_optimize_undo),this._adoptStructuralResponses(i,s),this._adoptInitialSpace(this._model,!0),this._resumePendingNavMode(),this._cacheSnapshot(),this._warmVpArmed&&this._space===this._warmVp?.space?this._warmVpArmed=!1:e&&this._space===t||this._restoreZoom(),this._loadOk=!0,this.hass.callWS({type:"houseplan/trail/get"}).then(t=>{this._vacSrvTrails=t?.trails||{},this.requestUpdate()}).catch(()=>{}),this._ensureLiveSyncSubscriptions()}catch(t){if(this._serverCfg)this._scheduleLoadRetry(!0);else if(this._loadTries>=8){this._serverStorage=!1;try{this._layout=JSON.parse(localStorage.getItem(om)||"{}")||{}}catch{this._layout={}}}}finally{this._loading=!1,this._continuityDataReady=!0,this._regSignature="",this._maybeRebuildDevices(),this.requestUpdate()}}_ensureLiveSyncSubscriptions(){const t=this.hass?.connection;if(!t)return;if(t!==this._liveSyncConnection&&(this._unsubCfg?.(),this._unsubCfg=null,this._unsubLayout?.(),this._unsubLayout=null,this._unsubTrail?.(),this._unsubTrail=void 0,this._unsubVirtual?.(),this._unsubVirtual=null,this._liveSyncGeneration++,this._liveSyncAttempt=null,this._liveSyncConnection=t),this._liveSyncAttempt)return;const e=this._liveSyncGeneration,i=[],s=(s,n,o,r)=>{s()||i.push(async()=>{const i=await t.subscribeEvents(r,o);e===this._liveSyncGeneration&&this.isConnected&&this.hass?.connection===t&&!s()?n(i):i?.()})};if(s(()=>this._unsubCfg,t=>{this._unsubCfg=t},"houseplan_config_updated",t=>{const e=Number(t?.data?.rev??-1);e!==this._cfgRev&&this._reloadConfigOnly(!1,e)}),s(()=>this._unsubTrail,t=>{this._unsubTrail=t},"houseplan_trail_updated",async()=>{try{const t=await this.hass.callWS({type:"houseplan/trail/get"});this._vacSrvTrails=t?.trails||{},this.requestUpdate()}catch{}}),s(()=>this._unsubLayout,t=>{this._unsubLayout=t},"houseplan_layout_updated",t=>this._onLayoutEvent(Number(t?.data?.rev??-1))),s(()=>this._unsubVirtual,t=>{this._unsubVirtual=t},"houseplan_virtual_light_updated",t=>{const e=wn(this._virtualLights,t?.data);e!==this._virtualLights&&(this._virtualLights=e,this._capturedSnapshotVirtual="",this._cacheSnapshot(),this.requestUpdate())}),!i.length)return;const n=function(t){return Promise.allSettled(t.map(t=>Promise.resolve().then(t)))}(i).then(()=>{});this._liveSyncAttempt=n,n.finally(()=>{this._liveSyncAttempt===n&&(this._liveSyncAttempt=null)})}async _reloadConfigOnly(t=!1,e){if(!t){if(void 0!==e&&e<=this._cfgRev)return;if(this._saveConfigDebounced.pending()&&this._saveConfigDebounced.flush(),this._cfgWriting)return clearTimeout(this._reloadRetry),void(this._reloadRetry=window.setTimeout(()=>this._reloadConfigOnly(!1,e),400))}this._beginContinuityCandidate("config-reload",!1);try{const t=await this.hass.callWS({type:"houseplan/config/get"}),e=t?.config&&Array.isArray(t.config.spaces)?t.config:null;if(Ch(e)!==(this._cfgContentFingerprint||Ch(this._serverCfg))&&!await this._signer.prepareImage(this.hass,this._candidateBackdrop(e)))return this._continuity.note("asset-failed"),void this._scheduleLoadRetry(!0);const i=this._space;this._adoptStructuralResponses(t),this._adoptInitialSpace(this._model,!0),this._resumePendingNavMode(),this._cacheSnapshot(),this._space!==i&&this._restoreZoom(),this._regSignature="",this._maybeRebuildDevices(),this.requestUpdate()}catch(t){this._showToast(this._t("toast.cfg_reload_failed",{err:this._errText(t)}))}finally{this._continuityDataReady=!0,this.requestUpdate()}}_scheduleLoadRetry(t=!1){if(void 0!==this._loadRetryTimer)return;const e=Math.min(8e3,500*2**Math.min(4,Math.max(1,this._loadTries-7)));this._loadRetryTimer=window.setTimeout(()=>{this._loadRetryTimer=void 0,!t&&this._loadOk||this._loading||!this.hass||this._loadFromServer()},e)}_ensureHaRegistryAuthority(){const t=this.hass?.connection||null;t&&t!==this._haRegistryConnection&&(this._haRegistryRelease?.(),this._haRegistryConnection=t,this._haRegistryRev=-1,this._haBindingCacheKey="",this._planHassMemo=null,this._haRegistryRelease=In(this.hass,this._onHaRegistryUpdate),this._onHaRegistryUpdate())}get _haRegistry(){return An(this.hass)}get _planHass(){const t=this._haRegistry,e=En(this.hass,t),i=this._planHassMemo;if(i&&i.hass===this.hass&&i.sig===e)return i.active;const s=On(this.hass,t),n=Nn(this.hass,t);return this._planHassMemo={hass:this.hass,sig:e,active:s,full:n},s}_captureRenderDeviceSnapshot(){if(!this.hass)return;const t=Date.now(),e=[...this._activityRt.entries()].map(([e,i])=>`${e}:${i.gen}:${i.flashTs}:`+(i.flashKind&&(i.expiresAt||i.flashTs+xu)>t?1:0)).join("|"),i=vn(this._virtualLights);if(this._capturedSnapshotSequence===this._hassSequence&&this._capturedSnapshotDevices===this._devices&&this._capturedSnapshotLayout===this._layout&&this._capturedSnapshotConfigEpoch===this._cfgEpoch&&this._capturedSnapshotVirtual===i&&this._capturedSnapshotActivity===e)return;const s=this._planHass,n=new Map,o=new Map,r=new Set(["sun.sun"]);this._vacFit?.source&&r.add(this._vacFit.source);const a=new Set,l=new Set,c=t=>{if(!t)return;const e=t.indexOf(":");if(e<0)return void r.add(t);const i=t.slice(0,e),s=t.slice(e+1);"device"===i?a.add(s):"entity"===i&&r.add(s)};for(const t of this._model)for(const e of t.rooms)e.area&&l.add(e.area),c(e.settings?.temp_source),c(e.settings?.hum_source);for(const t of this._serverCfg?.spaces||[])for(const e of t.openings||[])for(const t of mi(e))r.add(t);for(const t of this._serverCfg?.spaces||[])for(const e of t.decor||[])if("text"===e.kind){for(const t of String(e.text||"").matchAll(/\{([^{}\r\n]+)\}/g)){const e=Yi(t[1]);e?.entity&&r.add(e.entity)}e.entity&&r.add(e.entity),o.set(`decor:${t.id}:${e.id}`,ts(e.text,e,s,t=>!!s.entities?.[t]&&!!s.states?.[t]&&!ko(s,t,wo(this._markers))))}const h=ho(s,this._devices,null,this._virtualLights);for(const t of this._devices){for(const e of[!1,!0])n.set(ru(t.id,e),iu(s,t,{liveStates:!1!==this._config?.live_states,showTemperature:!1!==this._config?.show_temperature,showSignal:e,activityRuntime:this._activityRt.get(t.id),sourceDetails:!1,lightDevices:this._devices,lightSources:h,registryHass:this._fullRegistryHass,reducedMotion:this._reducedMotion}));if(this._isVacDev(t)){const e=this._vacSource(t,s),i=e?jh(s?.states?.[e]?.attributes):null,n=this._vacRt.get(t.id);o.set(`vacuum:${t.id}`,{source:e,telemetry:i,mapId:i?this._vacMapId(t,i,s):null,runtime:n?{trail:n.trail,lastTs:n.lastTs,moving:n.moving,jump:n.jump}:null,server:this._vacSrvTrails[t.id]||null})}}const d=ou({sourceSequence:this._hassSequence,hass:s,devices:this._devices,presentations:n,positions:(p=this._model.length>0,u=this._devices,_=t=>this._livePos(t),p?new Map(u.map(t=>[t.id,_(t)])):new Map),facts:o,entityIds:r,deviceIds:a,areaIds:l});var p,u,_;this._capturedSnapshotSequence=this._hassSequence,this._capturedSnapshotDevices=this._devices,this._capturedSnapshotLayout=this._layout,this._capturedSnapshotActivity=e,this._capturedSnapshotConfigEpoch=this._cfgEpoch,this._capturedSnapshotVirtual=i,this._visibleDeviceSnapshot&&"steady"!==this._continuity.state?this._candidateDeviceSnapshot=d:(this._visibleDeviceSnapshot=d,this._candidateDeviceSnapshot=null)}get _renderDeviceSnapshot(){return this._stagedDeviceSnapshotToken===this._continuity.token?this._candidateDeviceSnapshot||this._visibleDeviceSnapshot:this._visibleDeviceSnapshot||this._candidateDeviceSnapshot}get _renderPlanHass(){return this._renderDeviceSnapshot?.hass||this._planHass}get _renderDevices(){return this._renderDeviceSnapshot?.devices||this._devices}get _fullRegistryHass(){return this._planHass,this._planHassMemo?.full||this.hass}_bindingStatus(t){return Bn(this.hass,t,this._haRegistry)}houseplanDiagnostics(){const t=function(t){const e=An(t);return{access:e.access,authoritative:e.authoritative,revision:e.revision,lastSuccess:e.lastSuccess,error:e.error}}(this.hass),e={active:0,ha_disabled:0,orphaned:0,unverified:0};for(const t of this._markers)t.removed||"virtual"===t.binding||e[this._bindingStatus(t.binding).kind]++;return{registry:{...t,lastSuccessAgeMs:t.lastSuccess?Math.max(0,Date.now()-t.lastSuccess):null},bindings:e}}_openBindingInHa(t){const[e,i]=t.split(":");if(i)if("device"!==e){if("entity"===e){const t=this._fullRegistryHass.entities?.[i];t?.device_id&&vm("/config/devices/device/"+encodeURIComponent(t.device_id))}}else vm("/config/devices/device/"+encodeURIComponent(i))}_bindingHasHaPage(t){const[e,i]=t.split(":");return!!i&&("device"===e||"entity"===e&&!!this._fullRegistryHass.entities?.[i]?.device_id)}_toggleMarkerDialogVisibility(){const t=this._markerDialog;if(!t)return;const e="ha"===t.bindingMode?this._bindingStatus(t.binding):null,i=t.hideFromPlan||"ha_disabled"===e?.kind;i&&"ha_disabled"===e?.kind?this._showToast(this._t("entity"===e.reason?"toast.ha_disabled_show_entity":"toast.ha_disabled_show_device")):i&&"unverified"===e?.kind?this._showToast(this._t("toast.ha_binding_unverified")):this._markerDialog={...t,hideFromPlan:!i}}_hookConnection(){const t=this.hass?.connection;t&&t!==this._connHooked&&(this._connHooked?.removeEventListener?.("ready",this._onConnReady),this._connHooked?.removeEventListener?.("disconnected",this._onConnLost),this._connHooked?.removeEventListener?.("reconnect-error",this._onConnLost),t.addEventListener?.("ready",this._onConnReady),t.addEventListener?.("disconnected",this._onConnLost),t.addEventListener?.("reconnect-error",this._onConnLost),this._connHooked=t)}_display(t){return this._signer.display(this.hass,t)}_resign(){this._signer.resign(this.hass,Is(this._serverCfg))}_onLayoutEvent(t){t<=this._layoutRev||(clearTimeout(this._layoutSyncTimer),this._layoutSyncTimer=window.setTimeout(()=>{t<=this._layoutRev||this._reloadLayoutOnly()},200))}_noteLayoutRev(t){const e=t?.rev;"number"==typeof e&&e>this._layoutRev&&(this._layoutRev=e)}async _reloadLayoutOnly(){if(!this._serverStorage||!this.hass?.callWS)return;this._beginContinuityCandidate("layout-reload",!1);const t=new Map;for(const e of this._dirtyPos)this._layout[e]&&t.set(e,this._layout[e]);this._persistLayout.pending()&&this._persistLayout.flush();for(const[e,i]of this._sentPos)t.set(e,i);try{const e=await this.hass.callWS({type:"houseplan/layout/get"}),i={...e?.layout||{}};for(const[e,s]of t)i[e]=s;const s=Ch(i);s!==(this._layoutContentFingerprint||Ch(this._layout))&&(this._layout=i,this._layoutContentFingerprint=s),this._layoutRev=e?.rev??this._layoutRev,this._canOptimizeUndo=!!e?.can_optimize_undo,this._undoKind=e?.undo_kind||null,this._cacheSnapshot(),this.requestUpdate()}catch{}finally{this._continuityDataReady=!0,this.requestUpdate()}}_maybeRebuildDevices(){const t=this.hass;if(!t?.devices||!t?.entities||!t?.areas)return;const e=this._haRegistry,i=En(t,e)+":"+Object.keys(t.areas).length+":"+(this._norm?"n":"l")+":"+ar(t,this._config?.language);if(i===this._regSignature&&this._devices.length)return;this._regSignature=i;const s=new Map(this._devices.map(t=>[t.id,t.bindingStatus?.kind||"active"]));this._devices=So({hass:t,registry:e,areaToSpace:Object.fromEntries(Object.entries(this._areaToSpace).map(([t,e])=>[t,e.space])),markers:this._markers,settings:this._settings,excluded:this._excluded,showAll:this._showAll,firstSpaceId:this._model[0]?.id||"",loc:t=>this._t(t),iconRules:this._iconRules});const n=this._markers.filter(t=>!t.removed&&"virtual"!==t.binding).map(t=>t.binding).sort(),o=e.revision+":"+n.join("|");if(e.authoritative&&o!==this._haBindingCacheKey){const i=new Map;for(const s of n)i.set(s,Bn(t,s,e));!function(t){if("undefined"==typeof localStorage||!t.size)return;const e=Ln(),i=Date.now();for(const[s,n]of t)"active"===n.kind?e[s]={kind:"active",ts:i}:"ha_disabled"===n.kind&&(e[s]={kind:"ha_disabled",reason:n.reason,ts:i});const s=Object.fromEntries(Object.entries(e).sort((t,e)=>e[1].ts-t[1].ts).slice(0,1500));Mn=s;try{localStorage.setItem(Sn,JSON.stringify(s))}catch{}}(i),this._haBindingCacheKey=o}this._defPos=this._defaultPositions(),this._syncNewDevices(),this._seedHiddenDevices(),this._syncActivityRuntime();const r=new Set(this._devices.filter(t=>!t.hidden).map(t=>t.id));for(const t of this._vacRt.keys())r.has(t)||this._vacRt.delete(t);if(this._infoCard){const t=this._devices.find(t=>t.id===this._infoCard.id);this._infoCard=t&&"ha_disabled"!==t.bindingStatus?.kind?t:null}const a=this._devices.some(t=>"ha_disabled"===t.bindingStatus?.kind&&"ha_disabled"!==s.get(t.id));a&&("ha_disabled"!==this._infoCard?.bindingStatus?.kind&&"ha_disabled"!==this._devices.find(t=>t.id===this._infoCard?.id)?.bindingStatus?.kind||this._closeInfoCard(),this._drag&&"ha_disabled"===this._devices.find(t=>t.id===this._drag.id)?.bindingStatus?.kind&&(this._drag=null),clearTimeout(this._holdTimer),this._holdFired=!1,this._tip=null,this._tapConfirm=null),this._nativeMoreInfoEntity&&!this._planEntityAvailable(this._nativeMoreInfoEntity)&&(fm(this,"hass-more-info",{entityId:null}),this._nativeMoreInfoEntity=null)}_syncNewDevices(){if(!this._norm||!this._loadOk||!this._serverCfg)return;const t=this._devices.filter(t=>!t.marker&&!t.virtual).map(t=>t.id).sort(),e=t.join(",");if(e===this._newSyncKey)return;this._newSyncKey=e;const i=this._settings,{fresh:s,known:n}=function(t,e){if(!Array.isArray(e))return{fresh:[],known:[...t]};const i=new Set(e),s=t.filter(t=>!i.has(t));return{fresh:s,known:s.length?[...e,...s]:e}}(t,i.known_devices);if(!Array.isArray(i.known_devices)||s.length){const t=[...new Set([...i.new_device_ids||[],...s])];this._serverCfg={...this._serverCfg,settings:{...i,known_devices:n,new_device_ids:t}},this._saveConfig()}}get _newIds(){const t=this._settings.new_device_ids;return new Set(Array.isArray(t)?t:[])}_ackNewDevice(t){if(!this._newIds.has(t)||!this._serverCfg)return;const e=this._settings;this._serverCfg={...this._serverCfg,settings:{...e,new_device_ids:(e.new_device_ids||[]).filter(e=>e!==t)}},this._saveConfig(),this.requestUpdate()}get _markers(){return this._serverCfg?.markers||[]}_roomLqi(t){if(!t)return null;const e=[];for(const i of this._renderDevices){if(i.area!==t||i.virtual)continue;const s=_o(this._renderPlanHass,i.entities);null!=s&&e.push(s)}return zi(e)}_roomBounds(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}}_defaultPositions(){const t={},e=this._config?.icon_size??2.5;for(const i of this._model){const s=e/100*Hc(i)*1.3;for(const e of i.rooms){if(!e.area)continue;const n=this._devices.filter(t=>t.area===e.area&&t.space===i.id);if(!n.length)continue;const o=this._roomBounds(e),r=.1*Math.min(o.w,o.h),a=o.w-2*r,l=o.h-2*r,c=Math.max(1,Math.round(Math.sqrt(n.length*a/Math.max(l,1)))),h=Math.ceil(n.length/c),d=a/c,p=l/Math.max(h,1),u=n.map((t,e)=>({x:o.x+r+d*(e%c+.5),y:o.y+r+p*(Math.floor(e/c)+.5)}));Ni(u,o,s,.5*r),n.forEach((e,i)=>t[e.id]=Sc(u[i]))}}return t}_pos(t){const e=this._renderDeviceSnapshot?.positions.get(t.id);return e?{x:e.x,y:e.y}:this._livePos(t)}_livePos(t){const e=this._spaceModelById(t.space),i=this._layout[t.id];if(i)if(this._norm){if(i.s===t.space)return{x:i.x*pm,y:i.y*pm}}else if(void 0===i.s)return{x:i.x,y:i.y};return this._defPos[t.id]?this._defPos[t.id]:e?Sc(Nc(e)):{x:500,y:500}}_savePos(t,e,i){if(this._spaceModelById(t.space)){if(this._norm){const s=this._gridPitch,n=Math.round(e/s)*s,o=Math.round(i/s)*s,r=this._layout[t.id]?.k;this._layout={...this._layout,[t.id]:{s:t.space,x:Cc(n/pm),y:Cc(o/pm),...r?{k:r}:{}}}}else this._layout={...this._layout,[t.id]:{x:Math.round(e),y:Math.round(i)}};this._dirtyPos.add(t.id),this._persistLayout()}}_visualSamples(t){return Jp(this._renderPlanHass,t,this._renderDevices,void 0,this._fullRegistryHass).samples}_devicePresentation(t,e=!1!==this._config?.show_signal,i=!1){const s=i?null:this._renderDeviceSnapshot?.presentations.get(ru(t.id,e));return s||iu(this._renderPlanHass,t,{liveStates:!1!==this._config?.live_states,showTemperature:!1!==this._config?.show_temperature,showSignal:e,designPreview:i,activityRuntime:this._activityRt.get(t.id),sourceDetails:!1,lightDevices:this._renderDevices,registryHass:this._fullRegistryHass,reducedMotion:this._reducedMotion})}_deviceVisual(t){return this._devicePresentation(t).visual}_stateClass(t,e=this._deviceVisual(t)){const i=this._devicePresentation(t);return i.effectiveHidden?"":("icon_ripple"!==i.display||!1===this._config?.live_states||"alarm"===e.status||e.activity,eu({...i,visual:e}).join(" "))}_liveTemp(t){if(!this._config?.show_temperature)return null;if(!0===t.marker?.use_climate_temp){const e=mo(this._renderPlanHass,t.entities);if(null!=e)return e}return"mdi:thermometer"!==t.icon&&"mdi:air-filter"!==t.icon?null:go(this._renderPlanHass,t.entities)}_bindingEntities(t){if("virtual"===t||!t)return[];const e=this._bindingStatus(t);return"active"===e.kind?e.enabledEntityIds:e.allEntityIds}_bindingHasClimate(t){return this._bindingEntities(t).some(t=>t.startsWith("climate."))}_bindingHasAlarm(t){return this._bindingEntities(t).some(t=>{const e=this._planHass?.states?.[t]||this.hass?.states?.[t],i=this._fullRegistryHass.entities[t]||this.hass?.entities?.[t];return Bs(t.split(".")[0],e?.attributes?.device_class||i?.device_class||i?.original_device_class)})}_liveHum(t){return this._config?.show_temperature&&t.primary&&fo(this.hass,t.primary)?vo(this.hass,t.entities):null}_deviceBindingActive(t,e=!0){if(t.virtual||"virtual"===t.bindingKind)return!0;if(!t.bindingKind||!t.bindingRef)return!1;const i=this._bindingStatus(`${t.bindingKind}:${t.bindingRef}`);return"active"===i.kind||(e&&this._showToast(this._t("ha_disabled"===i.kind?"toast.ha_disabled_action":"toast.ha_binding_unverified")),!1)}_openMoreInfo(t){t?this._planEntityAvailable(t)?(this._nativeMoreInfoEntity=t,fm(this,"hass-more-info",{entityId:t})):this._showToast(this._t("toast.ha_disabled_action")):this._showToast(this._t("toast.no_entity"))}_interruptViewGesture(t,e){if(clearTimeout(this._holdTimer),clearTimeout(this._kioskHoldTimer),void 0!==t)for(const i of[e,this._stageEl])try{i?.hasPointerCapture?.(t)&&i.releasePointerCapture(t)}catch{}this._pointers.clear(),this._panStart=null,this._panLock=null,this._pinchStart=null,this._swipeStart=null}_closeInfoCard(){this._interruptViewGesture(),this._holdFired=!1,this._infoCard=null}_ctxDevice(t,e){"view"===this._mode&&(t.preventDefault(),t.stopPropagation(),this._deviceBindingActive(e)&&(e.primary?this._openMoreInfo(e.primary):this._infoCard=e))}_clickDevice(t,e){if(t.stopPropagation(),this._drag?.moved||this._suppressClick||this._holdFired)return;if("plan"===this._mode)return;if("devices"===this._mode)return void this._openMarkerDialog(e);const i=this._devices.find(t=>t.id===e.id);if(!i)return;const s=yd(i.tapAction,i.primary?.split(".")[0]),n=(t,e)=>{i.marker?.tap_confirm?this._tapConfirm={kind:"run",text:t,exec:e}:e()};if("toggle"===s){const t=this._toggleIntent(i);if(!t||!Sd(t))return;const e=t=>{const e=Sd(t);if(!e)return;if("virtual-light"===e.kind)return this._startDevicePressFeedback(i.id),void this.hass.callWS({type:"houseplan/virtual_light/toggle",marker_id:e.markerId}).then(t=>{const e=wn(this._virtualLights,t);e!==this._virtualLights&&(this._virtualLights=e,this._capturedSnapshotVirtual="",this._cacheSnapshot(),this.requestUpdate())}).catch(t=>this._showToast(this._t("toast.virtual_light_toggle_failed",{err:this._errText(t)})));const{command:s}=e;this._startDevicePressFeedback(i.id),this.hass.callService(s.domain,s.service,s.data).catch(t=>this._showToast(this._t("toast.error",{err:this._errText(t)})))},s=((o=t).targets.length?o.targets:o.skippedTargets).map(t=>t.name||t.entityId||t.ref).join(", ")||i.name;if(i.marker?.tap_confirm){const n=this._toggleConfirmationLines(t);if(!n.length)return;this._tapConfirm={kind:"toggle",text:this._t("confirm.tap_toggle",{name:s}),lines:n,initialIntent:t,deviceId:i.id,exec:()=>{const s=this._devices.find(t=>t.id===i.id),n=s?this._toggleIntent(s):null;n&&Md(t,n)?e(n):this._showToast(this._t("toast.tap_target_changed"))}}}else e(t);return}var o;if("info"===s)return this._interruptViewGesture(),void(this._infoCard=i);if(this._deviceBindingActive(i)){if("run"===s){const t=i.marker?.tap_target||"",e=function(t){const e=String(t||"").split(".")[0];return"automation"===e?{domain:"automation",service:"trigger"}:"script"===e?{domain:"script",service:"turn_on"}:"scene"===e?{domain:"scene",service:"turn_on"}:null}(t),s=this.hass.states[t];if(!e||!s)return void this._showToast(this._t("toast.run_target_missing"));const o=s.attributes?.friendly_name||t;return void n(this._t("confirm.tap_run",{name:o}),()=>{this._deviceBindingActive(i)&&this._planEntityAvailable(t)&&(this._startDevicePressFeedback(i.id),this.hass.callService(e.domain,e.service,{entity_id:t}).then(()=>{this._stampActivity(i.id,"event",this._activitySourceKey(i)),this.requestUpdate(),this._showToast(this._t("toast.run_started",{name:o}))}).catch(t=>this._showToast(this._t("toast.error",{err:this._errText(t)}))))})}"more-info"===s&&i.primary?this._openMoreInfo(i.primary):this._infoCard=i}}_keyDevice(t,e){"Enter"!==t.key&&" "!==t.key||"view"!==this._mode&&"devices"!==this._mode||(t.preventDefault(),this._clickDevice(t,e))}_startDevicePressFeedback(t){const e=[...this.renderRoot.querySelectorAll(".dev[data-id]")].find(e=>e.dataset.id===t),i=e?.querySelector(".device-shell");if(!i||"function"!=typeof i.animate)return;const s=Number.parseFloat(this.ownerDocument.defaultView?.getComputedStyle(i).scale||""),n=Number.isFinite(s)?Math.max(.95,Math.min(1,s)):1;this._devicePressAnimations.get(t)?.cancel();const o=this._reducedMotion?[{outlineColor:"transparent",outlineStyle:"solid",outlineWidth:"0px"},{outlineColor:"var(--hp-accent, #3ea6ff)",outlineStyle:"solid",outlineWidth:"2px",outlineOffset:"2px",offset:.5},{outlineColor:"transparent",outlineStyle:"solid",outlineWidth:"0px"}]:[{scale:String(n)},{scale:"0.95",offset:.5},{scale:"1"}],r=i.animate(o,{duration:200,easing:"cubic-bezier(.22,.61,.36,1)"});this._devicePressAnimations.set(t,r);const a=()=>{this._devicePressAnimations.get(t)===r&&this._devicePressAnimations.delete(t)};r.addEventListener("finish",a,{once:!0}),r.addEventListener("cancel",a,{once:!0})}_cancelDevicePressFeedback(){for(const t of this._devicePressAnimations.values())t.cancel();this._devicePressAnimations.clear()}_pruneDevicePressFeedback(){if(!this._devicePressAnimations.size)return;const t=new Set([...this.renderRoot.querySelectorAll(".dev[data-id]")].map(t=>t.dataset.id||""));for(const[e,i]of this._devicePressAnimations)t.has(e)||(i.cancel(),this._devicePressAnimations.delete(e))}_t(t,e){return lr(ar(this.hass,this._config?.language),t,e)}get _colorPickerLabels(){return{title:this._t("color_picker.title"),hue:this._t("color_picker.hue"),saturation:this._t("color_picker.saturation"),value:this._t("color_picker.value"),hex:this._t("color_picker.hex"),invalidHex:this._t("color_picker.invalid_hex")}}_help(t){const e=`${t}.aria`,i=ar(this.hass,this._config?.language);return cr(i,t)&&cr(i,e)?W``:G}get _stageEl(){return this.renderRoot.querySelector(".stage")}_contentItems(t){const e=[];for(const i of this._devices){if(i.space!==t.id||i.hidden)continue;const s=this._pos(i);e.push({minX:s.x,minY:s.y,maxX:s.x,maxY:s.y})}if(t.id===this._space){for(const t of this._openingsR){const i=Number(t.angle)*Math.PI/180,s=Math.cos(i)*t.rlen/2,n=Math.sin(i)*t.rlen/2,o=Pc([[t.rx-s,t.ry-n],[t.rx+s,t.ry+n]]);o&&e.push(o)}const i=this._decorH;for(const t of this._decorList){const s=Pc("line"===t.kind?[[t.x1*pm,t.y1*i],[t.x2*pm,t.y2*i]]:"text"===t.kind?[[t.x*pm,t.y*i]]:ua({x:t.x*pm,y:t.y*i,w:t.w*pm,h:t.h*i,angle:t.angle}));s&&e.push(s)}for(const i of this._physicalBodiesR(t)){const t=Pc(i);t&&e.push(t)}}return Ic(t,e)}_frameOf(){const t=this._spaceModel();if(!t){this._frame=null;const t={x:0,y:0,w:pm,h:pm};return{rect:t,all:t,outliers:0}}const e=this._frame,i="view"!==this._mode;if(e&&e.id===t.id&&this._bdDrag)return e;if(e&&e.id===t.id&&e.model===t&&e.layout===this._layout&&e.devs===this._devices&&e.far===this._showFar&&e.grow===i)return e;const s=zc(this._contentItems(t));let n=s.all||Oc(t),o=this._showFar?n:s.core||Oc(t);return e&&e.id===t.id&&i&&e.grow&&(o=_m(e.rect,o),n=_m(e.all,n)),this._frame={id:t.id,model:t,layout:this._layout,devs:this._devices,far:this._showFar,grow:i,rect:o,all:n,outliers:s.outliers},this._frame}_isoSource(){const t=this._spaceModel();if(!t)return null;const e=this._spaceWalls,i=this._openPairs().flatMap(t=>t.segs),s=this._openingsR.map((t,e)=>({id:String(t.id||e),sourceIndex:e,type:t.type,x:t.rx,y:t.ry,angle:Number(t.angle)||0,length:t.rlen>0?t.rlen:900,flipH:!!t.flip_h,flipV:!!t.flip_v})),n=cc(64,this._cellCm),o=cc(10,this._cellCm),r=`${t.id}|${function(t){let e=2166136261;const i=t=>{if("number"!=typeof t)if("string"!=typeof t)if("boolean"!=typeof t)if(Array.isArray(t)){e=fg(e,t.length);for(const e of t)i(e)}else{if(t&&"object"==typeof t){const e=t;for(const t of Object.keys(e).sort())i(t),i(e[t]);return}e=fg(e,-1)}else e=fg(e,t?1:0);else for(const i of t)e=fg(e,i.codePointAt(0)||0);else e=fg(e,t)};return i(t),e.toString(36)}({rooms:t.rooms,walls:e,openCuts:i,openings:s,partitions:t.partitions,roomDrafts:t.room_drafts,columns:t.wall_columns,cellCm:this._cellCm,gridPitch:this._gridPitch,wallKeyPitch:this._wallKeyPitch,camera:og,wallHeight:n,floorEdgeHeight:o,algorithm:3})}`;return{key:r,build:()=>{const o=Xl(t,this._cellCm,this._gridPitch,2e-4*this._gridPitch,this._partitionOpeningCuts(t)).all,r=this._roomWallOpeningInputs(this._openingsR,t),a=e.length||o.length?Cl(t.rooms,e,i,r,this._wallKeyPitch,this._cellCm,this._gridPitch,pm,o):null;if((e.length||o.length)&&!a)throw new Error("wall boolean geometry failed");const l=a?.paperGeom??Sl(t.rooms,e,i,this._wallKeyPitch,this._cellCm,this._gridPitch,pm);if(!l)throw new Error("floor boolean geometry failed");const c=a?.openingIndex||Rl(t.rooms,e,i,this._wallKeyPitch,this._cellCm,this._gridPitch,pm),h=s.map(t=>{const i=this._openingsR[t.sourceIndex],s="gate"===t.type?!t.flipV:t.flipV,o=i?.partitionHost?Fd(i.partitionHost,s):e.length||"gate"===t.type?El(c,{x:t.x,y:t.y,angle:t.angle,length:t.length,flip_v:s}):{ox:0,oy:0,cm:0,side:-1};return function(t,e=64){if(!(vg([t.x,t.y,t.angle,t.length,t.face.ox,t.face.oy,e])&&t.length>0&&e>0))throw new Error("invalid isometric opening input");const i=t.length/2;let s;if("passage"===t.type)s=[];else if("gate"===t.type){const n=10*t.face.side;s=[bg(t,0,[-i,0],[i,0],n,0,.88*e),bg(t,1,[i,0],[-i,0],-n,0,.88*e)]}else s="window"===t.type?[bg(t,0,[-i,0],[i,0],-90,.27*e,.78*e),bg(t,1,[i,0],[-i,0],90,.27*e,.78*e)]:[bg(t,0,[-i,0],[t.length,0],-90,0,.92*e)];return{id:t.id,sourceIndex:t.sourceIndex,type:t.type,leaves:Object.freeze(s.map(t=>Object.freeze(t)))}}({...t,face:o},n)});return{walls:a?.geom||[],floor:l,openings:Object.freeze(h)}}}}_isoSceneKey(){if(!this._labsIso||"view"!==this._mode)return null;try{return this._isoSource()?.key??null}catch{return`${this._space}|invalid`}}_isoScene(){const t=this._isoSource();if(!t)return null;const e=this._isoGeometryCache.get(t.key);if(e)return{key:t.key,...e};const i=this._frameOf().rect,s=t.build(),n=cc(64,this._cellCm),o=cc(10,this._cellCm),r=function(t){let e=1/0,i=1/0,s=-1/0,n=-1/0;for(const o of t)for(const t of o.leaves){const o=Math.hypot(t.closedVector[0],t.closedVector[1]);e=Math.min(e,t.hinge[0]-o),i=Math.min(i,t.hinge[1]-o),s=Math.max(s,t.hinge[0]+o),n=Math.max(n,t.hinge[1]+o)}return vg([e,i,s,n])?{x:e,y:i,w:s-e,h:n-i}:null}(s.openings),a=hg({rect:r?_m(i,r):i,wallHeight:n,openingHeight:n,floorDepth:o}),l=function(t,e=og,i=64){if(!Number.isFinite(i)||i<0)throw new Error("invalid wall height");const s=[],n=[],o=[];let r=0;for(let a=0;a<(t||[]).length;a++){const l=t[a];for(let t=0;t<(l||[]).length;t++){const c=ug(l[t],t>0);if(!(c.length<3||Math.abs(pg(c))<1e-9)){s.push(_g(c,e,i)),r+=c.length;for(let s=0;st.depth-e.depth||t.polygon-e.polygon||t.ring-e.ring||t.edge-e.edge),{topPath:s.join(" "),sides:n,contactPath:o.join(" "),edgeCount:r}}(s.walls,og,n),c={geometry:l,floor:mg(s.floor,o),openings:s.openings,frame:a};return tm(this._isoGeometryCache,t.key,c,8),{key:t.key,...c}}_effectiveProjection(){if("iso"!==this._desiredProjection||!this._model.length)return"flat";const t=this._isoSceneKey()||`${this._space}|invalid`;if(this._isoFallback.has(t))return"flat";try{const t=this._isoScene();return t?(e="iso",i=t.key,s=this._isoFallback,"iso"===e&&i&&!s.has(i)?"iso":"flat"):"flat"}catch(e){if(!this._isoFallback.has(t)){this._isoFallback.add(t);const i=t.split("|");console.warn(`HOUSEPLAN ISO FALLBACK: #89, space ${this._space}, fingerprint ${i[i.length-1]}, ${e instanceof Error?e.message:"renderer error"}`)}return"flat"}var e,i,s}_scenePoint(t){return"iso"===this._renderProjection?ag(t,0):t}_floorView(t){if("iso"!==this._renderProjection)return t;const e=lg([t.x,t.y]),i=lg([t.x+t.w,t.y+t.h]);return{x:e[0],y:e[1],w:i[0]-e[0],h:i[1]-e[1]}}_baseVb(){if("iso"===this._effectiveProjection()){if(!this._spaceDisplayForRender().showBorders){const t=hg({rect:this._frameOf().rect,wallHeight:cc(64,this._cellCm)});return[t.x,t.y,t.w,t.h]}const t=this._isoScene()?.frame??this._frameOf().rect;return[t.x,t.y,t.w,t.h]}const t=this._frameOf().rect;return[t.x,t.y,t.w,t.h]}get _outliers(){return this._showFar?0:this._frameOf().outliers}_fitFar(){this._showFar=!0,this._frame=null,this._resetZoom()}_fitAll(){this._showFar=!0,this._frame=null,this._resetZoom()}_renderFarHint(){return this._kiosk||"view"!==this._mode||this._booting||!this._outliers?G:W`
+
`}houseplanContinuityTrace(){return[...this._continuityHistory,...this._continuity.trace].slice(-80).map(t=>({...t,...t.stage?{stage:[...t.stage]}:{}}))}getCardSize(){return 12}get _norm(){return!(!this._serverCfg||!this._serverCfg.spaces.length)}_cfgFingerprint(){const t=this._serverCfg?.spaces||[];let e=t.length+":";for(const i of t){e+=(i.id||"")+","+(i.plan_aspect||"")+","+(i.plan_url||"").length+","+(i.plan_x??"")+","+(i.plan_y??"")+","+(i.plan_scale??"")+","+(i.plan_scale_x??"")+","+(i.plan_scale_y??"")+","+(i.plan_angle??"")+","+(i.rooms?.length||0)+","+(i.openings?.length||0)+","+(i.decor?.length||0)+";";for(const t of i.rooms||[]){const i=t.poly?.[0],s=t.poly?.[t.poly.length-1];e+=(t.poly?.length||0)+"."+(t.id||"")+"."+(t.open_to||[]).join("+")+"."+(t.area||"")+"."+JSON.stringify(t.settings||0)+"."+(t.x??"")+","+(t.y??"")+","+(t.w??"")+","+(t.h??"")+","+(i?i[0]+"/"+i[1]:"")+","+(s?s[0]+"/"+s[1]:"")+";"}}return e}get _model(){if(!this._serverCfg)return[];const t=this._cfgEpoch+"|"+this._cfgFingerprint();if(this._modelCache&&this._modelCache.key===t)return this._modelCache.model;const e=this._buildModel();return this._modelCache={key:t,model:e},e}_buildModel(){if(!this._serverCfg)return[];const t=this._renderCfg;return yc(t).map((e,i)=>{const s=t.spaces[i]?.plan_url;return e.bg&&s?{...e,bg:{...e.bg,href:s}}:e})}_spaceModel(){return this._hasFixedFloor?Ih(this._model,this._space):(t=this._model,e=this._space,t.find(t=>t.id===e)??t[0]);var t,e}_spaceModelById(t){return Ih(this._model,t)}_syncEmptySpaceState(){if(!!this._serverCfg&&0===this._serverCfg.spaces.length){if(!this._emptySpaceStateActive){this._emptySpaceStateActive=!0;for(const t of this._pointers.keys())for(const e of this.renderRoot.querySelectorAll("*"))try{e.hasPointerCapture?.(t)&&e.releasePointerCapture(t)}catch{}this._pointers.clear(),this._panStart=null,this._panLock=null,this._pinchStart=null,this._swipeStart=null,this._drag=null,this._rlResize=null,this._vacFit=null,this._compassDrag=!1,this._cancelModeTransition(!1),this._mode="view",this._clearGeometryGesture(),this._geometryHistory.clear(),this._resumeDraftBySpace={},this._tip=null,this._hoverRoom=null,this._openingInfo=null,this._closeInfoCard(),this._markerDialog=null,this._physicalDialog=null,this._backdropDialog=null,this._decorShapeDialog=null,this._decorTextDialog=null,this._roomDialog=!1,"edit"===this._spaceDialog?.mode&&(this._spaceDialog=null),this._editorSecondary.closeForNavigation(),this._saveConfigDebounced.cancel(),this._frame=null,this._planSnapGeometryCache=null,this._decorSnapCache=null,this._commitSpace("",!0)}}else this._emptySpaceStateActive=!1}get _areaToSpace(){const t={};for(const e of this._model)for(const i of e.rooms)i.area&&(t[i.area]={space:e.id,room:i});return t}get _settings(){return this._serverCfg?.settings||{}}get _showAll(){return this._settings.filter_seeded?this._showHidden:!!this._settings.show_all}_toggleShowAll(){if(this._serverCfg){if(this._settings.filter_seeded)return this._showHidden=!this._showHidden,void this.requestUpdate();this._serverCfg={...this._serverCfg,settings:{...this._serverCfg.settings,show_all:!this._settings.show_all}},this._regSignature="",this._maybeRebuildDevices(),this._saveConfig(),this.requestUpdate()}}_seedHiddenDevices(){if(!this._serverCfg||!this._norm||!this._canEdit)return;const t=this._serverCfg,e=function(t){const e=t.hass,i=t.registry||An(e),s=On(e,i),n=Nn(e,i),{areaToSpace:o,markers:a,settings:r,excluded:l,iconRules:c}=t,h=!1!==r.group_lights,d=wo(a),p=yo(s,h).filter(t=>!ko(s,t.eid,d)),u=new Set(p.map(t=>t.area)),_=qn(s),g=Wn(a,n),m=new Set(a.map(t=>t.binding)),f=[];for(const t of Object.values(s.devices)){const n=t.area_id;if(!n||!o[n])continue;if("service"===t.entry_type)continue;if(m.has("device:"+t.id))continue;if("active"!==Bn(e,"device:"+t.id,i).kind)continue;const a=jn(s,t.id,_[t.id]||[],g);if(a.partial&&!a.entityIds.length)continue;const r=a.entityIds,d=Un(s,t,r);let p=l.has(d)||"Group"===t.model||/scene/i.test(t.model||"")||/bridge/i.test((t.model||"")+(t.name||""))||"myheat"===d&&!!t.via_device_id;if(!p&&h&&u.has(n)){const e=(t.name_by_user||t.name||"").trim();"mdi:lightbulb"===bo(s,e,t.model,r,c)&&(p=!0)}p&&f.push("device:"+t.id)}return f}({hass:this.hass,registry:this._haRegistry,areaToSpace:Object.fromEntries(Object.entries(this._areaToSpace).map(([t,e])=>[t,e.space])),markers:this._markers,settings:this._settings,excluded:this._excluded,firstSpaceId:this._model[0]?.id||"",iconRules:this._iconRules});if(!e.length&&t.settings?.filter_seeded)return;t.markers=t.markers||[];const i=[];for(const s of e){const e="h"+s.slice(s.indexOf(":")+1);t.markers.push({id:e,binding:s,hidden:!0}),i.push(s.slice(s.indexOf(":")+1))}const s={...t.settings||{},filter_seeded:!0};delete s.show_all,i.length&&Array.isArray(s.new_device_ids)&&(s.new_device_ids=s.new_device_ids.filter(t=>!i.includes(t))),t.settings=s,this._regSignature="",this._maybeRebuildDevices(),this._saveConfig(),this.requestUpdate()}get _iconRules(){const t=this._settings.icon_rules;if(!t||!Array.isArray(t)||!t.length)return;const e=JSON.stringify(t);return e!==this._rulesCompiledSrc&&(this._rulesCompiledSrc=e,this._rulesCompiled=Jt(t)),this._rulesCompiled}get _fillColors(){return ps(this._settings)}get _excluded(){const t=this._settings.exclude_integrations;return t?new Set(t):Yt}willUpdate(t){t.has("_serverCfg")&&this._cfgEpoch++,this._syncEmptySpaceState(),t.has("hass")&&this.hass&&(this._hassSequence++,this._renderSnapshotAt=Date.now(),this._continuity.note("hass-snapshot"),this._ensureHaRegistryAuthority(),this._planHassMemo=null,this._hookConnection(),!this._loadOk&&!this._loading&&this._loadTries<8&&this._loadFromServer(),this._maybeRebuildDevices(),this._vacTick(),this._activityTick()),this._continuity.hasCompleteFrame&&"steady"===this._continuity.state&&this._continuity.refreshCompleteFrame(this._visualFrameFingerprint()),this._captureRenderDeviceSnapshot()}updated(){this._pruneDevicePressFeedback(),this._syncDayCycleClock(),this._warmSnapshot(),this._dtMeasure();const t=this._stageEl;t&&!this._roViewport&&(this._roViewport=new ResizeObserver(()=>this._refitView()),this._roViewport.observe(t)),t&&this._booting&&!this._bootTimer&&this._bootWatch();const e=this.renderRoot.querySelector(".hdr");if(e&&t&&!this._roHdr){const i=()=>{const e=this.renderRoot.querySelector("ha-card");if(!e)return;const i=t.getBoundingClientRect().top-e.getBoundingClientRect().top,s=Math.min(Math.max(e.getBoundingClientRect().top,0),120),n=Math.round(i+s);n>=0&&n!==this._hdrH&&(this._hdrH=n),n>=0&&!this._booting&&!this._config?.kiosk&&t.clientHeight>0&&this._warmPatch({hdrH:n,stageH:t.clientHeight})};this._roHdr=new ResizeObserver(()=>requestAnimationFrame(i)),this._roHdr.observe(e),this._onWinResize=()=>requestAnimationFrame(i),window.addEventListener("resize",this._onWinResize),i()}if(t&&!this._view&&this._refitView(),this._editorSecondary.afterRender(),this._settleContinuityFrame(),this._serverStorage&&this._loadOk&&0===this._model.length&&!this._spaceDialog&&!this._importDialog&&!this._onboardingShown){this._onboardingShown=!0;const t=function(t){const e=t?.floors;if(!e||"object"!=typeof e)return[];const i=[];for(const t of Object.values(e))t&&t.floor_id&&i.push({id:t.floor_id,name:t.name||t.floor_id,level:t.level??null});return i.sort((t,e)=>{const i=t.level??1e9,s=e.level??1e9;return i!==s?i-s:t.name.localeCompare(e.name)}),i}(this.hass);t.length?this._importDialog={floors:t.map(t=>({...t,checked:!0}))}:this._openSpaceDialog("create")}}_adoptStructuralResponses(t,e,i){const s=t?.config,n=s&&Array.isArray(s.spaces)?s:null,o=Dh(n),a=o!==(this._cfgContentFingerprint||Dh(this._serverCfg));if(a&&(this._geometryHistory.clear(),this._serverCfg&&this._clearGeometryGesture(),this._serverCfg=n,this._cfgContentFingerprint=o),this._cfgRev=t?.rev??this._cfgRev,t&&("virtual_lights"in t||"config"in t)){const e=mn(this._virtualLights,t.virtual_lights,this._cfgRev,"virtual_lights"in t);vn(e)!==vn(this._virtualLights)&&(this._virtualLights=e,this._capturedSnapshotVirtual="")}let r=!1;if(void 0!==e||void 0!==i){const t=i??e?.layout??{},s=Dh(t);r=s!==(this._layoutContentFingerprint||Dh(this._layout)),r&&(this._layout=t,this._layoutContentFingerprint=s),this._layoutRev=e?.rev??this._layoutRev}return this._canOptimizeUndo=!(!t?.can_optimize_undo&&!e?.can_optimize_undo),this._undoKind=t?.undo_kind||e?.undo_kind||null,"boolean"==typeof t?.can_write&&(this._serverCanWrite=t.can_write),a&&this._continuity.note("config-candidate",{configRev:this._cfgRev}),r&&this._continuity.note("layout-candidate",{layoutRev:this._layoutRev}),{configChanged:a,layoutChanged:r}}_resumePendingNavMode(){if(!this._pendingNavMode||!this._canEdit||this._config?.kiosk)return!1;const t=this._pendingNavMode;return this._pendingNavMode=null,this._setMode(t,!1),!0}async _loadFromServer(){this._loading=!0,this._loadTries++;const t=this._space,e=!!this._view;try{const[i,s]=await Promise.all([this.hass.callWS({type:"houseplan/config/get"}),this.hass.callWS({type:"houseplan/layout/get"})]),n=i?.config&&Array.isArray(i.config.spaces)?i.config:null,o=Dh(n)!==(this._cfgContentFingerprint||Dh(this._serverCfg))||Dh(s?.layout??{})!==(this._layoutContentFingerprint||Dh(this._layout));if(o){if(!await this._signer.prepareImage(this.hass,this._candidateBackdrop(n)))return this._continuity.note("asset-failed"),void this._scheduleLoadRetry(!0)}o&&this._continuity.hasCompleteFrame&&"steady"===this._continuity.state&&this._beginContinuityCandidate("structural-response",!0),this._connectionWasLost=!1,this._serverStorage=!0,"boolean"==typeof i?.can_write&&(this._serverCanWrite=i.can_write),this._canOptimizeUndo=!(!i?.can_optimize_undo&&!s?.can_optimize_undo),this._adoptStructuralResponses(i,s),this._adoptInitialSpace(this._model,!0),this._resumePendingNavMode(),this._cacheSnapshot(),this._warmVpArmed&&this._space===this._warmVp?.space?this._warmVpArmed=!1:e&&this._space===t||this._restoreZoom(),this._loadOk=!0,this.hass.callWS({type:"houseplan/trail/get"}).then(t=>{this._vacSrvTrails=t?.trails||{},this.requestUpdate()}).catch(()=>{}),this._ensureLiveSyncSubscriptions()}catch(t){if(this._serverCfg)this._scheduleLoadRetry(!0);else if(this._loadTries>=8){this._serverStorage=!1;try{this._layout=JSON.parse(localStorage.getItem(am)||"{}")||{}}catch{this._layout={}}}}finally{this._loading=!1,this._continuityDataReady=!0,this._regSignature="",this._maybeRebuildDevices(),this.requestUpdate()}}_ensureLiveSyncSubscriptions(){const t=this.hass?.connection;if(!t)return;if(t!==this._liveSyncConnection&&(this._unsubCfg?.(),this._unsubCfg=null,this._unsubLayout?.(),this._unsubLayout=null,this._unsubTrail?.(),this._unsubTrail=void 0,this._unsubVirtual?.(),this._unsubVirtual=null,this._liveSyncGeneration++,this._liveSyncAttempt=null,this._liveSyncConnection=t),this._liveSyncAttempt)return;const e=this._liveSyncGeneration,i=[],s=(s,n,o,a)=>{s()||i.push(async()=>{const i=await t.subscribeEvents(a,o);e===this._liveSyncGeneration&&this.isConnected&&this.hass?.connection===t&&!s()?n(i):i?.()})};if(s(()=>this._unsubCfg,t=>{this._unsubCfg=t},"houseplan_config_updated",t=>{const e=Number(t?.data?.rev??-1);e!==this._cfgRev&&this._reloadConfigOnly(!1,e)}),s(()=>this._unsubTrail,t=>{this._unsubTrail=t},"houseplan_trail_updated",async()=>{try{const t=await this.hass.callWS({type:"houseplan/trail/get"});this._vacSrvTrails=t?.trails||{},this.requestUpdate()}catch{}}),s(()=>this._unsubLayout,t=>{this._unsubLayout=t},"houseplan_layout_updated",t=>this._onLayoutEvent(Number(t?.data?.rev??-1))),s(()=>this._unsubVirtual,t=>{this._unsubVirtual=t},"houseplan_virtual_light_updated",t=>{const e=wn(this._virtualLights,t?.data);e!==this._virtualLights&&(this._virtualLights=e,this._capturedSnapshotVirtual="",this._cacheSnapshot(),this.requestUpdate())}),!i.length)return;const n=function(t){return Promise.allSettled(t.map(t=>Promise.resolve().then(t)))}(i).then(()=>{});this._liveSyncAttempt=n,n.finally(()=>{this._liveSyncAttempt===n&&(this._liveSyncAttempt=null)})}async _reloadConfigOnly(t=!1,e){if(!t){if(void 0!==e&&e<=this._cfgRev)return;if(this._saveConfigDebounced.pending()&&this._saveConfigDebounced.flush(),this._cfgWriting)return clearTimeout(this._reloadRetry),void(this._reloadRetry=window.setTimeout(()=>this._reloadConfigOnly(!1,e),400))}this._beginContinuityCandidate("config-reload",!1);try{const t=await this.hass.callWS({type:"houseplan/config/get"}),e=t?.config&&Array.isArray(t.config.spaces)?t.config:null;if(Dh(e)!==(this._cfgContentFingerprint||Dh(this._serverCfg))&&!await this._signer.prepareImage(this.hass,this._candidateBackdrop(e)))return this._continuity.note("asset-failed"),void this._scheduleLoadRetry(!0);const i=this._space;this._adoptStructuralResponses(t),this._adoptInitialSpace(this._model,!0),this._resumePendingNavMode(),this._cacheSnapshot(),this._space!==i&&this._restoreZoom(),this._regSignature="",this._maybeRebuildDevices(),this.requestUpdate()}catch(t){this._showToast(this._t("toast.cfg_reload_failed",{err:this._errText(t)}))}finally{this._continuityDataReady=!0,this.requestUpdate()}}_scheduleLoadRetry(t=!1){if(void 0!==this._loadRetryTimer)return;const e=Math.min(8e3,500*2**Math.min(4,Math.max(1,this._loadTries-7)));this._loadRetryTimer=window.setTimeout(()=>{this._loadRetryTimer=void 0,!t&&this._loadOk||this._loading||!this.hass||this._loadFromServer()},e)}_ensureHaRegistryAuthority(){const t=this.hass?.connection||null;t&&t!==this._haRegistryConnection&&(this._haRegistryRelease?.(),this._haRegistryConnection=t,this._haRegistryRev=-1,this._haBindingCacheKey="",this._planHassMemo=null,this._haRegistryRelease=In(this.hass,this._onHaRegistryUpdate),this._onHaRegistryUpdate())}get _haRegistry(){return An(this.hass)}get _planHass(){const t=this._haRegistry,e=En(this.hass,t),i=this._planHassMemo;if(i&&i.hass===this.hass&&i.sig===e)return i.active;const s=On(this.hass,t),n=Nn(this.hass,t);return this._planHassMemo={hass:this.hass,sig:e,active:s,full:n},s}_captureRenderDeviceSnapshot(){if(!this.hass)return;const t=Date.now(),e=[...this._activityRt.entries()].map(([e,i])=>`${e}:${i.gen}:${i.flashTs}:`+(i.flashKind&&(i.expiresAt||i.flashTs+$u)>t?1:0)).join("|"),i=vn(this._virtualLights);if(this._capturedSnapshotSequence===this._hassSequence&&this._capturedSnapshotDevices===this._devices&&this._capturedSnapshotLayout===this._layout&&this._capturedSnapshotConfigEpoch===this._cfgEpoch&&this._capturedSnapshotVirtual===i&&this._capturedSnapshotActivity===e)return;const s=this._planHass,n=new Map,o=new Map,a=new Set(["sun.sun"]);this._vacFit?.source&&a.add(this._vacFit.source);const r=new Set,l=new Set,c=t=>{if(!t)return;const e=t.indexOf(":");if(e<0)return void a.add(t);const i=t.slice(0,e),s=t.slice(e+1);"device"===i?r.add(s):"entity"===i&&a.add(s)};for(const t of this._model)for(const e of t.rooms)e.area&&l.add(e.area),c(e.settings?.temp_source),c(e.settings?.hum_source);for(const t of this._serverCfg?.spaces||[])for(const e of t.openings||[])for(const t of mi(e))a.add(t);for(const t of this._serverCfg?.spaces||[])for(const e of t.decor||[])if("text"===e.kind){for(const t of String(e.text||"").matchAll(/\{([^{}\r\n]+)\}/g)){const e=Yi(t[1]);e?.entity&&a.add(e.entity)}e.entity&&a.add(e.entity),o.set(`decor:${t.id}:${e.id}`,ts(e.text,e,s,t=>!!s.entities?.[t]&&!!s.states?.[t]&&!ko(s,t,wo(this._markers))))}const h=ho(s,this._devices,null,this._virtualLights);for(const t of this._devices){for(const e of[!1,!0])n.set(ru(t.id,e),su(s,t,{liveStates:!1!==this._config?.live_states,showTemperature:!1!==this._config?.show_temperature,showSignal:e,activityRuntime:this._activityRt.get(t.id),sourceDetails:!1,lightDevices:this._devices,lightSources:h,registryHass:this._fullRegistryHass,reducedMotion:this._reducedMotion}));if(this._isVacDev(t)){const e=this._vacSource(t,s),i=e?Uh(s?.states?.[e]?.attributes):null,n=this._vacRt.get(t.id);o.set(`vacuum:${t.id}`,{source:e,telemetry:i,mapId:i?this._vacMapId(t,i,s):null,runtime:n?{trail:n.trail,lastTs:n.lastTs,moving:n.moving,jump:n.jump}:null,server:this._vacSrvTrails[t.id]||null})}}const d=au({sourceSequence:this._hassSequence,hass:s,devices:this._devices,presentations:n,positions:(p=this._model.length>0,u=this._devices,_=t=>this._livePos(t),p?new Map(u.map(t=>[t.id,_(t)])):new Map),facts:o,entityIds:a,deviceIds:r,areaIds:l});var p,u,_;this._capturedSnapshotSequence=this._hassSequence,this._capturedSnapshotDevices=this._devices,this._capturedSnapshotLayout=this._layout,this._capturedSnapshotActivity=e,this._capturedSnapshotConfigEpoch=this._cfgEpoch,this._capturedSnapshotVirtual=i,this._visibleDeviceSnapshot&&"steady"!==this._continuity.state?this._candidateDeviceSnapshot=d:(this._visibleDeviceSnapshot=d,this._candidateDeviceSnapshot=null)}get _renderDeviceSnapshot(){return this._stagedDeviceSnapshotToken===this._continuity.token?this._candidateDeviceSnapshot||this._visibleDeviceSnapshot:this._visibleDeviceSnapshot||this._candidateDeviceSnapshot}get _renderPlanHass(){return this._renderDeviceSnapshot?.hass||this._planHass}get _renderDevices(){return this._renderDeviceSnapshot?.devices||this._devices}get _fullRegistryHass(){return this._planHass,this._planHassMemo?.full||this.hass}_bindingStatus(t){return Bn(this.hass,t,this._haRegistry)}houseplanDiagnostics(){const t=function(t){const e=An(t);return{access:e.access,authoritative:e.authoritative,revision:e.revision,lastSuccess:e.lastSuccess,error:e.error}}(this.hass),e={active:0,ha_disabled:0,orphaned:0,unverified:0};for(const t of this._markers)t.removed||"virtual"===t.binding||e[this._bindingStatus(t.binding).kind]++;return{registry:{...t,lastSuccessAgeMs:t.lastSuccess?Math.max(0,Date.now()-t.lastSuccess):null},bindings:e}}_openBindingInHa(t){const[e,i]=t.split(":");if(i)if("device"!==e){if("entity"===e){const t=this._fullRegistryHass.entities?.[i];t?.device_id&&ym("/config/devices/device/"+encodeURIComponent(t.device_id))}}else ym("/config/devices/device/"+encodeURIComponent(i))}_bindingHasHaPage(t){const[e,i]=t.split(":");return!!i&&("device"===e||"entity"===e&&!!this._fullRegistryHass.entities?.[i]?.device_id)}_toggleMarkerDialogVisibility(){const t=this._markerDialog;if(!t)return;const e="ha"===t.bindingMode?this._bindingStatus(t.binding):null,i=t.hideFromPlan||"ha_disabled"===e?.kind;i&&"ha_disabled"===e?.kind?this._showToast(this._t("entity"===e.reason?"toast.ha_disabled_show_entity":"toast.ha_disabled_show_device")):i&&"unverified"===e?.kind?this._showToast(this._t("toast.ha_binding_unverified")):this._markerDialog={...t,hideFromPlan:!i}}_hookConnection(){const t=this.hass?.connection;t&&t!==this._connHooked&&(this._connHooked?.removeEventListener?.("ready",this._onConnReady),this._connHooked?.removeEventListener?.("disconnected",this._onConnLost),this._connHooked?.removeEventListener?.("reconnect-error",this._onConnLost),t.addEventListener?.("ready",this._onConnReady),t.addEventListener?.("disconnected",this._onConnLost),t.addEventListener?.("reconnect-error",this._onConnLost),this._connHooked=t)}_display(t){return this._signer.display(this.hass,t)}_resign(){this._signer.resign(this.hass,Is(this._serverCfg))}_onLayoutEvent(t){t<=this._layoutRev||(clearTimeout(this._layoutSyncTimer),this._layoutSyncTimer=window.setTimeout(()=>{t<=this._layoutRev||this._reloadLayoutOnly()},200))}_noteLayoutRev(t){const e=t?.rev;"number"==typeof e&&e>this._layoutRev&&(this._layoutRev=e)}async _reloadLayoutOnly(){if(!this._serverStorage||!this.hass?.callWS)return;this._beginContinuityCandidate("layout-reload",!1);const t=new Map;for(const e of this._dirtyPos)this._layout[e]&&t.set(e,this._layout[e]);this._persistLayout.pending()&&this._persistLayout.flush();for(const[e,i]of this._sentPos)t.set(e,i);try{const e=await this.hass.callWS({type:"houseplan/layout/get"}),i={...e?.layout||{}};for(const[e,s]of t)i[e]=s;const s=Dh(i);s!==(this._layoutContentFingerprint||Dh(this._layout))&&(this._layout=i,this._layoutContentFingerprint=s),this._layoutRev=e?.rev??this._layoutRev,this._canOptimizeUndo=!!e?.can_optimize_undo,this._undoKind=e?.undo_kind||null,this._cacheSnapshot(),this.requestUpdate()}catch{}finally{this._continuityDataReady=!0,this.requestUpdate()}}_maybeRebuildDevices(){const t=this.hass;if(!t?.devices||!t?.entities||!t?.areas)return;const e=this._haRegistry,i=En(t,e)+":"+Object.keys(t.areas).length+":"+(this._norm?"n":"l")+":"+ra(t,this._config?.language);if(i===this._regSignature&&this._devices.length)return;this._regSignature=i;const s=new Map(this._devices.map(t=>[t.id,t.bindingStatus?.kind||"active"]));this._devices=So({hass:t,registry:e,areaToSpace:Object.fromEntries(Object.entries(this._areaToSpace).map(([t,e])=>[t,e.space])),markers:this._markers,settings:this._settings,excluded:this._excluded,showAll:this._showAll,firstSpaceId:this._model[0]?.id||"",loc:t=>this._t(t),iconRules:this._iconRules});const n=this._markers.filter(t=>!t.removed&&"virtual"!==t.binding).map(t=>t.binding).sort(),o=e.revision+":"+n.join("|");if(e.authoritative&&o!==this._haBindingCacheKey){const i=new Map;for(const s of n)i.set(s,Bn(t,s,e));!function(t){if("undefined"==typeof localStorage||!t.size)return;const e=Ln(),i=Date.now();for(const[s,n]of t)"active"===n.kind?e[s]={kind:"active",ts:i}:"ha_disabled"===n.kind&&(e[s]={kind:"ha_disabled",reason:n.reason,ts:i});const s=Object.fromEntries(Object.entries(e).sort((t,e)=>e[1].ts-t[1].ts).slice(0,1500));Mn=s;try{localStorage.setItem(Sn,JSON.stringify(s))}catch{}}(i),this._haBindingCacheKey=o}this._defPos=this._defaultPositions(),this._syncNewDevices(),this._seedHiddenDevices(),this._syncActivityRuntime();const a=new Set(this._devices.filter(t=>!t.hidden).map(t=>t.id));for(const t of this._vacRt.keys())a.has(t)||this._vacRt.delete(t);if(this._infoCard){const t=this._devices.find(t=>t.id===this._infoCard.id);this._infoCard=t&&"ha_disabled"!==t.bindingStatus?.kind?t:null}const r=this._devices.some(t=>"ha_disabled"===t.bindingStatus?.kind&&"ha_disabled"!==s.get(t.id));r&&("ha_disabled"!==this._infoCard?.bindingStatus?.kind&&"ha_disabled"!==this._devices.find(t=>t.id===this._infoCard?.id)?.bindingStatus?.kind||this._closeInfoCard(),this._drag&&"ha_disabled"===this._devices.find(t=>t.id===this._drag.id)?.bindingStatus?.kind&&(this._drag=null),clearTimeout(this._holdTimer),this._holdFired=!1,this._tip=null,this._tapConfirm=null),this._nativeMoreInfoEntity&&!this._planEntityAvailable(this._nativeMoreInfoEntity)&&(vm(this,"hass-more-info",{entityId:null}),this._nativeMoreInfoEntity=null)}_syncNewDevices(){if(!this._norm||!this._loadOk||!this._serverCfg)return;const t=this._devices.filter(t=>!t.marker&&!t.virtual).map(t=>t.id).sort(),e=t.join(",");if(e===this._newSyncKey)return;this._newSyncKey=e;const i=this._settings,{fresh:s,known:n}=function(t,e){if(!Array.isArray(e))return{fresh:[],known:[...t]};const i=new Set(e),s=t.filter(t=>!i.has(t));return{fresh:s,known:s.length?[...e,...s]:e}}(t,i.known_devices);if(!Array.isArray(i.known_devices)||s.length){const t=[...new Set([...i.new_device_ids||[],...s])];this._serverCfg={...this._serverCfg,settings:{...i,known_devices:n,new_device_ids:t}},this._saveConfig()}}get _newIds(){const t=this._settings.new_device_ids;return new Set(Array.isArray(t)?t:[])}_ackNewDevice(t){if(!this._newIds.has(t)||!this._serverCfg)return;const e=this._settings;this._serverCfg={...this._serverCfg,settings:{...e,new_device_ids:(e.new_device_ids||[]).filter(e=>e!==t)}},this._saveConfig(),this.requestUpdate()}get _markers(){return this._serverCfg?.markers||[]}_roomLqi(t){if(!t)return null;const e=[];for(const i of this._renderDevices){if(i.area!==t||i.virtual)continue;const s=_o(this._renderPlanHass,i.entities);null!=s&&e.push(s)}return zi(e)}_roomBounds(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}}_defaultPositions(){const t={},e=this._config?.icon_size??2.5;for(const i of this._model){const s=e/100*Lc(i)*1.3;for(const e of i.rooms){if(!e.area)continue;const n=this._devices.filter(t=>t.area===e.area&&t.space===i.id);if(!n.length)continue;const o=this._roomBounds(e),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(n.length*r/Math.max(l,1)))),h=Math.ceil(n.length/c),d=r/c,p=l/Math.max(h,1),u=n.map((t,e)=>({x:o.x+a+d*(e%c+.5),y:o.y+a+p*(Math.floor(e/c)+.5)}));Ni(u,o,s,.5*a),n.forEach((e,i)=>t[e.id]=Mc(u[i]))}}return t}_pos(t){const e=this._renderDeviceSnapshot?.positions.get(t.id);return e?{x:e.x,y:e.y}:this._livePos(t)}_livePos(t){const e=this._spaceModelById(t.space),i=this._layout[t.id];if(i)if(this._norm){if(i.s===t.space)return{x:i.x*um,y:i.y*um}}else if(void 0===i.s)return{x:i.x,y:i.y};return this._defPos[t.id]?this._defPos[t.id]:e?Mc(Hc(e)):{x:500,y:500}}_savePos(t,e,i){if(this._spaceModelById(t.space)){if(this._norm){const s=this._gridPitch,n=Math.round(e/s)*s,o=Math.round(i/s)*s,a=this._layout[t.id]?.k;this._layout={...this._layout,[t.id]:{s:t.space,x:Dc(n/um),y:Dc(o/um),...a?{k:a}:{}}}}else this._layout={...this._layout,[t.id]:{x:Math.round(e),y:Math.round(i)}};this._dirtyPos.add(t.id),this._persistLayout()}}_visualSamples(t){return Zp(this._renderPlanHass,t,this._renderDevices,void 0,this._fullRegistryHass).samples}_devicePresentation(t,e=!1!==this._config?.show_signal,i=!1){const s=i?null:this._renderDeviceSnapshot?.presentations.get(ru(t.id,e));return s||su(this._renderPlanHass,t,{liveStates:!1!==this._config?.live_states,showTemperature:!1!==this._config?.show_temperature,showSignal:e,designPreview:i,activityRuntime:this._activityRt.get(t.id),sourceDetails:!1,lightDevices:this._renderDevices,registryHass:this._fullRegistryHass,reducedMotion:this._reducedMotion})}_deviceVisual(t){return this._devicePresentation(t).visual}_stateClass(t,e=this._deviceVisual(t)){const i=this._devicePresentation(t);return i.effectiveHidden?"":("icon_ripple"!==i.display||!1===this._config?.live_states||"alarm"===e.status||e.activity,iu({...i,visual:e}).join(" "))}_liveTemp(t){if(!this._config?.show_temperature)return null;if(!0===t.marker?.use_climate_temp){const e=mo(this._renderPlanHass,t.entities);if(null!=e)return e}return"mdi:thermometer"!==t.icon&&"mdi:air-filter"!==t.icon?null:go(this._renderPlanHass,t.entities)}_bindingEntities(t){if("virtual"===t||!t)return[];const e=this._bindingStatus(t);return"active"===e.kind?e.enabledEntityIds:e.allEntityIds}_bindingHasClimate(t){return this._bindingEntities(t).some(t=>t.startsWith("climate."))}_bindingHasAlarm(t){return this._bindingEntities(t).some(t=>{const e=this._planHass?.states?.[t]||this.hass?.states?.[t],i=this._fullRegistryHass.entities[t]||this.hass?.entities?.[t];return Bs(t.split(".")[0],e?.attributes?.device_class||i?.device_class||i?.original_device_class)})}_liveHum(t){return this._config?.show_temperature&&t.primary&&fo(this.hass,t.primary)?vo(this.hass,t.entities):null}_deviceBindingActive(t,e=!0){if(t.virtual||"virtual"===t.bindingKind)return!0;if(!t.bindingKind||!t.bindingRef)return!1;const i=this._bindingStatus(`${t.bindingKind}:${t.bindingRef}`);return"active"===i.kind||(e&&this._showToast(this._t("ha_disabled"===i.kind?"toast.ha_disabled_action":"toast.ha_binding_unverified")),!1)}_openMoreInfo(t){t?this._planEntityAvailable(t)?(this._nativeMoreInfoEntity=t,vm(this,"hass-more-info",{entityId:t})):this._showToast(this._t("toast.ha_disabled_action")):this._showToast(this._t("toast.no_entity"))}_interruptViewGesture(t,e){if(clearTimeout(this._holdTimer),clearTimeout(this._kioskHoldTimer),void 0!==t)for(const i of[e,this._stageEl])try{i?.hasPointerCapture?.(t)&&i.releasePointerCapture(t)}catch{}this._pointers.clear(),this._panStart=null,this._panLock=null,this._pinchStart=null,this._swipeStart=null}_closeInfoCard(){this._interruptViewGesture(),this._holdFired=!1,this._infoCard=null}_ctxDevice(t,e){"view"===this._mode&&(t.preventDefault(),t.stopPropagation(),this._deviceBindingActive(e)&&(e.primary?this._openMoreInfo(e.primary):this._infoCard=e))}_clickDevice(t,e){if(t.stopPropagation(),this._drag?.moved||this._suppressClick||this._holdFired)return;if("plan"===this._mode)return;if("devices"===this._mode)return void this._openMarkerDialog(e);const i=this._devices.find(t=>t.id===e.id);if(!i)return;const s=bd(i.tapAction,i.primary?.split(".")[0]),n=(t,e)=>{i.marker?.tap_confirm?this._tapConfirm={kind:"run",text:t,exec:e}:e()};if("toggle"===s){const t=this._toggleIntent(i);if(!t||!Md(t))return;const e=t=>{const e=Md(t);if(!e)return;if("virtual-light"===e.kind)return this._startDevicePressFeedback(i.id),void this.hass.callWS({type:"houseplan/virtual_light/toggle",marker_id:e.markerId}).then(t=>{const e=wn(this._virtualLights,t);e!==this._virtualLights&&(this._virtualLights=e,this._capturedSnapshotVirtual="",this._cacheSnapshot(),this.requestUpdate())}).catch(t=>this._showToast(this._t("toast.virtual_light_toggle_failed",{err:this._errText(t)})));const{command:s}=e;this._startDevicePressFeedback(i.id),this.hass.callService(s.domain,s.service,s.data).catch(t=>this._showToast(this._t("toast.error",{err:this._errText(t)})))},s=((o=t).targets.length?o.targets:o.skippedTargets).map(t=>t.name||t.entityId||t.ref).join(", ")||i.name;if(i.marker?.tap_confirm){const n=this._toggleConfirmationLines(t);if(!n.length)return;this._tapConfirm={kind:"toggle",text:this._t("confirm.tap_toggle",{name:s}),lines:n,initialIntent:t,deviceId:i.id,exec:()=>{const s=this._devices.find(t=>t.id===i.id),n=s?this._toggleIntent(s):null;n&&Cd(t,n)?e(n):this._showToast(this._t("toast.tap_target_changed"))}}}else e(t);return}var o;if("info"===s)return this._interruptViewGesture(),void(this._infoCard=i);if(this._deviceBindingActive(i)){if("run"===s){const t=i.marker?.tap_target||"",e=function(t){const e=String(t||"").split(".")[0];return"automation"===e?{domain:"automation",service:"trigger"}:"script"===e?{domain:"script",service:"turn_on"}:"scene"===e?{domain:"scene",service:"turn_on"}:null}(t),s=this.hass.states[t];if(!e||!s)return void this._showToast(this._t("toast.run_target_missing"));const o=s.attributes?.friendly_name||t;return void n(this._t("confirm.tap_run",{name:o}),()=>{this._deviceBindingActive(i)&&this._planEntityAvailable(t)&&(this._startDevicePressFeedback(i.id),this.hass.callService(e.domain,e.service,{entity_id:t}).then(()=>{this._stampActivity(i.id,"event",this._activitySourceKey(i)),this.requestUpdate(),this._showToast(this._t("toast.run_started",{name:o}))}).catch(t=>this._showToast(this._t("toast.error",{err:this._errText(t)}))))})}"more-info"===s&&i.primary?this._openMoreInfo(i.primary):this._infoCard=i}}_keyDevice(t,e){"Enter"!==t.key&&" "!==t.key||"view"!==this._mode&&"devices"!==this._mode||(t.preventDefault(),this._clickDevice(t,e))}_startDevicePressFeedback(t){const e=[...this.renderRoot.querySelectorAll(".dev[data-id]")].find(e=>e.dataset.id===t),i=e?.querySelector(".device-shell");if(!i||"function"!=typeof i.animate)return;const s=Number.parseFloat(this.ownerDocument.defaultView?.getComputedStyle(i).scale||""),n=Number.isFinite(s)?Math.max(.95,Math.min(1,s)):1;this._devicePressAnimations.get(t)?.cancel();const o=this._reducedMotion?[{outlineColor:"transparent",outlineStyle:"solid",outlineWidth:"0px"},{outlineColor:"var(--hp-accent, #3ea6ff)",outlineStyle:"solid",outlineWidth:"2px",outlineOffset:"2px",offset:.5},{outlineColor:"transparent",outlineStyle:"solid",outlineWidth:"0px"}]:[{scale:String(n)},{scale:"0.95",offset:.5},{scale:"1"}],a=i.animate(o,{duration:200,easing:"cubic-bezier(.22,.61,.36,1)"});this._devicePressAnimations.set(t,a);const r=()=>{this._devicePressAnimations.get(t)===a&&this._devicePressAnimations.delete(t)};a.addEventListener("finish",r,{once:!0}),a.addEventListener("cancel",r,{once:!0})}_cancelDevicePressFeedback(){for(const t of this._devicePressAnimations.values())t.cancel();this._devicePressAnimations.clear()}_pruneDevicePressFeedback(){if(!this._devicePressAnimations.size)return;const t=new Set([...this.renderRoot.querySelectorAll(".dev[data-id]")].map(t=>t.dataset.id||""));for(const[e,i]of this._devicePressAnimations)t.has(e)||(i.cancel(),this._devicePressAnimations.delete(e))}_t(t,e){return la(ra(this.hass,this._config?.language),t,e)}get _colorPickerLabels(){return{title:this._t("color_picker.title"),hue:this._t("color_picker.hue"),saturation:this._t("color_picker.saturation"),value:this._t("color_picker.value"),hex:this._t("color_picker.hex"),invalidHex:this._t("color_picker.invalid_hex")}}_help(t){const e=`${t}.aria`,i=ra(this.hass,this._config?.language);return ca(i,t)&&ca(i,e)?W``:G}get _stageEl(){return this.renderRoot.querySelector(".stage")}_contentItems(t){const e=[];for(const i of this._devices){if(i.space!==t.id||i.hidden)continue;const s=this._pos(i);e.push({minX:s.x,minY:s.y,maxX:s.x,maxY:s.y})}if(t.id===this._space){for(const t of this._openingsR){const i=Number(t.angle)*Math.PI/180,s=Math.cos(i)*t.rlen/2,n=Math.sin(i)*t.rlen/2,o=Rc([[t.rx-s,t.ry-n],[t.rx+s,t.ry+n]]);o&&e.push(o)}const i=this._decorH;for(const t of this._decorList){const s=Rc("line"===t.kind?[[t.x1*um,t.y1*i],[t.x2*um,t.y2*i]]:"text"===t.kind?[[t.x*um,t.y*i]]:ur({x:t.x*um,y:t.y*i,w:t.w*um,h:t.h*i,angle:t.angle}));s&&e.push(s)}for(const i of this._physicalBodiesR(t)){const t=Rc(i);t&&e.push(t)}}return Ac(t,e)}_frameOf(){const t=this._spaceModel();if(!t){this._frame=null;const t={x:0,y:0,w:um,h:um};return{rect:t,all:t,outliers:0}}const e=this._frame,i="view"!==this._mode;if(e&&e.id===t.id&&this._bdDrag)return e;if(e&&e.id===t.id&&e.model===t&&e.layout===this._layout&&e.devs===this._devices&&e.far===this._showFar&&e.grow===i)return e;const s=Oc(this._contentItems(t));let n=s.all||Nc(t),o=this._showFar?n:s.core||Nc(t);return e&&e.id===t.id&&i&&e.grow&&(o=gm(e.rect,o),n=gm(e.all,n)),this._frame={id:t.id,model:t,layout:this._layout,devs:this._devices,far:this._showFar,grow:i,rect:o,all:n,outliers:s.outliers},this._frame}_isoSource(){const t=this._spaceModel();if(!t)return null;const e=this._spaceWalls,i=this._openPairs().flatMap(t=>t.segs),s=this._openingsR.map((t,e)=>({id:String(t.id||e),sourceIndex:e,type:t.type,x:t.rx,y:t.ry,angle:Number(t.angle)||0,length:t.rlen>0?t.rlen:900,flipH:!!t.flip_h,flipV:!!t.flip_v})),n=hc(64,this._cellCm),o=hc(10,this._cellCm),a=`${t.id}|${function(t){let e=2166136261;const i=t=>{if("number"!=typeof t)if("string"!=typeof t)if("boolean"!=typeof t)if(Array.isArray(t)){e=vg(e,t.length);for(const e of t)i(e)}else{if(t&&"object"==typeof t){const e=t;for(const t of Object.keys(e).sort())i(t),i(e[t]);return}e=vg(e,-1)}else e=vg(e,t?1:0);else for(const i of t)e=vg(e,i.codePointAt(0)||0);else e=vg(e,t)};return i(t),e.toString(36)}({rooms:t.rooms,walls:e,openCuts:i,openings:s,partitions:t.partitions,roomDrafts:t.room_drafts,columns:t.wall_columns,cellCm:this._cellCm,gridPitch:this._gridPitch,wallKeyPitch:this._wallKeyPitch,camera:ag,wallHeight:n,floorEdgeHeight:o,algorithm:3})}`;return{key:a,build:()=>{const o=Jl(t,this._cellCm,this._gridPitch,2e-4*this._gridPitch,this._partitionOpeningCuts(t)).all,a=this._roomWallOpeningInputs(this._openingsR,t),r=e.length||o.length?Dl(t.rooms,e,i,a,this._wallKeyPitch,this._cellCm,this._gridPitch,um,o):null;if((e.length||o.length)&&!r)throw new Error("wall boolean geometry failed");const l=r?.paperGeom??Ml(t.rooms,e,i,this._wallKeyPitch,this._cellCm,this._gridPitch,um);if(!l)throw new Error("floor boolean geometry failed");const c=r?.openingIndex||Il(t.rooms,e,i,this._wallKeyPitch,this._cellCm,this._gridPitch,um),h=s.map(t=>{const i=this._openingsR[t.sourceIndex],s="gate"===t.type?!t.flipV:t.flipV,o=i?.partitionHost?Ed(i.partitionHost,s):e.length||"gate"===t.type?zl(c,{x:t.x,y:t.y,angle:t.angle,length:t.length,flip_v:s}):{ox:0,oy:0,cm:0,side:-1};return function(t,e=64){if(!(yg([t.x,t.y,t.angle,t.length,t.face.ox,t.face.oy,e])&&t.length>0&&e>0))throw new Error("invalid isometric opening input");const i=t.length/2;let s;if("passage"===t.type)s=[];else if("gate"===t.type){const n=10*t.face.side;s=[wg(t,0,[-i,0],[i,0],n,0,.88*e),wg(t,1,[i,0],[-i,0],-n,0,.88*e)]}else s="window"===t.type?[wg(t,0,[-i,0],[i,0],-90,.27*e,.78*e),wg(t,1,[i,0],[-i,0],90,.27*e,.78*e)]:[wg(t,0,[-i,0],[t.length,0],-90,0,.92*e)];return{id:t.id,sourceIndex:t.sourceIndex,type:t.type,leaves:Object.freeze(s.map(t=>Object.freeze(t)))}}({...t,face:o},n)});return{walls:r?.geom||[],floor:l,openings:Object.freeze(h)}}}}_isoSceneKey(){if(!this._labsIso||"view"!==this._mode)return null;try{return this._isoSource()?.key??null}catch{return`${this._space}|invalid`}}_isoScene(){const t=this._isoSource();if(!t)return null;const e=this._isoGeometryCache.get(t.key);if(e)return{key:t.key,...e};const i=this._frameOf().rect,s=t.build(),n=hc(64,this._cellCm),o=hc(10,this._cellCm),a=function(t){let e=1/0,i=1/0,s=-1/0,n=-1/0;for(const o of t)for(const t of o.leaves){const o=Math.hypot(t.closedVector[0],t.closedVector[1]);e=Math.min(e,t.hinge[0]-o),i=Math.min(i,t.hinge[1]-o),s=Math.max(s,t.hinge[0]+o),n=Math.max(n,t.hinge[1]+o)}return yg([e,i,s,n])?{x:e,y:i,w:s-e,h:n-i}:null}(s.openings),r=dg({rect:a?gm(i,a):i,wallHeight:n,openingHeight:n,floorDepth:o}),l=function(t,e=ag,i=64){if(!Number.isFinite(i)||i<0)throw new Error("invalid wall height");const s=[],n=[],o=[];let a=0;for(let r=0;r<(t||[]).length;r++){const l=t[r];for(let t=0;t<(l||[]).length;t++){const c=_g(l[t],t>0);if(!(c.length<3||Math.abs(ug(c))<1e-9)){s.push(gg(c,e,i)),a+=c.length;for(let s=0;st.depth-e.depth||t.polygon-e.polygon||t.ring-e.ring||t.edge-e.edge),{topPath:s.join(" "),sides:n,contactPath:o.join(" "),edgeCount:a}}(s.walls,ag,n),c={geometry:l,floor:fg(s.floor,o),openings:s.openings,frame:r};return em(this._isoGeometryCache,t.key,c,8),{key:t.key,...c}}_effectiveProjection(){if("iso"!==this._desiredProjection||!this._model.length)return"flat";const t=this._isoSceneKey()||`${this._space}|invalid`;if(this._isoFallback.has(t))return"flat";try{const t=this._isoScene();return t?(e="iso",i=t.key,s=this._isoFallback,"iso"===e&&i&&!s.has(i)?"iso":"flat"):"flat"}catch(e){if(!this._isoFallback.has(t)){this._isoFallback.add(t);const i=t.split("|");console.warn(`HOUSEPLAN ISO FALLBACK: #89, space ${this._space}, fingerprint ${i[i.length-1]}, ${e instanceof Error?e.message:"renderer error"}`)}return"flat"}var e,i,s}_scenePoint(t){return"iso"===this._renderProjection?lg(t,0):t}_floorView(t){if("iso"!==this._renderProjection)return t;const e=cg([t.x,t.y]),i=cg([t.x+t.w,t.y+t.h]);return{x:e[0],y:e[1],w:i[0]-e[0],h:i[1]-e[1]}}_baseVb(){if("iso"===this._effectiveProjection()){if(!this._spaceDisplayForRender().showBorders){const t=dg({rect:this._frameOf().rect,wallHeight:hc(64,this._cellCm)});return[t.x,t.y,t.w,t.h]}const t=this._isoScene()?.frame??this._frameOf().rect;return[t.x,t.y,t.w,t.h]}const t=this._frameOf().rect;return[t.x,t.y,t.w,t.h]}get _outliers(){return this._showFar?0:this._frameOf().outliers}_fitFar(){this._showFar=!0,this._frame=null,this._resetZoom()}_fitAll(){this._showFar=!0,this._frame=null,this._resetZoom()}_renderFarHint(){return this._kiosk||"view"!==this._mode||this._booting||!this._outliers?G:W`
${this._t("canvas.far_objects",{n:this._outliers})} -
`}_renderHomeArrow(){if(this._booting)return G;const t=this._view;if(!t||!t.w||!t.h)return G;const e=this._baseVb(),i=e[0],s=e[1],n=e[2],o=e[3];if(!(i+n<=t.x||i>=t.x+t.w||s+o<=t.y||s>=t.y+t.h))return G;const r=Math.atan2(s+o/2-(t.y+t.h/2),i+n/2-(t.x+t.w/2)),a=50+38*Math.cos(r),l=50+38*Math.sin(r);return W``}_stageAspect(){const t=this._stageEl,e=this._baseVb();return t&&t.clientHeight?t.clientWidth/t.clientHeight:e[2]/e[3]}_viewOr(t){return this._view&&this._view.w?this._view:Oi(t,this._stageAspect())}_roomLabelReferenceViewWidth(t){if(!this._markup)return t.w;const e=this._stageEl,i=this.renderRoot.querySelector(".editorchrome");if(!e||e.clientWidth<=0||e.clientHeight<=0)return t.w;const s=e.clientHeight+(i?.getBoundingClientRect().height||0);return s<=0?t.w:this._viewForModeTarget(this._zoom,void 0,void 0,e.clientWidth,s).w}_screenToVb(t,e){const i=this._stageEl,s=this._viewOr(this._baseVb()),n=i?.clientWidth||1,o=i?.clientHeight||1;return[s.x+t/n*s.w,s.y+e/o*s.h]}_clampView(t,e){const i=(t,e,i,s)=>{const n=1*Math.max(e,s),o=i-n,r=i+s-e+n;return Math.max(Math.min(o,r),Math.min(Math.max(o,r),t))};return{w:t.w,h:t.h,x:i(t.x,t.w,e.x,e.w),y:i(t.y,t.h,e.y,e.h)}}_applyView(t,e,i){const s=this._baseVb(),n=Oi(s,this._stageAspect()),o=Math.min(wm.ZOOM_MAX,Math.max(wm.ZOOM_MIN,t)),r=n.w/o,a=n.h/o,l=this._viewOr(s),c=e??l.x+l.w/2,h=i??l.y+l.h/2,d=this._clampView({x:c-r/2,y:h-a/2,w:r,h:a},n);return!(this._view&&Math.abs(this._zoom-o)<1e-9&&Math.abs(this._view.x-d.x)<1e-6&&Math.abs(this._view.y-d.y)<1e-6&&Math.abs(this._view.w-d.w)<1e-6&&Math.abs(this._view.h-d.h)<1e-6)&&("opening"===this._tool&&(this._cursorPt=null,this._clearOpeningPlacement(!1)),this._zoom=o,this._view=d,!0)}_bootWatch(){clearTimeout(this._bootTimer),this._bootStart=Date.now(),this._bootLastH=-1,this._bootLastChange=this._bootStart;const t=()=>{if(!this._booting)return;const e=Date.now(),i=this._stageEl?this._stageEl.clientHeight:0;i!==this._bootLastH&&(this._bootLastH=i,this._bootLastChange=e);const s=e-this._bootStart;s>=1200||s>=700&&i>0&&e-this._bootLastChange>=250?this._bootSettled():this._bootTimer=window.setTimeout(t,100)};this._bootTimer=window.setTimeout(t,100)}_bootSettled(){this._booting&&!this._bootSettling&&(this._bootSettling=!0,this._refitView(),this._bootSettleRaf=requestAnimationFrame(()=>{this._bootSettleRaf=0,this._finishBootSettled()}))}_finishBootSettled(){if(!this._booting)return;this._refitView(),this._booting=!1,this._bootSettling=!1;const t=this._stageEl?.clientHeight??0;!this._config?.kiosk&&t>0&&this._warmPatch({hdrH:this._hdrH,stageH:t,vp:this._warmViewportState()},!0),this._bootFading=!0,this._bootTimer=window.setTimeout(()=>{this._bootFading=!1},220),this._bootSoft=!0,clearTimeout(this._bootSoftTimer),this._bootSoftTimer=window.setTimeout(()=>{this._bootSoft=!1},Jg)}_bootSoftCancel(){this._bootSoft&&(clearTimeout(this._bootSoftTimer),this._bootSoft=!1)}_beginResumeSettle(){this._booting||this._resumeSettling||(this._modeTransitionPreparing?this._modeTransitionForceAtomic=!0:this._cancelModeTransition(!0),this._viewportInvalidAt=0,this._beginContinuityCandidate("warm-resume",!1),this._loading?this.requestUpdate():this._loadFromServer())}_refitView(){if(this._modeTransitionBusy)return;const t=this._stageEl;if(!t||"visible"!==document.visibilityState||t.clientWidth<=0||t.clientHeight<=0)return void(this._viewportInvalidAt||(this._viewportInvalidAt=Date.now()));const e=[t.clientWidth,t.clientHeight],i=this._lastValidStageSize,s=!!i&&Math.abs(i[0]-e[0])<=.5&&Math.abs(i[1]-e[1])<=.5,n=this._viewportInvalidAt?Date.now()-this._viewportInvalidAt:0;if(this._viewportInvalidAt=0,!i)return this._lastValidStageSize=e,void(this._view||this._applyView(this._zoom));s?this._pendingRefitSize=null:(this._pendingRefitSize=e,this._refitRaf||(this._refitRaf=requestAnimationFrame(()=>{this._refitRaf=0;const t=this._pendingRefitSize;this._pendingRefitSize=null;const e=this._stageEl;if(!t||!e||e.clientWidth<=0||e.clientHeight<=0)return;if(Math.abs(e.clientWidth-t[0])>.5||Math.abs(e.clientHeight-t[1])>.5)return void this._refitView();const i=this._lastValidStageSize;if(i&&Math.abs(i[0]-t[0])<=.5&&Math.abs(i[1]-t[1])<=.5)return;this._lastValidStageSize=t;const s=this._view;n>=wh?this._beginContinuityCandidate("stage-size-restored",!0,"stage-size"):this._continuity.hasCompleteFrame&&this._beginContinuityCandidate("stage-resize",!0,"stage-size"),this._applyView(this._zoom,s?s.x+s.w/2:void 0,s?s.y+s.h/2:void 0)})))}_zoomAt(t,e,i){const s=this._stageEl;if(!s)return;const n=Oi(this._baseVb(),this._stageAspect()),o=Math.min(wm.ZOOM_MAX,Math.max(wm.ZOOM_MIN,i));"opening"===this._tool&&(this._cursorPt=null,this._clearOpeningPlacement(!1));const r=s.clientWidth,a=s.clientHeight,l=this._screenToVb(t,e),c=n.w/o,h=n.h/o;this._zoom=o,this._view=this._clampView({x:l[0]-t/r*c,y:l[1]-e/a*h,w:c,h:h},n)}_onWheel(t){const e=this._stageEl;if(!e)return;t.preventDefault();const i=e.getBoundingClientRect(),s=t.deltaY<0?1.15:1/1.15;this._zoomAt(t.clientX-i.left,t.clientY-i.top,this._zoom*s),this._saveZoom()}_stepZoom(t){const e=this._stageEl;e&&(this._zoomAt(e.clientWidth/2,e.clientHeight/2,this._zoom*(t>0?1.4:1/1.4)),this._saveZoom())}_resetZoom(){const t=this._baseVb();"opening"===this._tool&&(this._cursorPt=null,this._clearOpeningPlacement(!1)),this._zoom=1,this._view=Oi(t,this._stageAspect()),this._saveZoom()}_saveZoom(){if("view"===this._mode){this._zoomBySpace={...this._zoomBySpace,[this._space]:this._zoom};try{localStorage.setItem(am,JSON.stringify(this._zoomBySpace))}catch{}}}_restoreZoom(){const t=this._zoomBySpace[this._space]||1;this._zoom=t;const e=this._stageEl;if(e&&e.clientHeight){const e=this._baseVb();return this._applyView(t,e[0]+e[2]/2,e[1]+e[3]/2),void this.requestUpdate()}this._view=null,requestAnimationFrame(()=>{if(!this._stageEl)return;const e=this._baseVb();this._applyView(t,e[0]+e[2]/2,e[1]+e[3]/2),this.requestUpdate()})}_stagePointerDown(t){if(this._vacFit)return;if(this._kiosk&&(this._cyclePausedUntil=Date.now()+6e4,0===this._pointers.size?(this._swipeStart={x:t.clientX,y:t.clientY,id:t.pointerId},t.target.closest?.(".dev, .roomlabel, .oplock")||(clearTimeout(this._kioskHoldTimer),this._kioskHoldTimer=window.setTimeout(()=>{this._kioskDialog=!0,this._swipeStart=null},3e3))):(this._swipeStart=null,clearTimeout(this._kioskHoldTimer))),this._drag)return;if(this._markup&&t.target.closest?.(".roomlabel, .rlhandle, .rszhandle, .dev, .oplock, .op-hit, button"))return;if("devices"===this._mode&&t.target.closest(".dev"))return;if("decor"===this._mode&&this._decorPointerDown(t))return;this._pointers.set(t.pointerId,{x:t.clientX,y:t.clientY});const e=this._viewOr(this._baseVb());if(1===this._pointers.size)this._panStart={sx:t.clientX,sy:t.clientY,vx:e.x,vy:e.y},this._panLock=null,this._suppressClick=!1;else if(2===this._pointers.size){this._cancelBoundaryAnchor(),"opening"===this._tool?(this._cursorPt=null,this._clearOpeningPlacement(!1)):"draw"===this._tool&&this._clearPlanSnapHover();const t=[...this._pointers.values()],e=Math.hypot(t[0].x-t[1].x,t[0].y-t[1].y);this._pinchStart={dist:e,zoom:this._zoom},this._panStart=null,this._panLock=null}}get _swipeZone(){return!this._hasFixedFloor&&this._kiosk&&this._zoom<=1.001&&this._model.length>1}_stagePointerMove(t){if(this._physicalRotate?.pid!==t.pointerId)if(this._physicalDrag?.pid!==t.pointerId)if(this._dtDrag?.pid!==t.pointerId)if(this._bdDrag?.pid!==t.pointerId){if(this._decorDraft?.pid===t.pointerId){const e=this._decorDraft;let i=this._decorSnap(this._svgPoint(t),t.pointerType);if(t.shiftKey&&("rect"===e.kind||"ellipse"===e.kind)){const t=i[0]-e.a[0],s=i[1]-e.a[1],n=Math.max(Math.abs(t),Math.abs(s));i=this._snap([e.a[0]+(t<0?-n:n),e.a[1]+(s<0?-n:n)])}return void(this._decorDraft={...e,b:i})}if(this._decorMove?.pid!==t.pointerId)if(this._pointers.has(t.pointerId)){if(this._pointers.set(t.pointerId,{x:t.clientX,y:t.clientY}),this._markup&&1===this._pointers.size&&this._markupMove(t),this._pinchStart&&this._pointers.size>=2){"opening"===this._tool?(this._cursorPt=null,this._clearOpeningPlacement(!1)):"draw"===this._tool&&this._clearPlanSnapHover();const t=[...this._pointers.values()],e=Math.hypot(t[0].x-t[1].x,t[0].y-t[1].y)/(this._pinchStart.dist||1),i=this._stageEl.getBoundingClientRect(),s=(t[0].x+t[1].x)/2-i.left,n=(t[0].y+t[1].y)/2-i.top;this._zoomAt(s,n,this._pinchStart.zoom*e),this._suppressClick=!0,this._saveZoom()}else if(this._panStart){const e=t.clientX-this._panStart.sx,i=t.clientY-this._panStart.sy;Math.abs(e)+Math.abs(i)>4&&(this._suppressClick=!0,clearTimeout(this._holdTimer),"opening"===this._tool?(this._cursorPt=null,this._clearOpeningPlacement(!1)):"draw"===this._tool&&this._clearPlanSnapHover()),null===this._panLock&&Math.abs(e)+Math.abs(i)>8&&(this._panLock=this._swipeZone&&Math.abs(e)>1.5*Math.abs(i)?"swipe":"pan");const s=this._stageEl;if("pan"===this._panLock&&s){const t=this._baseVb(),n=this._viewOr(t),o=Oi(t,this._stageAspect());this._view=this._clampView({x:this._panStart.vx-e/(s.clientWidth||1)*n.w,y:this._panStart.vy-i/(s.clientHeight||1)*n.h,w:n.w,h:n.h},o)}}}else this._markupMove(t);else this._decorMoveUpdate(t)}else this._bdMove(t);else this._dtMove(t);else this._physicalMove(t);else this._physicalRotateMove(t)}_stagePointerLeave(t){this._markup&&("opening"===this._tool?(this._cursorPt=null,this._clearOpeningPlacement(!1)):"draw"===this._tool&&this._clearPlanSnapHover())}_stagePointerUp(t){if(this._kiosk){clearTimeout(this._kioskHoldTimer);const e=this._swipeStart;if(this._swipeStart=null,e&&e.id===t.pointerId){const i=t.clientX-e.x,s=t.clientY-e.y;if(Math.abs(i)+Math.abs(s)<8){const t=Date.now();t-this._lastTap<350&&this._resetZoom(),this._lastTap=t}const n="pan"===this._panLock?null:function(t,e,i,s,n,o=60){if(i>1.001||s.length<2)return null;if(Math.abs(t)t.id),this._space);n&&this._slideTo(n,i<0?"left":"right")&&(this._saveNav(),this._suppressClick=!0,setTimeout(()=>this._suppressClick=!1,0),this._showKioskDots())}}if(this._physicalDrag?.pid===t.pointerId)return void this._physicalUp(t);if(this._physicalRotate?.pid===t.pointerId)return void this._physicalRotateUp(t);if(this._dtDrag?.pid===t.pointerId)return void this._dtUp();if(this._bdDrag?.pid===t.pointerId)return void this._bdUp();if(this._decorDraft?.pid===t.pointerId)return void this._decorCommitDraft();if(this._decorMove?.pid===t.pointerId)return this._decorMove.moved&&(this._recordGeometry(this._t("history.decor_move"),this._decorMove.before),this._saveConfig()),void(this._decorMove=null);const e=!!this._pinchStart||!!this._panStart;this._pointers.delete(t.pointerId),this._pointers.size<2&&(this._pinchStart=null),0===this._pointers.size&&(this._panStart=null,this._panLock=null,setTimeout(()=>this._suppressClick=!1,0)),e&&0===this._pointers.size&&this.requestUpdate()}_clickRoom(t){!this._suppressClick&&t.area&&vm("/config/areas/area/"+t.area)}_pointerDown(t,e){if("plan"===this._mode)return;if("view"===this._mode){this._holdFired=!1,clearTimeout(this._holdTimer);const i=t.pointerId,s=t.currentTarget;return void(this._holdTimer=window.setTimeout(()=>{this._holdFired=!0,this._interruptViewGesture(i,s),this._infoCard=e},600))}if("ha_disabled"===e.bindingStatus?.kind)return;t.preventDefault();const i=this._pos(e);this._drag={id:e.id,sx:t.clientX,sy:t.clientY,ox:i.x,oy:i.y,moved:!1},bm(t),this._tip=null}_pointerMove(t,e){if(!this._drag||this._drag.id!==e.id)return;const i=this.renderRoot.querySelector(".stage");if(!i)return;const s=this._baseVb(),n=i.getBoundingClientRect(),o=this._viewOr(s),r=(t.clientX-this._drag.sx)/n.width*o.w,a=(t.clientY-this._drag.sy)/n.height*o.h;Math.abs(t.clientX-this._drag.sx)+Math.abs(t.clientY-this._drag.sy)>3&&(this._drag.moved=!0,clearTimeout(this._holdTimer));const l=Mc(this._drag.ox+r),c=Mc(this._drag.oy+a);this._savePos(e,l,c)}_pointerUp(t,e){if(clearTimeout(this._holdTimer),!this._drag||this._drag.id!==e.id)return;const i=this._drag.moved;this._drag=i?this._drag:null,i&&(this._selId=e.id,window.setTimeout(()=>this._drag=null,0))}_showToast(t){for(const t of this.renderRoot.querySelectorAll("hp-dialog"))t.closeTransientOverlays("toast");this._toast=t,clearTimeout(this._toastTimer),this._toastTimer=window.setTimeout(()=>{this._toast=""},3500)}_syncPointerHoverTargets(){const t=this._pointerModality.hoverEnabled;for(const e of this.renderRoot.querySelectorAll(dm))e.toggleAttribute("data-pointer-hover",t)}_syncPointerHoverSubtree(t){if(t.nodeType!==Node.ELEMENT_NODE)return;const e=t,i=this._pointerModality.hoverEnabled;e.matches(dm)&&e.toggleAttribute("data-pointer-hover",i);for(const t of e.querySelectorAll(dm))t.toggleAttribute("data-pointer-hover",i)}_clearTransientHover(t=!1){t&&this._pointerModality.suspend(),this._tip&&(this._tip=null),this._hoverRoom&&(this._hoverRoom=null)}_notePointer(t){this._boundaryPointerType=t.pointerType||"mouse";const e=this._pointerModality.modality,i=this._pointerModality.note(t);"touch"!==i&&"pen"!==i||e===i&&!this._tip&&!this._hoverRoom||this._clearTransientHover()}_guardTouchGesture(t){if(this._editorSecondary.handleOutsideDismiss(t))return;if("click"===t.type){if(!this._suppressClick&&!this._touchSequenceMultitouch&&Date.now()>this._touchClickBlockUntil)return;return t.preventDefault(),void t.stopImmediatePropagation()}const e=t;if(this._notePointer(e),"touch"===e.pointerType)if("pointerdown"!==t.type){if("pointermove"===t.type){const t=this._touchContacts.get(e.pointerId);if(!t)return;const i={...t,x:e.clientX,y:e.clientY};if(this._touchContacts.set(e.pointerId,i),this._touchSequenceMultitouch&&"view"===this._mode&&!this._vacFit&&this._pinchStart&&[...this._touchContacts.values()].every(t=>t.inStage)){this._pointers.set(e.pointerId,{x:e.clientX,y:e.clientY});const t=[...this._touchContacts.values()];if(t.length>=2&&this._stageEl){const[e,i]=t,s=Math.hypot(e.x-i.x,e.y-i.y)/(this._pinchStart.dist||1),n=this._stageEl.getBoundingClientRect();this._zoomAt((e.x+i.x)/2-n.left,(e.y+i.y)/2-n.top,this._pinchStart.zoom*s),this._saveZoom()}}return}if("pointerup"===t.type||"pointercancel"===t.type||"lostpointercapture"===t.type){if(this._clearTransientHover(),this._touchContacts.delete(e.pointerId),this._touchSequenceMultitouch){if(this._touchClickBlockUntil=Date.now()+500,this._pointers.delete(e.pointerId),!this._vacFit&&this._pointers.size>=2){const[t,e]=[...this._pointers.values()];this._pinchStart={dist:Math.hypot(t.x-e.x,t.y-e.y),zoom:this._zoom}}else this._pinchStart=null;0===this._pointers.size&&(this._panStart=null,this._panLock=null)}0===this._touchContacts.size&&(this._touchSequenceMultitouch=!1)}}else if(this._touchContacts.set(e.pointerId,{x:e.clientX,y:e.clientY,inStage:!!e.target?.closest?.(".stage")}),this._touchContacts.size>=2){this._clearTransientHover(),this._touchSequenceMultitouch=!0,this._touchClickBlockUntil=Number.POSITIVE_INFINITY,clearTimeout(this._holdTimer),clearTimeout(this._kioskHoldTimer),this._swipeStart=null;const t=[...this._touchContacts.values()];if("view"===this._mode&&!this._vacFit&&t.every(t=>t.inStage)){this._pointers=new Map([...this._touchContacts].map(([t,e])=>[t,{x:e.x,y:e.y}]));const[e,i]=t;this._pinchStart={dist:Math.hypot(e.x-i.x,e.y-i.y),zoom:this._zoom},this._panStart=null,this._panLock=null}else this._vacFit&&(this._pointers.clear(),this._pinchStart=null,this._panStart=null,this._panLock=null)}}_showTip(t,e,i,s,n,o){this._notePointer(t),this._pointerModality.hoverEnabled&&(this._drag||(this._tip={x:t.clientX,y:t.clientY,title:e,meta:i,lqi:s,temp:n,hum:o}))}get _gridPitch(){return kc}get _cellCm(){const t=Number(this._curSpaceCfg?.cell_cm);return Number.isFinite(t)&&t>0?t:5}_fmtLen(t,e){const i=function(t,e,i,s){return Math.hypot(e[0]-t[0],e[1]-t[1])/i*s}(t,e,this._gridPitch,this._cellCm);return li(i,"mi"===this.hass?.config?.unit_system?.length)}get _curSpaceCfg(){const t=this._rszPreview;return t&&t.space===this._space?t.sp:this._serverCfg?.spaces.find(t=>t.id===this._space)}get _renderCfg(){const t=this._rszPreview;return t&&this._serverCfg?{...this._serverCfg,spaces:this._serverCfg.spaces.map(e=>e.id===t.space?t.sp:e)}:this._serverCfg}get _spaceH(){return this._curSpaceCfg,pm}get _segments(){const t=this._curSpaceCfg,e=this._spaceH;return pi(t?.rooms||[]).map(t=>[t[0]*pm,t[1]*e,t[2]*pm,t[3]*e])}_savedNav(){if(this._hasFixedFloor)return null;try{return JSON.parse(localStorage.getItem(lm)||"null")}catch{return null}}_saveNav(){if(!this._hasFixedFloor)try{localStorage.setItem(lm,JSON.stringify({space:this._space}))}catch{}}_leaveCardRoute(){if(this._routeDepartureHandled)return;this._routeDepartureHandled=!0,"view"!==this._mode&&this._setMode("view",!1),this._pendingNavMode=null,this._geometryHistory.clear(),this._activeDraftId=null,this._resumeDraftBySpace={},this._draftSegmentCms=[],this._closingWallCm=null,this._drawWallField=null,this._showHidden=!1,this._tapConfirm=null,this._vacCalConfirm=null,this._decorEraseConfirm=null,this._openingInfo=null,this._closeInfoCard(),this._rulesDialog=null,this._alignDialog=null,this._backupImportDialog=null,this._backupExportDialog=null,this._settingsDialog=null,this._markerDialog=null,this._openingDialog=null,this._physicalDialog=null,this._wallDialog=null,this._backdropDialog=null,this._decorShapeDialog=null,this._decorTextDialog=null,this._mergeDialog=null,this._roomDialog=!1,this._spaceDialog=null,this._importDialog=null;const t=this._warmSlot;t?.owner===this._warmGen&&(t.vp=this._warmViewportState(),t.dlg=null,t.frameFingerprint="",clearTimeout(t.evict),t.evict=0),this._saveNav()}_setMode(t,e=!0){this._endTabDrag(),this._pendingNavMode=null;const i=this._spaceModel();if(!i)return this._cancelModeTransition(!1),void(this._mode="view");if(this._kiosk&&"view"!==t)return;if(this._mode===t){if(!e&&"view"===t&&this._modeTransitionBusy){const e=this._currentModeVisual(t),i=this._modeTransitionTargetZoom,s=this._modeTransitionTargetCenterX,n=this._modeTransitionTargetCenterY;this._cancelModeTransition(!1),this._commitViewModeAtomic(e,i,s,n)}return}if(this._bootSoftCancel(),("plan"===t||"decor"===t)&&!this._norm)return void this._showToast(this._t("toast.markup_needs_server"));if(this._wallFaceBatch&&this._roomDialogCancel(),"plan"===this._mode&&"draw"===this._tool&&!this._finishWallChain())return;this._clearTransientHover(!0),this._cancelDevicePressFeedback();const s=this._mode,n=this._effectiveProjection(),o=this._currentModeVisual(s),r=this._modeTransitionBusy,a=o&&"view"!==s&&"view"!==t?{...o,toolbarContentOpacity:this._reducedMotion?1:.35}:o;this._cancelModeTransition(!1),this._editorSecondary.closeForNavigation(),(this._decorMove||this._dtDrag||this._bdDrag)&&this._cancelDecorGesture();const l=!i.bg&&"view"===t!=("view"===s),c=r&&"view"===s&&"view"!==t?this._modeTransitionEditorCamera:null;let h=c?.zoom??(r?this._modeTransitionTargetZoom:this._zoom),d=c?c.centerX:r?this._modeTransitionTargetCenterX:a?.viewport.centerX,p=c?c.centerY:r?this._modeTransitionTargetCenterY:a?.viewport.centerY;if("view"===s&&"view"!==t&&!r){const e=this._view;if(this._viewModeSnap={space:this._space,zoom:this._zoom,cx:e?this._logicalViewCenter(n)?.x:void 0,cy:e?this._logicalViewCenter(n)?.y:void 0},"iso"===n){const e=this._logicalViewCenter("iso");d=e?.x,p=e?.y,this._view=null,this._mode=t,this._applyView(this._zoom,e?.x,e?.y)}l&&(h=1,d=void 0,p=void 0)}if("plan"===s&&this._activeDraftId&&(this._resumeDraftBySpace[this._space]=this._activeDraftId),this._mode=t,this._editorChromeMode="view"===t?s:t,"view"===t){"view"===s||r||(this._modeTransitionEditorCamera={zoom:this._zoom,centerX:a?.viewport.centerX,centerY:a?.viewport.centerY});const t=this._viewModeSnap;if(t&&t.space===this._space){h=t.zoom;const e=this._labsIso&&"iso"===this._viewPreference[this._space]?"iso":"flat",i=null!=t.cx&&null!=t.cy&&"iso"===e?ag([t.cx,t.cy],0):null;d=i?.[0]??t.cx,p=i?.[1]??t.cy}else t&&(h=this._zoomBySpace[this._space]||1,d=void 0,p=void 0)}else this._modeTransitionEditorCamera={zoom:h,centerX:d,centerY:p};this._modeTransitionTargetZoom=h,this._modeTransitionTargetCenterX=d,this._modeTransitionTargetCenterY=p,("iso"===n||"view"===t&&this._labsIso&&"iso"===this._viewPreference[this._space])&&(this._modeTransitionForceAtomic=!0);const u=++this._modeTransitionRequest;e?a?(this._modeTransitionPreparing=!0,this._modeTransitionVisual=a,this._prepareModeTransition(u,a,t,h,d,p)):(this._modeTransitionPreparing=!1,this._modeTransitionVisual=null,this._zoom=h,this._view=null,requestAnimationFrame(()=>{this.isConnected&&u===this._modeTransitionRequest&&this._mode===t&&(this._applyView(h,d,p),"view"===t&&(this._viewModeSnap=null,this._modeTransitionEditorCamera=null),this.requestUpdate())})):"view"===t&&this._commitViewModeAtomic(a,h,d,p),this._path=[],this._clearPlanSnapHover(),this._clearOpeningPlacement(!0),this._openWallAnchor=null,this._boundaryRestoreGuard=null,this._tool="draw",this._mergeSel=null,this._mergeDialog=null,this._splitSel=null,this._pendingSplit=null,this._selId=null,this._physicalSel=null,this._physicalDialog=null,this._physicalDrag=null,this._rszSel=null,this._rszDrag=null,this._rszLive=null,this._rszPreview=null,this._tip=null,this._hoverRoom=null,this._decorDraft=null,this._decorSel=null,this._decorMove=null,this._backdropDialog=null,this._decorTool="select",this._bdDrag=null,this._dtDrag=null,this._dtBox=null,"plan"===t&&(this._primeDrawWallField(),this._resumeLastDraft()),this._saveNav()}_primeDrawWallField(){null===this._drawWallField&&(this._drawWallField=ka(fa,this._imperial))}get _drawWallFieldValue(){return null===this._drawWallField?ka(fa,this._imperial):this._drawWallField}get _drawWallCm(){const t=Zg(this._drawWallFieldValue);if(null==t||t<=0)return null;const e=this._imperial?2.54*t:t,i="column"===this._tool?Hl:100;return e>=1&&e<=i?e:null}get _drawWallMaxCm(){return"column"===this._tool?Hl:100}_showPhysicalRange(t=this._drawWallMaxCm){this._showToast(this._t("toast.physical_range",{max:ka(t,this._imperial),unit:this._t(this._imperial?"wallthick.unit_in":"wallthick.unit_cm")}))}_draftSegmentCount(t=this._curSpaceCfg){return(t?.room_drafts||[]).reduce((t,e)=>t+(Array.isArray(e.segments)?e.segments.length:0),0)}_mergeSpacePartitions(t,e){const i=t?.partitions||[];if(i.length<2)return 0;const s=o_(i,{pitch:xc,seedIds:e,geometry:a_(t,{excludeDraftId:this._activeDraftId})});return s.merged?(t.partitions=s.partitions,r_(t.openings,t.partitions,s.openingMoves,{coordScale:pm,cellCm:this._cellCm,gridPitch:this._gridPitch}),s.merged):0}_finishWallChain(){if("draw"!==this._tool||this._wallFaceBatch||this._roomDialog)return!0;const t=this._curSpaceCfg;if(!t||this._path.length<2)return this._path=[],this._activeDraftId=null,this._draftSegmentCms=[],this._closingWallCm=null,this._clearPlanSnapHover(),!0;const e=tp(this._path,Qd(this._path.length-1,this._draftSegmentCms,this._drawWallCm,fa)),i=e.length;if((t.partitions||[]).length+i>mm)return this._showToast(this._t("toast.physical_limit")),!1;const s=this._geometrySnapshot();t.partitions||=[];const n=Date.now().toString(36),o=[];for(let s=0;st.id!==this._activeDraftId),t.room_drafts.length||delete t.room_drafts),this._recordGeometry(this._t("history.wall_chain_finish"),s),this._saveConfig(),delete this._resumeDraftBySpace[this._space],this._path=[],this._activeDraftId=null,this._draftSegmentCms=[],this._closingWallCm=null,this._clearPlanSnapHover(),!0}_activateMarkupTool(t){t!==this._tool&&(this._wallFaceBatch&&this._roomDialogCancel(),("draw"!==this._tool||this._finishWallChain())&&(this._cancelPath(),this._tool=t,"draw"===t&&this._resumeLastDraft(),"resize"===t&&(this._rszSel=null),"boundary"!==t&&"wallthick"!==t||(this._wallDialog=null)))}_limitReached(t){const e=this._curSpaceCfg;if(!e)return!0;const i="draft"===t?(e.room_drafts||[]).length>=200:"partition"===t?(e.partitions||[]).length>=mm:(e.wall_columns||[]).length>=500;return i&&this._showToast(this._t("toast.physical_limit")),i}_svgPoint(t){const e=this.renderRoot.querySelector(".stage").getBoundingClientRect();return this._screenToVb(t.clientX-e.left,t.clientY-e.top)}_snap(t){const e=this._gridPitch;return[Mc(ai(t[0],e)),Mc(ai(t[1],e))]}_snapDrawPoint(t,e=!1){const i=this._path[this._path.length-1],s=e&&i?function(t,e,i,s=1/0){if(!(i>0&&t?.every(Number.isFinite)&&e?.every(Number.isFinite)))return[e[0],e[1]];const n=e[0]-t[0],o=e[1]-t[1];if(Math.abs(n)+Math.abs(o)<=1e-12)return[t[0],t[1]];const r=Math.PI/4;let a=Math.atan2(o,n);a<0&&(a+=2*Math.PI);const l=Math.floor(a/r+.5)%8,[c,h]=[[1,0],[1,1],[0,1],[-1,1],[-1,0],[-1,-1],[0,-1],[1,-1]][l],d=c*c+h*h;let p=Math.max(0,Math.round((n*c+o*h)/(i*d)));if(Number.isFinite(s)&&s>=0){const e=(t,e)=>{if(!e)return 1/0;const n=e>0?s-t:t+s;return Math.max(0,Math.floor((n+1e-9*i)/i))};p=Math.min(p,e(t[0],c),e(t[1],h))}return[t[0]+c*p*i,t[1]+h*p*i]}(i,t,this._gridPitch,bc):t;return this._snap(s)}_planSnapOpeningCuts(t,e){if(!this._openingsR.length)return[];const i=this._openingWallIndexFor(t,e).value,s=[];for(const e of this._roomWallOpeningInputs(this._openingsR,t)){const t=Fl(i,e);if(!t.negative&&!t.positive)continue;const n=e.angle*Math.PI/180,o=Math.cos(n)*e.length/2,r=Math.sin(n)*e.length/2;s.push([e.x-o,e.y-r,e.x+o,e.y+r])}return s}_planSnapGeometrySnapshot(){const t=this._spaceModel();if(!t)return{key:`${this._space}|empty`,value:{segments:[],endpoints:[]}};const e=[this._space,this._cfgEpoch,this._activeDraftId||"",t.rooms.length,t.room_drafts.length,t.partitions.length].join("|");if(this._planSnapGeometryCache?.key===e)return this._planSnapGeometryCache;const i=this._openCuts(),s=Ud({space:t,activeDraftId:this._activeDraftId,roomCuts:[...i,...this._planSnapOpeningCuts(t,i)],partitionCuts:this._partitionOpeningCuts(t),epsilon:2e-4*this._gridPitch});return this._planSnapGeometryCache={key:e,value:s},this._planSnapGeometryCache}_planStructuralGeometrySnapshot(){const t=this._spaceModel();if(!t)return{key:`${this._space}|structural-empty`,value:{segments:[],endpoints:[]}};const e=["structural",this._space,this._cfgEpoch,this._activeDraftId||"",t.rooms.length,t.room_drafts.length,t.partitions.length].join("|");if(this._planStructuralGeometryCache?.key===e)return this._planStructuralGeometryCache;const i=Ud({space:t,activeDraftId:this._activeDraftId,roomCuts:this._openCuts(),epsilon:2e-4*this._gridPitch});return this._planStructuralGeometryCache={key:e,value:i},this._planStructuralGeometryCache}_planSnapContextKey(t){const e=this._path[0],i=this._path[this._path.length-1];return[t,this._tool,this._path.length,e?`${e[0]},${e[1]}`:"",i?`${i[0]},${i[1]}`:""].join("|")}_resolvePlanDrawPoint(t,e){const i=this._planSnapGeometrySnapshot(),s=this._path[this._path.length-1],n="draw"===this._tool&&this._path.length>=3?[{point:this._path[0],key:"closure:first-point"}]:[],o={tolerance:this._cssPxToRender(12),distinguishTolerance:this._cssPxToRender(8),gridStep:this._gridPitch,excludePoints:s?[s]:[],extraEndpoints:n,epsilon:2e-4*this._gridPitch},r=e&&s?Jd(i.value,t,{...o,anchor:s}):function(t,e,i){if(!(Nd(e)&&i.tolerance>=0))return{kind:"none",candidate:null,conflicts:[]};const s=i.epsilon??Od,n=i.excludePoints||[],o=Yd(Kd(t,e,i),i.distinguishTolerance||0);if(o)return o;let r=null;for(const o of t.segments){const t=[o.a[0],o.a[1],o.b[0],o.b[1]],a=Hs([e[0],e[1]],t);if(a>i.tolerance)continue;const l=Xd(o,e,i.gridStep);!Gd(l,n,s)&&Vd(a,o.key,r)&&(r={kind:"line",point:l,key:o.key,distance:a,segment:o})}return r?{kind:"resolved",candidate:r,conflicts:[]}:{kind:"none",candidate:null,conflicts:[]}}(i.value,t,o),a="resolved"===r.kind?r.candidate:null;return{point:a?[...a.point]:this._snapDrawPoint(t,e),candidate:a,conflicts:"ambiguous"===r.kind?r.conflicts:[],ambiguous:"ambiguous"===r.kind,contextKey:this._planSnapContextKey(i.key)}}get _activePlanSnapCandidate(){if(!this._markup||"draw"!==this._tool)return null;const t=this._planSnapHover;if(!t)return null;const e=this._planSnapGeometrySnapshot();return t.contextKey===this._planSnapContextKey(e.key)?t.candidate:null}get _activePlanSnapConflicts(){if(!this._markup||"draw"!==this._tool)return[];const t=this._planSnapHover;if(!t)return[];const e=this._planSnapGeometrySnapshot();return t.contextKey===this._planSnapContextKey(e.key)?t.conflicts:[]}_clearPlanSnapHover(t=!0){this._planSnapHover=null,this._syncPlanSnapActiveMarker(null),this._syncPlanSnapConflictMarkers([]),t&&(this._cursorPt=null)}_samePt(t,e){return fi(t,e)}_dropLegacySegments(){for(const t of this._serverCfg?.markers||[])"ripple"===t.display&&(t.display="icon_ripple");for(const t of this._serverCfg?.spaces||[]){delete t.segments;const e=new Set,i=t=>"string"==typeof t&&t.length>=1&&t.length<=64&&!e.has(t),s=t=>(e.add(t),!0),n=t=>Array.isArray(t)&&2===t.length&&t.every(t=>Number.isFinite(Number(t))&&Math.abs(Number(t))<=yc);if(Array.isArray(t.partitions)&&(t.partitions=t.partitions.filter(t=>t&&i(t.id)&&n(t.a)&&n(t.b)&&Math.hypot(t.a[0]-t.b[0],t.a[1]-t.b[1])>1e-9&&s(t.id)).map(t=>({...t,cm:Math.max(1,Math.min(100,Number(t.cm)||15))})),t.partitions.length||delete t.partitions),Array.isArray(t.wall_columns)&&(t.wall_columns=t.wall_columns.filter(t=>t&&i(t.id)&&n(t.center)&&s(t.id)).map(t=>({id:t.id,shape:"circle"===t.shape?"circle":"square",center:[Number(t.center[0]),Number(t.center[1])],cm:Bl(Number(t.cm)||15),..."circle"===t.shape?{}:{angle:ql(t.angle)}})),t.wall_columns.length||delete t.wall_columns),Array.isArray(t.room_drafts)&&(t.room_drafts=t.room_drafts.filter(t=>t&&i(t.id)&&Array.isArray(t.points)&&t.points.length>=2&&t.points.every(n)&&s(t.id)).map(t=>{const e=[[Number(t.points[0][0]),Number(t.points[0][1])]],i=[];for(let s=1;st.points.length>=2),t.room_drafts.length||delete t.room_drafts),Array.isArray(t.walls)){const e=rh(t.open_spans).map(t=>[t.a[0],t.a[1],t.b[0],t.b[1]]);t.walls=Ea(t.walls,t.rooms||[],xc,1,e),t.walls.length||delete t.walls}}}get _cfgWriting(){return this._writesPending>0}_writeConfig(){var t,e;this._writesPending++,this._writeChain=(t=this._writeChain,e=async()=>{if(!this._serverCfg)return;this._dropLegacySegments();const t=Zu(this._serverCfg),e=Ch(t);e!==Ch(this._serverCfg)&&(this._serverCfg=t),this._cfgContentFingerprint=e;const i=await this.hass.callWS({type:"houseplan/config/set",config:t,expected_rev:this._cfgRev});this._cfgRev=i?.rev??this._cfgRev+1},t.catch(()=>{}).then(e));return this._writeChain.finally(()=>{this._writesPending--})}_saveConfig(){this._cfgEpoch++,this._saveConfigDebounced()}_geometrySnapshot(t=this._space){const e=this._serverCfg?.spaces.find(e=>e.id===t);if(!e)return null;const i=t=>JSON.parse(JSON.stringify(t)),s={};for(const t of["plan_x","plan_y","plan_scale","plan_scale_x","plan_scale_y","plan_angle"])void 0!==e[t]&&(s[t]=e[t]);return{spaceId:t,rooms:i(e.rooms||[]),...Array.isArray(e.openings)?{openings:i(e.openings)}:{},...Array.isArray(e.walls)?{walls:i(e.walls)}:{},...Array.isArray(e.open_spans)?{open_spans:i(e.open_spans)}:{},...Array.isArray(e.room_drafts)?{room_drafts:i(e.room_drafts)}:{},...Array.isArray(e.partitions)?{partitions:i(e.partitions)}:{},...Array.isArray(e.wall_columns)?{wall_columns:i(e.wall_columns)}:{},...Array.isArray(e.decor)?{decor:i(e.decor)}:{},plan_transform:s}}_recordGeometry(t,e){if(!e)return;const i=this._geometrySnapshot(e.spaceId);i&&JSON.stringify(e)!==JSON.stringify(i)&&(this._geometryHistory.push({name:t,before:e,after:i}),this.requestUpdate())}_clearGeometryGesture(){this._path=[],this._clearPlanSnapHover(),this._clearOpeningPlacement(!1),this._mergeSel=null,this._mergeDialog=null,this._splitSel=null,this._pendingSplit=null,this._wallFaceBatch=null,this._wallRepairDiagnostic=null,this._roomDeleteDialog=null,this._openWallAnchor=null,this._boundaryRestoreGuard=null,this._wallDialog=null,this._physicalDialog=null,this._physicalSel=null,this._physicalDrag=null,this._physicalRotate=null,this._activeDraftId=null,this._draftSegmentCms=[],this._closingWallCm=null,this._openingDialog=null,this._rszSel=null,this._rszDrag=null,this._rszPreview=null,this._rszLive=null,this._decorDraft=null,this._decorMove=null,this._dtDrag=null,this._bdDrag=null}_cancelBoundaryAnchor(){return!("boundary"!==this._tool||!this._openWallAnchor)&&(this._openWallAnchor=null,this._boundaryRestoreGuard=null,this._clearPlanSnapHover(),this.requestUpdate(),!0)}_stagePointerCancel(t){if(clearTimeout(this._kioskHoldTimer),this._swipeStart?.id===t.pointerId&&(this._swipeStart=null),this._physicalDrag?.pid===t.pointerId||this._physicalRotate?.pid===t.pointerId)return void this._cancelPhysicalGesture();if(this._decorDraft?.pid===t.pointerId)return this._decorDraft=null,void this.requestUpdate();if(this._decorMove?.pid===t.pointerId||this._dtDrag?.pid===t.pointerId||this._bdDrag?.pid===t.pointerId)return void this._cancelDecorGesture();this._cancelBoundaryAnchor(),"opening"===this._tool?(this._cursorPt=null,this._clearOpeningPlacement(!1)):"draw"===this._tool&&this._clearPlanSnapHover();const e=!!this._pinchStart||!!this._panStart;this._pointers.delete(t.pointerId),this._pointers.size<2&&(this._pinchStart=null),0===this._pointers.size&&(this._panStart=null,this._panLock=null),e&&0===this._pointers.size&&this.requestUpdate()}_applyGeometryState(t){if(!this._canCommitSpace(t.spaceId))return!1;const e=this._serverCfg?.spaces.find(e=>e.id===t.spaceId);if(!e)return!1;const i=t=>JSON.parse(JSON.stringify(t));e.rooms=i(t.rooms),void 0!==t.openings?e.openings=i(t.openings):delete e.openings,void 0!==t.walls?e.walls=i(t.walls):delete e.walls,void 0!==t.open_spans?e.open_spans=i(t.open_spans):delete e.open_spans,void 0!==t.room_drafts?e.room_drafts=i(t.room_drafts):delete e.room_drafts,void 0!==t.partitions?e.partitions=i(t.partitions):delete e.partitions,void 0!==t.wall_columns?e.wall_columns=i(t.wall_columns):delete e.wall_columns,void 0!==t.decor?e.decor=i(t.decor):delete e.decor;for(const t of["plan_x","plan_y","plan_scale","plan_scale_x","plan_scale_y","plan_angle"])delete e[t];return Object.assign(e,i(t.plan_transform||{})),this._clearGeometryGesture(),this._space!==t.spaceId&&(this._commitSpace(t.spaceId),this._saveNav(),this._restoreZoom()),this._modelCache=null,this._frame=null,this._regSignature="",this._maybeRebuildDevices(),this._saveConfig(),this.requestUpdate(),!0}_roomAt(t){return this._spaceModel()?.rooms.find(e=>{const i=hi(e);return!!i&&wi(t,i)})}_overlapRoom(t){return this._spaceModel()?.rooms.find(e=>{const i=hi(e);return!!i&&Di(t,i)})}_pointInRoom(t,e){return e.poly?vi(t,e.poly):null!=e.x&&t[0]>=e.x&&t[0]<=e.x+e.w&&t[1]>=e.y&&t[1]<=e.y+e.h}_contourSelfIntersects(t){if(!kr(t))return!0;const e=t.length,i=.001;for(let s=0;s=500)return this._showToast(this._t("toast.physical_limit")),!1;const t=this._curSpaceCfg;return!(!this._activeDraftId&&(t?.room_drafts||[]).length>=200||this._draftSegmentCount(t)>=2e3||(t?.partitions||[]).length+this._path.length>mm)||(this._showToast(this._t("toast.physical_limit")),!1)}_markupClick(t){if(this._vacFit)return;if(!this._markup)return;const e=this._spaceModel();if(!e)return void this._clearGeometryGesture();if(this._suppressClick)return;if(this._drag||this._rlResize)return;const i=t.composedPath?.()||[];if(i.some(t=>t?.classList?.contains?.("roomlabel")||t?.classList?.contains?.("rlhandle")))return;if(i.some(t=>t?.classList?.contains?.("physical-hit")))return void("boundary"===this._tool&&this._showToast(this._t("toast.boundary_blocked")));const s=this._svgPoint(t);if("select"===this._tool)return void(this._physicalSel=null);if("resize"===this._tool){if(this._rszDrag||i.some(t=>t?.classList?.contains?.("rszhandle")))return;const t=[...e.rooms].reverse().find(t=>this._pointInRoom(s,t));return void(this._rszSel=t?.id||null)}if("delroom"===this._tool)return void this._deleteRoomClick(s);if("opening"===this._tool)return void this._openingClick(s);if("merge"===this._tool)return void this._mergeClick(s);if("wallthick"===this._tool)return void this._wallThickClick(s);if("boundary"===this._tool)return void this._boundaryClick(s);if("split"===this._tool)return void this._splitClick(s);if("column"===this._tool)return void this._columnClick(s);this._wallRepairDiagnostic=null;const n=this._resolvePlanDrawPoint(s,t.shiftKey);if(n.ambiguous)return this._planSnapHover={contextKey:n.contextKey,candidate:null,conflicts:n.conflicts},this._syncPlanSnapActiveMarker(null),this._syncPlanSnapConflictMarkers(n.conflicts),void this._showToast(this._t("toast.plan_snap_ambiguous"));let o=n.point;if(t.ctrlKey||t.metaKey){if(t.preventDefault(),this._path.length<3)return;o=[...this._path[0]]}if(!this._path.length){if(!t.shiftKey&&!n.candidate&&this._offerExistingWallFace(s))return;const e=this._draftEndAt(o);return e?(this._activeDraftId=e.draft.id,this._resumeDraftBySpace[this._space]=e.draft.id,this._path=e.reverse?[...e.draft.points].reverse().map(t=>[...t]):e.draft.points.map(t=>[...t]),void(this._draftSegmentCms=this._adoptDraftCms(this._path,e.reverse?[...e.draft.segments].reverse().map(t=>t.cm):e.draft.segments.map(t=>t.cm),e.draft.id))):(this._activeDraftId=null,this._draftSegmentCms=[],void(this._path=[o]))}const r=this._path[this._path.length-1];if(this._samePt(o,r))return;const a=this._draftEndAt(o,this._activeDraftId||void 0);if(a)return void this._mergeDraftEndpoint(a);if(!this._canAppendRoomDraftPoint())return;const l=this._drawWallCm;if(null==l)return void this._showPhysicalRange(100);const c=this._path.map(t=>[...t]);this._path=[...this._path,o],this._draftSegmentCms=[...this._draftSegmentCms,l],this._persistActiveDraftSegment(),this._offerWallFaces(c)}_draftEndAt(t,e){const i=this._spaceModel();if(!i)return null;const s=this._viewOr(this._baseVb()),n=Math.max(.15*this._gridPitch,this._stageEl?.clientWidth?s.w/this._stageEl.clientWidth*12:0);for(const s of i.room_drafts||[]){if(s.id===e)continue;if(s.points.length<2)continue;const i=s.points[0],o=s.points[s.points.length-1];if(Math.hypot(t[0]-o[0],t[1]-o[1])<=n)return{draft:s,reverse:!1};if(Math.hypot(t[0]-i[0],t[1]-i[1])<=n)return{draft:s,reverse:!0}}return null}_mergeDraftEndpoint(t){const e=this._curSpaceCfg;if(!e||!this._path.length)return;const i=this._path.map(t=>[...t]),s=this._wallGraphSources(i),n=Array.isArray(e.room_drafts)?e.room_drafts:[],o=this._activeDraftId?n.find(t=>t.id===this._activeDraftId):null,r=n.find(e=>e.id===t.draft.id);if(!r)return;const a=t.reverse?t.draft.points.map(t=>[...t]):[...t.draft.points].reverse().map(t=>[...t]),l=t.reverse?(r.segments||[]).map(t=>({...t})):[...r.segments||[]].reverse().map(t=>({...t})),c=this._path[this._path.length-1],h=this._samePt(c,a[0]),d=h?null:this._drawWallCm;if(!h&&null==d)return void this._showPhysicalRange(100);const p=this._draftSegmentCms.map((t,e)=>({...o?.segments?.[e]||{},cm:t})),u=[...this._path.map(t=>[...t]),...h?a.slice(1):a],_=[...p,...null==d?[]:[{cm:d}],...l],g=u.length>=4&&this._samePt(u[0],u[u.length-1]),m=u,f=_;if(m.length>500)return void this._showToast(this._t("toast.physical_limit"));const v=(o?.segments?.length||0)+(r.segments?.length||0);if(this._draftSegmentCount(e)-v+f.length>2e3)return void this._showToast(this._t("toast.physical_limit"));if(g){const t=m.slice(0,-1);if(this._contourSelfIntersects(t)||Pi(t)<=1e-6)return void this._showToast(this._t("toast.contour_cannot_close"));const e=this._overlapRoom(t);if(e)return void this._showToast(this._t("toast.room_overlap",{name:e.name||""}))}const y=this._geometrySnapshot(),b=this._activeDraftId||t.draft.id,w={...o||r,id:b,points:m.map(t=>[t[0]/pm,t[1]/pm]),segments:f};e.room_drafts=n.filter(e=>e.id!==t.draft.id&&(!this._activeDraftId||e.id!==this._activeDraftId)),e.room_drafts.push(w),this._activeDraftId=b,this._resumeDraftBySpace[this._space]=b,this._path=m,this._draftSegmentCms=this._adoptDraftCms(m,f.map(t=>Number(t.cm)),b),this._physicalSel=null,this._recordGeometry(this._t("history.draft_merge"),y),this._saveConfig(),null!=d&&this._offerWallFaces(i,i.length-1,s)}_adoptDraftCms(t,e,i){const s=Math.max(0,t.length-1),n=Qd(s,e,this._drawWallCm,fa);return e.length!==s&&console.debug(`[houseplan] draft ${i??"?"}: восстановлено толщин ${s-e.length} (#234)`),n}_persistActiveDraftSegment(){if(this._path.length<2||!this._curSpaceCfg)return;const t=this._geometrySnapshot(),e=this._curSpaceCfg;e.room_drafts||=[],this._activeDraftId||(this._activeDraftId="draft-"+Date.now().toString(36)),this._resumeDraftBySpace[this._space]=this._activeDraftId;const i=e.room_drafts.findIndex(t=>t.id===this._activeDraftId),s={...i>=0?e.room_drafts[i]:{},id:this._activeDraftId,points:this._path.map(t=>[t[0]/pm,t[1]/pm]),segments:this._draftSegmentCms.map((t,s)=>({...i>=0?e.room_drafts[i]?.segments?.[s]:{},cm:t}))};i>=0?e.room_drafts[i]=s:e.room_drafts.push(s),this._recordGeometry(this._t("history.draft_segment"),t),this._saveConfig()}_activeWallSourceKey(t){return`active:${this._activeDraftId||"session"}:${t}`}_wallGraphSources(t){const e=this._planStructuralGeometrySnapshot().value.segments.map(t=>({a:t.a,b:t.b,key:`static:${t.key}`}));for(let i=0;i+1t.key===i);if(s>=0){const[t]=this._wallFaceGraphCache.splice(s,1);return this._wallFaceGraphCache.push(t),t.value}const n=kp(t,e);return this._wallFaceGraphCache.push({key:i,value:n}),this._wallFaceGraphCache.length>4&&this._wallFaceGraphCache.shift(),n}_offerWallFaces(t,e=this._path.length-2,i){if(this._path.length<2||this._wallFaceBatch||this._roomDialog)return;const s=this._spaceModel();if(!s)return;const n=this._activeWallSourceKey(e),o=2e-4*this._gridPitch;let r,a;try{const e=i||this._wallGraphSources(t);a=this._wallGraphSources(this._path),r=function(t,e,i){const s=new Set(t.faces.map(t=>t.key));return e.faces.filter(t=>!s.has(t.key)&&t.sourceKeys.includes(i))}(this._wallFaceGraph(e,o),this._wallFaceGraph(a,o),n)}catch{return}if(!r.length){const t=Fp(a,{requiredSourceKey:n,maxDistance:xa(2,this._cellCm,this._gridPitch),gridStep:this._gridPitch,epsilon:o});return"ambiguous"===t.kind?(this._wallRepairDiagnostic=t.proposals[0]||null,void this._showToast(this._t("toast.wall_repair_ambiguous"))):void("repair"!==t.kind||this._overlapRoom(t.face.ring)||this._beginWallFaceBatch([{...t.face,repair:t.proposal}]))}for(const t of s.rooms){const e=hi(t);if(!t.id||!e)continue;const i=Fi(e,this._path,.02*this._gridPitch);if(!i)continue;const[s,n]=i,o=Pi(s)>=Pi(n)?s:n,a=o===s?n:s,l=[...r].sort((t,e)=>Math.abs(t.area-Pi(a))-Math.abs(e.area-Pi(a))||t.key.localeCompare(e.key))[0];if(!l)return;return void this._beginWallFaceBatch([{...l,ring:a.map(t=>[t[0],t[1]]),split:{roomId:t.id,mainPoly:o,newPoly:a},consumeAllActive:!0}])}const l=r.filter(t=>!(t.ring.length<3||this._contourSelfIntersects(t.ring))&&!this._overlapRoom(t.ring));l.length&&this._beginWallFaceBatch(l)}_beginWallFaceBatch(t){this._wallRepairDiagnostic=null,this._wallFaceBatch={candidates:[...t].sort((t,e)=>t.area-e.area||t.key.localeCompare(e.key)),index:0,decisions:[],activePath:this._path.map(t=>[...t]),activeCms:[...this._draftSegmentCms],activeDraftId:this._activeDraftId},this._clearPlanSnapHover(),this._nameSel="",this._areaSel="",this._resetRoomDialogFields(),this._roomDialog=!0}_offerExistingWallFace(t){if(this._path.length||this._wallFaceBatch||this._roomDialog)return!1;const e=2e-4*this._gridPitch;try{let i,s=xp(this._wallFaceGraph(this._wallGraphSources([]),e),t,e);if(!s){const n=Fp(this._wallGraphSources([]),{point:t,maxDistance:xa(2,this._cellCm,this._gridPitch),gridStep:this._gridPitch,epsilon:e});if("ambiguous"===n.kind)return this._wallRepairDiagnostic=n.proposals[0]||null,this._showToast(this._t("toast.wall_repair_ambiguous")),!0;if("repair"===n.kind)s=n.face,i=n.proposal;else if("none"===n.kind){const i=Fp(this._wallGraphSources([]),{point:t,maxDistance:this._cssPxToRender(12),gridStep:this._gridPitch,epsilon:e});if("repair"===i.kind)return this._wallRepairDiagnostic=i.proposal,this._showToast(this._t("toast.wall_repair_too_large")),!0}}return!(!s||s.ring.length<3||this._contourSelfIntersects(s.ring)||this._overlapRoom(s.ring))&&(this._beginWallFaceBatch([{...s,existing:!i,repair:i}]),!0)}catch{return!1}}_columnClick(t){const e=this._snap(t),i=this._drawWallCm;if(null==i)return void this._showPhysicalRange(Hl);if(!this._curSpaceCfg||this._limitReached("column"))return;const s=this._spaceModel();if(!s)return;const n={id:"column-"+Date.now().toString(36),shape:"square",center:e,cm:Bl(i),angle:0},o=(s.wall_columns||[]).find(t=>rc(t,n,.02*this._gridPitch));if(o)return clearTimeout(this._duplicateColumnTimer),this._duplicateColumnId=o.id,this._duplicateColumnTimer=window.setTimeout(()=>{this._duplicateColumnId=null},900),void this._showToast(this._t("toast.column_duplicate"));const r=this._geometrySnapshot(),a=this._curSpaceCfg;a.wall_columns||=[],a.wall_columns.push({...n,center:[e[0]/pm,e[1]/pm]}),this._recordGeometry(this._t("history.column_add"),r),this._saveConfig()}_openPhysicalDialog(t,e,i){const s=this._spaceModel();if(s)if("partition"===t){const i=s.partitions.find(t=>t.id===e);i&&(this._physicalDialog={kind:t,id:e,cm:ka(i.cm,this._imperial),length:this._fmtLen(i.a,i.b)})}else if("column"===t){const i=s.wall_columns.find(t=>t.id===e);i&&(this._physicalDialog={kind:t,id:e,cm:ka(i.cm,this._imperial),shape:i.shape,angle:this._angleField("square"===i.shape?ql(i.angle):0)})}else{const n=s.room_drafts.find(t=>t.id===e),o=Math.max(0,Math.min(n?.segments.length?n.segments.length-1:0,i||0));n?.segments[o]&&(this._physicalDialog={kind:t,id:e,segment:o,cm:ka(n.segments[o].cm,this._imperial),length:this._fmtLen(n.points[o],n.points[o+1])})}}_physicalDown(t,e,i){const s=this._spaceModel();if(!s)return;t.stopPropagation(),bm(t);const n=this._svgPoint(t),o=[];for(const t of[...s.wall_columns].reverse())nc(n,Kl(t,this._cellCm,this._gridPitch))&&o.push({kind:"column",id:t.id});for(const t of[...s.partitions].reverse()){const e=Vl(t.a,t.b,t.cm,this._cellCm,this._gridPitch);e&&nc(n,e)&&o.push({kind:"partition",id:t.id})}o.some(t=>t.kind===e&&t.id===i)||o.unshift({kind:e,id:i});const r=o.map(t=>`${t.kind}:${t.id}`).sort().join("|"),a=performance.now(),l=this._physicalPickCycle,c=o.length>1&&l?.signature===r&&a-l.at>380&&a-l.at<=1200&&Math.hypot(t.clientX-l.x,t.clientY-l.y)<=10?(l.index+1)%o.length:Math.max(0,o.findIndex(t=>t.kind===e&&t.id===i));this._physicalPickCycle={signature:r,index:c,x:t.clientX,y:t.clientY,at:a},e=o[c].kind,i=o[c].id;const h="partition"===e?s.partitions.find(t=>t.id===i):s.wall_columns.find(t=>t.id===i);h&&(this._physicalSel={kind:e,id:i},this._physicalDrag={pid:t.pointerId,kind:e,id:i,start:this._svgPoint(t),startClient:[t.clientX,t.clientY],before:this._geometrySnapshot(),moved:!1,base:JSON.parse(JSON.stringify(h)),delta:[0,0]})}_clampPhysicalDelta(t,e,i){const s="partition"===t?[e.a,e.b]:[e.center],n=s.map(t=>t[0]),o=s.map(t=>t[1]);return[Math.max(-yc*pm-Math.min(...n),Math.min(yc*pm-Math.max(...n),i[0])),Math.max(-yc*pm-Math.min(...o),Math.min(yc*pm-Math.max(...o),i[1]))]}_physicalMove(t){const e=this._physicalDrag;if(!e||e.pid!==t.pointerId)return;t.stopPropagation();const i=this._svgPoint(t),s="partition"===e.kind?e.base.a:e.base.center,n=this._snap([s[0]+i[0]-e.start[0],s[1]+i[1]-e.start[1]]),o=this._clampPhysicalDelta(e.kind,e.base,[n[0]-s[0],n[1]-s[1]]);this._physicalDrag={...e,delta:o,moved:e.moved||Math.hypot(t.clientX-e.startClient[0],t.clientY-e.startClient[1])>=5}}_physicalUp(t){const e=this._physicalDrag;if(!e||e.pid!==t.pointerId)return;if(t.stopPropagation(),this._physicalDrag=null,!e.moved)return void this._registerPhysicalTap(e.kind,e.id);const i=this._spaceModel();if(!this._curSpaceCfg||!i)return;const s=this._curSpaceCfg;if("partition"===e.kind){const t=(s.partitions||[]).find(t=>t.id===e.id),i=e.base;if(t){const n={...i,a:[i.a[0]+e.delta[0],i.a[1]+e.delta[1]],b:[i.b[0]+e.delta[0],i.b[1]+e.delta[1]]};t.a=[n.a[0]/pm,n.a[1]/pm],t.b=[n.b[0]/pm,n.b[1]/pm];for(const t of s.openings||[]){if("partition"!==t.host?.kind||t.host.id!==e.id)continue;const i=Pd(t,[n],pm,this._cellCm,this._gridPitch).resolved;i&&Object.assign(t,zd(t,i,pm))}}}else{const t=(s.wall_columns||[]).find(t=>t.id===e.id),n=e.base,o={...n,center:[n.center[0]+e.delta[0],n.center[1]+e.delta[1]]};if(i.wall_columns.some(t=>t.id!==e.id&&rc(t,o,.02*this._gridPitch)))return void this._showToast(this._t("toast.column_duplicate"));t&&(t.center=[(n.center[0]+e.delta[0])/pm,(n.center[1]+e.delta[1])/pm])}this._recordGeometry(this._t("history.physical_move"),e.before),this._saveConfig()}_registerPhysicalTap(t,e,i){const s=performance.now(),n=this._physicalLastTap?.kind===t&&this._physicalLastTap.id===e&&this._physicalLastTap.segment===i&&s-this._physicalLastTap.at<=360;this._physicalLastTap={kind:t,id:e,segment:i,at:s},n&&(this._physicalLastTap=null,this._openPhysicalDialog(t,e,i))}_cancelPhysicalGesture(){this._physicalDrag=null,this._physicalRotate=null,this.requestUpdate()}_physicalRotateDown(t,e){if("square"!==e.shape||!this._spaceModel())return;t.preventDefault(),t.stopPropagation(),bm(t);const i=this._svgPoint(t);this._physicalSel={kind:"column",id:e.id},this._physicalRotate={pid:t.pointerId,id:e.id,center:[...e.center],startAngle:180*Math.atan2(i[1]-e.center[1],i[0]-e.center[0])/Math.PI,baseAngle:ql(e.angle),angle:ql(e.angle),before:this._geometrySnapshot(),moved:!1}}_physicalRotateMove(t){const e=this._physicalRotate;if(!e||e.pid!==t.pointerId)return;t.preventDefault(),t.stopPropagation();const i=this._svgPoint(t),s=180*Math.atan2(i[1]-e.center[1],i[0]-e.center[0])/Math.PI,n=e.baseAngle+s-e.startAngle,o=ql(t.shiftKey?n:5*Math.round(n/5));this._physicalRotate={...e,angle:o,moved:e.moved||Math.abs(n-e.baseAngle)>=.5}}_physicalRotateUp(t){const e=this._physicalRotate;if(!e||e.pid!==t.pointerId)return;t.preventDefault(),t.stopPropagation(),this._physicalRotate=null;const i=this._spaceModel();if(!e.moved||!this._curSpaceCfg||!i)return;const s=i.wall_columns.find(t=>t.id===e.id);if(!s||"square"!==s.shape)return;const n={...s,angle:e.angle};if(i.wall_columns.some(t=>t.id!==e.id&&rc(t,n,.02*this._gridPitch)))return void this._showToast(this._t("toast.column_duplicate"));const o=this._curSpaceCfg.wall_columns?.find(t=>t.id===e.id);o&&(o.angle=e.angle,this._recordGeometry(this._t("history.physical_edit"),e.before),this._saveConfig())}_rszRooms(){const t=[],e=this._spaceModel();if(!e)return t;for(const i of e.rooms){const e=i.id?hi(i):null;e&&t.push({id:i.id,poly:e})}return t}_rszOpenings(){return this._openingsR.map(t=>({id:t.id,x:t.rx,y:t.ry,length:t.rlen}))}_rszOpts(){return{minDim:this._cmToUnits(30),eps:.05*this._gridPitch}}_rszSnapshot(){return JSON.stringify(this._geometrySnapshot()||{spaceId:this._space,rooms:[],openings:[],walls:[],open_spans:[]})}_rszApplyPreview(t,e){const i=this._rszDrag,s=this._serverCfg?.spaces.find(t=>t.id===this._space);if(!i||!s)return;const n=JSON.parse(i.snap),o={...s,rooms:n.rooms,openings:n.openings,walls:n.walls,open_spans:n.open_spans};Array.isArray(n.open_spans)&&n.open_spans.length||delete o.open_spans;const r=this._spaceH;for(const[e,i]of Object.entries(t)){const t=o.rooms.find(t=>t.id===e);t&&(t.poly=i.map(t=>[t[0]/pm,t[1]/r]),delete t.x,delete t.y,delete t.w,delete t.h)}for(const[t,i]of Object.entries(e)){const e=(o.openings||[]).find(e=>e.id===t);e&&(e.x=i[0]/pm,e.y=i[1]/r)}const a=[],l=[];for(const t of i.changed){const e=i.rooms.find(e=>e.id===t),s=o.rooms.find(e=>e.id===t);if(!e||!s?.poly)continue;const n=s.poly.map(t=>[t[0]*pm,t[1]*r]);if(e.poly.length===n.length)for(let t=0;tt.id===e);if(!s||!s.poly||s.poly.length<3)return null;if(i<0||i>=s.poly.length)return null;const n=[...s.poly[i]],o=[...s.poly[(i+1)%s.poly.length]];return{roomId:e,edge:i,a:n,b:o,n:fr(s.poly,i)}}(s,e,i);n&&(this._rszDrag={kind:"edge",pid:t.pointerId,roomId:e,plan:n,rooms:s,openings:this._rszOpenings(),snap:this._rszSnapshot(),moved:!1,d:0,k:1,changed:[]})}_rszCornerDown(t,e,i,s){"resize"!==this._tool||this._rszDrag||(t.stopPropagation(),t.preventDefault(),bm(t),this._rszDrag={kind:"scale",pid:t.pointerId,roomId:e,fixed:s,span0:Math.hypot(i[0]-s[0],i[1]-s[1])||1,rooms:this._rszRooms(),openings:this._rszOpenings(),snap:this._rszSnapshot(),moved:!1,d:0,k:1,changed:[]})}_rszMove(t){const e=this._rszDrag;if(!e||e.pid!==t.pointerId)return;t.stopPropagation();const i=this._svgPoint(t);if("edge"===e.kind){const t=e.plan,s=(i[0]-t.a[0])*t.n[0]+(i[1]-t.a[1])*t.n[1],n=this._snap([t.a[0]+t.n[0]*s,t.a[1]+t.n[1]*s]);let o=(n[0]-t.a[0])*t.n[0]+(n[1]-t.a[1])*t.n[1];if(o=function(t,e,i,s,n,o){if(!Number.isFinite(s)||Math.abs(s)<1e-9)return 0;const r=Math.sign(s);let a=Math.abs(s);const l=Math.max(n,1e-6);for(let s=0;s<4096&&a>1e-9;s++,a-=l){const s=r*a;if(Dr(t,e,i,s,o))return s}return 0}(e.rooms,e.openings,t,o,this._gridPitch,this._rszOpts()),o===e.d&&e.moved)return;e.d=o,e.moved=!0;const r=Sr(e.rooms,e.openings,t,o,this._rszOpts().eps);e.changed=Object.keys(r.polys),this._rszApplyPreview(r.polys,r.openings),this._rszLive=this._rszEdgeLabels(r,t)}else{const t=e.fixed,s=this._snap(i);let n=Math.hypot(s[0]-t[0],s[1]-t[1])/(e.span0||1);if(n=Math.max(.05,Math.min(20,n)),n=function(t,e,i,s,n,o){if(!Number.isFinite(n)||n<=0)return 1;if(Pr(t,e,i,s,n,o))return n;let r=1,a=n;for(let n=0;n<28;n++){const n=(r+a)/2;Pr(t,e,i,s,n,o)?r=n:a=n}return r}(e.rooms,e.openings,e.roomId,t,n,this._rszOpts()),n===e.k&&e.moved)return;e.k=n,e.moved=!0;const o=e.rooms.find(t=>t.id===e.roomId),r=e.rooms.filter(t=>t.id!==e.roomId).map(t=>t.poly),a=Tr(o,e.openings,r,t,n,2*this._rszOpts().eps);e.changed=[e.roomId],this._rszApplyPreview({[e.roomId]:a.poly},a.openings),this._rszLive=this._rszScaleLabels(a.poly)}this.requestUpdate()}_rszUp(t){const e=this._rszDrag;if(!e||e.pid!==t.pointerId)return;t.stopPropagation();const i=this._rszPreview;this._rszDrag=null,this._rszLive=null,this._rszPreview=null;if(!(e.moved&&("edge"===e.kind?Math.abs(e.d)>1e-9:Math.abs(e.k-1)>1e-9))||!i)return this._cfgEpoch++,void this.requestUpdate();const s=JSON.parse(e.snap),n=this._curSpaceCfg;if(n){n.rooms=i.sp.rooms,n.openings=i.sp.openings,Array.isArray(i.sp.walls)&&(i.sp.walls.length?n.walls=i.sp.walls:delete n.walls),Array.isArray(i.sp.open_spans)&&i.sp.open_spans.length?n.open_spans=i.sp.open_spans:delete n.open_spans;for(const t of e.changed){const e=n.rooms.find(e=>e.id===t);e?.poly&&(e.poly=wr(e.poly,1e-9))}this._commitOpenSpans(),Array.isArray(n.walls)&&n.walls.length&&(n.walls=Ea(n.walls,n.rooms||[],xc,1,this._cfgOpenCuts()),n.walls.length||delete n.walls)}this._suppressClick=!0,setTimeout(()=>this._suppressClick=!1,0),this._recordGeometry(this._t("history.resize_room"),s),this._saveConfig(),this.requestUpdate()}_rszCancelDrag(){this._rszDrag&&(this._rszDrag=null,this._rszLive=null,this._rszPreview=null,this._cfgEpoch++,this.requestUpdate())}_rszPointerCancel(t){const e=this._rszDrag;e&&e.pid===t.pointerId&&(t.stopPropagation(),this._rszCancelDrag())}_rszEdgeLabels(t,e){const i=this._rszDrag,s=[],n=t.polys[e.roomId]||i.rooms.find(t=>t.id===e.roomId).poly,o=n.length,r=e.edge,a=(r+1)%o,l=this._rszInnerSpanCms(e.roomId,n,t.polys);for(const t of[(r-1+o)%o,r,a]){const e=n[t],i=n[(t+1)%o],r=l?.[t];s.push({x:(e[0]+i[0])/2,y:(e[1]+i[1])/2,text:null==r?this._fmtLen(e,i):li(r,"mi"===this.hass?.config?.unit_system?.length)})}const c="mi"===this.hass?.config?.unit_system?.length,h=Object.keys(t.polys).length?Object.keys(t.polys):[e.roomId],d=this._spaceWalls,p=this._openPairs().flatMap(t=>t.segs),u=this._physicalBodiesR();for(const e of h){const n=t.polys[e]||i.rooms.find(t=>t.id===e).poly,o=d.length&&ml(Object.entries(t.polys).map(([t,e])=>({id:t,poly:e})),e,d,p,this._wallKeyPitch,this._cellCm,this._gridPitch,pm)||n,r=$i(o),a=u.length?ic(ec(o,u))*Math.pow(this._cellCm/this._gridPitch,2)/1e4:Rr(o,this._gridPitch,this._cellCm);s.push({x:r[0],y:r[1],text:Ir(a,c),area:!0})}return s}_rszInnerSpanCms(t,e,i){const s=Object.keys(i).length?Object.entries(i).map(([t,e])=>({id:t,poly:e})):this._spaceModel()?.rooms;if(!s?.length)return null;const n=this._spaceWalls;if(!n.length)return null;const o=function(t,e,i,s,n,o,r,a=1){const l=(t||[]).find(t=>t?.id===e),c=hi(l);if(!c||c.length<3)return null;const h=hl(t,e,i,s,n,o,r,a);if(!h)return c.map(()=>0);const d=4*Ka(n,a);return c.map((t,e)=>{const i=c[(e+1)%c.length],s=[(t[0]+i[0])/2,(t[1]+i[1])/2];for(let t=0;tt.segs),this._wallKeyPitch,this._cellCm,this._gridPitch,pm);if(!o||o.length!==e.length)return null;const r=this._cellCm/this._gridPitch;return e.map((t,i)=>function(t,e,i){const s=t?.length||0;if(s<3||!Array.isArray(i)||i.length!==s)return 0;const n=(Math.trunc(e)%s+s)%s,o=t[n],r=t[(n+1)%s],a=r[0]-o[0],l=r[1]-o[1],c=Math.hypot(a,l);if(!(c>0))return 0;const h=Math.max(0,Number(i[n])||0);if(!(h>0))return c;const d=[a/c,l/c],p=Xa(t,n),u=[o[0]+p[0]*h,o[1]+p[1]*h],_=e=>{const n=Math.max(0,Number(i[e])||0);if(!(n>0))return null;const r=t[e],a=t[(e+1)%s],l=a[0]-r[0],c=a[1]-r[1],h=Math.hypot(l,c);if(!(h>0))return null;const p=Xa(t,e),_=Za(u,d,[r[0]+p[0]*n,r[1]+p[1]*n],[l/h,c/h]);return _?(_[0]-o[0])*d[0]+(_[1]-o[1])*d[1]:null},g=_((n-1+s)%s)??0,m=(_((n+1)%s)??c)-g;return m>0?m:0}(e,i,o)*r)}_rszScaleLabels(t){const e="mi"===this.hass?.config?.unit_system?.length,i=t.map(t=>t[0]),s=t.map(t=>t[1]),n=this._spaceWalls,o=n.length&&this._rszSel&&ml([{id:this._rszSel,poly:t}],this._rszSel,n,[],this._wallKeyPitch,this._cellCm,this._gridPitch,pm)||t,r=$i(o),a=this._physicalBodiesR(),l=a.length?ic(ec(o,a))*Math.pow(this._cellCm/this._gridPitch,2)/1e4:Rr(o,this._gridPitch,this._cellCm),c=o.map(t=>t[0]),h=o.map(t=>t[1]),d=Math.max(...c)-Math.min(...c),p=Math.max(...h)-Math.min(...h);return[{x:Math.min(...i),y:Math.min(...s),text:`${this._fmtLen([0,0],[d,0])} × ${this._fmtLen([0,0],[p,0])}`},{x:r[0],y:r[1],text:Ir(l,e),area:!0}]}_renderResizeLayer(t){const e=Math.max(.013*t.w,5),i=e/2,s=t=>t.toFixed(1),n=`M ${s(-.7*i)} 0 H ${s(.7*i)} M 0 ${s(-.22*i)} V ${s(-i)} M ${s(-.32*i)} ${s(-.6*i)} L 0 ${s(-i)} L ${s(.32*i)} ${s(-.6*i)} M 0 ${s(.22*i)} V ${s(i)} M ${s(-.32*i)} ${s(.6*i)} L 0 ${s(i)} L ${s(.32*i)} ${s(.6*i)}`,o=[],r=this._rszRooms();for(const t of r)for(let i=0;i + `}_stageAspect(){const t=this._stageEl,e=this._baseVb();return t&&t.clientHeight?t.clientWidth/t.clientHeight:e[2]/e[3]}_viewOr(t){return this._view&&this._view.w?this._view:Oi(t,this._stageAspect())}_roomLabelReferenceViewWidth(t){if(!this._markup)return t.w;const e=this._stageEl,i=this.renderRoot.querySelector(".editorchrome");if(!e||e.clientWidth<=0||e.clientHeight<=0)return t.w;const s=e.clientHeight+(i?.getBoundingClientRect().height||0);return s<=0?t.w:this._viewForModeTarget(this._zoom,void 0,void 0,e.clientWidth,s).w}_screenToVb(t,e){const i=this._stageEl,s=this._viewOr(this._baseVb()),n=i?.clientWidth||1,o=i?.clientHeight||1;return[s.x+t/n*s.w,s.y+e/o*s.h]}_clampView(t,e){const i=(t,e,i,s)=>{const n=1*Math.max(e,s),o=i-n,a=i+s-e+n;return Math.max(Math.min(o,a),Math.min(Math.max(o,a),t))};return{w:t.w,h:t.h,x:i(t.x,t.w,e.x,e.w),y:i(t.y,t.h,e.y,e.h)}}_applyView(t,e,i){const s=this._baseVb(),n=Oi(s,this._stageAspect()),o=Math.min(km.ZOOM_MAX,Math.max(km.ZOOM_MIN,t)),a=n.w/o,r=n.h/o,l=this._viewOr(s),c=e??l.x+l.w/2,h=i??l.y+l.h/2,d=this._clampView({x:c-a/2,y:h-r/2,w:a,h:r},n);return!(this._view&&Math.abs(this._zoom-o)<1e-9&&Math.abs(this._view.x-d.x)<1e-6&&Math.abs(this._view.y-d.y)<1e-6&&Math.abs(this._view.w-d.w)<1e-6&&Math.abs(this._view.h-d.h)<1e-6)&&("opening"===this._tool&&(this._cursorPt=null,this._clearOpeningPlacement(!1)),this._zoom=o,this._view=d,!0)}_bootWatch(){clearTimeout(this._bootTimer),this._bootStart=Date.now(),this._bootLastH=-1,this._bootLastChange=this._bootStart;const t=()=>{if(!this._booting)return;const e=Date.now(),i=this._stageEl?this._stageEl.clientHeight:0;i!==this._bootLastH&&(this._bootLastH=i,this._bootLastChange=e);const s=e-this._bootStart;s>=1200||s>=700&&i>0&&e-this._bootLastChange>=250?this._bootSettled():this._bootTimer=window.setTimeout(t,100)};this._bootTimer=window.setTimeout(t,100)}_bootSettled(){this._booting&&!this._bootSettling&&(this._bootSettling=!0,this._refitView(),this._bootSettleRaf=requestAnimationFrame(()=>{this._bootSettleRaf=0,this._finishBootSettled()}))}_finishBootSettled(){if(!this._booting)return;this._refitView(),this._booting=!1,this._bootSettling=!1;const t=this._stageEl?.clientHeight??0;!this._config?.kiosk&&t>0&&this._warmPatch({hdrH:this._hdrH,stageH:t,vp:this._warmViewportState()},!0),this._bootFading=!0,this._bootTimer=window.setTimeout(()=>{this._bootFading=!1},220),this._bootSoft=!0,clearTimeout(this._bootSoftTimer),this._bootSoftTimer=window.setTimeout(()=>{this._bootSoft=!1},Zg)}_bootSoftCancel(){this._bootSoft&&(clearTimeout(this._bootSoftTimer),this._bootSoft=!1)}_beginResumeSettle(){this._booting||this._resumeSettling||(this._modeTransitionPreparing?this._modeTransitionForceAtomic=!0:this._cancelModeTransition(!0),this._viewportInvalidAt=0,this._beginContinuityCandidate("warm-resume",!1),this._loading?this.requestUpdate():this._loadFromServer())}_refitView(){if(this._modeTransitionBusy)return;const t=this._stageEl;if(!t||"visible"!==document.visibilityState||t.clientWidth<=0||t.clientHeight<=0)return void(this._viewportInvalidAt||(this._viewportInvalidAt=Date.now()));const e=[t.clientWidth,t.clientHeight],i=this._lastValidStageSize,s=!!i&&Math.abs(i[0]-e[0])<=.5&&Math.abs(i[1]-e[1])<=.5,n=this._viewportInvalidAt?Date.now()-this._viewportInvalidAt:0;if(this._viewportInvalidAt=0,!i)return this._lastValidStageSize=e,void(this._view||this._applyView(this._zoom));s?this._pendingRefitSize=null:(this._pendingRefitSize=e,this._refitRaf||(this._refitRaf=requestAnimationFrame(()=>{this._refitRaf=0;const t=this._pendingRefitSize;this._pendingRefitSize=null;const e=this._stageEl;if(!t||!e||e.clientWidth<=0||e.clientHeight<=0)return;if(Math.abs(e.clientWidth-t[0])>.5||Math.abs(e.clientHeight-t[1])>.5)return void this._refitView();const i=this._lastValidStageSize;if(i&&Math.abs(i[0]-t[0])<=.5&&Math.abs(i[1]-t[1])<=.5)return;this._lastValidStageSize=t;const s=this._view;n>=kh?this._beginContinuityCandidate("stage-size-restored",!0,"stage-size"):this._continuity.hasCompleteFrame&&this._beginContinuityCandidate("stage-resize",!0,"stage-size"),this._applyView(this._zoom,s?s.x+s.w/2:void 0,s?s.y+s.h/2:void 0)})))}_zoomAt(t,e,i){const s=this._stageEl;if(!s)return;const n=Oi(this._baseVb(),this._stageAspect()),o=Math.min(km.ZOOM_MAX,Math.max(km.ZOOM_MIN,i));"opening"===this._tool&&(this._cursorPt=null,this._clearOpeningPlacement(!1));const a=s.clientWidth,r=s.clientHeight,l=this._screenToVb(t,e),c=n.w/o,h=n.h/o;this._zoom=o,this._view=this._clampView({x:l[0]-t/a*c,y:l[1]-e/r*h,w:c,h:h},n)}_onWheel(t){const e=this._stageEl;if(!e)return;t.preventDefault();const i=e.getBoundingClientRect(),s=t.deltaY<0?1.15:1/1.15;this._zoomAt(t.clientX-i.left,t.clientY-i.top,this._zoom*s),this._saveZoom()}_stepZoom(t){const e=this._stageEl;e&&(this._zoomAt(e.clientWidth/2,e.clientHeight/2,this._zoom*(t>0?1.4:1/1.4)),this._saveZoom())}_resetZoom(){const t=this._baseVb();"opening"===this._tool&&(this._cursorPt=null,this._clearOpeningPlacement(!1)),this._zoom=1,this._view=Oi(t,this._stageAspect()),this._saveZoom()}_saveZoom(){if("view"===this._mode){this._zoomBySpace={...this._zoomBySpace,[this._space]:this._zoom};try{localStorage.setItem(lm,JSON.stringify(this._zoomBySpace))}catch{}}}_restoreZoom(){const t=this._zoomBySpace[this._space]||1;this._zoom=t;const e=this._stageEl;if(e&&e.clientHeight){const e=this._baseVb();return this._applyView(t,e[0]+e[2]/2,e[1]+e[3]/2),void this.requestUpdate()}this._view=null,requestAnimationFrame(()=>{if(!this._stageEl)return;const e=this._baseVb();this._applyView(t,e[0]+e[2]/2,e[1]+e[3]/2),this.requestUpdate()})}_stagePointerDown(t){if(this._vacFit)return;if(this._kiosk&&(this._cyclePausedUntil=Date.now()+6e4,0===this._pointers.size?(this._swipeStart={x:t.clientX,y:t.clientY,id:t.pointerId},t.target.closest?.(".dev, .roomlabel, .oplock")||(clearTimeout(this._kioskHoldTimer),this._kioskHoldTimer=window.setTimeout(()=>{this._kioskDialog=!0,this._swipeStart=null},3e3))):(this._swipeStart=null,clearTimeout(this._kioskHoldTimer))),this._drag)return;if(this._markup&&t.target.closest?.(".roomlabel, .rlhandle, .rszhandle, .dev, .oplock, .op-hit, button"))return;if("devices"===this._mode&&t.target.closest(".dev"))return;if("decor"===this._mode&&this._decorPointerDown(t))return;this._pointers.set(t.pointerId,{x:t.clientX,y:t.clientY});const e=this._viewOr(this._baseVb());if(1===this._pointers.size)this._panStart={sx:t.clientX,sy:t.clientY,vx:e.x,vy:e.y},this._panLock=null,this._suppressClick=!1;else if(2===this._pointers.size){this._cancelBoundaryAnchor(),"opening"===this._tool?(this._cursorPt=null,this._clearOpeningPlacement(!1)):"draw"===this._tool&&this._clearPlanSnapHover();const t=[...this._pointers.values()],e=Math.hypot(t[0].x-t[1].x,t[0].y-t[1].y);this._pinchStart={dist:e,zoom:this._zoom},this._panStart=null,this._panLock=null}}get _swipeZone(){return!this._hasFixedFloor&&this._kiosk&&this._zoom<=1.001&&this._model.length>1}_stagePointerMove(t){if(this._physicalRotate?.pid!==t.pointerId)if(this._physicalDrag?.pid!==t.pointerId)if(this._dtDrag?.pid!==t.pointerId)if(this._bdDrag?.pid!==t.pointerId){if(this._decorDraft?.pid===t.pointerId){const e=this._decorDraft;let i=this._decorSnap(this._svgPoint(t),t.pointerType);if(t.shiftKey&&("rect"===e.kind||"ellipse"===e.kind)){const t=i[0]-e.a[0],s=i[1]-e.a[1],n=Math.max(Math.abs(t),Math.abs(s));i=this._snap([e.a[0]+(t<0?-n:n),e.a[1]+(s<0?-n:n)])}return void(this._decorDraft={...e,b:i})}if(this._decorMove?.pid!==t.pointerId)if(this._pointers.has(t.pointerId)){if(this._pointers.set(t.pointerId,{x:t.clientX,y:t.clientY}),this._markup&&1===this._pointers.size&&this._markupMove(t),this._pinchStart&&this._pointers.size>=2){"opening"===this._tool?(this._cursorPt=null,this._clearOpeningPlacement(!1)):"draw"===this._tool&&this._clearPlanSnapHover();const t=[...this._pointers.values()],e=Math.hypot(t[0].x-t[1].x,t[0].y-t[1].y)/(this._pinchStart.dist||1),i=this._stageEl.getBoundingClientRect(),s=(t[0].x+t[1].x)/2-i.left,n=(t[0].y+t[1].y)/2-i.top;this._zoomAt(s,n,this._pinchStart.zoom*e),this._suppressClick=!0,this._saveZoom()}else if(this._panStart){const e=t.clientX-this._panStart.sx,i=t.clientY-this._panStart.sy;Math.abs(e)+Math.abs(i)>4&&(this._suppressClick=!0,clearTimeout(this._holdTimer),"opening"===this._tool?(this._cursorPt=null,this._clearOpeningPlacement(!1)):"draw"===this._tool&&this._clearPlanSnapHover()),null===this._panLock&&Math.abs(e)+Math.abs(i)>8&&(this._panLock=this._swipeZone&&Math.abs(e)>1.5*Math.abs(i)?"swipe":"pan");const s=this._stageEl;if("pan"===this._panLock&&s){const t=this._baseVb(),n=this._viewOr(t),o=Oi(t,this._stageAspect());this._view=this._clampView({x:this._panStart.vx-e/(s.clientWidth||1)*n.w,y:this._panStart.vy-i/(s.clientHeight||1)*n.h,w:n.w,h:n.h},o)}}}else this._markupMove(t);else this._decorMoveUpdate(t)}else this._bdMove(t);else this._dtMove(t);else this._physicalMove(t);else this._physicalRotateMove(t)}_stagePointerLeave(t){this._markup&&("opening"===this._tool?(this._cursorPt=null,this._clearOpeningPlacement(!1)):"draw"===this._tool&&this._clearPlanSnapHover())}_stagePointerUp(t){if(this._kiosk){clearTimeout(this._kioskHoldTimer);const e=this._swipeStart;if(this._swipeStart=null,e&&e.id===t.pointerId){const i=t.clientX-e.x,s=t.clientY-e.y;if(Math.abs(i)+Math.abs(s)<8){const t=Date.now();t-this._lastTap<350&&this._resetZoom(),this._lastTap=t}const n="pan"===this._panLock?null:function(t,e,i,s,n,o=60){if(i>1.001||s.length<2)return null;if(Math.abs(t)t.id),this._space);n&&this._slideTo(n,i<0?"left":"right")&&(this._saveNav(),this._suppressClick=!0,setTimeout(()=>this._suppressClick=!1,0),this._showKioskDots())}}if(this._physicalDrag?.pid===t.pointerId)return void this._physicalUp(t);if(this._physicalRotate?.pid===t.pointerId)return void this._physicalRotateUp(t);if(this._dtDrag?.pid===t.pointerId)return void this._dtUp();if(this._bdDrag?.pid===t.pointerId)return void this._bdUp();if(this._decorDraft?.pid===t.pointerId)return void this._decorCommitDraft();if(this._decorMove?.pid===t.pointerId)return this._decorMove.moved&&(this._recordGeometry(this._t("history.decor_move"),this._decorMove.before),this._saveConfig()),void(this._decorMove=null);const e=!!this._pinchStart||!!this._panStart;this._pointers.delete(t.pointerId),this._pointers.size<2&&(this._pinchStart=null),0===this._pointers.size&&(this._panStart=null,this._panLock=null,setTimeout(()=>this._suppressClick=!1,0)),e&&0===this._pointers.size&&this.requestUpdate()}_clickRoom(t){!this._suppressClick&&t.area&&ym("/config/areas/area/"+t.area)}_pointerDown(t,e){if("plan"===this._mode)return;if("view"===this._mode){this._holdFired=!1,clearTimeout(this._holdTimer);const i=t.pointerId,s=t.currentTarget;return void(this._holdTimer=window.setTimeout(()=>{this._holdFired=!0,this._interruptViewGesture(i,s),this._infoCard=e},600))}if("ha_disabled"===e.bindingStatus?.kind)return;t.preventDefault();const i=this._pos(e);this._drag={id:e.id,sx:t.clientX,sy:t.clientY,ox:i.x,oy:i.y,moved:!1},wm(t),this._tip=null}_pointerMove(t,e){if(!this._drag||this._drag.id!==e.id)return;const i=this.renderRoot.querySelector(".stage");if(!i)return;const s=this._baseVb(),n=i.getBoundingClientRect(),o=this._viewOr(s),a=(t.clientX-this._drag.sx)/n.width*o.w,r=(t.clientY-this._drag.sy)/n.height*o.h;Math.abs(t.clientX-this._drag.sx)+Math.abs(t.clientY-this._drag.sy)>3&&(this._drag.moved=!0,clearTimeout(this._holdTimer));const l=Cc(this._drag.ox+a),c=Cc(this._drag.oy+r);this._savePos(e,l,c)}_pointerUp(t,e){if(clearTimeout(this._holdTimer),!this._drag||this._drag.id!==e.id)return;const i=this._drag.moved;this._drag=i?this._drag:null,i&&(this._selId=e.id,window.setTimeout(()=>this._drag=null,0))}_showToast(t){for(const t of this.renderRoot.querySelectorAll("hp-dialog"))t.closeTransientOverlays("toast");this._toast=t,clearTimeout(this._toastTimer),this._toastTimer=window.setTimeout(()=>{this._toast=""},3500)}_syncPointerHoverTargets(){const t=this._pointerModality.hoverEnabled;for(const e of this.renderRoot.querySelectorAll(pm))e.toggleAttribute("data-pointer-hover",t)}_syncPointerHoverSubtree(t){if(t.nodeType!==Node.ELEMENT_NODE)return;const e=t,i=this._pointerModality.hoverEnabled;e.matches(pm)&&e.toggleAttribute("data-pointer-hover",i);for(const t of e.querySelectorAll(pm))t.toggleAttribute("data-pointer-hover",i)}_clearTransientHover(t=!1){t&&this._pointerModality.suspend(),this._tip&&(this._tip=null),this._hoverRoom&&(this._hoverRoom=null)}_notePointer(t){this._boundaryPointerType=t.pointerType||"mouse";const e=this._pointerModality.modality,i=this._pointerModality.note(t);"touch"!==i&&"pen"!==i||e===i&&!this._tip&&!this._hoverRoom||this._clearTransientHover()}_guardTouchGesture(t){if(this._editorSecondary.handleOutsideDismiss(t))return;if("click"===t.type){if(!this._suppressClick&&!this._touchSequenceMultitouch&&Date.now()>this._touchClickBlockUntil)return;return t.preventDefault(),void t.stopImmediatePropagation()}const e=t;if(this._notePointer(e),"touch"===e.pointerType)if("pointerdown"!==t.type){if("pointermove"===t.type){const t=this._touchContacts.get(e.pointerId);if(!t)return;const i={...t,x:e.clientX,y:e.clientY};if(this._touchContacts.set(e.pointerId,i),this._touchSequenceMultitouch&&"view"===this._mode&&!this._vacFit&&this._pinchStart&&[...this._touchContacts.values()].every(t=>t.inStage)){this._pointers.set(e.pointerId,{x:e.clientX,y:e.clientY});const t=[...this._touchContacts.values()];if(t.length>=2&&this._stageEl){const[e,i]=t,s=Math.hypot(e.x-i.x,e.y-i.y)/(this._pinchStart.dist||1),n=this._stageEl.getBoundingClientRect();this._zoomAt((e.x+i.x)/2-n.left,(e.y+i.y)/2-n.top,this._pinchStart.zoom*s),this._saveZoom()}}return}if("pointerup"===t.type||"pointercancel"===t.type||"lostpointercapture"===t.type){if(this._clearTransientHover(),this._touchContacts.delete(e.pointerId),this._touchSequenceMultitouch){if(this._touchClickBlockUntil=Date.now()+500,this._pointers.delete(e.pointerId),!this._vacFit&&this._pointers.size>=2){const[t,e]=[...this._pointers.values()];this._pinchStart={dist:Math.hypot(t.x-e.x,t.y-e.y),zoom:this._zoom}}else this._pinchStart=null;0===this._pointers.size&&(this._panStart=null,this._panLock=null)}0===this._touchContacts.size&&(this._touchSequenceMultitouch=!1)}}else if(this._touchContacts.set(e.pointerId,{x:e.clientX,y:e.clientY,inStage:!!e.target?.closest?.(".stage")}),this._touchContacts.size>=2){this._clearTransientHover(),this._touchSequenceMultitouch=!0,this._touchClickBlockUntil=Number.POSITIVE_INFINITY,clearTimeout(this._holdTimer),clearTimeout(this._kioskHoldTimer),this._swipeStart=null;const t=[...this._touchContacts.values()];if("view"===this._mode&&!this._vacFit&&t.every(t=>t.inStage)){this._pointers=new Map([...this._touchContacts].map(([t,e])=>[t,{x:e.x,y:e.y}]));const[e,i]=t;this._pinchStart={dist:Math.hypot(e.x-i.x,e.y-i.y),zoom:this._zoom},this._panStart=null,this._panLock=null}else this._vacFit&&(this._pointers.clear(),this._pinchStart=null,this._panStart=null,this._panLock=null)}}_showTip(t,e,i,s,n,o){this._notePointer(t),this._pointerModality.hoverEnabled&&(this._drag||(this._tip={x:t.clientX,y:t.clientY,title:e,meta:i,lqi:s,temp:n,hum:o}))}get _gridPitch(){return xc}get _cellCm(){const t=Number(this._curSpaceCfg?.cell_cm);return Number.isFinite(t)&&t>0?t:5}_fmtLen(t,e){const i=function(t,e,i,s){return Math.hypot(e[0]-t[0],e[1]-t[1])/i*s}(t,e,this._gridPitch,this._cellCm);return li(i,"mi"===this.hass?.config?.unit_system?.length)}get _curSpaceCfg(){const t=this._rszPreview;return t&&t.space===this._space?t.sp:this._serverCfg?.spaces.find(t=>t.id===this._space)}get _renderCfg(){const t=this._rszPreview;return t&&this._serverCfg?{...this._serverCfg,spaces:this._serverCfg.spaces.map(e=>e.id===t.space?t.sp:e)}:this._serverCfg}get _spaceH(){return this._curSpaceCfg,um}get _segments(){const t=this._curSpaceCfg,e=this._spaceH;return pi(t?.rooms||[]).map(t=>[t[0]*um,t[1]*e,t[2]*um,t[3]*e])}_savedNav(){if(this._hasFixedFloor)return null;try{return JSON.parse(localStorage.getItem(cm)||"null")}catch{return null}}_saveNav(){if(!this._hasFixedFloor)try{localStorage.setItem(cm,JSON.stringify({space:this._space}))}catch{}}_leaveCardRoute(){if(this._routeDepartureHandled)return;this._routeDepartureHandled=!0,"view"!==this._mode&&this._setMode("view",!1),this._pendingNavMode=null,this._geometryHistory.clear(),this._activeDraftId=null,this._resumeDraftBySpace={},this._draftSegmentCms=[],this._closingWallCm=null,this._drawWallField=null,this._showHidden=!1,this._tapConfirm=null,this._vacCalConfirm=null,this._decorEraseConfirm=null,this._openingInfo=null,this._closeInfoCard(),this._rulesDialog=null,this._alignDialog=null,this._backupImportDialog=null,this._backupExportDialog=null,this._settingsDialog=null,this._markerDialog=null,this._openingDialog=null,this._physicalDialog=null,this._wallDialog=null,this._backdropDialog=null,this._decorShapeDialog=null,this._decorTextDialog=null,this._mergeDialog=null,this._roomDialog=!1,this._spaceDialog=null,this._importDialog=null;const t=this._warmSlot;t?.owner===this._warmGen&&(t.vp=this._warmViewportState(),t.dlg=null,t.frameFingerprint="",clearTimeout(t.evict),t.evict=0),this._saveNav()}_setMode(t,e=!0){this._endTabDrag(),this._pendingNavMode=null;const i=this._spaceModel();if(!i)return this._cancelModeTransition(!1),void(this._mode="view");if(this._kiosk&&"view"!==t)return;if(this._mode===t){if(!e&&"view"===t&&this._modeTransitionBusy){const e=this._currentModeVisual(t),i=this._modeTransitionTargetZoom,s=this._modeTransitionTargetCenterX,n=this._modeTransitionTargetCenterY;this._cancelModeTransition(!1),this._commitViewModeAtomic(e,i,s,n)}return}if(this._bootSoftCancel(),("plan"===t||"decor"===t)&&!this._norm)return void this._showToast(this._t("toast.markup_needs_server"));if(this._wallFaceBatch&&this._roomDialogCancel(),"plan"===this._mode&&"draw"===this._tool&&!this._finishWallChain())return;this._clearTransientHover(!0),this._cancelDevicePressFeedback();const s=this._mode,n=this._effectiveProjection(),o=this._currentModeVisual(s),a=this._modeTransitionBusy,r=o&&"view"!==s&&"view"!==t?{...o,toolbarContentOpacity:this._reducedMotion?1:.35}:o;this._cancelModeTransition(!1),this._editorSecondary.closeForNavigation(),(this._decorMove||this._dtDrag||this._bdDrag)&&this._cancelDecorGesture();const l=!i.bg&&"view"===t!=("view"===s),c=a&&"view"===s&&"view"!==t?this._modeTransitionEditorCamera:null;let h=c?.zoom??(a?this._modeTransitionTargetZoom:this._zoom),d=c?c.centerX:a?this._modeTransitionTargetCenterX:r?.viewport.centerX,p=c?c.centerY:a?this._modeTransitionTargetCenterY:r?.viewport.centerY;if("view"===s&&"view"!==t&&!a){const e=this._view;if(this._viewModeSnap={space:this._space,zoom:this._zoom,cx:e?this._logicalViewCenter(n)?.x:void 0,cy:e?this._logicalViewCenter(n)?.y:void 0},"iso"===n){const e=this._logicalViewCenter("iso");d=e?.x,p=e?.y,this._view=null,this._mode=t,this._applyView(this._zoom,e?.x,e?.y)}l&&(h=1,d=void 0,p=void 0)}if("plan"===s&&this._activeDraftId&&(this._resumeDraftBySpace[this._space]=this._activeDraftId),this._mode=t,this._editorChromeMode="view"===t?s:t,"view"===t){"view"===s||a||(this._modeTransitionEditorCamera={zoom:this._zoom,centerX:r?.viewport.centerX,centerY:r?.viewport.centerY});const t=this._viewModeSnap;if(t&&t.space===this._space){h=t.zoom;const e=this._labsIso&&"iso"===this._viewPreference[this._space]?"iso":"flat",i=null!=t.cx&&null!=t.cy&&"iso"===e?lg([t.cx,t.cy],0):null;d=i?.[0]??t.cx,p=i?.[1]??t.cy}else t&&(h=this._zoomBySpace[this._space]||1,d=void 0,p=void 0)}else this._modeTransitionEditorCamera={zoom:h,centerX:d,centerY:p};this._modeTransitionTargetZoom=h,this._modeTransitionTargetCenterX=d,this._modeTransitionTargetCenterY=p,("iso"===n||"view"===t&&this._labsIso&&"iso"===this._viewPreference[this._space])&&(this._modeTransitionForceAtomic=!0);const u=++this._modeTransitionRequest;e?r?(this._modeTransitionPreparing=!0,this._modeTransitionVisual=r,this._prepareModeTransition(u,r,t,h,d,p)):(this._modeTransitionPreparing=!1,this._modeTransitionVisual=null,this._zoom=h,this._view=null,requestAnimationFrame(()=>{this.isConnected&&u===this._modeTransitionRequest&&this._mode===t&&(this._applyView(h,d,p),"view"===t&&(this._viewModeSnap=null,this._modeTransitionEditorCamera=null),this.requestUpdate())})):"view"===t&&this._commitViewModeAtomic(r,h,d,p),this._path=[],this._clearPlanSnapHover(),this._clearOpeningPlacement(!0),this._openWallAnchor=null,this._boundaryRestoreGuard=null,this._tool="draw",this._mergeSel=null,this._mergeDialog=null,this._splitSel=null,this._pendingSplit=null,this._selId=null,this._physicalSel=null,this._physicalDialog=null,this._physicalDrag=null,this._rszSel=null,this._rszDrag=null,this._rszLive=null,this._rszPreview=null,this._tip=null,this._hoverRoom=null,this._decorDraft=null,this._decorSel=null,this._decorMove=null,this._backdropDialog=null,this._decorTool="select",this._bdDrag=null,this._dtDrag=null,this._dtBox=null,"plan"===t&&(this._primeDrawWallField(),this._resumeLastDraft()),this._saveNav()}_primeDrawWallField(){null===this._drawWallField&&(this._drawWallField=kr(fr,this._imperial))}get _drawWallFieldValue(){return null===this._drawWallField?kr(fr,this._imperial):this._drawWallField}get _drawWallCm(){const t=Qg(this._drawWallFieldValue);if(null==t||t<=0)return null;const e=this._imperial?2.54*t:t,i="column"===this._tool?Ll:100;return e>=1&&e<=i?e:null}get _drawWallMaxCm(){return"column"===this._tool?Ll:100}_showPhysicalRange(t=this._drawWallMaxCm){this._showToast(this._t("toast.physical_range",{max:kr(t,this._imperial),unit:this._t(this._imperial?"wallthick.unit_in":"wallthick.unit_cm")}))}_draftSegmentCount(t=this._curSpaceCfg){return(t?.room_drafts||[]).reduce((t,e)=>t+(Array.isArray(e.segments)?e.segments.length:0),0)}_mergeSpacePartitions(t,e){const i=t?.partitions||[];if(i.length<2)return 0;const s=a_(i,{pitch:$c,seedIds:e,geometry:l_(t,{excludeDraftId:this._activeDraftId})});return s.merged?(t.partitions=s.partitions,r_(t.openings,t.partitions,s.openingMoves,{coordScale:um,cellCm:this._cellCm,gridPitch:this._gridPitch}),s.merged):0}_finishWallChain(){if("draw"!==this._tool||this._wallFaceBatch||this._roomDialog)return!0;const t=this._curSpaceCfg;if(!t||this._path.length<2)return this._path=[],this._activeDraftId=null,this._draftSegmentCms=[],this._closingWallCm=null,this._clearPlanSnapHover(),!0;const e=ep(this._path,tp(this._path.length-1,this._draftSegmentCms,this._drawWallCm,fr)),i=e.length;if((t.partitions||[]).length+i>fm)return this._showToast(this._t("toast.physical_limit")),!1;const s=this._geometrySnapshot();t.partitions||=[];const n=Date.now().toString(36),o=[];for(let s=0;st.id!==this._activeDraftId),t.room_drafts.length||delete t.room_drafts),this._recordGeometry(this._t("history.wall_chain_finish"),s),this._saveConfig(),delete this._resumeDraftBySpace[this._space],this._path=[],this._activeDraftId=null,this._draftSegmentCms=[],this._closingWallCm=null,this._clearPlanSnapHover(),!0}_activateMarkupTool(t){t!==this._tool&&(this._wallFaceBatch&&this._roomDialogCancel(),("draw"!==this._tool||this._finishWallChain())&&(this._cancelPath(),this._tool=t,"draw"===t&&this._resumeLastDraft(),"resize"===t&&(this._rszSel=null),"boundary"!==t&&"wallthick"!==t||(this._wallDialog=null)))}_limitReached(t){const e=this._curSpaceCfg;if(!e)return!0;const i="draft"===t?(e.room_drafts||[]).length>=200:"partition"===t?(e.partitions||[]).length>=fm:(e.wall_columns||[]).length>=500;return i&&this._showToast(this._t("toast.physical_limit")),i}_svgPoint(t){const e=this.renderRoot.querySelector(".stage").getBoundingClientRect();return this._screenToVb(t.clientX-e.left,t.clientY-e.top)}_snap(t){const e=this._gridPitch;return[Cc(ri(t[0],e)),Cc(ri(t[1],e))]}_snapDrawPoint(t,e=!1){const i=this._path[this._path.length-1],s=e&&i?function(t,e,i,s=1/0){if(!(i>0&&t?.every(Number.isFinite)&&e?.every(Number.isFinite)))return[e[0],e[1]];const n=e[0]-t[0],o=e[1]-t[1];if(Math.abs(n)+Math.abs(o)<=1e-12)return[t[0],t[1]];const a=Math.PI/4;let r=Math.atan2(o,n);r<0&&(r+=2*Math.PI);const l=Math.floor(r/a+.5)%8,[c,h]=[[1,0],[1,1],[0,1],[-1,1],[-1,0],[-1,-1],[0,-1],[1,-1]][l],d=c*c+h*h;let p=Math.max(0,Math.round((n*c+o*h)/(i*d)));if(Number.isFinite(s)&&s>=0){const e=(t,e)=>{if(!e)return 1/0;const n=e>0?s-t:t+s;return Math.max(0,Math.floor((n+1e-9*i)/i))};p=Math.min(p,e(t[0],c),e(t[1],h))}return[t[0]+c*p*i,t[1]+h*p*i]}(i,t,this._gridPitch,wc):t;return this._snap(s)}_planSnapOpeningCuts(t,e){if(!this._openingsR.length)return[];const i=this._openingWallIndexFor(t,e).value,s=[];for(const e of this._roomWallOpeningInputs(this._openingsR,t)){const t=El(i,e);if(!t.negative&&!t.positive)continue;const n=e.angle*Math.PI/180,o=Math.cos(n)*e.length/2,a=Math.sin(n)*e.length/2;s.push([e.x-o,e.y-a,e.x+o,e.y+a])}return s}_planSnapGeometrySnapshot(){const t=this._spaceModel();if(!t)return{key:`${this._space}|empty`,value:{segments:[],endpoints:[]}};const e=[this._space,this._cfgEpoch,this._activeDraftId||"",t.rooms.length,t.room_drafts.length,t.partitions.length].join("|");if(this._planSnapGeometryCache?.key===e)return this._planSnapGeometryCache;const i=this._openCuts(),s=Gd({space:t,activeDraftId:this._activeDraftId,roomCuts:[...i,...this._planSnapOpeningCuts(t,i)],partitionCuts:this._partitionOpeningCuts(t),epsilon:2e-4*this._gridPitch});return this._planSnapGeometryCache={key:e,value:s},this._planSnapGeometryCache}_planStructuralGeometrySnapshot(){const t=this._spaceModel();if(!t)return{key:`${this._space}|structural-empty`,value:{segments:[],endpoints:[]}};const e=["structural",this._space,this._cfgEpoch,this._activeDraftId||"",t.rooms.length,t.room_drafts.length,t.partitions.length].join("|");if(this._planStructuralGeometryCache?.key===e)return this._planStructuralGeometryCache;const i=Gd({space:t,activeDraftId:this._activeDraftId,roomCuts:this._openCuts(),epsilon:2e-4*this._gridPitch});return this._planStructuralGeometryCache={key:e,value:i},this._planStructuralGeometryCache}_planSnapContextKey(t){const e=this._path[0],i=this._path[this._path.length-1];return[t,this._tool,this._path.length,e?`${e[0]},${e[1]}`:"",i?`${i[0]},${i[1]}`:""].join("|")}_resolvePlanDrawPoint(t,e){const i=this._planSnapGeometrySnapshot(),s=this._path[this._path.length-1],n="draw"===this._tool&&this._path.length>=3?[{point:this._path[0],key:"closure:first-point"}]:[],o={tolerance:this._cssPxToRender(12),distinguishTolerance:this._cssPxToRender(8),gridStep:this._gridPitch,excludePoints:s?[s]:[],extraEndpoints:n,epsilon:2e-4*this._gridPitch},a=e&&s?Zd(i.value,t,{...o,anchor:s}):function(t,e,i){if(!(Hd(e)&&i.tolerance>=0))return{kind:"none",candidate:null,conflicts:[]};const s=i.epsilon??Nd,n=i.excludePoints||[],o=Xd(Yd(t,e,i),i.distinguishTolerance||0);if(o)return o;let a=null;for(const o of t.segments){const t=[o.a[0],o.a[1],o.b[0],o.b[1]],r=Hs([e[0],e[1]],t);if(r>i.tolerance)continue;const l=Jd(o,e,i.gridStep);!Vd(l,n,s)&&Kd(r,o.key,a)&&(a={kind:"line",point:l,key:o.key,distance:r,segment:o})}return a?{kind:"resolved",candidate:a,conflicts:[]}:{kind:"none",candidate:null,conflicts:[]}}(i.value,t,o),r="resolved"===a.kind?a.candidate:null;return{point:r?[...r.point]:this._snapDrawPoint(t,e),candidate:r,conflicts:"ambiguous"===a.kind?a.conflicts:[],ambiguous:"ambiguous"===a.kind,contextKey:this._planSnapContextKey(i.key)}}get _activePlanSnapCandidate(){if(!this._markup||"draw"!==this._tool)return null;const t=this._planSnapHover;if(!t)return null;const e=this._planSnapGeometrySnapshot();return t.contextKey===this._planSnapContextKey(e.key)?t.candidate:null}get _activePlanSnapConflicts(){if(!this._markup||"draw"!==this._tool)return[];const t=this._planSnapHover;if(!t)return[];const e=this._planSnapGeometrySnapshot();return t.contextKey===this._planSnapContextKey(e.key)?t.conflicts:[]}_clearPlanSnapHover(t=!0){this._planSnapHover=null,this._syncPlanSnapActiveMarker(null),this._syncPlanSnapConflictMarkers([]),t&&(this._cursorPt=null)}_samePt(t,e){return fi(t,e)}_dropLegacySegments(){for(const t of this._serverCfg?.markers||[])"ripple"===t.display&&(t.display="icon_ripple");for(const t of this._serverCfg?.spaces||[]){delete t.segments;const e=new Set,i=t=>"string"==typeof t&&t.length>=1&&t.length<=64&&!e.has(t),s=t=>(e.add(t),!0),n=t=>Array.isArray(t)&&2===t.length&&t.every(t=>Number.isFinite(Number(t))&&Math.abs(Number(t))<=bc);if(Array.isArray(t.partitions)&&(t.partitions=t.partitions.filter(t=>t&&i(t.id)&&n(t.a)&&n(t.b)&&Math.hypot(t.a[0]-t.b[0],t.a[1]-t.b[1])>1e-9&&s(t.id)).map(t=>({...t,cm:Math.max(1,Math.min(100,Number(t.cm)||15))})),t.partitions.length||delete t.partitions),Array.isArray(t.wall_columns)&&(t.wall_columns=t.wall_columns.filter(t=>t&&i(t.id)&&n(t.center)&&s(t.id)).map(t=>({id:t.id,shape:"circle"===t.shape?"circle":"square",center:[Number(t.center[0]),Number(t.center[1])],cm:ql(Number(t.cm)||15),..."circle"===t.shape?{}:{angle:Wl(t.angle)}})),t.wall_columns.length||delete t.wall_columns),Array.isArray(t.room_drafts)&&(t.room_drafts=t.room_drafts.filter(t=>t&&i(t.id)&&Array.isArray(t.points)&&t.points.length>=2&&t.points.every(n)&&s(t.id)).map(t=>{const e=[[Number(t.points[0][0]),Number(t.points[0][1])]],i=[];for(let s=1;st.points.length>=2),t.room_drafts.length||delete t.room_drafts),Array.isArray(t.walls)){const e=rh(t.open_spans).map(t=>[t.a[0],t.a[1],t.b[0],t.b[1]]);t.walls=Er(t.walls,t.rooms||[],$c,1,e),t.walls.length||delete t.walls}}}get _cfgWriting(){return this._writesPending>0}_writeConfig(){var t,e;this._writesPending++,this._writeChain=(t=this._writeChain,e=async()=>{if(!this._serverCfg)return;this._dropLegacySegments();const t=Qu(this._serverCfg),e=Dh(t);e!==Dh(this._serverCfg)&&(this._serverCfg=t),this._cfgContentFingerprint=e;const i=await this.hass.callWS({type:"houseplan/config/set",config:t,expected_rev:this._cfgRev});this._cfgRev=i?.rev??this._cfgRev+1},t.catch(()=>{}).then(e));return this._writeChain.finally(()=>{this._writesPending--})}_saveConfig(){this._cfgEpoch++,this._saveConfigDebounced()}_geometrySnapshot(t=this._space){const e=this._serverCfg?.spaces.find(e=>e.id===t);if(!e)return null;const i=t=>JSON.parse(JSON.stringify(t)),s={};for(const t of["plan_x","plan_y","plan_scale","plan_scale_x","plan_scale_y","plan_angle"])void 0!==e[t]&&(s[t]=e[t]);return{spaceId:t,rooms:i(e.rooms||[]),...Array.isArray(e.openings)?{openings:i(e.openings)}:{},...Array.isArray(e.walls)?{walls:i(e.walls)}:{},...Array.isArray(e.open_spans)?{open_spans:i(e.open_spans)}:{},...Array.isArray(e.room_drafts)?{room_drafts:i(e.room_drafts)}:{},...Array.isArray(e.partitions)?{partitions:i(e.partitions)}:{},...Array.isArray(e.wall_columns)?{wall_columns:i(e.wall_columns)}:{},...Array.isArray(e.decor)?{decor:i(e.decor)}:{},plan_transform:s}}_recordGeometry(t,e){if(!e)return;const i=this._geometrySnapshot(e.spaceId);i&&JSON.stringify(e)!==JSON.stringify(i)&&(this._geometryHistory.push({name:t,before:e,after:i}),this.requestUpdate())}_clearGeometryGesture(){this._path=[],this._clearPlanSnapHover(),this._clearOpeningPlacement(!1),this._mergeSel=null,this._mergeDialog=null,this._splitSel=null,this._pendingSplit=null,this._wallFaceBatch=null,this._wallRepairDiagnostic=null,this._roomDeleteDialog=null,this._openWallAnchor=null,this._boundaryRestoreGuard=null,this._wallDialog=null,this._physicalDialog=null,this._physicalSel=null,this._physicalDrag=null,this._physicalRotate=null,this._activeDraftId=null,this._draftSegmentCms=[],this._closingWallCm=null,this._openingDialog=null,this._rszSel=null,this._rszDrag=null,this._rszPreview=null,this._rszLive=null,this._decorDraft=null,this._decorMove=null,this._dtDrag=null,this._bdDrag=null}_cancelBoundaryAnchor(){return!("boundary"!==this._tool||!this._openWallAnchor)&&(this._openWallAnchor=null,this._boundaryRestoreGuard=null,this._clearPlanSnapHover(),this.requestUpdate(),!0)}_stagePointerCancel(t){if(clearTimeout(this._kioskHoldTimer),this._swipeStart?.id===t.pointerId&&(this._swipeStart=null),this._physicalDrag?.pid===t.pointerId||this._physicalRotate?.pid===t.pointerId)return void this._cancelPhysicalGesture();if(this._decorDraft?.pid===t.pointerId)return this._decorDraft=null,void this.requestUpdate();if(this._decorMove?.pid===t.pointerId||this._dtDrag?.pid===t.pointerId||this._bdDrag?.pid===t.pointerId)return void this._cancelDecorGesture();this._cancelBoundaryAnchor(),"opening"===this._tool?(this._cursorPt=null,this._clearOpeningPlacement(!1)):"draw"===this._tool&&this._clearPlanSnapHover();const e=!!this._pinchStart||!!this._panStart;this._pointers.delete(t.pointerId),this._pointers.size<2&&(this._pinchStart=null),0===this._pointers.size&&(this._panStart=null,this._panLock=null),e&&0===this._pointers.size&&this.requestUpdate()}_applyGeometryState(t){if(!this._canCommitSpace(t.spaceId))return!1;const e=this._serverCfg?.spaces.find(e=>e.id===t.spaceId);if(!e)return!1;const i=t=>JSON.parse(JSON.stringify(t));e.rooms=i(t.rooms),void 0!==t.openings?e.openings=i(t.openings):delete e.openings,void 0!==t.walls?e.walls=i(t.walls):delete e.walls,void 0!==t.open_spans?e.open_spans=i(t.open_spans):delete e.open_spans,void 0!==t.room_drafts?e.room_drafts=i(t.room_drafts):delete e.room_drafts,void 0!==t.partitions?e.partitions=i(t.partitions):delete e.partitions,void 0!==t.wall_columns?e.wall_columns=i(t.wall_columns):delete e.wall_columns,void 0!==t.decor?e.decor=i(t.decor):delete e.decor;for(const t of["plan_x","plan_y","plan_scale","plan_scale_x","plan_scale_y","plan_angle"])delete e[t];return Object.assign(e,i(t.plan_transform||{})),this._clearGeometryGesture(),this._space!==t.spaceId&&(this._commitSpace(t.spaceId),this._saveNav(),this._restoreZoom()),this._modelCache=null,this._frame=null,this._regSignature="",this._maybeRebuildDevices(),this._saveConfig(),this.requestUpdate(),!0}_roomAt(t){return this._spaceModel()?.rooms.find(e=>{const i=hi(e);return!!i&&wi(t,i)})}_overlapRoom(t){return this._spaceModel()?.rooms.find(e=>{const i=hi(e);return!!i&&Di(t,i)})}_pointInRoom(t,e){return e.poly?vi(t,e.poly):null!=e.x&&t[0]>=e.x&&t[0]<=e.x+e.w&&t[1]>=e.y&&t[1]<=e.y+e.h}_contourSelfIntersects(t){if(!ka(t))return!0;const e=t.length,i=.001;for(let s=0;s=500)return this._showToast(this._t("toast.physical_limit")),!1;const t=this._curSpaceCfg;return!(!this._activeDraftId&&(t?.room_drafts||[]).length>=200||this._draftSegmentCount(t)>=2e3||(t?.partitions||[]).length+this._path.length>fm)||(this._showToast(this._t("toast.physical_limit")),!1)}_markupClick(t){if(this._vacFit)return;if(!this._markup)return;const e=this._spaceModel();if(!e)return void this._clearGeometryGesture();if(this._suppressClick)return;if(this._drag||this._rlResize)return;const i=t.composedPath?.()||[];if(i.some(t=>t?.classList?.contains?.("roomlabel")||t?.classList?.contains?.("rlhandle")))return;if(i.some(t=>t?.classList?.contains?.("physical-hit")))return void("boundary"===this._tool&&this._showToast(this._t("toast.boundary_blocked")));const s=this._svgPoint(t);if("select"===this._tool)return void(this._physicalSel=null);if("resize"===this._tool){if(this._rszDrag||i.some(t=>t?.classList?.contains?.("rszhandle")))return;const t=[...e.rooms].reverse().find(t=>this._pointInRoom(s,t));return void(this._rszSel=t?.id||null)}if("delroom"===this._tool)return void this._deleteRoomClick(s);if("opening"===this._tool)return void this._openingClick(s);if("merge"===this._tool)return void this._mergeClick(s);if("wallthick"===this._tool)return void this._wallThickClick(s);if("boundary"===this._tool)return void this._boundaryClick(s);if("split"===this._tool)return void this._splitClick(s);if("column"===this._tool)return void this._columnClick(s);this._wallRepairDiagnostic=null;const n=this._resolvePlanDrawPoint(s,t.shiftKey);if(n.ambiguous)return this._planSnapHover={contextKey:n.contextKey,candidate:null,conflicts:n.conflicts},this._syncPlanSnapActiveMarker(null),this._syncPlanSnapConflictMarkers(n.conflicts),void this._showToast(this._t("toast.plan_snap_ambiguous"));let o=n.point;if(t.ctrlKey||t.metaKey){if(t.preventDefault(),this._path.length<3)return;o=[...this._path[0]]}if(!this._path.length){if(!t.shiftKey&&!n.candidate&&this._offerExistingWallFace(s))return;const e=this._draftEndAt(o);return e?(this._activeDraftId=e.draft.id,this._resumeDraftBySpace[this._space]=e.draft.id,this._path=e.reverse?[...e.draft.points].reverse().map(t=>[...t]):e.draft.points.map(t=>[...t]),void(this._draftSegmentCms=this._adoptDraftCms(this._path,e.reverse?[...e.draft.segments].reverse().map(t=>t.cm):e.draft.segments.map(t=>t.cm),e.draft.id))):(this._activeDraftId=null,this._draftSegmentCms=[],void(this._path=[o]))}const a=this._path[this._path.length-1];if(this._samePt(o,a))return;const r=this._draftEndAt(o,this._activeDraftId||void 0);if(r)return void this._mergeDraftEndpoint(r);if(!this._canAppendRoomDraftPoint())return;const l=this._drawWallCm;if(null==l)return void this._showPhysicalRange(100);const c=this._path.map(t=>[...t]);this._path=[...this._path,o],this._draftSegmentCms=[...this._draftSegmentCms,l],this._persistActiveDraftSegment(),this._offerWallFaces(c)}_draftEndAt(t,e){const i=this._spaceModel();if(!i)return null;const s=this._viewOr(this._baseVb()),n=Math.max(.15*this._gridPitch,this._stageEl?.clientWidth?s.w/this._stageEl.clientWidth*12:0);for(const s of i.room_drafts||[]){if(s.id===e)continue;if(s.points.length<2)continue;const i=s.points[0],o=s.points[s.points.length-1];if(Math.hypot(t[0]-o[0],t[1]-o[1])<=n)return{draft:s,reverse:!1};if(Math.hypot(t[0]-i[0],t[1]-i[1])<=n)return{draft:s,reverse:!0}}return null}_mergeDraftEndpoint(t){const e=this._curSpaceCfg;if(!e||!this._path.length)return;const i=this._path.map(t=>[...t]),s=this._wallGraphSources(i),n=Array.isArray(e.room_drafts)?e.room_drafts:[],o=this._activeDraftId?n.find(t=>t.id===this._activeDraftId):null,a=n.find(e=>e.id===t.draft.id);if(!a)return;const r=t.reverse?t.draft.points.map(t=>[...t]):[...t.draft.points].reverse().map(t=>[...t]),l=t.reverse?(a.segments||[]).map(t=>({...t})):[...a.segments||[]].reverse().map(t=>({...t})),c=this._path[this._path.length-1],h=this._samePt(c,r[0]),d=h?null:this._drawWallCm;if(!h&&null==d)return void this._showPhysicalRange(100);const p=this._draftSegmentCms.map((t,e)=>({...o?.segments?.[e]||{},cm:t})),u=[...this._path.map(t=>[...t]),...h?r.slice(1):r],_=[...p,...null==d?[]:[{cm:d}],...l],g=u.length>=4&&this._samePt(u[0],u[u.length-1]),m=u,f=_;if(m.length>500)return void this._showToast(this._t("toast.physical_limit"));const v=(o?.segments?.length||0)+(a.segments?.length||0);if(this._draftSegmentCount(e)-v+f.length>2e3)return void this._showToast(this._t("toast.physical_limit"));if(g){const t=m.slice(0,-1);if(this._contourSelfIntersects(t)||Pi(t)<=1e-6)return void this._showToast(this._t("toast.contour_cannot_close"));const e=this._overlapRoom(t);if(e)return void this._showToast(this._t("toast.room_overlap",{name:e.name||""}))}const y=this._geometrySnapshot(),b=this._activeDraftId||t.draft.id,w={...o||a,id:b,points:m.map(t=>[t[0]/um,t[1]/um]),segments:f};e.room_drafts=n.filter(e=>e.id!==t.draft.id&&(!this._activeDraftId||e.id!==this._activeDraftId)),e.room_drafts.push(w),this._activeDraftId=b,this._resumeDraftBySpace[this._space]=b,this._path=m,this._draftSegmentCms=this._adoptDraftCms(m,f.map(t=>Number(t.cm)),b),this._physicalSel=null,this._recordGeometry(this._t("history.draft_merge"),y),this._saveConfig(),null!=d&&this._offerWallFaces(i,i.length-1,s)}_adoptDraftCms(t,e,i){const s=Math.max(0,t.length-1),n=tp(s,e,this._drawWallCm,fr);return e.length!==s&&console.debug(`[houseplan] draft ${i??"?"}: восстановлено толщин ${s-e.length} (#234)`),n}_persistActiveDraftSegment(){if(this._path.length<2||!this._curSpaceCfg)return;const t=this._geometrySnapshot(),e=this._curSpaceCfg;e.room_drafts||=[],this._activeDraftId||(this._activeDraftId="draft-"+Date.now().toString(36)),this._resumeDraftBySpace[this._space]=this._activeDraftId;const i=e.room_drafts.findIndex(t=>t.id===this._activeDraftId),s={...i>=0?e.room_drafts[i]:{},id:this._activeDraftId,points:this._path.map(t=>[t[0]/um,t[1]/um]),segments:this._draftSegmentCms.map((t,s)=>({...i>=0?e.room_drafts[i]?.segments?.[s]:{},cm:t}))};i>=0?e.room_drafts[i]=s:e.room_drafts.push(s),this._recordGeometry(this._t("history.draft_segment"),t),this._saveConfig()}_activeWallSourceKey(t){return`active:${this._activeDraftId||"session"}:${t}`}_wallGraphSources(t){const e=this._planStructuralGeometrySnapshot().value.segments.map(t=>({a:t.a,b:t.b,key:`static:${t.key}`}));for(let i=0;i+1t.key===i);if(s>=0){const[t]=this._wallFaceGraphCache.splice(s,1);return this._wallFaceGraphCache.push(t),t.value}const n=xp(t,e);return this._wallFaceGraphCache.push({key:i,value:n}),this._wallFaceGraphCache.length>4&&this._wallFaceGraphCache.shift(),n}_offerWallFaces(t,e=this._path.length-2,i){if(this._path.length<2||this._wallFaceBatch||this._roomDialog)return;const s=this._spaceModel();if(!s)return;const n=this._activeWallSourceKey(e),o=2e-4*this._gridPitch;let a,r;try{const e=i||this._wallGraphSources(t);r=this._wallGraphSources(this._path),a=function(t,e,i){const s=new Set(t.faces.map(t=>t.key));return e.faces.filter(t=>!s.has(t.key)&&t.sourceKeys.includes(i))}(this._wallFaceGraph(e,o),this._wallFaceGraph(r,o),n)}catch{return}if(!a.length){const t=Ep(r,{requiredSourceKey:n,maxDistance:xr(2,this._cellCm,this._gridPitch),gridStep:this._gridPitch,epsilon:o});return"ambiguous"===t.kind?(this._wallRepairDiagnostic=t.proposals[0]||null,void this._showToast(this._t("toast.wall_repair_ambiguous"))):void("repair"!==t.kind||this._overlapRoom(t.face.ring)||this._beginWallFaceBatch([{...t.face,repair:t.proposal}]))}for(const t of s.rooms){const e=hi(t);if(!t.id||!e)continue;const i=Fi(e,this._path,.02*this._gridPitch);if(!i)continue;const[s,n]=i,o=Pi(s)>=Pi(n)?s:n,r=o===s?n:s,l=[...a].sort((t,e)=>Math.abs(t.area-Pi(r))-Math.abs(e.area-Pi(r))||t.key.localeCompare(e.key))[0];if(!l)return;return void this._beginWallFaceBatch([{...l,ring:r.map(t=>[t[0],t[1]]),split:{roomId:t.id,mainPoly:o,newPoly:r},consumeAllActive:!0}])}const l=a.filter(t=>!(t.ring.length<3||this._contourSelfIntersects(t.ring))&&!this._overlapRoom(t.ring));l.length&&this._beginWallFaceBatch(l)}_beginWallFaceBatch(t){this._wallRepairDiagnostic=null,this._wallFaceBatch={candidates:[...t].sort((t,e)=>t.area-e.area||t.key.localeCompare(e.key)),index:0,decisions:[],activePath:this._path.map(t=>[...t]),activeCms:[...this._draftSegmentCms],activeDraftId:this._activeDraftId},this._clearPlanSnapHover(),this._nameSel="",this._areaSel="",this._resetRoomDialogFields(),this._roomDialog=!0}_offerExistingWallFace(t){if(this._path.length||this._wallFaceBatch||this._roomDialog)return!1;const e=2e-4*this._gridPitch;try{let i,s=$p(this._wallFaceGraph(this._wallGraphSources([]),e),t,e);if(!s){const n=Ep(this._wallGraphSources([]),{point:t,maxDistance:xr(2,this._cellCm,this._gridPitch),gridStep:this._gridPitch,epsilon:e});if("ambiguous"===n.kind)return this._wallRepairDiagnostic=n.proposals[0]||null,this._showToast(this._t("toast.wall_repair_ambiguous")),!0;if("repair"===n.kind)s=n.face,i=n.proposal;else if("none"===n.kind){const i=Ep(this._wallGraphSources([]),{point:t,maxDistance:this._cssPxToRender(12),gridStep:this._gridPitch,epsilon:e});if("repair"===i.kind)return this._wallRepairDiagnostic=i.proposal,this._showToast(this._t("toast.wall_repair_too_large")),!0}}return!(!s||s.ring.length<3||this._contourSelfIntersects(s.ring)||this._overlapRoom(s.ring))&&(this._beginWallFaceBatch([{...s,existing:!i,repair:i}]),!0)}catch{return!1}}_columnClick(t){const e=this._snap(t),i=this._drawWallCm;if(null==i)return void this._showPhysicalRange(Ll);if(!this._curSpaceCfg||this._limitReached("column"))return;const s=this._spaceModel();if(!s)return;const n={id:"column-"+Date.now().toString(36),shape:"square",center:e,cm:ql(i),angle:0},o=(s.wall_columns||[]).find(t=>rc(t,n,.02*this._gridPitch));if(o)return clearTimeout(this._duplicateColumnTimer),this._duplicateColumnId=o.id,this._duplicateColumnTimer=window.setTimeout(()=>{this._duplicateColumnId=null},900),void this._showToast(this._t("toast.column_duplicate"));const a=this._geometrySnapshot(),r=this._curSpaceCfg;r.wall_columns||=[],r.wall_columns.push({...n,center:[e[0]/um,e[1]/um]}),this._recordGeometry(this._t("history.column_add"),a),this._saveConfig()}_openPhysicalDialog(t,e,i){const s=this._spaceModel();if(s)if("partition"===t){const i=s.partitions.find(t=>t.id===e);i&&(this._physicalDialog={kind:t,id:e,cm:kr(i.cm,this._imperial),length:this._fmtLen(i.a,i.b)})}else if("column"===t){const i=s.wall_columns.find(t=>t.id===e);i&&(this._physicalDialog={kind:t,id:e,cm:kr(i.cm,this._imperial),shape:i.shape,angle:this._angleField("square"===i.shape?Wl(i.angle):0)})}else{const n=s.room_drafts.find(t=>t.id===e),o=Math.max(0,Math.min(n?.segments.length?n.segments.length-1:0,i||0));n?.segments[o]&&(this._physicalDialog={kind:t,id:e,segment:o,cm:kr(n.segments[o].cm,this._imperial),length:this._fmtLen(n.points[o],n.points[o+1])})}}_physicalDown(t,e,i){const s=this._spaceModel();if(!s)return;t.stopPropagation(),wm(t);const n=this._svgPoint(t),o=[];for(const t of[...s.wall_columns].reverse())oc(n,Yl(t,this._cellCm,this._gridPitch))&&o.push({kind:"column",id:t.id});for(const t of[...s.partitions].reverse()){const e=Kl(t.a,t.b,t.cm,this._cellCm,this._gridPitch);e&&oc(n,e)&&o.push({kind:"partition",id:t.id})}o.some(t=>t.kind===e&&t.id===i)||o.unshift({kind:e,id:i});const a=o.map(t=>`${t.kind}:${t.id}`).sort().join("|"),r=performance.now(),l=this._physicalPickCycle,c=o.length>1&&l?.signature===a&&r-l.at>380&&r-l.at<=1200&&Math.hypot(t.clientX-l.x,t.clientY-l.y)<=10?(l.index+1)%o.length:Math.max(0,o.findIndex(t=>t.kind===e&&t.id===i));this._physicalPickCycle={signature:a,index:c,x:t.clientX,y:t.clientY,at:r},e=o[c].kind,i=o[c].id;const h="partition"===e?s.partitions.find(t=>t.id===i):s.wall_columns.find(t=>t.id===i);h&&(this._physicalSel={kind:e,id:i},this._physicalDrag={pid:t.pointerId,kind:e,id:i,start:this._svgPoint(t),startClient:[t.clientX,t.clientY],before:this._geometrySnapshot(),moved:!1,base:JSON.parse(JSON.stringify(h)),delta:[0,0]})}_clampPhysicalDelta(t,e,i){const s="partition"===t?[e.a,e.b]:[e.center],n=s.map(t=>t[0]),o=s.map(t=>t[1]);return[Math.max(-bc*um-Math.min(...n),Math.min(bc*um-Math.max(...n),i[0])),Math.max(-bc*um-Math.min(...o),Math.min(bc*um-Math.max(...o),i[1]))]}_physicalMove(t){const e=this._physicalDrag;if(!e||e.pid!==t.pointerId)return;t.stopPropagation();const i=this._svgPoint(t),s="partition"===e.kind?e.base.a:e.base.center,n=this._snap([s[0]+i[0]-e.start[0],s[1]+i[1]-e.start[1]]),o=this._clampPhysicalDelta(e.kind,e.base,[n[0]-s[0],n[1]-s[1]]);this._physicalDrag={...e,delta:o,moved:e.moved||Math.hypot(t.clientX-e.startClient[0],t.clientY-e.startClient[1])>=5}}_physicalUp(t){const e=this._physicalDrag;if(!e||e.pid!==t.pointerId)return;if(t.stopPropagation(),this._physicalDrag=null,!e.moved)return void this._registerPhysicalTap(e.kind,e.id);const i=this._spaceModel();if(!this._curSpaceCfg||!i)return;const s=this._curSpaceCfg;if("partition"===e.kind){const t=(s.partitions||[]).find(t=>t.id===e.id),i=e.base;if(t){const n={...i,a:[i.a[0]+e.delta[0],i.a[1]+e.delta[1]],b:[i.b[0]+e.delta[0],i.b[1]+e.delta[1]]};t.a=[n.a[0]/um,n.a[1]/um],t.b=[n.b[0]/um,n.b[1]/um];for(const t of s.openings||[]){if("partition"!==t.host?.kind||t.host.id!==e.id)continue;const i=Rd(t,[n],um,this._cellCm,this._gridPitch).resolved;i&&Object.assign(t,Od(t,i,um))}}}else{const t=(s.wall_columns||[]).find(t=>t.id===e.id),n=e.base,o={...n,center:[n.center[0]+e.delta[0],n.center[1]+e.delta[1]]};if(i.wall_columns.some(t=>t.id!==e.id&&rc(t,o,.02*this._gridPitch)))return void this._showToast(this._t("toast.column_duplicate"));t&&(t.center=[(n.center[0]+e.delta[0])/um,(n.center[1]+e.delta[1])/um])}this._recordGeometry(this._t("history.physical_move"),e.before),this._saveConfig()}_registerPhysicalTap(t,e,i){const s=performance.now(),n=this._physicalLastTap?.kind===t&&this._physicalLastTap.id===e&&this._physicalLastTap.segment===i&&s-this._physicalLastTap.at<=360;this._physicalLastTap={kind:t,id:e,segment:i,at:s},n&&(this._physicalLastTap=null,this._openPhysicalDialog(t,e,i))}_cancelPhysicalGesture(){this._physicalDrag=null,this._physicalRotate=null,this.requestUpdate()}_physicalRotateDown(t,e){if("square"!==e.shape||!this._spaceModel())return;t.preventDefault(),t.stopPropagation(),wm(t);const i=this._svgPoint(t);this._physicalSel={kind:"column",id:e.id},this._physicalRotate={pid:t.pointerId,id:e.id,center:[...e.center],startAngle:180*Math.atan2(i[1]-e.center[1],i[0]-e.center[0])/Math.PI,baseAngle:Wl(e.angle),angle:Wl(e.angle),before:this._geometrySnapshot(),moved:!1}}_physicalRotateMove(t){const e=this._physicalRotate;if(!e||e.pid!==t.pointerId)return;t.preventDefault(),t.stopPropagation();const i=this._svgPoint(t),s=180*Math.atan2(i[1]-e.center[1],i[0]-e.center[0])/Math.PI,n=e.baseAngle+s-e.startAngle,o=Wl(t.shiftKey?n:5*Math.round(n/5));this._physicalRotate={...e,angle:o,moved:e.moved||Math.abs(n-e.baseAngle)>=.5}}_physicalRotateUp(t){const e=this._physicalRotate;if(!e||e.pid!==t.pointerId)return;t.preventDefault(),t.stopPropagation(),this._physicalRotate=null;const i=this._spaceModel();if(!e.moved||!this._curSpaceCfg||!i)return;const s=i.wall_columns.find(t=>t.id===e.id);if(!s||"square"!==s.shape)return;const n={...s,angle:e.angle};if(i.wall_columns.some(t=>t.id!==e.id&&rc(t,n,.02*this._gridPitch)))return void this._showToast(this._t("toast.column_duplicate"));const o=this._curSpaceCfg.wall_columns?.find(t=>t.id===e.id);o&&(o.angle=e.angle,this._recordGeometry(this._t("history.physical_edit"),e.before),this._saveConfig())}_rszRooms(){const t=[],e=this._spaceModel();if(!e)return t;for(const i of e.rooms){const e=i.id?hi(i):null;e&&t.push({id:i.id,poly:e})}return t}_rszOpenings(){return this._openingsR.map(t=>({id:t.id,x:t.rx,y:t.ry,length:t.rlen}))}_rszOpts(){return{minDim:this._cmToUnits(30),eps:.05*this._gridPitch}}_rszSnapshot(){return JSON.stringify(this._geometrySnapshot()||{spaceId:this._space,rooms:[],openings:[],walls:[],open_spans:[]})}_rszApplyPreview(t,e){const i=this._rszDrag,s=this._serverCfg?.spaces.find(t=>t.id===this._space);if(!i||!s)return;const n=JSON.parse(i.snap),o={...s,rooms:n.rooms,openings:n.openings,walls:n.walls,open_spans:n.open_spans};Array.isArray(n.open_spans)&&n.open_spans.length||delete o.open_spans;const a=this._spaceH;for(const[e,i]of Object.entries(t)){const t=o.rooms.find(t=>t.id===e);t&&(t.poly=i.map(t=>[t[0]/um,t[1]/a]),delete t.x,delete t.y,delete t.w,delete t.h)}for(const[t,i]of Object.entries(e)){const e=(o.openings||[]).find(e=>e.id===t);e&&(e.x=i[0]/um,e.y=i[1]/a)}const r=[],l=[];for(const t of i.changed){const e=i.rooms.find(e=>e.id===t),s=o.rooms.find(e=>e.id===t);if(!e||!s?.poly)continue;const n=s.poly.map(t=>[t[0]*um,t[1]*a]);if(e.poly.length===n.length)for(let t=0;tt.id===e);if(!s||!s.poly||s.poly.length<3)return null;if(i<0||i>=s.poly.length)return null;const n=[...s.poly[i]],o=[...s.poly[(i+1)%s.poly.length]];return{roomId:e,edge:i,a:n,b:o,n:fa(s.poly,i)}}(s,e,i);n&&(this._rszDrag={kind:"edge",pid:t.pointerId,roomId:e,plan:n,rooms:s,openings:this._rszOpenings(),snap:this._rszSnapshot(),moved:!1,d:0,k:1,changed:[]})}_rszCornerDown(t,e,i,s){"resize"!==this._tool||this._rszDrag||(t.stopPropagation(),t.preventDefault(),wm(t),this._rszDrag={kind:"scale",pid:t.pointerId,roomId:e,fixed:s,span0:Math.hypot(i[0]-s[0],i[1]-s[1])||1,rooms:this._rszRooms(),openings:this._rszOpenings(),snap:this._rszSnapshot(),moved:!1,d:0,k:1,changed:[]})}_rszMove(t){const e=this._rszDrag;if(!e||e.pid!==t.pointerId)return;t.stopPropagation();const i=this._svgPoint(t);if("edge"===e.kind){const t=e.plan,s=(i[0]-t.a[0])*t.n[0]+(i[1]-t.a[1])*t.n[1],n=this._snap([t.a[0]+t.n[0]*s,t.a[1]+t.n[1]*s]);let o=(n[0]-t.a[0])*t.n[0]+(n[1]-t.a[1])*t.n[1];if(o=function(t,e,i,s,n,o){if(!Number.isFinite(s)||Math.abs(s)<1e-9)return 0;const a=Math.sign(s);let r=Math.abs(s);const l=Math.max(n,1e-6);for(let s=0;s<4096&&r>1e-9;s++,r-=l){const s=a*r;if(Da(t,e,i,s,o))return s}return 0}(e.rooms,e.openings,t,o,this._gridPitch,this._rszOpts()),o===e.d&&e.moved)return;e.d=o,e.moved=!0;const a=Sa(e.rooms,e.openings,t,o,this._rszOpts().eps);e.changed=Object.keys(a.polys),this._rszApplyPreview(a.polys,a.openings),this._rszLive=this._rszEdgeLabels(a,t)}else{const t=e.fixed,s=this._snap(i);let n=Math.hypot(s[0]-t[0],s[1]-t[1])/(e.span0||1);if(n=Math.max(.05,Math.min(20,n)),n=function(t,e,i,s,n,o){if(!Number.isFinite(n)||n<=0)return 1;if(Pa(t,e,i,s,n,o))return n;let a=1,r=n;for(let n=0;n<28;n++){const n=(a+r)/2;Pa(t,e,i,s,n,o)?a=n:r=n}return a}(e.rooms,e.openings,e.roomId,t,n,this._rszOpts()),n===e.k&&e.moved)return;e.k=n,e.moved=!0;const o=e.rooms.find(t=>t.id===e.roomId),a=e.rooms.filter(t=>t.id!==e.roomId).map(t=>t.poly),r=Ta(o,e.openings,a,t,n,2*this._rszOpts().eps);e.changed=[e.roomId],this._rszApplyPreview({[e.roomId]:r.poly},r.openings),this._rszLive=this._rszScaleLabels(r.poly)}this.requestUpdate()}_rszUp(t){const e=this._rszDrag;if(!e||e.pid!==t.pointerId)return;t.stopPropagation();const i=this._rszPreview;this._rszDrag=null,this._rszLive=null,this._rszPreview=null;if(!(e.moved&&("edge"===e.kind?Math.abs(e.d)>1e-9:Math.abs(e.k-1)>1e-9))||!i)return this._cfgEpoch++,void this.requestUpdate();const s=JSON.parse(e.snap),n=this._curSpaceCfg;if(n){n.rooms=i.sp.rooms,n.openings=i.sp.openings,Array.isArray(i.sp.walls)&&(i.sp.walls.length?n.walls=i.sp.walls:delete n.walls),Array.isArray(i.sp.open_spans)&&i.sp.open_spans.length?n.open_spans=i.sp.open_spans:delete n.open_spans;for(const t of e.changed){const e=n.rooms.find(e=>e.id===t);e?.poly&&(e.poly=wa(e.poly,1e-9))}this._commitOpenSpans(),Array.isArray(n.walls)&&n.walls.length&&(n.walls=Er(n.walls,n.rooms||[],$c,1,this._cfgOpenCuts()),n.walls.length||delete n.walls)}this._suppressClick=!0,setTimeout(()=>this._suppressClick=!1,0),this._recordGeometry(this._t("history.resize_room"),s),this._saveConfig(),this.requestUpdate()}_rszCancelDrag(){this._rszDrag&&(this._rszDrag=null,this._rszLive=null,this._rszPreview=null,this._cfgEpoch++,this.requestUpdate())}_rszPointerCancel(t){const e=this._rszDrag;e&&e.pid===t.pointerId&&(t.stopPropagation(),this._rszCancelDrag())}_rszEdgeLabels(t,e){const i=this._rszDrag,s=[],n=t.polys[e.roomId]||i.rooms.find(t=>t.id===e.roomId).poly,o=n.length,a=e.edge,r=(a+1)%o,l=this._rszInnerSpanCms(e.roomId,n,t.polys);for(const t of[(a-1+o)%o,a,r]){const e=n[t],i=n[(t+1)%o],a=l?.[t];s.push({x:(e[0]+i[0])/2,y:(e[1]+i[1])/2,text:null==a?this._fmtLen(e,i):li(a,"mi"===this.hass?.config?.unit_system?.length)})}const c="mi"===this.hass?.config?.unit_system?.length,h=Object.keys(t.polys).length?Object.keys(t.polys):[e.roomId],d=this._spaceWalls,p=this._openPairs().flatMap(t=>t.segs),u=this._physicalBodiesR();for(const e of h){const n=t.polys[e]||i.rooms.find(t=>t.id===e).poly,o=d.length&&fl(Object.entries(t.polys).map(([t,e])=>({id:t,poly:e})),e,d,p,this._wallKeyPitch,this._cellCm,this._gridPitch,um)||n,a=$i(o),r=u.length?sc(ic(o,u))*Math.pow(this._cellCm/this._gridPitch,2)/1e4:Ra(o,this._gridPitch,this._cellCm);s.push({x:a[0],y:a[1],text:Ia(r,c),area:!0})}return s}_rszInnerSpanCms(t,e,i){const s=Object.keys(i).length?Object.entries(i).map(([t,e])=>({id:t,poly:e})):this._spaceModel()?.rooms;if(!s?.length)return null;const n=this._spaceWalls;if(!n.length)return null;const o=function(t,e,i,s,n,o,a,r=1){const l=(t||[]).find(t=>t?.id===e),c=hi(l);if(!c||c.length<3)return null;const h=hl(t,e,i,s,n,o,a,r);if(!h)return c.map(()=>0);const d=4*Kr(n,r);return c.map((t,e)=>{const i=c[(e+1)%c.length],s=[(t[0]+i[0])/2,(t[1]+i[1])/2];for(let t=0;tt.segs),this._wallKeyPitch,this._cellCm,this._gridPitch,um);if(!o||o.length!==e.length)return null;const a=this._cellCm/this._gridPitch;return e.map((t,i)=>function(t,e,i){const s=t?.length||0;if(s<3||!Array.isArray(i)||i.length!==s)return 0;const n=(Math.trunc(e)%s+s)%s,o=t[n],a=t[(n+1)%s],r=a[0]-o[0],l=a[1]-o[1],c=Math.hypot(r,l);if(!(c>0))return 0;const h=Math.max(0,Number(i[n])||0);if(!(h>0))return c;const d=[r/c,l/c],p=Xr(t,n),u=[o[0]+p[0]*h,o[1]+p[1]*h],_=e=>{const n=Math.max(0,Number(i[e])||0);if(!(n>0))return null;const a=t[e],r=t[(e+1)%s],l=r[0]-a[0],c=r[1]-a[1],h=Math.hypot(l,c);if(!(h>0))return null;const p=Xr(t,e),_=Zr(u,d,[a[0]+p[0]*n,a[1]+p[1]*n],[l/h,c/h]);return _?(_[0]-o[0])*d[0]+(_[1]-o[1])*d[1]:null},g=_((n-1+s)%s)??0,m=(_((n+1)%s)??c)-g;return m>0?m:0}(e,i,o)*a)}_rszScaleLabels(t){const e="mi"===this.hass?.config?.unit_system?.length,i=t.map(t=>t[0]),s=t.map(t=>t[1]),n=this._spaceWalls,o=n.length&&this._rszSel&&fl([{id:this._rszSel,poly:t}],this._rszSel,n,[],this._wallKeyPitch,this._cellCm,this._gridPitch,um)||t,a=$i(o),r=this._physicalBodiesR(),l=r.length?sc(ic(o,r))*Math.pow(this._cellCm/this._gridPitch,2)/1e4:Ra(o,this._gridPitch,this._cellCm),c=o.map(t=>t[0]),h=o.map(t=>t[1]),d=Math.max(...c)-Math.min(...c),p=Math.max(...h)-Math.min(...h);return[{x:Math.min(...i),y:Math.min(...s),text:`${this._fmtLen([0,0],[d,0])} × ${this._fmtLen([0,0],[p,0])}`},{x:a[0],y:a[1],text:Ia(l,e),area:!0}]}_renderResizeLayer(t){const e=Math.max(.013*t.w,5),i=e/2,s=t=>t.toFixed(1),n=`M ${s(-.7*i)} 0 H ${s(.7*i)} M 0 ${s(-.22*i)} V ${s(-i)} M ${s(-.32*i)} ${s(-.6*i)} L 0 ${s(-i)} L ${s(.32*i)} ${s(-.6*i)} M 0 ${s(.22*i)} V ${s(i)} M ${s(-.32*i)} ${s(.6*i)} L 0 ${s(i)} L ${s(.32*i)} ${s(.6*i)}`,o=[],a=this._rszRooms();for(const t of a)for(let i=0;ithis._rszEdgeDown(e,t.id,i)} @pointermove=${t=>this._rszMove(t)} @pointerup=${t=>this._rszUp(t)} @pointercancel=${t=>this._rszPointerCancel(t)} - @lostpointercapture=${t=>this._rszPointerCancel(t)}>`),o.push(j``)}const a=this._rszSel?r.find(t=>t.id===this._rszSel):null;if(a){const t=a.poly.map(t=>t[0]),i=a.poly.map(t=>t[1]),s=Math.min(...t),n=Math.max(...t),r=Math.min(...i),l=Math.max(...i);o.push(j``);for(const[t,i,c,h]of[[s,r,n,l],[n,r,s,l],[n,l,s,r],[s,l,n,r]])o.push(j`this._rszCornerDown(e,a.id,[t,i],[c,h])} + @lostpointercapture=${t=>this._rszPointerCancel(t)}>`),o.push(j``)}const r=this._rszSel?a.find(t=>t.id===this._rszSel):null;if(r){const t=r.poly.map(t=>t[0]),i=r.poly.map(t=>t[1]),s=Math.min(...t),n=Math.max(...t),a=Math.min(...i),l=Math.max(...i);o.push(j``);for(const[t,i,c,h]of[[s,a,n,l],[n,a,s,l],[n,l,s,a],[s,l,n,a]])o.push(j`this._rszCornerDown(e,r.id,[t,i],[c,h])} @pointermove=${t=>this._rszMove(t)} @pointerup=${t=>this._rszUp(t)} @pointercancel=${t=>this._rszPointerCancel(t)} - @lostpointercapture=${t=>this._rszPointerCancel(t)}>`),o.push(j``)}return j`${o}`}get _openingsR(){const t=this._curSpaceCfg,e=this._spaceH,i=this._spaceModel();return i?(t?.openings||[]).flatMap(t=>{const s={...t,rx:t.x*pm,ry:t.y*e,rlen:t.length*pm};if(!t.host)return[s];const n=Pd(t,i.partitions,pm,this._cellCm,this._gridPitch);if(!n.resolved)return"plan"===this._mode?[{...s,orphanReason:n.reason||"invalid-host"}]:[];let[o,r]=n.resolved.center;const a=this._physicalDrag;return a?.moved&&"partition"===a.kind&&a.id===t.host.id&&(o+=a.delta[0],r+=a.delta[1]),[{...t,rx:o,ry:r,rlen:n.resolved.length,angle:n.resolved.angle,partitionHost:n.resolved}]}):[]}_partitionOpeningCuts(t=this._spaceModel(),e=()=>!0){if(!t)return[];return x_(k_(this._curSpaceCfg?.id===t.id?this._curSpaceCfg:null,t,this._cellCm,this._gridPitch,pm),e)}_roomWallOpeningInputs(t=this._openingsR,e=this._spaceModel()){if(!e)return[];const i=this._openPairs().flatMap(t=>t.segs);return $_(t,e,this._spaceWalls,i,this._wallKeyPitch,this._cellCm,this._gridPitch,pm)}_openingFace(t,e,i){return t.partitionHost?Fd(t.partitionHost,i):El(e,{x:t.rx,y:t.ry,angle:t.angle,length:t.rlen,flip_v:i})}_cmToUnits(t){return t/this._cellCm*this._gridPitch}get _decorList(){const t=this._curSpaceCfg;return Array.isArray(t?.decor)?t.decor:[]}get _decorH(){return pm}_decorResolvedStyle(t){return function(t,e,i,s=oa){const n="rect"===t?.kind||"ellipse"===t?.kind,o=t,r=Rt(o?.color,s.color);return{color:r,opacity:ra(o?.opacity,s.opacity),widthCm:da(t,e,i,s.widthCm),fill:!!n&&!0===o?.fill,fillColor:Rt(o?.fill_color,o?.fill?r:s.fillColor),fillOpacity:n&&o?.fill?ra(o?.fill_opacity,.25):s.fillOpacity}}(t,this._cellCm,this._gridPitch,oa)}_decorWidthUnits(t){return((t,e,i,s=oa.widthCm)=>{const n=Number(t?.width_cm);if(Number.isFinite(n)&&n>0)return ca(n,e,i);const o=Number(t?.width);return Number.isFinite(o)&&o>0?o:ca(s,e,i)})(t,this._cellCm,this._gridPitch,oa.widthCm)}_decorTextSizeCm(t){if("text"===t?.kind){const e=Number(t.size_cm);return Number.isFinite(e)&&e>0?e:ha(es*is(t),this._cellCm,this._gridPitch)}return ha(es,this._cellCm,this._gridPitch)}_decorTextUnits(t){if("text"!==t.kind)return es;const e=Number(t.size_cm);return Number.isFinite(e)&&e>0?ca(e,this._cellCm,this._gridPitch):es*is(t)}_decorSmallField(t){return Math.round(100*(this._imperial?t/2.54:t))/100}_decorSmallCm(t){const e=this._imperial?2.54*t:t;return Number.isFinite(e)?Math.max(.1,Math.min(100,e)):.1}_decorTextCm(t){const e=this._imperial?2.54*t:t;return Number.isFinite(e)?Math.max(.1,Math.min(Yg,e)):.1}_decorLargeField(t){return Math.round(100*(this._imperial?t/30.48:t/100))/100}_decorLargeCm(t){const e=this._imperial?30.48*t:100*t;return Number.isFinite(e)?Math.max(.1,Math.min(yc*this._cellCm,e)):.1}_angleField(t){const e=Number(t);return Number.isFinite(e)?String(Number(e.toFixed(3))):"0"}_decorBoxOf(t){return"rect"!==t.kind&&"ellipse"!==t.kind&&"furniture"!==t.kind?null:{x:t.x*pm,y:t.y*this._decorH,w:t.w*pm,h:t.h*this._decorH,angle:aa(t.angle)||void 0}}_decorSnapGeometry(t){const e=this._spaceModel();if(!e)return{points:[],segments:[]};const i=t||"",s=this._decorSnapCache;if(s&&s.epoch===this._cfgEpoch&&s.space===this._space&&s.height===this._decorH&&s.exclude===i)return s.geometry;const n=[];for(const e of this._decorList)if(e.id!==t)if("line"===e.kind){const t=[e.x1*pm,e.y1*this._decorH],i=[e.x2*pm,e.y2*this._decorH];n.push({points:[t,i,[(t[0]+i[0])/2,(t[1]+i[1])/2]],segments:[{a:t,b:i}]})}else if("text"===e.kind)n.push({points:[[e.x*pm,e.y*this._decorH]],segments:[]});else{const t=this._decorBoxOf(e);t&&n.push(_a(t))}for(const t of e.rooms){const e=hi(t);e?.length&&n.push({points:e.flatMap((t,i)=>{const s=e[(i+1)%e.length];return[t,[(t[0]+s[0])/2,(t[1]+s[1])/2]]}),segments:e.map((t,i)=>({a:t,b:e[(i+1)%e.length]}))})}const o=function(t){return{points:t.flatMap(t=>t.points),segments:t.flatMap(t=>t.segments)}}(n);return this._decorSnapCache={epoch:this._cfgEpoch,space:this._space,height:this._decorH,exclude:i,geometry:o},o}_decorSnap(t,e="mouse",i){const s=this._stageEl,n=this._viewOr(this._baseVb()),o="touch"===e||"pen"===e?14:8,r=s?n.w/Math.max(1,s.clientWidth)*o:this._gridPitch;return function(t,e,i,s){const n=s(t);let o=null;for(const n of e.points){const e=s(n),r=Math.hypot(e[0]-t[0],e[1]-t[1]);r<=i&&(!o||rthis._snap(t)).point}_replaceDecor(t,e){const i=this._curSpaceCfg;i&&(i.decor=this._decorList.map(i=>i.id===t?{...i,...e}:i),this.requestUpdate())}_cancelDecorGesture(){const t=this._decorMove?.before||this._dtDrag?.before||this._bdDrag?.before,e=t&&this._serverCfg?.spaces.find(e=>e.id===t.spaceId);if(t&&e){const i=t=>JSON.parse(JSON.stringify(t));void 0!==t.decor?e.decor=i(t.decor):delete e.decor;for(const t of["plan_x","plan_y","plan_scale","plan_scale_x","plan_scale_y","plan_angle"])delete e[t];Object.assign(e,i(t.plan_transform||{})),this._cfgEpoch++}this._decorMove=null,this._dtDrag=null,this._bdDrag=null,this.requestUpdate()}_decorPointerDown(t){const e=this._decorTool;if("select"===e||"erase"===e?t.target.closest?.(".dshape"):null)return!0;if("line"===e||"rect"===e||"ellipse"===e){t.preventDefault();const i=this._decorSnap(this._svgPoint(t),t.pointerType);return this._decorDraft={kind:e,a:i,b:i,pid:t.pointerId},bm(t),!0}if("text"===e){const e=this._decorSnap(this._svgPoint(t),t.pointerType);return this._decorTextDialog={x:Cc(e[0]/pm),y:Cc(e[1]/this._decorH),text:"",color:this._decorStyle.color,opacity:this._decorStyle.opacity,angle:"0",sizeCm:ha(es,this._cellCm,this._gridPitch)},this._decorTextSelection={start:0,end:0},!0}if("furniture"===e)return!!this._furnPalette&&(t.preventDefault(),this._furnPlace(this._svgPoint(t),t.shiftKey),!0);if("select"===e&&(this._decorSel=null),this._bdMovable){const e=this._bdRect,i=this._svgPoint(t),s=e.x+e.w/2,n=e.y+e.h/2,o=-aa(e.angle)*Math.PI/180,r=i[0]-s,a=i[1]-n,l=[s+r*Math.cos(o)-a*Math.sin(o),n+r*Math.sin(o)+a*Math.cos(o)];if(l[0]>=e.x&&l[0]<=e.x+e.w&&l[1]>=e.y&&l[1]<=e.y+e.h)return t.preventDefault(),this._bdStart(t)}return!1}_decorCommitDraft(){const t=this._decorDraft;if(this._decorDraft=null,!t)return;const e=.5*this._gridPitch;if(!function(t,e,i,s){const n=Math.abs(i[0]-e[0]),o=Math.abs(i[1]-e[1]);return"line"===t?Math.hypot(n,o)>=s:n>=s&&o>=s}(t.kind,t.a,t.b,e))return;const i=pm,s=this._decorH,n=this._decorStyle,o=this._geometrySnapshot(),r="dc"+Date.now().toString(36)+Math.random().toString(36).slice(2,5),a=Cc;let l;if("line"===t.kind)l={id:r,kind:"line",x1:a(t.a[0]/i),y1:a(t.a[1]/s),x2:a(t.b[0]/i),y2:a(t.b[1]/s),...pa(n,!1)};else{const e=a(Math.min(t.a[0],t.b[0])/i),o=a(Math.min(t.a[1],t.b[1])/s),c=Math.abs(t.b[0]-t.a[0])/i,h=Math.abs(t.b[1]-t.a[1])/s;l={id:r,kind:t.kind,x:e,y:o,w:c,h:h,...pa(n,!0)}}this._curSpaceCfg.decor=[...this._decorList,l],this._decorSel=r,this._recordGeometry(this._t("history.decor_add"),o),this._saveConfig(),this.requestUpdate()}_decorShapeDown(t,e){if("decor"!==this._mode)return;const i=this._decorTool;if("text"===i){if("text"!==e.kind)return;return t.stopPropagation(),t.preventDefault(),void this._decorOpenText(e)}"select"!==i&&"erase"!==i||(t.stopPropagation(),t.preventDefault(),"erase"!==i?(this._decorSel=e.id,this._decorMove={id:e.id,start:this._svgPoint(t),orig:JSON.parse(JSON.stringify(e)),pid:t.pointerId,moved:!1,before:this._geometrySnapshot()},bm(t)):this._decorEraseConfirm={id:e.id,kind:e.kind})}_decorMoveUpdate(t){const e=this._decorMove;if("furniture"===e.orig?.kind)return void this._furnMoveUpdate(t);const i=this._svgPoint(t),s=e.orig,n=("line"===s.kind?s.x1:s.x)*pm,o=("line"===s.kind?s.y1:s.y)*this._decorH,r=this._decorSnap([n+(i[0]-e.start[0]),o+(i[1]-e.start[1])],t.pointerType,e.id);let a=(r[0]-n)/pm,l=(r[1]-o)/this._decorH;const c=e.orig,h="line"===c.kind?Math.min(c.x1,c.x2):c.x,d="line"===c.kind?Math.min(c.y1,c.y2):c.y,p="line"===c.kind?Math.abs(c.x2-c.x1):c.w||0,u="line"===c.kind?Math.abs(c.y2-c.y1):c.h||0,_=yc;a=Math.max(-_-h,Math.min(_-h-p,a)),l=Math.max(-_-d,Math.min(_-d-u,l)),(a||l)&&(e.moved=!0);this._curSpaceCfg.decor=this._decorList.map(t=>{if(t.id!==e.id)return t;const i=e.orig;return"line"===t.kind?{...t,x1:i.x1+a,y1:i.y1+l,x2:i.x2+a,y2:i.y2+l}:{...t,x:i.x+a,y:i.y+l}}),this.requestUpdate()}_decorShapeDbl(t,e){"decor"===this._mode&&"select"===this._decorTool&&(t.preventDefault(),t.stopPropagation(),this._decorMove=null,this._decorSel=e.id,this._openDecorProperties(e))}_openDecorProperties(t){if("decor"!==this._mode||"select"!==this._decorTool)return;if("text"===t.kind)return void this._decorOpenText(t);if(!["line","rect","ellipse","furniture"].includes(t.kind))return;const e=this._decorResolvedStyle(t),i="line"===t.kind?t:null,s=this._decorBoxOf(t);this._decorShapeDialog={id:t.id,kind:t.kind,color:e.color,opacity:e.opacity,widthCm:e.widthCm,angle:this._angleField(aa(i?Os([i.x1*pm,i.y1*this._decorH],[i.x2*pm,i.y2*this._decorH]):t.angle)),...i?{lengthCm:ha(Math.hypot((i.x2-i.x1)*pm,(i.y2-i.y1)*this._decorH),this._cellCm,this._gridPitch),lineStyle:"dashed"===i.line_style?"dashed":"solid"}:{},...s?{sizeWCm:ha(s.w,this._cellCm,this._gridPitch),sizeHCm:ha(s.h,this._cellCm,this._gridPitch)}:{},..."furniture"===t.kind?{symbol:t.symbol}:{},..."rect"===t.kind||"ellipse"===t.kind?{fill:e.fill,fillColor:e.fillColor,fillOpacity:e.fillOpacity}:{}}}_decorOpenText(t){if("text"!==t.kind)return;let e=String(t.text??"");const i=[...e.matchAll(/\{([^{}\r\n]+)\}/g)].some(t=>!!Yi(t[1])),s=String(t.unit??"").trim(),n="state"===String(t.attr??"").trim().toLowerCase()?null:t.attr,o=i||s?"":Xi(t.entity,n),r=!(!String(t.entity??"").trim()||i||o&&!s);if(o&&!r){const t=e.indexOf("{}");e=t>=0?e.slice(0,t)+o+e.slice(t+2):`${e}${e?" ":""}${o}`}this._decorTextDialog={id:t.id,x:t.x,y:t.y,text:e,color:Rt(t.color,this._decorStyle.color),opacity:ra(t.opacity,this._decorStyle.opacity),angle:this._angleField(t.angle),sizeCm:this._decorTextSizeCm(t),pickerEntity:t.entity||"",preserveLegacy:r||void 0},this._decorTextSelection={start:e.length,end:e.length}}_decorRememberTextSelection(t){this._decorTextSelection={start:t.selectionStart??t.value.length,end:t.selectionEnd??t.value.length}}_decorInsertLiveVariable(t){const e=this._decorTextDialog;if(!e)return;const i=Xi(e.pickerEntity,t);if(!i)return;const s=e.text,n=Math.max(0,Math.min(s.length,this._decorTextSelection.start)),o=Math.max(n,Math.min(s.length,this._decorTextSelection.end));if(s.length-(o-n)+i.length>200)return;const r=s.slice(0,n)+i+s.slice(o),a=n+i.length;this._decorTextSelection={start:a,end:a},this._decorTextDialog={...e,text:r,preserveLegacy:void 0},this.updateComplete.then(()=>{const t=this.renderRoot.querySelector("textarea.dtarea");t&&(t.focus(),t.setSelectionRange(a,a))})}_decorSaveText(){const t=this._decorTextDialog,e=String(t?.text??"").replace(/\r\n?/g,"\n").trim();if(!t||!e)return void(this._decorTextDialog=null);const i=this._geometrySnapshot(),s=this._curSpaceCfg,n={color:t.color,opacity:ra(t.opacity),size_cm:Number(Math.max(.1,Math.min(Yg,t.sizeCm)).toFixed(4)),...aa(t.angle)?{angle:aa(t.angle)}:{}};if(t.id)s.decor=this._decorList.map(i=>{if(i.id!==t.id)return i;if("text"!==i.kind)return i;if(t.preserveLegacy){const{angle:t,size:s,scale:o,...r}=i;return{...r,text:e,...n}}const{entity:s,attr:o,unit:r,...a}=i,{angle:l,size:c,scale:h,...d}=a;return{...d,text:e,...n}});else{const i="dc"+Date.now().toString(36)+Math.random().toString(36).slice(2,5);s.decor=[...this._decorList,{id:i,kind:"text",x:t.x,y:t.y,text:e,...n}],this._decorSel=i}this._decorTextDialog=null,this._recordGeometry(this._t(t.id?"history.decor_edit":"history.decor_add"),i),this._saveConfig(),this.requestUpdate()}_decorSaveShape(){const t=this._decorShapeDialog;if(!t)return;const e=this._geometrySnapshot(),i={color:t.color,opacity:ra(t.opacity),widthCm:Math.max(.1,Math.min(100,Number(t.widthCm)||.1)),fill:!!t.fill,fillColor:t.fillColor||t.color,fillOpacity:ra(t.fillOpacity,.25)};this._curSpaceCfg.decor=this._decorList.map(e=>{if(e.id!==t.id)return e;const s="rect"===t.kind||"ellipse"===t.kind,n=pa(i,s);if("line"===e.kind){const i=(e.x1+e.x2)/2*pm,s=(e.y1+e.y2)/2*this._decorH,o=ca(Math.max(.1,Number(t.lengthCm)||.1),this._cellCm,this._gridPitch),r=aa(t.angle)*Math.PI/180,a=Math.cos(r)*o/2,l=Math.sin(r)*o/2,c=this._snap([i-a,s-l]),h=this._snap([i+a,s+l]),{width:d,line_style:p,...u}=e;return{...u,...n,x1:Cc(c[0]/pm),y1:Cc(c[1]/this._decorH),x2:Cc(h[0]/pm),y2:Cc(h[1]/this._decorH),..."dashed"===t.lineStyle?{line_style:"dashed"}:{}}}if("rect"===e.kind||"ellipse"===e.kind||"furniture"===e.kind){const i=e.w*pm,s=e.h*this._decorH,o=Math.max(this._gridPitch,ai(ca(Number(t.sizeWCm),this._cellCm,this._gridPitch),this._gridPitch)),r=Math.max(this._gridPitch,ai(ca(Number(t.sizeHCm),this._cellCm,this._gridPitch),this._gridPitch)),a=e.x*pm+i/2,l=e.y*this._decorH+s/2,c=aa(t.angle),h=la({x:a-o/2,y:l-r/2},c,t=>this._snap(t)),{width:d,angle:p,...u}=e;return{...u,...n,x:Cc(h[0]/pm),y:Cc(h[1]/this._decorH),w:o/pm,h:r/this._decorH,..."furniture"===e.kind&&t.symbol?{symbol:t.symbol}:{},...c?{angle:c}:{}}}return e}),this._decorStyle={...i,fill:"rect"===t.kind||"ellipse"===t.kind?i.fill:this._decorStyle.fill,fillColor:"rect"===t.kind||"ellipse"===t.kind?i.fillColor:this._decorStyle.fillColor,fillOpacity:"rect"===t.kind||"ellipse"===t.kind?i.fillOpacity:this._decorStyle.fillOpacity},this._decorShapeDialog=null,this._recordGeometry(this._t("history.decor_edit"),e),this._saveConfig(),this.requestUpdate()}get _dtSel(){return"decor"===this._mode&&"select"===this._decorTool&&this._decorSel&&this._decorList.find(t=>t.id===this._decorSel)||null}_dtPivot(t){return"line"===t.kind?[(t.x1+t.x2)/2*pm,(t.y1+t.y2)/2*this._decorH]:"furniture"===t.kind||"rect"===t.kind||"ellipse"===t.kind?[(t.x+t.w/2)*pm,(t.y+t.h/2)*this._decorH]:[t.x*pm,t.y*this._decorH]}_dtApply(t,e){const i=this._curSpaceCfg;i&&(i.decor=this._decorList.map(i=>{if(i.id!==t)return i;const s={...i};"text"===i.kind&&void 0!==e.textSizeCm&&(delete s.size,delete s.scale);const n={...s};return void 0!==e.textSizeCm&&(n.size_cm=Number(Math.max(.1,Math.min(Yg,e.textSizeCm)).toFixed(4))),void 0!==e.angle&&(e.angle?n.angle=Number(e.angle.toFixed(2)):delete n.angle),n}),this._cfgEpoch++,this.requestUpdate())}_dtStart(t,e,i,s){const n=this._dtSel;if(!n)return;t.stopPropagation(),t.preventDefault();const[o,r]=this._dtPivot(n),a=this._svgPoint(t),l=this._decorBoxOf(n);this._dtDrag={id:n.id,kind:e,pid:t.pointerId,ax:o,ay:r,r0:Math.hypot(a[0]-o,a[1]-r),a0:180*Math.atan2(a[1]-r,a[0]-o)/Math.PI,textSizeCm0:"text"===n.kind?this._decorTextSizeCm(n):1,angle0:"line"===n.kind?0:Number(n.angle)||0,sgx:i?.[0],sgy:i?.[1],orig:l||void 0,origShape:JSON.parse(JSON.stringify(n)),before:this._geometrySnapshot(),lineEnd:s,moved:!1},bm(t)}_dtMove(t){const e=this._dtDrag;if(!e)return;const i=this._svgPoint(t);if(void 0!==e.lineEnd&&"line"===e.origShape.kind){const s=this._decorSnap(i,t.pointerType,e.id),n=Cc(s[0]/pm),o=Cc(s[1]/this._decorH),r=e.origShape,a=0===e.lineEnd?r.x1:r.x2,l=0===e.lineEnd?r.y1:r.y2;return(Math.abs(n-a)>1e-9||Math.abs(o-l)>1e-9)&&(e.moved=!0),void this._replaceDecor(e.id,0===e.lineEnd?{x1:n,y1:o}:{x2:n,y2:o})}if("scale"===e.kind&&e.orig){const s=ga(e.orig,e.sgx??1,e.sgy??1,i[0],i[1],!t.shiftKey,this._gridPitch,this._gridPitch),n=Math.abs(s.x-e.orig.x)>1e-6||Math.abs(s.y-e.orig.y)>1e-6||Math.abs(s.w-e.orig.w)>1e-6||Math.abs(s.h-e.orig.h)>1e-6;if(!n&&!e.moved)return;return e.moved||=n,void this._decorApplyBox(e.id,s)}if("scale"===e.kind){const t=Math.hypot(i[0]-e.ax,i[1]-e.ay);if(e.r0<1e-6)return;const s=Math.max(.1,Math.min(Yg,e.textSizeCm0*(t/e.r0))),n=Math.abs(s-e.textSizeCm0)>1e-6;if(!n&&!e.moved)return;return e.moved||=n,void this._dtApply(e.id,{textSizeCm:s})}const s=180*Math.atan2(i[1]-e.ay,i[0]-e.ax)/Math.PI;let n=e.angle0+(s-e.a0);t.shiftKey||(n=5*Math.round(n/5)),n=(n%360+360)%360,n>180&&(n-=360);const o=Math.abs(n-e.angle0)>1e-6;(o||e.moved)&&(e.moved||=o,this._dtApply(e.id,{angle:n}))}_dtUp(){const t=this._dtDrag;this._dtDrag=null,t?.moved&&(this._recordGeometry(this._t("history.decor_transform"),t.before),this._saveConfig()),this.requestUpdate()}_dtMeasure(){const t=this._dtSel;if(!t)return void(this._dtBox&&(this._dtBox=null,this.requestUpdate()));let e;if("line"===t.kind){const i=t.x1*pm,s=t.y1*this._decorH,n=t.x2*pm,o=t.y2*this._decorH;e={id:t.id,x:Math.min(i,n),y:Math.min(s,o),w:Math.abs(n-i),h:Math.abs(o-s)}}else if("furniture"===t.kind||"rect"===t.kind||"ellipse"===t.kind)e={id:t.id,x:t.x*pm,y:t.y*this._decorH,w:t.w*pm,h:t.h*this._decorH};else{const i=this.renderRoot.querySelector(`text.dtext[data-id="${t.id}"]`);if(!i||"function"!=typeof i.getBBox)return;let s;try{s=i.getBBox()}catch{return}if(!s||!s.width&&!s.height)return;e={id:t.id,x:s.x,y:s.y,w:s.width,h:s.height}}const i=this._dtBox;i&&i.id===e.id&&Math.abs(i.x-e.x)<.01&&Math.abs(i.y-e.y)<.01&&Math.abs(i.w-e.w)<.01&&Math.abs(i.h-e.h)<.01||(this._dtBox=e,this.requestUpdate())}_deleteDecor(t){if(!this._decorList.some(e=>e.id===t))return;const e=this._geometrySnapshot();this._curSpaceCfg.decor=this._decorList.filter(e=>e.id!==t),this._decorSel===t&&(this._decorSel=null),this._recordGeometry(this._t("history.decor_delete"),e),this._saveConfig(),this.requestUpdate()}_decorDeleteSel(){this._decorSel&&this._deleteDecor(this._decorSel)}_confirmDecorErase(){const t=this._decorEraseConfirm;this._decorEraseConfirm=null,t&&this._deleteDecor(t.id)}get _furnWalls(){const t=this._rawPhysicalBodiesR().flatMap(t=>t.map((e,i)=>{const s=t[(i+1)%t.length];return[e[0],e[1],s[0],s[1]]}));return[...this._segments,...t]}get _furnWallReach(){return 6*this._gridPitch}_furnFieldValue(t){return Math.round(100*(this._imperial?t/30.48:t/100))/100}_furnFieldToCm(t){return e=this._imperial?30.48*t:100*t,Number.isFinite(e)?Math.max(1,Math.min(1e4,e)):1;var e}_furnPick(t){const e=function(t){const e=Vc(t);return e?{w:e.w,h:e.h}:{w:60,h:60}}(t);this._furnPalette={symbol:t,w:e.w,h:e.h}}_furnPlace(t,e=!1){const i=this._furnPalette,s=this._curSpaceCfg;if(!i||!s)return;const n=pm,o=this._decorH,r=Zc(Yc(i.w,this._cellCm,this._gridPitch,n)),a=Zc(Yc(i.h,this._cellCm,this._gridPitch,n)),l=this._geometrySnapshot(),c=this._decorSnap(t);let h=c[0],d=c[1],p=0;const u=e?null:ih(h,d,a*o,this._furnWalls,this._furnWallReach,this._gridPitch);u&&(h=u.cx,d=u.cy,p=u.angle);const _="df"+Date.now().toString(36)+Math.random().toString(36).slice(2,5),g={id:_,kind:"furniture",symbol:i.symbol,x:Cc(h/n-r/2),y:Cc(d/o-a/2),w:r,h:a,...pa(this._decorStyle,!1)};p&&(g.angle=Number(p.toFixed(2))),s.decor=[...this._decorList,g],this._decorSel=_,this._decorTool="select",this._furnPalette=null,this._recordGeometry(this._t("history.decor_add"),l),this._saveConfig(),this.requestUpdate()}_furnMoveUpdate(t){const e=this._decorMove;if("furniture"!==e.orig.kind)return;const i=e.orig,s=this._curSpaceCfg;if(!s)return;const n=pm,o=this._decorH,r=this._svgPoint(t),a=(i.x+i.w/2)*n+(r[0]-e.start[0]),l=(i.y+i.h/2)*o+(r[1]-e.start[1]);let c,h,d=Number(i.angle)||0;const p=t.shiftKey?null:ih(a,l,i.h*o,this._furnWalls,this._furnWallReach,this._gridPitch);if(p)c=p.cx/n-i.w/2,h=p.cy/o-i.h/2,d=p.angle;else{const s=this._decorSnap([a-i.w/2*n,l-i.h/2*o],t.pointerType,e.id);c=s[0]/n,h=s[1]/o}c=Cc(c),h=Cc(h),(Math.abs(c-i.x)>1e-9||Math.abs(h-i.y)>1e-9||Math.abs(d-(Number(i.angle)||0))>1e-9)&&(e.moved=!0),s.decor=this._decorList.map(t=>{if(t.id!==e.id)return t;const i={...t,x:c,y:h};return d?i.angle=Number(d.toFixed(2)):delete i.angle,i}),this.requestUpdate()}_decorApplyBox(t,e){const i=this._curSpaceCfg;if(!i)return;const s=pm,n=this._decorH;i.decor=this._decorList.map(i=>{if(i.id!==t)return i;const o=la(e,i.angle,t=>this._snap(t));return{...i,x:Cc(o[0]/s),y:Cc(o[1]/n),w:Math.max(this._gridPitch/s,Math.min(2*yc,e.w/s)),h:Math.max(this._gridPitch/n,Math.min(2*yc,e.h/n))}}),this._cfgEpoch++,this.requestUpdate()}get _furnLive(){const t=this._dtDrag;if(!t||"scale"!==t.kind||!t.orig)return null;const e=this._decorList.find(e=>e.id===t.id);if(!e||"furniture"!==e.kind)return null;const i=pm,s=this._decorH,n=e.w*i,o=e.h*s,r=function(t,e,i,s,n){const o=t+i/2,r=e+s/2,a=(Number(n)||0)*Math.PI/180,l=Math.cos(a),c=Math.sin(a),h=(t,e)=>{const i=t-o,s=e-r;return[o+i*l-s*c,r+i*c+s*l]};return[h(t,e),h(t+i,e),h(t+i,e+s),h(t,e+s)]}(e.x*i,e.y*s,n,o,Number(e.angle)||0),a=(t,e)=>[(t[0]+e[0])/2,(t[1]+e[1])/2],l=a(r[0],r[1]),c=a(r[0],r[3]);return[{x:l[0],y:l[1],text:this._fmtLen([0,0],[n,0])},{x:c[0],y:c[1],text:this._fmtLen([0,0],[0,o])}]}_renderFurnPalette(){const t=this._furnPalette,e=this._t(this._imperial?"gs.unit_ft":"gs.unit_m");return W`
t.stopPropagation()}> + @lostpointercapture=${t=>this._rszPointerCancel(t)}>`),o.push(j``)}return j`${o}`}get _openingsR(){const t=this._curSpaceCfg,e=this._spaceH,i=this._spaceModel();return i?(t?.openings||[]).flatMap(t=>{const s={...t,rx:t.x*um,ry:t.y*e,rlen:t.length*um};if(!t.host)return[s];const n=Rd(t,i.partitions,um,this._cellCm,this._gridPitch);if(!n.resolved)return"plan"===this._mode?[{...s,orphanReason:n.reason||"invalid-host"}]:[];let[o,a]=n.resolved.center;const r=this._physicalDrag;return r?.moved&&"partition"===r.kind&&r.id===t.host.id&&(o+=r.delta[0],a+=r.delta[1]),[{...t,rx:o,ry:a,rlen:n.resolved.length,angle:n.resolved.angle,partitionHost:n.resolved}]}):[]}_partitionOpeningCuts(t=this._spaceModel(),e=()=>!0){if(!t)return[];return $_(x_(this._curSpaceCfg?.id===t.id?this._curSpaceCfg:null,t,this._cellCm,this._gridPitch,um),e)}_roomWallOpeningInputs(t=this._openingsR,e=this._spaceModel()){if(!e)return[];const i=this._openPairs().flatMap(t=>t.segs);return S_(t,e,this._spaceWalls,i,this._wallKeyPitch,this._cellCm,this._gridPitch,um)}_openingFace(t,e,i){return t.partitionHost?Ed(t.partitionHost,i):zl(e,{x:t.rx,y:t.ry,angle:t.angle,length:t.rlen,flip_v:i})}_cmToUnits(t){return t/this._cellCm*this._gridPitch}get _decorList(){const t=this._curSpaceCfg;return Array.isArray(t?.decor)?t.decor:[]}get _decorH(){return um}_decorResolvedStyle(t){return function(t,e,i,s=or){const n="rect"===t?.kind||"ellipse"===t?.kind,o=t,a=Rt(o?.color,s.color);return{color:a,opacity:ar(o?.opacity,s.opacity),widthCm:dr(t,e,i,s.widthCm),fill:!!n&&!0===o?.fill,fillColor:Rt(o?.fill_color,o?.fill?a:s.fillColor),fillOpacity:n&&o?.fill?ar(o?.fill_opacity,.25):s.fillOpacity}}(t,this._cellCm,this._gridPitch,or)}_decorWidthUnits(t){return((t,e,i,s=or.widthCm)=>{const n=Number(t?.width_cm);if(Number.isFinite(n)&&n>0)return cr(n,e,i);const o=Number(t?.width);return Number.isFinite(o)&&o>0?o:cr(s,e,i)})(t,this._cellCm,this._gridPitch,or.widthCm)}_decorTextSizeCm(t){if("text"===t?.kind){const e=Number(t.size_cm);return Number.isFinite(e)&&e>0?e:hr(es*is(t),this._cellCm,this._gridPitch)}return hr(es,this._cellCm,this._gridPitch)}_decorTextUnits(t){if("text"!==t.kind)return es;const e=Number(t.size_cm);return Number.isFinite(e)&&e>0?cr(e,this._cellCm,this._gridPitch):es*is(t)}_decorSmallField(t){return Math.round(100*(this._imperial?t/2.54:t))/100}_decorSmallCm(t){const e=this._imperial?2.54*t:t;return Number.isFinite(e)?Math.max(.1,Math.min(100,e)):.1}_decorTextCm(t){const e=this._imperial?2.54*t:t;return Number.isFinite(e)?Math.max(.1,Math.min(Xg,e)):.1}_decorLargeField(t){return Math.round(100*(this._imperial?t/30.48:t/100))/100}_decorLargeCm(t){const e=this._imperial?30.48*t:100*t;return Number.isFinite(e)?Math.max(.1,Math.min(bc*this._cellCm,e)):.1}_angleField(t){const e=Number(t);return Number.isFinite(e)?String(Number(e.toFixed(3))):"0"}_decorBoxOf(t){return"rect"!==t.kind&&"ellipse"!==t.kind&&"furniture"!==t.kind?null:{x:t.x*um,y:t.y*this._decorH,w:t.w*um,h:t.h*this._decorH,angle:rr(t.angle)||void 0}}_decorSnapGeometry(t){const e=this._spaceModel();if(!e)return{points:[],segments:[]};const i=t||"",s=this._decorSnapCache;if(s&&s.epoch===this._cfgEpoch&&s.space===this._space&&s.height===this._decorH&&s.exclude===i)return s.geometry;const n=[];for(const e of this._decorList)if(e.id!==t)if("line"===e.kind){const t=[e.x1*um,e.y1*this._decorH],i=[e.x2*um,e.y2*this._decorH];n.push({points:[t,i,[(t[0]+i[0])/2,(t[1]+i[1])/2]],segments:[{a:t,b:i}]})}else if("text"===e.kind)n.push({points:[[e.x*um,e.y*this._decorH]],segments:[]});else{const t=this._decorBoxOf(e);t&&n.push(_r(t))}for(const t of e.rooms){const e=hi(t);e?.length&&n.push({points:e.flatMap((t,i)=>{const s=e[(i+1)%e.length];return[t,[(t[0]+s[0])/2,(t[1]+s[1])/2]]}),segments:e.map((t,i)=>({a:t,b:e[(i+1)%e.length]}))})}const o=function(t){return{points:t.flatMap(t=>t.points),segments:t.flatMap(t=>t.segments)}}(n);return this._decorSnapCache={epoch:this._cfgEpoch,space:this._space,height:this._decorH,exclude:i,geometry:o},o}_decorSnap(t,e="mouse",i){const s=this._stageEl,n=this._viewOr(this._baseVb()),o="touch"===e||"pen"===e?14:8,a=s?n.w/Math.max(1,s.clientWidth)*o:this._gridPitch;return function(t,e,i,s){const n=s(t);let o=null;for(const n of e.points){const e=s(n),a=Math.hypot(e[0]-t[0],e[1]-t[1]);a<=i&&(!o||athis._snap(t)).point}_replaceDecor(t,e){const i=this._curSpaceCfg;i&&(i.decor=this._decorList.map(i=>i.id===t?{...i,...e}:i),this.requestUpdate())}_cancelDecorGesture(){const t=this._decorMove?.before||this._dtDrag?.before||this._bdDrag?.before,e=t&&this._serverCfg?.spaces.find(e=>e.id===t.spaceId);if(t&&e){const i=t=>JSON.parse(JSON.stringify(t));void 0!==t.decor?e.decor=i(t.decor):delete e.decor;for(const t of["plan_x","plan_y","plan_scale","plan_scale_x","plan_scale_y","plan_angle"])delete e[t];Object.assign(e,i(t.plan_transform||{})),this._cfgEpoch++}this._decorMove=null,this._dtDrag=null,this._bdDrag=null,this.requestUpdate()}_decorPointerDown(t){const e=this._decorTool;if("select"===e||"erase"===e?t.target.closest?.(".dshape"):null)return!0;if("line"===e||"rect"===e||"ellipse"===e){t.preventDefault();const i=this._decorSnap(this._svgPoint(t),t.pointerType);return this._decorDraft={kind:e,a:i,b:i,pid:t.pointerId},wm(t),!0}if("text"===e){const e=this._decorSnap(this._svgPoint(t),t.pointerType);return this._decorTextDialog={x:Dc(e[0]/um),y:Dc(e[1]/this._decorH),text:"",color:this._decorStyle.color,opacity:this._decorStyle.opacity,angle:"0",sizeCm:hr(es,this._cellCm,this._gridPitch)},this._decorTextSelection={start:0,end:0},!0}if("furniture"===e)return!!this._furnPalette&&(t.preventDefault(),this._furnPlace(this._svgPoint(t),t.shiftKey),!0);if("select"===e&&(this._decorSel=null),this._bdMovable){const e=this._bdRect,i=this._svgPoint(t),s=e.x+e.w/2,n=e.y+e.h/2,o=-rr(e.angle)*Math.PI/180,a=i[0]-s,r=i[1]-n,l=[s+a*Math.cos(o)-r*Math.sin(o),n+a*Math.sin(o)+r*Math.cos(o)];if(l[0]>=e.x&&l[0]<=e.x+e.w&&l[1]>=e.y&&l[1]<=e.y+e.h)return t.preventDefault(),this._bdStart(t)}return!1}_decorCommitDraft(){const t=this._decorDraft;if(this._decorDraft=null,!t)return;const e=.5*this._gridPitch;if(!function(t,e,i,s){const n=Math.abs(i[0]-e[0]),o=Math.abs(i[1]-e[1]);return"line"===t?Math.hypot(n,o)>=s:n>=s&&o>=s}(t.kind,t.a,t.b,e))return;const i=um,s=this._decorH,n=this._decorStyle,o=this._geometrySnapshot(),a="dc"+Date.now().toString(36)+Math.random().toString(36).slice(2,5),r=Dc;let l;if("line"===t.kind)l={id:a,kind:"line",x1:r(t.a[0]/i),y1:r(t.a[1]/s),x2:r(t.b[0]/i),y2:r(t.b[1]/s),...pr(n,!1)};else{const e=r(Math.min(t.a[0],t.b[0])/i),o=r(Math.min(t.a[1],t.b[1])/s),c=Math.abs(t.b[0]-t.a[0])/i,h=Math.abs(t.b[1]-t.a[1])/s;l={id:a,kind:t.kind,x:e,y:o,w:c,h:h,...pr(n,!0)}}this._curSpaceCfg.decor=[...this._decorList,l],this._decorSel=a,this._recordGeometry(this._t("history.decor_add"),o),this._saveConfig(),this.requestUpdate()}_decorShapeDown(t,e){if("decor"!==this._mode)return;const i=this._decorTool;if("text"===i){if("text"!==e.kind)return;return t.stopPropagation(),t.preventDefault(),void this._decorOpenText(e)}"select"!==i&&"erase"!==i||(t.stopPropagation(),t.preventDefault(),"erase"!==i?(this._decorSel=e.id,this._decorMove={id:e.id,start:this._svgPoint(t),orig:JSON.parse(JSON.stringify(e)),pid:t.pointerId,moved:!1,before:this._geometrySnapshot()},wm(t)):this._decorEraseConfirm={id:e.id,kind:e.kind})}_decorMoveUpdate(t){const e=this._decorMove;if("furniture"===e.orig?.kind)return void this._furnMoveUpdate(t);const i=this._svgPoint(t),s=e.orig,n=("line"===s.kind?s.x1:s.x)*um,o=("line"===s.kind?s.y1:s.y)*this._decorH,a=this._decorSnap([n+(i[0]-e.start[0]),o+(i[1]-e.start[1])],t.pointerType,e.id);let r=(a[0]-n)/um,l=(a[1]-o)/this._decorH;const c=e.orig,h="line"===c.kind?Math.min(c.x1,c.x2):c.x,d="line"===c.kind?Math.min(c.y1,c.y2):c.y,p="line"===c.kind?Math.abs(c.x2-c.x1):c.w||0,u="line"===c.kind?Math.abs(c.y2-c.y1):c.h||0,_=bc;r=Math.max(-_-h,Math.min(_-h-p,r)),l=Math.max(-_-d,Math.min(_-d-u,l)),(r||l)&&(e.moved=!0);this._curSpaceCfg.decor=this._decorList.map(t=>{if(t.id!==e.id)return t;const i=e.orig;return"line"===t.kind?{...t,x1:i.x1+r,y1:i.y1+l,x2:i.x2+r,y2:i.y2+l}:{...t,x:i.x+r,y:i.y+l}}),this.requestUpdate()}_decorShapeDbl(t,e){"decor"===this._mode&&"select"===this._decorTool&&(t.preventDefault(),t.stopPropagation(),this._decorMove=null,this._decorSel=e.id,this._openDecorProperties(e))}_openDecorProperties(t){if("decor"!==this._mode||"select"!==this._decorTool)return;if("text"===t.kind)return void this._decorOpenText(t);if(!["line","rect","ellipse","furniture"].includes(t.kind))return;const e=this._decorResolvedStyle(t),i="line"===t.kind?t:null,s=this._decorBoxOf(t);this._decorShapeDialog={id:t.id,kind:t.kind,color:e.color,opacity:e.opacity,widthCm:e.widthCm,angle:this._angleField(rr(i?Os([i.x1*um,i.y1*this._decorH],[i.x2*um,i.y2*this._decorH]):t.angle)),...i?{lengthCm:hr(Math.hypot((i.x2-i.x1)*um,(i.y2-i.y1)*this._decorH),this._cellCm,this._gridPitch),lineStyle:"dashed"===i.line_style?"dashed":"solid"}:{},...s?{sizeWCm:hr(s.w,this._cellCm,this._gridPitch),sizeHCm:hr(s.h,this._cellCm,this._gridPitch)}:{},..."furniture"===t.kind?{symbol:t.symbol}:{},..."rect"===t.kind||"ellipse"===t.kind?{fill:e.fill,fillColor:e.fillColor,fillOpacity:e.fillOpacity}:{}}}_decorOpenText(t){if("text"!==t.kind)return;let e=String(t.text??"");const i=[...e.matchAll(/\{([^{}\r\n]+)\}/g)].some(t=>!!Yi(t[1])),s=String(t.unit??"").trim(),n="state"===String(t.attr??"").trim().toLowerCase()?null:t.attr,o=i||s?"":Xi(t.entity,n),a=!(!String(t.entity??"").trim()||i||o&&!s);if(o&&!a){const t=e.indexOf("{}");e=t>=0?e.slice(0,t)+o+e.slice(t+2):`${e}${e?" ":""}${o}`}this._decorTextDialog={id:t.id,x:t.x,y:t.y,text:e,color:Rt(t.color,this._decorStyle.color),opacity:ar(t.opacity,this._decorStyle.opacity),angle:this._angleField(t.angle),sizeCm:this._decorTextSizeCm(t),pickerEntity:t.entity||"",preserveLegacy:a||void 0},this._decorTextSelection={start:e.length,end:e.length}}_decorRememberTextSelection(t){this._decorTextSelection={start:t.selectionStart??t.value.length,end:t.selectionEnd??t.value.length}}_decorInsertLiveVariable(t){const e=this._decorTextDialog;if(!e)return;const i=Xi(e.pickerEntity,t);if(!i)return;const s=e.text,n=Math.max(0,Math.min(s.length,this._decorTextSelection.start)),o=Math.max(n,Math.min(s.length,this._decorTextSelection.end));if(s.length-(o-n)+i.length>200)return;const a=s.slice(0,n)+i+s.slice(o),r=n+i.length;this._decorTextSelection={start:r,end:r},this._decorTextDialog={...e,text:a,preserveLegacy:void 0},this.updateComplete.then(()=>{const t=this.renderRoot.querySelector("textarea.dtarea");t&&(t.focus(),t.setSelectionRange(r,r))})}_decorSaveText(){const t=this._decorTextDialog,e=String(t?.text??"").replace(/\r\n?/g,"\n").trim();if(!t||!e)return void(this._decorTextDialog=null);const i=this._geometrySnapshot(),s=this._curSpaceCfg,n={color:t.color,opacity:ar(t.opacity),size_cm:Number(Math.max(.1,Math.min(Xg,t.sizeCm)).toFixed(4)),...rr(t.angle)?{angle:rr(t.angle)}:{}};if(t.id)s.decor=this._decorList.map(i=>{if(i.id!==t.id)return i;if("text"!==i.kind)return i;if(t.preserveLegacy){const{angle:t,size:s,scale:o,...a}=i;return{...a,text:e,...n}}const{entity:s,attr:o,unit:a,...r}=i,{angle:l,size:c,scale:h,...d}=r;return{...d,text:e,...n}});else{const i="dc"+Date.now().toString(36)+Math.random().toString(36).slice(2,5);s.decor=[...this._decorList,{id:i,kind:"text",x:t.x,y:t.y,text:e,...n}],this._decorSel=i}this._decorTextDialog=null,this._recordGeometry(this._t(t.id?"history.decor_edit":"history.decor_add"),i),this._saveConfig(),this.requestUpdate()}_decorSaveShape(){const t=this._decorShapeDialog;if(!t)return;const e=this._geometrySnapshot(),i={color:t.color,opacity:ar(t.opacity),widthCm:Math.max(.1,Math.min(100,Number(t.widthCm)||.1)),fill:!!t.fill,fillColor:t.fillColor||t.color,fillOpacity:ar(t.fillOpacity,.25)};this._curSpaceCfg.decor=this._decorList.map(e=>{if(e.id!==t.id)return e;const s="rect"===t.kind||"ellipse"===t.kind,n=pr(i,s);if("line"===e.kind){const i=(e.x1+e.x2)/2*um,s=(e.y1+e.y2)/2*this._decorH,o=cr(Math.max(.1,Number(t.lengthCm)||.1),this._cellCm,this._gridPitch),a=rr(t.angle)*Math.PI/180,r=Math.cos(a)*o/2,l=Math.sin(a)*o/2,c=this._snap([i-r,s-l]),h=this._snap([i+r,s+l]),{width:d,line_style:p,...u}=e;return{...u,...n,x1:Dc(c[0]/um),y1:Dc(c[1]/this._decorH),x2:Dc(h[0]/um),y2:Dc(h[1]/this._decorH),..."dashed"===t.lineStyle?{line_style:"dashed"}:{}}}if("rect"===e.kind||"ellipse"===e.kind||"furniture"===e.kind){const i=e.w*um,s=e.h*this._decorH,o=Math.max(this._gridPitch,ri(cr(Number(t.sizeWCm),this._cellCm,this._gridPitch),this._gridPitch)),a=Math.max(this._gridPitch,ri(cr(Number(t.sizeHCm),this._cellCm,this._gridPitch),this._gridPitch)),r=e.x*um+i/2,l=e.y*this._decorH+s/2,c=rr(t.angle),h=lr({x:r-o/2,y:l-a/2},c,t=>this._snap(t)),{width:d,angle:p,...u}=e;return{...u,...n,x:Dc(h[0]/um),y:Dc(h[1]/this._decorH),w:o/um,h:a/this._decorH,..."furniture"===e.kind&&t.symbol?{symbol:t.symbol}:{},...c?{angle:c}:{}}}return e}),this._decorStyle={...i,fill:"rect"===t.kind||"ellipse"===t.kind?i.fill:this._decorStyle.fill,fillColor:"rect"===t.kind||"ellipse"===t.kind?i.fillColor:this._decorStyle.fillColor,fillOpacity:"rect"===t.kind||"ellipse"===t.kind?i.fillOpacity:this._decorStyle.fillOpacity},this._decorShapeDialog=null,this._recordGeometry(this._t("history.decor_edit"),e),this._saveConfig(),this.requestUpdate()}get _dtSel(){return"decor"===this._mode&&"select"===this._decorTool&&this._decorSel&&this._decorList.find(t=>t.id===this._decorSel)||null}_dtPivot(t){return"line"===t.kind?[(t.x1+t.x2)/2*um,(t.y1+t.y2)/2*this._decorH]:"furniture"===t.kind||"rect"===t.kind||"ellipse"===t.kind?[(t.x+t.w/2)*um,(t.y+t.h/2)*this._decorH]:[t.x*um,t.y*this._decorH]}_dtApply(t,e){const i=this._curSpaceCfg;i&&(i.decor=this._decorList.map(i=>{if(i.id!==t)return i;const s={...i};"text"===i.kind&&void 0!==e.textSizeCm&&(delete s.size,delete s.scale);const n={...s};return void 0!==e.textSizeCm&&(n.size_cm=Number(Math.max(.1,Math.min(Xg,e.textSizeCm)).toFixed(4))),void 0!==e.angle&&(e.angle?n.angle=Number(e.angle.toFixed(2)):delete n.angle),n}),this._cfgEpoch++,this.requestUpdate())}_dtStart(t,e,i,s){const n=this._dtSel;if(!n)return;t.stopPropagation(),t.preventDefault();const[o,a]=this._dtPivot(n),r=this._svgPoint(t),l=this._decorBoxOf(n);this._dtDrag={id:n.id,kind:e,pid:t.pointerId,ax:o,ay:a,r0:Math.hypot(r[0]-o,r[1]-a),a0:180*Math.atan2(r[1]-a,r[0]-o)/Math.PI,textSizeCm0:"text"===n.kind?this._decorTextSizeCm(n):1,angle0:"line"===n.kind?0:Number(n.angle)||0,sgx:i?.[0],sgy:i?.[1],orig:l||void 0,origShape:JSON.parse(JSON.stringify(n)),before:this._geometrySnapshot(),lineEnd:s,moved:!1},wm(t)}_dtMove(t){const e=this._dtDrag;if(!e)return;const i=this._svgPoint(t);if(void 0!==e.lineEnd&&"line"===e.origShape.kind){const s=this._decorSnap(i,t.pointerType,e.id),n=Dc(s[0]/um),o=Dc(s[1]/this._decorH),a=e.origShape,r=0===e.lineEnd?a.x1:a.x2,l=0===e.lineEnd?a.y1:a.y2;return(Math.abs(n-r)>1e-9||Math.abs(o-l)>1e-9)&&(e.moved=!0),void this._replaceDecor(e.id,0===e.lineEnd?{x1:n,y1:o}:{x2:n,y2:o})}if("scale"===e.kind&&e.orig){const s=gr(e.orig,e.sgx??1,e.sgy??1,i[0],i[1],!t.shiftKey,this._gridPitch,this._gridPitch),n=Math.abs(s.x-e.orig.x)>1e-6||Math.abs(s.y-e.orig.y)>1e-6||Math.abs(s.w-e.orig.w)>1e-6||Math.abs(s.h-e.orig.h)>1e-6;if(!n&&!e.moved)return;return e.moved||=n,void this._decorApplyBox(e.id,s)}if("scale"===e.kind){const t=Math.hypot(i[0]-e.ax,i[1]-e.ay);if(e.r0<1e-6)return;const s=Math.max(.1,Math.min(Xg,e.textSizeCm0*(t/e.r0))),n=Math.abs(s-e.textSizeCm0)>1e-6;if(!n&&!e.moved)return;return e.moved||=n,void this._dtApply(e.id,{textSizeCm:s})}const s=180*Math.atan2(i[1]-e.ay,i[0]-e.ax)/Math.PI;let n=e.angle0+(s-e.a0);t.shiftKey||(n=5*Math.round(n/5)),n=(n%360+360)%360,n>180&&(n-=360);const o=Math.abs(n-e.angle0)>1e-6;(o||e.moved)&&(e.moved||=o,this._dtApply(e.id,{angle:n}))}_dtUp(){const t=this._dtDrag;this._dtDrag=null,t?.moved&&(this._recordGeometry(this._t("history.decor_transform"),t.before),this._saveConfig()),this.requestUpdate()}_dtMeasure(){const t=this._dtSel;if(!t)return void(this._dtBox&&(this._dtBox=null,this.requestUpdate()));let e;if("line"===t.kind){const i=t.x1*um,s=t.y1*this._decorH,n=t.x2*um,o=t.y2*this._decorH;e={id:t.id,x:Math.min(i,n),y:Math.min(s,o),w:Math.abs(n-i),h:Math.abs(o-s)}}else if("furniture"===t.kind||"rect"===t.kind||"ellipse"===t.kind)e={id:t.id,x:t.x*um,y:t.y*this._decorH,w:t.w*um,h:t.h*this._decorH};else{const i=this.renderRoot.querySelector(`text.dtext[data-id="${t.id}"]`);if(!i||"function"!=typeof i.getBBox)return;let s;try{s=i.getBBox()}catch{return}if(!s||!s.width&&!s.height)return;e={id:t.id,x:s.x,y:s.y,w:s.width,h:s.height}}const i=this._dtBox;i&&i.id===e.id&&Math.abs(i.x-e.x)<.01&&Math.abs(i.y-e.y)<.01&&Math.abs(i.w-e.w)<.01&&Math.abs(i.h-e.h)<.01||(this._dtBox=e,this.requestUpdate())}_deleteDecor(t){if(!this._decorList.some(e=>e.id===t))return;const e=this._geometrySnapshot();this._curSpaceCfg.decor=this._decorList.filter(e=>e.id!==t),this._decorSel===t&&(this._decorSel=null),this._recordGeometry(this._t("history.decor_delete"),e),this._saveConfig(),this.requestUpdate()}_decorDeleteSel(){this._decorSel&&this._deleteDecor(this._decorSel)}_confirmDecorErase(){const t=this._decorEraseConfirm;this._decorEraseConfirm=null,t&&this._deleteDecor(t.id)}get _furnWalls(){const t=this._rawPhysicalBodiesR().flatMap(t=>t.map((e,i)=>{const s=t[(i+1)%t.length];return[e[0],e[1],s[0],s[1]]}));return[...this._segments,...t]}get _furnWallReach(){return 6*this._gridPitch}_furnFieldValue(t){return Math.round(100*(this._imperial?t/30.48:t/100))/100}_furnFieldToCm(t){return e=this._imperial?30.48*t:100*t,Number.isFinite(e)?Math.max(1,Math.min(1e4,e)):1;var e}_furnPick(t){const e=function(t){const e=Kc(t);return e?{w:e.w,h:e.h}:{w:60,h:60}}(t);this._furnPalette={symbol:t,w:e.w,h:e.h}}_furnPlace(t,e=!1){const i=this._furnPalette,s=this._curSpaceCfg;if(!i||!s)return;const n=um,o=this._decorH,a=Qc(Xc(i.w,this._cellCm,this._gridPitch,n)),r=Qc(Xc(i.h,this._cellCm,this._gridPitch,n)),l=this._geometrySnapshot(),c=this._decorSnap(t);let h=c[0],d=c[1],p=0;const u=e?null:sh(h,d,r*o,this._furnWalls,this._furnWallReach,this._gridPitch);u&&(h=u.cx,d=u.cy,p=u.angle);const _="df"+Date.now().toString(36)+Math.random().toString(36).slice(2,5),g={id:_,kind:"furniture",symbol:i.symbol,x:Dc(h/n-a/2),y:Dc(d/o-r/2),w:a,h:r,...pr(this._decorStyle,!1)};p&&(g.angle=Number(p.toFixed(2))),s.decor=[...this._decorList,g],this._decorSel=_,this._decorTool="select",this._furnPalette=null,this._recordGeometry(this._t("history.decor_add"),l),this._saveConfig(),this.requestUpdate()}_furnMoveUpdate(t){const e=this._decorMove;if("furniture"!==e.orig.kind)return;const i=e.orig,s=this._curSpaceCfg;if(!s)return;const n=um,o=this._decorH,a=this._svgPoint(t),r=(i.x+i.w/2)*n+(a[0]-e.start[0]),l=(i.y+i.h/2)*o+(a[1]-e.start[1]);let c,h,d=Number(i.angle)||0;const p=t.shiftKey?null:sh(r,l,i.h*o,this._furnWalls,this._furnWallReach,this._gridPitch);if(p)c=p.cx/n-i.w/2,h=p.cy/o-i.h/2,d=p.angle;else{const s=this._decorSnap([r-i.w/2*n,l-i.h/2*o],t.pointerType,e.id);c=s[0]/n,h=s[1]/o}c=Dc(c),h=Dc(h),(Math.abs(c-i.x)>1e-9||Math.abs(h-i.y)>1e-9||Math.abs(d-(Number(i.angle)||0))>1e-9)&&(e.moved=!0),s.decor=this._decorList.map(t=>{if(t.id!==e.id)return t;const i={...t,x:c,y:h};return d?i.angle=Number(d.toFixed(2)):delete i.angle,i}),this.requestUpdate()}_decorApplyBox(t,e){const i=this._curSpaceCfg;if(!i)return;const s=um,n=this._decorH;i.decor=this._decorList.map(i=>{if(i.id!==t)return i;const o=lr(e,i.angle,t=>this._snap(t));return{...i,x:Dc(o[0]/s),y:Dc(o[1]/n),w:Math.max(this._gridPitch/s,Math.min(2*bc,e.w/s)),h:Math.max(this._gridPitch/n,Math.min(2*bc,e.h/n))}}),this._cfgEpoch++,this.requestUpdate()}get _furnLive(){const t=this._dtDrag;if(!t||"scale"!==t.kind||!t.orig)return null;const e=this._decorList.find(e=>e.id===t.id);if(!e||"furniture"!==e.kind)return null;const i=um,s=this._decorH,n=e.w*i,o=e.h*s,a=function(t,e,i,s,n){const o=t+i/2,a=e+s/2,r=(Number(n)||0)*Math.PI/180,l=Math.cos(r),c=Math.sin(r),h=(t,e)=>{const i=t-o,s=e-a;return[o+i*l-s*c,a+i*c+s*l]};return[h(t,e),h(t+i,e),h(t+i,e+s),h(t,e+s)]}(e.x*i,e.y*s,n,o,Number(e.angle)||0),r=(t,e)=>[(t[0]+e[0])/2,(t[1]+e[1])/2],l=r(a[0],a[1]),c=r(a[0],a[3]);return[{x:l[0],y:l[1],text:this._fmtLen([0,0],[n,0])},{x:c[0],y:c[1],text:this._fmtLen([0,0],[0,o])}]}_renderFurnPalette(){const t=this._furnPalette,e=this._t(this._imperial?"gs.unit_ft":"gs.unit_m");return W`
t.stopPropagation()}>
${this._t("furn.title")} @@ -4936,16 +4936,16 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8
- ${jc.map(e=>W` + ${Uc.map(e=>W`
${this._t(`furn.group_${e}`)}
- ${Kc(e).map(e=>W``)}
`)} @@ -4961,22 +4961,22 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8 @input=${e=>this._furnPalette={...t,h:this._furnFieldToCm(Number(e.target.value))}} /> ${this._t("furn.place_hint")}
`:W`
${this._t("furn.pick_hint")}
`} -
`}get _bdBase(){const t=this._curSpaceCfg;return t?.plan_url?{...uc(t.plan_aspect,pm)}:null}get _bdRect(){const t=this._curSpaceCfg;return t?.plan_url?mc(t,pm):null}get _bdParams(){const t=this._curSpaceCfg,e=Number(t?.plan_x),i=Number(t?.plan_y),s=Number(t?.plan_scale),n=Number(t?.plan_scale_x),o=Number(t?.plan_scale_y),r=Number.isFinite(s)&&s>0?s:1;return{dx:Number.isFinite(e)?e:0,dy:Number.isFinite(i)?i:0,sx:Number.isFinite(n)&&n>0?n:r,sy:Number.isFinite(o)&&o>0?o:r,angle:aa(t?.plan_angle)}}_openBackdropDialog(t){if(!this._bdMovable||!this._bdRect)return;t?.preventDefault(),t?.stopPropagation(),this._bdDrag=null;const e=this._bdRect;this._backdropDialog={widthCm:ha(e.w,this._cellCm,this._gridPitch),heightCm:ha(e.h,this._cellCm,this._gridPitch),angle:this._angleField(e.angle)}}_saveBackdropDialog(){const t=this._backdropDialog,e=this._bdBase,i=this._bdRect;if(!t||!e||!i)return;const s=aa(t.angle),n=this._geometrySnapshot(),o=Math.min(e.w*gc,Math.max(e.w*_c,ai(ca(t.widthCm,this._cellCm,this._gridPitch),this._gridPitch))),r=Math.min(e.h*gc,Math.max(e.h*_c,ai(ca(t.heightCm,this._cellCm,this._gridPitch),this._gridPitch))),a=la({x:i.x+i.w/2-o/2,y:i.y+i.h/2-r/2},s,t=>this._snap(t));this._bdApply((a[0]-e.x)/pm,(a[1]-e.y)/pm,o/e.w,r/e.h,s),this._backdropDialog=null,this._recordGeometry(this._t("history.backdrop_transform"),n),this._saveConfig()}get _bdActive(){return"decor"===this._mode&&!!this._bdRect&&"backdrop"===this._decorTool}get _bdMovable(){return"decor"===this._mode&&"backdrop"===this._decorTool&&!!this._bdRect}_bdApply(t,e,i,s,n){const o=this._curSpaceCfg;if(!o)return;o.plan_x=Number(Cc(t).toFixed(6)),o.plan_y=Number(Cc(e).toFixed(6)),delete o.plan_scale,o.plan_scale_x=Number(Math.min(gc,Math.max(_c,i)).toFixed(6)),o.plan_scale_y=Number(Math.min(gc,Math.max(_c,s)).toFixed(6));const r=aa(n);r?o.plan_angle=Number(r.toFixed(2)):delete o.plan_angle,this._cfgEpoch++,this.requestUpdate()}_bdStart(t,e,i=!1){const s=this._bdBase,n=this._bdRect;if(!s||!n)return!1;const o=this._svgPoint(t),r=e?e[0]:0,a=e?e[1]:0,l=r>0?n.x:n.x+n.w,c=a>0?n.y:n.y+n.h;return this._bdDrag={kind:i?"rotate":e?"scale":"move",pid:t.pointerId,sx:o[0],sy:o[1],base:s,p0:this._bdParams,fx:l,fy:c,sgx:r,sgy:a,rect0:{x:n.x,y:n.y,w:n.w,h:n.h,angle:n.angle},before:this._geometrySnapshot(),moved:!1},bm(t),!0}_bdMove(t){const e=this._bdDrag;if(!e)return;const i=this._svgPoint(t),s=e.base;if("move"===e.kind){const t=e.rect0.x,n=e.rect0.y,o=this._snap([t+(i[0]-e.sx),n+(i[1]-e.sy)]),r=Math.abs(o[0]-t)>1e-9||Math.abs(o[1]-n)>1e-9;if(!r&&!e.moved)return;return e.moved||=r,void this._bdApply((o[0]-s.x)/pm,(o[1]-s.y)/pm,e.p0.sx,e.p0.sy,e.p0.angle)}if("rotate"===e.kind){const s=e.rect0.x+e.rect0.w/2,n=e.rect0.y+e.rect0.h/2,o=180*Math.atan2(e.sy-n,e.sx-s)/Math.PI;let r=e.p0.angle+(180*Math.atan2(i[1]-n,i[0]-s)/Math.PI-o);t.shiftKey||(r=5*Math.round(r/5)),r=aa(r);const a=Math.abs(r-e.p0.angle)>1e-9;if(!a&&!e.moved)return;return e.moved||=a,void this._bdApply(e.p0.dx,e.p0.dy,e.p0.sx,e.p0.sy,r)}const n=ga(e.rect0,e.sgx,e.sgy,i[0],i[1],!t.shiftKey,this._gridPitch,Math.min(s.w,s.h)*_c),o=n.w/Math.max(1e-9,s.w),r=n.h/Math.max(1e-9,s.h),a=Math.abs(o-e.p0.sx)>1e-9||Math.abs(r-e.p0.sy)>1e-9||Math.abs(n.x-e.rect0.x)>1e-9||Math.abs(n.y-e.rect0.y)>1e-9;if(!a&&!e.moved)return;e.moved||=a;const l=la(n,e.p0.angle,t=>this._snap(t));this._bdApply((l[0]-s.x)/pm,(l[1]-s.y)/pm,o,r,e.p0.angle)}get _bdMoved(){if("decor"!==this._mode||!this._bdRect)return!1;const t=this._bdParams;return 0!==t.dx||0!==t.dy||1!==t.sx||1!==t.sy||0!==t.angle}_bdReset(){const t=this._curSpaceCfg;if(!t)return;const e=this._geometrySnapshot();delete t.plan_x,delete t.plan_y,delete t.plan_scale,delete t.plan_scale_x,delete t.plan_scale_y,delete t.plan_angle,this._bdDrag=null,this._recordGeometry(this._t("history.backdrop_transform"),e),this._saveConfig(),this._showToast(this._t("decor.backdrop_reset_done")),this.requestUpdate()}_bdUp(){const t=this._bdDrag;this._bdDrag=null,t?.moved&&(this._recordGeometry(this._t("history.backdrop_transform"),t.before),this._saveConfig()),this.requestUpdate()}get _bdLive(){if(!this._bdDrag)return null;const t=this._bdRect;return t?{x:t.x+t.w/2,y:t.y+t.h/2,text:`${this._fmtLen([0,0],[t.w,0])} × ${this._fmtLen([0,0],[0,t.h])}`}:null}_renderBackdropFrame(t){const e=this._bdRect;if(!this._bdActive||!e)return G;const i=.02*Math.max(t.w,t.h),s=i/4,n=e.x+e.w/2,o=e.y+e.h/2,r=aa(e.angle),a=2.2*i;return j` +
`}get _bdBase(){const t=this._curSpaceCfg;return t?.plan_url?{..._c(t.plan_aspect,um)}:null}get _bdRect(){const t=this._curSpaceCfg;return t?.plan_url?fc(t,um):null}get _bdParams(){const t=this._curSpaceCfg,e=Number(t?.plan_x),i=Number(t?.plan_y),s=Number(t?.plan_scale),n=Number(t?.plan_scale_x),o=Number(t?.plan_scale_y),a=Number.isFinite(s)&&s>0?s:1;return{dx:Number.isFinite(e)?e:0,dy:Number.isFinite(i)?i:0,sx:Number.isFinite(n)&&n>0?n:a,sy:Number.isFinite(o)&&o>0?o:a,angle:rr(t?.plan_angle)}}_openBackdropDialog(t){if(!this._bdMovable||!this._bdRect)return;t?.preventDefault(),t?.stopPropagation(),this._bdDrag=null;const e=this._bdRect;this._backdropDialog={widthCm:hr(e.w,this._cellCm,this._gridPitch),heightCm:hr(e.h,this._cellCm,this._gridPitch),angle:this._angleField(e.angle)}}_saveBackdropDialog(){const t=this._backdropDialog,e=this._bdBase,i=this._bdRect;if(!t||!e||!i)return;const s=rr(t.angle),n=this._geometrySnapshot(),o=Math.min(e.w*mc,Math.max(e.w*gc,ri(cr(t.widthCm,this._cellCm,this._gridPitch),this._gridPitch))),a=Math.min(e.h*mc,Math.max(e.h*gc,ri(cr(t.heightCm,this._cellCm,this._gridPitch),this._gridPitch))),r=lr({x:i.x+i.w/2-o/2,y:i.y+i.h/2-a/2},s,t=>this._snap(t));this._bdApply((r[0]-e.x)/um,(r[1]-e.y)/um,o/e.w,a/e.h,s),this._backdropDialog=null,this._recordGeometry(this._t("history.backdrop_transform"),n),this._saveConfig()}get _bdActive(){return"decor"===this._mode&&!!this._bdRect&&"backdrop"===this._decorTool}get _bdMovable(){return"decor"===this._mode&&"backdrop"===this._decorTool&&!!this._bdRect}_bdApply(t,e,i,s,n){const o=this._curSpaceCfg;if(!o)return;o.plan_x=Number(Dc(t).toFixed(6)),o.plan_y=Number(Dc(e).toFixed(6)),delete o.plan_scale,o.plan_scale_x=Number(Math.min(mc,Math.max(gc,i)).toFixed(6)),o.plan_scale_y=Number(Math.min(mc,Math.max(gc,s)).toFixed(6));const a=rr(n);a?o.plan_angle=Number(a.toFixed(2)):delete o.plan_angle,this._cfgEpoch++,this.requestUpdate()}_bdStart(t,e,i=!1){const s=this._bdBase,n=this._bdRect;if(!s||!n)return!1;const o=this._svgPoint(t),a=e?e[0]:0,r=e?e[1]:0,l=a>0?n.x:n.x+n.w,c=r>0?n.y:n.y+n.h;return this._bdDrag={kind:i?"rotate":e?"scale":"move",pid:t.pointerId,sx:o[0],sy:o[1],base:s,p0:this._bdParams,fx:l,fy:c,sgx:a,sgy:r,rect0:{x:n.x,y:n.y,w:n.w,h:n.h,angle:n.angle},before:this._geometrySnapshot(),moved:!1},wm(t),!0}_bdMove(t){const e=this._bdDrag;if(!e)return;const i=this._svgPoint(t),s=e.base;if("move"===e.kind){const t=e.rect0.x,n=e.rect0.y,o=this._snap([t+(i[0]-e.sx),n+(i[1]-e.sy)]),a=Math.abs(o[0]-t)>1e-9||Math.abs(o[1]-n)>1e-9;if(!a&&!e.moved)return;return e.moved||=a,void this._bdApply((o[0]-s.x)/um,(o[1]-s.y)/um,e.p0.sx,e.p0.sy,e.p0.angle)}if("rotate"===e.kind){const s=e.rect0.x+e.rect0.w/2,n=e.rect0.y+e.rect0.h/2,o=180*Math.atan2(e.sy-n,e.sx-s)/Math.PI;let a=e.p0.angle+(180*Math.atan2(i[1]-n,i[0]-s)/Math.PI-o);t.shiftKey||(a=5*Math.round(a/5)),a=rr(a);const r=Math.abs(a-e.p0.angle)>1e-9;if(!r&&!e.moved)return;return e.moved||=r,void this._bdApply(e.p0.dx,e.p0.dy,e.p0.sx,e.p0.sy,a)}const n=gr(e.rect0,e.sgx,e.sgy,i[0],i[1],!t.shiftKey,this._gridPitch,Math.min(s.w,s.h)*gc),o=n.w/Math.max(1e-9,s.w),a=n.h/Math.max(1e-9,s.h),r=Math.abs(o-e.p0.sx)>1e-9||Math.abs(a-e.p0.sy)>1e-9||Math.abs(n.x-e.rect0.x)>1e-9||Math.abs(n.y-e.rect0.y)>1e-9;if(!r&&!e.moved)return;e.moved||=r;const l=lr(n,e.p0.angle,t=>this._snap(t));this._bdApply((l[0]-s.x)/um,(l[1]-s.y)/um,o,a,e.p0.angle)}get _bdMoved(){if("decor"!==this._mode||!this._bdRect)return!1;const t=this._bdParams;return 0!==t.dx||0!==t.dy||1!==t.sx||1!==t.sy||0!==t.angle}_bdReset(){const t=this._curSpaceCfg;if(!t)return;const e=this._geometrySnapshot();delete t.plan_x,delete t.plan_y,delete t.plan_scale,delete t.plan_scale_x,delete t.plan_scale_y,delete t.plan_angle,this._bdDrag=null,this._recordGeometry(this._t("history.backdrop_transform"),e),this._saveConfig(),this._showToast(this._t("decor.backdrop_reset_done")),this.requestUpdate()}_bdUp(){const t=this._bdDrag;this._bdDrag=null,t?.moved&&(this._recordGeometry(this._t("history.backdrop_transform"),t.before),this._saveConfig()),this.requestUpdate()}get _bdLive(){if(!this._bdDrag)return null;const t=this._bdRect;return t?{x:t.x+t.w/2,y:t.y+t.h/2,text:`${this._fmtLen([0,0],[t.w,0])} × ${this._fmtLen([0,0],[0,t.h])}`}:null}_renderBackdropFrame(t){const e=this._bdRect;if(!this._bdActive||!e)return G;const i=.02*Math.max(t.w,t.h),s=i/4,n=e.x+e.w/2,o=e.y+e.h/2,a=rr(e.angle),r=2.2*i;return j` - - + {t.stopPropagation(),t.preventDefault(),this._bdStart(t,void 0,!0)}}> - - ${[[-1,-1,"nwse"],[1,-1,"nesw"],[1,1,"nwse"],[-1,1,"nesw"]].map(([t,n,o])=>{const r=t<0?e.x:e.x+e.w,a=n<0?e.y:e.y+e.h;return j` + ${[[-1,-1,"nwse"],[1,-1,"nesw"],[1,1,"nwse"],[-1,1,"nesw"]].map(([t,n,o])=>{const a=t<0?e.x:e.x+e.w,r=n<0?e.y:e.y+e.h;return j`{e.stopPropagation(),e.preventDefault(),this._bdStart(e,[t,n])}}>`})} - `}_renderTextFrame(t){const e=this._dtSel,i=this._dtBox;if(!e||!i||i.id!==e.id)return G;const s=.018*Math.max(t.w,t.h),n=s/4;if("line"===e.kind){const t=[e.x1*pm,e.y1*this._decorH],i=[e.x2*pm,e.y2*this._decorH];return j` + cx="${a}" cy="${r}" r="${i.toFixed(1)}" + @pointerdown=${e=>{e.stopPropagation(),e.preventDefault(),this._bdStart(e,[t,n])}}>`})} + `}_renderTextFrame(t){const e=this._dtSel,i=this._dtBox;if(!e||!i||i.id!==e.id)return G;const s=.018*Math.max(t.w,t.h),n=s/4;if("line"===e.kind){const t=[e.x1*um,e.y1*this._decorH],i=[e.x2*um,e.y2*this._decorH];return j` ${[t,i].map((t,e)=>j`this._dtStart(t,"scale",void 0,e)}> `)} - `}const[o,r]=this._dtPivot(e),a=Number(e.angle)||0,l=2.2*s;return j` + `}const[o,a]=this._dtPivot(e),r=Number(e.angle)||0,l=2.2*s;return j` this._dtStart(i,"scale",[t,e])}>`)} - `}_renderDecorLayer(){const t=pm,e=this._decorH,i="decor"===this._mode,s=i&&"erase"===this._decorTool,n=this._decorList.map(n=>{const o="dshape"+(i&&this._decorSel===n.id?" dsel":""),r=this._decorResolvedStyle(n),a=this._decorWidthUnits(n),l=t=>this._decorShapeDown(t,n),c=t=>this._decorShapeDbl(t,n);if("line"===n.kind)return j``}_renderDecorLayer(){const t=um,e=this._decorH,i="decor"===this._mode,s=i&&"erase"===this._decorTool,n=this._decorList.map(n=>{const o="dshape"+(i&&this._decorSel===n.id?" dsel":""),a=this._decorResolvedStyle(n),r=this._decorWidthUnits(n),l=t=>this._decorShapeDown(t,n),c=t=>this._decorShapeDbl(t,n);if("line"===n.kind)return j` ${i&&"select"===this._decorTool?j``:G}`;if("rect"===n.kind){const i=(n.x+n.w/2)*t,h=(n.y+n.h/2)*e,d=aa(n.angle);return j``:G}`;if("rect"===n.kind){const i=(n.x+n.w/2)*t,h=(n.y+n.h/2)*e,d=rr(n.angle);return j` ${s?j``:G}`}if("ellipse"===n.kind){const i=(n.x+n.w/2)*t,h=(n.y+n.h/2)*e,d=aa(n.angle);return j``:G}`}if("ellipse"===n.kind){const i=(n.x+n.w/2)*t,h=(n.y+n.h/2)*e,d=rr(n.angle);return j` ${s?j``:G}`}if("furniture"===n.kind){const i=n.w*t,h=n.h*e,d=th(n.symbol,i,h);if(!d)return G;const p=Number(n.angle)||0,u=n.x*t+i/2,_=n.y*e+h/2,g=`${p?`rotate(${p} ${u} ${_}) `:""}translate(${n.x*t} ${n.y*e})`;return j``:G}`}if("furniture"===n.kind){const i=n.w*t,h=n.h*e,d=eh(n.symbol,i,h);if(!d)return G;const p=Number(n.angle)||0,u=n.x*t+i/2,_=n.y*e+h/2,g=`${p?`rotate(${p} ${u} ${_}) `:""}translate(${n.x*t} ${n.y*e})`;return j` ${s?j``:G}`}if("text"===n.kind){const i=this._decorTextUnits(n),s=this._renderDeviceSnapshot?.facts.get(`decor:${this._space}:${n.id}`),a=function(t){return String(t??"").replace(/\r\n?/g,"\n").split("\n")}("string"==typeof s?s:ts(n.text,n,this._renderPlanHass,t=>this._renderEntityAvailable(t))),h=n.x*t,d=n.y*e,p=Number(n.angle)||0,u=d-(a.length-1)*i*1.2/2;return j``:G}`}if("text"===n.kind){const i=this._decorTextUnits(n),s=this._renderDeviceSnapshot?.facts.get(`decor:${this._space}:${n.id}`),r=function(t){return String(t??"").replace(/\r\n?/g,"\n").split("\n")}("string"==typeof s?s:ts(n.text,n,this._renderPlanHass,t=>this._renderEntityAvailable(t))),h=n.x*t,d=n.y*e,p=Number(n.angle)||0,u=d-(r.length-1)*i*1.2/2;return j`${a.map((t,e)=>j`${t}`)}`}return G});let o=G;const r=this._decorDraft;if(r){const t=this._decorStyle,e=ca(t.widthCm,this._cellCm,this._gridPitch);if("line"===r.kind)o=j``;else{const i=Math.min(r.a[0],r.b[0]),s=Math.min(r.a[1],r.b[1]),n=Math.abs(r.b[0]-r.a[0]),a=Math.abs(r.b[1]-r.a[1]);o="rect"===r.kind?j``:j`${r.map((t,e)=>j`${t}`)}`}return G});let o=G;const a=this._decorDraft;if(a){const t=this._decorStyle,e=cr(t.widthCm,this._cellCm,this._gridPitch);if("line"===a.kind)o=j``;else{const i=Math.min(a.a[0],a.b[0]),s=Math.min(a.a[1],a.b[1]),n=Math.abs(a.b[0]-a.a[0]),r=Math.abs(a.b[1]-a.a[1]);o="rect"===a.kind?j``:j``}}return j`${n}${o}`}get _editorToolbarGroups(){return"plan"!==this._mode?[]:[{id:"opening",label:this._t("markup.opening"),icon:"mdi:door",activeItemId:"opening"===this._tool?this._openingPreset?.type:void 0,items:[{id:"window",label:this._t("opening.window"),icon:"mdi:window-closed-variant",role:"tool",invoke:()=>this._activateOpeningPlacement("window")},{id:"door",label:this._t("opening.door"),icon:"mdi:door-open",role:"tool",invoke:()=>this._activateOpeningPlacement("door")},{id:"passage",label:this._t("opening.passage"),icon:"mdi:arch",role:"tool",invoke:()=>this._activateOpeningPlacement("passage")},{id:"gate",label:this._t("opening.gate"),icon:"mdi:gate",role:"tool",invoke:()=>this._activateOpeningPlacement("gate")}]}]}_renderEditorGroupLauncher(t){return this._editorSecondary.renderGroupLauncher(t,this._editorToolbarGroups,this._editorSecondaryCopy)}get _editorSecondaryContextId(){const t=`editor:${this._mode}:${this._space}:${this._cfgEpoch}`,e=this._editorSecondary.activeGroup(this._editorToolbarGroups);if(e)return`${t}:group:${e.id}:${this._editorSecondary.groupGeneration}`;if("plan"===this._mode){const e=this._physicalSel;return e?`${t}:selection:${e.kind}:${e.id}:${e.segment??""}`:`${t}:tool:${this._tool}:${this._path.length}:${this._openWallAnchor?1:0}`}return"decor"===this._mode?"furniture"===this._decorTool?`${t}:palette:furniture:${this._furnPalette?.symbol||"none"}`:"select"===this._decorTool&&this._decorSel?`${t}:selection:decor:${this._decorSel}`:`${t}:tool:${this._decorTool}:${this._bdMoved?1:0}:${this._bdDrag?1:0}`:`${t}:none`}_runEditorContext(t,e){this._editorSecondary.runContext(t,this._editorSecondaryContextId,e)}_renderEditorGroupModel(t){return this._editorSecondary.renderGroupModel(t,this._editorSecondaryContextId,this._editorSecondaryCopy)}_renderDrawWallControl(){return W``}_renderPlanSecondary(){const t=this._editorSecondaryContextId,e=this._physicalSel;if(e){if(!("partition"===e.kind?!!this._curSpaceCfg.partitions?.some(t=>t.id===e.id):"column"===e.kind?!!this._curSpaceCfg.wall_columns?.some(t=>t.id===e.id):!!this._curSpaceCfg.room_drafts?.some(t=>t.id===e.id)))return null;const i="partition"===e.kind?this._t("markup.partition"):"column"===e.kind?this._t("markup.column"):this._t("markup.add");return{contextId:t,kind:"selection",ariaLabel:this._t("editor.context_actions",{object:i}),visibleLabel:i,content:W` `:W`${this._t("gs.bg_theme")}`}
`:W`
${this._t("gs.bg_daynight_hint")}
`} - ${ea(this.hass)?G:W`
${this._t("gs.sun_missing")}
`} + ${er(this.hass)?G:W`
${this._t("gs.sun_missing")}
`}
- `}_saveKioskScale(t){this._kioskScale={...this._kioskScale,...t};try{localStorage.setItem(cm,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(hm,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])}% @@ -5784,7 +5784,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8 ${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,r=this._effectiveProjection();this._renderProjection=r,this._labs.active.length&&function(t){Z_||ng(t);const e=J_,i=e.active.join(",");if(!i||i===tg)return;tg=i;const s=new Map(q_.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}`)}(Gg);const a="iso"===r,l="devices"===this._mode&&this._showAll,c=this._renderDevices.filter(t=>t.space===s.id&&(!t.hidden||l)),h=this._renderDeviceSnapshot,d=this._spaceDisplayForRender(),p=a?this._isoDecorationLayers(d):null,u=p?this._isoOpeningPanels(p):[],_=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=au(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){Q_||og(t);const e=Z_,i=e.active.join(",");if(!i||i===eg)return;eg=i;const s=new Map(W_.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}`)}(Vg);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(),p=r?this._isoDecorationLayers(d):null,u=p?this._isoOpeningPanels(p):[],_=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=lu(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` ${this._t("count.devices",{n:c.filter(t=>!t.hidden).length})} - ${this._labsIso&&"view"===this._mode&&!this._kiosk?W``:G}
@@ -5871,7 +5871,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8
this._markupClick(t)} @wheel=${t=>this._onWheel(t)} @pointerdown=${t=>{this._notePointer(t),this._stagePointerDown(t)}} @@ -5879,21 +5879,21 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8 @pointerleave=${t=>this._stagePointerLeave(t)} @pointerup=${t=>this._stagePointerUp(t)} @pointercancel=${t=>this._stagePointerCancel(t)}> - ${na(I,A)} + ${nr(I,A)} ${this._renderEditorSecondary()}
- ${a&&p?.structural?j``:G} + preserveAspectRatio=${p?.structural||!r?"xMidYMid meet":"none"}> + transform=${p?.structural?hg():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} @@ -5905,7 +5905,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8 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 r=Fs(d.fill,e);if(!this._markup&&(d.showBorders||"none"!==r)){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 a;const l=t=>{"view"===this._mode&&(void 0===a&&(a=this._roomArea(e)),this._showTip(t,e.name||this._t("room.unnamed"),a?this._t("tip.area",{value:a}):"",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):[],p=c?[]:this._thickWallCuts(),u=h.concat(p);u.length&&(n+=" noedge");const g=i(e),f=this._spaceWalls,v=f.length&&e.id&&g&&ml(s.rooms,e.id,f,this._openPairs().flatMap(t=>t.segs),this._wallKeyPitch,this._cellCm,this._gridPitch,pm)||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):[],p=c?[]:this._thickWallCuts(),u=h.concat(p);u.length&&(n+=" noedge");const g=i(e),f=this._spaceWalls,v=f.length&&e.id&&g&&fl(s.rooms,e.id,f,this._openPairs().flatMap(t=>t.segs),this._wallKeyPitch,this._cellCm,this._gridPitch,um,this._wallUnionGeometry()?.roomGeom)||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})}} @@ -5964,7 +5964,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8 ${this._renderTextFrame(b)} - ${a&&p?.structural?j``:G} ${""} -
+
${c.map(t=>this._renderDevice(t,b,m))} ${this._renderVacuums(c,b)} ${this._renderVacFit(b)} @@ -6051,7 +6051,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8 ${null!=this._tip.temp?W`${this._t("tip.temp_avg")} ${this._tip.temp}°`:G} ${null!=this._tip.hum?W`${this._t("tip.hum_avg")} ${this._tip.hum}%`:G} ${null!=this._tip.lqi?W`${this._t("tip.lqi")} - ${this._tip.lqi}`:G} + ${this._tip.lqi}`:G}
`:G} ${this._kiosk&&!this._hasFixedFloor&&this._kioskDots&&this._model.length>1?W`
${this._model.map(t=>W``)} @@ -6082,22 +6082,22 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8 `: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=Uh(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||[]),r=new Set(o);n&&r.add(s.source);const a=i?.entities||{},l=[];for(const t of r){const e=i?.states?.[t],o=Uh(t,e,a[t]);o?l.push(o):n&&t===s.source&&l.push({entityId:t,name:String(e?.attributes?.friendly_name||t),platform:a[t]?.platform?String(a[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),r=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=r.find(e=>e.entityId===t);return{entityId:t,status:s[t]||(e?.hasPosition?"ok":"unverified"),pinned:!0,candidates:r}}const a=r.find(t=>o.has(t.entityId)&&t.hasPosition&&"ok"===s[t.entityId]);return a?{entityId:a.entityId,status:"ok",pinned:!1,candidates:r}:{entityId:null,status:"none",pinned:!1,candidates:r}}(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=Jp(this._planHass,t,this._devices,e,this._fullRegistryHass);return{samples:i.samples,sourceKey:tu(this._planHass,t,i)}}_stampActivity(t,e,i){let s=this._activityRt.get(t);s||(s=$u(i||"",[]),this._activityRt.set(t,s)),null!=i&&(s.sources=i),Mu(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:r}=n;let a=this._activityRt.get(s.id);a?a.sources!==r&&Su(a,r,o,window.clearTimeout.bind(window)):(a=$u(r,o),this._activityRt.set(s.id,a))}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 r=Cu(o,s,window.clearTimeout.bind(window));r&&this._stampActivity(e.id,r,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=Yh(this.hass.states[i||""]?.state),n=jh(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 r="never"!==td(t.marker?.vacuum)&&!n?.path.length;!s&&o.moving&&(o.endedTs=Date.now(),r&&o.lastPos&&(o.trail=Kh(o.trail,o.lastPos,40)),o.lastPos=null),o.moving=s;const a=n?.pos;if(s&&a){const t=a.x+":"+a.y;if(t!==o.lastKey){const e=Date.now();o.jump=o.lastTs>0&&e-o.lastTs>1e4,o.lastKey=t,o.lastTs=e,r&&o.lastPos&&(o.trail=Kh(o.trail,o.lastPos,40)),o.lastPos=[a.x,a.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,r=n.candidates.find(t=>t.entityId===o)||null,a=o?jh(this.hass?.states[o]?.attributes):null,l=!1!==i.live&&("ok"===n.status||"unsupported"===n.status),c=this._vacPlanRoomAnchors(e.space),h=a?function(t,e){const i=new Set(e.map(Gh).filter(Boolean)),s=new Set;for(const e of t){const t=Gh(e.name||"");t&&i.has(t)&&s.add(t)}return s.size}(a.rooms,c.map(t=>t.name)):0,d=!!(l&&a&&h>=3),p=Object.keys(i.calibration||{}),u=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=Gh(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=Gh(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=Zp(this._planHass,t,this._devices,e,this._fullRegistryHass);return{samples:i.samples,sourceKey:eu(this._planHass,t,i)}}_stampActivity(t,e,i){let s=this._activityRt.get(t);s||(s=Su(i||"",[]),this._activityRt.set(t,s)),null!=i&&(s.sources=i),Cu(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&&Mu(r,a,o,window.clearTimeout.bind(window)):(r=Su(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=Du(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=Xh(this.hass.states[i||""]?.state),n=Uh(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"!==ed(t.marker?.vacuum)&&!n?.path.length;!s&&o.moving&&(o.endedTs=Date.now(),a&&o.lastPos&&(o.trail=Yh(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=Yh(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?Uh(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(Vh).filter(Boolean)),s=new Set;for(const e of t){const t=Vh(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),p=Object.keys(i.calibration||{}),u=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` `,y=n.candidates.some(t=>_.has(t.entityId)&&"known_xcme_incomplete"===t.category)||!!n.pinned&&!!o?.startsWith("camera.")&&!r?.hasPosition;return W` + `,y=n.candidates.some(t=>_.has(t.entityId)&&"known_xcme_incomplete"===t.category)||!!n.pinned&&!!o?.startsWith("camera.")&&!a?.hasPosition;return W`
${this._t("vac.diag_source")}${o||this._t("vac.source_none")}
- ${r?.platform?W`
${this._t("vac.diag_platform")}${r.platform}
`:G} + ${a?.platform?W`
${this._t("vac.diag_platform")}${a.platform}
`:G}
${this._t("vac.diag_status")}${this._t(`vac.source_status_${n.status}`)}
-
${this._t("vac.diag_position")}${a?.pos?this._t("common.yes"):this._t("common.no")}
-
${this._t("vac.diag_rooms")}${ss(this._t("vac.diag_rooms_value"),{total:String(a?.rooms.length||0),matched:String(h),readiness:this._t(h>=3?"vac.autocal_ready":"vac.autocal_not_ready")})}
-
${this._t("vac.diag_path")}${a?.path.length?this._t("common.yes"):this._t("common.no")}
-
${this._t("vac.diag_map")}${a?.mapId??"default"}
+
${this._t("vac.diag_position")}${r?.pos?this._t("common.yes"):this._t("common.no")}
+
${this._t("vac.diag_rooms")}${ss(this._t("vac.diag_rooms_value"),{total:String(r?.rooms.length||0),matched:String(h),readiness:this._t(h>=3?"vac.autocal_ready":"vac.autocal_not_ready")})}
+
${this._t("vac.diag_path")}${r?.path.length?this._t("common.yes"):this._t("common.no")}
+
${this._t("vac.diag_map")}${r?.mapId??"default"}
${"missing"===n.status||"disabled"===n.status||"unverified"===n.status?W`
- ${a?W` + ${r?W`
`}_vacMapId(t,e,i=this._planHass){const s=this._vacEntity(t),n=s?i?.states?.[s]?.attributes?.selected_map:null;return o=e.mapId,r=n,"default"!==o?o:null!=r?String(r):"default";var o,r}_vacSaveMatrix(t,e,i,s){const n=this._devices.find(e=>e.id===t),o=n?this._vacEnsureMarker(n):this._serverCfg?.markers?.find(e=>e.id===t);if(!o)return!1;const r={...o.vacuum||{}};return r.source=e,r.calibration={...r.calibration||{},[i]:s.map(t=>Number(t.toFixed(6)))},o.vacuum=r,this._regSignature="",this._maybeRebuildDevices(),this._saveConfig(),this.requestUpdate(),!0}_vacPlanRoomAnchors(t){return(this._spaceModelById(t)?.rooms||[]).map(t=>({room:t,poly:hi(t)})).filter(({room:t,poly:e})=>t.name&&e).map(({room:t,poly:e})=>{const i=Hh(e);return i?{name:String(t.name),cx:i[0],cy:i[1]}:null}).filter(Boolean)}_vacAutoCalibrate(t){const e=this._vacSource(t),i=e?jh(this.hass?.states[e]?.attributes):null;if(!e||!i||i.rooms.length<3)return void this._showToast(this._t("vac.autocal_no_rooms"));const s=this._vacPlanRoomAnchors(t.space),n=Vh(i.rooms,s);if(!n)return void this._showToast(this._t("vac.autocal_no_match"));const o=this._serverCfg?.spaces?.find(e=>e.id===t.space),r=Number(o?.cell_cm),a=Number.isFinite(r)&&r>0?r:5,l=function(t,e,i){return![t,e,i].every(Number.isFinite)||t<0||e<=0||i<=0?Number.POSITIVE_INFINITY:t/e*i}(n.residual,this._gridPitch,a),c=this._vacMapId(t,i);l>40?this._vacCalConfirm={markerId:t.id,source:e,mapId:c,matrix:n.matrix,rooms:n.matched.length,error:li(l,"mi"===this.hass?.config?.unit_system?.length)}:this._vacSaveMatrix(t.id,e,c,n.matrix)&&this._showToast(ss(this._t("vac.autocal_done"),{rooms:String(n.matched.length)}))}_vacApplyCalibrationProposal(t){const e=this._vacCalConfirm;if(e){if(this._vacCalConfirm=null,t){const t=this._devices.find(t=>t.id===e.markerId),i=Zh(e.matrix);if(!t||!i)return;if(this._markerDialog=null,t.space!==this._space&&!this._commitSpace(t.space))return;return void(this._vacFit={markerId:e.markerId,source:e.source,mapId:e.mapId,p:i,drag:null})}this._vacSaveMatrix(e.markerId,e.source,e.mapId,e.matrix)&&this._showToast(ss(this._t("vac.autocal_done"),{rooms:String(e.rooms)}))}}_vacStartFit(t){const e=this._vacSource(t),i=e?jh(this.hass?.states[e]?.attributes):null;if(!e||!i)return void this._showToast(this._t("vac.cal_need_pos"));const s=this._vacMapId(t,i),n=t.marker?.vacuum?.calibration?.[s],o=this._spaceModelById(t.space);if(!o)return;const r=o.vb,a=n&&6===n.length&&Zh(n)||function(t,e){const i=[],s=[];for(const e of t)null!=e.x0?(i.push(e.x0,e.x1),s.push(e.y0,e.y1)):(i.push(e.cx),s.push(e.cy));if(!i.length)return{ox:e[0]+e[2]/2,oy:e[1]+e[3]/2,s:e[2]/1e4,rot:0,mir:!0};const n=Math.min(...i),o=Math.max(...i),r=Math.min(...s),a=Math.max(...s),l=Math.max(o-n,a-r)||1,c={ox:0,oy:0,s:.6*Math.min(e[2],e[3])/l,rot:0,mir:!0},h=Jh(c),[d,p]=Eh(h,(n+o)/2,(r+a)/2);return c.ox=e[0]+e[2]/2-d,c.oy=e[1]+e[3]/2-p,c}(i.rooms,r);this._markerDialog=null,(t.space===this._space||this._commitSpace(t.space))&&(this._vacFit={markerId:t.id,source:e,mapId:s,p:a,drag:null})}_vacFitSave(){const t=this._vacFit;if(!t)return;const e=this._vacSaveMatrix(t.markerId,t.source,t.mapId,Jh(t.p));this._vacFit=null,e&&this._showToast(this._t("vac.cal_done"))}_vacFitTurn(t){const e=this._vacFit;if(!e)return;const i=jh(this.hass?.states[e.source]?.attributes),s=this._vacGhostCentre(i?.rooms||[]),n={...e.p,...t};this._vacFit={...e,p:Qh(n,e.p,s[0],s[1])}}_vacGhostCentre(t){const e=[],i=[];for(const s of t)e.push(s.x0??s.cx,s.x1??s.cx),i.push(s.y0??s.cy,s.y1??s.cy);return e.length?[(Math.min(...e)+Math.max(...e))/2,(Math.min(...i)+Math.max(...i))/2]:[0,0]}_vacDelta(t,e,i){const s=this._stageEl,n=s?.clientWidth||1,o=s?.clientHeight||1;return[e/n*t.w,i/o*t.h]}_vacFitPointer(t,e){const i=this._vacFit;if(!i)return;if(t.stopPropagation(),"pointerdown"===t.type){const e=t.target,s=e.getAttribute?.("data-corner");try{t.currentTarget.setPointerCapture?.(t.pointerId)}catch{}return void(this._vacFit={...i,drag:s?{kind:"scale",sx:t.clientX,sy:t.clientY,p0:{...i.p},fx:Number(s.split(",")[0]),fy:Number(s.split(",")[1])}:{kind:"move",sx:t.clientX,sy:t.clientY,p0:{...i.p},fx:0,fy:0}})}const s=i.drag;if(s){if("pointermove"===t.type){const[n,o]=this._vacDelta(e,t.clientX-s.sx,t.clientY-s.sy);if("move"===s.kind)this._vacFit={...i,p:{...s.p0,ox:s.p0.ox+n,oy:s.p0.oy+o}};else{const t=jh(this.hass?.states[i.source]?.attributes),e=this._vacGhostCentre(t?.rooms||[]),r=Jh(s.p0),[a,l]=Eh(r,e[0],e[1]),[c,h]=Eh(r,s.fx,s.fy),d=Math.hypot(a-c,l-h)||1,[p,u]=[2*a-c,2*l-h],_=Math.hypot(p+2*n-c,u+2*o-h)/2,g=Math.max(.05,_/d),m={...s.p0,s:s.p0.s*g};this._vacFit={...i,p:Qh(m,s.p0,s.fx,s.fy)}}return}"pointerup"!==t.type&&"pointercancel"!==t.type||(this._vacFit={...i,drag:null})}}_renderVacFit(t){const e=this._vacFit;if(!e)return G;const i=jh(this._renderPlanHass?.states?.[e.source]?.attributes);if(!i)return G;const s=Jh(e.p),n=[],o=[],r=[];for(const t of i.rooms){if(null==t.x0)continue;const e=[[t.x0,t.y0],[t.x1,t.y0],[t.x1,t.y1],[t.x0,t.y1]].map(([t,e])=>Eh(s,t,e));e.forEach(([t,e])=>{o.push(t),r.push(e)});const[i,a]=Eh(s,t.cx,t.cy);n.push(j` - ${t.name}`)}let a=G;if(i.pos){const[e,n]=Eh(s,i.pos.x,i.pos.y);a=j``}const l=[];if(o.length){const e=(()=>{const t=s[0]*s[4]-s[1]*s[3];return(e,i)=>[(s[4]*(e-s[2])-s[1]*(i-s[5]))/t,(-s[3]*(e-s[2])+s[0]*(i-s[5]))/t]})(),i=Math.min(...o),n=Math.max(...o),a=Math.min(...r),c=Math.max(...r),h=.022*t.w,d=h/4;for(const[t,s,o,r]of[[i,a,n,c],[n,a,i,c],[n,c,i,a],[i,c,n,a]]){const i=e(o,r);l.push(j``}_vacMapId(t,e,i=this._planHass){const s=this._vacEntity(t),n=s?i?.states?.[s]?.attributes?.selected_map:null;return o=e.mapId,a=n,"default"!==o?o:null!=a?String(a):"default";var o,a}_vacSaveMatrix(t,e,i,s){const n=this._devices.find(e=>e.id===t),o=n?this._vacEnsureMarker(n):this._serverCfg?.markers?.find(e=>e.id===t);if(!o)return!1;const a={...o.vacuum||{}};return a.source=e,a.calibration={...a.calibration||{},[i]:s.map(t=>Number(t.toFixed(6)))},o.vacuum=a,this._regSignature="",this._maybeRebuildDevices(),this._saveConfig(),this.requestUpdate(),!0}_vacPlanRoomAnchors(t){return(this._spaceModelById(t)?.rooms||[]).map(t=>({room:t,poly:hi(t)})).filter(({room:t,poly:e})=>t.name&&e).map(({room:t,poly:e})=>{const i=Lh(e);return i?{name:String(t.name),cx:i[0],cy:i[1]}:null}).filter(Boolean)}_vacAutoCalibrate(t){const e=this._vacSource(t),i=e?Uh(this.hass?.states[e]?.attributes):null;if(!e||!i||i.rooms.length<3)return void this._showToast(this._t("vac.autocal_no_rooms"));const s=this._vacPlanRoomAnchors(t.space),n=Kh(i.rooms,s);if(!n)return void this._showToast(this._t("vac.autocal_no_match"));const o=this._serverCfg?.spaces?.find(e=>e.id===t.space),a=Number(o?.cell_cm),r=Number.isFinite(a)&&a>0?a:5,l=function(t,e,i){return![t,e,i].every(Number.isFinite)||t<0||e<=0||i<=0?Number.POSITIVE_INFINITY:t/e*i}(n.residual,this._gridPitch,r),c=this._vacMapId(t,i);l>40?this._vacCalConfirm={markerId:t.id,source:e,mapId:c,matrix:n.matrix,rooms:n.matched.length,error:li(l,"mi"===this.hass?.config?.unit_system?.length)}:this._vacSaveMatrix(t.id,e,c,n.matrix)&&this._showToast(ss(this._t("vac.autocal_done"),{rooms:String(n.matched.length)}))}_vacApplyCalibrationProposal(t){const e=this._vacCalConfirm;if(e){if(this._vacCalConfirm=null,t){const t=this._devices.find(t=>t.id===e.markerId),i=Qh(e.matrix);if(!t||!i)return;if(this._markerDialog=null,t.space!==this._space&&!this._commitSpace(t.space))return;return void(this._vacFit={markerId:e.markerId,source:e.source,mapId:e.mapId,p:i,drag:null})}this._vacSaveMatrix(e.markerId,e.source,e.mapId,e.matrix)&&this._showToast(ss(this._t("vac.autocal_done"),{rooms:String(e.rooms)}))}}_vacStartFit(t){const e=this._vacSource(t),i=e?Uh(this.hass?.states[e]?.attributes):null;if(!e||!i)return void this._showToast(this._t("vac.cal_need_pos"));const s=this._vacMapId(t,i),n=t.marker?.vacuum?.calibration?.[s],o=this._spaceModelById(t.space);if(!o)return;const a=o.vb,r=n&&6===n.length&&Qh(n)||function(t,e){const i=[],s=[];for(const e of t)null!=e.x0?(i.push(e.x0,e.x1),s.push(e.y0,e.y1)):(i.push(e.cx),s.push(e.cy));if(!i.length)return{ox:e[0]+e[2]/2,oy:e[1]+e[3]/2,s:e[2]/1e4,rot:0,mir:!0};const n=Math.min(...i),o=Math.max(...i),a=Math.min(...s),r=Math.max(...s),l=Math.max(o-n,r-a)||1,c={ox:0,oy:0,s:.6*Math.min(e[2],e[3])/l,rot:0,mir:!0},h=Zh(c),[d,p]=zh(h,(n+o)/2,(a+r)/2);return c.ox=e[0]+e[2]/2-d,c.oy=e[1]+e[3]/2-p,c}(i.rooms,a);this._markerDialog=null,(t.space===this._space||this._commitSpace(t.space))&&(this._vacFit={markerId:t.id,source:e,mapId:s,p:r,drag:null})}_vacFitSave(){const t=this._vacFit;if(!t)return;const e=this._vacSaveMatrix(t.markerId,t.source,t.mapId,Zh(t.p));this._vacFit=null,e&&this._showToast(this._t("vac.cal_done"))}_vacFitTurn(t){const e=this._vacFit;if(!e)return;const i=Uh(this.hass?.states[e.source]?.attributes),s=this._vacGhostCentre(i?.rooms||[]),n={...e.p,...t};this._vacFit={...e,p:td(n,e.p,s[0],s[1])}}_vacGhostCentre(t){const e=[],i=[];for(const s of t)e.push(s.x0??s.cx,s.x1??s.cx),i.push(s.y0??s.cy,s.y1??s.cy);return e.length?[(Math.min(...e)+Math.max(...e))/2,(Math.min(...i)+Math.max(...i))/2]:[0,0]}_vacDelta(t,e,i){const s=this._stageEl,n=s?.clientWidth||1,o=s?.clientHeight||1;return[e/n*t.w,i/o*t.h]}_vacFitPointer(t,e){const i=this._vacFit;if(!i)return;if(t.stopPropagation(),"pointerdown"===t.type){const e=t.target,s=e.getAttribute?.("data-corner");try{t.currentTarget.setPointerCapture?.(t.pointerId)}catch{}return void(this._vacFit={...i,drag:s?{kind:"scale",sx:t.clientX,sy:t.clientY,p0:{...i.p},fx:Number(s.split(",")[0]),fy:Number(s.split(",")[1])}:{kind:"move",sx:t.clientX,sy:t.clientY,p0:{...i.p},fx:0,fy:0}})}const s=i.drag;if(s){if("pointermove"===t.type){const[n,o]=this._vacDelta(e,t.clientX-s.sx,t.clientY-s.sy);if("move"===s.kind)this._vacFit={...i,p:{...s.p0,ox:s.p0.ox+n,oy:s.p0.oy+o}};else{const t=Uh(this.hass?.states[i.source]?.attributes),e=this._vacGhostCentre(t?.rooms||[]),a=Zh(s.p0),[r,l]=zh(a,e[0],e[1]),[c,h]=zh(a,s.fx,s.fy),d=Math.hypot(r-c,l-h)||1,[p,u]=[2*r-c,2*l-h],_=Math.hypot(p+2*n-c,u+2*o-h)/2,g=Math.max(.05,_/d),m={...s.p0,s:s.p0.s*g};this._vacFit={...i,p:td(m,s.p0,s.fx,s.fy)}}return}"pointerup"!==t.type&&"pointercancel"!==t.type||(this._vacFit={...i,drag:null})}}_renderVacFit(t){const e=this._vacFit;if(!e)return G;const i=Uh(this._renderPlanHass?.states?.[e.source]?.attributes);if(!i)return G;const s=Zh(e.p),n=[],o=[],a=[];for(const t of i.rooms){if(null==t.x0)continue;const e=[[t.x0,t.y0],[t.x1,t.y0],[t.x1,t.y1],[t.x0,t.y1]].map(([t,e])=>zh(s,t,e));e.forEach(([t,e])=>{o.push(t),a.push(e)});const[i,r]=zh(s,t.cx,t.cy);n.push(j` + ${t.name}`)}let r=G;if(i.pos){const[e,n]=zh(s,i.pos.x,i.pos.y);r=j``}const l=[];if(o.length){const e=(()=>{const t=s[0]*s[4]-s[1]*s[3];return(e,i)=>[(s[4]*(e-s[2])-s[1]*(i-s[5]))/t,(-s[3]*(e-s[2])+s[0]*(i-s[5]))/t]})(),i=Math.min(...o),n=Math.max(...o),r=Math.min(...a),c=Math.max(...a),h=.022*t.w,d=h/4;for(const[t,s,o,a]of[[i,r,n,c],[n,r,i,c],[n,c,i,r],[i,c,n,r]]){const i=e(o,a);l.push(j` `)}}return W`this._vacFitPointer(e,t)} @pointermove=${e=>this._vacFitPointer(e,t)} @pointerup=${e=>this._vacFitPointer(e,t)} - @pointercancel=${e=>this._vacFitPointer(e,t)}>${n}${a}${l}`}_vacRafLoop(){this._vacRaf=requestAnimationFrame(()=>{const t=this.renderRoot,e=this._stageEl,i=this._vacLastView,s=t?.querySelectorAll?.(".vacpuck")||[];if(!e||!i||!s.length)return void(this._vacRaf=0);const n=e.getBoundingClientRect();for(const e of s){const s=e.getAttribute("data-mid"),o=e.getBoundingClientRect(),r=i.x+(o.left+o.width/2-n.left)/n.width*i.w,a=i.y+(o.top+o.height/2-n.top)/n.height*i.h;for(const e of t.querySelectorAll(`line.tip[data-mid="${s}"]`))e.setAttribute("x2",r.toFixed(1)),e.setAttribute("y2",a.toFixed(1))}this._vacRafLoop()})}_renderVacuums(t,e){if(this._markup||"decor"===this._mode)return G;const i=this._space+"|"+e.x+"|"+e.y+"|"+e.w+"|"+e.h,s=this._vacJumpOnce||i!==this._vacViewKey;this._vacViewKey=i,this._vacJumpOnce=!1;const n=[],o=[];for(const i of t){if(i.hidden||!this._isVacDev(i))continue;if("static_icon"===Bi(i.marker?.display))continue;const t=this._renderDeviceSnapshot?.facts.get(`vacuum:${i.id}`),r=t?.source??this._vacSource(i,this._renderPlanHass);if(!r)continue;const a=t?.telemetry??jh(this._renderPlanHass?.states[r]?.attributes);if(!a)continue;const l=String(t?.mapId??this._vacMapId(i,a,this._renderPlanHass)),c=i.marker?.vacuum?.calibration?.[l];if(!c||6!==c.length)continue;const h=t?.runtime??this._vacRt.get(i.id),d=h?.moving??!1,p=td(i.marker?.vacuum),u="always"===p||"cleaning"===p&&d,_=t?.server??this._vacSrvTrails[i.id],g=_?.current?.map_id===l&&Array.isArray(_.current.points)?_.current:null,m=_?.previous?.map_id===l&&Array.isArray(_.previous.points)?_.previous:null;if("always"===p&&m&&m.points.length>1){const t=m.points.map(([t,e])=>{const[i,s]=Eh(c,t,e),n=this._scenePoint([i,s]);return n[0].toFixed(1)+","+n[1].toFixed(1)}).join(" ");o.push(j``)}if(u){const t=qh(a,g,h?.trail||[]),e=!d||"integration"!==t.source&&"server"!==t.source?t.path:Wh(t.path);if(e.length){const t=e.map(t=>t.map(([t,e],i)=>{const[s,n]=Eh(c,t,e),o=this._scenePoint([s,n]);return`${i?"L":"M"} ${o[0].toFixed(1)} ${o[1].toFixed(1)}`}).join(" ")).join(" ");o.push(j``);const s=e[e.length-1];if(d&&s?.length>=2){const t=s[s.length-1],[e,n]=Eh(c,t[0],t[1]),r=this._scenePoint([e,n]),a=r[0].toFixed(1),l=r[1].toFixed(1);o.push(j``)}}}if(!d||!a.pos)continue;const[f,v]=Eh(c,a.pos.x,a.pos.y),y=this._scenePoint([f,v]),b=(y[0]-e.x)/e.w*100,w=(y[1]-e.y)/e.h*100,k=h&&h.lastTs>0&&Date.now()-h.lastTs>6e4,x=i.marker?.icon||i.icon||"mdi:robot-vacuum";n.push(W`
this._vacFitPointer(e,t)}>${n}${r}${l}`}_vacRafLoop(){this._vacRaf=requestAnimationFrame(()=>{const t=this.renderRoot,e=this._stageEl,i=this._vacLastView,s=t?.querySelectorAll?.(".vacpuck")||[];if(!e||!i||!s.length)return void(this._vacRaf=0);const n=e.getBoundingClientRect();for(const e of s){const s=e.getAttribute("data-mid"),o=e.getBoundingClientRect(),a=i.x+(o.left+o.width/2-n.left)/n.width*i.w,r=i.y+(o.top+o.height/2-n.top)/n.height*i.h;for(const e of t.querySelectorAll(`line.tip[data-mid="${s}"]`))e.setAttribute("x2",a.toFixed(1)),e.setAttribute("y2",r.toFixed(1))}this._vacRafLoop()})}_renderVacuums(t,e){if(this._markup||"decor"===this._mode)return G;const i=this._space+"|"+e.x+"|"+e.y+"|"+e.w+"|"+e.h,s=this._vacJumpOnce||i!==this._vacViewKey;this._vacViewKey=i,this._vacJumpOnce=!1;const n=[],o=[];for(const i of t){if(i.hidden||!this._isVacDev(i))continue;if("static_icon"===Bi(i.marker?.display))continue;const t=this._renderDeviceSnapshot?.facts.get(`vacuum:${i.id}`),a=t?.source??this._vacSource(i,this._renderPlanHass);if(!a)continue;const r=t?.telemetry??Uh(this._renderPlanHass?.states[a]?.attributes);if(!r)continue;const l=String(t?.mapId??this._vacMapId(i,r,this._renderPlanHass)),c=i.marker?.vacuum?.calibration?.[l];if(!c||6!==c.length)continue;const h=t?.runtime??this._vacRt.get(i.id),d=h?.moving??!1,p=ed(i.marker?.vacuum),u="always"===p||"cleaning"===p&&d,_=t?.server??this._vacSrvTrails[i.id],g=_?.current?.map_id===l&&Array.isArray(_.current.points)?_.current:null,m=_?.previous?.map_id===l&&Array.isArray(_.previous.points)?_.previous:null;if("always"===p&&m&&m.points.length>1){const t=m.points.map(([t,e])=>{const[i,s]=zh(c,t,e),n=this._scenePoint([i,s]);return n[0].toFixed(1)+","+n[1].toFixed(1)}).join(" ");o.push(j``)}if(u){const t=Wh(r,g,h?.trail||[]),e=!d||"integration"!==t.source&&"server"!==t.source?t.path:jh(t.path);if(e.length){const t=e.map(t=>t.map(([t,e],i)=>{const[s,n]=zh(c,t,e),o=this._scenePoint([s,n]);return`${i?"L":"M"} ${o[0].toFixed(1)} ${o[1].toFixed(1)}`}).join(" ")).join(" ");o.push(j``);const s=e[e.length-1];if(d&&s?.length>=2){const t=s[s.length-1],[e,n]=zh(c,t[0],t[1]),a=this._scenePoint([e,n]),r=a[0].toFixed(1),l=a[1].toFixed(1);o.push(j``)}}}if(!d||!r.pos)continue;const[f,v]=zh(c,r.pos.x,r.pos.y),y=this._scenePoint([f,v]),b=(y[0]-e.x)/e.w*100,w=(y[1]-e.y)/e.h*100,k=h&&h.lastTs>0&&Date.now()-h.lastTs>6e4,x=i.marker?.icon||i.icon||"mdi:robot-vacuum";n.push(W`
${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,r=(n[1]-e.y)/e.h*100,a=this._devicePresentation(t,i),l=[`left:${o}%`,`top:${r}%`,...Go(a)],c=a.disabledReason,h=a.haDisabled?this._t(`marker.ha_disabled_${c}`):t.userHidden?this._t("marker.hidden_ghost"):t.name,d=Gp(a),p="view"===this._mode||"devices"===this._mode,u=[h,a.haDisabled?"":this._t(`marker.state_a11y_${d}`),"none"!==a.pulse.kind?this._t(`marker.pulse_a11y_${a.pulse.reason}`):"",a.valueFullText||a.valueText||"",Ro(a.valueBadge),null!=a.lqiText&&a.lqiBand?this._t(`marker.lqi_a11y_${a.lqiBand}`,{value:a.lqiText}):""].filter(Boolean).join(", "),_=[t.model,a.valueBadge?.fullText||"",null!=a.lqiText?"LQI "+a.lqiText:""].filter(Boolean).join(" · ");return W`
this._clickDevice(e,t)} @keydown=${e=>this._keyDevice(e,t)} @contextmenu=${e=>this._ctxDevice(e,t)} - @pointerover=${e=>this._showTip(e,t.name,a.haDisabled?h:_)} + @pointerover=${e=>this._showTip(e,t.name,r.haDisabled?h:_)} @pointerleave=${()=>this._clearTransientHover()} @pointerdown=${e=>this._pointerDown(e,t)} - @pointermove=${e=>{this._pointerMove(e,t),this._showTip(e,t.name,a.haDisabled?h:_)}} + @pointermove=${e=>{this._pointerMove(e,t),this._showTip(e,t.name,r.haDisabled?h:_)}} @pointerup=${e=>this._pointerUp(e,t)} @pointercancel=${e=>this._pointerUp(e,t)} > - ${Ko(a,{newDevice:this._newIds.has(t.id),newDeviceTitle:this._t("device.new"),disabledTitle:a.haDisabled?h:""})} -
`}_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&&ml(i.rooms,t.id,s,this._openPairs().flatMap(t=>t.segs),this._wallKeyPitch,this._cellCm,this._gridPitch,pm)||e,o=this._cleanFloor(t,n),r=this._cellCm/this._gridPitch;return Ir(o.area*r*r/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 r=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,a=i.area_id||s?.area_id||null;if(!a)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=r.get(a);l||(l=new Map,r.set(a,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 r){const r=[],a=[];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&&r.push(e)}if(o.size>0&&(o.has(i)||s.ents.some(t=>o.has(t)))){const e=mo(t,s.ents);null!=e&&r.push(e)}if(l||"mdi:water-percent"===n){const e=vo(t,s.ents);null!=e&&a.push(e)}}(r.length||a.length)&&s.set(i,{temp:r.length?Math.round(r.reduce((t,e)=>t+e,0)/r.length*10)/10:null,hum:a.length?Math.round(a.reduce((t,e)=>t+e,0)/a.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?as(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 r=o.name||t.states[n]?.attributes?.friendly_name||n;i&&!(r+" "+n).toLowerCase().includes(i)||s.push({value:"entity:"+n,label:r,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*pm,y:i.y*pm};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},bm(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 r=o.vb,a=n.getBoundingClientRect(),l=this._viewOr(r),c=(t.clientX-this._drag.sx)/a.width*l.w,h=(t.clientY-this._drag.sy)/a.height*l.h;Math.abs(t.clientX-this._drag.sx)+Math.abs(t.clientY-this._drag.sy)>3&&(this._drag.moved=!0);const d=Mc(this._drag.ox+c),p=Mc(this._drag.oy+h);this._savePos({id:s,space:i},d,p)}_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,r=n.top+n.height/2,a=Math.max(8,Math.hypot(t.clientX-o,t.clientY-r));this._rlResize={id:"rl_"+(e.id||""),space:i,k0:this._labelScale(e),cx:o,cy:r,d0:a},bm(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/pm,y:o.y/pm,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``}_renderRoomLabel(t,e,i,s){if(!t.name&&!this._markup)return G;const n=this._labelPos(t,e.id),o=this._scenePoint([n.x,n.y]),r=(o[0]-i.x)/i.w*100,a=(o[1]-i.y)/i.h*100,l=Math.min(1,s.opacity+.25),c=this._labelScale(t),h=[];if(t.area||t.settings?.temp_source||t.settings?.hum_source||s.labelLight){if(s.labelTemp){const e=this._roomTemp(t);null!=e&&h.push(W`${e}°`)}if(s.labelHum){const e=this._roomHum(t);null!=e&&h.push(W`${e}%`)}if(s.labelLqi&&t.area){const e=this._roomLqi(t.area);null!=e&&h.push(W`${e}`)}if(s.labelLight){const e=(d=ho(this._renderPlanHass,this._renderDevices,t,this._virtualLights)).length?{on:d.filter(t=>t.on).length,total:d.length}:null;if(e){const t=0===e.on?this._t("roomcard.light_off"):e.on===e.total?this._t("roomcard.light_on"):this._t("roomcard.light_partial",{on:e.on,total:e.total});h.push(W`${t}`)}}}var d;const p=!!t.area,u=!this._markup;return W`
`}_renderRoomLabel(t,e,i,s){if(!t.name&&!this._markup)return G;const n=this._labelPos(t,e.id),o=this._scenePoint([n.x,n.y]),a=(o[0]-i.x)/i.w*100,r=(o[1]-i.y)/i.h*100,l=Math.min(1,s.opacity+.25),c=this._labelScale(t),h=[];if(t.area||t.settings?.temp_source||t.settings?.hum_source||s.labelLight){if(s.labelTemp){const e=this._roomTemp(t);null!=e&&h.push(W`${e}°`)}if(s.labelHum){const e=this._roomHum(t);null!=e&&h.push(W`${e}%`)}if(s.labelLqi&&t.area){const e=this._roomLqi(t.area);null!=e&&h.push(W`${e}`)}if(s.labelLight){const e=(d=ho(this._renderPlanHass,this._renderDevices,t,this._virtualLights)).length?{on:d.filter(t=>t.on).length,total:d.length}:null;if(e){const t=0===e.on?this._t("roomcard.light_off"):e.on===e.total?this._t("roomcard.light_on"):this._t("roomcard.light_partial",{on:e.on,total:e.total});h.push(W`${t}`)}}}var d;const p=!!t.area,u=!this._markup;return W`
this._labelDown(i,t,e.id)} @pointermove=${i=>this._labelMove(i,t,e.id)} @pointerup=${()=>this._labelUp(t)} @@ -6212,12 +6212,12 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8 @pointermove=${t=>this._rlResizeMove(t)} @pointerup=${()=>this._rlResizeUp()} @pointercancel=${()=>this._rlResizeUp()}>`):G} -
`}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),r=Math.round(10*o)/10,a=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)} · ${r}°
`}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,r=(i+n)/2;if("line"===t.kind){const e=Os(t.a,t.b);return{x:o,y:r,on45:Ns(e),text:`${this._fmtLen(t.a,t.b)} · ${Math.round(10*e)/10}°`}}const a=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]),a=this._fmtLen([0,0],[0,Math.abs(n-i)/2]);return{x:o,y:r,on45:!1,text:Math.abs(Math.abs(s-e)-Math.abs(n-i))<1e-6?`R ${t}`:`Rx ${t} × Ry ${a}`}}return{x:o,y:r,on45:!1,text:`${a} × ${l} · ${Ir(ha(Math.abs(s-e),this._cellCm,this._gridPitch)*ha(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=pm,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,r,a]="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` +
`}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=um,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` `})} - `}_renderOpeningCenterTick(t){const e=(t.angle+90)*Math.PI/180,i=cc(15,this._cellCm);return j``})} + `}_renderOpeningCenterTick(t){const e=(t.angle+90)*Math.PI/180,i=hc(15,this._cellCm);return j``}_renderOpeningDimensionGuides(t){const e=t.labels.flatMap(t=>t.dimension?[t.dimension]:[]);if(!e.length)return j``;const i=this._cssPxToRender(4);return j``}_roomCenter(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)]}_openingAmt(t){const e=t.contact&&this._renderOpeningEntityAvailable(t.contact)?this._renderPlanHass.states[t.contact]?.state:null;return gi(t.type,e,!!t.invert)}_planEntityAvailable(t){return!!t&&(!ko(this._fullRegistryHass,t,wo(this._markers))&&"active"===this._bindingStatus("entity:"+t).kind)}_renderEntityAvailable(t){return!!t&&(!ko(this._renderPlanHass,t,wo(this._markers))&&(!!this._renderPlanHass.entities?.[t]&&!!this._renderPlanHass.states?.[t]))}_openingEntityAvailable(t){return function(t,e,i=An(t)){return!!e&&"active"===Bn(t,`entity:${e}`,i).kind}(this.hass,t,this._haRegistry)}_renderOpeningEntityAvailable(t){return e=this._renderPlanHass,!!(i=t)&&!!e?.states?.[i];var e,i}_renderOpeningPlacementPreview(){const t=this._openingPreview;if(!t)return j``;const e={type:t.type,length:t.renderedLength,angle:t.angle,amount:gi(t.type,null),flipH:t.flipH,flipV:t.flipV,base:"var(--hp-open)",tone:"var(--hp-open)",cellCm:this._cellCm,gridPitch:this._gridPitch,face:t.face},i="passage"===t.type?function(t,e){const i=Math.max(0,t.renderedLength)/2,s=Math.max(0,t.target.physicalHalfWidth),n=s+.18*Math.max(0,e),o=t=>({x1:t,y1:-n,x2:t,y2:n});return{rect:{x:-i,y:s?-s:0,width:2*i,height:2*s},boundaries:[o(-i),o(i)]}}(t,cc(this._gridPitch,this._cellCm)):null;return j``}_roomCenter(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)]}_openingAmt(t){const e=t.contact&&this._renderOpeningEntityAvailable(t.contact)?this._renderPlanHass.states[t.contact]?.state:null;return gi(t.type,e,!!t.invert)}_planEntityAvailable(t){return!!t&&(!ko(this._fullRegistryHass,t,wo(this._markers))&&"active"===this._bindingStatus("entity:"+t).kind)}_renderEntityAvailable(t){return!!t&&(!ko(this._renderPlanHass,t,wo(this._markers))&&(!!this._renderPlanHass.entities?.[t]&&!!this._renderPlanHass.states?.[t]))}_openingEntityAvailable(t){return function(t,e,i=An(t)){return!!e&&"active"===Bn(t,`entity:${e}`,i).kind}(this.hass,t,this._haRegistry)}_renderOpeningEntityAvailable(t){return e=this._renderPlanHass,!!(i=t)&&!!e?.states?.[i];var e,i}_renderOpeningPlacementPreview(){const t=this._openingPreview;if(!t)return j``;const e={type:t.type,length:t.renderedLength,angle:t.angle,amount:gi(t.type,null),flipH:t.flipH,flipV:t.flipV,base:"var(--hp-open)",tone:"var(--hp-open)",cellCm:this._cellCm,gridPitch:this._gridPitch,face:t.face},i="passage"===t.type?function(t,e){const i=Math.max(0,t.renderedLength)/2,s=Math.max(0,t.target.physicalHalfWidth),n=s+.18*Math.max(0,e),o=t=>({x1:t,y1:-n,x2:t,y2:n});return{rect:{x:-i,y:s?-s:0,width:2*i,height:2*s},boundaries:[o(-i),o(i)]}}(t,hc(this._gridPitch,this._cellCm)):null;return j` `}_renderOpenings(t){const e=this._openingsR;if(!e.length)return j``;const i=this._spaceModel();if(!i)return j``;const s=t.color,n=this._spaceWalls,o=this._openPairs().flatMap(t=>t.segs),r=this._openingWallIndexFor(i,o).value;return j`${e.map(t=>{if(t.orphanReason)return j``}_renderOpenings(t){const e=this._openingsR;if(!e.length)return j``;const i=this._spaceModel();if(!i)return j``;const s=t.color,n=this._spaceWalls,o=this._openPairs().flatMap(t=>t.segs),a=this._openingWallIndexFor(i,o).value;return j`${e.map(t=>{if(t.orphanReason)return j`{e.stopPropagation(),this._editOpening(t)}}> - + ! - `;const e=this._openingAmt(t),i=e>0&&!!t.contact&&this._renderOpeningEntityAvailable(t.contact)?"var(--hp-open)":s,o="gate"===t.type?!t.flip_v:t.flip_v,a=t.partitionHost||n.length||"gate"===t.type?this._openingFace(t,r,!!o):{ox:0,oy:0,cm:0,side:-1},l={type:t.type,length:t.rlen,angle:t.angle,amount:e,flipH:!!t.flip_h,flipV:!!t.flip_v,base:s,tone:i,cellCm:this._cellCm,gridPitch:this._gridPitch,face:a},{half:c,outlineHalf:h,hitHalf:d}=qp(l),p=cc(10,this._cellCm),u=cc(12,this._cellCm);return j``;const e=this._openingAmt(t),i=e>0&&!!t.contact&&this._renderOpeningEntityAvailable(t.contact)?"var(--hp-open)":s,o="gate"===t.type?!t.flip_v:t.flip_v,r=t.partitionHost||n.length||"gate"===t.type?this._openingFace(t,a,!!o):{ox:0,oy:0,cm:0,side:-1},l={type:t.type,length:t.rlen,angle:t.angle,amount:e,flipH:!!t.flip_h,flipV:!!t.flip_v,base:s,tone:i,cellCm:this._cellCm,gridPitch:this._gridPitch,face:r},{half:c,outlineHalf:h,hitHalf:d}=Wp(l),p=hc(10,this._cellCm),u=hc(12,this._cellCm);return j` - ${Wp(l)} + ${jp(l)} + rx="${hc(6,this._cellCm)}"> this._opClick(e,t)} @@ -6265,7 +6265,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8 @pointermove=${e=>this._opPointerMove(e,t)} @pointerup=${e=>this._opPointerUp(e,t)} @pointercancel=${e=>this._opPointerUp(e,t)}> - `})}`}_renderOpeningLocks(t){const e=this._openingsR.filter(t=>!t.orphanReason&&("door"===t.type||"gate"===t.type)&&t.lock&&this._renderOpeningEntityAvailable(t.lock));if(!e.length)return W``;const i=this._spaceModel();if(!i)return W``;const s=this._openPairs().flatMap(t=>t.segs),n=this._openingWallIndexFor(i,s).value;return W`${e.map(e=>{const i=this._renderPlanHass.states[e.lock]?.state,s="locked"===i,o=s||["unlocked","open","opening","unlocking","locking"].includes(String(i)),r=(e.angle+90)*Math.PI/180,a="gate"===e.type?this._openingFace(e,n,!e.flip_v):null,l=cc(16,this._cellCm),c=a?-l*a.side:l*(e.flip_v?-1:1),h=e.rx+Math.cos(r)*c,d=e.ry+Math.sin(r)*c,p=this._scenePoint([h,d]),u=(p[0]-t.x)/t.w*100,_=(p[1]-t.y)/t.h*100;return W`
`})}`}_renderOpeningLocks(t){const e=this._openingsR.filter(t=>!t.orphanReason&&("door"===t.type||"gate"===t.type)&&t.lock&&this._renderOpeningEntityAvailable(t.lock));if(!e.length)return W``;const i=this._spaceModel();if(!i)return W``;const s=this._openPairs().flatMap(t=>t.segs),n=this._openingWallIndexFor(i,s).value;return W`${e.map(e=>{const i=this._renderPlanHass.states[e.lock]?.state,s="locked"===i,o=s||["unlocked","open","opening","unlocking","locking"].includes(String(i)),a=(e.angle+90)*Math.PI/180,r="gate"===e.type?this._openingFace(e,n,!e.flip_v):null,l=hc(16,this._cellCm),c=r?-l*r.side:l*(e.flip_v?-1:1),h=e.rx+Math.cos(a)*c,d=e.ry+Math.sin(a)*c,p=this._scenePoint([h,d]),u=(p[0]-t.x)/t.w*100,_=(p[1]-t.y)/t.h*100;return W`
{t.stopPropagation(),"view"===this._mode&&(this._openingInfo=e)}}> -
`})}`}_lockAction(t,e){if(this._openingEntityAvailable(t)){if("unlock"===e){const e=this.hass?.states?.[t]?.attributes?.friendly_name||t;if(!confirm(this._t("confirm.unlock",{name:e})))return}this.hass?.callService?.("lock",e,{entity_id:t})}}_renderOpeningInfoCard(){const t=this._openingInfo,e="passage"!==t.type&&t.contact&&this._openingEntityAvailable(t.contact)?t.contact:null,i=("door"===t.type||"gate"===t.type)&&t.lock&&this._openingEntityAvailable(t.lock)?t.lock:null,s=e?this.hass.states[e]?.state:null,n=this._openingAmt(t),o=i?this.hass.states[i]?.state:null,r="door"===t.type?"opening.door":"gate"===t.type?"opening.gate":"passage"===t.type?"opening.passage":"opening.window",a="door"===t.type?"mdi:door":"gate"===t.type?"mdi:gate":"passage"===t.type?"mdi:arch":"mdi:window-closed-variant",l="gate"===t.type?n>0?"mdi:gate-open":"mdi:gate":n>0?"mdi:door-open":"mdi:door-closed",c=(t,e,i,s="")=>W`
${e}${i}
`;return W``})}`}_lockAction(t,e){if(this._openingEntityAvailable(t)){if("unlock"===e){const e=this.hass?.states?.[t]?.attributes?.friendly_name||t;if(!confirm(this._t("confirm.unlock",{name:e})))return}this.hass?.callService?.("lock",e,{entity_id:t})}}_renderOpeningInfoCard(){const t=this._openingInfo,e="passage"!==t.type&&t.contact&&this._openingEntityAvailable(t.contact)?t.contact:null,i=("door"===t.type||"gate"===t.type)&&t.lock&&this._openingEntityAvailable(t.lock)?t.lock:null,s=e?this.hass.states[e]?.state:null,n=this._openingAmt(t),o=i?this.hass.states[i]?.state:null,a="door"===t.type?"opening.door":"gate"===t.type?"opening.gate":"passage"===t.type?"opening.passage":"opening.window",r="door"===t.type?"mdi:door":"gate"===t.type?"mdi:gate":"passage"===t.type?"mdi:arch":"mdi:window-closed-variant",l="gate"===t.type?n>0?"mdi:gate-open":"mdi:gate":n>0?"mdi:door-open":"mdi:door-closed",c=(t,e,i,s="")=>W`
${e}${i}
`;return W`this._openingInfo=null}>
${e?c(l,this._t("opening.contact_label"),"unavailable"===s||null==s?this._t("opening.state_unknown"):this._t(n>0?"opening.open":"opening.closed"),n>0?"warn":"ok"):G} @@ -6293,7 +6293,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8
-
`}_renderOpeningDialog(){const t=this._openingDialog,e=this._spaceModel()?.partitions||[],i=t.id?this._curSpaceCfg?.openings?.find(e=>e.id===t.id):null,s={id:t.id||"preview",type:t.type,x:t.x/pm,y:t.y/this._spaceH,angle:t.angle,length:i&&!t.lengthTouched?i.length:this._cmToUnits(Math.max(20,t.lengthCm))/pm,...t.host?{host:t.host}:{}},n=Id(i,s),o=t.host?n?Rd(s,e,pm,this._cellCm,this._gridPitch):Pd(s,e,pm,this._cellCm,this._gridPitch):null,r="does-not-fit-jamb"===o?.reason,a=t.host?e.find(e=>e.id===t.host.id):null,l=a?li(a.cm/2,this._imperial):"",c=!!t.host&&!o?.resolved&&!r,h="gate"===t.type?"mdi:gate":"window"===t.type?"mdi:window-closed-variant":"passage"===t.type?"mdi:arch":"mdi:door",d=(t,e,i)=>W`i(t.target.value)}> ${t.map(t=>W``)} `;return W` ${t.host?W` -
- ${c||r?W``:G} - ${c?this._t("opening.partition_orphan"):r?this._t("opening.partition_jamb_margin",{distance:l}):this._t("opening.host_partition")} +
+ ${c||a?W``:G} + ${c?this._t("opening.partition_orphan"):a?this._t("opening.partition_jamb_margin",{distance:l}):this._t("opening.host_partition")}
`:G} {const i=Zg(e.target.value);null!=i&&(this._openingDialog={...t,lengthCm:i,lengthTouched:!0})}} /> + @input=${e=>{const i=Qg(e.target.value);null!=i&&(this._openingDialog={...t,lengthCm:i,lengthTouched:!0})}} /> ${"passage"===t.type&&(t.contact||t.lock)?W`
@@ -6358,7 +6358,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8
-
`}_gridLevels(){const t=this._stageEl,e=this._viewOr(this._baseVb()),i=t&&t.clientWidth&&e.w?t.clientWidth/e.w:1;return function(t,e,i=7){if(!(t>0&&e>0&&Number.isFinite(e)))return null;const s=Bc.find(s=>t*s*e>=i);if(void 0===s)return null;const n=Bc.find(t=>t>=5*s)??5*s;return{fine:s,coarse:n}}(this._gridPitch,i)}_renderMarkupDefs(t){const e=this._gridLevels();if(!e)return j``;const i=this._gridPitch*e.fine,s=this._gridPitch*e.coarse,n=this._gridPitch*e.fine*.14;return j` +
`}_gridLevels(){const t=this._stageEl,e=this._viewOr(this._baseVb()),i=t&&t.clientWidth&&e.w?t.clientWidth/e.w:1;return function(t,e,i=7){if(!(t>0&&e>0&&Number.isFinite(e)))return null;const s=qc.find(s=>t*s*e>=i);if(void 0===s)return null;const n=qc.find(t=>t>=5*s)??5*s;return{fine:s,coarse:n}}(this._gridPitch,i)}_renderMarkupDefs(t){const e=this._gridLevels();if(!e)return j``;const i=this._gridPitch*e.fine,s=this._gridPitch*e.coarse,n=this._gridPitch*e.fine*.14;return j` @@ -6372,42 +6372,42 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8 - `}_renderPhysicalEditorLayer(){const t=this._spaceModel();if(!t)return j``;const e=this._gridPitch,i=this._viewOr(this._baseVb()),s=this._stageEl,n=s?.clientWidth?i.w/s.clientWidth:e/8,o=Math.max(.22*e,8*n),r=Math.max(o,12*n),a=t=>`M ${t.map(t=>`${t[0]} ${t[1]}`).join(" L ")} Z`,l=(t,e)=>this._physicalSel?.kind===t&&this._physicalSel.id===e||"column"===t&&this._duplicateColumnId===e,c=(t.room_drafts||[]).flatMap(t=>t.points.slice(0,-1).map((e,i)=>{const s=t.points[i+1],o=xa(t.segments[i]?.cm||15,this._cellCm,this._gridPitch);return j``}_renderPhysicalEditorLayer(){const t=this._spaceModel();if(!t)return j``;const e=this._gridPitch,i=this._viewOr(this._baseVb()),s=this._stageEl,n=s?.clientWidth?i.w/s.clientWidth:e/8,o=Math.max(.22*e,8*n),a=Math.max(o,12*n),r=t=>`M ${t.map(t=>`${t[0]} ${t[1]}`).join(" L ")} Z`,l=(t,e)=>this._physicalSel?.kind===t&&this._physicalSel.id===e||"column"===t&&this._duplicateColumnId===e,c=(t.room_drafts||[]).flatMap(t=>t.points.slice(0,-1).map((e,i)=>{const s=t.points[i+1],o=xr(t.segments[i]?.cm||15,this._cellCm,this._gridPitch);return j`{this._physicalSel={kind:"draft",id:t.id,segment:i},this._registerPhysicalTap("draft",t.id,i)}}>`})),h=(t.partitions||[]).map(t=>{const e=Vl(t.a,t.b,t.cm,this._cellCm,this._gridPitch);return e?j`{this._physicalSel={kind:"draft",id:t.id,segment:i},this._registerPhysicalTap("draft",t.id,i)}}>`})),h=(t.partitions||[]).map(t=>{const e=Kl(t.a,t.b,t.cm,this._cellCm,this._gridPitch);return e?j`this._physicalDown(e,"partition",t.id)} @pointermove=${t=>this._physicalMove(t)} - @pointerup=${t=>this._physicalUp(t)}>`:G}),d=(t.wall_columns||[]).map(t=>{const e=Kl(this._physicalRotate?.id===t.id?{...t,angle:this._physicalRotate.angle}:t,this._cellCm,this._gridPitch);return j`this._physicalUp(t)}>`:G}),d=(t.wall_columns||[]).map(t=>{const e=Yl(this._physicalRotate?.id===t.id?{...t,angle:this._physicalRotate.angle}:t,this._cellCm,this._gridPitch);return j`this._physicalDown(e,"column",t.id)} @pointermove=${t=>this._physicalMove(t)} - @pointerup=${t=>this._physicalUp(t)}>`}),p=this._physicalDrag,u=(()=>{if(!p?.moved)return G;const t="partition"===p.kind?Vl(p.base.a,p.base.b,p.base.cm,this._cellCm,this._gridPitch):Kl(p.base,this._cellCm,this._gridPitch);return t?j`this._physicalUp(t)}>`}),p=this._physicalDrag,u=(()=>{if(!p?.moved)return G;const t="partition"===p.kind?Kl(p.base.a,p.base.b,p.base.cm,this._cellCm,this._gridPitch):Yl(p.base,this._cellCm,this._gridPitch);return t?j``:G})(),_=(()=>{const i=this._physicalSel;if(!i)return G;if("draft"===i.kind){const e=t.room_drafts.find(t=>t.id===i.id);return e?j` t.join(",")).join(" ")}> ${e.points.map(t=>j``)} - `:G}if("partition"===i.kind){const e=t.partitions.find(t=>t.id===i.id);if(!e)return G;const s=Vl(e.a,e.b,e.cm,this._cellCm,this._gridPitch);if(!s)return G;const n=(e.a[0]+e.b[0])/2,r=(e.a[1]+e.b[1])/2;return j` - + `:G}if("partition"===i.kind){const e=t.partitions.find(t=>t.id===i.id);if(!e)return G;const s=Kl(e.a,e.b,e.cm,this._cellCm,this._gridPitch);if(!s)return G;const n=(e.a[0]+e.b[0])/2,a=(e.a[1]+e.b[1])/2;return j` + - - `}const s=t.wall_columns.find(t=>t.id===i.id);if(!s)return G;const l=this._physicalRotate?.id===s.id?{...s,angle:this._physicalRotate.angle}:s,c=Kl(l,this._cellCm,this._gridPitch);if("square"!==l.shape)return j` - + + `}const s=t.wall_columns.find(t=>t.id===i.id);if(!s)return G;const l=this._physicalRotate?.id===s.id?{...s,angle:this._physicalRotate.angle}:s,c=Yl(l,this._cellCm,this._gridPitch);if("square"!==l.shape)return j` + - `;const h=xa(l.cm,this._cellCm,this._gridPitch),d=ql(l.angle)*Math.PI/180,p=Math.sin(d),u=-Math.cos(d),_=[l.center[0]+p*h/2,l.center[1]+u*h/2],g=[_[0]+p*Math.max(e,24*n),_[1]+u*Math.max(e,24*n)];return j` - + `;const h=xr(l.cm,this._cellCm,this._gridPitch),d=Wl(l.angle)*Math.PI/180,p=Math.sin(d),u=-Math.cos(d),_=[l.center[0]+p*h/2,l.center[1]+u*h/2],g=[_[0]+p*Math.max(e,24*n),_[1]+u*Math.max(e,24*n)];return j` + - this._physicalRotateDown(t,s)} @pointermove=${t=>this._physicalRotateMove(t)} @pointerup=${t=>this._physicalRotateUp(t)}> - `})();return j`${c}${h}${d}${u}${_}`}_renderPlanSnapOverlay(){if(!this._markup||"draw"!==this._tool)return j``;const t=this._planSnapGeometrySnapshot().value,e=this._activePlanSnapCandidate,i=new Set(this._activePlanSnapConflicts.map(t=>t.key)),s=xa(5,this._cellCm,this._gridPitch),n=xa(10,this._cellCm,this._gridPitch);return j``})();return j`${c}${h}${d}${u}${_}`}_renderPlanSnapOverlay(){if(!this._markup||"draw"!==this._tool)return j``;const t=this._planSnapGeometrySnapshot().value,e=this._activePlanSnapCandidate,i=new Set(this._activePlanSnapConflicts.map(t=>t.key)),s=xr(5,this._cellCm,this._gridPitch),n=xr(10,this._cellCm,this._gridPitch);return j``}_syncPlanSnapActiveMarker(t){const e=this.renderRoot?.querySelector('[data-hp="plan-snap-active-marker"]');if(e){if(e.setAttribute("class",`plan-snap-node${t?" active":""}${"line"===t?.kind?" dynamic":""}`),e.setAttribute("data-active",t?"true":"false"),e.setAttribute("visibility",t?"visible":"hidden"),!t)return e.removeAttribute("data-kind"),void e.removeAttribute("data-key");e.setAttribute("data-kind",t.kind),e.setAttribute("data-key",t.key),e.setAttribute("cx",String(t.point[0])),e.setAttribute("cy",String(t.point[1])),e.setAttribute("r",String(xa(10,this._cellCm,this._gridPitch)))}}_syncPlanSnapConflictMarkers(t){const e=new Set(t.map(t=>t.key));for(const t of this.renderRoot?.querySelectorAll('.plan-snap-node[data-kind="endpoint"]')||[])t.setAttribute("class","plan-snap-node"+(e.has(t.dataset.key||"")?" conflict":""))}_planSnapPhysicalSegment(t){let e=0;const i=this._spaceModel();if(!i)return null;if("partition"===t.sourceKind)e=Number(i.partitions.find(e=>e.id===t.sourceId)?.cm)||0;else if("draft"===t.sourceKind){const s=/^(.*):(\d+)$/.exec(t.sourceId),n=s?i.room_drafts.find(t=>t.id===s[1]):null;e=n&&s&&Number(n.segments[Number(s[2])]?.cm)||0}else e=_l(i.rooms,this._spaceWalls,this._openCuts(),[t.a[0],t.a[1],t.b[0],t.b[1]],this._wallKeyPitch,this._cellCm,this._gridPitch,pm);return e>0?{a:[...t.a],b:[...t.b],halfDepth:xa(e,this._cellCm,this._gridPitch)/2}:null}_drawPreviewJoinPatchD(t,e){if(t.length<2)return"";const i=[];for(let s=0;s+10&&i.push({a:t[s],b:t[s+1],halfDepth:e[s]});if(!i.length)return"";const s=2e-4*this._gridPitch,n=this._planSnapGeometrySnapshot().value.segments.filter(e=>t.some(t=>Hs(t,[e.a[0],e.a[1],e.b[0],e.b[1]])<=s)).map(t=>this._planSnapPhysicalSegment(t)).filter(t=>!!t);return Ua([...i,...n],s).map(t=>`M ${t.map(t=>`${t[0]} ${t[1]}`).join(" L ")} Z`).join(" ")}_renderMarkupLayer(t){const e=this._openPairs().flatMap(t=>t.segs),i=this._thickWallCuts(),s=e.concat(i),n=s.length?Ds(this._segments,s,.02*this._gridPitch):this._segments,o=this._path,r=this._gridPitch,a=this._viewOr(this._baseVb()),l="draw"===this._tool?this._drawWallCm:null,c=(()=>"draw"===this._tool&&o.length&&null!=l&&l>0?this._contourClosed?o:this._cursorPt?[...o,this._cursorPt]:o.length>=2?o:null:null)(),h=c?Qd(c.length-1,this._contourClosed?[...this._draftSegmentCms,this._closingWallCm??void 0]:this._draftSegmentCms,l,fa).map(t=>xa(t,this._cellCm,this._gridPitch)/2):[],d=c?Ga(c,xa(l,this._cellCm,this._gridPitch)/2,this._contourClosed,h):"",p=c?this._drawPreviewJoinPatchD(c,h):"",u=this._wallFaceBatch?.candidates[this._wallFaceBatch.index]?.repair||this._wallRepairDiagnostic;return j` - ${this._gridLevels()?j``:G} + `}_syncPlanSnapActiveMarker(t){const e=this.renderRoot?.querySelector('[data-hp="plan-snap-active-marker"]');if(e){if(e.setAttribute("class",`plan-snap-node${t?" active":""}${"line"===t?.kind?" dynamic":""}`),e.setAttribute("data-active",t?"true":"false"),e.setAttribute("visibility",t?"visible":"hidden"),!t)return e.removeAttribute("data-kind"),void e.removeAttribute("data-key");e.setAttribute("data-kind",t.kind),e.setAttribute("data-key",t.key),e.setAttribute("cx",String(t.point[0])),e.setAttribute("cy",String(t.point[1])),e.setAttribute("r",String(xr(10,this._cellCm,this._gridPitch)))}}_syncPlanSnapConflictMarkers(t){const e=new Set(t.map(t=>t.key));for(const t of this.renderRoot?.querySelectorAll('.plan-snap-node[data-kind="endpoint"]')||[])t.setAttribute("class","plan-snap-node"+(e.has(t.dataset.key||"")?" conflict":""))}_planSnapPhysicalSegment(t){let e=0;const i=this._spaceModel();if(!i)return null;if("partition"===t.sourceKind)e=Number(i.partitions.find(e=>e.id===t.sourceId)?.cm)||0;else if("draft"===t.sourceKind){const s=/^(.*):(\d+)$/.exec(t.sourceId),n=s?i.room_drafts.find(t=>t.id===s[1]):null;e=n&&s&&Number(n.segments[Number(s[2])]?.cm)||0}else e=_l(i.rooms,this._spaceWalls,this._openCuts(),[t.a[0],t.a[1],t.b[0],t.b[1]],this._wallKeyPitch,this._cellCm,this._gridPitch,um);return e>0?{a:[...t.a],b:[...t.b],halfDepth:xr(e,this._cellCm,this._gridPitch)/2}:null}_drawPreviewJoinPatchD(t,e){if(t.length<2)return"";const i=[];for(let s=0;s+10&&i.push({a:t[s],b:t[s+1],halfDepth:e[s]});if(!i.length)return"";const s=2e-4*this._gridPitch,n=this._planSnapGeometrySnapshot().value.segments.filter(e=>t.some(t=>Hs(t,[e.a[0],e.a[1],e.b[0],e.b[1]])<=s)).map(t=>this._planSnapPhysicalSegment(t)).filter(t=>!!t);return Ur([...i,...n],s).map(t=>`M ${t.map(t=>`${t[0]} ${t[1]}`).join(" L ")} Z`).join(" ")}_renderMarkupLayer(t){const e=this._openPairs().flatMap(t=>t.segs),i=this._thickWallCuts(),s=e.concat(i),n=s.length?Ds(this._segments,s,.02*this._gridPitch):this._segments,o=this._path,a=this._gridPitch,r=this._viewOr(this._baseVb()),l="draw"===this._tool?this._drawWallCm:null,c=(()=>"draw"===this._tool&&o.length&&null!=l&&l>0?this._contourClosed?o:this._cursorPt?[...o,this._cursorPt]:o.length>=2?o:null:null)(),h=c?tp(c.length-1,this._contourClosed?[...this._draftSegmentCms,this._closingWallCm??void 0]:this._draftSegmentCms,l,fr).map(t=>xr(t,this._cellCm,this._gridPitch)/2):[],d=c?Gr(c,xr(l,this._cellCm,this._gridPitch)/2,this._contourClosed,h):"",p=c?this._drawPreviewJoinPatchD(c,h):"",u=this._wallFaceBatch?.candidates[this._wallFaceBatch.index]?.repair||this._wallRepairDiagnostic;return j` + ${this._gridLevels()?j``:G} ${n.map(t=>j``)} ${this._renderPhysicalEditorLayer()} - ${"column"===this._tool&&this._cursorPt&&this._drawWallCm?j``M ${Kl({shape:"square",center:this._cursorPt,cm:this._drawWallCm},this._cellCm,this._gridPitch).map(t=>`${t[0]} ${t[1]}`).join(" L ")} Z`)()}>`:G} + ${"column"===this._tool&&this._cursorPt&&this._drawWallCm?j``M ${Yl({shape:"square",center:this._cursorPt,cm:this._drawWallCm},this._cellCm,this._gridPitch).map(t=>`${t[0]} ${t[1]}`).join(" L ")} Z`)()}>`:G} ${d?j` `:G} ${p?j` @@ -6444,12 +6444,12 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8 ${o.length&&this._cursorPt&&"draw"===this._tool&&!this._contourClosed?j` ${this._activePlanSnapCandidate||this._activePlanSnapConflicts.length?G:j``}`:G} + r="${hc(.22*a,this._cellCm)}" aria-hidden="true">`}`:G} ${o.map((t,e)=>j``)} + cx="${t[0]}" cy="${t[1]}" r="${hc(.22*a,this._cellCm)}">`)} ${"split"===this._tool&&this._splitSel?.pts?.length?j`${this._splitSel.pts.length>1?j``:G} ${this._splitSel.pts.map((t,e)=>j``)} + cx="${t[0]}" cy="${t[1]}" r="${hc(.22*a,this._cellCm)}">`)} ${this._cursorPt?j``:G}`:G} `}_renderPartitionDeleteDialog(){const t=this._partitionDeleteDialog,e="mi"===this.hass?.config?.unit_system?.length;return W`

${this._t("confirm.delete_partition_openings_body",{count:t.openings.length})}

    - ${t.openings.map(t=>W`
  • ${this._t("confirm.delete_partition_openings_item",{type:this._t(`opening.${t.type}`),length:li(t.length*pm/this._gridPitch*this._cellCm,e)})}
  • `)} + ${t.openings.map(t=>W`
  • ${this._t("confirm.delete_partition_openings_item",{type:this._t(`opening.${t.type}`),length:li(t.length*um/this._gridPitch*this._cellCm,e)})}
  • `)}
@@ -6502,8 +6502,8 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8 `:G}
this._physicalDialog={...t,cm:e.target.value}} /> ${this._t(this._imperial?"wallthick.unit_in":"wallthick.unit_cm")}
${e&&"square"===t.shape?W` @@ -6663,7 +6663,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8 `:G}
- `}_markerValueBadgeFields(t){return(e={touched:t.valueBadgeTouched,originalHas:t.originalHasValueBadge,original:t.originalValueBadge,enabled:t.valueBadgeEnabled,source:t.valueBadgeSource,position:t.valueBadgePosition}).touched?{value_badge:{enabled:e.enabled,source:e.source,position:e.position}}:e.originalHas?{value_badge:e.original}:{};var e}_markerDraft(t){if("ha"===t.bindingMode&&(!t.binding||"virtual"===t.binding))return null;const e=qs(t.room),i=Ei(t.binding,t.devId,()=>"__hp_device_preview__"),s=this._markers.find(e=>e.id===i||e.id===t.devId),n=Zn(t.binding,t.controls,this._bindingEntities(t.binding)),o=this._effectiveStoredTapAction(t),r={id:i,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||null,...this._markerTapActionFields(t),...this._markerToggleEntityFields(t),tap_target:"run"===o&&t.tapTarget||null,tap_confirm:!!t.tapConfirm||null,controls:n.length?n:null,...this._markerLightFields(t),...this._markerValueBadgeFields(t),use_climate_temp:!!t.useClimateTemp||null,glow_radius_cm:(()=>{const e=Zg(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,vacuum:s?.vacuum||null};return("virtual"===t.binding||t.room)&&(r.space=e?.space||("virtual"===t.binding?this._space:null),r.area=e?.area||null,r.room_id=e?.roomId||null),r}_markerPreviewDevice(t){const e=this._markerDraft(t);if(!e)return null;const i=`${this._haRegistry.revision}\n${JSON.stringify(e)}`;if(this._markerPreviewMemo?.key===i)return this._markerPreviewMemo.device;const s=function(t){const{marker:e,...i}=t;return So({...i,markers:[e]}).find(t=>t.id===e.id)||null}({hass:this.hass,registry:this._haRegistry,areaToSpace:Object.fromEntries(Object.entries(this._areaToSpace).map(([t,e])=>[t,e.space])),marker:e,settings:this._settings,excluded:this._excluded,showAll:this._showAll,firstSpaceId:this._model[0]?.id||this._space,loc:t=>this._t(t),iconRules:this._iconRules});return this._markerPreviewMemo={key:i,device:s},s}_markerPreviewDevices(t){const e=this._markerPreviewDevicesMemo;if(e?.base===this._devices&&e.preview===t)return e.devices;const i=[...this._devices.filter(e=>e.id!==t.id),t];return this._markerPreviewDevicesMemo={base:this._devices,preview:t,devices:i},i}_toggleIntent(t,e=this._devices){return xd({hass:this._planHass,registryHass:this._fullRegistryHass,devices:e,device:t,virtualLights:this._virtualLights})}_toggleIntentForDialog(t){const e=this._markerPreviewDevice(t);if(!e)return null;const i=this._markerPreviewDevices(e);return this._toggleIntent(e,i)}_toggleStateText(t,e){const i=this._planHass?.states?.[t]||this.hass?.states?.[t];try{return i&&"function"==typeof this.hass?.formatEntityState?this.hass.formatEntityState(i):e}catch{return e}}_toggleConfirmationStateText(t){const e=String(t.state||"unknown"),i=t.entityId?this._toggleStateText(t.entityId,e):e;if(i.trim().toLocaleLowerCase()!==e.trim().toLocaleLowerCase())return i;const s={on:"confirm.state_on",off:"confirm.state_off",open:"confirm.state_open",closed:"confirm.state_closed",opening:"confirm.state_opening",closing:"confirm.state_closing",unknown:"confirm.state_unknown"}[e];return s?this._t(s):e.replaceAll("_"," ").replaceAll("-"," ")}_toggleConfirmationLines(t){const e={"turn-on":"confirm.state_on","turn-off":"confirm.state_off",open:"confirm.state_open",close:"confirm.state_closed",stop:"confirm.state_stopped"};return function(t,e){if(!Sd(t)||!t.nextEffect||!t.targets.length)return[];const i="group"===t.kind,s=i?t.targets.filter(t=>"on"===t.state).length:0,n=i?0===s?e.groupAllOff():e.groupCurrent(s,t.targets.length):e.state(t.targets[0]);let o;return o="toggle"===t.nextEffect?e.expectedByHa():i&&"turn-on"===t.nextEffect?e.groupAllOn():i&&"turn-off"===t.nextEffect?e.groupAllOff():e.effect(t.nextEffect),[e.current(n),e.expected(o),...t.skippedTargets.length?[e.unavailable(t.skippedTargets.length)]:[]]}(t,{state:t=>this._toggleConfirmationStateText(t),current:t=>this._t("confirm.current_state",{state:t}),expected:t=>this._t("confirm.expected_state",{state:t}),groupCurrent:(t,e)=>this._t("confirm.group_current",{on:t,total:e}),groupAllOn:()=>this._t("confirm.group_all_on"),groupAllOff:()=>this._t("confirm.group_all_off"),unavailable:t=>this._t("confirm.unavailable_targets",{count:t}),effect:t=>this._t(e[t]),expectedByHa:()=>this._t("confirm.expected_by_ha")})}_toggleHintLines(t){if(!t)return[];const e=t=>this._t(`marker.toggle_effect_${t.replace("-","_")}`),i=t=>this._t(`marker.toggle_skip_${t.replace("-","_")}`);return function(t,e){const i=t.targets[0]||t.skippedTargets[0],s=[];return"group"===t.kind?t.targets.length&&s.push(e.group(t.targets)):i&&s.push(e.single(i)),t.nextEffect&&t.targets.length&&s.push("group"===t.kind?e.groupCurrentNext(t.targets,t.nextEffect):e.currentNext(t.targets[0],t.nextEffect)),t.skippedTargets.length&&s.push(e.skipped(t.skippedTargets)),!t.command&&t.noneReason&&s.push(e.none(t.noneReason)),s}(t,{single:t=>{if("via"in t&&"virtual-light"===t.via)return this._t("marker.virtual_light_target",{name:t.name});const e=t.entityId||("ref"in t?t.ref:""),i=t.name||e;return this._t("marker.toggle_hint_single",{name:i,id:e})},group:t=>this._t("marker.toggle_hint_group",{count:t.length,names:t.map(t=>`${t.name} (${t.entityId})`).join(", ")}),currentNext:(t,i)=>"virtual-light"===t.via?this._t("marker.virtual_light_current",{state:this._t("on"===t.state?"marker.virtual_light_state_on":"marker.virtual_light_state_off"),effect:e(i)}):this._t("marker.toggle_hint_current",{state:this._toggleStateText(t.entityId,t.state),effect:e(i)}),groupCurrentNext:(t,i)=>this._t("marker.toggle_hint_group_current",{on:t.filter(t=>"on"===t.state).length,count:t.length,effect:e(i)}),skipped:t=>this._t("marker.toggle_hint_skipped",{count:t.length,targets:t.map(t=>{const e=t.entityId||t.ref;return`${t.name||e} (${e}: ${i(t.reason)})`}).join(", ")}),none:t=>this._t(`marker.toggle_none_${t.replaceAll("-","_")}`)})}_effectiveStoredTapAction(t,e){return t.tapActionTouched?t.tapAction:yd(t.originalHasTapAction?t.originalTapAction:null,e)}_effectiveMarkerTapAction(t,e=this._markerPreviewDevice(t)){return this._effectiveStoredTapAction(t,e?.primary?.split(".")[0])}_announceToggleDraft(t){const e=this._markerPreviewDevice(t),i=t.tapActionTouched?t:{...t,tapAction:this._effectiveMarkerTapAction(t,e)},s="toggle"===i.tapAction?this._toggleHintLines(this._toggleIntentForDialog(i)).join(" "):"";return{...i,tapHintAnnouncement:s}}_valueBadgeForBinding(t,e){const i={...t,binding:e,valueBadgeEnabled:!1,valueBadgeSource:null,valueBadgeTouched:!0},s=this._markerPreviewDevice(i);if(!s)return{valueBadgeEnabled:!1,valueBadgeSource:null,valueBadgeTouched:!0};const n=[...this._devices.filter(t=>t.id!==s.id),s],o=Wo(this._planHass,s,n),r=jo(this._planHass,s,o);return{valueBadgeEnabled:t.valueBadgeEnabled&&!!r,valueBadgeSource:r,valueBadgeTouched:!0}}_markerSpatialSource(t){const e=this._markerPreviewDevice(t);if(!e)return null;const i={...e,hidden:!1};return po(ho(this._planHass,[...this._devices.filter(t=>t.id!==i.id),i],null,this._virtualLights).filter(t=>t.device.id===i.id))}_markerAutoHasSpatialSource(t){const e={...t,lightRole:"auto",lightRoleTouched:!0},i=this._markerPreviewDevice(e);return!!i&&lo(this._planHass,{...i})}_setMarkerLightRole(t){const e=this._markerDialog;e&&(this._markerDialog={...e,lightRole:t,lightRoleTouched:!0})}_controlRefInfo(t){if(!t.startsWith("marker:"))return{label:this.hass.states[t]?.attributes?.friendly_name||t,sub:t,icon:t.startsWith("light.")?"mdi:lightbulb":"mdi:toggle-switch",warning:!this._planEntityAvailable(t)};const e=t.slice(7),i=this._markers.find(t=>t.id===e),s=this._devices.find(t=>t.id===e);if(!i||i.removed||!0!==i.is_light)return{label:this._t("marker.control_missing_label"),sub:`${this._t("marker.control_broken")} (${t})`,icon:"mdi:alert-outline",warning:!0};const n=this._serverCfg?.spaces.find(t=>t.id===(s?.space||i.space)),o=!!s&&to(s).length>0;return{label:i.name||s?.name||e,sub:[n?.title||s?.space||i.space,i.room_id||s?.area,o?"":this._t("marker.control_passive")].filter(Boolean).join(" · "),icon:i.icon||s?.icon||"mdi:lightbulb-outline",warning:!0===i.hidden||!0===s?.hidden}}_valueBadgeCandidateLabel(t){const e=t.source;if("derived_lqi"===e.kind)return this._t("marker.value_badge_lqi");if("derived_marker_state"===e.kind)return this._t("marker.value_badge_marker_state",{name:t.label});if("entity_state"===e.kind)return this._t("marker.value_badge_state",{name:t.label});const i=this.hass.states[e.entity_id]?.attributes?.friendly_name||this._fullRegistryHass.entities[e.entity_id]?.name||e.entity_id;return this._t(`marker.value_badge_attr_${e.attribute}`,{name:i})}_controlCandidates(t){const e=this._markerDraft(t)?.id||t.devId||"",i=[],s=new Set;for(const t of this._markers){if(t.id===e||t.removed||t.hidden||!0!==t.is_light)continue;if("virtual"!==t.binding&&"active"!==this._bindingStatus(t.binding).kind)continue;const n=this._devices.find(e=>e.id===t.id);if(!n||n.hidden)continue;const o=this._controlRefInfo(`marker:${t.id}`);for(const t of to(n))s.add(t);i.push({value:`marker:${t.id}`,label:o.label,sub:o.sub,icon:o.icon,search:`${o.label} ${o.sub} ${t.id} ${to(n).join(" ")}`.toLowerCase()})}const n=Object.keys(this.hass.states||{}).filter(e=>Ms(e)&&!s.has(e)&&Jn(t.binding,[e],this._bindingEntities(t.binding)).length>0&&this._planEntityAvailable(e)).map(t=>{const e=this._controlRefInfo(t);return{value:t,label:e.label,sub:t,icon:e.icon,search:`${e.label} ${t}`.toLowerCase()}}),o=t.controlsFilter.trim().toLowerCase();return[...i,...n].filter(e=>!t.controls.includes(e.value)&&(!o||e.search.includes(o))).slice(0,12).map(({search:t,...e})=>e)}_addControlRef(t,e){if(e.startsWith("marker:")){const i=this._markerDraft(t)?.id||t.devId||"";if(!i)return void this._showToast(this._t("toast.marker_binding_required"));const s=e.slice(7),n=this._markerDraft(t);if(function(t,e,i){if(!e||e===i)return!0;const s=new Map;for(const e of t)s.set(e.id,(e.controls||[]).filter(t=>"string"==typeof t&&t.startsWith("marker:")).map(t=>t.slice(7)));const n=new Set,o=[i];for(;o.length;){const t=o.pop();if(t===e)return!0;n.has(t)||(n.add(t),o.push(...s.get(t)||[]))}return!1}(n?[...this._markers.filter(t=>t.id!==i),n]:this._markers,i,s))return void this._showToast(this._t("toast.marker_control_cycle"))}this._markerDialog=this._announceToggleDraft({...t,controls:[...t.controls,e],controlsFilter:""})}_setMarkerGlowMode(t){const e=this._markerDialog;if(!e)return;if("auto"===t)return void(this._markerDialog={...e,glowMode:t,glowTouched:!0});const i=this._markerSpatialSource(e),s=xs(i?this._planHass.states[i.eid]:void 0,null,this._fillColors.glow_light.c),n=!e.glowColorDrafted,o="fixed"===t&&!e.glowBrightnessDrafted;this._markerDialog={...e,glowMode:t,glowColor:n?s.c:e.glowColor,glowBrightness:o?Math.max(1,Math.round(100*s.bri)):e.glowBrightness,glowColorDrafted:!0,glowBrightnessDrafted:e.glowBrightnessDrafted||"fixed"===t,glowTouched:!0}}_renderMarkerDialog(){const t=this._markerDialog,e="virtual"===t.bindingMode,i=this._bindingCandidates();this._bindingEntities(t.binding);const s=e?null:this._bindingStatus(t.binding),n=!e&&this._bindingHasHaPage(t.binding),o=this._markerPreviewDevice(t),r=this._effectiveMarkerTapAction(t,o),a=o?cs(this._serverCfg?.spaces.find(t=>t.id===o.space)):null,l=o?this._markerPreviewDevices(o):this._devices,c="toggle"===r&&o?this._toggleIntent(o,l):null,h=this._toggleHintLines(c),d=o?iu(this._planHass,o,{liveStates:!1!==this._config?.live_states,showTemperature:!1!==this._config?.show_temperature,showSignal:a?.showLqi??!1!==this._config?.show_signal,designPreview:!0,activityRuntime:this._activityRt.get(o.id),lightDevices:l,registryHass:this._fullRegistryHass,reducedMotion:this._reducedMotion}):null,p=o?Wo(this._planHass,o,l):[],u=o?jo(this._planHass,o,p):null,_=t.valueBadgeTouched?t.valueBadgeEnabled:!!d?.valueBadge,g=t.valueBadgeTouched?t.valueBadgeSource:d?.valueBadge?.source||t.valueBadgeSource,m=t.valueBadgeTouched?t.valueBadgePosition:d?.valueBadge?.position||t.valueBadgePosition,f=Ao(g),v=!!g&&!p.some(t=>t.key===f),y=p.find(t=>t.key===f),b=d?.valueSource?d.valueSource.attribute?`attr:${d.valueSource.eid}:${d.valueSource.attribute}`:`state:${d.valueSource.eid}`:"",w=this._markerAutoHasSpatialSource(t),k=!!o&&function(t,e){return io(t,e).some(t=>!!t.eid)}(this._planHass,{...o}),x=function(t,e,i,s){const n="always"===t||"auto"===t&&e,o=n&&!i;return{sourceExists:n,fromSourceEnabled:n&&i,manualEnabled:n,radiusEnabled:n,passive:o,effectiveMode:o&&"auto"===s?"fixed":s}}(t.lightRole,w,k,t.glowMode),$=!x.sourceExists,S=!x.fromSourceEnabled,M=x.passive,C=x.effectiveMode,D="never"===t.lightRole?this._t("marker.glow_disabled_never"):"auto"!==t.lightRole||w?M?this._t("marker.glow_passive_hint"):this._t("marker.glow_disabled_no_entity"):this._t("marker.glow_disabled_auto"),T=o?to(o):[],P=o&&eo(o)||"",R=!!t.lightEntity&&!T.includes(t.lightEntity),I=o?_d(o):[],A=!!t.toggleEntity&&!I.includes(t.toggleEntity),F="toggle"===r?this._toggleIntentForDialog({...t,toggleEntity:"",toggleEntityTouched:!0}):null,E=F?[...F.targets,...F.skippedTargets].map(t=>t.entityId||("ref"in t?t.ref:"")).filter(Boolean).join(", "):"",z=(()=>{if(e)return null;const s=i.find(e=>e.value===t.binding);if(s)return s.label;const[n,o]=t.binding.split(":");return"device"===n?this._fullRegistryHass.devices[o]?.name_by_user||this._fullRegistryHass.devices[o]?.name||o:this._fullRegistryHass.entities[o]?.name||this.hass.states[o]?.attributes?.friendly_name||o})();return W``}_markerValueBadgeFields(t){return(e={touched:t.valueBadgeTouched,originalHas:t.originalHasValueBadge,original:t.originalValueBadge,enabled:t.valueBadgeEnabled,source:t.valueBadgeSource,position:t.valueBadgePosition}).touched?{value_badge:{enabled:e.enabled,source:e.source,position:e.position}}:e.originalHas?{value_badge:e.original}:{};var e}_markerDraft(t){if("ha"===t.bindingMode&&(!t.binding||"virtual"===t.binding))return null;const e=qs(t.room),i=Ei(t.binding,t.devId,()=>"__hp_device_preview__"),s=this._markers.find(e=>e.id===i||e.id===t.devId),n=Zn(t.binding,t.controls,this._bindingEntities(t.binding)),o=this._effectiveStoredTapAction(t),a={id:i,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||null,...this._markerTapActionFields(t),...this._markerToggleEntityFields(t),tap_target:"run"===o&&t.tapTarget||null,tap_confirm:!!t.tapConfirm||null,controls:n.length?n:null,...this._markerLightFields(t),...this._markerValueBadgeFields(t),use_climate_temp:!!t.useClimateTemp||null,glow_radius_cm:(()=>{const e=Qg(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,vacuum:s?.vacuum||null};return("virtual"===t.binding||t.room)&&(a.space=e?.space||("virtual"===t.binding?this._space:null),a.area=e?.area||null,a.room_id=e?.roomId||null),a}_markerPreviewDevice(t){const e=this._markerDraft(t);if(!e)return null;const i=`${this._haRegistry.revision}\n${JSON.stringify(e)}`;if(this._markerPreviewMemo?.key===i)return this._markerPreviewMemo.device;const s=function(t){const{marker:e,...i}=t;return So({...i,markers:[e]}).find(t=>t.id===e.id)||null}({hass:this.hass,registry:this._haRegistry,areaToSpace:Object.fromEntries(Object.entries(this._areaToSpace).map(([t,e])=>[t,e.space])),marker:e,settings:this._settings,excluded:this._excluded,showAll:this._showAll,firstSpaceId:this._model[0]?.id||this._space,loc:t=>this._t(t),iconRules:this._iconRules});return this._markerPreviewMemo={key:i,device:s},s}_markerPreviewDevices(t){const e=this._markerPreviewDevicesMemo;if(e?.base===this._devices&&e.preview===t)return e.devices;const i=[...this._devices.filter(e=>e.id!==t.id),t];return this._markerPreviewDevicesMemo={base:this._devices,preview:t,devices:i},i}_toggleIntent(t,e=this._devices){return $d({hass:this._planHass,registryHass:this._fullRegistryHass,devices:e,device:t,virtualLights:this._virtualLights})}_toggleIntentForDialog(t){const e=this._markerPreviewDevice(t);if(!e)return null;const i=this._markerPreviewDevices(e);return this._toggleIntent(e,i)}_toggleStateText(t,e){const i=this._planHass?.states?.[t]||this.hass?.states?.[t];try{return i&&"function"==typeof this.hass?.formatEntityState?this.hass.formatEntityState(i):e}catch{return e}}_toggleConfirmationStateText(t){const e=String(t.state||"unknown"),i=t.entityId?this._toggleStateText(t.entityId,e):e;if(i.trim().toLocaleLowerCase()!==e.trim().toLocaleLowerCase())return i;const s={on:"confirm.state_on",off:"confirm.state_off",open:"confirm.state_open",closed:"confirm.state_closed",opening:"confirm.state_opening",closing:"confirm.state_closing",unknown:"confirm.state_unknown"}[e];return s?this._t(s):e.replaceAll("_"," ").replaceAll("-"," ")}_toggleConfirmationLines(t){const e={"turn-on":"confirm.state_on","turn-off":"confirm.state_off",open:"confirm.state_open",close:"confirm.state_closed",stop:"confirm.state_stopped"};return function(t,e){if(!Md(t)||!t.nextEffect||!t.targets.length)return[];const i="group"===t.kind,s=i?t.targets.filter(t=>"on"===t.state).length:0,n=i?0===s?e.groupAllOff():e.groupCurrent(s,t.targets.length):e.state(t.targets[0]);let o;return o="toggle"===t.nextEffect?e.expectedByHa():i&&"turn-on"===t.nextEffect?e.groupAllOn():i&&"turn-off"===t.nextEffect?e.groupAllOff():e.effect(t.nextEffect),[e.current(n),e.expected(o),...t.skippedTargets.length?[e.unavailable(t.skippedTargets.length)]:[]]}(t,{state:t=>this._toggleConfirmationStateText(t),current:t=>this._t("confirm.current_state",{state:t}),expected:t=>this._t("confirm.expected_state",{state:t}),groupCurrent:(t,e)=>this._t("confirm.group_current",{on:t,total:e}),groupAllOn:()=>this._t("confirm.group_all_on"),groupAllOff:()=>this._t("confirm.group_all_off"),unavailable:t=>this._t("confirm.unavailable_targets",{count:t}),effect:t=>this._t(e[t]),expectedByHa:()=>this._t("confirm.expected_by_ha")})}_toggleHintLines(t){if(!t)return[];const e=t=>this._t(`marker.toggle_effect_${t.replace("-","_")}`),i=t=>this._t(`marker.toggle_skip_${t.replace("-","_")}`);return function(t,e){const i=t.targets[0]||t.skippedTargets[0],s=[];return"group"===t.kind?t.targets.length&&s.push(e.group(t.targets)):i&&s.push(e.single(i)),t.nextEffect&&t.targets.length&&s.push("group"===t.kind?e.groupCurrentNext(t.targets,t.nextEffect):e.currentNext(t.targets[0],t.nextEffect)),t.skippedTargets.length&&s.push(e.skipped(t.skippedTargets)),!t.command&&t.noneReason&&s.push(e.none(t.noneReason)),s}(t,{single:t=>{if("via"in t&&"virtual-light"===t.via)return this._t("marker.virtual_light_target",{name:t.name});const e=t.entityId||("ref"in t?t.ref:""),i=t.name||e;return this._t("marker.toggle_hint_single",{name:i,id:e})},group:t=>this._t("marker.toggle_hint_group",{count:t.length,names:t.map(t=>`${t.name} (${t.entityId})`).join(", ")}),currentNext:(t,i)=>"virtual-light"===t.via?this._t("marker.virtual_light_current",{state:this._t("on"===t.state?"marker.virtual_light_state_on":"marker.virtual_light_state_off"),effect:e(i)}):this._t("marker.toggle_hint_current",{state:this._toggleStateText(t.entityId,t.state),effect:e(i)}),groupCurrentNext:(t,i)=>this._t("marker.toggle_hint_group_current",{on:t.filter(t=>"on"===t.state).length,count:t.length,effect:e(i)}),skipped:t=>this._t("marker.toggle_hint_skipped",{count:t.length,targets:t.map(t=>{const e=t.entityId||t.ref;return`${t.name||e} (${e}: ${i(t.reason)})`}).join(", ")}),none:t=>this._t(`marker.toggle_none_${t.replaceAll("-","_")}`)})}_effectiveStoredTapAction(t,e){return t.tapActionTouched?t.tapAction:bd(t.originalHasTapAction?t.originalTapAction:null,e)}_effectiveMarkerTapAction(t,e=this._markerPreviewDevice(t)){return this._effectiveStoredTapAction(t,e?.primary?.split(".")[0])}_announceToggleDraft(t){const e=this._markerPreviewDevice(t),i=t.tapActionTouched?t:{...t,tapAction:this._effectiveMarkerTapAction(t,e)},s="toggle"===i.tapAction?this._toggleHintLines(this._toggleIntentForDialog(i)).join(" "):"";return{...i,tapHintAnnouncement:s}}_valueBadgeForBinding(t,e){const i={...t,binding:e,valueBadgeEnabled:!1,valueBadgeSource:null,valueBadgeTouched:!0},s=this._markerPreviewDevice(i);if(!s)return{valueBadgeEnabled:!1,valueBadgeSource:null,valueBadgeTouched:!0};const n=[...this._devices.filter(t=>t.id!==s.id),s],o=Wo(this._planHass,s,n),a=jo(this._planHass,s,o);return{valueBadgeEnabled:t.valueBadgeEnabled&&!!a,valueBadgeSource:a,valueBadgeTouched:!0}}_markerSpatialSource(t){const e=this._markerPreviewDevice(t);if(!e)return null;const i={...e,hidden:!1};return po(ho(this._planHass,[...this._devices.filter(t=>t.id!==i.id),i],null,this._virtualLights).filter(t=>t.device.id===i.id))}_markerAutoHasSpatialSource(t){const e={...t,lightRole:"auto",lightRoleTouched:!0},i=this._markerPreviewDevice(e);return!!i&&lo(this._planHass,{...i})}_setMarkerLightRole(t){const e=this._markerDialog;e&&(this._markerDialog={...e,lightRole:t,lightRoleTouched:!0})}_controlRefInfo(t){if(!t.startsWith("marker:"))return{label:this.hass.states[t]?.attributes?.friendly_name||t,sub:t,icon:t.startsWith("light.")?"mdi:lightbulb":"mdi:toggle-switch",warning:!this._planEntityAvailable(t)};const e=t.slice(7),i=this._markers.find(t=>t.id===e),s=this._devices.find(t=>t.id===e);if(!i||i.removed||!0!==i.is_light)return{label:this._t("marker.control_missing_label"),sub:`${this._t("marker.control_broken")} (${t})`,icon:"mdi:alert-outline",warning:!0};const n=this._serverCfg?.spaces.find(t=>t.id===(s?.space||i.space)),o=!!s&&to(s).length>0;return{label:i.name||s?.name||e,sub:[n?.title||s?.space||i.space,i.room_id||s?.area,o?"":this._t("marker.control_passive")].filter(Boolean).join(" · "),icon:i.icon||s?.icon||"mdi:lightbulb-outline",warning:!0===i.hidden||!0===s?.hidden}}_valueBadgeCandidateLabel(t){const e=t.source;if("derived_lqi"===e.kind)return this._t("marker.value_badge_lqi");if("derived_marker_state"===e.kind)return this._t("marker.value_badge_marker_state",{name:t.label});if("entity_state"===e.kind)return this._t("marker.value_badge_state",{name:t.label});const i=this.hass.states[e.entity_id]?.attributes?.friendly_name||this._fullRegistryHass.entities[e.entity_id]?.name||e.entity_id;return this._t(`marker.value_badge_attr_${e.attribute}`,{name:i})}_controlCandidates(t){const e=this._markerDraft(t)?.id||t.devId||"",i=[],s=new Set;for(const t of this._markers){if(t.id===e||t.removed||t.hidden||!0!==t.is_light)continue;if("virtual"!==t.binding&&"active"!==this._bindingStatus(t.binding).kind)continue;const n=this._devices.find(e=>e.id===t.id);if(!n||n.hidden)continue;const o=this._controlRefInfo(`marker:${t.id}`);for(const t of to(n))s.add(t);i.push({value:`marker:${t.id}`,label:o.label,sub:o.sub,icon:o.icon,search:`${o.label} ${o.sub} ${t.id} ${to(n).join(" ")}`.toLowerCase()})}const n=Object.keys(this.hass.states||{}).filter(e=>Ms(e)&&!s.has(e)&&Jn(t.binding,[e],this._bindingEntities(t.binding)).length>0&&this._planEntityAvailable(e)).map(t=>{const e=this._controlRefInfo(t);return{value:t,label:e.label,sub:t,icon:e.icon,search:`${e.label} ${t}`.toLowerCase()}}),o=t.controlsFilter.trim().toLowerCase();return[...i,...n].filter(e=>!t.controls.includes(e.value)&&(!o||e.search.includes(o))).slice(0,12).map(({search:t,...e})=>e)}_addControlRef(t,e){if(e.startsWith("marker:")){const i=this._markerDraft(t)?.id||t.devId||"";if(!i)return void this._showToast(this._t("toast.marker_binding_required"));const s=e.slice(7),n=this._markerDraft(t);if(function(t,e,i){if(!e||e===i)return!0;const s=new Map;for(const e of t)s.set(e.id,(e.controls||[]).filter(t=>"string"==typeof t&&t.startsWith("marker:")).map(t=>t.slice(7)));const n=new Set,o=[i];for(;o.length;){const t=o.pop();if(t===e)return!0;n.has(t)||(n.add(t),o.push(...s.get(t)||[]))}return!1}(n?[...this._markers.filter(t=>t.id!==i),n]:this._markers,i,s))return void this._showToast(this._t("toast.marker_control_cycle"))}this._markerDialog=this._announceToggleDraft({...t,controls:[...t.controls,e],controlsFilter:""})}_setMarkerGlowMode(t){const e=this._markerDialog;if(!e)return;if("auto"===t)return void(this._markerDialog={...e,glowMode:t,glowTouched:!0});const i=this._markerSpatialSource(e),s=xs(i?this._planHass.states[i.eid]:void 0,null,this._fillColors.glow_light.c),n=!e.glowColorDrafted,o="fixed"===t&&!e.glowBrightnessDrafted;this._markerDialog={...e,glowMode:t,glowColor:n?s.c:e.glowColor,glowBrightness:o?Math.max(1,Math.round(100*s.bri)):e.glowBrightness,glowColorDrafted:!0,glowBrightnessDrafted:e.glowBrightnessDrafted||"fixed"===t,glowTouched:!0}}_renderMarkerDialog(){const t=this._markerDialog,e="virtual"===t.bindingMode,i=this._bindingCandidates();this._bindingEntities(t.binding);const s=e?null:this._bindingStatus(t.binding),n=!e&&this._bindingHasHaPage(t.binding),o=this._markerPreviewDevice(t),a=this._effectiveMarkerTapAction(t,o),r=o?cs(this._serverCfg?.spaces.find(t=>t.id===o.space)):null,l=o?this._markerPreviewDevices(o):this._devices,c="toggle"===a&&o?this._toggleIntent(o,l):null,h=this._toggleHintLines(c),d=o?su(this._planHass,o,{liveStates:!1!==this._config?.live_states,showTemperature:!1!==this._config?.show_temperature,showSignal:r?.showLqi??!1!==this._config?.show_signal,designPreview:!0,activityRuntime:this._activityRt.get(o.id),lightDevices:l,registryHass:this._fullRegistryHass,reducedMotion:this._reducedMotion}):null,p=o?Wo(this._planHass,o,l):[],u=o?jo(this._planHass,o,p):null,_=t.valueBadgeTouched?t.valueBadgeEnabled:!!d?.valueBadge,g=t.valueBadgeTouched?t.valueBadgeSource:d?.valueBadge?.source||t.valueBadgeSource,m=t.valueBadgeTouched?t.valueBadgePosition:d?.valueBadge?.position||t.valueBadgePosition,f=Ao(g),v=!!g&&!p.some(t=>t.key===f),y=p.find(t=>t.key===f),b=d?.valueSource?d.valueSource.attribute?`attr:${d.valueSource.eid}:${d.valueSource.attribute}`:`state:${d.valueSource.eid}`:"",w=this._markerAutoHasSpatialSource(t),k=!!o&&function(t,e){return io(t,e).some(t=>!!t.eid)}(this._planHass,{...o}),x=function(t,e,i,s){const n="always"===t||"auto"===t&&e,o=n&&!i;return{sourceExists:n,fromSourceEnabled:n&&i,manualEnabled:n,radiusEnabled:n,passive:o,effectiveMode:o&&"auto"===s?"fixed":s}}(t.lightRole,w,k,t.glowMode),$=!x.sourceExists,S=!x.fromSourceEnabled,M=x.passive,C=x.effectiveMode,D="never"===t.lightRole?this._t("marker.glow_disabled_never"):"auto"!==t.lightRole||w?M?this._t("marker.glow_passive_hint"):this._t("marker.glow_disabled_no_entity"):this._t("marker.glow_disabled_auto"),T=o?to(o):[],P=o&&eo(o)||"",R=!!t.lightEntity&&!T.includes(t.lightEntity),I=o?gd(o):[],A=!!t.toggleEntity&&!I.includes(t.toggleEntity),F="toggle"===a?this._toggleIntentForDialog({...t,toggleEntity:"",toggleEntityTouched:!0}):null,E=F?[...F.targets,...F.skippedTargets].map(t=>t.entityId||("ref"in t?t.ref:"")).filter(Boolean).join(", "):"",z=(()=>{if(e)return null;const s=i.find(e=>e.value===t.binding);if(s)return s.label;const[n,o]=t.binding.split(":");return"device"===n?this._fullRegistryHass.devices[o]?.name_by_user||this._fullRegistryHass.devices[o]?.name||o:this._fullRegistryHass.entities[o]?.name||this.hass.states[o]?.attributes?.friendly_name||o})();return W`this._markerDialog=null}>
@@ -6732,13 +6732,13 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8 - ${"toggle"===r&&(I.length>1||A)?W`
+ ${"toggle"===a&&(I.length>1||A)?W`
${this._help("marker.toggle_entity.help")} @@ -6758,11 +6758,11 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8 ${this._t("marker.toggle_entity_missing",{entity:t.toggleEntity,fallback:E||this._t("marker.toggle_entity_none")})}

`:G}
`:G} - ${"toggle"===r?W`
+ ${"toggle"===a?W`
${h.map(t=>W`
${t}
`)}
${t.tapHintAnnouncement}
`:G} - ${"run"===r?(()=>{const e=t.runFilter.trim().toLowerCase(),i=this._runCandidates().filter(t=>!e||t.label.toLowerCase().includes(e)||t.value.includes(e)),s=t.tapTarget?this._runCandidates().find(e=>e.value===t.tapTarget):null;return W` + ${"run"===a?(()=>{const e=t.runFilter.trim().toLowerCase(),i=this._runCandidates().filter(t=>!e||t.label.toLowerCase().includes(e)||t.value.includes(e)),s=t.tapTarget?this._runCandidates().find(e=>e.value===t.tapTarget):null;return W` ${t.tapTarget&&!s?W`
${this._t("marker.run_target_gone",{id:t.tapTarget})}
`:G} ${this._t("marker.nothing_found")}
`}
`}`})():G} - ${"run"===r||"toggle"===r?W`
- `}}wm.properties={_tabDrag:{state:!0},_hdrH:{state:!0},_booting:{state:!0},_bootFading:{state:!0},_bootSoft:{state:!0},_continuityEpoch:{state:!0},_tapConfirm:{state:!0},hass:{attribute:!1},_config:{state:!0},_space:{state:!0},_layout:{state:!0},_devices:{state:!0},_tip:{state:!0},_hoverRoom:{state:!0},_selId:{state:!0},_toast:{state:!0},_serverCfg:{state:!0},_mode:{state:!0},_tool:{state:!0},_wallDialog:{state:!0},_drawWallField:{state:!0},_activeDraftId:{state:!0},_physicalSel:{state:!0},_physicalDialog:{state:!0},_partitionDeleteDialog:{state:!0},_roomDeleteDialog:{state:!0},_physicalDrag:{state:!0},_physicalRotate:{state:!0},_duplicateColumnId:{state:!0},_rszSel:{state:!0},_rszLive:{state:!0},_opMeasure:{state:!0},_path:{state:!0},_cursorPt:{state:!0},_mergeSel:{state:!0},_openingPreset:{state:!0},_openingDialog:{state:!0},_openingInfo:{state:!0},_mergeDialog:{state:!0},_openWallAnchor:{state:!0},_splitSel:{state:!0},_decorTool:{state:!0},_decorStyle:{state:!0},_decorDraft:{state:!0},_decorSel:{state:!0},_decorEraseConfirm:{state:!0},_decorTextDialog:{state:!0},_decorShapeDialog:{state:!0},_backdropDialog:{state:!0},_furnPalette:{state:!0},_bdDrag:{state:!0},_dtBox:{state:!0},_dtDrag:{state:!0},_kioskDialog:{state:!0},_vacFit:{state:!0},_vacAllCamerasFor:{state:!0},_vacCalConfirm:{state:!0},_kioskDots:{state:!0},_areaSel:{state:!0},_nameSel:{state:!0},_roomDialog:{state:!0},_roomEditId:{state:!0},_roomFill:{state:!0},_roomCustomFill:{state:!0},_roomTempSrc:{state:!0},_roomHumSrc:{state:!0},_roomSrcOpen:{state:!0},_roomSrcFilter:{state:!0},_roomNameScale:{state:!0},_roomLabelScale:{state:!0},_spaceDialog:{state:!0},_infoCard:{state:!0},_rulesDialog:{state:!0},_settingsDialog:{state:!0},_alignDialog:{state:!0},_backupExportDialog:{state:!0},_backupImportDialog:{state:!0},_importDialog:{state:!0},_markerDialog:{state:!0},_zoom:{state:!0},_view:{state:!0}},wm.ZOOM_MAX=8,wm.ZOOM_MIN=1/3,wm.styles=[Kt,Iu],customElements.get("houseplan-card")||customElements.define("houseplan-card",wm),window.customCards=window.customCards||[],window.customCards.find(t=>"houseplan-card"===t.type)||window.customCards.push({type:"houseplan-card",name:"House Plan Card",description:"Interactive house plan: spaces, rooms and devices with live states and drag layout."}),console.info(`%c HOUSEPLAN-CARD %c v${Gg} `,"background:#3ea6ff;color:#04121f;font-weight:700",""); + `}}km.properties={_tabDrag:{state:!0},_hdrH:{state:!0},_booting:{state:!0},_bootFading:{state:!0},_bootSoft:{state:!0},_continuityEpoch:{state:!0},_tapConfirm:{state:!0},hass:{attribute:!1},_config:{state:!0},_space:{state:!0},_layout:{state:!0},_devices:{state:!0},_tip:{state:!0},_hoverRoom:{state:!0},_selId:{state:!0},_toast:{state:!0},_serverCfg:{state:!0},_mode:{state:!0},_tool:{state:!0},_wallDialog:{state:!0},_drawWallField:{state:!0},_activeDraftId:{state:!0},_physicalSel:{state:!0},_physicalDialog:{state:!0},_partitionDeleteDialog:{state:!0},_roomDeleteDialog:{state:!0},_physicalDrag:{state:!0},_physicalRotate:{state:!0},_duplicateColumnId:{state:!0},_rszSel:{state:!0},_rszLive:{state:!0},_opMeasure:{state:!0},_path:{state:!0},_cursorPt:{state:!0},_mergeSel:{state:!0},_openingPreset:{state:!0},_openingDialog:{state:!0},_openingInfo:{state:!0},_mergeDialog:{state:!0},_openWallAnchor:{state:!0},_splitSel:{state:!0},_decorTool:{state:!0},_decorStyle:{state:!0},_decorDraft:{state:!0},_decorSel:{state:!0},_decorEraseConfirm:{state:!0},_decorTextDialog:{state:!0},_decorShapeDialog:{state:!0},_backdropDialog:{state:!0},_furnPalette:{state:!0},_bdDrag:{state:!0},_dtBox:{state:!0},_dtDrag:{state:!0},_kioskDialog:{state:!0},_vacFit:{state:!0},_vacAllCamerasFor:{state:!0},_vacCalConfirm:{state:!0},_kioskDots:{state:!0},_areaSel:{state:!0},_nameSel:{state:!0},_roomDialog:{state:!0},_roomEditId:{state:!0},_roomFill:{state:!0},_roomCustomFill:{state:!0},_roomTempSrc:{state:!0},_roomHumSrc:{state:!0},_roomSrcOpen:{state:!0},_roomSrcFilter:{state:!0},_roomNameScale:{state:!0},_roomLabelScale:{state:!0},_spaceDialog:{state:!0},_infoCard:{state:!0},_rulesDialog:{state:!0},_settingsDialog:{state:!0},_alignDialog:{state:!0},_backupExportDialog:{state:!0},_backupImportDialog:{state:!0},_importDialog:{state:!0},_markerDialog:{state:!0},_zoom:{state:!0},_view:{state:!0}},km.ZOOM_MAX=8,km.ZOOM_MIN=1/3,km.styles=[Kt,Au],customElements.get("houseplan-card")||customElements.define("houseplan-card",km),window.customCards=window.customCards||[],window.customCards.find(t=>"houseplan-card"===t.type)||window.customCards.push({type:"houseplan-card",name:"House Plan Card",description:"Interactive house plan: spaces, rooms and devices with live states and drag layout."}),console.info(`%c HOUSEPLAN-CARD %c v${Vg} `,"background:#3ea6ff;color:#04121f;font-weight:700",""); diff --git a/dist/houseplan-card.js b/dist/houseplan-card.js index 95824be3..a08e73f8 100755 --- a/dist/houseplan-card.js +++ b/dist/houseplan-card.js @@ -1,4 +1,4 @@ -globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8921aeec392e69d7c511f35bace06";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)},r=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:a,defineProperty:l,getOwnPropertyDescriptor:c,getOwnPropertyNames:h,getOwnPropertySymbols:d,getPrototypeOf:p}=Object,u=globalThis,_=u.trustedTypes,g=_?_.emptyScript:"",m=u.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)=>!a(t,e),b={attribute:!0,type:String,converter:v,reflect:!1,useDefault:!1,hasChanged:y};Symbol.metadata??=Symbol("metadata"),u.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=p(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(r(t))}else void 0!==t&&e.push(r(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}),(u.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?"":"",r=E;for(let e=0;e"===l[0]?(r=n??E,c=-1):void 0===l[1]?c=-2:(c=r.lastIndex-l[2].length,a=l[1],r=void 0===l[3]?N:'"'===l[3]?L:H):r===L||r===H?r=N:r===z||r===O?r=E:(r=N,n=void 0);const d=r===N&&t[e+1].startsWith("/>")?" ":"";o+=r===E?i+T:c>=0?(s.push(a),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 r=t.length-1,a=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())&&a.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 r,a;for(t=n[0],r=0;r{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 pt=2,ut=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=ut(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}=rt,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,r=o!==t;if(r){let e;i._$AQ?.(t),i._$AM=t,void 0!==i._$AP&&(e=t._$AU)!==o._$AU&&i._$AP(e)}if(e!==n||r){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=ut(class extends _t{constructor(t){if(super(t),t.type!==pt)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 r=0;for(const e of t)n[r]=s?s(e,r):r,o[r]=i(e,r),r++;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:r}=this.dt(e,i,s);if(!Array.isArray(n))return this.ut=r,o;const a=this.ut??=[],l=[];let c,h,d=0,p=n.length-1,u=0,_=o.length-1;for(;d<=p&&u<=_;)if(null===n[d])d++;else if(null===n[p])p--;else if(a[d]===r[u])l[u]=wt(n[d],o[u]),d++,u++;else if(a[p]===r[_])l[_]=wt(n[p],o[_]),p--,_--;else if(a[d]===r[_])l[_]=wt(n[d],o[_]),bt(t,l[_+1],n[d]),d++,_--;else if(a[p]===r[u])l[u]=wt(n[p],o[u]),bt(t,n[d],n[p]),p--,u++;else if(void 0===c&&(c=St(r,u,_),h=St(a,d,p)),c.has(a[d]))if(c.has(a[p])){const e=h.get(r[u]),i=void 0!==e?n[e]:null;if(null===i){const e=bt(t,n[d]);wt(e,o[u]),l[u]=e}else l[u]=wt(i,o[u]),bt(t,n[d],i),n[e]=null;u++}else $t(n[p]),p--;else $t(n[d]),d++;for(;u<=_;){const e=bt(t,l[_+1]);wt(e,o[u]),l[u++]=e}for(;d<=p;){const t=n[d++];null!==t&&$t(t)}return this.ut=r,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__="9332b8278ae9e2f3a2e9ab4f07e3bf1b56fe0cb818a0a1c67d41e365ad74da43";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:p}=Object,u=globalThis,_=u.trustedTypes,g=_?_.emptyScript:"",m=u.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"),u.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=p(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}),(u.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 pt=2,ut=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=ut(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=ut(class extends _t{constructor(t){if(super(t),t.type!==pt)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,p=n.length-1,u=0,_=o.length-1;for(;d<=p&&u<=_;)if(null===n[d])d++;else if(null===n[p])p--;else if(r[d]===a[u])l[u]=wt(n[d],o[u]),d++,u++;else if(r[p]===a[_])l[_]=wt(n[p],o[_]),p--,_--;else if(r[d]===a[_])l[_]=wt(n[d],o[_]),bt(t,l[_+1],n[d]),d++,_--;else if(r[p]===a[u])l[u]=wt(n[p],o[u]),bt(t,n[d],n[p]),p--,u++;else if(void 0===c&&(c=St(a,u,_),h=St(r,d,p)),c.has(r[d]))if(c.has(r[p])){const e=h.get(a[u]),i=void 0!==e?n[e]:null;if(null===i){const e=bt(t,n[d]);wt(e,o[u]),l[u]=e}else l[u]=wt(i,o[u]),bt(t,n[d],i),n[e]=null;u++}else $t(n[p]),p--;else $t(n[d]),d++;for(;u<=_;){const e=bt(t,l[_+1]);wt(e,o[u]),l[u++]=e}for(;d<=p;){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`"number"==typeof t&&Number.isFinite(t)))return null;const[i,s,n]=e.map(t=>Math.round(Math.min(255,Math.max(0,t))));return`rgb(${i}, ${s}, ${n})`}const Et=(t,e,i)=>Math.min(i,Math.max(e,Number.isFinite(t)?t:e));function zt(t){return Number.isFinite(t)?(t%360+360)%360:0}function Ot(t){if("string"!=typeof t)return null;const e=t.trim().replace(/^#/,""),i=/^[0-9a-fA-F]{3}$/.test(e)?e.split("").map(t=>`${t}${t}`).join(""):e;return/^[0-9a-fA-F]{6}$/.test(i)?`#${i.toLowerCase()}`:null}function Nt(t){const e=Ot(t);return e?{r:Number.parseInt(e.slice(1,3),16),g:Number.parseInt(e.slice(3,5),16),b:Number.parseInt(e.slice(5,7),16)}:null}function Ht(t){const e=Et(t.r,0,255)/255,i=Et(t.g,0,255)/255,s=Et(t.b,0,255)/255,n=Math.max(e,i,s),o=n-Math.min(e,i,s);let r=0;return o>0&&(r=n===e?(i-s)/o%6*60:n===i?60*((s-e)/o+2):60*((e-i)/o+4)),{h:zt(r),s:0===n?0:o/n*100,v:100*n}}function Lt(t){return function(t){const e=t=>Math.round(Et(t,0,255)).toString(16).padStart(2,"0");return`#${e(t.r)}${e(t.g)}${e(t.b)}`}(function(t){const e=zt(t.h),i=Et(t.s,0,100)/100,s=Et(t.v,0,100)/100,n=s*i,o=n*(1-Math.abs(e/60%2-1)),r=s-n;let a;return a=e<60?[n,o,0]:e<120?[o,n,0]:e<180?[0,n,o]:e<240?[0,o,n]:e<300?[o,0,n]:[n,0,o],{r:Math.round(255*(a[0]+r)),g:Math.round(255*(a[1]+r)),b:Math.round(255*(a[2]+r))}}(t))}function Bt(t){const e=t.visualViewport;return e&&Number.isFinite(e.width)&&Number.isFinite(e.height)?{left:Number(e.offsetLeft)||0,top:Number(e.offsetTop)||0,width:Math.max(0,Number(e.width)||0),height:Math.max(0,Number(e.height)||0)}:{left:0,top:0,width:t.innerWidth,height:t.innerHeight}}function qt(t,e,i,s=7,n=8){const o=i.left+n,r=i.top+n,a=Math.max(o,i.left+i.width-n),l=Math.max(r,i.top+i.height-n),c=Math.max(0,a-o),h=Math.max(0,l-r),d=Math.min(Math.max(0,e.width),c),p=Math.min(Math.max(0,e.height),h);let u=t.left;u+d>a&&(u=t.right-d),u=Math.min(Math.max(o,u),Math.max(o,a-d));const _=t.bottom+s,g=t.top-s-p;let m="bottom",f=_;return _+p>l&&g>=r?(m="top",f=Math.min(Math.max(r,g),Math.max(r,l-p))):f=Math.min(Math.max(r,_),Math.max(r,l-p)),{left:Math.round(u),top:Math.round(f),side:m,maxWidth:Math.round(c),maxHeight:Math.round(h)}}class Wt{constructor(t,e,i){this.owner=t,this.name=e,this.keydown=i,this.host=null,this.root=null}window(){return this.owner.ownerDocument.defaultView}dialog(){return this.owner.closest("hp-dialog")}usesPopover(t=!1){const e=this.window();return!t&&!!e&&function(t){const e=t.HTMLElement?.prototype;return"function"==typeof e?.showPopover&&"function"==typeof e?.hidePopover}(e)}get hasFallback(){return!!this.host}containsPath(t){return t.includes(this.owner)||!!this.host&&t.includes(this.host)}ownsActiveElement(){let t=this.owner.ownerDocument.activeElement;for(;t?.shadowRoot?.activeElement;)t=t.shadowRoot.activeElement;return!(!t||t!==this.owner&&!this.owner.shadowRoot?.contains(t)&&!this.root?.contains(t))}renderFallback(t,e){const i=this.ensureFallback();return i?(lt(W`${t}`,i),i):null}surface(t,e){return e?this.owner.shadowRoot?.querySelector(t)||null:this.root?.querySelector(t)||null}destroy(){this.root&<(G,this.root),this.host?.remove(),this.host=null,this.root=null}ensureFallback(){if(this.root?.isConnected)return this.root;const t=this.dialog()?.overlayPortal()||this.owner.ownerDocument.body;if(!t)return null;const e=this.owner.ownerDocument.createElement("div");return e.dataset.hpOverlay=this.name,e.style.display="contents",this.keydown&&e.addEventListener("keydown",this.keydown,!0),t.append(e),this.host=e,this.root=e.attachShadow({mode:"open"}),this.root}}const jt={title:"Color picker",hue:"Hue",saturation:"Saturation",value:"Brightness",hex:"Hex color",invalidHex:"Enter a 3- or 6-digit hex color"};class Ut extends ht{constructor(){super(...arguments),this.label="",this.opacityLabel="Opacity",this.color="#607d8b",this.opacity=1,this.disabled=!1,this.showOpacity=!0,this.pickerLabels=jt,this._open=!1,this._pickerRaf=0,this._emitRaf=0,this._forceFallback=!1,this._overlayDispose=null,this._hue=0,this._saturation=0,this._value=0,this._hexDraft="#607d8b",this._hexInvalid=!1,this._lastValidColor="#607d8b",this._activePointerId=null,this._outsidePointerDown=t=>{if(!this._open)return;const e=t.composedPath();this._floating.containsPath(e)||this._closePicker(!1,"outside")},this._keyDown=t=>{this._open&&"Escape"===t.key&&(t.preventDefault(),t.stopImmediatePropagation(),this._closePicker(this._floating.ownsActiveElement(),"escape"))},this._floating=new Wt(this,"color-opacity",this._keyDown),this._queuePickerPosition=()=>{if(!this._open)return;this._pickerRaf&&cancelAnimationFrame(this._pickerRaf);const t=this._window();t&&(this._pickerRaf=t.requestAnimationFrame(()=>{this._pickerRaf=0,this._positionPicker()||this._closePicker()}))}}connectedCallback(){super.connectedCallback(),this._syncFromColor(this.color,!1),this.ownerDocument.addEventListener("pointerdown",this._outsidePointerDown,!0),this.ownerDocument.addEventListener("scroll",this._queuePickerPosition,!0);const t=this.ownerDocument.defaultView;t?.addEventListener("resize",this._queuePickerPosition),t?.addEventListener("orientationchange",this._queuePickerPosition),t?.visualViewport?.addEventListener("resize",this._queuePickerPosition),t?.visualViewport?.addEventListener("scroll",this._queuePickerPosition),this.addEventListener("keydown",this._keyDown,!0)}disconnectedCallback(){this.ownerDocument.removeEventListener("pointerdown",this._outsidePointerDown,!0),this.ownerDocument.removeEventListener("scroll",this._queuePickerPosition,!0);const t=this.ownerDocument.defaultView;t?.removeEventListener("resize",this._queuePickerPosition),t?.removeEventListener("orientationchange",this._queuePickerPosition),t?.visualViewport?.removeEventListener("resize",this._queuePickerPosition),t?.visualViewport?.removeEventListener("scroll",this._queuePickerPosition),this.removeEventListener("keydown",this._keyDown,!0),this._pickerRaf&&cancelAnimationFrame(this._pickerRaf),this._emitRaf&&cancelAnimationFrame(this._emitRaf),this._pickerRaf=0,this._emitRaf=0,this._closePicker(!1,"disconnect"),super.disconnectedCallback()}updated(t){if(t.has("color")){const t=Ot(this.color);t&&t!==this._lastValidColor&&this._syncFromColor(t,this._open)}this.disabled&&this._open?this._closePicker():this._open&&(this._supportsPopover()||this._renderFallback(),(t.has("color")||t.has("opacity")||t.has("showOpacity")||t.has("label")||t.has("opacityLabel")||t.has("pickerLabels"))&&this._queuePickerPosition())}_window(){return this._floating.window()}_supportsPopover(){return this._floating.usesPopover(this._forceFallback)}_dialog(){return this._floating.dialog()}async _toggle(){this.disabled||(this._open?this._closePicker():(this._forceFallback=!1,this._syncFromColor(this.color,!1),this._hexInvalid=!1,this._activePointerId=null,this._open=!0,await this.updateComplete,this._open&&(this._supportsPopover()||this._renderFallback(),this._positionPicker()?this._overlayDispose=this._dialog()?.registerOverlay({owner:this,group:"transient",close:t=>this._closePicker("escape"===t&&this._floating.ownsActiveElement(),t)})||null:this._closePicker())))}_closePicker(t=!1,e="exclusive"){if(!this._open&&!this._floating.hasFallback)return;const i=this._overlayDispose;this._overlayDispose=null,i?.();const s=this.renderRoot.querySelector(".picker");if(s?.hidePopover)try{s.matches(":popover-open")&&s.hidePopover()}catch{}this._open=!1,this._cancelQueuedEmit(),this._activePointerId=null,this._floating.destroy(),t&&this.updateComplete.then(()=>this.renderRoot.querySelector(".trigger")?.focus())}_surface(){return this._floating.surface(".picker",this._supportsPopover())}_renderFallback(){const t=Ut.styles.cssText;this._floating.renderFallback(this._pickerTemplate(!1),t)}_positionPicker(){if(!this._open)return!1;const t=this._window(),e=this.renderRoot.querySelector(".trigger");let i=this._surface();if(!t||!e?.isConnected||!i?.isConnected)return!1;const s=Bt(t);if(i.style.maxWidth=`${Math.max(0,s.width-16)}px`,i.style.maxHeight=`${Math.max(0,s.height-16)}px`,i.style.visibility="hidden",this._supportsPopover()&&i.showPopover)try{i.matches(":popover-open")||i.showPopover()}catch{if(this._forceFallback=!0,this._renderFallback(),i=this._surface(),!i?.isConnected)return!1;i.style.maxWidth=`${Math.max(0,s.width-16)}px`,i.style.maxHeight=`${Math.max(0,s.height-16)}px`,i.style.visibility="hidden"}const n=e.getBoundingClientRect(),o=i.getBoundingClientRect();if(!(n.width&&n.height&&o.width&&o.height))return!1;const r=qt(n,o,s);return i.style.left=`${r.left}px`,i.style.top=`${r.top}px`,i.dataset.side=r.side,i.style.visibility="",!0}_labels(){const t=this.pickerLabels||jt;return{title:t.title||jt.title,hue:t.hue||jt.hue,saturation:t.saturation||jt.saturation,value:t.value||jt.value,hex:t.hex||jt.hex,invalidHex:t.invalidHex||jt.invalidHex}}_syncFromColor(t,e){const i=Ot(Rt(t,"#607d8b"))||"#607d8b",s=Nt(i);if(!s)return;const n=Ht(s);(!e||n.s>1e-4)&&(this._hue=n.h),this._saturation=n.s,this._value=n.v,this._hexDraft=i,this._hexInvalid=!1,this._lastValidColor=i}_cancelQueuedEmit(t=!1){this._emitRaf&&cancelAnimationFrame(this._emitRaf),this._emitRaf=0,t&&this._syncFromColor(this._lastValidColor,!0)}_queueHsvEmit(){if(this._emitRaf)return;const t=this._window();t?this._emitRaf=t.requestAnimationFrame(()=>{this._emitRaf=0,this._emitHsv()}):this._emitHsv()}_emitHsv(){this._emit(Lt({h:this._hue,s:this._saturation,v:this._value}),this.opacity)}_setHue(t){this._hue=Math.min(359,Math.max(0,Number.isFinite(t)?t:0)),this._emitHsv()}_setSaturation(t){this._saturation=Math.min(100,Math.max(0,Number.isFinite(t)?t:0)),this._emitHsv()}_setValue(t){this._value=Math.min(100,Math.max(0,Number.isFinite(t)?t:0)),this._emitHsv()}_setOpacity(t){this._emit(this._lastValidColor,t)}_shiftRangeKey(t,e,i,s,n){if(!t.shiftKey)return;const o="ArrowRight"===t.key||"ArrowUp"===t.key?10:"ArrowLeft"===t.key||"ArrowDown"===t.key?-10:0;o&&(t.preventDefault(),t.stopPropagation(),n(Math.min(s,Math.max(i,e+o))))}_setSvFromPointer(t,e){const i=t.currentTarget.getBoundingClientRect();i.width&&i.height&&(this._saturation=Math.min(100,Math.max(0,(t.clientX-i.left)/i.width*100)),this._value=Math.min(100,Math.max(0,100*(1-(t.clientY-i.top)/i.height))),e?(this._cancelQueuedEmit(),this._emitHsv()):this._queueHsvEmit())}_svPointerDown(t){if(t.preventDefault(),t.stopPropagation(),null===this._activePointerId){this._activePointerId=t.pointerId;try{t.currentTarget.setPointerCapture(t.pointerId)}catch{}this._setSvFromPointer(t,!0)}}_svPointerMove(t){t.pointerId===this._activePointerId&&(t.preventDefault(),t.stopPropagation(),this._setSvFromPointer(t,!1))}_svPointerUp(t){if(t.pointerId===this._activePointerId){t.preventDefault(),t.stopPropagation(),this._setSvFromPointer(t,!0),this._activePointerId=null;try{t.currentTarget.releasePointerCapture(t.pointerId)}catch{}}}_svPointerCancel(t){t.pointerId===this._activePointerId&&(t.preventDefault(),t.stopPropagation(),this._activePointerId=null,this._cancelQueuedEmit(!0))}_svLostPointerCapture(t){t.pointerId===this._activePointerId&&(this._activePointerId=null,this._cancelQueuedEmit(!0))}_hexInput(t){const e=t.target.value;this._hexDraft=e,this._hexInvalid=!1;const i=Ot(e),s=i?Nt(i):null;if(!i||!s)return;const n=Ht(s);n.s>1e-4&&(this._hue=n.h),this._saturation=n.s,this._value=n.v,this._emit(i,this.opacity,!0)}_commitHex(){const t=Ot(this._hexDraft);if(!t)return this._hexDraft=this._lastValidColor,void(this._hexInvalid=!0);this._hexDraft=t,this._hexInvalid=!1,t!==this._lastValidColor&&this._emit(t,this.opacity)}_hexKeyDown(t){"Enter"===t.key&&(t.preventDefault(),t.stopPropagation(),this._commitHex())}_emit(t,e,i=!1){const s=Ot(t)||this._lastValidColor,n=Number.isFinite(e)?e:Number(this.opacity)||0,o=Math.min(1,Math.max(0,n));this.color=s,this.opacity=o,this._lastValidColor=s,i||(this._hexDraft=s),this._hexInvalid=!1,this.dispatchEvent(new CustomEvent("hp-color-opacity-change",{detail:{color:s,opacity:o},bubbles:!0,composed:!0}))}_pickerTemplate(t){const e=Math.round(100*Math.min(1,Math.max(0,Number(this.opacity)||0))),i=Lt({h:this._hue,s:this._saturation,v:this._value}),s=Lt({h:this._hue,s:100,v:100}),n=this._labels(),o=Math.round(this._hue),r=Math.round(this._saturation),a=Math.round(this._value);return W` + `,customElements.get("hp-dialog")||customElements.define("hp-dialog",Tt);const Pt=/^#[0-9a-fA-F]{6}$/;function Rt(t,e){return"string"==typeof t&&Pt.test(t)?t:e}const It="(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])",At=new RegExp(`^rgb\\(${It}, ${It}, ${It}\\)$`);function Ft(t){if(!Array.isArray(t)||t.length<3)return null;const e=t.slice(0,3);if(!e.every(t=>"number"==typeof t&&Number.isFinite(t)))return null;const[i,s,n]=e.map(t=>Math.round(Math.min(255,Math.max(0,t))));return`rgb(${i}, ${s}, ${n})`}const Et=(t,e,i)=>Math.min(i,Math.max(e,Number.isFinite(t)?t:e));function zt(t){return Number.isFinite(t)?(t%360+360)%360:0}function Ot(t){if("string"!=typeof t)return null;const e=t.trim().replace(/^#/,""),i=/^[0-9a-fA-F]{3}$/.test(e)?e.split("").map(t=>`${t}${t}`).join(""):e;return/^[0-9a-fA-F]{6}$/.test(i)?`#${i.toLowerCase()}`:null}function Nt(t){const e=Ot(t);return e?{r:Number.parseInt(e.slice(1,3),16),g:Number.parseInt(e.slice(3,5),16),b:Number.parseInt(e.slice(5,7),16)}:null}function Ht(t){const e=Et(t.r,0,255)/255,i=Et(t.g,0,255)/255,s=Et(t.b,0,255)/255,n=Math.max(e,i,s),o=n-Math.min(e,i,s);let a=0;return o>0&&(a=n===e?(i-s)/o%6*60:n===i?60*((s-e)/o+2):60*((e-i)/o+4)),{h:zt(a),s:0===n?0:o/n*100,v:100*n}}function Lt(t){return function(t){const e=t=>Math.round(Et(t,0,255)).toString(16).padStart(2,"0");return`#${e(t.r)}${e(t.g)}${e(t.b)}`}(function(t){const e=zt(t.h),i=Et(t.s,0,100)/100,s=Et(t.v,0,100)/100,n=s*i,o=n*(1-Math.abs(e/60%2-1)),a=s-n;let r;return r=e<60?[n,o,0]:e<120?[o,n,0]:e<180?[0,n,o]:e<240?[0,o,n]:e<300?[o,0,n]:[n,0,o],{r:Math.round(255*(r[0]+a)),g:Math.round(255*(r[1]+a)),b:Math.round(255*(r[2]+a))}}(t))}function Bt(t){const e=t.visualViewport;return e&&Number.isFinite(e.width)&&Number.isFinite(e.height)?{left:Number(e.offsetLeft)||0,top:Number(e.offsetTop)||0,width:Math.max(0,Number(e.width)||0),height:Math.max(0,Number(e.height)||0)}:{left:0,top:0,width:t.innerWidth,height:t.innerHeight}}function qt(t,e,i,s=7,n=8){const o=i.left+n,a=i.top+n,r=Math.max(o,i.left+i.width-n),l=Math.max(a,i.top+i.height-n),c=Math.max(0,r-o),h=Math.max(0,l-a),d=Math.min(Math.max(0,e.width),c),p=Math.min(Math.max(0,e.height),h);let u=t.left;u+d>r&&(u=t.right-d),u=Math.min(Math.max(o,u),Math.max(o,r-d));const _=t.bottom+s,g=t.top-s-p;let m="bottom",f=_;return _+p>l&&g>=a?(m="top",f=Math.min(Math.max(a,g),Math.max(a,l-p))):f=Math.min(Math.max(a,_),Math.max(a,l-p)),{left:Math.round(u),top:Math.round(f),side:m,maxWidth:Math.round(c),maxHeight:Math.round(h)}}class Wt{constructor(t,e,i){this.owner=t,this.name=e,this.keydown=i,this.host=null,this.root=null}window(){return this.owner.ownerDocument.defaultView}dialog(){return this.owner.closest("hp-dialog")}usesPopover(t=!1){const e=this.window();return!t&&!!e&&function(t){const e=t.HTMLElement?.prototype;return"function"==typeof e?.showPopover&&"function"==typeof e?.hidePopover}(e)}get hasFallback(){return!!this.host}containsPath(t){return t.includes(this.owner)||!!this.host&&t.includes(this.host)}ownsActiveElement(){let t=this.owner.ownerDocument.activeElement;for(;t?.shadowRoot?.activeElement;)t=t.shadowRoot.activeElement;return!(!t||t!==this.owner&&!this.owner.shadowRoot?.contains(t)&&!this.root?.contains(t))}renderFallback(t,e){const i=this.ensureFallback();return i?(lt(W`${t}`,i),i):null}surface(t,e){return e?this.owner.shadowRoot?.querySelector(t)||null:this.root?.querySelector(t)||null}destroy(){this.root&<(G,this.root),this.host?.remove(),this.host=null,this.root=null}ensureFallback(){if(this.root?.isConnected)return this.root;const t=this.dialog()?.overlayPortal()||this.owner.ownerDocument.body;if(!t)return null;const e=this.owner.ownerDocument.createElement("div");return e.dataset.hpOverlay=this.name,e.style.display="contents",this.keydown&&e.addEventListener("keydown",this.keydown,!0),t.append(e),this.host=e,this.root=e.attachShadow({mode:"open"}),this.root}}const jt={title:"Color picker",hue:"Hue",saturation:"Saturation",value:"Brightness",hex:"Hex color",invalidHex:"Enter a 3- or 6-digit hex color"};class Ut extends ht{constructor(){super(...arguments),this.label="",this.opacityLabel="Opacity",this.color="#607d8b",this.opacity=1,this.disabled=!1,this.showOpacity=!0,this.pickerLabels=jt,this._open=!1,this._pickerRaf=0,this._emitRaf=0,this._forceFallback=!1,this._overlayDispose=null,this._hue=0,this._saturation=0,this._value=0,this._hexDraft="#607d8b",this._hexInvalid=!1,this._lastValidColor="#607d8b",this._activePointerId=null,this._outsidePointerDown=t=>{if(!this._open)return;const e=t.composedPath();this._floating.containsPath(e)||this._closePicker(!1,"outside")},this._keyDown=t=>{this._open&&"Escape"===t.key&&(t.preventDefault(),t.stopImmediatePropagation(),this._closePicker(this._floating.ownsActiveElement(),"escape"))},this._floating=new Wt(this,"color-opacity",this._keyDown),this._queuePickerPosition=()=>{if(!this._open)return;this._pickerRaf&&cancelAnimationFrame(this._pickerRaf);const t=this._window();t&&(this._pickerRaf=t.requestAnimationFrame(()=>{this._pickerRaf=0,this._positionPicker()||this._closePicker()}))}}connectedCallback(){super.connectedCallback(),this._syncFromColor(this.color,!1),this.ownerDocument.addEventListener("pointerdown",this._outsidePointerDown,!0),this.ownerDocument.addEventListener("scroll",this._queuePickerPosition,!0);const t=this.ownerDocument.defaultView;t?.addEventListener("resize",this._queuePickerPosition),t?.addEventListener("orientationchange",this._queuePickerPosition),t?.visualViewport?.addEventListener("resize",this._queuePickerPosition),t?.visualViewport?.addEventListener("scroll",this._queuePickerPosition),this.addEventListener("keydown",this._keyDown,!0)}disconnectedCallback(){this.ownerDocument.removeEventListener("pointerdown",this._outsidePointerDown,!0),this.ownerDocument.removeEventListener("scroll",this._queuePickerPosition,!0);const t=this.ownerDocument.defaultView;t?.removeEventListener("resize",this._queuePickerPosition),t?.removeEventListener("orientationchange",this._queuePickerPosition),t?.visualViewport?.removeEventListener("resize",this._queuePickerPosition),t?.visualViewport?.removeEventListener("scroll",this._queuePickerPosition),this.removeEventListener("keydown",this._keyDown,!0),this._pickerRaf&&cancelAnimationFrame(this._pickerRaf),this._emitRaf&&cancelAnimationFrame(this._emitRaf),this._pickerRaf=0,this._emitRaf=0,this._closePicker(!1,"disconnect"),super.disconnectedCallback()}updated(t){if(t.has("color")){const t=Ot(this.color);t&&t!==this._lastValidColor&&this._syncFromColor(t,this._open)}this.disabled&&this._open?this._closePicker():this._open&&(this._supportsPopover()||this._renderFallback(),(t.has("color")||t.has("opacity")||t.has("showOpacity")||t.has("label")||t.has("opacityLabel")||t.has("pickerLabels"))&&this._queuePickerPosition())}_window(){return this._floating.window()}_supportsPopover(){return this._floating.usesPopover(this._forceFallback)}_dialog(){return this._floating.dialog()}async _toggle(){this.disabled||(this._open?this._closePicker():(this._forceFallback=!1,this._syncFromColor(this.color,!1),this._hexInvalid=!1,this._activePointerId=null,this._open=!0,await this.updateComplete,this._open&&(this._supportsPopover()||this._renderFallback(),this._positionPicker()?this._overlayDispose=this._dialog()?.registerOverlay({owner:this,group:"transient",close:t=>this._closePicker("escape"===t&&this._floating.ownsActiveElement(),t)})||null:this._closePicker())))}_closePicker(t=!1,e="exclusive"){if(!this._open&&!this._floating.hasFallback)return;const i=this._overlayDispose;this._overlayDispose=null,i?.();const s=this.renderRoot.querySelector(".picker");if(s?.hidePopover)try{s.matches(":popover-open")&&s.hidePopover()}catch{}this._open=!1,this._cancelQueuedEmit(),this._activePointerId=null,this._floating.destroy(),t&&this.updateComplete.then(()=>this.renderRoot.querySelector(".trigger")?.focus())}_surface(){return this._floating.surface(".picker",this._supportsPopover())}_renderFallback(){const t=Ut.styles.cssText;this._floating.renderFallback(this._pickerTemplate(!1),t)}_positionPicker(){if(!this._open)return!1;const t=this._window(),e=this.renderRoot.querySelector(".trigger");let i=this._surface();if(!t||!e?.isConnected||!i?.isConnected)return!1;const s=Bt(t);if(i.style.maxWidth=`${Math.max(0,s.width-16)}px`,i.style.maxHeight=`${Math.max(0,s.height-16)}px`,i.style.visibility="hidden",this._supportsPopover()&&i.showPopover)try{i.matches(":popover-open")||i.showPopover()}catch{if(this._forceFallback=!0,this._renderFallback(),i=this._surface(),!i?.isConnected)return!1;i.style.maxWidth=`${Math.max(0,s.width-16)}px`,i.style.maxHeight=`${Math.max(0,s.height-16)}px`,i.style.visibility="hidden"}const n=e.getBoundingClientRect(),o=i.getBoundingClientRect();if(!(n.width&&n.height&&o.width&&o.height))return!1;const a=qt(n,o,s);return i.style.left=`${a.left}px`,i.style.top=`${a.top}px`,i.dataset.side=a.side,i.style.visibility="",!0}_labels(){const t=this.pickerLabels||jt;return{title:t.title||jt.title,hue:t.hue||jt.hue,saturation:t.saturation||jt.saturation,value:t.value||jt.value,hex:t.hex||jt.hex,invalidHex:t.invalidHex||jt.invalidHex}}_syncFromColor(t,e){const i=Ot(Rt(t,"#607d8b"))||"#607d8b",s=Nt(i);if(!s)return;const n=Ht(s);(!e||n.s>1e-4)&&(this._hue=n.h),this._saturation=n.s,this._value=n.v,this._hexDraft=i,this._hexInvalid=!1,this._lastValidColor=i}_cancelQueuedEmit(t=!1){this._emitRaf&&cancelAnimationFrame(this._emitRaf),this._emitRaf=0,t&&this._syncFromColor(this._lastValidColor,!0)}_queueHsvEmit(){if(this._emitRaf)return;const t=this._window();t?this._emitRaf=t.requestAnimationFrame(()=>{this._emitRaf=0,this._emitHsv()}):this._emitHsv()}_emitHsv(){this._emit(Lt({h:this._hue,s:this._saturation,v:this._value}),this.opacity)}_setHue(t){this._hue=Math.min(359,Math.max(0,Number.isFinite(t)?t:0)),this._emitHsv()}_setSaturation(t){this._saturation=Math.min(100,Math.max(0,Number.isFinite(t)?t:0)),this._emitHsv()}_setValue(t){this._value=Math.min(100,Math.max(0,Number.isFinite(t)?t:0)),this._emitHsv()}_setOpacity(t){this._emit(this._lastValidColor,t)}_shiftRangeKey(t,e,i,s,n){if(!t.shiftKey)return;const o="ArrowRight"===t.key||"ArrowUp"===t.key?10:"ArrowLeft"===t.key||"ArrowDown"===t.key?-10:0;o&&(t.preventDefault(),t.stopPropagation(),n(Math.min(s,Math.max(i,e+o))))}_setSvFromPointer(t,e){const i=t.currentTarget.getBoundingClientRect();i.width&&i.height&&(this._saturation=Math.min(100,Math.max(0,(t.clientX-i.left)/i.width*100)),this._value=Math.min(100,Math.max(0,100*(1-(t.clientY-i.top)/i.height))),e?(this._cancelQueuedEmit(),this._emitHsv()):this._queueHsvEmit())}_svPointerDown(t){if(t.preventDefault(),t.stopPropagation(),null===this._activePointerId){this._activePointerId=t.pointerId;try{t.currentTarget.setPointerCapture(t.pointerId)}catch{}this._setSvFromPointer(t,!0)}}_svPointerMove(t){t.pointerId===this._activePointerId&&(t.preventDefault(),t.stopPropagation(),this._setSvFromPointer(t,!1))}_svPointerUp(t){if(t.pointerId===this._activePointerId){t.preventDefault(),t.stopPropagation(),this._setSvFromPointer(t,!0),this._activePointerId=null;try{t.currentTarget.releasePointerCapture(t.pointerId)}catch{}}}_svPointerCancel(t){t.pointerId===this._activePointerId&&(t.preventDefault(),t.stopPropagation(),this._activePointerId=null,this._cancelQueuedEmit(!0))}_svLostPointerCapture(t){t.pointerId===this._activePointerId&&(this._activePointerId=null,this._cancelQueuedEmit(!0))}_hexInput(t){const e=t.target.value;this._hexDraft=e,this._hexInvalid=!1;const i=Ot(e),s=i?Nt(i):null;if(!i||!s)return;const n=Ht(s);n.s>1e-4&&(this._hue=n.h),this._saturation=n.s,this._value=n.v,this._emit(i,this.opacity,!0)}_commitHex(){const t=Ot(this._hexDraft);if(!t)return this._hexDraft=this._lastValidColor,void(this._hexInvalid=!0);this._hexDraft=t,this._hexInvalid=!1,t!==this._lastValidColor&&this._emit(t,this.opacity)}_hexKeyDown(t){"Enter"===t.key&&(t.preventDefault(),t.stopPropagation(),this._commitHex())}_emit(t,e,i=!1){const s=Ot(t)||this._lastValidColor,n=Number.isFinite(e)?e:Number(this.opacity)||0,o=Math.min(1,Math.max(0,n));this.color=s,this.opacity=o,this._lastValidColor=s,i||(this._hexDraft=s),this._hexInvalid=!1,this.dispatchEvent(new CustomEvent("hp-color-opacity-change",{detail:{color:s,opacity:o},bubbles:!0,composed:!0}))}_pickerTemplate(t){const e=Math.round(100*Math.min(1,Math.max(0,Number(this.opacity)||0))),i=Lt({h:this._hue,s:this._saturation,v:this._value}),s=Lt({h:this._hue,s:100,v:100}),n=this._labels(),o=Math.round(this._hue),a=Math.round(this._saturation),r=Math.round(this._value);return W` `:G} - `}}hr.properties={hass:{attribute:!1},presentation:{attribute:!1},registry:{attribute:!1},deviceName:{attribute:!1}},hr.styles=[Kt,o` + `}}ha.properties={hass:{attribute:!1},presentation:{attribute:!1},registry:{attribute:!1},deviceName:{attribute:!1}},ha.styles=[Kt,o` :host { display: block; min-width: 0; } .devicepreview { margin: 4px 0 14px; @@ -4436,14 +4436,14 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8 .previewstage { min-height: 142px; } .previewfacts > div { grid-template-columns: minmax(0, 1fr); gap: 2px; } } - `],customElements.get("hp-device-preview")||customElements.define("hp-device-preview",hr);const dr=(t,e)=>[t[0]-e[0],t[1]-e[1]],pr=(t,e)=>[t[0]+e[0],t[1]+e[1]],ur=(t,e)=>t[0]*e[0]+t[1]*e[1],_r=t=>Math.hypot(t[0],t[1]);function gr(t){let e=0;for(let i=0;it[1]!=l>t[1]&&t[0]<(a-o)*(t[1]-r)/(l-r)+o&&(i=!i)}return i}([a[0]+r[0]*l,a[1]+r[1]*l],t)&&(r=[-r[0],-r[1]]),r}function vr(t,e,i,s){const n=s||fr(t,e),o=(e+1)%t.length;return t.map((t,s)=>s===e||s===o?[t[0]+n[0]*i,t[1]+n[1]*i]:[...t])}function yr(t,e,i,s){const n=[],o=dr(i,e),r=_r(o);if(rs||h>s)continue;const d=ur(dr(o,e),a),p=ur(dr(l,e),a),u=Math.max(0,Math.min(d,p)),_=Math.min(r,Math.max(d,p));_-u>s&&n.push([[e[0]+a[0]*u,e[1]+a[1]*u],[e[0]+a[0]*_,e[1]+a[1]*_]])}return n}function br(t,e,i,s,n){const o=yr(t,e,i,n);if(!o.length)return null;const r=t=>o.some(([e,i])=>mr(t,e,i)<=n),a=t.length,l=[];for(let o=0;on||f>n)continue;const v=ur(dr(e,c),u),y=ur(dr(i,c),u),b=Math.max(0,Math.min(v,y)),w=Math.min(p,Math.max(v,y));if(!(w-b<=n)){if(b>n&&bn&&w_r(dr(i,t[(s+1)%t.length]))>e);for(let t=0;t<2;t++)i=i.filter((t,s)=>{const n=i[(s-1+i.length)%i.length],o=i[(s+1)%i.length],r=(t[0]-n[0])*(o[1]-n[1])-(t[1]-n[1])*(o[0]-n[0]),a=_r(dr(o,n))||1;return Math.abs(r)/a>e});return i.length>=3?i:t}function kr(t){const e=t.length;if(e<3)return!1;for(let i=0;i(t[0]-n[0])*a[1]-(t[1]-n[1])*a[0],c=t=>(t[0]-n[0])*a[0]+(t[1]-n[1])*a[1],h=i,d=r-i;for(const e of t){const t=Math.abs(l(e));if(t<=i)continue;const n=c(e);n<=h||n>=d||tMath.abs(r+(t-p)/m*(a-r));s=Math.min(s,f(_),f(g))}}return s}function $r(t,e,i){if(Di(t,e,i))return!0;if(Ci(t,e,i)||Ci(e,t,i))return!1;let s=0;try{const i=ni([[...t.map(t=>[t[0],t[1]]),[t[0][0],t[0][1]]]],[[...e.map(t=>[t[0],t[1]]),[e[0][0],e[0][1]]]]);for(const t of i)t?.[0]&&(s+=Pi(t[0]))}catch{return!1}return s>Math.max(1e-7,i*i)}function Sr(t,e,i,s,n){const o=[i.n[0]*s,i.n[1]*s],r={polys:{},openings:{},movedSpans:{}};if(Math.abs(s)<1e-9)return r;for(const e of t){if(e.id===i.roomId){r.polys[e.id]=vr(e.poly,i.edge,s,i.n),r.movedSpans[e.id]=[[pr(i.a,o),pr(i.b,o)]];continue}const t=yr(e.poly,i.a,i.b,n);if(!t.length)continue;const a=br(e.poly,i.a,i.b,o,n);a&&(r.polys[e.id]=a,r.movedSpans[e.id]=t.map(([t,e])=>[pr(t,o),pr(e,o)]))}for(const t of e)mr([t.x,t.y],i.a,i.b)<=n&&(r.openings[t.id]=[t.x+o[0],t.y+o[1]]);return r}function Mr(t,e,i){for(const s of e)for(let e=0;ei)continue;const c=(t.x-n[0])*l[0]+(t.y-n[1])*l[1];if(c-t.length/2>=-i&&c+t.length/2<=a+i)return!0}return!1}function Cr(t,e,i){return t.filter(t=>e.some(e=>{for(let s=0;sa.polys[t.id]||t.poly;for(const e of l){const s=t.find(t=>t.id===e),n=a.polys[e];if(!kr(n))return!1;const l=gr(s.poly),h=gr(n);if(Math.abs(h)t.find(t=>t.id===e).poly),d=t.map(c);for(const t of Cr(e,h,2*r)){const e=a.openings[t.id];if(!Mr(e?{...t,x:e[0],y:e[1]}:t,d,2*r))return!1}return!0}function Tr(t,e,i,s,n,o){const r=t=>[s[0]+(t[0]-s[0])*n,s[1]+(t[1]-s[1])*n],a={poly:t.poly.map(r),openings:{}};for(const s of e){let e=!1;for(let i=0;i{for(let e=0;et.id===i);if(!l)return!1;const c=t.filter(t=>t.id!==i).map(t=>t.poly),h=Tr(l,e,c,s,n,2*a),d=h.poly,p=function(t){const e=function(t){const e=[...t].sort((t,e)=>t[0]-e[0]||t[1]-e[1]);if(e.length<3)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.pop(),n.pop(),s.concat(n)}(t);if(e.length<3)return 0;let i=1/0;for(let t=0;tt.id===i?d:t.poly);for(const t of Cr(e,[l.poly],2*a)){const e=h.openings[t.id];if(!Mr(e?{...t,x:e[0],y:e[1]}:t,u,2*a))return!1}return!0}function Rr(t,e,i){const s=i/e;return Pi(t)*s*s/1e4}function Ir(t,e){return e?`${Math.round(10.7639*t)} ft²`:`${(Math.round(10*t)/10).toFixed(1)} m²`}function Ar(t){const e=t%360;return e<0?e+360:e}function Fr(t,e){const i=function(t,e){return Ar(t+e)}(t,e)*Math.PI/180;return[Math.sin(i),-Math.cos(i)]}const Er=Object.freeze({dawn:Object.freeze({top:"#aabdd1",bottom:"#e8c8b7",horizon:"rgba(255,201,156,.56)",sun:"rgba(255,188,125,.78)",vignette:"rgba(65,72,99,.21)",outlineNear:"rgba(74,57,61,.25)",outlineMid:"rgba(255,238,224,.40)",outlineFar:"rgba(255,224,202,.18)"}),day:Object.freeze({top:"#dce9ef",bottom:"#cbdce3",horizon:"rgba(255,245,220,.45)",sun:"rgba(255,239,190,.72)",vignette:"rgba(65,91,105,.16)",outlineNear:"rgba(45,62,71,.28)",outlineMid:"rgba(255,255,255,.42)",outlineFar:"rgba(255,255,255,.20)"}),dusk:Object.freeze({top:"#48536c",bottom:"#9a7380",horizon:"rgba(242,156,114,.34)",sun:"rgba(255,167,113,.55)",vignette:"rgba(20,26,44,.39)",outlineNear:"rgba(238,219,225,.40)",outlineMid:"rgba(229,207,218,.26)",outlineFar:"rgba(215,190,205,.12)"}),night:Object.freeze({top:"#111a27",bottom:"#1f2f3e",horizon:"rgba(79,120,151,.16)",sun:"rgba(169,208,231,0)",vignette:"rgba(3,8,14,.58)",outlineNear:"rgba(218,238,249,.56)",outlineMid:"rgba(174,215,238,.30)",outlineFar:"rgba(136,194,226,.14)"})}),zr=t=>"number"==typeof t&&Number.isFinite(t),Or=(t,e,i)=>Math.min(i,Math.max(e,t));function Nr(t){return t.elevation<=-6?"night":t.elevation>=6?"day":t.rising?"dawn":"dusk"}function Hr(t){const e=(Math.floor(Number(t)||0)%1440+1440)%1440;return e>=300&&e<480?"dawn":e>=480&&e<1080?"day":e>=1080&&e<1260?"dusk":"night"}function Lr(t){const e=Nr(t),i=t.azimuth*Math.PI/180;return{sunX:50-42*Math.sin(i),sunY:78-Or(t.elevation,0,90)/90*64,sunOpacity:"night"===e?0:Or((t.elevation+6)/12,0,1)}}function Br(t){const e=(Math.floor(Number(t)||0)%1440+1440)%1440;if(e<300||e>=1260)return{sunX:50,sunY:78,sunOpacity:0};const i=(e-300)/960,s=(e-300)/120,n=(1260-e)/120;return{sunX:8+84*i,sunY:78-64*Math.sin(i*Math.PI),sunOpacity:Math.max(.18,Math.min(s,n,1))}}function qr(t,e=new Date){const i=function(t){const e=t?.states?.["sun.sun"]?.attributes;return e&&zr(e.azimuth)&&zr(e.elevation)&&"boolean"==typeof e.rising?{azimuth:Ar(e.azimuth),elevation:e.elevation,rising:e.rising}:null}(t);if(i)return{phase:Nr(i),source:"sun",...Lr(i)};const s="number"==typeof e?e:function(t=new Date){return 60*t.getHours()+t.getMinutes()}(e);return{phase:Hr(s),source:"clock",...Br(s)}}function Wr(t){return`${t.source}|${t.phase}|${t.sunX.toFixed(2)}|${t.sunY.toFixed(2)}|`+t.sunOpacity.toFixed(3)}const jr=[[-90,"#070c14"],[-12,"#070c14"],[-4,"#131a28"],[0,"#4a3527"],[10,"#e8ddcf"],[30,"#ffffff"],[90,"#ffffff"]],Ur=t=>Math.min(1,Math.max(0,t));function Gr(t,e,i=6){const s=t.angle*Math.PI/180,n=[Math.sin(s),-Math.cos(s)],o=s=>{const o=[t.x+n[0]*i*s,t.y+n[1]*i*s];return e.find(t=>t.poly.length>=3&&vi(o,t.poly))||null},r=o(1),a=o(-1);return r&&a?null:r||a?r?{normal:[-n[0],-n[1]],roomId:r.id}:{normal:n,roomId:a.id}:null}function Vr(t,e,i){return i>0&&t[0]*e[0]+t[1]*e[1]>.05}function Kr(t,e,i,s){return[[t[0],t[1]],[e[0],e[1]],[e[0]+i[0]*s,e[1]+i[1]*s],[t[0]+i[0]*s,t[1]+i[1]*s]]}function Yr(t,e){try{const i=ni([[...t.map(t=>[t[0],t[1]]),[t[0][0],t[0][1]]]],[[...e.map(t=>[t[0],t[1]]),[e[0][0],e[0][1]]]]),s=[];for(const t of i){const e=t?.[0];!Array.isArray(e)||e.length<4||s.push(e.slice(0,e.length-1).map(t=>[t[0],t[1]]))}return s}catch{return[]}}function Xr(t,e,i,s,n,o,r){if(!(s>0))return[];const a=Fr(i,n),l=[-a[0],-a[1]],c=function(t){const e=Math.min(90,Math.max(0,t));return.7*(.8+1.7*Math.pow(1-e/90,1.6))}(s),h=[];for(const i of e){if(!(i.length>0))continue;const e=Gr(i,t);if(!e||!Vr(e.normal,a,s))continue;const n=t.find(t=>t.id===e.roomId);if(!n)continue;const d=o&&o[e.roomId]||n.poly,p=i.angle*Math.PI/180,u=i.length/2,_=[-e.normal[0],-e.normal[1]],g=Math.max(0,r?.[i.id]||0),m=i.x+_[0]*g/2,f=i.y+_[1]*g/2,v=Math.cos(p)*u,y=Math.sin(p)*u,b=[m-v,f-y],w=[m+v,f+y],k=c*i.length,x=Yr(Kr(b,w,l,k),d);if(!x.length)continue;const $=l[0]*_[0]+l[1]*_[1];h.push({openingId:i.id,roomId:e.roomId,polys:x,a:b,b:w,dir:l,len:k,normal:_,depth:k*$})}return h}const Jr=t=>"number"==typeof t&&Number.isInteger(t)&&t>=0&&t<=359?t:null;function Zr(t,e){const i=Jr(e?.north_deg);return null!==i?i:Jr(t?.north_deg)}function Qr(t,e){const i=t=>"static"===t||"daynight"===t?t:null;return i(e?.bg_mode)??i(t?.bg_mode)??"static"}function ta(t,e){const i=e?.sun_rays;return"boolean"==typeof i?i:!0===t?.sun_rays}function ea(t){const e=t?.states?.["sun.sun"]?.attributes,i=Number(e?.azimuth),s=Number(e?.elevation);return Number.isFinite(i)&&Number.isFinite(s)?{azimuth:i,elevation:s}:null}const ia=["dawn","day","dusk","night"];function sa(t){if(!t)return"";const e=Er[t.phase];return[`--hp-day-cycle-outline-near:${e.outlineNear}`,`--hp-day-cycle-outline-mid:${e.outlineMid}`,`--hp-day-cycle-outline-far:${e.outlineFar}`].join(";")}function na(t,e=1){if(!t)return G;const i=[`--hp-day-cycle-sun-x:${t.sunX.toFixed(2)}%`,`--hp-day-cycle-sun-y:${t.sunY.toFixed(2)}%`,`--hp-day-cycle-sun-opacity:${t.sunOpacity.toFixed(3)}`,`opacity:${Math.min(1,Math.max(0,e)).toFixed(4)}`].join(";");return W``}houseplanContinuityTrace(){return[...this._continuityHistory,...this._continuity.trace].slice(-80).map(t=>({...t,...t.stage?{stage:[...t.stage]}:{}}))}render(){if(!this._config)return G;const t=this._snap?.config;if(!t)return this._errorCard(la(this._lang,"space_card.loading"));const e=this._config.space,i=this._renderDeviceSnapshot,s=uu({hass:i?.hass||this.hass,cfg:t,layout:this._snap?.layout||{},spaceId:e,iconSize:this._config.icon_size,stageWidth:this._stageWidth,lang:this._lang,displayUrl:t=>this._signer.display(this.hass,t),assetLoaded:this._onAssetLoaded,registry:i?{revision:i.sourceSequence,authoritative:!1,access:"limited",entities:{...i.hass.entities},devices:{...i.hass.devices},lastSuccess:i.capturedAt}:An(this.hass),devices:[...i?.devices||this._devices],presentations:i?.presentations,activityRuntime:this._activityRuntime,reducedMotion:this._reducedMotion,virtualLights:this._snap?.virtualLights,liveStates:!1!==this._config.live_states,showTemperature:!1!==this._config.show_temperature,showSignal:!1!==this._config.show_signal,inert:this._continuity.overlayBlocksInteraction});if(!s)return this._errorCard(la(this._lang,"space_card.not_found",{id:e}));const n=yc(t).find(t=>t.id===e),o=void 0!==this._config.title?this._config.title:n?.title||"",a=!1!==this._config.show_button,r=this._config.button_label||la(this._lang,"space_card.button"),l=this._continuity.overlayVisible||"recovery-error"===this._continuity.state?this._continuity.recoveryReason:null;return W` - + ${a?W`
+
`:G}
- `}}Ru.properties={hass:{attribute:!1},_config:{state:!0},_snap:{state:!0},_continuityEpoch:{state:!0}},Ru.styles=[Kt,o` + `}}Iu.properties={hass:{attribute:!1},_config:{state:!0},_snap:{state:!0},_continuityEpoch:{state:!0}},Iu.styles=[Kt,o` .hp-static-title { font-weight: 700; padding: 10px 14px 6px; @@ -4690,7 +4690,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8 text-align: center; color: var(--secondary-text-color, #9aa4ad); } - `],customElements.get("houseplan-space-card")||customElements.define("houseplan-space-card",Ru),window.customCards=window.customCards||[],window.customCards.find(t=>"houseplan-space-card"===t.type)||window.customCards.push({type:"houseplan-space-card",name:"House Plan — Space (static)",description:"Read-only live schematic of a single houseplan space, with a deep-link button.",preview:!1,documentation:"https://github.com/Matysh/houseplan-card"});const Iu=o` + `],customElements.get("houseplan-space-card")||customElements.define("houseplan-space-card",Iu),window.customCards=window.customCards||[],window.customCards.find(t=>"houseplan-space-card"===t.type)||window.customCards.push({type:"houseplan-space-card",name:"House Plan — Space (static)",description:"Read-only live schematic of a single houseplan space, with a deep-link button.",preview:!1,documentation:"https://github.com/Matysh/houseplan-card"});const Au=o` :host { --hp-editor-tray-bg-fallback: color-mix(in srgb, var(--card-background-color, var(--hp-bg)) 94%, var(--hp-line)); --hp-editor-tray-bg: color-mix(in srgb, var(--card-background-color, var(--hp-bg)) 86%, transparent); @@ -4861,7 +4861,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8 .editor-secondary { transition: none; } .editor-group-launcher .group-chevron { transition: none; } } -`,Au=(t,e)=>(t.composedPath?.()||[t.target]).some(t=>(t=>!!t&&"function"==typeof t.matches)(t)&&e(t));class Fu{constructor(t){this.host=t,this._openGroupId=null,this._groupGeneration=0,this._renderedContext="",this._focusOwned=!1,this._currentModel=null,this._blocked=!1,this._dismissPointerTarget=null,this._globalDismissListening=!1,this._globalDismissGuard=t=>{this.handleOutsideDismiss(t)}}get hasOpenGroup(){return null!==this._openGroupId}get groupGeneration(){return this._groupGeneration}activeGroup(t){return this._openGroupId&&t.find(t=>t.id===this._openGroupId)||null}reset(){this._openGroupId=null,this._contentAnimation?.cancel(),this._contentAnimation=void 0,this._renderedContext="",this._focusOwned=!1,this._currentModel=null,this._blocked=!1,this._dismissPointerTarget=null,clearTimeout(this._dismissTimer),this._dismissTimer=void 0,this._syncGlobalDismissListener()}closeForNavigation(){const t="palette"===this._currentModel?.kind?this._currentModel.dismiss:void 0,e=!!this._openGroupId||!!t;this._openGroupId=null,t?.(),t&&(this._currentModel=null),this._clearDismissClick(),e&&this.host.requestUpdate(),this._syncGlobalDismissListener()}openPalette(){this._openGroupId&&this.closeGroup(!1)}toggleGroup(t,e){this._openGroupId!==e?t.some(t=>t.id===e)&&("palette"===this._currentModel?.kind&&this._currentModel.dismiss?.(),this._groupGeneration+=1,this._openGroupId=e,this.host.clearTip(),this.host.requestUpdate(),this._syncGlobalDismissListener()):this.closeGroup(!1)}closeGroup(t){const e=this._openGroupId;this._openGroupId=null,this.host.requestUpdate(),this._syncGlobalDismissListener(),t&&e&&this.host.updateComplete().then(()=>{const t=this.host.root(),i=[...t.querySelectorAll("[data-editor-group]")].find(t=>t.dataset.editorGroup===e&&null!==t.offsetParent);(i||t.querySelector(".editbar-tools"))?.focus?.()})}renderGroupLauncher(t,e,i){const s=this._openGroupId===t.id,n=t.items.find(e=>e.id===t.activeItemId&&!e.disabled);return W`
-
`}afterRender(){const t=this.host.root();this._blocked&&(this._openGroupId?this.closeGroup(!1):"palette"===this._currentModel?.kind&&this._currentModel.dismiss?.()),this._syncGlobalDismissListener();const e=t.querySelector(".editor-secondary"),i=this._renderedContext,s=e?.dataset.contextId||"";if(s&&i&&s!==i&&!window.matchMedia?.("(prefers-reduced-motion: reduce)")?.matches&&(this._contentAnimation?.cancel(),this._contentAnimation=e?.querySelector(".editor-secondary-content")?.animate([{opacity:.35,transform:"translateY(-4px)"},{opacity:1,transform:"translateY(0)"}],{duration:100,easing:"ease-out"})),this._renderedContext=s,i&&s!==i&&this._focusOwned){const i=s?e?.querySelector('[tabindex="0"], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled])'):t.querySelector(".editbar-tools");i?.focus?.(),this._focusOwned=!!s}if("palette"===this._currentModel?.kind&&this._currentModel.launcherId){const e=[...t.querySelectorAll("[data-editor-palette]")].find(t=>t.dataset.editorPalette===this._currentModel?.launcherId);e&&null!==e.offsetParent||this._currentModel.dismiss?.()}if(!this._openGroupId)return;const n=[...t.querySelectorAll("[data-editor-group]")].find(t=>t.dataset.editorGroup===this._openGroupId);n&&null!==n.offsetParent||this.closeGroup(!0)}handleOutsideDismiss(t){if(Au(t,t=>t.hasAttribute("data-editor-navigation")))return"pointerdown"===t.type?this.closeForNavigation():"click"===t.type&&this._dismissPointerTarget&&this._clearDismissClick(),!1;if("click"===t.type&&this._dismissPointerTarget){return!!(t.composedPath?.()||[t.target]).includes(this._dismissPointerTarget)&&(this._clearDismissClick(),t.preventDefault(),t.stopImmediatePropagation(),!0)}const e=this._openGroupId||this._blocked||"palette"!==this._currentModel?.kind?null:this._currentModel;if("pointerdown"===t.type&&(this._openGroupId||e)){const i=Au(t,t=>t.classList.contains("editor-secondary")),s=Au(t,t=>!!t.dataset.editorGroup),n=Au(t,t=>!!t.dataset.editorPalette),o=Au(t,t=>t.classList.contains("stage"));if(!(i||s||n||"stay-open-on-canvas"===e?.dismissPolicy&&o))return t.preventDefault(),t.stopImmediatePropagation(),this._dismissPointerTarget=t.target,clearTimeout(this._dismissTimer),this._dismissTimer=window.setTimeout(()=>{this._clearDismissClick()},800),this._openGroupId?this.closeGroup(!1):e?.dismiss?.(),this._syncGlobalDismissListener(),!0}return!1}_activateGroupItem(t,e,i){if(t.id!==this._openGroupId)return;const s=t.items.find(t=>t.id===e);if(!s||s.disabled)return;const n="toggle"===s.role&&"stay-open"===s.closePolicy,o=0===i.detail;n||(this._openGroupId=null,this.host.requestUpdate(),this._syncGlobalDismissListener()),s.invoke(),!n&&o&&this.host.updateComplete().then(()=>{const e=[...this.host.root().querySelectorAll("[data-editor-group]")].find(e=>e.dataset.editorGroup===t.id&&null!==e.offsetParent);e?.focus()})}_groupKeydown(t){if(!["ArrowLeft","ArrowRight","Home","End"].includes(t.key))return;const e=[...t.currentTarget.querySelectorAll(".editor-group-item:not([disabled])")];if(!e.length)return;t.preventDefault();const i=e.indexOf(this.host.root().activeElement),s="Home"===t.key?0:"End"===t.key?e.length-1:"ArrowLeft"===t.key?i<=0?e.length-1:i-1:(i+1)%e.length;e[s]?.focus()}_clearDismissClick(){this._dismissPointerTarget=null,clearTimeout(this._dismissTimer),this._dismissTimer=void 0,this._syncGlobalDismissListener()}_syncGlobalDismissListener(){const t=!this._blocked&&"palette"===this._currentModel?.kind,e=!!this._openGroupId||t||!!this._dismissPointerTarget;e!==this._globalDismissListening&&(this._globalDismissListening=e,e?(window.addEventListener("pointerdown",this._globalDismissGuard,!0),window.addEventListener("click",this._globalDismissGuard,!0)):(window.removeEventListener("pointerdown",this._globalDismissGuard,!0),window.removeEventListener("click",this._globalDismissGuard,!0)))}}const Eu=t=>t.stopPropagation(),zu=4.166666666666667e-9;function Ou(t){return Number.isFinite(t)?Math.round(t/xc)*xc:t}const Nu=(t,e,i,s)=>Math.hypot(i-t,s-e),Hu=(t,e,i,s,n,o,r,a)=>Math.hypot(Math.max(Math.abs(n-t),Math.abs(n+r-(t+i))),Math.max(Math.abs(o-e),Math.abs(o+a-(e+s)))),Lu=(t,e,i,s,n,o,r)=>{const a=Math.max(Number(s)||0,0)/2,l=Math.PI/180,c=Math.cos(i*l)*a,h=Math.sin(i*l)*a,d=Math.cos(r*l)*a,p=Math.sin(r*l)*a,u=Math.max(Nu(t+c,e+h,n+d,o+p),Nu(t-c,e-h,n-d,o-p)),_=Math.max(Nu(t+c,e+h,n-d,o-p),Nu(t-c,e-h,n+d,o+p));return Math.min(u,_)},Bu=t=>{const e=Number(t?.cell_cm);return e>0?e:5};const qu=10**9;function Wu(t){if(Array.isArray(t))return t.map(t=>Wu(t));if(null!==t&&"object"==typeof t){const e={};for(const[i,s]of Object.entries(t))e[i]=Wu(s);return e}return t}function ju(t){if("number"!=typeof t||!Number.isFinite(t))return t;const e=(t<0||Object.is(t,-0)?-1:1)*(Math.floor(Math.abs(t)*qu+.5)/qu);return 0===e?0:e}function Uu(t){return null===t||"object"!=typeof t||Array.isArray(t)?null:t}function Gu(t){return Array.isArray(t)?t.filter(t=>null!==Uu(t)):[]}function Vu(t,e){for(const i of e)Object.prototype.hasOwnProperty.call(t,i)&&(t[i]=ju(t[i]))}function Ku(t){if(Array.isArray(t))for(let e=0;eArray.isArray(t)&&t.length>=2&&Number.isFinite(t[0])&&Number.isFinite(t[1]),e_=(t,e)=>Math.hypot(t[0]-e[0],t[1]-e[1]);function i_(t,e,i){const s=i[0]-e[0],n=i[1]-e[1],o=s*s+n*n;if(o<=0)return e_(t,e);let r=((t[0]-e[0])*s+(t[1]-e[1])*n)/o;return r=Math.max(0,Math.min(1,r)),Math.hypot(t[0]-(e[0]+s*r),t[1]-(e[1]+n*r))}function s_(t,e,i,s,n){for(const s of e)if(s&&!i.has(s.id)&&t_(s.a)&&t_(s.b)&&(e_(t,s.a)<=n||e_(t,s.b)<=n))return!0;for(const e of s?.roomPolygons||[])for(let i=0;i0&&a>0))return null;if(Math.abs(n[0]/r*(o[1]/a)-n[1]/r*(o[0]/a))>i)return null;for(const[i,n]of[[t.a,e.a],[t.a,e.b],[t.b,e.a],[t.b,e.b]])if(e_(i,n)<=s)return[(i[0]+n[0])/2,(i[1]+n[1])/2];return null}function o_(t,e){const i=.05*(Number(e.pitch)>0?Number(e.pitch):1),s=new Map;let n=(t||[]).filter(t=>!!t&&"string"==typeof t.id&&t_(t.a)&&t_(t.b));if(n.length<2)return{partitions:[...t||[]],merged:0,openingMoves:[]};const o=e.seedIds&&e.seedIds.length?new Set(e.seedIds):null;let r=0;for(let t=0;te_(e,t.at)>i);let h=c[0]??a.a,d=c[c.length-1]??l.b;if(c.length<2&&(h=a.a,d=l.b),d[0]0?(d[0]-h[0])/u:0,g=u>0?(d[1]-h[1])/u:0,m=t=>u>0?((t[0]-h[0])*_+(t[1]-h[1])*g)/u:0;for(const t of[a,l]){const e=m(t.a),i=m(t.b)-e;for(const[n,o]of s)o.toId===t.id&&s.set(n,{fromId:o.fromId,toId:p.id,base:e+o.base*i,span:o.span*i});s.set(t.id,{fromId:t.id,toId:p.id,base:e,span:i})}o&&o.add(p.id),n=n.filter((e,i)=>i!==t.i&&i!==t.j),n.splice(t.i,0,p),r++}return{partitions:n,merged:r,openingMoves:[...s.values()]}}function r_(t,e,i,s){if(!t?.length||!i.length)return 0;const n=new Map(i.map(t=>[t.fromId,t]));let o=0;for(const i of t){const t=i?.host;if(!t||"partition"!==t.kind)continue;const r=n.get(t.id);if(!r)continue;i.host={...t,id:r.toId,t:Qu(t.t,r)},o++;const a=Pd(i,e,s.coordScale,s.cellCm,s.gridPitch).resolved;a&&Object.assign(i,zd(i,a,s.coordScale))}return o}function a_(t,e){const i=e?.excludeDraftId||null;return{roomPolygons:(t?.rooms||[]).map(t=>hi(t)).filter(t=>!!t),columns:t?.wall_columns||[],draftEnds:(t?.room_drafts||[]).flatMap(t=>{if(i&&t?.id===i)return[];const e=t?.points||[];return e.length?[e[0],e[e.length-1]]:[]})}}const l_=t=>JSON.parse(JSON.stringify(t)),c_=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),h_=(t,e)=>e.length>0&&e.length<=35&&("space"===t?/^[a-z0-9_-]+$/.test(e):/^[A-Za-z0-9_-]+$/.test(e)),d_=(t,e,i)=>{const s=t.get(e)||[];s.push(i),t.set(e,s)};const p_=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),u_=(t,e,i)=>Math.min(i,Math.max(e,t)),__=t=>vc({spaces:[t]})[0],g_=(t,e,i)=>{const s=i>0?i:1,n=t=>`${(t[0]/s).toFixed(12)},${(t[1]/s).toFixed(12)}`,o=n(t),r=n(e);return o0?r:1,l=Math.max(s*a*.02,1e-9),c=[];for(const e of t||[])for(const t of hi(e)||[])c.push([t[0],t[1]]);for(const t of i||[])Array.isArray(t)&&t.length>=4&&t.slice(0,4).every(Number.isFinite)&&c.push([t[0],t[1]],[t[2],t[3]]);const h=t=>c.some(e=>Math.hypot(t[0]-e[0],t[1]-e[1])<=2*l),d=new Map;for(const r of t||[]){if(!r?.id)continue;const c=hl(t,r.id,e,i,s,n,o,a);if(c)for(let t=0;t0&&p>0&&r===u&&p!==r))continue;const _=c.poly[s],g=c.poly[(s+1)%c.poly.length],m=Math.hypot(g[0]-_[0],g[1]-_[1]);if(!(m>l&&m<.5*o-1e-9*o))continue;if(h(_)||h(g))continue;const f=g_(_,g,a),v=d.get(f);v?v.targets.add(r):d.set(f,{a:[_[0],_[1]],b:[g[0],g[1]],targets:new Set([r])})}}}let p=e.slice();const u=(t,e)=>Math.hypot(t[0]-e[0],t[1]-e[1])<=2*l,_=(t,e)=>{if(!Array.isArray(t.a)||!Array.isArray(t.b)||t.a.length<2||t.b.length<2)return!1;const i=[Number(t.a[0])*a,Number(t.a[1])*a],s=[Number(t.b[0])*a,Number(t.b[1])*a];return!![...i,...s].every(Number.isFinite)&&(u(i,e.a)&&u(s,e.b)||u(i,e.b)&&u(s,e.a))};for(const t of[...d.values()].filter(t=>1===t.targets.size).sort((t,e)=>g_(t.a,t.b,a).localeCompare(g_(e.a,e.b,a)))){const e=[...t.targets][0],i=p.filter(e=>_(e,t));if(new Set(i.map(t=>t.cm)).size>1)continue;let n=!1;p=p.map(i=>_(i,t)?(n=!0,i.cm===e?i:{...i,cm:e}):i),n||(p=Na(p,t.a,t.b,e,s,a))}return p}const f_=t=>{const e=[];for(const i of t||[]){const t=hi(i);if(t?.length)for(let i=0;i"string"==typeof t?.id?t.id:"").filter(Boolean),h=new Set(c),d=new Map;for(const t of c){const e=/^space_(.+)_([0-9a-f]{8})$/.exec(t);e&&d_(d,e[1],t)}const p=new Map,u=new Map,_=new Map;for(const t of a){const e="string"==typeof t?.id?t.id:"";if(!e)continue;const i=new Map;for(const s of Array.isArray(t.rooms)?t.rooms:[]){const t="string"==typeof s?.id?s.id:"";if(!t)continue;const n=/^room_(.+)_([0-9a-f]{8})$/.exec(t);n&&d_(i,n[1],t),u.has(t)||u.set(t,e);const o="string"==typeof s.area?s.area:"";if(o){const i=_.get(o)||[];i.push({spaceId:e,roomId:t}),_.set(o,i)}}p.set(e,i)}const g=new Set(u.keys()),m=new Set,f=new Set;for(const t of l)"string"==typeof t?.id&&t.id&&(!0===t.removed?f:m).add(t.id);const v={spaceRefsRemapped:0,roomRefsRemapped:0,positionsRemapped:0,markersDetached:0,positionsUnresolved:0,nestedRefsUnresolved:0,deadSpaceIds:[]},y=new Set,b=t=>h.has(t)||!h_("space",t)?null:1===d.get(t)?.length?d.get(t)[0]:null,w=(t,e)=>{if(!h_("room",t))return null;const i=p.get(e)?.get(t)||[];return 1===i.length?i[0]:null},k=t=>{const e=i.effectiveAreaByMarker?.[t]||"",s=e&&_.get(e)||[];return 1===s.length?s[0]:null},x=(t,e,i)=>{if("string"==typeof t.room_id&&t.room_id&&!g.has(t.room_id)){const s=e?w(t.room_id,e):null;s?(t.room_id=s,v.roomRefsRemapped++):i?(t.room_id=i.roomId,v.roomRefsRemapped++):!0!==t.removed&&delete t.room_id}const s=t.vacuum?.segment_map;if(s&&"object"==typeof s&&!Array.isArray(s))for(const t of Object.keys(s)){const i=s[t];if("string"!=typeof i||!i||g.has(i))continue;const n=e?w(i,e):null;n?(s[t]=n,v.roomRefsRemapped++):v.nestedRefsUnresolved++}};for(const t of l){const e="string"==typeof t?.id?t.id:"";if(!e)continue;const i="string"==typeof t.space?t.space:"",s=i&&!h.has(i),o=n[e],r="string"==typeof o?.s?o.s:"",a=r&&!h.has(r),l=!0===t.removed;let c=i&&h.has(i)?i:null,d=null,p=!1;if(s){const s=b(i);s?(t.space=s,c=s,p=!0,v.spaceRefsRemapped++):l||"virtual"===t.binding?l||(delete t.space,c=null,v.markersDetached++):(d=k(e),d?(t.space=d.spaceId,c=d.spaceId,v.spaceRefsRemapped++):(delete t.space,c=null,v.markersDetached++))}l&&!p||x(t,c,d),a&&(p&&r===i&&c?(n[e]={...o,s:c},v.positionsRemapped++,y.add(e)):l||(delete n[e],y.add(e)))}for(const t of Object.keys(n)){if(y.has(t))continue;const e=n[t],i="string"==typeof e?.s?e.s:"";if(!i||h.has(i))continue;const s=b(i);if(s){if(t.startsWith("rl_")){const i=t.slice(3),o=w(i,s);if(o){const i=`rl_${o}`;c_(n,i)||(n[i]={...e,s:s}),delete n[t],v.roomRefsRemapped++,v.positionsRemapped++;continue}}n[t]={...e,s:s},v.positionsRemapped++}}const $=new Set;for(const t of l){const e="string"==typeof t?.space?t.space:"";e&&!h.has(e)&&$.add(e)}for(const[t,e]of Object.entries(n)){const i="string"==typeof e?.s?e.s:"";i&&!h.has(i)&&($.add(i),m.has(t)&&!f.has(t)||v.positionsUnresolved++)}return v.deadSpaceIds=[...$].sort((t,e)=>t.localeCompare(e)),{config:s,layout:n,report:v,changed:JSON.stringify(s)!==o||JSON.stringify(n)!==r}}(t,e,i),n=s.config,o=JSON.stringify(t||{}),r=JSON.stringify(e||{}),a=Number.isInteger(Number(n.model_version))?Number(n.model_version):0,l=(t=>{let e=0,i=0,s=0;for(const i of t.markers||[]){if("ripple"===i.display&&(i.display="icon_ripple",e++),Array.isArray(i.controls)){const t="string"==typeof i.binding&&i.binding.startsWith("entity:")?i.binding.slice(7):"",s=t?i.controls.filter(e=>e!==t):i.controls;JSON.stringify(s)!==JSON.stringify(i.controls)&&(i.controls=s.length?s:null,e++)}const t=i.vacuum;t&&p_(t,"trail")&&(["never","cleaning","always"].includes(t.trail_mode)||(t.trail_mode=!1===t.trail?"never":"cleaning"),delete t.trail,e++)}for(const n of t.spaces||[]){const t=n.settings;"glow"===t?.fill_mode&&("boolean"!=typeof t.glow_enabled&&(t.glow_enabled=!0),t.fill_mode="none",e++,i++);for(const t of n.rooms||[]){const i=t.settings;"glow"===i?.fill_mode&&("boolean"!=typeof i.glow&&(i.glow=!0),delete i.fill_mode,e++,s++)}if(p_(n,"segments")&&(delete n.segments,e++),p_(n,"plan_scale")){const t=Number(n.plan_scale);Number.isFinite(t)&&t>=_c&&t<=gc&&(p_(n,"plan_scale_x")||(n.plan_scale_x=t),p_(n,"plan_scale_y")||(n.plan_scale_y=t),delete n.plan_scale,e++)}const o=Number(n.cell_cm);p_(n,"cell_cm")&&(!Number.isFinite(o)||o<.1||o>1e3)&&(n.cell_cm=Number.isFinite(o)&&o>0?u_(o,.1,1e3):5,e++);const r=Number(n.cell_cm),a=Number.isFinite(r)&&r>0?r:5;for(const t of n.wall_columns||[])if("circle"===t.shape)p_(t,"angle")&&(delete t.angle,e++);else if("square"===t.shape&&p_(t,"angle")){const i=((Number(t.angle)||0)%90+90)%90;t.angle!==i&&(t.angle=i,e++)}for(const t of n.decor||[]){if(p_(t,"width")){const i=Number(t.width);(p_(t,"width_cm")||Number.isFinite(i))&&(p_(t,"width_cm")||(t.width_cm=Number(u_(i/kc*a,.1,100).toFixed(6))),delete t.width,e++)}if("rect"!==t?.kind&&"ellipse"!==t?.kind||!0!==t.fill||(p_(t,"fill_color")||(t.fill_color=t.color||"#607d8b",e++),p_(t,"fill_opacity")||(t.fill_opacity=.25,e++)),"text"!==t?.kind)continue;void 0===t.size_cm?(t.size_cm=Number(u_(es*is(t)/kc*a,.1,2e3).toFixed(6)),delete t.scale,delete t.size,e++):(p_(t,"scale")||p_(t,"size"))&&(delete t.scale,delete t.size,e++);let i=String(t.text??"");const s=[...i.matchAll(/\{([^{}\r\n]+)\}/g)].some(t=>!!Yi(t[1]));if(!(p_(t,"entity")||p_(t,"attr")||p_(t,"unit")))continue;const n=String(t.unit??"").trim(),o="state"===String(t.attr??"").trim().toLowerCase()?null:t.attr,r=s||n?"":Xi(t.entity,o);if(s||r){if(r){const e=i.indexOf("{}");i=e>=0?i.slice(0,e)+r+i.slice(e+2):`${i}${i?" ":""}${r}`,t.text=i}delete t.entity,delete t.attr,delete t.unit,e++}}}return{total:e,glowSpaces:i,glowRooms:s}})(n);let c=l.total;for(const t of n.spaces||[]){const e=__(t);if(!e)continue;if(!rh(t.open_spans).length){const i=dh(e.rooms,null,pc,.02*kc,!0);i.length&&(t.open_spans=ph(i,pc),c++)}}const h=(d=n.spaces||[],JSON.parse(JSON.stringify(d)));var d;const p=function(t,e){const i=JSON.parse(JSON.stringify(t||[])),s=JSON.parse(JSON.stringify(e||{}));let n=0,o=0,r=0,a=0,l="",c=0,h=0,d=0;const p=(t,e)=>{Number.isFinite(t)&&Number.isFinite(e)&&t!==e&&Math.abs(e-t)<=zu&&h++},u=(t,e)=>{p(t[0],e[0]),p(t[1],e[1])},_={};let g=5;for(const t of i){const e=Bu(t);null!=t?.id&&(_[String(t.id)]=e),e>g&&(g=e)}const m=(t,e,i,s=!1)=>{if(!(t>zu||s))return;n++,t>r&&(r=t);const o=t*wc*e;o>a&&(a=o,l=i)};for(const t of i){const e=Bu(t),i=null!=t?.id?String(t.id):"";for(const s of t.rooms||[]){o++;let t=0;if(s.poly?.length)s.poly=s.poly.map(e=>{const i=[Ou(e[0]),Ou(e[1])];return t=Math.max(t,Nu(e[0],e[1],i[0],i[1])),u(e,i),i});else if(null!=s.x&&null!=s.y){const e=s.x,i=s.y,n=s.w||0,o=s.h||0,r=Ou(e+n),a=Ou(i+o),l=Ou(e),c=Ou(i),h=Math.max(xc,r-l),d=Math.max(xc,a-c);t=Hu(e,i,n,o,l,c,h,d),s.x=l,s.y=c,s.w=h,s.h=d,p(e,l),p(i,c),p(e+n,l+h),p(i+o,c+d)}m(t,e,i)}for(const s of t.room_drafts||[]){o++;let t=0;const n=s.points||[],r=n.map(e=>{const i=[Ou(e[0]),Ou(e[1])];return t=Math.max(t,Nu(e[0],e[1],i[0],i[1])),i}),a=r.length?[r[0]]:[],l=r.length?[[n[0],r[0]]]:[],c=[];for(let t=0;t+1=2)for(const[t,e]of l)u(t,e);m(t,e,i)}if(Array.isArray(t.room_drafts)){const e=t.room_drafts.length;t.room_drafts=t.room_drafts.filter(t=>t.points?.length>=2),d+=e-t.room_drafts.length,t.room_drafts.length||delete t.room_drafts}for(const s of t.partitions||[]){o++;const n=[s.a[0],s.a[1]],r=[s.b[0],s.b[1]],a=[Ou(n[0]),Ou(n[1])],l=[Ou(r[0]),Ou(r[1])];let c=Math.max(Nu(n[0],n[1],a[0],a[1]),Nu(r[0],r[1],l[0],l[1]));const h=Nu(a[0],a[1],l[0],l[1]),d=(t.openings||[]).filter(t=>"partition"===t.host?.kind&&t.host.id===s.id).every(t=>{const e=Number(t.length),i=Number(t.host.t),s=i*h;return Number.isFinite(e)&&e>0&&Number.isFinite(i)&&i>=0&&i<=1&&s-e/2>=-zu&&s+e/2<=h+zu});h>zu&&d?(s.a=a,s.b=l,u(n,a),u(r,l)):c=0,m(c,e,i)}for(const s of t.wall_columns||[]){o++;const t=[s.center[0],s.center[1]],n=[Ou(t[0]),Ou(t[1])],r=Nu(t[0],t[1],n[0],n[1]);s.center=n,u(t,n),m(r,e,i)}for(const s of t.decor||[]){o++;let t=0;if("line"===s.kind){const e=[s.x1,s.y1],i=[s.x2,s.y2],n=[Ou(e[0]),Ou(e[1])],o=[Ou(i[0]),Ou(i[1])];t=Math.max(Nu(e[0],e[1],n[0],n[1]),Nu(i[0],i[1],o[0],o[1])),s.x1=n[0],s.y1=n[1],s.x2=o[0],s.y2=o[1],u(e,n),u(i,o)}else{const e=s.x,i=s.y,n=s.w,o=s.h,r=Ou(e),a=Ou(i);if(null!=s.w&&null!=s.h){const l=Ou(e+n),c=Ou(i+o),h=Math.max(xc,l-r),d=Math.max(xc,c-a);t=Hu(e,i,n,o,r,a,h,d),s.w=h,s.h=d,p(e+n,r+h),p(i+o,a+d)}else t=Nu(e,i,r,a);s.x=r,s.y=a,p(e,r),p(i,a)}m(t,e,i)}for(const s of t.openings||[]){if(o++,"partition"===s.host?.kind){const n=(t.partitions||[]).find(t=>t.id===s.host.id),o=Number(s.host.t);if(!n||!Number.isFinite(o)||o<0||o>1)continue;const r=n.b[0]-n.a[0],a=n.b[1]-n.a[1];if(Math.hypot(r,a)<=zu)continue;const l=n.a[0]+r*o,h=n.a[1]+a*o;let d=180*Math.atan2(a,r)/Math.PI;d>=90?d-=180:d<-90&&(d+=180);const p=Number(s.angle),u=!(Number.isFinite(p)&&p===d),_=Lu(s.x,s.y,Number.isFinite(p)?p:d,Number(s.length)||0,l,h,d);s.x=l,s.y=h,s.angle=d,u&&c++,m(_,e,i,u);continue}const n=ui([s.x,s.y],t.rooms||[],.025,{step:xc,length:Number(s.length)||0});if(!n)continue;const r=Number(s.angle),a=!(Number.isFinite(r)&&r===n.angle),l=Lu(s.x,s.y,Number.isFinite(r)?r:n.angle,Number(s.length)||0,n.x,n.y,n.angle);s.x=n.x,s.y=n.y,s.angle=n.angle,a&&c++,m(l,e,i,a)}}for(const[t,e]of Object.entries(s)){if(!e||"object"!=typeof e)continue;const i=e;if("number"!=typeof i.x||"number"!=typeof i.y)continue;o++;const n=Ou(i.x),r=Ou(i.y),a=Nu(i.x,i.y,n,r);s[t]={...i,x:n,y:r},p(i.x,n),p(i.y,r);const l="string"==typeof i.s?i.s:"";m(a,_[l]??g,l)}return{spaces:i,layout:s,report:{moved:n,coordsCanonicalized:h,total:o,maxShift:r,maxShiftCm:a,maxSpace:l,rotated:c,removedDrafts:d},changed:n>0||h>0}}(n.spaces||[],s.layout);n.spaces=p.spaces;const u={...p.report};let _=0,g=0,m=0,f=0;for(let t=0;t[t.id,t.open_to||[]]),walls:e.walls||[]}),o=__(e),r=__(i);if(!o||!r)continue;const a=f_(o.rooms),l=f_(r.rooms),c=.02*kc;let d=bh(rh(e.open_spans),a,l,pc);const p=d.length;d=yh(d,r.rooms,pc,c),d=d.map(t=>{const e=nh(t,pc),s=[e[0],e[1]],n=[e[2],e[3]],o=[(e[0]+e[2])/2,(e[1]+e[3])/2],r=e[2]-e[0],a=e[3]-e[1],h=Math.hypot(r,a)||1,d=l.map(([t,e])=>[t[0],t[1],e[0],e[1]]).filter(t=>{const e=t[2]-t[0],i=t[3]-t[1],l=Math.hypot(e,i)||1;return Math.abs(r*i-a*e)/(h*l)<=1e-6&&ah(o,t).d<=4*c&&ah(s,t).d<=4*c&&ah(n,t).d<=4*c}).sort((t,e)=>Math.hypot(e[2]-e[0],e[3]-e[1])-Math.hypot(t[2]-t[0],t[3]-t[1]))[0];if(u.total++,!d)return t;const p=[[d[0],d[1]],[d[2],d[3]]],_=ch(s,d,p,kc,2*c),g=ch(n,d,p,kc,2*c);if(Math.hypot(g[0]-_[0],g[1]-_[1])<.5*kc)return t;const m=Math.max(Math.hypot(_[0]-s[0],_[1]-s[1]),Math.hypot(g[0]-n[0],g[1]-n[1]));if(m>1e-6*kc){u.moved++;const t=m/pc;t>u.maxShift&&(u.maxShift=t);const e=m/kc*(Number(i.cell_cm)>0?Number(i.cell_cm):5);e>u.maxShiftCm&&(u.maxShiftCm=e,u.maxSpace=String(i.id||""))}return sh(_,g,pc)}),d=yh(d,r.rooms,pc,c),g+=Math.max(0,p-d.length);const v=d.map(t=>nh(t,pc));d.length?i.open_spans=d:delete i.open_spans,uh(i.rooms||[],r.rooms,v,c);const y=Array.isArray(e.walls)?e.walls.length:0;let b=Oa(e.walls,a,l,xc,pc);b=m_(r.rooms,b,v,xc,Number(i.cell_cm)>0?Number(i.cell_cm):5,kc,pc),b=ul(r.rooms,b,v,xc,Number(i.cell_cm)>0?Number(i.cell_cm):5,kc,pc),b=Ea(b,i.rooms||[],xc,1,v.map(t=>[t[0]/pc,t[1]/pc,t[2]/pc,t[3]/pc])),_+=Math.max(0,y-b.length),b.length?i.walls=b:delete i.walls;const w=o_(i.partitions||[],{pitch:xc,geometry:a_(i)});w.merged&&(m+=w.merged,i.partitions=w.partitions,r_(i.openings,i.partitions,w.openingMoves,{coordScale:pc,cellCm:Number(i.cell_cm)>0?Number(i.cell_cm):5,gridPitch:kc}));const k=JSON.stringify({spans:i.open_spans||[],links:(i.rooms||[]).map(t=>[t.id,t.open_to||[]]),walls:i.walls||[]});k!==s&&f++}const v=Zu(n),y=Ju(p.layout),b=JSON.stringify(v)!==o||JSON.stringify(y)!==r;a<7&&b&&(v.model_version=7);const w=JSON.stringify(v)!==o||JSON.stringify(y)!==r,k=Number.isInteger(Number(v.model_version))?Number(v.model_version):a,x=w?u:{...u,moved:0,coordsCanonicalized:0,maxShift:0,maxShiftCm:0,maxSpace:"",rotated:0,removedDrafts:0},$=w?s.report:{...s.report,spaceRefsRemapped:0,roomRefsRemapped:0,positionsRemapped:0,markersDetached:0};return{config:v,layout:y,report:{...x,modelFrom:a,modelTo:k,migrated:w?c:0,glowSpacesMigrated:w?l.glowSpaces:0,glowRoomsMigrated:w?l.glowRooms:0,canonicalized:w?f:0,wallsMerged:w?_:0,spansMerged:w?g:0,partitionsMerged:w?m:0,...$},changed:w}}function y_(t,e,i){const s=(t?.spaces||[]).find(t=>t?.id===i),n=new Set((s?.rooms||[]).map(t=>String(t?.id||"")).filter(Boolean)),o=[...new Set((t?.markers||[]).filter(t=>!0!==t?.removed&&"string"==typeof t?.id).filter(t=>t.space===i||"string"==typeof t.room_id&&n.has(t.room_id)||e?.[t.id]?.s===i).map(t=>t.id))].sort((t,e)=>t.localeCompare(e));return{markerIds:o,count:o.length}}function b_(t,e,i=kc,s=1e3){return dh(e.rooms,t?.open_spans,s,.02*i)}function w_(t,e,i=kc){if(!e.length)return[];const s=t.filter(t=>t?.id),n=.02*i,o=[];for(let t=0;t{const e=[(t[0]+t[2])/2,(t[1]+t[3])/2];return h.some(t=>Hs(e,t)<4*n)}).map(t=>[...t]);d.length&&o.push({a:r,b:a,segs:d})}return o}function k_(t,e,i,s=kc,n=1e3){return(Array.isArray(t?.openings)?t.openings:[]).flatMap(t=>{const o={...t,rx:Number(t.x)*n,ry:Number(t.y)*n,rlen:Number(t.length)*n};if(!t.host)return[o];const r=Pd(t,e.partitions,n,i,s);return r.resolved?[{...t,rx:r.resolved.center[0],ry:r.resolved.center[1],rlen:r.resolved.length,angle:r.resolved.angle,partitionHost:r.resolved}]:[]})}function x_(t,e=()=>!0){return t.flatMap(t=>t.host&&t.partitionHost&&e(t)?[Ad(t.partitionHost)]:[])}function $_(t,e,i,s,n,o,r=kc,a=1e3){const l=dl(e.rooms,[...i],s,n,o,r,a);return t.flatMap(t=>{const e={x:t.rx,y:t.ry,angle:Number(t.angle)||0,length:t.rlen};return t.host?t.partitionHost&&Ed(t.partitionHost,l,2e-4*r)?[e]:[]:[e]})}function S_(t,e){const i=xc,s=kc,n=pc,o=Number.isFinite(Number(e.cellCm))&&Number(e.cellCm)>0?Number(e.cellCm):5,r=Array.isArray(t?.walls)?t.walls:[],a=b_(t,e,s,n),l=w_(e.rooms,a,s).flatMap(t=>t.segs),c=k_(t,e,o,s,n),h=x_(c),d=Xl(e,o,s,2e-4*s,h).all;return{space:e,walls:r,openCuts:l,openings:c,roomOpenings:$_(c,e,r,l,i,o,s,n),partitionCuts:h,physicalBodies:d,wallKeyPitch:i,cellCm:o,gridPitch:s,coordScale:n}}function M_(t,e,i){const s="string"==typeof t?.title?t.title.trim():"",n=null==t?.id?"":String(t.id).trim();return{spaceId:n,displayName:s||n||i(e+1)}}class C_{constructor(t=50){this._undo=[],this._redo=[],this._limit=Math.max(30,Math.floor(t))}get canUndo(){return this._undo.length>0}get canRedo(){return this._redo.length>0}get undoName(){return this._undo[this._undo.length-1]?.name??null}get redoName(){return this._redo[this._redo.length-1]?.name??null}get size(){return this._undo.length}push(t){this._undo.push(t),this._undo.length>this._limit&&this._undo.splice(0,this._undo.length-this._limit),this._redo=[]}undo(){const t=this._undo.pop()??null;return t&&this._redo.push(t),t}redo(){const t=this._redo.pop()??null;return t&&this._undo.push(t),t}clear(){this._undo=[],this._redo=[]}}const D_=new WeakMap;const T_=(t,e,i)=>255===t[i+3]&&e.every((e,s)=>Math.abs(t[i+s]-e)<=2);async function P_(t){const e=t.defaultView;if(!e||!e.CSS?.supports?.("mix-blend-mode","screen"))return!1;const i=[128,32,16],s=[16,64,128],n=[9,19,29],o=`\n \n \n \n \n \n `,r=e.URL.createObjectURL(new Blob([o],{type:"image/svg+xml"}));try{const o=await new Promise((t,i)=>{const s=new e.Image,n=e.setTimeout(()=>i(new Error("SVG blend probe timeout")),1e3);s.onload=()=>{e.clearTimeout(n),t(s)},s.onerror=()=>{e.clearTimeout(n),i(new Error("SVG blend probe failed"))},s.src=r}),a=t.createElement("canvas");a.width=4,a.height=1;const l=a.getContext("2d",{willReadFrequently:!0});if(!l)return!1;l.drawImage(o,0,0,4,1);const c=l.getImageData(0,0,4,1).data;return T_(c,i,0)&&T_(c,function(t,e){return[0,1,2].map(i=>Math.round(255-(255-t[i])*(255-e[i])/255))}(i,s),4)&&T_(c,s,8)&&T_(c,n,12)}catch{return!1}finally{e.URL.revokeObjectURL(r)}}const R_={now:()=>performance.now(),requestFrame:t=>requestAnimationFrame(t),cancelFrame:t=>cancelAnimationFrame(t)},I_=t=>Math.max(0,Math.min(1,t)),A_=(t,e,i)=>t+(e-t)*i,F_=(t,e,i)=>{const s=1-t;return 3*s*s*t*e+3*s*t*t*i+t*t*t};function E_(t,e){return{centerX:t.x+t.w/2,centerY:t.y+t.h/2,pixelsPerUnit:e>0&&t.w>0?e/t.w:1,viewBox:{...t}}}function z_(t,e,i){const s=Math.max(1e-9,t.pixelsPerUnit),n=Math.max(1e-9,e/s),o=Math.max(1e-9,i/s);return{x:t.centerX-n/2,y:t.centerY-o/2,w:n,h:o}}function O_(t){const e=t.trim(),i=/^rgba?\(\s*([\d.]+)[, ]+([\d.]+)[, ]+([\d.]+)(?:\s*[,/]\s*([\d.]+))?\s*\)$/i.exec(e);if(i)return[Number(i[1]),Number(i[2]),Number(i[3]),null==i[4]?1:Number(i[4])];const s=/^#([0-9a-f]{6}|[0-9a-f]{8})$/i.exec(e)?.[1];return s?[parseInt(s.slice(0,2),16),parseInt(s.slice(2,4),16),parseInt(s.slice(4,6),16),8===s.length?parseInt(s.slice(6,8),16)/255:1]:null}function N_(t,e,i){const s=O_(t),n=O_(e);if(!s||!n)return i<.5?t:e;const o=I_(i);return`rgba(${Math.round(A_(s[0],n[0],o))}, ${Math.round(A_(s[1],n[1],o))}, ${Math.round(A_(s[2],n[2],o))}, ${A_(s[3],n[3],o).toFixed(3)})`}function H_(t,e,i){const s=(t=>{const e=I_(t);if(0===e||1===e)return e;let i=0,s=1,n=e;for(let t=0;t<12;t++)n=(i+s)/2,F_(n,.2,.2){const e=this._state;if(!e||e.token!==n)return;const i=I_((t-e.startedAt)/e.duration);e.presented=i>=1?e.to:H_(e.from,e.to,i),e.phase=i>=1?"settling":"running",this._hooks.frame(e),i<1?this._raf=this._clock.requestFrame(r):(this._raf=0,this._hooks.settled(e),this._state?.token===n&&(this._state=null))};return this._raf=this._clock.requestFrame(r),n}cancel(t=!0){this._raf&&this._clock.cancelFrame(this._raf),this._raf=0;const e=this._state;this._state=null,this._token++,e&&t&&(e.phase="settling",e.presented=e.to,this._hooks.frame(e),this._hooks.settled(e))}dispose(){this.cancel(!1)}}const B_="houseplan_card_labs_v1",q_=Object.freeze([Object.freeze({id:"iso",issue:89,since:"1.62.0",expires:"1.65.0",summary:"Volumetric plan renderer"})]);function W_(t){const e=/^(\d+)\.(\d+)\.(\d+)(?:-[0-9A-Za-z.-]+)?$/.exec(String(t||"").trim());if(!e)return null;const i=e.slice(1).map(Number);return i.every(t=>Number.isSafeInteger(t))?i:null}function j_(t,e){for(let i=0;i<3;i++)if(t[i]!==e[i])return t[i]t.split(",")).map(t=>t.trim()).filter(Boolean)}function X_(t,e,i,s=q_){const n=function(t,e=q_){const i=W_(t),s=new Map;if(!i||!G_(e))return s;for(const t of e){const e=W_(t.since),n=W_(t.expires);j_(i,e)>=0&&j_(i,n)<0&&s.set(t.id,t)}return s}(i,s),o=new Set(G_(s)?s.map(t=>t.id):[]),r=new Set(function(t){if(!t)return[];try{const e=JSON.parse(t);return Array.isArray(e)?e.filter(t=>"string"==typeof t):[]}catch{return[]}}(e).filter(t=>n.has(t)));let a=!1;const l=t=>{if("off"===t)return r.clear(),void(a=!0);const e=t.startsWith("-"),i=e?t.slice(1):t;o.has(i)&&(a=!0,e||!n.has(i)?r.delete(i):r.add(i))};for(const e of Y_(new URLSearchParams(String(t.search||"").replace(/^\?/,""))))l(e);for(const e of Y_(V_(t.hash)))l(e);const c=Object.freeze([...r].sort());return{active:c,space:K_(t.hash),persist:a?JSON.stringify(c):void 0,knownUrlOperation:a}}let J_={active:Object.freeze([]),space:""},Z_="",Q_=!1,tg="";const eg=new Set;function ig(){if("undefined"==typeof window)return J_;const t=X_(window.location,function(){try{return window.localStorage.getItem(B_)}catch{return null}}(),Z_);void 0!==t.persist&&function(t){try{window.localStorage.setItem(B_,t)}catch{}}(t.persist),J_={active:t.active,space:t.space},window.__hpLabs=t.active;for(const t of eg)t(J_);return J_}function sg(){ig()}function ng(t){return Z_=t,"undefined"==typeof window?J_:(Q_||(Q_=!0,window.addEventListener("hashchange",sg),window.addEventListener("popstate",sg)),ig())}const og=Object.freeze({rotDeg:0,tiltDeg:20,xyScale:1,zScale:1,origin:Object.freeze([500,500])});function rg(t){return[t.rotDeg,t.tiltDeg,t.xyScale,t.zScale,t.origin[0],t.origin[1]].every(Number.isFinite)&&Math.abs(t.xyScale)>1e-12&&Math.abs(Math.cos(t.tiltDeg*Math.PI/180))>1e-12}function ag(t,e,i=og){if(!(rg(i)&&Number.isFinite(t[0])&&Number.isFinite(t[1])&&Number.isFinite(e)))throw new Error("invalid isometric projection input");const s=i.rotDeg*Math.PI/180,n=i.tiltDeg*Math.PI/180,o=t[0]-i.origin[0],r=t[1]-i.origin[1],a=(o*Math.cos(s)-r*Math.sin(s))*i.xyScale,l=(o*Math.sin(s)+r*Math.cos(s))*i.xyScale;return[i.origin[0]+a,i.origin[1]+l*Math.cos(n)-e*i.zScale*Math.sin(n)]}function lg(t,e=og){if(!rg(e)||!Number.isFinite(t[0])||!Number.isFinite(t[1]))throw new Error("invalid isometric projection input");const i=e.rotDeg*Math.PI/180,s=e.tiltDeg*Math.PI/180,n=(t[0]-e.origin[0])/e.xyScale,o=(t[1]-e.origin[1])/(e.xyScale*Math.cos(s));return[e.origin[0]+n*Math.cos(i)+o*Math.sin(i),e.origin[1]-n*Math.sin(i)+o*Math.cos(i)]}function cg(t=og){return`matrix(${function(t=og){if(!rg(t))throw new Error("invalid isometric camera");const e=t.rotDeg*Math.PI/180,i=t.tiltDeg*Math.PI/180,s=t.xyScale*Math.cos(e),n=-t.xyScale*Math.sin(e),o=t.xyScale*Math.sin(e)*Math.cos(i),r=t.xyScale*Math.cos(e)*Math.cos(i);return[s,o,n,r,t.origin[0]-s*t.origin[0]-n*t.origin[1],t.origin[1]-o*t.origin[0]-r*t.origin[1]]}(t).map(t=>Number(t.toFixed(12))).join(" ")})`}function hg(t,e=og){const{rect:i,wallHeight:s}=t,n=t.openingHeight??s,o=t.floorDepth??0;if(!(i.w>=0)||!(i.h>=0)||!Number.isFinite(s)||!Number.isFinite(n)||!Number.isFinite(o)||s<0||n<0||o<0)throw new Error("invalid isometric frame");const r=[[i.x,i.y],[i.x+i.w,i.y],[i.x+i.w,i.y+i.h],[i.x,i.y+i.h]],a=Math.max(s,n),l=r.flatMap(t=>[ag(t,-o,e),ag(t,a,e)]),c=l.map(t=>t[0]),h=l.map(t=>t[1]),d=Math.min(...c),p=Math.min(...h);return{x:d,y:p,w:Math.max(...c)-d,h:Math.max(...h)-p}}const dg=t=>`${Number(t[0].toFixed(4))} ${Number(t[1].toFixed(4))}`;function pg(t){let e=0;for(let i=0;iArray.isArray(t)&&Number.isFinite(t[0])&&Number.isFinite(t[1])).map(t=>[Number(t[0]),Number(t[1])]),i=e[e.length-1];return e.length>1&&e[0][0]===i[0]&&e[0][1]===i[1]&&e.pop(),e}(t);if(i.length<3)return[];const s=!e;return pg(i)>0===s?i:[...i].reverse()}function _g(t,e,i){return t.length?`M ${t.map(t=>dg(ag(t,i,e))).join(" L ")} Z`:""}function gg(t,e,i){const s=e[1]-t[1],n=-(e[0]-t[0]),o=i.rotDeg*Math.PI/180;return s*Math.sin(o)+n*Math.cos(o)}function mg(t,e,i=og){if(!Number.isFinite(e)||e<0)throw new Error("invalid floor edge height");const s=(t||[]).map(t=>{const e=(t||[]).map((t,e)=>function(t,e){const i=ug(t,e);if(!i.length)return i;let s=0;for(let t=1;t0)).filter(t=>t.length>=3&&Math.abs(pg(t))>=1e-9);return e}).filter(t=>t.length&&pg(t[0])>0);s.sort((t,e)=>{const i=t[0][0],s=e[0][0];return i[0]-s[0]||i[1]-s[1]||Math.abs(pg(e[0]))-Math.abs(pg(t[0]))});const n=[],o=[];let r=0;for(let t=0;tt.depth-e.depth||t.component-e.component||t.edge-e.edge),{footprintPath:n.join(" "),sides:o,componentCount:s.length,edgeCount:r}}function fg(t,e){return t^=Math.round(64*(Number.isFinite(e)?e:0)),Math.imul(t,16777619)>>>0}const vg=t=>t.every(Number.isFinite);function yg(t,e,i,s){const n=t[0]*i,o=t[1]*s,r=e*Math.PI/180;return[n*Math.cos(r)-o*Math.sin(r),n*Math.sin(r)+o*Math.cos(r)]}function bg(t,e,i,s,n,o,r){const a=t.flipH?-1:1,l="gate"===t.type?1:t.flipV?-1:1,c=(t.type,t.flipV,t.angle,t.face,{ox:0,oy:0}),h=function(t,e){return[t[0]+e[0],t[1]+e[1]]}([t.x+c.ox,t.y+c.oy],yg(i,t.angle,a,l));return{leaf:e,hinge:h,closedVector:yg(s,t.angle,a,l),quarterVector:yg([-s[1],s[0]],t.angle,a,l),turnDeg:n,bottom:o,top:r}}const wg=t=>`${Number(t[0].toFixed(4))} ${Number(t[1].toFixed(4))}`;function kg(t,e,i=og){const s=Math.max(0,Math.min(1,Number.isFinite(e)?e:0));return t.leaves.map(e=>{const n=function(t,e){const i=t.turnDeg*e*Math.PI/180;return[t.hinge[0]+t.closedVector[0]*Math.cos(i)+t.quarterVector[0]*Math.sin(i),t.hinge[1]+t.closedVector[1]*Math.cos(i)+t.quarterVector[1]*Math.sin(i)]}(e,s),o=ag(e.hinge,e.bottom,i),r=ag(n,e.bottom,i),a=ag(n,e.top,i),l=ag(e.hinge,e.top,i);return{id:t.id,sourceIndex:t.sourceIndex,type:t.type,leaf:e.leaf,d:`M ${wg(o)} L ${wg(r)} L ${wg(a)} L ${wg(l)} Z`,shadowD:`M ${wg(ag(e.hinge,0,i))} L ${wg(ag(n,0,i))}`,depth:Math.max(o[1],r[1])}})}const xg={window:120,door:90,passage:90,gate:300};function $g(t){return xg[t]}function Sg(t,e){const i=[t[0],t[1]],s=[e[0],e[1]];return function(t,e){return t[0]-e[0]||t[1]-e[1]}(i,s)<=0?{a:i,b:s}:{a:s,b:i}}function Mg(t){const e=new Map;return t.forEach((t,i)=>{if(!t.kind||t.open)return;const s=Sg(t.a,t.b);if(Math.hypot(s.b[0]-s.a[0],s.b[1]-s.a[1])<=1e-9)return;const n=function(t,e){const i=t=>(Math.abs(t)<=5e-10?0:Math.round(1e6*t)/1e6).toFixed(6);return`${i(t[0])},${i(t[1])}>${i(e[0])},${i(e[1])}`}(s.a,s.b),o=e.get(n);if(o)return o.physicalHalfWidth=Math.max(o.physicalHalfWidth,t.half||0),o.sourceOrder=Math.min(o.sourceOrder,i),void(t.partitionHost&&(o.partitionHost&&o.partitionHost.id!==t.partitionHost.id?o.ambiguousPartitionHost=!0:o.partitionHost=t.partitionHost));e.set(n,{segmentKey:n,a:s.a,b:s.b,physicalHalfWidth:Math.max(0,t.half||0),sourceOrder:i,...t.partitionHost?{partitionHost:t.partitionHost}:{}})}),[...e.values()]}function Cg(t,e){if(Math.abs(t.distance-e.distance)>1e-9)return t.distance-e.distance;if(Math.abs(t.perpendicular-e.perpendicular)>1e-9)return t.perpendicular-e.perpendicular;return(t.target.segmentKeye.target.segmentKey?1:0)||t.target.sourceOrder-e.target.sourceOrder}function Dg(t){const e=Mg(t.intervals).map(e=>{const i=function(t,e){const i=e.b[0]-e.a[0],s=e.b[1]-e.a[1],n=Math.hypot(i,s),o=i/n,r=s/n,a=(t[0]-e.a[0])*o+(t[1]-e.a[1])*r,l=Math.max(0,Math.min(n,a)),c=e.a[0]+l*o,h=e.a[1]+l*r;return{along:l,length:n,x:c,y:h,distance:Math.hypot(t[0]-c,t[1]-h),perpendicular:Math.abs((t[0]-e.a[0])*r-(t[1]-e.a[1])*o)}}(t.pointer,e);return{target:e,...i,envelope:Math.max(t.baseTolerance,e.physicalHalfWidth+t.bodyPointerPadding)}}).filter(t=>t.distance<=t.envelope+1e-9).filter(e=>!function(t,e,i,s,n){const o=e.b[0]-e.a[0],r=e.b[1]-e.a[1],a=Math.hypot(o,r);if(!(a>1e-9))return!1;const l=o/a,c=r/a;for(const o of i){if(!o.open&&o.kind)continue;const i=Sg(o.a,o.b),r=i.b[0]-i.a[0],a=i.b[1]-i.a[1],h=Math.hypot(r,a);if(!(h>1e-9))continue;const d=r/h,p=a/h;if(Math.abs(l*p-c*d)>1e-6)continue;if(Math.abs((i.a[0]-e.a[0])*c-(i.a[1]-e.a[1])*l)>n)continue;const u=(t[0]-i.a[0])*d+(t[1]-i.a[1])*p,_=1e-9;if(!(u<=_||u>=h-_)&&Math.abs((t[0]-i.a[0])*p-(t[1]-i.a[1])*d)<=s+1e-9)return!0}return!1}(t.pointer,e.target,t.intervals,e.envelope,Math.max(1e-9,Math.min(t.baseTolerance,.04*t.gridStep)))),i=e.filter(e=>!!e.target.partitionHost&&t.renderedLength+2*e.target.physicalHalfWidth>e.length+1e-9).sort(Cg),s=e.filter(e=>!e.target.partitionHost||t.renderedLength+2*e.target.physicalHalfWidth<=e.length+1e-9).sort(Cg);let n=s[0];if(!n)return{candidate:null,jambBlockedTarget:i[0]?.target||null};const o=s.filter(t=>Math.abs(t.distance-n.distance)<=1e-9&&Math.abs(t.perpendicular-n.perpendicular)<=1e-9),r=o.filter(t=>t.target.partitionHost);if(r.length){if(1!==new Set(r.map(t=>t.target.partitionHost.id)).size||r.some(t=>t.target.ambiguousPartitionHost))return{candidate:null,jambBlockedTarget:null};const t=r[0],e=t.target.b[0]-t.target.a[0],i=t.target.b[1]-t.target.a[1],s=Math.hypot(e,i),a=e/s,l=i/s,c=o.every(e=>{const i=e.target.b[0]-e.target.a[0],s=e.target.b[1]-e.target.a[1],n=Math.hypot(i,s),o=i/n,r=s/n,c=Math.abs(a*r-l*o)<=1e-6,h=Math.abs((e.target.a[0]-t.target.a[0])*l-(e.target.a[1]-t.target.a[1])*a);return c&&h<=1e-9});if(!c)return{candidate:null,jambBlockedTarget:null};n=t}if(n.target.ambiguousPartitionHost)return{candidate:null,jambBlockedTarget:null};const{target:a,length:l}=n,c=a.b[0]-a.a[0],h=a.b[1]-a.a[1],d=c/l,p=h/l,u=a.partitionHost?a.physicalHalfWidth:0,_=Math.min(Math.max(0,t.renderedLength)/2+u,l/2);let g=n.along;const m=Math.max(t.gridStep,1e-9),f=l/2;g=Math.abs(g-f)<=m/2?f:Math.round(g/m)*m,g=Math.max(_,Math.min(l-_,g));const v=a.a[0]+d*g,y=a.a[1]+p*g,b=Math.max(0,t.renderedLength)/2,w=g-b,k=g+b,x=Math.max(0,w),$=Math.max(0,l-k),S=[a.a[0]+d*(w-x/2),a.a[1]+p*(w-x/2)],M=[a.a[0]+d*(k+$/2),a.a[1]+p*(k+$/2)];let C=180*Math.atan2(h,c)/Math.PI;C>=90?C-=180:C<-90&&(C+=180);const D=Math.abs(g-f)<=1e-9;return{candidate:{presetRevision:t.preset.revision,geometryRevision:t.geometryRevision,pointer:[t.pointer[0],t.pointer[1]],type:t.preset.type,lengthCm:t.preset.lengthCm,flipH:t.preset.flipH,flipV:t.preset.flipV,x:v,y:y,angle:C,renderedLength:t.renderedLength,target:a,...a.partitionHost?{host:{...a.partitionHost,t:l>0?g/l:0}}:{},measure:{labels:[{distance:x,midpoint:S},{distance:$,midpoint:M}],guide:D?{x:v,y:y,angle:C}:null}},jambBlockedTarget:null}}function Tg(t,e,i,s,n=1e-6){return t.presetRevision===i&&t.geometryRevision===s&&Math.hypot(t.pointer[0]-e[0],t.pointer[1]-e[1])<=n}const Pg=(t,e)=>t[0]*e[1]-t[1]*e[0],Rg=(t,e)=>t[0]*e[0]+t[1]*e[1],Ig=(t,e)=>[t[0]-e[0],t[1]-e[1]],Ag=(t,e,i)=>[t[0]+e[0]*i,t[1]+e[1]*i];function Fg(t,e,i){return Math.abs(Pg(t,e))<=i}function Eg(t,e,i){return Math.abs(Pg(Ig(t,e),i))}function zg(t,e,i,s,n){const o=e[0]-t[0],r=e[1]-t[1],a=Math.hypot(o,r);if(!(a>n&&i>0))return[];const l=[o/a,r/a];return function(t,e,i){const s=e.map(([e,i])=>[Math.max(0,Math.min(e,i)),Math.min(t,Math.max(e,i))]).filter(([t,e])=>e>t+i).sort((t,e)=>t[0]-e[0]||t[1]-e[1]),n=[];for(const t of s){const e=n[n.length-1];!e||t[0]>e[1]+i?n.push([...t]):e[1]=Math.max(e[1],t[1])}const o=[];let r=0;for(const[t,e]of n)t>r+i&&o.push([r,t]),r=Math.max(r,e);return t>r+i&&o.push([r,t]),o}(a,s.flatMap(e=>{const s=e.b[0]-e.a[0],o=e.b[1]-e.a[1],r=Math.hypot(s,o);if(!(r>n&&Fg(l,[s/r,o/r],1e-6)))return[];if(Eg(e.a,t,l)>1.1*Math.max(i,n)||Eg(e.b,t,l)>1.1*Math.max(i,n))return[];return[[Rg(Ig(e.a,t),l),Rg(Ig(e.b,t),l)]]}),n).flatMap(([e,s])=>{const n=Ba({a:Ag(t,l,e),b:Ag(t,l,s),halfDepth:i});return n?[n]:[]})}function Og(t){const e=t.coordScale??1,i=Math.max(t.epsilon??2e-4*t.gridPitch,1e-9),s=[];for(const i of t.rooms||[]){if(!i?.id)continue;const n=hl(t.rooms,i.id,t.walls,t.openCuts,t.pitch,t.cellCm,t.gridPitch,e);if(!n||n.poly.length<3)continue;const o=Qa(n.poly,n.offsets);!o||o.length<3||s.push({roomId:i.id,profile:n,inner:o})}s.sort((t,e)=>t.roomId.localeCompare(e.roomId));const n=(t.roomOpenings||[]).map(t=>{const e=t.angle*Math.PI/180,i=[Math.cos(e),Math.sin(e)],s=Math.max(0,t.length)/2;return{a:Ag([t.x,t.y],i,-s),b:Ag([t.x,t.y],i,s)}}),o=[];for(const s of Tl(t.rooms,t.walls,t.openCuts,t.pitch,t.cellCm,t.gridPitch,e))for(const t of zg(s.a,s.b,s.depthUnits/2,n,i))o.push({body:t});const r=new Map;for(const e of t.partitionCuts||[]){const t=r.get(e.hostId)||[];t.push(e),r.set(e.hostId,t)}for(const e of t.partitions||[]){const s=xa(e.cm,t.cellCm,t.gridPitch)/2;for(const t of zg(e.a,e.b,s,r.get(e.id)||[],i))o.push({body:t,partitionId:e.id})}return{rooms:s,boundaries:o,epsilon:i}}function Ng(t,e,i,s){const n=t.profile.offsets[e];if(!(n>0))return null;const o=function(t,e){const i=t[e],s=t[(e+1)%t.length],n=s[0]-i[0],o=s[1]-i[1],r=Math.hypot(n,o)||1;return function(t){let e=0;for(let i=0;i=0?[-o/r,n/r]:[o/r,-n/r]}(t.profile.poly,e),r=Ag(i.center,o,n),a=[];for(let e=0;es&&Fg(i.axis,[l[0]/c,l[1]/c],1e-6)))continue;if(Eg(n,r,i.axis)>s||Eg(o,r,i.axis)>s)continue;const h=Rg(Ig(n,r),i.axis),d=Rg(Ig(o,r),i.axis);a.push([Math.min(h,d),Math.max(h,d)])}const l=function(t,e){t.sort((t,e)=>t[0]-e[0]||t[1]-e[1]);const i=[];for(const s of t){const t=i[i.length-1];!t||s[0]>t[1]+e?i.push([...s]):t[1]=Math.max(t[1],s[1])}return i}(a,s).find(([t,e])=>t<=s&&e>=-s);if(!l)return null;const[c,h]=l,d=Ag(r,i.axis,-i.half),p=Ag(r,i.axis,i.half),u=Math.max(0,-i.half-c),_=Math.max(0,h-i.half),g=u>0?Ag(r,i.axis,c):d,m=_>0?Ag(r,i.axis,h):p,f=Rg(o,i.normal)>=0?1:-1,v=(e,s,n)=>({from:e,to:s,label:[(e[0]+s[0])/2,(e[1]+s[1])/2],axis:i.axis,labelNormal:o,distance:n,roomId:t.roomId,roomSide:f,source:"room-face"});return{left:v(d,g,u),right:v(p,m,_)}}function Hg(t){const e=Ag(t.center,t.axis,-t.half),i=Ag(t.center,t.axis,t.half),s=Ag(t.center,t.axis,Math.min(-t.half,t.targetLo)),n=Ag(t.center,t.axis,Math.max(t.half,t.targetHi)),o=(e,i)=>({from:e,to:i,label:[(e[0]+i[0])/2,(e[1]+i[1])/2],axis:t.axis,labelNormal:t.normal,distance:Math.hypot(i[0]-e[0],i[1]-e[1]),source:"host-end"});return[o(e,s),o(i,n)]}function Lg(t,e,i,s){const n=Ig(i,e),o=Rg(n,n);if(!(o>s*s))return Math.hypot(...Ig(t,e))<=s;const r=Rg(Ig(t,e),n)/o;if(r<-s||r>1+s)return!1;const a=Ag(e,n,Math.max(0,Math.min(1,r)));return Math.hypot(...Ig(t,a))<=s}function Bg(t,e,i){let s=!1;for(let n=0,o=e.length-1;nt[1]!=c>t[1]&&t[0]<(l-r)*(t[1]-a)/(c-a)+r&&(s=!s)}return s}function qg(t,e,i,s,n,o){const r=Ig(s,i),a=Pg(e,r);if(Math.abs(a)<=o)return null;const l=Ig(i,t),c=Pg(l,r)/a,h=Pg(l,e)/a;return c<-o||c>n+o||h<-o||h>1+o?null:Math.max(0,Math.min(n,c))}function Wg(t,e,i){const s=Hg(i),n="partition"===t.host?.kind?t.host.id:void 0;return[{base:s[0],direction:[-i.axis[0],-i.axis[1]]},{base:s[1],direction:i.axis}].map(({base:t,direction:i})=>{const s=t.distance,o=function(t,e,i,s,n,o){let r=null;for(const a of s)if(!n||a.partitionId!==n){if(Bg(t,a.body,o))return 0;for(let s=0;sRg(Ig(t,n),i));return{center:n,axis:i,normal:s,half:Math.max(0,t.renderedLength)/2,targetLo:Math.min(...o),targetHi:Math.max(...o)}}(t),s=e.rooms.flatMap(t=>{const s=function(t,e,i){const{profile:s}=t;let n=null;for(let t=0;t0))continue;const o=s.poly[t],r=s.poly[(t+1)%s.poly.length],a=Ig(r,o),l=Math.hypot(a[0],a[1]);if(!(l>i&&Fg(e.axis,[a[0]/l,a[1]/l],1e-6)))continue;if(Eg(o,e.center,e.axis)>i||Eg(r,e.center,e.axis)>i)continue;const c=Rg(Ig(o,e.center),e.axis),h=Rg(Ig(r,e.center),e.axis),d=Math.min(c,h),p=Math.max(c,h);if(d>-e.half+i||p0?d:p<0?-p:0);(!n||u2)return Hg(i);if(s.length){const t=s.map(({room:t,edge:s})=>Ng(t,s,i,e.epsilon));if(t.some(t=>!t))return Hg(i);const n=t;return[...n.map(t=>t.left),...n.map(t=>t.right)]}return Wg(t,e,i)}function Ug(t){return!(!t.canEdit||t.kiosk||t.fixedFloor)&&("view"!==t.mode&&("mouse"===t.pointerType&&t.spaceCount>1))}const Gg="1.67.0-beta.3",Vg={badge:"display.badge",icon_ripple:"display.icon_ripple",value:"display.value",static_icon:"display.static_icon"},Kg={badge:"marker.display_hint_badge",icon_ripple:"marker.display_hint_icon_ripple",value:"marker.display_hint_value",static_icon:"marker.display_hint_static_icon"},Yg=2e3,Xg=1e3,Jg=1500,Zg=t=>{const e=String(t??"").trim().replace(",",".");if(!/^[+-]?(?:\d+(?:\.\d*)?|\.\d+)$/.test(e))return null;const i=Number(e);return Number.isFinite(i)?i:null},Qg=(t,e)=>{if(!t.has(e))return{hit:!1};const i=t.get(e);return t.delete(e),t.set(e,i),{hit:!0,value:i}},tm=(t,e,i,s)=>{for(t.delete(e),t.set(e,i);t.size>s;){const e=t.keys().next().value;if(void 0===e)break;t.delete(e)}},em=new Map;let im=0;const sm=t=>`${window.innerWidth}x${window.innerHeight}|${location.pathname}|${JSON.stringify(t??{})}`;let nm=1e4;const om="houseplan_card_layout_v1",rm="houseplan_card_cfg_v1",am="houseplan_card_zoom_v1",lm="houseplan_card_nav_v1",cm="houseplan_card_kiosk_v1",hm="houseplan_card_view_v1",dm="hp-dialog, hp-help, hp-color-opacity, hp-device-preview",pm=1e3,um=[[0,1],[45,.88],[70,.62],[86,.32],[100,0]],_m=(t,e)=>{const i=Math.min(t.x,e.x),s=Math.min(t.y,e.y);return{x:i,y:s,w:Math.max(t.x+t.w,e.x+e.w)-i,h:Math.max(t.y+t.h,e.y+e.h)-s}},gm=new Set(["select","draw","column","merge","split","resize","opening","boundary","wallthick","delroom"]),mm=2e3,fm=(t,e,i)=>{const s=new Event(e,{bubbles:!0,composed:!0});s.detail=i??{},t.dispatchEvent(s)},vm=t=>{history.pushState(null,"",t),fm(window,"location-changed",{replace:!1})},ym=(t,e)=>{let i,s=null;const n=(...n)=>{clearTimeout(i),s=n,i=window.setTimeout(()=>{i=void 0;const e=s;s=null,e&&t(...e)},e)};return n.flush=()=>{if(void 0===i)return;clearTimeout(i),i=void 0;const e=s;s=null,e&&t(...e)},n.cancel=()=>{clearTimeout(i),i=void 0,s=null},n.pending=()=>void 0!==i,n},bm=t=>{try{t.target?.setPointerCapture?.(t.pointerId)}catch{}};class wm extends ht{constructor(){super(...arguments),this._space="f1",this._layout={},this._serverStorage=!1,this._loadOk=!1,this._serverCanWrite=null,this._loading=!1,this._loadTries=0,this._serverCfg=null,this._cfgRev=0,this._cfgContentFingerprint="",this._unsubCfg=null,this._unsubLayout=null,this._unsubVirtual=null,this._liveSyncAttempt=null,this._liveSyncGeneration=0,this._liveSyncConnection=null,this._layoutRev=0,this._layoutContentFingerprint="",this._virtualLights=gn(null),this._canOptimizeUndo=!1,this._undoKind=null,this._devices=[],this._regSignature="",this._defPos={},this._newSyncKey="",this._tip=null,this._hoverRoom=null,this._pointerModality=new Du(this,()=>this._syncPointerHoverTargets()),this._devicePressAnimations=new Map,this._selId=null,this._toast="",this._mode="view",this._pendingNavMode=null,this._decorTool="select",this._decorStyle={...oa},this._decorDraft=null,this._decorMove=null,this._decorSel=null,this._decorEraseConfirm=null,this._decorTextDialog=null,this._decorShapeDialog=null,this._backdropDialog=null,this._decorTextSelection={start:0,end:0},this._furnPalette=null,this._dtBox=null,this._dtDrag=null,this._bdDrag=null,this._slide="",this._reducedMotion=!1,this._onMotionChange=t=>{this._reducedMotion=t.matches,this._cancelDevicePressFeedback(),t.matches&&this._modeTransitionPreparing?this._modeTransitionForceAtomic=!0:t.matches&&this._modeTransition.active&&this._cancelModeTransition(!0),this.requestUpdate()},this._editorChromeMode="plan",this._modeTransitionVisual=null,this._modeTransitionPreparing=!1,this._modeTransitionForceAtomic=!1,this._modeTransitionRequest=0,this._modeTransitionTargetZoom=1,this._modeTransitionEditorCamera=null,this._modeTransition=new L_({frame:t=>this._applyModeTransitionFrame(t),settled:t=>this._settleModeTransition(t)}),this._editorSecondary=new Fu({root:()=>this.renderRoot,requestUpdate:()=>this.requestUpdate(),updateComplete:()=>this.updateComplete,clearTip:()=>{this._tip=null}}),this._editorSecondaryCopy={groupActive:(t,e)=>this._t("editor.group_active",{group:t,item:e}),openGroup:t=>this._t("editor.open_group",{group:t}),disabledAction:(t,e)=>this._t("editor.disabled_action",{action:t,reason:e})},this._tool="draw",this._geometryHistory=new C_(50),this._wallDialog=null,this._drawWallField=null,this._activeDraftId=null,this._resumeDraftBySpace={},this._physicalSel=null,this._physicalDialog=null,this._partitionDeleteDialog=null,this._roomDeleteDialog=null,this._physicalDrag=null,this._physicalRotate=null,this._physicalLastTap=null,this._physicalPickCycle=null,this._wallUnionCache=null,this._isoGeometryCache=new Map,this._isoFallback=new Set,this._openingTunnelCache=null,this._openingWallIndexCache=new Map,this._openingPlacementIntervalsCache=null,this._openingDimensionContextCache=null,this._planSnapGeometryCache=null,this._planStructuralGeometryCache=null,this._physicalBodiesCache=null,this._lightPhysicalBodiesCache=null,this._cleanFloorCache=new Map,this._glowClipCache=new Map,this._glowGeometryWarnings=new Set,this._lightBarrierCache=null,this._glowFeatherUnits=null,this._glowRenderedSources=new Map,this._glowLastAppearance=new Map,this._glowEnteringSources=new Set,this._glowEnterRafs=new Map,this._glowFadeTimers=new Map,this._glowFeatherSuspendUntil=0,this._glowFeatherResumeTimer=0,this._glowSourceSeq=0,this._glowScreenBlend=!1,this._duplicateColumnId=null,this._duplicateColumnTimer=0,this._rszSel=null,this._rszDrag=null,this._rszPreview=null,this._rszLive=null,this._path=[],this._cursorPt=null,this._planSnapHover=null,this._mergeSel=null,this._openingPreset=null,this._openingRebindId=null,this._openingPresetRevision=0,this._openingHoverCandidate=null,this._openingJambBlockCm=null,this._openingDialog=null,this._openingInfo=null,this._opDrag=null,this._opMeasure=null,this._mergeDialog=null,this._openWallAnchor=null,this._boundaryPointerType="mouse",this._boundaryRestoreGuard=null,this._boundaryTargetMemo=null,this._boundaryPreviewMemo=null,this._splitSel=null,this._pendingSplit=null,this._wallFaceBatch=null,this._wallRepairDiagnostic=null,this._wallFaceGraphCache=[],this._areaSel="",this._nameSel="",this._roomDialog=!1,this._roomEditId=null,this._roomFill="",this._roomCustomFill=null,this._roomTempSrc="",this._roomHumSrc="",this._roomSrcOpen=null,this._roomSrcFilter="",this._roomNameScale=1,this._roomLabelScale=1,this._zoom=1,this._view=null,this._zoomBySpace={},this._viewModeSnap=null,this._pointers=new Map,this._panStart=null,this._panLock=null,this._pinchStart=null,this._suppressClick=!1,this._touchContacts=new Map,this._touchSequenceMultitouch=!1,this._touchClickBlockUntil=0,this._connectedPath="",this._routeDepartureHandled=!1,this._onLocationChanged=()=>{this._connectedPath&&location.pathname!==this._connectedPath?this._leaveCardRoute():location.pathname===this._connectedPath&&(this._routeDepartureHandled=!1)},this._touchGestureGuard={capture:!0,handleEvent:t=>this._guardTouchGesture(t)},this._hdrH=118,this._booting=!0,this._bootFading=!1,this._bootSettling=!1,this._bootSettleRaf=0,this._bootLastH=-1,this._bootStart=0,this._bootLastChange=0,this._bootSoft=!1,this._tapConfirm=null,this._onboardingShown=!1,this._rulesDialog=null,this._alignDialog=null,this._settingsDialog=null,this._backupExportDialog=null,this._backupImportDialog=null,this._sunRaysCache=null,this._dayCycleTimer=0,this._dayCycleClockKey="",this._compassDrag=!1,this._importDialog=null,this._importQueue=[],this._importTotal=0,this._rulesCompiledSrc="",this._infoCard=null,this._nativeMoreInfoEntity=null,this._markerDialog=null,this._spaceDialog=null,this._keyHandler=t=>this._onKey(t),this._warmVp=null,this._warmVpArmed=!1,this._warmLongReturn=!1,this._warmRevivePending=!1,this._warmGen=++im,this._warmKey=null,this._warmSlot=null,this._hashApplied=!1,this._navApplied=!1,this._labs={active:Object.freeze([]),space:""},this._viewPreference={},this._renderProjection="flat",this._kioskScale={icon:1,font:1},this._kioskDialog=!1,this._activityRt=new Map,this._vacRt=new Map,this._vacViewKey="",this._vacLastView=null,this._vacRaf=0,this._vacSrvTrails={},this._vacJumpOnce=!1,this._continuity=this._newContinuityController(),this._continuityHistory=[],this._continuityEpoch=0,this._continuityDataReady=!0,this._continuityPaintToken=-1,this._continuityDisposed=!1,this._renderSnapshotAt=Date.now(),this._hassSequence=0,this._visibleDeviceSnapshot=null,this._candidateDeviceSnapshot=null,this._stagedDeviceSnapshotToken=-1,this._capturedSnapshotSequence=-1,this._capturedSnapshotDevices=null,this._capturedSnapshotLayout=null,this._capturedSnapshotActivity="",this._capturedSnapshotConfigEpoch=-1,this._capturedSnapshotVirtual="",this._lastValidStageSize=null,this._pendingRefitSize=null,this._refitRaf=0,this._pageVisibility=t=>{if(this._continuity.visibility(t),this._dayCycleVisibility(t),"hidden"===t.kind)return this._clearTransientHover(!0),this._cancelDevicePressFeedback(),void(this._modeTransitionPreparing?this._modeTransitionForceAtomic=!0:this._cancelModeTransition(!0));if(this._vacJumpOnce=!0,!t.long){const t=Date.now();let e=!1;for(const i of this._activityRt.values())!i.flashKind||(i.expiresAt||i.flashTs+xu)>t||(i.flashTs=0,i.flashKind=null,i.expiresAt=0,e=!0);return void(e&&this.requestUpdate())}Date.now()-this._renderSnapshotAt>1e3&&this._continuity.note("device-snapshot-stale"),this._continuityDataReady=!1,this._continuityPaintToken=-1,this._resumeSettling=!0,this._loading?this.requestUpdate():this._loadFromServer()},this._resumeSettling=!1,this._viewportInvalidAt=0,this._vacFit=null,this._vacAllCamerasFor=null,this._vacAllCameraCache=null,this._vacCalConfirm=null,this._kioskDots=!1,this._cyclePausedUntil=0,this._swipeStart=null,this._tabDrag=null,this._tabDragRelease=null,this._tabSuppressClick=!1,this._tabOrderWarned=!1,this._lastTap=0,this._onLabsSnapshot=t=>{const e=this._effectiveProjection();this._labs=t;const i=this._effectiveProjection();this._convertProjectionView(e,i),this.requestUpdate()},this._onHashChange=()=>{if(this._hasFixedFloor)return;const t=this._hashSpace();if(t&&this._model.find(e=>e.id===t)&&t!==this._space){if(this._wallFaceBatch&&this._roomDialogCancel(),"plan"===this._mode&&"draw"===this._tool&&!this._finishWallChain())return;this._activeDraftId&&(this._resumeDraftBySpace[this._space]=this._activeDraftId),this._commitSpace(t),this._selId=null,this._path=[],this._clearPlanSnapHover(),this._clearOpeningPlacement(!0),this._tool="draw",this._openWallAnchor=null,this._boundaryRestoreGuard=null,this._activeDraftId=null,this._draftSegmentCms=[],this._closingWallCm=null,"plan"===this._mode&&"draw"===this._tool&&this._resumeLastDraft(),this._restoreZoom(),this.requestUpdate()}},this._drag=null,this._rlResize=null,this._holdFired=!1,this._retryContinuity=()=>{this._continuityDataReady=!1,this._continuityPaintToken=-1,this._continuity.retry(this._continuity.recoveryReason||"plan"),this._loading||this._loadFromServer()},this._cfgEpoch=0,this._modelCache=null,this._emptySpaceStateActive=!1,this._decorSnapCache=null,this._markerPreviewMemo=null,this._markerPreviewDevicesMemo=null,this._showHidden=!1,this._connHooked=null,this._connectionWasLost=!1,this._haRegistryConnection=null,this._haRegistryRev=-1,this._haBindingCacheKey="",this._planHassMemo=null,this._onHaRegistryUpdate=()=>{const t=An(this.hass);t.revision===this._haRegistryRev&&this._devices.length||(this._haRegistryRev=t.revision,this._planHassMemo=null,this._regSignature="",this._maybeRebuildDevices(),this.requestUpdate())},this._onConnReady=()=>{if(this._loadTries=0,clearTimeout(this._loadRetryTimer),this._loadRetryTimer=void 0,function(t){const e=Cn(t);e&&(Pn(t,e),Rn(t,e))}(this.hass),this._saveConfigDebounced.pending()&&this._saveConfigDebounced.flush(),this._cfgWriting)return clearTimeout(this._reloadRetry),void(this._reloadRetry=window.setTimeout(this._onConnReady,400));!this._connectionWasLost&&this._continuity.hasCompleteFrame?this._beginContinuityCandidate("connection-ready",!1,"plan"):(this._continuityDataReady=!1,this._continuityPaintToken=-1),this._loading||this._loadFromServer()},this._onConnLost=()=>{this._booting&&!this._continuity.hasCompleteFrame||(this._connectionWasLost=!0,this._continuityDataReady=!1,this._continuityPaintToken=-1,this._continuity.connectionLost())},this._signer=new Ph(()=>this.requestUpdate()),this._dirtyPos=new Set,this._sentPos=new Map,this._persistLayout=ym(()=>{if(this._serverStorage){const t=[...this._dirtyPos];this._dirtyPos.clear();for(const e of t){const t=Xu(this._layout[e]);t&&(this._layout={...this._layout,[e]:t},this._sentPos.set(e,t),this.hass.callWS({type:"houseplan/layout/update",device_id:e,pos:t}).then(t=>this._noteLayoutRev(t)).catch(t=>this._showToast(this._t("toast.pos_save_failed",{err:this._errText(t)}))).finally(()=>{this._sentPos.get(e)===t&&this._sentPos.delete(e)}))}this._cacheSnapshot()}else this._layout=Ju(this._layout),localStorage.setItem(om,JSON.stringify(this._layout))},600),this._frame=null,this._showFar=!1,this._writesPending=0,this._writeChain=Promise.resolve(),this._undoGeometry=()=>{if(this._cancelBoundaryAnchor())return;if(this._physicalDrag||this._physicalRotate)return void this._cancelPhysicalGesture();if(this._decorDraft)return this._decorDraft=null,void this.requestUpdate();if(this._decorMove||this._dtDrag||this._bdDrag)return void this._cancelDecorGesture();if(this._rszDrag)return void this._rszCancelDrag();const t=this._geometryHistory.undo();t&&(this._applyGeometryState(t.before)?this._showToast(this._t("history.undone",{name:t.name})):this._geometryHistory.clear())},this._redoGeometry=()=>{if(this._cancelBoundaryAnchor())return;if(this._physicalDrag||this._physicalRotate)return void this._cancelPhysicalGesture();if(this._decorDraft)return this._decorDraft=null,void this.requestUpdate();if(this._decorMove||this._dtDrag||this._bdDrag)return void this._cancelDecorGesture();if(this._rszDrag)return void this._rszCancelDrag();const t=this._geometryHistory.redo();t&&(this._applyGeometryState(t.after)?this._showToast(this._t("history.redone",{name:t.name})):this._geometryHistory.clear())},this._saveConfigDebounced=ym(()=>{this._serverCfg&&this._writeConfig().catch(t=>{"conflict"===t?.code?(this._showToast(this._t("toast.conflict")),this._cancelPath(),this._reloadConfigOnly(!0)):this._showToast(this._t("toast.cfg_save_failed",{err:this._errText(t)}))})},500),this._draftSegmentCms=[],this._closingWallCm=null,this._savePhysicalDialog=()=>{const t=this._physicalDialog,e=this._curSpaceCfg,i=this._spaceModel();if(!t||!e||!i)return;const s=Zg(t.cm);if(null==s)return void this._showPhysicalRange("column"===t.kind?Hl:100);const n=this._imperial?2.54*s:s,o="column"===t.kind?Hl:100;if(!Number.isFinite(n)||n<1||n>o)return void this._showPhysicalRange(o);if("column"===t.kind){const e=i.wall_columns.find(e=>e.id===t.id);if(!e)return;const s=Zg(t.angle||"0");if("circle"!==t.shape&&(null==s||s<0||s>=90))return void this._showToast(this._t("toast.physical_angle"));const o="circle"===t.shape?{id:t.id,shape:"circle",center:e.center,cm:n}:{id:t.id,shape:"square",center:e.center,cm:n,angle:s};if(i.wall_columns.some(e=>e.id!==t.id&&rc(e,o,.02*this._gridPitch)))return void this._showToast(this._t("toast.column_duplicate"))}const r=this._geometrySnapshot();if("partition"===t.kind){const i=(e.partitions||[]).find(e=>e.id===t.id);i&&(i.cm=n)}else if("column"===t.kind){const i=(e.wall_columns||[]).find(e=>e.id===t.id);i&&(i.cm=Bl(n),i.shape="circle"===t.shape?"circle":"square","square"===i.shape?i.angle=Zg(t.angle||"0"):delete i.angle)}else{const i=(e.room_drafts||[]).find(e=>e.id===t.id);i?.segments?.[t.segment||0]&&(i.segments[t.segment||0].cm=n)}this._recordGeometry(this._t("history.physical_edit"),r),this._physicalDialog=null,this._saveConfig()},this._deletePhysicalSelection=()=>{const t=this._physicalSel,e=this._curSpaceCfg;if(!t||!e)return;if("draft"===t.kind)return void this._deleteDraftWhole();const i=this._geometrySnapshot();if("partition"===t.kind){const i=(e.openings||[]).filter(e=>"partition"===e.host?.kind&&e.host.id===t.id).sort((t,e)=>(t.host?.t||0)-(e.host?.t||0));if(i.length)return void(this._partitionDeleteDialog={id:t.id,openings:i.map(t=>JSON.parse(JSON.stringify(t)))})}const s="partition"===t.kind?"partitions":"column"===t.kind?"wall_columns":"room_drafts";e[s]=(e[s]||[]).filter(e=>e.id!==t.id),e[s].length||delete e[s],this._activeDraftId===t.id&&this._cancelPath(),this._physicalSel=null,this._physicalDialog=null,this._recordGeometry(this._t("history.physical_delete"),i),this._saveConfig()},this._confirmPartitionDelete=()=>{const t=this._partitionDeleteDialog,e=this._curSpaceCfg;if(!t||!e)return;const i=this._geometrySnapshot();e.partitions=(e.partitions||[]).filter(e=>e.id!==t.id),e.partitions.length||delete e.partitions,e.openings=(e.openings||[]).filter(e=>"partition"!==e.host?.kind||e.host.id!==t.id),e.openings.length||delete e.openings,this._partitionDeleteDialog=null,this._physicalSel=null,this._physicalDialog=null,this._recordGeometry(this._t("history.physical_delete"),i),this._saveConfig()},this._deleteDraftWhole=()=>{const t="draft"===this._physicalDialog?.kind?this._physicalDialog.id:"draft"===this._physicalSel?.kind?this._physicalSel.id:null,e=this._curSpaceCfg;if(!t||!e||!confirm(this._t("confirm.delete_draft")))return;const i=this._geometrySnapshot();e.room_drafts=(e.room_drafts||[]).filter(e=>e.id!==t),e.room_drafts.length||delete e.room_drafts,this._activeDraftId===t&&this._cancelPath(),this._physicalSel=null,this._physicalDialog=null,this._recordGeometry(this._t("history.physical_delete"),i),this._saveConfig()},this._deleteDraftSegment=()=>{const t=this._physicalDialog,e=this._curSpaceCfg;if(!t||"draft"!==t.kind||!e)return;if(!confirm(this._t("confirm.delete_draft_segment")))return;const i=(e.room_drafts||[]).findIndex(e=>e.id===t.id);if(i<0)return;const s=e.room_drafts[i],n=Math.max(0,Math.min(s.segments.length-1,t.segment||0)),o=[],r=s.points.slice(0,n+1),a=s.points.slice(n+1);if(r.length>=2&&o.push({id:s.id,points:r,segments:s.segments.slice(0,n)}),a.length>=2&&o.push({id:o.length?`${s.id}-${Date.now().toString(36)}`:s.id,points:a,segments:s.segments.slice(n+1)}),2===o.length&&e.room_drafts.length>=200)return void this._showToast(this._t("toast.physical_limit"));const l=this._geometrySnapshot();e.room_drafts.splice(i,1,...o),e.room_drafts.length||delete e.room_drafts,this._activeDraftId===s.id&&this._cancelPath(),this._physicalDialog=null,this._physicalSel=o.length?{kind:"draft",id:o[0].id}:null,this._recordGeometry(this._t("history.draft_segment_delete"),l),this._saveConfig()},this._confirmRoomDelete=t=>{const e=this._roomDeleteDialog,i=this._curSpaceCfg,s=this._spaceModel();if(!e||!i||!s)return;const n=s.rooms.find(t=>t.id===e.roomId);if(!n)return void(this._roomDeleteDialog=null);const o=this._openCuts(),r=Mp(dl(s.rooms,this._spaceWalls,o,this._wallKeyPitch,this._cellCm,this._gridPitch,pm).filter(t=>t.roomId===n.id),s.partitions,this._openingsR.map(t=>({...t,x:t.rx,y:t.ry})),.02*this._gridPitch),a=new Set(r.materialize.filter(t=>!t.reusePartitionId).map(t=>t.interval.key)).size;if(t&&(i.partitions||[]).length+a>mm)return void this._showToast(this._t("toast.physical_limit"));const l=this._geometrySnapshot(),c=pl(s.rooms,this._spaceWalls,o,this._wallKeyPitch,this._cellCm,this._gridPitch,pm);if(t){i.partitions||=[];const t=new Map,e=new Map,s=Date.now().toString(36);for(const n of r.materialize){let o=n.reusePartitionId?i.partitions.find(t=>t.id===n.reusePartitionId):e.get(n.interval.key);o||(o={id:`partition-room-${s}-${e.size}`,a:[n.interval.a[0]/pm,n.interval.a[1]/pm],b:[n.interval.b[0]/pm,n.interval.b[1]/pm],cm:n.interval.cm},i.partitions.push(o),e.set(n.interval.key,o)),t.set(n.interval.key,o)}for(const e of i.openings||[]){const i=r.openingIntervals.get(e.id),s=i?t.get(i):null,n=this._openingsR.find(t=>t.id===e.id);if(!s||!n)continue;const o={a:[s.a[0]*pm,s.a[1]*pm],b:[s.b[0]*pm,s.b[1]*pm]};e.host={kind:"partition",id:s.id,t:Cp([n.rx,n.ry],o)}}}else if(r.removeOpeningIds.length){const t=new Set(r.removeOpeningIds);i.openings=(i.openings||[]).filter(e=>!t.has(e.id)),i.openings.length||delete i.openings}i.rooms=i.rooms.filter(t=>t.id!==n.id),this._cfgEpoch++,this._commitOpenSpans();const h=this._normalizeWalls(c,this._openCuts());h.length?i.walls=h:delete i.walls,this._roomDeleteDialog=null,this._recordGeometry(this._t(t?"history.delete_room_keep_walls":"history.delete_room_with_walls"),l),this._saveConfig(),this._regSignature="",this._maybeRebuildDevices(),this.requestUpdate()},this._rebindPartitionOpening=()=>{const t=this._openingDialog;if(!t?.id)return;const e=t.id;this._activateMarkupTool("opening"),"opening"===this._tool&&(this._openingRebindId=e,this._openingPreset={type:t.type,lengthCm:t.lengthCm,flipH:t.flipH,flipV:t.flipV,revision:++this._openingPresetRevision},this._openingDialog=null,this._openingHoverCandidate=null)},this._keepClosedAsPartitions=()=>{if(this._wallFaceBatch)return void this._decideWallFace(!1);if(!this._contourClosed||this._pendingSplit||!this._curSpaceCfg)return;const t=this._curSpaceCfg,e=this._path.slice(0,-1);if((t.partitions||[]).length+e.length>mm)return void this._showToast(this._t("toast.physical_limit"));const i=this._geometrySnapshot(),s=Qd(e.length,[...this._draftSegmentCms,this._closingWallCm??void 0],this._drawWallCm,fa);t.partitions||=[];const n=Date.now().toString(36);for(let i=0;it.id!==this._activeDraftId),t.room_drafts.length||delete t.room_drafts),this._recordGeometry(this._t("history.contour_to_partitions"),i),this._saveConfig(),this._roomDialog=!1,this._path=[],delete this._resumeDraftBySpace[this._space],this._activeDraftId=null,this._draftSegmentCms=[],this._closingWallCm=null},this._toggleServerPlans=async()=>{const t=this._spaceDialog;if(t)if(t.pickSaved)this._spaceDialog={...t,pickSaved:!1};else{this._spaceDialog={...t,pickSaved:!0,savedBusy:!0};try{const t=await this.hass.callWS({type:"houseplan/plans/list"}),e=this._spaceDialog;e&&(this._spaceDialog={...e,saved:t?.plans||[],savedBusy:!1})}catch(t){const e=this._spaceDialog;e&&(this._spaceDialog={...e,saved:[],savedBusy:!1}),this._showToast(this._t("toast.plans_list_failed",{err:this._errText(t)}))}}},this._aspectJob=null,this._dayCycleTick=()=>{if(!this.isConnected||"hidden"===this.ownerDocument.visibilityState)return;const t=this._dayCycleState();if(!t)return this._dayCycleTimer&&(clearInterval(this._dayCycleTimer),this._dayCycleTimer=0),void(this._dayCycleClockKey="");const e=Wr(t);e!==this._dayCycleClockKey&&(this._dayCycleClockKey=e,this.requestUpdate())},this._sunShown=!1,this._sunOut=!1,this._sunOutTimer=0,this._openSettingsDialog=()=>{if(!this._norm)return;const t=this._glowRadiusCm,e=this._imperial?Math.round(t/30.48*10)/10:Math.round(t)/100;this._settingsDialog={colors:JSON.parse(JSON.stringify(this._fillColors)),glowRadius:e,bgColor:hs(this._settings,{bgColor:null})||null,northDeg:Zr(this._settings,{}),bgMode:Qr(this._settings,{}),sunRays:ta(this._settings,{}),busy:!1}},this._openAlignDialog=()=>{if(!this._norm||!this._serverCfg)return;const t=this._serverCfg.spaces||[],e=Object.fromEntries(this._devices.filter(t=>!t.virtual&&!!t.area).map(t=>[t.id,t.area])),i=v_(this._serverCfg,this._layout||{},{effectiveAreaByMarker:e}),s=i.changed?this._checkOptimizeGeometry(i.config):null,n=Math.ceil(10*i.report.maxShiftCm)/10,o=t.find(t=>null!=t?.id&&String(t.id)===i.report.maxSpace),r=t.length>1&&o?String(o.title||o.id):"";this._alignDialog={report:i.report,config:i.config,layout:i.layout,cm:n,where:r,preflight:s,changed:i.changed,busy:!1}},this._optimizeUndoBusy=!1,this._openBackupExport=()=>{this._settingsDialog=null,this._backupExportDialog={kind:"full",planOnly:!1,busy:!1,error:""}},this._openRulesDialog=()=>{if(!this._norm)return;const t=this._settings.icon_rules,e=(t&&t.length?t:Xt).map(t=>({...t}));this._rulesDialog={rules:e,test:"",busy:!1}},this._climateCache=null,this._gearPtCache=new WeakMap}get _canEdit(){return!!this._norm&&(!0===this._serverCanWrite||!1!==this._serverCanWrite&&!0===this.hass?.user?.is_admin)}get _kiosk(){return!!this._config?.kiosk}_showKioskDots(){this._kioskDots=!0,clearTimeout(this._kioskDotsTimer),this._kioskDotsTimer=window.setTimeout(()=>this._kioskDots=!1,2500)}get _modeTransitionBusy(){return this._modeTransitionPreparing||this._modeTransition.active}_cssColor(t,e){const i=String(t||"").trim();if(!i)return e;const s=document.createElement("span");s.style.cssText=`position:absolute;visibility:hidden;color:${i}`,this.renderRoot.append(s);const n=getComputedStyle(s).color||e;return s.remove(),n}_currentModeVisual(t=this._mode){const e=this._modeTransition.presented||this._modeTransitionVisual;if(e)return{...e,viewport:{...e.viewport,viewBox:{...e.viewport.viewBox}}};const i=this._stageEl;if(!i||i.clientWidth<=0||i.clientHeight<=0)return null;const s=this.renderRoot.querySelector(".editorchrome"),n=this._viewOr(this._baseVb()),o=this.renderRoot.querySelector(".hp-paper"),r=this.renderRoot.querySelector(".hp-backdrop"),a=this.renderRoot.querySelector(".zoomwrap"),l=a?getComputedStyle(a).filter:"",c=Number(/brightness\(([^)]+)\)/.exec(l)?.[1]);return{presentedMode:t,editorChromeHeight:"view"===t?0:s?.getBoundingClientRect().height||0,stageWidth:i.clientWidth,stageHeight:i.clientHeight,viewport:E_(n,i.clientWidth),stageColor:getComputedStyle(i).backgroundColor||"rgb(255, 255, 255)",paperColor:o?getComputedStyle(o).fill:"rgb(255, 255, 255)",sceneBrightness:Number.isFinite(c)?c:1,architectureOpacity:"decor"===t?.35:1,backdropOpacity:r&&Number(getComputedStyle(r).opacity)||1,viewWeight:"view"===t?1:0,editorWeight:"view"===t?0:1,toolbarContentOpacity:"view"===t?0:1}}_viewForModeTarget(t,e,i,s,n){const o=Oi(this._baseVb(),s/Math.max(1,n)),r=Math.min(wm.ZOOM_MAX,Math.max(wm.ZOOM_MIN,t)),a=o.w/r,l=o.h/r,c=e??o.x+o.w/2,h=i??o.y+o.h/2;return this._clampView({x:c-a/2,y:h-l/2,w:a,h:l},o)}_targetStageColor(t){return"view"!==t?"rgb(255, 255, 255)":this._cssColor(this._stageBg(this._spaceDisplayForRender()),this._cssColor("var(--ha-card-background, var(--card-background-color, #111))","rgb(17, 17, 17)"))}_targetPaperColor(t){return"view"===t&&this._spaceModel()?.bg?this._cssColor("var(--ha-card-background, var(--card-background-color, #111))","rgb(17, 17, 17)"):"rgb(255, 255, 255)"}_targetBrightness(t){return 1}_applyModeTransitionFrame(t){t.targetMode===this._mode&&(this._modeTransitionVisual=t.presented,this._view={...t.presented.viewport.viewBox},this.requestUpdate())}_settleModeTransition(t){if(t.targetMode!==this._mode)return;const e=this._modeTransitionRequest;this._view={...t.to.viewport.viewBox},this._zoom=this._modeTransitionTargetZoom,this._modeTransitionVisual=null,this._modeTransitionPreparing=!1,this._lastValidStageSize=[t.to.stageWidth,t.to.stageHeight],"view"===this._mode&&(this._saveZoom(),this._viewModeSnap=null,this._modeTransitionEditorCamera=null),this.requestUpdate(),this.updateComplete.then(()=>{if(!this.isConnected||e!==this._modeTransitionRequest||this._modeTransitionBusy||t.targetMode!==this._mode)return;const i=this._stageEl;if(i&&i.clientWidth>0&&i.clientHeight>0&&(Math.abs(i.clientWidth-t.to.stageWidth)>.5||Math.abs(i.clientHeight-t.to.stageHeight)>.5)){const t=this._view;this._lastValidStageSize=[i.clientWidth,i.clientHeight],this._applyView(this._zoom,t?t.x+t.w/2:void 0,t?t.y+t.h/2:void 0),this.requestUpdate()}const s=this.renderRoot.activeElement;(!s||!s.isConnected||!!s.closest?.(".editorchrome, .stage"))&&this.renderRoot.querySelector(".modetab.active")?.focus?.({preventScroll:!0})})}_cancelModeTransition(t=!0){const e=!!this._modeTransition.state;this._modeTransitionRequest++,this._modeTransitionPreparing=!1,this._modeTransitionForceAtomic=!1,this._modeTransition.cancel(t),t&&e||(this._modeTransitionVisual=null)}_adoptMode(t){this._cancelModeTransition(!1),this._mode=t,"view"!==t&&(this._editorChromeMode=t)}_commitViewModeAtomic(t,e,i,s){if(this._modeTransitionPreparing=!1,this._modeTransitionVisual=null,this._modeTransitionForceAtomic=!1,this._zoom=e,t){const n=this._stageEl?.clientWidth||t.stageWidth,o=Math.max(1,t.stageHeight+t.editorChromeHeight);this._view=this._viewForModeTarget(e,i,s,n,o),this._lastValidStageSize=[n,o]}else this._view=null;this._viewModeSnap=null,this._modeTransitionEditorCamera=null,this._saveZoom(),this.requestUpdate()}_prepareModeTransition(t,e,i,s,n,o){this.updateComplete.then(()=>{if(!this.isConnected||t!==this._modeTransitionRequest||this._mode!==i)return void(t===this._modeTransitionRequest&&(this._modeTransitionPreparing=!1,this._modeTransitionVisual=null,this._modeTransitionForceAtomic=!1,this.requestUpdate()));const r=this.renderRoot.querySelector(".editorchrome"),a=r?.querySelector(".editorchrome-inner"),l="view"===i?0:a?.scrollHeight||a?.getBoundingClientRect().height||0,c=Math.max(1,e.stageHeight+e.editorChromeHeight),h=Math.max(1,c-l),d=this._stageEl?.clientWidth||e.stageWidth;if(d<=0||h<=0)return this._modeTransitionPreparing=!1,this._modeTransitionVisual=null,this._applyView(s,n,o),void this.requestUpdate();const p=this._viewForModeTarget(s,n,o,d,h),u={presentedMode:i,editorChromeHeight:l,stageWidth:d,stageHeight:h,viewport:E_(p,d),stageColor:this._targetStageColor(i),paperColor:this._targetPaperColor(i),sceneBrightness:this._targetBrightness(i),architectureOpacity:"decor"===i?.35:1,backdropOpacity:"decor"===i&&"backdrop"!==this._decorTool?.5:1,viewWeight:"view"===i?1:0,editorWeight:"view"===i?0:1,toolbarContentOpacity:"view"===i?0:1};this._modeTransitionPreparing=!1;const _=this._modeTransitionForceAtomic;this._modeTransitionForceAtomic=!1,this._modeTransition.start(e,u,i,this._reducedMotion||_?0:220)})}get _hasFixedFloor(){return!!this._config&&Object.prototype.hasOwnProperty.call(this._config,"floor")}_fixedFloorState(t=this._model,e=this._loadOk){const i=this._config?.floor,s=function(t){if(!t.hasFloor)return{kind:"absent"};const e=t.floor;if("string"==typeof e)return e.length?t.spaceIds.includes(e)?{kind:"valid",id:e,source:"id"}:{kind:"invalid",reason:"unknown-id",value:e}:{kind:"invalid",reason:"empty-id",value:e};if("number"==typeof e){if(!Number.isFinite(e))return{kind:"invalid",reason:"non-finite-index",value:e};if(!Number.isInteger(e))return{kind:"invalid",reason:"fractional-index",value:e};if(e<0)return{kind:"invalid",reason:"negative-index",value:e};const i=t.spaceIds[e];return void 0===i?{kind:"invalid",reason:"out-of-range-index",value:e}:{kind:"valid",id:i,source:"index"}}return{kind:"invalid",reason:"invalid-type",value:e}}({spaceIds:t.map(t=>t.id),hasFloor:this._hasFixedFloor,floor:i});return!this._hasFixedFloor||e?s:"number"==typeof i?"valid"===s.kind||"invalid"===s.kind&&"out-of-range-index"===s.reason?{kind:"pending",value:i}:s:"valid"===s.kind||"invalid"===s.kind&&"unknown-id"!==s.reason?s:{kind:"pending",value:i}}_canCommitSpace(t,e=!1){if(e||!this._hasFixedFloor)return!0;const i=this._fixedFloorState();return"valid"===i.kind&&i.id===t}_commitSpace(t,e=!1){return!!this._canCommitSpace(t,e)&&(t!==this._space&&(this._clearTransientHover(!0),this._cancelDevicePressFeedback()),this._space=t,!0)}_slideTo(t,e){if(t===this._space)return!0;if(!this._canCommitSpace(t))return!1;if(this._wallFaceBatch&&this._roomDialogCancel(),"plan"===this._mode&&"draw"===this._tool&&!this._finishWallChain())return!1;this._cancelModeTransition(!0);const i=window.matchMedia?.("(prefers-reduced-motion: reduce)")?.matches;return this._activeDraftId&&(this._resumeDraftBySpace[this._space]=this._activeDraftId),this._commitSpace(t),this._path=[],this._clearPlanSnapHover(),this._clearOpeningPlacement(!0),this._tool="draw",this._openWallAnchor=null,this._boundaryRestoreGuard=null,this._activeDraftId=null,this._draftSegmentCms=[],this._closingWallCm=null,this._selId=null,this._physicalSel=null,this._editorSecondary.closeForNavigation(),this._physicalDialog=null,this._physicalDrag=null,"plan"===this._mode&&"draw"===this._tool&&this._resumeLastDraft(),this._restoreZoom(),i||(this._slide=e,clearTimeout(this._slideTimer),this._slideTimer=window.setTimeout(()=>{this._slideTimer=void 0,this._slide="",this.requestUpdate()},190),this.requestUpdate()),!0}get _canReorderTabs(){return Ug({canEdit:this._canEdit,kiosk:this._kiosk,mode:this._mode,pointerType:"mouse",spaceCount:this._model.length,fixedFloor:this._hasFixedFloor})}_tabPointerDown(t,e){Ug({canEdit:this._canEdit,kiosk:this._kiosk,mode:this._mode,pointerType:t.pointerType,spaceCount:this._model.length,fixedFloor:this._hasFixedFloor})&&(bm(t),this._tabDragRelease=t=>this._tabPointerUp(t),window.addEventListener("pointerup",this._tabDragRelease),window.addEventListener("pointercancel",this._tabDragRelease),this._tabDrag={id:e,pointerId:t.pointerId,x:t.clientX,y:t.clientY,moved:!1,targetId:null,placement:null})}_tabDropTargetAt(t,e,i){const s=this._model.map(t=>t.id),n=s.indexOf(i);if(n<0)return null;const o=this.renderRoot.querySelectorAll('[data-hp="space-tab"]');for(const r of o){const o=r.dataset.id||"";if(!o||o===i)continue;const a=r.getBoundingClientRect();if(ta.right||ea.bottom)continue;const l=s.indexOf(o);return l<0?null:{targetId:o,placement:l=4)))return;var i,s;const n=this._tabDropTargetAt(t.clientX,t.clientY,e.id);e.moved&&e.targetId===n?.targetId&&e.placement===n?.placement||(this._tabDrag={...e,moved:!0,targetId:n?.targetId||null,placement:n?.placement||null})}_tabPointerUp(t){const e=this._tabDrag;if(e&&e.pointerId!==t.pointerId)return;const i="pointerup"===t.type&&e?.moved?this._tabDropTargetAt(t.clientX,t.clientY,e.id):null;"pointerup"===t.type&&e?.moved&&this._suppressNextTabClick(),this._endTabDrag(),e?.moved&&i&&this._commitTabOrder(e.id,i.targetId)}_endTabDrag(){this._tabDrag=null,this._tabDragRelease&&(window.removeEventListener("pointerup",this._tabDragRelease),window.removeEventListener("pointercancel",this._tabDragRelease),this._tabDragRelease=null)}_tabClick(t){if(this._tabSuppressClick)return this._tabSuppressClick=!1,clearTimeout(this._tabSuppressClickTimer),void(this._tabSuppressClickTimer=void 0);this._pickSpace(t)}_suppressNextTabClick(){this._tabSuppressClick=!0,clearTimeout(this._tabSuppressClickTimer),this._tabSuppressClickTimer=window.setTimeout(()=>{this._tabSuppressClick=!1,this._tabSuppressClickTimer=void 0},0)}_commitTabOrder(t,e){const i=this._serverCfg;if(!i||!this._canReorderTabs)return;const s=this._model.map(t=>t.id),n=function(t,e,i){const s=t.indexOf(e),n=t.indexOf(i);if(s<0||n<0||s===n)return t;const o=t.slice();return o.splice(s,1),o.splice(n,0,e),o}(s,t,e);if(n===s)return;const o=new Map(this._devices.map(t=>[String(t.id),String(t.area||"")])),r=function(t,e,i,s=()=>""){if(!i)return[];const n=[];for(const o of t){if(!o||!0===o.removed)continue;const t="string"==typeof o.id?o.id:"";if(!t)continue;if("string"==typeof o.space&&o.space)continue;const r=("string"==typeof o.area?o.area:"")||s(t)||"";r&&e[r]||n.push({id:t,space:i})}return n}(i.markers||[],Object.fromEntries(Object.entries(this._areaToSpace).map(([t,e])=>[t,e.space])),s[0]||"",t=>o.get(t)||"");if(r.length){const t=new Map(r.map(t=>[t.id,t.space]));for(const e of i.markers||[]){const i=t.get(String(e.id));i&&(e.space=i)}}i.spaces=function(t,e){const i=new Map(e.map((t,e)=>[t,e]));return t.map((t,e)=>({space:t,index:e})).sort((t,e)=>(i.get(String(t.space?.id))??Number.MAX_SAFE_INTEGER)-(i.get(String(e.space?.id))??Number.MAX_SAFE_INTEGER)||t.index-e.index).map(t=>t.space)}(i.spaces||[],n),this._saveConfig(),this._tabOrderWarned||(this._tabOrderWarned=!0,this._showToast(this._t("toast.space_order_changed")))}_pickSpace(t){if(this._endTabDrag(),t===this._space)return;const e=this._model.map(t=>t.id),i=e.indexOf(this._space),s=e.indexOf(t);this._navApplied=!0,this._showFar=!1,this._frame=null,this._slideTo(t,i>=0&&s0&&Date.now()>=this._cyclePausedUntil&&this._model.length>1&&this._zoom<=1.001){const t=this._model.map(t=>t.id),e=t.indexOf(this._space);this._slideTo(t[(e+1)%t.length],"left"),this._showKioskDots()}}_syncCycleTimer(){clearInterval(this._cycleTimer),this._cycleTimer=void 0,this.isConnected&&!this._hasFixedFloor&&this._config?.kiosk&&Number(this._config.cycle)>0&&(this._cycleTimer=window.setInterval(()=>this._cycleTick(),1e3*Number(this._config.cycle)))}get _editing(){return"plan"===this._mode||"devices"===this._mode||"decor"===this._mode}get _markup(){return"plan"===this._mode}_newContinuityController(){return new Mh(()=>{this._resumeSettling="steady"!==this._continuity.state,this._continuityEpoch++,this.isConnected&&this.requestUpdate()})}get _labsIso(){return this._labs.active.includes("iso")}get _desiredProjection(){return"view"===this._mode&&this._labsIso&&"iso"===this._viewPreference[this._space]?"iso":"flat"}_saveViewPreference(){try{localStorage.setItem(hm,JSON.stringify(this._viewPreference))}catch{}}_logicalViewCenter(t){const e=this._view;if(!e)return null;const i=[e.x+e.w/2,e.y+e.h/2],s="iso"===t?lg(i):i;return{x:s[0],y:s[1]}}_convertProjectionView(t,e){if(t===e)return;const i=this._logicalViewCenter(t);this._view=null;const s=i?"iso"===e?ag([i.x,i.y],0):[i.x,i.y]:null;this._applyView(this._zoom,s?.[0],s?.[1]),this._warmPatch({vp:this._warmViewportState()}),this.requestUpdate()}_setProjection(t){if(!this._labsIso||"view"!==this._mode)return;const e=this._effectiveProjection();if(this._viewPreference={...this._viewPreference,[this._space]:t},"iso"===t){const t=this._isoSceneKey();t&&this._isoFallback.delete(t)}this._saveViewPreference();const i=this._effectiveProjection();this._convertProjectionView(e,i)}_hashSpace(){return K_(window.location.hash||"")}connectedCallback(){this._connectedPath=location.pathname,this._routeDepartureHandled=!1,window.addEventListener("location-changed",this._onLocationChanged),window.addEventListener("popstate",this._onLocationChanged),this._continuityDisposed&&(this._continuity=this._newContinuityController(),this._continuityDisposed=!1,this._continuityPaintToken=-1);const t=(e=this.ownerDocument,D_.get(e)?.resolved);var e;void 0!==t&&(this._glowScreenBlend=t),this._continuityUnsub?.(),this._continuityUnsub=$h(this.ownerDocument,this._pageVisibility),super.connectedCallback(),this._pointerModality.connect(this.ownerDocument.defaultView);const i=this.ownerDocument.defaultView?.MutationObserver;i&&(this._pointerHoverObserver=new i(t=>{for(const e of t)for(const t of e.addedNodes)this._syncPointerHoverSubtree(t)}),this._pointerHoverObserver.observe(this.renderRoot,{childList:!0,subtree:!0})),this._motionMedia=window.matchMedia?.("(prefers-reduced-motion: reduce)"),this._reducedMotion=!!this._motionMedia?.matches,this._motionMedia?.addEventListener?.("change",this._onMotionChange),function(t){const e=D_.get(t);if(e)return e.promise;const i={promise:Promise.resolve(!1)};return i.promise=P_(t).catch(()=>!1).then(t=>(i.resolved=t,t)),D_.set(t,i),i.promise}(this.ownerDocument).then(t=>{t!==this._glowScreenBlend&&(this._glowScreenBlend=t,this.isConnected&&this.requestUpdate())}),this.hass&&this._ensureHaRegistryAuthority(),window.addEventListener("keydown",this._keyHandler),this._signer.start(()=>this.hass,()=>Is(this._serverCfg)),this._syncCycleTimer(),window.addEventListener("hashchange",this._onHashChange),this._labsUnsub?.(),this._labsUnsub=function(t,e){eg.add(e);const i=ng(t);return"undefined"==typeof window&&e(i),()=>{eg.delete(e)}}(Gg,this._onLabsSnapshot),this._booting?this._bootWatch():this._bootFading&&(clearTimeout(this._bootTimer),this._bootTimer=window.setTimeout(()=>{this._bootFading=!1},220)),this._bootSoft&&(clearTimeout(this._bootSoftTimer),this._bootSoftTimer=window.setTimeout(()=>{this._bootSoft=!1},Jg)),!this._loadOk&&this._serverCfg&&this.hass&&this._scheduleLoadRetry(),!this._warmSlot&&this._config&&this._warmAdopt(),this._loadOk&&this._ensureLiveSyncSubscriptions(),this._warmVp&&!this._warmRevivePending&&void 0===this._warmReviveTimer&&(this._warmRevivePending=!0,this._warmReviveTimer=window.setTimeout(()=>this._warmReviveDialog(),0)),this._warmLongReturn&&this._beginResumeSettle(),this._warmLongReturn=!1,this.requestUpdate()}disconnectedCallback(){this._connectedPath&&location.pathname!==this._connectedPath&&this._leaveCardRoute(),window.removeEventListener("location-changed",this._onLocationChanged),window.removeEventListener("popstate",this._onLocationChanged),this._continuityUnsub?.(),this._continuityUnsub=void 0,this._motionMedia?.removeEventListener?.("change",this._onMotionChange),this._motionMedia=void 0,this._vacRaf&&(cancelAnimationFrame(this._vacRaf),this._vacRaf=0),this._refitRaf&&(cancelAnimationFrame(this._refitRaf),this._refitRaf=0),this._dayCycleTimer&&(clearInterval(this._dayCycleTimer),this._dayCycleTimer=0),this._dayCycleClockKey="",this._bootSettleRaf&&(cancelAnimationFrame(this._bootSettleRaf),this._bootSettleRaf=0),this._bootSettling=!1;for(const t of this._activityRt.values())clearTimeout(t.timer);window.removeEventListener("keydown",this._keyHandler),this._endTabDrag(),clearTimeout(this._tabSuppressClickTimer),this._tabSuppressClickTimer=void 0,this._tabSuppressClick=!1,clearInterval(this._cycleTimer),clearTimeout(this._kioskDotsTimer),clearTimeout(this._kioskHoldTimer),clearTimeout(this._reloadRetry),clearTimeout(this._loadRetryTimer),this._loadRetryTimer=void 0,this._connHooked?.removeEventListener?.("ready",this._onConnReady),this._connHooked?.removeEventListener?.("disconnected",this._onConnLost),this._connHooked?.removeEventListener?.("reconnect-error",this._onConnLost),this._connHooked=null,this._haRegistryRelease?.(),this._haRegistryRelease=void 0,this._haRegistryConnection=null,this._signer.dispose(),clearTimeout(this._toastTimer),clearTimeout(this._slideTimer),this._modeTransition.dispose(),this._modeTransitionVisual=null,this._modeTransitionPreparing=!1,this._modeTransitionForceAtomic=!1,this._modeTransitionRequest++,this._slideTimer=void 0,this._slide="",clearTimeout(this._bootTimer),this._bootTimer=void 0,clearTimeout(this._bootSoftTimer),this._saveConfigDebounced.flush(),window.removeEventListener("hashchange",this._onHashChange),this._labsUnsub?.(),this._labsUnsub=void 0,clearTimeout(this._holdTimer),this._roViewport?.disconnect(),this._roViewport=void 0,this._roHdr?.disconnect(),this._roHdr=void 0,this._onWinResize&&(window.removeEventListener("resize",this._onWinResize),this._onWinResize=void 0),this._unsubCfg&&(this._unsubCfg(),this._unsubCfg=null),this._unsubLayout&&(this._unsubLayout(),this._unsubLayout=null),this._unsubVirtual&&(this._unsubVirtual(),this._unsubVirtual=null),this._unsubTrail&&(this._unsubTrail(),this._unsubTrail=void 0),this._liveSyncGeneration++,this._liveSyncAttempt=null,this._liveSyncConnection=null,clearTimeout(this._layoutSyncTimer),clearTimeout(this._duplicateColumnTimer);for(const t of this._glowFadeTimers.values())clearTimeout(t);for(const t of this._glowEnterRafs.values())cancelAnimationFrame(t);clearTimeout(this._glowFeatherResumeTimer),this._glowFeatherResumeTimer=0,this._glowFeatherSuspendUntil=0,this._glowFadeTimers.clear(),this._glowEnterRafs.clear(),this._glowEnteringSources.clear(),this._glowRenderedSources.clear(),this._glowLastAppearance.clear(),this._glowSourceSeq=0,this._warmSnapshot(),this._warmRevivePending=!1,clearTimeout(this._warmReviveTimer),this._warmReviveTimer=void 0,this._warmRelease(),this._openWallAnchor=null,this._boundaryRestoreGuard=null,this._clearPlanSnapHover(),this._clearOpeningPlacement(!0),this._touchContacts.clear(),this._touchSequenceMultitouch=!1,this._touchClickBlockUntil=0,this._clearTransientHover(!0),this._cancelDevicePressFeedback(),this._pointerHoverObserver?.disconnect(),this._pointerHoverObserver=void 0,this._pointerModality.disconnect(),this._editorSecondary.reset(),this._resumeSettling=!1,this._continuityHistory=[...this._continuityHistory,...this._continuity.trace].slice(-80),this._continuity.dispose(),this._continuityDisposed=!0,super.disconnectedCallback()}_onKey(t){if("Escape"===t.key&&this._vacFit)return this._vacFit=null,this._showToast(this._t("vac.cal_cancelled")),void t.stopPropagation();if("Escape"===t.key){if(this._tapConfirm)return void(this._tapConfirm=null);if(this._vacCalConfirm)return void(this._vacCalConfirm=null);if(this._decorEraseConfirm)return void(this._decorEraseConfirm=null);if(this._openingInfo)return void(this._openingInfo=null);if(this._infoCard)return void this._closeInfoCard();if(this._rulesDialog)return void(this._rulesDialog=null);if(this._alignDialog)return void(this._alignDialog=null);if(this._backupImportDialog)return void(this._backupImportDialog=null);if(this._backupExportDialog)return void(this._backupExportDialog=null);if(this._settingsDialog)return void(this._settingsDialog=null);if(this._markerDialog)return void(this._markerDialog=null);if(this._openingDialog)return void(this._openingDialog=null);if(this._physicalDialog)return void(this._physicalDialog=null);if(this._backdropDialog)return void(this._backdropDialog=null);if(this._decorShapeDialog)return void(this._decorShapeDialog=null);if(this._decorTextDialog)return void(this._decorTextDialog=null);if(this._spaceDialog&&!this._roomDialog)return this._spaceDialog=null,this._importQueue=[],void(this._importTotal=0);if(this._editorSecondary.hasOpenGroup)return t.preventDefault(),void this._editorSecondary.closeGroup(!0)}const e=t.composedPath?.()||[t.target],i=e.some(t=>t?.matches?.('input, textarea, select, [contenteditable="true"]')),s=e.some(t=>t?.classList?.contains?.("editor-secondary")),n=t.ctrlKey||t.metaKey,o=t.key.toLowerCase(),r=/^[a-z]$/.test(o),a="z"===o||!r&&"KeyZ"===t.code,l="y"===o||!r&&"KeyY"===t.code,c=n&&(a&&t.shiftKey||l),h=n&&a&&!t.shiftKey;if("decor"===this._mode){if((h||c)&&i)return;return c?(t.preventDefault(),void this._redoGeometry()):h?(t.preventDefault(),this._decorDraft?void(this._decorDraft=null):this._decorMove||this._dtDrag||this._bdDrag?void this._cancelDecorGesture():void this._undoGeometry()):"Delete"!==t.key&&"Backspace"!==t.key||!this._decorSel||i||s?void("Escape"===t.key&&(t.preventDefault(),this._decorDraft?this._decorDraft=null:this._decorMove||this._dtDrag||this._bdDrag?this._cancelDecorGesture():"furniture"===this._decorTool?(this._furnPalette=null,this._decorTool="select"):this._decorSel?this._decorSel=null:"select"!==this._decorTool?this._decorTool="select":this._setMode("view"))):(t.preventDefault(),void this._decorDeleteSel())}if(this._markup&&(!h&&!c||!i)){if(("Delete"===t.key||"Backspace"===t.key)&&this._physicalSel&&!i&&!s)return t.preventDefault(),void this._deletePhysicalSelection();if(c)return t.preventDefault(),void this._redoGeometry();if(h)return t.preventDefault(),this._rszDrag?void this._rszCancelDrag():this._wallFaceBatch?(this._roomDialogCancel(),void(this._activeDraftId&&this._path.length>1?this._undoActiveDraftPoint():this._undoPoint())):"draw"===this._tool&&this._path.length?void(this._activeDraftId&&this._path.length>1?this._undoActiveDraftPoint():this._undoPoint()):"split"===this._tool&&this._splitSel?.pts?.length?(this._splitSel={...this._splitSel,pts:this._splitSel.pts.slice(0,-1)},void(this._splitSel.pts.length||(this._cursorPt=null))):void this._undoGeometry();if("Escape"===t.key)return this._physicalDrag||this._physicalRotate?(t.preventDefault(),void this._cancelPhysicalGesture()):this._roomDialog?(t.preventDefault(),void this._roomDialogCancel()):"draw"===this._tool&&this._path.length?(t.preventDefault(),void this._undoPoint()):this._physicalSel?(t.preventDefault(),void(this._physicalSel=null)):"resize"===this._tool?(t.preventDefault(),this._rszDrag?void this._rszCancelDrag():void(this._rszSel?this._rszSel=null:this._tool="draw")):"split"===this._tool?(t.preventDefault(),void(this._splitSel?.pts?.length?(this._splitSel={...this._splitSel,pts:this._splitSel.pts.slice(0,-1)},this._splitSel.pts.length||(this._cursorPt=null)):this._splitSel?this._splitSel=null:this._tool="draw")):"merge"===this._tool?(t.preventDefault(),void(this._mergeSel?this._mergeSel=null:this._tool="draw")):this._wallDialog?(t.preventDefault(),void(this._wallDialog=null)):"boundary"===this._tool?(t.preventDefault(),void(this._openWallAnchor?this._cancelBoundaryAnchor():this._tool="draw")):void("opening"!==this._tool&&"wallthick"!==this._tool&&"delroom"!==this._tool&&"column"!==this._tool||(t.preventDefault(),"opening"===this._tool&&this._clearOpeningPlacement(!0),this._tool="draw"))}}_undoPoint(){if(this._path.length){if(this._contourClosed)return this._path=this._path.slice(0,-1),void(this._closingWallCm=null);if(this._activeDraftId&&this._path.length>1&&this._curSpaceCfg){const t=this._geometrySnapshot();this._path=this._path.slice(0,-1),this._draftSegmentCms=this._draftSegmentCms.slice(0,-1);const e=this._curSpaceCfg,i=(e.room_drafts||[]).findIndex(t=>t.id===this._activeDraftId);return void(i>=0&&(this._path.length<2?(e.room_drafts.splice(i,1),e.room_drafts.length||delete e.room_drafts,this._activeDraftId=null):e.room_drafts[i]={id:this._activeDraftId,points:this._path.map(t=>[t[0]/pm,t[1]/pm]),segments:this._draftSegmentCms.map(t=>({cm:t}))},this._recordGeometry(this._t("history.draft_segment_delete"),t),this._saveConfig()))}this._path=this._path.slice(0,-1)}}_undoActiveDraftPoint(){const t=this._activeDraftId,e=this._path[0]?[...this._path[0]]:null,i=this._geometryHistory.undo();if(!i)return void this._undoPoint();if(!this._applyGeometryState(i.before))return void this._geometryHistory.clear();const s=t?this._spaceModel()?.room_drafts.find(e=>e.id===t):null;s?(this._activeDraftId=s.id,this._path=s.points.map(t=>[...t]),this._draftSegmentCms=this._adoptDraftCms(this._path,s.segments.map(t=>t.cm),s.id),this._resumeDraftBySpace[this._space]=s.id):(this._activeDraftId=null,this._path=e?[e]:[],this._draftSegmentCms=[],t&&this._resumeDraftBySpace[this._space]===t&&delete this._resumeDraftBySpace[this._space]),this._clearPlanSnapHover(),this._showToast(this._t("history.undone",{name:i.name}))}static getConfigElement(){return document.createElement("houseplan-card-editor")}static getStubConfig(){return{type:"custom:houseplan-card"}}static _warmBootReset(t){for(const t of em.values())for(const e of t)clearTimeout(e.evict);em.clear(),nm=t&&t>0?t:1e4}static _warmBootStats(){let t=0,e=0;const i=[];for(const s of em.values())for(const n of s)t++,n.dlg&&(e++,i.push(n.dlg.kind));return{keys:em.size,slots:t,dlgs:e,drafts:i}}setConfig(t){const e=this._config,i=!!e&&Object.prototype.hasOwnProperty.call(e,"floor");this._config={icon_size:2.5,show_temperature:!0,live_states:!0,show_signal:!0,...t};(i!==this._hasFixedFloor||e?.floor!==this._config.floor)&&(this._hashApplied=!1,this._navApplied=!1,this._warmVpArmed=!1),this._config.kiosk&&(this._booting=!1,this._bootFading=!1),!this._hasFixedFloor&&t.default_floor&&this._commitSpace(t.default_floor,!0);try{this._zoomBySpace=JSON.parse(localStorage.getItem(am)||"{}")||{}}catch{this._zoomBySpace={}}try{const t=JSON.parse(localStorage.getItem(hm)||"{}")||{};this._viewPreference=Object.fromEntries(Object.entries(t).filter(t=>"flat"===t[1]||"iso"===t[1]))}catch{this._viewPreference={}}this._labs=ng(Gg);try{const t=JSON.parse(localStorage.getItem(cm)||"null");this._kioskScale={icon:zs(t?.icon),font:zs(t?.font)}}catch{}try{const t=JSON.parse(localStorage.getItem(rm)||"null");t&&t.config&&Array.isArray(t.config.spaces)&&(this._serverCfg=t.config,this._cfgEpoch++,this._cfgRev=t.rev||0,this._cfgContentFingerprint=t.config_fingerprint||Ch(t.config),this._layout=t.layout||{},this._layoutRev=t.layout_rev||0,this._layoutContentFingerprint=t.layout_fingerprint||Ch(this._layout),this._virtualLights=gn(t.virtual_lights,this._cfgRev),this._serverStorage=!0)}catch{}this._adoptInitialSpace(this._model,this._loadOk),"view"!==this._mode||this._view||(this._zoom=this._zoomBySpace[this._space]||1),this.isConnected&&(this._syncCycleTimer(),this._warmAdopt(),this._warmLongReturn&&this._beginResumeSettle(),this._warmLongReturn=!1)}_warmAdopt(){if(this._config?.kiosk)return;const t=sm(this._config);if(this._warmKey===t&&this._warmSlot)return;this._warmSlot&&this._warmRelease();const e=this.parentNode,i=this._warmIdx(e),s=em.get(t);if(!s||!s.length)return;const n=s.find(t=>t.owner===this._warmGen);if(n)return this._warmLongReturn=!!n.freed&&Date.now()-n.freed>=wh,clearTimeout(n.evict),n.evict=0,n.freed=0,n.live=!0,this._warmSlot=n,this._warmKey=t,n.frameFingerprint&&this._continuity.adoptCompleteFrame(n.frameFingerprint),void(!this._devices.length&&n.devices?.length&&(this._devices=[...n.devices]));const{slot:o,sure:r}=((t,e,i,s)=>{const n=t=>{const e=!!i&&t.place?.deref()===i;return e&&t.idx===s?4:t.live?0:e?3:2};let o=null,r=0,a=0,l=null;for(const i of t){if(i.owner===e)continue;l=i;const t=n(i);t<=0||(t>r?(o=i,r=t,a=1):t===r&&a++)}return!o||a>1?{slot:o||l,sure:!1}:{slot:o,sure:!0}})(s,this._warmGen,e,i);o&&(this._warmLongReturn=!!o.freed&&Date.now()-o.freed>=wh,this._booting=!1,this._bootFading=!1,this._hdrH=o.hdrH,this._bootSoft=!0,this.isConnected&&(clearTimeout(this._bootSoftTimer),this._bootSoftTimer=window.setTimeout(()=>{this._bootSoft=!1},Jg)),this._warmKey=t,r?(clearTimeout(o.evict),o.evict=0,o.owner=this._warmGen,o.place=e?new WeakRef(e):null,o.idx=i,o.live=!0,this._warmSlot=o,this._warmVp=o.vp,o.frameFingerprint&&this._continuity.adoptCompleteFrame(o.frameFingerprint),!this._devices.length&&o.devices?.length&&(this._devices=[...o.devices]),this._warmAdoptViewport(this._config)):(this._warmSlot={owner:this._warmGen,path:location.pathname,place:e?new WeakRef(e):null,idx:i,live:!0,hdrH:o.hdrH,stageH:o.stageH,vp:null,frameFingerprint:"",devices:null,dlg:null,freed:0,evict:0},s.push(this._warmSlot),this._warmTrim(s)))}_warmIdx(t){const e=t?.children;if(!e)return-1;for(let t=0;t4;){const e=t.findIndex(t=>!t.live);if(e<0)break;clearTimeout(t[e].evict),t.splice(e,1)}}_warmScheduleEvict(t,e){if(clearTimeout(t.evict),!(t.dlg||t.vp&&"view"!==t.vp.mode))return;const i=t.freed,s=t.owner;t.evict=window.setTimeout(()=>{if(t.evict=0,t.freed!==i||t.owner!==s)return;var n;t.dlg=null,t.vp=(n=t.vp)&&"view"!==n.mode?{...n,mode:"view",zoom:n.snap?.space===n.space?n.snap.zoom:n.zoom,view:null,snap:null,tool:"draw",decorTool:"select",showHidden:!1,selId:null,rszSel:null,decorSel:null}:n,t.frameFingerprint="";const o=em.get(e);if(!t.live&&o&&o.length>1){const e=o.indexOf(t);e>=0&&o.splice(e,1)}},nm+250)}_warmAdoptViewport(t){const e=this._warmVp;if(!e||this._warmSlot?.path!==location.pathname)return void(this._warmVp=null);const i=this._fixedFloorState();if(this._hashApplied||!this._model.find(t=>t.id===e.space)||"valid"===i.kind&&i.id!==e.space||this._hasFixedFloor&&"valid"!==i.kind)return void(this._warmVp=null);this._commitSpace(e.space,!0),this._navApplied=!0,this._adoptMode("view"!==e.mode&&this._canEdit&&!t.kiosk?e.mode:"view"),this._pendingNavMode="view"===e.mode||this._canEdit||t.kiosk?null:e.mode,this._zoom=e.zoom;const s=this._effectiveProjection(),n=s===e.projection&&this._labsIso===e.activeLabsIso;if(this._view=n&&e.view?{...e.view}:null,this._viewModeSnap=n&&e.snap?{...e.snap}:null,!n&&e.logicalCenter){const t="iso"===s?ag([e.logicalCenter.x,e.logicalCenter.y],0):[e.logicalCenter.x,e.logicalCenter.y];this._applyView(e.zoom,t[0],t[1])}var o;this._tool="openwall"===(o=e.tool)||"closewall"===o?"boundary":"opening"===(o=function(t){return"partition"===t?"draw":t}(o))?"draw":"string"==typeof o&&gm.has(o)?o:"draw",this._decorTool=e.decorTool,this._showHidden=e.showHidden,this._showFar!==e.showFar&&(this._showFar=e.showFar,this._frame=null),this._selId=e.selId,this._rszSel=e.rszSel,this._decorSel=e.decorSel,this._warmVpArmed=!0}_warmPatch(t,e=!1){if(this._config?.kiosk)return;const i=sm(this._config);if(!this._warmSlot||this._warmKey===i){if(!this._warmSlot){if(!e)return;const t=this.parentNode;this._warmKey=i,this._warmSlot={owner:this._warmGen,path:location.pathname,place:t?new WeakRef(t):null,idx:this._warmIdx(t),live:!0,hdrH:this._hdrH,stageH:0,vp:null,frameFingerprint:"",devices:null,dlg:null,freed:0,evict:0};const s=em.get(i)||[];for(s.push(this._warmSlot),em.set(i,s),this._warmTrim(s);em.size>8;){const t=em.keys().next().value;if(void 0===t||t===i)break;for(const e of em.get(t)||[])clearTimeout(e.evict);em.delete(t)}}Object.assign(this._warmSlot,t)}}_warmViewportState(){const t=this._effectiveProjection();return{space:this._space,mode:this._mode,projection:t,activeLabsIso:this._labsIso,logicalCenter:this._logicalViewCenter(t),zoom:this._zoom,view:this._view?{...this._view}:null,snap:this._viewModeSnap?{...this._viewModeSnap}:null,tool:this._tool,decorTool:this._decorTool,showHidden:this._showHidden,showFar:this._showFar,selId:this._selId,rszSel:this._rszSel,decorSel:this._decorSel}}_warmDialogState(){const t=(t,e)=>({kind:t,space:this._space,mode:this._mode,data:e});return this._tapConfirm||this._alignDialog||this._mergeDialog||this._importDialog||this._backupExportDialog||this._backupImportDialog?null:this._openingInfo?t("openingInfo",this._openingInfo.id):this._infoCard?t("info",this._infoCard.id):this._rulesDialog?this._rulesDialog.busy?null:t("rules",this._rulesDialog):this._settingsDialog?this._settingsDialog.busy?null:t("settings",this._settingsDialog):this._markerDialog?this._markerDialog.busy?null:t("marker",this._markerDialog):this._openingDialog?t("opening",this._openingDialog):this._backdropDialog?t("backdrop",this._backdropDialog):this._decorShapeDialog?t("decorShape",this._decorShapeDialog):this._decorTextDialog?t("decorText",this._decorTextDialog):this._roomDialog?t("room",{editId:this._roomEditId,fill:this._roomFill,customFill:this._roomCustomFill,tempSrc:this._roomTempSrc,humSrc:this._roomHumSrc,srcOpen:this._roomSrcOpen,srcFilter:this._roomSrcFilter,nameScale:this._roomNameScale,labelScale:this._roomLabelScale,areaSel:this._areaSel,nameSel:this._nameSel,pendingSplit:this._pendingSplit,wallFaceBatch:this._wallFaceBatch,path:this._path}):this._spaceDialog?this._spaceDialog.busy?null:t("space",this._spaceDialog):null}_warmSnapshot(){if(this._booting||this._config?.kiosk||"steady"!==this._continuity.state)return;const t={vp:this._warmViewportState(),frameFingerprint:this._continuity.frameFingerprint,devices:this._devices};if(this._warmRevivePending||(t.dlg=this._warmDialogState()),this.isConnected&&this._warmSlot?.owner===this._warmGen){const e=this.parentNode;t.place=e?new WeakRef(e):null,t.idx=this._warmIdx(e)}this._warmPatch(t)}_warmReviveDialog(){this._warmRevivePending=!1;const t=this._warmSlot;if(this._warmReviveTimer=void 0,!t||!t.dlg)return;const e=t.dlg,i=t.freed;if(t.dlg=null,t.freed=0,clearTimeout(t.evict),t.evict=0,i&&!(Date.now()-i>nm)&&e.space===this._space&&e.mode===this._mode){switch(e.kind){case"space":this._spaceDialog={...e.data,busy:!1,savedBusy:!1};break;case"marker":this._markerDialog={...e.data,busy:!1};break;case"settings":this._settingsDialog={...e.data,busy:!1};break;case"rules":this._rulesDialog={...e.data,busy:!1};break;case"opening":this._openingDialog={...e.data};break;case"backdrop":this._backdropDialog={...e.data};break;case"decorShape":this._decorShapeDialog={...e.data};break;case"decorText":{this._decorTextDialog={...e.data};const t=String(this._decorTextDialog?.text??"").length;this._decorTextSelection={start:t,end:t};break}case"room":{const t=e.data;this._roomEditId=t.editId,this._roomFill=t.fill,this._roomCustomFill=t.customFill||null,this._roomTempSrc=t.tempSrc,this._roomHumSrc=t.humSrc,this._roomSrcOpen=t.srcOpen,this._roomSrcFilter=t.srcFilter,this._roomNameScale=t.nameScale,this._roomLabelScale=t.labelScale,this._areaSel=t.areaSel,this._nameSel=t.nameSel,this._pendingSplit=t.pendingSplit,this._wallFaceBatch=t.wallFaceBatch||null,this._path=t.path,this._wallFaceBatch&&(this._activeDraftId=this._wallFaceBatch.activeDraftId,this._draftSegmentCms=[...this._wallFaceBatch.activeCms]),this._roomDialog=!0;break}case"info":{const t=this._devices.find(t=>t.id===e.data);t&&(this._infoCard=t);break}case"openingInfo":{const t=(this._curSpaceCfg?.openings||[]).find(t=>t.id===e.data);t&&(this._openingInfo=t);break}}this.requestUpdate()}}_cacheSnapshot(){if(this._serverCfg)try{this._cfgContentFingerprint=Ch(this._serverCfg),this._layoutContentFingerprint=Ch(this._layout),this._virtualLights=function(t,e,i){if(t.configRev===i)return t;const s=new Set((Array.isArray(e?.markers)?e.markers:[]).filter(yn).map(t=>t.id));return{...t,configRev:i,off:new Set([...t.off].filter(t=>s.has(t)))}}(this._virtualLights,this._serverCfg,this._cfgRev),localStorage.setItem(rm,JSON.stringify({config:this._serverCfg,rev:this._cfgRev,config_fingerprint:this._cfgContentFingerprint,layout:this._layout,layout_rev:this._layoutRev,layout_fingerprint:this._layoutContentFingerprint,virtual_lights:fn(this._virtualLights)}))}catch{}}_beginContinuityCandidate(t,e,i="plan"){return this._booting&&!this._continuity.hasCompleteFrame?this._continuity.token:(this._continuityDataReady=e,this._continuityPaintToken=-1,this._stagedDeviceSnapshotToken=-1,this._resumeSettling=!0,this._continuity.beginCandidate(t,i))}_continuityStageValid(){const t=this._stageEl;return!!t&&t.clientWidth>0&&t.clientHeight>0}_continuityAssetsReady(){if(!this._model.length)return!1;const t=this._model.length?this._spaceModel():null;return!t?.bg?.href||this._signer.isReady(this.hass,t.bg.href)}_initialSpaceSelection(t,e=this._loadOk){const i=this._fixedFloorState(t,e);return"valid"===i.kind?{id:i.id,source:"fixed"}:this._hasFixedFloor?{id:null,source:"none"}:function(t){const e=new Set(t.spaceIds.filter(t=>!!t));if(!e.size)return{id:null,source:"none"};const i=[["hash",!1===t.acceptHash?null:t.hashSpace],["current",t.preserveCurrent?t.currentSpace:null],["saved",t.savedSpace],["default",t.defaultSpace],["first",t.spaceIds[0]]];for(const[t,s]of i)if(s&&e.has(s))return{id:s,source:t};return{id:null,source:"none"}}({spaceIds:t.map(t=>t.id),hashSpace:this._hashSpace(),acceptHash:!this._hashApplied,currentSpace:this._space,preserveCurrent:this._hashApplied||this._navApplied||this._warmVpArmed,savedSpace:this._savedNav()?.space,defaultSpace:this._config?.default_floor})}_adoptInitialSpace(t,e=this._loadOk){const i=this._initialSpaceSelection(t,e);return i.id?(this._commitSpace(i.id,!0),"hash"===i.source&&(this._hashApplied=!0),"saved"===i.source&&(this._navApplied=!0),i):i}_candidateBackdrop(t,e=this._space){const i=vc(t),s=this._fixedFloorState(i,!0);if(this._hasFixedFloor&&"valid"!==s.kind)return"";const n=this._initialSpaceSelection(i,!0).id||(i.some(t=>t.id===e)?e:i[0]?.id);return i.find(t=>t.id===n)?.bg?.href||""}_visualFrameFingerprint(){const t=this._stageEl,e=t?[t.clientWidth,t.clientHeight]:[0,0];return Dh([this._cfgRev,this._cfgContentFingerprint||Ch(this._serverCfg),this._layoutRev,this._layoutContentFingerprint||Ch(this._layout),this._space,this._mode,this._view,e,this._glowScreenBlend?"screen":"normal",this.hass?.themes?.darkMode??this.hass?.themes?.default_theme??""])}_settleContinuityFrame(){if(this._booting||!this._continuityStageValid())return;if(!this._continuity.hasCompleteFrame&&"steady"===this._continuity.state)return void(this._continuityAssetsReady()&&(this._renderSnapshotAt=Date.now(),this._continuity.markCompleteFrame(this._visualFrameFingerprint())));if(!this._continuityDataReady)return;if(!["holding","offline-stale","overlay-pending","overlay-visible","candidate-ready"].includes(this._continuity.state))return;const t=this._continuity.token;if(this._candidateDeviceSnapshot&&this._candidateDeviceSnapshot!==this._visibleDeviceSnapshot&&this._stagedDeviceSnapshotToken!==t)return this._stagedDeviceSnapshotToken=t,void this.requestUpdate();this._continuityPaintToken!==t&&(this._continuityPaintToken=t,this._continuity.candidateReady(t)&&this._continuity.commitAfterPaint(t,{updateComplete:()=>this.updateComplete,stageValid:()=>this.isConnected&&this._continuityStageValid(),assetsReady:()=>this._continuityAssetsReady(),frameFingerprint:()=>this._visualFrameFingerprint()}).then(e=>{e&&t===this._continuity.token?(this._resumeSettling=!1,this._renderSnapshotAt=Date.now(),this._candidateDeviceSnapshot&&(this._visibleDeviceSnapshot=this._candidateDeviceSnapshot),this._candidateDeviceSnapshot=null,this._stagedDeviceSnapshotToken=-1,this._warmSnapshot()):t===this._continuity.token&&(this._continuityPaintToken=-1,this._stagedDeviceSnapshotToken=-1,this._candidateDeviceSnapshot=null,this.requestUpdate())}))}_onBackdropLoaded(t,e){this._signer.markLoaded(this.hass,t,e),this._continuity.note("asset-ready"),this._continuityPaintToken=-1,"steady"!==this._continuity.state&&this.requestUpdate()}_renderRecoveryOverlay(){if(!this._continuity.overlayVisible&&"recovery-error"!==this._continuity.state)return G;const t="connection"===this._continuity.recoveryReason;return W`
`}afterRender(){const t=this.host.root();this._blocked&&(this._openGroupId?this.closeGroup(!1):"palette"===this._currentModel?.kind&&this._currentModel.dismiss?.()),this._syncGlobalDismissListener();const e=t.querySelector(".editor-secondary"),i=this._renderedContext,s=e?.dataset.contextId||"";if(s&&i&&s!==i&&!window.matchMedia?.("(prefers-reduced-motion: reduce)")?.matches&&(this._contentAnimation?.cancel(),this._contentAnimation=e?.querySelector(".editor-secondary-content")?.animate([{opacity:.35,transform:"translateY(-4px)"},{opacity:1,transform:"translateY(0)"}],{duration:100,easing:"ease-out"})),this._renderedContext=s,i&&s!==i&&this._focusOwned){const i=s?e?.querySelector('[tabindex="0"], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled])'):t.querySelector(".editbar-tools");i?.focus?.(),this._focusOwned=!!s}if("palette"===this._currentModel?.kind&&this._currentModel.launcherId){const e=[...t.querySelectorAll("[data-editor-palette]")].find(t=>t.dataset.editorPalette===this._currentModel?.launcherId);e&&null!==e.offsetParent||this._currentModel.dismiss?.()}if(!this._openGroupId)return;const n=[...t.querySelectorAll("[data-editor-group]")].find(t=>t.dataset.editorGroup===this._openGroupId);n&&null!==n.offsetParent||this.closeGroup(!0)}handleOutsideDismiss(t){if(Fu(t,t=>t.hasAttribute("data-editor-navigation")))return"pointerdown"===t.type?this.closeForNavigation():"click"===t.type&&this._dismissPointerTarget&&this._clearDismissClick(),!1;if("click"===t.type&&this._dismissPointerTarget){return!!(t.composedPath?.()||[t.target]).includes(this._dismissPointerTarget)&&(this._clearDismissClick(),t.preventDefault(),t.stopImmediatePropagation(),!0)}const e=this._openGroupId||this._blocked||"palette"!==this._currentModel?.kind?null:this._currentModel;if("pointerdown"===t.type&&(this._openGroupId||e)){const i=Fu(t,t=>t.classList.contains("editor-secondary")),s=Fu(t,t=>!!t.dataset.editorGroup),n=Fu(t,t=>!!t.dataset.editorPalette),o=Fu(t,t=>t.classList.contains("stage"));if(!(i||s||n||"stay-open-on-canvas"===e?.dismissPolicy&&o))return t.preventDefault(),t.stopImmediatePropagation(),this._dismissPointerTarget=t.target,clearTimeout(this._dismissTimer),this._dismissTimer=window.setTimeout(()=>{this._clearDismissClick()},800),this._openGroupId?this.closeGroup(!1):e?.dismiss?.(),this._syncGlobalDismissListener(),!0}return!1}_activateGroupItem(t,e,i){if(t.id!==this._openGroupId)return;const s=t.items.find(t=>t.id===e);if(!s||s.disabled)return;const n="toggle"===s.role&&"stay-open"===s.closePolicy,o=0===i.detail;n||(this._openGroupId=null,this.host.requestUpdate(),this._syncGlobalDismissListener()),s.invoke(),!n&&o&&this.host.updateComplete().then(()=>{const e=[...this.host.root().querySelectorAll("[data-editor-group]")].find(e=>e.dataset.editorGroup===t.id&&null!==e.offsetParent);e?.focus()})}_groupKeydown(t){if(!["ArrowLeft","ArrowRight","Home","End"].includes(t.key))return;const e=[...t.currentTarget.querySelectorAll(".editor-group-item:not([disabled])")];if(!e.length)return;t.preventDefault();const i=e.indexOf(this.host.root().activeElement),s="Home"===t.key?0:"End"===t.key?e.length-1:"ArrowLeft"===t.key?i<=0?e.length-1:i-1:(i+1)%e.length;e[s]?.focus()}_clearDismissClick(){this._dismissPointerTarget=null,clearTimeout(this._dismissTimer),this._dismissTimer=void 0,this._syncGlobalDismissListener()}_syncGlobalDismissListener(){const t=!this._blocked&&"palette"===this._currentModel?.kind,e=!!this._openGroupId||t||!!this._dismissPointerTarget;e!==this._globalDismissListening&&(this._globalDismissListening=e,e?(window.addEventListener("pointerdown",this._globalDismissGuard,!0),window.addEventListener("click",this._globalDismissGuard,!0)):(window.removeEventListener("pointerdown",this._globalDismissGuard,!0),window.removeEventListener("click",this._globalDismissGuard,!0)))}}const zu=t=>t.stopPropagation(),Ou=4.166666666666667e-9;function Nu(t){return Number.isFinite(t)?Math.round(t/$c)*$c:t}const Hu=(t,e,i,s)=>Math.hypot(i-t,s-e),Lu=(t,e,i,s,n,o,a,r)=>Math.hypot(Math.max(Math.abs(n-t),Math.abs(n+a-(t+i))),Math.max(Math.abs(o-e),Math.abs(o+r-(e+s)))),Bu=(t,e,i,s,n,o,a)=>{const r=Math.max(Number(s)||0,0)/2,l=Math.PI/180,c=Math.cos(i*l)*r,h=Math.sin(i*l)*r,d=Math.cos(a*l)*r,p=Math.sin(a*l)*r,u=Math.max(Hu(t+c,e+h,n+d,o+p),Hu(t-c,e-h,n-d,o-p)),_=Math.max(Hu(t+c,e+h,n-d,o-p),Hu(t-c,e-h,n+d,o+p));return Math.min(u,_)},qu=t=>{const e=Number(t?.cell_cm);return e>0?e:5};const Wu=10**9;function ju(t){if(Array.isArray(t))return t.map(t=>ju(t));if(null!==t&&"object"==typeof t){const e={};for(const[i,s]of Object.entries(t))e[i]=ju(s);return e}return t}function Uu(t){if("number"!=typeof t||!Number.isFinite(t))return t;const e=(t<0||Object.is(t,-0)?-1:1)*(Math.floor(Math.abs(t)*Wu+.5)/Wu);return 0===e?0:e}function Gu(t){return null===t||"object"!=typeof t||Array.isArray(t)?null:t}function Vu(t){return Array.isArray(t)?t.filter(t=>null!==Gu(t)):[]}function Ku(t,e){for(const i of e)Object.prototype.hasOwnProperty.call(t,i)&&(t[i]=Uu(t[i]))}function Yu(t){if(Array.isArray(t))for(let e=0;eArray.isArray(t)&&t.length>=2&&Number.isFinite(t[0])&&Number.isFinite(t[1]),i_=(t,e)=>Math.hypot(t[0]-e[0],t[1]-e[1]);function s_(t,e,i){const s=i[0]-e[0],n=i[1]-e[1],o=s*s+n*n;if(o<=0)return i_(t,e);let a=((t[0]-e[0])*s+(t[1]-e[1])*n)/o;return a=Math.max(0,Math.min(1,a)),Math.hypot(t[0]-(e[0]+s*a),t[1]-(e[1]+n*a))}function n_(t,e,i,s,n){for(const s of e)if(s&&!i.has(s.id)&&e_(s.a)&&e_(s.b)&&(i_(t,s.a)<=n||i_(t,s.b)<=n))return!0;for(const e of s?.roomPolygons||[])for(let i=0;i0&&r>0))return null;if(Math.abs(n[0]/a*(o[1]/r)-n[1]/a*(o[0]/r))>i)return null;for(const[i,n]of[[t.a,e.a],[t.a,e.b],[t.b,e.a],[t.b,e.b]])if(i_(i,n)<=s)return[(i[0]+n[0])/2,(i[1]+n[1])/2];return null}function a_(t,e){const i=.05*(Number(e.pitch)>0?Number(e.pitch):1),s=new Map;let n=(t||[]).filter(t=>!!t&&"string"==typeof t.id&&e_(t.a)&&e_(t.b));if(n.length<2)return{partitions:[...t||[]],merged:0,openingMoves:[]};const o=e.seedIds&&e.seedIds.length?new Set(e.seedIds):null;let a=0;for(let t=0;ti_(e,t.at)>i);let h=c[0]??r.a,d=c[c.length-1]??l.b;if(c.length<2&&(h=r.a,d=l.b),d[0]0?(d[0]-h[0])/u:0,g=u>0?(d[1]-h[1])/u:0,m=t=>u>0?((t[0]-h[0])*_+(t[1]-h[1])*g)/u:0;for(const t of[r,l]){const e=m(t.a),i=m(t.b)-e;for(const[n,o]of s)o.toId===t.id&&s.set(n,{fromId:o.fromId,toId:p.id,base:e+o.base*i,span:o.span*i});s.set(t.id,{fromId:t.id,toId:p.id,base:e,span:i})}o&&o.add(p.id),n=n.filter((e,i)=>i!==t.i&&i!==t.j),n.splice(t.i,0,p),a++}return{partitions:n,merged:a,openingMoves:[...s.values()]}}function r_(t,e,i,s){if(!t?.length||!i.length)return 0;const n=new Map(i.map(t=>[t.fromId,t]));let o=0;for(const i of t){const t=i?.host;if(!t||"partition"!==t.kind)continue;const a=n.get(t.id);if(!a)continue;i.host={...t,id:a.toId,t:t_(t.t,a)},o++;const r=Rd(i,e,s.coordScale,s.cellCm,s.gridPitch).resolved;r&&Object.assign(i,Od(i,r,s.coordScale))}return o}function l_(t,e){const i=e?.excludeDraftId||null;return{roomPolygons:(t?.rooms||[]).map(t=>hi(t)).filter(t=>!!t),columns:t?.wall_columns||[],draftEnds:(t?.room_drafts||[]).flatMap(t=>{if(i&&t?.id===i)return[];const e=t?.points||[];return e.length?[e[0],e[e.length-1]]:[]})}}const c_=t=>JSON.parse(JSON.stringify(t)),h_=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),d_=(t,e)=>e.length>0&&e.length<=35&&("space"===t?/^[a-z0-9_-]+$/.test(e):/^[A-Za-z0-9_-]+$/.test(e)),p_=(t,e,i)=>{const s=t.get(e)||[];s.push(i),t.set(e,s)};const u_=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),__=(t,e,i)=>Math.min(i,Math.max(e,t)),g_=t=>yc({spaces:[t]})[0],m_=(t,e,i)=>{const s=i>0?i:1,n=t=>`${(t[0]/s).toFixed(12)},${(t[1]/s).toFixed(12)}`,o=n(t),a=n(e);return o0?a:1,l=Math.max(s*r*.02,1e-9),c=[];for(const e of t||[])for(const t of hi(e)||[])c.push([t[0],t[1]]);for(const t of i||[])Array.isArray(t)&&t.length>=4&&t.slice(0,4).every(Number.isFinite)&&c.push([t[0],t[1]],[t[2],t[3]]);const h=t=>c.some(e=>Math.hypot(t[0]-e[0],t[1]-e[1])<=2*l),d=new Map;for(const a of t||[]){if(!a?.id)continue;const c=hl(t,a.id,e,i,s,n,o,r);if(c)for(let t=0;t0&&p>0&&a===u&&p!==a))continue;const _=c.poly[s],g=c.poly[(s+1)%c.poly.length],m=Math.hypot(g[0]-_[0],g[1]-_[1]);if(!(m>l&&m<.5*o-1e-9*o))continue;if(h(_)||h(g))continue;const f=m_(_,g,r),v=d.get(f);v?v.targets.add(a):d.set(f,{a:[_[0],_[1]],b:[g[0],g[1]],targets:new Set([a])})}}}let p=e.slice();const u=(t,e)=>Math.hypot(t[0]-e[0],t[1]-e[1])<=2*l,_=(t,e)=>{if(!Array.isArray(t.a)||!Array.isArray(t.b)||t.a.length<2||t.b.length<2)return!1;const i=[Number(t.a[0])*r,Number(t.a[1])*r],s=[Number(t.b[0])*r,Number(t.b[1])*r];return!![...i,...s].every(Number.isFinite)&&(u(i,e.a)&&u(s,e.b)||u(i,e.b)&&u(s,e.a))};for(const t of[...d.values()].filter(t=>1===t.targets.size).sort((t,e)=>m_(t.a,t.b,r).localeCompare(m_(e.a,e.b,r)))){const e=[...t.targets][0],i=p.filter(e=>_(e,t));if(new Set(i.map(t=>t.cm)).size>1)continue;let n=!1;p=p.map(i=>_(i,t)?(n=!0,i.cm===e?i:{...i,cm:e}):i),n||(p=Nr(p,t.a,t.b,e,s,r))}return p}const v_=t=>{const e=[];for(const i of t||[]){const t=hi(i);if(t?.length)for(let i=0;i"string"==typeof t?.id?t.id:"").filter(Boolean),h=new Set(c),d=new Map;for(const t of c){const e=/^space_(.+)_([0-9a-f]{8})$/.exec(t);e&&p_(d,e[1],t)}const p=new Map,u=new Map,_=new Map;for(const t of r){const e="string"==typeof t?.id?t.id:"";if(!e)continue;const i=new Map;for(const s of Array.isArray(t.rooms)?t.rooms:[]){const t="string"==typeof s?.id?s.id:"";if(!t)continue;const n=/^room_(.+)_([0-9a-f]{8})$/.exec(t);n&&p_(i,n[1],t),u.has(t)||u.set(t,e);const o="string"==typeof s.area?s.area:"";if(o){const i=_.get(o)||[];i.push({spaceId:e,roomId:t}),_.set(o,i)}}p.set(e,i)}const g=new Set(u.keys()),m=new Set,f=new Set;for(const t of l)"string"==typeof t?.id&&t.id&&(!0===t.removed?f:m).add(t.id);const v={spaceRefsRemapped:0,roomRefsRemapped:0,positionsRemapped:0,markersDetached:0,positionsUnresolved:0,nestedRefsUnresolved:0,deadSpaceIds:[]},y=new Set,b=t=>h.has(t)||!d_("space",t)?null:1===d.get(t)?.length?d.get(t)[0]:null,w=(t,e)=>{if(!d_("room",t))return null;const i=p.get(e)?.get(t)||[];return 1===i.length?i[0]:null},k=t=>{const e=i.effectiveAreaByMarker?.[t]||"",s=e&&_.get(e)||[];return 1===s.length?s[0]:null},x=(t,e,i)=>{if("string"==typeof t.room_id&&t.room_id&&!g.has(t.room_id)){const s=e?w(t.room_id,e):null;s?(t.room_id=s,v.roomRefsRemapped++):i?(t.room_id=i.roomId,v.roomRefsRemapped++):!0!==t.removed&&delete t.room_id}const s=t.vacuum?.segment_map;if(s&&"object"==typeof s&&!Array.isArray(s))for(const t of Object.keys(s)){const i=s[t];if("string"!=typeof i||!i||g.has(i))continue;const n=e?w(i,e):null;n?(s[t]=n,v.roomRefsRemapped++):v.nestedRefsUnresolved++}};for(const t of l){const e="string"==typeof t?.id?t.id:"";if(!e)continue;const i="string"==typeof t.space?t.space:"",s=i&&!h.has(i),o=n[e],a="string"==typeof o?.s?o.s:"",r=a&&!h.has(a),l=!0===t.removed;let c=i&&h.has(i)?i:null,d=null,p=!1;if(s){const s=b(i);s?(t.space=s,c=s,p=!0,v.spaceRefsRemapped++):l||"virtual"===t.binding?l||(delete t.space,c=null,v.markersDetached++):(d=k(e),d?(t.space=d.spaceId,c=d.spaceId,v.spaceRefsRemapped++):(delete t.space,c=null,v.markersDetached++))}l&&!p||x(t,c,d),r&&(p&&a===i&&c?(n[e]={...o,s:c},v.positionsRemapped++,y.add(e)):l||(delete n[e],y.add(e)))}for(const t of Object.keys(n)){if(y.has(t))continue;const e=n[t],i="string"==typeof e?.s?e.s:"";if(!i||h.has(i))continue;const s=b(i);if(s){if(t.startsWith("rl_")){const i=t.slice(3),o=w(i,s);if(o){const i=`rl_${o}`;h_(n,i)||(n[i]={...e,s:s}),delete n[t],v.roomRefsRemapped++,v.positionsRemapped++;continue}}n[t]={...e,s:s},v.positionsRemapped++}}const $=new Set;for(const t of l){const e="string"==typeof t?.space?t.space:"";e&&!h.has(e)&&$.add(e)}for(const[t,e]of Object.entries(n)){const i="string"==typeof e?.s?e.s:"";i&&!h.has(i)&&($.add(i),m.has(t)&&!f.has(t)||v.positionsUnresolved++)}return v.deadSpaceIds=[...$].sort((t,e)=>t.localeCompare(e)),{config:s,layout:n,report:v,changed:JSON.stringify(s)!==o||JSON.stringify(n)!==a}}(t,e,i),n=s.config,o=JSON.stringify(t||{}),a=JSON.stringify(e||{}),r=Number.isInteger(Number(n.model_version))?Number(n.model_version):0,l=(t=>{let e=0,i=0,s=0;for(const i of t.markers||[]){if("ripple"===i.display&&(i.display="icon_ripple",e++),Array.isArray(i.controls)){const t="string"==typeof i.binding&&i.binding.startsWith("entity:")?i.binding.slice(7):"",s=t?i.controls.filter(e=>e!==t):i.controls;JSON.stringify(s)!==JSON.stringify(i.controls)&&(i.controls=s.length?s:null,e++)}const t=i.vacuum;t&&u_(t,"trail")&&(["never","cleaning","always"].includes(t.trail_mode)||(t.trail_mode=!1===t.trail?"never":"cleaning"),delete t.trail,e++)}for(const n of t.spaces||[]){const t=n.settings;"glow"===t?.fill_mode&&("boolean"!=typeof t.glow_enabled&&(t.glow_enabled=!0),t.fill_mode="none",e++,i++);for(const t of n.rooms||[]){const i=t.settings;"glow"===i?.fill_mode&&("boolean"!=typeof i.glow&&(i.glow=!0),delete i.fill_mode,e++,s++)}if(u_(n,"segments")&&(delete n.segments,e++),u_(n,"plan_scale")){const t=Number(n.plan_scale);Number.isFinite(t)&&t>=gc&&t<=mc&&(u_(n,"plan_scale_x")||(n.plan_scale_x=t),u_(n,"plan_scale_y")||(n.plan_scale_y=t),delete n.plan_scale,e++)}const o=Number(n.cell_cm);u_(n,"cell_cm")&&(!Number.isFinite(o)||o<.1||o>1e3)&&(n.cell_cm=Number.isFinite(o)&&o>0?__(o,.1,1e3):5,e++);const a=Number(n.cell_cm),r=Number.isFinite(a)&&a>0?a:5;for(const t of n.wall_columns||[])if("circle"===t.shape)u_(t,"angle")&&(delete t.angle,e++);else if("square"===t.shape&&u_(t,"angle")){const i=((Number(t.angle)||0)%90+90)%90;t.angle!==i&&(t.angle=i,e++)}for(const t of n.decor||[]){if(u_(t,"width")){const i=Number(t.width);(u_(t,"width_cm")||Number.isFinite(i))&&(u_(t,"width_cm")||(t.width_cm=Number(__(i/xc*r,.1,100).toFixed(6))),delete t.width,e++)}if("rect"!==t?.kind&&"ellipse"!==t?.kind||!0!==t.fill||(u_(t,"fill_color")||(t.fill_color=t.color||"#607d8b",e++),u_(t,"fill_opacity")||(t.fill_opacity=.25,e++)),"text"!==t?.kind)continue;void 0===t.size_cm?(t.size_cm=Number(__(es*is(t)/xc*r,.1,2e3).toFixed(6)),delete t.scale,delete t.size,e++):(u_(t,"scale")||u_(t,"size"))&&(delete t.scale,delete t.size,e++);let i=String(t.text??"");const s=[...i.matchAll(/\{([^{}\r\n]+)\}/g)].some(t=>!!Yi(t[1]));if(!(u_(t,"entity")||u_(t,"attr")||u_(t,"unit")))continue;const n=String(t.unit??"").trim(),o="state"===String(t.attr??"").trim().toLowerCase()?null:t.attr,a=s||n?"":Xi(t.entity,o);if(s||a){if(a){const e=i.indexOf("{}");i=e>=0?i.slice(0,e)+a+i.slice(e+2):`${i}${i?" ":""}${a}`,t.text=i}delete t.entity,delete t.attr,delete t.unit,e++}}}return{total:e,glowSpaces:i,glowRooms:s}})(n);let c=l.total;for(const t of n.spaces||[]){const e=g_(t);if(!e)continue;if(!rh(t.open_spans).length){const i=ph(e.rooms,null,uc,.02*xc,!0);i.length&&(t.open_spans=uh(i,uc),c++)}}const h=(d=n.spaces||[],JSON.parse(JSON.stringify(d)));var d;const p=function(t,e){const i=JSON.parse(JSON.stringify(t||[])),s=JSON.parse(JSON.stringify(e||{}));let n=0,o=0,a=0,r=0,l="",c=0,h=0,d=0;const p=(t,e)=>{Number.isFinite(t)&&Number.isFinite(e)&&t!==e&&Math.abs(e-t)<=Ou&&h++},u=(t,e)=>{p(t[0],e[0]),p(t[1],e[1])},_={};let g=5;for(const t of i){const e=qu(t);null!=t?.id&&(_[String(t.id)]=e),e>g&&(g=e)}const m=(t,e,i,s=!1)=>{if(!(t>Ou||s))return;n++,t>a&&(a=t);const o=t*kc*e;o>r&&(r=o,l=i)};for(const t of i){const e=qu(t),i=null!=t?.id?String(t.id):"";for(const s of t.rooms||[]){o++;let t=0;if(s.poly?.length)s.poly=s.poly.map(e=>{const i=[Nu(e[0]),Nu(e[1])];return t=Math.max(t,Hu(e[0],e[1],i[0],i[1])),u(e,i),i});else if(null!=s.x&&null!=s.y){const e=s.x,i=s.y,n=s.w||0,o=s.h||0,a=Nu(e+n),r=Nu(i+o),l=Nu(e),c=Nu(i),h=Math.max($c,a-l),d=Math.max($c,r-c);t=Lu(e,i,n,o,l,c,h,d),s.x=l,s.y=c,s.w=h,s.h=d,p(e,l),p(i,c),p(e+n,l+h),p(i+o,c+d)}m(t,e,i)}for(const s of t.room_drafts||[]){o++;let t=0;const n=s.points||[],a=n.map(e=>{const i=[Nu(e[0]),Nu(e[1])];return t=Math.max(t,Hu(e[0],e[1],i[0],i[1])),i}),r=a.length?[a[0]]:[],l=a.length?[[n[0],a[0]]]:[],c=[];for(let t=0;t+1=2)for(const[t,e]of l)u(t,e);m(t,e,i)}if(Array.isArray(t.room_drafts)){const e=t.room_drafts.length;t.room_drafts=t.room_drafts.filter(t=>t.points?.length>=2),d+=e-t.room_drafts.length,t.room_drafts.length||delete t.room_drafts}for(const s of t.partitions||[]){o++;const n=[s.a[0],s.a[1]],a=[s.b[0],s.b[1]],r=[Nu(n[0]),Nu(n[1])],l=[Nu(a[0]),Nu(a[1])];let c=Math.max(Hu(n[0],n[1],r[0],r[1]),Hu(a[0],a[1],l[0],l[1]));const h=Hu(r[0],r[1],l[0],l[1]),d=(t.openings||[]).filter(t=>"partition"===t.host?.kind&&t.host.id===s.id).every(t=>{const e=Number(t.length),i=Number(t.host.t),s=i*h;return Number.isFinite(e)&&e>0&&Number.isFinite(i)&&i>=0&&i<=1&&s-e/2>=-Ou&&s+e/2<=h+Ou});h>Ou&&d?(s.a=r,s.b=l,u(n,r),u(a,l)):c=0,m(c,e,i)}for(const s of t.wall_columns||[]){o++;const t=[s.center[0],s.center[1]],n=[Nu(t[0]),Nu(t[1])],a=Hu(t[0],t[1],n[0],n[1]);s.center=n,u(t,n),m(a,e,i)}for(const s of t.decor||[]){o++;let t=0;if("line"===s.kind){const e=[s.x1,s.y1],i=[s.x2,s.y2],n=[Nu(e[0]),Nu(e[1])],o=[Nu(i[0]),Nu(i[1])];t=Math.max(Hu(e[0],e[1],n[0],n[1]),Hu(i[0],i[1],o[0],o[1])),s.x1=n[0],s.y1=n[1],s.x2=o[0],s.y2=o[1],u(e,n),u(i,o)}else{const e=s.x,i=s.y,n=s.w,o=s.h,a=Nu(e),r=Nu(i);if(null!=s.w&&null!=s.h){const l=Nu(e+n),c=Nu(i+o),h=Math.max($c,l-a),d=Math.max($c,c-r);t=Lu(e,i,n,o,a,r,h,d),s.w=h,s.h=d,p(e+n,a+h),p(i+o,r+d)}else t=Hu(e,i,a,r);s.x=a,s.y=r,p(e,a),p(i,r)}m(t,e,i)}for(const s of t.openings||[]){if(o++,"partition"===s.host?.kind){const n=(t.partitions||[]).find(t=>t.id===s.host.id),o=Number(s.host.t);if(!n||!Number.isFinite(o)||o<0||o>1)continue;const a=n.b[0]-n.a[0],r=n.b[1]-n.a[1];if(Math.hypot(a,r)<=Ou)continue;const l=n.a[0]+a*o,h=n.a[1]+r*o;let d=180*Math.atan2(r,a)/Math.PI;d>=90?d-=180:d<-90&&(d+=180);const p=Number(s.angle),u=!(Number.isFinite(p)&&p===d),_=Bu(s.x,s.y,Number.isFinite(p)?p:d,Number(s.length)||0,l,h,d);s.x=l,s.y=h,s.angle=d,u&&c++,m(_,e,i,u);continue}const n=ui([s.x,s.y],t.rooms||[],.025,{step:$c,length:Number(s.length)||0});if(!n)continue;const a=Number(s.angle),r=!(Number.isFinite(a)&&a===n.angle),l=Bu(s.x,s.y,Number.isFinite(a)?a:n.angle,Number(s.length)||0,n.x,n.y,n.angle);s.x=n.x,s.y=n.y,s.angle=n.angle,r&&c++,m(l,e,i,r)}}for(const[t,e]of Object.entries(s)){if(!e||"object"!=typeof e)continue;const i=e;if("number"!=typeof i.x||"number"!=typeof i.y)continue;o++;const n=Nu(i.x),a=Nu(i.y),r=Hu(i.x,i.y,n,a);s[t]={...i,x:n,y:a},p(i.x,n),p(i.y,a);const l="string"==typeof i.s?i.s:"";m(r,_[l]??g,l)}return{spaces:i,layout:s,report:{moved:n,coordsCanonicalized:h,total:o,maxShift:a,maxShiftCm:r,maxSpace:l,rotated:c,removedDrafts:d},changed:n>0||h>0}}(n.spaces||[],s.layout);n.spaces=p.spaces;const u={...p.report};let _=0,g=0,m=0,f=0;for(let t=0;t[t.id,t.open_to||[]]),walls:e.walls||[]}),o=g_(e),a=g_(i);if(!o||!a)continue;const r=v_(o.rooms),l=v_(a.rooms),c=.02*xc;let d=wh(rh(e.open_spans),r,l,uc);const p=d.length;d=bh(d,a.rooms,uc,c),d=d.map(t=>{const e=oh(t,uc),s=[e[0],e[1]],n=[e[2],e[3]],o=[(e[0]+e[2])/2,(e[1]+e[3])/2],a=e[2]-e[0],r=e[3]-e[1],h=Math.hypot(a,r)||1,d=l.map(([t,e])=>[t[0],t[1],e[0],e[1]]).filter(t=>{const e=t[2]-t[0],i=t[3]-t[1],l=Math.hypot(e,i)||1;return Math.abs(a*i-r*e)/(h*l)<=1e-6&&lh(o,t).d<=4*c&&lh(s,t).d<=4*c&&lh(n,t).d<=4*c}).sort((t,e)=>Math.hypot(e[2]-e[0],e[3]-e[1])-Math.hypot(t[2]-t[0],t[3]-t[1]))[0];if(u.total++,!d)return t;const p=[[d[0],d[1]],[d[2],d[3]]],_=hh(s,d,p,xc,2*c),g=hh(n,d,p,xc,2*c);if(Math.hypot(g[0]-_[0],g[1]-_[1])<.5*xc)return t;const m=Math.max(Math.hypot(_[0]-s[0],_[1]-s[1]),Math.hypot(g[0]-n[0],g[1]-n[1]));if(m>1e-6*xc){u.moved++;const t=m/uc;t>u.maxShift&&(u.maxShift=t);const e=m/xc*(Number(i.cell_cm)>0?Number(i.cell_cm):5);e>u.maxShiftCm&&(u.maxShiftCm=e,u.maxSpace=String(i.id||""))}return nh(_,g,uc)}),d=bh(d,a.rooms,uc,c),g+=Math.max(0,p-d.length);const v=d.map(t=>oh(t,uc));d.length?i.open_spans=d:delete i.open_spans,_h(i.rooms||[],a.rooms,v,c);const y=Array.isArray(e.walls)?e.walls.length:0;let b=Or(e.walls,r,l,$c,uc);b=f_(a.rooms,b,v,$c,Number(i.cell_cm)>0?Number(i.cell_cm):5,xc,uc),b=ul(a.rooms,b,v,$c,Number(i.cell_cm)>0?Number(i.cell_cm):5,xc,uc),b=Er(b,i.rooms||[],$c,1,v.map(t=>[t[0]/uc,t[1]/uc,t[2]/uc,t[3]/uc])),_+=Math.max(0,y-b.length),b.length?i.walls=b:delete i.walls;const w=a_(i.partitions||[],{pitch:$c,geometry:l_(i)});w.merged&&(m+=w.merged,i.partitions=w.partitions,r_(i.openings,i.partitions,w.openingMoves,{coordScale:uc,cellCm:Number(i.cell_cm)>0?Number(i.cell_cm):5,gridPitch:xc}));const k=JSON.stringify({spans:i.open_spans||[],links:(i.rooms||[]).map(t=>[t.id,t.open_to||[]]),walls:i.walls||[]});k!==s&&f++}const v=Qu(n),y=Zu(p.layout),b=JSON.stringify(v)!==o||JSON.stringify(y)!==a;r<7&&b&&(v.model_version=7);const w=JSON.stringify(v)!==o||JSON.stringify(y)!==a,k=Number.isInteger(Number(v.model_version))?Number(v.model_version):r,x=w?u:{...u,moved:0,coordsCanonicalized:0,maxShift:0,maxShiftCm:0,maxSpace:"",rotated:0,removedDrafts:0},$=w?s.report:{...s.report,spaceRefsRemapped:0,roomRefsRemapped:0,positionsRemapped:0,markersDetached:0};return{config:v,layout:y,report:{...x,modelFrom:r,modelTo:k,migrated:w?c:0,glowSpacesMigrated:w?l.glowSpaces:0,glowRoomsMigrated:w?l.glowRooms:0,canonicalized:w?f:0,wallsMerged:w?_:0,spansMerged:w?g:0,partitionsMerged:w?m:0,...$},changed:w}}function b_(t,e,i){const s=(t?.spaces||[]).find(t=>t?.id===i),n=new Set((s?.rooms||[]).map(t=>String(t?.id||"")).filter(Boolean)),o=[...new Set((t?.markers||[]).filter(t=>!0!==t?.removed&&"string"==typeof t?.id).filter(t=>t.space===i||"string"==typeof t.room_id&&n.has(t.room_id)||e?.[t.id]?.s===i).map(t=>t.id))].sort((t,e)=>t.localeCompare(e));return{markerIds:o,count:o.length}}function w_(t,e,i=xc,s=1e3){return ph(e.rooms,t?.open_spans,s,.02*i)}function k_(t,e,i=xc){if(!e.length)return[];const s=t.filter(t=>t?.id),n=.02*i,o=[];for(let t=0;t{const e=[(t[0]+t[2])/2,(t[1]+t[3])/2];return h.some(t=>Hs(e,t)<4*n)}).map(t=>[...t]);d.length&&o.push({a:a,b:r,segs:d})}return o}function x_(t,e,i,s=xc,n=1e3){return(Array.isArray(t?.openings)?t.openings:[]).flatMap(t=>{const o={...t,rx:Number(t.x)*n,ry:Number(t.y)*n,rlen:Number(t.length)*n};if(!t.host)return[o];const a=Rd(t,e.partitions,n,i,s);return a.resolved?[{...t,rx:a.resolved.center[0],ry:a.resolved.center[1],rlen:a.resolved.length,angle:a.resolved.angle,partitionHost:a.resolved}]:[]})}function $_(t,e=()=>!0){return t.flatMap(t=>t.host&&t.partitionHost&&e(t)?[Fd(t.partitionHost)]:[])}function S_(t,e,i,s,n,o,a=xc,r=1e3){const l=dl(e.rooms,[...i],s,n,o,a,r);return t.flatMap(t=>{const e={x:t.rx,y:t.ry,angle:Number(t.angle)||0,length:t.rlen};return t.host?t.partitionHost&&zd(t.partitionHost,l,2e-4*a)?[e]:[]:[e]})}function M_(t,e){const i=$c,s=xc,n=uc,o=Number.isFinite(Number(e.cellCm))&&Number(e.cellCm)>0?Number(e.cellCm):5,a=Array.isArray(t?.walls)?t.walls:[],r=w_(t,e,s,n),l=k_(e.rooms,r,s).flatMap(t=>t.segs),c=x_(t,e,o,s,n),h=$_(c),d=Jl(e,o,s,2e-4*s,h).all;return{space:e,walls:a,openCuts:l,openings:c,roomOpenings:S_(c,e,a,l,i,o,s,n),partitionCuts:h,physicalBodies:d,wallKeyPitch:i,cellCm:o,gridPitch:s,coordScale:n}}function C_(t,e,i){const s="string"==typeof t?.title?t.title.trim():"",n=null==t?.id?"":String(t.id).trim();return{spaceId:n,displayName:s||n||i(e+1)}}class D_{constructor(t=50){this._undo=[],this._redo=[],this._limit=Math.max(30,Math.floor(t))}get canUndo(){return this._undo.length>0}get canRedo(){return this._redo.length>0}get undoName(){return this._undo[this._undo.length-1]?.name??null}get redoName(){return this._redo[this._redo.length-1]?.name??null}get size(){return this._undo.length}push(t){this._undo.push(t),this._undo.length>this._limit&&this._undo.splice(0,this._undo.length-this._limit),this._redo=[]}undo(){const t=this._undo.pop()??null;return t&&this._redo.push(t),t}redo(){const t=this._redo.pop()??null;return t&&this._undo.push(t),t}clear(){this._undo=[],this._redo=[]}}const T_=new WeakMap;const P_=(t,e,i)=>255===t[i+3]&&e.every((e,s)=>Math.abs(t[i+s]-e)<=2);async function R_(t){const e=t.defaultView;if(!e||!e.CSS?.supports?.("mix-blend-mode","screen"))return!1;const i=[128,32,16],s=[16,64,128],n=[9,19,29],o=`\n \n \n \n \n \n `,a=e.URL.createObjectURL(new Blob([o],{type:"image/svg+xml"}));try{const o=await new Promise((t,i)=>{const s=new e.Image,n=e.setTimeout(()=>i(new Error("SVG blend probe timeout")),1e3);s.onload=()=>{e.clearTimeout(n),t(s)},s.onerror=()=>{e.clearTimeout(n),i(new Error("SVG blend probe failed"))},s.src=a}),r=t.createElement("canvas");r.width=4,r.height=1;const l=r.getContext("2d",{willReadFrequently:!0});if(!l)return!1;l.drawImage(o,0,0,4,1);const c=l.getImageData(0,0,4,1).data;return P_(c,i,0)&&P_(c,function(t,e){return[0,1,2].map(i=>Math.round(255-(255-t[i])*(255-e[i])/255))}(i,s),4)&&P_(c,s,8)&&P_(c,n,12)}catch{return!1}finally{e.URL.revokeObjectURL(a)}}const I_={now:()=>performance.now(),requestFrame:t=>requestAnimationFrame(t),cancelFrame:t=>cancelAnimationFrame(t)},A_=t=>Math.max(0,Math.min(1,t)),F_=(t,e,i)=>t+(e-t)*i,E_=(t,e,i)=>{const s=1-t;return 3*s*s*t*e+3*s*t*t*i+t*t*t};function z_(t,e){return{centerX:t.x+t.w/2,centerY:t.y+t.h/2,pixelsPerUnit:e>0&&t.w>0?e/t.w:1,viewBox:{...t}}}function O_(t,e,i){const s=Math.max(1e-9,t.pixelsPerUnit),n=Math.max(1e-9,e/s),o=Math.max(1e-9,i/s);return{x:t.centerX-n/2,y:t.centerY-o/2,w:n,h:o}}function N_(t){const e=t.trim(),i=/^rgba?\(\s*([\d.]+)[, ]+([\d.]+)[, ]+([\d.]+)(?:\s*[,/]\s*([\d.]+))?\s*\)$/i.exec(e);if(i)return[Number(i[1]),Number(i[2]),Number(i[3]),null==i[4]?1:Number(i[4])];const s=/^#([0-9a-f]{6}|[0-9a-f]{8})$/i.exec(e)?.[1];return s?[parseInt(s.slice(0,2),16),parseInt(s.slice(2,4),16),parseInt(s.slice(4,6),16),8===s.length?parseInt(s.slice(6,8),16)/255:1]:null}function H_(t,e,i){const s=N_(t),n=N_(e);if(!s||!n)return i<.5?t:e;const o=A_(i);return`rgba(${Math.round(F_(s[0],n[0],o))}, ${Math.round(F_(s[1],n[1],o))}, ${Math.round(F_(s[2],n[2],o))}, ${F_(s[3],n[3],o).toFixed(3)})`}function L_(t,e,i){const s=(t=>{const e=A_(t);if(0===e||1===e)return e;let i=0,s=1,n=e;for(let t=0;t<12;t++)n=(i+s)/2,E_(n,.2,.2){const e=this._state;if(!e||e.token!==n)return;const i=A_((t-e.startedAt)/e.duration);e.presented=i>=1?e.to:L_(e.from,e.to,i),e.phase=i>=1?"settling":"running",this._hooks.frame(e),i<1?this._raf=this._clock.requestFrame(a):(this._raf=0,this._hooks.settled(e),this._state?.token===n&&(this._state=null))};return this._raf=this._clock.requestFrame(a),n}cancel(t=!0){this._raf&&this._clock.cancelFrame(this._raf),this._raf=0;const e=this._state;this._state=null,this._token++,e&&t&&(e.phase="settling",e.presented=e.to,this._hooks.frame(e),this._hooks.settled(e))}dispose(){this.cancel(!1)}}const q_="houseplan_card_labs_v1",W_=Object.freeze([Object.freeze({id:"iso",issue:89,since:"1.62.0",expires:"1.65.0",summary:"Volumetric plan renderer"})]);function j_(t){const e=/^(\d+)\.(\d+)\.(\d+)(?:-[0-9A-Za-z.-]+)?$/.exec(String(t||"").trim());if(!e)return null;const i=e.slice(1).map(Number);return i.every(t=>Number.isSafeInteger(t))?i:null}function U_(t,e){for(let i=0;i<3;i++)if(t[i]!==e[i])return t[i]t.split(",")).map(t=>t.trim()).filter(Boolean)}function J_(t,e,i,s=W_){const n=function(t,e=W_){const i=j_(t),s=new Map;if(!i||!V_(e))return s;for(const t of e){const e=j_(t.since),n=j_(t.expires);U_(i,e)>=0&&U_(i,n)<0&&s.set(t.id,t)}return s}(i,s),o=new Set(V_(s)?s.map(t=>t.id):[]),a=new Set(function(t){if(!t)return[];try{const e=JSON.parse(t);return Array.isArray(e)?e.filter(t=>"string"==typeof t):[]}catch{return[]}}(e).filter(t=>n.has(t)));let r=!1;const l=t=>{if("off"===t)return a.clear(),void(r=!0);const e=t.startsWith("-"),i=e?t.slice(1):t;o.has(i)&&(r=!0,e||!n.has(i)?a.delete(i):a.add(i))};for(const e of X_(new URLSearchParams(String(t.search||"").replace(/^\?/,""))))l(e);for(const e of X_(K_(t.hash)))l(e);const c=Object.freeze([...a].sort());return{active:c,space:Y_(t.hash),persist:r?JSON.stringify(c):void 0,knownUrlOperation:r}}let Z_={active:Object.freeze([]),space:""},Q_="",tg=!1,eg="";const ig=new Set;function sg(){if("undefined"==typeof window)return Z_;const t=J_(window.location,function(){try{return window.localStorage.getItem(q_)}catch{return null}}(),Q_);void 0!==t.persist&&function(t){try{window.localStorage.setItem(q_,t)}catch{}}(t.persist),Z_={active:t.active,space:t.space},window.__hpLabs=t.active;for(const t of ig)t(Z_);return Z_}function ng(){sg()}function og(t){return Q_=t,"undefined"==typeof window?Z_:(tg||(tg=!0,window.addEventListener("hashchange",ng),window.addEventListener("popstate",ng)),sg())}const ag=Object.freeze({rotDeg:0,tiltDeg:20,xyScale:1,zScale:1,origin:Object.freeze([500,500])});function rg(t){return[t.rotDeg,t.tiltDeg,t.xyScale,t.zScale,t.origin[0],t.origin[1]].every(Number.isFinite)&&Math.abs(t.xyScale)>1e-12&&Math.abs(Math.cos(t.tiltDeg*Math.PI/180))>1e-12}function lg(t,e,i=ag){if(!(rg(i)&&Number.isFinite(t[0])&&Number.isFinite(t[1])&&Number.isFinite(e)))throw new Error("invalid isometric projection input");const s=i.rotDeg*Math.PI/180,n=i.tiltDeg*Math.PI/180,o=t[0]-i.origin[0],a=t[1]-i.origin[1],r=(o*Math.cos(s)-a*Math.sin(s))*i.xyScale,l=(o*Math.sin(s)+a*Math.cos(s))*i.xyScale;return[i.origin[0]+r,i.origin[1]+l*Math.cos(n)-e*i.zScale*Math.sin(n)]}function cg(t,e=ag){if(!rg(e)||!Number.isFinite(t[0])||!Number.isFinite(t[1]))throw new Error("invalid isometric projection input");const i=e.rotDeg*Math.PI/180,s=e.tiltDeg*Math.PI/180,n=(t[0]-e.origin[0])/e.xyScale,o=(t[1]-e.origin[1])/(e.xyScale*Math.cos(s));return[e.origin[0]+n*Math.cos(i)+o*Math.sin(i),e.origin[1]-n*Math.sin(i)+o*Math.cos(i)]}function hg(t=ag){return`matrix(${function(t=ag){if(!rg(t))throw new Error("invalid isometric camera");const e=t.rotDeg*Math.PI/180,i=t.tiltDeg*Math.PI/180,s=t.xyScale*Math.cos(e),n=-t.xyScale*Math.sin(e),o=t.xyScale*Math.sin(e)*Math.cos(i),a=t.xyScale*Math.cos(e)*Math.cos(i);return[s,o,n,a,t.origin[0]-s*t.origin[0]-n*t.origin[1],t.origin[1]-o*t.origin[0]-a*t.origin[1]]}(t).map(t=>Number(t.toFixed(12))).join(" ")})`}function dg(t,e=ag){const{rect:i,wallHeight:s}=t,n=t.openingHeight??s,o=t.floorDepth??0;if(!(i.w>=0)||!(i.h>=0)||!Number.isFinite(s)||!Number.isFinite(n)||!Number.isFinite(o)||s<0||n<0||o<0)throw new Error("invalid isometric frame");const a=[[i.x,i.y],[i.x+i.w,i.y],[i.x+i.w,i.y+i.h],[i.x,i.y+i.h]],r=Math.max(s,n),l=a.flatMap(t=>[lg(t,-o,e),lg(t,r,e)]),c=l.map(t=>t[0]),h=l.map(t=>t[1]),d=Math.min(...c),p=Math.min(...h);return{x:d,y:p,w:Math.max(...c)-d,h:Math.max(...h)-p}}const pg=t=>`${Number(t[0].toFixed(4))} ${Number(t[1].toFixed(4))}`;function ug(t){let e=0;for(let i=0;iArray.isArray(t)&&Number.isFinite(t[0])&&Number.isFinite(t[1])).map(t=>[Number(t[0]),Number(t[1])]),i=e[e.length-1];return e.length>1&&e[0][0]===i[0]&&e[0][1]===i[1]&&e.pop(),e}(t);if(i.length<3)return[];const s=!e;return ug(i)>0===s?i:[...i].reverse()}function gg(t,e,i){return t.length?`M ${t.map(t=>pg(lg(t,i,e))).join(" L ")} Z`:""}function mg(t,e,i){const s=e[1]-t[1],n=-(e[0]-t[0]),o=i.rotDeg*Math.PI/180;return s*Math.sin(o)+n*Math.cos(o)}function fg(t,e,i=ag){if(!Number.isFinite(e)||e<0)throw new Error("invalid floor edge height");const s=(t||[]).map(t=>{const e=(t||[]).map((t,e)=>function(t,e){const i=_g(t,e);if(!i.length)return i;let s=0;for(let t=1;t0)).filter(t=>t.length>=3&&Math.abs(ug(t))>=1e-9);return e}).filter(t=>t.length&&ug(t[0])>0);s.sort((t,e)=>{const i=t[0][0],s=e[0][0];return i[0]-s[0]||i[1]-s[1]||Math.abs(ug(e[0]))-Math.abs(ug(t[0]))});const n=[],o=[];let a=0;for(let t=0;tt.depth-e.depth||t.component-e.component||t.edge-e.edge),{footprintPath:n.join(" "),sides:o,componentCount:s.length,edgeCount:a}}function vg(t,e){return t^=Math.round(64*(Number.isFinite(e)?e:0)),Math.imul(t,16777619)>>>0}const yg=t=>t.every(Number.isFinite);function bg(t,e,i,s){const n=t[0]*i,o=t[1]*s,a=e*Math.PI/180;return[n*Math.cos(a)-o*Math.sin(a),n*Math.sin(a)+o*Math.cos(a)]}function wg(t,e,i,s,n,o,a){const r=t.flipH?-1:1,l="gate"===t.type?1:t.flipV?-1:1,c=(t.type,t.flipV,t.angle,t.face,{ox:0,oy:0}),h=function(t,e){return[t[0]+e[0],t[1]+e[1]]}([t.x+c.ox,t.y+c.oy],bg(i,t.angle,r,l));return{leaf:e,hinge:h,closedVector:bg(s,t.angle,r,l),quarterVector:bg([-s[1],s[0]],t.angle,r,l),turnDeg:n,bottom:o,top:a}}const kg=t=>`${Number(t[0].toFixed(4))} ${Number(t[1].toFixed(4))}`;function xg(t,e,i=ag){const s=Math.max(0,Math.min(1,Number.isFinite(e)?e:0));return t.leaves.map(e=>{const n=function(t,e){const i=t.turnDeg*e*Math.PI/180;return[t.hinge[0]+t.closedVector[0]*Math.cos(i)+t.quarterVector[0]*Math.sin(i),t.hinge[1]+t.closedVector[1]*Math.cos(i)+t.quarterVector[1]*Math.sin(i)]}(e,s),o=lg(e.hinge,e.bottom,i),a=lg(n,e.bottom,i),r=lg(n,e.top,i),l=lg(e.hinge,e.top,i);return{id:t.id,sourceIndex:t.sourceIndex,type:t.type,leaf:e.leaf,d:`M ${kg(o)} L ${kg(a)} L ${kg(r)} L ${kg(l)} Z`,shadowD:`M ${kg(lg(e.hinge,0,i))} L ${kg(lg(n,0,i))}`,depth:Math.max(o[1],a[1])}})}const $g={window:120,door:90,passage:90,gate:300};function Sg(t){return $g[t]}function Mg(t,e){const i=[t[0],t[1]],s=[e[0],e[1]];return function(t,e){return t[0]-e[0]||t[1]-e[1]}(i,s)<=0?{a:i,b:s}:{a:s,b:i}}function Cg(t){const e=new Map;return t.forEach((t,i)=>{if(!t.kind||t.open)return;const s=Mg(t.a,t.b);if(Math.hypot(s.b[0]-s.a[0],s.b[1]-s.a[1])<=1e-9)return;const n=function(t,e){const i=t=>(Math.abs(t)<=5e-10?0:Math.round(1e6*t)/1e6).toFixed(6);return`${i(t[0])},${i(t[1])}>${i(e[0])},${i(e[1])}`}(s.a,s.b),o=e.get(n);if(o)return o.physicalHalfWidth=Math.max(o.physicalHalfWidth,t.half||0),o.sourceOrder=Math.min(o.sourceOrder,i),void(t.partitionHost&&(o.partitionHost&&o.partitionHost.id!==t.partitionHost.id?o.ambiguousPartitionHost=!0:o.partitionHost=t.partitionHost));e.set(n,{segmentKey:n,a:s.a,b:s.b,physicalHalfWidth:Math.max(0,t.half||0),sourceOrder:i,...t.partitionHost?{partitionHost:t.partitionHost}:{}})}),[...e.values()]}function Dg(t,e){if(Math.abs(t.distance-e.distance)>1e-9)return t.distance-e.distance;if(Math.abs(t.perpendicular-e.perpendicular)>1e-9)return t.perpendicular-e.perpendicular;return(t.target.segmentKeye.target.segmentKey?1:0)||t.target.sourceOrder-e.target.sourceOrder}function Tg(t){const e=Cg(t.intervals).map(e=>{const i=function(t,e){const i=e.b[0]-e.a[0],s=e.b[1]-e.a[1],n=Math.hypot(i,s),o=i/n,a=s/n,r=(t[0]-e.a[0])*o+(t[1]-e.a[1])*a,l=Math.max(0,Math.min(n,r)),c=e.a[0]+l*o,h=e.a[1]+l*a;return{along:l,length:n,x:c,y:h,distance:Math.hypot(t[0]-c,t[1]-h),perpendicular:Math.abs((t[0]-e.a[0])*a-(t[1]-e.a[1])*o)}}(t.pointer,e);return{target:e,...i,envelope:Math.max(t.baseTolerance,e.physicalHalfWidth+t.bodyPointerPadding)}}).filter(t=>t.distance<=t.envelope+1e-9).filter(e=>!function(t,e,i,s,n){const o=e.b[0]-e.a[0],a=e.b[1]-e.a[1],r=Math.hypot(o,a);if(!(r>1e-9))return!1;const l=o/r,c=a/r;for(const o of i){if(!o.open&&o.kind)continue;const i=Mg(o.a,o.b),a=i.b[0]-i.a[0],r=i.b[1]-i.a[1],h=Math.hypot(a,r);if(!(h>1e-9))continue;const d=a/h,p=r/h;if(Math.abs(l*p-c*d)>1e-6)continue;if(Math.abs((i.a[0]-e.a[0])*c-(i.a[1]-e.a[1])*l)>n)continue;const u=(t[0]-i.a[0])*d+(t[1]-i.a[1])*p,_=1e-9;if(!(u<=_||u>=h-_)&&Math.abs((t[0]-i.a[0])*p-(t[1]-i.a[1])*d)<=s+1e-9)return!0}return!1}(t.pointer,e.target,t.intervals,e.envelope,Math.max(1e-9,Math.min(t.baseTolerance,.04*t.gridStep)))),i=e.filter(e=>!!e.target.partitionHost&&t.renderedLength+2*e.target.physicalHalfWidth>e.length+1e-9).sort(Dg),s=e.filter(e=>!e.target.partitionHost||t.renderedLength+2*e.target.physicalHalfWidth<=e.length+1e-9).sort(Dg);let n=s[0];if(!n)return{candidate:null,jambBlockedTarget:i[0]?.target||null};const o=s.filter(t=>Math.abs(t.distance-n.distance)<=1e-9&&Math.abs(t.perpendicular-n.perpendicular)<=1e-9),a=o.filter(t=>t.target.partitionHost);if(a.length){if(1!==new Set(a.map(t=>t.target.partitionHost.id)).size||a.some(t=>t.target.ambiguousPartitionHost))return{candidate:null,jambBlockedTarget:null};const t=a[0],e=t.target.b[0]-t.target.a[0],i=t.target.b[1]-t.target.a[1],s=Math.hypot(e,i),r=e/s,l=i/s,c=o.every(e=>{const i=e.target.b[0]-e.target.a[0],s=e.target.b[1]-e.target.a[1],n=Math.hypot(i,s),o=i/n,a=s/n,c=Math.abs(r*a-l*o)<=1e-6,h=Math.abs((e.target.a[0]-t.target.a[0])*l-(e.target.a[1]-t.target.a[1])*r);return c&&h<=1e-9});if(!c)return{candidate:null,jambBlockedTarget:null};n=t}if(n.target.ambiguousPartitionHost)return{candidate:null,jambBlockedTarget:null};const{target:r,length:l}=n,c=r.b[0]-r.a[0],h=r.b[1]-r.a[1],d=c/l,p=h/l,u=r.partitionHost?r.physicalHalfWidth:0,_=Math.min(Math.max(0,t.renderedLength)/2+u,l/2);let g=n.along;const m=Math.max(t.gridStep,1e-9),f=l/2;g=Math.abs(g-f)<=m/2?f:Math.round(g/m)*m,g=Math.max(_,Math.min(l-_,g));const v=r.a[0]+d*g,y=r.a[1]+p*g,b=Math.max(0,t.renderedLength)/2,w=g-b,k=g+b,x=Math.max(0,w),$=Math.max(0,l-k),S=[r.a[0]+d*(w-x/2),r.a[1]+p*(w-x/2)],M=[r.a[0]+d*(k+$/2),r.a[1]+p*(k+$/2)];let C=180*Math.atan2(h,c)/Math.PI;C>=90?C-=180:C<-90&&(C+=180);const D=Math.abs(g-f)<=1e-9;return{candidate:{presetRevision:t.preset.revision,geometryRevision:t.geometryRevision,pointer:[t.pointer[0],t.pointer[1]],type:t.preset.type,lengthCm:t.preset.lengthCm,flipH:t.preset.flipH,flipV:t.preset.flipV,x:v,y:y,angle:C,renderedLength:t.renderedLength,target:r,...r.partitionHost?{host:{...r.partitionHost,t:l>0?g/l:0}}:{},measure:{labels:[{distance:x,midpoint:S},{distance:$,midpoint:M}],guide:D?{x:v,y:y,angle:C}:null}},jambBlockedTarget:null}}function Pg(t,e,i,s,n=1e-6){return t.presetRevision===i&&t.geometryRevision===s&&Math.hypot(t.pointer[0]-e[0],t.pointer[1]-e[1])<=n}const Rg=(t,e)=>t[0]*e[1]-t[1]*e[0],Ig=(t,e)=>t[0]*e[0]+t[1]*e[1],Ag=(t,e)=>[t[0]-e[0],t[1]-e[1]],Fg=(t,e,i)=>[t[0]+e[0]*i,t[1]+e[1]*i];function Eg(t,e,i){return Math.abs(Rg(t,e))<=i}function zg(t,e,i){return Math.abs(Rg(Ag(t,e),i))}function Og(t,e,i,s,n){const o=e[0]-t[0],a=e[1]-t[1],r=Math.hypot(o,a);if(!(r>n&&i>0))return[];const l=[o/r,a/r];return function(t,e,i){const s=e.map(([e,i])=>[Math.max(0,Math.min(e,i)),Math.min(t,Math.max(e,i))]).filter(([t,e])=>e>t+i).sort((t,e)=>t[0]-e[0]||t[1]-e[1]),n=[];for(const t of s){const e=n[n.length-1];!e||t[0]>e[1]+i?n.push([...t]):e[1]=Math.max(e[1],t[1])}const o=[];let a=0;for(const[t,e]of n)t>a+i&&o.push([a,t]),a=Math.max(a,e);return t>a+i&&o.push([a,t]),o}(r,s.flatMap(e=>{const s=e.b[0]-e.a[0],o=e.b[1]-e.a[1],a=Math.hypot(s,o);if(!(a>n&&Eg(l,[s/a,o/a],1e-6)))return[];if(zg(e.a,t,l)>1.1*Math.max(i,n)||zg(e.b,t,l)>1.1*Math.max(i,n))return[];return[[Ig(Ag(e.a,t),l),Ig(Ag(e.b,t),l)]]}),n).flatMap(([e,s])=>{const n=Br({a:Fg(t,l,e),b:Fg(t,l,s),halfDepth:i});return n?[n]:[]})}function Ng(t){const e=t.coordScale??1,i=Math.max(t.epsilon??2e-4*t.gridPitch,1e-9),s=[];for(const i of t.rooms||[]){if(!i?.id)continue;const n=hl(t.rooms,i.id,t.walls,t.openCuts,t.pitch,t.cellCm,t.gridPitch,e);if(!n||n.poly.length<3)continue;const o=Qr(n.poly,n.offsets);!o||o.length<3||s.push({roomId:i.id,profile:n,inner:o})}s.sort((t,e)=>t.roomId.localeCompare(e.roomId));const n=(t.roomOpenings||[]).map(t=>{const e=t.angle*Math.PI/180,i=[Math.cos(e),Math.sin(e)],s=Math.max(0,t.length)/2;return{a:Fg([t.x,t.y],i,-s),b:Fg([t.x,t.y],i,s)}}),o=[];for(const s of Pl(t.rooms,t.walls,t.openCuts,t.pitch,t.cellCm,t.gridPitch,e))for(const t of Og(s.a,s.b,s.depthUnits/2,n,i))o.push({body:t});const a=new Map;for(const e of t.partitionCuts||[]){const t=a.get(e.hostId)||[];t.push(e),a.set(e.hostId,t)}for(const e of t.partitions||[]){const s=xr(e.cm,t.cellCm,t.gridPitch)/2;for(const t of Og(e.a,e.b,s,a.get(e.id)||[],i))o.push({body:t,partitionId:e.id})}return{rooms:s,boundaries:o,epsilon:i}}function Hg(t,e,i,s){const n=t.profile.offsets[e];if(!(n>0))return null;const o=function(t,e){const i=t[e],s=t[(e+1)%t.length],n=s[0]-i[0],o=s[1]-i[1],a=Math.hypot(n,o)||1;return function(t){let e=0;for(let i=0;i=0?[-o/a,n/a]:[o/a,-n/a]}(t.profile.poly,e),a=Fg(i.center,o,n),r=[];for(let e=0;es&&Eg(i.axis,[l[0]/c,l[1]/c],1e-6)))continue;if(zg(n,a,i.axis)>s||zg(o,a,i.axis)>s)continue;const h=Ig(Ag(n,a),i.axis),d=Ig(Ag(o,a),i.axis);r.push([Math.min(h,d),Math.max(h,d)])}const l=function(t,e){t.sort((t,e)=>t[0]-e[0]||t[1]-e[1]);const i=[];for(const s of t){const t=i[i.length-1];!t||s[0]>t[1]+e?i.push([...s]):t[1]=Math.max(t[1],s[1])}return i}(r,s).find(([t,e])=>t<=s&&e>=-s);if(!l)return null;const[c,h]=l,d=Fg(a,i.axis,-i.half),p=Fg(a,i.axis,i.half),u=Math.max(0,-i.half-c),_=Math.max(0,h-i.half),g=u>0?Fg(a,i.axis,c):d,m=_>0?Fg(a,i.axis,h):p,f=Ig(o,i.normal)>=0?1:-1,v=(e,s,n)=>({from:e,to:s,label:[(e[0]+s[0])/2,(e[1]+s[1])/2],axis:i.axis,labelNormal:o,distance:n,roomId:t.roomId,roomSide:f,source:"room-face"});return{left:v(d,g,u),right:v(p,m,_)}}function Lg(t){const e=Fg(t.center,t.axis,-t.half),i=Fg(t.center,t.axis,t.half),s=Fg(t.center,t.axis,Math.min(-t.half,t.targetLo)),n=Fg(t.center,t.axis,Math.max(t.half,t.targetHi)),o=(e,i)=>({from:e,to:i,label:[(e[0]+i[0])/2,(e[1]+i[1])/2],axis:t.axis,labelNormal:t.normal,distance:Math.hypot(i[0]-e[0],i[1]-e[1]),source:"host-end"});return[o(e,s),o(i,n)]}function Bg(t,e,i,s){const n=Ag(i,e),o=Ig(n,n);if(!(o>s*s))return Math.hypot(...Ag(t,e))<=s;const a=Ig(Ag(t,e),n)/o;if(a<-s||a>1+s)return!1;const r=Fg(e,n,Math.max(0,Math.min(1,a)));return Math.hypot(...Ag(t,r))<=s}function qg(t,e,i){let s=!1;for(let n=0,o=e.length-1;nt[1]!=c>t[1]&&t[0]<(l-a)*(t[1]-r)/(c-r)+a&&(s=!s)}return s}function Wg(t,e,i,s,n,o){const a=Ag(s,i),r=Rg(e,a);if(Math.abs(r)<=o)return null;const l=Ag(i,t),c=Rg(l,a)/r,h=Rg(l,e)/r;return c<-o||c>n+o||h<-o||h>1+o?null:Math.max(0,Math.min(n,c))}function jg(t,e,i){const s=Lg(i),n="partition"===t.host?.kind?t.host.id:void 0;return[{base:s[0],direction:[-i.axis[0],-i.axis[1]]},{base:s[1],direction:i.axis}].map(({base:t,direction:i})=>{const s=t.distance,o=function(t,e,i,s,n,o){let a=null;for(const r of s)if(!n||r.partitionId!==n){if(qg(t,r.body,o))return 0;for(let s=0;sIg(Ag(t,n),i));return{center:n,axis:i,normal:s,half:Math.max(0,t.renderedLength)/2,targetLo:Math.min(...o),targetHi:Math.max(...o)}}(t),s=e.rooms.flatMap(t=>{const s=function(t,e,i){const{profile:s}=t;let n=null;for(let t=0;t0))continue;const o=s.poly[t],a=s.poly[(t+1)%s.poly.length],r=Ag(a,o),l=Math.hypot(r[0],r[1]);if(!(l>i&&Eg(e.axis,[r[0]/l,r[1]/l],1e-6)))continue;if(zg(o,e.center,e.axis)>i||zg(a,e.center,e.axis)>i)continue;const c=Ig(Ag(o,e.center),e.axis),h=Ig(Ag(a,e.center),e.axis),d=Math.min(c,h),p=Math.max(c,h);if(d>-e.half+i||p0?d:p<0?-p:0);(!n||u2)return Lg(i);if(s.length){const t=s.map(({room:t,edge:s})=>Hg(t,s,i,e.epsilon));if(t.some(t=>!t))return Lg(i);const n=t;return[...n.map(t=>t.left),...n.map(t=>t.right)]}return jg(t,e,i)}function Gg(t){return!(!t.canEdit||t.kiosk||t.fixedFloor)&&("view"!==t.mode&&("mouse"===t.pointerType&&t.spaceCount>1))}const Vg="1.67.0-beta.3",Kg={badge:"display.badge",icon_ripple:"display.icon_ripple",value:"display.value",static_icon:"display.static_icon"},Yg={badge:"marker.display_hint_badge",icon_ripple:"marker.display_hint_icon_ripple",value:"marker.display_hint_value",static_icon:"marker.display_hint_static_icon"},Xg=2e3,Jg=1e3,Zg=1500,Qg=t=>{const e=String(t??"").trim().replace(",",".");if(!/^[+-]?(?:\d+(?:\.\d*)?|\.\d+)$/.test(e))return null;const i=Number(e);return Number.isFinite(i)?i:null},tm=(t,e)=>{if(!t.has(e))return{hit:!1};const i=t.get(e);return t.delete(e),t.set(e,i),{hit:!0,value:i}},em=(t,e,i,s)=>{for(t.delete(e),t.set(e,i);t.size>s;){const e=t.keys().next().value;if(void 0===e)break;t.delete(e)}},im=new Map;let sm=0;const nm=t=>`${window.innerWidth}x${window.innerHeight}|${location.pathname}|${JSON.stringify(t??{})}`;let om=1e4;const am="houseplan_card_layout_v1",rm="houseplan_card_cfg_v1",lm="houseplan_card_zoom_v1",cm="houseplan_card_nav_v1",hm="houseplan_card_kiosk_v1",dm="houseplan_card_view_v1",pm="hp-dialog, hp-help, hp-color-opacity, hp-device-preview",um=1e3,_m=[[0,1],[45,.88],[70,.62],[86,.32],[100,0]],gm=(t,e)=>{const i=Math.min(t.x,e.x),s=Math.min(t.y,e.y);return{x:i,y:s,w:Math.max(t.x+t.w,e.x+e.w)-i,h:Math.max(t.y+t.h,e.y+e.h)-s}},mm=new Set(["select","draw","column","merge","split","resize","opening","boundary","wallthick","delroom"]),fm=2e3,vm=(t,e,i)=>{const s=new Event(e,{bubbles:!0,composed:!0});s.detail=i??{},t.dispatchEvent(s)},ym=t=>{history.pushState(null,"",t),vm(window,"location-changed",{replace:!1})},bm=(t,e)=>{let i,s=null;const n=(...n)=>{clearTimeout(i),s=n,i=window.setTimeout(()=>{i=void 0;const e=s;s=null,e&&t(...e)},e)};return n.flush=()=>{if(void 0===i)return;clearTimeout(i),i=void 0;const e=s;s=null,e&&t(...e)},n.cancel=()=>{clearTimeout(i),i=void 0,s=null},n.pending=()=>void 0!==i,n},wm=t=>{try{t.target?.setPointerCapture?.(t.pointerId)}catch{}};class km extends ht{constructor(){super(...arguments),this._space="f1",this._layout={},this._serverStorage=!1,this._loadOk=!1,this._serverCanWrite=null,this._loading=!1,this._loadTries=0,this._serverCfg=null,this._cfgRev=0,this._cfgContentFingerprint="",this._unsubCfg=null,this._unsubLayout=null,this._unsubVirtual=null,this._liveSyncAttempt=null,this._liveSyncGeneration=0,this._liveSyncConnection=null,this._layoutRev=0,this._layoutContentFingerprint="",this._virtualLights=gn(null),this._canOptimizeUndo=!1,this._undoKind=null,this._devices=[],this._regSignature="",this._defPos={},this._newSyncKey="",this._tip=null,this._hoverRoom=null,this._pointerModality=new Tu(this,()=>this._syncPointerHoverTargets()),this._devicePressAnimations=new Map,this._selId=null,this._toast="",this._mode="view",this._pendingNavMode=null,this._decorTool="select",this._decorStyle={...or},this._decorDraft=null,this._decorMove=null,this._decorSel=null,this._decorEraseConfirm=null,this._decorTextDialog=null,this._decorShapeDialog=null,this._backdropDialog=null,this._decorTextSelection={start:0,end:0},this._furnPalette=null,this._dtBox=null,this._dtDrag=null,this._bdDrag=null,this._slide="",this._reducedMotion=!1,this._onMotionChange=t=>{this._reducedMotion=t.matches,this._cancelDevicePressFeedback(),t.matches&&this._modeTransitionPreparing?this._modeTransitionForceAtomic=!0:t.matches&&this._modeTransition.active&&this._cancelModeTransition(!0),this.requestUpdate()},this._editorChromeMode="plan",this._modeTransitionVisual=null,this._modeTransitionPreparing=!1,this._modeTransitionForceAtomic=!1,this._modeTransitionRequest=0,this._modeTransitionTargetZoom=1,this._modeTransitionEditorCamera=null,this._modeTransition=new B_({frame:t=>this._applyModeTransitionFrame(t),settled:t=>this._settleModeTransition(t)}),this._editorSecondary=new Eu({root:()=>this.renderRoot,requestUpdate:()=>this.requestUpdate(),updateComplete:()=>this.updateComplete,clearTip:()=>{this._tip=null}}),this._editorSecondaryCopy={groupActive:(t,e)=>this._t("editor.group_active",{group:t,item:e}),openGroup:t=>this._t("editor.open_group",{group:t}),disabledAction:(t,e)=>this._t("editor.disabled_action",{action:t,reason:e})},this._tool="draw",this._geometryHistory=new D_(50),this._wallDialog=null,this._drawWallField=null,this._activeDraftId=null,this._resumeDraftBySpace={},this._physicalSel=null,this._physicalDialog=null,this._partitionDeleteDialog=null,this._roomDeleteDialog=null,this._physicalDrag=null,this._physicalRotate=null,this._physicalLastTap=null,this._physicalPickCycle=null,this._wallUnionCache=null,this._isoGeometryCache=new Map,this._isoFallback=new Set,this._openingTunnelCache=null,this._openingWallIndexCache=new Map,this._openingPlacementIntervalsCache=null,this._openingDimensionContextCache=null,this._planSnapGeometryCache=null,this._planStructuralGeometryCache=null,this._physicalBodiesCache=null,this._lightPhysicalBodiesCache=null,this._cleanFloorCache=new Map,this._glowClipCache=new Map,this._glowGeometryWarnings=new Set,this._lightBarrierCache=null,this._glowFeatherUnits=null,this._glowRenderedSources=new Map,this._glowLastAppearance=new Map,this._glowEnteringSources=new Set,this._glowEnterRafs=new Map,this._glowFadeTimers=new Map,this._glowFeatherSuspendUntil=0,this._glowFeatherResumeTimer=0,this._glowSourceSeq=0,this._glowScreenBlend=!1,this._duplicateColumnId=null,this._duplicateColumnTimer=0,this._rszSel=null,this._rszDrag=null,this._rszPreview=null,this._rszLive=null,this._path=[],this._cursorPt=null,this._planSnapHover=null,this._mergeSel=null,this._openingPreset=null,this._openingRebindId=null,this._openingPresetRevision=0,this._openingHoverCandidate=null,this._openingJambBlockCm=null,this._openingDialog=null,this._openingInfo=null,this._opDrag=null,this._opMeasure=null,this._mergeDialog=null,this._openWallAnchor=null,this._boundaryPointerType="mouse",this._boundaryRestoreGuard=null,this._boundaryTargetMemo=null,this._boundaryPreviewMemo=null,this._splitSel=null,this._pendingSplit=null,this._wallFaceBatch=null,this._wallRepairDiagnostic=null,this._wallFaceGraphCache=[],this._areaSel="",this._nameSel="",this._roomDialog=!1,this._roomEditId=null,this._roomFill="",this._roomCustomFill=null,this._roomTempSrc="",this._roomHumSrc="",this._roomSrcOpen=null,this._roomSrcFilter="",this._roomNameScale=1,this._roomLabelScale=1,this._zoom=1,this._view=null,this._zoomBySpace={},this._viewModeSnap=null,this._pointers=new Map,this._panStart=null,this._panLock=null,this._pinchStart=null,this._suppressClick=!1,this._touchContacts=new Map,this._touchSequenceMultitouch=!1,this._touchClickBlockUntil=0,this._connectedPath="",this._routeDepartureHandled=!1,this._onLocationChanged=()=>{this._connectedPath&&location.pathname!==this._connectedPath?this._leaveCardRoute():location.pathname===this._connectedPath&&(this._routeDepartureHandled=!1)},this._touchGestureGuard={capture:!0,handleEvent:t=>this._guardTouchGesture(t)},this._hdrH=118,this._booting=!0,this._bootFading=!1,this._bootSettling=!1,this._bootSettleRaf=0,this._bootLastH=-1,this._bootStart=0,this._bootLastChange=0,this._bootSoft=!1,this._tapConfirm=null,this._onboardingShown=!1,this._rulesDialog=null,this._alignDialog=null,this._settingsDialog=null,this._backupExportDialog=null,this._backupImportDialog=null,this._sunRaysCache=null,this._dayCycleTimer=0,this._dayCycleClockKey="",this._compassDrag=!1,this._importDialog=null,this._importQueue=[],this._importTotal=0,this._rulesCompiledSrc="",this._infoCard=null,this._nativeMoreInfoEntity=null,this._markerDialog=null,this._spaceDialog=null,this._keyHandler=t=>this._onKey(t),this._warmVp=null,this._warmVpArmed=!1,this._warmLongReturn=!1,this._warmRevivePending=!1,this._warmGen=++sm,this._warmKey=null,this._warmSlot=null,this._hashApplied=!1,this._navApplied=!1,this._labs={active:Object.freeze([]),space:""},this._viewPreference={},this._renderProjection="flat",this._kioskScale={icon:1,font:1},this._kioskDialog=!1,this._activityRt=new Map,this._vacRt=new Map,this._vacViewKey="",this._vacLastView=null,this._vacRaf=0,this._vacSrvTrails={},this._vacJumpOnce=!1,this._continuity=this._newContinuityController(),this._continuityHistory=[],this._continuityEpoch=0,this._continuityDataReady=!0,this._continuityPaintToken=-1,this._continuityDisposed=!1,this._renderSnapshotAt=Date.now(),this._hassSequence=0,this._visibleDeviceSnapshot=null,this._candidateDeviceSnapshot=null,this._stagedDeviceSnapshotToken=-1,this._capturedSnapshotSequence=-1,this._capturedSnapshotDevices=null,this._capturedSnapshotLayout=null,this._capturedSnapshotActivity="",this._capturedSnapshotConfigEpoch=-1,this._capturedSnapshotVirtual="",this._lastValidStageSize=null,this._pendingRefitSize=null,this._refitRaf=0,this._pageVisibility=t=>{if(this._continuity.visibility(t),this._dayCycleVisibility(t),"hidden"===t.kind)return this._clearTransientHover(!0),this._cancelDevicePressFeedback(),void(this._modeTransitionPreparing?this._modeTransitionForceAtomic=!0:this._cancelModeTransition(!0));if(this._vacJumpOnce=!0,!t.long){const t=Date.now();let e=!1;for(const i of this._activityRt.values())!i.flashKind||(i.expiresAt||i.flashTs+$u)>t||(i.flashTs=0,i.flashKind=null,i.expiresAt=0,e=!0);return void(e&&this.requestUpdate())}Date.now()-this._renderSnapshotAt>1e3&&this._continuity.note("device-snapshot-stale"),this._continuityDataReady=!1,this._continuityPaintToken=-1,this._resumeSettling=!0,this._loading?this.requestUpdate():this._loadFromServer()},this._resumeSettling=!1,this._viewportInvalidAt=0,this._vacFit=null,this._vacAllCamerasFor=null,this._vacAllCameraCache=null,this._vacCalConfirm=null,this._kioskDots=!1,this._cyclePausedUntil=0,this._swipeStart=null,this._tabDrag=null,this._tabDragRelease=null,this._tabSuppressClick=!1,this._tabOrderWarned=!1,this._lastTap=0,this._onLabsSnapshot=t=>{const e=this._effectiveProjection();this._labs=t;const i=this._effectiveProjection();this._convertProjectionView(e,i),this.requestUpdate()},this._onHashChange=()=>{if(this._hasFixedFloor)return;const t=this._hashSpace();if(t&&this._model.find(e=>e.id===t)&&t!==this._space){if(this._wallFaceBatch&&this._roomDialogCancel(),"plan"===this._mode&&"draw"===this._tool&&!this._finishWallChain())return;this._activeDraftId&&(this._resumeDraftBySpace[this._space]=this._activeDraftId),this._commitSpace(t),this._selId=null,this._path=[],this._clearPlanSnapHover(),this._clearOpeningPlacement(!0),this._tool="draw",this._openWallAnchor=null,this._boundaryRestoreGuard=null,this._activeDraftId=null,this._draftSegmentCms=[],this._closingWallCm=null,"plan"===this._mode&&"draw"===this._tool&&this._resumeLastDraft(),this._restoreZoom(),this.requestUpdate()}},this._drag=null,this._rlResize=null,this._holdFired=!1,this._retryContinuity=()=>{this._continuityDataReady=!1,this._continuityPaintToken=-1,this._continuity.retry(this._continuity.recoveryReason||"plan"),this._loading||this._loadFromServer()},this._cfgEpoch=0,this._modelCache=null,this._emptySpaceStateActive=!1,this._decorSnapCache=null,this._markerPreviewMemo=null,this._markerPreviewDevicesMemo=null,this._showHidden=!1,this._connHooked=null,this._connectionWasLost=!1,this._haRegistryConnection=null,this._haRegistryRev=-1,this._haBindingCacheKey="",this._planHassMemo=null,this._onHaRegistryUpdate=()=>{const t=An(this.hass);t.revision===this._haRegistryRev&&this._devices.length||(this._haRegistryRev=t.revision,this._planHassMemo=null,this._regSignature="",this._maybeRebuildDevices(),this.requestUpdate())},this._onConnReady=()=>{if(this._loadTries=0,clearTimeout(this._loadRetryTimer),this._loadRetryTimer=void 0,function(t){const e=Cn(t);e&&(Pn(t,e),Rn(t,e))}(this.hass),this._saveConfigDebounced.pending()&&this._saveConfigDebounced.flush(),this._cfgWriting)return clearTimeout(this._reloadRetry),void(this._reloadRetry=window.setTimeout(this._onConnReady,400));!this._connectionWasLost&&this._continuity.hasCompleteFrame?this._beginContinuityCandidate("connection-ready",!1,"plan"):(this._continuityDataReady=!1,this._continuityPaintToken=-1),this._loading||this._loadFromServer()},this._onConnLost=()=>{this._booting&&!this._continuity.hasCompleteFrame||(this._connectionWasLost=!0,this._continuityDataReady=!1,this._continuityPaintToken=-1,this._continuity.connectionLost())},this._signer=new Rh(()=>this.requestUpdate()),this._dirtyPos=new Set,this._sentPos=new Map,this._persistLayout=bm(()=>{if(this._serverStorage){const t=[...this._dirtyPos];this._dirtyPos.clear();for(const e of t){const t=Ju(this._layout[e]);t&&(this._layout={...this._layout,[e]:t},this._sentPos.set(e,t),this.hass.callWS({type:"houseplan/layout/update",device_id:e,pos:t}).then(t=>this._noteLayoutRev(t)).catch(t=>this._showToast(this._t("toast.pos_save_failed",{err:this._errText(t)}))).finally(()=>{this._sentPos.get(e)===t&&this._sentPos.delete(e)}))}this._cacheSnapshot()}else this._layout=Zu(this._layout),localStorage.setItem(am,JSON.stringify(this._layout))},600),this._frame=null,this._showFar=!1,this._writesPending=0,this._writeChain=Promise.resolve(),this._undoGeometry=()=>{if(this._cancelBoundaryAnchor())return;if(this._physicalDrag||this._physicalRotate)return void this._cancelPhysicalGesture();if(this._decorDraft)return this._decorDraft=null,void this.requestUpdate();if(this._decorMove||this._dtDrag||this._bdDrag)return void this._cancelDecorGesture();if(this._rszDrag)return void this._rszCancelDrag();const t=this._geometryHistory.undo();t&&(this._applyGeometryState(t.before)?this._showToast(this._t("history.undone",{name:t.name})):this._geometryHistory.clear())},this._redoGeometry=()=>{if(this._cancelBoundaryAnchor())return;if(this._physicalDrag||this._physicalRotate)return void this._cancelPhysicalGesture();if(this._decorDraft)return this._decorDraft=null,void this.requestUpdate();if(this._decorMove||this._dtDrag||this._bdDrag)return void this._cancelDecorGesture();if(this._rszDrag)return void this._rszCancelDrag();const t=this._geometryHistory.redo();t&&(this._applyGeometryState(t.after)?this._showToast(this._t("history.redone",{name:t.name})):this._geometryHistory.clear())},this._saveConfigDebounced=bm(()=>{this._serverCfg&&this._writeConfig().catch(t=>{"conflict"===t?.code?(this._showToast(this._t("toast.conflict")),this._cancelPath(),this._reloadConfigOnly(!0)):this._showToast(this._t("toast.cfg_save_failed",{err:this._errText(t)}))})},500),this._draftSegmentCms=[],this._closingWallCm=null,this._savePhysicalDialog=()=>{const t=this._physicalDialog,e=this._curSpaceCfg,i=this._spaceModel();if(!t||!e||!i)return;const s=Qg(t.cm);if(null==s)return void this._showPhysicalRange("column"===t.kind?Ll:100);const n=this._imperial?2.54*s:s,o="column"===t.kind?Ll:100;if(!Number.isFinite(n)||n<1||n>o)return void this._showPhysicalRange(o);if("column"===t.kind){const e=i.wall_columns.find(e=>e.id===t.id);if(!e)return;const s=Qg(t.angle||"0");if("circle"!==t.shape&&(null==s||s<0||s>=90))return void this._showToast(this._t("toast.physical_angle"));const o="circle"===t.shape?{id:t.id,shape:"circle",center:e.center,cm:n}:{id:t.id,shape:"square",center:e.center,cm:n,angle:s};if(i.wall_columns.some(e=>e.id!==t.id&&rc(e,o,.02*this._gridPitch)))return void this._showToast(this._t("toast.column_duplicate"))}const a=this._geometrySnapshot();if("partition"===t.kind){const i=(e.partitions||[]).find(e=>e.id===t.id);i&&(i.cm=n)}else if("column"===t.kind){const i=(e.wall_columns||[]).find(e=>e.id===t.id);i&&(i.cm=ql(n),i.shape="circle"===t.shape?"circle":"square","square"===i.shape?i.angle=Qg(t.angle||"0"):delete i.angle)}else{const i=(e.room_drafts||[]).find(e=>e.id===t.id);i?.segments?.[t.segment||0]&&(i.segments[t.segment||0].cm=n)}this._recordGeometry(this._t("history.physical_edit"),a),this._physicalDialog=null,this._saveConfig()},this._deletePhysicalSelection=()=>{const t=this._physicalSel,e=this._curSpaceCfg;if(!t||!e)return;if("draft"===t.kind)return void this._deleteDraftWhole();const i=this._geometrySnapshot();if("partition"===t.kind){const i=(e.openings||[]).filter(e=>"partition"===e.host?.kind&&e.host.id===t.id).sort((t,e)=>(t.host?.t||0)-(e.host?.t||0));if(i.length)return void(this._partitionDeleteDialog={id:t.id,openings:i.map(t=>JSON.parse(JSON.stringify(t)))})}const s="partition"===t.kind?"partitions":"column"===t.kind?"wall_columns":"room_drafts";e[s]=(e[s]||[]).filter(e=>e.id!==t.id),e[s].length||delete e[s],this._activeDraftId===t.id&&this._cancelPath(),this._physicalSel=null,this._physicalDialog=null,this._recordGeometry(this._t("history.physical_delete"),i),this._saveConfig()},this._confirmPartitionDelete=()=>{const t=this._partitionDeleteDialog,e=this._curSpaceCfg;if(!t||!e)return;const i=this._geometrySnapshot();e.partitions=(e.partitions||[]).filter(e=>e.id!==t.id),e.partitions.length||delete e.partitions,e.openings=(e.openings||[]).filter(e=>"partition"!==e.host?.kind||e.host.id!==t.id),e.openings.length||delete e.openings,this._partitionDeleteDialog=null,this._physicalSel=null,this._physicalDialog=null,this._recordGeometry(this._t("history.physical_delete"),i),this._saveConfig()},this._deleteDraftWhole=()=>{const t="draft"===this._physicalDialog?.kind?this._physicalDialog.id:"draft"===this._physicalSel?.kind?this._physicalSel.id:null,e=this._curSpaceCfg;if(!t||!e||!confirm(this._t("confirm.delete_draft")))return;const i=this._geometrySnapshot();e.room_drafts=(e.room_drafts||[]).filter(e=>e.id!==t),e.room_drafts.length||delete e.room_drafts,this._activeDraftId===t&&this._cancelPath(),this._physicalSel=null,this._physicalDialog=null,this._recordGeometry(this._t("history.physical_delete"),i),this._saveConfig()},this._deleteDraftSegment=()=>{const t=this._physicalDialog,e=this._curSpaceCfg;if(!t||"draft"!==t.kind||!e)return;if(!confirm(this._t("confirm.delete_draft_segment")))return;const i=(e.room_drafts||[]).findIndex(e=>e.id===t.id);if(i<0)return;const s=e.room_drafts[i],n=Math.max(0,Math.min(s.segments.length-1,t.segment||0)),o=[],a=s.points.slice(0,n+1),r=s.points.slice(n+1);if(a.length>=2&&o.push({id:s.id,points:a,segments:s.segments.slice(0,n)}),r.length>=2&&o.push({id:o.length?`${s.id}-${Date.now().toString(36)}`:s.id,points:r,segments:s.segments.slice(n+1)}),2===o.length&&e.room_drafts.length>=200)return void this._showToast(this._t("toast.physical_limit"));const l=this._geometrySnapshot();e.room_drafts.splice(i,1,...o),e.room_drafts.length||delete e.room_drafts,this._activeDraftId===s.id&&this._cancelPath(),this._physicalDialog=null,this._physicalSel=o.length?{kind:"draft",id:o[0].id}:null,this._recordGeometry(this._t("history.draft_segment_delete"),l),this._saveConfig()},this._confirmRoomDelete=t=>{const e=this._roomDeleteDialog,i=this._curSpaceCfg,s=this._spaceModel();if(!e||!i||!s)return;const n=s.rooms.find(t=>t.id===e.roomId);if(!n)return void(this._roomDeleteDialog=null);const o=this._openCuts(),a=Cp(dl(s.rooms,this._spaceWalls,o,this._wallKeyPitch,this._cellCm,this._gridPitch,um).filter(t=>t.roomId===n.id),s.partitions,this._openingsR.map(t=>({...t,x:t.rx,y:t.ry})),.02*this._gridPitch),r=new Set(a.materialize.filter(t=>!t.reusePartitionId).map(t=>t.interval.key)).size;if(t&&(i.partitions||[]).length+r>fm)return void this._showToast(this._t("toast.physical_limit"));const l=this._geometrySnapshot(),c=pl(s.rooms,this._spaceWalls,o,this._wallKeyPitch,this._cellCm,this._gridPitch,um);if(t){i.partitions||=[];const t=new Map,e=new Map,s=Date.now().toString(36);for(const n of a.materialize){let o=n.reusePartitionId?i.partitions.find(t=>t.id===n.reusePartitionId):e.get(n.interval.key);o||(o={id:`partition-room-${s}-${e.size}`,a:[n.interval.a[0]/um,n.interval.a[1]/um],b:[n.interval.b[0]/um,n.interval.b[1]/um],cm:n.interval.cm},i.partitions.push(o),e.set(n.interval.key,o)),t.set(n.interval.key,o)}for(const e of i.openings||[]){const i=a.openingIntervals.get(e.id),s=i?t.get(i):null,n=this._openingsR.find(t=>t.id===e.id);if(!s||!n)continue;const o={a:[s.a[0]*um,s.a[1]*um],b:[s.b[0]*um,s.b[1]*um]};e.host={kind:"partition",id:s.id,t:Dp([n.rx,n.ry],o)}}}else if(a.removeOpeningIds.length){const t=new Set(a.removeOpeningIds);i.openings=(i.openings||[]).filter(e=>!t.has(e.id)),i.openings.length||delete i.openings}i.rooms=i.rooms.filter(t=>t.id!==n.id),this._cfgEpoch++,this._commitOpenSpans();const h=this._normalizeWalls(c,this._openCuts());h.length?i.walls=h:delete i.walls,this._roomDeleteDialog=null,this._recordGeometry(this._t(t?"history.delete_room_keep_walls":"history.delete_room_with_walls"),l),this._saveConfig(),this._regSignature="",this._maybeRebuildDevices(),this.requestUpdate()},this._rebindPartitionOpening=()=>{const t=this._openingDialog;if(!t?.id)return;const e=t.id;this._activateMarkupTool("opening"),"opening"===this._tool&&(this._openingRebindId=e,this._openingPreset={type:t.type,lengthCm:t.lengthCm,flipH:t.flipH,flipV:t.flipV,revision:++this._openingPresetRevision},this._openingDialog=null,this._openingHoverCandidate=null)},this._keepClosedAsPartitions=()=>{if(this._wallFaceBatch)return void this._decideWallFace(!1);if(!this._contourClosed||this._pendingSplit||!this._curSpaceCfg)return;const t=this._curSpaceCfg,e=this._path.slice(0,-1);if((t.partitions||[]).length+e.length>fm)return void this._showToast(this._t("toast.physical_limit"));const i=this._geometrySnapshot(),s=tp(e.length,[...this._draftSegmentCms,this._closingWallCm??void 0],this._drawWallCm,fr);t.partitions||=[];const n=Date.now().toString(36);for(let i=0;it.id!==this._activeDraftId),t.room_drafts.length||delete t.room_drafts),this._recordGeometry(this._t("history.contour_to_partitions"),i),this._saveConfig(),this._roomDialog=!1,this._path=[],delete this._resumeDraftBySpace[this._space],this._activeDraftId=null,this._draftSegmentCms=[],this._closingWallCm=null},this._toggleServerPlans=async()=>{const t=this._spaceDialog;if(t)if(t.pickSaved)this._spaceDialog={...t,pickSaved:!1};else{this._spaceDialog={...t,pickSaved:!0,savedBusy:!0};try{const t=await this.hass.callWS({type:"houseplan/plans/list"}),e=this._spaceDialog;e&&(this._spaceDialog={...e,saved:t?.plans||[],savedBusy:!1})}catch(t){const e=this._spaceDialog;e&&(this._spaceDialog={...e,saved:[],savedBusy:!1}),this._showToast(this._t("toast.plans_list_failed",{err:this._errText(t)}))}}},this._aspectJob=null,this._dayCycleTick=()=>{if(!this.isConnected||"hidden"===this.ownerDocument.visibilityState)return;const t=this._dayCycleState();if(!t)return this._dayCycleTimer&&(clearInterval(this._dayCycleTimer),this._dayCycleTimer=0),void(this._dayCycleClockKey="");const e=Wa(t);e!==this._dayCycleClockKey&&(this._dayCycleClockKey=e,this.requestUpdate())},this._sunShown=!1,this._sunOut=!1,this._sunOutTimer=0,this._openSettingsDialog=()=>{if(!this._norm)return;const t=this._glowRadiusCm,e=this._imperial?Math.round(t/30.48*10)/10:Math.round(t)/100;this._settingsDialog={colors:JSON.parse(JSON.stringify(this._fillColors)),glowRadius:e,bgColor:hs(this._settings,{bgColor:null})||null,northDeg:Za(this._settings,{}),bgMode:Qa(this._settings,{}),sunRays:tr(this._settings,{}),busy:!1}},this._openAlignDialog=()=>{if(!this._norm||!this._serverCfg)return;const t=this._serverCfg.spaces||[],e=Object.fromEntries(this._devices.filter(t=>!t.virtual&&!!t.area).map(t=>[t.id,t.area])),i=y_(this._serverCfg,this._layout||{},{effectiveAreaByMarker:e}),s=i.changed?this._checkOptimizeGeometry(i.config):null,n=Math.ceil(10*i.report.maxShiftCm)/10,o=t.find(t=>null!=t?.id&&String(t.id)===i.report.maxSpace),a=t.length>1&&o?String(o.title||o.id):"";this._alignDialog={report:i.report,config:i.config,layout:i.layout,cm:n,where:a,preflight:s,changed:i.changed,busy:!1}},this._optimizeUndoBusy=!1,this._openBackupExport=()=>{this._settingsDialog=null,this._backupExportDialog={kind:"full",planOnly:!1,busy:!1,error:""}},this._openRulesDialog=()=>{if(!this._norm)return;const t=this._settings.icon_rules,e=(t&&t.length?t:Xt).map(t=>({...t}));this._rulesDialog={rules:e,test:"",busy:!1}},this._climateCache=null,this._gearPtCache=new WeakMap}get _canEdit(){return!!this._norm&&(!0===this._serverCanWrite||!1!==this._serverCanWrite&&!0===this.hass?.user?.is_admin)}get _kiosk(){return!!this._config?.kiosk}_showKioskDots(){this._kioskDots=!0,clearTimeout(this._kioskDotsTimer),this._kioskDotsTimer=window.setTimeout(()=>this._kioskDots=!1,2500)}get _modeTransitionBusy(){return this._modeTransitionPreparing||this._modeTransition.active}_cssColor(t,e){const i=String(t||"").trim();if(!i)return e;const s=document.createElement("span");s.style.cssText=`position:absolute;visibility:hidden;color:${i}`,this.renderRoot.append(s);const n=getComputedStyle(s).color||e;return s.remove(),n}_currentModeVisual(t=this._mode){const e=this._modeTransition.presented||this._modeTransitionVisual;if(e)return{...e,viewport:{...e.viewport,viewBox:{...e.viewport.viewBox}}};const i=this._stageEl;if(!i||i.clientWidth<=0||i.clientHeight<=0)return null;const s=this.renderRoot.querySelector(".editorchrome"),n=this._viewOr(this._baseVb()),o=this.renderRoot.querySelector(".hp-paper"),a=this.renderRoot.querySelector(".hp-backdrop"),r=this.renderRoot.querySelector(".zoomwrap"),l=r?getComputedStyle(r).filter:"",c=Number(/brightness\(([^)]+)\)/.exec(l)?.[1]);return{presentedMode:t,editorChromeHeight:"view"===t?0:s?.getBoundingClientRect().height||0,stageWidth:i.clientWidth,stageHeight:i.clientHeight,viewport:z_(n,i.clientWidth),stageColor:getComputedStyle(i).backgroundColor||"rgb(255, 255, 255)",paperColor:o?getComputedStyle(o).fill:"rgb(255, 255, 255)",sceneBrightness:Number.isFinite(c)?c:1,architectureOpacity:"decor"===t?.35:1,backdropOpacity:a&&Number(getComputedStyle(a).opacity)||1,viewWeight:"view"===t?1:0,editorWeight:"view"===t?0:1,toolbarContentOpacity:"view"===t?0:1}}_viewForModeTarget(t,e,i,s,n){const o=Oi(this._baseVb(),s/Math.max(1,n)),a=Math.min(km.ZOOM_MAX,Math.max(km.ZOOM_MIN,t)),r=o.w/a,l=o.h/a,c=e??o.x+o.w/2,h=i??o.y+o.h/2;return this._clampView({x:c-r/2,y:h-l/2,w:r,h:l},o)}_targetStageColor(t){return"view"!==t?"rgb(255, 255, 255)":this._cssColor(this._stageBg(this._spaceDisplayForRender()),this._cssColor("var(--ha-card-background, var(--card-background-color, #111))","rgb(17, 17, 17)"))}_targetPaperColor(t){return"view"===t&&this._spaceModel()?.bg?this._cssColor("var(--ha-card-background, var(--card-background-color, #111))","rgb(17, 17, 17)"):"rgb(255, 255, 255)"}_targetBrightness(t){return 1}_applyModeTransitionFrame(t){t.targetMode===this._mode&&(this._modeTransitionVisual=t.presented,this._view={...t.presented.viewport.viewBox},this.requestUpdate())}_settleModeTransition(t){if(t.targetMode!==this._mode)return;const e=this._modeTransitionRequest;this._view={...t.to.viewport.viewBox},this._zoom=this._modeTransitionTargetZoom,this._modeTransitionVisual=null,this._modeTransitionPreparing=!1,this._lastValidStageSize=[t.to.stageWidth,t.to.stageHeight],"view"===this._mode&&(this._saveZoom(),this._viewModeSnap=null,this._modeTransitionEditorCamera=null),this.requestUpdate(),this.updateComplete.then(()=>{if(!this.isConnected||e!==this._modeTransitionRequest||this._modeTransitionBusy||t.targetMode!==this._mode)return;const i=this._stageEl;if(i&&i.clientWidth>0&&i.clientHeight>0&&(Math.abs(i.clientWidth-t.to.stageWidth)>.5||Math.abs(i.clientHeight-t.to.stageHeight)>.5)){const t=this._view;this._lastValidStageSize=[i.clientWidth,i.clientHeight],this._applyView(this._zoom,t?t.x+t.w/2:void 0,t?t.y+t.h/2:void 0),this.requestUpdate()}const s=this.renderRoot.activeElement;(!s||!s.isConnected||!!s.closest?.(".editorchrome, .stage"))&&this.renderRoot.querySelector(".modetab.active")?.focus?.({preventScroll:!0})})}_cancelModeTransition(t=!0){const e=!!this._modeTransition.state;this._modeTransitionRequest++,this._modeTransitionPreparing=!1,this._modeTransitionForceAtomic=!1,this._modeTransition.cancel(t),t&&e||(this._modeTransitionVisual=null)}_adoptMode(t){this._cancelModeTransition(!1),this._mode=t,"view"!==t&&(this._editorChromeMode=t)}_commitViewModeAtomic(t,e,i,s){if(this._modeTransitionPreparing=!1,this._modeTransitionVisual=null,this._modeTransitionForceAtomic=!1,this._zoom=e,t){const n=this._stageEl?.clientWidth||t.stageWidth,o=Math.max(1,t.stageHeight+t.editorChromeHeight);this._view=this._viewForModeTarget(e,i,s,n,o),this._lastValidStageSize=[n,o]}else this._view=null;this._viewModeSnap=null,this._modeTransitionEditorCamera=null,this._saveZoom(),this.requestUpdate()}_prepareModeTransition(t,e,i,s,n,o){this.updateComplete.then(()=>{if(!this.isConnected||t!==this._modeTransitionRequest||this._mode!==i)return void(t===this._modeTransitionRequest&&(this._modeTransitionPreparing=!1,this._modeTransitionVisual=null,this._modeTransitionForceAtomic=!1,this.requestUpdate()));const a=this.renderRoot.querySelector(".editorchrome"),r=a?.querySelector(".editorchrome-inner"),l="view"===i?0:r?.scrollHeight||r?.getBoundingClientRect().height||0,c=Math.max(1,e.stageHeight+e.editorChromeHeight),h=Math.max(1,c-l),d=this._stageEl?.clientWidth||e.stageWidth;if(d<=0||h<=0)return this._modeTransitionPreparing=!1,this._modeTransitionVisual=null,this._applyView(s,n,o),void this.requestUpdate();const p=this._viewForModeTarget(s,n,o,d,h),u={presentedMode:i,editorChromeHeight:l,stageWidth:d,stageHeight:h,viewport:z_(p,d),stageColor:this._targetStageColor(i),paperColor:this._targetPaperColor(i),sceneBrightness:this._targetBrightness(i),architectureOpacity:"decor"===i?.35:1,backdropOpacity:"decor"===i&&"backdrop"!==this._decorTool?.5:1,viewWeight:"view"===i?1:0,editorWeight:"view"===i?0:1,toolbarContentOpacity:"view"===i?0:1};this._modeTransitionPreparing=!1;const _=this._modeTransitionForceAtomic;this._modeTransitionForceAtomic=!1,this._modeTransition.start(e,u,i,this._reducedMotion||_?0:220)})}get _hasFixedFloor(){return!!this._config&&Object.prototype.hasOwnProperty.call(this._config,"floor")}_fixedFloorState(t=this._model,e=this._loadOk){const i=this._config?.floor,s=function(t){if(!t.hasFloor)return{kind:"absent"};const e=t.floor;if("string"==typeof e)return e.length?t.spaceIds.includes(e)?{kind:"valid",id:e,source:"id"}:{kind:"invalid",reason:"unknown-id",value:e}:{kind:"invalid",reason:"empty-id",value:e};if("number"==typeof e){if(!Number.isFinite(e))return{kind:"invalid",reason:"non-finite-index",value:e};if(!Number.isInteger(e))return{kind:"invalid",reason:"fractional-index",value:e};if(e<0)return{kind:"invalid",reason:"negative-index",value:e};const i=t.spaceIds[e];return void 0===i?{kind:"invalid",reason:"out-of-range-index",value:e}:{kind:"valid",id:i,source:"index"}}return{kind:"invalid",reason:"invalid-type",value:e}}({spaceIds:t.map(t=>t.id),hasFloor:this._hasFixedFloor,floor:i});return!this._hasFixedFloor||e?s:"number"==typeof i?"valid"===s.kind||"invalid"===s.kind&&"out-of-range-index"===s.reason?{kind:"pending",value:i}:s:"valid"===s.kind||"invalid"===s.kind&&"unknown-id"!==s.reason?s:{kind:"pending",value:i}}_canCommitSpace(t,e=!1){if(e||!this._hasFixedFloor)return!0;const i=this._fixedFloorState();return"valid"===i.kind&&i.id===t}_commitSpace(t,e=!1){return!!this._canCommitSpace(t,e)&&(t!==this._space&&(this._clearTransientHover(!0),this._cancelDevicePressFeedback()),this._space=t,!0)}_slideTo(t,e){if(t===this._space)return!0;if(!this._canCommitSpace(t))return!1;if(this._wallFaceBatch&&this._roomDialogCancel(),"plan"===this._mode&&"draw"===this._tool&&!this._finishWallChain())return!1;this._cancelModeTransition(!0);const i=window.matchMedia?.("(prefers-reduced-motion: reduce)")?.matches;return this._activeDraftId&&(this._resumeDraftBySpace[this._space]=this._activeDraftId),this._commitSpace(t),this._path=[],this._clearPlanSnapHover(),this._clearOpeningPlacement(!0),this._tool="draw",this._openWallAnchor=null,this._boundaryRestoreGuard=null,this._activeDraftId=null,this._draftSegmentCms=[],this._closingWallCm=null,this._selId=null,this._physicalSel=null,this._editorSecondary.closeForNavigation(),this._physicalDialog=null,this._physicalDrag=null,"plan"===this._mode&&"draw"===this._tool&&this._resumeLastDraft(),this._restoreZoom(),i||(this._slide=e,clearTimeout(this._slideTimer),this._slideTimer=window.setTimeout(()=>{this._slideTimer=void 0,this._slide="",this.requestUpdate()},190),this.requestUpdate()),!0}get _canReorderTabs(){return Gg({canEdit:this._canEdit,kiosk:this._kiosk,mode:this._mode,pointerType:"mouse",spaceCount:this._model.length,fixedFloor:this._hasFixedFloor})}_tabPointerDown(t,e){Gg({canEdit:this._canEdit,kiosk:this._kiosk,mode:this._mode,pointerType:t.pointerType,spaceCount:this._model.length,fixedFloor:this._hasFixedFloor})&&(wm(t),this._tabDragRelease=t=>this._tabPointerUp(t),window.addEventListener("pointerup",this._tabDragRelease),window.addEventListener("pointercancel",this._tabDragRelease),this._tabDrag={id:e,pointerId:t.pointerId,x:t.clientX,y:t.clientY,moved:!1,targetId:null,placement:null})}_tabDropTargetAt(t,e,i){const s=this._model.map(t=>t.id),n=s.indexOf(i);if(n<0)return null;const o=this.renderRoot.querySelectorAll('[data-hp="space-tab"]');for(const a of o){const o=a.dataset.id||"";if(!o||o===i)continue;const r=a.getBoundingClientRect();if(tr.right||er.bottom)continue;const l=s.indexOf(o);return l<0?null:{targetId:o,placement:l=4)))return;var i,s;const n=this._tabDropTargetAt(t.clientX,t.clientY,e.id);e.moved&&e.targetId===n?.targetId&&e.placement===n?.placement||(this._tabDrag={...e,moved:!0,targetId:n?.targetId||null,placement:n?.placement||null})}_tabPointerUp(t){const e=this._tabDrag;if(e&&e.pointerId!==t.pointerId)return;const i="pointerup"===t.type&&e?.moved?this._tabDropTargetAt(t.clientX,t.clientY,e.id):null;"pointerup"===t.type&&e?.moved&&this._suppressNextTabClick(),this._endTabDrag(),e?.moved&&i&&this._commitTabOrder(e.id,i.targetId)}_endTabDrag(){this._tabDrag=null,this._tabDragRelease&&(window.removeEventListener("pointerup",this._tabDragRelease),window.removeEventListener("pointercancel",this._tabDragRelease),this._tabDragRelease=null)}_tabClick(t){if(this._tabSuppressClick)return this._tabSuppressClick=!1,clearTimeout(this._tabSuppressClickTimer),void(this._tabSuppressClickTimer=void 0);this._pickSpace(t)}_suppressNextTabClick(){this._tabSuppressClick=!0,clearTimeout(this._tabSuppressClickTimer),this._tabSuppressClickTimer=window.setTimeout(()=>{this._tabSuppressClick=!1,this._tabSuppressClickTimer=void 0},0)}_commitTabOrder(t,e){const i=this._serverCfg;if(!i||!this._canReorderTabs)return;const s=this._model.map(t=>t.id),n=function(t,e,i){const s=t.indexOf(e),n=t.indexOf(i);if(s<0||n<0||s===n)return t;const o=t.slice();return o.splice(s,1),o.splice(n,0,e),o}(s,t,e);if(n===s)return;const o=new Map(this._devices.map(t=>[String(t.id),String(t.area||"")])),a=function(t,e,i,s=()=>""){if(!i)return[];const n=[];for(const o of t){if(!o||!0===o.removed)continue;const t="string"==typeof o.id?o.id:"";if(!t)continue;if("string"==typeof o.space&&o.space)continue;const a=("string"==typeof o.area?o.area:"")||s(t)||"";a&&e[a]||n.push({id:t,space:i})}return n}(i.markers||[],Object.fromEntries(Object.entries(this._areaToSpace).map(([t,e])=>[t,e.space])),s[0]||"",t=>o.get(t)||"");if(a.length){const t=new Map(a.map(t=>[t.id,t.space]));for(const e of i.markers||[]){const i=t.get(String(e.id));i&&(e.space=i)}}i.spaces=function(t,e){const i=new Map(e.map((t,e)=>[t,e]));return t.map((t,e)=>({space:t,index:e})).sort((t,e)=>(i.get(String(t.space?.id))??Number.MAX_SAFE_INTEGER)-(i.get(String(e.space?.id))??Number.MAX_SAFE_INTEGER)||t.index-e.index).map(t=>t.space)}(i.spaces||[],n),this._saveConfig(),this._tabOrderWarned||(this._tabOrderWarned=!0,this._showToast(this._t("toast.space_order_changed")))}_pickSpace(t){if(this._endTabDrag(),t===this._space)return;const e=this._model.map(t=>t.id),i=e.indexOf(this._space),s=e.indexOf(t);this._navApplied=!0,this._showFar=!1,this._frame=null,this._slideTo(t,i>=0&&s0&&Date.now()>=this._cyclePausedUntil&&this._model.length>1&&this._zoom<=1.001){const t=this._model.map(t=>t.id),e=t.indexOf(this._space);this._slideTo(t[(e+1)%t.length],"left"),this._showKioskDots()}}_syncCycleTimer(){clearInterval(this._cycleTimer),this._cycleTimer=void 0,this.isConnected&&!this._hasFixedFloor&&this._config?.kiosk&&Number(this._config.cycle)>0&&(this._cycleTimer=window.setInterval(()=>this._cycleTick(),1e3*Number(this._config.cycle)))}get _editing(){return"plan"===this._mode||"devices"===this._mode||"decor"===this._mode}get _markup(){return"plan"===this._mode}_newContinuityController(){return new Ch(()=>{this._resumeSettling="steady"!==this._continuity.state,this._continuityEpoch++,this.isConnected&&this.requestUpdate()})}get _labsIso(){return this._labs.active.includes("iso")}get _desiredProjection(){return"view"===this._mode&&this._labsIso&&"iso"===this._viewPreference[this._space]?"iso":"flat"}_saveViewPreference(){try{localStorage.setItem(dm,JSON.stringify(this._viewPreference))}catch{}}_logicalViewCenter(t){const e=this._view;if(!e)return null;const i=[e.x+e.w/2,e.y+e.h/2],s="iso"===t?cg(i):i;return{x:s[0],y:s[1]}}_convertProjectionView(t,e){if(t===e)return;const i=this._logicalViewCenter(t);this._view=null;const s=i?"iso"===e?lg([i.x,i.y],0):[i.x,i.y]:null;this._applyView(this._zoom,s?.[0],s?.[1]),this._warmPatch({vp:this._warmViewportState()}),this.requestUpdate()}_setProjection(t){if(!this._labsIso||"view"!==this._mode)return;const e=this._effectiveProjection();if(this._viewPreference={...this._viewPreference,[this._space]:t},"iso"===t){const t=this._isoSceneKey();t&&this._isoFallback.delete(t)}this._saveViewPreference();const i=this._effectiveProjection();this._convertProjectionView(e,i)}_hashSpace(){return Y_(window.location.hash||"")}connectedCallback(){this._connectedPath=location.pathname,this._routeDepartureHandled=!1,window.addEventListener("location-changed",this._onLocationChanged),window.addEventListener("popstate",this._onLocationChanged),this._continuityDisposed&&(this._continuity=this._newContinuityController(),this._continuityDisposed=!1,this._continuityPaintToken=-1);const t=(e=this.ownerDocument,T_.get(e)?.resolved);var e;void 0!==t&&(this._glowScreenBlend=t),this._continuityUnsub?.(),this._continuityUnsub=Sh(this.ownerDocument,this._pageVisibility),super.connectedCallback(),this._pointerModality.connect(this.ownerDocument.defaultView);const i=this.ownerDocument.defaultView?.MutationObserver;i&&(this._pointerHoverObserver=new i(t=>{for(const e of t)for(const t of e.addedNodes)this._syncPointerHoverSubtree(t)}),this._pointerHoverObserver.observe(this.renderRoot,{childList:!0,subtree:!0})),this._motionMedia=window.matchMedia?.("(prefers-reduced-motion: reduce)"),this._reducedMotion=!!this._motionMedia?.matches,this._motionMedia?.addEventListener?.("change",this._onMotionChange),function(t){const e=T_.get(t);if(e)return e.promise;const i={promise:Promise.resolve(!1)};return i.promise=R_(t).catch(()=>!1).then(t=>(i.resolved=t,t)),T_.set(t,i),i.promise}(this.ownerDocument).then(t=>{t!==this._glowScreenBlend&&(this._glowScreenBlend=t,this.isConnected&&this.requestUpdate())}),this.hass&&this._ensureHaRegistryAuthority(),window.addEventListener("keydown",this._keyHandler),this._signer.start(()=>this.hass,()=>Is(this._serverCfg)),this._syncCycleTimer(),window.addEventListener("hashchange",this._onHashChange),this._labsUnsub?.(),this._labsUnsub=function(t,e){ig.add(e);const i=og(t);return"undefined"==typeof window&&e(i),()=>{ig.delete(e)}}(Vg,this._onLabsSnapshot),this._booting?this._bootWatch():this._bootFading&&(clearTimeout(this._bootTimer),this._bootTimer=window.setTimeout(()=>{this._bootFading=!1},220)),this._bootSoft&&(clearTimeout(this._bootSoftTimer),this._bootSoftTimer=window.setTimeout(()=>{this._bootSoft=!1},Zg)),!this._loadOk&&this._serverCfg&&this.hass&&this._scheduleLoadRetry(),!this._warmSlot&&this._config&&this._warmAdopt(),this._loadOk&&this._ensureLiveSyncSubscriptions(),this._warmVp&&!this._warmRevivePending&&void 0===this._warmReviveTimer&&(this._warmRevivePending=!0,this._warmReviveTimer=window.setTimeout(()=>this._warmReviveDialog(),0)),this._warmLongReturn&&this._beginResumeSettle(),this._warmLongReturn=!1,this.requestUpdate()}disconnectedCallback(){this._connectedPath&&location.pathname!==this._connectedPath&&this._leaveCardRoute(),window.removeEventListener("location-changed",this._onLocationChanged),window.removeEventListener("popstate",this._onLocationChanged),this._continuityUnsub?.(),this._continuityUnsub=void 0,this._motionMedia?.removeEventListener?.("change",this._onMotionChange),this._motionMedia=void 0,this._vacRaf&&(cancelAnimationFrame(this._vacRaf),this._vacRaf=0),this._refitRaf&&(cancelAnimationFrame(this._refitRaf),this._refitRaf=0),this._dayCycleTimer&&(clearInterval(this._dayCycleTimer),this._dayCycleTimer=0),this._dayCycleClockKey="",this._bootSettleRaf&&(cancelAnimationFrame(this._bootSettleRaf),this._bootSettleRaf=0),this._bootSettling=!1;for(const t of this._activityRt.values())clearTimeout(t.timer);window.removeEventListener("keydown",this._keyHandler),this._endTabDrag(),clearTimeout(this._tabSuppressClickTimer),this._tabSuppressClickTimer=void 0,this._tabSuppressClick=!1,clearInterval(this._cycleTimer),clearTimeout(this._kioskDotsTimer),clearTimeout(this._kioskHoldTimer),clearTimeout(this._reloadRetry),clearTimeout(this._loadRetryTimer),this._loadRetryTimer=void 0,this._connHooked?.removeEventListener?.("ready",this._onConnReady),this._connHooked?.removeEventListener?.("disconnected",this._onConnLost),this._connHooked?.removeEventListener?.("reconnect-error",this._onConnLost),this._connHooked=null,this._haRegistryRelease?.(),this._haRegistryRelease=void 0,this._haRegistryConnection=null,this._signer.dispose(),clearTimeout(this._toastTimer),clearTimeout(this._slideTimer),this._modeTransition.dispose(),this._modeTransitionVisual=null,this._modeTransitionPreparing=!1,this._modeTransitionForceAtomic=!1,this._modeTransitionRequest++,this._slideTimer=void 0,this._slide="",clearTimeout(this._bootTimer),this._bootTimer=void 0,clearTimeout(this._bootSoftTimer),this._saveConfigDebounced.flush(),window.removeEventListener("hashchange",this._onHashChange),this._labsUnsub?.(),this._labsUnsub=void 0,clearTimeout(this._holdTimer),this._roViewport?.disconnect(),this._roViewport=void 0,this._roHdr?.disconnect(),this._roHdr=void 0,this._onWinResize&&(window.removeEventListener("resize",this._onWinResize),this._onWinResize=void 0),this._unsubCfg&&(this._unsubCfg(),this._unsubCfg=null),this._unsubLayout&&(this._unsubLayout(),this._unsubLayout=null),this._unsubVirtual&&(this._unsubVirtual(),this._unsubVirtual=null),this._unsubTrail&&(this._unsubTrail(),this._unsubTrail=void 0),this._liveSyncGeneration++,this._liveSyncAttempt=null,this._liveSyncConnection=null,clearTimeout(this._layoutSyncTimer),clearTimeout(this._duplicateColumnTimer);for(const t of this._glowFadeTimers.values())clearTimeout(t);for(const t of this._glowEnterRafs.values())cancelAnimationFrame(t);clearTimeout(this._glowFeatherResumeTimer),this._glowFeatherResumeTimer=0,this._glowFeatherSuspendUntil=0,this._glowFadeTimers.clear(),this._glowEnterRafs.clear(),this._glowEnteringSources.clear(),this._glowRenderedSources.clear(),this._glowLastAppearance.clear(),this._glowSourceSeq=0,this._warmSnapshot(),this._warmRevivePending=!1,clearTimeout(this._warmReviveTimer),this._warmReviveTimer=void 0,this._warmRelease(),this._openWallAnchor=null,this._boundaryRestoreGuard=null,this._clearPlanSnapHover(),this._clearOpeningPlacement(!0),this._touchContacts.clear(),this._touchSequenceMultitouch=!1,this._touchClickBlockUntil=0,this._clearTransientHover(!0),this._cancelDevicePressFeedback(),this._pointerHoverObserver?.disconnect(),this._pointerHoverObserver=void 0,this._pointerModality.disconnect(),this._editorSecondary.reset(),this._resumeSettling=!1,this._continuityHistory=[...this._continuityHistory,...this._continuity.trace].slice(-80),this._continuity.dispose(),this._continuityDisposed=!0,super.disconnectedCallback()}_onKey(t){if("Escape"===t.key&&this._vacFit)return this._vacFit=null,this._showToast(this._t("vac.cal_cancelled")),void t.stopPropagation();if("Escape"===t.key){if(this._tapConfirm)return void(this._tapConfirm=null);if(this._vacCalConfirm)return void(this._vacCalConfirm=null);if(this._decorEraseConfirm)return void(this._decorEraseConfirm=null);if(this._openingInfo)return void(this._openingInfo=null);if(this._infoCard)return void this._closeInfoCard();if(this._rulesDialog)return void(this._rulesDialog=null);if(this._alignDialog)return void(this._alignDialog=null);if(this._backupImportDialog)return void(this._backupImportDialog=null);if(this._backupExportDialog)return void(this._backupExportDialog=null);if(this._settingsDialog)return void(this._settingsDialog=null);if(this._markerDialog)return void(this._markerDialog=null);if(this._openingDialog)return void(this._openingDialog=null);if(this._physicalDialog)return void(this._physicalDialog=null);if(this._backdropDialog)return void(this._backdropDialog=null);if(this._decorShapeDialog)return void(this._decorShapeDialog=null);if(this._decorTextDialog)return void(this._decorTextDialog=null);if(this._spaceDialog&&!this._roomDialog)return this._spaceDialog=null,this._importQueue=[],void(this._importTotal=0);if(this._editorSecondary.hasOpenGroup)return t.preventDefault(),void this._editorSecondary.closeGroup(!0)}const e=t.composedPath?.()||[t.target],i=e.some(t=>t?.matches?.('input, textarea, select, [contenteditable="true"]')),s=e.some(t=>t?.classList?.contains?.("editor-secondary")),n=t.ctrlKey||t.metaKey,o=t.key.toLowerCase(),a=/^[a-z]$/.test(o),r="z"===o||!a&&"KeyZ"===t.code,l="y"===o||!a&&"KeyY"===t.code,c=n&&(r&&t.shiftKey||l),h=n&&r&&!t.shiftKey;if("decor"===this._mode){if((h||c)&&i)return;return c?(t.preventDefault(),void this._redoGeometry()):h?(t.preventDefault(),this._decorDraft?void(this._decorDraft=null):this._decorMove||this._dtDrag||this._bdDrag?void this._cancelDecorGesture():void this._undoGeometry()):"Delete"!==t.key&&"Backspace"!==t.key||!this._decorSel||i||s?void("Escape"===t.key&&(t.preventDefault(),this._decorDraft?this._decorDraft=null:this._decorMove||this._dtDrag||this._bdDrag?this._cancelDecorGesture():"furniture"===this._decorTool?(this._furnPalette=null,this._decorTool="select"):this._decorSel?this._decorSel=null:"select"!==this._decorTool?this._decorTool="select":this._setMode("view"))):(t.preventDefault(),void this._decorDeleteSel())}if(this._markup&&(!h&&!c||!i)){if(("Delete"===t.key||"Backspace"===t.key)&&this._physicalSel&&!i&&!s)return t.preventDefault(),void this._deletePhysicalSelection();if(c)return t.preventDefault(),void this._redoGeometry();if(h)return t.preventDefault(),this._rszDrag?void this._rszCancelDrag():this._wallFaceBatch?(this._roomDialogCancel(),void(this._activeDraftId&&this._path.length>1?this._undoActiveDraftPoint():this._undoPoint())):"draw"===this._tool&&this._path.length?void(this._activeDraftId&&this._path.length>1?this._undoActiveDraftPoint():this._undoPoint()):"split"===this._tool&&this._splitSel?.pts?.length?(this._splitSel={...this._splitSel,pts:this._splitSel.pts.slice(0,-1)},void(this._splitSel.pts.length||(this._cursorPt=null))):void this._undoGeometry();if("Escape"===t.key)return this._physicalDrag||this._physicalRotate?(t.preventDefault(),void this._cancelPhysicalGesture()):this._roomDialog?(t.preventDefault(),void this._roomDialogCancel()):"draw"===this._tool&&this._path.length?(t.preventDefault(),void this._undoPoint()):this._physicalSel?(t.preventDefault(),void(this._physicalSel=null)):"resize"===this._tool?(t.preventDefault(),this._rszDrag?void this._rszCancelDrag():void(this._rszSel?this._rszSel=null:this._tool="draw")):"split"===this._tool?(t.preventDefault(),void(this._splitSel?.pts?.length?(this._splitSel={...this._splitSel,pts:this._splitSel.pts.slice(0,-1)},this._splitSel.pts.length||(this._cursorPt=null)):this._splitSel?this._splitSel=null:this._tool="draw")):"merge"===this._tool?(t.preventDefault(),void(this._mergeSel?this._mergeSel=null:this._tool="draw")):this._wallDialog?(t.preventDefault(),void(this._wallDialog=null)):"boundary"===this._tool?(t.preventDefault(),void(this._openWallAnchor?this._cancelBoundaryAnchor():this._tool="draw")):void("opening"!==this._tool&&"wallthick"!==this._tool&&"delroom"!==this._tool&&"column"!==this._tool||(t.preventDefault(),"opening"===this._tool&&this._clearOpeningPlacement(!0),this._tool="draw"))}}_undoPoint(){if(this._path.length){if(this._contourClosed)return this._path=this._path.slice(0,-1),void(this._closingWallCm=null);if(this._activeDraftId&&this._path.length>1&&this._curSpaceCfg){const t=this._geometrySnapshot();this._path=this._path.slice(0,-1),this._draftSegmentCms=this._draftSegmentCms.slice(0,-1);const e=this._curSpaceCfg,i=(e.room_drafts||[]).findIndex(t=>t.id===this._activeDraftId);return void(i>=0&&(this._path.length<2?(e.room_drafts.splice(i,1),e.room_drafts.length||delete e.room_drafts,this._activeDraftId=null):e.room_drafts[i]={id:this._activeDraftId,points:this._path.map(t=>[t[0]/um,t[1]/um]),segments:this._draftSegmentCms.map(t=>({cm:t}))},this._recordGeometry(this._t("history.draft_segment_delete"),t),this._saveConfig()))}this._path=this._path.slice(0,-1)}}_undoActiveDraftPoint(){const t=this._activeDraftId,e=this._path[0]?[...this._path[0]]:null,i=this._geometryHistory.undo();if(!i)return void this._undoPoint();if(!this._applyGeometryState(i.before))return void this._geometryHistory.clear();const s=t?this._spaceModel()?.room_drafts.find(e=>e.id===t):null;s?(this._activeDraftId=s.id,this._path=s.points.map(t=>[...t]),this._draftSegmentCms=this._adoptDraftCms(this._path,s.segments.map(t=>t.cm),s.id),this._resumeDraftBySpace[this._space]=s.id):(this._activeDraftId=null,this._path=e?[e]:[],this._draftSegmentCms=[],t&&this._resumeDraftBySpace[this._space]===t&&delete this._resumeDraftBySpace[this._space]),this._clearPlanSnapHover(),this._showToast(this._t("history.undone",{name:i.name}))}static getConfigElement(){return document.createElement("houseplan-card-editor")}static getStubConfig(){return{type:"custom:houseplan-card"}}static _warmBootReset(t){for(const t of im.values())for(const e of t)clearTimeout(e.evict);im.clear(),om=t&&t>0?t:1e4}static _warmBootStats(){let t=0,e=0;const i=[];for(const s of im.values())for(const n of s)t++,n.dlg&&(e++,i.push(n.dlg.kind));return{keys:im.size,slots:t,dlgs:e,drafts:i}}setConfig(t){const e=this._config,i=!!e&&Object.prototype.hasOwnProperty.call(e,"floor");this._config={icon_size:2.5,show_temperature:!0,live_states:!0,show_signal:!0,...t};(i!==this._hasFixedFloor||e?.floor!==this._config.floor)&&(this._hashApplied=!1,this._navApplied=!1,this._warmVpArmed=!1),this._config.kiosk&&(this._booting=!1,this._bootFading=!1),!this._hasFixedFloor&&t.default_floor&&this._commitSpace(t.default_floor,!0);try{this._zoomBySpace=JSON.parse(localStorage.getItem(lm)||"{}")||{}}catch{this._zoomBySpace={}}try{const t=JSON.parse(localStorage.getItem(dm)||"{}")||{};this._viewPreference=Object.fromEntries(Object.entries(t).filter(t=>"flat"===t[1]||"iso"===t[1]))}catch{this._viewPreference={}}this._labs=og(Vg);try{const t=JSON.parse(localStorage.getItem(hm)||"null");this._kioskScale={icon:zs(t?.icon),font:zs(t?.font)}}catch{}try{const t=JSON.parse(localStorage.getItem(rm)||"null");t&&t.config&&Array.isArray(t.config.spaces)&&(this._serverCfg=t.config,this._cfgEpoch++,this._cfgRev=t.rev||0,this._cfgContentFingerprint=t.config_fingerprint||Dh(t.config),this._layout=t.layout||{},this._layoutRev=t.layout_rev||0,this._layoutContentFingerprint=t.layout_fingerprint||Dh(this._layout),this._virtualLights=gn(t.virtual_lights,this._cfgRev),this._serverStorage=!0)}catch{}this._adoptInitialSpace(this._model,this._loadOk),"view"!==this._mode||this._view||(this._zoom=this._zoomBySpace[this._space]||1),this.isConnected&&(this._syncCycleTimer(),this._warmAdopt(),this._warmLongReturn&&this._beginResumeSettle(),this._warmLongReturn=!1)}_warmAdopt(){if(this._config?.kiosk)return;const t=nm(this._config);if(this._warmKey===t&&this._warmSlot)return;this._warmSlot&&this._warmRelease();const e=this.parentNode,i=this._warmIdx(e),s=im.get(t);if(!s||!s.length)return;const n=s.find(t=>t.owner===this._warmGen);if(n)return this._warmLongReturn=!!n.freed&&Date.now()-n.freed>=kh,clearTimeout(n.evict),n.evict=0,n.freed=0,n.live=!0,this._warmSlot=n,this._warmKey=t,n.frameFingerprint&&this._continuity.adoptCompleteFrame(n.frameFingerprint),void(!this._devices.length&&n.devices?.length&&(this._devices=[...n.devices]));const{slot:o,sure:a}=((t,e,i,s)=>{const n=t=>{const e=!!i&&t.place?.deref()===i;return e&&t.idx===s?4:t.live?0:e?3:2};let o=null,a=0,r=0,l=null;for(const i of t){if(i.owner===e)continue;l=i;const t=n(i);t<=0||(t>a?(o=i,a=t,r=1):t===a&&r++)}return!o||r>1?{slot:o||l,sure:!1}:{slot:o,sure:!0}})(s,this._warmGen,e,i);o&&(this._warmLongReturn=!!o.freed&&Date.now()-o.freed>=kh,this._booting=!1,this._bootFading=!1,this._hdrH=o.hdrH,this._bootSoft=!0,this.isConnected&&(clearTimeout(this._bootSoftTimer),this._bootSoftTimer=window.setTimeout(()=>{this._bootSoft=!1},Zg)),this._warmKey=t,a?(clearTimeout(o.evict),o.evict=0,o.owner=this._warmGen,o.place=e?new WeakRef(e):null,o.idx=i,o.live=!0,this._warmSlot=o,this._warmVp=o.vp,o.frameFingerprint&&this._continuity.adoptCompleteFrame(o.frameFingerprint),!this._devices.length&&o.devices?.length&&(this._devices=[...o.devices]),this._warmAdoptViewport(this._config)):(this._warmSlot={owner:this._warmGen,path:location.pathname,place:e?new WeakRef(e):null,idx:i,live:!0,hdrH:o.hdrH,stageH:o.stageH,vp:null,frameFingerprint:"",devices:null,dlg:null,freed:0,evict:0},s.push(this._warmSlot),this._warmTrim(s)))}_warmIdx(t){const e=t?.children;if(!e)return-1;for(let t=0;t4;){const e=t.findIndex(t=>!t.live);if(e<0)break;clearTimeout(t[e].evict),t.splice(e,1)}}_warmScheduleEvict(t,e){if(clearTimeout(t.evict),!(t.dlg||t.vp&&"view"!==t.vp.mode))return;const i=t.freed,s=t.owner;t.evict=window.setTimeout(()=>{if(t.evict=0,t.freed!==i||t.owner!==s)return;var n;t.dlg=null,t.vp=(n=t.vp)&&"view"!==n.mode?{...n,mode:"view",zoom:n.snap?.space===n.space?n.snap.zoom:n.zoom,view:null,snap:null,tool:"draw",decorTool:"select",showHidden:!1,selId:null,rszSel:null,decorSel:null}:n,t.frameFingerprint="";const o=im.get(e);if(!t.live&&o&&o.length>1){const e=o.indexOf(t);e>=0&&o.splice(e,1)}},om+250)}_warmAdoptViewport(t){const e=this._warmVp;if(!e||this._warmSlot?.path!==location.pathname)return void(this._warmVp=null);const i=this._fixedFloorState();if(this._hashApplied||!this._model.find(t=>t.id===e.space)||"valid"===i.kind&&i.id!==e.space||this._hasFixedFloor&&"valid"!==i.kind)return void(this._warmVp=null);this._commitSpace(e.space,!0),this._navApplied=!0,this._adoptMode("view"!==e.mode&&this._canEdit&&!t.kiosk?e.mode:"view"),this._pendingNavMode="view"===e.mode||this._canEdit||t.kiosk?null:e.mode,this._zoom=e.zoom;const s=this._effectiveProjection(),n=s===e.projection&&this._labsIso===e.activeLabsIso;if(this._view=n&&e.view?{...e.view}:null,this._viewModeSnap=n&&e.snap?{...e.snap}:null,!n&&e.logicalCenter){const t="iso"===s?lg([e.logicalCenter.x,e.logicalCenter.y],0):[e.logicalCenter.x,e.logicalCenter.y];this._applyView(e.zoom,t[0],t[1])}var o;this._tool="openwall"===(o=e.tool)||"closewall"===o?"boundary":"opening"===(o=function(t){return"partition"===t?"draw":t}(o))?"draw":"string"==typeof o&&mm.has(o)?o:"draw",this._decorTool=e.decorTool,this._showHidden=e.showHidden,this._showFar!==e.showFar&&(this._showFar=e.showFar,this._frame=null),this._selId=e.selId,this._rszSel=e.rszSel,this._decorSel=e.decorSel,this._warmVpArmed=!0}_warmPatch(t,e=!1){if(this._config?.kiosk)return;const i=nm(this._config);if(!this._warmSlot||this._warmKey===i){if(!this._warmSlot){if(!e)return;const t=this.parentNode;this._warmKey=i,this._warmSlot={owner:this._warmGen,path:location.pathname,place:t?new WeakRef(t):null,idx:this._warmIdx(t),live:!0,hdrH:this._hdrH,stageH:0,vp:null,frameFingerprint:"",devices:null,dlg:null,freed:0,evict:0};const s=im.get(i)||[];for(s.push(this._warmSlot),im.set(i,s),this._warmTrim(s);im.size>8;){const t=im.keys().next().value;if(void 0===t||t===i)break;for(const e of im.get(t)||[])clearTimeout(e.evict);im.delete(t)}}Object.assign(this._warmSlot,t)}}_warmViewportState(){const t=this._effectiveProjection();return{space:this._space,mode:this._mode,projection:t,activeLabsIso:this._labsIso,logicalCenter:this._logicalViewCenter(t),zoom:this._zoom,view:this._view?{...this._view}:null,snap:this._viewModeSnap?{...this._viewModeSnap}:null,tool:this._tool,decorTool:this._decorTool,showHidden:this._showHidden,showFar:this._showFar,selId:this._selId,rszSel:this._rszSel,decorSel:this._decorSel}}_warmDialogState(){const t=(t,e)=>({kind:t,space:this._space,mode:this._mode,data:e});return this._tapConfirm||this._alignDialog||this._mergeDialog||this._importDialog||this._backupExportDialog||this._backupImportDialog?null:this._openingInfo?t("openingInfo",this._openingInfo.id):this._infoCard?t("info",this._infoCard.id):this._rulesDialog?this._rulesDialog.busy?null:t("rules",this._rulesDialog):this._settingsDialog?this._settingsDialog.busy?null:t("settings",this._settingsDialog):this._markerDialog?this._markerDialog.busy?null:t("marker",this._markerDialog):this._openingDialog?t("opening",this._openingDialog):this._backdropDialog?t("backdrop",this._backdropDialog):this._decorShapeDialog?t("decorShape",this._decorShapeDialog):this._decorTextDialog?t("decorText",this._decorTextDialog):this._roomDialog?t("room",{editId:this._roomEditId,fill:this._roomFill,customFill:this._roomCustomFill,tempSrc:this._roomTempSrc,humSrc:this._roomHumSrc,srcOpen:this._roomSrcOpen,srcFilter:this._roomSrcFilter,nameScale:this._roomNameScale,labelScale:this._roomLabelScale,areaSel:this._areaSel,nameSel:this._nameSel,pendingSplit:this._pendingSplit,wallFaceBatch:this._wallFaceBatch,path:this._path}):this._spaceDialog?this._spaceDialog.busy?null:t("space",this._spaceDialog):null}_warmSnapshot(){if(this._booting||this._config?.kiosk||"steady"!==this._continuity.state)return;const t={vp:this._warmViewportState(),frameFingerprint:this._continuity.frameFingerprint,devices:this._devices};if(this._warmRevivePending||(t.dlg=this._warmDialogState()),this.isConnected&&this._warmSlot?.owner===this._warmGen){const e=this.parentNode;t.place=e?new WeakRef(e):null,t.idx=this._warmIdx(e)}this._warmPatch(t)}_warmReviveDialog(){this._warmRevivePending=!1;const t=this._warmSlot;if(this._warmReviveTimer=void 0,!t||!t.dlg)return;const e=t.dlg,i=t.freed;if(t.dlg=null,t.freed=0,clearTimeout(t.evict),t.evict=0,i&&!(Date.now()-i>om)&&e.space===this._space&&e.mode===this._mode){switch(e.kind){case"space":this._spaceDialog={...e.data,busy:!1,savedBusy:!1};break;case"marker":this._markerDialog={...e.data,busy:!1};break;case"settings":this._settingsDialog={...e.data,busy:!1};break;case"rules":this._rulesDialog={...e.data,busy:!1};break;case"opening":this._openingDialog={...e.data};break;case"backdrop":this._backdropDialog={...e.data};break;case"decorShape":this._decorShapeDialog={...e.data};break;case"decorText":{this._decorTextDialog={...e.data};const t=String(this._decorTextDialog?.text??"").length;this._decorTextSelection={start:t,end:t};break}case"room":{const t=e.data;this._roomEditId=t.editId,this._roomFill=t.fill,this._roomCustomFill=t.customFill||null,this._roomTempSrc=t.tempSrc,this._roomHumSrc=t.humSrc,this._roomSrcOpen=t.srcOpen,this._roomSrcFilter=t.srcFilter,this._roomNameScale=t.nameScale,this._roomLabelScale=t.labelScale,this._areaSel=t.areaSel,this._nameSel=t.nameSel,this._pendingSplit=t.pendingSplit,this._wallFaceBatch=t.wallFaceBatch||null,this._path=t.path,this._wallFaceBatch&&(this._activeDraftId=this._wallFaceBatch.activeDraftId,this._draftSegmentCms=[...this._wallFaceBatch.activeCms]),this._roomDialog=!0;break}case"info":{const t=this._devices.find(t=>t.id===e.data);t&&(this._infoCard=t);break}case"openingInfo":{const t=(this._curSpaceCfg?.openings||[]).find(t=>t.id===e.data);t&&(this._openingInfo=t);break}}this.requestUpdate()}}_cacheSnapshot(){if(this._serverCfg)try{this._cfgContentFingerprint=Dh(this._serverCfg),this._layoutContentFingerprint=Dh(this._layout),this._virtualLights=function(t,e,i){if(t.configRev===i)return t;const s=new Set((Array.isArray(e?.markers)?e.markers:[]).filter(yn).map(t=>t.id));return{...t,configRev:i,off:new Set([...t.off].filter(t=>s.has(t)))}}(this._virtualLights,this._serverCfg,this._cfgRev),localStorage.setItem(rm,JSON.stringify({config:this._serverCfg,rev:this._cfgRev,config_fingerprint:this._cfgContentFingerprint,layout:this._layout,layout_rev:this._layoutRev,layout_fingerprint:this._layoutContentFingerprint,virtual_lights:fn(this._virtualLights)}))}catch{}}_beginContinuityCandidate(t,e,i="plan"){return this._booting&&!this._continuity.hasCompleteFrame?this._continuity.token:(this._continuityDataReady=e,this._continuityPaintToken=-1,this._stagedDeviceSnapshotToken=-1,this._resumeSettling=!0,this._continuity.beginCandidate(t,i))}_continuityStageValid(){const t=this._stageEl;return!!t&&t.clientWidth>0&&t.clientHeight>0}_continuityAssetsReady(){if(!this._model.length)return!1;const t=this._model.length?this._spaceModel():null;return!t?.bg?.href||this._signer.isReady(this.hass,t.bg.href)}_initialSpaceSelection(t,e=this._loadOk){const i=this._fixedFloorState(t,e);return"valid"===i.kind?{id:i.id,source:"fixed"}:this._hasFixedFloor?{id:null,source:"none"}:function(t){const e=new Set(t.spaceIds.filter(t=>!!t));if(!e.size)return{id:null,source:"none"};const i=[["hash",!1===t.acceptHash?null:t.hashSpace],["current",t.preserveCurrent?t.currentSpace:null],["saved",t.savedSpace],["default",t.defaultSpace],["first",t.spaceIds[0]]];for(const[t,s]of i)if(s&&e.has(s))return{id:s,source:t};return{id:null,source:"none"}}({spaceIds:t.map(t=>t.id),hashSpace:this._hashSpace(),acceptHash:!this._hashApplied,currentSpace:this._space,preserveCurrent:this._hashApplied||this._navApplied||this._warmVpArmed,savedSpace:this._savedNav()?.space,defaultSpace:this._config?.default_floor})}_adoptInitialSpace(t,e=this._loadOk){const i=this._initialSpaceSelection(t,e);return i.id?(this._commitSpace(i.id,!0),"hash"===i.source&&(this._hashApplied=!0),"saved"===i.source&&(this._navApplied=!0),i):i}_candidateBackdrop(t,e=this._space){const i=yc(t),s=this._fixedFloorState(i,!0);if(this._hasFixedFloor&&"valid"!==s.kind)return"";const n=this._initialSpaceSelection(i,!0).id||(i.some(t=>t.id===e)?e:i[0]?.id);return i.find(t=>t.id===n)?.bg?.href||""}_visualFrameFingerprint(){const t=this._stageEl,e=t?[t.clientWidth,t.clientHeight]:[0,0];return Th([this._cfgRev,this._cfgContentFingerprint||Dh(this._serverCfg),this._layoutRev,this._layoutContentFingerprint||Dh(this._layout),this._space,this._mode,this._view,e,this._glowScreenBlend?"screen":"normal",this.hass?.themes?.darkMode??this.hass?.themes?.default_theme??""])}_settleContinuityFrame(){if(this._booting||!this._continuityStageValid())return;if(!this._continuity.hasCompleteFrame&&"steady"===this._continuity.state)return void(this._continuityAssetsReady()&&(this._renderSnapshotAt=Date.now(),this._continuity.markCompleteFrame(this._visualFrameFingerprint())));if(!this._continuityDataReady)return;if(!["holding","offline-stale","overlay-pending","overlay-visible","candidate-ready"].includes(this._continuity.state))return;const t=this._continuity.token;if(this._candidateDeviceSnapshot&&this._candidateDeviceSnapshot!==this._visibleDeviceSnapshot&&this._stagedDeviceSnapshotToken!==t)return this._stagedDeviceSnapshotToken=t,void this.requestUpdate();this._continuityPaintToken!==t&&(this._continuityPaintToken=t,this._continuity.candidateReady(t)&&this._continuity.commitAfterPaint(t,{updateComplete:()=>this.updateComplete,stageValid:()=>this.isConnected&&this._continuityStageValid(),assetsReady:()=>this._continuityAssetsReady(),frameFingerprint:()=>this._visualFrameFingerprint()}).then(e=>{e&&t===this._continuity.token?(this._resumeSettling=!1,this._renderSnapshotAt=Date.now(),this._candidateDeviceSnapshot&&(this._visibleDeviceSnapshot=this._candidateDeviceSnapshot),this._candidateDeviceSnapshot=null,this._stagedDeviceSnapshotToken=-1,this._warmSnapshot()):t===this._continuity.token&&(this._continuityPaintToken=-1,this._stagedDeviceSnapshotToken=-1,this._candidateDeviceSnapshot=null,this.requestUpdate())}))}_onBackdropLoaded(t,e){this._signer.markLoaded(this.hass,t,e),this._continuity.note("asset-ready"),this._continuityPaintToken=-1,"steady"!==this._continuity.state&&this.requestUpdate()}_renderRecoveryOverlay(){if(!this._continuity.overlayVisible&&"recovery-error"!==this._continuity.state)return G;const t="connection"===this._continuity.recoveryReason;return W`
t.stopPropagation()} @click=${t=>t.stopPropagation()} @@ -4907,26 +4907,26 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8 ${this._t(t?"continuity.restore_connection":"continuity.restore_plan")} ${"recovery-error"===this._continuity.state?W``:G} -
`}houseplanContinuityTrace(){return[...this._continuityHistory,...this._continuity.trace].slice(-80).map(t=>({...t,...t.stage?{stage:[...t.stage]}:{}}))}getCardSize(){return 12}get _norm(){return!(!this._serverCfg||!this._serverCfg.spaces.length)}_cfgFingerprint(){const t=this._serverCfg?.spaces||[];let e=t.length+":";for(const i of t){e+=(i.id||"")+","+(i.plan_aspect||"")+","+(i.plan_url||"").length+","+(i.plan_x??"")+","+(i.plan_y??"")+","+(i.plan_scale??"")+","+(i.plan_scale_x??"")+","+(i.plan_scale_y??"")+","+(i.plan_angle??"")+","+(i.rooms?.length||0)+","+(i.openings?.length||0)+","+(i.decor?.length||0)+";";for(const t of i.rooms||[]){const i=t.poly?.[0],s=t.poly?.[t.poly.length-1];e+=(t.poly?.length||0)+"."+(t.id||"")+"."+(t.open_to||[]).join("+")+"."+(t.area||"")+"."+JSON.stringify(t.settings||0)+"."+(t.x??"")+","+(t.y??"")+","+(t.w??"")+","+(t.h??"")+","+(i?i[0]+"/"+i[1]:"")+","+(s?s[0]+"/"+s[1]:"")+";"}}return e}get _model(){if(!this._serverCfg)return[];const t=this._cfgEpoch+"|"+this._cfgFingerprint();if(this._modelCache&&this._modelCache.key===t)return this._modelCache.model;const e=this._buildModel();return this._modelCache={key:t,model:e},e}_buildModel(){if(!this._serverCfg)return[];const t=this._renderCfg;return vc(t).map((e,i)=>{const s=t.spaces[i]?.plan_url;return e.bg&&s?{...e,bg:{...e.bg,href:s}}:e})}_spaceModel(){return this._hasFixedFloor?Rh(this._model,this._space):(t=this._model,e=this._space,t.find(t=>t.id===e)??t[0]);var t,e}_spaceModelById(t){return Rh(this._model,t)}_syncEmptySpaceState(){if(!!this._serverCfg&&0===this._serverCfg.spaces.length){if(!this._emptySpaceStateActive){this._emptySpaceStateActive=!0;for(const t of this._pointers.keys())for(const e of this.renderRoot.querySelectorAll("*"))try{e.hasPointerCapture?.(t)&&e.releasePointerCapture(t)}catch{}this._pointers.clear(),this._panStart=null,this._panLock=null,this._pinchStart=null,this._swipeStart=null,this._drag=null,this._rlResize=null,this._vacFit=null,this._compassDrag=!1,this._cancelModeTransition(!1),this._mode="view",this._clearGeometryGesture(),this._geometryHistory.clear(),this._resumeDraftBySpace={},this._tip=null,this._hoverRoom=null,this._openingInfo=null,this._closeInfoCard(),this._markerDialog=null,this._physicalDialog=null,this._backdropDialog=null,this._decorShapeDialog=null,this._decorTextDialog=null,this._roomDialog=!1,"edit"===this._spaceDialog?.mode&&(this._spaceDialog=null),this._editorSecondary.closeForNavigation(),this._saveConfigDebounced.cancel(),this._frame=null,this._planSnapGeometryCache=null,this._decorSnapCache=null,this._commitSpace("",!0)}}else this._emptySpaceStateActive=!1}get _areaToSpace(){const t={};for(const e of this._model)for(const i of e.rooms)i.area&&(t[i.area]={space:e.id,room:i});return t}get _settings(){return this._serverCfg?.settings||{}}get _showAll(){return this._settings.filter_seeded?this._showHidden:!!this._settings.show_all}_toggleShowAll(){if(this._serverCfg){if(this._settings.filter_seeded)return this._showHidden=!this._showHidden,void this.requestUpdate();this._serverCfg={...this._serverCfg,settings:{...this._serverCfg.settings,show_all:!this._settings.show_all}},this._regSignature="",this._maybeRebuildDevices(),this._saveConfig(),this.requestUpdate()}}_seedHiddenDevices(){if(!this._serverCfg||!this._norm||!this._canEdit)return;const t=this._serverCfg,e=function(t){const e=t.hass,i=t.registry||An(e),s=On(e,i),n=Nn(e,i),{areaToSpace:o,markers:r,settings:a,excluded:l,iconRules:c}=t,h=!1!==a.group_lights,d=wo(r),p=yo(s,h).filter(t=>!ko(s,t.eid,d)),u=new Set(p.map(t=>t.area)),_=qn(s),g=Wn(r,n),m=new Set(r.map(t=>t.binding)),f=[];for(const t of Object.values(s.devices)){const n=t.area_id;if(!n||!o[n])continue;if("service"===t.entry_type)continue;if(m.has("device:"+t.id))continue;if("active"!==Bn(e,"device:"+t.id,i).kind)continue;const r=jn(s,t.id,_[t.id]||[],g);if(r.partial&&!r.entityIds.length)continue;const a=r.entityIds,d=Un(s,t,a);let p=l.has(d)||"Group"===t.model||/scene/i.test(t.model||"")||/bridge/i.test((t.model||"")+(t.name||""))||"myheat"===d&&!!t.via_device_id;if(!p&&h&&u.has(n)){const e=(t.name_by_user||t.name||"").trim();"mdi:lightbulb"===bo(s,e,t.model,a,c)&&(p=!0)}p&&f.push("device:"+t.id)}return f}({hass:this.hass,registry:this._haRegistry,areaToSpace:Object.fromEntries(Object.entries(this._areaToSpace).map(([t,e])=>[t,e.space])),markers:this._markers,settings:this._settings,excluded:this._excluded,firstSpaceId:this._model[0]?.id||"",iconRules:this._iconRules});if(!e.length&&t.settings?.filter_seeded)return;t.markers=t.markers||[];const i=[];for(const s of e){const e="h"+s.slice(s.indexOf(":")+1);t.markers.push({id:e,binding:s,hidden:!0}),i.push(s.slice(s.indexOf(":")+1))}const s={...t.settings||{},filter_seeded:!0};delete s.show_all,i.length&&Array.isArray(s.new_device_ids)&&(s.new_device_ids=s.new_device_ids.filter(t=>!i.includes(t))),t.settings=s,this._regSignature="",this._maybeRebuildDevices(),this._saveConfig(),this.requestUpdate()}get _iconRules(){const t=this._settings.icon_rules;if(!t||!Array.isArray(t)||!t.length)return;const e=JSON.stringify(t);return e!==this._rulesCompiledSrc&&(this._rulesCompiledSrc=e,this._rulesCompiled=Jt(t)),this._rulesCompiled}get _fillColors(){return ps(this._settings)}get _excluded(){const t=this._settings.exclude_integrations;return t?new Set(t):Yt}willUpdate(t){t.has("_serverCfg")&&this._cfgEpoch++,this._syncEmptySpaceState(),t.has("hass")&&this.hass&&(this._hassSequence++,this._renderSnapshotAt=Date.now(),this._continuity.note("hass-snapshot"),this._ensureHaRegistryAuthority(),this._planHassMemo=null,this._hookConnection(),!this._loadOk&&!this._loading&&this._loadTries<8&&this._loadFromServer(),this._maybeRebuildDevices(),this._vacTick(),this._activityTick()),this._continuity.hasCompleteFrame&&"steady"===this._continuity.state&&this._continuity.refreshCompleteFrame(this._visualFrameFingerprint()),this._captureRenderDeviceSnapshot()}updated(){this._pruneDevicePressFeedback(),this._syncDayCycleClock(),this._warmSnapshot(),this._dtMeasure();const t=this._stageEl;t&&!this._roViewport&&(this._roViewport=new ResizeObserver(()=>this._refitView()),this._roViewport.observe(t)),t&&this._booting&&!this._bootTimer&&this._bootWatch();const e=this.renderRoot.querySelector(".hdr");if(e&&t&&!this._roHdr){const i=()=>{const e=this.renderRoot.querySelector("ha-card");if(!e)return;const i=t.getBoundingClientRect().top-e.getBoundingClientRect().top,s=Math.min(Math.max(e.getBoundingClientRect().top,0),120),n=Math.round(i+s);n>=0&&n!==this._hdrH&&(this._hdrH=n),n>=0&&!this._booting&&!this._config?.kiosk&&t.clientHeight>0&&this._warmPatch({hdrH:n,stageH:t.clientHeight})};this._roHdr=new ResizeObserver(()=>requestAnimationFrame(i)),this._roHdr.observe(e),this._onWinResize=()=>requestAnimationFrame(i),window.addEventListener("resize",this._onWinResize),i()}if(t&&!this._view&&this._refitView(),this._editorSecondary.afterRender(),this._settleContinuityFrame(),this._serverStorage&&this._loadOk&&0===this._model.length&&!this._spaceDialog&&!this._importDialog&&!this._onboardingShown){this._onboardingShown=!0;const t=function(t){const e=t?.floors;if(!e||"object"!=typeof e)return[];const i=[];for(const t of Object.values(e))t&&t.floor_id&&i.push({id:t.floor_id,name:t.name||t.floor_id,level:t.level??null});return i.sort((t,e)=>{const i=t.level??1e9,s=e.level??1e9;return i!==s?i-s:t.name.localeCompare(e.name)}),i}(this.hass);t.length?this._importDialog={floors:t.map(t=>({...t,checked:!0}))}:this._openSpaceDialog("create")}}_adoptStructuralResponses(t,e,i){const s=t?.config,n=s&&Array.isArray(s.spaces)?s:null,o=Ch(n),r=o!==(this._cfgContentFingerprint||Ch(this._serverCfg));if(r&&(this._geometryHistory.clear(),this._serverCfg&&this._clearGeometryGesture(),this._serverCfg=n,this._cfgContentFingerprint=o),this._cfgRev=t?.rev??this._cfgRev,t&&("virtual_lights"in t||"config"in t)){const e=mn(this._virtualLights,t.virtual_lights,this._cfgRev,"virtual_lights"in t);vn(e)!==vn(this._virtualLights)&&(this._virtualLights=e,this._capturedSnapshotVirtual="")}let a=!1;if(void 0!==e||void 0!==i){const t=i??e?.layout??{},s=Ch(t);a=s!==(this._layoutContentFingerprint||Ch(this._layout)),a&&(this._layout=t,this._layoutContentFingerprint=s),this._layoutRev=e?.rev??this._layoutRev}return this._canOptimizeUndo=!(!t?.can_optimize_undo&&!e?.can_optimize_undo),this._undoKind=t?.undo_kind||e?.undo_kind||null,"boolean"==typeof t?.can_write&&(this._serverCanWrite=t.can_write),r&&this._continuity.note("config-candidate",{configRev:this._cfgRev}),a&&this._continuity.note("layout-candidate",{layoutRev:this._layoutRev}),{configChanged:r,layoutChanged:a}}_resumePendingNavMode(){if(!this._pendingNavMode||!this._canEdit||this._config?.kiosk)return!1;const t=this._pendingNavMode;return this._pendingNavMode=null,this._setMode(t,!1),!0}async _loadFromServer(){this._loading=!0,this._loadTries++;const t=this._space,e=!!this._view;try{const[i,s]=await Promise.all([this.hass.callWS({type:"houseplan/config/get"}),this.hass.callWS({type:"houseplan/layout/get"})]),n=i?.config&&Array.isArray(i.config.spaces)?i.config:null,o=Ch(n)!==(this._cfgContentFingerprint||Ch(this._serverCfg))||Ch(s?.layout??{})!==(this._layoutContentFingerprint||Ch(this._layout));if(o){if(!await this._signer.prepareImage(this.hass,this._candidateBackdrop(n)))return this._continuity.note("asset-failed"),void this._scheduleLoadRetry(!0)}o&&this._continuity.hasCompleteFrame&&"steady"===this._continuity.state&&this._beginContinuityCandidate("structural-response",!0),this._connectionWasLost=!1,this._serverStorage=!0,"boolean"==typeof i?.can_write&&(this._serverCanWrite=i.can_write),this._canOptimizeUndo=!(!i?.can_optimize_undo&&!s?.can_optimize_undo),this._adoptStructuralResponses(i,s),this._adoptInitialSpace(this._model,!0),this._resumePendingNavMode(),this._cacheSnapshot(),this._warmVpArmed&&this._space===this._warmVp?.space?this._warmVpArmed=!1:e&&this._space===t||this._restoreZoom(),this._loadOk=!0,this.hass.callWS({type:"houseplan/trail/get"}).then(t=>{this._vacSrvTrails=t?.trails||{},this.requestUpdate()}).catch(()=>{}),this._ensureLiveSyncSubscriptions()}catch(t){if(this._serverCfg)this._scheduleLoadRetry(!0);else if(this._loadTries>=8){this._serverStorage=!1;try{this._layout=JSON.parse(localStorage.getItem(om)||"{}")||{}}catch{this._layout={}}}}finally{this._loading=!1,this._continuityDataReady=!0,this._regSignature="",this._maybeRebuildDevices(),this.requestUpdate()}}_ensureLiveSyncSubscriptions(){const t=this.hass?.connection;if(!t)return;if(t!==this._liveSyncConnection&&(this._unsubCfg?.(),this._unsubCfg=null,this._unsubLayout?.(),this._unsubLayout=null,this._unsubTrail?.(),this._unsubTrail=void 0,this._unsubVirtual?.(),this._unsubVirtual=null,this._liveSyncGeneration++,this._liveSyncAttempt=null,this._liveSyncConnection=t),this._liveSyncAttempt)return;const e=this._liveSyncGeneration,i=[],s=(s,n,o,r)=>{s()||i.push(async()=>{const i=await t.subscribeEvents(r,o);e===this._liveSyncGeneration&&this.isConnected&&this.hass?.connection===t&&!s()?n(i):i?.()})};if(s(()=>this._unsubCfg,t=>{this._unsubCfg=t},"houseplan_config_updated",t=>{const e=Number(t?.data?.rev??-1);e!==this._cfgRev&&this._reloadConfigOnly(!1,e)}),s(()=>this._unsubTrail,t=>{this._unsubTrail=t},"houseplan_trail_updated",async()=>{try{const t=await this.hass.callWS({type:"houseplan/trail/get"});this._vacSrvTrails=t?.trails||{},this.requestUpdate()}catch{}}),s(()=>this._unsubLayout,t=>{this._unsubLayout=t},"houseplan_layout_updated",t=>this._onLayoutEvent(Number(t?.data?.rev??-1))),s(()=>this._unsubVirtual,t=>{this._unsubVirtual=t},"houseplan_virtual_light_updated",t=>{const e=wn(this._virtualLights,t?.data);e!==this._virtualLights&&(this._virtualLights=e,this._capturedSnapshotVirtual="",this._cacheSnapshot(),this.requestUpdate())}),!i.length)return;const n=function(t){return Promise.allSettled(t.map(t=>Promise.resolve().then(t)))}(i).then(()=>{});this._liveSyncAttempt=n,n.finally(()=>{this._liveSyncAttempt===n&&(this._liveSyncAttempt=null)})}async _reloadConfigOnly(t=!1,e){if(!t){if(void 0!==e&&e<=this._cfgRev)return;if(this._saveConfigDebounced.pending()&&this._saveConfigDebounced.flush(),this._cfgWriting)return clearTimeout(this._reloadRetry),void(this._reloadRetry=window.setTimeout(()=>this._reloadConfigOnly(!1,e),400))}this._beginContinuityCandidate("config-reload",!1);try{const t=await this.hass.callWS({type:"houseplan/config/get"}),e=t?.config&&Array.isArray(t.config.spaces)?t.config:null;if(Ch(e)!==(this._cfgContentFingerprint||Ch(this._serverCfg))&&!await this._signer.prepareImage(this.hass,this._candidateBackdrop(e)))return this._continuity.note("asset-failed"),void this._scheduleLoadRetry(!0);const i=this._space;this._adoptStructuralResponses(t),this._adoptInitialSpace(this._model,!0),this._resumePendingNavMode(),this._cacheSnapshot(),this._space!==i&&this._restoreZoom(),this._regSignature="",this._maybeRebuildDevices(),this.requestUpdate()}catch(t){this._showToast(this._t("toast.cfg_reload_failed",{err:this._errText(t)}))}finally{this._continuityDataReady=!0,this.requestUpdate()}}_scheduleLoadRetry(t=!1){if(void 0!==this._loadRetryTimer)return;const e=Math.min(8e3,500*2**Math.min(4,Math.max(1,this._loadTries-7)));this._loadRetryTimer=window.setTimeout(()=>{this._loadRetryTimer=void 0,!t&&this._loadOk||this._loading||!this.hass||this._loadFromServer()},e)}_ensureHaRegistryAuthority(){const t=this.hass?.connection||null;t&&t!==this._haRegistryConnection&&(this._haRegistryRelease?.(),this._haRegistryConnection=t,this._haRegistryRev=-1,this._haBindingCacheKey="",this._planHassMemo=null,this._haRegistryRelease=In(this.hass,this._onHaRegistryUpdate),this._onHaRegistryUpdate())}get _haRegistry(){return An(this.hass)}get _planHass(){const t=this._haRegistry,e=En(this.hass,t),i=this._planHassMemo;if(i&&i.hass===this.hass&&i.sig===e)return i.active;const s=On(this.hass,t),n=Nn(this.hass,t);return this._planHassMemo={hass:this.hass,sig:e,active:s,full:n},s}_captureRenderDeviceSnapshot(){if(!this.hass)return;const t=Date.now(),e=[...this._activityRt.entries()].map(([e,i])=>`${e}:${i.gen}:${i.flashTs}:`+(i.flashKind&&(i.expiresAt||i.flashTs+xu)>t?1:0)).join("|"),i=vn(this._virtualLights);if(this._capturedSnapshotSequence===this._hassSequence&&this._capturedSnapshotDevices===this._devices&&this._capturedSnapshotLayout===this._layout&&this._capturedSnapshotConfigEpoch===this._cfgEpoch&&this._capturedSnapshotVirtual===i&&this._capturedSnapshotActivity===e)return;const s=this._planHass,n=new Map,o=new Map,r=new Set(["sun.sun"]);this._vacFit?.source&&r.add(this._vacFit.source);const a=new Set,l=new Set,c=t=>{if(!t)return;const e=t.indexOf(":");if(e<0)return void r.add(t);const i=t.slice(0,e),s=t.slice(e+1);"device"===i?a.add(s):"entity"===i&&r.add(s)};for(const t of this._model)for(const e of t.rooms)e.area&&l.add(e.area),c(e.settings?.temp_source),c(e.settings?.hum_source);for(const t of this._serverCfg?.spaces||[])for(const e of t.openings||[])for(const t of mi(e))r.add(t);for(const t of this._serverCfg?.spaces||[])for(const e of t.decor||[])if("text"===e.kind){for(const t of String(e.text||"").matchAll(/\{([^{}\r\n]+)\}/g)){const e=Yi(t[1]);e?.entity&&r.add(e.entity)}e.entity&&r.add(e.entity),o.set(`decor:${t.id}:${e.id}`,ts(e.text,e,s,t=>!!s.entities?.[t]&&!!s.states?.[t]&&!ko(s,t,wo(this._markers))))}const h=ho(s,this._devices,null,this._virtualLights);for(const t of this._devices){for(const e of[!1,!0])n.set(ru(t.id,e),iu(s,t,{liveStates:!1!==this._config?.live_states,showTemperature:!1!==this._config?.show_temperature,showSignal:e,activityRuntime:this._activityRt.get(t.id),sourceDetails:!1,lightDevices:this._devices,lightSources:h,registryHass:this._fullRegistryHass,reducedMotion:this._reducedMotion}));if(this._isVacDev(t)){const e=this._vacSource(t,s),i=e?jh(s?.states?.[e]?.attributes):null,n=this._vacRt.get(t.id);o.set(`vacuum:${t.id}`,{source:e,telemetry:i,mapId:i?this._vacMapId(t,i,s):null,runtime:n?{trail:n.trail,lastTs:n.lastTs,moving:n.moving,jump:n.jump}:null,server:this._vacSrvTrails[t.id]||null})}}const d=ou({sourceSequence:this._hassSequence,hass:s,devices:this._devices,presentations:n,positions:(p=this._model.length>0,u=this._devices,_=t=>this._livePos(t),p?new Map(u.map(t=>[t.id,_(t)])):new Map),facts:o,entityIds:r,deviceIds:a,areaIds:l});var p,u,_;this._capturedSnapshotSequence=this._hassSequence,this._capturedSnapshotDevices=this._devices,this._capturedSnapshotLayout=this._layout,this._capturedSnapshotActivity=e,this._capturedSnapshotConfigEpoch=this._cfgEpoch,this._capturedSnapshotVirtual=i,this._visibleDeviceSnapshot&&"steady"!==this._continuity.state?this._candidateDeviceSnapshot=d:(this._visibleDeviceSnapshot=d,this._candidateDeviceSnapshot=null)}get _renderDeviceSnapshot(){return this._stagedDeviceSnapshotToken===this._continuity.token?this._candidateDeviceSnapshot||this._visibleDeviceSnapshot:this._visibleDeviceSnapshot||this._candidateDeviceSnapshot}get _renderPlanHass(){return this._renderDeviceSnapshot?.hass||this._planHass}get _renderDevices(){return this._renderDeviceSnapshot?.devices||this._devices}get _fullRegistryHass(){return this._planHass,this._planHassMemo?.full||this.hass}_bindingStatus(t){return Bn(this.hass,t,this._haRegistry)}houseplanDiagnostics(){const t=function(t){const e=An(t);return{access:e.access,authoritative:e.authoritative,revision:e.revision,lastSuccess:e.lastSuccess,error:e.error}}(this.hass),e={active:0,ha_disabled:0,orphaned:0,unverified:0};for(const t of this._markers)t.removed||"virtual"===t.binding||e[this._bindingStatus(t.binding).kind]++;return{registry:{...t,lastSuccessAgeMs:t.lastSuccess?Math.max(0,Date.now()-t.lastSuccess):null},bindings:e}}_openBindingInHa(t){const[e,i]=t.split(":");if(i)if("device"!==e){if("entity"===e){const t=this._fullRegistryHass.entities?.[i];t?.device_id&&vm("/config/devices/device/"+encodeURIComponent(t.device_id))}}else vm("/config/devices/device/"+encodeURIComponent(i))}_bindingHasHaPage(t){const[e,i]=t.split(":");return!!i&&("device"===e||"entity"===e&&!!this._fullRegistryHass.entities?.[i]?.device_id)}_toggleMarkerDialogVisibility(){const t=this._markerDialog;if(!t)return;const e="ha"===t.bindingMode?this._bindingStatus(t.binding):null,i=t.hideFromPlan||"ha_disabled"===e?.kind;i&&"ha_disabled"===e?.kind?this._showToast(this._t("entity"===e.reason?"toast.ha_disabled_show_entity":"toast.ha_disabled_show_device")):i&&"unverified"===e?.kind?this._showToast(this._t("toast.ha_binding_unverified")):this._markerDialog={...t,hideFromPlan:!i}}_hookConnection(){const t=this.hass?.connection;t&&t!==this._connHooked&&(this._connHooked?.removeEventListener?.("ready",this._onConnReady),this._connHooked?.removeEventListener?.("disconnected",this._onConnLost),this._connHooked?.removeEventListener?.("reconnect-error",this._onConnLost),t.addEventListener?.("ready",this._onConnReady),t.addEventListener?.("disconnected",this._onConnLost),t.addEventListener?.("reconnect-error",this._onConnLost),this._connHooked=t)}_display(t){return this._signer.display(this.hass,t)}_resign(){this._signer.resign(this.hass,Is(this._serverCfg))}_onLayoutEvent(t){t<=this._layoutRev||(clearTimeout(this._layoutSyncTimer),this._layoutSyncTimer=window.setTimeout(()=>{t<=this._layoutRev||this._reloadLayoutOnly()},200))}_noteLayoutRev(t){const e=t?.rev;"number"==typeof e&&e>this._layoutRev&&(this._layoutRev=e)}async _reloadLayoutOnly(){if(!this._serverStorage||!this.hass?.callWS)return;this._beginContinuityCandidate("layout-reload",!1);const t=new Map;for(const e of this._dirtyPos)this._layout[e]&&t.set(e,this._layout[e]);this._persistLayout.pending()&&this._persistLayout.flush();for(const[e,i]of this._sentPos)t.set(e,i);try{const e=await this.hass.callWS({type:"houseplan/layout/get"}),i={...e?.layout||{}};for(const[e,s]of t)i[e]=s;const s=Ch(i);s!==(this._layoutContentFingerprint||Ch(this._layout))&&(this._layout=i,this._layoutContentFingerprint=s),this._layoutRev=e?.rev??this._layoutRev,this._canOptimizeUndo=!!e?.can_optimize_undo,this._undoKind=e?.undo_kind||null,this._cacheSnapshot(),this.requestUpdate()}catch{}finally{this._continuityDataReady=!0,this.requestUpdate()}}_maybeRebuildDevices(){const t=this.hass;if(!t?.devices||!t?.entities||!t?.areas)return;const e=this._haRegistry,i=En(t,e)+":"+Object.keys(t.areas).length+":"+(this._norm?"n":"l")+":"+ar(t,this._config?.language);if(i===this._regSignature&&this._devices.length)return;this._regSignature=i;const s=new Map(this._devices.map(t=>[t.id,t.bindingStatus?.kind||"active"]));this._devices=So({hass:t,registry:e,areaToSpace:Object.fromEntries(Object.entries(this._areaToSpace).map(([t,e])=>[t,e.space])),markers:this._markers,settings:this._settings,excluded:this._excluded,showAll:this._showAll,firstSpaceId:this._model[0]?.id||"",loc:t=>this._t(t),iconRules:this._iconRules});const n=this._markers.filter(t=>!t.removed&&"virtual"!==t.binding).map(t=>t.binding).sort(),o=e.revision+":"+n.join("|");if(e.authoritative&&o!==this._haBindingCacheKey){const i=new Map;for(const s of n)i.set(s,Bn(t,s,e));!function(t){if("undefined"==typeof localStorage||!t.size)return;const e=Ln(),i=Date.now();for(const[s,n]of t)"active"===n.kind?e[s]={kind:"active",ts:i}:"ha_disabled"===n.kind&&(e[s]={kind:"ha_disabled",reason:n.reason,ts:i});const s=Object.fromEntries(Object.entries(e).sort((t,e)=>e[1].ts-t[1].ts).slice(0,1500));Mn=s;try{localStorage.setItem(Sn,JSON.stringify(s))}catch{}}(i),this._haBindingCacheKey=o}this._defPos=this._defaultPositions(),this._syncNewDevices(),this._seedHiddenDevices(),this._syncActivityRuntime();const r=new Set(this._devices.filter(t=>!t.hidden).map(t=>t.id));for(const t of this._vacRt.keys())r.has(t)||this._vacRt.delete(t);if(this._infoCard){const t=this._devices.find(t=>t.id===this._infoCard.id);this._infoCard=t&&"ha_disabled"!==t.bindingStatus?.kind?t:null}const a=this._devices.some(t=>"ha_disabled"===t.bindingStatus?.kind&&"ha_disabled"!==s.get(t.id));a&&("ha_disabled"!==this._infoCard?.bindingStatus?.kind&&"ha_disabled"!==this._devices.find(t=>t.id===this._infoCard?.id)?.bindingStatus?.kind||this._closeInfoCard(),this._drag&&"ha_disabled"===this._devices.find(t=>t.id===this._drag.id)?.bindingStatus?.kind&&(this._drag=null),clearTimeout(this._holdTimer),this._holdFired=!1,this._tip=null,this._tapConfirm=null),this._nativeMoreInfoEntity&&!this._planEntityAvailable(this._nativeMoreInfoEntity)&&(fm(this,"hass-more-info",{entityId:null}),this._nativeMoreInfoEntity=null)}_syncNewDevices(){if(!this._norm||!this._loadOk||!this._serverCfg)return;const t=this._devices.filter(t=>!t.marker&&!t.virtual).map(t=>t.id).sort(),e=t.join(",");if(e===this._newSyncKey)return;this._newSyncKey=e;const i=this._settings,{fresh:s,known:n}=function(t,e){if(!Array.isArray(e))return{fresh:[],known:[...t]};const i=new Set(e),s=t.filter(t=>!i.has(t));return{fresh:s,known:s.length?[...e,...s]:e}}(t,i.known_devices);if(!Array.isArray(i.known_devices)||s.length){const t=[...new Set([...i.new_device_ids||[],...s])];this._serverCfg={...this._serverCfg,settings:{...i,known_devices:n,new_device_ids:t}},this._saveConfig()}}get _newIds(){const t=this._settings.new_device_ids;return new Set(Array.isArray(t)?t:[])}_ackNewDevice(t){if(!this._newIds.has(t)||!this._serverCfg)return;const e=this._settings;this._serverCfg={...this._serverCfg,settings:{...e,new_device_ids:(e.new_device_ids||[]).filter(e=>e!==t)}},this._saveConfig(),this.requestUpdate()}get _markers(){return this._serverCfg?.markers||[]}_roomLqi(t){if(!t)return null;const e=[];for(const i of this._renderDevices){if(i.area!==t||i.virtual)continue;const s=_o(this._renderPlanHass,i.entities);null!=s&&e.push(s)}return zi(e)}_roomBounds(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}}_defaultPositions(){const t={},e=this._config?.icon_size??2.5;for(const i of this._model){const s=e/100*Hc(i)*1.3;for(const e of i.rooms){if(!e.area)continue;const n=this._devices.filter(t=>t.area===e.area&&t.space===i.id);if(!n.length)continue;const o=this._roomBounds(e),r=.1*Math.min(o.w,o.h),a=o.w-2*r,l=o.h-2*r,c=Math.max(1,Math.round(Math.sqrt(n.length*a/Math.max(l,1)))),h=Math.ceil(n.length/c),d=a/c,p=l/Math.max(h,1),u=n.map((t,e)=>({x:o.x+r+d*(e%c+.5),y:o.y+r+p*(Math.floor(e/c)+.5)}));Ni(u,o,s,.5*r),n.forEach((e,i)=>t[e.id]=Sc(u[i]))}}return t}_pos(t){const e=this._renderDeviceSnapshot?.positions.get(t.id);return e?{x:e.x,y:e.y}:this._livePos(t)}_livePos(t){const e=this._spaceModelById(t.space),i=this._layout[t.id];if(i)if(this._norm){if(i.s===t.space)return{x:i.x*pm,y:i.y*pm}}else if(void 0===i.s)return{x:i.x,y:i.y};return this._defPos[t.id]?this._defPos[t.id]:e?Sc(Nc(e)):{x:500,y:500}}_savePos(t,e,i){if(this._spaceModelById(t.space)){if(this._norm){const s=this._gridPitch,n=Math.round(e/s)*s,o=Math.round(i/s)*s,r=this._layout[t.id]?.k;this._layout={...this._layout,[t.id]:{s:t.space,x:Cc(n/pm),y:Cc(o/pm),...r?{k:r}:{}}}}else this._layout={...this._layout,[t.id]:{x:Math.round(e),y:Math.round(i)}};this._dirtyPos.add(t.id),this._persistLayout()}}_visualSamples(t){return Jp(this._renderPlanHass,t,this._renderDevices,void 0,this._fullRegistryHass).samples}_devicePresentation(t,e=!1!==this._config?.show_signal,i=!1){const s=i?null:this._renderDeviceSnapshot?.presentations.get(ru(t.id,e));return s||iu(this._renderPlanHass,t,{liveStates:!1!==this._config?.live_states,showTemperature:!1!==this._config?.show_temperature,showSignal:e,designPreview:i,activityRuntime:this._activityRt.get(t.id),sourceDetails:!1,lightDevices:this._renderDevices,registryHass:this._fullRegistryHass,reducedMotion:this._reducedMotion})}_deviceVisual(t){return this._devicePresentation(t).visual}_stateClass(t,e=this._deviceVisual(t)){const i=this._devicePresentation(t);return i.effectiveHidden?"":("icon_ripple"!==i.display||!1===this._config?.live_states||"alarm"===e.status||e.activity,eu({...i,visual:e}).join(" "))}_liveTemp(t){if(!this._config?.show_temperature)return null;if(!0===t.marker?.use_climate_temp){const e=mo(this._renderPlanHass,t.entities);if(null!=e)return e}return"mdi:thermometer"!==t.icon&&"mdi:air-filter"!==t.icon?null:go(this._renderPlanHass,t.entities)}_bindingEntities(t){if("virtual"===t||!t)return[];const e=this._bindingStatus(t);return"active"===e.kind?e.enabledEntityIds:e.allEntityIds}_bindingHasClimate(t){return this._bindingEntities(t).some(t=>t.startsWith("climate."))}_bindingHasAlarm(t){return this._bindingEntities(t).some(t=>{const e=this._planHass?.states?.[t]||this.hass?.states?.[t],i=this._fullRegistryHass.entities[t]||this.hass?.entities?.[t];return Bs(t.split(".")[0],e?.attributes?.device_class||i?.device_class||i?.original_device_class)})}_liveHum(t){return this._config?.show_temperature&&t.primary&&fo(this.hass,t.primary)?vo(this.hass,t.entities):null}_deviceBindingActive(t,e=!0){if(t.virtual||"virtual"===t.bindingKind)return!0;if(!t.bindingKind||!t.bindingRef)return!1;const i=this._bindingStatus(`${t.bindingKind}:${t.bindingRef}`);return"active"===i.kind||(e&&this._showToast(this._t("ha_disabled"===i.kind?"toast.ha_disabled_action":"toast.ha_binding_unverified")),!1)}_openMoreInfo(t){t?this._planEntityAvailable(t)?(this._nativeMoreInfoEntity=t,fm(this,"hass-more-info",{entityId:t})):this._showToast(this._t("toast.ha_disabled_action")):this._showToast(this._t("toast.no_entity"))}_interruptViewGesture(t,e){if(clearTimeout(this._holdTimer),clearTimeout(this._kioskHoldTimer),void 0!==t)for(const i of[e,this._stageEl])try{i?.hasPointerCapture?.(t)&&i.releasePointerCapture(t)}catch{}this._pointers.clear(),this._panStart=null,this._panLock=null,this._pinchStart=null,this._swipeStart=null}_closeInfoCard(){this._interruptViewGesture(),this._holdFired=!1,this._infoCard=null}_ctxDevice(t,e){"view"===this._mode&&(t.preventDefault(),t.stopPropagation(),this._deviceBindingActive(e)&&(e.primary?this._openMoreInfo(e.primary):this._infoCard=e))}_clickDevice(t,e){if(t.stopPropagation(),this._drag?.moved||this._suppressClick||this._holdFired)return;if("plan"===this._mode)return;if("devices"===this._mode)return void this._openMarkerDialog(e);const i=this._devices.find(t=>t.id===e.id);if(!i)return;const s=yd(i.tapAction,i.primary?.split(".")[0]),n=(t,e)=>{i.marker?.tap_confirm?this._tapConfirm={kind:"run",text:t,exec:e}:e()};if("toggle"===s){const t=this._toggleIntent(i);if(!t||!Sd(t))return;const e=t=>{const e=Sd(t);if(!e)return;if("virtual-light"===e.kind)return this._startDevicePressFeedback(i.id),void this.hass.callWS({type:"houseplan/virtual_light/toggle",marker_id:e.markerId}).then(t=>{const e=wn(this._virtualLights,t);e!==this._virtualLights&&(this._virtualLights=e,this._capturedSnapshotVirtual="",this._cacheSnapshot(),this.requestUpdate())}).catch(t=>this._showToast(this._t("toast.virtual_light_toggle_failed",{err:this._errText(t)})));const{command:s}=e;this._startDevicePressFeedback(i.id),this.hass.callService(s.domain,s.service,s.data).catch(t=>this._showToast(this._t("toast.error",{err:this._errText(t)})))},s=((o=t).targets.length?o.targets:o.skippedTargets).map(t=>t.name||t.entityId||t.ref).join(", ")||i.name;if(i.marker?.tap_confirm){const n=this._toggleConfirmationLines(t);if(!n.length)return;this._tapConfirm={kind:"toggle",text:this._t("confirm.tap_toggle",{name:s}),lines:n,initialIntent:t,deviceId:i.id,exec:()=>{const s=this._devices.find(t=>t.id===i.id),n=s?this._toggleIntent(s):null;n&&Md(t,n)?e(n):this._showToast(this._t("toast.tap_target_changed"))}}}else e(t);return}var o;if("info"===s)return this._interruptViewGesture(),void(this._infoCard=i);if(this._deviceBindingActive(i)){if("run"===s){const t=i.marker?.tap_target||"",e=function(t){const e=String(t||"").split(".")[0];return"automation"===e?{domain:"automation",service:"trigger"}:"script"===e?{domain:"script",service:"turn_on"}:"scene"===e?{domain:"scene",service:"turn_on"}:null}(t),s=this.hass.states[t];if(!e||!s)return void this._showToast(this._t("toast.run_target_missing"));const o=s.attributes?.friendly_name||t;return void n(this._t("confirm.tap_run",{name:o}),()=>{this._deviceBindingActive(i)&&this._planEntityAvailable(t)&&(this._startDevicePressFeedback(i.id),this.hass.callService(e.domain,e.service,{entity_id:t}).then(()=>{this._stampActivity(i.id,"event",this._activitySourceKey(i)),this.requestUpdate(),this._showToast(this._t("toast.run_started",{name:o}))}).catch(t=>this._showToast(this._t("toast.error",{err:this._errText(t)}))))})}"more-info"===s&&i.primary?this._openMoreInfo(i.primary):this._infoCard=i}}_keyDevice(t,e){"Enter"!==t.key&&" "!==t.key||"view"!==this._mode&&"devices"!==this._mode||(t.preventDefault(),this._clickDevice(t,e))}_startDevicePressFeedback(t){const e=[...this.renderRoot.querySelectorAll(".dev[data-id]")].find(e=>e.dataset.id===t),i=e?.querySelector(".device-shell");if(!i||"function"!=typeof i.animate)return;const s=Number.parseFloat(this.ownerDocument.defaultView?.getComputedStyle(i).scale||""),n=Number.isFinite(s)?Math.max(.95,Math.min(1,s)):1;this._devicePressAnimations.get(t)?.cancel();const o=this._reducedMotion?[{outlineColor:"transparent",outlineStyle:"solid",outlineWidth:"0px"},{outlineColor:"var(--hp-accent, #3ea6ff)",outlineStyle:"solid",outlineWidth:"2px",outlineOffset:"2px",offset:.5},{outlineColor:"transparent",outlineStyle:"solid",outlineWidth:"0px"}]:[{scale:String(n)},{scale:"0.95",offset:.5},{scale:"1"}],r=i.animate(o,{duration:200,easing:"cubic-bezier(.22,.61,.36,1)"});this._devicePressAnimations.set(t,r);const a=()=>{this._devicePressAnimations.get(t)===r&&this._devicePressAnimations.delete(t)};r.addEventListener("finish",a,{once:!0}),r.addEventListener("cancel",a,{once:!0})}_cancelDevicePressFeedback(){for(const t of this._devicePressAnimations.values())t.cancel();this._devicePressAnimations.clear()}_pruneDevicePressFeedback(){if(!this._devicePressAnimations.size)return;const t=new Set([...this.renderRoot.querySelectorAll(".dev[data-id]")].map(t=>t.dataset.id||""));for(const[e,i]of this._devicePressAnimations)t.has(e)||(i.cancel(),this._devicePressAnimations.delete(e))}_t(t,e){return lr(ar(this.hass,this._config?.language),t,e)}get _colorPickerLabels(){return{title:this._t("color_picker.title"),hue:this._t("color_picker.hue"),saturation:this._t("color_picker.saturation"),value:this._t("color_picker.value"),hex:this._t("color_picker.hex"),invalidHex:this._t("color_picker.invalid_hex")}}_help(t){const e=`${t}.aria`,i=ar(this.hass,this._config?.language);return cr(i,t)&&cr(i,e)?W``:G}get _stageEl(){return this.renderRoot.querySelector(".stage")}_contentItems(t){const e=[];for(const i of this._devices){if(i.space!==t.id||i.hidden)continue;const s=this._pos(i);e.push({minX:s.x,minY:s.y,maxX:s.x,maxY:s.y})}if(t.id===this._space){for(const t of this._openingsR){const i=Number(t.angle)*Math.PI/180,s=Math.cos(i)*t.rlen/2,n=Math.sin(i)*t.rlen/2,o=Pc([[t.rx-s,t.ry-n],[t.rx+s,t.ry+n]]);o&&e.push(o)}const i=this._decorH;for(const t of this._decorList){const s=Pc("line"===t.kind?[[t.x1*pm,t.y1*i],[t.x2*pm,t.y2*i]]:"text"===t.kind?[[t.x*pm,t.y*i]]:ua({x:t.x*pm,y:t.y*i,w:t.w*pm,h:t.h*i,angle:t.angle}));s&&e.push(s)}for(const i of this._physicalBodiesR(t)){const t=Pc(i);t&&e.push(t)}}return Ic(t,e)}_frameOf(){const t=this._spaceModel();if(!t){this._frame=null;const t={x:0,y:0,w:pm,h:pm};return{rect:t,all:t,outliers:0}}const e=this._frame,i="view"!==this._mode;if(e&&e.id===t.id&&this._bdDrag)return e;if(e&&e.id===t.id&&e.model===t&&e.layout===this._layout&&e.devs===this._devices&&e.far===this._showFar&&e.grow===i)return e;const s=zc(this._contentItems(t));let n=s.all||Oc(t),o=this._showFar?n:s.core||Oc(t);return e&&e.id===t.id&&i&&e.grow&&(o=_m(e.rect,o),n=_m(e.all,n)),this._frame={id:t.id,model:t,layout:this._layout,devs:this._devices,far:this._showFar,grow:i,rect:o,all:n,outliers:s.outliers},this._frame}_isoSource(){const t=this._spaceModel();if(!t)return null;const e=this._spaceWalls,i=this._openPairs().flatMap(t=>t.segs),s=this._openingsR.map((t,e)=>({id:String(t.id||e),sourceIndex:e,type:t.type,x:t.rx,y:t.ry,angle:Number(t.angle)||0,length:t.rlen>0?t.rlen:900,flipH:!!t.flip_h,flipV:!!t.flip_v})),n=cc(64,this._cellCm),o=cc(10,this._cellCm),r=`${t.id}|${function(t){let e=2166136261;const i=t=>{if("number"!=typeof t)if("string"!=typeof t)if("boolean"!=typeof t)if(Array.isArray(t)){e=fg(e,t.length);for(const e of t)i(e)}else{if(t&&"object"==typeof t){const e=t;for(const t of Object.keys(e).sort())i(t),i(e[t]);return}e=fg(e,-1)}else e=fg(e,t?1:0);else for(const i of t)e=fg(e,i.codePointAt(0)||0);else e=fg(e,t)};return i(t),e.toString(36)}({rooms:t.rooms,walls:e,openCuts:i,openings:s,partitions:t.partitions,roomDrafts:t.room_drafts,columns:t.wall_columns,cellCm:this._cellCm,gridPitch:this._gridPitch,wallKeyPitch:this._wallKeyPitch,camera:og,wallHeight:n,floorEdgeHeight:o,algorithm:3})}`;return{key:r,build:()=>{const o=Xl(t,this._cellCm,this._gridPitch,2e-4*this._gridPitch,this._partitionOpeningCuts(t)).all,r=this._roomWallOpeningInputs(this._openingsR,t),a=e.length||o.length?Cl(t.rooms,e,i,r,this._wallKeyPitch,this._cellCm,this._gridPitch,pm,o):null;if((e.length||o.length)&&!a)throw new Error("wall boolean geometry failed");const l=a?.paperGeom??Sl(t.rooms,e,i,this._wallKeyPitch,this._cellCm,this._gridPitch,pm);if(!l)throw new Error("floor boolean geometry failed");const c=a?.openingIndex||Rl(t.rooms,e,i,this._wallKeyPitch,this._cellCm,this._gridPitch,pm),h=s.map(t=>{const i=this._openingsR[t.sourceIndex],s="gate"===t.type?!t.flipV:t.flipV,o=i?.partitionHost?Fd(i.partitionHost,s):e.length||"gate"===t.type?El(c,{x:t.x,y:t.y,angle:t.angle,length:t.length,flip_v:s}):{ox:0,oy:0,cm:0,side:-1};return function(t,e=64){if(!(vg([t.x,t.y,t.angle,t.length,t.face.ox,t.face.oy,e])&&t.length>0&&e>0))throw new Error("invalid isometric opening input");const i=t.length/2;let s;if("passage"===t.type)s=[];else if("gate"===t.type){const n=10*t.face.side;s=[bg(t,0,[-i,0],[i,0],n,0,.88*e),bg(t,1,[i,0],[-i,0],-n,0,.88*e)]}else s="window"===t.type?[bg(t,0,[-i,0],[i,0],-90,.27*e,.78*e),bg(t,1,[i,0],[-i,0],90,.27*e,.78*e)]:[bg(t,0,[-i,0],[t.length,0],-90,0,.92*e)];return{id:t.id,sourceIndex:t.sourceIndex,type:t.type,leaves:Object.freeze(s.map(t=>Object.freeze(t)))}}({...t,face:o},n)});return{walls:a?.geom||[],floor:l,openings:Object.freeze(h)}}}}_isoSceneKey(){if(!this._labsIso||"view"!==this._mode)return null;try{return this._isoSource()?.key??null}catch{return`${this._space}|invalid`}}_isoScene(){const t=this._isoSource();if(!t)return null;const e=this._isoGeometryCache.get(t.key);if(e)return{key:t.key,...e};const i=this._frameOf().rect,s=t.build(),n=cc(64,this._cellCm),o=cc(10,this._cellCm),r=function(t){let e=1/0,i=1/0,s=-1/0,n=-1/0;for(const o of t)for(const t of o.leaves){const o=Math.hypot(t.closedVector[0],t.closedVector[1]);e=Math.min(e,t.hinge[0]-o),i=Math.min(i,t.hinge[1]-o),s=Math.max(s,t.hinge[0]+o),n=Math.max(n,t.hinge[1]+o)}return vg([e,i,s,n])?{x:e,y:i,w:s-e,h:n-i}:null}(s.openings),a=hg({rect:r?_m(i,r):i,wallHeight:n,openingHeight:n,floorDepth:o}),l=function(t,e=og,i=64){if(!Number.isFinite(i)||i<0)throw new Error("invalid wall height");const s=[],n=[],o=[];let r=0;for(let a=0;a<(t||[]).length;a++){const l=t[a];for(let t=0;t<(l||[]).length;t++){const c=ug(l[t],t>0);if(!(c.length<3||Math.abs(pg(c))<1e-9)){s.push(_g(c,e,i)),r+=c.length;for(let s=0;st.depth-e.depth||t.polygon-e.polygon||t.ring-e.ring||t.edge-e.edge),{topPath:s.join(" "),sides:n,contactPath:o.join(" "),edgeCount:r}}(s.walls,og,n),c={geometry:l,floor:mg(s.floor,o),openings:s.openings,frame:a};return tm(this._isoGeometryCache,t.key,c,8),{key:t.key,...c}}_effectiveProjection(){if("iso"!==this._desiredProjection||!this._model.length)return"flat";const t=this._isoSceneKey()||`${this._space}|invalid`;if(this._isoFallback.has(t))return"flat";try{const t=this._isoScene();return t?(e="iso",i=t.key,s=this._isoFallback,"iso"===e&&i&&!s.has(i)?"iso":"flat"):"flat"}catch(e){if(!this._isoFallback.has(t)){this._isoFallback.add(t);const i=t.split("|");console.warn(`HOUSEPLAN ISO FALLBACK: #89, space ${this._space}, fingerprint ${i[i.length-1]}, ${e instanceof Error?e.message:"renderer error"}`)}return"flat"}var e,i,s}_scenePoint(t){return"iso"===this._renderProjection?ag(t,0):t}_floorView(t){if("iso"!==this._renderProjection)return t;const e=lg([t.x,t.y]),i=lg([t.x+t.w,t.y+t.h]);return{x:e[0],y:e[1],w:i[0]-e[0],h:i[1]-e[1]}}_baseVb(){if("iso"===this._effectiveProjection()){if(!this._spaceDisplayForRender().showBorders){const t=hg({rect:this._frameOf().rect,wallHeight:cc(64,this._cellCm)});return[t.x,t.y,t.w,t.h]}const t=this._isoScene()?.frame??this._frameOf().rect;return[t.x,t.y,t.w,t.h]}const t=this._frameOf().rect;return[t.x,t.y,t.w,t.h]}get _outliers(){return this._showFar?0:this._frameOf().outliers}_fitFar(){this._showFar=!0,this._frame=null,this._resetZoom()}_fitAll(){this._showFar=!0,this._frame=null,this._resetZoom()}_renderFarHint(){return this._kiosk||"view"!==this._mode||this._booting||!this._outliers?G:W`
+
`}houseplanContinuityTrace(){return[...this._continuityHistory,...this._continuity.trace].slice(-80).map(t=>({...t,...t.stage?{stage:[...t.stage]}:{}}))}getCardSize(){return 12}get _norm(){return!(!this._serverCfg||!this._serverCfg.spaces.length)}_cfgFingerprint(){const t=this._serverCfg?.spaces||[];let e=t.length+":";for(const i of t){e+=(i.id||"")+","+(i.plan_aspect||"")+","+(i.plan_url||"").length+","+(i.plan_x??"")+","+(i.plan_y??"")+","+(i.plan_scale??"")+","+(i.plan_scale_x??"")+","+(i.plan_scale_y??"")+","+(i.plan_angle??"")+","+(i.rooms?.length||0)+","+(i.openings?.length||0)+","+(i.decor?.length||0)+";";for(const t of i.rooms||[]){const i=t.poly?.[0],s=t.poly?.[t.poly.length-1];e+=(t.poly?.length||0)+"."+(t.id||"")+"."+(t.open_to||[]).join("+")+"."+(t.area||"")+"."+JSON.stringify(t.settings||0)+"."+(t.x??"")+","+(t.y??"")+","+(t.w??"")+","+(t.h??"")+","+(i?i[0]+"/"+i[1]:"")+","+(s?s[0]+"/"+s[1]:"")+";"}}return e}get _model(){if(!this._serverCfg)return[];const t=this._cfgEpoch+"|"+this._cfgFingerprint();if(this._modelCache&&this._modelCache.key===t)return this._modelCache.model;const e=this._buildModel();return this._modelCache={key:t,model:e},e}_buildModel(){if(!this._serverCfg)return[];const t=this._renderCfg;return yc(t).map((e,i)=>{const s=t.spaces[i]?.plan_url;return e.bg&&s?{...e,bg:{...e.bg,href:s}}:e})}_spaceModel(){return this._hasFixedFloor?Ih(this._model,this._space):(t=this._model,e=this._space,t.find(t=>t.id===e)??t[0]);var t,e}_spaceModelById(t){return Ih(this._model,t)}_syncEmptySpaceState(){if(!!this._serverCfg&&0===this._serverCfg.spaces.length){if(!this._emptySpaceStateActive){this._emptySpaceStateActive=!0;for(const t of this._pointers.keys())for(const e of this.renderRoot.querySelectorAll("*"))try{e.hasPointerCapture?.(t)&&e.releasePointerCapture(t)}catch{}this._pointers.clear(),this._panStart=null,this._panLock=null,this._pinchStart=null,this._swipeStart=null,this._drag=null,this._rlResize=null,this._vacFit=null,this._compassDrag=!1,this._cancelModeTransition(!1),this._mode="view",this._clearGeometryGesture(),this._geometryHistory.clear(),this._resumeDraftBySpace={},this._tip=null,this._hoverRoom=null,this._openingInfo=null,this._closeInfoCard(),this._markerDialog=null,this._physicalDialog=null,this._backdropDialog=null,this._decorShapeDialog=null,this._decorTextDialog=null,this._roomDialog=!1,"edit"===this._spaceDialog?.mode&&(this._spaceDialog=null),this._editorSecondary.closeForNavigation(),this._saveConfigDebounced.cancel(),this._frame=null,this._planSnapGeometryCache=null,this._decorSnapCache=null,this._commitSpace("",!0)}}else this._emptySpaceStateActive=!1}get _areaToSpace(){const t={};for(const e of this._model)for(const i of e.rooms)i.area&&(t[i.area]={space:e.id,room:i});return t}get _settings(){return this._serverCfg?.settings||{}}get _showAll(){return this._settings.filter_seeded?this._showHidden:!!this._settings.show_all}_toggleShowAll(){if(this._serverCfg){if(this._settings.filter_seeded)return this._showHidden=!this._showHidden,void this.requestUpdate();this._serverCfg={...this._serverCfg,settings:{...this._serverCfg.settings,show_all:!this._settings.show_all}},this._regSignature="",this._maybeRebuildDevices(),this._saveConfig(),this.requestUpdate()}}_seedHiddenDevices(){if(!this._serverCfg||!this._norm||!this._canEdit)return;const t=this._serverCfg,e=function(t){const e=t.hass,i=t.registry||An(e),s=On(e,i),n=Nn(e,i),{areaToSpace:o,markers:a,settings:r,excluded:l,iconRules:c}=t,h=!1!==r.group_lights,d=wo(a),p=yo(s,h).filter(t=>!ko(s,t.eid,d)),u=new Set(p.map(t=>t.area)),_=qn(s),g=Wn(a,n),m=new Set(a.map(t=>t.binding)),f=[];for(const t of Object.values(s.devices)){const n=t.area_id;if(!n||!o[n])continue;if("service"===t.entry_type)continue;if(m.has("device:"+t.id))continue;if("active"!==Bn(e,"device:"+t.id,i).kind)continue;const a=jn(s,t.id,_[t.id]||[],g);if(a.partial&&!a.entityIds.length)continue;const r=a.entityIds,d=Un(s,t,r);let p=l.has(d)||"Group"===t.model||/scene/i.test(t.model||"")||/bridge/i.test((t.model||"")+(t.name||""))||"myheat"===d&&!!t.via_device_id;if(!p&&h&&u.has(n)){const e=(t.name_by_user||t.name||"").trim();"mdi:lightbulb"===bo(s,e,t.model,r,c)&&(p=!0)}p&&f.push("device:"+t.id)}return f}({hass:this.hass,registry:this._haRegistry,areaToSpace:Object.fromEntries(Object.entries(this._areaToSpace).map(([t,e])=>[t,e.space])),markers:this._markers,settings:this._settings,excluded:this._excluded,firstSpaceId:this._model[0]?.id||"",iconRules:this._iconRules});if(!e.length&&t.settings?.filter_seeded)return;t.markers=t.markers||[];const i=[];for(const s of e){const e="h"+s.slice(s.indexOf(":")+1);t.markers.push({id:e,binding:s,hidden:!0}),i.push(s.slice(s.indexOf(":")+1))}const s={...t.settings||{},filter_seeded:!0};delete s.show_all,i.length&&Array.isArray(s.new_device_ids)&&(s.new_device_ids=s.new_device_ids.filter(t=>!i.includes(t))),t.settings=s,this._regSignature="",this._maybeRebuildDevices(),this._saveConfig(),this.requestUpdate()}get _iconRules(){const t=this._settings.icon_rules;if(!t||!Array.isArray(t)||!t.length)return;const e=JSON.stringify(t);return e!==this._rulesCompiledSrc&&(this._rulesCompiledSrc=e,this._rulesCompiled=Jt(t)),this._rulesCompiled}get _fillColors(){return ps(this._settings)}get _excluded(){const t=this._settings.exclude_integrations;return t?new Set(t):Yt}willUpdate(t){t.has("_serverCfg")&&this._cfgEpoch++,this._syncEmptySpaceState(),t.has("hass")&&this.hass&&(this._hassSequence++,this._renderSnapshotAt=Date.now(),this._continuity.note("hass-snapshot"),this._ensureHaRegistryAuthority(),this._planHassMemo=null,this._hookConnection(),!this._loadOk&&!this._loading&&this._loadTries<8&&this._loadFromServer(),this._maybeRebuildDevices(),this._vacTick(),this._activityTick()),this._continuity.hasCompleteFrame&&"steady"===this._continuity.state&&this._continuity.refreshCompleteFrame(this._visualFrameFingerprint()),this._captureRenderDeviceSnapshot()}updated(){this._pruneDevicePressFeedback(),this._syncDayCycleClock(),this._warmSnapshot(),this._dtMeasure();const t=this._stageEl;t&&!this._roViewport&&(this._roViewport=new ResizeObserver(()=>this._refitView()),this._roViewport.observe(t)),t&&this._booting&&!this._bootTimer&&this._bootWatch();const e=this.renderRoot.querySelector(".hdr");if(e&&t&&!this._roHdr){const i=()=>{const e=this.renderRoot.querySelector("ha-card");if(!e)return;const i=t.getBoundingClientRect().top-e.getBoundingClientRect().top,s=Math.min(Math.max(e.getBoundingClientRect().top,0),120),n=Math.round(i+s);n>=0&&n!==this._hdrH&&(this._hdrH=n),n>=0&&!this._booting&&!this._config?.kiosk&&t.clientHeight>0&&this._warmPatch({hdrH:n,stageH:t.clientHeight})};this._roHdr=new ResizeObserver(()=>requestAnimationFrame(i)),this._roHdr.observe(e),this._onWinResize=()=>requestAnimationFrame(i),window.addEventListener("resize",this._onWinResize),i()}if(t&&!this._view&&this._refitView(),this._editorSecondary.afterRender(),this._settleContinuityFrame(),this._serverStorage&&this._loadOk&&0===this._model.length&&!this._spaceDialog&&!this._importDialog&&!this._onboardingShown){this._onboardingShown=!0;const t=function(t){const e=t?.floors;if(!e||"object"!=typeof e)return[];const i=[];for(const t of Object.values(e))t&&t.floor_id&&i.push({id:t.floor_id,name:t.name||t.floor_id,level:t.level??null});return i.sort((t,e)=>{const i=t.level??1e9,s=e.level??1e9;return i!==s?i-s:t.name.localeCompare(e.name)}),i}(this.hass);t.length?this._importDialog={floors:t.map(t=>({...t,checked:!0}))}:this._openSpaceDialog("create")}}_adoptStructuralResponses(t,e,i){const s=t?.config,n=s&&Array.isArray(s.spaces)?s:null,o=Dh(n),a=o!==(this._cfgContentFingerprint||Dh(this._serverCfg));if(a&&(this._geometryHistory.clear(),this._serverCfg&&this._clearGeometryGesture(),this._serverCfg=n,this._cfgContentFingerprint=o),this._cfgRev=t?.rev??this._cfgRev,t&&("virtual_lights"in t||"config"in t)){const e=mn(this._virtualLights,t.virtual_lights,this._cfgRev,"virtual_lights"in t);vn(e)!==vn(this._virtualLights)&&(this._virtualLights=e,this._capturedSnapshotVirtual="")}let r=!1;if(void 0!==e||void 0!==i){const t=i??e?.layout??{},s=Dh(t);r=s!==(this._layoutContentFingerprint||Dh(this._layout)),r&&(this._layout=t,this._layoutContentFingerprint=s),this._layoutRev=e?.rev??this._layoutRev}return this._canOptimizeUndo=!(!t?.can_optimize_undo&&!e?.can_optimize_undo),this._undoKind=t?.undo_kind||e?.undo_kind||null,"boolean"==typeof t?.can_write&&(this._serverCanWrite=t.can_write),a&&this._continuity.note("config-candidate",{configRev:this._cfgRev}),r&&this._continuity.note("layout-candidate",{layoutRev:this._layoutRev}),{configChanged:a,layoutChanged:r}}_resumePendingNavMode(){if(!this._pendingNavMode||!this._canEdit||this._config?.kiosk)return!1;const t=this._pendingNavMode;return this._pendingNavMode=null,this._setMode(t,!1),!0}async _loadFromServer(){this._loading=!0,this._loadTries++;const t=this._space,e=!!this._view;try{const[i,s]=await Promise.all([this.hass.callWS({type:"houseplan/config/get"}),this.hass.callWS({type:"houseplan/layout/get"})]),n=i?.config&&Array.isArray(i.config.spaces)?i.config:null,o=Dh(n)!==(this._cfgContentFingerprint||Dh(this._serverCfg))||Dh(s?.layout??{})!==(this._layoutContentFingerprint||Dh(this._layout));if(o){if(!await this._signer.prepareImage(this.hass,this._candidateBackdrop(n)))return this._continuity.note("asset-failed"),void this._scheduleLoadRetry(!0)}o&&this._continuity.hasCompleteFrame&&"steady"===this._continuity.state&&this._beginContinuityCandidate("structural-response",!0),this._connectionWasLost=!1,this._serverStorage=!0,"boolean"==typeof i?.can_write&&(this._serverCanWrite=i.can_write),this._canOptimizeUndo=!(!i?.can_optimize_undo&&!s?.can_optimize_undo),this._adoptStructuralResponses(i,s),this._adoptInitialSpace(this._model,!0),this._resumePendingNavMode(),this._cacheSnapshot(),this._warmVpArmed&&this._space===this._warmVp?.space?this._warmVpArmed=!1:e&&this._space===t||this._restoreZoom(),this._loadOk=!0,this.hass.callWS({type:"houseplan/trail/get"}).then(t=>{this._vacSrvTrails=t?.trails||{},this.requestUpdate()}).catch(()=>{}),this._ensureLiveSyncSubscriptions()}catch(t){if(this._serverCfg)this._scheduleLoadRetry(!0);else if(this._loadTries>=8){this._serverStorage=!1;try{this._layout=JSON.parse(localStorage.getItem(am)||"{}")||{}}catch{this._layout={}}}}finally{this._loading=!1,this._continuityDataReady=!0,this._regSignature="",this._maybeRebuildDevices(),this.requestUpdate()}}_ensureLiveSyncSubscriptions(){const t=this.hass?.connection;if(!t)return;if(t!==this._liveSyncConnection&&(this._unsubCfg?.(),this._unsubCfg=null,this._unsubLayout?.(),this._unsubLayout=null,this._unsubTrail?.(),this._unsubTrail=void 0,this._unsubVirtual?.(),this._unsubVirtual=null,this._liveSyncGeneration++,this._liveSyncAttempt=null,this._liveSyncConnection=t),this._liveSyncAttempt)return;const e=this._liveSyncGeneration,i=[],s=(s,n,o,a)=>{s()||i.push(async()=>{const i=await t.subscribeEvents(a,o);e===this._liveSyncGeneration&&this.isConnected&&this.hass?.connection===t&&!s()?n(i):i?.()})};if(s(()=>this._unsubCfg,t=>{this._unsubCfg=t},"houseplan_config_updated",t=>{const e=Number(t?.data?.rev??-1);e!==this._cfgRev&&this._reloadConfigOnly(!1,e)}),s(()=>this._unsubTrail,t=>{this._unsubTrail=t},"houseplan_trail_updated",async()=>{try{const t=await this.hass.callWS({type:"houseplan/trail/get"});this._vacSrvTrails=t?.trails||{},this.requestUpdate()}catch{}}),s(()=>this._unsubLayout,t=>{this._unsubLayout=t},"houseplan_layout_updated",t=>this._onLayoutEvent(Number(t?.data?.rev??-1))),s(()=>this._unsubVirtual,t=>{this._unsubVirtual=t},"houseplan_virtual_light_updated",t=>{const e=wn(this._virtualLights,t?.data);e!==this._virtualLights&&(this._virtualLights=e,this._capturedSnapshotVirtual="",this._cacheSnapshot(),this.requestUpdate())}),!i.length)return;const n=function(t){return Promise.allSettled(t.map(t=>Promise.resolve().then(t)))}(i).then(()=>{});this._liveSyncAttempt=n,n.finally(()=>{this._liveSyncAttempt===n&&(this._liveSyncAttempt=null)})}async _reloadConfigOnly(t=!1,e){if(!t){if(void 0!==e&&e<=this._cfgRev)return;if(this._saveConfigDebounced.pending()&&this._saveConfigDebounced.flush(),this._cfgWriting)return clearTimeout(this._reloadRetry),void(this._reloadRetry=window.setTimeout(()=>this._reloadConfigOnly(!1,e),400))}this._beginContinuityCandidate("config-reload",!1);try{const t=await this.hass.callWS({type:"houseplan/config/get"}),e=t?.config&&Array.isArray(t.config.spaces)?t.config:null;if(Dh(e)!==(this._cfgContentFingerprint||Dh(this._serverCfg))&&!await this._signer.prepareImage(this.hass,this._candidateBackdrop(e)))return this._continuity.note("asset-failed"),void this._scheduleLoadRetry(!0);const i=this._space;this._adoptStructuralResponses(t),this._adoptInitialSpace(this._model,!0),this._resumePendingNavMode(),this._cacheSnapshot(),this._space!==i&&this._restoreZoom(),this._regSignature="",this._maybeRebuildDevices(),this.requestUpdate()}catch(t){this._showToast(this._t("toast.cfg_reload_failed",{err:this._errText(t)}))}finally{this._continuityDataReady=!0,this.requestUpdate()}}_scheduleLoadRetry(t=!1){if(void 0!==this._loadRetryTimer)return;const e=Math.min(8e3,500*2**Math.min(4,Math.max(1,this._loadTries-7)));this._loadRetryTimer=window.setTimeout(()=>{this._loadRetryTimer=void 0,!t&&this._loadOk||this._loading||!this.hass||this._loadFromServer()},e)}_ensureHaRegistryAuthority(){const t=this.hass?.connection||null;t&&t!==this._haRegistryConnection&&(this._haRegistryRelease?.(),this._haRegistryConnection=t,this._haRegistryRev=-1,this._haBindingCacheKey="",this._planHassMemo=null,this._haRegistryRelease=In(this.hass,this._onHaRegistryUpdate),this._onHaRegistryUpdate())}get _haRegistry(){return An(this.hass)}get _planHass(){const t=this._haRegistry,e=En(this.hass,t),i=this._planHassMemo;if(i&&i.hass===this.hass&&i.sig===e)return i.active;const s=On(this.hass,t),n=Nn(this.hass,t);return this._planHassMemo={hass:this.hass,sig:e,active:s,full:n},s}_captureRenderDeviceSnapshot(){if(!this.hass)return;const t=Date.now(),e=[...this._activityRt.entries()].map(([e,i])=>`${e}:${i.gen}:${i.flashTs}:`+(i.flashKind&&(i.expiresAt||i.flashTs+$u)>t?1:0)).join("|"),i=vn(this._virtualLights);if(this._capturedSnapshotSequence===this._hassSequence&&this._capturedSnapshotDevices===this._devices&&this._capturedSnapshotLayout===this._layout&&this._capturedSnapshotConfigEpoch===this._cfgEpoch&&this._capturedSnapshotVirtual===i&&this._capturedSnapshotActivity===e)return;const s=this._planHass,n=new Map,o=new Map,a=new Set(["sun.sun"]);this._vacFit?.source&&a.add(this._vacFit.source);const r=new Set,l=new Set,c=t=>{if(!t)return;const e=t.indexOf(":");if(e<0)return void a.add(t);const i=t.slice(0,e),s=t.slice(e+1);"device"===i?r.add(s):"entity"===i&&a.add(s)};for(const t of this._model)for(const e of t.rooms)e.area&&l.add(e.area),c(e.settings?.temp_source),c(e.settings?.hum_source);for(const t of this._serverCfg?.spaces||[])for(const e of t.openings||[])for(const t of mi(e))a.add(t);for(const t of this._serverCfg?.spaces||[])for(const e of t.decor||[])if("text"===e.kind){for(const t of String(e.text||"").matchAll(/\{([^{}\r\n]+)\}/g)){const e=Yi(t[1]);e?.entity&&a.add(e.entity)}e.entity&&a.add(e.entity),o.set(`decor:${t.id}:${e.id}`,ts(e.text,e,s,t=>!!s.entities?.[t]&&!!s.states?.[t]&&!ko(s,t,wo(this._markers))))}const h=ho(s,this._devices,null,this._virtualLights);for(const t of this._devices){for(const e of[!1,!0])n.set(ru(t.id,e),su(s,t,{liveStates:!1!==this._config?.live_states,showTemperature:!1!==this._config?.show_temperature,showSignal:e,activityRuntime:this._activityRt.get(t.id),sourceDetails:!1,lightDevices:this._devices,lightSources:h,registryHass:this._fullRegistryHass,reducedMotion:this._reducedMotion}));if(this._isVacDev(t)){const e=this._vacSource(t,s),i=e?Uh(s?.states?.[e]?.attributes):null,n=this._vacRt.get(t.id);o.set(`vacuum:${t.id}`,{source:e,telemetry:i,mapId:i?this._vacMapId(t,i,s):null,runtime:n?{trail:n.trail,lastTs:n.lastTs,moving:n.moving,jump:n.jump}:null,server:this._vacSrvTrails[t.id]||null})}}const d=au({sourceSequence:this._hassSequence,hass:s,devices:this._devices,presentations:n,positions:(p=this._model.length>0,u=this._devices,_=t=>this._livePos(t),p?new Map(u.map(t=>[t.id,_(t)])):new Map),facts:o,entityIds:a,deviceIds:r,areaIds:l});var p,u,_;this._capturedSnapshotSequence=this._hassSequence,this._capturedSnapshotDevices=this._devices,this._capturedSnapshotLayout=this._layout,this._capturedSnapshotActivity=e,this._capturedSnapshotConfigEpoch=this._cfgEpoch,this._capturedSnapshotVirtual=i,this._visibleDeviceSnapshot&&"steady"!==this._continuity.state?this._candidateDeviceSnapshot=d:(this._visibleDeviceSnapshot=d,this._candidateDeviceSnapshot=null)}get _renderDeviceSnapshot(){return this._stagedDeviceSnapshotToken===this._continuity.token?this._candidateDeviceSnapshot||this._visibleDeviceSnapshot:this._visibleDeviceSnapshot||this._candidateDeviceSnapshot}get _renderPlanHass(){return this._renderDeviceSnapshot?.hass||this._planHass}get _renderDevices(){return this._renderDeviceSnapshot?.devices||this._devices}get _fullRegistryHass(){return this._planHass,this._planHassMemo?.full||this.hass}_bindingStatus(t){return Bn(this.hass,t,this._haRegistry)}houseplanDiagnostics(){const t=function(t){const e=An(t);return{access:e.access,authoritative:e.authoritative,revision:e.revision,lastSuccess:e.lastSuccess,error:e.error}}(this.hass),e={active:0,ha_disabled:0,orphaned:0,unverified:0};for(const t of this._markers)t.removed||"virtual"===t.binding||e[this._bindingStatus(t.binding).kind]++;return{registry:{...t,lastSuccessAgeMs:t.lastSuccess?Math.max(0,Date.now()-t.lastSuccess):null},bindings:e}}_openBindingInHa(t){const[e,i]=t.split(":");if(i)if("device"!==e){if("entity"===e){const t=this._fullRegistryHass.entities?.[i];t?.device_id&&ym("/config/devices/device/"+encodeURIComponent(t.device_id))}}else ym("/config/devices/device/"+encodeURIComponent(i))}_bindingHasHaPage(t){const[e,i]=t.split(":");return!!i&&("device"===e||"entity"===e&&!!this._fullRegistryHass.entities?.[i]?.device_id)}_toggleMarkerDialogVisibility(){const t=this._markerDialog;if(!t)return;const e="ha"===t.bindingMode?this._bindingStatus(t.binding):null,i=t.hideFromPlan||"ha_disabled"===e?.kind;i&&"ha_disabled"===e?.kind?this._showToast(this._t("entity"===e.reason?"toast.ha_disabled_show_entity":"toast.ha_disabled_show_device")):i&&"unverified"===e?.kind?this._showToast(this._t("toast.ha_binding_unverified")):this._markerDialog={...t,hideFromPlan:!i}}_hookConnection(){const t=this.hass?.connection;t&&t!==this._connHooked&&(this._connHooked?.removeEventListener?.("ready",this._onConnReady),this._connHooked?.removeEventListener?.("disconnected",this._onConnLost),this._connHooked?.removeEventListener?.("reconnect-error",this._onConnLost),t.addEventListener?.("ready",this._onConnReady),t.addEventListener?.("disconnected",this._onConnLost),t.addEventListener?.("reconnect-error",this._onConnLost),this._connHooked=t)}_display(t){return this._signer.display(this.hass,t)}_resign(){this._signer.resign(this.hass,Is(this._serverCfg))}_onLayoutEvent(t){t<=this._layoutRev||(clearTimeout(this._layoutSyncTimer),this._layoutSyncTimer=window.setTimeout(()=>{t<=this._layoutRev||this._reloadLayoutOnly()},200))}_noteLayoutRev(t){const e=t?.rev;"number"==typeof e&&e>this._layoutRev&&(this._layoutRev=e)}async _reloadLayoutOnly(){if(!this._serverStorage||!this.hass?.callWS)return;this._beginContinuityCandidate("layout-reload",!1);const t=new Map;for(const e of this._dirtyPos)this._layout[e]&&t.set(e,this._layout[e]);this._persistLayout.pending()&&this._persistLayout.flush();for(const[e,i]of this._sentPos)t.set(e,i);try{const e=await this.hass.callWS({type:"houseplan/layout/get"}),i={...e?.layout||{}};for(const[e,s]of t)i[e]=s;const s=Dh(i);s!==(this._layoutContentFingerprint||Dh(this._layout))&&(this._layout=i,this._layoutContentFingerprint=s),this._layoutRev=e?.rev??this._layoutRev,this._canOptimizeUndo=!!e?.can_optimize_undo,this._undoKind=e?.undo_kind||null,this._cacheSnapshot(),this.requestUpdate()}catch{}finally{this._continuityDataReady=!0,this.requestUpdate()}}_maybeRebuildDevices(){const t=this.hass;if(!t?.devices||!t?.entities||!t?.areas)return;const e=this._haRegistry,i=En(t,e)+":"+Object.keys(t.areas).length+":"+(this._norm?"n":"l")+":"+ra(t,this._config?.language);if(i===this._regSignature&&this._devices.length)return;this._regSignature=i;const s=new Map(this._devices.map(t=>[t.id,t.bindingStatus?.kind||"active"]));this._devices=So({hass:t,registry:e,areaToSpace:Object.fromEntries(Object.entries(this._areaToSpace).map(([t,e])=>[t,e.space])),markers:this._markers,settings:this._settings,excluded:this._excluded,showAll:this._showAll,firstSpaceId:this._model[0]?.id||"",loc:t=>this._t(t),iconRules:this._iconRules});const n=this._markers.filter(t=>!t.removed&&"virtual"!==t.binding).map(t=>t.binding).sort(),o=e.revision+":"+n.join("|");if(e.authoritative&&o!==this._haBindingCacheKey){const i=new Map;for(const s of n)i.set(s,Bn(t,s,e));!function(t){if("undefined"==typeof localStorage||!t.size)return;const e=Ln(),i=Date.now();for(const[s,n]of t)"active"===n.kind?e[s]={kind:"active",ts:i}:"ha_disabled"===n.kind&&(e[s]={kind:"ha_disabled",reason:n.reason,ts:i});const s=Object.fromEntries(Object.entries(e).sort((t,e)=>e[1].ts-t[1].ts).slice(0,1500));Mn=s;try{localStorage.setItem(Sn,JSON.stringify(s))}catch{}}(i),this._haBindingCacheKey=o}this._defPos=this._defaultPositions(),this._syncNewDevices(),this._seedHiddenDevices(),this._syncActivityRuntime();const a=new Set(this._devices.filter(t=>!t.hidden).map(t=>t.id));for(const t of this._vacRt.keys())a.has(t)||this._vacRt.delete(t);if(this._infoCard){const t=this._devices.find(t=>t.id===this._infoCard.id);this._infoCard=t&&"ha_disabled"!==t.bindingStatus?.kind?t:null}const r=this._devices.some(t=>"ha_disabled"===t.bindingStatus?.kind&&"ha_disabled"!==s.get(t.id));r&&("ha_disabled"!==this._infoCard?.bindingStatus?.kind&&"ha_disabled"!==this._devices.find(t=>t.id===this._infoCard?.id)?.bindingStatus?.kind||this._closeInfoCard(),this._drag&&"ha_disabled"===this._devices.find(t=>t.id===this._drag.id)?.bindingStatus?.kind&&(this._drag=null),clearTimeout(this._holdTimer),this._holdFired=!1,this._tip=null,this._tapConfirm=null),this._nativeMoreInfoEntity&&!this._planEntityAvailable(this._nativeMoreInfoEntity)&&(vm(this,"hass-more-info",{entityId:null}),this._nativeMoreInfoEntity=null)}_syncNewDevices(){if(!this._norm||!this._loadOk||!this._serverCfg)return;const t=this._devices.filter(t=>!t.marker&&!t.virtual).map(t=>t.id).sort(),e=t.join(",");if(e===this._newSyncKey)return;this._newSyncKey=e;const i=this._settings,{fresh:s,known:n}=function(t,e){if(!Array.isArray(e))return{fresh:[],known:[...t]};const i=new Set(e),s=t.filter(t=>!i.has(t));return{fresh:s,known:s.length?[...e,...s]:e}}(t,i.known_devices);if(!Array.isArray(i.known_devices)||s.length){const t=[...new Set([...i.new_device_ids||[],...s])];this._serverCfg={...this._serverCfg,settings:{...i,known_devices:n,new_device_ids:t}},this._saveConfig()}}get _newIds(){const t=this._settings.new_device_ids;return new Set(Array.isArray(t)?t:[])}_ackNewDevice(t){if(!this._newIds.has(t)||!this._serverCfg)return;const e=this._settings;this._serverCfg={...this._serverCfg,settings:{...e,new_device_ids:(e.new_device_ids||[]).filter(e=>e!==t)}},this._saveConfig(),this.requestUpdate()}get _markers(){return this._serverCfg?.markers||[]}_roomLqi(t){if(!t)return null;const e=[];for(const i of this._renderDevices){if(i.area!==t||i.virtual)continue;const s=_o(this._renderPlanHass,i.entities);null!=s&&e.push(s)}return zi(e)}_roomBounds(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}}_defaultPositions(){const t={},e=this._config?.icon_size??2.5;for(const i of this._model){const s=e/100*Lc(i)*1.3;for(const e of i.rooms){if(!e.area)continue;const n=this._devices.filter(t=>t.area===e.area&&t.space===i.id);if(!n.length)continue;const o=this._roomBounds(e),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(n.length*r/Math.max(l,1)))),h=Math.ceil(n.length/c),d=r/c,p=l/Math.max(h,1),u=n.map((t,e)=>({x:o.x+a+d*(e%c+.5),y:o.y+a+p*(Math.floor(e/c)+.5)}));Ni(u,o,s,.5*a),n.forEach((e,i)=>t[e.id]=Mc(u[i]))}}return t}_pos(t){const e=this._renderDeviceSnapshot?.positions.get(t.id);return e?{x:e.x,y:e.y}:this._livePos(t)}_livePos(t){const e=this._spaceModelById(t.space),i=this._layout[t.id];if(i)if(this._norm){if(i.s===t.space)return{x:i.x*um,y:i.y*um}}else if(void 0===i.s)return{x:i.x,y:i.y};return this._defPos[t.id]?this._defPos[t.id]:e?Mc(Hc(e)):{x:500,y:500}}_savePos(t,e,i){if(this._spaceModelById(t.space)){if(this._norm){const s=this._gridPitch,n=Math.round(e/s)*s,o=Math.round(i/s)*s,a=this._layout[t.id]?.k;this._layout={...this._layout,[t.id]:{s:t.space,x:Dc(n/um),y:Dc(o/um),...a?{k:a}:{}}}}else this._layout={...this._layout,[t.id]:{x:Math.round(e),y:Math.round(i)}};this._dirtyPos.add(t.id),this._persistLayout()}}_visualSamples(t){return Zp(this._renderPlanHass,t,this._renderDevices,void 0,this._fullRegistryHass).samples}_devicePresentation(t,e=!1!==this._config?.show_signal,i=!1){const s=i?null:this._renderDeviceSnapshot?.presentations.get(ru(t.id,e));return s||su(this._renderPlanHass,t,{liveStates:!1!==this._config?.live_states,showTemperature:!1!==this._config?.show_temperature,showSignal:e,designPreview:i,activityRuntime:this._activityRt.get(t.id),sourceDetails:!1,lightDevices:this._renderDevices,registryHass:this._fullRegistryHass,reducedMotion:this._reducedMotion})}_deviceVisual(t){return this._devicePresentation(t).visual}_stateClass(t,e=this._deviceVisual(t)){const i=this._devicePresentation(t);return i.effectiveHidden?"":("icon_ripple"!==i.display||!1===this._config?.live_states||"alarm"===e.status||e.activity,iu({...i,visual:e}).join(" "))}_liveTemp(t){if(!this._config?.show_temperature)return null;if(!0===t.marker?.use_climate_temp){const e=mo(this._renderPlanHass,t.entities);if(null!=e)return e}return"mdi:thermometer"!==t.icon&&"mdi:air-filter"!==t.icon?null:go(this._renderPlanHass,t.entities)}_bindingEntities(t){if("virtual"===t||!t)return[];const e=this._bindingStatus(t);return"active"===e.kind?e.enabledEntityIds:e.allEntityIds}_bindingHasClimate(t){return this._bindingEntities(t).some(t=>t.startsWith("climate."))}_bindingHasAlarm(t){return this._bindingEntities(t).some(t=>{const e=this._planHass?.states?.[t]||this.hass?.states?.[t],i=this._fullRegistryHass.entities[t]||this.hass?.entities?.[t];return Bs(t.split(".")[0],e?.attributes?.device_class||i?.device_class||i?.original_device_class)})}_liveHum(t){return this._config?.show_temperature&&t.primary&&fo(this.hass,t.primary)?vo(this.hass,t.entities):null}_deviceBindingActive(t,e=!0){if(t.virtual||"virtual"===t.bindingKind)return!0;if(!t.bindingKind||!t.bindingRef)return!1;const i=this._bindingStatus(`${t.bindingKind}:${t.bindingRef}`);return"active"===i.kind||(e&&this._showToast(this._t("ha_disabled"===i.kind?"toast.ha_disabled_action":"toast.ha_binding_unverified")),!1)}_openMoreInfo(t){t?this._planEntityAvailable(t)?(this._nativeMoreInfoEntity=t,vm(this,"hass-more-info",{entityId:t})):this._showToast(this._t("toast.ha_disabled_action")):this._showToast(this._t("toast.no_entity"))}_interruptViewGesture(t,e){if(clearTimeout(this._holdTimer),clearTimeout(this._kioskHoldTimer),void 0!==t)for(const i of[e,this._stageEl])try{i?.hasPointerCapture?.(t)&&i.releasePointerCapture(t)}catch{}this._pointers.clear(),this._panStart=null,this._panLock=null,this._pinchStart=null,this._swipeStart=null}_closeInfoCard(){this._interruptViewGesture(),this._holdFired=!1,this._infoCard=null}_ctxDevice(t,e){"view"===this._mode&&(t.preventDefault(),t.stopPropagation(),this._deviceBindingActive(e)&&(e.primary?this._openMoreInfo(e.primary):this._infoCard=e))}_clickDevice(t,e){if(t.stopPropagation(),this._drag?.moved||this._suppressClick||this._holdFired)return;if("plan"===this._mode)return;if("devices"===this._mode)return void this._openMarkerDialog(e);const i=this._devices.find(t=>t.id===e.id);if(!i)return;const s=bd(i.tapAction,i.primary?.split(".")[0]),n=(t,e)=>{i.marker?.tap_confirm?this._tapConfirm={kind:"run",text:t,exec:e}:e()};if("toggle"===s){const t=this._toggleIntent(i);if(!t||!Md(t))return;const e=t=>{const e=Md(t);if(!e)return;if("virtual-light"===e.kind)return this._startDevicePressFeedback(i.id),void this.hass.callWS({type:"houseplan/virtual_light/toggle",marker_id:e.markerId}).then(t=>{const e=wn(this._virtualLights,t);e!==this._virtualLights&&(this._virtualLights=e,this._capturedSnapshotVirtual="",this._cacheSnapshot(),this.requestUpdate())}).catch(t=>this._showToast(this._t("toast.virtual_light_toggle_failed",{err:this._errText(t)})));const{command:s}=e;this._startDevicePressFeedback(i.id),this.hass.callService(s.domain,s.service,s.data).catch(t=>this._showToast(this._t("toast.error",{err:this._errText(t)})))},s=((o=t).targets.length?o.targets:o.skippedTargets).map(t=>t.name||t.entityId||t.ref).join(", ")||i.name;if(i.marker?.tap_confirm){const n=this._toggleConfirmationLines(t);if(!n.length)return;this._tapConfirm={kind:"toggle",text:this._t("confirm.tap_toggle",{name:s}),lines:n,initialIntent:t,deviceId:i.id,exec:()=>{const s=this._devices.find(t=>t.id===i.id),n=s?this._toggleIntent(s):null;n&&Cd(t,n)?e(n):this._showToast(this._t("toast.tap_target_changed"))}}}else e(t);return}var o;if("info"===s)return this._interruptViewGesture(),void(this._infoCard=i);if(this._deviceBindingActive(i)){if("run"===s){const t=i.marker?.tap_target||"",e=function(t){const e=String(t||"").split(".")[0];return"automation"===e?{domain:"automation",service:"trigger"}:"script"===e?{domain:"script",service:"turn_on"}:"scene"===e?{domain:"scene",service:"turn_on"}:null}(t),s=this.hass.states[t];if(!e||!s)return void this._showToast(this._t("toast.run_target_missing"));const o=s.attributes?.friendly_name||t;return void n(this._t("confirm.tap_run",{name:o}),()=>{this._deviceBindingActive(i)&&this._planEntityAvailable(t)&&(this._startDevicePressFeedback(i.id),this.hass.callService(e.domain,e.service,{entity_id:t}).then(()=>{this._stampActivity(i.id,"event",this._activitySourceKey(i)),this.requestUpdate(),this._showToast(this._t("toast.run_started",{name:o}))}).catch(t=>this._showToast(this._t("toast.error",{err:this._errText(t)}))))})}"more-info"===s&&i.primary?this._openMoreInfo(i.primary):this._infoCard=i}}_keyDevice(t,e){"Enter"!==t.key&&" "!==t.key||"view"!==this._mode&&"devices"!==this._mode||(t.preventDefault(),this._clickDevice(t,e))}_startDevicePressFeedback(t){const e=[...this.renderRoot.querySelectorAll(".dev[data-id]")].find(e=>e.dataset.id===t),i=e?.querySelector(".device-shell");if(!i||"function"!=typeof i.animate)return;const s=Number.parseFloat(this.ownerDocument.defaultView?.getComputedStyle(i).scale||""),n=Number.isFinite(s)?Math.max(.95,Math.min(1,s)):1;this._devicePressAnimations.get(t)?.cancel();const o=this._reducedMotion?[{outlineColor:"transparent",outlineStyle:"solid",outlineWidth:"0px"},{outlineColor:"var(--hp-accent, #3ea6ff)",outlineStyle:"solid",outlineWidth:"2px",outlineOffset:"2px",offset:.5},{outlineColor:"transparent",outlineStyle:"solid",outlineWidth:"0px"}]:[{scale:String(n)},{scale:"0.95",offset:.5},{scale:"1"}],a=i.animate(o,{duration:200,easing:"cubic-bezier(.22,.61,.36,1)"});this._devicePressAnimations.set(t,a);const r=()=>{this._devicePressAnimations.get(t)===a&&this._devicePressAnimations.delete(t)};a.addEventListener("finish",r,{once:!0}),a.addEventListener("cancel",r,{once:!0})}_cancelDevicePressFeedback(){for(const t of this._devicePressAnimations.values())t.cancel();this._devicePressAnimations.clear()}_pruneDevicePressFeedback(){if(!this._devicePressAnimations.size)return;const t=new Set([...this.renderRoot.querySelectorAll(".dev[data-id]")].map(t=>t.dataset.id||""));for(const[e,i]of this._devicePressAnimations)t.has(e)||(i.cancel(),this._devicePressAnimations.delete(e))}_t(t,e){return la(ra(this.hass,this._config?.language),t,e)}get _colorPickerLabels(){return{title:this._t("color_picker.title"),hue:this._t("color_picker.hue"),saturation:this._t("color_picker.saturation"),value:this._t("color_picker.value"),hex:this._t("color_picker.hex"),invalidHex:this._t("color_picker.invalid_hex")}}_help(t){const e=`${t}.aria`,i=ra(this.hass,this._config?.language);return ca(i,t)&&ca(i,e)?W``:G}get _stageEl(){return this.renderRoot.querySelector(".stage")}_contentItems(t){const e=[];for(const i of this._devices){if(i.space!==t.id||i.hidden)continue;const s=this._pos(i);e.push({minX:s.x,minY:s.y,maxX:s.x,maxY:s.y})}if(t.id===this._space){for(const t of this._openingsR){const i=Number(t.angle)*Math.PI/180,s=Math.cos(i)*t.rlen/2,n=Math.sin(i)*t.rlen/2,o=Rc([[t.rx-s,t.ry-n],[t.rx+s,t.ry+n]]);o&&e.push(o)}const i=this._decorH;for(const t of this._decorList){const s=Rc("line"===t.kind?[[t.x1*um,t.y1*i],[t.x2*um,t.y2*i]]:"text"===t.kind?[[t.x*um,t.y*i]]:ur({x:t.x*um,y:t.y*i,w:t.w*um,h:t.h*i,angle:t.angle}));s&&e.push(s)}for(const i of this._physicalBodiesR(t)){const t=Rc(i);t&&e.push(t)}}return Ac(t,e)}_frameOf(){const t=this._spaceModel();if(!t){this._frame=null;const t={x:0,y:0,w:um,h:um};return{rect:t,all:t,outliers:0}}const e=this._frame,i="view"!==this._mode;if(e&&e.id===t.id&&this._bdDrag)return e;if(e&&e.id===t.id&&e.model===t&&e.layout===this._layout&&e.devs===this._devices&&e.far===this._showFar&&e.grow===i)return e;const s=Oc(this._contentItems(t));let n=s.all||Nc(t),o=this._showFar?n:s.core||Nc(t);return e&&e.id===t.id&&i&&e.grow&&(o=gm(e.rect,o),n=gm(e.all,n)),this._frame={id:t.id,model:t,layout:this._layout,devs:this._devices,far:this._showFar,grow:i,rect:o,all:n,outliers:s.outliers},this._frame}_isoSource(){const t=this._spaceModel();if(!t)return null;const e=this._spaceWalls,i=this._openPairs().flatMap(t=>t.segs),s=this._openingsR.map((t,e)=>({id:String(t.id||e),sourceIndex:e,type:t.type,x:t.rx,y:t.ry,angle:Number(t.angle)||0,length:t.rlen>0?t.rlen:900,flipH:!!t.flip_h,flipV:!!t.flip_v})),n=hc(64,this._cellCm),o=hc(10,this._cellCm),a=`${t.id}|${function(t){let e=2166136261;const i=t=>{if("number"!=typeof t)if("string"!=typeof t)if("boolean"!=typeof t)if(Array.isArray(t)){e=vg(e,t.length);for(const e of t)i(e)}else{if(t&&"object"==typeof t){const e=t;for(const t of Object.keys(e).sort())i(t),i(e[t]);return}e=vg(e,-1)}else e=vg(e,t?1:0);else for(const i of t)e=vg(e,i.codePointAt(0)||0);else e=vg(e,t)};return i(t),e.toString(36)}({rooms:t.rooms,walls:e,openCuts:i,openings:s,partitions:t.partitions,roomDrafts:t.room_drafts,columns:t.wall_columns,cellCm:this._cellCm,gridPitch:this._gridPitch,wallKeyPitch:this._wallKeyPitch,camera:ag,wallHeight:n,floorEdgeHeight:o,algorithm:3})}`;return{key:a,build:()=>{const o=Jl(t,this._cellCm,this._gridPitch,2e-4*this._gridPitch,this._partitionOpeningCuts(t)).all,a=this._roomWallOpeningInputs(this._openingsR,t),r=e.length||o.length?Dl(t.rooms,e,i,a,this._wallKeyPitch,this._cellCm,this._gridPitch,um,o):null;if((e.length||o.length)&&!r)throw new Error("wall boolean geometry failed");const l=r?.paperGeom??Ml(t.rooms,e,i,this._wallKeyPitch,this._cellCm,this._gridPitch,um);if(!l)throw new Error("floor boolean geometry failed");const c=r?.openingIndex||Il(t.rooms,e,i,this._wallKeyPitch,this._cellCm,this._gridPitch,um),h=s.map(t=>{const i=this._openingsR[t.sourceIndex],s="gate"===t.type?!t.flipV:t.flipV,o=i?.partitionHost?Ed(i.partitionHost,s):e.length||"gate"===t.type?zl(c,{x:t.x,y:t.y,angle:t.angle,length:t.length,flip_v:s}):{ox:0,oy:0,cm:0,side:-1};return function(t,e=64){if(!(yg([t.x,t.y,t.angle,t.length,t.face.ox,t.face.oy,e])&&t.length>0&&e>0))throw new Error("invalid isometric opening input");const i=t.length/2;let s;if("passage"===t.type)s=[];else if("gate"===t.type){const n=10*t.face.side;s=[wg(t,0,[-i,0],[i,0],n,0,.88*e),wg(t,1,[i,0],[-i,0],-n,0,.88*e)]}else s="window"===t.type?[wg(t,0,[-i,0],[i,0],-90,.27*e,.78*e),wg(t,1,[i,0],[-i,0],90,.27*e,.78*e)]:[wg(t,0,[-i,0],[t.length,0],-90,0,.92*e)];return{id:t.id,sourceIndex:t.sourceIndex,type:t.type,leaves:Object.freeze(s.map(t=>Object.freeze(t)))}}({...t,face:o},n)});return{walls:r?.geom||[],floor:l,openings:Object.freeze(h)}}}}_isoSceneKey(){if(!this._labsIso||"view"!==this._mode)return null;try{return this._isoSource()?.key??null}catch{return`${this._space}|invalid`}}_isoScene(){const t=this._isoSource();if(!t)return null;const e=this._isoGeometryCache.get(t.key);if(e)return{key:t.key,...e};const i=this._frameOf().rect,s=t.build(),n=hc(64,this._cellCm),o=hc(10,this._cellCm),a=function(t){let e=1/0,i=1/0,s=-1/0,n=-1/0;for(const o of t)for(const t of o.leaves){const o=Math.hypot(t.closedVector[0],t.closedVector[1]);e=Math.min(e,t.hinge[0]-o),i=Math.min(i,t.hinge[1]-o),s=Math.max(s,t.hinge[0]+o),n=Math.max(n,t.hinge[1]+o)}return yg([e,i,s,n])?{x:e,y:i,w:s-e,h:n-i}:null}(s.openings),r=dg({rect:a?gm(i,a):i,wallHeight:n,openingHeight:n,floorDepth:o}),l=function(t,e=ag,i=64){if(!Number.isFinite(i)||i<0)throw new Error("invalid wall height");const s=[],n=[],o=[];let a=0;for(let r=0;r<(t||[]).length;r++){const l=t[r];for(let t=0;t<(l||[]).length;t++){const c=_g(l[t],t>0);if(!(c.length<3||Math.abs(ug(c))<1e-9)){s.push(gg(c,e,i)),a+=c.length;for(let s=0;st.depth-e.depth||t.polygon-e.polygon||t.ring-e.ring||t.edge-e.edge),{topPath:s.join(" "),sides:n,contactPath:o.join(" "),edgeCount:a}}(s.walls,ag,n),c={geometry:l,floor:fg(s.floor,o),openings:s.openings,frame:r};return em(this._isoGeometryCache,t.key,c,8),{key:t.key,...c}}_effectiveProjection(){if("iso"!==this._desiredProjection||!this._model.length)return"flat";const t=this._isoSceneKey()||`${this._space}|invalid`;if(this._isoFallback.has(t))return"flat";try{const t=this._isoScene();return t?(e="iso",i=t.key,s=this._isoFallback,"iso"===e&&i&&!s.has(i)?"iso":"flat"):"flat"}catch(e){if(!this._isoFallback.has(t)){this._isoFallback.add(t);const i=t.split("|");console.warn(`HOUSEPLAN ISO FALLBACK: #89, space ${this._space}, fingerprint ${i[i.length-1]}, ${e instanceof Error?e.message:"renderer error"}`)}return"flat"}var e,i,s}_scenePoint(t){return"iso"===this._renderProjection?lg(t,0):t}_floorView(t){if("iso"!==this._renderProjection)return t;const e=cg([t.x,t.y]),i=cg([t.x+t.w,t.y+t.h]);return{x:e[0],y:e[1],w:i[0]-e[0],h:i[1]-e[1]}}_baseVb(){if("iso"===this._effectiveProjection()){if(!this._spaceDisplayForRender().showBorders){const t=dg({rect:this._frameOf().rect,wallHeight:hc(64,this._cellCm)});return[t.x,t.y,t.w,t.h]}const t=this._isoScene()?.frame??this._frameOf().rect;return[t.x,t.y,t.w,t.h]}const t=this._frameOf().rect;return[t.x,t.y,t.w,t.h]}get _outliers(){return this._showFar?0:this._frameOf().outliers}_fitFar(){this._showFar=!0,this._frame=null,this._resetZoom()}_fitAll(){this._showFar=!0,this._frame=null,this._resetZoom()}_renderFarHint(){return this._kiosk||"view"!==this._mode||this._booting||!this._outliers?G:W`
${this._t("canvas.far_objects",{n:this._outliers})} -
`}_renderHomeArrow(){if(this._booting)return G;const t=this._view;if(!t||!t.w||!t.h)return G;const e=this._baseVb(),i=e[0],s=e[1],n=e[2],o=e[3];if(!(i+n<=t.x||i>=t.x+t.w||s+o<=t.y||s>=t.y+t.h))return G;const r=Math.atan2(s+o/2-(t.y+t.h/2),i+n/2-(t.x+t.w/2)),a=50+38*Math.cos(r),l=50+38*Math.sin(r);return W``}_stageAspect(){const t=this._stageEl,e=this._baseVb();return t&&t.clientHeight?t.clientWidth/t.clientHeight:e[2]/e[3]}_viewOr(t){return this._view&&this._view.w?this._view:Oi(t,this._stageAspect())}_roomLabelReferenceViewWidth(t){if(!this._markup)return t.w;const e=this._stageEl,i=this.renderRoot.querySelector(".editorchrome");if(!e||e.clientWidth<=0||e.clientHeight<=0)return t.w;const s=e.clientHeight+(i?.getBoundingClientRect().height||0);return s<=0?t.w:this._viewForModeTarget(this._zoom,void 0,void 0,e.clientWidth,s).w}_screenToVb(t,e){const i=this._stageEl,s=this._viewOr(this._baseVb()),n=i?.clientWidth||1,o=i?.clientHeight||1;return[s.x+t/n*s.w,s.y+e/o*s.h]}_clampView(t,e){const i=(t,e,i,s)=>{const n=1*Math.max(e,s),o=i-n,r=i+s-e+n;return Math.max(Math.min(o,r),Math.min(Math.max(o,r),t))};return{w:t.w,h:t.h,x:i(t.x,t.w,e.x,e.w),y:i(t.y,t.h,e.y,e.h)}}_applyView(t,e,i){const s=this._baseVb(),n=Oi(s,this._stageAspect()),o=Math.min(wm.ZOOM_MAX,Math.max(wm.ZOOM_MIN,t)),r=n.w/o,a=n.h/o,l=this._viewOr(s),c=e??l.x+l.w/2,h=i??l.y+l.h/2,d=this._clampView({x:c-r/2,y:h-a/2,w:r,h:a},n);return!(this._view&&Math.abs(this._zoom-o)<1e-9&&Math.abs(this._view.x-d.x)<1e-6&&Math.abs(this._view.y-d.y)<1e-6&&Math.abs(this._view.w-d.w)<1e-6&&Math.abs(this._view.h-d.h)<1e-6)&&("opening"===this._tool&&(this._cursorPt=null,this._clearOpeningPlacement(!1)),this._zoom=o,this._view=d,!0)}_bootWatch(){clearTimeout(this._bootTimer),this._bootStart=Date.now(),this._bootLastH=-1,this._bootLastChange=this._bootStart;const t=()=>{if(!this._booting)return;const e=Date.now(),i=this._stageEl?this._stageEl.clientHeight:0;i!==this._bootLastH&&(this._bootLastH=i,this._bootLastChange=e);const s=e-this._bootStart;s>=1200||s>=700&&i>0&&e-this._bootLastChange>=250?this._bootSettled():this._bootTimer=window.setTimeout(t,100)};this._bootTimer=window.setTimeout(t,100)}_bootSettled(){this._booting&&!this._bootSettling&&(this._bootSettling=!0,this._refitView(),this._bootSettleRaf=requestAnimationFrame(()=>{this._bootSettleRaf=0,this._finishBootSettled()}))}_finishBootSettled(){if(!this._booting)return;this._refitView(),this._booting=!1,this._bootSettling=!1;const t=this._stageEl?.clientHeight??0;!this._config?.kiosk&&t>0&&this._warmPatch({hdrH:this._hdrH,stageH:t,vp:this._warmViewportState()},!0),this._bootFading=!0,this._bootTimer=window.setTimeout(()=>{this._bootFading=!1},220),this._bootSoft=!0,clearTimeout(this._bootSoftTimer),this._bootSoftTimer=window.setTimeout(()=>{this._bootSoft=!1},Jg)}_bootSoftCancel(){this._bootSoft&&(clearTimeout(this._bootSoftTimer),this._bootSoft=!1)}_beginResumeSettle(){this._booting||this._resumeSettling||(this._modeTransitionPreparing?this._modeTransitionForceAtomic=!0:this._cancelModeTransition(!0),this._viewportInvalidAt=0,this._beginContinuityCandidate("warm-resume",!1),this._loading?this.requestUpdate():this._loadFromServer())}_refitView(){if(this._modeTransitionBusy)return;const t=this._stageEl;if(!t||"visible"!==document.visibilityState||t.clientWidth<=0||t.clientHeight<=0)return void(this._viewportInvalidAt||(this._viewportInvalidAt=Date.now()));const e=[t.clientWidth,t.clientHeight],i=this._lastValidStageSize,s=!!i&&Math.abs(i[0]-e[0])<=.5&&Math.abs(i[1]-e[1])<=.5,n=this._viewportInvalidAt?Date.now()-this._viewportInvalidAt:0;if(this._viewportInvalidAt=0,!i)return this._lastValidStageSize=e,void(this._view||this._applyView(this._zoom));s?this._pendingRefitSize=null:(this._pendingRefitSize=e,this._refitRaf||(this._refitRaf=requestAnimationFrame(()=>{this._refitRaf=0;const t=this._pendingRefitSize;this._pendingRefitSize=null;const e=this._stageEl;if(!t||!e||e.clientWidth<=0||e.clientHeight<=0)return;if(Math.abs(e.clientWidth-t[0])>.5||Math.abs(e.clientHeight-t[1])>.5)return void this._refitView();const i=this._lastValidStageSize;if(i&&Math.abs(i[0]-t[0])<=.5&&Math.abs(i[1]-t[1])<=.5)return;this._lastValidStageSize=t;const s=this._view;n>=wh?this._beginContinuityCandidate("stage-size-restored",!0,"stage-size"):this._continuity.hasCompleteFrame&&this._beginContinuityCandidate("stage-resize",!0,"stage-size"),this._applyView(this._zoom,s?s.x+s.w/2:void 0,s?s.y+s.h/2:void 0)})))}_zoomAt(t,e,i){const s=this._stageEl;if(!s)return;const n=Oi(this._baseVb(),this._stageAspect()),o=Math.min(wm.ZOOM_MAX,Math.max(wm.ZOOM_MIN,i));"opening"===this._tool&&(this._cursorPt=null,this._clearOpeningPlacement(!1));const r=s.clientWidth,a=s.clientHeight,l=this._screenToVb(t,e),c=n.w/o,h=n.h/o;this._zoom=o,this._view=this._clampView({x:l[0]-t/r*c,y:l[1]-e/a*h,w:c,h:h},n)}_onWheel(t){const e=this._stageEl;if(!e)return;t.preventDefault();const i=e.getBoundingClientRect(),s=t.deltaY<0?1.15:1/1.15;this._zoomAt(t.clientX-i.left,t.clientY-i.top,this._zoom*s),this._saveZoom()}_stepZoom(t){const e=this._stageEl;e&&(this._zoomAt(e.clientWidth/2,e.clientHeight/2,this._zoom*(t>0?1.4:1/1.4)),this._saveZoom())}_resetZoom(){const t=this._baseVb();"opening"===this._tool&&(this._cursorPt=null,this._clearOpeningPlacement(!1)),this._zoom=1,this._view=Oi(t,this._stageAspect()),this._saveZoom()}_saveZoom(){if("view"===this._mode){this._zoomBySpace={...this._zoomBySpace,[this._space]:this._zoom};try{localStorage.setItem(am,JSON.stringify(this._zoomBySpace))}catch{}}}_restoreZoom(){const t=this._zoomBySpace[this._space]||1;this._zoom=t;const e=this._stageEl;if(e&&e.clientHeight){const e=this._baseVb();return this._applyView(t,e[0]+e[2]/2,e[1]+e[3]/2),void this.requestUpdate()}this._view=null,requestAnimationFrame(()=>{if(!this._stageEl)return;const e=this._baseVb();this._applyView(t,e[0]+e[2]/2,e[1]+e[3]/2),this.requestUpdate()})}_stagePointerDown(t){if(this._vacFit)return;if(this._kiosk&&(this._cyclePausedUntil=Date.now()+6e4,0===this._pointers.size?(this._swipeStart={x:t.clientX,y:t.clientY,id:t.pointerId},t.target.closest?.(".dev, .roomlabel, .oplock")||(clearTimeout(this._kioskHoldTimer),this._kioskHoldTimer=window.setTimeout(()=>{this._kioskDialog=!0,this._swipeStart=null},3e3))):(this._swipeStart=null,clearTimeout(this._kioskHoldTimer))),this._drag)return;if(this._markup&&t.target.closest?.(".roomlabel, .rlhandle, .rszhandle, .dev, .oplock, .op-hit, button"))return;if("devices"===this._mode&&t.target.closest(".dev"))return;if("decor"===this._mode&&this._decorPointerDown(t))return;this._pointers.set(t.pointerId,{x:t.clientX,y:t.clientY});const e=this._viewOr(this._baseVb());if(1===this._pointers.size)this._panStart={sx:t.clientX,sy:t.clientY,vx:e.x,vy:e.y},this._panLock=null,this._suppressClick=!1;else if(2===this._pointers.size){this._cancelBoundaryAnchor(),"opening"===this._tool?(this._cursorPt=null,this._clearOpeningPlacement(!1)):"draw"===this._tool&&this._clearPlanSnapHover();const t=[...this._pointers.values()],e=Math.hypot(t[0].x-t[1].x,t[0].y-t[1].y);this._pinchStart={dist:e,zoom:this._zoom},this._panStart=null,this._panLock=null}}get _swipeZone(){return!this._hasFixedFloor&&this._kiosk&&this._zoom<=1.001&&this._model.length>1}_stagePointerMove(t){if(this._physicalRotate?.pid!==t.pointerId)if(this._physicalDrag?.pid!==t.pointerId)if(this._dtDrag?.pid!==t.pointerId)if(this._bdDrag?.pid!==t.pointerId){if(this._decorDraft?.pid===t.pointerId){const e=this._decorDraft;let i=this._decorSnap(this._svgPoint(t),t.pointerType);if(t.shiftKey&&("rect"===e.kind||"ellipse"===e.kind)){const t=i[0]-e.a[0],s=i[1]-e.a[1],n=Math.max(Math.abs(t),Math.abs(s));i=this._snap([e.a[0]+(t<0?-n:n),e.a[1]+(s<0?-n:n)])}return void(this._decorDraft={...e,b:i})}if(this._decorMove?.pid!==t.pointerId)if(this._pointers.has(t.pointerId)){if(this._pointers.set(t.pointerId,{x:t.clientX,y:t.clientY}),this._markup&&1===this._pointers.size&&this._markupMove(t),this._pinchStart&&this._pointers.size>=2){"opening"===this._tool?(this._cursorPt=null,this._clearOpeningPlacement(!1)):"draw"===this._tool&&this._clearPlanSnapHover();const t=[...this._pointers.values()],e=Math.hypot(t[0].x-t[1].x,t[0].y-t[1].y)/(this._pinchStart.dist||1),i=this._stageEl.getBoundingClientRect(),s=(t[0].x+t[1].x)/2-i.left,n=(t[0].y+t[1].y)/2-i.top;this._zoomAt(s,n,this._pinchStart.zoom*e),this._suppressClick=!0,this._saveZoom()}else if(this._panStart){const e=t.clientX-this._panStart.sx,i=t.clientY-this._panStart.sy;Math.abs(e)+Math.abs(i)>4&&(this._suppressClick=!0,clearTimeout(this._holdTimer),"opening"===this._tool?(this._cursorPt=null,this._clearOpeningPlacement(!1)):"draw"===this._tool&&this._clearPlanSnapHover()),null===this._panLock&&Math.abs(e)+Math.abs(i)>8&&(this._panLock=this._swipeZone&&Math.abs(e)>1.5*Math.abs(i)?"swipe":"pan");const s=this._stageEl;if("pan"===this._panLock&&s){const t=this._baseVb(),n=this._viewOr(t),o=Oi(t,this._stageAspect());this._view=this._clampView({x:this._panStart.vx-e/(s.clientWidth||1)*n.w,y:this._panStart.vy-i/(s.clientHeight||1)*n.h,w:n.w,h:n.h},o)}}}else this._markupMove(t);else this._decorMoveUpdate(t)}else this._bdMove(t);else this._dtMove(t);else this._physicalMove(t);else this._physicalRotateMove(t)}_stagePointerLeave(t){this._markup&&("opening"===this._tool?(this._cursorPt=null,this._clearOpeningPlacement(!1)):"draw"===this._tool&&this._clearPlanSnapHover())}_stagePointerUp(t){if(this._kiosk){clearTimeout(this._kioskHoldTimer);const e=this._swipeStart;if(this._swipeStart=null,e&&e.id===t.pointerId){const i=t.clientX-e.x,s=t.clientY-e.y;if(Math.abs(i)+Math.abs(s)<8){const t=Date.now();t-this._lastTap<350&&this._resetZoom(),this._lastTap=t}const n="pan"===this._panLock?null:function(t,e,i,s,n,o=60){if(i>1.001||s.length<2)return null;if(Math.abs(t)t.id),this._space);n&&this._slideTo(n,i<0?"left":"right")&&(this._saveNav(),this._suppressClick=!0,setTimeout(()=>this._suppressClick=!1,0),this._showKioskDots())}}if(this._physicalDrag?.pid===t.pointerId)return void this._physicalUp(t);if(this._physicalRotate?.pid===t.pointerId)return void this._physicalRotateUp(t);if(this._dtDrag?.pid===t.pointerId)return void this._dtUp();if(this._bdDrag?.pid===t.pointerId)return void this._bdUp();if(this._decorDraft?.pid===t.pointerId)return void this._decorCommitDraft();if(this._decorMove?.pid===t.pointerId)return this._decorMove.moved&&(this._recordGeometry(this._t("history.decor_move"),this._decorMove.before),this._saveConfig()),void(this._decorMove=null);const e=!!this._pinchStart||!!this._panStart;this._pointers.delete(t.pointerId),this._pointers.size<2&&(this._pinchStart=null),0===this._pointers.size&&(this._panStart=null,this._panLock=null,setTimeout(()=>this._suppressClick=!1,0)),e&&0===this._pointers.size&&this.requestUpdate()}_clickRoom(t){!this._suppressClick&&t.area&&vm("/config/areas/area/"+t.area)}_pointerDown(t,e){if("plan"===this._mode)return;if("view"===this._mode){this._holdFired=!1,clearTimeout(this._holdTimer);const i=t.pointerId,s=t.currentTarget;return void(this._holdTimer=window.setTimeout(()=>{this._holdFired=!0,this._interruptViewGesture(i,s),this._infoCard=e},600))}if("ha_disabled"===e.bindingStatus?.kind)return;t.preventDefault();const i=this._pos(e);this._drag={id:e.id,sx:t.clientX,sy:t.clientY,ox:i.x,oy:i.y,moved:!1},bm(t),this._tip=null}_pointerMove(t,e){if(!this._drag||this._drag.id!==e.id)return;const i=this.renderRoot.querySelector(".stage");if(!i)return;const s=this._baseVb(),n=i.getBoundingClientRect(),o=this._viewOr(s),r=(t.clientX-this._drag.sx)/n.width*o.w,a=(t.clientY-this._drag.sy)/n.height*o.h;Math.abs(t.clientX-this._drag.sx)+Math.abs(t.clientY-this._drag.sy)>3&&(this._drag.moved=!0,clearTimeout(this._holdTimer));const l=Mc(this._drag.ox+r),c=Mc(this._drag.oy+a);this._savePos(e,l,c)}_pointerUp(t,e){if(clearTimeout(this._holdTimer),!this._drag||this._drag.id!==e.id)return;const i=this._drag.moved;this._drag=i?this._drag:null,i&&(this._selId=e.id,window.setTimeout(()=>this._drag=null,0))}_showToast(t){for(const t of this.renderRoot.querySelectorAll("hp-dialog"))t.closeTransientOverlays("toast");this._toast=t,clearTimeout(this._toastTimer),this._toastTimer=window.setTimeout(()=>{this._toast=""},3500)}_syncPointerHoverTargets(){const t=this._pointerModality.hoverEnabled;for(const e of this.renderRoot.querySelectorAll(dm))e.toggleAttribute("data-pointer-hover",t)}_syncPointerHoverSubtree(t){if(t.nodeType!==Node.ELEMENT_NODE)return;const e=t,i=this._pointerModality.hoverEnabled;e.matches(dm)&&e.toggleAttribute("data-pointer-hover",i);for(const t of e.querySelectorAll(dm))t.toggleAttribute("data-pointer-hover",i)}_clearTransientHover(t=!1){t&&this._pointerModality.suspend(),this._tip&&(this._tip=null),this._hoverRoom&&(this._hoverRoom=null)}_notePointer(t){this._boundaryPointerType=t.pointerType||"mouse";const e=this._pointerModality.modality,i=this._pointerModality.note(t);"touch"!==i&&"pen"!==i||e===i&&!this._tip&&!this._hoverRoom||this._clearTransientHover()}_guardTouchGesture(t){if(this._editorSecondary.handleOutsideDismiss(t))return;if("click"===t.type){if(!this._suppressClick&&!this._touchSequenceMultitouch&&Date.now()>this._touchClickBlockUntil)return;return t.preventDefault(),void t.stopImmediatePropagation()}const e=t;if(this._notePointer(e),"touch"===e.pointerType)if("pointerdown"!==t.type){if("pointermove"===t.type){const t=this._touchContacts.get(e.pointerId);if(!t)return;const i={...t,x:e.clientX,y:e.clientY};if(this._touchContacts.set(e.pointerId,i),this._touchSequenceMultitouch&&"view"===this._mode&&!this._vacFit&&this._pinchStart&&[...this._touchContacts.values()].every(t=>t.inStage)){this._pointers.set(e.pointerId,{x:e.clientX,y:e.clientY});const t=[...this._touchContacts.values()];if(t.length>=2&&this._stageEl){const[e,i]=t,s=Math.hypot(e.x-i.x,e.y-i.y)/(this._pinchStart.dist||1),n=this._stageEl.getBoundingClientRect();this._zoomAt((e.x+i.x)/2-n.left,(e.y+i.y)/2-n.top,this._pinchStart.zoom*s),this._saveZoom()}}return}if("pointerup"===t.type||"pointercancel"===t.type||"lostpointercapture"===t.type){if(this._clearTransientHover(),this._touchContacts.delete(e.pointerId),this._touchSequenceMultitouch){if(this._touchClickBlockUntil=Date.now()+500,this._pointers.delete(e.pointerId),!this._vacFit&&this._pointers.size>=2){const[t,e]=[...this._pointers.values()];this._pinchStart={dist:Math.hypot(t.x-e.x,t.y-e.y),zoom:this._zoom}}else this._pinchStart=null;0===this._pointers.size&&(this._panStart=null,this._panLock=null)}0===this._touchContacts.size&&(this._touchSequenceMultitouch=!1)}}else if(this._touchContacts.set(e.pointerId,{x:e.clientX,y:e.clientY,inStage:!!e.target?.closest?.(".stage")}),this._touchContacts.size>=2){this._clearTransientHover(),this._touchSequenceMultitouch=!0,this._touchClickBlockUntil=Number.POSITIVE_INFINITY,clearTimeout(this._holdTimer),clearTimeout(this._kioskHoldTimer),this._swipeStart=null;const t=[...this._touchContacts.values()];if("view"===this._mode&&!this._vacFit&&t.every(t=>t.inStage)){this._pointers=new Map([...this._touchContacts].map(([t,e])=>[t,{x:e.x,y:e.y}]));const[e,i]=t;this._pinchStart={dist:Math.hypot(e.x-i.x,e.y-i.y),zoom:this._zoom},this._panStart=null,this._panLock=null}else this._vacFit&&(this._pointers.clear(),this._pinchStart=null,this._panStart=null,this._panLock=null)}}_showTip(t,e,i,s,n,o){this._notePointer(t),this._pointerModality.hoverEnabled&&(this._drag||(this._tip={x:t.clientX,y:t.clientY,title:e,meta:i,lqi:s,temp:n,hum:o}))}get _gridPitch(){return kc}get _cellCm(){const t=Number(this._curSpaceCfg?.cell_cm);return Number.isFinite(t)&&t>0?t:5}_fmtLen(t,e){const i=function(t,e,i,s){return Math.hypot(e[0]-t[0],e[1]-t[1])/i*s}(t,e,this._gridPitch,this._cellCm);return li(i,"mi"===this.hass?.config?.unit_system?.length)}get _curSpaceCfg(){const t=this._rszPreview;return t&&t.space===this._space?t.sp:this._serverCfg?.spaces.find(t=>t.id===this._space)}get _renderCfg(){const t=this._rszPreview;return t&&this._serverCfg?{...this._serverCfg,spaces:this._serverCfg.spaces.map(e=>e.id===t.space?t.sp:e)}:this._serverCfg}get _spaceH(){return this._curSpaceCfg,pm}get _segments(){const t=this._curSpaceCfg,e=this._spaceH;return pi(t?.rooms||[]).map(t=>[t[0]*pm,t[1]*e,t[2]*pm,t[3]*e])}_savedNav(){if(this._hasFixedFloor)return null;try{return JSON.parse(localStorage.getItem(lm)||"null")}catch{return null}}_saveNav(){if(!this._hasFixedFloor)try{localStorage.setItem(lm,JSON.stringify({space:this._space}))}catch{}}_leaveCardRoute(){if(this._routeDepartureHandled)return;this._routeDepartureHandled=!0,"view"!==this._mode&&this._setMode("view",!1),this._pendingNavMode=null,this._geometryHistory.clear(),this._activeDraftId=null,this._resumeDraftBySpace={},this._draftSegmentCms=[],this._closingWallCm=null,this._drawWallField=null,this._showHidden=!1,this._tapConfirm=null,this._vacCalConfirm=null,this._decorEraseConfirm=null,this._openingInfo=null,this._closeInfoCard(),this._rulesDialog=null,this._alignDialog=null,this._backupImportDialog=null,this._backupExportDialog=null,this._settingsDialog=null,this._markerDialog=null,this._openingDialog=null,this._physicalDialog=null,this._wallDialog=null,this._backdropDialog=null,this._decorShapeDialog=null,this._decorTextDialog=null,this._mergeDialog=null,this._roomDialog=!1,this._spaceDialog=null,this._importDialog=null;const t=this._warmSlot;t?.owner===this._warmGen&&(t.vp=this._warmViewportState(),t.dlg=null,t.frameFingerprint="",clearTimeout(t.evict),t.evict=0),this._saveNav()}_setMode(t,e=!0){this._endTabDrag(),this._pendingNavMode=null;const i=this._spaceModel();if(!i)return this._cancelModeTransition(!1),void(this._mode="view");if(this._kiosk&&"view"!==t)return;if(this._mode===t){if(!e&&"view"===t&&this._modeTransitionBusy){const e=this._currentModeVisual(t),i=this._modeTransitionTargetZoom,s=this._modeTransitionTargetCenterX,n=this._modeTransitionTargetCenterY;this._cancelModeTransition(!1),this._commitViewModeAtomic(e,i,s,n)}return}if(this._bootSoftCancel(),("plan"===t||"decor"===t)&&!this._norm)return void this._showToast(this._t("toast.markup_needs_server"));if(this._wallFaceBatch&&this._roomDialogCancel(),"plan"===this._mode&&"draw"===this._tool&&!this._finishWallChain())return;this._clearTransientHover(!0),this._cancelDevicePressFeedback();const s=this._mode,n=this._effectiveProjection(),o=this._currentModeVisual(s),r=this._modeTransitionBusy,a=o&&"view"!==s&&"view"!==t?{...o,toolbarContentOpacity:this._reducedMotion?1:.35}:o;this._cancelModeTransition(!1),this._editorSecondary.closeForNavigation(),(this._decorMove||this._dtDrag||this._bdDrag)&&this._cancelDecorGesture();const l=!i.bg&&"view"===t!=("view"===s),c=r&&"view"===s&&"view"!==t?this._modeTransitionEditorCamera:null;let h=c?.zoom??(r?this._modeTransitionTargetZoom:this._zoom),d=c?c.centerX:r?this._modeTransitionTargetCenterX:a?.viewport.centerX,p=c?c.centerY:r?this._modeTransitionTargetCenterY:a?.viewport.centerY;if("view"===s&&"view"!==t&&!r){const e=this._view;if(this._viewModeSnap={space:this._space,zoom:this._zoom,cx:e?this._logicalViewCenter(n)?.x:void 0,cy:e?this._logicalViewCenter(n)?.y:void 0},"iso"===n){const e=this._logicalViewCenter("iso");d=e?.x,p=e?.y,this._view=null,this._mode=t,this._applyView(this._zoom,e?.x,e?.y)}l&&(h=1,d=void 0,p=void 0)}if("plan"===s&&this._activeDraftId&&(this._resumeDraftBySpace[this._space]=this._activeDraftId),this._mode=t,this._editorChromeMode="view"===t?s:t,"view"===t){"view"===s||r||(this._modeTransitionEditorCamera={zoom:this._zoom,centerX:a?.viewport.centerX,centerY:a?.viewport.centerY});const t=this._viewModeSnap;if(t&&t.space===this._space){h=t.zoom;const e=this._labsIso&&"iso"===this._viewPreference[this._space]?"iso":"flat",i=null!=t.cx&&null!=t.cy&&"iso"===e?ag([t.cx,t.cy],0):null;d=i?.[0]??t.cx,p=i?.[1]??t.cy}else t&&(h=this._zoomBySpace[this._space]||1,d=void 0,p=void 0)}else this._modeTransitionEditorCamera={zoom:h,centerX:d,centerY:p};this._modeTransitionTargetZoom=h,this._modeTransitionTargetCenterX=d,this._modeTransitionTargetCenterY=p,("iso"===n||"view"===t&&this._labsIso&&"iso"===this._viewPreference[this._space])&&(this._modeTransitionForceAtomic=!0);const u=++this._modeTransitionRequest;e?a?(this._modeTransitionPreparing=!0,this._modeTransitionVisual=a,this._prepareModeTransition(u,a,t,h,d,p)):(this._modeTransitionPreparing=!1,this._modeTransitionVisual=null,this._zoom=h,this._view=null,requestAnimationFrame(()=>{this.isConnected&&u===this._modeTransitionRequest&&this._mode===t&&(this._applyView(h,d,p),"view"===t&&(this._viewModeSnap=null,this._modeTransitionEditorCamera=null),this.requestUpdate())})):"view"===t&&this._commitViewModeAtomic(a,h,d,p),this._path=[],this._clearPlanSnapHover(),this._clearOpeningPlacement(!0),this._openWallAnchor=null,this._boundaryRestoreGuard=null,this._tool="draw",this._mergeSel=null,this._mergeDialog=null,this._splitSel=null,this._pendingSplit=null,this._selId=null,this._physicalSel=null,this._physicalDialog=null,this._physicalDrag=null,this._rszSel=null,this._rszDrag=null,this._rszLive=null,this._rszPreview=null,this._tip=null,this._hoverRoom=null,this._decorDraft=null,this._decorSel=null,this._decorMove=null,this._backdropDialog=null,this._decorTool="select",this._bdDrag=null,this._dtDrag=null,this._dtBox=null,"plan"===t&&(this._primeDrawWallField(),this._resumeLastDraft()),this._saveNav()}_primeDrawWallField(){null===this._drawWallField&&(this._drawWallField=ka(fa,this._imperial))}get _drawWallFieldValue(){return null===this._drawWallField?ka(fa,this._imperial):this._drawWallField}get _drawWallCm(){const t=Zg(this._drawWallFieldValue);if(null==t||t<=0)return null;const e=this._imperial?2.54*t:t,i="column"===this._tool?Hl:100;return e>=1&&e<=i?e:null}get _drawWallMaxCm(){return"column"===this._tool?Hl:100}_showPhysicalRange(t=this._drawWallMaxCm){this._showToast(this._t("toast.physical_range",{max:ka(t,this._imperial),unit:this._t(this._imperial?"wallthick.unit_in":"wallthick.unit_cm")}))}_draftSegmentCount(t=this._curSpaceCfg){return(t?.room_drafts||[]).reduce((t,e)=>t+(Array.isArray(e.segments)?e.segments.length:0),0)}_mergeSpacePartitions(t,e){const i=t?.partitions||[];if(i.length<2)return 0;const s=o_(i,{pitch:xc,seedIds:e,geometry:a_(t,{excludeDraftId:this._activeDraftId})});return s.merged?(t.partitions=s.partitions,r_(t.openings,t.partitions,s.openingMoves,{coordScale:pm,cellCm:this._cellCm,gridPitch:this._gridPitch}),s.merged):0}_finishWallChain(){if("draw"!==this._tool||this._wallFaceBatch||this._roomDialog)return!0;const t=this._curSpaceCfg;if(!t||this._path.length<2)return this._path=[],this._activeDraftId=null,this._draftSegmentCms=[],this._closingWallCm=null,this._clearPlanSnapHover(),!0;const e=tp(this._path,Qd(this._path.length-1,this._draftSegmentCms,this._drawWallCm,fa)),i=e.length;if((t.partitions||[]).length+i>mm)return this._showToast(this._t("toast.physical_limit")),!1;const s=this._geometrySnapshot();t.partitions||=[];const n=Date.now().toString(36),o=[];for(let s=0;st.id!==this._activeDraftId),t.room_drafts.length||delete t.room_drafts),this._recordGeometry(this._t("history.wall_chain_finish"),s),this._saveConfig(),delete this._resumeDraftBySpace[this._space],this._path=[],this._activeDraftId=null,this._draftSegmentCms=[],this._closingWallCm=null,this._clearPlanSnapHover(),!0}_activateMarkupTool(t){t!==this._tool&&(this._wallFaceBatch&&this._roomDialogCancel(),("draw"!==this._tool||this._finishWallChain())&&(this._cancelPath(),this._tool=t,"draw"===t&&this._resumeLastDraft(),"resize"===t&&(this._rszSel=null),"boundary"!==t&&"wallthick"!==t||(this._wallDialog=null)))}_limitReached(t){const e=this._curSpaceCfg;if(!e)return!0;const i="draft"===t?(e.room_drafts||[]).length>=200:"partition"===t?(e.partitions||[]).length>=mm:(e.wall_columns||[]).length>=500;return i&&this._showToast(this._t("toast.physical_limit")),i}_svgPoint(t){const e=this.renderRoot.querySelector(".stage").getBoundingClientRect();return this._screenToVb(t.clientX-e.left,t.clientY-e.top)}_snap(t){const e=this._gridPitch;return[Mc(ai(t[0],e)),Mc(ai(t[1],e))]}_snapDrawPoint(t,e=!1){const i=this._path[this._path.length-1],s=e&&i?function(t,e,i,s=1/0){if(!(i>0&&t?.every(Number.isFinite)&&e?.every(Number.isFinite)))return[e[0],e[1]];const n=e[0]-t[0],o=e[1]-t[1];if(Math.abs(n)+Math.abs(o)<=1e-12)return[t[0],t[1]];const r=Math.PI/4;let a=Math.atan2(o,n);a<0&&(a+=2*Math.PI);const l=Math.floor(a/r+.5)%8,[c,h]=[[1,0],[1,1],[0,1],[-1,1],[-1,0],[-1,-1],[0,-1],[1,-1]][l],d=c*c+h*h;let p=Math.max(0,Math.round((n*c+o*h)/(i*d)));if(Number.isFinite(s)&&s>=0){const e=(t,e)=>{if(!e)return 1/0;const n=e>0?s-t:t+s;return Math.max(0,Math.floor((n+1e-9*i)/i))};p=Math.min(p,e(t[0],c),e(t[1],h))}return[t[0]+c*p*i,t[1]+h*p*i]}(i,t,this._gridPitch,bc):t;return this._snap(s)}_planSnapOpeningCuts(t,e){if(!this._openingsR.length)return[];const i=this._openingWallIndexFor(t,e).value,s=[];for(const e of this._roomWallOpeningInputs(this._openingsR,t)){const t=Fl(i,e);if(!t.negative&&!t.positive)continue;const n=e.angle*Math.PI/180,o=Math.cos(n)*e.length/2,r=Math.sin(n)*e.length/2;s.push([e.x-o,e.y-r,e.x+o,e.y+r])}return s}_planSnapGeometrySnapshot(){const t=this._spaceModel();if(!t)return{key:`${this._space}|empty`,value:{segments:[],endpoints:[]}};const e=[this._space,this._cfgEpoch,this._activeDraftId||"",t.rooms.length,t.room_drafts.length,t.partitions.length].join("|");if(this._planSnapGeometryCache?.key===e)return this._planSnapGeometryCache;const i=this._openCuts(),s=Ud({space:t,activeDraftId:this._activeDraftId,roomCuts:[...i,...this._planSnapOpeningCuts(t,i)],partitionCuts:this._partitionOpeningCuts(t),epsilon:2e-4*this._gridPitch});return this._planSnapGeometryCache={key:e,value:s},this._planSnapGeometryCache}_planStructuralGeometrySnapshot(){const t=this._spaceModel();if(!t)return{key:`${this._space}|structural-empty`,value:{segments:[],endpoints:[]}};const e=["structural",this._space,this._cfgEpoch,this._activeDraftId||"",t.rooms.length,t.room_drafts.length,t.partitions.length].join("|");if(this._planStructuralGeometryCache?.key===e)return this._planStructuralGeometryCache;const i=Ud({space:t,activeDraftId:this._activeDraftId,roomCuts:this._openCuts(),epsilon:2e-4*this._gridPitch});return this._planStructuralGeometryCache={key:e,value:i},this._planStructuralGeometryCache}_planSnapContextKey(t){const e=this._path[0],i=this._path[this._path.length-1];return[t,this._tool,this._path.length,e?`${e[0]},${e[1]}`:"",i?`${i[0]},${i[1]}`:""].join("|")}_resolvePlanDrawPoint(t,e){const i=this._planSnapGeometrySnapshot(),s=this._path[this._path.length-1],n="draw"===this._tool&&this._path.length>=3?[{point:this._path[0],key:"closure:first-point"}]:[],o={tolerance:this._cssPxToRender(12),distinguishTolerance:this._cssPxToRender(8),gridStep:this._gridPitch,excludePoints:s?[s]:[],extraEndpoints:n,epsilon:2e-4*this._gridPitch},r=e&&s?Jd(i.value,t,{...o,anchor:s}):function(t,e,i){if(!(Nd(e)&&i.tolerance>=0))return{kind:"none",candidate:null,conflicts:[]};const s=i.epsilon??Od,n=i.excludePoints||[],o=Yd(Kd(t,e,i),i.distinguishTolerance||0);if(o)return o;let r=null;for(const o of t.segments){const t=[o.a[0],o.a[1],o.b[0],o.b[1]],a=Hs([e[0],e[1]],t);if(a>i.tolerance)continue;const l=Xd(o,e,i.gridStep);!Gd(l,n,s)&&Vd(a,o.key,r)&&(r={kind:"line",point:l,key:o.key,distance:a,segment:o})}return r?{kind:"resolved",candidate:r,conflicts:[]}:{kind:"none",candidate:null,conflicts:[]}}(i.value,t,o),a="resolved"===r.kind?r.candidate:null;return{point:a?[...a.point]:this._snapDrawPoint(t,e),candidate:a,conflicts:"ambiguous"===r.kind?r.conflicts:[],ambiguous:"ambiguous"===r.kind,contextKey:this._planSnapContextKey(i.key)}}get _activePlanSnapCandidate(){if(!this._markup||"draw"!==this._tool)return null;const t=this._planSnapHover;if(!t)return null;const e=this._planSnapGeometrySnapshot();return t.contextKey===this._planSnapContextKey(e.key)?t.candidate:null}get _activePlanSnapConflicts(){if(!this._markup||"draw"!==this._tool)return[];const t=this._planSnapHover;if(!t)return[];const e=this._planSnapGeometrySnapshot();return t.contextKey===this._planSnapContextKey(e.key)?t.conflicts:[]}_clearPlanSnapHover(t=!0){this._planSnapHover=null,this._syncPlanSnapActiveMarker(null),this._syncPlanSnapConflictMarkers([]),t&&(this._cursorPt=null)}_samePt(t,e){return fi(t,e)}_dropLegacySegments(){for(const t of this._serverCfg?.markers||[])"ripple"===t.display&&(t.display="icon_ripple");for(const t of this._serverCfg?.spaces||[]){delete t.segments;const e=new Set,i=t=>"string"==typeof t&&t.length>=1&&t.length<=64&&!e.has(t),s=t=>(e.add(t),!0),n=t=>Array.isArray(t)&&2===t.length&&t.every(t=>Number.isFinite(Number(t))&&Math.abs(Number(t))<=yc);if(Array.isArray(t.partitions)&&(t.partitions=t.partitions.filter(t=>t&&i(t.id)&&n(t.a)&&n(t.b)&&Math.hypot(t.a[0]-t.b[0],t.a[1]-t.b[1])>1e-9&&s(t.id)).map(t=>({...t,cm:Math.max(1,Math.min(100,Number(t.cm)||15))})),t.partitions.length||delete t.partitions),Array.isArray(t.wall_columns)&&(t.wall_columns=t.wall_columns.filter(t=>t&&i(t.id)&&n(t.center)&&s(t.id)).map(t=>({id:t.id,shape:"circle"===t.shape?"circle":"square",center:[Number(t.center[0]),Number(t.center[1])],cm:Bl(Number(t.cm)||15),..."circle"===t.shape?{}:{angle:ql(t.angle)}})),t.wall_columns.length||delete t.wall_columns),Array.isArray(t.room_drafts)&&(t.room_drafts=t.room_drafts.filter(t=>t&&i(t.id)&&Array.isArray(t.points)&&t.points.length>=2&&t.points.every(n)&&s(t.id)).map(t=>{const e=[[Number(t.points[0][0]),Number(t.points[0][1])]],i=[];for(let s=1;st.points.length>=2),t.room_drafts.length||delete t.room_drafts),Array.isArray(t.walls)){const e=rh(t.open_spans).map(t=>[t.a[0],t.a[1],t.b[0],t.b[1]]);t.walls=Ea(t.walls,t.rooms||[],xc,1,e),t.walls.length||delete t.walls}}}get _cfgWriting(){return this._writesPending>0}_writeConfig(){var t,e;this._writesPending++,this._writeChain=(t=this._writeChain,e=async()=>{if(!this._serverCfg)return;this._dropLegacySegments();const t=Zu(this._serverCfg),e=Ch(t);e!==Ch(this._serverCfg)&&(this._serverCfg=t),this._cfgContentFingerprint=e;const i=await this.hass.callWS({type:"houseplan/config/set",config:t,expected_rev:this._cfgRev});this._cfgRev=i?.rev??this._cfgRev+1},t.catch(()=>{}).then(e));return this._writeChain.finally(()=>{this._writesPending--})}_saveConfig(){this._cfgEpoch++,this._saveConfigDebounced()}_geometrySnapshot(t=this._space){const e=this._serverCfg?.spaces.find(e=>e.id===t);if(!e)return null;const i=t=>JSON.parse(JSON.stringify(t)),s={};for(const t of["plan_x","plan_y","plan_scale","plan_scale_x","plan_scale_y","plan_angle"])void 0!==e[t]&&(s[t]=e[t]);return{spaceId:t,rooms:i(e.rooms||[]),...Array.isArray(e.openings)?{openings:i(e.openings)}:{},...Array.isArray(e.walls)?{walls:i(e.walls)}:{},...Array.isArray(e.open_spans)?{open_spans:i(e.open_spans)}:{},...Array.isArray(e.room_drafts)?{room_drafts:i(e.room_drafts)}:{},...Array.isArray(e.partitions)?{partitions:i(e.partitions)}:{},...Array.isArray(e.wall_columns)?{wall_columns:i(e.wall_columns)}:{},...Array.isArray(e.decor)?{decor:i(e.decor)}:{},plan_transform:s}}_recordGeometry(t,e){if(!e)return;const i=this._geometrySnapshot(e.spaceId);i&&JSON.stringify(e)!==JSON.stringify(i)&&(this._geometryHistory.push({name:t,before:e,after:i}),this.requestUpdate())}_clearGeometryGesture(){this._path=[],this._clearPlanSnapHover(),this._clearOpeningPlacement(!1),this._mergeSel=null,this._mergeDialog=null,this._splitSel=null,this._pendingSplit=null,this._wallFaceBatch=null,this._wallRepairDiagnostic=null,this._roomDeleteDialog=null,this._openWallAnchor=null,this._boundaryRestoreGuard=null,this._wallDialog=null,this._physicalDialog=null,this._physicalSel=null,this._physicalDrag=null,this._physicalRotate=null,this._activeDraftId=null,this._draftSegmentCms=[],this._closingWallCm=null,this._openingDialog=null,this._rszSel=null,this._rszDrag=null,this._rszPreview=null,this._rszLive=null,this._decorDraft=null,this._decorMove=null,this._dtDrag=null,this._bdDrag=null}_cancelBoundaryAnchor(){return!("boundary"!==this._tool||!this._openWallAnchor)&&(this._openWallAnchor=null,this._boundaryRestoreGuard=null,this._clearPlanSnapHover(),this.requestUpdate(),!0)}_stagePointerCancel(t){if(clearTimeout(this._kioskHoldTimer),this._swipeStart?.id===t.pointerId&&(this._swipeStart=null),this._physicalDrag?.pid===t.pointerId||this._physicalRotate?.pid===t.pointerId)return void this._cancelPhysicalGesture();if(this._decorDraft?.pid===t.pointerId)return this._decorDraft=null,void this.requestUpdate();if(this._decorMove?.pid===t.pointerId||this._dtDrag?.pid===t.pointerId||this._bdDrag?.pid===t.pointerId)return void this._cancelDecorGesture();this._cancelBoundaryAnchor(),"opening"===this._tool?(this._cursorPt=null,this._clearOpeningPlacement(!1)):"draw"===this._tool&&this._clearPlanSnapHover();const e=!!this._pinchStart||!!this._panStart;this._pointers.delete(t.pointerId),this._pointers.size<2&&(this._pinchStart=null),0===this._pointers.size&&(this._panStart=null,this._panLock=null),e&&0===this._pointers.size&&this.requestUpdate()}_applyGeometryState(t){if(!this._canCommitSpace(t.spaceId))return!1;const e=this._serverCfg?.spaces.find(e=>e.id===t.spaceId);if(!e)return!1;const i=t=>JSON.parse(JSON.stringify(t));e.rooms=i(t.rooms),void 0!==t.openings?e.openings=i(t.openings):delete e.openings,void 0!==t.walls?e.walls=i(t.walls):delete e.walls,void 0!==t.open_spans?e.open_spans=i(t.open_spans):delete e.open_spans,void 0!==t.room_drafts?e.room_drafts=i(t.room_drafts):delete e.room_drafts,void 0!==t.partitions?e.partitions=i(t.partitions):delete e.partitions,void 0!==t.wall_columns?e.wall_columns=i(t.wall_columns):delete e.wall_columns,void 0!==t.decor?e.decor=i(t.decor):delete e.decor;for(const t of["plan_x","plan_y","plan_scale","plan_scale_x","plan_scale_y","plan_angle"])delete e[t];return Object.assign(e,i(t.plan_transform||{})),this._clearGeometryGesture(),this._space!==t.spaceId&&(this._commitSpace(t.spaceId),this._saveNav(),this._restoreZoom()),this._modelCache=null,this._frame=null,this._regSignature="",this._maybeRebuildDevices(),this._saveConfig(),this.requestUpdate(),!0}_roomAt(t){return this._spaceModel()?.rooms.find(e=>{const i=hi(e);return!!i&&wi(t,i)})}_overlapRoom(t){return this._spaceModel()?.rooms.find(e=>{const i=hi(e);return!!i&&Di(t,i)})}_pointInRoom(t,e){return e.poly?vi(t,e.poly):null!=e.x&&t[0]>=e.x&&t[0]<=e.x+e.w&&t[1]>=e.y&&t[1]<=e.y+e.h}_contourSelfIntersects(t){if(!kr(t))return!0;const e=t.length,i=.001;for(let s=0;s=500)return this._showToast(this._t("toast.physical_limit")),!1;const t=this._curSpaceCfg;return!(!this._activeDraftId&&(t?.room_drafts||[]).length>=200||this._draftSegmentCount(t)>=2e3||(t?.partitions||[]).length+this._path.length>mm)||(this._showToast(this._t("toast.physical_limit")),!1)}_markupClick(t){if(this._vacFit)return;if(!this._markup)return;const e=this._spaceModel();if(!e)return void this._clearGeometryGesture();if(this._suppressClick)return;if(this._drag||this._rlResize)return;const i=t.composedPath?.()||[];if(i.some(t=>t?.classList?.contains?.("roomlabel")||t?.classList?.contains?.("rlhandle")))return;if(i.some(t=>t?.classList?.contains?.("physical-hit")))return void("boundary"===this._tool&&this._showToast(this._t("toast.boundary_blocked")));const s=this._svgPoint(t);if("select"===this._tool)return void(this._physicalSel=null);if("resize"===this._tool){if(this._rszDrag||i.some(t=>t?.classList?.contains?.("rszhandle")))return;const t=[...e.rooms].reverse().find(t=>this._pointInRoom(s,t));return void(this._rszSel=t?.id||null)}if("delroom"===this._tool)return void this._deleteRoomClick(s);if("opening"===this._tool)return void this._openingClick(s);if("merge"===this._tool)return void this._mergeClick(s);if("wallthick"===this._tool)return void this._wallThickClick(s);if("boundary"===this._tool)return void this._boundaryClick(s);if("split"===this._tool)return void this._splitClick(s);if("column"===this._tool)return void this._columnClick(s);this._wallRepairDiagnostic=null;const n=this._resolvePlanDrawPoint(s,t.shiftKey);if(n.ambiguous)return this._planSnapHover={contextKey:n.contextKey,candidate:null,conflicts:n.conflicts},this._syncPlanSnapActiveMarker(null),this._syncPlanSnapConflictMarkers(n.conflicts),void this._showToast(this._t("toast.plan_snap_ambiguous"));let o=n.point;if(t.ctrlKey||t.metaKey){if(t.preventDefault(),this._path.length<3)return;o=[...this._path[0]]}if(!this._path.length){if(!t.shiftKey&&!n.candidate&&this._offerExistingWallFace(s))return;const e=this._draftEndAt(o);return e?(this._activeDraftId=e.draft.id,this._resumeDraftBySpace[this._space]=e.draft.id,this._path=e.reverse?[...e.draft.points].reverse().map(t=>[...t]):e.draft.points.map(t=>[...t]),void(this._draftSegmentCms=this._adoptDraftCms(this._path,e.reverse?[...e.draft.segments].reverse().map(t=>t.cm):e.draft.segments.map(t=>t.cm),e.draft.id))):(this._activeDraftId=null,this._draftSegmentCms=[],void(this._path=[o]))}const r=this._path[this._path.length-1];if(this._samePt(o,r))return;const a=this._draftEndAt(o,this._activeDraftId||void 0);if(a)return void this._mergeDraftEndpoint(a);if(!this._canAppendRoomDraftPoint())return;const l=this._drawWallCm;if(null==l)return void this._showPhysicalRange(100);const c=this._path.map(t=>[...t]);this._path=[...this._path,o],this._draftSegmentCms=[...this._draftSegmentCms,l],this._persistActiveDraftSegment(),this._offerWallFaces(c)}_draftEndAt(t,e){const i=this._spaceModel();if(!i)return null;const s=this._viewOr(this._baseVb()),n=Math.max(.15*this._gridPitch,this._stageEl?.clientWidth?s.w/this._stageEl.clientWidth*12:0);for(const s of i.room_drafts||[]){if(s.id===e)continue;if(s.points.length<2)continue;const i=s.points[0],o=s.points[s.points.length-1];if(Math.hypot(t[0]-o[0],t[1]-o[1])<=n)return{draft:s,reverse:!1};if(Math.hypot(t[0]-i[0],t[1]-i[1])<=n)return{draft:s,reverse:!0}}return null}_mergeDraftEndpoint(t){const e=this._curSpaceCfg;if(!e||!this._path.length)return;const i=this._path.map(t=>[...t]),s=this._wallGraphSources(i),n=Array.isArray(e.room_drafts)?e.room_drafts:[],o=this._activeDraftId?n.find(t=>t.id===this._activeDraftId):null,r=n.find(e=>e.id===t.draft.id);if(!r)return;const a=t.reverse?t.draft.points.map(t=>[...t]):[...t.draft.points].reverse().map(t=>[...t]),l=t.reverse?(r.segments||[]).map(t=>({...t})):[...r.segments||[]].reverse().map(t=>({...t})),c=this._path[this._path.length-1],h=this._samePt(c,a[0]),d=h?null:this._drawWallCm;if(!h&&null==d)return void this._showPhysicalRange(100);const p=this._draftSegmentCms.map((t,e)=>({...o?.segments?.[e]||{},cm:t})),u=[...this._path.map(t=>[...t]),...h?a.slice(1):a],_=[...p,...null==d?[]:[{cm:d}],...l],g=u.length>=4&&this._samePt(u[0],u[u.length-1]),m=u,f=_;if(m.length>500)return void this._showToast(this._t("toast.physical_limit"));const v=(o?.segments?.length||0)+(r.segments?.length||0);if(this._draftSegmentCount(e)-v+f.length>2e3)return void this._showToast(this._t("toast.physical_limit"));if(g){const t=m.slice(0,-1);if(this._contourSelfIntersects(t)||Pi(t)<=1e-6)return void this._showToast(this._t("toast.contour_cannot_close"));const e=this._overlapRoom(t);if(e)return void this._showToast(this._t("toast.room_overlap",{name:e.name||""}))}const y=this._geometrySnapshot(),b=this._activeDraftId||t.draft.id,w={...o||r,id:b,points:m.map(t=>[t[0]/pm,t[1]/pm]),segments:f};e.room_drafts=n.filter(e=>e.id!==t.draft.id&&(!this._activeDraftId||e.id!==this._activeDraftId)),e.room_drafts.push(w),this._activeDraftId=b,this._resumeDraftBySpace[this._space]=b,this._path=m,this._draftSegmentCms=this._adoptDraftCms(m,f.map(t=>Number(t.cm)),b),this._physicalSel=null,this._recordGeometry(this._t("history.draft_merge"),y),this._saveConfig(),null!=d&&this._offerWallFaces(i,i.length-1,s)}_adoptDraftCms(t,e,i){const s=Math.max(0,t.length-1),n=Qd(s,e,this._drawWallCm,fa);return e.length!==s&&console.debug(`[houseplan] draft ${i??"?"}: восстановлено толщин ${s-e.length} (#234)`),n}_persistActiveDraftSegment(){if(this._path.length<2||!this._curSpaceCfg)return;const t=this._geometrySnapshot(),e=this._curSpaceCfg;e.room_drafts||=[],this._activeDraftId||(this._activeDraftId="draft-"+Date.now().toString(36)),this._resumeDraftBySpace[this._space]=this._activeDraftId;const i=e.room_drafts.findIndex(t=>t.id===this._activeDraftId),s={...i>=0?e.room_drafts[i]:{},id:this._activeDraftId,points:this._path.map(t=>[t[0]/pm,t[1]/pm]),segments:this._draftSegmentCms.map((t,s)=>({...i>=0?e.room_drafts[i]?.segments?.[s]:{},cm:t}))};i>=0?e.room_drafts[i]=s:e.room_drafts.push(s),this._recordGeometry(this._t("history.draft_segment"),t),this._saveConfig()}_activeWallSourceKey(t){return`active:${this._activeDraftId||"session"}:${t}`}_wallGraphSources(t){const e=this._planStructuralGeometrySnapshot().value.segments.map(t=>({a:t.a,b:t.b,key:`static:${t.key}`}));for(let i=0;i+1t.key===i);if(s>=0){const[t]=this._wallFaceGraphCache.splice(s,1);return this._wallFaceGraphCache.push(t),t.value}const n=kp(t,e);return this._wallFaceGraphCache.push({key:i,value:n}),this._wallFaceGraphCache.length>4&&this._wallFaceGraphCache.shift(),n}_offerWallFaces(t,e=this._path.length-2,i){if(this._path.length<2||this._wallFaceBatch||this._roomDialog)return;const s=this._spaceModel();if(!s)return;const n=this._activeWallSourceKey(e),o=2e-4*this._gridPitch;let r,a;try{const e=i||this._wallGraphSources(t);a=this._wallGraphSources(this._path),r=function(t,e,i){const s=new Set(t.faces.map(t=>t.key));return e.faces.filter(t=>!s.has(t.key)&&t.sourceKeys.includes(i))}(this._wallFaceGraph(e,o),this._wallFaceGraph(a,o),n)}catch{return}if(!r.length){const t=Fp(a,{requiredSourceKey:n,maxDistance:xa(2,this._cellCm,this._gridPitch),gridStep:this._gridPitch,epsilon:o});return"ambiguous"===t.kind?(this._wallRepairDiagnostic=t.proposals[0]||null,void this._showToast(this._t("toast.wall_repair_ambiguous"))):void("repair"!==t.kind||this._overlapRoom(t.face.ring)||this._beginWallFaceBatch([{...t.face,repair:t.proposal}]))}for(const t of s.rooms){const e=hi(t);if(!t.id||!e)continue;const i=Fi(e,this._path,.02*this._gridPitch);if(!i)continue;const[s,n]=i,o=Pi(s)>=Pi(n)?s:n,a=o===s?n:s,l=[...r].sort((t,e)=>Math.abs(t.area-Pi(a))-Math.abs(e.area-Pi(a))||t.key.localeCompare(e.key))[0];if(!l)return;return void this._beginWallFaceBatch([{...l,ring:a.map(t=>[t[0],t[1]]),split:{roomId:t.id,mainPoly:o,newPoly:a},consumeAllActive:!0}])}const l=r.filter(t=>!(t.ring.length<3||this._contourSelfIntersects(t.ring))&&!this._overlapRoom(t.ring));l.length&&this._beginWallFaceBatch(l)}_beginWallFaceBatch(t){this._wallRepairDiagnostic=null,this._wallFaceBatch={candidates:[...t].sort((t,e)=>t.area-e.area||t.key.localeCompare(e.key)),index:0,decisions:[],activePath:this._path.map(t=>[...t]),activeCms:[...this._draftSegmentCms],activeDraftId:this._activeDraftId},this._clearPlanSnapHover(),this._nameSel="",this._areaSel="",this._resetRoomDialogFields(),this._roomDialog=!0}_offerExistingWallFace(t){if(this._path.length||this._wallFaceBatch||this._roomDialog)return!1;const e=2e-4*this._gridPitch;try{let i,s=xp(this._wallFaceGraph(this._wallGraphSources([]),e),t,e);if(!s){const n=Fp(this._wallGraphSources([]),{point:t,maxDistance:xa(2,this._cellCm,this._gridPitch),gridStep:this._gridPitch,epsilon:e});if("ambiguous"===n.kind)return this._wallRepairDiagnostic=n.proposals[0]||null,this._showToast(this._t("toast.wall_repair_ambiguous")),!0;if("repair"===n.kind)s=n.face,i=n.proposal;else if("none"===n.kind){const i=Fp(this._wallGraphSources([]),{point:t,maxDistance:this._cssPxToRender(12),gridStep:this._gridPitch,epsilon:e});if("repair"===i.kind)return this._wallRepairDiagnostic=i.proposal,this._showToast(this._t("toast.wall_repair_too_large")),!0}}return!(!s||s.ring.length<3||this._contourSelfIntersects(s.ring)||this._overlapRoom(s.ring))&&(this._beginWallFaceBatch([{...s,existing:!i,repair:i}]),!0)}catch{return!1}}_columnClick(t){const e=this._snap(t),i=this._drawWallCm;if(null==i)return void this._showPhysicalRange(Hl);if(!this._curSpaceCfg||this._limitReached("column"))return;const s=this._spaceModel();if(!s)return;const n={id:"column-"+Date.now().toString(36),shape:"square",center:e,cm:Bl(i),angle:0},o=(s.wall_columns||[]).find(t=>rc(t,n,.02*this._gridPitch));if(o)return clearTimeout(this._duplicateColumnTimer),this._duplicateColumnId=o.id,this._duplicateColumnTimer=window.setTimeout(()=>{this._duplicateColumnId=null},900),void this._showToast(this._t("toast.column_duplicate"));const r=this._geometrySnapshot(),a=this._curSpaceCfg;a.wall_columns||=[],a.wall_columns.push({...n,center:[e[0]/pm,e[1]/pm]}),this._recordGeometry(this._t("history.column_add"),r),this._saveConfig()}_openPhysicalDialog(t,e,i){const s=this._spaceModel();if(s)if("partition"===t){const i=s.partitions.find(t=>t.id===e);i&&(this._physicalDialog={kind:t,id:e,cm:ka(i.cm,this._imperial),length:this._fmtLen(i.a,i.b)})}else if("column"===t){const i=s.wall_columns.find(t=>t.id===e);i&&(this._physicalDialog={kind:t,id:e,cm:ka(i.cm,this._imperial),shape:i.shape,angle:this._angleField("square"===i.shape?ql(i.angle):0)})}else{const n=s.room_drafts.find(t=>t.id===e),o=Math.max(0,Math.min(n?.segments.length?n.segments.length-1:0,i||0));n?.segments[o]&&(this._physicalDialog={kind:t,id:e,segment:o,cm:ka(n.segments[o].cm,this._imperial),length:this._fmtLen(n.points[o],n.points[o+1])})}}_physicalDown(t,e,i){const s=this._spaceModel();if(!s)return;t.stopPropagation(),bm(t);const n=this._svgPoint(t),o=[];for(const t of[...s.wall_columns].reverse())nc(n,Kl(t,this._cellCm,this._gridPitch))&&o.push({kind:"column",id:t.id});for(const t of[...s.partitions].reverse()){const e=Vl(t.a,t.b,t.cm,this._cellCm,this._gridPitch);e&&nc(n,e)&&o.push({kind:"partition",id:t.id})}o.some(t=>t.kind===e&&t.id===i)||o.unshift({kind:e,id:i});const r=o.map(t=>`${t.kind}:${t.id}`).sort().join("|"),a=performance.now(),l=this._physicalPickCycle,c=o.length>1&&l?.signature===r&&a-l.at>380&&a-l.at<=1200&&Math.hypot(t.clientX-l.x,t.clientY-l.y)<=10?(l.index+1)%o.length:Math.max(0,o.findIndex(t=>t.kind===e&&t.id===i));this._physicalPickCycle={signature:r,index:c,x:t.clientX,y:t.clientY,at:a},e=o[c].kind,i=o[c].id;const h="partition"===e?s.partitions.find(t=>t.id===i):s.wall_columns.find(t=>t.id===i);h&&(this._physicalSel={kind:e,id:i},this._physicalDrag={pid:t.pointerId,kind:e,id:i,start:this._svgPoint(t),startClient:[t.clientX,t.clientY],before:this._geometrySnapshot(),moved:!1,base:JSON.parse(JSON.stringify(h)),delta:[0,0]})}_clampPhysicalDelta(t,e,i){const s="partition"===t?[e.a,e.b]:[e.center],n=s.map(t=>t[0]),o=s.map(t=>t[1]);return[Math.max(-yc*pm-Math.min(...n),Math.min(yc*pm-Math.max(...n),i[0])),Math.max(-yc*pm-Math.min(...o),Math.min(yc*pm-Math.max(...o),i[1]))]}_physicalMove(t){const e=this._physicalDrag;if(!e||e.pid!==t.pointerId)return;t.stopPropagation();const i=this._svgPoint(t),s="partition"===e.kind?e.base.a:e.base.center,n=this._snap([s[0]+i[0]-e.start[0],s[1]+i[1]-e.start[1]]),o=this._clampPhysicalDelta(e.kind,e.base,[n[0]-s[0],n[1]-s[1]]);this._physicalDrag={...e,delta:o,moved:e.moved||Math.hypot(t.clientX-e.startClient[0],t.clientY-e.startClient[1])>=5}}_physicalUp(t){const e=this._physicalDrag;if(!e||e.pid!==t.pointerId)return;if(t.stopPropagation(),this._physicalDrag=null,!e.moved)return void this._registerPhysicalTap(e.kind,e.id);const i=this._spaceModel();if(!this._curSpaceCfg||!i)return;const s=this._curSpaceCfg;if("partition"===e.kind){const t=(s.partitions||[]).find(t=>t.id===e.id),i=e.base;if(t){const n={...i,a:[i.a[0]+e.delta[0],i.a[1]+e.delta[1]],b:[i.b[0]+e.delta[0],i.b[1]+e.delta[1]]};t.a=[n.a[0]/pm,n.a[1]/pm],t.b=[n.b[0]/pm,n.b[1]/pm];for(const t of s.openings||[]){if("partition"!==t.host?.kind||t.host.id!==e.id)continue;const i=Pd(t,[n],pm,this._cellCm,this._gridPitch).resolved;i&&Object.assign(t,zd(t,i,pm))}}}else{const t=(s.wall_columns||[]).find(t=>t.id===e.id),n=e.base,o={...n,center:[n.center[0]+e.delta[0],n.center[1]+e.delta[1]]};if(i.wall_columns.some(t=>t.id!==e.id&&rc(t,o,.02*this._gridPitch)))return void this._showToast(this._t("toast.column_duplicate"));t&&(t.center=[(n.center[0]+e.delta[0])/pm,(n.center[1]+e.delta[1])/pm])}this._recordGeometry(this._t("history.physical_move"),e.before),this._saveConfig()}_registerPhysicalTap(t,e,i){const s=performance.now(),n=this._physicalLastTap?.kind===t&&this._physicalLastTap.id===e&&this._physicalLastTap.segment===i&&s-this._physicalLastTap.at<=360;this._physicalLastTap={kind:t,id:e,segment:i,at:s},n&&(this._physicalLastTap=null,this._openPhysicalDialog(t,e,i))}_cancelPhysicalGesture(){this._physicalDrag=null,this._physicalRotate=null,this.requestUpdate()}_physicalRotateDown(t,e){if("square"!==e.shape||!this._spaceModel())return;t.preventDefault(),t.stopPropagation(),bm(t);const i=this._svgPoint(t);this._physicalSel={kind:"column",id:e.id},this._physicalRotate={pid:t.pointerId,id:e.id,center:[...e.center],startAngle:180*Math.atan2(i[1]-e.center[1],i[0]-e.center[0])/Math.PI,baseAngle:ql(e.angle),angle:ql(e.angle),before:this._geometrySnapshot(),moved:!1}}_physicalRotateMove(t){const e=this._physicalRotate;if(!e||e.pid!==t.pointerId)return;t.preventDefault(),t.stopPropagation();const i=this._svgPoint(t),s=180*Math.atan2(i[1]-e.center[1],i[0]-e.center[0])/Math.PI,n=e.baseAngle+s-e.startAngle,o=ql(t.shiftKey?n:5*Math.round(n/5));this._physicalRotate={...e,angle:o,moved:e.moved||Math.abs(n-e.baseAngle)>=.5}}_physicalRotateUp(t){const e=this._physicalRotate;if(!e||e.pid!==t.pointerId)return;t.preventDefault(),t.stopPropagation(),this._physicalRotate=null;const i=this._spaceModel();if(!e.moved||!this._curSpaceCfg||!i)return;const s=i.wall_columns.find(t=>t.id===e.id);if(!s||"square"!==s.shape)return;const n={...s,angle:e.angle};if(i.wall_columns.some(t=>t.id!==e.id&&rc(t,n,.02*this._gridPitch)))return void this._showToast(this._t("toast.column_duplicate"));const o=this._curSpaceCfg.wall_columns?.find(t=>t.id===e.id);o&&(o.angle=e.angle,this._recordGeometry(this._t("history.physical_edit"),e.before),this._saveConfig())}_rszRooms(){const t=[],e=this._spaceModel();if(!e)return t;for(const i of e.rooms){const e=i.id?hi(i):null;e&&t.push({id:i.id,poly:e})}return t}_rszOpenings(){return this._openingsR.map(t=>({id:t.id,x:t.rx,y:t.ry,length:t.rlen}))}_rszOpts(){return{minDim:this._cmToUnits(30),eps:.05*this._gridPitch}}_rszSnapshot(){return JSON.stringify(this._geometrySnapshot()||{spaceId:this._space,rooms:[],openings:[],walls:[],open_spans:[]})}_rszApplyPreview(t,e){const i=this._rszDrag,s=this._serverCfg?.spaces.find(t=>t.id===this._space);if(!i||!s)return;const n=JSON.parse(i.snap),o={...s,rooms:n.rooms,openings:n.openings,walls:n.walls,open_spans:n.open_spans};Array.isArray(n.open_spans)&&n.open_spans.length||delete o.open_spans;const r=this._spaceH;for(const[e,i]of Object.entries(t)){const t=o.rooms.find(t=>t.id===e);t&&(t.poly=i.map(t=>[t[0]/pm,t[1]/r]),delete t.x,delete t.y,delete t.w,delete t.h)}for(const[t,i]of Object.entries(e)){const e=(o.openings||[]).find(e=>e.id===t);e&&(e.x=i[0]/pm,e.y=i[1]/r)}const a=[],l=[];for(const t of i.changed){const e=i.rooms.find(e=>e.id===t),s=o.rooms.find(e=>e.id===t);if(!e||!s?.poly)continue;const n=s.poly.map(t=>[t[0]*pm,t[1]*r]);if(e.poly.length===n.length)for(let t=0;tt.id===e);if(!s||!s.poly||s.poly.length<3)return null;if(i<0||i>=s.poly.length)return null;const n=[...s.poly[i]],o=[...s.poly[(i+1)%s.poly.length]];return{roomId:e,edge:i,a:n,b:o,n:fr(s.poly,i)}}(s,e,i);n&&(this._rszDrag={kind:"edge",pid:t.pointerId,roomId:e,plan:n,rooms:s,openings:this._rszOpenings(),snap:this._rszSnapshot(),moved:!1,d:0,k:1,changed:[]})}_rszCornerDown(t,e,i,s){"resize"!==this._tool||this._rszDrag||(t.stopPropagation(),t.preventDefault(),bm(t),this._rszDrag={kind:"scale",pid:t.pointerId,roomId:e,fixed:s,span0:Math.hypot(i[0]-s[0],i[1]-s[1])||1,rooms:this._rszRooms(),openings:this._rszOpenings(),snap:this._rszSnapshot(),moved:!1,d:0,k:1,changed:[]})}_rszMove(t){const e=this._rszDrag;if(!e||e.pid!==t.pointerId)return;t.stopPropagation();const i=this._svgPoint(t);if("edge"===e.kind){const t=e.plan,s=(i[0]-t.a[0])*t.n[0]+(i[1]-t.a[1])*t.n[1],n=this._snap([t.a[0]+t.n[0]*s,t.a[1]+t.n[1]*s]);let o=(n[0]-t.a[0])*t.n[0]+(n[1]-t.a[1])*t.n[1];if(o=function(t,e,i,s,n,o){if(!Number.isFinite(s)||Math.abs(s)<1e-9)return 0;const r=Math.sign(s);let a=Math.abs(s);const l=Math.max(n,1e-6);for(let s=0;s<4096&&a>1e-9;s++,a-=l){const s=r*a;if(Dr(t,e,i,s,o))return s}return 0}(e.rooms,e.openings,t,o,this._gridPitch,this._rszOpts()),o===e.d&&e.moved)return;e.d=o,e.moved=!0;const r=Sr(e.rooms,e.openings,t,o,this._rszOpts().eps);e.changed=Object.keys(r.polys),this._rszApplyPreview(r.polys,r.openings),this._rszLive=this._rszEdgeLabels(r,t)}else{const t=e.fixed,s=this._snap(i);let n=Math.hypot(s[0]-t[0],s[1]-t[1])/(e.span0||1);if(n=Math.max(.05,Math.min(20,n)),n=function(t,e,i,s,n,o){if(!Number.isFinite(n)||n<=0)return 1;if(Pr(t,e,i,s,n,o))return n;let r=1,a=n;for(let n=0;n<28;n++){const n=(r+a)/2;Pr(t,e,i,s,n,o)?r=n:a=n}return r}(e.rooms,e.openings,e.roomId,t,n,this._rszOpts()),n===e.k&&e.moved)return;e.k=n,e.moved=!0;const o=e.rooms.find(t=>t.id===e.roomId),r=e.rooms.filter(t=>t.id!==e.roomId).map(t=>t.poly),a=Tr(o,e.openings,r,t,n,2*this._rszOpts().eps);e.changed=[e.roomId],this._rszApplyPreview({[e.roomId]:a.poly},a.openings),this._rszLive=this._rszScaleLabels(a.poly)}this.requestUpdate()}_rszUp(t){const e=this._rszDrag;if(!e||e.pid!==t.pointerId)return;t.stopPropagation();const i=this._rszPreview;this._rszDrag=null,this._rszLive=null,this._rszPreview=null;if(!(e.moved&&("edge"===e.kind?Math.abs(e.d)>1e-9:Math.abs(e.k-1)>1e-9))||!i)return this._cfgEpoch++,void this.requestUpdate();const s=JSON.parse(e.snap),n=this._curSpaceCfg;if(n){n.rooms=i.sp.rooms,n.openings=i.sp.openings,Array.isArray(i.sp.walls)&&(i.sp.walls.length?n.walls=i.sp.walls:delete n.walls),Array.isArray(i.sp.open_spans)&&i.sp.open_spans.length?n.open_spans=i.sp.open_spans:delete n.open_spans;for(const t of e.changed){const e=n.rooms.find(e=>e.id===t);e?.poly&&(e.poly=wr(e.poly,1e-9))}this._commitOpenSpans(),Array.isArray(n.walls)&&n.walls.length&&(n.walls=Ea(n.walls,n.rooms||[],xc,1,this._cfgOpenCuts()),n.walls.length||delete n.walls)}this._suppressClick=!0,setTimeout(()=>this._suppressClick=!1,0),this._recordGeometry(this._t("history.resize_room"),s),this._saveConfig(),this.requestUpdate()}_rszCancelDrag(){this._rszDrag&&(this._rszDrag=null,this._rszLive=null,this._rszPreview=null,this._cfgEpoch++,this.requestUpdate())}_rszPointerCancel(t){const e=this._rszDrag;e&&e.pid===t.pointerId&&(t.stopPropagation(),this._rszCancelDrag())}_rszEdgeLabels(t,e){const i=this._rszDrag,s=[],n=t.polys[e.roomId]||i.rooms.find(t=>t.id===e.roomId).poly,o=n.length,r=e.edge,a=(r+1)%o,l=this._rszInnerSpanCms(e.roomId,n,t.polys);for(const t of[(r-1+o)%o,r,a]){const e=n[t],i=n[(t+1)%o],r=l?.[t];s.push({x:(e[0]+i[0])/2,y:(e[1]+i[1])/2,text:null==r?this._fmtLen(e,i):li(r,"mi"===this.hass?.config?.unit_system?.length)})}const c="mi"===this.hass?.config?.unit_system?.length,h=Object.keys(t.polys).length?Object.keys(t.polys):[e.roomId],d=this._spaceWalls,p=this._openPairs().flatMap(t=>t.segs),u=this._physicalBodiesR();for(const e of h){const n=t.polys[e]||i.rooms.find(t=>t.id===e).poly,o=d.length&&ml(Object.entries(t.polys).map(([t,e])=>({id:t,poly:e})),e,d,p,this._wallKeyPitch,this._cellCm,this._gridPitch,pm)||n,r=$i(o),a=u.length?ic(ec(o,u))*Math.pow(this._cellCm/this._gridPitch,2)/1e4:Rr(o,this._gridPitch,this._cellCm);s.push({x:r[0],y:r[1],text:Ir(a,c),area:!0})}return s}_rszInnerSpanCms(t,e,i){const s=Object.keys(i).length?Object.entries(i).map(([t,e])=>({id:t,poly:e})):this._spaceModel()?.rooms;if(!s?.length)return null;const n=this._spaceWalls;if(!n.length)return null;const o=function(t,e,i,s,n,o,r,a=1){const l=(t||[]).find(t=>t?.id===e),c=hi(l);if(!c||c.length<3)return null;const h=hl(t,e,i,s,n,o,r,a);if(!h)return c.map(()=>0);const d=4*Ka(n,a);return c.map((t,e)=>{const i=c[(e+1)%c.length],s=[(t[0]+i[0])/2,(t[1]+i[1])/2];for(let t=0;tt.segs),this._wallKeyPitch,this._cellCm,this._gridPitch,pm);if(!o||o.length!==e.length)return null;const r=this._cellCm/this._gridPitch;return e.map((t,i)=>function(t,e,i){const s=t?.length||0;if(s<3||!Array.isArray(i)||i.length!==s)return 0;const n=(Math.trunc(e)%s+s)%s,o=t[n],r=t[(n+1)%s],a=r[0]-o[0],l=r[1]-o[1],c=Math.hypot(a,l);if(!(c>0))return 0;const h=Math.max(0,Number(i[n])||0);if(!(h>0))return c;const d=[a/c,l/c],p=Xa(t,n),u=[o[0]+p[0]*h,o[1]+p[1]*h],_=e=>{const n=Math.max(0,Number(i[e])||0);if(!(n>0))return null;const r=t[e],a=t[(e+1)%s],l=a[0]-r[0],c=a[1]-r[1],h=Math.hypot(l,c);if(!(h>0))return null;const p=Xa(t,e),_=Za(u,d,[r[0]+p[0]*n,r[1]+p[1]*n],[l/h,c/h]);return _?(_[0]-o[0])*d[0]+(_[1]-o[1])*d[1]:null},g=_((n-1+s)%s)??0,m=(_((n+1)%s)??c)-g;return m>0?m:0}(e,i,o)*r)}_rszScaleLabels(t){const e="mi"===this.hass?.config?.unit_system?.length,i=t.map(t=>t[0]),s=t.map(t=>t[1]),n=this._spaceWalls,o=n.length&&this._rszSel&&ml([{id:this._rszSel,poly:t}],this._rszSel,n,[],this._wallKeyPitch,this._cellCm,this._gridPitch,pm)||t,r=$i(o),a=this._physicalBodiesR(),l=a.length?ic(ec(o,a))*Math.pow(this._cellCm/this._gridPitch,2)/1e4:Rr(o,this._gridPitch,this._cellCm),c=o.map(t=>t[0]),h=o.map(t=>t[1]),d=Math.max(...c)-Math.min(...c),p=Math.max(...h)-Math.min(...h);return[{x:Math.min(...i),y:Math.min(...s),text:`${this._fmtLen([0,0],[d,0])} × ${this._fmtLen([0,0],[p,0])}`},{x:r[0],y:r[1],text:Ir(l,e),area:!0}]}_renderResizeLayer(t){const e=Math.max(.013*t.w,5),i=e/2,s=t=>t.toFixed(1),n=`M ${s(-.7*i)} 0 H ${s(.7*i)} M 0 ${s(-.22*i)} V ${s(-i)} M ${s(-.32*i)} ${s(-.6*i)} L 0 ${s(-i)} L ${s(.32*i)} ${s(-.6*i)} M 0 ${s(.22*i)} V ${s(i)} M ${s(-.32*i)} ${s(.6*i)} L 0 ${s(i)} L ${s(.32*i)} ${s(.6*i)}`,o=[],r=this._rszRooms();for(const t of r)for(let i=0;i + `}_stageAspect(){const t=this._stageEl,e=this._baseVb();return t&&t.clientHeight?t.clientWidth/t.clientHeight:e[2]/e[3]}_viewOr(t){return this._view&&this._view.w?this._view:Oi(t,this._stageAspect())}_roomLabelReferenceViewWidth(t){if(!this._markup)return t.w;const e=this._stageEl,i=this.renderRoot.querySelector(".editorchrome");if(!e||e.clientWidth<=0||e.clientHeight<=0)return t.w;const s=e.clientHeight+(i?.getBoundingClientRect().height||0);return s<=0?t.w:this._viewForModeTarget(this._zoom,void 0,void 0,e.clientWidth,s).w}_screenToVb(t,e){const i=this._stageEl,s=this._viewOr(this._baseVb()),n=i?.clientWidth||1,o=i?.clientHeight||1;return[s.x+t/n*s.w,s.y+e/o*s.h]}_clampView(t,e){const i=(t,e,i,s)=>{const n=1*Math.max(e,s),o=i-n,a=i+s-e+n;return Math.max(Math.min(o,a),Math.min(Math.max(o,a),t))};return{w:t.w,h:t.h,x:i(t.x,t.w,e.x,e.w),y:i(t.y,t.h,e.y,e.h)}}_applyView(t,e,i){const s=this._baseVb(),n=Oi(s,this._stageAspect()),o=Math.min(km.ZOOM_MAX,Math.max(km.ZOOM_MIN,t)),a=n.w/o,r=n.h/o,l=this._viewOr(s),c=e??l.x+l.w/2,h=i??l.y+l.h/2,d=this._clampView({x:c-a/2,y:h-r/2,w:a,h:r},n);return!(this._view&&Math.abs(this._zoom-o)<1e-9&&Math.abs(this._view.x-d.x)<1e-6&&Math.abs(this._view.y-d.y)<1e-6&&Math.abs(this._view.w-d.w)<1e-6&&Math.abs(this._view.h-d.h)<1e-6)&&("opening"===this._tool&&(this._cursorPt=null,this._clearOpeningPlacement(!1)),this._zoom=o,this._view=d,!0)}_bootWatch(){clearTimeout(this._bootTimer),this._bootStart=Date.now(),this._bootLastH=-1,this._bootLastChange=this._bootStart;const t=()=>{if(!this._booting)return;const e=Date.now(),i=this._stageEl?this._stageEl.clientHeight:0;i!==this._bootLastH&&(this._bootLastH=i,this._bootLastChange=e);const s=e-this._bootStart;s>=1200||s>=700&&i>0&&e-this._bootLastChange>=250?this._bootSettled():this._bootTimer=window.setTimeout(t,100)};this._bootTimer=window.setTimeout(t,100)}_bootSettled(){this._booting&&!this._bootSettling&&(this._bootSettling=!0,this._refitView(),this._bootSettleRaf=requestAnimationFrame(()=>{this._bootSettleRaf=0,this._finishBootSettled()}))}_finishBootSettled(){if(!this._booting)return;this._refitView(),this._booting=!1,this._bootSettling=!1;const t=this._stageEl?.clientHeight??0;!this._config?.kiosk&&t>0&&this._warmPatch({hdrH:this._hdrH,stageH:t,vp:this._warmViewportState()},!0),this._bootFading=!0,this._bootTimer=window.setTimeout(()=>{this._bootFading=!1},220),this._bootSoft=!0,clearTimeout(this._bootSoftTimer),this._bootSoftTimer=window.setTimeout(()=>{this._bootSoft=!1},Zg)}_bootSoftCancel(){this._bootSoft&&(clearTimeout(this._bootSoftTimer),this._bootSoft=!1)}_beginResumeSettle(){this._booting||this._resumeSettling||(this._modeTransitionPreparing?this._modeTransitionForceAtomic=!0:this._cancelModeTransition(!0),this._viewportInvalidAt=0,this._beginContinuityCandidate("warm-resume",!1),this._loading?this.requestUpdate():this._loadFromServer())}_refitView(){if(this._modeTransitionBusy)return;const t=this._stageEl;if(!t||"visible"!==document.visibilityState||t.clientWidth<=0||t.clientHeight<=0)return void(this._viewportInvalidAt||(this._viewportInvalidAt=Date.now()));const e=[t.clientWidth,t.clientHeight],i=this._lastValidStageSize,s=!!i&&Math.abs(i[0]-e[0])<=.5&&Math.abs(i[1]-e[1])<=.5,n=this._viewportInvalidAt?Date.now()-this._viewportInvalidAt:0;if(this._viewportInvalidAt=0,!i)return this._lastValidStageSize=e,void(this._view||this._applyView(this._zoom));s?this._pendingRefitSize=null:(this._pendingRefitSize=e,this._refitRaf||(this._refitRaf=requestAnimationFrame(()=>{this._refitRaf=0;const t=this._pendingRefitSize;this._pendingRefitSize=null;const e=this._stageEl;if(!t||!e||e.clientWidth<=0||e.clientHeight<=0)return;if(Math.abs(e.clientWidth-t[0])>.5||Math.abs(e.clientHeight-t[1])>.5)return void this._refitView();const i=this._lastValidStageSize;if(i&&Math.abs(i[0]-t[0])<=.5&&Math.abs(i[1]-t[1])<=.5)return;this._lastValidStageSize=t;const s=this._view;n>=kh?this._beginContinuityCandidate("stage-size-restored",!0,"stage-size"):this._continuity.hasCompleteFrame&&this._beginContinuityCandidate("stage-resize",!0,"stage-size"),this._applyView(this._zoom,s?s.x+s.w/2:void 0,s?s.y+s.h/2:void 0)})))}_zoomAt(t,e,i){const s=this._stageEl;if(!s)return;const n=Oi(this._baseVb(),this._stageAspect()),o=Math.min(km.ZOOM_MAX,Math.max(km.ZOOM_MIN,i));"opening"===this._tool&&(this._cursorPt=null,this._clearOpeningPlacement(!1));const a=s.clientWidth,r=s.clientHeight,l=this._screenToVb(t,e),c=n.w/o,h=n.h/o;this._zoom=o,this._view=this._clampView({x:l[0]-t/a*c,y:l[1]-e/r*h,w:c,h:h},n)}_onWheel(t){const e=this._stageEl;if(!e)return;t.preventDefault();const i=e.getBoundingClientRect(),s=t.deltaY<0?1.15:1/1.15;this._zoomAt(t.clientX-i.left,t.clientY-i.top,this._zoom*s),this._saveZoom()}_stepZoom(t){const e=this._stageEl;e&&(this._zoomAt(e.clientWidth/2,e.clientHeight/2,this._zoom*(t>0?1.4:1/1.4)),this._saveZoom())}_resetZoom(){const t=this._baseVb();"opening"===this._tool&&(this._cursorPt=null,this._clearOpeningPlacement(!1)),this._zoom=1,this._view=Oi(t,this._stageAspect()),this._saveZoom()}_saveZoom(){if("view"===this._mode){this._zoomBySpace={...this._zoomBySpace,[this._space]:this._zoom};try{localStorage.setItem(lm,JSON.stringify(this._zoomBySpace))}catch{}}}_restoreZoom(){const t=this._zoomBySpace[this._space]||1;this._zoom=t;const e=this._stageEl;if(e&&e.clientHeight){const e=this._baseVb();return this._applyView(t,e[0]+e[2]/2,e[1]+e[3]/2),void this.requestUpdate()}this._view=null,requestAnimationFrame(()=>{if(!this._stageEl)return;const e=this._baseVb();this._applyView(t,e[0]+e[2]/2,e[1]+e[3]/2),this.requestUpdate()})}_stagePointerDown(t){if(this._vacFit)return;if(this._kiosk&&(this._cyclePausedUntil=Date.now()+6e4,0===this._pointers.size?(this._swipeStart={x:t.clientX,y:t.clientY,id:t.pointerId},t.target.closest?.(".dev, .roomlabel, .oplock")||(clearTimeout(this._kioskHoldTimer),this._kioskHoldTimer=window.setTimeout(()=>{this._kioskDialog=!0,this._swipeStart=null},3e3))):(this._swipeStart=null,clearTimeout(this._kioskHoldTimer))),this._drag)return;if(this._markup&&t.target.closest?.(".roomlabel, .rlhandle, .rszhandle, .dev, .oplock, .op-hit, button"))return;if("devices"===this._mode&&t.target.closest(".dev"))return;if("decor"===this._mode&&this._decorPointerDown(t))return;this._pointers.set(t.pointerId,{x:t.clientX,y:t.clientY});const e=this._viewOr(this._baseVb());if(1===this._pointers.size)this._panStart={sx:t.clientX,sy:t.clientY,vx:e.x,vy:e.y},this._panLock=null,this._suppressClick=!1;else if(2===this._pointers.size){this._cancelBoundaryAnchor(),"opening"===this._tool?(this._cursorPt=null,this._clearOpeningPlacement(!1)):"draw"===this._tool&&this._clearPlanSnapHover();const t=[...this._pointers.values()],e=Math.hypot(t[0].x-t[1].x,t[0].y-t[1].y);this._pinchStart={dist:e,zoom:this._zoom},this._panStart=null,this._panLock=null}}get _swipeZone(){return!this._hasFixedFloor&&this._kiosk&&this._zoom<=1.001&&this._model.length>1}_stagePointerMove(t){if(this._physicalRotate?.pid!==t.pointerId)if(this._physicalDrag?.pid!==t.pointerId)if(this._dtDrag?.pid!==t.pointerId)if(this._bdDrag?.pid!==t.pointerId){if(this._decorDraft?.pid===t.pointerId){const e=this._decorDraft;let i=this._decorSnap(this._svgPoint(t),t.pointerType);if(t.shiftKey&&("rect"===e.kind||"ellipse"===e.kind)){const t=i[0]-e.a[0],s=i[1]-e.a[1],n=Math.max(Math.abs(t),Math.abs(s));i=this._snap([e.a[0]+(t<0?-n:n),e.a[1]+(s<0?-n:n)])}return void(this._decorDraft={...e,b:i})}if(this._decorMove?.pid!==t.pointerId)if(this._pointers.has(t.pointerId)){if(this._pointers.set(t.pointerId,{x:t.clientX,y:t.clientY}),this._markup&&1===this._pointers.size&&this._markupMove(t),this._pinchStart&&this._pointers.size>=2){"opening"===this._tool?(this._cursorPt=null,this._clearOpeningPlacement(!1)):"draw"===this._tool&&this._clearPlanSnapHover();const t=[...this._pointers.values()],e=Math.hypot(t[0].x-t[1].x,t[0].y-t[1].y)/(this._pinchStart.dist||1),i=this._stageEl.getBoundingClientRect(),s=(t[0].x+t[1].x)/2-i.left,n=(t[0].y+t[1].y)/2-i.top;this._zoomAt(s,n,this._pinchStart.zoom*e),this._suppressClick=!0,this._saveZoom()}else if(this._panStart){const e=t.clientX-this._panStart.sx,i=t.clientY-this._panStart.sy;Math.abs(e)+Math.abs(i)>4&&(this._suppressClick=!0,clearTimeout(this._holdTimer),"opening"===this._tool?(this._cursorPt=null,this._clearOpeningPlacement(!1)):"draw"===this._tool&&this._clearPlanSnapHover()),null===this._panLock&&Math.abs(e)+Math.abs(i)>8&&(this._panLock=this._swipeZone&&Math.abs(e)>1.5*Math.abs(i)?"swipe":"pan");const s=this._stageEl;if("pan"===this._panLock&&s){const t=this._baseVb(),n=this._viewOr(t),o=Oi(t,this._stageAspect());this._view=this._clampView({x:this._panStart.vx-e/(s.clientWidth||1)*n.w,y:this._panStart.vy-i/(s.clientHeight||1)*n.h,w:n.w,h:n.h},o)}}}else this._markupMove(t);else this._decorMoveUpdate(t)}else this._bdMove(t);else this._dtMove(t);else this._physicalMove(t);else this._physicalRotateMove(t)}_stagePointerLeave(t){this._markup&&("opening"===this._tool?(this._cursorPt=null,this._clearOpeningPlacement(!1)):"draw"===this._tool&&this._clearPlanSnapHover())}_stagePointerUp(t){if(this._kiosk){clearTimeout(this._kioskHoldTimer);const e=this._swipeStart;if(this._swipeStart=null,e&&e.id===t.pointerId){const i=t.clientX-e.x,s=t.clientY-e.y;if(Math.abs(i)+Math.abs(s)<8){const t=Date.now();t-this._lastTap<350&&this._resetZoom(),this._lastTap=t}const n="pan"===this._panLock?null:function(t,e,i,s,n,o=60){if(i>1.001||s.length<2)return null;if(Math.abs(t)t.id),this._space);n&&this._slideTo(n,i<0?"left":"right")&&(this._saveNav(),this._suppressClick=!0,setTimeout(()=>this._suppressClick=!1,0),this._showKioskDots())}}if(this._physicalDrag?.pid===t.pointerId)return void this._physicalUp(t);if(this._physicalRotate?.pid===t.pointerId)return void this._physicalRotateUp(t);if(this._dtDrag?.pid===t.pointerId)return void this._dtUp();if(this._bdDrag?.pid===t.pointerId)return void this._bdUp();if(this._decorDraft?.pid===t.pointerId)return void this._decorCommitDraft();if(this._decorMove?.pid===t.pointerId)return this._decorMove.moved&&(this._recordGeometry(this._t("history.decor_move"),this._decorMove.before),this._saveConfig()),void(this._decorMove=null);const e=!!this._pinchStart||!!this._panStart;this._pointers.delete(t.pointerId),this._pointers.size<2&&(this._pinchStart=null),0===this._pointers.size&&(this._panStart=null,this._panLock=null,setTimeout(()=>this._suppressClick=!1,0)),e&&0===this._pointers.size&&this.requestUpdate()}_clickRoom(t){!this._suppressClick&&t.area&&ym("/config/areas/area/"+t.area)}_pointerDown(t,e){if("plan"===this._mode)return;if("view"===this._mode){this._holdFired=!1,clearTimeout(this._holdTimer);const i=t.pointerId,s=t.currentTarget;return void(this._holdTimer=window.setTimeout(()=>{this._holdFired=!0,this._interruptViewGesture(i,s),this._infoCard=e},600))}if("ha_disabled"===e.bindingStatus?.kind)return;t.preventDefault();const i=this._pos(e);this._drag={id:e.id,sx:t.clientX,sy:t.clientY,ox:i.x,oy:i.y,moved:!1},wm(t),this._tip=null}_pointerMove(t,e){if(!this._drag||this._drag.id!==e.id)return;const i=this.renderRoot.querySelector(".stage");if(!i)return;const s=this._baseVb(),n=i.getBoundingClientRect(),o=this._viewOr(s),a=(t.clientX-this._drag.sx)/n.width*o.w,r=(t.clientY-this._drag.sy)/n.height*o.h;Math.abs(t.clientX-this._drag.sx)+Math.abs(t.clientY-this._drag.sy)>3&&(this._drag.moved=!0,clearTimeout(this._holdTimer));const l=Cc(this._drag.ox+a),c=Cc(this._drag.oy+r);this._savePos(e,l,c)}_pointerUp(t,e){if(clearTimeout(this._holdTimer),!this._drag||this._drag.id!==e.id)return;const i=this._drag.moved;this._drag=i?this._drag:null,i&&(this._selId=e.id,window.setTimeout(()=>this._drag=null,0))}_showToast(t){for(const t of this.renderRoot.querySelectorAll("hp-dialog"))t.closeTransientOverlays("toast");this._toast=t,clearTimeout(this._toastTimer),this._toastTimer=window.setTimeout(()=>{this._toast=""},3500)}_syncPointerHoverTargets(){const t=this._pointerModality.hoverEnabled;for(const e of this.renderRoot.querySelectorAll(pm))e.toggleAttribute("data-pointer-hover",t)}_syncPointerHoverSubtree(t){if(t.nodeType!==Node.ELEMENT_NODE)return;const e=t,i=this._pointerModality.hoverEnabled;e.matches(pm)&&e.toggleAttribute("data-pointer-hover",i);for(const t of e.querySelectorAll(pm))t.toggleAttribute("data-pointer-hover",i)}_clearTransientHover(t=!1){t&&this._pointerModality.suspend(),this._tip&&(this._tip=null),this._hoverRoom&&(this._hoverRoom=null)}_notePointer(t){this._boundaryPointerType=t.pointerType||"mouse";const e=this._pointerModality.modality,i=this._pointerModality.note(t);"touch"!==i&&"pen"!==i||e===i&&!this._tip&&!this._hoverRoom||this._clearTransientHover()}_guardTouchGesture(t){if(this._editorSecondary.handleOutsideDismiss(t))return;if("click"===t.type){if(!this._suppressClick&&!this._touchSequenceMultitouch&&Date.now()>this._touchClickBlockUntil)return;return t.preventDefault(),void t.stopImmediatePropagation()}const e=t;if(this._notePointer(e),"touch"===e.pointerType)if("pointerdown"!==t.type){if("pointermove"===t.type){const t=this._touchContacts.get(e.pointerId);if(!t)return;const i={...t,x:e.clientX,y:e.clientY};if(this._touchContacts.set(e.pointerId,i),this._touchSequenceMultitouch&&"view"===this._mode&&!this._vacFit&&this._pinchStart&&[...this._touchContacts.values()].every(t=>t.inStage)){this._pointers.set(e.pointerId,{x:e.clientX,y:e.clientY});const t=[...this._touchContacts.values()];if(t.length>=2&&this._stageEl){const[e,i]=t,s=Math.hypot(e.x-i.x,e.y-i.y)/(this._pinchStart.dist||1),n=this._stageEl.getBoundingClientRect();this._zoomAt((e.x+i.x)/2-n.left,(e.y+i.y)/2-n.top,this._pinchStart.zoom*s),this._saveZoom()}}return}if("pointerup"===t.type||"pointercancel"===t.type||"lostpointercapture"===t.type){if(this._clearTransientHover(),this._touchContacts.delete(e.pointerId),this._touchSequenceMultitouch){if(this._touchClickBlockUntil=Date.now()+500,this._pointers.delete(e.pointerId),!this._vacFit&&this._pointers.size>=2){const[t,e]=[...this._pointers.values()];this._pinchStart={dist:Math.hypot(t.x-e.x,t.y-e.y),zoom:this._zoom}}else this._pinchStart=null;0===this._pointers.size&&(this._panStart=null,this._panLock=null)}0===this._touchContacts.size&&(this._touchSequenceMultitouch=!1)}}else if(this._touchContacts.set(e.pointerId,{x:e.clientX,y:e.clientY,inStage:!!e.target?.closest?.(".stage")}),this._touchContacts.size>=2){this._clearTransientHover(),this._touchSequenceMultitouch=!0,this._touchClickBlockUntil=Number.POSITIVE_INFINITY,clearTimeout(this._holdTimer),clearTimeout(this._kioskHoldTimer),this._swipeStart=null;const t=[...this._touchContacts.values()];if("view"===this._mode&&!this._vacFit&&t.every(t=>t.inStage)){this._pointers=new Map([...this._touchContacts].map(([t,e])=>[t,{x:e.x,y:e.y}]));const[e,i]=t;this._pinchStart={dist:Math.hypot(e.x-i.x,e.y-i.y),zoom:this._zoom},this._panStart=null,this._panLock=null}else this._vacFit&&(this._pointers.clear(),this._pinchStart=null,this._panStart=null,this._panLock=null)}}_showTip(t,e,i,s,n,o){this._notePointer(t),this._pointerModality.hoverEnabled&&(this._drag||(this._tip={x:t.clientX,y:t.clientY,title:e,meta:i,lqi:s,temp:n,hum:o}))}get _gridPitch(){return xc}get _cellCm(){const t=Number(this._curSpaceCfg?.cell_cm);return Number.isFinite(t)&&t>0?t:5}_fmtLen(t,e){const i=function(t,e,i,s){return Math.hypot(e[0]-t[0],e[1]-t[1])/i*s}(t,e,this._gridPitch,this._cellCm);return li(i,"mi"===this.hass?.config?.unit_system?.length)}get _curSpaceCfg(){const t=this._rszPreview;return t&&t.space===this._space?t.sp:this._serverCfg?.spaces.find(t=>t.id===this._space)}get _renderCfg(){const t=this._rszPreview;return t&&this._serverCfg?{...this._serverCfg,spaces:this._serverCfg.spaces.map(e=>e.id===t.space?t.sp:e)}:this._serverCfg}get _spaceH(){return this._curSpaceCfg,um}get _segments(){const t=this._curSpaceCfg,e=this._spaceH;return pi(t?.rooms||[]).map(t=>[t[0]*um,t[1]*e,t[2]*um,t[3]*e])}_savedNav(){if(this._hasFixedFloor)return null;try{return JSON.parse(localStorage.getItem(cm)||"null")}catch{return null}}_saveNav(){if(!this._hasFixedFloor)try{localStorage.setItem(cm,JSON.stringify({space:this._space}))}catch{}}_leaveCardRoute(){if(this._routeDepartureHandled)return;this._routeDepartureHandled=!0,"view"!==this._mode&&this._setMode("view",!1),this._pendingNavMode=null,this._geometryHistory.clear(),this._activeDraftId=null,this._resumeDraftBySpace={},this._draftSegmentCms=[],this._closingWallCm=null,this._drawWallField=null,this._showHidden=!1,this._tapConfirm=null,this._vacCalConfirm=null,this._decorEraseConfirm=null,this._openingInfo=null,this._closeInfoCard(),this._rulesDialog=null,this._alignDialog=null,this._backupImportDialog=null,this._backupExportDialog=null,this._settingsDialog=null,this._markerDialog=null,this._openingDialog=null,this._physicalDialog=null,this._wallDialog=null,this._backdropDialog=null,this._decorShapeDialog=null,this._decorTextDialog=null,this._mergeDialog=null,this._roomDialog=!1,this._spaceDialog=null,this._importDialog=null;const t=this._warmSlot;t?.owner===this._warmGen&&(t.vp=this._warmViewportState(),t.dlg=null,t.frameFingerprint="",clearTimeout(t.evict),t.evict=0),this._saveNav()}_setMode(t,e=!0){this._endTabDrag(),this._pendingNavMode=null;const i=this._spaceModel();if(!i)return this._cancelModeTransition(!1),void(this._mode="view");if(this._kiosk&&"view"!==t)return;if(this._mode===t){if(!e&&"view"===t&&this._modeTransitionBusy){const e=this._currentModeVisual(t),i=this._modeTransitionTargetZoom,s=this._modeTransitionTargetCenterX,n=this._modeTransitionTargetCenterY;this._cancelModeTransition(!1),this._commitViewModeAtomic(e,i,s,n)}return}if(this._bootSoftCancel(),("plan"===t||"decor"===t)&&!this._norm)return void this._showToast(this._t("toast.markup_needs_server"));if(this._wallFaceBatch&&this._roomDialogCancel(),"plan"===this._mode&&"draw"===this._tool&&!this._finishWallChain())return;this._clearTransientHover(!0),this._cancelDevicePressFeedback();const s=this._mode,n=this._effectiveProjection(),o=this._currentModeVisual(s),a=this._modeTransitionBusy,r=o&&"view"!==s&&"view"!==t?{...o,toolbarContentOpacity:this._reducedMotion?1:.35}:o;this._cancelModeTransition(!1),this._editorSecondary.closeForNavigation(),(this._decorMove||this._dtDrag||this._bdDrag)&&this._cancelDecorGesture();const l=!i.bg&&"view"===t!=("view"===s),c=a&&"view"===s&&"view"!==t?this._modeTransitionEditorCamera:null;let h=c?.zoom??(a?this._modeTransitionTargetZoom:this._zoom),d=c?c.centerX:a?this._modeTransitionTargetCenterX:r?.viewport.centerX,p=c?c.centerY:a?this._modeTransitionTargetCenterY:r?.viewport.centerY;if("view"===s&&"view"!==t&&!a){const e=this._view;if(this._viewModeSnap={space:this._space,zoom:this._zoom,cx:e?this._logicalViewCenter(n)?.x:void 0,cy:e?this._logicalViewCenter(n)?.y:void 0},"iso"===n){const e=this._logicalViewCenter("iso");d=e?.x,p=e?.y,this._view=null,this._mode=t,this._applyView(this._zoom,e?.x,e?.y)}l&&(h=1,d=void 0,p=void 0)}if("plan"===s&&this._activeDraftId&&(this._resumeDraftBySpace[this._space]=this._activeDraftId),this._mode=t,this._editorChromeMode="view"===t?s:t,"view"===t){"view"===s||a||(this._modeTransitionEditorCamera={zoom:this._zoom,centerX:r?.viewport.centerX,centerY:r?.viewport.centerY});const t=this._viewModeSnap;if(t&&t.space===this._space){h=t.zoom;const e=this._labsIso&&"iso"===this._viewPreference[this._space]?"iso":"flat",i=null!=t.cx&&null!=t.cy&&"iso"===e?lg([t.cx,t.cy],0):null;d=i?.[0]??t.cx,p=i?.[1]??t.cy}else t&&(h=this._zoomBySpace[this._space]||1,d=void 0,p=void 0)}else this._modeTransitionEditorCamera={zoom:h,centerX:d,centerY:p};this._modeTransitionTargetZoom=h,this._modeTransitionTargetCenterX=d,this._modeTransitionTargetCenterY=p,("iso"===n||"view"===t&&this._labsIso&&"iso"===this._viewPreference[this._space])&&(this._modeTransitionForceAtomic=!0);const u=++this._modeTransitionRequest;e?r?(this._modeTransitionPreparing=!0,this._modeTransitionVisual=r,this._prepareModeTransition(u,r,t,h,d,p)):(this._modeTransitionPreparing=!1,this._modeTransitionVisual=null,this._zoom=h,this._view=null,requestAnimationFrame(()=>{this.isConnected&&u===this._modeTransitionRequest&&this._mode===t&&(this._applyView(h,d,p),"view"===t&&(this._viewModeSnap=null,this._modeTransitionEditorCamera=null),this.requestUpdate())})):"view"===t&&this._commitViewModeAtomic(r,h,d,p),this._path=[],this._clearPlanSnapHover(),this._clearOpeningPlacement(!0),this._openWallAnchor=null,this._boundaryRestoreGuard=null,this._tool="draw",this._mergeSel=null,this._mergeDialog=null,this._splitSel=null,this._pendingSplit=null,this._selId=null,this._physicalSel=null,this._physicalDialog=null,this._physicalDrag=null,this._rszSel=null,this._rszDrag=null,this._rszLive=null,this._rszPreview=null,this._tip=null,this._hoverRoom=null,this._decorDraft=null,this._decorSel=null,this._decorMove=null,this._backdropDialog=null,this._decorTool="select",this._bdDrag=null,this._dtDrag=null,this._dtBox=null,"plan"===t&&(this._primeDrawWallField(),this._resumeLastDraft()),this._saveNav()}_primeDrawWallField(){null===this._drawWallField&&(this._drawWallField=kr(fr,this._imperial))}get _drawWallFieldValue(){return null===this._drawWallField?kr(fr,this._imperial):this._drawWallField}get _drawWallCm(){const t=Qg(this._drawWallFieldValue);if(null==t||t<=0)return null;const e=this._imperial?2.54*t:t,i="column"===this._tool?Ll:100;return e>=1&&e<=i?e:null}get _drawWallMaxCm(){return"column"===this._tool?Ll:100}_showPhysicalRange(t=this._drawWallMaxCm){this._showToast(this._t("toast.physical_range",{max:kr(t,this._imperial),unit:this._t(this._imperial?"wallthick.unit_in":"wallthick.unit_cm")}))}_draftSegmentCount(t=this._curSpaceCfg){return(t?.room_drafts||[]).reduce((t,e)=>t+(Array.isArray(e.segments)?e.segments.length:0),0)}_mergeSpacePartitions(t,e){const i=t?.partitions||[];if(i.length<2)return 0;const s=a_(i,{pitch:$c,seedIds:e,geometry:l_(t,{excludeDraftId:this._activeDraftId})});return s.merged?(t.partitions=s.partitions,r_(t.openings,t.partitions,s.openingMoves,{coordScale:um,cellCm:this._cellCm,gridPitch:this._gridPitch}),s.merged):0}_finishWallChain(){if("draw"!==this._tool||this._wallFaceBatch||this._roomDialog)return!0;const t=this._curSpaceCfg;if(!t||this._path.length<2)return this._path=[],this._activeDraftId=null,this._draftSegmentCms=[],this._closingWallCm=null,this._clearPlanSnapHover(),!0;const e=ep(this._path,tp(this._path.length-1,this._draftSegmentCms,this._drawWallCm,fr)),i=e.length;if((t.partitions||[]).length+i>fm)return this._showToast(this._t("toast.physical_limit")),!1;const s=this._geometrySnapshot();t.partitions||=[];const n=Date.now().toString(36),o=[];for(let s=0;st.id!==this._activeDraftId),t.room_drafts.length||delete t.room_drafts),this._recordGeometry(this._t("history.wall_chain_finish"),s),this._saveConfig(),delete this._resumeDraftBySpace[this._space],this._path=[],this._activeDraftId=null,this._draftSegmentCms=[],this._closingWallCm=null,this._clearPlanSnapHover(),!0}_activateMarkupTool(t){t!==this._tool&&(this._wallFaceBatch&&this._roomDialogCancel(),("draw"!==this._tool||this._finishWallChain())&&(this._cancelPath(),this._tool=t,"draw"===t&&this._resumeLastDraft(),"resize"===t&&(this._rszSel=null),"boundary"!==t&&"wallthick"!==t||(this._wallDialog=null)))}_limitReached(t){const e=this._curSpaceCfg;if(!e)return!0;const i="draft"===t?(e.room_drafts||[]).length>=200:"partition"===t?(e.partitions||[]).length>=fm:(e.wall_columns||[]).length>=500;return i&&this._showToast(this._t("toast.physical_limit")),i}_svgPoint(t){const e=this.renderRoot.querySelector(".stage").getBoundingClientRect();return this._screenToVb(t.clientX-e.left,t.clientY-e.top)}_snap(t){const e=this._gridPitch;return[Cc(ri(t[0],e)),Cc(ri(t[1],e))]}_snapDrawPoint(t,e=!1){const i=this._path[this._path.length-1],s=e&&i?function(t,e,i,s=1/0){if(!(i>0&&t?.every(Number.isFinite)&&e?.every(Number.isFinite)))return[e[0],e[1]];const n=e[0]-t[0],o=e[1]-t[1];if(Math.abs(n)+Math.abs(o)<=1e-12)return[t[0],t[1]];const a=Math.PI/4;let r=Math.atan2(o,n);r<0&&(r+=2*Math.PI);const l=Math.floor(r/a+.5)%8,[c,h]=[[1,0],[1,1],[0,1],[-1,1],[-1,0],[-1,-1],[0,-1],[1,-1]][l],d=c*c+h*h;let p=Math.max(0,Math.round((n*c+o*h)/(i*d)));if(Number.isFinite(s)&&s>=0){const e=(t,e)=>{if(!e)return 1/0;const n=e>0?s-t:t+s;return Math.max(0,Math.floor((n+1e-9*i)/i))};p=Math.min(p,e(t[0],c),e(t[1],h))}return[t[0]+c*p*i,t[1]+h*p*i]}(i,t,this._gridPitch,wc):t;return this._snap(s)}_planSnapOpeningCuts(t,e){if(!this._openingsR.length)return[];const i=this._openingWallIndexFor(t,e).value,s=[];for(const e of this._roomWallOpeningInputs(this._openingsR,t)){const t=El(i,e);if(!t.negative&&!t.positive)continue;const n=e.angle*Math.PI/180,o=Math.cos(n)*e.length/2,a=Math.sin(n)*e.length/2;s.push([e.x-o,e.y-a,e.x+o,e.y+a])}return s}_planSnapGeometrySnapshot(){const t=this._spaceModel();if(!t)return{key:`${this._space}|empty`,value:{segments:[],endpoints:[]}};const e=[this._space,this._cfgEpoch,this._activeDraftId||"",t.rooms.length,t.room_drafts.length,t.partitions.length].join("|");if(this._planSnapGeometryCache?.key===e)return this._planSnapGeometryCache;const i=this._openCuts(),s=Gd({space:t,activeDraftId:this._activeDraftId,roomCuts:[...i,...this._planSnapOpeningCuts(t,i)],partitionCuts:this._partitionOpeningCuts(t),epsilon:2e-4*this._gridPitch});return this._planSnapGeometryCache={key:e,value:s},this._planSnapGeometryCache}_planStructuralGeometrySnapshot(){const t=this._spaceModel();if(!t)return{key:`${this._space}|structural-empty`,value:{segments:[],endpoints:[]}};const e=["structural",this._space,this._cfgEpoch,this._activeDraftId||"",t.rooms.length,t.room_drafts.length,t.partitions.length].join("|");if(this._planStructuralGeometryCache?.key===e)return this._planStructuralGeometryCache;const i=Gd({space:t,activeDraftId:this._activeDraftId,roomCuts:this._openCuts(),epsilon:2e-4*this._gridPitch});return this._planStructuralGeometryCache={key:e,value:i},this._planStructuralGeometryCache}_planSnapContextKey(t){const e=this._path[0],i=this._path[this._path.length-1];return[t,this._tool,this._path.length,e?`${e[0]},${e[1]}`:"",i?`${i[0]},${i[1]}`:""].join("|")}_resolvePlanDrawPoint(t,e){const i=this._planSnapGeometrySnapshot(),s=this._path[this._path.length-1],n="draw"===this._tool&&this._path.length>=3?[{point:this._path[0],key:"closure:first-point"}]:[],o={tolerance:this._cssPxToRender(12),distinguishTolerance:this._cssPxToRender(8),gridStep:this._gridPitch,excludePoints:s?[s]:[],extraEndpoints:n,epsilon:2e-4*this._gridPitch},a=e&&s?Zd(i.value,t,{...o,anchor:s}):function(t,e,i){if(!(Hd(e)&&i.tolerance>=0))return{kind:"none",candidate:null,conflicts:[]};const s=i.epsilon??Nd,n=i.excludePoints||[],o=Xd(Yd(t,e,i),i.distinguishTolerance||0);if(o)return o;let a=null;for(const o of t.segments){const t=[o.a[0],o.a[1],o.b[0],o.b[1]],r=Hs([e[0],e[1]],t);if(r>i.tolerance)continue;const l=Jd(o,e,i.gridStep);!Vd(l,n,s)&&Kd(r,o.key,a)&&(a={kind:"line",point:l,key:o.key,distance:r,segment:o})}return a?{kind:"resolved",candidate:a,conflicts:[]}:{kind:"none",candidate:null,conflicts:[]}}(i.value,t,o),r="resolved"===a.kind?a.candidate:null;return{point:r?[...r.point]:this._snapDrawPoint(t,e),candidate:r,conflicts:"ambiguous"===a.kind?a.conflicts:[],ambiguous:"ambiguous"===a.kind,contextKey:this._planSnapContextKey(i.key)}}get _activePlanSnapCandidate(){if(!this._markup||"draw"!==this._tool)return null;const t=this._planSnapHover;if(!t)return null;const e=this._planSnapGeometrySnapshot();return t.contextKey===this._planSnapContextKey(e.key)?t.candidate:null}get _activePlanSnapConflicts(){if(!this._markup||"draw"!==this._tool)return[];const t=this._planSnapHover;if(!t)return[];const e=this._planSnapGeometrySnapshot();return t.contextKey===this._planSnapContextKey(e.key)?t.conflicts:[]}_clearPlanSnapHover(t=!0){this._planSnapHover=null,this._syncPlanSnapActiveMarker(null),this._syncPlanSnapConflictMarkers([]),t&&(this._cursorPt=null)}_samePt(t,e){return fi(t,e)}_dropLegacySegments(){for(const t of this._serverCfg?.markers||[])"ripple"===t.display&&(t.display="icon_ripple");for(const t of this._serverCfg?.spaces||[]){delete t.segments;const e=new Set,i=t=>"string"==typeof t&&t.length>=1&&t.length<=64&&!e.has(t),s=t=>(e.add(t),!0),n=t=>Array.isArray(t)&&2===t.length&&t.every(t=>Number.isFinite(Number(t))&&Math.abs(Number(t))<=bc);if(Array.isArray(t.partitions)&&(t.partitions=t.partitions.filter(t=>t&&i(t.id)&&n(t.a)&&n(t.b)&&Math.hypot(t.a[0]-t.b[0],t.a[1]-t.b[1])>1e-9&&s(t.id)).map(t=>({...t,cm:Math.max(1,Math.min(100,Number(t.cm)||15))})),t.partitions.length||delete t.partitions),Array.isArray(t.wall_columns)&&(t.wall_columns=t.wall_columns.filter(t=>t&&i(t.id)&&n(t.center)&&s(t.id)).map(t=>({id:t.id,shape:"circle"===t.shape?"circle":"square",center:[Number(t.center[0]),Number(t.center[1])],cm:ql(Number(t.cm)||15),..."circle"===t.shape?{}:{angle:Wl(t.angle)}})),t.wall_columns.length||delete t.wall_columns),Array.isArray(t.room_drafts)&&(t.room_drafts=t.room_drafts.filter(t=>t&&i(t.id)&&Array.isArray(t.points)&&t.points.length>=2&&t.points.every(n)&&s(t.id)).map(t=>{const e=[[Number(t.points[0][0]),Number(t.points[0][1])]],i=[];for(let s=1;st.points.length>=2),t.room_drafts.length||delete t.room_drafts),Array.isArray(t.walls)){const e=rh(t.open_spans).map(t=>[t.a[0],t.a[1],t.b[0],t.b[1]]);t.walls=Er(t.walls,t.rooms||[],$c,1,e),t.walls.length||delete t.walls}}}get _cfgWriting(){return this._writesPending>0}_writeConfig(){var t,e;this._writesPending++,this._writeChain=(t=this._writeChain,e=async()=>{if(!this._serverCfg)return;this._dropLegacySegments();const t=Qu(this._serverCfg),e=Dh(t);e!==Dh(this._serverCfg)&&(this._serverCfg=t),this._cfgContentFingerprint=e;const i=await this.hass.callWS({type:"houseplan/config/set",config:t,expected_rev:this._cfgRev});this._cfgRev=i?.rev??this._cfgRev+1},t.catch(()=>{}).then(e));return this._writeChain.finally(()=>{this._writesPending--})}_saveConfig(){this._cfgEpoch++,this._saveConfigDebounced()}_geometrySnapshot(t=this._space){const e=this._serverCfg?.spaces.find(e=>e.id===t);if(!e)return null;const i=t=>JSON.parse(JSON.stringify(t)),s={};for(const t of["plan_x","plan_y","plan_scale","plan_scale_x","plan_scale_y","plan_angle"])void 0!==e[t]&&(s[t]=e[t]);return{spaceId:t,rooms:i(e.rooms||[]),...Array.isArray(e.openings)?{openings:i(e.openings)}:{},...Array.isArray(e.walls)?{walls:i(e.walls)}:{},...Array.isArray(e.open_spans)?{open_spans:i(e.open_spans)}:{},...Array.isArray(e.room_drafts)?{room_drafts:i(e.room_drafts)}:{},...Array.isArray(e.partitions)?{partitions:i(e.partitions)}:{},...Array.isArray(e.wall_columns)?{wall_columns:i(e.wall_columns)}:{},...Array.isArray(e.decor)?{decor:i(e.decor)}:{},plan_transform:s}}_recordGeometry(t,e){if(!e)return;const i=this._geometrySnapshot(e.spaceId);i&&JSON.stringify(e)!==JSON.stringify(i)&&(this._geometryHistory.push({name:t,before:e,after:i}),this.requestUpdate())}_clearGeometryGesture(){this._path=[],this._clearPlanSnapHover(),this._clearOpeningPlacement(!1),this._mergeSel=null,this._mergeDialog=null,this._splitSel=null,this._pendingSplit=null,this._wallFaceBatch=null,this._wallRepairDiagnostic=null,this._roomDeleteDialog=null,this._openWallAnchor=null,this._boundaryRestoreGuard=null,this._wallDialog=null,this._physicalDialog=null,this._physicalSel=null,this._physicalDrag=null,this._physicalRotate=null,this._activeDraftId=null,this._draftSegmentCms=[],this._closingWallCm=null,this._openingDialog=null,this._rszSel=null,this._rszDrag=null,this._rszPreview=null,this._rszLive=null,this._decorDraft=null,this._decorMove=null,this._dtDrag=null,this._bdDrag=null}_cancelBoundaryAnchor(){return!("boundary"!==this._tool||!this._openWallAnchor)&&(this._openWallAnchor=null,this._boundaryRestoreGuard=null,this._clearPlanSnapHover(),this.requestUpdate(),!0)}_stagePointerCancel(t){if(clearTimeout(this._kioskHoldTimer),this._swipeStart?.id===t.pointerId&&(this._swipeStart=null),this._physicalDrag?.pid===t.pointerId||this._physicalRotate?.pid===t.pointerId)return void this._cancelPhysicalGesture();if(this._decorDraft?.pid===t.pointerId)return this._decorDraft=null,void this.requestUpdate();if(this._decorMove?.pid===t.pointerId||this._dtDrag?.pid===t.pointerId||this._bdDrag?.pid===t.pointerId)return void this._cancelDecorGesture();this._cancelBoundaryAnchor(),"opening"===this._tool?(this._cursorPt=null,this._clearOpeningPlacement(!1)):"draw"===this._tool&&this._clearPlanSnapHover();const e=!!this._pinchStart||!!this._panStart;this._pointers.delete(t.pointerId),this._pointers.size<2&&(this._pinchStart=null),0===this._pointers.size&&(this._panStart=null,this._panLock=null),e&&0===this._pointers.size&&this.requestUpdate()}_applyGeometryState(t){if(!this._canCommitSpace(t.spaceId))return!1;const e=this._serverCfg?.spaces.find(e=>e.id===t.spaceId);if(!e)return!1;const i=t=>JSON.parse(JSON.stringify(t));e.rooms=i(t.rooms),void 0!==t.openings?e.openings=i(t.openings):delete e.openings,void 0!==t.walls?e.walls=i(t.walls):delete e.walls,void 0!==t.open_spans?e.open_spans=i(t.open_spans):delete e.open_spans,void 0!==t.room_drafts?e.room_drafts=i(t.room_drafts):delete e.room_drafts,void 0!==t.partitions?e.partitions=i(t.partitions):delete e.partitions,void 0!==t.wall_columns?e.wall_columns=i(t.wall_columns):delete e.wall_columns,void 0!==t.decor?e.decor=i(t.decor):delete e.decor;for(const t of["plan_x","plan_y","plan_scale","plan_scale_x","plan_scale_y","plan_angle"])delete e[t];return Object.assign(e,i(t.plan_transform||{})),this._clearGeometryGesture(),this._space!==t.spaceId&&(this._commitSpace(t.spaceId),this._saveNav(),this._restoreZoom()),this._modelCache=null,this._frame=null,this._regSignature="",this._maybeRebuildDevices(),this._saveConfig(),this.requestUpdate(),!0}_roomAt(t){return this._spaceModel()?.rooms.find(e=>{const i=hi(e);return!!i&&wi(t,i)})}_overlapRoom(t){return this._spaceModel()?.rooms.find(e=>{const i=hi(e);return!!i&&Di(t,i)})}_pointInRoom(t,e){return e.poly?vi(t,e.poly):null!=e.x&&t[0]>=e.x&&t[0]<=e.x+e.w&&t[1]>=e.y&&t[1]<=e.y+e.h}_contourSelfIntersects(t){if(!ka(t))return!0;const e=t.length,i=.001;for(let s=0;s=500)return this._showToast(this._t("toast.physical_limit")),!1;const t=this._curSpaceCfg;return!(!this._activeDraftId&&(t?.room_drafts||[]).length>=200||this._draftSegmentCount(t)>=2e3||(t?.partitions||[]).length+this._path.length>fm)||(this._showToast(this._t("toast.physical_limit")),!1)}_markupClick(t){if(this._vacFit)return;if(!this._markup)return;const e=this._spaceModel();if(!e)return void this._clearGeometryGesture();if(this._suppressClick)return;if(this._drag||this._rlResize)return;const i=t.composedPath?.()||[];if(i.some(t=>t?.classList?.contains?.("roomlabel")||t?.classList?.contains?.("rlhandle")))return;if(i.some(t=>t?.classList?.contains?.("physical-hit")))return void("boundary"===this._tool&&this._showToast(this._t("toast.boundary_blocked")));const s=this._svgPoint(t);if("select"===this._tool)return void(this._physicalSel=null);if("resize"===this._tool){if(this._rszDrag||i.some(t=>t?.classList?.contains?.("rszhandle")))return;const t=[...e.rooms].reverse().find(t=>this._pointInRoom(s,t));return void(this._rszSel=t?.id||null)}if("delroom"===this._tool)return void this._deleteRoomClick(s);if("opening"===this._tool)return void this._openingClick(s);if("merge"===this._tool)return void this._mergeClick(s);if("wallthick"===this._tool)return void this._wallThickClick(s);if("boundary"===this._tool)return void this._boundaryClick(s);if("split"===this._tool)return void this._splitClick(s);if("column"===this._tool)return void this._columnClick(s);this._wallRepairDiagnostic=null;const n=this._resolvePlanDrawPoint(s,t.shiftKey);if(n.ambiguous)return this._planSnapHover={contextKey:n.contextKey,candidate:null,conflicts:n.conflicts},this._syncPlanSnapActiveMarker(null),this._syncPlanSnapConflictMarkers(n.conflicts),void this._showToast(this._t("toast.plan_snap_ambiguous"));let o=n.point;if(t.ctrlKey||t.metaKey){if(t.preventDefault(),this._path.length<3)return;o=[...this._path[0]]}if(!this._path.length){if(!t.shiftKey&&!n.candidate&&this._offerExistingWallFace(s))return;const e=this._draftEndAt(o);return e?(this._activeDraftId=e.draft.id,this._resumeDraftBySpace[this._space]=e.draft.id,this._path=e.reverse?[...e.draft.points].reverse().map(t=>[...t]):e.draft.points.map(t=>[...t]),void(this._draftSegmentCms=this._adoptDraftCms(this._path,e.reverse?[...e.draft.segments].reverse().map(t=>t.cm):e.draft.segments.map(t=>t.cm),e.draft.id))):(this._activeDraftId=null,this._draftSegmentCms=[],void(this._path=[o]))}const a=this._path[this._path.length-1];if(this._samePt(o,a))return;const r=this._draftEndAt(o,this._activeDraftId||void 0);if(r)return void this._mergeDraftEndpoint(r);if(!this._canAppendRoomDraftPoint())return;const l=this._drawWallCm;if(null==l)return void this._showPhysicalRange(100);const c=this._path.map(t=>[...t]);this._path=[...this._path,o],this._draftSegmentCms=[...this._draftSegmentCms,l],this._persistActiveDraftSegment(),this._offerWallFaces(c)}_draftEndAt(t,e){const i=this._spaceModel();if(!i)return null;const s=this._viewOr(this._baseVb()),n=Math.max(.15*this._gridPitch,this._stageEl?.clientWidth?s.w/this._stageEl.clientWidth*12:0);for(const s of i.room_drafts||[]){if(s.id===e)continue;if(s.points.length<2)continue;const i=s.points[0],o=s.points[s.points.length-1];if(Math.hypot(t[0]-o[0],t[1]-o[1])<=n)return{draft:s,reverse:!1};if(Math.hypot(t[0]-i[0],t[1]-i[1])<=n)return{draft:s,reverse:!0}}return null}_mergeDraftEndpoint(t){const e=this._curSpaceCfg;if(!e||!this._path.length)return;const i=this._path.map(t=>[...t]),s=this._wallGraphSources(i),n=Array.isArray(e.room_drafts)?e.room_drafts:[],o=this._activeDraftId?n.find(t=>t.id===this._activeDraftId):null,a=n.find(e=>e.id===t.draft.id);if(!a)return;const r=t.reverse?t.draft.points.map(t=>[...t]):[...t.draft.points].reverse().map(t=>[...t]),l=t.reverse?(a.segments||[]).map(t=>({...t})):[...a.segments||[]].reverse().map(t=>({...t})),c=this._path[this._path.length-1],h=this._samePt(c,r[0]),d=h?null:this._drawWallCm;if(!h&&null==d)return void this._showPhysicalRange(100);const p=this._draftSegmentCms.map((t,e)=>({...o?.segments?.[e]||{},cm:t})),u=[...this._path.map(t=>[...t]),...h?r.slice(1):r],_=[...p,...null==d?[]:[{cm:d}],...l],g=u.length>=4&&this._samePt(u[0],u[u.length-1]),m=u,f=_;if(m.length>500)return void this._showToast(this._t("toast.physical_limit"));const v=(o?.segments?.length||0)+(a.segments?.length||0);if(this._draftSegmentCount(e)-v+f.length>2e3)return void this._showToast(this._t("toast.physical_limit"));if(g){const t=m.slice(0,-1);if(this._contourSelfIntersects(t)||Pi(t)<=1e-6)return void this._showToast(this._t("toast.contour_cannot_close"));const e=this._overlapRoom(t);if(e)return void this._showToast(this._t("toast.room_overlap",{name:e.name||""}))}const y=this._geometrySnapshot(),b=this._activeDraftId||t.draft.id,w={...o||a,id:b,points:m.map(t=>[t[0]/um,t[1]/um]),segments:f};e.room_drafts=n.filter(e=>e.id!==t.draft.id&&(!this._activeDraftId||e.id!==this._activeDraftId)),e.room_drafts.push(w),this._activeDraftId=b,this._resumeDraftBySpace[this._space]=b,this._path=m,this._draftSegmentCms=this._adoptDraftCms(m,f.map(t=>Number(t.cm)),b),this._physicalSel=null,this._recordGeometry(this._t("history.draft_merge"),y),this._saveConfig(),null!=d&&this._offerWallFaces(i,i.length-1,s)}_adoptDraftCms(t,e,i){const s=Math.max(0,t.length-1),n=tp(s,e,this._drawWallCm,fr);return e.length!==s&&console.debug(`[houseplan] draft ${i??"?"}: восстановлено толщин ${s-e.length} (#234)`),n}_persistActiveDraftSegment(){if(this._path.length<2||!this._curSpaceCfg)return;const t=this._geometrySnapshot(),e=this._curSpaceCfg;e.room_drafts||=[],this._activeDraftId||(this._activeDraftId="draft-"+Date.now().toString(36)),this._resumeDraftBySpace[this._space]=this._activeDraftId;const i=e.room_drafts.findIndex(t=>t.id===this._activeDraftId),s={...i>=0?e.room_drafts[i]:{},id:this._activeDraftId,points:this._path.map(t=>[t[0]/um,t[1]/um]),segments:this._draftSegmentCms.map((t,s)=>({...i>=0?e.room_drafts[i]?.segments?.[s]:{},cm:t}))};i>=0?e.room_drafts[i]=s:e.room_drafts.push(s),this._recordGeometry(this._t("history.draft_segment"),t),this._saveConfig()}_activeWallSourceKey(t){return`active:${this._activeDraftId||"session"}:${t}`}_wallGraphSources(t){const e=this._planStructuralGeometrySnapshot().value.segments.map(t=>({a:t.a,b:t.b,key:`static:${t.key}`}));for(let i=0;i+1t.key===i);if(s>=0){const[t]=this._wallFaceGraphCache.splice(s,1);return this._wallFaceGraphCache.push(t),t.value}const n=xp(t,e);return this._wallFaceGraphCache.push({key:i,value:n}),this._wallFaceGraphCache.length>4&&this._wallFaceGraphCache.shift(),n}_offerWallFaces(t,e=this._path.length-2,i){if(this._path.length<2||this._wallFaceBatch||this._roomDialog)return;const s=this._spaceModel();if(!s)return;const n=this._activeWallSourceKey(e),o=2e-4*this._gridPitch;let a,r;try{const e=i||this._wallGraphSources(t);r=this._wallGraphSources(this._path),a=function(t,e,i){const s=new Set(t.faces.map(t=>t.key));return e.faces.filter(t=>!s.has(t.key)&&t.sourceKeys.includes(i))}(this._wallFaceGraph(e,o),this._wallFaceGraph(r,o),n)}catch{return}if(!a.length){const t=Ep(r,{requiredSourceKey:n,maxDistance:xr(2,this._cellCm,this._gridPitch),gridStep:this._gridPitch,epsilon:o});return"ambiguous"===t.kind?(this._wallRepairDiagnostic=t.proposals[0]||null,void this._showToast(this._t("toast.wall_repair_ambiguous"))):void("repair"!==t.kind||this._overlapRoom(t.face.ring)||this._beginWallFaceBatch([{...t.face,repair:t.proposal}]))}for(const t of s.rooms){const e=hi(t);if(!t.id||!e)continue;const i=Fi(e,this._path,.02*this._gridPitch);if(!i)continue;const[s,n]=i,o=Pi(s)>=Pi(n)?s:n,r=o===s?n:s,l=[...a].sort((t,e)=>Math.abs(t.area-Pi(r))-Math.abs(e.area-Pi(r))||t.key.localeCompare(e.key))[0];if(!l)return;return void this._beginWallFaceBatch([{...l,ring:r.map(t=>[t[0],t[1]]),split:{roomId:t.id,mainPoly:o,newPoly:r},consumeAllActive:!0}])}const l=a.filter(t=>!(t.ring.length<3||this._contourSelfIntersects(t.ring))&&!this._overlapRoom(t.ring));l.length&&this._beginWallFaceBatch(l)}_beginWallFaceBatch(t){this._wallRepairDiagnostic=null,this._wallFaceBatch={candidates:[...t].sort((t,e)=>t.area-e.area||t.key.localeCompare(e.key)),index:0,decisions:[],activePath:this._path.map(t=>[...t]),activeCms:[...this._draftSegmentCms],activeDraftId:this._activeDraftId},this._clearPlanSnapHover(),this._nameSel="",this._areaSel="",this._resetRoomDialogFields(),this._roomDialog=!0}_offerExistingWallFace(t){if(this._path.length||this._wallFaceBatch||this._roomDialog)return!1;const e=2e-4*this._gridPitch;try{let i,s=$p(this._wallFaceGraph(this._wallGraphSources([]),e),t,e);if(!s){const n=Ep(this._wallGraphSources([]),{point:t,maxDistance:xr(2,this._cellCm,this._gridPitch),gridStep:this._gridPitch,epsilon:e});if("ambiguous"===n.kind)return this._wallRepairDiagnostic=n.proposals[0]||null,this._showToast(this._t("toast.wall_repair_ambiguous")),!0;if("repair"===n.kind)s=n.face,i=n.proposal;else if("none"===n.kind){const i=Ep(this._wallGraphSources([]),{point:t,maxDistance:this._cssPxToRender(12),gridStep:this._gridPitch,epsilon:e});if("repair"===i.kind)return this._wallRepairDiagnostic=i.proposal,this._showToast(this._t("toast.wall_repair_too_large")),!0}}return!(!s||s.ring.length<3||this._contourSelfIntersects(s.ring)||this._overlapRoom(s.ring))&&(this._beginWallFaceBatch([{...s,existing:!i,repair:i}]),!0)}catch{return!1}}_columnClick(t){const e=this._snap(t),i=this._drawWallCm;if(null==i)return void this._showPhysicalRange(Ll);if(!this._curSpaceCfg||this._limitReached("column"))return;const s=this._spaceModel();if(!s)return;const n={id:"column-"+Date.now().toString(36),shape:"square",center:e,cm:ql(i),angle:0},o=(s.wall_columns||[]).find(t=>rc(t,n,.02*this._gridPitch));if(o)return clearTimeout(this._duplicateColumnTimer),this._duplicateColumnId=o.id,this._duplicateColumnTimer=window.setTimeout(()=>{this._duplicateColumnId=null},900),void this._showToast(this._t("toast.column_duplicate"));const a=this._geometrySnapshot(),r=this._curSpaceCfg;r.wall_columns||=[],r.wall_columns.push({...n,center:[e[0]/um,e[1]/um]}),this._recordGeometry(this._t("history.column_add"),a),this._saveConfig()}_openPhysicalDialog(t,e,i){const s=this._spaceModel();if(s)if("partition"===t){const i=s.partitions.find(t=>t.id===e);i&&(this._physicalDialog={kind:t,id:e,cm:kr(i.cm,this._imperial),length:this._fmtLen(i.a,i.b)})}else if("column"===t){const i=s.wall_columns.find(t=>t.id===e);i&&(this._physicalDialog={kind:t,id:e,cm:kr(i.cm,this._imperial),shape:i.shape,angle:this._angleField("square"===i.shape?Wl(i.angle):0)})}else{const n=s.room_drafts.find(t=>t.id===e),o=Math.max(0,Math.min(n?.segments.length?n.segments.length-1:0,i||0));n?.segments[o]&&(this._physicalDialog={kind:t,id:e,segment:o,cm:kr(n.segments[o].cm,this._imperial),length:this._fmtLen(n.points[o],n.points[o+1])})}}_physicalDown(t,e,i){const s=this._spaceModel();if(!s)return;t.stopPropagation(),wm(t);const n=this._svgPoint(t),o=[];for(const t of[...s.wall_columns].reverse())oc(n,Yl(t,this._cellCm,this._gridPitch))&&o.push({kind:"column",id:t.id});for(const t of[...s.partitions].reverse()){const e=Kl(t.a,t.b,t.cm,this._cellCm,this._gridPitch);e&&oc(n,e)&&o.push({kind:"partition",id:t.id})}o.some(t=>t.kind===e&&t.id===i)||o.unshift({kind:e,id:i});const a=o.map(t=>`${t.kind}:${t.id}`).sort().join("|"),r=performance.now(),l=this._physicalPickCycle,c=o.length>1&&l?.signature===a&&r-l.at>380&&r-l.at<=1200&&Math.hypot(t.clientX-l.x,t.clientY-l.y)<=10?(l.index+1)%o.length:Math.max(0,o.findIndex(t=>t.kind===e&&t.id===i));this._physicalPickCycle={signature:a,index:c,x:t.clientX,y:t.clientY,at:r},e=o[c].kind,i=o[c].id;const h="partition"===e?s.partitions.find(t=>t.id===i):s.wall_columns.find(t=>t.id===i);h&&(this._physicalSel={kind:e,id:i},this._physicalDrag={pid:t.pointerId,kind:e,id:i,start:this._svgPoint(t),startClient:[t.clientX,t.clientY],before:this._geometrySnapshot(),moved:!1,base:JSON.parse(JSON.stringify(h)),delta:[0,0]})}_clampPhysicalDelta(t,e,i){const s="partition"===t?[e.a,e.b]:[e.center],n=s.map(t=>t[0]),o=s.map(t=>t[1]);return[Math.max(-bc*um-Math.min(...n),Math.min(bc*um-Math.max(...n),i[0])),Math.max(-bc*um-Math.min(...o),Math.min(bc*um-Math.max(...o),i[1]))]}_physicalMove(t){const e=this._physicalDrag;if(!e||e.pid!==t.pointerId)return;t.stopPropagation();const i=this._svgPoint(t),s="partition"===e.kind?e.base.a:e.base.center,n=this._snap([s[0]+i[0]-e.start[0],s[1]+i[1]-e.start[1]]),o=this._clampPhysicalDelta(e.kind,e.base,[n[0]-s[0],n[1]-s[1]]);this._physicalDrag={...e,delta:o,moved:e.moved||Math.hypot(t.clientX-e.startClient[0],t.clientY-e.startClient[1])>=5}}_physicalUp(t){const e=this._physicalDrag;if(!e||e.pid!==t.pointerId)return;if(t.stopPropagation(),this._physicalDrag=null,!e.moved)return void this._registerPhysicalTap(e.kind,e.id);const i=this._spaceModel();if(!this._curSpaceCfg||!i)return;const s=this._curSpaceCfg;if("partition"===e.kind){const t=(s.partitions||[]).find(t=>t.id===e.id),i=e.base;if(t){const n={...i,a:[i.a[0]+e.delta[0],i.a[1]+e.delta[1]],b:[i.b[0]+e.delta[0],i.b[1]+e.delta[1]]};t.a=[n.a[0]/um,n.a[1]/um],t.b=[n.b[0]/um,n.b[1]/um];for(const t of s.openings||[]){if("partition"!==t.host?.kind||t.host.id!==e.id)continue;const i=Rd(t,[n],um,this._cellCm,this._gridPitch).resolved;i&&Object.assign(t,Od(t,i,um))}}}else{const t=(s.wall_columns||[]).find(t=>t.id===e.id),n=e.base,o={...n,center:[n.center[0]+e.delta[0],n.center[1]+e.delta[1]]};if(i.wall_columns.some(t=>t.id!==e.id&&rc(t,o,.02*this._gridPitch)))return void this._showToast(this._t("toast.column_duplicate"));t&&(t.center=[(n.center[0]+e.delta[0])/um,(n.center[1]+e.delta[1])/um])}this._recordGeometry(this._t("history.physical_move"),e.before),this._saveConfig()}_registerPhysicalTap(t,e,i){const s=performance.now(),n=this._physicalLastTap?.kind===t&&this._physicalLastTap.id===e&&this._physicalLastTap.segment===i&&s-this._physicalLastTap.at<=360;this._physicalLastTap={kind:t,id:e,segment:i,at:s},n&&(this._physicalLastTap=null,this._openPhysicalDialog(t,e,i))}_cancelPhysicalGesture(){this._physicalDrag=null,this._physicalRotate=null,this.requestUpdate()}_physicalRotateDown(t,e){if("square"!==e.shape||!this._spaceModel())return;t.preventDefault(),t.stopPropagation(),wm(t);const i=this._svgPoint(t);this._physicalSel={kind:"column",id:e.id},this._physicalRotate={pid:t.pointerId,id:e.id,center:[...e.center],startAngle:180*Math.atan2(i[1]-e.center[1],i[0]-e.center[0])/Math.PI,baseAngle:Wl(e.angle),angle:Wl(e.angle),before:this._geometrySnapshot(),moved:!1}}_physicalRotateMove(t){const e=this._physicalRotate;if(!e||e.pid!==t.pointerId)return;t.preventDefault(),t.stopPropagation();const i=this._svgPoint(t),s=180*Math.atan2(i[1]-e.center[1],i[0]-e.center[0])/Math.PI,n=e.baseAngle+s-e.startAngle,o=Wl(t.shiftKey?n:5*Math.round(n/5));this._physicalRotate={...e,angle:o,moved:e.moved||Math.abs(n-e.baseAngle)>=.5}}_physicalRotateUp(t){const e=this._physicalRotate;if(!e||e.pid!==t.pointerId)return;t.preventDefault(),t.stopPropagation(),this._physicalRotate=null;const i=this._spaceModel();if(!e.moved||!this._curSpaceCfg||!i)return;const s=i.wall_columns.find(t=>t.id===e.id);if(!s||"square"!==s.shape)return;const n={...s,angle:e.angle};if(i.wall_columns.some(t=>t.id!==e.id&&rc(t,n,.02*this._gridPitch)))return void this._showToast(this._t("toast.column_duplicate"));const o=this._curSpaceCfg.wall_columns?.find(t=>t.id===e.id);o&&(o.angle=e.angle,this._recordGeometry(this._t("history.physical_edit"),e.before),this._saveConfig())}_rszRooms(){const t=[],e=this._spaceModel();if(!e)return t;for(const i of e.rooms){const e=i.id?hi(i):null;e&&t.push({id:i.id,poly:e})}return t}_rszOpenings(){return this._openingsR.map(t=>({id:t.id,x:t.rx,y:t.ry,length:t.rlen}))}_rszOpts(){return{minDim:this._cmToUnits(30),eps:.05*this._gridPitch}}_rszSnapshot(){return JSON.stringify(this._geometrySnapshot()||{spaceId:this._space,rooms:[],openings:[],walls:[],open_spans:[]})}_rszApplyPreview(t,e){const i=this._rszDrag,s=this._serverCfg?.spaces.find(t=>t.id===this._space);if(!i||!s)return;const n=JSON.parse(i.snap),o={...s,rooms:n.rooms,openings:n.openings,walls:n.walls,open_spans:n.open_spans};Array.isArray(n.open_spans)&&n.open_spans.length||delete o.open_spans;const a=this._spaceH;for(const[e,i]of Object.entries(t)){const t=o.rooms.find(t=>t.id===e);t&&(t.poly=i.map(t=>[t[0]/um,t[1]/a]),delete t.x,delete t.y,delete t.w,delete t.h)}for(const[t,i]of Object.entries(e)){const e=(o.openings||[]).find(e=>e.id===t);e&&(e.x=i[0]/um,e.y=i[1]/a)}const r=[],l=[];for(const t of i.changed){const e=i.rooms.find(e=>e.id===t),s=o.rooms.find(e=>e.id===t);if(!e||!s?.poly)continue;const n=s.poly.map(t=>[t[0]*um,t[1]*a]);if(e.poly.length===n.length)for(let t=0;tt.id===e);if(!s||!s.poly||s.poly.length<3)return null;if(i<0||i>=s.poly.length)return null;const n=[...s.poly[i]],o=[...s.poly[(i+1)%s.poly.length]];return{roomId:e,edge:i,a:n,b:o,n:fa(s.poly,i)}}(s,e,i);n&&(this._rszDrag={kind:"edge",pid:t.pointerId,roomId:e,plan:n,rooms:s,openings:this._rszOpenings(),snap:this._rszSnapshot(),moved:!1,d:0,k:1,changed:[]})}_rszCornerDown(t,e,i,s){"resize"!==this._tool||this._rszDrag||(t.stopPropagation(),t.preventDefault(),wm(t),this._rszDrag={kind:"scale",pid:t.pointerId,roomId:e,fixed:s,span0:Math.hypot(i[0]-s[0],i[1]-s[1])||1,rooms:this._rszRooms(),openings:this._rszOpenings(),snap:this._rszSnapshot(),moved:!1,d:0,k:1,changed:[]})}_rszMove(t){const e=this._rszDrag;if(!e||e.pid!==t.pointerId)return;t.stopPropagation();const i=this._svgPoint(t);if("edge"===e.kind){const t=e.plan,s=(i[0]-t.a[0])*t.n[0]+(i[1]-t.a[1])*t.n[1],n=this._snap([t.a[0]+t.n[0]*s,t.a[1]+t.n[1]*s]);let o=(n[0]-t.a[0])*t.n[0]+(n[1]-t.a[1])*t.n[1];if(o=function(t,e,i,s,n,o){if(!Number.isFinite(s)||Math.abs(s)<1e-9)return 0;const a=Math.sign(s);let r=Math.abs(s);const l=Math.max(n,1e-6);for(let s=0;s<4096&&r>1e-9;s++,r-=l){const s=a*r;if(Da(t,e,i,s,o))return s}return 0}(e.rooms,e.openings,t,o,this._gridPitch,this._rszOpts()),o===e.d&&e.moved)return;e.d=o,e.moved=!0;const a=Sa(e.rooms,e.openings,t,o,this._rszOpts().eps);e.changed=Object.keys(a.polys),this._rszApplyPreview(a.polys,a.openings),this._rszLive=this._rszEdgeLabels(a,t)}else{const t=e.fixed,s=this._snap(i);let n=Math.hypot(s[0]-t[0],s[1]-t[1])/(e.span0||1);if(n=Math.max(.05,Math.min(20,n)),n=function(t,e,i,s,n,o){if(!Number.isFinite(n)||n<=0)return 1;if(Pa(t,e,i,s,n,o))return n;let a=1,r=n;for(let n=0;n<28;n++){const n=(a+r)/2;Pa(t,e,i,s,n,o)?a=n:r=n}return a}(e.rooms,e.openings,e.roomId,t,n,this._rszOpts()),n===e.k&&e.moved)return;e.k=n,e.moved=!0;const o=e.rooms.find(t=>t.id===e.roomId),a=e.rooms.filter(t=>t.id!==e.roomId).map(t=>t.poly),r=Ta(o,e.openings,a,t,n,2*this._rszOpts().eps);e.changed=[e.roomId],this._rszApplyPreview({[e.roomId]:r.poly},r.openings),this._rszLive=this._rszScaleLabels(r.poly)}this.requestUpdate()}_rszUp(t){const e=this._rszDrag;if(!e||e.pid!==t.pointerId)return;t.stopPropagation();const i=this._rszPreview;this._rszDrag=null,this._rszLive=null,this._rszPreview=null;if(!(e.moved&&("edge"===e.kind?Math.abs(e.d)>1e-9:Math.abs(e.k-1)>1e-9))||!i)return this._cfgEpoch++,void this.requestUpdate();const s=JSON.parse(e.snap),n=this._curSpaceCfg;if(n){n.rooms=i.sp.rooms,n.openings=i.sp.openings,Array.isArray(i.sp.walls)&&(i.sp.walls.length?n.walls=i.sp.walls:delete n.walls),Array.isArray(i.sp.open_spans)&&i.sp.open_spans.length?n.open_spans=i.sp.open_spans:delete n.open_spans;for(const t of e.changed){const e=n.rooms.find(e=>e.id===t);e?.poly&&(e.poly=wa(e.poly,1e-9))}this._commitOpenSpans(),Array.isArray(n.walls)&&n.walls.length&&(n.walls=Er(n.walls,n.rooms||[],$c,1,this._cfgOpenCuts()),n.walls.length||delete n.walls)}this._suppressClick=!0,setTimeout(()=>this._suppressClick=!1,0),this._recordGeometry(this._t("history.resize_room"),s),this._saveConfig(),this.requestUpdate()}_rszCancelDrag(){this._rszDrag&&(this._rszDrag=null,this._rszLive=null,this._rszPreview=null,this._cfgEpoch++,this.requestUpdate())}_rszPointerCancel(t){const e=this._rszDrag;e&&e.pid===t.pointerId&&(t.stopPropagation(),this._rszCancelDrag())}_rszEdgeLabels(t,e){const i=this._rszDrag,s=[],n=t.polys[e.roomId]||i.rooms.find(t=>t.id===e.roomId).poly,o=n.length,a=e.edge,r=(a+1)%o,l=this._rszInnerSpanCms(e.roomId,n,t.polys);for(const t of[(a-1+o)%o,a,r]){const e=n[t],i=n[(t+1)%o],a=l?.[t];s.push({x:(e[0]+i[0])/2,y:(e[1]+i[1])/2,text:null==a?this._fmtLen(e,i):li(a,"mi"===this.hass?.config?.unit_system?.length)})}const c="mi"===this.hass?.config?.unit_system?.length,h=Object.keys(t.polys).length?Object.keys(t.polys):[e.roomId],d=this._spaceWalls,p=this._openPairs().flatMap(t=>t.segs),u=this._physicalBodiesR();for(const e of h){const n=t.polys[e]||i.rooms.find(t=>t.id===e).poly,o=d.length&&fl(Object.entries(t.polys).map(([t,e])=>({id:t,poly:e})),e,d,p,this._wallKeyPitch,this._cellCm,this._gridPitch,um)||n,a=$i(o),r=u.length?sc(ic(o,u))*Math.pow(this._cellCm/this._gridPitch,2)/1e4:Ra(o,this._gridPitch,this._cellCm);s.push({x:a[0],y:a[1],text:Ia(r,c),area:!0})}return s}_rszInnerSpanCms(t,e,i){const s=Object.keys(i).length?Object.entries(i).map(([t,e])=>({id:t,poly:e})):this._spaceModel()?.rooms;if(!s?.length)return null;const n=this._spaceWalls;if(!n.length)return null;const o=function(t,e,i,s,n,o,a,r=1){const l=(t||[]).find(t=>t?.id===e),c=hi(l);if(!c||c.length<3)return null;const h=hl(t,e,i,s,n,o,a,r);if(!h)return c.map(()=>0);const d=4*Kr(n,r);return c.map((t,e)=>{const i=c[(e+1)%c.length],s=[(t[0]+i[0])/2,(t[1]+i[1])/2];for(let t=0;tt.segs),this._wallKeyPitch,this._cellCm,this._gridPitch,um);if(!o||o.length!==e.length)return null;const a=this._cellCm/this._gridPitch;return e.map((t,i)=>function(t,e,i){const s=t?.length||0;if(s<3||!Array.isArray(i)||i.length!==s)return 0;const n=(Math.trunc(e)%s+s)%s,o=t[n],a=t[(n+1)%s],r=a[0]-o[0],l=a[1]-o[1],c=Math.hypot(r,l);if(!(c>0))return 0;const h=Math.max(0,Number(i[n])||0);if(!(h>0))return c;const d=[r/c,l/c],p=Xr(t,n),u=[o[0]+p[0]*h,o[1]+p[1]*h],_=e=>{const n=Math.max(0,Number(i[e])||0);if(!(n>0))return null;const a=t[e],r=t[(e+1)%s],l=r[0]-a[0],c=r[1]-a[1],h=Math.hypot(l,c);if(!(h>0))return null;const p=Xr(t,e),_=Zr(u,d,[a[0]+p[0]*n,a[1]+p[1]*n],[l/h,c/h]);return _?(_[0]-o[0])*d[0]+(_[1]-o[1])*d[1]:null},g=_((n-1+s)%s)??0,m=(_((n+1)%s)??c)-g;return m>0?m:0}(e,i,o)*a)}_rszScaleLabels(t){const e="mi"===this.hass?.config?.unit_system?.length,i=t.map(t=>t[0]),s=t.map(t=>t[1]),n=this._spaceWalls,o=n.length&&this._rszSel&&fl([{id:this._rszSel,poly:t}],this._rszSel,n,[],this._wallKeyPitch,this._cellCm,this._gridPitch,um)||t,a=$i(o),r=this._physicalBodiesR(),l=r.length?sc(ic(o,r))*Math.pow(this._cellCm/this._gridPitch,2)/1e4:Ra(o,this._gridPitch,this._cellCm),c=o.map(t=>t[0]),h=o.map(t=>t[1]),d=Math.max(...c)-Math.min(...c),p=Math.max(...h)-Math.min(...h);return[{x:Math.min(...i),y:Math.min(...s),text:`${this._fmtLen([0,0],[d,0])} × ${this._fmtLen([0,0],[p,0])}`},{x:a[0],y:a[1],text:Ia(l,e),area:!0}]}_renderResizeLayer(t){const e=Math.max(.013*t.w,5),i=e/2,s=t=>t.toFixed(1),n=`M ${s(-.7*i)} 0 H ${s(.7*i)} M 0 ${s(-.22*i)} V ${s(-i)} M ${s(-.32*i)} ${s(-.6*i)} L 0 ${s(-i)} L ${s(.32*i)} ${s(-.6*i)} M 0 ${s(.22*i)} V ${s(i)} M ${s(-.32*i)} ${s(.6*i)} L 0 ${s(i)} L ${s(.32*i)} ${s(.6*i)}`,o=[],a=this._rszRooms();for(const t of a)for(let i=0;ithis._rszEdgeDown(e,t.id,i)} @pointermove=${t=>this._rszMove(t)} @pointerup=${t=>this._rszUp(t)} @pointercancel=${t=>this._rszPointerCancel(t)} - @lostpointercapture=${t=>this._rszPointerCancel(t)}>`),o.push(j``)}const a=this._rszSel?r.find(t=>t.id===this._rszSel):null;if(a){const t=a.poly.map(t=>t[0]),i=a.poly.map(t=>t[1]),s=Math.min(...t),n=Math.max(...t),r=Math.min(...i),l=Math.max(...i);o.push(j``);for(const[t,i,c,h]of[[s,r,n,l],[n,r,s,l],[n,l,s,r],[s,l,n,r]])o.push(j`this._rszCornerDown(e,a.id,[t,i],[c,h])} + @lostpointercapture=${t=>this._rszPointerCancel(t)}>`),o.push(j``)}const r=this._rszSel?a.find(t=>t.id===this._rszSel):null;if(r){const t=r.poly.map(t=>t[0]),i=r.poly.map(t=>t[1]),s=Math.min(...t),n=Math.max(...t),a=Math.min(...i),l=Math.max(...i);o.push(j``);for(const[t,i,c,h]of[[s,a,n,l],[n,a,s,l],[n,l,s,a],[s,l,n,a]])o.push(j`this._rszCornerDown(e,r.id,[t,i],[c,h])} @pointermove=${t=>this._rszMove(t)} @pointerup=${t=>this._rszUp(t)} @pointercancel=${t=>this._rszPointerCancel(t)} - @lostpointercapture=${t=>this._rszPointerCancel(t)}>`),o.push(j``)}return j`${o}`}get _openingsR(){const t=this._curSpaceCfg,e=this._spaceH,i=this._spaceModel();return i?(t?.openings||[]).flatMap(t=>{const s={...t,rx:t.x*pm,ry:t.y*e,rlen:t.length*pm};if(!t.host)return[s];const n=Pd(t,i.partitions,pm,this._cellCm,this._gridPitch);if(!n.resolved)return"plan"===this._mode?[{...s,orphanReason:n.reason||"invalid-host"}]:[];let[o,r]=n.resolved.center;const a=this._physicalDrag;return a?.moved&&"partition"===a.kind&&a.id===t.host.id&&(o+=a.delta[0],r+=a.delta[1]),[{...t,rx:o,ry:r,rlen:n.resolved.length,angle:n.resolved.angle,partitionHost:n.resolved}]}):[]}_partitionOpeningCuts(t=this._spaceModel(),e=()=>!0){if(!t)return[];return x_(k_(this._curSpaceCfg?.id===t.id?this._curSpaceCfg:null,t,this._cellCm,this._gridPitch,pm),e)}_roomWallOpeningInputs(t=this._openingsR,e=this._spaceModel()){if(!e)return[];const i=this._openPairs().flatMap(t=>t.segs);return $_(t,e,this._spaceWalls,i,this._wallKeyPitch,this._cellCm,this._gridPitch,pm)}_openingFace(t,e,i){return t.partitionHost?Fd(t.partitionHost,i):El(e,{x:t.rx,y:t.ry,angle:t.angle,length:t.rlen,flip_v:i})}_cmToUnits(t){return t/this._cellCm*this._gridPitch}get _decorList(){const t=this._curSpaceCfg;return Array.isArray(t?.decor)?t.decor:[]}get _decorH(){return pm}_decorResolvedStyle(t){return function(t,e,i,s=oa){const n="rect"===t?.kind||"ellipse"===t?.kind,o=t,r=Rt(o?.color,s.color);return{color:r,opacity:ra(o?.opacity,s.opacity),widthCm:da(t,e,i,s.widthCm),fill:!!n&&!0===o?.fill,fillColor:Rt(o?.fill_color,o?.fill?r:s.fillColor),fillOpacity:n&&o?.fill?ra(o?.fill_opacity,.25):s.fillOpacity}}(t,this._cellCm,this._gridPitch,oa)}_decorWidthUnits(t){return((t,e,i,s=oa.widthCm)=>{const n=Number(t?.width_cm);if(Number.isFinite(n)&&n>0)return ca(n,e,i);const o=Number(t?.width);return Number.isFinite(o)&&o>0?o:ca(s,e,i)})(t,this._cellCm,this._gridPitch,oa.widthCm)}_decorTextSizeCm(t){if("text"===t?.kind){const e=Number(t.size_cm);return Number.isFinite(e)&&e>0?e:ha(es*is(t),this._cellCm,this._gridPitch)}return ha(es,this._cellCm,this._gridPitch)}_decorTextUnits(t){if("text"!==t.kind)return es;const e=Number(t.size_cm);return Number.isFinite(e)&&e>0?ca(e,this._cellCm,this._gridPitch):es*is(t)}_decorSmallField(t){return Math.round(100*(this._imperial?t/2.54:t))/100}_decorSmallCm(t){const e=this._imperial?2.54*t:t;return Number.isFinite(e)?Math.max(.1,Math.min(100,e)):.1}_decorTextCm(t){const e=this._imperial?2.54*t:t;return Number.isFinite(e)?Math.max(.1,Math.min(Yg,e)):.1}_decorLargeField(t){return Math.round(100*(this._imperial?t/30.48:t/100))/100}_decorLargeCm(t){const e=this._imperial?30.48*t:100*t;return Number.isFinite(e)?Math.max(.1,Math.min(yc*this._cellCm,e)):.1}_angleField(t){const e=Number(t);return Number.isFinite(e)?String(Number(e.toFixed(3))):"0"}_decorBoxOf(t){return"rect"!==t.kind&&"ellipse"!==t.kind&&"furniture"!==t.kind?null:{x:t.x*pm,y:t.y*this._decorH,w:t.w*pm,h:t.h*this._decorH,angle:aa(t.angle)||void 0}}_decorSnapGeometry(t){const e=this._spaceModel();if(!e)return{points:[],segments:[]};const i=t||"",s=this._decorSnapCache;if(s&&s.epoch===this._cfgEpoch&&s.space===this._space&&s.height===this._decorH&&s.exclude===i)return s.geometry;const n=[];for(const e of this._decorList)if(e.id!==t)if("line"===e.kind){const t=[e.x1*pm,e.y1*this._decorH],i=[e.x2*pm,e.y2*this._decorH];n.push({points:[t,i,[(t[0]+i[0])/2,(t[1]+i[1])/2]],segments:[{a:t,b:i}]})}else if("text"===e.kind)n.push({points:[[e.x*pm,e.y*this._decorH]],segments:[]});else{const t=this._decorBoxOf(e);t&&n.push(_a(t))}for(const t of e.rooms){const e=hi(t);e?.length&&n.push({points:e.flatMap((t,i)=>{const s=e[(i+1)%e.length];return[t,[(t[0]+s[0])/2,(t[1]+s[1])/2]]}),segments:e.map((t,i)=>({a:t,b:e[(i+1)%e.length]}))})}const o=function(t){return{points:t.flatMap(t=>t.points),segments:t.flatMap(t=>t.segments)}}(n);return this._decorSnapCache={epoch:this._cfgEpoch,space:this._space,height:this._decorH,exclude:i,geometry:o},o}_decorSnap(t,e="mouse",i){const s=this._stageEl,n=this._viewOr(this._baseVb()),o="touch"===e||"pen"===e?14:8,r=s?n.w/Math.max(1,s.clientWidth)*o:this._gridPitch;return function(t,e,i,s){const n=s(t);let o=null;for(const n of e.points){const e=s(n),r=Math.hypot(e[0]-t[0],e[1]-t[1]);r<=i&&(!o||rthis._snap(t)).point}_replaceDecor(t,e){const i=this._curSpaceCfg;i&&(i.decor=this._decorList.map(i=>i.id===t?{...i,...e}:i),this.requestUpdate())}_cancelDecorGesture(){const t=this._decorMove?.before||this._dtDrag?.before||this._bdDrag?.before,e=t&&this._serverCfg?.spaces.find(e=>e.id===t.spaceId);if(t&&e){const i=t=>JSON.parse(JSON.stringify(t));void 0!==t.decor?e.decor=i(t.decor):delete e.decor;for(const t of["plan_x","plan_y","plan_scale","plan_scale_x","plan_scale_y","plan_angle"])delete e[t];Object.assign(e,i(t.plan_transform||{})),this._cfgEpoch++}this._decorMove=null,this._dtDrag=null,this._bdDrag=null,this.requestUpdate()}_decorPointerDown(t){const e=this._decorTool;if("select"===e||"erase"===e?t.target.closest?.(".dshape"):null)return!0;if("line"===e||"rect"===e||"ellipse"===e){t.preventDefault();const i=this._decorSnap(this._svgPoint(t),t.pointerType);return this._decorDraft={kind:e,a:i,b:i,pid:t.pointerId},bm(t),!0}if("text"===e){const e=this._decorSnap(this._svgPoint(t),t.pointerType);return this._decorTextDialog={x:Cc(e[0]/pm),y:Cc(e[1]/this._decorH),text:"",color:this._decorStyle.color,opacity:this._decorStyle.opacity,angle:"0",sizeCm:ha(es,this._cellCm,this._gridPitch)},this._decorTextSelection={start:0,end:0},!0}if("furniture"===e)return!!this._furnPalette&&(t.preventDefault(),this._furnPlace(this._svgPoint(t),t.shiftKey),!0);if("select"===e&&(this._decorSel=null),this._bdMovable){const e=this._bdRect,i=this._svgPoint(t),s=e.x+e.w/2,n=e.y+e.h/2,o=-aa(e.angle)*Math.PI/180,r=i[0]-s,a=i[1]-n,l=[s+r*Math.cos(o)-a*Math.sin(o),n+r*Math.sin(o)+a*Math.cos(o)];if(l[0]>=e.x&&l[0]<=e.x+e.w&&l[1]>=e.y&&l[1]<=e.y+e.h)return t.preventDefault(),this._bdStart(t)}return!1}_decorCommitDraft(){const t=this._decorDraft;if(this._decorDraft=null,!t)return;const e=.5*this._gridPitch;if(!function(t,e,i,s){const n=Math.abs(i[0]-e[0]),o=Math.abs(i[1]-e[1]);return"line"===t?Math.hypot(n,o)>=s:n>=s&&o>=s}(t.kind,t.a,t.b,e))return;const i=pm,s=this._decorH,n=this._decorStyle,o=this._geometrySnapshot(),r="dc"+Date.now().toString(36)+Math.random().toString(36).slice(2,5),a=Cc;let l;if("line"===t.kind)l={id:r,kind:"line",x1:a(t.a[0]/i),y1:a(t.a[1]/s),x2:a(t.b[0]/i),y2:a(t.b[1]/s),...pa(n,!1)};else{const e=a(Math.min(t.a[0],t.b[0])/i),o=a(Math.min(t.a[1],t.b[1])/s),c=Math.abs(t.b[0]-t.a[0])/i,h=Math.abs(t.b[1]-t.a[1])/s;l={id:r,kind:t.kind,x:e,y:o,w:c,h:h,...pa(n,!0)}}this._curSpaceCfg.decor=[...this._decorList,l],this._decorSel=r,this._recordGeometry(this._t("history.decor_add"),o),this._saveConfig(),this.requestUpdate()}_decorShapeDown(t,e){if("decor"!==this._mode)return;const i=this._decorTool;if("text"===i){if("text"!==e.kind)return;return t.stopPropagation(),t.preventDefault(),void this._decorOpenText(e)}"select"!==i&&"erase"!==i||(t.stopPropagation(),t.preventDefault(),"erase"!==i?(this._decorSel=e.id,this._decorMove={id:e.id,start:this._svgPoint(t),orig:JSON.parse(JSON.stringify(e)),pid:t.pointerId,moved:!1,before:this._geometrySnapshot()},bm(t)):this._decorEraseConfirm={id:e.id,kind:e.kind})}_decorMoveUpdate(t){const e=this._decorMove;if("furniture"===e.orig?.kind)return void this._furnMoveUpdate(t);const i=this._svgPoint(t),s=e.orig,n=("line"===s.kind?s.x1:s.x)*pm,o=("line"===s.kind?s.y1:s.y)*this._decorH,r=this._decorSnap([n+(i[0]-e.start[0]),o+(i[1]-e.start[1])],t.pointerType,e.id);let a=(r[0]-n)/pm,l=(r[1]-o)/this._decorH;const c=e.orig,h="line"===c.kind?Math.min(c.x1,c.x2):c.x,d="line"===c.kind?Math.min(c.y1,c.y2):c.y,p="line"===c.kind?Math.abs(c.x2-c.x1):c.w||0,u="line"===c.kind?Math.abs(c.y2-c.y1):c.h||0,_=yc;a=Math.max(-_-h,Math.min(_-h-p,a)),l=Math.max(-_-d,Math.min(_-d-u,l)),(a||l)&&(e.moved=!0);this._curSpaceCfg.decor=this._decorList.map(t=>{if(t.id!==e.id)return t;const i=e.orig;return"line"===t.kind?{...t,x1:i.x1+a,y1:i.y1+l,x2:i.x2+a,y2:i.y2+l}:{...t,x:i.x+a,y:i.y+l}}),this.requestUpdate()}_decorShapeDbl(t,e){"decor"===this._mode&&"select"===this._decorTool&&(t.preventDefault(),t.stopPropagation(),this._decorMove=null,this._decorSel=e.id,this._openDecorProperties(e))}_openDecorProperties(t){if("decor"!==this._mode||"select"!==this._decorTool)return;if("text"===t.kind)return void this._decorOpenText(t);if(!["line","rect","ellipse","furniture"].includes(t.kind))return;const e=this._decorResolvedStyle(t),i="line"===t.kind?t:null,s=this._decorBoxOf(t);this._decorShapeDialog={id:t.id,kind:t.kind,color:e.color,opacity:e.opacity,widthCm:e.widthCm,angle:this._angleField(aa(i?Os([i.x1*pm,i.y1*this._decorH],[i.x2*pm,i.y2*this._decorH]):t.angle)),...i?{lengthCm:ha(Math.hypot((i.x2-i.x1)*pm,(i.y2-i.y1)*this._decorH),this._cellCm,this._gridPitch),lineStyle:"dashed"===i.line_style?"dashed":"solid"}:{},...s?{sizeWCm:ha(s.w,this._cellCm,this._gridPitch),sizeHCm:ha(s.h,this._cellCm,this._gridPitch)}:{},..."furniture"===t.kind?{symbol:t.symbol}:{},..."rect"===t.kind||"ellipse"===t.kind?{fill:e.fill,fillColor:e.fillColor,fillOpacity:e.fillOpacity}:{}}}_decorOpenText(t){if("text"!==t.kind)return;let e=String(t.text??"");const i=[...e.matchAll(/\{([^{}\r\n]+)\}/g)].some(t=>!!Yi(t[1])),s=String(t.unit??"").trim(),n="state"===String(t.attr??"").trim().toLowerCase()?null:t.attr,o=i||s?"":Xi(t.entity,n),r=!(!String(t.entity??"").trim()||i||o&&!s);if(o&&!r){const t=e.indexOf("{}");e=t>=0?e.slice(0,t)+o+e.slice(t+2):`${e}${e?" ":""}${o}`}this._decorTextDialog={id:t.id,x:t.x,y:t.y,text:e,color:Rt(t.color,this._decorStyle.color),opacity:ra(t.opacity,this._decorStyle.opacity),angle:this._angleField(t.angle),sizeCm:this._decorTextSizeCm(t),pickerEntity:t.entity||"",preserveLegacy:r||void 0},this._decorTextSelection={start:e.length,end:e.length}}_decorRememberTextSelection(t){this._decorTextSelection={start:t.selectionStart??t.value.length,end:t.selectionEnd??t.value.length}}_decorInsertLiveVariable(t){const e=this._decorTextDialog;if(!e)return;const i=Xi(e.pickerEntity,t);if(!i)return;const s=e.text,n=Math.max(0,Math.min(s.length,this._decorTextSelection.start)),o=Math.max(n,Math.min(s.length,this._decorTextSelection.end));if(s.length-(o-n)+i.length>200)return;const r=s.slice(0,n)+i+s.slice(o),a=n+i.length;this._decorTextSelection={start:a,end:a},this._decorTextDialog={...e,text:r,preserveLegacy:void 0},this.updateComplete.then(()=>{const t=this.renderRoot.querySelector("textarea.dtarea");t&&(t.focus(),t.setSelectionRange(a,a))})}_decorSaveText(){const t=this._decorTextDialog,e=String(t?.text??"").replace(/\r\n?/g,"\n").trim();if(!t||!e)return void(this._decorTextDialog=null);const i=this._geometrySnapshot(),s=this._curSpaceCfg,n={color:t.color,opacity:ra(t.opacity),size_cm:Number(Math.max(.1,Math.min(Yg,t.sizeCm)).toFixed(4)),...aa(t.angle)?{angle:aa(t.angle)}:{}};if(t.id)s.decor=this._decorList.map(i=>{if(i.id!==t.id)return i;if("text"!==i.kind)return i;if(t.preserveLegacy){const{angle:t,size:s,scale:o,...r}=i;return{...r,text:e,...n}}const{entity:s,attr:o,unit:r,...a}=i,{angle:l,size:c,scale:h,...d}=a;return{...d,text:e,...n}});else{const i="dc"+Date.now().toString(36)+Math.random().toString(36).slice(2,5);s.decor=[...this._decorList,{id:i,kind:"text",x:t.x,y:t.y,text:e,...n}],this._decorSel=i}this._decorTextDialog=null,this._recordGeometry(this._t(t.id?"history.decor_edit":"history.decor_add"),i),this._saveConfig(),this.requestUpdate()}_decorSaveShape(){const t=this._decorShapeDialog;if(!t)return;const e=this._geometrySnapshot(),i={color:t.color,opacity:ra(t.opacity),widthCm:Math.max(.1,Math.min(100,Number(t.widthCm)||.1)),fill:!!t.fill,fillColor:t.fillColor||t.color,fillOpacity:ra(t.fillOpacity,.25)};this._curSpaceCfg.decor=this._decorList.map(e=>{if(e.id!==t.id)return e;const s="rect"===t.kind||"ellipse"===t.kind,n=pa(i,s);if("line"===e.kind){const i=(e.x1+e.x2)/2*pm,s=(e.y1+e.y2)/2*this._decorH,o=ca(Math.max(.1,Number(t.lengthCm)||.1),this._cellCm,this._gridPitch),r=aa(t.angle)*Math.PI/180,a=Math.cos(r)*o/2,l=Math.sin(r)*o/2,c=this._snap([i-a,s-l]),h=this._snap([i+a,s+l]),{width:d,line_style:p,...u}=e;return{...u,...n,x1:Cc(c[0]/pm),y1:Cc(c[1]/this._decorH),x2:Cc(h[0]/pm),y2:Cc(h[1]/this._decorH),..."dashed"===t.lineStyle?{line_style:"dashed"}:{}}}if("rect"===e.kind||"ellipse"===e.kind||"furniture"===e.kind){const i=e.w*pm,s=e.h*this._decorH,o=Math.max(this._gridPitch,ai(ca(Number(t.sizeWCm),this._cellCm,this._gridPitch),this._gridPitch)),r=Math.max(this._gridPitch,ai(ca(Number(t.sizeHCm),this._cellCm,this._gridPitch),this._gridPitch)),a=e.x*pm+i/2,l=e.y*this._decorH+s/2,c=aa(t.angle),h=la({x:a-o/2,y:l-r/2},c,t=>this._snap(t)),{width:d,angle:p,...u}=e;return{...u,...n,x:Cc(h[0]/pm),y:Cc(h[1]/this._decorH),w:o/pm,h:r/this._decorH,..."furniture"===e.kind&&t.symbol?{symbol:t.symbol}:{},...c?{angle:c}:{}}}return e}),this._decorStyle={...i,fill:"rect"===t.kind||"ellipse"===t.kind?i.fill:this._decorStyle.fill,fillColor:"rect"===t.kind||"ellipse"===t.kind?i.fillColor:this._decorStyle.fillColor,fillOpacity:"rect"===t.kind||"ellipse"===t.kind?i.fillOpacity:this._decorStyle.fillOpacity},this._decorShapeDialog=null,this._recordGeometry(this._t("history.decor_edit"),e),this._saveConfig(),this.requestUpdate()}get _dtSel(){return"decor"===this._mode&&"select"===this._decorTool&&this._decorSel&&this._decorList.find(t=>t.id===this._decorSel)||null}_dtPivot(t){return"line"===t.kind?[(t.x1+t.x2)/2*pm,(t.y1+t.y2)/2*this._decorH]:"furniture"===t.kind||"rect"===t.kind||"ellipse"===t.kind?[(t.x+t.w/2)*pm,(t.y+t.h/2)*this._decorH]:[t.x*pm,t.y*this._decorH]}_dtApply(t,e){const i=this._curSpaceCfg;i&&(i.decor=this._decorList.map(i=>{if(i.id!==t)return i;const s={...i};"text"===i.kind&&void 0!==e.textSizeCm&&(delete s.size,delete s.scale);const n={...s};return void 0!==e.textSizeCm&&(n.size_cm=Number(Math.max(.1,Math.min(Yg,e.textSizeCm)).toFixed(4))),void 0!==e.angle&&(e.angle?n.angle=Number(e.angle.toFixed(2)):delete n.angle),n}),this._cfgEpoch++,this.requestUpdate())}_dtStart(t,e,i,s){const n=this._dtSel;if(!n)return;t.stopPropagation(),t.preventDefault();const[o,r]=this._dtPivot(n),a=this._svgPoint(t),l=this._decorBoxOf(n);this._dtDrag={id:n.id,kind:e,pid:t.pointerId,ax:o,ay:r,r0:Math.hypot(a[0]-o,a[1]-r),a0:180*Math.atan2(a[1]-r,a[0]-o)/Math.PI,textSizeCm0:"text"===n.kind?this._decorTextSizeCm(n):1,angle0:"line"===n.kind?0:Number(n.angle)||0,sgx:i?.[0],sgy:i?.[1],orig:l||void 0,origShape:JSON.parse(JSON.stringify(n)),before:this._geometrySnapshot(),lineEnd:s,moved:!1},bm(t)}_dtMove(t){const e=this._dtDrag;if(!e)return;const i=this._svgPoint(t);if(void 0!==e.lineEnd&&"line"===e.origShape.kind){const s=this._decorSnap(i,t.pointerType,e.id),n=Cc(s[0]/pm),o=Cc(s[1]/this._decorH),r=e.origShape,a=0===e.lineEnd?r.x1:r.x2,l=0===e.lineEnd?r.y1:r.y2;return(Math.abs(n-a)>1e-9||Math.abs(o-l)>1e-9)&&(e.moved=!0),void this._replaceDecor(e.id,0===e.lineEnd?{x1:n,y1:o}:{x2:n,y2:o})}if("scale"===e.kind&&e.orig){const s=ga(e.orig,e.sgx??1,e.sgy??1,i[0],i[1],!t.shiftKey,this._gridPitch,this._gridPitch),n=Math.abs(s.x-e.orig.x)>1e-6||Math.abs(s.y-e.orig.y)>1e-6||Math.abs(s.w-e.orig.w)>1e-6||Math.abs(s.h-e.orig.h)>1e-6;if(!n&&!e.moved)return;return e.moved||=n,void this._decorApplyBox(e.id,s)}if("scale"===e.kind){const t=Math.hypot(i[0]-e.ax,i[1]-e.ay);if(e.r0<1e-6)return;const s=Math.max(.1,Math.min(Yg,e.textSizeCm0*(t/e.r0))),n=Math.abs(s-e.textSizeCm0)>1e-6;if(!n&&!e.moved)return;return e.moved||=n,void this._dtApply(e.id,{textSizeCm:s})}const s=180*Math.atan2(i[1]-e.ay,i[0]-e.ax)/Math.PI;let n=e.angle0+(s-e.a0);t.shiftKey||(n=5*Math.round(n/5)),n=(n%360+360)%360,n>180&&(n-=360);const o=Math.abs(n-e.angle0)>1e-6;(o||e.moved)&&(e.moved||=o,this._dtApply(e.id,{angle:n}))}_dtUp(){const t=this._dtDrag;this._dtDrag=null,t?.moved&&(this._recordGeometry(this._t("history.decor_transform"),t.before),this._saveConfig()),this.requestUpdate()}_dtMeasure(){const t=this._dtSel;if(!t)return void(this._dtBox&&(this._dtBox=null,this.requestUpdate()));let e;if("line"===t.kind){const i=t.x1*pm,s=t.y1*this._decorH,n=t.x2*pm,o=t.y2*this._decorH;e={id:t.id,x:Math.min(i,n),y:Math.min(s,o),w:Math.abs(n-i),h:Math.abs(o-s)}}else if("furniture"===t.kind||"rect"===t.kind||"ellipse"===t.kind)e={id:t.id,x:t.x*pm,y:t.y*this._decorH,w:t.w*pm,h:t.h*this._decorH};else{const i=this.renderRoot.querySelector(`text.dtext[data-id="${t.id}"]`);if(!i||"function"!=typeof i.getBBox)return;let s;try{s=i.getBBox()}catch{return}if(!s||!s.width&&!s.height)return;e={id:t.id,x:s.x,y:s.y,w:s.width,h:s.height}}const i=this._dtBox;i&&i.id===e.id&&Math.abs(i.x-e.x)<.01&&Math.abs(i.y-e.y)<.01&&Math.abs(i.w-e.w)<.01&&Math.abs(i.h-e.h)<.01||(this._dtBox=e,this.requestUpdate())}_deleteDecor(t){if(!this._decorList.some(e=>e.id===t))return;const e=this._geometrySnapshot();this._curSpaceCfg.decor=this._decorList.filter(e=>e.id!==t),this._decorSel===t&&(this._decorSel=null),this._recordGeometry(this._t("history.decor_delete"),e),this._saveConfig(),this.requestUpdate()}_decorDeleteSel(){this._decorSel&&this._deleteDecor(this._decorSel)}_confirmDecorErase(){const t=this._decorEraseConfirm;this._decorEraseConfirm=null,t&&this._deleteDecor(t.id)}get _furnWalls(){const t=this._rawPhysicalBodiesR().flatMap(t=>t.map((e,i)=>{const s=t[(i+1)%t.length];return[e[0],e[1],s[0],s[1]]}));return[...this._segments,...t]}get _furnWallReach(){return 6*this._gridPitch}_furnFieldValue(t){return Math.round(100*(this._imperial?t/30.48:t/100))/100}_furnFieldToCm(t){return e=this._imperial?30.48*t:100*t,Number.isFinite(e)?Math.max(1,Math.min(1e4,e)):1;var e}_furnPick(t){const e=function(t){const e=Vc(t);return e?{w:e.w,h:e.h}:{w:60,h:60}}(t);this._furnPalette={symbol:t,w:e.w,h:e.h}}_furnPlace(t,e=!1){const i=this._furnPalette,s=this._curSpaceCfg;if(!i||!s)return;const n=pm,o=this._decorH,r=Zc(Yc(i.w,this._cellCm,this._gridPitch,n)),a=Zc(Yc(i.h,this._cellCm,this._gridPitch,n)),l=this._geometrySnapshot(),c=this._decorSnap(t);let h=c[0],d=c[1],p=0;const u=e?null:ih(h,d,a*o,this._furnWalls,this._furnWallReach,this._gridPitch);u&&(h=u.cx,d=u.cy,p=u.angle);const _="df"+Date.now().toString(36)+Math.random().toString(36).slice(2,5),g={id:_,kind:"furniture",symbol:i.symbol,x:Cc(h/n-r/2),y:Cc(d/o-a/2),w:r,h:a,...pa(this._decorStyle,!1)};p&&(g.angle=Number(p.toFixed(2))),s.decor=[...this._decorList,g],this._decorSel=_,this._decorTool="select",this._furnPalette=null,this._recordGeometry(this._t("history.decor_add"),l),this._saveConfig(),this.requestUpdate()}_furnMoveUpdate(t){const e=this._decorMove;if("furniture"!==e.orig.kind)return;const i=e.orig,s=this._curSpaceCfg;if(!s)return;const n=pm,o=this._decorH,r=this._svgPoint(t),a=(i.x+i.w/2)*n+(r[0]-e.start[0]),l=(i.y+i.h/2)*o+(r[1]-e.start[1]);let c,h,d=Number(i.angle)||0;const p=t.shiftKey?null:ih(a,l,i.h*o,this._furnWalls,this._furnWallReach,this._gridPitch);if(p)c=p.cx/n-i.w/2,h=p.cy/o-i.h/2,d=p.angle;else{const s=this._decorSnap([a-i.w/2*n,l-i.h/2*o],t.pointerType,e.id);c=s[0]/n,h=s[1]/o}c=Cc(c),h=Cc(h),(Math.abs(c-i.x)>1e-9||Math.abs(h-i.y)>1e-9||Math.abs(d-(Number(i.angle)||0))>1e-9)&&(e.moved=!0),s.decor=this._decorList.map(t=>{if(t.id!==e.id)return t;const i={...t,x:c,y:h};return d?i.angle=Number(d.toFixed(2)):delete i.angle,i}),this.requestUpdate()}_decorApplyBox(t,e){const i=this._curSpaceCfg;if(!i)return;const s=pm,n=this._decorH;i.decor=this._decorList.map(i=>{if(i.id!==t)return i;const o=la(e,i.angle,t=>this._snap(t));return{...i,x:Cc(o[0]/s),y:Cc(o[1]/n),w:Math.max(this._gridPitch/s,Math.min(2*yc,e.w/s)),h:Math.max(this._gridPitch/n,Math.min(2*yc,e.h/n))}}),this._cfgEpoch++,this.requestUpdate()}get _furnLive(){const t=this._dtDrag;if(!t||"scale"!==t.kind||!t.orig)return null;const e=this._decorList.find(e=>e.id===t.id);if(!e||"furniture"!==e.kind)return null;const i=pm,s=this._decorH,n=e.w*i,o=e.h*s,r=function(t,e,i,s,n){const o=t+i/2,r=e+s/2,a=(Number(n)||0)*Math.PI/180,l=Math.cos(a),c=Math.sin(a),h=(t,e)=>{const i=t-o,s=e-r;return[o+i*l-s*c,r+i*c+s*l]};return[h(t,e),h(t+i,e),h(t+i,e+s),h(t,e+s)]}(e.x*i,e.y*s,n,o,Number(e.angle)||0),a=(t,e)=>[(t[0]+e[0])/2,(t[1]+e[1])/2],l=a(r[0],r[1]),c=a(r[0],r[3]);return[{x:l[0],y:l[1],text:this._fmtLen([0,0],[n,0])},{x:c[0],y:c[1],text:this._fmtLen([0,0],[0,o])}]}_renderFurnPalette(){const t=this._furnPalette,e=this._t(this._imperial?"gs.unit_ft":"gs.unit_m");return W`
t.stopPropagation()}> + @lostpointercapture=${t=>this._rszPointerCancel(t)}>`),o.push(j``)}return j`${o}`}get _openingsR(){const t=this._curSpaceCfg,e=this._spaceH,i=this._spaceModel();return i?(t?.openings||[]).flatMap(t=>{const s={...t,rx:t.x*um,ry:t.y*e,rlen:t.length*um};if(!t.host)return[s];const n=Rd(t,i.partitions,um,this._cellCm,this._gridPitch);if(!n.resolved)return"plan"===this._mode?[{...s,orphanReason:n.reason||"invalid-host"}]:[];let[o,a]=n.resolved.center;const r=this._physicalDrag;return r?.moved&&"partition"===r.kind&&r.id===t.host.id&&(o+=r.delta[0],a+=r.delta[1]),[{...t,rx:o,ry:a,rlen:n.resolved.length,angle:n.resolved.angle,partitionHost:n.resolved}]}):[]}_partitionOpeningCuts(t=this._spaceModel(),e=()=>!0){if(!t)return[];return $_(x_(this._curSpaceCfg?.id===t.id?this._curSpaceCfg:null,t,this._cellCm,this._gridPitch,um),e)}_roomWallOpeningInputs(t=this._openingsR,e=this._spaceModel()){if(!e)return[];const i=this._openPairs().flatMap(t=>t.segs);return S_(t,e,this._spaceWalls,i,this._wallKeyPitch,this._cellCm,this._gridPitch,um)}_openingFace(t,e,i){return t.partitionHost?Ed(t.partitionHost,i):zl(e,{x:t.rx,y:t.ry,angle:t.angle,length:t.rlen,flip_v:i})}_cmToUnits(t){return t/this._cellCm*this._gridPitch}get _decorList(){const t=this._curSpaceCfg;return Array.isArray(t?.decor)?t.decor:[]}get _decorH(){return um}_decorResolvedStyle(t){return function(t,e,i,s=or){const n="rect"===t?.kind||"ellipse"===t?.kind,o=t,a=Rt(o?.color,s.color);return{color:a,opacity:ar(o?.opacity,s.opacity),widthCm:dr(t,e,i,s.widthCm),fill:!!n&&!0===o?.fill,fillColor:Rt(o?.fill_color,o?.fill?a:s.fillColor),fillOpacity:n&&o?.fill?ar(o?.fill_opacity,.25):s.fillOpacity}}(t,this._cellCm,this._gridPitch,or)}_decorWidthUnits(t){return((t,e,i,s=or.widthCm)=>{const n=Number(t?.width_cm);if(Number.isFinite(n)&&n>0)return cr(n,e,i);const o=Number(t?.width);return Number.isFinite(o)&&o>0?o:cr(s,e,i)})(t,this._cellCm,this._gridPitch,or.widthCm)}_decorTextSizeCm(t){if("text"===t?.kind){const e=Number(t.size_cm);return Number.isFinite(e)&&e>0?e:hr(es*is(t),this._cellCm,this._gridPitch)}return hr(es,this._cellCm,this._gridPitch)}_decorTextUnits(t){if("text"!==t.kind)return es;const e=Number(t.size_cm);return Number.isFinite(e)&&e>0?cr(e,this._cellCm,this._gridPitch):es*is(t)}_decorSmallField(t){return Math.round(100*(this._imperial?t/2.54:t))/100}_decorSmallCm(t){const e=this._imperial?2.54*t:t;return Number.isFinite(e)?Math.max(.1,Math.min(100,e)):.1}_decorTextCm(t){const e=this._imperial?2.54*t:t;return Number.isFinite(e)?Math.max(.1,Math.min(Xg,e)):.1}_decorLargeField(t){return Math.round(100*(this._imperial?t/30.48:t/100))/100}_decorLargeCm(t){const e=this._imperial?30.48*t:100*t;return Number.isFinite(e)?Math.max(.1,Math.min(bc*this._cellCm,e)):.1}_angleField(t){const e=Number(t);return Number.isFinite(e)?String(Number(e.toFixed(3))):"0"}_decorBoxOf(t){return"rect"!==t.kind&&"ellipse"!==t.kind&&"furniture"!==t.kind?null:{x:t.x*um,y:t.y*this._decorH,w:t.w*um,h:t.h*this._decorH,angle:rr(t.angle)||void 0}}_decorSnapGeometry(t){const e=this._spaceModel();if(!e)return{points:[],segments:[]};const i=t||"",s=this._decorSnapCache;if(s&&s.epoch===this._cfgEpoch&&s.space===this._space&&s.height===this._decorH&&s.exclude===i)return s.geometry;const n=[];for(const e of this._decorList)if(e.id!==t)if("line"===e.kind){const t=[e.x1*um,e.y1*this._decorH],i=[e.x2*um,e.y2*this._decorH];n.push({points:[t,i,[(t[0]+i[0])/2,(t[1]+i[1])/2]],segments:[{a:t,b:i}]})}else if("text"===e.kind)n.push({points:[[e.x*um,e.y*this._decorH]],segments:[]});else{const t=this._decorBoxOf(e);t&&n.push(_r(t))}for(const t of e.rooms){const e=hi(t);e?.length&&n.push({points:e.flatMap((t,i)=>{const s=e[(i+1)%e.length];return[t,[(t[0]+s[0])/2,(t[1]+s[1])/2]]}),segments:e.map((t,i)=>({a:t,b:e[(i+1)%e.length]}))})}const o=function(t){return{points:t.flatMap(t=>t.points),segments:t.flatMap(t=>t.segments)}}(n);return this._decorSnapCache={epoch:this._cfgEpoch,space:this._space,height:this._decorH,exclude:i,geometry:o},o}_decorSnap(t,e="mouse",i){const s=this._stageEl,n=this._viewOr(this._baseVb()),o="touch"===e||"pen"===e?14:8,a=s?n.w/Math.max(1,s.clientWidth)*o:this._gridPitch;return function(t,e,i,s){const n=s(t);let o=null;for(const n of e.points){const e=s(n),a=Math.hypot(e[0]-t[0],e[1]-t[1]);a<=i&&(!o||athis._snap(t)).point}_replaceDecor(t,e){const i=this._curSpaceCfg;i&&(i.decor=this._decorList.map(i=>i.id===t?{...i,...e}:i),this.requestUpdate())}_cancelDecorGesture(){const t=this._decorMove?.before||this._dtDrag?.before||this._bdDrag?.before,e=t&&this._serverCfg?.spaces.find(e=>e.id===t.spaceId);if(t&&e){const i=t=>JSON.parse(JSON.stringify(t));void 0!==t.decor?e.decor=i(t.decor):delete e.decor;for(const t of["plan_x","plan_y","plan_scale","plan_scale_x","plan_scale_y","plan_angle"])delete e[t];Object.assign(e,i(t.plan_transform||{})),this._cfgEpoch++}this._decorMove=null,this._dtDrag=null,this._bdDrag=null,this.requestUpdate()}_decorPointerDown(t){const e=this._decorTool;if("select"===e||"erase"===e?t.target.closest?.(".dshape"):null)return!0;if("line"===e||"rect"===e||"ellipse"===e){t.preventDefault();const i=this._decorSnap(this._svgPoint(t),t.pointerType);return this._decorDraft={kind:e,a:i,b:i,pid:t.pointerId},wm(t),!0}if("text"===e){const e=this._decorSnap(this._svgPoint(t),t.pointerType);return this._decorTextDialog={x:Dc(e[0]/um),y:Dc(e[1]/this._decorH),text:"",color:this._decorStyle.color,opacity:this._decorStyle.opacity,angle:"0",sizeCm:hr(es,this._cellCm,this._gridPitch)},this._decorTextSelection={start:0,end:0},!0}if("furniture"===e)return!!this._furnPalette&&(t.preventDefault(),this._furnPlace(this._svgPoint(t),t.shiftKey),!0);if("select"===e&&(this._decorSel=null),this._bdMovable){const e=this._bdRect,i=this._svgPoint(t),s=e.x+e.w/2,n=e.y+e.h/2,o=-rr(e.angle)*Math.PI/180,a=i[0]-s,r=i[1]-n,l=[s+a*Math.cos(o)-r*Math.sin(o),n+a*Math.sin(o)+r*Math.cos(o)];if(l[0]>=e.x&&l[0]<=e.x+e.w&&l[1]>=e.y&&l[1]<=e.y+e.h)return t.preventDefault(),this._bdStart(t)}return!1}_decorCommitDraft(){const t=this._decorDraft;if(this._decorDraft=null,!t)return;const e=.5*this._gridPitch;if(!function(t,e,i,s){const n=Math.abs(i[0]-e[0]),o=Math.abs(i[1]-e[1]);return"line"===t?Math.hypot(n,o)>=s:n>=s&&o>=s}(t.kind,t.a,t.b,e))return;const i=um,s=this._decorH,n=this._decorStyle,o=this._geometrySnapshot(),a="dc"+Date.now().toString(36)+Math.random().toString(36).slice(2,5),r=Dc;let l;if("line"===t.kind)l={id:a,kind:"line",x1:r(t.a[0]/i),y1:r(t.a[1]/s),x2:r(t.b[0]/i),y2:r(t.b[1]/s),...pr(n,!1)};else{const e=r(Math.min(t.a[0],t.b[0])/i),o=r(Math.min(t.a[1],t.b[1])/s),c=Math.abs(t.b[0]-t.a[0])/i,h=Math.abs(t.b[1]-t.a[1])/s;l={id:a,kind:t.kind,x:e,y:o,w:c,h:h,...pr(n,!0)}}this._curSpaceCfg.decor=[...this._decorList,l],this._decorSel=a,this._recordGeometry(this._t("history.decor_add"),o),this._saveConfig(),this.requestUpdate()}_decorShapeDown(t,e){if("decor"!==this._mode)return;const i=this._decorTool;if("text"===i){if("text"!==e.kind)return;return t.stopPropagation(),t.preventDefault(),void this._decorOpenText(e)}"select"!==i&&"erase"!==i||(t.stopPropagation(),t.preventDefault(),"erase"!==i?(this._decorSel=e.id,this._decorMove={id:e.id,start:this._svgPoint(t),orig:JSON.parse(JSON.stringify(e)),pid:t.pointerId,moved:!1,before:this._geometrySnapshot()},wm(t)):this._decorEraseConfirm={id:e.id,kind:e.kind})}_decorMoveUpdate(t){const e=this._decorMove;if("furniture"===e.orig?.kind)return void this._furnMoveUpdate(t);const i=this._svgPoint(t),s=e.orig,n=("line"===s.kind?s.x1:s.x)*um,o=("line"===s.kind?s.y1:s.y)*this._decorH,a=this._decorSnap([n+(i[0]-e.start[0]),o+(i[1]-e.start[1])],t.pointerType,e.id);let r=(a[0]-n)/um,l=(a[1]-o)/this._decorH;const c=e.orig,h="line"===c.kind?Math.min(c.x1,c.x2):c.x,d="line"===c.kind?Math.min(c.y1,c.y2):c.y,p="line"===c.kind?Math.abs(c.x2-c.x1):c.w||0,u="line"===c.kind?Math.abs(c.y2-c.y1):c.h||0,_=bc;r=Math.max(-_-h,Math.min(_-h-p,r)),l=Math.max(-_-d,Math.min(_-d-u,l)),(r||l)&&(e.moved=!0);this._curSpaceCfg.decor=this._decorList.map(t=>{if(t.id!==e.id)return t;const i=e.orig;return"line"===t.kind?{...t,x1:i.x1+r,y1:i.y1+l,x2:i.x2+r,y2:i.y2+l}:{...t,x:i.x+r,y:i.y+l}}),this.requestUpdate()}_decorShapeDbl(t,e){"decor"===this._mode&&"select"===this._decorTool&&(t.preventDefault(),t.stopPropagation(),this._decorMove=null,this._decorSel=e.id,this._openDecorProperties(e))}_openDecorProperties(t){if("decor"!==this._mode||"select"!==this._decorTool)return;if("text"===t.kind)return void this._decorOpenText(t);if(!["line","rect","ellipse","furniture"].includes(t.kind))return;const e=this._decorResolvedStyle(t),i="line"===t.kind?t:null,s=this._decorBoxOf(t);this._decorShapeDialog={id:t.id,kind:t.kind,color:e.color,opacity:e.opacity,widthCm:e.widthCm,angle:this._angleField(rr(i?Os([i.x1*um,i.y1*this._decorH],[i.x2*um,i.y2*this._decorH]):t.angle)),...i?{lengthCm:hr(Math.hypot((i.x2-i.x1)*um,(i.y2-i.y1)*this._decorH),this._cellCm,this._gridPitch),lineStyle:"dashed"===i.line_style?"dashed":"solid"}:{},...s?{sizeWCm:hr(s.w,this._cellCm,this._gridPitch),sizeHCm:hr(s.h,this._cellCm,this._gridPitch)}:{},..."furniture"===t.kind?{symbol:t.symbol}:{},..."rect"===t.kind||"ellipse"===t.kind?{fill:e.fill,fillColor:e.fillColor,fillOpacity:e.fillOpacity}:{}}}_decorOpenText(t){if("text"!==t.kind)return;let e=String(t.text??"");const i=[...e.matchAll(/\{([^{}\r\n]+)\}/g)].some(t=>!!Yi(t[1])),s=String(t.unit??"").trim(),n="state"===String(t.attr??"").trim().toLowerCase()?null:t.attr,o=i||s?"":Xi(t.entity,n),a=!(!String(t.entity??"").trim()||i||o&&!s);if(o&&!a){const t=e.indexOf("{}");e=t>=0?e.slice(0,t)+o+e.slice(t+2):`${e}${e?" ":""}${o}`}this._decorTextDialog={id:t.id,x:t.x,y:t.y,text:e,color:Rt(t.color,this._decorStyle.color),opacity:ar(t.opacity,this._decorStyle.opacity),angle:this._angleField(t.angle),sizeCm:this._decorTextSizeCm(t),pickerEntity:t.entity||"",preserveLegacy:a||void 0},this._decorTextSelection={start:e.length,end:e.length}}_decorRememberTextSelection(t){this._decorTextSelection={start:t.selectionStart??t.value.length,end:t.selectionEnd??t.value.length}}_decorInsertLiveVariable(t){const e=this._decorTextDialog;if(!e)return;const i=Xi(e.pickerEntity,t);if(!i)return;const s=e.text,n=Math.max(0,Math.min(s.length,this._decorTextSelection.start)),o=Math.max(n,Math.min(s.length,this._decorTextSelection.end));if(s.length-(o-n)+i.length>200)return;const a=s.slice(0,n)+i+s.slice(o),r=n+i.length;this._decorTextSelection={start:r,end:r},this._decorTextDialog={...e,text:a,preserveLegacy:void 0},this.updateComplete.then(()=>{const t=this.renderRoot.querySelector("textarea.dtarea");t&&(t.focus(),t.setSelectionRange(r,r))})}_decorSaveText(){const t=this._decorTextDialog,e=String(t?.text??"").replace(/\r\n?/g,"\n").trim();if(!t||!e)return void(this._decorTextDialog=null);const i=this._geometrySnapshot(),s=this._curSpaceCfg,n={color:t.color,opacity:ar(t.opacity),size_cm:Number(Math.max(.1,Math.min(Xg,t.sizeCm)).toFixed(4)),...rr(t.angle)?{angle:rr(t.angle)}:{}};if(t.id)s.decor=this._decorList.map(i=>{if(i.id!==t.id)return i;if("text"!==i.kind)return i;if(t.preserveLegacy){const{angle:t,size:s,scale:o,...a}=i;return{...a,text:e,...n}}const{entity:s,attr:o,unit:a,...r}=i,{angle:l,size:c,scale:h,...d}=r;return{...d,text:e,...n}});else{const i="dc"+Date.now().toString(36)+Math.random().toString(36).slice(2,5);s.decor=[...this._decorList,{id:i,kind:"text",x:t.x,y:t.y,text:e,...n}],this._decorSel=i}this._decorTextDialog=null,this._recordGeometry(this._t(t.id?"history.decor_edit":"history.decor_add"),i),this._saveConfig(),this.requestUpdate()}_decorSaveShape(){const t=this._decorShapeDialog;if(!t)return;const e=this._geometrySnapshot(),i={color:t.color,opacity:ar(t.opacity),widthCm:Math.max(.1,Math.min(100,Number(t.widthCm)||.1)),fill:!!t.fill,fillColor:t.fillColor||t.color,fillOpacity:ar(t.fillOpacity,.25)};this._curSpaceCfg.decor=this._decorList.map(e=>{if(e.id!==t.id)return e;const s="rect"===t.kind||"ellipse"===t.kind,n=pr(i,s);if("line"===e.kind){const i=(e.x1+e.x2)/2*um,s=(e.y1+e.y2)/2*this._decorH,o=cr(Math.max(.1,Number(t.lengthCm)||.1),this._cellCm,this._gridPitch),a=rr(t.angle)*Math.PI/180,r=Math.cos(a)*o/2,l=Math.sin(a)*o/2,c=this._snap([i-r,s-l]),h=this._snap([i+r,s+l]),{width:d,line_style:p,...u}=e;return{...u,...n,x1:Dc(c[0]/um),y1:Dc(c[1]/this._decorH),x2:Dc(h[0]/um),y2:Dc(h[1]/this._decorH),..."dashed"===t.lineStyle?{line_style:"dashed"}:{}}}if("rect"===e.kind||"ellipse"===e.kind||"furniture"===e.kind){const i=e.w*um,s=e.h*this._decorH,o=Math.max(this._gridPitch,ri(cr(Number(t.sizeWCm),this._cellCm,this._gridPitch),this._gridPitch)),a=Math.max(this._gridPitch,ri(cr(Number(t.sizeHCm),this._cellCm,this._gridPitch),this._gridPitch)),r=e.x*um+i/2,l=e.y*this._decorH+s/2,c=rr(t.angle),h=lr({x:r-o/2,y:l-a/2},c,t=>this._snap(t)),{width:d,angle:p,...u}=e;return{...u,...n,x:Dc(h[0]/um),y:Dc(h[1]/this._decorH),w:o/um,h:a/this._decorH,..."furniture"===e.kind&&t.symbol?{symbol:t.symbol}:{},...c?{angle:c}:{}}}return e}),this._decorStyle={...i,fill:"rect"===t.kind||"ellipse"===t.kind?i.fill:this._decorStyle.fill,fillColor:"rect"===t.kind||"ellipse"===t.kind?i.fillColor:this._decorStyle.fillColor,fillOpacity:"rect"===t.kind||"ellipse"===t.kind?i.fillOpacity:this._decorStyle.fillOpacity},this._decorShapeDialog=null,this._recordGeometry(this._t("history.decor_edit"),e),this._saveConfig(),this.requestUpdate()}get _dtSel(){return"decor"===this._mode&&"select"===this._decorTool&&this._decorSel&&this._decorList.find(t=>t.id===this._decorSel)||null}_dtPivot(t){return"line"===t.kind?[(t.x1+t.x2)/2*um,(t.y1+t.y2)/2*this._decorH]:"furniture"===t.kind||"rect"===t.kind||"ellipse"===t.kind?[(t.x+t.w/2)*um,(t.y+t.h/2)*this._decorH]:[t.x*um,t.y*this._decorH]}_dtApply(t,e){const i=this._curSpaceCfg;i&&(i.decor=this._decorList.map(i=>{if(i.id!==t)return i;const s={...i};"text"===i.kind&&void 0!==e.textSizeCm&&(delete s.size,delete s.scale);const n={...s};return void 0!==e.textSizeCm&&(n.size_cm=Number(Math.max(.1,Math.min(Xg,e.textSizeCm)).toFixed(4))),void 0!==e.angle&&(e.angle?n.angle=Number(e.angle.toFixed(2)):delete n.angle),n}),this._cfgEpoch++,this.requestUpdate())}_dtStart(t,e,i,s){const n=this._dtSel;if(!n)return;t.stopPropagation(),t.preventDefault();const[o,a]=this._dtPivot(n),r=this._svgPoint(t),l=this._decorBoxOf(n);this._dtDrag={id:n.id,kind:e,pid:t.pointerId,ax:o,ay:a,r0:Math.hypot(r[0]-o,r[1]-a),a0:180*Math.atan2(r[1]-a,r[0]-o)/Math.PI,textSizeCm0:"text"===n.kind?this._decorTextSizeCm(n):1,angle0:"line"===n.kind?0:Number(n.angle)||0,sgx:i?.[0],sgy:i?.[1],orig:l||void 0,origShape:JSON.parse(JSON.stringify(n)),before:this._geometrySnapshot(),lineEnd:s,moved:!1},wm(t)}_dtMove(t){const e=this._dtDrag;if(!e)return;const i=this._svgPoint(t);if(void 0!==e.lineEnd&&"line"===e.origShape.kind){const s=this._decorSnap(i,t.pointerType,e.id),n=Dc(s[0]/um),o=Dc(s[1]/this._decorH),a=e.origShape,r=0===e.lineEnd?a.x1:a.x2,l=0===e.lineEnd?a.y1:a.y2;return(Math.abs(n-r)>1e-9||Math.abs(o-l)>1e-9)&&(e.moved=!0),void this._replaceDecor(e.id,0===e.lineEnd?{x1:n,y1:o}:{x2:n,y2:o})}if("scale"===e.kind&&e.orig){const s=gr(e.orig,e.sgx??1,e.sgy??1,i[0],i[1],!t.shiftKey,this._gridPitch,this._gridPitch),n=Math.abs(s.x-e.orig.x)>1e-6||Math.abs(s.y-e.orig.y)>1e-6||Math.abs(s.w-e.orig.w)>1e-6||Math.abs(s.h-e.orig.h)>1e-6;if(!n&&!e.moved)return;return e.moved||=n,void this._decorApplyBox(e.id,s)}if("scale"===e.kind){const t=Math.hypot(i[0]-e.ax,i[1]-e.ay);if(e.r0<1e-6)return;const s=Math.max(.1,Math.min(Xg,e.textSizeCm0*(t/e.r0))),n=Math.abs(s-e.textSizeCm0)>1e-6;if(!n&&!e.moved)return;return e.moved||=n,void this._dtApply(e.id,{textSizeCm:s})}const s=180*Math.atan2(i[1]-e.ay,i[0]-e.ax)/Math.PI;let n=e.angle0+(s-e.a0);t.shiftKey||(n=5*Math.round(n/5)),n=(n%360+360)%360,n>180&&(n-=360);const o=Math.abs(n-e.angle0)>1e-6;(o||e.moved)&&(e.moved||=o,this._dtApply(e.id,{angle:n}))}_dtUp(){const t=this._dtDrag;this._dtDrag=null,t?.moved&&(this._recordGeometry(this._t("history.decor_transform"),t.before),this._saveConfig()),this.requestUpdate()}_dtMeasure(){const t=this._dtSel;if(!t)return void(this._dtBox&&(this._dtBox=null,this.requestUpdate()));let e;if("line"===t.kind){const i=t.x1*um,s=t.y1*this._decorH,n=t.x2*um,o=t.y2*this._decorH;e={id:t.id,x:Math.min(i,n),y:Math.min(s,o),w:Math.abs(n-i),h:Math.abs(o-s)}}else if("furniture"===t.kind||"rect"===t.kind||"ellipse"===t.kind)e={id:t.id,x:t.x*um,y:t.y*this._decorH,w:t.w*um,h:t.h*this._decorH};else{const i=this.renderRoot.querySelector(`text.dtext[data-id="${t.id}"]`);if(!i||"function"!=typeof i.getBBox)return;let s;try{s=i.getBBox()}catch{return}if(!s||!s.width&&!s.height)return;e={id:t.id,x:s.x,y:s.y,w:s.width,h:s.height}}const i=this._dtBox;i&&i.id===e.id&&Math.abs(i.x-e.x)<.01&&Math.abs(i.y-e.y)<.01&&Math.abs(i.w-e.w)<.01&&Math.abs(i.h-e.h)<.01||(this._dtBox=e,this.requestUpdate())}_deleteDecor(t){if(!this._decorList.some(e=>e.id===t))return;const e=this._geometrySnapshot();this._curSpaceCfg.decor=this._decorList.filter(e=>e.id!==t),this._decorSel===t&&(this._decorSel=null),this._recordGeometry(this._t("history.decor_delete"),e),this._saveConfig(),this.requestUpdate()}_decorDeleteSel(){this._decorSel&&this._deleteDecor(this._decorSel)}_confirmDecorErase(){const t=this._decorEraseConfirm;this._decorEraseConfirm=null,t&&this._deleteDecor(t.id)}get _furnWalls(){const t=this._rawPhysicalBodiesR().flatMap(t=>t.map((e,i)=>{const s=t[(i+1)%t.length];return[e[0],e[1],s[0],s[1]]}));return[...this._segments,...t]}get _furnWallReach(){return 6*this._gridPitch}_furnFieldValue(t){return Math.round(100*(this._imperial?t/30.48:t/100))/100}_furnFieldToCm(t){return e=this._imperial?30.48*t:100*t,Number.isFinite(e)?Math.max(1,Math.min(1e4,e)):1;var e}_furnPick(t){const e=function(t){const e=Kc(t);return e?{w:e.w,h:e.h}:{w:60,h:60}}(t);this._furnPalette={symbol:t,w:e.w,h:e.h}}_furnPlace(t,e=!1){const i=this._furnPalette,s=this._curSpaceCfg;if(!i||!s)return;const n=um,o=this._decorH,a=Qc(Xc(i.w,this._cellCm,this._gridPitch,n)),r=Qc(Xc(i.h,this._cellCm,this._gridPitch,n)),l=this._geometrySnapshot(),c=this._decorSnap(t);let h=c[0],d=c[1],p=0;const u=e?null:sh(h,d,r*o,this._furnWalls,this._furnWallReach,this._gridPitch);u&&(h=u.cx,d=u.cy,p=u.angle);const _="df"+Date.now().toString(36)+Math.random().toString(36).slice(2,5),g={id:_,kind:"furniture",symbol:i.symbol,x:Dc(h/n-a/2),y:Dc(d/o-r/2),w:a,h:r,...pr(this._decorStyle,!1)};p&&(g.angle=Number(p.toFixed(2))),s.decor=[...this._decorList,g],this._decorSel=_,this._decorTool="select",this._furnPalette=null,this._recordGeometry(this._t("history.decor_add"),l),this._saveConfig(),this.requestUpdate()}_furnMoveUpdate(t){const e=this._decorMove;if("furniture"!==e.orig.kind)return;const i=e.orig,s=this._curSpaceCfg;if(!s)return;const n=um,o=this._decorH,a=this._svgPoint(t),r=(i.x+i.w/2)*n+(a[0]-e.start[0]),l=(i.y+i.h/2)*o+(a[1]-e.start[1]);let c,h,d=Number(i.angle)||0;const p=t.shiftKey?null:sh(r,l,i.h*o,this._furnWalls,this._furnWallReach,this._gridPitch);if(p)c=p.cx/n-i.w/2,h=p.cy/o-i.h/2,d=p.angle;else{const s=this._decorSnap([r-i.w/2*n,l-i.h/2*o],t.pointerType,e.id);c=s[0]/n,h=s[1]/o}c=Dc(c),h=Dc(h),(Math.abs(c-i.x)>1e-9||Math.abs(h-i.y)>1e-9||Math.abs(d-(Number(i.angle)||0))>1e-9)&&(e.moved=!0),s.decor=this._decorList.map(t=>{if(t.id!==e.id)return t;const i={...t,x:c,y:h};return d?i.angle=Number(d.toFixed(2)):delete i.angle,i}),this.requestUpdate()}_decorApplyBox(t,e){const i=this._curSpaceCfg;if(!i)return;const s=um,n=this._decorH;i.decor=this._decorList.map(i=>{if(i.id!==t)return i;const o=lr(e,i.angle,t=>this._snap(t));return{...i,x:Dc(o[0]/s),y:Dc(o[1]/n),w:Math.max(this._gridPitch/s,Math.min(2*bc,e.w/s)),h:Math.max(this._gridPitch/n,Math.min(2*bc,e.h/n))}}),this._cfgEpoch++,this.requestUpdate()}get _furnLive(){const t=this._dtDrag;if(!t||"scale"!==t.kind||!t.orig)return null;const e=this._decorList.find(e=>e.id===t.id);if(!e||"furniture"!==e.kind)return null;const i=um,s=this._decorH,n=e.w*i,o=e.h*s,a=function(t,e,i,s,n){const o=t+i/2,a=e+s/2,r=(Number(n)||0)*Math.PI/180,l=Math.cos(r),c=Math.sin(r),h=(t,e)=>{const i=t-o,s=e-a;return[o+i*l-s*c,a+i*c+s*l]};return[h(t,e),h(t+i,e),h(t+i,e+s),h(t,e+s)]}(e.x*i,e.y*s,n,o,Number(e.angle)||0),r=(t,e)=>[(t[0]+e[0])/2,(t[1]+e[1])/2],l=r(a[0],a[1]),c=r(a[0],a[3]);return[{x:l[0],y:l[1],text:this._fmtLen([0,0],[n,0])},{x:c[0],y:c[1],text:this._fmtLen([0,0],[0,o])}]}_renderFurnPalette(){const t=this._furnPalette,e=this._t(this._imperial?"gs.unit_ft":"gs.unit_m");return W`
t.stopPropagation()}>
${this._t("furn.title")} @@ -4936,16 +4936,16 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8
- ${jc.map(e=>W` + ${Uc.map(e=>W`
${this._t(`furn.group_${e}`)}
- ${Kc(e).map(e=>W``)}
`)} @@ -4961,22 +4961,22 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8 @input=${e=>this._furnPalette={...t,h:this._furnFieldToCm(Number(e.target.value))}} /> ${this._t("furn.place_hint")}
`:W`
${this._t("furn.pick_hint")}
`} -
`}get _bdBase(){const t=this._curSpaceCfg;return t?.plan_url?{...uc(t.plan_aspect,pm)}:null}get _bdRect(){const t=this._curSpaceCfg;return t?.plan_url?mc(t,pm):null}get _bdParams(){const t=this._curSpaceCfg,e=Number(t?.plan_x),i=Number(t?.plan_y),s=Number(t?.plan_scale),n=Number(t?.plan_scale_x),o=Number(t?.plan_scale_y),r=Number.isFinite(s)&&s>0?s:1;return{dx:Number.isFinite(e)?e:0,dy:Number.isFinite(i)?i:0,sx:Number.isFinite(n)&&n>0?n:r,sy:Number.isFinite(o)&&o>0?o:r,angle:aa(t?.plan_angle)}}_openBackdropDialog(t){if(!this._bdMovable||!this._bdRect)return;t?.preventDefault(),t?.stopPropagation(),this._bdDrag=null;const e=this._bdRect;this._backdropDialog={widthCm:ha(e.w,this._cellCm,this._gridPitch),heightCm:ha(e.h,this._cellCm,this._gridPitch),angle:this._angleField(e.angle)}}_saveBackdropDialog(){const t=this._backdropDialog,e=this._bdBase,i=this._bdRect;if(!t||!e||!i)return;const s=aa(t.angle),n=this._geometrySnapshot(),o=Math.min(e.w*gc,Math.max(e.w*_c,ai(ca(t.widthCm,this._cellCm,this._gridPitch),this._gridPitch))),r=Math.min(e.h*gc,Math.max(e.h*_c,ai(ca(t.heightCm,this._cellCm,this._gridPitch),this._gridPitch))),a=la({x:i.x+i.w/2-o/2,y:i.y+i.h/2-r/2},s,t=>this._snap(t));this._bdApply((a[0]-e.x)/pm,(a[1]-e.y)/pm,o/e.w,r/e.h,s),this._backdropDialog=null,this._recordGeometry(this._t("history.backdrop_transform"),n),this._saveConfig()}get _bdActive(){return"decor"===this._mode&&!!this._bdRect&&"backdrop"===this._decorTool}get _bdMovable(){return"decor"===this._mode&&"backdrop"===this._decorTool&&!!this._bdRect}_bdApply(t,e,i,s,n){const o=this._curSpaceCfg;if(!o)return;o.plan_x=Number(Cc(t).toFixed(6)),o.plan_y=Number(Cc(e).toFixed(6)),delete o.plan_scale,o.plan_scale_x=Number(Math.min(gc,Math.max(_c,i)).toFixed(6)),o.plan_scale_y=Number(Math.min(gc,Math.max(_c,s)).toFixed(6));const r=aa(n);r?o.plan_angle=Number(r.toFixed(2)):delete o.plan_angle,this._cfgEpoch++,this.requestUpdate()}_bdStart(t,e,i=!1){const s=this._bdBase,n=this._bdRect;if(!s||!n)return!1;const o=this._svgPoint(t),r=e?e[0]:0,a=e?e[1]:0,l=r>0?n.x:n.x+n.w,c=a>0?n.y:n.y+n.h;return this._bdDrag={kind:i?"rotate":e?"scale":"move",pid:t.pointerId,sx:o[0],sy:o[1],base:s,p0:this._bdParams,fx:l,fy:c,sgx:r,sgy:a,rect0:{x:n.x,y:n.y,w:n.w,h:n.h,angle:n.angle},before:this._geometrySnapshot(),moved:!1},bm(t),!0}_bdMove(t){const e=this._bdDrag;if(!e)return;const i=this._svgPoint(t),s=e.base;if("move"===e.kind){const t=e.rect0.x,n=e.rect0.y,o=this._snap([t+(i[0]-e.sx),n+(i[1]-e.sy)]),r=Math.abs(o[0]-t)>1e-9||Math.abs(o[1]-n)>1e-9;if(!r&&!e.moved)return;return e.moved||=r,void this._bdApply((o[0]-s.x)/pm,(o[1]-s.y)/pm,e.p0.sx,e.p0.sy,e.p0.angle)}if("rotate"===e.kind){const s=e.rect0.x+e.rect0.w/2,n=e.rect0.y+e.rect0.h/2,o=180*Math.atan2(e.sy-n,e.sx-s)/Math.PI;let r=e.p0.angle+(180*Math.atan2(i[1]-n,i[0]-s)/Math.PI-o);t.shiftKey||(r=5*Math.round(r/5)),r=aa(r);const a=Math.abs(r-e.p0.angle)>1e-9;if(!a&&!e.moved)return;return e.moved||=a,void this._bdApply(e.p0.dx,e.p0.dy,e.p0.sx,e.p0.sy,r)}const n=ga(e.rect0,e.sgx,e.sgy,i[0],i[1],!t.shiftKey,this._gridPitch,Math.min(s.w,s.h)*_c),o=n.w/Math.max(1e-9,s.w),r=n.h/Math.max(1e-9,s.h),a=Math.abs(o-e.p0.sx)>1e-9||Math.abs(r-e.p0.sy)>1e-9||Math.abs(n.x-e.rect0.x)>1e-9||Math.abs(n.y-e.rect0.y)>1e-9;if(!a&&!e.moved)return;e.moved||=a;const l=la(n,e.p0.angle,t=>this._snap(t));this._bdApply((l[0]-s.x)/pm,(l[1]-s.y)/pm,o,r,e.p0.angle)}get _bdMoved(){if("decor"!==this._mode||!this._bdRect)return!1;const t=this._bdParams;return 0!==t.dx||0!==t.dy||1!==t.sx||1!==t.sy||0!==t.angle}_bdReset(){const t=this._curSpaceCfg;if(!t)return;const e=this._geometrySnapshot();delete t.plan_x,delete t.plan_y,delete t.plan_scale,delete t.plan_scale_x,delete t.plan_scale_y,delete t.plan_angle,this._bdDrag=null,this._recordGeometry(this._t("history.backdrop_transform"),e),this._saveConfig(),this._showToast(this._t("decor.backdrop_reset_done")),this.requestUpdate()}_bdUp(){const t=this._bdDrag;this._bdDrag=null,t?.moved&&(this._recordGeometry(this._t("history.backdrop_transform"),t.before),this._saveConfig()),this.requestUpdate()}get _bdLive(){if(!this._bdDrag)return null;const t=this._bdRect;return t?{x:t.x+t.w/2,y:t.y+t.h/2,text:`${this._fmtLen([0,0],[t.w,0])} × ${this._fmtLen([0,0],[0,t.h])}`}:null}_renderBackdropFrame(t){const e=this._bdRect;if(!this._bdActive||!e)return G;const i=.02*Math.max(t.w,t.h),s=i/4,n=e.x+e.w/2,o=e.y+e.h/2,r=aa(e.angle),a=2.2*i;return j` +
`}get _bdBase(){const t=this._curSpaceCfg;return t?.plan_url?{..._c(t.plan_aspect,um)}:null}get _bdRect(){const t=this._curSpaceCfg;return t?.plan_url?fc(t,um):null}get _bdParams(){const t=this._curSpaceCfg,e=Number(t?.plan_x),i=Number(t?.plan_y),s=Number(t?.plan_scale),n=Number(t?.plan_scale_x),o=Number(t?.plan_scale_y),a=Number.isFinite(s)&&s>0?s:1;return{dx:Number.isFinite(e)?e:0,dy:Number.isFinite(i)?i:0,sx:Number.isFinite(n)&&n>0?n:a,sy:Number.isFinite(o)&&o>0?o:a,angle:rr(t?.plan_angle)}}_openBackdropDialog(t){if(!this._bdMovable||!this._bdRect)return;t?.preventDefault(),t?.stopPropagation(),this._bdDrag=null;const e=this._bdRect;this._backdropDialog={widthCm:hr(e.w,this._cellCm,this._gridPitch),heightCm:hr(e.h,this._cellCm,this._gridPitch),angle:this._angleField(e.angle)}}_saveBackdropDialog(){const t=this._backdropDialog,e=this._bdBase,i=this._bdRect;if(!t||!e||!i)return;const s=rr(t.angle),n=this._geometrySnapshot(),o=Math.min(e.w*mc,Math.max(e.w*gc,ri(cr(t.widthCm,this._cellCm,this._gridPitch),this._gridPitch))),a=Math.min(e.h*mc,Math.max(e.h*gc,ri(cr(t.heightCm,this._cellCm,this._gridPitch),this._gridPitch))),r=lr({x:i.x+i.w/2-o/2,y:i.y+i.h/2-a/2},s,t=>this._snap(t));this._bdApply((r[0]-e.x)/um,(r[1]-e.y)/um,o/e.w,a/e.h,s),this._backdropDialog=null,this._recordGeometry(this._t("history.backdrop_transform"),n),this._saveConfig()}get _bdActive(){return"decor"===this._mode&&!!this._bdRect&&"backdrop"===this._decorTool}get _bdMovable(){return"decor"===this._mode&&"backdrop"===this._decorTool&&!!this._bdRect}_bdApply(t,e,i,s,n){const o=this._curSpaceCfg;if(!o)return;o.plan_x=Number(Dc(t).toFixed(6)),o.plan_y=Number(Dc(e).toFixed(6)),delete o.plan_scale,o.plan_scale_x=Number(Math.min(mc,Math.max(gc,i)).toFixed(6)),o.plan_scale_y=Number(Math.min(mc,Math.max(gc,s)).toFixed(6));const a=rr(n);a?o.plan_angle=Number(a.toFixed(2)):delete o.plan_angle,this._cfgEpoch++,this.requestUpdate()}_bdStart(t,e,i=!1){const s=this._bdBase,n=this._bdRect;if(!s||!n)return!1;const o=this._svgPoint(t),a=e?e[0]:0,r=e?e[1]:0,l=a>0?n.x:n.x+n.w,c=r>0?n.y:n.y+n.h;return this._bdDrag={kind:i?"rotate":e?"scale":"move",pid:t.pointerId,sx:o[0],sy:o[1],base:s,p0:this._bdParams,fx:l,fy:c,sgx:a,sgy:r,rect0:{x:n.x,y:n.y,w:n.w,h:n.h,angle:n.angle},before:this._geometrySnapshot(),moved:!1},wm(t),!0}_bdMove(t){const e=this._bdDrag;if(!e)return;const i=this._svgPoint(t),s=e.base;if("move"===e.kind){const t=e.rect0.x,n=e.rect0.y,o=this._snap([t+(i[0]-e.sx),n+(i[1]-e.sy)]),a=Math.abs(o[0]-t)>1e-9||Math.abs(o[1]-n)>1e-9;if(!a&&!e.moved)return;return e.moved||=a,void this._bdApply((o[0]-s.x)/um,(o[1]-s.y)/um,e.p0.sx,e.p0.sy,e.p0.angle)}if("rotate"===e.kind){const s=e.rect0.x+e.rect0.w/2,n=e.rect0.y+e.rect0.h/2,o=180*Math.atan2(e.sy-n,e.sx-s)/Math.PI;let a=e.p0.angle+(180*Math.atan2(i[1]-n,i[0]-s)/Math.PI-o);t.shiftKey||(a=5*Math.round(a/5)),a=rr(a);const r=Math.abs(a-e.p0.angle)>1e-9;if(!r&&!e.moved)return;return e.moved||=r,void this._bdApply(e.p0.dx,e.p0.dy,e.p0.sx,e.p0.sy,a)}const n=gr(e.rect0,e.sgx,e.sgy,i[0],i[1],!t.shiftKey,this._gridPitch,Math.min(s.w,s.h)*gc),o=n.w/Math.max(1e-9,s.w),a=n.h/Math.max(1e-9,s.h),r=Math.abs(o-e.p0.sx)>1e-9||Math.abs(a-e.p0.sy)>1e-9||Math.abs(n.x-e.rect0.x)>1e-9||Math.abs(n.y-e.rect0.y)>1e-9;if(!r&&!e.moved)return;e.moved||=r;const l=lr(n,e.p0.angle,t=>this._snap(t));this._bdApply((l[0]-s.x)/um,(l[1]-s.y)/um,o,a,e.p0.angle)}get _bdMoved(){if("decor"!==this._mode||!this._bdRect)return!1;const t=this._bdParams;return 0!==t.dx||0!==t.dy||1!==t.sx||1!==t.sy||0!==t.angle}_bdReset(){const t=this._curSpaceCfg;if(!t)return;const e=this._geometrySnapshot();delete t.plan_x,delete t.plan_y,delete t.plan_scale,delete t.plan_scale_x,delete t.plan_scale_y,delete t.plan_angle,this._bdDrag=null,this._recordGeometry(this._t("history.backdrop_transform"),e),this._saveConfig(),this._showToast(this._t("decor.backdrop_reset_done")),this.requestUpdate()}_bdUp(){const t=this._bdDrag;this._bdDrag=null,t?.moved&&(this._recordGeometry(this._t("history.backdrop_transform"),t.before),this._saveConfig()),this.requestUpdate()}get _bdLive(){if(!this._bdDrag)return null;const t=this._bdRect;return t?{x:t.x+t.w/2,y:t.y+t.h/2,text:`${this._fmtLen([0,0],[t.w,0])} × ${this._fmtLen([0,0],[0,t.h])}`}:null}_renderBackdropFrame(t){const e=this._bdRect;if(!this._bdActive||!e)return G;const i=.02*Math.max(t.w,t.h),s=i/4,n=e.x+e.w/2,o=e.y+e.h/2,a=rr(e.angle),r=2.2*i;return j` - - + {t.stopPropagation(),t.preventDefault(),this._bdStart(t,void 0,!0)}}> - - ${[[-1,-1,"nwse"],[1,-1,"nesw"],[1,1,"nwse"],[-1,1,"nesw"]].map(([t,n,o])=>{const r=t<0?e.x:e.x+e.w,a=n<0?e.y:e.y+e.h;return j` + ${[[-1,-1,"nwse"],[1,-1,"nesw"],[1,1,"nwse"],[-1,1,"nesw"]].map(([t,n,o])=>{const a=t<0?e.x:e.x+e.w,r=n<0?e.y:e.y+e.h;return j`{e.stopPropagation(),e.preventDefault(),this._bdStart(e,[t,n])}}>`})} - `}_renderTextFrame(t){const e=this._dtSel,i=this._dtBox;if(!e||!i||i.id!==e.id)return G;const s=.018*Math.max(t.w,t.h),n=s/4;if("line"===e.kind){const t=[e.x1*pm,e.y1*this._decorH],i=[e.x2*pm,e.y2*this._decorH];return j` + cx="${a}" cy="${r}" r="${i.toFixed(1)}" + @pointerdown=${e=>{e.stopPropagation(),e.preventDefault(),this._bdStart(e,[t,n])}}>`})} + `}_renderTextFrame(t){const e=this._dtSel,i=this._dtBox;if(!e||!i||i.id!==e.id)return G;const s=.018*Math.max(t.w,t.h),n=s/4;if("line"===e.kind){const t=[e.x1*um,e.y1*this._decorH],i=[e.x2*um,e.y2*this._decorH];return j` ${[t,i].map((t,e)=>j`this._dtStart(t,"scale",void 0,e)}> `)} - `}const[o,r]=this._dtPivot(e),a=Number(e.angle)||0,l=2.2*s;return j` + `}const[o,a]=this._dtPivot(e),r=Number(e.angle)||0,l=2.2*s;return j` this._dtStart(i,"scale",[t,e])}>`)} - `}_renderDecorLayer(){const t=pm,e=this._decorH,i="decor"===this._mode,s=i&&"erase"===this._decorTool,n=this._decorList.map(n=>{const o="dshape"+(i&&this._decorSel===n.id?" dsel":""),r=this._decorResolvedStyle(n),a=this._decorWidthUnits(n),l=t=>this._decorShapeDown(t,n),c=t=>this._decorShapeDbl(t,n);if("line"===n.kind)return j``}_renderDecorLayer(){const t=um,e=this._decorH,i="decor"===this._mode,s=i&&"erase"===this._decorTool,n=this._decorList.map(n=>{const o="dshape"+(i&&this._decorSel===n.id?" dsel":""),a=this._decorResolvedStyle(n),r=this._decorWidthUnits(n),l=t=>this._decorShapeDown(t,n),c=t=>this._decorShapeDbl(t,n);if("line"===n.kind)return j` ${i&&"select"===this._decorTool?j``:G}`;if("rect"===n.kind){const i=(n.x+n.w/2)*t,h=(n.y+n.h/2)*e,d=aa(n.angle);return j``:G}`;if("rect"===n.kind){const i=(n.x+n.w/2)*t,h=(n.y+n.h/2)*e,d=rr(n.angle);return j` ${s?j``:G}`}if("ellipse"===n.kind){const i=(n.x+n.w/2)*t,h=(n.y+n.h/2)*e,d=aa(n.angle);return j``:G}`}if("ellipse"===n.kind){const i=(n.x+n.w/2)*t,h=(n.y+n.h/2)*e,d=rr(n.angle);return j` ${s?j``:G}`}if("furniture"===n.kind){const i=n.w*t,h=n.h*e,d=th(n.symbol,i,h);if(!d)return G;const p=Number(n.angle)||0,u=n.x*t+i/2,_=n.y*e+h/2,g=`${p?`rotate(${p} ${u} ${_}) `:""}translate(${n.x*t} ${n.y*e})`;return j``:G}`}if("furniture"===n.kind){const i=n.w*t,h=n.h*e,d=eh(n.symbol,i,h);if(!d)return G;const p=Number(n.angle)||0,u=n.x*t+i/2,_=n.y*e+h/2,g=`${p?`rotate(${p} ${u} ${_}) `:""}translate(${n.x*t} ${n.y*e})`;return j` ${s?j``:G}`}if("text"===n.kind){const i=this._decorTextUnits(n),s=this._renderDeviceSnapshot?.facts.get(`decor:${this._space}:${n.id}`),a=function(t){return String(t??"").replace(/\r\n?/g,"\n").split("\n")}("string"==typeof s?s:ts(n.text,n,this._renderPlanHass,t=>this._renderEntityAvailable(t))),h=n.x*t,d=n.y*e,p=Number(n.angle)||0,u=d-(a.length-1)*i*1.2/2;return j``:G}`}if("text"===n.kind){const i=this._decorTextUnits(n),s=this._renderDeviceSnapshot?.facts.get(`decor:${this._space}:${n.id}`),r=function(t){return String(t??"").replace(/\r\n?/g,"\n").split("\n")}("string"==typeof s?s:ts(n.text,n,this._renderPlanHass,t=>this._renderEntityAvailable(t))),h=n.x*t,d=n.y*e,p=Number(n.angle)||0,u=d-(r.length-1)*i*1.2/2;return j`${a.map((t,e)=>j`${t}`)}`}return G});let o=G;const r=this._decorDraft;if(r){const t=this._decorStyle,e=ca(t.widthCm,this._cellCm,this._gridPitch);if("line"===r.kind)o=j``;else{const i=Math.min(r.a[0],r.b[0]),s=Math.min(r.a[1],r.b[1]),n=Math.abs(r.b[0]-r.a[0]),a=Math.abs(r.b[1]-r.a[1]);o="rect"===r.kind?j``:j`${r.map((t,e)=>j`${t}`)}`}return G});let o=G;const a=this._decorDraft;if(a){const t=this._decorStyle,e=cr(t.widthCm,this._cellCm,this._gridPitch);if("line"===a.kind)o=j``;else{const i=Math.min(a.a[0],a.b[0]),s=Math.min(a.a[1],a.b[1]),n=Math.abs(a.b[0]-a.a[0]),r=Math.abs(a.b[1]-a.a[1]);o="rect"===a.kind?j``:j``}}return j`${n}${o}`}get _editorToolbarGroups(){return"plan"!==this._mode?[]:[{id:"opening",label:this._t("markup.opening"),icon:"mdi:door",activeItemId:"opening"===this._tool?this._openingPreset?.type:void 0,items:[{id:"window",label:this._t("opening.window"),icon:"mdi:window-closed-variant",role:"tool",invoke:()=>this._activateOpeningPlacement("window")},{id:"door",label:this._t("opening.door"),icon:"mdi:door-open",role:"tool",invoke:()=>this._activateOpeningPlacement("door")},{id:"passage",label:this._t("opening.passage"),icon:"mdi:arch",role:"tool",invoke:()=>this._activateOpeningPlacement("passage")},{id:"gate",label:this._t("opening.gate"),icon:"mdi:gate",role:"tool",invoke:()=>this._activateOpeningPlacement("gate")}]}]}_renderEditorGroupLauncher(t){return this._editorSecondary.renderGroupLauncher(t,this._editorToolbarGroups,this._editorSecondaryCopy)}get _editorSecondaryContextId(){const t=`editor:${this._mode}:${this._space}:${this._cfgEpoch}`,e=this._editorSecondary.activeGroup(this._editorToolbarGroups);if(e)return`${t}:group:${e.id}:${this._editorSecondary.groupGeneration}`;if("plan"===this._mode){const e=this._physicalSel;return e?`${t}:selection:${e.kind}:${e.id}:${e.segment??""}`:`${t}:tool:${this._tool}:${this._path.length}:${this._openWallAnchor?1:0}`}return"decor"===this._mode?"furniture"===this._decorTool?`${t}:palette:furniture:${this._furnPalette?.symbol||"none"}`:"select"===this._decorTool&&this._decorSel?`${t}:selection:decor:${this._decorSel}`:`${t}:tool:${this._decorTool}:${this._bdMoved?1:0}:${this._bdDrag?1:0}`:`${t}:none`}_runEditorContext(t,e){this._editorSecondary.runContext(t,this._editorSecondaryContextId,e)}_renderEditorGroupModel(t){return this._editorSecondary.renderGroupModel(t,this._editorSecondaryContextId,this._editorSecondaryCopy)}_renderDrawWallControl(){return W``}_renderPlanSecondary(){const t=this._editorSecondaryContextId,e=this._physicalSel;if(e){if(!("partition"===e.kind?!!this._curSpaceCfg.partitions?.some(t=>t.id===e.id):"column"===e.kind?!!this._curSpaceCfg.wall_columns?.some(t=>t.id===e.id):!!this._curSpaceCfg.room_drafts?.some(t=>t.id===e.id)))return null;const i="partition"===e.kind?this._t("markup.partition"):"column"===e.kind?this._t("markup.column"):this._t("markup.add");return{contextId:t,kind:"selection",ariaLabel:this._t("editor.context_actions",{object:i}),visibleLabel:i,content:W` `:W`${this._t("gs.bg_theme")}`}
`:W`
${this._t("gs.bg_daynight_hint")}
`} - ${ea(this.hass)?G:W`
${this._t("gs.sun_missing")}
`} + ${er(this.hass)?G:W`
${this._t("gs.sun_missing")}
`}
- `}_saveKioskScale(t){this._kioskScale={...this._kioskScale,...t};try{localStorage.setItem(cm,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(hm,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])}% @@ -5784,7 +5784,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8 ${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,r=this._effectiveProjection();this._renderProjection=r,this._labs.active.length&&function(t){Z_||ng(t);const e=J_,i=e.active.join(",");if(!i||i===tg)return;tg=i;const s=new Map(q_.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}`)}(Gg);const a="iso"===r,l="devices"===this._mode&&this._showAll,c=this._renderDevices.filter(t=>t.space===s.id&&(!t.hidden||l)),h=this._renderDeviceSnapshot,d=this._spaceDisplayForRender(),p=a?this._isoDecorationLayers(d):null,u=p?this._isoOpeningPanels(p):[],_=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=au(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){Q_||og(t);const e=Z_,i=e.active.join(",");if(!i||i===eg)return;eg=i;const s=new Map(W_.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}`)}(Vg);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(),p=r?this._isoDecorationLayers(d):null,u=p?this._isoOpeningPanels(p):[],_=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=lu(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` ${this._t("count.devices",{n:c.filter(t=>!t.hidden).length})} - ${this._labsIso&&"view"===this._mode&&!this._kiosk?W``:G}
@@ -5871,7 +5871,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8
this._markupClick(t)} @wheel=${t=>this._onWheel(t)} @pointerdown=${t=>{this._notePointer(t),this._stagePointerDown(t)}} @@ -5879,21 +5879,21 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8 @pointerleave=${t=>this._stagePointerLeave(t)} @pointerup=${t=>this._stagePointerUp(t)} @pointercancel=${t=>this._stagePointerCancel(t)}> - ${na(I,A)} + ${nr(I,A)} ${this._renderEditorSecondary()}
- ${a&&p?.structural?j``:G} + preserveAspectRatio=${p?.structural||!r?"xMidYMid meet":"none"}> + transform=${p?.structural?hg():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} @@ -5905,7 +5905,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8 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 r=Fs(d.fill,e);if(!this._markup&&(d.showBorders||"none"!==r)){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 a;const l=t=>{"view"===this._mode&&(void 0===a&&(a=this._roomArea(e)),this._showTip(t,e.name||this._t("room.unnamed"),a?this._t("tip.area",{value:a}):"",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):[],p=c?[]:this._thickWallCuts(),u=h.concat(p);u.length&&(n+=" noedge");const g=i(e),f=this._spaceWalls,v=f.length&&e.id&&g&&ml(s.rooms,e.id,f,this._openPairs().flatMap(t=>t.segs),this._wallKeyPitch,this._cellCm,this._gridPitch,pm)||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):[],p=c?[]:this._thickWallCuts(),u=h.concat(p);u.length&&(n+=" noedge");const g=i(e),f=this._spaceWalls,v=f.length&&e.id&&g&&fl(s.rooms,e.id,f,this._openPairs().flatMap(t=>t.segs),this._wallKeyPitch,this._cellCm,this._gridPitch,um,this._wallUnionGeometry()?.roomGeom)||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})}} @@ -5964,7 +5964,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8 ${this._renderTextFrame(b)} - ${a&&p?.structural?j``:G} ${""} -
+
${c.map(t=>this._renderDevice(t,b,m))} ${this._renderVacuums(c,b)} ${this._renderVacFit(b)} @@ -6051,7 +6051,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8 ${null!=this._tip.temp?W`${this._t("tip.temp_avg")} ${this._tip.temp}°`:G} ${null!=this._tip.hum?W`${this._t("tip.hum_avg")} ${this._tip.hum}%`:G} ${null!=this._tip.lqi?W`${this._t("tip.lqi")} - ${this._tip.lqi}`:G} + ${this._tip.lqi}`:G}
`:G} ${this._kiosk&&!this._hasFixedFloor&&this._kioskDots&&this._model.length>1?W`
${this._model.map(t=>W``)} @@ -6082,22 +6082,22 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8 `: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=Uh(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||[]),r=new Set(o);n&&r.add(s.source);const a=i?.entities||{},l=[];for(const t of r){const e=i?.states?.[t],o=Uh(t,e,a[t]);o?l.push(o):n&&t===s.source&&l.push({entityId:t,name:String(e?.attributes?.friendly_name||t),platform:a[t]?.platform?String(a[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),r=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=r.find(e=>e.entityId===t);return{entityId:t,status:s[t]||(e?.hasPosition?"ok":"unverified"),pinned:!0,candidates:r}}const a=r.find(t=>o.has(t.entityId)&&t.hasPosition&&"ok"===s[t.entityId]);return a?{entityId:a.entityId,status:"ok",pinned:!1,candidates:r}:{entityId:null,status:"none",pinned:!1,candidates:r}}(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=Jp(this._planHass,t,this._devices,e,this._fullRegistryHass);return{samples:i.samples,sourceKey:tu(this._planHass,t,i)}}_stampActivity(t,e,i){let s=this._activityRt.get(t);s||(s=$u(i||"",[]),this._activityRt.set(t,s)),null!=i&&(s.sources=i),Mu(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:r}=n;let a=this._activityRt.get(s.id);a?a.sources!==r&&Su(a,r,o,window.clearTimeout.bind(window)):(a=$u(r,o),this._activityRt.set(s.id,a))}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 r=Cu(o,s,window.clearTimeout.bind(window));r&&this._stampActivity(e.id,r,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=Yh(this.hass.states[i||""]?.state),n=jh(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 r="never"!==td(t.marker?.vacuum)&&!n?.path.length;!s&&o.moving&&(o.endedTs=Date.now(),r&&o.lastPos&&(o.trail=Kh(o.trail,o.lastPos,40)),o.lastPos=null),o.moving=s;const a=n?.pos;if(s&&a){const t=a.x+":"+a.y;if(t!==o.lastKey){const e=Date.now();o.jump=o.lastTs>0&&e-o.lastTs>1e4,o.lastKey=t,o.lastTs=e,r&&o.lastPos&&(o.trail=Kh(o.trail,o.lastPos,40)),o.lastPos=[a.x,a.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,r=n.candidates.find(t=>t.entityId===o)||null,a=o?jh(this.hass?.states[o]?.attributes):null,l=!1!==i.live&&("ok"===n.status||"unsupported"===n.status),c=this._vacPlanRoomAnchors(e.space),h=a?function(t,e){const i=new Set(e.map(Gh).filter(Boolean)),s=new Set;for(const e of t){const t=Gh(e.name||"");t&&i.has(t)&&s.add(t)}return s.size}(a.rooms,c.map(t=>t.name)):0,d=!!(l&&a&&h>=3),p=Object.keys(i.calibration||{}),u=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=Gh(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=Gh(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=Zp(this._planHass,t,this._devices,e,this._fullRegistryHass);return{samples:i.samples,sourceKey:eu(this._planHass,t,i)}}_stampActivity(t,e,i){let s=this._activityRt.get(t);s||(s=Su(i||"",[]),this._activityRt.set(t,s)),null!=i&&(s.sources=i),Cu(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&&Mu(r,a,o,window.clearTimeout.bind(window)):(r=Su(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=Du(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=Xh(this.hass.states[i||""]?.state),n=Uh(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"!==ed(t.marker?.vacuum)&&!n?.path.length;!s&&o.moving&&(o.endedTs=Date.now(),a&&o.lastPos&&(o.trail=Yh(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=Yh(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?Uh(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(Vh).filter(Boolean)),s=new Set;for(const e of t){const t=Vh(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),p=Object.keys(i.calibration||{}),u=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` `,y=n.candidates.some(t=>_.has(t.entityId)&&"known_xcme_incomplete"===t.category)||!!n.pinned&&!!o?.startsWith("camera.")&&!r?.hasPosition;return W` + `,y=n.candidates.some(t=>_.has(t.entityId)&&"known_xcme_incomplete"===t.category)||!!n.pinned&&!!o?.startsWith("camera.")&&!a?.hasPosition;return W`
${this._t("vac.diag_source")}${o||this._t("vac.source_none")}
- ${r?.platform?W`
${this._t("vac.diag_platform")}${r.platform}
`:G} + ${a?.platform?W`
${this._t("vac.diag_platform")}${a.platform}
`:G}
${this._t("vac.diag_status")}${this._t(`vac.source_status_${n.status}`)}
-
${this._t("vac.diag_position")}${a?.pos?this._t("common.yes"):this._t("common.no")}
-
${this._t("vac.diag_rooms")}${ss(this._t("vac.diag_rooms_value"),{total:String(a?.rooms.length||0),matched:String(h),readiness:this._t(h>=3?"vac.autocal_ready":"vac.autocal_not_ready")})}
-
${this._t("vac.diag_path")}${a?.path.length?this._t("common.yes"):this._t("common.no")}
-
${this._t("vac.diag_map")}${a?.mapId??"default"}
+
${this._t("vac.diag_position")}${r?.pos?this._t("common.yes"):this._t("common.no")}
+
${this._t("vac.diag_rooms")}${ss(this._t("vac.diag_rooms_value"),{total:String(r?.rooms.length||0),matched:String(h),readiness:this._t(h>=3?"vac.autocal_ready":"vac.autocal_not_ready")})}
+
${this._t("vac.diag_path")}${r?.path.length?this._t("common.yes"):this._t("common.no")}
+
${this._t("vac.diag_map")}${r?.mapId??"default"}
${"missing"===n.status||"disabled"===n.status||"unverified"===n.status?W`
- ${a?W` + ${r?W`
`}_vacMapId(t,e,i=this._planHass){const s=this._vacEntity(t),n=s?i?.states?.[s]?.attributes?.selected_map:null;return o=e.mapId,r=n,"default"!==o?o:null!=r?String(r):"default";var o,r}_vacSaveMatrix(t,e,i,s){const n=this._devices.find(e=>e.id===t),o=n?this._vacEnsureMarker(n):this._serverCfg?.markers?.find(e=>e.id===t);if(!o)return!1;const r={...o.vacuum||{}};return r.source=e,r.calibration={...r.calibration||{},[i]:s.map(t=>Number(t.toFixed(6)))},o.vacuum=r,this._regSignature="",this._maybeRebuildDevices(),this._saveConfig(),this.requestUpdate(),!0}_vacPlanRoomAnchors(t){return(this._spaceModelById(t)?.rooms||[]).map(t=>({room:t,poly:hi(t)})).filter(({room:t,poly:e})=>t.name&&e).map(({room:t,poly:e})=>{const i=Hh(e);return i?{name:String(t.name),cx:i[0],cy:i[1]}:null}).filter(Boolean)}_vacAutoCalibrate(t){const e=this._vacSource(t),i=e?jh(this.hass?.states[e]?.attributes):null;if(!e||!i||i.rooms.length<3)return void this._showToast(this._t("vac.autocal_no_rooms"));const s=this._vacPlanRoomAnchors(t.space),n=Vh(i.rooms,s);if(!n)return void this._showToast(this._t("vac.autocal_no_match"));const o=this._serverCfg?.spaces?.find(e=>e.id===t.space),r=Number(o?.cell_cm),a=Number.isFinite(r)&&r>0?r:5,l=function(t,e,i){return![t,e,i].every(Number.isFinite)||t<0||e<=0||i<=0?Number.POSITIVE_INFINITY:t/e*i}(n.residual,this._gridPitch,a),c=this._vacMapId(t,i);l>40?this._vacCalConfirm={markerId:t.id,source:e,mapId:c,matrix:n.matrix,rooms:n.matched.length,error:li(l,"mi"===this.hass?.config?.unit_system?.length)}:this._vacSaveMatrix(t.id,e,c,n.matrix)&&this._showToast(ss(this._t("vac.autocal_done"),{rooms:String(n.matched.length)}))}_vacApplyCalibrationProposal(t){const e=this._vacCalConfirm;if(e){if(this._vacCalConfirm=null,t){const t=this._devices.find(t=>t.id===e.markerId),i=Zh(e.matrix);if(!t||!i)return;if(this._markerDialog=null,t.space!==this._space&&!this._commitSpace(t.space))return;return void(this._vacFit={markerId:e.markerId,source:e.source,mapId:e.mapId,p:i,drag:null})}this._vacSaveMatrix(e.markerId,e.source,e.mapId,e.matrix)&&this._showToast(ss(this._t("vac.autocal_done"),{rooms:String(e.rooms)}))}}_vacStartFit(t){const e=this._vacSource(t),i=e?jh(this.hass?.states[e]?.attributes):null;if(!e||!i)return void this._showToast(this._t("vac.cal_need_pos"));const s=this._vacMapId(t,i),n=t.marker?.vacuum?.calibration?.[s],o=this._spaceModelById(t.space);if(!o)return;const r=o.vb,a=n&&6===n.length&&Zh(n)||function(t,e){const i=[],s=[];for(const e of t)null!=e.x0?(i.push(e.x0,e.x1),s.push(e.y0,e.y1)):(i.push(e.cx),s.push(e.cy));if(!i.length)return{ox:e[0]+e[2]/2,oy:e[1]+e[3]/2,s:e[2]/1e4,rot:0,mir:!0};const n=Math.min(...i),o=Math.max(...i),r=Math.min(...s),a=Math.max(...s),l=Math.max(o-n,a-r)||1,c={ox:0,oy:0,s:.6*Math.min(e[2],e[3])/l,rot:0,mir:!0},h=Jh(c),[d,p]=Eh(h,(n+o)/2,(r+a)/2);return c.ox=e[0]+e[2]/2-d,c.oy=e[1]+e[3]/2-p,c}(i.rooms,r);this._markerDialog=null,(t.space===this._space||this._commitSpace(t.space))&&(this._vacFit={markerId:t.id,source:e,mapId:s,p:a,drag:null})}_vacFitSave(){const t=this._vacFit;if(!t)return;const e=this._vacSaveMatrix(t.markerId,t.source,t.mapId,Jh(t.p));this._vacFit=null,e&&this._showToast(this._t("vac.cal_done"))}_vacFitTurn(t){const e=this._vacFit;if(!e)return;const i=jh(this.hass?.states[e.source]?.attributes),s=this._vacGhostCentre(i?.rooms||[]),n={...e.p,...t};this._vacFit={...e,p:Qh(n,e.p,s[0],s[1])}}_vacGhostCentre(t){const e=[],i=[];for(const s of t)e.push(s.x0??s.cx,s.x1??s.cx),i.push(s.y0??s.cy,s.y1??s.cy);return e.length?[(Math.min(...e)+Math.max(...e))/2,(Math.min(...i)+Math.max(...i))/2]:[0,0]}_vacDelta(t,e,i){const s=this._stageEl,n=s?.clientWidth||1,o=s?.clientHeight||1;return[e/n*t.w,i/o*t.h]}_vacFitPointer(t,e){const i=this._vacFit;if(!i)return;if(t.stopPropagation(),"pointerdown"===t.type){const e=t.target,s=e.getAttribute?.("data-corner");try{t.currentTarget.setPointerCapture?.(t.pointerId)}catch{}return void(this._vacFit={...i,drag:s?{kind:"scale",sx:t.clientX,sy:t.clientY,p0:{...i.p},fx:Number(s.split(",")[0]),fy:Number(s.split(",")[1])}:{kind:"move",sx:t.clientX,sy:t.clientY,p0:{...i.p},fx:0,fy:0}})}const s=i.drag;if(s){if("pointermove"===t.type){const[n,o]=this._vacDelta(e,t.clientX-s.sx,t.clientY-s.sy);if("move"===s.kind)this._vacFit={...i,p:{...s.p0,ox:s.p0.ox+n,oy:s.p0.oy+o}};else{const t=jh(this.hass?.states[i.source]?.attributes),e=this._vacGhostCentre(t?.rooms||[]),r=Jh(s.p0),[a,l]=Eh(r,e[0],e[1]),[c,h]=Eh(r,s.fx,s.fy),d=Math.hypot(a-c,l-h)||1,[p,u]=[2*a-c,2*l-h],_=Math.hypot(p+2*n-c,u+2*o-h)/2,g=Math.max(.05,_/d),m={...s.p0,s:s.p0.s*g};this._vacFit={...i,p:Qh(m,s.p0,s.fx,s.fy)}}return}"pointerup"!==t.type&&"pointercancel"!==t.type||(this._vacFit={...i,drag:null})}}_renderVacFit(t){const e=this._vacFit;if(!e)return G;const i=jh(this._renderPlanHass?.states?.[e.source]?.attributes);if(!i)return G;const s=Jh(e.p),n=[],o=[],r=[];for(const t of i.rooms){if(null==t.x0)continue;const e=[[t.x0,t.y0],[t.x1,t.y0],[t.x1,t.y1],[t.x0,t.y1]].map(([t,e])=>Eh(s,t,e));e.forEach(([t,e])=>{o.push(t),r.push(e)});const[i,a]=Eh(s,t.cx,t.cy);n.push(j` - ${t.name}`)}let a=G;if(i.pos){const[e,n]=Eh(s,i.pos.x,i.pos.y);a=j``}const l=[];if(o.length){const e=(()=>{const t=s[0]*s[4]-s[1]*s[3];return(e,i)=>[(s[4]*(e-s[2])-s[1]*(i-s[5]))/t,(-s[3]*(e-s[2])+s[0]*(i-s[5]))/t]})(),i=Math.min(...o),n=Math.max(...o),a=Math.min(...r),c=Math.max(...r),h=.022*t.w,d=h/4;for(const[t,s,o,r]of[[i,a,n,c],[n,a,i,c],[n,c,i,a],[i,c,n,a]]){const i=e(o,r);l.push(j``}_vacMapId(t,e,i=this._planHass){const s=this._vacEntity(t),n=s?i?.states?.[s]?.attributes?.selected_map:null;return o=e.mapId,a=n,"default"!==o?o:null!=a?String(a):"default";var o,a}_vacSaveMatrix(t,e,i,s){const n=this._devices.find(e=>e.id===t),o=n?this._vacEnsureMarker(n):this._serverCfg?.markers?.find(e=>e.id===t);if(!o)return!1;const a={...o.vacuum||{}};return a.source=e,a.calibration={...a.calibration||{},[i]:s.map(t=>Number(t.toFixed(6)))},o.vacuum=a,this._regSignature="",this._maybeRebuildDevices(),this._saveConfig(),this.requestUpdate(),!0}_vacPlanRoomAnchors(t){return(this._spaceModelById(t)?.rooms||[]).map(t=>({room:t,poly:hi(t)})).filter(({room:t,poly:e})=>t.name&&e).map(({room:t,poly:e})=>{const i=Lh(e);return i?{name:String(t.name),cx:i[0],cy:i[1]}:null}).filter(Boolean)}_vacAutoCalibrate(t){const e=this._vacSource(t),i=e?Uh(this.hass?.states[e]?.attributes):null;if(!e||!i||i.rooms.length<3)return void this._showToast(this._t("vac.autocal_no_rooms"));const s=this._vacPlanRoomAnchors(t.space),n=Kh(i.rooms,s);if(!n)return void this._showToast(this._t("vac.autocal_no_match"));const o=this._serverCfg?.spaces?.find(e=>e.id===t.space),a=Number(o?.cell_cm),r=Number.isFinite(a)&&a>0?a:5,l=function(t,e,i){return![t,e,i].every(Number.isFinite)||t<0||e<=0||i<=0?Number.POSITIVE_INFINITY:t/e*i}(n.residual,this._gridPitch,r),c=this._vacMapId(t,i);l>40?this._vacCalConfirm={markerId:t.id,source:e,mapId:c,matrix:n.matrix,rooms:n.matched.length,error:li(l,"mi"===this.hass?.config?.unit_system?.length)}:this._vacSaveMatrix(t.id,e,c,n.matrix)&&this._showToast(ss(this._t("vac.autocal_done"),{rooms:String(n.matched.length)}))}_vacApplyCalibrationProposal(t){const e=this._vacCalConfirm;if(e){if(this._vacCalConfirm=null,t){const t=this._devices.find(t=>t.id===e.markerId),i=Qh(e.matrix);if(!t||!i)return;if(this._markerDialog=null,t.space!==this._space&&!this._commitSpace(t.space))return;return void(this._vacFit={markerId:e.markerId,source:e.source,mapId:e.mapId,p:i,drag:null})}this._vacSaveMatrix(e.markerId,e.source,e.mapId,e.matrix)&&this._showToast(ss(this._t("vac.autocal_done"),{rooms:String(e.rooms)}))}}_vacStartFit(t){const e=this._vacSource(t),i=e?Uh(this.hass?.states[e]?.attributes):null;if(!e||!i)return void this._showToast(this._t("vac.cal_need_pos"));const s=this._vacMapId(t,i),n=t.marker?.vacuum?.calibration?.[s],o=this._spaceModelById(t.space);if(!o)return;const a=o.vb,r=n&&6===n.length&&Qh(n)||function(t,e){const i=[],s=[];for(const e of t)null!=e.x0?(i.push(e.x0,e.x1),s.push(e.y0,e.y1)):(i.push(e.cx),s.push(e.cy));if(!i.length)return{ox:e[0]+e[2]/2,oy:e[1]+e[3]/2,s:e[2]/1e4,rot:0,mir:!0};const n=Math.min(...i),o=Math.max(...i),a=Math.min(...s),r=Math.max(...s),l=Math.max(o-n,r-a)||1,c={ox:0,oy:0,s:.6*Math.min(e[2],e[3])/l,rot:0,mir:!0},h=Zh(c),[d,p]=zh(h,(n+o)/2,(a+r)/2);return c.ox=e[0]+e[2]/2-d,c.oy=e[1]+e[3]/2-p,c}(i.rooms,a);this._markerDialog=null,(t.space===this._space||this._commitSpace(t.space))&&(this._vacFit={markerId:t.id,source:e,mapId:s,p:r,drag:null})}_vacFitSave(){const t=this._vacFit;if(!t)return;const e=this._vacSaveMatrix(t.markerId,t.source,t.mapId,Zh(t.p));this._vacFit=null,e&&this._showToast(this._t("vac.cal_done"))}_vacFitTurn(t){const e=this._vacFit;if(!e)return;const i=Uh(this.hass?.states[e.source]?.attributes),s=this._vacGhostCentre(i?.rooms||[]),n={...e.p,...t};this._vacFit={...e,p:td(n,e.p,s[0],s[1])}}_vacGhostCentre(t){const e=[],i=[];for(const s of t)e.push(s.x0??s.cx,s.x1??s.cx),i.push(s.y0??s.cy,s.y1??s.cy);return e.length?[(Math.min(...e)+Math.max(...e))/2,(Math.min(...i)+Math.max(...i))/2]:[0,0]}_vacDelta(t,e,i){const s=this._stageEl,n=s?.clientWidth||1,o=s?.clientHeight||1;return[e/n*t.w,i/o*t.h]}_vacFitPointer(t,e){const i=this._vacFit;if(!i)return;if(t.stopPropagation(),"pointerdown"===t.type){const e=t.target,s=e.getAttribute?.("data-corner");try{t.currentTarget.setPointerCapture?.(t.pointerId)}catch{}return void(this._vacFit={...i,drag:s?{kind:"scale",sx:t.clientX,sy:t.clientY,p0:{...i.p},fx:Number(s.split(",")[0]),fy:Number(s.split(",")[1])}:{kind:"move",sx:t.clientX,sy:t.clientY,p0:{...i.p},fx:0,fy:0}})}const s=i.drag;if(s){if("pointermove"===t.type){const[n,o]=this._vacDelta(e,t.clientX-s.sx,t.clientY-s.sy);if("move"===s.kind)this._vacFit={...i,p:{...s.p0,ox:s.p0.ox+n,oy:s.p0.oy+o}};else{const t=Uh(this.hass?.states[i.source]?.attributes),e=this._vacGhostCentre(t?.rooms||[]),a=Zh(s.p0),[r,l]=zh(a,e[0],e[1]),[c,h]=zh(a,s.fx,s.fy),d=Math.hypot(r-c,l-h)||1,[p,u]=[2*r-c,2*l-h],_=Math.hypot(p+2*n-c,u+2*o-h)/2,g=Math.max(.05,_/d),m={...s.p0,s:s.p0.s*g};this._vacFit={...i,p:td(m,s.p0,s.fx,s.fy)}}return}"pointerup"!==t.type&&"pointercancel"!==t.type||(this._vacFit={...i,drag:null})}}_renderVacFit(t){const e=this._vacFit;if(!e)return G;const i=Uh(this._renderPlanHass?.states?.[e.source]?.attributes);if(!i)return G;const s=Zh(e.p),n=[],o=[],a=[];for(const t of i.rooms){if(null==t.x0)continue;const e=[[t.x0,t.y0],[t.x1,t.y0],[t.x1,t.y1],[t.x0,t.y1]].map(([t,e])=>zh(s,t,e));e.forEach(([t,e])=>{o.push(t),a.push(e)});const[i,r]=zh(s,t.cx,t.cy);n.push(j` + ${t.name}`)}let r=G;if(i.pos){const[e,n]=zh(s,i.pos.x,i.pos.y);r=j``}const l=[];if(o.length){const e=(()=>{const t=s[0]*s[4]-s[1]*s[3];return(e,i)=>[(s[4]*(e-s[2])-s[1]*(i-s[5]))/t,(-s[3]*(e-s[2])+s[0]*(i-s[5]))/t]})(),i=Math.min(...o),n=Math.max(...o),r=Math.min(...a),c=Math.max(...a),h=.022*t.w,d=h/4;for(const[t,s,o,a]of[[i,r,n,c],[n,r,i,c],[n,c,i,r],[i,c,n,r]]){const i=e(o,a);l.push(j` `)}}return W`this._vacFitPointer(e,t)} @pointermove=${e=>this._vacFitPointer(e,t)} @pointerup=${e=>this._vacFitPointer(e,t)} - @pointercancel=${e=>this._vacFitPointer(e,t)}>${n}${a}${l}`}_vacRafLoop(){this._vacRaf=requestAnimationFrame(()=>{const t=this.renderRoot,e=this._stageEl,i=this._vacLastView,s=t?.querySelectorAll?.(".vacpuck")||[];if(!e||!i||!s.length)return void(this._vacRaf=0);const n=e.getBoundingClientRect();for(const e of s){const s=e.getAttribute("data-mid"),o=e.getBoundingClientRect(),r=i.x+(o.left+o.width/2-n.left)/n.width*i.w,a=i.y+(o.top+o.height/2-n.top)/n.height*i.h;for(const e of t.querySelectorAll(`line.tip[data-mid="${s}"]`))e.setAttribute("x2",r.toFixed(1)),e.setAttribute("y2",a.toFixed(1))}this._vacRafLoop()})}_renderVacuums(t,e){if(this._markup||"decor"===this._mode)return G;const i=this._space+"|"+e.x+"|"+e.y+"|"+e.w+"|"+e.h,s=this._vacJumpOnce||i!==this._vacViewKey;this._vacViewKey=i,this._vacJumpOnce=!1;const n=[],o=[];for(const i of t){if(i.hidden||!this._isVacDev(i))continue;if("static_icon"===Bi(i.marker?.display))continue;const t=this._renderDeviceSnapshot?.facts.get(`vacuum:${i.id}`),r=t?.source??this._vacSource(i,this._renderPlanHass);if(!r)continue;const a=t?.telemetry??jh(this._renderPlanHass?.states[r]?.attributes);if(!a)continue;const l=String(t?.mapId??this._vacMapId(i,a,this._renderPlanHass)),c=i.marker?.vacuum?.calibration?.[l];if(!c||6!==c.length)continue;const h=t?.runtime??this._vacRt.get(i.id),d=h?.moving??!1,p=td(i.marker?.vacuum),u="always"===p||"cleaning"===p&&d,_=t?.server??this._vacSrvTrails[i.id],g=_?.current?.map_id===l&&Array.isArray(_.current.points)?_.current:null,m=_?.previous?.map_id===l&&Array.isArray(_.previous.points)?_.previous:null;if("always"===p&&m&&m.points.length>1){const t=m.points.map(([t,e])=>{const[i,s]=Eh(c,t,e),n=this._scenePoint([i,s]);return n[0].toFixed(1)+","+n[1].toFixed(1)}).join(" ");o.push(j``)}if(u){const t=qh(a,g,h?.trail||[]),e=!d||"integration"!==t.source&&"server"!==t.source?t.path:Wh(t.path);if(e.length){const t=e.map(t=>t.map(([t,e],i)=>{const[s,n]=Eh(c,t,e),o=this._scenePoint([s,n]);return`${i?"L":"M"} ${o[0].toFixed(1)} ${o[1].toFixed(1)}`}).join(" ")).join(" ");o.push(j``);const s=e[e.length-1];if(d&&s?.length>=2){const t=s[s.length-1],[e,n]=Eh(c,t[0],t[1]),r=this._scenePoint([e,n]),a=r[0].toFixed(1),l=r[1].toFixed(1);o.push(j``)}}}if(!d||!a.pos)continue;const[f,v]=Eh(c,a.pos.x,a.pos.y),y=this._scenePoint([f,v]),b=(y[0]-e.x)/e.w*100,w=(y[1]-e.y)/e.h*100,k=h&&h.lastTs>0&&Date.now()-h.lastTs>6e4,x=i.marker?.icon||i.icon||"mdi:robot-vacuum";n.push(W`
this._vacFitPointer(e,t)}>${n}${r}${l}`}_vacRafLoop(){this._vacRaf=requestAnimationFrame(()=>{const t=this.renderRoot,e=this._stageEl,i=this._vacLastView,s=t?.querySelectorAll?.(".vacpuck")||[];if(!e||!i||!s.length)return void(this._vacRaf=0);const n=e.getBoundingClientRect();for(const e of s){const s=e.getAttribute("data-mid"),o=e.getBoundingClientRect(),a=i.x+(o.left+o.width/2-n.left)/n.width*i.w,r=i.y+(o.top+o.height/2-n.top)/n.height*i.h;for(const e of t.querySelectorAll(`line.tip[data-mid="${s}"]`))e.setAttribute("x2",a.toFixed(1)),e.setAttribute("y2",r.toFixed(1))}this._vacRafLoop()})}_renderVacuums(t,e){if(this._markup||"decor"===this._mode)return G;const i=this._space+"|"+e.x+"|"+e.y+"|"+e.w+"|"+e.h,s=this._vacJumpOnce||i!==this._vacViewKey;this._vacViewKey=i,this._vacJumpOnce=!1;const n=[],o=[];for(const i of t){if(i.hidden||!this._isVacDev(i))continue;if("static_icon"===Bi(i.marker?.display))continue;const t=this._renderDeviceSnapshot?.facts.get(`vacuum:${i.id}`),a=t?.source??this._vacSource(i,this._renderPlanHass);if(!a)continue;const r=t?.telemetry??Uh(this._renderPlanHass?.states[a]?.attributes);if(!r)continue;const l=String(t?.mapId??this._vacMapId(i,r,this._renderPlanHass)),c=i.marker?.vacuum?.calibration?.[l];if(!c||6!==c.length)continue;const h=t?.runtime??this._vacRt.get(i.id),d=h?.moving??!1,p=ed(i.marker?.vacuum),u="always"===p||"cleaning"===p&&d,_=t?.server??this._vacSrvTrails[i.id],g=_?.current?.map_id===l&&Array.isArray(_.current.points)?_.current:null,m=_?.previous?.map_id===l&&Array.isArray(_.previous.points)?_.previous:null;if("always"===p&&m&&m.points.length>1){const t=m.points.map(([t,e])=>{const[i,s]=zh(c,t,e),n=this._scenePoint([i,s]);return n[0].toFixed(1)+","+n[1].toFixed(1)}).join(" ");o.push(j``)}if(u){const t=Wh(r,g,h?.trail||[]),e=!d||"integration"!==t.source&&"server"!==t.source?t.path:jh(t.path);if(e.length){const t=e.map(t=>t.map(([t,e],i)=>{const[s,n]=zh(c,t,e),o=this._scenePoint([s,n]);return`${i?"L":"M"} ${o[0].toFixed(1)} ${o[1].toFixed(1)}`}).join(" ")).join(" ");o.push(j``);const s=e[e.length-1];if(d&&s?.length>=2){const t=s[s.length-1],[e,n]=zh(c,t[0],t[1]),a=this._scenePoint([e,n]),r=a[0].toFixed(1),l=a[1].toFixed(1);o.push(j``)}}}if(!d||!r.pos)continue;const[f,v]=zh(c,r.pos.x,r.pos.y),y=this._scenePoint([f,v]),b=(y[0]-e.x)/e.w*100,w=(y[1]-e.y)/e.h*100,k=h&&h.lastTs>0&&Date.now()-h.lastTs>6e4,x=i.marker?.icon||i.icon||"mdi:robot-vacuum";n.push(W`
${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,r=(n[1]-e.y)/e.h*100,a=this._devicePresentation(t,i),l=[`left:${o}%`,`top:${r}%`,...Go(a)],c=a.disabledReason,h=a.haDisabled?this._t(`marker.ha_disabled_${c}`):t.userHidden?this._t("marker.hidden_ghost"):t.name,d=Gp(a),p="view"===this._mode||"devices"===this._mode,u=[h,a.haDisabled?"":this._t(`marker.state_a11y_${d}`),"none"!==a.pulse.kind?this._t(`marker.pulse_a11y_${a.pulse.reason}`):"",a.valueFullText||a.valueText||"",Ro(a.valueBadge),null!=a.lqiText&&a.lqiBand?this._t(`marker.lqi_a11y_${a.lqiBand}`,{value:a.lqiText}):""].filter(Boolean).join(", "),_=[t.model,a.valueBadge?.fullText||"",null!=a.lqiText?"LQI "+a.lqiText:""].filter(Boolean).join(" · ");return W`
this._clickDevice(e,t)} @keydown=${e=>this._keyDevice(e,t)} @contextmenu=${e=>this._ctxDevice(e,t)} - @pointerover=${e=>this._showTip(e,t.name,a.haDisabled?h:_)} + @pointerover=${e=>this._showTip(e,t.name,r.haDisabled?h:_)} @pointerleave=${()=>this._clearTransientHover()} @pointerdown=${e=>this._pointerDown(e,t)} - @pointermove=${e=>{this._pointerMove(e,t),this._showTip(e,t.name,a.haDisabled?h:_)}} + @pointermove=${e=>{this._pointerMove(e,t),this._showTip(e,t.name,r.haDisabled?h:_)}} @pointerup=${e=>this._pointerUp(e,t)} @pointercancel=${e=>this._pointerUp(e,t)} > - ${Ko(a,{newDevice:this._newIds.has(t.id),newDeviceTitle:this._t("device.new"),disabledTitle:a.haDisabled?h:""})} -
`}_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&&ml(i.rooms,t.id,s,this._openPairs().flatMap(t=>t.segs),this._wallKeyPitch,this._cellCm,this._gridPitch,pm)||e,o=this._cleanFloor(t,n),r=this._cellCm/this._gridPitch;return Ir(o.area*r*r/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 r=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,a=i.area_id||s?.area_id||null;if(!a)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=r.get(a);l||(l=new Map,r.set(a,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 r){const r=[],a=[];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&&r.push(e)}if(o.size>0&&(o.has(i)||s.ents.some(t=>o.has(t)))){const e=mo(t,s.ents);null!=e&&r.push(e)}if(l||"mdi:water-percent"===n){const e=vo(t,s.ents);null!=e&&a.push(e)}}(r.length||a.length)&&s.set(i,{temp:r.length?Math.round(r.reduce((t,e)=>t+e,0)/r.length*10)/10:null,hum:a.length?Math.round(a.reduce((t,e)=>t+e,0)/a.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?as(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 r=o.name||t.states[n]?.attributes?.friendly_name||n;i&&!(r+" "+n).toLowerCase().includes(i)||s.push({value:"entity:"+n,label:r,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*pm,y:i.y*pm};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},bm(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 r=o.vb,a=n.getBoundingClientRect(),l=this._viewOr(r),c=(t.clientX-this._drag.sx)/a.width*l.w,h=(t.clientY-this._drag.sy)/a.height*l.h;Math.abs(t.clientX-this._drag.sx)+Math.abs(t.clientY-this._drag.sy)>3&&(this._drag.moved=!0);const d=Mc(this._drag.ox+c),p=Mc(this._drag.oy+h);this._savePos({id:s,space:i},d,p)}_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,r=n.top+n.height/2,a=Math.max(8,Math.hypot(t.clientX-o,t.clientY-r));this._rlResize={id:"rl_"+(e.id||""),space:i,k0:this._labelScale(e),cx:o,cy:r,d0:a},bm(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/pm,y:o.y/pm,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``}_renderRoomLabel(t,e,i,s){if(!t.name&&!this._markup)return G;const n=this._labelPos(t,e.id),o=this._scenePoint([n.x,n.y]),r=(o[0]-i.x)/i.w*100,a=(o[1]-i.y)/i.h*100,l=Math.min(1,s.opacity+.25),c=this._labelScale(t),h=[];if(t.area||t.settings?.temp_source||t.settings?.hum_source||s.labelLight){if(s.labelTemp){const e=this._roomTemp(t);null!=e&&h.push(W`${e}°`)}if(s.labelHum){const e=this._roomHum(t);null!=e&&h.push(W`${e}%`)}if(s.labelLqi&&t.area){const e=this._roomLqi(t.area);null!=e&&h.push(W`${e}`)}if(s.labelLight){const e=(d=ho(this._renderPlanHass,this._renderDevices,t,this._virtualLights)).length?{on:d.filter(t=>t.on).length,total:d.length}:null;if(e){const t=0===e.on?this._t("roomcard.light_off"):e.on===e.total?this._t("roomcard.light_on"):this._t("roomcard.light_partial",{on:e.on,total:e.total});h.push(W`${t}`)}}}var d;const p=!!t.area,u=!this._markup;return W`
`}_renderRoomLabel(t,e,i,s){if(!t.name&&!this._markup)return G;const n=this._labelPos(t,e.id),o=this._scenePoint([n.x,n.y]),a=(o[0]-i.x)/i.w*100,r=(o[1]-i.y)/i.h*100,l=Math.min(1,s.opacity+.25),c=this._labelScale(t),h=[];if(t.area||t.settings?.temp_source||t.settings?.hum_source||s.labelLight){if(s.labelTemp){const e=this._roomTemp(t);null!=e&&h.push(W`${e}°`)}if(s.labelHum){const e=this._roomHum(t);null!=e&&h.push(W`${e}%`)}if(s.labelLqi&&t.area){const e=this._roomLqi(t.area);null!=e&&h.push(W`${e}`)}if(s.labelLight){const e=(d=ho(this._renderPlanHass,this._renderDevices,t,this._virtualLights)).length?{on:d.filter(t=>t.on).length,total:d.length}:null;if(e){const t=0===e.on?this._t("roomcard.light_off"):e.on===e.total?this._t("roomcard.light_on"):this._t("roomcard.light_partial",{on:e.on,total:e.total});h.push(W`${t}`)}}}var d;const p=!!t.area,u=!this._markup;return W`
this._labelDown(i,t,e.id)} @pointermove=${i=>this._labelMove(i,t,e.id)} @pointerup=${()=>this._labelUp(t)} @@ -6212,12 +6212,12 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8 @pointermove=${t=>this._rlResizeMove(t)} @pointerup=${()=>this._rlResizeUp()} @pointercancel=${()=>this._rlResizeUp()}>`):G} -
`}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),r=Math.round(10*o)/10,a=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)} · ${r}°
`}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,r=(i+n)/2;if("line"===t.kind){const e=Os(t.a,t.b);return{x:o,y:r,on45:Ns(e),text:`${this._fmtLen(t.a,t.b)} · ${Math.round(10*e)/10}°`}}const a=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]),a=this._fmtLen([0,0],[0,Math.abs(n-i)/2]);return{x:o,y:r,on45:!1,text:Math.abs(Math.abs(s-e)-Math.abs(n-i))<1e-6?`R ${t}`:`Rx ${t} × Ry ${a}`}}return{x:o,y:r,on45:!1,text:`${a} × ${l} · ${Ir(ha(Math.abs(s-e),this._cellCm,this._gridPitch)*ha(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=pm,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,r,a]="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` +
`}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=um,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` `})} - `}_renderOpeningCenterTick(t){const e=(t.angle+90)*Math.PI/180,i=cc(15,this._cellCm);return j``})} + `}_renderOpeningCenterTick(t){const e=(t.angle+90)*Math.PI/180,i=hc(15,this._cellCm);return j``}_renderOpeningDimensionGuides(t){const e=t.labels.flatMap(t=>t.dimension?[t.dimension]:[]);if(!e.length)return j``;const i=this._cssPxToRender(4);return j``}_roomCenter(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)]}_openingAmt(t){const e=t.contact&&this._renderOpeningEntityAvailable(t.contact)?this._renderPlanHass.states[t.contact]?.state:null;return gi(t.type,e,!!t.invert)}_planEntityAvailable(t){return!!t&&(!ko(this._fullRegistryHass,t,wo(this._markers))&&"active"===this._bindingStatus("entity:"+t).kind)}_renderEntityAvailable(t){return!!t&&(!ko(this._renderPlanHass,t,wo(this._markers))&&(!!this._renderPlanHass.entities?.[t]&&!!this._renderPlanHass.states?.[t]))}_openingEntityAvailable(t){return function(t,e,i=An(t)){return!!e&&"active"===Bn(t,`entity:${e}`,i).kind}(this.hass,t,this._haRegistry)}_renderOpeningEntityAvailable(t){return e=this._renderPlanHass,!!(i=t)&&!!e?.states?.[i];var e,i}_renderOpeningPlacementPreview(){const t=this._openingPreview;if(!t)return j``;const e={type:t.type,length:t.renderedLength,angle:t.angle,amount:gi(t.type,null),flipH:t.flipH,flipV:t.flipV,base:"var(--hp-open)",tone:"var(--hp-open)",cellCm:this._cellCm,gridPitch:this._gridPitch,face:t.face},i="passage"===t.type?function(t,e){const i=Math.max(0,t.renderedLength)/2,s=Math.max(0,t.target.physicalHalfWidth),n=s+.18*Math.max(0,e),o=t=>({x1:t,y1:-n,x2:t,y2:n});return{rect:{x:-i,y:s?-s:0,width:2*i,height:2*s},boundaries:[o(-i),o(i)]}}(t,cc(this._gridPitch,this._cellCm)):null;return j``}_roomCenter(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)]}_openingAmt(t){const e=t.contact&&this._renderOpeningEntityAvailable(t.contact)?this._renderPlanHass.states[t.contact]?.state:null;return gi(t.type,e,!!t.invert)}_planEntityAvailable(t){return!!t&&(!ko(this._fullRegistryHass,t,wo(this._markers))&&"active"===this._bindingStatus("entity:"+t).kind)}_renderEntityAvailable(t){return!!t&&(!ko(this._renderPlanHass,t,wo(this._markers))&&(!!this._renderPlanHass.entities?.[t]&&!!this._renderPlanHass.states?.[t]))}_openingEntityAvailable(t){return function(t,e,i=An(t)){return!!e&&"active"===Bn(t,`entity:${e}`,i).kind}(this.hass,t,this._haRegistry)}_renderOpeningEntityAvailable(t){return e=this._renderPlanHass,!!(i=t)&&!!e?.states?.[i];var e,i}_renderOpeningPlacementPreview(){const t=this._openingPreview;if(!t)return j``;const e={type:t.type,length:t.renderedLength,angle:t.angle,amount:gi(t.type,null),flipH:t.flipH,flipV:t.flipV,base:"var(--hp-open)",tone:"var(--hp-open)",cellCm:this._cellCm,gridPitch:this._gridPitch,face:t.face},i="passage"===t.type?function(t,e){const i=Math.max(0,t.renderedLength)/2,s=Math.max(0,t.target.physicalHalfWidth),n=s+.18*Math.max(0,e),o=t=>({x1:t,y1:-n,x2:t,y2:n});return{rect:{x:-i,y:s?-s:0,width:2*i,height:2*s},boundaries:[o(-i),o(i)]}}(t,hc(this._gridPitch,this._cellCm)):null;return j` `}_renderOpenings(t){const e=this._openingsR;if(!e.length)return j``;const i=this._spaceModel();if(!i)return j``;const s=t.color,n=this._spaceWalls,o=this._openPairs().flatMap(t=>t.segs),r=this._openingWallIndexFor(i,o).value;return j`${e.map(t=>{if(t.orphanReason)return j``}_renderOpenings(t){const e=this._openingsR;if(!e.length)return j``;const i=this._spaceModel();if(!i)return j``;const s=t.color,n=this._spaceWalls,o=this._openPairs().flatMap(t=>t.segs),a=this._openingWallIndexFor(i,o).value;return j`${e.map(t=>{if(t.orphanReason)return j`{e.stopPropagation(),this._editOpening(t)}}> - + ! - `;const e=this._openingAmt(t),i=e>0&&!!t.contact&&this._renderOpeningEntityAvailable(t.contact)?"var(--hp-open)":s,o="gate"===t.type?!t.flip_v:t.flip_v,a=t.partitionHost||n.length||"gate"===t.type?this._openingFace(t,r,!!o):{ox:0,oy:0,cm:0,side:-1},l={type:t.type,length:t.rlen,angle:t.angle,amount:e,flipH:!!t.flip_h,flipV:!!t.flip_v,base:s,tone:i,cellCm:this._cellCm,gridPitch:this._gridPitch,face:a},{half:c,outlineHalf:h,hitHalf:d}=qp(l),p=cc(10,this._cellCm),u=cc(12,this._cellCm);return j``;const e=this._openingAmt(t),i=e>0&&!!t.contact&&this._renderOpeningEntityAvailable(t.contact)?"var(--hp-open)":s,o="gate"===t.type?!t.flip_v:t.flip_v,r=t.partitionHost||n.length||"gate"===t.type?this._openingFace(t,a,!!o):{ox:0,oy:0,cm:0,side:-1},l={type:t.type,length:t.rlen,angle:t.angle,amount:e,flipH:!!t.flip_h,flipV:!!t.flip_v,base:s,tone:i,cellCm:this._cellCm,gridPitch:this._gridPitch,face:r},{half:c,outlineHalf:h,hitHalf:d}=Wp(l),p=hc(10,this._cellCm),u=hc(12,this._cellCm);return j` - ${Wp(l)} + ${jp(l)} + rx="${hc(6,this._cellCm)}"> this._opClick(e,t)} @@ -6265,7 +6265,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8 @pointermove=${e=>this._opPointerMove(e,t)} @pointerup=${e=>this._opPointerUp(e,t)} @pointercancel=${e=>this._opPointerUp(e,t)}> - `})}`}_renderOpeningLocks(t){const e=this._openingsR.filter(t=>!t.orphanReason&&("door"===t.type||"gate"===t.type)&&t.lock&&this._renderOpeningEntityAvailable(t.lock));if(!e.length)return W``;const i=this._spaceModel();if(!i)return W``;const s=this._openPairs().flatMap(t=>t.segs),n=this._openingWallIndexFor(i,s).value;return W`${e.map(e=>{const i=this._renderPlanHass.states[e.lock]?.state,s="locked"===i,o=s||["unlocked","open","opening","unlocking","locking"].includes(String(i)),r=(e.angle+90)*Math.PI/180,a="gate"===e.type?this._openingFace(e,n,!e.flip_v):null,l=cc(16,this._cellCm),c=a?-l*a.side:l*(e.flip_v?-1:1),h=e.rx+Math.cos(r)*c,d=e.ry+Math.sin(r)*c,p=this._scenePoint([h,d]),u=(p[0]-t.x)/t.w*100,_=(p[1]-t.y)/t.h*100;return W`
`})}`}_renderOpeningLocks(t){const e=this._openingsR.filter(t=>!t.orphanReason&&("door"===t.type||"gate"===t.type)&&t.lock&&this._renderOpeningEntityAvailable(t.lock));if(!e.length)return W``;const i=this._spaceModel();if(!i)return W``;const s=this._openPairs().flatMap(t=>t.segs),n=this._openingWallIndexFor(i,s).value;return W`${e.map(e=>{const i=this._renderPlanHass.states[e.lock]?.state,s="locked"===i,o=s||["unlocked","open","opening","unlocking","locking"].includes(String(i)),a=(e.angle+90)*Math.PI/180,r="gate"===e.type?this._openingFace(e,n,!e.flip_v):null,l=hc(16,this._cellCm),c=r?-l*r.side:l*(e.flip_v?-1:1),h=e.rx+Math.cos(a)*c,d=e.ry+Math.sin(a)*c,p=this._scenePoint([h,d]),u=(p[0]-t.x)/t.w*100,_=(p[1]-t.y)/t.h*100;return W`
{t.stopPropagation(),"view"===this._mode&&(this._openingInfo=e)}}> -
`})}`}_lockAction(t,e){if(this._openingEntityAvailable(t)){if("unlock"===e){const e=this.hass?.states?.[t]?.attributes?.friendly_name||t;if(!confirm(this._t("confirm.unlock",{name:e})))return}this.hass?.callService?.("lock",e,{entity_id:t})}}_renderOpeningInfoCard(){const t=this._openingInfo,e="passage"!==t.type&&t.contact&&this._openingEntityAvailable(t.contact)?t.contact:null,i=("door"===t.type||"gate"===t.type)&&t.lock&&this._openingEntityAvailable(t.lock)?t.lock:null,s=e?this.hass.states[e]?.state:null,n=this._openingAmt(t),o=i?this.hass.states[i]?.state:null,r="door"===t.type?"opening.door":"gate"===t.type?"opening.gate":"passage"===t.type?"opening.passage":"opening.window",a="door"===t.type?"mdi:door":"gate"===t.type?"mdi:gate":"passage"===t.type?"mdi:arch":"mdi:window-closed-variant",l="gate"===t.type?n>0?"mdi:gate-open":"mdi:gate":n>0?"mdi:door-open":"mdi:door-closed",c=(t,e,i,s="")=>W`
${e}${i}
`;return W``})}`}_lockAction(t,e){if(this._openingEntityAvailable(t)){if("unlock"===e){const e=this.hass?.states?.[t]?.attributes?.friendly_name||t;if(!confirm(this._t("confirm.unlock",{name:e})))return}this.hass?.callService?.("lock",e,{entity_id:t})}}_renderOpeningInfoCard(){const t=this._openingInfo,e="passage"!==t.type&&t.contact&&this._openingEntityAvailable(t.contact)?t.contact:null,i=("door"===t.type||"gate"===t.type)&&t.lock&&this._openingEntityAvailable(t.lock)?t.lock:null,s=e?this.hass.states[e]?.state:null,n=this._openingAmt(t),o=i?this.hass.states[i]?.state:null,a="door"===t.type?"opening.door":"gate"===t.type?"opening.gate":"passage"===t.type?"opening.passage":"opening.window",r="door"===t.type?"mdi:door":"gate"===t.type?"mdi:gate":"passage"===t.type?"mdi:arch":"mdi:window-closed-variant",l="gate"===t.type?n>0?"mdi:gate-open":"mdi:gate":n>0?"mdi:door-open":"mdi:door-closed",c=(t,e,i,s="")=>W`
${e}${i}
`;return W`this._openingInfo=null}>
${e?c(l,this._t("opening.contact_label"),"unavailable"===s||null==s?this._t("opening.state_unknown"):this._t(n>0?"opening.open":"opening.closed"),n>0?"warn":"ok"):G} @@ -6293,7 +6293,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8
-
`}_renderOpeningDialog(){const t=this._openingDialog,e=this._spaceModel()?.partitions||[],i=t.id?this._curSpaceCfg?.openings?.find(e=>e.id===t.id):null,s={id:t.id||"preview",type:t.type,x:t.x/pm,y:t.y/this._spaceH,angle:t.angle,length:i&&!t.lengthTouched?i.length:this._cmToUnits(Math.max(20,t.lengthCm))/pm,...t.host?{host:t.host}:{}},n=Id(i,s),o=t.host?n?Rd(s,e,pm,this._cellCm,this._gridPitch):Pd(s,e,pm,this._cellCm,this._gridPitch):null,r="does-not-fit-jamb"===o?.reason,a=t.host?e.find(e=>e.id===t.host.id):null,l=a?li(a.cm/2,this._imperial):"",c=!!t.host&&!o?.resolved&&!r,h="gate"===t.type?"mdi:gate":"window"===t.type?"mdi:window-closed-variant":"passage"===t.type?"mdi:arch":"mdi:door",d=(t,e,i)=>W`i(t.target.value)}> ${t.map(t=>W``)} `;return W` ${t.host?W` -
- ${c||r?W``:G} - ${c?this._t("opening.partition_orphan"):r?this._t("opening.partition_jamb_margin",{distance:l}):this._t("opening.host_partition")} +
+ ${c||a?W``:G} + ${c?this._t("opening.partition_orphan"):a?this._t("opening.partition_jamb_margin",{distance:l}):this._t("opening.host_partition")}
`:G} {const i=Zg(e.target.value);null!=i&&(this._openingDialog={...t,lengthCm:i,lengthTouched:!0})}} /> + @input=${e=>{const i=Qg(e.target.value);null!=i&&(this._openingDialog={...t,lengthCm:i,lengthTouched:!0})}} /> ${"passage"===t.type&&(t.contact||t.lock)?W`
@@ -6358,7 +6358,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8
-
`}_gridLevels(){const t=this._stageEl,e=this._viewOr(this._baseVb()),i=t&&t.clientWidth&&e.w?t.clientWidth/e.w:1;return function(t,e,i=7){if(!(t>0&&e>0&&Number.isFinite(e)))return null;const s=Bc.find(s=>t*s*e>=i);if(void 0===s)return null;const n=Bc.find(t=>t>=5*s)??5*s;return{fine:s,coarse:n}}(this._gridPitch,i)}_renderMarkupDefs(t){const e=this._gridLevels();if(!e)return j``;const i=this._gridPitch*e.fine,s=this._gridPitch*e.coarse,n=this._gridPitch*e.fine*.14;return j` +
`}_gridLevels(){const t=this._stageEl,e=this._viewOr(this._baseVb()),i=t&&t.clientWidth&&e.w?t.clientWidth/e.w:1;return function(t,e,i=7){if(!(t>0&&e>0&&Number.isFinite(e)))return null;const s=qc.find(s=>t*s*e>=i);if(void 0===s)return null;const n=qc.find(t=>t>=5*s)??5*s;return{fine:s,coarse:n}}(this._gridPitch,i)}_renderMarkupDefs(t){const e=this._gridLevels();if(!e)return j``;const i=this._gridPitch*e.fine,s=this._gridPitch*e.coarse,n=this._gridPitch*e.fine*.14;return j` @@ -6372,42 +6372,42 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8 - `}_renderPhysicalEditorLayer(){const t=this._spaceModel();if(!t)return j``;const e=this._gridPitch,i=this._viewOr(this._baseVb()),s=this._stageEl,n=s?.clientWidth?i.w/s.clientWidth:e/8,o=Math.max(.22*e,8*n),r=Math.max(o,12*n),a=t=>`M ${t.map(t=>`${t[0]} ${t[1]}`).join(" L ")} Z`,l=(t,e)=>this._physicalSel?.kind===t&&this._physicalSel.id===e||"column"===t&&this._duplicateColumnId===e,c=(t.room_drafts||[]).flatMap(t=>t.points.slice(0,-1).map((e,i)=>{const s=t.points[i+1],o=xa(t.segments[i]?.cm||15,this._cellCm,this._gridPitch);return j``}_renderPhysicalEditorLayer(){const t=this._spaceModel();if(!t)return j``;const e=this._gridPitch,i=this._viewOr(this._baseVb()),s=this._stageEl,n=s?.clientWidth?i.w/s.clientWidth:e/8,o=Math.max(.22*e,8*n),a=Math.max(o,12*n),r=t=>`M ${t.map(t=>`${t[0]} ${t[1]}`).join(" L ")} Z`,l=(t,e)=>this._physicalSel?.kind===t&&this._physicalSel.id===e||"column"===t&&this._duplicateColumnId===e,c=(t.room_drafts||[]).flatMap(t=>t.points.slice(0,-1).map((e,i)=>{const s=t.points[i+1],o=xr(t.segments[i]?.cm||15,this._cellCm,this._gridPitch);return j`{this._physicalSel={kind:"draft",id:t.id,segment:i},this._registerPhysicalTap("draft",t.id,i)}}>`})),h=(t.partitions||[]).map(t=>{const e=Vl(t.a,t.b,t.cm,this._cellCm,this._gridPitch);return e?j`{this._physicalSel={kind:"draft",id:t.id,segment:i},this._registerPhysicalTap("draft",t.id,i)}}>`})),h=(t.partitions||[]).map(t=>{const e=Kl(t.a,t.b,t.cm,this._cellCm,this._gridPitch);return e?j`this._physicalDown(e,"partition",t.id)} @pointermove=${t=>this._physicalMove(t)} - @pointerup=${t=>this._physicalUp(t)}>`:G}),d=(t.wall_columns||[]).map(t=>{const e=Kl(this._physicalRotate?.id===t.id?{...t,angle:this._physicalRotate.angle}:t,this._cellCm,this._gridPitch);return j`this._physicalUp(t)}>`:G}),d=(t.wall_columns||[]).map(t=>{const e=Yl(this._physicalRotate?.id===t.id?{...t,angle:this._physicalRotate.angle}:t,this._cellCm,this._gridPitch);return j`this._physicalDown(e,"column",t.id)} @pointermove=${t=>this._physicalMove(t)} - @pointerup=${t=>this._physicalUp(t)}>`}),p=this._physicalDrag,u=(()=>{if(!p?.moved)return G;const t="partition"===p.kind?Vl(p.base.a,p.base.b,p.base.cm,this._cellCm,this._gridPitch):Kl(p.base,this._cellCm,this._gridPitch);return t?j`this._physicalUp(t)}>`}),p=this._physicalDrag,u=(()=>{if(!p?.moved)return G;const t="partition"===p.kind?Kl(p.base.a,p.base.b,p.base.cm,this._cellCm,this._gridPitch):Yl(p.base,this._cellCm,this._gridPitch);return t?j``:G})(),_=(()=>{const i=this._physicalSel;if(!i)return G;if("draft"===i.kind){const e=t.room_drafts.find(t=>t.id===i.id);return e?j` t.join(",")).join(" ")}> ${e.points.map(t=>j``)} - `:G}if("partition"===i.kind){const e=t.partitions.find(t=>t.id===i.id);if(!e)return G;const s=Vl(e.a,e.b,e.cm,this._cellCm,this._gridPitch);if(!s)return G;const n=(e.a[0]+e.b[0])/2,r=(e.a[1]+e.b[1])/2;return j` - + `:G}if("partition"===i.kind){const e=t.partitions.find(t=>t.id===i.id);if(!e)return G;const s=Kl(e.a,e.b,e.cm,this._cellCm,this._gridPitch);if(!s)return G;const n=(e.a[0]+e.b[0])/2,a=(e.a[1]+e.b[1])/2;return j` + - - `}const s=t.wall_columns.find(t=>t.id===i.id);if(!s)return G;const l=this._physicalRotate?.id===s.id?{...s,angle:this._physicalRotate.angle}:s,c=Kl(l,this._cellCm,this._gridPitch);if("square"!==l.shape)return j` - + + `}const s=t.wall_columns.find(t=>t.id===i.id);if(!s)return G;const l=this._physicalRotate?.id===s.id?{...s,angle:this._physicalRotate.angle}:s,c=Yl(l,this._cellCm,this._gridPitch);if("square"!==l.shape)return j` + - `;const h=xa(l.cm,this._cellCm,this._gridPitch),d=ql(l.angle)*Math.PI/180,p=Math.sin(d),u=-Math.cos(d),_=[l.center[0]+p*h/2,l.center[1]+u*h/2],g=[_[0]+p*Math.max(e,24*n),_[1]+u*Math.max(e,24*n)];return j` - + `;const h=xr(l.cm,this._cellCm,this._gridPitch),d=Wl(l.angle)*Math.PI/180,p=Math.sin(d),u=-Math.cos(d),_=[l.center[0]+p*h/2,l.center[1]+u*h/2],g=[_[0]+p*Math.max(e,24*n),_[1]+u*Math.max(e,24*n)];return j` + - this._physicalRotateDown(t,s)} @pointermove=${t=>this._physicalRotateMove(t)} @pointerup=${t=>this._physicalRotateUp(t)}> - `})();return j`${c}${h}${d}${u}${_}`}_renderPlanSnapOverlay(){if(!this._markup||"draw"!==this._tool)return j``;const t=this._planSnapGeometrySnapshot().value,e=this._activePlanSnapCandidate,i=new Set(this._activePlanSnapConflicts.map(t=>t.key)),s=xa(5,this._cellCm,this._gridPitch),n=xa(10,this._cellCm,this._gridPitch);return j``})();return j`${c}${h}${d}${u}${_}`}_renderPlanSnapOverlay(){if(!this._markup||"draw"!==this._tool)return j``;const t=this._planSnapGeometrySnapshot().value,e=this._activePlanSnapCandidate,i=new Set(this._activePlanSnapConflicts.map(t=>t.key)),s=xr(5,this._cellCm,this._gridPitch),n=xr(10,this._cellCm,this._gridPitch);return j``}_syncPlanSnapActiveMarker(t){const e=this.renderRoot?.querySelector('[data-hp="plan-snap-active-marker"]');if(e){if(e.setAttribute("class",`plan-snap-node${t?" active":""}${"line"===t?.kind?" dynamic":""}`),e.setAttribute("data-active",t?"true":"false"),e.setAttribute("visibility",t?"visible":"hidden"),!t)return e.removeAttribute("data-kind"),void e.removeAttribute("data-key");e.setAttribute("data-kind",t.kind),e.setAttribute("data-key",t.key),e.setAttribute("cx",String(t.point[0])),e.setAttribute("cy",String(t.point[1])),e.setAttribute("r",String(xa(10,this._cellCm,this._gridPitch)))}}_syncPlanSnapConflictMarkers(t){const e=new Set(t.map(t=>t.key));for(const t of this.renderRoot?.querySelectorAll('.plan-snap-node[data-kind="endpoint"]')||[])t.setAttribute("class","plan-snap-node"+(e.has(t.dataset.key||"")?" conflict":""))}_planSnapPhysicalSegment(t){let e=0;const i=this._spaceModel();if(!i)return null;if("partition"===t.sourceKind)e=Number(i.partitions.find(e=>e.id===t.sourceId)?.cm)||0;else if("draft"===t.sourceKind){const s=/^(.*):(\d+)$/.exec(t.sourceId),n=s?i.room_drafts.find(t=>t.id===s[1]):null;e=n&&s&&Number(n.segments[Number(s[2])]?.cm)||0}else e=_l(i.rooms,this._spaceWalls,this._openCuts(),[t.a[0],t.a[1],t.b[0],t.b[1]],this._wallKeyPitch,this._cellCm,this._gridPitch,pm);return e>0?{a:[...t.a],b:[...t.b],halfDepth:xa(e,this._cellCm,this._gridPitch)/2}:null}_drawPreviewJoinPatchD(t,e){if(t.length<2)return"";const i=[];for(let s=0;s+10&&i.push({a:t[s],b:t[s+1],halfDepth:e[s]});if(!i.length)return"";const s=2e-4*this._gridPitch,n=this._planSnapGeometrySnapshot().value.segments.filter(e=>t.some(t=>Hs(t,[e.a[0],e.a[1],e.b[0],e.b[1]])<=s)).map(t=>this._planSnapPhysicalSegment(t)).filter(t=>!!t);return Ua([...i,...n],s).map(t=>`M ${t.map(t=>`${t[0]} ${t[1]}`).join(" L ")} Z`).join(" ")}_renderMarkupLayer(t){const e=this._openPairs().flatMap(t=>t.segs),i=this._thickWallCuts(),s=e.concat(i),n=s.length?Ds(this._segments,s,.02*this._gridPitch):this._segments,o=this._path,r=this._gridPitch,a=this._viewOr(this._baseVb()),l="draw"===this._tool?this._drawWallCm:null,c=(()=>"draw"===this._tool&&o.length&&null!=l&&l>0?this._contourClosed?o:this._cursorPt?[...o,this._cursorPt]:o.length>=2?o:null:null)(),h=c?Qd(c.length-1,this._contourClosed?[...this._draftSegmentCms,this._closingWallCm??void 0]:this._draftSegmentCms,l,fa).map(t=>xa(t,this._cellCm,this._gridPitch)/2):[],d=c?Ga(c,xa(l,this._cellCm,this._gridPitch)/2,this._contourClosed,h):"",p=c?this._drawPreviewJoinPatchD(c,h):"",u=this._wallFaceBatch?.candidates[this._wallFaceBatch.index]?.repair||this._wallRepairDiagnostic;return j` - ${this._gridLevels()?j``:G} + `}_syncPlanSnapActiveMarker(t){const e=this.renderRoot?.querySelector('[data-hp="plan-snap-active-marker"]');if(e){if(e.setAttribute("class",`plan-snap-node${t?" active":""}${"line"===t?.kind?" dynamic":""}`),e.setAttribute("data-active",t?"true":"false"),e.setAttribute("visibility",t?"visible":"hidden"),!t)return e.removeAttribute("data-kind"),void e.removeAttribute("data-key");e.setAttribute("data-kind",t.kind),e.setAttribute("data-key",t.key),e.setAttribute("cx",String(t.point[0])),e.setAttribute("cy",String(t.point[1])),e.setAttribute("r",String(xr(10,this._cellCm,this._gridPitch)))}}_syncPlanSnapConflictMarkers(t){const e=new Set(t.map(t=>t.key));for(const t of this.renderRoot?.querySelectorAll('.plan-snap-node[data-kind="endpoint"]')||[])t.setAttribute("class","plan-snap-node"+(e.has(t.dataset.key||"")?" conflict":""))}_planSnapPhysicalSegment(t){let e=0;const i=this._spaceModel();if(!i)return null;if("partition"===t.sourceKind)e=Number(i.partitions.find(e=>e.id===t.sourceId)?.cm)||0;else if("draft"===t.sourceKind){const s=/^(.*):(\d+)$/.exec(t.sourceId),n=s?i.room_drafts.find(t=>t.id===s[1]):null;e=n&&s&&Number(n.segments[Number(s[2])]?.cm)||0}else e=_l(i.rooms,this._spaceWalls,this._openCuts(),[t.a[0],t.a[1],t.b[0],t.b[1]],this._wallKeyPitch,this._cellCm,this._gridPitch,um);return e>0?{a:[...t.a],b:[...t.b],halfDepth:xr(e,this._cellCm,this._gridPitch)/2}:null}_drawPreviewJoinPatchD(t,e){if(t.length<2)return"";const i=[];for(let s=0;s+10&&i.push({a:t[s],b:t[s+1],halfDepth:e[s]});if(!i.length)return"";const s=2e-4*this._gridPitch,n=this._planSnapGeometrySnapshot().value.segments.filter(e=>t.some(t=>Hs(t,[e.a[0],e.a[1],e.b[0],e.b[1]])<=s)).map(t=>this._planSnapPhysicalSegment(t)).filter(t=>!!t);return Ur([...i,...n],s).map(t=>`M ${t.map(t=>`${t[0]} ${t[1]}`).join(" L ")} Z`).join(" ")}_renderMarkupLayer(t){const e=this._openPairs().flatMap(t=>t.segs),i=this._thickWallCuts(),s=e.concat(i),n=s.length?Ds(this._segments,s,.02*this._gridPitch):this._segments,o=this._path,a=this._gridPitch,r=this._viewOr(this._baseVb()),l="draw"===this._tool?this._drawWallCm:null,c=(()=>"draw"===this._tool&&o.length&&null!=l&&l>0?this._contourClosed?o:this._cursorPt?[...o,this._cursorPt]:o.length>=2?o:null:null)(),h=c?tp(c.length-1,this._contourClosed?[...this._draftSegmentCms,this._closingWallCm??void 0]:this._draftSegmentCms,l,fr).map(t=>xr(t,this._cellCm,this._gridPitch)/2):[],d=c?Gr(c,xr(l,this._cellCm,this._gridPitch)/2,this._contourClosed,h):"",p=c?this._drawPreviewJoinPatchD(c,h):"",u=this._wallFaceBatch?.candidates[this._wallFaceBatch.index]?.repair||this._wallRepairDiagnostic;return j` + ${this._gridLevels()?j``:G} ${n.map(t=>j``)} ${this._renderPhysicalEditorLayer()} - ${"column"===this._tool&&this._cursorPt&&this._drawWallCm?j``M ${Kl({shape:"square",center:this._cursorPt,cm:this._drawWallCm},this._cellCm,this._gridPitch).map(t=>`${t[0]} ${t[1]}`).join(" L ")} Z`)()}>`:G} + ${"column"===this._tool&&this._cursorPt&&this._drawWallCm?j``M ${Yl({shape:"square",center:this._cursorPt,cm:this._drawWallCm},this._cellCm,this._gridPitch).map(t=>`${t[0]} ${t[1]}`).join(" L ")} Z`)()}>`:G} ${d?j` `:G} ${p?j` @@ -6444,12 +6444,12 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8 ${o.length&&this._cursorPt&&"draw"===this._tool&&!this._contourClosed?j` ${this._activePlanSnapCandidate||this._activePlanSnapConflicts.length?G:j``}`:G} + r="${hc(.22*a,this._cellCm)}" aria-hidden="true">`}`:G} ${o.map((t,e)=>j``)} + cx="${t[0]}" cy="${t[1]}" r="${hc(.22*a,this._cellCm)}">`)} ${"split"===this._tool&&this._splitSel?.pts?.length?j`${this._splitSel.pts.length>1?j``:G} ${this._splitSel.pts.map((t,e)=>j``)} + cx="${t[0]}" cy="${t[1]}" r="${hc(.22*a,this._cellCm)}">`)} ${this._cursorPt?j``:G}`:G} `}_renderPartitionDeleteDialog(){const t=this._partitionDeleteDialog,e="mi"===this.hass?.config?.unit_system?.length;return W`

${this._t("confirm.delete_partition_openings_body",{count:t.openings.length})}

    - ${t.openings.map(t=>W`
  • ${this._t("confirm.delete_partition_openings_item",{type:this._t(`opening.${t.type}`),length:li(t.length*pm/this._gridPitch*this._cellCm,e)})}
  • `)} + ${t.openings.map(t=>W`
  • ${this._t("confirm.delete_partition_openings_item",{type:this._t(`opening.${t.type}`),length:li(t.length*um/this._gridPitch*this._cellCm,e)})}
  • `)}
@@ -6502,8 +6502,8 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8 `:G}
this._physicalDialog={...t,cm:e.target.value}} /> ${this._t(this._imperial?"wallthick.unit_in":"wallthick.unit_cm")}
${e&&"square"===t.shape?W` @@ -6663,7 +6663,7 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8 `:G}
- `}_markerValueBadgeFields(t){return(e={touched:t.valueBadgeTouched,originalHas:t.originalHasValueBadge,original:t.originalValueBadge,enabled:t.valueBadgeEnabled,source:t.valueBadgeSource,position:t.valueBadgePosition}).touched?{value_badge:{enabled:e.enabled,source:e.source,position:e.position}}:e.originalHas?{value_badge:e.original}:{};var e}_markerDraft(t){if("ha"===t.bindingMode&&(!t.binding||"virtual"===t.binding))return null;const e=qs(t.room),i=Ei(t.binding,t.devId,()=>"__hp_device_preview__"),s=this._markers.find(e=>e.id===i||e.id===t.devId),n=Zn(t.binding,t.controls,this._bindingEntities(t.binding)),o=this._effectiveStoredTapAction(t),r={id:i,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||null,...this._markerTapActionFields(t),...this._markerToggleEntityFields(t),tap_target:"run"===o&&t.tapTarget||null,tap_confirm:!!t.tapConfirm||null,controls:n.length?n:null,...this._markerLightFields(t),...this._markerValueBadgeFields(t),use_climate_temp:!!t.useClimateTemp||null,glow_radius_cm:(()=>{const e=Zg(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,vacuum:s?.vacuum||null};return("virtual"===t.binding||t.room)&&(r.space=e?.space||("virtual"===t.binding?this._space:null),r.area=e?.area||null,r.room_id=e?.roomId||null),r}_markerPreviewDevice(t){const e=this._markerDraft(t);if(!e)return null;const i=`${this._haRegistry.revision}\n${JSON.stringify(e)}`;if(this._markerPreviewMemo?.key===i)return this._markerPreviewMemo.device;const s=function(t){const{marker:e,...i}=t;return So({...i,markers:[e]}).find(t=>t.id===e.id)||null}({hass:this.hass,registry:this._haRegistry,areaToSpace:Object.fromEntries(Object.entries(this._areaToSpace).map(([t,e])=>[t,e.space])),marker:e,settings:this._settings,excluded:this._excluded,showAll:this._showAll,firstSpaceId:this._model[0]?.id||this._space,loc:t=>this._t(t),iconRules:this._iconRules});return this._markerPreviewMemo={key:i,device:s},s}_markerPreviewDevices(t){const e=this._markerPreviewDevicesMemo;if(e?.base===this._devices&&e.preview===t)return e.devices;const i=[...this._devices.filter(e=>e.id!==t.id),t];return this._markerPreviewDevicesMemo={base:this._devices,preview:t,devices:i},i}_toggleIntent(t,e=this._devices){return xd({hass:this._planHass,registryHass:this._fullRegistryHass,devices:e,device:t,virtualLights:this._virtualLights})}_toggleIntentForDialog(t){const e=this._markerPreviewDevice(t);if(!e)return null;const i=this._markerPreviewDevices(e);return this._toggleIntent(e,i)}_toggleStateText(t,e){const i=this._planHass?.states?.[t]||this.hass?.states?.[t];try{return i&&"function"==typeof this.hass?.formatEntityState?this.hass.formatEntityState(i):e}catch{return e}}_toggleConfirmationStateText(t){const e=String(t.state||"unknown"),i=t.entityId?this._toggleStateText(t.entityId,e):e;if(i.trim().toLocaleLowerCase()!==e.trim().toLocaleLowerCase())return i;const s={on:"confirm.state_on",off:"confirm.state_off",open:"confirm.state_open",closed:"confirm.state_closed",opening:"confirm.state_opening",closing:"confirm.state_closing",unknown:"confirm.state_unknown"}[e];return s?this._t(s):e.replaceAll("_"," ").replaceAll("-"," ")}_toggleConfirmationLines(t){const e={"turn-on":"confirm.state_on","turn-off":"confirm.state_off",open:"confirm.state_open",close:"confirm.state_closed",stop:"confirm.state_stopped"};return function(t,e){if(!Sd(t)||!t.nextEffect||!t.targets.length)return[];const i="group"===t.kind,s=i?t.targets.filter(t=>"on"===t.state).length:0,n=i?0===s?e.groupAllOff():e.groupCurrent(s,t.targets.length):e.state(t.targets[0]);let o;return o="toggle"===t.nextEffect?e.expectedByHa():i&&"turn-on"===t.nextEffect?e.groupAllOn():i&&"turn-off"===t.nextEffect?e.groupAllOff():e.effect(t.nextEffect),[e.current(n),e.expected(o),...t.skippedTargets.length?[e.unavailable(t.skippedTargets.length)]:[]]}(t,{state:t=>this._toggleConfirmationStateText(t),current:t=>this._t("confirm.current_state",{state:t}),expected:t=>this._t("confirm.expected_state",{state:t}),groupCurrent:(t,e)=>this._t("confirm.group_current",{on:t,total:e}),groupAllOn:()=>this._t("confirm.group_all_on"),groupAllOff:()=>this._t("confirm.group_all_off"),unavailable:t=>this._t("confirm.unavailable_targets",{count:t}),effect:t=>this._t(e[t]),expectedByHa:()=>this._t("confirm.expected_by_ha")})}_toggleHintLines(t){if(!t)return[];const e=t=>this._t(`marker.toggle_effect_${t.replace("-","_")}`),i=t=>this._t(`marker.toggle_skip_${t.replace("-","_")}`);return function(t,e){const i=t.targets[0]||t.skippedTargets[0],s=[];return"group"===t.kind?t.targets.length&&s.push(e.group(t.targets)):i&&s.push(e.single(i)),t.nextEffect&&t.targets.length&&s.push("group"===t.kind?e.groupCurrentNext(t.targets,t.nextEffect):e.currentNext(t.targets[0],t.nextEffect)),t.skippedTargets.length&&s.push(e.skipped(t.skippedTargets)),!t.command&&t.noneReason&&s.push(e.none(t.noneReason)),s}(t,{single:t=>{if("via"in t&&"virtual-light"===t.via)return this._t("marker.virtual_light_target",{name:t.name});const e=t.entityId||("ref"in t?t.ref:""),i=t.name||e;return this._t("marker.toggle_hint_single",{name:i,id:e})},group:t=>this._t("marker.toggle_hint_group",{count:t.length,names:t.map(t=>`${t.name} (${t.entityId})`).join(", ")}),currentNext:(t,i)=>"virtual-light"===t.via?this._t("marker.virtual_light_current",{state:this._t("on"===t.state?"marker.virtual_light_state_on":"marker.virtual_light_state_off"),effect:e(i)}):this._t("marker.toggle_hint_current",{state:this._toggleStateText(t.entityId,t.state),effect:e(i)}),groupCurrentNext:(t,i)=>this._t("marker.toggle_hint_group_current",{on:t.filter(t=>"on"===t.state).length,count:t.length,effect:e(i)}),skipped:t=>this._t("marker.toggle_hint_skipped",{count:t.length,targets:t.map(t=>{const e=t.entityId||t.ref;return`${t.name||e} (${e}: ${i(t.reason)})`}).join(", ")}),none:t=>this._t(`marker.toggle_none_${t.replaceAll("-","_")}`)})}_effectiveStoredTapAction(t,e){return t.tapActionTouched?t.tapAction:yd(t.originalHasTapAction?t.originalTapAction:null,e)}_effectiveMarkerTapAction(t,e=this._markerPreviewDevice(t)){return this._effectiveStoredTapAction(t,e?.primary?.split(".")[0])}_announceToggleDraft(t){const e=this._markerPreviewDevice(t),i=t.tapActionTouched?t:{...t,tapAction:this._effectiveMarkerTapAction(t,e)},s="toggle"===i.tapAction?this._toggleHintLines(this._toggleIntentForDialog(i)).join(" "):"";return{...i,tapHintAnnouncement:s}}_valueBadgeForBinding(t,e){const i={...t,binding:e,valueBadgeEnabled:!1,valueBadgeSource:null,valueBadgeTouched:!0},s=this._markerPreviewDevice(i);if(!s)return{valueBadgeEnabled:!1,valueBadgeSource:null,valueBadgeTouched:!0};const n=[...this._devices.filter(t=>t.id!==s.id),s],o=Wo(this._planHass,s,n),r=jo(this._planHass,s,o);return{valueBadgeEnabled:t.valueBadgeEnabled&&!!r,valueBadgeSource:r,valueBadgeTouched:!0}}_markerSpatialSource(t){const e=this._markerPreviewDevice(t);if(!e)return null;const i={...e,hidden:!1};return po(ho(this._planHass,[...this._devices.filter(t=>t.id!==i.id),i],null,this._virtualLights).filter(t=>t.device.id===i.id))}_markerAutoHasSpatialSource(t){const e={...t,lightRole:"auto",lightRoleTouched:!0},i=this._markerPreviewDevice(e);return!!i&&lo(this._planHass,{...i})}_setMarkerLightRole(t){const e=this._markerDialog;e&&(this._markerDialog={...e,lightRole:t,lightRoleTouched:!0})}_controlRefInfo(t){if(!t.startsWith("marker:"))return{label:this.hass.states[t]?.attributes?.friendly_name||t,sub:t,icon:t.startsWith("light.")?"mdi:lightbulb":"mdi:toggle-switch",warning:!this._planEntityAvailable(t)};const e=t.slice(7),i=this._markers.find(t=>t.id===e),s=this._devices.find(t=>t.id===e);if(!i||i.removed||!0!==i.is_light)return{label:this._t("marker.control_missing_label"),sub:`${this._t("marker.control_broken")} (${t})`,icon:"mdi:alert-outline",warning:!0};const n=this._serverCfg?.spaces.find(t=>t.id===(s?.space||i.space)),o=!!s&&to(s).length>0;return{label:i.name||s?.name||e,sub:[n?.title||s?.space||i.space,i.room_id||s?.area,o?"":this._t("marker.control_passive")].filter(Boolean).join(" · "),icon:i.icon||s?.icon||"mdi:lightbulb-outline",warning:!0===i.hidden||!0===s?.hidden}}_valueBadgeCandidateLabel(t){const e=t.source;if("derived_lqi"===e.kind)return this._t("marker.value_badge_lqi");if("derived_marker_state"===e.kind)return this._t("marker.value_badge_marker_state",{name:t.label});if("entity_state"===e.kind)return this._t("marker.value_badge_state",{name:t.label});const i=this.hass.states[e.entity_id]?.attributes?.friendly_name||this._fullRegistryHass.entities[e.entity_id]?.name||e.entity_id;return this._t(`marker.value_badge_attr_${e.attribute}`,{name:i})}_controlCandidates(t){const e=this._markerDraft(t)?.id||t.devId||"",i=[],s=new Set;for(const t of this._markers){if(t.id===e||t.removed||t.hidden||!0!==t.is_light)continue;if("virtual"!==t.binding&&"active"!==this._bindingStatus(t.binding).kind)continue;const n=this._devices.find(e=>e.id===t.id);if(!n||n.hidden)continue;const o=this._controlRefInfo(`marker:${t.id}`);for(const t of to(n))s.add(t);i.push({value:`marker:${t.id}`,label:o.label,sub:o.sub,icon:o.icon,search:`${o.label} ${o.sub} ${t.id} ${to(n).join(" ")}`.toLowerCase()})}const n=Object.keys(this.hass.states||{}).filter(e=>Ms(e)&&!s.has(e)&&Jn(t.binding,[e],this._bindingEntities(t.binding)).length>0&&this._planEntityAvailable(e)).map(t=>{const e=this._controlRefInfo(t);return{value:t,label:e.label,sub:t,icon:e.icon,search:`${e.label} ${t}`.toLowerCase()}}),o=t.controlsFilter.trim().toLowerCase();return[...i,...n].filter(e=>!t.controls.includes(e.value)&&(!o||e.search.includes(o))).slice(0,12).map(({search:t,...e})=>e)}_addControlRef(t,e){if(e.startsWith("marker:")){const i=this._markerDraft(t)?.id||t.devId||"";if(!i)return void this._showToast(this._t("toast.marker_binding_required"));const s=e.slice(7),n=this._markerDraft(t);if(function(t,e,i){if(!e||e===i)return!0;const s=new Map;for(const e of t)s.set(e.id,(e.controls||[]).filter(t=>"string"==typeof t&&t.startsWith("marker:")).map(t=>t.slice(7)));const n=new Set,o=[i];for(;o.length;){const t=o.pop();if(t===e)return!0;n.has(t)||(n.add(t),o.push(...s.get(t)||[]))}return!1}(n?[...this._markers.filter(t=>t.id!==i),n]:this._markers,i,s))return void this._showToast(this._t("toast.marker_control_cycle"))}this._markerDialog=this._announceToggleDraft({...t,controls:[...t.controls,e],controlsFilter:""})}_setMarkerGlowMode(t){const e=this._markerDialog;if(!e)return;if("auto"===t)return void(this._markerDialog={...e,glowMode:t,glowTouched:!0});const i=this._markerSpatialSource(e),s=xs(i?this._planHass.states[i.eid]:void 0,null,this._fillColors.glow_light.c),n=!e.glowColorDrafted,o="fixed"===t&&!e.glowBrightnessDrafted;this._markerDialog={...e,glowMode:t,glowColor:n?s.c:e.glowColor,glowBrightness:o?Math.max(1,Math.round(100*s.bri)):e.glowBrightness,glowColorDrafted:!0,glowBrightnessDrafted:e.glowBrightnessDrafted||"fixed"===t,glowTouched:!0}}_renderMarkerDialog(){const t=this._markerDialog,e="virtual"===t.bindingMode,i=this._bindingCandidates();this._bindingEntities(t.binding);const s=e?null:this._bindingStatus(t.binding),n=!e&&this._bindingHasHaPage(t.binding),o=this._markerPreviewDevice(t),r=this._effectiveMarkerTapAction(t,o),a=o?cs(this._serverCfg?.spaces.find(t=>t.id===o.space)):null,l=o?this._markerPreviewDevices(o):this._devices,c="toggle"===r&&o?this._toggleIntent(o,l):null,h=this._toggleHintLines(c),d=o?iu(this._planHass,o,{liveStates:!1!==this._config?.live_states,showTemperature:!1!==this._config?.show_temperature,showSignal:a?.showLqi??!1!==this._config?.show_signal,designPreview:!0,activityRuntime:this._activityRt.get(o.id),lightDevices:l,registryHass:this._fullRegistryHass,reducedMotion:this._reducedMotion}):null,p=o?Wo(this._planHass,o,l):[],u=o?jo(this._planHass,o,p):null,_=t.valueBadgeTouched?t.valueBadgeEnabled:!!d?.valueBadge,g=t.valueBadgeTouched?t.valueBadgeSource:d?.valueBadge?.source||t.valueBadgeSource,m=t.valueBadgeTouched?t.valueBadgePosition:d?.valueBadge?.position||t.valueBadgePosition,f=Ao(g),v=!!g&&!p.some(t=>t.key===f),y=p.find(t=>t.key===f),b=d?.valueSource?d.valueSource.attribute?`attr:${d.valueSource.eid}:${d.valueSource.attribute}`:`state:${d.valueSource.eid}`:"",w=this._markerAutoHasSpatialSource(t),k=!!o&&function(t,e){return io(t,e).some(t=>!!t.eid)}(this._planHass,{...o}),x=function(t,e,i,s){const n="always"===t||"auto"===t&&e,o=n&&!i;return{sourceExists:n,fromSourceEnabled:n&&i,manualEnabled:n,radiusEnabled:n,passive:o,effectiveMode:o&&"auto"===s?"fixed":s}}(t.lightRole,w,k,t.glowMode),$=!x.sourceExists,S=!x.fromSourceEnabled,M=x.passive,C=x.effectiveMode,D="never"===t.lightRole?this._t("marker.glow_disabled_never"):"auto"!==t.lightRole||w?M?this._t("marker.glow_passive_hint"):this._t("marker.glow_disabled_no_entity"):this._t("marker.glow_disabled_auto"),T=o?to(o):[],P=o&&eo(o)||"",R=!!t.lightEntity&&!T.includes(t.lightEntity),I=o?_d(o):[],A=!!t.toggleEntity&&!I.includes(t.toggleEntity),F="toggle"===r?this._toggleIntentForDialog({...t,toggleEntity:"",toggleEntityTouched:!0}):null,E=F?[...F.targets,...F.skippedTargets].map(t=>t.entityId||("ref"in t?t.ref:"")).filter(Boolean).join(", "):"",z=(()=>{if(e)return null;const s=i.find(e=>e.value===t.binding);if(s)return s.label;const[n,o]=t.binding.split(":");return"device"===n?this._fullRegistryHass.devices[o]?.name_by_user||this._fullRegistryHass.devices[o]?.name||o:this._fullRegistryHass.entities[o]?.name||this.hass.states[o]?.attributes?.friendly_name||o})();return W``}_markerValueBadgeFields(t){return(e={touched:t.valueBadgeTouched,originalHas:t.originalHasValueBadge,original:t.originalValueBadge,enabled:t.valueBadgeEnabled,source:t.valueBadgeSource,position:t.valueBadgePosition}).touched?{value_badge:{enabled:e.enabled,source:e.source,position:e.position}}:e.originalHas?{value_badge:e.original}:{};var e}_markerDraft(t){if("ha"===t.bindingMode&&(!t.binding||"virtual"===t.binding))return null;const e=qs(t.room),i=Ei(t.binding,t.devId,()=>"__hp_device_preview__"),s=this._markers.find(e=>e.id===i||e.id===t.devId),n=Zn(t.binding,t.controls,this._bindingEntities(t.binding)),o=this._effectiveStoredTapAction(t),a={id:i,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||null,...this._markerTapActionFields(t),...this._markerToggleEntityFields(t),tap_target:"run"===o&&t.tapTarget||null,tap_confirm:!!t.tapConfirm||null,controls:n.length?n:null,...this._markerLightFields(t),...this._markerValueBadgeFields(t),use_climate_temp:!!t.useClimateTemp||null,glow_radius_cm:(()=>{const e=Qg(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,vacuum:s?.vacuum||null};return("virtual"===t.binding||t.room)&&(a.space=e?.space||("virtual"===t.binding?this._space:null),a.area=e?.area||null,a.room_id=e?.roomId||null),a}_markerPreviewDevice(t){const e=this._markerDraft(t);if(!e)return null;const i=`${this._haRegistry.revision}\n${JSON.stringify(e)}`;if(this._markerPreviewMemo?.key===i)return this._markerPreviewMemo.device;const s=function(t){const{marker:e,...i}=t;return So({...i,markers:[e]}).find(t=>t.id===e.id)||null}({hass:this.hass,registry:this._haRegistry,areaToSpace:Object.fromEntries(Object.entries(this._areaToSpace).map(([t,e])=>[t,e.space])),marker:e,settings:this._settings,excluded:this._excluded,showAll:this._showAll,firstSpaceId:this._model[0]?.id||this._space,loc:t=>this._t(t),iconRules:this._iconRules});return this._markerPreviewMemo={key:i,device:s},s}_markerPreviewDevices(t){const e=this._markerPreviewDevicesMemo;if(e?.base===this._devices&&e.preview===t)return e.devices;const i=[...this._devices.filter(e=>e.id!==t.id),t];return this._markerPreviewDevicesMemo={base:this._devices,preview:t,devices:i},i}_toggleIntent(t,e=this._devices){return $d({hass:this._planHass,registryHass:this._fullRegistryHass,devices:e,device:t,virtualLights:this._virtualLights})}_toggleIntentForDialog(t){const e=this._markerPreviewDevice(t);if(!e)return null;const i=this._markerPreviewDevices(e);return this._toggleIntent(e,i)}_toggleStateText(t,e){const i=this._planHass?.states?.[t]||this.hass?.states?.[t];try{return i&&"function"==typeof this.hass?.formatEntityState?this.hass.formatEntityState(i):e}catch{return e}}_toggleConfirmationStateText(t){const e=String(t.state||"unknown"),i=t.entityId?this._toggleStateText(t.entityId,e):e;if(i.trim().toLocaleLowerCase()!==e.trim().toLocaleLowerCase())return i;const s={on:"confirm.state_on",off:"confirm.state_off",open:"confirm.state_open",closed:"confirm.state_closed",opening:"confirm.state_opening",closing:"confirm.state_closing",unknown:"confirm.state_unknown"}[e];return s?this._t(s):e.replaceAll("_"," ").replaceAll("-"," ")}_toggleConfirmationLines(t){const e={"turn-on":"confirm.state_on","turn-off":"confirm.state_off",open:"confirm.state_open",close:"confirm.state_closed",stop:"confirm.state_stopped"};return function(t,e){if(!Md(t)||!t.nextEffect||!t.targets.length)return[];const i="group"===t.kind,s=i?t.targets.filter(t=>"on"===t.state).length:0,n=i?0===s?e.groupAllOff():e.groupCurrent(s,t.targets.length):e.state(t.targets[0]);let o;return o="toggle"===t.nextEffect?e.expectedByHa():i&&"turn-on"===t.nextEffect?e.groupAllOn():i&&"turn-off"===t.nextEffect?e.groupAllOff():e.effect(t.nextEffect),[e.current(n),e.expected(o),...t.skippedTargets.length?[e.unavailable(t.skippedTargets.length)]:[]]}(t,{state:t=>this._toggleConfirmationStateText(t),current:t=>this._t("confirm.current_state",{state:t}),expected:t=>this._t("confirm.expected_state",{state:t}),groupCurrent:(t,e)=>this._t("confirm.group_current",{on:t,total:e}),groupAllOn:()=>this._t("confirm.group_all_on"),groupAllOff:()=>this._t("confirm.group_all_off"),unavailable:t=>this._t("confirm.unavailable_targets",{count:t}),effect:t=>this._t(e[t]),expectedByHa:()=>this._t("confirm.expected_by_ha")})}_toggleHintLines(t){if(!t)return[];const e=t=>this._t(`marker.toggle_effect_${t.replace("-","_")}`),i=t=>this._t(`marker.toggle_skip_${t.replace("-","_")}`);return function(t,e){const i=t.targets[0]||t.skippedTargets[0],s=[];return"group"===t.kind?t.targets.length&&s.push(e.group(t.targets)):i&&s.push(e.single(i)),t.nextEffect&&t.targets.length&&s.push("group"===t.kind?e.groupCurrentNext(t.targets,t.nextEffect):e.currentNext(t.targets[0],t.nextEffect)),t.skippedTargets.length&&s.push(e.skipped(t.skippedTargets)),!t.command&&t.noneReason&&s.push(e.none(t.noneReason)),s}(t,{single:t=>{if("via"in t&&"virtual-light"===t.via)return this._t("marker.virtual_light_target",{name:t.name});const e=t.entityId||("ref"in t?t.ref:""),i=t.name||e;return this._t("marker.toggle_hint_single",{name:i,id:e})},group:t=>this._t("marker.toggle_hint_group",{count:t.length,names:t.map(t=>`${t.name} (${t.entityId})`).join(", ")}),currentNext:(t,i)=>"virtual-light"===t.via?this._t("marker.virtual_light_current",{state:this._t("on"===t.state?"marker.virtual_light_state_on":"marker.virtual_light_state_off"),effect:e(i)}):this._t("marker.toggle_hint_current",{state:this._toggleStateText(t.entityId,t.state),effect:e(i)}),groupCurrentNext:(t,i)=>this._t("marker.toggle_hint_group_current",{on:t.filter(t=>"on"===t.state).length,count:t.length,effect:e(i)}),skipped:t=>this._t("marker.toggle_hint_skipped",{count:t.length,targets:t.map(t=>{const e=t.entityId||t.ref;return`${t.name||e} (${e}: ${i(t.reason)})`}).join(", ")}),none:t=>this._t(`marker.toggle_none_${t.replaceAll("-","_")}`)})}_effectiveStoredTapAction(t,e){return t.tapActionTouched?t.tapAction:bd(t.originalHasTapAction?t.originalTapAction:null,e)}_effectiveMarkerTapAction(t,e=this._markerPreviewDevice(t)){return this._effectiveStoredTapAction(t,e?.primary?.split(".")[0])}_announceToggleDraft(t){const e=this._markerPreviewDevice(t),i=t.tapActionTouched?t:{...t,tapAction:this._effectiveMarkerTapAction(t,e)},s="toggle"===i.tapAction?this._toggleHintLines(this._toggleIntentForDialog(i)).join(" "):"";return{...i,tapHintAnnouncement:s}}_valueBadgeForBinding(t,e){const i={...t,binding:e,valueBadgeEnabled:!1,valueBadgeSource:null,valueBadgeTouched:!0},s=this._markerPreviewDevice(i);if(!s)return{valueBadgeEnabled:!1,valueBadgeSource:null,valueBadgeTouched:!0};const n=[...this._devices.filter(t=>t.id!==s.id),s],o=Wo(this._planHass,s,n),a=jo(this._planHass,s,o);return{valueBadgeEnabled:t.valueBadgeEnabled&&!!a,valueBadgeSource:a,valueBadgeTouched:!0}}_markerSpatialSource(t){const e=this._markerPreviewDevice(t);if(!e)return null;const i={...e,hidden:!1};return po(ho(this._planHass,[...this._devices.filter(t=>t.id!==i.id),i],null,this._virtualLights).filter(t=>t.device.id===i.id))}_markerAutoHasSpatialSource(t){const e={...t,lightRole:"auto",lightRoleTouched:!0},i=this._markerPreviewDevice(e);return!!i&&lo(this._planHass,{...i})}_setMarkerLightRole(t){const e=this._markerDialog;e&&(this._markerDialog={...e,lightRole:t,lightRoleTouched:!0})}_controlRefInfo(t){if(!t.startsWith("marker:"))return{label:this.hass.states[t]?.attributes?.friendly_name||t,sub:t,icon:t.startsWith("light.")?"mdi:lightbulb":"mdi:toggle-switch",warning:!this._planEntityAvailable(t)};const e=t.slice(7),i=this._markers.find(t=>t.id===e),s=this._devices.find(t=>t.id===e);if(!i||i.removed||!0!==i.is_light)return{label:this._t("marker.control_missing_label"),sub:`${this._t("marker.control_broken")} (${t})`,icon:"mdi:alert-outline",warning:!0};const n=this._serverCfg?.spaces.find(t=>t.id===(s?.space||i.space)),o=!!s&&to(s).length>0;return{label:i.name||s?.name||e,sub:[n?.title||s?.space||i.space,i.room_id||s?.area,o?"":this._t("marker.control_passive")].filter(Boolean).join(" · "),icon:i.icon||s?.icon||"mdi:lightbulb-outline",warning:!0===i.hidden||!0===s?.hidden}}_valueBadgeCandidateLabel(t){const e=t.source;if("derived_lqi"===e.kind)return this._t("marker.value_badge_lqi");if("derived_marker_state"===e.kind)return this._t("marker.value_badge_marker_state",{name:t.label});if("entity_state"===e.kind)return this._t("marker.value_badge_state",{name:t.label});const i=this.hass.states[e.entity_id]?.attributes?.friendly_name||this._fullRegistryHass.entities[e.entity_id]?.name||e.entity_id;return this._t(`marker.value_badge_attr_${e.attribute}`,{name:i})}_controlCandidates(t){const e=this._markerDraft(t)?.id||t.devId||"",i=[],s=new Set;for(const t of this._markers){if(t.id===e||t.removed||t.hidden||!0!==t.is_light)continue;if("virtual"!==t.binding&&"active"!==this._bindingStatus(t.binding).kind)continue;const n=this._devices.find(e=>e.id===t.id);if(!n||n.hidden)continue;const o=this._controlRefInfo(`marker:${t.id}`);for(const t of to(n))s.add(t);i.push({value:`marker:${t.id}`,label:o.label,sub:o.sub,icon:o.icon,search:`${o.label} ${o.sub} ${t.id} ${to(n).join(" ")}`.toLowerCase()})}const n=Object.keys(this.hass.states||{}).filter(e=>Ms(e)&&!s.has(e)&&Jn(t.binding,[e],this._bindingEntities(t.binding)).length>0&&this._planEntityAvailable(e)).map(t=>{const e=this._controlRefInfo(t);return{value:t,label:e.label,sub:t,icon:e.icon,search:`${e.label} ${t}`.toLowerCase()}}),o=t.controlsFilter.trim().toLowerCase();return[...i,...n].filter(e=>!t.controls.includes(e.value)&&(!o||e.search.includes(o))).slice(0,12).map(({search:t,...e})=>e)}_addControlRef(t,e){if(e.startsWith("marker:")){const i=this._markerDraft(t)?.id||t.devId||"";if(!i)return void this._showToast(this._t("toast.marker_binding_required"));const s=e.slice(7),n=this._markerDraft(t);if(function(t,e,i){if(!e||e===i)return!0;const s=new Map;for(const e of t)s.set(e.id,(e.controls||[]).filter(t=>"string"==typeof t&&t.startsWith("marker:")).map(t=>t.slice(7)));const n=new Set,o=[i];for(;o.length;){const t=o.pop();if(t===e)return!0;n.has(t)||(n.add(t),o.push(...s.get(t)||[]))}return!1}(n?[...this._markers.filter(t=>t.id!==i),n]:this._markers,i,s))return void this._showToast(this._t("toast.marker_control_cycle"))}this._markerDialog=this._announceToggleDraft({...t,controls:[...t.controls,e],controlsFilter:""})}_setMarkerGlowMode(t){const e=this._markerDialog;if(!e)return;if("auto"===t)return void(this._markerDialog={...e,glowMode:t,glowTouched:!0});const i=this._markerSpatialSource(e),s=xs(i?this._planHass.states[i.eid]:void 0,null,this._fillColors.glow_light.c),n=!e.glowColorDrafted,o="fixed"===t&&!e.glowBrightnessDrafted;this._markerDialog={...e,glowMode:t,glowColor:n?s.c:e.glowColor,glowBrightness:o?Math.max(1,Math.round(100*s.bri)):e.glowBrightness,glowColorDrafted:!0,glowBrightnessDrafted:e.glowBrightnessDrafted||"fixed"===t,glowTouched:!0}}_renderMarkerDialog(){const t=this._markerDialog,e="virtual"===t.bindingMode,i=this._bindingCandidates();this._bindingEntities(t.binding);const s=e?null:this._bindingStatus(t.binding),n=!e&&this._bindingHasHaPage(t.binding),o=this._markerPreviewDevice(t),a=this._effectiveMarkerTapAction(t,o),r=o?cs(this._serverCfg?.spaces.find(t=>t.id===o.space)):null,l=o?this._markerPreviewDevices(o):this._devices,c="toggle"===a&&o?this._toggleIntent(o,l):null,h=this._toggleHintLines(c),d=o?su(this._planHass,o,{liveStates:!1!==this._config?.live_states,showTemperature:!1!==this._config?.show_temperature,showSignal:r?.showLqi??!1!==this._config?.show_signal,designPreview:!0,activityRuntime:this._activityRt.get(o.id),lightDevices:l,registryHass:this._fullRegistryHass,reducedMotion:this._reducedMotion}):null,p=o?Wo(this._planHass,o,l):[],u=o?jo(this._planHass,o,p):null,_=t.valueBadgeTouched?t.valueBadgeEnabled:!!d?.valueBadge,g=t.valueBadgeTouched?t.valueBadgeSource:d?.valueBadge?.source||t.valueBadgeSource,m=t.valueBadgeTouched?t.valueBadgePosition:d?.valueBadge?.position||t.valueBadgePosition,f=Ao(g),v=!!g&&!p.some(t=>t.key===f),y=p.find(t=>t.key===f),b=d?.valueSource?d.valueSource.attribute?`attr:${d.valueSource.eid}:${d.valueSource.attribute}`:`state:${d.valueSource.eid}`:"",w=this._markerAutoHasSpatialSource(t),k=!!o&&function(t,e){return io(t,e).some(t=>!!t.eid)}(this._planHass,{...o}),x=function(t,e,i,s){const n="always"===t||"auto"===t&&e,o=n&&!i;return{sourceExists:n,fromSourceEnabled:n&&i,manualEnabled:n,radiusEnabled:n,passive:o,effectiveMode:o&&"auto"===s?"fixed":s}}(t.lightRole,w,k,t.glowMode),$=!x.sourceExists,S=!x.fromSourceEnabled,M=x.passive,C=x.effectiveMode,D="never"===t.lightRole?this._t("marker.glow_disabled_never"):"auto"!==t.lightRole||w?M?this._t("marker.glow_passive_hint"):this._t("marker.glow_disabled_no_entity"):this._t("marker.glow_disabled_auto"),T=o?to(o):[],P=o&&eo(o)||"",R=!!t.lightEntity&&!T.includes(t.lightEntity),I=o?gd(o):[],A=!!t.toggleEntity&&!I.includes(t.toggleEntity),F="toggle"===a?this._toggleIntentForDialog({...t,toggleEntity:"",toggleEntityTouched:!0}):null,E=F?[...F.targets,...F.skippedTargets].map(t=>t.entityId||("ref"in t?t.ref:"")).filter(Boolean).join(", "):"",z=(()=>{if(e)return null;const s=i.find(e=>e.value===t.binding);if(s)return s.label;const[n,o]=t.binding.split(":");return"device"===n?this._fullRegistryHass.devices[o]?.name_by_user||this._fullRegistryHass.devices[o]?.name||o:this._fullRegistryHass.entities[o]?.name||this.hass.states[o]?.attributes?.friendly_name||o})();return W`this._markerDialog=null}>
@@ -6732,13 +6732,13 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8 - ${"toggle"===r&&(I.length>1||A)?W`
+ ${"toggle"===a&&(I.length>1||A)?W`
${this._help("marker.toggle_entity.help")} @@ -6758,11 +6758,11 @@ globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="67351f8b3fc2bcc5d5432c7156df5bb015c8 ${this._t("marker.toggle_entity_missing",{entity:t.toggleEntity,fallback:E||this._t("marker.toggle_entity_none")})}

`:G}
`:G} - ${"toggle"===r?W`
+ ${"toggle"===a?W`
${h.map(t=>W`
${t}
`)}
${t.tapHintAnnouncement}
`:G} - ${"run"===r?(()=>{const e=t.runFilter.trim().toLowerCase(),i=this._runCandidates().filter(t=>!e||t.label.toLowerCase().includes(e)||t.value.includes(e)),s=t.tapTarget?this._runCandidates().find(e=>e.value===t.tapTarget):null;return W` + ${"run"===a?(()=>{const e=t.runFilter.trim().toLowerCase(),i=this._runCandidates().filter(t=>!e||t.label.toLowerCase().includes(e)||t.value.includes(e)),s=t.tapTarget?this._runCandidates().find(e=>e.value===t.tapTarget):null;return W` ${t.tapTarget&&!s?W`
${this._t("marker.run_target_gone",{id:t.tapTarget})}
`:G} ${this._t("marker.nothing_found")}
`}
`}`})():G} - ${"run"===r||"toggle"===r?W`
- `}}wm.properties={_tabDrag:{state:!0},_hdrH:{state:!0},_booting:{state:!0},_bootFading:{state:!0},_bootSoft:{state:!0},_continuityEpoch:{state:!0},_tapConfirm:{state:!0},hass:{attribute:!1},_config:{state:!0},_space:{state:!0},_layout:{state:!0},_devices:{state:!0},_tip:{state:!0},_hoverRoom:{state:!0},_selId:{state:!0},_toast:{state:!0},_serverCfg:{state:!0},_mode:{state:!0},_tool:{state:!0},_wallDialog:{state:!0},_drawWallField:{state:!0},_activeDraftId:{state:!0},_physicalSel:{state:!0},_physicalDialog:{state:!0},_partitionDeleteDialog:{state:!0},_roomDeleteDialog:{state:!0},_physicalDrag:{state:!0},_physicalRotate:{state:!0},_duplicateColumnId:{state:!0},_rszSel:{state:!0},_rszLive:{state:!0},_opMeasure:{state:!0},_path:{state:!0},_cursorPt:{state:!0},_mergeSel:{state:!0},_openingPreset:{state:!0},_openingDialog:{state:!0},_openingInfo:{state:!0},_mergeDialog:{state:!0},_openWallAnchor:{state:!0},_splitSel:{state:!0},_decorTool:{state:!0},_decorStyle:{state:!0},_decorDraft:{state:!0},_decorSel:{state:!0},_decorEraseConfirm:{state:!0},_decorTextDialog:{state:!0},_decorShapeDialog:{state:!0},_backdropDialog:{state:!0},_furnPalette:{state:!0},_bdDrag:{state:!0},_dtBox:{state:!0},_dtDrag:{state:!0},_kioskDialog:{state:!0},_vacFit:{state:!0},_vacAllCamerasFor:{state:!0},_vacCalConfirm:{state:!0},_kioskDots:{state:!0},_areaSel:{state:!0},_nameSel:{state:!0},_roomDialog:{state:!0},_roomEditId:{state:!0},_roomFill:{state:!0},_roomCustomFill:{state:!0},_roomTempSrc:{state:!0},_roomHumSrc:{state:!0},_roomSrcOpen:{state:!0},_roomSrcFilter:{state:!0},_roomNameScale:{state:!0},_roomLabelScale:{state:!0},_spaceDialog:{state:!0},_infoCard:{state:!0},_rulesDialog:{state:!0},_settingsDialog:{state:!0},_alignDialog:{state:!0},_backupExportDialog:{state:!0},_backupImportDialog:{state:!0},_importDialog:{state:!0},_markerDialog:{state:!0},_zoom:{state:!0},_view:{state:!0}},wm.ZOOM_MAX=8,wm.ZOOM_MIN=1/3,wm.styles=[Kt,Iu],customElements.get("houseplan-card")||customElements.define("houseplan-card",wm),window.customCards=window.customCards||[],window.customCards.find(t=>"houseplan-card"===t.type)||window.customCards.push({type:"houseplan-card",name:"House Plan Card",description:"Interactive house plan: spaces, rooms and devices with live states and drag layout."}),console.info(`%c HOUSEPLAN-CARD %c v${Gg} `,"background:#3ea6ff;color:#04121f;font-weight:700",""); + `}}km.properties={_tabDrag:{state:!0},_hdrH:{state:!0},_booting:{state:!0},_bootFading:{state:!0},_bootSoft:{state:!0},_continuityEpoch:{state:!0},_tapConfirm:{state:!0},hass:{attribute:!1},_config:{state:!0},_space:{state:!0},_layout:{state:!0},_devices:{state:!0},_tip:{state:!0},_hoverRoom:{state:!0},_selId:{state:!0},_toast:{state:!0},_serverCfg:{state:!0},_mode:{state:!0},_tool:{state:!0},_wallDialog:{state:!0},_drawWallField:{state:!0},_activeDraftId:{state:!0},_physicalSel:{state:!0},_physicalDialog:{state:!0},_partitionDeleteDialog:{state:!0},_roomDeleteDialog:{state:!0},_physicalDrag:{state:!0},_physicalRotate:{state:!0},_duplicateColumnId:{state:!0},_rszSel:{state:!0},_rszLive:{state:!0},_opMeasure:{state:!0},_path:{state:!0},_cursorPt:{state:!0},_mergeSel:{state:!0},_openingPreset:{state:!0},_openingDialog:{state:!0},_openingInfo:{state:!0},_mergeDialog:{state:!0},_openWallAnchor:{state:!0},_splitSel:{state:!0},_decorTool:{state:!0},_decorStyle:{state:!0},_decorDraft:{state:!0},_decorSel:{state:!0},_decorEraseConfirm:{state:!0},_decorTextDialog:{state:!0},_decorShapeDialog:{state:!0},_backdropDialog:{state:!0},_furnPalette:{state:!0},_bdDrag:{state:!0},_dtBox:{state:!0},_dtDrag:{state:!0},_kioskDialog:{state:!0},_vacFit:{state:!0},_vacAllCamerasFor:{state:!0},_vacCalConfirm:{state:!0},_kioskDots:{state:!0},_areaSel:{state:!0},_nameSel:{state:!0},_roomDialog:{state:!0},_roomEditId:{state:!0},_roomFill:{state:!0},_roomCustomFill:{state:!0},_roomTempSrc:{state:!0},_roomHumSrc:{state:!0},_roomSrcOpen:{state:!0},_roomSrcFilter:{state:!0},_roomNameScale:{state:!0},_roomLabelScale:{state:!0},_spaceDialog:{state:!0},_infoCard:{state:!0},_rulesDialog:{state:!0},_settingsDialog:{state:!0},_alignDialog:{state:!0},_backupExportDialog:{state:!0},_backupImportDialog:{state:!0},_importDialog:{state:!0},_markerDialog:{state:!0},_zoom:{state:!0},_view:{state:!0}},km.ZOOM_MAX=8,km.ZOOM_MIN=1/3,km.styles=[Kt,Au],customElements.get("houseplan-card")||customElements.define("houseplan-card",km),window.customCards=window.customCards||[],window.customCards.find(t=>"houseplan-card"===t.type)||window.customCards.push({type:"houseplan-card",name:"House Plan Card",description:"Interactive house plan: spaces, rooms and devices with live states and drag layout."}),console.info(`%c HOUSEPLAN-CARD %c v${Vg} `,"background:#3ea6ff;color:#04121f;font-weight:700",""); diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index c494ea18..6de817fb 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -428,10 +428,17 @@ uses `H = max(incident half-depth)` and clips excessive overlap to a straight bevel bounded by `1.25 × H`; degree-2 joins keep the legacy `MITRE_LIMIT = 4`. The final bevel is applied to canonical masonry after its room/atomic/exterior union, preventing later boolean inputs from recreating the discarded spike. -Paper re-unions the room centre footprint after the same cut so an interior -bevel exposes clean floor rather than scene background. Full, Static, hidden -Iso, room fills/hover, clean-floor calculations and light barriers therefore -observe the same topology, and cached HA/theme ticks do not rebuild the map. +Canonical masonry replaces each affected local mask with complete physical ray +strips clipped to the room union, retains overlap through the approved radius, +and preserves the established full exterior cut outside the room union. This +prevents the repair from deleting half an incident strip or changing a concave +facade. Paper re-unions the room centre footprint after its facade cut. +`wallBodiesGeometry.roomGeom` caches this repaired room masonry before openings +and independent bodies; clean-floor consumers subtract it from each source room +and clip their fallback, so fill cannot escape the building or silently drop a +floor pocket. Full, Static, hidden Iso, room fills/hover and light barriers +therefore observe the same topology, and cached HA/theme ticks do not rebuild +the map. Before the exterior offset is built, each saved atomic endpoint splits its containing collinear union edge. Offset changes are explicit butt steps at that endpoint, including nonzero-to-zero transitions. The topology tolerance starts diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 5e76dbe6..b438b1a0 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -6,7 +6,10 @@ straight bevel instead of producing long hatched spikes, including mixed wall thicknesses. The node stays filled and matches across Plan, View, kiosk, Static, hidden Iso and light/shadow barriers; ordinary two-wall corners keep - their previous shape ([#249](https://github.com/Matysh/houseplan-card/issues/249)). + their previous shape. Clean room fills now use that same bounded masonry, so + strongly asymmetric junctions cannot push floor outside the building or + leave a missing floor pocket + ([#249](https://github.com/Matysh/houseplan-card/issues/249)). ## v1.67.0-beta.3 — 2026-08-23 diff --git a/docs/CHANGELOG.ru.md b/docs/CHANGELOG.ru.md index 9189916b..6feda1ff 100755 --- a/docs/CHANGELOG.ru.md +++ b/docs/CHANGELOG.ru.md @@ -12,7 +12,9 @@ клинья штриховки теперь заменяются ограниченной прямой фаской, в том числе при разной толщине стен. Сам узел остаётся заполненным и одинаковым в Plan, View, kiosk, Static, скрытой изометрии и световых/теневых барьерах; обычные - углы из двух стен сохраняют прежнюю форму + углы из двух стен сохраняют прежнюю форму. Чистая заливка комнаты использует + ту же ограниченную геометрию стен, поэтому сильно различающаяся толщина в + узле не выводит пол за контур здания и не оставляет пропущенный участок пола ([#249](https://github.com/Matysh/houseplan-card/issues/249)). ## v1.67.0-beta.3 — 2026-08-23 diff --git a/docs/TESTING.md b/docs/TESTING.md index a7e6f6f0..5080ba8a 100644 --- a/docs/TESTING.md +++ b/docs/TESTING.md @@ -1685,9 +1685,13 @@ that it automatically runs blocking verification. Review and accept the canonical set. See `demo/golden/README.md`. For #249, `test/wall-thickness.test.mjs` additionally covers equal and unequal -three-/four-ray nodes, reversed input, winding/order changes, production -`coordScale = 1000`, unchanged two-ray joins and the anonymised regression -fixture in `test/fixtures/249-multiwall-junction.json`. +three-/four-ray nodes (including literal 15/50/70 cm arms), reversed input, +winding/order changes, production `coordScale = 1000`, unchanged two-ray joins +and the anonymised regression fixture in +`test/fixtures/249-multiwall-junction.json`. The asymmetric corner-Split case +also proves that the union of clean-room floors equals the original room union +minus canonical bounded masonry and that every floor vertex remains inside the +source building. `demo/smoke_multiwall_junction.mjs` checks Plan/View/kiosk/Static/hidden-Iso parity, paper and clean-floor presence, shared Glow/sun masonry, cache reuse on HA/theme ticks, no saved-config mutation, a filled node and the removed old diff --git a/docs/WALL-THICKNESS.md b/docs/WALL-THICKNESS.md index 402d6d1f..4c15570f 100644 --- a/docs/WALL-THICKNESS.md +++ b/docs/WALL-THICKNESS.md @@ -78,10 +78,21 @@ At a physical node with **three or more distinct incident rays**, the stricter multi-wall rule applies (#249). Shared room ownership and reversed interval direction do not create extra rays. One structural node map records the largest incident half-depth `H`; every excessive join is cut back with a straight local -bevel and may not extend beyond `R = 1.25 × H`. The node centre and each wall arm -remain masonry, so the bevel cannot create a floor pinhole. Ordinary two-ray -corners retain the exact historical `MITRE_LIMIT = 4` contract. This is computed -geometry only: saved room outlines and wall entries are not rewritten. +bevel and may not extend beyond `R = 1.25 × H`. Inside the room union, a bounded +mask replaces the legacy ring with the complete finite ray strips, retains their +overlap through `R`, and removes only the remaining excessive pairwise wedge. +Outside the room union, the established full facade cut is preserved. This keeps +the node centre and every arm area-connected without allowing an interior child +mitre to change a concave facade. Ordinary two-ray corners retain the exact +historical `MITRE_LIMIT = 4` contract. This is computed geometry only: saved room +outlines and wall entries are not rewritten. + +Clean-floor consumers subtract the cached, repaired canonical room masonry from +their source room and take its outer component. The result is clipped to the +source room on fallback. Openings and independent partitions are deliberately +excluded from this shared `roomGeom`, so a door does not change the room fill +and a detached body cannot punch it. Full and Static render paths reuse the same +structural cache instead of rebuilding wall booleans once per room. **Hatch density is physical (#230).** The pattern step is a distance on the plan, not a count of coordinate units: `wallHatchStepUnits(cellCm)` returns @@ -150,9 +161,10 @@ patches. This fallback never rounds persisted rooms, walls or open spans to the grid and never turns a failure of the mandatory exterior/body/opening passes into a successful result. One noisy junction therefore cannot remove otherwise valid masonry, paper, floor faces or light barriers for the whole space (#197). -The same failure isolation covers the degree-3+ bevel cuts: malformed candidates -are skipped locally, and an aggregate boolean failure retries valid cuts one at -a time instead of reverting every multi-wall node. +The same failure isolation covers degree-3+ repair: every node is rebuilt and +committed independently inside its bounded mask. A malformed local candidate +therefore keeps that node's previous body without reverting successful repairs +at unrelated nodes. Runtime normalisation remains lossless for every positive exact thickness interval, regardless of its length. The explicit **Optimize plans** maintenance diff --git a/docs/images/01-view-desktop.png b/docs/images/01-view-desktop.png index f66ae663..d1947abb 100644 Binary files a/docs/images/01-view-desktop.png and b/docs/images/01-view-desktop.png differ diff --git a/docs/images/02-view-touch.png b/docs/images/02-view-touch.png index bf3be886..8d4589d8 100644 Binary files a/docs/images/02-view-touch.png and b/docs/images/02-view-touch.png differ diff --git a/docs/images/04-room-contour-close.png b/docs/images/04-room-contour-close.png index dc7f4786..51dc20b7 100644 Binary files a/docs/images/04-room-contour-close.png and b/docs/images/04-room-contour-close.png differ diff --git a/docs/images/05-plan-context-tray.png b/docs/images/05-plan-context-tray.png index db08bc70..d759e1e5 100644 Binary files a/docs/images/05-plan-context-tray.png and b/docs/images/05-plan-context-tray.png differ diff --git a/docs/images/06-device-display-preview.png b/docs/images/06-device-display-preview.png index 8a370604..e97464df 100644 Binary files a/docs/images/06-device-display-preview.png and b/docs/images/06-device-display-preview.png differ diff --git a/docs/images/06-device-editor.png b/docs/images/06-device-editor.png index 501d4f71..42398476 100644 Binary files a/docs/images/06-device-editor.png and b/docs/images/06-device-editor.png differ diff --git a/docs/images/07-background-editor.png b/docs/images/07-background-editor.png index ea6bbd43..b5aae2b5 100644 Binary files a/docs/images/07-background-editor.png and b/docs/images/07-background-editor.png differ diff --git a/docs/images/09-device-info.png b/docs/images/09-device-info.png index b2500e6e..e2c9d1e0 100644 Binary files a/docs/images/09-device-info.png and b/docs/images/09-device-info.png differ diff --git a/docs/images/screenshots.json b/docs/images/screenshots.json index 71c402a5..a4ebd783 100644 --- a/docs/images/screenshots.json +++ b/docs/images/screenshots.json @@ -2,7 +2,7 @@ "version": 1, "fixture": "synthetic-only", "chromium": "151.0.7922.34", - "sourceFingerprint": "6a0df196b4f3d3808e292515419b71ff8959c8fd8c04a0ebde21f55914d35da2", + "sourceFingerprint": "7290c3656eb8bb60f2c0f616dc74fcb6b05b4fb20f0fd5e4c4c6479d79a1b6b7", "captureScriptSha256": "ce2e9542fed9dade3085be87d16f69adb2ac8262893ad78ad966b1b9673f2983", "command": "npm run build && node demo/docs/capture.mjs", "scenarios": { @@ -14,8 +14,8 @@ }, "theme": "dark", "language": "en", - "sourceSha256": "6a0df196b4f3d3808e292515419b71ff8959c8fd8c04a0ebde21f55914d35da2", - "imageSha256": "36223106c073f07d8cc3ecf8eaab37192ebb2687daba65c5c21047d0b7890de0" + "sourceSha256": "7290c3656eb8bb60f2c0f616dc74fcb6b05b4fb20f0fd5e4c4c6479d79a1b6b7", + "imageSha256": "aaab24546dac767fc434c627c0aaecd69458b97872cf7a97ce417686946902d1" }, "view-touch": { "file": "02-view-touch.png", @@ -25,8 +25,8 @@ }, "theme": "dark", "language": "en", - "sourceSha256": "6a0df196b4f3d3808e292515419b71ff8959c8fd8c04a0ebde21f55914d35da2", - "imageSha256": "41e3ba67f8db0e98f26f484293af83ef937c369ca5ca6a59a3350d8954c906f4" + "sourceSha256": "7290c3656eb8bb60f2c0f616dc74fcb6b05b4fb20f0fd5e4c4c6479d79a1b6b7", + "imageSha256": "3cbdf7aa2105d72b2dea0d644862f36118e268d8c8d2e285f1edcffc49648a93" }, "space-create": { "file": "03-space-create.png", @@ -36,7 +36,7 @@ }, "theme": "dark", "language": "en", - "sourceSha256": "6a0df196b4f3d3808e292515419b71ff8959c8fd8c04a0ebde21f55914d35da2", + "sourceSha256": "7290c3656eb8bb60f2c0f616dc74fcb6b05b4fb20f0fd5e4c4c6479d79a1b6b7", "imageSha256": "c33a7279165a4cec6fa6fadb6fd08cd967e082a17fe101ef442d27d36ae59b6b" }, "room-contour-close": { @@ -47,8 +47,8 @@ }, "theme": "dark", "language": "en", - "sourceSha256": "6a0df196b4f3d3808e292515419b71ff8959c8fd8c04a0ebde21f55914d35da2", - "imageSha256": "b2d827fb2fb76d8340509a7bb4446369003ec94d017a7ea60d285923fbd4558e" + "sourceSha256": "7290c3656eb8bb60f2c0f616dc74fcb6b05b4fb20f0fd5e4c4c6479d79a1b6b7", + "imageSha256": "2ac9fad407384ba3ef46330a7ffcdcb0cd6ca1e3412e0ad935f58b74f9efde6c" }, "plan-context-tray": { "file": "05-plan-context-tray.png", @@ -58,8 +58,8 @@ }, "theme": "dark", "language": "en", - "sourceSha256": "6a0df196b4f3d3808e292515419b71ff8959c8fd8c04a0ebde21f55914d35da2", - "imageSha256": "e15754f68638b6128a30fc64bc830ac1cf611be7e6e10bcfaf84f17d1965aa33" + "sourceSha256": "7290c3656eb8bb60f2c0f616dc74fcb6b05b4fb20f0fd5e4c4c6479d79a1b6b7", + "imageSha256": "b729f6ac72181ffe0edc5003e400642f2238ceac6c6423e4add8eb8e45fd4253" }, "device-editor": { "file": "06-device-editor.png", @@ -69,8 +69,8 @@ }, "theme": "dark", "language": "en", - "sourceSha256": "6a0df196b4f3d3808e292515419b71ff8959c8fd8c04a0ebde21f55914d35da2", - "imageSha256": "d0ffd31ce80bfde21ab75da356a5fc1af38246f2b301030880320620c228d89d" + "sourceSha256": "7290c3656eb8bb60f2c0f616dc74fcb6b05b4fb20f0fd5e4c4c6479d79a1b6b7", + "imageSha256": "b68e560bbc3744a911cbf9d37b0eee765d1ef437b27fe65402c38b13921da1fe" }, "device-display-preview": { "file": "06-device-display-preview.png", @@ -80,8 +80,8 @@ }, "theme": "dark", "language": "en", - "sourceSha256": "6a0df196b4f3d3808e292515419b71ff8959c8fd8c04a0ebde21f55914d35da2", - "imageSha256": "2cdabae1f89c3286e4fac0ce30f757ee1690b707ab8a5488748b7cd420626160" + "sourceSha256": "7290c3656eb8bb60f2c0f616dc74fcb6b05b4fb20f0fd5e4c4c6479d79a1b6b7", + "imageSha256": "7393c93fd60666703531f8882fac9b421452aaf04e47f1a12997afae39cfb7e7" }, "background-editor": { "file": "07-background-editor.png", @@ -91,8 +91,8 @@ }, "theme": "dark", "language": "en", - "sourceSha256": "6a0df196b4f3d3808e292515419b71ff8959c8fd8c04a0ebde21f55914d35da2", - "imageSha256": "1678442b3d4ec4a5a59141b5a0213a0118d4455a924381bd6d80a3800eae686a" + "sourceSha256": "7290c3656eb8bb60f2c0f616dc74fcb6b05b4fb20f0fd5e4c4c6479d79a1b6b7", + "imageSha256": "7017cb7faaa6ce54627b72560c18c616c766b3cc1e5e794771f4dd5dcc517d6f" }, "room-card": { "file": "08-room-card.png", @@ -102,7 +102,7 @@ }, "theme": "dark", "language": "en", - "sourceSha256": "6a0df196b4f3d3808e292515419b71ff8959c8fd8c04a0ebde21f55914d35da2", + "sourceSha256": "7290c3656eb8bb60f2c0f616dc74fcb6b05b4fb20f0fd5e4c4c6479d79a1b6b7", "imageSha256": "029a3e69ec647a8a370d99e6bb7f9225833c526739076022f6b52ba54bff30ea" }, "device-info": { @@ -113,8 +113,8 @@ }, "theme": "dark", "language": "en", - "sourceSha256": "6a0df196b4f3d3808e292515419b71ff8959c8fd8c04a0ebde21f55914d35da2", - "imageSha256": "dd492f53150b7149085daada5cce9eeae9bde9e7ea1d86679a54b3041f72f517" + "sourceSha256": "7290c3656eb8bb60f2c0f616dc74fcb6b05b4fb20f0fd5e4c4c6479d79a1b6b7", + "imageSha256": "b49138235d348ca6a2d74da5c9891298f44546fd902efcdea49ef89605654b33" } } } diff --git a/src/houseplan-card.ts b/src/houseplan-card.ts index 161c4c47..4cd4121e 100755 --- a/src/houseplan-card.ts +++ b/src/houseplan-card.ts @@ -11621,6 +11621,7 @@ class HouseplanCard extends LitElement { space.rooms.map((room) => [room, roomPoly(room)]), ); const openCuts = this._openPairs().flatMap((pair) => pair.segs); + const roomWalls = this._wallUnionGeometry()?.roomGeom; const pathD = (points: number[][]) => 'M ' + points.map((point) => point[0] + ' ' + point[1]).join(' L ') + ' Z'; const shapes = space.rooms.map((room) => { @@ -11631,6 +11632,7 @@ class HouseplanCard extends LitElement { ? (innerContourForRoom( space.rooms, room.id, this._spaceWalls, openCuts, this._wallKeyPitch, this._cellCm, this._gridPitch, NORM_W, + roomWalls, ) || ownPoly) : ownPoly; const otherPolys = space.rooms @@ -11825,10 +11827,12 @@ class HouseplanCard extends LitElement { ? pairs.filter((p) => p.a.id === room.id || p.b.id === room.id).flatMap((p) => p.segs) : pairs.flatMap((p) => p.segs); const walls = this._spaceWalls; + const roomWalls = this._wallUnionGeometry()?.roomGeom; const floor = walls.length && room.id ? (innerContourForRoom( space.rooms, room.id, walls, allOpenCuts, this._wallKeyPitch, this._cellCm, this._gridPitch, NORM_W, + roomWalls, ) || poly) : poly; const contours: { axis: number[][]; face: number[][] }[] = [{ axis: poly, face: floor }]; @@ -14768,11 +14772,13 @@ class HouseplanCard extends LitElement { const openingWallIndex = this._openingWallIndexFor(space, openCuts).value; const innerByRoom: Record = {}; const wallDepthByOpening: Record = {}; + const roomWalls = this._wallUnionGeometry()?.roomGeom; if (walls.length) { for (const r of rooms) { const inn = innerContourForRoom( space.rooms, r.id, walls, openCuts, this._wallKeyPitch, this._cellCm, this._gridPitch, NORM_W, + roomWalls, ); if (inn) innerByRoom[r.id] = inn; } @@ -15927,11 +15933,13 @@ class HouseplanCard extends LitElement { const openCuts = enabled.length === polys.length ? [] : this._openPairs().flatMap((pair) => pair.segs); + const roomWalls = this._wallUnionGeometry()?.roomGeom; const enabledClip = enabled.length === polys.length ? null : enabled.map(({ r, poly }) => { const floorPoly = walls.length && r.id ? (innerContourForRoom( space.rooms, r.id, walls, openCuts, this._wallKeyPitch, this._cellCm, this._gridPitch, NORM_W, + roomWalls, ) || poly) : poly; const clean = this._cleanFloor(r, floorPoly, space).path; @@ -16772,6 +16780,7 @@ class HouseplanCard extends LitElement { space.rooms, r.id, walls, this._openPairs().flatMap((p) => p.segs), this._wallKeyPitch, this._cellCm, this._gridPitch, NORM_W, + this._wallUnionGeometry()?.roomGeom, ) || myPoly) : myPoly; const holes = fillPoly ? islandsOf(fillPoly, otherPolys(r)) : []; @@ -17933,6 +17942,7 @@ class HouseplanCard extends LitElement { space.rooms, r.id, walls, this._openPairs().flatMap((p) => p.segs), this._wallKeyPitch, this._cellCm, this._gridPitch, NORM_W, + this._wallUnionGeometry()?.roomGeom, ) || poly) : poly; const clean = this._cleanFloor(r, floor); diff --git a/src/wall-thickness.ts b/src/wall-thickness.ts index 8bee86c2..99b2c8ba 100644 --- a/src/wall-thickness.ts +++ b/src/wall-thickness.ts @@ -1752,6 +1752,44 @@ export function insetOffsetsForRoom( /** Alias — half offsets drive both inset and outset. */ export const halfOffsetsForRoom = insetOffsetsForRoom; +/** + * A bounded inward bevel may cross a neighbouring source edge when incident + * wall depths differ sharply. Keep only the part that is physically inside + * the room and return its largest outer ring; room consumers accept one simple + * contour and handle nested-room holes separately. + */ +function clipInnerContourToRoom( + contour: number[][], + room: number[][], +): number[][] | null { + try { + const clipped = intersection( + closedRing(contour) as any, + closedRing(room) as any, + ); + return largestOuterContour(clipped); + } catch { + return null; + } +} + +/** Largest simple outer ring from polygon-clipping geometry. */ +function largestOuterContour(geometry: any): number[][] | null { + let best: number[][] | null = null; + let bestArea = 0; + for (const polygon of geometry || []) { + const raw = polygon?.[0]; + if (!Array.isArray(raw) || raw.length < 4) continue; + const ring = raw.slice(0, -1).map((point: number[]) => [point[0], point[1]]); + const area = Math.abs(signedArea(ring)); + if (ring.length >= 3 && area > bestArea) { + best = ring; + bestArea = area; + } + } + return best; +} + /** * Inner (clean-floor) contour of a room: inset by half wall thickness. * Returns the original poly when there is no thickness. @@ -1765,6 +1803,8 @@ export function innerContourForRoom( cellCm: number, gridPitch: number, coordScale = 1, + /** Canonical room-wall masonry before opening cuts; pass the render cache. */ + sharedRoomWallGeometry?: any, ): number[][] | null { const room = (rooms || []).find((r) => r?.id === roomId); const poly = roomPoly(room); @@ -1775,7 +1815,22 @@ export function innerContourForRoom( const multiWallNodes = multiWallNodesForGeometry( rooms, walls, openCuts, pitch, cellCm, gridPitch, coordScale, ); - return insetContour(pr.poly, pr.offsets, multiWallNodes) + const inset = insetContour(pr.poly, pr.offsets, multiWallNodes); + if (!inset) return poly.map((p) => [p[0], p[1]]); + if (!multiWallNodes.nodes.length) return inset; + const roomWallGeometry = sharedRoomWallGeometry ?? wallBodiesGeometry( + rooms, walls, openCuts, [], pitch, cellCm, gridPitch, coordScale, + )?.roomGeom; + if (roomWallGeometry) { + try { + const floor = difference(closedRing(pr.poly) as any, roomWallGeometry); + const contour = largestOuterContour(floor); + if (contour) return contour; + } catch { + // Fall through to the bounded contour clip; never return an outside tip. + } + } + return clipInnerContourToRoom(inset, pr.poly) || poly.map((p) => [p[0], p[1]]); } @@ -1791,8 +1846,9 @@ interface MultiWallRoomRing { } /** Excess pairwise overlap triangles removed to expose the straight bevel. */ -export function multiWallBevelTriangles( +function multiWallBevelTrianglesAt( map: MultiWallNodeMap | null | undefined, + retainToLimit: boolean, ): number[][][] { if (!map) return []; const triangles: number[][][] = []; @@ -1820,41 +1876,113 @@ export function multiWallBevelTriangles( hit[0] - node.point[0], hit[1] - node.point[1], ); if (!Number.isFinite(distance) || distance <= node.limit) continue; - const triangle = stableJunctionPatch([pA, pB, hit], map.coordinateScale); + // Canonical masonry retains pairwise overlap up to R so ordinary + // right-angle arms stay area-connected. The exterior paper uses the + // offset origins instead: its job is to remove the complete facade + // tooth, and the room centre is unioned back immediately afterwards. + const advanceA = retainToLimit ? Math.sqrt(Math.max( + 0, node.limit * node.limit - a.halfDepth * a.halfDepth, + )) : 0; + const advanceB = retainToLimit ? Math.sqrt(Math.max( + 0, node.limit * node.limit - b.halfDepth * b.halfDepth, + )) : 0; + const qA = [pA[0] + a.u[0] * advanceA, pA[1] + a.u[1] * advanceA]; + const qB = [pB[0] + b.u[0] * advanceB, pB[1] + b.u[1] * advanceB]; + const triangle = stableJunctionPatch([qA, qB, hit], map.coordinateScale); if (triangle) triangles.push(triangle); } } return triangles; } -function bevelMultiWallBody(body: any, map: MultiWallNodeMap): any { +export function multiWallBevelTriangles( + map: MultiWallNodeMap | null | undefined, +): number[][][] { + return multiWallBevelTrianglesAt(map, true); +} + +function bevelMultiWallBody( + body: any, + map: MultiWallNodeMap, + centre?: any, + envelope?: any, +): any { if (!body || !map.nodes.length) return body; - let cuts: any = null; - for (const triangle of multiWallBevelTriangles(map)) { + let current = body; + for (const node of map.nodes) { + const radius = MITRE_LIMIT * node.halfDepth + map.epsilon * 2; + const extent = radius * 2; + const mask = [ + [node.point[0] - radius, node.point[1] - radius], + [node.point[0] + radius, node.point[1] - radius], + [node.point[0] + radius, node.point[1] + radius], + [node.point[0] - radius, node.point[1] + radius], + ]; try { - const piece = closedRing(triangle) as any; - cuts = cuts ? union(cuts, piece) : piece; - } catch { - // Keep other valid local cuts; one bad candidate cannot erase the pass. - } - } - if (!cuts) return body; - try { - return difference(body, cuts); - } catch { - // Polyclip can reject a valid aggregate even when each local candidate is - // usable. Retry one-by-one so one unstable corner cannot suppress the - // bevels at every other independent node. - let recovered = body; - for (const triangle of multiWallBevelTriangles(map)) { - try { - recovered = difference(recovered, closedRing(triangle) as any); - } catch { - // Keep the last valid body and isolate this candidate only. + let boundedCurrent = current; + for (const triangle of multiWallBevelTrianglesAt({ + ...map, + nodes: [node], + }, false)) { + boundedCurrent = difference(boundedCurrent, closedRing(triangle) as any); } + let local: any = null; + for (const ray of node.rays) { + const n = [-ray.u[1], ray.u[0]]; + const rectangle = stableJunctionPatch([ + [node.point[0] + n[0] * ray.halfDepth, + node.point[1] + n[1] * ray.halfDepth], + [node.point[0] + ray.u[0] * extent + n[0] * ray.halfDepth, + node.point[1] + ray.u[1] * extent + n[1] * ray.halfDepth], + [node.point[0] + ray.u[0] * extent - n[0] * ray.halfDepth, + node.point[1] + ray.u[1] * extent - n[1] * ray.halfDepth], + [node.point[0] - n[0] * ray.halfDepth, + node.point[1] - n[1] * ray.halfDepth], + ], map.coordinateScale); + if (!rectangle) continue; + const piece: any = closedRing(rectangle) as any; + local = local ? union(local, piece) : piece; + } + for (const triangle of multiWallBevelTriangles({ + ...map, + nodes: [node], + })) { + // Rebuild the physical half-strips first, then remove only their + // excessive pairwise overlap. Applying this cut to the legacy room + // ring itself can delete an incident half-strip and strand floor. + local = difference(local, closedRing(triangle) as any); + } + // Rays share a mathematical endpoint. A tiny physical core turns that + // point contact into a stable polygon contact for boolean/render paths. + const coreRadius = Math.min( + ...node.rays.map((ray) => ray.halfDepth), + ) * 0.02; + local = union(local, closedRing([ + [node.point[0] - coreRadius, node.point[1] - coreRadius], + [node.point[0] + coreRadius, node.point[1] - coreRadius], + [node.point[0] + coreRadius, node.point[1] + coreRadius], + [node.point[0] - coreRadius, node.point[1] + coreRadius], + ]) as any); + if (!local) continue; + let localInside = intersection(local, closedRing(mask) as any); + if (centre) localInside = intersection(localInside, centre); + else if (envelope) localInside = intersection(localInside, envelope); + const outside = difference(boundedCurrent, closedRing(mask) as any); + const preservedExterior = centre + ? difference( + intersection(boundedCurrent, closedRing(mask) as any), + centre, + ) + : null; + current = preservedExterior + ? union(outside, preservedExterior, localInside) + : union(outside, localInside); + } catch { + // Isolate the failed node. Other valid nodes still receive their repair; + // mandatory surrounding structural failures remain fail-dark upstream. } - return recovered; } + return current; } function bevelMultiWallPaper( @@ -1862,7 +1990,14 @@ function bevelMultiWallPaper( centre: any, map: MultiWallNodeMap, ): any { - const beveled = bevelMultiWallBody(paper, map); + let beveled = paper; + for (const triangle of multiWallBevelTrianglesAt(map, false)) { + try { + beveled = difference(beveled, closedRing(triangle) as any); + } catch { + // Isolate the failed local cut and retain the rest of the paper. + } + } try { // Paper is the complete room footprint. Interior bevel cuts expose floor, // not the scene background, so the centre union must always remain solid. @@ -2275,7 +2410,14 @@ export function wallBodiesGeometry( gridPitch: number, coordScale = 1, extraBodies: number[][][] = [], -): { geom: any; paperGeom: any; depthUnits: number; openingIndex: OpeningWallIndex | null } | null { +): { + geom: any; + /** Canonical room masonry before opening cuts and independent bodies. */ + roomGeom: any; + paperGeom: any; + depthUnits: number; + openingIndex: OpeningWallIndex | null; +} | null { if (!walls?.length && !extraBodies.length) return null; const roomRings: MultiWallRoomRing[] = []; const multiWallNodes = multiWallNodesForGeometry( @@ -2365,7 +2507,8 @@ export function wallBodiesGeometry( if (exterior?.shell?.length) body = body ? union(body, exterior.shell) : exterior.shell; if (body && multiWallNodes.nodes.length) - body = bevelMultiWallBody(body, multiWallNodes); + body = bevelMultiWallBody(body, multiWallNodes, exterior?.centre, paperGeom); + const roomGeom = body || []; // cut opening tunnels (axis-aligned to opening angle) for (const o of openings) { if (!(o.length > 0)) continue; @@ -2390,7 +2533,7 @@ export function wallBodiesGeometry( if (extra.length < 3) continue; body = body ? union(body, closedRing(extra) as any) : [closedRing(extra)]; } - return { geom: body || [], paperGeom, depthUnits: maxDepth, openingIndex }; + return { geom: body || [], roomGeom, paperGeom, depthUnits: maxDepth, openingIndex }; } catch { return null; } @@ -2408,14 +2551,23 @@ export function wallBodiesUnionPath( /** Independent physical bodies are unioned only after room openings are cut, * so a door/window/gate can never punch a coincident partition or column. */ extraBodies: number[][][] = [], -): { d: string; paperD: string; depthUnits: number; fillRule: 'evenodd' | 'nonzero' } | null { +): { + d: string; + roomGeom: any; + paperD: string; + depthUnits: number; + fillRule: 'evenodd' | 'nonzero'; +} | null { if (!walls?.length && !extraBodies.length) return null; const united = wallBodiesGeometry( rooms, walls, openCuts, openings, pitch, cellCm, gridPitch, coordScale, extraBodies, ); const d = united ? polyclipToPathD(united.geom) : ''; const paperD = united ? polyclipToPathD(united.paperGeom) : ''; - if (united && d) return { d, paperD, depthUnits: united.depthUnits, fillRule: 'evenodd' }; + if (united && d) return { + d, roomGeom: united.roomGeom, paperD, + depthUnits: united.depthUnits, fillRule: 'evenodd', + }; if (united) return null; // successful empty result: do not resurrect raw rings // Fail closed. The old raw per-room-ring fallback is the exact algorithm // that creates an exterior tooth at a corner Split, so resurrecting it after diff --git a/test/wall-thickness.test.mjs b/test/wall-thickness.test.mjs index 1a094b01..1c844c05 100644 --- a/test/wall-thickness.test.mjs +++ b/test/wall-thickness.test.mjs @@ -625,6 +625,7 @@ test('issue #249 node classification is order, direction and scale independent', const cases = [ { angles: [0, 30, 200], halves: [5, 5, 5], bevel: true }, { angles: [45, 102, 230], halves: [7, 5, 5], bevel: true }, + { angles: [45, 102, 230], halves: [1.5, 5, 7], bevel: true }, { angles: [0, 90, 180, 270], halves: [5, 5, 5, 5], bevel: true }, { angles: [0, 90, 180, 270], halves: [2, 5, 3, 7], bevel: false }, ]; @@ -718,7 +719,11 @@ test('issue #249 node classification is order, direction and scale independent', ); assert.equal(fanMap.nodes.length, 1); assert.equal(fanMap.nodes[0].rays.length, fixture.angles.length); - assert.equal(fan.geometry.geom.length, 1, 'fan wall arms are disconnected'); + assert.equal( + fan.geometry.geom.length, + 1, + `fan ${fixture.angles.join('/')} halves ${fixture.halves.join('/')} wall arms are disconnected`, + ); assertProbeInside(fan.geometry.geom, fan.node, 'fan bevel punched a node hole'); for (const [rayIndex, ray] of fanMap.nodes[0].rays.entries()) { const armPoint = [ @@ -1149,7 +1154,9 @@ test('issue #197 keeps the full masonry when one virtual-junction patch has ULP assert.ok(geometry.geom.length > 0); assert.ok(geometry.paperGeom.length > 0); // #249 intentionally bevels degree-3+ nodes in this older fixture too. - closeTo(geometryArea(geometry.geom), 124495.74029324856, 1e-6); + // #249 retains the physical multi-wall overlap up to R instead of reducing + // right-angle arms to point contacts. + closeTo(geometryArea(geometry.geom), 124512.89263371378, 1e-6); closeTo(geometryArea(geometry.paperGeom), 727248.4374999999, 1e-6); assert.equal( JSON.stringify({ rooms, walls, cuts, openings, extraBodies }), before, @@ -1512,21 +1519,24 @@ test('Split with both endpoints at exterior vertices bevels both new 3-ray corne assert.equal(map.nodes.length, 2); }); -test('corner Split clean-floor contours use the same bounded bevel endpoints', () => { +test('corner Split clean floors equal room union minus canonical bounded walls', () => { const fixture = cornerSplitFixture({ dividerCm: 100 }); const floors = fixture.rooms.map((room) => innerContourForRoom( fixture.rooms, room.id, fixture.walls, [], pitch, cellCm, GRID_PITCH, )); assert.ok(floors.every(Boolean)); - const map = assertBoundedMultiWallBevels( - fixture.rooms, fixture.walls, fixture.after, - ); - const boundedEndpoints = multiWallBevelTriangles(map) - .flatMap((triangle) => triangle.slice(0, 2)); - for (const endpoint of boundedEndpoints) { - assert.ok(floors.some((floor) => floor.some((point) => - Math.hypot(point[0] - endpoint[0], point[1] - endpoint[1]) < 1e-7)), - `clean-floor contours lost bevel endpoint ${endpoint}`); + const actual = union(...floors.map((floor) => closedGeometry(floor))); + const expected = difference(closedGeometry(fixture.original.poly), fixture.after.geom); + const extra = geometryDifferenceArea(actual, expected); + const missing = geometryDifferenceArea(expected, actual); + assert.ok(extra <= 1e-7 && missing <= 1e-7, + `floor mismatch extra=${extra} missing=${missing} floors=${JSON.stringify(floors)}`); + for (const floor of floors) { + for (const point of floor) { + assert.ok(point[0] >= 100 - 1e-7 && point[0] <= 900 + 1e-7 + && point[1] >= 100 - 1e-7 && point[1] <= 700 + 1e-7, + `clean floor escaped the source building: ${point}`); + } } });