`}_renderFallback(){const e=d.styles.cssText;this._floating.renderFallback(this._tooltipTemplate(!1),e)}_surface(){return this._floating.surface(".tooltip",this._usesPopover())}_position(){if(!this._open)return!1;const e=this._window(),t=this.renderRoot.querySelector(".trigger");let i=this._surface();if(!e||!t?.isConnected||!i?.isConnected)return!1;const o=s(e);if(i.style.maxWidth=`${Math.max(0,Math.min(320,o.width-16))}px`,i.style.maxHeight=`${Math.max(0,o.height-16)}px`,i.style.visibility="hidden",this._usesPopover()&&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.visibility="hidden"}const n=t.getBoundingClientRect(),r=i.getBoundingClientRect();if(!(n.width&&n.height&&r.width&&r.height))return!1;const l=a(n,r,o);return i.style.left=`${l.left}px`,i.style.top=`${l.top}px`,i.dataset.side=l.side,i.style.visibility="",!0}render(){if(!this._hasContent())return i;const e=this.ariaLabel.trim();return t`
({value:e.id,label:e.title||e.id})),this._spacesAuthoritative=!0}catch{this._spaces=[],this._spacesAuthoritative=!1}finally{this._spacesLoading=!1}}}get _lang(){return o(this.hass,this._config?.language)}get _floorToken(){const e=this._config?.floor;return"number"==typeof e?`__houseplan_yaml_floor_index__:${String(e)}`:null}get _formData(){const e={...this._config},o=this._floorToken;return o?e.floor=o:Object.prototype.hasOwnProperty.call(e,"floor")||(e.floor=""),e}get _schema(){const e=this._spaces||[],o=this._lang,a=[{value:"",label:t(o,"editor.floor_none")}],i=this._floorToken;i&&a.push({value:i,label:t(o,"editor.floor_index",{index:String(this._config?.floor)})});const l="string"==typeof this._config?.floor?this._config.floor:"";l&&!e.some(e=>e.value===l)&&a.push({value:l,label:l}),a.push(...e);const n="string"==typeof this._config?.default_floor?this._config.default_floor:"",r=[...e];return n&&!e.some(e=>e.value===n)&&r.unshift({value:n,label:n}),[{name:"title",selector:{text:{}}},{name:"floor",selector:{select:{mode:"dropdown",options:a}}},e.length?{name:"default_floor",selector:{select:{mode:"dropdown",options:r}}}:{name:"default_floor",selector:{text:{}}},{name:"language",selector:{select:{mode:"dropdown",options:s(t(o,"editor.lang_auto"),this._config?.language)}}},{name:"icon_size",selector:{number:{min:1,max:6,step:.1,mode:"box"}}},{name:"show_temperature",selector:{boolean:{}}},{name:"live_states",selector:{boolean:{}}},{name:"show_signal",selector:{boolean:{}}},{name:"kiosk",selector:{boolean:{}}},{name:"cycle",selector:{number:{min:0,max:3600,step:5,mode:"box"}}}]}render(){if(!this.hass||!this._config)return a;const e=i(this,l,o(this.hass,this._config.language));if("cold"===e)return n();if("warm"===e)return r;this._loadSpaces();const s=this._lang,h={title:t(s,"editor.title"),floor:t(s,"editor.floor"),default_floor:t(s,"editor.default_floor"),language:t(s,"editor.language"),icon_size:t(s,"editor.icon_size"),show_temperature:t(s,"editor.show_temperature"),live_states:t(s,"editor.live_states"),show_signal:t(s,"editor.show_signal"),kiosk:t(s,"editor.kiosk"),cycle:t(s,"editor.cycle")},f=this._schema,_=function(e,o,t){if(!t||null===o)return null;const s="string"==typeof e?.default_floor?e.default_floor:"";return!s||o.some(e=>e.value===s)?null:s}(this._config,this._spaces,this._spacesAuthoritative),d=e=>c`({value:e.id,label:e.title||e.id})),this._spacesAuthoritative=!0}catch{this._spaces=[],this._spacesAuthoritative=!1}finally{this._spacesLoading=!1}}}get _lang(){return o(this.hass,this._config?.language)}get _floorToken(){const e=this._config?.floor;return"number"==typeof e?`__houseplan_yaml_floor_index__:${String(e)}`:null}get _formData(){const e={...this._config},o=this._floorToken;return o?e.floor=o:Object.prototype.hasOwnProperty.call(e,"floor")||(e.floor=""),e}get _schema(){const e=this._spaces||[],o=this._lang,a=[{value:"",label:t(o,"editor.floor_none")}],i=this._floorToken;i&&a.push({value:i,label:t(o,"editor.floor_index",{index:String(this._config?.floor)})});const l="string"==typeof this._config?.floor?this._config.floor:"";l&&!e.some(e=>e.value===l)&&a.push({value:l,label:l}),a.push(...e);const n="string"==typeof this._config?.default_floor?this._config.default_floor:"",r=[...e];return n&&!e.some(e=>e.value===n)&&r.unshift({value:n,label:n}),[{name:"title",selector:{text:{}}},{name:"floor",selector:{select:{mode:"dropdown",options:a}}},e.length?{name:"default_floor",selector:{select:{mode:"dropdown",options:r}}}:{name:"default_floor",selector:{text:{}}},{name:"language",selector:{select:{mode:"dropdown",options:s(t(o,"editor.lang_auto"),this._config?.language)}}},{name:"icon_size",selector:{number:{min:1,max:6,step:.1,mode:"box"}}},{name:"show_temperature",selector:{boolean:{}}},{name:"live_states",selector:{boolean:{}}},{name:"show_signal",selector:{boolean:{}}},{name:"kiosk",selector:{boolean:{}}},{name:"cycle",selector:{number:{min:0,max:3600,step:5,mode:"box"}}}]}render(){if(!this.hass||!this._config)return a;const e=i(this,l,o(this.hass,this._config.language));if("cold"===e)return n();if("warm"===e)return r;this._loadSpaces();const s=this._lang,h={title:t(s,"editor.title"),floor:t(s,"editor.floor"),default_floor:t(s,"editor.default_floor"),language:t(s,"editor.language"),icon_size:t(s,"editor.icon_size"),show_temperature:t(s,"editor.show_temperature"),live_states:t(s,"editor.live_states"),show_signal:t(s,"editor.show_signal"),kiosk:t(s,"editor.kiosk"),cycle:t(s,"editor.cycle")},f=this._schema,_=function(e,o,t){if(!t||null===o)return null;const s="string"==typeof e?.default_floor?e.default_floor:"";return!s||o.some(e=>e.value===s)?null:s}(this._config,this._spaces,this._spacesAuthoritative),d=e=>c`r===this.ot[t]))return e}else if(this.ot===t)return e;return this.ot=Array.isArray(t)?Array.from(t):t,this.render(t,s)}});export{a as i};
+globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="2e6f7d70c797ae4e865b10859c77cc3380a432272a975b8f35b51234ae3cfe62";import{dS as r,dT as t,dU as e}from"./houseplan-card-BMuv6THL.js";const s={},a=r(class extends t{constructor(){super(...arguments),this.ot=s}render(r,t){return t()}update(r,[t,s]){if(Array.isArray(t)){if(Array.isArray(this.ot)&&this.ot.length===t.length&&t.every((r,t)=>r===this.ot[t]))return e}else if(this.ot===t)return e;return this.ot=Array.isArray(t)?Array.from(t):t,this.render(t,s)}});export{a as i};
diff --git a/custom_components/houseplan/frontend/houseplan-assets/houseplan-card-DXAxXz4t.js b/custom_components/houseplan/frontend/houseplan-assets/houseplan-card-BMuv6THL.js
similarity index 95%
rename from custom_components/houseplan/frontend/houseplan-assets/houseplan-card-DXAxXz4t.js
rename to custom_components/houseplan/frontend/houseplan-assets/houseplan-card-BMuv6THL.js
index 604cb83a..31c623ae 100644
--- a/custom_components/houseplan/frontend/houseplan-assets/houseplan-card-DXAxXz4t.js
+++ b/custom_components/houseplan/frontend/houseplan-assets/houseplan-card-BMuv6THL.js
@@ -1,4 +1,4 @@
-globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="c8d5c166e30a11241ef32c7e1dc70368632e84c448524a8340494350ec4d5fca";const e=globalThis,t=e.ShadowRoot&&(void 0===e.ShadyCSS||e.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,i=Symbol(),n=new WeakMap;let r=class{constructor(e,t,n){if(this._$cssResult$=!0,n!==i)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=e,this.t=t}get styleSheet(){let e=this.o;const i=this.t;if(t&&void 0===e){const t=void 0!==i&&1===i.length;t&&(e=n.get(i)),void 0===e&&((this.o=e=new CSSStyleSheet).replaceSync(this.cssText),t&&n.set(i,e))}return e}toString(){return this.cssText}};const o=(e,...t)=>{const n=1===e.length?e[0]:t.reduce((t,i,n)=>t+(e=>{if(!0===e._$cssResult$)return e.cssText;if("number"==typeof e)return e;throw Error("Value passed to 'css' function must be a 'css' function result: "+e+". Use 'unsafeCSS' to pass non-literal values, but take care to ensure page security.")})(i)+e[n+1],e[0]);return new r(n,e,i)},s=t?e=>e:e=>e instanceof CSSStyleSheet?(e=>{let t="";for(const i of e.cssRules)t+=i.cssText;return(e=>new r("string"==typeof e?e:e+"",void 0,i))(t)})(e):e,{is:a,defineProperty:l,getOwnPropertyDescriptor:c,getOwnPropertyNames:h,getOwnPropertySymbols:d,getPrototypeOf:u}=Object,p=globalThis,_=p.trustedTypes,m=_?_.emptyScript:"",g=p.reactiveElementPolyfillSupport,f=(e,t)=>e,v={toAttribute(e,t){switch(t){case Boolean:e=e?m:null;break;case Object:case Array:e=null==e?e:JSON.stringify(e)}return e},fromAttribute(e,t){let i=e;switch(t){case Boolean:i=null!==e;break;case Number:i=null===e?null:Number(e);break;case Object:case Array:try{i=JSON.parse(e)}catch(e){i=null}}return i}},y=(e,t)=>!a(e,t),b={attribute:!0,type:String,converter:v,reflect:!1,useDefault:!1,hasChanged:y};Symbol.metadata??=Symbol("metadata"),p.litPropertyMetadata??=new WeakMap;let w=class extends HTMLElement{static addInitializer(e){this._$Ei(),(this.l??=[]).push(e)}static get observedAttributes(){return this.finalize(),this._$Eh&&[...this._$Eh.keys()]}static createProperty(e,t=b){if(t.state&&(t.attribute=!1),this._$Ei(),this.prototype.hasOwnProperty(e)&&((t=Object.create(t)).wrapped=!0),this.elementProperties.set(e,t),!t.noAccessor){const i=Symbol(),n=this.getPropertyDescriptor(e,i,t);void 0!==n&&l(this.prototype,e,n)}}static getPropertyDescriptor(e,t,i){const{get:n,set:r}=c(this.prototype,e)??{get(){return this[t]},set(e){this[t]=e}};return{get:n,set(t){const o=n?.call(this);r?.call(this,t),this.requestUpdate(e,o,i)},configurable:!0,enumerable:!0}}static getPropertyOptions(e){return this.elementProperties.get(e)??b}static _$Ei(){if(this.hasOwnProperty(f("elementProperties")))return;const e=u(this);e.finalize(),void 0!==e.l&&(this.l=[...e.l]),this.elementProperties=new Map(e.elementProperties)}static finalize(){if(this.hasOwnProperty(f("finalized")))return;if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(f("properties"))){const e=this.properties,t=[...h(e),...d(e)];for(const i of t)this.createProperty(i,e[i])}const e=this[Symbol.metadata];if(null!==e){const t=litPropertyMetadata.get(e);if(void 0!==t)for(const[e,i]of t)this.elementProperties.set(e,i)}this._$Eh=new Map;for(const[e,t]of this.elementProperties){const i=this._$Eu(e,t);void 0!==i&&this._$Eh.set(i,e)}this.elementStyles=this.finalizeStyles(this.styles)}static finalizeStyles(e){const t=[];if(Array.isArray(e)){const i=new Set(e.flat(1/0).reverse());for(const e of i)t.unshift(s(e))}else void 0!==e&&t.push(s(e));return t}static _$Eu(e,t){const i=t.attribute;return!1===i?void 0:"string"==typeof i?i:"string"==typeof e?e.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(e=>this.enableUpdating=e),this._$AL=new Map,this._$E_(),this.requestUpdate(),this.constructor.l?.forEach(e=>e(this))}addController(e){(this._$EO??=new Set).add(e),void 0!==this.renderRoot&&this.isConnected&&e.hostConnected?.()}removeController(e){this._$EO?.delete(e)}_$E_(){const e=new Map,t=this.constructor.elementProperties;for(const i of t.keys())this.hasOwnProperty(i)&&(e.set(i,this[i]),delete this[i]);e.size>0&&(this._$Ep=e)}createRenderRoot(){const i=this.shadowRoot??this.attachShadow(this.constructor.shadowRootOptions);return((i,n)=>{if(t)i.adoptedStyleSheets=n.map(e=>e instanceof CSSStyleSheet?e:e.styleSheet);else for(const t of n){const n=document.createElement("style"),r=e.litNonce;void 0!==r&&n.setAttribute("nonce",r),n.textContent=t.cssText,i.appendChild(n)}})(i,this.constructor.elementStyles),i}connectedCallback(){this.renderRoot??=this.createRenderRoot(),this.enableUpdating(!0),this._$EO?.forEach(e=>e.hostConnected?.())}enableUpdating(e){}disconnectedCallback(){this._$EO?.forEach(e=>e.hostDisconnected?.())}attributeChangedCallback(e,t,i){this._$AK(e,i)}_$ET(e,t){const i=this.constructor.elementProperties.get(e),n=this.constructor._$Eu(e,i);if(void 0!==n&&!0===i.reflect){const r=(void 0!==i.converter?.toAttribute?i.converter:v).toAttribute(t,i.type);this._$Em=e,null==r?this.removeAttribute(n):this.setAttribute(n,r),this._$Em=null}}_$AK(e,t){const i=this.constructor,n=i._$Eh.get(e);if(void 0!==n&&this._$Em!==n){const e=i.getPropertyOptions(n),r="function"==typeof e.converter?{fromAttribute:e.converter}:void 0!==e.converter?.fromAttribute?e.converter:v;this._$Em=n;const o=r.fromAttribute(t,e.type);this[n]=o??this._$Ej?.get(n)??o,this._$Em=null}}requestUpdate(e,t,i,n=!1,r){if(void 0!==e){const o=this.constructor;if(!1===n&&(r=this[e]),i??=o.getPropertyOptions(e),!((i.hasChanged??y)(r,t)||i.useDefault&&i.reflect&&r===this._$Ej?.get(e)&&!this.hasAttribute(o._$Eu(e,i))))return;this.C(e,t,i)}!1===this.isUpdatePending&&(this._$ES=this._$EP())}C(e,t,{useDefault:i,reflect:n,wrapped:r},o){i&&!(this._$Ej??=new Map).has(e)&&(this._$Ej.set(e,o??t??this[e]),!0!==r||void 0!==o)||(this._$AL.has(e)||(this.hasUpdated||i||(t=void 0),this._$AL.set(e,t)),!0===n&&this._$Em!==e&&(this._$Eq??=new Set).add(e))}async _$EP(){this.isUpdatePending=!0;try{await this._$ES}catch(e){Promise.reject(e)}const e=this.scheduleUpdate();return null!=e&&await e,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){if(!this.isUpdatePending)return;if(!this.hasUpdated){if(this.renderRoot??=this.createRenderRoot(),this._$Ep){for(const[e,t]of this._$Ep)this[e]=t;this._$Ep=void 0}const e=this.constructor.elementProperties;if(e.size>0)for(const[t,i]of e){const{wrapped:e}=i,n=this[t];!0!==e||this._$AL.has(t)||void 0===n||this.C(t,void 0,i,n)}}let e=!1;const t=this._$AL;try{e=this.shouldUpdate(t),e?(this.willUpdate(t),this._$EO?.forEach(e=>e.hostUpdate?.()),this.update(t)):this._$EM()}catch(t){throw e=!1,this._$EM(),t}e&&this._$AE(t)}willUpdate(e){}_$AE(e){this._$EO?.forEach(e=>e.hostUpdated?.()),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(e)),this.updated(e)}_$EM(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$ES}shouldUpdate(e){return!0}update(e){this._$Eq&&=this._$Eq.forEach(e=>this._$ET(e,this[e])),this._$EM()}updated(e){}firstUpdated(e){}};w.elementStyles=[],w.shadowRootOptions={mode:"open"},w[f("elementProperties")]=new Map,w[f("finalized")]=new Map,g?.({ReactiveElement:w}),(p.reactiveElementVersions??=[]).push("2.1.2");const k=globalThis,x=e=>e,S=k.trustedTypes,$=S?S.createPolicy("lit-html",{createHTML:e=>e}):void 0,M="$lit$",R=`lit$${Math.random().toFixed(9).slice(2)}$`,C="?"+R,T=`<${C}>`,D=document,A=()=>D.createComment(""),P=e=>null===e||"object"!=typeof e&&"function"!=typeof e,F=Array.isArray,z="[ \t\n\f\r]",I=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,O=/-->/g,E=/>/g,N=RegExp(`>|${z}(?:([^\\s"'>=/]+)(${z}*=${z}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),H=/'/g,L=/"/g,B=/^(?:script|style|textarea|title)$/i,q=e=>(t,...i)=>({_$litType$:e,strings:t,values:i}),j=q(1),W=q(2),U=Symbol.for("lit-noChange"),V=Symbol.for("lit-nothing"),G=new WeakMap,K=D.createTreeWalker(D,129);function Y(e,t){if(!F(e)||!e.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==$?$.createHTML(t):t}const X=(e,t)=>{const i=e.length-1,n=[];let r,o=2===t?"":3===t?"":"")),n]};class Z{constructor({strings:e,_$litType$:t},i){let n;this.parts=[];let r=0,o=0;const s=e.length-1,a=this.parts,[l,c]=X(e,t);if(this.el=Z.createElement(l,i),K.currentNode=this.el.content,2===t||3===t){const e=this.el.content.firstChild;e.replaceWith(...e.childNodes)}for(;null!==(n=K.nextNode())&&a.length0){n.textContent=S?S.emptyScript:"";for(let i=0;iF(e)||"function"==typeof e?.[Symbol.iterator])(e)?this.k(e):this._(e)}O(e){return this._$AA.parentNode.insertBefore(e,this._$AB)}T(e){this._$AH!==e&&(this._$AR(),this._$AH=this.O(e))}_(e){this._$AH!==V&&P(this._$AH)?this._$AA.nextSibling.data=e:this.T(D.createTextNode(e)),this._$AH=e}$(e){const{values:t,_$litType$:i}=e,n="number"==typeof i?this._$AC(e):(void 0===i.el&&(i.el=Z.createElement(Y(i.h,i.h[0]),this.options)),i);if(this._$AH?._$AD===n)this._$AH.p(t);else{const e=new Q(n,this),i=e.u(this.options);e.p(t),this.T(i),this._$AH=e}}_$AC(e){let t=G.get(e.strings);return void 0===t&&G.set(e.strings,t=new Z(e)),t}k(e){F(this._$AH)||(this._$AH=[],this._$AR());const t=this._$AH;let i,n=0;for(const r of e)n===t.length?t.push(i=new ee(this.O(A()),this.O(A()),this,this.options)):i=t[n],i._$AI(r),n++;n2||""!==i[0]||""!==i[1]?(this._$AH=Array(i.length-1).fill(new String),this.strings=i):this._$AH=V}_$AI(e,t=this,i,n){const r=this.strings;let o=!1;if(void 0===r)e=J(this,e,t,0),o=!P(e)||e!==this._$AH&&e!==U,o&&(this._$AH=e);else{const n=e;let s,a;for(e=r[0],s=0;s{const n=i?.renderBefore??t;let r=n._$litPart$;if(void 0===r){const e=i?.renderBefore??null;n._$litPart$=r=new ee(t.insertBefore(A(),e),e,void 0,i??{})}return r._$AI(e),r},ce=globalThis;let he=class extends w{constructor(){super(...arguments),this.renderOptions={host:this},this._$Do=void 0}createRenderRoot(){const e=super.createRenderRoot();return this.renderOptions.renderBefore??=e.firstChild,e}update(e){const t=this.render();this.hasUpdated||(this.renderOptions.isConnected=this.isConnected),super.update(e),this._$Do=le(t,this.renderRoot,this.renderOptions)}connectedCallback(){super.connectedCallback(),this._$Do?.setConnected(!0)}disconnectedCallback(){super.disconnectedCallback(),this._$Do?.setConnected(!1)}render(){return U}};he._$litElement$=!0,he.finalized=!0,ce.litElementHydrateSupport?.({LitElement:he});const de=ce.litElementPolyfillSupport;de?.({LitElement:he}),(ce.litElementVersions??=[]).push("4.2.2");const ue=2,pe=e=>(...t)=>({_$litDirective$:e,values:t});let _e=class{constructor(e){}get _$AU(){return this._$AM._$AU}_$AT(e,t,i){this._$Ct=e,this._$AM=t,this._$Ci=i}_$AS(e,t){return this.update(e,t)}update(e,t){return this.render(...t)}};const{I:me}=se,ge=e=>e,fe=(e,t)=>void 0!==e?._$litType$,ve=()=>document.createComment(""),ye=(e,t,i)=>{const n=e._$AA.parentNode,r=void 0===t?e._$AB:t._$AA;if(void 0===i){const t=n.insertBefore(ve(),r),o=n.insertBefore(ve(),r);i=new me(t,o,e,e.options)}else{const t=i._$AB.nextSibling,o=i._$AM,s=o!==e;if(s){let t;i._$AQ?.(e),i._$AM=e,void 0!==i._$AP&&(t=e._$AU)!==o._$AU&&i._$AP(t)}if(t!==r||s){let e=i._$AA;for(;e!==t;){const t=ge(e).nextSibling;ge(n).insertBefore(e,r),e=t}}}return i},be=(e,t,i=e)=>(e._$AI(t,i),e),we={},ke=(e,t=we)=>e._$AH=t,xe=e=>e._$AH,Se=e=>{e._$AR(),e._$AA.remove()},$e=e=>(e=>null!=e?._$litType$?.h)(e)?e._$litType$.h:e.strings,Me=pe(class extends _e{constructor(e){super(e),this.et=new WeakMap}render(e){return[e]}update(e,[t]){const i=fe(this.it)?$e(this.it):null,n=fe(t)?$e(t):null;if(null!==i&&(null===n||i!==n)){const t=xe(e).pop();let n=this.et.get(i);if(void 0===n){const e=document.createDocumentFragment();n=le(V,e),n.setConnected(!1),this.et.set(i,n)}ke(n,[t]),ye(n,void 0,t)}if(null!==n){if(null===i||i!==n){const t=this.et.get(n);if(void 0!==t){const i=xe(t).pop();(e=>{e._$AR()})(e),ye(e,void 0,i),ke(e,[i])}}this.it=t}else this.it=void 0;return this.render(t)}}),Re=new WeakMap;let Ce=0;class Te extends he{constructor(){super(...arguments),this.title="",this.icon="",this.wide=!1,this.alert=!1,this.describedBy="",this.dismissOnScrim=!1,this.flexContent=!1,this.hass=null,this._opener=null,this._focusRoot=null,this._useHaDialog=null,this._closing=!1,this._overlays=[],this._titleId="hp-dialog-title-"+ ++Ce,this._focusInitial=()=>{const e=this._focusableElements(),t=e.find(e=>e.hasAttribute("autofocus"))||e[0]||(this._usesHaDialog()?null:this.renderRoot.querySelector(".close"))||this.renderRoot.querySelector(".surface")||this.renderRoot.querySelector("ha-dialog");t?.focus({preventScroll:!0})},this._requestClose=()=>{this._closing||(this._closing=!0,this.dispatchEvent(new CustomEvent("hp-close",{bubbles:!0,composed:!0})))},this._onKeyDown=e=>{if("Escape"===e.key){e.preventDefault(),e.stopImmediatePropagation(),this._pruneOverlays();const t=this._overlays[this._overlays.length-1];return t?void this._closeOverlay(t,"escape"):void this._requestClose()}if("Tab"!==e.key||this._usesHaDialog())return;const t=this.renderRoot.querySelector(".close"),i=t?[t,...this._focusableElements()]:this._focusableElements();if(!i.length)return e.preventDefault(),void this.renderRoot.querySelector(".surface")?.focus({preventScroll:!0});const n=this._deepActiveElement(),r=i[0],o=i[i.length-1];!e.shiftKey||n!==r&&i.includes(n)?e.shiftKey||n!==o||(e.preventDefault(),r.focus()):(e.preventDefault(),o.focus())},this._onFallbackCancel=e=>{e.preventDefault(),this._requestClose()},this._onFallbackClick=e=>{this.dismissOnScrim&&e.target===e.currentTarget&&this._requestClose()}}_usesHaDialog(){return!0===this._useHaDialog&&!this.alert}connectedCallback(){this.setAttribute("data-hp","dialog"),super.connectedCallback(),this._opener=this._deepActiveElement();const e=this.getRootNode();this._focusRoot=e;const t=Re.get(e)||{dialogs:new Set,opener:this._opener};t.dialogs.add(this),Re.set(e,t),null===this._useHaDialog&&(this._useHaDialog=!!customElements.get("ha-dialog")),this.addEventListener("keydown",this._onKeyDown,!0),queueMicrotask(()=>{this._ensureNativeModal()&&this._focusInitial()})}disconnectedCallback(){this.removeEventListener("keydown",this._onKeyDown,!0);const e=[...this._overlays];this._overlays=[];for(const t of e.reverse())t.close("disconnect");const t=this._focusRoot,i=this._opener;this._opener=null,this._focusRoot=null;const n=t?Re.get(t):void 0;n?.dialogs.delete(this),super.disconnectedCallback(),t&&n&&requestAnimationFrame(()=>{const e=Re.get(t);if(!e)return;if(!e.dialogs.size)return e.opener?.isConnected&&e.opener.focus({preventScroll:!0}),void Re.delete(t);const n=i?.closest("hp-dialog");i?.isConnected&&n&&e.dialogs.has(n)&&i.focus({preventScroll:!0})})}firstUpdated(e){super.firstUpdated(e),this._ensureNativeModal(),queueMicrotask(()=>this._focusInitial())}updated(e){super.updated(e),this._ensureNativeModal()}_ensureNativeModal(){if(this._usesHaDialog()||!this.isConnected)return!1;const e=this.renderRoot.querySelector("dialog");if(!e?.isConnected)return!1;try{return!e.matches(":modal")&&(e.open&&e.close(),e.showModal(),!0)}catch{return!1}}_deepActiveElement(){let e=document.activeElement;for(;e?.shadowRoot?.activeElement;)e=e.shadowRoot.activeElement;return e&&e!==document.body?e:null}_focusableElements(){const e=["[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(","),t=[],i=new Set,n=r=>{if(!i.has(r)){if(i.add(r),r instanceof HTMLElement){if(r.matches(e)&&t.push(r),r instanceof HTMLSlotElement){for(const e of r.assignedNodes({flatten:!0}))n(e);return}if(r.shadowRoot){for(const e of r.shadowRoot.childNodes)n(e);return}}for(const e of r.childNodes)n(e)}};for(const e of this.childNodes)n(e);const r=this.overlayPortal();return r&&n(r),t.filter(e=>{let t=e;for(;t;){const e=getComputedStyle(t);if(t.hidden||t.inert||"true"===t.getAttribute("aria-hidden")||"none"===e.display||"hidden"===e.visibility)return!1;if(t=t.assignedSlot||t.parentElement||(t.getRootNode()instanceof ShadowRoot?t.getRootNode().host:null),t===this)break}return!0})}rejectClose(){this._closing=!1,this.requestUpdate()}_pruneOverlays(){this._overlays=this._overlays.filter(e=>e.owner.isConnected)}_closeOverlay(e,t){const i=this._overlays.findIndex(t=>t.token===e.token);i>=0&&this._overlays.splice(i,1),e.close(t)}registerOverlay(e){this._pruneOverlays();const t=this._overlays.find(t=>t.owner===e.owner);t&&this._overlays.splice(this._overlays.indexOf(t),1);const i=e.group||"transient";for(const e of[...this._overlays].reverse())e.group===i&&this._closeOverlay(e,"exclusive");const n={...e,group:i,token:Symbol("hp-overlay")};this._overlays.push(n);let r=!1;return()=>{if(r)return;r=!0;const e=this._overlays.findIndex(e=>e.token===n.token);e>=0&&this._overlays.splice(e,1)}}closeTransientOverlays(e="outside"){this._pruneOverlays();const t=[...this._overlays].filter(e=>"transient"===(e.group||"transient"));for(const i of t.reverse())this._closeOverlay(i,e);return t.length>0}overlayPortal(){return this.renderRoot.querySelector(".overlay-portal")}render(){const e=j`
+globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="2e6f7d70c797ae4e865b10859c77cc3380a432272a975b8f35b51234ae3cfe62";const e=globalThis,t=e.ShadowRoot&&(void 0===e.ShadyCSS||e.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,i=Symbol(),n=new WeakMap;let r=class{constructor(e,t,n){if(this._$cssResult$=!0,n!==i)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=e,this.t=t}get styleSheet(){let e=this.o;const i=this.t;if(t&&void 0===e){const t=void 0!==i&&1===i.length;t&&(e=n.get(i)),void 0===e&&((this.o=e=new CSSStyleSheet).replaceSync(this.cssText),t&&n.set(i,e))}return e}toString(){return this.cssText}};const o=(e,...t)=>{const n=1===e.length?e[0]:t.reduce((t,i,n)=>t+(e=>{if(!0===e._$cssResult$)return e.cssText;if("number"==typeof e)return e;throw Error("Value passed to 'css' function must be a 'css' function result: "+e+". Use 'unsafeCSS' to pass non-literal values, but take care to ensure page security.")})(i)+e[n+1],e[0]);return new r(n,e,i)},s=t?e=>e:e=>e instanceof CSSStyleSheet?(e=>{let t="";for(const i of e.cssRules)t+=i.cssText;return(e=>new r("string"==typeof e?e:e+"",void 0,i))(t)})(e):e,{is:a,defineProperty:l,getOwnPropertyDescriptor:c,getOwnPropertyNames:h,getOwnPropertySymbols:d,getPrototypeOf:u}=Object,p=globalThis,_=p.trustedTypes,m=_?_.emptyScript:"",g=p.reactiveElementPolyfillSupport,f=(e,t)=>e,v={toAttribute(e,t){switch(t){case Boolean:e=e?m:null;break;case Object:case Array:e=null==e?e:JSON.stringify(e)}return e},fromAttribute(e,t){let i=e;switch(t){case Boolean:i=null!==e;break;case Number:i=null===e?null:Number(e);break;case Object:case Array:try{i=JSON.parse(e)}catch(e){i=null}}return i}},y=(e,t)=>!a(e,t),b={attribute:!0,type:String,converter:v,reflect:!1,useDefault:!1,hasChanged:y};Symbol.metadata??=Symbol("metadata"),p.litPropertyMetadata??=new WeakMap;let w=class extends HTMLElement{static addInitializer(e){this._$Ei(),(this.l??=[]).push(e)}static get observedAttributes(){return this.finalize(),this._$Eh&&[...this._$Eh.keys()]}static createProperty(e,t=b){if(t.state&&(t.attribute=!1),this._$Ei(),this.prototype.hasOwnProperty(e)&&((t=Object.create(t)).wrapped=!0),this.elementProperties.set(e,t),!t.noAccessor){const i=Symbol(),n=this.getPropertyDescriptor(e,i,t);void 0!==n&&l(this.prototype,e,n)}}static getPropertyDescriptor(e,t,i){const{get:n,set:r}=c(this.prototype,e)??{get(){return this[t]},set(e){this[t]=e}};return{get:n,set(t){const o=n?.call(this);r?.call(this,t),this.requestUpdate(e,o,i)},configurable:!0,enumerable:!0}}static getPropertyOptions(e){return this.elementProperties.get(e)??b}static _$Ei(){if(this.hasOwnProperty(f("elementProperties")))return;const e=u(this);e.finalize(),void 0!==e.l&&(this.l=[...e.l]),this.elementProperties=new Map(e.elementProperties)}static finalize(){if(this.hasOwnProperty(f("finalized")))return;if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(f("properties"))){const e=this.properties,t=[...h(e),...d(e)];for(const i of t)this.createProperty(i,e[i])}const e=this[Symbol.metadata];if(null!==e){const t=litPropertyMetadata.get(e);if(void 0!==t)for(const[e,i]of t)this.elementProperties.set(e,i)}this._$Eh=new Map;for(const[e,t]of this.elementProperties){const i=this._$Eu(e,t);void 0!==i&&this._$Eh.set(i,e)}this.elementStyles=this.finalizeStyles(this.styles)}static finalizeStyles(e){const t=[];if(Array.isArray(e)){const i=new Set(e.flat(1/0).reverse());for(const e of i)t.unshift(s(e))}else void 0!==e&&t.push(s(e));return t}static _$Eu(e,t){const i=t.attribute;return!1===i?void 0:"string"==typeof i?i:"string"==typeof e?e.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(e=>this.enableUpdating=e),this._$AL=new Map,this._$E_(),this.requestUpdate(),this.constructor.l?.forEach(e=>e(this))}addController(e){(this._$EO??=new Set).add(e),void 0!==this.renderRoot&&this.isConnected&&e.hostConnected?.()}removeController(e){this._$EO?.delete(e)}_$E_(){const e=new Map,t=this.constructor.elementProperties;for(const i of t.keys())this.hasOwnProperty(i)&&(e.set(i,this[i]),delete this[i]);e.size>0&&(this._$Ep=e)}createRenderRoot(){const i=this.shadowRoot??this.attachShadow(this.constructor.shadowRootOptions);return((i,n)=>{if(t)i.adoptedStyleSheets=n.map(e=>e instanceof CSSStyleSheet?e:e.styleSheet);else for(const t of n){const n=document.createElement("style"),r=e.litNonce;void 0!==r&&n.setAttribute("nonce",r),n.textContent=t.cssText,i.appendChild(n)}})(i,this.constructor.elementStyles),i}connectedCallback(){this.renderRoot??=this.createRenderRoot(),this.enableUpdating(!0),this._$EO?.forEach(e=>e.hostConnected?.())}enableUpdating(e){}disconnectedCallback(){this._$EO?.forEach(e=>e.hostDisconnected?.())}attributeChangedCallback(e,t,i){this._$AK(e,i)}_$ET(e,t){const i=this.constructor.elementProperties.get(e),n=this.constructor._$Eu(e,i);if(void 0!==n&&!0===i.reflect){const r=(void 0!==i.converter?.toAttribute?i.converter:v).toAttribute(t,i.type);this._$Em=e,null==r?this.removeAttribute(n):this.setAttribute(n,r),this._$Em=null}}_$AK(e,t){const i=this.constructor,n=i._$Eh.get(e);if(void 0!==n&&this._$Em!==n){const e=i.getPropertyOptions(n),r="function"==typeof e.converter?{fromAttribute:e.converter}:void 0!==e.converter?.fromAttribute?e.converter:v;this._$Em=n;const o=r.fromAttribute(t,e.type);this[n]=o??this._$Ej?.get(n)??o,this._$Em=null}}requestUpdate(e,t,i,n=!1,r){if(void 0!==e){const o=this.constructor;if(!1===n&&(r=this[e]),i??=o.getPropertyOptions(e),!((i.hasChanged??y)(r,t)||i.useDefault&&i.reflect&&r===this._$Ej?.get(e)&&!this.hasAttribute(o._$Eu(e,i))))return;this.C(e,t,i)}!1===this.isUpdatePending&&(this._$ES=this._$EP())}C(e,t,{useDefault:i,reflect:n,wrapped:r},o){i&&!(this._$Ej??=new Map).has(e)&&(this._$Ej.set(e,o??t??this[e]),!0!==r||void 0!==o)||(this._$AL.has(e)||(this.hasUpdated||i||(t=void 0),this._$AL.set(e,t)),!0===n&&this._$Em!==e&&(this._$Eq??=new Set).add(e))}async _$EP(){this.isUpdatePending=!0;try{await this._$ES}catch(e){Promise.reject(e)}const e=this.scheduleUpdate();return null!=e&&await e,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){if(!this.isUpdatePending)return;if(!this.hasUpdated){if(this.renderRoot??=this.createRenderRoot(),this._$Ep){for(const[e,t]of this._$Ep)this[e]=t;this._$Ep=void 0}const e=this.constructor.elementProperties;if(e.size>0)for(const[t,i]of e){const{wrapped:e}=i,n=this[t];!0!==e||this._$AL.has(t)||void 0===n||this.C(t,void 0,i,n)}}let e=!1;const t=this._$AL;try{e=this.shouldUpdate(t),e?(this.willUpdate(t),this._$EO?.forEach(e=>e.hostUpdate?.()),this.update(t)):this._$EM()}catch(t){throw e=!1,this._$EM(),t}e&&this._$AE(t)}willUpdate(e){}_$AE(e){this._$EO?.forEach(e=>e.hostUpdated?.()),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(e)),this.updated(e)}_$EM(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$ES}shouldUpdate(e){return!0}update(e){this._$Eq&&=this._$Eq.forEach(e=>this._$ET(e,this[e])),this._$EM()}updated(e){}firstUpdated(e){}};w.elementStyles=[],w.shadowRootOptions={mode:"open"},w[f("elementProperties")]=new Map,w[f("finalized")]=new Map,g?.({ReactiveElement:w}),(p.reactiveElementVersions??=[]).push("2.1.2");const k=globalThis,x=e=>e,S=k.trustedTypes,$=S?S.createPolicy("lit-html",{createHTML:e=>e}):void 0,M="$lit$",R=`lit$${Math.random().toFixed(9).slice(2)}$`,C="?"+R,T=`<${C}>`,D=document,A=()=>D.createComment(""),P=e=>null===e||"object"!=typeof e&&"function"!=typeof e,F=Array.isArray,z="[ \t\n\f\r]",I=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,O=/-->/g,E=/>/g,N=RegExp(`>|${z}(?:([^\\s"'>=/]+)(${z}*=${z}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),H=/'/g,L=/"/g,B=/^(?:script|style|textarea|title)$/i,q=e=>(t,...i)=>({_$litType$:e,strings:t,values:i}),j=q(1),W=q(2),U=Symbol.for("lit-noChange"),V=Symbol.for("lit-nothing"),G=new WeakMap,K=D.createTreeWalker(D,129);function Y(e,t){if(!F(e)||!e.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==$?$.createHTML(t):t}const X=(e,t)=>{const i=e.length-1,n=[];let r,o=2===t?"":3===t?"":"")),n]};class Z{constructor({strings:e,_$litType$:t},i){let n;this.parts=[];let r=0,o=0;const s=e.length-1,a=this.parts,[l,c]=X(e,t);if(this.el=Z.createElement(l,i),K.currentNode=this.el.content,2===t||3===t){const e=this.el.content.firstChild;e.replaceWith(...e.childNodes)}for(;null!==(n=K.nextNode())&&a.length0){n.textContent=S?S.emptyScript:"";for(let i=0;iF(e)||"function"==typeof e?.[Symbol.iterator])(e)?this.k(e):this._(e)}O(e){return this._$AA.parentNode.insertBefore(e,this._$AB)}T(e){this._$AH!==e&&(this._$AR(),this._$AH=this.O(e))}_(e){this._$AH!==V&&P(this._$AH)?this._$AA.nextSibling.data=e:this.T(D.createTextNode(e)),this._$AH=e}$(e){const{values:t,_$litType$:i}=e,n="number"==typeof i?this._$AC(e):(void 0===i.el&&(i.el=Z.createElement(Y(i.h,i.h[0]),this.options)),i);if(this._$AH?._$AD===n)this._$AH.p(t);else{const e=new Q(n,this),i=e.u(this.options);e.p(t),this.T(i),this._$AH=e}}_$AC(e){let t=G.get(e.strings);return void 0===t&&G.set(e.strings,t=new Z(e)),t}k(e){F(this._$AH)||(this._$AH=[],this._$AR());const t=this._$AH;let i,n=0;for(const r of e)n===t.length?t.push(i=new ee(this.O(A()),this.O(A()),this,this.options)):i=t[n],i._$AI(r),n++;n2||""!==i[0]||""!==i[1]?(this._$AH=Array(i.length-1).fill(new String),this.strings=i):this._$AH=V}_$AI(e,t=this,i,n){const r=this.strings;let o=!1;if(void 0===r)e=J(this,e,t,0),o=!P(e)||e!==this._$AH&&e!==U,o&&(this._$AH=e);else{const n=e;let s,a;for(e=r[0],s=0;s{const n=i?.renderBefore??t;let r=n._$litPart$;if(void 0===r){const e=i?.renderBefore??null;n._$litPart$=r=new ee(t.insertBefore(A(),e),e,void 0,i??{})}return r._$AI(e),r},ce=globalThis;let he=class extends w{constructor(){super(...arguments),this.renderOptions={host:this},this._$Do=void 0}createRenderRoot(){const e=super.createRenderRoot();return this.renderOptions.renderBefore??=e.firstChild,e}update(e){const t=this.render();this.hasUpdated||(this.renderOptions.isConnected=this.isConnected),super.update(e),this._$Do=le(t,this.renderRoot,this.renderOptions)}connectedCallback(){super.connectedCallback(),this._$Do?.setConnected(!0)}disconnectedCallback(){super.disconnectedCallback(),this._$Do?.setConnected(!1)}render(){return U}};he._$litElement$=!0,he.finalized=!0,ce.litElementHydrateSupport?.({LitElement:he});const de=ce.litElementPolyfillSupport;de?.({LitElement:he}),(ce.litElementVersions??=[]).push("4.2.2");const ue=2,pe=e=>(...t)=>({_$litDirective$:e,values:t});let _e=class{constructor(e){}get _$AU(){return this._$AM._$AU}_$AT(e,t,i){this._$Ct=e,this._$AM=t,this._$Ci=i}_$AS(e,t){return this.update(e,t)}update(e,t){return this.render(...t)}};const{I:me}=se,ge=e=>e,fe=(e,t)=>void 0!==e?._$litType$,ve=()=>document.createComment(""),ye=(e,t,i)=>{const n=e._$AA.parentNode,r=void 0===t?e._$AB:t._$AA;if(void 0===i){const t=n.insertBefore(ve(),r),o=n.insertBefore(ve(),r);i=new me(t,o,e,e.options)}else{const t=i._$AB.nextSibling,o=i._$AM,s=o!==e;if(s){let t;i._$AQ?.(e),i._$AM=e,void 0!==i._$AP&&(t=e._$AU)!==o._$AU&&i._$AP(t)}if(t!==r||s){let e=i._$AA;for(;e!==t;){const t=ge(e).nextSibling;ge(n).insertBefore(e,r),e=t}}}return i},be=(e,t,i=e)=>(e._$AI(t,i),e),we={},ke=(e,t=we)=>e._$AH=t,xe=e=>e._$AH,Se=e=>{e._$AR(),e._$AA.remove()},$e=e=>(e=>null!=e?._$litType$?.h)(e)?e._$litType$.h:e.strings,Me=pe(class extends _e{constructor(e){super(e),this.et=new WeakMap}render(e){return[e]}update(e,[t]){const i=fe(this.it)?$e(this.it):null,n=fe(t)?$e(t):null;if(null!==i&&(null===n||i!==n)){const t=xe(e).pop();let n=this.et.get(i);if(void 0===n){const e=document.createDocumentFragment();n=le(V,e),n.setConnected(!1),this.et.set(i,n)}ke(n,[t]),ye(n,void 0,t)}if(null!==n){if(null===i||i!==n){const t=this.et.get(n);if(void 0!==t){const i=xe(t).pop();(e=>{e._$AR()})(e),ye(e,void 0,i),ke(e,[i])}}this.it=t}else this.it=void 0;return this.render(t)}}),Re=new WeakMap;let Ce=0;class Te extends he{constructor(){super(...arguments),this.title="",this.icon="",this.wide=!1,this.alert=!1,this.describedBy="",this.dismissOnScrim=!1,this.flexContent=!1,this.hass=null,this._opener=null,this._focusRoot=null,this._useHaDialog=null,this._closing=!1,this._overlays=[],this._titleId="hp-dialog-title-"+ ++Ce,this._focusInitial=()=>{const e=this._focusableElements(),t=e.find(e=>e.hasAttribute("autofocus"))||e[0]||(this._usesHaDialog()?null:this.renderRoot.querySelector(".close"))||this.renderRoot.querySelector(".surface")||this.renderRoot.querySelector("ha-dialog");t?.focus({preventScroll:!0})},this._requestClose=()=>{this._closing||(this._closing=!0,this.dispatchEvent(new CustomEvent("hp-close",{bubbles:!0,composed:!0})))},this._onKeyDown=e=>{if("Escape"===e.key){e.preventDefault(),e.stopImmediatePropagation(),this._pruneOverlays();const t=this._overlays[this._overlays.length-1];return t?void this._closeOverlay(t,"escape"):void this._requestClose()}if("Tab"!==e.key||this._usesHaDialog())return;const t=this.renderRoot.querySelector(".close"),i=t?[t,...this._focusableElements()]:this._focusableElements();if(!i.length)return e.preventDefault(),void this.renderRoot.querySelector(".surface")?.focus({preventScroll:!0});const n=this._deepActiveElement(),r=i[0],o=i[i.length-1];!e.shiftKey||n!==r&&i.includes(n)?e.shiftKey||n!==o||(e.preventDefault(),r.focus()):(e.preventDefault(),o.focus())},this._onFallbackCancel=e=>{e.preventDefault(),this._requestClose()},this._onFallbackClick=e=>{this.dismissOnScrim&&e.target===e.currentTarget&&this._requestClose()}}_usesHaDialog(){return!0===this._useHaDialog&&!this.alert}connectedCallback(){this.setAttribute("data-hp","dialog"),super.connectedCallback(),this._opener=this._deepActiveElement();const e=this.getRootNode();this._focusRoot=e;const t=Re.get(e)||{dialogs:new Set,opener:this._opener};t.dialogs.add(this),Re.set(e,t),null===this._useHaDialog&&(this._useHaDialog=!!customElements.get("ha-dialog")),this.addEventListener("keydown",this._onKeyDown,!0),queueMicrotask(()=>{this._ensureNativeModal()&&this._focusInitial()})}disconnectedCallback(){this.removeEventListener("keydown",this._onKeyDown,!0);const e=[...this._overlays];this._overlays=[];for(const t of e.reverse())t.close("disconnect");const t=this._focusRoot,i=this._opener;this._opener=null,this._focusRoot=null;const n=t?Re.get(t):void 0;n?.dialogs.delete(this),super.disconnectedCallback(),t&&n&&requestAnimationFrame(()=>{const e=Re.get(t);if(!e)return;if(!e.dialogs.size)return e.opener?.isConnected&&e.opener.focus({preventScroll:!0}),void Re.delete(t);const n=i?.closest("hp-dialog");i?.isConnected&&n&&e.dialogs.has(n)&&i.focus({preventScroll:!0})})}firstUpdated(e){super.firstUpdated(e),this._ensureNativeModal(),queueMicrotask(()=>this._focusInitial())}updated(e){super.updated(e),this._ensureNativeModal()}_ensureNativeModal(){if(this._usesHaDialog()||!this.isConnected)return!1;const e=this.renderRoot.querySelector("dialog");if(!e?.isConnected)return!1;try{return!e.matches(":modal")&&(e.open&&e.close(),e.showModal(),!0)}catch{return!1}}_deepActiveElement(){let e=document.activeElement;for(;e?.shadowRoot?.activeElement;)e=e.shadowRoot.activeElement;return e&&e!==document.body?e:null}_focusableElements(){const e=["[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(","),t=[],i=new Set,n=r=>{if(!i.has(r)){if(i.add(r),r instanceof HTMLElement){if(r.matches(e)&&t.push(r),r instanceof HTMLSlotElement){for(const e of r.assignedNodes({flatten:!0}))n(e);return}if(r.shadowRoot){for(const e of r.shadowRoot.childNodes)n(e);return}}for(const e of r.childNodes)n(e)}};for(const e of this.childNodes)n(e);const r=this.overlayPortal();return r&&n(r),t.filter(e=>{let t=e;for(;t;){const e=getComputedStyle(t);if(t.hidden||t.inert||"true"===t.getAttribute("aria-hidden")||"none"===e.display||"hidden"===e.visibility)return!1;if(t=t.assignedSlot||t.parentElement||(t.getRootNode()instanceof ShadowRoot?t.getRootNode().host:null),t===this)break}return!0})}rejectClose(){this._closing=!1,this.requestUpdate()}_pruneOverlays(){this._overlays=this._overlays.filter(e=>e.owner.isConnected)}_closeOverlay(e,t){const i=this._overlays.findIndex(t=>t.token===e.token);i>=0&&this._overlays.splice(i,1),e.close(t)}registerOverlay(e){this._pruneOverlays();const t=this._overlays.find(t=>t.owner===e.owner);t&&this._overlays.splice(this._overlays.indexOf(t),1);const i=e.group||"transient";for(const e of[...this._overlays].reverse())e.group===i&&this._closeOverlay(e,"exclusive");const n={...e,group:i,token:Symbol("hp-overlay")};this._overlays.push(n);let r=!1;return()=>{if(r)return;r=!0;const e=this._overlays.findIndex(e=>e.token===n.token);e>=0&&this._overlays.splice(e,1)}}closeTransientOverlays(e="outside"){this._pruneOverlays();const t=[...this._overlays].filter(e=>"transient"===(e.group||"transient"));for(const i of t.reverse())this._closeOverlay(i,e);return t.length>0}overlayPortal(){return this.renderRoot.querySelector(".overlay-portal")}render(){const e=j`
${this.icon?j``:V}
${this.title}`;return this._usesHaDialog()?this.describedBy?j`
`})}
- `}const br={color:"#607d8b",opacity:1,widthCm:3.6,fill:!1,fillColor:"#607d8b",fillOpacity:.25},wr=(e,t=1)=>{const i=Number(e);return Number.isFinite(i)?Math.min(1,Math.max(0,i)):t},kr=e=>{let t=Number(e);return Number.isFinite(t)?(t=(t%360+360)%360,t>180?t-360:t):0};function xr(e,t,i){return kr(t)?[e.x,e.y]:i([e.x,e.y])}function Sr(e,t,i,n){const r=Math.abs(i[0]-t[0]),o=Math.abs(i[1]-t[1]);return"line"===e?Math.hypot(r,o)>=n:r>=n&&o>=n}const $r=(e,t,i)=>{const n=Number(e),r=Number.isFinite(t)&&t>0?t:5;return Number.isFinite(n)&&n>0?n/r*i:0},Mr=(e,t,i)=>{const n=Number(e),r=Number.isFinite(t)&&t>0?t:5;return Number.isFinite(n)&&i>0?n/i*r:0},Rr=(e,t,i,n=br.widthCm)=>{const r=Number(e?.width_cm);if(Number.isFinite(r)&&r>0)return r;const o=Number(e?.width);return Number.isFinite(o)&&o>0?Mr(o,t,i):n};function Cr(e){const t=br;return e.color===t.color&&e.opacity===t.opacity&&e.widthCm===t.widthCm&&e.fill===t.fill&&e.fillColor===t.fillColor&&e.fillOpacity===t.fillOpacity?null:{color:e.color,opacity:wr(e.opacity),width_cm:Math.max(.1,Math.min(100,Number(e.widthCm)||.1)),fill:!!e.fill,fill_color:e.fillColor,fill_opacity:wr(e.fillOpacity,.25)}}function Tr(e,t){return{color:e.color,opacity:wr(e.opacity),width_cm:Math.max(.1,Math.min(100,Number(e.widthCm)||.1)),...t?{fill:e.fill,fill_color:e.fillColor,fill_opacity:wr(e.fillOpacity,.25)}:{}}}function Dr(e){const t=e.x+e.w/2,i=e.y+e.h/2,n=kr(e.angle)*Math.PI/180,r=Math.cos(n),o=Math.sin(n),s=(e,n)=>{const s=e-t,a=n-i;return[t+s*r-a*o,i+s*o+a*r]};return[s(e.x,e.y),s(e.x+e.w,e.y),s(e.x+e.w,e.y+e.h),s(e.x,e.y+e.h)]}function Ar(e){const t=Dr(e),i=(e,t)=>[(e[0]+t[0])/2,(e[1]+t[1])/2],n=[(t[0][0]+t[2][0])/2,(t[0][1]+t[2][1])/2];return{points:[...t,i(t[0],t[1]),i(t[1],t[2]),i(t[2],t[3]),i(t[3],t[0]),n],segments:t.map((e,i)=>({a:e,b:t[(i+1)%4]}))}}function Pr(e,t,i,n,r,o,s,a){const l=kr(e.angle)*Math.PI/180,c=Math.cos(l),h=Math.sin(l),d=-Math.sin(l),u=Math.cos(l),p=e.x+e.w/2,_=e.y+e.h/2,m=t>0?-e.w/2:e.w/2,g=i>0?-e.h/2:e.h/2,f=p+m*c+g*d,v=_+m*h+g*u,y=n-f,b=r-v;let w=(y*c+b*h)*(t>0?1:-1),k=(y*d+b*u)*(i>0?1:-1),x=null;if(o){const t=w/Math.max(e.w,a),i=k/Math.max(e.h,a);x=Math.max(a/Math.max(e.w,a),a/Math.max(e.h,a),t,i),w=e.w*x,k=e.h*x}if(s>0)if(o){const t=Math.max(1,Math.round(e.w/s)),i=Math.max(1,Math.round(e.h/s));if(Math.abs(e.w-t*s)<1e-6&&Math.abs(e.h-i*s)<1e-6){const n=(e,t)=>{let i=Math.abs(e),n=Math.abs(t);for(;n;)[i,n]=[n,i%n];return Math.max(1,i)},r=1/n(t,i),o=Math.max(a/e.w,a/e.h),s=Math.max(o,Math.round((x??1)/r)*r);w=e.w*s,k=e.h*s}else{e.w>=e.h?(w=Math.round(w/s)*s,k=w*(e.h/Math.max(e.w,a))):(k=Math.round(k/s)*s,w=k*(e.w/Math.max(e.h,a)))}}else w=Math.round(w/s)*s,k=Math.round(k/s)*s;w=Math.max(a,w),k=Math.max(a,k);return{x:f+(t>0?w/2:-w/2)*c+(i>0?k/2:-k/2)*d-w/2,y:v+(t>0?w/2:-w/2)*h+(i>0?k/2:-k/2)*u-k/2,w:w,h:k,angle:kr(e.angle)||void 0}}const Fr=(e,t,i)=>{const n=i[0]-t[0],r=i[1]-t[1],o=n*n+r*r;if(o<1e-12)return[...t];const s=Math.max(0,Math.min(1,((e[0]-t[0])*n+(e[1]-t[1])*r)/o));return[t[0]+n*s,t[1]+r*s]};function zr(e,t,i,n){const r=n(e);let o=null;for(const r of t.points){const t=n(r),s=Math.hypot(t[0]-e[0],t[1]-e[1]);s<=i&&(!o||se.points),segments:e.flatMap(e=>e.segments)}}const Or=Math.tan(.25*Math.PI/180);function Er(e,t){const i=Math.abs(Number(t[0])-Number(e[0])),n=Math.abs(Number(t[1])-Number(e[1]));if(!([i,n].every(Number.isFinite)&&i>0&&n>0))return null;const r=i>=n?"horizontal":"vertical",o=Math.max(i,n),s=Math.min(i,n);return s/o>Or?null:{axis:r,major:o,minor:s,angleDegrees:180*Math.atan2(s,o)/Math.PI}}function Nr(e,t){const i=Er(e,t);return i?"horizontal"===i.axis?[Number(t[0]),Number(e[1])]:[Number(e[0]),Number(t[1])]:[Number(t[0]),Number(t[1])]}const Hr=e=>`${e[0]},${e[1]}`,Lr=(e,t)=>e[0]===t[0]&&e[1]===t[1],Br=(e,t)=>{const i=Hr(e),n=Hr(t);return i{let t=0;for(let i=0;i{if(e.length<3)return!1;for(let t=0;t1e-12},Wr=(e,t)=>Lr(e,t.from)?[...t.to]:[...e],Ur=(e,t)=>e.map(e=>Array.isArray(e?.poly)?{...e,poly:e.poly.map(e=>Wr(e,t))}:e),Vr=(e,t,i)=>{const n=e.flatMap((e,t)=>ei(e)?.some(e=>Lr(e,i.from))?[t]:[]);if(!n.length)return!1;for(const i of n){const n=ei(e[i]),r=ei(t[i]);if(!n||!r)continue;if(!jr(r))return!1;const o=Math.sign(qr(n)),s=Math.sign(qr(r));if(o&&s&&o!==s)return!1}const r=new Set;for(const e of n){const i=ei(t[e]);if(i)for(let n=0;n{let i=0;for(const n of e){const e=ei(n);if(e)for(let n=0;n{const{a:i,b:n,axis:r}=e,o="horizontal"===r?{from:n,to:[n[0],i[1]]}:{from:n,to:[i[0],n[1]]},s="horizontal"===r?{from:i,to:[i[0],n[1]]}:{from:i,to:[n[0],i[1]]};return[{move:o,preservedDegree:Gr(t,i)},{move:s,preservedDegree:Gr(t,n)}].sort((e,t)=>t.preservedDegree-e.preservedDegree||Hr(e.move.to).localeCompare(Hr(t.move.to))||Hr(e.move.from).localeCompare(Hr(t.move.from))).map(e=>e.move)};function Yr(e){const t=JSON.parse(JSON.stringify(e||{}));let i=Array.isArray(t.rooms)?t.rooms:[];const n=new Map;for(const e of i){const t=ei(e);if(t)for(let e=0;ee.key.localeCompare(t.key))){let t=null;for(const n of Kr(e,i)){const e=a.get(Hr(n.from));if(e&&e!==Hr(n.to))continue;const r=Ur(i,n);if(Vr(i,r,n)){t=n,i=r;break}}t?(a.set(Hr(t.from),Hr(t.to)),r++,s=Math.max(s,Math.hypot(t.to[0]-t.from[0],t.to[1]-t.from[1]))):o++}t.rooms=i;for(const e of t.partitions||[]){if(!Array.isArray(e?.a)||!Array.isArray(e?.b))continue;const i=Er(e.a,e.b);if(!i)continue;const n={key:String(e.id||Br(e.a,e.b)),a:[...e.a],b:[...e.b],axis:i.axis};let a=null;for(const i of Kr(n,[{poly:[e.a,e.b]}])){const n=Wr(e.a,i),r=Wr(e.b,i),o=Math.hypot(r[0]-n[0],r[1]-n[1]);if(!(o>0))continue;const s=(t.openings||[]).filter(t=>"partition"===t?.host?.kind&&t.host.id===e.id).every(e=>{const t=Number(e.host.t),i=Number(e.length);return Number.isFinite(t)&&t>=0&&t<=1&&Number.isFinite(i)&&i>0&&t*o-i/2>=-1e-12&&t*o+i/2<=o+1e-12});if(s){a=i,e.a=n,e.b=r;break}}a?(r++,s=Math.max(s,Math.hypot(a.to[0]-a.from[0],a.to[1]-a.from[1]))):o++}return{space:t,report:{wallsStraightened:r,wallsStraightenSkipped:o,maxStraightenShift:s},changed:r>0}}const Xr=["rect","ellipse","furniture","image"],Zr=10**9,Jr=240,Qr=1e-4;function eo(e){if(Array.isArray(e))return e.map(e=>eo(e));if(null!==e&&"object"==typeof e){const t={};for(const[i,n]of Object.entries(e))t[i]=eo(n);return t}return e}function to(e){if("number"!=typeof e||!Number.isFinite(e))return e;const t=(e<0||Object.is(e,-0)?-1:1)*(Math.floor(Math.abs(e)*Zr+.5)/Zr);return 0===t?0:t}function io(e){if("number"!=typeof e||!Number.isFinite(e))return e;const t=e*Jr,i=Math.round(t);if(Math.abs(t-i)null!==ro(e)):[]}function so(e){return"string"==typeof e&&Xr.includes(e)}function ao(e,t){for(const i of t)Object.prototype.hasOwnProperty.call(e,i)&&(e[i]=to(e[i]))}function lo(e,t){for(const i of t)Object.prototype.hasOwnProperty.call(e,i)&&(e[i]=io(e[i]))}function co(e){if(Array.isArray(e))for(let t=0;t{for(const r of n){const n=t[r];"number"==typeof n&&Number.isFinite(n)&&i(n,e)}},n=t=>{if(Array.isArray(t))for(let n=0;n{if(Array.isArray(e))for(const t of e)n(t)};for(const i of oo(e.rooms))t(i,["x","y","w","h"]),r(i.poly);for(const t of oo(e.walls))n(t.a),n(t.b);for(const t of oo(e.wall_segments))n(t.a),n(t.b);for(const i of oo(e.openings))t(i,["x","y"]);for(const i of oo(e.decor))"line"===i.kind?t(i,["x1","y1","x2","y2"]):so(i.kind)?t(i,["x","y","w","h"]):"text"===i.kind&&t(i,["x","y"]);for(const t of oo(e.room_drafts))r(t.points);for(const t of oo(e.partitions))n(t.a),n(t.b);for(const t of oo(e.wall_columns))n(t.center);for(const t of oo(e.open_spans))n(t.a),n(t.b)}const r=ro(t);if(!r)return;const o=new Map;if(n)for(const e of oo(n.spaces))null!=e.id&&o.set(String(e.id),e);for(const e of Object.values(r)){const t=ro(e);if(!t)continue;const n=null!=t.s&&o.get(String(t.s))||null;for(const e of["x","y"]){const r=t[e];"number"==typeof r&&Number.isFinite(r)&&i(r,n)}}}function po(e){const t=Number(e?.cell_cm);return t>0?t:5}function _o(e,t={}){const i={canonicalized:0,far:0,maxShift:0,maxShiftCm:0,spaces:[],bySpace:new Map},n=oo(ro(e)?.spaces);let r=5;for(const e of n)r=Math.max(r,po(e));uo(e,t,(e,t)=>{const n=e*Jr,o=Math.abs(n-Math.round(n)),s=io(e),a=o>0&&o=Qr))return;const l=a&&"number"==typeof s?Math.abs(s-e):0;if(a?i.canonicalized++:i.far++,i.maxShift=Math.max(i.maxShift,l),i.maxShiftCm=Math.max(i.maxShiftCm,l*Jr*(t?po(t):r)),!t?.id||!a)return;const c=String(t.id);let h=i.bySpace.get(c);h||(h={spaceId:c,space:String(t.title||c),canonicalized:0,far:0,maxShift:0,maxShiftCm:0},i.bySpace.set(c,h)),h.canonicalized++,h.maxShift=Math.max(h.maxShift,l),h.maxShiftCm=Math.max(h.maxShiftCm,l*Jr*po(t))}),i.bySpace.size&&uo(e,t,(e,t)=>{if(!t?.id)return;const n=i.bySpace.get(String(t.id));if(!n)return;const r=e*Jr;Math.abs(r-Math.round(r))>=Qr&&n.far++}),i.spaces=[...i.bySpace.values()];const{bySpace:o,...s}=i;return s}function mo(e){return function(e){const t=e,i=ro(t);i&&lo(i,["x","y"]);return t}(eo(e))}function go(e){const t=e,i=ro(t);if(!i)return t;for(const e of Object.values(i)){const t=ro(e);t&&lo(t,["x","y"])}return t}function fo(e){return vo(eo(e))}function vo(e){const t=e,i=ro(t);if(!i)return t;for(const e of oo(i.spaces)){ao(e,["plan_x","plan_y","plan_scale","plan_scale_x","plan_scale_y","plan_angle"]);for(const t of oo(e.rooms))lo(t,["x","y","w","h"]),ho(t.poly);for(const t of oo(e.walls))co(t.a),co(t.b);for(const t of oo(e.wall_segments))co(t.a),co(t.b);for(const t of oo(e.openings)){lo(t,["x","y"]),ao(t,["angle","length"]);const e=ro(t.host);e&&ao(e,["t"])}for(const t of oo(e.decor))"line"===t.kind?lo(t,["x1","y1","x2","y2"]):so(t.kind)?(lo(t,["x","y","w","h"]),ao(t,["angle"])):"text"===t.kind&&(lo(t,["x","y"]),ao(t,["scale","angle"]));for(const t of oo(e.room_drafts))ho(t.points);for(const t of oo(e.partitions))co(t.a),co(t.b);for(const t of oo(e.wall_columns))co(t.center),"square"===t.shape&&ao(t,["angle"]);for(const t of oo(e.open_spans))co(t.a),co(t.b)}for(const e of oo(i.markers))ao(e,["angle"]);return t}const yo=15,bo=8;function wo(e,t,i,n,r){const o=i[0]-e[0],s=i[1]-e[1],a=Math.hypot(o,s);if(!(a>0)||a<=r+1e-9)return null;const l=o/a,c=s/a,h=t=>{const n=(t[0]-e[0])*l+(t[1]-e[1])*c,o=(r-n)/(a-n);return!Number.isFinite(o)||o<-1e-9||o>1+1e-9?null:[t[0]+(i[0]-t[0])*o,t[1]+(i[1]-t[1])*o]},d=h(t),u=h(n);return d&&u?[[e[0],e[1]],t,d,u,n]:null}const ko=Math.sin(.25*Math.PI/180);function xo(e,t){return Number.isFinite(e)&&e>0&&Number.isFinite(t)&&t>0&&e*t<3}function So(e){const t=Number(e)>0?Number(e):5;if(5===t)return 8;const i=5/t*8;return Math.min(80,Math.max(.5,i))}function $o(e,t){return Number.isFinite(e)&&e>0&&Number.isFinite(t)&&t>0&&e*t<2}function Mo(e){return Number.isFinite(e)?Math.max(1,Math.min(100,e)):1}function Ro(e,t){return!Number.isFinite(e)||e<0?"":String(t?Math.round(e/2.54*100)/100:Math.round(100*e)/100)}function Co(e,t,i){if(!Number.isFinite(e)||e<=0)return 0;const n=Number(t)>0?Number(t):5;return Mo(e)/n*i}function To(e,t){return t>0&&Number.isFinite(e)?Math.round(e/t)*t:e}function Do(e){return Math.max(1e-6*Math.abs(e),1e-9)}function Ao(e,t){if(!(t>0&&Number.isFinite(e)))return e;const i=To(e,t);return Math.abs(i-e)<=Do(t)?i:e}function Po(e,t){let i=t[0]-e[0],n=t[1]-e[1];const r=Math.hypot(i,n);return r<1e-12?[1,0]:(i/=r,n/=r,(i<-1e-12||Math.abs(i)<=1e-12&&n<0)&&(i=-i,n=-n),[i,n])}function Fo(e,t,i){const n=[Ao(e[0],i),Ao(e[1],i)],r=[Ao(t[0],i),Ao(t[1],i)],o=To((n[0]+r[0])/2,i),s=To((n[1]+r[1])/2,i),[a,l]=Po(n,r);let c=Math.atan2(l,a);c<0&&(c+=Math.PI);const h=Math.round(1800*c)/1800,d=i>0&&i<.01?6:i<1?4:2;return`${o.toFixed(d)},${s.toFixed(d)}@${h.toFixed(4)}`}function zo(e,t,i,n){return 1===n?Fo(e,t,i):Fo([e[0]/n,e[1]/n],[t[0]/n,t[1]/n],i)}function Io(e,t){if(!Array.isArray(e.a)||!Array.isArray(e.b)||e.a.length<2||e.b.length<2)return null;const i=[Number(e.a[0]),Number(e.a[1]),Number(e.b[0]),Number(e.b[1])];if(!i.every(Number.isFinite))return null;const n=t>0?t:1;return[[i[0]*n,i[1]*n],[i[2]*n,i[3]*n]]}function Oo(e,t,i,n,r){const o=r>0?r:1;return{key:zo(e,t,n,o),cm:Mo(i),a:[e[0]/o,e[1]/o],b:[t[0]/o,t[1]/o]}}function Eo(e,t){const i=t>0?t:1,n=[];for(const t of e){const e=t.key.lastIndexOf("@");if(e<0)continue;const[r,o]=t.key.slice(0,e).split(",").map(Number),s=Number(t.key.slice(e+1));[r,o,s].every(Number.isFinite)&&n.push({w:t,x:r*i,y:o*i,ang:s})}return n}function No(e,t){const[i,n]=Po(e,t);let r=Math.atan2(n,i);return r<0&&(r+=Math.PI),r}function Ho(e,t){let i=Math.abs(e-t);return i>Math.PI/2&&(i=Math.PI-i),i<.02}function Lo(e,t,i,n,r=1){if(!e?.length)return null;const o=zo(t,i,n,r),s=e.find(e=>e.key===o);if(s)return s;const a=r>0?r:1,l=Do(n)*a,c=(e,t)=>Math.abs(e[0]-t[0])<=l&&Math.abs(e[1]-t[1])<=l;for(const n of e){const e=Io(n,a);if(e&&(c(e[0],t)&&c(e[1],i)||c(e[0],i)&&c(e[1],t)))return n}const h=(t[0]+i[0])/2,d=(t[1]+i[1])/2,u=No(t,i),p=Math.max(.5*n,1e-9)*a;for(const t of Eo(e,a))if(Ho(t.ang,u)&&Math.hypot(t.x-h,t.y-d)<=p)return t.w;return null}function Bo(e,t,i,n,r=1){const o=Lo(e,t,i,n,r);if(o&&o.cm>0)return Mo(o.cm);const s=function(e,t,i,n,r){if(!e?.length)return null;const o=r>0?r:1,s=Math.hypot(i[0]-t[0],i[1]-t[1]);if(s<1e-12)return null;const a=No(t,i),l=Math.max(.5*n,1e-9)*o;let c=null;for(const n of e){if(!(n.cm>0))continue;const e=Io(n,o);if(!e)continue;const r=Math.hypot(e[1][0]-e[0][0],e[1][1]-e[0][1]);if(r<1e-12||!Ho(No(e[0],e[1]),a))continue;if(Ds(t[0],t[1],e[0][0],e[0][1],e[1][0],e[1][1])>l||Ds(i[0],i[1],e[0][0],e[0][1],e[1][0],e[1][1])>l)continue;if(r+l(o.has(e.key)||(e=>{const t=Io(e,n);if(!t)return!1;const[i,o]=t,a=o[0]-i[0],c=o[1]-i[1],h=Math.hypot(a,c);if(h<=l)return!1;if(!s.some(e=>{const t=[e[0],e[1]],n=[e[2],e[3]];return Ho(No(i,o),No(t,n))&&Ds(i[0],i[1],t[0],t[1],n[0],n[1])<=l&&Ds(o[0],o[1],t[0],t[1],n[0],n[1])<=l}))return!1;const d=(r||[]).some(e=>{const t=[e[0],e[1]],n=[e[2],e[3]];if(!Ho(No(i,o),No(t,n)))return!1;const r=e=>Math.abs((e[0]-i[0])*c-(e[1]-i[1])*a)/h;if(r(t)>l||r(n)>l)return!1;const s=h*h,d=((t[0]-i[0])*a+(t[1]-i[1])*c)/s,u=((n[0]-i[0])*a+(n[1]-i[1])*c)/s;return Math.min(1,Math.max(d,u))-Math.max(0,Math.min(d,u))>l/h});return!d})(e))&&e.cm>=1&&e.cm<=100)}function jo(e,t,i,n=8){const[r,o]=Po(e,t);let s=Math.atan2(o,r);s<0&&(s+=Math.PI);let a=i*Math.PI/180%Math.PI;a<0&&(a+=Math.PI);let l=Math.abs(s-a);return l>Math.PI/2&&(l=Math.PI-l),l<=n*Math.PI/180}function Wo(e,t,i,n,r=1,o="affine",s){if(!e?.length)return[];if(t.length!==i.length)return"fixed-topology"===o&&s?.(),e.slice();const a=r>0?r:1,l=Math.max(.5*n,1e-9)*a,c=Math.max(n*a*1e-6,1e-9),h=[],d=new Map,u=new Map,p=(e,t,i)=>{const n=e.get(t)||new Set;n.add(i),e.set(t,n)};for(let e=0;e[e[0]+(t[0]-e[0])*i,e[1]+(t[1]-e[1])*i],m=(e,t)=>Math.hypot(e[0]-t[0],e[1]-t[1])<=c,g=(e,t)=>{if("fixed-topology"===o){const i=t.na[0]-t.oa[0],n=t.na[1]-t.oa[1],r=t.nb[0]-t.ob[0],o=t.nb[1]-t.ob[1];return Math.hypot(i-r,n-o)<=c?[e[0]+i,e[1]+n]:m(e,t.oa)?[...t.na]:m(e,t.ob)?[...t.nb]:[...e]}const i=Math.max(0,Math.min(1,((e[0]-t.oa[0])*t.dx+(e[1]-t.oa[1])*t.dy)/t.len2));return _(t.na,t.nb,i)},f=(e,t)=>{const[i,n]=Po(e,t);return(t[0]-e[0])*i+(t[1]-e[1])*n>=0?[[...e],[...t]]:[[...t],[...e]]},v=[],y=[],b=(e,t,i)=>{if(Math.hypot(t[0]-e[0],t[1]-e[1])<=c)return;const[r,o]=f(e,t),s=Mo(i);if(y.some(e=>e.entry.cm===s&&m(e.span[0],r)&&m(e.span[1],o)))return;const l=Oo(r,o,s,n,a);v.push(l),y.push({entry:l,span:[r,o]})};for(const t of e){const e=Io(t,a);if(e){const[i,n]=f(e[0],e[1]),r=n[0]-i[0],s=n[1]-i[1],a=r*r+s*s,d=Math.sqrt(a);if(d<=c){v.push({...t,cm:Mo(t.cm)});continue}const u=[];for(const e of h){if(!Ho(No(i,n),No(e.oa,e.ob)))continue;const t=e=>Math.abs((e[0]-i[0])*s-(e[1]-i[1])*r)/d;if(t(e.oa)>l||t(e.ob)>l)continue;const o=((e.oa[0]-i[0])*r+(e.oa[1]-i[1])*s)/a,h=((e.ob[0]-i[0])*r+(e.ob[1]-i[1])*s)/a,p=Math.max(0,Math.min(o,h)),_=Math.min(1,Math.max(o,h));(_-p)*d>c&&u.push({lo:p,hi:_,move:e})}if(!u.length){"fixed-topology"===o?v.push({...t}):b(i,n,t.cm);continue}const p=[0,1,...u.flatMap(({lo:e,hi:t})=>[e,t])].sort((e,t)=>e-t).filter((e,t,i)=>0===t||Math.abs(e-i[t-1])*d>c),y=[];for(let e=0;e+1a>=e.lo-1e-12&&a<=e.hi+1e-12);if(!l.length){y.push([o,s]);continue}const h=[g(o,l[0].move),g(s,l[0].move)],f=l.slice(1).some(e=>{const t=g(o,e.move),i=g(s,e.move);return!m(h[0],t)||!m(h[1],i)});y.push(f?[o,s]:h)}const w=(e,t)=>{const i=e[1][0]-e[0][0],n=e[1][1]-e[0][1],r=t[1][0]-t[0][0],o=t[1][1]-t[0][1],s=Math.hypot(i,n);return!(s<=c||i*r+n*o<=0)&&Math.abs(i*o-n*r)/s<=c},k=[];for(const e of y){const t=k[k.length-1];t&&m(t[1],e[0])&&w(t,e)?t[1]=e[1]:k.push([[...e[0]],[...e[1]]])}if("fixed-topology"===o&&1===k.length){const[i,n]=k[0];if(m(i,e[0])&&m(n,e[1])||m(i,e[1])&&m(n,e[0])){v.push({...t});continue}}for(const[e,i]of k)b(e,i,t.cm);continue}if("fixed-topology"===o){const e=u.get(t.key);if(1===e?.size){const i=[...e][0];v.push(i===t.key?{...t}:{...t,key:i});continue}const i=[Eo([t],a)[0]];1!==a&&i.push(Eo([t],1)[0]);const n=i.filter(Boolean).some(e=>h.some(t=>{if(!Ho(e.ang,No(t.oa,t.ob)))return!1;const i=((e.x-t.oa[0])*t.dx+(e.y-t.oa[1])*t.dy)/t.len2;return i>=-1e-6&&i<=1.000001&&Ds(e.x,e.y,t.oa[0],t.oa[1],t.ob[0],t.ob[1])<=l}));((e?.size||0)>1||n)&&s?.(),v.push({...t});continue}let i="";const r=d.get(t.key);if(1===r?.size&&(i=[...r][0]),!i){const e=Eo([t],a)[0];if(e){const t=new Set;for(const i of h){if(!Ho(e.ang,No(i.oa,i.ob)))continue;const r=((e.x-i.oa[0])*i.dx+(e.y-i.oa[1])*i.dy)/i.len2;if(r<-1e-6||r>1.000001)continue;if(Ds(e.x,e.y,i.oa[0],i.oa[1],i.ob[0],i.ob[1])>l)continue;const o=g([e.x,e.y],i),[s,c]=Po(i.na,i.nb),h=Math.max(n*a,1e-6);t.add(zo([o[0]-s*h,o[1]-c*h],[o[0]+s*h,o[1]+c*h],n,a))}1===t.size&&(i=[...t][0])}}v.push({...t,key:i||t.key,cm:Mo(t.cm)})}return v}function Uo(e,t,i,n,r=1,o="affine"){return Wo(e,t,i,n,r,o)}function Vo(e,t,i,n,r=1,o="fixed-topology"){let s=!1;const a=Wo(e,t,i,n,r,o,()=>{s=!0});return{walls:s?(e||[]).map(e=>({...e})):a,rejected:s}}function Go(e,t,i,n=1,r=[]){const o=n>0?n:1,s=Math.abs(i),a=Math.max(s*o*Qr,1e-9),l=(r||[]).flatMap(e=>{const t=Io(e,o);return t?t.map(e=>[...e]):[]}),c=e=>e.every((e,t)=>(e=>{if(!(s>0))return!0;const t=e/o/s;return Math.abs(t-Math.round(t))Math.abs(e-i[t])<=a)),h=[],d=e=>JSON.stringify([e.key,e.cm,e.a,e.b]);for(const i of e||[]){const e=Io(i,o);if(!e)continue;const[n,r]=e;if(![n[0],n[1],r[0],r[1]].every(Number.isFinite)||!c(n)||!c(r)){h.push(d(i));continue}const s=r[0]-n[0],l=r[1]-n[1],u=Math.hypot(s,l);if(u<=a){h.push(d(i));continue}const p=s/u,_=l/u,m=[];for(const e of t){const[t,i]=e;if(![t?.[0],t?.[1],i?.[0],i?.[1]].every(Number.isFinite))continue;const r=e=>Math.abs((e[0]-n[0])*_-(e[1]-n[1])*p);if(r(t)>a||r(i)>a)continue;const o=(t[0]-n[0])*p+(t[1]-n[1])*_,s=(i[0]-n[0])*p+(i[1]-n[1])*_,l=Math.max(0,Math.min(o,s)),c=Math.min(u,Math.max(o,s));c-l>a&&m.push([l,c])}m.sort((e,t)=>e[0]-t[0]||e[1]-t[1]);let g=0;for(const[e,t]of m){if(e>g+a)break;if(g=Math.max(g,t),g>=u-a)break}ge.key!==s);return null==n||n<1?a:[...a,Oo(t,i,n,r,o)]}function Yo(e,t,i,n,r,o=[],s=1){let a=e?e.slice():[];for(const e of function(e,t,i,n,r=1,o=[]){const s=gs(e,t,i,n,r,o);if(!s)return[];const a=[];for(let e=0;e0||(c=Ko(c,t,i,n,r,s)))}return c}function Zo(e){const{a:t,b:i,halfDepth:n}=e;if(!Array.isArray(t)||!Array.isArray(i)||t.length<2||i.length<2||![t[0],t[1],i[0],i[1]].every(Number.isFinite))return null;const r=i[0]-t[0],o=i[1]-t[1],s=Math.hypot(r,o);if(!(s>1e-9&&n>0&&Number.isFinite(n)))return null;const a=-o/s*n,l=r/s*n;return[[t[0]+a,t[1]+l],[i[0]+a,i[1]+l],[i[0]-a,i[1]-l],[t[0]-a,t[1]-l]]}function Jo(e,t,i){return Math.hypot(e[0]-t[0],e[1]-t[1])<=i}function Qo(e,t,i){const n=t.b[0]-t.a[0],r=t.b[1]-t.a[1],o=n*n+r*r;if(!(o>i*i))return!1;const s=((e[0]-t.a[0])*n+(e[1]-t.a[1])*r)/o;if(!(s>0&&s<1))return!1;const a=[t.a[0]+n*s,t.a[1]+r*s];return Math.hypot(e[0]-a[0],e[1]-a[1])<=i}function es(e,t,i,n){const r=Math.hypot(t,i);if(!(r>1e-9&&n>0))return;const o=[t/r,i/r],s=e.find(e=>Math.abs(e.u[0]*o[1]-e.u[1]*o[0])<1e-9&&e.u[0]*o[0]+e.u[1]*o[1]>1-1e-9);s?s.halfDepth=Math.max(s.halfDepth,n):e.push({u:o,halfDepth:n})}function ts(e,t){try{const i=jt(Fs(e),Fs(t));let n=null,r=0;for(const e of i||[]){const t=e?.[0]||[],i=Math.abs(as(t));t.length>=4&&i>r&&(r=i,n=t.slice(0,-1).map(e=>[e[0],e[1]]))}return n}catch{return null}}function is(e,t=1e-6){const i=(e||[]).map((e,t)=>({segment:e,index:t})).filter(({segment:e})=>e&&Array.isArray(e.a)&&Array.isArray(e.b)&&e.a.length>=2&&e.b.length>=2&&e.a.every(Number.isFinite)&&e.b.every(Number.isFinite)&&Number.isFinite(e.halfDepth)&&e.halfDepth>0&&Math.hypot(e.b[0]-e.a[0],e.b[1]-e.a[1])>1e-9);if(i.length<2)return[];const n=Math.max(Number.isFinite(t)?t:0,1e-9),r=i.flatMap(({segment:e})=>[e.a,e.b]).map(e=>[e[0],e[1]]).sort((e,t)=>e[0]-t[0]||e[1]-t[1]),o=[];for(const e of r)o.some(t=>Jo(t,e,n))||o.push(e);const s=[];for(const e of o){const t=[];let r=!1;for(const{segment:o,index:s}of i){const i=Math.hypot(o.b[0]-o.a[0],o.b[1]-o.a[1]);Jo(e,o.a,n)?t.push({u:[(o.b[0]-o.a[0])/i,(o.b[1]-o.a[1])/i],halfDepth:o.halfDepth,length:i,index:s}):Jo(e,o.b,n)?t.push({u:[(o.a[0]-o.b[0])/i,(o.a[1]-o.b[1])/i],halfDepth:o.halfDepth,length:i,index:s}):Qo(e,o,n)&&(r=!0)}if(r||2!==t.length)continue;const[o,a]=t,l=o.u[0]*a.u[1]-o.u[1]*a.u[0];if(Math.abs(l)<1e-9)continue;const c=l<0?1:-1,h=[-o.u[1],o.u[0]],d=[-a.u[1],a.u[0]],u=[e[0]+h[0]*o.halfDepth*c,e[1]+h[1]*o.halfDepth*c],p=[e[0]-d[0]*a.halfDepth*c,e[1]-d[1]*a.halfDepth*c];if(!hs(u,o.u,p,a.u))continue;const _=[[o,a,p,[d[0]*-c,d[1]*-c]],[a,o,u,[h[0]*c,h[1]*c]]];for(const[t,,i,r]of _){const o=Math.min(2*t.halfDepth,t.length),a=[-t.u[1]*t.halfDepth,t.u[0]*t.halfDepth],l=[[e[0]+a[0],e[1]+a[1]],[e[0]+t.u[0]*o+a[0],e[1]+t.u[1]*o+a[1]],[e[0]+t.u[0]*o-a[0],e[1]+t.u[1]*o-a[1]],[e[0]-a[0],e[1]-a[1]]],c=e=>(e[0]-i[0])*r[0]+(e[1]-i[1])*r[1],h=[];for(let e=0;e=-1e-12&&h.push(t),n>1e-12&&r<-1e-12||n<-1e-12&&r>1e-12){const e=n/(n-r);h.push([t[0]+(i[0]-t[0])*e,t[1]+(i[1]-t[1])*e])}}h.length>=3&&Math.abs(as(h))>n*n&&s.push({segmentIndex:t.index,wedge:h})}}return s}function ns(e,t=1e-6){const i=(e||[]).filter(e=>e&&Array.isArray(e.a)&&Array.isArray(e.b)&&e.a.length>=2&&e.b.length>=2&&e.a.every(Number.isFinite)&&e.b.every(Number.isFinite)&&Number.isFinite(e.halfDepth)&&e.halfDepth>0&&Math.hypot(e.b[0]-e.a[0],e.b[1]-e.a[1])>1e-9);if(i.length<2)return[];const n=Math.max(Number.isFinite(t)?t:0,1e-9),r=i.flatMap(e=>[e.a,e.b]).map(e=>[e[0],e[1]]).sort((e,t)=>e[0]-t[0]||e[1]-t[1]),o=[];for(const e of r)o.some(t=>Jo(t,e,n))||o.push(e);const s=[],a=i.map((e,t)=>({roomId:"",a:[e.a[0],e.a[1]],b:[e.b[0],e.b[1]],key:`join-${t}`,kind:"outer",cm:0,open:!1,half:e.halfDepth})),l=ws(a,n);for(const e of ks(l).fans)s.push(e);const c=e=>!!xs(l,e);for(const e of o){if(c(e))continue;const t=[];for(const r of i)Jo(e,r.a,n)?es(t,r.b[0]-r.a[0],r.b[1]-r.a[1],r.halfDepth):Jo(e,r.b,n)?es(t,r.a[0]-r.b[0],r.a[1]-r.b[1],r.halfDepth):Qo(e,r,n)&&(es(t,r.a[0]-e[0],r.a[1]-e[1],r.halfDepth),es(t,r.b[0]-e[0],r.b[1]-e[1],r.halfDepth));if(!(t.length<2)){t.sort((e,t)=>Math.atan2(e.u[1],e.u[0])-Math.atan2(t.u[1],t.u[0])||e.halfDepth-t.halfDepth);for(let i=0;in*n&&s.push(m)}}}return s}function rs(e,t,i,n){if(!(t>0)||!e||e.length<2)return"";if(i&&e.length>=3){let i=e;const r=e[e.length-1];if(e.length>=4&&Math.hypot(e[0][0]-r[0],e[0][1]-r[1])<1e-9&&(i=e.slice(0,-1)),i.length>=3){const e=i.map((e,i)=>n?.[i]||t),r=Qs(i,e),o=ps(i,e);if(r&&o)return`${_s(r)} ${_s(ms(o))}`}}const r=[];for(let i=0;i=1e-9&&a>0&&r.push({a:o,b:s,halfDepth:a})}const o=r.map(Zo);for(const{segmentIndex:e,wedge:t}of is(r)){const i=o[e];if(!i)continue;const n=ts(i,t);n&&(o[e]=n)}const s=[...o.filter(e=>!!e),...ns(r)],a=function(e){let t=null;try{for(const i of e){if(i.length<3)continue;const e=Fs(i);t=t?Bt(t,e):[e]}return t}catch{return null}}(s);return a?Us(a):s.map(e=>_s(e)).join(" ")}function os(e,t,i,n,r=1){if(!i.length)return!1;const o=ss(n,r),s=(e[0]+t[0])/2,a=(e[1]+t[1])/2,[l,c]=Po(e,t);for(const e of i){const[t,i]=Po([e[0],e[1]],[e[2],e[3]]);if(!(Math.abs(l*i-c*t)>.05)&&Ds(s,a,e[0],e[1],e[2],e[3])<=o)return!0}return!1}function ss(e,t){return Math.max(e*(t>0?t:1)*.04,1e-9)}function as(e){let t=0;for(let i=0;ie[1]!=l>e[1]&&e[0]<(a-o)*(e[1]-s)/(l-s+0)+o&&(i=!i)}return i}([c[0]+.001*a,c[1]+.001*l],e)||(a=-a,l=-l),[a,l]}function cs(e,t){const i=e[0]*t[1]-e[1]*t[0],n=e[0]*t[0]+e[1]*t[1];return Math.abs(i)<1e-9&&n>0}function hs(e,t,i,n){const r=t[0]*n[1]-t[1]*n[0];if(Math.abs(r)<1e-12)return null;const o=[i[0]-e[0],i[1]-e[1]],s=(o[0]*n[1]-o[1]*n[0])/r;return[e[0]+s*t[0],e[1]+s*t[1]]}function ds(e,t,i){const n=e?.length||0;if(n<3||!Array.isArray(i)||i.length!==n)return 0;const r=(Math.trunc(t)%n+n)%n,o=e[r],s=e[(r+1)%n],a=s[0]-o[0],l=s[1]-o[1],c=Math.hypot(a,l);if(!(c>0))return 0;const h=Math.max(0,Number(i[r])||0);if(!(h>0))return c;const d=[a/c,l/c],u=ls(e,r),p=[o[0]+u[0]*h,o[1]+u[1]*h],_=t=>{const r=Math.max(0,Number(i[t])||0);if(!(r>0))return null;const s=e[t],a=e[(t+1)%n],l=a[0]-s[0],c=a[1]-s[1],h=Math.hypot(l,c);if(!(h>0))return null;const u=ls(e,t),_=hs(p,d,[s[0]+u[0]*r,s[1]+u[1]*r],[l/h,c/h]);return _?(_[0]-o[0])*d[0]+(_[1]-o[1])*d[1]:null},m=_((r-1+n)%n)??0,g=(_((r+1)%n)??c)-m;return g>0?g:0}function us(e,t,i,n,r,o,s,a=1){const l=(e||[]).find(e=>e?.id===t),c=ei(l);if(!c||c.length<3)return null;const h=$s(e,t,i,n,r,o,s,a);if(!h)return c.map(()=>0);const d=4*ss(r,a);return c.map((e,t)=>{const i=c[(t+1)%c.length],n=[(e[0]+i[0])/2,(e[1]+i[1])/2];for(let e=0;e!(e>0)))return e.map(e=>[e[0],e[1]]);const r=[];for(let o=0;o0||u>0)){r.push([e[o][0],e[o][1]]);continue}if(d>0!=u>0){const t=e[o],i=d>0?[t[0]+p*d,t[1]+_*d]:[t[0],t[1]],n=u>0?[t[0]+m*u,t[1]+g*u]:[t[0],t[1]];r.push(i),Math.hypot(n[0]-i[0],n[1]-i[1])>1e-9&&r.push(n);continue}if(cs(w,k)){const t=e[o],i=[t[0]+p*d,t[1]+_*d],n=[t[0]+m*u,t[1]+g*u];r.push(i),Math.hypot(n[0]-i[0],n[1]-i[1])>1e-9&&r.push(n);continue}const $=hs(x,w,S,k),M=Math.max(d,u,1e-9),R=xs(i,e[o])?.limit??4*M;if($){const i=Math.hypot($[0]-e[o][0],$[1]-e[o][1]);if(Number.isFinite(i)&&i<=R){r.push($);continue}if(Gs(e,t,o)){r.push($);continue}}d>0&&r.push([e[o][0]+p*d,e[o][1]+_*d]),u>0&&r.push([e[o][0]+m*u,e[o][1]+g*u]),d>0||u>0||r.push([e[o][0],e[o][1]])}return r.length>=3?r:null}function _s(e,t=!0){if(!e.length)return"";let i=`M ${e[0][0]} ${e[0][1]}`;for(let t=1;te?.id===t),a=ei(s);if(!a||a.length<3)return null;const l=ss(n,r),c=[];for(const i of e||[]){if(!i||i.id===t)continue;const e=ei(i);if(e)for(const t of Cn(a,e,l))c.push([t[0],t[1]],[t[2],t[3]])}for(const e of i||[])c.push([e[0],e[1]],[e[2],e[3]]);for(const e of o||[]){const t=Io(e,r);t&&c.push(t[0],t[1])}const h=[],d=[];for(let e=0;el)continue;const s=((e[0]-t[0])*(i[0]-t[0])+(e[1]-t[1])*(i[1]-t[1]))/(n*n);s<=r||s>=1-r||(o.some(e=>Math.abs(e-s)*n<=2*l)||o.push(s))}o.sort((e,t)=>e-t);for(const n of o)h.push([t[0]+(i[0]-t[0])*n,t[1]+(i[1]-t[1])*n]),d.push(e)}return{poly:h,parent:d,orig:a}}function fs(e,t,i,n){const r=t.poly.length,o=new Array(r).fill(0);if(!e?.length)return o;const s=new Set,a=[];for(let l=0;l0?(o[l]=Mo(c.cm),s.add(c.key)):a.push(l)}if(!a.length)return o;const l=n>0?n:1,c=Math.max(.5*i,1e-9)*l,h=Eo(e,l).filter(e=>e.w.cm>0);for(let e=a.length-1;e>=0;e--){const i=a[e],n=t.poly[i],s=t.poly[(i+1)%r],d=No(n,s);let u=null;for(const e of h){const t=Io(e.w,l);if(!t||!Ho(No(t[0],t[1]),d))continue;if(Ds(n[0],n[1],t[0][0],t[0][1],t[1][0],t[1][1])>c||Ds(s[0],s[1],t[0][0],t[0][1],t[1][0],t[1][1])>c)continue;const i=Math.hypot(s[0]-n[0],s[1]-n[1]),r=Math.hypot(t[1][0]-t[0][0],t[1][1]-t[0][1]),o=Math.max(0,r-i);(!u||oc||Ds(r[0],r[1],t[0][0],t[0][1],t[1][0],t[1][1])>c)continue;i=!0,o=Math.max(0,Math.hypot(t[1][0]-t[0][0],t[1][1]-t[0][1])-_)}else{if(Ds(e.x,e.y,n[0],n[1],r[0],r[1])>c)continue;o=Math.hypot(e.x-d,e.y-u)}(!p||i&&!p.exact||i===p.exact&&o0?i:1,o=(e||[]).filter(e=>e&&!e.open&&null!==e.kind&&Number.isFinite(e.half)&&e.half>0&&Array.isArray(e.a)&&Array.isArray(e.b)&&e.a.length>=2&&e.b.length>=2&&[e.a[0],e.a[1],e.b[0],e.b[1]].every(Number.isFinite)&&Math.hypot(e.b[0]-e.a[0],e.b[1]-e.a[1])>n).sort((e,t)=>e.key.localeCompare(t.key)||e.a[0]-t.a[0]||e.a[1]-t.a[1]||e.b[0]-t.b[0]||e.b[1]-t.b[1]||e.half-t.half),s=new Map;for(const e of o){const t=s.get(e.key);t?e.half>t.half&&s.set(e.key,{...t,half:e.half}):s.set(e.key,e)}const a=[...s.values()].flatMap(e=>[{point:[e.a[0],e.a[1]],other:e.b,halfDepth:e.half,kind:e.kind,key:e.key},{point:[e.b[0],e.b[1]],other:e.a,halfDepth:e.half,kind:e.kind,key:e.key}]).sort((e,t)=>e.point[0]-t.point[0]||e.point[1]-t.point[1]||e.other[0]-t.other[0]||e.other[1]-t.other[1]||e.halfDepth-t.halfDepth),l=new Map;for(const e of a){const[t,i]=vs(e.point,n),r=ys(t,i),o=l.get(r)||[];o.push(e),l.set(r,o)}const c=[],h=new Map;for(const e of a){const t=bs(h,e.point,n).filter(t=>Math.hypot(t.point[0]-e.point[0],t.point[1]-e.point[1])<=n).sort((t,i)=>Math.hypot(t.point[0]-e.point[0],t.point[1]-e.point[1])-Math.hypot(i.point[0]-e.point[0],i.point[1]-e.point[1])||t.point[0]-i.point[0]||t.point[1]-i.point[1]);let i=t[0];if(!i){i={point:[...e.point],rays:[]},c.push(i);const[t,r]=vs(i.point,n),o=ys(t,r),s=h.get(o)||[];s.push(i),h.set(o,s)}const r=e.other[0]-e.point[0],o=e.other[1]-e.point[1],s=Math.hypot(r,o);if(!(s>n))continue;const a=[r/s,o/s];let l=Math.atan2(a[1],a[0]);l<0&&(l+=2*Math.PI),i.rays.push({u:a,halfDepth:e.halfDepth,length:s,angle:l})}const d=[],u=e=>{const t=1e-9*Math.max(1,r),i=e.filter(e=>Number.isFinite(e.halfDepth)&&e.halfDepth>0&&Number.isFinite(e.length)&&e.length>n);return i.filter((e,n)=>!i.some((i,r)=>r!==n&&i.halfDepth>=e.halfDepth-t&&i.length>=e.length-t&&(i.halfDepth>e.halfDepth+t||i.length>e.length+t||re.length-t.length||e.halfDepth-t.halfDepth).map(e=>({...e}))};for(const e of c){const t=e.rays.sort((e,t)=>e.angle-t.angle||e.length-t.length||e.halfDepth-t.halfDepth),i=[];for(const e of t){const t=i[i.length-1];t&&Math.abs(e.angle-t.angle)<=1e-9?t.supports.push({halfDepth:e.halfDepth,length:e.length}):i.push({u:[...e.u],angle:e.angle,supports:[{halfDepth:e.halfDepth,length:e.length}]})}if(i.length>1&&2*Math.PI-i[i.length-1].angle+i[0].angle<=1e-9){const e=i.pop();i[0].supports.push(...e.supports)}if(i.length<3)continue;const r=i.map(t=>{const i=u(t.supports),r=new Set,o=[];for(const s of i){const i=[e.point[0]+t.u[0]*s.length,e.point[1]+t.u[1]*s.length];for(const t of bs(l,i,n)){if("shared"!==t.kind||Math.hypot(t.point[0]-i[0],t.point[1]-i[1])>n)continue;const s=t.other[0]-t.point[0],a=t.other[1]-t.point[1],l=Math.hypot(s,a);if(!(l>n))continue;const c=s/l,h=a/l;if(Math.hypot(t.other[0]-e.point[0],t.other[1]-e.point[1])<=n)continue;const d=`${t.key}|${t.point[0]}|${t.point[1]}|${t.other[0]}|${t.other[1]}|${t.halfDepth}`;r.has(d)||(r.add(d),o.push({start:[t.point[0],t.point[1]],u:[c,h],length:l,halfDepth:t.halfDepth}))}}return o.sort((e,t)=>e.start[0]-t.start[0]||e.start[1]-t.start[1]||e.u[0]-t.u[0]||e.u[1]-t.u[1]||e.length-t.length||e.halfDepth-t.halfDepth),{u:[...t.u],halfDepth:Math.max(...i.map(e=>e.halfDepth)),length:Math.max(...i.map(e=>e.length)),supports:i,continuations:o}}).filter(e=>Number.isFinite(e.halfDepth)&&e.halfDepth>0&&Number.isFinite(e.length)&&e.length>n);if(r.length<3)continue;const o=Math.max(...r.map(e=>e.halfDepth));o>0&&Number.isFinite(o)&&d.push({point:[...e.point],rays:r,halfDepth:o,limit:1.25*o})}d.sort((e,t)=>e.point[0]-t.point[0]||e.point[1]-t.point[1]);const p=new Map;for(const e of d){const[t,i]=vs(e.point,n),r=ys(t,i),o=p.get(r)||[];o.push(e),p.set(r,o)}return{epsilon:n,coordinateScale:r,nodes:d,index:p}}function ks(e){const t={fans:[],supports:[]};if(!e?.nodes?.length)return t;const i=Math.max(e.epsilon,1e-9)**2;for(const n of e.nodes){const e=n.rays.filter(e=>Number.isFinite(e.halfDepth)&&e.halfDepth>0).map(e=>({...e,thickLength:Math.max(...e.supports.filter(t=>t.halfDepth>=e.halfDepth-1e-12).map(e=>e.length),0),angle:(()=>{const t=Math.atan2(e.u[1],e.u[0]);return t<0?t+2*Math.PI:t})()})).sort((e,t)=>e.angle-t.angle);if(e.length<2)continue;const r=n.point;for(const i of e)for(const e of i.supports){if(!(e.halfDepth>0&&e.length>0))continue;const n=-i.u[1]*e.halfDepth,o=i.u[0]*e.halfDepth,s=[r[0]+i.u[0]*e.length,r[1]+i.u[1]*e.length];t.supports.push([[r[0]+n,r[1]+o],[s[0]+n,s[1]+o],[s[0]-n,s[1]-o],[r[0]-n,r[1]-o]])}for(let n=0;n{const e=s.angle-o.angle;return e>0?e:e+2*Math.PI})();if(a<1e-9)continue;const l=a>Math.PI+1e-9,c=4*Math.max(o.halfDepth,s.halfDepth),h=[r[0]-o.u[1]*o.halfDepth,r[1]+o.u[0]*o.halfDepth],d=[r[0]+s.u[1]*s.halfDepth,r[1]-s.u[0]*s.halfDepth],u=o.u[0]*s.u[1]-o.u[1]*s.u[0],p=e=>{let t=Math.atan2(e[1]-r[1],e[0]-r[0])-o.angle;for(;t<0;)t+=2*Math.PI;return t<=a+1e-9};let _=null;if(Math.abs(u)>1e-9){const e=((d[0]-h[0])*s.u[1]-(d[1]-h[1])*s.u[0])/u,t=((d[0]-h[0])*o.u[1]-(d[1]-h[1])*o.u[0])/u,i=[h[0]+o.u[0]*e,h[1]+o.u[1]*e];(l?e<=1e-9&&t<=1e-9:e>1e-9&&e<=o.thickLength&&t<=s.thickLength)&&Math.hypot(i[0]-r[0],i[1]-r[1])<=c&&p(i)&&(_=i)}const m=e=>{Math.abs(as(e))>i&&t.fans.push(e)};if(_){const e=1.5*Math.max(o.halfDepth,s.halfDepth);m(wo([r[0],r[1]],h,_,d,e)??[[r[0],r[1]],h,_,d]);continue}if(l){m([[r[0],r[1]],h,d]);continue}const g=(e,t)=>Math.min(t,Math.sqrt(Math.max(c**2-e**2,0)),2*Math.max(o.halfDepth,s.halfDepth)),f=[h[0]+o.u[0]*g(o.halfDepth,o.thickLength),h[1]+o.u[1]*g(o.halfDepth,o.thickLength)],v=[d[0]+s.u[0]*g(s.halfDepth,s.thickLength),d[1]+s.u[1]*g(s.halfDepth,s.thickLength)];m([[r[0],r[1]],h,f,v,d])}}return t}function xs(e,t){return!e||!Array.isArray(t)||t.length<2||!t.slice(0,2).every(Number.isFinite)?null:bs(e.index,t,e.epsilon).filter(i=>Math.hypot(i.point[0]-t[0],i.point[1]-t[1])<=e.epsilon).sort((e,i)=>Math.hypot(e.point[0]-t[0],e.point[1]-t[1])-Math.hypot(i.point[0]-t[0],i.point[1]-t[1])||e.point[0]-i.point[0]||e.point[1]-i.point[1])[0]||null}function Ss(e,t,i,n,r,o,s){return ws(Ms(e,t,i,n,r,o,s),4*ss(n,s),s)}function $s(e,t,i,n,r,o,s,a=1){const l=gs(e,t,n,r,a,i);if(!l)return null;const c=function(e,t,i){const n=(e||[]).find(e=>e?.id===t),r=ei(n);if(!r)return[];const o=[];for(const n of e||[]){if(!n||n.id===t)continue;const e=ei(n);if(e)for(const t of Cn(r,e,i))o.push(t)}return o}(e,t,ss(r,a)),h=function(e,t,i,n,r){const o=ss(n,r),s=[];for(let a=0;aDs(h,d,e[0],e[1],e[2],e[3])<=o);s.push(u?"shared":"outer")}return s}(l.poly,c,n,r,a),d=fs(i,l,r,a),u=d.map((e,t)=>h[t]&&e>0?Co(e,o,s)/2:0);return{...l,kinds:h,cms:d,offsets:u}}function Ms(e,t,i,n,r,o,s=1){const a=[];for(const l of e||[]){if(!l?.id)continue;const c=$s(e,l.id,t,i,n,r,o,s);if(c)for(let e=0;e0&&(a=Ko(a,e.a,e.b,e.cm,n,s));return a}function Cs(e,t,i,n,r,o,s=1){if(!t?.length)return[];const a=Ms(e,t,i,n,r,o,s),l=new Map;for(const e of a){if(e.open||!e.kind||!e.roomId)continue;const t=l.get(e.key)||new Set;t.add(e.roomId),l.set(e.key,t)}const c=e=>{const t=[...l.get(e)||[]].sort();return 1!==t.length&&2!==t.length?`ambiguous:${e}`:`${1===t.length?"outer":"shared"}:${t.join("|")}`},h=[],d=new Set;for(const e of a)!e.open&&e.cm>0&&!d.has(e.key)&&(d.add(e.key),h.push({...e,ownerSignature:c(e.key)}));const u=[];for(const a of e||[]){if(!a?.id)continue;const l=$s(e,a.id,t,i,n,r,o,s);if(l)for(let e=0;e0)||null===l.kinds[i]){e++;continue}const o=c(zo(l.poly[i],l.poly[(i+1)%l.poly.length],n,s));let a=e;for(;a+10&&u.push({a:[d[0],d[1]],b:[p[0],p[1]],key:zo(d,p,n,s),cm:r,len:_,ownerSignature:o}),e=a+1}}}u.sort((e,t)=>t.len-e.len||e.key.localeCompare(t.key));const p=[],_=new Set,m=new Set,g=4*ss(n,s);for(const e of u){const t=h.filter(t=>!m.has(t.key)&&t.cm===e.cm&&t.ownerSignature===e.ownerSignature&&Ho(No(t.a,t.b),No(e.a,e.b))&&Ds(t.a[0],t.a[1],e.a[0],e.a[1],e.b[0],e.b[1])<=g&&Ds(t.b[0],t.b[1],e.a[0],e.a[1],e.b[0],e.b[1])<=g);if(t.length){for(const e of t)m.add(e.key);_.has(e.key)||(_.add(e.key),p.push(Oo(e.a,e.b,e.cm,n,s)))}}for(const e of h)m.has(e.key)||_.has(e.key)||(_.add(e.key),p.push(Oo(e.a,e.b,e.cm,n,s)));return p}function Ts(e,t,i,n,r,o,s,a=1){const l=ss(r,a),c=(n[0]+n[2])/2,h=(n[1]+n[3])/2,d=No([n[0],n[1]],[n[2],n[3]]);let u=null;for(const n of Ms(e,t,i,r,o,s,a)){if(!Ho(No(n.a,n.b),d))continue;const e=Ds(c,h,n.a[0],n.a[1],n.b[0],n.b[1]);e>4*l||(!u||e[e[0],e[1]]),o=Math.abs(as(r));r.length>=3&&o>i&&(t=r,i=o)}return t}function Ps(e,t,i,n,r,o,s,a=1,l,c){const h=(e||[]).find(e=>e?.id===t),d=ei(h);if(!d||d.length<3)return null;if(!i?.length)return d.map(e=>[e[0],e[1]]);const u=$s(e,t,i,n,r,o,s,a);if(!u||!u.offsets.some(e=>e>0))return d.map(e=>[e[0],e[1]]);const p=c||Ss(e,i,n,r,o,s,a),_=ps(u.poly,u.offsets,p);if(!_)return d.map(e=>[e[0],e[1]]);if(!p.nodes.length)return _;const m=void 0===l?Ks(e,i,n,[],r,o,s,a):null,g=l??("ok"===m?.status||"degraded-extra"===m?.status?m.roomGeom:void 0);if(g)try{const e=As(jt(Fs(u.poly),g));if(e)return e}catch{}return function(e,t){try{return As(qt(Fs(e),Fs(t)))}catch{return null}}(_,u.poly)||d.map(e=>[e[0],e[1]])}function Fs(e){const t=e.map(e=>[e[0],e[1]]);return t.push([e[0][0],e[0][1]]),[t]}function zs(e){return!(!Array.isArray(e)||!e.length)&&e.every(e=>Array.isArray(e)&&e.length&&e.every(e=>Array.isArray(e)&&e.length>=4&&e.every(e=>Array.isArray(e)&&e.length>=2&&Number.isFinite(e[0])&&Number.isFinite(e[1])))&&Math.abs($i(e[0]))>1e-9)}function Is(e,t,i,n){const r=n?new Set(n):null;let o=null;for(let n=0;nt.epsilon))continue;const l=Ls([[e.point[0]+a[0]*n.halfDepth,e.point[1]+a[1]*n.halfDepth],[e.point[0]+s.u[0]*r+a[0]*n.halfDepth,e.point[1]+s.u[1]*r+a[1]*n.halfDepth],[e.point[0]+s.u[0]*r-a[0]*n.halfDepth,e.point[1]+s.u[1]*r-a[1]*n.halfDepth],[e.point[0]-a[0]*n.halfDepth,e.point[1]-a[1]*n.halfDepth]],t.coordinateScale);if(!l)continue;const c=Fs(l);o=o?Bt(o,c):c}}return o}function Os(e,t,i){let n=null;for(const r of e.rays)for(const e of r.continuations){const r=[-e.u[1],e.u[0]],o=[e.start[0]+e.u[0]*e.length,e.start[1]+e.u[1]*e.length],s=Ls([[e.start[0]+r[0]*e.halfDepth,e.start[1]+r[1]*e.halfDepth],[o[0]+r[0]*e.halfDepth,o[1]+r[1]*e.halfDepth],[o[0]-r[0]*e.halfDepth,o[1]-r[1]*e.halfDepth],[e.start[0]-r[0]*e.halfDepth,e.start[1]-r[1]*e.halfDepth]],t.coordinateScale);if(!s)continue;const a=qt(Fs(s),i);Array.isArray(a)&&0!==a.length&&(n=n?Bt(n,a):a)}return n}function Es(e,t,i=2*(4*e.halfDepth+2*t.epsilon)){const n=function(e,t=ko){const i=new Set,n=Number.isFinite(t)&&t>=0?t:ko;for(let t=0;te-t)}(e);return n.length?Is(e,t,i,n):null}function Ns(e,t,i,n,r){const o=function(e){let t=null;for(const i of e){const e=Fs(i);try{t=t?Bt(t,e):e}catch{}}return t}(function(e,t,i=!1){if(!e)return[];const n=[];for(const r of e.nodes)for(let o=0;o1e-9)||h>=Math.PI-1e-9)continue;const d=[-s.u[1],s.u[0]],u=[-a.u[1],a.u[0]],p=[r.point[0]+d[0]*s.halfDepth,r.point[1]+d[1]*s.halfDepth],_=[r.point[0]-u[0]*a.halfDepth,r.point[1]-u[1]*a.halfDepth],m=hs(p,s.u,_,a.u);if(!m)continue;const g=Math.hypot(m[0]-r.point[0],m[1]-r.point[1]);if(!Number.isFinite(g)||g<=r.limit)continue;const f=t?Math.sqrt(Math.max(0,r.limit*r.limit-s.halfDepth*s.halfDepth)):0,v=t?Math.sqrt(Math.max(0,r.limit*r.limit-a.halfDepth*a.halfDepth)):0,y=Ls([[p[0]+s.u[0]*f,p[1]+s.u[1]*f],[_[0]+a.u[0]*v,_[1]+a.u[1]*v],m],e.coordinateScale);if(y&&n.push(y),i){const t=m[0]-r.point[0],i=m[1]-r.point[1],o=Math.hypot(t,i),s=g-r.limit;if(o>e.epsilon&&s>e.epsilon){const a=Math.min(Math.max(8*e.epsilon,.05*r.halfDepth),.25*s),l=t/o,c=i/o,h=-c,d=l,u=Ls([[m[0]-l*a+h*a,m[1]-c*a+d*a],[m[0]-l*a-h*a,m[1]-c*a-d*a],[m[0]+l*a,m[1]+c*a]],e.coordinateScale);u&&n.push(u)}}}return n}({...t,nodes:[e]},i,n));return o&&r?jt(o,r):o}function Hs(e,t,i,n){if(!e||!t.nodes.length)return e;let r=null;try{r=function(e){let t=null;for(const i of e.nodes){const n=Es(i,e);n&&(t=t?Bt(t,n):n)}return t}(t)}catch{return e}let o=e;for(const e of t.nodes){const s=4*e.halfDepth+2*t.epsilon,a=2*s,l=[[e.point[0]-s,e.point[1]-s],[e.point[0]+s,e.point[1]-s],[e.point[0]+s,e.point[1]+s],[e.point[0]-s,e.point[1]+s]];try{let s=o;const c=Ns(e,t,!1,!0,r);c&&(s=jt(s,c));let h=Is(e,t,a);const d=Ns(e,t,!0,!0,r);d&&(h=jt(h,d)),r&&(h=Bt(h,r));const u=.02*Math.min(...e.rays.map(e=>e.halfDepth));if(h=Bt(h,Fs([[e.point[0]-u,e.point[1]-u],[e.point[0]+u,e.point[1]-u],[e.point[0]+u,e.point[1]+u],[e.point[0]-u,e.point[1]+u]])),!h)continue;let p=qt(h,Fs(l));n?p=qt(p,n):i&&(p=qt(p,i));const _=Fs(l),m=jt(s,_),g=i?jt(qt(s,_),i):null,f=Os(e,t,_);o=Bt(m,...g?[g]:[],...f?[f]:[],p)}catch{}}if(r)try{let e=r;n?e=qt(e,n):i&&(e=qt(e,i)),o=Bt(o,e)}catch{}return o}function Ls(e,t=1){if(!Array.isArray(e)||e.length<3)return null;const i=Number.isFinite(t)&&t>0?t:1,n=1e-12*Math.max(1,i),r=[];for(const t of e){if(!Array.isArray(t)||t.length<2)return null;const e=Number(t[0]),i=Number(t[1]);if(!Number.isFinite(e)||!Number.isFinite(i))return null;const o=Math.round(e/n)*n,s=Math.round(i/n)*n;if(!Number.isFinite(o)||!Number.isFinite(s))return null;r.push([Object.is(o,-0)?0:o,Object.is(s,-0)?0:s])}return Math.abs(as(r))>n*n?r:null}function Bs(e,t,i,n){if(Ds(e[0],e[1],t[0],t[1],i[0],i[1])>n)return!1;const r=i[0]-t[0],o=i[1]-t[1],s=(e[0]-t[0])*r+(e[1]-t[1])*o,a=r*r+o*o,l=n*Math.sqrt(a);return s>=-l&&s<=a+l}function qs(e,t,i){const n=[],r=[];for(let o=0;oi*i))continue;const d=i/Math.sqrt(h),u=[0,1];for(const e of t)for(const t of[e.a,e.b]){if(!Bs(t,s,a,i))continue;const e=((t[0]-s[0])*l+(t[1]-s[1])*c)/h;e>d&&e<1-d&&u.push(e)}u.sort((e,t)=>e-t);const p=u.filter((e,t)=>0===t||Math.abs(e-u[t-1])>d);for(let e=0;e=3&&r.length===n.length?{poly:n,offsets:r}:null}function js(e,t,i,n,r,o,s,a){const l=(e||[]).map(ei).filter(e=>!!e&&e.length>=3);if(!l.length)return null;let c=Bt(Fs(l[0]));for(let e=1;e"outer"===e.kind&&e.half>0),u=4*ss(n,s),p=a||ws(h,u,s);let _=null;for(const e of function(e){const t=[];for(const i of Array.isArray(e)?e:[])if(Array.isArray(i))for(const e of i){if(!Array.isArray(e)||e.length<4)continue;const i=e.slice(0,-1).map(e=>[e[0],e[1]]);i.length>=3&&t.push(i)}return t}(c)){const t=qs(e,d,u);if(!t||!t.offsets.some(e=>e>0))continue;const i=Qs(t.poly,t.offsets,p),n=ps(t.poly,t.offsets,p);if(!i||!n)continue;const r=jt(Fs(i),Fs(n));_=_?Bt(_,r):r}return{centre:c,shell:_||[]}}function Ws(e,t,i,n,r,o,s=1){try{const a=js(e,t,i,n,r,o,s,Ss(e,t,i,n,r,o,s));if(!a)return[];return a.shell?.length?Bt(a.centre,a.shell):a.centre}catch{return null}}function Us(e){if(!e)return"";let t="";for(const i of e)if(Array.isArray(i))for(const e of i){if(!Array.isArray(e)||e.length<4)continue;const i=e.slice(0,e.length-1);i.length<3||(t+=(t?" ":"")+_s(i.map(e=>[e[0],e[1]])))}return t}const Vs=15;function Gs(e,t,i){const n=e?.length||0;if(n<3||t?.length!==n)return!1;const r=e[(i-1+n)%n],o=e[i],s=e[(i+1)%n],a=[r[0]-o[0],r[1]-o[1]],l=[s[0]-o[0],s[1]-o[1]],c=Math.hypot(a[0],a[1]),h=Math.hypot(l[0],l[1]);if(!(c>1e-9&&h>1e-9))return!1;const d=Math.max(-1,Math.min(1,(a[0]*l[0]+a[1]*l[1])/(c*h))),u=Math.acos(d);if(!(u>1e-9))return!1;if(u>=Vs*Math.PI/180)return!1;const p=Math.max(0,t[(i-1+n)%n]),_=Math.max(0,t[i]);if(!(p>0||_>0))return!1;const m=Math.sin(u);if(!(m>1e-12))return!1;const g=(_+p*d)/m,f=(p+_*d)/m;return Number.isFinite(g)&&Number.isFinite(f)&&g>0&&f>0&&ge>0))continue;for(const e of l.offsets)e>0&&(u=Math.max(u,2*e));const c=Qs(l.poly,l.offsets,d),p=ps(l.poly,l.offsets,d);c&&h.push({outset:c,inset:p})}for(const e of l){const t=e.map(e=>e[0]),i=e.map(e=>e[1]);if(t.length){const n=Math.min(Math.max(...t)-Math.min(...t),Math.max(...i)-Math.min(...i)),r=Math.min(...e.map((t,i)=>{const n=e[(i+1)%e.length];return Math.hypot(n[0]-t[0],n[1]-t[1])}));u=Math.max(u,e.length>16?n:r)}}const p=function(e,t,i,n,r,o,s,a){if(!t?.length||!i?.length)return[];const l=4*ss(n,s),c=new Map;for(const a of Ms(e,t,i,n,r,o,s))!a.open&&a.half>0&&!c.has(a.key)&&c.set(a.key,a);const h=[...c.values()];if(h.length<2)return[];const d=a||ws(h,l),u=[];for(const e of i)for(const t of[[e[0],e[1]],[e[2],e[3]]])u.some(e=>Math.hypot(e[0]-t[0],e[1]-t[1])<=l)||u.push(t);const p=[],_=(e,t)=>{let i=0,n=0;if(Math.hypot(e.a[0]-t[0],e.a[1]-t[1])<=l)i=e.b[0]-e.a[0],n=e.b[1]-e.a[1];else{if(!(Math.hypot(e.b[0]-t[0],e.b[1]-t[1])<=l))return null;i=e.a[0]-e.b[0],n=e.a[1]-e.b[1]}const r=Math.hypot(i,n);return r>l?[i/r,n/r]:null};for(const e of u){const t=h.map(t=>({iv:t,u:_(t,e)})).filter(e=>!!e.u);for(let i=0;i0?[e.slice(),u,m,_]:[e.slice(),_,m,u];else{if(!f)continue;{const t=[-r.u[1],r.u[0]],i=[-o.u[1],o.u[0]],n=s<0?1:-1,a=[e[0]+t[0]*r.iv.half*n,e[1]+t[1]*r.iv.half*n],l=[e[0]-i[0]*o.iv.half*n,e[1]-i[1]*o.iv.half*n];y=s>0?[e.slice(),a,l]:[e.slice(),l,a]}}Math.abs(as(y))>l*l&&p.push(y)}}return p}(e,t,i,r,o,s,a,d),_=n.length?ea(e,t,i,r,o,s,a):null;let m="exterior";try{const v=js(e,t,i,r,o,s,a,d);m="paper";const y=v?v.shell?.length?Bt(v.centre,v.shell):v.centre:[],b=e=>{const t=Fs(e.outset);if(!e.inset)return t;const i=Fs(e.inset);return jt(t,i)};m="room-rings";let w=null;for(const e of h)try{const t=b(e);w=w?Bt(w,t):t}catch{}if(m="edge-bodies",v)for(const n of Zs(e,t,i,r,o,s,a))try{const e=qt(Fs(n.quad),v.centre);w=w?Bt(w,e):e}catch{}m="junctions",w=function(e,t,i=1,n=Bt){let r=e;for(const e of t||[]){const t=Ls(e,i);if(t)try{const e=Fs(t);r=r?n(r,e):e}catch{}}return r}(w,p,a),m="facade-clip",w&&v&&(w=qt(w,v.centre)),m="exterior-shell";const k=[];let x=0;if(v?.shell?.length)if(w)try{const e=Bt(w,v.shell);if(!zs(e))throw new Error("invalid shell union");w=e}catch{if(!zs(w)||!zs(v.shell))throw new Error("invalid shell");k.push({id:"exterior-shell",geom:v.shell}),x++}else w=v.shell;if(m="multi-wall-trim",w&&d.nodes.length){const e=e=>e.rays.some(e=>e.supports.some(e=>e.length<2*e.halfDepth)),t=d.nodes.filter(e);if(t.length){w=Hs(w,{...d,nodes:t},v?.centre,y)}}if(m="junction-corners",d.nodes.length){const n=ks(d),l=function(e,t,i,n,r,o,s,a){try{const l=js(e,t,i,n,r,o,s,{epsilon:a.epsilon,coordinateScale:a.coordinateScale,nodes:[],index:new Map});return l?l.shell?.length?Bt(l.centre,l.shell):l.centre:null}catch{return null}}(e,t,i,r,o,s,a,d);for(const e of n.fans)try{let t=[Fs(e)];if(l&&(t=qt(t,l)),!t?.length)continue;w=w?Bt(w,t):t}catch{}g=w,f=Math.max(d.epsilon,1e-9)**2,w=Array.isArray(g)?g.map(e=>{if(!Array.isArray(e)||!e.length)return e;const[t,...i]=e;return Math.abs(as(t||[]))<=f?null:[t,...i.filter(e=>Math.abs(as(e||[]))>f)]}).filter(e=>!!e):g}const S=w||[],$=[...zs(S)?[{id:"room-primary",geom:S}]:[],...k.map((e,t)=>({id:`room-isolated-${t}`,geom:e.geom}))];m="openings";for(const e of n){if(!(e.length>0))continue;const t=na(_,e,!0);if(!t.negative&&!t.positive)continue;const i=e.angle*Math.PI/180,n=Math.cos(i),o=Math.sin(i),s=-o,l=n,c=e.length/2,h=1.25*Math.max(u,r*a),d=[[e.x-n*c-s*h,e.y-o*c-l*h],[e.x+n*c-s*h,e.y+o*c-l*h],[e.x+n*c+s*h,e.y+o*c+l*h],[e.x-n*c+s*h,e.y-o*c+l*h]];w&&(w=jt(w,Fs(d)));for(const e of k)e.geom=jt(e.geom,Fs(d))}m="extras";const M=[];let R=0;const C=c.mergeExtra||((e,t)=>e?Bt(e,t):t);for(let e=0;ee.length>=2&&Number.isFinite(e[0])&&Number.isFinite(e[1]))||Math.abs($i(t))<=1e-9){R++;continue}const i=[Fs(t)];try{const t=C(w,i,e);if(!zs(t))throw new Error("invalid extra union");w=t}catch{R++,zs(i)&&M.push({id:`extra-${e}`,geom:i})}}M.push(...k),M.sort((e,t)=>Us(e.geom).localeCompare(Us(t.geom)));const T=w||[];return{status:R||x?"degraded-extra":"ok",geom:T,components:[...zs(T)?[{id:"primary",geom:T}]:[],...M.map((e,t)=>({...e,id:`isolated-${t}`}))],roomGeom:S,roomComponents:$,paperGeom:y,depthUnits:u,openingPadUnits:1.25*Math.max(u,r*a),openingIndex:_,multiWallNodes:d,degradedExtraCount:R+x}}catch{return c.onCoreFailure?.(m),{status:"failed-core",geom:[],components:[],roomGeom:[],paperGeom:[],roomComponents:[],depthUnits:u,openingIndex:null,multiWallNodes:d,degradedExtraCount:0}}var g,f}function Ys(e,t,i,n=[],r,o,s,a=1,l=[],c={}){if(!t?.length&&!l.length)return null;return Xs(Ks(e,t,i,n,r,o,s,a,l,c))}function Xs(e){if("failed-core"===e.status||"not-applicable"===e.status)return null;const t=e.components.map(e=>({id:e.id,d:Us(e.geom),fillRule:"evenodd"})).filter(e=>!!e.d),i=t[0]?.d||"",n=Us(e.paperGeom);if(t.length){const r={status:e.status,d:i,paths:t,components:e.components,roomGeom:e.roomGeom,multiWallNodes:e.multiWallNodes,paperD:n,depthUnits:e.depthUnits,fillRule:"evenodd"};return Object.defineProperties(r,{roomComponents:{value:e.roomComponents||[],enumerable:!1},openingIndex:{value:e.openingIndex,enumerable:!1},openingPadUnits:{value:e.openingPadUnits,enumerable:!1}}),r}return null}function Zs(e,t,i,n,r,o,s=1){if(!t?.length)return[];const a=new Set,l=[];for(const c of e||[]){if(!c?.id)continue;const h=$s(e,c.id,t,i,n,r,o,s);if(!h)continue;const d=h.poly;for(let e=0;e0))continue;const p=zo(t,i,n,s);if(a.has(p))continue;a.add(p);const _=Co(u,r,o),[m,g]=ls(d,e),f=-m,v=-g,y=_/2,b=[[t[0]+f*y,t[1]+v*y],[i[0]+f*y,i[1]+v*y],[i[0]+m*y,i[1]+g*y],[t[0]+m*y,t[1]+g*y]];l.push({key:p,kind:c,cm:u,quad:b,a:[t[0],t[1]],b:[i[0],i[1]],depthUnits:_})}}return l}function Js(e,t=[]){let i=_s(e.quad);const[n,r]=Po(e.a,e.b),o=n,s=r,a=-s,l=o;for(const n of t){if(!jo(e.a,e.b,n.angle))continue;if(Ds(n.x,n.y,e.a[0],e.a[1],e.b[0],e.b[1])>Math.max(.55*e.depthUnits,.001))continue;const t=n.length/2,r=e.depthUnits,c=n.x,h=n.y;i+=` ${_s(ms([[c-o*t-a*r,h-s*t-l*r],[c+o*t-a*r,h+s*t-l*r],[c+o*t+a*r,h+s*t+l*r],[c-o*t+a*r,h-s*t+l*r]]))}`}return i}function Qs(e,t,i){const n=e?.length||0;if(n<3||t.length!==n)return null;if(t.every(e=>!(e>0)))return e.map(e=>[e[0],e[1]]);ms(e),t.slice().reverse();const r=[];for(let o=0;o0||l>0)){r.push([e[o][0],e[o][1]]);continue}if(a>0!=l>0){const t=e[o],i=a>0?[t[0]-c*a,t[1]-h*a]:[t[0],t[1]],n=l>0?[t[0]-d*l,t[1]-u*l]:[t[0],t[1]];r.push(i),Math.hypot(n[0]-i[0],n[1]-i[1])>1e-9&&r.push(n);continue}if(cs(w,k)){const t=e[o],i=[t[0]-c*a,t[1]-h*a],n=[t[0]-d*l,t[1]-u*l];r.push(i),Math.hypot(n[0]-i[0],n[1]-i[1])>1e-9&&r.push(n);continue}const $=hs(x,w,S,k),M=Math.max(a,l,1e-9),R=xs(i,e[o])?.limit??4*M;if($){const i=Math.hypot($[0]-e[o][0],$[1]-e[o][1]);if(Number.isFinite(i)&&i<=R){r.push($);continue}if(Gs(e,t,o)){r.push([e[o][0],e[o][1]]);continue}}a>0&&r.push([e[o][0]-c*a,e[o][1]-h*a]),l>0&&r.push([e[o][0]-d*l,e[o][1]-u*l])}return r.length>=3?r:null}function ea(e,t,i,n,r,o,s=1){const a=[];for(const l of e||[]){if(!l?.id)continue;const c=$s(e,l.id,t,i,n,r,o,s);if(!c)continue;const h=Math.abs($i(c.poly));for(let e=0;e[Math.max(t,e.x0),Math.min(i,e.x1)]).filter(e=>e[1]-e[0]>n).sort((e,t)=>e[0]-t[0]||e[1]-t[1]);if(!r.length)return{coverage:0,full:!1};let o=r[0][0],s=r[0][1],a=0,l=o<=t+n;for(let e=1;e=i-n,{coverage:a,full:l}}function ia(e,t){return Number(t.full)-Number(e.full)||e.faceDistance-t.faceDistance||e.area-t.area||e.roomId.localeCompare(t.roomId)}function na(e,t,i=!1){const n=Number(t?.x),r=Number(t?.y),o=Number(t?.angle),s=Number(t?.length);if(!([n,r,o,s].every(Number.isFinite)&&s>0))return{negative:null,positive:null};const a=o*Math.PI/180,l=Math.cos(a),c=Math.sin(a),h=-c,d=l,u=s/2,p=Math.max(1e-9,e.adjacencyEps),_=new Map;let m=0;for(const t of e.edges){if(i&&!(t.half>0))continue;if(!jo(t.a,t.b,o))continue;const[e,s]=Po(t.a,t.b);if(Math.abs((n-t.a[0])*s-(r-t.a[1])*e)>p)continue;const a=(t.a[0]-n)*l+(t.a[1]-r)*c,g=(t.b[0]-n)*l+(t.b[1]-r)*c,f=Math.max(-u,Math.min(a,g)),v=Math.min(u,Math.max(a,g));if(v-f<=p)continue;const y=t.inward[0]*h+t.inward[1]*d>=0?1:-1,b=((t.a[0]+t.b[0])/2-n)*h+((t.a[1]+t.b[1])/2-r)*d,w=Math.abs(b+y*t.half),k=`${y}|${t.roomId}`,x={x0:f,x1:v,half:t.half,cm:t.cm,key:t.key,axis:[e,s]},S=_.get(k);S?(S.pieces.push(x),S.faceDistance=Math.min(S.faceDistance,w)):_.set(k,{roomId:t.roomId,side:y,order:m++,pieces:[x],faceDistance:w,area:t.area,coverage:0,full:!1})}for(const e of _.values()){const t=ta(e.pieces,-u,u,p);e.coverage=t.coverage,e.full=t.full}const g=e=>{const t=[..._.values()].filter(t=>t.side===e&&t.coverage>p);return t.sort(ia),t[0]||null};return{negative:g(-1),positive:g(1)}}function ra(e,t,i,n,r,o,s=1,a=[]){return oa(ea(e,i,a,n,r,o,s),t)}function oa(e,t){const i=na(e,t),n=[i.negative,i.positive].filter(e=>!!e);if(!n.length)return{ox:0,oy:0,cm:0,side:-1};const r=i.negative&&i.positive?-1:n[0].side,o=t.flip_v?-r:r,s=(-1===o?i.negative:i.positive)||n[0],a=[...s.pieces].sort((e,t)=>(e.x0<=0&&e.x1>=0?0:Math.min(Math.abs(e.x0),Math.abs(e.x1)))-(t.x0<=0&&t.x1>=0?0:Math.min(Math.abs(t.x0),Math.abs(t.x1)))||t.x1-t.x0-(e.x1-e.x0)||e.key.localeCompare(t.key))[0];if(!(a.half>0&&a.cm>0))return{ox:0,oy:0,cm:0,side:o};const l=t.angle*Math.PI/180,c=-Math.sin(l),h=Math.cos(l);return{ox:c*o*a.half,oy:h*o*a.half,cm:a.cm,side:o}}function sa(e,t){const i=1e-9,n=t.filter(e=>Number.isFinite(e.x0)&&Number.isFinite(e.x1)&&Number.isFinite(e.half)&&e.x1>e.x0&&e.half>0);if(!n.length)return"";const r=n.flatMap(e=>[e.x0,e.x1]).sort((e,t)=>e-t),o=[];for(const e of r){const t=o[o.length-1];(void 0===t||e>t+i)&&o.push(e)}const s=[];for(let e=0;e+1t+i))continue;const a=(t+r)/2,l=n.reduce((e,t)=>a>=t.x0-i&&a<=t.x1+i?Math.max(e,t.half):e,0);if(!(l>0))continue;const c=s[s.length-1];c&&t<=c.x1+i&&Math.abs(l-c.half)<=i?c.x1=r:s.push({x0:t,x1:r,half:l})}const a=[];for(const e of s){const t=a[a.length-1],n=t?.[t.length-1];n&&e.x0<=n.x1+i?(e.x0=n.x1,t.push(e)):a.push([e])}return a.map(t=>{const i=t[0],n=t[t.length-1],r=Math.min(.25*Math.min(...t.map(e=>e.half)),.75),o=-e*r,s=[];if(1===e){s.push(`M ${i.x0} ${o} L ${n.x1} ${o}`);for(let e=t.length-1;e>=0;e--){const i=t[e];s.push(`L ${i.x1} ${i.half} L ${i.x0} ${i.half}`)}}else{s.push(`M ${n.x1} ${o} L ${i.x0} ${o}`);for(const e of t)s.push(`L ${e.x0} ${-e.half} L ${e.x1} ${-e.half}`)}return s.push("Z"),s.join(" ")}).join(" ")}function aa(e,t,i,n){if(!n)return i;const r=e.angle*Math.PI/180,o=Math.cos(r),s=Math.sin(r),a=[],l=1e-9;for(const r of i){const[i,c]=r.axis,h=o*i+s*c;if(Math.abs(h)<=l)continue;const d=e.x*i+e.y*c,u=d+h*r.x0,p=d+h*r.x1,_=Math.min(u,p),m=Math.max(u,p),g=`${r.key}|${t}`,f=n.get(g)||[];let v=[[_,m]];for(const[e,t]of f){const i=[];for(const[n,r]of v)t<=n+l||e>=r-l?i.push([n,r]):(e>n+l&&i.push([n,Math.min(r,e)]),te[0]-t[0]||e[1]-t[1]),b=[];for(const e of y){const t=b[b.length-1];t&&e[0]<=t[1]+l?t[1]=Math.max(t[1],e[1]):b.push([e[0],e[1]])}n.set(g,b)}return a}function la(e,t){const i=new Map;return t.map(t=>function(e,t,i){const n=na(e,t,!0),r=n.negative,o=n.positive;if(!r&&!o)return null;let s;if(r&&o)s=[{candidate:r,side:-1},{candidate:o,side:1}];else{const e=r||o;s=[{candidate:e,side:-1},{candidate:e,side:1}]}const a=s.map(({candidate:e,side:n})=>({candidate:e,side:n,pieces:aa(t,n,e.pieces,i)})),l=a.map(({candidate:e,side:t,pieces:i})=>({side:t,roomId:e.roomId,d:sa(t,i)})),c=a.flatMap(({pieces:e})=>e);if(!c.length)return null;const h=Math.max(...c.map(e=>e.half));return{faces:l,minY:-h,maxY:h,wallKey:[...new Set(c.map(e=>e.key))].sort().join("|")}}(e,t,i))}const ca=150,ha=1e-6;function da(e){return Number.isFinite(e)?Math.max(1,Math.min(ca,e)):1}function ua(e){return((Number.isFinite(Number(e))?Number(e):0)%90+90)%90}const pa=e=>{const t=e.map(e=>[e[0],e[1]]);return!t.length||t[0][0]===t[t.length-1][0]&&t[0][1]===t[t.length-1][1]||t.push([...t[0]]),[t]},_a=(e,t)=>e[0]===t[0]&&e[1]===t[1];function ma(e,t=1e-6){const i=Number.isFinite(t)&&t>0?t:ha,n=[];for(const t of e||[]){if(!Array.isArray(t)||t.length<2)return null;const e=Number(t[0]),r=Number(t[1]);if(!Number.isFinite(e)||!Number.isFinite(r))return null;const o=Math.round(e/i)*i,s=Math.round(r/i)*i;if(!Number.isFinite(o)||!Number.isFinite(s))return null;const a=[Object.is(o,-0)?0:o,Object.is(s,-0)?0:s];n.length&&_a(n[n.length-1],a)||n.push(a)}return n.length>1&&_a(n[0],n[n.length-1])&&n.pop(),n.length<3||new Set(n.map(e=>`${e[0]},${e[1]}`)).size<3?null:$i(n)>i*i?n:null}function ga(e){const t=[];for(const i of e||[])for(const e of i||[]){const i=(e||[]).filter(e=>Array.isArray(e)&&e.length>=2);i.length<4||t.push(`M ${i.slice(0,-1).map(e=>`${e[0]} ${e[1]}`).join(" L ")} Z`)}return t.join(" ")}function fa(e,t,i,n,r){return Zo({a:e,b:t,halfDepth:Co(i,n,r)/2})}function va(e,t,i){const n=Number(t)>0?Number(t):5,r=da(e.cm)/n*i,o=e.center[0],s=e.center[1];if("circle"===e.shape){const e=r/2;return Array.from({length:96},(t,i)=>{const n=i/96*Math.PI*2;return[o+Math.cos(n)*e,s+Math.sin(n)*e]})}const a=r/2,l=ua(e.angle)*Math.PI/180,c=Math.cos(l),h=Math.sin(l);return[[-a,-a],[a,-a],[a,a],[-a,a]].map(([e,t])=>[o+e*c-t*h,s+e*h+t*c])}function ya(e,t){const i=Number.isFinite(t)?Math.max(0,Math.min(1,t)):0,n=(e.a[0]+e.b[0])/2,r=(e.a[1]+e.b[1])/2,o=(e.b[0]-e.a[0])*i/2,s=(e.b[1]-e.a[1])*i/2;return{...e,a:[n-o,r-s],b:[n+o,r+s]}}function ba(e,t,i=1e-9){if(!t.length)return[e];let n=[pa(e)];try{for(const e of t){const t=e.b[0]-e.a[0],r=e.b[1]-e.a[1],o=Math.hypot(t,r);if(!(o>i))continue;const s=t/o,a=r/o,l=-a,c=s,h=1.25*Math.max(Number(e.depth)||0,4*i),d=Math.max(2*i,1e-9*o),u=[[e.a[0]-s*d-l*h,e.a[1]-a*d-c*h],[e.b[0]+s*d-l*h,e.b[1]+a*d-c*h],[e.b[0]+s*d+l*h,e.b[1]+a*d+c*h],[e.a[0]-s*d+l*h,e.a[1]-a*d+c*h]];n=jt(n,pa(u))}return Da(n)}catch{return[e]}}function wa(e,t){try{const i=jt([[...e.map(e=>[e[0],e[1]]),[e[0][0],e[0][1]]]],[[...t.map(e=>[e[0],e[1]]),[t[0][0],t[0][1]]]]);let n=null,r=0;for(const e of i||[]){const t=e?.[0]||[],i=Math.abs($i(t));t.length>=4&&i>r&&(r=i,n=t.slice(0,-1).map(e=>[e[0],e[1]]))}return n}catch{return null}}function ka(e,t,i,n=Math.max(2e-4*i,1e-9),r=[]){const o=[],s=new Map;for(const e of r){const t=s.get(e.hostId)||[];t.push(e),s.set(e.hostId,t)}const a=[],l=[],c=[];for(const n of e.partitions||[]){const e={a:n.a,b:n.b,halfDepth:Co(n.cm,t,i)/2};if(!(e.halfDepth>0))continue;const r=Zo(e);r&&(o.push(e),a.push(r),c.push({id:n.id,body:r}))}const h=o;for(const{segmentIndex:e,wedge:t}of is(h,n)){const i={list:a,at:e},n=wa(i.list[i.at],t);n&&(i.list[i.at]=n,c[i.at].body=n)}for(const e of c)l.push(...ba(e.body,s.get(e.id)||[],n));const d=(e.wall_columns||[]).map(e=>va(e,t,i)),u=ns(o,n).flatMap(e=>ba(e,r,n));return{partitions:a,columns:d,patches:u,all:[...l,...u,...d]}}function xa(e){try{const t=e.map(e=>ma(e)).filter(e=>!!e).map(e=>pa(e));return t.length?Bt(t[0],...t.slice(1)):null}catch{return null}}const Sa=e=>`M ${e.map(e=>`${e[0]} ${e[1]}`).join(" L ")} Z`;function $a(e){const t=[];for(const i of e||[]){if(Ca([i])<=1e-6)continue;const e=[];for(const t of i||[]){const i=(t||[]).filter(e=>Array.isArray(e)&&e.length>=2);i.length<4||e.push(Sa(i.slice(0,-1)))}e.length&&t.push(e.join(" "))}return t}function Ma(e,t,i={}){const n=xa(e.filter(e=>e.length>=3)),r=t.some(e=>!ma(e))?null:xa(t);if(!n)return[];if(r)try{return $a(qt(n,r))}catch{}return function(e,t,i){let n=null;for(let r=0;r=4&&t.push(e.slice(0,-1).map(e=>[e[0],e[1]]));return t}function Da(e){const t=[];for(const i of e||[]){const e=i?.[0];e?.length>=4&&t.push(e.slice(0,-1).map(e=>[e[0],e[1]]))}return t}function Aa(e,t){let i=!1;for(let n=0,r=t.length-1;ne[1]!=l>e[1]&&e[0]<(a-o)*(e[1]-s)/(l-s||1e-12)+o&&(i=!i)}return i}function Pa(e,t){for(const i of t||[]){const t=i?.[0];if(!t?.length||!Aa(e,t))continue;let n=!1;for(let t=1;ti)return!1;if(Math.abs(da(e.cm)-da(t.cm))>1e-6)return!1;if(e.shape!==t.shape)return!0;if("circle"===e.shape||"circle"===t.shape)return!0;const n=Math.abs(ua(e.angle)-ua(t.angle));return Math.min(n,90-n)<=1e-6}const za=2.54;function Ia(e){const t="number"==typeof e?e:NaN;return!Number.isFinite(t)||t<=0||5===t?1:5/t}function Oa(e,t){return e*Ia(t)}function Ea(e){return e?za:1}function Na(e,t){if(!t)return String(e);const i=e/za;return String(Math.round(1e6*i)/1e6)}function Ha(e,t){return t?e*za:e}const La=1e3;function Ba(e,t){const i=Number(e),n=Number.isFinite(i)&&i>0?i:1,r=n>=1?t:t*n,o=n>=1?t/n:t;return{x:(t-r)/2,y:(t-o)/2,w:r,h:o}}const qa=.01,ja=100;function Wa(e,t=1e3){const i=Ba(e?.plan_aspect,t),n=Number(e?.plan_scale),r=Number.isFinite(n)&&n>0?Math.min(ja,Math.max(qa,n)):1,o=Number(e?.plan_scale_x),s=Number(e?.plan_scale_y),a=Number.isFinite(o)&&o>0?Math.min(ja,Math.max(qa,o)):r,l=Number.isFinite(s)&&s>0?Math.min(ja,Math.max(qa,s)):r,c=Number(e?.plan_x),h=Number(e?.plan_y),d=kr(e?.plan_angle);return{x:i.x+(Number.isFinite(c)?tl(c):0)*t,y:i.y+(Number.isFinite(h)?tl(h):0)*t,w:i.w*a,h:i.h*l,...d?{angle:d}:{}}}function Ua(e){if(null==e.x||null==e.y)return{x:e.x,y:e.y,w:e.w,h:e.h};const t=Number(e.w)||0,i=Number(e.h)||0;return{x:t<0?e.x+t:e.x,y:i<0?e.y+i:e.y,w:Math.abs(t),h:Math.abs(i)}}function Va(e){return e&&Array.isArray(e.spaces)?e.spaces.map(e=>{const t=La,i=function(e){return Array.isArray(e)&&4===e.length&&e.every(e=>Number.isFinite(e))&&e[2]>1e-6&&e[3]>1e-6?e:[0,0,1,1]}(e.view_box);return{id:e.id,title:e.title,cellCm:Number.isFinite(Number(e.cell_cm))&&Number(e.cell_cm)>0?Number(e.cell_cm):5,vb:[i[0]*La,i[1]*t,i[2]*La,i[3]*t],bg:e.plan_url?{href:zn(e.plan_url),...Wa(e,La)}:null,rooms:(e.rooms||[]).map(e=>{const i={...e,...Ua(e)};return{id:i.id,name:i.name,area:i.area??null,open_to:i.open_to||void 0,settings:i.settings||void 0,x:null!=i.x?i.x*La:void 0,y:null!=i.y?i.y*t:void 0,w:null!=i.w?i.w*La:void 0,h:null!=i.h?i.h*t:void 0,poly:i.poly?i.poly.map(e=>[e[0]*La,e[1]*t]):void 0,wall_ids:Array.isArray(i.wall_ids)?[...i.wall_ids]:void 0}}),wall_segments:(e.wall_segments||[]).map(e=>({...e,id:String(e.id),a:[Number(e.a?.[0])*La,Number(e.a?.[1])*t],b:[Number(e.b?.[0])*La,Number(e.b?.[1])*t],cm:Number(e.cm)})),partitions:(e.partitions||[]).map(e=>({id:e.id,a:[e.a[0]*La,e.a[1]*t],b:[e.b[0]*La,e.b[1]*t],cm:Number(e.cm)})),wall_columns:(e.wall_columns||[]).map(e=>({id:e.id,shape:"circle"===e.shape?"circle":"square",center:[e.center[0]*La,e.center[1]*t],cm:Number(e.cm),..."circle"===e.shape?{}:{angle:ua(e.angle)}}))}}):[]}const Ga=5e3,Ka=Ga*La,Ya=240,Xa=La/Ya,Za=1/Ya;function Ja(e){if(!Number.isFinite(e))return e;const t=Math.round(e*Ya/La)*La/Ya;return Math.abs(t-e)<=1e-9*Xa?e:t}function Qa(e){return{x:Ja(e.x),y:Ja(e.y)}}function el(e){return Number.isFinite(e)?Math.min(Ka,Math.max(-Ka,e)):0}function tl(e){return Number.isFinite(e)?Math.min(Ga,Math.max(-Ga,e)):0}const il=1/3,nl=200;function rl(e){return"house"===e?"house":"content"}function ol(e){let t=1/0,i=1/0,n=-1/0,r=-1/0;for(const o of e){const e=Number(o[0]),s=Number(o[1]);Number.isFinite(e)&&Number.isFinite(s)&&(en&&(n=e),s>r&&(r=s))}return t>n?null:{minX:t,minY:i,maxX:n,maxY:r}}function sl(e){const t=[],i=e=>{if(Array.isArray(e))if(e.length>=2&&Number.isFinite(Number(e[0]))&&Number.isFinite(Number(e[1])))t.push([Number(e[0]),Number(e[1])]);else for(const t of e)i(t)};return i(e),ol(t)}function al(e,t){const i=Number.isFinite(t)&&t>0?t:0;return{minX:e.minX-i,minY:e.minY-i,maxX:e.maxX+i,maxY:e.maxY+i}}function ll(e){return e.poly&&e.poly.length?ol(e.poly):null==e.x||null==e.y?null:ol([[e.x,e.y],[e.x+(e.w||0),e.y+(e.h||0)]])}function cl(e,t=1e3,i=1e3){const n=Number(e.x)*t,r=Number(e.y)*i,o=Number(e.w)*t,s=Number(e.h)*i;return![n,r,o,s].every(Number.isFinite)||o<=0||s<=0?null:ol(Dr({x:n,y:r,w:o,h:s,angle:kr(e.angle)||void 0}))}function hl(e,t){const i=[];for(const t of e.rooms||[]){const e=ll(t);e&&i.push(e)}if(e.bg){const t=ol(Dr(e.bg));t&&i.push(t)}for(const e of t||[])if(Array.isArray(e)){const t=ol([e]);t&&i.push(t)}else i.push(e);return i}const dl=e=>{if(!e.length)return 0;const t=[...e].sort((e,t)=>e-t),i=t.length>>1;return t.length%2?t[i]:(t[i-1]+t[i])/2},ul=e=>{let t=1/0,i=1/0,n=-1/0,r=-1/0;for(const o of e)o.minXn&&(n=o.maxX),o.maxY>r&&(r=o.maxY);return t>n||i>r?null:{x:t,y:i,w:n-t,h:r-i}};function pl(e,t){let{x:i,y:n,w:r,h:o}=e;r<30&&(i=i+r/2-100,r=nl),o<30&&(n=n+o/2-100,o=nl);const s="number"==typeof t?{top:t,right:t,bottom:t,left:t}:t,a=Math.max(r,o),l=a*s.top,c=a*s.right,h=a*s.bottom,d=a*s.left;return{x:i-d,y:n-l,w:r+d+c,h:o+l+h}}function _l(e,t={}){const i=t.pad??.05,n=t.k??10,r=t.minSpread??50,o=e.filter(e=>Number.isFinite(e.minX)&&Number.isFinite(e.minY)&&Number.isFinite(e.maxX)&&Number.isFinite(e.maxY)&&Math.abs(e.minX)<=Ka&&Math.abs(e.maxX)<=Ka&&Math.abs(e.minY)<=Ka&&Math.abs(e.maxY)<=Ka);if(!o.length)return{core:null,all:null,outliers:0};const s=ul(o);if(o.length<4){const e=pl(s,i);return{core:e,all:e,outliers:0}}const a=o.map(e=>(e.minX+e.maxX)/2),l=o.map(e=>(e.minY+e.maxY)/2),c=dl(a),h=dl(l),d=o.map((e,t)=>Math.max(Math.abs(a[t]-c),Math.abs(l[t]-h))),u=Math.max(((e,t)=>e.length?e[Math.min(e.length-1,Math.max(0,Math.round(t*(e.length-1))))]:0)([...d].sort((e,t)=>e-t),.75),r),p=d.map(e=>e>n*u),_=p.filter(Boolean).length,m=_&&_<=o.length*il?o.filter((e,t)=>!p[t]):o;return{core:pl(ul(m)||s,i),all:pl(s,i),outliers:m===o?0:_}}function ml(e){return _l(e,{pad:0}).all}function gl(e,t,i=.05){const n=_l(hl(e,t),{pad:i});if(n.core)return n.core;const r=e.vb&&4===e.vb.length&&e.vb[2]>0&&e.vb[3]>0?e.vb:[0,0,La,La];return{x:r[0],y:r[1],w:r[2],h:r[3]}}function fl(e){const t=gl(e);return{x:t.x+t.w/2,y:t.y+t.h/2}}function vl(e){const t=[];for(const i of e.rooms||[]){const e=ll(i);e&&t.push(e)}const i=_l(t,{pad:0}).core,n=La*Ia(e.cellCm??5);return i?Math.max(n,Math.min(Ka,Math.max(i.w,i.h))):n}function yl(e,t,i,n=1){const r=Number(i),o=Number.isFinite(n)&&n>0?n:1;return!Number.isFinite(r)||r<=0?e*o:e*vl(t)*o/r}const bl=[1,2,5,10,20,50,100,200,500,1e3];function wl(e,t,i=7){if(!(e>0&&t>0&&Number.isFinite(t)))return null;const n=bl.find(n=>e*n*t>=i);if(void 0===n)return null;const r=bl.find(e=>e>=5*n)??5*n;return{fine:n,coarse:r}}function kl(e){if(e.poly&&e.poly.length){const t=e.poly.map(e=>e[0]),i=e.poly.map(e=>e[1]),n=Math.min(...t),r=Math.min(...i);return{x:n,y:r,w:Math.max(...t)-n,h:Math.max(...i)-r}}return{x:e.x??0,y:e.y??0,w:e.w??0,h:e.h??0}}function xl(e,t,i,n,r,o=new Set){const s=t[e.id];return!o.has(e.id)&&s&&s.s===e.space?{x:s.x*La,y:s.y*La}:n[e.id]?n[e.id]:Qa(fl(r))}function Sl(e,t,i,n){const r=i["rl_"+(e.id||"")];if(r&&r.s===t)return{x:r.x*La,y:r.y*La};const o=function(e){if(e.poly){const t=e.poly.length;return[e.poly.reduce((e,t)=>e+t[0],0)/t,e.poly.reduce((e,t)=>e+t[1],0)/t]}return[e.x+e.w/2,e.y+.1*Math.min(e.w,e.h)]}(e);return Qa({x:o[0],y:o[1]})}function $l(e,t){for(const i of e?.spaces??[])for(const e of i?.decor??[])if("furniture"===e?.kind&&"string"==typeof e.symbol&&t(e.symbol))return!0;return!1}let Ml=0;const Rl=new Set;const Cl=new class{constructor(e){this.options=e,this._art=null,this._failed=!1,this._terminal=!1,this._inFlight=null,this._hosts=new Set,this._settled=[]}state(){return this._art?"ready":this._failed?"fallback":"pending"}get terminal(){return this._terminal}art(e,t){if(this._art)return this._art[e];t&&!this._failed&&this._hosts.add(t)}adopt(e,t){return!!this._art||(t!==this.options.expectedFingerprint?((this.options.warn??console.warn)("[houseplan] furniture artwork from another build ignored",{fingerprint:t}),!1):(this._install(e),!0))}ensure(){return"pending"!==this.state()?Promise.resolve():(this._inFlight||(this._inFlight=this._loadWithRetry().finally(()=>{this._inFlight=null})),this._inFlight)}onSettled(e){"pending"===this.state()?this._settled.push(e):Promise.resolve().then(e)}async _loadWithRetry(){let e=new Error("furniture artwork did not load");for(const t of[0,1])try{const i=await this.options.load(t);if(i.FURNITURE_ART_FINGERPRINT!==this.options.expectedFingerprint){this._terminal=!0,e=new Error(`furniture artwork fingerprint mismatch: expected ${this.options.expectedFingerprint}, got ${i.FURNITURE_ART_FINGERPRINT}`);break}if(this._art)return;return void this._install(i.GENERATED_FURNITURE_ART)}catch(t){e=t}this._art||(this._failed=!0,(this.options.warn??console.warn)("[houseplan] furniture artwork unavailable",e),this.options.loadFailed?.(this._terminal),this._flush())}_install(e){this._art=e,this._failed=!1,this._flush()}_flush(){const e=[...this._hosts];this._hosts.clear();for(const t of e)t.isConnected&&t.requestUpdate();const t=this._settled.splice(0);for(const e of t)e()}}({expectedFingerprint:"c8d5c166e30a11241ef32c7e1dc70368632e84c448524a8340494350ec4d5fca",load:async e=>0===e?await import("./furniture-plan-art.generated-Dw0IIirB.js"):await import((()=>{const e=new URL("./furniture-plan-art.generated-Dw0IIirB.js",import.meta.url);return e.searchParams.set("hp_retry","art-"+ ++Ml),e.href})()),loadFailed:e=>{for(const t of Rl)t(e)}}),Tl=["furniture","appliance","sanitary","other"],Dl=[{id:"sofa",group:"furniture",category:"sofa",w:220,h:90,g:[["r",0,0,1,1],["l",.09,.26,.91,.26],["l",.09,.26,.09,1],["l",.91,.26,.91,1],["l",.5,.26,.5,1]]},{id:"armchair",group:"furniture",category:"armchair",w:90,h:85,g:[["r",0,0,1,1],["l",.14,.28,.86,.28],["l",.14,.28,.14,1],["l",.86,.28,.86,1]]},{id:"coffee_table",group:"furniture",category:"coffee_table",w:110,h:60,g:[["r",0,0,1,1],["r",.08,.14,.84,.72]]},{id:"table_dining",group:"furniture",category:"dining_table",w:140,h:80,g:[["r",0,0,1,1],["r",.06,.11,.88,.78]]},{id:"table_round",group:"furniture",category:"dining_table",w:120,h:120,g:[["e",.5,.5,.5,.5],["e",.5,.5,.41,.41]]},{id:"chair",group:"furniture",category:"chair",w:45,h:45,g:[["r",0,0,1,.18],["r",.06,.18,.88,.8]]},{id:"desk",group:"furniture",category:"work_table",w:120,h:60,g:[["r",0,0,1,1],["r",.63,.07,.31,.86],["l",.63,.5,.94,.5]]},{id:"bed_double",group:"furniture",category:"bed",w:160,h:200,g:[["r",0,0,1,1],["r",0,0,1,.07],["r",.06,.1,.4,.15],["r",.54,.1,.4,.15],["l",0,.33,1,.33]]},{id:"bed_single",group:"furniture",category:"bed",w:90,h:200,g:[["r",0,0,1,1],["r",0,0,1,.07],["r",.15,.1,.7,.15],["l",0,.33,1,.33]]},{id:"nightstand",group:"furniture",category:"nightstand",w:45,h:40,g:[["r",0,0,1,1],["r",.12,.14,.76,.33],["r",.12,.53,.76,.33]]},{id:"wardrobe",group:"furniture",category:"wardrobe",w:100,h:60,g:[["r",0,0,1,1],["l",0,.72,1,.72],["l",.5,.72,.5,1]]},{id:"bookshelf",group:"furniture",category:"wardrobe",w:80,h:30,g:[["r",0,0,1,1],["l",.34,0,.34,1],["l",.67,0,.67,1]]},{id:"fridge",group:"appliance",category:"fridge",w:60,h:65,g:[["r",0,0,1,1],["l",0,.36,1,.36],["l",.83,.44,.83,.64]]},{id:"stove",group:"appliance",category:"cooktop",w:60,h:60,g:[["r",0,0,1,1],["e",.29,.31,.15,.15],["e",.71,.31,.15,.15],["e",.29,.71,.15,.15],["e",.71,.71,.15,.15]]},{id:"dishwasher",group:"appliance",category:"dishwasher",w:60,h:60,g:[["r",0,0,1,1],["r",.1,.12,.8,.76],["e",.5,.5,.27,.27],["e",.5,.5,.13,.13]]},{id:"washer",group:"appliance",category:"washer",w:60,h:60,g:[["r",0,0,1,1],["l",.08,.17,.92,.17],["e",.5,.57,.3,.3],["e",.5,.57,.14,.14]]},{id:"dryer",group:"appliance",category:"dryer",w:60,h:60,g:[["r",0,0,1,1],["l",.08,.17,.92,.17],["e",.5,.57,.3,.3],["p",.36,.5,.5,.64,.64,.5]]},{id:"tv",group:"appliance",category:"tv",w:120,h:30,g:[["r",0,0,1,.42],["l",.5,.42,.5,.72],["l",.3,.72,.7,.72]]},{id:"ac",group:"appliance",category:"air_conditioner",w:90,h:25,g:[["r",0,0,1,1],["l",.05,.55,.95,.55],["l",.05,.79,.95,.79]]},{id:"water_heater",group:"appliance",category:"boiler",w:45,h:45,g:[["e",.5,.5,.5,.5],["e",.5,.5,.31,.31]]},{id:"toilet",group:"sanitary",category:"toilet",w:40,h:70,g:[["r",.06,0,.88,.2],["e",.5,.58,.37,.35],["e",.5,.58,.22,.2]]},{id:"bathtub",group:"sanitary",category:"bathtub",w:170,h:75,g:[["r",0,0,1,1],["r",.05,.11,.77,.78],["e",.89,.5,.045,.1]]},{id:"shower",group:"sanitary",category:"shower",w:90,h:90,g:[["r",0,0,1,1],["l",0,0,1,1],["l",1,0,0,1],["e",.5,.5,.08,.08]]},{id:"sink",group:"sanitary",category:"sink",w:60,h:45,g:[["r",0,0,1,1],["e",.5,.6,.34,.3],["e",.5,.15,.07,.07]]},{id:"kitchen_sink",group:"sanitary",category:"kitchen_sink",w:80,h:60,g:[["r",0,0,1,1],["r",.06,.24,.44,.64],["r",.54,.24,.4,.64],["e",.5,.12,.06,.06]]},{id:"bidet",group:"sanitary",category:"bidet",w:40,h:55,g:[["e",.5,.5,.44,.5],["e",.5,.5,.26,.3]]},{id:"stairs",group:"other",category:"stairs",w:100,h:280,g:[["r",0,0,1,1],["l",0,.111,1,.111],["l",0,.222,1,.222],["l",0,.333,1,.333],["l",0,.444,1,.444],["l",0,.556,1,.556],["l",0,.667,1,.667],["l",0,.778,1,.778],["l",0,.889,1,.889],["l",.5,.93,.5,.06],["p",.38,.16,.5,.06,.62,.16]]},{id:"fireplace",group:"other",category:"fireplace",w:120,h:40,g:[["r",0,0,1,1],["p",.22,1,.22,.42,.78,.42,.78,1]]},{id:"plant",group:"other",category:"plant",w:40,h:40,g:[["e",.5,.5,.22,.22],["l",.5,.28,.5,.02],["l",.5,.72,.5,.98],["l",.28,.5,.02,.5],["l",.72,.5,.98,.5],["l",.34,.34,.13,.13],["l",.66,.66,.87,.87],["l",.66,.34,.87,.13],["l",.34,.66,.13,.87]]},{id:"rug",group:"other",category:"rug",w:200,h:140,g:[["r",0,0,1,1],["r",.06,.09,.88,.82]]}],Al=new Set(["fridge","dishwasher","washer","dryer","ac","water_heater","shower","sink","stairs","fireplace","plant","rug"]),Pl=[...[{id:"coffee_table",group:"furniture",category:"coffee_table",w:120,h:60},{id:"coffee_table_round",group:"furniture",category:"coffee_table",w:80,h:80},{id:"coffee_table_oval",group:"furniture",category:"coffee_table",w:120,h:60},{id:"coffee_table_rounded",group:"furniture",category:"coffee_table",w:120,h:60},{id:"table_dining",group:"furniture",category:"dining_table",w:160,h:90},{id:"table_round",group:"furniture",category:"dining_table",w:110,h:110},{id:"table_dining_oval",group:"furniture",category:"dining_table",w:180,h:100},{id:"table_dining_rounded",group:"furniture",category:"dining_table",w:160,h:90},{id:"desk",group:"furniture",category:"work_table",w:140,h:70},{id:"desk_corner",group:"furniture",category:"work_table",w:160,h:160},{id:"chair",group:"furniture",category:"chair",w:50,h:50},{id:"chair_bar",group:"furniture",category:"chair",w:45,h:48},{id:"armchair",group:"furniture",category:"armchair",w:90,h:90},{id:"armchair_office",group:"furniture",category:"armchair",w:65,h:65},{id:"sofa",group:"furniture",category:"sofa",w:180,h:90},{id:"sofa_three_seat",group:"furniture",category:"sofa",w:240,h:90},{id:"sofa_corner_right",group:"furniture",category:"sofa",w:260,h:170},{id:"bed_single",group:"furniture",category:"bed",w:90,h:200},{id:"bed_double",group:"furniture",category:"bed",w:160,h:200},{id:"nightstand",group:"furniture",category:"nightstand",w:50,h:40},{id:"cabinet_tv",group:"furniture",category:"nightstand",w:140,h:45},{id:"cabinet_shoe",group:"furniture",category:"nightstand",w:80,h:35},{id:"cabinet_sink",group:"furniture",category:"nightstand",w:80,h:50},{id:"bookshelf",group:"furniture",category:"wardrobe",w:100,h:35},{id:"wall_unit",group:"furniture",category:"wardrobe",w:240,h:45},{id:"wardrobe",group:"furniture",category:"wardrobe",w:180,h:60},{id:"kitchen_floor",group:"furniture",category:"kitchen_cabinet",w:60,h:60},{id:"kitchen_floor_corner",group:"furniture",category:"kitchen_cabinet",w:90,h:90},{id:"kitchen_wall",group:"furniture",category:"kitchen_cabinet",w:60,h:35},{id:"kitchen_wall_corner",group:"furniture",category:"kitchen_cabinet",w:60,h:60},{id:"shelf_floor",group:"furniture",category:"shelving",w:100,h:35},{id:"shelf_wall",group:"furniture",category:"shelving",w:100,h:25},{id:"cooktop_two",group:"appliance",category:"cooktop",w:30,h:50},{id:"stove",group:"appliance",category:"cooktop",w:60,h:60},{id:"tv",group:"appliance",category:"tv",w:120,h:28},{id:"tv_wall",group:"appliance",category:"tv",w:120,h:15},{id:"toilet",group:"sanitary",category:"toilet",w:40,h:70},{id:"toilet_built_in",group:"sanitary",category:"toilet",w:40,h:55},{id:"bathtub",group:"sanitary",category:"bathtub",w:170,h:75},{id:"bathtub_corner",group:"sanitary",category:"bathtub",w:140,h:140},{id:"bidet",group:"sanitary",category:"bidet",w:40,h:60},{id:"bidet_built_in",group:"sanitary",category:"bidet",w:40,h:50},{id:"kitchen_sink",group:"sanitary",category:"kitchen_sink",w:60,h:50},{id:"kitchen_sink_double",group:"sanitary",category:"kitchen_sink",w:90,h:50}].map(e=>({id:e.id,group:e.group,category:e.category,w:e.w,h:e.h,designer:!0})),...Dl.filter(e=>Al.has(e.id))],Fl=new Map(Pl.map(e=>[e.id,e]));function zl(e){return e&&Fl.get(e)||null}function Il(e){return!0===Fl.get(e)?.designer}function Ol(e){return Pl.filter(t=>t.group===e)}function El(e){const t=zl(e);return t?{w:t.w,h:t.h}:{w:60,h:60}}function Nl(e,t,i=Xa,n=1e3){const r=Number(t)>0?Number(t):5;return(Number(e)||0)/r*i/n}const Hl=5e-4,Ll=Ga;function Bl(e){return Number.isFinite(e)?Math.max(Hl,Math.min(Ll,e)):Hl}function ql(e){return Number.isFinite(e)?Math.max(1,Math.min(1e4,e)):1}const jl=e=>{const t=Math.round(1e3*e)/1e3;return Object.is(t,-0)?"0":String(t)};function Wl(e,t){const i=zl(e);if(!i)return null;if(i.designer)return Cl.art(e,t)??null;const n=function(e,t,i){if(!e.g)return"";const n=e=>jl(e*t),r=e=>jl(e*i),o=[];for(const s of e.g)if("r"===s[0]){const[,e,t,i,a]=s;o.push(`M${n(e)} ${r(t)}H${n(e+i)}V${r(t+a)}H${n(e)}Z`)}else if("l"===s[0]){const[,e,t,i,a]=s;o.push(`M${n(e)} ${r(t)}L${n(i)} ${r(a)}`)}else if("e"===s[0]){const[,e,a,l,c]=s;o.push(`M${n(e-l)} ${r(a)}A${jl(l*t)} ${jl(c*i)} 0 0 1 ${n(e+l)} ${r(a)}A${jl(l*t)} ${jl(c*i)} 0 0 1 ${n(e-l)} ${r(a)}Z`)}else{const e=s.slice(1);if(e.length<4)continue;let t=`M${n(e[0])} ${r(e[1])}`;for(let i=2;i+10?n:Number.isFinite(r)&&r>0?r:1,s=Number(t),a=o*(Number.isFinite(s)&&s>0?s:1);return Number.isFinite(a)&&a>0?a:o}function Vl(e,t,i,n,r){const o=e+i/2,s=t+n/2,a=(Number(r)||0)*Math.PI/180,l=Math.cos(a),c=Math.sin(a),h=(e,t)=>{const i=e-o,n=t-s;return[o+i*l-n*c,s+i*c+n*l]};return[h(e,t),h(e+i,t),h(e+i,t+n),h(e,t+n)]}function Gl(e,t,i,n,r,o,s){const a=Number.isFinite(s)&&s>0?s:1e-6,l=(Number(e.angle)||0)*Math.PI/180,c=Math.cos(l),h=Math.sin(l),d=-Math.sin(l),u=Math.cos(l),p=e.x+e.w/2,_=e.y+e.h/2,m=t>0?-e.w/2:t<0?e.w/2:0,g=i>0?-e.h/2:i<0?e.h/2:0,f=p+m*c+g*d,v=_+m*h+g*u,y=n-f,b=r-v,w=t?(y*c+b*h)*(t>0?1:-1):e.w,k=i?(y*d+b*u)*(i>0?1:-1):e.h;let x=t?Math.abs(w):e.w,S=i?Math.abs(k):e.h;if(o&&t&&i){const t=x/Math.max(e.w,a),i=S/Math.max(e.h,a),n=Math.abs(t-1)>=Math.abs(i-1)?t:i,r=Math.max(a/e.w,a/e.h),o=Math.max(r,Number.isFinite(n)?n:r);x=e.w*o,S=e.h*o}x=Math.max(a,Number.isFinite(x)?x:a),S=Math.max(a,Number.isFinite(S)?S:a);const $=!!t&&w<0,M=!!i&&k<0,R=t?(t>0?1:-1)*($?-1:1):0,C=i?(i>0?1:-1)*(M?-1:1):0,T=f+R*(x/2)*c+C*(S/2)*d,D=v+R*(x/2)*h+C*(S/2)*u,A=!!e.flip_h!==$,P=!!e.flip_v!==M;return{x:T-x/2,y:D-S/2,w:x,h:S,...Number(e.angle)?{angle:Number(e.angle)}:{},...A?{flip_h:!0}:{},...P?{flip_v:!0}:{}}}function Kl(e,t,i,n){let r=Number(e)+(Number(i)-Number(t));if([r,t,i].every(Number.isFinite)||(r=0),n){const e=r/45;r=45*(e<0?-Math.round(Math.abs(e)):Math.round(e))}return r=(r%360+360)%360,r>180?r-360:r}function Yl(e,t,i,n,r){const o=e.x*t,s=e.y*i,a=e.w*t,l=e.h*i,c=o+a/2,h=s+l/2,d=o+(e.flip_h?a:0),u=s+(e.flip_v?l:0),p=(e.flip_h?-1:1)*a/n,_=(e.flip_v?-1:1)*l/r,m=Number(e.angle)||0;return(m?`rotate(${m} ${c} ${h}) `:"")+`translate(${d} ${u}) scale(${p} ${_})`}function Xl(e,t,i,n=.1){if("string"==typeof e&&!e.trim())return null;const r=Number(e);if(!Number.isFinite(r)||0===r)return null;const o=r*(t?30.48:100),s=Math.abs(o);return si?null:o}function Zl(e,t,i){const n=Math.abs(Number(e))/(i?30.48:100),r=Number(n.toFixed(6));return String(t?-r:r)}const Jl=15e3,Ql=2e3,ec=new WeakMap;function tc(e,t){let i=ec.get(e);if(!i){const t=new Set;i={hiddenAt:"hidden"===e.visibilityState?Date.now():0,token:0,subscribers:t,onVisibility:()=>{const t=ec.get(e);if(!t)return;const i=Date.now();if("hidden"===e.visibilityState){t.hiddenAt||(t.hiddenAt=i);const e={kind:"hidden",token:t.token,at:i,hiddenFor:0,long:!1};for(const i of[...t.subscribers])i(e);return}const n=t.hiddenAt?Math.max(0,i-t.hiddenAt):0;t.hiddenAt=0,t.token++;const r={kind:"visible",token:t.token,at:i,hiddenFor:n,long:n>=Jl};for(const e of[...t.subscribers])e(r)},onPageShow:t=>{const i=ec.get(e);if(!i)return;const n=Date.now();i.token++;const r={kind:"pageshow",token:i.token,at:n,hiddenFor:0,long:!!t.persisted,persisted:!!t.persisted};for(const e of[...i.subscribers])e(r)}},ec.set(e,i),e.addEventListener("visibilitychange",i.onVisibility),e.defaultView?.addEventListener("pageshow",i.onPageShow)}return i.subscribers.add(t),()=>{const i=ec.get(e);i&&(i.subscribers.delete(t),i.subscribers.size||(e.removeEventListener("visibilitychange",i.onVisibility),e.defaultView?.removeEventListener("pageshow",i.onPageShow),ec.delete(e)))}}const ic={now:()=>Date.now(),setTimeout:(e,t)=>window.setTimeout(e,t),clearTimeout:e=>window.clearTimeout(e),requestAnimationFrame:e=>window.requestAnimationFrame(e),cancelAnimationFrame:e=>window.cancelAnimationFrame(e)};class nc{constructor(e,t=ic){this.onChange=e,this.clock=t,this._state="steady",this._token=0,this._frameFingerprint="",this._hasCompleteFrame=!1,this._overlayPhase="none",this._recoveryReason=null,this._overlayTimer=0,this._overlayRaf=0,this._overlayOpaqueAt=0,this._barrierRafs=new Set,this._trace=[],this._disposed=!1}get state(){return this._state}get token(){return this._token}get frameFingerprint(){return this._frameFingerprint}get hasCompleteFrame(){return this._hasCompleteFrame}get overlayPhase(){return this._overlayPhase}get overlayVisible(){return"none"!==this._overlayPhase}get overlayBlocksInteraction(){return this.overlayVisible}get recoveryReason(){return this._recoveryReason}get trace(){return this._trace.map(e=>({...e,...e.stage?{stage:[...e.stage]}:{}}))}note(e,t={}){this.record(e,void 0,t)}record(e,t,i={}){this._trace.push({at:this.clock.now(),token:this._token,event:e,state:this._state,...t?{reason:t}:{},...i}),this._trace.length>80&&this._trace.splice(0,this._trace.length-80)}changed(){this._disposed||this.onChange()}adoptCompleteFrame(e){e&&(this._hasCompleteFrame=!0,this._frameFingerprint=e,this._state="steady",this._recoveryReason=null,this.clearOverlay(),this.record("frame-adopted"),this.changed())}markCompleteFrame(e){e&&(this._hasCompleteFrame=!0,this._frameFingerprint=e,this._state="steady",this._recoveryReason=null,this.clearOverlay(),this.record("frame-complete"),this.changed())}refreshCompleteFrame(e){!this._disposed&&this._hasCompleteFrame&&"steady"===this._state&&e&&e!==this._frameFingerprint&&(this._frameFingerprint=e,this.record("frame-refreshed"))}visibility(e){return"hidden"===e.kind?(this.record("visibility-hidden"),this._token):e.long||"visible"!==e.kind&&"pageshow"!==e.kind?this.beginCandidate("pageshow"===e.kind?"pageshow":"long-resume"):(this.record("pageshow"===e.kind?"pageshow-noop":"visibility-visible-quick"),this._token)}beginCandidate(e,t="plan"){return this._token++,this._recoveryReason=t,this._hasCompleteFrame?(this._state="connection"===t?"offline-stale":"holding",this.clearOverlay()):this.overlayVisible?this._state="overlay-visible":(this._state="overlay-pending",this.scheduleOverlay(t)),this.record("candidate-start",e),this.changed(),this._token}connectionLost(){return this.beginCandidate("connection-lost","connection")}candidateReady(e){return!this._disposed&&e===this._token&&(this._state="candidate-ready",this.record("candidate-ready"),this.changed(),!0)}async commitAfterPaint(e,t){if(this._disposed||e!==this._token)return!1;let i=!0;const n=(async()=>{for(await t.updateComplete();i&&!this._disposed&&e===this._token;)if(t.stageValid()&&t.assetsReady()){if(await this.nextFrame(),e!==this._token||!t.stageValid()||!t.assetsReady())continue;if(await this.nextFrame(),e===this._token&&t.stageValid()&&t.assetsReady())return!0}else await this.nextFrame();return!1})();let r=0;const o=new Promise(e=>{r=this.clock.setTimeout(()=>e({ready:!1,timedOut:!0}),Ql)}),s=await Promise.race([n.then(e=>({ready:e,timedOut:!1})),o]);return i=!1,this.clock.clearTimeout(r),!this._disposed&&e===this._token&&(!(!s.ready&&!s.timedOut)&&(s.ready?(this._hasCompleteFrame=!0,this._frameFingerprint=t.frameFingerprint(),this.record("paint-barrier"),this.finishOverlayAfterCommit(),!0):(this.record("paint-barrier-timeout"),this._hasCompleteFrame?(this._state="connection"===this._recoveryReason?"offline-stale":"steady",this.clearOverlay()):(this._state="recovery-error","opaque"!==this._overlayPhase&&this.showOverlayNow()),this.changed(),!1)))}retry(e=this._recoveryReason||"plan"){return this.beginCandidate("retry",e)}nextFrame(){return new Promise(e=>{const t=this.clock.requestAnimationFrame(()=>{this._barrierRafs.delete(t),e()});this._barrierRafs.add(t)})}scheduleOverlay(e){this.clearOverlayTimer(),this._recoveryReason=e,this._overlayTimer=this.clock.setTimeout(()=>{this._overlayTimer=0,this._hasCompleteFrame||"overlay-pending"!==this._state&&"candidate-ready"!==this._state||(this._state="overlay-visible",this._overlayPhase="entering",this.record("overlay-enter"),this.changed(),this._overlayRaf=this.clock.requestAnimationFrame(()=>{this._overlayRaf=0,"entering"===this._overlayPhase&&(this._overlayPhase="fading-in",this.changed(),this._overlayTimer=this.clock.setTimeout(()=>{this._overlayTimer=0,"fading-in"===this._overlayPhase&&(this._overlayPhase="opaque",this._overlayOpaqueAt=this.clock.now(),this.record("overlay-opaque"),this.changed())},150))}))},150)}showOverlayNow(){this.clearOverlayTimer(),this._overlayPhase="opaque",this._overlayOpaqueAt=this.clock.now(),this.record("overlay-error")}finishOverlayAfterCommit(){if(this.clearOverlayTimer(),"none"===this._overlayPhase||"entering"===this._overlayPhase||"fading-in"===this._overlayPhase)return this.clearOverlay(),this._state="steady",this._recoveryReason=null,this.record("candidate-committed"),void this.changed();const e=Math.max(0,this._overlayOpaqueAt+250-this.clock.now());this._overlayTimer=this.clock.setTimeout(()=>{this._overlayTimer=0,this._overlayPhase="leaving",this.record("overlay-leave"),this.changed(),this._overlayTimer=this.clock.setTimeout(()=>{this._overlayTimer=0,this._overlayPhase="none",this._state="steady",this._recoveryReason=null,this.record("candidate-committed"),this.changed()},180)},e)}clearOverlayTimer(){this._overlayTimer&&this.clock.clearTimeout(this._overlayTimer),this._overlayTimer=0}clearOverlay(){this.clearOverlayTimer(),this._overlayRaf&&this.clock.cancelAnimationFrame(this._overlayRaf),this._overlayRaf=0,this._overlayPhase="none",this._overlayOpaqueAt=0}dispose(){this._disposed=!0,this._token++,this.clearOverlay();for(const e of this._barrierRafs)this.clock.cancelAnimationFrame(e);this._barrierRafs.clear()}}function rc(e){let t=2166136261,i=2654435769;const n=new WeakSet,r=e=>{for(let n=0;n>>0)+(i>>>2)}},o=e=>{if(null===e)return void r("n");const t=typeof e;if("string"===t)return void r(`s${e.length}:${e}`);if("number"===t)return void r(`d${Number.isNaN(e)?"NaN":String(e)}`);if("boolean"===t)return void r(e?"t":"f");if("undefined"===t)return void r("u");if("object"!==t)return void r(`${t}:${String(e)}`);const i=e;if(n.has(i))r("[cycle]");else{if(n.add(i),Array.isArray(e)){r("[");for(const t of e)o(t);return r("]"),void n.delete(i)}r("{");for(const t of Object.keys(e).sort())r(t),o(e[t]);r("}"),n.delete(i)}};return o(e),`${(t>>>0).toString(16).padStart(8,"0")}${(i>>>0).toString(16).padStart(8,"0")}`}function oc(e){return rc(e)}const sc=new WeakMap;class ac{constructor(e,t=()=>Date.now()){this.onUpdate=e,this.now=t,this.fallbackAuthority={},this.referenceOwner={},this.referenced=new Set,this.queued=new Set,this.disposed=!1,this.sharedUpdate=()=>{this.disposed||this.onUpdate()}}bind(e){const t=((e,t)=>{const i=e?.connection||e?.callWS||t;return!i||"object"!=typeof i&&"function"!=typeof i?t:i})(e,this.fallbackAuthority);return this.shared&&this.authority===t||(this.shared&&(this.shared.listeners.delete(this.sharedUpdate),this.shared.references.delete(this.referenceOwner)),this.authority=t,this.shared=(e=>{let t=sc.get(e);return t||(t={signed:{},queued:new Set,inFlight:new Map,retry:new Map,listeners:new Set,settlers:new Set,references:new Map},sc.set(e,t)),t})(t),this.disposed||(this.shared.listeners.add(this.sharedUpdate),this.shared.references.set(this.referenceOwner,new Set(this.referenced)))),this.shared}start(e,t){this.disposed=!1,this.referenced=new Set(t());const i=this.bind(e());i.listeners.add(this.sharedUpdate),i.references.set(this.referenceOwner,new Set(this.referenced)),this.stopTimer(),this.resignTimer=setInterval(()=>this.resign(e(),t()),288e5)}dispose(){if(this.disposed=!0,this.stopTimer(),clearTimeout(this.batchTimer),this.shared){this.shared.listeners.delete(this.sharedUpdate),this.shared.references.delete(this.referenceOwner);for(const e of this.queued)this.shared.queued.delete(e)}this.queued.clear()}invalidate(e){const t=this.bind(e);clearTimeout(this.batchTimer),this.queued.clear(),t.queued.clear(),t.inFlight.clear(),t.retry.clear(),t.signed={}}stopTimer(){void 0!==this.resignTimer&&clearInterval(this.resignTimer),this.resignTimer=void 0}display(e,t){const i=zn(t);if(!i.startsWith("/api/houseplan/content/"))return i;const n=this.bind(e);this.referenced.add(i),n.references.set(this.referenceOwner,new Set(this.referenced));const r=n.signed[i],o=r?this.now()-r.at:1/0;return o{const t=[...this.queued];this.queued.clear();for(const e of t)i.queued.delete(e);this.sign(e,t)},30))}sign(e,t){if(!t.length||!e?.callWS)return;const i=this.bind(e);for(const n of function(e,t){const i=Math.max(1,Math.floor(t)),n=[];for(let t=0;t{const n=i.inFlight.get(e);return!(void 0!==n&&t-n<15e3)&&(i.inFlight.set(e,t),!0)});r.length&&e.callWS({type:"houseplan/content/sign",paths:r}).then(e=>{const t=this.now();let n=0,o=!1;for(const s of r){const r=e?.urls?.[s];if("string"==typeof r&&r){const e=i.signed[s];e?.loaded&&e.url!==r?(e.pending={url:r,at:t},this.preloadReplacement(i,s,r,t)):(i.signed[s]={url:r,at:t,loaded:e?.url===r&&!!e.loaded},o=!0),i.retry.delete(s),n++}else this.backOff(i,s)}if(n&&(this.trimShared(i),o))for(const e of[...i.listeners])e()}).catch(()=>{for(const e of r)this.backOff(i,e)}).finally(()=>{for(const e of r)i.inFlight.get(e)===t&&i.inFlight.delete(e);for(const e of[...i.settlers])e()})}}preloadReplacement(e,t,i,n){const r=()=>{const r=e.signed[t];if(r?.pending?.url===i){e.signed[t]={url:i,at:n,loaded:!0},e.retry.delete(t),this.trimShared(e);for(const t of[...e.listeners])t()}},o=()=>{const n=e.signed[t];n?.pending?.url===i&&(delete n.pending,this.backOff(e,t))};if("undefined"==typeof Image)return void r();const s=new Image;s.onload=()=>{("function"==typeof s.decode?s.decode():Promise.resolve()).then(r).catch(o)},s.onerror=o,s.src=i}preloadCurrentImage(e,t,i){if(i.loaded)return Promise.resolve(!0);if(i.preload)return i.preload;if("undefined"==typeof Image)return i.loaded=!0,Promise.resolve(!0);const n=i.url;return i.preload=new Promise(r=>{const o=new Image;let s=!1;const a=o=>{if(s)return;s=!0,clearTimeout(l);const a=e.signed[t];if(a===i&&delete a.preload,o&&a===i&&a.url===n){a.loaded=!0;for(const t of[...e.listeners])t();r(!0)}else o||a!==i||this.backOff(e,t),r(!1)};o.onload=()=>{("function"==typeof o.decode?o.decode():Promise.resolve()).then(()=>a(!0)).catch(()=>a(!1))},o.onerror=()=>a(!1);const l=setTimeout(()=>a(!1),Ql);o.src=n}),i.preload}prepareImage(e,t){const i=zn(t);if(!i.startsWith("/api/houseplan/content/"))return Promise.resolve(!0);const n=this.bind(e),r=()=>{const t=n.signed[i];if(t&&this.now()-t.atthis.now()&&!n.inFlight.has(i)&&!n.queued.has(i)?Promise.resolve(!1):null},o=r();return o?(s=o,new Promise(e=>{let t=!1;const i=i=>{t||(t=!0,clearTimeout(n),e(i))},n=setTimeout(()=>i(!1),Ql);s.then(i).catch(()=>i(!1))})):new Promise(e=>{let t=!1,i=null;const o=i=>{t||(t=!0,clearTimeout(a),n.settlers.delete(s),e(i))},s=()=>{t||i||(i=r(),i&&i.then(o).catch(()=>o(!1)))},a=setTimeout(()=>o(!1),Ql);n.settlers.add(s),s()});var s}backOff(e,t){const i=e.retry.get(t)?.delay||0,n=Math.min(6e4,i?2*i:2e3);e.retry.set(t,{notBefore:this.now()+n,delay:n})}trimShared(e){const t=Object.entries(e.signed);if(t.length<=512)return;const i=new Set(e.inFlight.keys());for(const t of e.references.values())for(const e of t)i.add(e);for(const[e,n]of t)(n.pending||n.preload)&&i.add(e);t.sort((e,t)=>t[1].at-e[1].at);const n=t.filter(([e])=>i.has(e));for(const e of t){if(n.length>=512)break;i.has(e[0])||n.push(e)}e.signed=Object.fromEntries(n)}resign(e,t){const i=this.bind(e);this.referenced=new Set(t),i.references.set(this.referenceOwner,new Set(this.referenced));const n=this.now(),r=new Set;for(const e of i.references.values())for(const t of e)r.add(t);const o={};for(const[e,t]of Object.entries(i.signed))r.has(e)&&n-t.at!!o[e]&&!o[e].pending))}markLoaded(e,t,i){const n=zn(t);if(!n.startsWith("/api/houseplan/content/"))return;const r=this.bind(e).signed[n];if(r&&(!i||r.url===i)&&!r.loaded){r.loaded=!0;for(const t of[...this.bind(e).listeners])t()}}isReady(e,t){const i=zn(t);if(!i.startsWith("/api/houseplan/content/"))return!0;const n=this.bind(e).signed[i];return!!n&&this.now()-n.ate.id===t)}function cc(e,t){return{id:e,title:t,plan_url:null,view_box:[0,0,1,1],rooms:[],wall_segments:[]}}function hc(e="file"){const t="draw"===e;return{source:e,showBorders:t,showNames:t,displayTouched:!1}}function dc(e,t){if(e.displayTouched)return{...e,source:t};const i="draw"===t;return{...e,source:t,showBorders:i,showNames:i}}function uc(e,t,i){return{...e,[t]:i,displayTouched:!0}}function pc(e){const t=String(e??"").trim().replace(",",".");if(!/^[+-]?(?:\d+(?:\.\d*)?|\.\d+)$/.test(t))return null;const i=Number(t);return Number.isFinite(i)?i:null}function _c(e,t){const i=e=>{if(""===String(e??"").trim())return{valid:!0,value:null};const t=pc(e);return{valid:null!==t,value:t}},n=i(e),r=i(t);return n.valid&&r.valid?null!==n.value&&null!==r.value&&n.value>r.value?{valid:!0,min:r.value,max:n.value}:{valid:!0,min:n.value,max:r.value}:{valid:!1,min:n.value,max:r.value}}function mc(e,t,i,n,r,o){const s=_c(n,r);return ln(e,t,o&&s.valid?{settings:{...i.settings||{},temp_min:s.min,temp_max:s.max}}:i)}function gc(e){const t=e=>"number"==typeof e&&Number.isFinite(e)?String(e):"";return[t(e?.temp_min),t(e?.temp_max)]}function fc(e,t,i){const n=_c(t,i);return!!n.valid&&(null===n.min?delete e.temp_min:e.temp_min=n.min,null===n.max?delete e.temp_max:e.temp_max=n.max,!0)}var vc="M11,18H13V16H11V18M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M12,20C7.59,20 4,16.41 4,12C4,7.59 7.59,4 12,4C16.41,4 20,7.59 20,12C20,16.41 16.41,20 12,20M12,6A4,4 0 0,0 8,10H10A2,2 0 0,1 12,8A2,2 0 0,1 14,10C14,12 11,11.75 11,15H13C13,12.75 16,12.5 16,10A4,4 0 0,0 12,6Z";function yc(e,t,i){return[e[0]*t+e[1]*i+e[2],e[3]*t+e[4]*i+e[5]]}function bc(e,t){let i=0;for(const[n,r]of t){const t=yc(e,n[0],n[1]);i=Math.max(i,Math.hypot(t[0]-r[0],t[1]-r[1]))}return i}const wc=e=>{if(null==e||""===e)return null;const t=Number(e);return Number.isFinite(t)?t:null},kc=e=>{const t=e,i=wc(Array.isArray(t)?t[0]:t?.x),n=wc(Array.isArray(t)?t[1]:t?.y);return null==i||null==n?null:[i,n]};function xc(e){if(!Array.isArray(e))return null;const t=[];for(const i of e){const e=kc(i);if(!e)return null;t.push(e)}if(t.length>1){const e=t[0],i=t[t.length-1];e[0]===i[0]&&e[1]===i[1]&&t.pop()}if(t.length<3)return null;let i=0,n=0,r=0;for(let e=0;ee+t[0],0)/t.length,t.reduce((e,t)=>e+t[1],0)/t.length]:[n/(3*i),r/(3*i)]}function Sc(e){if(!Array.isArray(e))return null;const t=[];for(const i of e){const e=kc(i);if(!e)return null;t.push(e)}if(t.length>1){const e=t[0],i=t[t.length-1];e[0]===i[0]&&e[1]===i[1]&&t.pop()}const i=xc(t);if(!i)return null;const n=t.map(e=>e[0]),r=t.map(e=>e[1]);return{centroid:i,bbox:[Math.min(...n),Math.min(...r),Math.max(...n),Math.max(...r)]}}function $c(e){let t=e;if(t&&"object"==typeof t&&!Array.isArray(t)){const e=t;t=e.path??e.points??t}if(!Array.isArray(t)||!t.length)return[];let i=(t.some(e=>(e=>Array.isArray(e)?e.length>=2&&!Array.isArray(e[0])&&("object"!=typeof e[0]||null==e[0]):!!e&&"object"==typeof e&&("x"in e||"y"in e))(e))?[t]:t.filter(Array.isArray)).map(e=>e.map(kc).filter(e=>null!=e)).filter(e=>e.length>=2);i.length>64&&(i=i.slice(-64));const n=i.reduce((e,t)=>e+t.length,0);if(n<=4e3)return i.map(e=>e.slice());const r=4e3-2*i.length,o=i.map(e=>e.length-2),s=o.reduce((e,t)=>e+t,0),a=o.map(e=>r*e/s),l=a.map(Math.floor);let c=r-l.reduce((e,t)=>e+t,0);const h=a.map((e,t)=>({index:t,fraction:e-Math.floor(e)})).sort((e,t)=>t.fraction-e.fraction||e.index-t.index);for(let e=0;efunction(e,t){if(t>=e.length)return e.slice();if(t<=2)return[e[0],e[e.length-1]];const i=[];for(let n=0;ne.slice()),i=t[t.length-1];return i?(i.length>2?i.pop():t.pop(),t):[]}const Cc=e=>Number.isFinite(e[0])&&Number.isFinite(e[1]),Tc=(e,t)=>e[0]===t[0]&&e[1]===t[1];function Dc(e){if(!e)return null;const t=e.vacuum_position||e.robot_position||null,i=t&&null!=wc(t.x)&&null!=wc(t.y)?{x:wc(t.x),y:wc(t.y),a:wc(t.a??t.angle??t.theta)}:null,n=$c(e.path?.path??e.path?.points??e.path),r=[],o=e.rooms,s=Array.isArray(o)?o.map((e,t)=>[String(e?.id??t),e]):o&&"object"==typeof o?Object.entries(o):[];for(const[e,t]of s){if(!t||"object"!=typeof t)continue;const i=String(t.name??t.label??"").trim(),n=[[wc(t.cx),wc(t.cy)],[wc(t.center?.x),wc(t.center?.y)],[wc(t.x),wc(t.y)]].find(([e,t])=>null!=e&&null!=t);let o=n?.[0]??null,s=n?.[1]??null;const a=Sc(t.outline),l=wc(t.x0),c=wc(t.y0),h=wc(t.x1),d=wc(t.y1),u=(null!=l&&null!=c&&null!=h&&null!=d?[Math.min(l,h),Math.min(c,d),Math.max(l,h),Math.max(c,d)]:null)||a?.bbox||null;if(null!=o&&null!=s||!a||([o,s]=a.centroid),null!=o&&null!=s||!u||(o=(u[0]+u[2])/2,s=(u[1]+u[3])/2),i&&null!=o&&null!=s){const t={id:e,name:i,cx:o,cy:s};u&&([t.x0,t.y0,t.x1,t.y1]=u),r.push(t)}}const a=function(e){return String(e.map_name??e.current_map??e.map_index??e.selected_map??"default")}(e);return i||r.length||n.length?{pos:i,path:n,rooms:r,mapId:a}:null}function Ac(e,t,i){return![e,t,i].every(Number.isFinite)||e<0||t<=0||i<=0?Number.POSITIVE_INFINITY:e/t*i}const Pc=40;function Fc(e,t,i){if(!e||!t)return null;const n=t.attributes||{},r=e.split(".")[0]||"",o=null!=i?.platform?String(i.platform):null,s=!!kc(n.vacuum_position??n.robot_position),a=!(!n.rooms||"object"!=typeof n.rooms),l=$c(n.path?.path??n.path?.points??n.path).length>0,c=[n.map_name,n.current_map,n.map_index,n.selected_map].some(e=>null!=e),h="xiaomi_cloud_map_extractor"===o,d=a||l||c;let u=null;if(s?u="compatible":h?u="known_xcme_incomplete":d?u="partial":"camera"===r&&(u="camera"),!u)return null;const p=s?"camera"===r?300:200:h?100:d?50:0;return{entityId:e,name:String(n.friendly_name||e),platform:o,category:u,hasPosition:s,hasRooms:a,hasPath:l,hasMapId:c,score:p}}const zc=e=>e.toLowerCase().replace(/[\s_\-.,]+/g,"");function Ic(e,t){const i=new Set(t.map(zc).filter(Boolean)),n=new Set;for(const t of e){const e=zc(t.name||"");e&&i.has(e)&&n.add(e)}return n.size}function Oc(e,t){const i=new Map(t.map(e=>[zc(e.name),e])),n=[],r=[];for(const t of e){const e=i.get(zc(t.name));e&&(n.push([[t.cx,t.cy],[e.cx,e.cy]]),r.push(t.name))}if(n.length<3)return null;const o=function(e){if(e.length<3)return null;let t=0,i=0,n=0,r=0,o=0,s=0,a=0,l=0,c=0,h=0,d=0,u=0;for(const[[p,_],[m,g]]of e){if(![p,_,m,g].every(Number.isFinite))return null;t+=p*p,i+=p*_,n+=p,r+=_*_,o+=_,s+=1,a+=p*m,l+=_*m,c+=m,h+=p*g,d+=_*g,u+=g}const p=[t,i,n,i,r,o,n,o,s],_=e=>{const[t,i,n,r,o,s,a,l,c]=p,h=t*(o*c-s*l)-i*(r*c-s*a)+n*(r*l-o*a);if(!Number.isFinite(h)||Math.abs(h)<1e-9)return null;const d=[(o*c-s*l)/h,(n*l-i*c)/h,(i*s-n*o)/h,(s*a-r*c)/h,(t*c-n*a)/h,(n*r-t*s)/h,(r*l-o*a)/h,(i*a-t*l)/h,(t*o-i*r)/h];return[d[0]*e[0]+d[1]*e[1]+d[2]*e[2],d[3]*e[0]+d[4]*e[1]+d[5]*e[2],d[6]*e[0]+d[7]*e[1]+d[8]*e[2]]},m=_([a,l,c]),g=_([h,d,u]);if(!m||!g)return null;const f=[m[0],m[1],m[2],g[0],g[1],g[2]];return f.every(Number.isFinite)?f:null}(n);return o?{matrix:o,matched:r,residual:bc(o,n)}:null}function Ec(e,t,i){const n=e[e.length-1];if(n&&n[0]===t[0]&&n[1]===t[1])return e;if(e.push(t),e.length<=600)return e;let r=function(e,t){if(e.length<3)return e.slice();const i=new Uint8Array(e.length);i[0]=i[e.length-1]=1;const n=[[0,e.length-1]];for(;n.length;){const[r,o]=n.pop(),[s,a]=e[r],[l,c]=e[o],h=l-s,d=c-a,u=Math.hypot(h,d)||1e-9;let p=0,_=-1;for(let t=r+1;tp&&(p=i,_=t)}_>0&&p>t&&(i[_]=1,n.push([r,_],[_,o]))}const r=[];for(let t=0;t600&&(r=r.filter((e,t)=>t%2==0||t===r.length-1)),r}function Nc(e){return"cleaning"===e||"returning"===e||"on"===e}const Hc={0:[1,0],90:[0,1],180:[-1,0],270:[0,-1]};function Lc(e){const[t,i]=Hc[e.rot]||[1,0],n=e.mir?-1:1;return[e.s*t*n,-e.s*i,e.ox,e.s*i*n,e.s*t,e.oy]}function Bc(e){const t=e[0]*e[4]-e[1]*e[3];if(!Number.isFinite(t)||Math.abs(t)<1e-12)return null;const i=t<0,n=Math.sqrt(Math.abs(t));let r=180*Math.atan2(-e[1],e[4])/Math.PI;return r=(90*Math.round(r/90)%360+360)%360,{ox:e[2],oy:e[5],s:n,rot:r,mir:i}}function qc(e,t){const i=[],n=[];for(const t of e)null!=t.x0?(i.push(t.x0,t.x1),n.push(t.y0,t.y1)):(i.push(t.cx),n.push(t.cy));if(!i.length)return{ox:t[0]+t[2]/2,oy:t[1]+t[3]/2,s:t[2]/1e4,rot:0,mir:!0};const r=Math.min(...i),o=Math.max(...i),s=Math.min(...n),a=Math.max(...n),l=Math.max(o-r,a-s)||1,c={ox:0,oy:0,s:.6*Math.min(t[2],t[3])/l,rot:0,mir:!0},h=Lc(c),[d,u]=yc(h,(r+o)/2,(s+a)/2);return c.ox=t[0]+t[2]/2-d,c.oy=t[1]+t[3]/2-u,c}function jc(e,t,i,n){const[r,o]=yc(Lc(t),i,n),s=Lc({...e,ox:0,oy:0}),[a,l]=yc(s,i,n);return{...e,ox:r-a,oy:o-l}}function Wc(e){const t=e?.trail_mode;return"never"===t||"cleaning"===t||"always"===t?t:!1===e?.trail?"never":"cleaning"}const Uc=e=>"number"==typeof e&&Number.isFinite(e);function Vc(e){return Array.isArray(e)&&6===e.length&&e.every(Uc)?[e[0],e[1],e[2],e[3],e[4],e[5]]:null}function Gc(e,t,i){return"legacy:"+e+" "+t+" "+i}function Kc(e,t,i,n){const r=t?.map_routes;if(Array.isArray(r))return r.filter(e=>e&&"string"==typeof e.id&&e.id).map(e=>({id:e.id,source:String(e.source??""),map_id:String(e.map_id??""),space:String(e.space??""),calibration:Vc(e.calibration)}));const o="string"==typeof t?.source&&t.source?t.source:n||"";if(!o)return[];const s=t?.calibration;if(!s||"object"!=typeof s)return[];const a=[];for(const t of Object.keys(s)){const n=Vc(s[t]);n&&a.push({id:Gc(e,o,t),source:o,map_id:t,space:i,calibration:n})}return a}const Yc=(e,t)=>e instanceof Map?e.get(t):e?.[t];function Xc(e){const t=[];let i=!1,n="",r="";for(const o of e.routes){const s=Yc(e.observed,o.source);void 0!==s&&(i=!0,n||(n=o.source,r=s),s===o.map_id&&t.push(o))}if(t.length>1)return{kind:"ambiguous",routeIds:t.map(e=>e.id).sort()};if(1===t.length){const i=t[0];if(e.spaceIds&&!e.spaceIds.has(i.space))return{kind:"missing_space",route:i};const n=Vc(i.calibration);return n?{kind:"ready",route:{...i,calibration:n}}:{kind:"needs_calibration",route:i}}if(i)return{kind:"unmapped",source:n,mapId:r};const o=e.observed instanceof Map?[...e.observed.entries()]:Object.entries(e.observed||{});if(o.length){const e=o.slice().sort((e,t)=>e[0].localeCompare(t[0]))[0];return{kind:"unmapped",source:e[0],mapId:e[1]}}return{kind:"none"}}function Zc(e,t,i){const n=new Set;for(const t of e)t.source&&n.add(t.source);for(const e of t)e&&n.add(e);const r={};for(const e of[...n].sort()){const t=i(e);void 0!==t&&(r[e]=t)}return r}function Jc(e,t,i){if(!e)return null;const n="string"==typeof e.route_id?e.route_id:"";if(n)return t.find(e=>e.id===n)||null;const r=function(e,t,i){if(!e||"string"!=typeof e.map_id)return{kind:"orphan_run"};const n=e.map_id,r="string"==typeof i?i:"";let o=t.filter(e=>e.map_id===n);return r&&(o=o.filter(e=>e.source===r)),1===o.length?{kind:"adopted",route:o[0]}:0===o.length?{kind:"orphan_run"}:{kind:"ambiguous_run",routeIds:o.map(e=>e.id).sort()}}(e,t,i);return"adopted"===r.kind?r.route:null}function Qc(e){const t="ready"===e.resolution.kind?e.resolution.route:null,i=t&&t.space===e.renderSpace?Vc(t.calibration):null,n=Jc(e.serverCurrent,e.routes,e.rootSource),r=!!t&&!!n&&n.id===t.id,o=Jc(e.serverPrevious,e.routes,e.rootSource);return{live:i,currentRunMatches:r,previous:!!o&&o.space===e.renderSpace&&(e.explicitRoutes||!!t&&o.id===t.id)?Vc(o.calibration):null}}const eh={availability:"available",status:"alarm",activity:"none"},th=new Set(["motion","vibration","sound"]),ih=new Set(["occupancy","presence"]),nh=new Set(["door","window","garage_door","opening"]),rh=new Set(["running","power"]),oh=new Set(["smoke","gas","carbon_monoxide","moisture","safety","tamper","problem"]);const sh=new Set(["running","working","washing","rinsing","spinning","drying","heating","cooling","cleaning","cooking","playing","recording","pumping","irrigating","humidifying","dehumidifying","fan","preheating","defrosting"]),ah=new Set([...sh,"start","started","run","active","in_progress","wash","rinse","spin","dry"]),lh=new Set(["off","idle","paused","standby","docked","finished","complete","completed","stopped","ready","sleeping","stop","end","done","inactive"]),ch=new Set(["heat","cool","heat_cool","auto","dry","fan_only"]),hh=e=>""===e||"unknown"===e||"unavailable"===e||"__missing__"===e,dh=e=>String(e??"").trim().toLowerCase(),uh=e=>dh(e).replace(/[\s-]+/g,"_").replace(/_+/g,"_").replace(/^_|_$/g,""),ph=new Map([["run_state",0],["job_state",0],["operation_state",0],["activity_state",0],["machine_state",1],["running_state",1],["status",2],["device_status",2],["machine_status",2]]),_h=new Set(["wifi","connection","signal","battery"]);function mh(e,t){const i=e?.entities?.[t]||{};if("config"===i.entity_category)return null;const n=String(t||"").split(".").slice(1).join("."),r=[i.translation_key,i.original_name,i.name],o=[...r,n];r.some(e=>dh(e))||o.push(e?.states?.[t]?.attributes?.friendly_name);const s=o.map(uh).filter(Boolean);if(s.some(e=>e.split("_").some(e=>_h.has(e))))return null;let a=null;for(const e of s)for(const[t,i]of ph)(e===t||e.endsWith(`_${t}`))&&(a=null==a?i:Math.min(a,i));return a}const gh=(e,t)=>null!=mh(e,t);function fh(e,t){if(!t.startsWith("switch."))return!1;const i=e?.entities?.[t]||{},n=e?.states?.[t],r=t.slice(7).toLowerCase();if(/(?:^|_)(?:main_)?power$/.test(r))return!0;if([i.translation_key,i.original_name,i.name].map(dh).some(e=>["power","main power","power switch","питание"].includes(e)))return!0;const o=dh(n?.attributes?.friendly_name);return/(?:^|[\s._-])(?:main[\s._-]+)?power$/.test(o)||/(?:^|[\s._-])питание$/.test(o)}function vh(e){for(const t of["hvac_action","action","current_operation","run_state","job_state","operation","activity"]){const i=dh(e?.[t]);if(sh.has(i)||lh.has(i))return i}return""}function yh(e,t){const i=e?.states?.[t],n=i?dh(i.state):"__missing__",r=String(t||"").split(".")[0],o=dh(i?.attributes?.device_class),s={eid:t,state:n,availability:hh(n)?"unavailable":"available",status:"neutral",activity:"none",edge:"none"};if("unavailable"===s.availability)return s;if(function(e,t,i){return"alarm_control_panel"===e?"triggered"===i:"on"===i&&Wn(e,t)}(r,o,n))return{...s,status:"alarm"};if("binary_sensor"===r)return th.has(o)?{...s,edge:"rising"}:ih.has(o)?{...s,activity:"on"===n?"presence":"none"}:nh.has(o)?{...s,status:"on"===n?"open":"neutral",edge:"rising"}:"moving"===o?{...s,activity:"on"===n?"transition":"none"}:rh.has(o)&&"on"===n?{...s,status:"working",activity:"running"}:s;if("cover"===r)return{...s,activity:"opening"===n||"closing"===n?"transition":"none",edge:"terminal_transition"};if("lock"===r)return{...s,status:"unlocked"===n||"open"===n?"open":"neutral",activity:"locking"===n||"unlocking"===n?"transition":"none",edge:"terminal_transition"};if("valve"===r)return{...s,status:["open","opening","closing"].includes(n)?"open":"neutral",activity:"opening"===n||"closing"===n?"transition":"none",edge:"terminal_transition"};if("climate"===r){const e=vh(i.attributes),t=Array.isArray(i.attributes?.hvac_modes)?i.attributes.hvac_modes.map(dh):[],r=!lh.has(n)&&(ch.has(n)||sh.has(n)||t.includes(n));return(e?sh.has(e):r)?{...s,status:"working",activity:"running"}:s}if(["light","switch","fan","humidifier"].includes(r))return"on"===n?{...s,status:"working",activity:"running"}:s;if("media_player"===r)return"off"===n?{...s,availability:"unavailable"}:s;if("vacuum"===r)return"cleaning"===n?{...s,status:"working",activity:"running"}:"returning"===n?{...s,status:"working",activity:"transition"}:s;if("script"===r)return"on"===n?{...s,status:"working",activity:"running"}:s;if("automation"===r)return s;if("button"===r||"event"===r)return{...s,edge:"change"};const a=vh(i.attributes);return sh.has(a)||sh.has(n)&&!lh.has(n)?{...s,status:"working",activity:"running"}:s}function bh(e,t,i){const n=i.filter(t=>t.startsWith("switch.")&&!e?.entities?.[t]?.entity_category),r=t.find(t=>fh(e,t));if(!(n.length>1&&!!r))return t.map(t=>yh(e,t));const o=t.find(t=>t!==r&&gh(e,t)),s=yh(e,r);return"unavailable"===s.availability||"off"===s.state?t.map(t=>({eid:t,state:e?.states?.[t]?dh(e.states[t].state):"__missing__",availability:"unavailable",status:"neutral",activity:"none",edge:"none"})):t.map(t=>{if(t===o)return function(e,t){const i=e?.states?.[t],n=i?dh(i.state):"__missing__",r={eid:t,state:n,availability:hh(n)?"unavailable":"available",status:"neutral",activity:"none",edge:"none"};if("unavailable"===r.availability)return r;const o=vh(i?.attributes);return sh.has(o)||ah.has(n)&&!lh.has(n)?{...r,status:"working",activity:"running"}:r}(e,t);return{...t===r?s:yh(e,t),status:"neutral",activity:"none",edge:"none"}})}function wh(e){if(!e.length)return{availability:"available",status:"neutral",activity:"none"};const t=e.filter(e=>"available"===e.availability);if(!t.length)return{availability:"unavailable",status:"neutral",activity:"none"};if(t.some(e=>"alarm"===e.status))return eh;const i=t.some(e=>"working"===e.status)?"working":t.some(e=>"open"===e.status)?"open":"neutral",n=t.some(e=>"transition"===e.activity)?"transition":t.some(e=>"presence"===e.activity)?"presence":t.some(e=>"running"===e.activity)?"running":"none";return{availability:"available",status:i,activity:n}}function kh(e,t){if(!(e=>!!e&&!hh(e))(e)||"unavailable"===t.availability||e===t.state)return null;if("rising"===t.edge)return"off"===e&&"on"===t.state?"event":null;if("change"===t.edge)return"event";if("terminal_transition"===t.edge){const i=new Set([e,t.state]);if(i.has("closed")&&i.has("open")||i.has("locked")&&i.has("unlocked"))return"transition"}return null}const xh=(e,t=0)=>{const i=Number(e);return Number.isInteger(i)&&i>=0?i:t},Sh=(e,t)=>{const i={rev:0,configRev:xh(t),off:new Set};if(null==e)return{snapshot:i,valid:!1};const n=e.off;return!Number.isInteger(e.rev)||Number(e.rev)<0||!Number.isInteger(e.config_rev)||Number(e.config_rev)<0||!Array.isArray(n)||n.some(e=>"string"!=typeof e||!e)?{snapshot:i,valid:!1}:{snapshot:{rev:Number(e.rev),configRev:Number(e.config_rev),off:new Set(n)},valid:!0}};function $h(e,t=0){return Sh(e,t).snapshot}function Mh(e,t,i,n){const r=Sh(t,i);return n&&r.valid&&r.snapshot.configRev===i?e.configRev===i&&r.snapshot.rev{try{const[i,n]=await Promise.all([e.callWS({type:"config/device_registry/list"}),e.callWS({type:"config/entity_registry/list"})]),r=Eh(i,"id"),o=Eh(n,"entity_id");if(!r||!o)throw new Error("invalid_registry_response");t.devices=r,t.entities=o,t.authoritative=!0,t.access="full",t.lastSuccess=Date.now(),t.error=void 0}catch(e){t.authoritative=!1,t.access="limited",t.error=function(e){if(e&&"object"==typeof e){const t=e;return String(t.message||t.code||t.error||"registry_unavailable")}return String(e||"registry_unavailable")}(e)}finally{t.revision++,t.loading=void 0,function(e){for(const t of[...e.listeners])try{t()}catch{}}(t)}})()),t.loading}function Hh(e,t){void 0===t.reloadTimer&&(t.reloadTimer=globalThis.setTimeout(()=>{t.reloadTimer=void 0,Nh(e,t)},80))}async function Lh(e,t){if(t.subscribing||t.unsubDevice&&t.unsubEntity)return t.subscribing;const i=e?.connection?.subscribeEvents;return"function"==typeof i?(t.subscribing=(async()=>{try{t.unsubDevice||(t.unsubDevice=await i.call(e.connection,()=>Hh(e,t),"device_registry_updated")),t.unsubEntity||(t.unsubEntity=await i.call(e.connection,()=>Hh(e,t),"entity_registry_updated"))}catch{}finally{0===t.refs&&(t.unsubDevice?.(),t.unsubEntity?.(),t.unsubDevice=void 0,t.unsubEntity=void 0),t.subscribing=void 0}})(),t.subscribing):void 0}function Bh(e,t){const i=Oh(e);if(!i)return()=>{};const n=0===i.refs;i.refs++,i.listeners.add(t),("pending"===i.access||n)&&Nh(e,i),Lh(e,i);let r=!1;return()=>{r||(r=!0,i.listeners.delete(t),i.refs=Math.max(0,i.refs-1),i.refs>0||(i.unsubDevice?.(),i.unsubEntity?.(),i.unsubDevice=void 0,i.unsubEntity=void 0,void 0!==i.reloadTimer&&globalThis.clearTimeout(i.reloadTimer),i.reloadTimer=void 0))}}function qh(e){const t=Oh(e);t&&(Hh(e,t),Lh(e,t))}function jh(e){const t=Oh(e);if(!t)return{revision:0,authoritative:!1,access:"limited",devices:e?.devices||{},entities:e?.entities||{},lastSuccess:0,error:"registry_unavailable"};let i=e?.devices||{},n=e?.entities||{};if(t.authoritative){const r=t.liveDevices!==i||t.liveEntities!==n,o=void 0!==t.liveDevices||void 0!==t.liveEntities;if(r&&(t.liveDevices=i,t.liveEntities=n,t.projectedRevision=void 0,o&&Hh(e,t)),t.projectedRevision!==t.revision||!t.projectedDevices||!t.projectedEntities){const e={...t.devices},r={...t.entities};for(const[t,n]of Object.entries(i))Object.prototype.hasOwnProperty.call(e,t)||(e[t]=n);for(const[e,t]of Object.entries(n))Object.prototype.hasOwnProperty.call(r,e)||(r[e]=t);t.projectedDevices=e,t.projectedEntities=r,t.projectedRevision=t.revision}i=t.projectedDevices,n=t.projectedEntities}return{revision:t.revision,authoritative:t.authoritative,access:t.access,devices:i,entities:n,lastSuccess:t.lastSuccess,error:t.error}}function Wh(e){if(!e||"object"!=typeof e&&"function"!=typeof e)return 0;let t=Ph.get(e);return t||(t=Fh++,Ph.set(e,t)),t}function Uh(e,t=jh(e)){return[t.revision,t.access,Wh(t.devices),Wh(t.entities)].join(":")}function Vh(e){return!!e&&null==e.disabled_by}function Gh(e,t=jh(e)){const i={},n={},r={};for(const[e,n]of Object.entries(t.devices||{}))Vh(n)&&(i[e]=n);for(const[e,i]of Object.entries(t.entities||{})){if(!Vh(i))continue;const r=i.device_id?t.devices?.[i.device_id]:null;t.authoritative&&i.device_id&&!r||(r&&!Vh(r)||(n[e]=i))}for(const[i,n]of Object.entries(e?.states||{})){const e=t.entities?.[i];if(e&&!Vh(e))continue;const o=e?.device_id?t.devices?.[e.device_id]:null;t.authoritative&&e?.device_id&&!o||(o&&!Vh(o)||(r[i]=n))}return{...e,devices:i,entities:n,states:r}}function Kh(e,t=jh(e)){return{...e,devices:t.devices||{},entities:t.entities||{}}}function Yh(e,t){const i=[];for(const[n,r]of Object.entries(e||{}))r?.device_id===t&&i.push(n);return i}function Xh(){if(Ih)return Ih;if("undefined"==typeof localStorage)return{};try{const e=JSON.parse(localStorage.getItem(zh)||"{}");if(!e||"object"!=typeof e||Array.isArray(e))return{};const t=Date.now(),i={};for(const[n,r]of Object.entries(e))!r||"active"!==r.kind&&"ha_disabled"!==r.kind||!Number.isFinite(r.ts)||t-r.ts>7776e6||(i[n]=r);return Ih=i,Ih}catch{return{}}}function Zh(e,t,i=jh(e)){if(!t||"virtual"===t)return{kind:"active",enabledEntityIds:[],allEntityIds:[]};const n=t.indexOf(":");if(n<1)return{kind:"unverified",reason:"registry_unavailable",enabledEntityIds:[],allEntityIds:[]};const r=t.slice(0,n),o=t.slice(n+1);if("device"!==r&&"entity"!==r||!o)return{kind:"unverified",reason:"registry_unavailable",enabledEntityIds:[],allEntityIds:[]};const s=i.devices||{},a=i.entities||{};if(i.authoritative){if("device"===r){const e=s[o];if(!e)return{kind:"orphaned",reason:"device_missing",enabledEntityIds:[],allEntityIds:[]};const t=Yh(a,o);if(!Vh(e))return{kind:"ha_disabled",reason:"device",enabledEntityIds:[],allEntityIds:t};const i=t.filter(e=>Vh(a[e]));return t.length&&!i.length?{kind:"ha_disabled",reason:"all_entities",enabledEntityIds:[],allEntityIds:t}:{kind:"active",enabledEntityIds:i,allEntityIds:t}}const t=a[o];return t&&!Vh(t)?{kind:"ha_disabled",reason:"entity",enabledEntityIds:[],allEntityIds:[o]}:t?.device_id&&!s[t.device_id]?{kind:"orphaned",reason:"device_missing",enabledEntityIds:[],allEntityIds:[o]}:t?.device_id&&!Vh(s[t.device_id])?{kind:"ha_disabled",reason:"device",enabledEntityIds:[],allEntityIds:[o]}:t||e?.states?.[o]?{kind:"active",enabledEntityIds:[o],allEntityIds:[o]}:{kind:"orphaned",reason:"entity_missing",enabledEntityIds:[],allEntityIds:[]}}const l=function(e){return Xh()[e]||null}(t);if("device"===r){const t=s[o],i=Yh(a,o);if(null!=t?.disabled_by)return{kind:"ha_disabled",reason:"device",enabledEntityIds:[],allEntityIds:i};const n=i.filter(e=>{const t=a[e];return null==t?.disabled_by&&(!t.device_id||null==s[t.device_id]?.disabled_by)});if(i.length&&!n.length&&i.every(e=>null!=a[e]?.disabled_by))return{kind:"ha_disabled",reason:"all_entities",enabledEntityIds:[],allEntityIds:i};if("ha_disabled"===l?.kind)return{kind:"ha_disabled",reason:l.reason||"device",enabledEntityIds:[],allEntityIds:i};if(t||n.some(t=>!!e?.states?.[t]))return{kind:"active",enabledEntityIds:n,allEntityIds:i}}else{const t=a[o];if(null!=t?.disabled_by)return{kind:"ha_disabled",reason:"entity",enabledEntityIds:[],allEntityIds:[o]};if(t?.device_id&&null!=s[t.device_id]?.disabled_by)return{kind:"ha_disabled",reason:"device",enabledEntityIds:[],allEntityIds:[o]};if("ha_disabled"===l?.kind)return{kind:"ha_disabled",reason:l.reason||"entity",enabledEntityIds:[],allEntityIds:[o]};if(t||e?.states?.[o])return{kind:"active",enabledEntityIds:[o],allEntityIds:[o]}}return{kind:"unverified",reason:"registry_unavailable",enabledEntityIds:[],allEntityIds:[]}}function Jh(e){const t=jh(e);return{access:t.access,authoritative:t.authoritative,revision:t.revision,lastSuccess:t.lastSuccess,error:t.error}}function Qh(e){const t={};for(const[i,n]of Object.entries(e.entities)){if(!n?.device_id||!Vh(n))continue;const r=e.devices?.[n.device_id];r&&!Vh(r)||(t[n.device_id]=t[n.device_id]||[]).push(i)}return t}function ed(e,t){const i=new Map;for(const n of e){if(!0===n?.removed)continue;const e=n?.binding||"";if(!e.startsWith("entity:"))continue;const r=e.slice(7);if(!r)continue;const o=t?.entities?.[r]?.device_id;if(!o)continue;const s=i.get(o)||new Set;s.add(r),i.set(o,s)}return{byDevice:i}}function td(e,t,i,n){const r=n.byDevice.get(t);return r?.size?{partial:!0,entityIds:i.filter(t=>!r.has(t)&&!e?.entities?.[t]?.hidden)}:{partial:!1,entityIds:[...i]}}function id(e,t,i){if(t.identifiers?.[0]?.[0])return t.identifiers[0][0];for(const t of i){const i=e.entities[t]?.platform;if(i)return i}return""}function nd(e,t){if(/_device_temperature$/.test(t))return!1;if(e.entities?.[t]?.entity_category)return!1;const i=e.states[t];if(!i)return/_temperature$/.test(t);const n=i.attributes||{};return"temperature"===n.device_class||/°C|°F/.test(n.unit_of_measurement||"")||/_temperature$/.test(t)}const rd=["vacuum","lawn_mower","climate","media_player","light","cover","lock","valve","alarm_control_panel","water_heater","fan","humidifier","siren","camera","remote"],od=e=>[...e.filter(e=>!e.reg?.hidden),...e.filter(e=>!!e.reg?.hidden)];function sd(e,t){const i=t.map(t=>({eid:t,reg:e?.entities?.[t]})).filter(e=>!!e.reg);if(!i.length)return[];const n=i.filter(e=>!e.reg.entity_category),r=n.length?n:i;for(const e of rd){const t=r.filter(t=>t.eid.startsWith(e+"."));if(t.length)return od(t).map(e=>e.eid)}const o=r.filter(t=>function(e,t){if(!t.startsWith("binary_sensor."))return!1;const i=dh(e?.states?.[t]?.attributes?.device_class||e?.entities?.[t]?.device_class||e?.entities?.[t]?.original_device_class);return th.has(i)||ih.has(i)||nh.has(i)||rh.has(i)||"moving"===i||oh.has(i)}(e,t.eid));if(o.length)return od(o).map(e=>e.eid);const s=r.filter(e=>e.eid.startsWith("switch."));if(s.length){const t=od(s),n=t.find(t=>fh(e,t.eid));if(s.length>1&&n){const t=i.filter(t=>t.eid!==n.eid&&"config"!==t.reg?.entity_category&&null!=mh(e,t.eid)),r=t.filter(e=>!e.reg?.entity_category),o=r.length?r:t;for(const t of[0,1,2]){const i=od(o.filter(i=>mh(e,i.eid)===t));if(i.length)return[i[0].eid,n.eid]}}return[(n||t[0]).eid]}const a=[];for(const e of Le)a.push(...od(r.filter(t=>t.eid.startsWith(e+"."))));return a.push(...od(r.filter(e=>!Le.includes(e.eid.split(".")[0])))),a.map(e=>e.eid)}function ad(e,t,i){const n=t.map(t=>({eid:t,reg:e.entities[t],st:e.states[t]})).filter(e=>e.reg),r=[n.filter(e=>!e.reg.hidden&&!e.reg.entity_category),n.filter(e=>!e.reg.entity_category),n.filter(e=>!e.reg.hidden),n];if("mdi:thermometer"===i||"mdi:air-filter"===i)for(const t of r){const i=t.find(t=>nd(e,t.eid));if(i)return i.eid}const o=sd(e,t);return o.find(Rn)||o[0]}function ld(e,t,i=[]){return[...new Set(cd(e,t,i))].filter(e=>Rn(e))}function cd(e,t,i=[]){const n=e?.startsWith("entity:")?new Set([e.slice(7)]):new Set(i);return(t||[]).filter(e=>"string"==typeof e&&!n.has(e))}function hd(e,t){if("string"==typeof t)return e.area===t;const i=e.marker?.room_id;return i?!!t.id&&i===t.id:!!t.area&&e.area===t.area}function dd(e){const t=e.marker?.binding?.startsWith("entity:")?e.marker.binding.slice(7):null,i=e.entities.filter(Rn),n=e.primary&&Rn(e.primary)?e.primary:null;return[...new Set([t,n,...i].filter(e=>!!e&&Rn(e)))]}function ud(e){const t=dd(e),i=e.marker?.light_entity;return i&&t.includes(i)?i:t[0]||null}function pd(e,t){if(!1===t.marker?.is_light)return[];if(!0===t.marker?.is_light){return[{eid:ud(t),via:"forced"}]}const i=t.primary||sd(e,t.entities)[0];return i&&!i.startsWith("light.")?[]:t.entities.filter(t=>t.startsWith("light.")&&!!e.states?.[t]).map(e=>({eid:e,via:"light"}))}const _d=new WeakMap,md=new WeakMap;function gd(e){return e.map(e=>[e.id||"",!0===e.hidden?1:0,e.primary||"",[...e.entities].join(","),void 0===e.controls?"":[...e.controls].join(","),e.marker?.id||"",e.marker?.binding||"",e.marker?.is_light,e.marker?.tap_action||"",!0===e.marker?.removed?1:0,e.marker?.light_entity||"",null==e.marker?.controls?"":[...e.marker.controls].join(",")].join("")).join("")}function fd(e){const t=gd(e),i=_d.get(e);if(i?.fingerprint===t)return i;const n=e.filter(e=>!e.hidden),r=new Map,o=new Map;for(const t of e){o.set(t,cd(t.marker?.binding,t.marker?.controls??t.controls,t.entities));const e=t.hidden||!0!==t.marker?.is_light?null:t.marker?.id||t.id;e&&r.set(String(e),t)}const s=new Map;for(const t of e){const e=o.get(t)||[],i=new Set(void 0===t.controls?e.filter(Rn):t.controls.filter(Rn)),n=ud(t),a=i.size?[...i]:n?[n]:[];for(const i of e){if(!i.startsWith("marker:"))continue;const e=i.slice(7);if(!e||e===String(t.marker?.id||t.id||""))continue;if(!r.has(e))continue;const n=s.get(e)||{markerId:e,controllers:[],driverEids:[]};n.controllers.push({device:t,driverEids:[...a]}),n.driverEids=[...new Set([...n.driverEids,...a])],s.set(e,n)}}const a={fingerprint:t,visible:n,markerById:r,persistedByDevice:o,incomingByMarker:s};return _d.set(e,a),a}function vd(e){return fd(e).incomingByMarker}function yd(e,t){const i=ld(t.marker?.binding,t.controls??t.marker?.controls,t.entities),n=cd(t.marker?.binding,t.marker?.controls??t.controls,t.entities);return(null!=t.marker?.is_light||!i.length&&!n.some(e=>e.startsWith("marker:")))&&pd(e,t).length>0}function bd(e,t){return pd(e,t).some(e=>!!e.eid)}function wd(e,t,i,n){const r="always"===e||"auto"===e&&t,o=r&&!i;return{sourceExists:r,fromSourceEnabled:r&&i,manualEnabled:r,radiusEnabled:r,passive:o,effectiveMode:o&&"auto"===n?"fixed":n}}function kd(e,t){const i=ld(t.marker?.binding,t.controls??t.marker?.controls,t.entities).map(e=>({eid:e,via:"controls"})),n=yd(e,t)?pd(e,t):[];for(const e of n)e.eid&&i.some(t=>t.eid===e.eid)||i.push(e);return i}function xd(e,t,i,n){if(null!=i)return xd(e,t,null,n).filter(e=>hd(e.device,i));const r=gd(t),o=function(e,t){const i=new Set;for(const e of t){for(const t of e.entities)i.add(t);for(const t of e.controls||e.marker?.controls||[])"string"!=typeof t||t.startsWith("marker:")||i.add(t)}return[...i].sort().map(t=>`${t}:${e?.states?.[t]?.state??""}`).join("|")}(e,t),s=Rh(n),a=md.get(t);if(a?.graphFingerprint===r&&a.stateFingerprint===o&&a.virtualLightFingerprint===s&&a.registry===e?.entities)return a.sources;const{visible:l,markerById:c,persistedByDevice:h,incomingByMarker:d}=fd(t),u=null==i?l:l.filter(e=>hd(e,i)),p=new Map,_=new Map;for(const t of u){const i=kd(e,t).filter(e=>"controls"!==e.via);for(const n of i){const i=!0===t.marker?.is_light?String(t.marker?.id||t.id||""):"",r=i?`marker:${i}`:`entity:${n.eid}`,o=n.eid?[n.eid]:[],s={key:r,eid:n.eid||"",stateEids:o,serviceEids:o,device:t,via:n.via,castsGlow:!0,passive:!n.eid,on:!n.eid||"on"===e.states?.[n.eid]?.state};p.set(t,[...p.get(t)||[],s]),n.eid&&_.set(n.eid,s)}}const m=new Map;for(const e of t){const t=h.get(e)||[],i=new Set(void 0===e.controls?t.filter(Rn):e.controls);m.set(e,i)}for(const t of p.values())for(const i of t){if(!i.passive)continue;const t=i.key.slice(7),r=d.get(t);i.on=!r||r.driverEids.some(t=>"on"===e.states?.[t]?.state),!r&&Ch(i.device.marker)&&(i.on=Th(i.device.marker,n))}const g=new Map,f=e=>{const t=g.get(e.key);(!t||e.castsGlow&&!t.castsGlow)&&g.set(e.key,e)};for(const t of l){const n=h.get(t)||[],r=null==i||hd(t,i);for(const i of n){if(i.startsWith("marker:")){const e=c.get(i.slice(7)),t=e?p.get(e):null;if(t)for(const e of t)f(e);continue}if(!Rn(i)||!m.get(t)?.has(i))continue;const n=_.get(i);n?f(n):r&&f({key:`entity:${i}`,eid:i,stateEids:[i],serviceEids:[i],device:t,via:"controls",castsGlow:!1,passive:!1,on:"on"===e.states?.[i]?.state})}for(const e of p.get(t)||[])f(e)}const v=[...g.values()];return md.set(t,{graphFingerprint:r,stateFingerprint:o,virtualLightFingerprint:s,registry:e?.entities,sources:v}),v}function Sd(e){const t=e.filter(e=>e.castsGlow);return t.find(e=>e.on)||t[0]||null}function $d(e){return e.length?e.some(e=>e.on)?"on":"off":"none"}function Md(e,t){const i=[];for(const n of t){const t=e.states[n];if(!t)continue;const r=(t.attributes?.unit_of_measurement||"").toLowerCase();if(/_(linkquality|lqi)$/.test(n)||"lqi"===r){const e=parseFloat(t.state);isNaN(e)||i.push(e);continue}const o=t.attributes?.linkquality??t.attributes?.lqi;if(null!=o){const e=parseFloat(o);isNaN(e)||i.push(e)}}return Pi(i)}function Rd(e,t){for(const i of t){if(!nd(e,i))continue;const t=e.states[i];if(!t)continue;const n=parseFloat(t.state);if(!isNaN(n))return Math.round(10*n)/10}return null}function Cd(e,t){for(const i of t){if(!i.startsWith("climate."))continue;const t=e.states[i];if(!t||"unavailable"===t.state||"unknown"===t.state)continue;const n=parseFloat(t.attributes?.current_temperature);if(Number.isFinite(n))return Math.round(10*n)/10}return null}function Td(e,t){if(e.entities?.[t]?.entity_category)return!1;const i=e.states[t];if(!i)return/_humidity$/.test(t);const n=i.attributes||{};return"humidity"===n.device_class||"%"===n.unit_of_measurement&&/_humidity$/.test(t)||/_humidity$/.test(t)}function Dd(e,t){for(const i of t){if(!Td(e,i))continue;const t=e.states[i];if(!t)continue;const n=parseFloat(t.state);if(!isNaN(n))return Math.round(n)}return null}function Ad(e,t){if(!t)return[];const i=[];for(const[t,n]of Object.entries(e.entities)){if(!t.startsWith("light.")||n.hidden||!Vh(n))continue;let r=null;if("group"===n.platform)r=n.area_id||null;else{if(!n.device_id)continue;{const t=e.devices[n.device_id];if(!Vh(t))continue;if("Group"!==t?.model)continue;r=t.area_id||n.area_id||null}}if(!r)continue;const o=e.states[t];i.push({eid:t,name:n.name||o?.attributes?.friendly_name||t,area:r})}return i}function Pd(e,t,i,n,r){const o=He(t,i,r);if(o!==Ne)return o;const s=[];for(const t of n){const i=e.states[t]?.attributes?.device_class;i&&s.push(i)}return function(e){for(const t of e){const e=Ee[t];if(e)return e}return null}(s)??Ne}function Fd(e,t){return e.map(e=>{if(!Array.isArray(e.controls))return e;const i=e.controls.filter(e=>!("string"==typeof e&&e.startsWith("marker:")&&t.has(e.slice(7))));return i.length===e.controls.length?e:{...e,controls:i.length?i:null}})}function zd(e,t,i){if(!t||!i||t===i)return[...e];const n=`marker:${t}`,r=`marker:${i}`;return e.map(e=>{const t=Array.isArray(e.controls)?e.controls.map(e=>e===n?r:e):e.controls,i="derived_marker_state"===e.value_badge?.source?.kind&&e.value_badge.source.ref===n?{...e.value_badge,source:{...e.value_badge.source,ref:r}}:e.value_badge,o="derived_marker_state"===e.value_source?.kind&&e.value_source.ref===n?{...e.value_source,ref:r}:e.value_source;return t===e.controls&&i===e.value_badge&&o===e.value_source?e:{...e,controls:t,...void 0!==i?{value_badge:i}:{},...void 0!==o?{value_source:o}:{}}})}function Id(e,t,i){if(!t||t===i)return!0;const n=new Map;for(const t of e)n.set(t.id,(t.controls||[]).filter(e=>"string"==typeof e&&e.startsWith("marker:")).map(e=>e.slice(7)));const r=new Set,o=[i];for(;o.length;){const e=o.pop();if(e===t)return!0;r.has(e)||(r.add(e),o.push(...n.get(e)||[]))}return!1}function Od(e,t,i,n){const r=new Set([t]),o=e.filter(e=>{const o=e.id===t||!n&&e.binding===i;return o&&r.add(e.id),!o});return{markers:n?o:[...o,{id:t,binding:i,removed:!0,hidden:!0}],cleanupIds:r}}function Ed(e){const t=new Set,i=new Set,n=new Set;for(const r of e||[]){const e=String(r.binding||"").indexOf(":");if(e<1)continue;const o=r.binding.slice(0,e),s=r.binding.slice(e+1);s&&(!0===r?.removed?"device"===o?t.add(s):"entity"===o&&i.add(s):"entity"===o&&n.add(s))}return{devices:t,entities:i,liveEntities:n}}function Nd(e,t,i){if(i.liveEntities.has(t))return!1;if(i.entities.has(t))return!0;const n=e?.entities?.[t]?.device_id;return!!n&&i.devices.has(n)}function Hd(e,t,i,n,r){const o=ld(t.binding,t.controls,e.entities).filter(e=>!Nd(i,e,n)).filter(e=>"active"===Zh(i,"entity:"+e,r).kind);e.marker=t,e.controls=o,e.userHidden=!0===t.hidden,e.hidden=e.userHidden||"ha_disabled"===e.bindingStatus?.kind,t.name&&(e.name=t.name),t.icon&&(e.icon=t.icon),null!=t.model&&(e.model=t.model),e.link=t.link??null,e.description=t.description??null,e.pdfs=t.pdfs||[],e.tapAction=t.tap_action??null}function Ld(e){const t=e.hass,i=e.registry||jh(t),n=Gh(t,i),r=Kh(t,i),{areaToSpace:o,markers:s,settings:a,excluded:l,iconRules:c}=e,h=!1!==a.group_lights,d=Ed(s),u=Ad(n,h).filter(e=>!Nd(n,e.eid,d)),p=new Set(u.map(e=>e.area)),_=Qh(n),m=ed(s,r),g=new Set(s.map(e=>e.binding)),f=[];for(const e of Object.values(n.devices)){const r=e.area_id;if(!r||!o[r])continue;if("service"===e.entry_type)continue;if(g.has("device:"+e.id))continue;if("active"!==Zh(t,"device:"+e.id,i).kind)continue;const s=td(n,e.id,_[e.id]||[],m);if(s.partial&&!s.entityIds.length)continue;const a=s.entityIds,d=id(n,e,a);let u=l.has(d)||"Group"===e.model||/scene/i.test(e.model||"")||/bridge/i.test((e.model||"")+(e.name||""))||"myheat"===d&&!!e.via_device_id;if(!u&&h&&p.has(r)){const t=(e.name_by_user||e.name||"").trim();"mdi:lightbulb"===Pd(n,t,e.model,a,c)&&(u=!0)}u&&f.push("device:"+e.id)}return f}function Bd(e,t,i,n){if("string"==typeof e.room_id&&e.room_id.length>0&&null===e.area)return{area:"",space:e.space||n};const r=e.area||t||"";return{area:r,space:r&&i[r]||e.space||n}}function qd(e){const t=e.hass,i=e.registry||jh(t),n=Gh(t,i),r=Kh(t,i),{areaToSpace:o,markers:s,settings:a,excluded:l,showAll:c,firstSpaceId:h,loc:d,iconRules:u}=e,p=!1!==a.group_lights,_=Ed(s),m=Ad(n,p).filter(e=>!Nd(n,e.eid,_)),g=new Set(m.map(e=>e.area)),f=Qh(n),v=function(e){const t={};for(const[i,n]of Object.entries(e.entities||{}))n?.device_id&&(t[n.device_id]=t[n.device_id]||[]).push(i);return t}(r),y=ed(s,r),b=new Set;for(const e of s){const[t,i]=e.binding.split(":");"device"!==t&&"entity"!==t||!i||b.add(e.binding)}const w=(e,t)=>s.find(i=>i.binding===e+":"+t),k={},x=[];for(const e of Object.values(n.devices)){const r=e.area_id;if(!r||!o[r])continue;if("service"===e.entry_type)continue;if(b.has("device:"+e.id))continue;const s=Zh(t,"device:"+e.id,i);if("active"!==s.kind)continue;const h=w("device",e.id);if(h&&h.hidden&&!a.filter_seeded)continue;const _=td(n,e.id,f[e.id]||[],y);if(_.partial&&!_.entityIds.length)continue;const m=_.entityIds,v=_.partial?{kind:"active",enabledEntityIds:m,allEntityIds:m}:s,S=id(n,e,m),$=!a.filter_seeded;if($&&!c){if(l.has(S))continue;if("Group"===e.model)continue;if(/scene/i.test(e.model||""))continue;if(/bridge/i.test((e.model||"")+(e.name||"")))continue;if("myheat"===S&&e.via_device_id)continue}const M=(e.name_by_user||e.name||d("device.unnamed")).trim(),R=M+"|"+r;let C=Pd(n,M,e.model,m,u);if(m.some(e=>e.startsWith("lock."))&&(C="mdi:lock"),$&&!c&&p&&"mdi:lightbulb"===C&&g.has(r))continue;k[R]=(k[R]||0)+1;const T=k[R]>1?M+" "+k[R]:M,D={id:e.id,name:T,model:e.model||"",area:r,space:o[r],icon:C,entities:m,allEntities:v.allEntityIds,bindingStatus:v,bindingKind:"device",bindingRef:e.id,pdfs:[]};D.primary=ad(n,m,C),"mdi:thermometer"!==C&&"mdi:air-filter"!==C||(D.temp=Rd(n,m)),D.primary&&Td(n,D.primary)&&(D.hum=Dd(n,m)),x.push(D)}for(const e of m)o[e.area]&&(b.has("entity:"+e.eid)||x.push({id:"lg_"+e.eid,name:e.name,model:d("device.light_group"),area:e.area,space:o[e.area],icon:"mdi:lightbulb-group",entities:[e.eid],allEntities:[e.eid],bindingStatus:{kind:"active",enabledEntityIds:[e.eid],allEntityIds:[e.eid]},primary:e.eid,bindingKind:"entity",bindingRef:e.eid,pdfs:[]}));for(const e of s){if(e.removed)continue;const[s,l]=e.binding.split(":"),c="device"===s||"entity"===s?Zh(t,e.binding,i):null;if(!e.hidden||a.filter_seeded||"ha_disabled"===c?.kind)if("device"===s){const t=c;if("unverified"===t.kind)continue;const s=r.devices[l],{area:a,space:p}=Bd(e,s?.area_id,o,h),m="active"===t.kind?t.enabledEntityIds:[];let g=s?Pd(n,s.name_by_user||s.name||"",s.model,m,u):"mdi:help-circle";m.some(e=>e.startsWith("lock."))&&(g="mdi:lock");const f={id:e.id,name:s?.name_by_user||s?.name||d("device.fallback"),model:s?.model||"",area:a,space:p,icon:g,entities:m,allEntities:t.allEntityIds.length?t.allEntityIds:s&&v[s.id]||[],bindingStatus:t,bindingKind:"device",bindingRef:l};f.primary=ad(n,m,g),"mdi:thermometer"!==g&&"mdi:air-filter"!==g||(f.temp=Rd(n,m)),f.primary&&Td(n,f.primary)&&(f.hum=Dd(n,m)),Hd(f,e,r,_,i),x.push(f)}else if("entity"===s){if(Nd(r,l,_))continue;const t=c;if("unverified"===t.kind)continue;const s=r.entities[l],a=s?.area_id||s?.device_id&&r.devices[s.device_id]?.area_id||"",{area:d,space:p}=Bd(e,a,o,h),m=n.states[l],g=s?.name||m?.attributes?.friendly_name||l;let f=Pd(n,g,"",[l],u);l.startsWith("lock.")&&(f="mdi:lock");const v={id:e.id,name:g,model:"",area:d,space:p,icon:f,entities:"active"===t.kind?[l]:[],allEntities:[l],bindingStatus:t,primary:"active"===t.kind?l:void 0,bindingKind:"entity",bindingRef:l};"mdi:thermometer"!==f&&"mdi:air-filter"!==f||!v.entities.length||(v.temp=Rd(n,v.entities)),v.entities.length&&Td(n,l)&&(v.hum=Dd(n,v.entities)),Hd(v,e,r,_,i),x.push(v)}else{const t=e.area||"",n=e.space||t&&o[t]||h,s={id:e.id,name:e.name||d("device.virtual"),model:e.model||"",area:t,space:n,icon:e.icon||"mdi:map-marker",entities:[],allEntities:[],bindingStatus:{kind:"active",enabledEntityIds:[],allEntityIds:[]},bindingKind:"virtual",virtual:!0};Hd(s,e,r,_,i),x.push(s)}}return x}function jd(e){const{marker:t,siblingMarkers:i=[],...n}=e;return qd({...n,markers:[...i.filter(e=>e.id!==t.id),t]}).find(e=>e.id===t.id)||null}function Wd(e,t,i,n){if(!t)return null;if(function(e,t,i){if(!t)return!1;const n=t.indexOf(":");if(n<1)return!1;const r=t.slice(0,n),o=t.slice(n+1),s=Ed(i);return"device"===r?s.devices.has(o):"entity"===r&&Nd(e,o,s)}(e,t,n))return null;const r=t.indexOf(":");if(r<0)return null;const o=t.slice(0,r),s=t.slice(r+1);if(!s)return null;if("entity"===o){const t=parseFloat(e.states[s]?.state);return Number.isFinite(t)?"temp"===i?Math.round(10*t)/10:Math.round(t):null}if("device"===o){const t=Object.entries(e.entities).filter(([,e])=>e.device_id===s).map(([e])=>e);return"temp"===i?Rd(e,t):Dd(e,t)}return null}const Ud=new RegExp(["water","voda","coolant","flow_?temp","return_?temp","target","setpoint","chip","cpu","processor","board","core_temp","device_temp","batter","akkum","freezer","fridge","oven","kettle","boiler"].join("|"),"i");function Vd(e,t){return t.area?t.area:e&&t.id?`@room/${encodeURIComponent(e)}/${encodeURIComponent(t.id)}`:null}function Gd(e){return null==e.area&&e.space&&e.room_id?Vd(e.space,{id:e.room_id,area:null}):e.area||null}function Kd(e){const t=e?.exclude_integrations;return t?new Set(t):Pe}function Yd(e,t,i,n=Pe){const r=new Map;if(!e?.entities)return r;const o=Ed(i),s=new Set,a=new Map,l=new Map;for(const e of i||[]){if(e?.removed)continue;const t=(e.binding||"").indexOf(":");if(t<=0)continue;const i=e.binding.slice(0,t),n=e.binding.slice(t+1);if(!n)continue;!0===e.use_climate_temp&&s.add(n);const r=Gd(e);r&&("entity"!==i||a.has(n)?"device"!==i||l.has(n)||l.set(n,r):a.set(n,r))}const c=new Map;for(const[t,i]of Object.entries(e.entities)){if(i.device_id&&o.devices.has(i.device_id)&&!o.liveEntities.has(t)||!i.device_id&&o.entities.has(t)&&!o.liveEntities.has(t))continue;const r=i.device_id?e.devices?.[i.device_id]:null;if(!Vh(i)||r&&!Vh(r))continue;const h=a.get(t)||(i.device_id?l.get(i.device_id):null)||i.area_id||r?.area_id||null;if(!h)continue;if(i.entity_category)continue;if(!(s.size>0&&t.startsWith("climate.")&&(s.has(t)||i.device_id&&s.has(i.device_id)))){if(n.has(i.platform))continue;if(Ud.test(t))continue}let d=c.get(h);d||(d=new Map,c.set(h,d));const u=i.device_id||t;let p=d.get(u);if(!p){const n=e.states?.[t];p={name:(r?r.name_by_user||r.name:i.name||n?.attributes?.friendly_name||t)||t,model:r?.model,ents:[]},d.set(u,p)}p.ents.push(t)}for(const[i,n]of c){const o=[],a=[];for(const[i,r]of n){const n=Pd(e,r.name,r.model,r.ents,t),l="mdi:thermometer"===n||"mdi:air-filter"===n;if(l){const t=Rd(e,r.ents);null!=t&&o.push(t)}if(s.size>0&&(s.has(i)||r.ents.some(e=>s.has(e)))){const t=Cd(e,r.ents);null!=t&&o.push(t)}if(l||"mdi:water-percent"===n){const t=Dd(e,r.ents);null!=t&&a.push(t)}}(o.length||a.length)&&r.set(i,{temp:o.length?Math.round(o.reduce((e,t)=>e+t,0)/o.length*10)/10:null,hum:a.length?Math.round(a.reduce((e,t)=>e+t,0)/a.length):null})}return r}function Xd(e,t,i){const n=[];for(const r of t){if(r.area!==i||r.virtual)continue;const t=Md(e,r.entities);null!=t&&n.push(t)}return Pi(n)}const Zd={offStates:["off"],unknownUsesToggle:!0},Jd={light:Zd,switch:Zd,fan:Zd,humidifier:Zd,input_boolean:Zd,automation:Zd,remote:Zd,group:Zd,climate:{...Zd,featureMasks:{turn_on:256,turn_off:128,toggle:384}},media_player:{...Zd,featureMasks:{turn_on:128,turn_off:256,toggle:384}},siren:{...Zd,featureMasks:{turn_on:1,turn_off:2,toggle:3}},vacuum:{...Zd,featureMasks:{turn_on:1,turn_off:2,toggle:3}},water_heater:{...Zd,featureMasks:{turn_on:8,turn_off:8,toggle:8}},camera:{...Zd,featureMasks:{turn_on:1,turn_off:1,toggle:1}}};function Qd(e){return e.slice(0,e.indexOf("."))}function eu(e,t,i){if(!e?.services||"object"!=typeof e.services)return!1;const n=e.services?.[t];return!!n&&Object.prototype.hasOwnProperty.call(n,i)}function tu(e,t,i){return eu(e,t,i)?{domain:t,service:i}:eu(e,"homeassistant",i)?{domain:"homeassistant",service:i}:null}function iu(e,t){return e?.entities?.[t]||null}function nu(e,t,i){const n=e?.states?.[i],r=iu(t,i);return n?.attributes?.friendly_name||r?.name||r?.original_name||i}function ru(e,t){const i=iu(e,t);if(null!=i?.disabled_by)return!0;const n=i?.device_id?e?.devices?.[i.device_id]:null;return null!=n?.disabled_by}function ou(e,t){const i=e?.attributes?.supported_features;if(null==i||""===i)return!1;const n=Number(i);return Number.isFinite(n)&&(n&t)===t}function su(e,t,i){const n=Qd(i);if("lock"===n||"alarm_control_panel"===n)return!0;if("cover"!==n)return!1;const r=e?.states?.[i],o=iu(t,i),s=String(r?.attributes?.device_class||o?.device_class||o?.original_device_class||"");return Bi.has(s)}function au(e,t,i,n,r){return{ref:i,entityId:n,name:n?nu(e,t,n):null,reason:r}}function lu(e,t,i,n,r,o=null){return{target:null,skipped:au(e,t,i,n,r),semantics:o,nextEffect:null,command:null}}function cu(e,t,i,n,r=i){const o=Qd(i);if("cover"!==o&&"valve"!==o)return function(e,t,i,n,r=i){const o=Qd(i),s=e?.states?.[i];if(ru(t,i))return lu(e,t,r,i,"ha-disabled","power");if(su(e,t,i))return lu(e,t,r,i,"secure");if(!s)return lu(e,t,r,i,"missing","power");if("unavailable"===s.state)return lu(e,t,r,i,"unavailable","power");const a=Jd[o];if(!a)return lu(e,t,r,i,"unsupported");let l,c;if("unknown"===s.state||""===s.state){if(!a.unknownUsesToggle)return lu(e,t,r,i,"unsupported","power");l="toggle",c="toggle"}else a.offStates.includes(String(s.state))?(l="turn-on",c="turn_on"):(l="turn-off",c="turn_off");const h=a.featureMasks?.[c];if(h&&!ou(s,h))return lu(e,t,r,i,"unsupported","power");const d=tu(e,o,c);return d?{target:{entityId:i,name:nu(e,t,i),state:String(s.state||""),via:n},skipped:null,semantics:"power",nextEffect:l,command:{...d,data:{entity_id:i}}}:lu(e,t,r,i,"unsupported","power")}(e,t,i,n,r);if(ru(t,i))return lu(e,t,r,i,"ha-disabled",o);if(su(e,t,i))return lu(e,t,r,i,"secure",o);const s=e?.states?.[i];if(!s)return lu(e,t,r,i,"missing",o);if("unavailable"===s.state)return lu(e,t,r,i,"unavailable",o);const a=function(e,t,i){const n=String(i?.state||""),r="closed"===n?{service:`open_${t}`,effect:"open",feature:1}:"open"===n?{service:`close_${t}`,effect:"close",feature:2}:"opening"===n||"closing"===n?{service:`stop_${t}`,effect:"stop",feature:8}:null;return r&&ou(i,r.feature)&&eu(e,t,r.service)?r:ou(i,3)&&eu(e,t,"toggle")?{service:"toggle",effect:"toggle"}:null}(e,o,s);if(!a)return lu(e,t,r,i,"unsupported",o);return{target:{entityId:i,name:nu(e,t,i),state:String(s.state||""),via:n},skipped:null,semantics:o,nextEffect:a.effect,command:{domain:o,service:a.service,data:{entity_id:i}}}}function hu(e){return"entity"===e.bindingKind?e.bindingRef&&Rn(e.bindingRef)?[e.bindingRef]:[]:"virtual"===e.bindingKind?[]:dd(e)}function du(e){const t=e.marker?.toggle_entity;return t&&hu(e).includes(t)?t:null}function uu(e,t,i){const n=function(e,t){if("entity"===e.bindingKind&&e.bindingRef){const t=e.marker?.light_entity?ud(e):null;return[...new Set([t,e.bindingRef].filter(e=>!!e))]}const i=e.entities.length?e.entities:e.allEntities||[],n=e.marker?.light_entity||e.primary&&Rn(e.primary)?ud(e):null;return[...new Set([n,...sd(t,i)].filter(e=>!!e))]}(i,t);if(!n.length)return null;const r="entity"===i.bindingKind?"binding":"device-role";if("binding"===r)return cu(e,t,n[0],r);let o=null,s=null;for(const i of n){const n=cu(e,t,i,r);if(n.command)return n;const a=n.skipped?.reason;if("missing"===a||"unavailable"===a||"secure"===a)return n;"ha-disabled"!==a?o||=n:s||=n}return o||s}function pu(e){const t=e.skipped?.reason;return"missing"===t?"unavailable":t||"unsupported"}function _u(e,t){return{origin:e,kind:"none",semantics:null,targets:[],skippedTargets:[],noneReason:t,nextEffect:null,command:null}}function mu(e,t){return"cover"===e||"toggle"===e?"toggle":"more-info"===e||"run"===e||"info"===e||"none"===e?e:(null==e||""===e)&&"light"===t?"toggle":"info"}function gu(e,t){return{origin:e,kind:"single",semantics:t.semantics,targets:t.target?[t.target]:[],skippedTargets:t.skipped?[t.skipped]:[],noneReason:t.command?null:pu(t),nextEffect:t.nextEffect,command:t.command}}function fu(e,t,i,n=[]){const r=new Map,o=[],s=new Set,a=e=>{const t=`${e.ref}\n${e.entityId||""}\n${e.reason}`;s.has(t)||(s.add(t),o.push(e))};for(const e of n)a(e);for(const n of i){const i=cu(e,t,n.entityId,n.via,n.ref);i.target?r.set(n.entityId,r.get(n.entityId)||i.target):i.skipped&&a(i.skipped)}const l=[...r.values()];if(!l.length)return{origin:"explicit-toggle",kind:"group",semantics:"group-power",targets:l,skippedTargets:o,noneReason:o.length&&o.every(e=>"secure"===e.reason)?"secure":"configured-targets-missing",nextEffect:null,command:null};const c=l.some(e=>"on"===e.state)?"turn_off":"turn_on",h=tu(e,"homeassistant",c);return h?{origin:"explicit-toggle",kind:"group",semantics:"group-power",targets:l,skippedTargets:o,noneReason:null,nextEffect:"turn_on"===c?"turn-on":"turn-off",command:{...h,data:{entity_id:l.map(e=>e.entityId)}}}:{origin:"explicit-toggle",kind:"group",semantics:"group-power",targets:[],skippedTargets:[...o,...l.map(i=>au(e,t,i.entityId,i.entityId,"unsupported"))],noneReason:"unsupported",nextEffect:null,command:null}}function vu(e){return String(e.marker?.id||e.id||"")}function yu(e){const{hass:t,device:i}=e,n=e.registryHass||t,r=function(e){return"toggle"===e.tapAction?"explicit-toggle":"cover"===e.tapAction?"legacy-cover":!e.tapAction&&e.primary?.startsWith("light.")?"default-light":null}(i);if(!r)return null;const o=i.marker;if("explicit-toggle"===r&&Ch(o)){const t=String(o?.id||i.id||""),n=vd(e.devices).get(t);if(n)return function(e,t){const i=e.registryHass||e.hass;return fu(e.hass,i,t.driverEids.map(e=>({entityId:e,via:"control-marker-driver",ref:`marker:${t.markerId}`})))}(e,n);const s=Th(o,e.virtualLights);return{origin:r,kind:"single",semantics:"power",targets:[{entityId:"",name:i.name,state:s?"on":"off",via:"virtual-light"}],skippedTargets:[],noneReason:null,nextEffect:s?"turn-off":"turn-on",command:null,operation:{kind:"virtual-light",markerId:o.id}}}if("explicit-toggle"===r){if(cd(i.marker?.binding,i.marker?.controls??i.controls,i.entities).length)return function(e,t=null){const{hass:i,device:n,devices:r}=e,o=e.registryHass||i,s=cd(n.marker?.binding,n.marker?.controls??n.controls,n.entities),a=e.lightSources||xd(i,r,null,e.virtualLights),l=new Map;for(const e of a){if(!e.key.startsWith("marker:"))continue;const t=l.get(e.key)||[];t.push(e),l.set(e.key,t)}const c=vd(r),h=new Map;for(const e of r){const t=String(e.marker?.id||e.id||"");t&&h.set(t,e)}const d=[],u=[];t&&d.push({entityId:t,via:"entity"===n.bindingKind?"binding":"device-role",ref:t});for(const e of s){if(!e.startsWith("marker:")){Rn(e)?d.push({entityId:e,via:"control-entity",ref:e}):u.push(au(i,o,e,e.includes(".")?e:null,"unsupported"));continue}const t=l.get(e)||[];if(!t.length){const t=h.get(e.slice(7));if("ha_disabled"===t?.bindingStatus?.kind){const n=t.bindingStatus.allEntityIds[0]||null;u.push({ref:e,entityId:n,name:t.name||(n?nu(i,o,n):null),reason:"ha-disabled"})}else u.push(au(i,o,e,null,"missing"));continue}const r=[...new Set(t.flatMap(e=>e.serviceEids))];if(r.length){for(const t of r)d.push({entityId:t,via:"control-entity",ref:e});continue}const s=t.some(e=>e.passive),a=e.slice(7),p=vu(n),_=c.get(a)?.controllers.find(e=>vu(e.device)===p);if(s&&_?.driverEids.length)for(const t of _.driverEids)d.push({entityId:t,via:"control-marker-driver",ref:e});else u.push(au(i,o,e,null,s?"missing":"unsupported"))}return fu(i,o,d,u)}(e,du(i))}if("legacy-cover"===r){const e=i.entities.find(e=>e.startsWith("cover."))||i.allEntities?.find(e=>e.startsWith("cover."));return e?gu(r,cu(t,n,e,"device-role")):_u(r,"no-actionable-entity")}const s=du(i),a=s?cu(t,n,s,"entity"===i.bindingKind?"binding":"device-role"):uu(t,n,i);return a?gu(r,a):_u(r,i.virtual||"virtual"===i.bindingKind?"no-actionable-entity":"no-binding")}function bu(e){if(!e)return[];const t=Array.isArray(e.data.entity_id)?e.data.entity_id:[e.data.entity_id];return[...new Set(t)].sort()}function wu(e){return e?e.operation?e.operation:e.command?{kind:"ha-service",command:e.command}:null:null}const ku=new Set(["missing","ha-disabled","unavailable"]);function xu(e,t){const i=wu(e),n=wu(t);return!(!i||!n||i.kind!==n.kind)&&("virtual-light"===i.kind&&"virtual-light"===n.kind?i.markerId===n.markerId:"ha-service"===i.kind&&"ha-service"===n.kind&&function(e,t){const i=bu(e),n=bu(t);return i.length===n.length&&i.every((e,t)=>e===n[t])}(i.command,n.command))}function Su(e,t){const i=e.targets[0]||e.skippedTargets[0],n=[];return"group"===e.kind?e.targets.length&&n.push(t.group(e.targets)):i&&n.push(t.single(i)),e.nextEffect&&e.targets.length&&n.push("group"===e.kind?t.groupCurrentNext(e.targets,e.nextEffect):t.currentNext(e.targets[0],e.nextEffect)),e.skippedTargets.length&&n.push(t.skipped(e.skippedTargets)),!e.command&&e.noneReason&&n.push(t.none(e.noneReason)),n}function $u(e,t){return e.catch(()=>{}).then(t)}const Mu=e=>{const t=e?.config;return t&&Array.isArray(t.spaces)?t:null},Ru=(e,t)=>"number"==typeof e&&Number.isFinite(e)?e:t;class Cu{constructor(e){this.onBodyReplaced=e,this.config=null,this.configRev=0,this.configFingerprint="",this.layout={},this.layoutRev=0,this.layoutFingerprint=""}setConfig(e){const t=this.config;e!==t&&(this.config=e,this.onBodyReplaced?.("_serverCfg",t))}setLayout(e){const t=this.layout;e!==t&&(this.layout=e,this.onBodyReplaced?.("_layout",t))}currentConfigFingerprint(){return this.configFingerprint||rc(this.config)}currentLayoutFingerprint(){return this.layoutFingerprint||rc(this.layout)}adoptResponses(e,t,i,n){const r=Mu(e),o=rc(r),s=o!==this.currentConfigFingerprint();s&&(i(),this.setConfig(r),this.configFingerprint=o),this.configRev=e?.rev??this.configRev;let a=!1;if(void 0!==t){const e=t?.layout??{},i=rc(e);a=i!==this.currentLayoutFingerprint(),a&&(n(),this.setLayout(e),this.layoutFingerprint=i),this.layoutRev=t?.rev??this.layoutRev}return{configChanged:s,layoutChanged:a}}adoptMergedLayout(e,t,i){const n=rc(e),r=n!==rc(this.layout);return r&&(i?.(),this.setLayout(e)),this.layoutFingerprint=n,this.layoutRev=t?.rev??this.layoutRev,r}stageConfigCandidate(e){const t=rc(e);t!==rc(this.config)&&this.setConfig(e),this.configFingerprint=t}acceptConfigWrite(e,t){this.configFingerprint=rc(e),this.configRev=Ru(t?.rev,this.configRev+1)}acceptPairWrite(e,t,i){this.setConfig(e),this.configFingerprint=rc(e),this.setLayout(t),this.layoutFingerprint=rc(t),this.configRev=Ru(i?.config_rev,this.configRev+1),this.layoutRev=Ru(i?.layout_rev,this.layoutRev+1)}noteLayoutRevision(e){"number"==typeof e&&e>this.layoutRev&&(this.layoutRev=e)}stageLocalConfig(e){this.setConfig(e)}stageLocalLayout(e){this.setLayout(e)}seedIdentity(e){Object.assign(this,e)}refreshConfigFingerprint(){this.configFingerprint=rc(this.config)}refreshLayoutFingerprint(){this.layoutFingerprint=rc(this.layout)}beginOptimistic(e,t){return function(e,t,i,n,r){return{previous:JSON.parse(JSON.stringify(e)),previousFingerprint:i,revision:n,attempted:t,attemptedFingerprint:r(t)}}(e,t,this.configFingerprint,this.configRev,rc)}rollbackOptimistic(e){const t=this.config;return!(!t||this.configRev!==e.revision||rc(t)!==e.attemptedFingerprint)&&(this.setConfig(e.previous),this.configFingerprint=e.previousFingerprint,!0)}restoreCached(e){const t=e?.config;return!(!t||!Array.isArray(t.spaces))&&(this.setConfig(t),this.configRev=e?.rev||0,this.configFingerprint=e?.config_fingerprint||rc(t),this.setLayout(e?.layout||{}),this.layoutRev=e?.layout_rev||0,this.layoutFingerprint=e?.layout_fingerprint||rc(this.layout),!0)}snapshot(e){return this.config?(this.refreshConfigFingerprint(),this.refreshLayoutFingerprint(),{config:this.config,rev:this.configRev,config_fingerprint:this.configFingerprint,layout:this.layout,layout_rev:this.layoutRev,layout_fingerprint:this.layoutFingerprint,virtual_lights:e}):null}}async function Tu(e,t){const{cfgResp:i,layResp:n}=t,r=e._adoption,o=Mu(i),s=null!=i&&rc(o)!==r.currentConfigFingerprint()||null!=n&&rc(n.layout??{})!==r.currentLayoutFingerprint();if(s){if(!await e._signer.prepareImage(e.hass,e._candidateBackdrop(o)))return e._continuity.note("asset-failed"),e._scheduleLoadRetry(!0),{status:"asset-wait"}}s&&e._continuity.hasCompleteFrame&&"steady"===e._continuity.state&&e._beginContinuityCandidate(t.reason,!0),t.beforeAdopt?.();const a=e._space;return function(e,t,i){const n=e._adoption,r=!!n.config,{configChanged:o,layoutChanged:s}=n.adoptResponses(t??{},i,()=>{e._geometryHistory.clear(),e._devicePositionHistory.clear(),e._cancelDeviceDrag(),e._pendingPhysicalWrites.clear(),e._clearRoomFocus(!0),e._cancelCameraTransition(!1),r&&e._clearGeometryGesture()},()=>{e._cancelCameraTransition(!1),e._devicePositionHistory.clear(),e._cancelDeviceDrag()});if(o&&e._seedDecorStyle(n.config),t&&("virtual_lights"in t||"config"in t)){const i=Mh(e._virtualLights,t.virtual_lights,n.configRev,"virtual_lights"in t);Rh(i)!==Rh(e._virtualLights)&&(e._virtualLights=i,e._capturedSnapshotVirtual="")}e._canOptimizeUndo=!(!t?.can_optimize_undo&&!i?.can_optimize_undo),e._adoptConfigCapabilities(t),e._undoKind=t?.undo_kind||i?.undo_kind||null,"boolean"==typeof t?.can_write&&(e._serverCanWrite=t.can_write),o&&e._continuity.note("config-candidate",{configRev:n.configRev}),s&&e._continuity.note("layout-candidate",{layoutRev:n.layoutRev})}(e,i,n),"reload"===t.profile&&(e._syncDecorAssets(o).catch(()=>{}),e._adoptInitialSpace(e._model,!0),e._resumePendingNavMode(),e._cacheSnapshot()),{status:"adopted",spaceChanged:e._space!==a}}const Du=e=>!!e&&e.length>=2&&Number.isFinite(e[0])&&Number.isFinite(e[1]);function Au(e,t=5,i=5){return Co(e.cm,t,i)/2}function Pu(e,t,i=1,n=5,r=5,o=0){const s=e.host;if(!s||"partition"!==s.kind||"string"!=typeof s.id||!s.id)return{resolved:null,reason:"invalid-host"};const a=t.find(e=>e.id===s.id);if(!a)return{resolved:null,reason:"missing-partition"};if(!Du(a.a)||!Du(a.b)||!Number.isFinite(s.t)||s.t<0||s.t>1)return{resolved:null,reason:"invalid-position"};const l=a.b[0]-a.a[0],c=a.b[1]-a.a[1],h=Math.hypot(l,c),d=Number(e.length)*i;if(!(h>1e-9&&d>0&&Number.isFinite(d)))return{resolved:null,reason:"invalid-length"};const u=s.t*h;if(u-d/2h-o+1e-9)return{resolved:null,reason:"does-not-fit"};const p=l/h,_=c/h;let m=180*Math.atan2(c,l)/Math.PI;return m>=90?m-=180:m<-90&&(m+=180),{reason:null,resolved:{opening:e,host:s,partition:a,center:[a.a[0]+l*s.t,a.a[1]+c*s.t],angle:m,length:d,depth:Co(a.cm,n,r),t:s.t,axis:{a:[a.a[0],a.a[1]],b:[a.b[0],a.b[1]],ux:p,uy:_,length:h}}}}function Fu(e,t,i=1,n=5,r=5){return Pu(e,t,i,n,r,0)}function zu(e,t,i=1,n=5,r=5){const o=e.host,s="partition"===o?.kind?t.find(e=>e.id===o.id):void 0;if(!s)return Fu(e,t,i,n,r);const a=Pu(e,t,i,n,r,Au(s,n,r));return"does-not-fit"===a.reason?{resolved:null,reason:"does-not-fit-jamb"}:a}function Iu(e,t){return!e||(e.length!==t.length||e.host?.kind!==t.host?.kind||e.host?.id!==t.host?.id||e.host?.t!==t.host?.t)}function Ou(e){const{center:t,length:i,axis:n,host:r}=e,o=i/2;return{hostId:r.id,a:[t[0]-n.ux*o,t[1]-n.uy*o],b:[t[0]+n.ux*o,t[1]+n.uy*o],depth:e.depth}}function Eu(e,t=!1){const i=t?1:-1,n=e.depth/2;return{ox:-e.axis.uy*i*n,oy:e.axis.ux*i*n,cm:e.partition.cm,side:i}}function Nu(e,t,i){return e.flatMap(e=>!Du(e.a)||!Du(e.b)||Math.hypot(e.b[0]-e.a[0],e.b[1]-e.a[1])<=1e-9?[]:[{roomId:"",a:[e.a[0],e.a[1]],b:[e.b[0],e.b[1]],key:`partition:${e.id}`,kind:"outer",cm:e.cm,open:!1,half:Co(e.cm,t,i)/2,partitionHost:{kind:"partition",id:e.id}}])}function Hu(e,t,i){const{center:n,length:r,axis:o}=e,s=r/2,a=t.flatMap(e=>{if(!e.kind||e.open)return[];const t=e.b[0]-e.a[0],r=e.b[1]-e.a[1],a=Math.hypot(t,r);if(!(a>i))return[];const l=t/a,c=r/a;if(Math.abs(o.ux*c-o.uy*l)>1e-6)return[];if(Math.abs((n[0]-e.a[0])*c-(n[1]-e.a[1])*l)>i)return[];const h=e=>(e[0]-n[0])*o.ux+(e[1]-n[1])*o.uy,d=h(e.a),u=h(e.b),p=Math.max(-s,Math.min(d,u)),_=Math.min(s,Math.max(d,u));return _>=p-i?[[p,_]]:[]});if(!a.length)return!1;a.sort((e,t)=>e[0]-t[0]||e[1]-t[1]);let l=-s;for(const[e,t]of a){if(e>l+i)return!1;if(l=Math.max(l,t),l>=s-i)return!0}return!1}function Lu(e,t,i=1e-9){const n=e.length/(2*e.axis.length),r=e.t-n,o=e.t+n;return t.some(t=>{if(t.host.id!==e.host.id||t.opening.id===e.opening.id)return!1;const n=t.length/(2*t.axis.length);return Math.max(r,t.t-n)`}const br={color:"#607d8b",opacity:1,widthCm:3.6,fill:!1,fillColor:"#607d8b",fillOpacity:.25},wr=(e,t=1)=>{const i=Number(e);return Number.isFinite(i)?Math.min(1,Math.max(0,i)):t},kr=e=>{let t=Number(e);return Number.isFinite(t)?(t=(t%360+360)%360,t>180?t-360:t):0};function xr(e,t,i){return kr(t)?[e.x,e.y]:i([e.x,e.y])}function Sr(e,t,i,n){const r=Math.abs(i[0]-t[0]),o=Math.abs(i[1]-t[1]);return"line"===e?Math.hypot(r,o)>=n:r>=n&&o>=n}const $r=(e,t,i)=>{const n=Number(e),r=Number.isFinite(t)&&t>0?t:5;return Number.isFinite(n)&&n>0?n/r*i:0},Mr=(e,t,i)=>{const n=Number(e),r=Number.isFinite(t)&&t>0?t:5;return Number.isFinite(n)&&i>0?n/i*r:0},Rr=(e,t,i,n=br.widthCm)=>{const r=Number(e?.width_cm);if(Number.isFinite(r)&&r>0)return r;const o=Number(e?.width);return Number.isFinite(o)&&o>0?Mr(o,t,i):n};function Cr(e){const t=br;return e.color===t.color&&e.opacity===t.opacity&&e.widthCm===t.widthCm&&e.fill===t.fill&&e.fillColor===t.fillColor&&e.fillOpacity===t.fillOpacity?null:{color:e.color,opacity:wr(e.opacity),width_cm:Math.max(.1,Math.min(100,Number(e.widthCm)||.1)),fill:!!e.fill,fill_color:e.fillColor,fill_opacity:wr(e.fillOpacity,.25)}}function Tr(e,t){return{color:e.color,opacity:wr(e.opacity),width_cm:Math.max(.1,Math.min(100,Number(e.widthCm)||.1)),...t?{fill:e.fill,fill_color:e.fillColor,fill_opacity:wr(e.fillOpacity,.25)}:{}}}function Dr(e){const t=e.x+e.w/2,i=e.y+e.h/2,n=kr(e.angle)*Math.PI/180,r=Math.cos(n),o=Math.sin(n),s=(e,n)=>{const s=e-t,a=n-i;return[t+s*r-a*o,i+s*o+a*r]};return[s(e.x,e.y),s(e.x+e.w,e.y),s(e.x+e.w,e.y+e.h),s(e.x,e.y+e.h)]}function Ar(e){const t=Dr(e),i=(e,t)=>[(e[0]+t[0])/2,(e[1]+t[1])/2],n=[(t[0][0]+t[2][0])/2,(t[0][1]+t[2][1])/2];return{points:[...t,i(t[0],t[1]),i(t[1],t[2]),i(t[2],t[3]),i(t[3],t[0]),n],segments:t.map((e,i)=>({a:e,b:t[(i+1)%4]}))}}function Pr(e,t,i,n,r,o,s,a){const l=kr(e.angle)*Math.PI/180,c=Math.cos(l),h=Math.sin(l),d=-Math.sin(l),u=Math.cos(l),p=e.x+e.w/2,_=e.y+e.h/2,m=t>0?-e.w/2:e.w/2,g=i>0?-e.h/2:e.h/2,f=p+m*c+g*d,v=_+m*h+g*u,y=n-f,b=r-v;let w=(y*c+b*h)*(t>0?1:-1),k=(y*d+b*u)*(i>0?1:-1),x=null;if(o){const t=w/Math.max(e.w,a),i=k/Math.max(e.h,a);x=Math.max(a/Math.max(e.w,a),a/Math.max(e.h,a),t,i),w=e.w*x,k=e.h*x}if(s>0)if(o){const t=Math.max(1,Math.round(e.w/s)),i=Math.max(1,Math.round(e.h/s));if(Math.abs(e.w-t*s)<1e-6&&Math.abs(e.h-i*s)<1e-6){const n=(e,t)=>{let i=Math.abs(e),n=Math.abs(t);for(;n;)[i,n]=[n,i%n];return Math.max(1,i)},r=1/n(t,i),o=Math.max(a/e.w,a/e.h),s=Math.max(o,Math.round((x??1)/r)*r);w=e.w*s,k=e.h*s}else{e.w>=e.h?(w=Math.round(w/s)*s,k=w*(e.h/Math.max(e.w,a))):(k=Math.round(k/s)*s,w=k*(e.w/Math.max(e.h,a)))}}else w=Math.round(w/s)*s,k=Math.round(k/s)*s;w=Math.max(a,w),k=Math.max(a,k);return{x:f+(t>0?w/2:-w/2)*c+(i>0?k/2:-k/2)*d-w/2,y:v+(t>0?w/2:-w/2)*h+(i>0?k/2:-k/2)*u-k/2,w:w,h:k,angle:kr(e.angle)||void 0}}const Fr=(e,t,i)=>{const n=i[0]-t[0],r=i[1]-t[1],o=n*n+r*r;if(o<1e-12)return[...t];const s=Math.max(0,Math.min(1,((e[0]-t[0])*n+(e[1]-t[1])*r)/o));return[t[0]+n*s,t[1]+r*s]};function zr(e,t,i,n){const r=n(e);let o=null;for(const r of t.points){const t=n(r),s=Math.hypot(t[0]-e[0],t[1]-e[1]);s<=i&&(!o||se.points),segments:e.flatMap(e=>e.segments)}}const Or=Math.tan(.25*Math.PI/180);function Er(e,t){const i=Math.abs(Number(t[0])-Number(e[0])),n=Math.abs(Number(t[1])-Number(e[1]));if(!([i,n].every(Number.isFinite)&&i>0&&n>0))return null;const r=i>=n?"horizontal":"vertical",o=Math.max(i,n),s=Math.min(i,n);return s/o>Or?null:{axis:r,major:o,minor:s,angleDegrees:180*Math.atan2(s,o)/Math.PI}}function Nr(e,t){const i=Er(e,t);return i?"horizontal"===i.axis?[Number(t[0]),Number(e[1])]:[Number(e[0]),Number(t[1])]:[Number(t[0]),Number(t[1])]}const Hr=e=>`${e[0]},${e[1]}`,Lr=(e,t)=>e[0]===t[0]&&e[1]===t[1],Br=(e,t)=>{const i=Hr(e),n=Hr(t);return i{let t=0;for(let i=0;i{if(e.length<3)return!1;for(let t=0;t1e-12},Wr=(e,t)=>Lr(e,t.from)?[...t.to]:[...e],Ur=(e,t)=>e.map(e=>Array.isArray(e?.poly)?{...e,poly:e.poly.map(e=>Wr(e,t))}:e),Vr=(e,t,i)=>{const n=e.flatMap((e,t)=>ei(e)?.some(e=>Lr(e,i.from))?[t]:[]);if(!n.length)return!1;for(const i of n){const n=ei(e[i]),r=ei(t[i]);if(!n||!r)continue;if(!jr(r))return!1;const o=Math.sign(qr(n)),s=Math.sign(qr(r));if(o&&s&&o!==s)return!1}const r=new Set;for(const e of n){const i=ei(t[e]);if(i)for(let n=0;n{let i=0;for(const n of e){const e=ei(n);if(e)for(let n=0;n{const{a:i,b:n,axis:r}=e,o="horizontal"===r?{from:n,to:[n[0],i[1]]}:{from:n,to:[i[0],n[1]]},s="horizontal"===r?{from:i,to:[i[0],n[1]]}:{from:i,to:[n[0],i[1]]};return[{move:o,preservedDegree:Gr(t,i)},{move:s,preservedDegree:Gr(t,n)}].sort((e,t)=>t.preservedDegree-e.preservedDegree||Hr(e.move.to).localeCompare(Hr(t.move.to))||Hr(e.move.from).localeCompare(Hr(t.move.from))).map(e=>e.move)};function Yr(e){const t=JSON.parse(JSON.stringify(e||{}));let i=Array.isArray(t.rooms)?t.rooms:[];const n=new Map;for(const e of i){const t=ei(e);if(t)for(let e=0;ee.key.localeCompare(t.key))){let t=null;for(const n of Kr(e,i)){const e=a.get(Hr(n.from));if(e&&e!==Hr(n.to))continue;const r=Ur(i,n);if(Vr(i,r,n)){t=n,i=r;break}}t?(a.set(Hr(t.from),Hr(t.to)),r++,s=Math.max(s,Math.hypot(t.to[0]-t.from[0],t.to[1]-t.from[1]))):o++}t.rooms=i;for(const e of t.partitions||[]){if(!Array.isArray(e?.a)||!Array.isArray(e?.b))continue;const i=Er(e.a,e.b);if(!i)continue;const n={key:String(e.id||Br(e.a,e.b)),a:[...e.a],b:[...e.b],axis:i.axis};let a=null;for(const i of Kr(n,[{poly:[e.a,e.b]}])){const n=Wr(e.a,i),r=Wr(e.b,i),o=Math.hypot(r[0]-n[0],r[1]-n[1]);if(!(o>0))continue;const s=(t.openings||[]).filter(t=>"partition"===t?.host?.kind&&t.host.id===e.id).every(e=>{const t=Number(e.host.t),i=Number(e.length);return Number.isFinite(t)&&t>=0&&t<=1&&Number.isFinite(i)&&i>0&&t*o-i/2>=-1e-12&&t*o+i/2<=o+1e-12});if(s){a=i,e.a=n,e.b=r;break}}a?(r++,s=Math.max(s,Math.hypot(a.to[0]-a.from[0],a.to[1]-a.from[1]))):o++}return{space:t,report:{wallsStraightened:r,wallsStraightenSkipped:o,maxStraightenShift:s},changed:r>0}}const Xr=["rect","ellipse","furniture","image"],Zr=10**9,Jr=240,Qr=1e-4;function eo(e){if(Array.isArray(e))return e.map(e=>eo(e));if(null!==e&&"object"==typeof e){const t={};for(const[i,n]of Object.entries(e))t[i]=eo(n);return t}return e}function to(e){if("number"!=typeof e||!Number.isFinite(e))return e;const t=(e<0||Object.is(e,-0)?-1:1)*(Math.floor(Math.abs(e)*Zr+.5)/Zr);return 0===t?0:t}function io(e){if("number"!=typeof e||!Number.isFinite(e))return e;const t=e*Jr,i=Math.round(t);if(Math.abs(t-i)null!==ro(e)):[]}function so(e){return"string"==typeof e&&Xr.includes(e)}function ao(e,t){for(const i of t)Object.prototype.hasOwnProperty.call(e,i)&&(e[i]=to(e[i]))}function lo(e,t){for(const i of t)Object.prototype.hasOwnProperty.call(e,i)&&(e[i]=io(e[i]))}function co(e){if(Array.isArray(e))for(let t=0;t{for(const r of n){const n=t[r];"number"==typeof n&&Number.isFinite(n)&&i(n,e)}},n=t=>{if(Array.isArray(t))for(let n=0;n{if(Array.isArray(e))for(const t of e)n(t)};for(const i of oo(e.rooms))t(i,["x","y","w","h"]),r(i.poly);for(const t of oo(e.walls))n(t.a),n(t.b);for(const t of oo(e.wall_segments))n(t.a),n(t.b);for(const i of oo(e.openings))t(i,["x","y"]);for(const i of oo(e.decor))"line"===i.kind?t(i,["x1","y1","x2","y2"]):so(i.kind)?t(i,["x","y","w","h"]):"text"===i.kind&&t(i,["x","y"]);for(const t of oo(e.room_drafts))r(t.points);for(const t of oo(e.partitions))n(t.a),n(t.b);for(const t of oo(e.wall_columns))n(t.center);for(const t of oo(e.open_spans))n(t.a),n(t.b)}const r=ro(t);if(!r)return;const o=new Map;if(n)for(const e of oo(n.spaces))null!=e.id&&o.set(String(e.id),e);for(const e of Object.values(r)){const t=ro(e);if(!t)continue;const n=null!=t.s&&o.get(String(t.s))||null;for(const e of["x","y"]){const r=t[e];"number"==typeof r&&Number.isFinite(r)&&i(r,n)}}}function po(e){const t=Number(e?.cell_cm);return t>0?t:5}function _o(e,t={}){const i={canonicalized:0,far:0,maxShift:0,maxShiftCm:0,spaces:[],bySpace:new Map},n=oo(ro(e)?.spaces);let r=5;for(const e of n)r=Math.max(r,po(e));uo(e,t,(e,t)=>{const n=e*Jr,o=Math.abs(n-Math.round(n)),s=io(e),a=o>0&&o=Qr))return;const l=a&&"number"==typeof s?Math.abs(s-e):0;if(a?i.canonicalized++:i.far++,i.maxShift=Math.max(i.maxShift,l),i.maxShiftCm=Math.max(i.maxShiftCm,l*Jr*(t?po(t):r)),!t?.id||!a)return;const c=String(t.id);let h=i.bySpace.get(c);h||(h={spaceId:c,space:String(t.title||c),canonicalized:0,far:0,maxShift:0,maxShiftCm:0},i.bySpace.set(c,h)),h.canonicalized++,h.maxShift=Math.max(h.maxShift,l),h.maxShiftCm=Math.max(h.maxShiftCm,l*Jr*po(t))}),i.bySpace.size&&uo(e,t,(e,t)=>{if(!t?.id)return;const n=i.bySpace.get(String(t.id));if(!n)return;const r=e*Jr;Math.abs(r-Math.round(r))>=Qr&&n.far++}),i.spaces=[...i.bySpace.values()];const{bySpace:o,...s}=i;return s}function mo(e){return function(e){const t=e,i=ro(t);i&&lo(i,["x","y"]);return t}(eo(e))}function go(e){const t=e,i=ro(t);if(!i)return t;for(const e of Object.values(i)){const t=ro(e);t&&lo(t,["x","y"])}return t}function fo(e){return vo(eo(e))}function vo(e){const t=e,i=ro(t);if(!i)return t;for(const e of oo(i.spaces)){ao(e,["plan_x","plan_y","plan_scale","plan_scale_x","plan_scale_y","plan_angle"]);for(const t of oo(e.rooms))lo(t,["x","y","w","h"]),ho(t.poly);for(const t of oo(e.walls))co(t.a),co(t.b);for(const t of oo(e.wall_segments))co(t.a),co(t.b);for(const t of oo(e.openings)){lo(t,["x","y"]),ao(t,["angle","length"]);const e=ro(t.host);e&&ao(e,["t"])}for(const t of oo(e.decor))"line"===t.kind?lo(t,["x1","y1","x2","y2"]):so(t.kind)?(lo(t,["x","y","w","h"]),ao(t,["angle"])):"text"===t.kind&&(lo(t,["x","y"]),ao(t,["scale","angle"]));for(const t of oo(e.room_drafts))ho(t.points);for(const t of oo(e.partitions))co(t.a),co(t.b);for(const t of oo(e.wall_columns))co(t.center),"square"===t.shape&&ao(t,["angle"]);for(const t of oo(e.open_spans))co(t.a),co(t.b)}for(const e of oo(i.markers))ao(e,["angle"]);return t}const yo=15,bo=8;function wo(e,t,i,n,r){const o=i[0]-e[0],s=i[1]-e[1],a=Math.hypot(o,s);if(!(a>0)||a<=r+1e-9)return null;const l=o/a,c=s/a,h=t=>{const n=(t[0]-e[0])*l+(t[1]-e[1])*c,o=(r-n)/(a-n);return!Number.isFinite(o)||o<-1e-9||o>1+1e-9?null:[t[0]+(i[0]-t[0])*o,t[1]+(i[1]-t[1])*o]},d=h(t),u=h(n);return d&&u?[[e[0],e[1]],t,d,u,n]:null}const ko=Math.sin(.25*Math.PI/180);function xo(e,t){return Number.isFinite(e)&&e>0&&Number.isFinite(t)&&t>0&&e*t<3}function So(e){const t=Number(e)>0?Number(e):5;if(5===t)return 8;const i=5/t*8;return Math.min(80,Math.max(.5,i))}function $o(e,t){return Number.isFinite(e)&&e>0&&Number.isFinite(t)&&t>0&&e*t<2}function Mo(e){return Number.isFinite(e)?Math.max(1,Math.min(100,e)):1}function Ro(e,t){return!Number.isFinite(e)||e<0?"":String(t?Math.round(e/2.54*100)/100:Math.round(100*e)/100)}function Co(e,t,i){if(!Number.isFinite(e)||e<=0)return 0;const n=Number(t)>0?Number(t):5;return Mo(e)/n*i}function To(e,t){return t>0&&Number.isFinite(e)?Math.round(e/t)*t:e}function Do(e){return Math.max(1e-6*Math.abs(e),1e-9)}function Ao(e,t){if(!(t>0&&Number.isFinite(e)))return e;const i=To(e,t);return Math.abs(i-e)<=Do(t)?i:e}function Po(e,t){let i=t[0]-e[0],n=t[1]-e[1];const r=Math.hypot(i,n);return r<1e-12?[1,0]:(i/=r,n/=r,(i<-1e-12||Math.abs(i)<=1e-12&&n<0)&&(i=-i,n=-n),[i,n])}function Fo(e,t,i){const n=[Ao(e[0],i),Ao(e[1],i)],r=[Ao(t[0],i),Ao(t[1],i)],o=To((n[0]+r[0])/2,i),s=To((n[1]+r[1])/2,i),[a,l]=Po(n,r);let c=Math.atan2(l,a);c<0&&(c+=Math.PI);const h=Math.round(1800*c)/1800,d=i>0&&i<.01?6:i<1?4:2;return`${o.toFixed(d)},${s.toFixed(d)}@${h.toFixed(4)}`}function zo(e,t,i,n){return 1===n?Fo(e,t,i):Fo([e[0]/n,e[1]/n],[t[0]/n,t[1]/n],i)}function Io(e,t){if(!Array.isArray(e.a)||!Array.isArray(e.b)||e.a.length<2||e.b.length<2)return null;const i=[Number(e.a[0]),Number(e.a[1]),Number(e.b[0]),Number(e.b[1])];if(!i.every(Number.isFinite))return null;const n=t>0?t:1;return[[i[0]*n,i[1]*n],[i[2]*n,i[3]*n]]}function Oo(e,t,i,n,r){const o=r>0?r:1;return{key:zo(e,t,n,o),cm:Mo(i),a:[e[0]/o,e[1]/o],b:[t[0]/o,t[1]/o]}}function Eo(e,t){const i=t>0?t:1,n=[];for(const t of e){const e=t.key.lastIndexOf("@");if(e<0)continue;const[r,o]=t.key.slice(0,e).split(",").map(Number),s=Number(t.key.slice(e+1));[r,o,s].every(Number.isFinite)&&n.push({w:t,x:r*i,y:o*i,ang:s})}return n}function No(e,t){const[i,n]=Po(e,t);let r=Math.atan2(n,i);return r<0&&(r+=Math.PI),r}function Ho(e,t){let i=Math.abs(e-t);return i>Math.PI/2&&(i=Math.PI-i),i<.02}function Lo(e,t,i,n,r=1){if(!e?.length)return null;const o=zo(t,i,n,r),s=e.find(e=>e.key===o);if(s)return s;const a=r>0?r:1,l=Do(n)*a,c=(e,t)=>Math.abs(e[0]-t[0])<=l&&Math.abs(e[1]-t[1])<=l;for(const n of e){const e=Io(n,a);if(e&&(c(e[0],t)&&c(e[1],i)||c(e[0],i)&&c(e[1],t)))return n}const h=(t[0]+i[0])/2,d=(t[1]+i[1])/2,u=No(t,i),p=Math.max(.5*n,1e-9)*a;for(const t of Eo(e,a))if(Ho(t.ang,u)&&Math.hypot(t.x-h,t.y-d)<=p)return t.w;return null}function Bo(e,t,i,n,r=1){const o=Lo(e,t,i,n,r);if(o&&o.cm>0)return Mo(o.cm);const s=function(e,t,i,n,r){if(!e?.length)return null;const o=r>0?r:1,s=Math.hypot(i[0]-t[0],i[1]-t[1]);if(s<1e-12)return null;const a=No(t,i),l=Math.max(.5*n,1e-9)*o;let c=null;for(const n of e){if(!(n.cm>0))continue;const e=Io(n,o);if(!e)continue;const r=Math.hypot(e[1][0]-e[0][0],e[1][1]-e[0][1]);if(r<1e-12||!Ho(No(e[0],e[1]),a))continue;if(Ds(t[0],t[1],e[0][0],e[0][1],e[1][0],e[1][1])>l||Ds(i[0],i[1],e[0][0],e[0][1],e[1][0],e[1][1])>l)continue;if(r+l(o.has(e.key)||(e=>{const t=Io(e,n);if(!t)return!1;const[i,o]=t,a=o[0]-i[0],c=o[1]-i[1],h=Math.hypot(a,c);if(h<=l)return!1;if(!s.some(e=>{const t=[e[0],e[1]],n=[e[2],e[3]];return Ho(No(i,o),No(t,n))&&Ds(i[0],i[1],t[0],t[1],n[0],n[1])<=l&&Ds(o[0],o[1],t[0],t[1],n[0],n[1])<=l}))return!1;const d=(r||[]).some(e=>{const t=[e[0],e[1]],n=[e[2],e[3]];if(!Ho(No(i,o),No(t,n)))return!1;const r=e=>Math.abs((e[0]-i[0])*c-(e[1]-i[1])*a)/h;if(r(t)>l||r(n)>l)return!1;const s=h*h,d=((t[0]-i[0])*a+(t[1]-i[1])*c)/s,u=((n[0]-i[0])*a+(n[1]-i[1])*c)/s;return Math.min(1,Math.max(d,u))-Math.max(0,Math.min(d,u))>l/h});return!d})(e))&&e.cm>=1&&e.cm<=100)}function jo(e,t,i,n=8){const[r,o]=Po(e,t);let s=Math.atan2(o,r);s<0&&(s+=Math.PI);let a=i*Math.PI/180%Math.PI;a<0&&(a+=Math.PI);let l=Math.abs(s-a);return l>Math.PI/2&&(l=Math.PI-l),l<=n*Math.PI/180}function Wo(e,t,i,n,r=1,o="affine",s){if(!e?.length)return[];if(t.length!==i.length)return"fixed-topology"===o&&s?.(),e.slice();const a=r>0?r:1,l=Math.max(.5*n,1e-9)*a,c=Math.max(n*a*1e-6,1e-9),h=[],d=new Map,u=new Map,p=(e,t,i)=>{const n=e.get(t)||new Set;n.add(i),e.set(t,n)};for(let e=0;e[e[0]+(t[0]-e[0])*i,e[1]+(t[1]-e[1])*i],m=(e,t)=>Math.hypot(e[0]-t[0],e[1]-t[1])<=c,g=(e,t)=>{if("fixed-topology"===o){const i=t.na[0]-t.oa[0],n=t.na[1]-t.oa[1],r=t.nb[0]-t.ob[0],o=t.nb[1]-t.ob[1];return Math.hypot(i-r,n-o)<=c?[e[0]+i,e[1]+n]:m(e,t.oa)?[...t.na]:m(e,t.ob)?[...t.nb]:[...e]}const i=Math.max(0,Math.min(1,((e[0]-t.oa[0])*t.dx+(e[1]-t.oa[1])*t.dy)/t.len2));return _(t.na,t.nb,i)},f=(e,t)=>{const[i,n]=Po(e,t);return(t[0]-e[0])*i+(t[1]-e[1])*n>=0?[[...e],[...t]]:[[...t],[...e]]},v=[],y=[],b=(e,t,i)=>{if(Math.hypot(t[0]-e[0],t[1]-e[1])<=c)return;const[r,o]=f(e,t),s=Mo(i);if(y.some(e=>e.entry.cm===s&&m(e.span[0],r)&&m(e.span[1],o)))return;const l=Oo(r,o,s,n,a);v.push(l),y.push({entry:l,span:[r,o]})};for(const t of e){const e=Io(t,a);if(e){const[i,n]=f(e[0],e[1]),r=n[0]-i[0],s=n[1]-i[1],a=r*r+s*s,d=Math.sqrt(a);if(d<=c){v.push({...t,cm:Mo(t.cm)});continue}const u=[];for(const e of h){if(!Ho(No(i,n),No(e.oa,e.ob)))continue;const t=e=>Math.abs((e[0]-i[0])*s-(e[1]-i[1])*r)/d;if(t(e.oa)>l||t(e.ob)>l)continue;const o=((e.oa[0]-i[0])*r+(e.oa[1]-i[1])*s)/a,h=((e.ob[0]-i[0])*r+(e.ob[1]-i[1])*s)/a,p=Math.max(0,Math.min(o,h)),_=Math.min(1,Math.max(o,h));(_-p)*d>c&&u.push({lo:p,hi:_,move:e})}if(!u.length){"fixed-topology"===o?v.push({...t}):b(i,n,t.cm);continue}const p=[0,1,...u.flatMap(({lo:e,hi:t})=>[e,t])].sort((e,t)=>e-t).filter((e,t,i)=>0===t||Math.abs(e-i[t-1])*d>c),y=[];for(let e=0;e+1a>=e.lo-1e-12&&a<=e.hi+1e-12);if(!l.length){y.push([o,s]);continue}const h=[g(o,l[0].move),g(s,l[0].move)],f=l.slice(1).some(e=>{const t=g(o,e.move),i=g(s,e.move);return!m(h[0],t)||!m(h[1],i)});y.push(f?[o,s]:h)}const w=(e,t)=>{const i=e[1][0]-e[0][0],n=e[1][1]-e[0][1],r=t[1][0]-t[0][0],o=t[1][1]-t[0][1],s=Math.hypot(i,n);return!(s<=c||i*r+n*o<=0)&&Math.abs(i*o-n*r)/s<=c},k=[];for(const e of y){const t=k[k.length-1];t&&m(t[1],e[0])&&w(t,e)?t[1]=e[1]:k.push([[...e[0]],[...e[1]]])}if("fixed-topology"===o&&1===k.length){const[i,n]=k[0];if(m(i,e[0])&&m(n,e[1])||m(i,e[1])&&m(n,e[0])){v.push({...t});continue}}for(const[e,i]of k)b(e,i,t.cm);continue}if("fixed-topology"===o){const e=u.get(t.key);if(1===e?.size){const i=[...e][0];v.push(i===t.key?{...t}:{...t,key:i});continue}const i=[Eo([t],a)[0]];1!==a&&i.push(Eo([t],1)[0]);const n=i.filter(Boolean).some(e=>h.some(t=>{if(!Ho(e.ang,No(t.oa,t.ob)))return!1;const i=((e.x-t.oa[0])*t.dx+(e.y-t.oa[1])*t.dy)/t.len2;return i>=-1e-6&&i<=1.000001&&Ds(e.x,e.y,t.oa[0],t.oa[1],t.ob[0],t.ob[1])<=l}));((e?.size||0)>1||n)&&s?.(),v.push({...t});continue}let i="";const r=d.get(t.key);if(1===r?.size&&(i=[...r][0]),!i){const e=Eo([t],a)[0];if(e){const t=new Set;for(const i of h){if(!Ho(e.ang,No(i.oa,i.ob)))continue;const r=((e.x-i.oa[0])*i.dx+(e.y-i.oa[1])*i.dy)/i.len2;if(r<-1e-6||r>1.000001)continue;if(Ds(e.x,e.y,i.oa[0],i.oa[1],i.ob[0],i.ob[1])>l)continue;const o=g([e.x,e.y],i),[s,c]=Po(i.na,i.nb),h=Math.max(n*a,1e-6);t.add(zo([o[0]-s*h,o[1]-c*h],[o[0]+s*h,o[1]+c*h],n,a))}1===t.size&&(i=[...t][0])}}v.push({...t,key:i||t.key,cm:Mo(t.cm)})}return v}function Uo(e,t,i,n,r=1,o="affine"){return Wo(e,t,i,n,r,o)}function Vo(e,t,i,n,r=1,o="fixed-topology"){let s=!1;const a=Wo(e,t,i,n,r,o,()=>{s=!0});return{walls:s?(e||[]).map(e=>({...e})):a,rejected:s}}function Go(e,t,i,n=1,r=[]){const o=n>0?n:1,s=Math.abs(i),a=Math.max(s*o*Qr,1e-9),l=(r||[]).flatMap(e=>{const t=Io(e,o);return t?t.map(e=>[...e]):[]}),c=e=>e.every((e,t)=>(e=>{if(!(s>0))return!0;const t=e/o/s;return Math.abs(t-Math.round(t))Math.abs(e-i[t])<=a)),h=[],d=e=>JSON.stringify([e.key,e.cm,e.a,e.b]);for(const i of e||[]){const e=Io(i,o);if(!e)continue;const[n,r]=e;if(![n[0],n[1],r[0],r[1]].every(Number.isFinite)||!c(n)||!c(r)){h.push(d(i));continue}const s=r[0]-n[0],l=r[1]-n[1],u=Math.hypot(s,l);if(u<=a){h.push(d(i));continue}const p=s/u,_=l/u,m=[];for(const e of t){const[t,i]=e;if(![t?.[0],t?.[1],i?.[0],i?.[1]].every(Number.isFinite))continue;const r=e=>Math.abs((e[0]-n[0])*_-(e[1]-n[1])*p);if(r(t)>a||r(i)>a)continue;const o=(t[0]-n[0])*p+(t[1]-n[1])*_,s=(i[0]-n[0])*p+(i[1]-n[1])*_,l=Math.max(0,Math.min(o,s)),c=Math.min(u,Math.max(o,s));c-l>a&&m.push([l,c])}m.sort((e,t)=>e[0]-t[0]||e[1]-t[1]);let g=0;for(const[e,t]of m){if(e>g+a)break;if(g=Math.max(g,t),g>=u-a)break}ge.key!==s);return null==n||n<1?a:[...a,Oo(t,i,n,r,o)]}function Yo(e,t,i,n,r,o=[],s=1){let a=e?e.slice():[];for(const e of function(e,t,i,n,r=1,o=[]){const s=gs(e,t,i,n,r,o);if(!s)return[];const a=[];for(let e=0;e0||(c=Ko(c,t,i,n,r,s)))}return c}function Zo(e){const{a:t,b:i,halfDepth:n}=e;if(!Array.isArray(t)||!Array.isArray(i)||t.length<2||i.length<2||![t[0],t[1],i[0],i[1]].every(Number.isFinite))return null;const r=i[0]-t[0],o=i[1]-t[1],s=Math.hypot(r,o);if(!(s>1e-9&&n>0&&Number.isFinite(n)))return null;const a=-o/s*n,l=r/s*n;return[[t[0]+a,t[1]+l],[i[0]+a,i[1]+l],[i[0]-a,i[1]-l],[t[0]-a,t[1]-l]]}function Jo(e,t,i){return Math.hypot(e[0]-t[0],e[1]-t[1])<=i}function Qo(e,t,i){const n=t.b[0]-t.a[0],r=t.b[1]-t.a[1],o=n*n+r*r;if(!(o>i*i))return!1;const s=((e[0]-t.a[0])*n+(e[1]-t.a[1])*r)/o;if(!(s>0&&s<1))return!1;const a=[t.a[0]+n*s,t.a[1]+r*s];return Math.hypot(e[0]-a[0],e[1]-a[1])<=i}function es(e,t,i,n){const r=Math.hypot(t,i);if(!(r>1e-9&&n>0))return;const o=[t/r,i/r],s=e.find(e=>Math.abs(e.u[0]*o[1]-e.u[1]*o[0])<1e-9&&e.u[0]*o[0]+e.u[1]*o[1]>1-1e-9);s?s.halfDepth=Math.max(s.halfDepth,n):e.push({u:o,halfDepth:n})}function ts(e,t){try{const i=jt(Fs(e),Fs(t));let n=null,r=0;for(const e of i||[]){const t=e?.[0]||[],i=Math.abs(as(t));t.length>=4&&i>r&&(r=i,n=t.slice(0,-1).map(e=>[e[0],e[1]]))}return n}catch{return null}}function is(e,t=1e-6){const i=(e||[]).map((e,t)=>({segment:e,index:t})).filter(({segment:e})=>e&&Array.isArray(e.a)&&Array.isArray(e.b)&&e.a.length>=2&&e.b.length>=2&&e.a.every(Number.isFinite)&&e.b.every(Number.isFinite)&&Number.isFinite(e.halfDepth)&&e.halfDepth>0&&Math.hypot(e.b[0]-e.a[0],e.b[1]-e.a[1])>1e-9);if(i.length<2)return[];const n=Math.max(Number.isFinite(t)?t:0,1e-9),r=i.flatMap(({segment:e})=>[e.a,e.b]).map(e=>[e[0],e[1]]).sort((e,t)=>e[0]-t[0]||e[1]-t[1]),o=[];for(const e of r)o.some(t=>Jo(t,e,n))||o.push(e);const s=[];for(const e of o){const t=[];let r=!1;for(const{segment:o,index:s}of i){const i=Math.hypot(o.b[0]-o.a[0],o.b[1]-o.a[1]);Jo(e,o.a,n)?t.push({u:[(o.b[0]-o.a[0])/i,(o.b[1]-o.a[1])/i],halfDepth:o.halfDepth,length:i,index:s}):Jo(e,o.b,n)?t.push({u:[(o.a[0]-o.b[0])/i,(o.a[1]-o.b[1])/i],halfDepth:o.halfDepth,length:i,index:s}):Qo(e,o,n)&&(r=!0)}if(r||2!==t.length)continue;const[o,a]=t,l=o.u[0]*a.u[1]-o.u[1]*a.u[0];if(Math.abs(l)<1e-9)continue;const c=l<0?1:-1,h=[-o.u[1],o.u[0]],d=[-a.u[1],a.u[0]],u=[e[0]+h[0]*o.halfDepth*c,e[1]+h[1]*o.halfDepth*c],p=[e[0]-d[0]*a.halfDepth*c,e[1]-d[1]*a.halfDepth*c];if(!hs(u,o.u,p,a.u))continue;const _=[[o,a,p,[d[0]*-c,d[1]*-c]],[a,o,u,[h[0]*c,h[1]*c]]];for(const[t,,i,r]of _){const o=Math.min(2*t.halfDepth,t.length),a=[-t.u[1]*t.halfDepth,t.u[0]*t.halfDepth],l=[[e[0]+a[0],e[1]+a[1]],[e[0]+t.u[0]*o+a[0],e[1]+t.u[1]*o+a[1]],[e[0]+t.u[0]*o-a[0],e[1]+t.u[1]*o-a[1]],[e[0]-a[0],e[1]-a[1]]],c=e=>(e[0]-i[0])*r[0]+(e[1]-i[1])*r[1],h=[];for(let e=0;e=-1e-12&&h.push(t),n>1e-12&&r<-1e-12||n<-1e-12&&r>1e-12){const e=n/(n-r);h.push([t[0]+(i[0]-t[0])*e,t[1]+(i[1]-t[1])*e])}}h.length>=3&&Math.abs(as(h))>n*n&&s.push({segmentIndex:t.index,wedge:h})}}return s}function ns(e,t=1e-6){const i=(e||[]).filter(e=>e&&Array.isArray(e.a)&&Array.isArray(e.b)&&e.a.length>=2&&e.b.length>=2&&e.a.every(Number.isFinite)&&e.b.every(Number.isFinite)&&Number.isFinite(e.halfDepth)&&e.halfDepth>0&&Math.hypot(e.b[0]-e.a[0],e.b[1]-e.a[1])>1e-9);if(i.length<2)return[];const n=Math.max(Number.isFinite(t)?t:0,1e-9),r=i.flatMap(e=>[e.a,e.b]).map(e=>[e[0],e[1]]).sort((e,t)=>e[0]-t[0]||e[1]-t[1]),o=[];for(const e of r)o.some(t=>Jo(t,e,n))||o.push(e);const s=[],a=i.map((e,t)=>({roomId:"",a:[e.a[0],e.a[1]],b:[e.b[0],e.b[1]],key:`join-${t}`,kind:"outer",cm:0,open:!1,half:e.halfDepth})),l=ws(a,n);for(const e of ks(l).fans)s.push(e);const c=e=>!!xs(l,e);for(const e of o){if(c(e))continue;const t=[];for(const r of i)Jo(e,r.a,n)?es(t,r.b[0]-r.a[0],r.b[1]-r.a[1],r.halfDepth):Jo(e,r.b,n)?es(t,r.a[0]-r.b[0],r.a[1]-r.b[1],r.halfDepth):Qo(e,r,n)&&(es(t,r.a[0]-e[0],r.a[1]-e[1],r.halfDepth),es(t,r.b[0]-e[0],r.b[1]-e[1],r.halfDepth));if(!(t.length<2)){t.sort((e,t)=>Math.atan2(e.u[1],e.u[0])-Math.atan2(t.u[1],t.u[0])||e.halfDepth-t.halfDepth);for(let i=0;in*n&&s.push(m)}}}return s}function rs(e,t,i,n){if(!(t>0)||!e||e.length<2)return"";if(i&&e.length>=3){let i=e;const r=e[e.length-1];if(e.length>=4&&Math.hypot(e[0][0]-r[0],e[0][1]-r[1])<1e-9&&(i=e.slice(0,-1)),i.length>=3){const e=i.map((e,i)=>n?.[i]||t),r=Qs(i,e),o=ps(i,e);if(r&&o)return`${_s(r)} ${_s(ms(o))}`}}const r=[];for(let i=0;i=1e-9&&a>0&&r.push({a:o,b:s,halfDepth:a})}const o=r.map(Zo);for(const{segmentIndex:e,wedge:t}of is(r)){const i=o[e];if(!i)continue;const n=ts(i,t);n&&(o[e]=n)}const s=[...o.filter(e=>!!e),...ns(r)],a=function(e){let t=null;try{for(const i of e){if(i.length<3)continue;const e=Fs(i);t=t?Bt(t,e):[e]}return t}catch{return null}}(s);return a?Us(a):s.map(e=>_s(e)).join(" ")}function os(e,t,i,n,r=1){if(!i.length)return!1;const o=ss(n,r),s=(e[0]+t[0])/2,a=(e[1]+t[1])/2,[l,c]=Po(e,t);for(const e of i){const[t,i]=Po([e[0],e[1]],[e[2],e[3]]);if(!(Math.abs(l*i-c*t)>.05)&&Ds(s,a,e[0],e[1],e[2],e[3])<=o)return!0}return!1}function ss(e,t){return Math.max(e*(t>0?t:1)*.04,1e-9)}function as(e){let t=0;for(let i=0;ie[1]!=l>e[1]&&e[0]<(a-o)*(e[1]-s)/(l-s+0)+o&&(i=!i)}return i}([c[0]+.001*a,c[1]+.001*l],e)||(a=-a,l=-l),[a,l]}function cs(e,t){const i=e[0]*t[1]-e[1]*t[0],n=e[0]*t[0]+e[1]*t[1];return Math.abs(i)<1e-9&&n>0}function hs(e,t,i,n){const r=t[0]*n[1]-t[1]*n[0];if(Math.abs(r)<1e-12)return null;const o=[i[0]-e[0],i[1]-e[1]],s=(o[0]*n[1]-o[1]*n[0])/r;return[e[0]+s*t[0],e[1]+s*t[1]]}function ds(e,t,i){const n=e?.length||0;if(n<3||!Array.isArray(i)||i.length!==n)return 0;const r=(Math.trunc(t)%n+n)%n,o=e[r],s=e[(r+1)%n],a=s[0]-o[0],l=s[1]-o[1],c=Math.hypot(a,l);if(!(c>0))return 0;const h=Math.max(0,Number(i[r])||0);if(!(h>0))return c;const d=[a/c,l/c],u=ls(e,r),p=[o[0]+u[0]*h,o[1]+u[1]*h],_=t=>{const r=Math.max(0,Number(i[t])||0);if(!(r>0))return null;const s=e[t],a=e[(t+1)%n],l=a[0]-s[0],c=a[1]-s[1],h=Math.hypot(l,c);if(!(h>0))return null;const u=ls(e,t),_=hs(p,d,[s[0]+u[0]*r,s[1]+u[1]*r],[l/h,c/h]);return _?(_[0]-o[0])*d[0]+(_[1]-o[1])*d[1]:null},m=_((r-1+n)%n)??0,g=(_((r+1)%n)??c)-m;return g>0?g:0}function us(e,t,i,n,r,o,s,a=1){const l=(e||[]).find(e=>e?.id===t),c=ei(l);if(!c||c.length<3)return null;const h=$s(e,t,i,n,r,o,s,a);if(!h)return c.map(()=>0);const d=4*ss(r,a);return c.map((e,t)=>{const i=c[(t+1)%c.length],n=[(e[0]+i[0])/2,(e[1]+i[1])/2];for(let e=0;e!(e>0)))return e.map(e=>[e[0],e[1]]);const r=[];for(let o=0;o0||u>0)){r.push([e[o][0],e[o][1]]);continue}if(d>0!=u>0){const t=e[o],i=d>0?[t[0]+p*d,t[1]+_*d]:[t[0],t[1]],n=u>0?[t[0]+m*u,t[1]+g*u]:[t[0],t[1]];r.push(i),Math.hypot(n[0]-i[0],n[1]-i[1])>1e-9&&r.push(n);continue}if(cs(w,k)){const t=e[o],i=[t[0]+p*d,t[1]+_*d],n=[t[0]+m*u,t[1]+g*u];r.push(i),Math.hypot(n[0]-i[0],n[1]-i[1])>1e-9&&r.push(n);continue}const $=hs(x,w,S,k),M=Math.max(d,u,1e-9),R=xs(i,e[o])?.limit??4*M;if($){const i=Math.hypot($[0]-e[o][0],$[1]-e[o][1]);if(Number.isFinite(i)&&i<=R){r.push($);continue}if(Gs(e,t,o)){r.push($);continue}}d>0&&r.push([e[o][0]+p*d,e[o][1]+_*d]),u>0&&r.push([e[o][0]+m*u,e[o][1]+g*u]),d>0||u>0||r.push([e[o][0],e[o][1]])}return r.length>=3?r:null}function _s(e,t=!0){if(!e.length)return"";let i=`M ${e[0][0]} ${e[0][1]}`;for(let t=1;te?.id===t),a=ei(s);if(!a||a.length<3)return null;const l=ss(n,r),c=[];for(const i of e||[]){if(!i||i.id===t)continue;const e=ei(i);if(e)for(const t of Cn(a,e,l))c.push([t[0],t[1]],[t[2],t[3]])}for(const e of i||[])c.push([e[0],e[1]],[e[2],e[3]]);for(const e of o||[]){const t=Io(e,r);t&&c.push(t[0],t[1])}const h=[],d=[];for(let e=0;el)continue;const s=((e[0]-t[0])*(i[0]-t[0])+(e[1]-t[1])*(i[1]-t[1]))/(n*n);s<=r||s>=1-r||(o.some(e=>Math.abs(e-s)*n<=2*l)||o.push(s))}o.sort((e,t)=>e-t);for(const n of o)h.push([t[0]+(i[0]-t[0])*n,t[1]+(i[1]-t[1])*n]),d.push(e)}return{poly:h,parent:d,orig:a}}function fs(e,t,i,n){const r=t.poly.length,o=new Array(r).fill(0);if(!e?.length)return o;const s=new Set,a=[];for(let l=0;l0?(o[l]=Mo(c.cm),s.add(c.key)):a.push(l)}if(!a.length)return o;const l=n>0?n:1,c=Math.max(.5*i,1e-9)*l,h=Eo(e,l).filter(e=>e.w.cm>0);for(let e=a.length-1;e>=0;e--){const i=a[e],n=t.poly[i],s=t.poly[(i+1)%r],d=No(n,s);let u=null;for(const e of h){const t=Io(e.w,l);if(!t||!Ho(No(t[0],t[1]),d))continue;if(Ds(n[0],n[1],t[0][0],t[0][1],t[1][0],t[1][1])>c||Ds(s[0],s[1],t[0][0],t[0][1],t[1][0],t[1][1])>c)continue;const i=Math.hypot(s[0]-n[0],s[1]-n[1]),r=Math.hypot(t[1][0]-t[0][0],t[1][1]-t[0][1]),o=Math.max(0,r-i);(!u||oc||Ds(r[0],r[1],t[0][0],t[0][1],t[1][0],t[1][1])>c)continue;i=!0,o=Math.max(0,Math.hypot(t[1][0]-t[0][0],t[1][1]-t[0][1])-_)}else{if(Ds(e.x,e.y,n[0],n[1],r[0],r[1])>c)continue;o=Math.hypot(e.x-d,e.y-u)}(!p||i&&!p.exact||i===p.exact&&o0?i:1,o=(e||[]).filter(e=>e&&!e.open&&null!==e.kind&&Number.isFinite(e.half)&&e.half>0&&Array.isArray(e.a)&&Array.isArray(e.b)&&e.a.length>=2&&e.b.length>=2&&[e.a[0],e.a[1],e.b[0],e.b[1]].every(Number.isFinite)&&Math.hypot(e.b[0]-e.a[0],e.b[1]-e.a[1])>n).sort((e,t)=>e.key.localeCompare(t.key)||e.a[0]-t.a[0]||e.a[1]-t.a[1]||e.b[0]-t.b[0]||e.b[1]-t.b[1]||e.half-t.half),s=new Map;for(const e of o){const t=s.get(e.key);t?e.half>t.half&&s.set(e.key,{...t,half:e.half}):s.set(e.key,e)}const a=[...s.values()].flatMap(e=>[{point:[e.a[0],e.a[1]],other:e.b,halfDepth:e.half,kind:e.kind,key:e.key},{point:[e.b[0],e.b[1]],other:e.a,halfDepth:e.half,kind:e.kind,key:e.key}]).sort((e,t)=>e.point[0]-t.point[0]||e.point[1]-t.point[1]||e.other[0]-t.other[0]||e.other[1]-t.other[1]||e.halfDepth-t.halfDepth),l=new Map;for(const e of a){const[t,i]=vs(e.point,n),r=ys(t,i),o=l.get(r)||[];o.push(e),l.set(r,o)}const c=[],h=new Map;for(const e of a){const t=bs(h,e.point,n).filter(t=>Math.hypot(t.point[0]-e.point[0],t.point[1]-e.point[1])<=n).sort((t,i)=>Math.hypot(t.point[0]-e.point[0],t.point[1]-e.point[1])-Math.hypot(i.point[0]-e.point[0],i.point[1]-e.point[1])||t.point[0]-i.point[0]||t.point[1]-i.point[1]);let i=t[0];if(!i){i={point:[...e.point],rays:[]},c.push(i);const[t,r]=vs(i.point,n),o=ys(t,r),s=h.get(o)||[];s.push(i),h.set(o,s)}const r=e.other[0]-e.point[0],o=e.other[1]-e.point[1],s=Math.hypot(r,o);if(!(s>n))continue;const a=[r/s,o/s];let l=Math.atan2(a[1],a[0]);l<0&&(l+=2*Math.PI),i.rays.push({u:a,halfDepth:e.halfDepth,length:s,angle:l})}const d=[],u=e=>{const t=1e-9*Math.max(1,r),i=e.filter(e=>Number.isFinite(e.halfDepth)&&e.halfDepth>0&&Number.isFinite(e.length)&&e.length>n);return i.filter((e,n)=>!i.some((i,r)=>r!==n&&i.halfDepth>=e.halfDepth-t&&i.length>=e.length-t&&(i.halfDepth>e.halfDepth+t||i.length>e.length+t||re.length-t.length||e.halfDepth-t.halfDepth).map(e=>({...e}))};for(const e of c){const t=e.rays.sort((e,t)=>e.angle-t.angle||e.length-t.length||e.halfDepth-t.halfDepth),i=[];for(const e of t){const t=i[i.length-1];t&&Math.abs(e.angle-t.angle)<=1e-9?t.supports.push({halfDepth:e.halfDepth,length:e.length}):i.push({u:[...e.u],angle:e.angle,supports:[{halfDepth:e.halfDepth,length:e.length}]})}if(i.length>1&&2*Math.PI-i[i.length-1].angle+i[0].angle<=1e-9){const e=i.pop();i[0].supports.push(...e.supports)}if(i.length<3)continue;const r=i.map(t=>{const i=u(t.supports),r=new Set,o=[];for(const s of i){const i=[e.point[0]+t.u[0]*s.length,e.point[1]+t.u[1]*s.length];for(const t of bs(l,i,n)){if("shared"!==t.kind||Math.hypot(t.point[0]-i[0],t.point[1]-i[1])>n)continue;const s=t.other[0]-t.point[0],a=t.other[1]-t.point[1],l=Math.hypot(s,a);if(!(l>n))continue;const c=s/l,h=a/l;if(Math.hypot(t.other[0]-e.point[0],t.other[1]-e.point[1])<=n)continue;const d=`${t.key}|${t.point[0]}|${t.point[1]}|${t.other[0]}|${t.other[1]}|${t.halfDepth}`;r.has(d)||(r.add(d),o.push({start:[t.point[0],t.point[1]],u:[c,h],length:l,halfDepth:t.halfDepth}))}}return o.sort((e,t)=>e.start[0]-t.start[0]||e.start[1]-t.start[1]||e.u[0]-t.u[0]||e.u[1]-t.u[1]||e.length-t.length||e.halfDepth-t.halfDepth),{u:[...t.u],halfDepth:Math.max(...i.map(e=>e.halfDepth)),length:Math.max(...i.map(e=>e.length)),supports:i,continuations:o}}).filter(e=>Number.isFinite(e.halfDepth)&&e.halfDepth>0&&Number.isFinite(e.length)&&e.length>n);if(r.length<3)continue;const o=Math.max(...r.map(e=>e.halfDepth));o>0&&Number.isFinite(o)&&d.push({point:[...e.point],rays:r,halfDepth:o,limit:1.25*o})}d.sort((e,t)=>e.point[0]-t.point[0]||e.point[1]-t.point[1]);const p=new Map;for(const e of d){const[t,i]=vs(e.point,n),r=ys(t,i),o=p.get(r)||[];o.push(e),p.set(r,o)}return{epsilon:n,coordinateScale:r,nodes:d,index:p}}function ks(e){const t={fans:[],supports:[]};if(!e?.nodes?.length)return t;const i=Math.max(e.epsilon,1e-9)**2;for(const n of e.nodes){const e=n.rays.filter(e=>Number.isFinite(e.halfDepth)&&e.halfDepth>0).map(e=>({...e,thickLength:Math.max(...e.supports.filter(t=>t.halfDepth>=e.halfDepth-1e-12).map(e=>e.length),0),angle:(()=>{const t=Math.atan2(e.u[1],e.u[0]);return t<0?t+2*Math.PI:t})()})).sort((e,t)=>e.angle-t.angle);if(e.length<2)continue;const r=n.point;for(const i of e)for(const e of i.supports){if(!(e.halfDepth>0&&e.length>0))continue;const n=-i.u[1]*e.halfDepth,o=i.u[0]*e.halfDepth,s=[r[0]+i.u[0]*e.length,r[1]+i.u[1]*e.length];t.supports.push([[r[0]+n,r[1]+o],[s[0]+n,s[1]+o],[s[0]-n,s[1]-o],[r[0]-n,r[1]-o]])}for(let n=0;n{const e=s.angle-o.angle;return e>0?e:e+2*Math.PI})();if(a<1e-9)continue;const l=a>Math.PI+1e-9,c=4*Math.max(o.halfDepth,s.halfDepth),h=[r[0]-o.u[1]*o.halfDepth,r[1]+o.u[0]*o.halfDepth],d=[r[0]+s.u[1]*s.halfDepth,r[1]-s.u[0]*s.halfDepth],u=o.u[0]*s.u[1]-o.u[1]*s.u[0],p=e=>{let t=Math.atan2(e[1]-r[1],e[0]-r[0])-o.angle;for(;t<0;)t+=2*Math.PI;return t<=a+1e-9};let _=null;if(Math.abs(u)>1e-9){const e=((d[0]-h[0])*s.u[1]-(d[1]-h[1])*s.u[0])/u,t=((d[0]-h[0])*o.u[1]-(d[1]-h[1])*o.u[0])/u,i=[h[0]+o.u[0]*e,h[1]+o.u[1]*e];(l?e<=1e-9&&t<=1e-9:e>1e-9&&e<=o.thickLength&&t<=s.thickLength)&&Math.hypot(i[0]-r[0],i[1]-r[1])<=c&&p(i)&&(_=i)}const m=e=>{Math.abs(as(e))>i&&t.fans.push(e)};if(_){const e=1.5*Math.max(o.halfDepth,s.halfDepth);m(wo([r[0],r[1]],h,_,d,e)??[[r[0],r[1]],h,_,d]);continue}if(l){m([[r[0],r[1]],h,d]);continue}const g=(e,t)=>Math.min(t,Math.sqrt(Math.max(c**2-e**2,0)),2*Math.max(o.halfDepth,s.halfDepth)),f=[h[0]+o.u[0]*g(o.halfDepth,o.thickLength),h[1]+o.u[1]*g(o.halfDepth,o.thickLength)],v=[d[0]+s.u[0]*g(s.halfDepth,s.thickLength),d[1]+s.u[1]*g(s.halfDepth,s.thickLength)];m([[r[0],r[1]],h,f,v,d])}}return t}function xs(e,t){return!e||!Array.isArray(t)||t.length<2||!t.slice(0,2).every(Number.isFinite)?null:bs(e.index,t,e.epsilon).filter(i=>Math.hypot(i.point[0]-t[0],i.point[1]-t[1])<=e.epsilon).sort((e,i)=>Math.hypot(e.point[0]-t[0],e.point[1]-t[1])-Math.hypot(i.point[0]-t[0],i.point[1]-t[1])||e.point[0]-i.point[0]||e.point[1]-i.point[1])[0]||null}function Ss(e,t,i,n,r,o,s){return ws(Ms(e,t,i,n,r,o,s),4*ss(n,s),s)}function $s(e,t,i,n,r,o,s,a=1){const l=gs(e,t,n,r,a,i);if(!l)return null;const c=function(e,t,i){const n=(e||[]).find(e=>e?.id===t),r=ei(n);if(!r)return[];const o=[];for(const n of e||[]){if(!n||n.id===t)continue;const e=ei(n);if(e)for(const t of Cn(r,e,i))o.push(t)}return o}(e,t,ss(r,a)),h=function(e,t,i,n,r){const o=ss(n,r),s=[];for(let a=0;aDs(h,d,e[0],e[1],e[2],e[3])<=o);s.push(u?"shared":"outer")}return s}(l.poly,c,n,r,a),d=fs(i,l,r,a),u=d.map((e,t)=>h[t]&&e>0?Co(e,o,s)/2:0);return{...l,kinds:h,cms:d,offsets:u}}function Ms(e,t,i,n,r,o,s=1){const a=[];for(const l of e||[]){if(!l?.id)continue;const c=$s(e,l.id,t,i,n,r,o,s);if(c)for(let e=0;e0&&(a=Ko(a,e.a,e.b,e.cm,n,s));return a}function Cs(e,t,i,n,r,o,s=1){if(!t?.length)return[];const a=Ms(e,t,i,n,r,o,s),l=new Map;for(const e of a){if(e.open||!e.kind||!e.roomId)continue;const t=l.get(e.key)||new Set;t.add(e.roomId),l.set(e.key,t)}const c=e=>{const t=[...l.get(e)||[]].sort();return 1!==t.length&&2!==t.length?`ambiguous:${e}`:`${1===t.length?"outer":"shared"}:${t.join("|")}`},h=[],d=new Set;for(const e of a)!e.open&&e.cm>0&&!d.has(e.key)&&(d.add(e.key),h.push({...e,ownerSignature:c(e.key)}));const u=[];for(const a of e||[]){if(!a?.id)continue;const l=$s(e,a.id,t,i,n,r,o,s);if(l)for(let e=0;e0)||null===l.kinds[i]){e++;continue}const o=c(zo(l.poly[i],l.poly[(i+1)%l.poly.length],n,s));let a=e;for(;a+10&&u.push({a:[d[0],d[1]],b:[p[0],p[1]],key:zo(d,p,n,s),cm:r,len:_,ownerSignature:o}),e=a+1}}}u.sort((e,t)=>t.len-e.len||e.key.localeCompare(t.key));const p=[],_=new Set,m=new Set,g=4*ss(n,s);for(const e of u){const t=h.filter(t=>!m.has(t.key)&&t.cm===e.cm&&t.ownerSignature===e.ownerSignature&&Ho(No(t.a,t.b),No(e.a,e.b))&&Ds(t.a[0],t.a[1],e.a[0],e.a[1],e.b[0],e.b[1])<=g&&Ds(t.b[0],t.b[1],e.a[0],e.a[1],e.b[0],e.b[1])<=g);if(t.length){for(const e of t)m.add(e.key);_.has(e.key)||(_.add(e.key),p.push(Oo(e.a,e.b,e.cm,n,s)))}}for(const e of h)m.has(e.key)||_.has(e.key)||(_.add(e.key),p.push(Oo(e.a,e.b,e.cm,n,s)));return p}function Ts(e,t,i,n,r,o,s,a=1){const l=ss(r,a),c=(n[0]+n[2])/2,h=(n[1]+n[3])/2,d=No([n[0],n[1]],[n[2],n[3]]);let u=null;for(const n of Ms(e,t,i,r,o,s,a)){if(!Ho(No(n.a,n.b),d))continue;const e=Ds(c,h,n.a[0],n.a[1],n.b[0],n.b[1]);e>4*l||(!u||e[e[0],e[1]]),o=Math.abs(as(r));r.length>=3&&o>i&&(t=r,i=o)}return t}function Ps(e,t,i,n,r,o,s,a=1,l,c){const h=(e||[]).find(e=>e?.id===t),d=ei(h);if(!d||d.length<3)return null;if(!i?.length)return d.map(e=>[e[0],e[1]]);const u=$s(e,t,i,n,r,o,s,a);if(!u||!u.offsets.some(e=>e>0))return d.map(e=>[e[0],e[1]]);const p=c||Ss(e,i,n,r,o,s,a),_=ps(u.poly,u.offsets,p);if(!_)return d.map(e=>[e[0],e[1]]);if(!p.nodes.length)return _;const m=void 0===l?Ks(e,i,n,[],r,o,s,a):null,g=l??("ok"===m?.status||"degraded-extra"===m?.status?m.roomGeom:void 0);if(g)try{const e=As(jt(Fs(u.poly),g));if(e)return e}catch{}return function(e,t){try{return As(qt(Fs(e),Fs(t)))}catch{return null}}(_,u.poly)||d.map(e=>[e[0],e[1]])}function Fs(e){const t=e.map(e=>[e[0],e[1]]);return t.push([e[0][0],e[0][1]]),[t]}function zs(e){return!(!Array.isArray(e)||!e.length)&&e.every(e=>Array.isArray(e)&&e.length&&e.every(e=>Array.isArray(e)&&e.length>=4&&e.every(e=>Array.isArray(e)&&e.length>=2&&Number.isFinite(e[0])&&Number.isFinite(e[1])))&&Math.abs($i(e[0]))>1e-9)}function Is(e,t,i,n){const r=n?new Set(n):null;let o=null;for(let n=0;nt.epsilon))continue;const l=Ls([[e.point[0]+a[0]*n.halfDepth,e.point[1]+a[1]*n.halfDepth],[e.point[0]+s.u[0]*r+a[0]*n.halfDepth,e.point[1]+s.u[1]*r+a[1]*n.halfDepth],[e.point[0]+s.u[0]*r-a[0]*n.halfDepth,e.point[1]+s.u[1]*r-a[1]*n.halfDepth],[e.point[0]-a[0]*n.halfDepth,e.point[1]-a[1]*n.halfDepth]],t.coordinateScale);if(!l)continue;const c=Fs(l);o=o?Bt(o,c):c}}return o}function Os(e,t,i){let n=null;for(const r of e.rays)for(const e of r.continuations){const r=[-e.u[1],e.u[0]],o=[e.start[0]+e.u[0]*e.length,e.start[1]+e.u[1]*e.length],s=Ls([[e.start[0]+r[0]*e.halfDepth,e.start[1]+r[1]*e.halfDepth],[o[0]+r[0]*e.halfDepth,o[1]+r[1]*e.halfDepth],[o[0]-r[0]*e.halfDepth,o[1]-r[1]*e.halfDepth],[e.start[0]-r[0]*e.halfDepth,e.start[1]-r[1]*e.halfDepth]],t.coordinateScale);if(!s)continue;const a=qt(Fs(s),i);Array.isArray(a)&&0!==a.length&&(n=n?Bt(n,a):a)}return n}function Es(e,t,i=2*(4*e.halfDepth+2*t.epsilon)){const n=function(e,t=ko){const i=new Set,n=Number.isFinite(t)&&t>=0?t:ko;for(let t=0;te-t)}(e);return n.length?Is(e,t,i,n):null}function Ns(e,t,i,n,r){const o=function(e){let t=null;for(const i of e){const e=Fs(i);try{t=t?Bt(t,e):e}catch{}}return t}(function(e,t,i=!1){if(!e)return[];const n=[];for(const r of e.nodes)for(let o=0;o1e-9)||h>=Math.PI-1e-9)continue;const d=[-s.u[1],s.u[0]],u=[-a.u[1],a.u[0]],p=[r.point[0]+d[0]*s.halfDepth,r.point[1]+d[1]*s.halfDepth],_=[r.point[0]-u[0]*a.halfDepth,r.point[1]-u[1]*a.halfDepth],m=hs(p,s.u,_,a.u);if(!m)continue;const g=Math.hypot(m[0]-r.point[0],m[1]-r.point[1]);if(!Number.isFinite(g)||g<=r.limit)continue;const f=t?Math.sqrt(Math.max(0,r.limit*r.limit-s.halfDepth*s.halfDepth)):0,v=t?Math.sqrt(Math.max(0,r.limit*r.limit-a.halfDepth*a.halfDepth)):0,y=Ls([[p[0]+s.u[0]*f,p[1]+s.u[1]*f],[_[0]+a.u[0]*v,_[1]+a.u[1]*v],m],e.coordinateScale);if(y&&n.push(y),i){const t=m[0]-r.point[0],i=m[1]-r.point[1],o=Math.hypot(t,i),s=g-r.limit;if(o>e.epsilon&&s>e.epsilon){const a=Math.min(Math.max(8*e.epsilon,.05*r.halfDepth),.25*s),l=t/o,c=i/o,h=-c,d=l,u=Ls([[m[0]-l*a+h*a,m[1]-c*a+d*a],[m[0]-l*a-h*a,m[1]-c*a-d*a],[m[0]+l*a,m[1]+c*a]],e.coordinateScale);u&&n.push(u)}}}return n}({...t,nodes:[e]},i,n));return o&&r?jt(o,r):o}function Hs(e,t,i,n){if(!e||!t.nodes.length)return e;let r=null;try{r=function(e){let t=null;for(const i of e.nodes){const n=Es(i,e);n&&(t=t?Bt(t,n):n)}return t}(t)}catch{return e}let o=e;for(const e of t.nodes){const s=4*e.halfDepth+2*t.epsilon,a=2*s,l=[[e.point[0]-s,e.point[1]-s],[e.point[0]+s,e.point[1]-s],[e.point[0]+s,e.point[1]+s],[e.point[0]-s,e.point[1]+s]];try{let s=o;const c=Ns(e,t,!1,!0,r);c&&(s=jt(s,c));let h=Is(e,t,a);const d=Ns(e,t,!0,!0,r);d&&(h=jt(h,d)),r&&(h=Bt(h,r));const u=.02*Math.min(...e.rays.map(e=>e.halfDepth));if(h=Bt(h,Fs([[e.point[0]-u,e.point[1]-u],[e.point[0]+u,e.point[1]-u],[e.point[0]+u,e.point[1]+u],[e.point[0]-u,e.point[1]+u]])),!h)continue;let p=qt(h,Fs(l));n?p=qt(p,n):i&&(p=qt(p,i));const _=Fs(l),m=jt(s,_),g=i?jt(qt(s,_),i):null,f=Os(e,t,_);o=Bt(m,...g?[g]:[],...f?[f]:[],p)}catch{}}if(r)try{let e=r;n?e=qt(e,n):i&&(e=qt(e,i)),o=Bt(o,e)}catch{}return o}function Ls(e,t=1){if(!Array.isArray(e)||e.length<3)return null;const i=Number.isFinite(t)&&t>0?t:1,n=1e-12*Math.max(1,i),r=[];for(const t of e){if(!Array.isArray(t)||t.length<2)return null;const e=Number(t[0]),i=Number(t[1]);if(!Number.isFinite(e)||!Number.isFinite(i))return null;const o=Math.round(e/n)*n,s=Math.round(i/n)*n;if(!Number.isFinite(o)||!Number.isFinite(s))return null;r.push([Object.is(o,-0)?0:o,Object.is(s,-0)?0:s])}return Math.abs(as(r))>n*n?r:null}function Bs(e,t,i,n){if(Ds(e[0],e[1],t[0],t[1],i[0],i[1])>n)return!1;const r=i[0]-t[0],o=i[1]-t[1],s=(e[0]-t[0])*r+(e[1]-t[1])*o,a=r*r+o*o,l=n*Math.sqrt(a);return s>=-l&&s<=a+l}function qs(e,t,i){const n=[],r=[];for(let o=0;oi*i))continue;const d=i/Math.sqrt(h),u=[0,1];for(const e of t)for(const t of[e.a,e.b]){if(!Bs(t,s,a,i))continue;const e=((t[0]-s[0])*l+(t[1]-s[1])*c)/h;e>d&&e<1-d&&u.push(e)}u.sort((e,t)=>e-t);const p=u.filter((e,t)=>0===t||Math.abs(e-u[t-1])>d);for(let e=0;e=3&&r.length===n.length?{poly:n,offsets:r}:null}function js(e,t,i,n,r,o,s,a){const l=(e||[]).map(ei).filter(e=>!!e&&e.length>=3);if(!l.length)return null;let c=Bt(Fs(l[0]));for(let e=1;e"outer"===e.kind&&e.half>0),u=4*ss(n,s),p=a||ws(h,u,s);let _=null;for(const e of function(e){const t=[];for(const i of Array.isArray(e)?e:[])if(Array.isArray(i))for(const e of i){if(!Array.isArray(e)||e.length<4)continue;const i=e.slice(0,-1).map(e=>[e[0],e[1]]);i.length>=3&&t.push(i)}return t}(c)){const t=qs(e,d,u);if(!t||!t.offsets.some(e=>e>0))continue;const i=Qs(t.poly,t.offsets,p),n=ps(t.poly,t.offsets,p);if(!i||!n)continue;const r=jt(Fs(i),Fs(n));_=_?Bt(_,r):r}return{centre:c,shell:_||[]}}function Ws(e,t,i,n,r,o,s=1){try{const a=js(e,t,i,n,r,o,s,Ss(e,t,i,n,r,o,s));if(!a)return[];return a.shell?.length?Bt(a.centre,a.shell):a.centre}catch{return null}}function Us(e){if(!e)return"";let t="";for(const i of e)if(Array.isArray(i))for(const e of i){if(!Array.isArray(e)||e.length<4)continue;const i=e.slice(0,e.length-1);i.length<3||(t+=(t?" ":"")+_s(i.map(e=>[e[0],e[1]])))}return t}const Vs=15;function Gs(e,t,i){const n=e?.length||0;if(n<3||t?.length!==n)return!1;const r=e[(i-1+n)%n],o=e[i],s=e[(i+1)%n],a=[r[0]-o[0],r[1]-o[1]],l=[s[0]-o[0],s[1]-o[1]],c=Math.hypot(a[0],a[1]),h=Math.hypot(l[0],l[1]);if(!(c>1e-9&&h>1e-9))return!1;const d=Math.max(-1,Math.min(1,(a[0]*l[0]+a[1]*l[1])/(c*h))),u=Math.acos(d);if(!(u>1e-9))return!1;if(u>=Vs*Math.PI/180)return!1;const p=Math.max(0,t[(i-1+n)%n]),_=Math.max(0,t[i]);if(!(p>0||_>0))return!1;const m=Math.sin(u);if(!(m>1e-12))return!1;const g=(_+p*d)/m,f=(p+_*d)/m;return Number.isFinite(g)&&Number.isFinite(f)&&g>0&&f>0&&ge>0))continue;for(const e of l.offsets)e>0&&(u=Math.max(u,2*e));const c=Qs(l.poly,l.offsets,d),p=ps(l.poly,l.offsets,d);c&&h.push({outset:c,inset:p})}for(const e of l){const t=e.map(e=>e[0]),i=e.map(e=>e[1]);if(t.length){const n=Math.min(Math.max(...t)-Math.min(...t),Math.max(...i)-Math.min(...i)),r=Math.min(...e.map((t,i)=>{const n=e[(i+1)%e.length];return Math.hypot(n[0]-t[0],n[1]-t[1])}));u=Math.max(u,e.length>16?n:r)}}const p=function(e,t,i,n,r,o,s,a){if(!t?.length||!i?.length)return[];const l=4*ss(n,s),c=new Map;for(const a of Ms(e,t,i,n,r,o,s))!a.open&&a.half>0&&!c.has(a.key)&&c.set(a.key,a);const h=[...c.values()];if(h.length<2)return[];const d=a||ws(h,l),u=[];for(const e of i)for(const t of[[e[0],e[1]],[e[2],e[3]]])u.some(e=>Math.hypot(e[0]-t[0],e[1]-t[1])<=l)||u.push(t);const p=[],_=(e,t)=>{let i=0,n=0;if(Math.hypot(e.a[0]-t[0],e.a[1]-t[1])<=l)i=e.b[0]-e.a[0],n=e.b[1]-e.a[1];else{if(!(Math.hypot(e.b[0]-t[0],e.b[1]-t[1])<=l))return null;i=e.a[0]-e.b[0],n=e.a[1]-e.b[1]}const r=Math.hypot(i,n);return r>l?[i/r,n/r]:null};for(const e of u){const t=h.map(t=>({iv:t,u:_(t,e)})).filter(e=>!!e.u);for(let i=0;i0?[e.slice(),u,m,_]:[e.slice(),_,m,u];else{if(!f)continue;{const t=[-r.u[1],r.u[0]],i=[-o.u[1],o.u[0]],n=s<0?1:-1,a=[e[0]+t[0]*r.iv.half*n,e[1]+t[1]*r.iv.half*n],l=[e[0]-i[0]*o.iv.half*n,e[1]-i[1]*o.iv.half*n];y=s>0?[e.slice(),a,l]:[e.slice(),l,a]}}Math.abs(as(y))>l*l&&p.push(y)}}return p}(e,t,i,r,o,s,a,d),_=n.length?ea(e,t,i,r,o,s,a):null;let m="exterior";try{const v=js(e,t,i,r,o,s,a,d);m="paper";const y=v?v.shell?.length?Bt(v.centre,v.shell):v.centre:[],b=e=>{const t=Fs(e.outset);if(!e.inset)return t;const i=Fs(e.inset);return jt(t,i)};m="room-rings";let w=null;for(const e of h)try{const t=b(e);w=w?Bt(w,t):t}catch{}if(m="edge-bodies",v)for(const n of Zs(e,t,i,r,o,s,a))try{const e=qt(Fs(n.quad),v.centre);w=w?Bt(w,e):e}catch{}m="junctions",w=function(e,t,i=1,n=Bt){let r=e;for(const e of t||[]){const t=Ls(e,i);if(t)try{const e=Fs(t);r=r?n(r,e):e}catch{}}return r}(w,p,a),m="facade-clip",w&&v&&(w=qt(w,v.centre)),m="exterior-shell";const k=[];let x=0;if(v?.shell?.length)if(w)try{const e=Bt(w,v.shell);if(!zs(e))throw new Error("invalid shell union");w=e}catch{if(!zs(w)||!zs(v.shell))throw new Error("invalid shell");k.push({id:"exterior-shell",geom:v.shell}),x++}else w=v.shell;if(m="multi-wall-trim",w&&d.nodes.length){const e=e=>e.rays.some(e=>e.supports.some(e=>e.length<2*e.halfDepth)),t=d.nodes.filter(e);if(t.length){w=Hs(w,{...d,nodes:t},v?.centre,y)}}if(m="junction-corners",d.nodes.length){const n=ks(d),l=function(e,t,i,n,r,o,s,a){try{const l=js(e,t,i,n,r,o,s,{epsilon:a.epsilon,coordinateScale:a.coordinateScale,nodes:[],index:new Map});return l?l.shell?.length?Bt(l.centre,l.shell):l.centre:null}catch{return null}}(e,t,i,r,o,s,a,d);for(const e of n.fans)try{let t=[Fs(e)];if(l&&(t=qt(t,l)),!t?.length)continue;w=w?Bt(w,t):t}catch{}g=w,f=Math.max(d.epsilon,1e-9)**2,w=Array.isArray(g)?g.map(e=>{if(!Array.isArray(e)||!e.length)return e;const[t,...i]=e;return Math.abs(as(t||[]))<=f?null:[t,...i.filter(e=>Math.abs(as(e||[]))>f)]}).filter(e=>!!e):g}const S=w||[],$=[...zs(S)?[{id:"room-primary",geom:S}]:[],...k.map((e,t)=>({id:`room-isolated-${t}`,geom:e.geom}))];m="openings";for(const e of n){if(!(e.length>0))continue;const t=na(_,e,!0);if(!t.negative&&!t.positive)continue;const i=e.angle*Math.PI/180,n=Math.cos(i),o=Math.sin(i),s=-o,l=n,c=e.length/2,h=1.25*Math.max(u,r*a),d=[[e.x-n*c-s*h,e.y-o*c-l*h],[e.x+n*c-s*h,e.y+o*c-l*h],[e.x+n*c+s*h,e.y+o*c+l*h],[e.x-n*c+s*h,e.y-o*c+l*h]];w&&(w=jt(w,Fs(d)));for(const e of k)e.geom=jt(e.geom,Fs(d))}m="extras";const M=[];let R=0;const C=c.mergeExtra||((e,t)=>e?Bt(e,t):t);for(let e=0;ee.length>=2&&Number.isFinite(e[0])&&Number.isFinite(e[1]))||Math.abs($i(t))<=1e-9){R++;continue}const i=[Fs(t)];try{const t=C(w,i,e);if(!zs(t))throw new Error("invalid extra union");w=t}catch{R++,zs(i)&&M.push({id:`extra-${e}`,geom:i})}}M.push(...k),M.sort((e,t)=>Us(e.geom).localeCompare(Us(t.geom)));const T=w||[];return{status:R||x?"degraded-extra":"ok",geom:T,components:[...zs(T)?[{id:"primary",geom:T}]:[],...M.map((e,t)=>({...e,id:`isolated-${t}`}))],roomGeom:S,roomComponents:$,paperGeom:y,depthUnits:u,openingPadUnits:1.25*Math.max(u,r*a),openingIndex:_,multiWallNodes:d,degradedExtraCount:R+x}}catch{return c.onCoreFailure?.(m),{status:"failed-core",geom:[],components:[],roomGeom:[],paperGeom:[],roomComponents:[],depthUnits:u,openingIndex:null,multiWallNodes:d,degradedExtraCount:0}}var g,f}function Ys(e,t,i,n=[],r,o,s,a=1,l=[],c={}){if(!t?.length&&!l.length)return null;return Xs(Ks(e,t,i,n,r,o,s,a,l,c))}function Xs(e){if("failed-core"===e.status||"not-applicable"===e.status)return null;const t=e.components.map(e=>({id:e.id,d:Us(e.geom),fillRule:"evenodd"})).filter(e=>!!e.d),i=t[0]?.d||"",n=Us(e.paperGeom);if(t.length){const r={status:e.status,d:i,paths:t,components:e.components,roomGeom:e.roomGeom,multiWallNodes:e.multiWallNodes,paperD:n,depthUnits:e.depthUnits,fillRule:"evenodd"};return Object.defineProperties(r,{roomComponents:{value:e.roomComponents||[],enumerable:!1},openingIndex:{value:e.openingIndex,enumerable:!1},openingPadUnits:{value:e.openingPadUnits,enumerable:!1}}),r}return null}function Zs(e,t,i,n,r,o,s=1){if(!t?.length)return[];const a=new Set,l=[];for(const c of e||[]){if(!c?.id)continue;const h=$s(e,c.id,t,i,n,r,o,s);if(!h)continue;const d=h.poly;for(let e=0;e0))continue;const p=zo(t,i,n,s);if(a.has(p))continue;a.add(p);const _=Co(u,r,o),[m,g]=ls(d,e),f=-m,v=-g,y=_/2,b=[[t[0]+f*y,t[1]+v*y],[i[0]+f*y,i[1]+v*y],[i[0]+m*y,i[1]+g*y],[t[0]+m*y,t[1]+g*y]];l.push({key:p,kind:c,cm:u,quad:b,a:[t[0],t[1]],b:[i[0],i[1]],depthUnits:_})}}return l}function Js(e,t=[]){let i=_s(e.quad);const[n,r]=Po(e.a,e.b),o=n,s=r,a=-s,l=o;for(const n of t){if(!jo(e.a,e.b,n.angle))continue;if(Ds(n.x,n.y,e.a[0],e.a[1],e.b[0],e.b[1])>Math.max(.55*e.depthUnits,.001))continue;const t=n.length/2,r=e.depthUnits,c=n.x,h=n.y;i+=` ${_s(ms([[c-o*t-a*r,h-s*t-l*r],[c+o*t-a*r,h+s*t-l*r],[c+o*t+a*r,h+s*t+l*r],[c-o*t+a*r,h-s*t+l*r]]))}`}return i}function Qs(e,t,i){const n=e?.length||0;if(n<3||t.length!==n)return null;if(t.every(e=>!(e>0)))return e.map(e=>[e[0],e[1]]);ms(e),t.slice().reverse();const r=[];for(let o=0;o0||l>0)){r.push([e[o][0],e[o][1]]);continue}if(a>0!=l>0){const t=e[o],i=a>0?[t[0]-c*a,t[1]-h*a]:[t[0],t[1]],n=l>0?[t[0]-d*l,t[1]-u*l]:[t[0],t[1]];r.push(i),Math.hypot(n[0]-i[0],n[1]-i[1])>1e-9&&r.push(n);continue}if(cs(w,k)){const t=e[o],i=[t[0]-c*a,t[1]-h*a],n=[t[0]-d*l,t[1]-u*l];r.push(i),Math.hypot(n[0]-i[0],n[1]-i[1])>1e-9&&r.push(n);continue}const $=hs(x,w,S,k),M=Math.max(a,l,1e-9),R=xs(i,e[o])?.limit??4*M;if($){const i=Math.hypot($[0]-e[o][0],$[1]-e[o][1]);if(Number.isFinite(i)&&i<=R){r.push($);continue}if(Gs(e,t,o)){r.push([e[o][0],e[o][1]]);continue}}a>0&&r.push([e[o][0]-c*a,e[o][1]-h*a]),l>0&&r.push([e[o][0]-d*l,e[o][1]-u*l])}return r.length>=3?r:null}function ea(e,t,i,n,r,o,s=1){const a=[];for(const l of e||[]){if(!l?.id)continue;const c=$s(e,l.id,t,i,n,r,o,s);if(!c)continue;const h=Math.abs($i(c.poly));for(let e=0;e[Math.max(t,e.x0),Math.min(i,e.x1)]).filter(e=>e[1]-e[0]>n).sort((e,t)=>e[0]-t[0]||e[1]-t[1]);if(!r.length)return{coverage:0,full:!1};let o=r[0][0],s=r[0][1],a=0,l=o<=t+n;for(let e=1;e=i-n,{coverage:a,full:l}}function ia(e,t){return Number(t.full)-Number(e.full)||e.faceDistance-t.faceDistance||e.area-t.area||e.roomId.localeCompare(t.roomId)}function na(e,t,i=!1){const n=Number(t?.x),r=Number(t?.y),o=Number(t?.angle),s=Number(t?.length);if(!([n,r,o,s].every(Number.isFinite)&&s>0))return{negative:null,positive:null};const a=o*Math.PI/180,l=Math.cos(a),c=Math.sin(a),h=-c,d=l,u=s/2,p=Math.max(1e-9,e.adjacencyEps),_=new Map;let m=0;for(const t of e.edges){if(i&&!(t.half>0))continue;if(!jo(t.a,t.b,o))continue;const[e,s]=Po(t.a,t.b);if(Math.abs((n-t.a[0])*s-(r-t.a[1])*e)>p)continue;const a=(t.a[0]-n)*l+(t.a[1]-r)*c,g=(t.b[0]-n)*l+(t.b[1]-r)*c,f=Math.max(-u,Math.min(a,g)),v=Math.min(u,Math.max(a,g));if(v-f<=p)continue;const y=t.inward[0]*h+t.inward[1]*d>=0?1:-1,b=((t.a[0]+t.b[0])/2-n)*h+((t.a[1]+t.b[1])/2-r)*d,w=Math.abs(b+y*t.half),k=`${y}|${t.roomId}`,x={x0:f,x1:v,half:t.half,cm:t.cm,key:t.key,axis:[e,s]},S=_.get(k);S?(S.pieces.push(x),S.faceDistance=Math.min(S.faceDistance,w)):_.set(k,{roomId:t.roomId,side:y,order:m++,pieces:[x],faceDistance:w,area:t.area,coverage:0,full:!1})}for(const e of _.values()){const t=ta(e.pieces,-u,u,p);e.coverage=t.coverage,e.full=t.full}const g=e=>{const t=[..._.values()].filter(t=>t.side===e&&t.coverage>p);return t.sort(ia),t[0]||null};return{negative:g(-1),positive:g(1)}}function ra(e,t,i,n,r,o,s=1,a=[]){return oa(ea(e,i,a,n,r,o,s),t)}function oa(e,t){const i=na(e,t),n=[i.negative,i.positive].filter(e=>!!e);if(!n.length)return{ox:0,oy:0,cm:0,side:-1};const r=i.negative&&i.positive?-1:n[0].side,o=t.flip_v?-r:r,s=(-1===o?i.negative:i.positive)||n[0],a=[...s.pieces].sort((e,t)=>(e.x0<=0&&e.x1>=0?0:Math.min(Math.abs(e.x0),Math.abs(e.x1)))-(t.x0<=0&&t.x1>=0?0:Math.min(Math.abs(t.x0),Math.abs(t.x1)))||t.x1-t.x0-(e.x1-e.x0)||e.key.localeCompare(t.key))[0];if(!(a.half>0&&a.cm>0))return{ox:0,oy:0,cm:0,side:o};const l=t.angle*Math.PI/180,c=-Math.sin(l),h=Math.cos(l);return{ox:c*o*a.half,oy:h*o*a.half,cm:a.cm,side:o}}function sa(e,t){const i=1e-9,n=t.filter(e=>Number.isFinite(e.x0)&&Number.isFinite(e.x1)&&Number.isFinite(e.half)&&e.x1>e.x0&&e.half>0);if(!n.length)return"";const r=n.flatMap(e=>[e.x0,e.x1]).sort((e,t)=>e-t),o=[];for(const e of r){const t=o[o.length-1];(void 0===t||e>t+i)&&o.push(e)}const s=[];for(let e=0;e+1t+i))continue;const a=(t+r)/2,l=n.reduce((e,t)=>a>=t.x0-i&&a<=t.x1+i?Math.max(e,t.half):e,0);if(!(l>0))continue;const c=s[s.length-1];c&&t<=c.x1+i&&Math.abs(l-c.half)<=i?c.x1=r:s.push({x0:t,x1:r,half:l})}const a=[];for(const e of s){const t=a[a.length-1],n=t?.[t.length-1];n&&e.x0<=n.x1+i?(e.x0=n.x1,t.push(e)):a.push([e])}return a.map(t=>{const i=t[0],n=t[t.length-1],r=Math.min(.25*Math.min(...t.map(e=>e.half)),.75),o=-e*r,s=[];if(1===e){s.push(`M ${i.x0} ${o} L ${n.x1} ${o}`);for(let e=t.length-1;e>=0;e--){const i=t[e];s.push(`L ${i.x1} ${i.half} L ${i.x0} ${i.half}`)}}else{s.push(`M ${n.x1} ${o} L ${i.x0} ${o}`);for(const e of t)s.push(`L ${e.x0} ${-e.half} L ${e.x1} ${-e.half}`)}return s.push("Z"),s.join(" ")}).join(" ")}function aa(e,t,i,n){if(!n)return i;const r=e.angle*Math.PI/180,o=Math.cos(r),s=Math.sin(r),a=[],l=1e-9;for(const r of i){const[i,c]=r.axis,h=o*i+s*c;if(Math.abs(h)<=l)continue;const d=e.x*i+e.y*c,u=d+h*r.x0,p=d+h*r.x1,_=Math.min(u,p),m=Math.max(u,p),g=`${r.key}|${t}`,f=n.get(g)||[];let v=[[_,m]];for(const[e,t]of f){const i=[];for(const[n,r]of v)t<=n+l||e>=r-l?i.push([n,r]):(e>n+l&&i.push([n,Math.min(r,e)]),te[0]-t[0]||e[1]-t[1]),b=[];for(const e of y){const t=b[b.length-1];t&&e[0]<=t[1]+l?t[1]=Math.max(t[1],e[1]):b.push([e[0],e[1]])}n.set(g,b)}return a}function la(e,t){const i=new Map;return t.map(t=>function(e,t,i){const n=na(e,t,!0),r=n.negative,o=n.positive;if(!r&&!o)return null;let s;if(r&&o)s=[{candidate:r,side:-1},{candidate:o,side:1}];else{const e=r||o;s=[{candidate:e,side:-1},{candidate:e,side:1}]}const a=s.map(({candidate:e,side:n})=>({candidate:e,side:n,pieces:aa(t,n,e.pieces,i)})),l=a.map(({candidate:e,side:t,pieces:i})=>({side:t,roomId:e.roomId,d:sa(t,i)})),c=a.flatMap(({pieces:e})=>e);if(!c.length)return null;const h=Math.max(...c.map(e=>e.half));return{faces:l,minY:-h,maxY:h,wallKey:[...new Set(c.map(e=>e.key))].sort().join("|")}}(e,t,i))}const ca=150,ha=1e-6;function da(e){return Number.isFinite(e)?Math.max(1,Math.min(ca,e)):1}function ua(e){return((Number.isFinite(Number(e))?Number(e):0)%90+90)%90}const pa=e=>{const t=e.map(e=>[e[0],e[1]]);return!t.length||t[0][0]===t[t.length-1][0]&&t[0][1]===t[t.length-1][1]||t.push([...t[0]]),[t]},_a=(e,t)=>e[0]===t[0]&&e[1]===t[1];function ma(e,t=1e-6){const i=Number.isFinite(t)&&t>0?t:ha,n=[];for(const t of e||[]){if(!Array.isArray(t)||t.length<2)return null;const e=Number(t[0]),r=Number(t[1]);if(!Number.isFinite(e)||!Number.isFinite(r))return null;const o=Math.round(e/i)*i,s=Math.round(r/i)*i;if(!Number.isFinite(o)||!Number.isFinite(s))return null;const a=[Object.is(o,-0)?0:o,Object.is(s,-0)?0:s];n.length&&_a(n[n.length-1],a)||n.push(a)}return n.length>1&&_a(n[0],n[n.length-1])&&n.pop(),n.length<3||new Set(n.map(e=>`${e[0]},${e[1]}`)).size<3?null:$i(n)>i*i?n:null}function ga(e){const t=[];for(const i of e||[])for(const e of i||[]){const i=(e||[]).filter(e=>Array.isArray(e)&&e.length>=2);i.length<4||t.push(`M ${i.slice(0,-1).map(e=>`${e[0]} ${e[1]}`).join(" L ")} Z`)}return t.join(" ")}function fa(e,t,i,n,r){return Zo({a:e,b:t,halfDepth:Co(i,n,r)/2})}function va(e,t,i){const n=Number(t)>0?Number(t):5,r=da(e.cm)/n*i,o=e.center[0],s=e.center[1];if("circle"===e.shape){const e=r/2;return Array.from({length:96},(t,i)=>{const n=i/96*Math.PI*2;return[o+Math.cos(n)*e,s+Math.sin(n)*e]})}const a=r/2,l=ua(e.angle)*Math.PI/180,c=Math.cos(l),h=Math.sin(l);return[[-a,-a],[a,-a],[a,a],[-a,a]].map(([e,t])=>[o+e*c-t*h,s+e*h+t*c])}function ya(e,t){const i=Number.isFinite(t)?Math.max(0,Math.min(1,t)):0,n=(e.a[0]+e.b[0])/2,r=(e.a[1]+e.b[1])/2,o=(e.b[0]-e.a[0])*i/2,s=(e.b[1]-e.a[1])*i/2;return{...e,a:[n-o,r-s],b:[n+o,r+s]}}function ba(e,t,i=1e-9){if(!t.length)return[e];let n=[pa(e)];try{for(const e of t){const t=e.b[0]-e.a[0],r=e.b[1]-e.a[1],o=Math.hypot(t,r);if(!(o>i))continue;const s=t/o,a=r/o,l=-a,c=s,h=1.25*Math.max(Number(e.depth)||0,4*i),d=Math.max(2*i,1e-9*o),u=[[e.a[0]-s*d-l*h,e.a[1]-a*d-c*h],[e.b[0]+s*d-l*h,e.b[1]+a*d-c*h],[e.b[0]+s*d+l*h,e.b[1]+a*d+c*h],[e.a[0]-s*d+l*h,e.a[1]-a*d+c*h]];n=jt(n,pa(u))}return Da(n)}catch{return[e]}}function wa(e,t){try{const i=jt([[...e.map(e=>[e[0],e[1]]),[e[0][0],e[0][1]]]],[[...t.map(e=>[e[0],e[1]]),[t[0][0],t[0][1]]]]);let n=null,r=0;for(const e of i||[]){const t=e?.[0]||[],i=Math.abs($i(t));t.length>=4&&i>r&&(r=i,n=t.slice(0,-1).map(e=>[e[0],e[1]]))}return n}catch{return null}}function ka(e,t,i,n=Math.max(2e-4*i,1e-9),r=[]){const o=[],s=new Map;for(const e of r){const t=s.get(e.hostId)||[];t.push(e),s.set(e.hostId,t)}const a=[],l=[],c=[];for(const n of e.partitions||[]){const e={a:n.a,b:n.b,halfDepth:Co(n.cm,t,i)/2};if(!(e.halfDepth>0))continue;const r=Zo(e);r&&(o.push(e),a.push(r),c.push({id:n.id,body:r}))}const h=o;for(const{segmentIndex:e,wedge:t}of is(h,n)){const i={list:a,at:e},n=wa(i.list[i.at],t);n&&(i.list[i.at]=n,c[i.at].body=n)}for(const e of c)l.push(...ba(e.body,s.get(e.id)||[],n));const d=(e.wall_columns||[]).map(e=>va(e,t,i)),u=ns(o,n).flatMap(e=>ba(e,r,n));return{partitions:a,columns:d,patches:u,all:[...l,...u,...d]}}function xa(e){try{const t=e.map(e=>ma(e)).filter(e=>!!e).map(e=>pa(e));return t.length?Bt(t[0],...t.slice(1)):null}catch{return null}}const Sa=e=>`M ${e.map(e=>`${e[0]} ${e[1]}`).join(" L ")} Z`;function $a(e){const t=[];for(const i of e||[]){if(Ca([i])<=1e-6)continue;const e=[];for(const t of i||[]){const i=(t||[]).filter(e=>Array.isArray(e)&&e.length>=2);i.length<4||e.push(Sa(i.slice(0,-1)))}e.length&&t.push(e.join(" "))}return t}function Ma(e,t,i={}){const n=xa(e.filter(e=>e.length>=3)),r=t.some(e=>!ma(e))?null:xa(t);if(!n)return[];if(r)try{return $a(qt(n,r))}catch{}return function(e,t,i){let n=null;for(let r=0;r=4&&t.push(e.slice(0,-1).map(e=>[e[0],e[1]]));return t}function Da(e){const t=[];for(const i of e||[]){const e=i?.[0];e?.length>=4&&t.push(e.slice(0,-1).map(e=>[e[0],e[1]]))}return t}function Aa(e,t){let i=!1;for(let n=0,r=t.length-1;ne[1]!=l>e[1]&&e[0]<(a-o)*(e[1]-s)/(l-s||1e-12)+o&&(i=!i)}return i}function Pa(e,t){for(const i of t||[]){const t=i?.[0];if(!t?.length||!Aa(e,t))continue;let n=!1;for(let t=1;ti)return!1;if(Math.abs(da(e.cm)-da(t.cm))>1e-6)return!1;if(e.shape!==t.shape)return!0;if("circle"===e.shape||"circle"===t.shape)return!0;const n=Math.abs(ua(e.angle)-ua(t.angle));return Math.min(n,90-n)<=1e-6}const za=2.54;function Ia(e){const t="number"==typeof e?e:NaN;return!Number.isFinite(t)||t<=0||5===t?1:5/t}function Oa(e,t){return e*Ia(t)}function Ea(e){return e?za:1}function Na(e,t){if(!t)return String(e);const i=e/za;return String(Math.round(1e6*i)/1e6)}function Ha(e,t){return t?e*za:e}const La=1e3;function Ba(e,t){const i=Number(e),n=Number.isFinite(i)&&i>0?i:1,r=n>=1?t:t*n,o=n>=1?t/n:t;return{x:(t-r)/2,y:(t-o)/2,w:r,h:o}}const qa=.01,ja=100;function Wa(e,t=1e3){const i=Ba(e?.plan_aspect,t),n=Number(e?.plan_scale),r=Number.isFinite(n)&&n>0?Math.min(ja,Math.max(qa,n)):1,o=Number(e?.plan_scale_x),s=Number(e?.plan_scale_y),a=Number.isFinite(o)&&o>0?Math.min(ja,Math.max(qa,o)):r,l=Number.isFinite(s)&&s>0?Math.min(ja,Math.max(qa,s)):r,c=Number(e?.plan_x),h=Number(e?.plan_y),d=kr(e?.plan_angle);return{x:i.x+(Number.isFinite(c)?tl(c):0)*t,y:i.y+(Number.isFinite(h)?tl(h):0)*t,w:i.w*a,h:i.h*l,...d?{angle:d}:{}}}function Ua(e){if(null==e.x||null==e.y)return{x:e.x,y:e.y,w:e.w,h:e.h};const t=Number(e.w)||0,i=Number(e.h)||0;return{x:t<0?e.x+t:e.x,y:i<0?e.y+i:e.y,w:Math.abs(t),h:Math.abs(i)}}function Va(e){return e&&Array.isArray(e.spaces)?e.spaces.map(e=>{const t=La,i=function(e){return Array.isArray(e)&&4===e.length&&e.every(e=>Number.isFinite(e))&&e[2]>1e-6&&e[3]>1e-6?e:[0,0,1,1]}(e.view_box);return{id:e.id,title:e.title,cellCm:Number.isFinite(Number(e.cell_cm))&&Number(e.cell_cm)>0?Number(e.cell_cm):5,vb:[i[0]*La,i[1]*t,i[2]*La,i[3]*t],bg:e.plan_url?{href:zn(e.plan_url),...Wa(e,La)}:null,rooms:(e.rooms||[]).map(e=>{const i={...e,...Ua(e)};return{id:i.id,name:i.name,area:i.area??null,open_to:i.open_to||void 0,settings:i.settings||void 0,x:null!=i.x?i.x*La:void 0,y:null!=i.y?i.y*t:void 0,w:null!=i.w?i.w*La:void 0,h:null!=i.h?i.h*t:void 0,poly:i.poly?i.poly.map(e=>[e[0]*La,e[1]*t]):void 0,wall_ids:Array.isArray(i.wall_ids)?[...i.wall_ids]:void 0}}),wall_segments:(e.wall_segments||[]).map(e=>({...e,id:String(e.id),a:[Number(e.a?.[0])*La,Number(e.a?.[1])*t],b:[Number(e.b?.[0])*La,Number(e.b?.[1])*t],cm:Number(e.cm)})),partitions:(e.partitions||[]).map(e=>({id:e.id,a:[e.a[0]*La,e.a[1]*t],b:[e.b[0]*La,e.b[1]*t],cm:Number(e.cm)})),wall_columns:(e.wall_columns||[]).map(e=>({id:e.id,shape:"circle"===e.shape?"circle":"square",center:[e.center[0]*La,e.center[1]*t],cm:Number(e.cm),..."circle"===e.shape?{}:{angle:ua(e.angle)}}))}}):[]}const Ga=5e3,Ka=Ga*La,Ya=240,Xa=La/Ya,Za=1/Ya;function Ja(e){if(!Number.isFinite(e))return e;const t=Math.round(e*Ya/La)*La/Ya;return Math.abs(t-e)<=1e-9*Xa?e:t}function Qa(e){return{x:Ja(e.x),y:Ja(e.y)}}function el(e){return Number.isFinite(e)?Math.min(Ka,Math.max(-Ka,e)):0}function tl(e){return Number.isFinite(e)?Math.min(Ga,Math.max(-Ga,e)):0}const il=1/3,nl=200;function rl(e){return"house"===e?"house":"content"}function ol(e){let t=1/0,i=1/0,n=-1/0,r=-1/0;for(const o of e){const e=Number(o[0]),s=Number(o[1]);Number.isFinite(e)&&Number.isFinite(s)&&(en&&(n=e),s>r&&(r=s))}return t>n?null:{minX:t,minY:i,maxX:n,maxY:r}}function sl(e){const t=[],i=e=>{if(Array.isArray(e))if(e.length>=2&&Number.isFinite(Number(e[0]))&&Number.isFinite(Number(e[1])))t.push([Number(e[0]),Number(e[1])]);else for(const t of e)i(t)};return i(e),ol(t)}function al(e,t){const i=Number.isFinite(t)&&t>0?t:0;return{minX:e.minX-i,minY:e.minY-i,maxX:e.maxX+i,maxY:e.maxY+i}}function ll(e){return e.poly&&e.poly.length?ol(e.poly):null==e.x||null==e.y?null:ol([[e.x,e.y],[e.x+(e.w||0),e.y+(e.h||0)]])}function cl(e,t=1e3,i=1e3){const n=Number(e.x)*t,r=Number(e.y)*i,o=Number(e.w)*t,s=Number(e.h)*i;return![n,r,o,s].every(Number.isFinite)||o<=0||s<=0?null:ol(Dr({x:n,y:r,w:o,h:s,angle:kr(e.angle)||void 0}))}function hl(e,t){const i=[];for(const t of e.rooms||[]){const e=ll(t);e&&i.push(e)}if(e.bg){const t=ol(Dr(e.bg));t&&i.push(t)}for(const e of t||[])if(Array.isArray(e)){const t=ol([e]);t&&i.push(t)}else i.push(e);return i}const dl=e=>{if(!e.length)return 0;const t=[...e].sort((e,t)=>e-t),i=t.length>>1;return t.length%2?t[i]:(t[i-1]+t[i])/2},ul=e=>{let t=1/0,i=1/0,n=-1/0,r=-1/0;for(const o of e)o.minXn&&(n=o.maxX),o.maxY>r&&(r=o.maxY);return t>n||i>r?null:{x:t,y:i,w:n-t,h:r-i}};function pl(e,t){let{x:i,y:n,w:r,h:o}=e;r<30&&(i=i+r/2-100,r=nl),o<30&&(n=n+o/2-100,o=nl);const s="number"==typeof t?{top:t,right:t,bottom:t,left:t}:t,a=Math.max(r,o),l=a*s.top,c=a*s.right,h=a*s.bottom,d=a*s.left;return{x:i-d,y:n-l,w:r+d+c,h:o+l+h}}function _l(e,t={}){const i=t.pad??.05,n=t.k??10,r=t.minSpread??50,o=e.filter(e=>Number.isFinite(e.minX)&&Number.isFinite(e.minY)&&Number.isFinite(e.maxX)&&Number.isFinite(e.maxY)&&Math.abs(e.minX)<=Ka&&Math.abs(e.maxX)<=Ka&&Math.abs(e.minY)<=Ka&&Math.abs(e.maxY)<=Ka);if(!o.length)return{core:null,all:null,outliers:0};const s=ul(o);if(o.length<4){const e=pl(s,i);return{core:e,all:e,outliers:0}}const a=o.map(e=>(e.minX+e.maxX)/2),l=o.map(e=>(e.minY+e.maxY)/2),c=dl(a),h=dl(l),d=o.map((e,t)=>Math.max(Math.abs(a[t]-c),Math.abs(l[t]-h))),u=Math.max(((e,t)=>e.length?e[Math.min(e.length-1,Math.max(0,Math.round(t*(e.length-1))))]:0)([...d].sort((e,t)=>e-t),.75),r),p=d.map(e=>e>n*u),_=p.filter(Boolean).length,m=_&&_<=o.length*il?o.filter((e,t)=>!p[t]):o;return{core:pl(ul(m)||s,i),all:pl(s,i),outliers:m===o?0:_}}function ml(e){return _l(e,{pad:0}).all}function gl(e,t,i=.05){const n=_l(hl(e,t),{pad:i});if(n.core)return n.core;const r=e.vb&&4===e.vb.length&&e.vb[2]>0&&e.vb[3]>0?e.vb:[0,0,La,La];return{x:r[0],y:r[1],w:r[2],h:r[3]}}function fl(e){const t=gl(e);return{x:t.x+t.w/2,y:t.y+t.h/2}}function vl(e){const t=[];for(const i of e.rooms||[]){const e=ll(i);e&&t.push(e)}const i=_l(t,{pad:0}).core,n=La*Ia(e.cellCm??5);return i?Math.max(n,Math.min(Ka,Math.max(i.w,i.h))):n}function yl(e,t,i,n=1){const r=Number(i),o=Number.isFinite(n)&&n>0?n:1;return!Number.isFinite(r)||r<=0?e*o:e*vl(t)*o/r}const bl=[1,2,5,10,20,50,100,200,500,1e3];function wl(e,t,i=7){if(!(e>0&&t>0&&Number.isFinite(t)))return null;const n=bl.find(n=>e*n*t>=i);if(void 0===n)return null;const r=bl.find(e=>e>=5*n)??5*n;return{fine:n,coarse:r}}function kl(e){if(e.poly&&e.poly.length){const t=e.poly.map(e=>e[0]),i=e.poly.map(e=>e[1]),n=Math.min(...t),r=Math.min(...i);return{x:n,y:r,w:Math.max(...t)-n,h:Math.max(...i)-r}}return{x:e.x??0,y:e.y??0,w:e.w??0,h:e.h??0}}function xl(e,t,i,n,r,o=new Set){const s=t[e.id];return!o.has(e.id)&&s&&s.s===e.space?{x:s.x*La,y:s.y*La}:n[e.id]?n[e.id]:Qa(fl(r))}function Sl(e,t,i,n){const r=i["rl_"+(e.id||"")];if(r&&r.s===t)return{x:r.x*La,y:r.y*La};const o=function(e){if(e.poly){const t=e.poly.length;return[e.poly.reduce((e,t)=>e+t[0],0)/t,e.poly.reduce((e,t)=>e+t[1],0)/t]}return[e.x+e.w/2,e.y+.1*Math.min(e.w,e.h)]}(e);return Qa({x:o[0],y:o[1]})}function $l(e,t){for(const i of e?.spaces??[])for(const e of i?.decor??[])if("furniture"===e?.kind&&"string"==typeof e.symbol&&t(e.symbol))return!0;return!1}let Ml=0;const Rl=new Set;const Cl=new class{constructor(e){this.options=e,this._art=null,this._failed=!1,this._terminal=!1,this._inFlight=null,this._hosts=new Set,this._settled=[]}state(){return this._art?"ready":this._failed?"fallback":"pending"}get terminal(){return this._terminal}art(e,t){if(this._art)return this._art[e];t&&!this._failed&&this._hosts.add(t)}adopt(e,t){return!!this._art||(t!==this.options.expectedFingerprint?((this.options.warn??console.warn)("[houseplan] furniture artwork from another build ignored",{fingerprint:t}),!1):(this._install(e),!0))}ensure(){return"pending"!==this.state()?Promise.resolve():(this._inFlight||(this._inFlight=this._loadWithRetry().finally(()=>{this._inFlight=null})),this._inFlight)}onSettled(e){"pending"===this.state()?this._settled.push(e):Promise.resolve().then(e)}async _loadWithRetry(){let e=new Error("furniture artwork did not load");for(const t of[0,1])try{const i=await this.options.load(t);if(i.FURNITURE_ART_FINGERPRINT!==this.options.expectedFingerprint){this._terminal=!0,e=new Error(`furniture artwork fingerprint mismatch: expected ${this.options.expectedFingerprint}, got ${i.FURNITURE_ART_FINGERPRINT}`);break}if(this._art)return;return void this._install(i.GENERATED_FURNITURE_ART)}catch(t){e=t}this._art||(this._failed=!0,(this.options.warn??console.warn)("[houseplan] furniture artwork unavailable",e),this.options.loadFailed?.(this._terminal),this._flush())}_install(e){this._art=e,this._failed=!1,this._flush()}_flush(){const e=[...this._hosts];this._hosts.clear();for(const t of e)t.isConnected&&t.requestUpdate();const t=this._settled.splice(0);for(const e of t)e()}}({expectedFingerprint:"2e6f7d70c797ae4e865b10859c77cc3380a432272a975b8f35b51234ae3cfe62",load:async e=>0===e?await import("./furniture-plan-art.generated-XOCt_Wns.js"):await import((()=>{const e=new URL("./furniture-plan-art.generated-XOCt_Wns.js",import.meta.url);return e.searchParams.set("hp_retry","art-"+ ++Ml),e.href})()),loadFailed:e=>{for(const t of Rl)t(e)}}),Tl=["furniture","appliance","sanitary","other"],Dl=[{id:"sofa",group:"furniture",category:"sofa",w:220,h:90,g:[["r",0,0,1,1],["l",.09,.26,.91,.26],["l",.09,.26,.09,1],["l",.91,.26,.91,1],["l",.5,.26,.5,1]]},{id:"armchair",group:"furniture",category:"armchair",w:90,h:85,g:[["r",0,0,1,1],["l",.14,.28,.86,.28],["l",.14,.28,.14,1],["l",.86,.28,.86,1]]},{id:"coffee_table",group:"furniture",category:"coffee_table",w:110,h:60,g:[["r",0,0,1,1],["r",.08,.14,.84,.72]]},{id:"table_dining",group:"furniture",category:"dining_table",w:140,h:80,g:[["r",0,0,1,1],["r",.06,.11,.88,.78]]},{id:"table_round",group:"furniture",category:"dining_table",w:120,h:120,g:[["e",.5,.5,.5,.5],["e",.5,.5,.41,.41]]},{id:"chair",group:"furniture",category:"chair",w:45,h:45,g:[["r",0,0,1,.18],["r",.06,.18,.88,.8]]},{id:"desk",group:"furniture",category:"work_table",w:120,h:60,g:[["r",0,0,1,1],["r",.63,.07,.31,.86],["l",.63,.5,.94,.5]]},{id:"bed_double",group:"furniture",category:"bed",w:160,h:200,g:[["r",0,0,1,1],["r",0,0,1,.07],["r",.06,.1,.4,.15],["r",.54,.1,.4,.15],["l",0,.33,1,.33]]},{id:"bed_single",group:"furniture",category:"bed",w:90,h:200,g:[["r",0,0,1,1],["r",0,0,1,.07],["r",.15,.1,.7,.15],["l",0,.33,1,.33]]},{id:"nightstand",group:"furniture",category:"nightstand",w:45,h:40,g:[["r",0,0,1,1],["r",.12,.14,.76,.33],["r",.12,.53,.76,.33]]},{id:"wardrobe",group:"furniture",category:"wardrobe",w:100,h:60,g:[["r",0,0,1,1],["l",0,.72,1,.72],["l",.5,.72,.5,1]]},{id:"bookshelf",group:"furniture",category:"wardrobe",w:80,h:30,g:[["r",0,0,1,1],["l",.34,0,.34,1],["l",.67,0,.67,1]]},{id:"fridge",group:"appliance",category:"fridge",w:60,h:65,g:[["r",0,0,1,1],["l",0,.36,1,.36],["l",.83,.44,.83,.64]]},{id:"stove",group:"appliance",category:"cooktop",w:60,h:60,g:[["r",0,0,1,1],["e",.29,.31,.15,.15],["e",.71,.31,.15,.15],["e",.29,.71,.15,.15],["e",.71,.71,.15,.15]]},{id:"dishwasher",group:"appliance",category:"dishwasher",w:60,h:60,g:[["r",0,0,1,1],["r",.1,.12,.8,.76],["e",.5,.5,.27,.27],["e",.5,.5,.13,.13]]},{id:"washer",group:"appliance",category:"washer",w:60,h:60,g:[["r",0,0,1,1],["l",.08,.17,.92,.17],["e",.5,.57,.3,.3],["e",.5,.57,.14,.14]]},{id:"dryer",group:"appliance",category:"dryer",w:60,h:60,g:[["r",0,0,1,1],["l",.08,.17,.92,.17],["e",.5,.57,.3,.3],["p",.36,.5,.5,.64,.64,.5]]},{id:"tv",group:"appliance",category:"tv",w:120,h:30,g:[["r",0,0,1,.42],["l",.5,.42,.5,.72],["l",.3,.72,.7,.72]]},{id:"ac",group:"appliance",category:"air_conditioner",w:90,h:25,g:[["r",0,0,1,1],["l",.05,.55,.95,.55],["l",.05,.79,.95,.79]]},{id:"water_heater",group:"appliance",category:"boiler",w:45,h:45,g:[["e",.5,.5,.5,.5],["e",.5,.5,.31,.31]]},{id:"toilet",group:"sanitary",category:"toilet",w:40,h:70,g:[["r",.06,0,.88,.2],["e",.5,.58,.37,.35],["e",.5,.58,.22,.2]]},{id:"bathtub",group:"sanitary",category:"bathtub",w:170,h:75,g:[["r",0,0,1,1],["r",.05,.11,.77,.78],["e",.89,.5,.045,.1]]},{id:"shower",group:"sanitary",category:"shower",w:90,h:90,g:[["r",0,0,1,1],["l",0,0,1,1],["l",1,0,0,1],["e",.5,.5,.08,.08]]},{id:"sink",group:"sanitary",category:"sink",w:60,h:45,g:[["r",0,0,1,1],["e",.5,.6,.34,.3],["e",.5,.15,.07,.07]]},{id:"kitchen_sink",group:"sanitary",category:"kitchen_sink",w:80,h:60,g:[["r",0,0,1,1],["r",.06,.24,.44,.64],["r",.54,.24,.4,.64],["e",.5,.12,.06,.06]]},{id:"bidet",group:"sanitary",category:"bidet",w:40,h:55,g:[["e",.5,.5,.44,.5],["e",.5,.5,.26,.3]]},{id:"stairs",group:"other",category:"stairs",w:100,h:280,g:[["r",0,0,1,1],["l",0,.111,1,.111],["l",0,.222,1,.222],["l",0,.333,1,.333],["l",0,.444,1,.444],["l",0,.556,1,.556],["l",0,.667,1,.667],["l",0,.778,1,.778],["l",0,.889,1,.889],["l",.5,.93,.5,.06],["p",.38,.16,.5,.06,.62,.16]]},{id:"fireplace",group:"other",category:"fireplace",w:120,h:40,g:[["r",0,0,1,1],["p",.22,1,.22,.42,.78,.42,.78,1]]},{id:"plant",group:"other",category:"plant",w:40,h:40,g:[["e",.5,.5,.22,.22],["l",.5,.28,.5,.02],["l",.5,.72,.5,.98],["l",.28,.5,.02,.5],["l",.72,.5,.98,.5],["l",.34,.34,.13,.13],["l",.66,.66,.87,.87],["l",.66,.34,.87,.13],["l",.34,.66,.13,.87]]},{id:"rug",group:"other",category:"rug",w:200,h:140,g:[["r",0,0,1,1],["r",.06,.09,.88,.82]]}],Al=new Set(["fridge","dishwasher","washer","dryer","ac","water_heater","shower","sink","stairs","fireplace","plant","rug"]),Pl=[...[{id:"coffee_table",group:"furniture",category:"coffee_table",w:120,h:60},{id:"coffee_table_round",group:"furniture",category:"coffee_table",w:80,h:80},{id:"coffee_table_oval",group:"furniture",category:"coffee_table",w:120,h:60},{id:"coffee_table_rounded",group:"furniture",category:"coffee_table",w:120,h:60},{id:"table_dining",group:"furniture",category:"dining_table",w:160,h:90},{id:"table_round",group:"furniture",category:"dining_table",w:110,h:110},{id:"table_dining_oval",group:"furniture",category:"dining_table",w:180,h:100},{id:"table_dining_rounded",group:"furniture",category:"dining_table",w:160,h:90},{id:"desk",group:"furniture",category:"work_table",w:140,h:70},{id:"desk_corner",group:"furniture",category:"work_table",w:160,h:160},{id:"chair",group:"furniture",category:"chair",w:50,h:50},{id:"chair_bar",group:"furniture",category:"chair",w:45,h:48},{id:"armchair",group:"furniture",category:"armchair",w:90,h:90},{id:"armchair_office",group:"furniture",category:"armchair",w:65,h:65},{id:"sofa",group:"furniture",category:"sofa",w:180,h:90},{id:"sofa_three_seat",group:"furniture",category:"sofa",w:240,h:90},{id:"sofa_corner_right",group:"furniture",category:"sofa",w:260,h:170},{id:"bed_single",group:"furniture",category:"bed",w:90,h:200},{id:"bed_double",group:"furniture",category:"bed",w:160,h:200},{id:"nightstand",group:"furniture",category:"nightstand",w:50,h:40},{id:"cabinet_tv",group:"furniture",category:"nightstand",w:140,h:45},{id:"cabinet_shoe",group:"furniture",category:"nightstand",w:80,h:35},{id:"cabinet_sink",group:"furniture",category:"nightstand",w:80,h:50},{id:"bookshelf",group:"furniture",category:"wardrobe",w:100,h:35},{id:"wall_unit",group:"furniture",category:"wardrobe",w:240,h:45},{id:"wardrobe",group:"furniture",category:"wardrobe",w:180,h:60},{id:"kitchen_floor",group:"furniture",category:"kitchen_cabinet",w:60,h:60},{id:"kitchen_floor_corner",group:"furniture",category:"kitchen_cabinet",w:90,h:90},{id:"kitchen_wall",group:"furniture",category:"kitchen_cabinet",w:60,h:35},{id:"kitchen_wall_corner",group:"furniture",category:"kitchen_cabinet",w:60,h:60},{id:"shelf_floor",group:"furniture",category:"shelving",w:100,h:35},{id:"shelf_wall",group:"furniture",category:"shelving",w:100,h:25},{id:"cooktop_two",group:"appliance",category:"cooktop",w:30,h:50},{id:"stove",group:"appliance",category:"cooktop",w:60,h:60},{id:"tv",group:"appliance",category:"tv",w:120,h:28},{id:"tv_wall",group:"appliance",category:"tv",w:120,h:15},{id:"toilet",group:"sanitary",category:"toilet",w:40,h:70},{id:"toilet_built_in",group:"sanitary",category:"toilet",w:40,h:55},{id:"bathtub",group:"sanitary",category:"bathtub",w:170,h:75},{id:"bathtub_corner",group:"sanitary",category:"bathtub",w:140,h:140},{id:"bidet",group:"sanitary",category:"bidet",w:40,h:60},{id:"bidet_built_in",group:"sanitary",category:"bidet",w:40,h:50},{id:"kitchen_sink",group:"sanitary",category:"kitchen_sink",w:60,h:50},{id:"kitchen_sink_double",group:"sanitary",category:"kitchen_sink",w:90,h:50}].map(e=>({id:e.id,group:e.group,category:e.category,w:e.w,h:e.h,designer:!0})),...Dl.filter(e=>Al.has(e.id))],Fl=new Map(Pl.map(e=>[e.id,e]));function zl(e){return e&&Fl.get(e)||null}function Il(e){return!0===Fl.get(e)?.designer}function Ol(e){return Pl.filter(t=>t.group===e)}function El(e){const t=zl(e);return t?{w:t.w,h:t.h}:{w:60,h:60}}function Nl(e,t,i=Xa,n=1e3){const r=Number(t)>0?Number(t):5;return(Number(e)||0)/r*i/n}const Hl=5e-4,Ll=Ga;function Bl(e){return Number.isFinite(e)?Math.max(Hl,Math.min(Ll,e)):Hl}function ql(e){return Number.isFinite(e)?Math.max(1,Math.min(1e4,e)):1}const jl=e=>{const t=Math.round(1e3*e)/1e3;return Object.is(t,-0)?"0":String(t)};function Wl(e,t){const i=zl(e);if(!i)return null;if(i.designer)return Cl.art(e,t)??null;const n=function(e,t,i){if(!e.g)return"";const n=e=>jl(e*t),r=e=>jl(e*i),o=[];for(const s of e.g)if("r"===s[0]){const[,e,t,i,a]=s;o.push(`M${n(e)} ${r(t)}H${n(e+i)}V${r(t+a)}H${n(e)}Z`)}else if("l"===s[0]){const[,e,t,i,a]=s;o.push(`M${n(e)} ${r(t)}L${n(i)} ${r(a)}`)}else if("e"===s[0]){const[,e,a,l,c]=s;o.push(`M${n(e-l)} ${r(a)}A${jl(l*t)} ${jl(c*i)} 0 0 1 ${n(e+l)} ${r(a)}A${jl(l*t)} ${jl(c*i)} 0 0 1 ${n(e-l)} ${r(a)}Z`)}else{const e=s.slice(1);if(e.length<4)continue;let t=`M${n(e[0])} ${r(e[1])}`;for(let i=2;i+10?n:Number.isFinite(r)&&r>0?r:1,s=Number(t),a=o*(Number.isFinite(s)&&s>0?s:1);return Number.isFinite(a)&&a>0?a:o}function Vl(e,t,i,n,r){const o=e+i/2,s=t+n/2,a=(Number(r)||0)*Math.PI/180,l=Math.cos(a),c=Math.sin(a),h=(e,t)=>{const i=e-o,n=t-s;return[o+i*l-n*c,s+i*c+n*l]};return[h(e,t),h(e+i,t),h(e+i,t+n),h(e,t+n)]}function Gl(e,t,i,n,r,o,s){const a=Number.isFinite(s)&&s>0?s:1e-6,l=(Number(e.angle)||0)*Math.PI/180,c=Math.cos(l),h=Math.sin(l),d=-Math.sin(l),u=Math.cos(l),p=e.x+e.w/2,_=e.y+e.h/2,m=t>0?-e.w/2:t<0?e.w/2:0,g=i>0?-e.h/2:i<0?e.h/2:0,f=p+m*c+g*d,v=_+m*h+g*u,y=n-f,b=r-v,w=t?(y*c+b*h)*(t>0?1:-1):e.w,k=i?(y*d+b*u)*(i>0?1:-1):e.h;let x=t?Math.abs(w):e.w,S=i?Math.abs(k):e.h;if(o&&t&&i){const t=x/Math.max(e.w,a),i=S/Math.max(e.h,a),n=Math.abs(t-1)>=Math.abs(i-1)?t:i,r=Math.max(a/e.w,a/e.h),o=Math.max(r,Number.isFinite(n)?n:r);x=e.w*o,S=e.h*o}x=Math.max(a,Number.isFinite(x)?x:a),S=Math.max(a,Number.isFinite(S)?S:a);const $=!!t&&w<0,M=!!i&&k<0,R=t?(t>0?1:-1)*($?-1:1):0,C=i?(i>0?1:-1)*(M?-1:1):0,T=f+R*(x/2)*c+C*(S/2)*d,D=v+R*(x/2)*h+C*(S/2)*u,A=!!e.flip_h!==$,P=!!e.flip_v!==M;return{x:T-x/2,y:D-S/2,w:x,h:S,...Number(e.angle)?{angle:Number(e.angle)}:{},...A?{flip_h:!0}:{},...P?{flip_v:!0}:{}}}function Kl(e,t,i,n){let r=Number(e)+(Number(i)-Number(t));if([r,t,i].every(Number.isFinite)||(r=0),n){const e=r/45;r=45*(e<0?-Math.round(Math.abs(e)):Math.round(e))}return r=(r%360+360)%360,r>180?r-360:r}function Yl(e,t,i,n,r){const o=e.x*t,s=e.y*i,a=e.w*t,l=e.h*i,c=o+a/2,h=s+l/2,d=o+(e.flip_h?a:0),u=s+(e.flip_v?l:0),p=(e.flip_h?-1:1)*a/n,_=(e.flip_v?-1:1)*l/r,m=Number(e.angle)||0;return(m?`rotate(${m} ${c} ${h}) `:"")+`translate(${d} ${u}) scale(${p} ${_})`}function Xl(e,t,i,n=.1){if("string"==typeof e&&!e.trim())return null;const r=Number(e);if(!Number.isFinite(r)||0===r)return null;const o=r*(t?30.48:100),s=Math.abs(o);return si?null:o}function Zl(e,t,i){const n=Math.abs(Number(e))/(i?30.48:100),r=Number(n.toFixed(6));return String(t?-r:r)}const Jl=15e3,Ql=2e3,ec=new WeakMap;function tc(e,t){let i=ec.get(e);if(!i){const t=new Set;i={hiddenAt:"hidden"===e.visibilityState?Date.now():0,token:0,subscribers:t,onVisibility:()=>{const t=ec.get(e);if(!t)return;const i=Date.now();if("hidden"===e.visibilityState){t.hiddenAt||(t.hiddenAt=i);const e={kind:"hidden",token:t.token,at:i,hiddenFor:0,long:!1};for(const i of[...t.subscribers])i(e);return}const n=t.hiddenAt?Math.max(0,i-t.hiddenAt):0;t.hiddenAt=0,t.token++;const r={kind:"visible",token:t.token,at:i,hiddenFor:n,long:n>=Jl};for(const e of[...t.subscribers])e(r)},onPageShow:t=>{const i=ec.get(e);if(!i)return;const n=Date.now();i.token++;const r={kind:"pageshow",token:i.token,at:n,hiddenFor:0,long:!!t.persisted,persisted:!!t.persisted};for(const e of[...i.subscribers])e(r)}},ec.set(e,i),e.addEventListener("visibilitychange",i.onVisibility),e.defaultView?.addEventListener("pageshow",i.onPageShow)}return i.subscribers.add(t),()=>{const i=ec.get(e);i&&(i.subscribers.delete(t),i.subscribers.size||(e.removeEventListener("visibilitychange",i.onVisibility),e.defaultView?.removeEventListener("pageshow",i.onPageShow),ec.delete(e)))}}const ic={now:()=>Date.now(),setTimeout:(e,t)=>window.setTimeout(e,t),clearTimeout:e=>window.clearTimeout(e),requestAnimationFrame:e=>window.requestAnimationFrame(e),cancelAnimationFrame:e=>window.cancelAnimationFrame(e)};class nc{constructor(e,t=ic){this.onChange=e,this.clock=t,this._state="steady",this._token=0,this._frameFingerprint="",this._hasCompleteFrame=!1,this._overlayPhase="none",this._recoveryReason=null,this._overlayTimer=0,this._overlayRaf=0,this._overlayOpaqueAt=0,this._barrierRafs=new Set,this._trace=[],this._disposed=!1}get state(){return this._state}get token(){return this._token}get frameFingerprint(){return this._frameFingerprint}get hasCompleteFrame(){return this._hasCompleteFrame}get overlayPhase(){return this._overlayPhase}get overlayVisible(){return"none"!==this._overlayPhase}get overlayBlocksInteraction(){return this.overlayVisible}get recoveryReason(){return this._recoveryReason}get trace(){return this._trace.map(e=>({...e,...e.stage?{stage:[...e.stage]}:{}}))}note(e,t={}){this.record(e,void 0,t)}record(e,t,i={}){this._trace.push({at:this.clock.now(),token:this._token,event:e,state:this._state,...t?{reason:t}:{},...i}),this._trace.length>80&&this._trace.splice(0,this._trace.length-80)}changed(){this._disposed||this.onChange()}adoptCompleteFrame(e){e&&(this._hasCompleteFrame=!0,this._frameFingerprint=e,this._state="steady",this._recoveryReason=null,this.clearOverlay(),this.record("frame-adopted"),this.changed())}markCompleteFrame(e){e&&(this._hasCompleteFrame=!0,this._frameFingerprint=e,this._state="steady",this._recoveryReason=null,this.clearOverlay(),this.record("frame-complete"),this.changed())}refreshCompleteFrame(e){!this._disposed&&this._hasCompleteFrame&&"steady"===this._state&&e&&e!==this._frameFingerprint&&(this._frameFingerprint=e,this.record("frame-refreshed"))}visibility(e){return"hidden"===e.kind?(this.record("visibility-hidden"),this._token):e.long||"visible"!==e.kind&&"pageshow"!==e.kind?this.beginCandidate("pageshow"===e.kind?"pageshow":"long-resume"):(this.record("pageshow"===e.kind?"pageshow-noop":"visibility-visible-quick"),this._token)}beginCandidate(e,t="plan"){return this._token++,this._recoveryReason=t,this._hasCompleteFrame?(this._state="connection"===t?"offline-stale":"holding",this.clearOverlay()):this.overlayVisible?this._state="overlay-visible":(this._state="overlay-pending",this.scheduleOverlay(t)),this.record("candidate-start",e),this.changed(),this._token}connectionLost(){return this.beginCandidate("connection-lost","connection")}candidateReady(e){return!this._disposed&&e===this._token&&(this._state="candidate-ready",this.record("candidate-ready"),this.changed(),!0)}async commitAfterPaint(e,t){if(this._disposed||e!==this._token)return!1;let i=!0;const n=(async()=>{for(await t.updateComplete();i&&!this._disposed&&e===this._token;)if(t.stageValid()&&t.assetsReady()){if(await this.nextFrame(),e!==this._token||!t.stageValid()||!t.assetsReady())continue;if(await this.nextFrame(),e===this._token&&t.stageValid()&&t.assetsReady())return!0}else await this.nextFrame();return!1})();let r=0;const o=new Promise(e=>{r=this.clock.setTimeout(()=>e({ready:!1,timedOut:!0}),Ql)}),s=await Promise.race([n.then(e=>({ready:e,timedOut:!1})),o]);return i=!1,this.clock.clearTimeout(r),!this._disposed&&e===this._token&&(!(!s.ready&&!s.timedOut)&&(s.ready?(this._hasCompleteFrame=!0,this._frameFingerprint=t.frameFingerprint(),this.record("paint-barrier"),this.finishOverlayAfterCommit(),!0):(this.record("paint-barrier-timeout"),this._hasCompleteFrame?(this._state="connection"===this._recoveryReason?"offline-stale":"steady",this.clearOverlay()):(this._state="recovery-error","opaque"!==this._overlayPhase&&this.showOverlayNow()),this.changed(),!1)))}retry(e=this._recoveryReason||"plan"){return this.beginCandidate("retry",e)}nextFrame(){return new Promise(e=>{const t=this.clock.requestAnimationFrame(()=>{this._barrierRafs.delete(t),e()});this._barrierRafs.add(t)})}scheduleOverlay(e){this.clearOverlayTimer(),this._recoveryReason=e,this._overlayTimer=this.clock.setTimeout(()=>{this._overlayTimer=0,this._hasCompleteFrame||"overlay-pending"!==this._state&&"candidate-ready"!==this._state||(this._state="overlay-visible",this._overlayPhase="entering",this.record("overlay-enter"),this.changed(),this._overlayRaf=this.clock.requestAnimationFrame(()=>{this._overlayRaf=0,"entering"===this._overlayPhase&&(this._overlayPhase="fading-in",this.changed(),this._overlayTimer=this.clock.setTimeout(()=>{this._overlayTimer=0,"fading-in"===this._overlayPhase&&(this._overlayPhase="opaque",this._overlayOpaqueAt=this.clock.now(),this.record("overlay-opaque"),this.changed())},150))}))},150)}showOverlayNow(){this.clearOverlayTimer(),this._overlayPhase="opaque",this._overlayOpaqueAt=this.clock.now(),this.record("overlay-error")}finishOverlayAfterCommit(){if(this.clearOverlayTimer(),"none"===this._overlayPhase||"entering"===this._overlayPhase||"fading-in"===this._overlayPhase)return this.clearOverlay(),this._state="steady",this._recoveryReason=null,this.record("candidate-committed"),void this.changed();const e=Math.max(0,this._overlayOpaqueAt+250-this.clock.now());this._overlayTimer=this.clock.setTimeout(()=>{this._overlayTimer=0,this._overlayPhase="leaving",this.record("overlay-leave"),this.changed(),this._overlayTimer=this.clock.setTimeout(()=>{this._overlayTimer=0,this._overlayPhase="none",this._state="steady",this._recoveryReason=null,this.record("candidate-committed"),this.changed()},180)},e)}clearOverlayTimer(){this._overlayTimer&&this.clock.clearTimeout(this._overlayTimer),this._overlayTimer=0}clearOverlay(){this.clearOverlayTimer(),this._overlayRaf&&this.clock.cancelAnimationFrame(this._overlayRaf),this._overlayRaf=0,this._overlayPhase="none",this._overlayOpaqueAt=0}dispose(){this._disposed=!0,this._token++,this.clearOverlay();for(const e of this._barrierRafs)this.clock.cancelAnimationFrame(e);this._barrierRafs.clear()}}function rc(e){let t=2166136261,i=2654435769;const n=new WeakSet,r=e=>{for(let n=0;n>>0)+(i>>>2)}},o=e=>{if(null===e)return void r("n");const t=typeof e;if("string"===t)return void r(`s${e.length}:${e}`);if("number"===t)return void r(`d${Number.isNaN(e)?"NaN":String(e)}`);if("boolean"===t)return void r(e?"t":"f");if("undefined"===t)return void r("u");if("object"!==t)return void r(`${t}:${String(e)}`);const i=e;if(n.has(i))r("[cycle]");else{if(n.add(i),Array.isArray(e)){r("[");for(const t of e)o(t);return r("]"),void n.delete(i)}r("{");for(const t of Object.keys(e).sort())r(t),o(e[t]);r("}"),n.delete(i)}};return o(e),`${(t>>>0).toString(16).padStart(8,"0")}${(i>>>0).toString(16).padStart(8,"0")}`}function oc(e){return rc(e)}const sc=new WeakMap;class ac{constructor(e,t=()=>Date.now()){this.onUpdate=e,this.now=t,this.fallbackAuthority={},this.referenceOwner={},this.referenced=new Set,this.queued=new Set,this.disposed=!1,this.sharedUpdate=()=>{this.disposed||this.onUpdate()}}bind(e){const t=((e,t)=>{const i=e?.connection||e?.callWS||t;return!i||"object"!=typeof i&&"function"!=typeof i?t:i})(e,this.fallbackAuthority);return this.shared&&this.authority===t||(this.shared&&(this.shared.listeners.delete(this.sharedUpdate),this.shared.references.delete(this.referenceOwner)),this.authority=t,this.shared=(e=>{let t=sc.get(e);return t||(t={signed:{},queued:new Set,inFlight:new Map,retry:new Map,listeners:new Set,settlers:new Set,references:new Map},sc.set(e,t)),t})(t),this.disposed||(this.shared.listeners.add(this.sharedUpdate),this.shared.references.set(this.referenceOwner,new Set(this.referenced)))),this.shared}start(e,t){this.disposed=!1,this.referenced=new Set(t());const i=this.bind(e());i.listeners.add(this.sharedUpdate),i.references.set(this.referenceOwner,new Set(this.referenced)),this.stopTimer(),this.resignTimer=setInterval(()=>this.resign(e(),t()),288e5)}dispose(){if(this.disposed=!0,this.stopTimer(),clearTimeout(this.batchTimer),this.shared){this.shared.listeners.delete(this.sharedUpdate),this.shared.references.delete(this.referenceOwner);for(const e of this.queued)this.shared.queued.delete(e)}this.queued.clear()}invalidate(e){const t=this.bind(e);clearTimeout(this.batchTimer),this.queued.clear(),t.queued.clear(),t.inFlight.clear(),t.retry.clear(),t.signed={}}stopTimer(){void 0!==this.resignTimer&&clearInterval(this.resignTimer),this.resignTimer=void 0}display(e,t){const i=zn(t);if(!i.startsWith("/api/houseplan/content/"))return i;const n=this.bind(e);this.referenced.add(i),n.references.set(this.referenceOwner,new Set(this.referenced));const r=n.signed[i],o=r?this.now()-r.at:1/0;return o{const t=[...this.queued];this.queued.clear();for(const e of t)i.queued.delete(e);this.sign(e,t)},30))}sign(e,t){if(!t.length||!e?.callWS)return;const i=this.bind(e);for(const n of function(e,t){const i=Math.max(1,Math.floor(t)),n=[];for(let t=0;t{const n=i.inFlight.get(e);return!(void 0!==n&&t-n<15e3)&&(i.inFlight.set(e,t),!0)});r.length&&e.callWS({type:"houseplan/content/sign",paths:r}).then(e=>{const t=this.now();let n=0,o=!1;for(const s of r){const r=e?.urls?.[s];if("string"==typeof r&&r){const e=i.signed[s];e?.loaded&&e.url!==r?(e.pending={url:r,at:t},this.preloadReplacement(i,s,r,t)):(i.signed[s]={url:r,at:t,loaded:e?.url===r&&!!e.loaded},o=!0),i.retry.delete(s),n++}else this.backOff(i,s)}if(n&&(this.trimShared(i),o))for(const e of[...i.listeners])e()}).catch(()=>{for(const e of r)this.backOff(i,e)}).finally(()=>{for(const e of r)i.inFlight.get(e)===t&&i.inFlight.delete(e);for(const e of[...i.settlers])e()})}}preloadReplacement(e,t,i,n){const r=()=>{const r=e.signed[t];if(r?.pending?.url===i){e.signed[t]={url:i,at:n,loaded:!0},e.retry.delete(t),this.trimShared(e);for(const t of[...e.listeners])t()}},o=()=>{const n=e.signed[t];n?.pending?.url===i&&(delete n.pending,this.backOff(e,t))};if("undefined"==typeof Image)return void r();const s=new Image;s.onload=()=>{("function"==typeof s.decode?s.decode():Promise.resolve()).then(r).catch(o)},s.onerror=o,s.src=i}preloadCurrentImage(e,t,i){if(i.loaded)return Promise.resolve(!0);if(i.preload)return i.preload;if("undefined"==typeof Image)return i.loaded=!0,Promise.resolve(!0);const n=i.url;return i.preload=new Promise(r=>{const o=new Image;let s=!1;const a=o=>{if(s)return;s=!0,clearTimeout(l);const a=e.signed[t];if(a===i&&delete a.preload,o&&a===i&&a.url===n){a.loaded=!0;for(const t of[...e.listeners])t();r(!0)}else o||a!==i||this.backOff(e,t),r(!1)};o.onload=()=>{("function"==typeof o.decode?o.decode():Promise.resolve()).then(()=>a(!0)).catch(()=>a(!1))},o.onerror=()=>a(!1);const l=setTimeout(()=>a(!1),Ql);o.src=n}),i.preload}prepareImage(e,t){const i=zn(t);if(!i.startsWith("/api/houseplan/content/"))return Promise.resolve(!0);const n=this.bind(e),r=()=>{const t=n.signed[i];if(t&&this.now()-t.atthis.now()&&!n.inFlight.has(i)&&!n.queued.has(i)?Promise.resolve(!1):null},o=r();return o?(s=o,new Promise(e=>{let t=!1;const i=i=>{t||(t=!0,clearTimeout(n),e(i))},n=setTimeout(()=>i(!1),Ql);s.then(i).catch(()=>i(!1))})):new Promise(e=>{let t=!1,i=null;const o=i=>{t||(t=!0,clearTimeout(a),n.settlers.delete(s),e(i))},s=()=>{t||i||(i=r(),i&&i.then(o).catch(()=>o(!1)))},a=setTimeout(()=>o(!1),Ql);n.settlers.add(s),s()});var s}backOff(e,t){const i=e.retry.get(t)?.delay||0,n=Math.min(6e4,i?2*i:2e3);e.retry.set(t,{notBefore:this.now()+n,delay:n})}trimShared(e){const t=Object.entries(e.signed);if(t.length<=512)return;const i=new Set(e.inFlight.keys());for(const t of e.references.values())for(const e of t)i.add(e);for(const[e,n]of t)(n.pending||n.preload)&&i.add(e);t.sort((e,t)=>t[1].at-e[1].at);const n=t.filter(([e])=>i.has(e));for(const e of t){if(n.length>=512)break;i.has(e[0])||n.push(e)}e.signed=Object.fromEntries(n)}resign(e,t){const i=this.bind(e);this.referenced=new Set(t),i.references.set(this.referenceOwner,new Set(this.referenced));const n=this.now(),r=new Set;for(const e of i.references.values())for(const t of e)r.add(t);const o={};for(const[e,t]of Object.entries(i.signed))r.has(e)&&n-t.at!!o[e]&&!o[e].pending))}markLoaded(e,t,i){const n=zn(t);if(!n.startsWith("/api/houseplan/content/"))return;const r=this.bind(e).signed[n];if(r&&(!i||r.url===i)&&!r.loaded){r.loaded=!0;for(const t of[...this.bind(e).listeners])t()}}isReady(e,t){const i=zn(t);if(!i.startsWith("/api/houseplan/content/"))return!0;const n=this.bind(e).signed[i];return!!n&&this.now()-n.ate.id===t)}function cc(e,t){return{id:e,title:t,plan_url:null,view_box:[0,0,1,1],rooms:[],wall_segments:[]}}function hc(e="file"){const t="draw"===e;return{source:e,showBorders:t,showNames:t,displayTouched:!1}}function dc(e,t){if(e.displayTouched)return{...e,source:t};const i="draw"===t;return{...e,source:t,showBorders:i,showNames:i}}function uc(e,t,i){return{...e,[t]:i,displayTouched:!0}}function pc(e){const t=String(e??"").trim().replace(",",".");if(!/^[+-]?(?:\d+(?:\.\d*)?|\.\d+)$/.test(t))return null;const i=Number(t);return Number.isFinite(i)?i:null}function _c(e,t){const i=e=>{if(""===String(e??"").trim())return{valid:!0,value:null};const t=pc(e);return{valid:null!==t,value:t}},n=i(e),r=i(t);return n.valid&&r.valid?null!==n.value&&null!==r.value&&n.value>r.value?{valid:!0,min:r.value,max:n.value}:{valid:!0,min:n.value,max:r.value}:{valid:!1,min:n.value,max:r.value}}function mc(e,t,i,n,r,o){const s=_c(n,r);return ln(e,t,o&&s.valid?{settings:{...i.settings||{},temp_min:s.min,temp_max:s.max}}:i)}function gc(e){const t=e=>"number"==typeof e&&Number.isFinite(e)?String(e):"";return[t(e?.temp_min),t(e?.temp_max)]}function fc(e,t,i){const n=_c(t,i);return!!n.valid&&(null===n.min?delete e.temp_min:e.temp_min=n.min,null===n.max?delete e.temp_max:e.temp_max=n.max,!0)}var vc="M11,18H13V16H11V18M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M12,20C7.59,20 4,16.41 4,12C4,7.59 7.59,4 12,4C16.41,4 20,7.59 20,12C20,16.41 16.41,20 12,20M12,6A4,4 0 0,0 8,10H10A2,2 0 0,1 12,8A2,2 0 0,1 14,10C14,12 11,11.75 11,15H13C13,12.75 16,12.5 16,10A4,4 0 0,0 12,6Z";function yc(e,t,i){return[e[0]*t+e[1]*i+e[2],e[3]*t+e[4]*i+e[5]]}function bc(e,t){let i=0;for(const[n,r]of t){const t=yc(e,n[0],n[1]);i=Math.max(i,Math.hypot(t[0]-r[0],t[1]-r[1]))}return i}const wc=e=>{if(null==e||""===e)return null;const t=Number(e);return Number.isFinite(t)?t:null},kc=e=>{const t=e,i=wc(Array.isArray(t)?t[0]:t?.x),n=wc(Array.isArray(t)?t[1]:t?.y);return null==i||null==n?null:[i,n]};function xc(e){if(!Array.isArray(e))return null;const t=[];for(const i of e){const e=kc(i);if(!e)return null;t.push(e)}if(t.length>1){const e=t[0],i=t[t.length-1];e[0]===i[0]&&e[1]===i[1]&&t.pop()}if(t.length<3)return null;let i=0,n=0,r=0;for(let e=0;ee+t[0],0)/t.length,t.reduce((e,t)=>e+t[1],0)/t.length]:[n/(3*i),r/(3*i)]}function Sc(e){if(!Array.isArray(e))return null;const t=[];for(const i of e){const e=kc(i);if(!e)return null;t.push(e)}if(t.length>1){const e=t[0],i=t[t.length-1];e[0]===i[0]&&e[1]===i[1]&&t.pop()}const i=xc(t);if(!i)return null;const n=t.map(e=>e[0]),r=t.map(e=>e[1]);return{centroid:i,bbox:[Math.min(...n),Math.min(...r),Math.max(...n),Math.max(...r)]}}function $c(e){let t=e;if(t&&"object"==typeof t&&!Array.isArray(t)){const e=t;t=e.path??e.points??t}if(!Array.isArray(t)||!t.length)return[];let i=(t.some(e=>(e=>Array.isArray(e)?e.length>=2&&!Array.isArray(e[0])&&("object"!=typeof e[0]||null==e[0]):!!e&&"object"==typeof e&&("x"in e||"y"in e))(e))?[t]:t.filter(Array.isArray)).map(e=>e.map(kc).filter(e=>null!=e)).filter(e=>e.length>=2);i.length>64&&(i=i.slice(-64));const n=i.reduce((e,t)=>e+t.length,0);if(n<=4e3)return i.map(e=>e.slice());const r=4e3-2*i.length,o=i.map(e=>e.length-2),s=o.reduce((e,t)=>e+t,0),a=o.map(e=>r*e/s),l=a.map(Math.floor);let c=r-l.reduce((e,t)=>e+t,0);const h=a.map((e,t)=>({index:t,fraction:e-Math.floor(e)})).sort((e,t)=>t.fraction-e.fraction||e.index-t.index);for(let e=0;efunction(e,t){if(t>=e.length)return e.slice();if(t<=2)return[e[0],e[e.length-1]];const i=[];for(let n=0;ne.slice()),i=t[t.length-1];return i?(i.length>2?i.pop():t.pop(),t):[]}const Cc=e=>Number.isFinite(e[0])&&Number.isFinite(e[1]),Tc=(e,t)=>e[0]===t[0]&&e[1]===t[1];function Dc(e){if(!e)return null;const t=e.vacuum_position||e.robot_position||null,i=t&&null!=wc(t.x)&&null!=wc(t.y)?{x:wc(t.x),y:wc(t.y),a:wc(t.a??t.angle??t.theta)}:null,n=$c(e.path?.path??e.path?.points??e.path),r=[],o=e.rooms,s=Array.isArray(o)?o.map((e,t)=>[String(e?.id??t),e]):o&&"object"==typeof o?Object.entries(o):[];for(const[e,t]of s){if(!t||"object"!=typeof t)continue;const i=String(t.name??t.label??"").trim(),n=[[wc(t.cx),wc(t.cy)],[wc(t.center?.x),wc(t.center?.y)],[wc(t.x),wc(t.y)]].find(([e,t])=>null!=e&&null!=t);let o=n?.[0]??null,s=n?.[1]??null;const a=Sc(t.outline),l=wc(t.x0),c=wc(t.y0),h=wc(t.x1),d=wc(t.y1),u=(null!=l&&null!=c&&null!=h&&null!=d?[Math.min(l,h),Math.min(c,d),Math.max(l,h),Math.max(c,d)]:null)||a?.bbox||null;if(null!=o&&null!=s||!a||([o,s]=a.centroid),null!=o&&null!=s||!u||(o=(u[0]+u[2])/2,s=(u[1]+u[3])/2),i&&null!=o&&null!=s){const t={id:e,name:i,cx:o,cy:s};u&&([t.x0,t.y0,t.x1,t.y1]=u),r.push(t)}}const a=function(e){return String(e.map_name??e.current_map??e.map_index??e.selected_map??"default")}(e);return i||r.length||n.length?{pos:i,path:n,rooms:r,mapId:a}:null}function Ac(e,t,i){return![e,t,i].every(Number.isFinite)||e<0||t<=0||i<=0?Number.POSITIVE_INFINITY:e/t*i}const Pc=40;function Fc(e,t,i){if(!e||!t)return null;const n=t.attributes||{},r=e.split(".")[0]||"",o=null!=i?.platform?String(i.platform):null,s=!!kc(n.vacuum_position??n.robot_position),a=!(!n.rooms||"object"!=typeof n.rooms),l=$c(n.path?.path??n.path?.points??n.path).length>0,c=[n.map_name,n.current_map,n.map_index,n.selected_map].some(e=>null!=e),h="xiaomi_cloud_map_extractor"===o,d=a||l||c;let u=null;if(s?u="compatible":h?u="known_xcme_incomplete":d?u="partial":"camera"===r&&(u="camera"),!u)return null;const p=s?"camera"===r?300:200:h?100:d?50:0;return{entityId:e,name:String(n.friendly_name||e),platform:o,category:u,hasPosition:s,hasRooms:a,hasPath:l,hasMapId:c,score:p}}const zc=e=>e.toLowerCase().replace(/[\s_\-.,]+/g,"");function Ic(e,t){const i=new Set(t.map(zc).filter(Boolean)),n=new Set;for(const t of e){const e=zc(t.name||"");e&&i.has(e)&&n.add(e)}return n.size}function Oc(e,t){const i=new Map(t.map(e=>[zc(e.name),e])),n=[],r=[];for(const t of e){const e=i.get(zc(t.name));e&&(n.push([[t.cx,t.cy],[e.cx,e.cy]]),r.push(t.name))}if(n.length<3)return null;const o=function(e){if(e.length<3)return null;let t=0,i=0,n=0,r=0,o=0,s=0,a=0,l=0,c=0,h=0,d=0,u=0;for(const[[p,_],[m,g]]of e){if(![p,_,m,g].every(Number.isFinite))return null;t+=p*p,i+=p*_,n+=p,r+=_*_,o+=_,s+=1,a+=p*m,l+=_*m,c+=m,h+=p*g,d+=_*g,u+=g}const p=[t,i,n,i,r,o,n,o,s],_=e=>{const[t,i,n,r,o,s,a,l,c]=p,h=t*(o*c-s*l)-i*(r*c-s*a)+n*(r*l-o*a);if(!Number.isFinite(h)||Math.abs(h)<1e-9)return null;const d=[(o*c-s*l)/h,(n*l-i*c)/h,(i*s-n*o)/h,(s*a-r*c)/h,(t*c-n*a)/h,(n*r-t*s)/h,(r*l-o*a)/h,(i*a-t*l)/h,(t*o-i*r)/h];return[d[0]*e[0]+d[1]*e[1]+d[2]*e[2],d[3]*e[0]+d[4]*e[1]+d[5]*e[2],d[6]*e[0]+d[7]*e[1]+d[8]*e[2]]},m=_([a,l,c]),g=_([h,d,u]);if(!m||!g)return null;const f=[m[0],m[1],m[2],g[0],g[1],g[2]];return f.every(Number.isFinite)?f:null}(n);return o?{matrix:o,matched:r,residual:bc(o,n)}:null}function Ec(e,t,i){const n=e[e.length-1];if(n&&n[0]===t[0]&&n[1]===t[1])return e;if(e.push(t),e.length<=600)return e;let r=function(e,t){if(e.length<3)return e.slice();const i=new Uint8Array(e.length);i[0]=i[e.length-1]=1;const n=[[0,e.length-1]];for(;n.length;){const[r,o]=n.pop(),[s,a]=e[r],[l,c]=e[o],h=l-s,d=c-a,u=Math.hypot(h,d)||1e-9;let p=0,_=-1;for(let t=r+1;tp&&(p=i,_=t)}_>0&&p>t&&(i[_]=1,n.push([r,_],[_,o]))}const r=[];for(let t=0;t600&&(r=r.filter((e,t)=>t%2==0||t===r.length-1)),r}function Nc(e){return"cleaning"===e||"returning"===e||"on"===e}const Hc={0:[1,0],90:[0,1],180:[-1,0],270:[0,-1]};function Lc(e){const[t,i]=Hc[e.rot]||[1,0],n=e.mir?-1:1;return[e.s*t*n,-e.s*i,e.ox,e.s*i*n,e.s*t,e.oy]}function Bc(e){const t=e[0]*e[4]-e[1]*e[3];if(!Number.isFinite(t)||Math.abs(t)<1e-12)return null;const i=t<0,n=Math.sqrt(Math.abs(t));let r=180*Math.atan2(-e[1],e[4])/Math.PI;return r=(90*Math.round(r/90)%360+360)%360,{ox:e[2],oy:e[5],s:n,rot:r,mir:i}}function qc(e,t){const i=[],n=[];for(const t of e)null!=t.x0?(i.push(t.x0,t.x1),n.push(t.y0,t.y1)):(i.push(t.cx),n.push(t.cy));if(!i.length)return{ox:t[0]+t[2]/2,oy:t[1]+t[3]/2,s:t[2]/1e4,rot:0,mir:!0};const r=Math.min(...i),o=Math.max(...i),s=Math.min(...n),a=Math.max(...n),l=Math.max(o-r,a-s)||1,c={ox:0,oy:0,s:.6*Math.min(t[2],t[3])/l,rot:0,mir:!0},h=Lc(c),[d,u]=yc(h,(r+o)/2,(s+a)/2);return c.ox=t[0]+t[2]/2-d,c.oy=t[1]+t[3]/2-u,c}function jc(e,t,i,n){const[r,o]=yc(Lc(t),i,n),s=Lc({...e,ox:0,oy:0}),[a,l]=yc(s,i,n);return{...e,ox:r-a,oy:o-l}}function Wc(e){const t=e?.trail_mode;return"never"===t||"cleaning"===t||"always"===t?t:!1===e?.trail?"never":"cleaning"}const Uc=e=>"number"==typeof e&&Number.isFinite(e);function Vc(e){return Array.isArray(e)&&6===e.length&&e.every(Uc)?[e[0],e[1],e[2],e[3],e[4],e[5]]:null}function Gc(e,t,i){return"legacy:"+e+" "+t+" "+i}function Kc(e,t,i,n){const r=t?.map_routes;if(Array.isArray(r))return r.filter(e=>e&&"string"==typeof e.id&&e.id).map(e=>({id:e.id,source:String(e.source??""),map_id:String(e.map_id??""),space:String(e.space??""),calibration:Vc(e.calibration)}));const o="string"==typeof t?.source&&t.source?t.source:n||"";if(!o)return[];const s=t?.calibration;if(!s||"object"!=typeof s)return[];const a=[];for(const t of Object.keys(s)){const n=Vc(s[t]);n&&a.push({id:Gc(e,o,t),source:o,map_id:t,space:i,calibration:n})}return a}const Yc=(e,t)=>e instanceof Map?e.get(t):e?.[t];function Xc(e){const t=[];let i=!1,n="",r="";for(const o of e.routes){const s=Yc(e.observed,o.source);void 0!==s&&(i=!0,n||(n=o.source,r=s),s===o.map_id&&t.push(o))}if(t.length>1)return{kind:"ambiguous",routeIds:t.map(e=>e.id).sort()};if(1===t.length){const i=t[0];if(e.spaceIds&&!e.spaceIds.has(i.space))return{kind:"missing_space",route:i};const n=Vc(i.calibration);return n?{kind:"ready",route:{...i,calibration:n}}:{kind:"needs_calibration",route:i}}if(i)return{kind:"unmapped",source:n,mapId:r};const o=e.observed instanceof Map?[...e.observed.entries()]:Object.entries(e.observed||{});if(o.length){const e=o.slice().sort((e,t)=>e[0].localeCompare(t[0]))[0];return{kind:"unmapped",source:e[0],mapId:e[1]}}return{kind:"none"}}function Zc(e,t,i){const n=new Set;for(const t of e)t.source&&n.add(t.source);for(const e of t)e&&n.add(e);const r={};for(const e of[...n].sort()){const t=i(e);void 0!==t&&(r[e]=t)}return r}function Jc(e,t,i){if(!e)return null;const n="string"==typeof e.route_id?e.route_id:"";if(n)return t.find(e=>e.id===n)||null;const r=function(e,t,i){if(!e||"string"!=typeof e.map_id)return{kind:"orphan_run"};const n=e.map_id,r="string"==typeof i?i:"";let o=t.filter(e=>e.map_id===n);return r&&(o=o.filter(e=>e.source===r)),1===o.length?{kind:"adopted",route:o[0]}:0===o.length?{kind:"orphan_run"}:{kind:"ambiguous_run",routeIds:o.map(e=>e.id).sort()}}(e,t,i);return"adopted"===r.kind?r.route:null}function Qc(e){const t="ready"===e.resolution.kind?e.resolution.route:null,i=t&&t.space===e.renderSpace?Vc(t.calibration):null,n=Jc(e.serverCurrent,e.routes,e.rootSource),r=!!t&&!!n&&n.id===t.id,o=Jc(e.serverPrevious,e.routes,e.rootSource);return{live:i,currentRunMatches:r,previous:!!o&&o.space===e.renderSpace&&(e.explicitRoutes||!!t&&o.id===t.id)?Vc(o.calibration):null}}const eh={availability:"available",status:"alarm",activity:"none"},th=new Set(["motion","vibration","sound"]),ih=new Set(["occupancy","presence"]),nh=new Set(["door","window","garage_door","opening"]),rh=new Set(["running","power"]),oh=new Set(["smoke","gas","carbon_monoxide","moisture","safety","tamper","problem"]);const sh=new Set(["running","working","washing","rinsing","spinning","drying","heating","cooling","cleaning","cooking","playing","recording","pumping","irrigating","humidifying","dehumidifying","fan","preheating","defrosting"]),ah=new Set([...sh,"start","started","run","active","in_progress","wash","rinse","spin","dry"]),lh=new Set(["off","idle","paused","standby","docked","finished","complete","completed","stopped","ready","sleeping","stop","end","done","inactive"]),ch=new Set(["heat","cool","heat_cool","auto","dry","fan_only"]),hh=e=>""===e||"unknown"===e||"unavailable"===e||"__missing__"===e,dh=e=>String(e??"").trim().toLowerCase(),uh=e=>dh(e).replace(/[\s-]+/g,"_").replace(/_+/g,"_").replace(/^_|_$/g,""),ph=new Map([["run_state",0],["job_state",0],["operation_state",0],["activity_state",0],["machine_state",1],["running_state",1],["status",2],["device_status",2],["machine_status",2]]),_h=new Set(["wifi","connection","signal","battery"]);function mh(e,t){const i=e?.entities?.[t]||{};if("config"===i.entity_category)return null;const n=String(t||"").split(".").slice(1).join("."),r=[i.translation_key,i.original_name,i.name],o=[...r,n];r.some(e=>dh(e))||o.push(e?.states?.[t]?.attributes?.friendly_name);const s=o.map(uh).filter(Boolean);if(s.some(e=>e.split("_").some(e=>_h.has(e))))return null;let a=null;for(const e of s)for(const[t,i]of ph)(e===t||e.endsWith(`_${t}`))&&(a=null==a?i:Math.min(a,i));return a}const gh=(e,t)=>null!=mh(e,t);function fh(e,t){if(!t.startsWith("switch."))return!1;const i=e?.entities?.[t]||{},n=e?.states?.[t],r=t.slice(7).toLowerCase();if(/(?:^|_)(?:main_)?power$/.test(r))return!0;if([i.translation_key,i.original_name,i.name].map(dh).some(e=>["power","main power","power switch","питание"].includes(e)))return!0;const o=dh(n?.attributes?.friendly_name);return/(?:^|[\s._-])(?:main[\s._-]+)?power$/.test(o)||/(?:^|[\s._-])питание$/.test(o)}function vh(e){for(const t of["hvac_action","action","current_operation","run_state","job_state","operation","activity"]){const i=dh(e?.[t]);if(sh.has(i)||lh.has(i))return i}return""}function yh(e,t){const i=e?.states?.[t],n=i?dh(i.state):"__missing__",r=String(t||"").split(".")[0],o=dh(i?.attributes?.device_class),s={eid:t,state:n,availability:hh(n)?"unavailable":"available",status:"neutral",activity:"none",edge:"none"};if("unavailable"===s.availability)return s;if(function(e,t,i){return"alarm_control_panel"===e?"triggered"===i:"on"===i&&Wn(e,t)}(r,o,n))return{...s,status:"alarm"};if("binary_sensor"===r)return th.has(o)?{...s,edge:"rising"}:ih.has(o)?{...s,activity:"on"===n?"presence":"none"}:nh.has(o)?{...s,status:"on"===n?"open":"neutral",edge:"rising"}:"moving"===o?{...s,activity:"on"===n?"transition":"none"}:rh.has(o)&&"on"===n?{...s,status:"working",activity:"running"}:s;if("cover"===r)return{...s,activity:"opening"===n||"closing"===n?"transition":"none",edge:"terminal_transition"};if("lock"===r)return{...s,status:"unlocked"===n||"open"===n?"open":"neutral",activity:"locking"===n||"unlocking"===n?"transition":"none",edge:"terminal_transition"};if("valve"===r)return{...s,status:["open","opening","closing"].includes(n)?"open":"neutral",activity:"opening"===n||"closing"===n?"transition":"none",edge:"terminal_transition"};if("climate"===r){const e=vh(i.attributes),t=Array.isArray(i.attributes?.hvac_modes)?i.attributes.hvac_modes.map(dh):[],r=!lh.has(n)&&(ch.has(n)||sh.has(n)||t.includes(n));return(e?sh.has(e):r)?{...s,status:"working",activity:"running"}:s}if(["light","switch","fan","humidifier"].includes(r))return"on"===n?{...s,status:"working",activity:"running"}:s;if("media_player"===r)return"off"===n?{...s,availability:"unavailable"}:s;if("vacuum"===r)return"cleaning"===n?{...s,status:"working",activity:"running"}:"returning"===n?{...s,status:"working",activity:"transition"}:s;if("script"===r)return"on"===n?{...s,status:"working",activity:"running"}:s;if("automation"===r)return s;if("button"===r||"event"===r)return{...s,edge:"change"};const a=vh(i.attributes);return sh.has(a)||sh.has(n)&&!lh.has(n)?{...s,status:"working",activity:"running"}:s}function bh(e,t,i){const n=i.filter(t=>t.startsWith("switch.")&&!e?.entities?.[t]?.entity_category),r=t.find(t=>fh(e,t));if(!(n.length>1&&!!r))return t.map(t=>yh(e,t));const o=t.find(t=>t!==r&&gh(e,t)),s=yh(e,r);return"unavailable"===s.availability||"off"===s.state?t.map(t=>({eid:t,state:e?.states?.[t]?dh(e.states[t].state):"__missing__",availability:"unavailable",status:"neutral",activity:"none",edge:"none"})):t.map(t=>{if(t===o)return function(e,t){const i=e?.states?.[t],n=i?dh(i.state):"__missing__",r={eid:t,state:n,availability:hh(n)?"unavailable":"available",status:"neutral",activity:"none",edge:"none"};if("unavailable"===r.availability)return r;const o=vh(i?.attributes);return sh.has(o)||ah.has(n)&&!lh.has(n)?{...r,status:"working",activity:"running"}:r}(e,t);return{...t===r?s:yh(e,t),status:"neutral",activity:"none",edge:"none"}})}function wh(e){if(!e.length)return{availability:"available",status:"neutral",activity:"none"};const t=e.filter(e=>"available"===e.availability);if(!t.length)return{availability:"unavailable",status:"neutral",activity:"none"};if(t.some(e=>"alarm"===e.status))return eh;const i=t.some(e=>"working"===e.status)?"working":t.some(e=>"open"===e.status)?"open":"neutral",n=t.some(e=>"transition"===e.activity)?"transition":t.some(e=>"presence"===e.activity)?"presence":t.some(e=>"running"===e.activity)?"running":"none";return{availability:"available",status:i,activity:n}}function kh(e,t){if(!(e=>!!e&&!hh(e))(e)||"unavailable"===t.availability||e===t.state)return null;if("rising"===t.edge)return"off"===e&&"on"===t.state?"event":null;if("change"===t.edge)return"event";if("terminal_transition"===t.edge){const i=new Set([e,t.state]);if(i.has("closed")&&i.has("open")||i.has("locked")&&i.has("unlocked"))return"transition"}return null}const xh=(e,t=0)=>{const i=Number(e);return Number.isInteger(i)&&i>=0?i:t},Sh=(e,t)=>{const i={rev:0,configRev:xh(t),off:new Set};if(null==e)return{snapshot:i,valid:!1};const n=e.off;return!Number.isInteger(e.rev)||Number(e.rev)<0||!Number.isInteger(e.config_rev)||Number(e.config_rev)<0||!Array.isArray(n)||n.some(e=>"string"!=typeof e||!e)?{snapshot:i,valid:!1}:{snapshot:{rev:Number(e.rev),configRev:Number(e.config_rev),off:new Set(n)},valid:!0}};function $h(e,t=0){return Sh(e,t).snapshot}function Mh(e,t,i,n){const r=Sh(t,i);return n&&r.valid&&r.snapshot.configRev===i?e.configRev===i&&r.snapshot.rev{try{const[i,n]=await Promise.all([e.callWS({type:"config/device_registry/list"}),e.callWS({type:"config/entity_registry/list"})]),r=Eh(i,"id"),o=Eh(n,"entity_id");if(!r||!o)throw new Error("invalid_registry_response");t.devices=r,t.entities=o,t.authoritative=!0,t.access="full",t.lastSuccess=Date.now(),t.error=void 0}catch(e){t.authoritative=!1,t.access="limited",t.error=function(e){if(e&&"object"==typeof e){const t=e;return String(t.message||t.code||t.error||"registry_unavailable")}return String(e||"registry_unavailable")}(e)}finally{t.revision++,t.loading=void 0,function(e){for(const t of[...e.listeners])try{t()}catch{}}(t)}})()),t.loading}function Hh(e,t){void 0===t.reloadTimer&&(t.reloadTimer=globalThis.setTimeout(()=>{t.reloadTimer=void 0,Nh(e,t)},80))}async function Lh(e,t){if(t.subscribing||t.unsubDevice&&t.unsubEntity)return t.subscribing;const i=e?.connection?.subscribeEvents;return"function"==typeof i?(t.subscribing=(async()=>{try{t.unsubDevice||(t.unsubDevice=await i.call(e.connection,()=>Hh(e,t),"device_registry_updated")),t.unsubEntity||(t.unsubEntity=await i.call(e.connection,()=>Hh(e,t),"entity_registry_updated"))}catch{}finally{0===t.refs&&(t.unsubDevice?.(),t.unsubEntity?.(),t.unsubDevice=void 0,t.unsubEntity=void 0),t.subscribing=void 0}})(),t.subscribing):void 0}function Bh(e,t){const i=Oh(e);if(!i)return()=>{};const n=0===i.refs;i.refs++,i.listeners.add(t),("pending"===i.access||n)&&Nh(e,i),Lh(e,i);let r=!1;return()=>{r||(r=!0,i.listeners.delete(t),i.refs=Math.max(0,i.refs-1),i.refs>0||(i.unsubDevice?.(),i.unsubEntity?.(),i.unsubDevice=void 0,i.unsubEntity=void 0,void 0!==i.reloadTimer&&globalThis.clearTimeout(i.reloadTimer),i.reloadTimer=void 0))}}function qh(e){const t=Oh(e);t&&(Hh(e,t),Lh(e,t))}function jh(e){const t=Oh(e);if(!t)return{revision:0,authoritative:!1,access:"limited",devices:e?.devices||{},entities:e?.entities||{},lastSuccess:0,error:"registry_unavailable"};let i=e?.devices||{},n=e?.entities||{};if(t.authoritative){const r=t.liveDevices!==i||t.liveEntities!==n,o=void 0!==t.liveDevices||void 0!==t.liveEntities;if(r&&(t.liveDevices=i,t.liveEntities=n,t.projectedRevision=void 0,o&&Hh(e,t)),t.projectedRevision!==t.revision||!t.projectedDevices||!t.projectedEntities){const e={...t.devices},r={...t.entities};for(const[t,n]of Object.entries(i))Object.prototype.hasOwnProperty.call(e,t)||(e[t]=n);for(const[e,t]of Object.entries(n))Object.prototype.hasOwnProperty.call(r,e)||(r[e]=t);t.projectedDevices=e,t.projectedEntities=r,t.projectedRevision=t.revision}i=t.projectedDevices,n=t.projectedEntities}return{revision:t.revision,authoritative:t.authoritative,access:t.access,devices:i,entities:n,lastSuccess:t.lastSuccess,error:t.error}}function Wh(e){if(!e||"object"!=typeof e&&"function"!=typeof e)return 0;let t=Ph.get(e);return t||(t=Fh++,Ph.set(e,t)),t}function Uh(e,t=jh(e)){return[t.revision,t.access,Wh(t.devices),Wh(t.entities)].join(":")}function Vh(e){return!!e&&null==e.disabled_by}function Gh(e,t=jh(e)){const i={},n={},r={};for(const[e,n]of Object.entries(t.devices||{}))Vh(n)&&(i[e]=n);for(const[e,i]of Object.entries(t.entities||{})){if(!Vh(i))continue;const r=i.device_id?t.devices?.[i.device_id]:null;t.authoritative&&i.device_id&&!r||(r&&!Vh(r)||(n[e]=i))}for(const[i,n]of Object.entries(e?.states||{})){const e=t.entities?.[i];if(e&&!Vh(e))continue;const o=e?.device_id?t.devices?.[e.device_id]:null;t.authoritative&&e?.device_id&&!o||(o&&!Vh(o)||(r[i]=n))}return{...e,devices:i,entities:n,states:r}}function Kh(e,t=jh(e)){return{...e,devices:t.devices||{},entities:t.entities||{}}}function Yh(e,t){const i=[];for(const[n,r]of Object.entries(e||{}))r?.device_id===t&&i.push(n);return i}function Xh(){if(Ih)return Ih;if("undefined"==typeof localStorage)return{};try{const e=JSON.parse(localStorage.getItem(zh)||"{}");if(!e||"object"!=typeof e||Array.isArray(e))return{};const t=Date.now(),i={};for(const[n,r]of Object.entries(e))!r||"active"!==r.kind&&"ha_disabled"!==r.kind||!Number.isFinite(r.ts)||t-r.ts>7776e6||(i[n]=r);return Ih=i,Ih}catch{return{}}}function Zh(e,t,i=jh(e)){if(!t||"virtual"===t)return{kind:"active",enabledEntityIds:[],allEntityIds:[]};const n=t.indexOf(":");if(n<1)return{kind:"unverified",reason:"registry_unavailable",enabledEntityIds:[],allEntityIds:[]};const r=t.slice(0,n),o=t.slice(n+1);if("device"!==r&&"entity"!==r||!o)return{kind:"unverified",reason:"registry_unavailable",enabledEntityIds:[],allEntityIds:[]};const s=i.devices||{},a=i.entities||{};if(i.authoritative){if("device"===r){const e=s[o];if(!e)return{kind:"orphaned",reason:"device_missing",enabledEntityIds:[],allEntityIds:[]};const t=Yh(a,o);if(!Vh(e))return{kind:"ha_disabled",reason:"device",enabledEntityIds:[],allEntityIds:t};const i=t.filter(e=>Vh(a[e]));return t.length&&!i.length?{kind:"ha_disabled",reason:"all_entities",enabledEntityIds:[],allEntityIds:t}:{kind:"active",enabledEntityIds:i,allEntityIds:t}}const t=a[o];return t&&!Vh(t)?{kind:"ha_disabled",reason:"entity",enabledEntityIds:[],allEntityIds:[o]}:t?.device_id&&!s[t.device_id]?{kind:"orphaned",reason:"device_missing",enabledEntityIds:[],allEntityIds:[o]}:t?.device_id&&!Vh(s[t.device_id])?{kind:"ha_disabled",reason:"device",enabledEntityIds:[],allEntityIds:[o]}:t||e?.states?.[o]?{kind:"active",enabledEntityIds:[o],allEntityIds:[o]}:{kind:"orphaned",reason:"entity_missing",enabledEntityIds:[],allEntityIds:[]}}const l=function(e){return Xh()[e]||null}(t);if("device"===r){const t=s[o],i=Yh(a,o);if(null!=t?.disabled_by)return{kind:"ha_disabled",reason:"device",enabledEntityIds:[],allEntityIds:i};const n=i.filter(e=>{const t=a[e];return null==t?.disabled_by&&(!t.device_id||null==s[t.device_id]?.disabled_by)});if(i.length&&!n.length&&i.every(e=>null!=a[e]?.disabled_by))return{kind:"ha_disabled",reason:"all_entities",enabledEntityIds:[],allEntityIds:i};if("ha_disabled"===l?.kind)return{kind:"ha_disabled",reason:l.reason||"device",enabledEntityIds:[],allEntityIds:i};if(t||n.some(t=>!!e?.states?.[t]))return{kind:"active",enabledEntityIds:n,allEntityIds:i}}else{const t=a[o];if(null!=t?.disabled_by)return{kind:"ha_disabled",reason:"entity",enabledEntityIds:[],allEntityIds:[o]};if(t?.device_id&&null!=s[t.device_id]?.disabled_by)return{kind:"ha_disabled",reason:"device",enabledEntityIds:[],allEntityIds:[o]};if("ha_disabled"===l?.kind)return{kind:"ha_disabled",reason:l.reason||"entity",enabledEntityIds:[],allEntityIds:[o]};if(t||e?.states?.[o])return{kind:"active",enabledEntityIds:[o],allEntityIds:[o]}}return{kind:"unverified",reason:"registry_unavailable",enabledEntityIds:[],allEntityIds:[]}}function Jh(e){const t=jh(e);return{access:t.access,authoritative:t.authoritative,revision:t.revision,lastSuccess:t.lastSuccess,error:t.error}}function Qh(e){const t={};for(const[i,n]of Object.entries(e.entities)){if(!n?.device_id||!Vh(n))continue;const r=e.devices?.[n.device_id];r&&!Vh(r)||(t[n.device_id]=t[n.device_id]||[]).push(i)}return t}function ed(e,t){const i=new Map;for(const n of e){if(!0===n?.removed)continue;const e=n?.binding||"";if(!e.startsWith("entity:"))continue;const r=e.slice(7);if(!r)continue;const o=t?.entities?.[r]?.device_id;if(!o)continue;const s=i.get(o)||new Set;s.add(r),i.set(o,s)}return{byDevice:i}}function td(e,t,i,n){const r=n.byDevice.get(t);return r?.size?{partial:!0,entityIds:i.filter(t=>!r.has(t)&&!e?.entities?.[t]?.hidden)}:{partial:!1,entityIds:[...i]}}function id(e,t,i){if(t.identifiers?.[0]?.[0])return t.identifiers[0][0];for(const t of i){const i=e.entities[t]?.platform;if(i)return i}return""}function nd(e,t){if(/_device_temperature$/.test(t))return!1;if(e.entities?.[t]?.entity_category)return!1;const i=e.states[t];if(!i)return/_temperature$/.test(t);const n=i.attributes||{};return"temperature"===n.device_class||/°C|°F/.test(n.unit_of_measurement||"")||/_temperature$/.test(t)}const rd=["vacuum","lawn_mower","climate","media_player","light","cover","lock","valve","alarm_control_panel","water_heater","fan","humidifier","siren","camera","remote"],od=e=>[...e.filter(e=>!e.reg?.hidden),...e.filter(e=>!!e.reg?.hidden)];function sd(e,t){const i=t.map(t=>({eid:t,reg:e?.entities?.[t]})).filter(e=>!!e.reg);if(!i.length)return[];const n=i.filter(e=>!e.reg.entity_category),r=n.length?n:i;for(const e of rd){const t=r.filter(t=>t.eid.startsWith(e+"."));if(t.length)return od(t).map(e=>e.eid)}const o=r.filter(t=>function(e,t){if(!t.startsWith("binary_sensor."))return!1;const i=dh(e?.states?.[t]?.attributes?.device_class||e?.entities?.[t]?.device_class||e?.entities?.[t]?.original_device_class);return th.has(i)||ih.has(i)||nh.has(i)||rh.has(i)||"moving"===i||oh.has(i)}(e,t.eid));if(o.length)return od(o).map(e=>e.eid);const s=r.filter(e=>e.eid.startsWith("switch."));if(s.length){const t=od(s),n=t.find(t=>fh(e,t.eid));if(s.length>1&&n){const t=i.filter(t=>t.eid!==n.eid&&"config"!==t.reg?.entity_category&&null!=mh(e,t.eid)),r=t.filter(e=>!e.reg?.entity_category),o=r.length?r:t;for(const t of[0,1,2]){const i=od(o.filter(i=>mh(e,i.eid)===t));if(i.length)return[i[0].eid,n.eid]}}return[(n||t[0]).eid]}const a=[];for(const e of Le)a.push(...od(r.filter(t=>t.eid.startsWith(e+"."))));return a.push(...od(r.filter(e=>!Le.includes(e.eid.split(".")[0])))),a.map(e=>e.eid)}function ad(e,t,i){const n=t.map(t=>({eid:t,reg:e.entities[t],st:e.states[t]})).filter(e=>e.reg),r=[n.filter(e=>!e.reg.hidden&&!e.reg.entity_category),n.filter(e=>!e.reg.entity_category),n.filter(e=>!e.reg.hidden),n];if("mdi:thermometer"===i||"mdi:air-filter"===i)for(const t of r){const i=t.find(t=>nd(e,t.eid));if(i)return i.eid}const o=sd(e,t);return o.find(Rn)||o[0]}function ld(e,t,i=[]){return[...new Set(cd(e,t,i))].filter(e=>Rn(e))}function cd(e,t,i=[]){const n=e?.startsWith("entity:")?new Set([e.slice(7)]):new Set(i);return(t||[]).filter(e=>"string"==typeof e&&!n.has(e))}function hd(e,t){if("string"==typeof t)return e.area===t;const i=e.marker?.room_id;return i?!!t.id&&i===t.id:!!t.area&&e.area===t.area}function dd(e){const t=e.marker?.binding?.startsWith("entity:")?e.marker.binding.slice(7):null,i=e.entities.filter(Rn),n=e.primary&&Rn(e.primary)?e.primary:null;return[...new Set([t,n,...i].filter(e=>!!e&&Rn(e)))]}function ud(e){const t=dd(e),i=e.marker?.light_entity;return i&&t.includes(i)?i:t[0]||null}function pd(e,t){if(!1===t.marker?.is_light)return[];if(!0===t.marker?.is_light){return[{eid:ud(t),via:"forced"}]}const i=t.primary||sd(e,t.entities)[0];return i&&!i.startsWith("light.")?[]:t.entities.filter(t=>t.startsWith("light.")&&!!e.states?.[t]).map(e=>({eid:e,via:"light"}))}const _d=new WeakMap,md=new WeakMap;function gd(e){return e.map(e=>[e.id||"",!0===e.hidden?1:0,e.primary||"",[...e.entities].join(","),void 0===e.controls?"":[...e.controls].join(","),e.marker?.id||"",e.marker?.binding||"",e.marker?.is_light,e.marker?.tap_action||"",!0===e.marker?.removed?1:0,e.marker?.light_entity||"",null==e.marker?.controls?"":[...e.marker.controls].join(",")].join("")).join("")}function fd(e){const t=gd(e),i=_d.get(e);if(i?.fingerprint===t)return i;const n=e.filter(e=>!e.hidden),r=new Map,o=new Map;for(const t of e){o.set(t,cd(t.marker?.binding,t.marker?.controls??t.controls,t.entities));const e=t.hidden||!0!==t.marker?.is_light?null:t.marker?.id||t.id;e&&r.set(String(e),t)}const s=new Map;for(const t of e){const e=o.get(t)||[],i=new Set(void 0===t.controls?e.filter(Rn):t.controls.filter(Rn)),n=ud(t),a=i.size?[...i]:n?[n]:[];for(const i of e){if(!i.startsWith("marker:"))continue;const e=i.slice(7);if(!e||e===String(t.marker?.id||t.id||""))continue;if(!r.has(e))continue;const n=s.get(e)||{markerId:e,controllers:[],driverEids:[]};n.controllers.push({device:t,driverEids:[...a]}),n.driverEids=[...new Set([...n.driverEids,...a])],s.set(e,n)}}const a={fingerprint:t,visible:n,markerById:r,persistedByDevice:o,incomingByMarker:s};return _d.set(e,a),a}function vd(e){return fd(e).incomingByMarker}function yd(e,t){const i=ld(t.marker?.binding,t.controls??t.marker?.controls,t.entities),n=cd(t.marker?.binding,t.marker?.controls??t.controls,t.entities);return(null!=t.marker?.is_light||!i.length&&!n.some(e=>e.startsWith("marker:")))&&pd(e,t).length>0}function bd(e,t){return pd(e,t).some(e=>!!e.eid)}function wd(e,t,i,n){const r="always"===e||"auto"===e&&t,o=r&&!i;return{sourceExists:r,fromSourceEnabled:r&&i,manualEnabled:r,radiusEnabled:r,passive:o,effectiveMode:o&&"auto"===n?"fixed":n}}function kd(e,t){const i=ld(t.marker?.binding,t.controls??t.marker?.controls,t.entities).map(e=>({eid:e,via:"controls"})),n=yd(e,t)?pd(e,t):[];for(const e of n)e.eid&&i.some(t=>t.eid===e.eid)||i.push(e);return i}function xd(e,t,i,n){if(null!=i)return xd(e,t,null,n).filter(e=>hd(e.device,i));const r=gd(t),o=function(e,t){const i=new Set;for(const e of t){for(const t of e.entities)i.add(t);for(const t of e.controls||e.marker?.controls||[])"string"!=typeof t||t.startsWith("marker:")||i.add(t)}return[...i].sort().map(t=>`${t}:${e?.states?.[t]?.state??""}`).join("|")}(e,t),s=Rh(n),a=md.get(t);if(a?.graphFingerprint===r&&a.stateFingerprint===o&&a.virtualLightFingerprint===s&&a.registry===e?.entities)return a.sources;const{visible:l,markerById:c,persistedByDevice:h,incomingByMarker:d}=fd(t),u=null==i?l:l.filter(e=>hd(e,i)),p=new Map,_=new Map;for(const t of u){const i=kd(e,t).filter(e=>"controls"!==e.via);for(const n of i){const i=!0===t.marker?.is_light?String(t.marker?.id||t.id||""):"",r=i?`marker:${i}`:`entity:${n.eid}`,o=n.eid?[n.eid]:[],s={key:r,eid:n.eid||"",stateEids:o,serviceEids:o,device:t,via:n.via,castsGlow:!0,passive:!n.eid,on:!n.eid||"on"===e.states?.[n.eid]?.state};p.set(t,[...p.get(t)||[],s]),n.eid&&_.set(n.eid,s)}}const m=new Map;for(const e of t){const t=h.get(e)||[],i=new Set(void 0===e.controls?t.filter(Rn):e.controls);m.set(e,i)}for(const t of p.values())for(const i of t){if(!i.passive)continue;const t=i.key.slice(7),r=d.get(t);i.on=!r||r.driverEids.some(t=>"on"===e.states?.[t]?.state),!r&&Ch(i.device.marker)&&(i.on=Th(i.device.marker,n))}const g=new Map,f=e=>{const t=g.get(e.key);(!t||e.castsGlow&&!t.castsGlow)&&g.set(e.key,e)};for(const t of l){const n=h.get(t)||[],r=null==i||hd(t,i);for(const i of n){if(i.startsWith("marker:")){const e=c.get(i.slice(7)),t=e?p.get(e):null;if(t)for(const e of t)f(e);continue}if(!Rn(i)||!m.get(t)?.has(i))continue;const n=_.get(i);n?f(n):r&&f({key:`entity:${i}`,eid:i,stateEids:[i],serviceEids:[i],device:t,via:"controls",castsGlow:!1,passive:!1,on:"on"===e.states?.[i]?.state})}for(const e of p.get(t)||[])f(e)}const v=[...g.values()];return md.set(t,{graphFingerprint:r,stateFingerprint:o,virtualLightFingerprint:s,registry:e?.entities,sources:v}),v}function Sd(e){const t=e.filter(e=>e.castsGlow);return t.find(e=>e.on)||t[0]||null}function $d(e){return e.length?e.some(e=>e.on)?"on":"off":"none"}function Md(e,t){const i=[];for(const n of t){const t=e.states[n];if(!t)continue;const r=(t.attributes?.unit_of_measurement||"").toLowerCase();if(/_(linkquality|lqi)$/.test(n)||"lqi"===r){const e=parseFloat(t.state);isNaN(e)||i.push(e);continue}const o=t.attributes?.linkquality??t.attributes?.lqi;if(null!=o){const e=parseFloat(o);isNaN(e)||i.push(e)}}return Pi(i)}function Rd(e,t){for(const i of t){if(!nd(e,i))continue;const t=e.states[i];if(!t)continue;const n=parseFloat(t.state);if(!isNaN(n))return Math.round(10*n)/10}return null}function Cd(e,t){for(const i of t){if(!i.startsWith("climate."))continue;const t=e.states[i];if(!t||"unavailable"===t.state||"unknown"===t.state)continue;const n=parseFloat(t.attributes?.current_temperature);if(Number.isFinite(n))return Math.round(10*n)/10}return null}function Td(e,t){if(e.entities?.[t]?.entity_category)return!1;const i=e.states[t];if(!i)return/_humidity$/.test(t);const n=i.attributes||{};return"humidity"===n.device_class||"%"===n.unit_of_measurement&&/_humidity$/.test(t)||/_humidity$/.test(t)}function Dd(e,t){for(const i of t){if(!Td(e,i))continue;const t=e.states[i];if(!t)continue;const n=parseFloat(t.state);if(!isNaN(n))return Math.round(n)}return null}function Ad(e,t){if(!t)return[];const i=[];for(const[t,n]of Object.entries(e.entities)){if(!t.startsWith("light.")||n.hidden||!Vh(n))continue;let r=null;if("group"===n.platform)r=n.area_id||null;else{if(!n.device_id)continue;{const t=e.devices[n.device_id];if(!Vh(t))continue;if("Group"!==t?.model)continue;r=t.area_id||n.area_id||null}}if(!r)continue;const o=e.states[t];i.push({eid:t,name:n.name||o?.attributes?.friendly_name||t,area:r})}return i}function Pd(e,t,i,n,r){const o=He(t,i,r);if(o!==Ne)return o;const s=[];for(const t of n){const i=e.states[t]?.attributes?.device_class;i&&s.push(i)}return function(e){for(const t of e){const e=Ee[t];if(e)return e}return null}(s)??Ne}function Fd(e,t){return e.map(e=>{if(!Array.isArray(e.controls))return e;const i=e.controls.filter(e=>!("string"==typeof e&&e.startsWith("marker:")&&t.has(e.slice(7))));return i.length===e.controls.length?e:{...e,controls:i.length?i:null}})}function zd(e,t,i){if(!t||!i||t===i)return[...e];const n=`marker:${t}`,r=`marker:${i}`;return e.map(e=>{const t=Array.isArray(e.controls)?e.controls.map(e=>e===n?r:e):e.controls,i="derived_marker_state"===e.value_badge?.source?.kind&&e.value_badge.source.ref===n?{...e.value_badge,source:{...e.value_badge.source,ref:r}}:e.value_badge,o="derived_marker_state"===e.value_source?.kind&&e.value_source.ref===n?{...e.value_source,ref:r}:e.value_source;return t===e.controls&&i===e.value_badge&&o===e.value_source?e:{...e,controls:t,...void 0!==i?{value_badge:i}:{},...void 0!==o?{value_source:o}:{}}})}function Id(e,t,i){if(!t||t===i)return!0;const n=new Map;for(const t of e)n.set(t.id,(t.controls||[]).filter(e=>"string"==typeof e&&e.startsWith("marker:")).map(e=>e.slice(7)));const r=new Set,o=[i];for(;o.length;){const e=o.pop();if(e===t)return!0;r.has(e)||(r.add(e),o.push(...n.get(e)||[]))}return!1}function Od(e,t,i,n){const r=new Set([t]),o=e.filter(e=>{const o=e.id===t||!n&&e.binding===i;return o&&r.add(e.id),!o});return{markers:n?o:[...o,{id:t,binding:i,removed:!0,hidden:!0}],cleanupIds:r}}function Ed(e){const t=new Set,i=new Set,n=new Set;for(const r of e||[]){const e=String(r.binding||"").indexOf(":");if(e<1)continue;const o=r.binding.slice(0,e),s=r.binding.slice(e+1);s&&(!0===r?.removed?"device"===o?t.add(s):"entity"===o&&i.add(s):"entity"===o&&n.add(s))}return{devices:t,entities:i,liveEntities:n}}function Nd(e,t,i){if(i.liveEntities.has(t))return!1;if(i.entities.has(t))return!0;const n=e?.entities?.[t]?.device_id;return!!n&&i.devices.has(n)}function Hd(e,t,i,n,r){const o=ld(t.binding,t.controls,e.entities).filter(e=>!Nd(i,e,n)).filter(e=>"active"===Zh(i,"entity:"+e,r).kind);e.marker=t,e.controls=o,e.userHidden=!0===t.hidden,e.hidden=e.userHidden||"ha_disabled"===e.bindingStatus?.kind,t.name&&(e.name=t.name),t.icon&&(e.icon=t.icon),null!=t.model&&(e.model=t.model),e.link=t.link??null,e.description=t.description??null,e.pdfs=t.pdfs||[],e.tapAction=t.tap_action??null}function Ld(e){const t=e.hass,i=e.registry||jh(t),n=Gh(t,i),r=Kh(t,i),{areaToSpace:o,markers:s,settings:a,excluded:l,iconRules:c}=e,h=!1!==a.group_lights,d=Ed(s),u=Ad(n,h).filter(e=>!Nd(n,e.eid,d)),p=new Set(u.map(e=>e.area)),_=Qh(n),m=ed(s,r),g=new Set(s.map(e=>e.binding)),f=[];for(const e of Object.values(n.devices)){const r=e.area_id;if(!r||!o[r])continue;if("service"===e.entry_type)continue;if(g.has("device:"+e.id))continue;if("active"!==Zh(t,"device:"+e.id,i).kind)continue;const s=td(n,e.id,_[e.id]||[],m);if(s.partial&&!s.entityIds.length)continue;const a=s.entityIds,d=id(n,e,a);let u=l.has(d)||"Group"===e.model||/scene/i.test(e.model||"")||/bridge/i.test((e.model||"")+(e.name||""))||"myheat"===d&&!!e.via_device_id;if(!u&&h&&p.has(r)){const t=(e.name_by_user||e.name||"").trim();"mdi:lightbulb"===Pd(n,t,e.model,a,c)&&(u=!0)}u&&f.push("device:"+e.id)}return f}function Bd(e,t,i,n){if("string"==typeof e.room_id&&e.room_id.length>0&&null===e.area)return{area:"",space:e.space||n};const r=e.area||t||"";return{area:r,space:r&&i[r]||e.space||n}}function qd(e){const t=e.hass,i=e.registry||jh(t),n=Gh(t,i),r=Kh(t,i),{areaToSpace:o,markers:s,settings:a,excluded:l,showAll:c,firstSpaceId:h,loc:d,iconRules:u}=e,p=!1!==a.group_lights,_=Ed(s),m=Ad(n,p).filter(e=>!Nd(n,e.eid,_)),g=new Set(m.map(e=>e.area)),f=Qh(n),v=function(e){const t={};for(const[i,n]of Object.entries(e.entities||{}))n?.device_id&&(t[n.device_id]=t[n.device_id]||[]).push(i);return t}(r),y=ed(s,r),b=new Set;for(const e of s){const[t,i]=e.binding.split(":");"device"!==t&&"entity"!==t||!i||b.add(e.binding)}const w=(e,t)=>s.find(i=>i.binding===e+":"+t),k={},x=[];for(const e of Object.values(n.devices)){const r=e.area_id;if(!r||!o[r])continue;if("service"===e.entry_type)continue;if(b.has("device:"+e.id))continue;const s=Zh(t,"device:"+e.id,i);if("active"!==s.kind)continue;const h=w("device",e.id);if(h&&h.hidden&&!a.filter_seeded)continue;const _=td(n,e.id,f[e.id]||[],y);if(_.partial&&!_.entityIds.length)continue;const m=_.entityIds,v=_.partial?{kind:"active",enabledEntityIds:m,allEntityIds:m}:s,S=id(n,e,m),$=!a.filter_seeded;if($&&!c){if(l.has(S))continue;if("Group"===e.model)continue;if(/scene/i.test(e.model||""))continue;if(/bridge/i.test((e.model||"")+(e.name||"")))continue;if("myheat"===S&&e.via_device_id)continue}const M=(e.name_by_user||e.name||d("device.unnamed")).trim(),R=M+"|"+r;let C=Pd(n,M,e.model,m,u);if(m.some(e=>e.startsWith("lock."))&&(C="mdi:lock"),$&&!c&&p&&"mdi:lightbulb"===C&&g.has(r))continue;k[R]=(k[R]||0)+1;const T=k[R]>1?M+" "+k[R]:M,D={id:e.id,name:T,model:e.model||"",area:r,space:o[r],icon:C,entities:m,allEntities:v.allEntityIds,bindingStatus:v,bindingKind:"device",bindingRef:e.id,pdfs:[]};D.primary=ad(n,m,C),"mdi:thermometer"!==C&&"mdi:air-filter"!==C||(D.temp=Rd(n,m)),D.primary&&Td(n,D.primary)&&(D.hum=Dd(n,m)),x.push(D)}for(const e of m)o[e.area]&&(b.has("entity:"+e.eid)||x.push({id:"lg_"+e.eid,name:e.name,model:d("device.light_group"),area:e.area,space:o[e.area],icon:"mdi:lightbulb-group",entities:[e.eid],allEntities:[e.eid],bindingStatus:{kind:"active",enabledEntityIds:[e.eid],allEntityIds:[e.eid]},primary:e.eid,bindingKind:"entity",bindingRef:e.eid,pdfs:[]}));for(const e of s){if(e.removed)continue;const[s,l]=e.binding.split(":"),c="device"===s||"entity"===s?Zh(t,e.binding,i):null;if(!e.hidden||a.filter_seeded||"ha_disabled"===c?.kind)if("device"===s){const t=c;if("unverified"===t.kind)continue;const s=r.devices[l],{area:a,space:p}=Bd(e,s?.area_id,o,h),m="active"===t.kind?t.enabledEntityIds:[];let g=s?Pd(n,s.name_by_user||s.name||"",s.model,m,u):"mdi:help-circle";m.some(e=>e.startsWith("lock."))&&(g="mdi:lock");const f={id:e.id,name:s?.name_by_user||s?.name||d("device.fallback"),model:s?.model||"",area:a,space:p,icon:g,entities:m,allEntities:t.allEntityIds.length?t.allEntityIds:s&&v[s.id]||[],bindingStatus:t,bindingKind:"device",bindingRef:l};f.primary=ad(n,m,g),"mdi:thermometer"!==g&&"mdi:air-filter"!==g||(f.temp=Rd(n,m)),f.primary&&Td(n,f.primary)&&(f.hum=Dd(n,m)),Hd(f,e,r,_,i),x.push(f)}else if("entity"===s){if(Nd(r,l,_))continue;const t=c;if("unverified"===t.kind)continue;const s=r.entities[l],a=s?.area_id||s?.device_id&&r.devices[s.device_id]?.area_id||"",{area:d,space:p}=Bd(e,a,o,h),m=n.states[l],g=s?.name||m?.attributes?.friendly_name||l;let f=Pd(n,g,"",[l],u);l.startsWith("lock.")&&(f="mdi:lock");const v={id:e.id,name:g,model:"",area:d,space:p,icon:f,entities:"active"===t.kind?[l]:[],allEntities:[l],bindingStatus:t,primary:"active"===t.kind?l:void 0,bindingKind:"entity",bindingRef:l};"mdi:thermometer"!==f&&"mdi:air-filter"!==f||!v.entities.length||(v.temp=Rd(n,v.entities)),v.entities.length&&Td(n,l)&&(v.hum=Dd(n,v.entities)),Hd(v,e,r,_,i),x.push(v)}else{const t=e.area||"",n=e.space||t&&o[t]||h,s={id:e.id,name:e.name||d("device.virtual"),model:e.model||"",area:t,space:n,icon:e.icon||"mdi:map-marker",entities:[],allEntities:[],bindingStatus:{kind:"active",enabledEntityIds:[],allEntityIds:[]},bindingKind:"virtual",virtual:!0};Hd(s,e,r,_,i),x.push(s)}}return x}function jd(e){const{marker:t,siblingMarkers:i=[],...n}=e;return qd({...n,markers:[...i.filter(e=>e.id!==t.id),t]}).find(e=>e.id===t.id)||null}function Wd(e,t,i,n){if(!t)return null;if(function(e,t,i){if(!t)return!1;const n=t.indexOf(":");if(n<1)return!1;const r=t.slice(0,n),o=t.slice(n+1),s=Ed(i);return"device"===r?s.devices.has(o):"entity"===r&&Nd(e,o,s)}(e,t,n))return null;const r=t.indexOf(":");if(r<0)return null;const o=t.slice(0,r),s=t.slice(r+1);if(!s)return null;if("entity"===o){const t=parseFloat(e.states[s]?.state);return Number.isFinite(t)?"temp"===i?Math.round(10*t)/10:Math.round(t):null}if("device"===o){const t=Object.entries(e.entities).filter(([,e])=>e.device_id===s).map(([e])=>e);return"temp"===i?Rd(e,t):Dd(e,t)}return null}const Ud=new RegExp(["water","voda","coolant","flow_?temp","return_?temp","target","setpoint","chip","cpu","processor","board","core_temp","device_temp","batter","akkum","freezer","fridge","oven","kettle","boiler"].join("|"),"i");function Vd(e,t){return t.area?t.area:e&&t.id?`@room/${encodeURIComponent(e)}/${encodeURIComponent(t.id)}`:null}function Gd(e){return null==e.area&&e.space&&e.room_id?Vd(e.space,{id:e.room_id,area:null}):e.area||null}function Kd(e){const t=e?.exclude_integrations;return t?new Set(t):Pe}function Yd(e,t,i,n=Pe){const r=new Map;if(!e?.entities)return r;const o=Ed(i),s=new Set,a=new Map,l=new Map;for(const e of i||[]){if(e?.removed)continue;const t=(e.binding||"").indexOf(":");if(t<=0)continue;const i=e.binding.slice(0,t),n=e.binding.slice(t+1);if(!n)continue;!0===e.use_climate_temp&&s.add(n);const r=Gd(e);r&&("entity"!==i||a.has(n)?"device"!==i||l.has(n)||l.set(n,r):a.set(n,r))}const c=new Map;for(const[t,i]of Object.entries(e.entities)){if(i.device_id&&o.devices.has(i.device_id)&&!o.liveEntities.has(t)||!i.device_id&&o.entities.has(t)&&!o.liveEntities.has(t))continue;const r=i.device_id?e.devices?.[i.device_id]:null;if(!Vh(i)||r&&!Vh(r))continue;const h=a.get(t)||(i.device_id?l.get(i.device_id):null)||i.area_id||r?.area_id||null;if(!h)continue;if(i.entity_category)continue;if(!(s.size>0&&t.startsWith("climate.")&&(s.has(t)||i.device_id&&s.has(i.device_id)))){if(n.has(i.platform))continue;if(Ud.test(t))continue}let d=c.get(h);d||(d=new Map,c.set(h,d));const u=i.device_id||t;let p=d.get(u);if(!p){const n=e.states?.[t];p={name:(r?r.name_by_user||r.name:i.name||n?.attributes?.friendly_name||t)||t,model:r?.model,ents:[]},d.set(u,p)}p.ents.push(t)}for(const[i,n]of c){const o=[],a=[];for(const[i,r]of n){const n=Pd(e,r.name,r.model,r.ents,t),l="mdi:thermometer"===n||"mdi:air-filter"===n;if(l){const t=Rd(e,r.ents);null!=t&&o.push(t)}if(s.size>0&&(s.has(i)||r.ents.some(e=>s.has(e)))){const t=Cd(e,r.ents);null!=t&&o.push(t)}if(l||"mdi:water-percent"===n){const t=Dd(e,r.ents);null!=t&&a.push(t)}}(o.length||a.length)&&r.set(i,{temp:o.length?Math.round(o.reduce((e,t)=>e+t,0)/o.length*10)/10:null,hum:a.length?Math.round(a.reduce((e,t)=>e+t,0)/a.length):null})}return r}function Xd(e,t,i){const n=[];for(const r of t){if(r.area!==i||r.virtual)continue;const t=Md(e,r.entities);null!=t&&n.push(t)}return Pi(n)}const Zd={offStates:["off"],unknownUsesToggle:!0},Jd={light:Zd,switch:Zd,fan:Zd,humidifier:Zd,input_boolean:Zd,automation:Zd,remote:Zd,group:Zd,climate:{...Zd,featureMasks:{turn_on:256,turn_off:128,toggle:384}},media_player:{...Zd,featureMasks:{turn_on:128,turn_off:256,toggle:384}},siren:{...Zd,featureMasks:{turn_on:1,turn_off:2,toggle:3}},vacuum:{...Zd,featureMasks:{turn_on:1,turn_off:2,toggle:3}},water_heater:{...Zd,featureMasks:{turn_on:8,turn_off:8,toggle:8}},camera:{...Zd,featureMasks:{turn_on:1,turn_off:1,toggle:1}}};function Qd(e){return e.slice(0,e.indexOf("."))}function eu(e,t,i){if(!e?.services||"object"!=typeof e.services)return!1;const n=e.services?.[t];return!!n&&Object.prototype.hasOwnProperty.call(n,i)}function tu(e,t,i){return eu(e,t,i)?{domain:t,service:i}:eu(e,"homeassistant",i)?{domain:"homeassistant",service:i}:null}function iu(e,t){return e?.entities?.[t]||null}function nu(e,t,i){const n=e?.states?.[i],r=iu(t,i);return n?.attributes?.friendly_name||r?.name||r?.original_name||i}function ru(e,t){const i=iu(e,t);if(null!=i?.disabled_by)return!0;const n=i?.device_id?e?.devices?.[i.device_id]:null;return null!=n?.disabled_by}function ou(e,t){const i=e?.attributes?.supported_features;if(null==i||""===i)return!1;const n=Number(i);return Number.isFinite(n)&&(n&t)===t}function su(e,t,i){const n=Qd(i);if("lock"===n||"alarm_control_panel"===n)return!0;if("cover"!==n)return!1;const r=e?.states?.[i],o=iu(t,i),s=String(r?.attributes?.device_class||o?.device_class||o?.original_device_class||"");return Bi.has(s)}function au(e,t,i,n,r){return{ref:i,entityId:n,name:n?nu(e,t,n):null,reason:r}}function lu(e,t,i,n,r,o=null){return{target:null,skipped:au(e,t,i,n,r),semantics:o,nextEffect:null,command:null}}function cu(e,t,i,n,r=i){const o=Qd(i);if("cover"!==o&&"valve"!==o)return function(e,t,i,n,r=i){const o=Qd(i),s=e?.states?.[i];if(ru(t,i))return lu(e,t,r,i,"ha-disabled","power");if(su(e,t,i))return lu(e,t,r,i,"secure");if(!s)return lu(e,t,r,i,"missing","power");if("unavailable"===s.state)return lu(e,t,r,i,"unavailable","power");const a=Jd[o];if(!a)return lu(e,t,r,i,"unsupported");let l,c;if("unknown"===s.state||""===s.state){if(!a.unknownUsesToggle)return lu(e,t,r,i,"unsupported","power");l="toggle",c="toggle"}else a.offStates.includes(String(s.state))?(l="turn-on",c="turn_on"):(l="turn-off",c="turn_off");const h=a.featureMasks?.[c];if(h&&!ou(s,h))return lu(e,t,r,i,"unsupported","power");const d=tu(e,o,c);return d?{target:{entityId:i,name:nu(e,t,i),state:String(s.state||""),via:n},skipped:null,semantics:"power",nextEffect:l,command:{...d,data:{entity_id:i}}}:lu(e,t,r,i,"unsupported","power")}(e,t,i,n,r);if(ru(t,i))return lu(e,t,r,i,"ha-disabled",o);if(su(e,t,i))return lu(e,t,r,i,"secure",o);const s=e?.states?.[i];if(!s)return lu(e,t,r,i,"missing",o);if("unavailable"===s.state)return lu(e,t,r,i,"unavailable",o);const a=function(e,t,i){const n=String(i?.state||""),r="closed"===n?{service:`open_${t}`,effect:"open",feature:1}:"open"===n?{service:`close_${t}`,effect:"close",feature:2}:"opening"===n||"closing"===n?{service:`stop_${t}`,effect:"stop",feature:8}:null;return r&&ou(i,r.feature)&&eu(e,t,r.service)?r:ou(i,3)&&eu(e,t,"toggle")?{service:"toggle",effect:"toggle"}:null}(e,o,s);if(!a)return lu(e,t,r,i,"unsupported",o);return{target:{entityId:i,name:nu(e,t,i),state:String(s.state||""),via:n},skipped:null,semantics:o,nextEffect:a.effect,command:{domain:o,service:a.service,data:{entity_id:i}}}}function hu(e){return"entity"===e.bindingKind?e.bindingRef&&Rn(e.bindingRef)?[e.bindingRef]:[]:"virtual"===e.bindingKind?[]:dd(e)}function du(e){const t=e.marker?.toggle_entity;return t&&hu(e).includes(t)?t:null}function uu(e,t,i){const n=function(e,t){if("entity"===e.bindingKind&&e.bindingRef){const t=e.marker?.light_entity?ud(e):null;return[...new Set([t,e.bindingRef].filter(e=>!!e))]}const i=e.entities.length?e.entities:e.allEntities||[],n=e.marker?.light_entity||e.primary&&Rn(e.primary)?ud(e):null;return[...new Set([n,...sd(t,i)].filter(e=>!!e))]}(i,t);if(!n.length)return null;const r="entity"===i.bindingKind?"binding":"device-role";if("binding"===r)return cu(e,t,n[0],r);let o=null,s=null;for(const i of n){const n=cu(e,t,i,r);if(n.command)return n;const a=n.skipped?.reason;if("missing"===a||"unavailable"===a||"secure"===a)return n;"ha-disabled"!==a?o||=n:s||=n}return o||s}function pu(e){const t=e.skipped?.reason;return"missing"===t?"unavailable":t||"unsupported"}function _u(e,t){return{origin:e,kind:"none",semantics:null,targets:[],skippedTargets:[],noneReason:t,nextEffect:null,command:null}}function mu(e,t){return"cover"===e||"toggle"===e?"toggle":"more-info"===e||"run"===e||"info"===e||"none"===e?e:(null==e||""===e)&&"light"===t?"toggle":"info"}function gu(e,t){return{origin:e,kind:"single",semantics:t.semantics,targets:t.target?[t.target]:[],skippedTargets:t.skipped?[t.skipped]:[],noneReason:t.command?null:pu(t),nextEffect:t.nextEffect,command:t.command}}function fu(e,t,i,n=[]){const r=new Map,o=[],s=new Set,a=e=>{const t=`${e.ref}\n${e.entityId||""}\n${e.reason}`;s.has(t)||(s.add(t),o.push(e))};for(const e of n)a(e);for(const n of i){const i=cu(e,t,n.entityId,n.via,n.ref);i.target?r.set(n.entityId,r.get(n.entityId)||i.target):i.skipped&&a(i.skipped)}const l=[...r.values()];if(!l.length)return{origin:"explicit-toggle",kind:"group",semantics:"group-power",targets:l,skippedTargets:o,noneReason:o.length&&o.every(e=>"secure"===e.reason)?"secure":"configured-targets-missing",nextEffect:null,command:null};const c=l.some(e=>"on"===e.state)?"turn_off":"turn_on",h=tu(e,"homeassistant",c);return h?{origin:"explicit-toggle",kind:"group",semantics:"group-power",targets:l,skippedTargets:o,noneReason:null,nextEffect:"turn_on"===c?"turn-on":"turn-off",command:{...h,data:{entity_id:l.map(e=>e.entityId)}}}:{origin:"explicit-toggle",kind:"group",semantics:"group-power",targets:[],skippedTargets:[...o,...l.map(i=>au(e,t,i.entityId,i.entityId,"unsupported"))],noneReason:"unsupported",nextEffect:null,command:null}}function vu(e){return String(e.marker?.id||e.id||"")}function yu(e){const{hass:t,device:i}=e,n=e.registryHass||t,r=function(e){return"toggle"===e.tapAction?"explicit-toggle":"cover"===e.tapAction?"legacy-cover":!e.tapAction&&e.primary?.startsWith("light.")?"default-light":null}(i);if(!r)return null;const o=i.marker;if("explicit-toggle"===r&&Ch(o)){const t=String(o?.id||i.id||""),n=vd(e.devices).get(t);if(n)return function(e,t){const i=e.registryHass||e.hass;return fu(e.hass,i,t.driverEids.map(e=>({entityId:e,via:"control-marker-driver",ref:`marker:${t.markerId}`})))}(e,n);const s=Th(o,e.virtualLights);return{origin:r,kind:"single",semantics:"power",targets:[{entityId:"",name:i.name,state:s?"on":"off",via:"virtual-light"}],skippedTargets:[],noneReason:null,nextEffect:s?"turn-off":"turn-on",command:null,operation:{kind:"virtual-light",markerId:o.id}}}if("explicit-toggle"===r){if(cd(i.marker?.binding,i.marker?.controls??i.controls,i.entities).length)return function(e,t=null){const{hass:i,device:n,devices:r}=e,o=e.registryHass||i,s=cd(n.marker?.binding,n.marker?.controls??n.controls,n.entities),a=e.lightSources||xd(i,r,null,e.virtualLights),l=new Map;for(const e of a){if(!e.key.startsWith("marker:"))continue;const t=l.get(e.key)||[];t.push(e),l.set(e.key,t)}const c=vd(r),h=new Map;for(const e of r){const t=String(e.marker?.id||e.id||"");t&&h.set(t,e)}const d=[],u=[];t&&d.push({entityId:t,via:"entity"===n.bindingKind?"binding":"device-role",ref:t});for(const e of s){if(!e.startsWith("marker:")){Rn(e)?d.push({entityId:e,via:"control-entity",ref:e}):u.push(au(i,o,e,e.includes(".")?e:null,"unsupported"));continue}const t=l.get(e)||[];if(!t.length){const t=h.get(e.slice(7));if("ha_disabled"===t?.bindingStatus?.kind){const n=t.bindingStatus.allEntityIds[0]||null;u.push({ref:e,entityId:n,name:t.name||(n?nu(i,o,n):null),reason:"ha-disabled"})}else u.push(au(i,o,e,null,"missing"));continue}const r=[...new Set(t.flatMap(e=>e.serviceEids))];if(r.length){for(const t of r)d.push({entityId:t,via:"control-entity",ref:e});continue}const s=t.some(e=>e.passive),a=e.slice(7),p=vu(n),_=c.get(a)?.controllers.find(e=>vu(e.device)===p);if(s&&_?.driverEids.length)for(const t of _.driverEids)d.push({entityId:t,via:"control-marker-driver",ref:e});else u.push(au(i,o,e,null,s?"missing":"unsupported"))}return fu(i,o,d,u)}(e,du(i))}if("legacy-cover"===r){const e=i.entities.find(e=>e.startsWith("cover."))||i.allEntities?.find(e=>e.startsWith("cover."));return e?gu(r,cu(t,n,e,"device-role")):_u(r,"no-actionable-entity")}const s=du(i),a=s?cu(t,n,s,"entity"===i.bindingKind?"binding":"device-role"):uu(t,n,i);return a?gu(r,a):_u(r,i.virtual||"virtual"===i.bindingKind?"no-actionable-entity":"no-binding")}function bu(e){if(!e)return[];const t=Array.isArray(e.data.entity_id)?e.data.entity_id:[e.data.entity_id];return[...new Set(t)].sort()}function wu(e){return e?e.operation?e.operation:e.command?{kind:"ha-service",command:e.command}:null:null}const ku=new Set(["missing","ha-disabled","unavailable"]);function xu(e,t){const i=wu(e),n=wu(t);return!(!i||!n||i.kind!==n.kind)&&("virtual-light"===i.kind&&"virtual-light"===n.kind?i.markerId===n.markerId:"ha-service"===i.kind&&"ha-service"===n.kind&&function(e,t){const i=bu(e),n=bu(t);return i.length===n.length&&i.every((e,t)=>e===n[t])}(i.command,n.command))}function Su(e,t){const i=e.targets[0]||e.skippedTargets[0],n=[];return"group"===e.kind?e.targets.length&&n.push(t.group(e.targets)):i&&n.push(t.single(i)),e.nextEffect&&e.targets.length&&n.push("group"===e.kind?t.groupCurrentNext(e.targets,e.nextEffect):t.currentNext(e.targets[0],e.nextEffect)),e.skippedTargets.length&&n.push(t.skipped(e.skippedTargets)),!e.command&&e.noneReason&&n.push(t.none(e.noneReason)),n}function $u(e,t){return e.catch(()=>{}).then(t)}const Mu=e=>{const t=e?.config;return t&&Array.isArray(t.spaces)?t:null},Ru=(e,t)=>"number"==typeof e&&Number.isFinite(e)?e:t;class Cu{constructor(e){this.onBodyReplaced=e,this.config=null,this.configRev=0,this.configFingerprint="",this.layout={},this.layoutRev=0,this.layoutFingerprint=""}setConfig(e){const t=this.config;e!==t&&(this.config=e,this.onBodyReplaced?.("_serverCfg",t))}setLayout(e){const t=this.layout;e!==t&&(this.layout=e,this.onBodyReplaced?.("_layout",t))}currentConfigFingerprint(){return this.configFingerprint||rc(this.config)}currentLayoutFingerprint(){return this.layoutFingerprint||rc(this.layout)}adoptResponses(e,t,i,n){const r=Mu(e),o=rc(r),s=o!==this.currentConfigFingerprint();s&&(i(),this.setConfig(r),this.configFingerprint=o),this.configRev=e?.rev??this.configRev;let a=!1;if(void 0!==t){const e=t?.layout??{},i=rc(e);a=i!==this.currentLayoutFingerprint(),a&&(n(),this.setLayout(e),this.layoutFingerprint=i),this.layoutRev=t?.rev??this.layoutRev}return{configChanged:s,layoutChanged:a}}adoptMergedLayout(e,t,i){const n=rc(e),r=n!==rc(this.layout);return r&&(i?.(),this.setLayout(e)),this.layoutFingerprint=n,this.layoutRev=t?.rev??this.layoutRev,r}stageConfigCandidate(e){const t=rc(e);t!==rc(this.config)&&this.setConfig(e),this.configFingerprint=t}acceptConfigWrite(e,t){this.configFingerprint=rc(e),this.configRev=Ru(t?.rev,this.configRev+1)}acceptPairWrite(e,t,i){this.setConfig(e),this.configFingerprint=rc(e),this.setLayout(t),this.layoutFingerprint=rc(t),this.configRev=Ru(i?.config_rev,this.configRev+1),this.layoutRev=Ru(i?.layout_rev,this.layoutRev+1)}noteLayoutRevision(e){"number"==typeof e&&e>this.layoutRev&&(this.layoutRev=e)}stageLocalConfig(e){this.setConfig(e)}stageLocalLayout(e){this.setLayout(e)}seedIdentity(e){Object.assign(this,e)}refreshConfigFingerprint(){this.configFingerprint=rc(this.config)}refreshLayoutFingerprint(){this.layoutFingerprint=rc(this.layout)}beginOptimistic(e,t){return function(e,t,i,n,r){return{previous:JSON.parse(JSON.stringify(e)),previousFingerprint:i,revision:n,attempted:t,attemptedFingerprint:r(t)}}(e,t,this.configFingerprint,this.configRev,rc)}rollbackOptimistic(e){const t=this.config;return!(!t||this.configRev!==e.revision||rc(t)!==e.attemptedFingerprint)&&(this.setConfig(e.previous),this.configFingerprint=e.previousFingerprint,!0)}restoreCached(e){const t=e?.config;return!(!t||!Array.isArray(t.spaces))&&(this.setConfig(t),this.configRev=e?.rev||0,this.configFingerprint=e?.config_fingerprint||rc(t),this.setLayout(e?.layout||{}),this.layoutRev=e?.layout_rev||0,this.layoutFingerprint=e?.layout_fingerprint||rc(this.layout),!0)}snapshot(e){return this.config?(this.refreshConfigFingerprint(),this.refreshLayoutFingerprint(),{config:this.config,rev:this.configRev,config_fingerprint:this.configFingerprint,layout:this.layout,layout_rev:this.layoutRev,layout_fingerprint:this.layoutFingerprint,virtual_lights:e}):null}}async function Tu(e,t){const{cfgResp:i,layResp:n}=t,r=e._adoption,o=Mu(i),s=null!=i&&rc(o)!==r.currentConfigFingerprint()||null!=n&&rc(n.layout??{})!==r.currentLayoutFingerprint();if(s){if(!await e._signer.prepareImage(e.hass,e._candidateBackdrop(o)))return e._continuity.note("asset-failed"),e._scheduleLoadRetry(!0),{status:"asset-wait"}}s&&e._continuity.hasCompleteFrame&&"steady"===e._continuity.state&&e._beginContinuityCandidate(t.reason,!0),t.beforeAdopt?.();const a=e._space;return function(e,t,i){const n=e._adoption,r=!!n.config,{configChanged:o,layoutChanged:s}=n.adoptResponses(t??{},i,()=>{e._geometryHistory.clear(),e._devicePositionHistory.clear(),e._cancelDeviceDrag(),e._pendingPhysicalWrites.clear(),e._clearRoomFocus(!0),e._cancelCameraTransition(!1),r&&e._clearGeometryGesture()},()=>{e._cancelCameraTransition(!1),e._devicePositionHistory.clear(),e._cancelDeviceDrag()});if(o&&e._seedDecorStyle(n.config),t&&("virtual_lights"in t||"config"in t)){const i=Mh(e._virtualLights,t.virtual_lights,n.configRev,"virtual_lights"in t);Rh(i)!==Rh(e._virtualLights)&&(e._virtualLights=i,e._capturedSnapshotVirtual="")}e._canOptimizeUndo=!(!t?.can_optimize_undo&&!i?.can_optimize_undo),e._adoptConfigCapabilities(t),e._undoKind=t?.undo_kind||i?.undo_kind||null,"boolean"==typeof t?.can_write&&(e._serverCanWrite=t.can_write),o&&e._continuity.note("config-candidate",{configRev:n.configRev}),s&&e._continuity.note("layout-candidate",{layoutRev:n.layoutRev})}(e,i,n),"reload"===t.profile&&(e._syncDecorAssets(o).catch(()=>{}),e._adoptInitialSpace(e._model,!0),e._resumePendingNavMode(),e._cacheSnapshot()),t.afterAdopt?.(),{status:"adopted",spaceChanged:e._space!==a}}const Du=e=>!!e&&e.length>=2&&Number.isFinite(e[0])&&Number.isFinite(e[1]);function Au(e,t=5,i=5){return Co(e.cm,t,i)/2}function Pu(e,t,i=1,n=5,r=5,o=0){const s=e.host;if(!s||"partition"!==s.kind||"string"!=typeof s.id||!s.id)return{resolved:null,reason:"invalid-host"};const a=t.find(e=>e.id===s.id);if(!a)return{resolved:null,reason:"missing-partition"};if(!Du(a.a)||!Du(a.b)||!Number.isFinite(s.t)||s.t<0||s.t>1)return{resolved:null,reason:"invalid-position"};const l=a.b[0]-a.a[0],c=a.b[1]-a.a[1],h=Math.hypot(l,c),d=Number(e.length)*i;if(!(h>1e-9&&d>0&&Number.isFinite(d)))return{resolved:null,reason:"invalid-length"};const u=s.t*h;if(u-d/2h-o+1e-9)return{resolved:null,reason:"does-not-fit"};const p=l/h,_=c/h;let m=180*Math.atan2(c,l)/Math.PI;return m>=90?m-=180:m<-90&&(m+=180),{reason:null,resolved:{opening:e,host:s,partition:a,center:[a.a[0]+l*s.t,a.a[1]+c*s.t],angle:m,length:d,depth:Co(a.cm,n,r),t:s.t,axis:{a:[a.a[0],a.a[1]],b:[a.b[0],a.b[1]],ux:p,uy:_,length:h}}}}function Fu(e,t,i=1,n=5,r=5){return Pu(e,t,i,n,r,0)}function zu(e,t,i=1,n=5,r=5){const o=e.host,s="partition"===o?.kind?t.find(e=>e.id===o.id):void 0;if(!s)return Fu(e,t,i,n,r);const a=Pu(e,t,i,n,r,Au(s,n,r));return"does-not-fit"===a.reason?{resolved:null,reason:"does-not-fit-jamb"}:a}function Iu(e,t){return!e||(e.length!==t.length||e.host?.kind!==t.host?.kind||e.host?.id!==t.host?.id||e.host?.t!==t.host?.t)}function Ou(e){const{center:t,length:i,axis:n,host:r}=e,o=i/2;return{hostId:r.id,a:[t[0]-n.ux*o,t[1]-n.uy*o],b:[t[0]+n.ux*o,t[1]+n.uy*o],depth:e.depth}}function Eu(e,t=!1){const i=t?1:-1,n=e.depth/2;return{ox:-e.axis.uy*i*n,oy:e.axis.ux*i*n,cm:e.partition.cm,side:i}}function Nu(e,t,i){return e.flatMap(e=>!Du(e.a)||!Du(e.b)||Math.hypot(e.b[0]-e.a[0],e.b[1]-e.a[1])<=1e-9?[]:[{roomId:"",a:[e.a[0],e.a[1]],b:[e.b[0],e.b[1]],key:`partition:${e.id}`,kind:"outer",cm:e.cm,open:!1,half:Co(e.cm,t,i)/2,partitionHost:{kind:"partition",id:e.id}}])}function Hu(e,t,i){const{center:n,length:r,axis:o}=e,s=r/2,a=t.flatMap(e=>{if(!e.kind||e.open)return[];const t=e.b[0]-e.a[0],r=e.b[1]-e.a[1],a=Math.hypot(t,r);if(!(a>i))return[];const l=t/a,c=r/a;if(Math.abs(o.ux*c-o.uy*l)>1e-6)return[];if(Math.abs((n[0]-e.a[0])*c-(n[1]-e.a[1])*l)>i)return[];const h=e=>(e[0]-n[0])*o.ux+(e[1]-n[1])*o.uy,d=h(e.a),u=h(e.b),p=Math.max(-s,Math.min(d,u)),_=Math.min(s,Math.max(d,u));return _>=p-i?[[p,_]]:[]});if(!a.length)return!1;a.sort((e,t)=>e[0]-t[0]||e[1]-t[1]);let l=-s;for(const[e,t]of a){if(e>l+i)return!1;if(l=Math.max(l,t),l>=s-i)return!0}return!1}function Lu(e,t,i=1e-9){const n=e.length/(2*e.axis.length),r=e.t-n,o=e.t+n;return t.some(t=>{if(t.host.id!==e.host.id||t.opening.id===e.opening.id)return!1;const n=t.length/(2*t.axis.length);return Math.max(r,t.t-n){e.isConnected&&e.requestUpdate()}),Wu.has(e)?"warm":"cold"):(Uu.delete(e)&&(e.inert=!1,e.removeAttribute("aria-busy")),i&&(e.setAttribute("lang","fallback"===n?"en":i),Wu.add(e)),"ready")}function Gu(){return j``}const Ku=[{code:"en",nativeLabel:"English",dictionary:ju},{code:"ru",nativeLabel:"Русский",dictionary:{"editor.context_actions":"Действия: {object}","editor.tool_options":"Параметры инструмента: {tool}","editor.palette":"Палитра: {tool}","editor.open_group":"Группа инструментов: {group}","editor.group_active":"{group} — активно: {item}","editor.disabled_action":"{action} недоступно: {reason}","editor.loading":"Загружаем редактор…","editor.loading_aria":"Редактор плана загружается","editor.load_failed":"Не удалось загрузить редактор.","editor.refresh_advice":"Обновите страницу и повторите попытку.","editor.retry_advice":"Проверьте сеть и нажмите ещё раз.","version_mismatch.title":"Версии House Plan не совпадают","version_mismatch.body":"Если Home Assistant ещё перезапускается, дождитесь завершения, затем перезагрузите эту страницу.","version_mismatch.frontend":"Карточка","version_mismatch.backend":"Интеграция","version_mismatch.reload":"Перезагрузить страницу","color_picker.title":"Выбор цвета","color_picker.hue":"Оттенок","color_picker.saturation":"Насыщенность","color_picker.value":"Яркость","color_picker.hex":"Цвет HEX","color_picker.invalid_hex":"Введите цвет HEX из 3 или 6 цифр","color_picker.confirm":"ОК","btn.properties":"Свойства","btn.keep_as_walls":"Оставить стенами","btn.delete_room_keep_walls":"Удалить комнату, оставить стены","btn.delete_room_with_walls":"Удалить комнату и стены","title.markup_select":"Выбор и редактирование стен и колонн","title.markup_column":"Колонна: кликните точку сетки для квадратной колонны","markup.partition":"Перегородка","markup.column":"Колонна","markup.hint_column":"кликните точку сетки, чтобы поставить квадратную колонну","history.wall_segment":"Добавление отрезка стены","history.column_add":"Добавление колонны","history.physical_edit":"Изменение физического объекта","history.physical_delete":"Удаление физического объекта","history.physical_move":"Перемещение физического объекта","history.wall_face_batch":"Создание комнат из стен","toast.column_duplicate":"Колонна с тем же центром и внешним размером уже существует","physical.partition_properties":"Свойства перегородки","physical.column_properties":"Свойства колонны","physical.shape":"Форма","physical.square":"Квадрат","physical.circle":"Круг","physical.diameter":"Диаметр","physical.side":"Сторона","physical.rotation":"Угол поворота","physical.length":"Длина","physical.allowed_range":"Допустимо: {min}–{max} {unit}","physical.column_size_title":"Внешняя сторона квадратной колонны, создаваемой кликом (1–150 см).","card.title":"План дома","count.devices":"{n} устр.","empty.no_spaces":"Пространств пока нет.","empty.add_first":"Добавьте первое пространство и загрузите план этажа.","empty.read_only":"Пространства не настроены. Попросите администратора добавить первое.","empty.install":"Установите интеграцию House Plan и добавьте запись в «Устройства и службы».","btn.add_space":"Добавить пространство","btn.cancel":"Отмена","btn.save":"Сохранить","btn.close":"Закрыть","btn.delete":"Удалить","btn.copy":"Копировать","btn.edit":"Редактировать","btn.open_in_ha":"Открыть в HA","btn.reset":"Сброс","btn.attach":"Прикрепить…","btn.upload":"Загрузить…","btn.replace":"Заменить…","title.zoom_in":"Приблизить","title.zoom_out":"Отдалить","title.zoom_fit":"Вписать всё","title.configure_space":"Настроить пространство","title.add_space":"Добавить пространство","title.markup_add":"Стены: рисуйте непрерывную цепочку; каждый принятый отрезок сохраняется отдельно. Shift фиксирует 45°","title.markup_merge":"Объединить: клик по одной комнате, затем по соседней с общей стеной","title.markup_split":"Разделить комнату: клик по комнате, затем две точки на её стенах","title.markup_delroom":"Удалить комнату: кликните внутри комнаты и подтвердите удаление","title.need_plan":"Загрузите подложку (план этажа)","markup.add":"Стены","markup.merge":"Объединить","markup.split":"Разделить","markup.resize":"Размер","title.markup_resize":"Изменение размера комнат: тяните доступную ручку горизонтальной или вертикальной стены","markup.hint_resize":"тяните доступную ручку стены · стена упирается в первую небезопасную позицию · Esc — отмена · Ctrl+Z — отмена шага","resize.disabled.diagonal":"Стена расположена под углом: Resize поддерживает только горизонтальные и вертикальные стены","resize.disabled.side-angle":"Примыкающая стена расположена под углом: для Resize обе примыкающие стены должны образовывать прямой угол","resize.disabled.duplicate-physical-wall":"Стену перекрывает отдельная перегородка или колонна; удалите или переместите её перед изменением размера","resize.disabled.partial-shared":"Соседняя комната использует только часть этой стены, поэтому её нельзя безопасно двигать как одну общую стену","resize.disabled.unequal-shared":"У соседней комнаты другие конечные точки или длина стены, поэтому стены нельзя безопасно двигать вместе","resize.disabled.multiple-rooms":"Перемещение затронуло бы больше двух комнат","resize.disabled.thickness-conflict":"Толщину стены нельзя безопасно сохранить","resize.disabled.opening-conflict":"Проём на этой стене нельзя безопасно переместить","resize.disabled.invalid-geometry":"Эту стену нельзя переместить без изменения структуры плана","resize.limit_stopped":"Стена остановлена: дальше нарушается ограничение стыков","resize.commit_failed":"Изменение размера отменено: итоговый план не прошёл проверку геометрии","resize.preview_failed":"Стена остановлена в последней безопасной позиции: геометрию плана нельзя сохранить без потерь","markup.opening":"Проём","markup.delete_room":"Удалить комнату","history.undo":"Отменить","history.redo":"Повторить","history.undo_named":"Отменить: {name} (Ctrl+Z)","history.redo_named":"Повторить: {name} (Ctrl+Shift+Z / Ctrl+Y)","history.undo_empty":"Нет операций для отмены","history.redo_empty":"Нет операций для повтора","history.undone":"Отменено: {name}","history.redone":"Повторено: {name}","history.add_room":"Создание комнаты","history.split_room":"Разделение комнаты","history.merge_rooms":"Объединение комнат","history.resize_room":"Изменение размера комнаты","history.wall_thickness":"Изменение толщины стены","history.add_opening":"Добавление дверного или оконного проёма","history.edit_opening":"Изменение проёма","history.move_opening":"Перемещение проёма","history.delete_opening":"Удаление проёма","history.delete_room_keep_walls":"Удаление комнаты с сохранением стен","history.delete_room_with_walls":"Удаление комнаты и её стен","history.decor_add":"Добавление объекта декора","history.decor_edit":"Изменение объекта декора","history.decor_move":"Перемещение объекта декора","history.decor_transform":"Трансформация объекта декора","history.decor_delete":"Удаление объекта декора","history.backdrop_transform":"Трансформация подложки плана","history.device_move":"Перемещение: {name}","history.device_stale":"История позиций больше неприменима и была очищена","opening.new":"Новый проём","opening.edit":"Проём","opening.door":"Дверь","opening.window":"Окно","opening.gate":"Ворота","opening.passage":"Открытый проём","opening.passage_binding_warning":"При сохранении датчик открытия и замок будут удалены.","opening.invalid_passage_fields":"У открытого проёма на плане «{room}» есть недопустимые параметры: {fields}.","opening.type_label":"Тип","opening.length_label":"Длина, см","opening.contact_label":"Датчик открытия","opening.lock_label":"Замок","opening.none":"— нет —","opening.search_ph":"Поиск: имя или entity_id…","opening.invert":"Инвертировать открыто/закрыто","opening.flip_h":"Петли с другой стороны","opening.flip_v":"Открывается в другую сторону","opening.open":"Открыто","opening.closed":"Закрыто","opening.locked":"Заперто","opening.unlocked":"Не заперто","opening.state_unknown":"недоступно","opening.no_entities":"Датчики не привязаны — статичный символ на плане.","toast.opening_no_wall":"Кликните рядом со стеной комнаты или независимой стеной","opening.host_partition":"Независимая стена","opening.partition_orphan":"Независимая стена этого проёма больше не существует","opening.partition_jamb_margin":"Оставьте от края проёма до торца стены минимум {distance}","opening.rebind_partition":"Привязать к другой независимой стене","confirm.delete_partition_openings_title":"Удалить стену и проёмы?","confirm.delete_partition_openings_body":"В стене есть проёмы: {count}. Они будут удалены вместе со стеной.","confirm.delete_partition_openings_item":"• {type}, {length}","markup.hint_points":"точек: {n} · Shift — шаг 45° · Esc — завершить цепочку · Ctrl+Z — убрать точку · при замыкании будет предложена комната","markup.hint_start":"кликните точку сетки, чтобы начать цепочку стен","tip.lqi":"средний сигнал zigbee:","tip.area":"площадь: {value}","info.device_header":"Устройство на плане","info.model":"Модель","info.state":"Состояние","info.link":"Ссылка","info.manuals":"Инструкции","info.none":"Нет дополнительной информации","marker.new_device":"Новое устройство","marker.name_label":"Имя (отображается на плане)","marker.name_ph":"Название","marker.binding_label":"Привязка к устройству HA","marker.binding_disabled":"деактивировано в Home Assistant","marker.virtual_option":"Виртуальное устройство (без привязки)","marker.search_ph":"Поиск устройства / группы…","marker.nothing_found":"ничего не найдено","marker.room_label":"Комната","marker.room_override":" (переопределить размещение)","marker.room_choose":"— выберите комнату —","marker.room_auto":"— по зоне устройства (авто) —","marker.icon_label":"Иконка","marker.icon_ph":"mdi:… (пусто = авто)","marker.display_label":"Отображение","display.badge":"Значок + состояние","display.icon_ripple":"Значок + состояние и активность","display.static_icon":"Всегда статичный значок","marker.display_hint_badge":"Значок и динамическая подложка показывают состояние устройства без обычной пульсации активности. Красная тревога сохраняется.","marker.display_hint_icon_ripple":"Значок, динамическая подложка и пульсация: короткая — для событий, постоянная — для работы, движения или присутствия. Красная тревога имеет отдельный приоритет.","marker.display_hint_value":"Значок заменяется выбранным или автоматически найденным значением Home Assistant; подложка продолжает показывать состояние. Красная тревога сохраняется.","marker.display_hint_static_icon":"Подложка в цветах темы и значок всегда остаются одинаковыми. Состояния, активность, недоступность и тревоги не меняют отображение.","marker.static_alarm_warning":"Это устройство может сообщать о тревогах. Статичный режим скрывает визуальную тревогу маркера.","marker.preview.title":"Предпросмотр отображения","marker.preview.actual":"Сейчас","marker.preview.example":"Пример","marker.preview.integration":"Интеграция","marker.preview.source":"Источник отображения","marker.preview.current_state":"Текущее состояние","marker.preview.result":"На плане","marker.preview.details":"Подробнее об источниках","marker.preview.select_source":"Выберите устройство или сущность Home Assistant, чтобы увидеть фактическое отображение.","marker.preview.unknown_provider":"Интеграция неизвестна","marker.preview.virtual_provider":"House Plan · виртуальное устройство","marker.preview.no_source":"Нет активного источника","marker.preview.no_state":"Нет текущего состояния","marker.preview.mixed_states":"Несколько разных состояний","marker.preview.multiple_sources":"Источников: {n}","marker.preview.more_sources":"ещё {n}","marker.preview.scaled":"Предпросмотр уменьшен до {n}%, чтобы поместиться. Сохранённый размер не изменится.","marker.preview.demo_short":"Показать краткую активность","marker.preview.demo_continuous":"Показать постоянную активность","marker.preview.stop_continuous":"Остановить постоянную активность","marker.preview.demo_short_notice":"Пример краткой активности; фактическое состояние устройства не меняется.","marker.preview.demo_continuous_notice":"Пример постоянной активности; фактическое состояние устройства не меняется.","marker.preview.demo_already_visible":"Текущее состояние уже показывает реальную активность или тревогу.","marker.preview.reduced_motion":"В системе включено уменьшение движения, поэтому обычная активность показана точкой.","marker.preview.reason.neutral":"Нейтральная тёмная подложка","marker.preview.reason.working":"Жёлтая подложка: устройство сейчас работает","marker.preview.reason.working_activity":"Жёлтая подложка и эффект активности: устройство сейчас работает","marker.preview.reason.open":"Оранжевая подложка: физически открыто или разблокировано","marker.preview.reason.cover_icon_state":"Нейтральная подложка; состояние и значок определяет сущность шторы или заслонки","marker.preview.reason.presence":"Эффект активности, пока обнаружено присутствие","marker.preview.reason.event":"Короткий эффект активности после события","marker.preview.reason.transition":"Эффект активности во время движения или смены состояния","marker.preview.reason.media_neutral":"Медиаустройство остаётся на нейтральной тёмной подложке, пока доступно","marker.preview.reason.unavailable":"Приглушённая нейтральная подложка: отключено или недоступно","marker.preview.reason.alarm":"Красная тревожная подложка; тревога отображается всегда","marker.preview.reason.live_states_disabled":"Оформление по живым состояниям отключено в настройках карточки","marker.preview.reason.value_no_state":"Нет подходящего значения состояния — вместо него показан значок","marker.preview.reason.value_ambiguous_sources":"Подходит несколько источников значения — вместо него показан значок","marker.preview.reason.value_non_scalar":"Источник вернул не простое значение — вместо него показан значок","marker.preview.reason.value_virtual":"У виртуального устройства нет значения HA — вместо него показан значок","marker.preview.reason.vacuum_live_plan_only":"Живая позиция и след пылесоса доступны только на полном плане","marker.preview.reason.hidden_design_preview":"Устройство скрыто на плане, но его оформление видно в предпросмотре","marker.preview.reason.composite_power_source":"Состояние берётся из сущности питания устройства; вспомогательные переключатели не учитываются","marker.preview.reason.activity_display_disabled":"Выбранный режим отображения не показывает обычные эффекты активности","marker.preview.reason.ha_disabled":"Привязка отключена в Home Assistant, поэтому устройство будет скрыто на плане","marker.preview.reason.orphaned":"Сохранённая привязка Home Assistant больше не найдена","marker.preview.reason.static_icon":"Статичный режим: состояние устройства не меняет значок","marker.activity_color":"Цвет пульсации активности","marker.ripple_size":"Размер пульсации активности","marker.activity_alarm_note":"Цвет и размер относятся только к обычной активности и не влияют на красную тревогу.","marker.pulse_a11y_alarm":"Тревога","marker.pulse_a11y_event":"Недавнее событие","marker.pulse_a11y_presence":"Обнаружено присутствие","marker.pulse_a11y_transition":"Изменение состояния","marker.pulse_a11y_running":"Работает","marker.state_a11y_neutral":"Обычное состояние","marker.state_a11y_working":"Работает","marker.state_a11y_open":"Открыто","marker.state_a11y_locked":"Заблокировано","marker.state_a11y_unlocked":"Разблокировано","marker.state_a11y_alarm":"Тревога","marker.state_a11y_unavailable":"Недоступно","marker.lqi_a11y_low":"LQI {value}, слабый сигнал","marker.lqi_a11y_mid":"LQI {value}, средний сигнал","marker.lqi_a11y_high":"LQI {value}, сильный сигнал","marker.size_label":"Размер / поворот значка","marker.angle_label":"Поворот","marker.model_label":"Модель","marker.model_ph":"напр. Aqara T&H","marker.link_label":"Ссылка","marker.desc_label":"Описание","marker.desc_ph":"Заметки, характеристики…","marker.manuals_label":"Инструкции (PDF и т.п.)","marker.sub_device":"устройство","marker.sub_z2m_group":" · Z2M-группа","marker.sub_group":"группа","marker.sub_helper":"хелпер","space.new":"Новое пространство","space.copy_title":"Копирование пространства","space.copy_name":"Название нового пространства","space.copy_fallback":"Пространство","space.copy_create":"Создать копию","space.copy_optimize_title":"Оптимизировать перед копированием?","space.copy_optimize_body":"Перед созданием «{name}» House Plan должен оптимизировать весь план, включая другие пространства. Продолжить?","space.copy_optimize_confirm":"Оптимизировать и скопировать","space.copy_error_changed":"План изменился, пока было открыто подтверждение. Проверьте его и повторите попытку.","space.copy_error_source_missing":"Исходного пространства больше нет. Снова откройте его настройки и повторите попытку.","space.copy_error_source_invalid":"House Plan не смог проверить все стены этого пространства. Исправьте исходное пространство и повторите попытку.","space.copy_error_spaces_limit":"В House Plan уже создано максимальное число пространств.","space.copy_error_partitions_limit":"В этом пространстве слишком много стен для копирования.","space.copy_error_openings_limit":"В этом пространстве слишком много проёмов для копирования.","space.copy_error_decor_limit":"В этом пространстве слишком много элементов подложки для копирования.","space.copy_error_columns_limit":"В этом пространстве слишком много колонн для копирования.","space.copy_error_opening_host":"Один из проёмов больше не привязан к стене. Исправьте или удалите его перед копированием.","space.copy_error_geometry":"Копия создаст небезопасную геометрию стен. Исправьте исходное пространство и повторите попытку.","space.copy_error_optimize_geometry":"Копирование остановлено: оптимизация всего плана небезопасна для одного из пространств.","space.header":"Пространство","space.title_label":"Название","space.title_ph":"Например: Гараж","space.plan_label":"Подложка (план)","space.no_plan":"нет подложки","space.plan_alt":"план","room.new":"Новая комната","room.name_label":"Отображаемое имя","room.name_ph":"Например: Терраса","room.area_label":"Зона Home Assistant (свободные)","room.no_area_option":"— без зоны —","room.default_name":"Комната","device.unnamed":"без имени","device.light_group":"группа света","device.fallback":"устройство","device.virtual":"виртуальное устройство","confirm.delete_room_title":"Удалить комнату «{name}»?","confirm.delete_room_body":"Выберите, нужно ли оставить физические стены, принадлежащие только этой комнате. Общие с другой комнатой стены сохраняются всегда.","confirm.remove_marker_title":"Удалить устройство с плана?","confirm.remove_marker_body":"Устройство исчезнет полностью и перестанет участвовать в данных плана. Позже его можно будет добавить заново.","confirm.erase_decor":"Стереть объект «{kind}»? Действие можно отменить из истории редактора.","confirm.delete_space_title":"Удалить пространство?","confirm.delete_space_body":"Пространство, все его комнаты и вся разметка плана будут удалены.","confirm.delete_space_vac_routes":"Также будет снято сопоставление карт роботов: {count}.","space.delete_blocked":"Это пространство всё ещё используется устройствами: {n}. Сначала перенесите их в другое пространство или удалите.","toast.pos_save_failed":"Не удалось сохранить позицию: {err}","toast.no_entity":"У устройства нет подходящей сущности","toast.ha_disabled_action":"Деактивированный объект Home Assistant нельзя использовать на плане.","toast.ha_disabled_show_device":"Деактивированное в Home Assistant устройство нельзя показать на плане. Сначала активируйте его в Home Assistant.","toast.ha_disabled_show_entity":"Деактивированную в Home Assistant сущность нельзя показать на плане. Сначала активируйте её в Home Assistant.","toast.ha_disabled_add":"Деактивированный объект Home Assistant нельзя добавить на план. Сначала активируйте его в Home Assistant.","toast.ha_binding_unverified":"Статус объекта не удалось подтвердить по реестру Home Assistant. Отображение и действия временно недоступны.","toast.markup_needs_server":"Разметка доступна после переноса конфига на сервер","toast.space_order_changed":"Порядок изменён. Если где-то этаж карточки задан номером, проверьте такие панели.","toast.conflict":"Конфиг изменён в другом окне — данные обновлены, повторите последнее действие","toast.cfg_save_failed":"Не удалось сохранить конфиг: {err}","toast.room_overlap":"Контур накладывается на комнату «{name}» — комнаты не должны накладываться","toast.contour_cannot_close":"Контур нельзя замкнуть: он вырожден или пересекает сам себя","toast.merge_not_adjacent":"Объединять можно только комнаты с общей стеной","toast.rooms_merged":"Комнаты объединены в «{name}»","toast.split_pick_wall":"Начните разрез на стене комнаты","toast.split_bad_cut":"Разрез — от стены до стены внутри комнаты, без пересечения стен и самого себя","merge.header":"Объединение комнат","merge.hint":"У объединённой комнаты одно имя и одна зона. Вторая зона освобождается — её устройства уйдут с плана, пока их не заберёт другая комната.","merge.keep":"Оставить","merge.no_area":"без зоны","toast.room_saved":"Комната сохранена ({n}). Устройств добавлено: {added}. Обведите следующую или выйдите из разметки.","toast.room_saved_no_area":"Комната сохранена ({n}, без зоны). Обведите следующую или выйдите из разметки.","toast.marker_needs_server":"Редактирование устройств доступно после переноса конфига на сервер","toast.virtual_name_required":"Укажите имя виртуального устройства","toast.marker_saved":"Устройство сохранено","toast.marker_removed":"Устройство удалено с плана","toast.integration_missing":"Интеграция House Plan не установлена — управление недоступно","toast.plan_formats":"Поддерживаются SVG, PNG, JPG, WebP","toast.plan_required":"Загрузите подложку — план этажа обязателен","toast.space_added_onboard":"Пространство добавлено. Обведите комнаты: кликайте по точкам сетки и замкните контур.","toast.space_added":"Пространство добавлено","toast.space_copied":"Пространство «{name}» создано","toast.space_saved":"Пространство сохранено","toast.space_deleted":"Пространство удалено","toast.delete_failed":"Ошибка удаления: {err}","toast.error":"Ошибка: {err}","toast.toggle_target_unavailable":"Цель «{name}» недоступна — действие не выполнено","toast.toggle_targets_unavailable":"Цели недоступны: {names}. Действие не выполнено","toast.file_failed":"Файл «{name}» не загружен: {err}","toast.files_attached":"Прикреплено файлов: {n}","err.unknown":"неизвестная ошибка","err.code":"код {code}","err.too_large":"файл больше {mb} МБ","err.bad_ext":"недопустимый тип (нужен PDF/изображение)","err.unauthorized":"нужны права администратора","editor.title":"Заголовок","editor.default_floor":"Стартовое пространство","editor.default_floor_missing":"Стартовое пространство «{id}» больше не существует. Выберите другое.","editor.floor":"Закреплённое пространство","editor.floor_none":"— не закреплять —","editor.floor_index":"YAML-индекс {index} (сохранён)","fixed_floor.loading":"Загружаем закреплённое пространство…","fixed_floor.invalid_title":"Закреплённое пространство недоступно","fixed_floor.invalid_body":"Проверьте floor в конфигурации карточки. Настроенное значение: {value}","editor.icon_size":"Размер иконок, % ширины плана","editor.show_temperature":"Показывать температуру","editor.live_states":"Живые состояния (вкл/выкл, открыто…)","editor.light_pools":"Световые пулы и тени от стен","editor.show_signal":"Показывать сигнал zigbee (LQI)","editor.language":"Язык интерфейса","editor.lang_auto":"Авто (профиль HA)","title.icon_rules":"Правила иконок: какая MDI-иконка достаётся устройству по имени","rules.title":"Правила иконок","rules.hint":"Правила проверяются сверху вниз по строке «имя устройства + модель» (regex без учёта регистра); срабатывает первое совпадение. Если ничего не подошло — решает device class сущности, затем — иконка-заглушка.","rules.pattern_ph":"regex, напр. розетк|plug","rules.icon_ph":"mdi:power-socket-de","rules.add":"Добавить правило","rules.reset":"Сбросить к умолчаниям","rules.test_ph":"Проверьте имя устройства…","rules.invalid":"некорректный regex","rules.saved":"Правила иконок сохранены","btn.up":"Вверх","btn.down":"Вниз","tap.info":"Карточка устройства","tap.more_info":"Диалог HA (more-info)","tap.toggle":"Переключить состояние","marker.tap_label":"Действие по нажатию для этого устройства","tap.toggle_note":"Под селектором показано, какое состояние изменится. Защищённые устройства не переключаются с плана.","import.title":"Создать пространства из этажей HA","import.hint":"Home Assistant уже знает эти этажи. Отметьте, какие превратить в пространства плана — далее для каждого попросим картинку плана. Комнаты затем обводятся вручную по плану.","import.start":"Создать: {n}","import.manual":"Начать с нуля","import.progress":"Этаж {i} из {n}","import.done":"Пространства созданы. Обведите комнаты: кликайте по точкам сетки и замкните контур.","btn.skip":"Пропустить","space.scale_label":"Масштаб (размер клетки сетки)","space.cell_cm.help":"Связывает сетку с реальными размерами: от значения зависят длины и площади, толщина стен, размеры проёмов и радиус свечения. Изменение после разметки меняет расчётные размеры всего пространства, но не двигает его точки на плане.","space.cell_cm.help.aria":"Подсказка: масштаб пространства","space.scale_unit":"см на клетку","space.scale_unit_imperial":"дюйм на клетку","space.display_section":"Отображение","space.show_borders":"Всегда отображать границы комнат","space.zero_wall_style":"Стены нулевой толщины","space.zero_wall_style.help":"Пунктирные стены нулевой толщины пропускают Glow и солнечные лучи, сплошные блокируют их как барьер нулевой площади. Выбор меняет все такие стены пространства, даже когда их линии скрыты в просмотре.","space.zero_wall_style.help.aria":"Подсказка: вид стен нулевой толщины","space.zero_wall_dashed":"Пунктирные","space.zero_wall_solid":"Сплошные","space.show_names":"Отображать названия комнат (перетаскиваются)","space.room_color":"Цвет границ и названий","space.opacity":"Прозрачность","space.fill_label":"Заливка комнат","space.fill_mode.help":"«Свой цвет» задаёт оформление, а «Свет», «Температура» и «LQI» используют текущие данные Home Assistant; Glow включается отдельно.","space.fill_mode.help.aria":"Подсказка: режим заливки комнат","fill.none":"Нет","fill.lqi":"По силе зигби-сигнала","fill.light":"По освещению","fill.custom":"Свой цвет","space.custom_fill":"Цвет заливки","space.source_file":"У меня есть картинка плана","space.source_draw":"Нет подложки — нарисую комнаты вручную","fill.temp":"По температуре","tip.temp_avg":"средняя температура:","tip.hum_avg":"средняя влажность:","space_card.button":"Перейти к пространству","space_card.not_found":"Пространство «{id}» не найдено","space_card.loading":"Загрузка…","continuity.restore_plan":"Восстанавливаем план…","continuity.restore_connection":"Восстанавливаем подключение к устройствам…","continuity.retry":"Повторить","editor.space":"Пространство","editor.framing":"Кадрирование","editor.fit_content":"Всё видимое содержимое","editor.fit_house":"Плотно по геометрии дома","editor.show_button":"Показывать кнопку","editor.button_label":"Текст кнопки","editor.button_target":"Путь дашборда (куда вести)","marker.sub_entity":"сущность","title.general_settings":"Общие настройки","title.export_pdf":"Сохранить в PDF","pdf.title":"Сохранение в PDF","pdf.dimensions":"Отображать размеры и площади","pdf.decor":"Отображать мебель и другой декор","pdf.room_names":"Отображать названия комнат","pdf.backdrop":"Отображать подложку","pdf.save":"Сохранить","pdf.saving":"Формируем…","pdf.failed":"Не удалось создать PDF.","pdf.too_large":"Размер изображений превышает лимит PDF 25 МБ.","pdf.asset_failed":"Не удалось загрузить подложку или изображение декора.","pdf.internal_dimensions":"Внутренние размеры","pdf.scale":"Масштаб 1:{n}","pdf.north":"Север","gs.title":"Общие настройки","gs.light_group":"Заливка: освещение","gs.light_on":"Свет включён","gs.light_off":"Весь свет выключен","gs.temp_group":"Заливка: температура","gs.temp_cold":"Холодно","gs.temp_ok":"Комфорт","gs.temp_hot":"Жарко","gs.lqi_group":"Заливка: зигби-сигнал","gs.lqi_low":"Слабый сигнал","gs.lqi_high":"Сильный сигнал","gs.reset":"Сбросить к умолчаниям","gs.saved":"Общие настройки сохранены","gs.radar_show_live":"Показывать текущее присутствие на плане","gs.radar_show_live_hint":"Скрывает или показывает все живые цели радаров. Это не запускает и не останавливает запись наблюдений.","radar.title":"Присутствие на плане","radar.help":"Свяжите маркер с точными сущностями радара Home Assistant, укажите положение датчика и профиль координат. Живые позиции обрезаются по выбранной комнате.","radar.help.aria":"Подсказка: настройки радара присутствия","radar.enabled":"Использовать этот радар присутствия","radar.show_live":"Показывать живые цели","radar.configure":"Настроить радар","radar.configure_on_plan":"Настроить на плане","radar.change_installation":"Сменить установку","radar.no_contour":"У комнаты нет контура. Точки радара не будут обрезаться по комнате.","radar.discard_setup_title":"Отменить настройку радара?","radar.discard_setup":"Несохранённая настройка радара будет потеряна.","radar.step_place_mount":"Укажите физическое положение датчика","radar.step_place_heading":"Укажите точку прямо перед датчиком","radar.step_reference":"Укажите контрольное положение {n}, затем начните измерение","radar.step_check_reference":"Укажите независимое проверочное положение","radar.start_measure":"Начать измерение","radar.countdown":"Встаньте в отмеченное место через {seconds} с","radar.capturing":"Стойте неподвижно и в одиночестве…","radar.fit_ready":"Калибровка готова","radar.check_third":"Проверить в другом положении","radar.check_complete":"Независимая проверка завершена","radar.error_distance":"Расхождение положения: {distance}","radar.ambiguous_target":"Обнаружено несколько целей. Повторите измерение в одиночестве.","radar.insufficient_samples":"Недостаточно актуальных координат. Повторите или настройте вручную.","radar.bad_references":"Выберите разнесённые положения в разных направлениях от датчика.","radar.ambiguous_sources":"Измерения допускают два одинаково вероятных направления. Выберите точки, по которым можно различить левую и правую стороны.","radar.bad_fit":"Измерения не совпадают. Проверьте единицы, положение датчика и контрольные точки.","radar.desktop_hint":"Для точной настройки используйте компьютер. Редактирование на тач-устройствах поддерживается по остаточному принципу.","radar.detected":"House Plan распознал признаки радара у этого устройства. Перед сохранением проверьте точные источники.","radar.detected_ld2450":"House Plan нашёл набор координат ESPHome LD2450. Перед сохранением проверьте точные источники X/Y.","radar.additional_actions":"Дополнительные действия","radar.declare":"Это радар присутствия","radar.profile":"Профиль данных","radar.profile_esphome_ld2450_v1":"ESPHome LD2450 (цели X/Y)","radar.profile_cartesian_v1":"Декартовы цели (X/Y)","radar.profile_polar_v1":"Полярная цель (дальность/угол)","radar.profile_range_v1":"Только дальность","radar.profile_zones_v1":"Состояния зон","radar.profile_presence_v1":"Только присутствие","radar.room":"Комната радара","radar.room_choose":"Выберите комнату","radar.target":"Цель {n}","radar.axis_x":"Сущность координаты X","radar.axis_y":"Сущность координаты Y","radar.add_target":"Добавить слот цели","radar.range_channel":"Канал дальности {n}","radar.add_range":"Добавить канал дальности","radar.presence_gate":"Сущность присутствия для слота","radar.swap_axes":"Поменять оси X и Y местами","radar.axis_x_sign":"Направление X","radar.axis_y_sign":"Направление Y","radar.distance_source":"Сущность дальности","radar.angle_source":"Сущность угла","radar.angle_unit":"Единица угла","radar.degrees":"Градусы","radar.radians":"Радианы","radar.angle_zero":"Направление нулевого угла","radar.angle_forward":"Вперёд","radar.angle_right":"Вправо","radar.angle_clockwise":"Угол растёт по часовой стрелке","radar.zone_source":"Сущность зоны","radar.occupancy_source":"Сущность присутствия","radar.count_source":"Сущность количества целей","radar.availability_source":"Сущность доступности","radar.source_choose":"Выберите сущность","radar.source_optional":"Необязательно","radar.source_missing":"сейчас недоступна","radar.saved_unsupported":"Сохранённая настройка радара не поддерживается или неполна. Она неактивна; удалите её либо обновите House Plan перед повторной настройкой.","radar.occupancy":"Присутствие (вкл/выкл)","radar.count":"Количество","radar.mount":"Положение и направление","radar.mount_hint":"Это физическое положение датчика. Перемещение его декоративного маркера не меняет установку.","radar.heading":"Направление, °","radar.range_cm":"Дальность, см","radar.fov_deg":"Угол обзора, °","radar.unit":"Единица источника","radar.mirror":"Отразить ось влево/вправо","radar.remove":"Удалить настройки радара","radar.invalid":"Перед сохранением заполните комнату, источники и положение радара.","radar.check_sources":"Проверить живые данные","radar.checking":"Проверяем…","radar.health":"Состояние подключения","radar.live_summary":"Текущих целей: {targets}; дуг дальности: {ranges}","radar.health_ok":"Актуальные данные получены","radar.health_off":"Цели не обнаружены","radar.health_stale":"Часть координат устарела","radar.health_partial":"Часть источников актуальна, часть устарела","radar.health_restricted":"Нет доступа к одному или нескольким источникам","radar.health_incomplete":"Текущий отчёт радара неполон","radar.health_position_unavailable":"Есть присутствие, но актуальное положение недоступно","radar.health_unavailable":"Данные датчика недоступны","radar.health_needs_setup":"Требуется настроить установку","radar.health_inconsistent":"Источники передают противоречивые данные","radar.health_unknown":"Текущее состояние неизвестно","radar.health_disabled":"Радар отключён","radar.error_invalid_radar":"Проверьте настройки радара.","radar.error_invalid_selection":"Выберите существующую комнату и допустимые источники.","radar.error_source_restricted":"Нет доступа ко всем выбранным источникам.","radar.error_rate_limited":"Слишком много запросов. Повторите чуть позже.","radar.error_not_ready":"Обработка данных радара ещё не готова.","radar.error_conflict":"План изменился. Откройте настройку радара заново и повторите попытку.","radar.error_source_unavailable":"Один или несколько выбранных источников радара недоступны.","radar.error_unsupported_capability":"Установленная интеграция не поддерживает эту возможность радара.","radar.report_age":"{seconds} с назад","space.show_lqi":"Показывать зигби-сигнал (LQI) у устройств","space.hide_decor":"Скрыть декоративный слой","space.hide_decor_tip":"Линии, фигуры, надписи и мебель остаются на месте — их видно в редакторе подложки, но не на плане.","space.hide_openings":"Скрыть проёмы","space.hide_openings_tip":"Двери, окна и ворота не рисуются, но продолжают работать: свет проходит, солнце светит в окна, датчики открытия срабатывают. В редакторе плана проёмы видно всегда.","gs.light_none":"Нет источников света","mode.plan":"Редактор плана","mode.devices":"Редактор устройств","display.value":"Значение + состояние","marker.subarea":"без зоны, вручную","device.new":"Новое устройство — откройте его редактор, чтобы снять отметку","opening.unlock_action":"Открыть замок","opening.lock_action":"Закрыть замок","opening.lock_pending":"Выполняется…","title.close_editor":"Закрыть редактор (вернуться к просмотру)","title.add_device":"Добавить устройство на план","devbar.add":"Добавить","devbar.rules":"Правила иконок","device_inbox.button":"Устройства","device_inbox.title":"Устройства на плане","device_inbox.search":"Поиск по устройствам, сущностям и интеграциям…","device_inbox.add_virtual":"Добавить виртуальное устройство","device_inbox.tab_on_plan":"На плане","device_inbox.tab_available":"Доступны","device_inbox.tab_hidden":"Скрытые","device_inbox.tab_readd":"Доступны снова","device_inbox.only_new":"Только новые","device_inbox.show_entities":"Показывать сущности","device_inbox.show_hidden":"Показывать скрытые на плане","device_inbox.show_hidden.help":"Временно показывает на плане скрытые и деактивированные маркеры служебными призраками только в редакторе устройств. Сохранённая видимость устройств не меняется.","device_inbox.show_hidden.help.aria":"Подсказка: показывать скрытые устройства на плане","device_inbox.new":"Новое","device_inbox.find":"Найти на плане","device_inbox.edit":"Настроить","device_inbox.hide":"Скрыть","device_inbox.show":"Показать","device_inbox.add":"Добавить","device_inbox.readd":"Добавить заново","device_inbox.hide_available":"Скрыть из списка","device_inbox.show_more":"Показать ещё","device_inbox.more_actions":"Другие действия","device_inbox.find_hidden_hint":"Сначала включите «Показывать скрытые на плане»","device_inbox.show_disabled":"Перед показом активируйте эту привязку в Home Assistant","device_inbox.empty_on_plan":"На плане пока нет подходящих устройств.","device_inbox.empty_available":"Нет доступных устройств для добавления.","device_inbox.empty_hidden":"Скрытых устройств нет.","device_inbox.empty_readd":"Нет удалённых устройств, доступных для повторного добавления.","device_inbox.reason_visible_auto":"Найдено автоматически","device_inbox.reason_visible_explicit":"Добавлено явно","device_inbox.reason_manual_hidden":"Скрыто пользователем","device_inbox.reason_automatic_hidden":"Скрыто автоматически","device_inbox.reason_service_entry":"Служебная запись реестра","device_inbox.reason_excluded_integration":"Исключена интеграция «{integration}»","device_inbox.reason_excluded_domain":"Непространственный тип сущности","device_inbox.reason_grouped_light":"Представлено группой света комнаты","device_inbox.reason_represented_by_parent":"Представлено родительским устройством","device_inbox.reason_removed":"Ранее удалено с плана","device_inbox.reason_available":"Можно добавить на план","device_inbox.reason_no_bound_room":"Зона HA не связана с комнатой плана","device_inbox.status_ha_disabled":"Отключено в Home Assistant","device_inbox.status_orphaned":"Привязка больше не найдена в Home Assistant","device_inbox.status_unverified":"Реестр Home Assistant временно недоступен","device_inbox.saved":"Список устройств обновлён","device_inbox.filters_excluded":"Исключённые интеграции","device_inbox.filters_group_lights":"Объединять светильники комнаты в один маркер","device_inbox.filters_preview_appear":"появится: {count}","device_inbox.filters_preview_hide":"скроется: {count}","device_inbox.filters_preview_lights":"затронет светильников: {count}","device_inbox.filters_reset":"Вернуть рекомендуемые","device_inbox.filters_save":"Сохранить фильтры","device_inbox.filters_search_ph":"Добавить интеграцию…","device_inbox.filters_title":"Фильтры обнаружения","space.roomcard_section":"В карточке комнаты:","space.label_temp":"Температура","space.label_hum":"Влажность","space.label_lqi":"Средний Zigbee-сигнал","space.label_light":"Свет вкл/выкл","roomcard.light_on":"Вкл","roomcard.light_off":"Выкл","roomcard.light_partial":"{on} из {total}","toast.split_pick_inside":"Промежуточные точки разреза — внутри комнаты","mode.decor":"Редактор подложки","decor.select":"Выбрать","decor.line":"Линия","decor.rect":"Прямоугольник","decor.ellipse":"Овал","decor.text":"Надпись","decor.erase":"Стереть","decor.erase_confirm_title":"Стереть объект?","decor.color":"Цвет","decor.width":"Толщина линии","decor.line_style":"Стиль линии","decor.line_style_solid":"Сплошная","decor.line_style_dashed":"Пунктирная","decor.fill":"Заливка","decor.fill_color":"Цвет заливки","decor.length":"Длина","decor.size":"Размер","decor.flip_h":"Отзеркалить по горизонтали","decor.flip_v":"Отзеркалить по вертикали","decor.angle":"Угол поворота, °","decor.text_size":"Размер текста","decor.backdrop_properties":"Свойства картинки-подложки","decor.text_title":"Надпись","decor.object_title":"Редактирование: {kind}","decor.text_label":"Текст","decor.live_group":"Вставить переменную HA","decor.live_entity":"Сущность","decor.live_entity_ph":"выберите сущность","decor.live_attr":"Значение","decor.live_attr_ph":"выберите состояние или атрибут","decor.live_state":"Состояние","decor.backdrop":"Картинка-подложка","decor.backdrop_hint":"Тяните картинку — перемещение; угол — размер; верхнюю ручку — поворот. Shift меняет пропорции или снимает шаг угла.","decor.backdrop_reset":"Вернуть картинку","decor.backdrop_reset_done":"Картинка вернулась на своё место и в свой размер","marker.icon_auto":"Авто: {icon} (по правилам иконок; выберите свою, чтобы заменить)","marker.icon_pin_auto":"Закрепить","mode.plan_tip":"Редактор плана — геометрия дома: рисование и объединение/разделение комнат, привязка к зонам HA, двери, окна и ворота, карточки комнат, масштаб","mode.devices_tip":"Редактор устройств — всё про значки: перетаскивание, клик — настройка привязки/иконки/отображения, виртуальные устройства, правила иконок","mode.decor_tip":"Редактор подложки — чисто визуальный декор под планом: линии, прямоугольники, овалы и надписи, не реагирующие на клики","space.glow_enabled":"Свечение источников света","gs.glow_group":"Свечение источников света","gs.glow_base":"Темнота дома","gs.glow_light":"Цвет света по умолчанию / интенсивность","gs.wall_group":"Стены","gs.wall_fill":"Цвет заливки стен","gs.glow_radius":"Радиус свечения","gs.glow_radius.help":"Задаёт общий радиус светового пятна в метрах или футах; персональный радиус устройства заменяет это значение.","gs.glow_radius.help.aria":"Подсказка: общий радиус свечения","gs.unit_m":"м","gs.unit_ft":"фут","marker.controls_label":"Управляет другими источниками света","marker.controls.help":"При действии «Переключить состояние» перечисленные источники переключаются вместе с этим маркером. Их световые пятна остаются у собственных маркеров, а эта связь сама по себе не делает управляющий маркер источником света.","marker.controls.help.aria":"Подсказка: управление другими источниками света","marker.controls_filter":"Поиск ламп и выключателей…","info.controls":"Управляет","marker.glow_radius_label":"Радиус свечения","marker.glow_radius.help":"Задаёт радиус свечения в метрах или футах; пустое значение использует радиус из общих настроек.","marker.glow_radius.help.aria":"Подсказка: радиус свечения","markup.wallthick":"Толщина","markup.select":"Выбрать","title.markup_wallthick":"Толщина — клик по стене задаёт толщину от 0 до 100 см.","markup.hint_wallthick":"клик по стене · Esc закрывает без применения","wallthick.field":"Толщина","wallthick.unit_cm":"см","wallthick.unit_in":"дюйм","wallthick.apply_room":"Применить ко всем стенам комнаты","markup.draw_wall_title":"Толщина каждого нового сегмента стены (0–100 см). Общие стены сохраняют существующее значение.","room.queue_progress":"Комната {current} из {total}","toast.wall_rooms_saved":"Создано комнат: {n}","toast.wall_chain_saved":"Цепочка стен сохранена","toast.wallthick_pick":"Кликните по стене","toast.wallthick_set":"Толщина стены задана","toast.wallthick_cleared":"Толщина стены убрана","toast.physical_range":"Введите значение от {min} до {max} {unit}","toast.zero_wall_opening_conflict":"Сначала удалите проём на этом участке стены.","toast.zero_wall_ambiguous":"Не удалось однозначно выбрать участок стены. Уточните геометрию узла.","toast.zero_wall_migration_blocked":"Пространство не преобразовано: {reason}. Данные не изменены.","toast.physical_angle":"Введите угол поворота от 0° до 90°, не включая 90°","toast.physical_limit":"В пространстве достигнут лимит объектов этого типа","toast.geometry_unsafe":"Изменение отменено: геометрию стен нельзя безопасно построить.","junction.limit_angle":"Слишком острый угол между стенами: {actual}°, минимум {limit}°.","junction.limit_valence":"Слишком много стен в одном узле: {actual}, максимум {limit}.","junction.limit_length":"Слишком короткий участок стены: {actual} см, минимум {limit} см.","junction.limit_distance":"Стены и узлы слишком близко: {actual} см, минимум {limit} см.","junction.limit_clearance":"Внутри комнаты не остаётся места: {actual} см², минимум {limit} см².","junction.limit_check_failed":"Проверку стыков выполнить не удалось — изменение не сохранено","toast.wall_model_migration_blocked":"Не удалось обновить модель стен: {reason}. План не изменён. Запустите «Оптимизировать планы»; если ошибка повторится, исправьте конфликтующую геометрию стен.","toast.wall_model_client_outdated":"Обновите карточку и перезагрузите страницу перед редактированием плана.","wall_model.reason.invalid-room":"некорректный контур комнаты","wall_model.reason.zero-length":"отрезок стены нулевой длины","wall_model.reason.third-owner":"стена принадлежит более чем двум комнатам","wall_model.reason.duplicate-id":"конфликт идентификаторов стен","wall_model.reason.thickness-conflict":"конфликт значений толщины стены","wall_model.reason.opening-host":"проём нельзя однозначно привязать к стене","toast.delete_room_pick":"Кликните внутри комнаты, которую нужно удалить","toast.plan_snap_ambiguous":"Увеличьте масштаб, чтобы выбрать узел стены","toast.wall_repair_ambiguous":"У контура несколько возможных соединений. Увеличьте масштаб и соедините стены явно.","toast.wall_repair_too_large":"Разрыв больше 2 см. Соедините стены перед созданием комнаты.","toast.wall_repair_changed":"Геометрия стен изменилась. Попробуйте создать комнату ещё раз.","toast.opening_on_zero_wall":"Проёмы на стене нулевой толщины запрещены","marker.from_ha_option":"Выбрать из списка HA","marker.show_entities":"Показывать сущности","marker.show_entities_tip":"Добавляет в список не только устройства, но и все их сущности","marker.pick_ph":"Выберите устройство…","room.open_area":"Открыть зону в HA","room.fit_action":"Вписать комнату {name}","view.volumetric":"Объёмный вид","view.flat":"Плоский вид","kiosk.title":"Размеры на этом экране","kiosk.hint":"Хранится только на этом устройстве — у каждого настенного планшета или ТВ свои удобные размеры.","kiosk.icon_scale":"Размер значков устройств","kiosk.font_scale":"Размер текста карточек комнат","editor.kiosk":"Режим настенного устройства (киоск)","editor.cycle":"Автосмена пространств каждые N секунд (киоск, 0 = выкл)","room.settings_title":"Настройки комнаты","room.settings_section":"Настройки комнаты (переопределяют пространство)","room.fill_label":"Заливка в ЭТОЙ комнате","fill.inherit":"Как у пространства","room.custom_fill_space":"Цвет пространства","room.custom_fill_own":"Цвет комнаты","room.temp_range_label":"Диапазон комфорта","room.temp_range_min":"Нижняя граница комфортной температуры","room.temp_range_max":"Верхняя граница комфортной температуры","room.temp_range_reset":"Как у пространства","room.temp_range.help":"Диапазон применяется только к этой комнате. Пустое поле наследует соответствующую границу пространства; если границы поменялись местами, House Plan использует меньшую как нижнюю, а большую как верхнюю.","room.temp_range.help.aria":"О диапазоне комфорта комнаты","room.temp_src_label":"Источник температуры","room.hum_src_label":"Источник влажности","room.src_average":"Средняя по датчикам комнаты (по умолчанию)","room.src_pick":"Конкретное устройство или сущность HA","room.src_ph":"Выберите источник…","toast.room_updated":"Комната обновлена","space.card_font":"Размер шрифта карточек комнат (всё пространство)","room.sizes_section":"Размеры шрифтов","room.name_scale":"Размер названия","room.label_scale":"Размер подписей","preview.room_name":"Гостиная","toast.cfg_reload_failed":"Не удалось перечитать план с сервера: {err}","toast.locale_load_failed":"Не удалось загрузить языковой пакет. До перезагрузки страницы используется английский.","toast.furniture_art_load_failed":"Не удалось загрузить изображения мебели. Обновите страницу, чтобы их показать.","room.settings_short":"Настройки комнаты","room.unnamed":"Комната без имени","marker.use_climate_temp":"Учитывать температуру устройства в комнате","marker.use_climate_temp_tip":"Добавляет current_temperature кондиционера или термостата в среднюю температуру комнаты. Внешний бейдж со значением настраивается отдельно ниже.","marker.value_badge_title":"Бейдж со значением","marker.value_badge.help":"Показывает одно выбранное значение рядом со значком. Не влияет на комнатные показатели, свет, Glow и действие по нажатию.","marker.value_badge.help.aria":"Подсказка: бейдж со значением устройства","marker.value_badge_enabled":"Отображать бейдж со значением","marker.value_badge_source":"Значение","marker.value_badge_source.help":"Выберите конкретное состояние, поддерживаемый атрибут или производное значение этого устройства.","marker.value_badge_source.help.aria":"Подсказка: источник значения бейджа","marker.value_badge_position":"Расположение","marker.value_badge_position.help":"Выбранная сторона сохраняется постоянно и не переворачивается автоматически у края плана.","marker.value_badge_position.help.aria":"Подсказка: расположение бейджа","marker.value_badge_right":"Справа","marker.value_badge_bottom":"Снизу","marker.value_badge_left":"Слева","marker.value_badge_top":"Сверху","marker.value_badge_empty":"У этого устройства нет доступных значений","marker.value_badge_static":"Статичный значок не показывает живые значения. Настройка сохранится.","marker.value_badge_missing":"Источник недоступен","marker.value_badge_missing_hint":"Сохранённый источник сейчас недоступен. Можно сохранить его, отключить бейдж или выбрать другой.","marker.value_badge_duplicate":"То же значение уже показано внутри значка.","marker.value_badge_state":"Состояние · {name}","marker.value_badge_marker_state":"Состояние источника света · {name}","marker.value_badge_lqi":"Качество Zigbee-сигнала (среднее)","marker.value_badge_attr_current_temperature":"Текущая температура · {name}","marker.value_badge_attr_temperature":"Целевая температура · {name}","marker.value_badge_attr_current_humidity":"Текущая влажность · {name}","marker.value_badge_attr_humidity":"Влажность · {name}","marker.value_badge_attr_current_position":"Положение · {name}","marker.value_badge_attr_percentage":"Скорость · {name}","marker.value_badge_attr_brightness":"Яркость · {name}","marker.value_badge_attr_volume_level":"Громкость · {name}","marker.value_badge_attr_battery_level":"Заряд батареи · {name}","marker.value_badge_attr_fan_speed":"Скорость вентилятора · {name}","marker.value_source":"Источник значения","marker.value_source.help":"Выберите, что заменит значок. Действие по нажатию не изменится.","marker.value_source.help.aria":"Подсказка: источник значения внутри значка","marker.value_source_auto":"Автоматически (как раньше)","marker.value_source_missing_hint":"Сохранённый источник сейчас недоступен. До его восстановления или выбора другого значения внутри будет показано —.","marker.light_role_label":"Является источником света","marker.light_role.help":"«Авто» использует фактическую роль привязанного устройства, «Всегда» принудительно создаёт собственный источник, а «Никогда» исключает его; связанные лампы выше остаются независимыми.","marker.light_role.help.aria":"Подсказка: является ли устройство источником света","marker.light_role_auto_yes":"Автоматически (источник света)","marker.light_role_auto_no":"Автоматически (не источник света)","marker.light_role_always":"Всегда источник света","marker.light_role_never":"Никогда не источник света","marker.light_entity_label":"Ведущая сущность света","marker.light_entity.help":"Для составного устройства выберите сущность, состояние, цвет и яркость которой представляют этот источник на плане. Автоматический вариант сохраняет совместимость со старыми планами.","marker.light_entity.help.aria":"Подсказка: ведущая сущность света","marker.light_entity_auto":"Автоматически ({entity})","marker.light_entity_none":"нет управляемой сущности","marker.light_entity_missing":"Сохранённая сущность {entity} недоступна. Временно используется {fallback}; выбор восстановится, если сущность вернётся.","marker.toggle_entity_label":"Переключаемая сущность","marker.toggle_entity.help":"Для составного устройства выберите собственную лампу или переключатель, которой управляет нажатие. Автоматический вариант сохраняет прежние правила цели и не зависит от ведущей сущности света.","marker.toggle_entity.help.aria":"Подсказка: переключаемая сущность","marker.toggle_entity_auto":"Автоматически ({entity})","marker.toggle_entity_none":"нет собственной управляемой сущности","marker.toggle_entity_missing":"Сохранённой сущности {entity} больше нет среди выбираемых каналов этого маркера. Временно используется {fallback}; выбор восстановится, если сущность вернётся.","marker.glow_color_label":"Цвет и яркость свечения","marker.glow_mode.help":"Используйте данные источника, задайте только цвет или зафиксируйте цвет и яркость. Минимум — 1%; чтобы отключить источник, выберите «Никогда».","marker.glow_mode.help.aria":"Подсказка: цвет и яркость свечения","marker.glow_mode_auto":"Из источника","marker.glow_mode_color":"Задать цвет","marker.glow_mode_fixed":"Задать цвет и яркость","marker.glow_color":"Цвет свечения","marker.glow_brightness":"Яркость","marker.glow_disabled_never":"Настройки свечения недоступны: маркер явно исключён из источников света.","marker.glow_disabled_auto":"В автоматическом режиме у этого маркера не найден пространственный источник света.","marker.glow_disabled_no_entity":"Для пространственного источника нет активной управляемой сущности Home Assistant.","marker.glow_passive_hint":"У источника нет собственных данных Home Assistant. Задайте цвет и яркость вручную; радиус остаётся доступным.","marker.control_broken":"Сохранённый источник отсутствует или больше не отмечен как источник света","marker.control_missing_label":"Отсутствующий источник на плане","marker.control_passive":"пассивный источник","toast.marker_control_cycle":"Такая связь создаст циклическую цепочку управления светом.","toast.marker_binding_required":"Сначала выберите устройство Home Assistant, затем добавьте управляемый источник света.","confirm.unlock_title":"Открыть замок?","confirm.unlock_body":"House Plan отправит этому замку команду открытия.","toast.files_migrate_failed":"Не удалось перенести вложения к новой привязке, ссылки остались на старые файлы: {err}","space.pick_saved":"Уже загруженные","space.pick_saved_hint":"Планы, сохранённые на сервере, включая отцеплённые ранее","space.no_saved":"На сервере пока нет сохранённых планов.","space.loading":"Загрузка…","space.used_by":"используется: {list}","space.in_use":"План используется пространством — сначала отцепите его","btn.use":"Выбрать","confirm.delete_plan_title":"Удалить файл плана?","confirm.delete_plan_body":"Файл будет удалён с сервера. Это действие нельзя отменить.","toast.plans_list_failed":"Не удалось получить список планов: {err}","toast.plan_delete_failed":"Не удалось удалить план: {err}","marker.hide":"Скрыть","marker.hide_tip":"Устройство исчезнет с плана после сохранения, но продолжит участвовать в расчёте сигнала комнаты. Вернуть его можно через каталог «Устройства» в редакторе устройств.","marker.show":"Показать","marker.show_tip":"Устройство снова появится на плане после сохранения.","marker.hidden_ghost":"Устройство скрыто пользователем","marker.ha_disabled_device":"Устройство деактивировано в Home Assistant и скрыто с плана.","marker.ha_disabled_entity":"Сущность деактивирована в Home Assistant и скрыта с плана.","marker.ha_disabled_all_entities":"У устройства нет активных сущностей Home Assistant, поэтому оно скрыто с плана.","marker.ha_registry_limited":"Полный реестр Home Assistant недоступен этому пользователю. Неподтверждённый объект временно нельзя показывать или использовать.","marker.delete_tip":"Полностью удалить устройство с плана и из всех расчётов. Позже его можно добавить заново.","tap.run":"Запустить автоматизацию/скрипт/сцену","tap.none":"Ничего не делать","marker.run_target_label":"Что запускать","marker.run_search_ph":"Поиск: автоматизация, скрипт или сцена…","marker.run_target_gone":"Цель {id} не найдена — выберите заново","marker.tap_confirm":"Спрашивать подтверждение","marker.tap_confirm_tip":"Перед выполнением показать диалог подтверждения — защита от случайных нажатий.","marker.toggle_hint_single":"Цель: {name} ({id}).","marker.virtual_light_target":"Виртуальный свет: {name}.","marker.virtual_light_current":"Ручное состояние: {state} → {effect}.","marker.virtual_light_state_on":"включён","marker.virtual_light_state_off":"выключен","marker.toggle_hint_group":"Переключатся источники ({count}): {names}.","marker.toggle_hint_current":"Сейчас: {state} → {effect}.","marker.toggle_hint_group_current":"Сейчас включено {on} из {count} → {effect}.","marker.toggle_hint_skipped":"Не будут затронуты ({count}): {targets}.","marker.toggle_effect_turn_on":"включится","marker.toggle_effect_turn_off":"выключится","marker.toggle_effect_open":"откроется","marker.toggle_effect_close":"закроется","marker.toggle_effect_stop":"остановится","marker.toggle_effect_toggle":"состояние переключится","marker.toggle_skip_missing":"не найдено","marker.toggle_skip_ha_disabled":"деактивировано в HA","marker.toggle_skip_unavailable":"недоступно","marker.toggle_skip_unsupported":"переключение не поддерживается","marker.toggle_skip_secure":"заблокировано из соображений безопасности","marker.toggle_none_no_binding":"У устройства нет привязки, состояние переключать нечем. По нажатию ничего не произойдёт.","marker.toggle_none_no_actionable_entity":"У устройства нет состояния, которое можно переключить. По нажатию ничего не произойдёт.","marker.toggle_none_configured_targets_missing":"Настроенные цели сейчас недоступны. Собственная сущность устройства не будет подставлена вместо них.","marker.toggle_none_ha_disabled":"Цель деактивирована в Home Assistant и не может использоваться на плане.","marker.toggle_none_unavailable":"Цель сейчас недоступна. По нажатию ничего не произойдёт.","marker.toggle_none_unsupported":"Для этой сущности Home Assistant не предоставляет безопасного переключения. По нажатию ничего не произойдёт.","marker.toggle_none_secure":"Переключение замков, сигнализации и защитных ворот с плана заблокировано из соображений безопасности.","run.automation":"автоматизация","run.script":"скрипт","run.scene":"сцена","confirm.tap_run":"Запустить «{name}»?","confirm.tap_toggle":"Переключить «{name}»?","confirm.current_state":"Текущее состояние: {state}","confirm.expected_state":"После переключения: {state}","confirm.group_current":"включено {on} из {total}","confirm.group_all_on":"все включены","confirm.group_all_off":"все выключены","confirm.unavailable_targets":"Недоступно: {count}","confirm.expected_by_ha":"Состояние определит Home Assistant","confirm.state_on":"Включено","confirm.state_off":"Выключено","confirm.state_open":"Открыто","confirm.state_closed":"Закрыто","confirm.state_opening":"Открывается","confirm.state_closing":"Закрывается","confirm.state_stopped":"Остановлено","confirm.state_unknown":"Неизвестно","toast.run_started":"Запущено: {name}","toast.run_target_missing":"Цель запуска не найдена — проверьте настройки устройства","toast.run_target_required":"Выберите автоматизацию, скрипт или сцену","toast.tap_target_changed":"Цель действия изменилась. Повторите попытку.","toast.virtual_light_toggle_failed":"Не удалось переключить виртуальный свет: {err}","toast.value_badge_source_required":"Выберите значение для бейджа","btn.run":"Выполнить","vac.section":"Робот-пылесос: живая позиция","vac.autocal":"Настроить автоматически","vac.live":"Живая позиция на плане","vac.trail":"Показывать путь робота","vac.autocal_no_rooms":"Интеграция не отдаёт список комнат — откройте «Подогнать вручную»","vac.route_warn_unmapped":"Робот убирает на карте, которая не сопоставлена ни одному этажу","vac.route_warn_needs_calibration":"Карта сопоставлена этажу, но не откалибрована","vac.route_warn_ambiguous":"Две карты неразличимы — этаж не выбран","vac.route_warn_missing_space":"Пространство этой карты удалено","vac.autocal_no_match":"Не совпали имена комнат (нужно ≥3 общих) — откройте «Подогнать вручную»","vac.autocal_done":"Готово: привязка по {rooms} комнатам. Запустите уборку и проверьте","vac.cal_need_pos":"Робот сейчас не отдаёт координаты — запустите уборку и поставьте на паузу","vac.cal_done":"Калибровка сохранена. Запустите уборку и проверьте","vac.cal_cancelled":"Калибровка отменена","vac.fit":"Подогнать вручную","vac.fit_hint":"Перетащите карту робота на место, растяните за уголки","vac.fit_rotate":"Повернуть 90°","vac.fit_mirror":"Отразить","vac.trail_never":"Не показывать никогда","vac.trail_cleaning":"Во время уборки","vac.trail_always":"Показывать всегда","gs.bg_group":"Фон сцены","gs.bg_color":"Цвет фона вокруг плана","gs.bg_default":"Как в теме","gs.bg_theme":"по умолчанию — из темы","gs.bg_mode":"Фон плана","gs.bg_mode.help":"«Следует за Солнцем» использует sun.sun, а при недоступности — локальные часы браузера; статичный режим всегда показывает выбранный цвет.","gs.bg_mode.help.aria":"Подсказка: общий фон плана","gs.bg_static":"Статичный цвет","gs.bg_daynight":"Следует за Солнцем","gs.sun_group":"Солнце","gs.sun_missing":"Сущность sun.sun не найдена — фон следует локальным часам, а оконные лучи недоступны.","gs.north":"Север на плане","gs.north.help":"Угол отсчитывается по часовой стрелке от верхней вертикали плана; север нужен для оконных лучей, а не для фона «Следует за Солнцем».","gs.north.help.aria":"Подсказка: общее направление севера","gs.north_ph":"не задан","gs.north_clear":"Сбросить","gs.north_letter":"С","gs.sun_rays":"Солнце в окнах","gs.about_version":"Houseplan Card v{v}","gs.about_github":"GitHub · документация и issues","gs.about_telegram":"Чат в Telegram","support.title":"Помощь и обратная связь","space.bg_color":"Цвет фона вокруг плана","space.bg_inherit":"Наследовать общий","space.bg_inherited":"наследуется из общих настроек","space.bg_mode":"Фон плана","space.bg_mode.help":"Выберите наследование общего фона либо переопределите это пространство статичным цветом или режимом «Следует за Солнцем».","space.bg_mode.help.aria":"Подсказка: фон пространства","space.north":"Север на плане (переопределение)","space.north.help":"Переопределяет общий север для этого пространства; угол отсчитывается по часовой стрелке от верхней вертикали плана и используется оконными лучами.","space.north.help.aria":"Подсказка: север для пространства","space.north_inherited":"наследуется: {v}","space.sun_rays":"Солнце в окнах","space.sun_inherit":"Наследовать общий","space.sun_on":"Вкл","space.sun_off":"Выкл","canvas.far_objects":"Объектов далеко от плана: {n}","canvas.show_far":"Показать","canvas.home_tip":"План там — нажмите, чтобы вписать","gs.grid_group":"Обслуживание планов","gs.grid_hint":"Обновляет модели данных, выравнивает элементы по сетке и объединяет лишние фрагменты стен. Перед записью будет показан точный отчёт.","gs.align_all":"Оптимизировать планы","gs.align_title":"Оптимизировать планы","gs.align_none":"Все планы уже используют актуальную и оптимальную модель данных.","gs.optimize_no_automatic_changes":"Автоматических изменений нет. Проверьте пункты ниже.","gs.align_count":"Сдвинется элементов: {n} из {total}, максимум на {cm} см.","gs.align_where":"Наибольший сдвиг — в пространстве «{s}».","gs.align_turned":"Проёмов с исправлением угла: {n}.","gs.align_preflight_failed":"Не удалось безопасно проверить геометрию следующих пространств: {spaces}{more}.","gs.align_preflight_hint":"Планы не изменены. Скопируйте диагностику кнопкой ниже и приложите её к отчёту об ошибке вместе с экспортом пространства.","gs.preflight_reason_prepare-exception":"Не удалось подготовить геометрию пространства (исключение при сборке модели)","gs.preflight_reason_wall-null":"Тело стен не построилось (объединение вернуло пустоту)","gs.preflight_reason_wall-degraded-extra":"Тело стен деградировало с лишней геометрией","gs.preflight_reason_wall-failed-core":"Ядро тела стен не собралось","gs.preflight_reason_wall-exception":"Построение стен упало с исключением","gs.preflight_reason_floor-null":"Контур пола не построился","gs.preflight_reason_floor-exception":"Построение пола упало с исключением","gs.preflight_copy":"Скопировать диагностику","gs.preflight_copied":"Диагностика скопирована","gs.preflight_update_hint":"Версии карточки и интеграции различаются — обновите House Plan и повторите.","gs.align_preflight_space":"Пространство {n}","gs.align_preflight_more":" и ещё {n}","gs.optimize_changes":"Миграций модели: {m}; обновлено пространств: {c}; устранён шум координат: {p}; объединено отрезков реальных стен: {w}; объединено отрезков стен нулевой толщины: {s}; независимых: {i}.","gs.zero_walls_migrated":"Преобразовано виртуальных участков: {n}.","gs.wall_segments_migrated":"Стабилизировано сегментов стен: {n}.","gs.room_drafts_migrated":"Незавершённые контуры преобразованы в обычные стены: {drafts}; отрезков: {segments}.","gs.optimize_lattice_summary":"Канонизировано шумовых значений координат: {n}; максимальный сдвиг: {cm} см.","gs.optimize_lattice_space":"{space}: канонизировано значений координат: {n}; оставлено значений вне сетки: {far}.","gs.optimize_coincident_partitions":"Скрытые участки независимых стен поглощены стенами комнат: {n}.","gs.optimize_openings_rehosted":"Проёмы перепривязаны к стенам комнат: {n}.","gs.optimize_walls_straightened":"Выпрямлено стен: {n}; максимальное перемещение: {cm} см.","gs.optimize_walls_straightened_where":"Максимальная правка стены: {s}.","gs.optimize_walls_straighten_skipped":"Оставлено почти осевых стен, которые нельзя безопасно выпрямить: {n}.","gs.optimize_glow_migration":"Старый Glow: пространств — {spaces} → без заливки данных + независимый Glow; комнат — {rooms} → наследуемая заливка + независимый Glow.","gs.optimize_references":"Исправлено ссылок: пространства — {spaces}; комнаты — {rooms}; позиции — {positions}; устройств отвязано от отсутствующих пространств — {detached}.","gs.optimize_reference_more":", и ещё {n}","gs.optimize_orphans_removed":"Убрано забытых записей: {total} — подписи комнат: {rooms}; устройства: {devices}; групповые метки: {groups}. Все они принадлежали пространствам, удалённым ранее.","gs.optimize_live_positions":"Старые позиции в удалённых пространствах принадлежат существующим объектам: {n}{names}. Они будут сохранены.","gs.optimize_live_positions_remove":"Старые позиции в удалённых пространствах принадлежат существующим объектам: {n}{names}. Они выбраны для удаления.","gs.optimize_live_names":": {names}{more}","gs.optimize_live_remove":"Убрать старые позиции","gs.optimize_live_keep":"Сохранить старые позиции","gs.optimize_live_selected":"Старые позиции будут убраны после применения оптимизации.","gs.optimize_unverified":"Не удалось безопасно проверить позиций: {n}. Они оставлены без изменений.","gs.optimize_registry_limited":"Для безопасной проверки нужен полный доступ администратора к реестрам Home Assistant.","gs.optimize_vacuum_warning":"Сопоставления комнат пылесоса требуют проверки: {n}.","gs.optimize_details":"Подробности","gs.optimize_details_more":"И ещё записей: {n}.","gs.optimize_detail_removed":"будет удалено","gs.optimize_detail_live":"будет сохранено","gs.optimize_detail_unverified":"не проверено","gs.optimize_detail_room_label":"подпись комнаты","gs.optimize_detail_device":"устройство","gs.optimize_detail_group":"групповая метка","gs.optimize_detail_unknown":"неизвестный владелец","gs.optimize_detail_item":"{status}: {kind} {id}; прежнее пространство {space}","gs.align_warn":"Элементы, намеренно поставленные между узлами, будут сдвинуты. После операции доступна одна отмена — только до следующего изменения плана.","gs.align_run":"Оптимизировать","gs.align_done":"Планы оптимизированы: сдвинуто элементов — {n}, обслужено записей — {m}, исправлено ссылок — {r}","gs.optimize_undo":"Отменить последнюю оптимизацию","gs.optimize_undone":"Последняя оптимизация отменена","decor.furniture":"Мебель","decor.image":"Изображение","decor.image_title":"Свои изображения","decor.image_upload":"Загрузить изображение","decor.image_replace":"Заменить изображение","decor.image_uploading":"Загрузка…","decor.image_asset":"Файл изображения","decor.image_pick_hint":"Загрузите изображение или выберите уже используемое в House Plan.","decor.image_place_hint":"Кликните по плану, чтобы разместить изображение.","decor.image_none":"Загруженных изображений пока нет.","decor.image_unavailable":"Изображение недоступно","decor.image_used":"Используется в объектах: {n}","decor.image_upload_failed":"Не удалось загрузить изображение: {err}","decor.image_error_capacity":"Хранилище пользовательских изображений заполнено.","decor.image_in_use":"Перед удалением файла удалите все размещённые копии.","decor.image_delete_title":"Удалить файл изображения?","decor.image_delete_message":"Удалить «{name}» из House Plan? Это действие нельзя отменить.","furn.title":"Библиотека мебели","furn.symbol":"Символ","furn.group_furniture":"Мебель","furn.group_appliance":"Техника","furn.group_sanitary":"Сантехника","furn.group_other":"Прочее","furn.width":"Ширина","furn.depth":"Глубина","furn.back_to_categories":"Все категории","furn.pick_hint":"Выберите категорию, затем символ.","furn.place_hint":"Кликните по плану — предмет встанет к ближайшей стене. Shift — свободно.","furn.cat_air_conditioner":"Кондиционеры","furn.cat_armchair":"Кресла","furn.cat_bathtub":"Ванны","furn.cat_bed":"Кровати","furn.cat_bidet":"Биде","furn.cat_boiler":"Бойлеры","furn.cat_chair":"Стулья","furn.cat_coffee_table":"Журнальные столы","furn.cat_cooktop":"Варочные панели","furn.cat_dining_table":"Обеденные столы","furn.cat_dishwasher":"Посудомоечные машины","furn.cat_dryer":"Сушильные машины","furn.cat_fireplace":"Камины","furn.cat_fridge":"Холодильники","furn.cat_kitchen_cabinet":"Кухонные шкафы","furn.cat_kitchen_sink":"Кухонные мойки","furn.cat_nightstand":"Тумбы","furn.cat_plant":"Растения","furn.cat_rug":"Ковры","furn.cat_shelving":"Стеллажи","furn.cat_shower":"Душевые","furn.cat_sink":"Раковины","furn.cat_sofa":"Диваны","furn.cat_stairs":"Лестницы","furn.cat_toilet":"Унитазы","furn.cat_tv":"Телевизоры","furn.cat_wardrobe":"Шкафы","furn.cat_washer":"Стиральные машины","furn.cat_work_table":"Рабочие столы","furn.sym_sofa":"Диван двухместный","furn.sym_sofa_three_seat":"Диван трёхместный","furn.sym_sofa_corner_right":"Угловой диван, правый","furn.sym_armchair":"Кресло мягкое","furn.sym_armchair_office":"Кресло офисное","furn.sym_coffee_table":"Журнальный стол, прямоугольный","furn.sym_coffee_table_round":"Журнальный стол, круглый","furn.sym_coffee_table_oval":"Журнальный стол, овальный","furn.sym_coffee_table_rounded":"Журнальный стол, скруглённый","furn.sym_table_dining":"Обеденный стол, прямоугольный","furn.sym_table_round":"Круглый стол","furn.sym_table_dining_oval":"Обеденный стол, овальный","furn.sym_table_dining_rounded":"Обеденный стол, скруглённый","furn.sym_chair":"Стул","furn.sym_chair_bar":"Барный стул","furn.sym_desk":"Рабочий стол, прямоугольный","furn.sym_desk_corner":"Рабочий стол, угловой","furn.sym_bed_double":"Двуспальная кровать","furn.sym_bed_single":"Односпальная кровать","furn.sym_nightstand":"Тумба прикроватная","furn.sym_cabinet_tv":"Тумба под телевизор","furn.sym_cabinet_shoe":"Тумба для обуви","furn.sym_cabinet_sink":"Тумба под раковину","furn.sym_wardrobe":"Шкаф гардеробный","furn.sym_bookshelf":"Шкаф книжный","furn.sym_wall_unit":"Шкаф-стенка","furn.sym_kitchen_floor":"Кухонный напольный модуль","furn.sym_kitchen_floor_corner":"Кухонный напольный угловой модуль","furn.sym_kitchen_wall":"Кухонный навесной модуль","furn.sym_kitchen_wall_corner":"Кухонный навесной угловой модуль","furn.sym_shelf_floor":"Стеллаж напольный","furn.sym_shelf_wall":"Полка настенная","furn.sym_fridge":"Холодильник","furn.sym_stove":"Варочная панель, 4 конфорки","furn.sym_cooktop_two":"Варочная панель, 2 конфорки","furn.sym_dishwasher":"Посудомоечная машина","furn.sym_washer":"Стиральная машина","furn.sym_dryer":"Сушильная машина","furn.sym_tv":"Телевизор на подставке","furn.sym_tv_wall":"Телевизор на кронштейне","furn.sym_ac":"Кондиционер","furn.sym_water_heater":"Бойлер","furn.sym_toilet":"Унитаз напольный","furn.sym_toilet_built_in":"Унитаз встроенный","furn.sym_bathtub":"Ванна прямоугольная","furn.sym_bathtub_corner":"Ванна угловая","furn.sym_shower":"Душ","furn.sym_sink":"Раковина","furn.sym_kitchen_sink":"Кухонная мойка одинарная","furn.sym_kitchen_sink_double":"Кухонная мойка двойная","furn.sym_bidet":"Биде напольное","furn.sym_bidet_built_in":"Биде встроенное","furn.sym_stairs":"Лестница","furn.sym_fireplace":"Камин","furn.sym_plant":"Растение","furn.sym_rug":"Ковёр","common.yes":"Да","common.no":"Нет","vac.diag_source":"Источник","vac.diag_platform":"Интеграция","vac.diag_status":"Статус","vac.diag_position":"Позиция","vac.diag_rooms":"Комнаты","vac.diag_rooms_value":"{total} · совпало имён: {matched} · {readiness}","vac.autocal_ready":"автокалибровка доступна","vac.autocal_not_ready":"нужно 3 совпавших имени","vac.diag_path":"Путь интеграции","vac.diag_map":"ID карты","vac.source_none":"не выбран","vac.source_status_ok":"Готов","vac.source_status_missing":"Не найден","vac.source_status_disabled":"Деактивирован в Home Assistant","vac.source_status_unavailable":"Недоступен","vac.source_status_unverified":"Нельзя проверить с текущими правами","vac.source_status_unsupported":"Нет данных позиции","vac.source_status_none":"Нет источника","vac.source_banner_missing":"Сохранённый источник больше не существует. Он не заменён автоматически: выберите другой или восстановите его в Home Assistant.","vac.source_banner_disabled":"Сохранённый источник деактивирован в Home Assistant. Активируйте его там или выберите другой.","vac.source_banner_unverified":"Текущих прав Home Assistant недостаточно для проверки источника. Привязка сохранена и не будет заменена автоматически.","vac.choose_source":"Выбрать источник","vac.source_auto":"Автоматически","vac.source_auto_hint":"Использовать совместимую сущность этого устройства","vac.all_cameras":"Все камеры","vac.all_cameras_warn":"Камера может не отдавать данные робота. Выбирайте её только если это карта вашего пылесоса.","vac.all_cameras_empty":"Других сущностей камеры не найдено.","vac.platform_unknown":"интеграция неизвестна","vac.cap_position":"позиция","vac.cap_rooms_short":"комнаты","vac.cap_path":"путь","vac.cap_map":"ID карты","vac.cap_none":"данные робота не обнаружены","vac.xcme_hint":"Включите атрибуты Xiaomi Cloud Map Extractor:","vac.documentation":"Документация","vac.residual_title":"Проверьте автокалибровку","vac.residual_message":"Совпавшие комнаты расходятся максимум на {error}. Примените приблизительную калибровку, подгоните её вручную либо отмените без изменения сохранённых настроек.","vac.apply_proposal":"Применить","gs.backup_group":"Резервная копия и перенос","gs.backup_hint":"Скачайте переносимую JSON-копию или проверьте и импортируйте копию, созданную House Plan.","backup.export_open":"Экспорт","backup.import_open":"Импорт","backup.export_title":"Экспорт House Plan","backup.import_title":"Импорт House Plan","backup.export_hint":"Выберите, должна ли копия содержать всю конфигурацию House Plan или только текущее пространство.","backup.full":"Полная копия","backup.current_space":"Текущее пространство","backup.current_space_title":"Текущее пространство: {title}","backup.no_current_space":"Нет текущего пространства","backup.plan_only":"Только планировка","backup.plan_only_hint":"Сохранить комнаты, стены, проёмы, декор и позиции подписей комнат без устройств и привязок Home Assistant.","backup.plan_only_preview":"Файл содержит только планировку","backup.privacy_warning":"Архив сохраняет названия, идентификаторы Home Assistant и точные координаты. Внутренние планы и вложения указываются ссылками, но не вкладываются; текущие состояния и маршруты пылесосов не включаются.","backup.download":"Скачать JSON","backup.export_done":"Резервная копия скачана","backup.reading":"Проверяем резервную копию…","backup.revalidated":"После предпросмотра план изменился. Сводка обновлена — проверьте её и подтвердите ещё раз.","backup.error.support_invalid_message":"Проверьте сообщение для поддержки и повторите попытку.","backup.error.support_package_too_large":"Обезличенный пакет для поддержки превышает лимит 8 МиБ.","backup.error.support_preview_expired":"Предпросмотр вложения для поддержки истёк или больше недоступен.","backup.error.support_rate_limited":"Запрошено слишком много репортов или предпросмотров. Повторите позже.","backup.error.support_rejected":"Репорт не прошёл проверку службы поддержки.","backup.error.support_unavailable":"Закрытая служба поддержки временно недоступна.","backup.error.unauthorized":"У вас нет прав на экспорт или импорт этого плана.","backup.error.not_ready":"House Plan ещё не готов. Повторите попытку через несколько секунд.","backup.error.too_large":"Размер резервной копии превышает 8 МиБ.","backup.error.invalid_json":"Выбранный файл не является корректным JSON.","backup.error.invalid_format":"Выбранный файл не является резервной копией House Plan.","backup.error.invalid_image":"Изображение повреждено или не соответствует своему формату.","backup.error.unsupported_export_version":"Эта версия формата резервной копии не поддерживается установленной версией.","backup.error.unsupported_image":"Используйте поддерживаемое изображение PNG, JPEG, WebP или SVG.","backup.error.future_model":"Резервная копия создана в более новой версии модели данных House Plan.","backup.error.invalid_config":"Резервная копия содержит некорректную конфигурацию House Plan.","backup.error.wall_model_migration_blocked":"Не удалось безопасно обновить модель стен из резервной копии. Сначала оптимизируйте исходный план и повторите экспорт.","backup.error.invalid_layout":"Резервная копия содержит некорректные позиции объектов.","backup.error.invalid_content":"Резервная копия содержит некорректные или несогласованные ссылки на файлы.","backup.error.space_not_found":"Выбранное пространство больше не существует.","backup.error.capacity_exceeded":"Добавление этой копии превысит ограничения размера плана.","backup.error.preview_expired":"Время предпросмотра истекло. Выберите файл резервной копии заново.","backup.error.preview_owner_mismatch":"Этот предпросмотр принадлежит другому пользователю Home Assistant.","backup.error.conflict":"После предпросмотра план изменился. Проверьте обновлённую сводку.","backup.error.content_confirmation_required":"Подтвердите отсоединение недоступных локальных файлов.","backup.error.commit_failed":"Не удалось безопасно применить копию. Предыдущий план восстановлен или ожидает восстановления.","backup.error.missing_plan":"После предпросмотра исчез связанный файл плана. Проверьте копию ещё раз.","backup.error.missing_content":"После предпросмотра исчез связанный локальный файл. Проверьте копию ещё раз.","backup.error.marker_control_missing":"В резервной копии отсутствует связанный источник света на плане.","backup.error.marker_control_not_light":"Связанная цель больше не отмечена как источник света.","backup.error.marker_control_self":"Источник света не может управлять самим собой.","backup.error.marker_control_cycle":"Резервная копия содержит циклическую цепочку управления светом.","backup.error.duplicate_marker_control":"Резервная копия содержит повторяющуюся связь с источником света.","backup.error.no_backup":"Нет снимка импорта или оптимизации, который можно восстановить.","backup.error.in_use":"Элемент ещё используется","backup.error.invalid_data":"Запрос содержит некорректные данные","backup.error.invalid_light_entity":"Ведущий свет должен быть сущностью light.* или switch.*","backup.error.invalid_marker_control":"Некорректная ссылка управления маркером","backup.error.invalid_name":"Некорректное имя","backup.error.invalid_partition_opening_host":"Проём должен сохранить свою перегородку-носитель","backup.error.invalid_partition_opening_jamb_margin":"Проём не оставляет физического простенка у края стены","backup.error.invalid_passage_fields":"Открытый проход не может нести настройки двери","backup.error.invalid_space_id":"Неизвестное пространство","backup.error.invalid_toggle_entity":"Сущность переключения должна быть light.* или switch.*","backup.error.invalid_value_badge":"Некорректные настройки бейджа значения","backup.error.invalid_value_badge_attribute":"Некорректный атрибут бейджа значения","backup.error.invalid_value_badge_position":"Некорректная позиция бейджа значения","backup.error.invalid_value_badge_source":"Некорректный источник бейджа значения","backup.error.invalid_vacuum_map_route":"Проверьте сопоставление карт робота пространствам.","backup.error.invalid_value_source":"Некорректный источник значения","backup.error.invalid_value_source_attribute":"Некорректный атрибут источника значения","backup.error.io_error":"Файловая операция на сервере не удалась","backup.error.not_toggleable":"Это устройство нельзя переключить","backup.error.nothing_to_repair":"Нечего чинить","backup.error.space_in_use":"На пространство ещё есть ссылки","backup.error.value_badge_source_required":"Бейджу значения нужен источник","backup.error.wall_model_client_outdated":"План обновлён в другом месте — перезагрузите страницу","backup.same_source":"Создано на этом экземпляре Home Assistant","backup.foreign_source":"Создано на другом экземпляре Home Assistant","backup.created":"Создано: {value}","backup.versions":"Карточка {card}; интеграция {integration}; модель данных {model}","backup.count_spaces":"Пространств: {n}","backup.count_rooms":"Комнат: {n}","backup.count_walls":"Стен: {n}","backup.count_openings":"Проёмов: {n}","backup.count_decor":"Объектов декора: {n}","backup.count_markers":"Устройств: {n}","backup.count_layout":"Позиций: {n}","backup.bindings":"Привязки — устройства: {device}, сущности: {entity}, виртуальные: {virtual}; позиций без пространства: {legacy}","backup.binding_status":"Статус на целевом экземпляре — активных: {active}, деактивированных: {disabled}, отсутствующих: {missing}","backup.missing_areas":"На целевом экземпляре отсутствуют зоны: {areas}","backup.dropped_marker_links":"Связи с источниками света вне переносимого пространства пропущены: {n}.","backup.room_drafts_migrated":"Старые незавершённые контуры преобразованы в обычные стены: {drafts}; отрезков: {segments}.","backup.repaired_target_refs":"Существующих ссылок восстановлено этим импортом: {n}.","backup.preserved_unresolved_refs":"Неоднозначные ссылки сохранены без изменений: {n}.","backup.preserved_unresolved_hint":"House Plan ничего не угадывал и не удалял. После импорта запустите «Оптимизировать планы», чтобы проверить оставшиеся ссылки.","backup.import_details":"Подробности восстановления ссылок","backup.import_detail.incoming_remapped":"Ссылок обновлено внутри импортируемой копии: {n}","backup.import_detail.target_repaired":"Существующих ссылок восстановлено: {n}","backup.import_detail.preserved_unresolved":"Неразрешимых ссылок сохранено: {n}","backup.import_detail.collisions":"Конфликтов назначения безопасно сохранено: {n}","backup.import_detail.dropped_links":"Входящих связей пропущено по правилам переноса: {n}","backup.import_detail.bounded_lineages":"Чрезмерно вложенных идентификаторов ограничено: {n}","backup.replace_warning":"Текущая конфигурация и расположение будут заменены. Загруженные файлы не удаляются. Одну отмену можно выполнить до следующего изменения плана.","backup.foreign_bookkeeping":"Служебные списки известных и новых устройств другого экземпляра импортированы не будут.","backup.final_name":"Название нового пространства","backup.target_settings":"Глобальные настройки целевого экземпляра не изменятся.","backup.duplicates":"Уже существующих привязок: {n}","backup.skip":"Пропустить повторяющиеся устройства","backup.virtual_copy":"Добавить безопасные статичные виртуальные копии","backup.content":"Связанное содержимое","backup.decor_images_summary":"Свои изображения: объектов — {objects}, файлов — {assets}; отсутствует файлов — {missing}.","backup.content_available":"доступно локально","backup.content_external":"внешняя ссылка","backup.content_detach_required":"будет отвязано","backup.confirm_detach":"Я понимаю, что недоступные внутренние планы и вложения будут отвязаны от импортируемой конфигурации.","backup.confirm_missing_images":"Я понимаю, что отсутствующие свои изображения останутся восстанавливаемыми заглушками, а остальные недоступные локальные файлы будут отвязаны.","backup.replace":"Заменить","backup.add":"Добавить пространство","backup.space_done":"Пространство импортировано: комнат — {rooms}, устройств — {markers}, существующих ссылок восстановлено — {refs}","backup.full_done":"Копия восстановлена: пространств — {spaces}, комнат — {rooms}, устройств — {markers}","backup.undo_import":"Отменить последний полный импорт","backup.import_undone":"Полный импорт отменён","backdrop.large_title":"Большое изображение","backdrop.large_body":"Изображение {w}×{h} ({fileMb} МБ), для показа потребуется около {decodedMb} МБ памяти. На планшетах это может привести к падению страницы.","backdrop.unknown_body":"Не удалось прочитать размеры изображения — файл может быть повреждён. Продолжение может привести к падению страницы на планшете.","backdrop.reduced_dimensions":"Уменьшенная копия: {w}×{h} px.","backdrop.use_downscaled":"Загрузить уменьшенную копию","backdrop.reducing":"Уменьшаем…","backdrop.keep_original":"Оставить оригинал","backdrop.too_large_title":"Изображение слишком большое","backdrop.too_large_body":"Изображение превышает возможности браузера ({w}×{h}, предел {limit} px по стороне). Уменьшите его в редакторе на компьютере и загрузите снова.","backdrop.downscale_failed":"Не удалось создать уменьшенную копию. Текущий план не изменён."}},{code:"de",nativeLabel:"Deutsch",loadDictionary:async function(e){const t=0===e?await import("./de-DvdscEer.js"):await import(new URL("./de-DvdscEer.js?retry",import.meta.url).href);return{dictionary:t.dictionary,fingerprint:t.fingerprint}}},{code:"fr",nativeLabel:"Français",loadDictionary:async function(e){const t=0===e?await import("./fr-jiXq6Mrg.js"):await import(new URL("./fr-jiXq6Mrg.js?retry",import.meta.url).href);return{dictionary:t.dictionary,fingerprint:t.fingerprint}}}],Yu=ju,Xu=new Set;const Zu=new class{constructor(e,t,i=console.warn,n){this.entries=e,this.expectedFingerprint=t,this.warn=i,this.loadFailed=n,this.dictionaries=new Map,this.pending=new Map,this.failed=new Set;for(const t of e)t.dictionary&&this.dictionaries.set(t.code,t.dictionary)}state(e){return this.dictionaries.has(e)?"ready":this.failed.has(e)?"fallback":"pending"}dictionary(e){return this.dictionaries.get(e)}ensure(e){if("pending"!==this.state(e))return Promise.resolve();const t=this.pending.get(e);if(t)return t;const i=this.entries.find(t=>t.code===e),n=this.load(i).finally(()=>this.pending.delete(e));return this.pending.set(e,n),n}async load(e){if(!e?.loadDictionary)return void(e&&this.failed.add(e.code));let t;for(const i of[0,1])try{const t=await e.loadDictionary(i);if(t.fingerprint!==this.expectedFingerprint)throw new Error(`locale fingerprint mismatch for ${e.code}`);return this.dictionaries.set(e.code,t.dictionary),void this.failed.delete(e.code)}catch(e){t=e}this.failed.add(e.code),this.warn(`[houseplan] unable to load ${e.code} locale; using English`,t),this.loadFailed?.(e.code)}}(Ku,"c8d5c166e30a11241ef32c7e1dc70368632e84c448524a8340494350ec4d5fca",console.warn,function(e){for(const t of Xu)t(e)});function Ju(e){const t=tp(e)?.code??"en";return Zu.dictionary(t)??Yu}function Qu(e){return"string"==typeof e?e.trim().replaceAll("_","-").toLowerCase():""}const ep=new Map(Ku.map(e=>[Qu(e.code),e]));function tp(e){return ep.get(Qu(e))}function ip(e,t){const i=[{value:"",label:e},...Ku.map(({code:e,nativeLabel:t})=>({value:e,label:t}))],n="string"==typeof t?t:"";return n&&!i.some(e=>e.value===n)&&i.push({value:n,label:tp(n)?.nativeLabel??n}),i}function np(e,t){return function(e,t,i,n){const r=new Map(i.map(e=>[Qu(e),e])),o=r.get(Qu(e));if(o)return o;const s=Qu(t),a=r.get(s);return a||(r.get(s.split("-")[0]||"")??n)}(t,e?.locale?.language||e?.language,Ku.map(({code:e})=>e),"en")}function rp(e,t,i){return Qi(Ju(e)[t]??Yu[t]??t,i)}function op(e,t){const i=Ju(e)[t]??Yu[t];return"string"==typeof i&&i.trim().length>0}function sp(e,t,i,n){return{ox:0,oy:0}}function ap(e,t){const i=(e.angle+90)*Math.PI/180,n=Oa(16,t),r=e.gateFace?-n*e.gateFace.side:n*(e.flipV?-1:1);return[[e.x+Math.cos(i)*r,e.y+Math.sin(i)*r],r<0]}function lp(e){const t=e.length/2,i=e.face.cm>0?e.face.cm/e.cellCm*e.gridPitch/2:Oa(4,e.cellCm),n="gate"===e.type?Math.sin(10*Math.PI/180)*t:0;return{half:t,jambHalf:i,gateDepth:n,outlineHalf:Math.max(Oa(16,e.cellCm),i+Oa(8,e.cellCm),n+Oa(8,e.cellCm)),hitHalf:Math.max(Oa(20,e.cellCm),i+Oa(10,e.cellCm),n+Oa(12,e.cellCm))}}function cp(e,t,i){e.minX=Math.min(e.minX,t),e.minY=Math.min(e.minY,i),e.maxX=Math.max(e.maxX,t),e.maxY=Math.max(e.maxY,i)}function hp(e,t,i,n,r,o,s,a){const l=Math.min(s,a)*Math.PI/180,c=Math.max(s,a)*Math.PI/180,h=(e,t)=>{const i=Math.atan2(t,e),n=[l,c];for(let e=-3;e<=3;e++){const t=e*Math.PI-i,r=Math.PI/2+e*Math.PI-i;t>l&&tl&&r0&&[e.length,e.angle,t[0],t[1]].every(Number.isFinite)))return null;const{half:i,jambHalf:n}=lp(e),r=Ia(e.cellCm),o=1.75*r,s=1.25*r,a=.75*r,l={minX:-i-s,minY:-n-s,maxX:i+s,maxY:n+s},c={minX:1/0,minY:1/0,maxX:-1/0,maxY:-1/0};if("window"===e.type)hp(c,-i,0,i,-o,o,-90,0),hp(c,i,-i,0,-o,o,0,90),cp(c,-i-a,-i-a),cp(c,i+a,a);else if("gate"===e.type){const t=10*e.face.side;hp(c,-i,0,i,-o,o,0,t),hp(c,i,-i,0,-o,o,-t,0)}else hp(c,-i,0,e.length,-o,o,-90,0),cp(c,-i-a,-e.length-a),cp(c,i+a,a);const[h,d]=dp(e),u={...l};cp(u,c.minX+h,c.minY+d),cp(u,c.maxX+h,c.maxY+d);const p=e.flipH?-1:1,_="gate"===e.type?1:e.flipV?-1:1,m=e.angle*Math.PI/180,g=Math.cos(m),f=Math.sin(m),v={minX:1/0,minY:1/0,maxX:-1/0,maxY:-1/0};for(const e of[u.minX,u.maxX])for(const i of[u.minY,u.maxY]){const n=e*p,r=i*_;cp(v,t[0]+n*g-r*f,t[1]+n*f+r*g)}return v}function pp(e){if("passage"===e.type)return W``;const t=Math.max(0,Math.min(1,e.amount)),{half:i,jambHalf:n}=lp(e),r=Ia(e.cellCm),o=1.75*r,s=e.flipH?-1:1,a=e.flipV?-1:1,l="gate"===e.type?1:a,[c,h]=dp(e);let d;if("window"===e.type){const o=Math.PI/2*i,s=e.face.cm>0?W`{e.isConnected&&e.requestUpdate()}),Wu.has(e)?"warm":"cold"):(Uu.delete(e)&&(e.inert=!1,e.removeAttribute("aria-busy")),i&&(e.setAttribute("lang","fallback"===n?"en":i),Wu.add(e)),"ready")}function Gu(){return j``}const Ku=[{code:"en",nativeLabel:"English",dictionary:ju},{code:"ru",nativeLabel:"Русский",dictionary:{"editor.context_actions":"Действия: {object}","editor.tool_options":"Параметры инструмента: {tool}","editor.palette":"Палитра: {tool}","editor.open_group":"Группа инструментов: {group}","editor.group_active":"{group} — активно: {item}","editor.disabled_action":"{action} недоступно: {reason}","editor.loading":"Загружаем редактор…","editor.loading_aria":"Редактор плана загружается","editor.load_failed":"Не удалось загрузить редактор.","editor.refresh_advice":"Обновите страницу и повторите попытку.","editor.retry_advice":"Проверьте сеть и нажмите ещё раз.","version_mismatch.title":"Версии House Plan не совпадают","version_mismatch.body":"Если Home Assistant ещё перезапускается, дождитесь завершения, затем перезагрузите эту страницу.","version_mismatch.frontend":"Карточка","version_mismatch.backend":"Интеграция","version_mismatch.reload":"Перезагрузить страницу","color_picker.title":"Выбор цвета","color_picker.hue":"Оттенок","color_picker.saturation":"Насыщенность","color_picker.value":"Яркость","color_picker.hex":"Цвет HEX","color_picker.invalid_hex":"Введите цвет HEX из 3 или 6 цифр","color_picker.confirm":"ОК","btn.properties":"Свойства","btn.keep_as_walls":"Оставить стенами","btn.delete_room_keep_walls":"Удалить комнату, оставить стены","btn.delete_room_with_walls":"Удалить комнату и стены","title.markup_select":"Выбор и редактирование стен и колонн","title.markup_column":"Колонна: кликните точку сетки для квадратной колонны","markup.partition":"Перегородка","markup.column":"Колонна","markup.hint_column":"кликните точку сетки, чтобы поставить квадратную колонну","history.wall_segment":"Добавление отрезка стены","history.column_add":"Добавление колонны","history.physical_edit":"Изменение физического объекта","history.physical_delete":"Удаление физического объекта","history.physical_move":"Перемещение физического объекта","history.wall_face_batch":"Создание комнат из стен","toast.column_duplicate":"Колонна с тем же центром и внешним размером уже существует","physical.partition_properties":"Свойства перегородки","physical.column_properties":"Свойства колонны","physical.shape":"Форма","physical.square":"Квадрат","physical.circle":"Круг","physical.diameter":"Диаметр","physical.side":"Сторона","physical.rotation":"Угол поворота","physical.length":"Длина","physical.allowed_range":"Допустимо: {min}–{max} {unit}","physical.column_size_title":"Внешняя сторона квадратной колонны, создаваемой кликом (1–150 см).","card.title":"План дома","count.devices":"{n} устр.","empty.no_spaces":"Пространств пока нет.","empty.add_first":"Добавьте первое пространство и загрузите план этажа.","empty.read_only":"Пространства не настроены. Попросите администратора добавить первое.","empty.install":"Установите интеграцию House Plan и добавьте запись в «Устройства и службы».","btn.add_space":"Добавить пространство","btn.cancel":"Отмена","btn.save":"Сохранить","btn.close":"Закрыть","btn.delete":"Удалить","btn.copy":"Копировать","btn.edit":"Редактировать","btn.open_in_ha":"Открыть в HA","btn.reset":"Сброс","btn.attach":"Прикрепить…","btn.upload":"Загрузить…","btn.replace":"Заменить…","title.zoom_in":"Приблизить","title.zoom_out":"Отдалить","title.zoom_fit":"Вписать всё","title.configure_space":"Настроить пространство","title.add_space":"Добавить пространство","title.markup_add":"Стены: рисуйте непрерывную цепочку; каждый принятый отрезок сохраняется отдельно. Shift фиксирует 45°","title.markup_merge":"Объединить: клик по одной комнате, затем по соседней с общей стеной","title.markup_split":"Разделить комнату: клик по комнате, затем две точки на её стенах","title.markup_delroom":"Удалить комнату: кликните внутри комнаты и подтвердите удаление","title.need_plan":"Загрузите подложку (план этажа)","markup.add":"Стены","markup.merge":"Объединить","markup.split":"Разделить","markup.resize":"Размер","title.markup_resize":"Изменение размера комнат: тяните доступную ручку горизонтальной или вертикальной стены","markup.hint_resize":"тяните доступную ручку стены · стена упирается в первую небезопасную позицию · Esc — отмена · Ctrl+Z — отмена шага","resize.disabled.diagonal":"Стена расположена под углом: Resize поддерживает только горизонтальные и вертикальные стены","resize.disabled.side-angle":"Примыкающая стена расположена под углом: для Resize обе примыкающие стены должны образовывать прямой угол","resize.disabled.duplicate-physical-wall":"Стену перекрывает отдельная перегородка или колонна; удалите или переместите её перед изменением размера","resize.disabled.partial-shared":"Соседняя комната использует только часть этой стены, поэтому её нельзя безопасно двигать как одну общую стену","resize.disabled.unequal-shared":"У соседней комнаты другие конечные точки или длина стены, поэтому стены нельзя безопасно двигать вместе","resize.disabled.multiple-rooms":"Перемещение затронуло бы больше двух комнат","resize.disabled.thickness-conflict":"Толщину стены нельзя безопасно сохранить","resize.disabled.opening-conflict":"Проём на этой стене нельзя безопасно переместить","resize.disabled.invalid-geometry":"Эту стену нельзя переместить без изменения структуры плана","resize.limit_stopped":"Стена остановлена: дальше нарушается ограничение стыков","resize.commit_failed":"Изменение размера отменено: итоговый план не прошёл проверку геометрии","resize.preview_failed":"Стена остановлена в последней безопасной позиции: геометрию плана нельзя сохранить без потерь","markup.opening":"Проём","markup.delete_room":"Удалить комнату","history.undo":"Отменить","history.redo":"Повторить","history.undo_named":"Отменить: {name} (Ctrl+Z)","history.redo_named":"Повторить: {name} (Ctrl+Shift+Z / Ctrl+Y)","history.undo_empty":"Нет операций для отмены","history.redo_empty":"Нет операций для повтора","history.undone":"Отменено: {name}","history.redone":"Повторено: {name}","history.add_room":"Создание комнаты","history.split_room":"Разделение комнаты","history.merge_rooms":"Объединение комнат","history.resize_room":"Изменение размера комнаты","history.wall_thickness":"Изменение толщины стены","history.add_opening":"Добавление дверного или оконного проёма","history.edit_opening":"Изменение проёма","history.move_opening":"Перемещение проёма","history.delete_opening":"Удаление проёма","history.delete_room_keep_walls":"Удаление комнаты с сохранением стен","history.delete_room_with_walls":"Удаление комнаты и её стен","history.decor_add":"Добавление объекта декора","history.decor_edit":"Изменение объекта декора","history.decor_move":"Перемещение объекта декора","history.decor_transform":"Трансформация объекта декора","history.decor_delete":"Удаление объекта декора","history.backdrop_transform":"Трансформация подложки плана","history.device_move":"Перемещение: {name}","history.device_stale":"История позиций больше неприменима и была очищена","opening.new":"Новый проём","opening.edit":"Проём","opening.door":"Дверь","opening.window":"Окно","opening.gate":"Ворота","opening.passage":"Открытый проём","opening.passage_binding_warning":"При сохранении датчик открытия и замок будут удалены.","opening.invalid_passage_fields":"У открытого проёма на плане «{room}» есть недопустимые параметры: {fields}.","opening.type_label":"Тип","opening.length_label":"Длина, см","opening.contact_label":"Датчик открытия","opening.lock_label":"Замок","opening.none":"— нет —","opening.search_ph":"Поиск: имя или entity_id…","opening.invert":"Инвертировать открыто/закрыто","opening.flip_h":"Петли с другой стороны","opening.flip_v":"Открывается в другую сторону","opening.open":"Открыто","opening.closed":"Закрыто","opening.locked":"Заперто","opening.unlocked":"Не заперто","opening.state_unknown":"недоступно","opening.no_entities":"Датчики не привязаны — статичный символ на плане.","toast.opening_no_wall":"Кликните рядом со стеной комнаты или независимой стеной","opening.host_partition":"Независимая стена","opening.partition_orphan":"Независимая стена этого проёма больше не существует","opening.partition_jamb_margin":"Оставьте от края проёма до торца стены минимум {distance}","opening.rebind_partition":"Привязать к другой независимой стене","confirm.delete_partition_openings_title":"Удалить стену и проёмы?","confirm.delete_partition_openings_body":"В стене есть проёмы: {count}. Они будут удалены вместе со стеной.","confirm.delete_partition_openings_item":"• {type}, {length}","markup.hint_points":"точек: {n} · Shift — шаг 45° · Esc — завершить цепочку · Ctrl+Z — убрать точку · при замыкании будет предложена комната","markup.hint_start":"кликните точку сетки, чтобы начать цепочку стен","tip.lqi":"средний сигнал zigbee:","tip.area":"площадь: {value}","info.device_header":"Устройство на плане","info.model":"Модель","info.state":"Состояние","info.link":"Ссылка","info.manuals":"Инструкции","info.none":"Нет дополнительной информации","marker.new_device":"Новое устройство","marker.name_label":"Имя (отображается на плане)","marker.name_ph":"Название","marker.binding_label":"Привязка к устройству HA","marker.binding_disabled":"деактивировано в Home Assistant","marker.virtual_option":"Виртуальное устройство (без привязки)","marker.search_ph":"Поиск устройства / группы…","marker.nothing_found":"ничего не найдено","marker.room_label":"Комната","marker.room_override":" (переопределить размещение)","marker.room_choose":"— выберите комнату —","marker.room_auto":"— по зоне устройства (авто) —","marker.icon_label":"Иконка","marker.icon_ph":"mdi:… (пусто = авто)","marker.display_label":"Отображение","display.badge":"Значок + состояние","display.icon_ripple":"Значок + состояние и активность","display.static_icon":"Всегда статичный значок","marker.display_hint_badge":"Значок и динамическая подложка показывают состояние устройства без обычной пульсации активности. Красная тревога сохраняется.","marker.display_hint_icon_ripple":"Значок, динамическая подложка и пульсация: короткая — для событий, постоянная — для работы, движения или присутствия. Красная тревога имеет отдельный приоритет.","marker.display_hint_value":"Значок заменяется выбранным или автоматически найденным значением Home Assistant; подложка продолжает показывать состояние. Красная тревога сохраняется.","marker.display_hint_static_icon":"Подложка в цветах темы и значок всегда остаются одинаковыми. Состояния, активность, недоступность и тревоги не меняют отображение.","marker.static_alarm_warning":"Это устройство может сообщать о тревогах. Статичный режим скрывает визуальную тревогу маркера.","marker.preview.title":"Предпросмотр отображения","marker.preview.actual":"Сейчас","marker.preview.example":"Пример","marker.preview.integration":"Интеграция","marker.preview.source":"Источник отображения","marker.preview.current_state":"Текущее состояние","marker.preview.result":"На плане","marker.preview.details":"Подробнее об источниках","marker.preview.select_source":"Выберите устройство или сущность Home Assistant, чтобы увидеть фактическое отображение.","marker.preview.unknown_provider":"Интеграция неизвестна","marker.preview.virtual_provider":"House Plan · виртуальное устройство","marker.preview.no_source":"Нет активного источника","marker.preview.no_state":"Нет текущего состояния","marker.preview.mixed_states":"Несколько разных состояний","marker.preview.multiple_sources":"Источников: {n}","marker.preview.more_sources":"ещё {n}","marker.preview.scaled":"Предпросмотр уменьшен до {n}%, чтобы поместиться. Сохранённый размер не изменится.","marker.preview.demo_short":"Показать краткую активность","marker.preview.demo_continuous":"Показать постоянную активность","marker.preview.stop_continuous":"Остановить постоянную активность","marker.preview.demo_short_notice":"Пример краткой активности; фактическое состояние устройства не меняется.","marker.preview.demo_continuous_notice":"Пример постоянной активности; фактическое состояние устройства не меняется.","marker.preview.demo_already_visible":"Текущее состояние уже показывает реальную активность или тревогу.","marker.preview.reduced_motion":"В системе включено уменьшение движения, поэтому обычная активность показана точкой.","marker.preview.reason.neutral":"Нейтральная тёмная подложка","marker.preview.reason.working":"Жёлтая подложка: устройство сейчас работает","marker.preview.reason.working_activity":"Жёлтая подложка и эффект активности: устройство сейчас работает","marker.preview.reason.open":"Оранжевая подложка: физически открыто или разблокировано","marker.preview.reason.cover_icon_state":"Нейтральная подложка; состояние и значок определяет сущность шторы или заслонки","marker.preview.reason.presence":"Эффект активности, пока обнаружено присутствие","marker.preview.reason.event":"Короткий эффект активности после события","marker.preview.reason.transition":"Эффект активности во время движения или смены состояния","marker.preview.reason.media_neutral":"Медиаустройство остаётся на нейтральной тёмной подложке, пока доступно","marker.preview.reason.unavailable":"Приглушённая нейтральная подложка: отключено или недоступно","marker.preview.reason.alarm":"Красная тревожная подложка; тревога отображается всегда","marker.preview.reason.live_states_disabled":"Оформление по живым состояниям отключено в настройках карточки","marker.preview.reason.value_no_state":"Нет подходящего значения состояния — вместо него показан значок","marker.preview.reason.value_ambiguous_sources":"Подходит несколько источников значения — вместо него показан значок","marker.preview.reason.value_non_scalar":"Источник вернул не простое значение — вместо него показан значок","marker.preview.reason.value_virtual":"У виртуального устройства нет значения HA — вместо него показан значок","marker.preview.reason.vacuum_live_plan_only":"Живая позиция и след пылесоса доступны только на полном плане","marker.preview.reason.hidden_design_preview":"Устройство скрыто на плане, но его оформление видно в предпросмотре","marker.preview.reason.composite_power_source":"Состояние берётся из сущности питания устройства; вспомогательные переключатели не учитываются","marker.preview.reason.activity_display_disabled":"Выбранный режим отображения не показывает обычные эффекты активности","marker.preview.reason.ha_disabled":"Привязка отключена в Home Assistant, поэтому устройство будет скрыто на плане","marker.preview.reason.orphaned":"Сохранённая привязка Home Assistant больше не найдена","marker.preview.reason.static_icon":"Статичный режим: состояние устройства не меняет значок","marker.activity_color":"Цвет пульсации активности","marker.ripple_size":"Размер пульсации активности","marker.activity_alarm_note":"Цвет и размер относятся только к обычной активности и не влияют на красную тревогу.","marker.pulse_a11y_alarm":"Тревога","marker.pulse_a11y_event":"Недавнее событие","marker.pulse_a11y_presence":"Обнаружено присутствие","marker.pulse_a11y_transition":"Изменение состояния","marker.pulse_a11y_running":"Работает","marker.state_a11y_neutral":"Обычное состояние","marker.state_a11y_working":"Работает","marker.state_a11y_open":"Открыто","marker.state_a11y_locked":"Заблокировано","marker.state_a11y_unlocked":"Разблокировано","marker.state_a11y_alarm":"Тревога","marker.state_a11y_unavailable":"Недоступно","marker.lqi_a11y_low":"LQI {value}, слабый сигнал","marker.lqi_a11y_mid":"LQI {value}, средний сигнал","marker.lqi_a11y_high":"LQI {value}, сильный сигнал","marker.size_label":"Размер / поворот значка","marker.angle_label":"Поворот","marker.model_label":"Модель","marker.model_ph":"напр. Aqara T&H","marker.link_label":"Ссылка","marker.desc_label":"Описание","marker.desc_ph":"Заметки, характеристики…","marker.manuals_label":"Инструкции (PDF и т.п.)","marker.sub_device":"устройство","marker.sub_z2m_group":" · Z2M-группа","marker.sub_group":"группа","marker.sub_helper":"хелпер","space.new":"Новое пространство","space.copy_title":"Копирование пространства","space.copy_name":"Название нового пространства","space.copy_fallback":"Пространство","space.copy_create":"Создать копию","space.copy_optimize_title":"Оптимизировать перед копированием?","space.copy_optimize_body":"Перед созданием «{name}» House Plan должен оптимизировать весь план, включая другие пространства. Продолжить?","space.copy_optimize_confirm":"Оптимизировать и скопировать","space.copy_error_changed":"План изменился, пока было открыто подтверждение. Проверьте его и повторите попытку.","space.copy_error_source_missing":"Исходного пространства больше нет. Снова откройте его настройки и повторите попытку.","space.copy_error_source_invalid":"House Plan не смог проверить все стены этого пространства. Исправьте исходное пространство и повторите попытку.","space.copy_error_spaces_limit":"В House Plan уже создано максимальное число пространств.","space.copy_error_partitions_limit":"В этом пространстве слишком много стен для копирования.","space.copy_error_openings_limit":"В этом пространстве слишком много проёмов для копирования.","space.copy_error_decor_limit":"В этом пространстве слишком много элементов подложки для копирования.","space.copy_error_columns_limit":"В этом пространстве слишком много колонн для копирования.","space.copy_error_opening_host":"Один из проёмов больше не привязан к стене. Исправьте или удалите его перед копированием.","space.copy_error_geometry":"Копия создаст небезопасную геометрию стен. Исправьте исходное пространство и повторите попытку.","space.copy_error_optimize_geometry":"Копирование остановлено: оптимизация всего плана небезопасна для одного из пространств.","space.header":"Пространство","space.title_label":"Название","space.title_ph":"Например: Гараж","space.plan_label":"Подложка (план)","space.no_plan":"нет подложки","space.plan_alt":"план","room.new":"Новая комната","room.name_label":"Отображаемое имя","room.name_ph":"Например: Терраса","room.area_label":"Зона Home Assistant (свободные)","room.no_area_option":"— без зоны —","room.default_name":"Комната","device.unnamed":"без имени","device.light_group":"группа света","device.fallback":"устройство","device.virtual":"виртуальное устройство","confirm.delete_room_title":"Удалить комнату «{name}»?","confirm.delete_room_body":"Выберите, нужно ли оставить физические стены, принадлежащие только этой комнате. Общие с другой комнатой стены сохраняются всегда.","confirm.remove_marker_title":"Удалить устройство с плана?","confirm.remove_marker_body":"Устройство исчезнет полностью и перестанет участвовать в данных плана. Позже его можно будет добавить заново.","confirm.erase_decor":"Стереть объект «{kind}»? Действие можно отменить из истории редактора.","confirm.delete_space_title":"Удалить пространство?","confirm.delete_space_body":"Пространство, все его комнаты и вся разметка плана будут удалены.","confirm.delete_space_vac_routes":"Также будет снято сопоставление карт роботов: {count}.","space.delete_blocked":"Это пространство всё ещё используется устройствами: {n}. Сначала перенесите их в другое пространство или удалите.","toast.pos_save_failed":"Не удалось сохранить позицию: {err}","toast.no_entity":"У устройства нет подходящей сущности","toast.ha_disabled_action":"Деактивированный объект Home Assistant нельзя использовать на плане.","toast.ha_disabled_show_device":"Деактивированное в Home Assistant устройство нельзя показать на плане. Сначала активируйте его в Home Assistant.","toast.ha_disabled_show_entity":"Деактивированную в Home Assistant сущность нельзя показать на плане. Сначала активируйте её в Home Assistant.","toast.ha_disabled_add":"Деактивированный объект Home Assistant нельзя добавить на план. Сначала активируйте его в Home Assistant.","toast.ha_binding_unverified":"Статус объекта не удалось подтвердить по реестру Home Assistant. Отображение и действия временно недоступны.","toast.markup_needs_server":"Разметка доступна после переноса конфига на сервер","toast.space_order_changed":"Порядок изменён. Если где-то этаж карточки задан номером, проверьте такие панели.","toast.conflict":"Конфиг изменён в другом окне — данные обновлены, повторите последнее действие","toast.cfg_save_failed":"Не удалось сохранить конфиг: {err}","toast.room_overlap":"Контур накладывается на комнату «{name}» — комнаты не должны накладываться","toast.contour_cannot_close":"Контур нельзя замкнуть: он вырожден или пересекает сам себя","toast.merge_not_adjacent":"Объединять можно только комнаты с общей стеной","toast.rooms_merged":"Комнаты объединены в «{name}»","toast.split_pick_wall":"Начните разрез на стене комнаты","toast.split_bad_cut":"Разрез — от стены до стены внутри комнаты, без пересечения стен и самого себя","merge.header":"Объединение комнат","merge.hint":"У объединённой комнаты одно имя и одна зона. Вторая зона освобождается — её устройства уйдут с плана, пока их не заберёт другая комната.","merge.keep":"Оставить","merge.no_area":"без зоны","toast.room_saved":"Комната сохранена ({n}). Устройств добавлено: {added}. Обведите следующую или выйдите из разметки.","toast.room_saved_no_area":"Комната сохранена ({n}, без зоны). Обведите следующую или выйдите из разметки.","toast.marker_needs_server":"Редактирование устройств доступно после переноса конфига на сервер","toast.virtual_name_required":"Укажите имя виртуального устройства","toast.marker_saved":"Устройство сохранено","toast.marker_removed":"Устройство удалено с плана","toast.integration_missing":"Интеграция House Plan не установлена — управление недоступно","toast.plan_formats":"Поддерживаются SVG, PNG, JPG, WebP","toast.plan_required":"Загрузите подложку — план этажа обязателен","toast.space_added_onboard":"Пространство добавлено. Обведите комнаты: кликайте по точкам сетки и замкните контур.","toast.space_added":"Пространство добавлено","toast.space_copied":"Пространство «{name}» создано","toast.space_saved":"Пространство сохранено","toast.space_deleted":"Пространство удалено","toast.delete_failed":"Ошибка удаления: {err}","toast.error":"Ошибка: {err}","toast.toggle_target_unavailable":"Цель «{name}» недоступна — действие не выполнено","toast.toggle_targets_unavailable":"Цели недоступны: {names}. Действие не выполнено","toast.file_failed":"Файл «{name}» не загружен: {err}","toast.files_attached":"Прикреплено файлов: {n}","err.unknown":"неизвестная ошибка","err.code":"код {code}","err.too_large":"файл больше {mb} МБ","err.bad_ext":"недопустимый тип (нужен PDF/изображение)","err.unauthorized":"нужны права администратора","editor.title":"Заголовок","editor.default_floor":"Стартовое пространство","editor.default_floor_missing":"Стартовое пространство «{id}» больше не существует. Выберите другое.","editor.floor":"Закреплённое пространство","editor.floor_none":"— не закреплять —","editor.floor_index":"YAML-индекс {index} (сохранён)","fixed_floor.loading":"Загружаем закреплённое пространство…","fixed_floor.invalid_title":"Закреплённое пространство недоступно","fixed_floor.invalid_body":"Проверьте floor в конфигурации карточки. Настроенное значение: {value}","editor.icon_size":"Размер иконок, % ширины плана","editor.show_temperature":"Показывать температуру","editor.live_states":"Живые состояния (вкл/выкл, открыто…)","editor.light_pools":"Световые пулы и тени от стен","editor.show_signal":"Показывать сигнал zigbee (LQI)","editor.language":"Язык интерфейса","editor.lang_auto":"Авто (профиль HA)","title.icon_rules":"Правила иконок: какая MDI-иконка достаётся устройству по имени","rules.title":"Правила иконок","rules.hint":"Правила проверяются сверху вниз по строке «имя устройства + модель» (regex без учёта регистра); срабатывает первое совпадение. Если ничего не подошло — решает device class сущности, затем — иконка-заглушка.","rules.pattern_ph":"regex, напр. розетк|plug","rules.icon_ph":"mdi:power-socket-de","rules.add":"Добавить правило","rules.reset":"Сбросить к умолчаниям","rules.test_ph":"Проверьте имя устройства…","rules.invalid":"некорректный regex","rules.saved":"Правила иконок сохранены","btn.up":"Вверх","btn.down":"Вниз","tap.info":"Карточка устройства","tap.more_info":"Диалог HA (more-info)","tap.toggle":"Переключить состояние","marker.tap_label":"Действие по нажатию для этого устройства","tap.toggle_note":"Под селектором показано, какое состояние изменится. Защищённые устройства не переключаются с плана.","import.title":"Создать пространства из этажей HA","import.hint":"Home Assistant уже знает эти этажи. Отметьте, какие превратить в пространства плана — далее для каждого попросим картинку плана. Комнаты затем обводятся вручную по плану.","import.start":"Создать: {n}","import.manual":"Начать с нуля","import.progress":"Этаж {i} из {n}","import.done":"Пространства созданы. Обведите комнаты: кликайте по точкам сетки и замкните контур.","btn.skip":"Пропустить","space.scale_label":"Масштаб (размер клетки сетки)","space.cell_cm.help":"Связывает сетку с реальными размерами: от значения зависят длины и площади, толщина стен, размеры проёмов и радиус свечения. Изменение после разметки меняет расчётные размеры всего пространства, но не двигает его точки на плане.","space.cell_cm.help.aria":"Подсказка: масштаб пространства","space.scale_unit":"см на клетку","space.scale_unit_imperial":"дюйм на клетку","space.display_section":"Отображение","space.show_borders":"Всегда отображать границы комнат","space.zero_wall_style":"Стены нулевой толщины","space.zero_wall_style.help":"Пунктирные стены нулевой толщины пропускают Glow и солнечные лучи, сплошные блокируют их как барьер нулевой площади. Выбор меняет все такие стены пространства, даже когда их линии скрыты в просмотре.","space.zero_wall_style.help.aria":"Подсказка: вид стен нулевой толщины","space.zero_wall_dashed":"Пунктирные","space.zero_wall_solid":"Сплошные","space.show_names":"Отображать названия комнат (перетаскиваются)","space.room_color":"Цвет границ и названий","space.opacity":"Прозрачность","space.fill_label":"Заливка комнат","space.fill_mode.help":"«Свой цвет» задаёт оформление, а «Свет», «Температура» и «LQI» используют текущие данные Home Assistant; Glow включается отдельно.","space.fill_mode.help.aria":"Подсказка: режим заливки комнат","fill.none":"Нет","fill.lqi":"По силе зигби-сигнала","fill.light":"По освещению","fill.custom":"Свой цвет","space.custom_fill":"Цвет заливки","space.source_file":"У меня есть картинка плана","space.source_draw":"Нет подложки — нарисую комнаты вручную","fill.temp":"По температуре","tip.temp_avg":"средняя температура:","tip.hum_avg":"средняя влажность:","space_card.button":"Перейти к пространству","space_card.not_found":"Пространство «{id}» не найдено","space_card.loading":"Загрузка…","continuity.restore_plan":"Восстанавливаем план…","continuity.restore_connection":"Восстанавливаем подключение к устройствам…","continuity.retry":"Повторить","editor.space":"Пространство","editor.framing":"Кадрирование","editor.fit_content":"Всё видимое содержимое","editor.fit_house":"Плотно по геометрии дома","editor.show_button":"Показывать кнопку","editor.button_label":"Текст кнопки","editor.button_target":"Путь дашборда (куда вести)","marker.sub_entity":"сущность","title.general_settings":"Общие настройки","title.export_pdf":"Сохранить в PDF","pdf.title":"Сохранение в PDF","pdf.dimensions":"Отображать размеры и площади","pdf.decor":"Отображать мебель и другой декор","pdf.room_names":"Отображать названия комнат","pdf.backdrop":"Отображать подложку","pdf.save":"Сохранить","pdf.saving":"Формируем…","pdf.failed":"Не удалось создать PDF.","pdf.too_large":"Размер изображений превышает лимит PDF 25 МБ.","pdf.asset_failed":"Не удалось загрузить подложку или изображение декора.","pdf.internal_dimensions":"Внутренние размеры","pdf.scale":"Масштаб 1:{n}","pdf.north":"Север","gs.title":"Общие настройки","gs.light_group":"Заливка: освещение","gs.light_on":"Свет включён","gs.light_off":"Весь свет выключен","gs.temp_group":"Заливка: температура","gs.temp_cold":"Холодно","gs.temp_ok":"Комфорт","gs.temp_hot":"Жарко","gs.lqi_group":"Заливка: зигби-сигнал","gs.lqi_low":"Слабый сигнал","gs.lqi_high":"Сильный сигнал","gs.reset":"Сбросить к умолчаниям","gs.saved":"Общие настройки сохранены","gs.radar_show_live":"Показывать текущее присутствие на плане","gs.radar_show_live_hint":"Скрывает или показывает все живые цели радаров. Это не запускает и не останавливает запись наблюдений.","radar.title":"Присутствие на плане","radar.help":"Свяжите маркер с точными сущностями радара Home Assistant, укажите положение датчика и профиль координат. Живые позиции обрезаются по выбранной комнате.","radar.help.aria":"Подсказка: настройки радара присутствия","radar.enabled":"Использовать этот радар присутствия","radar.show_live":"Показывать живые цели","radar.configure":"Настроить радар","radar.configure_on_plan":"Настроить на плане","radar.change_installation":"Сменить установку","radar.no_contour":"У комнаты нет контура. Точки радара не будут обрезаться по комнате.","radar.discard_setup_title":"Отменить настройку радара?","radar.discard_setup":"Несохранённая настройка радара будет потеряна.","radar.step_place_mount":"Укажите физическое положение датчика","radar.step_place_heading":"Укажите точку прямо перед датчиком","radar.step_reference":"Укажите контрольное положение {n}, затем начните измерение","radar.step_check_reference":"Укажите независимое проверочное положение","radar.start_measure":"Начать измерение","radar.countdown":"Встаньте в отмеченное место через {seconds} с","radar.capturing":"Стойте неподвижно и в одиночестве…","radar.fit_ready":"Калибровка готова","radar.check_third":"Проверить в другом положении","radar.check_complete":"Независимая проверка завершена","radar.error_distance":"Расхождение положения: {distance}","radar.ambiguous_target":"Обнаружено несколько целей. Повторите измерение в одиночестве.","radar.insufficient_samples":"Недостаточно актуальных координат. Повторите или настройте вручную.","radar.bad_references":"Выберите разнесённые положения в разных направлениях от датчика.","radar.ambiguous_sources":"Измерения допускают два одинаково вероятных направления. Выберите точки, по которым можно различить левую и правую стороны.","radar.bad_fit":"Измерения не совпадают. Проверьте единицы, положение датчика и контрольные точки.","radar.desktop_hint":"Для точной настройки используйте компьютер. Редактирование на тач-устройствах поддерживается по остаточному принципу.","radar.detected":"House Plan распознал признаки радара у этого устройства. Перед сохранением проверьте точные источники.","radar.detected_ld2450":"House Plan нашёл набор координат ESPHome LD2450. Перед сохранением проверьте точные источники X/Y.","radar.additional_actions":"Дополнительные действия","radar.declare":"Это радар присутствия","radar.profile":"Профиль данных","radar.profile_esphome_ld2450_v1":"ESPHome LD2450 (цели X/Y)","radar.profile_cartesian_v1":"Декартовы цели (X/Y)","radar.profile_polar_v1":"Полярная цель (дальность/угол)","radar.profile_range_v1":"Только дальность","radar.profile_zones_v1":"Состояния зон","radar.profile_presence_v1":"Только присутствие","radar.room":"Комната радара","radar.room_choose":"Выберите комнату","radar.target":"Цель {n}","radar.axis_x":"Сущность координаты X","radar.axis_y":"Сущность координаты Y","radar.add_target":"Добавить слот цели","radar.range_channel":"Канал дальности {n}","radar.add_range":"Добавить канал дальности","radar.presence_gate":"Сущность присутствия для слота","radar.swap_axes":"Поменять оси X и Y местами","radar.axis_x_sign":"Направление X","radar.axis_y_sign":"Направление Y","radar.distance_source":"Сущность дальности","radar.angle_source":"Сущность угла","radar.angle_unit":"Единица угла","radar.degrees":"Градусы","radar.radians":"Радианы","radar.angle_zero":"Направление нулевого угла","radar.angle_forward":"Вперёд","radar.angle_right":"Вправо","radar.angle_clockwise":"Угол растёт по часовой стрелке","radar.zone_source":"Сущность зоны","radar.occupancy_source":"Сущность присутствия","radar.count_source":"Сущность количества целей","radar.availability_source":"Сущность доступности","radar.source_choose":"Выберите сущность","radar.source_optional":"Необязательно","radar.source_missing":"сейчас недоступна","radar.saved_unsupported":"Сохранённая настройка радара не поддерживается или неполна. Она неактивна; удалите её либо обновите House Plan перед повторной настройкой.","radar.occupancy":"Присутствие (вкл/выкл)","radar.count":"Количество","radar.mount":"Положение и направление","radar.mount_hint":"Это физическое положение датчика. Перемещение его декоративного маркера не меняет установку.","radar.heading":"Направление, °","radar.range_cm":"Дальность, см","radar.fov_deg":"Угол обзора, °","radar.unit":"Единица источника","radar.mirror":"Отразить ось влево/вправо","radar.remove":"Удалить настройки радара","radar.invalid":"Перед сохранением заполните комнату, источники и положение радара.","radar.check_sources":"Проверить живые данные","radar.checking":"Проверяем…","radar.health":"Состояние подключения","radar.live_summary":"Текущих целей: {targets}; дуг дальности: {ranges}","radar.health_ok":"Актуальные данные получены","radar.health_off":"Цели не обнаружены","radar.health_stale":"Часть координат устарела","radar.health_partial":"Часть источников актуальна, часть устарела","radar.health_restricted":"Нет доступа к одному или нескольким источникам","radar.health_incomplete":"Текущий отчёт радара неполон","radar.health_position_unavailable":"Есть присутствие, но актуальное положение недоступно","radar.health_unavailable":"Данные датчика недоступны","radar.health_needs_setup":"Требуется настроить установку","radar.health_inconsistent":"Источники передают противоречивые данные","radar.health_unknown":"Текущее состояние неизвестно","radar.health_disabled":"Радар отключён","radar.error_invalid_radar":"Проверьте настройки радара.","radar.error_invalid_selection":"Выберите существующую комнату и допустимые источники.","radar.error_source_restricted":"Нет доступа ко всем выбранным источникам.","radar.error_rate_limited":"Слишком много запросов. Повторите чуть позже.","radar.error_not_ready":"Обработка данных радара ещё не готова.","radar.error_conflict":"План изменился. Откройте настройку радара заново и повторите попытку.","radar.error_source_unavailable":"Один или несколько выбранных источников радара недоступны.","radar.error_unsupported_capability":"Установленная интеграция не поддерживает эту возможность радара.","radar.report_age":"{seconds} с назад","space.show_lqi":"Показывать зигби-сигнал (LQI) у устройств","space.hide_decor":"Скрыть декоративный слой","space.hide_decor_tip":"Линии, фигуры, надписи и мебель остаются на месте — их видно в редакторе подложки, но не на плане.","space.hide_openings":"Скрыть проёмы","space.hide_openings_tip":"Двери, окна и ворота не рисуются, но продолжают работать: свет проходит, солнце светит в окна, датчики открытия срабатывают. В редакторе плана проёмы видно всегда.","gs.light_none":"Нет источников света","mode.plan":"Редактор плана","mode.devices":"Редактор устройств","display.value":"Значение + состояние","marker.subarea":"без зоны, вручную","device.new":"Новое устройство — откройте его редактор, чтобы снять отметку","opening.unlock_action":"Открыть замок","opening.lock_action":"Закрыть замок","opening.lock_pending":"Выполняется…","title.close_editor":"Закрыть редактор (вернуться к просмотру)","title.add_device":"Добавить устройство на план","devbar.add":"Добавить","devbar.rules":"Правила иконок","device_inbox.button":"Устройства","device_inbox.title":"Устройства на плане","device_inbox.search":"Поиск по устройствам, сущностям и интеграциям…","device_inbox.add_virtual":"Добавить виртуальное устройство","device_inbox.tab_on_plan":"На плане","device_inbox.tab_available":"Доступны","device_inbox.tab_hidden":"Скрытые","device_inbox.tab_readd":"Доступны снова","device_inbox.only_new":"Только новые","device_inbox.show_entities":"Показывать сущности","device_inbox.show_hidden":"Показывать скрытые на плане","device_inbox.show_hidden.help":"Временно показывает на плане скрытые и деактивированные маркеры служебными призраками только в редакторе устройств. Сохранённая видимость устройств не меняется.","device_inbox.show_hidden.help.aria":"Подсказка: показывать скрытые устройства на плане","device_inbox.new":"Новое","device_inbox.find":"Найти на плане","device_inbox.edit":"Настроить","device_inbox.hide":"Скрыть","device_inbox.show":"Показать","device_inbox.add":"Добавить","device_inbox.readd":"Добавить заново","device_inbox.hide_available":"Скрыть из списка","device_inbox.show_more":"Показать ещё","device_inbox.more_actions":"Другие действия","device_inbox.find_hidden_hint":"Сначала включите «Показывать скрытые на плане»","device_inbox.show_disabled":"Перед показом активируйте эту привязку в Home Assistant","device_inbox.empty_on_plan":"На плане пока нет подходящих устройств.","device_inbox.empty_available":"Нет доступных устройств для добавления.","device_inbox.empty_hidden":"Скрытых устройств нет.","device_inbox.empty_readd":"Нет удалённых устройств, доступных для повторного добавления.","device_inbox.reason_visible_auto":"Найдено автоматически","device_inbox.reason_visible_explicit":"Добавлено явно","device_inbox.reason_manual_hidden":"Скрыто пользователем","device_inbox.reason_automatic_hidden":"Скрыто автоматически","device_inbox.reason_service_entry":"Служебная запись реестра","device_inbox.reason_excluded_integration":"Исключена интеграция «{integration}»","device_inbox.reason_excluded_domain":"Непространственный тип сущности","device_inbox.reason_grouped_light":"Представлено группой света комнаты","device_inbox.reason_represented_by_parent":"Представлено родительским устройством","device_inbox.reason_removed":"Ранее удалено с плана","device_inbox.reason_available":"Можно добавить на план","device_inbox.reason_no_bound_room":"Зона HA не связана с комнатой плана","device_inbox.status_ha_disabled":"Отключено в Home Assistant","device_inbox.status_orphaned":"Привязка больше не найдена в Home Assistant","device_inbox.status_unverified":"Реестр Home Assistant временно недоступен","device_inbox.saved":"Список устройств обновлён","device_inbox.filters_excluded":"Исключённые интеграции","device_inbox.filters_group_lights":"Объединять светильники комнаты в один маркер","device_inbox.filters_preview_appear":"появится: {count}","device_inbox.filters_preview_hide":"скроется: {count}","device_inbox.filters_preview_lights":"затронет светильников: {count}","device_inbox.filters_reset":"Вернуть рекомендуемые","device_inbox.filters_save":"Сохранить фильтры","device_inbox.filters_search_ph":"Добавить интеграцию…","device_inbox.filters_title":"Фильтры обнаружения","space.roomcard_section":"В карточке комнаты:","space.label_temp":"Температура","space.label_hum":"Влажность","space.label_lqi":"Средний Zigbee-сигнал","space.label_light":"Свет вкл/выкл","roomcard.light_on":"Вкл","roomcard.light_off":"Выкл","roomcard.light_partial":"{on} из {total}","toast.split_pick_inside":"Промежуточные точки разреза — внутри комнаты","mode.decor":"Редактор подложки","decor.select":"Выбрать","decor.line":"Линия","decor.rect":"Прямоугольник","decor.ellipse":"Овал","decor.text":"Надпись","decor.erase":"Стереть","decor.erase_confirm_title":"Стереть объект?","decor.color":"Цвет","decor.width":"Толщина линии","decor.line_style":"Стиль линии","decor.line_style_solid":"Сплошная","decor.line_style_dashed":"Пунктирная","decor.fill":"Заливка","decor.fill_color":"Цвет заливки","decor.length":"Длина","decor.size":"Размер","decor.flip_h":"Отзеркалить по горизонтали","decor.flip_v":"Отзеркалить по вертикали","decor.angle":"Угол поворота, °","decor.text_size":"Размер текста","decor.backdrop_properties":"Свойства картинки-подложки","decor.text_title":"Надпись","decor.object_title":"Редактирование: {kind}","decor.text_label":"Текст","decor.live_group":"Вставить переменную HA","decor.live_entity":"Сущность","decor.live_entity_ph":"выберите сущность","decor.live_attr":"Значение","decor.live_attr_ph":"выберите состояние или атрибут","decor.live_state":"Состояние","decor.backdrop":"Картинка-подложка","decor.backdrop_hint":"Тяните картинку — перемещение; угол — размер; верхнюю ручку — поворот. Shift меняет пропорции или снимает шаг угла.","decor.backdrop_reset":"Вернуть картинку","decor.backdrop_reset_done":"Картинка вернулась на своё место и в свой размер","marker.icon_auto":"Авто: {icon} (по правилам иконок; выберите свою, чтобы заменить)","marker.icon_pin_auto":"Закрепить","mode.plan_tip":"Редактор плана — геометрия дома: рисование и объединение/разделение комнат, привязка к зонам HA, двери, окна и ворота, карточки комнат, масштаб","mode.devices_tip":"Редактор устройств — всё про значки: перетаскивание, клик — настройка привязки/иконки/отображения, виртуальные устройства, правила иконок","mode.decor_tip":"Редактор подложки — чисто визуальный декор под планом: линии, прямоугольники, овалы и надписи, не реагирующие на клики","space.glow_enabled":"Свечение источников света","gs.glow_group":"Свечение источников света","gs.glow_base":"Темнота дома","gs.glow_light":"Цвет света по умолчанию / интенсивность","gs.wall_group":"Стены","gs.wall_fill":"Цвет заливки стен","gs.glow_radius":"Радиус свечения","gs.glow_radius.help":"Задаёт общий радиус светового пятна в метрах или футах; персональный радиус устройства заменяет это значение.","gs.glow_radius.help.aria":"Подсказка: общий радиус свечения","gs.unit_m":"м","gs.unit_ft":"фут","marker.controls_label":"Управляет другими источниками света","marker.controls.help":"При действии «Переключить состояние» перечисленные источники переключаются вместе с этим маркером. Их световые пятна остаются у собственных маркеров, а эта связь сама по себе не делает управляющий маркер источником света.","marker.controls.help.aria":"Подсказка: управление другими источниками света","marker.controls_filter":"Поиск ламп и выключателей…","info.controls":"Управляет","marker.glow_radius_label":"Радиус свечения","marker.glow_radius.help":"Задаёт радиус свечения в метрах или футах; пустое значение использует радиус из общих настроек.","marker.glow_radius.help.aria":"Подсказка: радиус свечения","markup.wallthick":"Толщина","markup.select":"Выбрать","title.markup_wallthick":"Толщина — клик по стене задаёт толщину от 0 до 100 см.","markup.hint_wallthick":"клик по стене · Esc закрывает без применения","wallthick.field":"Толщина","wallthick.unit_cm":"см","wallthick.unit_in":"дюйм","wallthick.apply_room":"Применить ко всем стенам комнаты","markup.draw_wall_title":"Толщина каждого нового сегмента стены (0–100 см). Общие стены сохраняют существующее значение.","room.queue_progress":"Комната {current} из {total}","toast.wall_rooms_saved":"Создано комнат: {n}","toast.wall_chain_saved":"Цепочка стен сохранена","toast.wallthick_pick":"Кликните по стене","toast.wallthick_set":"Толщина стены задана","toast.wallthick_cleared":"Толщина стены убрана","toast.physical_range":"Введите значение от {min} до {max} {unit}","toast.zero_wall_opening_conflict":"Сначала удалите проём на этом участке стены.","toast.zero_wall_ambiguous":"Не удалось однозначно выбрать участок стены. Уточните геометрию узла.","toast.zero_wall_migration_blocked":"Пространство не преобразовано: {reason}. Данные не изменены.","toast.physical_angle":"Введите угол поворота от 0° до 90°, не включая 90°","toast.physical_limit":"В пространстве достигнут лимит объектов этого типа","toast.geometry_unsafe":"Изменение отменено: геометрию стен нельзя безопасно построить.","junction.limit_angle":"Слишком острый угол между стенами: {actual}°, минимум {limit}°.","junction.limit_valence":"Слишком много стен в одном узле: {actual}, максимум {limit}.","junction.limit_length":"Слишком короткий участок стены: {actual} см, минимум {limit} см.","junction.limit_distance":"Стены и узлы слишком близко: {actual} см, минимум {limit} см.","junction.limit_clearance":"Внутри комнаты не остаётся места: {actual} см², минимум {limit} см².","junction.limit_check_failed":"Проверку стыков выполнить не удалось — изменение не сохранено","toast.wall_model_migration_blocked":"Не удалось обновить модель стен: {reason}. План не изменён. Запустите «Оптимизировать планы»; если ошибка повторится, исправьте конфликтующую геометрию стен.","toast.wall_model_client_outdated":"Обновите карточку и перезагрузите страницу перед редактированием плана.","wall_model.reason.invalid-room":"некорректный контур комнаты","wall_model.reason.zero-length":"отрезок стены нулевой длины","wall_model.reason.third-owner":"стена принадлежит более чем двум комнатам","wall_model.reason.duplicate-id":"конфликт идентификаторов стен","wall_model.reason.thickness-conflict":"конфликт значений толщины стены","wall_model.reason.opening-host":"проём нельзя однозначно привязать к стене","toast.delete_room_pick":"Кликните внутри комнаты, которую нужно удалить","toast.plan_snap_ambiguous":"Увеличьте масштаб, чтобы выбрать узел стены","toast.wall_repair_ambiguous":"У контура несколько возможных соединений. Увеличьте масштаб и соедините стены явно.","toast.wall_repair_too_large":"Разрыв больше 2 см. Соедините стены перед созданием комнаты.","toast.wall_repair_changed":"Геометрия стен изменилась. Попробуйте создать комнату ещё раз.","toast.opening_on_zero_wall":"Проёмы на стене нулевой толщины запрещены","marker.from_ha_option":"Выбрать из списка HA","marker.show_entities":"Показывать сущности","marker.show_entities_tip":"Добавляет в список не только устройства, но и все их сущности","marker.pick_ph":"Выберите устройство…","room.open_area":"Открыть зону в HA","room.fit_action":"Вписать комнату {name}","view.volumetric":"Объёмный вид","view.flat":"Плоский вид","kiosk.title":"Размеры на этом экране","kiosk.hint":"Хранится только на этом устройстве — у каждого настенного планшета или ТВ свои удобные размеры.","kiosk.icon_scale":"Размер значков устройств","kiosk.font_scale":"Размер текста карточек комнат","editor.kiosk":"Режим настенного устройства (киоск)","editor.cycle":"Автосмена пространств каждые N секунд (киоск, 0 = выкл)","room.settings_title":"Настройки комнаты","room.settings_section":"Настройки комнаты (переопределяют пространство)","room.fill_label":"Заливка в ЭТОЙ комнате","fill.inherit":"Как у пространства","room.custom_fill_space":"Цвет пространства","room.custom_fill_own":"Цвет комнаты","room.temp_range_label":"Диапазон комфорта","room.temp_range_min":"Нижняя граница комфортной температуры","room.temp_range_max":"Верхняя граница комфортной температуры","room.temp_range_reset":"Как у пространства","room.temp_range.help":"Диапазон применяется только к этой комнате. Пустое поле наследует соответствующую границу пространства; если границы поменялись местами, House Plan использует меньшую как нижнюю, а большую как верхнюю.","room.temp_range.help.aria":"О диапазоне комфорта комнаты","room.temp_src_label":"Источник температуры","room.hum_src_label":"Источник влажности","room.src_average":"Средняя по датчикам комнаты (по умолчанию)","room.src_pick":"Конкретное устройство или сущность HA","room.src_ph":"Выберите источник…","toast.room_updated":"Комната обновлена","space.card_font":"Размер шрифта карточек комнат (всё пространство)","room.sizes_section":"Размеры шрифтов","room.name_scale":"Размер названия","room.label_scale":"Размер подписей","preview.room_name":"Гостиная","toast.cfg_reload_failed":"Не удалось перечитать план с сервера: {err}","toast.locale_load_failed":"Не удалось загрузить языковой пакет. До перезагрузки страницы используется английский.","toast.furniture_art_load_failed":"Не удалось загрузить изображения мебели. Обновите страницу, чтобы их показать.","room.settings_short":"Настройки комнаты","room.unnamed":"Комната без имени","marker.use_climate_temp":"Учитывать температуру устройства в комнате","marker.use_climate_temp_tip":"Добавляет current_temperature кондиционера или термостата в среднюю температуру комнаты. Внешний бейдж со значением настраивается отдельно ниже.","marker.value_badge_title":"Бейдж со значением","marker.value_badge.help":"Показывает одно выбранное значение рядом со значком. Не влияет на комнатные показатели, свет, Glow и действие по нажатию.","marker.value_badge.help.aria":"Подсказка: бейдж со значением устройства","marker.value_badge_enabled":"Отображать бейдж со значением","marker.value_badge_source":"Значение","marker.value_badge_source.help":"Выберите конкретное состояние, поддерживаемый атрибут или производное значение этого устройства.","marker.value_badge_source.help.aria":"Подсказка: источник значения бейджа","marker.value_badge_position":"Расположение","marker.value_badge_position.help":"Выбранная сторона сохраняется постоянно и не переворачивается автоматически у края плана.","marker.value_badge_position.help.aria":"Подсказка: расположение бейджа","marker.value_badge_right":"Справа","marker.value_badge_bottom":"Снизу","marker.value_badge_left":"Слева","marker.value_badge_top":"Сверху","marker.value_badge_empty":"У этого устройства нет доступных значений","marker.value_badge_static":"Статичный значок не показывает живые значения. Настройка сохранится.","marker.value_badge_missing":"Источник недоступен","marker.value_badge_missing_hint":"Сохранённый источник сейчас недоступен. Можно сохранить его, отключить бейдж или выбрать другой.","marker.value_badge_duplicate":"То же значение уже показано внутри значка.","marker.value_badge_state":"Состояние · {name}","marker.value_badge_marker_state":"Состояние источника света · {name}","marker.value_badge_lqi":"Качество Zigbee-сигнала (среднее)","marker.value_badge_attr_current_temperature":"Текущая температура · {name}","marker.value_badge_attr_temperature":"Целевая температура · {name}","marker.value_badge_attr_current_humidity":"Текущая влажность · {name}","marker.value_badge_attr_humidity":"Влажность · {name}","marker.value_badge_attr_current_position":"Положение · {name}","marker.value_badge_attr_percentage":"Скорость · {name}","marker.value_badge_attr_brightness":"Яркость · {name}","marker.value_badge_attr_volume_level":"Громкость · {name}","marker.value_badge_attr_battery_level":"Заряд батареи · {name}","marker.value_badge_attr_fan_speed":"Скорость вентилятора · {name}","marker.value_source":"Источник значения","marker.value_source.help":"Выберите, что заменит значок. Действие по нажатию не изменится.","marker.value_source.help.aria":"Подсказка: источник значения внутри значка","marker.value_source_auto":"Автоматически (как раньше)","marker.value_source_missing_hint":"Сохранённый источник сейчас недоступен. До его восстановления или выбора другого значения внутри будет показано —.","marker.light_role_label":"Является источником света","marker.light_role.help":"«Авто» использует фактическую роль привязанного устройства, «Всегда» принудительно создаёт собственный источник, а «Никогда» исключает его; связанные лампы выше остаются независимыми.","marker.light_role.help.aria":"Подсказка: является ли устройство источником света","marker.light_role_auto_yes":"Автоматически (источник света)","marker.light_role_auto_no":"Автоматически (не источник света)","marker.light_role_always":"Всегда источник света","marker.light_role_never":"Никогда не источник света","marker.light_entity_label":"Ведущая сущность света","marker.light_entity.help":"Для составного устройства выберите сущность, состояние, цвет и яркость которой представляют этот источник на плане. Автоматический вариант сохраняет совместимость со старыми планами.","marker.light_entity.help.aria":"Подсказка: ведущая сущность света","marker.light_entity_auto":"Автоматически ({entity})","marker.light_entity_none":"нет управляемой сущности","marker.light_entity_missing":"Сохранённая сущность {entity} недоступна. Временно используется {fallback}; выбор восстановится, если сущность вернётся.","marker.toggle_entity_label":"Переключаемая сущность","marker.toggle_entity.help":"Для составного устройства выберите собственную лампу или переключатель, которой управляет нажатие. Автоматический вариант сохраняет прежние правила цели и не зависит от ведущей сущности света.","marker.toggle_entity.help.aria":"Подсказка: переключаемая сущность","marker.toggle_entity_auto":"Автоматически ({entity})","marker.toggle_entity_none":"нет собственной управляемой сущности","marker.toggle_entity_missing":"Сохранённой сущности {entity} больше нет среди выбираемых каналов этого маркера. Временно используется {fallback}; выбор восстановится, если сущность вернётся.","marker.glow_color_label":"Цвет и яркость свечения","marker.glow_mode.help":"Используйте данные источника, задайте только цвет или зафиксируйте цвет и яркость. Минимум — 1%; чтобы отключить источник, выберите «Никогда».","marker.glow_mode.help.aria":"Подсказка: цвет и яркость свечения","marker.glow_mode_auto":"Из источника","marker.glow_mode_color":"Задать цвет","marker.glow_mode_fixed":"Задать цвет и яркость","marker.glow_color":"Цвет свечения","marker.glow_brightness":"Яркость","marker.glow_disabled_never":"Настройки свечения недоступны: маркер явно исключён из источников света.","marker.glow_disabled_auto":"В автоматическом режиме у этого маркера не найден пространственный источник света.","marker.glow_disabled_no_entity":"Для пространственного источника нет активной управляемой сущности Home Assistant.","marker.glow_passive_hint":"У источника нет собственных данных Home Assistant. Задайте цвет и яркость вручную; радиус остаётся доступным.","marker.control_broken":"Сохранённый источник отсутствует или больше не отмечен как источник света","marker.control_missing_label":"Отсутствующий источник на плане","marker.control_passive":"пассивный источник","toast.marker_control_cycle":"Такая связь создаст циклическую цепочку управления светом.","toast.marker_binding_required":"Сначала выберите устройство Home Assistant, затем добавьте управляемый источник света.","confirm.unlock_title":"Открыть замок?","confirm.unlock_body":"House Plan отправит этому замку команду открытия.","toast.files_migrate_failed":"Не удалось перенести вложения к новой привязке, ссылки остались на старые файлы: {err}","space.pick_saved":"Уже загруженные","space.pick_saved_hint":"Планы, сохранённые на сервере, включая отцеплённые ранее","space.no_saved":"На сервере пока нет сохранённых планов.","space.loading":"Загрузка…","space.used_by":"используется: {list}","space.in_use":"План используется пространством — сначала отцепите его","btn.use":"Выбрать","confirm.delete_plan_title":"Удалить файл плана?","confirm.delete_plan_body":"Файл будет удалён с сервера. Это действие нельзя отменить.","toast.plans_list_failed":"Не удалось получить список планов: {err}","toast.plan_delete_failed":"Не удалось удалить план: {err}","marker.hide":"Скрыть","marker.hide_tip":"Устройство исчезнет с плана после сохранения, но продолжит участвовать в расчёте сигнала комнаты. Вернуть его можно через каталог «Устройства» в редакторе устройств.","marker.show":"Показать","marker.show_tip":"Устройство снова появится на плане после сохранения.","marker.hidden_ghost":"Устройство скрыто пользователем","marker.ha_disabled_device":"Устройство деактивировано в Home Assistant и скрыто с плана.","marker.ha_disabled_entity":"Сущность деактивирована в Home Assistant и скрыта с плана.","marker.ha_disabled_all_entities":"У устройства нет активных сущностей Home Assistant, поэтому оно скрыто с плана.","marker.ha_registry_limited":"Полный реестр Home Assistant недоступен этому пользователю. Неподтверждённый объект временно нельзя показывать или использовать.","marker.delete_tip":"Полностью удалить устройство с плана и из всех расчётов. Позже его можно добавить заново.","tap.run":"Запустить автоматизацию/скрипт/сцену","tap.none":"Ничего не делать","marker.run_target_label":"Что запускать","marker.run_search_ph":"Поиск: автоматизация, скрипт или сцена…","marker.run_target_gone":"Цель {id} не найдена — выберите заново","marker.tap_confirm":"Спрашивать подтверждение","marker.tap_confirm_tip":"Перед выполнением показать диалог подтверждения — защита от случайных нажатий.","marker.toggle_hint_single":"Цель: {name} ({id}).","marker.virtual_light_target":"Виртуальный свет: {name}.","marker.virtual_light_current":"Ручное состояние: {state} → {effect}.","marker.virtual_light_state_on":"включён","marker.virtual_light_state_off":"выключен","marker.toggle_hint_group":"Переключатся источники ({count}): {names}.","marker.toggle_hint_current":"Сейчас: {state} → {effect}.","marker.toggle_hint_group_current":"Сейчас включено {on} из {count} → {effect}.","marker.toggle_hint_skipped":"Не будут затронуты ({count}): {targets}.","marker.toggle_effect_turn_on":"включится","marker.toggle_effect_turn_off":"выключится","marker.toggle_effect_open":"откроется","marker.toggle_effect_close":"закроется","marker.toggle_effect_stop":"остановится","marker.toggle_effect_toggle":"состояние переключится","marker.toggle_skip_missing":"не найдено","marker.toggle_skip_ha_disabled":"деактивировано в HA","marker.toggle_skip_unavailable":"недоступно","marker.toggle_skip_unsupported":"переключение не поддерживается","marker.toggle_skip_secure":"заблокировано из соображений безопасности","marker.toggle_none_no_binding":"У устройства нет привязки, состояние переключать нечем. По нажатию ничего не произойдёт.","marker.toggle_none_no_actionable_entity":"У устройства нет состояния, которое можно переключить. По нажатию ничего не произойдёт.","marker.toggle_none_configured_targets_missing":"Настроенные цели сейчас недоступны. Собственная сущность устройства не будет подставлена вместо них.","marker.toggle_none_ha_disabled":"Цель деактивирована в Home Assistant и не может использоваться на плане.","marker.toggle_none_unavailable":"Цель сейчас недоступна. По нажатию ничего не произойдёт.","marker.toggle_none_unsupported":"Для этой сущности Home Assistant не предоставляет безопасного переключения. По нажатию ничего не произойдёт.","marker.toggle_none_secure":"Переключение замков, сигнализации и защитных ворот с плана заблокировано из соображений безопасности.","run.automation":"автоматизация","run.script":"скрипт","run.scene":"сцена","confirm.tap_run":"Запустить «{name}»?","confirm.tap_toggle":"Переключить «{name}»?","confirm.current_state":"Текущее состояние: {state}","confirm.expected_state":"После переключения: {state}","confirm.group_current":"включено {on} из {total}","confirm.group_all_on":"все включены","confirm.group_all_off":"все выключены","confirm.unavailable_targets":"Недоступно: {count}","confirm.expected_by_ha":"Состояние определит Home Assistant","confirm.state_on":"Включено","confirm.state_off":"Выключено","confirm.state_open":"Открыто","confirm.state_closed":"Закрыто","confirm.state_opening":"Открывается","confirm.state_closing":"Закрывается","confirm.state_stopped":"Остановлено","confirm.state_unknown":"Неизвестно","toast.run_started":"Запущено: {name}","toast.run_target_missing":"Цель запуска не найдена — проверьте настройки устройства","toast.run_target_required":"Выберите автоматизацию, скрипт или сцену","toast.tap_target_changed":"Цель действия изменилась. Повторите попытку.","toast.virtual_light_toggle_failed":"Не удалось переключить виртуальный свет: {err}","toast.value_badge_source_required":"Выберите значение для бейджа","btn.run":"Выполнить","vac.section":"Робот-пылесос: живая позиция","vac.autocal":"Настроить автоматически","vac.live":"Живая позиция на плане","vac.trail":"Показывать путь робота","vac.autocal_no_rooms":"Интеграция не отдаёт список комнат — откройте «Подогнать вручную»","vac.route_warn_unmapped":"Робот убирает на карте, которая не сопоставлена ни одному этажу","vac.route_warn_needs_calibration":"Карта сопоставлена этажу, но не откалибрована","vac.route_warn_ambiguous":"Две карты неразличимы — этаж не выбран","vac.route_warn_missing_space":"Пространство этой карты удалено","vac.autocal_no_match":"Не совпали имена комнат (нужно ≥3 общих) — откройте «Подогнать вручную»","vac.autocal_done":"Готово: привязка по {rooms} комнатам. Запустите уборку и проверьте","vac.cal_need_pos":"Робот сейчас не отдаёт координаты — запустите уборку и поставьте на паузу","vac.cal_done":"Калибровка сохранена. Запустите уборку и проверьте","vac.cal_cancelled":"Калибровка отменена","vac.fit":"Подогнать вручную","vac.fit_hint":"Перетащите карту робота на место, растяните за уголки","vac.fit_rotate":"Повернуть 90°","vac.fit_mirror":"Отразить","vac.trail_never":"Не показывать никогда","vac.trail_cleaning":"Во время уборки","vac.trail_always":"Показывать всегда","gs.bg_group":"Фон сцены","gs.bg_color":"Цвет фона вокруг плана","gs.bg_default":"Как в теме","gs.bg_theme":"по умолчанию — из темы","gs.bg_mode":"Фон плана","gs.bg_mode.help":"«Следует за Солнцем» использует sun.sun, а при недоступности — локальные часы браузера; статичный режим всегда показывает выбранный цвет.","gs.bg_mode.help.aria":"Подсказка: общий фон плана","gs.bg_static":"Статичный цвет","gs.bg_daynight":"Следует за Солнцем","gs.sun_group":"Солнце","gs.sun_missing":"Сущность sun.sun не найдена — фон следует локальным часам, а оконные лучи недоступны.","gs.north":"Север на плане","gs.north.help":"Угол отсчитывается по часовой стрелке от верхней вертикали плана; север нужен для оконных лучей, а не для фона «Следует за Солнцем».","gs.north.help.aria":"Подсказка: общее направление севера","gs.north_ph":"не задан","gs.north_clear":"Сбросить","gs.north_letter":"С","gs.sun_rays":"Солнце в окнах","gs.about_version":"Houseplan Card v{v}","gs.about_github":"GitHub · документация и issues","gs.about_telegram":"Чат в Telegram","support.title":"Помощь и обратная связь","space.bg_color":"Цвет фона вокруг плана","space.bg_inherit":"Наследовать общий","space.bg_inherited":"наследуется из общих настроек","space.bg_mode":"Фон плана","space.bg_mode.help":"Выберите наследование общего фона либо переопределите это пространство статичным цветом или режимом «Следует за Солнцем».","space.bg_mode.help.aria":"Подсказка: фон пространства","space.north":"Север на плане (переопределение)","space.north.help":"Переопределяет общий север для этого пространства; угол отсчитывается по часовой стрелке от верхней вертикали плана и используется оконными лучами.","space.north.help.aria":"Подсказка: север для пространства","space.north_inherited":"наследуется: {v}","space.sun_rays":"Солнце в окнах","space.sun_inherit":"Наследовать общий","space.sun_on":"Вкл","space.sun_off":"Выкл","canvas.far_objects":"Объектов далеко от плана: {n}","canvas.show_far":"Показать","canvas.home_tip":"План там — нажмите, чтобы вписать","gs.grid_group":"Обслуживание планов","gs.grid_hint":"Обновляет модели данных, выравнивает элементы по сетке и объединяет лишние фрагменты стен. Перед записью будет показан точный отчёт.","gs.align_all":"Оптимизировать планы","gs.align_title":"Оптимизировать планы","gs.align_none":"Все планы уже используют актуальную и оптимальную модель данных.","gs.optimize_no_automatic_changes":"Автоматических изменений нет. Проверьте пункты ниже.","gs.align_count":"Сдвинется элементов: {n} из {total}, максимум на {cm} см.","gs.align_where":"Наибольший сдвиг — в пространстве «{s}».","gs.align_turned":"Проёмов с исправлением угла: {n}.","gs.align_preflight_failed":"Не удалось безопасно проверить геометрию следующих пространств: {spaces}{more}.","gs.align_preflight_hint":"Планы не изменены. Скопируйте диагностику кнопкой ниже и приложите её к отчёту об ошибке вместе с экспортом пространства.","gs.preflight_reason_prepare-exception":"Не удалось подготовить геометрию пространства (исключение при сборке модели)","gs.preflight_reason_wall-null":"Тело стен не построилось (объединение вернуло пустоту)","gs.preflight_reason_wall-degraded-extra":"Тело стен деградировало с лишней геометрией","gs.preflight_reason_wall-failed-core":"Ядро тела стен не собралось","gs.preflight_reason_wall-exception":"Построение стен упало с исключением","gs.preflight_reason_floor-null":"Контур пола не построился","gs.preflight_reason_floor-exception":"Построение пола упало с исключением","gs.preflight_copy":"Скопировать диагностику","gs.preflight_copied":"Диагностика скопирована","gs.preflight_update_hint":"Версии карточки и интеграции различаются — обновите House Plan и повторите.","gs.align_preflight_space":"Пространство {n}","gs.align_preflight_more":" и ещё {n}","gs.optimize_changes":"Миграций модели: {m}; обновлено пространств: {c}; устранён шум координат: {p}; объединено отрезков реальных стен: {w}; объединено отрезков стен нулевой толщины: {s}; независимых: {i}.","gs.zero_walls_migrated":"Преобразовано виртуальных участков: {n}.","gs.wall_segments_migrated":"Стабилизировано сегментов стен: {n}.","gs.room_drafts_migrated":"Незавершённые контуры преобразованы в обычные стены: {drafts}; отрезков: {segments}.","gs.optimize_lattice_summary":"Канонизировано шумовых значений координат: {n}; максимальный сдвиг: {cm} см.","gs.optimize_lattice_space":"{space}: канонизировано значений координат: {n}; оставлено значений вне сетки: {far}.","gs.optimize_coincident_partitions":"Скрытые участки независимых стен поглощены стенами комнат: {n}.","gs.optimize_openings_rehosted":"Проёмы перепривязаны к стенам комнат: {n}.","gs.optimize_walls_straightened":"Выпрямлено стен: {n}; максимальное перемещение: {cm} см.","gs.optimize_walls_straightened_where":"Максимальная правка стены: {s}.","gs.optimize_walls_straighten_skipped":"Оставлено почти осевых стен, которые нельзя безопасно выпрямить: {n}.","gs.optimize_glow_migration":"Старый Glow: пространств — {spaces} → без заливки данных + независимый Glow; комнат — {rooms} → наследуемая заливка + независимый Glow.","gs.optimize_references":"Исправлено ссылок: пространства — {spaces}; комнаты — {rooms}; позиции — {positions}; устройств отвязано от отсутствующих пространств — {detached}.","gs.optimize_reference_more":", и ещё {n}","gs.optimize_orphans_removed":"Убрано забытых записей: {total} — подписи комнат: {rooms}; устройства: {devices}; групповые метки: {groups}. Все они принадлежали пространствам, удалённым ранее.","gs.optimize_live_positions":"Старые позиции в удалённых пространствах принадлежат существующим объектам: {n}{names}. Они будут сохранены.","gs.optimize_live_positions_remove":"Старые позиции в удалённых пространствах принадлежат существующим объектам: {n}{names}. Они выбраны для удаления.","gs.optimize_live_names":": {names}{more}","gs.optimize_live_remove":"Убрать старые позиции","gs.optimize_live_keep":"Сохранить старые позиции","gs.optimize_live_selected":"Старые позиции будут убраны после применения оптимизации.","gs.optimize_unverified":"Не удалось безопасно проверить позиций: {n}. Они оставлены без изменений.","gs.optimize_registry_limited":"Для безопасной проверки нужен полный доступ администратора к реестрам Home Assistant.","gs.optimize_vacuum_warning":"Сопоставления комнат пылесоса требуют проверки: {n}.","gs.optimize_details":"Подробности","gs.optimize_details_more":"И ещё записей: {n}.","gs.optimize_detail_removed":"будет удалено","gs.optimize_detail_live":"будет сохранено","gs.optimize_detail_unverified":"не проверено","gs.optimize_detail_room_label":"подпись комнаты","gs.optimize_detail_device":"устройство","gs.optimize_detail_group":"групповая метка","gs.optimize_detail_unknown":"неизвестный владелец","gs.optimize_detail_item":"{status}: {kind} {id}; прежнее пространство {space}","gs.align_warn":"Элементы, намеренно поставленные между узлами, будут сдвинуты. После операции доступна одна отмена — только до следующего изменения плана.","gs.align_run":"Оптимизировать","gs.align_done":"Планы оптимизированы: сдвинуто элементов — {n}, обслужено записей — {m}, исправлено ссылок — {r}","gs.optimize_undo":"Отменить последнюю оптимизацию","gs.optimize_undone":"Последняя оптимизация отменена","decor.furniture":"Мебель","decor.image":"Изображение","decor.image_title":"Свои изображения","decor.image_upload":"Загрузить изображение","decor.image_replace":"Заменить изображение","decor.image_uploading":"Загрузка…","decor.image_asset":"Файл изображения","decor.image_pick_hint":"Загрузите изображение или выберите уже используемое в House Plan.","decor.image_place_hint":"Кликните по плану, чтобы разместить изображение.","decor.image_none":"Загруженных изображений пока нет.","decor.image_unavailable":"Изображение недоступно","decor.image_used":"Используется в объектах: {n}","decor.image_upload_failed":"Не удалось загрузить изображение: {err}","decor.image_error_capacity":"Хранилище пользовательских изображений заполнено.","decor.image_in_use":"Перед удалением файла удалите все размещённые копии.","decor.image_delete_title":"Удалить файл изображения?","decor.image_delete_message":"Удалить «{name}» из House Plan? Это действие нельзя отменить.","furn.title":"Библиотека мебели","furn.symbol":"Символ","furn.group_furniture":"Мебель","furn.group_appliance":"Техника","furn.group_sanitary":"Сантехника","furn.group_other":"Прочее","furn.width":"Ширина","furn.depth":"Глубина","furn.back_to_categories":"Все категории","furn.pick_hint":"Выберите категорию, затем символ.","furn.place_hint":"Кликните по плану — предмет встанет к ближайшей стене. Shift — свободно.","furn.cat_air_conditioner":"Кондиционеры","furn.cat_armchair":"Кресла","furn.cat_bathtub":"Ванны","furn.cat_bed":"Кровати","furn.cat_bidet":"Биде","furn.cat_boiler":"Бойлеры","furn.cat_chair":"Стулья","furn.cat_coffee_table":"Журнальные столы","furn.cat_cooktop":"Варочные панели","furn.cat_dining_table":"Обеденные столы","furn.cat_dishwasher":"Посудомоечные машины","furn.cat_dryer":"Сушильные машины","furn.cat_fireplace":"Камины","furn.cat_fridge":"Холодильники","furn.cat_kitchen_cabinet":"Кухонные шкафы","furn.cat_kitchen_sink":"Кухонные мойки","furn.cat_nightstand":"Тумбы","furn.cat_plant":"Растения","furn.cat_rug":"Ковры","furn.cat_shelving":"Стеллажи","furn.cat_shower":"Душевые","furn.cat_sink":"Раковины","furn.cat_sofa":"Диваны","furn.cat_stairs":"Лестницы","furn.cat_toilet":"Унитазы","furn.cat_tv":"Телевизоры","furn.cat_wardrobe":"Шкафы","furn.cat_washer":"Стиральные машины","furn.cat_work_table":"Рабочие столы","furn.sym_sofa":"Диван двухместный","furn.sym_sofa_three_seat":"Диван трёхместный","furn.sym_sofa_corner_right":"Угловой диван, правый","furn.sym_armchair":"Кресло мягкое","furn.sym_armchair_office":"Кресло офисное","furn.sym_coffee_table":"Журнальный стол, прямоугольный","furn.sym_coffee_table_round":"Журнальный стол, круглый","furn.sym_coffee_table_oval":"Журнальный стол, овальный","furn.sym_coffee_table_rounded":"Журнальный стол, скруглённый","furn.sym_table_dining":"Обеденный стол, прямоугольный","furn.sym_table_round":"Круглый стол","furn.sym_table_dining_oval":"Обеденный стол, овальный","furn.sym_table_dining_rounded":"Обеденный стол, скруглённый","furn.sym_chair":"Стул","furn.sym_chair_bar":"Барный стул","furn.sym_desk":"Рабочий стол, прямоугольный","furn.sym_desk_corner":"Рабочий стол, угловой","furn.sym_bed_double":"Двуспальная кровать","furn.sym_bed_single":"Односпальная кровать","furn.sym_nightstand":"Тумба прикроватная","furn.sym_cabinet_tv":"Тумба под телевизор","furn.sym_cabinet_shoe":"Тумба для обуви","furn.sym_cabinet_sink":"Тумба под раковину","furn.sym_wardrobe":"Шкаф гардеробный","furn.sym_bookshelf":"Шкаф книжный","furn.sym_wall_unit":"Шкаф-стенка","furn.sym_kitchen_floor":"Кухонный напольный модуль","furn.sym_kitchen_floor_corner":"Кухонный напольный угловой модуль","furn.sym_kitchen_wall":"Кухонный навесной модуль","furn.sym_kitchen_wall_corner":"Кухонный навесной угловой модуль","furn.sym_shelf_floor":"Стеллаж напольный","furn.sym_shelf_wall":"Полка настенная","furn.sym_fridge":"Холодильник","furn.sym_stove":"Варочная панель, 4 конфорки","furn.sym_cooktop_two":"Варочная панель, 2 конфорки","furn.sym_dishwasher":"Посудомоечная машина","furn.sym_washer":"Стиральная машина","furn.sym_dryer":"Сушильная машина","furn.sym_tv":"Телевизор на подставке","furn.sym_tv_wall":"Телевизор на кронштейне","furn.sym_ac":"Кондиционер","furn.sym_water_heater":"Бойлер","furn.sym_toilet":"Унитаз напольный","furn.sym_toilet_built_in":"Унитаз встроенный","furn.sym_bathtub":"Ванна прямоугольная","furn.sym_bathtub_corner":"Ванна угловая","furn.sym_shower":"Душ","furn.sym_sink":"Раковина","furn.sym_kitchen_sink":"Кухонная мойка одинарная","furn.sym_kitchen_sink_double":"Кухонная мойка двойная","furn.sym_bidet":"Биде напольное","furn.sym_bidet_built_in":"Биде встроенное","furn.sym_stairs":"Лестница","furn.sym_fireplace":"Камин","furn.sym_plant":"Растение","furn.sym_rug":"Ковёр","common.yes":"Да","common.no":"Нет","vac.diag_source":"Источник","vac.diag_platform":"Интеграция","vac.diag_status":"Статус","vac.diag_position":"Позиция","vac.diag_rooms":"Комнаты","vac.diag_rooms_value":"{total} · совпало имён: {matched} · {readiness}","vac.autocal_ready":"автокалибровка доступна","vac.autocal_not_ready":"нужно 3 совпавших имени","vac.diag_path":"Путь интеграции","vac.diag_map":"ID карты","vac.source_none":"не выбран","vac.source_status_ok":"Готов","vac.source_status_missing":"Не найден","vac.source_status_disabled":"Деактивирован в Home Assistant","vac.source_status_unavailable":"Недоступен","vac.source_status_unverified":"Нельзя проверить с текущими правами","vac.source_status_unsupported":"Нет данных позиции","vac.source_status_none":"Нет источника","vac.source_banner_missing":"Сохранённый источник больше не существует. Он не заменён автоматически: выберите другой или восстановите его в Home Assistant.","vac.source_banner_disabled":"Сохранённый источник деактивирован в Home Assistant. Активируйте его там или выберите другой.","vac.source_banner_unverified":"Текущих прав Home Assistant недостаточно для проверки источника. Привязка сохранена и не будет заменена автоматически.","vac.choose_source":"Выбрать источник","vac.source_auto":"Автоматически","vac.source_auto_hint":"Использовать совместимую сущность этого устройства","vac.all_cameras":"Все камеры","vac.all_cameras_warn":"Камера может не отдавать данные робота. Выбирайте её только если это карта вашего пылесоса.","vac.all_cameras_empty":"Других сущностей камеры не найдено.","vac.platform_unknown":"интеграция неизвестна","vac.cap_position":"позиция","vac.cap_rooms_short":"комнаты","vac.cap_path":"путь","vac.cap_map":"ID карты","vac.cap_none":"данные робота не обнаружены","vac.xcme_hint":"Включите атрибуты Xiaomi Cloud Map Extractor:","vac.documentation":"Документация","vac.residual_title":"Проверьте автокалибровку","vac.residual_message":"Совпавшие комнаты расходятся максимум на {error}. Примените приблизительную калибровку, подгоните её вручную либо отмените без изменения сохранённых настроек.","vac.apply_proposal":"Применить","gs.backup_group":"Резервная копия и перенос","gs.backup_hint":"Скачайте переносимую JSON-копию или проверьте и импортируйте копию, созданную House Plan.","backup.export_open":"Экспорт","backup.import_open":"Импорт","backup.export_title":"Экспорт House Plan","backup.import_title":"Импорт House Plan","backup.export_hint":"Выберите, должна ли копия содержать всю конфигурацию House Plan или только текущее пространство.","backup.full":"Полная копия","backup.current_space":"Текущее пространство","backup.current_space_title":"Текущее пространство: {title}","backup.no_current_space":"Нет текущего пространства","backup.plan_only":"Только планировка","backup.plan_only_hint":"Сохранить комнаты, стены, проёмы, декор и позиции подписей комнат без устройств и привязок Home Assistant.","backup.plan_only_preview":"Файл содержит только планировку","backup.privacy_warning":"Архив сохраняет названия, идентификаторы Home Assistant и точные координаты. Внутренние планы и вложения указываются ссылками, но не вкладываются; текущие состояния и маршруты пылесосов не включаются.","backup.download":"Скачать JSON","backup.export_done":"Резервная копия скачана","backup.reading":"Проверяем резервную копию…","backup.revalidated":"После предпросмотра план изменился. Сводка обновлена — проверьте её и подтвердите ещё раз.","backup.error.support_invalid_message":"Проверьте сообщение для поддержки и повторите попытку.","backup.error.support_package_too_large":"Обезличенный пакет для поддержки превышает лимит 8 МиБ.","backup.error.support_preview_expired":"Предпросмотр вложения для поддержки истёк или больше недоступен.","backup.error.support_rate_limited":"Запрошено слишком много репортов или предпросмотров. Повторите позже.","backup.error.support_rejected":"Репорт не прошёл проверку службы поддержки.","backup.error.support_unavailable":"Закрытая служба поддержки временно недоступна.","backup.error.unauthorized":"У вас нет прав на экспорт или импорт этого плана.","backup.error.not_ready":"House Plan ещё не готов. Повторите попытку через несколько секунд.","backup.error.too_large":"Размер резервной копии превышает 8 МиБ.","backup.error.invalid_json":"Выбранный файл не является корректным JSON.","backup.error.invalid_format":"Выбранный файл не является резервной копией House Plan.","backup.error.invalid_image":"Изображение повреждено или не соответствует своему формату.","backup.error.unsupported_export_version":"Эта версия формата резервной копии не поддерживается установленной версией.","backup.error.unsupported_image":"Используйте поддерживаемое изображение PNG, JPEG, WebP или SVG.","backup.error.future_model":"Резервная копия создана в более новой версии модели данных House Plan.","backup.error.invalid_config":"Резервная копия содержит некорректную конфигурацию House Plan.","backup.error.wall_model_migration_blocked":"Не удалось безопасно обновить модель стен из резервной копии. Сначала оптимизируйте исходный план и повторите экспорт.","backup.error.invalid_layout":"Резервная копия содержит некорректные позиции объектов.","backup.error.invalid_content":"Резервная копия содержит некорректные или несогласованные ссылки на файлы.","backup.error.space_not_found":"Выбранное пространство больше не существует.","backup.error.capacity_exceeded":"Добавление этой копии превысит ограничения размера плана.","backup.error.preview_expired":"Время предпросмотра истекло. Выберите файл резервной копии заново.","backup.error.preview_owner_mismatch":"Этот предпросмотр принадлежит другому пользователю Home Assistant.","backup.error.conflict":"После предпросмотра план изменился. Проверьте обновлённую сводку.","backup.error.content_confirmation_required":"Подтвердите отсоединение недоступных локальных файлов.","backup.error.commit_failed":"Не удалось безопасно применить копию. Предыдущий план восстановлен или ожидает восстановления.","backup.error.missing_plan":"После предпросмотра исчез связанный файл плана. Проверьте копию ещё раз.","backup.error.missing_content":"После предпросмотра исчез связанный локальный файл. Проверьте копию ещё раз.","backup.error.marker_control_missing":"В резервной копии отсутствует связанный источник света на плане.","backup.error.marker_control_not_light":"Связанная цель больше не отмечена как источник света.","backup.error.marker_control_self":"Источник света не может управлять самим собой.","backup.error.marker_control_cycle":"Резервная копия содержит циклическую цепочку управления светом.","backup.error.duplicate_marker_control":"Резервная копия содержит повторяющуюся связь с источником света.","backup.error.no_backup":"Нет снимка импорта или оптимизации, который можно восстановить.","backup.error.in_use":"Элемент ещё используется","backup.error.invalid_data":"Запрос содержит некорректные данные","backup.error.invalid_light_entity":"Ведущий свет должен быть сущностью light.* или switch.*","backup.error.invalid_marker_control":"Некорректная ссылка управления маркером","backup.error.invalid_name":"Некорректное имя","backup.error.invalid_partition_opening_host":"Проём должен сохранить свою перегородку-носитель","backup.error.invalid_partition_opening_jamb_margin":"Проём не оставляет физического простенка у края стены","backup.error.invalid_passage_fields":"Открытый проход не может нести настройки двери","backup.error.invalid_space_id":"Неизвестное пространство","backup.error.invalid_toggle_entity":"Сущность переключения должна быть light.* или switch.*","backup.error.invalid_value_badge":"Некорректные настройки бейджа значения","backup.error.invalid_value_badge_attribute":"Некорректный атрибут бейджа значения","backup.error.invalid_value_badge_position":"Некорректная позиция бейджа значения","backup.error.invalid_value_badge_source":"Некорректный источник бейджа значения","backup.error.invalid_vacuum_map_route":"Проверьте сопоставление карт робота пространствам.","backup.error.invalid_value_source":"Некорректный источник значения","backup.error.invalid_value_source_attribute":"Некорректный атрибут источника значения","backup.error.io_error":"Файловая операция на сервере не удалась","backup.error.not_toggleable":"Это устройство нельзя переключить","backup.error.nothing_to_repair":"Нечего чинить","backup.error.space_in_use":"На пространство ещё есть ссылки","backup.error.value_badge_source_required":"Бейджу значения нужен источник","backup.error.wall_model_client_outdated":"План обновлён в другом месте — перезагрузите страницу","backup.same_source":"Создано на этом экземпляре Home Assistant","backup.foreign_source":"Создано на другом экземпляре Home Assistant","backup.created":"Создано: {value}","backup.versions":"Карточка {card}; интеграция {integration}; модель данных {model}","backup.count_spaces":"Пространств: {n}","backup.count_rooms":"Комнат: {n}","backup.count_walls":"Стен: {n}","backup.count_openings":"Проёмов: {n}","backup.count_decor":"Объектов декора: {n}","backup.count_markers":"Устройств: {n}","backup.count_layout":"Позиций: {n}","backup.bindings":"Привязки — устройства: {device}, сущности: {entity}, виртуальные: {virtual}; позиций без пространства: {legacy}","backup.binding_status":"Статус на целевом экземпляре — активных: {active}, деактивированных: {disabled}, отсутствующих: {missing}","backup.missing_areas":"На целевом экземпляре отсутствуют зоны: {areas}","backup.dropped_marker_links":"Связи с источниками света вне переносимого пространства пропущены: {n}.","backup.room_drafts_migrated":"Старые незавершённые контуры преобразованы в обычные стены: {drafts}; отрезков: {segments}.","backup.repaired_target_refs":"Существующих ссылок восстановлено этим импортом: {n}.","backup.preserved_unresolved_refs":"Неоднозначные ссылки сохранены без изменений: {n}.","backup.preserved_unresolved_hint":"House Plan ничего не угадывал и не удалял. После импорта запустите «Оптимизировать планы», чтобы проверить оставшиеся ссылки.","backup.import_details":"Подробности восстановления ссылок","backup.import_detail.incoming_remapped":"Ссылок обновлено внутри импортируемой копии: {n}","backup.import_detail.target_repaired":"Существующих ссылок восстановлено: {n}","backup.import_detail.preserved_unresolved":"Неразрешимых ссылок сохранено: {n}","backup.import_detail.collisions":"Конфликтов назначения безопасно сохранено: {n}","backup.import_detail.dropped_links":"Входящих связей пропущено по правилам переноса: {n}","backup.import_detail.bounded_lineages":"Чрезмерно вложенных идентификаторов ограничено: {n}","backup.replace_warning":"Текущая конфигурация и расположение будут заменены. Загруженные файлы не удаляются. Одну отмену можно выполнить до следующего изменения плана.","backup.foreign_bookkeeping":"Служебные списки известных и новых устройств другого экземпляра импортированы не будут.","backup.final_name":"Название нового пространства","backup.target_settings":"Глобальные настройки целевого экземпляра не изменятся.","backup.duplicates":"Уже существующих привязок: {n}","backup.skip":"Пропустить повторяющиеся устройства","backup.virtual_copy":"Добавить безопасные статичные виртуальные копии","backup.content":"Связанное содержимое","backup.decor_images_summary":"Свои изображения: объектов — {objects}, файлов — {assets}; отсутствует файлов — {missing}.","backup.content_available":"доступно локально","backup.content_external":"внешняя ссылка","backup.content_detach_required":"будет отвязано","backup.confirm_detach":"Я понимаю, что недоступные внутренние планы и вложения будут отвязаны от импортируемой конфигурации.","backup.confirm_missing_images":"Я понимаю, что отсутствующие свои изображения останутся восстанавливаемыми заглушками, а остальные недоступные локальные файлы будут отвязаны.","backup.replace":"Заменить","backup.add":"Добавить пространство","backup.space_done":"Пространство импортировано: комнат — {rooms}, устройств — {markers}, существующих ссылок восстановлено — {refs}","backup.full_done":"Копия восстановлена: пространств — {spaces}, комнат — {rooms}, устройств — {markers}","backup.undo_import":"Отменить последний полный импорт","backup.import_undone":"Полный импорт отменён","backdrop.large_title":"Большое изображение","backdrop.large_body":"Изображение {w}×{h} ({fileMb} МБ), для показа потребуется около {decodedMb} МБ памяти. На планшетах это может привести к падению страницы.","backdrop.unknown_body":"Не удалось прочитать размеры изображения — файл может быть повреждён. Продолжение может привести к падению страницы на планшете.","backdrop.reduced_dimensions":"Уменьшенная копия: {w}×{h} px.","backdrop.use_downscaled":"Загрузить уменьшенную копию","backdrop.reducing":"Уменьшаем…","backdrop.keep_original":"Оставить оригинал","backdrop.too_large_title":"Изображение слишком большое","backdrop.too_large_body":"Изображение превышает возможности браузера ({w}×{h}, предел {limit} px по стороне). Уменьшите его в редакторе на компьютере и загрузите снова.","backdrop.downscale_failed":"Не удалось создать уменьшенную копию. Текущий план не изменён."}},{code:"de",nativeLabel:"Deutsch",loadDictionary:async function(e){const t=0===e?await import("./de-CnIkrYVa.js"):await import(new URL("./de-CnIkrYVa.js?retry",import.meta.url).href);return{dictionary:t.dictionary,fingerprint:t.fingerprint}}},{code:"fr",nativeLabel:"Français",loadDictionary:async function(e){const t=0===e?await import("./fr-D1gV1f-s.js"):await import(new URL("./fr-D1gV1f-s.js?retry",import.meta.url).href);return{dictionary:t.dictionary,fingerprint:t.fingerprint}}}],Yu=ju,Xu=new Set;const Zu=new class{constructor(e,t,i=console.warn,n){this.entries=e,this.expectedFingerprint=t,this.warn=i,this.loadFailed=n,this.dictionaries=new Map,this.pending=new Map,this.failed=new Set;for(const t of e)t.dictionary&&this.dictionaries.set(t.code,t.dictionary)}state(e){return this.dictionaries.has(e)?"ready":this.failed.has(e)?"fallback":"pending"}dictionary(e){return this.dictionaries.get(e)}ensure(e){if("pending"!==this.state(e))return Promise.resolve();const t=this.pending.get(e);if(t)return t;const i=this.entries.find(t=>t.code===e),n=this.load(i).finally(()=>this.pending.delete(e));return this.pending.set(e,n),n}async load(e){if(!e?.loadDictionary)return void(e&&this.failed.add(e.code));let t;for(const i of[0,1])try{const t=await e.loadDictionary(i);if(t.fingerprint!==this.expectedFingerprint)throw new Error(`locale fingerprint mismatch for ${e.code}`);return this.dictionaries.set(e.code,t.dictionary),void this.failed.delete(e.code)}catch(e){t=e}this.failed.add(e.code),this.warn(`[houseplan] unable to load ${e.code} locale; using English`,t),this.loadFailed?.(e.code)}}(Ku,"2e6f7d70c797ae4e865b10859c77cc3380a432272a975b8f35b51234ae3cfe62",console.warn,function(e){for(const t of Xu)t(e)});function Ju(e){const t=tp(e)?.code??"en";return Zu.dictionary(t)??Yu}function Qu(e){return"string"==typeof e?e.trim().replaceAll("_","-").toLowerCase():""}const ep=new Map(Ku.map(e=>[Qu(e.code),e]));function tp(e){return ep.get(Qu(e))}function ip(e,t){const i=[{value:"",label:e},...Ku.map(({code:e,nativeLabel:t})=>({value:e,label:t}))],n="string"==typeof t?t:"";return n&&!i.some(e=>e.value===n)&&i.push({value:n,label:tp(n)?.nativeLabel??n}),i}function np(e,t){return function(e,t,i,n){const r=new Map(i.map(e=>[Qu(e),e])),o=r.get(Qu(e));if(o)return o;const s=Qu(t),a=r.get(s);return a||(r.get(s.split("-")[0]||"")??n)}(t,e?.locale?.language||e?.language,Ku.map(({code:e})=>e),"en")}function rp(e,t,i){return Qi(Ju(e)[t]??Yu[t]??t,i)}function op(e,t){const i=Ju(e)[t]??Yu[t];return"string"==typeof i&&i.trim().length>0}function sp(e,t,i,n){return{ox:0,oy:0}}function ap(e,t){const i=(e.angle+90)*Math.PI/180,n=Oa(16,t),r=e.gateFace?-n*e.gateFace.side:n*(e.flipV?-1:1);return[[e.x+Math.cos(i)*r,e.y+Math.sin(i)*r],r<0]}function lp(e){const t=e.length/2,i=e.face.cm>0?e.face.cm/e.cellCm*e.gridPitch/2:Oa(4,e.cellCm),n="gate"===e.type?Math.sin(10*Math.PI/180)*t:0;return{half:t,jambHalf:i,gateDepth:n,outlineHalf:Math.max(Oa(16,e.cellCm),i+Oa(8,e.cellCm),n+Oa(8,e.cellCm)),hitHalf:Math.max(Oa(20,e.cellCm),i+Oa(10,e.cellCm),n+Oa(12,e.cellCm))}}function cp(e,t,i){e.minX=Math.min(e.minX,t),e.minY=Math.min(e.minY,i),e.maxX=Math.max(e.maxX,t),e.maxY=Math.max(e.maxY,i)}function hp(e,t,i,n,r,o,s,a){const l=Math.min(s,a)*Math.PI/180,c=Math.max(s,a)*Math.PI/180,h=(e,t)=>{const i=Math.atan2(t,e),n=[l,c];for(let e=-3;e<=3;e++){const t=e*Math.PI-i,r=Math.PI/2+e*Math.PI-i;t>l&&tl&&r0&&[e.length,e.angle,t[0],t[1]].every(Number.isFinite)))return null;const{half:i,jambHalf:n}=lp(e),r=Ia(e.cellCm),o=1.75*r,s=1.25*r,a=.75*r,l={minX:-i-s,minY:-n-s,maxX:i+s,maxY:n+s},c={minX:1/0,minY:1/0,maxX:-1/0,maxY:-1/0};if("window"===e.type)hp(c,-i,0,i,-o,o,-90,0),hp(c,i,-i,0,-o,o,0,90),cp(c,-i-a,-i-a),cp(c,i+a,a);else if("gate"===e.type){const t=10*e.face.side;hp(c,-i,0,i,-o,o,0,t),hp(c,i,-i,0,-o,o,-t,0)}else hp(c,-i,0,e.length,-o,o,-90,0),cp(c,-i-a,-e.length-a),cp(c,i+a,a);const[h,d]=dp(e),u={...l};cp(u,c.minX+h,c.minY+d),cp(u,c.maxX+h,c.maxY+d);const p=e.flipH?-1:1,_="gate"===e.type?1:e.flipV?-1:1,m=e.angle*Math.PI/180,g=Math.cos(m),f=Math.sin(m),v={minX:1/0,minY:1/0,maxX:-1/0,maxY:-1/0};for(const e of[u.minX,u.maxX])for(const i of[u.minY,u.maxY]){const n=e*p,r=i*_;cp(v,t[0]+n*g-r*f,t[1]+n*f+r*g)}return v}function pp(e){if("passage"===e.type)return W``;const t=Math.max(0,Math.min(1,e.amount)),{half:i,jambHalf:n}=lp(e),r=Ia(e.cellCm),o=1.75*r,s=e.flipH?-1:1,a=e.flipV?-1:1,l="gate"===e.type?1:a,[c,h]=dp(e);let d;if("window"===e.type){const o=Math.PI/2*i,s=e.face.cm>0?W``:W``;d=W`
e.frontendVersion===t.frontendVersion&&e.backendVersion===t.backendVersion&&e.kiosk===t.kiosk&&e.reducedMotion===t.reducedMotion)(this._input,t)||!((e,t)=>e.kind===t.kind&&("unknown"===e.kind||"unknown"!==t.kind&&e.frontend===t.frontend&&e.backend===t.backend))(this._relation,i);this._input=t,this._relation=i,n&&this._reconcile()}finishBannerExit(e){this._banner&&"leaving"===this._banner.phase&&this._banner.token===e&&(this._banner=null,this.hooks.changed())}_reconcile(){if(this._cancelTimer(),!this._connected||"mismatch"!==this._relation.kind)return this._attemptTarget=null,this._attemptState=null,void this._hideBanner();if(!this._input.kiosk)return this._attemptTarget=null,this._attemptState=null,void this._showBanner(this._relation.frontend,this._relation.backend);const e=this._relation.backend;if(this._attemptTarget===e&&null!==this._attemptState||(this._attemptTarget=e,this._attemptState=function(e,t){try{const i=e();return i?i.getItem(tg)===t?"attempted":"fresh":"unavailable"}catch{return"unavailable"}}(this.hooks.storage,e)),"fresh"===this._attemptState)return this._hideBanner(),void this._armTimer();this._showBanner(this._relation.frontend,e)}_armTimer(){this._connected&&void 0===this._timer&&"mismatch"===this._relation.kind&&this._input.kiosk&&"fresh"===this._attemptState&&(this._timer=this.hooks.clock.setTimeout(()=>{this._timer=void 0,this._tick()},250))}_cancelTimer(){void 0!==this._timer&&(this.hooks.clock.clearTimeout(this._timer),this._timer=void 0)}_tick(){if(!this._connected||"mismatch"!==this._relation.kind||!this._input.kiosk||"fresh"!==this._attemptState)return;if(!function(e){return e.connected&&e.initialFrameSettled&&e.viewOnly&&e.surfacesIdle&&e.configWritesIdle&&e.physicalWritesIdle&&e.layoutWritesIdle&&e.gesturesIdle&&e.interactionPauseElapsed&&e.baseZoom}(this.hooks.safety()))return void this._armTimer();const e=this._relation.backend,t=function(e,t){try{const i=e();return i?i.getItem(tg)===t?"attempted":(i.setItem(tg,t),"claimed"):"unavailable"}catch{return"unavailable"}}(this.hooks.storage,e);if(this._attemptTarget=e,this._attemptState="claimed"===t?"attempted":t,"claimed"===t){this._showBanner(this._relation.frontend,e);try{this.hooks.reload()}catch{}}else this._showBanner(this._relation.frontend,e)}_showBanner(e,t){"visible"===this._banner?.phase&&this._banner.frontend===e&&this._banner.backend===t||(this._banner={frontend:e,backend:t,phase:"visible",token:++this._noticeToken},this.hooks.changed())}_hideBanner(){if(this._banner)return this._input.reducedMotion?(this._banner=null,void this.hooks.changed()):void("leaving"!==this._banner.phase&&(this._banner={...this._banner,phase:"leaving",token:++this._noticeToken},this.hooks.changed()))}}const rg=1;function og(e,t){const i=t&&"object"==typeof t?t:{};e._haIntegrationVersion=ig(i.integration_version);const n=i.support_api;e._haSupportApi="number"==typeof n&&Number.isSafeInteger(n)?n:null,e._haDecorAssetsApi=1===i.decor_assets_api?1:null,e._haSummaryPanelApi=1===i.summary_panel_api?1:null,e._haRadarStage1Api=1===i.radar_stage1_api?1:null,e._syncVersionRecovery()}function sg(e){const t=e._stageEl,i=e._loadOk&&!e._loading&&e._continuityDataReady&&!e._resumeSettling&&!e._connectionWasLost&&!e._booting&&!e._bootFading&&!e._bootSettling&&!e._bootSoft&&e._continuity.hasCompleteFrame&&"steady"===e._continuity.state&&!e._continuity.overlayBlocksInteraction&&!!t&&t.clientWidth>0&&t.clientHeight>0,n=!(0!==e._pointers.size||0!==e._touchContacts.size||e._touchSequenceMultitouch||e._roomPointer||e._panStart||e._panLock||e._pinchStart||e._swipeStart||e._tabDrag||e._tabDragRelease||e._drag||e._deviceDrag||e._rlResize||e._resize?.dragging||e._physicalDrag||e._physicalRotate||e._opDrag||e._decorDraft||e._decorMove||e._dtDrag||e._bdDrag||e._furnTouchPending||e._compassDrag||e._viewportGestureDirty||e._devicePositionBusy||e._modeTransitionBusy||e._cameraTransition.active||e._slide||0!==e._warmModeRequest),r=!(e._editorSecondaryDialogBlocked||e._partitionDeleteDialog||e._roomDeleteDialog||e._backdropGuard||e._vacFit||e._editorSecondary?.hasOpenGroup||e._furnPalette||e._decorImagePalette);return{connected:e.isConnected,initialFrameSettled:i,viewOnly:!0===e._config?.kiosk&&"view"===e._mode&&!e._editing,surfacesIdle:r,configWritesIdle:0===e._writesPending&&!e._saveConfigDebounced.pending(),physicalWritesIdle:0===e._pendingPhysicalWrites.size,layoutWritesIdle:!e._persistLayout.pending()&&0===e._dirtyPos.size&&0===e._sentPos.size&&!e._devicePositionBusy,gesturesIdle:n,interactionPauseElapsed:Date.now()>=e._cyclePausedUntil,baseZoom:e._zoom<=1.001}}class ag{constructor(){this.seen=null,this.diagnosticsCache=null}observe(e,t,i,n){this.invalidateDiagnosticsForHass(e,t,i),this.intake(t,n)}intake(e,t){e&&this.seen!==e&&(this.seen=e,t())}invalidate(){this.diagnosticsCache=null}invalidateDiagnosticsForHass(e,t,i){this.diagnosticsCache&&(e?.entities!==t?.entities||e?.devices!==t?.devices||[...i?.entityIds||[]].some(i=>!!e?.states?.[i]!=!!t?.states?.[i]))&&this.invalidate()}diagnostics(e,t,i){if(this.diagnosticsCache)return this.diagnosticsCache;const n={active:0,ha_disabled:0,orphaned:0,unverified:0};for(const e of t)e.removed||"virtual"===e.binding||n[i(e.binding).kind]++;return this.diagnosticsCache={registry:Jh(e),bindings:n},this.diagnosticsCache}}function lg(e){const t=e;t._hassSequence++,t._renderSnapshotAt=Date.now(),t._continuity.note("hass-snapshot"),t._ensureHaRegistryAuthority(),t._planHassMemo=null,t._hookConnection(),!t._loadOk&&!t._loading&&t._loadTries<8&&t._loadFromServer(),t._maybeRebuildDevices(),t._vacTick(),t._activityTick()}function cg(e){return!!e&&"object"==typeof e&&1===e.version}function hg(e,t){const i=e.radar;return e.space===t&&!0!==e.hidden&&!0!==e.removed&&cg(i)&&!0===i.enabled&&!1!==i.show_live}const dg={ok:"radar.health_ok",off:"radar.health_off",stale:"radar.health_stale",partial:"radar.health_partial",restricted:"radar.health_restricted",incomplete:"radar.health_incomplete",position_unavailable:"radar.health_position_unavailable",unavailable:"radar.health_unavailable",needs_setup:"radar.health_needs_setup",inconsistent:"radar.health_inconsistent",unknown:"radar.health_unknown"};const ug=e=>"number"==typeof e&&Number.isFinite(e);class pg{constructor(e){this.host=e,this.frames=new Map,this.connection=null,this.space="",this.generation=0,this.expiryTimer=0,this.deadlines=new Map}sync(e,t){const i=this.host.hass?.connection;if(!t||!i||!this.host.isConnected)return void this.stop();if(this.unsubscribe&&this.connection===i&&this.space===e)return;this.stop(),this.connection=i,this.space=e;const n=++this.generation,r=i.subscribeMessage?.bind(i);"function"==typeof r&&Promise.resolve(r(e=>{if(n!==this.generation||!this.host.isConnected)return;const t=function(e){if(!e||"object"!=typeof e)return null;const t=e;if("string"!=typeof t.marker_id||"string"!=typeof t.server_session_id||!Number.isSafeInteger(t.seq)||"string"!=typeof t.health)return null;const i=Array.isArray(t.targets)?t.targets.slice(0,256).flatMap(e=>{if(!e||"object"!=typeof e)return[];const t=e;return"string"==typeof t.slot&&ug(t.x)&&ug(t.y)&&ug(t.expires_at)&&ug(t.reported_at)&&("bounded_latest"===t.pair_quality||"coherent"===t.pair_quality)?[{...t,included:!0===t.included,smooth:!0===t.smooth}]:[]}):[],n=Array.isArray(t.ranges)?t.ranges.slice(0,64).flatMap(e=>{if(!e||"object"!=typeof e)return[];const t=e;if(!("string"==typeof t.id&&ug(t.x)&&ug(t.y)&&ug(t.radius)&&ug(t.expires_at)&&ug(t.reported_at)))return[];const i=Array.isArray(t.segments)?t.segments.slice(0,64).flatMap(e=>{if(!Array.isArray(e))return[];const t=e.slice(0,181).flatMap(e=>Array.isArray(e)&&2===e.length&&ug(e[0])&&ug(e[1])?[[e[0],e[1]]]:[]);return t.length>=2?[t]:[]}):void 0;return[{...t,...i?{segments:i}:{}}]}):[],r=Array.isArray(t.zones)?t.zones.slice(0,64).flatMap(e=>{if(!e||"object"!=typeof e)return[];const t=e;if("string"!=typeof t.id)return[];const i=t.state;if(null!==i&&"boolean"!=typeof i&&!ug(i))return[];const n=Array.isArray(t.polygon)?t.polygon.slice(0,64).flatMap(e=>Array.isArray(e)&&2===e.length&&ug(e[0])&&ug(e[1])?[[e[0],e[1]]]:[]):[];return[{id:t.id,state:i,...n.length>=3?{polygon:n}:{}}]}):[];return{server_session_id:t.server_session_id,marker_id:t.marker_id,source_generation:"string"==typeof t.source_generation?t.source_generation:void 0,calibration_revision:"string"==typeof t.calibration_revision?t.calibration_revision:void 0,seq:t.seq,reported_at:ug(t.reported_at)?t.reported_at:void 0,expires_at:ug(t.expires_at)?t.expires_at:void 0,health:t.health,reported_presence:"boolean"==typeof t.reported_presence?t.reported_presence:null,complete:!0===t.complete,targets:i,ranges:n,zones:r}}(e);if(!t)return;if(!function(e,t){return!e||t.server_session_id!==e.server_session_id||t.source_generation!==e.source_generation||t.calibration_revision!==e.calibration_revision||t.seq>e.seq}(this.frames.get(t.marker_id),t))return;const i=function(e,t=Date.now()){if(!ug(e.expires_at))return null;if(!ug(e.reported_at))return Math.max(0,1e3*e.expires_at-t);const i=Math.max(0,1e3*(e.expires_at-e.reported_at)),n=Math.max(0,t-1e3*e.reported_at);return Math.max(0,i-n)}(t);"restricted"===t.health||"disabled"===t.health||0===i?(this.frames.delete(t.marker_id),this.deadlines.delete(t.marker_id)):(this.frames.set(t.marker_id,t),null==i?this.deadlines.delete(t.marker_id):this.deadlines.set(t.marker_id,this.monotonicNow()+i)),this.armExpiry(),this.host.requestUpdate()},{type:"houseplan/radar/subscribe",space_id:e})).then(e=>{n===this.generation&&this.host.isConnected?"function"==typeof e&&(this.unsubscribe=e):"function"==typeof e&&e()}).catch(()=>{n===this.generation&&this.stop()})}stop(){this.generation++,this.unsubscribe?.(),this.unsubscribe=void 0,this.connection=null,this.space="",clearTimeout(this.expiryTimer),this.expiryTimer=0,this.frames.size&&(this.frames.clear(),this.host.isConnected&&this.host.requestUpdate()),this.deadlines.clear()}armExpiry(){clearTimeout(this.expiryTimer);const e=this.monotonicNow(),t=[...this.deadlines.values()].filter(t=>t>e);if(!t.length)return;const i=Math.max(20,Math.min(...t)-e+10);this.expiryTimer=window.setTimeout(()=>{this.expiryTimer=0;let e=!1;const t=this.monotonicNow();for(const[i,n]of this.deadlines)n>t||(this.deadlines.delete(i),this.frames.delete(i),e=!0);this.armExpiry(),e&&this.host.isConnected&&this.host.requestUpdate()},i)}monotonicNow(){return globalThis.performance?.now?.()??Date.now()}}const _g=Object.freeze({enabled:!1,z2mBaseTopics:Object.freeze([])});function mg(e){if("string"!=typeof e)return null;const t=e.trim().replace(/^\/+|\/+$/g,"").replace(/\/{2,}/g,"/");return!t||t.length>180||/[#+\u0000-\u001f\u007f]/.test(t)?null:t}function gg(e){const t=e?.zigbee_topology;if(!t||"object"!=typeof t)return _g;const i=t,n=Array.isArray(i.z2m_base_topics)?i.z2m_base_topics:Array.isArray(i.z2mBaseTopics)?i.z2mBaseTopics:[],r=new Set,o=[];for(const e of n){const t=mg(e);if(t&&!r.has(t)&&(r.add(t),o.push(t),8===o.length))break}return{enabled:!0===i.enabled,z2mBaseTopics:o}}function fg(e,t){const i={...e},n=t.z2mBaseTopics.map(mg).filter(Boolean);return t.enabled||n.length?i.zigbee_topology={enabled:!0===t.enabled,z2m_base_topics:[...new Set(n)].slice(0,8)}:delete i.zigbee_topology,i}const vg={now:()=>performance.now(),requestFrame:e=>requestAnimationFrame(e),cancelFrame:e=>cancelAnimationFrame(e)},yg=e=>Math.max(0,Math.min(1,e)),bg=(e,t,i)=>e+(t-e)*i,wg=(e,t,i)=>{const n=1-e;return 3*n*n*e*t+3*n*e*e*i+e*e*e},kg=e=>{const t=yg(e);if(0===t||1===t)return t;let i=0,n=1,r=t;for(let e=0;e<12;e++)r=(i+n)/2,wg(r,.2,.2)0&&e.w>0?t/e.w:1,viewBox:{...e}}}function Sg(e,t,i){const n=Math.max(1e-9,e.pixelsPerUnit),r=Math.max(1e-9,t/n),o=Math.max(1e-9,i/n);return{x:e.centerX-r/2,y:e.centerY-o/2,w:r,h:o}}function $g(e){const t=e.trim(),i=/^rgba?\(\s*([\d.]+)[, ]+([\d.]+)[, ]+([\d.]+)(?:\s*[,/]\s*([\d.]+))?\s*\)$/i.exec(t);if(i)return[Number(i[1]),Number(i[2]),Number(i[3]),null==i[4]?1:Number(i[4])];const n=/^#([0-9a-f]{6}|[0-9a-f]{8})$/i.exec(t)?.[1];return n?[parseInt(n.slice(0,2),16),parseInt(n.slice(2,4),16),parseInt(n.slice(4,6),16),8===n.length?parseInt(n.slice(6,8),16)/255:1]:null}function Mg(e,t,i){const n=$g(e),r=$g(t);if(!n||!r)return i<.5?e:t;const o=yg(i);return`rgba(${Math.round(bg(n[0],r[0],o))}, ${Math.round(bg(n[1],r[1],o))}, ${Math.round(bg(n[2],r[2],o))}, ${bg(n[3],r[3],o).toFixed(3)})`}class Rg{constructor(e,t=vg){this._hooks=e,this._clock=t,this._token=0,this._raf=0,this._state=null}get state(){return this._state}get active(){return"running"===this._state?.phase||"preparing"===this._state?.phase}get presented(){return this._state?.presented||null}start(e,t,i,n=220){this.cancel(!1);const r=++this._token,o=this._clock.now();if(this._state={token:r,phase:n<=0?"settling":"running",from:e,to:t,presented:n<=0?t:e,startedAt:o,duration:Math.max(0,n),targetMode:i},n<=0)return this._hooks.frame(this._state),this._hooks.settled(this._state),this._state=null,r;this._hooks.frame(this._state);const s=e=>{const t=this._state;if(!t||t.token!==r)return;const i=yg((e-t.startedAt)/t.duration);t.presented=i>=1?t.to:function(e,t,i){const n=kg(i),r=bg(e.stageWidth,t.stageWidth,n),o=bg(e.stageHeight,t.stageHeight,n),s=Math.max(1e-9,e.viewport.pixelsPerUnit),a=Math.max(1e-9,t.viewport.pixelsPerUnit),l={centerX:bg(e.viewport.centerX,t.viewport.centerX,n),centerY:bg(e.viewport.centerY,t.viewport.centerY,n),pixelsPerUnit:Math.exp(bg(Math.log(s),Math.log(a),n))};return{presentedMode:n<.5?e.presentedMode:t.presentedMode,editorChromeHeight:bg(e.editorChromeHeight,t.editorChromeHeight,n),stageWidth:r,stageHeight:o,viewport:{...l,viewBox:Sg(l,r,o)},stageColor:Mg(e.stageColor,t.stageColor,n),paperColor:Mg(e.paperColor,t.paperColor,n),sceneBrightness:bg(e.sceneBrightness,t.sceneBrightness,n),architectureOpacity:bg(e.architectureOpacity,t.architectureOpacity,n),backdropOpacity:bg(e.backdropOpacity,t.backdropOpacity,n),viewWeight:bg(e.viewWeight,t.viewWeight,n),editorWeight:bg(e.editorWeight,t.editorWeight,n),toolbarContentOpacity:bg(e.toolbarContentOpacity,t.toolbarContentOpacity,n)}}(t.from,t.to,i),t.phase=i>=1?"settling":"running",this._hooks.frame(t),i<1?this._raf=this._clock.requestFrame(s):(this._raf=0,this._hooks.settled(t),this._state?.token===r&&(this._state=null))};return this._raf=this._clock.requestFrame(s),r}cancel(e=!0){this._raf&&this._clock.cancelFrame(this._raf),this._raf=0;const t=this._state;this._state=null,this._token++,t&&e&&(t.phase="settling",t.presented=t.to,this._hooks.frame(t),this._hooks.settled(t))}dispose(){this.cancel(!1)}}const Cg={now:()=>"undefined"!=typeof performance?performance.now():Date.now(),requestFrame:e=>"function"==typeof requestAnimationFrame?requestAnimationFrame(e):null,cancelFrame:e=>{"function"==typeof cancelAnimationFrame&&cancelAnimationFrame(e)}},Tg=e=>Number.isFinite(e);function Dg(e){return!!e&&Tg(e.zoom)&&e.zoom>0&&Tg(e.viewBox.x)&&Tg(e.viewBox.y)&&Tg(e.viewBox.w)&&e.viewBox.w>0&&Tg(e.viewBox.h)&&e.viewBox.h>0}function Ag(e){return{zoom:e.zoom,viewBox:{...e.viewBox}}}function Pg(e,t){return Math.abs(e.zoom-t.zoom)<1e-9&&Math.abs(e.viewBox.x-t.viewBox.x)<1e-6&&Math.abs(e.viewBox.y-t.viewBox.y)<1e-6&&Math.abs(e.viewBox.w-t.viewBox.w)<1e-6&&Math.abs(e.viewBox.h-t.viewBox.h)<1e-6}const Fg=(e,t,i)=>e+(t-e)*i,zg=(e,t,i)=>Math.exp(Fg(Math.log(e),Math.log(t),i));class Ig{constructor(e,t=Cg){this._hooks=e,this._clock=t,this._token=0,this._raf=null,this._state=null}get state(){return this._state}get active(){return"running"===this._state?.phase}get presented(){return this._state?.presented||null}get target(){return this._state?.to||null}start(e,t,i,n){this.cancel(!1);const r=++this._token,o=Ag(e),s=Ag(t),a=n>0&&Dg(o)&&Dg(s),l=this._clock.now(),c={token:r,phase:a?"running":"settling",from:o,to:s,presented:Ag(a?o:s),startedAt:l,duration:a?n:0,reason:i};if(this._state=c,this._hooks.frame(c),!a)return this._settle(r),r;const h=e=>{const t=this._state;if(!t||t.token!==r)return;const i=Math.max(0,Math.min(1,(e-t.startedAt)/t.duration));if(t.presented=i>=1?Ag(t.to):function(e,t,i){if(!Dg(e))return Ag(t);if(!Dg(t))return Ag(e);const n=kg(i);if(n<=0)return Ag(e);if(n>=1)return Ag(t);const r=e.viewBox.x+e.viewBox.w/2,o=e.viewBox.y+e.viewBox.h/2,s=t.viewBox.x+t.viewBox.w/2,a=t.viewBox.y+t.viewBox.h/2,l=zg(e.viewBox.w,t.viewBox.w,n),c=zg(e.viewBox.h,t.viewBox.h,n),h=Fg(r,s,n),d=Fg(o,a,n);return{zoom:zg(e.zoom,t.zoom,n),viewBox:{x:h-l/2,y:d-c/2,w:l,h:c}}}(t.from,t.to,i),t.phase=i>=1?"settling":"running",this._hooks.frame(t),i>=1)return this._raf=null,void this._settle(r);this._raf=this._clock.requestFrame(h),null===this._raf&&this._settle(r)};return this._raf=this._clock.requestFrame(h),null===this._raf&&(c.phase="settling",c.presented=Ag(s),this._hooks.frame(c),this._settle(r)),r}cancel(e=!0){null!==this._raf&&this._clock.cancelFrame(this._raf),this._raf=null;const t=this._state;this._state=null,this._token++,t&&e&&(t.phase="settling",t.presented=Ag(t.to),this._hooks.frame(t),this._hooks.settled(t))}dispose(){this.cancel(!1)}_settle(e){const t=this._state;t&&t.token===e&&(t.phase="settling",t.presented=Ag(t.to),this._hooks.settled(t),this._state?.token===e&&(this._state=null))}}function Og(e,t,i){const n=e.querySelector("ha-card");if(!n)return null;const r=n.getBoundingClientRect(),o=t.getBoundingClientRect().top-r.top,s=i?0:Math.min(Math.max(r.top,0),120),a=Math.round(o+s);return a>=0?a:null}const Eg=Object.freeze({rotDeg:4,tiltDeg:20,xyScale:1,zScale:1,origin:Object.freeze([500,500])}),Ng=64,Hg=10,Lg=4,Bg=68;function qg(e){return[e.rotDeg,e.tiltDeg,e.xyScale,e.zScale,e.origin[0],e.origin[1]].every(Number.isFinite)&&Math.abs(e.xyScale)>1e-12&&Math.abs(Math.cos(e.tiltDeg*Math.PI/180))>1e-12}function jg(e,t,i=Eg){if(!Number.isFinite(e[0])||!Number.isFinite(e[1]))throw new Error("invalid isometric projection input");return function(e,t){if(!Number.isFinite(e[0])||!Number.isFinite(e[1])||!t.every(Number.isFinite))throw new Error("invalid isometric affine input");const[i,n,r,o,s,a]=t;return[i*e[0]+r*e[1]+s,n*e[0]+o*e[1]+a]}(e,Ug(t,i))}function Wg(e,t=Eg){if(!qg(t)||!Number.isFinite(e[0])||!Number.isFinite(e[1]))throw new Error("invalid isometric projection input");const i=t.rotDeg*Math.PI/180,n=t.tiltDeg*Math.PI/180,r=(e[0]-t.origin[0])/t.xyScale,o=(e[1]-t.origin[1])/(t.xyScale*Math.cos(n));return[t.origin[0]+r*Math.cos(i)+o*Math.sin(i),t.origin[1]-r*Math.sin(i)+o*Math.cos(i)]}function Ug(e=0,t=Eg){if(!qg(t)||!Number.isFinite(e))throw new Error("invalid isometric camera");const i=t.rotDeg*Math.PI/180,n=t.tiltDeg*Math.PI/180,r=t.xyScale*Math.cos(i),o=-t.xyScale*Math.sin(i),s=t.xyScale*Math.sin(i)*Math.cos(n),a=t.xyScale*Math.cos(i)*Math.cos(n);return[r,s,o,a,t.origin[0]-r*t.origin[0]-o*t.origin[1],t.origin[1]-s*t.origin[0]-a*t.origin[1]-e*t.zScale*Math.sin(n)]}function Vg(e=Eg){return function(e=0,t=Eg){return`matrix(${Ug(e,t).map(e=>Number(e.toFixed(12))).join(" ")})`}(0,e)}function Gg(e,t=Eg){const{rect:i,wallHeight:n}=e,r=e.openingHeight??n,o=e.floorDepth??0,s=e.raisedHeight??n;if(!(i.w>=0)||!(i.h>=0)||!Number.isFinite(n)||!Number.isFinite(r)||!Number.isFinite(o)||!Number.isFinite(s)||n<0||r<0||o<0||s<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]],l=Math.max(n,r,s),c=a.flatMap(e=>[jg(e,-o,t),jg(e,l,t)]),h=c.map(e=>e[0]),d=c.map(e=>e[1]),u=Math.min(...h),p=Math.min(...d);return{x:u,y:p,w:Math.max(...h)-u,h:Math.max(...d)-p}}const Kg=[".dev",".vacpuck",".oplock",".op-hit",".opening",".rlgo","a","button","input","select","textarea",'[contenteditable]:not([contenteditable="false"])',"[data-room-fit-block]",'[role="link"]','[role="button"]'].join(","),Yg=(e,t)=>{try{return"function"==typeof e?.matches&&e.matches(t)}catch{return!1}};function Xg(e){for(const t of e){const e=t;if(Yg(e,".roomlabel[data-id]")){const t=e.getAttribute?.("data-id");return t?{kind:"room",roomId:t}:{kind:"interactive"}}if(Yg(e,Kg))return{kind:"interactive"};if(Yg(e,'[data-hp="room"][data-id]')){const t=e.getAttribute?.("data-id");return t?{kind:"room",roomId:t}:{kind:"interactive"}}if(Yg(e,".stage"))return{kind:"background"}}return{kind:"outside"}}function Zg(e){const t=Xg(e);return"room"===t.kind?t.roomId:null}class Jg{constructor(){this.pointer=null,this.sequence=null}clear(){this.pointer=null,this.sequence=null}clearOutside(e){let t={kind:"outside"};try{t=Xg(e.composedPath())}catch{}"outside"===t.kind&&this.clear()}pointerDown(e,t,i){let n={kind:"outside"};try{n=Xg(e.composedPath())}catch{}this.pointer=function(e){const t="mouse"===(i=e.pointerType)||"touch"===i||"pen"===i?i:null;var i;return t&&"view"===e.mode&&"background"===e.owner.kind&&!e.blocked&&e.isPrimary&&0===e.button&&Number.isFinite(e.x)&&Number.isFinite(e.y)?{pointerId:e.pointerId,spaceId:e.spaceId,modality:t,x:e.x,y:e.y}:null}({pointerId:e.pointerId,pointerType:e.pointerType,isPrimary:e.isPrimary,button:e.button,spaceId:t,mode:i?"view":"blocked",owner:n,blocked:!i,x:e.clientX,y:e.clientY}),this.pointer||(this.sequence=null)}pointerUp(e,t,i,n,r=Date.now()){let o={kind:"outside"};try{o=Xg(e.composedPath())}catch{}const s=function(e,t,i){if(!t||"view"!==i.mode||"background"!==i.owner.kind||i.blocked||t.pointerId!==i.pointerId||t.spaceId!==i.spaceId||!Number.isFinite(i.x)||!Number.isFinite(i.y)||!Number.isFinite(i.now)||Math.abs(i.x-t.x)+Math.abs(i.y-t.y)>=8)return{sequence:null,trigger:!1};const n=e?i.now-e.at:Number.POSITIVE_INFINITY;return e&&e.spaceId===i.spaceId&&e.modality===t.modality&&n>=0&&n<=350?{sequence:null,trigger:!0}:{sequence:{at:i.now,spaceId:i.spaceId,modality:t.modality},trigger:!1}}(this.sequence,this.pointer,{pointerId:e.pointerId,spaceId:t,mode:i?"view":"blocked",owner:o,blocked:n||!i,x:e.clientX,y:e.clientY,now:r});return this.pointer=null,this.sequence=s.sequence,s.trigger}}const Qg=e=>e.length>=2&&Number.isFinite(e[0])&&Number.isFinite(e[1]);function ef(e){return!!e&&Number.isFinite(e.x)&&Number.isFinite(e.y)&&Number.isFinite(e.w)&&e.w>0&&Number.isFinite(e.h)&&e.h>0}function tf(e,t=0){if(!e.length||!Number.isFinite(t)||t<0||!e.every(Qg))return null;let i=1/0,n=1/0,r=-1/0,o=-1/0;for(const t of e)i=Math.min(i,t[0]),n=Math.min(n,t[1]),r=Math.max(r,t[0]),o=Math.max(o,t[1]);const s=r-i,a=o-n;return s>0&&a>0?{x:i-t,y:n-t,w:s+2*t,h:a+2*t}:null}function nf(e,t,i){const n="string"!=typeof t||"invalid"!==t&&"no-borders"!==t&&"unverified"!==t&&!/^[a-z0-9]{1,8}$/i.test(t)?"redacted":t;return Object.freeze({kind:e,fingerprint:n,terminal:!!i})}function rf(e,t){return`${e("editor.load_failed")} ${e(t.terminal?"editor.refresh_advice":"editor.retry_advice")}`}class of extends Error{}class sf{constructor(e){this.options=e,this._state="idle",this._inFlight=null}get state(){return this._state}ensure(){return"ready"===this._state?Promise.resolve(!0):"failed"===this._state?Promise.resolve(!1):(this._inFlight||(this._setState("loading"),this._inFlight=this._loadWithRetry().finally(()=>{this._inFlight=null})),this._inFlight)}async _loadWithRetry(){let e=new Error("Editor runtime did not load"),t=!1;for(const i of[0,1])try{const e=await this.options.load(i);if(e.fingerprint!==this.options.expectedFingerprint)throw new of(`Editor runtime fingerprint mismatch: expected ${this.options.expectedFingerprint}, got ${e.fingerprint}`);const t=e.create();return this.options.install(t),this._setState("ready"),!0}catch(i){e=i,i instanceof of&&(t=!0)}return this._setState(t?"failed":"idle"),this.options.failed?.(e,{terminal:t}),!1}_setState(e){e!==this._state&&(this._state=e,this.options.stateChanged?.(e))}}const af=(e,t)=>{if(!e.has(t))return{hit:!1};const i=e.get(t);return e.delete(t),e.set(t,i),{hit:!0,value:i}},lf=(e,t,i,n)=>{for(e.delete(t),e.set(t,i);e.size>n;){const t=e.keys().next().value;if(void 0===t)break;e.delete(t)}},cf=new Set(["select","draw","column","merge","split","resize","opening","wallthick","delroom"]),hf=e=>`${window.innerWidth}x${window.innerHeight}|${location.pathname}|${JSON.stringify(e??{})}`,df="houseplan_card_alpha_v1",uf=Object.freeze([Object.freeze({id:"iso",issue:89,summary:"Volumetric plan renderer"})]);function pf(e){return/^[a-z][a-z0-9-]*$/.test(e.id)&&Number.isInteger(e.issue)&&e.issue>0&&!!e.summary.trim()}function _f(e){const t=String(e||"").replace(/^#/,"");return new URLSearchParams(t)}function mf(e){return _f(e).get("space")||""}function gf(e,t,i=uf){const n=function(e){const t=new Set;for(const i of e){if(!pf(i)||t.has(i.id))return!1;t.add(i.id)}return!0}(i),r=function(e){let t,i=!1;const n=e=>{for(const n of e.getAll("hp_alpha"))i=!0,"1"===n?t=!0:"0"===n&&(t=!1)};return n(new URLSearchParams(String(e.search||"").replace(/^\?/,""))),n(_f(e.hash)),{present:i,value:t}}(e),o=void 0!==r.value,s="1"===t,a=o?!0===r.value:!r.present&&s,l=n&&a;return{alpha:l,active:Object.freeze(l?i.map(e=>e.id).sort():[]),space:mf(e.hash),persist:n&&o?l?"1":"0":void 0,knownUrlOperation:o}}let ff={alpha:!1,active:Object.freeze([]),space:""},vf=!1,yf="";const bf=new Set;function wf(){if("undefined"==typeof window)return ff;const e=gf(window.location,function(){try{return window.localStorage.getItem(df)}catch{return null}}());void 0!==e.persist&&function(e){try{window.localStorage.setItem(df,e)}catch{}}(e.persist),ff={alpha:e.alpha,active:e.active,space:e.space},window.__hpAlpha=e.alpha,window.__hpLabs=e.active;for(const e of bf)e(ff);return ff}function kf(){wf()}function xf(){if("undefined"==typeof window)return ff;if(!vf){vf=!0,window.__hpLabsListenerCleanup?.(),window.addEventListener("hashchange",kf),window.addEventListener("popstate",kf);const e=()=>{window.removeEventListener("hashchange",kf),window.removeEventListener("popstate",kf),window.__hpLabsListenerCleanup===e&&delete window.__hpLabsListenerCleanup};window.__hpLabsListenerCleanup=e}return wf()}const Sf={window:120,door:90,passage:90,gate:300};function $f(e){return Sf[e]}function Mf(e,t){return{type:e,lengthCm:$f(e),flipH:!1,flipV:!1,revision:t}}function Rf(e,t){const i=Math.max(0,e.renderedLength)/2,n=Math.max(0,e.target.physicalHalfWidth),r=n+.18*Math.max(0,t),o=e=>({x1:e,y1:-r,x2:e,y2:r});return{rect:{x:-i,y:n?-n:0,width:2*i,height:2*n},boundaries:[o(-i),o(i)]}}function Cf(e,t){const i=[e[0],e[1]],n=[t[0],t[1]];return function(e,t){return e[0]-t[0]||e[1]-t[1]}(i,n)<=0?{a:i,b:n}:{a:n,b:i}}function Tf(e){const t=new Map;return e.forEach((e,i)=>{if(!e.kind||e.open)return;const n=Cf(e.a,e.b);if(Math.hypot(n.b[0]-n.a[0],n.b[1]-n.a[1])<=1e-9)return;const r=function(e,t){const i=e=>(Math.abs(e)<=5e-10?0:Math.round(1e6*e)/1e6).toFixed(6);return`${i(e[0])},${i(e[1])}>${i(t[0])},${i(t[1])}`}(n.a,n.b),o=t.get(r);if(o)return o.physicalHalfWidth=Math.max(o.physicalHalfWidth,e.half||0),o.sourceOrder=Math.min(o.sourceOrder,i),void(e.partitionHost&&(o.partitionHost&&o.partitionHost.id!==e.partitionHost.id?o.ambiguousPartitionHost=!0:o.partitionHost=e.partitionHost));t.set(r,{segmentKey:r,a:n.a,b:n.b,physicalHalfWidth:Math.max(0,e.half||0),sourceOrder:i,...e.partitionHost?{partitionHost:e.partitionHost}:{}})}),[...t.values()]}function Df(e,t){if(Math.abs(e.distance-t.distance)>1e-9)return e.distance-t.distance;if(Math.abs(e.perpendicular-t.perpendicular)>1e-9)return e.perpendicular-t.perpendicular;return(e.target.segmentKeyt.target.segmentKey?1:0)||e.target.sourceOrder-t.target.sourceOrder}function Af(e){const t=Tf(e.intervals).map(t=>{const i=function(e,t){const i=t.b[0]-t.a[0],n=t.b[1]-t.a[1],r=Math.hypot(i,n),o=i/r,s=n/r,a=(e[0]-t.a[0])*o+(e[1]-t.a[1])*s,l=Math.max(0,Math.min(r,a)),c=t.a[0]+l*o,h=t.a[1]+l*s;return{along:l,length:r,x:c,y:h,distance:Math.hypot(e[0]-c,e[1]-h),perpendicular:Math.abs((e[0]-t.a[0])*s-(e[1]-t.a[1])*o)}}(e.pointer,t);return{target:t,...i,envelope:Math.max(e.baseTolerance,t.physicalHalfWidth+e.bodyPointerPadding)}}).filter(e=>e.distance<=e.envelope+1e-9).filter(t=>!function(e,t,i,n,r){const o=t.b[0]-t.a[0],s=t.b[1]-t.a[1],a=Math.hypot(o,s);if(!(a>1e-9))return!1;const l=o/a,c=s/a;for(const o of i){if(!o.open&&o.kind)continue;const i=Cf(o.a,o.b),s=i.b[0]-i.a[0],a=i.b[1]-i.a[1],h=Math.hypot(s,a);if(!(h>1e-9))continue;const d=s/h,u=a/h;if(Math.abs(l*u-c*d)>1e-6)continue;if(Math.abs((i.a[0]-t.a[0])*c-(i.a[1]-t.a[1])*l)>r)continue;const p=(e[0]-i.a[0])*d+(e[1]-i.a[1])*u,_=1e-9;if(!(p<=_||p>=h-_)&&Math.abs((e[0]-i.a[0])*u-(e[1]-i.a[1])*d)<=n+1e-9)return!0}return!1}(e.pointer,t.target,e.intervals,t.envelope,Math.max(1e-9,Math.min(e.baseTolerance,.04*e.gridStep)))),i=t.filter(t=>!!t.target.partitionHost&&e.renderedLength+2*t.target.physicalHalfWidth>t.length+1e-9).sort(Df),n=t.filter(t=>!t.target.partitionHost||e.renderedLength+2*t.target.physicalHalfWidth<=t.length+1e-9).sort(Df);let r=n[0];if(!r)return{candidate:null,jambBlockedTarget:i[0]?.target||null};const o=n.filter(e=>Math.abs(e.distance-r.distance)<=1e-9&&Math.abs(e.perpendicular-r.perpendicular)<=1e-9),s=o.filter(e=>e.target.partitionHost);if(s.length){if(1!==new Set(s.map(e=>e.target.partitionHost.id)).size||s.some(e=>e.target.ambiguousPartitionHost))return{candidate:null,jambBlockedTarget:null};const e=s[0],t=e.target.b[0]-e.target.a[0],i=e.target.b[1]-e.target.a[1],n=Math.hypot(t,i),a=t/n,l=i/n;if(!o.every(t=>{const i=t.target.b[0]-t.target.a[0],n=t.target.b[1]-t.target.a[1],r=Math.hypot(i,n),o=i/r,s=n/r,c=Math.abs(a*s-l*o)<=1e-6,h=Math.abs((t.target.a[0]-e.target.a[0])*l-(t.target.a[1]-e.target.a[1])*a);return c&&h<=1e-9}))return{candidate:null,jambBlockedTarget:null};r=e}if(r.target.ambiguousPartitionHost)return{candidate:null,jambBlockedTarget:null};const{target:a,length:l}=r,c=a.b[0]-a.a[0],h=a.b[1]-a.a[1],d=c/l,u=h/l,p=a.partitionHost?a.physicalHalfWidth:0,_=Math.min(Math.max(0,e.renderedLength)/2+p,l/2);let m=r.along;const g=Math.max(e.gridStep,1e-9),f=l/2;m=Math.abs(m-f)<=g/2?f:Math.round(m/g)*g,m=Math.max(_,Math.min(l-_,m));const v=a.a[0]+d*m,y=a.a[1]+u*m,b=Math.max(0,e.renderedLength)/2,w=m-b,k=m+b,x=Math.max(0,w),S=Math.max(0,l-k),$=[a.a[0]+d*(w-x/2),a.a[1]+u*(w-x/2)],M=[a.a[0]+d*(k+S/2),a.a[1]+u*(k+S/2)];let R=180*Math.atan2(h,c)/Math.PI;R>=90?R-=180:R<-90&&(R+=180);const C=Math.abs(m-f)<=1e-9;return{candidate:{presetRevision:e.preset.revision,geometryRevision:e.geometryRevision,pointer:[e.pointer[0],e.pointer[1]],type:e.preset.type,lengthCm:e.preset.lengthCm,flipH:e.preset.flipH,flipV:e.preset.flipV,x:v,y:y,angle:R,renderedLength:e.renderedLength,target:a,...a.partitionHost?{host:{...a.partitionHost,t:l>0?m/l:0}}:{},measure:{labels:[{distance:x,midpoint:$},{distance:S,midpoint:M}],guide:C?{x:v,y:y,angle:R}:null}},jambBlockedTarget:null}}function Pf(e,t,i,n,r=1e-6){return e.presetRevision===i&&e.geometryRevision===n&&Math.hypot(e.pointer[0]-t[0],e.pointer[1]-t[1])<=r}function Ff(e){return!(!e.canEdit||e.kiosk||e.fixedFloor)&&("view"!==e.mode&&("mouse"===e.pointerType&&e.spaceCount>1))}class zf{constructor(e,t,i){this.loader=e,this.host=t,this.adopted=i,this.attachment=null}connect(){if(this.runtime)return void this.runtime.connect();this.attachment?.cancel();const e=this.loader.attach(this.host,e=>this.adopt(e));this.runtime||(this.attachment=e)}disconnect(){this.attachment?.cancel(),this.attachment=null,this.runtime?.disconnect()}adopt(e){this.attachment=null,this.runtime||(this.runtime=e,this.adopted(e))}}const If=new class{constructor(e){this.load=e,this.factory=null,this.pending=null}get warm(){return null!==this.factory}create(e){return this.factory?this.factory(e):null}attach(e,t){let i=!0;const n={cancel:()=>{i=!1}},r=this.create(e);return r?(t(r),n):(this.ensure().then(n=>{i&&t(n(e))},()=>{}),n)}ensure(){return this.factory?Promise.resolve(this.factory):(this.pending||(this.pending=this.load().then(e=>(this.factory=e,this.pending=null,e),e=>{throw this.pending=null,e})),this.pending)}reset(){this.factory=null,this.pending=null}}(()=>import("./summary-panel-runtime-loaded-Cdo93NMV.js").then(function(e){return e.e}).then(({LoadedSummaryPanelRuntime:e})=>t=>new e(t)));function Of(e){const t=globalThis.__HP_VERSION_OVERRIDE__;return"string"==typeof t&&t.length>0?t:e}let Ef=0;const Nf="1.74.0-beta.1",Hf="c8d5c166e30a11241ef32c7e1dc70368632e84c448524a8340494350ec4d5fca",Lf=1500,Bf=new Map;let qf=0,jf=1e4;const Wf="houseplan_card_layout_v1",Uf="houseplan_card_cfg_v1",Vf="houseplan_card_zoom_v1",Gf="houseplan_card_nav_v1",Kf="houseplan_card_view_v1",Yf="hp-dialog, hp-help, hp-color-opacity, hp-device-preview",Xf=1e3,Zf=(e,t)=>{const i=Math.min(e.x,t.x),n=Math.min(e.y,t.y);return{x:i,y:n,w:Math.max(e.x+e.w,t.x+t.w)-i,h:Math.max(e.y+e.h,t.y+t.h)-n}},Jf=(e,t,i)=>{const n=new Event(t,{bubbles:!0,composed:!0});n.detail=i??{},e.dispatchEvent(n)},Qf=e=>{history.pushState(null,"",e),Jf(window,"location-changed",{replace:!1})},ev=(e,t)=>{let i,n=null;const r=(...r)=>{clearTimeout(i),n=r,i=window.setTimeout(()=>{i=void 0;const t=n;n=null,t&&e(...t)},t)};return r.flush=()=>{if(void 0===i)return;clearTimeout(i),i=void 0;const t=n;n=null,t&&e(...t)},r.cancel=()=>{clearTimeout(i),i=void 0,n=null},r.pending=()=>void 0!==i,r},tv=e=>{try{e.target?.setPointerCapture?.(e.pointerId)}catch{}},iv=["edges","corners"];class nv extends he{constructor(){var e;super(...arguments),this._editorRuntime=null,this._liveRt=null,this._onboardingRuntime=null,this._editorRuntimeLoadingVisible=!1,this._backdropGuard=null,this._editorModeRequest=0,this._warmModeRequest=0,this._editorRuntimeLoader=new sf({expectedFingerprint:Hf,load:async e=>{const t=0===e?await import("./houseplan-editor-runtime-DbApDIhu.js"):await import((()=>{const e=new URL("./houseplan-editor-runtime-DbApDIhu.js",import.meta.url);return e.searchParams.set("hp_retry",`${Nf}-${++Ef}`),e.href})());return{fingerprint:t.EDITOR_RUNTIME_FINGERPRINT,create:()=>new t.HouseplanEditorRuntime(this)}},install:e=>{this._editorRuntime=e},stateChanged:e=>this._editorRuntimeStateChanged(e),failed:(e,t)=>{console.error("[houseplan] unable to load editor runtime",e),t.terminal&&this._versionRecovery.hasCurrentMismatchNotice||this._showToast(rf(e=>this._t(e),t))}}),this._onboardingRuntimeLoader=new sf({expectedFingerprint:Hf,load:async e=>{const t=0===e?await import("./houseplan-onboarding-runtime-BpONoVw8.js"):await import((()=>{const e=new URL("./houseplan-onboarding-runtime-BpONoVw8.js",import.meta.url);return e.searchParams.set("hp_retry",`${Nf}-${++Ef}`),e.href})());return{fingerprint:t.ONBOARDING_RUNTIME_FINGERPRINT,create:()=>new t.HouseplanOnboardingRuntime(this)}},install:e=>{this._onboardingRuntime=e},failed:(e,t)=>{console.error("[houseplan] unable to load onboarding runtime",e),t.terminal&&this._versionRecovery.hasCurrentMismatchNotice||this._showToast(rf(e=>this._t(e),t))}}),this._isoSceneRuntime=null,this._isoSceneRuntimeLoader=new sf({expectedFingerprint:Hf,load:async e=>{const t=0===e?await import("./iso-scene-render-DY37-w1-.js"):await import((()=>{const e=new URL("./iso-scene-render-DY37-w1-.js",import.meta.url);return e.searchParams.set("hp_retry",`${Nf}-${++Ef}`),e.href})());return{fingerprint:t.ISO_SCENE_RUNTIME_FINGERPRINT,create:()=>t}},install:e=>{const t=this._effectiveProjection();this._isoSceneRuntime=e,this._isoProjectionSnapshot=null;const i=this._effectiveProjection();this._convertProjectionView(t,i),this.isConnected&&this.requestUpdate()},failed:(e,t)=>{console.warn("[houseplan] hidden isometric runtime diagnostic",nf("runtime-load","unverified",t.terminal)),this.isConnected&&this.requestUpdate()}}),this._pdfRuntime=null,this._pdfRuntimeLoader=new sf({expectedFingerprint:Hf,load:async e=>{const t=0===e?await import("./pdf-export-C4aEaLXl.js"):await import((()=>{const e=new URL("./pdf-export-C4aEaLXl.js",import.meta.url);return e.searchParams.set("hp_retry",`${Nf}-${++Ef}`),e.href})());return{fingerprint:t.PDF_EXPORT_FINGERPRINT,create:()=>new t.PdfExportRuntime}},install:e=>{this._pdfRuntime=e,this.isConnected&&this.requestUpdate()},failed:(e,t)=>{if(console.error("[houseplan] unable to load PDF export runtime",e),!t.terminal||!this._versionRecovery.hasCurrentMismatchNotice){const e=rf(e=>this._t(e),t),i=this._t("editor.load_failed"),n=e.startsWith(i)?e.slice(i.length).trim():e;this._showToast(`${this._t("pdf.failed")} ${n}`.trim())}}}),this.panelHost=!1,this.narrow=null,this._space="f1",this._adoption=new Cu((e,t)=>this.requestUpdate(e,t)),this._serverStorage=!1,this._loadOk=!1,this._serverCanWrite=null,this._loading=!1,this._loadTries=0,this._unsubCfg=null,this._unsubLayout=null,this._unsubVirtual=null,this._liveSyncAttempt=null,this._liveSyncGeneration=0,this._liveSyncConnection=null,this._virtualLights=$h(null),this._canOptimizeUndo=!1,this._undoKind=null,this._devices=[],this._regSignature="",this._defPos={},this._newSyncKey="",this._areaRelocationIds=new Set,this._areaSnapshotCleanupCandidates=new Map,this._areaRelocationSyncKey="",this._areaRelocationWrite=Promise.resolve(),this._tip=null,this._hoverRoom=null,this._pointerModality=new qm(this,()=>this._syncPointerHoverTargets()),this._devicePressAnimations=new Map,this._selId=null,this._toast="",this._mode="view",this._pendingNavMode=null,this._decorTool="select",this._decorStyle={...br},this._decorStyleSeeded=!1,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._decorImagePalette=null,this._decorAssetCatalog=[],this._decorAssets=new Map,this._decorAssetBusy=!1,this._furnCategory=null,this._furnPreviewInput=null,this._furnTouchPending=null,this._dtBox=null,this._dtDrag=null,this._bdDrag=null,this._slide="",this._reducedMotion=!1,this._onMotionChange=e=>{this._reducedMotion=e.matches,this._cancelDevicePressFeedback(),e.matches&&this._cancelCameraTransition(!0),e.matches&&this._modeTransitionPreparing?this._modeTransitionForceAtomic=!0:e.matches&&this._modeTransition.active&&this._cancelModeTransition(!0),this._syncVersionRecovery(),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 Rg({frame:e=>this._applyModeTransitionFrame(e),settled:e=>this._settleModeTransition(e)}),this._cameraTransitionFit=null,this._cameraTransition=new Ig({frame:e=>this._applyCameraTransitionFrame(e),settled:e=>this._settleCameraTransition(e)}),this._editorSecondaryCopy={groupActive:(e,t)=>this._t("editor.group_active",{group:e,item:t}),openGroup:e=>this._t("editor.open_group",{group:e}),disabledAction:(e,t)=>this._t("editor.disabled_action",{action:e,reason:t})},this._tool="draw",this._geometryHistory=new Jm(50),this._devicePositionHistory=new Jm(50),this._devicePositionBusy=!1,this._wallDialog=null,this._drawWallField=null,this._activeWallChainId=null,this._activeWallChainPartitionIds=[],this._wallChainRedo=[],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._wallUnionCacheValue=null,this._wallUnionPool=new Map,this._isoGeometryCache=new Map,this._renderIsoScene=null,this._isoProjectionSnapshot=null,this._isoStructuralBuildCount=0,this._isoFallback=new Set,this._openingTunnelCache=null,this._openingWallIndexCache=new Map,this._openingPlacementIntervalsCache=null,this._openingDimensionContextCache=null,this._planSnapGeometryCache=null,this._planStructuralGeometryCache=null,this._hiddenWallDiagnosticCache=null,this._physicalBodiesCache=null,this._lightPhysicalBodiesCache=null,this._cleanFloorCache=new Map,this._innerContourCache=new Map,this._glowRuntimeState=im(),this._glowRuntimeHost={window:()=>this.ownerDocument.defaultView||window,isConnected:()=>this.isConnected,requestUpdate:()=>this.requestUpdate(),reducedMotion:()=>this._reducedMotion},this._lightBarrierCache=null,this._lightBarrierPool=new Map,this._glowScreenBlend=!1,this._duplicateColumnId=null,this._duplicateColumnTimer=0,this._rszLimitViolation=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._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._roomTempMin="",this._roomTempMax="",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._roomFocus=null,this._roomPointer=null,this._doubleFit=new Jg,this._pointers=new Map,this._panStart=null,this._panLock=null,this._pinchStart=null,this._suppressClick=!1,this._viewportGestureDirty=!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:e=>this._guardTouchGesture(e)},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._dangerConfirm=null,this._dangerConfirmController=new Ae(e=>{this._dangerConfirm=e}),this._confirmDanger=e=>this._config&&this.hass?"warm"===this._syncDangerConfirmLocaleGate()||this._dangerConfirmMissingSpace()?Promise.resolve(!1):this._dangerConfirmController.confirm(e):Promise.resolve(!1),this._cancelDangerConfirm=()=>{this._dangerConfirmController.cancel()},this._onDangerConfirmDecision=e=>{this._dangerConfirmController.resolve(e.detail.token,e.detail.accepted)},this._onboardingShown=!1,this._rulesDialog=null,this._preflightClipboardFallback=null,this._haIntegrationVersion=null,this._versionRecovery=(e=this,new ng({clock:{setTimeout:(e,t)=>window.setTimeout(e,t),clearTimeout:e=>window.clearTimeout(e)},storage:()=>e.ownerDocument.defaultView?.sessionStorage??null,safety:()=>sg(e),reload:()=>e._reloadDocument(),changed:()=>{e.requestUpdate()}})),this._haSupportApi=null,this._haDecorAssetsApi=null,this._haSummaryPanelApi=null,this._haRadarStage1Api=null,this._radarLive=new pg(this),this._decorAssetSyncToken=0,this._alignDialog=null,this._settingsDialog=null,this._pdfDialog=!1,this._supportDialog=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._deviceInbox=null,this._deviceInboxReturn=null,this._deviceInboxMemo=null,this._markerDialog=null,this._spaceDialog=null,this._keyHandler=e=>this._onKey(e),this._warmVp=null,this._warmVpArmed=!1,this._warmLongReturn=!1,this._warmRevivePending=!1,this._warmGen=++qf,this._warmKey=null,this._warmSlot=null,this._hashApplied=!1,this._navApplied=!1,this._labs={alpha:!1,active:Object.freeze([]),space:""},this._viewPreference={},this._renderProjection="flat",this._kioskScale={icon:1,font:1},this._kioskDialog=!1,this._summarySlot=new zf(If,this,e=>{this._summary=e,this._capturedSnapshotSequence=-1,this.isConnected&&(e.connect(),this.hasUpdated&&this.requestUpdate())}),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=e=>{if(this._continuity.visibility(e),this._dayCycleVisibility(e),this._summary?.visibility(e.kind),"hidden"===e.kind)return this._radarLive.stop(),this._editorRuntime?._cancelRadarSetup(),this._clearRoomFocus(!0),this._clearTransientHover(!0),this._cancelDevicePressFeedback(),this._cancelCameraTransition(!0),void(this._modeTransitionPreparing?this._modeTransitionForceAtomic=!0:this._cancelModeTransition(!0));if(this._vacJumpOnce=!0,this._syncRadarLive(),!e.long){const e=Date.now();let t=!1;for(const i of this._activityRt.values())!i.flashKind||(i.expiresAt||i.flashTs+Em)>e||(i.flashTs=0,i.flashKind=null,i.expiresAt=0,t=!0);return void(t&&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._onLabsSnapshot=e=>{const t=this._effectiveProjection();this._labs=e,this._isoProjectionSnapshot=null,this._labsIso&&this._ensureIsoSceneRuntime();const i=this._effectiveProjection();this._convertProjectionView(t,i),this.requestUpdate()},this._onHashChange=()=>{if(this._hasFixedFloor)return;const e=this._hashSpace();if(e&&this._model.find(t=>t.id===e)&&e!==this._space){if(this._wallFaceBatch&&this._roomDialogCancel(),"plan"===this._mode&&"draw"===this._tool&&!this._finishWallChain())return;this._commitSpace(e),this._selId=null,this._path=[],this._clearPlanSnapHover(),this._clearOpeningPlacement(!0),this._tool="draw",this._activeWallChainId=null,this._activeWallChainPartitionIds=[],this._wallChainSegmentCms=[],this._closingWallCm=null,this._restoreZoom(),this.requestUpdate()}},this._drag=null,this._deviceDrag=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._cfgEpochPreservedConfig=null,this._terminalFrame=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._renderLife=new ag,this._liveEditorPaintCount=0,this._onHaRegistryUpdate=()=>{const e=jh(this.hass);e.revision===this._haRegistryRev&&this._devices.length||(this._haRegistryRev=e.revision,this._renderLife.invalidate(),this._planHassMemo=null,this._regSignature="",this._maybeRebuildDevices(),this.requestUpdate())},this._onConnReady=()=>{if(this._loadTries=0,clearTimeout(this._loadRetryTimer),this._loadRetryTimer=void 0,qh(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 ac(()=>this.requestUpdate()),this._dirtyPos=new Set,this._sentPos=new Map,this._persistLayout=ev(()=>{if(this._serverStorage){const e=[...this._dirtyPos];this._dirtyPos.clear();for(const t of e){const e=mo(this._layout[t]);e&&(this._layout={...this._layout,[t]:e},this._sentPos.set(t,e),this.hass.callWS({type:"houseplan/layout/update",device_id:t,pos:e}).then(e=>this._noteLayoutRev(e)).catch(e=>this._showToast(this._t("toast.pos_save_failed",{err:this._errText(e)}))).finally(()=>{this._sentPos.get(t)===e&&this._sentPos.delete(t)}))}this._cacheSnapshot()}else this._persistLocalLayout()},600),this._frame=null,this._showFar=!1,this._writesPending=0,this._writeChain=Promise.resolve(),this._pendingPhysicalWrites=new Map,this._undoGeometry=()=>this._editorRuntimeOrThrow()._undoGeometry(),this._redoGeometry=()=>this._editorRuntimeOrThrow()._redoGeometry(),this._saveConfigDebounced=ev(()=>{this._serverCfg&&this._writeConfig().catch(e=>{const t=!0===e?.physicalGeometryRolledBack;"geometry-unsafe"!==e?.code&&("wall_model_client_outdated"===e?.code?this._showToast(this._t("toast.wall_model_client_outdated")):"conflict"===e?.code?(this._showToast(this._t("toast.conflict")),t||(this._cancelPath(),this._reloadConfigOnly(!0))):this._showToast(this._t("toast.cfg_save_failed",{err:this._errText(e)})),t&&this._reloadRejectedPhysicalWrite())})},500),this._wallChainSegmentCms=[],this._closingWallCm=null,this._savePhysicalDialog=()=>this._editorRuntimeOrThrow()._savePhysicalDialog(),this._deletePhysicalSelection=()=>this._editorRuntimeOrThrow()._deletePhysicalSelection(),this._confirmPartitionDelete=()=>this._editorRuntimeOrThrow()._confirmPartitionDelete(),this._confirmRoomDelete=e=>this._editorRuntimeOrThrow()._confirmRoomDelete(e),this._rebindPartitionOpening=()=>this._editorRuntimeOrThrow()._rebindPartitionOpening(),this._keepClosedAsPartitions=()=>this._editorRuntimeOrThrow()._keepClosedAsPartitions(),this._toggleServerPlans=async()=>this._onboardingRuntime&&this._spaceDialogUsesOnboardingRuntime("create")?this._onboardingRuntime._toggleServerPlans():this._editorRuntimeOrThrow()._toggleServerPlans(),this._aspectJob=null,this._dayCycleTick=()=>{if(!this.isConnected||"hidden"===this.ownerDocument.visibilityState)return;const e=this._dayCycleState();if(!e)return this._dayCycleTimer&&(clearInterval(this._dayCycleTimer),this._dayCycleTimer=0),void(this._dayCycleClockKey="");const t=rr(e);t!==this._dayCycleClockKey&&(this._dayCycleClockKey=t,this.requestUpdate())},this._sunShown=!1,this._sunOut=!1,this._sunOutTimer=0,this._openSettingsDialog=()=>{if(this._editorRuntime)return this._editorRuntime._openSettingsDialog();this._ensureEditorRuntime().then(e=>{e&&this._openSettingsDialog()})},this._openSupportDialog=()=>{this._editorRuntime?this._editorRuntime._openSupportDialog():this._ensureEditorRuntime().then(e=>{e&&this._openSupportDialog()})},this._openPdfDialog=()=>{this._pdfRuntimeLoader.ensure().then(e=>{e&&(this._pdfDialog=!0,this.requestUpdate())})},this._reportedPreflightFingerprint=null,this._openAlignDialog=()=>this._editorRuntimeOrThrow()._openAlignDialog(),this._toggleOptimizeLivePositions=()=>this._editorRuntimeOrThrow()._toggleOptimizeLivePositions(),this._optimizeUndoBusy=!1,this._openBackupExport=()=>this._editorRuntimeOrThrow()._openBackupExport(),this._openRulesDialog=()=>this._editorRuntimeOrThrow()._openRulesDialog(),this._climateCache=null,this._gearPtCache=new WeakMap}requestUpdate(e,t,i){if("hass"===e&&this.hass&&this._liveRt){const e=this._visibleDeviceSnapshot||this._candidateDeviceSnapshot;if(!this._liveRt.hass(t,this.hass,e?{entityIds:e.entityIds}:null,()=>lg(this))&&!this._summary?.observeHassComposition())return}void 0!==e&&(this._terminalFrame=0),this._editorRuntime?._routeLiveEditorUpdate(e,t)||(this._liveRt?.clear(),super.requestUpdate(e,t,i))}_editorRuntimeOrThrow(){if(!this._editorRuntime)throw new Error("Houseplan editor runtime is not loaded");return this._editorRuntime}async _ensureEditorRuntime(){return this._editorRuntimeLoader.ensure()}async _ensureOnboardingRuntime(){return this._onboardingRuntimeLoader.ensure()}async _ensureIsoSceneRuntime(){return this._isoSceneRuntimeLoader.ensure()}_editorRuntimeStateChanged(e){clearTimeout(this._editorRuntimeLoadingTimer),this._editorRuntimeLoadingTimer=void 0,"loading"!==e?(this._editorRuntimeLoadingVisible=!1,this.requestUpdate()):this._editorRuntimeLoadingTimer=window.setTimeout(()=>{this._editorRuntimeLoadingVisible=!0,this.requestUpdate()},150)}async _requestMode(e,t=!0,i=!1){const n=++this._editorModeRequest;if(i&&(this._warmModeRequest=n,this._refitRaf&&(cancelAnimationFrame(this._refitRaf),this._refitRaf=0),this._pendingRefitSize=null),"view"===e||await this._ensureEditorRuntime()){if(n===this._editorModeRequest&&this.isConnected)return i?(this._adoptMode(e),this._warmRevivePending&&(clearTimeout(this._warmReviveTimer),this._warmReviveTimer=void 0,this._warmReviveDialog()),this.requestUpdate(),void this.updateComplete.then(()=>requestAnimationFrame(()=>requestAnimationFrame(()=>{if(this._warmModeRequest!==n||n!==this._editorModeRequest)return;const e=this._stageEl;this._lastValidStageSize=e&&e.clientWidth>0&&e.clientHeight>0?[e.clientWidth,e.clientHeight]:null,this._pendingRefitSize=null,this._warmModeRequest=0})))):void this._setMode(e,t);this._warmModeRequest===n&&(this._warmModeRequest=0)}else this._warmModeRequest===n&&(this._warmModeRequest=0)}get _layout(){return this._adoption.layout}set _layout(e){this._adoption.stageLocalLayout(e)}get _layoutRev(){return this._adoption.layoutRev}set _layoutRev(e){this._adoption.seedIdentity({layoutRev:e})}get _layoutContentFingerprint(){return this._adoption.layoutFingerprint}set _layoutContentFingerprint(e){this._adoption.seedIdentity({layoutFingerprint:e})}get _serverCfg(){return this._adoption.config}set _serverCfg(e){this._adoption.stageLocalConfig(e)}get _cfgRev(){return this._adoption.configRev}set _cfgRev(e){this._adoption.seedIdentity({configRev:e})}get _cfgContentFingerprint(){return this._adoption.configFingerprint}set _cfgContentFingerprint(e){this._adoption.seedIdentity({configFingerprint:e})}_seedDecorStyle(e){var t,i;if(t=Cl,i=this,$l(e,Il)&&"pending"===t.state()&&(t.art("",i),t.ensure()),this._decorStyleSeeded||!e)return;this._decorStyleSeeded=!0;const n=e.settings?.decor_default_style;n&&(this._decorStyle=function(e,t){if(!e||"object"!=typeof e)return{...t};const i=e,n="string"==typeof i.color&&i.color?i.color:t.color,r="string"==typeof i.fill_color&&i.fill_color?i.fill_color:t.fillColor,o=Number(i.width_cm);return{color:n,opacity:wr(i.opacity,t.opacity),widthCm:Number.isFinite(o)&&o>0?Math.max(.1,Math.min(100,o)):t.widthCm,fill:"boolean"==typeof i.fill?i.fill:t.fill,fillColor:r,fillOpacity:wr(i.fill_opacity,t.fillOpacity)}}(n,br))}get _canManageConfiguration(){return null!==this._serverCanWrite?this._serverCanWrite:!0===this.hass?.user?.is_admin}get _canEdit(){return this._norm&&this._canManageConfiguration}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}get _doubleFitEnabled(){return!("view"!==this._mode||this._vacFit||this._modeTransitionBusy||this._touchSequenceMultitouch||"steady"!==this._continuity.state||this._continuity.overlayBlocksInteraction)}_cameraState(){const e=this._viewOr(this._baseVb());return{zoom:this._zoom,viewBox:{...e}}}_normalizeCameraState(e){const t=this._cameraTransitionFit||Fi(this._baseVb(),this._stageAspect());return{zoom:Math.min(nv.ZOOM_MAX,Math.max(nv.ZOOM_MIN,e.zoom)),viewBox:this._clampView({...e.viewBox},t)}}_applyCameraTransitionFrame(e){const t=this._normalizeCameraState(e.presented);e.presented=t,this._zoom=t.zoom,this._view={...t.viewBox},this._liveVp(!0)}_settleCameraTransition(e){const t=this._normalizeCameraState(e.to);this._zoom=t.zoom,this._view={...t.viewBox},this._cameraTransitionFit=null,"room"!==e.reason&&this._saveZoom(),this.requestUpdate()}_cancelCameraTransition(e=!1,t=!1){const i=this._cameraTransition.state?.reason,n=t&&this._cameraTransition.active?this._cameraTransition.presented?.zoom:void 0;this._cameraTransition.cancel(e),this._cameraTransitionFit=null,void 0!==n&&"room"!==i&&this._saveZoom()}_prepareCameraCommand(){this._bootSoftCancel(),this._modeTransitionBusy&&this._cancelModeTransition(!0),"opening"===this._tool&&(this._cursorPt=null,this._clearOpeningPlacement(!1))}_startCameraTransition(e,t,i,n){const r=this._cameraState(),o=this._cameraTransition.target;return(!o||!Pg(o,e))&&(Pg(r,e)?(this._cancelCameraTransition(!1),!1):(this._cameraTransitionFit={...t},this._cameraTransition.start(r,e,i,this._reducedMotion?0:n),!0))}_cssColor(e,t){const i=String(e||"").trim();if(!i)return t;const n=document.createElement("span");n.style.cssText=`position:absolute;visibility:hidden;color:${i}`,this.renderRoot.append(n);const r=getComputedStyle(n).color||t;return n.remove(),r}_currentModeVisual(e=this._mode){const t=this._modeTransition.presented||this._modeTransitionVisual;if(t)return{...t,viewport:{...t.viewport,viewBox:{...t.viewport.viewBox}}};const i=this._stageEl;if(!i||i.clientWidth<=0||i.clientHeight<=0)return null;const n=this.renderRoot.querySelector(".editorchrome"),r=this._viewOr(this._baseVb()),o=this.renderRoot.querySelector(".hp-paper"),s=this.renderRoot.querySelector(".hp-backdrop"),a=this.renderRoot.querySelector(".zoomwrap"),l=a?getComputedStyle(a).filter:"",c=Number(/brightness\(([^)]+)\)/.exec(l)?.[1]);return{presentedMode:e,editorChromeHeight:"view"===e?0:n?.getBoundingClientRect().height||0,stageWidth:i.clientWidth,stageHeight:i.clientHeight,viewport:xg(r,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"===e?.35:1,backdropOpacity:s&&Number(getComputedStyle(s).opacity)||1,viewWeight:"view"===e?1:0,editorWeight:"view"===e?0:1,toolbarContentOpacity:"view"===e?0:1}}_viewForModeTarget(e,t,i,n,r){const o=Fi(this._baseVb(),n/r),s=Math.min(nv.ZOOM_MAX,Math.max(nv.ZOOM_MIN,e)),a=o.w/s,l=o.h/s,c=t??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(e){return"view"!==e?"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(e){return"view"===e&&this._spaceModel()?.bg?this._cssColor("var(--ha-card-background, var(--card-background-color, #111))","rgb(17, 17, 17)"):"rgb(255, 255, 255)"}_targetBrightness(e){return 1}_applyModeTransitionFrame(e){e.targetMode===this._mode&&(this._modeTransitionVisual=e.presented,this._view={...e.presented.viewport.viewBox},this.requestUpdate())}_settleModeTransition(e){if(e.targetMode!==this._mode)return;const t=this._modeTransitionRequest;this._view={...e.to.viewport.viewBox},this._zoom=this._modeTransitionTargetZoom,this._modeTransitionVisual=null,this._modeTransitionPreparing=!1,this._lastValidStageSize=[e.to.stageWidth,e.to.stageHeight],"view"===this._mode&&(this._saveZoom(),this._viewModeSnap=null,this._modeTransitionEditorCamera=null),this.requestUpdate(),this.updateComplete.then(()=>{if(!this.isConnected||t!==this._modeTransitionRequest||this._modeTransitionBusy||e.targetMode!==this._mode)return;const i=this._stageEl;if(i&&i.clientWidth>0&&i.clientHeight>0&&(Math.abs(i.clientWidth-e.to.stageWidth)>.5||Math.abs(i.clientHeight-e.to.stageHeight)>.5)){const e=this._view;this._lastValidStageSize=[i.clientWidth,i.clientHeight],this._applyView(this._zoom,e?e.x+e.w/2:void 0,e?e.y+e.h/2:void 0),this.requestUpdate()}const n=this.renderRoot.activeElement;(!n||!n.isConnected||!!n.closest?.(".editorchrome, .stage"))&&this.renderRoot.querySelector(".modetab.active")?.focus?.({preventScroll:!0})})}_cancelModeTransition(e=!0){this._cancelCameraTransition(!1);const t=!!this._modeTransition.state;this._modeTransitionRequest++,this._modeTransitionPreparing=!1,this._modeTransitionForceAtomic=!1,this._modeTransition.cancel(e),e&&t||(this._modeTransitionVisual=null)}_adoptMode(e){e!==this._mode&&this._clearRoomFocus(!0),this._cancelModeTransition(!1),this._mode=e,this._isoProjectionSnapshot=null,"view"!==e&&(this._editorChromeMode=e)}_commitViewModeAtomic(e,t,i,n){if(this._modeTransitionPreparing=!1,this._modeTransitionVisual=null,this._modeTransitionForceAtomic=!1,this._zoom=t,e){const r=this._stageEl?.clientWidth||e.stageWidth,o=Math.max(1,e.stageHeight+e.editorChromeHeight);this._view=this._viewForModeTarget(t,i,n,r,o),this._lastValidStageSize=[r,o]}else this._view=null;this._viewModeSnap=null,this._modeTransitionEditorCamera=null,this._saveZoom(),this.requestUpdate()}_prepareModeTransition(e,t,i,n,r,o){this.updateComplete.then(()=>{if(!this.isConnected||e!==this._modeTransitionRequest||this._mode!==i)return void(e===this._modeTransitionRequest&&(this._modeTransitionPreparing=!1,this._modeTransitionVisual=null,this._modeTransitionForceAtomic=!1,this.requestUpdate()));const s=this.renderRoot.querySelector(".editorchrome-inner"),a="view"===i?0:s?.scrollHeight||0,l=Math.max(1,(this.panelHost?this.clientHeight:innerHeight)-Og(this.renderRoot,this._stageEl,this.panelHost)),c=this._stageEl?.clientWidth||t.stageWidth,h=this._viewForModeTarget(n,r,o,c,l),d={presentedMode:i,editorChromeHeight:a,stageWidth:c,stageHeight:l,viewport:xg(h,c),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 u=this._modeTransitionForceAtomic;this._modeTransitionForceAtomic=!1,this._modeTransition.start(t,d,i,this._reducedMotion||u?0:220)})}get _hasFixedFloor(){return!!this._config&&Object.prototype.hasOwnProperty.call(this._config,"floor")}_fixedFloorState(e=this._model,t=this._loadOk){const i=this._config?.floor,n=function(e){if(!e.hasFloor)return{kind:"absent"};const t=e.floor;if("string"==typeof t)return t.length?e.spaceIds.includes(t)?{kind:"valid",id:t,source:"id"}:{kind:"invalid",reason:"unknown-id",value:t}:{kind:"invalid",reason:"empty-id",value:t};if("number"==typeof t){if(!Number.isFinite(t))return{kind:"invalid",reason:"non-finite-index",value:t};if(!Number.isInteger(t))return{kind:"invalid",reason:"fractional-index",value:t};if(t<0)return{kind:"invalid",reason:"negative-index",value:t};const i=e.spaceIds[t];return void 0===i?{kind:"invalid",reason:"out-of-range-index",value:t}:{kind:"valid",id:i,source:"index"}}return{kind:"invalid",reason:"invalid-type",value:t}}({spaceIds:e.map(e=>e.id),hasFloor:this._hasFixedFloor,floor:i});return!this._hasFixedFloor||t?n:"number"==typeof i?"valid"===n.kind||"invalid"===n.kind&&"out-of-range-index"===n.reason?{kind:"pending",value:i}:n:"valid"===n.kind||"invalid"===n.kind&&"unknown-id"!==n.reason?n:{kind:"pending",value:i}}_canCommitSpace(e,t=!1){if(t||!this._hasFixedFloor)return!0;const i=this._fixedFloorState();return"valid"===i.kind&&i.id===e}_commitSpace(e,t=!1){return!!this._canCommitSpace(e,t)&&(e!==this._space&&(this._clearRoomFocus(!0),this._cancelDangerConfirm(),this._cancelCameraTransition(!1),this._clearTransientHover(!0),this._cancelDevicePressFeedback(),this._editorRuntime?._clearFurniturePreview()),this._space=e,this._isoProjectionSnapshot=null,!0)}_slideTo(e,t){if(e===this._space)return!0;if(!this._canCommitSpace(e))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._commitSpace(e),this._path=[],this._clearPlanSnapHover(),this._clearOpeningPlacement(!0),this._tool="draw",this._activeWallChainId=null,this._activeWallChainPartitionIds=[],this._wallChainSegmentCms=[],this._closingWallCm=null,this._selId=null,this._physicalSel=null,this._editorSecondary?.closeForNavigation(),this._physicalDialog=null,this._physicalDrag=null,this._restoreZoom(),i||(this._slide=t,clearTimeout(this._slideTimer),this._slideTimer=window.setTimeout(()=>{this._slideTimer=void 0,this._slide="",this.requestUpdate()},190),this.requestUpdate()),!0}get _canReorderTabs(){return Ff({canEdit:this._canEdit,kiosk:this._kiosk,mode:this._mode,pointerType:"mouse",spaceCount:this._model.length,fixedFloor:this._hasFixedFloor})}_tabPointerDown(e,t){Ff({canEdit:this._canEdit,kiosk:this._kiosk,mode:this._mode,pointerType:e.pointerType,spaceCount:this._model.length,fixedFloor:this._hasFixedFloor})&&(tv(e),this._tabDragRelease=e=>this._tabPointerUp(e),window.addEventListener("pointerup",this._tabDragRelease),window.addEventListener("pointercancel",this._tabDragRelease),this._tabDrag={id:t,pointerId:e.pointerId,x:e.clientX,y:e.clientY,moved:!1,targetId:null,placement:null})}_tabDropTargetAt(e,t,i){const n=this._model.map(e=>e.id),r=n.indexOf(i);if(r<0)return null;const o=this.renderRoot.querySelectorAll('[data-hp="space-tab"]');for(const s of o){const o=s.dataset.id||"";if(!o||o===i)continue;const a=s.getBoundingClientRect();if(ea.right||ta.bottom)continue;const l=n.indexOf(o);return l<0?null:{targetId:o,placement:l=4)))return;var i,n;const r=this._tabDropTargetAt(e.clientX,e.clientY,t.id);t.moved&&t.targetId===r?.targetId&&t.placement===r?.placement||(this._tabDrag={...t,moved:!0,targetId:r?.targetId||null,placement:r?.placement||null})}_tabPointerUp(e){const t=this._tabDrag;if(t&&t.pointerId!==e.pointerId)return;const i="pointerup"===e.type&&t?.moved?this._tabDropTargetAt(e.clientX,e.clientY,t.id):null;"pointerup"===e.type&&t?.moved&&this._suppressNextTabClick(),this._endTabDrag(),t?.moved&&i&&this._commitTabOrder(t.id,i.targetId)}_endTabDrag(){this._tabDrag=null,this._tabDragRelease&&(window.removeEventListener("pointerup",this._tabDragRelease),window.removeEventListener("pointercancel",this._tabDragRelease),this._tabDragRelease=null)}_tabClick(e){if(this._tabSuppressClick)return this._tabSuppressClick=!1,clearTimeout(this._tabSuppressClickTimer),void(this._tabSuppressClickTimer=void 0);this._pickSpace(e)}_suppressNextTabClick(){this._tabSuppressClick=!0,clearTimeout(this._tabSuppressClickTimer),this._tabSuppressClickTimer=window.setTimeout(()=>{this._tabSuppressClick=!1,this._tabSuppressClickTimer=void 0},0)}_commitTabOrder(e,t){const i=this._serverCfg;if(!i||!this._canReorderTabs)return;const n=this._model.map(e=>e.id),r=function(e,t,i){const n=e.indexOf(t),r=e.indexOf(i);if(n<0||r<0||n===r)return e;const o=e.slice();return o.splice(n,1),o.splice(r,0,t),o}(n,e,t);if(r===n)return;const o=new Map(this._devices.map(e=>[String(e.id),String(e.area||"")])),s=function(e,t,i,n=()=>""){if(!i)return[];const r=[];for(const o of e){if(!o||!0===o.removed)continue;const e="string"==typeof o.id?o.id:"";if(!e)continue;if("string"==typeof o.space&&o.space)continue;const s=("string"==typeof o.area?o.area:"")||n(e)||"";s&&t[s]||r.push({id:e,space:i})}return r}(i.markers||[],Object.fromEntries(Object.entries(this._areaToSpace).map(([e,t])=>[e,t.space])),n[0]||"",e=>o.get(e)||"");if(s.length){const e=new Map(s.map(e=>[e.id,e.space]));for(const t of i.markers||[]){const i=e.get(String(t.id));i&&(t.space=i)}}i.spaces=function(e,t){const i=new Map(t.map((e,t)=>[e,t]));return e.map((e,t)=>({space:e,index:t})).sort((e,t)=>(i.get(String(e.space?.id))??Number.MAX_SAFE_INTEGER)-(i.get(String(t.space?.id))??Number.MAX_SAFE_INTEGER)||e.index-t.index).map(e=>e.space)}(i.spaces||[],r),this._saveConfig(),this._tabOrderWarned||(this._tabOrderWarned=!0,this._showToast(this._t("toast.space_order_changed")))}_pickSpace(e){if(this._endTabDrag(),e===this._space)return;const t=this._model.map(e=>e.id),i=t.indexOf(this._space),n=t.indexOf(e);this._navApplied=!0,this._showFar=!1,this._frame=null,this._slideTo(e,i>=0&&n0&&Date.now()>=this._cyclePausedUntil&&this._model.length>1&&this._zoom<=1.001){const e=this._model.map(e=>e.id),t=e.indexOf(this._space);this._slideTo(e[(t+1)%e.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}get _wallUnionCache(){return this._wallUnionCacheValue}set _wallUnionCache(e){this._wallUnionCacheValue=e,null===e&&this._wallUnionPool.clear()}get _glowClipCache(){return this._glowRuntimeState.clipCache}get _glowGeometryWarnings(){return this._glowRuntimeState.geometryWarnings}get _glowFeatherUnits(){return this._glowRuntimeState.featherUnits}set _glowFeatherUnits(e){this._glowRuntimeState.featherUnits=e}get _glowRenderedSources(){return this._glowRuntimeState.renderedSources}get _glowLastAppearance(){return this._glowRuntimeState.lastAppearance}get _glowFeatherSuspendUntil(){return this._glowRuntimeState.featherSuspendUntil}set _glowFeatherSuspendUntil(e){this._glowRuntimeState.featherSuspendUntil=e}get _glowFeatherResumeTimer(){return this._glowRuntimeState.featherResumeTimer}set _glowFeatherResumeTimer(e){this._glowRuntimeState.featherResumeTimer=e}get _glowSourceSeq(){return this._glowRuntimeState.sourceSeq}set _glowSourceSeq(e){this._glowRuntimeState.sourceSeq=e}_syncDangerConfirmLocaleGate(){return this._config&&this.hass?Vu(this,Zu,np(this.hass,this._config.language)):"ready"}_dangerConfirmMissingSpace(){const e=this._model;if(!e.length)return!1;const t=this._fixedFloorState(e);return"pending"!==t.kind&&"invalid"!==t.kind&&!this._spaceModel()}_syncVersionRecovery(){this._versionRecovery.update({frontendVersion:Of(Nf),backendVersion:this._haIntegrationVersion,kiosk:!0===this._config?.kiosk,reducedMotion:this._reducedMotion})}_newContinuityController(){return new nc(()=>{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(Kf,JSON.stringify(this._viewPreference))}catch{}}_logicalViewCenter(e){const t=this._view;if(!t)return null;const i=[t.x+t.w/2,t.y+t.h/2],n="iso"===e?Wg(i):i;return{x:n[0],y:n[1]}}_convertProjectionView(e,t){if(e===t)return;this._clearRoomFocus(!0);const i=this._logicalViewCenter(e);this._view=null;const n=i?"iso"===t?jg([i.x,i.y],0):[i.x,i.y]:null;this._applyView(this._zoom,n?.[0],n?.[1]),this._warmPatch({vp:this._warmViewportState()}),this.requestUpdate()}_setProjection(e){if(!this._labsIso||"view"!==this._mode)return;const t=this._effectiveProjection();if(this._viewPreference={...this._viewPreference,[this._space]:e},"iso"===e){this._ensureIsoSceneRuntime();const e=this._isoSceneKey();e&&this._isoFallback.delete(e),this._isoFallback.delete(`${this._space}|no-borders`),this._clearIsoInvalidFallback()}this._saveViewPreference(),this._isoProjectionSnapshot=null;const i=this._effectiveProjection();this._convertProjectionView(t,i)}_hashSpace(){return mf(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 e=Gm(this.ownerDocument);var t;void 0!==e&&(this._glowScreenBlend=e),this._continuityUnsub?.(),this._continuityUnsub=tc(this.ownerDocument,this._pageVisibility),this._languageFailureUnsub?.(),this._languageFailureUnsub=function(...e){return()=>{for(const t of e)t()}}((t=()=>{this._showToast(this._t("toast.locale_load_failed"))},Xu.add(t),()=>Xu.delete(t)),function(e){return Rl.add(e),()=>{Rl.delete(e)}}(()=>this._showToast(this._t("toast.furniture_art_load_failed")))),super.connectedCallback(),this._summarySlot.connect(),this._ensureLiveRuntime().catch(()=>this.requestUpdate()),this._pointerModality.connect(this.ownerDocument.defaultView);const i=this.ownerDocument.defaultView?.MutationObserver;i&&(this._pointerHoverObserver=new i(e=>{for(const t of e)for(const e of t.addedNodes)this._syncPointerHoverSubtree(e)}),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),this._syncVersionRecovery(),this._versionRecovery.connect(),Vm(this.ownerDocument).then(e=>{e!==this._glowScreenBlend&&(this._glowScreenBlend=e,this.isConnected&&this.requestUpdate())}),this.hass&&this._ensureHaRegistryAuthority(),window.addEventListener("keydown",this._keyHandler),this._signer.start(()=>this.hass,()=>this._referencedContentUrls()),this._syncCycleTimer(),window.addEventListener("hashchange",this._onHashChange),this._labsUnsub?.(),this._labsUnsub=function(e){bf.add(e);const t=xf();return"undefined"==typeof window&&e(t),()=>{bf.delete(e)}}(this._onLabsSnapshot),this._labsIso&&this._ensureIsoSceneRuntime(),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},Lf)),!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._versionRecovery.disconnect(),this._liveRt?.dispose(),this._radarLive.stop(),this._editorRuntime?._disposeLiveEditor(),this._clearRoomFocus(!0),this._cancelDangerConfirm(),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._languageFailureUnsub?.(),this._languageFailureUnsub=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._warmModeRequest=0,this._dayCycleTimer&&(clearInterval(this._dayCycleTimer),this._dayCycleTimer=0),this._summarySlot.disconnect(),this._dayCycleClockKey="",this._bootSettleRaf&&(cancelAnimationFrame(this._bootSettleRaf),this._bootSettleRaf=0),this._bootSettling=!1;for(const e of this._activityRt.values())clearTimeout(e.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),clearTimeout(this._editorRuntimeLoadingTimer),this._editorRuntimeLoadingTimer=void 0,this._editorRuntimeLoadingVisible=!1,this._modeTransition.dispose(),this._cameraTransition.dispose(),this._cameraTransitionFit=null,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(),this._cancelDeviceDrag(),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),mm(this._glowRuntimeState,this._glowRuntimeHost),this._warmSnapshot(),this._warmRevivePending=!1,clearTimeout(this._warmReviveTimer),this._warmReviveTimer=void 0,this._warmRelease(),this._clearPlanSnapHover(),this._clearOpeningPlacement(!0),this._editorRuntime?._clearFurniturePreview(),this._editorRuntime?._furnShiftDetach(),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(e){if("Escape"===e.key&&this._vacFit){if(this._vacFit.busy)return;return this._vacFit=null,this._showToast(this._t("vac.cal_cancelled")),void e.stopPropagation()}if("Escape"===e.key){if(this._tapConfirm)return void(this._tapConfirm=null);if(this._vacCalConfirm)return void(this._vacCalConfirm.busy||(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 this._alignDialog=null,void(this._preflightClipboardFallback=null);if(this._backupImportDialog)return void(this._backupImportDialog=null);if(this._backupExportDialog)return void(this._backupExportDialog=null);if(this._pdfDialog)return void(this._pdfDialog=!1);if(this._supportDialog)return void this._editorRuntime?._closeSupportDialog();if(this._settingsDialog)return void(this._settingsDialog=null);if(this._summary?.closeDialogIfIdle())return;if(this._markerDialog)return void this._closeMarkerDialog();if(this._deviceInbox)return void(this._deviceInbox=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 e.preventDefault(),void this._editorSecondary?.closeGroup(!0)}const t=e.composedPath?.()||[e.target],i=t.some(e=>e?.matches?.('input, textarea, select, [contenteditable="true"]')),n=t.some(e=>e?.classList?.contains?.("editor-secondary")),r=e.ctrlKey||e.metaKey,o=e.key.toLowerCase(),s=/^[a-z]$/.test(o),a="z"===o||!s&&"KeyZ"===e.code,l="y"===o||!s&&"KeyY"===e.code,c=r&&(a&&e.shiftKey||l),h=r&&a&&!e.shiftKey;if("decor"===this._mode){if((h||c)&&i)return;if(c)return e.preventDefault(),void this._redoGeometry();if(h)return e.preventDefault(),this._decorDraft?void(this._decorDraft=null):this._decorMove||this._dtDrag||this._bdDrag?void this._cancelDecorGesture():void this._undoGeometry();if(("Delete"===e.key||"Backspace"===e.key)&&this._decorSel&&!i&&!n)return e.preventDefault(),void this._decorDeleteSel();const t="ArrowLeft"===e.key?[-this._gridPitch,0]:"ArrowRight"===e.key?[this._gridPitch,0]:"ArrowUp"===e.key?[0,-this._gridPitch]:"ArrowDown"===e.key?[0,this._gridPitch]:null;return!t||r||e.altKey||"select"!==this._decorTool||!this._decorSel||!this._decorList.some(e=>e.id===this._decorSel)||this._decorDraft||this._decorMove||this._dtDrag||this._bdDrag||i||n||this._editorSecondaryDialogBlocked?void("Escape"===e.key&&(e.preventDefault(),this._decorDraft?this._decorDraft=null:this._decorMove||this._dtDrag||this._bdDrag?this._cancelDecorGesture():"furniture"===this._decorTool?(this._editorRuntime?._clearFurniturePreview(),this._editorRuntime?._furnShiftDetach(),this._furnPalette=null,this._furnCategory=null,this._decorTool="select"):this._decorSel?this._decorSel=null:"select"!==this._decorTool?this._decorTool="select":this._setMode("view"))):(e.preventDefault(),void this._decorNudge(t[0],t[1]))}if("devices"===this._mode){if((h||c)&&i)return;return c?(e.preventDefault(),void this._redoDevicePosition()):h?(e.preventDefault(),void this._undoDevicePosition()):void("Escape"===e.key&&this._deviceDrag&&(e.preventDefault(),this._cancelDeviceDrag()))}if(this._markup&&(!h&&!c||!i)){if(("Delete"===e.key||"Backspace"===e.key)&&this._physicalSel&&!i&&!n)return e.preventDefault(),void this._deletePhysicalSelection();if(c)return e.preventDefault(),void this._redoGeometry();if(h)return e.preventDefault(),this._resize?.dragging?void this._rszCancelDrag():this._wallFaceBatch?(this._roomDialogCancel(),void(this._activeWallChainId&&this._path.length>1?this._undoActiveWallPoint():this._undoPoint())):"draw"===this._tool&&this._path.length?void(this._activeWallChainId&&this._path.length>1?this._undoActiveWallPoint():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"===e.key)return this._physicalDrag||this._physicalRotate?(e.preventDefault(),void this._cancelPhysicalGesture()):this._roomDialog?(e.preventDefault(),void this._roomDialogCancel()):"draw"===this._tool&&this._path.length?(e.preventDefault(),void this._finishWallChain()):this._physicalSel?(e.preventDefault(),void(this._physicalSel=null)):"resize"===this._tool?(e.preventDefault(),this._resize?.dragging?void this._rszCancelDrag():("exit-tool"===this._resize?.escapeIdle()&&(this._tool="draw"),void this.requestUpdate())):"split"===this._tool?(e.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?(e.preventDefault(),void(this._mergeSel?this._mergeSel=null:this._tool="draw")):this._wallDialog?(e.preventDefault(),void(this._wallDialog=null)):void("opening"!==this._tool&&"wallthick"!==this._tool&&"delroom"!==this._tool&&"column"!==this._tool||(e.preventDefault(),"opening"===this._tool&&this._clearOpeningPlacement(!0),this._tool="draw"))}}_undoPoint(){if(this._path.length)return this._contourClosed?(this._path=this._path.slice(0,-1),void(this._closingWallCm=null)):void(this._activeWallChainPartitionIds.length&&this._path.length>1?this._undoActiveWallPoint():this._path=this._path.slice(0,-1))}_undoActiveWallPoint(){const e=[...this._activeWallChainPartitionIds],t=e[e.length-1],i=this._spaceModel()?.partitions.find(e=>e.id===t),n=this._path[0]?[...this._path[0]]:null,r=this._path.slice(0,-1).map(e=>[...e]),o=this._wallChainSegmentCms.slice(0,-1),s=this._geometryHistory.undo();if(!s)return this._activeWallChainPartitionIds=[],this._wallChainSegmentCms=[],this._wallChainRedo=[],void(this._path=n?[n]:[]);this._applyGeometryState(s.before,!0)?(this._activeWallChainId||=`chain-${Date.now().toString(36)}`,this._activeWallChainPartitionIds=e.slice(0,-1),this._path=r.length?r:n?[n]:[],this._wallChainSegmentCms=o,i&&this._wallChainRedo.push({id:i.id,point:[...i.b],cm:i.cm}),this._clearPlanSnapHover(),this._showToast(this._t("history.undone",{name:s.name}))):this._geometryHistory.clear()}static async getConfigElement(){return await import("./editor-Gxbn7bnW.js"),document.createElement("houseplan-card-editor")}static getStubConfig(){return{type:"custom:houseplan-card"}}static _warmBootReset(e){for(const e of Bf.values())for(const t of e)clearTimeout(t.evict);Bf.clear(),jf=e&&e>0?e:1e4}static _warmBootStats(){let e=0,t=0;const i=[];for(const n of Bf.values())for(const r of n)e++,r.dlg&&(t++,i.push(r.dlg.kind));return{keys:Bf.size,slots:e,dlgs:t,drafts:i}}setConfig(e){const t=this._config,i=!!t&&Object.prototype.hasOwnProperty.call(t,"floor");this._config={icon_size:2.5,show_temperature:!0,live_states:!0,show_signal:!0,...e};(i!==this._hasFixedFloor||t?.floor!==this._config.floor)&&(this._hashApplied=!1,this._navApplied=!1,this._warmVpArmed=!1),this._config.kiosk&&(this._booting=!1,this._bootFading=!1),!this._hasFixedFloor&&e.default_floor&&this._commitSpace(e.default_floor,!0);try{this._zoomBySpace=JSON.parse(localStorage.getItem(Vf)||"{}")||{}}catch{this._zoomBySpace={}}try{const e=JSON.parse(localStorage.getItem(Kf)||"{}")||{};this._viewPreference=Object.fromEntries(Object.entries(e).filter(e=>"flat"===e[1]||"iso"===e[1]))}catch{this._viewPreference={}}if(this._labs=xf(),this.isConnected&&this._labsIso&&this._ensureIsoSceneRuntime(),!this._summary?.applyLocalScaleForCurrentIdentity())try{const e=JSON.parse(localStorage.getItem("houseplan_card_kiosk_v1")||"null");this._kioskScale={icon:Nn(e?.icon),font:Nn(e?.font)}}catch{}try{const e=JSON.parse(localStorage.getItem(Uf)||"null");this._adoption.restoreCached(e)&&(this._seedDecorStyle(this._serverCfg),this._cfgEpoch++,this._virtualLights=$h(e.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),this._syncVersionRecovery()}_warmAdopt(){if(this._config?.kiosk)return;const e=hf(this._config);if(this._warmKey===e&&this._warmSlot)return;this._warmSlot&&this._warmRelease();const t=this.parentNode,i=this._warmIdx(t),n=Bf.get(e);if(!n||!n.length)return;const r=n.find(e=>e.owner===this._warmGen);if(r)return this._warmLongReturn=!!r.freed&&Date.now()-r.freed>=Jl,clearTimeout(r.evict),r.evict=0,r.freed=0,r.live=!0,this._warmSlot=r,this._warmKey=e,r.frameFingerprint&&this._continuity.adoptCompleteFrame(r.frameFingerprint),void(!this._devices.length&&r.devices?.length&&(this._devices=[...r.devices]));const{slot:o,sure:s}=((e,t,i,n)=>{const r=e=>{const t=!!i&&e.place?.deref()===i;return t&&e.idx===n?4:e.live?0:t?3:2};let o=null,s=0,a=0,l=null;for(const i of e){if(i.owner===t)continue;l=i;const e=r(i);e<=0||(e>s?(o=i,s=e,a=1):e===s&&a++)}return!o||a>1?{slot:o||l,sure:!1}:{slot:o,sure:!0}})(n,this._warmGen,t,i);o&&(this._warmLongReturn=!!o.freed&&Date.now()-o.freed>=Jl,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},Lf)),this._warmKey=e,s?(clearTimeout(o.evict),o.evict=0,o.owner=this._warmGen,o.place=t?new WeakRef(t):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:t?new WeakRef(t):null,idx:i,live:!0,hdrH:o.hdrH,stageH:o.stageH,vp:null,frameFingerprint:"",devices:null,dlg:null,freed:0,evict:0},n.push(this._warmSlot),this._warmTrim(n)))}_warmIdx(e){const t=e?.children;if(!t)return-1;for(let e=0;e4;){const t=e.findIndex(e=>!e.live);if(t<0)break;clearTimeout(e[t].evict),e.splice(t,1)}}_warmScheduleEvict(e,t){if(clearTimeout(e.evict),!(e.dlg||e.vp&&"view"!==e.vp.mode))return;const i=e.freed,n=e.owner;e.evict=window.setTimeout(()=>{if(e.evict=0,e.freed!==i||e.owner!==n)return;var r;e.dlg=null,e.vp=(r=e.vp)&&"view"!==r.mode?{...r,mode:"view",zoom:r.snap?.space===r.space?r.snap.zoom:r.zoom,view:null,snap:null,tool:"draw",decorTool:"select",showHidden:!1,selId:null,rszSel:null,decorSel:null}:r,e.frameFingerprint="";const o=Bf.get(t);if(!e.live&&o&&o.length>1){const t=o.indexOf(e);t>=0&&o.splice(t,1)}},jf+250)}_warmAdoptViewport(e){const t=this._warmVp;if(!t||this._warmSlot?.path!==location.pathname)return void(this._warmVp=null);const i=this._fixedFloorState();if(this._hashApplied||!this._model.find(e=>e.id===t.space)||"valid"===i.kind&&i.id!==t.space||this._hasFixedFloor&&"valid"!==i.kind)return void(this._warmVp=null);this._commitSpace(t.space,!0),this._navApplied=!0;const n="view"!==t.mode&&this._canEdit&&!e.kiosk?t.mode:"view";this._adoptMode("view"),this._pendingNavMode="view"===t.mode||this._canEdit||e.kiosk?null:t.mode,this._zoom=t.zoom;const r=this._effectiveProjection(),o=r===t.projection&&this._labsIso===t.activeLabsIso;if(this._view=o&&t.view?{...t.view}:null,this._viewModeSnap=o&&t.snap?{...t.snap}:null,!o&&t.logicalCenter){const e="iso"===r?jg([t.logicalCenter.x,t.logicalCenter.y],0):[t.logicalCenter.x,t.logicalCenter.y];this._applyView(t.zoom,e[0],e[1])}var s;this._tool="opening"===(s=function(e){return"partition"===e?"draw":e}(s=t.tool))?"draw":"string"==typeof s&&cf.has(s)?s:"draw",this._decorTool=t.decorTool,this._showHidden=t.showHidden,this._showFar!==t.showFar&&(this._showFar=t.showFar,this._frame=null),this._selId=t.selId,this._resize?.restoreSelection(t.rszSel),this._decorSel=t.decorSel,this._warmVpArmed=!0,"view"!==n&&this._requestMode(n,!1,!0)}_warmPatch(e,t=!1){if(this._config?.kiosk)return;const i=hf(this._config);if(!this._warmSlot||this._warmKey===i){if(!this._warmSlot){if(!t)return;const e=this.parentNode;this._warmKey=i,this._warmSlot={owner:this._warmGen,path:location.pathname,place:e?new WeakRef(e):null,idx:this._warmIdx(e),live:!0,hdrH:this._hdrH,stageH:0,vp:null,frameFingerprint:"",devices:null,dlg:null,freed:0,evict:0};const n=Bf.get(i)||[];for(n.push(this._warmSlot),Bf.set(i,n),this._warmTrim(n);Bf.size>8;){const e=Bf.keys().next().value;if(void 0===e||e===i)break;for(const t of Bf.get(e)||[])clearTimeout(t.evict);Bf.delete(e)}}Object.assign(this._warmSlot,e)}}_warmViewportState(){const e=this._effectiveProjection();return{space:this._space,mode:this._mode,projection:e,activeLabsIso:this._labsIso,logicalCenter:this._logicalViewCenter(e),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._resize?.selectedRoomId,decorSel:this._decorSel}}_warmDialogState(){const e=(e,t)=>({kind:e,space:this._space,mode:this._mode,data:t});return this._tapConfirm||this._alignDialog||this._mergeDialog||this._importDialog||this._backupExportDialog||this._backupImportDialog?null:this._openingInfo?e("openingInfo",this._openingInfo.id):this._infoCard?e("info",this._infoCard.id):this._rulesDialog?this._rulesDialog.busy?null:e("rules",this._rulesDialog):this._settingsDialog?this._settingsDialog.busy?null:e("settings",this._settingsDialog):this._markerDialog?this._markerDialog.busy?null:e("marker",this._markerDialog):this._openingDialog?e("opening",this._openingDialog):this._backdropDialog?e("backdrop",this._backdropDialog):this._decorShapeDialog?e("decorShape",this._decorShapeDialog):this._decorTextDialog?e("decorText",this._decorTextDialog):this._roomDialog?e("room",{editId:this._roomEditId,fill:this._roomFill,customFill:this._roomCustomFill,tempMin:this._roomTempMin,tempMax:this._roomTempMax,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:e("space",this._spaceDialog):null}_warmSnapshot(){if(this._booting||this._config?.kiosk||"steady"!==this._continuity.state)return;const e={vp:this._warmViewportState(),frameFingerprint:this._continuity.frameFingerprint,devices:this._devices,hdrH:this._hdrH};if(this._warmRevivePending||(e.dlg=this._warmDialogState()),this.isConnected&&this._warmSlot?.owner===this._warmGen){const t=this.parentNode;e.place=t?new WeakRef(t):null,e.idx=this._warmIdx(t)}this._warmPatch(e)}_warmReviveDialog(){const e=this._warmSlot;if(this._warmReviveTimer=void 0,!e||!e.dlg)return void(this._warmRevivePending=!1);const t=e.dlg,i=e.freed;if(t.mode===this._mode||"view"===t.mode||this._warmVp?.mode!==t.mode||this._editorRuntime){if(this._warmRevivePending=!1,e.dlg=null,e.freed=0,clearTimeout(e.evict),e.evict=0,i&&!(Date.now()-i>jf)&&t.space===this._space&&t.mode===this._mode){switch(t.kind){case"space":this._spaceDialog={...t.data,busy:!1,savedBusy:!1};break;case"marker":this._markerDialog={...t.data,busy:!1};break;case"settings":this._settingsDialog={...t.data,busy:!1};break;case"rules":this._rulesDialog={...t.data,busy:!1};break;case"opening":this._openingDialog={...t.data};break;case"backdrop":this._backdropDialog={...t.data};break;case"decorShape":this._decorShapeDialog={...t.data};break;case"decorText":{this._decorTextDialog={...t.data};const e=String(this._decorTextDialog?.text??"").length;this._decorTextSelection={start:e,end:e};break}case"room":{const e=t.data;this._roomEditId=e.editId,this._roomFill=e.fill,this._roomCustomFill=e.customFill||null,this._roomTempMin=e.tempMin||"",this._roomTempMax=e.tempMax||"",this._roomTempSrc=e.tempSrc,this._roomHumSrc=e.humSrc,this._roomSrcOpen=e.srcOpen,this._roomSrcFilter=e.srcFilter,this._roomNameScale=e.nameScale,this._roomLabelScale=e.labelScale,this._areaSel=e.areaSel,this._nameSel=e.nameSel,this._pendingSplit=e.pendingSplit,this._wallFaceBatch=e.wallFaceBatch||null,this._path=e.path,this._wallFaceBatch&&(this._activeWallChainId=`chain-${Date.now().toString(36)}`,this._activeWallChainPartitionIds=[...this._wallFaceBatch.activePartitionIds],this._wallChainSegmentCms=[...this._wallFaceBatch.activeCms]),this._roomDialog=!0;break}case"info":{const e=this._devices.find(e=>e.id===t.data);e&&(this._infoCard=e);break}case"openingInfo":{const e=(this._curSpaceCfg?.openings||[]).find(e=>e.id===t.data);e&&(this._openingInfo=e);break}}this.requestUpdate()}}else this._warmRevivePending=!0}_cacheSnapshot(){if(this._serverCfg)try{this._virtualLights=function(e,t,i){if(e.configRev===i)return e;const n=new Set((Array.isArray(t?.markers)?t.markers:[]).filter(Ch).map(e=>e.id));return{...e,configRev:i,off:new Set([...e.off].filter(e=>n.has(e)))}}(this._virtualLights,this._serverCfg,this._cfgRev);const e=this._adoption.snapshot(function(e){return{rev:e.rev,config_rev:e.configRev,off:[...e.off].sort()}}(this._virtualLights));e&&localStorage.setItem(Uf,JSON.stringify(e))}catch{}}_beginContinuityCandidate(e,t,i="plan"){return this._booting&&!this._continuity.hasCompleteFrame?this._continuity.token:(this._continuityDataReady=t,this._continuityPaintToken=-1,this._stagedDeviceSnapshotToken=-1,this._resumeSettling=!0,this._continuity.beginCandidate(e,i))}_continuityStageValid(){const e=this._stageEl;return!!e&&e.clientWidth>0&&e.clientHeight>0}_versionReloadSafetySnapshot(){return sg(this)}_continuityAssetsReady(){if(!this._model.length)return!1;const e=this._model.length?this._spaceModel():null;return!e?.bg?.href||this._signer.isReady(this.hass,e.bg.href)}_initialSpaceSelection(e,t=this._loadOk){const i=this._fixedFloorState(e,t);return"valid"===i.kind?{id:i.id,source:"fixed"}:this._hasFixedFloor?{id:null,source:"none"}:function(e){const t=new Set(e.spaceIds.filter(e=>!!e));if(!t.size)return{id:null,source:"none"};const i=[["hash",!1===e.acceptHash?null:e.hashSpace],["current",e.preserveCurrent?e.currentSpace:null],["saved",e.savedSpace],["default",e.defaultSpace],["first",e.spaceIds[0]]];for(const[e,n]of i)if(n&&t.has(n))return{id:n,source:e};return{id:null,source:"none"}}({spaceIds:e.map(e=>e.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(e,t=this._loadOk){const i=this._initialSpaceSelection(e,t);return i.id?(this._commitSpace(i.id,!0),"hash"===i.source&&(this._hashApplied=!0),"saved"===i.source&&(this._navApplied=!0),i):i}_candidateBackdrop(e,t=this._space){const i=Va(e),n=this._fixedFloorState(i,!0);if(this._hasFixedFloor&&"valid"!==n.kind)return"";const r=this._initialSpaceSelection(i,!0).id||(i.some(e=>e.id===t)?t:i[0]?.id);return i.find(e=>e.id===r)?.bg?.href||""}_visualFrameFingerprint(){const e=this._stageEl,t=e?[e.clientWidth,e.clientHeight]:[0,0];return oc([this._cfgRev,this._adoption.currentConfigFingerprint(),this._layoutRev,this._adoption.currentLayoutFingerprint(),this._space,this._mode,this._view,t,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 e=this._continuity.token;if(this._candidateDeviceSnapshot&&this._candidateDeviceSnapshot!==this._visibleDeviceSnapshot&&this._stagedDeviceSnapshotToken!==e)return this._stagedDeviceSnapshotToken=e,void this.requestUpdate();this._continuityPaintToken!==e&&(this._continuityPaintToken=e,this._continuity.candidateReady(e)&&this._continuity.commitAfterPaint(e,{updateComplete:()=>this.updateComplete,stageValid:()=>this.isConnected&&this._continuityStageValid(),assetsReady:()=>this._continuityAssetsReady(),frameFingerprint:()=>this._visualFrameFingerprint()}).then(t=>{t&&e===this._continuity.token?(this._resumeSettling=!1,this._renderSnapshotAt=Date.now(),this._candidateDeviceSnapshot&&(this._visibleDeviceSnapshot=this._candidateDeviceSnapshot),this._candidateDeviceSnapshot=null,this._stagedDeviceSnapshotToken=-1,this._warmSnapshot()):e===this._continuity.token&&(this._continuityPaintToken=-1,this._stagedDeviceSnapshotToken=-1,this._candidateDeviceSnapshot=null,this.requestUpdate())}))}_onBackdropLoaded(e,t){this._signer.markLoaded(this.hass,e,t),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 V;const e="connection"===this._continuity.recoveryReason;return j`
diff --git a/custom_components/houseplan/frontend/houseplan-assets/houseplan-editor-runtime-DbApDIhu.js b/custom_components/houseplan/frontend/houseplan-assets/houseplan-editor-runtime-BR7ukTUP.js
similarity index 99%
rename from custom_components/houseplan/frontend/houseplan-assets/houseplan-editor-runtime-DbApDIhu.js
rename to custom_components/houseplan/frontend/houseplan-assets/houseplan-editor-runtime-BR7ukTUP.js
index 309708b8..36e1e359 100644
--- a/custom_components/houseplan/frontend/houseplan-assets/houseplan-editor-runtime-DbApDIhu.js
+++ b/custom_components/houseplan/frontend/houseplan-assets/houseplan-editor-runtime-BR7ukTUP.js
@@ -1,4 +1,4 @@
-globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="c8d5c166e30a11241ef32c7e1dc70368632e84c448524a8340494350ec4d5fca";import{s as t,e,n as s,f as i,i as o,l as a,o as n,r,A as l,b as h,D as c,w as d,N as p,a as u,c as _,d as m,g,h as f,j as b,k as v,m as y,p as $,q as w,t as k,u as x,v as S,x as M,y as C,z as P,B as D,C as I,E as T,F as z,G as R,H as A,I as F,J as N,K as E,L as H,M as O,O as L,P as B,Q as W,R as j,S as G,T as q,U,V as K,W as V,X as J,Y,Z as X,_ as Z,$ as Q,a0 as tt,a1 as et,a2 as st,a3 as it,a4 as ot,a5 as at,a6 as nt,a7 as rt,a8 as lt,a9 as ht,aa as ct,ab as dt,ac as pt,ad as ut,ae as _t,af as mt,ag as gt,ah as ft,ai as bt,aj as vt,ak as yt,al as $t,am as wt,an as kt,ao as xt,ap as St,aq as Mt,ar as Ct,as as Pt,at as Dt,au as It,av as Tt,aw as zt,ax as Rt,ay as At,az as Ft,aA as Nt,aB as Et,aC as Ht,aD as Ot,aE as Lt,aF as Bt,aG as Wt,aH as jt,aI as Gt,aJ as qt,aK as Ut,aL as Kt,aM as Vt,aN as Jt,aO as Yt,aP as Xt,aQ as Zt,aR as Qt,aS as te,aT as ee,aU as se,aV as ie,aW as oe,aX as ae,aY as ne,aZ as re,a_ as le,a$ as he,b0 as ce,b1 as de,b2 as pe,b3 as ue,b4 as _e,b5 as me,b6 as ge,b7 as fe,b8 as be,b9 as ve,ba as ye,bb as $e,bc as we,bd as ke,be as xe,bf as Se,bg as Me,bh as Ce,bi as Pe,bj as De,bk as Ie,bl as Te,bm as ze,bn as Re,bo as Ae,bp as Fe,bq as Ne,br as Ee,bs as He,bt as Oe,bu as Le,bv as Be,bw as We,bx as je,by as Ge,bz as qe,bA as Ue,bB as Ke,bC as Ve,bD as Je,bE as Ye,bF as Xe,bG as Ze,bH as Qe,bI as ts,bJ as es,bK as ss,bL as is,bM as os,bN as as,bO as ns,bP as rs,bQ as ls,bR as hs,bS as cs,bT as ds,bU as ps,bV as us,bW as _s,bX as ms,bY as gs,bZ as fs,b_ as bs,b$ as vs,c0 as ys,c1 as $s,c2 as ws,c3 as ks,c4 as xs,c5 as Ss,c6 as Ms,c7 as Cs,c8 as Ps,c9 as Ds,ca as Is,cb as Ts,cc as zs,cd as Rs,ce as As,cf as Fs,cg as Ns,ch as Es,ci as Hs,cj as Os,ck as Ls,cl as Bs,cm as Ws,cn as js,co as Gs,cp as qs,cq as Us,cr as Ks,cs as Vs,ct as Js,cu as Ys,cv as Xs,cw as Zs,cx as Qs,cy as ti,cz as ei,cA as si,cB as ii,cC as oi,cD as ai,cE as ni,cF as ri,cG as li,cH as hi,cI as ci,cJ as di,cK as pi,cL as ui,cM as _i,cN as mi,cO as gi,cP as fi,cQ as bi,cR as vi,cS as yi,cT as $i,cU as wi,cV as ki,cW as xi,cX as Si,cY as Mi,cZ as Ci,c_ as Pi,c$ as Di,d0 as Ii,d1 as Ti,d2 as zi,d3 as Ri,d4 as Ai,d5 as Fi,d6 as Ni,d7 as Ei,d8 as Hi,d9 as Oi,da as Li,db as Bi,dc as Wi,dd as ji,de as Gi,df as qi,dg as Ui,dh as Ki,di as Vi,dj as Ji,dk as Yi,dl as Xi,dm as Zi,dn as Qi,dp as to,dq as eo,dr as so,ds as io,dt as oo,du as ao,dv as no,dw as ro,dx as lo,dy as ho,dz as co}from"./houseplan-card-DXAxXz4t.js";import{i as po}from"./guard-IppSarFv.js";import{F as uo,f as _o,p as mo,c as go,e as fo,r as bo,a as vo,s as yo}from"./backdrop-pick-qyPNmULR.js";import{t as $o,h as wo,m as ko,T as xo}from"./zigbee-topology-rqneqkBH.js";import{GENERATED_FURNITURE_ART as So,FURNITURE_ART_FINGERPRINT as Mo}from"./furniture-plan-art.generated-Dw0IIirB.js";var Co={"gs.hint":"Fill colors apply to every space; each color has its own opacity. Which fill mode a space uses is set in that space's dialog.","gs.show_room_tooltip":"Show the room information window on hover","support.about_group":"About the card","support.guide_group":"Documentation","support.guide":"User guide","support.form_group":"Send a report or suggestion","support.contact":"Contact details (email/tg/WhatsApp), optional.","support.message":"Message","support.attach":"Attach anonymized information from your plan","support.attach_hint":"Includes only allowed plan geometry, settings and bounded runtime facts. Excludes names, Home Assistant IDs, live states, URLs, files, and your message/contact.","support.geometry_warning":"The package contains no names or Home Assistant IDs, but it does contain the exact geometry and dimensions of your home.","support.close_busy_title":"Stop the current operation?","support.close_busy_body":"House Plan is preparing or sending the report. Closing now stops waiting for the result.","support.building":"Preparing anonymized data…","support.preview_summary":"Package v{version} · {spaces} spaces · {size} KiB","support.prepared":"Snapshot prepared {n} min ago","support.show_data":"Show data","support.download":"Download JSON","support.refresh":"Refresh snapshot","support.privacy":"When you send, your message, optional contact and, if selected, exact geometry leave your Home Assistant through the House Plan project relay and are visible to maintainers. The project node keeps the report for up to 30 days. Network infrastructure sees your HA server address, but House Plan does not retain it raw; rate-limit and idempotency metadata is kept for up to 24 hours.","support.error_title":"The report was not sent","support.manual_recovery":"You can keep the message and attachment and continue manually:","support.copy_message":"Copy message","support.success":"Report sent: {id}. Save this number when contacting support.","support.copy_id":"Copy ID","support.sending":"Sending…","support.retry":"Retry","support.send":"Send","support.update_required":"Update the House Plan card and integration to compatible versions to send reports.","support.message_copied":"Message copied","support.id_copied":"Report ID copied","support.copy_failed":"Could not access the clipboard. Select and copy the text manually.","support.validation.message_required":"Enter a message.","support.validation.message_too_long":"The message must contain no more than 10,000 characters.","support.validation.contact_too_long":"Contact details must contain no more than 320 characters.","support.validation.preview_missing":"Wait for the attachment preview or turn the attachment off.","support.validation.preview_expired":"The attachment preview expired. Refresh the snapshot.","support.error.support_invalid_message":"Check the message and try again.","support.error.support_preview_expired":"The attachment preview expired or is no longer available. Refresh the snapshot.","support.error.support_package_too_large":"The anonymized package exceeds the 8 MiB limit.","support.error.support_rate_limited":"Too many reports or previews were requested. Try again later.","support.error.support_unavailable":"The private support service is temporarily unavailable. Your draft remains here.","support.error.support_rejected":"The report did not pass the support service validation.","support.error.unauthorized":"You do not have permission to send this report.","vac.routes_section":"Maps and floors","vac.routes_current_map":"Current map","vac.routes_no_map":"no telemetry","vac.routes_status":"Routing","vac.routes_state_ready":"map assigned and calibrated","vac.routes_state_needs_calibration":"map assigned, calibration needed","vac.routes_state_unmapped":"current map is not assigned to a floor","vac.routes_state_ambiguous":"two maps are indistinguishable — no floor is chosen","vac.routes_state_missing_space":"the map's space was deleted","vac.routes_state_none":"no map data","vac.routes_empty":"No map is assigned to a floor yet.","vac.route_map_default":"no map id","vac.route_active":"Active","vac.route_space":"Space","vac.route_space_none":"not selected","vac.route_status_ready":"ready","vac.route_status_needs_calibration":"needs calibration","vac.route_status_ambiguous":"ambiguous","vac.route_status_missing_space":"space deleted","vac.route_missing_space_group":"Deleted space","vac.route_add_current":"Add current map","vac.route_delete":"Remove map","vac.route_delete_title":"Remove the map from its floor?","vac.route_delete_body":"Calibration and saved paths for this map will be removed. Continue?","vac.route_delete_confirm":"Remove","vac.route_space_title":"Move the map to another space?","vac.route_space_body":"Calibration and saved paths for this map will be removed. Continue?","vac.route_space_confirm":"Move","vac.route_missing_space_hint":"One of the maps points at a deleted space: pick a new one or remove the map. Until then the robot is not drawn for that map.","vac.route_default_hint":"The source reports no stable map id. Several floors cannot be told apart without another source or the robot's own selected map.","vac.route_target_hint":"The dock stays in the “{space}” space regardless of the current map.","vac.route_add_source":"Add a map source","vac.route_add_source_hint":"For integrations that give each map its own camera. The “All cameras” section above widens this list.","vac.route_source_no_map":"no map reported"};const Po={en:Co,ru:{"gs.hint":"Цвета заливок действуют на все пространства; у каждого цвета своя прозрачность. Какой режим заливки использует пространство — задаётся в его диалоге.","gs.show_room_tooltip":"Показывать окно с информацией при наведении на комнату","support.about_group":"О карточке","support.guide_group":"Документация","support.guide":"Руководство пользователя","support.form_group":"Отправить репорт или предложение","support.contact":"Контакт для связи (email/tg/WhatsApp), необязательно.","support.message":"Сообщение","support.attach":"Прикрепить обезличенную информацию из вашего плана","support.attach_hint":"В пакет входят только разрешённые геометрия, настройки и ограниченные сведения о среде. Не входят имена, HA id, текущие состояния, URL, файлы, сообщение и контакт.","support.geometry_warning":"Пакет не содержит имён и HA id, но содержит точную геометрию и размеры дома.","support.close_busy_title":"Прервать текущую операцию?","support.close_busy_body":"House Plan подготавливает или отправляет репорт. При закрытии ожидание результата прекратится.","support.building":"Подготавливаем обезличенные данные…","support.preview_summary":"Пакет v{version} · пространств: {spaces} · {size} КиБ","support.prepared":"Снимок подготовлен {n} мин назад","support.show_data":"Показать данные","support.download":"Скачать JSON","support.refresh":"Обновить снимок","support.privacy":"При отправке сообщение, необязательный контакт и, если выбран пакет, точная геометрия покидают ваш Home Assistant через relay проекта House Plan и доступны мейнтейнерам. Узел проекта хранит репорт до 30 дней. Сетевая инфраструктура видит адрес сервера HA, но House Plan не сохраняет его в исходном виде; метаданные лимитов и идемпотентности хранятся до 24 часов.","support.error_title":"Репорт не отправлен","support.manual_recovery":"Сообщение и вложение можно сохранить и продолжить вручную:","support.copy_message":"Копировать сообщение","support.success":"Репорт отправлен: {id}. Сохраните номер для связи с поддержкой.","support.copy_id":"Копировать ID","support.sending":"Отправляем…","support.retry":"Повторить","support.send":"Отправить","support.update_required":"Обновите карточку и интеграцию House Plan до совместимых версий, чтобы отправлять репорты.","support.message_copied":"Сообщение скопировано","support.id_copied":"ID репорта скопирован","support.copy_failed":"Не удалось получить доступ к буферу обмена. Выделите и скопируйте текст вручную.","support.validation.message_required":"Введите сообщение.","support.validation.message_too_long":"Сообщение должно содержать не более 10 000 символов.","support.validation.contact_too_long":"Контакт должен содержать не более 320 символов.","support.validation.preview_missing":"Дождитесь предпросмотра вложения или отключите его.","support.validation.preview_expired":"Предпросмотр вложения истёк. Обновите снимок.","support.error.support_invalid_message":"Проверьте сообщение и повторите попытку.","support.error.support_preview_expired":"Предпросмотр вложения истёк или больше недоступен. Обновите снимок.","support.error.support_package_too_large":"Обезличенный пакет превышает лимит 8 МиБ.","support.error.support_rate_limited":"Запрошено слишком много репортов или предпросмотров. Повторите позже.","support.error.support_unavailable":"Закрытая служба поддержки временно недоступна. Черновик сохранён в этом окне.","support.error.support_rejected":"Репорт не прошёл проверку службы поддержки.","support.error.unauthorized":"У вас нет прав на отправку этого репорта.","vac.routes_section":"Карты и этажи","vac.routes_current_map":"Текущая карта","vac.routes_no_map":"источник молчит","vac.routes_status":"Маршрутизация","vac.routes_state_ready":"карта сопоставлена и откалибрована","vac.routes_state_needs_calibration":"карта сопоставлена, нужна калибровка","vac.routes_state_unmapped":"текущая карта не сопоставлена этажу","vac.routes_state_ambiguous":"две карты неразличимы — этаж не выбирается","vac.routes_state_missing_space":"пространство карты удалено","vac.routes_state_none":"нет данных о карте","vac.routes_empty":"Ни одна карта ещё не сопоставлена этажу.","vac.route_map_default":"без идентификатора","vac.route_active":"Текущая","vac.route_space":"Пространство","vac.route_space_none":"не выбрано","vac.route_status_ready":"готова","vac.route_status_needs_calibration":"нужна калибровка","vac.route_status_ambiguous":"неоднозначна","vac.route_status_missing_space":"пространство удалено","vac.route_missing_space_group":"Пространство удалено","vac.route_add_current":"Добавить текущую карту","vac.route_delete":"Удалить карту","vac.route_delete_title":"Удалить карту с этажа?","vac.route_delete_body":"Калибровка и сохранённые пути этой карты будут удалены. Продолжить?","vac.route_delete_confirm":"Удалить","vac.route_space_title":"Перенести карту в другое пространство?","vac.route_space_body":"Калибровка и сохранённые пути этой карты будут удалены. Продолжить?","vac.route_space_confirm":"Перенести","vac.route_missing_space_hint":"Одна из карт ссылается на удалённое пространство: выберите новое или удалите карту. Пока ссылка не исправлена, робот на этой карте не рисуется.","vac.route_default_hint":"Источник не сообщает стабильный идентификатор карты. Несколько этажей нельзя различить без другого источника или собственной карты робота.","vac.route_target_hint":"Док остаётся в пространстве «{space}» независимо от текущей карты.","vac.route_add_source":"Добавить источник карты","vac.route_add_source_hint":"Для интеграций, где у каждой карты своя камера. Список расширяется разделом «Все камеры» выше.","vac.route_source_no_map":"карта не читается"},de:{"gs.hint":"Füllfarben gelten für jeden Bereich; jede Farbe hat ihre eigene Deckkraft. Der Füllmodus wird in den Einstellungen des jeweiligen Bereichs festgelegt.","gs.show_room_tooltip":"Rauminformationen beim Darüberfahren anzeigen","support.about_group":"Über die Karte","support.guide_group":"Dokumentation","support.guide":"Benutzerhandbuch","support.form_group":"Bericht oder Vorschlag senden","support.contact":"Kontakt (E-Mail/tg/WhatsApp), optional.","support.message":"Nachricht","support.attach":"Anonymisierte Informationen aus dem Plan anhängen","support.attach_hint":"Enthält nur erlaubte Plangeometrie, Einstellungen und begrenzte Laufzeitdaten. Namen, Home-Assistant-IDs, Live-Zustände, URLs, Dateien, Nachricht und Kontakt werden ausgeschlossen.","support.geometry_warning":"Das Paket enthält keine Namen oder Home-Assistant-IDs, aber die exakte Geometrie und die Maße Ihres Hauses.","support.close_busy_title":"Aktuellen Vorgang abbrechen?","support.close_busy_body":"House Plan bereitet den Bericht vor oder sendet ihn. Beim Schließen wird nicht weiter auf das Ergebnis gewartet.","support.building":"Anonymisierte Daten werden vorbereitet…","support.preview_summary":"Paket v{version} · {spaces} Bereiche · {size} KiB","support.prepared":"Schnappschuss vor {n} Min. erstellt","support.show_data":"Daten anzeigen","support.download":"JSON herunterladen","support.refresh":"Schnappschuss aktualisieren","support.privacy":"Beim Senden verlassen Ihre Nachricht, der optionale Kontakt und, falls ausgewählt, die exakte Geometrie Ihren Home Assistant über das House-Plan-Projektrelay und sind für die Maintainer sichtbar. Der Projektserver speichert den Bericht bis zu 30 Tage. Die Netzwerkinfrastruktur sieht die Adresse Ihres HA-Servers, House Plan speichert sie jedoch nicht im Rohformat; Limit- und Idempotenzdaten bleiben bis zu 24 Stunden erhalten.","support.error_title":"Der Bericht wurde nicht gesendet","support.manual_recovery":"Nachricht und Anhang können gespeichert und manuell weitergegeben werden:","support.copy_message":"Nachricht kopieren","support.success":"Bericht gesendet: {id}. Bewahren Sie diese Nummer für den Support auf.","support.copy_id":"ID kopieren","support.sending":"Wird gesendet…","support.retry":"Erneut versuchen","support.send":"Senden","support.update_required":"Aktualisieren Sie House-Plan-Karte und Integration auf kompatible Versionen, um Berichte zu senden.","support.message_copied":"Nachricht kopiert","support.id_copied":"Berichts-ID kopiert","support.copy_failed":"Kein Zugriff auf die Zwischenablage. Markieren und kopieren Sie den Text manuell.","support.validation.message_required":"Geben Sie eine Nachricht ein.","support.validation.message_too_long":"Die Nachricht darf höchstens 10.000 Zeichen enthalten.","support.validation.contact_too_long":"Der Kontakt darf höchstens 320 Zeichen enthalten.","support.validation.preview_missing":"Warten Sie auf die Vorschau oder deaktivieren Sie den Anhang.","support.validation.preview_expired":"Die Anhangsvorschau ist abgelaufen. Aktualisieren Sie den Schnappschuss.","support.error.support_invalid_message":"Prüfen Sie die Nachricht und versuchen Sie es erneut.","support.error.support_preview_expired":"Die Anhangsvorschau ist abgelaufen oder nicht mehr verfügbar. Aktualisieren Sie den Schnappschuss.","support.error.support_package_too_large":"Das anonymisierte Paket überschreitet das Limit von 8 MiB.","support.error.support_rate_limited":"Zu viele Berichte oder Vorschauen wurden angefordert. Versuchen Sie es später erneut.","support.error.support_unavailable":"Der private Supportdienst ist vorübergehend nicht verfügbar. Der Entwurf bleibt in diesem Fenster erhalten.","support.error.support_rejected":"Der Bericht hat die Prüfung des Supportdienstes nicht bestanden.","support.error.unauthorized":"Sie dürfen diesen Bericht nicht senden.","vac.routes_section":"Karten und Etagen","vac.routes_current_map":"Aktuelle Karte","vac.routes_no_map":"keine Telemetrie","vac.routes_status":"Zuordnung","vac.routes_state_ready":"Karte zugeordnet und kalibriert","vac.routes_state_needs_calibration":"Karte zugeordnet, Kalibrierung nötig","vac.routes_state_unmapped":"aktuelle Karte keiner Etage zugeordnet","vac.routes_state_ambiguous":"zwei Karten nicht unterscheidbar — keine Etage gewählt","vac.routes_state_missing_space":"der Raum der Karte wurde gelöscht","vac.routes_state_none":"keine Kartendaten","vac.routes_empty":"Noch keine Karte einer Etage zugeordnet.","vac.route_map_default":"ohne Karten-ID","vac.route_active":"Aktiv","vac.route_space":"Raum","vac.route_space_none":"nicht gewählt","vac.route_status_ready":"bereit","vac.route_status_needs_calibration":"Kalibrierung nötig","vac.route_status_ambiguous":"mehrdeutig","vac.route_status_missing_space":"Raum gelöscht","vac.route_missing_space_group":"Gelöschter Bereich","vac.route_add_current":"Aktuelle Karte hinzufügen","vac.route_delete":"Karte entfernen","vac.route_delete_title":"Karte von der Etage entfernen?","vac.route_delete_body":"Kalibrierung und gespeicherte Pfade dieser Karte werden entfernt. Fortfahren?","vac.route_delete_confirm":"Entfernen","vac.route_space_title":"Karte in einen anderen Raum verschieben?","vac.route_space_body":"Kalibrierung und gespeicherte Pfade dieser Karte werden entfernt. Fortfahren?","vac.route_space_confirm":"Verschieben","vac.route_missing_space_hint":"Eine Karte verweist auf einen gelöschten Raum: neuen wählen oder Karte entfernen. Bis dahin wird der Roboter für diese Karte nicht gezeichnet.","vac.route_default_hint":"Die Quelle meldet keine stabile Karten-ID. Mehrere Etagen lassen sich ohne andere Quelle oder die vom Roboter gewählte Karte nicht unterscheiden.","vac.route_target_hint":"Die Station bleibt unabhängig von der aktuellen Karte im Raum „{space}“.","vac.route_add_source":"Kartenquelle hinzufügen","vac.route_add_source_hint":"Für Integrationen, die jeder Karte eine eigene Kamera geben. Der Abschnitt „Alle Kameras“ oben erweitert diese Liste.","vac.route_source_no_map":"keine Karte gemeldet"},fr:{"gs.hint":"Les couleurs de remplissage s’appliquent à tous les espaces ; chaque couleur possède sa propre opacité. Le mode de remplissage utilisé par un espace se règle dans la boîte de dialogue de cet espace.","gs.show_room_tooltip":"Afficher les informations de la pièce au survol","support.about_group":"À propos de la carte","support.guide_group":"Documentation d’aide","support.guide":"Guide utilisateur","support.form_group":"Envoyer un rapport ou une suggestion","support.contact":"Contact (e-mail/tg/WhatsApp), facultatif.","support.message":"Votre message","support.attach":"Joindre des informations anonymisées de votre plan","support.attach_hint":"Inclut uniquement la géométrie, les réglages autorisés et des données d’exécution limitées. Exclut les noms, identifiants Home Assistant, états en direct, URL, fichiers, message et contact.","support.geometry_warning":"Le paquet ne contient ni noms ni identifiants Home Assistant, mais il contient la géométrie et les dimensions exactes de votre logement.","support.close_busy_title":"Interrompre l’opération en cours ?","support.close_busy_body":"House Plan prépare ou envoie le rapport. Fermer maintenant arrête l’attente du résultat.","support.building":"Préparation des données anonymisées…","support.preview_summary":"Paquet v{version} · {spaces} espaces · {size} Kio","support.prepared":"Instantané préparé il y a {n} min","support.show_data":"Afficher les données","support.download":"Télécharger le JSON","support.refresh":"Actualiser l’instantané","support.privacy":"Lors de l’envoi, votre message, le contact facultatif et, si elle est sélectionnée, la géométrie exacte quittent votre Home Assistant via le relais du projet House Plan et sont visibles par les mainteneurs. Le serveur du projet conserve le rapport jusqu’à 30 jours. L’infrastructure réseau voit l’adresse de votre serveur HA, mais House Plan ne la conserve pas en clair ; les métadonnées de limitation et d’idempotence sont gardées jusqu’à 24 heures.","support.error_title":"Le rapport n’a pas été envoyé","support.manual_recovery":"Vous pouvez conserver le message et la pièce jointe puis continuer manuellement :","support.copy_message":"Copier le message","support.success":"Rapport envoyé : {id}. Conservez ce numéro pour contacter l’assistance.","support.copy_id":"Copier l’ID","support.sending":"Envoi…","support.retry":"Réessayer","support.send":"Envoyer","support.update_required":"Mettez à jour la carte et l’intégration House Plan vers des versions compatibles pour envoyer des rapports.","support.message_copied":"Message copié","support.id_copied":"ID du rapport copié","support.copy_failed":"Impossible d’accéder au presse-papiers. Sélectionnez et copiez le texte manuellement.","support.validation.message_required":"Saisissez un message.","support.validation.message_too_long":"Le message ne doit pas dépasser 10 000 caractères.","support.validation.contact_too_long":"Le contact ne doit pas dépasser 320 caractères.","support.validation.preview_missing":"Attendez l’aperçu de la pièce jointe ou désactivez-la.","support.validation.preview_expired":"L’aperçu de la pièce jointe a expiré. Actualisez l’instantané.","support.error.support_invalid_message":"Vérifiez le message et réessayez.","support.error.support_preview_expired":"L’aperçu de la pièce jointe a expiré ou n’est plus disponible. Actualisez l’instantané.","support.error.support_package_too_large":"Le paquet anonymisé dépasse la limite de 8 Mio.","support.error.support_rate_limited":"Trop de rapports ou d’aperçus ont été demandés. Réessayez plus tard.","support.error.support_unavailable":"Le service d’assistance privé est temporairement indisponible. Le brouillon reste dans cette fenêtre.","support.error.support_rejected":"Le rapport n’a pas passé la validation du service d’assistance.","support.error.unauthorized":"Vous n’êtes pas autorisé à envoyer ce rapport.","vac.routes_section":"Cartes et étages","vac.routes_current_map":"Carte actuelle","vac.routes_no_map":"aucune télémétrie","vac.routes_status":"Routage","vac.routes_state_ready":"carte assignée et calibrée","vac.routes_state_needs_calibration":"carte assignée, calibrage requis","vac.routes_state_unmapped":"carte actuelle non assignée à un étage","vac.routes_state_ambiguous":"deux cartes indiscernables — aucun étage choisi","vac.routes_state_missing_space":"l'espace de la carte a été supprimé","vac.routes_state_none":"aucune donnée de carte","vac.routes_empty":"Aucune carte n'est encore assignée à un étage.","vac.route_map_default":"sans identifiant","vac.route_active":"Active","vac.route_space":"Espace","vac.route_space_none":"non sélectionné","vac.route_status_ready":"prête","vac.route_status_needs_calibration":"calibrage requis","vac.route_status_ambiguous":"ambiguë","vac.route_status_missing_space":"espace supprimé","vac.route_missing_space_group":"Espace supprimé","vac.route_add_current":"Ajouter la carte actuelle","vac.route_delete":"Supprimer la carte","vac.route_delete_title":"Retirer la carte de son étage ?","vac.route_delete_body":"Le calibrage et les trajets enregistrés de cette carte seront supprimés. Continuer ?","vac.route_delete_confirm":"Supprimer","vac.route_space_title":"Déplacer la carte vers un autre espace ?","vac.route_space_body":"Le calibrage et les trajets enregistrés de cette carte seront supprimés. Continuer ?","vac.route_space_confirm":"Déplacer","vac.route_missing_space_hint":"Une carte pointe vers un espace supprimé : choisissez-en un autre ou supprimez la carte. D'ici là, le robot n'est pas dessiné pour cette carte.","vac.route_default_hint":"La source ne fournit pas d'identifiant de carte stable. Plusieurs étages ne peuvent pas être distingués sans une autre source ou la carte sélectionnée du robot.","vac.route_target_hint":"La station reste dans l'espace « {space} » quelle que soit la carte actuelle.","vac.route_add_source":"Ajouter une source de carte","vac.route_add_source_hint":"Pour les intégrations qui donnent à chaque carte sa propre caméra. La section « Toutes les caméras » ci-dessus élargit cette liste.","vac.route_source_no_map":"aucune carte signalée"}};function Do(e,s,i){return t(Po[e]?.[s]??Co[s]??s,i)}function Io(t,e,s,i,o){return{markerId:t,source:i,mapId:o,space:e.length?"":s}}function To(t,e,s){return{...t,space:s.has(e)?e:""}}function zo(t,e=Math.random){const s=new Set(t);for(let t=0;t<64;t+=1){const t="vr_"+Math.floor(16777215*e()).toString(36).padStart(5,"0");if(!s.has(t))return t}return"vr_"+Date.now().toString(36)}function Ro(t,e,s){return t.map(t=>t.id===e?{...t,calibration:s}:t)}const Ao=new WeakMap,Fo=(t,e)=>{const s=(t._serverCfg?.spaces||[]).find(t=>t?.id===e);return String(s?.name||s?.id||e)};function No(t,i,o){const c=t.host,d=a(c.hass,c._config?.language),p=(t,e)=>Do(d,t,e),u=i.marker?.vacuum||{},_=Array.isArray(u.map_routes),m=c._vacSource(i)||"",g=e(i.id,u,i.space,m),f=(c._serverCfg?.spaces||[]).filter(t=>"string"==typeof t?.id&&!!t.id).map(t=>({id:t.id,name:String(t.name||t.id)})),b=new Set(f.map(t=>t.id)),v=n(g,[m],t=>c._vacObservedMapId(i,t)),y=r({routes:g,observed:v,spaceIds:b}),$="ready"===y.kind||"needs_calibration"===y.kind||"missing_space"===y.kind?y.route.id:"",w=m?v[m]:void 0,k=async e=>{let o=_?u.map_routes??null:null;if(!o&&(o=function(t,e,i,o){if(!i)return null;const a=t?.calibration;if(!a||"object"!=typeof a)return null;const n=new Set,r=[];for(const t of Object.keys(a)){const l=s(a[t]);if(!l)continue;const h=o(n);n.add(h),r.push({id:h,source:i,map_id:t,space:e,calibration:l})}return r.length?r:null}(u,i.space,m,t=>zo(t))??[],!m&&Object.keys(u.calibration||{}).length))return!1;const a=e(o);return!!a&&(async e=>{const s=c._serverCfg;if(!s)return!1;const o=JSON.parse(JSON.stringify(s));o.markers=o.markers||[];let a=o.markers.find(t=>t.id===i.id);if(!a){if("device"!==i.bindingKind&&"entity"!==i.bindingKind||!i.bindingRef)return!1;a={id:i.id,binding:`${i.bindingKind}:${i.bindingRef}`,space:i.space||null,area:i.area||null,hidden:!!i.hidden},o.markers.push(a)}a.vacuum={...a.vacuum||{},map_routes:e},delete a.vacuum.calibration;const n=c._adoption.beginOptimistic(s,o);c._adoption.stageLocalConfig(o),c._regSignature="",c._maybeRebuildDevices(),c.requestUpdate(),c._saveConfigDebounced.pending()&&c._saveConfigDebounced.cancel();try{return await t._saveConfigNow(),!0}catch(t){return c._rollbackOptimistic(n),c._regSignature="",c._maybeRebuildDevices(),c.requestUpdate(),c._showToast(c._t("toast.cfg_save_failed",{err:c._errText(t)})),!1}})(a)},x=o.candidates.filter(t=>t.entityId!==m&&!g.some(e=>e.source===t.entityId)),S=async(t,e)=>{if(!e||e===t.space)return;await c._confirmDanger({key:"vacuum_route_space",kind:"warning",title:p("vac.route_space_title"),message:p("vac.route_space_body"),objectName:t.map_id||p("vac.route_map_default"),confirmLabel:p("vac.route_space_confirm"),cancelLabel:c._t("btn.cancel")})&&await k(s=>function(t,e,s,i){return t.map(t=>t.id===e?{...t,id:i,space:s,calibration:null}:t)}(s,t.id,e,zo(new Set(g.map(t=>t.id)))))},M=new Map(f.map((t,e)=>[t.id,e])),C=(t,e)=>t.map_id.localeCompare(e.map_id)||t.source.localeCompare(e.source)||t.id.localeCompare(e.id),P=g.filter(t=>b.has(t.space)).sort((t,e)=>(M.get(t.space)??0)-(M.get(e.space)??0)||C(t,e)),D=g.filter(t=>!b.has(t.space)).sort(C),I=[...P,...D],T=!!m&&void 0!==w&&!g.some(t=>t.source===m&&t.map_id===w);let z=Ao.get(t);const R=z?.source||"",A=z?.mapId||"",F=!!z&&g.some(t=>t.source===R&&t.map_id===A);z&&(z.markerId!==i.id||c._vacObservedMapId(i,z.source)!==z.mapId||F&&!z.saving)&&(Ao.delete(t),z=void 0),z?.space&&!b.has(z.space)&&(z=To(z,"",b),Ao.set(t,z));const N=e=>h`
+globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="2e6f7d70c797ae4e865b10859c77cc3380a432272a975b8f35b51234ae3cfe62";import{s as t,e,n as s,f as i,i as o,l as a,o as n,r,A as l,b as h,D as c,w as d,N as p,a as u,c as _,d as m,g,h as f,j as b,k as v,m as y,p as $,q as w,t as k,u as x,v as S,x as M,y as C,z as P,B as D,C as I,E as T,F as z,G as R,H as A,I as F,J as N,K as E,L as H,M as O,O as L,P as B,Q as W,R as j,S as G,T as q,U,V as K,W as V,X as J,Y,Z as X,_ as Z,$ as Q,a0 as tt,a1 as et,a2 as st,a3 as it,a4 as ot,a5 as at,a6 as nt,a7 as rt,a8 as lt,a9 as ht,aa as ct,ab as dt,ac as pt,ad as ut,ae as _t,af as mt,ag as gt,ah as ft,ai as bt,aj as vt,ak as yt,al as $t,am as wt,an as kt,ao as xt,ap as St,aq as Mt,ar as Ct,as as Pt,at as Dt,au as It,av as Tt,aw as zt,ax as Rt,ay as At,az as Ft,aA as Nt,aB as Et,aC as Ht,aD as Ot,aE as Lt,aF as Bt,aG as Wt,aH as jt,aI as Gt,aJ as qt,aK as Ut,aL as Kt,aM as Vt,aN as Jt,aO as Yt,aP as Xt,aQ as Zt,aR as Qt,aS as te,aT as ee,aU as se,aV as ie,aW as oe,aX as ae,aY as ne,aZ as re,a_ as le,a$ as he,b0 as ce,b1 as de,b2 as pe,b3 as ue,b4 as _e,b5 as me,b6 as ge,b7 as fe,b8 as be,b9 as ve,ba as ye,bb as $e,bc as we,bd as ke,be as xe,bf as Se,bg as Me,bh as Ce,bi as Pe,bj as De,bk as Ie,bl as Te,bm as ze,bn as Re,bo as Ae,bp as Fe,bq as Ne,br as Ee,bs as He,bt as Oe,bu as Le,bv as Be,bw as We,bx as je,by as Ge,bz as qe,bA as Ue,bB as Ke,bC as Ve,bD as Je,bE as Ye,bF as Xe,bG as Ze,bH as Qe,bI as ts,bJ as es,bK as ss,bL as is,bM as os,bN as as,bO as ns,bP as rs,bQ as ls,bR as hs,bS as cs,bT as ds,bU as ps,bV as us,bW as _s,bX as ms,bY as gs,bZ as fs,b_ as bs,b$ as vs,c0 as ys,c1 as $s,c2 as ws,c3 as ks,c4 as xs,c5 as Ss,c6 as Ms,c7 as Cs,c8 as Ps,c9 as Ds,ca as Is,cb as Ts,cc as zs,cd as Rs,ce as As,cf as Fs,cg as Ns,ch as Es,ci as Hs,cj as Os,ck as Ls,cl as Bs,cm as Ws,cn as js,co as Gs,cp as qs,cq as Us,cr as Ks,cs as Vs,ct as Js,cu as Ys,cv as Xs,cw as Zs,cx as Qs,cy as ti,cz as ei,cA as si,cB as ii,cC as oi,cD as ai,cE as ni,cF as ri,cG as li,cH as hi,cI as ci,cJ as di,cK as pi,cL as ui,cM as _i,cN as mi,cO as gi,cP as fi,cQ as bi,cR as vi,cS as yi,cT as $i,cU as wi,cV as ki,cW as xi,cX as Si,cY as Mi,cZ as Ci,c_ as Pi,c$ as Di,d0 as Ii,d1 as Ti,d2 as zi,d3 as Ri,d4 as Ai,d5 as Fi,d6 as Ni,d7 as Ei,d8 as Hi,d9 as Oi,da as Li,db as Bi,dc as Wi,dd as ji,de as Gi,df as qi,dg as Ui,dh as Ki,di as Vi,dj as Ji,dk as Yi,dl as Xi,dm as Zi,dn as Qi,dp as to,dq as eo,dr as so,ds as io,dt as oo,du as ao,dv as no,dw as ro,dx as lo,dy as ho,dz as co}from"./houseplan-card-BMuv6THL.js";import{i as po}from"./guard-8MebpCtO.js";import{F as uo,f as _o,p as mo,c as go,e as fo,r as bo,a as vo,s as yo}from"./backdrop-pick-DJt73xkJ.js";import{t as $o,h as wo,m as ko,T as xo}from"./zigbee-topology-86ml1Wbm.js";import{GENERATED_FURNITURE_ART as So,FURNITURE_ART_FINGERPRINT as Mo}from"./furniture-plan-art.generated-XOCt_Wns.js";var Co={"gs.hint":"Fill colors apply to every space; each color has its own opacity. Which fill mode a space uses is set in that space's dialog.","gs.show_room_tooltip":"Show the room information window on hover","support.about_group":"About the card","support.guide_group":"Documentation","support.guide":"User guide","support.form_group":"Send a report or suggestion","support.contact":"Contact details (email/tg/WhatsApp), optional.","support.message":"Message","support.attach":"Attach anonymized information from your plan","support.attach_hint":"Includes only allowed plan geometry, settings and bounded runtime facts. Excludes names, Home Assistant IDs, live states, URLs, files, and your message/contact.","support.geometry_warning":"The package contains no names or Home Assistant IDs, but it does contain the exact geometry and dimensions of your home.","support.close_busy_title":"Stop the current operation?","support.close_busy_body":"House Plan is preparing or sending the report. Closing now stops waiting for the result.","support.building":"Preparing anonymized data…","support.preview_summary":"Package v{version} · {spaces} spaces · {size} KiB","support.prepared":"Snapshot prepared {n} min ago","support.show_data":"Show data","support.download":"Download JSON","support.refresh":"Refresh snapshot","support.privacy":"When you send, your message, optional contact and, if selected, exact geometry leave your Home Assistant through the House Plan project relay and are visible to maintainers. The project node keeps the report for up to 30 days. Network infrastructure sees your HA server address, but House Plan does not retain it raw; rate-limit and idempotency metadata is kept for up to 24 hours.","support.error_title":"The report was not sent","support.manual_recovery":"You can keep the message and attachment and continue manually:","support.copy_message":"Copy message","support.success":"Report sent: {id}. Save this number when contacting support.","support.copy_id":"Copy ID","support.sending":"Sending…","support.retry":"Retry","support.send":"Send","support.update_required":"Update the House Plan card and integration to compatible versions to send reports.","support.message_copied":"Message copied","support.id_copied":"Report ID copied","support.copy_failed":"Could not access the clipboard. Select and copy the text manually.","support.validation.message_required":"Enter a message.","support.validation.message_too_long":"The message must contain no more than 10,000 characters.","support.validation.contact_too_long":"Contact details must contain no more than 320 characters.","support.validation.preview_missing":"Wait for the attachment preview or turn the attachment off.","support.validation.preview_expired":"The attachment preview expired. Refresh the snapshot.","support.error.support_invalid_message":"Check the message and try again.","support.error.support_preview_expired":"The attachment preview expired or is no longer available. Refresh the snapshot.","support.error.support_package_too_large":"The anonymized package exceeds the 8 MiB limit.","support.error.support_rate_limited":"Too many reports or previews were requested. Try again later.","support.error.support_unavailable":"The private support service is temporarily unavailable. Your draft remains here.","support.error.support_rejected":"The report did not pass the support service validation.","support.error.unauthorized":"You do not have permission to send this report.","vac.routes_section":"Maps and floors","vac.routes_current_map":"Current map","vac.routes_no_map":"no telemetry","vac.routes_status":"Routing","vac.routes_state_ready":"map assigned and calibrated","vac.routes_state_needs_calibration":"map assigned, calibration needed","vac.routes_state_unmapped":"current map is not assigned to a floor","vac.routes_state_ambiguous":"two maps are indistinguishable — no floor is chosen","vac.routes_state_missing_space":"the map's space was deleted","vac.routes_state_none":"no map data","vac.routes_empty":"No map is assigned to a floor yet.","vac.route_map_default":"no map id","vac.route_active":"Active","vac.route_space":"Space","vac.route_space_none":"not selected","vac.route_status_ready":"ready","vac.route_status_needs_calibration":"needs calibration","vac.route_status_ambiguous":"ambiguous","vac.route_status_missing_space":"space deleted","vac.route_missing_space_group":"Deleted space","vac.route_add_current":"Add current map","vac.route_delete":"Remove map","vac.route_delete_title":"Remove the map from its floor?","vac.route_delete_body":"Calibration and saved paths for this map will be removed. Continue?","vac.route_delete_confirm":"Remove","vac.route_space_title":"Move the map to another space?","vac.route_space_body":"Calibration and saved paths for this map will be removed. Continue?","vac.route_space_confirm":"Move","vac.route_missing_space_hint":"One of the maps points at a deleted space: pick a new one or remove the map. Until then the robot is not drawn for that map.","vac.route_default_hint":"The source reports no stable map id. Several floors cannot be told apart without another source or the robot's own selected map.","vac.route_target_hint":"The dock stays in the “{space}” space regardless of the current map.","vac.route_add_source":"Add a map source","vac.route_add_source_hint":"For integrations that give each map its own camera. The “All cameras” section above widens this list.","vac.route_source_no_map":"no map reported"};const Po={en:Co,ru:{"gs.hint":"Цвета заливок действуют на все пространства; у каждого цвета своя прозрачность. Какой режим заливки использует пространство — задаётся в его диалоге.","gs.show_room_tooltip":"Показывать окно с информацией при наведении на комнату","support.about_group":"О карточке","support.guide_group":"Документация","support.guide":"Руководство пользователя","support.form_group":"Отправить репорт или предложение","support.contact":"Контакт для связи (email/tg/WhatsApp), необязательно.","support.message":"Сообщение","support.attach":"Прикрепить обезличенную информацию из вашего плана","support.attach_hint":"В пакет входят только разрешённые геометрия, настройки и ограниченные сведения о среде. Не входят имена, HA id, текущие состояния, URL, файлы, сообщение и контакт.","support.geometry_warning":"Пакет не содержит имён и HA id, но содержит точную геометрию и размеры дома.","support.close_busy_title":"Прервать текущую операцию?","support.close_busy_body":"House Plan подготавливает или отправляет репорт. При закрытии ожидание результата прекратится.","support.building":"Подготавливаем обезличенные данные…","support.preview_summary":"Пакет v{version} · пространств: {spaces} · {size} КиБ","support.prepared":"Снимок подготовлен {n} мин назад","support.show_data":"Показать данные","support.download":"Скачать JSON","support.refresh":"Обновить снимок","support.privacy":"При отправке сообщение, необязательный контакт и, если выбран пакет, точная геометрия покидают ваш Home Assistant через relay проекта House Plan и доступны мейнтейнерам. Узел проекта хранит репорт до 30 дней. Сетевая инфраструктура видит адрес сервера HA, но House Plan не сохраняет его в исходном виде; метаданные лимитов и идемпотентности хранятся до 24 часов.","support.error_title":"Репорт не отправлен","support.manual_recovery":"Сообщение и вложение можно сохранить и продолжить вручную:","support.copy_message":"Копировать сообщение","support.success":"Репорт отправлен: {id}. Сохраните номер для связи с поддержкой.","support.copy_id":"Копировать ID","support.sending":"Отправляем…","support.retry":"Повторить","support.send":"Отправить","support.update_required":"Обновите карточку и интеграцию House Plan до совместимых версий, чтобы отправлять репорты.","support.message_copied":"Сообщение скопировано","support.id_copied":"ID репорта скопирован","support.copy_failed":"Не удалось получить доступ к буферу обмена. Выделите и скопируйте текст вручную.","support.validation.message_required":"Введите сообщение.","support.validation.message_too_long":"Сообщение должно содержать не более 10 000 символов.","support.validation.contact_too_long":"Контакт должен содержать не более 320 символов.","support.validation.preview_missing":"Дождитесь предпросмотра вложения или отключите его.","support.validation.preview_expired":"Предпросмотр вложения истёк. Обновите снимок.","support.error.support_invalid_message":"Проверьте сообщение и повторите попытку.","support.error.support_preview_expired":"Предпросмотр вложения истёк или больше недоступен. Обновите снимок.","support.error.support_package_too_large":"Обезличенный пакет превышает лимит 8 МиБ.","support.error.support_rate_limited":"Запрошено слишком много репортов или предпросмотров. Повторите позже.","support.error.support_unavailable":"Закрытая служба поддержки временно недоступна. Черновик сохранён в этом окне.","support.error.support_rejected":"Репорт не прошёл проверку службы поддержки.","support.error.unauthorized":"У вас нет прав на отправку этого репорта.","vac.routes_section":"Карты и этажи","vac.routes_current_map":"Текущая карта","vac.routes_no_map":"источник молчит","vac.routes_status":"Маршрутизация","vac.routes_state_ready":"карта сопоставлена и откалибрована","vac.routes_state_needs_calibration":"карта сопоставлена, нужна калибровка","vac.routes_state_unmapped":"текущая карта не сопоставлена этажу","vac.routes_state_ambiguous":"две карты неразличимы — этаж не выбирается","vac.routes_state_missing_space":"пространство карты удалено","vac.routes_state_none":"нет данных о карте","vac.routes_empty":"Ни одна карта ещё не сопоставлена этажу.","vac.route_map_default":"без идентификатора","vac.route_active":"Текущая","vac.route_space":"Пространство","vac.route_space_none":"не выбрано","vac.route_status_ready":"готова","vac.route_status_needs_calibration":"нужна калибровка","vac.route_status_ambiguous":"неоднозначна","vac.route_status_missing_space":"пространство удалено","vac.route_missing_space_group":"Пространство удалено","vac.route_add_current":"Добавить текущую карту","vac.route_delete":"Удалить карту","vac.route_delete_title":"Удалить карту с этажа?","vac.route_delete_body":"Калибровка и сохранённые пути этой карты будут удалены. Продолжить?","vac.route_delete_confirm":"Удалить","vac.route_space_title":"Перенести карту в другое пространство?","vac.route_space_body":"Калибровка и сохранённые пути этой карты будут удалены. Продолжить?","vac.route_space_confirm":"Перенести","vac.route_missing_space_hint":"Одна из карт ссылается на удалённое пространство: выберите новое или удалите карту. Пока ссылка не исправлена, робот на этой карте не рисуется.","vac.route_default_hint":"Источник не сообщает стабильный идентификатор карты. Несколько этажей нельзя различить без другого источника или собственной карты робота.","vac.route_target_hint":"Док остаётся в пространстве «{space}» независимо от текущей карты.","vac.route_add_source":"Добавить источник карты","vac.route_add_source_hint":"Для интеграций, где у каждой карты своя камера. Список расширяется разделом «Все камеры» выше.","vac.route_source_no_map":"карта не читается"},de:{"gs.hint":"Füllfarben gelten für jeden Bereich; jede Farbe hat ihre eigene Deckkraft. Der Füllmodus wird in den Einstellungen des jeweiligen Bereichs festgelegt.","gs.show_room_tooltip":"Rauminformationen beim Darüberfahren anzeigen","support.about_group":"Über die Karte","support.guide_group":"Dokumentation","support.guide":"Benutzerhandbuch","support.form_group":"Bericht oder Vorschlag senden","support.contact":"Kontakt (E-Mail/tg/WhatsApp), optional.","support.message":"Nachricht","support.attach":"Anonymisierte Informationen aus dem Plan anhängen","support.attach_hint":"Enthält nur erlaubte Plangeometrie, Einstellungen und begrenzte Laufzeitdaten. Namen, Home-Assistant-IDs, Live-Zustände, URLs, Dateien, Nachricht und Kontakt werden ausgeschlossen.","support.geometry_warning":"Das Paket enthält keine Namen oder Home-Assistant-IDs, aber die exakte Geometrie und die Maße Ihres Hauses.","support.close_busy_title":"Aktuellen Vorgang abbrechen?","support.close_busy_body":"House Plan bereitet den Bericht vor oder sendet ihn. Beim Schließen wird nicht weiter auf das Ergebnis gewartet.","support.building":"Anonymisierte Daten werden vorbereitet…","support.preview_summary":"Paket v{version} · {spaces} Bereiche · {size} KiB","support.prepared":"Schnappschuss vor {n} Min. erstellt","support.show_data":"Daten anzeigen","support.download":"JSON herunterladen","support.refresh":"Schnappschuss aktualisieren","support.privacy":"Beim Senden verlassen Ihre Nachricht, der optionale Kontakt und, falls ausgewählt, die exakte Geometrie Ihren Home Assistant über das House-Plan-Projektrelay und sind für die Maintainer sichtbar. Der Projektserver speichert den Bericht bis zu 30 Tage. Die Netzwerkinfrastruktur sieht die Adresse Ihres HA-Servers, House Plan speichert sie jedoch nicht im Rohformat; Limit- und Idempotenzdaten bleiben bis zu 24 Stunden erhalten.","support.error_title":"Der Bericht wurde nicht gesendet","support.manual_recovery":"Nachricht und Anhang können gespeichert und manuell weitergegeben werden:","support.copy_message":"Nachricht kopieren","support.success":"Bericht gesendet: {id}. Bewahren Sie diese Nummer für den Support auf.","support.copy_id":"ID kopieren","support.sending":"Wird gesendet…","support.retry":"Erneut versuchen","support.send":"Senden","support.update_required":"Aktualisieren Sie House-Plan-Karte und Integration auf kompatible Versionen, um Berichte zu senden.","support.message_copied":"Nachricht kopiert","support.id_copied":"Berichts-ID kopiert","support.copy_failed":"Kein Zugriff auf die Zwischenablage. Markieren und kopieren Sie den Text manuell.","support.validation.message_required":"Geben Sie eine Nachricht ein.","support.validation.message_too_long":"Die Nachricht darf höchstens 10.000 Zeichen enthalten.","support.validation.contact_too_long":"Der Kontakt darf höchstens 320 Zeichen enthalten.","support.validation.preview_missing":"Warten Sie auf die Vorschau oder deaktivieren Sie den Anhang.","support.validation.preview_expired":"Die Anhangsvorschau ist abgelaufen. Aktualisieren Sie den Schnappschuss.","support.error.support_invalid_message":"Prüfen Sie die Nachricht und versuchen Sie es erneut.","support.error.support_preview_expired":"Die Anhangsvorschau ist abgelaufen oder nicht mehr verfügbar. Aktualisieren Sie den Schnappschuss.","support.error.support_package_too_large":"Das anonymisierte Paket überschreitet das Limit von 8 MiB.","support.error.support_rate_limited":"Zu viele Berichte oder Vorschauen wurden angefordert. Versuchen Sie es später erneut.","support.error.support_unavailable":"Der private Supportdienst ist vorübergehend nicht verfügbar. Der Entwurf bleibt in diesem Fenster erhalten.","support.error.support_rejected":"Der Bericht hat die Prüfung des Supportdienstes nicht bestanden.","support.error.unauthorized":"Sie dürfen diesen Bericht nicht senden.","vac.routes_section":"Karten und Etagen","vac.routes_current_map":"Aktuelle Karte","vac.routes_no_map":"keine Telemetrie","vac.routes_status":"Zuordnung","vac.routes_state_ready":"Karte zugeordnet und kalibriert","vac.routes_state_needs_calibration":"Karte zugeordnet, Kalibrierung nötig","vac.routes_state_unmapped":"aktuelle Karte keiner Etage zugeordnet","vac.routes_state_ambiguous":"zwei Karten nicht unterscheidbar — keine Etage gewählt","vac.routes_state_missing_space":"der Raum der Karte wurde gelöscht","vac.routes_state_none":"keine Kartendaten","vac.routes_empty":"Noch keine Karte einer Etage zugeordnet.","vac.route_map_default":"ohne Karten-ID","vac.route_active":"Aktiv","vac.route_space":"Raum","vac.route_space_none":"nicht gewählt","vac.route_status_ready":"bereit","vac.route_status_needs_calibration":"Kalibrierung nötig","vac.route_status_ambiguous":"mehrdeutig","vac.route_status_missing_space":"Raum gelöscht","vac.route_missing_space_group":"Gelöschter Bereich","vac.route_add_current":"Aktuelle Karte hinzufügen","vac.route_delete":"Karte entfernen","vac.route_delete_title":"Karte von der Etage entfernen?","vac.route_delete_body":"Kalibrierung und gespeicherte Pfade dieser Karte werden entfernt. Fortfahren?","vac.route_delete_confirm":"Entfernen","vac.route_space_title":"Karte in einen anderen Raum verschieben?","vac.route_space_body":"Kalibrierung und gespeicherte Pfade dieser Karte werden entfernt. Fortfahren?","vac.route_space_confirm":"Verschieben","vac.route_missing_space_hint":"Eine Karte verweist auf einen gelöschten Raum: neuen wählen oder Karte entfernen. Bis dahin wird der Roboter für diese Karte nicht gezeichnet.","vac.route_default_hint":"Die Quelle meldet keine stabile Karten-ID. Mehrere Etagen lassen sich ohne andere Quelle oder die vom Roboter gewählte Karte nicht unterscheiden.","vac.route_target_hint":"Die Station bleibt unabhängig von der aktuellen Karte im Raum „{space}“.","vac.route_add_source":"Kartenquelle hinzufügen","vac.route_add_source_hint":"Für Integrationen, die jeder Karte eine eigene Kamera geben. Der Abschnitt „Alle Kameras“ oben erweitert diese Liste.","vac.route_source_no_map":"keine Karte gemeldet"},fr:{"gs.hint":"Les couleurs de remplissage s’appliquent à tous les espaces ; chaque couleur possède sa propre opacité. Le mode de remplissage utilisé par un espace se règle dans la boîte de dialogue de cet espace.","gs.show_room_tooltip":"Afficher les informations de la pièce au survol","support.about_group":"À propos de la carte","support.guide_group":"Documentation d’aide","support.guide":"Guide utilisateur","support.form_group":"Envoyer un rapport ou une suggestion","support.contact":"Contact (e-mail/tg/WhatsApp), facultatif.","support.message":"Votre message","support.attach":"Joindre des informations anonymisées de votre plan","support.attach_hint":"Inclut uniquement la géométrie, les réglages autorisés et des données d’exécution limitées. Exclut les noms, identifiants Home Assistant, états en direct, URL, fichiers, message et contact.","support.geometry_warning":"Le paquet ne contient ni noms ni identifiants Home Assistant, mais il contient la géométrie et les dimensions exactes de votre logement.","support.close_busy_title":"Interrompre l’opération en cours ?","support.close_busy_body":"House Plan prépare ou envoie le rapport. Fermer maintenant arrête l’attente du résultat.","support.building":"Préparation des données anonymisées…","support.preview_summary":"Paquet v{version} · {spaces} espaces · {size} Kio","support.prepared":"Instantané préparé il y a {n} min","support.show_data":"Afficher les données","support.download":"Télécharger le JSON","support.refresh":"Actualiser l’instantané","support.privacy":"Lors de l’envoi, votre message, le contact facultatif et, si elle est sélectionnée, la géométrie exacte quittent votre Home Assistant via le relais du projet House Plan et sont visibles par les mainteneurs. Le serveur du projet conserve le rapport jusqu’à 30 jours. L’infrastructure réseau voit l’adresse de votre serveur HA, mais House Plan ne la conserve pas en clair ; les métadonnées de limitation et d’idempotence sont gardées jusqu’à 24 heures.","support.error_title":"Le rapport n’a pas été envoyé","support.manual_recovery":"Vous pouvez conserver le message et la pièce jointe puis continuer manuellement :","support.copy_message":"Copier le message","support.success":"Rapport envoyé : {id}. Conservez ce numéro pour contacter l’assistance.","support.copy_id":"Copier l’ID","support.sending":"Envoi…","support.retry":"Réessayer","support.send":"Envoyer","support.update_required":"Mettez à jour la carte et l’intégration House Plan vers des versions compatibles pour envoyer des rapports.","support.message_copied":"Message copié","support.id_copied":"ID du rapport copié","support.copy_failed":"Impossible d’accéder au presse-papiers. Sélectionnez et copiez le texte manuellement.","support.validation.message_required":"Saisissez un message.","support.validation.message_too_long":"Le message ne doit pas dépasser 10 000 caractères.","support.validation.contact_too_long":"Le contact ne doit pas dépasser 320 caractères.","support.validation.preview_missing":"Attendez l’aperçu de la pièce jointe ou désactivez-la.","support.validation.preview_expired":"L’aperçu de la pièce jointe a expiré. Actualisez l’instantané.","support.error.support_invalid_message":"Vérifiez le message et réessayez.","support.error.support_preview_expired":"L’aperçu de la pièce jointe a expiré ou n’est plus disponible. Actualisez l’instantané.","support.error.support_package_too_large":"Le paquet anonymisé dépasse la limite de 8 Mio.","support.error.support_rate_limited":"Trop de rapports ou d’aperçus ont été demandés. Réessayez plus tard.","support.error.support_unavailable":"Le service d’assistance privé est temporairement indisponible. Le brouillon reste dans cette fenêtre.","support.error.support_rejected":"Le rapport n’a pas passé la validation du service d’assistance.","support.error.unauthorized":"Vous n’êtes pas autorisé à envoyer ce rapport.","vac.routes_section":"Cartes et étages","vac.routes_current_map":"Carte actuelle","vac.routes_no_map":"aucune télémétrie","vac.routes_status":"Routage","vac.routes_state_ready":"carte assignée et calibrée","vac.routes_state_needs_calibration":"carte assignée, calibrage requis","vac.routes_state_unmapped":"carte actuelle non assignée à un étage","vac.routes_state_ambiguous":"deux cartes indiscernables — aucun étage choisi","vac.routes_state_missing_space":"l'espace de la carte a été supprimé","vac.routes_state_none":"aucune donnée de carte","vac.routes_empty":"Aucune carte n'est encore assignée à un étage.","vac.route_map_default":"sans identifiant","vac.route_active":"Active","vac.route_space":"Espace","vac.route_space_none":"non sélectionné","vac.route_status_ready":"prête","vac.route_status_needs_calibration":"calibrage requis","vac.route_status_ambiguous":"ambiguë","vac.route_status_missing_space":"espace supprimé","vac.route_missing_space_group":"Espace supprimé","vac.route_add_current":"Ajouter la carte actuelle","vac.route_delete":"Supprimer la carte","vac.route_delete_title":"Retirer la carte de son étage ?","vac.route_delete_body":"Le calibrage et les trajets enregistrés de cette carte seront supprimés. Continuer ?","vac.route_delete_confirm":"Supprimer","vac.route_space_title":"Déplacer la carte vers un autre espace ?","vac.route_space_body":"Le calibrage et les trajets enregistrés de cette carte seront supprimés. Continuer ?","vac.route_space_confirm":"Déplacer","vac.route_missing_space_hint":"Une carte pointe vers un espace supprimé : choisissez-en un autre ou supprimez la carte. D'ici là, le robot n'est pas dessiné pour cette carte.","vac.route_default_hint":"La source ne fournit pas d'identifiant de carte stable. Plusieurs étages ne peuvent pas être distingués sans une autre source ou la carte sélectionnée du robot.","vac.route_target_hint":"La station reste dans l'espace « {space} » quelle que soit la carte actuelle.","vac.route_add_source":"Ajouter une source de carte","vac.route_add_source_hint":"Pour les intégrations qui donnent à chaque carte sa propre caméra. La section « Toutes les caméras » ci-dessus élargit cette liste.","vac.route_source_no_map":"aucune carte signalée"}};function Do(e,s,i){return t(Po[e]?.[s]??Co[s]??s,i)}function Io(t,e,s,i,o){return{markerId:t,source:i,mapId:o,space:e.length?"":s}}function To(t,e,s){return{...t,space:s.has(e)?e:""}}function zo(t,e=Math.random){const s=new Set(t);for(let t=0;t<64;t+=1){const t="vr_"+Math.floor(16777215*e()).toString(36).padStart(5,"0");if(!s.has(t))return t}return"vr_"+Date.now().toString(36)}function Ro(t,e,s){return t.map(t=>t.id===e?{...t,calibration:s}:t)}const Ao=new WeakMap,Fo=(t,e)=>{const s=(t._serverCfg?.spaces||[]).find(t=>t?.id===e);return String(s?.name||s?.id||e)};function No(t,i,o){const c=t.host,d=a(c.hass,c._config?.language),p=(t,e)=>Do(d,t,e),u=i.marker?.vacuum||{},_=Array.isArray(u.map_routes),m=c._vacSource(i)||"",g=e(i.id,u,i.space,m),f=(c._serverCfg?.spaces||[]).filter(t=>"string"==typeof t?.id&&!!t.id).map(t=>({id:t.id,name:String(t.name||t.id)})),b=new Set(f.map(t=>t.id)),v=n(g,[m],t=>c._vacObservedMapId(i,t)),y=r({routes:g,observed:v,spaceIds:b}),$="ready"===y.kind||"needs_calibration"===y.kind||"missing_space"===y.kind?y.route.id:"",w=m?v[m]:void 0,k=async e=>{let o=_?u.map_routes??null:null;if(!o&&(o=function(t,e,i,o){if(!i)return null;const a=t?.calibration;if(!a||"object"!=typeof a)return null;const n=new Set,r=[];for(const t of Object.keys(a)){const l=s(a[t]);if(!l)continue;const h=o(n);n.add(h),r.push({id:h,source:i,map_id:t,space:e,calibration:l})}return r.length?r:null}(u,i.space,m,t=>zo(t))??[],!m&&Object.keys(u.calibration||{}).length))return!1;const a=e(o);return!!a&&(async e=>{const s=c._serverCfg;if(!s)return!1;const o=JSON.parse(JSON.stringify(s));o.markers=o.markers||[];let a=o.markers.find(t=>t.id===i.id);if(!a){if("device"!==i.bindingKind&&"entity"!==i.bindingKind||!i.bindingRef)return!1;a={id:i.id,binding:`${i.bindingKind}:${i.bindingRef}`,space:i.space||null,area:i.area||null,hidden:!!i.hidden},o.markers.push(a)}a.vacuum={...a.vacuum||{},map_routes:e},delete a.vacuum.calibration;const n=c._adoption.beginOptimistic(s,o);c._adoption.stageLocalConfig(o),c._regSignature="",c._maybeRebuildDevices(),c.requestUpdate(),c._saveConfigDebounced.pending()&&c._saveConfigDebounced.cancel();try{return await t._saveConfigNow(),!0}catch(t){return c._rollbackOptimistic(n),c._regSignature="",c._maybeRebuildDevices(),c.requestUpdate(),c._showToast(c._t("toast.cfg_save_failed",{err:c._errText(t)})),!1}})(a)},x=o.candidates.filter(t=>t.entityId!==m&&!g.some(e=>e.source===t.entityId)),S=async(t,e)=>{if(!e||e===t.space)return;await c._confirmDanger({key:"vacuum_route_space",kind:"warning",title:p("vac.route_space_title"),message:p("vac.route_space_body"),objectName:t.map_id||p("vac.route_map_default"),confirmLabel:p("vac.route_space_confirm"),cancelLabel:c._t("btn.cancel")})&&await k(s=>function(t,e,s,i){return t.map(t=>t.id===e?{...t,id:i,space:s,calibration:null}:t)}(s,t.id,e,zo(new Set(g.map(t=>t.id)))))},M=new Map(f.map((t,e)=>[t.id,e])),C=(t,e)=>t.map_id.localeCompare(e.map_id)||t.source.localeCompare(e.source)||t.id.localeCompare(e.id),P=g.filter(t=>b.has(t.space)).sort((t,e)=>(M.get(t.space)??0)-(M.get(e.space)??0)||C(t,e)),D=g.filter(t=>!b.has(t.space)).sort(C),I=[...P,...D],T=!!m&&void 0!==w&&!g.some(t=>t.source===m&&t.map_id===w);let z=Ao.get(t);const R=z?.source||"",A=z?.mapId||"",F=!!z&&g.some(t=>t.source===R&&t.map_id===A);z&&(z.markerId!==i.id||c._vacObservedMapId(i,z.source)!==z.mapId||F&&!z.saving)&&(Ao.delete(t),z=void 0),z?.space&&!b.has(z.space)&&(z=To(z,"",b),Ao.set(t,z));const N=e=>h`
- `}}const Sc=(t,e)=>t[0]*e[1]-t[1]*e[0],Mc=(t,e)=>t[0]*e[0]+t[1]*e[1],Cc=(t,e)=>[t[0]-e[0],t[1]-e[1]],Pc=(t,e,s)=>[t[0]+e[0]*s,t[1]+e[1]*s];function Dc(t,e,s){return Math.abs(Sc(t,e))<=s}function Ic(t,e,s){return Math.abs(Sc(Cc(t,e),s))}function Tc(t,e,s,i,o){const a=e[0]-t[0],n=e[1]-t[1],r=Math.hypot(a,n);if(!(r>o&&s>0))return[];const l=[a/r,n/r];return function(t,e,s){const i=e.map(([e,s])=>[Math.max(0,Math.min(e,s)),Math.min(t,Math.max(e,s))]).filter(([t,e])=>e>t+s).sort((t,e)=>t[0]-e[0]||t[1]-e[1]),o=[];for(const t of i){const e=o[o.length-1];!e||t[0]>e[1]+s?o.push([...t]):e[1]=Math.max(e[1],t[1])}const a=[];let n=0;for(const[t,e]of o)t>n+s&&a.push([n,t]),n=Math.max(n,e);return t>n+s&&a.push([n,t]),a}(r,i.flatMap(e=>{const i=e.b[0]-e.a[0],a=e.b[1]-e.a[1],n=Math.hypot(i,a);if(!(n>o&&Dc(l,[i/n,a/n],1e-6)))return[];if(Ic(e.a,t,l)>1.1*Math.max(s,o)||Ic(e.b,t,l)>1.1*Math.max(s,o))return[];return[[Mc(Cc(e.a,t),l),Mc(Cc(e.b,t),l)]]}),o).flatMap(([e,i])=>{const o=Xt({a:Pc(t,l,e),b:Pc(t,l,i),halfDepth:s});return o?[o]:[]})}function zc(t){const e=t.coordScale??1,s=Math.max(t.epsilon??2e-4*t.gridPitch,1e-9),i=[];for(const s of t.rooms||[]){if(!s?.id)continue;const o=Z(t.rooms,s.id,t.walls,t.openCuts,t.pitch,t.cellCm,t.gridPitch,e);if(!o||o.poly.length<3)continue;const a=Jt(o.poly,o.offsets);!a||a.length<3||i.push({roomId:s.id,profile:o,inner:a})}i.sort((t,e)=>t.roomId.localeCompare(e.roomId));const o=(t.roomOpenings||[]).map(t=>{const e=t.angle*Math.PI/180,s=[Math.cos(e),Math.sin(e)],i=Math.max(0,t.length)/2;return{a:Pc([t.x,t.y],s,-i),b:Pc([t.x,t.y],s,i)}}),a=[];for(const i of Yt(t.rooms,t.walls,t.openCuts,t.pitch,t.cellCm,t.gridPitch,e))for(const t of Tc(i.a,i.b,i.depthUnits/2,o,s))a.push({body:t});const n=new Map;for(const e of t.partitionCuts||[]){const t=n.get(e.hostId)||[];t.push(e),n.set(e.hostId,t)}for(const e of t.partitions||[]){const i=b(e.cm,t.cellCm,t.gridPitch)/2;for(const t of Tc(e.a,e.b,i,n.get(e.id)||[],s))a.push({body:t,partitionId:e.id})}return{rooms:i,boundaries:a,epsilon:s}}function Rc(t,e,s,i){const o=t.profile.offsets[e];if(!(o>0))return null;const a=function(t,e){const s=t[e],i=t[(e+1)%t.length],o=i[0]-s[0],a=i[1]-s[1],n=Math.hypot(o,a)||1;return function(t){let e=0;for(let s=0;s=0?[-a/n,o/n]:[a/n,-o/n]}(t.profile.poly,e),n=Pc(s.center,a,o),r=[];for(let e=0;ei&&Dc(s.axis,[l[0]/h,l[1]/h],1e-6)))continue;if(Ic(o,n,s.axis)>i||Ic(a,n,s.axis)>i)continue;const c=Mc(Cc(o,n),s.axis),d=Mc(Cc(a,n),s.axis);r.push([Math.min(c,d),Math.max(c,d)])}const l=function(t,e){t.sort((t,e)=>t[0]-e[0]||t[1]-e[1]);const s=[];for(const i of t){const t=s[s.length-1];!t||i[0]>t[1]+e?s.push([...i]):t[1]=Math.max(t[1],i[1])}return s}(r,i).find(([t,e])=>t<=i&&e>=-i);if(!l)return null;const[h,c]=l,d=Pc(n,s.axis,-s.half),p=Pc(n,s.axis,s.half),u=Math.max(0,-s.half-h),_=Math.max(0,c-s.half),m=u>0?Pc(n,s.axis,h):d,g=_>0?Pc(n,s.axis,c):p,f=Mc(a,s.normal)>=0?1:-1,b=(e,i,o)=>({from:e,to:i,label:[(e[0]+i[0])/2,(e[1]+i[1])/2],axis:s.axis,labelNormal:a,distance:o,roomId:t.roomId,roomSide:f,source:"room-face"});return{left:b(d,m,u),right:b(p,g,_)}}function Ac(t){const e=Pc(t.center,t.axis,-t.half),s=Pc(t.center,t.axis,t.half),i=Pc(t.center,t.axis,Math.min(-t.half,t.targetLo)),o=Pc(t.center,t.axis,Math.max(t.half,t.targetHi)),a=(e,s)=>({from:e,to:s,label:[(e[0]+s[0])/2,(e[1]+s[1])/2],axis:t.axis,labelNormal:t.normal,distance:Math.hypot(s[0]-e[0],s[1]-e[1]),source:"host-end"});return[a(e,i),a(s,o)]}function Fc(t,e,s,i){const o=Cc(s,e),a=Mc(o,o);if(!(a>i*i))return Math.hypot(...Cc(t,e))<=i;const n=Mc(Cc(t,e),o)/a;if(n<-i||n>1+i)return!1;const r=Pc(e,o,Math.max(0,Math.min(1,n)));return Math.hypot(...Cc(t,r))<=i}function Nc(t,e,s){let i=!1;for(let o=0,a=e.length-1;ot[1]!=h>t[1]&&t[0]<(l-n)*(t[1]-r)/(h-r)+n&&(i=!i)}return i}function Ec(t,e,s,i,o,a){const n=Cc(i,s),r=Sc(e,n);if(Math.abs(r)<=a)return null;const l=Cc(s,t),h=Sc(l,n)/r,c=Sc(l,e)/r;return h<-a||h>o+a||c<-a||c>1+a?null:Math.max(0,Math.min(o,h))}function Hc(t,e,s){const i=Ac(s),o="partition"===t.host?.kind?t.host.id:void 0;return[{base:i[0],direction:[-s.axis[0],-s.axis[1]]},{base:i[1],direction:s.axis}].map(({base:t,direction:s})=>{const i=t.distance,a=function(t,e,s,i,o,a){let n=null;for(const r of i)if(!o||r.partitionId!==o){if(Nc(t,r.body,a))return 0;for(let i=0;iMc(Cc(t,o),s));return{center:o,axis:s,normal:i,half:Math.max(0,t.renderedLength)/2,targetLo:Math.min(...a),targetHi:Math.max(...a)}}(t),i=e.rooms.flatMap(t=>{const i=function(t,e,s){const{profile:i}=t;let o=null;for(let t=0;t0))continue;const a=i.poly[t],n=i.poly[(t+1)%i.poly.length],r=Cc(n,a),l=Math.hypot(r[0],r[1]);if(!(l>s&&Dc(e.axis,[r[0]/l,r[1]/l],1e-6)))continue;if(Ic(a,e.center,e.axis)>s||Ic(n,e.center,e.axis)>s)continue;const h=Mc(Cc(a,e.center),e.axis),c=Mc(Cc(n,e.center),e.axis),d=Math.min(h,c),p=Math.max(h,c);if(d>-e.half+s||p0?d:p<0?-p:0);(!o||u2)return Ac(s);if(i.length){const t=i.map(({room:t,edge:i})=>Rc(t,i,s,e.epsilon));if(t.some(t=>!t))return Ac(s);const o=t;return[...o.map(t=>t.left),...o.map(t=>t.right)]}return Hc(t,e,s)}function Lc(t,e,s,i,o){const a=(n=t,JSON.parse(JSON.stringify(n)));var n;const r=[...new Set(i.filter(t=>"string"==typeof t&&t))],l={partitionsMerged:0,partitionsReconciled:0,openingsRehosted:0,changed:!1};if(!r.length||!Array.isArray(a?.partitions))return{space:a,report:l};const h=JSON.stringify(a),c=sl(a.partitions,{pitch:o.pitch,seedIds:r,geometry:ol(a)});c.merged&&(a.partitions=c.partitions);const d=Array.isArray(a.openings)?a.openings:[];c.merged&&il(d,c.partitions,c.openingMoves,{coordScale:o.coordScale,cellCm:o.cellCm,gridPitch:o.gridPitch});const p=function(t,e,s){const i=new Set(t.map(t=>t.id)),o=new Map(s.map(t=>[t.fromId,t.toId]));return[...new Set(e.map(t=>o.get(t)||t).filter(t=>i.has(t)))].sort((t,e)=>t.localeCompare(e))}(c.partitions,r,c.openingMoves),u=bl(a,{rooms:e.rooms,wall_columns:e.wall_columns,partitions:c.partitions.map(t=>({...t,a:[t.a[0]*o.coordScale,t.a[1]*o.coordScale],b:[t.b[0]*o.coordScale,t.b[1]*o.coordScale]}))},a.walls,s,{...o,partitionIds:p});return u.partitionsReconciled&&(u.walls.length?a.walls=u.walls:delete a.walls,u.partitions.length?a.partitions=u.partitions:delete a.partitions,u.openings.length?a.openings=u.openings:delete a.openings),{space:a,report:{partitionsMerged:c.merged,partitionsReconciled:u.partitionsReconciled,openingsRehosted:u.openingsRehosted,changed:JSON.stringify(a)!==h}}}const Bc=t=>void 0===t?t:JSON.parse(JSON.stringify(t)),Wc=(t,e)=>!!t&&"object"==typeof t&&Object.prototype.hasOwnProperty.call(t,e);function jc(t,e){const s=e?new Set(e):null;return(t||[]).filter(t=>"string"==typeof t?.id&&(!s||s.has(t.id))).map(t=>{const e=t.vacuum;return{markerId:t.id,roomIdPresent:Wc(t,"room_id"),...Wc(t,"room_id")?{roomId:Bc(t.room_id)}:{},vacuumPresent:Wc(t,"vacuum"),segmentMapPresent:Wc(e,"segment_map"),...Wc(e,"segment_map")?{segmentMap:Bc(e?.segment_map)}:{}}}).sort((t,e)=>t.markerId.localeCompare(e.markerId))}function Gc(t,e){const s=Bc([...t||[]]),i=new Set;for(const t of s){if("string"!=typeof t?.id)continue;let s=!1;"delete"===e.kind?t.room_id===e.roomId&&(delete t.room_id,s=!0):t.room_id===e.dropId&&(t.room_id=e.keepId,s=!0);const o=t.vacuum?.segment_map;if(o&&"object"==typeof o&&!Array.isArray(o)){for(const t of Object.keys(o))"delete"===e.kind&&o[t]===e.roomId?(delete o[t],s=!0):"merge"===e.kind&&o[t]===e.dropId&&(o[t]=e.keepId,s=!0);"delete"===e.kind&&0===Object.keys(o).length&&(t.vacuum&&delete t.vacuum.segment_map,t.vacuum&&0===Object.keys(t.vacuum).length&&delete t.vacuum)}s&&i.add(t.id)}const o=[...i].sort((t,e)=>t.localeCompare(e));return{markers:s,before:jc(t,o),after:jc(s,o),changed:o.length}}const qc="1.74.0-beta.1";co.adopt(So,Mo);const Uc={badge:"display.badge",icon_ripple:"display.icon_ripple",value:"display.value",static_icon:"display.static_icon"},Kc={badge:"marker.display_hint_badge",icon_ripple:"marker.display_hint_icon_ripple",value:"marker.display_hint_value",static_icon:"marker.display_hint_static_icon"},Vc=2e3,Jc=1e3,Yc=(t,e,s,i)=>{for(t.delete(e),t.set(e,s);t.size>i;){const e=t.keys().next().value;if(void 0===e)break;t.delete(e)}},Xc=1e3,Zc=2e3,Qc=t=>{try{t.target?.setPointerCapture?.(t.pointerId)}catch{}},td="c8d5c166e30a11241ef32c7e1dc70368632e84c448524a8340494350ec4d5fca";class ed{constructor(t){this.host=t,this._junctionBaselineCache=new WeakMap,this._resizePreviewNodes=null,this._resizeBaselineLimits=[],this._resizeBaseFrameStable=!0,this._supportPreviewGeneration=0,this._decorAssetGuardReplace=null,this._undoGeometry=()=>{if(this.host._physicalDrag||this.host._physicalRotate)return void this._cancelPhysicalGesture();if(this.host._decorDraft)return this.host._decorDraft=null,void this.host.requestUpdate();if(this.host._decorMove||this.host._dtDrag||this.host._bdDrag)return void this._cancelDecorGesture();if(this.host._resize.dragging)return void this._rszCancelDrag();const t=this.host._geometryHistory.undo();t&&(this._applyGeometryState(t.before,!0)?this.host._showToast(this.host._t("history.undone",{name:t.name})):this.host._geometryHistory.clear())},this._redoGeometry=()=>{if(this.host._physicalDrag||this.host._physicalRotate)return void this._cancelPhysicalGesture();if(this.host._decorDraft)return this.host._decorDraft=null,void this.host.requestUpdate();if(this.host._decorMove||this.host._dtDrag||this.host._bdDrag)return void this._cancelDecorGesture();if(this.host._resize.dragging)return void this._rszCancelDrag();if(this.host._activeWallChainId&&this.host._wallChainRedo.length){const t=this.host._activeWallChainId,e=this.host._path.map(t=>[...t]),s=[...this.host._activeWallChainPartitionIds],i=[...this.host._wallChainSegmentCms],o=[...this.host._wallChainRedo],a=o[o.length-1],n=this.host._geometryHistory.redo();if(!n)return;return this._applyGeometryState(n.after,!0)?(this.host._activeWallChainId=t,this.host._path=[...e,[...a.point]],this.host._activeWallChainPartitionIds=[...s,a.id],this.host._wallChainSegmentCms=[...i,a.cm],this.host._wallChainRedo=o.slice(0,-1),this._clearPlanSnapHover(),void this.host._showToast(this.host._t("history.redone",{name:n.name}))):void this.host._geometryHistory.clear()}const t=this.host._geometryHistory.redo();t&&(this._applyGeometryState(t.after,!0)?this.host._showToast(this.host._t("history.redone",{name:t.name})):this.host._geometryHistory.clear())},this._savePhysicalDialog=()=>{const t=this.host._physicalDialog,e=this.host._curSpaceCfg,s=this.host._spaceModel();if(!t||!e||!s)return;const i=ot(t.cm);if(null==i)return void this._showPhysicalRange("column"===t.kind?Zt:100,"column"===t.kind?1:0);const o=this.host._imperial?2.54*i:i,a="column"===t.kind?Zt:100,n="column"===t.kind?1:0;if(!Number.isFinite(o)||oa)return void this._showPhysicalRange(a,n);if("column"===t.kind){const e=s.wall_columns.find(e=>e.id===t.id);if(!e)return;const i=ot(t.angle||"0");if("circle"!==t.shape&&(null==i||i<0||i>=90))return void this.host._showToast(this.host._t("toast.physical_angle"));const a="circle"===t.shape?{id:t.id,shape:"circle",center:e.center,cm:o}:{id:t.id,shape:"square",center:e.center,cm:o,angle:i};if(s.wall_columns.some(e=>e.id!==t.id&&Qt(e,a,.02*this.host._gridPitch)))return void this.host._showToast(this.host._t("toast.column_duplicate"))}const r=this._geometrySnapshot();if("partition"===t.kind){const s=(e.partitions||[]).find(e=>e.id===t.id);if(s&&0===o&&te(e.openings,{kind:"partition",id:t.id}))return void this.host._showToast(this.host._t("toast.zero_wall_opening_conflict"));s&&(s.cm=o)}else if("column"===t.kind){const s=(e.wall_columns||[]).find(e=>e.id===t.id);s&&(s.cm=ee(o),s.shape="circle"===t.shape?"circle":"square","square"===s.shape?s.angle=ot(t.angle||"0"):delete s.angle)}const l=this._commitPhysicalGeometry(this.host._t("history.physical_edit"),r);this.host._physicalDialog=null,l||this.host.requestUpdate()},this._deletePhysicalSelection=async()=>{const t=this.host._physicalSel,e=this.host._curSpaceCfg;if(!t||!e)return;const s=this._geometrySnapshot();if("partition"===t.kind){const s=(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(s.length)return void(this.host._partitionDeleteDialog={id:t.id,openings:s.map(t=>JSON.parse(JSON.stringify(t)))})}const i="partition"===t.kind?"partitions":"wall_columns";e[i]=(e[i]||[]).filter(e=>e.id!==t.id),e[i].length||delete e[i],this.host._activeWallChainPartitionIds.includes(t.id)&&this._cancelPath(),this.host._physicalSel=null,this.host._physicalDialog=null,this._commitPhysicalGeometry(this.host._t("history.physical_delete"),s)},this._confirmPartitionDelete=()=>{const t=this.host._partitionDeleteDialog,e=this.host._curSpaceCfg;if(!t||!e)return;const s=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.host._partitionDeleteDialog=null,this.host._physicalSel=null,this.host._physicalDialog=null,this._commitPhysicalGeometry(this.host._t("history.physical_delete"),s)},this._furnShiftListener=t=>{if("Shift"!==t.key)return;const e=this.host._furnPreviewInput;if(!e)return;const s="keydown"===t.type;e.free!==s&&(this.host._furnPreviewInput={...e,free:s},this.host.requestUpdate())},this._furnShiftAttached=!1,this._confirmRoomDelete=t=>{const e=this.host._roomDeleteDialog,s=this.host._curSpaceCfg,i=this.host._spaceModel();if(!e||!s||!i)return;const o=i.rooms.find(t=>t.id===e.roomId);if(!o)return void(this.host._roomDeleteDialog=null);const a=this.host._openCuts(),n=tc(ht(i.rooms,this.host._spaceWalls,a,this.host._wallKeyPitch,this.host._cellCm,this.host._gridPitch,Xc).filter(t=>t.roomId===o.id),i.partitions,this.host._openingsR.map(t=>({...t,x:t.rx,y:t.ry})),.02*this.host._gridPitch),r=new Set(n.materialize.filter(t=>!t.reusePartitionId).map(t=>t.interval.key)).size;if(t&&(s.partitions||[]).length+r>Zc)return void this.host._showToast(this.host._t("toast.physical_limit"));const l=this._geometrySnapshot(),h=Gc(this.host._serverCfg?.markers||[],{kind:"delete",roomId:e.roomId});l&&h.changed&&(l.roomReferences=h.before);const c=se(i.rooms,this.host._spaceWalls,a,this.host._wallKeyPitch,this.host._cellCm,this.host._gridPitch,Xc);if(t){s.partitions||=[];const t=new Map,e=new Map,i=t=>{const e=(s.wall_segments||[]).find(e=>{const s=[Number(e.a?.[0])*Xc,Number(e.a?.[1])*Xc],i=[Number(e.b?.[0])*Xc,Number(e.b?.[1])*Xc];return this._samePt(t.a,s)&&this._samePt(t.b,i)||this._samePt(t.a,i)&&this._samePt(t.b,s)});return"string"==typeof e?.id&&e.id?e.id:null},o=Date.now().toString(36);for(const a of n.materialize){let n=a.reusePartitionId?s.partitions.find(t=>t.id===a.reusePartitionId):e.get(a.interval.key);n||(n={id:i(a.interval)||`partition-room-${o}-${e.size}`,a:[a.interval.a[0]/Xc,a.interval.a[1]/Xc],b:[a.interval.b[0]/Xc,a.interval.b[1]/Xc],cm:a.interval.cm},s.partitions.push(n),e.set(a.interval.key,n)),t.set(a.interval.key,n)}for(const e of s.openings||[]){const s=n.openingIntervals.get(e.id),i=s?t.get(s):null,o=this.host._openingsR.find(t=>t.id===e.id);if(!i||!o)continue;const a={a:[i.a[0]*Xc,i.a[1]*Xc],b:[i.b[0]*Xc,i.b[1]*Xc]};e.host={kind:"partition",id:i.id,t:ec([o.rx,o.ry],a)}}}else if(n.removeOpeningIds.length){const t=new Set(n.removeOpeningIds);s.openings=(s.openings||[]).filter(e=>!t.has(e.id)),s.openings.length||delete s.openings}s.rooms=s.rooms.filter(t=>t.id!==o.id),h.changed&&this.host._serverCfg&&(this.host._serverCfg.markers=h.markers),this.host._cfgEpoch++;const d=this.host._normalizeWalls(c,this.host._openCuts());d.length?s.walls=d:delete s.walls,this.host._roomDeleteDialog=null,this._commitPhysicalGeometry(this.host._t(t?"history.delete_room_keep_walls":"history.delete_room_with_walls"),l),this.host._regSignature="",this.host._maybeRebuildDevices(),this.host.requestUpdate()},this._rebindPartitionOpening=()=>{const t=this.host._openingDialog;if(!t?.id)return;const e=t.id;this._activateMarkupTool("opening"),"opening"===this.host._tool&&(this.host._openingRebindId=e,this.host._openingPreset={type:t.type,lengthCm:t.lengthCm,flipH:t.flipH,flipV:t.flipV,revision:++this.host._openingPresetRevision},this.host._openingDialog=null,this.host._openingHoverCandidate=null)},this._deviceInboxTabKey=t=>{if("ArrowLeft"!==t.key&&"ArrowRight"!==t.key)return;const e=this.host._deviceInbox;if(!e)return;const s=["on_plan","available","hidden","readd"],i="ArrowRight"===t.key?1:-1,o=(s.indexOf(e.tab)+i+s.length)%s.length;this.host._deviceInbox={...e,tab:s[o],limit:100,onlyNew:!1},t.preventDefault()},this._keepClosedAsPartitions=()=>{this.host._wallFaceBatch?this._decideWallFace(!1):this.host._contourClosed&&!this.host._pendingSplit&&this.host._curSpaceCfg&&this._finalizeWallChainPartitions(this.host._activeWallChainPartitionIds)&&(this.host._roomDialog=!1,this.host._path=[],this.host._activeWallChainId=null,this.host._activeWallChainPartitionIds=[],this.host._wallChainSegmentCms=[],this.host._wallChainRedo=[],this.host._closingWallCm=null,this.host.requestUpdate())},this._toggleServerPlans=async()=>{const t=this.host._spaceDialog;if(t)if(t.pickSaved)this.host._spaceDialog={...t,pickSaved:!1};else{this.host._spaceDialog={...t,pickSaved:!0,savedBusy:!0};try{const t=await this.host.hass.callWS({type:"houseplan/plans/list"}),e=this.host._spaceDialog;e&&(this.host._spaceDialog={...e,saved:t?.plans||[],savedBusy:!1})}catch(t){const e=this.host._spaceDialog;e&&(this.host._spaceDialog={...e,saved:[],savedBusy:!1}),this.host._showToast(this.host._t("toast.plans_list_failed",{err:this.host._errText(t)}))}}},this._openSettingsDialog=()=>{if(!this.host._norm)return;const t=this.host._glowRadiusCm,e=this.host._imperial?Math.round(t/30.48*10)/10:Math.round(t)/100;this.host._settingsDialog={colors:JSON.parse(JSON.stringify(this.host._fillColors)),glowRadius:e,bgColor:le(this.host._settings,{bgColor:null})||null,northDeg:re(this.host._settings,{}),bgMode:ne(this.host._settings,{}),sunRays:ae(this.host._settings,{}),radarShowLive:!1!==this.host._settings.radar?.show_live,showRoomTooltip:oe(this.host._settings),zigbeeTopology:ie(this.host._settings),busy:!1}},this._openSupportDialog=()=>{this.host._norm&&this.host._canEdit&&(clearTimeout(this._supportExpiryTimer),this._supportExpiryTimer=void 0,this._supportPreviewGeneration+=1,this.host._supportDialog={draftId:gc("draft"),idempotencyKey:gc("report"),submissionFingerprint:"",contact:"",message:"",attach:!1,status:"idle",preview:null,rawOpen:!1,errorCode:"",reportId:""})},this._openAlignDialog=()=>this._previewAlignDialog(!1),this._toggleOptimizeLivePositions=()=>{const t=this.host._alignDialog;t&&!t.busy&&t.report.liveMissingPositions.length&&this._previewAlignDialog(!t.removeLiveMissingPositions)},this._openBackupExport=()=>{this.host._settingsDialog=null,this.host._backupExportDialog={kind:"full",planOnly:!1,busy:!1,error:""}},this._decorStylePersistTimer=null,this._openRulesDialog=()=>{if(!this.host._norm)return;const t=this.host._settings.icon_rules,e=(t&&t.length?t:he).map(t=>({...t}));this.host._rulesDialog={rules:e,test:"",busy:!1}},this._discoveryPreviewMemo=null,this._decorImages=new xc(t,{decorSnap:(t,e)=>this._decorSnap(t,e),geometrySnapshot:()=>this._geometrySnapshot(),clearFurniturePreview:()=>this._clearFurniturePreview(),recordGeometry:(t,e)=>this._recordGeometry(t,e),saveConfig:()=>this._saveConfig(),saveShape:()=>this._decorSaveShape(),setGuardReplace:t=>{this._decorAssetGuardReplace=t},furnShiftDetach:()=>this._furnShiftDetach(),furnPick:t=>this._furnPick(t),furnFieldValue:t=>this._furnFieldValue(t),furnFieldToCm:t=>this._furnFieldToCm(t)}),this._radarSetup=new hh({hass:()=>t.hass,requestUpdate:()=>t.requestUpdate(),t:(e,s)=>t._t(e,s),configFromDraft:nh,apply:e=>{t._markerDialog&&(t._markerDialog={...t._markerDialog,radar:e,radarEligible:!0,radarTouched:!0,radarRemove:!1})},confirmDiscard:()=>t._confirmDanger((t=>({key:"discard-radar-setup",kind:"warning",title:t("radar.discard_setup_title"),message:t("radar.discard_setup"),confirmLabel:t("btn.close"),cancelLabel:t("btn.cancel")}))(e=>t._t(e)))}),t._editorSecondary=new cc({root:()=>t.renderRoot,requestUpdate:()=>t.requestUpdate(),updateComplete:()=>t.updateComplete,clearTip:()=>{t._tip=null}}),t._resize=new an}_routeLiveEditorUpdate(t,e){const s=Vo(this.host,t,e);return!s&&this.host._resize.preview&&(this._resizeBaseFrameStable=!1),s}_commitLiveEditor(){!function(t){const e=t,s=qo(t);s.raf&&"function"==typeof cancelAnimationFrame&&cancelAnimationFrame(s.raf),s.raf=0,Xo(s);const i=e.renderRoot?.querySelector("[data-hp-live-editor]");i&&c(l,i);const o=e.renderRoot?.querySelector("[data-hp-live-editor-html]");if(o){const t=e._viewOr(e._baseVb());c(e._renderLiveEditorMeasurements(t),o)}Uo(s,s.requestedRevision)}(this.host)}_disposeLiveEditor(){this._radarSetup.reset(),function(t){Lo(t);const e=Bo.get(t);e&&(e.raf&&"function"==typeof cancelAnimationFrame&&cancelAnimationFrame(e.raf),Xo(e),Uo(e,e.requestedRevision),Bo.delete(t))}(this.host)}_cancelRadarSetup(){this._radarSetup.interrupt()}async _whenLiveEditorSettled(){await this.host.updateComplete,await function(t){const e=Bo.get(t);if(!e||!e.raf||e.paintedRevision>=e.requestedRevision)return Promise.resolve();const s=e.requestedRevision;return new Promise(t=>e.waiters.push({revision:s,resolve:t}))}(this.host)}_queuePointerMove(t,e){Ho(this.host,t,e)}_flushPointerMove(t){Oo(this.host,t)}_cancelPointerMove(t){Lo(this.host,t)}_help(t){const e=`${t}.aria`,s=a(this.host.hass,this.host._config?.language);return ce(s,t)&&ce(s,e)?h``}}const Sc=(t,e)=>t[0]*e[1]-t[1]*e[0],Mc=(t,e)=>t[0]*e[0]+t[1]*e[1],Cc=(t,e)=>[t[0]-e[0],t[1]-e[1]],Pc=(t,e,s)=>[t[0]+e[0]*s,t[1]+e[1]*s];function Dc(t,e,s){return Math.abs(Sc(t,e))<=s}function Ic(t,e,s){return Math.abs(Sc(Cc(t,e),s))}function Tc(t,e,s,i,o){const a=e[0]-t[0],n=e[1]-t[1],r=Math.hypot(a,n);if(!(r>o&&s>0))return[];const l=[a/r,n/r];return function(t,e,s){const i=e.map(([e,s])=>[Math.max(0,Math.min(e,s)),Math.min(t,Math.max(e,s))]).filter(([t,e])=>e>t+s).sort((t,e)=>t[0]-e[0]||t[1]-e[1]),o=[];for(const t of i){const e=o[o.length-1];!e||t[0]>e[1]+s?o.push([...t]):e[1]=Math.max(e[1],t[1])}const a=[];let n=0;for(const[t,e]of o)t>n+s&&a.push([n,t]),n=Math.max(n,e);return t>n+s&&a.push([n,t]),a}(r,i.flatMap(e=>{const i=e.b[0]-e.a[0],a=e.b[1]-e.a[1],n=Math.hypot(i,a);if(!(n>o&&Dc(l,[i/n,a/n],1e-6)))return[];if(Ic(e.a,t,l)>1.1*Math.max(s,o)||Ic(e.b,t,l)>1.1*Math.max(s,o))return[];return[[Mc(Cc(e.a,t),l),Mc(Cc(e.b,t),l)]]}),o).flatMap(([e,i])=>{const o=Xt({a:Pc(t,l,e),b:Pc(t,l,i),halfDepth:s});return o?[o]:[]})}function zc(t){const e=t.coordScale??1,s=Math.max(t.epsilon??2e-4*t.gridPitch,1e-9),i=[];for(const s of t.rooms||[]){if(!s?.id)continue;const o=Z(t.rooms,s.id,t.walls,t.openCuts,t.pitch,t.cellCm,t.gridPitch,e);if(!o||o.poly.length<3)continue;const a=Jt(o.poly,o.offsets);!a||a.length<3||i.push({roomId:s.id,profile:o,inner:a})}i.sort((t,e)=>t.roomId.localeCompare(e.roomId));const o=(t.roomOpenings||[]).map(t=>{const e=t.angle*Math.PI/180,s=[Math.cos(e),Math.sin(e)],i=Math.max(0,t.length)/2;return{a:Pc([t.x,t.y],s,-i),b:Pc([t.x,t.y],s,i)}}),a=[];for(const i of Yt(t.rooms,t.walls,t.openCuts,t.pitch,t.cellCm,t.gridPitch,e))for(const t of Tc(i.a,i.b,i.depthUnits/2,o,s))a.push({body:t});const n=new Map;for(const e of t.partitionCuts||[]){const t=n.get(e.hostId)||[];t.push(e),n.set(e.hostId,t)}for(const e of t.partitions||[]){const i=b(e.cm,t.cellCm,t.gridPitch)/2;for(const t of Tc(e.a,e.b,i,n.get(e.id)||[],s))a.push({body:t,partitionId:e.id})}return{rooms:i,boundaries:a,epsilon:s}}function Rc(t,e,s,i){const o=t.profile.offsets[e];if(!(o>0))return null;const a=function(t,e){const s=t[e],i=t[(e+1)%t.length],o=i[0]-s[0],a=i[1]-s[1],n=Math.hypot(o,a)||1;return function(t){let e=0;for(let s=0;s=0?[-a/n,o/n]:[a/n,-o/n]}(t.profile.poly,e),n=Pc(s.center,a,o),r=[];for(let e=0;ei&&Dc(s.axis,[l[0]/h,l[1]/h],1e-6)))continue;if(Ic(o,n,s.axis)>i||Ic(a,n,s.axis)>i)continue;const c=Mc(Cc(o,n),s.axis),d=Mc(Cc(a,n),s.axis);r.push([Math.min(c,d),Math.max(c,d)])}const l=function(t,e){t.sort((t,e)=>t[0]-e[0]||t[1]-e[1]);const s=[];for(const i of t){const t=s[s.length-1];!t||i[0]>t[1]+e?s.push([...i]):t[1]=Math.max(t[1],i[1])}return s}(r,i).find(([t,e])=>t<=i&&e>=-i);if(!l)return null;const[h,c]=l,d=Pc(n,s.axis,-s.half),p=Pc(n,s.axis,s.half),u=Math.max(0,-s.half-h),_=Math.max(0,c-s.half),m=u>0?Pc(n,s.axis,h):d,g=_>0?Pc(n,s.axis,c):p,f=Mc(a,s.normal)>=0?1:-1,b=(e,i,o)=>({from:e,to:i,label:[(e[0]+i[0])/2,(e[1]+i[1])/2],axis:s.axis,labelNormal:a,distance:o,roomId:t.roomId,roomSide:f,source:"room-face"});return{left:b(d,m,u),right:b(p,g,_)}}function Ac(t){const e=Pc(t.center,t.axis,-t.half),s=Pc(t.center,t.axis,t.half),i=Pc(t.center,t.axis,Math.min(-t.half,t.targetLo)),o=Pc(t.center,t.axis,Math.max(t.half,t.targetHi)),a=(e,s)=>({from:e,to:s,label:[(e[0]+s[0])/2,(e[1]+s[1])/2],axis:t.axis,labelNormal:t.normal,distance:Math.hypot(s[0]-e[0],s[1]-e[1]),source:"host-end"});return[a(e,i),a(s,o)]}function Fc(t,e,s,i){const o=Cc(s,e),a=Mc(o,o);if(!(a>i*i))return Math.hypot(...Cc(t,e))<=i;const n=Mc(Cc(t,e),o)/a;if(n<-i||n>1+i)return!1;const r=Pc(e,o,Math.max(0,Math.min(1,n)));return Math.hypot(...Cc(t,r))<=i}function Nc(t,e,s){let i=!1;for(let o=0,a=e.length-1;ot[1]!=h>t[1]&&t[0]<(l-n)*(t[1]-r)/(h-r)+n&&(i=!i)}return i}function Ec(t,e,s,i,o,a){const n=Cc(i,s),r=Sc(e,n);if(Math.abs(r)<=a)return null;const l=Cc(s,t),h=Sc(l,n)/r,c=Sc(l,e)/r;return h<-a||h>o+a||c<-a||c>1+a?null:Math.max(0,Math.min(o,h))}function Hc(t,e,s){const i=Ac(s),o="partition"===t.host?.kind?t.host.id:void 0;return[{base:i[0],direction:[-s.axis[0],-s.axis[1]]},{base:i[1],direction:s.axis}].map(({base:t,direction:s})=>{const i=t.distance,a=function(t,e,s,i,o,a){let n=null;for(const r of i)if(!o||r.partitionId!==o){if(Nc(t,r.body,a))return 0;for(let i=0;iMc(Cc(t,o),s));return{center:o,axis:s,normal:i,half:Math.max(0,t.renderedLength)/2,targetLo:Math.min(...a),targetHi:Math.max(...a)}}(t),i=e.rooms.flatMap(t=>{const i=function(t,e,s){const{profile:i}=t;let o=null;for(let t=0;t0))continue;const a=i.poly[t],n=i.poly[(t+1)%i.poly.length],r=Cc(n,a),l=Math.hypot(r[0],r[1]);if(!(l>s&&Dc(e.axis,[r[0]/l,r[1]/l],1e-6)))continue;if(Ic(a,e.center,e.axis)>s||Ic(n,e.center,e.axis)>s)continue;const h=Mc(Cc(a,e.center),e.axis),c=Mc(Cc(n,e.center),e.axis),d=Math.min(h,c),p=Math.max(h,c);if(d>-e.half+s||p0?d:p<0?-p:0);(!o||u2)return Ac(s);if(i.length){const t=i.map(({room:t,edge:i})=>Rc(t,i,s,e.epsilon));if(t.some(t=>!t))return Ac(s);const o=t;return[...o.map(t=>t.left),...o.map(t=>t.right)]}return Hc(t,e,s)}function Lc(t,e,s,i,o){const a=(n=t,JSON.parse(JSON.stringify(n)));var n;const r=[...new Set(i.filter(t=>"string"==typeof t&&t))],l={partitionsMerged:0,partitionsReconciled:0,openingsRehosted:0,changed:!1};if(!r.length||!Array.isArray(a?.partitions))return{space:a,report:l};const h=JSON.stringify(a),c=sl(a.partitions,{pitch:o.pitch,seedIds:r,geometry:ol(a)});c.merged&&(a.partitions=c.partitions);const d=Array.isArray(a.openings)?a.openings:[];c.merged&&il(d,c.partitions,c.openingMoves,{coordScale:o.coordScale,cellCm:o.cellCm,gridPitch:o.gridPitch});const p=function(t,e,s){const i=new Set(t.map(t=>t.id)),o=new Map(s.map(t=>[t.fromId,t.toId]));return[...new Set(e.map(t=>o.get(t)||t).filter(t=>i.has(t)))].sort((t,e)=>t.localeCompare(e))}(c.partitions,r,c.openingMoves),u=bl(a,{rooms:e.rooms,wall_columns:e.wall_columns,partitions:c.partitions.map(t=>({...t,a:[t.a[0]*o.coordScale,t.a[1]*o.coordScale],b:[t.b[0]*o.coordScale,t.b[1]*o.coordScale]}))},a.walls,s,{...o,partitionIds:p});return u.partitionsReconciled&&(u.walls.length?a.walls=u.walls:delete a.walls,u.partitions.length?a.partitions=u.partitions:delete a.partitions,u.openings.length?a.openings=u.openings:delete a.openings),{space:a,report:{partitionsMerged:c.merged,partitionsReconciled:u.partitionsReconciled,openingsRehosted:u.openingsRehosted,changed:JSON.stringify(a)!==h}}}const Bc=t=>void 0===t?t:JSON.parse(JSON.stringify(t)),Wc=(t,e)=>!!t&&"object"==typeof t&&Object.prototype.hasOwnProperty.call(t,e);function jc(t,e){const s=e?new Set(e):null;return(t||[]).filter(t=>"string"==typeof t?.id&&(!s||s.has(t.id))).map(t=>{const e=t.vacuum;return{markerId:t.id,roomIdPresent:Wc(t,"room_id"),...Wc(t,"room_id")?{roomId:Bc(t.room_id)}:{},vacuumPresent:Wc(t,"vacuum"),segmentMapPresent:Wc(e,"segment_map"),...Wc(e,"segment_map")?{segmentMap:Bc(e?.segment_map)}:{}}}).sort((t,e)=>t.markerId.localeCompare(e.markerId))}function Gc(t,e){const s=Bc([...t||[]]),i=new Set;for(const t of s){if("string"!=typeof t?.id)continue;let s=!1;"delete"===e.kind?t.room_id===e.roomId&&(delete t.room_id,s=!0):t.room_id===e.dropId&&(t.room_id=e.keepId,s=!0);const o=t.vacuum?.segment_map;if(o&&"object"==typeof o&&!Array.isArray(o)){for(const t of Object.keys(o))"delete"===e.kind&&o[t]===e.roomId?(delete o[t],s=!0):"merge"===e.kind&&o[t]===e.dropId&&(o[t]=e.keepId,s=!0);"delete"===e.kind&&0===Object.keys(o).length&&(t.vacuum&&delete t.vacuum.segment_map,t.vacuum&&0===Object.keys(t.vacuum).length&&delete t.vacuum)}s&&i.add(t.id)}const o=[...i].sort((t,e)=>t.localeCompare(e));return{markers:s,before:jc(t,o),after:jc(s,o),changed:o.length}}const qc="1.74.0-beta.1";co.adopt(So,Mo);const Uc={badge:"display.badge",icon_ripple:"display.icon_ripple",value:"display.value",static_icon:"display.static_icon"},Kc={badge:"marker.display_hint_badge",icon_ripple:"marker.display_hint_icon_ripple",value:"marker.display_hint_value",static_icon:"marker.display_hint_static_icon"},Vc=2e3,Jc=1e3,Yc=(t,e,s,i)=>{for(t.delete(e),t.set(e,s);t.size>i;){const e=t.keys().next().value;if(void 0===e)break;t.delete(e)}},Xc=1e3,Zc=2e3,Qc=t=>{try{t.target?.setPointerCapture?.(t.pointerId)}catch{}},td="2e6f7d70c797ae4e865b10859c77cc3380a432272a975b8f35b51234ae3cfe62";class ed{constructor(t){this.host=t,this._junctionBaselineCache=new WeakMap,this._resizePreviewNodes=null,this._resizeBaselineLimits=[],this._resizeBaseFrameStable=!0,this._supportPreviewGeneration=0,this._decorAssetGuardReplace=null,this._undoGeometry=()=>{if(this.host._physicalDrag||this.host._physicalRotate)return void this._cancelPhysicalGesture();if(this.host._decorDraft)return this.host._decorDraft=null,void this.host.requestUpdate();if(this.host._decorMove||this.host._dtDrag||this.host._bdDrag)return void this._cancelDecorGesture();if(this.host._resize.dragging)return void this._rszCancelDrag();const t=this.host._geometryHistory.undo();t&&(this._applyGeometryState(t.before,!0)?this.host._showToast(this.host._t("history.undone",{name:t.name})):this.host._geometryHistory.clear())},this._redoGeometry=()=>{if(this.host._physicalDrag||this.host._physicalRotate)return void this._cancelPhysicalGesture();if(this.host._decorDraft)return this.host._decorDraft=null,void this.host.requestUpdate();if(this.host._decorMove||this.host._dtDrag||this.host._bdDrag)return void this._cancelDecorGesture();if(this.host._resize.dragging)return void this._rszCancelDrag();if(this.host._activeWallChainId&&this.host._wallChainRedo.length){const t=this.host._activeWallChainId,e=this.host._path.map(t=>[...t]),s=[...this.host._activeWallChainPartitionIds],i=[...this.host._wallChainSegmentCms],o=[...this.host._wallChainRedo],a=o[o.length-1],n=this.host._geometryHistory.redo();if(!n)return;return this._applyGeometryState(n.after,!0)?(this.host._activeWallChainId=t,this.host._path=[...e,[...a.point]],this.host._activeWallChainPartitionIds=[...s,a.id],this.host._wallChainSegmentCms=[...i,a.cm],this.host._wallChainRedo=o.slice(0,-1),this._clearPlanSnapHover(),void this.host._showToast(this.host._t("history.redone",{name:n.name}))):void this.host._geometryHistory.clear()}const t=this.host._geometryHistory.redo();t&&(this._applyGeometryState(t.after,!0)?this.host._showToast(this.host._t("history.redone",{name:t.name})):this.host._geometryHistory.clear())},this._savePhysicalDialog=()=>{const t=this.host._physicalDialog,e=this.host._curSpaceCfg,s=this.host._spaceModel();if(!t||!e||!s)return;const i=ot(t.cm);if(null==i)return void this._showPhysicalRange("column"===t.kind?Zt:100,"column"===t.kind?1:0);const o=this.host._imperial?2.54*i:i,a="column"===t.kind?Zt:100,n="column"===t.kind?1:0;if(!Number.isFinite(o)||oa)return void this._showPhysicalRange(a,n);if("column"===t.kind){const e=s.wall_columns.find(e=>e.id===t.id);if(!e)return;const i=ot(t.angle||"0");if("circle"!==t.shape&&(null==i||i<0||i>=90))return void this.host._showToast(this.host._t("toast.physical_angle"));const a="circle"===t.shape?{id:t.id,shape:"circle",center:e.center,cm:o}:{id:t.id,shape:"square",center:e.center,cm:o,angle:i};if(s.wall_columns.some(e=>e.id!==t.id&&Qt(e,a,.02*this.host._gridPitch)))return void this.host._showToast(this.host._t("toast.column_duplicate"))}const r=this._geometrySnapshot();if("partition"===t.kind){const s=(e.partitions||[]).find(e=>e.id===t.id);if(s&&0===o&&te(e.openings,{kind:"partition",id:t.id}))return void this.host._showToast(this.host._t("toast.zero_wall_opening_conflict"));s&&(s.cm=o)}else if("column"===t.kind){const s=(e.wall_columns||[]).find(e=>e.id===t.id);s&&(s.cm=ee(o),s.shape="circle"===t.shape?"circle":"square","square"===s.shape?s.angle=ot(t.angle||"0"):delete s.angle)}const l=this._commitPhysicalGeometry(this.host._t("history.physical_edit"),r);this.host._physicalDialog=null,l||this.host.requestUpdate()},this._deletePhysicalSelection=async()=>{const t=this.host._physicalSel,e=this.host._curSpaceCfg;if(!t||!e)return;const s=this._geometrySnapshot();if("partition"===t.kind){const s=(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(s.length)return void(this.host._partitionDeleteDialog={id:t.id,openings:s.map(t=>JSON.parse(JSON.stringify(t)))})}const i="partition"===t.kind?"partitions":"wall_columns";e[i]=(e[i]||[]).filter(e=>e.id!==t.id),e[i].length||delete e[i],this.host._activeWallChainPartitionIds.includes(t.id)&&this._cancelPath(),this.host._physicalSel=null,this.host._physicalDialog=null,this._commitPhysicalGeometry(this.host._t("history.physical_delete"),s)},this._confirmPartitionDelete=()=>{const t=this.host._partitionDeleteDialog,e=this.host._curSpaceCfg;if(!t||!e)return;const s=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.host._partitionDeleteDialog=null,this.host._physicalSel=null,this.host._physicalDialog=null,this._commitPhysicalGeometry(this.host._t("history.physical_delete"),s)},this._furnShiftListener=t=>{if("Shift"!==t.key)return;const e=this.host._furnPreviewInput;if(!e)return;const s="keydown"===t.type;e.free!==s&&(this.host._furnPreviewInput={...e,free:s},this.host.requestUpdate())},this._furnShiftAttached=!1,this._confirmRoomDelete=t=>{const e=this.host._roomDeleteDialog,s=this.host._curSpaceCfg,i=this.host._spaceModel();if(!e||!s||!i)return;const o=i.rooms.find(t=>t.id===e.roomId);if(!o)return void(this.host._roomDeleteDialog=null);const a=this.host._openCuts(),n=tc(ht(i.rooms,this.host._spaceWalls,a,this.host._wallKeyPitch,this.host._cellCm,this.host._gridPitch,Xc).filter(t=>t.roomId===o.id),i.partitions,this.host._openingsR.map(t=>({...t,x:t.rx,y:t.ry})),.02*this.host._gridPitch),r=new Set(n.materialize.filter(t=>!t.reusePartitionId).map(t=>t.interval.key)).size;if(t&&(s.partitions||[]).length+r>Zc)return void this.host._showToast(this.host._t("toast.physical_limit"));const l=this._geometrySnapshot(),h=Gc(this.host._serverCfg?.markers||[],{kind:"delete",roomId:e.roomId});l&&h.changed&&(l.roomReferences=h.before);const c=se(i.rooms,this.host._spaceWalls,a,this.host._wallKeyPitch,this.host._cellCm,this.host._gridPitch,Xc);if(t){s.partitions||=[];const t=new Map,e=new Map,i=t=>{const e=(s.wall_segments||[]).find(e=>{const s=[Number(e.a?.[0])*Xc,Number(e.a?.[1])*Xc],i=[Number(e.b?.[0])*Xc,Number(e.b?.[1])*Xc];return this._samePt(t.a,s)&&this._samePt(t.b,i)||this._samePt(t.a,i)&&this._samePt(t.b,s)});return"string"==typeof e?.id&&e.id?e.id:null},o=Date.now().toString(36);for(const a of n.materialize){let n=a.reusePartitionId?s.partitions.find(t=>t.id===a.reusePartitionId):e.get(a.interval.key);n||(n={id:i(a.interval)||`partition-room-${o}-${e.size}`,a:[a.interval.a[0]/Xc,a.interval.a[1]/Xc],b:[a.interval.b[0]/Xc,a.interval.b[1]/Xc],cm:a.interval.cm},s.partitions.push(n),e.set(a.interval.key,n)),t.set(a.interval.key,n)}for(const e of s.openings||[]){const s=n.openingIntervals.get(e.id),i=s?t.get(s):null,o=this.host._openingsR.find(t=>t.id===e.id);if(!i||!o)continue;const a={a:[i.a[0]*Xc,i.a[1]*Xc],b:[i.b[0]*Xc,i.b[1]*Xc]};e.host={kind:"partition",id:i.id,t:ec([o.rx,o.ry],a)}}}else if(n.removeOpeningIds.length){const t=new Set(n.removeOpeningIds);s.openings=(s.openings||[]).filter(e=>!t.has(e.id)),s.openings.length||delete s.openings}s.rooms=s.rooms.filter(t=>t.id!==o.id),h.changed&&this.host._serverCfg&&(this.host._serverCfg.markers=h.markers),this.host._cfgEpoch++;const d=this.host._normalizeWalls(c,this.host._openCuts());d.length?s.walls=d:delete s.walls,this.host._roomDeleteDialog=null,this._commitPhysicalGeometry(this.host._t(t?"history.delete_room_keep_walls":"history.delete_room_with_walls"),l),this.host._regSignature="",this.host._maybeRebuildDevices(),this.host.requestUpdate()},this._rebindPartitionOpening=()=>{const t=this.host._openingDialog;if(!t?.id)return;const e=t.id;this._activateMarkupTool("opening"),"opening"===this.host._tool&&(this.host._openingRebindId=e,this.host._openingPreset={type:t.type,lengthCm:t.lengthCm,flipH:t.flipH,flipV:t.flipV,revision:++this.host._openingPresetRevision},this.host._openingDialog=null,this.host._openingHoverCandidate=null)},this._deviceInboxTabKey=t=>{if("ArrowLeft"!==t.key&&"ArrowRight"!==t.key)return;const e=this.host._deviceInbox;if(!e)return;const s=["on_plan","available","hidden","readd"],i="ArrowRight"===t.key?1:-1,o=(s.indexOf(e.tab)+i+s.length)%s.length;this.host._deviceInbox={...e,tab:s[o],limit:100,onlyNew:!1},t.preventDefault()},this._keepClosedAsPartitions=()=>{this.host._wallFaceBatch?this._decideWallFace(!1):this.host._contourClosed&&!this.host._pendingSplit&&this.host._curSpaceCfg&&this._finalizeWallChainPartitions(this.host._activeWallChainPartitionIds)&&(this.host._roomDialog=!1,this.host._path=[],this.host._activeWallChainId=null,this.host._activeWallChainPartitionIds=[],this.host._wallChainSegmentCms=[],this.host._wallChainRedo=[],this.host._closingWallCm=null,this.host.requestUpdate())},this._toggleServerPlans=async()=>{const t=this.host._spaceDialog;if(t)if(t.pickSaved)this.host._spaceDialog={...t,pickSaved:!1};else{this.host._spaceDialog={...t,pickSaved:!0,savedBusy:!0};try{const t=await this.host.hass.callWS({type:"houseplan/plans/list"}),e=this.host._spaceDialog;e&&(this.host._spaceDialog={...e,saved:t?.plans||[],savedBusy:!1})}catch(t){const e=this.host._spaceDialog;e&&(this.host._spaceDialog={...e,saved:[],savedBusy:!1}),this.host._showToast(this.host._t("toast.plans_list_failed",{err:this.host._errText(t)}))}}},this._openSettingsDialog=()=>{if(!this.host._norm)return;const t=this.host._glowRadiusCm,e=this.host._imperial?Math.round(t/30.48*10)/10:Math.round(t)/100;this.host._settingsDialog={colors:JSON.parse(JSON.stringify(this.host._fillColors)),glowRadius:e,bgColor:le(this.host._settings,{bgColor:null})||null,northDeg:re(this.host._settings,{}),bgMode:ne(this.host._settings,{}),sunRays:ae(this.host._settings,{}),radarShowLive:!1!==this.host._settings.radar?.show_live,showRoomTooltip:oe(this.host._settings),zigbeeTopology:ie(this.host._settings),busy:!1}},this._openSupportDialog=()=>{this.host._norm&&this.host._canEdit&&(clearTimeout(this._supportExpiryTimer),this._supportExpiryTimer=void 0,this._supportPreviewGeneration+=1,this.host._supportDialog={draftId:gc("draft"),idempotencyKey:gc("report"),submissionFingerprint:"",contact:"",message:"",attach:!1,status:"idle",preview:null,rawOpen:!1,errorCode:"",reportId:""})},this._openAlignDialog=()=>this._previewAlignDialog(!1),this._toggleOptimizeLivePositions=()=>{const t=this.host._alignDialog;t&&!t.busy&&t.report.liveMissingPositions.length&&this._previewAlignDialog(!t.removeLiveMissingPositions)},this._openBackupExport=()=>{this.host._settingsDialog=null,this.host._backupExportDialog={kind:"full",planOnly:!1,busy:!1,error:""}},this._decorStylePersistTimer=null,this._openRulesDialog=()=>{if(!this.host._norm)return;const t=this.host._settings.icon_rules,e=(t&&t.length?t:he).map(t=>({...t}));this.host._rulesDialog={rules:e,test:"",busy:!1}},this._discoveryPreviewMemo=null,this._decorImages=new xc(t,{decorSnap:(t,e)=>this._decorSnap(t,e),geometrySnapshot:()=>this._geometrySnapshot(),clearFurniturePreview:()=>this._clearFurniturePreview(),recordGeometry:(t,e)=>this._recordGeometry(t,e),saveConfig:()=>this._saveConfig(),saveShape:()=>this._decorSaveShape(),setGuardReplace:t=>{this._decorAssetGuardReplace=t},furnShiftDetach:()=>this._furnShiftDetach(),furnPick:t=>this._furnPick(t),furnFieldValue:t=>this._furnFieldValue(t),furnFieldToCm:t=>this._furnFieldToCm(t)}),this._radarSetup=new hh({hass:()=>t.hass,requestUpdate:()=>t.requestUpdate(),t:(e,s)=>t._t(e,s),configFromDraft:nh,apply:e=>{t._markerDialog&&(t._markerDialog={...t._markerDialog,radar:e,radarEligible:!0,radarTouched:!0,radarRemove:!1})},confirmDiscard:()=>t._confirmDanger((t=>({key:"discard-radar-setup",kind:"warning",title:t("radar.discard_setup_title"),message:t("radar.discard_setup"),confirmLabel:t("btn.close"),cancelLabel:t("btn.cancel")}))(e=>t._t(e)))}),t._editorSecondary=new cc({root:()=>t.renderRoot,requestUpdate:()=>t.requestUpdate(),updateComplete:()=>t.updateComplete,clearTip:()=>{t._tip=null}}),t._resize=new an}_routeLiveEditorUpdate(t,e){const s=Vo(this.host,t,e);return!s&&this.host._resize.preview&&(this._resizeBaseFrameStable=!1),s}_commitLiveEditor(){!function(t){const e=t,s=qo(t);s.raf&&"function"==typeof cancelAnimationFrame&&cancelAnimationFrame(s.raf),s.raf=0,Xo(s);const i=e.renderRoot?.querySelector("[data-hp-live-editor]");i&&c(l,i);const o=e.renderRoot?.querySelector("[data-hp-live-editor-html]");if(o){const t=e._viewOr(e._baseVb());c(e._renderLiveEditorMeasurements(t),o)}Uo(s,s.requestedRevision)}(this.host)}_disposeLiveEditor(){this._radarSetup.reset(),function(t){Lo(t);const e=Bo.get(t);e&&(e.raf&&"function"==typeof cancelAnimationFrame&&cancelAnimationFrame(e.raf),Xo(e),Uo(e,e.requestedRevision),Bo.delete(t))}(this.host)}_cancelRadarSetup(){this._radarSetup.interrupt()}async _whenLiveEditorSettled(){await this.host.updateComplete,await function(t){const e=Bo.get(t);if(!e||!e.raf||e.paintedRevision>=e.requestedRevision)return Promise.resolve();const s=e.requestedRevision;return new Promise(t=>e.waiters.push({revision:s,resolve:t}))}(this.host)}_queuePointerMove(t,e){Ho(this.host,t,e)}_flushPointerMove(t){Oo(this.host,t)}_cancelPointerMove(t){Lo(this.host,t)}_help(t){const e=`${t}.aria`,s=a(this.host.hass,this.host._config?.language);return ce(s,t)&&ce(s,e)?h``:l}_setMode(t,e=!0){t!==this.host._mode&&this.host._cancelDangerConfirm(),this.host._endTabDrag(),this._clearFurniturePreview(),this.host._pendingNavMode=null;const s=this.host._spaceModel();if(!s)return this.host._cancelModeTransition(!1),void(this.host._mode="view");if(this.host._kiosk&&"view"!==t)return;if(this.host._mode===t){if(!e&&"view"===t&&this.host._modeTransitionBusy){const e=this.host._currentModeVisual(t),s=this.host._modeTransitionTargetZoom,i=this.host._modeTransitionTargetCenterX,o=this.host._modeTransitionTargetCenterY;this.host._cancelModeTransition(!1),this.host._commitViewModeAtomic(e,s,i,o)}return}if("devices"===this.host._mode&&this.host._cancelDeviceDrag(),this.host._bootSoftCancel(),("plan"===t||"decor"===t)&&!this.host._norm)return void this.host._showToast(this.host._t("toast.markup_needs_server"));if(this.host._wallFaceBatch&&this._roomDialogCancel(),"plan"===this.host._mode&&"draw"===this.host._tool&&!this._finishWallChain())return;this.host._clearTransientHover(!0),this.host._cancelDevicePressFeedback();const i=this.host._mode,o=this.host._effectiveProjection(),a=this.host._currentModeVisual(i),n=this.host._modeTransitionBusy,r=a&&"view"!==i&&"view"!==t?{...a,toolbarContentOpacity:this.host._reducedMotion?1:.35}:a;this.host._cancelModeTransition(!1),this.host._editorSecondary.closeForNavigation(),(this.host._decorMove||this.host._dtDrag||this.host._bdDrag)&&this._cancelDecorGesture();const l=!s.bg&&"view"===t!=("view"===i),h=n&&"view"===i&&"view"!==t?this.host._modeTransitionEditorCamera:null;let c=h?.zoom??(n?this.host._modeTransitionTargetZoom:this.host._zoom),d=h?h.centerX:n?this.host._modeTransitionTargetCenterX:r?.viewport.centerX,p=h?h.centerY:n?this.host._modeTransitionTargetCenterY:r?.viewport.centerY;if("view"===i&&"view"!==t&&!n){const e=this.host._view;if(this.host._viewModeSnap={space:this.host._space,zoom:this.host._zoom,cx:e?this.host._logicalViewCenter(o)?.x:void 0,cy:e?this.host._logicalViewCenter(o)?.y:void 0,w:"flat"===o?e?.w:void 0},"iso"===o){const e=this.host._logicalViewCenter("iso");d=e?.x,p=e?.y,this.host._view=null,this.host._mode=t,this.host._applyView(this.host._zoom,e?.x,e?.y)}l&&(c=1,d=void 0,p=void 0)}if(this.host._mode=t,"devices"===i&&"devices"!==t&&(this.host._showHidden=!1,this.host._deviceInbox=null,this.host._deviceInboxReturn=null,this.host._deviceInboxMemo=null),this.host._editorChromeMode="view"===t?i:t,"view"===t){"view"===i||n||(this.host._modeTransitionEditorCamera={zoom:this.host._zoom,centerX:r?.viewport.centerX,centerY:r?.viewport.centerY});const t=this.host._viewModeSnap;if(t&&t.space===this.host._space){c=t.zoom;const e=this.host._labsIso&&"iso"===this.host._viewPreference[this.host._space]?"iso":"flat",s=null!=t.cx&&null!=t.cy&&"iso"===e?de([t.cx,t.cy],0):null;d=s?.[0]??t.cx,p=s?.[1]??t.cy}else t&&(c=this.host._zoomBySpace[this.host._space]||1,d=void 0,p=void 0)}else this.host._modeTransitionEditorCamera={zoom:c,centerX:d,centerY:p};this.host._modeTransitionTargetZoom=c,this.host._modeTransitionTargetCenterX=d,this.host._modeTransitionTargetCenterY=p,("iso"===o||"view"===t&&this.host._labsIso&&"iso"===this.host._viewPreference[this.host._space])&&(this.host._modeTransitionForceAtomic=!0);const u=++this.host._modeTransitionRequest;e?r?(this.host._modeTransitionPreparing=!0,this.host._modeTransitionVisual=r,this.host._prepareModeTransition(u,r,t,c,d,p)):(this.host._modeTransitionPreparing=!1,this.host._modeTransitionVisual=null,this.host._zoom=c,this.host._view=null,requestAnimationFrame(()=>{this.host.isConnected&&u===this.host._modeTransitionRequest&&this.host._mode===t&&(this.host._applyView(c,d,p),"view"===t&&(this.host._viewModeSnap=null,this.host._modeTransitionEditorCamera=null),this.host.requestUpdate())})):"view"===t&&this.host._commitViewModeAtomic(r,c,d,p),this.host._path=[],this._clearPlanSnapHover(),this._clearOpeningPlacement(!0),this.host._tool="draw",this.host._mergeSel=null,this.host._mergeDialog=null,this.host._splitSel=null,this.host._pendingSplit=null,this.host._selId=null,this.host._physicalSel=null,this.host._physicalDialog=null,this.host._physicalDrag=null,this._rszResetController(),this.host._tip=null,this.host._hoverRoom=null,this.host._decorDraft=null,this.host._decorSel=null,this.host._decorMove=null,this.host._backdropDialog=null,this.host._decorTool="select",this.host._bdDrag=null,this.host._dtDrag=null,this.host._dtBox=null,"plan"===t&&this._primeDrawWallField(),this.host._saveNav()}_primeDrawWallField(){null===this.host._drawWallField&&(this.host._drawWallField=pe(ct,this.host._imperial))}_showPhysicalRange(t=this.host._drawWallMaxCm,e=0){this.host._showToast(this.host._t("toast.physical_range",{min:pe(e,this.host._imperial),max:pe(t,this.host._imperial),unit:this.host._t(this.host._imperial?"wallthick.unit_in":"wallthick.unit_cm")}))}_mergeSpacePartitions(t,e){const s=t?.partitions||[];if(s.length<2)return 0;const i=sl(s,{pitch:N,seedIds:e,geometry:ol(t)});return i.merged?(t.partitions=i.partitions,il(t.openings,t.partitions,i.openingMoves,{coordScale:Xc,cellCm:this.host._cellCm,gridPitch:this.host._gridPitch}),i.merged):0}_finalizeWallChainPartitions(t){if(!t.length)return!0;const e=this.host._curSpaceCfg,s=this.host._spaceModel(),i=this._geometrySnapshot();if(!e||!s||!i)return!1;const o=t.map(t=>rr(e,t)).find(Boolean)||null,a={path:this.host._path.map(t=>[...t]),chainId:this.host._activeWallChainId,ids:[...this.host._activeWallChainPartitionIds],cms:[...this.host._wallChainSegmentCms],redo:this.host._wallChainRedo.map(t=>({...t,point:[...t.point]})),closingCm:this.host._closingWallCm};let n;try{n=Lc(e,s,this.host._openCuts(),t,{pitch:this.host._wallKeyPitch,cellCm:this.host._cellCm,gridPitch:this.host._gridPitch,coordScale:Xc})}catch{return this.host._showToast(this.host._t("toast.geometry_unsafe")),!1}if(!n.report.changed)return!0;const r=this.host._serverCfg,l=r?.spaces?.findIndex(t=>t.id===i.spaceId)??-1;if(l<0)return!1;r.spaces[l]=n.space;const h=function(t,e,s,i){const{host:o}=t,a=o._serverCfg,n=()=>t._commitPhysicalGeometry(e,s,[],!1);if(!s||!a||!i||10!==Number(a.model_version||0))return n();let r;try{r=jn(a).config}catch(e){return t._clearGeometryGesture(),t._restoreGeometryStateLocal(s),t._showWallModelMigrationBlocked(e),!1}const l=r.spaces.find(t=>t.id===s.spaceId),h=JSON.parse(JSON.stringify(a));if(!l||!t._restoreGeometryStateInConfig(h,s))return n();const c=h.spaces.find(t=>t.id===s.spaceId),d=lr(l,i),p=lr(c,i);if(!d||!p)return n();const u={...r,spaces:[d.space]},_={...h,spaces:[p.space]};let m=null,g=!1;try{const t=o._path.length>=2?o._path.map(t=>[t[0]/hr,t[1]/hr]):[];g=$n(l)<=$n(s,t)&&o._checkSpacePhysicalGeometry(u,s.spaceId,t=>{m=t}).ok}catch{g=!1}if(!g)return cr(t,s);const f=t._junctionLimitsIntroduced(u,_,s.spaceId,m,d.roomIds);if(f.length)return t._clearGeometryGesture(),t._restoreGeometryStateLocal(s),o._showToast(t._junctionLimitLabel(f[0])),!1;qn(a,r);const b=a.spaces.find(t=>t.id===s.spaceId),v=o._pendingPhysicalWrites.get(s.spaceId);return o._pendingPhysicalWrites.set(s.spaceId,{before:v?.before||s,fingerprint:K(b)}),t._saveConfig(),!0}(this,this.host._t("history.wall_segment"),i,o);return!!h||(this.host._path=a.path,this.host._activeWallChainId=a.chainId,this.host._activeWallChainPartitionIds=a.ids,this.host._wallChainSegmentCms=a.cms,this.host._wallChainRedo=a.redo,this.host._closingWallCm=a.closingCm,!1)}_finishWallChain(){return!("draw"===this.host._tool&&!this.host._wallFaceBatch&&!this.host._roomDialog)||!!this._finalizeWallChainPartitions(this.host._activeWallChainPartitionIds)&&(this.host._path=[],this.host._activeWallChainId=null,this.host._activeWallChainPartitionIds=[],this.host._wallChainSegmentCms=[],this.host._wallChainRedo=[],this.host._closingWallCm=null,this._clearPlanSnapHover(),!0)}_activateMarkupTool(t){t!==this.host._tool&&(this.host._wallFaceBatch&&this._roomDialogCancel(),("draw"!==this.host._tool||this._finishWallChain())&&(this._cancelPath(),"resize"===this.host._tool&&(this.host._resize.dragging?this._rszCancelDrag():this.host._resize.reset()),this.host._tool=t,"resize"===t&&this.host._resize.selectRoom(null),"wallthick"===t&&(this.host._wallDialog=null)))}_limitReached(t){const e=this.host._curSpaceCfg;if(!e)return!0;const s="partition"===t?(e.partitions||[]).length>=Zc:(e.wall_columns||[]).length>=500;return s&&this.host._showToast(this.host._t("toast.physical_limit")),s}_svgPoint(t){const e=this.host.renderRoot.querySelector(".stage").getBoundingClientRect();return this.host._screenToVb(t.clientX-e.left,t.clientY-e.top)}_snap(t){const e=this.host._gridPitch;return[ue(_e(t[0],e)),ue(_e(t[1],e))]}_snapDrawPoint(t,e=!1){const s=this.host._path[this.host._path.length-1],i=e&&s?me(s,t,this.host._gridPitch,ho):t;return this._snap(i)}_planSnapOpeningCuts(t,e){if(!this.host._openingsR.length)return[];const s=this.host._openingWallIndexFor(t,e).value,i=[];for(const e of this.host._roomWallOpeningInputs(this.host._openingsR,t)){const t=ft(s,e);if(!t.negative&&!t.positive)continue;const o=e.angle*Math.PI/180,a=Math.cos(o)*e.length/2,n=Math.sin(o)*e.length/2;i.push([e.x-a,e.y-n,e.x+a,e.y+n])}return i}_planSnapGeometrySnapshot(){const t=this.host._spaceModel();if(!t)return{key:`${this.host._space}|empty`,value:{segments:[],endpoints:[]}};const e=[this.host._space,this.host._cfgEpoch,t.rooms.length,t.partitions.length].join("|");if(this.host._planSnapGeometryCache?.key===e)return this.host._planSnapGeometryCache;const s=this.host._openCuts(),i=yh({space:t,roomCuts:this._planSnapOpeningCuts(t,s),partitionCuts:this._partitionOpeningCuts(t),epsilon:2e-4*this.host._gridPitch});return this.host._planSnapGeometryCache={key:e,value:i},this.host._planSnapGeometryCache}_hiddenWallDiagnosticSnapshot(){const t=this.host._spaceModel();if(!t)return{key:`${this.host._space}|hidden-empty`,value:{segments:[],endpoints:[]}};const e=["hidden",this.host._space,this.host._cfgEpoch,t.rooms.length,t.partitions.length].join("|");if(this.host._hiddenWallDiagnosticCache?.key===e)return this.host._hiddenWallDiagnosticCache;const s=vh({space:t,epsilon:2e-4*this.host._gridPitch});return this.host._hiddenWallDiagnosticCache={key:e,value:s},this.host._hiddenWallDiagnosticCache}_planStructuralGeometrySnapshot(){const t=this.host._spaceModel();if(!t)return{key:`${this.host._space}|structural-empty`,value:{segments:[],endpoints:[]}};const e=["structural",this.host._space,this.host._cfgEpoch,t.rooms.length,t.partitions.length].join("|");if(this.host._planStructuralGeometryCache?.key===e)return this.host._planStructuralGeometryCache;const s=yh({space:t,epsilon:2e-4*this.host._gridPitch});return this.host._planStructuralGeometryCache={key:e,value:s},this.host._planStructuralGeometryCache}_planSnapContextKey(t){const e=this.host._path[0],s=this.host._path[this.host._path.length-1];return[t,this.host._tool,this.host._path.length,e?`${e[0]},${e[1]}`:"",s?`${s[0]},${s[1]}`:""].join("|")}_resolvePlanDrawPoint(t,e){const s=this._planSnapGeometrySnapshot(),i=this.host._path[this.host._path.length-1],o="draw"===this.host._tool&&this.host._path.length>=3?[{point:this.host._path[0],key:"closure:first-point"}]:[],a=this.host._path.length>1?this.host._path.slice(1):i?[i]:[],n={tolerance:this._cssPxToRender(12),distinguishTolerance:this._cssPxToRender(8),gridStep:this.host._gridPitch,excludePoints:a,extraEndpoints:o,epsilon:2e-4*this.host._gridPitch},r=e&&i?Mh(s.value,t,{...n,anchor:i}):function(t,e,s){if(!(dh(e)&&s.tolerance>=0))return{kind:"none",candidate:null,conflicts:[]};const i=s.epsilon??ch,o=s.excludePoints||[],a=xh(kh(t,e,s),s.distinguishTolerance||0);if(a)return a;let n=null;for(const a of t.segments){const t=[a.a[0],a.a[1],a.b[0],a.b[1]],r=Ot([e[0],e[1]],t);if(r>s.tolerance)continue;const l=Sh(a,e,s.gridStep);!$h(l,o,i)&&wh(r,a.key,n)&&(n={kind:"line",point:l,key:a.key,distance:r,segment:a})}return n?{kind:"resolved",candidate:n,conflicts:[]}:{kind:"none",candidate:null,conflicts:[]}}(s.value,t,n),l="resolved"===r.kind?r.candidate:null,h=l?[...l.point]:this._snapDrawPoint(t,e),c=i?ge(i,h):h;return{point:c,candidate:l&&q(c,l.point)?l:null,conflicts:"ambiguous"===r.kind?r.conflicts:[],ambiguous:"ambiguous"===r.kind,contextKey:this._planSnapContextKey(s.key)}}_clearPlanSnapHover(t=!0){this.host._planSnapHover=null,this._syncPlanSnapActiveMarker(null),this._syncPlanSnapConflictMarkers([]),t&&(this.host._cursorPt=null)}_samePt(t,e){return q(t,e)}_dropLegacySegments(t=this.host._serverCfg){for(const e of t?.markers||[])"ripple"===e.display&&(e.display="icon_ripple");for(const e of t?.spaces||[]){delete e.segments;const t=new Set,s=e=>"string"==typeof e&&e.length>=1&&e.length<=64&&!t.has(e),i=e=>(t.add(e),!0),o=t=>Array.isArray(t)&&2===t.length&&t.every(t=>Number.isFinite(Number(t))&&Math.abs(Number(t))<=Ut);if(Array.isArray(e.partitions)&&(e.partitions=e.partitions.filter(t=>t&&s(t.id)&&o(t.a)&&o(t.b)&&Math.hypot(t.a[0]-t.b[0],t.a[1]-t.b[1])>1e-9&&i(t.id)).map(t=>({...t,cm:Number.isFinite(Number(t.cm))?Math.max(0,Math.min(100,Number(t.cm))):15})),e.partitions.length||delete e.partitions),Array.isArray(e.wall_columns)&&(e.wall_columns=e.wall_columns.filter(t=>t&&s(t.id)&&o(t.center)&&i(t.id)).map(t=>({id:t.id,shape:"circle"===t.shape?"circle":"square",center:[Number(t.center[0]),Number(t.center[1])],cm:ee(Number(t.cm)||15),..."circle"===t.shape?{}:{angle:fe(t.angle)}})),e.wall_columns.length||delete e.wall_columns),Array.isArray(e.walls)){const t=be(Tt({spaces:[e]}),e.id),s=t?ve(e,t,Xc,.02*kt).contour.map(t=>t.map(t=>t/Xc)):L(e.open_spans).map(t=>[t.a[0],t.a[1],t.b[0],t.b[1]]);e.walls=xt(e.walls,e.rooms||[],N,1,s),e.walls.length||delete e.walls}}}_rollbackRejectedPhysicalWrites(t){if(!this.host._serverCfg||!t.length)return!1;let e=!1;for(const[s]of t){const t=this.host._pendingPhysicalWrites.get(s);t&&(e=this._restoreGeometryStateInConfig(this.host._serverCfg,t.before)||e,this.host._pendingPhysicalWrites.delete(s))}return!!e&&(this._clearGeometryGesture(),this.host._geometryHistory.clear(),this.host._cfgEpoch++,this.host._modelCache=null,this.host._wallUnionCache=null,this.host._physicalBodiesCache=null,this.host._frame=null,this.host._regSignature="",this.host._adoption.refreshConfigFingerprint(),this.host._maybeRebuildDevices(),this.host.requestUpdate(),!0)}async _reloadRejectedPhysicalWrite(){const t=this.host._writeChain;await t.catch(()=>{}),await this.host._reloadConfigOnly(!0)}_prepareConfigCandidate(t){return this._dropLegacySegments(t),ye(t)}_writeConfig(t=null){this.host._writesPending++,this.host._writeChain=$e(this.host._writeChain,async()=>{if(!this.host._serverCfg)return;const e=zt(this.host._serverCfg),s=this._prepareConfigCandidate(this.host._serverCfg),i=zt(s);t&&e===t.attemptedFingerprint&&Object.assign(t,{revision:this.host._cfgRev,attempted:s,attemptedFingerprint:i});const o=[...this.host._pendingPhysicalWrites.entries()];for(const[t,e]of o){const i=s.spaces.find(e=>e.id===t),o=K(i);if(o===e.fingerprint)continue;let a=!1;try{a=this.host._checkSpacePhysicalGeometry(s,t).ok}catch{a=!1}if(!a)throw this._restoreGeometryStateLocal(e.before),this.host._pendingPhysicalWrites.delete(t),this.host._geometryHistory.clear(),this.host._showToast(this.host._t("toast.geometry_unsafe")),Object.assign(new Error("unsafe wall geometry"),{code:"geometry-unsafe"});e.fingerprint=o}this.host._adoption.stageConfigCandidate(s);try{await this.host._sendConfigCandidate(s)}catch(t){if(!this._rollbackRejectedPhysicalWrites(o))throw t;const e=t&&"object"==typeof t?t:Object.assign(new Error(String(t)),{cause:t});throw e.physicalGeometryRolledBack=!0,e}for(const[t,e]of o)this.host._pendingPhysicalWrites.get(t)?.fingerprint===e.fingerprint&&this.host._pendingPhysicalWrites.delete(t)});return this.host._writeChain.finally(()=>{this.host._writesPending--})}_saveConfig(){this.host._cfgEpoch++,this.host._saveConfigDebounced()}_geometrySnapshotFromConfig(t,e){const s=t?.spaces?.find(t=>t.id===e);if(!s)return null;const i=t=>JSON.parse(JSON.stringify(t)),o={};for(const t of["plan_x","plan_y","plan_scale","plan_scale_x","plan_scale_y","plan_angle"])void 0!==s[t]&&(o[t]=s[t]);return{spaceId:e,rooms:i(s.rooms||[]),...Array.isArray(s.openings)?{openings:i(s.openings)}:{},...Array.isArray(s.walls)?{walls:i(s.walls)}:{},...Array.isArray(s.wall_segments)?{wall_segments:i(s.wall_segments)}:{},...Array.isArray(s.open_spans)?{open_spans:i(s.open_spans)}:{},...Array.isArray(s.partitions)?{partitions:i(s.partitions)}:{},...Array.isArray(s.wall_columns)?{wall_columns:i(s.wall_columns)}:{},...Array.isArray(s.decor)?{decor:i(s.decor)}:{},plan_transform:o}}_geometrySnapshot(t=this.host._space){return this._geometrySnapshotFromConfig(this.host._serverCfg,t)}_recordGeometry(t,e){if(!e)return;const s=this._geometrySnapshot(e.spaceId);s&&JSON.stringify(e)!==JSON.stringify(s)&&(e.wallChainSeedIds&&(s.wallChainSeedIds=[...this.host._activeWallChainPartitionIds]),e.roomReferences&&(s.roomReferences=jc(this.host._serverCfg?.markers||[],e.roomReferences.map(t=>t.markerId))),this.host._geometryHistory.push({name:t,before:e,after:s}),this.host.requestUpdate())}_restoreGeometryStateInConfig(t,e,s=!1){const i=t?.spaces?.find(t=>t.id===e.spaceId);if(!i)return!1;const o=t=>JSON.parse(JSON.stringify(t)),a=new Map((i.rooms||[]).map(t=>[t.id,t]));if(i.rooms=o(e.rooms),s)for(const t of i.rooms){const e=a.get(t.id);!Array.isArray(t.wall_ids)&&Array.isArray(e?.wall_ids)&&e.wall_ids.length===t.poly?.length&&(t.wall_ids=o(e.wall_ids))}const n=(t,e)=>{void 0!==e?i[t]=o(e):s&&"wall_segments"===t||delete i[t]},r=new Map((i.openings||[]).map(t=>[t.id,t]));if(n("openings",e.openings),n("walls",e.walls),n("wall_segments",e.wall_segments),n("open_spans",e.open_spans),n("partitions",e.partitions),n("wall_columns",e.wall_columns),n("decor",e.decor),s)for(const t of i.openings||[]){const e=r.get(t.id);t.host||"wall"!==e?.host?.kind||(t.host=o(e.host))}for(const t of["plan_x","plan_y","plan_scale","plan_scale_x","plan_scale_y","plan_angle"])delete i[t];return Object.assign(i,o(e.plan_transform||{})),e.roomReferences&&(t.markers||=[],function(t,e){const s=new Map((t||[]).map(t=>[t?.id,t]));for(const t of e){const e=s.get(t.markerId);e&&(t.roomIdPresent?e.room_id=Bc(t.roomId):delete e.room_id,t.segmentMapPresent?(e.vacuum&&"object"==typeof e.vacuum&&!Array.isArray(e.vacuum)||(e.vacuum={}),e.vacuum.segment_map=Bc(t.segmentMap)||{}):e.vacuum&&"object"==typeof e.vacuum&&!Array.isArray(e.vacuum)&&(delete e.vacuum.segment_map,t.vacuumPresent||0!==Object.keys(e.vacuum).length||delete e.vacuum))}}(t.markers,e.roomReferences)),!0}_canonicalWallChainHistoryState(t){if(this.host._activeWallChainId||!t.wallChainSeedIds?.length)return t;if(!this.host._serverCfg)return null;const e=JSON.parse(JSON.stringify(this.host._serverCfg));if(!this._restoreGeometryStateInConfig(e,t))return null;let s;try{s=jn(e).config}catch{return null}const i=s.spaces?.find(e=>e.id===t.spaceId),o=be(Tt(s),t.spaceId);if(!i||!o)return null;const a=Lc(i,o,we(i,o,kt,Xc),t.wallChainSeedIds,{pitch:N,cellCm:Number(i.cell_cm)>0?Number(i.cell_cm):5,gridPitch:kt,coordScale:Xc}),n=s.spaces.findIndex(e=>e.id===t.spaceId);let r;s.spaces[n]=a.space;try{r=jn(s).config}catch{return null}const l=this._geometrySnapshotFromConfig(r,t.spaceId);return l?(l.wallChainSeedIds=[...t.wallChainSeedIds],t.roomReferences&&(l.roomReferences=JSON.parse(JSON.stringify(t.roomReferences))),l):null}_restoreGeometryStateLocal(t){return!!this._restoreGeometryStateInConfig(this.host._serverCfg,t)&&(this.host._cfgEpoch++,this.host._modelCache=null,this.host._wallUnionCache=null,this.host._physicalBodiesCache=null,this.host._frame=null,this.host.requestUpdate(),!0)}_wallModelBlockerLabel(t){const e=t instanceof un?t.reason:"invalid-room";return this.host._t(`wall_model.reason.${e}`)}_hasLegacyZeroWallFields(t=this.host._serverCfg){return(t?.spaces||[]).some(t=>Array.isArray(t?.open_spans)&&t.open_spans.length>0||(t?.rooms||[]).some(t=>Array.isArray(t?.open_to)&&t.open_to.length>0))}_showWallModelMigrationBlocked(t){const e=this._hasLegacyZeroWallFields()?"toast.zero_wall_migration_blocked":"toast.wall_model_migration_blocked";this.host._showToast(this.host._t(e,{reason:this._wallModelBlockerLabel(t)}))}_limitSegmentsOf(t){const e=[];for(const s of t?.wall_segments||[])s?.a&&s?.b&&e.push({id:String(s.id||""),a:s.a,b:s.b,cm:Number(s.cm)});for(const s of t?.partitions||[])s?.a&&s?.b&&e.push({id:String(s.id||""),a:s.a,b:s.b,cm:Number(s.cm)});return e}_junctionLimitViolations(t,e,s,i){const o=(t?.spaces||[]).find(t=>t?.id===e);return o?function(t,e,s,i,o){const a=(t?.spaces||[]).find(t=>t?.id===e);if(!a)return[];const n=Number(a.cell_cm)>0?Number(a.cell_cm):5,r=[...Tr(s),...Nr(s,n,N),...Hr(s,n,N)];let l=i?.multiWallNodes||null;if(!l)try{l=tt(a.rooms||[],a.walls||[],[],N,n,N,1)}catch{l=null}const h=i&&"lightweight"!==i.status?i:null;let c="ok"===h?.status||"degraded-extra"===h?.status?h.roomGeom:null;const d=null===i||"lightweight"===i?.status;if(!c&&!d&&l?.nodes.length)try{const t=et(a.rooms||[],a.walls||[],[],[],N,n,N,1);c="ok"===t?.status||"degraded-extra"===t?.status?t.roomGeom:null}catch{c=null}for(const t of a.rooms||[]){const e=String(t?.id||"");if(!e||o&&!o.has(e))continue;let s=null;try{s=st(a.rooms||[],e,a.walls||[],[],N,n,N,1,d?null:c??void 0,l)}catch{s=null}r.push(...Or(e,s,n,N))}return r}(t,e,this._limitSegmentsOf(o),s,i):[]}_junctionLimitLabel(t){const e=t=>String(Math.round(10*t)/10);return this.host._t(`junction.limit_${t.rule}`,{actual:e(t.actual),limit:e(t.limit)})}_junctionLimitsIntroduced(t,e,s,i,o){const a=o?.length?new Set(o):void 0;let n;const r=(e.spaces||[]).find(t=>t?.id===s);let l="";try{l=K(r)}catch{l=""}const h=!a&&e&&"object"==typeof e?this._junctionBaselineCache.get(e):void 0;if(h&&l&&h.fingerprint===l&&h.spaceId===s&&(n=h.violations),!n){try{const t=Number(e?.model_version||0)>=10?e:jn(e).config;n=this.host._junctionLimitViolations(t,s,a?null:void 0,a)}catch{return[]}!a&&e&&"object"==typeof e&&l&&this._junctionBaselineCache.set(e,{spaceId:s,fingerprint:l,violations:n})}let c=[],d=n;try{c=this.host._junctionLimitViolations(t,s,i,a),a&&(d=n.filter(t=>"clearance"!==t.rule||a.has(t.subject)))}catch{return[{rule:"check_failed",subject:s,actual:0,limit:0}]}return Lr(c,d)}_commitPhysicalGeometry(t,e,s=[],i=!0){if(!e||!this.host._serverCfg)return!1;const o=this.host._serverCfg,a=t=>{const s=t?.spaces?.find(t=>t.id===e.spaceId);return s?{...t,spaces:[s]}:t},n=this._geometrySnapshotFromConfig(o,e.spaceId),r=o.spaces.find(t=>t.id===e.spaceId);if(!r||K(e)===K(r))return!1;let l,h=!1;try{h=this.host._checkSpacePhysicalGeometry(a(o),e.spaceId).ok}catch{h=!1}if(!h)return this._clearGeometryGesture(),this._restoreGeometryStateLocal(e),this.host._showToast(this.host._t("toast.geometry_unsafe")),!1;let c=e;try{if(Number(o.model_version||0)<9){const t=JSON.parse(JSON.stringify(o));if(!this._restoreGeometryStateInConfig(t,e))throw new un("invalid-room",e.spaceId);const s=jn(t).config;c=this._geometrySnapshotFromConfig(s,e.spaceId)||e,c.wallChainSeedIds=e.wallChainSeedIds,c.roomReferences=e.roomReferences;const i=JSON.parse(JSON.stringify(s));if(!n||!this._restoreGeometryStateInConfig(i,n,!0))throw new un("invalid-room",e.spaceId);const a=s.spaces.find(t=>t.id===e.spaceId),r=i.spaces.find(t=>t.id===e.spaceId);if(!Array.isArray(n.wall_segments)&&JSON.stringify(e.rooms)===JSON.stringify(n.rooms))for(const t of r?.wall_segments||[])t.cm=U(n.walls,t.a,t.b,N,1);const h=((t,e,s)=>{const i=new Map,o=new Map((t?.rooms||[]).map(t=>[t.id,t])),a=new Map((e||[]).map(t=>[t.id,t])),{rooms:n}=zn(s,In(t));for(const t of n){const e=a.get(t.id),n=o.get(t.id),r=H(e),l=(s.rooms||[]).find(e=>e.id===t.id),h=H(l),c=H(n);if(r&&h&&c&&r.length===h.length&&c.length===n?.wall_ids?.length&&t.poly.length===t.wall_ids.length)for(let e=0;e{const o=[];for(let a=0;apn||kn(r,s,i)>pn)continue;const l=wn(n,s,i),h=wn(r,s,i);l<-1e-9||h>1+pn||h<=l+pn||o.push({start:l,id:e[a]})}return o.sort((t,e)=>t.start-e.start)},o=s(c,n.wall_ids,r[e],r[(e+1)%r.length]),a=s(t.poly,t.wall_ids,h[e],h[(e+1)%h.length]);if(o.length&&o.length===a.length)for(let t=0;tt.id===e.spaceId),i=this.host._path.length>=2?this.host._path.map(t=>[t[0]/Xc,t[1]/Xc]):[];i.push(...s.map(t=>[t[0],t[1]])),d=$n(t)<=$n(c,i)&&this.host._checkSpacePhysicalGeometry(a(l),e.spaceId).ok}catch{d=!1}if(!d)return this._clearGeometryGesture(),this._restoreGeometryStateLocal(e),this.host._showToast(this.host._t("toast.geometry_unsafe")),!1;const p=JSON.parse(JSON.stringify(o));this._restoreGeometryStateInConfig(p,e);const u=this._junctionLimitsIntroduced(l,p,e.spaceId);if(u.length)return this._clearGeometryGesture(),this._restoreGeometryStateLocal(e),this.host._showToast(this._junctionLimitLabel(u[0])),!1;qn(o,l),i&&this._recordGeometry(t,c);const _=o.spaces.find(t=>t.id===e.spaceId),m=this.host._pendingPhysicalWrites.get(e.spaceId);return this.host._pendingPhysicalWrites.set(e.spaceId,{before:m?.before||c,fingerprint:K(_)}),this._saveConfig(),!0}_clearGeometryGesture(){this._clearFurniturePreview(),this.host._path=[],this._clearPlanSnapHover(),this._clearOpeningPlacement(!1),this.host._mergeSel=null,this.host._mergeDialog=null,this.host._splitSel=null,this.host._pendingSplit=null,this.host._wallFaceBatch=null,this.host._wallRepairDiagnostic=null,this.host._roomDeleteDialog=null,this.host._wallDialog=null,this.host._physicalDialog=null,this.host._physicalSel=null,this.host._physicalDrag=null,this.host._physicalRotate=null,this.host._activeWallChainId=null,this.host._activeWallChainPartitionIds=[],this.host._wallChainSegmentCms=[],this.host._wallChainRedo=[],this.host._closingWallCm=null,this.host._openingDialog=null,this._rszResetController(),this.host._decorDraft=null,this.host._decorMove=null,this.host._dtDrag=null,this.host._bdDrag=null}_stagePointerCancel(t){return clearTimeout(this.host._kioskHoldTimer),this.host._swipeStart?.id===t.pointerId&&(this.host._swipeStart=null),this.host._furnTouchPending?.pid===t.pointerId?(this._clearFurniturePreview(),this.host._pointers.delete(t.pointerId),void this.host.requestUpdate()):this.host._physicalDrag?.pid!==t.pointerId&&this.host._physicalRotate?.pid!==t.pointerId?this.host._decorDraft?.pid===t.pointerId?(this.host._decorDraft=null,void this.host.requestUpdate()):void(this.host._decorMove?.pid!==t.pointerId&&this.host._dtDrag?.pid!==t.pointerId&&this.host._bdDrag?.pid!==t.pointerId?("opening"===this.host._tool?(this.host._cursorPt=null,this._clearOpeningPlacement(!1)):"draw"===this.host._tool&&this._clearPlanSnapHover(),this.host._pointers.delete(t.pointerId),this.host._pointers.size<2&&(this.host._pinchStart=null),0===this.host._pointers.size&&(this.host._panStart=null,this.host._panLock=null),this.host._viewportGestureDirty&&0===this.host._pointers.size&&(this.host._viewportGestureDirty=!1,this.host.requestUpdate())):this._cancelDecorGesture()):void this._cancelPhysicalGesture()}_applyGeometryState(t,e=!1){const s=this._canonicalWallChainHistoryState(t);if(!s||!this.host._canCommitSpace(s.spaceId))return!1;const i=this._geometrySnapshot(s.spaceId);if(!i||!this._restoreGeometryStateLocal(s))return!1;const o=this.host._serverCfg,a=K(i)!==K(s);if(a){let t=!1;try{const i=o?this.host._checkSpacePhysicalGeometry(o,s.spaceId):null;t=!!i?.ok||!(!e||"wall-degraded-extra"!==i?.reason)}catch{t=!1}if(!t)return this._restoreGeometryStateLocal(i),this.host._showToast(this.host._t("toast.geometry_unsafe")),!1}let n;try{n=jn(o).config}catch(t){return this._restoreGeometryStateLocal(i),this._showWallModelMigrationBlocked(t),!1}if(a){let t=!1;try{const i=n?this.host._checkSpacePhysicalGeometry(n,s.spaceId):null;t=!!i?.ok||!(!e||"wall-degraded-extra"!==i?.reason)}catch{t=!1}if(!t)return this._restoreGeometryStateLocal(i),this.host._showToast(this.host._t("toast.geometry_unsafe")),!1;qn(o,n);const a=o?.spaces.find(t=>t.id===s.spaceId),r=this.host._pendingPhysicalWrites.get(s.spaceId);this.host._pendingPhysicalWrites.set(s.spaceId,{before:r?.before||i,fingerprint:K(a)})}else qn(o,n);return this._clearGeometryGesture(),this.host._space!==s.spaceId&&(this.host._commitSpace(s.spaceId),this.host._saveNav(),this.host._restoreZoom()),this.host._modelCache=null,this.host._frame=null,this.host._regSignature="",this.host._maybeRebuildDevices(),this._saveConfig(),this.host.requestUpdate(),!0}_roomAt(t){return this.host._spaceModel()?.rooms.find(e=>{const s=H(e);return!!s&&ke(t,s)})}_overlapRoom(t){return this.host._spaceModel()?.rooms.find(e=>{const s=H(e);return!!s&&R(t,s)})}_pointInRoom(t,e){return e.poly?xe(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(!Ta(t))return!0;const e=t.length,s=.001;for(let i=0;i=500)return this.host._showToast(this.host._t("toast.physical_limit")),!1;const t=this.host._curSpaceCfg;return!((t?.partitions||[]).length>=Zc)||(this.host._showToast(this.host._t("toast.physical_limit")),!1)}_markupClick(t){if(this.host._vacFit)return;if(!this.host._markup)return;const e=this.host._spaceModel();if(!e)return void this._clearGeometryGesture();if(this.host._suppressClick)return;if(this.host._drag||this.host._rlResize)return;const s=t.composedPath?.()||[];if(s.some(t=>t?.classList?.contains?.("roomlabel")||t?.classList?.contains?.("rlhandle")))return;if(s.some(t=>t?.classList?.contains?.("physical-hit")))return;const i=this._svgPoint(t);if("select"===this.host._tool)return void(this.host._physicalSel=null);if("resize"===this.host._tool){if(this.host._resize.dragging||s.some(t=>t?.classList?.contains?.("rszhandle")))return;const t=[...e.rooms].reverse().find(t=>this._pointInRoom(i,t));return this.host._resize.selectRoom(t?.id||null),void this.host.requestUpdate()}if("delroom"===this.host._tool)return void this._deleteRoomClick(i);if("opening"===this.host._tool)return void this._openingClick(i);if("merge"===this.host._tool)return void this._mergeClick(i);if("wallthick"===this.host._tool)return void this._wallThickClick(i);if("split"===this.host._tool)return void this._splitClick(i);if("column"===this.host._tool)return void this._columnClick(i);this.host._wallRepairDiagnostic=null;const o=this._resolvePlanDrawPoint(i,t.shiftKey);if(o.ambiguous)return this.host._planSnapHover={contextKey:o.contextKey,candidate:null,conflicts:o.conflicts},this._syncPlanSnapActiveMarker(null),this._syncPlanSnapConflictMarkers(o.conflicts),void this.host._showToast(this.host._t("toast.plan_snap_ambiguous"));let a=o.point;if(t.ctrlKey||t.metaKey){if(t.preventDefault(),this.host._path.length<3)return;a=ge(this.host._path[this.host._path.length-1],this.host._path[0])}if(!this.host._path.length){if(!t.shiftKey&&!o.candidate&&this._offerExistingWallFace(i))return;return this.host._activeWallChainId=`chain-${Date.now().toString(36)}`,this.host._activeWallChainPartitionIds=[],this.host._wallChainSegmentCms=[],this.host._wallChainRedo=[],void(this.host._path=[a])}const n=this.host._path[this.host._path.length-1];if(this._samePt(a,n))return;if(!this._canAppendWallPoint())return;const r=this.host._drawWallCm;if(null==r)return void this._showPhysicalRange(100);const l=this.host._curSpaceCfg;if(!l)return;const h=this.host._path.map(t=>[...t]),c=this.host._activeWallChainId,d=[...this.host._activeWallChainPartitionIds],p=[...this.host._wallChainSegmentCms],u=this._wallGraphSources([]),_=this._geometrySnapshot();_&&(_.wallChainSeedIds=[...d]);const m=`partition-${crypto.randomUUID?.()||`${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`}`;if(l.partitions||=[],l.partitions.push({id:m,a:[n[0]/Xc,n[1]/Xc],b:[a[0]/Xc,a[1]/Xc],cm:r}),this.host._path=[...this.host._path,a],this.host._wallChainSegmentCms=[...this.host._wallChainSegmentCms,r],this.host._activeWallChainPartitionIds=[...d,m],this.host._wallChainRedo=[],!dr(this,this.host._t("history.wall_segment"),_))return this.host._activeWallChainId=c,this.host._activeWallChainPartitionIds=d,this.host._path=h,void(this.host._wallChainSegmentCms=p);this._offerWallFaces(h,h.length-1,u)}_activeWallSourceKey(t){const e=this.host._activeWallChainPartitionIds[t],s=e?this._planStructuralGeometrySnapshot().value.segments.find(t=>"partition"===t.sourceKind&&t.sourceId===e):null;return s?`static:${s.key}`:`active:${this.host._activeWallChainId||"session"}:${t}`}_wallGraphSources(t){return this._planStructuralGeometrySnapshot().value.segments.map(t=>({a:t.a,b:t.b,key:`static:${t.key}`}))}_wallFaceGraph(t,e){const s=`${this.host._space}|${e}|${JSON.stringify(t)}`,i=this.host._wallFaceGraphCache.findIndex(t=>t.key===s);if(i>=0){const[t]=this.host._wallFaceGraphCache.splice(i,1);return this.host._wallFaceGraphCache.push(t),t.value}const o=Yh(t,e);return this.host._wallFaceGraphCache.push({key:s,value:o}),this.host._wallFaceGraphCache.length>4&&this.host._wallFaceGraphCache.shift(),o}_offerWallFaces(t,e=this.host._path.length-2,s){if(this.host._path.length<2||this.host._wallFaceBatch||this.host._roomDialog)return;const i=this.host._spaceModel();if(!i)return;const o=this._activeWallSourceKey(e),a=2e-4*this.host._gridPitch;let n,r;try{const e=s||this._wallGraphSources(t);r=this._wallGraphSources(this.host._path),n=function(t,e,s){const i=new Set(t.faces.map(t=>t.key));return e.faces.filter(t=>!i.has(t.key)&&t.sourceKeys.includes(s))}(this._wallFaceGraph(e,a),this._wallFaceGraph(r,a),o)}catch{return}if(!n.length){const t=lc(r,{requiredSourceKey:o,maxDistance:b(2,this.host._cellCm,this.host._gridPitch),gridStep:this.host._gridPitch,epsilon:a});return"ambiguous"===t.kind?(this.host._wallRepairDiagnostic=t.proposals[0]||null,void this.host._showToast(this.host._t(0===this.host._drawWallCm?"toast.zero_wall_ambiguous":"toast.wall_repair_ambiguous"))):void("repair"!==t.kind||this._overlapRoom(t.face.ring)||this._beginWallFaceBatch([{...t.face,repair:t.proposal}]))}for(const t of i.rooms){const e=H(t);if(!t.id||!e)continue;const s=Se(e,this.host._path,.02*this.host._gridPitch);if(!s)continue;const[i,o]=s,a=F(i)>=F(o)?i:o,r=a===i?o:i,l=[...n].sort((t,e)=>Math.abs(t.area-F(r))-Math.abs(e.area-F(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:a,newPoly:r},consumeAllActive:!0}])}const l=n.filter(t=>!(t.ring.length<3||this._contourSelfIntersects(t.ring))&&!this._overlapRoom(t.ring));l.length&&this._beginWallFaceBatch(l)}_beginWallFaceBatch(t){this.host._wallRepairDiagnostic=null,this.host._wallFaceBatch={candidates:[...t].sort((t,e)=>t.area-e.area||t.key.localeCompare(e.key)),index:0,decisions:[],activePath:this.host._path.map(t=>[...t]),activeCms:[...this.host._wallChainSegmentCms],activePartitionIds:[...this.host._activeWallChainPartitionIds]},this._clearPlanSnapHover(),this.host._nameSel="",this.host._areaSel="",this._resetRoomDialogFields(),this.host._roomDialog=!0}_offerExistingWallFace(t){if(this.host._path.length||this.host._wallFaceBatch||this.host._roomDialog)return!1;const e=2e-4*this.host._gridPitch;try{let s,i=Xh(this._wallFaceGraph(this._wallGraphSources([]),e),t,e);if(!i){const o=lc(this._wallGraphSources([]),{point:t,maxDistance:b(2,this.host._cellCm,this.host._gridPitch),gridStep:this.host._gridPitch,epsilon:e});if("ambiguous"===o.kind)return this.host._wallRepairDiagnostic=o.proposals[0]||null,this.host._showToast(this.host._t(0===this.host._drawWallCm?"toast.zero_wall_ambiguous":"toast.wall_repair_ambiguous")),!0;if("repair"===o.kind)i=o.face,s=o.proposal;else if("none"===o.kind){const s=lc(this._wallGraphSources([]),{point:t,maxDistance:this._cssPxToRender(12),gridStep:this.host._gridPitch,epsilon:e});if("repair"===s.kind)return this.host._wallRepairDiagnostic=s.proposal,this.host._showToast(this.host._t("toast.wall_repair_too_large")),!0}}return!(!i||i.ring.length<3||this._contourSelfIntersects(i.ring)||this._overlapRoom(i.ring))&&(this._beginWallFaceBatch([{...i,existing:!s,repair:s}]),!0)}catch{return!1}}_columnClick(t){const e=this._snap(t),s=this.host._drawWallCm;if(null==s)return void this._showPhysicalRange(Zt,1);if(!this.host._curSpaceCfg||this._limitReached("column"))return;const i=this.host._spaceModel();if(!i)return;const o={id:"column-"+Date.now().toString(36),shape:"square",center:e,cm:ee(s),angle:0},a=(i.wall_columns||[]).find(t=>Qt(t,o,.02*this.host._gridPitch));if(a)return clearTimeout(this.host._duplicateColumnTimer),this.host._duplicateColumnId=a.id,this.host._duplicateColumnTimer=window.setTimeout(()=>{this.host._duplicateColumnId=null},900),void this.host._showToast(this.host._t("toast.column_duplicate"));const n=this._geometrySnapshot(),r=this.host._curSpaceCfg;r.wall_columns||=[],r.wall_columns.push({...o,center:[e[0]/Xc,e[1]/Xc]}),this._commitPhysicalGeometry(this.host._t("history.column_add"),n)}_openPhysicalDialog(t,e){const s=this.host._spaceModel();if(s)if("partition"===t){const i=s.partitions.find(t=>t.id===e);i&&(this.host._physicalDialog={kind:t,id:e,cm:pe(i.cm,this.host._imperial),length:this.host._fmtLen(i.a,i.b)})}else if("column"===t){const i=s.wall_columns.find(t=>t.id===e);i&&(this.host._physicalDialog={kind:t,id:e,cm:pe(i.cm,this.host._imperial),shape:i.shape,angle:this.host._angleField("square"===i.shape?fe(i.angle):0)})}}_physicalDown(t,e,s){const i=this.host._spaceModel();if(!i)return;t.stopPropagation(),Qc(t);const o=this._svgPoint(t),a=[];for(const t of[...i.wall_columns].reverse())Me(o,Ce(t,this.host._cellCm,this.host._gridPitch))&&a.push({kind:"column",id:t.id});for(const t of[...i.partitions].reverse()){const e=Pe(t.a,t.b,t.cm,this.host._cellCm,this.host._gridPitch);e&&Me(o,e)&&a.push({kind:"partition",id:t.id})}a.some(t=>t.kind===e&&t.id===s)||a.unshift({kind:e,id:s});const n=a.map(t=>`${t.kind}:${t.id}`).sort().join("|"),r=performance.now(),l=this.host._physicalPickCycle,h=a.length>1&&l?.signature===n&&r-l.at>380&&r-l.at<=1200&&Math.hypot(t.clientX-l.x,t.clientY-l.y)<=10?(l.index+1)%a.length:Math.max(0,a.findIndex(t=>t.kind===e&&t.id===s));this.host._physicalPickCycle={signature:n,index:h,x:t.clientX,y:t.clientY,at:r},e=a[h].kind,s=a[h].id;const c="partition"===e?i.partitions.find(t=>t.id===s):i.wall_columns.find(t=>t.id===s);c&&(this.host._physicalSel={kind:e,id:s},this.host._physicalDrag={pid:t.pointerId,kind:e,id:s,start:this._svgPoint(t),startClient:[t.clientX,t.clientY],before:this._geometrySnapshot(),moved:!1,base:JSON.parse(JSON.stringify(c)),delta:[0,0]})}_clampPhysicalDelta(t,e,s){const i="partition"===t?[e.a,e.b]:[e.center],o=i.map(t=>t[0]),a=i.map(t=>t[1]);return[Math.max(-Ut*Xc-Math.min(...o),Math.min(Ut*Xc-Math.max(...o),s[0])),Math.max(-Ut*Xc-Math.min(...a),Math.min(Ut*Xc-Math.max(...a),s[1]))]}_physicalMove(t){t.stopPropagation(),Ho(this.host,"physical",()=>this._physicalMoveNow(t))}_physicalMoveNow(t){const e=this.host._physicalDrag;if(!e||e.pid!==t.pointerId)return;t.stopPropagation();const s=this._svgPoint(t),i="partition"===e.kind?e.base.a:e.base.center,o=this._snap([i[0]+s[0]-e.start[0],i[1]+s[1]-e.start[1]]),a=this._clampPhysicalDelta(e.kind,e.base,[o[0]-i[0],o[1]-i[1]]);this.host._physicalDrag={...e,delta:a,moved:e.moved||Math.hypot(t.clientX-e.startClient[0],t.clientY-e.startClient[1])>=5}}_physicalUp(t){Oo(this.host,"physical");const e=this.host._physicalDrag;if(!e||e.pid!==t.pointerId)return;if(t.stopPropagation(),this.host._physicalDrag=null,!e.moved)return void this._registerPhysicalTap(e.kind,e.id);const s=this.host._spaceModel();if(!this.host._curSpaceCfg||!s)return;const i=this.host._curSpaceCfg;if("partition"===e.kind){const t=(i.partitions||[]).find(t=>t.id===e.id),s=e.base;if(t){const o={...s,a:[s.a[0]+e.delta[0],s.a[1]+e.delta[1]],b:[s.b[0]+e.delta[0],s.b[1]+e.delta[1]]};t.a=[o.a[0]/Xc,o.a[1]/Xc],t.b=[o.b[0]/Xc,o.b[1]/Xc];for(const t of i.openings||[]){if("partition"!==t.host?.kind||t.host.id!==e.id)continue;const s=rt(t,[o],Xc,this.host._cellCm,this.host._gridPitch).resolved;s&&Object.assign(t,lt(t,s,Xc))}}}else{const t=(i.wall_columns||[]).find(t=>t.id===e.id),o=e.base,a={...o,center:[o.center[0]+e.delta[0],o.center[1]+e.delta[1]]};if(s.wall_columns.some(t=>t.id!==e.id&&Qt(t,a,.02*this.host._gridPitch)))return void this.host._showToast(this.host._t("toast.column_duplicate"));t&&(t.center=[(o.center[0]+e.delta[0])/Xc,(o.center[1]+e.delta[1])/Xc])}this._commitPhysicalGeometry(this.host._t("history.physical_move"),e.before)}_registerPhysicalTap(t,e){const s=performance.now(),i=this.host._physicalLastTap?.kind===t&&this.host._physicalLastTap.id===e&&s-this.host._physicalLastTap.at<=360;this.host._physicalLastTap={kind:t,id:e,at:s},i&&(this.host._physicalLastTap=null,this._openPhysicalDialog(t,e))}_cancelPhysicalGesture(){Lo(this.host,"physical"),Lo(this.host,"physical-rotate"),this.host._physicalDrag=null,this.host._physicalRotate=null,this.host.requestUpdate()}_physicalRotateDown(t,e){if("square"!==e.shape||!this.host._spaceModel())return;t.preventDefault(),t.stopPropagation(),Qc(t);const s=this._svgPoint(t);this.host._physicalSel={kind:"column",id:e.id},this.host._physicalRotate={pid:t.pointerId,id:e.id,center:[...e.center],startAngle:180*Math.atan2(s[1]-e.center[1],s[0]-e.center[0])/Math.PI,baseAngle:fe(e.angle),angle:fe(e.angle),before:this._geometrySnapshot(),moved:!1}}_physicalRotateMove(t){t.preventDefault(),t.stopPropagation(),Ho(this.host,"physical-rotate",()=>this._physicalRotateMoveNow(t))}_physicalRotateMoveNow(t){const e=this.host._physicalRotate;if(!e||e.pid!==t.pointerId)return;t.preventDefault(),t.stopPropagation();const s=this._svgPoint(t),i=180*Math.atan2(s[1]-e.center[1],s[0]-e.center[0])/Math.PI,o=e.baseAngle+i-e.startAngle,a=fe(t.shiftKey?o:5*Math.round(o/5));this.host._physicalRotate={...e,angle:a,moved:e.moved||Math.abs(o-e.baseAngle)>=.5}}_physicalRotateUp(t){Oo(this.host,"physical-rotate");const e=this.host._physicalRotate;if(!e||e.pid!==t.pointerId)return;t.preventDefault(),t.stopPropagation(),this.host._physicalRotate=null;const s=this.host._spaceModel();if(!e.moved||!this.host._curSpaceCfg||!s)return;const i=s.wall_columns.find(t=>t.id===e.id);if(!i||"square"!==i.shape)return;const o={...i,angle:e.angle};if(s.wall_columns.some(t=>t.id!==e.id&&Qt(t,o,.02*this.host._gridPitch)))return void this.host._showToast(this.host._t("toast.column_duplicate"));const a=this.host._curSpaceCfg.wall_columns?.find(t=>t.id===e.id);a&&(a.angle=e.angle,this._commitPhysicalGeometry(this.host._t("history.physical_edit"),e.before))}_rszRooms(){const t=[],e=this.host._spaceModel();if(!e)return t;for(const s of e.rooms){const e=s.id?H(s):null;e&&t.push({id:s.id,poly:e,wall_ids:Array.isArray(s.wall_ids)?[...s.wall_ids]:void 0})}return s=t,i=Math.max(1e-12,1e-12*this.host._gridPitch),s.map(t=>{if(!Array.isArray(t.wall_ids)||t.wall_ids.length!==t.poly.length)return{...t,poly:t.poly.map(t=>[...t])};const e=t.poly.map(t=>[...t]);let s=!0;for(;s&&e.length>3;){s=!1;for(let t=0;t0){e.splice(t,1),s=!0;break}}}return{...t,poly:e}});var s,i}_rszOpenings(){return this.host._openingsR.map(t=>({id:t.id,x:t.rx,y:t.ry,length:t.rlen,hosted:!!t.host,angle:t.angle,type:t.type}))}_rszObstacles(){const t=this.host._spaceModel();if(!t)return[];const e=[];for(const s of t.partitions||[])e.push({kind:"segment",a:[...s.a],b:[...s.b],half:b(s.cm,this.host._cellCm,this.host._gridPitch)/2});for(const s of t.wall_columns||[]){const t=b(s.cm,this.host._cellCm,this.host._gridPitch)/2;e.push({kind:"circle",center:[...s.center],radius:"square"===s.shape?t*Math.SQRT2:t})}return e}_rszOptsFor(t,e){const s=U(this.host._spaceWalls,t,e,this.host._wallKeyPitch,Xc),i=this.host._spaceWalls.filter(t=>Array.isArray(t.a)&&Array.isArray(t.b)&&t.a.length>=2&&t.b.length>=2).map(t=>({wall:t,a:[t.a[0]*Xc,t.a[1]*this.host._spaceH],b:[t.b[0]*Xc,t.b[1]*this.host._spaceH]})),o=Math.abs(t[0]-e[0])<=.05*this.host._gridPitch?"v":Math.abs(t[1]-e[1])<=.05*this.host._gridPitch?"h":null,a=i.filter(s=>!!o&&("h"===o?!(Math.abs(s.a[1]-t[1])>.05*this.host._gridPitch||Math.abs(s.b[1]-t[1])>.05*this.host._gridPitch)&&Math.min(Math.max(t[0],e[0]),Math.max(s.a[0],s.b[0]))-Math.max(Math.min(t[0],e[0]),Math.min(s.a[0],s.b[0]))>.05*this.host._gridPitch:!(Math.abs(s.a[0]-t[0])>.05*this.host._gridPitch||Math.abs(s.b[0]-t[0])>.05*this.host._gridPitch)&&Math.min(Math.max(t[1],e[1]),Math.max(s.a[1],s.b[1]))-Math.max(Math.min(t[1],e[1]),Math.min(s.a[1],s.b[1]))>.05*this.host._gridPitch)),n=new Set(a.map(t=>Number(t.wall.cm)).filter(t=>t>0));return{minDim:this.host._cmToUnits(30),eps:.05*this.host._gridPitch,step:this.host._gridPitch,movingHalf:s>0?b(s,this.host._cellCm,this.host._gridPitch)/2:0,obstacles:this._rszObstacles(),thicknessConflict:n.size>1}}_rszResolution(t,e,s){const i=this.host._resize.snapshotIdentity||s||this._rszSnapshot(),o=`${this.host._space}|${this.host._cellCm}|${this.host._gridPitch}|${i}`,a=`${t}:${e}`;return this.host._resize.resolve(o,a,()=>{const s=[...this.host._resize.rooms||this._rszRooms()],i=s.find(e=>e.id===t),o=i?.poly?.[e]||[0,0],a=i?.poly?.[(e+1)%(i?.poly?.length||1)]||[0,0];return function(t,e,s,i,o){const{eps:a}=o,n=t.find(t=>t.id===s);if(!n||i<0||i>=(n.poly?.length||0)||n.poly.length<4||!Ta(n.poly))return{enabled:!1,reason:"invalid-geometry"};const r=n.poly[i],l=n.poly[(i+1)%n.poly.length],h=Fa(r,l,a);if(!h)return{enabled:!1,reason:"diagonal"};if(!Oa(n.poly,i,h,a))return{enabled:!1,reason:"side-angle"};if(o.thicknessConflict)return{enabled:!1,reason:"thickness-conflict"};for(const t of o.obstacles||[])if(Wa(t,r,l,o))return{enabled:!1,reason:"duplicate-physical-wall"};const c=Ca(xa(l,r)),d=[],p=new Set;let u=!1,_=!1;for(const e of t)if(e.id!==s)for(let t=0;t1||d.length>1)return{enabled:!1,reason:"multiple-rooms"};const m={[s]:i},g=[s];if(1===d.length){const t=d[0];if(!Ta(t.room.poly))return{enabled:!1,reason:"invalid-geometry"};if(!Oa(t.room.poly,t.edge,h,a))return{enabled:!1,reason:"side-angle"};g.push(t.room.id),m[t.room.id]=t.edge}const f=[];for(const t of e)if(!(Da([t.x,t.y],r,l)>2*a)){if(t.hosted||t.length>c+2*a)return{enabled:!1,reason:"opening-conflict"};f.push(t.id)}const b=Object.fromEntries(g.map(e=>[e,t.find(t=>t.id===e).poly.length])),v=[];for(const e of g){const s=t.find(t=>t.id===e),i=m[e],o=(i-1+s.poly.length)%s.poly.length,n=(i+1)%s.poly.length,r=qa(t,e,o,1,a),l=qa(t,e,n,0,a);if(!r||!l)return{enabled:!1,reason:"partial-shared"};v.push(r,l)}const y={roomId:s,edge:i,a:[...r],b:[...l],n:Ia(n.poly,i),roomIds:g,edgeByRoom:m,topology:b,movingOpeningIds:f,sideOwnership:v};if(!Za(t,e,y,0,o))return{enabled:!1,reason:"invalid-geometry"};const $=Math.abs(Number(o.step));if(Number.isFinite($)&&$>a){const s=[-$,$];if(!s.some(s=>Za(t,e,y,s,o))){if(!s.some(s=>Va(Ja(t,e,y,s),y,a)))return{enabled:!1,reason:"partial-shared"};const i={...o,obstacles:[]};return s.some(s=>Za(t,e,y,s,i))?{enabled:!1,reason:"duplicate-physical-wall"}:e.length&&s.some(e=>Za(t,[],y,e,o))?{enabled:!1,reason:"opening-conflict"}:{enabled:!1,reason:"invalid-geometry"}}}return{enabled:!0,plan:y}}(s,[...this.host._resize.openings||this._rszOpenings()],t,e,this._rszOptsFor(o,a))})}_rszSnapshot(){return JSON.stringify(this._geometrySnapshot()||{spaceId:this.host._space,rooms:[],openings:[],walls:[],open_spans:[]})}_rszResetController(){const t=null!==this.host._resize.preview;this.host._resize.reset(),t&&this.host._cfgEpoch++}_rszProjectPreview(t,e,s,i,o){this.host._rszLimitViolation=null;const a=this.host._serverCfg?.spaces.find(t=>t.id===this.host._space);if(!a||!this.host._serverCfg)return{ok:!1,reason:"missing-context"};const n=JSON.parse(t),r={...a,rooms:n.rooms,openings:n.openings||[]};for(const t of["walls","wall_segments","open_spans","partitions","wall_columns","decor"])void 0!==n[t]?r[t]=n[t]:delete r[t];for(const t of["plan_x","plan_y","plan_scale","plan_scale_x","plan_scale_y","plan_angle"])void 0!==n.plan_transform?.[t]?r[t]=n.plan_transform[t]:delete r[t];const l=this.host._spaceH;for(const[t,s]of Object.entries(e)){const e=r.rooms.find(e=>e.id===t);e&&(e.poly=s.map(t=>[t[0]/Xc,t[1]/l]),delete e.x,delete e.y,delete e.w,delete e.h)}for(const[t,e]of Object.entries(s)){const s=(r.openings||[]).find(e=>e.id===t);s&&(s.x=e[0]/Xc,s.y=e[1]/l)}const h=[],c=[];for(const t of i){const e=o.find(e=>e.id===t),s=r.rooms.find(e=>e.id===t);if(!e||!s?.poly)continue;const i=s.poly.map(t=>[t[0]*Xc,t[1]*l]);if(e.poly.length!==i.length)continue;const a=Array.isArray(e.wall_ids)?e.wall_ids:[];for(let t=0;tt.id===s):null;o&&(o.a=[i[t][0]/Xc,i[t][1]/Xc],o.b=[i[(t+1)%i.length][0]/Xc,i[(t+1)%i.length][1]/Xc])}}if(h.length&&Array.isArray(r.walls)&&r.walls.length){const t=De(r.walls,h,c,this.host._wallKeyPitch,Xc,"fixed-topology");if(t.rejected)return{ok:!1,reason:"wall-metadata"};r.walls=t.walls}const d=[];for(const t of r.rooms||[]){const e=H(t);if(e&&!(e.length<2))for(let t=0;tJSON.stringify([t?.key,t?.cm,t?.a,t?.b]),u=new Map;for(const t of n.walls||[]){const e=p(t);u.set(e,(u.get(e)||0)+1)}const _=[];for(const t of r.walls||[]){const e=p(t),s=u.get(e)||0;s?u.set(e,s-1):_.push(t)}if(Ie(_,d,this.host._wallKeyPitch,Xc,n.walls||[]).length)return{ok:!1,reason:"wall-metadata"};const m=function(t,e,s=1e-8){const i=rn(t),o=new Set(e),a=i.flatMap(t=>{if(!o.has(String(t.id||"")))return[];const e=cn(hn(t));return e?[e]:[]});return i.flatMap(t=>{const e=String(t.id||""),i=cn(hn(t)),n=!!i&&a.some(t=>i.minX<=t.maxX+s&&i.maxX+s>=t.minX&&i.minY<=t.maxY+s&&i.maxY+s>=t.minY);return e&&(o.has(e)||n)?[e]:[]})}(r.rooms||[],i),g=dn(r,m);if(!g||!this._rszSpaceCandidateGeometry(this.host._space,g).ok)return{ok:!1,reason:"physical-geometry"};const f={...this.host._serverCfg,spaces:(this.host._serverCfg?.spaces||[]).map(t=>t?.id===this.host._space?r:t)};try{this._resizePreviewNodes=tt(g.rooms,g.walls,[],N,this.host._cellCm,this.host._gridPitch,Xc)}catch{this._resizePreviewNodes=null}let b;try{const t=new Set(i),e=this.host._junctionLimitViolations(f,this.host._space,{status:"lightweight",multiWallNodes:this._resizePreviewNodes},t);b=Lr(e,this._resizeBaselineLimits.filter(e=>"clearance"!==e.rule||t.has(e.subject)))}catch{b=[{rule:"check_failed",subject:this.host._space,actual:0,limit:0}]}return b.length?(this.host._rszLimitViolation=b[0],{ok:!1,reason:"junction-limit"}):{ok:!0,value:{preview:{space:this.host._space,sp:r},beforeWalls:n.walls||[],afterWalls:r.walls||[],artifact:null}}}_rszAcceptPreview(t,e){if(this.host._cfgEpoch++,this.host._physicalBodiesCache&&(this.host._physicalBodiesCache.key=`${this.host._space}|${this.host._cfgEpoch}|${this.host._cellCm}|${this.host._gridPitch}`),!t||!e)return;const s=Te(e);if(!s)return;const i=`${this.host._space}|${this.host._cfgEpoch}|${t.sp.rooms.length}`;Object.defineProperty(s,"sourceFingerprint",{value:zt([t.sp,this.host._cellCm,this.host._gridPitch]),enumerable:!1});const o={key:i,value:s};Yc(this.host._wallUnionPool,i,o,8),this.host._wallUnionCache=o}_rszSpaceCandidateGeometry(t,e){if(!this.host._serverCfg)return{ok:!1,wallGeometry:null};const s={...this.host._serverCfg,spaces:this.host._serverCfg.spaces.map(s=>s.id===t?e:s)};let i=null;try{return{ok:this.host._checkSpacePhysicalGeometry(s,t,t=>{i=t}).ok,wallGeometry:i}}catch{return{ok:!1,wallGeometry:null}}}_rszSpaceCandidateRenderable(t,e){if(!this.host._serverCfg)return!1;try{const s={...this.host._serverCfg,spaces:this.host._serverCfg.spaces.map(s=>s.id===t?e:s)};return this.host._checkSpacePhysicalGeometry(s,t).ok}catch{return!1}}_rszCandidateRenderable(t){return!!t&&t.space===this.host._space&&this._rszSpaceCandidateRenderable(t.space,t.sp)}_rszEdgeDown(t,e,s){if("resize"!==this.host._tool||this.host._resize.dragging)return;this._resizeBaseFrameStable=!0,t.stopPropagation(),t.preventDefault();const i=this._rszRooms(),o=this._rszResolution(e,s);if(!o.enabled)return void this.host._showToast(this._rszReasonText(o.reason));Qc(t);const a=o.plan;try{this._resizeBaselineLimits=this.host._junctionLimitViolations(this.host._serverCfg,this.host._space,null,new Set(a.roomIds))}catch{this._resizeBaselineLimits=[]}const n=this._svgPoint(t),r=`${this.host._space}|${this.host._cfgEpoch}|${i.length}`,l=this.host._wallUnionCache?.key===r?this.host._wallUnionCache.value:null,h=this._rszSnapshot();this.host._resize.begin({pointerId:t.pointerId,start:[n[0],n[1]],roomId:e,plan:a,options:this._rszOptsFor(a.a,a.b),rooms:i,openings:this._rszOpenings(),snapshotIdentity:h,before:JSON.parse(h),wallUnionBefore:l,epochBefore:this.host._cfgEpoch})}_rszReasonText(t){return this.host._t(`resize.disabled.${t}`)}_rszDisabledActivate(t,e){t.stopPropagation(),t.preventDefault(),this.host._showToast(this._rszReasonText(e))}_rszDisabledKey(t,e){"Enter"!==t.key&&" "!==t.key||this._rszDisabledActivate(t,e)}_rszMove(t){this.host._resize.ownsPointer(t.pointerId)&&(t.stopPropagation(),Ho(this.host,"resize",()=>this._rszMoveNow(t)))}_rszMoveNow(t){if(!this.host._resize.ownsPointer(t.pointerId))return;t.stopPropagation();const e=this._svgPoint(t),s=this.host._resize.move({pointerId:t.pointerId,point:[e[0],e[1]],step:this.host._gridPitch,snap:t=>{const e=this._snap(t);return[e[0],e[1]]},project:(t,e,s,i,o)=>this._rszProjectPreview(t,e,s,i,o),publish:(t,e)=>this._rszAcceptPreview(t,e),measure:(t,e)=>this._rszEdgeLabels(t,e)});if("rejected"===s.kind)return s.notify&&this.host._showToast(this.host._rszLimitViolation?`${this.host._t("resize.limit_stopped")} — `+this._junctionLimitLabel(this.host._rszLimitViolation):this.host._t("resize.preview_failed")),void this.host.requestUpdate();"accepted"===s.kind&&this.host.requestUpdate()}_rszUp(t){if(Oo(this.host,"resize"),!this.host._resize.ownsPointer(t.pointerId))return;t.stopPropagation();const e=this.host._resize.finish({pointerId:t.pointerId,currentSnapshotIdentity:this._rszSnapshot(),validatePreview:t=>this._rszCandidateRenderable(t)});if("no-op"===e.kind)return this.host._cfgEpoch++,void this.host.requestUpdate();if("rejected"===e.kind)return this.host._cfgEpoch++,this.host._showToast(this.host._t("resize.commit_failed")),void this.host.requestUpdate();const s=e.preview,i=this.host._serverCfg?.spaces.find(t=>t.id===s.space);i&&(i.rooms=s.sp.rooms,i.openings=s.sp.openings,Array.isArray(s.sp.walls)&&(s.sp.walls.length?i.walls=s.sp.walls:delete i.walls),Array.isArray(s.sp.wall_segments)&&(i.wall_segments=s.sp.wall_segments)),this.host._suppressClick=!0,setTimeout(()=>this.host._suppressClick=!1,0),this._commitPhysicalGeometry(this.host._t("history.resize_room"),e.before),this.host.requestUpdate()}_rszCancelDrag(t){Lo(this.host,"resize");const e=this.host._resize.cancel(this._rszSnapshot(),t);if("no-op"!==e.kind){if(null!==e.restoreEpoch?this.host._cfgEpoch=e.restoreEpoch:this.host._cfgEpoch++,this.host._physicalBodiesCache&&(this.host._physicalBodiesCache.key=`${this.host._space}|${this.host._cfgEpoch}|${this.host._cellCm}|${this.host._gridPitch}`),e.restoreWallUnion){const t=this.host._spaceModel();if(t){const s=`${this.host._space}|${this.host._cfgEpoch}|${t.rooms.length}`,i={key:s,value:e.restoreWallUnion};Yc(this.host._wallUnionPool,s,i,8),this.host._wallUnionCache=i}}null!==e.restoreEpoch&&"plan"===this.host._mode&&this._resizeBaseFrameStable&&(this.host._terminalFrame=1),this.host.requestUpdate()}}_rszPointerCancel(t){this.host._resize.ownsPointer(t.pointerId)&&(t.stopPropagation(),this._rszCancelDrag(t.pointerId))}_rszEdgeLabels(t,e,s=this.host._resize.rooms){const i=s,o=[],a=t.polys[e.roomId]||i?.find(t=>t.id===e.roomId).poly;if(!a||!i)return o;const n=a.length,r=this._rszInnerSpanCms(e.roomId,a,t.polys);for(const t of function(t,e){const s=t.length;return[(e-1+s)%s,(e+1)%s]}(a,e.edge)){const e=a[t],s=a[(t+1)%n],i=r?.[t];o.push({kind:"length",x:(e[0]+s[0])/2,y:(e[1]+s[1])/2,text:null==i?this.host._fmtLen(e,s):Nt(i,"mi"===this.host.hass?.config?.unit_system?.length),edge:{a:[e[0],e[1]],b:[s[0],s[1]]}})}const l="mi"===this.host.hass?.config?.unit_system?.length,h=e.roomIds,c=this.host._spaceWalls,d=this.host._physicalBodiesR(),p=this.host._baseVb(),u=this.host._view&&this.host._view.w>0&&this.host._view.h>0?this.host._view:{x:p[0],y:p[1],w:p[2],h:p[3]},[_,m]=this.host._lastValidStageSize||[u.w,u.h],g={...u,stageWidth:Math.max(1,_),stageHeight:Math.max(1,m)},f=this.host._spaceModel(),b=this.host._config?.icon_size??2.5,v=f?ze(b>8?2.5:b,f,u.w,this.host._kiosk?this.host._kioskScale.icon:1)*g.stageWidth/100:24,y=Math.max(10,.77*v),$=this.host._t("room.settings_short"),w=y*(1.457+.66*Math.max(1,$.length)*.42);for(const s of h){const a=t.polys[s]||i.find(t=>t.id===s).poly,n=c.length&&f&&st(f.rooms,s,c,this.host._openCuts(),this.host._wallKeyPitch,this.host._cellCm,this.host._gridPitch,Xc,null,this._resizePreviewNodes)||a,r=d.length?Re(Ae(n,d))*Math.pow(this.host._cellCm/this.host._gridPitch,2)/1e4:Fe(n,this.host._gridPitch,this.host._cellCm),h=Ne(r,l),p=ur({poly:a,edge:e.edgeByRoom[s],text:h,view:g,gearCenter:Ee(a),gearWidthPx:w,gearHeightPx:y});o.push({kind:"area",roomId:s,x:p.anchor[0],y:p.anchor[1],text:h,placement:p})}return o}_rszInnerSpanCms(t,e,s){const i=Object.keys(s).length?Object.entries(s).map(([t,e])=>({id:t,poly:e})):this.host._spaceModel()?.rooms;if(!i?.length)return null;const o=this.host._spaceWalls;if(!o.length)return null;const a=this.host._openCuts(),n=He(i,t,o,a,this.host._wallKeyPitch,this.host._cellCm,this.host._gridPitch,Xc);if(!n||n.length!==e.length)return null;const r=this.host._cellCm/this.host._gridPitch;return e.map((t,s)=>Oe(e,s,n)*r)}_renderResizeMeasurements(){const t=this.host._resize.liveLabels;if(!t?.length)return l;const e=t.filter(t=>"length"===t.kind),s=t.filter(t=>"area"===t.kind);return d`
${e.map((t,e)=>d`
diff --git a/custom_components/houseplan/frontend/houseplan-assets/houseplan-onboarding-runtime-BpONoVw8.js b/custom_components/houseplan/frontend/houseplan-assets/houseplan-onboarding-runtime-DKBSTd7u.js
similarity index 98%
rename from custom_components/houseplan/frontend/houseplan-assets/houseplan-onboarding-runtime-BpONoVw8.js
rename to custom_components/houseplan/frontend/houseplan-assets/houseplan-onboarding-runtime-DKBSTd7u.js
index 503a06bc..7221443d 100644
--- a/custom_components/houseplan/frontend/houseplan-assets/houseplan-onboarding-runtime-BpONoVw8.js
+++ b/custom_components/houseplan/frontend/houseplan-assets/houseplan-onboarding-runtime-DKBSTd7u.js
@@ -1,4 +1,4 @@
-globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="c8d5c166e30a11241ef32c7e1dc70368632e84c448524a8340494350ec4d5fca";import{l as t,b0 as s,A as e,t as a,b as o,cj as l,ck as i,cl as h,cm as c,aZ as n,cn as r,cs as p,co as d,cp as _,cq as u,cr as g,ct as m,cu as b,dp as $,dq as v,dr as f,aY as y,a_ as w,ds as D}from"./houseplan-card-DXAxXz4t.js";import{c as k,e as S,r as C,a as M}from"./backdrop-pick-qyPNmULR.js";const F=1e3,x=t=>{if(!t.trim())return null;const s=Number(t.replace(",","."));return Number.isFinite(s)?s:null},T="c8d5c166e30a11241ef32c7e1dc70368632e84c448524a8340494350ec4d5fca";class L{constructor(t){this.host=t,this._toggleServerPlans=async()=>{const t=this.host._spaceDialog;if(t)if(t.pickSaved)this.host._spaceDialog={...t,pickSaved:!1};else{this.host._spaceDialog={...t,pickSaved:!0,savedBusy:!0};try{const t=await this.host.hass.callWS({type:"houseplan/plans/list"}),s=this.host._spaceDialog;s&&(this.host._spaceDialog={...s,saved:t?.plans||[],savedBusy:!1})}catch(t){const s=this.host._spaceDialog;s&&(this.host._spaceDialog={...s,saved:[],savedBusy:!1}),this.host._showToast(this.host._t("toast.plans_list_failed",{err:this.host._errText(t)}))}}}}_help(l){const i=`${l}.aria`,h=t(this.host.hass,this.host._config?.language);return s(h,l)&&s(h,i)?o`{if(!t.trim())return null;const s=Number(t.replace(",","."));return Number.isFinite(s)?s:null},T="2e6f7d70c797ae4e865b10859c77cc3380a432272a975b8f35b51234ae3cfe62";class L{constructor(t){this.host=t,this._toggleServerPlans=async()=>{const t=this.host._spaceDialog;if(t)if(t.pickSaved)this.host._spaceDialog={...t,pickSaved:!1};else{this.host._spaceDialog={...t,pickSaved:!0,savedBusy:!0};try{const t=await this.host.hass.callWS({type:"houseplan/plans/list"}),s=this.host._spaceDialog;s&&(this.host._spaceDialog={...s,saved:t?.plans||[],savedBusy:!1})}catch(t){const s=this.host._spaceDialog;s&&(this.host._spaceDialog={...s,saved:[],savedBusy:!1}),this.host._showToast(this.host._t("toast.plans_list_failed",{err:this.host._errText(t)}))}}}}_help(l){const i=`${l}.aria`,h=t(this.host.hass,this.host._config?.language);return s(h,l)&&s(h,i)?o``:e}_openSpaceDialog(t,s){if(!this.host._serverStorage||!this.host._serverCfg)return void this.host._showToast(this.host._t("toast.integration_missing"));if("edit"===t){const e=this.host._serverCfg.spaces.find(t=>t.id===s);if(!e)return;const a=l(e),o=e.settings?.custom_fill&&"object"==typeof e.settings.custom_fill?i(e.settings.custom_fill):null,p="none"===a.fill?{...o||h,a:0}:o;return void(this.host._spaceDialog={mode:t,spaceId:s,title:e.title,planUrl:e.plan_url||null,planFile:null,source:e.plan_url?"file":"draw",showBorders:a.showBorders,showNames:a.showNames,zeroWallStyle:r(e),displayTouched:!0,hideDecor:a.hideDecor,hideOpenings:a.hideOpenings,roomColor:a.color,roomOpacity:a.opacity,fillMode:"none"===a.fill?"custom":a.fill,customFill:p,glowEnabled:a.glow,bgColor:a.bgColor,bgMode:"static"===e.settings?.bg_mode||"daynight"===e.settings?.bg_mode?e.settings.bg_mode:null,northDeg:n({},e.settings),sunRays:"boolean"==typeof e.settings?.sun_rays?e.settings.sun_rays:null,tempMin:a.tempMin,tempMax:a.tempMax,showLqi:a.showLqi??this.host._config?.show_signal??!0,cardFontScale:a.cardFontScale,labelTemp:a.labelTemp,labelHum:a.labelHum,labelLqi:a.labelLqi,labelLight:a.labelLight,cellCm:Number(e.cell_cm)>0?Number(e.cell_cm):5,cellCmInput:c(Number(e.cell_cm)>0?Number(e.cell_cm):5,this.host._imperial),cellCmTouched:!1,busy:!1})}const e=p(this.host._imperial);this.host._spaceDialog={mode:t,title:"",planUrl:null,planFile:null,...m(),hideDecor:!1,hideOpenings:!1,zeroWallStyle:"dashed",roomColor:g,roomOpacity:u,fillMode:"custom",customFill:{...h,a:0},glowEnabled:!0,bgColor:null,bgMode:"daynight",northDeg:null,sunRays:null,tempMin:_,tempMax:d,showLqi:this.host._config?.show_signal??!0,cardFontScale:1,labelTemp:!1,labelHum:!1,labelLqi:!1,labelLight:!1,cellCm:e,cellCmInput:c(e,this.host._imperial),cellCmTouched:!1,busy:!1}}async _pickPlanFile(t){const s=t.target,e=s.files?.[0];if(!e||!this.host._spaceDialog)return;s.value="";const a=await k(e);if("reject"===a.kind)return void this.host._showToast(this.host._t("toast.plan_formats"));if("guard"===a.kind)return void(this.host._backdropGuard=a.state);const o=await S(e,a.ext,e.name);this.host._spaceDialog&&(this.host._spaceDialog={...this.host._spaceDialog,planFile:o})}_renderBackdropGuard(){return C(this.host,t=>{this.host._spaceDialog&&(this.host._spaceDialog={...this.host._spaceDialog,planFile:t})},()=>{this.host._backdropGuard=null},this.host.hass)??e}_useServerPlan(t){const s=this.host._spaceDialog;s&&(this.host._spaceDialog={...s,planUrl:t,planFile:null,pickSaved:!1,savedAspect:void 0},this.host._aspectJob=this._readPlanAspect(t))}async _readPlanAspect(t){for(let s=0;s<40;s++){const s=this.host._display(t);if(s){const e=await new Promise(t=>{const e=new Image;e.onload=()=>t(e.naturalWidth&&e.naturalHeight?e.naturalWidth/e.naturalHeight:0),e.onerror=()=>t(0),e.src=s}),a=this.host._spaceDialog;return a&&a.planUrl===t&&Number.isFinite(e)&&e>0?(this.host._spaceDialog={...a,savedAspect:e},e):0}if(await new Promise(t=>setTimeout(t,150)),this.host._spaceDialog?.planUrl!==t)return 0}return 0}async _deleteServerPlan(t){const s=this.host._spaceDialog,e=s?.saved?.find(s=>s.name===t);if(!s||!e||e.used_by.length||e.url===s.planUrl)return;const a=await this.host._confirmDanger({key:"delete-plan",kind:"destructive",title:this.host._t("confirm.delete_plan_title"),message:this.host._t("confirm.delete_plan_body"),objectName:t,confirmLabel:this.host._t("btn.delete"),cancelLabel:this.host._t("btn.cancel")}),o=this.host._spaceDialog,l=o?.saved?.find(s=>s.name===t);if(a&&o&&l&&l.url===e.url&&l.modified===e.modified&&!l.used_by.length&&l.url!==o.planUrl)try{await this.host.hass.callWS({type:"houseplan/plans/delete",name:t});const s=this.host._spaceDialog;s?.saved&&(this.host._spaceDialog={...s,saved:s.saved.filter(s=>s.name!==t)})}catch(t){this.host._showToast(this.host._t("toast.plan_delete_failed",{err:this.host._errText(t)}))}}_renderServerPlans(t){if(t.savedBusy)return o`
${this.host._t("space.loading")}
`;const s=t.saved||[];if(!s.length)return o`
${this.host._t("space.no_saved")}
`;return o`
${s.map(s=>{return o`
diff --git a/custom_components/houseplan/frontend/houseplan-assets/hp-zigbee-topology-overlay-CvYXeB7d.js b/custom_components/houseplan/frontend/houseplan-assets/hp-zigbee-topology-overlay-BRoahbu2.js
similarity index 91%
rename from custom_components/houseplan/frontend/houseplan-assets/hp-zigbee-topology-overlay-CvYXeB7d.js
rename to custom_components/houseplan/frontend/houseplan-assets/hp-zigbee-topology-overlay-BRoahbu2.js
index fcd9a341..91e93105 100644
--- a/custom_components/houseplan/frontend/houseplan-assets/hp-zigbee-topology-overlay-CvYXeB7d.js
+++ b/custom_components/houseplan/frontend/houseplan-assets/hp-zigbee-topology-overlay-BRoahbu2.js
@@ -1,5 +1,5 @@
-globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="c8d5c166e30a11241ef32c7e1dc70368632e84c448524a8340494350ec4d5fca";import{m as e,l as t,A as i,e7 as r,w as o,b as s,k as n}from"./houseplan-card-DXAxXz4t.js";import{t as a,a as h,r as d}from"./zigbee-topology-rqneqkBH.js";import{zigbeeTopologyRuntimeSnapshot as p,subscribeZigbeeTopology as l}from"./zigbee-topology-runtime-BszC8bHw.js";function c(e,t,i,r,o,s=9,n=4.5){const a=t.x-e.x,h=t.y-e.y,d=Math.hypot(a,h),p=d-Math.max(0,i)-Math.max(0,r);if(!Number.isFinite(d)||d<=0||p<4)return null;const l=a/d,c=h/d,_="toward-neighbor"===o,u=_?{x:t.x-l*Math.max(0,r),y:t.y-c*Math.max(0,r)}:{x:e.x+l*Math.max(0,i),y:e.y+c*Math.max(0,i)},m=Math.min(s,Math.max(4,.45*p)),v=Math.min(n,.5*m),g=_?-1:1,b=u.x+l*m*g,y=u.y+c*m*g,x=-c;return{tip:u,points:[u,{x:b+x*v,y:y+l*v},{x:b-x*v,y:y-l*v}]}}const _={revision:0,topologies:[],states:{}},u="data-hp-zigbee-topology-endpoint";class m extends e{constructor(){super(...arguments),this.devices=[],this.currentSpace="",this._runtime=_,this._hovered="",this._desiredEndpointIds=new Set,this._endpointSetDirty=!1,this._endpointElements=new Set,this._pointerOver=e=>{if(!this._mouseAllowed(e))return void this._clear();const t=this._deviceFromEvent(e),i=t?.dataset.id||"";i&&i!==this._hovered&&(this._hovered=i,this.requestUpdate())},this._pointerOut=e=>{const t=this._deviceFromEvent(e);if(!t||t.dataset.id!==this._hovered)return;const i=e.relatedTarget instanceof Element?e.relatedTarget.closest('[data-hp="device"]'):null;i?.dataset.id!==this._hovered&&this._clear()},this._pointerDown=e=>{"mouse"!==e.pointerType&&this._clear()}}connectedCallback(){super.connectedCallback();const e=this.getRootNode();e.host&&"undefined"!=typeof MutationObserver&&(this._hoverGateObserver=new MutationObserver(()=>{e.host.hasAttribute("data-pointer-hover")||this._clear()}),this._hoverGateObserver.observe(e.host,{attributes:!0,attributeFilter:["data-pointer-hover"]})),queueMicrotask(()=>this._connectParent())}disconnectedCallback(){this._release?.(),this._release=void 0,this._disconnectParent(),this._hoverGateObserver?.disconnect(),this._hoverGateObserver=void 0,this._hovered="",this._desiredEndpointIds.clear(),super.disconnectedCallback()}updated(e){e.has("hass")&&(this._release?.(),this._acceptRuntime(p(this.hass)),this._release=l(this.hass,()=>{this._acceptRuntime(p(this.hass))}));const t=e.has("currentSpace")||e.has("devices")||e.has("registry");t&&(this._mappedMemo=void 0,this.devices.some(e=>e.id===this._hovered&&e.space===this.currentSpace)||this._clear()),this._connectParent(),(this._endpointSetDirty||t)&&this._syncEndpointOwnership()}_acceptRuntime(e){e.revision===this._runtime.revision&&e.topologies===this._runtime.topologies&&e.states===this._runtime.states||(this._setDesiredEndpointIds([]),this._clearEndpointOwnership(),this._endpointSetDirty=!1,this._runtime=e,this._mappedMemo=void 0,this.requestUpdate())}_connectParent(){const e=this.parentElement;e&&e!==this._parent&&(this._disconnectParent(),this._parent=e,e.addEventListener("pointerover",this._pointerOver),e.addEventListener("pointerout",this._pointerOut),e.addEventListener("pointerdown",this._pointerDown,!0),"undefined"!=typeof MutationObserver&&(this._markerObserver=new MutationObserver(()=>this._syncEndpointOwnership()),this._markerObserver.observe(e,{childList:!0})),this._syncEndpointOwnership())}_disconnectParent(){this._parent?.removeEventListener("pointerover",this._pointerOver),this._parent?.removeEventListener("pointerout",this._pointerOut),this._parent?.removeEventListener("pointerdown",this._pointerDown,!0),this._markerObserver?.disconnect(),this._markerObserver=void 0,this._clearEndpointOwnership(),this._parent=void 0}_deviceFromEvent(e){for(const t of e.composedPath())if(t instanceof HTMLElement&&"device"===t.dataset.hp)return t;return null}_mouseAllowed(e){const t=this.getRootNode();return"mouse"===e.pointerType&&t.host?.hasAttribute?.("data-pointer-hover")}_clear(){this._setDesiredEndpointIds([]),this._clearEndpointOwnership(),this._endpointSetDirty=!1,this._hovered&&(this._hovered="",this.requestUpdate())}_setDesiredEndpointIds(e){const t=new Set(e);t.size===this._desiredEndpointIds.size&&[...t].every(e=>this._desiredEndpointIds.has(e))||(this._desiredEndpointIds=t,this._endpointSetDirty=!0)}_marker(e){return[...this._parent?.querySelectorAll('.dev[data-hp="device"][data-id]')||[]].find(t=>t.dataset.id===e)||null}_clearEndpointOwnership(){for(const e of this._endpointElements)e.removeAttribute(u);for(const e of this._parent?.querySelectorAll(`[${u}]`)||[])e.removeAttribute(u);this._endpointElements.clear()}_syncEndpointOwnership(){const e=new Set;for(const t of this._desiredEndpointIds){const i=this._marker(t);i&&e.add(i)}for(const t of this._endpointElements)e.has(t)||t.removeAttribute(u);for(const t of this._parent?.querySelectorAll(`[${u}]`)||[])e.has(t)||t.removeAttribute(u);for(const t of e)this._endpointElements.has(t)&&t.hasAttribute(u)||t.setAttribute(u,"");this._endpointElements=e,this._endpointSetDirty=!1}_position(e,t,i){const r=this._marker(e);if(!r)return null;const o=Number.parseFloat(r.style.left),s=Number.parseFloat(r.style.top),n=r.getBoundingClientRect();return Number.isFinite(o)&&Number.isFinite(s)?{x:o*t/100,y:s*i/100,width:n.width,height:n.height}:null}_targetText(e){if("remote-space"===e.kind){const i=this.spaces?.find(t=>t.id===e.spaceId)?.title;return"string"==typeof i&&i.trim()||a(t(this.hass),"route_other_space")}return a(t(this.hass),"unplaced-coordinator"===e.kind?"route_coordinator_not_on_plan":"route_device_not_on_plan")}_markerClearance(e){return.61*Math.max(e.width,e.height)+3}_points(e){return e.map(e=>`${e.x.toFixed(2)},${e.y.toFixed(2)}`).join(" ")}render(){if(!this._hovered||!this.registry||!this._runtime.topologies.length)return this._setDesiredEndpointIds([]),i;const e=this._mappedMemo,n=e&&e.runtime===this._runtime&&e.devices===this.devices&&e.registry===this.registry?e.mapped:h(this._runtime.topologies,this.devices,this.registry);e&&n===e.mapped||(this._mappedMemo={runtime:this._runtime,devices:this.devices,registry:this.registry,mapped:n});const p=d(n,this.currentSpace,this._hovered),l=this.clientWidth||this._parent?.clientWidth||1,_=this.clientHeight||this._parent?.clientHeight||1,u=this._position(this._hovered,l,_);if(!u)return this._setDesiredEndpointIds([]),i;const m=p.lines.map(e=>({...e,point:this._position(e.neighborMarkerId,l,_)})).filter(e=>!!e.point).map(e=>{const t=void 0===e.lqi?"rgba(145,155,165,.85)":r(e.lqi),i=e.routeDirection?c(u,e.point,this._markerClearance(u),this._markerClearance(e.point),e.routeDirection):null;return{...e,color:t,arrow:i}}),v=u.x>l/2,g=this._markerClearance(u)+18,b=p.parentTargets.map((e,t)=>{const i=30*(t-(p.parentTargets.length-1)/2),r={x:u.x+(v?-g:g),y:Math.max(14,Math.min(_-14,u.y+i))};return{target:e,point:r,arrow:c(u,r,this._markerClearance(u),0,"toward-neighbor")}});return this._setDesiredEndpointIds(m.length||b.length||p.remoteCount?[this._hovered,...m.map(e=>e.neighborMarkerId)]:[]),s`
- ${m.length||b.length?o`
`)}
- ${b.map(e=>s`
s`
${this._targetText(e.target)}
`)}
${p.remoteCount?s`
`${Number(e[0].toFixed(4))} ${Number(e[1].toFixed(4))}`;function j(e){let t=0;for(let n=0;nArray.isArray(e)&&Number.isFinite(e[0])&&Number.isFinite(e[1])).map(e=>[Number(e[0]),Number(e[1])]),n=t[t.length-1];return t.length>1&&t[0][0]===n[0]&&t[0][1]===n[1]&&t.pop(),t}(e);if(n.length<3)return[];const o=!t;return j(n)>0===o?n:[...n].reverse()}function O(e,t,o){return e.length?`M ${e.map(e=>C(n(e,o,t))).join(" L ")} Z`:""}function A(e,t,n){const o=t[1]-e[1],i=-(t[0]-e[0]),a=n.rotDeg*Math.PI/180;return o*Math.sin(a)+i*Math.cos(a)}function B(t,o,i=e){if(!Number.isFinite(o)||o<0)throw new Error("invalid floor edge height");const a=(t||[]).map(e=>(e||[]).map((e,t)=>function(e,t){const n=N(e,t);if(!n.length)return n;let o=0;for(let e=1;e0)).filter(e=>e.length>=3&&Math.abs(j(e))>=1e-9)).filter(e=>e.length&&j(e[0])>0);a.sort((e,t)=>{const n=e[0][0],o=t[0][0];return n[0]-o[0]||n[1]-o[1]||Math.abs(j(t[0]))-Math.abs(j(e[0]))});const r=[],s=[];let l=0;for(let e=0;ee.depth-t.depth||e.component-t.component||e.edge-t.edge),{footprintPath:r.join(" "),sides:s,componentCount:a.length,edgeCount:l}}function R(e,t){return e^=Math.round(64*(Number.isFinite(t)?t:0)),Math.imul(e,16777619)>>>0}const H=Object.freeze({revision:1,leafThicknessRatio:.04,frameThicknessRatio:.055,gateTurnDeg:10,gateTopRatio:.88,windowBottomRatio:.27,windowTopRatio:.78,doorTopRatio:.92});H.leafThicknessRatio,H.frameThicknessRatio;const F=e=>e.every(Number.isFinite);function T(e,t){return Object.freeze([Object.is(e,-0)?0:e,Object.is(t,-0)?0:t])}function L(e,t){return[e[0]+t[0],e[1]+t[1]]}function V(e,t){return[e[0]-t[0],e[1]-t[1]]}function G(e,t){return[e[0]*t,e[1]*t]}function W(e,t,n,o){const i=e[0]*n,a=e[1]*o,r=t*Math.PI/180;return[i*Math.cos(r)-a*Math.sin(r),i*Math.sin(r)+a*Math.cos(r)]}function E(e,t,n,i,a,r,s){const l=e.flipH?-1:1,c="gate"===e.type?1:e.flipV?-1:1,d=o(e.type,e.flipV,e.angle,e.face);return{leaf:t,hinge:L([e.x+d.ox,e.y+d.oy],W(n,e.angle,l,c)),closedVector:W(i,e.angle,l,c),quarterVector:W([-i[1],i[0]],e.angle,l,c),turnDeg:a,bottom:r,top:s}}const q=e=>`${Number(e[0].toFixed(4))} ${Number(e[1].toFixed(4))}`;function D(e,t,o,i,a={}){const r=o.map(e=>n(e.point,e.z,i));return Object.freeze({kind:e,material:t,d:`M ${r.map(q).join(" L ")} Z`,depth:Math.max(...r.map(e=>e[1])),...a})}function _(e,t,n,o,i,a,r,s={}){return D(e,t,[{point:n,z:i},{point:o,z:i},{point:o,z:a},{point:n,z:a}],r,s)}function U(t,o,i=e){const a=Math.max(0,Math.min(1,Number.isFinite(o)?o:0));return t.leaves.map(e=>{const o=function(e,t){const n=e.turnDeg*t*Math.PI/180;return[e.hinge[0]+e.closedVector[0]*Math.cos(n)+e.quarterVector[0]*Math.sin(n),e.hinge[1]+e.closedVector[1]*Math.cos(n)+e.quarterVector[1]*Math.sin(n)]}(e,a),r=n(e.hinge,e.bottom,i),s=n(o,e.bottom,i),l=n(o,e.top,i),c=n(e.hinge,e.top,i),d="window"===t.type?"light-window":"matte-leaf",h="window"===t.type?Object.freeze([_("window-insert","light-window",e.hinge,o,e.bottom,e.top,i)]):function(e,t,n,o){const i=V(t,e.hinge),a=Math.hypot(i[0],i[1]);if(!(a>1e-9&&n>0))return Object.freeze([]);const r=T(-i[1]*n/(2*a),i[0]*n/(2*a)),s=L(e.hinge,r),l=L(t,r),c=V(e.hinge,r),d=V(t,r),h=[_("leaf-back","matte-leaf",d,c,e.bottom,e.top,o),_("leaf-front","matte-leaf",s,l,e.bottom,e.top,o),_("leaf-edge","matte-leaf",c,s,e.bottom,e.top,o,{edge:"hinge"}),_("leaf-edge","matte-leaf",l,d,e.bottom,e.top,o,{edge:"tip"}),D("leaf-top","matte-leaf",[{point:s,z:e.top},{point:c,z:e.top},{point:d,z:e.top},{point:l,z:e.top}],o)];return Object.freeze(h.sort((e,t)=>e.depth-t.depth||e.kind.localeCompare(t.kind)||String(e.edge||"").localeCompare(String(t.edge||""))))}(e,o,t.leafThickness,i);return Object.freeze({id:t.id,sourceIndex:t.sourceIndex,type:t.type,leaf:e.leaf,d:`M ${q(r)} L ${q(s)} L ${q(l)} L ${q(c)} Z`,shadowD:`M ${q(n(e.hinge,0,i))} L ${q(n(o,0,i))}`,depth:Math.max(r[1],s[1]),material:d,thickness:"window"===t.type?0:t.leafThickness,surfaces:h})})}const K=1e-9,Z=e=>e.length>=2&&Number.isFinite(e[0])&&Number.isFinite(e[1]);function J(e){let t=0;for(let n=0;n=3&&e.every(Z)&&Math.abs(J(e))>K}function X(e,t,n){const o=n[0]-t[0],i=n[1]-t[1],a=o*o+i*i,r=a?Math.max(0,Math.min(1,((e[0]-t[0])*o+(e[1]-t[1])*i)/a)):0;return Math.hypot(e[0]-t[0]-r*o,e[1]-t[1]-r*i)}function Y(e,t,n=1e-7){for(let o=0;oe[1]!=r[1]>e[1]&&e[0]<(r[0]-a[0])*(e[1]-a[1])/(r[1]-a[1])+a[0]&&(n=!n)}return n}function te(e){return Math.max(0,Math.abs(J(e.outer))-(e.holes||[]).reduce((e,t)=>e+Math.abs(J(t)),0))}function ne(e){return!!e.id&&Q(e.outer)&&(e.holes||[]).every(Q)&&te(e)>K}function oe(e,t){if(!ne(t)||Y(e,t.outer)||!ee(e,t.outer))return!1;for(const n of t.holes||[])if(Y(e,n)||ee(e,n))return!1;return!0}function ie(e){if(!ne(e))return null;if(e.safePoint&&oe(e.safePoint,e))return[e.safePoint[0],e.safePoint[1]];const t=e.outer.map(e=>e[0]),n=e.outer.map(e=>e[1]),o=Math.min(...t),i=Math.max(...t),a=Math.min(...n),r=Math.max(...n),s=[[(o+i)/2,(a+r)/2],[t.reduce((e,t)=>e+t,0)/t.length,n.reduce((e,t)=>e+t,0)/n.length]];for(let t=0;t{if(!oe(t,e))return;const n=function(e,t){let n=1/0;for(const o of[t.outer,...t.holes||[]])for(let t=0;tc+K&&(l=t,c=n)};s.forEach(d);for(let e=1;e<16;e++)for(let t=1;t<16;t++)d([o+(i-o)*e/16,a+(r-a)*t/16]);return l}function ae(e){if(!Z(e.floorAnchor))return null;const t=e.roomsValidated?e.rooms:e.rooms.filter(ne),n=e.preferredRoomId&&t.find(t=>t.id===e.preferredRoomId)||null;let o=null;return"device"===e.kind?(n&&oe(e.floorAnchor,n)&&(o=n),o||(o=t.filter(t=>oe(e.floorAnchor,t)).sort((e,t)=>te(e)-te(t)||((e,t)=>et?1:0)(e.id,t.id))[0]||null)):o=n,o?{id:o.id,area:te(o),safePoint:e.roomsValidated&&o.safePoint?[o.safePoint[0],o.safePoint[1]]:ie(o)}:null}function re(t,o,i,a=e,r=[0,0]){if(!Z(t)||!Z(o)||o[0]<0||o[1]<0||!Number.isFinite(i)||!Z(r))throw new Error("invalid isometric overlay footprint");return[[t[0]-o[0],t[1]-o[1]],[t[0]+o[0],t[1]-o[1]],[t[0]+o[0],t[1]+o[1]],[t[0]-o[0],t[1]+o[1]]].map(e=>{const t=n(e,i,a);return[t[0]+r[0],t[1]+r[1]]})}function se(e,t,n){return(t[0]-e[0])*(n[1]-e[1])-(t[1]-e[1])*(n[0]-e[0])}function le(e,t,n,o){const i=se(e,t,n),a=se(e,t,o),r=se(n,o,e),s=se(n,o,t);return(i>K&&a<-K||i<-K&&a>K)&&(r>K&&s<-K||r<-K&&s>K)||(Math.abs(i)<=K&&X(n,e,t)<=K||Math.abs(a)<=K&&X(o,e,t)<=K||Math.abs(r)<=K&&X(e,n,o)<=K||Math.abs(s)<=K&&X(t,n,o)<=K)}function ce(e,t,n,o){return le(e,t,n,o)?0:Math.min(X(e,n,o),X(t,n,o),X(n,e,t),X(o,e,t))}const de=new WeakMap;function he(e){if(!e.length)return null;let t=1/0,n=1/0,o=-1/0,i=-1/0;for(const a of e){if(!Z(a))return null;t=Math.min(t,a[0]),n=Math.min(n,a[1]),o=Math.max(o,a[0]),i=Math.max(i,a[1])}return[t,n,o,i]}function ue(e,t){if(!t)return he(e.outer);if(de.has(e))return de.get(e)??null;const n=he(e.outer);return de.set(e,n),n}function fe(e,t,n){return e[0]<=t[2]+n&&e[2]>=t[0]-n&&e[1]<=t[3]+n&&e[3]>=t[1]-n}function pe(e,t,n,o){return Math.min(t[0],n[0])<=e[2]+o&&Math.max(t[0],n[0])>=e[0]-o&&Math.min(t[1],n[1])<=e[3]+o&&Math.max(t[1],n[1])>=e[1]-o}function me(e,t,n,o,i){const a=ue(n,i);if(!a||!fe(t,a,o))return!1;if(e.some(e=>function(e,t){return!!ee(e,t.outer)&&!(t.holes||[]).some(t=>ee(e,t))}(e,n)))return!0;if(n.outer.some(n=>n[0]>=t[0]&&n[0]<=t[2]&&n[1]>=t[1]&&n[1]<=t[3]&&ee(n,e)))return!0;for(const i of[n.outer,...n.holes||[]])for(let n=0;n"wall-side"===e.layer?0:"wall-top"===e.layer?1:2,Me=e=>{if("wall-side"===e.layer)return`${e.face.polygon}:${e.face.ring}:${e.face.edge}`;if("wall-top"===e.layer)return String(e.face.component);const t=e.surface;return`${t.sourceIndex}:${t.leaf??-1}:${t.kind}:${t.jamb??-1}:${t.edge??""}:${t.id}:${t.material}`};function be(e,t){const n=[...e.sides.map(e=>({layer:"wall-side",depth:e.depth,face:e})),...e.topFaces.map(e=>({layer:"wall-top",depth:e.depth,face:e})),...t.map(e=>({layer:"opening",depth:e.depth,surface:e}))];return n.sort((e,t)=>e.depth-t.depth||xe(e)-xe(t)||Me(e).localeCompare(Me(t))),Object.freeze(n)}const Se=Object.freeze({textLatinAdvance:.72,textWideAsciiAdvance:1,textWideAdvance:1.1,textSpaceAdvance:.4,textWidthSafety:1.08,deviceShellInset:.134375,deviceShellGap:.1,deviceSectionGap:.08,deviceBadgeMinWidth:.7875,deviceBadgeHeight:.7875,deviceBadgeInlinePadding:.28,deviceValueInlinePadding:.32,deviceAuxiliaryExtent:.7,deviceLqiFontSize:.38,deviceLqiTop:.734375,deviceLqiBelowBottomBadgeTop:1.571875,devicePadding:.08,roomNameLineHeight:1.25,roomAreaLinkWidth:1.1,roomMetricsTopGap:.15,roomMetricFontSize:.75,roomMetricLineHeight:1.25,roomMetricIconWidth:1.05,roomMetricInnerGap:.12,roomMetricRowGap:.55,roomMetricMinWidth:11,roomPadding:.4,openingLockHalfSize:.62,roomMetricTextCharacters:Object.freeze({temperature:10,humidity:8,lqi:6,light:24})});function $e(e){return[...String(e)].reduce((e,t)=>/\s/.test(t)?e+Se.textSpaceAdvance:/[MW@#%&]/.test(t)?e+Se.textWideAsciiAdvance:e+(t.codePointAt(0)>255?Se.textWideAdvance:Se.textLatinAdvance),0)*Se.textWidthSafety}function ke(e,t){return $e(e)*z(t||e)}function ze(e,t){return[Math.max(Math.abs(e.left),Math.abs(e.right))+t,Math.max(Math.abs(e.top),Math.abs(e.bottom))+t]}function Ie(e){if("opening-lock"===e.kind){const t=(Number.isFinite(e.size)&&e.size>0?e.size:0)*Se.openingLockHalfSize;return[t,t]}if("room-label"===e.kind){const t=Number.isFinite(e.font)&&e.font>0?e.font:0,n=v(e.room.settings?.name_scale),o=v(e.room.settings?.label_scale),i=($e(e.room.name||"")+(e.room.area?Se.roomAreaLinkWidth:0))*n,a=Se.roomNameLineHeight*n,r=[e.display.labelTemp?Se.roomMetricTextCharacters.temperature:0,e.display.labelHum?Se.roomMetricTextCharacters.humidity:0,e.display.labelLqi&&e.room.area?Se.roomMetricTextCharacters.lqi:0,e.display.labelLight?Se.roomMetricTextCharacters.light:0].filter(e=>e>0),s=Se.roomMetricFontSize*o,l=r.length?Math.max(Se.roomMetricMinWidth,r.reduce((e,t)=>e+Se.roomMetricIconWidth+Se.roomMetricInnerGap+t*Se.textLatinAdvance*Se.textWidthSafety,0)+(r.length-1)*Se.roomMetricRowGap)*s:0,c=r.length?s*Se.roomMetricLineHeight:0,d=ze({left:-Math.max(i,l)/2,right:Math.max(i,l)/2,top:-a/2,bottom:r.length?a/2+Se.roomMetricsTopGap+c:a/2},Se.roomPadding);return[d[0]*t,d[1]*t]}const t=Number.isFinite(e.core)&&e.core>0?e.core:0,n=e.presentation,o=null==n.valueText?1:Math.max(1,ke(n.valueText,n.valueFullText||n.valueText)+Se.deviceValueInlinePadding),i=[];n.valueBadge&&i.push(Math.max(Se.deviceBadgeMinWidth,ke(n.valueBadge.text,n.valueBadge.fullText||n.valueBadge.text)+Se.deviceBadgeInlinePadding));for(const e of x(n)){const t=e.text+e.suffix;i.push(Math.max(Se.deviceBadgeMinWidth,ke(t,t)+Se.deviceBadgeInlinePadding))}const a=n.valueBadge?.position||"right";let r;if(!i.length||"left"!==a&&"right"!==a)if(i.length){const e=i.reduce((e,t)=>e+t,0)+(i.length-1)*Se.deviceSectionGap,t=Math.max(o,e),n=1+Se.deviceShellGap+Se.deviceBadgeHeight;r="bottom"===a?{left:-t/2-Se.deviceShellInset,right:t/2+Se.deviceShellInset,top:-.5-Se.deviceShellInset,bottom:-.5+n+Se.deviceShellInset}:{left:-t/2-Se.deviceShellInset,right:t/2+Se.deviceShellInset,top:.5-n-Se.deviceShellInset,bottom:.5+Se.deviceShellInset}}else r={left:-.5-Se.deviceShellInset,right:-.5+o+Se.deviceShellInset,top:-.5-Se.deviceShellInset,bottom:.5+Se.deviceShellInset};else{const e=Math.max(...i),t=i.length*Se.deviceBadgeHeight+(i.length-1)*Se.deviceSectionGap,n=o+Se.deviceShellGap+e,s=Math.max(1,t);r="right"===a?{left:-.5-Se.deviceShellInset,right:-.5+n+Se.deviceShellInset,top:-s/2-Se.deviceShellInset,bottom:s/2+Se.deviceShellInset}:{left:.5-n-Se.deviceShellInset,right:.5+Se.deviceShellInset,top:-s/2-Se.deviceShellInset,bottom:s/2+Se.deviceShellInset}}const s=Se.deviceAuxiliaryExtent;if(r.left=Math.min(r.left,-s),r.right=Math.max(r.right,s),r.top=Math.min(r.top,-s),r.bottom=Math.max(r.bottom,s),n.pulse.animated){const e=Math.max(1,n.pulse.diameterScale)/2;r.left=Math.min(r.left,-e),r.right=Math.max(r.right,e),r.top=Math.min(r.top,-e),r.bottom=Math.max(r.bottom,e)}if(null!=n.lqiText){const e="bottom"===n.valueBadge?.position?Se.deviceLqiBelowBottomBadgeTop:Se.deviceLqiTop,t=$e(n.lqiText)*Se.deviceLqiFontSize/2;r.left=Math.min(r.left,-t),r.right=Math.max(r.right,t),r.bottom=Math.max(r.bottom,e+Se.deviceLqiFontSize)}const l=ze(r,Se.devicePadding);return[l[0]*t,l[1]*t]}function Pe(e,t){return e.flatMap((e,n)=>e.orphanReason?[]:[{id:String(e.id||n),sourceIndex:n,type:e.type,x:e.rx,y:e.ry,angle:Number(e.angle)||0,length:e.rlen>0?e.rlen:.9*t,flipH:!!e.flip_h,flipV:!!e.flip_v}])}function Ce(e){return{id:e.id,x:e.x,y:e.y,w:e.w,h:e.h,poly:e.poly,wall_ids:e.wall_ids}}function je(e,t){const n=e?.partitionHost;if(!n)return null;const o="gate"===t.type?!t.flipV:t.flipV;return{sourceIndex:t.sourceIndex,hostId:n.host.id,t:n.t,depth:n.depth,face:p(n,o)}}function Ne(n,o=H){const i=Pe(n.openings,n.coordinateScale),r=i.map(e=>je(n.openings[e.sourceIndex],e)),p=a(t,n.cellCm),m=a(s,n.cellCm),g=a(l,n.cellCm);return{key:`${n.space.id}|${function(e){let t=2166136261;const n=e=>{if("number"!=typeof e)if("string"!=typeof e)if("boolean"!=typeof e)if(Array.isArray(e)){t=R(t,e.length);for(const t of e)n(t)}else{if(e&&"object"==typeof e){const t=e;for(const e of Object.keys(t).sort())n(e),n(t[e]);return}t=R(t,-1)}else t=R(t,e?1:0);else for(const n of e)t=R(t,n.codePointAt(0)||0);else t=R(t,e)};return n(e),t.toString(36)}({rooms:n.space.rooms.map(Ce),walls:n.walls,openCuts:n.openCuts,openings:i,openingHosts:r,openingGeometryPolicy:o,partitions:n.space.partitions,columns:n.space.wall_columns,cellCm:n.cellCm,gridPitch:n.gridPitch,wallKeyPitch:n.wallKeyPitch,camera:e,wallHeight:p,raisedHeight:g,floorEdgeHeight:m,algorithm:4})}`,build:()=>{n.onBuild();const a=c(n.space,n.cellCm,n.gridPitch,2e-4*n.gridPitch,n.partitionCuts()).all,s=n.roomOpenings(),l=n.walls.length||a.length?d(n.space.rooms,n.walls,n.openCuts,s,n.wallKeyPitch,n.cellCm,n.gridPitch,n.coordinateScale,a):null;if(l&&("failed-core"===l.status||"not-applicable"===l.status))throw new Error("wall boolean geometry failed");const m=l?.paperGeom??h(n.space.rooms,n.walls,n.openCuts,n.wallKeyPitch,n.cellCm,n.gridPitch,n.coordinateScale);if(!m)throw new Error("floor boolean geometry failed");const g=l?.openingIndex||u(n.space.rooms,n.walls,n.openCuts,n.wallKeyPitch,n.cellCm,n.gridPitch,n.coordinateScale),w=i.map((e,i)=>{const a=r[i],s="gate"===e.type?!e.flipV:e.flipV,l=a?a.face:n.walls.length||"gate"===e.type?f(g,{x:e.x,y:e.y,angle:e.angle,length:e.length,flip_v:s}):{ox:0,oy:0,cm:0,side:-1};return function(e,n=t,o=H){const i=e.face.cm??0;if(!F([e.x,e.y,e.angle,e.length,e.face.ox,e.face.oy,i,n])||!(e.length>0)||!(n>0)||-1!==e.face.side&&1!==e.face.side||i<0)throw new Error("invalid isometric opening input");const a=e.length/2,r=e.angle*Math.PI/180,s=T(Math.cos(r),Math.sin(r)),l=T(-Math.sin(r),Math.cos(r)),c=T(e.x,e.y),d=T(e.x-s[0]*a,e.y-s[1]*a),h=T(e.x+s[0]*a,e.y+s[1]*a),u=T(e.face.ox,e.face.oy),f=T(d[0]+u[0],d[1]+u[1]),p=T(h[0]+u[0],h[1]+u[1]),m=T(d[0]-u[0],d[1]-u[1]),g=T(h[0]-u[0],h[1]-u[1]),w=Object.freeze({center:c,tangent:s,normal:l,start:d,end:h}),y=Object.freeze({side:e.face.side,cm:i,depth:2*Math.hypot(e.face.ox,e.face.oy),offset:u,selectedStart:f,selectedEnd:p,oppositeStart:m,oppositeEnd:g}),v="passage"===e.type?[]:[Object.freeze({jamb:0,center:d,selected:f,opposite:m}),Object.freeze({jamb:1,center:h,selected:p,opposite:g})];let x;if("passage"===e.type)x=[];else if("gate"===e.type){const t=e.face.side*o.gateTurnDeg;x=[E(e,0,[-a,0],[a,0],t,0,n*o.gateTopRatio),E(e,1,[a,0],[-a,0],-t,0,n*o.gateTopRatio)]}else x="window"===e.type?[E(e,0,[-a,0],[a,0],-90,n*o.windowBottomRatio,n*o.windowTopRatio),E(e,1,[a,0],[-a,0],90,n*o.windowBottomRatio,n*o.windowTopRatio)]:[E(e,0,[-a,0],[e.length,0],-90,0,n*o.doorTopRatio)];return Object.freeze({id:e.id,sourceIndex:e.sourceIndex,type:e.type,wallHeight:n,leafThickness:n*o.leafThicknessRatio,frameThickness:n*o.frameThicknessRatio,axis:w,face:y,reveals:Object.freeze(v),leaves:Object.freeze(x.map(e=>Object.freeze({...e,hinge:T(e.hinge[0],e.hinge[1]),closedVector:T(e.closedVector[0],e.closedVector[1]),quarterVector:T(e.quarterVector[0],e.quarterVector[1])})))})}({...e,face:l},p,o)}),y=Object.freeze(w);return{walls:l?.components.flatMap(e=>e.geom)||[],floor:m,openings:y,openingSurfaces:Object.freeze(y.flatMap(t=>function(t,n=e){if("passage"===t.type)return Object.freeze([]);const o=[];if(t.face.depth>1e-9)for(const e of t.reveals)o.push(_("jamb-reveal","reveal",e.selected,e.opposite,0,t.wallHeight,n,{jamb:e.jamb}));if("window"!==t.type||!t.leaves.length)return Object.freeze(o.sort((e,t)=>e.depth-t.depth||e.kind.localeCompare(t.kind)||(e.jamb??0)-(t.jamb??0)));const i=Math.min(...t.leaves.map(e=>e.bottom)),a=Math.max(...t.leaves.map(e=>e.top)),r=Math.min(t.frameThickness,Math.hypot(t.axis.end[0]-t.axis.start[0],t.axis.end[1]-t.axis.start[1])/4,(a-i)/4),s=L(t.axis.start,G(t.axis.tangent,r)),l=V(t.axis.end,G(t.axis.tangent,r)),c=t.face.depth>1e-9?[t.face.offset,T(-t.face.offset[0],-t.face.offset[1])]:[t.face.offset];for(const e of c){const c=L(t.axis.start,e),d=L(t.axis.end,e),h=L(s,e),u=L(l,e);o.push(_("window-frame-side","light-frame",c,h,i,a,n,{jamb:0}),_("window-frame-side","light-frame",u,d,i,a,n,{jamb:1}),_("window-frame-top","light-frame",h,u,Math.max(i,a-r),a,n))}return t.face.depth>1e-9&&o.push(D("window-sill","light-sill",[{point:t.face.selectedStart,z:i},{point:t.face.selectedEnd,z:i},{point:t.face.oppositeEnd,z:i},{point:t.face.oppositeStart,z:i}],n)),Object.freeze(o.sort((e,t)=>e.depth-t.depth||e.kind.localeCompare(t.kind)||(e.jamb??0)-(t.jamb??0)))}(t).map(e=>Object.freeze({...e,id:t.id,sourceIndex:t.sourceIndex,type:t.type}))))}}}}const Oe=e=>Array.isArray(e)?e:[];function Ae(e,t){const o=e=>Oe(e).flatMap(e=>Array.isArray(e)&&Number.isFinite(e[0])&&Number.isFinite(e[1])?[n([Number(e[0]),Number(e[1])],t)]:[]);return Oe(e).flatMap(e=>{const t=Oe(e);if(!t.length)return[];const n=o(t[0]);if(n.length<3)return[];return[{outer:n,holes:t.slice(1).map(o).filter(e=>e.length>=3)}]})}function Be(o){const i=a(t,o.cellCm),r=a(s,o.cellCm),c=a(l,o.cellCm),d=S(o.cache,o.source.key);let h=d.hit?d.value:void 0;if(!h){const a=o.source.build(),s=function(o,i=e,a=t){if(!Number.isFinite(a)||a<0)throw new Error("invalid wall height");const r=[],s=[],l=[],c=[];let d=0;for(let e=0;e<(o||[]).length;e++){const t=o[e],h=[];let u=-1/0;for(let o=0;o<(t||[]).length;o++){const s=N(t[o],o>0);if(s.length<3||Math.abs(j(s))<1e-9)continue;const f=O(s,i,a);r.push(f),h.push(f),u=Math.max(u,...s.map(e=>n(e,a,i)[1])),d+=s.length;for(let t=0;te.depth-t.depth||e.polygon-t.polygon||e.ring-t.ring||e.edge-t.edge),s.sort((e,t)=>e.depth-t.depth||e.component-t.component),{topPath:r.join(" "),topFaces:s,sides:l,contactPath:c.join(" "),edgeCount:d}}(a.walls,e,i),l=Ae(a.walls,i);h={geometry:s,floor:B(a.floor,r),wallSilhouettes:Object.freeze([...l,...s.sides.map(e=>({outer:e.points}))]),openings:a.openings,openingSurfaces:a.openingSurfaces},$(o.cache,o.source.key,h,8)}const u=function(e){let t=1/0,n=1/0,o=-1/0,i=-1/0;const a=(e,a=0)=>{t=Math.min(t,e[0]-a),n=Math.min(n,e[1]-a),o=Math.max(o,e[0]+a),i=Math.max(i,e[1]+a)};for(const t of e)if("passage"!==t.type){a(t.axis.start),a(t.axis.end),a(t.face.selectedStart),a(t.face.selectedEnd),a(t.face.oppositeStart),a(t.face.oppositeEnd);for(const e of t.leaves){const n=Math.hypot(e.closedVector[0],e.closedVector[1])+t.leafThickness/2;a(e.hinge,n)}}return F([t,n,o,i])?{x:t,y:n,w:o-t,h:i-n}:null}(h.openings),f=u?Re(o.liveFrame,u):o.liveFrame,p=k({rect:f,wallHeight:i,openingHeight:i,floorDepth:r,raisedHeight:c});return{key:o.source.key,...h,frame:p}}const Re=(e,t)=>{const n=Math.min(e.x,t.x),o=Math.min(e.y,t.y);return{x:n,y:o,w:Math.max(e.x+e.w,t.x+t.w)-n,h:Math.max(e.y+e.h,t.y+t.h)-o}},He=e=>{if(!e.length||!e.every(e=>Number.isFinite(e[0])&&Number.isFinite(e[1])))return null;const t=e.map(e=>e[0]),n=e.map(e=>e[1]),o=Math.min(...t),i=Math.min(...n);return{x:o,y:i,w:Math.max(...t)-o,h:Math.max(...n)-i}},Fe=(e,t)=>{const n=e.placement,o=t?n.visualScene:n.raisedScene,[i,a]=e.screenHalfSize,r=t?n.footprint:n.footprint.map(e=>[e[0]-n.nudgeScene[0],e[1]-n.nudgeScene[1]]);return[n.floorScene,...r,[o[0]-i,o[1]-a],[o[0]+i,o[1]-a],[o[0]+i,o[1]+a],[o[0]-i,o[1]+a]]},Te=(e,t)=>void 0===t?e:e.filter(e=>e.placement.owner?.id===t);function Le(e,t){return e?He(Te(e.entries,t).flatMap(e=>Fe(e,!0))):null}function Ve(e){const t=Te(e.entries,e.ownerId),n=He(t.flatMap(e=>Fe(e,!1))),o=n?Re(e.baseBounds,n):e.baseBounds,i=e.targetView(o);if(!(i&&i.w>0&&i.h>0&&[i.x,i.y,i.w,i.h].every(Number.isFinite)))return null;const a=e.stageSize;if(!(n&&a&&a.width>0&&a.height>0))return{bounds:o,view:i};const r=e=>Math.max(e.w/a.width,e.h/a.height),s=t=>{const o=48*t,i={x:n.x-o,y:n.y-o,w:n.w+2*o,h:n.h+2*o},a=Re(e.baseBounds,i),r=e.targetView(a);return r&&[r.x,r.y,r.w,r.h].every(Number.isFinite)&&r.w>0&&r.h>0?{bounds:a,view:r}:null};let l=0,c=Math.max(r(i),Number.EPSILON),d=s(c);for(let e=0;d&&r(d.view)>c*(1+1e-10)&&e<24;e++)l=c,c*=2,d=s(c);if(!d)return null;for(let e=0;e<40;e++){const e=(l+c)/2,t=s(e);if(!t)return null;r(t.view)<=e?(c=e,d=t):l=e}return d}const Ge=new WeakMap,We=2048,Ee=new WeakMap,qe=new WeakMap,De=new WeakMap;function _e(e,t){if(e.size!==t.size)return!1;for(const[n,o]of t)if(e.get(n)!==o)return!1;return!0}function Ue(e){const t=Ge.get(e.rooms);if(t)return t;const n=e.rooms.flatMap((e,t)=>{const n=w(e);return n&&n.length>=3?[{room:e,index:t,poly:n}]:[]}),o=Object.freeze(n.map(({room:e,index:t,poly:o})=>{const i=y(o,n.filter(e=>e.index!==t).map(e=>e.poly)),a={id:e.id||`room-index-${t}`,outer:o.map(e=>[e[0],e[1]]),holes:i.map(e=>e.map(e=>[e[0],e[1]]))};return{room:e,overlayRoom:{...a,safePoint:ie(a)||void 0}}}));return Ge.set(e.rooms,o),o}function Ke(o){const s=o.stageSize&&o.stageSize.width>0&&o.stageSize.height>0?Math.max(o.view.w/o.stageSize.width,o.view.h/o.stageSize.height):Math.max(o.view.w,o.view.h)/1e3,l=Ue(o.space),c=l.map(e=>e.overlayRoom),d=a(t,o.cellCm),h=a(i,o.cellCm),u=new Map,f=new Map,p=new Map,m=[];let g=Ee.get(o.wallSilhouettes);g||(g=new Map,Ee.set(o.wallSilhouettes,g));let w=qe.get(l);w||(w=new Map,qe.set(l,w));const y=o.iconPct*r(o.space)*o.kioskIconScale/100,v=o.deviceBasePct*r(o.space)*o.kioskIconScale/100,x=(a,r,l,u,f,p=!1)=>{const m=`${!1===o.resolveCollisions?"fit":"live"}\0${a}\0${r}`,y=[l[0],l[1],u[0],u[1],f||"",d,h,o.layers.shadows?1:0,p?1:0].join("|"),v=`${y}|${s}`,x=S(g,m);if(x.hit&&x.value.signature===v)return x.value.placement;if(x.hit&&x.value.shapeSignature===y&&s<=x.value.unitsPerPixel){const e=x.value.placement,t=e.nudgeDistanceCss*x.value.unitsPerPixel/s;if(!e.nearWallBefore||e.cleared&&t<=48)return e}const M=`${a}\0${r}`,b=[l[0],l[1],f||""].join("|"),k=S(w,M),z=k.hit&&k.value.signature===b?k.value.owner:ae({kind:a,floorAnchor:l,rooms:c,roomsValidated:!0,preferredRoomId:f});k.hit&&k.value.signature===b||$(w,M,{signature:b,owner:z},We);const I=function(o){const a=o.camera||e,r=o.wallHeight??t,s=o.visualOffset??i,l=o.sceneUnitsPerCssPixel??1,c=o.safetyGapCssPx??4,d=o.maxNudgeCssPx??48;if(!Z(o.floorAnchor)||!Z(o.footprintHalfSize)||o.footprintHalfSize[0]<0||o.footprintHalfSize[1]<0||!Number.isFinite(r)||r<0||!Number.isFinite(s)||s<0||!Number.isFinite(l)||l<=0||!Number.isFinite(c)||c<0||!Number.isFinite(d)||d<0)throw new Error("invalid isometric overlay input");const h=[o.floorAnchor[0],o.floorAnchor[1]],u=n(h,0,a),f=(p=o.kind,!o.showBorders||"device"!==p&&"room-label"!==p&&"opening-lock"!==p?"floor":"raised");var p;if("floor"===f)return{plane:f,owner:null,floorAnchor:h,floorScene:u,raisedScene:u,visualScene:u,footprint:[],nudgeScene:[0,0],nudgeCss:[0,0],nudgeDistanceCss:0,nudged:!1,nearWallBefore:!1,nearWallAfter:!1,cleared:!0,capped:!1,grounding:{center:u,visible:!1},tether:ye(u,u,!1),status:"ok",reason:null};const m=r+s,g=n(h,m,a),w=o.ownerAlreadyResolved?o.resolvedOwner??null:ae(o),y=o.wallGeometryValidated??o.wallSilhouettes.every(ge),v=c*l,x=re(h,o.footprintHalfSize,m,a),M=e=>{const t=he(e);return!!t&&o.wallSilhouettes.some(n=>me(e,t,n,v,!0===o.wallGeometryValidated))},b=!y||M(x);let S=0,$=[0,0],k=null,z=!1,I=y?"ok":"degraded",P=y?null:"invalid-wall-geometry";if(y&&b)if(w)if(w.safePoint){const e=o.rooms.find(e=>e.id===w.id)||null,t=n(w.safePoint,m,a),i=t[0]-g[0],r=t[1]-g[1],s=Math.hypot(i,r);if(s<=K)I="degraded",P="invalid-safe-point";else{const t=i/s,n=r/s,a=Math.min(d,s/l),c=a*l/s,u=[h[0]+(w.safePoint[0]-h[0])*c,h[1]+(w.safePoint[1]-h[1])*c],f=[t*a*l,n*a*l],p=he([...x,...x.map(e=>[e[0]+f[0],e[1]+f[1]])]),m=p?o.wallSilhouettes.filter(e=>{const t=ue(e,!0===o.wallGeometryValidated);return!!t&&fe(p,t,v)}):o.wallSilhouettes,g=!!e&&we(h,u,e),y=e=>{const i=[t*e*l,n*e*l],a=x.map(e=>[e[0]+i[0],e[1]+i[1]]),r=he(a);return!!r&&m.some(e=>me(a,r,e,v,!0===o.wallGeometryValidated))},M=o.nudgeHintCss;if(Number.isFinite(M)&&M>=0&&M<=a){const t=M*l/s,n=[h[0]+(w.safePoint[0]-h[0])*t,h[1]+(w.safePoint[1]-h[1])*t];(g||e&&we(h,n,e))&&!y(M)&&(S=M,k=!1)}if(null===k){let t=null,n=0,o=!1;const i=Math.ceil(a);for(let r=1;r<=i;r++){const i=Math.min(a,r),c=i*l/s,d=[h[0]+(w.safePoint[0]-h[0])*c,h[1]+(w.safePoint[1]-h[1])*c];if(!(g||e&&we(h,d,e))){o=!0;break}if(!y(i)){t=i;break}n=i}if(null!==t){let e=n,o=t;for(let t=0;t<14;t++){const t=(e+o)/2;y(t)?e=t:o=t}S=o}else S=n,z=!0,I="degraded",P=o?"owner-boundary":"nudge-cap"}$=[t*S*l,n*S*l]}}else I="degraded",P="invalid-safe-point";else I="degraded",P="missing-owner";const C=[g[0]+$[0],g[1]+$[1]],j=re(h,o.footprintHalfSize,m,a,$),N=!y||(k??M(j)),O=S>K,A=O||b||N||!!o.hovered||!!o.focused||!!o.selected;return{plane:f,owner:w,floorAnchor:h,floorScene:u,raisedScene:g,visualScene:C,footprint:j,nudgeScene:$,nudgeCss:[$[0]/l,$[1]/l],nudgeDistanceCss:S,nudged:O,nearWallBefore:b,nearWallAfter:N,cleared:!N,capped:z,grounding:{center:u,visible:!1!==o.filtersSupported},tether:ye(u,C,A),status:I,reason:P}}({kind:a,floorAnchor:l,rooms:c,roomsValidated:!0,preferredRoomId:f,ownerAlreadyResolved:!0,resolvedOwner:z,nudgeHintCss:x.hit&&x.value.shapeSignature===y?x.value.placement.nudgeDistanceCss*x.value.unitsPerPixel/s:void 0,showBorders:!0,wallSilhouettes:!1===o.resolveCollisions?[]:o.wallSilhouettes,wallGeometryValidated:!0,footprintHalfSize:u,wallHeight:d,visualOffset:h,sceneUnitsPerCssPixel:s,filtersSupported:o.layers.shadows,hovered:!0,selected:p});return $(g,m,{signature:v,shapeSignature:y,unitsPerPixel:s,placement:I},We),I};for(const e of o.devices){const t=o.positionOf(e),n=o.presentationOf(e,o.showLqi),i=v*n.scale,a=Ie({kind:"device",core:i,presentation:n}),r=e.marker?.room_id||l.find(t=>!!e.area&&t.room.area===e.area)?.overlayRoom.id||null,s=x("device",e.id,[t.x,t.y],a,r,o.selectedDeviceId===e.id);u.set(e.id,s),m.push({id:e.id,kind:"device",placement:s,groundRadius:Math.max(.32*i,2),screenHalfSize:a})}for(const{room:e,overlayRoom:t}of l){if(!o.display.showNames||!e.name)continue;const n=o.labelPositionOf(e,o.space.id),i=.5*y*(o.labelScaleOf(e)*o.kioskFontScale*o.display.cardFontScale),a=Ie({kind:"room-label",font:i,room:e,display:o.display}),r=x("room-label",t.id,[n.x,n.y],a,t.id,o.focusedRoomId===e.id);f.set(e,r),m.push({id:t.id,kind:"room-label",placement:r,groundRadius:Math.max(.75*i,2),screenHalfSize:a})}const M=o.openings.filter(e=>!e.orphanReason&&("door"===e.type||"gate"===e.type)&&"string"==typeof e.lock&&!!e.lock&&o.openingEntityAvailable(e.lock));if(M.length){const e=o.openingWallIndex();for(const t of M){const n=Je(t,e,o.cellCm),i=n.floorAnchor,a=.62*y,r=Ie({kind:"opening-lock",size:a}),s=x("opening-lock",String(t.id),i,r,n.preferredRoomId,o.selectedOpeningId===t.id);p.set(String(t.id),s),m.push({id:String(t.id),kind:"opening-lock",placement:s,groundRadius:Math.max(.28*a,2),screenHalfSize:r})}}const b={devices:u,rooms:f,locks:p,entries:Object.freeze(m)},k=!1===o.resolveCollisions?"fit":"live";let z=De.get(o.wallSilhouettes);z||(z=new Map,De.set(o.wallSilhouettes,z));const I=z.get(k);return I&&function(e,t){return e.length===t.length&&t.every((t,n)=>{const o=e[n];return o.id===t.id&&o.kind===t.kind&&o.placement===t.placement&&o.groundRadius===t.groundRadius&&o.screenHalfSize[0]===t.screenHalfSize[0]&&o.screenHalfSize[1]===t.screenHalfSize[1]})}(I.entries,b.entries)&&_e(I.devices,b.devices)&&_e(I.rooms,b.rooms)&&_e(I.locks,b.locks)?I:(z.set(k,b),b)}function Ze(e,t,n){return Je(e,t,n).floorAnchor}function Je(e,t,n){const o=!e.flip_v,i="gate"===e.type?e.partitionHost?p(e.partitionHost,o):f(t,{x:e.rx,y:e.ry,angle:e.angle,length:e.rlen,flip_v:o}):null,[a,r]=m({x:e.rx,y:e.ry,angle:e.angle,flipV:!!e.flip_v,gateFace:i},n);if(e.partitionHost)return{floorAnchor:a,preferredRoomId:null};const s=g(t,{x:e.rx,y:e.ry,angle:e.angle,length:e.rlen},!0),l=r?"negative":"positive";return{floorAnchor:a,preferredRoomId:s[l]?.roomId||null}}function Qe(e){let t=!1;try{t="undefined"!=typeof CSS&&"function"==typeof CSS.supports&&CSS.supports("filter","blur(1px)")}catch{t=!1}let n=!1;try{n="function"==typeof matchMedia&&matchMedia("(forced-colors: active)").matches}catch{n=!0}return function(e){const t=!!e.showBorders;return{structural:t,panels:t&&!e.hideOpenings,shadows:t&&e.filtersSupported&&!e.forcedColors,materialNuance:t&&e.filtersSupported&&!e.forcedColors,floorSymbols:!e.hideOpenings&&!t}}({showBorders:e.showBorders,hideOpenings:e.hideOpenings,filtersSupported:t,forcedColors:n})}function Xe(e,t,n,o){if(!e.panels||!t)return[];return t.openings.flatMap(e=>{const t=n[e.sourceIndex];return t?U(e,o(t)):[]}).sort((e,t)=>e.depth-t.depth||e.sourceIndex-t.sourceIndex||e.leaf-t.leaf)}function Ye(e){const t=Qe(e.display),n=t.panels?Xe(t,e.scene,e.openings,e.amountOf):[],o=e.overlays(t),i=t=>({layers:t,panels:n,overlays:o,underlay:at(t,e.scene?.floor,e.cellCm),shadows:rt(t,n,e.scene?.geometry,e.cellCm),walls:st(e.projection,t,e.scene,n,e.cellCm),grounds:ot(o,t,e.cellCm),raised:it(o)});try{return i(t)}catch(e){if(!t.shadows&&!t.materialNuance)throw e;return i({...t,shadows:!1,materialNuance:!1})}}const et=()=>b``;function tt(e){return`translate(${a(4,e)} ${a(8,e)})`}function nt(e,t,n){const o=I(n);return b`
+globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="2e6f7d70c797ae4e865b10859c77cc3380a432272a975b8f35b51234ae3cfe62";import{dB as e,dC as t,b1 as n,dD as o,dE as i,h as a,dF as r,dG as s,dH as l,dI as c,a1 as d,dJ as h,ag as u,bU as f,bT as p,dK as m,ah as g,L as w,dL as y,cR as v,dM as x,A as M,w as b,dN as S,dO as $,dP as k,dQ as z,dR as I}from"./houseplan-card-BMuv6THL.js";import{i as P}from"./guard-8MebpCtO.js";const C=e=>`${Number(e[0].toFixed(4))} ${Number(e[1].toFixed(4))}`;function j(e){let t=0;for(let n=0;nArray.isArray(e)&&Number.isFinite(e[0])&&Number.isFinite(e[1])).map(e=>[Number(e[0]),Number(e[1])]),n=t[t.length-1];return t.length>1&&t[0][0]===n[0]&&t[0][1]===n[1]&&t.pop(),t}(e);if(n.length<3)return[];const o=!t;return j(n)>0===o?n:[...n].reverse()}function O(e,t,o){return e.length?`M ${e.map(e=>C(n(e,o,t))).join(" L ")} Z`:""}function A(e,t,n){const o=t[1]-e[1],i=-(t[0]-e[0]),a=n.rotDeg*Math.PI/180;return o*Math.sin(a)+i*Math.cos(a)}function B(t,o,i=e){if(!Number.isFinite(o)||o<0)throw new Error("invalid floor edge height");const a=(t||[]).map(e=>(e||[]).map((e,t)=>function(e,t){const n=N(e,t);if(!n.length)return n;let o=0;for(let e=1;e0)).filter(e=>e.length>=3&&Math.abs(j(e))>=1e-9)).filter(e=>e.length&&j(e[0])>0);a.sort((e,t)=>{const n=e[0][0],o=t[0][0];return n[0]-o[0]||n[1]-o[1]||Math.abs(j(t[0]))-Math.abs(j(e[0]))});const r=[],s=[];let l=0;for(let e=0;ee.depth-t.depth||e.component-t.component||e.edge-t.edge),{footprintPath:r.join(" "),sides:s,componentCount:a.length,edgeCount:l}}function R(e,t){return e^=Math.round(64*(Number.isFinite(t)?t:0)),Math.imul(e,16777619)>>>0}const H=Object.freeze({revision:1,leafThicknessRatio:.04,frameThicknessRatio:.055,gateTurnDeg:10,gateTopRatio:.88,windowBottomRatio:.27,windowTopRatio:.78,doorTopRatio:.92});H.leafThicknessRatio,H.frameThicknessRatio;const F=e=>e.every(Number.isFinite);function T(e,t){return Object.freeze([Object.is(e,-0)?0:e,Object.is(t,-0)?0:t])}function L(e,t){return[e[0]+t[0],e[1]+t[1]]}function V(e,t){return[e[0]-t[0],e[1]-t[1]]}function G(e,t){return[e[0]*t,e[1]*t]}function W(e,t,n,o){const i=e[0]*n,a=e[1]*o,r=t*Math.PI/180;return[i*Math.cos(r)-a*Math.sin(r),i*Math.sin(r)+a*Math.cos(r)]}function E(e,t,n,i,a,r,s){const l=e.flipH?-1:1,c="gate"===e.type?1:e.flipV?-1:1,d=o(e.type,e.flipV,e.angle,e.face);return{leaf:t,hinge:L([e.x+d.ox,e.y+d.oy],W(n,e.angle,l,c)),closedVector:W(i,e.angle,l,c),quarterVector:W([-i[1],i[0]],e.angle,l,c),turnDeg:a,bottom:r,top:s}}const q=e=>`${Number(e[0].toFixed(4))} ${Number(e[1].toFixed(4))}`;function D(e,t,o,i,a={}){const r=o.map(e=>n(e.point,e.z,i));return Object.freeze({kind:e,material:t,d:`M ${r.map(q).join(" L ")} Z`,depth:Math.max(...r.map(e=>e[1])),...a})}function _(e,t,n,o,i,a,r,s={}){return D(e,t,[{point:n,z:i},{point:o,z:i},{point:o,z:a},{point:n,z:a}],r,s)}function U(t,o,i=e){const a=Math.max(0,Math.min(1,Number.isFinite(o)?o:0));return t.leaves.map(e=>{const o=function(e,t){const n=e.turnDeg*t*Math.PI/180;return[e.hinge[0]+e.closedVector[0]*Math.cos(n)+e.quarterVector[0]*Math.sin(n),e.hinge[1]+e.closedVector[1]*Math.cos(n)+e.quarterVector[1]*Math.sin(n)]}(e,a),r=n(e.hinge,e.bottom,i),s=n(o,e.bottom,i),l=n(o,e.top,i),c=n(e.hinge,e.top,i),d="window"===t.type?"light-window":"matte-leaf",h="window"===t.type?Object.freeze([_("window-insert","light-window",e.hinge,o,e.bottom,e.top,i)]):function(e,t,n,o){const i=V(t,e.hinge),a=Math.hypot(i[0],i[1]);if(!(a>1e-9&&n>0))return Object.freeze([]);const r=T(-i[1]*n/(2*a),i[0]*n/(2*a)),s=L(e.hinge,r),l=L(t,r),c=V(e.hinge,r),d=V(t,r),h=[_("leaf-back","matte-leaf",d,c,e.bottom,e.top,o),_("leaf-front","matte-leaf",s,l,e.bottom,e.top,o),_("leaf-edge","matte-leaf",c,s,e.bottom,e.top,o,{edge:"hinge"}),_("leaf-edge","matte-leaf",l,d,e.bottom,e.top,o,{edge:"tip"}),D("leaf-top","matte-leaf",[{point:s,z:e.top},{point:c,z:e.top},{point:d,z:e.top},{point:l,z:e.top}],o)];return Object.freeze(h.sort((e,t)=>e.depth-t.depth||e.kind.localeCompare(t.kind)||String(e.edge||"").localeCompare(String(t.edge||""))))}(e,o,t.leafThickness,i);return Object.freeze({id:t.id,sourceIndex:t.sourceIndex,type:t.type,leaf:e.leaf,d:`M ${q(r)} L ${q(s)} L ${q(l)} L ${q(c)} Z`,shadowD:`M ${q(n(e.hinge,0,i))} L ${q(n(o,0,i))}`,depth:Math.max(r[1],s[1]),material:d,thickness:"window"===t.type?0:t.leafThickness,surfaces:h})})}const K=1e-9,Z=e=>e.length>=2&&Number.isFinite(e[0])&&Number.isFinite(e[1]);function J(e){let t=0;for(let n=0;n=3&&e.every(Z)&&Math.abs(J(e))>K}function X(e,t,n){const o=n[0]-t[0],i=n[1]-t[1],a=o*o+i*i,r=a?Math.max(0,Math.min(1,((e[0]-t[0])*o+(e[1]-t[1])*i)/a)):0;return Math.hypot(e[0]-t[0]-r*o,e[1]-t[1]-r*i)}function Y(e,t,n=1e-7){for(let o=0;oe[1]!=r[1]>e[1]&&e[0]<(r[0]-a[0])*(e[1]-a[1])/(r[1]-a[1])+a[0]&&(n=!n)}return n}function te(e){return Math.max(0,Math.abs(J(e.outer))-(e.holes||[]).reduce((e,t)=>e+Math.abs(J(t)),0))}function ne(e){return!!e.id&&Q(e.outer)&&(e.holes||[]).every(Q)&&te(e)>K}function oe(e,t){if(!ne(t)||Y(e,t.outer)||!ee(e,t.outer))return!1;for(const n of t.holes||[])if(Y(e,n)||ee(e,n))return!1;return!0}function ie(e){if(!ne(e))return null;if(e.safePoint&&oe(e.safePoint,e))return[e.safePoint[0],e.safePoint[1]];const t=e.outer.map(e=>e[0]),n=e.outer.map(e=>e[1]),o=Math.min(...t),i=Math.max(...t),a=Math.min(...n),r=Math.max(...n),s=[[(o+i)/2,(a+r)/2],[t.reduce((e,t)=>e+t,0)/t.length,n.reduce((e,t)=>e+t,0)/n.length]];for(let t=0;t{if(!oe(t,e))return;const n=function(e,t){let n=1/0;for(const o of[t.outer,...t.holes||[]])for(let t=0;tc+K&&(l=t,c=n)};s.forEach(d);for(let e=1;e<16;e++)for(let t=1;t<16;t++)d([o+(i-o)*e/16,a+(r-a)*t/16]);return l}function ae(e){if(!Z(e.floorAnchor))return null;const t=e.roomsValidated?e.rooms:e.rooms.filter(ne),n=e.preferredRoomId&&t.find(t=>t.id===e.preferredRoomId)||null;let o=null;return"device"===e.kind?(n&&oe(e.floorAnchor,n)&&(o=n),o||(o=t.filter(t=>oe(e.floorAnchor,t)).sort((e,t)=>te(e)-te(t)||((e,t)=>et?1:0)(e.id,t.id))[0]||null)):o=n,o?{id:o.id,area:te(o),safePoint:e.roomsValidated&&o.safePoint?[o.safePoint[0],o.safePoint[1]]:ie(o)}:null}function re(t,o,i,a=e,r=[0,0]){if(!Z(t)||!Z(o)||o[0]<0||o[1]<0||!Number.isFinite(i)||!Z(r))throw new Error("invalid isometric overlay footprint");return[[t[0]-o[0],t[1]-o[1]],[t[0]+o[0],t[1]-o[1]],[t[0]+o[0],t[1]+o[1]],[t[0]-o[0],t[1]+o[1]]].map(e=>{const t=n(e,i,a);return[t[0]+r[0],t[1]+r[1]]})}function se(e,t,n){return(t[0]-e[0])*(n[1]-e[1])-(t[1]-e[1])*(n[0]-e[0])}function le(e,t,n,o){const i=se(e,t,n),a=se(e,t,o),r=se(n,o,e),s=se(n,o,t);return(i>K&&a<-K||i<-K&&a>K)&&(r>K&&s<-K||r<-K&&s>K)||(Math.abs(i)<=K&&X(n,e,t)<=K||Math.abs(a)<=K&&X(o,e,t)<=K||Math.abs(r)<=K&&X(e,n,o)<=K||Math.abs(s)<=K&&X(t,n,o)<=K)}function ce(e,t,n,o){return le(e,t,n,o)?0:Math.min(X(e,n,o),X(t,n,o),X(n,e,t),X(o,e,t))}const de=new WeakMap;function he(e){if(!e.length)return null;let t=1/0,n=1/0,o=-1/0,i=-1/0;for(const a of e){if(!Z(a))return null;t=Math.min(t,a[0]),n=Math.min(n,a[1]),o=Math.max(o,a[0]),i=Math.max(i,a[1])}return[t,n,o,i]}function ue(e,t){if(!t)return he(e.outer);if(de.has(e))return de.get(e)??null;const n=he(e.outer);return de.set(e,n),n}function fe(e,t,n){return e[0]<=t[2]+n&&e[2]>=t[0]-n&&e[1]<=t[3]+n&&e[3]>=t[1]-n}function pe(e,t,n,o){return Math.min(t[0],n[0])<=e[2]+o&&Math.max(t[0],n[0])>=e[0]-o&&Math.min(t[1],n[1])<=e[3]+o&&Math.max(t[1],n[1])>=e[1]-o}function me(e,t,n,o,i){const a=ue(n,i);if(!a||!fe(t,a,o))return!1;if(e.some(e=>function(e,t){return!!ee(e,t.outer)&&!(t.holes||[]).some(t=>ee(e,t))}(e,n)))return!0;if(n.outer.some(n=>n[0]>=t[0]&&n[0]<=t[2]&&n[1]>=t[1]&&n[1]<=t[3]&&ee(n,e)))return!0;for(const i of[n.outer,...n.holes||[]])for(let n=0;n"wall-side"===e.layer?0:"wall-top"===e.layer?1:2,Me=e=>{if("wall-side"===e.layer)return`${e.face.polygon}:${e.face.ring}:${e.face.edge}`;if("wall-top"===e.layer)return String(e.face.component);const t=e.surface;return`${t.sourceIndex}:${t.leaf??-1}:${t.kind}:${t.jamb??-1}:${t.edge??""}:${t.id}:${t.material}`};function be(e,t){const n=[...e.sides.map(e=>({layer:"wall-side",depth:e.depth,face:e})),...e.topFaces.map(e=>({layer:"wall-top",depth:e.depth,face:e})),...t.map(e=>({layer:"opening",depth:e.depth,surface:e}))];return n.sort((e,t)=>e.depth-t.depth||xe(e)-xe(t)||Me(e).localeCompare(Me(t))),Object.freeze(n)}const Se=Object.freeze({textLatinAdvance:.72,textWideAsciiAdvance:1,textWideAdvance:1.1,textSpaceAdvance:.4,textWidthSafety:1.08,deviceShellInset:.134375,deviceShellGap:.1,deviceSectionGap:.08,deviceBadgeMinWidth:.7875,deviceBadgeHeight:.7875,deviceBadgeInlinePadding:.28,deviceValueInlinePadding:.32,deviceAuxiliaryExtent:.7,deviceLqiFontSize:.38,deviceLqiTop:.734375,deviceLqiBelowBottomBadgeTop:1.571875,devicePadding:.08,roomNameLineHeight:1.25,roomAreaLinkWidth:1.1,roomMetricsTopGap:.15,roomMetricFontSize:.75,roomMetricLineHeight:1.25,roomMetricIconWidth:1.05,roomMetricInnerGap:.12,roomMetricRowGap:.55,roomMetricMinWidth:11,roomPadding:.4,openingLockHalfSize:.62,roomMetricTextCharacters:Object.freeze({temperature:10,humidity:8,lqi:6,light:24})});function $e(e){return[...String(e)].reduce((e,t)=>/\s/.test(t)?e+Se.textSpaceAdvance:/[MW@#%&]/.test(t)?e+Se.textWideAsciiAdvance:e+(t.codePointAt(0)>255?Se.textWideAdvance:Se.textLatinAdvance),0)*Se.textWidthSafety}function ke(e,t){return $e(e)*z(t||e)}function ze(e,t){return[Math.max(Math.abs(e.left),Math.abs(e.right))+t,Math.max(Math.abs(e.top),Math.abs(e.bottom))+t]}function Ie(e){if("opening-lock"===e.kind){const t=(Number.isFinite(e.size)&&e.size>0?e.size:0)*Se.openingLockHalfSize;return[t,t]}if("room-label"===e.kind){const t=Number.isFinite(e.font)&&e.font>0?e.font:0,n=v(e.room.settings?.name_scale),o=v(e.room.settings?.label_scale),i=($e(e.room.name||"")+(e.room.area?Se.roomAreaLinkWidth:0))*n,a=Se.roomNameLineHeight*n,r=[e.display.labelTemp?Se.roomMetricTextCharacters.temperature:0,e.display.labelHum?Se.roomMetricTextCharacters.humidity:0,e.display.labelLqi&&e.room.area?Se.roomMetricTextCharacters.lqi:0,e.display.labelLight?Se.roomMetricTextCharacters.light:0].filter(e=>e>0),s=Se.roomMetricFontSize*o,l=r.length?Math.max(Se.roomMetricMinWidth,r.reduce((e,t)=>e+Se.roomMetricIconWidth+Se.roomMetricInnerGap+t*Se.textLatinAdvance*Se.textWidthSafety,0)+(r.length-1)*Se.roomMetricRowGap)*s:0,c=r.length?s*Se.roomMetricLineHeight:0,d=ze({left:-Math.max(i,l)/2,right:Math.max(i,l)/2,top:-a/2,bottom:r.length?a/2+Se.roomMetricsTopGap+c:a/2},Se.roomPadding);return[d[0]*t,d[1]*t]}const t=Number.isFinite(e.core)&&e.core>0?e.core:0,n=e.presentation,o=null==n.valueText?1:Math.max(1,ke(n.valueText,n.valueFullText||n.valueText)+Se.deviceValueInlinePadding),i=[];n.valueBadge&&i.push(Math.max(Se.deviceBadgeMinWidth,ke(n.valueBadge.text,n.valueBadge.fullText||n.valueBadge.text)+Se.deviceBadgeInlinePadding));for(const e of x(n)){const t=e.text+e.suffix;i.push(Math.max(Se.deviceBadgeMinWidth,ke(t,t)+Se.deviceBadgeInlinePadding))}const a=n.valueBadge?.position||"right";let r;if(!i.length||"left"!==a&&"right"!==a)if(i.length){const e=i.reduce((e,t)=>e+t,0)+(i.length-1)*Se.deviceSectionGap,t=Math.max(o,e),n=1+Se.deviceShellGap+Se.deviceBadgeHeight;r="bottom"===a?{left:-t/2-Se.deviceShellInset,right:t/2+Se.deviceShellInset,top:-.5-Se.deviceShellInset,bottom:-.5+n+Se.deviceShellInset}:{left:-t/2-Se.deviceShellInset,right:t/2+Se.deviceShellInset,top:.5-n-Se.deviceShellInset,bottom:.5+Se.deviceShellInset}}else r={left:-.5-Se.deviceShellInset,right:-.5+o+Se.deviceShellInset,top:-.5-Se.deviceShellInset,bottom:.5+Se.deviceShellInset};else{const e=Math.max(...i),t=i.length*Se.deviceBadgeHeight+(i.length-1)*Se.deviceSectionGap,n=o+Se.deviceShellGap+e,s=Math.max(1,t);r="right"===a?{left:-.5-Se.deviceShellInset,right:-.5+n+Se.deviceShellInset,top:-s/2-Se.deviceShellInset,bottom:s/2+Se.deviceShellInset}:{left:.5-n-Se.deviceShellInset,right:.5+Se.deviceShellInset,top:-s/2-Se.deviceShellInset,bottom:s/2+Se.deviceShellInset}}const s=Se.deviceAuxiliaryExtent;if(r.left=Math.min(r.left,-s),r.right=Math.max(r.right,s),r.top=Math.min(r.top,-s),r.bottom=Math.max(r.bottom,s),n.pulse.animated){const e=Math.max(1,n.pulse.diameterScale)/2;r.left=Math.min(r.left,-e),r.right=Math.max(r.right,e),r.top=Math.min(r.top,-e),r.bottom=Math.max(r.bottom,e)}if(null!=n.lqiText){const e="bottom"===n.valueBadge?.position?Se.deviceLqiBelowBottomBadgeTop:Se.deviceLqiTop,t=$e(n.lqiText)*Se.deviceLqiFontSize/2;r.left=Math.min(r.left,-t),r.right=Math.max(r.right,t),r.bottom=Math.max(r.bottom,e+Se.deviceLqiFontSize)}const l=ze(r,Se.devicePadding);return[l[0]*t,l[1]*t]}function Pe(e,t){return e.flatMap((e,n)=>e.orphanReason?[]:[{id:String(e.id||n),sourceIndex:n,type:e.type,x:e.rx,y:e.ry,angle:Number(e.angle)||0,length:e.rlen>0?e.rlen:.9*t,flipH:!!e.flip_h,flipV:!!e.flip_v}])}function Ce(e){return{id:e.id,x:e.x,y:e.y,w:e.w,h:e.h,poly:e.poly,wall_ids:e.wall_ids}}function je(e,t){const n=e?.partitionHost;if(!n)return null;const o="gate"===t.type?!t.flipV:t.flipV;return{sourceIndex:t.sourceIndex,hostId:n.host.id,t:n.t,depth:n.depth,face:p(n,o)}}function Ne(n,o=H){const i=Pe(n.openings,n.coordinateScale),r=i.map(e=>je(n.openings[e.sourceIndex],e)),p=a(t,n.cellCm),m=a(s,n.cellCm),g=a(l,n.cellCm);return{key:`${n.space.id}|${function(e){let t=2166136261;const n=e=>{if("number"!=typeof e)if("string"!=typeof e)if("boolean"!=typeof e)if(Array.isArray(e)){t=R(t,e.length);for(const t of e)n(t)}else{if(e&&"object"==typeof e){const t=e;for(const e of Object.keys(t).sort())n(e),n(t[e]);return}t=R(t,-1)}else t=R(t,e?1:0);else for(const n of e)t=R(t,n.codePointAt(0)||0);else t=R(t,e)};return n(e),t.toString(36)}({rooms:n.space.rooms.map(Ce),walls:n.walls,openCuts:n.openCuts,openings:i,openingHosts:r,openingGeometryPolicy:o,partitions:n.space.partitions,columns:n.space.wall_columns,cellCm:n.cellCm,gridPitch:n.gridPitch,wallKeyPitch:n.wallKeyPitch,camera:e,wallHeight:p,raisedHeight:g,floorEdgeHeight:m,algorithm:4})}`,build:()=>{n.onBuild();const a=c(n.space,n.cellCm,n.gridPitch,2e-4*n.gridPitch,n.partitionCuts()).all,s=n.roomOpenings(),l=n.walls.length||a.length?d(n.space.rooms,n.walls,n.openCuts,s,n.wallKeyPitch,n.cellCm,n.gridPitch,n.coordinateScale,a):null;if(l&&("failed-core"===l.status||"not-applicable"===l.status))throw new Error("wall boolean geometry failed");const m=l?.paperGeom??h(n.space.rooms,n.walls,n.openCuts,n.wallKeyPitch,n.cellCm,n.gridPitch,n.coordinateScale);if(!m)throw new Error("floor boolean geometry failed");const g=l?.openingIndex||u(n.space.rooms,n.walls,n.openCuts,n.wallKeyPitch,n.cellCm,n.gridPitch,n.coordinateScale),w=i.map((e,i)=>{const a=r[i],s="gate"===e.type?!e.flipV:e.flipV,l=a?a.face:n.walls.length||"gate"===e.type?f(g,{x:e.x,y:e.y,angle:e.angle,length:e.length,flip_v:s}):{ox:0,oy:0,cm:0,side:-1};return function(e,n=t,o=H){const i=e.face.cm??0;if(!F([e.x,e.y,e.angle,e.length,e.face.ox,e.face.oy,i,n])||!(e.length>0)||!(n>0)||-1!==e.face.side&&1!==e.face.side||i<0)throw new Error("invalid isometric opening input");const a=e.length/2,r=e.angle*Math.PI/180,s=T(Math.cos(r),Math.sin(r)),l=T(-Math.sin(r),Math.cos(r)),c=T(e.x,e.y),d=T(e.x-s[0]*a,e.y-s[1]*a),h=T(e.x+s[0]*a,e.y+s[1]*a),u=T(e.face.ox,e.face.oy),f=T(d[0]+u[0],d[1]+u[1]),p=T(h[0]+u[0],h[1]+u[1]),m=T(d[0]-u[0],d[1]-u[1]),g=T(h[0]-u[0],h[1]-u[1]),w=Object.freeze({center:c,tangent:s,normal:l,start:d,end:h}),y=Object.freeze({side:e.face.side,cm:i,depth:2*Math.hypot(e.face.ox,e.face.oy),offset:u,selectedStart:f,selectedEnd:p,oppositeStart:m,oppositeEnd:g}),v="passage"===e.type?[]:[Object.freeze({jamb:0,center:d,selected:f,opposite:m}),Object.freeze({jamb:1,center:h,selected:p,opposite:g})];let x;if("passage"===e.type)x=[];else if("gate"===e.type){const t=e.face.side*o.gateTurnDeg;x=[E(e,0,[-a,0],[a,0],t,0,n*o.gateTopRatio),E(e,1,[a,0],[-a,0],-t,0,n*o.gateTopRatio)]}else x="window"===e.type?[E(e,0,[-a,0],[a,0],-90,n*o.windowBottomRatio,n*o.windowTopRatio),E(e,1,[a,0],[-a,0],90,n*o.windowBottomRatio,n*o.windowTopRatio)]:[E(e,0,[-a,0],[e.length,0],-90,0,n*o.doorTopRatio)];return Object.freeze({id:e.id,sourceIndex:e.sourceIndex,type:e.type,wallHeight:n,leafThickness:n*o.leafThicknessRatio,frameThickness:n*o.frameThicknessRatio,axis:w,face:y,reveals:Object.freeze(v),leaves:Object.freeze(x.map(e=>Object.freeze({...e,hinge:T(e.hinge[0],e.hinge[1]),closedVector:T(e.closedVector[0],e.closedVector[1]),quarterVector:T(e.quarterVector[0],e.quarterVector[1])})))})}({...e,face:l},p,o)}),y=Object.freeze(w);return{walls:l?.components.flatMap(e=>e.geom)||[],floor:m,openings:y,openingSurfaces:Object.freeze(y.flatMap(t=>function(t,n=e){if("passage"===t.type)return Object.freeze([]);const o=[];if(t.face.depth>1e-9)for(const e of t.reveals)o.push(_("jamb-reveal","reveal",e.selected,e.opposite,0,t.wallHeight,n,{jamb:e.jamb}));if("window"!==t.type||!t.leaves.length)return Object.freeze(o.sort((e,t)=>e.depth-t.depth||e.kind.localeCompare(t.kind)||(e.jamb??0)-(t.jamb??0)));const i=Math.min(...t.leaves.map(e=>e.bottom)),a=Math.max(...t.leaves.map(e=>e.top)),r=Math.min(t.frameThickness,Math.hypot(t.axis.end[0]-t.axis.start[0],t.axis.end[1]-t.axis.start[1])/4,(a-i)/4),s=L(t.axis.start,G(t.axis.tangent,r)),l=V(t.axis.end,G(t.axis.tangent,r)),c=t.face.depth>1e-9?[t.face.offset,T(-t.face.offset[0],-t.face.offset[1])]:[t.face.offset];for(const e of c){const c=L(t.axis.start,e),d=L(t.axis.end,e),h=L(s,e),u=L(l,e);o.push(_("window-frame-side","light-frame",c,h,i,a,n,{jamb:0}),_("window-frame-side","light-frame",u,d,i,a,n,{jamb:1}),_("window-frame-top","light-frame",h,u,Math.max(i,a-r),a,n))}return t.face.depth>1e-9&&o.push(D("window-sill","light-sill",[{point:t.face.selectedStart,z:i},{point:t.face.selectedEnd,z:i},{point:t.face.oppositeEnd,z:i},{point:t.face.oppositeStart,z:i}],n)),Object.freeze(o.sort((e,t)=>e.depth-t.depth||e.kind.localeCompare(t.kind)||(e.jamb??0)-(t.jamb??0)))}(t).map(e=>Object.freeze({...e,id:t.id,sourceIndex:t.sourceIndex,type:t.type}))))}}}}const Oe=e=>Array.isArray(e)?e:[];function Ae(e,t){const o=e=>Oe(e).flatMap(e=>Array.isArray(e)&&Number.isFinite(e[0])&&Number.isFinite(e[1])?[n([Number(e[0]),Number(e[1])],t)]:[]);return Oe(e).flatMap(e=>{const t=Oe(e);if(!t.length)return[];const n=o(t[0]);if(n.length<3)return[];return[{outer:n,holes:t.slice(1).map(o).filter(e=>e.length>=3)}]})}function Be(o){const i=a(t,o.cellCm),r=a(s,o.cellCm),c=a(l,o.cellCm),d=S(o.cache,o.source.key);let h=d.hit?d.value:void 0;if(!h){const a=o.source.build(),s=function(o,i=e,a=t){if(!Number.isFinite(a)||a<0)throw new Error("invalid wall height");const r=[],s=[],l=[],c=[];let d=0;for(let e=0;e<(o||[]).length;e++){const t=o[e],h=[];let u=-1/0;for(let o=0;o<(t||[]).length;o++){const s=N(t[o],o>0);if(s.length<3||Math.abs(j(s))<1e-9)continue;const f=O(s,i,a);r.push(f),h.push(f),u=Math.max(u,...s.map(e=>n(e,a,i)[1])),d+=s.length;for(let t=0;te.depth-t.depth||e.polygon-t.polygon||e.ring-t.ring||e.edge-t.edge),s.sort((e,t)=>e.depth-t.depth||e.component-t.component),{topPath:r.join(" "),topFaces:s,sides:l,contactPath:c.join(" "),edgeCount:d}}(a.walls,e,i),l=Ae(a.walls,i);h={geometry:s,floor:B(a.floor,r),wallSilhouettes:Object.freeze([...l,...s.sides.map(e=>({outer:e.points}))]),openings:a.openings,openingSurfaces:a.openingSurfaces},$(o.cache,o.source.key,h,8)}const u=function(e){let t=1/0,n=1/0,o=-1/0,i=-1/0;const a=(e,a=0)=>{t=Math.min(t,e[0]-a),n=Math.min(n,e[1]-a),o=Math.max(o,e[0]+a),i=Math.max(i,e[1]+a)};for(const t of e)if("passage"!==t.type){a(t.axis.start),a(t.axis.end),a(t.face.selectedStart),a(t.face.selectedEnd),a(t.face.oppositeStart),a(t.face.oppositeEnd);for(const e of t.leaves){const n=Math.hypot(e.closedVector[0],e.closedVector[1])+t.leafThickness/2;a(e.hinge,n)}}return F([t,n,o,i])?{x:t,y:n,w:o-t,h:i-n}:null}(h.openings),f=u?Re(o.liveFrame,u):o.liveFrame,p=k({rect:f,wallHeight:i,openingHeight:i,floorDepth:r,raisedHeight:c});return{key:o.source.key,...h,frame:p}}const Re=(e,t)=>{const n=Math.min(e.x,t.x),o=Math.min(e.y,t.y);return{x:n,y:o,w:Math.max(e.x+e.w,t.x+t.w)-n,h:Math.max(e.y+e.h,t.y+t.h)-o}},He=e=>{if(!e.length||!e.every(e=>Number.isFinite(e[0])&&Number.isFinite(e[1])))return null;const t=e.map(e=>e[0]),n=e.map(e=>e[1]),o=Math.min(...t),i=Math.min(...n);return{x:o,y:i,w:Math.max(...t)-o,h:Math.max(...n)-i}},Fe=(e,t)=>{const n=e.placement,o=t?n.visualScene:n.raisedScene,[i,a]=e.screenHalfSize,r=t?n.footprint:n.footprint.map(e=>[e[0]-n.nudgeScene[0],e[1]-n.nudgeScene[1]]);return[n.floorScene,...r,[o[0]-i,o[1]-a],[o[0]+i,o[1]-a],[o[0]+i,o[1]+a],[o[0]-i,o[1]+a]]},Te=(e,t)=>void 0===t?e:e.filter(e=>e.placement.owner?.id===t);function Le(e,t){return e?He(Te(e.entries,t).flatMap(e=>Fe(e,!0))):null}function Ve(e){const t=Te(e.entries,e.ownerId),n=He(t.flatMap(e=>Fe(e,!1))),o=n?Re(e.baseBounds,n):e.baseBounds,i=e.targetView(o);if(!(i&&i.w>0&&i.h>0&&[i.x,i.y,i.w,i.h].every(Number.isFinite)))return null;const a=e.stageSize;if(!(n&&a&&a.width>0&&a.height>0))return{bounds:o,view:i};const r=e=>Math.max(e.w/a.width,e.h/a.height),s=t=>{const o=48*t,i={x:n.x-o,y:n.y-o,w:n.w+2*o,h:n.h+2*o},a=Re(e.baseBounds,i),r=e.targetView(a);return r&&[r.x,r.y,r.w,r.h].every(Number.isFinite)&&r.w>0&&r.h>0?{bounds:a,view:r}:null};let l=0,c=Math.max(r(i),Number.EPSILON),d=s(c);for(let e=0;d&&r(d.view)>c*(1+1e-10)&&e<24;e++)l=c,c*=2,d=s(c);if(!d)return null;for(let e=0;e<40;e++){const e=(l+c)/2,t=s(e);if(!t)return null;r(t.view)<=e?(c=e,d=t):l=e}return d}const Ge=new WeakMap,We=2048,Ee=new WeakMap,qe=new WeakMap,De=new WeakMap;function _e(e,t){if(e.size!==t.size)return!1;for(const[n,o]of t)if(e.get(n)!==o)return!1;return!0}function Ue(e){const t=Ge.get(e.rooms);if(t)return t;const n=e.rooms.flatMap((e,t)=>{const n=w(e);return n&&n.length>=3?[{room:e,index:t,poly:n}]:[]}),o=Object.freeze(n.map(({room:e,index:t,poly:o})=>{const i=y(o,n.filter(e=>e.index!==t).map(e=>e.poly)),a={id:e.id||`room-index-${t}`,outer:o.map(e=>[e[0],e[1]]),holes:i.map(e=>e.map(e=>[e[0],e[1]]))};return{room:e,overlayRoom:{...a,safePoint:ie(a)||void 0}}}));return Ge.set(e.rooms,o),o}function Ke(o){const s=o.stageSize&&o.stageSize.width>0&&o.stageSize.height>0?Math.max(o.view.w/o.stageSize.width,o.view.h/o.stageSize.height):Math.max(o.view.w,o.view.h)/1e3,l=Ue(o.space),c=l.map(e=>e.overlayRoom),d=a(t,o.cellCm),h=a(i,o.cellCm),u=new Map,f=new Map,p=new Map,m=[];let g=Ee.get(o.wallSilhouettes);g||(g=new Map,Ee.set(o.wallSilhouettes,g));let w=qe.get(l);w||(w=new Map,qe.set(l,w));const y=o.iconPct*r(o.space)*o.kioskIconScale/100,v=o.deviceBasePct*r(o.space)*o.kioskIconScale/100,x=(a,r,l,u,f,p=!1)=>{const m=`${!1===o.resolveCollisions?"fit":"live"}\0${a}\0${r}`,y=[l[0],l[1],u[0],u[1],f||"",d,h,o.layers.shadows?1:0,p?1:0].join("|"),v=`${y}|${s}`,x=S(g,m);if(x.hit&&x.value.signature===v)return x.value.placement;if(x.hit&&x.value.shapeSignature===y&&s<=x.value.unitsPerPixel){const e=x.value.placement,t=e.nudgeDistanceCss*x.value.unitsPerPixel/s;if(!e.nearWallBefore||e.cleared&&t<=48)return e}const M=`${a}\0${r}`,b=[l[0],l[1],f||""].join("|"),k=S(w,M),z=k.hit&&k.value.signature===b?k.value.owner:ae({kind:a,floorAnchor:l,rooms:c,roomsValidated:!0,preferredRoomId:f});k.hit&&k.value.signature===b||$(w,M,{signature:b,owner:z},We);const I=function(o){const a=o.camera||e,r=o.wallHeight??t,s=o.visualOffset??i,l=o.sceneUnitsPerCssPixel??1,c=o.safetyGapCssPx??4,d=o.maxNudgeCssPx??48;if(!Z(o.floorAnchor)||!Z(o.footprintHalfSize)||o.footprintHalfSize[0]<0||o.footprintHalfSize[1]<0||!Number.isFinite(r)||r<0||!Number.isFinite(s)||s<0||!Number.isFinite(l)||l<=0||!Number.isFinite(c)||c<0||!Number.isFinite(d)||d<0)throw new Error("invalid isometric overlay input");const h=[o.floorAnchor[0],o.floorAnchor[1]],u=n(h,0,a),f=(p=o.kind,!o.showBorders||"device"!==p&&"room-label"!==p&&"opening-lock"!==p?"floor":"raised");var p;if("floor"===f)return{plane:f,owner:null,floorAnchor:h,floorScene:u,raisedScene:u,visualScene:u,footprint:[],nudgeScene:[0,0],nudgeCss:[0,0],nudgeDistanceCss:0,nudged:!1,nearWallBefore:!1,nearWallAfter:!1,cleared:!0,capped:!1,grounding:{center:u,visible:!1},tether:ye(u,u,!1),status:"ok",reason:null};const m=r+s,g=n(h,m,a),w=o.ownerAlreadyResolved?o.resolvedOwner??null:ae(o),y=o.wallGeometryValidated??o.wallSilhouettes.every(ge),v=c*l,x=re(h,o.footprintHalfSize,m,a),M=e=>{const t=he(e);return!!t&&o.wallSilhouettes.some(n=>me(e,t,n,v,!0===o.wallGeometryValidated))},b=!y||M(x);let S=0,$=[0,0],k=null,z=!1,I=y?"ok":"degraded",P=y?null:"invalid-wall-geometry";if(y&&b)if(w)if(w.safePoint){const e=o.rooms.find(e=>e.id===w.id)||null,t=n(w.safePoint,m,a),i=t[0]-g[0],r=t[1]-g[1],s=Math.hypot(i,r);if(s<=K)I="degraded",P="invalid-safe-point";else{const t=i/s,n=r/s,a=Math.min(d,s/l),c=a*l/s,u=[h[0]+(w.safePoint[0]-h[0])*c,h[1]+(w.safePoint[1]-h[1])*c],f=[t*a*l,n*a*l],p=he([...x,...x.map(e=>[e[0]+f[0],e[1]+f[1]])]),m=p?o.wallSilhouettes.filter(e=>{const t=ue(e,!0===o.wallGeometryValidated);return!!t&&fe(p,t,v)}):o.wallSilhouettes,g=!!e&&we(h,u,e),y=e=>{const i=[t*e*l,n*e*l],a=x.map(e=>[e[0]+i[0],e[1]+i[1]]),r=he(a);return!!r&&m.some(e=>me(a,r,e,v,!0===o.wallGeometryValidated))},M=o.nudgeHintCss;if(Number.isFinite(M)&&M>=0&&M<=a){const t=M*l/s,n=[h[0]+(w.safePoint[0]-h[0])*t,h[1]+(w.safePoint[1]-h[1])*t];(g||e&&we(h,n,e))&&!y(M)&&(S=M,k=!1)}if(null===k){let t=null,n=0,o=!1;const i=Math.ceil(a);for(let r=1;r<=i;r++){const i=Math.min(a,r),c=i*l/s,d=[h[0]+(w.safePoint[0]-h[0])*c,h[1]+(w.safePoint[1]-h[1])*c];if(!(g||e&&we(h,d,e))){o=!0;break}if(!y(i)){t=i;break}n=i}if(null!==t){let e=n,o=t;for(let t=0;t<14;t++){const t=(e+o)/2;y(t)?e=t:o=t}S=o}else S=n,z=!0,I="degraded",P=o?"owner-boundary":"nudge-cap"}$=[t*S*l,n*S*l]}}else I="degraded",P="invalid-safe-point";else I="degraded",P="missing-owner";const C=[g[0]+$[0],g[1]+$[1]],j=re(h,o.footprintHalfSize,m,a,$),N=!y||(k??M(j)),O=S>K,A=O||b||N||!!o.hovered||!!o.focused||!!o.selected;return{plane:f,owner:w,floorAnchor:h,floorScene:u,raisedScene:g,visualScene:C,footprint:j,nudgeScene:$,nudgeCss:[$[0]/l,$[1]/l],nudgeDistanceCss:S,nudged:O,nearWallBefore:b,nearWallAfter:N,cleared:!N,capped:z,grounding:{center:u,visible:!1!==o.filtersSupported},tether:ye(u,C,A),status:I,reason:P}}({kind:a,floorAnchor:l,rooms:c,roomsValidated:!0,preferredRoomId:f,ownerAlreadyResolved:!0,resolvedOwner:z,nudgeHintCss:x.hit&&x.value.shapeSignature===y?x.value.placement.nudgeDistanceCss*x.value.unitsPerPixel/s:void 0,showBorders:!0,wallSilhouettes:!1===o.resolveCollisions?[]:o.wallSilhouettes,wallGeometryValidated:!0,footprintHalfSize:u,wallHeight:d,visualOffset:h,sceneUnitsPerCssPixel:s,filtersSupported:o.layers.shadows,hovered:!0,selected:p});return $(g,m,{signature:v,shapeSignature:y,unitsPerPixel:s,placement:I},We),I};for(const e of o.devices){const t=o.positionOf(e),n=o.presentationOf(e,o.showLqi),i=v*n.scale,a=Ie({kind:"device",core:i,presentation:n}),r=e.marker?.room_id||l.find(t=>!!e.area&&t.room.area===e.area)?.overlayRoom.id||null,s=x("device",e.id,[t.x,t.y],a,r,o.selectedDeviceId===e.id);u.set(e.id,s),m.push({id:e.id,kind:"device",placement:s,groundRadius:Math.max(.32*i,2),screenHalfSize:a})}for(const{room:e,overlayRoom:t}of l){if(!o.display.showNames||!e.name)continue;const n=o.labelPositionOf(e,o.space.id),i=.5*y*(o.labelScaleOf(e)*o.kioskFontScale*o.display.cardFontScale),a=Ie({kind:"room-label",font:i,room:e,display:o.display}),r=x("room-label",t.id,[n.x,n.y],a,t.id,o.focusedRoomId===e.id);f.set(e,r),m.push({id:t.id,kind:"room-label",placement:r,groundRadius:Math.max(.75*i,2),screenHalfSize:a})}const M=o.openings.filter(e=>!e.orphanReason&&("door"===e.type||"gate"===e.type)&&"string"==typeof e.lock&&!!e.lock&&o.openingEntityAvailable(e.lock));if(M.length){const e=o.openingWallIndex();for(const t of M){const n=Je(t,e,o.cellCm),i=n.floorAnchor,a=.62*y,r=Ie({kind:"opening-lock",size:a}),s=x("opening-lock",String(t.id),i,r,n.preferredRoomId,o.selectedOpeningId===t.id);p.set(String(t.id),s),m.push({id:String(t.id),kind:"opening-lock",placement:s,groundRadius:Math.max(.28*a,2),screenHalfSize:r})}}const b={devices:u,rooms:f,locks:p,entries:Object.freeze(m)},k=!1===o.resolveCollisions?"fit":"live";let z=De.get(o.wallSilhouettes);z||(z=new Map,De.set(o.wallSilhouettes,z));const I=z.get(k);return I&&function(e,t){return e.length===t.length&&t.every((t,n)=>{const o=e[n];return o.id===t.id&&o.kind===t.kind&&o.placement===t.placement&&o.groundRadius===t.groundRadius&&o.screenHalfSize[0]===t.screenHalfSize[0]&&o.screenHalfSize[1]===t.screenHalfSize[1]})}(I.entries,b.entries)&&_e(I.devices,b.devices)&&_e(I.rooms,b.rooms)&&_e(I.locks,b.locks)?I:(z.set(k,b),b)}function Ze(e,t,n){return Je(e,t,n).floorAnchor}function Je(e,t,n){const o=!e.flip_v,i="gate"===e.type?e.partitionHost?p(e.partitionHost,o):f(t,{x:e.rx,y:e.ry,angle:e.angle,length:e.rlen,flip_v:o}):null,[a,r]=m({x:e.rx,y:e.ry,angle:e.angle,flipV:!!e.flip_v,gateFace:i},n);if(e.partitionHost)return{floorAnchor:a,preferredRoomId:null};const s=g(t,{x:e.rx,y:e.ry,angle:e.angle,length:e.rlen},!0),l=r?"negative":"positive";return{floorAnchor:a,preferredRoomId:s[l]?.roomId||null}}function Qe(e){let t=!1;try{t="undefined"!=typeof CSS&&"function"==typeof CSS.supports&&CSS.supports("filter","blur(1px)")}catch{t=!1}let n=!1;try{n="function"==typeof matchMedia&&matchMedia("(forced-colors: active)").matches}catch{n=!0}return function(e){const t=!!e.showBorders;return{structural:t,panels:t&&!e.hideOpenings,shadows:t&&e.filtersSupported&&!e.forcedColors,materialNuance:t&&e.filtersSupported&&!e.forcedColors,floorSymbols:!e.hideOpenings&&!t}}({showBorders:e.showBorders,hideOpenings:e.hideOpenings,filtersSupported:t,forcedColors:n})}function Xe(e,t,n,o){if(!e.panels||!t)return[];return t.openings.flatMap(e=>{const t=n[e.sourceIndex];return t?U(e,o(t)):[]}).sort((e,t)=>e.depth-t.depth||e.sourceIndex-t.sourceIndex||e.leaf-t.leaf)}function Ye(e){const t=Qe(e.display),n=t.panels?Xe(t,e.scene,e.openings,e.amountOf):[],o=e.overlays(t),i=t=>({layers:t,panels:n,overlays:o,underlay:at(t,e.scene?.floor,e.cellCm),shadows:rt(t,n,e.scene?.geometry,e.cellCm),walls:st(e.projection,t,e.scene,n,e.cellCm),grounds:ot(o,t,e.cellCm),raised:it(o)});try{return i(t)}catch(e){if(!t.shadows&&!t.materialNuance)throw e;return i({...t,shadows:!1,materialNuance:!1})}}const et=()=>b``;function tt(e){return`translate(${a(4,e)} ${a(8,e)})`}function nt(e,t,n){const o=I(n);return b`
${"walls"===t&&e.materialNuance?b`
diff --git a/custom_components/houseplan/frontend/houseplan-assets/live-interaction-runtime-rm6xNkUs.js b/custom_components/houseplan/frontend/houseplan-assets/live-interaction-runtime-DCcaRZ3p.js
similarity index 96%
rename from custom_components/houseplan/frontend/houseplan-assets/live-interaction-runtime-rm6xNkUs.js
rename to custom_components/houseplan/frontend/houseplan-assets/live-interaction-runtime-DCcaRZ3p.js
index 3c58761b..1d164a91 100644
--- a/custom_components/houseplan/frontend/houseplan-assets/live-interaction-runtime-rm6xNkUs.js
+++ b/custom_components/houseplan/frontend/houseplan-assets/live-interaction-runtime-DCcaRZ3p.js
@@ -1 +1 @@
-globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="c8d5c166e30a11241ef32c7e1dc70368632e84c448524a8340494350ec4d5fca";import{e7 as e}from"./houseplan-card-DXAxXz4t.js";const t=new WeakMap,n=e=>{let n=t.get(e);return n||(n={painted:null,pending:null,raf:0},t.set(e,n)),n},o=e=>`${e.x} ${e.y} ${e.w} ${e.h}`;const r=e=>0===e.translateXPercent&&0===e.translateYPercent&&1===e.scaleX&&1===e.scaleY,a=e=>[e.x,e.y,e.w,e.h].every(Number.isFinite)&&e.w>0&&e.h>0,s=(e,t)=>{if(!t)return e.style.removeProperty("transform"),e.style.removeProperty("transform-origin"),void e.style.removeProperty("will-change");e.style.transformOrigin="0 0",e.style.willChange="transform",e.style.transform=`translate(${t.translateXPercent}%,${t.translateYPercent}%) scale(${t.scaleX},${t.scaleY})`};function i(e,t,n){if(!a(t.view)||!a(n.view)||!a(n.floor))return;const i=o(n.view),l=o(n.floor);for(const t of e.querySelectorAll('[data-hp-live-viewbox="camera"]'))t.setAttribute("viewBox",i);for(const t of e.querySelectorAll('[data-hp-live-viewbox="floor"]'))t.setAttribute("viewBox",l);const c=(f=t.view,u=n.view,{translateXPercent:(f.x-u.x)/u.w*100,translateYPercent:(f.y-u.y)/u.h*100,scaleX:f.w/u.w,scaleY:f.h/u.h});var f,u;for(const t of e.querySelectorAll('[data-hp-live-layer="camera"]'))s(t,r(c)?null:c);const d=e.querySelector("[data-hp-live-zoom]");if(d){d.hidden=n.zoom<=1;const e=d.querySelector("[data-hp-live-zoom-value]");e&&(e.textContent=`${Math.round(100*n.zoom)}%`)}}const l=e=>{const t=e._viewOr(e._baseVb());return{view:{...t},floor:{...e._floorView(t)},zoom:e._zoom}};const c=new WeakMap,f=(e,t,n,o)=>{if(!n)return;const r=document.createElement("span");if(r.className="m",t){r.append(`${t} `);const e=document.createElement("b");e.textContent=n,o&&(e.style.color=o),r.append(e)}else r.textContent=n;e.append(r)},u=(e,t,n)=>{const o=e.querySelector(t);o&&(o.setAttribute("d",n),o.toggleAttribute("hidden",!n))};function d(t){const n=t,o=n.renderRoot;if(!o)return;((t,n)=>{const o=n.querySelector("[data-hp-live-tip]");if(!o)return;const r=t._tip;if(!r)return o.hidden=!0,void o.replaceChildren();o.style.left=`${r.x+12}px`,o.style.top=`${r.y+12}px`,o.replaceChildren();const a=document.createElement("b");a.textContent=r.title,o.append(a),f(o,"",r.meta),f(o,t._t("tip.temp_avg"),null==r.temp?"":`${r.temp}°`),f(o,t._t("tip.hum_avg"),null==r.hum?"":`${r.hum}%`),f(o,t._t("tip.lqi"),null==r.lqi?"":String(r.lqi),null==r.lqi?void 0:e(r.lqi)),o.hidden=!1})(n,o);const r=n._hoverRoom,a=c.get(t),s=r?.space||"",i=r?.room||null;if(a?.room===i&&a?.space===s)return;c.set(t,{room:i,space:s});const l=r&&n._spaceModel(),d=l?n._roomHoverPaths(l):null;u(o,'[data-hp-live-room-hover="fill"]',d?.fillD||""),u(o,'[data-hp-live-room-hover="halo"]',d?.outlineD||""),u(o,'[data-hp-live-room-hover="outline"]',d?.outlineD||"")}function m(e){c.delete(e)}class p{constructor(e){this.host=e,this.deferredHass=!1}hass(e,t,n,o){const r=function(e,t,n){if(e===t)return"none";if(!e||!t||!n)return"structural";if(e.connection!==t.connection||e.entities!==t.entities||e.devices!==t.devices||e.areas!==t.areas||e.themes!==t.themes||e.user!==t.user||e.config!==t.config||e.floors!==t.floors||e.services!==t.services||e.panels!==t.panels||e.language!==t.language||e.locale?.language!==t.locale?.language||e.locale?.number_format!==t.locale?.number_format||e.locale?.time_format!==t.locale?.time_format||e.locale?.date_format!==t.locale?.date_format)return"structural";const o=new Set(["states","connection","entities","devices","areas","themes","user","config","floors","services","panels","language","locale"]);for(const n of new Set([...Object.keys(e),...Object.keys(t)]))if(!o.has(n)&&e[n]!==t[n])return"structural";for(const o of n.entityIds)if(e.states?.[o]!==t.states?.[o])return"state";return"none"}(e,t,n),a="state"===r&&this.active();a&&(this.deferredHass=!0);const s="none"!==r&&!a;return s||this.host._renderLife.observe(e,t,n,o),s}clear(){this.deferredHass=!1}take(){const e=this.deferredHass;return this.deferredHass=!1,e}viewport(e=!1){!function(e,t=!1){const o=e,r=n(e),a=l(o);if(t)return r.raf&&"function"==typeof cancelAnimationFrame&&cancelAnimationFrame(r.raf),r.raf=0,r.pending=null,r.painted||(r.painted=a),void i(o.renderRoot,r.painted,a);r.pending=a,r.raf||"function"!=typeof requestAnimationFrame||(r.raf=requestAnimationFrame(()=>{r.raf=0;const e=r.pending;r.pending=null;const t=o.renderRoot;e&&t&&(r.painted||(r.painted=e),i(t,r.painted,e))}))}(this.host,e)}hover(){d(this.host)}active(){const e=this.host;return e._pointers.size>0||e._cameraTransition.active||!!e._deviceDrag||!!e._physicalDrag||!!e._physicalRotate||!!e._decorMove||!!e._decorDraft||!!e._dtDrag||!!e._bdDrag||!!e._opDrag||!!e._resize?.dragging}commit(){!function(e){const t=e,o=n(e);o.raf&&"function"==typeof cancelAnimationFrame&&cancelAnimationFrame(o.raf),o.raf=0,o.pending=null,o.painted=l(t);const r=t.renderRoot;if(r){for(const e of r.querySelectorAll('[data-hp-live-layer="camera"]'))s(e,null);i(r,o.painted,o.painted)}}(this.host),m(this.host),d(this.host)}dispose(){!function(e){const n=t.get(e);n?.raf&&"function"==typeof cancelAnimationFrame&&cancelAnimationFrame(n.raf),t.delete(e)}(this.host),m(this.host)}}export{p as LiveRuntime};
+globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="2e6f7d70c797ae4e865b10859c77cc3380a432272a975b8f35b51234ae3cfe62";import{e7 as e}from"./houseplan-card-BMuv6THL.js";const t=new WeakMap,n=e=>{let n=t.get(e);return n||(n={painted:null,pending:null,raf:0},t.set(e,n)),n},o=e=>`${e.x} ${e.y} ${e.w} ${e.h}`;const r=e=>0===e.translateXPercent&&0===e.translateYPercent&&1===e.scaleX&&1===e.scaleY,a=e=>[e.x,e.y,e.w,e.h].every(Number.isFinite)&&e.w>0&&e.h>0,s=(e,t)=>{if(!t)return e.style.removeProperty("transform"),e.style.removeProperty("transform-origin"),void e.style.removeProperty("will-change");e.style.transformOrigin="0 0",e.style.willChange="transform",e.style.transform=`translate(${t.translateXPercent}%,${t.translateYPercent}%) scale(${t.scaleX},${t.scaleY})`};function i(e,t,n){if(!a(t.view)||!a(n.view)||!a(n.floor))return;const i=o(n.view),l=o(n.floor);for(const t of e.querySelectorAll('[data-hp-live-viewbox="camera"]'))t.setAttribute("viewBox",i);for(const t of e.querySelectorAll('[data-hp-live-viewbox="floor"]'))t.setAttribute("viewBox",l);const c=(f=t.view,u=n.view,{translateXPercent:(f.x-u.x)/u.w*100,translateYPercent:(f.y-u.y)/u.h*100,scaleX:f.w/u.w,scaleY:f.h/u.h});var f,u;for(const t of e.querySelectorAll('[data-hp-live-layer="camera"]'))s(t,r(c)?null:c);const d=e.querySelector("[data-hp-live-zoom]");if(d){d.hidden=n.zoom<=1;const e=d.querySelector("[data-hp-live-zoom-value]");e&&(e.textContent=`${Math.round(100*n.zoom)}%`)}}const l=e=>{const t=e._viewOr(e._baseVb());return{view:{...t},floor:{...e._floorView(t)},zoom:e._zoom}};const c=new WeakMap,f=(e,t,n,o)=>{if(!n)return;const r=document.createElement("span");if(r.className="m",t){r.append(`${t} `);const e=document.createElement("b");e.textContent=n,o&&(e.style.color=o),r.append(e)}else r.textContent=n;e.append(r)},u=(e,t,n)=>{const o=e.querySelector(t);o&&(o.setAttribute("d",n),o.toggleAttribute("hidden",!n))};function d(t){const n=t,o=n.renderRoot;if(!o)return;((t,n)=>{const o=n.querySelector("[data-hp-live-tip]");if(!o)return;const r=t._tip;if(!r)return o.hidden=!0,void o.replaceChildren();o.style.left=`${r.x+12}px`,o.style.top=`${r.y+12}px`,o.replaceChildren();const a=document.createElement("b");a.textContent=r.title,o.append(a),f(o,"",r.meta),f(o,t._t("tip.temp_avg"),null==r.temp?"":`${r.temp}°`),f(o,t._t("tip.hum_avg"),null==r.hum?"":`${r.hum}%`),f(o,t._t("tip.lqi"),null==r.lqi?"":String(r.lqi),null==r.lqi?void 0:e(r.lqi)),o.hidden=!1})(n,o);const r=n._hoverRoom,a=c.get(t),s=r?.space||"",i=r?.room||null;if(a?.room===i&&a?.space===s)return;c.set(t,{room:i,space:s});const l=r&&n._spaceModel(),d=l?n._roomHoverPaths(l):null;u(o,'[data-hp-live-room-hover="fill"]',d?.fillD||""),u(o,'[data-hp-live-room-hover="halo"]',d?.outlineD||""),u(o,'[data-hp-live-room-hover="outline"]',d?.outlineD||"")}function m(e){c.delete(e)}class p{constructor(e){this.host=e,this.deferredHass=!1}hass(e,t,n,o){const r=function(e,t,n){if(e===t)return"none";if(!e||!t||!n)return"structural";if(e.connection!==t.connection||e.entities!==t.entities||e.devices!==t.devices||e.areas!==t.areas||e.themes!==t.themes||e.user!==t.user||e.config!==t.config||e.floors!==t.floors||e.services!==t.services||e.panels!==t.panels||e.language!==t.language||e.locale?.language!==t.locale?.language||e.locale?.number_format!==t.locale?.number_format||e.locale?.time_format!==t.locale?.time_format||e.locale?.date_format!==t.locale?.date_format)return"structural";const o=new Set(["states","connection","entities","devices","areas","themes","user","config","floors","services","panels","language","locale"]);for(const n of new Set([...Object.keys(e),...Object.keys(t)]))if(!o.has(n)&&e[n]!==t[n])return"structural";for(const o of n.entityIds)if(e.states?.[o]!==t.states?.[o])return"state";return"none"}(e,t,n),a="state"===r&&this.active();a&&(this.deferredHass=!0);const s="none"!==r&&!a;return s||this.host._renderLife.observe(e,t,n,o),s}clear(){this.deferredHass=!1}take(){const e=this.deferredHass;return this.deferredHass=!1,e}viewport(e=!1){!function(e,t=!1){const o=e,r=n(e),a=l(o);if(t)return r.raf&&"function"==typeof cancelAnimationFrame&&cancelAnimationFrame(r.raf),r.raf=0,r.pending=null,r.painted||(r.painted=a),void i(o.renderRoot,r.painted,a);r.pending=a,r.raf||"function"!=typeof requestAnimationFrame||(r.raf=requestAnimationFrame(()=>{r.raf=0;const e=r.pending;r.pending=null;const t=o.renderRoot;e&&t&&(r.painted||(r.painted=e),i(t,r.painted,e))}))}(this.host,e)}hover(){d(this.host)}active(){const e=this.host;return e._pointers.size>0||e._cameraTransition.active||!!e._deviceDrag||!!e._physicalDrag||!!e._physicalRotate||!!e._decorMove||!!e._decorDraft||!!e._dtDrag||!!e._bdDrag||!!e._opDrag||!!e._resize?.dragging}commit(){!function(e){const t=e,o=n(e);o.raf&&"function"==typeof cancelAnimationFrame&&cancelAnimationFrame(o.raf),o.raf=0,o.pending=null,o.painted=l(t);const r=t.renderRoot;if(r){for(const e of r.querySelectorAll('[data-hp-live-layer="camera"]'))s(e,null);i(r,o.painted,o.painted)}}(this.host),m(this.host),d(this.host)}dispose(){!function(e){const n=t.get(e);n?.raf&&"function"==typeof cancelAnimationFrame&&cancelAnimationFrame(n.raf),t.delete(e)}(this.host),m(this.host)}}export{p as LiveRuntime};
diff --git a/custom_components/houseplan/frontend/houseplan-assets/pdf-export-C4aEaLXl.js b/custom_components/houseplan/frontend/houseplan-assets/pdf-export-BqxOXzDP.js
similarity index 99%
rename from custom_components/houseplan/frontend/houseplan-assets/pdf-export-C4aEaLXl.js
rename to custom_components/houseplan/frontend/houseplan-assets/pdf-export-BqxOXzDP.js
index 0abd0f35..6a87fafb 100644
--- a/custom_components/houseplan/frontend/houseplan-assets/pdf-export-C4aEaLXl.js
+++ b/custom_components/houseplan/frontend/houseplan-assets/pdf-export-BqxOXzDP.js
@@ -1,4 +1,4 @@
-globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="c8d5c166e30a11241ef32c7e1dc70368632e84c448524a8340494350ec4d5fca";import{k as A,m as B,A as E,b as s,aA as w,dV as Q,L as C,a2 as g,N as I,an as Y,J as R,bo as M,bn as F,dW as i,dX as x,dY as b,dZ as L,d_ as D,d$ as G,bq as o,aZ as t,b9 as c,bu as W,bv as m,dI as n,e0 as e,a1 as h,e1 as S,e2 as r}from"./houseplan-card-DXAxXz4t.js";import{GENERATED_FURNITURE_ART as j}from"./furniture-plan-art.generated-Dw0IIirB.js";const H="hp.pdf.options";class v extends B{constructor(){super(...arguments),this.options=null,this.busy=!1}willUpdate(){!this.options&&this.context?.space&&(this.options=function(){const A={dimensions:!0,roomNames:!0,decor:!1,backdrop:!0};try{const B=JSON.parse(localStorage.getItem(H)||"null");return 1===B?.v?{dimensions:!1!==B.dimensions,roomNames:!1!==B.roomNames,decor:!0===B.decor,backdrop:!1!==B.backdrop}:A}catch{return A}}())}setOption(A,B){this.options={...this.options||{dimensions:!0,roomNames:!0,decor:!1,backdrop:!0},[A]:B},this.requestUpdate()}async save(){if(!this.busy&&this.options){this.busy=!0,this.requestUpdate();try{try{localStorage.setItem(H,JSON.stringify({v:1,...this.options}))}catch{}await this.context.save(this.options),this.context.close()}catch(A){const B=A instanceof Error?A.message:"pdf.failed",E="pdf.too_large"===B||"pdf.asset_failed"===B?B:"pdf.failed";this.context.toast(this.context.t(E))}finally{this.busy=!1,this.requestUpdate()}}}render(){if(!this.context?.space)return E;const A=this.options||{dimensions:!0,roomNames:!0,decor:!1,backdrop:!0},B=(B,E)=>s`