- `}export{l as F,c as a,g as b,H as c,D as e,r as f,u as i,a as p,R as r,p as s,_ as t};
+ `}export{l as F,c as a,_ as b,H as c,p as d,C as e,s as f,u as i,a as p,F as r,m as s,g as t};
diff --git a/custom_components/houseplan/frontend/houseplan-assets/de-Cm5MlI_Y.js b/custom_components/houseplan/frontend/houseplan-assets/de-Cm5MlI_Y.js
deleted file mode 100644
index 94307c29..00000000
--- a/custom_components/houseplan/frontend/houseplan-assets/de-Cm5MlI_Y.js
+++ /dev/null
@@ -1 +0,0 @@
-globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="bd7029808eb6094140d9fa8245f50816cb452430a353f4231d16e02c97078a06";var e={"editor.context_actions":"Aktionen: {object}","editor.tool_options":"Werkzeugoptionen: {tool}","editor.palette":"Palette: {tool}","editor.open_group":"Werkzeuggruppe: {group}","editor.group_active":"{group} — aktiv: {item}","editor.disabled_action":"{action} ist nicht verfügbar: {reason}","editor.loading":"Editor wird geladen…","editor.loading_aria":"Der Plan-Editor wird geladen","editor.load_failed":"Der Editor konnte nicht geladen werden.","editor.refresh_advice":"Seite aktualisieren und erneut versuchen.","editor.retry_advice":"Verbindung prüfen und erneut drücken.","color_picker.title":"Farbwähler","color_picker.hue":"Farbton","color_picker.saturation":"Sättigung","color_picker.value":"Helligkeit","color_picker.hex":"Hex-Farbe","color_picker.invalid_hex":"Geben Sie eine 3- oder 6-stellige Hex-Farbe ein","btn.properties":"Eigenschaften","btn.keep_as_walls":"Als Wände behalten","btn.delete_room_keep_walls":"Raum löschen, Wände behalten","btn.delete_room_with_walls":"Raum und Wände löschen","title.markup_select":"Wände, Säulen und gespeicherte Umrisse auswählen und bearbeiten","title.markup_column":"Säule: Klicken Sie auf einen Rasterpunkt, um eine quadratische Säule zu platzieren","markup.partition":"Trennwand","markup.column":"Säule","markup.hint_column":"Klicken Sie auf einen Rasterpunkt, um eine quadratische Säule zu platzieren","history.draft_segment":"Raum-Entwurfsegment hinzufügen","history.draft_merge":"Unvollständige Raumumrisse verbinden","history.draft_segment_delete":"Raum-Entwurfssegment entfernen","history.column_add":"Säule hinzufügen","history.physical_edit":"Physisches Objekt ändern","history.physical_delete":"Physisches Objekt löschen","history.physical_move":"Physisches Objekt verschieben","history.contour_to_partitions":"Umriss in geschlossene Wände umwandeln","history.wall_chain_finish":"Wandkette fertigstellen","history.wall_face_batch":"Räume aus Wänden erstellen","toast.column_duplicate":"Eine Säule mit demselben Zentrum und äußerer Größe existiert bereits","confirm.delete_draft_title":"Unvollständigen Umriss löschen?","confirm.delete_draft_body":"Der gesamte unvollständige Raumumriss wird gelöscht. Beim Abbrechen wird nichts geändert.","confirm.delete_draft_segment_title":"Umrisssegment löschen?","confirm.delete_draft_segment_body":"Dieses Entwurfssegment wird gelöscht. Der verbleibende Umriss kann sich in zwei Teile aufteilen.","physical.partition_properties":"Eigenschaften der Trennwand","physical.column_properties":"Eigenschaften der Säule","physical.draft_properties":"Eigenschaften des Entwurfssegments","physical.shape":"Form","physical.square":"Quadrat","physical.circle":"Kreis","physical.diameter":"Durchmesser","physical.side":"Seite","physical.rotation":"Drehwinkel","physical.length":"Länge","physical.allowed_range":"Erlaubt: {min}–{max} {unit}","physical.delete_segment":"Segment löschen","physical.delete_draft":"Gesamten Umriss löschen","physical.column_size_title":"Außenmaß der per Klick platzierten quadratischen Säule (1–150 cm).","card.title":"Hausplan","count.devices":"{n} Entwicklung","empty.no_spaces":"Noch keine Bereiche.","empty.add_first":"Ersten Bereich hinzufügen und einen Grundriss hochladen.","empty.install":"Installieren Sie die House Plan-Integration und fügen Sie sie unter „Geräte & Dienste“ hinzu.","btn.add_space":"Bereich hinzufügen","btn.cancel":"Abbrechen","btn.save":"Speichern","btn.close":"Schließen","btn.delete":"Löschen","btn.edit":"Bearbeiten","btn.open_in_ha":"In HA öffnen","btn.reset":"Zurücksetzen","btn.attach":"Anhängen…","btn.upload":"Hochladen…","btn.replace":"Ersetzen…","title.zoom_in":"Zoomen","title.zoom_out":"Herauszoomen","title.zoom_fit":"Alles anpassen","title.configure_space":"Bereich konfigurieren","title.add_space":"Bereich hinzufügen","title.markup_add":"Wände: eine durchgehende Kette zeichnen; Shift sperrt auf 45°. Werkzeugwechsel oder Verlassen des Editors beendet die Kette und wandelt sie in unabhängige Wände","title.markup_merge":"Zusammenführen: Klicken Sie auf einen Raum und dann auf den Nachbarraum, mit dem er eine Wand teilt","title.markup_split":"Raum teilen: Klicken Sie auf den Raum und dann auf zwei Punkte an seinen Wänden","title.markup_delroom":"Raum löschen: Klicken Sie in einen Raum und bestätigen Sie","title.need_plan":"Einen Grundriss hochladen","markup.add":"Wände","markup.merge":"Zusammenführen","markup.split":"Teilen","markup.resize":"Größe ändern","title.markup_resize":"Räume vergrößern/verkleinern: Ziehen Sie einen verfügbaren horizontalen oder vertikalen Wandgriff","markup.hint_resize":"Ziehen Sie einen verfügbaren Wandgriff · die Wand stoppt an der ersten unsicheren Position · Esc bricht ab · Strg+Z — rückgängig","resize.disabled.diagonal":"Diese Wand ist geneigt; Größe ändern unterstützt nur horizontale und vertikale Wände","resize.disabled.side-angle":"Eine angrenzende Wand ist geneigt; Größe ändern erfordert, dass beide angrenzenden Wände diese Wand im rechten Winkel treffen","resize.disabled.duplicate-physical-wall":"Eine separate Trennwand, unfertige Kontur oder ein Pfeiler überlappt diese Wand; entfernen oder verschieben Sie sie, bevor Sie die Größe ändern","resize.disabled.partial-shared":"Ein angrenzender Raum nutzt nur einen Teil dieser Wand, daher kann sie nicht sicher als gemeinsame Wand verschoben werden","resize.disabled.unequal-shared":"Der angrenzende Raum nutzt andere Endpunkte oder Wandlängen, daher können die Wände nicht gemeinsam sicher bewegt werden","resize.disabled.multiple-rooms":"Das Verschieben dieser Wand würde mehr als zwei Räume betreffen","resize.disabled.thickness-conflict":"Die Wandstärke kann nicht sicher beibehalten werden","resize.disabled.opening-conflict":"Eine Öffnung an dieser Wand kann nicht sicher verschoben werden","resize.disabled.invalid-geometry":"Diese Wand kann nicht ohne Änderung der Planstruktur geändert werden","resize.limit_stopped":"Wand gestoppt: der nächste Schritt würde ein Anschlusslimit verletzen","resize.commit_failed":"Größenänderung wurde abgebrochen, da der endgültige Plan die Geometrieprüfung nicht bestanden hat","resize.preview_failed":"Größenänderung am letzten sicheren Punkt gestoppt, da die Plan-Geometrie nicht beibehalten werden konnte","markup.opening":"Öffnung","markup.delete_room":"Raum löschen","history.undo":"Rückgängig","history.redo":"Wiederholen","history.undo_named":"Rückgängig: {name} (Strg+Z)","history.redo_named":"Wiederholen: {name} (Strg+Shift+Z / Strg+Y)","history.undo_empty":"Nichts zu widerrufen","history.redo_empty":"Nichts zu wiederholen","history.undone":"Rückgängig gemacht: {name}","history.redone":"Wiederholt: {name}","history.add_room":"Raum erstellen","history.split_room":"Raum teilen","history.merge_rooms":"Räume zusammenführen","history.resize_room":"Raumgröße ändern","history.wall_thickness":"Wandstärke ändern","history.add_opening":"Tür- oder Fensteröffnung hinzufügen","history.edit_opening":"Öffnung bearbeiten","history.move_opening":"Öffnung verschieben","history.delete_opening":"Öffnung löschen","history.delete_room_keep_walls":"Raum löschen, Wände behalten","history.delete_room_with_walls":"Raum und Wände löschen","history.decor_add":"Dekorobjekt hinzufügen","history.decor_edit":"Dekorobjekt bearbeiten","history.decor_move":"Dekorobjekt verschieben","history.decor_transform":"Dekorobjekt transformieren","history.decor_delete":"Dekorobjekt löschen","history.backdrop_transform":"Plan-Hintergrund transformieren","history.device_move":"{name} verschieben","history.device_stale":"Der Positionsverlauf ist nicht mehr anwendbar und wurde gelöscht","opening.new":"Neue Öffnung","opening.edit":"Öffnung","opening.door":"Tür","opening.window":"Fenster","opening.gate":"Tor","opening.passage":"Offener Durchgang","opening.passage_binding_warning":"Das Speichern entfernt den Öffnungs-/Schließsensor und das Schloss.","opening.invalid_passage_fields":"Der offene Durchgang auf dem Plan „{room}“ hat nicht unterstützte Einstellungen: {fields}.","opening.type_label":"Typ","opening.length_label":"Länge, cm","opening.contact_label":"Öffnungs-/Schließsensor","opening.lock_label":"Schloss","opening.none":"— keine —","opening.search_ph":"Suche: Name oder Entitäts-ID…","opening.invert":"Geöffnet/geschlossen invertieren","opening.flip_h":"Scharnier an der anderen Zarge","opening.flip_v":"Öffnet zur anderen Seite","opening.open":"Offen","opening.closed":"Geschlossen","opening.locked":"Verriegelt","opening.unlocked":"Entriegelt","opening.state_unknown":"nicht verfügbar","opening.no_entities":"Keine Sensoren gebunden — ein statisches Symbol auf dem Plan.","toast.opening_no_wall":"Neben eine Raumwand oder eine unabhängige Wand klicken","opening.host_partition":"Unabhängige Wand","opening.partition_orphan":"Die unabhängige Wand für diese Öffnung existiert nicht mehr","opening.partition_jamb_margin":"Mindestens {distance} zwischen der Öffnung und dem Wandende lassen","opening.rebind_partition":"An eine andere unabhängige Wand anfügen","confirm.delete_partition_openings_title":"Wand und Öffnungen löschen?","confirm.delete_partition_openings_body":"Diese Wand enthält {count} Öffnung(en). Sie werden zusammen gelöscht.","confirm.delete_partition_openings_item":"• {type}, {length}","markup.hint_points":"Punkte: {n} · Shift — 45° Schritte · Esc — Kette beenden · Ctrl+Z — Punkt rückgängig machen · Schließen eines Bereichs erstellt einen Raum","markup.hint_start":"Klicken Sie auf einen Rasterpunkt, um eine Wandkette zu starten","tip.lqi":"durchschnittliches Zigbee-Signal:","tip.area":"Bereich: {value}","info.device_header":"Gerät im Plan","info.model":"Modell","info.state":"Status","info.link":"Verbindung","info.manuals":"Handbücher","info.none":"Keine zusätzlichen Informationen","marker.new_device":"Neues Gerät","marker.name_label":"Name (im Plan angezeigt)","marker.name_ph":"Name","marker.binding_label":"An ein HA-Gerät binden","marker.binding_disabled":"in Home Assistant deaktiviert","marker.virtual_option":"Virtuelles Gerät (keine Bindung)","marker.search_ph":"Gerät/Gruppe suchen…","marker.nothing_found":"Nichts gefunden","marker.room_label":"Raum","marker.room_override":" (Platzierung überschreiben)","marker.room_choose":"— Raum auswählen —","marker.room_auto":"— nach Gerätebereich (auto) —","marker.icon_label":"Symbol","marker.icon_ph":"mdi:… (leer = automatisch)","marker.display_label":"Anzeige","display.badge":"Symbol + Zustand","display.icon_ripple":"Symbol + Zustand und Aktivität","display.static_icon":"Immer statisches Symbol","marker.display_hint_badge":"Das Symbol und die dynamische Platte zeigen den Gerätezustand ohne den üblichen Aktivitätspuls. Rote Alarme bleiben sichtbar.","marker.display_hint_icon_ripple":"Das Symbol, die dynamische Platte und der Puls zeigen einen kurzen Puls für Ereignisse und einen kontinuierlichen Puls für Arbeit, Bewegung oder Anwesenheit. Rote Alarme haben eine separate Priorität.","marker.display_hint_value":"Ein ausgewählter oder automatisch ermittelter Home Assistant-Wert ersetzt das Symbol, während die Platte weiterhin den Zustand anzeigt. Rote Alarme bleiben sichtbar.","marker.display_hint_static_icon":"Die themenabhängige Hülle und das Symbol bleiben immer gleich. Zustand, Aktivität, Nichtverfügbarkeit und Alarme verändern nicht das Erscheinungsbild.","marker.static_alarm_warning":"Dieses Gerät kann Alarme melden. Die statische Anzeige verbirgt die visuelle Alarmanzeige des Markers.","marker.preview.title":"Anzeigevorschau","marker.preview.actual":"Jetzt","marker.preview.example":"Beispiel","marker.preview.integration":"Bereitgestellt von","marker.preview.source":"Anzeigquelle","marker.preview.current_state":"Aktueller Zustand","marker.preview.result":"Auf dem Plan","marker.preview.details":"Quelldetails","marker.preview.select_source":"Ein Home-Assistant-Gerät oder eine Entität auswählen, um die tatsächliche Anzeige zu sehen.","marker.preview.unknown_provider":"Unbekannte Integration","marker.preview.virtual_provider":"House Plan · virtuelles Gerät","marker.preview.no_source":"Keine aktive Quelle","marker.preview.no_state":"Kein aktueller Zustand","marker.preview.mixed_states":"Mehrere verschiedene Zustände","marker.preview.multiple_sources":"{n}-Quellen","marker.preview.more_sources":"+{n} mehr","marker.preview.scaled":"Die Vorschau wird auf {n}% skaliert, um zu passen. Die gespeicherte Größe bleibt unverändert.","marker.preview.demo_short":"Kurze Aktivität anzeigen","marker.preview.demo_continuous":"Kontinuierliche Aktivität anzeigen","marker.preview.stop_continuous":"Kontinuierliche Aktivität stoppen","marker.preview.demo_short_notice":"Kurzes Aktivitätsbeispiel; der tatsächliche Gerätezustand bleibt unverändert.","marker.preview.demo_continuous_notice":"Kontinuierliches Aktivitätsbeispiel; der tatsächliche Gerätezustand bleibt unverändert.","marker.preview.demo_already_visible":"Der aktuelle Zustand zeigt bereits eine echte Aktivitäts- oder Alarmeffekt.","marker.preview.reduced_motion":"Systemweit reduzierte Bewegungen sind aktiviert, daher wird gewöhnliche Aktivität als Punkt angezeigt.","marker.preview.reason.neutral":"Neutrale dunkle Platte","marker.preview.reason.working":"Gelbe Platte: Das Gerät arbeitet jetzt","marker.preview.reason.working_activity":"Gelbe Platte und Aktivitätseffekt: das Gerät funktioniert jetzt","marker.preview.reason.open":"Orange Platte: physisch geöffnet oder entriegelt","marker.preview.reason.cover_icon_state":"Neutrale Platte; die Abdeckungseinheit steuert den angezeigten Zustand und das Symbol","marker.preview.reason.presence":"Aktivitätseffekt, während Präsenz erkannt wird","marker.preview.reason.event":"Kurzer Aktivitätseffekt nach einem erkannten Ereignis","marker.preview.reason.transition":"Aktivitätseffekt, während das Gerät sich bewegt oder den Zustand ändert","marker.preview.reason.media_neutral":"Mediengeräte bleiben im verfügbaren Zustand auf einer neutralen dunklen Platte","marker.preview.reason.unavailable":"Gedämpfte neutrale Platte: nicht verfügbar oder ausgeschaltet","marker.preview.reason.alarm":"Rote Alarmplatte; Alarmanzeige wird immer angezeigt","marker.preview.reason.live_states_disabled":"Live-Zustandsstil ist für diese Karte deaktiviert","marker.preview.reason.value_no_state":"Kein nutzbarer Zustandswert; stattdessen wird das Symbol angezeigt","marker.preview.reason.value_ambiguous_sources":"Mehrere mögliche Wertequellen; stattdessen wird das Symbol angezeigt","marker.preview.reason.value_non_scalar":"Die Quelle lieferte keinen einfachen Wert; stattdessen wird das Symbol angezeigt","marker.preview.reason.value_virtual":"Ein virtuelles Gerät hat keinen Home Assistant-Wert; stattdessen wird das Symbol angezeigt","marker.preview.reason.vacuum_live_plan_only":"Echtzeitposition und -spur des Staubsaugers sind nur im vollständigen Plan verfügbar","marker.preview.reason.hidden_design_preview":"Das Gerät ist im Plan ausgeblendet; diese Designvorschau bleibt sichtbar","marker.preview.reason.composite_power_source":"Der Status stammt vom Power-Entity des Geräts; Hilfsschalter werden ignoriert","marker.preview.reason.activity_display_disabled":"Der gewählte Anzeigemodus zeigt gewöhnliche Aktivitätseffekte nicht an","marker.preview.reason.ha_disabled":"Die Home Assistant-Verbindung ist deaktiviert und wird im Plan ausgeblendet","marker.preview.reason.orphaned":"Die gespeicherte Home Assistant-Verbindung konnte nicht mehr gefunden werden","marker.preview.reason.static_icon":"Statischer Modus: Der Gerätestatus ändert das Symbol nicht","marker.activity_color":"Aktivitätspulsfarbe","marker.ripple_size":"Aktivitätspulsgröße","marker.activity_alarm_note":"Farbe und Größe betreffen nur gewöhnliche Aktivität und ändern keine roten Alarme.","marker.pulse_a11y_alarm":"Alarm","marker.pulse_a11y_event":"Kürzliches Ereignis","marker.pulse_a11y_presence":"Anwesenheit erkannt","marker.pulse_a11y_transition":"Statusänderung","marker.pulse_a11y_running":"Arbeitet","marker.state_a11y_neutral":"Standardzustand","marker.state_a11y_working":"Funktionierend","marker.state_a11y_open":"Offen","marker.state_a11y_locked":"Verschlossen","marker.state_a11y_unlocked":"Entriegelt","marker.state_a11y_alarm":"Alarm","marker.state_a11y_unavailable":"Nicht verfügbar","marker.lqi_a11y_low":"LQI {value}, schwaches Signal","marker.lqi_a11y_mid":"LQI {value}, mittleres Signal","marker.lqi_a11y_high":"LQI {value}, starkes Signal","marker.size_label":"Symbolgröße / Drehung","marker.angle_label":"Drehen","marker.model_label":"Modell","marker.model_ph":"z.B. Aqara T&H","marker.link_label":"Link","marker.desc_label":"Beschreibung","marker.desc_ph":"Notizen, Spezifikationen…","marker.manuals_label":"Handbücher (PDF usw.)","marker.sub_device":"Gerät","marker.sub_z2m_group":"· Z2M Gruppe","marker.sub_group":"Gruppe","marker.sub_helper":"Helfer","space.new":"Neuer Bereich","space.header":"Bereich","space.title_label":"Titel","space.title_ph":"z.B. Garage","space.plan_label":"Grundriss (Hintergrund)","space.no_plan":"Kein Planbild","space.plan_alt":"Grundriss","room.new":"Neuer Raum","room.name_label":"Anzeigename","room.name_ph":"z.B. Terrasse","room.area_label":"Home Assistant Bereich (nicht zugewiesen)","room.no_area_option":"— kein Bereich —","room.default_name":"Raum","device.unnamed":"unbenannt","device.light_group":"Lichtgruppe","device.fallback":"Gerät","device.virtual":"Virtuelles Gerät","confirm.delete_room_title":'Raum "{name}" löschen?',"confirm.delete_room_body":"Festlegen, ob die ausschließlich zu diesem Raum gehörenden physischen Wände erhalten bleiben. Mit einem anderen Raum geteilte Wände bleiben immer erhalten.","confirm.remove_marker_title":"Gerät aus dem Plan löschen?","confirm.remove_marker_body":"Das Gerät verschwindet vollständig und trägt nicht mehr zu den Plandaten bei. Es kann später erneut hinzugefügt werden.","confirm.erase_decor":"Das Objekt „{kind}“ löschen? Diese Aktion kann im Editor rückgängig gemacht werden.","confirm.delete_space_title":"Bereich löschen?","confirm.delete_space_body":"Der Bereich, alle seine Räume und die gesamte Planmarkierung werden gelöscht.","space.delete_blocked":"Dieser Bereich wird noch von {n} Gerät(en) verwendet. Die Geräte zuerst in einen anderen Bereich verschieben oder löschen.","toast.pos_save_failed":"Position nicht gespeichert: {err}","toast.no_entity":"Das Gerät hat keine geeignete Entität","toast.ha_disabled_action":"Ein deaktiviertes Home Assistant-Objekt kann im Plan nicht verwendet werden.","toast.ha_disabled_show_device":"Ein in Home Assistant deaktiviertes Gerät kann im Plan nicht angezeigt werden. Aktivieren Sie es zuerst in Home Assistant.","toast.ha_disabled_show_entity":"Eine in Home Assistant deaktivierte Entität kann im Plan nicht angezeigt werden. Aktivieren Sie sie zuerst in Home Assistant.","toast.ha_disabled_add":"Ein deaktiviertes Home Assistant-Objekt kann nicht dem Plan hinzugefügt werden. Aktivieren Sie es zuerst in Home Assistant.","toast.ha_binding_unverified":"Der Status des Objekts konnte über das Home Assistant-Register nicht überprüft werden. Anzeige und Aktionen sind vorübergehend nicht verfügbar.","toast.markup_needs_server":"Markup ist verfügbar, nachdem die Konfiguration auf den Server verschoben wurde.","toast.space_order_changed":"Reihenfolge geändert. Wenn eine Karte ihr Stockwerk nach Nummer festlegt, überprüfen Sie diese Paneele.","toast.conflict":"Die Konfiguration wurde in einem anderen Fenster geändert — Daten aktualisiert, wiederholen Sie Ihre letzte Aktion.","toast.cfg_save_failed":"Speichern der Konfiguration fehlgeschlagen: {err}","toast.room_overlap":"Die Umrisse überlappen den Raum „{name}“ — Räume dürfen sich nicht überlappen","toast.contour_cannot_close":"Die Kontur kann nicht geschlossen werden, da sie entartet ist oder sich selbst schneidet","toast.merge_not_adjacent":"Es können nur Räume zusammengeführt werden, die eine Wand teilen","toast.rooms_merged":"Räume zu „{name}“ zusammengeführt","toast.split_pick_wall":"Beginnen Sie den Schnitt an der Wand des Raumes","toast.split_bad_cut":"Der Schnitt muss wand-zu-wand innerhalb des Raumes verlaufen, ohne Wände oder sich selbst zu kreuzen","merge.header":"Räume zusammenführen","merge.hint":"Der zusammengeführte Raum behält einen Namen und eine Fläche. Die andere Fläche wird freigegeben — ihre Geräte verlassen den Plan, bis ein anderer Raum sie beansprucht.","merge.keep":"Behalten","merge.no_area":"keine Fläche","toast.room_saved":"Raum gespeichert ({n}). Hinzugefügte Geräte: {added}. Zeichnen Sie die nächste Kontur oder verlassen Sie die Markierung.","toast.room_saved_no_area":"Raum gespeichert ({n}, keine Fläche). Zeichnen Sie die nächste Kontur oder verlassen Sie die Markierung.","toast.marker_needs_server":"Die Gerätebearbeitung ist verfügbar, nachdem die Konfiguration auf den Server verschoben wurde","toast.virtual_name_required":"Einen Namen für das virtuelle Gerät eingeben","toast.marker_saved":"Gerät gespeichert","toast.marker_removed":"Gerät aus dem Plan gelöscht","toast.integration_missing":"Die House Plan-Integration ist nicht installiert — Verwaltung nicht verfügbar","toast.plan_formats":"Unterstützte Formate: SVG, PNG, JPG, WebP","toast.plan_required":"Grundriss hochladen — erforderlich","toast.space_added_onboard":"Bereich hinzugefügt. Räume einzeichnen: Rasterpunkte anklicken und die Kontur schließen.","toast.space_added":"Bereich hinzugefügt","toast.space_saved":"Bereich gespeichert","toast.space_deleted":"Bereich gelöscht","toast.delete_failed":"Löschen fehlgeschlagen: {err}","toast.error":"Fehler: {err}","toast.toggle_target_unavailable":"Ziel „{name}“ ist nicht verfügbar — keine Aktion durchgeführt","toast.toggle_targets_unavailable":"Ziele nicht verfügbar: {names}. Keine Aktion durchgeführt","toast.file_failed":'Datei "{name}" wurde nicht hochgeladen: {err}',"toast.files_attached":"Dateien angehängt: {n}","err.unknown":"unbekannter Fehler","err.code":"Code {code}","err.too_large":"Datei größer als {mb} MB","err.bad_ext":"nicht unterstützter Typ (PDF/Bild erwartet)","err.unauthorized":"Administratorrechte erforderlich","editor.title":"Titel","editor.default_floor":"Anfangsbereich","editor.default_floor_missing":"Anfangsbereich „{id}“ existiert nicht mehr. Wählen Sie einen anderen Bereich.","editor.floor":"Fester Bereich","editor.floor_none":"— nicht fest —","editor.floor_index":"YAML-Index {index} (beibehalten)","fixed_floor.loading":"Lade den festen Bereich…","fixed_floor.invalid_title":"Der feste Bereich ist nicht verfügbar","fixed_floor.invalid_body":"Überprüfen Sie die Etage in der Kartenkonfiguration. Der konfigurierte Wert ist: {value}","editor.icon_size":"Symbolgröße, % der Planbreite","editor.show_temperature":"Temperatur anzeigen","editor.live_states":"Live-Zustände (ein/aus, offen…)","editor.light_pools":"Lichtkegel und Wandschatten","editor.show_signal":"Zigbee-Signal anzeigen (LQI)","editor.language":"Schnittstellensprache","editor.lang_auto":"Automatisch (HA-Profil)","title.icon_rules":"Symbolregeln: welche MDI-Symbole Geräte nach Namen erhalten","rules.title":"Symbolregeln","rules.hint":'Regeln werden von oben anhand von "Gerätename + Modell" (Großschreibungs-unempfindliches Regex) überprüft; das erste Match gewinnt. Wenn nichts übereinstimmt, entscheidet die Entität-Geräteklasse, dann das generische Chip-Symbol.',"rules.pattern_ph":"regex, z. B. Stecker|Steckdose","rules.icon_ph":"mdi:power-socket-de","rules.add":"Regel hinzufügen","rules.reset":"Zurücksetzen auf Standardeinstellungen","rules.test_ph":"Versuch mal einen Gerätenamen...","rules.invalid":"ungültiges regex","rules.saved":"Icon-Regeln gespeichert","btn.up":"Nach oben","btn.down":"Nach unten","tap.info":"Gerätekarte","tap.more_info":"HA Mehr-Info-Dialog","tap.toggle":"Zustand umschalten","marker.tap_label":"Tap-Aktion für dieses Gerät","tap.toggle_note":"Der aufgelöste Zustand ist unten dargestellt. Sichere Geräte werden niemals aus dem Plan umgeschaltet.","import.title":"Bereiche aus HA-Etagen erstellen","import.hint":"Home Assistant kennt diese Etagen bereits. Die Etagen auswählen, die zu Planbereichen werden sollen; anschließend für jeden Bereich einen Grundriss hochladen. Die Räume werden danach von Hand eingezeichnet.","import.start":"{n} Bereich(e) erstellen","import.manual":"Von Grund auf neu starten","import.progress":"Etage {i} von {n}","import.done":"Bereiche erstellt. Räume einzeichnen: Rasterpunkte anklicken und die Kontur schließen.","btn.skip":"Überspringen","space.scale_label":"Maßstab (Rasterzellen-Größe)","space.cell_cm.help":"Verknüpft das Raster mit realen Abmessungen: Davon hängen Längen und Flächen, Wandstärken, Öffnungsgrößen und der Leuchtradius ab. Eine spätere Änderung verändert die berechneten Abmessungen des gesamten Bereichs, verschiebt aber keine Punkte im Plan.","space.cell_cm.help.aria":"Hilfe: Maßstab des Bereichs","space.scale_unit":"cm pro Zelle","space.scale_unit_imperial":"Zoll pro Zelle","space.display_section":"Anzeige","space.show_borders":"Raumgrenzen immer anzeigen","space.zero_wall_style":"Wände ohne Dicke","space.zero_wall_style.help":"Gestrichelte Wände ohne Dicke lassen Glow und Sonnenstrahlen durch, durchgezogene blockieren sie als Barriere ohne Fläche. Die Auswahl gilt für alle solchen Wände im Bereich, auch wenn ihre Linie in der Ansicht ausgeblendet ist.","space.zero_wall_style.help.aria":"Hilfe: Darstellung der Wände ohne Dicke","space.zero_wall_dashed":"Gestrichelt","space.zero_wall_solid":"Durchgezogen","space.show_names":"Raumnamen anzeigen (zum Verschieben ziehen)","space.room_color":"Farbe der Begrenzung & des Namens","space.opacity":"Deckkraft","space.fill_label":"Raumausfüllung","space.fill_mode.help":"„Eigene Farbe“ gestaltet den Bereich; „Licht“, „Temperatur“ und „LQI“ verwenden aktuelle Daten aus Home Assistant. Glow wird separat aktiviert.","space.fill_mode.help.aria":"Hilfe: Modus der Raumausfüllung","fill.none":"Keine","fill.lqi":"Zigbee-Signal","fill.light":"Lichter","fill.custom":"Benutzerdefinierte Farbe","space.custom_fill":"Füllfarbe","space.source_file":"Ich habe einen Grundriss als Bild","space.source_draw":"Kein Bild – ich werde die Räume von Hand umreißen","fill.temp":"Temperatur","tip.temp_avg":"Durchschnittstemperatur:","tip.hum_avg":"Durchschnittliche Luftfeuchtigkeit:","space_card.button":"Grundriss öffnen","space_card.not_found":"Bereich „{id}“ nicht gefunden","space_card.loading":"Laden…","continuity.restore_plan":"Grundriss wiederherstellen…","continuity.restore_connection":"Geräteverbindung wiederherstellen…","continuity.retry":"Erneut versuchen","editor.space":"Bereich","editor.framing":"Bildausschnitt","editor.fit_content":"Alle sichtbaren Inhalte","editor.fit_house":"Eng an der Hausgeometrie","editor.show_button":"Schaltfläche anzeigen","editor.button_label":"Beschriftung der Schaltfläche","editor.button_target":"Ziel-Dashboard-Pfad","marker.sub_entity":"Entität","title.general_settings":"Allgemeine Einstellungen","gs.title":"Allgemeine Einstellungen","gs.light_group":"Füllung: Licht","gs.light_on":"Lichter an","gs.light_off":"Alle Lichter aus","gs.temp_group":"Füllung: Temperatur","gs.temp_cold":"Kalt","gs.temp_ok":"Angenehm","gs.temp_hot":"Heiß","gs.lqi_group":"Füllung: Zigbee-Signal","gs.lqi_low":"Schwaches Signal","gs.lqi_high":"Starkes Signal","gs.reset":"Auf Standard zurücksetzen","gs.saved":"Allgemeine Einstellungen gespeichert","space.show_lqi":"Zigbee-Signal (LQI) neben Geräten anzeigen","space.hide_decor":"Dekorationsschicht ausblenden","space.hide_decor_tip":"Linien, Formen, Beschriftungen und Möbel bleiben an ihrem Platz — im Hintergrundeditor sichtbar, aber nicht auf dem Plan.","space.hide_openings":"Öffnungen ausblenden","space.hide_openings_tip":"Tür-, Fenster- und Tor-Symbole werden nicht gezeichnet, aber die Öffnungen funktionieren weiterhin: Licht fällt hindurch, die Sonne kommt durch ein Fenster herein, Kontaktsensoren öffnen sie weiterhin. Der Planeditor zeigt sie immer an.","gs.light_none":"Keine Lichtquellen","mode.plan":"Planeditor","mode.devices":"Geräteeditor","display.value":"Wert + Zustand","marker.subarea":"kein Bereich, manuell","device.new":"Neues Gerät — Editor öffnen, um zu schließen","opening.unlock_action":"Entsperren","opening.lock_action":"Sperren","opening.lock_pending":"Wird ausgeführt…","title.close_editor":"Editor schließen (zur Ansicht zurück)","title.add_device":"Gerät zum Plan hinzufügen","devbar.add":"Hinzufügen","devbar.rules":"Symbolregeln","device_inbox.button":"Geräte","device_inbox.title":"Geräte auf dem Plan","device_inbox.search":"Geräte, Entitäten und Integrationen suchen…","device_inbox.add_virtual":"Virtuelles Gerät hinzufügen","device_inbox.tab_on_plan":"Auf Plan","device_inbox.tab_available":"Verfügbar","device_inbox.tab_hidden":"Versteckt","device_inbox.tab_readd":"Wieder verfügbar","device_inbox.only_new":"Nur neu","device_inbox.show_entities":"Entitäten anzeigen","device_inbox.show_hidden":"Versteckte auf Plan anzeigen","device_inbox.show_hidden.help":"Zeigt ausgeblendete und deaktivierte Marker vorübergehend als Bearbeitungs-Geister auf dem Plan. Die gespeicherte Sichtbarkeit der Geräte bleibt unverändert.","device_inbox.show_hidden.help.aria":"Hilfe: ausgeblendete Geräte auf dem Plan anzeigen","device_inbox.new":"Neu","device_inbox.find":"Auf dem Plan finden","device_inbox.edit":"Bearbeiten","device_inbox.hide":"Ausblenden","device_inbox.show":"Anzeigen","device_inbox.add":"Hinzufügen","device_inbox.readd":"Wieder hinzufügen","device_inbox.hide_available":"Aus der Liste ausblenden","device_inbox.show_more":"Mehr anzeigen","device_inbox.more_actions":"Weitere Aktionen","device_inbox.find_hidden_hint":"Zuerst „Versteckte auf Plan anzeigen“ aktivieren","device_inbox.show_disabled":"Diese Bindung in Home Assistant aktivieren, bevor sie angezeigt wird","device_inbox.empty_on_plan":"Es befinden sich noch keine passenden Geräte auf dem Plan.","device_inbox.empty_available":"Es sind keine Geräte zum Hinzufügen verfügbar.","device_inbox.empty_hidden":"Es gibt keine versteckten Geräte.","device_inbox.empty_readd":"Es sind keine entfernten Geräte verfügbar, um sie erneut hinzuzufügen.","device_inbox.reason_visible_auto":"Automatisch erkannt","device_inbox.reason_visible_explicit":"Explizit hinzugefügt","device_inbox.reason_manual_hidden":"Vom Benutzer versteckt","device_inbox.reason_automatic_hidden":"Automatisch versteckt","device_inbox.reason_service_entry":"Nur Service-Registry-Eintrag","device_inbox.reason_excluded_integration":"Integration „{integration}“ durch Erkennungsfilter ausgeschlossen","device_inbox.reason_excluded_domain":"Nicht-räumlicher Entitätstyp","device_inbox.reason_grouped_light":"Dargestellt durch eine Raumlichtgruppe","device_inbox.reason_represented_by_parent":"Dargestellt durch sein übergeordnetes Gerät","device_inbox.reason_removed":"Zuvor aus dem Plan entfernt","device_inbox.reason_available":"Zum Hinzufügen zum Plan verfügbar","device_inbox.reason_no_bound_room":"HA-Bereich ist nicht mit einem Planraum verknüpft","device_inbox.status_ha_disabled":"In Home Assistant deaktiviert","device_inbox.status_orphaned":"Bindung ist in Home Assistant nicht mehr vorhanden","device_inbox.status_unverified":"Home Assistant-Register vorübergehend nicht verfügbar","device_inbox.saved":"Geräteliste aktualisiert","device_inbox.filters_excluded":"Ausgeschlossene Integrationen","device_inbox.filters_group_lights":"Raumleuchten zu einem Marker gruppieren","device_inbox.filters_preview_appear":"erscheint: {count}","device_inbox.filters_preview_hide":"verschwindet: {count}","device_inbox.filters_preview_lights":"betroffene Leuchten: {count}","device_inbox.filters_reset":"Empfohlene wiederherstellen","device_inbox.filters_save":"Filter speichern","device_inbox.filters_search_ph":"Integration hinzufügen…","device_inbox.filters_title":"Erkennungsfilter","space.roomcard_section":"Raumkarte zeigt:","space.label_temp":"Temperatur","space.label_hum":"Luftfeuchtigkeit","space.label_lqi":"Durchschnittliches Zigbee-Signal","space.label_light":"Lichter ein/aus","roomcard.light_on":"Ein","roomcard.light_off":"Aus","roomcard.light_partial":"{on} von {total}","toast.split_pick_inside":"Zwischenliegende Schnittpunkte müssen innerhalb des Raumes liegen","mode.decor":"Hintergrundeditor","decor.select":"Auswählen","decor.line":"Linie","decor.rect":"Rechteck","decor.ellipse":"Oval","decor.text":"Text","decor.erase":"Löschen","decor.erase_confirm_title":"Objekt löschen?","decor.color":"Farbe","decor.width":"Linienbreite","decor.line_style":"Linienstil","decor.line_style_solid":"Durchgehend","decor.line_style_dashed":"Gepunktet","decor.fill":"Füllen","decor.fill_color":"Füllfarbe","decor.length":"Länge","decor.size":"Größe","decor.flip_h":"Horizontal spiegeln","decor.flip_v":"Vertikal spiegeln","decor.angle":"Rotationswinkel, °","decor.text_size":"Textgröße","decor.backdrop_properties":"Eigenschaften des Planhintergrunds","decor.text_title":"Textbeschriftung","decor.object_title":"{kind} bearbeiten","decor.text_label":"Text","decor.live_group":"HA-Variable einfügen","decor.live_entity":"Entität","decor.live_entity_ph":"Wählen Sie eine Entität","decor.live_attr":"Wert","decor.live_attr_ph":"Wählen Sie Status oder Attribut","decor.live_state":"Status","decor.backdrop":"Hintergrundbild","decor.backdrop_hint":"Ziehen zum Verschieben; eine Ecke ziehen zum Größenändern; den oberen Griff zum Drehen verwenden. Shift ändert das Verhältnis oder befreit den Winkel.","decor.backdrop_reset":"Bild zurücksetzen","decor.backdrop_reset_done":"Das Bild ist wieder an seinem ursprünglichen Platz und in seiner ursprünglichen Größe","marker.icon_auto":"Auto: {icon} (nach Symbolregeln; wählen Sie eines zur Überschreibung)","marker.icon_pin_auto":"Anheften","mode.plan_tip":"Planungseditor — die Geometrie des Hauses: Räume zeichnen und teilen/zusammenführen, sie mit HA-Bereichen verbinden, Türen, Fenster und Tore platzieren, Raumkarten verschieben, Maßstab festlegen","mode.devices_tip":"Geräteeditor — alles über Symbole: ziehen zum Positionieren, klicken zum Bearbeiten von Bindung/Symbol/Anzeige, virtuelle Geräte hinzufügen, Symbolregeln","mode.decor_tip":"Hintergrundeditor — rein visuelle Dekoration unter dem Plan: Linien, Rechtecke, Ellipsen und Textbeschriftungen, die niemals auf Klicks reagieren","space.glow_enabled":"Lichtquellen-Glühen","gs.glow_group":"Glow von Lichtquellen","gs.glow_base":"Grunddunkelheit des Hauses","gs.glow_light":"Standardlichtfarbe / Intensität","gs.wall_group":"Wände","gs.wall_fill":"Wandfüllung","gs.glow_radius":"Glow-Radius","gs.glow_radius.help":"Legt den allgemeinen Radius des Lichtscheins in Metern oder Fuß fest; ein gerätespezifischer Radius überschreibt diesen Wert.","gs.glow_radius.help.aria":"Hilfe: allgemeiner Glow-Radius","gs.unit_m":"m","gs.unit_ft":"ft","marker.controls_label":"Steuert andere Lichtquellen","marker.controls.help":"Mit der Aktion „Zustand umschalten“ werden die aufgeführten Quellen zusammen mit diesem Marker umgeschaltet. Ihr Glow bleibt an ihren eigenen Markern, und die Verknüpfung allein macht den steuernden Marker nicht zur Lichtquelle.","marker.controls.help.aria":"Hilfe: andere Lichtquellen steuern","marker.controls_filter":"Suchlichter und Schalter…","info.controls":"Steuerungen","marker.glow_radius_label":"Leuchtradius","marker.glow_radius.help":"Legt den Leuchtradius in Metern oder Fuß fest; ein leerer Wert verwendet den Radius aus den allgemeinen Einstellungen.","marker.glow_radius.help.aria":"Hilfe: Leuchtradius","markup.wallthick":"Dicke","markup.select":"Auswählen","title.markup_wallthick":"Dicke — klicken Sie auf eine Wand, um ihre Dicke von 0 bis 100 cm festzulegen.","markup.hint_wallthick":"klicken Sie auf eine Wand · Esc schließt ohne Anwendung","wallthick.field":"Dicke","wallthick.unit_cm":"cm","wallthick.unit_in":"in","wallthick.apply_room":"Auf alle Wände dieses Raums anwenden","markup.draw_wall_title":"Dicke jedes neuen Wandsegments (0–100 cm). Gemeinsame Wände behalten den bestehenden Wert.","room.queue_progress":"Raum {current} von {total}","toast.wall_rooms_saved":"Erstellte Räume: {n}","toast.wall_chain_saved":"Wandkette gespeichert","toast.wallthick_pick":"Eine Wand anklicken","toast.wallthick_set":"Wandstärke eingestellt","toast.wallthick_cleared":"Wandstärke entfernt","toast.physical_range":"Einen Wert von {min} bis {max} {unit} eingeben","toast.zero_wall_opening_conflict":"Entfernen Sie zuerst die Öffnung an diesem Wandsegment.","toast.zero_wall_ambiguous":"Das Wandsegment ist mehrdeutig. Vereinfachen oder passen Sie den Anschluss an.","toast.zero_wall_migration_blocked":"Der Bereich wurde nicht konvertiert: {reason}. Es wurden keine Daten geändert.","toast.physical_angle":"Einen Drehwinkel von 0° bis unter 90° eingeben","toast.physical_limit":"Der Bereich hat das Limit für diesen Geometrietyp erreicht","toast.geometry_unsafe":"Änderung abgebrochen: Wandgeometrie konnte nicht sicher erstellt werden.","junction.limit_angle":"Der Winkel zwischen den Wänden ist zu spitz: {actual}°, mindestens {limit}°.","junction.limit_valence":"Zu viele Wände treffen in einem Knoten aufeinander: {actual}, maximal {limit}.","junction.limit_length":"Das Wandsegment ist zu kurz: {actual} cm, mindestens {limit} cm.","junction.limit_distance":"Wände und Knoten sind zu dicht beieinander: {actual} cm, Minimum {limit} cm.","junction.limit_clearance":"Kein Wohnbereich ist übrig: {actual} cm², Minimum {limit} cm².","junction.limit_check_failed":"Die Überprüfung der Verbindungen konnte nicht durchgeführt werden — die Änderung wurde nicht gespeichert.","toast.wall_model_migration_blocked":"Das Wandmodell konnte nicht aktualisiert werden: {reason}. Der Plan wurde nicht geändert. Führen Sie „Pläne optimieren“ aus; wenn der Fehler erneut auftritt, beheben Sie die widersprüchliche Wandgeometrie.","toast.wall_model_client_outdated":"Aktualisieren Sie die Karte und laden Sie die Seite neu, bevor Sie den Plan bearbeiten.","wall_model.reason.invalid-room":"ungültiger Raumkontur","wall_model.reason.zero-length":"Wandsegment mit null Länge","wall_model.reason.third-owner":"Wand, die von mehr als zwei Räumen geteilt wird","wall_model.reason.duplicate-id":"widersprüchliche Wandkennungen","wall_model.reason.thickness-conflict":"widersprüchliche Wandstärkenwerte","wall_model.reason.opening-host":"Öffnung kann nicht einer Wand zugewiesen werden","toast.delete_room_pick":"Klicken Sie in den Raum, den Sie löschen möchten","toast.plan_snap_ambiguous":"Zoomen Sie hinein, um den Wandknoten auszuwählen","toast.wall_repair_ambiguous":"Der Raumumriss hat mehr als eine mögliche Verbindung. Zoomen Sie hinein und verbinden Sie ihn explizit.","toast.wall_repair_too_large":"Die Lücke ist größer als 2 cm. Verbinden Sie die Wände, bevor Sie den Raum erstellen.","toast.wall_repair_changed":"Die Wandgeometrie hat sich geändert. Versuchen Sie erneut, den Raum zu erstellen.","toast.opening_on_zero_wall":"Öffnungen können nicht auf einer Wand mit null Dicke sitzen.","marker.from_ha_option":"Wählen Sie aus der HA-Liste.","marker.show_entities":"Entitäten anzeigen.","marker.show_entities_tip":"Fügt nicht nur Geräte zur Liste hinzu, sondern auch alle ihre Entitäten.","marker.pick_ph":"Wählen Sie ein Gerät…","room.open_area":"Öffnen Sie den HA-Bereich.","view.volumetric":"Volumetrische Ansicht.","view.flat":"Flache Ansicht.","kiosk.title":"Die Größen dieses Bildschirms.","kiosk.hint":"Nur auf diesem Gerät gespeichert – jedes Wandtablet oder TV kann seine eigenen komfortablen Größen haben.","kiosk.icon_scale":"Gerätesymbolgröße.","kiosk.font_scale":"Textgröße der Raumkarte.","editor.kiosk":"Wandgeräte- (Kiosk-)Modus.","editor.cycle":"Bereiche automatisch alle N Sekunden wechseln (Kiosk, 0 = aus)","room.settings_title":"Raumeinstellungen.","room.settings_section":"Raumeinstellungen (überschreibt den Bereich)","room.fill_label":"Diesen Raum ausfüllen","fill.inherit":"Als den Bereich","room.custom_fill_space":"Bereichsfarbe","room.custom_fill_own":"Raumfarbe","room.temp_src_label":"Temperaturquelle","room.hum_src_label":"Luftfeuchtigkeitsquelle","room.src_average":"Durchschnitt über die Sensoren des Raums (Standard)","room.src_pick":"Ein bestimmtes HA-Gerät oder Entität","room.src_ph":"Quelle wählen…","toast.room_updated":"Raum aktualisiert","space.card_font":"Schriftgröße der Raumkarte (gesamter Bereich)","room.sizes_section":"Schriftgrößen","room.name_scale":"Raumname Größe","room.label_scale":"Metrikgröße","preview.room_name":"Wohnzimmer","toast.cfg_reload_failed":"Der Plan konnte nicht vom Server neu geladen werden: {err}","toast.locale_load_failed":"Das Sprachpaket konnte nicht geladen werden. Bis zum Neuladen der Seite wird Englisch verwendet.","room.settings_short":"Raumeinstellungen","room.unnamed":"Unbenannter Raum","marker.use_climate_temp":"Geräte-Temperatur im Raum berücksichtigen","marker.use_climate_temp_tip":"Fügt die aktuelle Temperatur einer Klimaanlage oder eines Thermostats zum Raumdurchschnitt hinzu. Das externe Wert-Label unten separat konfigurieren.","marker.value_badge_title":"Wert-Label","marker.value_badge.help":"Zeigt einen ausgewählten Wert neben dem Symbol an. Dies beeinflusst nicht die Raumkennzahlen, Licht, Glanz oder die Tippaktion.","marker.value_badge.help.aria":"Hilfe: Gerätewert-Badge","marker.value_badge_enabled":"Zeige ein Wert-Badge","marker.value_badge_source":"Wert","marker.value_badge_source.help":"Wählen Sie einen bestimmten Zustand, ein unterstütztes Attribut oder einen abgeleiteten Wert dieses Geräts.","marker.value_badge_source.help.aria":"Hilfe: Quelle des Wert-Badges","marker.value_badge_position":"Position","marker.value_badge_position.help":"Die gewählte Seite bleibt fest und dreht sich nicht automatisch an einem Planrand.","marker.value_badge_position.help.aria":"Hilfe: Position des Wert-Badges","marker.value_badge_right":"Rechts","marker.value_badge_bottom":"Unten","marker.value_badge_left":"Links","marker.value_badge_top":"Oben","marker.value_badge_empty":"Für dieses Gerät stehen keine Werte zur Verfügung","marker.value_badge_static":"Ein statisches Symbol zeigt keine Live-Werte an. Die Einstellung wird beibehalten.","marker.value_badge_missing":"Quelle nicht verfügbar","marker.value_badge_missing_hint":"Die gespeicherte Quelle ist derzeit nicht verfügbar. Behalten Sie sie bei, deaktivieren Sie das Badge oder wählen Sie einen anderen Wert.","marker.value_badge_duplicate":"Derselbe Wert wird bereits im Symbol angezeigt.","marker.value_badge_state":"Status · {name}","marker.value_badge_marker_state":"Lichtquellstatus · {name}","marker.value_badge_lqi":"Durchschnittliche Zigbee-Signalqualität","marker.value_badge_attr_current_temperature":"Aktuelle Temperatur · {name}","marker.value_badge_attr_temperature":"Zieltemperatur · {name}","marker.value_badge_attr_current_humidity":"Aktuelle Luftfeuchtigkeit · {name}","marker.value_badge_attr_humidity":"Luftfeuchtigkeit · {name}","marker.value_badge_attr_current_position":"Position · {name}","marker.value_badge_attr_percentage":"Geschwindigkeit · {name}","marker.value_badge_attr_brightness":"Helligkeit · {name}","marker.value_badge_attr_volume_level":"Lautstärke · {name}","marker.value_badge_attr_battery_level":"Batterie · {name}","marker.value_badge_attr_fan_speed":"Lüftergeschwindigkeit · {name}","marker.value_source":"Wertquelle","marker.value_source.help":"Wähle den Wert, der das Symbol ersetzt. Die Tipp-Aktion bleibt unverändert.","marker.value_source.help.aria":"Hilfe: Wertquelle in der Gerätefläche","marker.value_source_auto":"Automatisch (wie bisher)","marker.value_source_missing_hint":"Die gespeicherte Quelle ist derzeit nicht verfügbar. Bis sie wieder verfügbar ist oder ein anderer Wert gewählt wird, zeigt die Fläche —.","marker.light_role_label":"Ist dieses Gerät eine Lichtquelle?","marker.light_role.help":"„Auto“ verwendet die ermittelte Rolle des verknüpften Geräts, „Immer“ erzwingt eine eigene Quelle und „Nie“ schließt sie aus; oben verknüpfte Lichter bleiben unabhängig.","marker.light_role.help.aria":"Hilfe: ob dieses Gerät eine Lichtquelle ist","marker.light_role_auto_yes":"Automatisch (Lichtquelle)","marker.light_role_auto_no":"Automatisch (keine Lichtquelle)","marker.light_role_always":"Immer eine Lichtquelle","marker.light_role_never":"Nie eine Lichtquelle","marker.light_entity_label":"Führende Lichtereinheit","marker.light_entity.help":"Für ein Verbundgerät wählen Sie die Entität, deren Zustand, Farbe und Helligkeit diese Planquelle darstellen. Der automatische Rückgriff bleibt mit älteren Plänen kompatibel.","marker.light_entity.help.aria":"Hilfe: führende Lichtentität","marker.light_entity_auto":"Automatisch ({entity})","marker.light_entity_none":"keine steuerbare Entität","marker.light_entity_missing":"Die gespeicherte Entität {entity} ist nicht verfügbar. House Plan verwendet vorübergehend {fallback}; die gespeicherte Auswahl wird wiederhergestellt, wenn sie zurückkehrt.","marker.toggle_entity_label":"Zu toggelnde Entität","marker.toggle_entity.help":"Für ein Verbundgerät wählen Sie das genaue eigene Licht oder den Schalter, der durch Tippen bedient wird. Automatisch behält die vorherigen Zielregeln bei und ist unabhängig von der führenden Lichtentität.","marker.toggle_entity.help.aria":"Hilfe: zu toggelnde Entität","marker.toggle_entity_auto":"Automatisch ({entity})","marker.toggle_entity_none":"keine eigene steuerbare Entität","marker.toggle_entity_missing":"Die gespeicherte Entität {entity} ist nicht mehr unter den auswählbaren Kanälen dieses Markers. House Plan verwendet vorübergehend {fallback}; die gespeicherte Auswahl wird wiederhergestellt, wenn sie zurückkehrt.","marker.glow_color_label":"Leuchtfarbe und Helligkeit","marker.glow_mode.help":"Verwenden Sie Live-Quellwerte, überschreiben Sie nur deren Farbe oder fixieren Sie sowohl Farbe als auch Helligkeit. Das Minimum beträgt 1 %; um die Quelle zu deaktivieren, wählen Sie „Nie“.","marker.glow_mode.help.aria":"Hilfe: Leuchtfarbe und Helligkeit","marker.glow_mode_auto":"Von Quelle","marker.glow_mode_color":"Farbe einstellen","marker.glow_mode_fixed":"Farbe und Helligkeit einstellen","marker.glow_color":"Leuchtfarbe","marker.glow_brightness":"Helligkeit","marker.glow_disabled_never":"Leuchteinstellungen sind nicht verfügbar, da dieser Marker ausdrücklich keine Lichtquelle ist.","marker.glow_disabled_auto":"Im Automatikmodus wurde keine räumliche Lichtquelle für diesen Marker gefunden.","marker.glow_disabled_no_entity":"Keine aktive steuerbare Home Assistant-Entität ist für diese räumliche Quelle verfügbar.","marker.glow_passive_hint":"Diese Quelle hat keine eigenen Home Assistant-Daten. Stellen Sie ihre Farbe und Helligkeit manuell ein; ihr Radius bleibt verfügbar.","marker.control_broken":"Gespeicherte Quelle fehlt oder ist nicht mehr als Licht markiert","marker.control_missing_label":"Fehlendes Planlicht","marker.control_passive":"passive Quelle","toast.marker_control_cycle":"Dieser Link würde eine kreisförmige Kette von Lichtsteuerungen erzeugen.","toast.marker_binding_required":"Wählen Sie ein Home Assistant-Gerät, bevor Sie eine andere Lichtquelle verlinken.","confirm.unlock_title":"Schloss öffnen?","confirm.unlock_body":"House Plan sendet einen Befehl zum Öffnen an dieses Schloss.","toast.files_migrate_failed":"Anhänge konnten nicht zur neuen Bindung verschoben werden, Links zeigen weiterhin auf die alten Dateien: {err}","space.pick_saved":"Bereits hochgeladen","space.pick_saved_hint":"Auf dem Server gespeicherte Pläne, einschließlich solcher, die Sie zuvor getrennt haben","space.no_saved":"Noch keine Pläne auf dem Server gespeichert.","space.loading":"Laden…","space.used_by":"in Benutzung: {list}","space.in_use":"Ein Bereich verwendet diesen Plan noch — zuerst die Verknüpfung lösen","btn.use":"Verwenden","confirm.delete_plan_title":"Plandatei löschen?","confirm.delete_plan_body":"Die Datei wird vom Server gelöscht. Dieser Vorgang kann nicht rückgängig gemacht werden.","toast.plans_list_failed":"Konnte die gespeicherten Pläne nicht auflisten: {err}","toast.plan_delete_failed":"Konnte den Plan nicht löschen: {err}","marker.hide":"Ausblenden","marker.hide_tip":'Das Gerät wird nach dem Speichern aus dem Plan verschwinden, aber weiterhin zum Signalsignal des Raums zählen. Stellen Sie es über den Katalog "Geräte" im Geräte-Editor wieder her.',"marker.show":"Anzeigen","marker.show_tip":"Das Gerät wird nach dem Speichern wieder im Plan erscheinen.","marker.hidden_ghost":"Vom Benutzer ausgeblendetes Gerät","marker.ha_disabled_device":"Das Gerät ist in Home Assistant deaktiviert und im Plan ausgeblendet.","marker.ha_disabled_entity":"Die Entität ist in Home Assistant deaktiviert und im Plan ausgeblendet.","marker.ha_disabled_all_entities":"Das Gerät hat keine aktiven Home Assistant-Entitäten, daher ist es im Plan ausgeblendet.","marker.ha_registry_limited":"Das vollständige Home Assistant-Register ist für diesen Benutzer nicht verfügbar. Das nicht verifizierte Objekt kann vorerst nicht angezeigt oder verwendet werden.","marker.delete_tip":"Löschen Sie das Gerät vollständig aus dem Plan und allen Aggregaten. Sie können es später wieder hinzufügen.","tap.run":"Führen Sie Automation/Skript/Szene aus","tap.none":"Nichts tun","marker.run_target_label":"Was ausführen","marker.run_search_ph":"Suchen: Automation, Skript oder Szene…","marker.run_target_gone":"Ziel {id} nicht gefunden — erneut auswählen","marker.tap_confirm":"Um Bestätigung bitten","marker.tap_confirm_tip":"Vor der Ausführung ein Bestätigungsdialogfeld anzeigen — eine Vorsichtsmaßnahme gegen versehentliche Berührungen.","marker.toggle_hint_single":"Ziel: {name} ({id}).","marker.virtual_light_target":"Virtuelles Licht: {name}.","marker.virtual_light_current":"Manueller Zustand: {state} → {effect}.","marker.virtual_light_state_on":"ein","marker.virtual_light_state_off":"aus","marker.toggle_hint_group":"Wird {count}-Quelle(n) umschalten: {names}.","marker.toggle_hint_current":"Jetzt: {state} → {effect}.","marker.toggle_hint_group_current":"Derzeit an: {on} von {count} → {effect}.","marker.toggle_hint_skipped":"Wird übersprungen ({count}): {targets}.","marker.toggle_effect_turn_on":"wird eingeschaltet","marker.toggle_effect_turn_off":"wird ausgeschaltet","marker.toggle_effect_open":"wird geöffnet","marker.toggle_effect_close":"wird geschlossen","marker.toggle_effect_stop":"wird gestoppt","marker.toggle_effect_toggle":"Zustand wird umgeschaltet","marker.toggle_skip_missing":"nicht gefunden","marker.toggle_skip_ha_disabled":"in HA deaktiviert","marker.toggle_skip_unavailable":"nicht verfügbar","marker.toggle_skip_unsupported":"Umschalten wird nicht unterstützt","marker.toggle_skip_secure":"aus Sicherheitsgründen blockiert","marker.toggle_none_no_binding":"Dieses Gerät hat keine Bindung, daher gibt es keinen Zustand, der umgeschaltet werden könnte. Tippen bewirkt nichts.","marker.toggle_none_no_actionable_entity":"Dieses Gerät hat keinen Zustand, der umgeschaltet werden könnte. Tippen bewirkt nichts.","marker.toggle_none_configured_targets_missing":"Die konfigurierten Ziele sind nicht verfügbar. Die eigene Entität des Geräts wird nicht ersetzt.","marker.toggle_none_ha_disabled":"Das Ziel ist in Home Assistant deaktiviert und kann im Plan nicht verwendet werden.","marker.toggle_none_unavailable":"Das Ziel ist derzeit nicht verfügbar. Tippen bewirkt nichts.","marker.toggle_none_unsupported":"Home Assistant bietet keine sichere Umschaltfunktion für dieses Gerät. Tippen bewirkt nichts.","marker.toggle_none_secure":"Das Umschalten von Schlössern, Alarmen und gesicherten Toren über den Plan ist aus Sicherheitsgründen gesperrt.","run.automation":"Automatisierung","run.script":"Skript","run.scene":"Szene","confirm.tap_run":'"{name}" ausführen?',"confirm.tap_toggle":'"{name}" umschalten?',"confirm.current_state":"Aktueller Zustand: {state}","confirm.expected_state":"Nach dem Umschalten: {state}","confirm.group_current":"an {on} von {total}","confirm.group_all_on":"alle sind eingeschaltet","confirm.group_all_off":"alle sind ausgeschaltet","confirm.unavailable_targets":"Nicht verfügbar: {count}","confirm.expected_by_ha":"Home Assistant ermittelt den Zustand","confirm.state_on":"Ein","confirm.state_off":"Aus","confirm.state_open":"Offen","confirm.state_closed":"Geschlossen","confirm.state_opening":"Wird geöffnet","confirm.state_closing":"Wird geschlossen","confirm.state_stopped":"Gestoppt","confirm.state_unknown":"Unbekannt","toast.run_started":"Gestartet: {name}","toast.run_target_missing":"Ausführungsziel nicht gefunden — überprüfen Sie die Geräteeinstellungen","toast.run_target_required":"Wählen Sie eine Automatisierung, ein Skript oder eine Szene aus","toast.tap_target_changed":"Das Ziel der Aktion hat sich geändert. Versuchen Sie es erneut.","toast.virtual_light_toggle_failed":"Das virtuelle Licht konnte nicht umgeschaltet werden: {err}","toast.value_badge_source_required":"Einen Wert für den Badge auswählen","btn.run":"Ausführen","vac.section":"Roboterstaubsauger: aktuelle Position","vac.autocal":"Automatisch einrichten","vac.live":"Aktuelle Position im Plan","vac.trail":"Roboterpfad anzeigen","vac.autocal_no_rooms":'Die Integration meldet keine Raumliste — öffnen Sie "Manuell anpassen"',"vac.route_warn_unmapped":"Der Roboter reinigt eine Karte, die keiner Etage zugeordnet ist","vac.route_warn_needs_calibration":"Die Karte ist einer Etage zugeordnet, aber nicht kalibriert","vac.route_warn_ambiguous":"Zwei Karten sind nicht unterscheidbar — keine Etage gewählt","vac.route_warn_missing_space":"Der Raum dieser Karte wurde gelöscht","vac.autocal_no_match":'Raumnamen stimmten nicht überein (mindestens 3 müssen übereinstimmen) — öffnen Sie "Manuell anpassen"',"vac.autocal_done":"Fertig: über {rooms} Räume zugeordnet. Eine Reinigung starten und das Ergebnis prüfen.","vac.cal_need_pos":"Der Roboter meldet keine Koordinaten — starten Sie eine Reinigung und pausieren Sie sie","vac.cal_done":"Kalibrierung gespeichert. Eine Reinigung starten und das Ergebnis prüfen.","vac.cal_cancelled":"Kalibrierung abgebrochen","vac.fit":"Manuell anpassen","vac.fit_hint":"Roboterkarte an die richtige Position ziehen und an den Ecken skalieren","vac.fit_rotate":"90° drehen","vac.fit_mirror":"Spiegeln","vac.trail_never":"Nie","vac.trail_cleaning":"Beim Reinigen","vac.trail_always":"Immer","gs.bg_group":"Bühnenhintergrund","gs.bg_color":"Hintergrund um den Plan","gs.bg_default":"Standardthema","gs.bg_theme":"Standardthema","gs.bg_mode":"Planhintergrund","gs.bg_mode.help":"„Folgt der Sonne“ verwendet sun.sun und ersatzweise die lokale Browserzeit; „Statische Farbe“ zeigt immer die ausgewählte Farbe.","gs.bg_mode.help.aria":"Hilfe: allgemeiner Planhintergrund","gs.bg_static":"Statische Farbe","gs.bg_daynight":"Folgt der Sonne","gs.sun_group":"Sonne","gs.sun_missing":"Die sun.sun-Entität wurde nicht gefunden — der Hintergrund folgt Ihrer lokalen Uhr; Fensterstrahlen sind nicht verfügbar.","gs.north":"Norden auf dem Plan","gs.north.help":"Der Winkel wird im Uhrzeigersinn von der oberen Vertikalen des Plans gemessen; Norden wird für Fensterstrahlen benötigt, nicht für den Hintergrund „Folgt der Sonne“.","gs.north.help.aria":"Hilfe: allgemeine Nordrichtung","gs.north_ph":"nicht gesetzt","gs.north_clear":"Löschen","gs.north_letter":"N","gs.sun_rays":"Sonnenlicht durch Fenster","gs.about_version":"House Plan Card v{v}","gs.about_github":"GitHub · Dokumentation & Probleme","gs.about_telegram":"Telegram-Chat","support.title":"Hilfe & Feedback","space.bg_color":"Hintergrund rund um den Plan","space.bg_inherit":"Allgemein erben","space.bg_inherited":"erbt allgemeine Einstellungen","space.bg_mode":"Planhintergrund","space.bg_mode.help":"Übernehmen Sie den allgemeinen Hintergrund oder überschreiben Sie diesen Bereich mit einer statischen Farbe oder „Folgt der Sonne“.","space.bg_mode.help.aria":"Hilfe: Hintergrund des Bereichs","space.north":"Norden auf dem Plan (überschreiben)","space.north.help":"Überschreibt die allgemeine Nordrichtung für diesen Bereich; der Winkel wird im Uhrzeigersinn von der oberen Vertikalen des Plans gemessen und für Fensterstrahlen verwendet.","space.north.help.aria":"Hilfe: Norden für diesen Bereich","space.north_inherited":"geerbt: {v}","space.sun_rays":"Sonnenlicht durch Fenster","space.sun_inherit":"Allgemein erben","space.sun_on":"Ein","space.sun_off":"Aus","canvas.far_objects":"{n} Objekt(e) weit vom Plan entfernt","canvas.show_far":"Anzeigen","canvas.home_tip":"Der Plan ist dort drüben — klicken, um ihn anzupassen","gs.grid_group":"Planwartung","gs.grid_hint":"Aktualisiert Datenmodelle, richtet Planelemente am Raster aus und fasst redundante Wandfragmente zusammen. Ein exakter Bericht wird angezeigt, bevor etwas gespeichert wird.","gs.align_all":"Pläne optimieren","gs.align_title":"Pläne optimieren","gs.align_none":"Alle Pläne verwenden bereits das aktuelle optimierte Datenmodell.","gs.optimize_no_automatic_changes":"Es gibt keine automatischen Änderungen, die angewendet werden müssen. Überprüfen Sie die unten stehenden Punkte.","gs.align_count":"{n} von {total} Elementen werden sich um höchstens {cm} cm bewegen.","gs.align_where":"Die größte Verschiebung ist in „{s}“.","gs.align_turned":"Öffnungen, deren Winkel korrigiert wurde: {n}.","gs.align_removed_drafts":"Ungültige Umrisse vom Raster zusammengeklappt und entfernt: {n}.","gs.optimize_redundant_drafts":"Gespeicherte Wandketten, die durch feste Raumwände verdeckt waren, wurden entfernt: {n}.","gs.align_preflight_failed":"Die Geometrie der folgenden Bereiche konnte nicht sicher überprüft werden: {spaces}{more}.","gs.align_preflight_hint":"Pläne wurden nicht geändert. Kopieren Sie die Diagnosen mit dem untenstehenden Button und fügen Sie sie zusammen mit einem Raumexport dem Fehlerbericht bei.","gs.preflight_reason_prepare-exception":"Die Bereichsgeometrie konnte nicht vorbereitet werden (Ausnahme beim Erstellen des Modells)","gs.preflight_reason_wall-null":"Der Wandkörper wurde nicht erstellt (die Vereinigung lieferte leer zurück)","gs.preflight_reason_wall-degraded-extra":"Der Wandkörper wurde mit zusätzlicher Geometrie beschädigt","gs.preflight_reason_wall-failed-core":"Der Kern des Wandkörpers konnte nicht zusammengesetzt werden","gs.preflight_reason_wall-exception":"Die Wandkonstruktion warf eine Ausnahme","gs.preflight_reason_floor-null":"Der Fußbodenumriss wurde nicht erstellt","gs.preflight_reason_floor-exception":"Bodenaufbau hat eine Ausnahme ausgelöst","gs.preflight_copy":"Diagnosen kopieren","gs.preflight_copied":"Diagnosen kopiert","gs.preflight_update_hint":"Die Karten- und Integrationsversionen unterscheiden sich — Hausplan aktualisieren und erneut versuchen.","gs.align_preflight_space":"Bereich {n}","gs.align_preflight_more":", und {n} mehr","gs.optimize_changes":"Modellmigrationen: {m}; aktualisierte Bereiche: {c}; entfernte verrauschte Koordinatenwerte: {p}; zusammengeführte Fragmente realer Wände: {w}; zusammengeführte Fragmente von Wänden ohne Dicke: {s}; unabhängige Wände: {i}.","gs.zero_walls_migrated":"Virtuelle Wandspannweiten konvertiert: {n}.","gs.wall_segments_migrated":"Wandsegmente stabilisiert: {n}.","gs.optimize_lattice_summary":"Rauschen in den Koordinatenwerten kanonisiert: {n}; maximale Bewegung: {cm} cm.","gs.optimize_lattice_space":"{space}: Koordinatenwerte kanonisiert: {n}; außerhalb des Rasters liegende Werte unverändert gelassen: {far}.","gs.optimize_coincident_partitions":"Versteckte unabhängige Wandabschnitte in Raumwände integriert: {n}.","gs.optimize_openings_rehosted":"Öffnungen wieder an Raumwände angebracht: {n}.","gs.optimize_walls_straightened":"Wände begradigt: {n}; maximale Bewegung: {cm} cm.","gs.optimize_walls_straightened_where":"Größte Wandkorrektur: {s}.","gs.optimize_walls_straighten_skipped":"Nahe Achsenwände unverändert gelassen, da sie nicht sicher repariert werden konnten: {n}.","gs.optimize_glow_migration":"Legacy Glow: {spaces} Bereiche → keine Datenfüllung + unabhängiges Glow; {rooms} Räume → geerbte Datenfüllung + unabhängiges Glow.","gs.optimize_references":"Referenzen repariert: Bereiche — {spaces}; Räume — {rooms}; Positionen — {positions}; Geräte aus fehlenden Bereichen gelöst — {detached}.","gs.optimize_reference_more":", und {n} mehr","gs.optimize_orphans_removed":"Vergessene Einträge entfernt: {total} — Raumbezeichnungen: {rooms}; Geräte: {devices}; Gruppenmarkierungen: {groups}. Sie gehörten zu zuvor gelöschten Bereichen.","gs.optimize_live_positions":"Alte Positionen in gelöschten Bereichen gehören zu vorhandenen Objekten: {n}{names}. Sie werden beibehalten.","gs.optimize_live_positions_remove":"Alte Positionen in gelöschten Bereichen gehören zu vorhandenen Objekten: {n}{names}. Sie sind zur Entfernung ausgewählt.","gs.optimize_live_names":": {names}{more}","gs.optimize_live_remove":"Alte Positionen entfernen","gs.optimize_live_keep":"Alte Positionen beibehalten","gs.optimize_live_selected":"Alte Positionen werden nach der Anwendung von Optimieren entfernt.","gs.optimize_unverified":"Positionen konnten nicht sicher überprüft werden: {n}. Sie wurden unverändert belassen.","gs.optimize_registry_limited":"Voller Administratorzugriff auf die Home Assistant-Registries ist für eine sichere Überprüfung erforderlich.","gs.optimize_vacuum_warning":"Raumzuordnungen, die noch überprüft werden müssen: {n}.","gs.optimize_details":"Details","gs.optimize_details_more":"Und {n} weitere Einträge.","gs.optimize_detail_removed":"wird entfernt","gs.optimize_detail_live":"wird beibehalten","gs.optimize_detail_unverified":"nicht überprüft","gs.optimize_detail_room_label":"Raumkennzeichnung","gs.optimize_detail_device":"Gerät","gs.optimize_detail_group":"Gruppenkennzeichen","gs.optimize_detail_unknown":"unbekannter Eigentümer","gs.optimize_detail_item":"{status}: {kind} {id}; alter Bereich {space}","gs.align_warn":"Absichtlich zwischen Rasterknoten platzierte Elemente werden sich bewegen. Nach der Operation ist nur eine Rückgängig-Funktion verfügbar, und zwar nur bis zur nächsten Planbearbeitung.","gs.align_run":"Optimieren","gs.align_done":"Pläne optimiert: {n} Elemente bewegt, {m} Datensätze beibehalten, {r} Verweise repariert","gs.optimize_undo":"Letzte Optimierung rückgängig machen","gs.optimize_undone":"Die letzte Optimierung wurde rückgängig gemacht","decor.furniture":"Möbel","decor.image":"Bild","decor.image_title":"Eigene Bilder","decor.image_upload":"Bild hochladen","decor.image_replace":"Bild ersetzen","decor.image_uploading":"Wird hochgeladen…","decor.image_asset":"Bilddatei","decor.image_pick_hint":"Ein Bild hochladen oder ein vorhandenes auswählen.","decor.image_place_hint":"Auf den Plan klicken, um das Bild zu platzieren.","decor.image_none":"Noch keine Bilder hochgeladen.","decor.image_unavailable":"Bild nicht verfügbar","decor.image_used":"In {n} Objekten verwendet","decor.image_upload_failed":"Bild konnte nicht hochgeladen werden: {err}","decor.image_error_capacity":"Der Speicher für benutzerdefinierte Bilder ist voll.","decor.image_in_use":"Vor dem Löschen alle platzierten Kopien entfernen.","decor.image_delete_title":"Bilddatei löschen?","decor.image_delete_message":"„{name}“ aus House Plan löschen? Dies kann nicht rückgängig gemacht werden.","furn.title":"Möbelbibliothek","furn.symbol":"Symbol","furn.group_furniture":"Möbel","furn.group_appliance":"Geräte","furn.group_sanitary":"Sanitär","furn.group_other":"Sonstiges","furn.width":"Breite","furn.depth":"Tiefe","furn.back_to_categories":"Alle Kategorien","furn.pick_hint":"Wählen Sie eine Kategorie und dann ein Symbol.","furn.place_hint":"Klicken Sie auf den Plan — das Element wird an der nächsten Wand platziert. Mit Shift wird es frei platziert.","furn.cat_air_conditioner":"Klimaanlagen","furn.cat_armchair":"Sessel","furn.cat_bathtub":"Badewannen","furn.cat_bed":"Betten","furn.cat_bidet":"Bidets","furn.cat_boiler":"Warmwasserbereiter","furn.cat_chair":"Stühle","furn.cat_coffee_table":"Couchtische","furn.cat_cooktop":"Kochfelder","furn.cat_dining_table":"Esstische","furn.cat_dishwasher":"Geschirrspüler","furn.cat_dryer":"Wäschetrockner","furn.cat_fireplace":"Kamine","furn.cat_fridge":"Kühlschränke","furn.cat_kitchen_cabinet":"Küchenschränke","furn.cat_kitchen_sink":"Küchenspülen","furn.cat_nightstand":"Schränke","furn.cat_plant":"Pflanzen","furn.cat_rug":"Teppiche","furn.cat_shelving":"Regale","furn.cat_shower":"Duschen","furn.cat_sink":"Waschbecken","furn.cat_sofa":"Sofas","furn.cat_stairs":"Treppen","furn.cat_toilet":"Toiletten","furn.cat_tv":"Fernseher","furn.cat_wardrobe":"Kleiderschränke","furn.cat_washer":"Waschmaschinen","furn.cat_work_table":"Schreibtische","furn.sym_sofa":"Zweisitzer-Sofa","furn.sym_sofa_three_seat":"Dreisitzer-Sofa","furn.sym_sofa_corner_right":"Ecksofa rechts","furn.sym_armchair":"Polstersessel","furn.sym_armchair_office":"Bürostuhl","furn.sym_coffee_table":"Rechteckiger Couchtisch","furn.sym_coffee_table_round":"Runder Couchtisch","furn.sym_coffee_table_oval":"Ovaler Couchtisch","furn.sym_coffee_table_rounded":"Abgerundeter Couchtisch","furn.sym_table_dining":"Rechteckiger Esstisch","furn.sym_table_round":"Rundtisch","furn.sym_table_dining_oval":"Ovaler Esstisch","furn.sym_table_dining_rounded":"Abgerundeter Esstisch","furn.sym_chair":"Stuhl","furn.sym_chair_bar":"Barhocker","furn.sym_desk":"Rechteckiger Schreibtisch","furn.sym_desk_corner":"Eckschreibtisch","furn.sym_bed_double":"Doppelbett","furn.sym_bed_single":"Einzelbett","furn.sym_nightstand":"Nachttisch","furn.sym_cabinet_tv":"TV-Schrank","furn.sym_cabinet_shoe":"Schuhschrank","furn.sym_cabinet_sink":"Waschtischunterschrank","furn.sym_wardrobe":"Kleiderschrank","furn.sym_bookshelf":"Bücherschrank","furn.sym_wall_unit":"Schrankwand","furn.sym_kitchen_floor":"Küchen-Unterschrank","furn.sym_kitchen_floor_corner":"Küchen-Eckunterschrank","furn.sym_kitchen_wall":"Küchen-Hängeschrank","furn.sym_kitchen_wall_corner":"Küchen-Eckhängeschrank","furn.sym_shelf_floor":"Standregal","furn.sym_shelf_wall":"Wandregal","furn.sym_fridge":"Kühlschrank","furn.sym_stove":"Vierflammiges Kochfeld","furn.sym_cooktop_two":"Zweiflammiges Kochfeld","furn.sym_dishwasher":"Geschirrspüler","furn.sym_washer":"Waschmaschine","furn.sym_dryer":"Wäschetrockner","furn.sym_tv":"Fernseher mit Standfuß","furn.sym_tv_wall":"Wandfernseher","furn.sym_ac":"Klimaanlage","furn.sym_water_heater":"Wassererhitzer","furn.sym_toilet":"Stand-WC","furn.sym_toilet_built_in":"Wand-WC","furn.sym_bathtub":"Rechteckige Badewanne","furn.sym_bathtub_corner":"Eckbadewanne","furn.sym_shower":"Dusche","furn.sym_sink":"Waschbecken","furn.sym_kitchen_sink":"Einzel-Küchenspüle","furn.sym_kitchen_sink_double":"Doppel-Küchenspüle","furn.sym_bidet":"Stand-Bidet","furn.sym_bidet_built_in":"Wand-Bidet","furn.sym_stairs":"Treppe","furn.sym_fireplace":"Kamin","furn.sym_plant":"Pflanze","furn.sym_rug":"Teppich","common.yes":"Ja","common.no":"Nein","vac.diag_source":"Quelle","vac.diag_platform":"Integration","vac.diag_status":"Status","vac.diag_position":"Position","vac.diag_rooms":"Räume","vac.diag_rooms_value":"{total} · {matched} Namen stimmen überein · {readiness}","vac.autocal_ready":"Auto-Kalibrierung verfügbar","vac.autocal_not_ready":"3 übereinstimmende Namen erforderlich","vac.diag_path":"Integrationspfad","vac.diag_map":"Karten-ID","vac.source_none":"nicht ausgewählt","vac.source_status_ok":"Bereit","vac.source_status_missing":"Fehlend","vac.source_status_disabled":"In Home Assistant deaktiviert","vac.source_status_unavailable":"Nicht verfügbar","vac.source_status_unverified":"Kann mit den aktuellen Berechtigungen nicht verifizieren","vac.source_status_unsupported":"Keine Positionsdaten","vac.source_status_none":"Keine Quelle","vac.source_banner_missing":"Die gespeicherte Quelle existiert nicht mehr. Sie wurde nicht automatisch ersetzt; wählen Sie eine andere Quelle oder stellen Sie sie in Home Assistant wieder her.","vac.source_banner_disabled":"Die gespeicherte Quelle ist in Home Assistant deaktiviert. Aktivieren Sie sie dort oder wählen Sie eine andere Quelle.","vac.source_banner_unverified":"Die aktuellen Home Assistant-Berechtigungen können diese gespeicherte Quelle nicht verifizieren. Sie bleibt angepinnt und wird nicht automatisch ersetzt.","vac.choose_source":"Quelle wählen","vac.source_auto":"Automatisch","vac.source_auto_hint":"Verwenden Sie eine kompatible Entität von diesem Gerät","vac.all_cameras":"Alle Kameras","vac.all_cameras_warn":"Eine Kamera liefert möglicherweise keine Roboter-Daten. Wählen Sie eine nur, wenn es Ihre Saugroboter-Karte ist.","vac.all_cameras_empty":"Keine anderen Kamera-Entitäten gefunden.","vac.platform_unknown":"unbekannte Integration","vac.cap_position":"Position","vac.cap_rooms_short":"Räume","vac.cap_path":"Pfad","vac.cap_map":"Karten-ID","vac.cap_none":"Keine Roboter-Daten erkannt","vac.xcme_hint":"Aktivieren Sie diese Xiaomi Cloud Map Extractor-Attribute:","vac.documentation":"Dokumentation","vac.residual_title":"Automatische Kalibrierung überprüfen","vac.residual_message":"Die zugeordneten Räume weichen um bis zu {error} voneinander ab. Diese ungefähre Kalibrierung anwenden, manuell verfeinern oder ohne Änderung der gespeicherten Einrichtung abbrechen.","vac.apply_proposal":"Anwenden","gs.backup_group":"Sichern und übertragen","gs.backup_hint":"Laden Sie ein tragbares JSON-Backup herunter oder sehen Sie eine Vorschau und importieren Sie ein Backup, das mit House Plan erstellt wurde.","backup.export_open":"Exportieren","backup.import_open":"Importieren","backup.export_title":"House Plan exportieren","backup.import_title":"House Plan importieren","backup.export_hint":"Wählen Sie, ob das Backup die gesamte House Plan-Konfiguration oder nur den aktuellen Bereich enthalten soll.","backup.full":"Vollständiges Backup","backup.current_space":"Aktueller Bereich","backup.current_space_title":"Aktueller Bereich: {title}","backup.no_current_space":"Kein aktueller Bereich","backup.plan_only":"Nur Plan","backup.plan_only_hint":"Räume, Wände, Öffnungen, Dekor und Raumbezeichnungspositionen ohne Geräte oder Home Assistant-Bindungen beibehalten.","backup.plan_only_preview":"Diese Datei enthält nur den Plan.","backup.privacy_warning":"Das Archiv enthält Namen, Home Assistant-Kennungen und genaue Koordinaten. Interne Pläne und Anhänge werden referenziert, nicht eingebettet; Laufzeitzustände und Staubsaugerspuren sind nicht enthalten.","backup.download":"JSON herunterladen","backup.export_done":"Backup heruntergeladen","backup.reading":"Überprüfe das Backup…","backup.revalidated":"Der Plan wurde nach dieser Vorschau geändert. Die Zusammenfassung wurde aktualisiert; überprüfen Sie sie und bestätigen Sie erneut.","backup.error.support_invalid_message":"Prüfen Sie die Supportnachricht und versuchen Sie es erneut.","backup.error.support_package_too_large":"Das anonymisierte Supportpaket überschreitet das Limit von 8 MiB.","backup.error.support_preview_expired":"Die Vorschau des Supportanhangs ist abgelaufen oder nicht mehr verfügbar.","backup.error.support_rate_limited":"Zu viele Supportberichte oder Vorschauen wurden angefordert. Versuchen Sie es später erneut.","backup.error.support_rejected":"Der Bericht hat die Prüfung des Supportdienstes nicht bestanden.","backup.error.support_unavailable":"Der private Supportdienst ist vorübergehend nicht verfügbar.","backup.error.unauthorized":"Sie haben keine Berechtigung, diesen Plan zu exportieren oder zu importieren.","backup.error.not_ready":"Der Hausplan ist noch nicht fertig. Versuchen Sie es in einem Moment erneut.","backup.error.too_large":"Das Backup überschreitet das 8-MiB-Limit.","backup.error.invalid_json":"Die ausgewählte Datei ist kein gültiges JSON.","backup.error.invalid_format":"Die ausgewählte Datei ist kein House Plan-Backup.","backup.error.invalid_image":"Das Bild ist beschädigt oder entspricht nicht seinem Format.","backup.error.unsupported_export_version":"Dieses Backup-Format wird von der installierten Version nicht unterstützt.","backup.error.unsupported_image":"Verwenden Sie ein unterstütztes PNG-, JPEG-, WebP- oder SVG-Bild.","backup.error.future_model":"Das Backup wurde mit einem neueren House-Plan-Datenmodell erstellt.","backup.error.invalid_config":"Das Backup enthält eine ungültige House-Plan-Konfiguration.","backup.error.wall_model_migration_blocked":"Das Backup-Wandmodell konnte nicht sicher aktualisiert werden. Optimieren Sie zuerst den Quellplan und exportieren Sie ihn dann erneut.","backup.error.invalid_layout":"Das Backup enthält ungültige Objektpositionen.","backup.error.invalid_content":"Das Backup enthält ungültige oder inkonsistente Inhaltsreferenzen.","backup.error.space_not_found":"Der ausgewählte Bereich existiert nicht mehr.","backup.error.capacity_exceeded":"Durch das Hinzufügen dieses Backups würden die Planlimits überschritten.","backup.error.preview_expired":"Die Vorschau ist abgelaufen. Wählen Sie die Backup-Datei erneut aus.","backup.error.preview_owner_mismatch":"Diese Vorschau gehört zu einem anderen Home-Assistant-Benutzer.","backup.error.conflict":"Der Plan hat sich nach der Vorschau geändert. Überprüfen Sie die aktualisierte Zusammenfassung.","backup.error.content_confirmation_required":"Bestätigen Sie, dass nicht verfügbare lokale Inhalte getrennt werden können.","backup.error.commit_failed":"Das Backup konnte nicht sicher angewendet werden. Der vorherige Plan wurde wiederhergestellt oder wartet auf die Wiederherstellung.","backup.error.missing_plan":"Eine referenzierte Plan-Datei ist nach der Vorschau verschwunden. Überprüfen Sie das Backup erneut.","backup.error.missing_content":"Ein referenziertes lokales Anhangselement ist nach der Vorschau verschwunden. Überprüfen Sie das Backup erneut.","backup.error.marker_control_missing":"Ein verknüpftes Planlicht fehlt im Backup.","backup.error.marker_control_not_light":"Ein verknüpftes Planziel ist nicht mehr als Lichtquelle markiert.","backup.error.marker_control_self":"Eine Lichtquelle kann sich nicht selbst steuern.","backup.error.marker_control_cycle":"Das Backup enthält eine kreisförmige Kette von Lichtsteuerungen.","backup.error.duplicate_marker_control":"Das Backup enthält eine doppelte Plan-Licht-Verknüpfung.","backup.error.no_backup":"Es gibt keinen Import- oder Optimierungssnapshot zur Wiederherstellung.","backup.error.in_use":"Das Element wird noch verwendet","backup.error.invalid_data":"Die Anfrage enthält ungültige Daten","backup.error.invalid_light_entity":"Das führende Licht muss eine light.*- oder switch.*-Entität sein","backup.error.invalid_marker_control":"Ungültige Marker-Steuerungsreferenz","backup.error.invalid_name":"Der Name ist ungültig","backup.error.invalid_partition_opening_host":"Die Öffnung muss ihren Trennwand-Träger behalten","backup.error.invalid_partition_opening_jamb_margin":"Die Öffnung lässt keinen physischen Pfosten am Wandende","backup.error.invalid_passage_fields":"Ein offener Durchgang kann keine Tür-Einstellungen tragen","backup.error.invalid_space_id":"Unbekannter Raumbereich","backup.error.invalid_toggle_entity":"Die Schalt-Entität muss light.* oder switch.* sein","backup.error.invalid_value_badge":"Ungültige Wert-Badge-Einstellungen","backup.error.invalid_value_badge_attribute":"Ungültiges Wert-Badge-Attribut","backup.error.invalid_value_badge_position":"Ungültige Wert-Badge-Position","backup.error.invalid_value_badge_source":"Ungültige Wert-Badge-Quelle","backup.error.invalid_value_source":"Ungültige Wertquelle","backup.error.invalid_value_source_attribute":"Ungültiges Wertquellen-Attribut","backup.error.io_error":"Eine Dateioperation auf dem Server ist fehlgeschlagen","backup.error.not_toggleable":"Dieses Gerät kann nicht geschaltet werden","backup.error.nothing_to_repair":"Nichts zu reparieren","backup.error.space_in_use":"Der Raumbereich wird noch referenziert","backup.error.value_badge_source_required":"Das Wert-Badge braucht eine Quelle","backup.error.wall_model_client_outdated":"Der Plan wurde anderswo aktualisiert — Seite neu laden","backup.same_source":"Erstellt auf dieser Home Assistant-Instanz","backup.foreign_source":"Erstellt auf einer anderen Home Assistant-Instanz","backup.created":"Erstellt: {value}","backup.versions":"Karte {card}; Integration {integration}; Datenmodell {model}","backup.count_spaces":"Bereiche: {n}","backup.count_rooms":"Räume: {n}","backup.count_walls":"Wände: {n}","backup.count_openings":"Öffnungen: {n}","backup.count_decor":"Dekorationsobjekte: {n}","backup.count_markers":"Geräte: {n}","backup.count_layout":"Positionen: {n}","backup.bindings":"Verknüpfungen — Geräte: {device}, Entitäten: {entity}, virtuell: {virtual}; Positionen ohne Bereich: {legacy}","backup.binding_status":"Zielstatus — aktiv: {active}, deaktiviert: {disabled}, fehlt: {missing}","backup.missing_areas":"Auf dem Ziel fehlende Bereiche: {areas}","backup.dropped_marker_links":"Planlicht-Verknüpfungen außerhalb dieses übertragenen Bereichs wurden ausgelassen: {n}.","backup.repaired_target_refs":"Durch den Import dieses Bereichs wiederhergestellte vorhandene Referenzen: {n}.","backup.preserved_unresolved_refs":"Referenzen, die nicht eindeutig wiederhergestellt werden konnten, wurden beibehalten: {n}.","backup.preserved_unresolved_hint":"Es wurden keine Daten geraten oder gelöscht. Führen Sie nach dem Import Optimierungspläne aus, um die verbleibenden Referenzen zu überprüfen.","backup.import_details":"Importieren von Referenzdetails","backup.import_detail.incoming_remapped":"Referenzen innerhalb der importierten Kopie aktualisiert: {n}","backup.import_detail.target_repaired":"Vorhandene Referenzen wiederhergestellt: {n}","backup.import_detail.preserved_unresolved":"Unaufgelöste Referenzen beibehalten: {n}","backup.import_detail.collisions":"Zielkonflikte sicher beibehalten: {n}","backup.import_detail.dropped_links":"Eingehende Links durch Übertragungsregeln ausgelassen: {n}","backup.import_detail.bounded_lineages":"Übermäßig verschachtelte Kennungen begrenzt belassen: {n}","backup.replace_warning":"Dies ersetzt die aktuelle Konfiguration und das Layout. Hochgeladene Dateien werden niemals gelöscht. Eine Rückgängig-Möglichkeit bleibt bis zur nächsten Planbearbeitung verfügbar.","backup.foreign_bookkeeping":"Instanzspezifische bekannte/neue Gerätebuchführung wird nicht importiert.","backup.final_name":"Name des neuen Bereichs","backup.target_settings":"Die globalen Einstellungen der Zielinstanz bleiben unverändert.","backup.duplicates":"Bindungen bereits vorhanden: {n}","backup.skip":"Doppelte Geräte überspringen","backup.virtual_copy":"Sichere statische virtuelle Kopien hinzufügen","backup.content":"Referenzierter Inhalt","backup.decor_images_summary":"Eigene Bilder: {objects} Objekte, {assets} Dateien; fehlende Dateien: {missing}.","backup.content_available":"lokal verfügbar","backup.content_external":"externer Link","backup.content_detach_required":"wird getrennt","backup.confirm_detach":"Ich verstehe, dass nicht verfügbare interne Pläne und Anhänge von der importierten Konfiguration getrennt werden.","backup.confirm_missing_images":"Ich verstehe, dass fehlende eigene Bilder als reparierbare Platzhalter erhalten bleiben und andere nicht verfügbare lokale Dateien getrennt werden.","backup.replace":"Ersetzen","backup.add":"Bereich hinzufügen","backup.space_done":"Bereich importiert: {rooms} Räume, {markers} Geräte, {refs} bestehende Referenzen wiederhergestellt","backup.full_done":"Backup wiederhergestellt: {spaces} Bereiche, {rooms} Räume, {markers} Geräte","backup.undo_import":"Letzten vollständigen Import rückgängig machen","backup.import_undone":"Vollständiger Import rückgängig gemacht","backdrop.large_title":"Großes Bild","backdrop.large_body":"Dieses Bild ist {w}×{h} ({fileMb} MB Datei) und benötigt etwa {decodedMb} MB Speicher zur Anzeige. Auf Tablets kann das die Seite zum Absturz bringen.","backdrop.unknown_body":"Die Bildabmessungen konnten nicht gelesen werden — die Datei ist möglicherweise beschädigt. Fortfahren kann die Seite auf Tablets zum Absturz bringen.","backdrop.reduced_dimensions":"Verkleinerte Kopie: {w}×{h} px.","backdrop.use_downscaled":"Verkleinerte Kopie hochladen","backdrop.reducing":"Wird verkleinert…","backdrop.keep_original":"Original behalten","backdrop.too_large_title":"Bild ist zu groß","backdrop.too_large_body":"Dieses Bild überschreitet die Anzeigegrenzen des Browsers ({w}×{h}, Limit {limit} px pro Seite). Bitte verkleinern Sie es in einem Desktop-Editor und laden Sie es erneut hoch.","backdrop.downscale_failed":"Die verkleinerte Kopie konnte nicht erstellt werden. Der aktuelle Plan wurde nicht geändert."};const n="bd7029808eb6094140d9fa8245f50816cb452430a353f4231d16e02c97078a06";export{e as dictionary,n as fingerprint};
diff --git a/custom_components/houseplan/frontend/houseplan-assets/de-DZwnjt2u.js b/custom_components/houseplan/frontend/houseplan-assets/de-DZwnjt2u.js
new file mode 100644
index 00000000..2d83e92d
--- /dev/null
+++ b/custom_components/houseplan/frontend/houseplan-assets/de-DZwnjt2u.js
@@ -0,0 +1 @@
+globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="781b6de4892612660b01762cd408049137fa0d00417a43ef5bbdfb1ef37dc9a5";var e={"editor.context_actions":"Aktionen: {object}","editor.tool_options":"Werkzeugoptionen: {tool}","editor.palette":"Palette: {tool}","editor.open_group":"Werkzeuggruppe: {group}","editor.group_active":"{group} — aktiv: {item}","editor.disabled_action":"{action} ist nicht verfügbar: {reason}","editor.loading":"Editor wird geladen…","editor.loading_aria":"Der Plan-Editor wird geladen","editor.load_failed":"Der Editor konnte nicht geladen werden.","editor.refresh_advice":"Seite aktualisieren und erneut versuchen.","editor.retry_advice":"Verbindung prüfen und erneut drücken.","color_picker.title":"Farbwähler","color_picker.hue":"Farbton","color_picker.saturation":"Sättigung","color_picker.value":"Helligkeit","color_picker.hex":"Hex-Farbe","color_picker.invalid_hex":"Geben Sie eine 3- oder 6-stellige Hex-Farbe ein","btn.properties":"Eigenschaften","btn.keep_as_walls":"Als Wände behalten","btn.delete_room_keep_walls":"Raum löschen, Wände behalten","btn.delete_room_with_walls":"Raum und Wände löschen","title.markup_select":"Wände, Säulen und gespeicherte Umrisse auswählen und bearbeiten","title.markup_column":"Säule: Klicken Sie auf einen Rasterpunkt, um eine quadratische Säule zu platzieren","markup.partition":"Trennwand","markup.column":"Säule","markup.hint_column":"Klicken Sie auf einen Rasterpunkt, um eine quadratische Säule zu platzieren","history.draft_segment":"Raum-Entwurfsegment hinzufügen","history.draft_merge":"Unvollständige Raumumrisse verbinden","history.draft_segment_delete":"Raum-Entwurfssegment entfernen","history.column_add":"Säule hinzufügen","history.physical_edit":"Physisches Objekt ändern","history.physical_delete":"Physisches Objekt löschen","history.physical_move":"Physisches Objekt verschieben","history.contour_to_partitions":"Umriss in geschlossene Wände umwandeln","history.wall_chain_finish":"Wandkette fertigstellen","history.wall_face_batch":"Räume aus Wänden erstellen","toast.column_duplicate":"Eine Säule mit demselben Zentrum und äußerer Größe existiert bereits","confirm.delete_draft_title":"Unvollständigen Umriss löschen?","confirm.delete_draft_body":"Der gesamte unvollständige Raumumriss wird gelöscht. Beim Abbrechen wird nichts geändert.","confirm.delete_draft_segment_title":"Umrisssegment löschen?","confirm.delete_draft_segment_body":"Dieses Entwurfssegment wird gelöscht. Der verbleibende Umriss kann sich in zwei Teile aufteilen.","physical.partition_properties":"Eigenschaften der Trennwand","physical.column_properties":"Eigenschaften der Säule","physical.draft_properties":"Eigenschaften des Entwurfssegments","physical.shape":"Form","physical.square":"Quadrat","physical.circle":"Kreis","physical.diameter":"Durchmesser","physical.side":"Seite","physical.rotation":"Drehwinkel","physical.length":"Länge","physical.allowed_range":"Erlaubt: {min}–{max} {unit}","physical.delete_segment":"Segment löschen","physical.delete_draft":"Gesamten Umriss löschen","physical.column_size_title":"Außenmaß der per Klick platzierten quadratischen Säule (1–150 cm).","card.title":"Hausplan","count.devices":"{n} Entwicklung","empty.no_spaces":"Noch keine Bereiche.","empty.add_first":"Ersten Bereich hinzufügen und einen Grundriss hochladen.","empty.install":"Installieren Sie die House Plan-Integration und fügen Sie sie unter „Geräte & Dienste“ hinzu.","btn.add_space":"Bereich hinzufügen","btn.cancel":"Abbrechen","btn.save":"Speichern","btn.close":"Schließen","btn.delete":"Löschen","btn.edit":"Bearbeiten","btn.open_in_ha":"In HA öffnen","btn.reset":"Zurücksetzen","btn.attach":"Anhängen…","btn.upload":"Hochladen…","btn.replace":"Ersetzen…","title.zoom_in":"Zoomen","title.zoom_out":"Herauszoomen","title.zoom_fit":"Alles anpassen","title.configure_space":"Bereich konfigurieren","title.add_space":"Bereich hinzufügen","title.markup_add":"Wände: eine durchgehende Kette zeichnen; Shift sperrt auf 45°. Werkzeugwechsel oder Verlassen des Editors beendet die Kette und wandelt sie in unabhängige Wände","title.markup_merge":"Zusammenführen: Klicken Sie auf einen Raum und dann auf den Nachbarraum, mit dem er eine Wand teilt","title.markup_split":"Raum teilen: Klicken Sie auf den Raum und dann auf zwei Punkte an seinen Wänden","title.markup_delroom":"Raum löschen: Klicken Sie in einen Raum und bestätigen Sie","title.need_plan":"Einen Grundriss hochladen","markup.add":"Wände","markup.merge":"Zusammenführen","markup.split":"Teilen","markup.resize":"Größe ändern","title.markup_resize":"Räume vergrößern/verkleinern: Ziehen Sie einen verfügbaren horizontalen oder vertikalen Wandgriff","markup.hint_resize":"Ziehen Sie einen verfügbaren Wandgriff · die Wand stoppt an der ersten unsicheren Position · Esc bricht ab · Strg+Z — rückgängig","resize.disabled.diagonal":"Diese Wand ist geneigt; Größe ändern unterstützt nur horizontale und vertikale Wände","resize.disabled.side-angle":"Eine angrenzende Wand ist geneigt; Größe ändern erfordert, dass beide angrenzenden Wände diese Wand im rechten Winkel treffen","resize.disabled.duplicate-physical-wall":"Eine separate Trennwand, unfertige Kontur oder ein Pfeiler überlappt diese Wand; entfernen oder verschieben Sie sie, bevor Sie die Größe ändern","resize.disabled.partial-shared":"Ein angrenzender Raum nutzt nur einen Teil dieser Wand, daher kann sie nicht sicher als gemeinsame Wand verschoben werden","resize.disabled.unequal-shared":"Der angrenzende Raum nutzt andere Endpunkte oder Wandlängen, daher können die Wände nicht gemeinsam sicher bewegt werden","resize.disabled.multiple-rooms":"Das Verschieben dieser Wand würde mehr als zwei Räume betreffen","resize.disabled.thickness-conflict":"Die Wandstärke kann nicht sicher beibehalten werden","resize.disabled.opening-conflict":"Eine Öffnung an dieser Wand kann nicht sicher verschoben werden","resize.disabled.invalid-geometry":"Diese Wand kann nicht ohne Änderung der Planstruktur geändert werden","resize.limit_stopped":"Wand gestoppt: der nächste Schritt würde ein Anschlusslimit verletzen","resize.commit_failed":"Größenänderung wurde abgebrochen, da der endgültige Plan die Geometrieprüfung nicht bestanden hat","resize.preview_failed":"Größenänderung am letzten sicheren Punkt gestoppt, da die Plan-Geometrie nicht beibehalten werden konnte","markup.opening":"Öffnung","markup.delete_room":"Raum löschen","history.undo":"Rückgängig","history.redo":"Wiederholen","history.undo_named":"Rückgängig: {name} (Strg+Z)","history.redo_named":"Wiederholen: {name} (Strg+Shift+Z / Strg+Y)","history.undo_empty":"Nichts zu widerrufen","history.redo_empty":"Nichts zu wiederholen","history.undone":"Rückgängig gemacht: {name}","history.redone":"Wiederholt: {name}","history.add_room":"Raum erstellen","history.split_room":"Raum teilen","history.merge_rooms":"Räume zusammenführen","history.resize_room":"Raumgröße ändern","history.wall_thickness":"Wandstärke ändern","history.add_opening":"Tür- oder Fensteröffnung hinzufügen","history.edit_opening":"Öffnung bearbeiten","history.move_opening":"Öffnung verschieben","history.delete_opening":"Öffnung löschen","history.delete_room_keep_walls":"Raum löschen, Wände behalten","history.delete_room_with_walls":"Raum und Wände löschen","history.decor_add":"Dekorobjekt hinzufügen","history.decor_edit":"Dekorobjekt bearbeiten","history.decor_move":"Dekorobjekt verschieben","history.decor_transform":"Dekorobjekt transformieren","history.decor_delete":"Dekorobjekt löschen","history.backdrop_transform":"Plan-Hintergrund transformieren","history.device_move":"{name} verschieben","history.device_stale":"Der Positionsverlauf ist nicht mehr anwendbar und wurde gelöscht","opening.new":"Neue Öffnung","opening.edit":"Öffnung","opening.door":"Tür","opening.window":"Fenster","opening.gate":"Tor","opening.passage":"Offener Durchgang","opening.passage_binding_warning":"Das Speichern entfernt den Öffnungs-/Schließsensor und das Schloss.","opening.invalid_passage_fields":"Der offene Durchgang auf dem Plan „{room}“ hat nicht unterstützte Einstellungen: {fields}.","opening.type_label":"Typ","opening.length_label":"Länge, cm","opening.contact_label":"Öffnungs-/Schließsensor","opening.lock_label":"Schloss","opening.none":"— keine —","opening.search_ph":"Suche: Name oder Entitäts-ID…","opening.invert":"Geöffnet/geschlossen invertieren","opening.flip_h":"Scharnier an der anderen Zarge","opening.flip_v":"Öffnet zur anderen Seite","opening.open":"Offen","opening.closed":"Geschlossen","opening.locked":"Verriegelt","opening.unlocked":"Entriegelt","opening.state_unknown":"nicht verfügbar","opening.no_entities":"Keine Sensoren gebunden — ein statisches Symbol auf dem Plan.","toast.opening_no_wall":"Neben eine Raumwand oder eine unabhängige Wand klicken","opening.host_partition":"Unabhängige Wand","opening.partition_orphan":"Die unabhängige Wand für diese Öffnung existiert nicht mehr","opening.partition_jamb_margin":"Mindestens {distance} zwischen der Öffnung und dem Wandende lassen","opening.rebind_partition":"An eine andere unabhängige Wand anfügen","confirm.delete_partition_openings_title":"Wand und Öffnungen löschen?","confirm.delete_partition_openings_body":"Diese Wand enthält {count} Öffnung(en). Sie werden zusammen gelöscht.","confirm.delete_partition_openings_item":"• {type}, {length}","markup.hint_points":"Punkte: {n} · Shift — 45° Schritte · Esc — Kette beenden · Ctrl+Z — Punkt rückgängig machen · Schließen eines Bereichs erstellt einen Raum","markup.hint_start":"Klicken Sie auf einen Rasterpunkt, um eine Wandkette zu starten","tip.lqi":"durchschnittliches Zigbee-Signal:","tip.area":"Bereich: {value}","info.device_header":"Gerät im Plan","info.model":"Modell","info.state":"Status","info.link":"Verbindung","info.manuals":"Handbücher","info.none":"Keine zusätzlichen Informationen","marker.new_device":"Neues Gerät","marker.name_label":"Name (im Plan angezeigt)","marker.name_ph":"Name","marker.binding_label":"An ein HA-Gerät binden","marker.binding_disabled":"in Home Assistant deaktiviert","marker.virtual_option":"Virtuelles Gerät (keine Bindung)","marker.search_ph":"Gerät/Gruppe suchen…","marker.nothing_found":"Nichts gefunden","marker.room_label":"Raum","marker.room_override":" (Platzierung überschreiben)","marker.room_choose":"— Raum auswählen —","marker.room_auto":"— nach Gerätebereich (auto) —","marker.icon_label":"Symbol","marker.icon_ph":"mdi:… (leer = automatisch)","marker.display_label":"Anzeige","display.badge":"Symbol + Zustand","display.icon_ripple":"Symbol + Zustand und Aktivität","display.static_icon":"Immer statisches Symbol","marker.display_hint_badge":"Das Symbol und die dynamische Platte zeigen den Gerätezustand ohne den üblichen Aktivitätspuls. Rote Alarme bleiben sichtbar.","marker.display_hint_icon_ripple":"Das Symbol, die dynamische Platte und der Puls zeigen einen kurzen Puls für Ereignisse und einen kontinuierlichen Puls für Arbeit, Bewegung oder Anwesenheit. Rote Alarme haben eine separate Priorität.","marker.display_hint_value":"Ein ausgewählter oder automatisch ermittelter Home Assistant-Wert ersetzt das Symbol, während die Platte weiterhin den Zustand anzeigt. Rote Alarme bleiben sichtbar.","marker.display_hint_static_icon":"Die themenabhängige Hülle und das Symbol bleiben immer gleich. Zustand, Aktivität, Nichtverfügbarkeit und Alarme verändern nicht das Erscheinungsbild.","marker.static_alarm_warning":"Dieses Gerät kann Alarme melden. Die statische Anzeige verbirgt die visuelle Alarmanzeige des Markers.","marker.preview.title":"Anzeigevorschau","marker.preview.actual":"Jetzt","marker.preview.example":"Beispiel","marker.preview.integration":"Bereitgestellt von","marker.preview.source":"Anzeigquelle","marker.preview.current_state":"Aktueller Zustand","marker.preview.result":"Auf dem Plan","marker.preview.details":"Quelldetails","marker.preview.select_source":"Ein Home-Assistant-Gerät oder eine Entität auswählen, um die tatsächliche Anzeige zu sehen.","marker.preview.unknown_provider":"Unbekannte Integration","marker.preview.virtual_provider":"House Plan · virtuelles Gerät","marker.preview.no_source":"Keine aktive Quelle","marker.preview.no_state":"Kein aktueller Zustand","marker.preview.mixed_states":"Mehrere verschiedene Zustände","marker.preview.multiple_sources":"{n}-Quellen","marker.preview.more_sources":"+{n} mehr","marker.preview.scaled":"Die Vorschau wird auf {n}% skaliert, um zu passen. Die gespeicherte Größe bleibt unverändert.","marker.preview.demo_short":"Kurze Aktivität anzeigen","marker.preview.demo_continuous":"Kontinuierliche Aktivität anzeigen","marker.preview.stop_continuous":"Kontinuierliche Aktivität stoppen","marker.preview.demo_short_notice":"Kurzes Aktivitätsbeispiel; der tatsächliche Gerätezustand bleibt unverändert.","marker.preview.demo_continuous_notice":"Kontinuierliches Aktivitätsbeispiel; der tatsächliche Gerätezustand bleibt unverändert.","marker.preview.demo_already_visible":"Der aktuelle Zustand zeigt bereits eine echte Aktivitäts- oder Alarmeffekt.","marker.preview.reduced_motion":"Systemweit reduzierte Bewegungen sind aktiviert, daher wird gewöhnliche Aktivität als Punkt angezeigt.","marker.preview.reason.neutral":"Neutrale dunkle Platte","marker.preview.reason.working":"Gelbe Platte: Das Gerät arbeitet jetzt","marker.preview.reason.working_activity":"Gelbe Platte und Aktivitätseffekt: das Gerät funktioniert jetzt","marker.preview.reason.open":"Orange Platte: physisch geöffnet oder entriegelt","marker.preview.reason.cover_icon_state":"Neutrale Platte; die Abdeckungseinheit steuert den angezeigten Zustand und das Symbol","marker.preview.reason.presence":"Aktivitätseffekt, während Präsenz erkannt wird","marker.preview.reason.event":"Kurzer Aktivitätseffekt nach einem erkannten Ereignis","marker.preview.reason.transition":"Aktivitätseffekt, während das Gerät sich bewegt oder den Zustand ändert","marker.preview.reason.media_neutral":"Mediengeräte bleiben im verfügbaren Zustand auf einer neutralen dunklen Platte","marker.preview.reason.unavailable":"Gedämpfte neutrale Platte: nicht verfügbar oder ausgeschaltet","marker.preview.reason.alarm":"Rote Alarmplatte; Alarmanzeige wird immer angezeigt","marker.preview.reason.live_states_disabled":"Live-Zustandsstil ist für diese Karte deaktiviert","marker.preview.reason.value_no_state":"Kein nutzbarer Zustandswert; stattdessen wird das Symbol angezeigt","marker.preview.reason.value_ambiguous_sources":"Mehrere mögliche Wertequellen; stattdessen wird das Symbol angezeigt","marker.preview.reason.value_non_scalar":"Die Quelle lieferte keinen einfachen Wert; stattdessen wird das Symbol angezeigt","marker.preview.reason.value_virtual":"Ein virtuelles Gerät hat keinen Home Assistant-Wert; stattdessen wird das Symbol angezeigt","marker.preview.reason.vacuum_live_plan_only":"Echtzeitposition und -spur des Staubsaugers sind nur im vollständigen Plan verfügbar","marker.preview.reason.hidden_design_preview":"Das Gerät ist im Plan ausgeblendet; diese Designvorschau bleibt sichtbar","marker.preview.reason.composite_power_source":"Der Status stammt vom Power-Entity des Geräts; Hilfsschalter werden ignoriert","marker.preview.reason.activity_display_disabled":"Der gewählte Anzeigemodus zeigt gewöhnliche Aktivitätseffekte nicht an","marker.preview.reason.ha_disabled":"Die Home Assistant-Verbindung ist deaktiviert und wird im Plan ausgeblendet","marker.preview.reason.orphaned":"Die gespeicherte Home Assistant-Verbindung konnte nicht mehr gefunden werden","marker.preview.reason.static_icon":"Statischer Modus: Der Gerätestatus ändert das Symbol nicht","marker.activity_color":"Aktivitätspulsfarbe","marker.ripple_size":"Aktivitätspulsgröße","marker.activity_alarm_note":"Farbe und Größe betreffen nur gewöhnliche Aktivität und ändern keine roten Alarme.","marker.pulse_a11y_alarm":"Alarm","marker.pulse_a11y_event":"Kürzliches Ereignis","marker.pulse_a11y_presence":"Anwesenheit erkannt","marker.pulse_a11y_transition":"Statusänderung","marker.pulse_a11y_running":"Arbeitet","marker.state_a11y_neutral":"Standardzustand","marker.state_a11y_working":"Funktionierend","marker.state_a11y_open":"Offen","marker.state_a11y_locked":"Verschlossen","marker.state_a11y_unlocked":"Entriegelt","marker.state_a11y_alarm":"Alarm","marker.state_a11y_unavailable":"Nicht verfügbar","marker.lqi_a11y_low":"LQI {value}, schwaches Signal","marker.lqi_a11y_mid":"LQI {value}, mittleres Signal","marker.lqi_a11y_high":"LQI {value}, starkes Signal","marker.size_label":"Symbolgröße / Drehung","marker.angle_label":"Drehen","marker.model_label":"Modell","marker.model_ph":"z.B. Aqara T&H","marker.link_label":"Link","marker.desc_label":"Beschreibung","marker.desc_ph":"Notizen, Spezifikationen…","marker.manuals_label":"Handbücher (PDF usw.)","marker.sub_device":"Gerät","marker.sub_z2m_group":"· Z2M Gruppe","marker.sub_group":"Gruppe","marker.sub_helper":"Helfer","space.new":"Neuer Bereich","space.header":"Bereich","space.title_label":"Titel","space.title_ph":"z.B. Garage","space.plan_label":"Grundriss (Hintergrund)","space.no_plan":"Kein Planbild","space.plan_alt":"Grundriss","room.new":"Neuer Raum","room.name_label":"Anzeigename","room.name_ph":"z.B. Terrasse","room.area_label":"Home Assistant Bereich (nicht zugewiesen)","room.no_area_option":"— kein Bereich —","room.default_name":"Raum","device.unnamed":"unbenannt","device.light_group":"Lichtgruppe","device.fallback":"Gerät","device.virtual":"Virtuelles Gerät","confirm.delete_room_title":'Raum "{name}" löschen?',"confirm.delete_room_body":"Festlegen, ob die ausschließlich zu diesem Raum gehörenden physischen Wände erhalten bleiben. Mit einem anderen Raum geteilte Wände bleiben immer erhalten.","confirm.remove_marker_title":"Gerät aus dem Plan löschen?","confirm.remove_marker_body":"Das Gerät verschwindet vollständig und trägt nicht mehr zu den Plandaten bei. Es kann später erneut hinzugefügt werden.","confirm.erase_decor":"Das Objekt „{kind}“ löschen? Diese Aktion kann im Editor rückgängig gemacht werden.","confirm.delete_space_title":"Bereich löschen?","confirm.delete_space_body":"Der Bereich, alle seine Räume und die gesamte Planmarkierung werden gelöscht.","confirm.delete_space_vac_routes":"Zuordnungen von Roboterkarten werden ebenfalls entfernt: {count}.","space.delete_blocked":"Dieser Bereich wird noch von {n} Gerät(en) verwendet. Die Geräte zuerst in einen anderen Bereich verschieben oder löschen.","toast.pos_save_failed":"Position nicht gespeichert: {err}","toast.no_entity":"Das Gerät hat keine geeignete Entität","toast.ha_disabled_action":"Ein deaktiviertes Home Assistant-Objekt kann im Plan nicht verwendet werden.","toast.ha_disabled_show_device":"Ein in Home Assistant deaktiviertes Gerät kann im Plan nicht angezeigt werden. Aktivieren Sie es zuerst in Home Assistant.","toast.ha_disabled_show_entity":"Eine in Home Assistant deaktivierte Entität kann im Plan nicht angezeigt werden. Aktivieren Sie sie zuerst in Home Assistant.","toast.ha_disabled_add":"Ein deaktiviertes Home Assistant-Objekt kann nicht dem Plan hinzugefügt werden. Aktivieren Sie es zuerst in Home Assistant.","toast.ha_binding_unverified":"Der Status des Objekts konnte über das Home Assistant-Register nicht überprüft werden. Anzeige und Aktionen sind vorübergehend nicht verfügbar.","toast.markup_needs_server":"Markup ist verfügbar, nachdem die Konfiguration auf den Server verschoben wurde.","toast.space_order_changed":"Reihenfolge geändert. Wenn eine Karte ihr Stockwerk nach Nummer festlegt, überprüfen Sie diese Paneele.","toast.conflict":"Die Konfiguration wurde in einem anderen Fenster geändert — Daten aktualisiert, wiederholen Sie Ihre letzte Aktion.","toast.cfg_save_failed":"Speichern der Konfiguration fehlgeschlagen: {err}","toast.room_overlap":"Die Umrisse überlappen den Raum „{name}“ — Räume dürfen sich nicht überlappen","toast.contour_cannot_close":"Die Kontur kann nicht geschlossen werden, da sie entartet ist oder sich selbst schneidet","toast.merge_not_adjacent":"Es können nur Räume zusammengeführt werden, die eine Wand teilen","toast.rooms_merged":"Räume zu „{name}“ zusammengeführt","toast.split_pick_wall":"Beginnen Sie den Schnitt an der Wand des Raumes","toast.split_bad_cut":"Der Schnitt muss wand-zu-wand innerhalb des Raumes verlaufen, ohne Wände oder sich selbst zu kreuzen","merge.header":"Räume zusammenführen","merge.hint":"Der zusammengeführte Raum behält einen Namen und eine Fläche. Die andere Fläche wird freigegeben — ihre Geräte verlassen den Plan, bis ein anderer Raum sie beansprucht.","merge.keep":"Behalten","merge.no_area":"keine Fläche","toast.room_saved":"Raum gespeichert ({n}). Hinzugefügte Geräte: {added}. Zeichnen Sie die nächste Kontur oder verlassen Sie die Markierung.","toast.room_saved_no_area":"Raum gespeichert ({n}, keine Fläche). Zeichnen Sie die nächste Kontur oder verlassen Sie die Markierung.","toast.marker_needs_server":"Die Gerätebearbeitung ist verfügbar, nachdem die Konfiguration auf den Server verschoben wurde","toast.virtual_name_required":"Einen Namen für das virtuelle Gerät eingeben","toast.marker_saved":"Gerät gespeichert","toast.marker_removed":"Gerät aus dem Plan gelöscht","toast.integration_missing":"Die House Plan-Integration ist nicht installiert — Verwaltung nicht verfügbar","toast.plan_formats":"Unterstützte Formate: SVG, PNG, JPG, WebP","toast.plan_required":"Grundriss hochladen — erforderlich","toast.space_added_onboard":"Bereich hinzugefügt. Räume einzeichnen: Rasterpunkte anklicken und die Kontur schließen.","toast.space_added":"Bereich hinzugefügt","toast.space_saved":"Bereich gespeichert","toast.space_deleted":"Bereich gelöscht","toast.delete_failed":"Löschen fehlgeschlagen: {err}","toast.error":"Fehler: {err}","toast.toggle_target_unavailable":"Ziel „{name}“ ist nicht verfügbar — keine Aktion durchgeführt","toast.toggle_targets_unavailable":"Ziele nicht verfügbar: {names}. Keine Aktion durchgeführt","toast.file_failed":'Datei "{name}" wurde nicht hochgeladen: {err}',"toast.files_attached":"Dateien angehängt: {n}","err.unknown":"unbekannter Fehler","err.code":"Code {code}","err.too_large":"Datei größer als {mb} MB","err.bad_ext":"nicht unterstützter Typ (PDF/Bild erwartet)","err.unauthorized":"Administratorrechte erforderlich","editor.title":"Titel","editor.default_floor":"Anfangsbereich","editor.default_floor_missing":"Anfangsbereich „{id}“ existiert nicht mehr. Wählen Sie einen anderen Bereich.","editor.floor":"Fester Bereich","editor.floor_none":"— nicht fest —","editor.floor_index":"YAML-Index {index} (beibehalten)","fixed_floor.loading":"Lade den festen Bereich…","fixed_floor.invalid_title":"Der feste Bereich ist nicht verfügbar","fixed_floor.invalid_body":"Überprüfen Sie die Etage in der Kartenkonfiguration. Der konfigurierte Wert ist: {value}","editor.icon_size":"Symbolgröße, % der Planbreite","editor.show_temperature":"Temperatur anzeigen","editor.live_states":"Live-Zustände (ein/aus, offen…)","editor.light_pools":"Lichtkegel und Wandschatten","editor.show_signal":"Zigbee-Signal anzeigen (LQI)","editor.language":"Schnittstellensprache","editor.lang_auto":"Automatisch (HA-Profil)","title.icon_rules":"Symbolregeln: welche MDI-Symbole Geräte nach Namen erhalten","rules.title":"Symbolregeln","rules.hint":'Regeln werden von oben anhand von "Gerätename + Modell" (Großschreibungs-unempfindliches Regex) überprüft; das erste Match gewinnt. Wenn nichts übereinstimmt, entscheidet die Entität-Geräteklasse, dann das generische Chip-Symbol.',"rules.pattern_ph":"regex, z. B. Stecker|Steckdose","rules.icon_ph":"mdi:power-socket-de","rules.add":"Regel hinzufügen","rules.reset":"Zurücksetzen auf Standardeinstellungen","rules.test_ph":"Versuch mal einen Gerätenamen...","rules.invalid":"ungültiges regex","rules.saved":"Icon-Regeln gespeichert","btn.up":"Nach oben","btn.down":"Nach unten","tap.info":"Gerätekarte","tap.more_info":"HA Mehr-Info-Dialog","tap.toggle":"Zustand umschalten","marker.tap_label":"Tap-Aktion für dieses Gerät","tap.toggle_note":"Der aufgelöste Zustand ist unten dargestellt. Sichere Geräte werden niemals aus dem Plan umgeschaltet.","import.title":"Bereiche aus HA-Etagen erstellen","import.hint":"Home Assistant kennt diese Etagen bereits. Die Etagen auswählen, die zu Planbereichen werden sollen; anschließend für jeden Bereich einen Grundriss hochladen. Die Räume werden danach von Hand eingezeichnet.","import.start":"{n} Bereich(e) erstellen","import.manual":"Von Grund auf neu starten","import.progress":"Etage {i} von {n}","import.done":"Bereiche erstellt. Räume einzeichnen: Rasterpunkte anklicken und die Kontur schließen.","btn.skip":"Überspringen","space.scale_label":"Maßstab (Rasterzellen-Größe)","space.cell_cm.help":"Verknüpft das Raster mit realen Abmessungen: Davon hängen Längen und Flächen, Wandstärken, Öffnungsgrößen und der Leuchtradius ab. Eine spätere Änderung verändert die berechneten Abmessungen des gesamten Bereichs, verschiebt aber keine Punkte im Plan.","space.cell_cm.help.aria":"Hilfe: Maßstab des Bereichs","space.scale_unit":"cm pro Zelle","space.scale_unit_imperial":"Zoll pro Zelle","space.display_section":"Anzeige","space.show_borders":"Raumgrenzen immer anzeigen","space.zero_wall_style":"Wände ohne Dicke","space.zero_wall_style.help":"Gestrichelte Wände ohne Dicke lassen Glow und Sonnenstrahlen durch, durchgezogene blockieren sie als Barriere ohne Fläche. Die Auswahl gilt für alle solchen Wände im Bereich, auch wenn ihre Linie in der Ansicht ausgeblendet ist.","space.zero_wall_style.help.aria":"Hilfe: Darstellung der Wände ohne Dicke","space.zero_wall_dashed":"Gestrichelt","space.zero_wall_solid":"Durchgezogen","space.show_names":"Raumnamen anzeigen (zum Verschieben ziehen)","space.room_color":"Farbe der Begrenzung & des Namens","space.opacity":"Deckkraft","space.fill_label":"Raumausfüllung","space.fill_mode.help":"„Eigene Farbe“ gestaltet den Bereich; „Licht“, „Temperatur“ und „LQI“ verwenden aktuelle Daten aus Home Assistant. Glow wird separat aktiviert.","space.fill_mode.help.aria":"Hilfe: Modus der Raumausfüllung","fill.none":"Keine","fill.lqi":"Zigbee-Signal","fill.light":"Lichter","fill.custom":"Benutzerdefinierte Farbe","space.custom_fill":"Füllfarbe","space.source_file":"Ich habe einen Grundriss als Bild","space.source_draw":"Kein Bild – ich werde die Räume von Hand umreißen","fill.temp":"Temperatur","tip.temp_avg":"Durchschnittstemperatur:","tip.hum_avg":"Durchschnittliche Luftfeuchtigkeit:","space_card.button":"Grundriss öffnen","space_card.not_found":"Bereich „{id}“ nicht gefunden","space_card.loading":"Laden…","continuity.restore_plan":"Grundriss wiederherstellen…","continuity.restore_connection":"Geräteverbindung wiederherstellen…","continuity.retry":"Erneut versuchen","editor.space":"Bereich","editor.framing":"Bildausschnitt","editor.fit_content":"Alle sichtbaren Inhalte","editor.fit_house":"Eng an der Hausgeometrie","editor.show_button":"Schaltfläche anzeigen","editor.button_label":"Beschriftung der Schaltfläche","editor.button_target":"Ziel-Dashboard-Pfad","marker.sub_entity":"Entität","title.general_settings":"Allgemeine Einstellungen","gs.title":"Allgemeine Einstellungen","gs.light_group":"Füllung: Licht","gs.light_on":"Lichter an","gs.light_off":"Alle Lichter aus","gs.temp_group":"Füllung: Temperatur","gs.temp_cold":"Kalt","gs.temp_ok":"Angenehm","gs.temp_hot":"Heiß","gs.lqi_group":"Füllung: Zigbee-Signal","gs.lqi_low":"Schwaches Signal","gs.lqi_high":"Starkes Signal","gs.reset":"Auf Standard zurücksetzen","gs.saved":"Allgemeine Einstellungen gespeichert","space.show_lqi":"Zigbee-Signal (LQI) neben Geräten anzeigen","space.hide_decor":"Dekorationsschicht ausblenden","space.hide_decor_tip":"Linien, Formen, Beschriftungen und Möbel bleiben an ihrem Platz — im Hintergrundeditor sichtbar, aber nicht auf dem Plan.","space.hide_openings":"Öffnungen ausblenden","space.hide_openings_tip":"Tür-, Fenster- und Tor-Symbole werden nicht gezeichnet, aber die Öffnungen funktionieren weiterhin: Licht fällt hindurch, die Sonne kommt durch ein Fenster herein, Kontaktsensoren öffnen sie weiterhin. Der Planeditor zeigt sie immer an.","gs.light_none":"Keine Lichtquellen","mode.plan":"Planeditor","mode.devices":"Geräteeditor","display.value":"Wert + Zustand","marker.subarea":"kein Bereich, manuell","device.new":"Neues Gerät — Editor öffnen, um zu schließen","opening.unlock_action":"Entsperren","opening.lock_action":"Sperren","opening.lock_pending":"Wird ausgeführt…","title.close_editor":"Editor schließen (zur Ansicht zurück)","title.add_device":"Gerät zum Plan hinzufügen","devbar.add":"Hinzufügen","devbar.rules":"Symbolregeln","device_inbox.button":"Geräte","device_inbox.title":"Geräte auf dem Plan","device_inbox.search":"Geräte, Entitäten und Integrationen suchen…","device_inbox.add_virtual":"Virtuelles Gerät hinzufügen","device_inbox.tab_on_plan":"Auf Plan","device_inbox.tab_available":"Verfügbar","device_inbox.tab_hidden":"Versteckt","device_inbox.tab_readd":"Wieder verfügbar","device_inbox.only_new":"Nur neu","device_inbox.show_entities":"Entitäten anzeigen","device_inbox.show_hidden":"Versteckte auf Plan anzeigen","device_inbox.show_hidden.help":"Zeigt ausgeblendete und deaktivierte Marker vorübergehend als Bearbeitungs-Geister auf dem Plan. Die gespeicherte Sichtbarkeit der Geräte bleibt unverändert.","device_inbox.show_hidden.help.aria":"Hilfe: ausgeblendete Geräte auf dem Plan anzeigen","device_inbox.new":"Neu","device_inbox.find":"Auf dem Plan finden","device_inbox.edit":"Bearbeiten","device_inbox.hide":"Ausblenden","device_inbox.show":"Anzeigen","device_inbox.add":"Hinzufügen","device_inbox.readd":"Wieder hinzufügen","device_inbox.hide_available":"Aus der Liste ausblenden","device_inbox.show_more":"Mehr anzeigen","device_inbox.more_actions":"Weitere Aktionen","device_inbox.find_hidden_hint":"Zuerst „Versteckte auf Plan anzeigen“ aktivieren","device_inbox.show_disabled":"Diese Bindung in Home Assistant aktivieren, bevor sie angezeigt wird","device_inbox.empty_on_plan":"Es befinden sich noch keine passenden Geräte auf dem Plan.","device_inbox.empty_available":"Es sind keine Geräte zum Hinzufügen verfügbar.","device_inbox.empty_hidden":"Es gibt keine versteckten Geräte.","device_inbox.empty_readd":"Es sind keine entfernten Geräte verfügbar, um sie erneut hinzuzufügen.","device_inbox.reason_visible_auto":"Automatisch erkannt","device_inbox.reason_visible_explicit":"Explizit hinzugefügt","device_inbox.reason_manual_hidden":"Vom Benutzer versteckt","device_inbox.reason_automatic_hidden":"Automatisch versteckt","device_inbox.reason_service_entry":"Nur Service-Registry-Eintrag","device_inbox.reason_excluded_integration":"Integration „{integration}“ durch Erkennungsfilter ausgeschlossen","device_inbox.reason_excluded_domain":"Nicht-räumlicher Entitätstyp","device_inbox.reason_grouped_light":"Dargestellt durch eine Raumlichtgruppe","device_inbox.reason_represented_by_parent":"Dargestellt durch sein übergeordnetes Gerät","device_inbox.reason_removed":"Zuvor aus dem Plan entfernt","device_inbox.reason_available":"Zum Hinzufügen zum Plan verfügbar","device_inbox.reason_no_bound_room":"HA-Bereich ist nicht mit einem Planraum verknüpft","device_inbox.status_ha_disabled":"In Home Assistant deaktiviert","device_inbox.status_orphaned":"Bindung ist in Home Assistant nicht mehr vorhanden","device_inbox.status_unverified":"Home Assistant-Register vorübergehend nicht verfügbar","device_inbox.saved":"Geräteliste aktualisiert","device_inbox.filters_excluded":"Ausgeschlossene Integrationen","device_inbox.filters_group_lights":"Raumleuchten zu einem Marker gruppieren","device_inbox.filters_preview_appear":"erscheint: {count}","device_inbox.filters_preview_hide":"verschwindet: {count}","device_inbox.filters_preview_lights":"betroffene Leuchten: {count}","device_inbox.filters_reset":"Empfohlene wiederherstellen","device_inbox.filters_save":"Filter speichern","device_inbox.filters_search_ph":"Integration hinzufügen…","device_inbox.filters_title":"Erkennungsfilter","space.roomcard_section":"Raumkarte zeigt:","space.label_temp":"Temperatur","space.label_hum":"Luftfeuchtigkeit","space.label_lqi":"Durchschnittliches Zigbee-Signal","space.label_light":"Lichter ein/aus","roomcard.light_on":"Ein","roomcard.light_off":"Aus","roomcard.light_partial":"{on} von {total}","toast.split_pick_inside":"Zwischenliegende Schnittpunkte müssen innerhalb des Raumes liegen","mode.decor":"Hintergrundeditor","decor.select":"Auswählen","decor.line":"Linie","decor.rect":"Rechteck","decor.ellipse":"Oval","decor.text":"Text","decor.erase":"Löschen","decor.erase_confirm_title":"Objekt löschen?","decor.color":"Farbe","decor.width":"Linienbreite","decor.line_style":"Linienstil","decor.line_style_solid":"Durchgehend","decor.line_style_dashed":"Gepunktet","decor.fill":"Füllen","decor.fill_color":"Füllfarbe","decor.length":"Länge","decor.size":"Größe","decor.flip_h":"Horizontal spiegeln","decor.flip_v":"Vertikal spiegeln","decor.angle":"Rotationswinkel, °","decor.text_size":"Textgröße","decor.backdrop_properties":"Eigenschaften des Planhintergrunds","decor.text_title":"Textbeschriftung","decor.object_title":"{kind} bearbeiten","decor.text_label":"Text","decor.live_group":"HA-Variable einfügen","decor.live_entity":"Entität","decor.live_entity_ph":"Wählen Sie eine Entität","decor.live_attr":"Wert","decor.live_attr_ph":"Wählen Sie Status oder Attribut","decor.live_state":"Status","decor.backdrop":"Hintergrundbild","decor.backdrop_hint":"Ziehen zum Verschieben; eine Ecke ziehen zum Größenändern; den oberen Griff zum Drehen verwenden. Shift ändert das Verhältnis oder befreit den Winkel.","decor.backdrop_reset":"Bild zurücksetzen","decor.backdrop_reset_done":"Das Bild ist wieder an seinem ursprünglichen Platz und in seiner ursprünglichen Größe","marker.icon_auto":"Auto: {icon} (nach Symbolregeln; wählen Sie eines zur Überschreibung)","marker.icon_pin_auto":"Anheften","mode.plan_tip":"Planungseditor — die Geometrie des Hauses: Räume zeichnen und teilen/zusammenführen, sie mit HA-Bereichen verbinden, Türen, Fenster und Tore platzieren, Raumkarten verschieben, Maßstab festlegen","mode.devices_tip":"Geräteeditor — alles über Symbole: ziehen zum Positionieren, klicken zum Bearbeiten von Bindung/Symbol/Anzeige, virtuelle Geräte hinzufügen, Symbolregeln","mode.decor_tip":"Hintergrundeditor — rein visuelle Dekoration unter dem Plan: Linien, Rechtecke, Ellipsen und Textbeschriftungen, die niemals auf Klicks reagieren","space.glow_enabled":"Lichtquellen-Glühen","gs.glow_group":"Glow von Lichtquellen","gs.glow_base":"Grunddunkelheit des Hauses","gs.glow_light":"Standardlichtfarbe / Intensität","gs.wall_group":"Wände","gs.wall_fill":"Wandfüllung","gs.glow_radius":"Glow-Radius","gs.glow_radius.help":"Legt den allgemeinen Radius des Lichtscheins in Metern oder Fuß fest; ein gerätespezifischer Radius überschreibt diesen Wert.","gs.glow_radius.help.aria":"Hilfe: allgemeiner Glow-Radius","gs.unit_m":"m","gs.unit_ft":"ft","marker.controls_label":"Steuert andere Lichtquellen","marker.controls.help":"Mit der Aktion „Zustand umschalten“ werden die aufgeführten Quellen zusammen mit diesem Marker umgeschaltet. Ihr Glow bleibt an ihren eigenen Markern, und die Verknüpfung allein macht den steuernden Marker nicht zur Lichtquelle.","marker.controls.help.aria":"Hilfe: andere Lichtquellen steuern","marker.controls_filter":"Suchlichter und Schalter…","info.controls":"Steuerungen","marker.glow_radius_label":"Leuchtradius","marker.glow_radius.help":"Legt den Leuchtradius in Metern oder Fuß fest; ein leerer Wert verwendet den Radius aus den allgemeinen Einstellungen.","marker.glow_radius.help.aria":"Hilfe: Leuchtradius","markup.wallthick":"Dicke","markup.select":"Auswählen","title.markup_wallthick":"Dicke — klicken Sie auf eine Wand, um ihre Dicke von 0 bis 100 cm festzulegen.","markup.hint_wallthick":"klicken Sie auf eine Wand · Esc schließt ohne Anwendung","wallthick.field":"Dicke","wallthick.unit_cm":"cm","wallthick.unit_in":"in","wallthick.apply_room":"Auf alle Wände dieses Raums anwenden","markup.draw_wall_title":"Dicke jedes neuen Wandsegments (0–100 cm). Gemeinsame Wände behalten den bestehenden Wert.","room.queue_progress":"Raum {current} von {total}","toast.wall_rooms_saved":"Erstellte Räume: {n}","toast.wall_chain_saved":"Wandkette gespeichert","toast.wallthick_pick":"Eine Wand anklicken","toast.wallthick_set":"Wandstärke eingestellt","toast.wallthick_cleared":"Wandstärke entfernt","toast.physical_range":"Einen Wert von {min} bis {max} {unit} eingeben","toast.zero_wall_opening_conflict":"Entfernen Sie zuerst die Öffnung an diesem Wandsegment.","toast.zero_wall_ambiguous":"Das Wandsegment ist mehrdeutig. Vereinfachen oder passen Sie den Anschluss an.","toast.zero_wall_migration_blocked":"Der Bereich wurde nicht konvertiert: {reason}. Es wurden keine Daten geändert.","toast.physical_angle":"Einen Drehwinkel von 0° bis unter 90° eingeben","toast.physical_limit":"Der Bereich hat das Limit für diesen Geometrietyp erreicht","toast.geometry_unsafe":"Änderung abgebrochen: Wandgeometrie konnte nicht sicher erstellt werden.","junction.limit_angle":"Der Winkel zwischen den Wänden ist zu spitz: {actual}°, mindestens {limit}°.","junction.limit_valence":"Zu viele Wände treffen in einem Knoten aufeinander: {actual}, maximal {limit}.","junction.limit_length":"Das Wandsegment ist zu kurz: {actual} cm, mindestens {limit} cm.","junction.limit_distance":"Wände und Knoten sind zu dicht beieinander: {actual} cm, Minimum {limit} cm.","junction.limit_clearance":"Kein Wohnbereich ist übrig: {actual} cm², Minimum {limit} cm².","junction.limit_check_failed":"Die Überprüfung der Verbindungen konnte nicht durchgeführt werden — die Änderung wurde nicht gespeichert.","toast.wall_model_migration_blocked":"Das Wandmodell konnte nicht aktualisiert werden: {reason}. Der Plan wurde nicht geändert. Führen Sie „Pläne optimieren“ aus; wenn der Fehler erneut auftritt, beheben Sie die widersprüchliche Wandgeometrie.","toast.wall_model_client_outdated":"Aktualisieren Sie die Karte und laden Sie die Seite neu, bevor Sie den Plan bearbeiten.","wall_model.reason.invalid-room":"ungültiger Raumkontur","wall_model.reason.zero-length":"Wandsegment mit null Länge","wall_model.reason.third-owner":"Wand, die von mehr als zwei Räumen geteilt wird","wall_model.reason.duplicate-id":"widersprüchliche Wandkennungen","wall_model.reason.thickness-conflict":"widersprüchliche Wandstärkenwerte","wall_model.reason.opening-host":"Öffnung kann nicht einer Wand zugewiesen werden","toast.delete_room_pick":"Klicken Sie in den Raum, den Sie löschen möchten","toast.plan_snap_ambiguous":"Zoomen Sie hinein, um den Wandknoten auszuwählen","toast.wall_repair_ambiguous":"Der Raumumriss hat mehr als eine mögliche Verbindung. Zoomen Sie hinein und verbinden Sie ihn explizit.","toast.wall_repair_too_large":"Die Lücke ist größer als 2 cm. Verbinden Sie die Wände, bevor Sie den Raum erstellen.","toast.wall_repair_changed":"Die Wandgeometrie hat sich geändert. Versuchen Sie erneut, den Raum zu erstellen.","toast.opening_on_zero_wall":"Öffnungen können nicht auf einer Wand mit null Dicke sitzen.","marker.from_ha_option":"Wählen Sie aus der HA-Liste.","marker.show_entities":"Entitäten anzeigen.","marker.show_entities_tip":"Fügt nicht nur Geräte zur Liste hinzu, sondern auch alle ihre Entitäten.","marker.pick_ph":"Wählen Sie ein Gerät…","room.open_area":"Öffnen Sie den HA-Bereich.","view.volumetric":"Volumetrische Ansicht.","view.flat":"Flache Ansicht.","kiosk.title":"Die Größen dieses Bildschirms.","kiosk.hint":"Nur auf diesem Gerät gespeichert – jedes Wandtablet oder TV kann seine eigenen komfortablen Größen haben.","kiosk.icon_scale":"Gerätesymbolgröße.","kiosk.font_scale":"Textgröße der Raumkarte.","editor.kiosk":"Wandgeräte- (Kiosk-)Modus.","editor.cycle":"Bereiche automatisch alle N Sekunden wechseln (Kiosk, 0 = aus)","room.settings_title":"Raumeinstellungen.","room.settings_section":"Raumeinstellungen (überschreibt den Bereich)","room.fill_label":"Diesen Raum ausfüllen","fill.inherit":"Als den Bereich","room.custom_fill_space":"Bereichsfarbe","room.custom_fill_own":"Raumfarbe","room.temp_src_label":"Temperaturquelle","room.hum_src_label":"Luftfeuchtigkeitsquelle","room.src_average":"Durchschnitt über die Sensoren des Raums (Standard)","room.src_pick":"Ein bestimmtes HA-Gerät oder Entität","room.src_ph":"Quelle wählen…","toast.room_updated":"Raum aktualisiert","space.card_font":"Schriftgröße der Raumkarte (gesamter Bereich)","room.sizes_section":"Schriftgrößen","room.name_scale":"Raumname Größe","room.label_scale":"Metrikgröße","preview.room_name":"Wohnzimmer","toast.cfg_reload_failed":"Der Plan konnte nicht vom Server neu geladen werden: {err}","toast.locale_load_failed":"Das Sprachpaket konnte nicht geladen werden. Bis zum Neuladen der Seite wird Englisch verwendet.","room.settings_short":"Raumeinstellungen","room.unnamed":"Unbenannter Raum","marker.use_climate_temp":"Geräte-Temperatur im Raum berücksichtigen","marker.use_climate_temp_tip":"Fügt die aktuelle Temperatur einer Klimaanlage oder eines Thermostats zum Raumdurchschnitt hinzu. Das externe Wert-Label unten separat konfigurieren.","marker.value_badge_title":"Wert-Label","marker.value_badge.help":"Zeigt einen ausgewählten Wert neben dem Symbol an. Dies beeinflusst nicht die Raumkennzahlen, Licht, Glanz oder die Tippaktion.","marker.value_badge.help.aria":"Hilfe: Gerätewert-Badge","marker.value_badge_enabled":"Zeige ein Wert-Badge","marker.value_badge_source":"Wert","marker.value_badge_source.help":"Wählen Sie einen bestimmten Zustand, ein unterstütztes Attribut oder einen abgeleiteten Wert dieses Geräts.","marker.value_badge_source.help.aria":"Hilfe: Quelle des Wert-Badges","marker.value_badge_position":"Position","marker.value_badge_position.help":"Die gewählte Seite bleibt fest und dreht sich nicht automatisch an einem Planrand.","marker.value_badge_position.help.aria":"Hilfe: Position des Wert-Badges","marker.value_badge_right":"Rechts","marker.value_badge_bottom":"Unten","marker.value_badge_left":"Links","marker.value_badge_top":"Oben","marker.value_badge_empty":"Für dieses Gerät stehen keine Werte zur Verfügung","marker.value_badge_static":"Ein statisches Symbol zeigt keine Live-Werte an. Die Einstellung wird beibehalten.","marker.value_badge_missing":"Quelle nicht verfügbar","marker.value_badge_missing_hint":"Die gespeicherte Quelle ist derzeit nicht verfügbar. Behalten Sie sie bei, deaktivieren Sie das Badge oder wählen Sie einen anderen Wert.","marker.value_badge_duplicate":"Derselbe Wert wird bereits im Symbol angezeigt.","marker.value_badge_state":"Status · {name}","marker.value_badge_marker_state":"Lichtquellstatus · {name}","marker.value_badge_lqi":"Durchschnittliche Zigbee-Signalqualität","marker.value_badge_attr_current_temperature":"Aktuelle Temperatur · {name}","marker.value_badge_attr_temperature":"Zieltemperatur · {name}","marker.value_badge_attr_current_humidity":"Aktuelle Luftfeuchtigkeit · {name}","marker.value_badge_attr_humidity":"Luftfeuchtigkeit · {name}","marker.value_badge_attr_current_position":"Position · {name}","marker.value_badge_attr_percentage":"Geschwindigkeit · {name}","marker.value_badge_attr_brightness":"Helligkeit · {name}","marker.value_badge_attr_volume_level":"Lautstärke · {name}","marker.value_badge_attr_battery_level":"Batterie · {name}","marker.value_badge_attr_fan_speed":"Lüftergeschwindigkeit · {name}","marker.value_source":"Wertquelle","marker.value_source.help":"Wähle den Wert, der das Symbol ersetzt. Die Tipp-Aktion bleibt unverändert.","marker.value_source.help.aria":"Hilfe: Wertquelle in der Gerätefläche","marker.value_source_auto":"Automatisch (wie bisher)","marker.value_source_missing_hint":"Die gespeicherte Quelle ist derzeit nicht verfügbar. Bis sie wieder verfügbar ist oder ein anderer Wert gewählt wird, zeigt die Fläche —.","marker.light_role_label":"Ist dieses Gerät eine Lichtquelle?","marker.light_role.help":"„Auto“ verwendet die ermittelte Rolle des verknüpften Geräts, „Immer“ erzwingt eine eigene Quelle und „Nie“ schließt sie aus; oben verknüpfte Lichter bleiben unabhängig.","marker.light_role.help.aria":"Hilfe: ob dieses Gerät eine Lichtquelle ist","marker.light_role_auto_yes":"Automatisch (Lichtquelle)","marker.light_role_auto_no":"Automatisch (keine Lichtquelle)","marker.light_role_always":"Immer eine Lichtquelle","marker.light_role_never":"Nie eine Lichtquelle","marker.light_entity_label":"Führende Lichtereinheit","marker.light_entity.help":"Für ein Verbundgerät wählen Sie die Entität, deren Zustand, Farbe und Helligkeit diese Planquelle darstellen. Der automatische Rückgriff bleibt mit älteren Plänen kompatibel.","marker.light_entity.help.aria":"Hilfe: führende Lichtentität","marker.light_entity_auto":"Automatisch ({entity})","marker.light_entity_none":"keine steuerbare Entität","marker.light_entity_missing":"Die gespeicherte Entität {entity} ist nicht verfügbar. House Plan verwendet vorübergehend {fallback}; die gespeicherte Auswahl wird wiederhergestellt, wenn sie zurückkehrt.","marker.toggle_entity_label":"Zu toggelnde Entität","marker.toggle_entity.help":"Für ein Verbundgerät wählen Sie das genaue eigene Licht oder den Schalter, der durch Tippen bedient wird. Automatisch behält die vorherigen Zielregeln bei und ist unabhängig von der führenden Lichtentität.","marker.toggle_entity.help.aria":"Hilfe: zu toggelnde Entität","marker.toggle_entity_auto":"Automatisch ({entity})","marker.toggle_entity_none":"keine eigene steuerbare Entität","marker.toggle_entity_missing":"Die gespeicherte Entität {entity} ist nicht mehr unter den auswählbaren Kanälen dieses Markers. House Plan verwendet vorübergehend {fallback}; die gespeicherte Auswahl wird wiederhergestellt, wenn sie zurückkehrt.","marker.glow_color_label":"Leuchtfarbe und Helligkeit","marker.glow_mode.help":"Verwenden Sie Live-Quellwerte, überschreiben Sie nur deren Farbe oder fixieren Sie sowohl Farbe als auch Helligkeit. Das Minimum beträgt 1 %; um die Quelle zu deaktivieren, wählen Sie „Nie“.","marker.glow_mode.help.aria":"Hilfe: Leuchtfarbe und Helligkeit","marker.glow_mode_auto":"Von Quelle","marker.glow_mode_color":"Farbe einstellen","marker.glow_mode_fixed":"Farbe und Helligkeit einstellen","marker.glow_color":"Leuchtfarbe","marker.glow_brightness":"Helligkeit","marker.glow_disabled_never":"Leuchteinstellungen sind nicht verfügbar, da dieser Marker ausdrücklich keine Lichtquelle ist.","marker.glow_disabled_auto":"Im Automatikmodus wurde keine räumliche Lichtquelle für diesen Marker gefunden.","marker.glow_disabled_no_entity":"Keine aktive steuerbare Home Assistant-Entität ist für diese räumliche Quelle verfügbar.","marker.glow_passive_hint":"Diese Quelle hat keine eigenen Home Assistant-Daten. Stellen Sie ihre Farbe und Helligkeit manuell ein; ihr Radius bleibt verfügbar.","marker.control_broken":"Gespeicherte Quelle fehlt oder ist nicht mehr als Licht markiert","marker.control_missing_label":"Fehlendes Planlicht","marker.control_passive":"passive Quelle","toast.marker_control_cycle":"Dieser Link würde eine kreisförmige Kette von Lichtsteuerungen erzeugen.","toast.marker_binding_required":"Wählen Sie ein Home Assistant-Gerät, bevor Sie eine andere Lichtquelle verlinken.","confirm.unlock_title":"Schloss öffnen?","confirm.unlock_body":"House Plan sendet einen Befehl zum Öffnen an dieses Schloss.","toast.files_migrate_failed":"Anhänge konnten nicht zur neuen Bindung verschoben werden, Links zeigen weiterhin auf die alten Dateien: {err}","space.pick_saved":"Bereits hochgeladen","space.pick_saved_hint":"Auf dem Server gespeicherte Pläne, einschließlich solcher, die Sie zuvor getrennt haben","space.no_saved":"Noch keine Pläne auf dem Server gespeichert.","space.loading":"Laden…","space.used_by":"in Benutzung: {list}","space.in_use":"Ein Bereich verwendet diesen Plan noch — zuerst die Verknüpfung lösen","btn.use":"Verwenden","confirm.delete_plan_title":"Plandatei löschen?","confirm.delete_plan_body":"Die Datei wird vom Server gelöscht. Dieser Vorgang kann nicht rückgängig gemacht werden.","toast.plans_list_failed":"Konnte die gespeicherten Pläne nicht auflisten: {err}","toast.plan_delete_failed":"Konnte den Plan nicht löschen: {err}","marker.hide":"Ausblenden","marker.hide_tip":'Das Gerät wird nach dem Speichern aus dem Plan verschwinden, aber weiterhin zum Signalsignal des Raums zählen. Stellen Sie es über den Katalog "Geräte" im Geräte-Editor wieder her.',"marker.show":"Anzeigen","marker.show_tip":"Das Gerät wird nach dem Speichern wieder im Plan erscheinen.","marker.hidden_ghost":"Vom Benutzer ausgeblendetes Gerät","marker.ha_disabled_device":"Das Gerät ist in Home Assistant deaktiviert und im Plan ausgeblendet.","marker.ha_disabled_entity":"Die Entität ist in Home Assistant deaktiviert und im Plan ausgeblendet.","marker.ha_disabled_all_entities":"Das Gerät hat keine aktiven Home Assistant-Entitäten, daher ist es im Plan ausgeblendet.","marker.ha_registry_limited":"Das vollständige Home Assistant-Register ist für diesen Benutzer nicht verfügbar. Das nicht verifizierte Objekt kann vorerst nicht angezeigt oder verwendet werden.","marker.delete_tip":"Löschen Sie das Gerät vollständig aus dem Plan und allen Aggregaten. Sie können es später wieder hinzufügen.","tap.run":"Führen Sie Automation/Skript/Szene aus","tap.none":"Nichts tun","marker.run_target_label":"Was ausführen","marker.run_search_ph":"Suchen: Automation, Skript oder Szene…","marker.run_target_gone":"Ziel {id} nicht gefunden — erneut auswählen","marker.tap_confirm":"Um Bestätigung bitten","marker.tap_confirm_tip":"Vor der Ausführung ein Bestätigungsdialogfeld anzeigen — eine Vorsichtsmaßnahme gegen versehentliche Berührungen.","marker.toggle_hint_single":"Ziel: {name} ({id}).","marker.virtual_light_target":"Virtuelles Licht: {name}.","marker.virtual_light_current":"Manueller Zustand: {state} → {effect}.","marker.virtual_light_state_on":"ein","marker.virtual_light_state_off":"aus","marker.toggle_hint_group":"Wird {count}-Quelle(n) umschalten: {names}.","marker.toggle_hint_current":"Jetzt: {state} → {effect}.","marker.toggle_hint_group_current":"Derzeit an: {on} von {count} → {effect}.","marker.toggle_hint_skipped":"Wird übersprungen ({count}): {targets}.","marker.toggle_effect_turn_on":"wird eingeschaltet","marker.toggle_effect_turn_off":"wird ausgeschaltet","marker.toggle_effect_open":"wird geöffnet","marker.toggle_effect_close":"wird geschlossen","marker.toggle_effect_stop":"wird gestoppt","marker.toggle_effect_toggle":"Zustand wird umgeschaltet","marker.toggle_skip_missing":"nicht gefunden","marker.toggle_skip_ha_disabled":"in HA deaktiviert","marker.toggle_skip_unavailable":"nicht verfügbar","marker.toggle_skip_unsupported":"Umschalten wird nicht unterstützt","marker.toggle_skip_secure":"aus Sicherheitsgründen blockiert","marker.toggle_none_no_binding":"Dieses Gerät hat keine Bindung, daher gibt es keinen Zustand, der umgeschaltet werden könnte. Tippen bewirkt nichts.","marker.toggle_none_no_actionable_entity":"Dieses Gerät hat keinen Zustand, der umgeschaltet werden könnte. Tippen bewirkt nichts.","marker.toggle_none_configured_targets_missing":"Die konfigurierten Ziele sind nicht verfügbar. Die eigene Entität des Geräts wird nicht ersetzt.","marker.toggle_none_ha_disabled":"Das Ziel ist in Home Assistant deaktiviert und kann im Plan nicht verwendet werden.","marker.toggle_none_unavailable":"Das Ziel ist derzeit nicht verfügbar. Tippen bewirkt nichts.","marker.toggle_none_unsupported":"Home Assistant bietet keine sichere Umschaltfunktion für dieses Gerät. Tippen bewirkt nichts.","marker.toggle_none_secure":"Das Umschalten von Schlössern, Alarmen und gesicherten Toren über den Plan ist aus Sicherheitsgründen gesperrt.","run.automation":"Automatisierung","run.script":"Skript","run.scene":"Szene","confirm.tap_run":'"{name}" ausführen?',"confirm.tap_toggle":'"{name}" umschalten?',"confirm.current_state":"Aktueller Zustand: {state}","confirm.expected_state":"Nach dem Umschalten: {state}","confirm.group_current":"an {on} von {total}","confirm.group_all_on":"alle sind eingeschaltet","confirm.group_all_off":"alle sind ausgeschaltet","confirm.unavailable_targets":"Nicht verfügbar: {count}","confirm.expected_by_ha":"Home Assistant ermittelt den Zustand","confirm.state_on":"Ein","confirm.state_off":"Aus","confirm.state_open":"Offen","confirm.state_closed":"Geschlossen","confirm.state_opening":"Wird geöffnet","confirm.state_closing":"Wird geschlossen","confirm.state_stopped":"Gestoppt","confirm.state_unknown":"Unbekannt","toast.run_started":"Gestartet: {name}","toast.run_target_missing":"Ausführungsziel nicht gefunden — überprüfen Sie die Geräteeinstellungen","toast.run_target_required":"Wählen Sie eine Automatisierung, ein Skript oder eine Szene aus","toast.tap_target_changed":"Das Ziel der Aktion hat sich geändert. Versuchen Sie es erneut.","toast.virtual_light_toggle_failed":"Das virtuelle Licht konnte nicht umgeschaltet werden: {err}","toast.value_badge_source_required":"Einen Wert für den Badge auswählen","btn.run":"Ausführen","vac.section":"Roboterstaubsauger: aktuelle Position","vac.autocal":"Automatisch einrichten","vac.live":"Aktuelle Position im Plan","vac.trail":"Roboterpfad anzeigen","vac.autocal_no_rooms":'Die Integration meldet keine Raumliste — öffnen Sie "Manuell anpassen"',"vac.route_warn_unmapped":"Der Roboter reinigt eine Karte, die keiner Etage zugeordnet ist","vac.route_warn_needs_calibration":"Die Karte ist einer Etage zugeordnet, aber nicht kalibriert","vac.route_warn_ambiguous":"Zwei Karten sind nicht unterscheidbar — keine Etage gewählt","vac.route_warn_missing_space":"Der Raum dieser Karte wurde gelöscht","vac.autocal_no_match":'Raumnamen stimmten nicht überein (mindestens 3 müssen übereinstimmen) — öffnen Sie "Manuell anpassen"',"vac.autocal_done":"Fertig: über {rooms} Räume zugeordnet. Eine Reinigung starten und das Ergebnis prüfen.","vac.cal_need_pos":"Der Roboter meldet keine Koordinaten — starten Sie eine Reinigung und pausieren Sie sie","vac.cal_done":"Kalibrierung gespeichert. Eine Reinigung starten und das Ergebnis prüfen.","vac.cal_cancelled":"Kalibrierung abgebrochen","vac.fit":"Manuell anpassen","vac.fit_hint":"Roboterkarte an die richtige Position ziehen und an den Ecken skalieren","vac.fit_rotate":"90° drehen","vac.fit_mirror":"Spiegeln","vac.trail_never":"Nie","vac.trail_cleaning":"Beim Reinigen","vac.trail_always":"Immer","gs.bg_group":"Bühnenhintergrund","gs.bg_color":"Hintergrund um den Plan","gs.bg_default":"Standardthema","gs.bg_theme":"Standardthema","gs.bg_mode":"Planhintergrund","gs.bg_mode.help":"„Folgt der Sonne“ verwendet sun.sun und ersatzweise die lokale Browserzeit; „Statische Farbe“ zeigt immer die ausgewählte Farbe.","gs.bg_mode.help.aria":"Hilfe: allgemeiner Planhintergrund","gs.bg_static":"Statische Farbe","gs.bg_daynight":"Folgt der Sonne","gs.sun_group":"Sonne","gs.sun_missing":"Die sun.sun-Entität wurde nicht gefunden — der Hintergrund folgt Ihrer lokalen Uhr; Fensterstrahlen sind nicht verfügbar.","gs.north":"Norden auf dem Plan","gs.north.help":"Der Winkel wird im Uhrzeigersinn von der oberen Vertikalen des Plans gemessen; Norden wird für Fensterstrahlen benötigt, nicht für den Hintergrund „Folgt der Sonne“.","gs.north.help.aria":"Hilfe: allgemeine Nordrichtung","gs.north_ph":"nicht gesetzt","gs.north_clear":"Löschen","gs.north_letter":"N","gs.sun_rays":"Sonnenlicht durch Fenster","gs.about_version":"House Plan Card v{v}","gs.about_github":"GitHub · Dokumentation & Probleme","gs.about_telegram":"Telegram-Chat","support.title":"Hilfe & Feedback","space.bg_color":"Hintergrund rund um den Plan","space.bg_inherit":"Allgemein erben","space.bg_inherited":"erbt allgemeine Einstellungen","space.bg_mode":"Planhintergrund","space.bg_mode.help":"Übernehmen Sie den allgemeinen Hintergrund oder überschreiben Sie diesen Bereich mit einer statischen Farbe oder „Folgt der Sonne“.","space.bg_mode.help.aria":"Hilfe: Hintergrund des Bereichs","space.north":"Norden auf dem Plan (überschreiben)","space.north.help":"Überschreibt die allgemeine Nordrichtung für diesen Bereich; der Winkel wird im Uhrzeigersinn von der oberen Vertikalen des Plans gemessen und für Fensterstrahlen verwendet.","space.north.help.aria":"Hilfe: Norden für diesen Bereich","space.north_inherited":"geerbt: {v}","space.sun_rays":"Sonnenlicht durch Fenster","space.sun_inherit":"Allgemein erben","space.sun_on":"Ein","space.sun_off":"Aus","canvas.far_objects":"{n} Objekt(e) weit vom Plan entfernt","canvas.show_far":"Anzeigen","canvas.home_tip":"Der Plan ist dort drüben — klicken, um ihn anzupassen","gs.grid_group":"Planwartung","gs.grid_hint":"Aktualisiert Datenmodelle, richtet Planelemente am Raster aus und fasst redundante Wandfragmente zusammen. Ein exakter Bericht wird angezeigt, bevor etwas gespeichert wird.","gs.align_all":"Pläne optimieren","gs.align_title":"Pläne optimieren","gs.align_none":"Alle Pläne verwenden bereits das aktuelle optimierte Datenmodell.","gs.optimize_no_automatic_changes":"Es gibt keine automatischen Änderungen, die angewendet werden müssen. Überprüfen Sie die unten stehenden Punkte.","gs.align_count":"{n} von {total} Elementen werden sich um höchstens {cm} cm bewegen.","gs.align_where":"Die größte Verschiebung ist in „{s}“.","gs.align_turned":"Öffnungen, deren Winkel korrigiert wurde: {n}.","gs.align_removed_drafts":"Ungültige Umrisse vom Raster zusammengeklappt und entfernt: {n}.","gs.optimize_redundant_drafts":"Gespeicherte Wandketten, die durch feste Raumwände verdeckt waren, wurden entfernt: {n}.","gs.align_preflight_failed":"Die Geometrie der folgenden Bereiche konnte nicht sicher überprüft werden: {spaces}{more}.","gs.align_preflight_hint":"Pläne wurden nicht geändert. Kopieren Sie die Diagnosen mit dem untenstehenden Button und fügen Sie sie zusammen mit einem Raumexport dem Fehlerbericht bei.","gs.preflight_reason_prepare-exception":"Die Bereichsgeometrie konnte nicht vorbereitet werden (Ausnahme beim Erstellen des Modells)","gs.preflight_reason_wall-null":"Der Wandkörper wurde nicht erstellt (die Vereinigung lieferte leer zurück)","gs.preflight_reason_wall-degraded-extra":"Der Wandkörper wurde mit zusätzlicher Geometrie beschädigt","gs.preflight_reason_wall-failed-core":"Der Kern des Wandkörpers konnte nicht zusammengesetzt werden","gs.preflight_reason_wall-exception":"Die Wandkonstruktion warf eine Ausnahme","gs.preflight_reason_floor-null":"Der Fußbodenumriss wurde nicht erstellt","gs.preflight_reason_floor-exception":"Bodenaufbau hat eine Ausnahme ausgelöst","gs.preflight_copy":"Diagnosen kopieren","gs.preflight_copied":"Diagnosen kopiert","gs.preflight_update_hint":"Die Karten- und Integrationsversionen unterscheiden sich — Hausplan aktualisieren und erneut versuchen.","gs.align_preflight_space":"Bereich {n}","gs.align_preflight_more":", und {n} mehr","gs.optimize_changes":"Modellmigrationen: {m}; aktualisierte Bereiche: {c}; entfernte verrauschte Koordinatenwerte: {p}; zusammengeführte Fragmente realer Wände: {w}; zusammengeführte Fragmente von Wänden ohne Dicke: {s}; unabhängige Wände: {i}.","gs.zero_walls_migrated":"Virtuelle Wandspannweiten konvertiert: {n}.","gs.wall_segments_migrated":"Wandsegmente stabilisiert: {n}.","gs.optimize_lattice_summary":"Rauschen in den Koordinatenwerten kanonisiert: {n}; maximale Bewegung: {cm} cm.","gs.optimize_lattice_space":"{space}: Koordinatenwerte kanonisiert: {n}; außerhalb des Rasters liegende Werte unverändert gelassen: {far}.","gs.optimize_coincident_partitions":"Versteckte unabhängige Wandabschnitte in Raumwände integriert: {n}.","gs.optimize_openings_rehosted":"Öffnungen wieder an Raumwände angebracht: {n}.","gs.optimize_walls_straightened":"Wände begradigt: {n}; maximale Bewegung: {cm} cm.","gs.optimize_walls_straightened_where":"Größte Wandkorrektur: {s}.","gs.optimize_walls_straighten_skipped":"Nahe Achsenwände unverändert gelassen, da sie nicht sicher repariert werden konnten: {n}.","gs.optimize_glow_migration":"Legacy Glow: {spaces} Bereiche → keine Datenfüllung + unabhängiges Glow; {rooms} Räume → geerbte Datenfüllung + unabhängiges Glow.","gs.optimize_references":"Referenzen repariert: Bereiche — {spaces}; Räume — {rooms}; Positionen — {positions}; Geräte aus fehlenden Bereichen gelöst — {detached}.","gs.optimize_reference_more":", und {n} mehr","gs.optimize_orphans_removed":"Vergessene Einträge entfernt: {total} — Raumbezeichnungen: {rooms}; Geräte: {devices}; Gruppenmarkierungen: {groups}. Sie gehörten zu zuvor gelöschten Bereichen.","gs.optimize_live_positions":"Alte Positionen in gelöschten Bereichen gehören zu vorhandenen Objekten: {n}{names}. Sie werden beibehalten.","gs.optimize_live_positions_remove":"Alte Positionen in gelöschten Bereichen gehören zu vorhandenen Objekten: {n}{names}. Sie sind zur Entfernung ausgewählt.","gs.optimize_live_names":": {names}{more}","gs.optimize_live_remove":"Alte Positionen entfernen","gs.optimize_live_keep":"Alte Positionen beibehalten","gs.optimize_live_selected":"Alte Positionen werden nach der Anwendung von Optimieren entfernt.","gs.optimize_unverified":"Positionen konnten nicht sicher überprüft werden: {n}. Sie wurden unverändert belassen.","gs.optimize_registry_limited":"Voller Administratorzugriff auf die Home Assistant-Registries ist für eine sichere Überprüfung erforderlich.","gs.optimize_vacuum_warning":"Raumzuordnungen, die noch überprüft werden müssen: {n}.","gs.optimize_details":"Details","gs.optimize_details_more":"Und {n} weitere Einträge.","gs.optimize_detail_removed":"wird entfernt","gs.optimize_detail_live":"wird beibehalten","gs.optimize_detail_unverified":"nicht überprüft","gs.optimize_detail_room_label":"Raumkennzeichnung","gs.optimize_detail_device":"Gerät","gs.optimize_detail_group":"Gruppenkennzeichen","gs.optimize_detail_unknown":"unbekannter Eigentümer","gs.optimize_detail_item":"{status}: {kind} {id}; alter Bereich {space}","gs.align_warn":"Absichtlich zwischen Rasterknoten platzierte Elemente werden sich bewegen. Nach der Operation ist nur eine Rückgängig-Funktion verfügbar, und zwar nur bis zur nächsten Planbearbeitung.","gs.align_run":"Optimieren","gs.align_done":"Pläne optimiert: {n} Elemente bewegt, {m} Datensätze beibehalten, {r} Verweise repariert","gs.optimize_undo":"Letzte Optimierung rückgängig machen","gs.optimize_undone":"Die letzte Optimierung wurde rückgängig gemacht","decor.furniture":"Möbel","decor.image":"Bild","decor.image_title":"Eigene Bilder","decor.image_upload":"Bild hochladen","decor.image_replace":"Bild ersetzen","decor.image_uploading":"Wird hochgeladen…","decor.image_asset":"Bilddatei","decor.image_pick_hint":"Ein Bild hochladen oder ein vorhandenes auswählen.","decor.image_place_hint":"Auf den Plan klicken, um das Bild zu platzieren.","decor.image_none":"Noch keine Bilder hochgeladen.","decor.image_unavailable":"Bild nicht verfügbar","decor.image_used":"In {n} Objekten verwendet","decor.image_upload_failed":"Bild konnte nicht hochgeladen werden: {err}","decor.image_error_capacity":"Der Speicher für benutzerdefinierte Bilder ist voll.","decor.image_in_use":"Vor dem Löschen alle platzierten Kopien entfernen.","decor.image_delete_title":"Bilddatei löschen?","decor.image_delete_message":"„{name}“ aus House Plan löschen? Dies kann nicht rückgängig gemacht werden.","furn.title":"Möbelbibliothek","furn.symbol":"Symbol","furn.group_furniture":"Möbel","furn.group_appliance":"Geräte","furn.group_sanitary":"Sanitär","furn.group_other":"Sonstiges","furn.width":"Breite","furn.depth":"Tiefe","furn.back_to_categories":"Alle Kategorien","furn.pick_hint":"Wählen Sie eine Kategorie und dann ein Symbol.","furn.place_hint":"Klicken Sie auf den Plan — das Element wird an der nächsten Wand platziert. Mit Shift wird es frei platziert.","furn.cat_air_conditioner":"Klimaanlagen","furn.cat_armchair":"Sessel","furn.cat_bathtub":"Badewannen","furn.cat_bed":"Betten","furn.cat_bidet":"Bidets","furn.cat_boiler":"Warmwasserbereiter","furn.cat_chair":"Stühle","furn.cat_coffee_table":"Couchtische","furn.cat_cooktop":"Kochfelder","furn.cat_dining_table":"Esstische","furn.cat_dishwasher":"Geschirrspüler","furn.cat_dryer":"Wäschetrockner","furn.cat_fireplace":"Kamine","furn.cat_fridge":"Kühlschränke","furn.cat_kitchen_cabinet":"Küchenschränke","furn.cat_kitchen_sink":"Küchenspülen","furn.cat_nightstand":"Schränke","furn.cat_plant":"Pflanzen","furn.cat_rug":"Teppiche","furn.cat_shelving":"Regale","furn.cat_shower":"Duschen","furn.cat_sink":"Waschbecken","furn.cat_sofa":"Sofas","furn.cat_stairs":"Treppen","furn.cat_toilet":"Toiletten","furn.cat_tv":"Fernseher","furn.cat_wardrobe":"Kleiderschränke","furn.cat_washer":"Waschmaschinen","furn.cat_work_table":"Schreibtische","furn.sym_sofa":"Zweisitzer-Sofa","furn.sym_sofa_three_seat":"Dreisitzer-Sofa","furn.sym_sofa_corner_right":"Ecksofa rechts","furn.sym_armchair":"Polstersessel","furn.sym_armchair_office":"Bürostuhl","furn.sym_coffee_table":"Rechteckiger Couchtisch","furn.sym_coffee_table_round":"Runder Couchtisch","furn.sym_coffee_table_oval":"Ovaler Couchtisch","furn.sym_coffee_table_rounded":"Abgerundeter Couchtisch","furn.sym_table_dining":"Rechteckiger Esstisch","furn.sym_table_round":"Rundtisch","furn.sym_table_dining_oval":"Ovaler Esstisch","furn.sym_table_dining_rounded":"Abgerundeter Esstisch","furn.sym_chair":"Stuhl","furn.sym_chair_bar":"Barhocker","furn.sym_desk":"Rechteckiger Schreibtisch","furn.sym_desk_corner":"Eckschreibtisch","furn.sym_bed_double":"Doppelbett","furn.sym_bed_single":"Einzelbett","furn.sym_nightstand":"Nachttisch","furn.sym_cabinet_tv":"TV-Schrank","furn.sym_cabinet_shoe":"Schuhschrank","furn.sym_cabinet_sink":"Waschtischunterschrank","furn.sym_wardrobe":"Kleiderschrank","furn.sym_bookshelf":"Bücherschrank","furn.sym_wall_unit":"Schrankwand","furn.sym_kitchen_floor":"Küchen-Unterschrank","furn.sym_kitchen_floor_corner":"Küchen-Eckunterschrank","furn.sym_kitchen_wall":"Küchen-Hängeschrank","furn.sym_kitchen_wall_corner":"Küchen-Eckhängeschrank","furn.sym_shelf_floor":"Standregal","furn.sym_shelf_wall":"Wandregal","furn.sym_fridge":"Kühlschrank","furn.sym_stove":"Vierflammiges Kochfeld","furn.sym_cooktop_two":"Zweiflammiges Kochfeld","furn.sym_dishwasher":"Geschirrspüler","furn.sym_washer":"Waschmaschine","furn.sym_dryer":"Wäschetrockner","furn.sym_tv":"Fernseher mit Standfuß","furn.sym_tv_wall":"Wandfernseher","furn.sym_ac":"Klimaanlage","furn.sym_water_heater":"Wassererhitzer","furn.sym_toilet":"Stand-WC","furn.sym_toilet_built_in":"Wand-WC","furn.sym_bathtub":"Rechteckige Badewanne","furn.sym_bathtub_corner":"Eckbadewanne","furn.sym_shower":"Dusche","furn.sym_sink":"Waschbecken","furn.sym_kitchen_sink":"Einzel-Küchenspüle","furn.sym_kitchen_sink_double":"Doppel-Küchenspüle","furn.sym_bidet":"Stand-Bidet","furn.sym_bidet_built_in":"Wand-Bidet","furn.sym_stairs":"Treppe","furn.sym_fireplace":"Kamin","furn.sym_plant":"Pflanze","furn.sym_rug":"Teppich","common.yes":"Ja","common.no":"Nein","vac.diag_source":"Quelle","vac.diag_platform":"Integration","vac.diag_status":"Status","vac.diag_position":"Position","vac.diag_rooms":"Räume","vac.diag_rooms_value":"{total} · {matched} Namen stimmen überein · {readiness}","vac.autocal_ready":"Auto-Kalibrierung verfügbar","vac.autocal_not_ready":"3 übereinstimmende Namen erforderlich","vac.diag_path":"Integrationspfad","vac.diag_map":"Karten-ID","vac.source_none":"nicht ausgewählt","vac.source_status_ok":"Bereit","vac.source_status_missing":"Fehlend","vac.source_status_disabled":"In Home Assistant deaktiviert","vac.source_status_unavailable":"Nicht verfügbar","vac.source_status_unverified":"Kann mit den aktuellen Berechtigungen nicht verifizieren","vac.source_status_unsupported":"Keine Positionsdaten","vac.source_status_none":"Keine Quelle","vac.source_banner_missing":"Die gespeicherte Quelle existiert nicht mehr. Sie wurde nicht automatisch ersetzt; wählen Sie eine andere Quelle oder stellen Sie sie in Home Assistant wieder her.","vac.source_banner_disabled":"Die gespeicherte Quelle ist in Home Assistant deaktiviert. Aktivieren Sie sie dort oder wählen Sie eine andere Quelle.","vac.source_banner_unverified":"Die aktuellen Home Assistant-Berechtigungen können diese gespeicherte Quelle nicht verifizieren. Sie bleibt angepinnt und wird nicht automatisch ersetzt.","vac.choose_source":"Quelle wählen","vac.source_auto":"Automatisch","vac.source_auto_hint":"Verwenden Sie eine kompatible Entität von diesem Gerät","vac.all_cameras":"Alle Kameras","vac.all_cameras_warn":"Eine Kamera liefert möglicherweise keine Roboter-Daten. Wählen Sie eine nur, wenn es Ihre Saugroboter-Karte ist.","vac.all_cameras_empty":"Keine anderen Kamera-Entitäten gefunden.","vac.platform_unknown":"unbekannte Integration","vac.cap_position":"Position","vac.cap_rooms_short":"Räume","vac.cap_path":"Pfad","vac.cap_map":"Karten-ID","vac.cap_none":"Keine Roboter-Daten erkannt","vac.xcme_hint":"Aktivieren Sie diese Xiaomi Cloud Map Extractor-Attribute:","vac.documentation":"Dokumentation","vac.residual_title":"Automatische Kalibrierung überprüfen","vac.residual_message":"Die zugeordneten Räume weichen um bis zu {error} voneinander ab. Diese ungefähre Kalibrierung anwenden, manuell verfeinern oder ohne Änderung der gespeicherten Einrichtung abbrechen.","vac.apply_proposal":"Anwenden","gs.backup_group":"Sichern und übertragen","gs.backup_hint":"Laden Sie ein tragbares JSON-Backup herunter oder sehen Sie eine Vorschau und importieren Sie ein Backup, das mit House Plan erstellt wurde.","backup.export_open":"Exportieren","backup.import_open":"Importieren","backup.export_title":"House Plan exportieren","backup.import_title":"House Plan importieren","backup.export_hint":"Wählen Sie, ob das Backup die gesamte House Plan-Konfiguration oder nur den aktuellen Bereich enthalten soll.","backup.full":"Vollständiges Backup","backup.current_space":"Aktueller Bereich","backup.current_space_title":"Aktueller Bereich: {title}","backup.no_current_space":"Kein aktueller Bereich","backup.plan_only":"Nur Plan","backup.plan_only_hint":"Räume, Wände, Öffnungen, Dekor und Raumbezeichnungspositionen ohne Geräte oder Home Assistant-Bindungen beibehalten.","backup.plan_only_preview":"Diese Datei enthält nur den Plan.","backup.privacy_warning":"Das Archiv enthält Namen, Home Assistant-Kennungen und genaue Koordinaten. Interne Pläne und Anhänge werden referenziert, nicht eingebettet; Laufzeitzustände und Staubsaugerspuren sind nicht enthalten.","backup.download":"JSON herunterladen","backup.export_done":"Backup heruntergeladen","backup.reading":"Überprüfe das Backup…","backup.revalidated":"Der Plan wurde nach dieser Vorschau geändert. Die Zusammenfassung wurde aktualisiert; überprüfen Sie sie und bestätigen Sie erneut.","backup.error.support_invalid_message":"Prüfen Sie die Supportnachricht und versuchen Sie es erneut.","backup.error.support_package_too_large":"Das anonymisierte Supportpaket überschreitet das Limit von 8 MiB.","backup.error.support_preview_expired":"Die Vorschau des Supportanhangs ist abgelaufen oder nicht mehr verfügbar.","backup.error.support_rate_limited":"Zu viele Supportberichte oder Vorschauen wurden angefordert. Versuchen Sie es später erneut.","backup.error.support_rejected":"Der Bericht hat die Prüfung des Supportdienstes nicht bestanden.","backup.error.support_unavailable":"Der private Supportdienst ist vorübergehend nicht verfügbar.","backup.error.unauthorized":"Sie haben keine Berechtigung, diesen Plan zu exportieren oder zu importieren.","backup.error.not_ready":"Der Hausplan ist noch nicht fertig. Versuchen Sie es in einem Moment erneut.","backup.error.too_large":"Das Backup überschreitet das 8-MiB-Limit.","backup.error.invalid_json":"Die ausgewählte Datei ist kein gültiges JSON.","backup.error.invalid_format":"Die ausgewählte Datei ist kein House Plan-Backup.","backup.error.invalid_image":"Das Bild ist beschädigt oder entspricht nicht seinem Format.","backup.error.unsupported_export_version":"Dieses Backup-Format wird von der installierten Version nicht unterstützt.","backup.error.unsupported_image":"Verwenden Sie ein unterstütztes PNG-, JPEG-, WebP- oder SVG-Bild.","backup.error.future_model":"Das Backup wurde mit einem neueren House-Plan-Datenmodell erstellt.","backup.error.invalid_config":"Das Backup enthält eine ungültige House-Plan-Konfiguration.","backup.error.wall_model_migration_blocked":"Das Backup-Wandmodell konnte nicht sicher aktualisiert werden. Optimieren Sie zuerst den Quellplan und exportieren Sie ihn dann erneut.","backup.error.invalid_layout":"Das Backup enthält ungültige Objektpositionen.","backup.error.invalid_content":"Das Backup enthält ungültige oder inkonsistente Inhaltsreferenzen.","backup.error.space_not_found":"Der ausgewählte Bereich existiert nicht mehr.","backup.error.capacity_exceeded":"Durch das Hinzufügen dieses Backups würden die Planlimits überschritten.","backup.error.preview_expired":"Die Vorschau ist abgelaufen. Wählen Sie die Backup-Datei erneut aus.","backup.error.preview_owner_mismatch":"Diese Vorschau gehört zu einem anderen Home-Assistant-Benutzer.","backup.error.conflict":"Der Plan hat sich nach der Vorschau geändert. Überprüfen Sie die aktualisierte Zusammenfassung.","backup.error.content_confirmation_required":"Bestätigen Sie, dass nicht verfügbare lokale Inhalte getrennt werden können.","backup.error.commit_failed":"Das Backup konnte nicht sicher angewendet werden. Der vorherige Plan wurde wiederhergestellt oder wartet auf die Wiederherstellung.","backup.error.missing_plan":"Eine referenzierte Plan-Datei ist nach der Vorschau verschwunden. Überprüfen Sie das Backup erneut.","backup.error.missing_content":"Ein referenziertes lokales Anhangselement ist nach der Vorschau verschwunden. Überprüfen Sie das Backup erneut.","backup.error.marker_control_missing":"Ein verknüpftes Planlicht fehlt im Backup.","backup.error.marker_control_not_light":"Ein verknüpftes Planziel ist nicht mehr als Lichtquelle markiert.","backup.error.marker_control_self":"Eine Lichtquelle kann sich nicht selbst steuern.","backup.error.marker_control_cycle":"Das Backup enthält eine kreisförmige Kette von Lichtsteuerungen.","backup.error.duplicate_marker_control":"Das Backup enthält eine doppelte Plan-Licht-Verknüpfung.","backup.error.no_backup":"Es gibt keinen Import- oder Optimierungssnapshot zur Wiederherstellung.","backup.error.in_use":"Das Element wird noch verwendet","backup.error.invalid_data":"Die Anfrage enthält ungültige Daten","backup.error.invalid_light_entity":"Das führende Licht muss eine light.*- oder switch.*-Entität sein","backup.error.invalid_marker_control":"Ungültige Marker-Steuerungsreferenz","backup.error.invalid_name":"Der Name ist ungültig","backup.error.invalid_partition_opening_host":"Die Öffnung muss ihren Trennwand-Träger behalten","backup.error.invalid_partition_opening_jamb_margin":"Die Öffnung lässt keinen physischen Pfosten am Wandende","backup.error.invalid_passage_fields":"Ein offener Durchgang kann keine Tür-Einstellungen tragen","backup.error.invalid_space_id":"Unbekannter Raumbereich","backup.error.invalid_toggle_entity":"Die Schalt-Entität muss light.* oder switch.* sein","backup.error.invalid_value_badge":"Ungültige Wert-Badge-Einstellungen","backup.error.invalid_value_badge_attribute":"Ungültiges Wert-Badge-Attribut","backup.error.invalid_value_badge_position":"Ungültige Wert-Badge-Position","backup.error.invalid_value_badge_source":"Ungültige Wert-Badge-Quelle","backup.error.invalid_vacuum_map_route":"Prüfen Sie die Zuordnung der Roboterkarten zu Räumen.","backup.error.invalid_value_source":"Ungültige Wertquelle","backup.error.invalid_value_source_attribute":"Ungültiges Wertquellen-Attribut","backup.error.io_error":"Eine Dateioperation auf dem Server ist fehlgeschlagen","backup.error.not_toggleable":"Dieses Gerät kann nicht geschaltet werden","backup.error.nothing_to_repair":"Nichts zu reparieren","backup.error.space_in_use":"Der Raumbereich wird noch referenziert","backup.error.value_badge_source_required":"Das Wert-Badge braucht eine Quelle","backup.error.wall_model_client_outdated":"Der Plan wurde anderswo aktualisiert — Seite neu laden","backup.same_source":"Erstellt auf dieser Home Assistant-Instanz","backup.foreign_source":"Erstellt auf einer anderen Home Assistant-Instanz","backup.created":"Erstellt: {value}","backup.versions":"Karte {card}; Integration {integration}; Datenmodell {model}","backup.count_spaces":"Bereiche: {n}","backup.count_rooms":"Räume: {n}","backup.count_walls":"Wände: {n}","backup.count_openings":"Öffnungen: {n}","backup.count_decor":"Dekorationsobjekte: {n}","backup.count_markers":"Geräte: {n}","backup.count_layout":"Positionen: {n}","backup.bindings":"Verknüpfungen — Geräte: {device}, Entitäten: {entity}, virtuell: {virtual}; Positionen ohne Bereich: {legacy}","backup.binding_status":"Zielstatus — aktiv: {active}, deaktiviert: {disabled}, fehlt: {missing}","backup.missing_areas":"Auf dem Ziel fehlende Bereiche: {areas}","backup.dropped_marker_links":"Planlicht-Verknüpfungen außerhalb dieses übertragenen Bereichs wurden ausgelassen: {n}.","backup.repaired_target_refs":"Durch den Import dieses Bereichs wiederhergestellte vorhandene Referenzen: {n}.","backup.preserved_unresolved_refs":"Referenzen, die nicht eindeutig wiederhergestellt werden konnten, wurden beibehalten: {n}.","backup.preserved_unresolved_hint":"Es wurden keine Daten geraten oder gelöscht. Führen Sie nach dem Import Optimierungspläne aus, um die verbleibenden Referenzen zu überprüfen.","backup.import_details":"Importieren von Referenzdetails","backup.import_detail.incoming_remapped":"Referenzen innerhalb der importierten Kopie aktualisiert: {n}","backup.import_detail.target_repaired":"Vorhandene Referenzen wiederhergestellt: {n}","backup.import_detail.preserved_unresolved":"Unaufgelöste Referenzen beibehalten: {n}","backup.import_detail.collisions":"Zielkonflikte sicher beibehalten: {n}","backup.import_detail.dropped_links":"Eingehende Links durch Übertragungsregeln ausgelassen: {n}","backup.import_detail.bounded_lineages":"Übermäßig verschachtelte Kennungen begrenzt belassen: {n}","backup.replace_warning":"Dies ersetzt die aktuelle Konfiguration und das Layout. Hochgeladene Dateien werden niemals gelöscht. Eine Rückgängig-Möglichkeit bleibt bis zur nächsten Planbearbeitung verfügbar.","backup.foreign_bookkeeping":"Instanzspezifische bekannte/neue Gerätebuchführung wird nicht importiert.","backup.final_name":"Name des neuen Bereichs","backup.target_settings":"Die globalen Einstellungen der Zielinstanz bleiben unverändert.","backup.duplicates":"Bindungen bereits vorhanden: {n}","backup.skip":"Doppelte Geräte überspringen","backup.virtual_copy":"Sichere statische virtuelle Kopien hinzufügen","backup.content":"Referenzierter Inhalt","backup.decor_images_summary":"Eigene Bilder: {objects} Objekte, {assets} Dateien; fehlende Dateien: {missing}.","backup.content_available":"lokal verfügbar","backup.content_external":"externer Link","backup.content_detach_required":"wird getrennt","backup.confirm_detach":"Ich verstehe, dass nicht verfügbare interne Pläne und Anhänge von der importierten Konfiguration getrennt werden.","backup.confirm_missing_images":"Ich verstehe, dass fehlende eigene Bilder als reparierbare Platzhalter erhalten bleiben und andere nicht verfügbare lokale Dateien getrennt werden.","backup.replace":"Ersetzen","backup.add":"Bereich hinzufügen","backup.space_done":"Bereich importiert: {rooms} Räume, {markers} Geräte, {refs} bestehende Referenzen wiederhergestellt","backup.full_done":"Backup wiederhergestellt: {spaces} Bereiche, {rooms} Räume, {markers} Geräte","backup.undo_import":"Letzten vollständigen Import rückgängig machen","backup.import_undone":"Vollständiger Import rückgängig gemacht","backdrop.large_title":"Großes Bild","backdrop.large_body":"Dieses Bild ist {w}×{h} ({fileMb} MB Datei) und benötigt etwa {decodedMb} MB Speicher zur Anzeige. Auf Tablets kann das die Seite zum Absturz bringen.","backdrop.unknown_body":"Die Bildabmessungen konnten nicht gelesen werden — die Datei ist möglicherweise beschädigt. Fortfahren kann die Seite auf Tablets zum Absturz bringen.","backdrop.reduced_dimensions":"Verkleinerte Kopie: {w}×{h} px.","backdrop.use_downscaled":"Verkleinerte Kopie hochladen","backdrop.reducing":"Wird verkleinert…","backdrop.keep_original":"Original behalten","backdrop.too_large_title":"Bild ist zu groß","backdrop.too_large_body":"Dieses Bild überschreitet die Anzeigegrenzen des Browsers ({w}×{h}, Limit {limit} px pro Seite). Bitte verkleinern Sie es in einem Desktop-Editor und laden Sie es erneut hoch.","backdrop.downscale_failed":"Die verkleinerte Kopie konnte nicht erstellt werden. Der aktuelle Plan wurde nicht geändert."};const n="781b6de4892612660b01762cd408049137fa0d00417a43ef5bbdfb1ef37dc9a5";export{e as dictionary,n as fingerprint};
diff --git a/dist/houseplan-assets/editor-CxXW-QO8.js b/custom_components/houseplan/frontend/houseplan-assets/editor-CHYZKnjE.js
similarity index 94%
rename from dist/houseplan-assets/editor-CxXW-QO8.js
rename to custom_components/houseplan/frontend/houseplan-assets/editor-CHYZKnjE.js
index 504db8f5..9018afbb 100644
--- a/dist/houseplan-assets/editor-CxXW-QO8.js
+++ b/custom_components/houseplan/frontend/houseplan-assets/editor-CHYZKnjE.js
@@ -1,4 +1,4 @@
-globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="bd7029808eb6094140d9fa8245f50816cb452430a353f4231d16e02c97078a06";import{g as e,l as o,t,dm as s,A as a,dn as i,dp as l,dq as n,E as r,c}from"./houseplan-card-BTXh6SvG.js";class h extends e{constructor(){super(...arguments),this._spaces=null,this._spacesLoading=!1,this._spacesAuthoritative=!1}setConfig(e){this._config=e}async _loadSpaces(){if(!this._spaces&&!this._spacesLoading&&this.hass){this._spacesLoading=!0;try{const e=await this.hass.callWS({type:"houseplan/config/get"});this._spaces=(e?.config?.spaces||[]).map(e=>({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`{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,m=p.trustedTypes,_=m?m.emptyScript:"",f=p.reactiveElementPolyfillSupport,g=(e,t)=>e,v={toAttribute(e,t){switch(t){case Boolean:e=e?_: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(g("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(g("finalized")))return;if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(g("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[g("elementProperties")]=new Map,w[g("finalized")]=new Map,f?.({ReactiveElement:w}),(p.reactiveElementVersions??=[]).push("2.1.2");const k=globalThis,x=e=>e,$=k.trustedTypes,S=$?$.createPolicy("lit-html",{createHTML:e=>e}):void 0,M="$lit$",C=`lit$${Math.random().toFixed(9).slice(2)}$`,T="?"+C,R=`<${T}>`,D=document,z=()=>D.createComment(""),A=e=>null===e||"object"!=typeof e&&"function"!=typeof e,P=Array.isArray,O="[ \t\n\f\r]",F=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,I=/-->/g,E=/>/g,H=RegExp(`>|${O}(?:([^\\s"'>=/]+)(${O}*=${O}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),N=/'/g,L=/"/g,B=/^(?:script|style|textarea|title)$/i,q=e=>(t,...i)=>({_$litType$:e,strings:t,values:i}),W=q(1),j=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(!P(e)||!e.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==S?S.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=$?$.emptyScript:"";for(let i=0;iP(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&&A(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){P(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(z()),this.O(z()),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=!A(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(z(),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=new WeakMap;let pe=0;class me extends he{constructor(){super(...arguments),this.title="",this.icon="",this.wide=!1,this.alert=!1,this.describedBy="",this.dismissOnScrim=!1,this.hass=null,this._opener=null,this._focusRoot=null,this._useHaDialog=!1,this._closing=!1,this._overlays=[],this._titleId="hp-dialog-title-"+ ++pe,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 this._useHaDialog&&!this.alert}connectedCallback(){super.connectedCallback(),this._opener=this._deepActiveElement();const e=this.getRootNode();this._focusRoot=e;const t=ue.get(e)||{dialogs:new Set,opener:this._opener};t.dialogs.add(this),ue.set(e,t),this._useHaDialog=!!customElements.get("ha-dialog"),this.addEventListener("keydown",this._onKeyDown,!0)}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?ue.get(t):void 0;n?.dialogs.delete(this),super.disconnectedCallback(),t&&n&&requestAnimationFrame(()=>{const e=ue.get(t);if(!e)return;if(!e.dialogs.size)return e.opener?.isConnected&&e.opener.focus({preventScroll:!0}),void ue.delete(t);const n=i?.closest("hp-dialog");i?.isConnected&&n&&e.dialogs.has(n)&&i.focus({preventScroll:!0})})}firstUpdated(e){if(super.firstUpdated(e),!this._usesHaDialog()){const e=this.renderRoot.querySelector("dialog");e&&!e.open&&e.showModal()}queueMicrotask(()=>this._focusInitial())}_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=W`
+globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="781b6de4892612660b01762cd408049137fa0d00417a43ef5bbdfb1ef37dc9a5";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,m=p.trustedTypes,_=m?m.emptyScript:"",f=p.reactiveElementPolyfillSupport,g=(e,t)=>e,v={toAttribute(e,t){switch(t){case Boolean:e=e?_: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(g("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(g("finalized")))return;if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(g("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[g("elementProperties")]=new Map,w[g("finalized")]=new Map,f?.({ReactiveElement:w}),(p.reactiveElementVersions??=[]).push("2.1.2");const k=globalThis,x=e=>e,$=k.trustedTypes,S=$?$.createPolicy("lit-html",{createHTML:e=>e}):void 0,M="$lit$",C=`lit$${Math.random().toFixed(9).slice(2)}$`,T="?"+C,R=`<${T}>`,D=document,z=()=>D.createComment(""),A=e=>null===e||"object"!=typeof e&&"function"!=typeof e,P=Array.isArray,O="[ \t\n\f\r]",F=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,I=/-->/g,E=/>/g,H=RegExp(`>|${O}(?:([^\\s"'>=/]+)(${O}*=${O}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),N=/'/g,L=/"/g,B=/^(?:script|style|textarea|title)$/i,q=e=>(t,...i)=>({_$litType$:e,strings:t,values:i}),W=q(1),j=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(!P(e)||!e.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==S?S.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=$?$.emptyScript:"";for(let i=0;iP(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&&A(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){P(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(z()),this.O(z()),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=!A(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(z(),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=new WeakMap;let pe=0;class me extends he{constructor(){super(...arguments),this.title="",this.icon="",this.wide=!1,this.alert=!1,this.describedBy="",this.dismissOnScrim=!1,this.hass=null,this._opener=null,this._focusRoot=null,this._useHaDialog=!1,this._closing=!1,this._overlays=[],this._titleId="hp-dialog-title-"+ ++pe,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 this._useHaDialog&&!this.alert}connectedCallback(){super.connectedCallback(),this._opener=this._deepActiveElement();const e=this.getRootNode();this._focusRoot=e;const t=ue.get(e)||{dialogs:new Set,opener:this._opener};t.dialogs.add(this),ue.set(e,t),this._useHaDialog=!!customElements.get("ha-dialog"),this.addEventListener("keydown",this._onKeyDown,!0)}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?ue.get(t):void 0;n?.dialogs.delete(this),super.disconnectedCallback(),t&&n&&requestAnimationFrame(()=>{const e=ue.get(t);if(!e)return;if(!e.dialogs.size)return e.opener?.isConnected&&e.opener.focus({preventScroll:!0}),void ue.delete(t);const n=i?.closest("hp-dialog");i?.isConnected&&n&&e.dialogs.has(n)&&i.focus({preventScroll:!0})})}firstUpdated(e){if(super.firstUpdated(e),!this._usesHaDialog()){const e=this.renderRoot.querySelector("dialog");e&&!e.open&&e.showModal()}queueMicrotask(()=>this._focusInitial())}_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=W`
${this.icon?W``:V}
${this.title}`;return this._usesHaDialog()?this.describedBy?W`{e.isConnected&&e.requestUpdate()}),uu.has(e)?"warm":"cold"):(pu.delete(e)&&(e.inert=!1,e.removeAttribute("aria-busy")),i&&(e.setAttribute("lang","fallback"===n?"en":i),uu.add(e)),"ready")}function _u(){return W``}const fu=[{code:"en",nativeLabel:"English",dictionary:du},{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":"Проверьте сеть и нажмите ещё раз.","color_picker.title":"Выбор цвета","color_picker.hue":"Оттенок","color_picker.saturation":"Насыщенность","color_picker.value":"Яркость","color_picker.hex":"Цвет HEX","color_picker.invalid_hex":"Введите цвет HEX из 3 или 6 цифр","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.draft_segment":"Добавление сегмента черновика комнаты","history.draft_merge":"Соединение незавершённых контуров комнаты","history.draft_segment_delete":"Удаление сегмента черновика комнаты","history.column_add":"Добавление колонны","history.physical_edit":"Изменение физического объекта","history.physical_delete":"Удаление физического объекта","history.physical_move":"Перемещение физического объекта","history.contour_to_partitions":"Преобразование контура в замкнутые стены","history.wall_chain_finish":"Завершение цепочки стен","history.wall_face_batch":"Создание комнат из стен","toast.column_duplicate":"Колонна с тем же центром и внешним размером уже существует","confirm.delete_draft_title":"Удалить незавершённый контур?","confirm.delete_draft_body":"Весь незавершённый контур комнаты будет удалён. При отмене ничего не изменится.","confirm.delete_draft_segment_title":"Удалить сегмент контура?","confirm.delete_draft_segment_body":"Этот сегмент черновика будет удалён. Оставшийся контур может разделиться на два.","physical.partition_properties":"Свойства перегородки","physical.column_properties":"Свойства колонны","physical.draft_properties":"Свойства сегмента черновика","physical.shape":"Форма","physical.square":"Квадрат","physical.circle":"Круг","physical.diameter":"Диаметр","physical.side":"Сторона","physical.rotation":"Угол поворота","physical.length":"Длина","physical.allowed_range":"Допустимо: {min}–{max} {unit}","physical.delete_segment":"Удалить сегмент","physical.delete_draft":"Удалить весь контур","physical.column_size_title":"Внешняя сторона квадратной колонны, создаваемой кликом (1–150 см).","card.title":"План дома","count.devices":"{n} устр.","empty.no_spaces":"Пространств пока нет.","empty.add_first":"Добавьте первое пространство и загрузите план этажа.","empty.install":"Установите интеграцию House Plan и добавьте запись в «Устройства и службы».","btn.add_space":"Добавить пространство","btn.cancel":"Отмена","btn.save":"Сохранить","btn.close":"Закрыть","btn.delete":"Удалить","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.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":"Пространство, все его комнаты и вся разметка плана будут удалены.","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_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":"Общие настройки","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":"Общие настройки сохранены","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","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_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":"Не удалось загрузить языковой пакет. До перезагрузки страницы используется английский.","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_removed_drafts":"Схлопнувшиеся на сетке некорректные контуры удалены: {n}.","gs.optimize_redundant_drafts":"Сохранённые цепочки стен, полностью скрытые стенами комнат, удалены: {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.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_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.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-Cm5MlI_Y.js"):await import(new URL("./de-Cm5MlI_Y.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-CDWnrdfn.js"):await import(new URL("./fr-CDWnrdfn.js?retry",import.meta.url).href);return{dictionary:t.dictionary,fingerprint:t.fingerprint}}}],gu=du,vu=new Set;const yu=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)}}(fu,"bd7029808eb6094140d9fa8245f50816cb452430a353f4231d16e02c97078a06",console.warn,function(e){for(const t of vu)t(e)});function bu(e){const t=xu(e)?.code??"en";return yu.dictionary(t)??gu}function wu(e){return"string"==typeof e?e.trim().replaceAll("_","-").toLowerCase():""}const ku=new Map(fu.map(e=>[wu(e.code),e]));function xu(e){return ku.get(wu(e))}function $u(e,t){const i=[{value:"",label:e},...fu.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:xu(n)?.nativeLabel??n}),i}function Su(e,t){return function(e,t,i,n){const r=new Map(i.map(e=>[wu(e),e])),o=r.get(wu(e));if(o)return o;const s=wu(t),a=r.get(s);return a||(r.get(s.split("-")[0]||"")??n)}(t,e?.locale?.language||e?.language,fu.map(({code:e})=>e),"en")}function Mu(e,t,i){return Hi(bu(e)[t]??gu[t]??t,i)}function Cu(e,t){const i=bu(e)[t]??gu[t];return"string"==typeof i&&i.trim().length>0}function Tu(e){const t=e.length/2,i=e.face.cm>0?e.face.cm/e.cellCm*e.gridPitch/2:ya(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(ya(16,e.cellCm),i+ya(8,e.cellCm),n+ya(8,e.cellCm)),hitHalf:Math.max(ya(20,e.cellCm),i+ya(10,e.cellCm),n+ya(12,e.cellCm))}}function Ru(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 Du(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}=Tu(e),r=va(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)Du(c,-i,0,i,-o,o,-90,0),Du(c,i,-i,0,-o,o,0,90),Ru(c,-i-a,-i-a),Ru(c,i+a,a);else if("gate"===e.type){const t=10*e.face.side;Du(c,-i,0,i,-o,o,0,t),Du(c,i,-i,0,-o,o,-t,0)}else Du(c,-i,0,e.length,-o,o,-90,0),Ru(c,-i-a,-e.length-a),Ru(c,i+a,a);const[h,d]=zu(e),u={...l};Ru(u,c.minX+h,c.minY+d),Ru(u,c.maxX+h,c.maxY+d);const p=e.flipH?-1:1,m="gate"===e.type?1:e.flipV?-1:1,_=e.angle*Math.PI/180,f=Math.cos(_),g=Math.sin(_),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*m;Ru(v,t[0]+n*f-r*g,t[1]+n*g+r*f)}return v}function Pu(e){if("passage"===e.type)return j``;const t=Math.max(0,Math.min(1,e.amount)),{half:i,jambHalf:n}=Tu(e),r=va(e.cellCm),o=1.75*r,s=e.flipH?-1:1,a=e.flipV?-1:1,l="gate"===e.type?1:a,[c,h]=zu(e);let d;if("window"===e.type){const o=Math.PI/2*i,s=e.face.cm>0?j`{e.isConnected&&e.requestUpdate()}),uu.has(e)?"warm":"cold"):(pu.delete(e)&&(e.inert=!1,e.removeAttribute("aria-busy")),i&&(e.setAttribute("lang","fallback"===n?"en":i),uu.add(e)),"ready")}function _u(){return W``}const fu=[{code:"en",nativeLabel:"English",dictionary:du},{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":"Проверьте сеть и нажмите ещё раз.","color_picker.title":"Выбор цвета","color_picker.hue":"Оттенок","color_picker.saturation":"Насыщенность","color_picker.value":"Яркость","color_picker.hex":"Цвет HEX","color_picker.invalid_hex":"Введите цвет HEX из 3 или 6 цифр","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.draft_segment":"Добавление сегмента черновика комнаты","history.draft_merge":"Соединение незавершённых контуров комнаты","history.draft_segment_delete":"Удаление сегмента черновика комнаты","history.column_add":"Добавление колонны","history.physical_edit":"Изменение физического объекта","history.physical_delete":"Удаление физического объекта","history.physical_move":"Перемещение физического объекта","history.contour_to_partitions":"Преобразование контура в замкнутые стены","history.wall_chain_finish":"Завершение цепочки стен","history.wall_face_batch":"Создание комнат из стен","toast.column_duplicate":"Колонна с тем же центром и внешним размером уже существует","confirm.delete_draft_title":"Удалить незавершённый контур?","confirm.delete_draft_body":"Весь незавершённый контур комнаты будет удалён. При отмене ничего не изменится.","confirm.delete_draft_segment_title":"Удалить сегмент контура?","confirm.delete_draft_segment_body":"Этот сегмент черновика будет удалён. Оставшийся контур может разделиться на два.","physical.partition_properties":"Свойства перегородки","physical.column_properties":"Свойства колонны","physical.draft_properties":"Свойства сегмента черновика","physical.shape":"Форма","physical.square":"Квадрат","physical.circle":"Круг","physical.diameter":"Диаметр","physical.side":"Сторона","physical.rotation":"Угол поворота","physical.length":"Длина","physical.allowed_range":"Допустимо: {min}–{max} {unit}","physical.delete_segment":"Удалить сегмент","physical.delete_draft":"Удалить весь контур","physical.column_size_title":"Внешняя сторона квадратной колонны, создаваемой кликом (1–150 см).","card.title":"План дома","count.devices":"{n} устр.","empty.no_spaces":"Пространств пока нет.","empty.add_first":"Добавьте первое пространство и загрузите план этажа.","empty.install":"Установите интеграцию House Plan и добавьте запись в «Устройства и службы».","btn.add_space":"Добавить пространство","btn.cancel":"Отмена","btn.save":"Сохранить","btn.close":"Закрыть","btn.delete":"Удалить","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.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_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":"Общие настройки","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":"Общие настройки сохранены","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","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_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":"Не удалось загрузить языковой пакет. До перезагрузки страницы используется английский.","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_removed_drafts":"Схлопнувшиеся на сетке некорректные контуры удалены: {n}.","gs.optimize_redundant_drafts":"Сохранённые цепочки стен, полностью скрытые стенами комнат, удалены: {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.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.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-DZwnjt2u.js"):await import(new URL("./de-DZwnjt2u.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-C7WePbhg.js"):await import(new URL("./fr-C7WePbhg.js?retry",import.meta.url).href);return{dictionary:t.dictionary,fingerprint:t.fingerprint}}}],gu=du,vu=new Set;const yu=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)}}(fu,"781b6de4892612660b01762cd408049137fa0d00417a43ef5bbdfb1ef37dc9a5",console.warn,function(e){for(const t of vu)t(e)});function bu(e){const t=xu(e)?.code??"en";return yu.dictionary(t)??gu}function wu(e){return"string"==typeof e?e.trim().replaceAll("_","-").toLowerCase():""}const ku=new Map(fu.map(e=>[wu(e.code),e]));function xu(e){return ku.get(wu(e))}function $u(e,t){const i=[{value:"",label:e},...fu.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:xu(n)?.nativeLabel??n}),i}function Su(e,t){return function(e,t,i,n){const r=new Map(i.map(e=>[wu(e),e])),o=r.get(wu(e));if(o)return o;const s=wu(t),a=r.get(s);return a||(r.get(s.split("-")[0]||"")??n)}(t,e?.locale?.language||e?.language,fu.map(({code:e})=>e),"en")}function Mu(e,t,i){return Hi(bu(e)[t]??gu[t]??t,i)}function Cu(e,t){const i=bu(e)[t]??gu[t];return"string"==typeof i&&i.trim().length>0}function Tu(e){const t=e.length/2,i=e.face.cm>0?e.face.cm/e.cellCm*e.gridPitch/2:ya(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(ya(16,e.cellCm),i+ya(8,e.cellCm),n+ya(8,e.cellCm)),hitHalf:Math.max(ya(20,e.cellCm),i+ya(10,e.cellCm),n+ya(12,e.cellCm))}}function Ru(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 Du(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}=Tu(e),r=va(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)Du(c,-i,0,i,-o,o,-90,0),Du(c,i,-i,0,-o,o,0,90),Ru(c,-i-a,-i-a),Ru(c,i+a,a);else if("gate"===e.type){const t=10*e.face.side;Du(c,-i,0,i,-o,o,0,t),Du(c,i,-i,0,-o,o,-t,0)}else Du(c,-i,0,e.length,-o,o,-90,0),Ru(c,-i-a,-e.length-a),Ru(c,i+a,a);const[h,d]=zu(e),u={...l};Ru(u,c.minX+h,c.minY+d),Ru(u,c.maxX+h,c.maxY+d);const p=e.flipH?-1:1,m="gate"===e.type?1:e.flipV?-1:1,_=e.angle*Math.PI/180,f=Math.cos(_),g=Math.sin(_),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*m;Ru(v,t[0]+n*f-r*g,t[1]+n*g+r*f)}return v}function Pu(e){if("passage"===e.type)return j``;const t=Math.max(0,Math.min(1,e.amount)),{half:i,jambHalf:n}=Tu(e),r=va(e.cellCm),o=1.75*r,s=e.flipH?-1:1,a=e.flipV?-1:1,l="gate"===e.type?1:a,[c,h]=zu(e);let d;if("window"===e.type){const o=Math.PI/2*i,s=e.face.cm>0?j``:j``;d=j`
performance.now(),requestFrame:e=>requestAnimationFrame(e),cancelFrame:e=>cancelAnimationFrame(e)},O_=e=>Math.max(0,Math.min(1,e)),F_=(e,t,i)=>e+(t-e)*i,I_=(e,t,i)=>{const n=1-e;return 3*n*n*e*t+3*n*e*e*i+e*e*e},E_=e=>{const t=O_(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,I_(r,.2,.2)0&&e.w>0?t/e.w:1,viewBox:{...e}}}function N_(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 L_(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 B_(e,t,i){const n=L_(e),r=L_(t);if(!n||!r)return i<.5?e:t;const o=O_(i);return`rgba(${Math.round(F_(n[0],r[0],o))}, ${Math.round(F_(n[1],r[1],o))}, ${Math.round(F_(n[2],r[2],o))}, ${F_(n[3],r[3],o).toFixed(3)})`}class q_{constructor(e,t=P_){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=O_((e-t.startedAt)/t.duration);t.presented=i>=1?t.to:function(e,t,i){const n=E_(i),r=F_(e.stageWidth,t.stageWidth,n),o=F_(e.stageHeight,t.stageHeight,n),s=Math.max(1e-9,e.viewport.pixelsPerUnit),a=Math.max(1e-9,t.viewport.pixelsPerUnit),l={centerX:F_(e.viewport.centerX,t.viewport.centerX,n),centerY:F_(e.viewport.centerY,t.viewport.centerY,n),pixelsPerUnit:Math.exp(F_(Math.log(s),Math.log(a),n))};return{presentedMode:n<.5?e.presentedMode:t.presentedMode,editorChromeHeight:F_(e.editorChromeHeight,t.editorChromeHeight,n),stageWidth:r,stageHeight:o,viewport:{...l,viewBox:N_(l,r,o)},stageColor:B_(e.stageColor,t.stageColor,n),paperColor:B_(e.paperColor,t.paperColor,n),sceneBrightness:F_(e.sceneBrightness,t.sceneBrightness,n),architectureOpacity:F_(e.architectureOpacity,t.architectureOpacity,n),backdropOpacity:F_(e.backdropOpacity,t.backdropOpacity,n),viewWeight:F_(e.viewWeight,t.viewWeight,n),editorWeight:F_(e.editorWeight,t.editorWeight,n),toolbarContentOpacity:F_(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 W_={now:()=>"undefined"!=typeof performance?performance.now():Date.now(),requestFrame:e=>"function"==typeof requestAnimationFrame?requestAnimationFrame(e):null,cancelFrame:e=>{"function"==typeof cancelAnimationFrame&&cancelAnimationFrame(e)}},j_=e=>Number.isFinite(e);function U_(e){return!!e&&j_(e.zoom)&&e.zoom>0&&j_(e.viewBox.x)&&j_(e.viewBox.y)&&j_(e.viewBox.w)&&e.viewBox.w>0&&j_(e.viewBox.h)&&e.viewBox.h>0}function V_(e){return{zoom:e.zoom,viewBox:{...e.viewBox}}}function G_(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 K_=(e,t,i)=>e+(t-e)*i,Y_=(e,t,i)=>Math.exp(K_(Math.log(e),Math.log(t),i));class X_{constructor(e,t=W_){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=V_(e),s=V_(t),a=n>0&&U_(o)&&U_(s),l=this._clock.now(),c={token:r,phase:a?"running":"settling",from:o,to:s,presented:V_(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?V_(t.to):function(e,t,i){if(!U_(e))return V_(t);if(!U_(t))return V_(e);const n=E_(i);if(n<=0)return V_(e);if(n>=1)return V_(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=Y_(e.viewBox.w,t.viewBox.w,n),c=Y_(e.viewBox.h,t.viewBox.h,n),h=K_(r,s,n),d=K_(o,a,n);return{zoom:Y_(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=V_(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=V_(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=V_(t.to),this._hooks.settled(t),this._state?.token===e&&(this._state=null))}}function Z_(e,t){return`${e("editor.load_failed")} ${e(t.terminal?"editor.refresh_advice":"editor.retry_advice")}`}class J_ extends Error{}class Q_{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 J_(`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 J_&&(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 ef="houseplan_card_labs_v1",tf=Object.freeze([Object.freeze({id:"iso",issue:89,since:"1.62.0",expires:"1.65.0",summary:"Volumetric plan renderer"})]);function nf(e){const t=/^(\d+)\.(\d+)\.(\d+)(?:-[0-9A-Za-z.-]+)?$/.exec(String(e||"").trim());if(!t)return null;const i=t.slice(1).map(Number);return i.every(e=>Number.isSafeInteger(e))?i:null}function rf(e,t){for(let i=0;i<3;i++)if(e[i]!==t[i])return e[i]e.split(",")).map(e=>e.trim()).filter(Boolean)}function hf(e,t,i,n=tf){const r=function(e,t=tf){const i=nf(e),n=new Map;if(!i||!sf(t))return n;for(const e of t){const t=nf(e.since),r=nf(e.expires);rf(i,t)>=0&&rf(i,r)<0&&n.set(e.id,e)}return n}(i,n),o=new Set(sf(n)?n.map(e=>e.id):[]),s=new Set(function(e){if(!e)return[];try{const t=JSON.parse(e);return Array.isArray(t)?t.filter(e=>"string"==typeof e):[]}catch{return[]}}(t).filter(e=>r.has(e)));let a=!1;const l=e=>{if("off"===e)return s.clear(),void(a=!0);const t=e.startsWith("-"),i=t?e.slice(1):e;o.has(i)&&(a=!0,t||!r.has(i)?s.delete(i):s.add(i))};for(const t of cf(new URLSearchParams(String(e.search||"").replace(/^\?/,""))))l(t);for(const t of cf(af(e.hash)))l(t);const c=Object.freeze([...s].sort());return{active:c,space:lf(e.hash),persist:a?JSON.stringify(c):void 0,knownUrlOperation:a}}let df={active:Object.freeze([]),space:""},uf="",pf=!1,mf="";const _f=new Set;function ff(){if("undefined"==typeof window)return df;const e=hf(window.location,function(){try{return window.localStorage.getItem(ef)}catch{return null}}(),uf);void 0!==e.persist&&function(e){try{window.localStorage.setItem(ef,e)}catch{}}(e.persist),df={active:e.active,space:e.space},window.__hpLabs=e.active;for(const e of _f)e(df);return df}function gf(){ff()}function vf(e){if(uf=e,"undefined"==typeof window)return df;if(!pf){pf=!0,window.__hpLabsListenerCleanup?.(),window.addEventListener("hashchange",gf),window.addEventListener("popstate",gf);const e=()=>{window.removeEventListener("hashchange",gf),window.removeEventListener("popstate",gf),window.__hpLabsListenerCleanup===e&&delete window.__hpLabsListenerCleanup};window.__hpLabsListenerCleanup=e}return ff()}const yf=Object.freeze({rotDeg:0,tiltDeg:20,xyScale:1,zScale:1,origin:Object.freeze([500,500])});function bf(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 wf(e,t,i=yf){if(!(bf(i)&&Number.isFinite(e[0])&&Number.isFinite(e[1])&&Number.isFinite(t)))throw new Error("invalid isometric projection input");const n=i.rotDeg*Math.PI/180,r=i.tiltDeg*Math.PI/180,o=e[0]-i.origin[0],s=e[1]-i.origin[1],a=(o*Math.cos(n)-s*Math.sin(n))*i.xyScale,l=(o*Math.sin(n)+s*Math.cos(n))*i.xyScale;return[i.origin[0]+a,i.origin[1]+l*Math.cos(r)-t*i.zScale*Math.sin(r)]}function kf(e,t=yf){if(!bf(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 xf(e=yf){return`matrix(${function(e=yf){if(!bf(e))throw new Error("invalid isometric camera");const t=e.rotDeg*Math.PI/180,i=e.tiltDeg*Math.PI/180,n=e.xyScale*Math.cos(t),r=-e.xyScale*Math.sin(t),o=e.xyScale*Math.sin(t)*Math.cos(i),s=e.xyScale*Math.cos(t)*Math.cos(i);return[n,o,r,s,e.origin[0]-n*e.origin[0]-r*e.origin[1],e.origin[1]-o*e.origin[0]-s*e.origin[1]]}(e).map(e=>Number(e.toFixed(12))).join(" ")})`}function $f(e,t=yf){const{rect:i,wallHeight:n}=e,r=e.openingHeight??n,o=e.floorDepth??0;if(!(i.w>=0)||!(i.h>=0)||!Number.isFinite(n)||!Number.isFinite(r)||!Number.isFinite(o)||n<0||r<0||o<0)throw new Error("invalid isometric frame");const s=[[i.x,i.y],[i.x+i.w,i.y],[i.x+i.w,i.y+i.h],[i.x,i.y+i.h]],a=Math.max(n,r),l=s.flatMap(e=>[wf(e,-o,t),wf(e,a,t)]),c=l.map(e=>e[0]),h=l.map(e=>e[1]),d=Math.min(...c),u=Math.min(...h);return{x:d,y:u,w:Math.max(...c)-d,h:Math.max(...h)-u}}const Sf=e=>`${Number(e[0].toFixed(4))} ${Number(e[1].toFixed(4))}`;function Mf(e){let t=0;for(let i=0;iArray.isArray(e)&&Number.isFinite(e[0])&&Number.isFinite(e[1])).map(e=>[Number(e[0]),Number(e[1])]),i=t[t.length-1];return t.length>1&&t[0][0]===i[0]&&t[0][1]===i[1]&&t.pop(),t}(e);if(i.length<3)return[];const n=!t;return Mf(i)>0===n?i:[...i].reverse()}function Tf(e,t,i){return e.length?`M ${e.map(e=>Sf(wf(e,i,t))).join(" L ")} Z`:""}function Rf(e,t,i){const n=t[1]-e[1],r=-(t[0]-e[0]),o=i.rotDeg*Math.PI/180;return n*Math.sin(o)+r*Math.cos(o)}function Df(e,t,i=yf){if(!Number.isFinite(t)||t<0)throw new Error("invalid floor edge height");const n=(e||[]).map(e=>(e||[]).map((e,t)=>function(e,t){const i=Cf(e,t);if(!i.length)return i;let n=0;for(let e=1;e0)).filter(e=>e.length>=3&&Math.abs(Mf(e))>=1e-9)).filter(e=>e.length&&Mf(e[0])>0);n.sort((e,t)=>{const i=e[0][0],n=t[0][0];return i[0]-n[0]||i[1]-n[1]||Math.abs(Mf(t[0]))-Math.abs(Mf(e[0]))});const r=[],o=[];let s=0;for(let e=0;ee.depth-t.depth||e.component-t.component||e.edge-t.edge),{footprintPath:r.join(" "),sides:o,componentCount:n.length,edgeCount:s}}function zf(e,t){return e^=Math.round(64*(Number.isFinite(t)?t:0)),Math.imul(e,16777619)>>>0}const Af=e=>e.every(Number.isFinite);function Pf(e,t,i,n){const r=e[0]*i,o=e[1]*n,s=t*Math.PI/180;return[r*Math.cos(s)-o*Math.sin(s),r*Math.sin(s)+o*Math.cos(s)]}function Of(e,t,i,n,r,o,s){const a=e.flipH?-1:1,l="gate"===e.type?1:e.flipV?-1:1,c=(e.type,e.flipV,e.angle,e.face,{ox:0,oy:0}),h=function(e,t){return[e[0]+t[0],e[1]+t[1]]}([e.x+c.ox,e.y+c.oy],Pf(i,e.angle,a,l));return{leaf:t,hinge:h,closedVector:Pf(n,e.angle,a,l),quarterVector:Pf([-n[1],n[0]],e.angle,a,l),turnDeg:r,bottom:o,top:s}}const Ff=e=>`${Number(e[0].toFixed(4))} ${Number(e[1].toFixed(4))}`;function If(e,t,i=yf){const n=Math.max(0,Math.min(1,Number.isFinite(t)?t:0));return e.leaves.map(t=>{const r=function(e,t){const i=e.turnDeg*t*Math.PI/180;return[e.hinge[0]+e.closedVector[0]*Math.cos(i)+e.quarterVector[0]*Math.sin(i),e.hinge[1]+e.closedVector[1]*Math.cos(i)+e.quarterVector[1]*Math.sin(i)]}(t,n),o=wf(t.hinge,t.bottom,i),s=wf(r,t.bottom,i),a=wf(r,t.top,i),l=wf(t.hinge,t.top,i);return{id:e.id,sourceIndex:e.sourceIndex,type:e.type,leaf:t.leaf,d:`M ${Ff(o)} L ${Ff(s)} L ${Ff(a)} L ${Ff(l)} Z`,shadowD:`M ${Ff(wf(t.hinge,0,i))} L ${Ff(wf(r,0,i))}`,depth:Math.max(o[1],s[1])}})}const Ef={window:120,door:90,passage:90,gate:300};function Hf(e){return Ef[e]}function Nf(e,t){return{type:e,lengthCm:Hf(e),flipH:!1,flipV:!1,revision:t}}function Lf(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 Bf(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 qf(e){const t=new Map;return e.forEach((e,i)=>{if(!e.kind||e.open)return;const n=Bf(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 Wf(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 jf(e){const t=qf(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=Bf(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,m=1e-9;if(!(p<=m||p>=h-m)&&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(Wf),n=t.filter(t=>!t.target.partitionHost||e.renderedLength+2*t.target.physicalHalfWidth<=t.length+1e-9).sort(Wf);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,m=Math.min(Math.max(0,e.renderedLength)/2+p,l/2);let _=r.along;const f=Math.max(e.gridStep,1e-9),g=l/2;_=Math.abs(_-g)<=f/2?g:Math.round(_/f)*f,_=Math.max(m,Math.min(l-m,_));const v=a.a[0]+d*_,y=a.a[1]+u*_,b=Math.max(0,e.renderedLength)/2,w=_-b,k=_+b,x=Math.max(0,w),$=Math.max(0,l-k),S=[a.a[0]+d*(w-x/2),a.a[1]+u*(w-x/2)],M=[a.a[0]+d*(k+$/2),a.a[1]+u*(k+$/2)];let C=180*Math.atan2(h,c)/Math.PI;C>=90?C-=180:C<-90&&(C+=180);const T=Math.abs(_-g)<=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:C,renderedLength:e.renderedLength,target:a,...a.partitionHost?{host:{...a.partitionHost,t:l>0?_/l:0}}:{},measure:{labels:[{distance:x,midpoint:S},{distance:$,midpoint:M}],guide:T?{x:v,y:y,angle:C}:null}},jambBlockedTarget:null}}function Uf(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 Vf(e){return!(!e.canEdit||e.kiosk||e.fixedFloor)&&("view"!==e.mode&&("mouse"===e.pointerType&&e.spaceCount>1))}let Gf=0;const Kf="1.71.0-beta.2",Yf="bd7029808eb6094140d9fa8245f50816cb452430a353f4231d16e02c97078a06",Xf=1500,Zf=(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}},Jf=(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)}},Qf=new Map;let eg=0;const tg=e=>`${window.innerWidth}x${window.innerHeight}|${location.pathname}|${JSON.stringify(e??{})}`;let ig=1e4;const ng="houseplan_card_layout_v1",rg="houseplan_card_cfg_v1",og="houseplan_card_zoom_v1",sg="houseplan_card_nav_v1",ag="houseplan_card_kiosk_v1",lg="houseplan_card_view_v1",cg="hp-dialog, hp-help, hp-color-opacity, hp-device-preview",hg=1e3,dg=(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}},ug=new Set(["select","draw","column","merge","split","resize","opening","wallthick","delroom"]),pg=(e,t,i)=>{const n=new Event(t,{bubbles:!0,composed:!0});n.detail=i??{},e.dispatchEvent(n)},mg=e=>{history.pushState(null,"",e),pg(window,"location-changed",{replace:!1})},_g=(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},fg=e=>{try{e.target?.setPointerCapture?.(e.pointerId)}catch{}},gg=["edges","corners"];class vg extends he{constructor(){super(...arguments),this._editorRuntime=null,this._onboardingRuntime=null,this._editorRuntimeLoadingVisible=!1,this._backdropGuard=null,this._editorModeRequest=0,this._warmModeRequest=0,this._editorRuntimeLoader=new Q_({expectedFingerprint:Yf,load:async e=>{const t=0===e?await import("./houseplan-editor-runtime-CmI5Go3m.js"):await import((()=>{const e=new URL("./houseplan-editor-runtime-CmI5Go3m.js",import.meta.url);return e.searchParams.set("hp_retry",`${Kf}-${++Gf}`),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),this._showToast(Z_(e=>this._t(e),t))}}),this._onboardingRuntimeLoader=new Q_({expectedFingerprint:Yf,load:async e=>{const t=0===e?await import("./houseplan-onboarding-runtime-BB8OHZOL.js"):await import((()=>{const e=new URL("./houseplan-onboarding-runtime-BB8OHZOL.js",import.meta.url);return e.searchParams.set("hp_retry",`${Kf}-${++Gf}`),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),this._showToast(Z_(e=>this._t(e),t))}}),this._space="f1",this._layout={},this._serverStorage=!1,this._loadOk=!1,this._serverCanWrite=null,this._loading=!1,this._loadTries=0,this._serverCfg=null,this._cfgRev=0,this._cfgContentFingerprint="",this._unsubCfg=null,this._unsubLayout=null,this._unsubVirtual=null,this._liveSyncAttempt=null,this._liveSyncGeneration=0,this._liveSyncConnection=null,this._layoutRev=0,this._layoutContentFingerprint="",this._virtualLights=Jc(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 g_(this,()=>this._syncPointerHoverTargets()),this._devicePressAnimations=new Map,this._selId=null,this._toast="",this._mode="view",this._pendingNavMode=null,this._decorTool="select",this._decorStyle={...rr},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.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 q_({frame:e=>this._applyModeTransitionFrame(e),settled:e=>this._settleModeTransition(e)}),this._cameraTransitionFit=null,this._cameraTransition=new X_({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 D_(50),this._devicePositionHistory=new D_(50),this._devicePositionBusy=!1,this._wallDialog=null,this._drawWallField=null,this._activeDraftId=null,this._resumeDraftBySpace={},this._physicalSel=null,this._physicalDialog=null,this._partitionDeleteDialog=null,this._roomDeleteDialog=null,this._physicalDrag=null,this._physicalRotate=null,this._physicalLastTap=null,this._physicalPickCycle=null,this._wallUnionCacheValue=null,this._wallUnionPool=new Map,this._isoGeometryCache=new Map,this._isoFallback=new Set,this._openingTunnelCache=null,this._openingWallIndexCache=new Map,this._openingPlacementIntervalsCache=null,this._openingDimensionContextCache=null,this._planSnapGeometryCache=null,this._planStructuralGeometryCache=null,this._hiddenWallDiagnosticCache=null,this._physicalBodiesCache=null,this._lightPhysicalBodiesCache=null,this._cleanFloorCache=new Map,this._innerContourCache=new Map,this._glowRuntimeState=zm(),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._roomTempSrc="",this._roomHumSrc="",this._roomSrcOpen=null,this._roomSrcFilter="",this._roomNameScale=1,this._roomLabelScale=1,this._zoom=1,this._view=null,this._zoomBySpace={},this._viewModeSnap=null,this._pointers=new Map,this._panStart=null,this._panLock=null,this._pinchStart=null,this._suppressClick=!1,this._touchContacts=new Map,this._touchSequenceMultitouch=!1,this._touchClickBlockUntil=0,this._connectedPath="",this._routeDepartureHandled=!1,this._onLocationChanged=()=>{this._connectedPath&&location.pathname!==this._connectedPath?this._leaveCardRoute():location.pathname===this._connectedPath&&(this._routeDepartureHandled=!1)},this._touchGestureGuard={capture:!0,handleEvent: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 fe(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._haSupportApi=null,this._haDecorAssetsApi=null,this._decorAssetSyncToken=0,this._alignDialog=null,this._settingsDialog=null,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=++eg,this._warmKey=null,this._warmSlot=null,this._hashApplied=!1,this._navApplied=!1,this._labs={active:Object.freeze([]),space:""},this._viewPreference={},this._renderProjection="flat",this._kioskScale={icon:1,font:1},this._kioskDialog=!1,this._activityRt=new Map,this._vacRt=new Map,this._vacViewKey="",this._vacLastView=null,this._vacRaf=0,this._vacSrvTrails={},this._vacJumpOnce=!1,this._continuity=this._newContinuityController(),this._continuityHistory=[],this._continuityEpoch=0,this._continuityDataReady=!0,this._continuityPaintToken=-1,this._continuityDisposed=!1,this._renderSnapshotAt=Date.now(),this._hassSequence=0,this._visibleDeviceSnapshot=null,this._candidateDeviceSnapshot=null,this._stagedDeviceSnapshotToken=-1,this._capturedSnapshotSequence=-1,this._capturedSnapshotDevices=null,this._capturedSnapshotLayout=null,this._capturedSnapshotActivity="",this._capturedSnapshotConfigEpoch=-1,this._capturedSnapshotVirtual="",this._lastValidStageSize=null,this._pendingRefitSize=null,this._refitRaf=0,this._pageVisibility=e=>{if(this._continuity.visibility(e),this._dayCycleVisibility(e),"hidden"===e.kind)return this._clearTransientHover(!0),this._cancelDevicePressFeedback(),this._cancelCameraTransition(!0),void(this._modeTransitionPreparing?this._modeTransitionForceAtomic=!0:this._cancelModeTransition(!0));if(this._vacJumpOnce=!0,!e.long){const e=Date.now();let t=!1;for(const i of this._activityRt.values())!i.flashKind||(i.expiresAt||i.flashTs+u_)>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._lastTap=0,this._onLabsSnapshot=e=>{const t=this._effectiveProjection();this._labs=e;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._activeDraftId&&(this._resumeDraftBySpace[this._space]=this._activeDraftId),this._commitSpace(e),this._selId=null,this._path=[],this._clearPlanSnapHover(),this._clearOpeningPlacement(!0),this._tool="draw",this._activeDraftId=null,this._draftSegmentCms=[],this._closingWallCm=null,"plan"===this._mode&&"draw"===this._tool&&this._resumeLastDraft(),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._modelCache=null,this._emptySpaceStateActive=!1,this._decorSnapCache=null,this._markerPreviewMemo=null,this._markerPreviewDevicesMemo=null,this._showHidden=!1,this._connHooked=null,this._connectionWasLost=!1,this._haRegistryConnection=null,this._haRegistryRev=-1,this._haBindingCacheKey="",this._planHassMemo=null,this._onHaRegistryUpdate=()=>{const e=gh(this.hass);e.revision===this._haRegistryRev&&this._devices.length||(this._haRegistryRev=e.revision,this._planHassMemo=null,this._regSignature="",this._maybeRebuildDevices(),this.requestUpdate())},this._onConnReady=()=>{if(this._loadTries=0,clearTimeout(this._loadRetryTimer),this._loadRetryTimer=void 0,fh(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 Wl(()=>this.requestUpdate()),this._dirtyPos=new Set,this._sentPos=new Map,this._persistLayout=_g(()=>{if(this._serverStorage){const e=[...this._dirtyPos];this._dirtyPos.clear();for(const t of e){const e=Qr(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=_g(()=>{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._draftSegmentCms=[],this._closingWallCm=null,this._savePhysicalDialog=()=>this._editorRuntimeOrThrow()._savePhysicalDialog(),this._deletePhysicalSelection=()=>this._editorRuntimeOrThrow()._deletePhysicalSelection(),this._confirmPartitionDelete=()=>this._editorRuntimeOrThrow()._confirmPartitionDelete(),this._deleteDraftWhole=()=>this._editorRuntimeOrThrow()._deleteDraftWhole(),this._deleteDraftSegment=()=>this._editorRuntimeOrThrow()._deleteDraftSegment(),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=qn(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._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}_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()}_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)}_seedDecorStyle(e){if(this._decorStyleSeeded||!e)return;this._decorStyleSeeded=!0;const t=e.settings?.decor_default_style;t&&(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:or(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:or(i.fill_opacity,t.fillOpacity)}}(t,rr))}get _canEdit(){return!!this._norm&&(!0===this._serverCanWrite||!1!==this._serverCanWrite&&!0===this.hass?.user?.is_admin)}get _kiosk(){return!!this._config?.kiosk}_showKioskDots(){this._kioskDots=!0,clearTimeout(this._kioskDotsTimer),this._kioskDotsTimer=window.setTimeout(()=>this._kioskDots=!1,2500)}get _modeTransitionBusy(){return this._modeTransitionPreparing||this._modeTransition.active}_cameraState(){const e=this._viewOr(this._baseVb());return{zoom:this._zoom,viewBox:{...e}}}_normalizeCameraState(e){const t=this._cameraTransitionFit||vi(this._baseVb(),this._stageAspect());return{zoom:Math.min(vg.ZOOM_MAX,Math.max(vg.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.requestUpdate()}_settleCameraTransition(e){const t=this._normalizeCameraState(e.to);this._zoom=t.zoom,this._view={...t.viewBox},this._cameraTransitionFit=null,this._saveZoom(),this.requestUpdate()}_cancelCameraTransition(e=!1,t=!1){const i=t&&this._cameraTransition.active?this._cameraTransition.presented?.zoom:void 0;this._cameraTransition.cancel(e),this._cameraTransitionFit=null,void 0!==i&&this._saveZoom()}_prepareCameraCommand(){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||!G_(o,e))&&(G_(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:H_(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=vi(this._baseVb(),n/Math.max(1,r)),s=Math.min(vg.ZOOM_MAX,Math.max(vg.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){this._cancelModeTransition(!1),this._mode=e,"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"),a=s?.querySelector(".editorchrome-inner"),l="view"===i?0:a?.scrollHeight||a?.getBoundingClientRect().height||0,c=Math.max(1,t.stageHeight+t.editorChromeHeight),h=Math.max(1,c-l),d=this._stageEl?.clientWidth||t.stageWidth;if(d<=0||h<=0)return this._modeTransitionPreparing=!1,this._modeTransitionVisual=null,this._applyView(n,r,o),void this.requestUpdate();const u=this._viewForModeTarget(n,r,o,d,h),p={presentedMode:i,editorChromeHeight:l,stageWidth:d,stageHeight:h,viewport:H_(u,d),stageColor:this._targetStageColor(i),paperColor:this._targetPaperColor(i),sceneBrightness:this._targetBrightness(i),architectureOpacity:"decor"===i?.35:1,backdropOpacity:"decor"===i&&"backdrop"!==this._decorTool?.5:1,viewWeight:"view"===i?1:0,editorWeight:"view"===i?0:1,toolbarContentOpacity:"view"===i?0:1};this._modeTransitionPreparing=!1;const m=this._modeTransitionForceAtomic;this._modeTransitionForceAtomic=!1,this._modeTransition.start(t,p,i,this._reducedMotion||m?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._cancelDangerConfirm(),this._cancelCameraTransition(!1),this._clearTransientHover(!0),this._cancelDevicePressFeedback(),this._editorRuntime?._clearFurniturePreview()),this._space=e,!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._activeDraftId&&(this._resumeDraftBySpace[this._space]=this._activeDraftId),this._commitSpace(e),this._path=[],this._clearPlanSnapHover(),this._clearOpeningPlacement(!0),this._tool="draw",this._activeDraftId=null,this._draftSegmentCms=[],this._closingWallCm=null,this._selId=null,this._physicalSel=null,this._editorSecondary?.closeForNavigation(),this._physicalDialog=null,this._physicalDrag=null,"plan"===this._mode&&"draw"===this._tool&&this._resumeLastDraft(),this._restoreZoom(),i||(this._slide=t,clearTimeout(this._slideTimer),this._slideTimer=window.setTimeout(()=>{this._slideTimer=void 0,this._slide="",this.requestUpdate()},190),this.requestUpdate()),!0}get _canReorderTabs(){return Vf({canEdit:this._canEdit,kiosk:this._kiosk,mode:this._mode,pointerType:"mouse",spaceCount:this._model.length,fixedFloor:this._hasFixedFloor})}_tabPointerDown(e,t){Vf({canEdit:this._canEdit,kiosk:this._kiosk,mode:this._mode,pointerType:e.pointerType,spaceCount:this._model.length,fixedFloor:this._hasFixedFloor})&&(fg(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?mu(this,yu,Su(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()}_newContinuityController(){return new Nl(()=>{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(lg,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?kf(i):i;return{x:n[0],y:n[1]}}_convertProjectionView(e,t){if(e===t)return;const i=this._logicalViewCenter(e);this._view=null;const n=i?"iso"===t?wf([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){const e=this._isoSceneKey();e&&this._isoFallback.delete(e)}this._saveViewPreference();const i=this._effectiveProjection();this._convertProjectionView(t,i)}_hashSpace(){return lf(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=k_(this.ownerDocument);var t;void 0!==e&&(this._glowScreenBlend=e),this._continuityUnsub?.(),this._continuityUnsub=El(this.ownerDocument,this._pageVisibility),this._languageFailureUnsub?.(),this._languageFailureUnsub=(t=()=>{this._showToast(this._t("toast.locale_load_failed"))},vu.add(t),()=>vu.delete(t)),super.connectedCallback(),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),w_(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,t){_f.add(t);const i=vf(e);return"undefined"==typeof window&&t(i),()=>{_f.delete(t)}}(Kf,this._onLabsSnapshot),this._booting?this._bootWatch():this._bootFading&&(clearTimeout(this._bootTimer),this._bootTimer=window.setTimeout(()=>{this._bootFading=!1},220)),this._bootSoft&&(clearTimeout(this._bootSoftTimer),this._bootSoftTimer=window.setTimeout(()=>{this._bootSoft=!1},Xf)),!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._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._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),jm(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)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=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._supportDialog)return void this._editorRuntime?._closeSupportDialog();if(this._settingsDialog)return void(this._settingsDialog=null);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;return c?(e.preventDefault(),void this._redoGeometry()):h?(e.preventDefault(),this._decorDraft?void(this._decorDraft=null):this._decorMove||this._dtDrag||this._bdDrag?void this._cancelDecorGesture():void this._undoGeometry()):"Delete"!==e.key&&"Backspace"!==e.key||!this._decorSel||i||n?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._decorDeleteSel())}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._activeDraftId&&this._path.length>1?this._undoActiveDraftPoint():this._undoPoint())):"draw"===this._tool&&this._path.length?void(this._activeDraftId&&this._path.length>1?this._undoActiveDraftPoint():this._undoPoint()):"split"===this._tool&&this._splitSel?.pts?.length?(this._splitSel={...this._splitSel,pts:this._splitSel.pts.slice(0,-1)},void(this._splitSel.pts.length||(this._cursorPt=null))):void this._undoGeometry();if("Escape"===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){if(this._contourClosed)return this._path=this._path.slice(0,-1),void(this._closingWallCm=null);if(this._activeDraftId&&this._path.length>1&&this._curSpaceCfg){const e=this._geometrySnapshot();this._path=this._path.slice(0,-1),this._draftSegmentCms=this._draftSegmentCms.slice(0,-1);const t=this._curSpaceCfg,i=(t.room_drafts||[]).findIndex(e=>e.id===this._activeDraftId);if(i>=0){const n=Array.isArray(t.room_drafts[i]?.segments)?t.room_drafts[i].segments:[];this._path.length<2?(t.room_drafts.splice(i,1),t.room_drafts.length||delete t.room_drafts,this._activeDraftId=null):t.room_drafts[i]={id:this._activeDraftId,points:this._path.map(e=>[e[0]/hg,e[1]/hg]),segments:this._draftSegmentCms.map((e,t)=>({...n[t]||{},cm:e}))},this._commitPhysicalGeometry(this._t("history.draft_segment_delete"),e)}return}this._path=this._path.slice(0,-1)}}_undoActiveDraftPoint(){const e=this._activeDraftId,t=this._path[0]?[...this._path[0]]:null,i=this._geometryHistory.undo();if(!i)return void this._undoPoint();if(!this._applyGeometryState(i.before,!0))return void this._geometryHistory.clear();const n=e?this._spaceModel()?.room_drafts.find(t=>t.id===e):null;n?(this._activeDraftId=n.id,this._path=n.points.map(e=>[...e]),this._draftSegmentCms=this._adoptDraftCms(this._path,n.segments.map(e=>e.cm),n.id),this._resumeDraftBySpace[this._space]=n.id):(this._activeDraftId=null,this._path=t?[t]:[],this._draftSegmentCms=[],e&&this._resumeDraftBySpace[this._space]===e&&delete this._resumeDraftBySpace[this._space]),this._clearPlanSnapHover(),this._showToast(this._t("history.undone",{name:i.name}))}static async getConfigElement(){return await import("./editor-CxXW-QO8.js"),document.createElement("houseplan-card-editor")}static getStubConfig(){return{type:"custom:houseplan-card"}}static _warmBootReset(e){for(const e of Qf.values())for(const t of e)clearTimeout(t.evict);Qf.clear(),ig=e&&e>0?e:1e4}static _warmBootStats(){let e=0,t=0;const i=[];for(const n of Qf.values())for(const r of n)e++,r.dlg&&(t++,i.push(r.dlg.kind));return{keys:Qf.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(og)||"{}")||{}}catch{this._zoomBySpace={}}try{const e=JSON.parse(localStorage.getItem(lg)||"{}")||{};this._viewPreference=Object.fromEntries(Object.entries(e).filter(e=>"flat"===e[1]||"iso"===e[1]))}catch{this._viewPreference={}}this._labs=vf(Kf);try{const e=JSON.parse(localStorage.getItem(ag)||"null");this._kioskScale={icon:kn(e?.icon),font:kn(e?.font)}}catch{}try{const e=JSON.parse(localStorage.getItem(rg)||"null");e&&e.config&&Array.isArray(e.config.spaces)&&(this._serverCfg=e.config,this._seedDecorStyle(this._serverCfg),this._cfgEpoch++,this._cfgRev=e.rev||0,this._cfgContentFingerprint=e.config_fingerprint||Ll(e.config),this._layout=e.layout||{},this._layoutRev=e.layout_rev||0,this._layoutContentFingerprint=e.layout_fingerprint||Ll(this._layout),this._virtualLights=Jc(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)}_warmAdopt(){if(this._config?.kiosk)return;const e=tg(this._config);if(this._warmKey===e&&this._warmSlot)return;this._warmSlot&&this._warmRelease();const t=this.parentNode,i=this._warmIdx(t),n=Qf.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>=Ol,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>=Ol,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},Xf)),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=Qf.get(t);if(!e.live&&o&&o.length>1){const t=o.indexOf(e);t>=0&&o.splice(t,1)}},ig+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?wf([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&&ug.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=tg(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=Qf.get(i)||[];for(n.push(this._warmSlot),Qf.set(i,n),this._warmTrim(n);Qf.size>8;){const e=Qf.keys().next().value;if(void 0===e||e===i)break;for(const t of Qf.get(e)||[])clearTimeout(t.evict);Qf.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,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};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>ig)&&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._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._activeDraftId=this._wallFaceBatch.activeDraftId,this._draftSegmentCms=[...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._cfgContentFingerprint=Ll(this._serverCfg),this._layoutContentFingerprint=Ll(this._layout),this._virtualLights=function(e,t,i){if(e.configRev===i)return e;const n=new Set((Array.isArray(t?.markers)?t.markers:[]).filter(ih).map(e=>e.id));return{...e,configRev:i,off:new Set([...e.off].filter(e=>n.has(e)))}}(this._virtualLights,this._serverCfg,this._cfgRev),localStorage.setItem(rg,JSON.stringify({config:this._serverCfg,rev:this._cfgRev,config_fingerprint:this._cfgContentFingerprint,layout:this._layout,layout_rev:this._layoutRev,layout_fingerprint:this._layoutContentFingerprint,virtual_lights:eh(this._virtualLights)}))}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}_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=Ra(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 Bl([this._cfgRev,this._cfgContentFingerprint||Ll(this._serverCfg),this._layoutRev,this._layoutContentFingerprint||Ll(this._layout),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 W`
e.stopPropagation()}
@click=${e=>e.stopPropagation()}
diff --git a/custom_components/houseplan/frontend/houseplan-assets/houseplan-editor-runtime-CmI5Go3m.js b/custom_components/houseplan/frontend/houseplan-assets/houseplan-editor-runtime-o7FB8qC-.js
similarity index 85%
rename from custom_components/houseplan/frontend/houseplan-assets/houseplan-editor-runtime-CmI5Go3m.js
rename to custom_components/houseplan/frontend/houseplan-assets/houseplan-editor-runtime-o7FB8qC-.js
index a96847ec..2b2b92cd 100644
--- a/custom_components/houseplan/frontend/houseplan-assets/houseplan-editor-runtime-CmI5Go3m.js
+++ b/custom_components/houseplan/frontend/houseplan-assets/houseplan-editor-runtime-o7FB8qC-.js
@@ -1,4 +1,4 @@
-globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="bd7029808eb6094140d9fa8245f50816cb452430a353f4231d16e02c97078a06";import{e as t,i as e,E as s,s as i,a as o,n as a,f as n,b as r,l,o as h,r as c,A as d,c as p,d as u,g as _,h as m,j as g,t as f,w as b,k as v,m as y,v as $,p as w,q as k,u as x,x as S,y as M,z as D,B as C,C as P,D as I,F as T,G as R,H as z,I as A,J as F,K as N,L as H,M as L,N as E,O,P as B,Q as W,R as G,S as j,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 Dt,as as Ct,at as Pt,au as It,av as Tt,aw as Rt,ax as zt,ay as At,az as Ft,aA as Nt,aB as Ht,aC as Lt,aD as Et,aE as Ot,aF as Bt,aG as Wt,aH as Gt,aI as jt,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 De,bi as Ce,bj as Pe,bk as Ie,bl as Te,bm as Re,bn as ze,bo as Ae,bp as Fe,bq as Ne,br as He,bs as Le,bt as Ee,bu as Oe,bv as Be,bw as We,bx as Ge,by as je,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 Ds,c8 as Cs,c9 as Ps,ca as Is,cb as Ts,cc as Rs,cd as zs,ce as As,cf as Fs,cg as Ns,ch as Hs,ci as Ls,cj as Es,ck as Os,cl as Bs,cm as Ws,cn as Gs,co as js,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 Di,c_ as Ci,c$ as Pi,d0 as Ii,d1 as Ti,d2 as Ri,d3 as zi,d4 as Ai,d5 as Fi,d6 as Ni,d7 as Hi,d8 as Li,d9 as Ei,da as Oi,db as Bi,dc as Wi,dd as Gi,de as ji,df as qi,dg as Ui,dh as Ki,di as Vi,dj as Ji}from"./houseplan-card-BTXh6SvG.js";import{F as Yi,f as Xi,p as Zi,c as Qi,i as to,e as eo,r as so,a as io,b as oo,s as ao,t as no}from"./backdrop-pick-DxKIBNjn.js";const ro={},lo=t(class extends e{constructor(){super(...arguments),this.ot=ro}render(t,e){return e()}update(t,[e,i]){if(Array.isArray(e)){if(Array.isArray(this.ot)&&this.ot.length===e.length&&e.every((t,e)=>t===this.ot[e]))return s}else if(this.ot===e)return s;return this.ot=Array.isArray(e)?Array.from(e):e,this.render(e,i)}});var ho={"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_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."};const co={en:ho,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_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}» независимо от текущей карты."},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_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}“."},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_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."}};function po(t,e,s){return i(co[t]?.[e]??ho[e]??e,s)}function uo(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 _o(t,e,s){return t.map(t=>t.id===e?{...t,calibration:s}:t)}const mo=(t,e)=>{const s=(t._serverCfg?.spaces||[]).find(t=>t?.id===e);return String(s?.name||s?.id||e)};function go(t,e,s){const i=t.host,n=l(i.hass,i._config?.language),r=(t,e)=>po(n,t,e),u=e.marker?.vacuum||{},_=Array.isArray(u.map_routes)&&u.map_routes.length>0,m=i._vacSource(e)||"",g=o(e.id,u,e.space,m),f=(i._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=h(g,[m],t=>i._vacObservedMapId(e,t)),y=c({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=t=>{let i=_?u.map_routes:null;return!(!i&&(i=function(t,e,s,i){if(!s)return null;const o=t?.calibration;if(!o||"object"!=typeof o)return null;const n=new Set,r=[];for(const t of Object.keys(o)){const l=a(o[t]);if(!l)continue;const h=i(n);n.add(h),r.push({id:h,source:s,map_id:t,space:e,calibration:l})}return r.length?r:null}(u,e.space,m,t=>uo(t))??[],!m&&Object.keys(u.calibration||{}).length))&&(s({map_routes:t(i),calibration:void 0}),!0)},x=()=>new Set(g.map(t=>t.id)),S=new Map(f.map((t,e)=>[t.id,e])),M=[...g].sort((t,e)=>(S.get(t.space)??1e6)-(S.get(e.space)??1e6)||t.map_id.localeCompare(e.map_id)||t.source.localeCompare(e.source)),D=!!m&&void 0!==w&&!g.some(t=>t.source===m&&t.map_id===w);return p`
+globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="781b6de4892612660b01762cd408049137fa0d00417a43ef5bbdfb1ef37dc9a5";import{e as t,i as e,E as s,s as i,a as o,n as a,f as n,b as r,l,o as h,r as c,A as d,c as p,d as u,g as _,h as m,j as g,t as f,w as b,k as v,m as y,v as $,p as w,q as k,u as x,x as S,y as M,z as D,B as C,C as P,D as I,F as T,G as R,H as z,I as A,J as F,K as N,L as H,M as L,N as E,O,P as B,Q as W,R as G,S as j,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 Dt,as as Ct,at as Pt,au as It,av as Tt,aw as Rt,ax as zt,ay as At,az as Ft,aA as Nt,aB as Ht,aC as Lt,aD as Et,aE as Ot,aF as Bt,aG as Wt,aH as Gt,aI as jt,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 De,bi as Ce,bj as Pe,bk as Ie,bl as Te,bm as Re,bn as ze,bo as Ae,bp as Fe,bq as Ne,br as He,bs as Le,bt as Ee,bu as Oe,bv as Be,bw as We,bx as Ge,by as je,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 Ds,c8 as Cs,c9 as Ps,ca as Is,cb as Ts,cc as Rs,cd as zs,ce as As,cf as Fs,cg as Ns,ch as Hs,ci as Ls,cj as Es,ck as Os,cl as Bs,cm as Ws,cn as Gs,co as js,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 Di,c_ as Ci,c$ as Pi,d0 as Ii,d1 as Ti,d2 as Ri,d3 as zi,d4 as Ai,d5 as Fi,d6 as Ni,d7 as Hi,d8 as Li,d9 as Ei,da as Oi,db as Bi,dc as Wi,dd as Gi,de as ji,df as qi,dg as Ui,dh as Ki,di as Vi,dj as Ji}from"./houseplan-card-CuVuAiJj.js";import{F as Yi,f as Xi,p as Zi,c as Qi,i as to,e as eo,r as so,a as io,b as oo,s as ao,d as no,t as ro}from"./backdrop-pick-BJ59BurK.js";const lo={},ho=t(class extends e{constructor(){super(...arguments),this.ot=lo}render(t,e){return e()}update(t,[e,i]){if(Array.isArray(e)){if(Array.isArray(this.ot)&&this.ot.length===e.length&&e.every((t,e)=>t===this.ot[e]))return s}else if(this.ot===e)return s;return this.ot=Array.isArray(e)?Array.from(e):e,this.render(e,i)}});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_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."};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_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}» независимо от текущей карты."},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_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}“."},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_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."}};function uo(t,e,s){return i(po[t]?.[e]??co[e]??e,s)}function _o(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 mo(t,e,s){return t.map(t=>t.id===e?{...t,calibration:s}:t)}const go=(t,e)=>{const s=(t._serverCfg?.spaces||[]).find(t=>t?.id===e);return String(s?.name||s?.id||e)};function fo(t,e,s){const i=t.host,n=l(i.hass,i._config?.language),r=(t,e)=>uo(n,t,e),u=e.marker?.vacuum||{},_=Array.isArray(u.map_routes)&&u.map_routes.length>0,m=i._vacSource(e)||"",g=o(e.id,u,e.space,m),f=(i._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=h(g,[m],t=>i._vacObservedMapId(e,t)),y=c({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=t=>{let i=_?u.map_routes:null;return!(!i&&(i=function(t,e,s,i){if(!s)return null;const o=t?.calibration;if(!o||"object"!=typeof o)return null;const n=new Set,r=[];for(const t of Object.keys(o)){const l=a(o[t]);if(!l)continue;const h=i(n);n.add(h),r.push({id:h,source:s,map_id:t,space:e,calibration:l})}return r.length?r:null}(u,e.space,m,t=>_o(t))??[],!m&&Object.keys(u.calibration||{}).length))&&(s({map_routes:t(i),calibration:void 0}),!0)},x=()=>new Set(g.map(t=>t.id)),S=new Map(f.map((t,e)=>[t.id,e])),M=[...g].sort((t,e)=>(S.get(t.space)??1e6)-(S.get(e.space)??1e6)||t.map_id.localeCompare(e.map_id)||t.source.localeCompare(e.source)),D=!!m&&void 0!==w&&!g.some(t=>t.source===m&&t.map_id===w);return p`
- `}}export{Gl as EDITOR_RUNTIME_FINGERPRINT,jl as HouseplanEditorRuntime};
+ `}}export{jl as EDITOR_RUNTIME_FINGERPRINT,ql as HouseplanEditorRuntime};
diff --git a/custom_components/houseplan/frontend/houseplan-assets/houseplan-onboarding-runtime-BB8OHZOL.js b/custom_components/houseplan/frontend/houseplan-assets/houseplan-onboarding-runtime-CAJfA2x6.js
similarity index 98%
rename from custom_components/houseplan/frontend/houseplan-assets/houseplan-onboarding-runtime-BB8OHZOL.js
rename to custom_components/houseplan/frontend/houseplan-assets/houseplan-onboarding-runtime-CAJfA2x6.js
index 7b1086b8..651f96e7 100644
--- a/custom_components/houseplan/frontend/houseplan-assets/houseplan-onboarding-runtime-BB8OHZOL.js
+++ b/custom_components/houseplan/frontend/houseplan-assets/houseplan-onboarding-runtime-CAJfA2x6.js
@@ -1,4 +1,4 @@
-globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="bd7029808eb6094140d9fa8245f50816cb452430a353f4231d16e02c97078a06";import{l as t,aK as s,A as e,t as o,c as a,ca as l,cb as i,cc as h,cd as c,aH as n,ce as r,cj as p,cf as d,cg as _,ch as u,ci as g,db as m,aG as b,aI as $,dc as v}from"./houseplan-card-BTXh6SvG.js";import{i as f,c as y,e as w,r as D,a as k,b as S,s as C,t as M}from"./backdrop-pick-DxKIBNjn.js";const F=1e3,x=t=>{if(!t.trim())return null;const s=Number(t.replace(",","."));return Number.isFinite(s)?s:null},T="bd7029808eb6094140d9fa8245f50816cb452430a353f4231d16e02c97078a06";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)?a`{if(!t.trim())return null;const s=Number(t.replace(",","."));return Number.isFinite(s)?s:null},T="781b6de4892612660b01762cd408049137fa0d00417a43ef5bbdfb1ef37dc9a5";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)?a``: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 o=l(e),a=e.settings?.custom_fill&&"object"==typeof e.settings.custom_fill?i(e.settings.custom_fill):null,p="none"===o.fill?{...a||h,a:0}:a;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:o.showBorders,showNames:o.showNames,zeroWallStyle:r(e),displayTouched:!0,hideDecor:o.hideDecor,hideOpenings:o.hideOpenings,roomColor:o.color,roomOpacity:o.opacity,fillMode:"none"===o.fill?"custom":o.fill,customFill:p,glowEnabled:o.glow,bgColor:o.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:o.tempMin,tempMax:o.tempMax,showLqi:o.showLqi??this.host._config?.show_signal??!0,cardFontScale:o.cardFontScale,labelTemp:o.labelTemp,labelHum:o.labelHum,labelLqi:o.labelLqi,labelLight:o.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,...f(),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 o=await y(e);if("reject"===o.kind)return void this.host._showToast(this.host._t("toast.plan_formats"));if("guard"===o.kind)return void(this.host._backdropGuard=o.state);const a=await w(e,o.ext,e.name);this.host._spaceDialog&&(this.host._spaceDialog={...this.host._spaceDialog,planFile:a})}_renderBackdropGuard(){return D(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}),o=this.host._spaceDialog;return o&&o.planUrl===t&&Number.isFinite(e)&&e>0?(this.host._spaceDialog={...o,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 o=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")}),a=this.host._spaceDialog,l=a?.saved?.find(s=>s.name===t);if(o&&a&&l&&l.url===e.url&&l.modified===e.modified&&!l.used_by.length&&l.url!==a.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 a`
${this.host._t("space.loading")}
`;const s=t.saved||[];if(!s.length)return a`
${this.host._t("space.no_saved")}
`;return a`
${s.map(s=>{return a`
diff --git a/custom_components/houseplan/frontend/houseplan-card.js b/custom_components/houseplan/frontend/houseplan-card.js
index a8baeb43..21ed9334 100644
--- a/custom_components/houseplan/frontend/houseplan-card.js
+++ b/custom_components/houseplan/frontend/houseplan-card.js
@@ -1 +1 @@
-globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="bd7029808eb6094140d9fa8245f50816cb452430a353f4231d16e02c97078a06";try{await import("./houseplan-assets/houseplan-card-BTXh6SvG.js")}catch(e){if(!customElements.get("houseplan-card")){const l=String(navigator.language||"en").toLowerCase();const m=l.startsWith("ru")?"House Plan обновился — перезагрузите страницу (Ctrl+F5).":l.startsWith("de")?"House Plan wurde aktualisiert — bitte laden Sie die Seite neu (Strg+F5).":l.startsWith("fr")?"House Plan a été mis à jour — veuillez recharger la page (Ctrl+F5).":"House Plan was updated — please reload the page (Ctrl+F5).";customElements.define("houseplan-card",class extends HTMLElement{setConfig(){}getCardSize(){return 1}connectedCallback(){this.style.cssText="display:block;box-sizing:border-box;padding:16px;border:1px solid var(--divider-color,#e0e0e0);border-radius:var(--ha-card-border-radius,12px);background:var(--card-background-color,#fff);color:var(--primary-text-color,#212121);font:14px/1.4 var(--paper-font-body1_-_font-family,sans-serif)";this.textContent=m}})}console.error("[houseplan] stale entry: the main chunk is unavailable",e)}
+globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="781b6de4892612660b01762cd408049137fa0d00417a43ef5bbdfb1ef37dc9a5";try{await import("./houseplan-assets/houseplan-card-CuVuAiJj.js")}catch(e){if(!customElements.get("houseplan-card")){const l=String(navigator.language||"en").toLowerCase();const m=l.startsWith("ru")?"House Plan обновился — перезагрузите страницу (Ctrl+F5).":l.startsWith("de")?"House Plan wurde aktualisiert — bitte laden Sie die Seite neu (Strg+F5).":l.startsWith("fr")?"House Plan a été mis à jour — veuillez recharger la page (Ctrl+F5).":"House Plan was updated — please reload the page (Ctrl+F5).";customElements.define("houseplan-card",class extends HTMLElement{setConfig(){}getCardSize(){return 1}connectedCallback(){this.style.cssText="display:block;box-sizing:border-box;padding:16px;border:1px solid var(--divider-color,#e0e0e0);border-radius:var(--ha-card-border-radius,12px);background:var(--card-background-color,#fff);color:var(--primary-text-color,#212121);font:14px/1.4 var(--paper-font-body1_-_font-family,sans-serif)";this.textContent=m}})}console.error("[houseplan] stale entry: the main chunk is unavailable",e)}
diff --git a/custom_components/houseplan/import_export.py b/custom_components/houseplan/import_export.py
index f8e8cbc8..7d42d7bf 100644
--- a/custom_components/houseplan/import_export.py
+++ b/custom_components/houseplan/import_export.py
@@ -52,6 +52,7 @@ from .validation import (
sanitize_marker_id,
validate_marker_controls,
validate_marker_light_entities,
+ validate_marker_vacuum_routes,
validate_marker_value_badges,
validate_opening_passages,
validate_partition_opening_hosts,
@@ -1580,6 +1581,7 @@ def build_space_merge(
validate_marker_controls(merged_config, current_config)
validate_marker_light_entities(merged_config, current_config)
validate_marker_value_badges(merged_config, current_config)
+ validate_marker_vacuum_routes(merged_config, current_config)
validate_opening_passages(merged_config, current_config)
validate_partition_opening_hosts(merged_config, current_config)
except (
@@ -1875,6 +1877,7 @@ def create_preview(
validate_marker_controls(incoming_config, validate_all=True)
validate_marker_light_entities(incoming_config, validate_all=True)
validate_marker_value_badges(incoming_config, validate_all=True)
+ validate_marker_vacuum_routes(incoming_config, validate_all=True)
except MarkerControlError as err:
raise ImportFailure(err.code, str(err)) from err
content, confirmation = _content_state(document, same_source, config_root)
diff --git a/custom_components/houseplan/validation.py b/custom_components/houseplan/validation.py
index 41dcaa39..ff3cb196 100644
--- a/custom_components/houseplan/validation.py
+++ b/custom_components/houseplan/validation.py
@@ -17,6 +17,7 @@ from custom_components.houseplan.coordinate_canonicalization import (
canonicalize_layout_geometry,
canonicalize_position,
)
+from custom_components.houseplan.vacuum_routes import validate_marker_routes
# ---------- limits and extension sets ----------
PLAN_EXTENSIONS = {"svg": "image/svg+xml", "png": "image/png", "jpg": "image/jpeg", "webp": "image/webp"}
@@ -882,6 +883,50 @@ def validate_marker_value_badges(
validate_source(source, "value_source")
+def validate_marker_vacuum_routes(
+ config: dict, previous: dict | None = None, *, validate_all: bool = False
+) -> None:
+ """Validate changed vacuum map routes; dormant future data round-trips.
+
+ Change-aware like the badge validator above (#162): an untouched legacy or
+ future-shaped block must not block an unrelated save, but any edit to
+ routing has to leave the marker in a state the resolver can answer for —
+ unique identities, six-number matrices and target spaces that exist.
+ """
+ markers = config.get("markers") or []
+ spaces = config.get("spaces")
+ space_ids = None
+ if isinstance(spaces, list):
+ space_ids = {
+ str(space.get("id")) for space in spaces
+ if isinstance(space, dict) and isinstance(space.get("id"), str)
+ }
+ old_markers = (previous or {}).get("markers") or []
+ old_by_id = {str(marker.get("id")): marker for marker in old_markers}
+ by_id = {str(marker.get("id")): marker for marker in markers}
+ new_ids = set(by_id)
+ consumed_old_ids: set[str] = set()
+ for marker_id, marker in by_id.items():
+ old_marker = _matching_previous_marker(
+ marker, marker_id, old_by_id, old_markers, new_ids,
+ consumed_old_ids, validate_all,
+ )
+ routes = (marker.get("vacuum") or {}).get("map_routes")
+ old_routes = None if validate_all else ((old_marker or {}).get("vacuum") or {}).get("map_routes")
+ if not validate_all and routes == old_routes:
+ continue
+ problems = validate_marker_routes(marker_id, routes, space_ids)
+ if problems:
+ reasons = ", ".join(sorted({problem["reason"] for problem in problems}))
+ # Literal, not the constant: the #42 scanner proves the emitted
+ # code against ERROR_CODES by reading the source, and it cannot
+ # follow a name. The pair is pinned by a test below.
+ raise MarkerControlError(
+ "invalid_vacuum_map_route",
+ f"Invalid vacuum map routes on {marker_id}: {reasons}",
+ )
+
+
def validate_marker_light_entities(
config: dict, previous: dict | None = None, *, validate_all: bool = False
) -> None:
diff --git a/custom_components/houseplan/websocket_api.py b/custom_components/houseplan/websocket_api.py
index e38a4c70..aaef0f35 100755
--- a/custom_components/houseplan/websocket_api.py
+++ b/custom_components/houseplan/websocket_api.py
@@ -113,6 +113,7 @@ from .validation import (
valid_space_id,
validate_marker_controls,
validate_marker_light_entities,
+ validate_marker_vacuum_routes,
validate_marker_value_badges,
validate_opening_passages,
validate_partition_opening_hosts,
@@ -1578,6 +1579,7 @@ async def ws_config_set(hass: HomeAssistant, connection, msg: dict[str, Any]) ->
validate_marker_controls(msg["config"], data.get("config"))
validate_marker_light_entities(msg["config"], data.get("config"))
validate_marker_value_badges(msg["config"], data.get("config"))
+ validate_marker_vacuum_routes(msg["config"], data.get("config"))
validate_opening_passages(msg["config"], data.get("config"))
validate_partition_opening_hosts(msg["config"], data.get("config"))
return validate_junction_limits(
@@ -1936,6 +1938,7 @@ async def ws_plan_optimize(hass: HomeAssistant, connection, msg: dict[str, Any])
validate_marker_controls(msg["config"], config_data.get("config"))
validate_marker_light_entities(msg["config"], config_data.get("config"))
validate_marker_value_badges(msg["config"], config_data.get("config"))
+ validate_marker_vacuum_routes(msg["config"], config_data.get("config"))
validate_opening_passages(msg["config"], config_data.get("config"))
validate_partition_opening_hosts(
msg["config"], config_data.get("config"),
diff --git a/dist/houseplan-assets.json b/dist/houseplan-assets.json
index adab2b07..0a30d4d1 100644
--- a/dist/houseplan-assets.json
+++ b/dist/houseplan-assets.json
@@ -1,125 +1,125 @@
{
"schema": 1,
- "fingerprint": "bd7029808eb6094140d9fa8245f50816cb452430a353f4231d16e02c97078a06",
+ "fingerprint": "781b6de4892612660b01762cd408049137fa0d00417a43ef5bbdfb1ef37dc9a5",
"entry": "houseplan-card.js",
"initialViewFiles": [
- "houseplan-assets/houseplan-card-BTXh6SvG.js",
+ "houseplan-assets/houseplan-card-CuVuAiJj.js",
"houseplan-card.js"
],
- "initialViewGzipBytes": 292859,
+ "initialViewGzipBytes": 292979,
"lazyFiles": [
- "houseplan-assets/backdrop-pick-DxKIBNjn.js",
- "houseplan-assets/de-Cm5MlI_Y.js",
- "houseplan-assets/editor-CxXW-QO8.js",
- "houseplan-assets/fr-CDWnrdfn.js",
- "houseplan-assets/houseplan-editor-runtime-CmI5Go3m.js",
- "houseplan-assets/houseplan-onboarding-runtime-BB8OHZOL.js"
+ "houseplan-assets/backdrop-pick-BJ59BurK.js",
+ "houseplan-assets/de-DZwnjt2u.js",
+ "houseplan-assets/editor-CHYZKnjE.js",
+ "houseplan-assets/fr-C7WePbhg.js",
+ "houseplan-assets/houseplan-editor-runtime-o7FB8qC-.js",
+ "houseplan-assets/houseplan-onboarding-runtime-CAJfA2x6.js"
],
- "lazyGzipBytes": 219508,
+ "lazyGzipBytes": 219759,
"lazyEditorFiles": [
- "houseplan-assets/backdrop-pick-DxKIBNjn.js",
- "houseplan-assets/editor-CxXW-QO8.js",
- "houseplan-assets/houseplan-editor-runtime-CmI5Go3m.js"
+ "houseplan-assets/backdrop-pick-BJ59BurK.js",
+ "houseplan-assets/editor-CHYZKnjE.js",
+ "houseplan-assets/houseplan-editor-runtime-o7FB8qC-.js"
],
- "lazyEditorGzipBytes": 163600,
+ "lazyEditorGzipBytes": 163722,
"lazyOnboardingFiles": [
- "houseplan-assets/backdrop-pick-DxKIBNjn.js",
- "houseplan-assets/houseplan-onboarding-runtime-BB8OHZOL.js"
+ "houseplan-assets/backdrop-pick-BJ59BurK.js",
+ "houseplan-assets/houseplan-onboarding-runtime-CAJfA2x6.js"
],
- "lazyOnboardingGzipBytes": 14138,
+ "lazyOnboardingGzipBytes": 14234,
"lazyLocaleFiles": [
- "houseplan-assets/de-Cm5MlI_Y.js",
- "houseplan-assets/fr-CDWnrdfn.js"
+ "houseplan-assets/de-DZwnjt2u.js",
+ "houseplan-assets/fr-C7WePbhg.js"
],
- "lazyLocaleGzipBytes": 48949,
+ "lazyLocaleGzipBytes": 49082,
"files": [
{
- "path": "houseplan-assets/backdrop-pick-DxKIBNjn.js",
- "sha256": "b63841500de9009bdab1dda314af5c1ca3eead311f1dd05f1830f0da589b0f4c",
- "rawBytes": 20996,
- "gzipBytes": 7179,
+ "path": "houseplan-assets/backdrop-pick-BJ59BurK.js",
+ "sha256": "8be84f207f5d68f15f792323ab0c4f3a689132d154d3a68a47b04b6112d7fe93",
+ "rawBytes": 21378,
+ "gzipBytes": 7279,
"isEntry": false,
"imports": [
- "houseplan-assets/houseplan-card-BTXh6SvG.js"
+ "houseplan-assets/houseplan-card-CuVuAiJj.js"
],
"dynamicImports": []
},
{
- "path": "houseplan-assets/de-Cm5MlI_Y.js",
- "sha256": "cacdb232ff6403d2fdfb40a304df67aee139fbba4a6a6a2992a176e733ea4edb",
- "rawBytes": 81940,
- "gzipBytes": 24744,
+ "path": "houseplan-assets/de-DZwnjt2u.js",
+ "sha256": "b5d15c4488fda2e435fb6220ccaaa2696cbee3991540885a18d3bbcbb31cf5e4",
+ "rawBytes": 82140,
+ "gzipBytes": 24809,
"isEntry": false,
"imports": [],
"dynamicImports": []
},
{
- "path": "houseplan-assets/editor-CxXW-QO8.js",
- "sha256": "3cda68688d097f4198daa63b06d46eeb60c60ceb9399c4a83c586adae61852e3",
+ "path": "houseplan-assets/editor-CHYZKnjE.js",
+ "sha256": "0eb13886c6e6814cca1ce7d791c92968c9823c50abb31f0895a74c039fe7b9e5",
"rawBytes": 3826,
- "gzipBytes": 1584,
+ "gzipBytes": 1582,
"isEntry": false,
"imports": [
- "houseplan-assets/houseplan-card-BTXh6SvG.js"
+ "houseplan-assets/houseplan-card-CuVuAiJj.js"
],
"dynamicImports": []
},
{
- "path": "houseplan-assets/fr-CDWnrdfn.js",
- "sha256": "74c6d85b8e5ae259fa0d40948e19848a3010caf717edea225a8f2129d7cf2227",
- "rawBytes": 84059,
- "gzipBytes": 24205,
+ "path": "houseplan-assets/fr-C7WePbhg.js",
+ "sha256": "fe7b6e9bd8dbdd7b3e175bdc6e58b8927538f4078f89a306bed1fc78857d520d",
+ "rawBytes": 84267,
+ "gzipBytes": 24273,
"isEntry": false,
"imports": [],
"dynamicImports": []
},
{
- "path": "houseplan-assets/houseplan-card-BTXh6SvG.js",
- "sha256": "a2278cdaf370fb864adb820cfdbd884671ffa4b4ea61785f375ed384907d8562",
- "rawBytes": 1039135,
- "gzipBytes": 292060,
+ "path": "houseplan-assets/houseplan-card-CuVuAiJj.js",
+ "sha256": "dc8ac636f240e73c54f26bfff9ca62d5a6516e37850e2498e913637f85ee7f6a",
+ "rawBytes": 1039585,
+ "gzipBytes": 292182,
"isEntry": false,
"imports": [],
"dynamicImports": [
- "houseplan-assets/de-Cm5MlI_Y.js",
- "houseplan-assets/editor-CxXW-QO8.js",
- "houseplan-assets/fr-CDWnrdfn.js",
- "houseplan-assets/houseplan-editor-runtime-CmI5Go3m.js",
- "houseplan-assets/houseplan-onboarding-runtime-BB8OHZOL.js"
+ "houseplan-assets/de-DZwnjt2u.js",
+ "houseplan-assets/editor-CHYZKnjE.js",
+ "houseplan-assets/fr-C7WePbhg.js",
+ "houseplan-assets/houseplan-editor-runtime-o7FB8qC-.js",
+ "houseplan-assets/houseplan-onboarding-runtime-CAJfA2x6.js"
]
},
{
- "path": "houseplan-assets/houseplan-editor-runtime-CmI5Go3m.js",
- "sha256": "ccca4dc1b21b421cf2fb37a1bb27ab417492cf1d3478fa2ad8b0f555d9496798",
- "rawBytes": 589868,
- "gzipBytes": 154837,
+ "path": "houseplan-assets/houseplan-editor-runtime-o7FB8qC-.js",
+ "sha256": "66d51bf9c6363689f5ddf47a87b30e12ddfc970ff726596e5f1324b3d1f2bbab",
+ "rawBytes": 589941,
+ "gzipBytes": 154861,
"isEntry": false,
"imports": [
- "houseplan-assets/backdrop-pick-DxKIBNjn.js",
- "houseplan-assets/houseplan-card-BTXh6SvG.js"
+ "houseplan-assets/backdrop-pick-BJ59BurK.js",
+ "houseplan-assets/houseplan-card-CuVuAiJj.js"
],
"dynamicImports": []
},
{
- "path": "houseplan-assets/houseplan-onboarding-runtime-BB8OHZOL.js",
- "sha256": "be730d372a4390126890a15fee9af9ae154ac94d7df4d7dd51a3b639128cab91",
+ "path": "houseplan-assets/houseplan-onboarding-runtime-CAJfA2x6.js",
+ "sha256": "16c760331824dbd047763b6a8381ec6589da01f95e0bcfcab7801f0ad08e142e",
"rawBytes": 28088,
- "gzipBytes": 6959,
+ "gzipBytes": 6955,
"isEntry": false,
"imports": [
- "houseplan-assets/backdrop-pick-DxKIBNjn.js",
- "houseplan-assets/houseplan-card-BTXh6SvG.js"
+ "houseplan-assets/backdrop-pick-BJ59BurK.js",
+ "houseplan-assets/houseplan-card-CuVuAiJj.js"
],
"dynamicImports": []
},
{
"path": "houseplan-card.js",
- "sha256": "ac8fe2593f1937bd0bdc86f131b0b58ac668f59092c70f0b3af4092edba54138",
+ "sha256": "c8bf46999b6b15e83a03786879ed075813d25f6532ff22d3362eaefbcc0d226b",
"rawBytes": 1183,
- "gzipBytes": 799,
+ "gzipBytes": 797,
"isEntry": true,
"imports": [
- "houseplan-assets/houseplan-card-BTXh6SvG.js"
+ "houseplan-assets/houseplan-card-CuVuAiJj.js"
],
"dynamicImports": []
}
diff --git a/dist/houseplan-assets/backdrop-pick-DxKIBNjn.js b/dist/houseplan-assets/backdrop-pick-BJ59BurK.js
similarity index 65%
rename from dist/houseplan-assets/backdrop-pick-DxKIBNjn.js
rename to dist/houseplan-assets/backdrop-pick-BJ59BurK.js
index b9ca4cc1..8c072753 100644
--- a/dist/houseplan-assets/backdrop-pick-DxKIBNjn.js
+++ b/dist/houseplan-assets/backdrop-pick-BJ59BurK.js
@@ -1,6 +1,6 @@
-globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="bd7029808eb6094140d9fa8245f50816cb452430a353f4231d16e02c97078a06";import{dk as e,c as t,A as i,d as o,g as n,dl as s}from"./houseplan-card-BTXh6SvG.js";function r(e){const t=e.visualViewport;return t&&Number.isFinite(t.width)&&Number.isFinite(t.height)?{left:Number(t.offsetLeft)||0,top:Number(t.offsetTop)||0,width:Math.max(0,Number(t.width)||0),height:Math.max(0,Number(t.height)||0)}:{left:0,top:0,width:e.innerWidth,height:e.innerHeight}}function a(e,t,i,o=7,n=8){const s=i.left+n,r=i.top+n,a=Math.max(s,i.left+i.width-n),l=Math.max(r,i.top+i.height-n),h=Math.max(0,a-s),d=Math.max(0,l-r),c=Math.min(Math.max(0,t.width),h),u=Math.min(Math.max(0,t.height),d);let p=e.left;p+c>a&&(p=e.right-c),p=Math.min(Math.max(s,p),Math.max(s,a-c));const _=e.bottom+o,g=e.top-o-u;let m="bottom",f=_;return _+u>l&&g>=r?(m="top",f=Math.min(Math.max(r,g),Math.max(r,l-u))):f=Math.min(Math.max(r,_),Math.max(r,l-u)),{left:Math.round(p),top:Math.round(f),side:m,maxWidth:Math.round(h),maxHeight:Math.round(d)}}class l{constructor(e,t,i){this.owner=e,this.name=t,this.keydown=i,this.host=null,this.root=null}window(){return this.owner.ownerDocument.defaultView}dialog(){return this.owner.closest("hp-dialog")}usesPopover(e=!1){const t=this.window();return!e&&!!t&&function(e){const t=e.HTMLElement?.prototype;return"function"==typeof t?.showPopover&&"function"==typeof t?.hidePopover}(t)}get hasFallback(){return!!this.host}containsPath(e){return e.includes(this.owner)||!!this.host&&e.includes(this.host)}ownsActiveElement(){let e=this.owner.ownerDocument.activeElement;for(;e?.shadowRoot?.activeElement;)e=e.shadowRoot.activeElement;return!(!e||e!==this.owner&&!this.owner.shadowRoot?.contains(e)&&!this.root?.contains(e))}renderFallback(i,o){const n=this.ensureFallback();return n?(e(t`${i}`,n),n):null}surface(e,t){return t?this.owner.shadowRoot?.querySelector(e)||null:this.root?.querySelector(e)||null}destroy(){this.root&&e(i,this.root),this.host?.remove(),this.host=null,this.root=null}ensureFallback(){if(this.root?.isConnected)return this.root;const e=this.dialog()?.overlayPortal()||this.owner.ownerDocument.body;if(!e)return null;const t=this.owner.ownerDocument.createElement("div");return t.dataset.hpOverlay=this.name,t.style.display="contents",this.keydown&&t.addEventListener("keydown",this.keydown,!0),e.append(t),this.host=t,this.root=t.attachShadow({mode:"open"}),this.root}}let h=0;class d extends n{constructor(){super(...arguments),this.text="",this.ariaLabel="",this.pointerHover=!1,this._open=!1,this._openTimer=0,this._closeTimer=0,this._positionRaf=0,this._forceFallback=!1,this._hoverOwned=!1,this._overlayDispose=null,this._scrollDialog=null,this._descriptionId="hp-help-description-"+ ++h,this._surfacePointerEnter=()=>{const e=this._window();this._closeTimer&&e?.clearTimeout(this._closeTimer),this._closeTimer=0},this._surfacePointerLeave=()=>{this._scheduleClose()},this._outsidePointerDown=e=>{if(!this._open)return;const t=e.composedPath();this._floating.containsPath(t)||this._closeHelp(!1,"outside")},this._dialogScroll=e=>{const t=this._floating.containsPath(e.composedPath()),i=e.target,o=this._dialog(),n=i instanceof Node&&(i===o||i instanceof Element&&i.contains(this));var s;this._open&&(s=n,!t&&s)&&this._closeHelp(!1,"scroll")},this._keyDown=e=>{if(!this._open||e.defaultPrevented)return;if("Escape"===e.key)return e.preventDefault(),e.stopImmediatePropagation(),void this._closeHelp(this._floating.ownsActiveElement(),"escape");const t=this.renderRoot.querySelector(".trigger");if(!t||!e.composedPath().includes(t))return;const i=this._surface();if(!i||i.scrollHeight<=i.clientHeight)return;const o=Math.max(40,.8*i.clientHeight),n={ArrowDown:40,ArrowUp:-40,PageDown:o,PageUp:-o};if("Home"===e.key)i.scrollTop=0;else if("End"===e.key)i.scrollTop=i.scrollHeight;else{if(!(e.key in n))return;i.scrollBy({top:n[e.key],behavior:"auto"})}e.preventDefault(),e.stopImmediatePropagation()},this._floating=new l(this,"help",this._keyDown),this._queuePosition=()=>{if(!this._open||this._positionRaf)return;const e=this._window();e&&(this._positionRaf=e.requestAnimationFrame(()=>{this._positionRaf=0,this._position()||this._closeHelp()}))}}connectedCallback(){super.connectedCallback(),this.addEventListener("keydown",this._keyDown,!0)}willUpdate(){this.toggleAttribute("data-has-content",this._hasContent())}disconnectedCallback(){const e=this.ownerDocument.defaultView;this._unsubscribeOpenListeners(),this.removeEventListener("keydown",this._keyDown,!0),this._clearTimers(),this._positionRaf&&e?.cancelAnimationFrame(this._positionRaf),this._positionRaf=0,this._closeHelp(!1,"disconnect"),super.disconnectedCallback()}updated(e){if(e.has("pointerHover")&&!this.pointerHover){const e=this._window();this._openTimer&&e?.clearTimeout(this._openTimer),this._openTimer=0,this._hoverOwned&&this._closeHelp(!1,"outside")}this._hasContent()||!this._open?this._open&&e.has("text")&&(this._usesPopover()||this._renderFallback(),this._queuePosition()):this._closeHelp()}_window(){return this._floating.window()}_dialog(){return this._floating.dialog()}_usesPopover(){return this._floating.usesPopover(this._forceFallback)}_hasContent(){return e=this.text,t=this.ariaLabel,"string"==typeof e&&e.trim().length>0&&"string"==typeof t&&t.trim().length>0;var e,t}_clearTimers(){const e=this._window();this._openTimer&&e?.clearTimeout(this._openTimer),this._closeTimer&&e?.clearTimeout(this._closeTimer),this._openTimer=0,this._closeTimer=0}_scheduleOpen(){const e=this._window();this.pointerHover&&e&&!this._open&&!this._openTimer&&(this._closeTimer&&e.clearTimeout(this._closeTimer),this._closeTimer=0,this._openTimer=e.setTimeout(()=>{this._openTimer=0,this.isConnected&&(this._hoverOwned=!0,this._openHelp())},300))}_scheduleClose(){const e=this._window(),t=this.renderRoot.querySelector(".trigger");e&&!t?.matches(":focus-visible")&&(this._openTimer&&e.clearTimeout(this._openTimer),this._closeTimer&&e.clearTimeout(this._closeTimer),this._openTimer=0,this._closeTimer=e.setTimeout(()=>{this._closeTimer=0,this.isConnected&&this._closeHelp()},150))}_triggerPointerEnter(e){this.pointerHover&&"mouse"===e.pointerType&&this._scheduleOpen()}_triggerPointerLeave(e){"mouse"===e.pointerType&&this._scheduleClose()}_triggerFocus(){queueMicrotask(()=>{const e=this.renderRoot.querySelector(".trigger");e?.matches(":focus-visible")&&(this._hoverOwned=!1,this._openHelp())})}_triggerBlur(){this._scheduleClose()}_triggerClick(){this._open?this._closeHelp():(this._hoverOwned=!1,this._openHelp())}_subscribeOpenListeners(){this.ownerDocument.addEventListener("pointerdown",this._outsidePointerDown,!0),this.ownerDocument.addEventListener("keydown",this._keyDown,!0);const e=this._window();e?.addEventListener("resize",this._queuePosition),e?.addEventListener("orientationchange",this._queuePosition),e?.visualViewport?.addEventListener("resize",this._queuePosition),e?.visualViewport?.addEventListener("scroll",this._queuePosition),this._scrollDialog=this._dialog(),this._scrollDialog?.addEventListener("scroll",this._dialogScroll,!0)}_unsubscribeOpenListeners(){this.ownerDocument.removeEventListener("pointerdown",this._outsidePointerDown,!0),this.ownerDocument.removeEventListener("keydown",this._keyDown,!0);const e=this._window();e?.removeEventListener("resize",this._queuePosition),e?.removeEventListener("orientationchange",this._queuePosition),e?.visualViewport?.removeEventListener("resize",this._queuePosition),e?.visualViewport?.removeEventListener("scroll",this._queuePosition),this._scrollDialog?.removeEventListener("scroll",this._dialogScroll,!0),this._scrollDialog=null}async _openHelp(){!this._open&&this._hasContent()&&(this._clearTimers(),this._forceFallback=!1,this._open=!0,this._subscribeOpenListeners(),await this.updateComplete,this._open&&(this._usesPopover()||this._renderFallback(),this._position()?this._overlayDispose=this._dialog()?.registerOverlay({owner:this,group:"transient",close:e=>this._closeHelp("escape"===e&&this._floating.ownsActiveElement(),e)})||null:this._closeHelp()))}_closeHelp(e=!1,t="exclusive"){if(!this._open&&!this._floating.hasFallback)return;this._clearTimers();const i=this._overlayDispose;this._overlayDispose=null,i?.();const o=this.renderRoot.querySelector(".tooltip");if(o?.hidePopover)try{o.matches(":popover-open")&&o.hidePopover()}catch{}this._open=!1,this._hoverOwned=!1,this._unsubscribeOpenListeners(),this._floating.destroy(),e&&this.updateComplete.then(()=>this.renderRoot.querySelector(".trigger")?.focus())}_tooltipTemplate(e){return t`
- `}export{l as F,c as a,g as b,H as c,D as e,r as f,u as i,a as p,R as r,p as s,_ as t};
+ `}export{l as F,c as a,_ as b,H as c,p as d,C as e,s as f,u as i,a as p,F as r,m as s,g as t};
diff --git a/dist/houseplan-assets/de-Cm5MlI_Y.js b/dist/houseplan-assets/de-Cm5MlI_Y.js
deleted file mode 100644
index 94307c29..00000000
--- a/dist/houseplan-assets/de-Cm5MlI_Y.js
+++ /dev/null
@@ -1 +0,0 @@
-globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="bd7029808eb6094140d9fa8245f50816cb452430a353f4231d16e02c97078a06";var e={"editor.context_actions":"Aktionen: {object}","editor.tool_options":"Werkzeugoptionen: {tool}","editor.palette":"Palette: {tool}","editor.open_group":"Werkzeuggruppe: {group}","editor.group_active":"{group} — aktiv: {item}","editor.disabled_action":"{action} ist nicht verfügbar: {reason}","editor.loading":"Editor wird geladen…","editor.loading_aria":"Der Plan-Editor wird geladen","editor.load_failed":"Der Editor konnte nicht geladen werden.","editor.refresh_advice":"Seite aktualisieren und erneut versuchen.","editor.retry_advice":"Verbindung prüfen und erneut drücken.","color_picker.title":"Farbwähler","color_picker.hue":"Farbton","color_picker.saturation":"Sättigung","color_picker.value":"Helligkeit","color_picker.hex":"Hex-Farbe","color_picker.invalid_hex":"Geben Sie eine 3- oder 6-stellige Hex-Farbe ein","btn.properties":"Eigenschaften","btn.keep_as_walls":"Als Wände behalten","btn.delete_room_keep_walls":"Raum löschen, Wände behalten","btn.delete_room_with_walls":"Raum und Wände löschen","title.markup_select":"Wände, Säulen und gespeicherte Umrisse auswählen und bearbeiten","title.markup_column":"Säule: Klicken Sie auf einen Rasterpunkt, um eine quadratische Säule zu platzieren","markup.partition":"Trennwand","markup.column":"Säule","markup.hint_column":"Klicken Sie auf einen Rasterpunkt, um eine quadratische Säule zu platzieren","history.draft_segment":"Raum-Entwurfsegment hinzufügen","history.draft_merge":"Unvollständige Raumumrisse verbinden","history.draft_segment_delete":"Raum-Entwurfssegment entfernen","history.column_add":"Säule hinzufügen","history.physical_edit":"Physisches Objekt ändern","history.physical_delete":"Physisches Objekt löschen","history.physical_move":"Physisches Objekt verschieben","history.contour_to_partitions":"Umriss in geschlossene Wände umwandeln","history.wall_chain_finish":"Wandkette fertigstellen","history.wall_face_batch":"Räume aus Wänden erstellen","toast.column_duplicate":"Eine Säule mit demselben Zentrum und äußerer Größe existiert bereits","confirm.delete_draft_title":"Unvollständigen Umriss löschen?","confirm.delete_draft_body":"Der gesamte unvollständige Raumumriss wird gelöscht. Beim Abbrechen wird nichts geändert.","confirm.delete_draft_segment_title":"Umrisssegment löschen?","confirm.delete_draft_segment_body":"Dieses Entwurfssegment wird gelöscht. Der verbleibende Umriss kann sich in zwei Teile aufteilen.","physical.partition_properties":"Eigenschaften der Trennwand","physical.column_properties":"Eigenschaften der Säule","physical.draft_properties":"Eigenschaften des Entwurfssegments","physical.shape":"Form","physical.square":"Quadrat","physical.circle":"Kreis","physical.diameter":"Durchmesser","physical.side":"Seite","physical.rotation":"Drehwinkel","physical.length":"Länge","physical.allowed_range":"Erlaubt: {min}–{max} {unit}","physical.delete_segment":"Segment löschen","physical.delete_draft":"Gesamten Umriss löschen","physical.column_size_title":"Außenmaß der per Klick platzierten quadratischen Säule (1–150 cm).","card.title":"Hausplan","count.devices":"{n} Entwicklung","empty.no_spaces":"Noch keine Bereiche.","empty.add_first":"Ersten Bereich hinzufügen und einen Grundriss hochladen.","empty.install":"Installieren Sie die House Plan-Integration und fügen Sie sie unter „Geräte & Dienste“ hinzu.","btn.add_space":"Bereich hinzufügen","btn.cancel":"Abbrechen","btn.save":"Speichern","btn.close":"Schließen","btn.delete":"Löschen","btn.edit":"Bearbeiten","btn.open_in_ha":"In HA öffnen","btn.reset":"Zurücksetzen","btn.attach":"Anhängen…","btn.upload":"Hochladen…","btn.replace":"Ersetzen…","title.zoom_in":"Zoomen","title.zoom_out":"Herauszoomen","title.zoom_fit":"Alles anpassen","title.configure_space":"Bereich konfigurieren","title.add_space":"Bereich hinzufügen","title.markup_add":"Wände: eine durchgehende Kette zeichnen; Shift sperrt auf 45°. Werkzeugwechsel oder Verlassen des Editors beendet die Kette und wandelt sie in unabhängige Wände","title.markup_merge":"Zusammenführen: Klicken Sie auf einen Raum und dann auf den Nachbarraum, mit dem er eine Wand teilt","title.markup_split":"Raum teilen: Klicken Sie auf den Raum und dann auf zwei Punkte an seinen Wänden","title.markup_delroom":"Raum löschen: Klicken Sie in einen Raum und bestätigen Sie","title.need_plan":"Einen Grundriss hochladen","markup.add":"Wände","markup.merge":"Zusammenführen","markup.split":"Teilen","markup.resize":"Größe ändern","title.markup_resize":"Räume vergrößern/verkleinern: Ziehen Sie einen verfügbaren horizontalen oder vertikalen Wandgriff","markup.hint_resize":"Ziehen Sie einen verfügbaren Wandgriff · die Wand stoppt an der ersten unsicheren Position · Esc bricht ab · Strg+Z — rückgängig","resize.disabled.diagonal":"Diese Wand ist geneigt; Größe ändern unterstützt nur horizontale und vertikale Wände","resize.disabled.side-angle":"Eine angrenzende Wand ist geneigt; Größe ändern erfordert, dass beide angrenzenden Wände diese Wand im rechten Winkel treffen","resize.disabled.duplicate-physical-wall":"Eine separate Trennwand, unfertige Kontur oder ein Pfeiler überlappt diese Wand; entfernen oder verschieben Sie sie, bevor Sie die Größe ändern","resize.disabled.partial-shared":"Ein angrenzender Raum nutzt nur einen Teil dieser Wand, daher kann sie nicht sicher als gemeinsame Wand verschoben werden","resize.disabled.unequal-shared":"Der angrenzende Raum nutzt andere Endpunkte oder Wandlängen, daher können die Wände nicht gemeinsam sicher bewegt werden","resize.disabled.multiple-rooms":"Das Verschieben dieser Wand würde mehr als zwei Räume betreffen","resize.disabled.thickness-conflict":"Die Wandstärke kann nicht sicher beibehalten werden","resize.disabled.opening-conflict":"Eine Öffnung an dieser Wand kann nicht sicher verschoben werden","resize.disabled.invalid-geometry":"Diese Wand kann nicht ohne Änderung der Planstruktur geändert werden","resize.limit_stopped":"Wand gestoppt: der nächste Schritt würde ein Anschlusslimit verletzen","resize.commit_failed":"Größenänderung wurde abgebrochen, da der endgültige Plan die Geometrieprüfung nicht bestanden hat","resize.preview_failed":"Größenänderung am letzten sicheren Punkt gestoppt, da die Plan-Geometrie nicht beibehalten werden konnte","markup.opening":"Öffnung","markup.delete_room":"Raum löschen","history.undo":"Rückgängig","history.redo":"Wiederholen","history.undo_named":"Rückgängig: {name} (Strg+Z)","history.redo_named":"Wiederholen: {name} (Strg+Shift+Z / Strg+Y)","history.undo_empty":"Nichts zu widerrufen","history.redo_empty":"Nichts zu wiederholen","history.undone":"Rückgängig gemacht: {name}","history.redone":"Wiederholt: {name}","history.add_room":"Raum erstellen","history.split_room":"Raum teilen","history.merge_rooms":"Räume zusammenführen","history.resize_room":"Raumgröße ändern","history.wall_thickness":"Wandstärke ändern","history.add_opening":"Tür- oder Fensteröffnung hinzufügen","history.edit_opening":"Öffnung bearbeiten","history.move_opening":"Öffnung verschieben","history.delete_opening":"Öffnung löschen","history.delete_room_keep_walls":"Raum löschen, Wände behalten","history.delete_room_with_walls":"Raum und Wände löschen","history.decor_add":"Dekorobjekt hinzufügen","history.decor_edit":"Dekorobjekt bearbeiten","history.decor_move":"Dekorobjekt verschieben","history.decor_transform":"Dekorobjekt transformieren","history.decor_delete":"Dekorobjekt löschen","history.backdrop_transform":"Plan-Hintergrund transformieren","history.device_move":"{name} verschieben","history.device_stale":"Der Positionsverlauf ist nicht mehr anwendbar und wurde gelöscht","opening.new":"Neue Öffnung","opening.edit":"Öffnung","opening.door":"Tür","opening.window":"Fenster","opening.gate":"Tor","opening.passage":"Offener Durchgang","opening.passage_binding_warning":"Das Speichern entfernt den Öffnungs-/Schließsensor und das Schloss.","opening.invalid_passage_fields":"Der offene Durchgang auf dem Plan „{room}“ hat nicht unterstützte Einstellungen: {fields}.","opening.type_label":"Typ","opening.length_label":"Länge, cm","opening.contact_label":"Öffnungs-/Schließsensor","opening.lock_label":"Schloss","opening.none":"— keine —","opening.search_ph":"Suche: Name oder Entitäts-ID…","opening.invert":"Geöffnet/geschlossen invertieren","opening.flip_h":"Scharnier an der anderen Zarge","opening.flip_v":"Öffnet zur anderen Seite","opening.open":"Offen","opening.closed":"Geschlossen","opening.locked":"Verriegelt","opening.unlocked":"Entriegelt","opening.state_unknown":"nicht verfügbar","opening.no_entities":"Keine Sensoren gebunden — ein statisches Symbol auf dem Plan.","toast.opening_no_wall":"Neben eine Raumwand oder eine unabhängige Wand klicken","opening.host_partition":"Unabhängige Wand","opening.partition_orphan":"Die unabhängige Wand für diese Öffnung existiert nicht mehr","opening.partition_jamb_margin":"Mindestens {distance} zwischen der Öffnung und dem Wandende lassen","opening.rebind_partition":"An eine andere unabhängige Wand anfügen","confirm.delete_partition_openings_title":"Wand und Öffnungen löschen?","confirm.delete_partition_openings_body":"Diese Wand enthält {count} Öffnung(en). Sie werden zusammen gelöscht.","confirm.delete_partition_openings_item":"• {type}, {length}","markup.hint_points":"Punkte: {n} · Shift — 45° Schritte · Esc — Kette beenden · Ctrl+Z — Punkt rückgängig machen · Schließen eines Bereichs erstellt einen Raum","markup.hint_start":"Klicken Sie auf einen Rasterpunkt, um eine Wandkette zu starten","tip.lqi":"durchschnittliches Zigbee-Signal:","tip.area":"Bereich: {value}","info.device_header":"Gerät im Plan","info.model":"Modell","info.state":"Status","info.link":"Verbindung","info.manuals":"Handbücher","info.none":"Keine zusätzlichen Informationen","marker.new_device":"Neues Gerät","marker.name_label":"Name (im Plan angezeigt)","marker.name_ph":"Name","marker.binding_label":"An ein HA-Gerät binden","marker.binding_disabled":"in Home Assistant deaktiviert","marker.virtual_option":"Virtuelles Gerät (keine Bindung)","marker.search_ph":"Gerät/Gruppe suchen…","marker.nothing_found":"Nichts gefunden","marker.room_label":"Raum","marker.room_override":" (Platzierung überschreiben)","marker.room_choose":"— Raum auswählen —","marker.room_auto":"— nach Gerätebereich (auto) —","marker.icon_label":"Symbol","marker.icon_ph":"mdi:… (leer = automatisch)","marker.display_label":"Anzeige","display.badge":"Symbol + Zustand","display.icon_ripple":"Symbol + Zustand und Aktivität","display.static_icon":"Immer statisches Symbol","marker.display_hint_badge":"Das Symbol und die dynamische Platte zeigen den Gerätezustand ohne den üblichen Aktivitätspuls. Rote Alarme bleiben sichtbar.","marker.display_hint_icon_ripple":"Das Symbol, die dynamische Platte und der Puls zeigen einen kurzen Puls für Ereignisse und einen kontinuierlichen Puls für Arbeit, Bewegung oder Anwesenheit. Rote Alarme haben eine separate Priorität.","marker.display_hint_value":"Ein ausgewählter oder automatisch ermittelter Home Assistant-Wert ersetzt das Symbol, während die Platte weiterhin den Zustand anzeigt. Rote Alarme bleiben sichtbar.","marker.display_hint_static_icon":"Die themenabhängige Hülle und das Symbol bleiben immer gleich. Zustand, Aktivität, Nichtverfügbarkeit und Alarme verändern nicht das Erscheinungsbild.","marker.static_alarm_warning":"Dieses Gerät kann Alarme melden. Die statische Anzeige verbirgt die visuelle Alarmanzeige des Markers.","marker.preview.title":"Anzeigevorschau","marker.preview.actual":"Jetzt","marker.preview.example":"Beispiel","marker.preview.integration":"Bereitgestellt von","marker.preview.source":"Anzeigquelle","marker.preview.current_state":"Aktueller Zustand","marker.preview.result":"Auf dem Plan","marker.preview.details":"Quelldetails","marker.preview.select_source":"Ein Home-Assistant-Gerät oder eine Entität auswählen, um die tatsächliche Anzeige zu sehen.","marker.preview.unknown_provider":"Unbekannte Integration","marker.preview.virtual_provider":"House Plan · virtuelles Gerät","marker.preview.no_source":"Keine aktive Quelle","marker.preview.no_state":"Kein aktueller Zustand","marker.preview.mixed_states":"Mehrere verschiedene Zustände","marker.preview.multiple_sources":"{n}-Quellen","marker.preview.more_sources":"+{n} mehr","marker.preview.scaled":"Die Vorschau wird auf {n}% skaliert, um zu passen. Die gespeicherte Größe bleibt unverändert.","marker.preview.demo_short":"Kurze Aktivität anzeigen","marker.preview.demo_continuous":"Kontinuierliche Aktivität anzeigen","marker.preview.stop_continuous":"Kontinuierliche Aktivität stoppen","marker.preview.demo_short_notice":"Kurzes Aktivitätsbeispiel; der tatsächliche Gerätezustand bleibt unverändert.","marker.preview.demo_continuous_notice":"Kontinuierliches Aktivitätsbeispiel; der tatsächliche Gerätezustand bleibt unverändert.","marker.preview.demo_already_visible":"Der aktuelle Zustand zeigt bereits eine echte Aktivitäts- oder Alarmeffekt.","marker.preview.reduced_motion":"Systemweit reduzierte Bewegungen sind aktiviert, daher wird gewöhnliche Aktivität als Punkt angezeigt.","marker.preview.reason.neutral":"Neutrale dunkle Platte","marker.preview.reason.working":"Gelbe Platte: Das Gerät arbeitet jetzt","marker.preview.reason.working_activity":"Gelbe Platte und Aktivitätseffekt: das Gerät funktioniert jetzt","marker.preview.reason.open":"Orange Platte: physisch geöffnet oder entriegelt","marker.preview.reason.cover_icon_state":"Neutrale Platte; die Abdeckungseinheit steuert den angezeigten Zustand und das Symbol","marker.preview.reason.presence":"Aktivitätseffekt, während Präsenz erkannt wird","marker.preview.reason.event":"Kurzer Aktivitätseffekt nach einem erkannten Ereignis","marker.preview.reason.transition":"Aktivitätseffekt, während das Gerät sich bewegt oder den Zustand ändert","marker.preview.reason.media_neutral":"Mediengeräte bleiben im verfügbaren Zustand auf einer neutralen dunklen Platte","marker.preview.reason.unavailable":"Gedämpfte neutrale Platte: nicht verfügbar oder ausgeschaltet","marker.preview.reason.alarm":"Rote Alarmplatte; Alarmanzeige wird immer angezeigt","marker.preview.reason.live_states_disabled":"Live-Zustandsstil ist für diese Karte deaktiviert","marker.preview.reason.value_no_state":"Kein nutzbarer Zustandswert; stattdessen wird das Symbol angezeigt","marker.preview.reason.value_ambiguous_sources":"Mehrere mögliche Wertequellen; stattdessen wird das Symbol angezeigt","marker.preview.reason.value_non_scalar":"Die Quelle lieferte keinen einfachen Wert; stattdessen wird das Symbol angezeigt","marker.preview.reason.value_virtual":"Ein virtuelles Gerät hat keinen Home Assistant-Wert; stattdessen wird das Symbol angezeigt","marker.preview.reason.vacuum_live_plan_only":"Echtzeitposition und -spur des Staubsaugers sind nur im vollständigen Plan verfügbar","marker.preview.reason.hidden_design_preview":"Das Gerät ist im Plan ausgeblendet; diese Designvorschau bleibt sichtbar","marker.preview.reason.composite_power_source":"Der Status stammt vom Power-Entity des Geräts; Hilfsschalter werden ignoriert","marker.preview.reason.activity_display_disabled":"Der gewählte Anzeigemodus zeigt gewöhnliche Aktivitätseffekte nicht an","marker.preview.reason.ha_disabled":"Die Home Assistant-Verbindung ist deaktiviert und wird im Plan ausgeblendet","marker.preview.reason.orphaned":"Die gespeicherte Home Assistant-Verbindung konnte nicht mehr gefunden werden","marker.preview.reason.static_icon":"Statischer Modus: Der Gerätestatus ändert das Symbol nicht","marker.activity_color":"Aktivitätspulsfarbe","marker.ripple_size":"Aktivitätspulsgröße","marker.activity_alarm_note":"Farbe und Größe betreffen nur gewöhnliche Aktivität und ändern keine roten Alarme.","marker.pulse_a11y_alarm":"Alarm","marker.pulse_a11y_event":"Kürzliches Ereignis","marker.pulse_a11y_presence":"Anwesenheit erkannt","marker.pulse_a11y_transition":"Statusänderung","marker.pulse_a11y_running":"Arbeitet","marker.state_a11y_neutral":"Standardzustand","marker.state_a11y_working":"Funktionierend","marker.state_a11y_open":"Offen","marker.state_a11y_locked":"Verschlossen","marker.state_a11y_unlocked":"Entriegelt","marker.state_a11y_alarm":"Alarm","marker.state_a11y_unavailable":"Nicht verfügbar","marker.lqi_a11y_low":"LQI {value}, schwaches Signal","marker.lqi_a11y_mid":"LQI {value}, mittleres Signal","marker.lqi_a11y_high":"LQI {value}, starkes Signal","marker.size_label":"Symbolgröße / Drehung","marker.angle_label":"Drehen","marker.model_label":"Modell","marker.model_ph":"z.B. Aqara T&H","marker.link_label":"Link","marker.desc_label":"Beschreibung","marker.desc_ph":"Notizen, Spezifikationen…","marker.manuals_label":"Handbücher (PDF usw.)","marker.sub_device":"Gerät","marker.sub_z2m_group":"· Z2M Gruppe","marker.sub_group":"Gruppe","marker.sub_helper":"Helfer","space.new":"Neuer Bereich","space.header":"Bereich","space.title_label":"Titel","space.title_ph":"z.B. Garage","space.plan_label":"Grundriss (Hintergrund)","space.no_plan":"Kein Planbild","space.plan_alt":"Grundriss","room.new":"Neuer Raum","room.name_label":"Anzeigename","room.name_ph":"z.B. Terrasse","room.area_label":"Home Assistant Bereich (nicht zugewiesen)","room.no_area_option":"— kein Bereich —","room.default_name":"Raum","device.unnamed":"unbenannt","device.light_group":"Lichtgruppe","device.fallback":"Gerät","device.virtual":"Virtuelles Gerät","confirm.delete_room_title":'Raum "{name}" löschen?',"confirm.delete_room_body":"Festlegen, ob die ausschließlich zu diesem Raum gehörenden physischen Wände erhalten bleiben. Mit einem anderen Raum geteilte Wände bleiben immer erhalten.","confirm.remove_marker_title":"Gerät aus dem Plan löschen?","confirm.remove_marker_body":"Das Gerät verschwindet vollständig und trägt nicht mehr zu den Plandaten bei. Es kann später erneut hinzugefügt werden.","confirm.erase_decor":"Das Objekt „{kind}“ löschen? Diese Aktion kann im Editor rückgängig gemacht werden.","confirm.delete_space_title":"Bereich löschen?","confirm.delete_space_body":"Der Bereich, alle seine Räume und die gesamte Planmarkierung werden gelöscht.","space.delete_blocked":"Dieser Bereich wird noch von {n} Gerät(en) verwendet. Die Geräte zuerst in einen anderen Bereich verschieben oder löschen.","toast.pos_save_failed":"Position nicht gespeichert: {err}","toast.no_entity":"Das Gerät hat keine geeignete Entität","toast.ha_disabled_action":"Ein deaktiviertes Home Assistant-Objekt kann im Plan nicht verwendet werden.","toast.ha_disabled_show_device":"Ein in Home Assistant deaktiviertes Gerät kann im Plan nicht angezeigt werden. Aktivieren Sie es zuerst in Home Assistant.","toast.ha_disabled_show_entity":"Eine in Home Assistant deaktivierte Entität kann im Plan nicht angezeigt werden. Aktivieren Sie sie zuerst in Home Assistant.","toast.ha_disabled_add":"Ein deaktiviertes Home Assistant-Objekt kann nicht dem Plan hinzugefügt werden. Aktivieren Sie es zuerst in Home Assistant.","toast.ha_binding_unverified":"Der Status des Objekts konnte über das Home Assistant-Register nicht überprüft werden. Anzeige und Aktionen sind vorübergehend nicht verfügbar.","toast.markup_needs_server":"Markup ist verfügbar, nachdem die Konfiguration auf den Server verschoben wurde.","toast.space_order_changed":"Reihenfolge geändert. Wenn eine Karte ihr Stockwerk nach Nummer festlegt, überprüfen Sie diese Paneele.","toast.conflict":"Die Konfiguration wurde in einem anderen Fenster geändert — Daten aktualisiert, wiederholen Sie Ihre letzte Aktion.","toast.cfg_save_failed":"Speichern der Konfiguration fehlgeschlagen: {err}","toast.room_overlap":"Die Umrisse überlappen den Raum „{name}“ — Räume dürfen sich nicht überlappen","toast.contour_cannot_close":"Die Kontur kann nicht geschlossen werden, da sie entartet ist oder sich selbst schneidet","toast.merge_not_adjacent":"Es können nur Räume zusammengeführt werden, die eine Wand teilen","toast.rooms_merged":"Räume zu „{name}“ zusammengeführt","toast.split_pick_wall":"Beginnen Sie den Schnitt an der Wand des Raumes","toast.split_bad_cut":"Der Schnitt muss wand-zu-wand innerhalb des Raumes verlaufen, ohne Wände oder sich selbst zu kreuzen","merge.header":"Räume zusammenführen","merge.hint":"Der zusammengeführte Raum behält einen Namen und eine Fläche. Die andere Fläche wird freigegeben — ihre Geräte verlassen den Plan, bis ein anderer Raum sie beansprucht.","merge.keep":"Behalten","merge.no_area":"keine Fläche","toast.room_saved":"Raum gespeichert ({n}). Hinzugefügte Geräte: {added}. Zeichnen Sie die nächste Kontur oder verlassen Sie die Markierung.","toast.room_saved_no_area":"Raum gespeichert ({n}, keine Fläche). Zeichnen Sie die nächste Kontur oder verlassen Sie die Markierung.","toast.marker_needs_server":"Die Gerätebearbeitung ist verfügbar, nachdem die Konfiguration auf den Server verschoben wurde","toast.virtual_name_required":"Einen Namen für das virtuelle Gerät eingeben","toast.marker_saved":"Gerät gespeichert","toast.marker_removed":"Gerät aus dem Plan gelöscht","toast.integration_missing":"Die House Plan-Integration ist nicht installiert — Verwaltung nicht verfügbar","toast.plan_formats":"Unterstützte Formate: SVG, PNG, JPG, WebP","toast.plan_required":"Grundriss hochladen — erforderlich","toast.space_added_onboard":"Bereich hinzugefügt. Räume einzeichnen: Rasterpunkte anklicken und die Kontur schließen.","toast.space_added":"Bereich hinzugefügt","toast.space_saved":"Bereich gespeichert","toast.space_deleted":"Bereich gelöscht","toast.delete_failed":"Löschen fehlgeschlagen: {err}","toast.error":"Fehler: {err}","toast.toggle_target_unavailable":"Ziel „{name}“ ist nicht verfügbar — keine Aktion durchgeführt","toast.toggle_targets_unavailable":"Ziele nicht verfügbar: {names}. Keine Aktion durchgeführt","toast.file_failed":'Datei "{name}" wurde nicht hochgeladen: {err}',"toast.files_attached":"Dateien angehängt: {n}","err.unknown":"unbekannter Fehler","err.code":"Code {code}","err.too_large":"Datei größer als {mb} MB","err.bad_ext":"nicht unterstützter Typ (PDF/Bild erwartet)","err.unauthorized":"Administratorrechte erforderlich","editor.title":"Titel","editor.default_floor":"Anfangsbereich","editor.default_floor_missing":"Anfangsbereich „{id}“ existiert nicht mehr. Wählen Sie einen anderen Bereich.","editor.floor":"Fester Bereich","editor.floor_none":"— nicht fest —","editor.floor_index":"YAML-Index {index} (beibehalten)","fixed_floor.loading":"Lade den festen Bereich…","fixed_floor.invalid_title":"Der feste Bereich ist nicht verfügbar","fixed_floor.invalid_body":"Überprüfen Sie die Etage in der Kartenkonfiguration. Der konfigurierte Wert ist: {value}","editor.icon_size":"Symbolgröße, % der Planbreite","editor.show_temperature":"Temperatur anzeigen","editor.live_states":"Live-Zustände (ein/aus, offen…)","editor.light_pools":"Lichtkegel und Wandschatten","editor.show_signal":"Zigbee-Signal anzeigen (LQI)","editor.language":"Schnittstellensprache","editor.lang_auto":"Automatisch (HA-Profil)","title.icon_rules":"Symbolregeln: welche MDI-Symbole Geräte nach Namen erhalten","rules.title":"Symbolregeln","rules.hint":'Regeln werden von oben anhand von "Gerätename + Modell" (Großschreibungs-unempfindliches Regex) überprüft; das erste Match gewinnt. Wenn nichts übereinstimmt, entscheidet die Entität-Geräteklasse, dann das generische Chip-Symbol.',"rules.pattern_ph":"regex, z. B. Stecker|Steckdose","rules.icon_ph":"mdi:power-socket-de","rules.add":"Regel hinzufügen","rules.reset":"Zurücksetzen auf Standardeinstellungen","rules.test_ph":"Versuch mal einen Gerätenamen...","rules.invalid":"ungültiges regex","rules.saved":"Icon-Regeln gespeichert","btn.up":"Nach oben","btn.down":"Nach unten","tap.info":"Gerätekarte","tap.more_info":"HA Mehr-Info-Dialog","tap.toggle":"Zustand umschalten","marker.tap_label":"Tap-Aktion für dieses Gerät","tap.toggle_note":"Der aufgelöste Zustand ist unten dargestellt. Sichere Geräte werden niemals aus dem Plan umgeschaltet.","import.title":"Bereiche aus HA-Etagen erstellen","import.hint":"Home Assistant kennt diese Etagen bereits. Die Etagen auswählen, die zu Planbereichen werden sollen; anschließend für jeden Bereich einen Grundriss hochladen. Die Räume werden danach von Hand eingezeichnet.","import.start":"{n} Bereich(e) erstellen","import.manual":"Von Grund auf neu starten","import.progress":"Etage {i} von {n}","import.done":"Bereiche erstellt. Räume einzeichnen: Rasterpunkte anklicken und die Kontur schließen.","btn.skip":"Überspringen","space.scale_label":"Maßstab (Rasterzellen-Größe)","space.cell_cm.help":"Verknüpft das Raster mit realen Abmessungen: Davon hängen Längen und Flächen, Wandstärken, Öffnungsgrößen und der Leuchtradius ab. Eine spätere Änderung verändert die berechneten Abmessungen des gesamten Bereichs, verschiebt aber keine Punkte im Plan.","space.cell_cm.help.aria":"Hilfe: Maßstab des Bereichs","space.scale_unit":"cm pro Zelle","space.scale_unit_imperial":"Zoll pro Zelle","space.display_section":"Anzeige","space.show_borders":"Raumgrenzen immer anzeigen","space.zero_wall_style":"Wände ohne Dicke","space.zero_wall_style.help":"Gestrichelte Wände ohne Dicke lassen Glow und Sonnenstrahlen durch, durchgezogene blockieren sie als Barriere ohne Fläche. Die Auswahl gilt für alle solchen Wände im Bereich, auch wenn ihre Linie in der Ansicht ausgeblendet ist.","space.zero_wall_style.help.aria":"Hilfe: Darstellung der Wände ohne Dicke","space.zero_wall_dashed":"Gestrichelt","space.zero_wall_solid":"Durchgezogen","space.show_names":"Raumnamen anzeigen (zum Verschieben ziehen)","space.room_color":"Farbe der Begrenzung & des Namens","space.opacity":"Deckkraft","space.fill_label":"Raumausfüllung","space.fill_mode.help":"„Eigene Farbe“ gestaltet den Bereich; „Licht“, „Temperatur“ und „LQI“ verwenden aktuelle Daten aus Home Assistant. Glow wird separat aktiviert.","space.fill_mode.help.aria":"Hilfe: Modus der Raumausfüllung","fill.none":"Keine","fill.lqi":"Zigbee-Signal","fill.light":"Lichter","fill.custom":"Benutzerdefinierte Farbe","space.custom_fill":"Füllfarbe","space.source_file":"Ich habe einen Grundriss als Bild","space.source_draw":"Kein Bild – ich werde die Räume von Hand umreißen","fill.temp":"Temperatur","tip.temp_avg":"Durchschnittstemperatur:","tip.hum_avg":"Durchschnittliche Luftfeuchtigkeit:","space_card.button":"Grundriss öffnen","space_card.not_found":"Bereich „{id}“ nicht gefunden","space_card.loading":"Laden…","continuity.restore_plan":"Grundriss wiederherstellen…","continuity.restore_connection":"Geräteverbindung wiederherstellen…","continuity.retry":"Erneut versuchen","editor.space":"Bereich","editor.framing":"Bildausschnitt","editor.fit_content":"Alle sichtbaren Inhalte","editor.fit_house":"Eng an der Hausgeometrie","editor.show_button":"Schaltfläche anzeigen","editor.button_label":"Beschriftung der Schaltfläche","editor.button_target":"Ziel-Dashboard-Pfad","marker.sub_entity":"Entität","title.general_settings":"Allgemeine Einstellungen","gs.title":"Allgemeine Einstellungen","gs.light_group":"Füllung: Licht","gs.light_on":"Lichter an","gs.light_off":"Alle Lichter aus","gs.temp_group":"Füllung: Temperatur","gs.temp_cold":"Kalt","gs.temp_ok":"Angenehm","gs.temp_hot":"Heiß","gs.lqi_group":"Füllung: Zigbee-Signal","gs.lqi_low":"Schwaches Signal","gs.lqi_high":"Starkes Signal","gs.reset":"Auf Standard zurücksetzen","gs.saved":"Allgemeine Einstellungen gespeichert","space.show_lqi":"Zigbee-Signal (LQI) neben Geräten anzeigen","space.hide_decor":"Dekorationsschicht ausblenden","space.hide_decor_tip":"Linien, Formen, Beschriftungen und Möbel bleiben an ihrem Platz — im Hintergrundeditor sichtbar, aber nicht auf dem Plan.","space.hide_openings":"Öffnungen ausblenden","space.hide_openings_tip":"Tür-, Fenster- und Tor-Symbole werden nicht gezeichnet, aber die Öffnungen funktionieren weiterhin: Licht fällt hindurch, die Sonne kommt durch ein Fenster herein, Kontaktsensoren öffnen sie weiterhin. Der Planeditor zeigt sie immer an.","gs.light_none":"Keine Lichtquellen","mode.plan":"Planeditor","mode.devices":"Geräteeditor","display.value":"Wert + Zustand","marker.subarea":"kein Bereich, manuell","device.new":"Neues Gerät — Editor öffnen, um zu schließen","opening.unlock_action":"Entsperren","opening.lock_action":"Sperren","opening.lock_pending":"Wird ausgeführt…","title.close_editor":"Editor schließen (zur Ansicht zurück)","title.add_device":"Gerät zum Plan hinzufügen","devbar.add":"Hinzufügen","devbar.rules":"Symbolregeln","device_inbox.button":"Geräte","device_inbox.title":"Geräte auf dem Plan","device_inbox.search":"Geräte, Entitäten und Integrationen suchen…","device_inbox.add_virtual":"Virtuelles Gerät hinzufügen","device_inbox.tab_on_plan":"Auf Plan","device_inbox.tab_available":"Verfügbar","device_inbox.tab_hidden":"Versteckt","device_inbox.tab_readd":"Wieder verfügbar","device_inbox.only_new":"Nur neu","device_inbox.show_entities":"Entitäten anzeigen","device_inbox.show_hidden":"Versteckte auf Plan anzeigen","device_inbox.show_hidden.help":"Zeigt ausgeblendete und deaktivierte Marker vorübergehend als Bearbeitungs-Geister auf dem Plan. Die gespeicherte Sichtbarkeit der Geräte bleibt unverändert.","device_inbox.show_hidden.help.aria":"Hilfe: ausgeblendete Geräte auf dem Plan anzeigen","device_inbox.new":"Neu","device_inbox.find":"Auf dem Plan finden","device_inbox.edit":"Bearbeiten","device_inbox.hide":"Ausblenden","device_inbox.show":"Anzeigen","device_inbox.add":"Hinzufügen","device_inbox.readd":"Wieder hinzufügen","device_inbox.hide_available":"Aus der Liste ausblenden","device_inbox.show_more":"Mehr anzeigen","device_inbox.more_actions":"Weitere Aktionen","device_inbox.find_hidden_hint":"Zuerst „Versteckte auf Plan anzeigen“ aktivieren","device_inbox.show_disabled":"Diese Bindung in Home Assistant aktivieren, bevor sie angezeigt wird","device_inbox.empty_on_plan":"Es befinden sich noch keine passenden Geräte auf dem Plan.","device_inbox.empty_available":"Es sind keine Geräte zum Hinzufügen verfügbar.","device_inbox.empty_hidden":"Es gibt keine versteckten Geräte.","device_inbox.empty_readd":"Es sind keine entfernten Geräte verfügbar, um sie erneut hinzuzufügen.","device_inbox.reason_visible_auto":"Automatisch erkannt","device_inbox.reason_visible_explicit":"Explizit hinzugefügt","device_inbox.reason_manual_hidden":"Vom Benutzer versteckt","device_inbox.reason_automatic_hidden":"Automatisch versteckt","device_inbox.reason_service_entry":"Nur Service-Registry-Eintrag","device_inbox.reason_excluded_integration":"Integration „{integration}“ durch Erkennungsfilter ausgeschlossen","device_inbox.reason_excluded_domain":"Nicht-räumlicher Entitätstyp","device_inbox.reason_grouped_light":"Dargestellt durch eine Raumlichtgruppe","device_inbox.reason_represented_by_parent":"Dargestellt durch sein übergeordnetes Gerät","device_inbox.reason_removed":"Zuvor aus dem Plan entfernt","device_inbox.reason_available":"Zum Hinzufügen zum Plan verfügbar","device_inbox.reason_no_bound_room":"HA-Bereich ist nicht mit einem Planraum verknüpft","device_inbox.status_ha_disabled":"In Home Assistant deaktiviert","device_inbox.status_orphaned":"Bindung ist in Home Assistant nicht mehr vorhanden","device_inbox.status_unverified":"Home Assistant-Register vorübergehend nicht verfügbar","device_inbox.saved":"Geräteliste aktualisiert","device_inbox.filters_excluded":"Ausgeschlossene Integrationen","device_inbox.filters_group_lights":"Raumleuchten zu einem Marker gruppieren","device_inbox.filters_preview_appear":"erscheint: {count}","device_inbox.filters_preview_hide":"verschwindet: {count}","device_inbox.filters_preview_lights":"betroffene Leuchten: {count}","device_inbox.filters_reset":"Empfohlene wiederherstellen","device_inbox.filters_save":"Filter speichern","device_inbox.filters_search_ph":"Integration hinzufügen…","device_inbox.filters_title":"Erkennungsfilter","space.roomcard_section":"Raumkarte zeigt:","space.label_temp":"Temperatur","space.label_hum":"Luftfeuchtigkeit","space.label_lqi":"Durchschnittliches Zigbee-Signal","space.label_light":"Lichter ein/aus","roomcard.light_on":"Ein","roomcard.light_off":"Aus","roomcard.light_partial":"{on} von {total}","toast.split_pick_inside":"Zwischenliegende Schnittpunkte müssen innerhalb des Raumes liegen","mode.decor":"Hintergrundeditor","decor.select":"Auswählen","decor.line":"Linie","decor.rect":"Rechteck","decor.ellipse":"Oval","decor.text":"Text","decor.erase":"Löschen","decor.erase_confirm_title":"Objekt löschen?","decor.color":"Farbe","decor.width":"Linienbreite","decor.line_style":"Linienstil","decor.line_style_solid":"Durchgehend","decor.line_style_dashed":"Gepunktet","decor.fill":"Füllen","decor.fill_color":"Füllfarbe","decor.length":"Länge","decor.size":"Größe","decor.flip_h":"Horizontal spiegeln","decor.flip_v":"Vertikal spiegeln","decor.angle":"Rotationswinkel, °","decor.text_size":"Textgröße","decor.backdrop_properties":"Eigenschaften des Planhintergrunds","decor.text_title":"Textbeschriftung","decor.object_title":"{kind} bearbeiten","decor.text_label":"Text","decor.live_group":"HA-Variable einfügen","decor.live_entity":"Entität","decor.live_entity_ph":"Wählen Sie eine Entität","decor.live_attr":"Wert","decor.live_attr_ph":"Wählen Sie Status oder Attribut","decor.live_state":"Status","decor.backdrop":"Hintergrundbild","decor.backdrop_hint":"Ziehen zum Verschieben; eine Ecke ziehen zum Größenändern; den oberen Griff zum Drehen verwenden. Shift ändert das Verhältnis oder befreit den Winkel.","decor.backdrop_reset":"Bild zurücksetzen","decor.backdrop_reset_done":"Das Bild ist wieder an seinem ursprünglichen Platz und in seiner ursprünglichen Größe","marker.icon_auto":"Auto: {icon} (nach Symbolregeln; wählen Sie eines zur Überschreibung)","marker.icon_pin_auto":"Anheften","mode.plan_tip":"Planungseditor — die Geometrie des Hauses: Räume zeichnen und teilen/zusammenführen, sie mit HA-Bereichen verbinden, Türen, Fenster und Tore platzieren, Raumkarten verschieben, Maßstab festlegen","mode.devices_tip":"Geräteeditor — alles über Symbole: ziehen zum Positionieren, klicken zum Bearbeiten von Bindung/Symbol/Anzeige, virtuelle Geräte hinzufügen, Symbolregeln","mode.decor_tip":"Hintergrundeditor — rein visuelle Dekoration unter dem Plan: Linien, Rechtecke, Ellipsen und Textbeschriftungen, die niemals auf Klicks reagieren","space.glow_enabled":"Lichtquellen-Glühen","gs.glow_group":"Glow von Lichtquellen","gs.glow_base":"Grunddunkelheit des Hauses","gs.glow_light":"Standardlichtfarbe / Intensität","gs.wall_group":"Wände","gs.wall_fill":"Wandfüllung","gs.glow_radius":"Glow-Radius","gs.glow_radius.help":"Legt den allgemeinen Radius des Lichtscheins in Metern oder Fuß fest; ein gerätespezifischer Radius überschreibt diesen Wert.","gs.glow_radius.help.aria":"Hilfe: allgemeiner Glow-Radius","gs.unit_m":"m","gs.unit_ft":"ft","marker.controls_label":"Steuert andere Lichtquellen","marker.controls.help":"Mit der Aktion „Zustand umschalten“ werden die aufgeführten Quellen zusammen mit diesem Marker umgeschaltet. Ihr Glow bleibt an ihren eigenen Markern, und die Verknüpfung allein macht den steuernden Marker nicht zur Lichtquelle.","marker.controls.help.aria":"Hilfe: andere Lichtquellen steuern","marker.controls_filter":"Suchlichter und Schalter…","info.controls":"Steuerungen","marker.glow_radius_label":"Leuchtradius","marker.glow_radius.help":"Legt den Leuchtradius in Metern oder Fuß fest; ein leerer Wert verwendet den Radius aus den allgemeinen Einstellungen.","marker.glow_radius.help.aria":"Hilfe: Leuchtradius","markup.wallthick":"Dicke","markup.select":"Auswählen","title.markup_wallthick":"Dicke — klicken Sie auf eine Wand, um ihre Dicke von 0 bis 100 cm festzulegen.","markup.hint_wallthick":"klicken Sie auf eine Wand · Esc schließt ohne Anwendung","wallthick.field":"Dicke","wallthick.unit_cm":"cm","wallthick.unit_in":"in","wallthick.apply_room":"Auf alle Wände dieses Raums anwenden","markup.draw_wall_title":"Dicke jedes neuen Wandsegments (0–100 cm). Gemeinsame Wände behalten den bestehenden Wert.","room.queue_progress":"Raum {current} von {total}","toast.wall_rooms_saved":"Erstellte Räume: {n}","toast.wall_chain_saved":"Wandkette gespeichert","toast.wallthick_pick":"Eine Wand anklicken","toast.wallthick_set":"Wandstärke eingestellt","toast.wallthick_cleared":"Wandstärke entfernt","toast.physical_range":"Einen Wert von {min} bis {max} {unit} eingeben","toast.zero_wall_opening_conflict":"Entfernen Sie zuerst die Öffnung an diesem Wandsegment.","toast.zero_wall_ambiguous":"Das Wandsegment ist mehrdeutig. Vereinfachen oder passen Sie den Anschluss an.","toast.zero_wall_migration_blocked":"Der Bereich wurde nicht konvertiert: {reason}. Es wurden keine Daten geändert.","toast.physical_angle":"Einen Drehwinkel von 0° bis unter 90° eingeben","toast.physical_limit":"Der Bereich hat das Limit für diesen Geometrietyp erreicht","toast.geometry_unsafe":"Änderung abgebrochen: Wandgeometrie konnte nicht sicher erstellt werden.","junction.limit_angle":"Der Winkel zwischen den Wänden ist zu spitz: {actual}°, mindestens {limit}°.","junction.limit_valence":"Zu viele Wände treffen in einem Knoten aufeinander: {actual}, maximal {limit}.","junction.limit_length":"Das Wandsegment ist zu kurz: {actual} cm, mindestens {limit} cm.","junction.limit_distance":"Wände und Knoten sind zu dicht beieinander: {actual} cm, Minimum {limit} cm.","junction.limit_clearance":"Kein Wohnbereich ist übrig: {actual} cm², Minimum {limit} cm².","junction.limit_check_failed":"Die Überprüfung der Verbindungen konnte nicht durchgeführt werden — die Änderung wurde nicht gespeichert.","toast.wall_model_migration_blocked":"Das Wandmodell konnte nicht aktualisiert werden: {reason}. Der Plan wurde nicht geändert. Führen Sie „Pläne optimieren“ aus; wenn der Fehler erneut auftritt, beheben Sie die widersprüchliche Wandgeometrie.","toast.wall_model_client_outdated":"Aktualisieren Sie die Karte und laden Sie die Seite neu, bevor Sie den Plan bearbeiten.","wall_model.reason.invalid-room":"ungültiger Raumkontur","wall_model.reason.zero-length":"Wandsegment mit null Länge","wall_model.reason.third-owner":"Wand, die von mehr als zwei Räumen geteilt wird","wall_model.reason.duplicate-id":"widersprüchliche Wandkennungen","wall_model.reason.thickness-conflict":"widersprüchliche Wandstärkenwerte","wall_model.reason.opening-host":"Öffnung kann nicht einer Wand zugewiesen werden","toast.delete_room_pick":"Klicken Sie in den Raum, den Sie löschen möchten","toast.plan_snap_ambiguous":"Zoomen Sie hinein, um den Wandknoten auszuwählen","toast.wall_repair_ambiguous":"Der Raumumriss hat mehr als eine mögliche Verbindung. Zoomen Sie hinein und verbinden Sie ihn explizit.","toast.wall_repair_too_large":"Die Lücke ist größer als 2 cm. Verbinden Sie die Wände, bevor Sie den Raum erstellen.","toast.wall_repair_changed":"Die Wandgeometrie hat sich geändert. Versuchen Sie erneut, den Raum zu erstellen.","toast.opening_on_zero_wall":"Öffnungen können nicht auf einer Wand mit null Dicke sitzen.","marker.from_ha_option":"Wählen Sie aus der HA-Liste.","marker.show_entities":"Entitäten anzeigen.","marker.show_entities_tip":"Fügt nicht nur Geräte zur Liste hinzu, sondern auch alle ihre Entitäten.","marker.pick_ph":"Wählen Sie ein Gerät…","room.open_area":"Öffnen Sie den HA-Bereich.","view.volumetric":"Volumetrische Ansicht.","view.flat":"Flache Ansicht.","kiosk.title":"Die Größen dieses Bildschirms.","kiosk.hint":"Nur auf diesem Gerät gespeichert – jedes Wandtablet oder TV kann seine eigenen komfortablen Größen haben.","kiosk.icon_scale":"Gerätesymbolgröße.","kiosk.font_scale":"Textgröße der Raumkarte.","editor.kiosk":"Wandgeräte- (Kiosk-)Modus.","editor.cycle":"Bereiche automatisch alle N Sekunden wechseln (Kiosk, 0 = aus)","room.settings_title":"Raumeinstellungen.","room.settings_section":"Raumeinstellungen (überschreibt den Bereich)","room.fill_label":"Diesen Raum ausfüllen","fill.inherit":"Als den Bereich","room.custom_fill_space":"Bereichsfarbe","room.custom_fill_own":"Raumfarbe","room.temp_src_label":"Temperaturquelle","room.hum_src_label":"Luftfeuchtigkeitsquelle","room.src_average":"Durchschnitt über die Sensoren des Raums (Standard)","room.src_pick":"Ein bestimmtes HA-Gerät oder Entität","room.src_ph":"Quelle wählen…","toast.room_updated":"Raum aktualisiert","space.card_font":"Schriftgröße der Raumkarte (gesamter Bereich)","room.sizes_section":"Schriftgrößen","room.name_scale":"Raumname Größe","room.label_scale":"Metrikgröße","preview.room_name":"Wohnzimmer","toast.cfg_reload_failed":"Der Plan konnte nicht vom Server neu geladen werden: {err}","toast.locale_load_failed":"Das Sprachpaket konnte nicht geladen werden. Bis zum Neuladen der Seite wird Englisch verwendet.","room.settings_short":"Raumeinstellungen","room.unnamed":"Unbenannter Raum","marker.use_climate_temp":"Geräte-Temperatur im Raum berücksichtigen","marker.use_climate_temp_tip":"Fügt die aktuelle Temperatur einer Klimaanlage oder eines Thermostats zum Raumdurchschnitt hinzu. Das externe Wert-Label unten separat konfigurieren.","marker.value_badge_title":"Wert-Label","marker.value_badge.help":"Zeigt einen ausgewählten Wert neben dem Symbol an. Dies beeinflusst nicht die Raumkennzahlen, Licht, Glanz oder die Tippaktion.","marker.value_badge.help.aria":"Hilfe: Gerätewert-Badge","marker.value_badge_enabled":"Zeige ein Wert-Badge","marker.value_badge_source":"Wert","marker.value_badge_source.help":"Wählen Sie einen bestimmten Zustand, ein unterstütztes Attribut oder einen abgeleiteten Wert dieses Geräts.","marker.value_badge_source.help.aria":"Hilfe: Quelle des Wert-Badges","marker.value_badge_position":"Position","marker.value_badge_position.help":"Die gewählte Seite bleibt fest und dreht sich nicht automatisch an einem Planrand.","marker.value_badge_position.help.aria":"Hilfe: Position des Wert-Badges","marker.value_badge_right":"Rechts","marker.value_badge_bottom":"Unten","marker.value_badge_left":"Links","marker.value_badge_top":"Oben","marker.value_badge_empty":"Für dieses Gerät stehen keine Werte zur Verfügung","marker.value_badge_static":"Ein statisches Symbol zeigt keine Live-Werte an. Die Einstellung wird beibehalten.","marker.value_badge_missing":"Quelle nicht verfügbar","marker.value_badge_missing_hint":"Die gespeicherte Quelle ist derzeit nicht verfügbar. Behalten Sie sie bei, deaktivieren Sie das Badge oder wählen Sie einen anderen Wert.","marker.value_badge_duplicate":"Derselbe Wert wird bereits im Symbol angezeigt.","marker.value_badge_state":"Status · {name}","marker.value_badge_marker_state":"Lichtquellstatus · {name}","marker.value_badge_lqi":"Durchschnittliche Zigbee-Signalqualität","marker.value_badge_attr_current_temperature":"Aktuelle Temperatur · {name}","marker.value_badge_attr_temperature":"Zieltemperatur · {name}","marker.value_badge_attr_current_humidity":"Aktuelle Luftfeuchtigkeit · {name}","marker.value_badge_attr_humidity":"Luftfeuchtigkeit · {name}","marker.value_badge_attr_current_position":"Position · {name}","marker.value_badge_attr_percentage":"Geschwindigkeit · {name}","marker.value_badge_attr_brightness":"Helligkeit · {name}","marker.value_badge_attr_volume_level":"Lautstärke · {name}","marker.value_badge_attr_battery_level":"Batterie · {name}","marker.value_badge_attr_fan_speed":"Lüftergeschwindigkeit · {name}","marker.value_source":"Wertquelle","marker.value_source.help":"Wähle den Wert, der das Symbol ersetzt. Die Tipp-Aktion bleibt unverändert.","marker.value_source.help.aria":"Hilfe: Wertquelle in der Gerätefläche","marker.value_source_auto":"Automatisch (wie bisher)","marker.value_source_missing_hint":"Die gespeicherte Quelle ist derzeit nicht verfügbar. Bis sie wieder verfügbar ist oder ein anderer Wert gewählt wird, zeigt die Fläche —.","marker.light_role_label":"Ist dieses Gerät eine Lichtquelle?","marker.light_role.help":"„Auto“ verwendet die ermittelte Rolle des verknüpften Geräts, „Immer“ erzwingt eine eigene Quelle und „Nie“ schließt sie aus; oben verknüpfte Lichter bleiben unabhängig.","marker.light_role.help.aria":"Hilfe: ob dieses Gerät eine Lichtquelle ist","marker.light_role_auto_yes":"Automatisch (Lichtquelle)","marker.light_role_auto_no":"Automatisch (keine Lichtquelle)","marker.light_role_always":"Immer eine Lichtquelle","marker.light_role_never":"Nie eine Lichtquelle","marker.light_entity_label":"Führende Lichtereinheit","marker.light_entity.help":"Für ein Verbundgerät wählen Sie die Entität, deren Zustand, Farbe und Helligkeit diese Planquelle darstellen. Der automatische Rückgriff bleibt mit älteren Plänen kompatibel.","marker.light_entity.help.aria":"Hilfe: führende Lichtentität","marker.light_entity_auto":"Automatisch ({entity})","marker.light_entity_none":"keine steuerbare Entität","marker.light_entity_missing":"Die gespeicherte Entität {entity} ist nicht verfügbar. House Plan verwendet vorübergehend {fallback}; die gespeicherte Auswahl wird wiederhergestellt, wenn sie zurückkehrt.","marker.toggle_entity_label":"Zu toggelnde Entität","marker.toggle_entity.help":"Für ein Verbundgerät wählen Sie das genaue eigene Licht oder den Schalter, der durch Tippen bedient wird. Automatisch behält die vorherigen Zielregeln bei und ist unabhängig von der führenden Lichtentität.","marker.toggle_entity.help.aria":"Hilfe: zu toggelnde Entität","marker.toggle_entity_auto":"Automatisch ({entity})","marker.toggle_entity_none":"keine eigene steuerbare Entität","marker.toggle_entity_missing":"Die gespeicherte Entität {entity} ist nicht mehr unter den auswählbaren Kanälen dieses Markers. House Plan verwendet vorübergehend {fallback}; die gespeicherte Auswahl wird wiederhergestellt, wenn sie zurückkehrt.","marker.glow_color_label":"Leuchtfarbe und Helligkeit","marker.glow_mode.help":"Verwenden Sie Live-Quellwerte, überschreiben Sie nur deren Farbe oder fixieren Sie sowohl Farbe als auch Helligkeit. Das Minimum beträgt 1 %; um die Quelle zu deaktivieren, wählen Sie „Nie“.","marker.glow_mode.help.aria":"Hilfe: Leuchtfarbe und Helligkeit","marker.glow_mode_auto":"Von Quelle","marker.glow_mode_color":"Farbe einstellen","marker.glow_mode_fixed":"Farbe und Helligkeit einstellen","marker.glow_color":"Leuchtfarbe","marker.glow_brightness":"Helligkeit","marker.glow_disabled_never":"Leuchteinstellungen sind nicht verfügbar, da dieser Marker ausdrücklich keine Lichtquelle ist.","marker.glow_disabled_auto":"Im Automatikmodus wurde keine räumliche Lichtquelle für diesen Marker gefunden.","marker.glow_disabled_no_entity":"Keine aktive steuerbare Home Assistant-Entität ist für diese räumliche Quelle verfügbar.","marker.glow_passive_hint":"Diese Quelle hat keine eigenen Home Assistant-Daten. Stellen Sie ihre Farbe und Helligkeit manuell ein; ihr Radius bleibt verfügbar.","marker.control_broken":"Gespeicherte Quelle fehlt oder ist nicht mehr als Licht markiert","marker.control_missing_label":"Fehlendes Planlicht","marker.control_passive":"passive Quelle","toast.marker_control_cycle":"Dieser Link würde eine kreisförmige Kette von Lichtsteuerungen erzeugen.","toast.marker_binding_required":"Wählen Sie ein Home Assistant-Gerät, bevor Sie eine andere Lichtquelle verlinken.","confirm.unlock_title":"Schloss öffnen?","confirm.unlock_body":"House Plan sendet einen Befehl zum Öffnen an dieses Schloss.","toast.files_migrate_failed":"Anhänge konnten nicht zur neuen Bindung verschoben werden, Links zeigen weiterhin auf die alten Dateien: {err}","space.pick_saved":"Bereits hochgeladen","space.pick_saved_hint":"Auf dem Server gespeicherte Pläne, einschließlich solcher, die Sie zuvor getrennt haben","space.no_saved":"Noch keine Pläne auf dem Server gespeichert.","space.loading":"Laden…","space.used_by":"in Benutzung: {list}","space.in_use":"Ein Bereich verwendet diesen Plan noch — zuerst die Verknüpfung lösen","btn.use":"Verwenden","confirm.delete_plan_title":"Plandatei löschen?","confirm.delete_plan_body":"Die Datei wird vom Server gelöscht. Dieser Vorgang kann nicht rückgängig gemacht werden.","toast.plans_list_failed":"Konnte die gespeicherten Pläne nicht auflisten: {err}","toast.plan_delete_failed":"Konnte den Plan nicht löschen: {err}","marker.hide":"Ausblenden","marker.hide_tip":'Das Gerät wird nach dem Speichern aus dem Plan verschwinden, aber weiterhin zum Signalsignal des Raums zählen. Stellen Sie es über den Katalog "Geräte" im Geräte-Editor wieder her.',"marker.show":"Anzeigen","marker.show_tip":"Das Gerät wird nach dem Speichern wieder im Plan erscheinen.","marker.hidden_ghost":"Vom Benutzer ausgeblendetes Gerät","marker.ha_disabled_device":"Das Gerät ist in Home Assistant deaktiviert und im Plan ausgeblendet.","marker.ha_disabled_entity":"Die Entität ist in Home Assistant deaktiviert und im Plan ausgeblendet.","marker.ha_disabled_all_entities":"Das Gerät hat keine aktiven Home Assistant-Entitäten, daher ist es im Plan ausgeblendet.","marker.ha_registry_limited":"Das vollständige Home Assistant-Register ist für diesen Benutzer nicht verfügbar. Das nicht verifizierte Objekt kann vorerst nicht angezeigt oder verwendet werden.","marker.delete_tip":"Löschen Sie das Gerät vollständig aus dem Plan und allen Aggregaten. Sie können es später wieder hinzufügen.","tap.run":"Führen Sie Automation/Skript/Szene aus","tap.none":"Nichts tun","marker.run_target_label":"Was ausführen","marker.run_search_ph":"Suchen: Automation, Skript oder Szene…","marker.run_target_gone":"Ziel {id} nicht gefunden — erneut auswählen","marker.tap_confirm":"Um Bestätigung bitten","marker.tap_confirm_tip":"Vor der Ausführung ein Bestätigungsdialogfeld anzeigen — eine Vorsichtsmaßnahme gegen versehentliche Berührungen.","marker.toggle_hint_single":"Ziel: {name} ({id}).","marker.virtual_light_target":"Virtuelles Licht: {name}.","marker.virtual_light_current":"Manueller Zustand: {state} → {effect}.","marker.virtual_light_state_on":"ein","marker.virtual_light_state_off":"aus","marker.toggle_hint_group":"Wird {count}-Quelle(n) umschalten: {names}.","marker.toggle_hint_current":"Jetzt: {state} → {effect}.","marker.toggle_hint_group_current":"Derzeit an: {on} von {count} → {effect}.","marker.toggle_hint_skipped":"Wird übersprungen ({count}): {targets}.","marker.toggle_effect_turn_on":"wird eingeschaltet","marker.toggle_effect_turn_off":"wird ausgeschaltet","marker.toggle_effect_open":"wird geöffnet","marker.toggle_effect_close":"wird geschlossen","marker.toggle_effect_stop":"wird gestoppt","marker.toggle_effect_toggle":"Zustand wird umgeschaltet","marker.toggle_skip_missing":"nicht gefunden","marker.toggle_skip_ha_disabled":"in HA deaktiviert","marker.toggle_skip_unavailable":"nicht verfügbar","marker.toggle_skip_unsupported":"Umschalten wird nicht unterstützt","marker.toggle_skip_secure":"aus Sicherheitsgründen blockiert","marker.toggle_none_no_binding":"Dieses Gerät hat keine Bindung, daher gibt es keinen Zustand, der umgeschaltet werden könnte. Tippen bewirkt nichts.","marker.toggle_none_no_actionable_entity":"Dieses Gerät hat keinen Zustand, der umgeschaltet werden könnte. Tippen bewirkt nichts.","marker.toggle_none_configured_targets_missing":"Die konfigurierten Ziele sind nicht verfügbar. Die eigene Entität des Geräts wird nicht ersetzt.","marker.toggle_none_ha_disabled":"Das Ziel ist in Home Assistant deaktiviert und kann im Plan nicht verwendet werden.","marker.toggle_none_unavailable":"Das Ziel ist derzeit nicht verfügbar. Tippen bewirkt nichts.","marker.toggle_none_unsupported":"Home Assistant bietet keine sichere Umschaltfunktion für dieses Gerät. Tippen bewirkt nichts.","marker.toggle_none_secure":"Das Umschalten von Schlössern, Alarmen und gesicherten Toren über den Plan ist aus Sicherheitsgründen gesperrt.","run.automation":"Automatisierung","run.script":"Skript","run.scene":"Szene","confirm.tap_run":'"{name}" ausführen?',"confirm.tap_toggle":'"{name}" umschalten?',"confirm.current_state":"Aktueller Zustand: {state}","confirm.expected_state":"Nach dem Umschalten: {state}","confirm.group_current":"an {on} von {total}","confirm.group_all_on":"alle sind eingeschaltet","confirm.group_all_off":"alle sind ausgeschaltet","confirm.unavailable_targets":"Nicht verfügbar: {count}","confirm.expected_by_ha":"Home Assistant ermittelt den Zustand","confirm.state_on":"Ein","confirm.state_off":"Aus","confirm.state_open":"Offen","confirm.state_closed":"Geschlossen","confirm.state_opening":"Wird geöffnet","confirm.state_closing":"Wird geschlossen","confirm.state_stopped":"Gestoppt","confirm.state_unknown":"Unbekannt","toast.run_started":"Gestartet: {name}","toast.run_target_missing":"Ausführungsziel nicht gefunden — überprüfen Sie die Geräteeinstellungen","toast.run_target_required":"Wählen Sie eine Automatisierung, ein Skript oder eine Szene aus","toast.tap_target_changed":"Das Ziel der Aktion hat sich geändert. Versuchen Sie es erneut.","toast.virtual_light_toggle_failed":"Das virtuelle Licht konnte nicht umgeschaltet werden: {err}","toast.value_badge_source_required":"Einen Wert für den Badge auswählen","btn.run":"Ausführen","vac.section":"Roboterstaubsauger: aktuelle Position","vac.autocal":"Automatisch einrichten","vac.live":"Aktuelle Position im Plan","vac.trail":"Roboterpfad anzeigen","vac.autocal_no_rooms":'Die Integration meldet keine Raumliste — öffnen Sie "Manuell anpassen"',"vac.route_warn_unmapped":"Der Roboter reinigt eine Karte, die keiner Etage zugeordnet ist","vac.route_warn_needs_calibration":"Die Karte ist einer Etage zugeordnet, aber nicht kalibriert","vac.route_warn_ambiguous":"Zwei Karten sind nicht unterscheidbar — keine Etage gewählt","vac.route_warn_missing_space":"Der Raum dieser Karte wurde gelöscht","vac.autocal_no_match":'Raumnamen stimmten nicht überein (mindestens 3 müssen übereinstimmen) — öffnen Sie "Manuell anpassen"',"vac.autocal_done":"Fertig: über {rooms} Räume zugeordnet. Eine Reinigung starten und das Ergebnis prüfen.","vac.cal_need_pos":"Der Roboter meldet keine Koordinaten — starten Sie eine Reinigung und pausieren Sie sie","vac.cal_done":"Kalibrierung gespeichert. Eine Reinigung starten und das Ergebnis prüfen.","vac.cal_cancelled":"Kalibrierung abgebrochen","vac.fit":"Manuell anpassen","vac.fit_hint":"Roboterkarte an die richtige Position ziehen und an den Ecken skalieren","vac.fit_rotate":"90° drehen","vac.fit_mirror":"Spiegeln","vac.trail_never":"Nie","vac.trail_cleaning":"Beim Reinigen","vac.trail_always":"Immer","gs.bg_group":"Bühnenhintergrund","gs.bg_color":"Hintergrund um den Plan","gs.bg_default":"Standardthema","gs.bg_theme":"Standardthema","gs.bg_mode":"Planhintergrund","gs.bg_mode.help":"„Folgt der Sonne“ verwendet sun.sun und ersatzweise die lokale Browserzeit; „Statische Farbe“ zeigt immer die ausgewählte Farbe.","gs.bg_mode.help.aria":"Hilfe: allgemeiner Planhintergrund","gs.bg_static":"Statische Farbe","gs.bg_daynight":"Folgt der Sonne","gs.sun_group":"Sonne","gs.sun_missing":"Die sun.sun-Entität wurde nicht gefunden — der Hintergrund folgt Ihrer lokalen Uhr; Fensterstrahlen sind nicht verfügbar.","gs.north":"Norden auf dem Plan","gs.north.help":"Der Winkel wird im Uhrzeigersinn von der oberen Vertikalen des Plans gemessen; Norden wird für Fensterstrahlen benötigt, nicht für den Hintergrund „Folgt der Sonne“.","gs.north.help.aria":"Hilfe: allgemeine Nordrichtung","gs.north_ph":"nicht gesetzt","gs.north_clear":"Löschen","gs.north_letter":"N","gs.sun_rays":"Sonnenlicht durch Fenster","gs.about_version":"House Plan Card v{v}","gs.about_github":"GitHub · Dokumentation & Probleme","gs.about_telegram":"Telegram-Chat","support.title":"Hilfe & Feedback","space.bg_color":"Hintergrund rund um den Plan","space.bg_inherit":"Allgemein erben","space.bg_inherited":"erbt allgemeine Einstellungen","space.bg_mode":"Planhintergrund","space.bg_mode.help":"Übernehmen Sie den allgemeinen Hintergrund oder überschreiben Sie diesen Bereich mit einer statischen Farbe oder „Folgt der Sonne“.","space.bg_mode.help.aria":"Hilfe: Hintergrund des Bereichs","space.north":"Norden auf dem Plan (überschreiben)","space.north.help":"Überschreibt die allgemeine Nordrichtung für diesen Bereich; der Winkel wird im Uhrzeigersinn von der oberen Vertikalen des Plans gemessen und für Fensterstrahlen verwendet.","space.north.help.aria":"Hilfe: Norden für diesen Bereich","space.north_inherited":"geerbt: {v}","space.sun_rays":"Sonnenlicht durch Fenster","space.sun_inherit":"Allgemein erben","space.sun_on":"Ein","space.sun_off":"Aus","canvas.far_objects":"{n} Objekt(e) weit vom Plan entfernt","canvas.show_far":"Anzeigen","canvas.home_tip":"Der Plan ist dort drüben — klicken, um ihn anzupassen","gs.grid_group":"Planwartung","gs.grid_hint":"Aktualisiert Datenmodelle, richtet Planelemente am Raster aus und fasst redundante Wandfragmente zusammen. Ein exakter Bericht wird angezeigt, bevor etwas gespeichert wird.","gs.align_all":"Pläne optimieren","gs.align_title":"Pläne optimieren","gs.align_none":"Alle Pläne verwenden bereits das aktuelle optimierte Datenmodell.","gs.optimize_no_automatic_changes":"Es gibt keine automatischen Änderungen, die angewendet werden müssen. Überprüfen Sie die unten stehenden Punkte.","gs.align_count":"{n} von {total} Elementen werden sich um höchstens {cm} cm bewegen.","gs.align_where":"Die größte Verschiebung ist in „{s}“.","gs.align_turned":"Öffnungen, deren Winkel korrigiert wurde: {n}.","gs.align_removed_drafts":"Ungültige Umrisse vom Raster zusammengeklappt und entfernt: {n}.","gs.optimize_redundant_drafts":"Gespeicherte Wandketten, die durch feste Raumwände verdeckt waren, wurden entfernt: {n}.","gs.align_preflight_failed":"Die Geometrie der folgenden Bereiche konnte nicht sicher überprüft werden: {spaces}{more}.","gs.align_preflight_hint":"Pläne wurden nicht geändert. Kopieren Sie die Diagnosen mit dem untenstehenden Button und fügen Sie sie zusammen mit einem Raumexport dem Fehlerbericht bei.","gs.preflight_reason_prepare-exception":"Die Bereichsgeometrie konnte nicht vorbereitet werden (Ausnahme beim Erstellen des Modells)","gs.preflight_reason_wall-null":"Der Wandkörper wurde nicht erstellt (die Vereinigung lieferte leer zurück)","gs.preflight_reason_wall-degraded-extra":"Der Wandkörper wurde mit zusätzlicher Geometrie beschädigt","gs.preflight_reason_wall-failed-core":"Der Kern des Wandkörpers konnte nicht zusammengesetzt werden","gs.preflight_reason_wall-exception":"Die Wandkonstruktion warf eine Ausnahme","gs.preflight_reason_floor-null":"Der Fußbodenumriss wurde nicht erstellt","gs.preflight_reason_floor-exception":"Bodenaufbau hat eine Ausnahme ausgelöst","gs.preflight_copy":"Diagnosen kopieren","gs.preflight_copied":"Diagnosen kopiert","gs.preflight_update_hint":"Die Karten- und Integrationsversionen unterscheiden sich — Hausplan aktualisieren und erneut versuchen.","gs.align_preflight_space":"Bereich {n}","gs.align_preflight_more":", und {n} mehr","gs.optimize_changes":"Modellmigrationen: {m}; aktualisierte Bereiche: {c}; entfernte verrauschte Koordinatenwerte: {p}; zusammengeführte Fragmente realer Wände: {w}; zusammengeführte Fragmente von Wänden ohne Dicke: {s}; unabhängige Wände: {i}.","gs.zero_walls_migrated":"Virtuelle Wandspannweiten konvertiert: {n}.","gs.wall_segments_migrated":"Wandsegmente stabilisiert: {n}.","gs.optimize_lattice_summary":"Rauschen in den Koordinatenwerten kanonisiert: {n}; maximale Bewegung: {cm} cm.","gs.optimize_lattice_space":"{space}: Koordinatenwerte kanonisiert: {n}; außerhalb des Rasters liegende Werte unverändert gelassen: {far}.","gs.optimize_coincident_partitions":"Versteckte unabhängige Wandabschnitte in Raumwände integriert: {n}.","gs.optimize_openings_rehosted":"Öffnungen wieder an Raumwände angebracht: {n}.","gs.optimize_walls_straightened":"Wände begradigt: {n}; maximale Bewegung: {cm} cm.","gs.optimize_walls_straightened_where":"Größte Wandkorrektur: {s}.","gs.optimize_walls_straighten_skipped":"Nahe Achsenwände unverändert gelassen, da sie nicht sicher repariert werden konnten: {n}.","gs.optimize_glow_migration":"Legacy Glow: {spaces} Bereiche → keine Datenfüllung + unabhängiges Glow; {rooms} Räume → geerbte Datenfüllung + unabhängiges Glow.","gs.optimize_references":"Referenzen repariert: Bereiche — {spaces}; Räume — {rooms}; Positionen — {positions}; Geräte aus fehlenden Bereichen gelöst — {detached}.","gs.optimize_reference_more":", und {n} mehr","gs.optimize_orphans_removed":"Vergessene Einträge entfernt: {total} — Raumbezeichnungen: {rooms}; Geräte: {devices}; Gruppenmarkierungen: {groups}. Sie gehörten zu zuvor gelöschten Bereichen.","gs.optimize_live_positions":"Alte Positionen in gelöschten Bereichen gehören zu vorhandenen Objekten: {n}{names}. Sie werden beibehalten.","gs.optimize_live_positions_remove":"Alte Positionen in gelöschten Bereichen gehören zu vorhandenen Objekten: {n}{names}. Sie sind zur Entfernung ausgewählt.","gs.optimize_live_names":": {names}{more}","gs.optimize_live_remove":"Alte Positionen entfernen","gs.optimize_live_keep":"Alte Positionen beibehalten","gs.optimize_live_selected":"Alte Positionen werden nach der Anwendung von Optimieren entfernt.","gs.optimize_unverified":"Positionen konnten nicht sicher überprüft werden: {n}. Sie wurden unverändert belassen.","gs.optimize_registry_limited":"Voller Administratorzugriff auf die Home Assistant-Registries ist für eine sichere Überprüfung erforderlich.","gs.optimize_vacuum_warning":"Raumzuordnungen, die noch überprüft werden müssen: {n}.","gs.optimize_details":"Details","gs.optimize_details_more":"Und {n} weitere Einträge.","gs.optimize_detail_removed":"wird entfernt","gs.optimize_detail_live":"wird beibehalten","gs.optimize_detail_unverified":"nicht überprüft","gs.optimize_detail_room_label":"Raumkennzeichnung","gs.optimize_detail_device":"Gerät","gs.optimize_detail_group":"Gruppenkennzeichen","gs.optimize_detail_unknown":"unbekannter Eigentümer","gs.optimize_detail_item":"{status}: {kind} {id}; alter Bereich {space}","gs.align_warn":"Absichtlich zwischen Rasterknoten platzierte Elemente werden sich bewegen. Nach der Operation ist nur eine Rückgängig-Funktion verfügbar, und zwar nur bis zur nächsten Planbearbeitung.","gs.align_run":"Optimieren","gs.align_done":"Pläne optimiert: {n} Elemente bewegt, {m} Datensätze beibehalten, {r} Verweise repariert","gs.optimize_undo":"Letzte Optimierung rückgängig machen","gs.optimize_undone":"Die letzte Optimierung wurde rückgängig gemacht","decor.furniture":"Möbel","decor.image":"Bild","decor.image_title":"Eigene Bilder","decor.image_upload":"Bild hochladen","decor.image_replace":"Bild ersetzen","decor.image_uploading":"Wird hochgeladen…","decor.image_asset":"Bilddatei","decor.image_pick_hint":"Ein Bild hochladen oder ein vorhandenes auswählen.","decor.image_place_hint":"Auf den Plan klicken, um das Bild zu platzieren.","decor.image_none":"Noch keine Bilder hochgeladen.","decor.image_unavailable":"Bild nicht verfügbar","decor.image_used":"In {n} Objekten verwendet","decor.image_upload_failed":"Bild konnte nicht hochgeladen werden: {err}","decor.image_error_capacity":"Der Speicher für benutzerdefinierte Bilder ist voll.","decor.image_in_use":"Vor dem Löschen alle platzierten Kopien entfernen.","decor.image_delete_title":"Bilddatei löschen?","decor.image_delete_message":"„{name}“ aus House Plan löschen? Dies kann nicht rückgängig gemacht werden.","furn.title":"Möbelbibliothek","furn.symbol":"Symbol","furn.group_furniture":"Möbel","furn.group_appliance":"Geräte","furn.group_sanitary":"Sanitär","furn.group_other":"Sonstiges","furn.width":"Breite","furn.depth":"Tiefe","furn.back_to_categories":"Alle Kategorien","furn.pick_hint":"Wählen Sie eine Kategorie und dann ein Symbol.","furn.place_hint":"Klicken Sie auf den Plan — das Element wird an der nächsten Wand platziert. Mit Shift wird es frei platziert.","furn.cat_air_conditioner":"Klimaanlagen","furn.cat_armchair":"Sessel","furn.cat_bathtub":"Badewannen","furn.cat_bed":"Betten","furn.cat_bidet":"Bidets","furn.cat_boiler":"Warmwasserbereiter","furn.cat_chair":"Stühle","furn.cat_coffee_table":"Couchtische","furn.cat_cooktop":"Kochfelder","furn.cat_dining_table":"Esstische","furn.cat_dishwasher":"Geschirrspüler","furn.cat_dryer":"Wäschetrockner","furn.cat_fireplace":"Kamine","furn.cat_fridge":"Kühlschränke","furn.cat_kitchen_cabinet":"Küchenschränke","furn.cat_kitchen_sink":"Küchenspülen","furn.cat_nightstand":"Schränke","furn.cat_plant":"Pflanzen","furn.cat_rug":"Teppiche","furn.cat_shelving":"Regale","furn.cat_shower":"Duschen","furn.cat_sink":"Waschbecken","furn.cat_sofa":"Sofas","furn.cat_stairs":"Treppen","furn.cat_toilet":"Toiletten","furn.cat_tv":"Fernseher","furn.cat_wardrobe":"Kleiderschränke","furn.cat_washer":"Waschmaschinen","furn.cat_work_table":"Schreibtische","furn.sym_sofa":"Zweisitzer-Sofa","furn.sym_sofa_three_seat":"Dreisitzer-Sofa","furn.sym_sofa_corner_right":"Ecksofa rechts","furn.sym_armchair":"Polstersessel","furn.sym_armchair_office":"Bürostuhl","furn.sym_coffee_table":"Rechteckiger Couchtisch","furn.sym_coffee_table_round":"Runder Couchtisch","furn.sym_coffee_table_oval":"Ovaler Couchtisch","furn.sym_coffee_table_rounded":"Abgerundeter Couchtisch","furn.sym_table_dining":"Rechteckiger Esstisch","furn.sym_table_round":"Rundtisch","furn.sym_table_dining_oval":"Ovaler Esstisch","furn.sym_table_dining_rounded":"Abgerundeter Esstisch","furn.sym_chair":"Stuhl","furn.sym_chair_bar":"Barhocker","furn.sym_desk":"Rechteckiger Schreibtisch","furn.sym_desk_corner":"Eckschreibtisch","furn.sym_bed_double":"Doppelbett","furn.sym_bed_single":"Einzelbett","furn.sym_nightstand":"Nachttisch","furn.sym_cabinet_tv":"TV-Schrank","furn.sym_cabinet_shoe":"Schuhschrank","furn.sym_cabinet_sink":"Waschtischunterschrank","furn.sym_wardrobe":"Kleiderschrank","furn.sym_bookshelf":"Bücherschrank","furn.sym_wall_unit":"Schrankwand","furn.sym_kitchen_floor":"Küchen-Unterschrank","furn.sym_kitchen_floor_corner":"Küchen-Eckunterschrank","furn.sym_kitchen_wall":"Küchen-Hängeschrank","furn.sym_kitchen_wall_corner":"Küchen-Eckhängeschrank","furn.sym_shelf_floor":"Standregal","furn.sym_shelf_wall":"Wandregal","furn.sym_fridge":"Kühlschrank","furn.sym_stove":"Vierflammiges Kochfeld","furn.sym_cooktop_two":"Zweiflammiges Kochfeld","furn.sym_dishwasher":"Geschirrspüler","furn.sym_washer":"Waschmaschine","furn.sym_dryer":"Wäschetrockner","furn.sym_tv":"Fernseher mit Standfuß","furn.sym_tv_wall":"Wandfernseher","furn.sym_ac":"Klimaanlage","furn.sym_water_heater":"Wassererhitzer","furn.sym_toilet":"Stand-WC","furn.sym_toilet_built_in":"Wand-WC","furn.sym_bathtub":"Rechteckige Badewanne","furn.sym_bathtub_corner":"Eckbadewanne","furn.sym_shower":"Dusche","furn.sym_sink":"Waschbecken","furn.sym_kitchen_sink":"Einzel-Küchenspüle","furn.sym_kitchen_sink_double":"Doppel-Küchenspüle","furn.sym_bidet":"Stand-Bidet","furn.sym_bidet_built_in":"Wand-Bidet","furn.sym_stairs":"Treppe","furn.sym_fireplace":"Kamin","furn.sym_plant":"Pflanze","furn.sym_rug":"Teppich","common.yes":"Ja","common.no":"Nein","vac.diag_source":"Quelle","vac.diag_platform":"Integration","vac.diag_status":"Status","vac.diag_position":"Position","vac.diag_rooms":"Räume","vac.diag_rooms_value":"{total} · {matched} Namen stimmen überein · {readiness}","vac.autocal_ready":"Auto-Kalibrierung verfügbar","vac.autocal_not_ready":"3 übereinstimmende Namen erforderlich","vac.diag_path":"Integrationspfad","vac.diag_map":"Karten-ID","vac.source_none":"nicht ausgewählt","vac.source_status_ok":"Bereit","vac.source_status_missing":"Fehlend","vac.source_status_disabled":"In Home Assistant deaktiviert","vac.source_status_unavailable":"Nicht verfügbar","vac.source_status_unverified":"Kann mit den aktuellen Berechtigungen nicht verifizieren","vac.source_status_unsupported":"Keine Positionsdaten","vac.source_status_none":"Keine Quelle","vac.source_banner_missing":"Die gespeicherte Quelle existiert nicht mehr. Sie wurde nicht automatisch ersetzt; wählen Sie eine andere Quelle oder stellen Sie sie in Home Assistant wieder her.","vac.source_banner_disabled":"Die gespeicherte Quelle ist in Home Assistant deaktiviert. Aktivieren Sie sie dort oder wählen Sie eine andere Quelle.","vac.source_banner_unverified":"Die aktuellen Home Assistant-Berechtigungen können diese gespeicherte Quelle nicht verifizieren. Sie bleibt angepinnt und wird nicht automatisch ersetzt.","vac.choose_source":"Quelle wählen","vac.source_auto":"Automatisch","vac.source_auto_hint":"Verwenden Sie eine kompatible Entität von diesem Gerät","vac.all_cameras":"Alle Kameras","vac.all_cameras_warn":"Eine Kamera liefert möglicherweise keine Roboter-Daten. Wählen Sie eine nur, wenn es Ihre Saugroboter-Karte ist.","vac.all_cameras_empty":"Keine anderen Kamera-Entitäten gefunden.","vac.platform_unknown":"unbekannte Integration","vac.cap_position":"Position","vac.cap_rooms_short":"Räume","vac.cap_path":"Pfad","vac.cap_map":"Karten-ID","vac.cap_none":"Keine Roboter-Daten erkannt","vac.xcme_hint":"Aktivieren Sie diese Xiaomi Cloud Map Extractor-Attribute:","vac.documentation":"Dokumentation","vac.residual_title":"Automatische Kalibrierung überprüfen","vac.residual_message":"Die zugeordneten Räume weichen um bis zu {error} voneinander ab. Diese ungefähre Kalibrierung anwenden, manuell verfeinern oder ohne Änderung der gespeicherten Einrichtung abbrechen.","vac.apply_proposal":"Anwenden","gs.backup_group":"Sichern und übertragen","gs.backup_hint":"Laden Sie ein tragbares JSON-Backup herunter oder sehen Sie eine Vorschau und importieren Sie ein Backup, das mit House Plan erstellt wurde.","backup.export_open":"Exportieren","backup.import_open":"Importieren","backup.export_title":"House Plan exportieren","backup.import_title":"House Plan importieren","backup.export_hint":"Wählen Sie, ob das Backup die gesamte House Plan-Konfiguration oder nur den aktuellen Bereich enthalten soll.","backup.full":"Vollständiges Backup","backup.current_space":"Aktueller Bereich","backup.current_space_title":"Aktueller Bereich: {title}","backup.no_current_space":"Kein aktueller Bereich","backup.plan_only":"Nur Plan","backup.plan_only_hint":"Räume, Wände, Öffnungen, Dekor und Raumbezeichnungspositionen ohne Geräte oder Home Assistant-Bindungen beibehalten.","backup.plan_only_preview":"Diese Datei enthält nur den Plan.","backup.privacy_warning":"Das Archiv enthält Namen, Home Assistant-Kennungen und genaue Koordinaten. Interne Pläne und Anhänge werden referenziert, nicht eingebettet; Laufzeitzustände und Staubsaugerspuren sind nicht enthalten.","backup.download":"JSON herunterladen","backup.export_done":"Backup heruntergeladen","backup.reading":"Überprüfe das Backup…","backup.revalidated":"Der Plan wurde nach dieser Vorschau geändert. Die Zusammenfassung wurde aktualisiert; überprüfen Sie sie und bestätigen Sie erneut.","backup.error.support_invalid_message":"Prüfen Sie die Supportnachricht und versuchen Sie es erneut.","backup.error.support_package_too_large":"Das anonymisierte Supportpaket überschreitet das Limit von 8 MiB.","backup.error.support_preview_expired":"Die Vorschau des Supportanhangs ist abgelaufen oder nicht mehr verfügbar.","backup.error.support_rate_limited":"Zu viele Supportberichte oder Vorschauen wurden angefordert. Versuchen Sie es später erneut.","backup.error.support_rejected":"Der Bericht hat die Prüfung des Supportdienstes nicht bestanden.","backup.error.support_unavailable":"Der private Supportdienst ist vorübergehend nicht verfügbar.","backup.error.unauthorized":"Sie haben keine Berechtigung, diesen Plan zu exportieren oder zu importieren.","backup.error.not_ready":"Der Hausplan ist noch nicht fertig. Versuchen Sie es in einem Moment erneut.","backup.error.too_large":"Das Backup überschreitet das 8-MiB-Limit.","backup.error.invalid_json":"Die ausgewählte Datei ist kein gültiges JSON.","backup.error.invalid_format":"Die ausgewählte Datei ist kein House Plan-Backup.","backup.error.invalid_image":"Das Bild ist beschädigt oder entspricht nicht seinem Format.","backup.error.unsupported_export_version":"Dieses Backup-Format wird von der installierten Version nicht unterstützt.","backup.error.unsupported_image":"Verwenden Sie ein unterstütztes PNG-, JPEG-, WebP- oder SVG-Bild.","backup.error.future_model":"Das Backup wurde mit einem neueren House-Plan-Datenmodell erstellt.","backup.error.invalid_config":"Das Backup enthält eine ungültige House-Plan-Konfiguration.","backup.error.wall_model_migration_blocked":"Das Backup-Wandmodell konnte nicht sicher aktualisiert werden. Optimieren Sie zuerst den Quellplan und exportieren Sie ihn dann erneut.","backup.error.invalid_layout":"Das Backup enthält ungültige Objektpositionen.","backup.error.invalid_content":"Das Backup enthält ungültige oder inkonsistente Inhaltsreferenzen.","backup.error.space_not_found":"Der ausgewählte Bereich existiert nicht mehr.","backup.error.capacity_exceeded":"Durch das Hinzufügen dieses Backups würden die Planlimits überschritten.","backup.error.preview_expired":"Die Vorschau ist abgelaufen. Wählen Sie die Backup-Datei erneut aus.","backup.error.preview_owner_mismatch":"Diese Vorschau gehört zu einem anderen Home-Assistant-Benutzer.","backup.error.conflict":"Der Plan hat sich nach der Vorschau geändert. Überprüfen Sie die aktualisierte Zusammenfassung.","backup.error.content_confirmation_required":"Bestätigen Sie, dass nicht verfügbare lokale Inhalte getrennt werden können.","backup.error.commit_failed":"Das Backup konnte nicht sicher angewendet werden. Der vorherige Plan wurde wiederhergestellt oder wartet auf die Wiederherstellung.","backup.error.missing_plan":"Eine referenzierte Plan-Datei ist nach der Vorschau verschwunden. Überprüfen Sie das Backup erneut.","backup.error.missing_content":"Ein referenziertes lokales Anhangselement ist nach der Vorschau verschwunden. Überprüfen Sie das Backup erneut.","backup.error.marker_control_missing":"Ein verknüpftes Planlicht fehlt im Backup.","backup.error.marker_control_not_light":"Ein verknüpftes Planziel ist nicht mehr als Lichtquelle markiert.","backup.error.marker_control_self":"Eine Lichtquelle kann sich nicht selbst steuern.","backup.error.marker_control_cycle":"Das Backup enthält eine kreisförmige Kette von Lichtsteuerungen.","backup.error.duplicate_marker_control":"Das Backup enthält eine doppelte Plan-Licht-Verknüpfung.","backup.error.no_backup":"Es gibt keinen Import- oder Optimierungssnapshot zur Wiederherstellung.","backup.error.in_use":"Das Element wird noch verwendet","backup.error.invalid_data":"Die Anfrage enthält ungültige Daten","backup.error.invalid_light_entity":"Das führende Licht muss eine light.*- oder switch.*-Entität sein","backup.error.invalid_marker_control":"Ungültige Marker-Steuerungsreferenz","backup.error.invalid_name":"Der Name ist ungültig","backup.error.invalid_partition_opening_host":"Die Öffnung muss ihren Trennwand-Träger behalten","backup.error.invalid_partition_opening_jamb_margin":"Die Öffnung lässt keinen physischen Pfosten am Wandende","backup.error.invalid_passage_fields":"Ein offener Durchgang kann keine Tür-Einstellungen tragen","backup.error.invalid_space_id":"Unbekannter Raumbereich","backup.error.invalid_toggle_entity":"Die Schalt-Entität muss light.* oder switch.* sein","backup.error.invalid_value_badge":"Ungültige Wert-Badge-Einstellungen","backup.error.invalid_value_badge_attribute":"Ungültiges Wert-Badge-Attribut","backup.error.invalid_value_badge_position":"Ungültige Wert-Badge-Position","backup.error.invalid_value_badge_source":"Ungültige Wert-Badge-Quelle","backup.error.invalid_value_source":"Ungültige Wertquelle","backup.error.invalid_value_source_attribute":"Ungültiges Wertquellen-Attribut","backup.error.io_error":"Eine Dateioperation auf dem Server ist fehlgeschlagen","backup.error.not_toggleable":"Dieses Gerät kann nicht geschaltet werden","backup.error.nothing_to_repair":"Nichts zu reparieren","backup.error.space_in_use":"Der Raumbereich wird noch referenziert","backup.error.value_badge_source_required":"Das Wert-Badge braucht eine Quelle","backup.error.wall_model_client_outdated":"Der Plan wurde anderswo aktualisiert — Seite neu laden","backup.same_source":"Erstellt auf dieser Home Assistant-Instanz","backup.foreign_source":"Erstellt auf einer anderen Home Assistant-Instanz","backup.created":"Erstellt: {value}","backup.versions":"Karte {card}; Integration {integration}; Datenmodell {model}","backup.count_spaces":"Bereiche: {n}","backup.count_rooms":"Räume: {n}","backup.count_walls":"Wände: {n}","backup.count_openings":"Öffnungen: {n}","backup.count_decor":"Dekorationsobjekte: {n}","backup.count_markers":"Geräte: {n}","backup.count_layout":"Positionen: {n}","backup.bindings":"Verknüpfungen — Geräte: {device}, Entitäten: {entity}, virtuell: {virtual}; Positionen ohne Bereich: {legacy}","backup.binding_status":"Zielstatus — aktiv: {active}, deaktiviert: {disabled}, fehlt: {missing}","backup.missing_areas":"Auf dem Ziel fehlende Bereiche: {areas}","backup.dropped_marker_links":"Planlicht-Verknüpfungen außerhalb dieses übertragenen Bereichs wurden ausgelassen: {n}.","backup.repaired_target_refs":"Durch den Import dieses Bereichs wiederhergestellte vorhandene Referenzen: {n}.","backup.preserved_unresolved_refs":"Referenzen, die nicht eindeutig wiederhergestellt werden konnten, wurden beibehalten: {n}.","backup.preserved_unresolved_hint":"Es wurden keine Daten geraten oder gelöscht. Führen Sie nach dem Import Optimierungspläne aus, um die verbleibenden Referenzen zu überprüfen.","backup.import_details":"Importieren von Referenzdetails","backup.import_detail.incoming_remapped":"Referenzen innerhalb der importierten Kopie aktualisiert: {n}","backup.import_detail.target_repaired":"Vorhandene Referenzen wiederhergestellt: {n}","backup.import_detail.preserved_unresolved":"Unaufgelöste Referenzen beibehalten: {n}","backup.import_detail.collisions":"Zielkonflikte sicher beibehalten: {n}","backup.import_detail.dropped_links":"Eingehende Links durch Übertragungsregeln ausgelassen: {n}","backup.import_detail.bounded_lineages":"Übermäßig verschachtelte Kennungen begrenzt belassen: {n}","backup.replace_warning":"Dies ersetzt die aktuelle Konfiguration und das Layout. Hochgeladene Dateien werden niemals gelöscht. Eine Rückgängig-Möglichkeit bleibt bis zur nächsten Planbearbeitung verfügbar.","backup.foreign_bookkeeping":"Instanzspezifische bekannte/neue Gerätebuchführung wird nicht importiert.","backup.final_name":"Name des neuen Bereichs","backup.target_settings":"Die globalen Einstellungen der Zielinstanz bleiben unverändert.","backup.duplicates":"Bindungen bereits vorhanden: {n}","backup.skip":"Doppelte Geräte überspringen","backup.virtual_copy":"Sichere statische virtuelle Kopien hinzufügen","backup.content":"Referenzierter Inhalt","backup.decor_images_summary":"Eigene Bilder: {objects} Objekte, {assets} Dateien; fehlende Dateien: {missing}.","backup.content_available":"lokal verfügbar","backup.content_external":"externer Link","backup.content_detach_required":"wird getrennt","backup.confirm_detach":"Ich verstehe, dass nicht verfügbare interne Pläne und Anhänge von der importierten Konfiguration getrennt werden.","backup.confirm_missing_images":"Ich verstehe, dass fehlende eigene Bilder als reparierbare Platzhalter erhalten bleiben und andere nicht verfügbare lokale Dateien getrennt werden.","backup.replace":"Ersetzen","backup.add":"Bereich hinzufügen","backup.space_done":"Bereich importiert: {rooms} Räume, {markers} Geräte, {refs} bestehende Referenzen wiederhergestellt","backup.full_done":"Backup wiederhergestellt: {spaces} Bereiche, {rooms} Räume, {markers} Geräte","backup.undo_import":"Letzten vollständigen Import rückgängig machen","backup.import_undone":"Vollständiger Import rückgängig gemacht","backdrop.large_title":"Großes Bild","backdrop.large_body":"Dieses Bild ist {w}×{h} ({fileMb} MB Datei) und benötigt etwa {decodedMb} MB Speicher zur Anzeige. Auf Tablets kann das die Seite zum Absturz bringen.","backdrop.unknown_body":"Die Bildabmessungen konnten nicht gelesen werden — die Datei ist möglicherweise beschädigt. Fortfahren kann die Seite auf Tablets zum Absturz bringen.","backdrop.reduced_dimensions":"Verkleinerte Kopie: {w}×{h} px.","backdrop.use_downscaled":"Verkleinerte Kopie hochladen","backdrop.reducing":"Wird verkleinert…","backdrop.keep_original":"Original behalten","backdrop.too_large_title":"Bild ist zu groß","backdrop.too_large_body":"Dieses Bild überschreitet die Anzeigegrenzen des Browsers ({w}×{h}, Limit {limit} px pro Seite). Bitte verkleinern Sie es in einem Desktop-Editor und laden Sie es erneut hoch.","backdrop.downscale_failed":"Die verkleinerte Kopie konnte nicht erstellt werden. Der aktuelle Plan wurde nicht geändert."};const n="bd7029808eb6094140d9fa8245f50816cb452430a353f4231d16e02c97078a06";export{e as dictionary,n as fingerprint};
diff --git a/dist/houseplan-assets/de-DZwnjt2u.js b/dist/houseplan-assets/de-DZwnjt2u.js
new file mode 100644
index 00000000..2d83e92d
--- /dev/null
+++ b/dist/houseplan-assets/de-DZwnjt2u.js
@@ -0,0 +1 @@
+globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="781b6de4892612660b01762cd408049137fa0d00417a43ef5bbdfb1ef37dc9a5";var e={"editor.context_actions":"Aktionen: {object}","editor.tool_options":"Werkzeugoptionen: {tool}","editor.palette":"Palette: {tool}","editor.open_group":"Werkzeuggruppe: {group}","editor.group_active":"{group} — aktiv: {item}","editor.disabled_action":"{action} ist nicht verfügbar: {reason}","editor.loading":"Editor wird geladen…","editor.loading_aria":"Der Plan-Editor wird geladen","editor.load_failed":"Der Editor konnte nicht geladen werden.","editor.refresh_advice":"Seite aktualisieren und erneut versuchen.","editor.retry_advice":"Verbindung prüfen und erneut drücken.","color_picker.title":"Farbwähler","color_picker.hue":"Farbton","color_picker.saturation":"Sättigung","color_picker.value":"Helligkeit","color_picker.hex":"Hex-Farbe","color_picker.invalid_hex":"Geben Sie eine 3- oder 6-stellige Hex-Farbe ein","btn.properties":"Eigenschaften","btn.keep_as_walls":"Als Wände behalten","btn.delete_room_keep_walls":"Raum löschen, Wände behalten","btn.delete_room_with_walls":"Raum und Wände löschen","title.markup_select":"Wände, Säulen und gespeicherte Umrisse auswählen und bearbeiten","title.markup_column":"Säule: Klicken Sie auf einen Rasterpunkt, um eine quadratische Säule zu platzieren","markup.partition":"Trennwand","markup.column":"Säule","markup.hint_column":"Klicken Sie auf einen Rasterpunkt, um eine quadratische Säule zu platzieren","history.draft_segment":"Raum-Entwurfsegment hinzufügen","history.draft_merge":"Unvollständige Raumumrisse verbinden","history.draft_segment_delete":"Raum-Entwurfssegment entfernen","history.column_add":"Säule hinzufügen","history.physical_edit":"Physisches Objekt ändern","history.physical_delete":"Physisches Objekt löschen","history.physical_move":"Physisches Objekt verschieben","history.contour_to_partitions":"Umriss in geschlossene Wände umwandeln","history.wall_chain_finish":"Wandkette fertigstellen","history.wall_face_batch":"Räume aus Wänden erstellen","toast.column_duplicate":"Eine Säule mit demselben Zentrum und äußerer Größe existiert bereits","confirm.delete_draft_title":"Unvollständigen Umriss löschen?","confirm.delete_draft_body":"Der gesamte unvollständige Raumumriss wird gelöscht. Beim Abbrechen wird nichts geändert.","confirm.delete_draft_segment_title":"Umrisssegment löschen?","confirm.delete_draft_segment_body":"Dieses Entwurfssegment wird gelöscht. Der verbleibende Umriss kann sich in zwei Teile aufteilen.","physical.partition_properties":"Eigenschaften der Trennwand","physical.column_properties":"Eigenschaften der Säule","physical.draft_properties":"Eigenschaften des Entwurfssegments","physical.shape":"Form","physical.square":"Quadrat","physical.circle":"Kreis","physical.diameter":"Durchmesser","physical.side":"Seite","physical.rotation":"Drehwinkel","physical.length":"Länge","physical.allowed_range":"Erlaubt: {min}–{max} {unit}","physical.delete_segment":"Segment löschen","physical.delete_draft":"Gesamten Umriss löschen","physical.column_size_title":"Außenmaß der per Klick platzierten quadratischen Säule (1–150 cm).","card.title":"Hausplan","count.devices":"{n} Entwicklung","empty.no_spaces":"Noch keine Bereiche.","empty.add_first":"Ersten Bereich hinzufügen und einen Grundriss hochladen.","empty.install":"Installieren Sie die House Plan-Integration und fügen Sie sie unter „Geräte & Dienste“ hinzu.","btn.add_space":"Bereich hinzufügen","btn.cancel":"Abbrechen","btn.save":"Speichern","btn.close":"Schließen","btn.delete":"Löschen","btn.edit":"Bearbeiten","btn.open_in_ha":"In HA öffnen","btn.reset":"Zurücksetzen","btn.attach":"Anhängen…","btn.upload":"Hochladen…","btn.replace":"Ersetzen…","title.zoom_in":"Zoomen","title.zoom_out":"Herauszoomen","title.zoom_fit":"Alles anpassen","title.configure_space":"Bereich konfigurieren","title.add_space":"Bereich hinzufügen","title.markup_add":"Wände: eine durchgehende Kette zeichnen; Shift sperrt auf 45°. Werkzeugwechsel oder Verlassen des Editors beendet die Kette und wandelt sie in unabhängige Wände","title.markup_merge":"Zusammenführen: Klicken Sie auf einen Raum und dann auf den Nachbarraum, mit dem er eine Wand teilt","title.markup_split":"Raum teilen: Klicken Sie auf den Raum und dann auf zwei Punkte an seinen Wänden","title.markup_delroom":"Raum löschen: Klicken Sie in einen Raum und bestätigen Sie","title.need_plan":"Einen Grundriss hochladen","markup.add":"Wände","markup.merge":"Zusammenführen","markup.split":"Teilen","markup.resize":"Größe ändern","title.markup_resize":"Räume vergrößern/verkleinern: Ziehen Sie einen verfügbaren horizontalen oder vertikalen Wandgriff","markup.hint_resize":"Ziehen Sie einen verfügbaren Wandgriff · die Wand stoppt an der ersten unsicheren Position · Esc bricht ab · Strg+Z — rückgängig","resize.disabled.diagonal":"Diese Wand ist geneigt; Größe ändern unterstützt nur horizontale und vertikale Wände","resize.disabled.side-angle":"Eine angrenzende Wand ist geneigt; Größe ändern erfordert, dass beide angrenzenden Wände diese Wand im rechten Winkel treffen","resize.disabled.duplicate-physical-wall":"Eine separate Trennwand, unfertige Kontur oder ein Pfeiler überlappt diese Wand; entfernen oder verschieben Sie sie, bevor Sie die Größe ändern","resize.disabled.partial-shared":"Ein angrenzender Raum nutzt nur einen Teil dieser Wand, daher kann sie nicht sicher als gemeinsame Wand verschoben werden","resize.disabled.unequal-shared":"Der angrenzende Raum nutzt andere Endpunkte oder Wandlängen, daher können die Wände nicht gemeinsam sicher bewegt werden","resize.disabled.multiple-rooms":"Das Verschieben dieser Wand würde mehr als zwei Räume betreffen","resize.disabled.thickness-conflict":"Die Wandstärke kann nicht sicher beibehalten werden","resize.disabled.opening-conflict":"Eine Öffnung an dieser Wand kann nicht sicher verschoben werden","resize.disabled.invalid-geometry":"Diese Wand kann nicht ohne Änderung der Planstruktur geändert werden","resize.limit_stopped":"Wand gestoppt: der nächste Schritt würde ein Anschlusslimit verletzen","resize.commit_failed":"Größenänderung wurde abgebrochen, da der endgültige Plan die Geometrieprüfung nicht bestanden hat","resize.preview_failed":"Größenänderung am letzten sicheren Punkt gestoppt, da die Plan-Geometrie nicht beibehalten werden konnte","markup.opening":"Öffnung","markup.delete_room":"Raum löschen","history.undo":"Rückgängig","history.redo":"Wiederholen","history.undo_named":"Rückgängig: {name} (Strg+Z)","history.redo_named":"Wiederholen: {name} (Strg+Shift+Z / Strg+Y)","history.undo_empty":"Nichts zu widerrufen","history.redo_empty":"Nichts zu wiederholen","history.undone":"Rückgängig gemacht: {name}","history.redone":"Wiederholt: {name}","history.add_room":"Raum erstellen","history.split_room":"Raum teilen","history.merge_rooms":"Räume zusammenführen","history.resize_room":"Raumgröße ändern","history.wall_thickness":"Wandstärke ändern","history.add_opening":"Tür- oder Fensteröffnung hinzufügen","history.edit_opening":"Öffnung bearbeiten","history.move_opening":"Öffnung verschieben","history.delete_opening":"Öffnung löschen","history.delete_room_keep_walls":"Raum löschen, Wände behalten","history.delete_room_with_walls":"Raum und Wände löschen","history.decor_add":"Dekorobjekt hinzufügen","history.decor_edit":"Dekorobjekt bearbeiten","history.decor_move":"Dekorobjekt verschieben","history.decor_transform":"Dekorobjekt transformieren","history.decor_delete":"Dekorobjekt löschen","history.backdrop_transform":"Plan-Hintergrund transformieren","history.device_move":"{name} verschieben","history.device_stale":"Der Positionsverlauf ist nicht mehr anwendbar und wurde gelöscht","opening.new":"Neue Öffnung","opening.edit":"Öffnung","opening.door":"Tür","opening.window":"Fenster","opening.gate":"Tor","opening.passage":"Offener Durchgang","opening.passage_binding_warning":"Das Speichern entfernt den Öffnungs-/Schließsensor und das Schloss.","opening.invalid_passage_fields":"Der offene Durchgang auf dem Plan „{room}“ hat nicht unterstützte Einstellungen: {fields}.","opening.type_label":"Typ","opening.length_label":"Länge, cm","opening.contact_label":"Öffnungs-/Schließsensor","opening.lock_label":"Schloss","opening.none":"— keine —","opening.search_ph":"Suche: Name oder Entitäts-ID…","opening.invert":"Geöffnet/geschlossen invertieren","opening.flip_h":"Scharnier an der anderen Zarge","opening.flip_v":"Öffnet zur anderen Seite","opening.open":"Offen","opening.closed":"Geschlossen","opening.locked":"Verriegelt","opening.unlocked":"Entriegelt","opening.state_unknown":"nicht verfügbar","opening.no_entities":"Keine Sensoren gebunden — ein statisches Symbol auf dem Plan.","toast.opening_no_wall":"Neben eine Raumwand oder eine unabhängige Wand klicken","opening.host_partition":"Unabhängige Wand","opening.partition_orphan":"Die unabhängige Wand für diese Öffnung existiert nicht mehr","opening.partition_jamb_margin":"Mindestens {distance} zwischen der Öffnung und dem Wandende lassen","opening.rebind_partition":"An eine andere unabhängige Wand anfügen","confirm.delete_partition_openings_title":"Wand und Öffnungen löschen?","confirm.delete_partition_openings_body":"Diese Wand enthält {count} Öffnung(en). Sie werden zusammen gelöscht.","confirm.delete_partition_openings_item":"• {type}, {length}","markup.hint_points":"Punkte: {n} · Shift — 45° Schritte · Esc — Kette beenden · Ctrl+Z — Punkt rückgängig machen · Schließen eines Bereichs erstellt einen Raum","markup.hint_start":"Klicken Sie auf einen Rasterpunkt, um eine Wandkette zu starten","tip.lqi":"durchschnittliches Zigbee-Signal:","tip.area":"Bereich: {value}","info.device_header":"Gerät im Plan","info.model":"Modell","info.state":"Status","info.link":"Verbindung","info.manuals":"Handbücher","info.none":"Keine zusätzlichen Informationen","marker.new_device":"Neues Gerät","marker.name_label":"Name (im Plan angezeigt)","marker.name_ph":"Name","marker.binding_label":"An ein HA-Gerät binden","marker.binding_disabled":"in Home Assistant deaktiviert","marker.virtual_option":"Virtuelles Gerät (keine Bindung)","marker.search_ph":"Gerät/Gruppe suchen…","marker.nothing_found":"Nichts gefunden","marker.room_label":"Raum","marker.room_override":" (Platzierung überschreiben)","marker.room_choose":"— Raum auswählen —","marker.room_auto":"— nach Gerätebereich (auto) —","marker.icon_label":"Symbol","marker.icon_ph":"mdi:… (leer = automatisch)","marker.display_label":"Anzeige","display.badge":"Symbol + Zustand","display.icon_ripple":"Symbol + Zustand und Aktivität","display.static_icon":"Immer statisches Symbol","marker.display_hint_badge":"Das Symbol und die dynamische Platte zeigen den Gerätezustand ohne den üblichen Aktivitätspuls. Rote Alarme bleiben sichtbar.","marker.display_hint_icon_ripple":"Das Symbol, die dynamische Platte und der Puls zeigen einen kurzen Puls für Ereignisse und einen kontinuierlichen Puls für Arbeit, Bewegung oder Anwesenheit. Rote Alarme haben eine separate Priorität.","marker.display_hint_value":"Ein ausgewählter oder automatisch ermittelter Home Assistant-Wert ersetzt das Symbol, während die Platte weiterhin den Zustand anzeigt. Rote Alarme bleiben sichtbar.","marker.display_hint_static_icon":"Die themenabhängige Hülle und das Symbol bleiben immer gleich. Zustand, Aktivität, Nichtverfügbarkeit und Alarme verändern nicht das Erscheinungsbild.","marker.static_alarm_warning":"Dieses Gerät kann Alarme melden. Die statische Anzeige verbirgt die visuelle Alarmanzeige des Markers.","marker.preview.title":"Anzeigevorschau","marker.preview.actual":"Jetzt","marker.preview.example":"Beispiel","marker.preview.integration":"Bereitgestellt von","marker.preview.source":"Anzeigquelle","marker.preview.current_state":"Aktueller Zustand","marker.preview.result":"Auf dem Plan","marker.preview.details":"Quelldetails","marker.preview.select_source":"Ein Home-Assistant-Gerät oder eine Entität auswählen, um die tatsächliche Anzeige zu sehen.","marker.preview.unknown_provider":"Unbekannte Integration","marker.preview.virtual_provider":"House Plan · virtuelles Gerät","marker.preview.no_source":"Keine aktive Quelle","marker.preview.no_state":"Kein aktueller Zustand","marker.preview.mixed_states":"Mehrere verschiedene Zustände","marker.preview.multiple_sources":"{n}-Quellen","marker.preview.more_sources":"+{n} mehr","marker.preview.scaled":"Die Vorschau wird auf {n}% skaliert, um zu passen. Die gespeicherte Größe bleibt unverändert.","marker.preview.demo_short":"Kurze Aktivität anzeigen","marker.preview.demo_continuous":"Kontinuierliche Aktivität anzeigen","marker.preview.stop_continuous":"Kontinuierliche Aktivität stoppen","marker.preview.demo_short_notice":"Kurzes Aktivitätsbeispiel; der tatsächliche Gerätezustand bleibt unverändert.","marker.preview.demo_continuous_notice":"Kontinuierliches Aktivitätsbeispiel; der tatsächliche Gerätezustand bleibt unverändert.","marker.preview.demo_already_visible":"Der aktuelle Zustand zeigt bereits eine echte Aktivitäts- oder Alarmeffekt.","marker.preview.reduced_motion":"Systemweit reduzierte Bewegungen sind aktiviert, daher wird gewöhnliche Aktivität als Punkt angezeigt.","marker.preview.reason.neutral":"Neutrale dunkle Platte","marker.preview.reason.working":"Gelbe Platte: Das Gerät arbeitet jetzt","marker.preview.reason.working_activity":"Gelbe Platte und Aktivitätseffekt: das Gerät funktioniert jetzt","marker.preview.reason.open":"Orange Platte: physisch geöffnet oder entriegelt","marker.preview.reason.cover_icon_state":"Neutrale Platte; die Abdeckungseinheit steuert den angezeigten Zustand und das Symbol","marker.preview.reason.presence":"Aktivitätseffekt, während Präsenz erkannt wird","marker.preview.reason.event":"Kurzer Aktivitätseffekt nach einem erkannten Ereignis","marker.preview.reason.transition":"Aktivitätseffekt, während das Gerät sich bewegt oder den Zustand ändert","marker.preview.reason.media_neutral":"Mediengeräte bleiben im verfügbaren Zustand auf einer neutralen dunklen Platte","marker.preview.reason.unavailable":"Gedämpfte neutrale Platte: nicht verfügbar oder ausgeschaltet","marker.preview.reason.alarm":"Rote Alarmplatte; Alarmanzeige wird immer angezeigt","marker.preview.reason.live_states_disabled":"Live-Zustandsstil ist für diese Karte deaktiviert","marker.preview.reason.value_no_state":"Kein nutzbarer Zustandswert; stattdessen wird das Symbol angezeigt","marker.preview.reason.value_ambiguous_sources":"Mehrere mögliche Wertequellen; stattdessen wird das Symbol angezeigt","marker.preview.reason.value_non_scalar":"Die Quelle lieferte keinen einfachen Wert; stattdessen wird das Symbol angezeigt","marker.preview.reason.value_virtual":"Ein virtuelles Gerät hat keinen Home Assistant-Wert; stattdessen wird das Symbol angezeigt","marker.preview.reason.vacuum_live_plan_only":"Echtzeitposition und -spur des Staubsaugers sind nur im vollständigen Plan verfügbar","marker.preview.reason.hidden_design_preview":"Das Gerät ist im Plan ausgeblendet; diese Designvorschau bleibt sichtbar","marker.preview.reason.composite_power_source":"Der Status stammt vom Power-Entity des Geräts; Hilfsschalter werden ignoriert","marker.preview.reason.activity_display_disabled":"Der gewählte Anzeigemodus zeigt gewöhnliche Aktivitätseffekte nicht an","marker.preview.reason.ha_disabled":"Die Home Assistant-Verbindung ist deaktiviert und wird im Plan ausgeblendet","marker.preview.reason.orphaned":"Die gespeicherte Home Assistant-Verbindung konnte nicht mehr gefunden werden","marker.preview.reason.static_icon":"Statischer Modus: Der Gerätestatus ändert das Symbol nicht","marker.activity_color":"Aktivitätspulsfarbe","marker.ripple_size":"Aktivitätspulsgröße","marker.activity_alarm_note":"Farbe und Größe betreffen nur gewöhnliche Aktivität und ändern keine roten Alarme.","marker.pulse_a11y_alarm":"Alarm","marker.pulse_a11y_event":"Kürzliches Ereignis","marker.pulse_a11y_presence":"Anwesenheit erkannt","marker.pulse_a11y_transition":"Statusänderung","marker.pulse_a11y_running":"Arbeitet","marker.state_a11y_neutral":"Standardzustand","marker.state_a11y_working":"Funktionierend","marker.state_a11y_open":"Offen","marker.state_a11y_locked":"Verschlossen","marker.state_a11y_unlocked":"Entriegelt","marker.state_a11y_alarm":"Alarm","marker.state_a11y_unavailable":"Nicht verfügbar","marker.lqi_a11y_low":"LQI {value}, schwaches Signal","marker.lqi_a11y_mid":"LQI {value}, mittleres Signal","marker.lqi_a11y_high":"LQI {value}, starkes Signal","marker.size_label":"Symbolgröße / Drehung","marker.angle_label":"Drehen","marker.model_label":"Modell","marker.model_ph":"z.B. Aqara T&H","marker.link_label":"Link","marker.desc_label":"Beschreibung","marker.desc_ph":"Notizen, Spezifikationen…","marker.manuals_label":"Handbücher (PDF usw.)","marker.sub_device":"Gerät","marker.sub_z2m_group":"· Z2M Gruppe","marker.sub_group":"Gruppe","marker.sub_helper":"Helfer","space.new":"Neuer Bereich","space.header":"Bereich","space.title_label":"Titel","space.title_ph":"z.B. Garage","space.plan_label":"Grundriss (Hintergrund)","space.no_plan":"Kein Planbild","space.plan_alt":"Grundriss","room.new":"Neuer Raum","room.name_label":"Anzeigename","room.name_ph":"z.B. Terrasse","room.area_label":"Home Assistant Bereich (nicht zugewiesen)","room.no_area_option":"— kein Bereich —","room.default_name":"Raum","device.unnamed":"unbenannt","device.light_group":"Lichtgruppe","device.fallback":"Gerät","device.virtual":"Virtuelles Gerät","confirm.delete_room_title":'Raum "{name}" löschen?',"confirm.delete_room_body":"Festlegen, ob die ausschließlich zu diesem Raum gehörenden physischen Wände erhalten bleiben. Mit einem anderen Raum geteilte Wände bleiben immer erhalten.","confirm.remove_marker_title":"Gerät aus dem Plan löschen?","confirm.remove_marker_body":"Das Gerät verschwindet vollständig und trägt nicht mehr zu den Plandaten bei. Es kann später erneut hinzugefügt werden.","confirm.erase_decor":"Das Objekt „{kind}“ löschen? Diese Aktion kann im Editor rückgängig gemacht werden.","confirm.delete_space_title":"Bereich löschen?","confirm.delete_space_body":"Der Bereich, alle seine Räume und die gesamte Planmarkierung werden gelöscht.","confirm.delete_space_vac_routes":"Zuordnungen von Roboterkarten werden ebenfalls entfernt: {count}.","space.delete_blocked":"Dieser Bereich wird noch von {n} Gerät(en) verwendet. Die Geräte zuerst in einen anderen Bereich verschieben oder löschen.","toast.pos_save_failed":"Position nicht gespeichert: {err}","toast.no_entity":"Das Gerät hat keine geeignete Entität","toast.ha_disabled_action":"Ein deaktiviertes Home Assistant-Objekt kann im Plan nicht verwendet werden.","toast.ha_disabled_show_device":"Ein in Home Assistant deaktiviertes Gerät kann im Plan nicht angezeigt werden. Aktivieren Sie es zuerst in Home Assistant.","toast.ha_disabled_show_entity":"Eine in Home Assistant deaktivierte Entität kann im Plan nicht angezeigt werden. Aktivieren Sie sie zuerst in Home Assistant.","toast.ha_disabled_add":"Ein deaktiviertes Home Assistant-Objekt kann nicht dem Plan hinzugefügt werden. Aktivieren Sie es zuerst in Home Assistant.","toast.ha_binding_unverified":"Der Status des Objekts konnte über das Home Assistant-Register nicht überprüft werden. Anzeige und Aktionen sind vorübergehend nicht verfügbar.","toast.markup_needs_server":"Markup ist verfügbar, nachdem die Konfiguration auf den Server verschoben wurde.","toast.space_order_changed":"Reihenfolge geändert. Wenn eine Karte ihr Stockwerk nach Nummer festlegt, überprüfen Sie diese Paneele.","toast.conflict":"Die Konfiguration wurde in einem anderen Fenster geändert — Daten aktualisiert, wiederholen Sie Ihre letzte Aktion.","toast.cfg_save_failed":"Speichern der Konfiguration fehlgeschlagen: {err}","toast.room_overlap":"Die Umrisse überlappen den Raum „{name}“ — Räume dürfen sich nicht überlappen","toast.contour_cannot_close":"Die Kontur kann nicht geschlossen werden, da sie entartet ist oder sich selbst schneidet","toast.merge_not_adjacent":"Es können nur Räume zusammengeführt werden, die eine Wand teilen","toast.rooms_merged":"Räume zu „{name}“ zusammengeführt","toast.split_pick_wall":"Beginnen Sie den Schnitt an der Wand des Raumes","toast.split_bad_cut":"Der Schnitt muss wand-zu-wand innerhalb des Raumes verlaufen, ohne Wände oder sich selbst zu kreuzen","merge.header":"Räume zusammenführen","merge.hint":"Der zusammengeführte Raum behält einen Namen und eine Fläche. Die andere Fläche wird freigegeben — ihre Geräte verlassen den Plan, bis ein anderer Raum sie beansprucht.","merge.keep":"Behalten","merge.no_area":"keine Fläche","toast.room_saved":"Raum gespeichert ({n}). Hinzugefügte Geräte: {added}. Zeichnen Sie die nächste Kontur oder verlassen Sie die Markierung.","toast.room_saved_no_area":"Raum gespeichert ({n}, keine Fläche). Zeichnen Sie die nächste Kontur oder verlassen Sie die Markierung.","toast.marker_needs_server":"Die Gerätebearbeitung ist verfügbar, nachdem die Konfiguration auf den Server verschoben wurde","toast.virtual_name_required":"Einen Namen für das virtuelle Gerät eingeben","toast.marker_saved":"Gerät gespeichert","toast.marker_removed":"Gerät aus dem Plan gelöscht","toast.integration_missing":"Die House Plan-Integration ist nicht installiert — Verwaltung nicht verfügbar","toast.plan_formats":"Unterstützte Formate: SVG, PNG, JPG, WebP","toast.plan_required":"Grundriss hochladen — erforderlich","toast.space_added_onboard":"Bereich hinzugefügt. Räume einzeichnen: Rasterpunkte anklicken und die Kontur schließen.","toast.space_added":"Bereich hinzugefügt","toast.space_saved":"Bereich gespeichert","toast.space_deleted":"Bereich gelöscht","toast.delete_failed":"Löschen fehlgeschlagen: {err}","toast.error":"Fehler: {err}","toast.toggle_target_unavailable":"Ziel „{name}“ ist nicht verfügbar — keine Aktion durchgeführt","toast.toggle_targets_unavailable":"Ziele nicht verfügbar: {names}. Keine Aktion durchgeführt","toast.file_failed":'Datei "{name}" wurde nicht hochgeladen: {err}',"toast.files_attached":"Dateien angehängt: {n}","err.unknown":"unbekannter Fehler","err.code":"Code {code}","err.too_large":"Datei größer als {mb} MB","err.bad_ext":"nicht unterstützter Typ (PDF/Bild erwartet)","err.unauthorized":"Administratorrechte erforderlich","editor.title":"Titel","editor.default_floor":"Anfangsbereich","editor.default_floor_missing":"Anfangsbereich „{id}“ existiert nicht mehr. Wählen Sie einen anderen Bereich.","editor.floor":"Fester Bereich","editor.floor_none":"— nicht fest —","editor.floor_index":"YAML-Index {index} (beibehalten)","fixed_floor.loading":"Lade den festen Bereich…","fixed_floor.invalid_title":"Der feste Bereich ist nicht verfügbar","fixed_floor.invalid_body":"Überprüfen Sie die Etage in der Kartenkonfiguration. Der konfigurierte Wert ist: {value}","editor.icon_size":"Symbolgröße, % der Planbreite","editor.show_temperature":"Temperatur anzeigen","editor.live_states":"Live-Zustände (ein/aus, offen…)","editor.light_pools":"Lichtkegel und Wandschatten","editor.show_signal":"Zigbee-Signal anzeigen (LQI)","editor.language":"Schnittstellensprache","editor.lang_auto":"Automatisch (HA-Profil)","title.icon_rules":"Symbolregeln: welche MDI-Symbole Geräte nach Namen erhalten","rules.title":"Symbolregeln","rules.hint":'Regeln werden von oben anhand von "Gerätename + Modell" (Großschreibungs-unempfindliches Regex) überprüft; das erste Match gewinnt. Wenn nichts übereinstimmt, entscheidet die Entität-Geräteklasse, dann das generische Chip-Symbol.',"rules.pattern_ph":"regex, z. B. Stecker|Steckdose","rules.icon_ph":"mdi:power-socket-de","rules.add":"Regel hinzufügen","rules.reset":"Zurücksetzen auf Standardeinstellungen","rules.test_ph":"Versuch mal einen Gerätenamen...","rules.invalid":"ungültiges regex","rules.saved":"Icon-Regeln gespeichert","btn.up":"Nach oben","btn.down":"Nach unten","tap.info":"Gerätekarte","tap.more_info":"HA Mehr-Info-Dialog","tap.toggle":"Zustand umschalten","marker.tap_label":"Tap-Aktion für dieses Gerät","tap.toggle_note":"Der aufgelöste Zustand ist unten dargestellt. Sichere Geräte werden niemals aus dem Plan umgeschaltet.","import.title":"Bereiche aus HA-Etagen erstellen","import.hint":"Home Assistant kennt diese Etagen bereits. Die Etagen auswählen, die zu Planbereichen werden sollen; anschließend für jeden Bereich einen Grundriss hochladen. Die Räume werden danach von Hand eingezeichnet.","import.start":"{n} Bereich(e) erstellen","import.manual":"Von Grund auf neu starten","import.progress":"Etage {i} von {n}","import.done":"Bereiche erstellt. Räume einzeichnen: Rasterpunkte anklicken und die Kontur schließen.","btn.skip":"Überspringen","space.scale_label":"Maßstab (Rasterzellen-Größe)","space.cell_cm.help":"Verknüpft das Raster mit realen Abmessungen: Davon hängen Längen und Flächen, Wandstärken, Öffnungsgrößen und der Leuchtradius ab. Eine spätere Änderung verändert die berechneten Abmessungen des gesamten Bereichs, verschiebt aber keine Punkte im Plan.","space.cell_cm.help.aria":"Hilfe: Maßstab des Bereichs","space.scale_unit":"cm pro Zelle","space.scale_unit_imperial":"Zoll pro Zelle","space.display_section":"Anzeige","space.show_borders":"Raumgrenzen immer anzeigen","space.zero_wall_style":"Wände ohne Dicke","space.zero_wall_style.help":"Gestrichelte Wände ohne Dicke lassen Glow und Sonnenstrahlen durch, durchgezogene blockieren sie als Barriere ohne Fläche. Die Auswahl gilt für alle solchen Wände im Bereich, auch wenn ihre Linie in der Ansicht ausgeblendet ist.","space.zero_wall_style.help.aria":"Hilfe: Darstellung der Wände ohne Dicke","space.zero_wall_dashed":"Gestrichelt","space.zero_wall_solid":"Durchgezogen","space.show_names":"Raumnamen anzeigen (zum Verschieben ziehen)","space.room_color":"Farbe der Begrenzung & des Namens","space.opacity":"Deckkraft","space.fill_label":"Raumausfüllung","space.fill_mode.help":"„Eigene Farbe“ gestaltet den Bereich; „Licht“, „Temperatur“ und „LQI“ verwenden aktuelle Daten aus Home Assistant. Glow wird separat aktiviert.","space.fill_mode.help.aria":"Hilfe: Modus der Raumausfüllung","fill.none":"Keine","fill.lqi":"Zigbee-Signal","fill.light":"Lichter","fill.custom":"Benutzerdefinierte Farbe","space.custom_fill":"Füllfarbe","space.source_file":"Ich habe einen Grundriss als Bild","space.source_draw":"Kein Bild – ich werde die Räume von Hand umreißen","fill.temp":"Temperatur","tip.temp_avg":"Durchschnittstemperatur:","tip.hum_avg":"Durchschnittliche Luftfeuchtigkeit:","space_card.button":"Grundriss öffnen","space_card.not_found":"Bereich „{id}“ nicht gefunden","space_card.loading":"Laden…","continuity.restore_plan":"Grundriss wiederherstellen…","continuity.restore_connection":"Geräteverbindung wiederherstellen…","continuity.retry":"Erneut versuchen","editor.space":"Bereich","editor.framing":"Bildausschnitt","editor.fit_content":"Alle sichtbaren Inhalte","editor.fit_house":"Eng an der Hausgeometrie","editor.show_button":"Schaltfläche anzeigen","editor.button_label":"Beschriftung der Schaltfläche","editor.button_target":"Ziel-Dashboard-Pfad","marker.sub_entity":"Entität","title.general_settings":"Allgemeine Einstellungen","gs.title":"Allgemeine Einstellungen","gs.light_group":"Füllung: Licht","gs.light_on":"Lichter an","gs.light_off":"Alle Lichter aus","gs.temp_group":"Füllung: Temperatur","gs.temp_cold":"Kalt","gs.temp_ok":"Angenehm","gs.temp_hot":"Heiß","gs.lqi_group":"Füllung: Zigbee-Signal","gs.lqi_low":"Schwaches Signal","gs.lqi_high":"Starkes Signal","gs.reset":"Auf Standard zurücksetzen","gs.saved":"Allgemeine Einstellungen gespeichert","space.show_lqi":"Zigbee-Signal (LQI) neben Geräten anzeigen","space.hide_decor":"Dekorationsschicht ausblenden","space.hide_decor_tip":"Linien, Formen, Beschriftungen und Möbel bleiben an ihrem Platz — im Hintergrundeditor sichtbar, aber nicht auf dem Plan.","space.hide_openings":"Öffnungen ausblenden","space.hide_openings_tip":"Tür-, Fenster- und Tor-Symbole werden nicht gezeichnet, aber die Öffnungen funktionieren weiterhin: Licht fällt hindurch, die Sonne kommt durch ein Fenster herein, Kontaktsensoren öffnen sie weiterhin. Der Planeditor zeigt sie immer an.","gs.light_none":"Keine Lichtquellen","mode.plan":"Planeditor","mode.devices":"Geräteeditor","display.value":"Wert + Zustand","marker.subarea":"kein Bereich, manuell","device.new":"Neues Gerät — Editor öffnen, um zu schließen","opening.unlock_action":"Entsperren","opening.lock_action":"Sperren","opening.lock_pending":"Wird ausgeführt…","title.close_editor":"Editor schließen (zur Ansicht zurück)","title.add_device":"Gerät zum Plan hinzufügen","devbar.add":"Hinzufügen","devbar.rules":"Symbolregeln","device_inbox.button":"Geräte","device_inbox.title":"Geräte auf dem Plan","device_inbox.search":"Geräte, Entitäten und Integrationen suchen…","device_inbox.add_virtual":"Virtuelles Gerät hinzufügen","device_inbox.tab_on_plan":"Auf Plan","device_inbox.tab_available":"Verfügbar","device_inbox.tab_hidden":"Versteckt","device_inbox.tab_readd":"Wieder verfügbar","device_inbox.only_new":"Nur neu","device_inbox.show_entities":"Entitäten anzeigen","device_inbox.show_hidden":"Versteckte auf Plan anzeigen","device_inbox.show_hidden.help":"Zeigt ausgeblendete und deaktivierte Marker vorübergehend als Bearbeitungs-Geister auf dem Plan. Die gespeicherte Sichtbarkeit der Geräte bleibt unverändert.","device_inbox.show_hidden.help.aria":"Hilfe: ausgeblendete Geräte auf dem Plan anzeigen","device_inbox.new":"Neu","device_inbox.find":"Auf dem Plan finden","device_inbox.edit":"Bearbeiten","device_inbox.hide":"Ausblenden","device_inbox.show":"Anzeigen","device_inbox.add":"Hinzufügen","device_inbox.readd":"Wieder hinzufügen","device_inbox.hide_available":"Aus der Liste ausblenden","device_inbox.show_more":"Mehr anzeigen","device_inbox.more_actions":"Weitere Aktionen","device_inbox.find_hidden_hint":"Zuerst „Versteckte auf Plan anzeigen“ aktivieren","device_inbox.show_disabled":"Diese Bindung in Home Assistant aktivieren, bevor sie angezeigt wird","device_inbox.empty_on_plan":"Es befinden sich noch keine passenden Geräte auf dem Plan.","device_inbox.empty_available":"Es sind keine Geräte zum Hinzufügen verfügbar.","device_inbox.empty_hidden":"Es gibt keine versteckten Geräte.","device_inbox.empty_readd":"Es sind keine entfernten Geräte verfügbar, um sie erneut hinzuzufügen.","device_inbox.reason_visible_auto":"Automatisch erkannt","device_inbox.reason_visible_explicit":"Explizit hinzugefügt","device_inbox.reason_manual_hidden":"Vom Benutzer versteckt","device_inbox.reason_automatic_hidden":"Automatisch versteckt","device_inbox.reason_service_entry":"Nur Service-Registry-Eintrag","device_inbox.reason_excluded_integration":"Integration „{integration}“ durch Erkennungsfilter ausgeschlossen","device_inbox.reason_excluded_domain":"Nicht-räumlicher Entitätstyp","device_inbox.reason_grouped_light":"Dargestellt durch eine Raumlichtgruppe","device_inbox.reason_represented_by_parent":"Dargestellt durch sein übergeordnetes Gerät","device_inbox.reason_removed":"Zuvor aus dem Plan entfernt","device_inbox.reason_available":"Zum Hinzufügen zum Plan verfügbar","device_inbox.reason_no_bound_room":"HA-Bereich ist nicht mit einem Planraum verknüpft","device_inbox.status_ha_disabled":"In Home Assistant deaktiviert","device_inbox.status_orphaned":"Bindung ist in Home Assistant nicht mehr vorhanden","device_inbox.status_unverified":"Home Assistant-Register vorübergehend nicht verfügbar","device_inbox.saved":"Geräteliste aktualisiert","device_inbox.filters_excluded":"Ausgeschlossene Integrationen","device_inbox.filters_group_lights":"Raumleuchten zu einem Marker gruppieren","device_inbox.filters_preview_appear":"erscheint: {count}","device_inbox.filters_preview_hide":"verschwindet: {count}","device_inbox.filters_preview_lights":"betroffene Leuchten: {count}","device_inbox.filters_reset":"Empfohlene wiederherstellen","device_inbox.filters_save":"Filter speichern","device_inbox.filters_search_ph":"Integration hinzufügen…","device_inbox.filters_title":"Erkennungsfilter","space.roomcard_section":"Raumkarte zeigt:","space.label_temp":"Temperatur","space.label_hum":"Luftfeuchtigkeit","space.label_lqi":"Durchschnittliches Zigbee-Signal","space.label_light":"Lichter ein/aus","roomcard.light_on":"Ein","roomcard.light_off":"Aus","roomcard.light_partial":"{on} von {total}","toast.split_pick_inside":"Zwischenliegende Schnittpunkte müssen innerhalb des Raumes liegen","mode.decor":"Hintergrundeditor","decor.select":"Auswählen","decor.line":"Linie","decor.rect":"Rechteck","decor.ellipse":"Oval","decor.text":"Text","decor.erase":"Löschen","decor.erase_confirm_title":"Objekt löschen?","decor.color":"Farbe","decor.width":"Linienbreite","decor.line_style":"Linienstil","decor.line_style_solid":"Durchgehend","decor.line_style_dashed":"Gepunktet","decor.fill":"Füllen","decor.fill_color":"Füllfarbe","decor.length":"Länge","decor.size":"Größe","decor.flip_h":"Horizontal spiegeln","decor.flip_v":"Vertikal spiegeln","decor.angle":"Rotationswinkel, °","decor.text_size":"Textgröße","decor.backdrop_properties":"Eigenschaften des Planhintergrunds","decor.text_title":"Textbeschriftung","decor.object_title":"{kind} bearbeiten","decor.text_label":"Text","decor.live_group":"HA-Variable einfügen","decor.live_entity":"Entität","decor.live_entity_ph":"Wählen Sie eine Entität","decor.live_attr":"Wert","decor.live_attr_ph":"Wählen Sie Status oder Attribut","decor.live_state":"Status","decor.backdrop":"Hintergrundbild","decor.backdrop_hint":"Ziehen zum Verschieben; eine Ecke ziehen zum Größenändern; den oberen Griff zum Drehen verwenden. Shift ändert das Verhältnis oder befreit den Winkel.","decor.backdrop_reset":"Bild zurücksetzen","decor.backdrop_reset_done":"Das Bild ist wieder an seinem ursprünglichen Platz und in seiner ursprünglichen Größe","marker.icon_auto":"Auto: {icon} (nach Symbolregeln; wählen Sie eines zur Überschreibung)","marker.icon_pin_auto":"Anheften","mode.plan_tip":"Planungseditor — die Geometrie des Hauses: Räume zeichnen und teilen/zusammenführen, sie mit HA-Bereichen verbinden, Türen, Fenster und Tore platzieren, Raumkarten verschieben, Maßstab festlegen","mode.devices_tip":"Geräteeditor — alles über Symbole: ziehen zum Positionieren, klicken zum Bearbeiten von Bindung/Symbol/Anzeige, virtuelle Geräte hinzufügen, Symbolregeln","mode.decor_tip":"Hintergrundeditor — rein visuelle Dekoration unter dem Plan: Linien, Rechtecke, Ellipsen und Textbeschriftungen, die niemals auf Klicks reagieren","space.glow_enabled":"Lichtquellen-Glühen","gs.glow_group":"Glow von Lichtquellen","gs.glow_base":"Grunddunkelheit des Hauses","gs.glow_light":"Standardlichtfarbe / Intensität","gs.wall_group":"Wände","gs.wall_fill":"Wandfüllung","gs.glow_radius":"Glow-Radius","gs.glow_radius.help":"Legt den allgemeinen Radius des Lichtscheins in Metern oder Fuß fest; ein gerätespezifischer Radius überschreibt diesen Wert.","gs.glow_radius.help.aria":"Hilfe: allgemeiner Glow-Radius","gs.unit_m":"m","gs.unit_ft":"ft","marker.controls_label":"Steuert andere Lichtquellen","marker.controls.help":"Mit der Aktion „Zustand umschalten“ werden die aufgeführten Quellen zusammen mit diesem Marker umgeschaltet. Ihr Glow bleibt an ihren eigenen Markern, und die Verknüpfung allein macht den steuernden Marker nicht zur Lichtquelle.","marker.controls.help.aria":"Hilfe: andere Lichtquellen steuern","marker.controls_filter":"Suchlichter und Schalter…","info.controls":"Steuerungen","marker.glow_radius_label":"Leuchtradius","marker.glow_radius.help":"Legt den Leuchtradius in Metern oder Fuß fest; ein leerer Wert verwendet den Radius aus den allgemeinen Einstellungen.","marker.glow_radius.help.aria":"Hilfe: Leuchtradius","markup.wallthick":"Dicke","markup.select":"Auswählen","title.markup_wallthick":"Dicke — klicken Sie auf eine Wand, um ihre Dicke von 0 bis 100 cm festzulegen.","markup.hint_wallthick":"klicken Sie auf eine Wand · Esc schließt ohne Anwendung","wallthick.field":"Dicke","wallthick.unit_cm":"cm","wallthick.unit_in":"in","wallthick.apply_room":"Auf alle Wände dieses Raums anwenden","markup.draw_wall_title":"Dicke jedes neuen Wandsegments (0–100 cm). Gemeinsame Wände behalten den bestehenden Wert.","room.queue_progress":"Raum {current} von {total}","toast.wall_rooms_saved":"Erstellte Räume: {n}","toast.wall_chain_saved":"Wandkette gespeichert","toast.wallthick_pick":"Eine Wand anklicken","toast.wallthick_set":"Wandstärke eingestellt","toast.wallthick_cleared":"Wandstärke entfernt","toast.physical_range":"Einen Wert von {min} bis {max} {unit} eingeben","toast.zero_wall_opening_conflict":"Entfernen Sie zuerst die Öffnung an diesem Wandsegment.","toast.zero_wall_ambiguous":"Das Wandsegment ist mehrdeutig. Vereinfachen oder passen Sie den Anschluss an.","toast.zero_wall_migration_blocked":"Der Bereich wurde nicht konvertiert: {reason}. Es wurden keine Daten geändert.","toast.physical_angle":"Einen Drehwinkel von 0° bis unter 90° eingeben","toast.physical_limit":"Der Bereich hat das Limit für diesen Geometrietyp erreicht","toast.geometry_unsafe":"Änderung abgebrochen: Wandgeometrie konnte nicht sicher erstellt werden.","junction.limit_angle":"Der Winkel zwischen den Wänden ist zu spitz: {actual}°, mindestens {limit}°.","junction.limit_valence":"Zu viele Wände treffen in einem Knoten aufeinander: {actual}, maximal {limit}.","junction.limit_length":"Das Wandsegment ist zu kurz: {actual} cm, mindestens {limit} cm.","junction.limit_distance":"Wände und Knoten sind zu dicht beieinander: {actual} cm, Minimum {limit} cm.","junction.limit_clearance":"Kein Wohnbereich ist übrig: {actual} cm², Minimum {limit} cm².","junction.limit_check_failed":"Die Überprüfung der Verbindungen konnte nicht durchgeführt werden — die Änderung wurde nicht gespeichert.","toast.wall_model_migration_blocked":"Das Wandmodell konnte nicht aktualisiert werden: {reason}. Der Plan wurde nicht geändert. Führen Sie „Pläne optimieren“ aus; wenn der Fehler erneut auftritt, beheben Sie die widersprüchliche Wandgeometrie.","toast.wall_model_client_outdated":"Aktualisieren Sie die Karte und laden Sie die Seite neu, bevor Sie den Plan bearbeiten.","wall_model.reason.invalid-room":"ungültiger Raumkontur","wall_model.reason.zero-length":"Wandsegment mit null Länge","wall_model.reason.third-owner":"Wand, die von mehr als zwei Räumen geteilt wird","wall_model.reason.duplicate-id":"widersprüchliche Wandkennungen","wall_model.reason.thickness-conflict":"widersprüchliche Wandstärkenwerte","wall_model.reason.opening-host":"Öffnung kann nicht einer Wand zugewiesen werden","toast.delete_room_pick":"Klicken Sie in den Raum, den Sie löschen möchten","toast.plan_snap_ambiguous":"Zoomen Sie hinein, um den Wandknoten auszuwählen","toast.wall_repair_ambiguous":"Der Raumumriss hat mehr als eine mögliche Verbindung. Zoomen Sie hinein und verbinden Sie ihn explizit.","toast.wall_repair_too_large":"Die Lücke ist größer als 2 cm. Verbinden Sie die Wände, bevor Sie den Raum erstellen.","toast.wall_repair_changed":"Die Wandgeometrie hat sich geändert. Versuchen Sie erneut, den Raum zu erstellen.","toast.opening_on_zero_wall":"Öffnungen können nicht auf einer Wand mit null Dicke sitzen.","marker.from_ha_option":"Wählen Sie aus der HA-Liste.","marker.show_entities":"Entitäten anzeigen.","marker.show_entities_tip":"Fügt nicht nur Geräte zur Liste hinzu, sondern auch alle ihre Entitäten.","marker.pick_ph":"Wählen Sie ein Gerät…","room.open_area":"Öffnen Sie den HA-Bereich.","view.volumetric":"Volumetrische Ansicht.","view.flat":"Flache Ansicht.","kiosk.title":"Die Größen dieses Bildschirms.","kiosk.hint":"Nur auf diesem Gerät gespeichert – jedes Wandtablet oder TV kann seine eigenen komfortablen Größen haben.","kiosk.icon_scale":"Gerätesymbolgröße.","kiosk.font_scale":"Textgröße der Raumkarte.","editor.kiosk":"Wandgeräte- (Kiosk-)Modus.","editor.cycle":"Bereiche automatisch alle N Sekunden wechseln (Kiosk, 0 = aus)","room.settings_title":"Raumeinstellungen.","room.settings_section":"Raumeinstellungen (überschreibt den Bereich)","room.fill_label":"Diesen Raum ausfüllen","fill.inherit":"Als den Bereich","room.custom_fill_space":"Bereichsfarbe","room.custom_fill_own":"Raumfarbe","room.temp_src_label":"Temperaturquelle","room.hum_src_label":"Luftfeuchtigkeitsquelle","room.src_average":"Durchschnitt über die Sensoren des Raums (Standard)","room.src_pick":"Ein bestimmtes HA-Gerät oder Entität","room.src_ph":"Quelle wählen…","toast.room_updated":"Raum aktualisiert","space.card_font":"Schriftgröße der Raumkarte (gesamter Bereich)","room.sizes_section":"Schriftgrößen","room.name_scale":"Raumname Größe","room.label_scale":"Metrikgröße","preview.room_name":"Wohnzimmer","toast.cfg_reload_failed":"Der Plan konnte nicht vom Server neu geladen werden: {err}","toast.locale_load_failed":"Das Sprachpaket konnte nicht geladen werden. Bis zum Neuladen der Seite wird Englisch verwendet.","room.settings_short":"Raumeinstellungen","room.unnamed":"Unbenannter Raum","marker.use_climate_temp":"Geräte-Temperatur im Raum berücksichtigen","marker.use_climate_temp_tip":"Fügt die aktuelle Temperatur einer Klimaanlage oder eines Thermostats zum Raumdurchschnitt hinzu. Das externe Wert-Label unten separat konfigurieren.","marker.value_badge_title":"Wert-Label","marker.value_badge.help":"Zeigt einen ausgewählten Wert neben dem Symbol an. Dies beeinflusst nicht die Raumkennzahlen, Licht, Glanz oder die Tippaktion.","marker.value_badge.help.aria":"Hilfe: Gerätewert-Badge","marker.value_badge_enabled":"Zeige ein Wert-Badge","marker.value_badge_source":"Wert","marker.value_badge_source.help":"Wählen Sie einen bestimmten Zustand, ein unterstütztes Attribut oder einen abgeleiteten Wert dieses Geräts.","marker.value_badge_source.help.aria":"Hilfe: Quelle des Wert-Badges","marker.value_badge_position":"Position","marker.value_badge_position.help":"Die gewählte Seite bleibt fest und dreht sich nicht automatisch an einem Planrand.","marker.value_badge_position.help.aria":"Hilfe: Position des Wert-Badges","marker.value_badge_right":"Rechts","marker.value_badge_bottom":"Unten","marker.value_badge_left":"Links","marker.value_badge_top":"Oben","marker.value_badge_empty":"Für dieses Gerät stehen keine Werte zur Verfügung","marker.value_badge_static":"Ein statisches Symbol zeigt keine Live-Werte an. Die Einstellung wird beibehalten.","marker.value_badge_missing":"Quelle nicht verfügbar","marker.value_badge_missing_hint":"Die gespeicherte Quelle ist derzeit nicht verfügbar. Behalten Sie sie bei, deaktivieren Sie das Badge oder wählen Sie einen anderen Wert.","marker.value_badge_duplicate":"Derselbe Wert wird bereits im Symbol angezeigt.","marker.value_badge_state":"Status · {name}","marker.value_badge_marker_state":"Lichtquellstatus · {name}","marker.value_badge_lqi":"Durchschnittliche Zigbee-Signalqualität","marker.value_badge_attr_current_temperature":"Aktuelle Temperatur · {name}","marker.value_badge_attr_temperature":"Zieltemperatur · {name}","marker.value_badge_attr_current_humidity":"Aktuelle Luftfeuchtigkeit · {name}","marker.value_badge_attr_humidity":"Luftfeuchtigkeit · {name}","marker.value_badge_attr_current_position":"Position · {name}","marker.value_badge_attr_percentage":"Geschwindigkeit · {name}","marker.value_badge_attr_brightness":"Helligkeit · {name}","marker.value_badge_attr_volume_level":"Lautstärke · {name}","marker.value_badge_attr_battery_level":"Batterie · {name}","marker.value_badge_attr_fan_speed":"Lüftergeschwindigkeit · {name}","marker.value_source":"Wertquelle","marker.value_source.help":"Wähle den Wert, der das Symbol ersetzt. Die Tipp-Aktion bleibt unverändert.","marker.value_source.help.aria":"Hilfe: Wertquelle in der Gerätefläche","marker.value_source_auto":"Automatisch (wie bisher)","marker.value_source_missing_hint":"Die gespeicherte Quelle ist derzeit nicht verfügbar. Bis sie wieder verfügbar ist oder ein anderer Wert gewählt wird, zeigt die Fläche —.","marker.light_role_label":"Ist dieses Gerät eine Lichtquelle?","marker.light_role.help":"„Auto“ verwendet die ermittelte Rolle des verknüpften Geräts, „Immer“ erzwingt eine eigene Quelle und „Nie“ schließt sie aus; oben verknüpfte Lichter bleiben unabhängig.","marker.light_role.help.aria":"Hilfe: ob dieses Gerät eine Lichtquelle ist","marker.light_role_auto_yes":"Automatisch (Lichtquelle)","marker.light_role_auto_no":"Automatisch (keine Lichtquelle)","marker.light_role_always":"Immer eine Lichtquelle","marker.light_role_never":"Nie eine Lichtquelle","marker.light_entity_label":"Führende Lichtereinheit","marker.light_entity.help":"Für ein Verbundgerät wählen Sie die Entität, deren Zustand, Farbe und Helligkeit diese Planquelle darstellen. Der automatische Rückgriff bleibt mit älteren Plänen kompatibel.","marker.light_entity.help.aria":"Hilfe: führende Lichtentität","marker.light_entity_auto":"Automatisch ({entity})","marker.light_entity_none":"keine steuerbare Entität","marker.light_entity_missing":"Die gespeicherte Entität {entity} ist nicht verfügbar. House Plan verwendet vorübergehend {fallback}; die gespeicherte Auswahl wird wiederhergestellt, wenn sie zurückkehrt.","marker.toggle_entity_label":"Zu toggelnde Entität","marker.toggle_entity.help":"Für ein Verbundgerät wählen Sie das genaue eigene Licht oder den Schalter, der durch Tippen bedient wird. Automatisch behält die vorherigen Zielregeln bei und ist unabhängig von der führenden Lichtentität.","marker.toggle_entity.help.aria":"Hilfe: zu toggelnde Entität","marker.toggle_entity_auto":"Automatisch ({entity})","marker.toggle_entity_none":"keine eigene steuerbare Entität","marker.toggle_entity_missing":"Die gespeicherte Entität {entity} ist nicht mehr unter den auswählbaren Kanälen dieses Markers. House Plan verwendet vorübergehend {fallback}; die gespeicherte Auswahl wird wiederhergestellt, wenn sie zurückkehrt.","marker.glow_color_label":"Leuchtfarbe und Helligkeit","marker.glow_mode.help":"Verwenden Sie Live-Quellwerte, überschreiben Sie nur deren Farbe oder fixieren Sie sowohl Farbe als auch Helligkeit. Das Minimum beträgt 1 %; um die Quelle zu deaktivieren, wählen Sie „Nie“.","marker.glow_mode.help.aria":"Hilfe: Leuchtfarbe und Helligkeit","marker.glow_mode_auto":"Von Quelle","marker.glow_mode_color":"Farbe einstellen","marker.glow_mode_fixed":"Farbe und Helligkeit einstellen","marker.glow_color":"Leuchtfarbe","marker.glow_brightness":"Helligkeit","marker.glow_disabled_never":"Leuchteinstellungen sind nicht verfügbar, da dieser Marker ausdrücklich keine Lichtquelle ist.","marker.glow_disabled_auto":"Im Automatikmodus wurde keine räumliche Lichtquelle für diesen Marker gefunden.","marker.glow_disabled_no_entity":"Keine aktive steuerbare Home Assistant-Entität ist für diese räumliche Quelle verfügbar.","marker.glow_passive_hint":"Diese Quelle hat keine eigenen Home Assistant-Daten. Stellen Sie ihre Farbe und Helligkeit manuell ein; ihr Radius bleibt verfügbar.","marker.control_broken":"Gespeicherte Quelle fehlt oder ist nicht mehr als Licht markiert","marker.control_missing_label":"Fehlendes Planlicht","marker.control_passive":"passive Quelle","toast.marker_control_cycle":"Dieser Link würde eine kreisförmige Kette von Lichtsteuerungen erzeugen.","toast.marker_binding_required":"Wählen Sie ein Home Assistant-Gerät, bevor Sie eine andere Lichtquelle verlinken.","confirm.unlock_title":"Schloss öffnen?","confirm.unlock_body":"House Plan sendet einen Befehl zum Öffnen an dieses Schloss.","toast.files_migrate_failed":"Anhänge konnten nicht zur neuen Bindung verschoben werden, Links zeigen weiterhin auf die alten Dateien: {err}","space.pick_saved":"Bereits hochgeladen","space.pick_saved_hint":"Auf dem Server gespeicherte Pläne, einschließlich solcher, die Sie zuvor getrennt haben","space.no_saved":"Noch keine Pläne auf dem Server gespeichert.","space.loading":"Laden…","space.used_by":"in Benutzung: {list}","space.in_use":"Ein Bereich verwendet diesen Plan noch — zuerst die Verknüpfung lösen","btn.use":"Verwenden","confirm.delete_plan_title":"Plandatei löschen?","confirm.delete_plan_body":"Die Datei wird vom Server gelöscht. Dieser Vorgang kann nicht rückgängig gemacht werden.","toast.plans_list_failed":"Konnte die gespeicherten Pläne nicht auflisten: {err}","toast.plan_delete_failed":"Konnte den Plan nicht löschen: {err}","marker.hide":"Ausblenden","marker.hide_tip":'Das Gerät wird nach dem Speichern aus dem Plan verschwinden, aber weiterhin zum Signalsignal des Raums zählen. Stellen Sie es über den Katalog "Geräte" im Geräte-Editor wieder her.',"marker.show":"Anzeigen","marker.show_tip":"Das Gerät wird nach dem Speichern wieder im Plan erscheinen.","marker.hidden_ghost":"Vom Benutzer ausgeblendetes Gerät","marker.ha_disabled_device":"Das Gerät ist in Home Assistant deaktiviert und im Plan ausgeblendet.","marker.ha_disabled_entity":"Die Entität ist in Home Assistant deaktiviert und im Plan ausgeblendet.","marker.ha_disabled_all_entities":"Das Gerät hat keine aktiven Home Assistant-Entitäten, daher ist es im Plan ausgeblendet.","marker.ha_registry_limited":"Das vollständige Home Assistant-Register ist für diesen Benutzer nicht verfügbar. Das nicht verifizierte Objekt kann vorerst nicht angezeigt oder verwendet werden.","marker.delete_tip":"Löschen Sie das Gerät vollständig aus dem Plan und allen Aggregaten. Sie können es später wieder hinzufügen.","tap.run":"Führen Sie Automation/Skript/Szene aus","tap.none":"Nichts tun","marker.run_target_label":"Was ausführen","marker.run_search_ph":"Suchen: Automation, Skript oder Szene…","marker.run_target_gone":"Ziel {id} nicht gefunden — erneut auswählen","marker.tap_confirm":"Um Bestätigung bitten","marker.tap_confirm_tip":"Vor der Ausführung ein Bestätigungsdialogfeld anzeigen — eine Vorsichtsmaßnahme gegen versehentliche Berührungen.","marker.toggle_hint_single":"Ziel: {name} ({id}).","marker.virtual_light_target":"Virtuelles Licht: {name}.","marker.virtual_light_current":"Manueller Zustand: {state} → {effect}.","marker.virtual_light_state_on":"ein","marker.virtual_light_state_off":"aus","marker.toggle_hint_group":"Wird {count}-Quelle(n) umschalten: {names}.","marker.toggle_hint_current":"Jetzt: {state} → {effect}.","marker.toggle_hint_group_current":"Derzeit an: {on} von {count} → {effect}.","marker.toggle_hint_skipped":"Wird übersprungen ({count}): {targets}.","marker.toggle_effect_turn_on":"wird eingeschaltet","marker.toggle_effect_turn_off":"wird ausgeschaltet","marker.toggle_effect_open":"wird geöffnet","marker.toggle_effect_close":"wird geschlossen","marker.toggle_effect_stop":"wird gestoppt","marker.toggle_effect_toggle":"Zustand wird umgeschaltet","marker.toggle_skip_missing":"nicht gefunden","marker.toggle_skip_ha_disabled":"in HA deaktiviert","marker.toggle_skip_unavailable":"nicht verfügbar","marker.toggle_skip_unsupported":"Umschalten wird nicht unterstützt","marker.toggle_skip_secure":"aus Sicherheitsgründen blockiert","marker.toggle_none_no_binding":"Dieses Gerät hat keine Bindung, daher gibt es keinen Zustand, der umgeschaltet werden könnte. Tippen bewirkt nichts.","marker.toggle_none_no_actionable_entity":"Dieses Gerät hat keinen Zustand, der umgeschaltet werden könnte. Tippen bewirkt nichts.","marker.toggle_none_configured_targets_missing":"Die konfigurierten Ziele sind nicht verfügbar. Die eigene Entität des Geräts wird nicht ersetzt.","marker.toggle_none_ha_disabled":"Das Ziel ist in Home Assistant deaktiviert und kann im Plan nicht verwendet werden.","marker.toggle_none_unavailable":"Das Ziel ist derzeit nicht verfügbar. Tippen bewirkt nichts.","marker.toggle_none_unsupported":"Home Assistant bietet keine sichere Umschaltfunktion für dieses Gerät. Tippen bewirkt nichts.","marker.toggle_none_secure":"Das Umschalten von Schlössern, Alarmen und gesicherten Toren über den Plan ist aus Sicherheitsgründen gesperrt.","run.automation":"Automatisierung","run.script":"Skript","run.scene":"Szene","confirm.tap_run":'"{name}" ausführen?',"confirm.tap_toggle":'"{name}" umschalten?',"confirm.current_state":"Aktueller Zustand: {state}","confirm.expected_state":"Nach dem Umschalten: {state}","confirm.group_current":"an {on} von {total}","confirm.group_all_on":"alle sind eingeschaltet","confirm.group_all_off":"alle sind ausgeschaltet","confirm.unavailable_targets":"Nicht verfügbar: {count}","confirm.expected_by_ha":"Home Assistant ermittelt den Zustand","confirm.state_on":"Ein","confirm.state_off":"Aus","confirm.state_open":"Offen","confirm.state_closed":"Geschlossen","confirm.state_opening":"Wird geöffnet","confirm.state_closing":"Wird geschlossen","confirm.state_stopped":"Gestoppt","confirm.state_unknown":"Unbekannt","toast.run_started":"Gestartet: {name}","toast.run_target_missing":"Ausführungsziel nicht gefunden — überprüfen Sie die Geräteeinstellungen","toast.run_target_required":"Wählen Sie eine Automatisierung, ein Skript oder eine Szene aus","toast.tap_target_changed":"Das Ziel der Aktion hat sich geändert. Versuchen Sie es erneut.","toast.virtual_light_toggle_failed":"Das virtuelle Licht konnte nicht umgeschaltet werden: {err}","toast.value_badge_source_required":"Einen Wert für den Badge auswählen","btn.run":"Ausführen","vac.section":"Roboterstaubsauger: aktuelle Position","vac.autocal":"Automatisch einrichten","vac.live":"Aktuelle Position im Plan","vac.trail":"Roboterpfad anzeigen","vac.autocal_no_rooms":'Die Integration meldet keine Raumliste — öffnen Sie "Manuell anpassen"',"vac.route_warn_unmapped":"Der Roboter reinigt eine Karte, die keiner Etage zugeordnet ist","vac.route_warn_needs_calibration":"Die Karte ist einer Etage zugeordnet, aber nicht kalibriert","vac.route_warn_ambiguous":"Zwei Karten sind nicht unterscheidbar — keine Etage gewählt","vac.route_warn_missing_space":"Der Raum dieser Karte wurde gelöscht","vac.autocal_no_match":'Raumnamen stimmten nicht überein (mindestens 3 müssen übereinstimmen) — öffnen Sie "Manuell anpassen"',"vac.autocal_done":"Fertig: über {rooms} Räume zugeordnet. Eine Reinigung starten und das Ergebnis prüfen.","vac.cal_need_pos":"Der Roboter meldet keine Koordinaten — starten Sie eine Reinigung und pausieren Sie sie","vac.cal_done":"Kalibrierung gespeichert. Eine Reinigung starten und das Ergebnis prüfen.","vac.cal_cancelled":"Kalibrierung abgebrochen","vac.fit":"Manuell anpassen","vac.fit_hint":"Roboterkarte an die richtige Position ziehen und an den Ecken skalieren","vac.fit_rotate":"90° drehen","vac.fit_mirror":"Spiegeln","vac.trail_never":"Nie","vac.trail_cleaning":"Beim Reinigen","vac.trail_always":"Immer","gs.bg_group":"Bühnenhintergrund","gs.bg_color":"Hintergrund um den Plan","gs.bg_default":"Standardthema","gs.bg_theme":"Standardthema","gs.bg_mode":"Planhintergrund","gs.bg_mode.help":"„Folgt der Sonne“ verwendet sun.sun und ersatzweise die lokale Browserzeit; „Statische Farbe“ zeigt immer die ausgewählte Farbe.","gs.bg_mode.help.aria":"Hilfe: allgemeiner Planhintergrund","gs.bg_static":"Statische Farbe","gs.bg_daynight":"Folgt der Sonne","gs.sun_group":"Sonne","gs.sun_missing":"Die sun.sun-Entität wurde nicht gefunden — der Hintergrund folgt Ihrer lokalen Uhr; Fensterstrahlen sind nicht verfügbar.","gs.north":"Norden auf dem Plan","gs.north.help":"Der Winkel wird im Uhrzeigersinn von der oberen Vertikalen des Plans gemessen; Norden wird für Fensterstrahlen benötigt, nicht für den Hintergrund „Folgt der Sonne“.","gs.north.help.aria":"Hilfe: allgemeine Nordrichtung","gs.north_ph":"nicht gesetzt","gs.north_clear":"Löschen","gs.north_letter":"N","gs.sun_rays":"Sonnenlicht durch Fenster","gs.about_version":"House Plan Card v{v}","gs.about_github":"GitHub · Dokumentation & Probleme","gs.about_telegram":"Telegram-Chat","support.title":"Hilfe & Feedback","space.bg_color":"Hintergrund rund um den Plan","space.bg_inherit":"Allgemein erben","space.bg_inherited":"erbt allgemeine Einstellungen","space.bg_mode":"Planhintergrund","space.bg_mode.help":"Übernehmen Sie den allgemeinen Hintergrund oder überschreiben Sie diesen Bereich mit einer statischen Farbe oder „Folgt der Sonne“.","space.bg_mode.help.aria":"Hilfe: Hintergrund des Bereichs","space.north":"Norden auf dem Plan (überschreiben)","space.north.help":"Überschreibt die allgemeine Nordrichtung für diesen Bereich; der Winkel wird im Uhrzeigersinn von der oberen Vertikalen des Plans gemessen und für Fensterstrahlen verwendet.","space.north.help.aria":"Hilfe: Norden für diesen Bereich","space.north_inherited":"geerbt: {v}","space.sun_rays":"Sonnenlicht durch Fenster","space.sun_inherit":"Allgemein erben","space.sun_on":"Ein","space.sun_off":"Aus","canvas.far_objects":"{n} Objekt(e) weit vom Plan entfernt","canvas.show_far":"Anzeigen","canvas.home_tip":"Der Plan ist dort drüben — klicken, um ihn anzupassen","gs.grid_group":"Planwartung","gs.grid_hint":"Aktualisiert Datenmodelle, richtet Planelemente am Raster aus und fasst redundante Wandfragmente zusammen. Ein exakter Bericht wird angezeigt, bevor etwas gespeichert wird.","gs.align_all":"Pläne optimieren","gs.align_title":"Pläne optimieren","gs.align_none":"Alle Pläne verwenden bereits das aktuelle optimierte Datenmodell.","gs.optimize_no_automatic_changes":"Es gibt keine automatischen Änderungen, die angewendet werden müssen. Überprüfen Sie die unten stehenden Punkte.","gs.align_count":"{n} von {total} Elementen werden sich um höchstens {cm} cm bewegen.","gs.align_where":"Die größte Verschiebung ist in „{s}“.","gs.align_turned":"Öffnungen, deren Winkel korrigiert wurde: {n}.","gs.align_removed_drafts":"Ungültige Umrisse vom Raster zusammengeklappt und entfernt: {n}.","gs.optimize_redundant_drafts":"Gespeicherte Wandketten, die durch feste Raumwände verdeckt waren, wurden entfernt: {n}.","gs.align_preflight_failed":"Die Geometrie der folgenden Bereiche konnte nicht sicher überprüft werden: {spaces}{more}.","gs.align_preflight_hint":"Pläne wurden nicht geändert. Kopieren Sie die Diagnosen mit dem untenstehenden Button und fügen Sie sie zusammen mit einem Raumexport dem Fehlerbericht bei.","gs.preflight_reason_prepare-exception":"Die Bereichsgeometrie konnte nicht vorbereitet werden (Ausnahme beim Erstellen des Modells)","gs.preflight_reason_wall-null":"Der Wandkörper wurde nicht erstellt (die Vereinigung lieferte leer zurück)","gs.preflight_reason_wall-degraded-extra":"Der Wandkörper wurde mit zusätzlicher Geometrie beschädigt","gs.preflight_reason_wall-failed-core":"Der Kern des Wandkörpers konnte nicht zusammengesetzt werden","gs.preflight_reason_wall-exception":"Die Wandkonstruktion warf eine Ausnahme","gs.preflight_reason_floor-null":"Der Fußbodenumriss wurde nicht erstellt","gs.preflight_reason_floor-exception":"Bodenaufbau hat eine Ausnahme ausgelöst","gs.preflight_copy":"Diagnosen kopieren","gs.preflight_copied":"Diagnosen kopiert","gs.preflight_update_hint":"Die Karten- und Integrationsversionen unterscheiden sich — Hausplan aktualisieren und erneut versuchen.","gs.align_preflight_space":"Bereich {n}","gs.align_preflight_more":", und {n} mehr","gs.optimize_changes":"Modellmigrationen: {m}; aktualisierte Bereiche: {c}; entfernte verrauschte Koordinatenwerte: {p}; zusammengeführte Fragmente realer Wände: {w}; zusammengeführte Fragmente von Wänden ohne Dicke: {s}; unabhängige Wände: {i}.","gs.zero_walls_migrated":"Virtuelle Wandspannweiten konvertiert: {n}.","gs.wall_segments_migrated":"Wandsegmente stabilisiert: {n}.","gs.optimize_lattice_summary":"Rauschen in den Koordinatenwerten kanonisiert: {n}; maximale Bewegung: {cm} cm.","gs.optimize_lattice_space":"{space}: Koordinatenwerte kanonisiert: {n}; außerhalb des Rasters liegende Werte unverändert gelassen: {far}.","gs.optimize_coincident_partitions":"Versteckte unabhängige Wandabschnitte in Raumwände integriert: {n}.","gs.optimize_openings_rehosted":"Öffnungen wieder an Raumwände angebracht: {n}.","gs.optimize_walls_straightened":"Wände begradigt: {n}; maximale Bewegung: {cm} cm.","gs.optimize_walls_straightened_where":"Größte Wandkorrektur: {s}.","gs.optimize_walls_straighten_skipped":"Nahe Achsenwände unverändert gelassen, da sie nicht sicher repariert werden konnten: {n}.","gs.optimize_glow_migration":"Legacy Glow: {spaces} Bereiche → keine Datenfüllung + unabhängiges Glow; {rooms} Räume → geerbte Datenfüllung + unabhängiges Glow.","gs.optimize_references":"Referenzen repariert: Bereiche — {spaces}; Räume — {rooms}; Positionen — {positions}; Geräte aus fehlenden Bereichen gelöst — {detached}.","gs.optimize_reference_more":", und {n} mehr","gs.optimize_orphans_removed":"Vergessene Einträge entfernt: {total} — Raumbezeichnungen: {rooms}; Geräte: {devices}; Gruppenmarkierungen: {groups}. Sie gehörten zu zuvor gelöschten Bereichen.","gs.optimize_live_positions":"Alte Positionen in gelöschten Bereichen gehören zu vorhandenen Objekten: {n}{names}. Sie werden beibehalten.","gs.optimize_live_positions_remove":"Alte Positionen in gelöschten Bereichen gehören zu vorhandenen Objekten: {n}{names}. Sie sind zur Entfernung ausgewählt.","gs.optimize_live_names":": {names}{more}","gs.optimize_live_remove":"Alte Positionen entfernen","gs.optimize_live_keep":"Alte Positionen beibehalten","gs.optimize_live_selected":"Alte Positionen werden nach der Anwendung von Optimieren entfernt.","gs.optimize_unverified":"Positionen konnten nicht sicher überprüft werden: {n}. Sie wurden unverändert belassen.","gs.optimize_registry_limited":"Voller Administratorzugriff auf die Home Assistant-Registries ist für eine sichere Überprüfung erforderlich.","gs.optimize_vacuum_warning":"Raumzuordnungen, die noch überprüft werden müssen: {n}.","gs.optimize_details":"Details","gs.optimize_details_more":"Und {n} weitere Einträge.","gs.optimize_detail_removed":"wird entfernt","gs.optimize_detail_live":"wird beibehalten","gs.optimize_detail_unverified":"nicht überprüft","gs.optimize_detail_room_label":"Raumkennzeichnung","gs.optimize_detail_device":"Gerät","gs.optimize_detail_group":"Gruppenkennzeichen","gs.optimize_detail_unknown":"unbekannter Eigentümer","gs.optimize_detail_item":"{status}: {kind} {id}; alter Bereich {space}","gs.align_warn":"Absichtlich zwischen Rasterknoten platzierte Elemente werden sich bewegen. Nach der Operation ist nur eine Rückgängig-Funktion verfügbar, und zwar nur bis zur nächsten Planbearbeitung.","gs.align_run":"Optimieren","gs.align_done":"Pläne optimiert: {n} Elemente bewegt, {m} Datensätze beibehalten, {r} Verweise repariert","gs.optimize_undo":"Letzte Optimierung rückgängig machen","gs.optimize_undone":"Die letzte Optimierung wurde rückgängig gemacht","decor.furniture":"Möbel","decor.image":"Bild","decor.image_title":"Eigene Bilder","decor.image_upload":"Bild hochladen","decor.image_replace":"Bild ersetzen","decor.image_uploading":"Wird hochgeladen…","decor.image_asset":"Bilddatei","decor.image_pick_hint":"Ein Bild hochladen oder ein vorhandenes auswählen.","decor.image_place_hint":"Auf den Plan klicken, um das Bild zu platzieren.","decor.image_none":"Noch keine Bilder hochgeladen.","decor.image_unavailable":"Bild nicht verfügbar","decor.image_used":"In {n} Objekten verwendet","decor.image_upload_failed":"Bild konnte nicht hochgeladen werden: {err}","decor.image_error_capacity":"Der Speicher für benutzerdefinierte Bilder ist voll.","decor.image_in_use":"Vor dem Löschen alle platzierten Kopien entfernen.","decor.image_delete_title":"Bilddatei löschen?","decor.image_delete_message":"„{name}“ aus House Plan löschen? Dies kann nicht rückgängig gemacht werden.","furn.title":"Möbelbibliothek","furn.symbol":"Symbol","furn.group_furniture":"Möbel","furn.group_appliance":"Geräte","furn.group_sanitary":"Sanitär","furn.group_other":"Sonstiges","furn.width":"Breite","furn.depth":"Tiefe","furn.back_to_categories":"Alle Kategorien","furn.pick_hint":"Wählen Sie eine Kategorie und dann ein Symbol.","furn.place_hint":"Klicken Sie auf den Plan — das Element wird an der nächsten Wand platziert. Mit Shift wird es frei platziert.","furn.cat_air_conditioner":"Klimaanlagen","furn.cat_armchair":"Sessel","furn.cat_bathtub":"Badewannen","furn.cat_bed":"Betten","furn.cat_bidet":"Bidets","furn.cat_boiler":"Warmwasserbereiter","furn.cat_chair":"Stühle","furn.cat_coffee_table":"Couchtische","furn.cat_cooktop":"Kochfelder","furn.cat_dining_table":"Esstische","furn.cat_dishwasher":"Geschirrspüler","furn.cat_dryer":"Wäschetrockner","furn.cat_fireplace":"Kamine","furn.cat_fridge":"Kühlschränke","furn.cat_kitchen_cabinet":"Küchenschränke","furn.cat_kitchen_sink":"Küchenspülen","furn.cat_nightstand":"Schränke","furn.cat_plant":"Pflanzen","furn.cat_rug":"Teppiche","furn.cat_shelving":"Regale","furn.cat_shower":"Duschen","furn.cat_sink":"Waschbecken","furn.cat_sofa":"Sofas","furn.cat_stairs":"Treppen","furn.cat_toilet":"Toiletten","furn.cat_tv":"Fernseher","furn.cat_wardrobe":"Kleiderschränke","furn.cat_washer":"Waschmaschinen","furn.cat_work_table":"Schreibtische","furn.sym_sofa":"Zweisitzer-Sofa","furn.sym_sofa_three_seat":"Dreisitzer-Sofa","furn.sym_sofa_corner_right":"Ecksofa rechts","furn.sym_armchair":"Polstersessel","furn.sym_armchair_office":"Bürostuhl","furn.sym_coffee_table":"Rechteckiger Couchtisch","furn.sym_coffee_table_round":"Runder Couchtisch","furn.sym_coffee_table_oval":"Ovaler Couchtisch","furn.sym_coffee_table_rounded":"Abgerundeter Couchtisch","furn.sym_table_dining":"Rechteckiger Esstisch","furn.sym_table_round":"Rundtisch","furn.sym_table_dining_oval":"Ovaler Esstisch","furn.sym_table_dining_rounded":"Abgerundeter Esstisch","furn.sym_chair":"Stuhl","furn.sym_chair_bar":"Barhocker","furn.sym_desk":"Rechteckiger Schreibtisch","furn.sym_desk_corner":"Eckschreibtisch","furn.sym_bed_double":"Doppelbett","furn.sym_bed_single":"Einzelbett","furn.sym_nightstand":"Nachttisch","furn.sym_cabinet_tv":"TV-Schrank","furn.sym_cabinet_shoe":"Schuhschrank","furn.sym_cabinet_sink":"Waschtischunterschrank","furn.sym_wardrobe":"Kleiderschrank","furn.sym_bookshelf":"Bücherschrank","furn.sym_wall_unit":"Schrankwand","furn.sym_kitchen_floor":"Küchen-Unterschrank","furn.sym_kitchen_floor_corner":"Küchen-Eckunterschrank","furn.sym_kitchen_wall":"Küchen-Hängeschrank","furn.sym_kitchen_wall_corner":"Küchen-Eckhängeschrank","furn.sym_shelf_floor":"Standregal","furn.sym_shelf_wall":"Wandregal","furn.sym_fridge":"Kühlschrank","furn.sym_stove":"Vierflammiges Kochfeld","furn.sym_cooktop_two":"Zweiflammiges Kochfeld","furn.sym_dishwasher":"Geschirrspüler","furn.sym_washer":"Waschmaschine","furn.sym_dryer":"Wäschetrockner","furn.sym_tv":"Fernseher mit Standfuß","furn.sym_tv_wall":"Wandfernseher","furn.sym_ac":"Klimaanlage","furn.sym_water_heater":"Wassererhitzer","furn.sym_toilet":"Stand-WC","furn.sym_toilet_built_in":"Wand-WC","furn.sym_bathtub":"Rechteckige Badewanne","furn.sym_bathtub_corner":"Eckbadewanne","furn.sym_shower":"Dusche","furn.sym_sink":"Waschbecken","furn.sym_kitchen_sink":"Einzel-Küchenspüle","furn.sym_kitchen_sink_double":"Doppel-Küchenspüle","furn.sym_bidet":"Stand-Bidet","furn.sym_bidet_built_in":"Wand-Bidet","furn.sym_stairs":"Treppe","furn.sym_fireplace":"Kamin","furn.sym_plant":"Pflanze","furn.sym_rug":"Teppich","common.yes":"Ja","common.no":"Nein","vac.diag_source":"Quelle","vac.diag_platform":"Integration","vac.diag_status":"Status","vac.diag_position":"Position","vac.diag_rooms":"Räume","vac.diag_rooms_value":"{total} · {matched} Namen stimmen überein · {readiness}","vac.autocal_ready":"Auto-Kalibrierung verfügbar","vac.autocal_not_ready":"3 übereinstimmende Namen erforderlich","vac.diag_path":"Integrationspfad","vac.diag_map":"Karten-ID","vac.source_none":"nicht ausgewählt","vac.source_status_ok":"Bereit","vac.source_status_missing":"Fehlend","vac.source_status_disabled":"In Home Assistant deaktiviert","vac.source_status_unavailable":"Nicht verfügbar","vac.source_status_unverified":"Kann mit den aktuellen Berechtigungen nicht verifizieren","vac.source_status_unsupported":"Keine Positionsdaten","vac.source_status_none":"Keine Quelle","vac.source_banner_missing":"Die gespeicherte Quelle existiert nicht mehr. Sie wurde nicht automatisch ersetzt; wählen Sie eine andere Quelle oder stellen Sie sie in Home Assistant wieder her.","vac.source_banner_disabled":"Die gespeicherte Quelle ist in Home Assistant deaktiviert. Aktivieren Sie sie dort oder wählen Sie eine andere Quelle.","vac.source_banner_unverified":"Die aktuellen Home Assistant-Berechtigungen können diese gespeicherte Quelle nicht verifizieren. Sie bleibt angepinnt und wird nicht automatisch ersetzt.","vac.choose_source":"Quelle wählen","vac.source_auto":"Automatisch","vac.source_auto_hint":"Verwenden Sie eine kompatible Entität von diesem Gerät","vac.all_cameras":"Alle Kameras","vac.all_cameras_warn":"Eine Kamera liefert möglicherweise keine Roboter-Daten. Wählen Sie eine nur, wenn es Ihre Saugroboter-Karte ist.","vac.all_cameras_empty":"Keine anderen Kamera-Entitäten gefunden.","vac.platform_unknown":"unbekannte Integration","vac.cap_position":"Position","vac.cap_rooms_short":"Räume","vac.cap_path":"Pfad","vac.cap_map":"Karten-ID","vac.cap_none":"Keine Roboter-Daten erkannt","vac.xcme_hint":"Aktivieren Sie diese Xiaomi Cloud Map Extractor-Attribute:","vac.documentation":"Dokumentation","vac.residual_title":"Automatische Kalibrierung überprüfen","vac.residual_message":"Die zugeordneten Räume weichen um bis zu {error} voneinander ab. Diese ungefähre Kalibrierung anwenden, manuell verfeinern oder ohne Änderung der gespeicherten Einrichtung abbrechen.","vac.apply_proposal":"Anwenden","gs.backup_group":"Sichern und übertragen","gs.backup_hint":"Laden Sie ein tragbares JSON-Backup herunter oder sehen Sie eine Vorschau und importieren Sie ein Backup, das mit House Plan erstellt wurde.","backup.export_open":"Exportieren","backup.import_open":"Importieren","backup.export_title":"House Plan exportieren","backup.import_title":"House Plan importieren","backup.export_hint":"Wählen Sie, ob das Backup die gesamte House Plan-Konfiguration oder nur den aktuellen Bereich enthalten soll.","backup.full":"Vollständiges Backup","backup.current_space":"Aktueller Bereich","backup.current_space_title":"Aktueller Bereich: {title}","backup.no_current_space":"Kein aktueller Bereich","backup.plan_only":"Nur Plan","backup.plan_only_hint":"Räume, Wände, Öffnungen, Dekor und Raumbezeichnungspositionen ohne Geräte oder Home Assistant-Bindungen beibehalten.","backup.plan_only_preview":"Diese Datei enthält nur den Plan.","backup.privacy_warning":"Das Archiv enthält Namen, Home Assistant-Kennungen und genaue Koordinaten. Interne Pläne und Anhänge werden referenziert, nicht eingebettet; Laufzeitzustände und Staubsaugerspuren sind nicht enthalten.","backup.download":"JSON herunterladen","backup.export_done":"Backup heruntergeladen","backup.reading":"Überprüfe das Backup…","backup.revalidated":"Der Plan wurde nach dieser Vorschau geändert. Die Zusammenfassung wurde aktualisiert; überprüfen Sie sie und bestätigen Sie erneut.","backup.error.support_invalid_message":"Prüfen Sie die Supportnachricht und versuchen Sie es erneut.","backup.error.support_package_too_large":"Das anonymisierte Supportpaket überschreitet das Limit von 8 MiB.","backup.error.support_preview_expired":"Die Vorschau des Supportanhangs ist abgelaufen oder nicht mehr verfügbar.","backup.error.support_rate_limited":"Zu viele Supportberichte oder Vorschauen wurden angefordert. Versuchen Sie es später erneut.","backup.error.support_rejected":"Der Bericht hat die Prüfung des Supportdienstes nicht bestanden.","backup.error.support_unavailable":"Der private Supportdienst ist vorübergehend nicht verfügbar.","backup.error.unauthorized":"Sie haben keine Berechtigung, diesen Plan zu exportieren oder zu importieren.","backup.error.not_ready":"Der Hausplan ist noch nicht fertig. Versuchen Sie es in einem Moment erneut.","backup.error.too_large":"Das Backup überschreitet das 8-MiB-Limit.","backup.error.invalid_json":"Die ausgewählte Datei ist kein gültiges JSON.","backup.error.invalid_format":"Die ausgewählte Datei ist kein House Plan-Backup.","backup.error.invalid_image":"Das Bild ist beschädigt oder entspricht nicht seinem Format.","backup.error.unsupported_export_version":"Dieses Backup-Format wird von der installierten Version nicht unterstützt.","backup.error.unsupported_image":"Verwenden Sie ein unterstütztes PNG-, JPEG-, WebP- oder SVG-Bild.","backup.error.future_model":"Das Backup wurde mit einem neueren House-Plan-Datenmodell erstellt.","backup.error.invalid_config":"Das Backup enthält eine ungültige House-Plan-Konfiguration.","backup.error.wall_model_migration_blocked":"Das Backup-Wandmodell konnte nicht sicher aktualisiert werden. Optimieren Sie zuerst den Quellplan und exportieren Sie ihn dann erneut.","backup.error.invalid_layout":"Das Backup enthält ungültige Objektpositionen.","backup.error.invalid_content":"Das Backup enthält ungültige oder inkonsistente Inhaltsreferenzen.","backup.error.space_not_found":"Der ausgewählte Bereich existiert nicht mehr.","backup.error.capacity_exceeded":"Durch das Hinzufügen dieses Backups würden die Planlimits überschritten.","backup.error.preview_expired":"Die Vorschau ist abgelaufen. Wählen Sie die Backup-Datei erneut aus.","backup.error.preview_owner_mismatch":"Diese Vorschau gehört zu einem anderen Home-Assistant-Benutzer.","backup.error.conflict":"Der Plan hat sich nach der Vorschau geändert. Überprüfen Sie die aktualisierte Zusammenfassung.","backup.error.content_confirmation_required":"Bestätigen Sie, dass nicht verfügbare lokale Inhalte getrennt werden können.","backup.error.commit_failed":"Das Backup konnte nicht sicher angewendet werden. Der vorherige Plan wurde wiederhergestellt oder wartet auf die Wiederherstellung.","backup.error.missing_plan":"Eine referenzierte Plan-Datei ist nach der Vorschau verschwunden. Überprüfen Sie das Backup erneut.","backup.error.missing_content":"Ein referenziertes lokales Anhangselement ist nach der Vorschau verschwunden. Überprüfen Sie das Backup erneut.","backup.error.marker_control_missing":"Ein verknüpftes Planlicht fehlt im Backup.","backup.error.marker_control_not_light":"Ein verknüpftes Planziel ist nicht mehr als Lichtquelle markiert.","backup.error.marker_control_self":"Eine Lichtquelle kann sich nicht selbst steuern.","backup.error.marker_control_cycle":"Das Backup enthält eine kreisförmige Kette von Lichtsteuerungen.","backup.error.duplicate_marker_control":"Das Backup enthält eine doppelte Plan-Licht-Verknüpfung.","backup.error.no_backup":"Es gibt keinen Import- oder Optimierungssnapshot zur Wiederherstellung.","backup.error.in_use":"Das Element wird noch verwendet","backup.error.invalid_data":"Die Anfrage enthält ungültige Daten","backup.error.invalid_light_entity":"Das führende Licht muss eine light.*- oder switch.*-Entität sein","backup.error.invalid_marker_control":"Ungültige Marker-Steuerungsreferenz","backup.error.invalid_name":"Der Name ist ungültig","backup.error.invalid_partition_opening_host":"Die Öffnung muss ihren Trennwand-Träger behalten","backup.error.invalid_partition_opening_jamb_margin":"Die Öffnung lässt keinen physischen Pfosten am Wandende","backup.error.invalid_passage_fields":"Ein offener Durchgang kann keine Tür-Einstellungen tragen","backup.error.invalid_space_id":"Unbekannter Raumbereich","backup.error.invalid_toggle_entity":"Die Schalt-Entität muss light.* oder switch.* sein","backup.error.invalid_value_badge":"Ungültige Wert-Badge-Einstellungen","backup.error.invalid_value_badge_attribute":"Ungültiges Wert-Badge-Attribut","backup.error.invalid_value_badge_position":"Ungültige Wert-Badge-Position","backup.error.invalid_value_badge_source":"Ungültige Wert-Badge-Quelle","backup.error.invalid_vacuum_map_route":"Prüfen Sie die Zuordnung der Roboterkarten zu Räumen.","backup.error.invalid_value_source":"Ungültige Wertquelle","backup.error.invalid_value_source_attribute":"Ungültiges Wertquellen-Attribut","backup.error.io_error":"Eine Dateioperation auf dem Server ist fehlgeschlagen","backup.error.not_toggleable":"Dieses Gerät kann nicht geschaltet werden","backup.error.nothing_to_repair":"Nichts zu reparieren","backup.error.space_in_use":"Der Raumbereich wird noch referenziert","backup.error.value_badge_source_required":"Das Wert-Badge braucht eine Quelle","backup.error.wall_model_client_outdated":"Der Plan wurde anderswo aktualisiert — Seite neu laden","backup.same_source":"Erstellt auf dieser Home Assistant-Instanz","backup.foreign_source":"Erstellt auf einer anderen Home Assistant-Instanz","backup.created":"Erstellt: {value}","backup.versions":"Karte {card}; Integration {integration}; Datenmodell {model}","backup.count_spaces":"Bereiche: {n}","backup.count_rooms":"Räume: {n}","backup.count_walls":"Wände: {n}","backup.count_openings":"Öffnungen: {n}","backup.count_decor":"Dekorationsobjekte: {n}","backup.count_markers":"Geräte: {n}","backup.count_layout":"Positionen: {n}","backup.bindings":"Verknüpfungen — Geräte: {device}, Entitäten: {entity}, virtuell: {virtual}; Positionen ohne Bereich: {legacy}","backup.binding_status":"Zielstatus — aktiv: {active}, deaktiviert: {disabled}, fehlt: {missing}","backup.missing_areas":"Auf dem Ziel fehlende Bereiche: {areas}","backup.dropped_marker_links":"Planlicht-Verknüpfungen außerhalb dieses übertragenen Bereichs wurden ausgelassen: {n}.","backup.repaired_target_refs":"Durch den Import dieses Bereichs wiederhergestellte vorhandene Referenzen: {n}.","backup.preserved_unresolved_refs":"Referenzen, die nicht eindeutig wiederhergestellt werden konnten, wurden beibehalten: {n}.","backup.preserved_unresolved_hint":"Es wurden keine Daten geraten oder gelöscht. Führen Sie nach dem Import Optimierungspläne aus, um die verbleibenden Referenzen zu überprüfen.","backup.import_details":"Importieren von Referenzdetails","backup.import_detail.incoming_remapped":"Referenzen innerhalb der importierten Kopie aktualisiert: {n}","backup.import_detail.target_repaired":"Vorhandene Referenzen wiederhergestellt: {n}","backup.import_detail.preserved_unresolved":"Unaufgelöste Referenzen beibehalten: {n}","backup.import_detail.collisions":"Zielkonflikte sicher beibehalten: {n}","backup.import_detail.dropped_links":"Eingehende Links durch Übertragungsregeln ausgelassen: {n}","backup.import_detail.bounded_lineages":"Übermäßig verschachtelte Kennungen begrenzt belassen: {n}","backup.replace_warning":"Dies ersetzt die aktuelle Konfiguration und das Layout. Hochgeladene Dateien werden niemals gelöscht. Eine Rückgängig-Möglichkeit bleibt bis zur nächsten Planbearbeitung verfügbar.","backup.foreign_bookkeeping":"Instanzspezifische bekannte/neue Gerätebuchführung wird nicht importiert.","backup.final_name":"Name des neuen Bereichs","backup.target_settings":"Die globalen Einstellungen der Zielinstanz bleiben unverändert.","backup.duplicates":"Bindungen bereits vorhanden: {n}","backup.skip":"Doppelte Geräte überspringen","backup.virtual_copy":"Sichere statische virtuelle Kopien hinzufügen","backup.content":"Referenzierter Inhalt","backup.decor_images_summary":"Eigene Bilder: {objects} Objekte, {assets} Dateien; fehlende Dateien: {missing}.","backup.content_available":"lokal verfügbar","backup.content_external":"externer Link","backup.content_detach_required":"wird getrennt","backup.confirm_detach":"Ich verstehe, dass nicht verfügbare interne Pläne und Anhänge von der importierten Konfiguration getrennt werden.","backup.confirm_missing_images":"Ich verstehe, dass fehlende eigene Bilder als reparierbare Platzhalter erhalten bleiben und andere nicht verfügbare lokale Dateien getrennt werden.","backup.replace":"Ersetzen","backup.add":"Bereich hinzufügen","backup.space_done":"Bereich importiert: {rooms} Räume, {markers} Geräte, {refs} bestehende Referenzen wiederhergestellt","backup.full_done":"Backup wiederhergestellt: {spaces} Bereiche, {rooms} Räume, {markers} Geräte","backup.undo_import":"Letzten vollständigen Import rückgängig machen","backup.import_undone":"Vollständiger Import rückgängig gemacht","backdrop.large_title":"Großes Bild","backdrop.large_body":"Dieses Bild ist {w}×{h} ({fileMb} MB Datei) und benötigt etwa {decodedMb} MB Speicher zur Anzeige. Auf Tablets kann das die Seite zum Absturz bringen.","backdrop.unknown_body":"Die Bildabmessungen konnten nicht gelesen werden — die Datei ist möglicherweise beschädigt. Fortfahren kann die Seite auf Tablets zum Absturz bringen.","backdrop.reduced_dimensions":"Verkleinerte Kopie: {w}×{h} px.","backdrop.use_downscaled":"Verkleinerte Kopie hochladen","backdrop.reducing":"Wird verkleinert…","backdrop.keep_original":"Original behalten","backdrop.too_large_title":"Bild ist zu groß","backdrop.too_large_body":"Dieses Bild überschreitet die Anzeigegrenzen des Browsers ({w}×{h}, Limit {limit} px pro Seite). Bitte verkleinern Sie es in einem Desktop-Editor und laden Sie es erneut hoch.","backdrop.downscale_failed":"Die verkleinerte Kopie konnte nicht erstellt werden. Der aktuelle Plan wurde nicht geändert."};const n="781b6de4892612660b01762cd408049137fa0d00417a43ef5bbdfb1ef37dc9a5";export{e as dictionary,n as fingerprint};
diff --git a/custom_components/houseplan/frontend/houseplan-assets/editor-CxXW-QO8.js b/dist/houseplan-assets/editor-CHYZKnjE.js
similarity index 94%
rename from custom_components/houseplan/frontend/houseplan-assets/editor-CxXW-QO8.js
rename to dist/houseplan-assets/editor-CHYZKnjE.js
index 504db8f5..9018afbb 100644
--- a/custom_components/houseplan/frontend/houseplan-assets/editor-CxXW-QO8.js
+++ b/dist/houseplan-assets/editor-CHYZKnjE.js
@@ -1,4 +1,4 @@
-globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="bd7029808eb6094140d9fa8245f50816cb452430a353f4231d16e02c97078a06";import{g as e,l as o,t,dm as s,A as a,dn as i,dp as l,dq as n,E as r,c}from"./houseplan-card-BTXh6SvG.js";class h extends e{constructor(){super(...arguments),this._spaces=null,this._spacesLoading=!1,this._spacesAuthoritative=!1}setConfig(e){this._config=e}async _loadSpaces(){if(!this._spaces&&!this._spacesLoading&&this.hass){this._spacesLoading=!0;try{const e=await this.hass.callWS({type:"houseplan/config/get"});this._spaces=(e?.config?.spaces||[]).map(e=>({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`{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,m=p.trustedTypes,_=m?m.emptyScript:"",f=p.reactiveElementPolyfillSupport,g=(e,t)=>e,v={toAttribute(e,t){switch(t){case Boolean:e=e?_: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(g("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(g("finalized")))return;if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(g("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[g("elementProperties")]=new Map,w[g("finalized")]=new Map,f?.({ReactiveElement:w}),(p.reactiveElementVersions??=[]).push("2.1.2");const k=globalThis,x=e=>e,$=k.trustedTypes,S=$?$.createPolicy("lit-html",{createHTML:e=>e}):void 0,M="$lit$",C=`lit$${Math.random().toFixed(9).slice(2)}$`,T="?"+C,R=`<${T}>`,D=document,z=()=>D.createComment(""),A=e=>null===e||"object"!=typeof e&&"function"!=typeof e,P=Array.isArray,O="[ \t\n\f\r]",F=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,I=/-->/g,E=/>/g,H=RegExp(`>|${O}(?:([^\\s"'>=/]+)(${O}*=${O}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),N=/'/g,L=/"/g,B=/^(?:script|style|textarea|title)$/i,q=e=>(t,...i)=>({_$litType$:e,strings:t,values:i}),W=q(1),j=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(!P(e)||!e.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==S?S.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=$?$.emptyScript:"";for(let i=0;iP(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&&A(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){P(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(z()),this.O(z()),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=!A(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(z(),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=new WeakMap;let pe=0;class me extends he{constructor(){super(...arguments),this.title="",this.icon="",this.wide=!1,this.alert=!1,this.describedBy="",this.dismissOnScrim=!1,this.hass=null,this._opener=null,this._focusRoot=null,this._useHaDialog=!1,this._closing=!1,this._overlays=[],this._titleId="hp-dialog-title-"+ ++pe,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 this._useHaDialog&&!this.alert}connectedCallback(){super.connectedCallback(),this._opener=this._deepActiveElement();const e=this.getRootNode();this._focusRoot=e;const t=ue.get(e)||{dialogs:new Set,opener:this._opener};t.dialogs.add(this),ue.set(e,t),this._useHaDialog=!!customElements.get("ha-dialog"),this.addEventListener("keydown",this._onKeyDown,!0)}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?ue.get(t):void 0;n?.dialogs.delete(this),super.disconnectedCallback(),t&&n&&requestAnimationFrame(()=>{const e=ue.get(t);if(!e)return;if(!e.dialogs.size)return e.opener?.isConnected&&e.opener.focus({preventScroll:!0}),void ue.delete(t);const n=i?.closest("hp-dialog");i?.isConnected&&n&&e.dialogs.has(n)&&i.focus({preventScroll:!0})})}firstUpdated(e){if(super.firstUpdated(e),!this._usesHaDialog()){const e=this.renderRoot.querySelector("dialog");e&&!e.open&&e.showModal()}queueMicrotask(()=>this._focusInitial())}_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=W`
+globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="781b6de4892612660b01762cd408049137fa0d00417a43ef5bbdfb1ef37dc9a5";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,m=p.trustedTypes,_=m?m.emptyScript:"",f=p.reactiveElementPolyfillSupport,g=(e,t)=>e,v={toAttribute(e,t){switch(t){case Boolean:e=e?_: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(g("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(g("finalized")))return;if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(g("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[g("elementProperties")]=new Map,w[g("finalized")]=new Map,f?.({ReactiveElement:w}),(p.reactiveElementVersions??=[]).push("2.1.2");const k=globalThis,x=e=>e,$=k.trustedTypes,S=$?$.createPolicy("lit-html",{createHTML:e=>e}):void 0,M="$lit$",C=`lit$${Math.random().toFixed(9).slice(2)}$`,T="?"+C,R=`<${T}>`,D=document,z=()=>D.createComment(""),A=e=>null===e||"object"!=typeof e&&"function"!=typeof e,P=Array.isArray,O="[ \t\n\f\r]",F=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,I=/-->/g,E=/>/g,H=RegExp(`>|${O}(?:([^\\s"'>=/]+)(${O}*=${O}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),N=/'/g,L=/"/g,B=/^(?:script|style|textarea|title)$/i,q=e=>(t,...i)=>({_$litType$:e,strings:t,values:i}),W=q(1),j=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(!P(e)||!e.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==S?S.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=$?$.emptyScript:"";for(let i=0;iP(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&&A(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){P(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(z()),this.O(z()),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=!A(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(z(),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=new WeakMap;let pe=0;class me extends he{constructor(){super(...arguments),this.title="",this.icon="",this.wide=!1,this.alert=!1,this.describedBy="",this.dismissOnScrim=!1,this.hass=null,this._opener=null,this._focusRoot=null,this._useHaDialog=!1,this._closing=!1,this._overlays=[],this._titleId="hp-dialog-title-"+ ++pe,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 this._useHaDialog&&!this.alert}connectedCallback(){super.connectedCallback(),this._opener=this._deepActiveElement();const e=this.getRootNode();this._focusRoot=e;const t=ue.get(e)||{dialogs:new Set,opener:this._opener};t.dialogs.add(this),ue.set(e,t),this._useHaDialog=!!customElements.get("ha-dialog"),this.addEventListener("keydown",this._onKeyDown,!0)}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?ue.get(t):void 0;n?.dialogs.delete(this),super.disconnectedCallback(),t&&n&&requestAnimationFrame(()=>{const e=ue.get(t);if(!e)return;if(!e.dialogs.size)return e.opener?.isConnected&&e.opener.focus({preventScroll:!0}),void ue.delete(t);const n=i?.closest("hp-dialog");i?.isConnected&&n&&e.dialogs.has(n)&&i.focus({preventScroll:!0})})}firstUpdated(e){if(super.firstUpdated(e),!this._usesHaDialog()){const e=this.renderRoot.querySelector("dialog");e&&!e.open&&e.showModal()}queueMicrotask(()=>this._focusInitial())}_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=W`
${this.icon?W``:V}
${this.title}`;return this._usesHaDialog()?this.describedBy?W`{e.isConnected&&e.requestUpdate()}),uu.has(e)?"warm":"cold"):(pu.delete(e)&&(e.inert=!1,e.removeAttribute("aria-busy")),i&&(e.setAttribute("lang","fallback"===n?"en":i),uu.add(e)),"ready")}function _u(){return W``}const fu=[{code:"en",nativeLabel:"English",dictionary:du},{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":"Проверьте сеть и нажмите ещё раз.","color_picker.title":"Выбор цвета","color_picker.hue":"Оттенок","color_picker.saturation":"Насыщенность","color_picker.value":"Яркость","color_picker.hex":"Цвет HEX","color_picker.invalid_hex":"Введите цвет HEX из 3 или 6 цифр","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.draft_segment":"Добавление сегмента черновика комнаты","history.draft_merge":"Соединение незавершённых контуров комнаты","history.draft_segment_delete":"Удаление сегмента черновика комнаты","history.column_add":"Добавление колонны","history.physical_edit":"Изменение физического объекта","history.physical_delete":"Удаление физического объекта","history.physical_move":"Перемещение физического объекта","history.contour_to_partitions":"Преобразование контура в замкнутые стены","history.wall_chain_finish":"Завершение цепочки стен","history.wall_face_batch":"Создание комнат из стен","toast.column_duplicate":"Колонна с тем же центром и внешним размером уже существует","confirm.delete_draft_title":"Удалить незавершённый контур?","confirm.delete_draft_body":"Весь незавершённый контур комнаты будет удалён. При отмене ничего не изменится.","confirm.delete_draft_segment_title":"Удалить сегмент контура?","confirm.delete_draft_segment_body":"Этот сегмент черновика будет удалён. Оставшийся контур может разделиться на два.","physical.partition_properties":"Свойства перегородки","physical.column_properties":"Свойства колонны","physical.draft_properties":"Свойства сегмента черновика","physical.shape":"Форма","physical.square":"Квадрат","physical.circle":"Круг","physical.diameter":"Диаметр","physical.side":"Сторона","physical.rotation":"Угол поворота","physical.length":"Длина","physical.allowed_range":"Допустимо: {min}–{max} {unit}","physical.delete_segment":"Удалить сегмент","physical.delete_draft":"Удалить весь контур","physical.column_size_title":"Внешняя сторона квадратной колонны, создаваемой кликом (1–150 см).","card.title":"План дома","count.devices":"{n} устр.","empty.no_spaces":"Пространств пока нет.","empty.add_first":"Добавьте первое пространство и загрузите план этажа.","empty.install":"Установите интеграцию House Plan и добавьте запись в «Устройства и службы».","btn.add_space":"Добавить пространство","btn.cancel":"Отмена","btn.save":"Сохранить","btn.close":"Закрыть","btn.delete":"Удалить","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.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":"Пространство, все его комнаты и вся разметка плана будут удалены.","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_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":"Общие настройки","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":"Общие настройки сохранены","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","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_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":"Не удалось загрузить языковой пакет. До перезагрузки страницы используется английский.","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_removed_drafts":"Схлопнувшиеся на сетке некорректные контуры удалены: {n}.","gs.optimize_redundant_drafts":"Сохранённые цепочки стен, полностью скрытые стенами комнат, удалены: {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.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_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.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-Cm5MlI_Y.js"):await import(new URL("./de-Cm5MlI_Y.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-CDWnrdfn.js"):await import(new URL("./fr-CDWnrdfn.js?retry",import.meta.url).href);return{dictionary:t.dictionary,fingerprint:t.fingerprint}}}],gu=du,vu=new Set;const yu=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)}}(fu,"bd7029808eb6094140d9fa8245f50816cb452430a353f4231d16e02c97078a06",console.warn,function(e){for(const t of vu)t(e)});function bu(e){const t=xu(e)?.code??"en";return yu.dictionary(t)??gu}function wu(e){return"string"==typeof e?e.trim().replaceAll("_","-").toLowerCase():""}const ku=new Map(fu.map(e=>[wu(e.code),e]));function xu(e){return ku.get(wu(e))}function $u(e,t){const i=[{value:"",label:e},...fu.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:xu(n)?.nativeLabel??n}),i}function Su(e,t){return function(e,t,i,n){const r=new Map(i.map(e=>[wu(e),e])),o=r.get(wu(e));if(o)return o;const s=wu(t),a=r.get(s);return a||(r.get(s.split("-")[0]||"")??n)}(t,e?.locale?.language||e?.language,fu.map(({code:e})=>e),"en")}function Mu(e,t,i){return Hi(bu(e)[t]??gu[t]??t,i)}function Cu(e,t){const i=bu(e)[t]??gu[t];return"string"==typeof i&&i.trim().length>0}function Tu(e){const t=e.length/2,i=e.face.cm>0?e.face.cm/e.cellCm*e.gridPitch/2:ya(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(ya(16,e.cellCm),i+ya(8,e.cellCm),n+ya(8,e.cellCm)),hitHalf:Math.max(ya(20,e.cellCm),i+ya(10,e.cellCm),n+ya(12,e.cellCm))}}function Ru(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 Du(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}=Tu(e),r=va(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)Du(c,-i,0,i,-o,o,-90,0),Du(c,i,-i,0,-o,o,0,90),Ru(c,-i-a,-i-a),Ru(c,i+a,a);else if("gate"===e.type){const t=10*e.face.side;Du(c,-i,0,i,-o,o,0,t),Du(c,i,-i,0,-o,o,-t,0)}else Du(c,-i,0,e.length,-o,o,-90,0),Ru(c,-i-a,-e.length-a),Ru(c,i+a,a);const[h,d]=zu(e),u={...l};Ru(u,c.minX+h,c.minY+d),Ru(u,c.maxX+h,c.maxY+d);const p=e.flipH?-1:1,m="gate"===e.type?1:e.flipV?-1:1,_=e.angle*Math.PI/180,f=Math.cos(_),g=Math.sin(_),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*m;Ru(v,t[0]+n*f-r*g,t[1]+n*g+r*f)}return v}function Pu(e){if("passage"===e.type)return j``;const t=Math.max(0,Math.min(1,e.amount)),{half:i,jambHalf:n}=Tu(e),r=va(e.cellCm),o=1.75*r,s=e.flipH?-1:1,a=e.flipV?-1:1,l="gate"===e.type?1:a,[c,h]=zu(e);let d;if("window"===e.type){const o=Math.PI/2*i,s=e.face.cm>0?j`{e.isConnected&&e.requestUpdate()}),uu.has(e)?"warm":"cold"):(pu.delete(e)&&(e.inert=!1,e.removeAttribute("aria-busy")),i&&(e.setAttribute("lang","fallback"===n?"en":i),uu.add(e)),"ready")}function _u(){return W``}const fu=[{code:"en",nativeLabel:"English",dictionary:du},{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":"Проверьте сеть и нажмите ещё раз.","color_picker.title":"Выбор цвета","color_picker.hue":"Оттенок","color_picker.saturation":"Насыщенность","color_picker.value":"Яркость","color_picker.hex":"Цвет HEX","color_picker.invalid_hex":"Введите цвет HEX из 3 или 6 цифр","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.draft_segment":"Добавление сегмента черновика комнаты","history.draft_merge":"Соединение незавершённых контуров комнаты","history.draft_segment_delete":"Удаление сегмента черновика комнаты","history.column_add":"Добавление колонны","history.physical_edit":"Изменение физического объекта","history.physical_delete":"Удаление физического объекта","history.physical_move":"Перемещение физического объекта","history.contour_to_partitions":"Преобразование контура в замкнутые стены","history.wall_chain_finish":"Завершение цепочки стен","history.wall_face_batch":"Создание комнат из стен","toast.column_duplicate":"Колонна с тем же центром и внешним размером уже существует","confirm.delete_draft_title":"Удалить незавершённый контур?","confirm.delete_draft_body":"Весь незавершённый контур комнаты будет удалён. При отмене ничего не изменится.","confirm.delete_draft_segment_title":"Удалить сегмент контура?","confirm.delete_draft_segment_body":"Этот сегмент черновика будет удалён. Оставшийся контур может разделиться на два.","physical.partition_properties":"Свойства перегородки","physical.column_properties":"Свойства колонны","physical.draft_properties":"Свойства сегмента черновика","physical.shape":"Форма","physical.square":"Квадрат","physical.circle":"Круг","physical.diameter":"Диаметр","physical.side":"Сторона","physical.rotation":"Угол поворота","physical.length":"Длина","physical.allowed_range":"Допустимо: {min}–{max} {unit}","physical.delete_segment":"Удалить сегмент","physical.delete_draft":"Удалить весь контур","physical.column_size_title":"Внешняя сторона квадратной колонны, создаваемой кликом (1–150 см).","card.title":"План дома","count.devices":"{n} устр.","empty.no_spaces":"Пространств пока нет.","empty.add_first":"Добавьте первое пространство и загрузите план этажа.","empty.install":"Установите интеграцию House Plan и добавьте запись в «Устройства и службы».","btn.add_space":"Добавить пространство","btn.cancel":"Отмена","btn.save":"Сохранить","btn.close":"Закрыть","btn.delete":"Удалить","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.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_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":"Общие настройки","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":"Общие настройки сохранены","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","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_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":"Не удалось загрузить языковой пакет. До перезагрузки страницы используется английский.","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_removed_drafts":"Схлопнувшиеся на сетке некорректные контуры удалены: {n}.","gs.optimize_redundant_drafts":"Сохранённые цепочки стен, полностью скрытые стенами комнат, удалены: {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.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.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-DZwnjt2u.js"):await import(new URL("./de-DZwnjt2u.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-C7WePbhg.js"):await import(new URL("./fr-C7WePbhg.js?retry",import.meta.url).href);return{dictionary:t.dictionary,fingerprint:t.fingerprint}}}],gu=du,vu=new Set;const yu=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)}}(fu,"781b6de4892612660b01762cd408049137fa0d00417a43ef5bbdfb1ef37dc9a5",console.warn,function(e){for(const t of vu)t(e)});function bu(e){const t=xu(e)?.code??"en";return yu.dictionary(t)??gu}function wu(e){return"string"==typeof e?e.trim().replaceAll("_","-").toLowerCase():""}const ku=new Map(fu.map(e=>[wu(e.code),e]));function xu(e){return ku.get(wu(e))}function $u(e,t){const i=[{value:"",label:e},...fu.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:xu(n)?.nativeLabel??n}),i}function Su(e,t){return function(e,t,i,n){const r=new Map(i.map(e=>[wu(e),e])),o=r.get(wu(e));if(o)return o;const s=wu(t),a=r.get(s);return a||(r.get(s.split("-")[0]||"")??n)}(t,e?.locale?.language||e?.language,fu.map(({code:e})=>e),"en")}function Mu(e,t,i){return Hi(bu(e)[t]??gu[t]??t,i)}function Cu(e,t){const i=bu(e)[t]??gu[t];return"string"==typeof i&&i.trim().length>0}function Tu(e){const t=e.length/2,i=e.face.cm>0?e.face.cm/e.cellCm*e.gridPitch/2:ya(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(ya(16,e.cellCm),i+ya(8,e.cellCm),n+ya(8,e.cellCm)),hitHalf:Math.max(ya(20,e.cellCm),i+ya(10,e.cellCm),n+ya(12,e.cellCm))}}function Ru(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 Du(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}=Tu(e),r=va(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)Du(c,-i,0,i,-o,o,-90,0),Du(c,i,-i,0,-o,o,0,90),Ru(c,-i-a,-i-a),Ru(c,i+a,a);else if("gate"===e.type){const t=10*e.face.side;Du(c,-i,0,i,-o,o,0,t),Du(c,i,-i,0,-o,o,-t,0)}else Du(c,-i,0,e.length,-o,o,-90,0),Ru(c,-i-a,-e.length-a),Ru(c,i+a,a);const[h,d]=zu(e),u={...l};Ru(u,c.minX+h,c.minY+d),Ru(u,c.maxX+h,c.maxY+d);const p=e.flipH?-1:1,m="gate"===e.type?1:e.flipV?-1:1,_=e.angle*Math.PI/180,f=Math.cos(_),g=Math.sin(_),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*m;Ru(v,t[0]+n*f-r*g,t[1]+n*g+r*f)}return v}function Pu(e){if("passage"===e.type)return j``;const t=Math.max(0,Math.min(1,e.amount)),{half:i,jambHalf:n}=Tu(e),r=va(e.cellCm),o=1.75*r,s=e.flipH?-1:1,a=e.flipV?-1:1,l="gate"===e.type?1:a,[c,h]=zu(e);let d;if("window"===e.type){const o=Math.PI/2*i,s=e.face.cm>0?j``:j``;d=j`
performance.now(),requestFrame:e=>requestAnimationFrame(e),cancelFrame:e=>cancelAnimationFrame(e)},O_=e=>Math.max(0,Math.min(1,e)),F_=(e,t,i)=>e+(t-e)*i,I_=(e,t,i)=>{const n=1-e;return 3*n*n*e*t+3*n*e*e*i+e*e*e},E_=e=>{const t=O_(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,I_(r,.2,.2)0&&e.w>0?t/e.w:1,viewBox:{...e}}}function N_(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 L_(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 B_(e,t,i){const n=L_(e),r=L_(t);if(!n||!r)return i<.5?e:t;const o=O_(i);return`rgba(${Math.round(F_(n[0],r[0],o))}, ${Math.round(F_(n[1],r[1],o))}, ${Math.round(F_(n[2],r[2],o))}, ${F_(n[3],r[3],o).toFixed(3)})`}class q_{constructor(e,t=P_){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=O_((e-t.startedAt)/t.duration);t.presented=i>=1?t.to:function(e,t,i){const n=E_(i),r=F_(e.stageWidth,t.stageWidth,n),o=F_(e.stageHeight,t.stageHeight,n),s=Math.max(1e-9,e.viewport.pixelsPerUnit),a=Math.max(1e-9,t.viewport.pixelsPerUnit),l={centerX:F_(e.viewport.centerX,t.viewport.centerX,n),centerY:F_(e.viewport.centerY,t.viewport.centerY,n),pixelsPerUnit:Math.exp(F_(Math.log(s),Math.log(a),n))};return{presentedMode:n<.5?e.presentedMode:t.presentedMode,editorChromeHeight:F_(e.editorChromeHeight,t.editorChromeHeight,n),stageWidth:r,stageHeight:o,viewport:{...l,viewBox:N_(l,r,o)},stageColor:B_(e.stageColor,t.stageColor,n),paperColor:B_(e.paperColor,t.paperColor,n),sceneBrightness:F_(e.sceneBrightness,t.sceneBrightness,n),architectureOpacity:F_(e.architectureOpacity,t.architectureOpacity,n),backdropOpacity:F_(e.backdropOpacity,t.backdropOpacity,n),viewWeight:F_(e.viewWeight,t.viewWeight,n),editorWeight:F_(e.editorWeight,t.editorWeight,n),toolbarContentOpacity:F_(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 W_={now:()=>"undefined"!=typeof performance?performance.now():Date.now(),requestFrame:e=>"function"==typeof requestAnimationFrame?requestAnimationFrame(e):null,cancelFrame:e=>{"function"==typeof cancelAnimationFrame&&cancelAnimationFrame(e)}},j_=e=>Number.isFinite(e);function U_(e){return!!e&&j_(e.zoom)&&e.zoom>0&&j_(e.viewBox.x)&&j_(e.viewBox.y)&&j_(e.viewBox.w)&&e.viewBox.w>0&&j_(e.viewBox.h)&&e.viewBox.h>0}function V_(e){return{zoom:e.zoom,viewBox:{...e.viewBox}}}function G_(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 K_=(e,t,i)=>e+(t-e)*i,Y_=(e,t,i)=>Math.exp(K_(Math.log(e),Math.log(t),i));class X_{constructor(e,t=W_){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=V_(e),s=V_(t),a=n>0&&U_(o)&&U_(s),l=this._clock.now(),c={token:r,phase:a?"running":"settling",from:o,to:s,presented:V_(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?V_(t.to):function(e,t,i){if(!U_(e))return V_(t);if(!U_(t))return V_(e);const n=E_(i);if(n<=0)return V_(e);if(n>=1)return V_(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=Y_(e.viewBox.w,t.viewBox.w,n),c=Y_(e.viewBox.h,t.viewBox.h,n),h=K_(r,s,n),d=K_(o,a,n);return{zoom:Y_(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=V_(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=V_(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=V_(t.to),this._hooks.settled(t),this._state?.token===e&&(this._state=null))}}function Z_(e,t){return`${e("editor.load_failed")} ${e(t.terminal?"editor.refresh_advice":"editor.retry_advice")}`}class J_ extends Error{}class Q_{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 J_(`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 J_&&(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 ef="houseplan_card_labs_v1",tf=Object.freeze([Object.freeze({id:"iso",issue:89,since:"1.62.0",expires:"1.65.0",summary:"Volumetric plan renderer"})]);function nf(e){const t=/^(\d+)\.(\d+)\.(\d+)(?:-[0-9A-Za-z.-]+)?$/.exec(String(e||"").trim());if(!t)return null;const i=t.slice(1).map(Number);return i.every(e=>Number.isSafeInteger(e))?i:null}function rf(e,t){for(let i=0;i<3;i++)if(e[i]!==t[i])return e[i]e.split(",")).map(e=>e.trim()).filter(Boolean)}function hf(e,t,i,n=tf){const r=function(e,t=tf){const i=nf(e),n=new Map;if(!i||!sf(t))return n;for(const e of t){const t=nf(e.since),r=nf(e.expires);rf(i,t)>=0&&rf(i,r)<0&&n.set(e.id,e)}return n}(i,n),o=new Set(sf(n)?n.map(e=>e.id):[]),s=new Set(function(e){if(!e)return[];try{const t=JSON.parse(e);return Array.isArray(t)?t.filter(e=>"string"==typeof e):[]}catch{return[]}}(t).filter(e=>r.has(e)));let a=!1;const l=e=>{if("off"===e)return s.clear(),void(a=!0);const t=e.startsWith("-"),i=t?e.slice(1):e;o.has(i)&&(a=!0,t||!r.has(i)?s.delete(i):s.add(i))};for(const t of cf(new URLSearchParams(String(e.search||"").replace(/^\?/,""))))l(t);for(const t of cf(af(e.hash)))l(t);const c=Object.freeze([...s].sort());return{active:c,space:lf(e.hash),persist:a?JSON.stringify(c):void 0,knownUrlOperation:a}}let df={active:Object.freeze([]),space:""},uf="",pf=!1,mf="";const _f=new Set;function ff(){if("undefined"==typeof window)return df;const e=hf(window.location,function(){try{return window.localStorage.getItem(ef)}catch{return null}}(),uf);void 0!==e.persist&&function(e){try{window.localStorage.setItem(ef,e)}catch{}}(e.persist),df={active:e.active,space:e.space},window.__hpLabs=e.active;for(const e of _f)e(df);return df}function gf(){ff()}function vf(e){if(uf=e,"undefined"==typeof window)return df;if(!pf){pf=!0,window.__hpLabsListenerCleanup?.(),window.addEventListener("hashchange",gf),window.addEventListener("popstate",gf);const e=()=>{window.removeEventListener("hashchange",gf),window.removeEventListener("popstate",gf),window.__hpLabsListenerCleanup===e&&delete window.__hpLabsListenerCleanup};window.__hpLabsListenerCleanup=e}return ff()}const yf=Object.freeze({rotDeg:0,tiltDeg:20,xyScale:1,zScale:1,origin:Object.freeze([500,500])});function bf(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 wf(e,t,i=yf){if(!(bf(i)&&Number.isFinite(e[0])&&Number.isFinite(e[1])&&Number.isFinite(t)))throw new Error("invalid isometric projection input");const n=i.rotDeg*Math.PI/180,r=i.tiltDeg*Math.PI/180,o=e[0]-i.origin[0],s=e[1]-i.origin[1],a=(o*Math.cos(n)-s*Math.sin(n))*i.xyScale,l=(o*Math.sin(n)+s*Math.cos(n))*i.xyScale;return[i.origin[0]+a,i.origin[1]+l*Math.cos(r)-t*i.zScale*Math.sin(r)]}function kf(e,t=yf){if(!bf(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 xf(e=yf){return`matrix(${function(e=yf){if(!bf(e))throw new Error("invalid isometric camera");const t=e.rotDeg*Math.PI/180,i=e.tiltDeg*Math.PI/180,n=e.xyScale*Math.cos(t),r=-e.xyScale*Math.sin(t),o=e.xyScale*Math.sin(t)*Math.cos(i),s=e.xyScale*Math.cos(t)*Math.cos(i);return[n,o,r,s,e.origin[0]-n*e.origin[0]-r*e.origin[1],e.origin[1]-o*e.origin[0]-s*e.origin[1]]}(e).map(e=>Number(e.toFixed(12))).join(" ")})`}function $f(e,t=yf){const{rect:i,wallHeight:n}=e,r=e.openingHeight??n,o=e.floorDepth??0;if(!(i.w>=0)||!(i.h>=0)||!Number.isFinite(n)||!Number.isFinite(r)||!Number.isFinite(o)||n<0||r<0||o<0)throw new Error("invalid isometric frame");const s=[[i.x,i.y],[i.x+i.w,i.y],[i.x+i.w,i.y+i.h],[i.x,i.y+i.h]],a=Math.max(n,r),l=s.flatMap(e=>[wf(e,-o,t),wf(e,a,t)]),c=l.map(e=>e[0]),h=l.map(e=>e[1]),d=Math.min(...c),u=Math.min(...h);return{x:d,y:u,w:Math.max(...c)-d,h:Math.max(...h)-u}}const Sf=e=>`${Number(e[0].toFixed(4))} ${Number(e[1].toFixed(4))}`;function Mf(e){let t=0;for(let i=0;iArray.isArray(e)&&Number.isFinite(e[0])&&Number.isFinite(e[1])).map(e=>[Number(e[0]),Number(e[1])]),i=t[t.length-1];return t.length>1&&t[0][0]===i[0]&&t[0][1]===i[1]&&t.pop(),t}(e);if(i.length<3)return[];const n=!t;return Mf(i)>0===n?i:[...i].reverse()}function Tf(e,t,i){return e.length?`M ${e.map(e=>Sf(wf(e,i,t))).join(" L ")} Z`:""}function Rf(e,t,i){const n=t[1]-e[1],r=-(t[0]-e[0]),o=i.rotDeg*Math.PI/180;return n*Math.sin(o)+r*Math.cos(o)}function Df(e,t,i=yf){if(!Number.isFinite(t)||t<0)throw new Error("invalid floor edge height");const n=(e||[]).map(e=>(e||[]).map((e,t)=>function(e,t){const i=Cf(e,t);if(!i.length)return i;let n=0;for(let e=1;e0)).filter(e=>e.length>=3&&Math.abs(Mf(e))>=1e-9)).filter(e=>e.length&&Mf(e[0])>0);n.sort((e,t)=>{const i=e[0][0],n=t[0][0];return i[0]-n[0]||i[1]-n[1]||Math.abs(Mf(t[0]))-Math.abs(Mf(e[0]))});const r=[],o=[];let s=0;for(let e=0;ee.depth-t.depth||e.component-t.component||e.edge-t.edge),{footprintPath:r.join(" "),sides:o,componentCount:n.length,edgeCount:s}}function zf(e,t){return e^=Math.round(64*(Number.isFinite(t)?t:0)),Math.imul(e,16777619)>>>0}const Af=e=>e.every(Number.isFinite);function Pf(e,t,i,n){const r=e[0]*i,o=e[1]*n,s=t*Math.PI/180;return[r*Math.cos(s)-o*Math.sin(s),r*Math.sin(s)+o*Math.cos(s)]}function Of(e,t,i,n,r,o,s){const a=e.flipH?-1:1,l="gate"===e.type?1:e.flipV?-1:1,c=(e.type,e.flipV,e.angle,e.face,{ox:0,oy:0}),h=function(e,t){return[e[0]+t[0],e[1]+t[1]]}([e.x+c.ox,e.y+c.oy],Pf(i,e.angle,a,l));return{leaf:t,hinge:h,closedVector:Pf(n,e.angle,a,l),quarterVector:Pf([-n[1],n[0]],e.angle,a,l),turnDeg:r,bottom:o,top:s}}const Ff=e=>`${Number(e[0].toFixed(4))} ${Number(e[1].toFixed(4))}`;function If(e,t,i=yf){const n=Math.max(0,Math.min(1,Number.isFinite(t)?t:0));return e.leaves.map(t=>{const r=function(e,t){const i=e.turnDeg*t*Math.PI/180;return[e.hinge[0]+e.closedVector[0]*Math.cos(i)+e.quarterVector[0]*Math.sin(i),e.hinge[1]+e.closedVector[1]*Math.cos(i)+e.quarterVector[1]*Math.sin(i)]}(t,n),o=wf(t.hinge,t.bottom,i),s=wf(r,t.bottom,i),a=wf(r,t.top,i),l=wf(t.hinge,t.top,i);return{id:e.id,sourceIndex:e.sourceIndex,type:e.type,leaf:t.leaf,d:`M ${Ff(o)} L ${Ff(s)} L ${Ff(a)} L ${Ff(l)} Z`,shadowD:`M ${Ff(wf(t.hinge,0,i))} L ${Ff(wf(r,0,i))}`,depth:Math.max(o[1],s[1])}})}const Ef={window:120,door:90,passage:90,gate:300};function Hf(e){return Ef[e]}function Nf(e,t){return{type:e,lengthCm:Hf(e),flipH:!1,flipV:!1,revision:t}}function Lf(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 Bf(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 qf(e){const t=new Map;return e.forEach((e,i)=>{if(!e.kind||e.open)return;const n=Bf(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 Wf(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 jf(e){const t=qf(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=Bf(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,m=1e-9;if(!(p<=m||p>=h-m)&&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(Wf),n=t.filter(t=>!t.target.partitionHost||e.renderedLength+2*t.target.physicalHalfWidth<=t.length+1e-9).sort(Wf);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,m=Math.min(Math.max(0,e.renderedLength)/2+p,l/2);let _=r.along;const f=Math.max(e.gridStep,1e-9),g=l/2;_=Math.abs(_-g)<=f/2?g:Math.round(_/f)*f,_=Math.max(m,Math.min(l-m,_));const v=a.a[0]+d*_,y=a.a[1]+u*_,b=Math.max(0,e.renderedLength)/2,w=_-b,k=_+b,x=Math.max(0,w),$=Math.max(0,l-k),S=[a.a[0]+d*(w-x/2),a.a[1]+u*(w-x/2)],M=[a.a[0]+d*(k+$/2),a.a[1]+u*(k+$/2)];let C=180*Math.atan2(h,c)/Math.PI;C>=90?C-=180:C<-90&&(C+=180);const T=Math.abs(_-g)<=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:C,renderedLength:e.renderedLength,target:a,...a.partitionHost?{host:{...a.partitionHost,t:l>0?_/l:0}}:{},measure:{labels:[{distance:x,midpoint:S},{distance:$,midpoint:M}],guide:T?{x:v,y:y,angle:C}:null}},jambBlockedTarget:null}}function Uf(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 Vf(e){return!(!e.canEdit||e.kiosk||e.fixedFloor)&&("view"!==e.mode&&("mouse"===e.pointerType&&e.spaceCount>1))}let Gf=0;const Kf="1.71.0-beta.2",Yf="bd7029808eb6094140d9fa8245f50816cb452430a353f4231d16e02c97078a06",Xf=1500,Zf=(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}},Jf=(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)}},Qf=new Map;let eg=0;const tg=e=>`${window.innerWidth}x${window.innerHeight}|${location.pathname}|${JSON.stringify(e??{})}`;let ig=1e4;const ng="houseplan_card_layout_v1",rg="houseplan_card_cfg_v1",og="houseplan_card_zoom_v1",sg="houseplan_card_nav_v1",ag="houseplan_card_kiosk_v1",lg="houseplan_card_view_v1",cg="hp-dialog, hp-help, hp-color-opacity, hp-device-preview",hg=1e3,dg=(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}},ug=new Set(["select","draw","column","merge","split","resize","opening","wallthick","delroom"]),pg=(e,t,i)=>{const n=new Event(t,{bubbles:!0,composed:!0});n.detail=i??{},e.dispatchEvent(n)},mg=e=>{history.pushState(null,"",e),pg(window,"location-changed",{replace:!1})},_g=(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},fg=e=>{try{e.target?.setPointerCapture?.(e.pointerId)}catch{}},gg=["edges","corners"];class vg extends he{constructor(){super(...arguments),this._editorRuntime=null,this._onboardingRuntime=null,this._editorRuntimeLoadingVisible=!1,this._backdropGuard=null,this._editorModeRequest=0,this._warmModeRequest=0,this._editorRuntimeLoader=new Q_({expectedFingerprint:Yf,load:async e=>{const t=0===e?await import("./houseplan-editor-runtime-CmI5Go3m.js"):await import((()=>{const e=new URL("./houseplan-editor-runtime-CmI5Go3m.js",import.meta.url);return e.searchParams.set("hp_retry",`${Kf}-${++Gf}`),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),this._showToast(Z_(e=>this._t(e),t))}}),this._onboardingRuntimeLoader=new Q_({expectedFingerprint:Yf,load:async e=>{const t=0===e?await import("./houseplan-onboarding-runtime-BB8OHZOL.js"):await import((()=>{const e=new URL("./houseplan-onboarding-runtime-BB8OHZOL.js",import.meta.url);return e.searchParams.set("hp_retry",`${Kf}-${++Gf}`),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),this._showToast(Z_(e=>this._t(e),t))}}),this._space="f1",this._layout={},this._serverStorage=!1,this._loadOk=!1,this._serverCanWrite=null,this._loading=!1,this._loadTries=0,this._serverCfg=null,this._cfgRev=0,this._cfgContentFingerprint="",this._unsubCfg=null,this._unsubLayout=null,this._unsubVirtual=null,this._liveSyncAttempt=null,this._liveSyncGeneration=0,this._liveSyncConnection=null,this._layoutRev=0,this._layoutContentFingerprint="",this._virtualLights=Jc(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 g_(this,()=>this._syncPointerHoverTargets()),this._devicePressAnimations=new Map,this._selId=null,this._toast="",this._mode="view",this._pendingNavMode=null,this._decorTool="select",this._decorStyle={...rr},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.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 q_({frame:e=>this._applyModeTransitionFrame(e),settled:e=>this._settleModeTransition(e)}),this._cameraTransitionFit=null,this._cameraTransition=new X_({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 D_(50),this._devicePositionHistory=new D_(50),this._devicePositionBusy=!1,this._wallDialog=null,this._drawWallField=null,this._activeDraftId=null,this._resumeDraftBySpace={},this._physicalSel=null,this._physicalDialog=null,this._partitionDeleteDialog=null,this._roomDeleteDialog=null,this._physicalDrag=null,this._physicalRotate=null,this._physicalLastTap=null,this._physicalPickCycle=null,this._wallUnionCacheValue=null,this._wallUnionPool=new Map,this._isoGeometryCache=new Map,this._isoFallback=new Set,this._openingTunnelCache=null,this._openingWallIndexCache=new Map,this._openingPlacementIntervalsCache=null,this._openingDimensionContextCache=null,this._planSnapGeometryCache=null,this._planStructuralGeometryCache=null,this._hiddenWallDiagnosticCache=null,this._physicalBodiesCache=null,this._lightPhysicalBodiesCache=null,this._cleanFloorCache=new Map,this._innerContourCache=new Map,this._glowRuntimeState=zm(),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._roomTempSrc="",this._roomHumSrc="",this._roomSrcOpen=null,this._roomSrcFilter="",this._roomNameScale=1,this._roomLabelScale=1,this._zoom=1,this._view=null,this._zoomBySpace={},this._viewModeSnap=null,this._pointers=new Map,this._panStart=null,this._panLock=null,this._pinchStart=null,this._suppressClick=!1,this._touchContacts=new Map,this._touchSequenceMultitouch=!1,this._touchClickBlockUntil=0,this._connectedPath="",this._routeDepartureHandled=!1,this._onLocationChanged=()=>{this._connectedPath&&location.pathname!==this._connectedPath?this._leaveCardRoute():location.pathname===this._connectedPath&&(this._routeDepartureHandled=!1)},this._touchGestureGuard={capture:!0,handleEvent: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 fe(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._haSupportApi=null,this._haDecorAssetsApi=null,this._decorAssetSyncToken=0,this._alignDialog=null,this._settingsDialog=null,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=++eg,this._warmKey=null,this._warmSlot=null,this._hashApplied=!1,this._navApplied=!1,this._labs={active:Object.freeze([]),space:""},this._viewPreference={},this._renderProjection="flat",this._kioskScale={icon:1,font:1},this._kioskDialog=!1,this._activityRt=new Map,this._vacRt=new Map,this._vacViewKey="",this._vacLastView=null,this._vacRaf=0,this._vacSrvTrails={},this._vacJumpOnce=!1,this._continuity=this._newContinuityController(),this._continuityHistory=[],this._continuityEpoch=0,this._continuityDataReady=!0,this._continuityPaintToken=-1,this._continuityDisposed=!1,this._renderSnapshotAt=Date.now(),this._hassSequence=0,this._visibleDeviceSnapshot=null,this._candidateDeviceSnapshot=null,this._stagedDeviceSnapshotToken=-1,this._capturedSnapshotSequence=-1,this._capturedSnapshotDevices=null,this._capturedSnapshotLayout=null,this._capturedSnapshotActivity="",this._capturedSnapshotConfigEpoch=-1,this._capturedSnapshotVirtual="",this._lastValidStageSize=null,this._pendingRefitSize=null,this._refitRaf=0,this._pageVisibility=e=>{if(this._continuity.visibility(e),this._dayCycleVisibility(e),"hidden"===e.kind)return this._clearTransientHover(!0),this._cancelDevicePressFeedback(),this._cancelCameraTransition(!0),void(this._modeTransitionPreparing?this._modeTransitionForceAtomic=!0:this._cancelModeTransition(!0));if(this._vacJumpOnce=!0,!e.long){const e=Date.now();let t=!1;for(const i of this._activityRt.values())!i.flashKind||(i.expiresAt||i.flashTs+u_)>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._lastTap=0,this._onLabsSnapshot=e=>{const t=this._effectiveProjection();this._labs=e;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._activeDraftId&&(this._resumeDraftBySpace[this._space]=this._activeDraftId),this._commitSpace(e),this._selId=null,this._path=[],this._clearPlanSnapHover(),this._clearOpeningPlacement(!0),this._tool="draw",this._activeDraftId=null,this._draftSegmentCms=[],this._closingWallCm=null,"plan"===this._mode&&"draw"===this._tool&&this._resumeLastDraft(),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._modelCache=null,this._emptySpaceStateActive=!1,this._decorSnapCache=null,this._markerPreviewMemo=null,this._markerPreviewDevicesMemo=null,this._showHidden=!1,this._connHooked=null,this._connectionWasLost=!1,this._haRegistryConnection=null,this._haRegistryRev=-1,this._haBindingCacheKey="",this._planHassMemo=null,this._onHaRegistryUpdate=()=>{const e=gh(this.hass);e.revision===this._haRegistryRev&&this._devices.length||(this._haRegistryRev=e.revision,this._planHassMemo=null,this._regSignature="",this._maybeRebuildDevices(),this.requestUpdate())},this._onConnReady=()=>{if(this._loadTries=0,clearTimeout(this._loadRetryTimer),this._loadRetryTimer=void 0,fh(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 Wl(()=>this.requestUpdate()),this._dirtyPos=new Set,this._sentPos=new Map,this._persistLayout=_g(()=>{if(this._serverStorage){const e=[...this._dirtyPos];this._dirtyPos.clear();for(const t of e){const e=Qr(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=_g(()=>{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._draftSegmentCms=[],this._closingWallCm=null,this._savePhysicalDialog=()=>this._editorRuntimeOrThrow()._savePhysicalDialog(),this._deletePhysicalSelection=()=>this._editorRuntimeOrThrow()._deletePhysicalSelection(),this._confirmPartitionDelete=()=>this._editorRuntimeOrThrow()._confirmPartitionDelete(),this._deleteDraftWhole=()=>this._editorRuntimeOrThrow()._deleteDraftWhole(),this._deleteDraftSegment=()=>this._editorRuntimeOrThrow()._deleteDraftSegment(),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=qn(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._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}_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()}_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)}_seedDecorStyle(e){if(this._decorStyleSeeded||!e)return;this._decorStyleSeeded=!0;const t=e.settings?.decor_default_style;t&&(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:or(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:or(i.fill_opacity,t.fillOpacity)}}(t,rr))}get _canEdit(){return!!this._norm&&(!0===this._serverCanWrite||!1!==this._serverCanWrite&&!0===this.hass?.user?.is_admin)}get _kiosk(){return!!this._config?.kiosk}_showKioskDots(){this._kioskDots=!0,clearTimeout(this._kioskDotsTimer),this._kioskDotsTimer=window.setTimeout(()=>this._kioskDots=!1,2500)}get _modeTransitionBusy(){return this._modeTransitionPreparing||this._modeTransition.active}_cameraState(){const e=this._viewOr(this._baseVb());return{zoom:this._zoom,viewBox:{...e}}}_normalizeCameraState(e){const t=this._cameraTransitionFit||vi(this._baseVb(),this._stageAspect());return{zoom:Math.min(vg.ZOOM_MAX,Math.max(vg.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.requestUpdate()}_settleCameraTransition(e){const t=this._normalizeCameraState(e.to);this._zoom=t.zoom,this._view={...t.viewBox},this._cameraTransitionFit=null,this._saveZoom(),this.requestUpdate()}_cancelCameraTransition(e=!1,t=!1){const i=t&&this._cameraTransition.active?this._cameraTransition.presented?.zoom:void 0;this._cameraTransition.cancel(e),this._cameraTransitionFit=null,void 0!==i&&this._saveZoom()}_prepareCameraCommand(){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||!G_(o,e))&&(G_(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:H_(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=vi(this._baseVb(),n/Math.max(1,r)),s=Math.min(vg.ZOOM_MAX,Math.max(vg.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){this._cancelModeTransition(!1),this._mode=e,"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"),a=s?.querySelector(".editorchrome-inner"),l="view"===i?0:a?.scrollHeight||a?.getBoundingClientRect().height||0,c=Math.max(1,t.stageHeight+t.editorChromeHeight),h=Math.max(1,c-l),d=this._stageEl?.clientWidth||t.stageWidth;if(d<=0||h<=0)return this._modeTransitionPreparing=!1,this._modeTransitionVisual=null,this._applyView(n,r,o),void this.requestUpdate();const u=this._viewForModeTarget(n,r,o,d,h),p={presentedMode:i,editorChromeHeight:l,stageWidth:d,stageHeight:h,viewport:H_(u,d),stageColor:this._targetStageColor(i),paperColor:this._targetPaperColor(i),sceneBrightness:this._targetBrightness(i),architectureOpacity:"decor"===i?.35:1,backdropOpacity:"decor"===i&&"backdrop"!==this._decorTool?.5:1,viewWeight:"view"===i?1:0,editorWeight:"view"===i?0:1,toolbarContentOpacity:"view"===i?0:1};this._modeTransitionPreparing=!1;const m=this._modeTransitionForceAtomic;this._modeTransitionForceAtomic=!1,this._modeTransition.start(t,p,i,this._reducedMotion||m?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._cancelDangerConfirm(),this._cancelCameraTransition(!1),this._clearTransientHover(!0),this._cancelDevicePressFeedback(),this._editorRuntime?._clearFurniturePreview()),this._space=e,!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._activeDraftId&&(this._resumeDraftBySpace[this._space]=this._activeDraftId),this._commitSpace(e),this._path=[],this._clearPlanSnapHover(),this._clearOpeningPlacement(!0),this._tool="draw",this._activeDraftId=null,this._draftSegmentCms=[],this._closingWallCm=null,this._selId=null,this._physicalSel=null,this._editorSecondary?.closeForNavigation(),this._physicalDialog=null,this._physicalDrag=null,"plan"===this._mode&&"draw"===this._tool&&this._resumeLastDraft(),this._restoreZoom(),i||(this._slide=t,clearTimeout(this._slideTimer),this._slideTimer=window.setTimeout(()=>{this._slideTimer=void 0,this._slide="",this.requestUpdate()},190),this.requestUpdate()),!0}get _canReorderTabs(){return Vf({canEdit:this._canEdit,kiosk:this._kiosk,mode:this._mode,pointerType:"mouse",spaceCount:this._model.length,fixedFloor:this._hasFixedFloor})}_tabPointerDown(e,t){Vf({canEdit:this._canEdit,kiosk:this._kiosk,mode:this._mode,pointerType:e.pointerType,spaceCount:this._model.length,fixedFloor:this._hasFixedFloor})&&(fg(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?mu(this,yu,Su(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()}_newContinuityController(){return new Nl(()=>{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(lg,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?kf(i):i;return{x:n[0],y:n[1]}}_convertProjectionView(e,t){if(e===t)return;const i=this._logicalViewCenter(e);this._view=null;const n=i?"iso"===t?wf([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){const e=this._isoSceneKey();e&&this._isoFallback.delete(e)}this._saveViewPreference();const i=this._effectiveProjection();this._convertProjectionView(t,i)}_hashSpace(){return lf(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=k_(this.ownerDocument);var t;void 0!==e&&(this._glowScreenBlend=e),this._continuityUnsub?.(),this._continuityUnsub=El(this.ownerDocument,this._pageVisibility),this._languageFailureUnsub?.(),this._languageFailureUnsub=(t=()=>{this._showToast(this._t("toast.locale_load_failed"))},vu.add(t),()=>vu.delete(t)),super.connectedCallback(),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),w_(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,t){_f.add(t);const i=vf(e);return"undefined"==typeof window&&t(i),()=>{_f.delete(t)}}(Kf,this._onLabsSnapshot),this._booting?this._bootWatch():this._bootFading&&(clearTimeout(this._bootTimer),this._bootTimer=window.setTimeout(()=>{this._bootFading=!1},220)),this._bootSoft&&(clearTimeout(this._bootSoftTimer),this._bootSoftTimer=window.setTimeout(()=>{this._bootSoft=!1},Xf)),!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._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._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),jm(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)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=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._supportDialog)return void this._editorRuntime?._closeSupportDialog();if(this._settingsDialog)return void(this._settingsDialog=null);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;return c?(e.preventDefault(),void this._redoGeometry()):h?(e.preventDefault(),this._decorDraft?void(this._decorDraft=null):this._decorMove||this._dtDrag||this._bdDrag?void this._cancelDecorGesture():void this._undoGeometry()):"Delete"!==e.key&&"Backspace"!==e.key||!this._decorSel||i||n?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._decorDeleteSel())}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._activeDraftId&&this._path.length>1?this._undoActiveDraftPoint():this._undoPoint())):"draw"===this._tool&&this._path.length?void(this._activeDraftId&&this._path.length>1?this._undoActiveDraftPoint():this._undoPoint()):"split"===this._tool&&this._splitSel?.pts?.length?(this._splitSel={...this._splitSel,pts:this._splitSel.pts.slice(0,-1)},void(this._splitSel.pts.length||(this._cursorPt=null))):void this._undoGeometry();if("Escape"===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){if(this._contourClosed)return this._path=this._path.slice(0,-1),void(this._closingWallCm=null);if(this._activeDraftId&&this._path.length>1&&this._curSpaceCfg){const e=this._geometrySnapshot();this._path=this._path.slice(0,-1),this._draftSegmentCms=this._draftSegmentCms.slice(0,-1);const t=this._curSpaceCfg,i=(t.room_drafts||[]).findIndex(e=>e.id===this._activeDraftId);if(i>=0){const n=Array.isArray(t.room_drafts[i]?.segments)?t.room_drafts[i].segments:[];this._path.length<2?(t.room_drafts.splice(i,1),t.room_drafts.length||delete t.room_drafts,this._activeDraftId=null):t.room_drafts[i]={id:this._activeDraftId,points:this._path.map(e=>[e[0]/hg,e[1]/hg]),segments:this._draftSegmentCms.map((e,t)=>({...n[t]||{},cm:e}))},this._commitPhysicalGeometry(this._t("history.draft_segment_delete"),e)}return}this._path=this._path.slice(0,-1)}}_undoActiveDraftPoint(){const e=this._activeDraftId,t=this._path[0]?[...this._path[0]]:null,i=this._geometryHistory.undo();if(!i)return void this._undoPoint();if(!this._applyGeometryState(i.before,!0))return void this._geometryHistory.clear();const n=e?this._spaceModel()?.room_drafts.find(t=>t.id===e):null;n?(this._activeDraftId=n.id,this._path=n.points.map(e=>[...e]),this._draftSegmentCms=this._adoptDraftCms(this._path,n.segments.map(e=>e.cm),n.id),this._resumeDraftBySpace[this._space]=n.id):(this._activeDraftId=null,this._path=t?[t]:[],this._draftSegmentCms=[],e&&this._resumeDraftBySpace[this._space]===e&&delete this._resumeDraftBySpace[this._space]),this._clearPlanSnapHover(),this._showToast(this._t("history.undone",{name:i.name}))}static async getConfigElement(){return await import("./editor-CxXW-QO8.js"),document.createElement("houseplan-card-editor")}static getStubConfig(){return{type:"custom:houseplan-card"}}static _warmBootReset(e){for(const e of Qf.values())for(const t of e)clearTimeout(t.evict);Qf.clear(),ig=e&&e>0?e:1e4}static _warmBootStats(){let e=0,t=0;const i=[];for(const n of Qf.values())for(const r of n)e++,r.dlg&&(t++,i.push(r.dlg.kind));return{keys:Qf.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(og)||"{}")||{}}catch{this._zoomBySpace={}}try{const e=JSON.parse(localStorage.getItem(lg)||"{}")||{};this._viewPreference=Object.fromEntries(Object.entries(e).filter(e=>"flat"===e[1]||"iso"===e[1]))}catch{this._viewPreference={}}this._labs=vf(Kf);try{const e=JSON.parse(localStorage.getItem(ag)||"null");this._kioskScale={icon:kn(e?.icon),font:kn(e?.font)}}catch{}try{const e=JSON.parse(localStorage.getItem(rg)||"null");e&&e.config&&Array.isArray(e.config.spaces)&&(this._serverCfg=e.config,this._seedDecorStyle(this._serverCfg),this._cfgEpoch++,this._cfgRev=e.rev||0,this._cfgContentFingerprint=e.config_fingerprint||Ll(e.config),this._layout=e.layout||{},this._layoutRev=e.layout_rev||0,this._layoutContentFingerprint=e.layout_fingerprint||Ll(this._layout),this._virtualLights=Jc(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)}_warmAdopt(){if(this._config?.kiosk)return;const e=tg(this._config);if(this._warmKey===e&&this._warmSlot)return;this._warmSlot&&this._warmRelease();const t=this.parentNode,i=this._warmIdx(t),n=Qf.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>=Ol,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>=Ol,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},Xf)),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=Qf.get(t);if(!e.live&&o&&o.length>1){const t=o.indexOf(e);t>=0&&o.splice(t,1)}},ig+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?wf([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&&ug.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=tg(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=Qf.get(i)||[];for(n.push(this._warmSlot),Qf.set(i,n),this._warmTrim(n);Qf.size>8;){const e=Qf.keys().next().value;if(void 0===e||e===i)break;for(const t of Qf.get(e)||[])clearTimeout(t.evict);Qf.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,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};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>ig)&&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._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._activeDraftId=this._wallFaceBatch.activeDraftId,this._draftSegmentCms=[...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._cfgContentFingerprint=Ll(this._serverCfg),this._layoutContentFingerprint=Ll(this._layout),this._virtualLights=function(e,t,i){if(e.configRev===i)return e;const n=new Set((Array.isArray(t?.markers)?t.markers:[]).filter(ih).map(e=>e.id));return{...e,configRev:i,off:new Set([...e.off].filter(e=>n.has(e)))}}(this._virtualLights,this._serverCfg,this._cfgRev),localStorage.setItem(rg,JSON.stringify({config:this._serverCfg,rev:this._cfgRev,config_fingerprint:this._cfgContentFingerprint,layout:this._layout,layout_rev:this._layoutRev,layout_fingerprint:this._layoutContentFingerprint,virtual_lights:eh(this._virtualLights)}))}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}_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=Ra(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 Bl([this._cfgRev,this._cfgContentFingerprint||Ll(this._serverCfg),this._layoutRev,this._layoutContentFingerprint||Ll(this._layout),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 W`
e.stopPropagation()}
@click=${e=>e.stopPropagation()}
diff --git a/dist/houseplan-assets/houseplan-editor-runtime-CmI5Go3m.js b/dist/houseplan-assets/houseplan-editor-runtime-o7FB8qC-.js
similarity index 85%
rename from dist/houseplan-assets/houseplan-editor-runtime-CmI5Go3m.js
rename to dist/houseplan-assets/houseplan-editor-runtime-o7FB8qC-.js
index a96847ec..2b2b92cd 100644
--- a/dist/houseplan-assets/houseplan-editor-runtime-CmI5Go3m.js
+++ b/dist/houseplan-assets/houseplan-editor-runtime-o7FB8qC-.js
@@ -1,4 +1,4 @@
-globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="bd7029808eb6094140d9fa8245f50816cb452430a353f4231d16e02c97078a06";import{e as t,i as e,E as s,s as i,a as o,n as a,f as n,b as r,l,o as h,r as c,A as d,c as p,d as u,g as _,h as m,j as g,t as f,w as b,k as v,m as y,v as $,p as w,q as k,u as x,x as S,y as M,z as D,B as C,C as P,D as I,F as T,G as R,H as z,I as A,J as F,K as N,L as H,M as L,N as E,O,P as B,Q as W,R as G,S as j,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 Dt,as as Ct,at as Pt,au as It,av as Tt,aw as Rt,ax as zt,ay as At,az as Ft,aA as Nt,aB as Ht,aC as Lt,aD as Et,aE as Ot,aF as Bt,aG as Wt,aH as Gt,aI as jt,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 De,bi as Ce,bj as Pe,bk as Ie,bl as Te,bm as Re,bn as ze,bo as Ae,bp as Fe,bq as Ne,br as He,bs as Le,bt as Ee,bu as Oe,bv as Be,bw as We,bx as Ge,by as je,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 Ds,c8 as Cs,c9 as Ps,ca as Is,cb as Ts,cc as Rs,cd as zs,ce as As,cf as Fs,cg as Ns,ch as Hs,ci as Ls,cj as Es,ck as Os,cl as Bs,cm as Ws,cn as Gs,co as js,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 Di,c_ as Ci,c$ as Pi,d0 as Ii,d1 as Ti,d2 as Ri,d3 as zi,d4 as Ai,d5 as Fi,d6 as Ni,d7 as Hi,d8 as Li,d9 as Ei,da as Oi,db as Bi,dc as Wi,dd as Gi,de as ji,df as qi,dg as Ui,dh as Ki,di as Vi,dj as Ji}from"./houseplan-card-BTXh6SvG.js";import{F as Yi,f as Xi,p as Zi,c as Qi,i as to,e as eo,r as so,a as io,b as oo,s as ao,t as no}from"./backdrop-pick-DxKIBNjn.js";const ro={},lo=t(class extends e{constructor(){super(...arguments),this.ot=ro}render(t,e){return e()}update(t,[e,i]){if(Array.isArray(e)){if(Array.isArray(this.ot)&&this.ot.length===e.length&&e.every((t,e)=>t===this.ot[e]))return s}else if(this.ot===e)return s;return this.ot=Array.isArray(e)?Array.from(e):e,this.render(e,i)}});var ho={"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_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."};const co={en:ho,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_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}» независимо от текущей карты."},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_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}“."},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_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."}};function po(t,e,s){return i(co[t]?.[e]??ho[e]??e,s)}function uo(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 _o(t,e,s){return t.map(t=>t.id===e?{...t,calibration:s}:t)}const mo=(t,e)=>{const s=(t._serverCfg?.spaces||[]).find(t=>t?.id===e);return String(s?.name||s?.id||e)};function go(t,e,s){const i=t.host,n=l(i.hass,i._config?.language),r=(t,e)=>po(n,t,e),u=e.marker?.vacuum||{},_=Array.isArray(u.map_routes)&&u.map_routes.length>0,m=i._vacSource(e)||"",g=o(e.id,u,e.space,m),f=(i._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=h(g,[m],t=>i._vacObservedMapId(e,t)),y=c({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=t=>{let i=_?u.map_routes:null;return!(!i&&(i=function(t,e,s,i){if(!s)return null;const o=t?.calibration;if(!o||"object"!=typeof o)return null;const n=new Set,r=[];for(const t of Object.keys(o)){const l=a(o[t]);if(!l)continue;const h=i(n);n.add(h),r.push({id:h,source:s,map_id:t,space:e,calibration:l})}return r.length?r:null}(u,e.space,m,t=>uo(t))??[],!m&&Object.keys(u.calibration||{}).length))&&(s({map_routes:t(i),calibration:void 0}),!0)},x=()=>new Set(g.map(t=>t.id)),S=new Map(f.map((t,e)=>[t.id,e])),M=[...g].sort((t,e)=>(S.get(t.space)??1e6)-(S.get(e.space)??1e6)||t.map_id.localeCompare(e.map_id)||t.source.localeCompare(e.source)),D=!!m&&void 0!==w&&!g.some(t=>t.source===m&&t.map_id===w);return p`
+globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="781b6de4892612660b01762cd408049137fa0d00417a43ef5bbdfb1ef37dc9a5";import{e as t,i as e,E as s,s as i,a as o,n as a,f as n,b as r,l,o as h,r as c,A as d,c as p,d as u,g as _,h as m,j as g,t as f,w as b,k as v,m as y,v as $,p as w,q as k,u as x,x as S,y as M,z as D,B as C,C as P,D as I,F as T,G as R,H as z,I as A,J as F,K as N,L as H,M as L,N as E,O,P as B,Q as W,R as G,S as j,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 Dt,as as Ct,at as Pt,au as It,av as Tt,aw as Rt,ax as zt,ay as At,az as Ft,aA as Nt,aB as Ht,aC as Lt,aD as Et,aE as Ot,aF as Bt,aG as Wt,aH as Gt,aI as jt,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 De,bi as Ce,bj as Pe,bk as Ie,bl as Te,bm as Re,bn as ze,bo as Ae,bp as Fe,bq as Ne,br as He,bs as Le,bt as Ee,bu as Oe,bv as Be,bw as We,bx as Ge,by as je,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 Ds,c8 as Cs,c9 as Ps,ca as Is,cb as Ts,cc as Rs,cd as zs,ce as As,cf as Fs,cg as Ns,ch as Hs,ci as Ls,cj as Es,ck as Os,cl as Bs,cm as Ws,cn as Gs,co as js,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 Di,c_ as Ci,c$ as Pi,d0 as Ii,d1 as Ti,d2 as Ri,d3 as zi,d4 as Ai,d5 as Fi,d6 as Ni,d7 as Hi,d8 as Li,d9 as Ei,da as Oi,db as Bi,dc as Wi,dd as Gi,de as ji,df as qi,dg as Ui,dh as Ki,di as Vi,dj as Ji}from"./houseplan-card-CuVuAiJj.js";import{F as Yi,f as Xi,p as Zi,c as Qi,i as to,e as eo,r as so,a as io,b as oo,s as ao,d as no,t as ro}from"./backdrop-pick-BJ59BurK.js";const lo={},ho=t(class extends e{constructor(){super(...arguments),this.ot=lo}render(t,e){return e()}update(t,[e,i]){if(Array.isArray(e)){if(Array.isArray(this.ot)&&this.ot.length===e.length&&e.every((t,e)=>t===this.ot[e]))return s}else if(this.ot===e)return s;return this.ot=Array.isArray(e)?Array.from(e):e,this.render(e,i)}});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_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."};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_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}» независимо от текущей карты."},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_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}“."},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_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."}};function uo(t,e,s){return i(po[t]?.[e]??co[e]??e,s)}function _o(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 mo(t,e,s){return t.map(t=>t.id===e?{...t,calibration:s}:t)}const go=(t,e)=>{const s=(t._serverCfg?.spaces||[]).find(t=>t?.id===e);return String(s?.name||s?.id||e)};function fo(t,e,s){const i=t.host,n=l(i.hass,i._config?.language),r=(t,e)=>uo(n,t,e),u=e.marker?.vacuum||{},_=Array.isArray(u.map_routes)&&u.map_routes.length>0,m=i._vacSource(e)||"",g=o(e.id,u,e.space,m),f=(i._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=h(g,[m],t=>i._vacObservedMapId(e,t)),y=c({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=t=>{let i=_?u.map_routes:null;return!(!i&&(i=function(t,e,s,i){if(!s)return null;const o=t?.calibration;if(!o||"object"!=typeof o)return null;const n=new Set,r=[];for(const t of Object.keys(o)){const l=a(o[t]);if(!l)continue;const h=i(n);n.add(h),r.push({id:h,source:s,map_id:t,space:e,calibration:l})}return r.length?r:null}(u,e.space,m,t=>_o(t))??[],!m&&Object.keys(u.calibration||{}).length))&&(s({map_routes:t(i),calibration:void 0}),!0)},x=()=>new Set(g.map(t=>t.id)),S=new Map(f.map((t,e)=>[t.id,e])),M=[...g].sort((t,e)=>(S.get(t.space)??1e6)-(S.get(e.space)??1e6)||t.map_id.localeCompare(e.map_id)||t.source.localeCompare(e.source)),D=!!m&&void 0!==w&&!g.some(t=>t.source===m&&t.map_id===w);return p`
- `}}export{Gl as EDITOR_RUNTIME_FINGERPRINT,jl as HouseplanEditorRuntime};
+ `}}export{jl as EDITOR_RUNTIME_FINGERPRINT,ql as HouseplanEditorRuntime};
diff --git a/dist/houseplan-assets/houseplan-onboarding-runtime-BB8OHZOL.js b/dist/houseplan-assets/houseplan-onboarding-runtime-CAJfA2x6.js
similarity index 98%
rename from dist/houseplan-assets/houseplan-onboarding-runtime-BB8OHZOL.js
rename to dist/houseplan-assets/houseplan-onboarding-runtime-CAJfA2x6.js
index 7b1086b8..651f96e7 100644
--- a/dist/houseplan-assets/houseplan-onboarding-runtime-BB8OHZOL.js
+++ b/dist/houseplan-assets/houseplan-onboarding-runtime-CAJfA2x6.js
@@ -1,4 +1,4 @@
-globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="bd7029808eb6094140d9fa8245f50816cb452430a353f4231d16e02c97078a06";import{l as t,aK as s,A as e,t as o,c as a,ca as l,cb as i,cc as h,cd as c,aH as n,ce as r,cj as p,cf as d,cg as _,ch as u,ci as g,db as m,aG as b,aI as $,dc as v}from"./houseplan-card-BTXh6SvG.js";import{i as f,c as y,e as w,r as D,a as k,b as S,s as C,t as M}from"./backdrop-pick-DxKIBNjn.js";const F=1e3,x=t=>{if(!t.trim())return null;const s=Number(t.replace(",","."));return Number.isFinite(s)?s:null},T="bd7029808eb6094140d9fa8245f50816cb452430a353f4231d16e02c97078a06";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)?a`{if(!t.trim())return null;const s=Number(t.replace(",","."));return Number.isFinite(s)?s:null},T="781b6de4892612660b01762cd408049137fa0d00417a43ef5bbdfb1ef37dc9a5";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)?a``: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 o=l(e),a=e.settings?.custom_fill&&"object"==typeof e.settings.custom_fill?i(e.settings.custom_fill):null,p="none"===o.fill?{...a||h,a:0}:a;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:o.showBorders,showNames:o.showNames,zeroWallStyle:r(e),displayTouched:!0,hideDecor:o.hideDecor,hideOpenings:o.hideOpenings,roomColor:o.color,roomOpacity:o.opacity,fillMode:"none"===o.fill?"custom":o.fill,customFill:p,glowEnabled:o.glow,bgColor:o.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:o.tempMin,tempMax:o.tempMax,showLqi:o.showLqi??this.host._config?.show_signal??!0,cardFontScale:o.cardFontScale,labelTemp:o.labelTemp,labelHum:o.labelHum,labelLqi:o.labelLqi,labelLight:o.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,...f(),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 o=await y(e);if("reject"===o.kind)return void this.host._showToast(this.host._t("toast.plan_formats"));if("guard"===o.kind)return void(this.host._backdropGuard=o.state);const a=await w(e,o.ext,e.name);this.host._spaceDialog&&(this.host._spaceDialog={...this.host._spaceDialog,planFile:a})}_renderBackdropGuard(){return D(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}),o=this.host._spaceDialog;return o&&o.planUrl===t&&Number.isFinite(e)&&e>0?(this.host._spaceDialog={...o,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 o=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")}),a=this.host._spaceDialog,l=a?.saved?.find(s=>s.name===t);if(o&&a&&l&&l.url===e.url&&l.modified===e.modified&&!l.used_by.length&&l.url!==a.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 a`
${this.host._t("space.loading")}
`;const s=t.saved||[];if(!s.length)return a`
${this.host._t("space.no_saved")}
`;return a`
${s.map(s=>{return a`
diff --git a/dist/houseplan-card.js b/dist/houseplan-card.js
index a8baeb43..21ed9334 100644
--- a/dist/houseplan-card.js
+++ b/dist/houseplan-card.js
@@ -1 +1 @@
-globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="bd7029808eb6094140d9fa8245f50816cb452430a353f4231d16e02c97078a06";try{await import("./houseplan-assets/houseplan-card-BTXh6SvG.js")}catch(e){if(!customElements.get("houseplan-card")){const l=String(navigator.language||"en").toLowerCase();const m=l.startsWith("ru")?"House Plan обновился — перезагрузите страницу (Ctrl+F5).":l.startsWith("de")?"House Plan wurde aktualisiert — bitte laden Sie die Seite neu (Strg+F5).":l.startsWith("fr")?"House Plan a été mis à jour — veuillez recharger la page (Ctrl+F5).":"House Plan was updated — please reload the page (Ctrl+F5).";customElements.define("houseplan-card",class extends HTMLElement{setConfig(){}getCardSize(){return 1}connectedCallback(){this.style.cssText="display:block;box-sizing:border-box;padding:16px;border:1px solid var(--divider-color,#e0e0e0);border-radius:var(--ha-card-border-radius,12px);background:var(--card-background-color,#fff);color:var(--primary-text-color,#212121);font:14px/1.4 var(--paper-font-body1_-_font-family,sans-serif)";this.textContent=m}})}console.error("[houseplan] stale entry: the main chunk is unavailable",e)}
+globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="781b6de4892612660b01762cd408049137fa0d00417a43ef5bbdfb1ef37dc9a5";try{await import("./houseplan-assets/houseplan-card-CuVuAiJj.js")}catch(e){if(!customElements.get("houseplan-card")){const l=String(navigator.language||"en").toLowerCase();const m=l.startsWith("ru")?"House Plan обновился — перезагрузите страницу (Ctrl+F5).":l.startsWith("de")?"House Plan wurde aktualisiert — bitte laden Sie die Seite neu (Strg+F5).":l.startsWith("fr")?"House Plan a été mis à jour — veuillez recharger la page (Ctrl+F5).":"House Plan was updated — please reload the page (Ctrl+F5).";customElements.define("houseplan-card",class extends HTMLElement{setConfig(){}getCardSize(){return 1}connectedCallback(){this.style.cssText="display:block;box-sizing:border-box;padding:16px;border:1px solid var(--divider-color,#e0e0e0);border-radius:var(--ha-card-border-radius,12px);background:var(--card-background-color,#fff);color:var(--primary-text-color,#212121);font:14px/1.4 var(--paper-font-body1_-_font-family,sans-serif)";this.textContent=m}})}console.error("[houseplan] stale entry: the main chunk is unavailable",e)}
diff --git a/scripts/mutation-gate.mjs b/scripts/mutation-gate.mjs
index 24eb09e6..064cae7f 100644
--- a/scripts/mutation-gate.mjs
+++ b/scripts/mutation-gate.mjs
@@ -354,6 +354,33 @@ const MUTANT_DEFINITIONS = [
replace: " case 'нет такого':\n return resolution.kind as any;",
}],
},
+ {
+ id: 'vacuum-route-validation-accepts-a-dead-space',
+ guard: 'node scripts/backend-test-guard.mjs '
+ + 'invalid_routes_are_rejected '
+ + 'tests_backend/test_vacuum_route_validation.py',
+ because: 'a route saved against a space that does not exist can never resolve, so the '
+ + 'write has to be refused at the boundary rather than discovered as a missing robot '
+ + '(#162, M-D backend half)',
+ patches: [{
+ file: 'custom_components/houseplan/vacuum_routes.py',
+ find: ' elif space_ids is not None and space not in space_ids:\n problems.append(issue(route_id, "unknown_space"))',
+ replace: ' elif False:\n problems.append(issue(route_id, "unknown_space"))',
+ }],
+ },
+ {
+ id: 'space-delete-keeps-foreign-vacuum-routes',
+ guard: 'npx tsc -p tsconfig.test.json && node scripts/fix-test-build.mjs '
+ + '&& node --test --test-name-pattern="уносит только свои маршруты" '
+ + 'test/space-deletion.test.mjs',
+ because: 'a deleted space must take the robot map assignments that pointed at it; leaving '
+ + 'them behind keeps a route nothing can resolve and a robot that never appears (#162, AC16)',
+ patches: [{
+ file: 'src/space-deletion.ts',
+ find: ' const kept = routes.filter((route: any) => route?.space !== spaceId);',
+ replace: ' const kept = routes;',
+ }],
+ },
{
id: 'area-snapshot-cleanup-ignores-authority',
guard: 'npx tsc -p tsconfig.test.json && node scripts/fix-test-build.mjs '
@@ -1397,8 +1424,8 @@ const MUTANT_DEFINITIONS = [
+ 'unregistered-error hole #42 closes (AC5 m1)',
patches: [{
file: 'custom_components/houseplan/const.py',
- find: ' "invalid_space_id", "invalid_toggle_entity", "invalid_value_badge",',
- replace: ' "invalid_toggle_entity", "invalid_value_badge",',
+ find: ' "invalid_space_id", "invalid_toggle_entity", "invalid_vacuum_map_route",',
+ replace: ' "invalid_toggle_entity", "invalid_vacuum_map_route",',
}],
},
{
diff --git a/src/houseplan-editor-runtime.ts b/src/houseplan-editor-runtime.ts
index c58574b8..aefdb610 100644
--- a/src/houseplan-editor-runtime.ts
+++ b/src/houseplan-editor-runtime.ts
@@ -226,7 +226,7 @@ import {
} from './zero-walls';
import { snapNearAxisEndpoint } from './near-axis';
import type { SpaceReferenceRepairContext } from './space-reference-repair';
-import { collectSpaceMarkerDependencies } from './space-deletion';
+import { collectSpaceMarkerDependencies, spaceDeletionMessage } from './space-deletion';
import {
checkSpacePhysicalGeometry,
checkOptimizeGeometry,
@@ -8863,7 +8863,8 @@ public async _deleteSpace(): Promise {
key: 'delete-space',
kind: 'destructive',
title: this.host._t('confirm.delete_space_title'),
- message: this.host._t('confirm.delete_space_body'),
+ message: spaceDeletionMessage(this.host._t('confirm.delete_space_body'),
+ this.host._t('confirm.delete_space_vac_routes'), dependencies.routeCount),
objectName: sp.title,
confirmLabel: this.host._t('btn.delete'),
cancelLabel: this.host._t('btn.cancel'),
diff --git a/src/i18n/de.json b/src/i18n/de.json
index e626c9fd..dfcf5d27 100644
--- a/src/i18n/de.json
+++ b/src/i18n/de.json
@@ -292,6 +292,7 @@
"confirm.erase_decor": "Das Objekt „{kind}“ löschen? Diese Aktion kann im Editor rückgängig gemacht werden.",
"confirm.delete_space_title": "Bereich löschen?",
"confirm.delete_space_body": "Der Bereich, alle seine Räume und die gesamte Planmarkierung werden gelöscht.",
+ "confirm.delete_space_vac_routes": "Zuordnungen von Roboterkarten werden ebenfalls entfernt: {count}.",
"space.delete_blocked": "Dieser Bereich wird noch von {n} Gerät(en) verwendet. Die Geräte zuerst in einen anderen Bereich verschieben oder löschen.",
"toast.pos_save_failed": "Position nicht gespeichert: {err}",
"toast.no_entity": "Das Gerät hat keine geeignete Entität",
@@ -1153,6 +1154,7 @@
"backup.error.invalid_value_badge_attribute": "Ungültiges Wert-Badge-Attribut",
"backup.error.invalid_value_badge_position": "Ungültige Wert-Badge-Position",
"backup.error.invalid_value_badge_source": "Ungültige Wert-Badge-Quelle",
+ "backup.error.invalid_vacuum_map_route": "Prüfen Sie die Zuordnung der Roboterkarten zu Räumen.",
"backup.error.invalid_value_source": "Ungültige Wertquelle",
"backup.error.invalid_value_source_attribute": "Ungültiges Wertquellen-Attribut",
"backup.error.io_error": "Eine Dateioperation auf dem Server ist fehlgeschlagen",
diff --git a/src/i18n/en.json b/src/i18n/en.json
index 9fee6eb7..41201049 100644
--- a/src/i18n/en.json
+++ b/src/i18n/en.json
@@ -292,6 +292,7 @@
"confirm.erase_decor": "Erase the {kind} object? You can undo this action from the editor history.",
"confirm.delete_space_title": "Delete space?",
"confirm.delete_space_body": "The space, all its rooms and all its plan markup will be deleted.",
+ "confirm.delete_space_vac_routes": "Robot map assignments will also be removed: {count}.",
"space.delete_blocked": "This space is still used by {n} device(s). Move them to another space or delete them first.",
"toast.pos_save_failed": "Failed to save position: {err}",
"toast.no_entity": "The device has no suitable entity",
@@ -1153,6 +1154,7 @@
"backup.error.invalid_value_badge_attribute": "Invalid value badge attribute",
"backup.error.invalid_value_badge_position": "Invalid value badge position",
"backup.error.invalid_value_badge_source": "Invalid value badge source",
+ "backup.error.invalid_vacuum_map_route": "Check how the robot's maps are assigned to spaces.",
"backup.error.invalid_value_source": "Invalid value source",
"backup.error.invalid_value_source_attribute": "Invalid value source attribute",
"backup.error.io_error": "A file operation failed on the server",
diff --git a/src/i18n/fr.json b/src/i18n/fr.json
index 3596d198..46668223 100644
--- a/src/i18n/fr.json
+++ b/src/i18n/fr.json
@@ -292,6 +292,7 @@
"confirm.erase_decor": "Effacer l’objet {kind} ? Vous pouvez annuler cette action depuis l’historique de l’éditeur.",
"confirm.delete_space_title": "Supprimer l’espace ?",
"confirm.delete_space_body": "L’espace, toutes ses pièces et tout le tracé du plan seront supprimés.",
+ "confirm.delete_space_vac_routes": "Les affectations de cartes de robots seront aussi supprimées : {count}.",
"space.delete_blocked": "Cet espace est encore utilisé par {n} appareil(s). Déplacez-les vers un autre espace ou supprimez-les d’abord.",
"toast.pos_save_failed": "Échec de l’enregistrement de la position : {err}",
"toast.no_entity": "L’appareil n’a aucune entité adaptée",
@@ -1153,6 +1154,7 @@
"backup.error.invalid_value_badge_attribute": "Attribut de badge de valeur invalide",
"backup.error.invalid_value_badge_position": "Position de badge de valeur invalide",
"backup.error.invalid_value_badge_source": "Source de badge de valeur invalide",
+ "backup.error.invalid_vacuum_map_route": "Vérifiez l'affectation des cartes du robot aux espaces.",
"backup.error.invalid_value_source": "Source de valeur invalide",
"backup.error.invalid_value_source_attribute": "Attribut de source de valeur invalide",
"backup.error.io_error": "Une opération de fichier a échoué sur le serveur",
diff --git a/src/i18n/ru.json b/src/i18n/ru.json
index aaf0b25a..865b79ca 100644
--- a/src/i18n/ru.json
+++ b/src/i18n/ru.json
@@ -292,6 +292,7 @@
"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": "У устройства нет подходящей сущности",
@@ -1153,6 +1154,7 @@
"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": "Файловая операция на сервере не удалась",
diff --git a/src/space-deletion.ts b/src/space-deletion.ts
index 31fc3e54..96329969 100644
--- a/src/space-deletion.ts
+++ b/src/space-deletion.ts
@@ -3,8 +3,21 @@
export interface SpaceDeletionDependencyReport {
markerIds: string[];
count: number;
+ /**
+ * Markers that live on ANOTHER floor but route one of their robot maps here
+ * (#162). They do not block the deletion — the dock is not in this space —
+ * but the user has to be told how many map assignments disappear with it.
+ */
+ routeMarkerIds: string[];
+ routeCount: number;
}
+/** Ids of routes this marker points at the space being deleted. */
+const routesIntoSpace = (marker: any, spaceId: string): string[] =>
+ (marker?.vacuum?.map_routes || [])
+ .filter((route: any) => route && route.space === spaceId && typeof route.id === 'string')
+ .map((route: any) => route.id);
+
const clone = (value: T): T => JSON.parse(JSON.stringify(value));
export function collectSpaceMarkerDependencies(
@@ -23,7 +36,27 @@ export function collectSpaceMarkerDependencies(
|| layout?.[marker.id]?.s === spaceId)
.map((marker: any) => marker.id))]
.sort((a: string, b: string) => a.localeCompare(b));
- return { markerIds, count: markerIds.length };
+ const routeMarkerIds = (config?.markers || [])
+ .filter((marker: any) => marker?.removed !== true && typeof marker?.id === 'string')
+ .filter((marker: any) => !markerIds.includes(marker.id))
+ .filter((marker: any) => routesIntoSpace(marker, spaceId).length > 0)
+ .map((marker: any) => marker.id)
+ .sort((a: string, b: string) => a.localeCompare(b));
+ return {
+ markerIds, count: markerIds.length,
+ routeMarkerIds, routeCount: routeMarkerIds.length,
+ };
+}
+
+/**
+ * Confirm text for a space delete: the base warning, plus how many robot map
+ * assignments go with it (#162). Composed here so the count cannot quietly
+ * fall out of the dialog when the wording changes.
+ */
+export function spaceDeletionMessage(
+ base: string, routesTemplate: string, routeCount: number,
+): string {
+ return routeCount ? `${base} ${routesTemplate.replace('{count}', String(routeCount))}` : base;
}
export function createSpaceDeletionCandidate(
@@ -61,5 +94,13 @@ export function createSpaceDeletionCandidate(
for (const [key, position] of Object.entries(layout)) {
if ((position as any)?.s === spaceId) delete layout[key];
}
+ // #162: a robot docked elsewhere keeps its dock and its other maps; only the
+ // routes that pointed here go, in the same logical operation as the space.
+ for (const marker of config.markers || []) {
+ const routes = marker?.vacuum?.map_routes;
+ if (!Array.isArray(routes)) continue;
+ const kept = routes.filter((route: any) => route?.space !== spaceId);
+ if (kept.length !== routes.length) marker.vacuum.map_routes = kept;
+ }
return { config, layout, dependencies };
}
diff --git a/test/space-deletion.test.mjs b/test/space-deletion.test.mjs
index 55c0f0bf..6f37aa05 100644
--- a/test/space-deletion.test.mjs
+++ b/test/space-deletion.test.mjs
@@ -2,7 +2,7 @@ import test from 'node:test';
import assert from 'node:assert/strict';
import {
- collectSpaceMarkerDependencies, createSpaceDeletionCandidate,
+ collectSpaceMarkerDependencies, createSpaceDeletionCandidate, spaceDeletionMessage,
} from '../test-build/space-deletion.js';
test('issue 244 space dependency count deduplicates all three reference paths', () => {
@@ -20,7 +20,7 @@ test('issue 244 space dependency count deduplicates all three reference paths',
all: { s: 'f1' }, room: { s: 'f2' }, position: { s: 'f1' }, removed: { s: 'f1' },
};
assert.deepEqual(collectSpaceMarkerDependencies(config, layout, 'f1'), {
- markerIds: ['all', 'position', 'room'], count: 3,
+ markerIds: ['all', 'position', 'room'], count: 3, routeMarkerIds: [], routeCount: 0,
});
const blocked = createSpaceDeletionCandidate(config, layout, 'f1');
assert.deepEqual(blocked.config, config);
@@ -109,3 +109,57 @@ test('issue 244 deleting the last occupied space detaches placement but preserve
assert.equal(config.markers[0].space, 'only', 'input config is immutable');
assert.equal(layout.direct.s, 'only', 'input layout is immutable');
});
+
+// --- #162: карты робота, назначенные удаляемому пространству -----------------
+
+const routeCfg = () => ({
+ spaces: [{ id: 'floor1', rooms: [] }, { id: 'floor2', rooms: [] }],
+ markers: [{
+ id: 'robot', space: 'floor1',
+ vacuum: {
+ source: 'camera.robot',
+ map_routes: [
+ { id: 'r1', source: 'camera.robot', map_id: 'm1', space: 'floor1', calibration: [1, 0, 0, 0, 1, 0] },
+ { id: 'r2', source: 'camera.robot', map_id: 'm2', space: 'floor2', calibration: [2, 0, 0, 0, 2, 0] },
+ ],
+ },
+ }],
+});
+
+test('#162 удаление пространства считает чужие карты роботов отдельно', () => {
+ const report = collectSpaceMarkerDependencies(routeCfg(), {}, 'floor2');
+ assert.deepEqual(report.markerIds, [], 'док робота живёт на другом этаже и удалению не мешает');
+ assert.deepEqual(report.routeMarkerIds, ['robot']);
+ assert.equal(report.routeCount, 1);
+});
+
+test('#162 маркер В удаляемом пространстве не считается дважды', () => {
+ const report = collectSpaceMarkerDependencies(routeCfg(), {}, 'floor1');
+ assert.deepEqual(report.markerIds, ['robot']);
+ assert.deepEqual(report.routeMarkerIds, [], 'он уже в блокирующем списке');
+});
+
+test('#162 удаление уносит только свои маршруты, док и соседние карты целы', () => {
+ const { config } = createSpaceDeletionCandidate(routeCfg(), {}, 'floor2');
+ const marker = config.markers[0];
+ assert.equal(marker.space, 'floor1', 'док остался на своём этаже');
+ assert.deepEqual(marker.vacuum.map_routes.map((r) => r.id), ['r1']);
+ assert.equal(marker.vacuum.source, 'camera.robot', 'корневой источник не тронут');
+});
+
+test('#162 легаси-калибровка удалением пространства не трогается', () => {
+ const cfg = {
+ spaces: [{ id: 'floor1', rooms: [] }, { id: 'floor2', rooms: [] }],
+ markers: [{ id: 'robot', space: 'floor1', vacuum: { source: 'camera.robot', calibration: { m1: [1, 0, 0, 0, 1, 0] } } }],
+ };
+ const { config } = createSpaceDeletionCandidate(cfg, {}, 'floor2');
+ assert.deepEqual(config.markers[0].vacuum.calibration, { m1: [1, 0, 0, 0, 1, 0] });
+});
+
+test('#162 текст подтверждения называет число карт, а без них не меняется', () => {
+ const base = 'Пространство будет удалено.';
+ const template = 'Также будет снято сопоставление карт роботов: {count}.';
+ assert.equal(spaceDeletionMessage(base, template, 0), base);
+ assert.equal(spaceDeletionMessage(base, template, 2),
+ 'Пространство будет удалено. Также будет снято сопоставление карт роботов: 2.');
+});
diff --git a/tests_backend/test_vacuum_route_validation.py b/tests_backend/test_vacuum_route_validation.py
new file mode 100644
index 00000000..375e9278
--- /dev/null
+++ b/tests_backend/test_vacuum_route_validation.py
@@ -0,0 +1,83 @@
+"""Семантическая валидация маршрутов карт при config/set и импорте (#162)."""
+import pytest
+
+from custom_components.houseplan.validation import (
+ MarkerControlError,
+ validate_marker_vacuum_routes,
+)
+from custom_components.houseplan.vacuum_routes import VAC_ROUTE_ERROR
+
+IDENTITY = [1, 0, 0, 0, 1, 0]
+
+
+def _config(routes, spaces=("floor1", "floor2")):
+ return {
+ "spaces": [{"id": space} for space in spaces],
+ "markers": [{"id": "m1", "space": "floor1", "vacuum": {"map_routes": routes}}],
+ }
+
+
+def _route(**over):
+ base = {"id": "r1", "source": "camera.robot", "map_id": "m1",
+ "space": "floor1", "calibration": IDENTITY}
+ base.update(over)
+ return base
+
+
+def test_valid_routes_pass():
+ validate_marker_vacuum_routes(_config([_route(), _route(id="r2", map_id="m2", space="floor2")]))
+
+
+def test_error_code_is_the_public_contract_code():
+ assert VAC_ROUTE_ERROR == "invalid_vacuum_map_route"
+ with pytest.raises(MarkerControlError) as excinfo:
+ validate_marker_vacuum_routes(_config([_route(space="нет такого")]))
+ assert excinfo.value.code == VAC_ROUTE_ERROR
+
+
+@pytest.mark.parametrize("routes", [
+ [_route(space="удалённое")],
+ [_route(), _route(id="r2")],
+ [_route(), _route(map_id="m2")],
+ [_route(calibration=[1, 2, 3])],
+ [_route(source="не-entity")],
+ [_route(id="")],
+ ["строка вместо объекта"],
+])
+def test_invalid_routes_are_rejected(routes):
+ with pytest.raises(MarkerControlError):
+ validate_marker_vacuum_routes(_config(routes))
+
+
+def test_untouched_invalid_routes_do_not_block_an_unrelated_save():
+ """Смена другого поля не обязана чинить чужие/будущие данные."""
+ broken = _config([_route(space="исчезнувшее")])
+ previous = {"markers": [dict(broken["markers"][0])], "spaces": broken["spaces"]}
+ validate_marker_vacuum_routes(broken, previous)
+ # но правка самих маршрутов обязана оставить их валидными
+ edited = _config([_route(space="исчезнувшее"), _route(id="r2", map_id="m2")])
+ with pytest.raises(MarkerControlError):
+ validate_marker_vacuum_routes(edited, previous)
+
+
+def test_import_validates_everything():
+ broken = _config([_route(space="исчезнувшее")])
+ with pytest.raises(MarkerControlError):
+ validate_marker_vacuum_routes(broken, None, validate_all=True)
+
+
+def test_missing_spaces_list_skips_the_referential_check_only():
+ config = {"markers": [{"id": "m1", "vacuum": {"map_routes": [_route(space="floor9")]}}]}
+ validate_marker_vacuum_routes(config)
+ config["markers"][0]["vacuum"]["map_routes"] = [_route(space="floor9", calibration=[1])]
+ with pytest.raises(MarkerControlError):
+ validate_marker_vacuum_routes(config)
+
+
+def test_legacy_marker_without_routes_is_untouched():
+ config = {
+ "spaces": [{"id": "floor1"}],
+ "markers": [{"id": "m1", "space": "floor1",
+ "vacuum": {"source": "camera.robot", "calibration": {"m1": IDENTITY}}}],
+ }
+ validate_marker_vacuum_routes(config, None, validate_all=True)