diff --git a/README.md b/README.md index 02f537e..ebee90c 100644 --- a/README.md +++ b/README.md @@ -71,12 +71,12 @@ also be changed on the screen or by an automation, and your own YAML for one scr

ESP Screens in Home Assistant: your screens in the sidebar, the pages of the living room screen side by side with their top bar, and the entity library on the right

-

ESP Screens, a page in Home Assistant: every screen on the left, its top bar and tiles on the right.

+

ESP Screens, a page in Home Assistant: your screens on the left, the pages of the chosen screen in the middle with the values Home Assistant reports right now, the library on the right.

Choosing tiles: the pages of the screen side by side, next to the library with its search and filters Tile settings of the curtains in the drawer: double-width with open, stop and close on the tile, what a tap does, and the pastel background

-

Search your home, drop a tile on the preview, tap it for its name, width, control and color, and for what a tap does: open its card, switch it, or run any action Home Assistant has for it, such as the curtains to 50 %. Save, and the screen has it.

+

Search your home, drop a tile on the preview, tap it for its name, width, control and color, and for what a tap does: open its card, switch it, or run any action Home Assistant has for it, such as the curtains to 50 %. Save, and the screen has it. ⌘K searches screens, entities and actions; Identify blinks a screen so you know which one it is.

Add to the top bar, in the drawer: the time, an analog clock, the date, suggestions from your own home and any entity Settings in ESP Screens: New screen and Firmware & USB, the firmware updates, the Alerts cheatsheet, and the Claude skill diff --git a/docs/images/editor-alerts.png b/docs/images/editor-alerts.png index ca34403..e468032 100644 Binary files a/docs/images/editor-alerts.png and b/docs/images/editor-alerts.png differ diff --git a/docs/images/editor-tiles.png b/docs/images/editor-tiles.png index 3cadcfa..6adb635 100644 Binary files a/docs/images/editor-tiles.png and b/docs/images/editor-tiles.png differ diff --git a/docs/images/editor.png b/docs/images/editor.png index d15af57..24249de 100644 Binary files a/docs/images/editor.png and b/docs/images/editor.png differ diff --git a/screen_manager/CHANGELOG.md b/screen_manager/CHANGELOG.md index c40a8e4..b7b4307 100644 --- a/screen_manager/CHANGELOG.md +++ b/screen_manager/CHANGELOG.md @@ -7,6 +7,12 @@ A new editor, built as a Vue app, with the same firmware. - **Pages side by side.** The pages of a screen stand next to each other, at the screen's own shape (square for a Guition, 4:3 for a CYD), the way you swipe through them. Dragging from the library onto a page and between cells works as before, with mouse and touch; drop past the last page for a new one. - **The top bar is part of the mockup.** Tap the bar on any page to name the screen and choose its items; the drawer shows every item as the screen draws it. Adding the time, the date, the dial or an entity happens in the same drawer. - **Screen settings as a tab** next to Layout, with the same rows as the settings page on the screen. **Read current data** and **Override YAML** live in the ··· menu of the screen; New screen, Firmware & USB, Alerts and the app Settings are pages of their own, reached from the sidebar. +- **Live values on the mockup.** The tiles show what Home Assistant reports right now: the temperature with its unit, On or Off with a lit icon, the heating's current temperature and setpoint, the volume, a cover's position, the song that plays. Sliders and switches on the cards stand where they stand on the screen. The page asks every eight seconds while it is open. +- **Identify.** The ··· menu of a screen has Identify: the screen shows a short card and blinks its backlight, so with three screens you know which is which. Needs firmware 0.2.31 or newer, like every alert. +- **Try an alert.** The Alerts page opens with Try it: fill in the same seven fields an automation sends, choose one screen or all of them, and Send. The result says how many screens showed it and which fields were left empty. +- **Copy, export, import.** The ··· menu copies the layout of another screen onto this one, exports the layout as a JSON file (and to the clipboard), and imports one. An imported layout is trimmed to what the screen's firmware holds, and nothing is sent before you press Save & send. +- **A smarter library.** A room filter and Hide placed next to the domain chips; a lit icon for a light, switch or fan that is on, a grey one for an entity Home Assistant can't reach. ⌘K (Ctrl+K) opens a search over screens, entities and actions: open a screen, add an entity to the page you have open, save, identify, export. +- **Updates with content.** The Update badge has What's new: the changelog lines since that screen's firmware. A running update shows a progress bar with its stage (building, writing over Wi-Fi, waiting for the screen, checking it stays up) and the last line of the ESPHome log; Settings → Firmware updates shows the log's tail. - **Dark mode follows your browser**, as Home Assistant's own Auto theme does. - Same add-on API, same data, same firmware: nothing to update on the screens. The page is now built with Vue and Vite (`web/`); its files carry a hash of their content, so an update never runs an old script against a new page. diff --git a/screen_manager/DOCS.md b/screen_manager/DOCS.md index 6e6759f..fcae8e6 100644 --- a/screen_manager/DOCS.md +++ b/screen_manager/DOCS.md @@ -15,7 +15,7 @@ for existing profiles: check, build or reinstall via USB, the IP address (OTA) o Download. Existing ESPHome profiles in the HA config folder are found automatically. -**Settings** in the sidebar has the nightly firmware updates, the **Alerts** cheatsheet +**Settings** in the sidebar has the nightly firmware updates (the Update badge of a screen lists what's new, a running update shows its progress), the **Alerts** cheatsheet with a form to try an alert (an alert on one screen, or on every screen with the `esp_screens_show_alert` event) and **Claude**: install the ESP Screens skill for Claude Code in Home Assistant, or download it for claude.ai, and ask Claude for the alert automation. @@ -27,6 +27,7 @@ to configure; firmware 0.2.32 or newer renders them. After pairing via the HA ESPHome integration, choose the tiles in ESP Screens. Tap a tile and its settings open in a drawer on the right, with the mockup still in view: click behavior, larger values, mini-sliders, a wider tile, backgrounds. +The mockup shows what Home Assistant reports right now: values, On or Off, positions, the song that plays. **Identify** in the ··· menu blinks a screen so you know which one it is; the same menu copies the layout of another screen, or exports and imports one as JSON. ⌘K searches screens, entities and actions. **Screen settings**, the tab next to Layout, has brightness and standby. **Read current data** in the ··· menu of a screen helps with missing attributes or an offline screen. New cards require firmware 0.2.0. The ··· menu of a screen also has **Override YAML** for a persistent, hardware-specific diff --git a/screen_manager/Dockerfile b/screen_manager/Dockerfile index a6e2f08..a6e8dd5 100644 --- a/screen_manager/Dockerfile +++ b/screen_manager/Dockerfile @@ -5,6 +5,8 @@ ARG BUILD_ARCH LABEL io.hass.version="${BUILD_VERSION}" io.hass.type="app" io.hass.arch="${BUILD_ARCH}" RUN pip install --no-cache-dir 'aiohttp>=3.12,<4' PyYAML COPY app /app +# The Update badge shows what's new from the changelog (app 0.2.74). +COPY CHANGELOG.md /app/CHANGELOG.md WORKDIR /app ENTRYPOINT [] CMD ["python3", "/app/server.py"] diff --git a/screen_manager/app/changelog.py b/screen_manager/app/changelog.py new file mode 100644 index 0000000..795744f --- /dev/null +++ b/screen_manager/app/changelog.py @@ -0,0 +1,41 @@ +"""What's new for the Update badge (app 0.2.74): the CHANGELOG sections since a screen's firmware. + +The Dockerfile copies CHANGELOG.md next to this file; a development checkout has it one folder up. +Each `## (firmware )` section gives its bullet lines as plain text, newest first. +""" +import re +from pathlib import Path + +HEADER = re.compile(r'^## (\d+\.\d+\.\d+) \(firmware (\d+\.\d+\.\d+)\)') +BOLD = re.compile(r'\*\*(.+?)\*\*') +CODE = re.compile(r'`([^`]*)`') +LINK = re.compile(r'\[([^\]]+)\]\([^)]+\)') + + +def load(path=None, limit=20): + """[{app, firmware, lines}] for the latest sections; [] without a changelog.""" + candidates = [Path(path)] if path else [Path(__file__).with_name('CHANGELOG.md'), Path(__file__).parent.parent / 'CHANGELOG.md'] + for candidate in candidates: + if candidate.exists(): + return parse(candidate.read_text(), limit) + return [] + + +def parse(text, limit=20): + sections = [] + for line in text.splitlines(): + match = HEADER.match(line) + if match: + if len(sections) >= limit: + break + sections.append({'app': match.group(1), 'firmware': match.group(2), 'lines': []}) + elif sections and line.startswith('- '): + sections[-1]['lines'].append(plain(line[2:])) + return sections + + +def plain(markdown): + text = BOLD.sub(r'\1', markdown) + text = CODE.sub(r'\1', text) + text = LINK.sub(r'\1', text) + return text.strip() diff --git a/screen_manager/app/server.py b/screen_manager/app/server.py index 8b893be..e965bff 100644 --- a/screen_manager/app/server.py +++ b/screen_manager/app/server.py @@ -1623,6 +1623,48 @@ def create_app(manager, development=False): manager.registry_index().get(t['entity']),getattr(manager.ha,'state_words',None)), 'attributes':state_message(i,t,manager.ha.states)['a'], 'options':t.get('options',{})} for i,t in enumerate(layout['tiles'])]}) + async def states(request): + """Live values for the editor's mockup (app 0.2.74): the state, Home Assistant's word and the attributes a + card shows, for the tiles on the page, saved or not. At most sixty entities per request.""" + index = manager.registry_index() + result = {} + for eid in request.query.getall('entity', [])[:60]: + if not isinstance(eid, str) or eid not in manager.ha.states: + continue + state = manager.ha.states.get(eid, {}) + entry = index.get(eid) + message = state_message(0, {'entity': eid, 'name': ''}, manager.ha.states, + precision=header_bar.precision_of(entry) if eid.startswith('sensor.') else None) + result[eid] = {'state': message['state'], 'a': message['a'], + 'word': state_word(eid, state.get('state'), state.get('attributes'), entry, getattr(manager.ha, 'state_words', None))} + return web.json_response({'states': result}) + def one_alert_target(inbox): + screen = manager.screen(inbox) + if screen is None: + raise ValueError('Unknown screen.') + ready, skipped = alert_targets([screen]) + if not ready: + raise ValueError(f"{screen['name']} can't show an alert: {skipped[0][1] if skipped else 'not ready'}.") + return ready[0] + async def identify(request): + """Identify (app 0.2.74): the screen shows a short card and blinks its backlight, so you know which one it is.""" + screen = one_alert_target(request.match_info['inbox']) + data, _ = alert_data({'title': f"This is {screen['name']}", 'subtitle': 'Identify, from ESP Screens', 'icon': 'bell-ring', + 'color': 'blue', 'button_text': 'OK', 'timeout': 8, 'flash': True}) + await manager.ha.call(alert_service(screen['node']), data) + return web.json_response({'ok': True}) + async def test_alert(request): + """Alerts → Try it (app 0.2.74): one alert to one screen or to every screen, with the fields an automation sends.""" + body = await request.json() + if not isinstance(body, dict): + raise ValueError('Invalid alert.') + data = body.get('data') if isinstance(body.get('data'), dict) else {} + if body.get('screen') == 'all': + return web.json_response(await manager.broadcast(BROADCAST_SHOW, data)) + screen = one_alert_target(str(body.get('screen', ''))) + service, unusable = alert_data(data) + await manager.ha.call(alert_service(screen['node']), service) + return web.json_response({'sent': 1, 'failed': 0, 'skipped': 0, 'unusable': unusable}) async def install_claude_skill(request): """Settings → Claude → Install: writes the skill into Home Assistant's configuration folder, only on request.""" return web.json_response(claude_skill.install(manager.skill_dir)) @@ -1667,6 +1709,9 @@ def create_app(manager, development=False): app.router.add_get('/', index) app.router.add_get('/api/inventory', inventory) app.router.add_get('/api/capabilities', capabilities) + app.router.add_get('/api/states', states) + app.router.add_post('/api/screens/{inbox}/identify', identify) + app.router.add_post('/api/alerts/test', test_alert) app.router.add_get('/api/entity-actions', entity_actions) app.router.add_post('/api/header-preview', header_preview) app.router.add_post('/api/claude-skill', install_claude_skill) diff --git a/screen_manager/app/static/assets/index-BuQ5a76G.js b/screen_manager/app/static/assets/index-BuQ5a76G.js new file mode 100644 index 0000000..85d3ed5 --- /dev/null +++ b/screen_manager/app/static/assets/index-BuQ5a76G.js @@ -0,0 +1,28 @@ +(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const o of document.querySelectorAll('link[rel="modulepreload"]'))s(o);new MutationObserver(o=>{for(const l of o)if(l.type==="childList")for(const a of l.addedNodes)a.tagName==="LINK"&&a.rel==="modulepreload"&&s(a)}).observe(document,{childList:!0,subtree:!0});function n(o){const l={};return o.integrity&&(l.integrity=o.integrity),o.referrerPolicy&&(l.referrerPolicy=o.referrerPolicy),o.crossOrigin==="use-credentials"?l.credentials="include":o.crossOrigin==="anonymous"?l.credentials="omit":l.credentials="same-origin",l}function s(o){if(o.ep)return;o.ep=!0;const l=n(o);fetch(o.href,l)}})();function Ro(e){const t=Object.create(null);for(const n of e.split(","))t[n]=1;return n=>n in t}const ke={},on=[],$t=()=>{},ol=()=>!1,Ms=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&(e.charCodeAt(2)>122||e.charCodeAt(2)<97),Ls=e=>e.startsWith("onUpdate:"),De=Object.assign,Ho=(e,t)=>{const n=e.indexOf(t);n>-1&&e.splice(n,1)},La=Object.prototype.hasOwnProperty,me=(e,t)=>La.call(e,t),se=Array.isArray,Yt=e=>ts(e)==="[object Map]",Dt=e=>ts(e)==="[object Set]",ci=e=>ts(e)==="[object Date]",re=e=>typeof e=="function",Te=e=>typeof e=="string",xt=e=>typeof e=="symbol",we=e=>e!==null&&typeof e=="object",il=e=>(we(e)||re(e))&&re(e.then)&&re(e.catch),ll=Object.prototype.toString,ts=e=>ll.call(e),Da=e=>ts(e).slice(8,-1),al=e=>ts(e)==="[object Object]",Uo=e=>Te(e)&&e!=="NaN"&&e[0]!=="-"&&""+parseInt(e,10)===e,Rn=Ro(",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted"),Ds=e=>{const t=Object.create(null);return(n=>t[n]||(t[n]=e(n)))},Fa=/-\w/g,Ve=Ds(e=>e.replace(Fa,t=>t.slice(1).toUpperCase())),Na=/\B([A-Z])/g,Qt=Ds(e=>e.replace(Na,"-$1").toLowerCase()),Fs=Ds(e=>e.charAt(0).toUpperCase()+e.slice(1)),Qs=Ds(e=>e?`on${Fs(e)}`:""),kt=(e,t)=>!Object.is(e,t),ps=(e,...t)=>{for(let n=0;n{Object.defineProperty(e,t,{configurable:!0,enumerable:!1,writable:s,value:n})},Ns=e=>{const t=parseFloat(e);return isNaN(t)?e:t};let di;const Rs=()=>di||(di=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{});function Pe(e){if(se(e)){const t={};for(let n=0;nn.startsWith("/*")?"":n).split(Ra).forEach(n=>{if(n){const s=n.split(Ha);s.length>1&&(t[s[0].trim()]=s[1].trim())}}),t}function ue(e){let t="";if(Te(e))t=e;else if(se(e))for(let n=0;nut(n,t))}const cl=e=>!!(e&&e.__v_isRef===!0),y=e=>Te(e)?e:e==null?"":se(e)||we(e)&&(e.toString===ll||!re(e.toString))?cl(e)?y(e.value):JSON.stringify(e,dl,2):String(e),dl=(e,t)=>cl(t)?dl(e,t.value):Yt(t)?{[`Map(${t.size})`]:[...t.entries()].reduce((n,[s,o],l)=>(n[Zs(s,l)+" =>"]=o,n),{})}:Dt(t)?{[`Set(${t.size})`]:[...t.values()].map(n=>Zs(n))}:xt(t)?Zs(t):we(t)&&!se(t)&&!al(t)?String(t):t,Zs=(e,t="")=>{var n;return xt(e)?`Symbol(${(n=e.description)!=null?n:t})`:e};let Le;class qa{constructor(t=!1){this.detached=t,this._active=!0,this._on=0,this.effects=[],this.cleanups=[],this._isPaused=!1,this._warnOnRun=!0,this.__v_skip=!0,!t&&Le&&(Le.active?(this.parent=Le,this.index=(Le.scopes||(Le.scopes=[])).push(this)-1):(this._active=!1,this._warnOnRun=!1))}get active(){return this._active}pause(){if(this._active){this._isPaused=!0;let t,n;if(this.scopes){const s=this.scopes.slice();for(t=0,n=s.length;t0&&--this._on===0){if(Le===this)Le=this.prevScope;else{let t=Le;for(;t;){if(t.prevScope===this){t.prevScope=this.prevScope;break}t=t.prevScope}}this.prevScope=void 0}}stop(t){if(this._active){this._active=!1;let n,s;for(n=0,s=this.effects.length;n0)return;if(Un){let t=Un;for(Un=void 0;t;){const n=t.next;t.next=void 0,t.flags&=-9,t=n}}let e;for(;Hn;){let t=Hn;for(Hn=void 0;t;){const n=t.next;if(t.next=void 0,t.flags&=-9,t.flags&1)try{t.trigger()}catch(s){e||(e=s)}t=n}}if(e)throw e}function vl(e){for(let t=e.deps;t;t=t.nextDep)t.version=-1,t.prevActiveLink=t.dep.activeLink,t.dep.activeLink=t}function ml(e){let t,n=e.depsTail,s=n;for(;s;){const o=s.prevDep;s.version===-1?(s===n&&(n=o),Wo(s),za(s)):t=s,s.dep.activeLink=s.prevActiveLink,s.prevActiveLink=void 0,s=o}e.deps=t,e.depsTail=n}function go(e){for(let t=e.deps;t;t=t.nextDep)if(t.dep.version!==t.version||t.dep.computed&&(yl(t.dep.computed)||t.dep.version!==t.version))return!0;return!!e._dirty}function yl(e){if(e.flags&4&&!(e.flags&16)||(e.flags&=-17,e.globalVersion===Kn)||(e.globalVersion=Kn,!e.isSSR&&e.flags&128&&(!e.deps&&!e._dirty||!go(e))))return;e.flags|=2;const t=e.dep,n=xe,s=rt;xe=e,rt=!0;try{vl(e);const o=e.fn(e._value);(t.version===0||kt(o,e._value))&&(e.flags|=128,e._value=o,t.version++)}catch(o){throw t.version++,o}finally{xe=n,rt=s,ml(e),e.flags&=-3}}function Wo(e,t=!1){const{dep:n,prevSub:s,nextSub:o}=e;if(s&&(s.nextSub=o,e.prevSub=void 0),o&&(o.prevSub=s,e.nextSub=void 0),n.subs===e&&(n.subs=s,!s&&n.computed)){n.computed.flags&=-5;for(let l=n.computed.deps;l;l=l.nextDep)Wo(l,!0)}!t&&!--n.sc&&n.map&&n.map.delete(n.key)}function za(e){const{prevDep:t,nextDep:n}=e;t&&(t.nextDep=n,e.prevDep=void 0),n&&(n.prevDep=t,e.nextDep=void 0)}let rt=!0;const gl=[];function Ft(){gl.push(rt),rt=!1}function Nt(){const e=gl.pop();rt=e===void 0?!0:e}function hi(e){const{cleanup:t}=e;if(e.cleanup=void 0,t){const n=xe;xe=void 0;try{t()}finally{xe=n}}}let Kn=0;class Ja{constructor(t,n){this.sub=t,this.dep=n,this.version=n.version,this.nextDep=this.prevDep=this.nextSub=this.prevSub=this.prevActiveLink=void 0}}class Ko{constructor(t){this.computed=t,this.version=0,this.activeLink=void 0,this.subs=void 0,this.map=void 0,this.key=void 0,this.sc=0,this.__v_skip=!0}track(t){if(!xe||!rt||xe===this.computed)return;let n=this.activeLink;if(n===void 0||n.sub!==xe)n=this.activeLink=new Ja(xe,this),xe.deps?(n.prevDep=xe.depsTail,xe.depsTail.nextDep=n,xe.depsTail=n):xe.deps=xe.depsTail=n,bl(n);else if(n.version===-1&&(n.version=this.version,n.nextDep)){const s=n.nextDep;s.prevDep=n.prevDep,n.prevDep&&(n.prevDep.nextDep=s),n.prevDep=xe.depsTail,n.nextDep=void 0,xe.depsTail.nextDep=n,xe.depsTail=n,xe.deps===n&&(xe.deps=s)}return n}trigger(t){this.version++,Kn++,this.notify(t)}notify(t){Bo();try{for(let n=this.subs;n;n=n.prevSub)n.sub.notify()&&n.sub.dep.notify()}finally{Vo()}}}function bl(e){if(e.dep.sc++,e.sub.flags&4){const t=e.dep.computed;if(t&&!e.dep.subs){t.flags|=20;for(let s=t.deps;s;s=s.nextDep)bl(s)}const n=e.dep.subs;n!==e&&(e.prevSub=n,n&&(n.nextSub=e)),e.dep.subs=e}}const bo=new WeakMap,ln=Symbol(""),wo=Symbol(""),qn=Symbol("");function Fe(e,t,n){if(rt&&xe){let s=bo.get(e);s||bo.set(e,s=new Map);let o=s.get(n);o||(s.set(n,o=new Ko),o.map=s,o.key=n),o.track()}}function Ot(e,t,n,s,o,l){const a=bo.get(e);if(!a){Kn++;return}const r=d=>{d&&d.trigger()};if(Bo(),t==="clear")a.forEach(r);else{const d=se(e),u=d&&Uo(n);if(d&&n==="length"){const f=Number(s);a.forEach((p,_)=>{(_==="length"||_===qn||!xt(_)&&_>=f)&&r(p)})}else switch((n!==void 0||a.has(void 0))&&r(a.get(n)),u&&r(a.get(qn)),t){case"add":d?u&&r(a.get("length")):(r(a.get(ln)),Yt(e)&&r(a.get(wo)));break;case"delete":d||(r(a.get(ln)),Yt(e)&&r(a.get(wo)));break;case"set":Yt(e)&&r(a.get(ln));break}}Vo()}function vn(e){const t=ve(e);return t===e||(Fe(t,"iterate",qn),nt(e))?t:St(e)?zt(e)?t.map(n=>Jt(ot(n))):t.map(Jt):t.map(ot)}function Hs(e){return Fe(e=ve(e),"iterate",qn),e}function wt(e,t){return St(e)?Jt(zt(e)?ot(t):t):ot(t)}const Ga={__proto__:null,[Symbol.iterator](){return to(this,Symbol.iterator,e=>wt(this,e))},concat(...e){return vn(this).concat(...e.map(t=>se(t)?vn(t):t))},entries(){return to(this,"entries",e=>(e[1]=wt(this,e[1]),e))},every(e,t){return At(this,"every",e,t,void 0,arguments)},filter(e,t){return At(this,"filter",e,t,n=>n.map(s=>wt(this,s)),arguments)},find(e,t){return At(this,"find",e,t,n=>wt(this,n),arguments)},findIndex(e,t){return At(this,"findIndex",e,t,void 0,arguments)},findLast(e,t){return At(this,"findLast",e,t,n=>wt(this,n),arguments)},findLastIndex(e,t){return At(this,"findLastIndex",e,t,void 0,arguments)},forEach(e,t){return At(this,"forEach",e,t,void 0,arguments)},includes(...e){return no(this,"includes",e)},indexOf(...e){return no(this,"indexOf",e)},join(e){return vn(this).join(e)},lastIndexOf(...e){return no(this,"lastIndexOf",e)},map(e,t){return At(this,"map",e,t,void 0,arguments)},pop(){return Pn(this,"pop")},push(...e){return Pn(this,"push",e)},reduce(e,...t){return vi(this,"reduce",e,t)},reduceRight(e,...t){return vi(this,"reduceRight",e,t)},shift(){return Pn(this,"shift")},some(e,t){return At(this,"some",e,t,void 0,arguments)},splice(...e){return Pn(this,"splice",e)},toReversed(){return vn(this).toReversed()},toSorted(e){return vn(this).toSorted(e)},toSpliced(...e){return vn(this).toSpliced(...e)},unshift(...e){return Pn(this,"unshift",e)},values(){return to(this,"values",e=>wt(this,e))}};function to(e,t,n){const s=Hs(e),o=s[t]();return s!==e&&!nt(e)&&(o._next=o.next,o.next=()=>{const l=o._next();return l.done||(l.value=n(l.value)),l}),o}const Xa=Array.prototype;function At(e,t,n,s,o,l){const a=Hs(e),r=a!==e&&!nt(e),d=a[t];if(d!==Xa[t]){const p=d.apply(e,l);return r?ot(p):p}let u=n;a!==e&&(r?u=function(p,_){return n.call(this,wt(e,p),_,e)}:n.length>2&&(u=function(p,_){return n.call(this,p,_,e)}));const f=d.call(a,u,s);return r&&o?o(f):f}function vi(e,t,n,s){const o=Hs(e),l=o!==e&&!nt(e);let a=n,r=!1;o!==e&&(l?(r=s.length===0,a=function(u,f,p){return r&&(r=!1,u=wt(e,u)),n.call(this,u,wt(e,f),p,e)}):n.length>3&&(a=function(u,f,p){return n.call(this,u,f,p,e)}));const d=o[t](a,...s);return r?wt(e,d):d}function no(e,t,n){const s=ve(e);Fe(s,"iterate",qn);const o=s[t](...n);return(o===-1||o===!1)&&zo(n[0])?(n[0]=ve(n[0]),s[t](...n)):o}function Pn(e,t,n=[]){Ft(),Bo();const s=ve(e)[t].apply(e,n);return Vo(),Nt(),s}const Qa=Ro("__proto__,__v_isRef,__isVue"),wl=new Set(Object.getOwnPropertyNames(Symbol).filter(e=>e!=="arguments"&&e!=="caller").map(e=>Symbol[e]).filter(xt));function Za(e){xt(e)||(e=String(e));const t=ve(this);return Fe(t,"has",e),t.hasOwnProperty(e)}class _l{constructor(t=!1,n=!1){this._isReadonly=t,this._isShallow=n}get(t,n,s){if(n==="__v_skip")return t.__v_skip;const o=this._isReadonly,l=this._isShallow;if(n==="__v_isReactive")return!o;if(n==="__v_isReadonly")return o;if(n==="__v_isShallow")return l;if(n==="__v_raw")return s===(o?l?ur:Sl:l?xl:$l).get(t)||Object.getPrototypeOf(t)===Object.getPrototypeOf(s)?t:void 0;const a=se(t);if(!o){let d;if(a&&(d=Ga[n]))return d;if(n==="hasOwnProperty")return Za}const r=Reflect.get(t,n,He(t)?t:s);if((xt(n)?wl.has(n):Qa(n))||(o||Fe(t,"get",n),l))return r;if(He(r)){const d=a&&Uo(n)?r:r.value;return o&&we(d)?ko(d):d}return we(r)?o?ko(r):fn(r):r}}class kl extends _l{constructor(t=!1){super(!1,t)}set(t,n,s,o){let l=t[n];const a=se(t)&&Uo(n);if(!this._isShallow){const u=St(l);if(!nt(s)&&!St(s)&&(l=ve(l),s=ve(s)),!a&&He(l)&&!He(s))return u||(l.value=s),!0}const r=a?Number(n)e,rs=e=>Reflect.getPrototypeOf(e);function or(e,t,n){return function(...s){const o=this.__v_raw,l=ve(o),a=Yt(l),r=e==="entries"||e===Symbol.iterator&&a,d=e==="keys"&&a,u=o[e](...s),f=n?_o:t?Jt:ot;return!t&&Fe(l,"iterate",d?wo:ln),De(Object.create(u),{next(){const{value:p,done:_}=u.next();return _?{value:p,done:_}:{value:r?[f(p[0]),f(p[1])]:f(p),done:_}}})}}function us(e){return function(...t){return e==="delete"?!1:e==="clear"?void 0:this}}function ir(e,t){const n={get(o){const l=this.__v_raw,a=ve(l),r=ve(o);e||(kt(o,r)&&Fe(a,"get",o),Fe(a,"get",r));const{has:d}=rs(a),u=t?_o:e?Jt:ot;if(d.call(a,o))return u(l.get(o));if(d.call(a,r))return u(l.get(r));l!==a&&l.get(o)},get size(){const o=this.__v_raw;return!e&&Fe(ve(o),"iterate",ln),o.size},has(o){const l=this.__v_raw,a=ve(l),r=ve(o);return e||(kt(o,r)&&Fe(a,"has",o),Fe(a,"has",r)),o===r?l.has(o):l.has(o)||l.has(r)},forEach(o,l){const a=this,r=a.__v_raw,d=ve(r),u=t?_o:e?Jt:ot;return!e&&Fe(d,"iterate",ln),r.forEach((f,p)=>o.call(l,u(f),u(p),a))}};return De(n,e?{add:us("add"),set:us("set"),delete:us("delete"),clear:us("clear")}:{add(o){const l=ve(this),a=rs(l),r=ve(o),d=!t&&!nt(o)&&!St(o)?r:o;return a.has.call(l,d)||kt(o,d)&&a.has.call(l,o)||kt(r,d)&&a.has.call(l,r)||(l.add(d),Ot(l,"add",d,d)),this},set(o,l){!t&&!nt(l)&&!St(l)&&(l=ve(l));const a=ve(this),{has:r,get:d}=rs(a);let u=r.call(a,o);u||(o=ve(o),u=r.call(a,o));const f=d.call(a,o);return a.set(o,l),u?kt(l,f)&&Ot(a,"set",o,l):Ot(a,"add",o,l),this},delete(o){const l=ve(this),{has:a,get:r}=rs(l);let d=a.call(l,o);d||(o=ve(o),d=a.call(l,o)),r&&r.call(l,o);const u=l.delete(o);return d&&Ot(l,"delete",o,void 0),u},clear(){const o=ve(this),l=o.size!==0,a=o.clear();return l&&Ot(o,"clear",void 0,void 0),a}}),["keys","values","entries",Symbol.iterator].forEach(o=>{n[o]=or(o,e,t)}),n}function qo(e,t){const n=ir(e,t);return(s,o,l)=>o==="__v_isReactive"?!e:o==="__v_isReadonly"?e:o==="__v_raw"?s:Reflect.get(me(n,o)&&o in s?n:s,o,l)}const lr={get:qo(!1,!1)},ar={get:qo(!1,!0)},rr={get:qo(!0,!1)};const $l=new WeakMap,xl=new WeakMap,Sl=new WeakMap,ur=new WeakMap;function cr(e){switch(e){case"Object":case"Array":return 1;case"Map":case"Set":case"WeakMap":case"WeakSet":return 2;default:return 0}}function fn(e){return St(e)?e:Yo(e,!1,tr,lr,$l)}function dr(e){return Yo(e,!1,sr,ar,xl)}function ko(e){return Yo(e,!0,nr,rr,Sl)}function Yo(e,t,n,s,o){if(!we(e)||e.__v_raw&&!(t&&e.__v_isReactive)||e.__v_skip||!Object.isExtensible(e))return e;const l=o.get(e);if(l)return l;const a=cr(Da(e));if(a===0)return e;const r=new Proxy(e,a===2?s:n);return o.set(e,r),r}function zt(e){return St(e)?zt(e.__v_raw):!!(e&&e.__v_isReactive)}function St(e){return!!(e&&e.__v_isReadonly)}function nt(e){return!!(e&&e.__v_isShallow)}function zo(e){return e?!!e.__v_raw:!1}function ve(e){const t=e&&e.__v_raw;return t?ve(t):e}function fr(e){return!me(e,"__v_skip")&&Object.isExtensible(e)&&rl(e,"__v_skip",!0),e}const ot=e=>we(e)?fn(e):e,Jt=e=>we(e)?ko(e):e;function He(e){return e?e.__v_isRef===!0:!1}function fe(e){return pr(e,!1)}function pr(e,t){return He(e)?e:new hr(e,t)}class hr{constructor(t,n){this.dep=new Ko,this.__v_isRef=!0,this.__v_isShallow=!1,this._rawValue=n?t:ve(t),this._value=n?t:ot(t),this.__v_isShallow=n}get value(){return this.dep.track(),this._value}set value(t){const n=this._rawValue,s=this.__v_isShallow||nt(t)||St(t);t=s?t:ve(t),kt(t,n)&&(this._rawValue=t,this._value=s?t:ot(t),this.dep.trigger())}}function v(e){return He(e)?e.value:e}const vr={get:(e,t,n)=>t==="__v_raw"?e:v(Reflect.get(e,t,n)),set:(e,t,n,s)=>{const o=e[t];return He(o)&&!He(n)?(o.value=n,!0):Reflect.set(e,t,n,s)}};function Cl(e){return zt(e)?e:new Proxy(e,vr)}class mr{constructor(t,n,s){this.fn=t,this.setter=n,this._value=void 0,this.dep=new Ko(this),this.__v_isRef=!0,this.deps=void 0,this.depsTail=void 0,this.flags=16,this.globalVersion=Kn-1,this.next=void 0,this.effect=this,this.__v_isReadonly=!n,this.isSSR=s}notify(){if(this.flags|=16,!(this.flags&8)&&xe!==this)return hl(this,!0),!0}get value(){const t=this.dep.track();return yl(this),t&&(t.version=this.dep.version),this._value}set value(t){this.setter&&this.setter(t)}}function yr(e,t,n=!1){let s,o;return re(e)?s=e:(s=e.get,o=e.set),new mr(s,o,n)}const cs={},ws=new WeakMap;let nn;function gr(e,t=!1,n=nn){if(n){let s=ws.get(n);s||ws.set(n,s=[]),s.push(e)}}function br(e,t,n=ke){const{immediate:s,deep:o,once:l,scheduler:a,augmentJob:r,call:d}=n,u=C=>o?C:nt(C)||o===!1||o===0?It(C,1):It(C);let f,p,_,T,M=!1,I=!1;if(He(e)?(p=()=>e.value,M=nt(e)):zt(e)?(p=()=>u(e),M=!0):se(e)?(I=!0,M=e.some(C=>zt(C)||nt(C)),p=()=>e.map(C=>{if(He(C))return C.value;if(zt(C))return u(C);if(re(C))return d?d(C,2):C()})):re(e)?t?p=d?()=>d(e,2):e:p=()=>{if(_){Ft();try{_()}finally{Nt()}}const C=nn;nn=f;try{return d?d(e,3,[T]):e(T)}finally{nn=C}}:p=$t,t&&o){const C=p,z=o===!0?1/0:o;p=()=>It(C(),z)}const $=Ya(),x=()=>{f.stop(),$&&$.active&&Ho($.effects,f)};if(l&&t){const C=t;t=(...z)=>{const P=C(...z);return x(),P}}let O=I?new Array(e.length).fill(cs):cs;const J=C=>{if(!(!(f.flags&1)||!f.dirty&&!C))if(t){const z=f.run();if(C||o||M||(I?z.some((P,S)=>kt(P,O[S])):kt(z,O))){_&&_();const P=nn;nn=f;try{const S=[z,O===cs?void 0:I&&O[0]===cs?[]:O,T];O=z,d?d(t,3,S):t(...S)}finally{nn=P}}}else f.run()};return r&&r(J),f=new fl(p),f.scheduler=a?()=>a(J,!1):J,T=C=>gr(C,!1,f),_=f.onStop=()=>{const C=ws.get(f);if(C){if(d)d(C,4);else for(const z of C)z();ws.delete(f)}},t?s?J(!0):O=f.run():a?a(J.bind(null,!0),!0):f.run(),x.pause=f.pause.bind(f),x.resume=f.resume.bind(f),x.stop=x,x}function It(e,t=1/0,n){if(t<=0||!we(e)||e.__v_skip||(n=n||new Map,(n.get(e)||0)>=t))return e;if(n.set(e,t),t--,He(e))It(e.value,t,n);else if(se(e))for(let s=0;s{It(s,t,n)});else if(al(e)){for(const s in e)It(e[s],t,n);for(const s of Object.getOwnPropertySymbols(e))Object.prototype.propertyIsEnumerable.call(e,s)&&It(e[s],t,n)}return e}function ns(e,t,n,s){try{return s?e(...s):e()}catch(o){Us(o,t,n)}}function ct(e,t,n,s){if(re(e)){const o=ns(e,t,n,s);return o&&il(o)&&o.catch(l=>{Us(l,t,n)}),o}if(se(e)){const o=[];for(let l=0;l>>1,o=Be[s],l=Yn(o);l=Yn(n)?Be.push(e):Be.splice(_r(t),0,e),e.flags|=1,Tl()}}function Tl(){_s||(_s=Al.then(Pl))}function kr(e){if(!se(e))Wt&&e.id===-1?Wt.splice(mn+1,0,e):e.flags&1||(gn.push(e),e.flags|=1);else for(let t=0;tYn(n)-Yn(s));if(gn.length=0,Wt){for(let n=0;ne.id==null?e.flags&2?-1:1/0:e.id;function Pl(e){try{for(gt=0;gt{s._d&&Ti(-1);const l=ks(t),a=rn.length;let r;try{r=e(...o)}finally{for(let d=rn.length;d>a;d--)na();ks(l),s._d&&Ti(1)}return r};return s._n=!0,s._c=!0,s._d=!0,s}function ye(e,t){if(ze===null)return e;const n=qs(ze),s=e.dirs||(e.dirs=[]);for(let o=0;o1)return n&&re(t)?t.call(s&&s.proxy):t}}const Sr=Symbol.for("v-scx"),Cr=()=>hs(Sr);function an(e,t,n){return Il(e,t,n)}function Il(e,t,n=ke){const{immediate:s,deep:o,flush:l,once:a}=n,r=De({},n),d=t&&s||!t&&l!=="post";let u;if(Gn){if(l==="sync"){const T=Cr();u=T.__watcherHandles||(T.__watcherHandles=[])}else if(!d){const T=()=>{};return T.stop=$t,T.resume=$t,T.pause=$t,T}}const f=Ne;r.call=(T,M,I)=>ct(T,f,M,I);let p=!1;l==="post"?r.scheduler=T=>{We(T,f&&f.suspense)}:l!=="sync"&&(p=!0,r.scheduler=(T,M)=>{M?T():Jo(T)}),r.augmentJob=T=>{t&&(T.flags|=4),p&&(T.flags|=2,f&&(T.id=f.uid,T.i=f))};const _=br(e,t,r);return Gn&&(u?u.push(_):d&&_()),_}function Ar(e,t,n){const s=this.proxy,o=Te(e)?e.includes(".")?Ml(s,e):()=>s[e]:e.bind(s,s);let l;re(t)?l=t:(l=t.handler,n=t);const a=ss(this),r=Il(o,l.bind(s),n);return a(),r}function Ml(e,t){const n=t.split(".");return()=>{let s=e;for(let o=0;oe.__isTeleport,so=Symbol("_leaveCb");function Er(e){let t=e[0];if(e.length>1){for(const n of e)if(n.type!==Rt){t=n;break}}return t}function Ll(e){if(!Xo(e))return Bs(e.type)&&e.children?Er(e.children):e;if(e.component)return e.component.subTree;const{shapeFlag:t,children:n}=e;if(n){if(t&16)return n[0];if(t&32&&re(n.default))return n.default()}}function Go(e,t){if(e.shapeFlag&6&&e.component){e.transition=t;const n=e.component.subTree;Go(Bs(n.type)&&Ll(n)||n,t)}else e.shapeFlag&128?(e.ssContent.transition=t.clone(e.ssContent),e.ssFallback.transition=t.clone(e.ssFallback)):e.transition=t}function Ce(e,t){return re(e)?De({name:e.name},t,{setup:e}):e}function Dl(e){e.ids=[e.ids[0]+e.ids[2]+++"-",0,0]}function yi(e,t){let n;return!!((n=Object.getOwnPropertyDescriptor(e,t))&&!n.configurable)}const $s=new WeakMap;function jn(e,t,n,s,o=!1){if(se(e)){e.forEach((I,$)=>jn(I,t&&(se(t)?t[$]:t),n,s,o));return}if(Bn(s)&&!o){s.shapeFlag&512&&s.type.__asyncResolved&&s.component.subTree.component&&jn(e,t,n,s.component.subTree);return}const l=s.shapeFlag&4?qs(s.component):s.el,a=o?null:l,{i:r,r:d}=e,u=t&&t.r,f=r.refs===ke?r.refs={}:r.refs,p=r.setupState,_=ve(p),T=p===ke?ol:I=>yi(f,I)?!1:me(_,I),M=(I,$)=>!($&&yi(f,$));if(u!=null&&u!==d){if(gi(t),Te(u))f[u]=null,T(u)&&(p[u]=null);else if(He(u)){const I=t;M(u,I.k)&&(u.value=null),I.k&&(f[I.k]=null)}}if(re(d))ns(d,r,12,[a,f]);else{const I=Te(d),$=He(d);if(I||$){const x=()=>{if(e.f){const O=I?T(d)?p[d]:f[d]:M()||!e.k?d.value:f[e.k];if(o)se(O)&&Ho(O,l);else if(se(O))O.includes(l)||O.push(l);else if(I)f[d]=[l],T(d)&&(p[d]=f[d]);else{const J=[l];M(d,e.k)&&(d.value=J),e.k&&(f[e.k]=J)}}else I?(f[d]=a,T(d)&&(p[d]=a)):$&&(M(d,e.k)&&(d.value=a),e.k&&(f[e.k]=a))};if(a){const O=()=>{x(),$s.delete(e)};O.id=-1,$s.set(e,O),We(O,n)}else gi(e),x()}}}function gi(e){const t=$s.get(e);t&&(t.flags|=8,$s.delete(e))}Rs().requestIdleCallback;Rs().cancelIdleCallback;const Bn=e=>!!e.type.__asyncLoader,Xo=e=>e.type.__isKeepAlive;function Pr(e,t){Fl(e,"a",t)}function Or(e,t){Fl(e,"da",t)}function Fl(e,t,n=Ne){const s=e.__wdc||(e.__wdc=()=>{let o=n;for(;o;){if(o.isDeactivated)return;o=o.parent}return e()});if(Vs(t,s,n),n){let o=n.parent;for(;o&&o.parent;)Xo(o.parent.vnode)&&Ir(s,t,n,o),o=o.parent}}function Ir(e,t,n,s){const o=Vs(t,e,s,!0);Nl(()=>{Ho(s[t],o)},n)}function Vs(e,t,n=Ne,s=!1){if(n){const o=n[e]||(n[e]=[]),l=t.__weh||(t.__weh=(...a)=>{Ft();const r=ss(n),d=ct(t,n,e,a);return r(),Nt(),d});return s?o.unshift(l):o.push(l),l}}const Ut=e=>(t,n=Ne)=>{(!Gn||e==="sp")&&Vs(e,(...s)=>t(...s),n)},Mr=Ut("bm"),hn=Ut("m"),Lr=Ut("bu"),Dr=Ut("u"),An=Ut("bum"),Nl=Ut("um"),Fr=Ut("sp"),Nr=Ut("rtg"),Rr=Ut("rtc");function Hr(e,t=Ne){Vs("ec",e,t)}const Ur="components",Rl=Symbol.for("v-ndc");function jr(e){return Te(e)?Br(Ur,e,!1)||e:e||Rl}function Br(e,t,n=!0,s=!1){const o=ze||Ne;if(o){const l=o.type;{const r=Cu(l,!1);if(r&&(r===t||r===Ve(t)||r===Fs(Ve(t))))return l}const a=bi(o[e]||l[e],t)||bi(o.appContext[e],t);return!a&&s?l:a}}function bi(e,t){return e&&(e[t]||e[Ve(t)]||e[Fs(Ve(t))])}function ie(e,t,n,s){let o;const l=n,a=se(e);if(a||Te(e)){const r=a&&zt(e);let d=!1,u=!1;r&&(d=!nt(e),u=St(e),e=Hs(e)),o=new Array(e.length);for(let f=0,p=e.length;ft(r,d,void 0,l));else{const r=Object.keys(e);o=new Array(r.length);for(let d=0,u=r.length;de?la(e)?qs(e):$o(e.parent):null,Vn=De(Object.create(null),{$:e=>e,$el:e=>e.vnode.el,$data:e=>e.data,$props:e=>e.props,$attrs:e=>e.attrs,$slots:e=>e.slots,$refs:e=>e.refs,$parent:e=>$o(e.parent),$root:e=>$o(e.root),$host:e=>e.ce,$emit:e=>e.emit,$options:e=>Ul(e),$forceUpdate:e=>e.f||(e.f=()=>{Jo(e.update)}),$nextTick:e=>e.n||(e.n=js.bind(e.proxy)),$watch:e=>Ar.bind(e)}),oo=(e,t)=>e!==ke&&!e.__isScriptSetup&&me(e,t),Vr={get({_:e},t){if(t==="__v_skip")return!0;const{ctx:n,setupState:s,data:o,props:l,accessCache:a,type:r,appContext:d}=e;if(t[0]!=="$"){const _=a[t];if(_!==void 0)switch(_){case 1:return s[t];case 2:return o[t];case 4:return n[t];case 3:return l[t]}else{if(oo(s,t))return a[t]=1,s[t];if(o!==ke&&me(o,t))return a[t]=2,o[t];if(me(l,t))return a[t]=3,l[t];if(n!==ke&&me(n,t))return a[t]=4,n[t];xo&&(a[t]=0)}}const u=Vn[t];let f,p;if(u)return t==="$attrs"&&Fe(e.attrs,"get",""),u(e);if((f=r.__cssModules)&&(f=f[t]))return f;if(n!==ke&&me(n,t))return a[t]=4,n[t];if(p=d.config.globalProperties,me(p,t))return p[t]},set({_:e},t,n){const{data:s,setupState:o,ctx:l}=e;return oo(o,t)?(o[t]=n,!0):s!==ke&&me(s,t)?(s[t]=n,!0):me(e.props,t)||t[0]==="$"&&t.slice(1)in e?!1:(l[t]=n,!0)},has({_:{data:e,setupState:t,accessCache:n,ctx:s,appContext:o,props:l,type:a}},r){let d;return!!(n[r]||e!==ke&&r[0]!=="$"&&me(e,r)||oo(t,r)||me(l,r)||me(s,r)||me(Vn,r)||me(o.config.globalProperties,r)||(d=a.__cssModules)&&d[r])},defineProperty(e,t,n){return n.get!=null?e._.accessCache[t]=0:me(n,"value")&&this.set(e,t,n.value,null),Reflect.defineProperty(e,t,n)}};function wi(e){return se(e)?e.reduce((t,n)=>(t[n]=null,t),{}):e}let xo=!0;function Wr(e){const t=Ul(e),n=e.proxy,s=e.ctx;xo=!1,t.beforeCreate&&_i(t.beforeCreate,e,"bc");const{data:o,computed:l,methods:a,watch:r,provide:d,inject:u,created:f,beforeMount:p,mounted:_,beforeUpdate:T,updated:M,activated:I,deactivated:$,beforeDestroy:x,beforeUnmount:O,destroyed:J,unmounted:C,render:z,renderTracked:P,renderTriggered:S,errorCaptured:b,serverPrefetch:A,expose:q,inheritAttrs:W,components:le,directives:Z,filters:B}=t;if(u&&Kr(u,s,null),a)for(const V in a){const Q=a[V];re(Q)&&(s[V]=Q.bind(n))}if(o){const V=o.call(n,n);we(V)&&(e.data=fn(V))}if(xo=!0,l)for(const V in l){const Q=l[V],Ee=re(Q)?Q.bind(n,n):re(Q.get)?Q.get.bind(n,n):$t,pt=!re(Q)&&re(Q.set)?Q.set.bind(n):$t,Ze=k({get:Ee,set:pt});Object.defineProperty(s,V,{enumerable:!0,configurable:!0,get:()=>Ze.value,set:qe=>Ze.value=qe})}if(r)for(const V in r)Hl(r[V],s,n,V);if(d){const V=re(d)?d.call(n):d;Reflect.ownKeys(V).forEach(Q=>{xr(Q,V[Q])})}f&&_i(f,e,"c");function ce(V,Q){se(Q)?Q.forEach(Ee=>V(Ee.bind(n))):Q&&V(Q.bind(n))}if(ce(Mr,p),ce(hn,_),ce(Lr,T),ce(Dr,M),ce(Pr,I),ce(Or,$),ce(Hr,b),ce(Rr,P),ce(Nr,S),ce(An,O),ce(Nl,C),ce(Fr,A),se(q))if(q.length){const V=e.exposed||(e.exposed={});q.forEach(Q=>{Object.defineProperty(V,Q,{get:()=>n[Q],set:Ee=>n[Q]=Ee,enumerable:!0})})}else e.exposed||(e.exposed={});z&&e.render===$t&&(e.render=z),W!=null&&(e.inheritAttrs=W),le&&(e.components=le),Z&&(e.directives=Z),A&&Dl(e)}function Kr(e,t,n=$t){se(e)&&(e=So(e));for(const s in e){const o=e[s];let l;we(o)?"default"in o?l=hs(o.from||s,o.default,!0):l=hs(o.from||s):l=hs(o),He(l)?Object.defineProperty(t,s,{enumerable:!0,configurable:!0,get:()=>l.value,set:a=>l.value=a}):t[s]=l}}function _i(e,t,n){ct(se(e)?e.map(s=>s.bind(t.proxy)):e.bind(t.proxy),t,n)}function Hl(e,t,n,s){let o=s.includes(".")?Ml(n,s):()=>n[s];if(Te(e)){const l=t[e];re(l)&&an(o,l)}else if(re(e))an(o,e.bind(n));else if(we(e))if(se(e))e.forEach(l=>Hl(l,t,n,s));else{const l=re(e.handler)?e.handler.bind(n):t[e.handler];re(l)&&an(o,l,e)}}function Ul(e){const t=e.type,{mixins:n,extends:s}=t,{mixins:o,optionsCache:l,config:{optionMergeStrategies:a}}=e.appContext,r=l.get(t);let d;return r?d=r:!o.length&&!n&&!s?d=t:(d={},o.length&&o.forEach(u=>xs(d,u,a,!0)),xs(d,t,a)),we(t)&&l.set(t,d),d}function xs(e,t,n,s=!1){const{mixins:o,extends:l}=t;l&&xs(e,l,n,!0),o&&o.forEach(a=>xs(e,a,n,!0));for(const a in t)if(!(s&&a==="expose")){const r=qr[a]||n&&n[a];e[a]=r?r(e[a],t[a]):t[a]}return e}const qr={data:ki,props:$i,emits:$i,methods:Mn,computed:Mn,beforeCreate:Ue,created:Ue,beforeMount:Ue,mounted:Ue,beforeUpdate:Ue,updated:Ue,beforeDestroy:Ue,beforeUnmount:Ue,destroyed:Ue,unmounted:Ue,activated:Ue,deactivated:Ue,errorCaptured:Ue,serverPrefetch:Ue,components:Mn,directives:Mn,watch:zr,provide:ki,inject:Yr};function ki(e,t){return t?e?function(){return De(re(e)?e.call(this,this):e,re(t)?t.call(this,this):t)}:t:e}function Yr(e,t){return Mn(So(e),So(t))}function So(e){if(se(e)){const t={};for(let n=0;nt==="modelValue"||t==="model-value"?e.modelModifiers:e[`${t}Modifiers`]||e[`${Ve(t)}Modifiers`]||e[`${Qt(t)}Modifiers`];function Qr(e,t,...n){if(e.isUnmounted)return;const s=e.vnode.props||ke;let o=n;const l=t.startsWith("update:"),a=l&&Xr(s,t.slice(7));a&&(a.trim&&(o=n.map(f=>Te(f)?f.trim():f)),a.number&&(o=o.map(Ns)));let r,d=s[r=Qs(t)]||s[r=Qs(Ve(t))];!d&&l&&(d=s[r=Qs(Qt(t))]),d&&ct(d,e,6,o);const u=s[r+"Once"];if(u){if(!e.emitted)e.emitted={};else if(e.emitted[r])return;e.emitted[r]=!0,ct(u,e,6,o)}}const Zr=new WeakMap;function Bl(e,t,n=!1){const s=n?Zr:t.emitsCache,o=s.get(e);if(o!==void 0)return o;const l=e.emits;let a={},r=!1;if(!re(e)){const d=u=>{const f=Bl(u,t,!0);f&&(r=!0,De(a,f))};!n&&t.mixins.length&&t.mixins.forEach(d),e.extends&&d(e.extends),e.mixins&&e.mixins.forEach(d)}return!l&&!r?(we(e)&&s.set(e,null),null):(se(l)?l.forEach(d=>a[d]=null):De(a,l),we(e)&&s.set(e,a),a)}function Ws(e,t){return!e||!Ms(t)?!1:(t=t.slice(2),t=t==="Once"?t:t.replace(/Once$/,""),me(e,t[0].toLowerCase()+t.slice(1))||me(e,Qt(t))||me(e,t))}function xi(e){const{type:t,vnode:n,proxy:s,withProxy:o,propsOptions:[l],slots:a,attrs:r,emit:d,render:u,renderCache:f,props:p,data:_,setupState:T,ctx:M,inheritAttrs:I}=e,$=ks(e);let x,O;try{if(n.shapeFlag&4){const C=o||s,z=C;x=_t(u.call(z,C,f,p,T,_,M)),O=r}else{const C=t;x=_t(C.length>1?C(p,{attrs:r,slots:a,emit:d}):C(p,null)),O=t.props?r:eu(r)}}catch(C){rn.length=0,Us(C,e,1),x=$e(Rt)}let J=x;if(O&&I!==!1){const C=Object.keys(O),{shapeFlag:z}=J;C.length&&z&7&&(l&&C.some(Ls)&&(O=tu(O,l)),J=kn(J,O,!1,!0))}if(n.dirs&&(J=kn(J,null,!1,!0),J.dirs=J.dirs?J.dirs.concat(n.dirs):n.dirs),n.transition){const C=Bs(J.type)&&Ll(J)||J;Go(C,n.transition)}return x=J,ks($),x}const eu=e=>{let t;for(const n in e)(n==="class"||n==="style"||Ms(n))&&((t||(t={}))[n]=e[n]);return t},tu=(e,t)=>{const n={};for(const s in e)(!Ls(s)||!(s.slice(9)in t))&&(n[s]=e[s]);return n};function nu(e,t,n){const{props:s,children:o,component:l}=e,{props:a,children:r,patchFlag:d}=t,u=l.emitsOptions;if(t.dirs||t.transition)return!0;if(n&&d>=0){if(d&1024)return!0;if(d&16)return s?Si(s,a,u):!!a;if(d&8){const f=t.dynamicProps;for(let p=0;pObject.create(Wl),ql=e=>Object.getPrototypeOf(e)===Wl;function ou(e,t,n,s=!1){const o={},l=Kl();e.propsDefaults=Object.create(null),Yl(e,t,o,l);for(const a in e.propsOptions[0])a in o||(o[a]=void 0);n?e.props=s?o:dr(o):e.type.props?e.props=o:e.props=l,e.attrs=l}function iu(e,t,n,s){const{props:o,attrs:l,vnode:{patchFlag:a}}=e,r=ve(o),[d]=e.propsOptions;let u=!1;if((s||a>0)&&!(a&16)){if(a&8){const f=e.vnode.dynamicProps;for(let p=0;p{d=!0;const[_,T]=zl(p,t,!0);De(a,_),T&&r.push(...T)};!n&&t.mixins.length&&t.mixins.forEach(f),e.extends&&f(e.extends),e.mixins&&e.mixins.forEach(f)}if(!l&&!d)return we(e)&&s.set(e,on),on;if(se(l))for(let f=0;fe==="_"||e==="_ctx"||e==="$stable",Zo=e=>se(e)?e.map(_t):[_t(e)],au=(e,t,n)=>{if(t._n)return t;const s=$r((...o)=>Zo(t(...o)),n);return s._c=!1,s},Jl=(e,t,n)=>{const s=e._ctx;for(const o in e){if(Qo(o))continue;const l=e[o];if(re(l))t[o]=au(o,l,s);else if(l!=null){const a=Zo(l);t[o]=()=>a}}},Gl=(e,t)=>{const n=Zo(t);e.slots.default=()=>n},Xl=(e,t,n)=>{for(const s in t)(n||!Qo(s))&&(e[s]=t[s])},ru=(e,t,n)=>{const s=e.slots=Kl();if(e.vnode.shapeFlag&32){const o=t._;o?(Xl(s,t,n),n&&rl(s,"_",o,!0)):Jl(t,s)}else t&&Gl(e,t)},uu=(e,t,n)=>{const{vnode:s,slots:o}=e;let l=!0,a=ke;if(s.shapeFlag&32){const r=t._;r?n&&r===1?l=!1:Xl(o,t,n):(l=!t.$stable,Jl(t,o)),a=t}else t&&(Gl(e,t),a={default:1});if(l)for(const r in o)!Qo(r)&&a[r]==null&&delete o[r]},We=hu;function cu(e){return du(e)}function du(e,t){const n=Rs();n.__VUE__=!0;const{insert:s,remove:o,patchProp:l,createElement:a,createText:r,createComment:d,setText:u,setElementText:f,parentNode:p,nextSibling:_,setScopeId:T=$t,insertStaticContent:M}=e,I=(g,w,E,R=null,L=null,F=null,Y=void 0,K=null,j=!!w.dynamicChildren)=>{if(g===w)return;g&&!On(g,w)&&(R=de(g),qe(g,L,F,!0),g=null),w.patchFlag===-2&&(j=!1,w.dynamicChildren=null),w.dynamicChildren&&g&&g.dynamicChildren&&g.dynamicChildren.hasOnce&&(w.dynamicChildren===on&&(w.dynamicChildren=[]),w.dynamicChildren.hasOnce=!0);const{type:D,ref:ne,shapeFlag:G}=w;switch(D){case Ks:$(g,w,E,R);break;case Rt:x(g,w,E,R);break;case vs:g==null&&O(w,E,R,Y);break;case U:le(g,w,E,R,L,F,Y,K,j);break;default:G&1?z(g,w,E,R,L,F,Y,K,j):G&6?Z(g,w,E,R,L,F,Y,K,j):(G&64||G&128)&&D.process(g,w,E,R,L,F,Y,K,j,Zt)}ne!=null&&L?jn(ne,g&&g.ref,F,w||g,!w):ne==null&&g&&g.ref!=null&&jn(g.ref,null,F,g,!0)},$=(g,w,E,R)=>{if(g==null)s(w.el=r(w.children),E,R);else{const L=w.el=g.el;w.children!==g.children&&u(L,w.children)}},x=(g,w,E,R)=>{g==null?s(w.el=d(w.children||""),E,R):w.el=g.el},O=(g,w,E,R)=>{[g.el,g.anchor]=M(g.children,w,E,R,g.el,g.anchor)},J=({el:g,anchor:w},E,R)=>{let L;for(;g&&g!==w;)L=_(g),s(g,E,R),g=L;s(w,E,R)},C=({el:g,anchor:w})=>{let E;for(;g&&g!==w;)E=_(g),o(g),g=E;o(w)},z=(g,w,E,R,L,F,Y,K,j)=>{if(w.type==="svg"?Y="svg":w.type==="math"&&(Y="mathml"),g==null)P(w,E,R,L,F,Y,K,j);else{const D=g.el&&g.el._isVueCE?g.el:null;try{D&&D._beginPatch(),A(g,w,L,F,Y,K,j)}finally{D&&D._endPatch()}}},P=(g,w,E,R,L,F,Y,K)=>{let j,D;const{props:ne,shapeFlag:G,transition:te,dirs:ae}=g;if(j=g.el=a(g.type,F,ne&&ne.is,ne),G&8?f(j,g.children):G&16&&b(g.children,j,null,R,L,io(g,F),Y,K),ae&&en(g,null,R,"created"),S(j,g,g.scopeId,Y,R),ne){for(const _e in ne)_e!=="value"&&!Rn(_e)&&l(j,_e,null,ne[_e],F,R);"value"in ne&&l(j,"value",null,ne.value,F),(D=ne.onVnodeBeforeMount)&&yt(D,R,g)}ae&&en(g,null,R,"beforeMount");const he=fu(L,te);he&&te.beforeEnter(j),s(j,w,E),((D=ne&&ne.onVnodeMounted)||he||ae)&&We(()=>{D&&yt(D,R,g),he&&te.enter(j),ae&&en(g,null,R,"mounted")},L)},S=(g,w,E,R,L)=>{if(E&&T(g,E),R)for(let F=0;F{for(let D=j;D{const K=w.el=g.el;let{patchFlag:j,dynamicChildren:D,dirs:ne}=w;j|=g.patchFlag&16;const G=g.props||ke,te=w.props||ke;let ae;if(E&&tn(E,!1),(ae=te.onVnodeBeforeUpdate)&&yt(ae,E,w,g),ne&&en(w,g,E,"beforeUpdate"),E&&tn(E,!0),D&&(!g.dynamicChildren||g.dynamicChildren.length!==D.length)&&(j=0,Y=!1,D=null),(G.innerHTML&&te.innerHTML==null||G.textContent&&te.textContent==null)&&f(K,""),D?q(g.dynamicChildren,D,K,E,R,io(w,L),F):Y||Q(g,w,K,null,E,R,io(w,L),F,!1),j>0){if(j&16)W(K,G,te,E,L);else if(j&2&&G.class!==te.class&&l(K,"class",null,te.class,L),j&4&&l(K,"style",G.style,te.style,L),j&8){const he=w.dynamicProps;for(let _e=0;_e{ae&&yt(ae,E,w,g),ne&&en(w,g,E,"updated")},R)},q=(g,w,E,R,L,F,Y)=>{for(let K=0;K{if(w!==E){if(w!==ke)for(const F in w)!Rn(F)&&!(F in E)&&l(g,F,w[F],null,L,R);for(const F in E){if(Rn(F))continue;const Y=E[F],K=w[F];Y!==K&&F!=="value"&&l(g,F,K,Y,L,R)}"value"in E&&l(g,"value",w.value,E.value,L)}},le=(g,w,E,R,L,F,Y,K,j)=>{const D=w.el=g?g.el:r(""),ne=w.anchor=g?g.anchor:r("");let{patchFlag:G,dynamicChildren:te,slotScopeIds:ae}=w;ae&&(K=K?K.concat(ae):ae),g==null?(s(D,E,R),s(ne,E,R),b(w.children||[],E,ne,L,F,Y,K,j)):G>0&&G&64&&te&&g.dynamicChildren&&g.dynamicChildren.length===te.length?(q(g.dynamicChildren,te,E,L,F,Y,K),(w.key!=null||L&&w===L.subTree)&&Ql(g,w,!0)):Q(g,w,E,ne,L,F,Y,K,j)},Z=(g,w,E,R,L,F,Y,K,j)=>{w.slotScopeIds=K,g==null?w.shapeFlag&512?L.ctx.activate(w,E,R,Y,j):B(w,E,R,L,F,Y,j):X(g,w,j)},B=(g,w,E,R,L,F,Y)=>{const K=g.component=wu(g,R,L);if(Xo(g)&&(K.ctx.renderer=Zt),ku(K,!1,Y),K.asyncDep){if(L&&L.registerDep(K,ce,Y),!g.el){const j=K.subTree=$e(Rt);x(null,j,w,E),g.placeholder=j.el}}else ce(K,g,w,E,L,F,Y)},X=(g,w,E)=>{const R=w.component=g.component;if(nu(g,w,E))if(R.asyncDep&&!R.asyncResolved){w.el=g.el,V(R,w,E);return}else R.next=w,R.update();else w.el=g.el,R.vnode=w},ce=(g,w,E,R,L,F,Y)=>{const K=()=>{if(g.isMounted){let{next:G,bu:te,u:ae,parent:he,vnode:_e}=g;{const vt=Zl(g);if(vt){G&&(G.el=_e.el,V(g,G,Y)),vt.asyncDep.then(()=>{We(()=>{g.isUnmounted||D()},L)});return}}let ge=G,Oe;tn(g,!1),G?(G.el=_e.el,V(g,G,Y)):G=_e,te&&ps(te),(Oe=G.props&&G.props.onVnodeBeforeUpdate)&&yt(Oe,he,G,_e),tn(g,!0);const Me=xi(g),ht=g.subTree;g.subTree=Me,I(ht,Me,p(ht.el),de(ht),g,L,F),G.el=Me.el,ge===null&&su(g,Me.el),ae&&We(ae,L),(Oe=G.props&&G.props.onVnodeUpdated)&&We(()=>yt(Oe,he,G,_e),L)}else{let G;const{el:te,props:ae}=w,{bm:he,m:_e,parent:ge,root:Oe,type:Me}=g,ht=Bn(w);tn(g,!1),he&&ps(he),!ht&&(G=ae&&ae.onVnodeBeforeMount)&&yt(G,ge,w),tn(g,!0);{Oe.ce&&Oe.ce._hasShadowRoot()&&Oe.ce._injectChildStyle(Me,g.parent?g.parent.type:void 0);const vt=g.subTree=xi(g);I(null,vt,E,R,g,L,F),w.el=vt.el}if(_e&&We(_e,L),!ht&&(G=ae&&ae.onVnodeMounted)){const vt=w;We(()=>yt(G,ge,vt),L)}(w.shapeFlag&256||ge&&Bn(ge.vnode)&&ge.vnode.shapeFlag&256)&&g.a&&We(g.a,L),g.isMounted=!0,w=E=R=null}};g.scope.on();const j=g.effect=new fl(K);g.scope.off();const D=g.update=j.run.bind(j),ne=g.job=j.runIfDirty.bind(j);ne.i=g,ne.id=g.uid,j.scheduler=()=>Jo(ne),tn(g,!0),D()},V=(g,w,E)=>{w.component=g;const R=g.vnode.props;g.vnode=w,g.next=null,iu(g,w.props,R,E),uu(g,w.children,E),Ft(),mi(g),Nt()},Q=(g,w,E,R,L,F,Y,K,j=!1)=>{const D=g&&g.children,ne=g?g.shapeFlag:0,G=w.children,{patchFlag:te,shapeFlag:ae}=w;if(te>0){if(te&128){pt(D,G,E,R,L,F,Y,K,j);return}else if(te&256){Ee(D,G,E,R,L,F,Y,K,j);return}}ae&8?(ne&16&&N(D,L,F),G!==D&&f(E,G)):ne&16?ae&16?pt(D,G,E,R,L,F,Y,K,j):N(D,L,F,!0):(ne&8&&f(E,""),ae&16&&b(G,E,R,L,F,Y,K,j))},Ee=(g,w,E,R,L,F,Y,K,j)=>{g=g||on,w=w||on;const D=g.length,ne=w.length,G=Math.min(D,ne);let te;for(te=0;tene?N(g,L,F,!0,!1,G):b(w,E,R,L,F,Y,K,j,G)},pt=(g,w,E,R,L,F,Y,K,j)=>{let D=0;const ne=w.length;let G=g.length-1,te=ne-1;for(;D<=G&&D<=te;){const ae=g[D],he=w[D]=j?Et(w[D]):_t(w[D]);if(On(ae,he))I(ae,he,E,null,L,F,Y,K,j);else break;D++}for(;D<=G&&D<=te;){const ae=g[G],he=w[te]=j?Et(w[te]):_t(w[te]);if(On(ae,he))I(ae,he,E,null,L,F,Y,K,j);else break;G--,te--}if(D>G){if(D<=te){const ae=te+1,he=aete)for(;D<=G;)qe(g[D],L,F,!0),D++;else{const ae=D,he=D,_e=new Map;for(D=he;D<=te;D++){const Ye=w[D]=j?Et(w[D]):_t(w[D]);Ye.key!=null&&_e.set(Ye.key,D)}let ge,Oe=0;const Me=te-he+1;let ht=!1,vt=0;const En=new Array(Me);for(D=0;D=Me){qe(Ye,L,F,!0);continue}let mt;if(Ye.key!=null)mt=_e.get(Ye.key);else for(ge=he;ge<=te;ge++)if(En[ge-he]===0&&On(Ye,w[ge])){mt=ge;break}mt===void 0?qe(Ye,L,F,!0):(En[mt-he]=D+1,mt>=vt?vt=mt:ht=!0,I(Ye,w[mt],E,null,L,F,Y,K,j),Oe++)}const ai=ht?pu(En):on;for(ge=ai.length-1,D=Me-1;D>=0;D--){const Ye=he+D,mt=w[Ye],ri=w[Ye+1],ui=Ye+1{const{el:F,type:Y,transition:K,children:j,shapeFlag:D}=g;if(D&6){Ze(g.component.subTree,w,E,R);return}if(D&128){g.suspense.move(w,E,R);return}if(D&64){Y.move(g,w,E,Zt);return}if(Y===U){s(F,w,E);for(let G=0;GK.enter(F),L));else{const{leave:G,delayLeave:te,afterLeave:ae}=K,he=()=>{g.ctx.isUnmounted?o(F):s(F,w,E)},_e=()=>{const ge=F._isLeaving||!!F[so];F._isLeaving&&F[so](!0),K.persisted&&!ge?he():G(F,()=>{he(),ae&&ae()})};te?te(F,he,_e):_e()}else s(F,w,E)},qe=(g,w,E,R=!1,L=!1)=>{const{type:F,props:Y,ref:K,children:j,dynamicChildren:D,shapeFlag:ne,patchFlag:G,dirs:te,cacheIndex:ae,memo:he}=g;if((G===-2||D&&D.hasOnce)&&(L=!1),K!=null&&(Ft(),jn(K,null,E,g,!0),Nt()),ae!=null&&(!g.ctx||g.ctx===w)&&(w.renderCache[ae]=void 0),ne&256){w.ctx.deactivate(g);return}const _e=ne&1&&te,ge=!Bn(g);let Oe;if(ge&&(Oe=Y&&Y.onVnodeBeforeUnmount)&&yt(Oe,w,g),ne&6)pe(g.component,E,R);else{if(ne&128){g.suspense.unmount(E,R);return}_e&&en(g,null,w,"beforeUnmount"),ne&64?g.type.remove(g,w,E,Zt,R):D&&!D.hasOnce&&(F!==U||G>0&&G&64)?N(D,w,E,!1,!0):(F===U&&G&384||!L&&ne&16)&&N(j,w,E),R&&ls(g)}const Me=he!=null&&ae==null;(ge&&(Oe=Y&&Y.onVnodeUnmounted)||_e||Me)&&We(()=>{Oe&&yt(Oe,w,g),_e&&en(g,null,w,"unmounted"),Me&&(g.el=null)},E)},ls=g=>{const{type:w,el:E,anchor:R,transition:L}=g;if(w===U){as(E,R);return}if(w===vs){C(g),L&&!L.persisted&&L.afterLeave&&L.afterLeave();return}const F=()=>{o(E),L&&!L.persisted&&L.afterLeave&&L.afterLeave()};if(g.shapeFlag&1&&L&&!L.persisted){const{leave:Y,delayLeave:K}=L,j=()=>Y(E,F);K?K(g.el,F,j):j()}else F()},as=(g,w)=>{let E;for(;g!==w;)E=_(g),o(g),g=E;o(w)},pe=(g,w,E)=>{const{bum:R,scope:L,job:F,subTree:Y,um:K,m:j,a:D}=g;Ai(j),Ai(D),R&&ps(R),L.stop(),F?(F.flags|=8,qe(Y,g,w,E)):g.vnode.el&&Y&&(Y.transition=g.vnode.transition,qe(Y,g,w,E)),K&&We(K,w),We(()=>{g.isUnmounted=!0},w)},N=(g,w,E,R=!1,L=!1,F=0)=>{for(let Y=F;Y{if(g.shapeFlag&6)return de(g.component.subTree);if(g.shapeFlag&128)return g.suspense.next();const w=_(g.anchor||g.el),E=w&&w[Tr];return E?_(E):w};let et=!1;const Tn=(g,w,E)=>{let R;g==null?w._vnode&&(qe(w._vnode,null,null,!0),R=w._vnode.component):I(w._vnode||null,g,w,null,null,null,E),w._vnode=g,et||(et=!0,mi(R),El(),et=!1)},Zt={p:I,um:qe,m:Ze,r:ls,mt:B,mc:b,pc:Q,pbc:q,n:de,o:e};return{render:Tn,hydrate:void 0,createApp:Gr(Tn)}}function io({type:e,props:t},n){return n==="svg"&&e==="foreignObject"||n==="mathml"&&e==="annotation-xml"&&t&&t.encoding&&t.encoding.includes("html")?void 0:n}function tn({effect:e,job:t},n){n?(e.flags|=32,t.flags|=4):(e.flags&=-33,t.flags&=-5)}function fu(e,t){return(!e||e&&!e.pendingBranch)&&t&&!t.persisted}function Ql(e,t,n=!1){const s=e.children,o=t.children;if(se(s)&&se(o))for(let l=0;l>1,e[n[r]]0&&(t[s]=n[l-1]),n[l]=s)}}for(l=n.length,a=n[l-1];l-- >0;)n[l]=a,a=t[a];return n}function Zl(e){const t=e.subTree.component;if(t)return t.asyncDep&&!t.asyncResolved?t:Zl(t)}function Ai(e){if(e)for(let t=0;te.__isSuspense;function hu(e,t){t&&t.pendingBranch?se(e)?t.effects.push(...e):t.effects.push(e):kr(e)}const U=Symbol.for("v-fgt"),Ks=Symbol.for("v-txt"),Rt=Symbol.for("v-cmt"),vs=Symbol.for("v-stc"),rn=[];let Je=null;function h(e=!1){rn.push(Je=e?null:[])}function na(){rn.pop(),Je=rn[rn.length-1]||null}let zn=1;function Ti(e,t=!1){zn+=e,e<0&&Je&&t&&(Je.hasOnce=!0)}function sa(e){return e.dynamicChildren=zn>0?Je||on:null,na(),zn>0&&Je&&Je.push(e),e}function m(e,t,n,s,o,l){return sa(i(e,t,n,s,o,l,!0))}function Ke(e,t,n,s,o){return sa($e(e,t,n,s,o,!0))}function oa(e){return e?e.__v_isVNode===!0:!1}function On(e,t){return e.type===t.type&&e.key===t.key}const ia=({key:e})=>e??null,ms=({ref:e,ref_key:t,ref_for:n})=>(typeof e=="number"&&(e=""+e),e!=null?Te(e)||He(e)||re(e)?{i:ze,r:e,k:t,f:!!n}:e:null);function i(e,t=null,n=null,s=0,o=null,l=e===U?0:1,a=!1,r=!1){const d={__v_isVNode:!0,__v_skip:!0,type:e,props:t,key:t&&ia(t),ref:t&&ms(t),scopeId:Ol,slotScopeIds:null,children:n,component:null,suspense:null,ssContent:null,ssFallback:null,dirs:null,transition:null,el:null,anchor:null,target:null,targetStart:null,targetAnchor:null,staticCount:0,shapeFlag:l,patchFlag:s,dynamicProps:o,dynamicChildren:null,appContext:null,ctx:ze};return r?(Ss(d,n),l&128&&e.normalize(d)):n&&(d.shapeFlag|=Te(n)?8:16),zn>0&&!a&&Je&&(d.patchFlag>0||l&6)&&d.patchFlag!==32&&Je.push(d),d}const $e=vu;function vu(e,t=null,n=null,s=0,o=null,l=!1){if((!e||e===Rl)&&(e=Rt),oa(e)){const r=kn(e,t,!0);return n&&Ss(r,n),zn>0&&!l&&Je&&(r.shapeFlag&6?Je[Je.indexOf(e)]=r:Je.push(r)),r.patchFlag=-2,r}if(Au(e)&&(e=e.__vccOpts),t){t=mu(t);let{class:r,style:d}=t;r&&!Te(r)&&(t.class=ue(r)),we(d)&&(zo(d)&&!se(d)&&(d=De({},d)),t.style=Pe(d))}const a=Te(e)?1:ta(e)?128:Bs(e)?64:we(e)?4:re(e)?2:0;return i(e,t,n,s,o,a,l,!0)}function mu(e){return e?zo(e)||ql(e)?De({},e):e:null}function kn(e,t,n=!1,s=!1){const{props:o,ref:l,patchFlag:a,children:r,transition:d}=e,u=t?yu(o||{},t):o,f={__v_isVNode:!0,__v_skip:!0,type:e.type,props:u,key:u&&ia(u),ref:t&&t.ref?n&&l?se(l)?l.concat(ms(t)):[l,ms(t)]:ms(t):l,scopeId:e.scopeId,slotScopeIds:e.slotScopeIds,children:r,target:e.target,targetStart:e.targetStart,targetAnchor:e.targetAnchor,staticCount:e.staticCount,shapeFlag:e.shapeFlag,patchFlag:t&&e.type!==U?a===-1?16:a|16:a,dynamicProps:e.dynamicProps,dynamicChildren:e.dynamicChildren,appContext:e.appContext,dirs:e.dirs,transition:d,component:e.component,suspense:e.suspense,ssContent:e.ssContent&&kn(e.ssContent),ssFallback:e.ssFallback&&kn(e.ssFallback),placeholder:e.placeholder,el:e.el,anchor:e.anchor,ctx:e.ctx,ce:e.ce,cacheIndex:e.cacheIndex};return d&&s&&Go(f,d.clone(f)),f}function ee(e=" ",t=0){return $e(Ks,null,e,t)}function ys(e,t){const n=$e(vs,null,e);return n.staticCount=t,n}function H(e="",t=!1){return t?(h(),Ke(Rt,null,e)):$e(Rt,null,e)}function _t(e){return e==null||typeof e=="boolean"?$e(Rt):se(e)?$e(U,null,e.slice()):oa(e)?Et(e):$e(Ks,null,String(e))}function Et(e){return e.el===null&&e.patchFlag!==-1||e.memo?e:kn(e)}function Ss(e,t){let n=0;const{shapeFlag:s}=e;if(t==null)t=null;else if(se(t))n=16;else if(typeof t=="object")if(s&65){const o=t.default;o&&(o._c&&(o._d=!1),Ss(e,o()),o._c&&(o._d=!0));return}else{n=32;const o=t._;!o&&!ql(t)?t._ctx=ze:o===3&&ze&&(ze.slots._===1?t._=1:(t._=2,e.patchFlag|=1024))}else if(re(t)){if(s&65){Ss(e,{default:t});return}t={default:t,_ctx:ze},n=32}else t=String(t),s&64?(n=16,t=[ee(t)]):n=8;e.children=t,e.shapeFlag|=n}function yu(...e){const t={};for(let n=0;nNe||ze;let Cs,Jn;{const e=Rs(),t=(n,s)=>{let o;return(o=e[n])||(o=e[n]=[]),o.push(s),l=>{o.length>1?o.forEach(a=>a(l)):o[0](l)}};Cs=t("__VUE_INSTANCE_SETTERS__",n=>Ne=n),Jn=t("__VUE_SSR_SETTERS__",n=>Gn=n)}const ss=e=>{const t=Ne;return Cs(e),e.scope.on(),()=>{e.scope.off(),Cs(t)}},Ei=()=>{Ne&&Ne.scope.off(),Cs(null)};function la(e){return e.vnode.shapeFlag&4}let Gn=!1;function ku(e,t=!1,n=!1){t&&Jn(t);const{props:s,children:o}=e.vnode,l=la(e);ou(e,s,l,t),ru(e,o,n||t);const a=l?$u(e,t):void 0;return t&&Jn(!1),a}function $u(e,t){const n=e.type;e.accessCache=Object.create(null),e.proxy=new Proxy(e.ctx,Vr);const{setup:s}=n;if(s){Ft();const o=e.setupContext=s.length>1?Su(e):null,l=ss(e),a=ns(s,e,0,[e.props,o]),r=il(a);if(Nt(),l(),(r||e.sp)&&!Bn(e)&&Dl(e),r){if(a.then(Ei,Ei),t)return a.then(d=>{Jn(!0);try{Pi(e,d,t)}finally{Jn(!1)}}).catch(d=>{Us(d,e,0)});e.asyncDep=a}else Pi(e,a)}else aa(e)}function Pi(e,t,n){re(t)?e.type.__ssrInlineRender?e.ssrRender=t:e.render=t:we(t)&&(e.setupState=Cl(t)),aa(e)}function aa(e,t,n){const s=e.type;e.render||(e.render=s.render||$t);{const o=ss(e);Ft();try{Wr(e)}finally{Nt(),o()}}}const xu={get(e,t){return Fe(e,"get",""),e[t]}};function Su(e){const t=n=>{e.exposed=n||{}};return{attrs:new Proxy(e.attrs,xu),slots:e.slots,emit:e.emit,expose:t}}function qs(e){return e.exposed?e.exposeProxy||(e.exposeProxy=new Proxy(Cl(fr(e.exposed)),{get(t,n){if(n in t)return t[n];if(n in Vn)return Vn[n](e)},has(t,n){return n in t||n in Vn}})):e.proxy}function Cu(e,t=!0){return re(e)?e.displayName||e.name:e.name||t&&e.__name}function Au(e){return re(e)&&"__vccOpts"in e}const k=(e,t)=>yr(e,t,Gn),Tu="3.5.43";let Ao;const Oi=typeof window<"u"&&window.trustedTypes;if(Oi)try{Ao=Oi.createPolicy("vue",{createHTML:e=>e})}catch{}const ra=Ao?e=>Ao.createHTML(e):e=>e,Eu="http://www.w3.org/2000/svg",Pu="http://www.w3.org/1998/Math/MathML",Tt=typeof document<"u"?document:null,Ii=Tt&&Tt.createElement("template"),Ou={insert:(e,t,n)=>{t.insertBefore(e,n||null)},remove:e=>{const t=e.parentNode;t&&t.removeChild(e)},createElement:(e,t,n,s)=>{const o=t==="svg"?Tt.createElementNS(Eu,e):t==="mathml"?Tt.createElementNS(Pu,e):n?Tt.createElement(e,{is:n}):Tt.createElement(e);return e==="select"&&s&&s.multiple!=null&&o.setAttribute("multiple",s.multiple),o},createText:e=>Tt.createTextNode(e),createComment:e=>Tt.createComment(e),setText:(e,t)=>{e.nodeValue=t},setElementText:(e,t)=>{e.textContent=t},parentNode:e=>e.parentNode,nextSibling:e=>e.nextSibling,querySelector:e=>Tt.querySelector(e),setScopeId(e,t){e.setAttribute(t,"")},insertStaticContent(e,t,n,s,o,l){const a=n?n.previousSibling:t.lastChild;if(o&&(o===l||o.nextSibling))for(;t.insertBefore(o.cloneNode(!0),n),!(o===l||!(o=o.nextSibling)););else{Ii.innerHTML=ra(s==="svg"?`${e}`:s==="mathml"?`${e}`:e);const r=Ii.content;if(s==="svg"||s==="mathml"){const d=r.firstChild;for(;d.firstChild;)r.appendChild(d.firstChild);r.removeChild(d)}t.insertBefore(r,n)}return[a?a.nextSibling:t.firstChild,n?n.previousSibling:t.lastChild]}},Iu=Symbol("_vtc");function Mu(e,t,n){const s=e[Iu];s&&(t=(t?[t,...s]:[...s]).join(" ")),t==null?e.removeAttribute("class"):n?e.setAttribute("class",t):e.className=t}const Mi=Symbol("_vod"),Lu=Symbol("_vsh"),Du=Symbol(""),Fu=/(?:^|;)\s*display\s*:/;function Nu(e,t,n){const s=e.style,o=Te(n);let l=!1;if(n&&!o){if(t)if(Te(t))for(const a of t.split(";")){const r=a.slice(0,a.indexOf(":")).trim();n[r]==null&&Ln(s,r,"")}else for(const a in t)n[a]==null&&Ln(s,a,"");for(const a in n){a==="display"&&(l=!0);const r=n[a];r!=null?Hu(e,a,!Te(t)&&t?t[a]:void 0,r)||Ln(s,a,r):Ln(s,a,"")}}else if(o){if(t!==n){const a=s[Du];a&&(n+=";"+a),s.cssText=n,l=Fu.test(n)}}else t&&e.removeAttribute("style");Mi in e&&(e[Mi]=l?s.display:"",e[Lu]&&(s.display="none"))}const ds=/\s*!important$/;function Ln(e,t,n){if(se(n))n.forEach(s=>Ln(e,t,s));else if(n==null&&(n=""),t.startsWith("--"))ds.test(n)?e.setProperty(t,n.replace(ds,""),"important"):e.setProperty(t,n);else{const s=Ru(e,t);ds.test(n)?e.setProperty(Qt(s),n.replace(ds,""),"important"):e[s]=n}}const Li=["Webkit","Moz","ms"],lo={};function Ru(e,t){const n=lo[t];if(n)return n;let s=Ve(t);if(s!=="filter"&&s in e)return lo[t]=s;s=Fs(s);for(let o=0;oao||(Ku.then(()=>ao=0),ao=Date.now());function Yu(e,t){const n=s=>{if(!s._vts)s._vts=Date.now();else if(s._vts<=n.attached)return;const o=n.value;if(se(o)){const l=s.stopImmediatePropagation;s.stopImmediatePropagation=()=>{l.call(s),s._stopped=!0};const a=o.slice(),r=[s];for(let d=0;de.charCodeAt(0)===111&&e.charCodeAt(1)===110&&e.charCodeAt(2)>96&&e.charCodeAt(2)<123,zu=(e,t,n,s,o,l)=>{const a=o==="svg";t==="class"?Mu(e,s,a):t==="style"?Nu(e,n,s):Ms(t)?Ls(t)||ju(e,t,n,s,l):(t[0]==="."?(t=t.slice(1),!0):t[0]==="^"?(t=t.slice(1),!1):Ju(e,t,s,a))?(Ni(e,t,s),!e.tagName.includes("-")&&(t==="value"||t==="checked"||t==="selected")&&Fi(e,t,s,a,l,t!=="value")):e._isVueCE&&(Gu(e,t)||e._def.__asyncLoader&&(/[A-Z]/.test(t)||!Te(s)))?Ni(e,Ve(t),s,l,t):(t==="true-value"?e._trueValue=s:t==="false-value"&&(e._falseValue=s),Fi(e,t,s,a))};function Ju(e,t,n,s){if(s)return!!(t==="innerHTML"||t==="textContent"||t in e&&Hi(t)&&re(n));if(t==="spellcheck"||t==="draggable"||t==="translate"||t==="autocorrect"||t==="sandbox"&&e.tagName==="IFRAME"||t==="form"||t==="list"&&e.tagName==="INPUT"||t==="type"&&e.tagName==="TEXTAREA")return!1;if(t==="width"||t==="height"){const o=e.tagName;if(o==="IMG"||o==="VIDEO"||o==="CANVAS"||o==="SOURCE")return!1}return Hi(t)&&Te(n)?!1:t in e}function Gu(e,t){const n=e._def.props;if(!n)return!1;const s=Ve(t);return Array.isArray(n)?n.some(o=>Ve(o)===s):Object.keys(n).some(o=>Ve(o)===s)}const Gt=e=>{const t=e.props["onUpdate:modelValue"]||!1;return se(t)?n=>ps(t,n):t};function Xu(e){e.target.composing=!0}function Ui(e){const t=e.target;t.composing&&(t.composing=!1,t.dispatchEvent(new Event("input")))}const Ge=Symbol("_assign"),fs=Symbol("_initialValue");function ro(e,t,n){return t&&(e=e.trim()),n&&(e=Ns(e)),e}const Ie={created(e,{modifiers:{lazy:t,trim:n,number:s}},o){e.parentNode&&(e.type==="text"?e[fs]=e.defaultValue.replace(/[\r\n]/g,""):e.type==="textarea"&&(e[fs]=e.defaultValue.replace(/\r\n?/g,` +`))),e[Ge]=Gt(o);const l=s||o.props&&o.props.type==="number";Mt(e,t?"change":"input",a=>{a.target.composing||e[Ge](ro(e.value,n,l))}),(n||l)&&Mt(e,"change",()=>{e.value=ro(e.value,n,l)}),t||(Mt(e,"compositionstart",Xu),Mt(e,"compositionend",Ui),Mt(e,"change",Ui))},mounted(e,{value:t,modifiers:{trim:n,number:s}}){const o=t??"",l=e[fs];delete e[fs],l!==void 0&&(e.type==="text"||e.type==="textarea")&&e.value!==l?e[Ge](ro(e.value,n,s)):e.value=o},beforeUpdate(e,{value:t,oldValue:n,modifiers:{lazy:s,trim:o,number:l}},a){if(e[Ge]=Gt(a),e.composing)return;const r=(l||e.type==="number")&&!/^0\d/.test(e.value)?Ns(e.value):e.value,d=t??"";if(r===d)return;const u=e.getRootNode();(u instanceof Document||u instanceof ShadowRoot)&&u.activeElement===e&&e.type!=="range"&&(s&&t===n||o&&e.value.trim()===d)||(e.value=d)}},Qu={deep:!0,created(e,t,n){e[Ge]=Gt(n),Mt(e,"change",()=>{const s=e._modelValue,o=$n(e),l=e.checked,a=e[Ge];if(se(s)){const r=jo(s,o),d=r!==-1;if(l&&!d)a(s.concat(o));else if(!l&&d){const u=[...s];u.splice(r,1),a(u)}}else if(Dt(s)){const r=new Set(s);l?r.add(o):r.delete(o),a(r)}else a(ua(e,l))})},mounted:ji,beforeUpdate(e,t,n){e[Ge]=Gt(n),ji(e,t,n)}};function ji(e,{value:t,oldValue:n},s){e._modelValue=t;let o;if(se(t))o=jo(t,s.props.value)>-1;else if(Dt(t))o=t.has(s.props.value);else{if(t===n)return;o=ut(t,ua(e,!0))}e.checked!==o&&(e.checked=o)}const Bi={created(e,{value:t},n){e.checked=ut(t,n.props.value),e[Ge]=Gt(n),Mt(e,"change",()=>{e[Ge]($n(e))})},beforeUpdate(e,{value:t,oldValue:n},s){e[Ge]=Gt(s),t!==n&&(e.checked=ut(t,s.props.value))}},un={deep:!0,created(e,{value:t,modifiers:{number:n}},s){e._modelValue=t,Mt(e,"change",()=>{const o=Array.prototype.filter.call(e.options,d=>d.selected).map(d=>n?Ns($n(d)):$n(d)),l=e.multiple,a=l?Dt(e._modelValue)?new Set(o):o:o[0],r=e._pendingValue=[l,l?se(a)?o.slice():o:a];try{e[Ge](a)}finally{js(()=>{e._pendingValue===r&&(e._pendingValue=void 0)})}}),e[Ge]=Gt(s)},mounted(e,{value:t}){Vi(e,t)},beforeUpdate(e,{value:t},n){e._modelValue=t,e[Ge]=Gt(n)},updated(e,{value:t}){const n=e._pendingValue;e._pendingValue=void 0,(!n||n[0]!==e.multiple||!Zu(t,n[1],n[0]))&&Vi(e,t)}};function Zu(e,t,n){if(!n||se(e))return ut(e,t);if(Dt(e)){if(e.size!==t.length)return!1;for(const s of t)if(!e.has(s))return!1;return!0}return!1}function Vi(e,t){const n=e.multiple,s=se(t);if(!(n&&!s&&!Dt(t))){for(let o=0,l=e.options.length;oString(u)===String(r)):a.selected=jo(t,r)>-1}else a.selected=t.has(r);else if(ut($n(a),t)){e.selectedIndex!==o&&(e.selectedIndex=o);return}}!n&&e.selectedIndex!==-1&&(e.selectedIndex=-1)}}function $n(e){return"_value"in e?e._value:e.value}function ua(e,t){const n=t?"_trueValue":"_falseValue";return n in e?e[n]:t}const ec=["ctrl","shift","alt","meta"],tc={stop:e=>e.stopPropagation(),prevent:e=>e.preventDefault(),self:e=>e.target!==e.currentTarget,ctrl:e=>!e.ctrlKey,shift:e=>!e.shiftKey,alt:e=>!e.altKey,meta:e=>!e.metaKey,left:e=>"button"in e&&e.button!==0,middle:e=>"button"in e&&e.button!==1,right:e=>"button"in e&&e.button!==2,exact:(e,t)=>ec.some(n=>e[`${n}Key`]&&!t.includes(n))},it=(e,t)=>{if(!e)return e;const n=e._withMods||(e._withMods={}),s=t.join(".");return n[s]||(n[s]=((o,...l)=>{for(let a=0;a{const n=e._withKeys||(e._withKeys={}),s=t.join(".");return n[s]||(n[s]=(o=>{if(!("key"in o))return;const l=Qt(o.key);if(t.some(a=>a===l||nc[a]===l))return e(o)}))},sc=De({patchProp:zu},Ou);let Wi;function oc(){return Wi||(Wi=cu(sc))}const ic=((...e)=>{const t=oc().createApp(...e),{mount:n}=t;return t.mount=s=>{const o=ac(s);if(!o)return;const l=t._component;!re(l)&&!l.render&&!l.template&&(l.template=o.innerHTML),o.nodeType===1&&(o.textContent="");const a=n(o,!1,lc(o));return o instanceof Element&&(o.removeAttribute("v-cloak"),o.setAttribute("data-v-app","")),a},t});function lc(e){if(e instanceof SVGElement)return"svg";if(typeof MathMLElement=="function"&&e instanceof MathMLElement)return"mathml"}function ac(e){return Te(e)?document.querySelector(e):e}const rc=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],uc=["Su","Mo","Tu","We","Th","Fr","Sa"],da={clock:"clock-outline",analog:"clock-outline",date:"calendar"},je=e=>JSON.stringify(e),be=e=>String.fromCodePoint(parseInt(e,16));function ei(e,t=new Date){let n=t.getHours();return e||(n=n%12||12),`${String(n).padStart(2,"0")}:${String(t.getMinutes()).padStart(2,"0")}`}const ti=(e=new Date)=>`${uc[e.getDay()]} ${e.getDate()} ${rc[e.getMonth()]}`;function cc(e,t=Math.floor(Date.now()/1e3)){const n=t-e,s=Math.abs(n),o=l=>Math.floor(s/l);return n<0?s<3600?`In ${Math.max(1,o(60))} min`:s<86400?o(3600)===1?"In 1 hour":`In ${o(3600)} hours`:s<172800?"Tomorrow":`In ${o(86400)} days`:s<60?"Just now":s<3600?`${o(60)} min ago`:s<86400?o(3600)===1?"1 hour ago":`${o(3600)} hours ago`:s<172800?"Yesterday":s<604800?`${o(86400)} days ago`:s<2592e3?o(604800)===1?"1 week ago":`${o(604800)} weeks ago`:s<31536e3?o(2592e3)===1?"1 month ago":`${o(2592e3)} months ago`:o(31536e3)===1?"1 year ago":`${o(31536e3)} years ago`}const dc={guition:{width:448,top:36,name:27,text:21,icon:26},cyd:{width:298,top:24,name:18,text:14,icon:18}},Ki=document.createElement("canvas").getContext("2d"),To=new Map,fc=()=>To.clear();function sn(e,t){const n=`${t}|${e}`;let s=To.get(n);if(!s){Ki.font=t;const o=Ki.measureText(e);s={left:-o.actualBoundingBoxLeft,right:o.actualBoundingBoxRight,top:-o.actualBoundingBoxAscent,bottom:o.actualBoundingBoxDescent,advance:o.width},To.set(n,s)}return s}const pc=e=>({name:`500 ${e.name}px "Bar Roboto"`,text:`400 ${e.text}px "Bar Roboto"`,icon:`${e.icon}px "Tile Icons"`});function hc(e){return{icon:Math.max(2,Math.floor((e*4+5)/10)),item:Math.max(6,Math.floor((e*125+50)/100)),name:Math.max(8,Math.floor((e*16+5)/10))}}function fa(e,t,n,s){const o=pc(t),l=sn("0",o.text),a=Math.round(l.bottom-l.top),r=hc(a),d=sn(String.fromCodePoint(983376),o.icon),u=Math.round(d.bottom-d.top),f=e.map((C,z)=>{const P=s(C),S={index:z,item:C,view:P,shown:P.shown,width:0};return P.analog?(S.dial=u,S.width=u,S):(P.icon&&(S.icon={glyph:be(P.icon),ink:sn(be(P.icon),o.icon)},S.width+=S.icon.ink.right-S.icon.ink.left),P.text&&(S.text={value:P.text,ink:sn(P.text,o.text)},S.width+=(S.icon?r.icon:0)+S.text.ink.right-S.text.ink.left),S)}),p=f.filter(C=>C.shown),_=sn(n,o.name).advance,T=Math.min(_,Math.floor(t.width*35/100)),M=C=>C.reduce((z,P)=>z+P.width,0)+Math.max(0,C.length-1)*r.item;let I=0;for(;It.width;)I++;const $=p.slice(I),x=new Set(p.slice(0,I).map(C=>C.index));let O=t.width-M($);for(const C of $)C.x=O,O+=C.width+r.item;const J=$.length?$[0].x-r.name:t.width;return{metrics:t,fonts:o,cap:a,zero:l,gaps:r,parts:f,placed:$,dropped:x,nameText:n,natural:_,nameRoom:J}}function vc(e,t,n){if(sn(e,t).advance<=n)return e;const s=[...e];for(;s.length&&sn(s.join("")+"...",t).advance>n;)s.pop();return s.join("")+"..."}function mc(e){"fonts"in document&&Promise.all([document.fonts.load('500 27px "Bar Roboto"',"Studio 0"),document.fonts.load('400 21px "Bar Roboto"',"Away 0"),document.fonts.load('26px "Tile Icons"',String.fromCodePoint(983376))]).then(()=>{fc(),e()}).catch(()=>{})}let pa="";function yc(e){pa=e||""}async function ni(e,t={}){const n=await fetch(`api/${e}`,{...t,headers:{"Content-Type":"application/json","X-Screen-CSRF":pa,...t.headers}});if(!n.ok){let s="That didn't work. Refresh the page and try again.";try{s=(await n.json()).error||s}catch{}throw new Error(s)}return n}const dt=async e=>(await ni(e)).json(),Xe=async(e,t,n,s={})=>{const l=await(await ni(e,{method:t,body:n===void 0?void 0:JSON.stringify(n),...s})).text();return l?JSON.parse(l):null},Lt=6,xn=8,si=xn*Lt,st=e=>e.options?.size==="wide",Wn=(e,t)=>t?[e,e+1]:[e],Eo=e=>e-e%2,As=e=>Math.floor(e/Lt),ft=e=>e.tiles.map(t=>({tile:t,slot:t.slot}));function ha(e){let t=0;return e.map(n=>{const s=st(n);s&&t%2===1&&t++;const o=t;return t+=s?2:1,o})}function gc(e){const t=ha(e);return e.some((n,s)=>n.slot!==t[s])}function Ys(e){if(e.tiles.some(t=>!Number.isInteger(t.slot))){const t=ha(e.tiles);e.tiles.forEach((n,s)=>n.slot=t[s])}e.tiles.sort((t,n)=>t.slot-n.slot)}function oi(e){const t=new Set;for(const{tile:n,slot:s}of e)for(const o of Wn(s,st(n)))t.add(o);return t}const Xn=(e,t,n)=>Number.isInteger(t)&&t>=0&&t+(n?1:0)!e.has(s));function bc(e,t){for(let n=0;no.includes(u))?r.push(d):a.push({tile:d,slot:d.slot}));for(const d of r){const u=st(d),f=oi(a);let p=l.map(_=>u?Eo(_):_).find(_=>Xn(f,_,u));if(p===void 0&&(p=va(f,u,d.slot)),p<0)return null;a.push({tile:d,slot:p})}return a.sort((d,u)=>d.slot-u.slot)}function jt(e,t=1){const n=Math.max(0,...e.map(({tile:s,slot:o})=>o+(st(s)?2:1)));return Math.min(xn,Math.max(1,Math.ceil(n/Lt),t||1))}function wc(e){const t=e.split(".")[0];return t==="sun"?{options:{display:"sunpath",size:"wide"}}:t==="weather"?{options:{display:"forecast",size:"wide"}}:t==="screen"?{options:{display:"digital",size:"wide"}}:{}}const ya=e=>({entity:e,name:"",slot:-1,...wc(e)});function ga(e,t){const n=e.entity.split(".")[0],s=t.controls?.[n],o=e.options||{};if(!s||o.size!=="wide"||(o.display||"standard")!=="standard"||o.inline==="slider")return null;const l=o.controls??s.default;return l==="none"?null:l}function _c(e,t){const n=ga(e,t);return n?t.controls?.[e.entity.split(".")[0]]?.choices.find(s=>s.key===n)?.label.toLocaleLowerCase()||n:"none"}const Po=e=>(/^(\d+)\.(\d+)\.(\d+)$/.exec(e||"")||[]).slice(1).map(Number);function Sn(e,t){const[n,s]=[Po(e),Po(t)];if(n.length!==3||s.length!==3)return!1;for(let o=0;o<3;o++)if(n[o]!==s[o])return n[o]>s[o];return!0}const kc=(e,t,n,s)=>Sn(e,`${t}.${n}.${s}`);function $c(e){const t=Po(e);return t.length!==3?10:t[0]>0||t[1]>2||t[1]===2&&t[2]>=7?20:10}const ba={standard:"standard",watch:"large value",forecast:"weather forecast",graph:"graph",digital:"digital clock",analog:"analog clock",sunpath:"sun path"},qi=["light","switch","input_boolean","fan","media_player","climate"],xc=["light","fan","cover","number","input_number","media_player"],Sc={light:["Light","☀","#ad7600","#fff3d3"],climate:["Climate","❄","#c86620","#ffebdc"],vacuum:["Vacuum","◉","#008577","#def3ed"],fan:["Fan","✣","#008aab","#def5fa"],cover:["Cover","▤","#8053af","#eee5f8"],media_player:["Media","▶","#007cad","#def2fc"],sensor:["Sensor","⌁","#3476b1","#e5effa"],binary_sensor:["Status","◈","#ad7600","#fff3d3"],switch:["Switch","⏻","#ad7600","#fff3d3"],input_boolean:["Switch","⏻","#ad7600","#fff3d3"],scene:["Scene","✦","#8053af","#eee5f8"],script:["Script","▷","#8053af","#eee5f8"],weather:["Weather","☁","#007cad","#def2fc"],number:["Value","±","#008577","#def3ed"],input_number:["Value","±","#008577","#def3ed"],select:["Select","≡","#5862af","#eaecfa"],input_select:["Select","≡","#5862af","#eaecfa"],button:["Action","↗","#5862af","#eaecfa"],input_button:["Action","↗","#5862af","#eaecfa"],screen:["Clock","◷","#25282c","#e9ecf1"],sun:["Sun","☼","#c86620","#ffebdc"],timer:["Timer","⏱","#008577","#def3ed"],person:["Person","☺","#2f7d32","#e1f2e2"],camera:["Camera","◧","#3d4a57","#e6ebf0"],image:["Image","◧","#3d4a57","#e6ebf0"]},bt=e=>Sc[e.split(".")[0]]||["Entity","◇","#637184","#edf0f4"],c=fn({inventory:{screens:[],entities:[]},connected:!1,reachable:!0,selected:null,layout:null,dirty:!1,busy:!1,saved:0,tab:"layout",selectedTile:null,inspector:null,iconPickerOpen:!1,actionPickerOpen:!1,actionSearch:"",insertAt:-1,filter:"",search:"",capabilities:{},entityActions:{},topbarPreviews:{},topbarAdded:null,topbarOverflow:[],settingEdits:{},settingPending:!1,updating:[],toast:null,now:Date.now(),fontsVersion:0,route:location.hash,overrideProfile:null,overrideFriendly:"",drag:{active:!1,moving:null,preview:null},menuOpen:!1,liveStates:{},room:"",hidePlaced:!1,palette:!1,firmwareJob:null}),Ct=k(()=>c.inventory.screens.find(e=>e.id===c.selected)),wa=k(()=>Ct.value?.firmware||""),wn=(e,t,n)=>kc(wa.value,e,t,n),cn=k(()=>$c(wa.value)),ii=k(()=>Ct.value?.board==="guition"),_a=k(()=>dc[ii.value?"guition":"cyd"]),uo=k(()=>c.selectedTile&&c.layout?c.layout.tiles.find(e=>e.entity===c.selectedTile):void 0);let Yi=0;function Se(e,t){c.toast={message:e,action:t},clearTimeout(Yi),Yi=window.setTimeout(()=>c.toast=null,t?8e3:5e3)}function Cc(){c.toast=null}async function lt(e,t,n="API key"){try{if(!navigator.clipboard||!window.isSecureContext)throw new Error;await navigator.clipboard.writeText(e),Se(`${n} copied.`)}catch{if(t){const s=document.createRange();s.selectNodeContents(t);const o=window.getSelection();o?.removeAllRanges(),o?.addRange(s)}Se(document.execCommand("copy")?`${n} copied.`:`${n} is selected. Copy with Ctrl+C or Command+C.`)}}function Ts(){const e="/config/integrations/dashboard";try{window.top.location.assign(e)}catch{window.open(e,"_blank")}}const Ac=["","#settings","#new-screen","#firmware","#alerts","#override"],tt=k(()=>Ac.includes(c.route)?c.route:"");function Ae(e){if(location.hash===e){c.route=e;return}location.hash=e}window.addEventListener("hashchange",()=>{c.route=location.hash,window.scrollTo(0,0)});function os(e){return c.inventory.entities.find(t=>t.id===e)?.name||c.inventory.builtin?.find(t=>t.id===e)?.name||e}let co={source:null,byName:{}};function is(e){return co.source!==c.inventory.icons&&(co={source:c.inventory.icons,byName:Object.fromEntries((c.inventory.icons?.groups||[]).flatMap(t=>t.icons.map(n=>[n.name,n])))}),e?co.byName[e]:void 0}function Xt(e){const t=c.inventory.icons;if(!t)return"F0335";const n=c.inventory.entities.find(o=>o.id===e),s=e.split(".")[0];return t.builtin?.[e]?t.builtin[e]:n?.icon?n.icon:s==="weather"?t.weather[n?.state||""]||t.weather.partlycloudy:s==="sun"?t.sun[n?.state||""]||t.sun.below_horizon:t.defaults[s]||t.fallback}const gs=e=>is(e.options?.icon)?.cp||Xt(e.entity),fo=new Set;async function zs(e){const t=[...new Set(e)].filter(n=>!fo.has(n)&&!n.startsWith("screen."));if(t.length){t.forEach(n=>fo.add(n));try{for(let n=0;n`entity=${encodeURIComponent(o)}`).join("&");Object.assign(c.capabilities,(await dt(`capabilities?${s}`)).capabilities||{})}}catch{t.forEach(n=>fo.delete(n))}}}const po=new Set;async function Tc(e){if(!po.has(e)){po.add(e);try{c.entityActions[e]=(await dt(`entity-actions?entity=${encodeURIComponent(e)}`)).actions}catch{po.delete(e)}}}let ho=!1;async function Js(){const e=[...new Set((c.layout?.tiles||[]).map(t=>t.entity).filter(t=>!t.startsWith("screen.")))];if(!(!e.length||ho)){ho=!0;try{for(let t=0;t`entity=${encodeURIComponent(s)}`).join("&");Object.assign(c.liveStates,(await dt(`states?${n}`)).states||{})}}catch{}finally{ho=!1}}}function Ec(e){const t=c.liveStates[e];if(t)return t;const n=c.inventory.entities.find(s=>s.id===e);return n?.state?{state:n.state,word:null,a:{}}:null}function Qe(){c.dirty=!0,c.saved=0}function ka(e){if(e!==c.selected&&c.dirty&&!confirm("You have unsaved changes. Open a different screen anyway?"))return;e!==c.selected&&(Zn(),c.settingEdits={}),c.selected=e,c.selectedTile=null,c.inspector=null,c.tab="layout",c.menuOpen=!1;const t=c.inventory.screens.find(s=>s.id===e);if(!t){c.layout=null;return}const n=JSON.parse(JSON.stringify(t.layout));Ys(n),n.pages=jt(ft(n),n.pages),c.layout=n,c.insertAt=-1,c.dirty=!1,c.saved=0,Xs(0),zs(n.tiles.map(s=>s.entity)),Js(),Ae("")}function Pc(e){const t=c.layout,n=t.tiles.map(o=>`${o.entity}@${o.slot}`).join();for(const{tile:o,slot:l}of e)o.slot=l,t.tiles.includes(o)||t.tiles.push(o);Ys(t),t.pages=jt(ft(t),t.pages);const s=t.tiles.map(o=>`${o.entity}@${o.slot}`).join()!==n;return s&&Qe(),s}function Gs(e,t){if(!c.layout)return!1;zs([e.entity]);const n=ma(c.layout.tiles,e,t),s=n?Pc(n):!1;return s&&!c.liveStates[e.entity]&&Js(),s}function $a(e){const t=c.layout;if(!t||t.tiles.some(o=>o.entity===e)||t.tiles.length>=cn.value)return;const n=ya(e),s=c.insertAt>=0?c.insertAt:bc(oi(ft(t)),st(n));c.insertAt=-1,s>=0&&Gs(n,s)&&Oo(e)}function xa(e){const t=c.layout;if(!t)return;const n=t.tiles.indexOf(e);n<0||(t.tiles.splice(n,1),c.selectedTile===e.entity&&Re(),Qe(),t.pages=jt(ft(t),t.pages),Se(`${e.name||os(e.entity)} removed`,{label:"Undo",run:()=>Gs(e,e.slot)}))}function zi(){const e=c.layout;e&&(e.pages=Math.min(xn,jt(ft(e),e.pages)+1),Qe())}function Oc(e){const t=c.layout;if(t){for(const n of t.tiles)As(n.slot)>e&&(n.slot-=Lt);t.pages=Math.max(1,jt(ft(t),t.pages)-1),Qe()}}function Ic(){const e=c.layout;if(!e)return 1;const t=c.drag.preview||ft(e),n=jt(t,e.pages);return c.drag.active&&nr.key!=="none"&&o.controls.includes(r.key))?.key||"none"),Qe(),c.layout&&st(e)&&!l){const r=oi(ft(c.layout).filter(f=>f.tile!==e)),d=Eo(e.slot),u=Xn(r,d,!0)?d:va(r,!0,d);u>=0&&(e.slot=u),Ys(c.layout),c.layout.pages=jt(ft(c.layout),c.layout.pages)}}function Oo(e){c.selectedTile!==e&&(c.iconPickerOpen=!1,c.actionPickerOpen=!1,c.actionSearch=""),c.selectedTile=e,c.inspector={kind:"tile"},zs([e])}function Pt(e){c.inspector?.kind==="bar"&&c.inspector.index===e||(c.iconPickerOpen=!1),c.selectedTile=null,c.inspector={kind:"bar",index:e}}function Ji(){c.selectedTile=null,c.inspector={kind:"bar-add"}}function Re(){c.inspector=null,c.selectedTile=null}async function Io(){if(!(c.busy||!c.layout||!c.selected)){c.busy=!0;try{const{settings:e,...t}=c.layout;await Xe(`screens/${encodeURIComponent(c.selected)}`,"PUT",t),c.dirty=!1,c.saved=Date.now(),Se("Saved. Your screen is being updated."),await pn()}catch(e){Se(e.message)}finally{c.busy=!1}}}const dn=e=>!!(e&&e.alert_action&&Sn(e.firmware,c.inventory.alerts?.min_firmware||"0.2.31"));async function Sa(e){try{await Xe(`screens/${encodeURIComponent(e.id)}/identify`,"POST"),Se(`${e.name} blinks and shows a card for a few seconds.`)}catch(t){Se(t.message)}}async function Mc(e,t){return await Xe("alerts/test","POST",{screen:e,data:t})}const Lc=["title","tiles","header","pages"];function Ca(e,t){const n=c.layout;if(!n)return;const s=(Array.isArray(e.tiles)?e.tiles:[]).filter(r=>!!(r&&typeof r=="object"&&typeof r.entity=="string"&&r.entity.includes("."))).map(r=>({entity:r.entity,name:typeof r.name=="string"?r.name:"",slot:Number.isInteger(r.slot)?r.slot:-1,...r.options&&typeof r.options=="object"?{options:{...r.options}}:{}})),o=new Set,l=s.filter(r=>!o.has(r.entity)&&o.add(r.entity)),a=l.slice(0,cn.value);n.tiles=a,e.header&&Array.isArray(e.header.items)?n.header={items:e.header.items.map(r=>({...r}))}:delete n.header,n.pages=Number.isInteger(e.pages)?e.pages:1,Ys(n),n.pages=jt(ft(n),n.pages),Re(),Qe(),zs(a.map(r=>r.entity)),Js(),Xs(0),Se(a.lengthn.id===e);!t||!c.layout||Ca(JSON.parse(JSON.stringify(t.layout)),`Layout of ${t.name} copied`)}function Fc(){const e=c.layout;if(!e)return"";const t={esp_screens_layout:1};for(const n of Lc)e[n]!==void 0&&(t[n]=e[n]);return JSON.stringify(t,null,2)}function Aa(){const e=Fc();if(!e)return;const t=`${(Ct.value?.name||"screen").toLowerCase().replace(/[^a-z0-9]+/g,"-")}.layout.json`,n=URL.createObjectURL(new Blob([e],{type:"application/json"})),s=document.createElement("a");s.href=n,s.download=t,s.click(),setTimeout(()=>URL.revokeObjectURL(n),5e3),lt(e,void 0,"Layout JSON")}function Nc(e){let t;try{t=JSON.parse(e)}catch{Se("That isn't JSON. Export a layout first, or paste one from another ESP Screens.");return}if(!t||typeof t!="object"||!Array.isArray(t.tiles)){Se("No tiles in this file. Expected a layout exported from ESP Screens.");return}Ca(t,"Layout imported")}function Gi(e){const t=c.inventory.updates?.target,n=c.inventory.updates?.changelog;if(!n||!t)return[];const s=e.firmware,o=[];for(const l of n)if(!(Sn(l.firmware,t)&&l.firmware!==t)&&!(s&&Sn(s,l.firmware)))for(const a of l.lines)o.includes(a)||o.push(a);return o}let vo=!1;async function Rc(){if(!vo){vo=!0;try{const e=await dt("firmware");c.firmwareJob={job:e.job,logs:e.logs||[]}}catch{}finally{vo=!1}}}const Mo=()=>c.inventory.screens.some(e=>e.update?.state==="running")||c.updating.length>0;function yn(e){const t=e.update||{};if(!(t.state==="running"||c.updating.includes(e.id)))return null;const n=c.firmwareJob?.job?.stage;return t.phase==="verify"?{percent:78,text:Nn.verify}:t.phase==="settle"?{percent:92,text:Nn.settle}:t.phase==="install"||!t.phase?n==="upload"?{percent:66,text:"Writing the firmware over Wi-Fi…"}:n?{percent:40,text:"Building the firmware…"}:{percent:12,text:Nn.install}:{percent:12,text:Nn[t.phase]||"Starting update…"}}const Ht=()=>c.layout?.header?.items??(c.layout?.settings?.show_clock??!0?[{type:"clock"}]:[]),Kt=()=>c.inventory.header?.max_items||6;function Qn(e){c.layout&&(c.layout.header={items:e},Qe(),Xs())}let Xi=0;function Xs(e=150){clearTimeout(Xi),Xi=window.setTimeout(async()=>{const t=Ht();if(t.some(n=>n.type==="entity"))try{const n=await Xe("header-preview","POST",{header:{items:t}});t.forEach((s,o)=>c.topbarPreviews[je(s)]=n.items[o])}catch{}},e)}function Dn(e){return e.type==="entity"?os(e.entity):c.inventory.header?.builtin.find(t=>t.type===e.type)?.label||e.type}function Vt(e){const t=new Date(c.now);if(e.type==="clock")return{text:ei(Cn().clock_24h!==!1,t),shown:!0};if(e.type==="date")return{text:ti(t),shown:!0};if(e.type==="analog")return{analog:!0,shown:!0};const n=c.topbarPreviews[je(e)];return n?{icon:n.i||null,text:n.k==="ago"?cc(n.e,Math.floor(c.now/1e3)):n.t,color:n.c?`#${n.c}`:null,shown:n.shown}:{icon:e.icon==="none"?null:is(e.icon)?.cp||Xt(e.entity),text:"…",shown:!0,loading:!0}}function mo(e,t){const n=[...Ht()];return t<0||t>=n.length||e===t?!1:(n.splice(t,0,...n.splice(e,1)),Qn(n),!0)}function Qi(e){const t=[...Ht()],[n]=t.splice(e,1);n&&(c.inspector?.kind==="bar"&&Re(),Qn(t),Se(`${Dn(n)} removed from the top bar`,{label:"Undo",run:()=>{const s=[...Ht()];s.splice(Math.min(e,s.length),0,n),Qn(s)}}))}function yo(e){const t=Ht();if(t.length>=Kt())return Se(`The top bar has room for ${Kt()} items.`);if(t.some(n=>je(n)===je(e)))return Se("This is already in the top bar.");c.topbarAdded={key:je(e),time:Date.now()},Qn([...t,e]),Pt(t.length)}const Hc=[{title:"Brightness",icon:"F0599",rows:[{key:"brightness",label:"Brightness",kind:"number",min:5,max:100,step:5,unit:"%"},{key:"dark_mode",label:"Dark mode",kind:"toggle"},{key:"standby_enabled",label:"Auto standby",kind:"toggle"},{key:"standby_seconds",label:"Standby after",kind:"duration",min:60,max:86400,needs:"standby_enabled"},{key:"standby_brightness",label:"Standby brightness",kind:"number",min:0,max:100,step:5,unit:"%",needs:"standby_enabled",cap:"brightness"}]},{title:"Night",icon:"F0594",rows:[{key:"night_enabled",label:"Night mode",kind:"toggle"},{key:"night_start",label:"Starts",kind:"moment",needs:"night_enabled"},{key:"night_end",label:"Ends",kind:"moment",needs:"night_enabled"},{key:"night_brightness",label:"Night brightness",kind:"number",min:0,max:100,step:5,unit:"%",needs:"night_enabled",cap:"brightness"}]},{title:"Screen",icon:"F0379",rows:[{key:"clock_24h",label:"Clock",kind:"choice",options:[[!1,"12 hour"],[!0,"24 hour"]]},{key:"auto_home",label:"Back to page 1",kind:"toggle"},{key:"auto_home_seconds",label:"After",kind:"duration",min:30,max:3600,needs:"auto_home"},{key:"home_on_standby",label:"Also on standby",kind:"toggle"},{key:"swipe_pages",label:"Swipe between pages",kind:"toggle"},{key:"rotation",label:"Rotation",kind:"choice",options:[[0,"0°"],[90,"90°"],[180,"180°"],[270,"270°"]]}]}],Ta=4e3;let qt={},_n=null,Es=0,bs=null;const li=()=>Ct.value?.settings;function Cn(){const e=li(),t={...e?.values||{}};for(const[n,s]of Object.entries(c.settingEdits))t[n]=s.value;return t}const Uc=e=>e<300?30:e<900?60:e<3600?300:e<7200?900:1800;function Zi(e,t,n,s,o){if(e.kind==="moment"){let r=s&&t%60?Math.floor(t/60)*60+(n>0?60:0):t+n*(s?60:15);return r%=1440,r<0?r+1440:r}const l=e.kind==="duration"?Uc(n<0?t-1:t):e.step,a=e.cap?Math.min(e.max,o[e.cap]):e.max;return Math.min(a,Math.max(e.min,t+n*l))}function jc(e){if(e<60)return`${e} sec`;if(e<3600)return`${Math.floor(e/60)} min`;const t=Math.floor(e/3600),n=Math.floor(e%3600/60);return n?`${t} h ${String(n).padStart(2,"0")}`:`${t} h`}function Bc(e,t){const n=Math.floor(e/60),s=String(e%60).padStart(2,"0");return t?`${String(n).padStart(2,"0")}:${s}`:`${n%12||12}:${s} ${n<12?"AM":"PM"}`}function Vc(e,t){const n=t[e.key];return n==null?"—":e.kind==="number"?`${n}${e.unit||""}`:e.kind==="duration"?jc(n):e.kind==="moment"?Bc(n,t.clock_24h!==!1):""}function Fn(e,t,n){if(_n&&_n!==c.selected&&Object.keys(qt).length){Zn(),Se("Still saving the other screen's settings. Try again in a moment.");return}_n=c.selected;const s=Cn();if(c.settingEdits[e]={value:t,at:Date.now()},qt[e]=t,e==="brightness")for(const o of["standby_brightness","night_brightness"])s[o]>t&&(c.settingEdits[o]={value:t,at:Date.now()});c.settingPending=!0,clearTimeout(Es),Es=window.setTimeout(()=>Zn(),n)}async function Zn(e=!1){if(clearTimeout(Es),bs||!Object.keys(qt).length||!_n)return;const t=_n,n=qt;qt={};const s=ni(`screens/${encodeURIComponent(t)}/settings`,{method:"PUT",body:JSON.stringify({settings:n}),keepalive:e});bs=s;try{const o=await(await s).json(),l=c.inventory.screens.find(a=>a.id===t);l&&(l.settings=o)}catch(o){if(Se(o.message),t===c.selected)for(const l of Object.keys(n))delete c.settingEdits[l];if(t===c.selected&&n.brightness!==void 0)for(const l of["standby_brightness","night_brightness"])delete c.settingEdits[l]}finally{bs=null,Object.keys(qt).length?Es=window.setTimeout(()=>Zn(),150):_n=null,c.settingPending=!!Object.keys(qt).length,t===c.selected&&Ps(),setTimeout(()=>{t===c.selected&&Ps()},Ta+100)}}function Ps(){const e=li();for(const[t,n]of Object.entries(c.settingEdits))qt[t]!==void 0||bs||(e&&e.values[t]===n.value||Date.now()-n.at>Ta)&&delete c.settingEdits[t]}const Nn={install:"Building and installing…",verify:"Waiting for the screen to come back…",settle:"Checking that it stays stable…"};async function Lo(e,t){c.updating.push(e.id);try{await Xe(`screens/${encodeURIComponent(e.id)}/update`,"POST",t?{host:t}:{}),await pn()}catch(n){c.updating=c.updating.filter(s=>s!==e.id),Se(n.message)}}async function el(){try{await Xe("updates/run","POST"),await pn()}catch(e){Se(e.message)}}async function Wc(e){try{await Xe("updates","PUT",{auto:e}),c.inventory.updates&&(c.inventory.updates.auto=e),Se(e?"Screens will now update automatically at night.":"Automatic updates are off.")}catch(t){Se(t.message)}}async function Kc(){try{c.inventory.claude_skill=await Xe("claude-skill","POST"),Se(c.inventory.claude_skill?.restart?"Skill installed. Restart Claude Code once so it finds the new skills folder.":"Skill installed. Claude Code picks it up right away.")}catch(e){Se(e.message)}}async function pn(e=!0){try{const t=await dt(e?"inventory":"inventory?light=1");c.inventory=e?t:{...c.inventory,...t},t.csrf&&yc(t.csrf),c.connected=!!c.inventory.connected,c.reachable=!0;for(const n of c.inventory.screens)n.update?.state==="running"&&(c.updating=c.updating.filter(s=>s!==n.id));c.selected&&Ps()}catch{c.reachable=!1}}function qc(e){c.inventory={...c.inventory,...e},c.connected=!!c.inventory.connected;for(const t of c.inventory.screens)t.update?.state==="running"&&(c.updating=c.updating.filter(n=>n!==t.id));c.selected&&Ps()}let tl=0,Do=Date.now(),Os=!1,In=null;function Yc(){In||typeof EventSource>"u"||(In=new EventSource("api/events"),In.onopen=()=>{Os=!0,es()},In.onmessage=e=>{document.hidden||qc(JSON.parse(e.data))},In.onerror=()=>{Os=!1,es()})}function es(){clearTimeout(tl);const e=Os?6e4:c.inventory.updates?.busy?3e3:1e4;tl=window.setTimeout(async()=>{if(!document.hidden){const t=Date.now()-Do>=3e5;t&&(Do=Date.now()),(t||!Os)&&await pn(t)}es()},e)}let nl=!1;function zc(){nl||(nl=!0,pn(),Yc(),es(),mc(()=>c.fontsVersion++),setInterval(()=>{!c.layout||document.hidden||c.drag.active||(c.now=Date.now(),Xs(0))},3e4),setInterval(()=>{!document.hidden&&c.layout&&c.tab==="layout"&&tt.value===""&&Js()},8e3),setInterval(()=>{!document.hidden&&Mo()?Rc():c.firmwareJob&&!Mo()&&(c.firmwareJob=null)},3e3),document.addEventListener("visibilitychange",async()=>{document.hidden||(Do=Date.now(),c.now=Date.now(),await pn(),es())}),window.addEventListener("pagehide",()=>Zn(!0)),window.addEventListener("beforeunload",e=>{c.dirty&&(e.preventDefault(),e.returnValue="")}))}const Jc={class:"side"},Gc={id:"screens"},Xc=["aria-current","onClick"],Qc={class:"txt"},Zc={key:0,class:"pill"},ed={key:1,class:"spin small"},td=["onSubmit"],nd=["disabled","title","onClick"],sd={key:2,class:"whatsnew"},od=["aria-valuenow"],id={class:"progress-text"},ld=["title"],ad=["title"],rd={id:"pending"},ud={class:"pending-actions"},cd=["onClick"],dd=["aria-current"],fd={class:"more"},pd=["aria-current"],hd={class:"mdi"},vd=["aria-current"],md={class:"mdi"},yd=["aria-current"],gd={class:"mdi"},bd=Ce({__name:"Sidebar",setup(e){const t=fe(null),n=fe("");function s(d){const u=d.update||{};return u.state==="running"||c.updating.includes(d.id)?{kind:"running",text:Nn[u.phase||""]||"Starting update…"}:u.state==="queued"?{kind:"queued",text:"Queued for the update"}:u.available&&d.online?{kind:"available",text:`Update ${u.target}`}:u.result&&Date.now()/1e3-u.result.time<86400?{kind:u.result.state==="failed"?"failed":"done",text:u.result.message}:null}function o(d){const u=d.update||{};u.host&&u.profile?Lo(d):u.profile&&(t.value=d.id,n.value="")}function l(d){const u=n.value.trim();u&&(t.value=null,Lo(d,u))}const a=()=>{const d=c.firmwareJob?.logs||[];return d.length?d[d.length-1]:""},r=d=>d.installed?"Installed, but not yet in Home Assistant. Add the discovered ESPHome device under Settings → Devices & services, paste the API key there, and turn on “Allow the device to perform Home Assistant actions” under Configure.":d.downloaded?"Firmware downloaded, not yet in Home Assistant. Put it on the screen with ESPHome Web, then add the discovered ESPHome device under Settings → Devices & services, paste the API key there, and allow the Home Assistant actions under Configure.":`Not yet in Home Assistant. Already flashed? Add the ESPHome device under Settings → Devices & services, then allow the Home Assistant actions under Configure. Not flashed yet? Firmware & USB → ${d.file}.`;return(d,u)=>(h(),m("aside",Jc,[u[20]||(u[20]=i("div",{class:"brand"},[i("span",{class:"mark"},"▦"),i("span",null,"ESP Screens")],-1)),i("span",{id:"connection",class:ue(["conn",{online:v(c).connected}]),role:"status"},y(v(c).reachable?v(c).connected?"Home Assistant connected":"Reconnecting to Home Assistant…":"Management page unreachable · retrying…"),3),i("button",{type:"button",class:"search-btn",id:"open-palette",onClick:u[0]||(u[0]=f=>v(c).palette=!0)},[...u[10]||(u[10]=[ee("⌕ Search",-1),i("kbd",null,"⌘K",-1)])]),u[21]||(u[21]=i("div",{class:"label"},"Screens",-1)),i("div",Gc,[(h(!0),m(U,null,ie(v(c).inventory.screens,f=>(h(),m("div",{key:f.id,class:ue(["screen-item",{selected:f.id===v(c).selected&&v(tt)===""}])},[i("button",{type:"button",class:"nav-item","aria-current":f.id===v(c).selected&&v(tt)===""?"true":"false",onClick:p=>v(ka)(f.id)},[i("span",{class:ue(["dot",{off:!f.online}])},null,2),i("span",Qc,[i("span",null,y(f.name),1),i("small",null,y(f.online?"Online":"Offline")+y(f.area?" · "+f.area:"")+" · "+y(f.firmware||"unknown"),1)]),s(f)?.kind==="available"?(h(),m("span",Zc,"Update")):s(f)?.kind==="running"?(h(),m("span",ed)):H("",!0)],8,Xc),s(f)?(h(),m("div",{key:0,class:ue(["screen-update",s(f).kind])},[s(f).kind==="available"?(h(),m(U,{key:0},[t.value===f.id?(h(),m(U,{key:0},[u[12]||(u[12]=i("small",null,"The IP address, once; new firmware reports it itself.",-1)),i("form",{class:"screen-host",onSubmit:it(p=>l(f),["prevent"])},[ye(i("input",{"onUpdate:modelValue":u[1]||(u[1]=p=>n.value=p),placeholder:"IP address, e.g. 192.168.1.50",required:"",pattern:"[A-Za-z0-9][A-Za-z0-9.\\-]*","aria-label":"IP address",autofocus:""},null,512),[[Ie,n.value]]),u[11]||(u[11]=i("button",{type:"submit",class:"btn mini primary"},"Start",-1)),i("button",{type:"button",class:"icon-btn","aria-label":"Cancel",onClick:u[2]||(u[2]=p=>t.value=null)},"✕")],40,td)],64)):(h(),m(U,{key:1},[i("small",null,y(s(f).text),1),i("button",{type:"button",class:"btn mini primary",disabled:!f.update?.profile,title:f.update?.profile?"":"No ESPHome profile found with this device name.",onClick:p=>o(f)},"Update",8,nd)],64)),v(Gi)(f).length?(h(),m("details",sd,[u[13]||(u[13]=i("summary",null,"What's new",-1)),i("ul",null,[(h(!0),m(U,null,ie(v(Gi)(f).slice(0,8),p=>(h(),m("li",{key:p},y(p),1))),128))])])):H("",!0)],64)):s(f).kind==="running"&&v(yn)(f)?(h(),m(U,{key:1},[i("div",{class:"progress",role:"progressbar","aria-valuenow":v(yn)(f).percent,"aria-valuemin":"0","aria-valuemax":"100"},[i("i",{style:Pe({width:v(yn)(f).percent+"%"})},null,4)],8,od),i("div",id,[i("span",null,y(v(yn)(f).percent)+" %",1),i("span",{title:a()},y(v(yn)(f).text),9,ld)]),a()?(h(),m("small",{key:0,title:a(),style:{"white-space":"nowrap",overflow:"hidden","text-overflow":"ellipsis"}},y(a()),9,ad)):H("",!0),i("button",{type:"button",class:"btn link mini",style:{"justify-self":"start"},onClick:u[3]||(u[3]=p=>v(Ae)("#firmware"))},"Full log")],64)):(h(),m("small",{key:2,class:ue({failed:s(f).kind==="failed"})},y(s(f).text),3))],2)):H("",!0)],2))),128))]),i("div",rd,[(h(!0),m(U,null,ie(v(c).inventory.pending||[],f=>(h(),m("div",{key:f.file,class:"pending"},[i("strong",null,y(f.friendly),1),i("small",null,y(r(f)),1),i("div",ud,[i("button",{type:"button",class:"btn mini quiet",onClick:u[4]||(u[4]=(...p)=>v(Ts)&&v(Ts)(...p))},"Open Devices & services"),f.api_key?(h(),m("button",{key:0,type:"button",class:"btn mini quiet",onClick:p=>v(lt)(f.api_key)},"Copy API key",8,cd)):H("",!0)])]))),128))]),i("button",{id:"new-screen",type:"button",class:"nav-item ghost","aria-current":v(tt)==="#new-screen"?"true":"false",onClick:u[5]||(u[5]=f=>v(Ae)("#new-screen"))},[...u[14]||(u[14]=[i("span",{class:"plus"},"+",-1),i("span",{class:"txt"},"New screen",-1)])],8,dd),u[22]||(u[22]=i("div",{class:"spacer"},null,-1)),i("div",fd,[u[19]||(u[19]=i("div",{class:"label"},"More",-1)),i("button",{id:"open-firmware",type:"button",class:"nav-item","aria-current":v(tt)==="#firmware"?"true":"false",onClick:u[6]||(u[6]=f=>v(Ae)("#firmware"))},[i("span",hd,y(v(be)("F0241")),1),u[15]||(u[15]=i("span",{class:"txt"},"Firmware & USB",-1))],8,pd),i("button",{id:"open-alerts",type:"button",class:"nav-item","aria-current":v(tt)==="#alerts"?"true":"false",onClick:u[7]||(u[7]=f=>v(Ae)("#alerts"))},[i("span",md,y(v(be)("F0594")),1),u[16]||(u[16]=i("span",{class:"txt"},"Alerts",-1))],8,vd),i("button",{id:"open-settings",type:"button",class:"nav-item","aria-current":v(tt)==="#settings"?"true":"false",onClick:u[8]||(u[8]=f=>v(Ae)("#settings"))},[i("span",gd,y(v(be)("F0493")),1),u[17]||(u[17]=i("span",{class:"txt"},"Settings",-1))],8,yd),i("button",{id:"refresh",type:"button",class:"nav-item ghost",onClick:u[9]||(u[9]=f=>v(pn)())},[...u[18]||(u[18]=[i("span",{class:"plus"},"↻",-1),i("span",{class:"txt"},"Refresh",-1)])])])]))}}),wd={key:0,id:"toast",class:"toast",role:"status"},_d=Ce({__name:"Toast",setup(e){return(t,n)=>v(c).toast?(h(),m("div",wd,[i("span",null,y(v(c).toast.message),1),v(c).toast.action?(h(),m("button",{key:0,type:"button",onClick:n[0]||(n[0]=s=>{v(c).toast.action.run(),v(Cc)()})},y(v(c).toast.action.label),1)):H("",!0)])):H("",!0)}}),kd={class:"palette-list"},$d={class:"palette-group"},xd=["onMouseenter","onClick"],Sd={key:0,class:"mdi"},Cd={key:1,class:"glyph"},Ad={class:"tx"},Td={key:0},Ed={key:2,class:"hint-key"},Pd={key:0,class:"palette-empty"},Od=Ce({__name:"CommandPalette",setup(e){const t=fe(""),n=fe(0),s=fe(null),o=k(()=>{const u=t.value.trim().toLocaleLowerCase(),f=[];for(const T of c.inventory.screens)f.push({group:"Screens",label:T.name,detail:`${T.online?"Online":"Offline"} · ${T.firmware||"unknown"}`,glyphText:"▦",run:()=>ka(T.id)});const p=Ct.value,_=[{group:"Actions",label:"New screen",detail:"Connect and install",glyphText:"+",run:()=>Ae("#new-screen")},{group:"Actions",label:"Firmware & USB",icon:"F0241",run:()=>Ae("#firmware")},{group:"Actions",label:"Alerts",detail:"Cheatsheet and a test alert",icon:"F0594",run:()=>Ae("#alerts")},{group:"Actions",label:"Settings",detail:"Updates, Claude",icon:"F0493",run:()=>Ae("#settings")}];if(p&&c.layout&&_.unshift({group:"Actions",label:"Save & send",detail:c.dirty?"Unsaved changes":"Nothing to save",key:"⌘S",run:()=>Io()},{group:"Actions",label:"Layout",detail:p.name,run:()=>{Ae(""),c.tab="layout"}},{group:"Actions",label:"Screen settings",detail:p.name,run:()=>{Ae(""),c.tab="settings"}},{group:"Actions",label:"Identify this screen",detail:dn(p)?"Blinks the backlight and shows a card":"Needs a newer firmware",run:()=>{dn(p)&&Sa(p)}},{group:"Actions",label:"Export layout",detail:"Download and copy as JSON",run:Aa}),f.push(..._),p&&c.layout&&u){const T=new Set(c.layout.tiles.map(I=>I.entity)),M=c.layout.tiles.length>=cn.value;for(const I of c.inventory.entities)if(!(I.tile===!1||T.has(I.id))&&`${I.name} ${I.id} ${I.area||""} ${I.device||""}`.toLocaleLowerCase().includes(u)&&(f.push({group:"Add to this screen",label:I.name,detail:[bt(I.id)[0],I.area].filter(Boolean).join(" · "),icon:c.inventory.icons?Xt(I.id):void 0,run:()=>{M||$a(I.id)}}),f.length>60))break}return u?f.filter(T=>`${T.label} ${T.detail||""}`.toLocaleLowerCase().includes(u)):f}),l=k(()=>{const u=[];return o.value.forEach((f,p)=>{(u.find(T=>T.group===f.group)||(u.push({group:f.group,items:[]}),u[u.length-1])).items.push({item:f,index:p})}),u});function a(){c.palette=!1}function r(u){a(),u.run()}function d(u){if(u.key==="Escape")u.preventDefault(),a();else if(u.key==="ArrowDown")u.preventDefault(),n.value=Math.min(o.value.length-1,n.value+1);else if(u.key==="ArrowUp")u.preventDefault(),n.value=Math.max(0,n.value-1);else if(u.key==="Enter"){u.preventDefault();const f=o.value[n.value];f&&r(f)}}return an(t,()=>n.value=0),an(()=>c.palette,async u=>{u&&(t.value="",n.value=0,await js(),s.value?.focus())}),(u,f)=>v(c).palette?(h(),m("div",{key:0,class:"palette-backdrop",onClick:a},[i("div",{class:"palette",role:"dialog","aria-label":"Search",onClick:f[1]||(f[1]=it(()=>{},["stop"])),onKeydown:d},[ye(i("input",{ref_key:"input",ref:s,"onUpdate:modelValue":f[0]||(f[0]=p=>t.value=p),id:"palette-input",placeholder:"Search screens, entities, actions…","aria-label":"Search",autocomplete:"off"},null,512),[[Ie,t.value]]),i("div",kd,[(h(!0),m(U,null,ie(l.value,p=>(h(),m(U,{key:p.group},[i("div",$d,y(p.group),1),(h(!0),m(U,null,ie(p.items,({item:_,index:T})=>(h(),m("button",{key:T,type:"button",class:ue(["palette-item",{active:T===n.value}]),onMouseenter:M=>n.value=T,onClick:M=>r(_)},[_.icon?(h(),m("span",Sd,y(v(be)(_.icon)),1)):(h(),m("span",Cd,y(_.glyphText||"›"),1)),i("span",Ad,[i("span",null,y(_.label),1),_.detail?(h(),m("small",Td,y(_.detail),1)):H("",!0)]),_.key?(h(),m("kbd",Ed,y(_.key),1)):H("",!0)],42,xd))),128))],64))),128)),o.value.length?H("",!0):(h(),m("p",Pd,"Nothing matches. Type part of a screen, entity or action."))])],32)])):H("",!0)}}),oe={source:null,element:null,ghost:null,timer:0,start:null,offset:{x:0,y:0},pointerId:null,suppressUntil:0,last:null,scroller:0,target:null},Ea={mounted(e,t){e.__dragSource=t.value,e.addEventListener("pointerdown",s=>{const o=e.__dragSource;if(!(s.button!==0||e.disabled||s.target.closest(".remove"))){s.pointerType!=="touch"&&s.preventDefault(),Object.assign(oe,{source:o,element:e,start:{x:s.clientX,y:s.clientY},pointerId:s.pointerId});try{e.setPointerCapture(s.pointerId)}catch{}clearTimeout(oe.timer),s.pointerType==="touch"&&(oe.timer=window.setTimeout(()=>sl(s),260))}}),e.addEventListener("pointermove",s=>{if(c.drag.active||!oe.start||oe.element!==e)return;const o=Math.hypot(s.clientX-oe.start.x,s.clientY-oe.start.y);if(s.pointerType==="touch"){o>10&&(clearTimeout(oe.timer),oe.start=null);return}o>=6&&sl(s)});const n=()=>{oe.element===e&&!c.drag.active&&(clearTimeout(oe.timer),oe.start=null)};e.addEventListener("pointerup",n),e.addEventListener("pointercancel",n)},updated(e,t){e.__dragSource=t.value}};function sl(e){if(c.drag.active||!oe.start||!oe.source||!oe.element)return;c.drag.active=!0,c.drag.moving=oe.source.kind==="tile"?oe.source.tile:ya(oe.source.id),c.drag.preview=null,oe.target=null,getSelection()?.removeAllRanges();const t=oe.element.getBoundingClientRect(),n=oe.element.cloneNode(!0);n.classList.add("drag-ghost"),n.style.width=`${t.width}px`,n.style.height=`${t.height}px`,oe.offset={x:e.clientX-t.left,y:e.clientY-t.top},document.body.append(n),oe.ghost=n,document.addEventListener("pointermove",Fo),document.addEventListener("pointerup",Is),document.addEventListener("pointercancel",Is);try{oe.element.releasePointerCapture(oe.pointerId)}catch{}try{document.documentElement.setPointerCapture(oe.pointerId)}catch{}document.addEventListener("touchmove",Pa,{passive:!1}),oe.scroller=window.setInterval(()=>{if(!oe.last)return;const s=document.querySelector(".canvas");if(!s)return;const o=s.getBoundingClientRect(),l=oe.last.xo.right-60?12:0,a=oe.last.yo.bottom-60?12:0;(l||a)&&(s.scrollBy(l,a),No(Oa(oe.last.x,oe.last.y)))},16),No(-1),Fo(e)}function Pa(e){c.drag.active&&e.preventDefault()}function Is(e){e.pointerId===oe.pointerId&&Id(e.type==="pointerup")}function Fo(e){!oe.ghost||e.pointerId!==oe.pointerId||(oe.last={x:e.clientX,y:e.clientY},oe.ghost.style.transform=`translate(${e.clientX-oe.offset.x}px, ${e.clientY-oe.offset.y}px)`,No(Oa(e.clientX,e.clientY)))}function Oa(e,t){let n=null,s=1/0;for(const l of document.querySelectorAll(".pages [data-slot]")){const a=l.getBoundingClientRect(),r=Math.hypot(Math.max(a.left-e,0,e-a.right),Math.max(a.top-t,0,t-a.bottom));r16)return-1;let o=Number(n.cell.dataset.slot);return n.cell.classList.contains("wide")&&e>(n.r.left+n.r.right)/2&&(o+=1),o}function No(e){oe.target===e||!c.layout||!c.drag.moving||(oe.target=e,c.drag.preview=e>=0?ma(c.layout.tiles,c.drag.moving,e):null)}function Id(e){const t=c.drag.preview,n=c.drag.moving;document.removeEventListener("pointermove",Fo),document.removeEventListener("pointerup",Is),document.removeEventListener("pointercancel",Is),document.removeEventListener("touchmove",Pa);try{document.documentElement.releasePointerCapture(oe.pointerId)}catch{}if(oe.ghost?.remove(),Object.assign(oe,{ghost:null,suppressUntil:Date.now()+400,last:null,start:null,target:null,element:null,source:null}),clearInterval(oe.scroller),c.drag.active=!1,c.drag.preview=null,c.drag.moving=null,e&&t&&n&&c.layout){const s=c.layout.tiles.map(o=>`${o.entity}@${o.slot}`).join();for(const{tile:o,slot:l}of t)o.slot=l,c.layout.tiles.includes(o)||c.layout.tiles.push(o);c.layout.tiles.sort((o,l)=>o.slot-l.slot),c.layout.tiles.map(o=>`${o.entity}@${o.slot}`).join()!==s&&Qe(),s.includes(`${n.entity}@`)||Gs(n,n.slot)}}window.addEventListener("click",e=>{Date.now()t.tile.name||os(t.tile.entity)),s=k(()=>st(t.tile)),o=k(()=>c.inventory.backgrounds?.[t.tile.options?.background||""]?.color),l=k(()=>t.tile.options?.background==="none"),a=k(()=>t.tile.options?.display||"standard"),r=k(()=>a.value!=="standard"?ba[a.value]||a.value:""),d=k(()=>ga(t.tile,c.inventory)),u=k(()=>t.tile.entity.split(".")[0]),f=k(()=>c.inventory.icons?.controls||{}),p=V=>f.value[V]?be(f.value[V]):"",_=k(()=>c.selectedTile===t.tile.entity&&c.inspector?.kind==="tile"),T=k(()=>!t.placeholder&&c.layout?.tiles.includes(t.tile)),M=k(()=>`${n.value}, slot ${t.slot%Lt+1} on page ${As(t.slot)+1}. Enter: configure, arrow keys: move`),I=k(()=>new Date(c.now)),$=k(()=>(I.value.getHours()%12+I.value.getMinutes()/60)*30),x=k(()=>I.value.getMinutes()*6),O=k(()=>u.value==="screen"?null:Ec(t.tile.entity)),J=k(()=>!O.value||["unavailable","unknown",""].includes(O.value.state)),C=k(()=>!!O.value&&!J.value&&O.value.state!=="off"&&O.value.state!=="closed"&&O.value.state!=="standby"&&O.value.state!=="idle"&&O.value.state!=="docked"),z=k(()=>["light","switch","input_boolean","fan"].includes(u.value)&&O.value?.state==="on"),P=k(()=>O.value?.a?.unit_of_measurement),S=V=>V.charAt(0).toUpperCase()+V.slice(1).replace(/_/g," "),b={"clear-night":"Clear, night",cloudy:"Cloudy",exceptional:"Exceptional",fog:"Fog",hail:"Hail",lightning:"Lightning","lightning-rainy":"Lightning, rainy",partlycloudy:"Partly cloudy",pouring:"Pouring",rainy:"Rainy",snowy:"Snowy","snowy-rainy":"Snowy, rainy",sunny:"Sunny",windy:"Windy","windy-variant":"Windy"},A=["scene","script","button","input_button"],q=k(()=>{const V=O.value;if(!V||A.includes(u.value))return r.value;if(J.value)return V.state==="unknown"?"Unknown":"Unavailable";const Q=V.a||{};return u.value==="climate"?`${Q.current_temperature!==void 0?`${Q.current_temperature}° · `:""}${V.word||S(V.state)}`:u.value==="weather"?`${V.word||b[V.state]||S(V.state)}${Q.temperature!==void 0?` · ${Q.temperature}°`:""}`:u.value==="cover"&&Q.current_position!==void 0&&Q.current_position>0&&Q.current_position<100?`${V.word||S(V.state)} · ${Q.current_position} %`:u.value==="media_player"&&Q.media_title?`${V.word||S(V.state)} · ${Q.media_title}`:u.value==="sensor"?`${V.state}${P.value?` ${P.value}`:""}`:(u.value==="timer",V.word||S(V.state))}),W=k(()=>O.value&&!J.value?O.value.state:"—"),le=k(()=>{const V=O.value;if(!V||J.value)return 0;const Q=V.a||{};if(u.value==="light")return V.state==="on"?Q.brightness!==void 0?Math.round(Q.brightness/255*100):100:0;if(u.value==="fan")return V.state==="on"?Q.percentage??100:0;if(u.value==="cover")return Q.current_position??(V.state==="open"?100:0);if(u.value==="media_player")return Math.round((Q.volume_level??0)*100);if(u.value==="number"||u.value==="input_number"){const Ee=Number(V.state),pt=Number(Q.min??0),Ze=Number(Q.max??100);return Number.isFinite(Ee)&&Ze>pt?Math.round((Ee-pt)/(Ze-pt)*100):0}return 0}),Z=k(()=>({background:`linear-gradient(to right, ${le.value?"#ffbf38":"#c9ccd1"} ${le.value}%, ${le.value?"#fff1d3":"#e6e8ec"} ${le.value}%)`})),B=k(()=>({background:`linear-gradient(to right, #2196f3 ${le.value}%, #d3e8fb ${le.value}%)`})),X=k(()=>{const V=O.value?.a?.temperature;return V!=null?`${V}°`:"—"});async function ce(V){if(V.key==="Enter"||V.key===" "){V.preventDefault(),Oo(t.tile.entity);return}const Q={ArrowLeft:-1,ArrowRight:1,ArrowUp:-2,ArrowDown:2}[V.key];Q&&(V.preventDefault(),Gs(t.tile,t.tile.slot+(s.value?Math.sign(Q)*2:Q))&&(await js(),document.querySelector(`.pages [data-slot="${t.tile.slot}"]`)?.focus()))}return(V,Q)=>ye((h(),m("div",{class:ue(["tile",{wide:s.value,bare:l.value,placeholder:e.placeholder||!T.value,chosen:_.value}]),"data-slot":e.slot,style:Pe(o.value&&!l.value?{backgroundColor:o.value}:void 0),tabindex:T.value?0:-1,role:T.value?"button":void 0,"aria-label":T.value?M.value:void 0,onClick:Q[1]||(Q[1]=Ee=>T.value&&v(Oo)(e.tile.entity)),onKeydown:Q[2]||(Q[2]=Ee=>T.value&&ce(Ee))},[a.value==="analog"?(h(),m(U,{key:0},[(h(),m("svg",Ld,[Q[3]||(Q[3]=i("circle",{cx:"30",cy:"30",r:"27",fill:"#fff",stroke:"#c9ccd1"},null,-1)),(h(),m(U,null,ie([0,90,180,270],Ee=>i("line",{key:Ee,x1:"30",y1:"5",x2:"30",y2:"9",stroke:"#1b1b1b","stroke-width":"1.5",transform:`rotate(${Ee} 30 30)`},null,8,Dd)),64)),i("line",{x1:"30",y1:"30",x2:"30",y2:"16",stroke:"#1b1b1b","stroke-width":"2.4","stroke-linecap":"round",transform:`rotate(${$.value} 30 30)`},null,8,Fd),i("line",{x1:"30",y1:"30",x2:"30",y2:"11",stroke:"#1b1b1b","stroke-width":"1.6","stroke-linecap":"round",transform:`rotate(${x.value} 30 30)`},null,8,Nd),Q[4]||(Q[4]=i("circle",{cx:"30",cy:"30",r:"1.8",fill:"#1b1b1b"},null,-1))])),s.value?(h(),m("span",Rd,[i("span",Hd,[i("span",Ud,y(n.value),1),i("span",jd,y(r.value),1)])])):H("",!0)],64)):a.value==="digital"&&u.value==="screen"?(h(),m(U,{key:1},[i("span",Bd,y(v(be)(v(gs)(e.tile))),1),i("span",Vd,[i("span",Wd,y(String(I.value.getHours()).padStart(2,"0"))+":"+y(String(I.value.getMinutes()).padStart(2,"0")),1),i("span",Kd,y(n.value),1)])],64)):s.value?(h(),m(U,{key:2},[i("span",qd,[i("span",{class:ue(["ic mdi",{lit:z.value}])},y(v(be)(v(gs)(e.tile))),3),i("span",Yd,[i("span",zd,y(n.value),1),a.value==="watch"?(h(),m("span",Jd,[ee(y(W.value),1),P.value&&!J.value?(h(),m("small",Gd,y(P.value),1)):H("",!0)])):q.value?(h(),m("span",{key:1,class:ue(["st",{off:J.value}])},y(q.value),3)):H("",!0)])]),e.tile.options?.inline==="slider"?(h(),m("span",{key:0,class:"mini-slider",style:Pe(Z.value)},null,4)):H("",!0),d.value?(h(),m("span",Xd,[d.value==="toggle"?(h(),m("span",{key:0,class:ue(["tog",{off:!C.value}])},null,2)):d.value==="setpoint"?(h(),m("span",Qd,[i("span",Zd,y(p("minus")||"−"),1),i("b",null,y(X.value),1),i("span",ef,y(p("plus")||"+"),1)])):d.value==="stepper"&&u.value.endsWith("select")?(h(),m(U,{key:2},[i("span",tf,y(p("chevron-left")),1),i("span",nf,y(p("chevron-right")),1)],64)):d.value==="stepper"?(h(),m("span",sf,[i("span",of,y(p("minus")||"−"),1),i("b",null,y(W.value),1),i("span",lf,y(p("plus")||"+"),1)])):d.value==="mode"?(h(),m(U,{key:4},[i("span",af,y(p("power")),1),i("span",rf,y(p("fire")),1),i("span",uf,y(p("snowflake")),1)],64)):d.value==="volume"?(h(),m(U,{key:5},[i("span",{class:"range",style:Pe(B.value)},null,4),i("span",cf,y(p("volume-high")),1)],64)):d.value==="playback"?(h(),m(U,{key:6},[i("span",df,y(p("skip-previous")),1),i("span",ff,y(p(C.value?"pause":"play")||p("play")),1),i("span",pf,y(p("skip-next")),1)],64)):d.value==="buttons"&&u.value==="cover"?(h(),m(U,{key:7},[i("span",hf,y(p("arrow-expand-horizontal")),1),i("span",vf,y(p("stop")),1),i("span",mf,y(p("arrow-collapse-horizontal")),1)],64)):d.value==="buttons"&&u.value==="vacuum"?(h(),m(U,{key:8},[i("span",yf,y(p("play")),1),i("span",gf,y(p("stop")),1),i("span",bf,y(p("home-map-marker")),1)],64)):d.value==="buttons"&&u.value==="timer"?(h(),m(U,{key:9},[i("span",wf,y(p("play")),1),i("span",_f,y(p("close")),1)],64)):d.value==="run"?(h(),m("span",kf,y({scene:"Activate",script:"Run"}[u.value]||"Press"),1)):(h(),m("span",{key:11,class:"range",style:Pe({background:`linear-gradient(to right, #2196f3 ${le.value}%, #d3e8fb ${le.value}%)`})},null,4))])):H("",!0)],64)):(h(),m(U,{key:3},[i("span",{class:ue(["ic mdi",{lit:z.value}])},y(v(be)(v(gs)(e.tile))),3),i("span",$f,[a.value==="watch"?(h(),m("span",xf,[ee(y(W.value),1),P.value&&!J.value?(h(),m("small",Sf,y(P.value),1)):H("",!0)])):H("",!0),i("span",Cf,y(n.value),1),a.value!=="watch"&&q.value?(h(),m("span",{key:1,class:ue(["st",{off:J.value}])},y(q.value),3)):H("",!0),e.tile.options?.inline==="slider"?(h(),m("span",{key:2,class:"mini-slider",style:Pe(Z.value)},null,4)):H("",!0)])],64)),T.value?(h(),m("button",{key:4,type:"button",class:"remove",title:"Remove tile","aria-label":`Remove ${n.value}`,onClick:Q[0]||(Q[0]=it(Ee=>v(xa)(e.tile),["stop"]))},"✕",8,Af)):H("",!0)],46,Md)),[[v(Ea),{kind:"tile",tile:e.tile}]])}}),Ef=["viewBox","aria-label"],Pf=["y"],Of=["cx","cy","r","stroke","stroke-width"],If=["x1","y1","x2","y2","stroke","stroke-width"],Mf=["x","y","fill"],Lf=["x","y"],Ia=Ce({__name:"TopbarSvg",props:{items:{},nameText:{},single:{type:Boolean}},setup(e,{expose:t}){const n=e,s=k(()=>{c.fontsVersion,c.now,c.topbarPreviews;const $=n.items||Ht();return fa($,_a.value,n.nameText??(c.layout?.title||"Home"),Vt)}),o=k(()=>s.value.metrics),l=k(()=>n.single?Math.round(o.value.text*1.4):o.value.top+Math.round(o.value.name*.45)),a=k(()=>n.single?Math.round(o.value.text*1.05):o.value.top),r=k(()=>{if(!n.single)return s.value.placed;const $=s.value.parts[0];return $&&($.x=0),$?[$]:[]}),d=k(()=>n.single?`-2 0 ${Math.max(1,r.value[0]?.width||1)+4} ${l.value}`:`0 0 ${o.value.width} ${l.value}`),u=k(()=>a.value+(s.value.zero.top+s.value.zero.bottom)/2),f=k(()=>vc(s.value.nameText,s.value.fonts.name,Math.min(s.value.natural,s.value.nameRoom))),p=k(()=>new Date(c.now));function _($){const x=p.value;return[[(x.getHours()%12+x.getMinutes()/60)*30,$*.24],[x.getMinutes()*6,$*.34]].map(([O,J])=>{const C=O*Math.PI/180;return{x2:J*Math.sin(C),y2:-J*Math.cos(C)}})}const T=$=>$.x-$.icon.ink.left,M=$=>($.icon?$.x+($.icon.ink.right-$.icon.ink.left)+s.value.gaps.icon:$.x)-$.text.ink.left,I=k(()=>`${(Math.max(1,r.value[0]?.width||1)+4)*(26/o.value.icon)}px`);return t({lay:s}),($,x)=>(h(),m("svg",{viewBox:d.value,role:"img","aria-label":e.single?"How it looks on the screen":`Top bar: ${s.value.nameText}`,style:Pe(e.single?{width:I.value}:void 0)},[e.single?H("",!0):(h(),m("text",{key:0,x:"0",y:o.value.top,fill:"#1b1b1b",style:Pe({font:s.value.fonts.name})},y(f.value),13,Pf)),i("g",null,[(h(!0),m(U,null,ie(r.value,O=>(h(),m(U,{key:O.index},[O.dial?(h(),m(U,{key:0},[i("circle",{cx:O.x+O.dial/2,cy:u.value,r:O.dial/2-Math.max(1,Math.round(O.dial/10))/2,fill:"none",stroke:O.view.color||"#46525e","stroke-width":Math.max(1,Math.round(O.dial/10))},null,8,Of),(h(!0),m(U,null,ie(_(O.dial),(J,C)=>(h(),m("line",{key:C,x1:O.x+O.dial/2,y1:u.value,x2:O.x+O.dial/2+J.x2,y2:u.value+J.y2,stroke:O.view.color||"#46525e","stroke-width":Math.max(1,Math.round(O.dial*.075)),"stroke-linecap":"round"},null,8,If))),128))],64)):(h(),m(U,{key:1},[O.icon?(h(),m("text",{key:0,x:T(O),y:u.value-(O.icon.ink.top+O.icon.ink.bottom)/2,fill:O.view.color||"#46525e",style:Pe({font:s.value.fonts.icon})},y(O.icon.glyph),13,Mf)):H("",!0),O.text?(h(),m("text",{key:1,x:M(O),y:a.value,fill:"#46525e",style:Pe({font:s.value.fonts.text})},y(O.text.value),13,Lf)):H("",!0)],64))],64))),128))])],12,Ef))}}),Df={class:"page"},Ff={class:"page-label"},Nf={key:1},Rf={class:"tiles"},Hf=["data-slot","aria-label","onClick"],Uf=Ce({__name:"DevicePage",props:{page:{},entries:{},pages:{},moving:{}},setup(e){const t=e,n=k(()=>new Map(t.entries.map(u=>[u.slot,u]))),s=k(()=>new Set(t.entries.filter(u=>st(u.tile)).map(u=>u.slot+1))),o=k(()=>Array.from({length:Lt},(u,f)=>t.page*Lt+f).filter(u=>!s.value.has(u))),l=k(()=>t.pages>1&&!t.entries.some(u=>As(u.slot)===t.page)),a=k(()=>c.inspector?.kind==="bar"||c.inspector?.kind==="bar-add"),r=k(()=>t.entries.filter(u=>As(u.slot)===t.page).reduce((u,f)=>u+(st(f.tile)?2:1),0));function d(u){const f=c.insertAt===u;c.insertAt=f?-1:u,c.insertAt>=0&&document.querySelector("#search")?.focus()}return(u,f)=>(h(),m("div",Df,[i("div",Ff,[i("span",null,"Page "+y(e.page+1),1),l.value?(h(),m("button",{key:0,type:"button",class:"btn mini",title:"The pages after this one shift up one slot",onClick:f[0]||(f[0]=p=>v(Oc)(e.page))},"Remove page")):(h(),m("span",Nf,y(r.value)+" / "+y(v(Lt)),1))]),i("div",{class:ue(["device",{cyd:!v(ii)}])},[i("div",{class:ue(["bar-wrap",{selected:a.value}]),title:"Edit top bar",role:"button",tabindex:"0",onClick:f[1]||(f[1]=p=>v(Pt)(0)),onKeydown:f[2]||(f[2]=ca(it(p=>v(Pt)(0),["prevent"]),["enter"]))},[$e(Ia)],34),i("div",Rf,[(h(!0),m(U,null,ie(o.value,p=>(h(),m(U,{key:p},[n.value.get(p)?(h(),Ke(Tf,{key:0,tile:n.value.get(p).tile,slot:p,placeholder:n.value.get(p).tile===e.moving},null,8,["tile","slot","placeholder"])):(h(),m("button",{key:1,type:"button",class:ue(["cell",{"insert-here":v(c).insertAt===p}]),"data-slot":p,title:"Empty slot. Click to add a tile here, or drag one over.","aria-label":`Empty slot ${p%v(Lt)+1} on page ${e.page+1}: add the next tile here`,onClick:_=>d(p)},[f[3]||(f[3]=i("span",null,"+",-1)),i("small",null,y(v(c).insertAt===p?"Next tile goes here":"Empty"),1)],10,Hf))],64))),128))])],2)]))}}),jf={class:"library",id:"library"},Bf={class:"lib-head"},Vf={class:"lib-title"},Wf={class:"filters",id:"filters"},Kf=["aria-pressed","onClick"],qf={class:"lib-row"},Yf=["value"],zf=["aria-pressed"],Jf={class:"lib-list",id:"results","aria-live":"polite"},Gf=["title","disabled","onClick"],Xf={class:"tx"},Qf={key:0,class:"hint"},Zf={key:1,class:"hint"},ep={class:"lib-foot"},tp=Ce({__name:"Library",setup(e){const t=[["","All"],["light","Lights"],["climate","Climate"],["switch","Switches"],["binary_sensor","Status"],["button","Actions"],["script","Scripts"],["fan","Fans"],["cover","Covers"],["scene","Scenes"],["vacuum","Vacuum"],["sensor","Sensors"],["media_player","Media"],["weather","Weather"],["number","Values"],["select","Selects"],["person","People"],["timer","Timers"],["screen","Clock"]],n={switch:"input_boolean",number:"input_number",select:"input_select",weather:"sun",button:"input_button"},s=k(()=>new Set(c.layout?.tiles.map(u=>u.entity)||[])),o=k(()=>[...new Set(c.inventory.entities.map(u=>u.area).filter(u=>!!u))].sort((u,f)=>u.localeCompare(f))),l=k(()=>{const u=c.search.toLocaleLowerCase(),f=c.filter,p=c.room;return[...c.inventory.builtin||[],...c.inventory.entities].filter(_=>_.tile!==!1&&(ii.value||!["camera","image"].includes(_.id.split(".")[0]))&&(!f||_.id.startsWith(f+".")||n[f]===_.id.split(".")[0])&&(!p||_.area===p)&&(!c.hidePlaced||!s.value.has(_.id))&&`${_.name} ${_.id} ${_.device||""} ${_.area||""}`.toLocaleLowerCase().includes(u))}),a=k(()=>(c.layout?.tiles.length||0)>=cn.value),r=k(()=>c.inventory.entities.length),d=u=>{const f=u.id.split(".")[0];return u.state==="unavailable"||u.state==="unknown"?"gone":["light","switch","input_boolean","fan"].includes(f)&&u.state==="on"?"on":""};return(u,f)=>(h(),m("aside",jf,[i("div",Bf,[i("div",Vf,[f[3]||(f[3]=ee("Library ",-1)),i("small",null,y(r.value)+" entities",1)]),ye(i("input",{id:"search","onUpdate:modelValue":f[0]||(f[0]=p=>v(c).search=p),type:"search",placeholder:"Search by name, device, or room…",autocomplete:"off","aria-label":"Add an entity"},null,512),[[Ie,v(c).search]]),i("div",Wf,[(h(),m(U,null,ie(t,([p,_])=>i("button",{key:p,type:"button","aria-pressed":v(c).filter===p?"true":"false",onClick:T=>v(c).filter=p},[p?(h(),m("span",{key:0,class:"domain-icon",style:Pe({color:v(bt)(p+".")[2],background:v(bt)(p+".")[3]}),"aria-hidden":"true"},y(v(bt)(p+".")[1]),5)):H("",!0),ee(y(_),1)],8,Kf)),64))]),i("div",qf,[ye(i("select",{id:"room","onUpdate:modelValue":f[1]||(f[1]=p=>v(c).room=p),"aria-label":"Room"},[f[4]||(f[4]=i("option",{value:""},"All rooms",-1)),(h(!0),m(U,null,ie(o.value,p=>(h(),m("option",{key:p,value:p},y(p),9,Yf))),128))],512),[[un,v(c).room]]),i("button",{type:"button",class:"chip-toggle",id:"hide-placed","aria-pressed":v(c).hidePlaced?"true":"false",title:"Hide what is already on this screen",onClick:f[2]||(f[2]=p=>v(c).hidePlaced=!v(c).hidePlaced)},"Hide placed",8,zf)])]),i("div",Jf,[(h(!0),m(U,null,ie(l.value.slice(0,80),p=>ye((h(),m("button",{key:p.id,type:"button",class:"ent",title:p.id,disabled:s.value.has(p.id)||a.value,onClick:_=>v($a)(p.id)},[i("span",{class:ue(["av mdi",d(p)]),style:Pe({color:v(bt)(p.id)[2],background:v(bt)(p.id)[3]})},y(v(c).inventory.icons?v(be)(v(Xt)(p.id)):v(bt)(p.id)[1]),7),i("span",Xf,[i("b",null,y(p.name),1),i("small",null,y([v(bt)(p.id)[0],p.area,p.device].filter(Boolean).join(" · ")),1)]),i("span",{class:ue(["add",{done:s.value.has(p.id)}])},y(s.value.has(p.id)?"✓":"+"),3)],8,Gf)),[[v(Ea),{kind:"entity",id:p.id}]])),128)),l.value.length?l.value.length>80?(h(),m("p",Zf,y(l.value.length)+" results. Keep typing to narrow it down.",1)):H("",!0):(h(),m("p",Qf,y(v(c).hidePlaced&&!v(c).search&&!v(c).filter&&!v(c).room?"Everything here is already on this screen.":"No entities found. Try a different name, room or filter."),1))]),i("div",ep,y(a.value?`This screen holds ${v(cn)} tiles${v(cn)===10?"; update its firmware for 20":""}.`:"Drag onto a page, or tap + to add to the first free slot. ⌘K searches everything."),1)]))}}),np={class:"canvas-head"},sp={id:"count"},op={key:0,id:"no-tiles"},ip={key:1},lp={key:2,id:"positions-hint",class:"warn"},ap={class:"pages",id:"layout-preview","aria-label":"Screen layout"},rp={class:"page-label"},up=["tabindex"],cp=Ce({__name:"LayoutView",setup(e){const t=k(()=>c.layout),n=k(()=>c.drag.preview||ft(t.value)),s=k(()=>jt(n.value,t.value.pages)),o=k(()=>Ic()),l=k(()=>s.valuegc(t.value.tiles)&&!wn(0,2,26)?`Empty slots and fixed positions work from firmware 0.2.26. This screen (firmware ${Ct.value?.firmware||"unknown"}) shifts the tiles up to the first free slot until that update.`:"");function r(d){d.target.closest(".device, .page-label, .canvas-head")||c.inspector&&Re()}return(d,u)=>(h(),m(U,null,[i("div",{class:"canvas",id:"canvas",onClick:r},[i("div",np,[i("b",sp,y(s.value)+" "+y(s.value===1?"page":"pages")+" · "+y(t.value.tiles.length)+" / "+y(v(cn))+" tiles",1),t.value.tiles.length?(h(),m("span",ip,"Tap the top bar or a tile to change it. Drag to move; drop on the next page for a new one.")):(h(),m("span",op,"Add your first light, scene, or device from the library.")),a.value?(h(),m("span",lp,y(a.value),1)):H("",!0)]),i("div",ap,[(h(!0),m(U,null,ie(o.value,f=>(h(),Ke(Uf,{key:f,page:f-1,entries:n.value,pages:s.value,moving:v(c).drag.moving},null,8,["page","entries","pages","moving"]))),128)),i("div",{class:ue(["page ghost",{disabled:!l.value}])},[i("div",rp,[i("span",null,"Page "+y(o.value+1),1)]),i("div",{class:ue(["device",{cyd:v(Ct)?.board!=="guition"}]),id:"add-page",role:"button",tabindex:l.value?0:-1,onClick:u[0]||(u[0]=f=>l.value&&v(zi)()),onKeydown:u[1]||(u[1]=ca(it(f=>l.value&&v(zi)(),["prevent"]),["enter"]))},y(l.value?"+ Add page":`${v(xn)} pages is the most`),43,up)],2)])]),$e(tp)],64))}}),dp={class:"status",id:"settings-status",role:"status"},fp={key:0,class:"set-grid",id:"settings-groups"},pp={class:"mdi"},hp=["data-setting","title","onClick"],vp=["id"],mp={class:"s-control"},yp=["id","aria-checked","aria-labelledby","disabled","onClick"],gp=["aria-labelledby"],bp=["aria-pressed","disabled","onClick"],wp={key:2,class:"step"},_p=["aria-label","disabled","onPointerdown","onClick"],kp={class:"mdi"},$p=["id","aria-labelledby"],xp=["aria-label","disabled","onPointerdown","onClick"],Sp={class:"mdi"},Cp=Ce({__name:"SettingsTab",setup(e){const t=k(()=>li()),n=k(()=>Cn()),s=k(()=>t.value?.owner==="screen"&&!Ct.value?.online),o=k(()=>Hc.map(M=>({...M,rows:M.rows.filter(I=>t.value?.keys.includes(I.key))})).filter(M=>M.rows.length)),l=M=>s.value||!!t.value?.unavailable.includes(M.key),a=M=>M.needs?!!n.value[M.needs]:!0,r=k(()=>s.value?"This screen is offline. Its settings can change once it's back.":c.settingPending?"Saving…":t.value?.owner==="screen"?"Changes apply on the screen at once, and show up here when they change there.":"Changes apply at once. Firmware 0.2.49 lets the screen keep them itself."),d=(M,I)=>{const $=n.value[M.key];return l(M)||!a(M)||$===null||$===void 0?!0:M.kind!=="moment"&&Zi(M,$,I,!1,n.value)===$},u=new WeakMap;function f(M,I,$){const x=Cn(),O=Zi(M,x[M.key],I,$,x);O!==x[M.key]&&Fn(M.key,O,600)}function p(M,I,$){const x=M.currentTarget;if(x.disabled||M.button!==0)return;const O={timer:0,held:!1};u.set(x,O);let J=0;O.timer=window.setTimeout(function C(){O.held=!0,J+=1,f(I,$,J>5),O.timer=window.setTimeout(C,180)},450)}function _(M){const I=u.get(M.currentTarget);I&&clearTimeout(I.timer)}function T(M,I,$){const x=u.get(M.currentTarget);if(x?.held){x.held=!1;return}f(I,$,!1)}return(M,I)=>(h(),m("div",{class:ue(["settings",{offline:s.value}]),id:"general-settings"},[i("span",dp,y(r.value),1),t.value?(h(),m("div",fp,[(h(!0),m(U,null,ie(o.value,$=>(h(),m("section",{key:$.title,class:"set-card"},[i("h4",null,[i("span",pp,y(v(be)($.icon)),1),ee(y($.title),1)]),(h(!0),m(U,null,ie($.rows,x=>(h(),m("div",{key:x.key,class:ue(["srow",[`setting-${x.kind}`,{inactive:!a(x)||l(x)}]]),"data-setting":x.key,title:l(x)&&!s.value?"This entity is off in Home Assistant, or the screen is restarting.":"",onClick:O=>x.kind==="toggle"&&O.target.closest(".srow")===O.currentTarget&&!O.target.closest("button")&&!l(x)&&v(Fn)(x.key,!n.value[x.key],150)},[i("span",{class:"s-label",id:`setting-label-${x.key}`},y(x.label),9,vp),i("div",mp,[x.kind==="toggle"?(h(),m("button",{key:0,type:"button",class:ue(["switch",{unknown:n.value[x.key]===null||n.value[x.key]===void 0}]),role:"switch",id:`setting-${x.key}`,"aria-checked":n.value[x.key]?"true":"false","aria-labelledby":`setting-label-${x.key}`,disabled:l(x),onClick:it(O=>v(Fn)(x.key,!n.value[x.key],150),["stop"])},null,10,yp)):x.kind==="choice"?(h(),m("div",{key:1,class:"seg",role:"group","aria-labelledby":`setting-label-${x.key}`},[(h(!0),m(U,null,ie(x.options,([O,J])=>(h(),m("button",{key:String(O),type:"button","aria-pressed":n.value[x.key]===O?"true":"false",disabled:l(x),onClick:C=>v(Fn)(x.key,O,150)},y(J),9,bp))),128))],8,gp)):(h(),m("div",wp,[i("button",{type:"button","aria-label":`${x.label} lower`,disabled:d(x,-1),onPointerdown:O=>p(O,x,-1),onPointerup:_,onPointercancel:_,onPointerleave:_,onClick:O=>T(O,x,-1)},[i("span",kp,y(v(be)("F0374")),1)],40,_p),i("output",{id:`setting-${x.key}`,"aria-labelledby":`setting-label-${x.key}`},y(v(Vc)(x,n.value)),9,$p),i("button",{type:"button","aria-label":`${x.label} higher`,disabled:d(x,1),onPointerdown:O=>p(O,x,1),onPointerup:_,onPointercancel:_,onPointerleave:_,onClick:O=>T(O,x,1)},[i("span",Sp,y(v(be)("F0415")),1)],40,xp)]))])],10,hp))),128))]))),128))])):H("",!0)],2))}}),Ap={class:"seg wrap",role:"group"},Tp=["disabled","aria-pressed","onClick"],at=Ce({__name:"Segmented",props:{choices:{},value:{},disabled:{type:Boolean}},emits:["pick"],setup(e,{emit:t}){const n=t;return(s,o)=>(h(),m("div",Ap,[(h(!0),m(U,null,ie(e.choices,([l,a])=>(h(),m("button",{key:String(l),type:"button",disabled:e.disabled,"aria-pressed":String(l)===String(e.value)?"true":"false",onClick:r=>n("pick",l)},y(a),9,Tp))),128))]))}}),Ep={class:"f"},Pp={key:0},Op={key:1,class:"warn"},Ip=["aria-expanded"],Mp={class:"tx"},Lp={key:0,class:"mono"},Dp={class:"link"},Fp={key:0,class:"picker"},Np={class:"action-list"},Rp=["aria-pressed","onClick"],Hp={key:0,class:"hint"},Up={key:1,class:"warn"},jp={class:"f-label"},Bp=["aria-label","value","onChange"],Vp=["value"],Wp={key:3,class:"action-number"},Kp=["aria-label","value","onInput"],qp=["onClick"],Yp={key:4,class:"action-number"},zp=["aria-label","min","max","step","value","placeholder","onInput"],Jp={key:0},Gp=["aria-label","value","placeholder","onInput"],Xp={key:6},Qp={key:0,class:"warn"},Zp={key:3},eh=Ce({__name:"ActionPicker",props:{tile:{}},setup(e){const t=e,n=k(()=>c.entityActions[t.tile.entity]),s=k(()=>t.tile.options?.action),o=k(()=>n.value?.find(C=>C.action===s.value?.action)),l=k(()=>c.actionPickerOpen||!s.value),a=k(()=>{const C=c.actionSearch.trim().toLocaleLowerCase();return(n.value||[]).filter(z=>`${z.name} ${z.action} ${z.description}`.toLocaleLowerCase().includes(C))});n.value===void 0&&Tc(t.tile.entity);function r(C){const z=C.action===s.value?.action;t.tile.options={...t.tile.options,action:z?s.value:{action:C.action}},c.actionPickerOpen=!1,Qe()}function d(C,z){const P={...t.tile.options?.action?.data||{}};z===void 0?delete P[C]:P[C]=z,t.tile.options={...t.tile.options,action:{action:s.value.action,...Object.keys(P).length?{data:P}:{}}},Qe()}const u=k(()=>{if(!o.value)return[];const C=t.tile.options?.action?.data||{};return o.value.fields.filter(z=>z.required&&C[z.key]===void 0).map(z=>z.name)}),f=C=>Object.keys(C.selector||{})[0]||"text",p=C=>(C.selector||{})[f(C)]||{},_=C=>C.example===void 0?"":typeof C.example=="string"?C.example:JSON.stringify(C.example);function T(C){const z=p(C),P=f(C);return Array.isArray(C.options)?C.options.map(S=>[S,S]):P==="select"&&Array.isArray(z.options)&&!z.multiple?z.options.map(S=>S&&typeof S=="object"?[String(S.value),String(S.label??S.value)]:[String(S),String(S)]):null}const M=C=>"#"+C.map(z=>Math.max(0,Math.min(255,Number(z)||0)).toString(16).padStart(2,"0")).join(""),I=C=>Array.isArray(C)&&C.length===3?M(C):"#ffffff",$=C=>C===void 0?"":typeof C=="string"?C:JSON.stringify(C);function x(C,z){const P=z.trim();if(!P)return d(C.key,void 0);if(f(C)==="text")return d(C.key,z);try{d(C.key,JSON.parse(P))}catch{d(C.key,z)}}function O(C,z){d(C.key,z===""||!Number.isFinite(Number(z))?void 0:Number(z))}const J=C=>p(C).unit_of_measurement||f(C)==="color_temp"&&p(C).unit||"";return(C,z)=>(h(),m("div",Ep,[z[3]||(z[3]=i("span",{class:"f-label"},"Action",-1)),n.value===void 0?(h(),m("small",Pp,"Asking Home Assistant which actions this entity has…")):n.value===null?(h(),m("small",Op,"Home Assistant isn't answering right now. Try again in a moment.")):(h(),m(U,{key:2},[i("button",{type:"button",class:"row","aria-expanded":l.value?"true":"false",onClick:z[0]||(z[0]=P=>v(c).actionPickerOpen=!l.value)},[i("span",Mp,[i("b",null,y(o.value?o.value.name:s.value?s.value.action:"Choose an action"),1),s.value?(h(),m("small",Lp,y(s.value.action),1)):H("",!0)]),i("span",Dp,y(l.value?"Close":"Change"),1)],8,Ip),l.value?(h(),m("div",Fp,[ye(i("input",{"onUpdate:modelValue":z[1]||(z[1]=P=>v(c).actionSearch=P),type:"search",placeholder:"Search, for example toggle, position, or play","aria-label":"Search for an action"},null,512),[[Ie,v(c).actionSearch]]),i("div",Np,[(h(!0),m(U,null,ie(a.value,P=>(h(),m("button",{key:P.action,type:"button",class:"action-choice","aria-pressed":P.action===s.value?.action?"true":"false",onClick:S=>r(P)},[i("strong",null,y(P.name),1),i("small",null,y(P.description?`${P.action} · ${P.description}`:P.action),1)],8,Rp))),128)),a.value.length?H("",!0):(h(),m("p",Hp,"No action found."))])])):H("",!0),s.value&&!o.value?(h(),m("small",Up,"Home Assistant doesn't offer this action for this entity any more, so a tap does nothing. Choose another one.")):H("",!0),o.value&&!l.value?(h(),m(U,{key:2},[(h(!0),m(U,null,ie(o.value.fields,P=>(h(),m("div",{key:P.key,class:"f"},[i("span",jp,y(P.required?P.name:`${P.name} (optional)`),1),f(P)==="boolean"?(h(),Ke(at,{key:0,choices:[["","Not set"],["true","On"],["false","Off"]],value:s.value?.data?.[P.key]===void 0?"":String(s.value?.data?.[P.key]),onPick:S=>d(P.key,S===""?void 0:S==="true")},null,8,["value","onPick"])):T(P)&&T(P).length<=4?(h(),Ke(at,{key:1,choices:[["","Not set"],...T(P)],value:s.value?.data?.[P.key]===void 0?"":String(s.value?.data?.[P.key]),onPick:S=>d(P.key,S===""?void 0:S)},null,8,["choices","value","onPick"])):T(P)?(h(),m("select",{key:2,"aria-label":P.name,value:String(s.value?.data?.[P.key]??""),onChange:S=>d(P.key,S.target.value===""?void 0:S.target.value)},[z[2]||(z[2]=i("option",{value:""},"Not set",-1)),(h(!0),m(U,null,ie(T(P),([S,b])=>(h(),m("option",{key:S,value:S},y(b),9,Vp))),128))],40,Bp)):f(P)==="color_rgb"?(h(),m("div",Wp,[i("input",{type:"color","aria-label":P.name,value:I(s.value?.data?.[P.key]),onInput:S=>d(P.key,[1,3,5].map(b=>parseInt(S.target.value.slice(b,b+2),16)))},null,40,Kp),i("button",{type:"button",class:"btn quiet mini",onClick:S=>d(P.key,void 0)},"Not set",8,qp)])):f(P)==="number"||f(P)==="color_temp"?(h(),m("div",Yp,[i("input",{type:"number","aria-label":P.name,min:p(P).min,max:p(P).max,step:p(P).step==="any"?"any":p(P).step,value:s.value?.data?.[P.key]??"",placeholder:_(P),onInput:S=>O(P,S.target.value)},null,40,zp),J(P)?(h(),m("span",Jp,y(J(P)),1)):H("",!0)])):(h(),m("input",{key:5,type:"text","aria-label":P.name,value:$(s.value?.data?.[P.key]),placeholder:_(P),onInput:S=>x(P,S.target.value)},null,40,Gp)),P.description?(h(),m("small",Xp,y(P.description),1)):H("",!0)]))),128)),u.value.length?(h(),m("small",Qp,"Home Assistant needs "+y(u.value.join(", "))+".",1)):H("",!0)],64)):H("",!0),v(wn)(0,2,58)?H("",!0):(h(),m("small",Zp,"The screen performs an action from firmware 0.2.58: press Update on the screen. Until then a tap works as Automatic."))],64))]))}}),th={class:"f"},nh=["aria-expanded"],sh={class:"av mdi"},oh={class:"tx"},ih={class:"link"},lh={key:0,class:"picker"},ah=["aria-pressed","title"],rh={class:"mdi"},uh=["aria-pressed"],ch={class:"icon-list"},dh={class:"icon-grid"},fh=["title","aria-label","aria-pressed","onClick"],ph={class:"mdi"},hh={key:0,class:"hint"},vh={key:1},Ma=Ce({__name:"IconPicker",props:{selected:{},automatic:{},autoLabel:{},allowNone:{type:Boolean},note:{}},emits:["pick"],setup(e,{emit:t}){const n=e,s=t,o=fe(""),l=k(()=>is(n.selected)),a=k(()=>n.selected==="none"?"":be(l.value?.cp||n.automatic)),r=k(()=>n.selected==="none"?"No icon":l.value?.label||n.autoLabel),d=k(()=>{const u=o.value.trim().toLocaleLowerCase();return(c.inventory.icons?.groups||[]).map(f=>({label:f.label,icons:f.icons.filter(p=>!u||`${p.label} ${p.name.replaceAll("-"," ")} ${f.label}`.toLocaleLowerCase().includes(u))})).filter(f=>f.icons.length)});return(u,f)=>(h(),m("div",th,[f[5]||(f[5]=i("span",{class:"f-label"},"Icon",-1)),i("button",{type:"button",class:"row","aria-expanded":v(c).iconPickerOpen?"true":"false",onClick:f[0]||(f[0]=p=>v(c).iconPickerOpen=!v(c).iconPickerOpen)},[i("span",sh,y(a.value),1),i("span",oh,[i("b",null,y(r.value),1)]),i("span",ih,y(v(c).iconPickerOpen?"Close":"Change"),1)],8,nh),v(c).iconPickerOpen?(h(),m("div",lh,[ye(i("input",{"onUpdate:modelValue":f[1]||(f[1]=p=>o.value=p),type:"search",placeholder:"Search, for example lamp, music, or door","aria-label":"Search for an icon"},null,512),[[Ie,o.value]]),i("button",{type:"button",class:"icon-choice icon-auto","aria-pressed":e.selected==="auto"?"true":"false",title:e.autoLabel,onClick:f[2]||(f[2]=p=>s("pick","auto"))},[i("span",rh,y(v(be)(e.automatic)),1),i("span",null,y(e.autoLabel),1)],8,ah),e.allowNone?(h(),m("button",{key:0,type:"button",class:"icon-choice icon-auto","aria-pressed":e.selected==="none"?"true":"false",title:"No icon",onClick:f[3]||(f[3]=p=>s("pick","none"))},[...f[4]||(f[4]=[i("span",{class:"mdi"},null,-1),i("span",null,"No icon, text only",-1)])],8,uh)):H("",!0),i("div",ch,[(h(!0),m(U,null,ie(d.value,p=>(h(),m("section",{key:p.label},[i("small",null,y(p.label),1),i("div",dh,[(h(!0),m(U,null,ie(p.icons,_=>(h(),m("button",{key:_.name,type:"button",class:"icon-choice",title:_.label,"aria-label":`Icon: ${_.label}`,"aria-pressed":e.selected===_.name?"true":"false",onClick:T=>s("pick",_.name)},[i("span",ph,y(v(be)(_.cp)),1)],8,fh))),128))])]))),128)),d.value.length?H("",!0):(h(),m("p",hh,"No icon found."))])])):H("",!0),e.note?(h(),m("small",vh,y(e.note),1)):H("",!0)]))}}),mh={class:"dr-head"},yh={class:"tx"},gh={class:"mono"},bh={class:"dr-body"},wh={class:"f"},_h=["value","placeholder"],kh={class:"f"},$h={key:0,class:"warn"},xh={class:"f"},Sh={key:1,class:"f"},Ch={key:2,class:"f"},Ah={key:4,class:"f"},Th={key:0,class:"warn"},Eh={key:5,class:"f"},Ph={class:"f"},Oh={class:"sw"},Ih=["aria-label","aria-pressed","onClick"],Mh={class:"dr-foot"},Lh=Ce({__name:"TileInspector",props:{tile:{}},setup(e){const t=e,n=k(()=>t.tile.entity.split(".")[0]),s=k(()=>os(t.tile.entity)),o=k(()=>c.capabilities[t.tile.entity]),l=(q,W)=>t.tile.options?.[q]??W,a=k(()=>l("display",n.value==="screen"?"digital":"standard")),r=k(()=>{const q=n.value==="screen"?[["digital","Digital clock"],["analog","Analog clock"]]:[["standard","Name and status"],["watch","Large value"]],W=o.value;return n.value==="weather"&&(!W||W.displays.includes("forecast")||a.value==="forecast")&&q.push(["forecast","Weather forecast"]),n.value==="sensor"&&(!W||W.displays.includes("graph")||a.value==="graph")&&q.push(["graph","Graph"]),n.value==="sun"&&q.push(["sunpath","Sun path"]),q}),d=k(()=>{const q=o.value;return q&&a.value==="graph"&&!q.displays.includes("graph")?"Home Assistant has no numbers for this entity, so the graph stays empty. Choose another display.":q&&a.value==="forecast"&&!q.displays.includes("forecast")?"This weather service has no daily forecast in Home Assistant. Choose another display.":""}),u=k(()=>l("size","single")),f=k(()=>c.inventory.controls?.[n.value]),p=k(()=>l("controls",f.value?.default)),_=k(()=>{const q=o.value;return(f.value?.choices||[]).filter(W=>!q||W.key==="none"||W.key===p.value||q.controls.includes(W.key)).map(W=>[W.key,W.label])}),T=k(()=>{const q=o.value;return q&&p.value!=="none"&&!q.controls.includes(p.value)?{text:"Home Assistant doesn't offer this control for this entity, so it stays empty on the screen. Choose another one.",warn:!0}:{text:wn(0,2,19)?"On the right of the double-width tile, like the rows in Home Assistant. Tapping the name works as set below.":"The screen shows direct control from firmware 0.2.19; until then the tile stays as it was.",warn:!1}}),M=k(()=>l("tap","auto")),I=k(()=>{const q=[["auto","Automatic"],["detail","Open control"],["none","View only"]];return((o.value?o.value.toggle:qi.includes(n.value))||M.value==="toggle")&&q.push(["toggle","On / off"]),q.push(["action","Perform action"]),q}),$=k(()=>M.value==="toggle"&&o.value&&!o.value.toggle?{text:"Home Assistant can't turn this on and off, so a tap does nothing. Choose another option.",warn:!0}:M.value==="toggle"&&!qi.includes(n.value)&&!wn(0,2,58)?{text:"The screen switches this from firmware 0.2.58: press Update on the screen. Until then a tap opens its card.",warn:!1}:M.value==="toggle"?{text:"Hold the tile to open its card.",warn:!1}:null),x=k(()=>l("inline","none")),O=k(()=>xc.includes(n.value)&&(!o.value||o.value.inline||x.value==="slider")),J=k(()=>x.value==="slider"&&o.value&&!o.value.inline),C=k(()=>l("history_hours",24)),z=k(()=>Object.entries(c.inventory.backgrounds||{})),P=k(()=>!!c.inventory.entities.find(q=>q.id===t.tile.entity)?.icon),S=k(()=>!!c.inventory.icons&&n.value!=="screen"&&!["forecast","sunpath"].includes(a.value));function b(q){t.tile.name=q,Qe()}function A(){c.inspector={kind:"inspect",entity:t.tile.entity}}return(q,W)=>(h(),m(U,null,[i("div",mh,[i("span",{class:"av mdi",style:Pe({color:v(bt)(e.tile.entity)[2],background:v(bt)(e.tile.entity)[3]})},y(v(be)(v(gs)(e.tile))),5),i("span",yh,[i("b",null,y(e.tile.name||s.value),1),i("small",gh,y(e.tile.entity),1)]),i("button",{type:"button",class:"icon-btn","aria-label":"Close",onClick:W[0]||(W[0]=(...le)=>v(Re)&&v(Re)(...le))},"✕")]),i("div",bh,[i("div",wh,[W[10]||(W[10]=i("label",{class:"f-label",for:"tile-name"},"Name on the screen",-1)),i("input",{id:"tile-name",value:e.tile.name,placeholder:s.value,maxlength:"60",onInput:W[1]||(W[1]=le=>b(le.target.value))},null,40,_h)]),S.value?(h(),Ke(Ma,{key:0,selected:e.tile.options?.icon||"auto",automatic:v(Xt)(e.tile.entity),"auto-label":`Automatic (${P.value?"from Home Assistant":"default"})`,note:v(wn)(0,2,18)?"":"The screen shows a chosen icon from firmware 0.2.18.",onPick:W[2]||(W[2]=le=>v(Bt)(e.tile,"icon",le))},null,8,["selected","automatic","auto-label","note"])):H("",!0),i("div",kh,[W[11]||(W[11]=i("span",{class:"f-label"},"Display",-1)),$e(at,{choices:r.value,value:a.value,onPick:W[3]||(W[3]=le=>v(Bt)(e.tile,"display",le))},null,8,["choices","value"]),d.value?(h(),m("small",$h,y(d.value),1)):H("",!0)]),i("div",xh,[W[12]||(W[12]=i("span",{class:"f-label"},"Width",-1)),$e(at,{choices:[["single","Normal"],["wide","Double-width"]],value:u.value,onPick:W[4]||(W[4]=le=>v(Bt)(e.tile,"size",le))},null,8,["value"])]),f.value&&u.value==="wide"?(h(),m("div",Sh,[W[13]||(W[13]=i("span",{class:"f-label"},"Direct control on the tile",-1)),$e(at,{choices:_.value,value:p.value,onPick:W[5]||(W[5]=le=>v(Bt)(e.tile,"controls",le))},null,8,["choices","value"]),i("small",{class:ue({warn:T.value.warn})},y(T.value.text),3)])):H("",!0),n.value!=="screen"?(h(),m("div",Ch,[W[14]||(W[14]=i("span",{class:"f-label"},"On tap",-1)),$e(at,{choices:I.value,value:M.value,onPick:W[6]||(W[6]=le=>v(Bt)(e.tile,"tap",le))},null,8,["choices","value"]),$.value?(h(),m("small",{key:0,class:ue({warn:$.value.warn})},y($.value.text),3)):H("",!0)])):H("",!0),n.value!=="screen"&&M.value==="action"?(h(),Ke(eh,{key:3,tile:e.tile},null,8,["tile"])):H("",!0),O.value?(h(),m("div",Ah,[W[15]||(W[15]=i("span",{class:"f-label"},"Small slider on the tile",-1)),$e(at,{choices:[["none","No"],["slider","Yes, control directly"]],value:x.value,onPick:W[7]||(W[7]=le=>v(Bt)(e.tile,"inline",le))},null,8,["value"]),J.value?(h(),m("small",Th,"Home Assistant has nothing a slider can change for this entity. Choose No.")):H("",!0)])):H("",!0),n.value==="sensor"?(h(),m("div",Eh,[W[16]||(W[16]=i("span",{class:"f-label"},"History",-1)),$e(at,{choices:[[1,"1 hour"],[6,"6 hours"],[24,"24 hours"]],value:C.value,onPick:W[8]||(W[8]=le=>v(Bt)(e.tile,"history_hours",Number(le)))},null,8,["value"])])):H("",!0),i("div",Ph,[W[17]||(W[17]=i("span",{class:"f-label"},"Pastel background",-1)),i("div",Oh,[(h(!0),m(U,null,ie(z.value,([le,Z])=>(h(),m("button",{key:le,type:"button","aria-label":`Background: ${Z.label}`,"aria-pressed":(e.tile.options?.background||"auto")===le?"true":"false",onClick:B=>v(Bt)(e.tile,"background",le)},[i("i",{class:ue(Z.color?"":le==="none"?"none":"auto"),style:Pe(Z.color?{background:Z.color}:void 0)},null,6),ee(y(Z.label),1)],8,Ih))),128))])])]),i("div",Mh,[i("button",{type:"button",class:"btn danger",onClick:W[9]||(W[9]=le=>v(xa)(e.tile))},"Remove"),W[18]||(W[18]=i("span",{class:"spacer"},null,-1)),n.value!=="screen"?(h(),m("button",{key:0,type:"button",class:"btn quiet",onClick:A},"Read current data")):H("",!0)])],64))}}),Dh={class:"dr-head"},Fh={class:"av mdi",style:{background:"var(--seg)",color:"var(--ink-2)"}},Nh={class:"tx"},Rh={class:"dr-body"},Hh={class:"f"},Uh=["value"],jh={class:"f"},Bh={class:"f-label",id:"topbar-caption"},Vh={style:{"text-transform":"none","letter-spacing":"0","font-weight":"500"}},Wh={class:"items",id:"topbar-chips",role:"list","aria-labelledby":"topbar-caption"},Kh=["data-index","aria-label","onPointerdown","onClick","onKeydown"],qh={class:"tx"},Yh=["aria-label","onClick"],zh=["disabled","title"],Jh={class:"live",id:"topbar-live"},Gh={class:"f"},Xh={class:"f"},Qh={key:1,class:"f"},Zh={key:2},ev={key:0,class:"dr-foot"},tv=["disabled"],nv=["disabled"],sv=Ce({__name:"TopbarInspector",props:{index:{}},setup(e){const t=e,n=k(()=>Ht()),s=k(()=>n.value[t.index]),o=k(()=>(c.fontsVersion,c.now,c.topbarPreviews,fa(n.value,_a.value,c.layout?.title||"Home",Vt))),l=k(()=>o.value.dropped),a=k(()=>c.inventory.header?.min_firmware||"0.2.32"),r=k(()=>{const[Z,B,X]=a.value.split(".").map(Number);return wn(Z,B,X)}),d=k(()=>r.value?l.value.size?"Not everything fits next to the name: the screen drops the dashed items. Remove one or choose a shorter name.":"Drag to reorder; tap an item to configure it.":`Sensors, the date, and the analog clock appear from firmware ${a.value}; until that update, this screen shows the name and, if the time is in the bar, the clock.`),u=(Z,B)=>{const X=Vt(Z);return X.shown?l.value.has(B)?"Doesn't fit next to the name":X.analog?"Dial":X.text:"Hidden: not active right now"},f=Z=>{const B=Vt(Z);return B.analog||Z.type!=="entity"?is(da[Z.type])?.cp:B.icon},p=Z=>c.topbarAdded?.key===je(Z)&&Date.now()-c.topbarAdded.time<1200;function _(Z){c.layout&&(c.layout.title=Z,Qe())}function T(Z){const B=[...n.value];B[t.index]={...B[t.index],...Z},Qn(B)}const M=k(()=>s.value?Vt(s.value).shown?l.value.has(t.index)?"Doesn't currently fit next to the name":"How it looks on the screen":"Hidden right now: not active":""),I=k(()=>Cn().clock_24h!==!1),$=k(()=>({clock:ei(I.value,new Date(c.now)),analog:"Small dial with the time",date:ti(new Date(c.now))})),x=fe({index:-1,active:!1,moved:!1});let O=null,J=0,C=null,z=0;function P(Z,B){Z.button!==0||Z.target.closest(".x")||(Z.pointerType!=="touch"&&Z.preventDefault(),x.value={index:B,active:!1,moved:!1},O={x:Z.clientX,y:Z.clientY},C=Z.pointerId,clearTimeout(J),Z.pointerType==="touch"&&(J=window.setTimeout(S,260)),document.addEventListener("pointermove",A),document.addEventListener("pointerup",q),document.addEventListener("pointercancel",q))}function S(){x.value.active=!0,document.addEventListener("touchmove",b,{passive:!1})}function b(Z){x.value.active&&Z.preventDefault()}function A(Z){if(Z.pointerId!==C||!O)return;if(!x.value.active){const ce=Math.hypot(Z.clientX-O.x,Z.clientY-O.y);if(Z.pointerType==="touch"){ce>10&&(clearTimeout(J),O=null);return}if(ce<6)return;S()}const B=[...document.querySelectorAll(".items .item[data-index]")];let X=x.value.index;if(B.forEach((ce,V)=>{const Q=ce.getBoundingClientRect();Vx.value.index&&Z.clientY>Q.top+Q.height/2&&(X=Math.max(X,V))}),X!==x.value.index&&c.layout){const ce=[...n.value];ce.splice(X,0,...ce.splice(x.value.index,1)),c.layout.header={items:ce};const V=t.index===x.value.index;x.value.index=X,x.value.moved=!0,V&&Pt(X)}}function q(Z){Z.pointerId===C&&(clearTimeout(J),document.removeEventListener("pointermove",A),document.removeEventListener("pointerup",q),document.removeEventListener("pointercancel",q),document.removeEventListener("touchmove",b),x.value.active&&(z=Date.now()+400,x.value.moved&&Qe()),x.value={index:-1,active:!1,moved:!1},O=null,C=null)}function W(Z){Date.now()(h(),m(U,null,[i("div",Dh,[i("span",Fh,y(s.value?v(be)(f(s.value)||"F0150"):v(be)("F0150")),1),i("span",Nh,[i("b",null,y(s.value?s.value.type==="entity"?v(os)(s.value.entity):v(Dn)(s.value):"Top bar"),1),i("small",{class:ue({mono:s.value?.type==="entity"})},y(s.value?s.value.type==="entity"?s.value.entity:"From the screen itself, also works without Home Assistant":`${n.value.length} of ${v(Kt)()} items`),3)]),i("button",{type:"button",class:"icon-btn","aria-label":"Close",onClick:B[0]||(B[0]=(...X)=>v(Re)&&v(Re)(...X))},"✕")]),i("div",Rh,[i("div",Hh,[B[10]||(B[10]=i("label",{class:"f-label",for:"title"},"Left: name",-1)),i("input",{id:"title",value:v(c).layout?.title,maxlength:"60",placeholder:"For example: Living room",onInput:B[1]||(B[1]=X=>_(X.target.value))},null,40,Uh)]),i("div",jh,[i("span",Bh,[B[11]||(B[11]=ee("Right: time, sensors, or a clock ",-1)),i("span",Vh," · "+y(n.value.length)+" / "+y(v(Kt)()),1)]),i("div",Wh,[(h(!0),m(U,null,ie(n.value,(X,ce)=>(h(),m("div",{key:v(je)(X)+ce,class:ue(["item",{selected:ce===e.index,"is-hidden":!v(Vt)(X).shown,"is-overflow":l.value.has(ce),"just-added":p(X),"dragging-chip":x.value.active&&x.value.index===ce}]),role:"listitem",tabindex:"0","data-index":ce,"aria-label":`${v(Dn)(X)}, slot ${ce+1}. Enter: configure, arrows: move`,onPointerdown:V=>P(V,ce),onClick:V=>W(ce),onKeydown:V=>le(V,ce)},[B[12]||(B[12]=i("span",{class:"grip","aria-hidden":"true"},"⋮⋮",-1)),i("span",{class:"av mdi",style:Pe(v(Vt)(X).color?{color:v(Vt)(X).color}:void 0)},y(f(X)?v(be)(f(X)):""),5),i("span",qh,[i("b",null,y(v(Dn)(X)),1),i("small",null,y(u(X,ce)),1)]),i("button",{type:"button",class:"x","aria-label":`Remove ${v(Dn)(X)} from the top bar`,onClick:it(V=>v(Qi)(ce),["stop"])},"✕",8,Yh)],42,Kh))),128)),i("button",{type:"button",class:"ghost-btn",id:"topbar-add",disabled:n.value.length>=v(Kt)(),title:n.value.length>=v(Kt)()?`Maximum ${v(Kt)()} items`:"Add the time, date, analog clock, or an entity",onClick:B[2]||(B[2]=(...X)=>v(Ji)&&v(Ji)(...X))},"+ Add time, date, or an entity",8,zh)]),i("small",{id:"topbar-hint",class:ue({warn:l.value.size>0&&r.value})},y(d.value),3)]),s.value?(h(),m(U,{key:0},[i("div",Jh,[i("small",null,y(M.value),1),$e(Ia,{items:[s.value],single:""},null,8,["items"])]),s.value.type==="entity"?(h(),m(U,{key:0},[i("div",Gh,[B[13]||(B[13]=i("span",{class:"f-label"},"What to show",-1)),$e(at,{choices:(v(c).inventory.header?.contents||[]).map(X=>[X.key,X.label]),value:s.value.content,onPick:B[3]||(B[3]=X=>T({content:X}))},null,8,["choices","value"]),B[14]||(B[14]=i("small",null,"Last changed keeps counting on the screen itself: “Just now”, “5 min ago”, “Yesterday”.",-1))]),$e(Ma,{selected:s.value.icon||"auto",automatic:v(c).topbarPreviews[v(je)(s.value)]?.auto_icon||v(Xt)(s.value.entity),"auto-label":"Automatic (like Home Assistant)","allow-none":"",onPick:B[4]||(B[4]=X=>T({icon:X}))},null,8,["selected","automatic"]),i("div",Xh,[B[15]||(B[15]=i("span",{class:"f-label"},"Show",-1)),$e(at,{choices:(v(c).inventory.header?.shows||[]).map(X=>[X.key,X.label]),value:s.value.show,onPick:B[5]||(B[5]=X=>T({show:X}))},null,8,["choices","value"]),B[16]||(B[16]=i("small",null,"Only when active hides the item as long as it's off, closed, away, or 0. Handy for an open door, a running washing machine, or who's home.",-1))])],64)):s.value.type!=="date"?(h(),m("div",Qh,[B[17]||(B[17]=i("span",{class:"f-label"},"Format",-1)),$e(at,{choices:[["24","24 hour"],["12","12 hour"]],value:I.value?"24":"12",onPick:B[6]||(B[6]=X=>v(Fn)("clock_24h",X==="24",150))},null,8,["value"]),B[18]||(B[18]=i("small",null,"The screen's own clock setting: it applies at once to every clock on this screen, including the clock tiles.",-1))])):(h(),m("small",Zh,y($.value.date)+" today. The date follows the screen's own clock.",1))],64)):H("",!0)]),s.value?(h(),m("div",ev,[i("button",{type:"button",class:"btn danger",onClick:B[7]||(B[7]=X=>v(Qi)(e.index))},"Remove"),B[19]||(B[19]=i("span",{class:"spacer"},null,-1)),i("button",{type:"button",class:"btn quiet",disabled:e.index===0,onClick:B[8]||(B[8]=X=>v(mo)(e.index,e.index-1)&&v(Pt)(e.index-1))},"↑ Up",8,tv),i("button",{type:"button",class:"btn quiet",disabled:e.index>=n.value.length-1,onClick:B[9]||(B[9]=X=>v(mo)(e.index,e.index+1)&&v(Pt)(e.index+1))},"↓ Down",8,nv)])):H("",!0)],64))}}),ov={class:"dr-head"},iv={class:"tx"},lv={class:"dr-body"},av={class:"f"},rv={class:"options"},uv=["disabled","onClick"],cv={class:"mdi"},dv={class:"tx"},fv={key:0,class:"f"},pv={class:"options"},hv=["disabled","onClick"],vv={class:"mdi"},mv={class:"tx"},yv={class:"f"},gv={class:"options"},bv=["disabled","onClick"],wv={class:"mdi"},_v={class:"tx"},kv={key:0,class:"hint"},$v={key:1,class:"hint"},xv={class:"dr-foot"},Sv=Ce({__name:"TopbarAdd",setup(e){const t=fe(""),n=k(()=>new Set(Ht().map(je))),s=k(()=>Cn().clock_24h!==!1),o=k(()=>({clock:ei(s.value,new Date(c.now)),analog:"Small dial with the time",date:ti(new Date(c.now))})),l=k(()=>c.inventory.header?.suggestions?.[c.selected||""]||[]),a=k(()=>{const d=t.value.trim().toLocaleLowerCase();return c.inventory.entities.filter(u=>`${u.name} ${u.id} ${u.area||""} ${u.device||""}`.toLocaleLowerCase().includes(d))}),r=d=>({type:"entity",entity:d,content:"state",icon:"auto",show:"always"});return(d,u)=>(h(),m(U,null,[i("div",ov,[u[4]||(u[4]=i("span",{class:"av",style:{background:"var(--seg)",color:"var(--ink-2)","font-size":"18px"}},"+",-1)),i("span",iv,[u[3]||(u[3]=i("b",null,"Add to the top bar",-1)),i("small",null,y(v(Ht)().length)+" of "+y(v(Kt)())+" slots used",1)]),i("button",{type:"button",class:"icon-btn","aria-label":"Close",onClick:u[0]||(u[0]=(...f)=>v(Re)&&v(Re)(...f))},"✕")]),i("div",lv,[i("div",av,[u[5]||(u[5]=i("span",{class:"f-label"},"From the screen itself",-1)),i("div",rv,[(h(!0),m(U,null,ie(v(c).inventory.header?.builtin||[],f=>(h(),m("button",{key:f.type,type:"button",class:"option",disabled:n.value.has(v(je)({type:f.type})),onClick:p=>v(yo)({type:f.type})},[i("span",cv,y(v(be)(v(is)(v(da)[f.type])?.cp||"F0150")),1),i("span",dv,[i("strong",null,y(f.label),1),i("small",null,y(n.value.has(v(je)({type:f.type}))?"Already added":o.value[f.type]),1)])],8,uv))),128))])]),l.value.length?(h(),m("div",fv,[u[6]||(u[6]=i("span",{class:"f-label"},"Suggestions from Home Assistant",-1)),i("div",pv,[(h(!0),m(U,null,ie(l.value,f=>(h(),m("button",{key:v(je)(f.item),type:"button",class:"option",disabled:n.value.has(v(je)(f.item)),onClick:p=>v(yo)(f.item)},[i("span",vv,y(v(be)(f.icon||v(Xt)(f.item.entity))),1),i("span",mv,[i("strong",null,y(f.label),1),i("small",null,y(n.value.has(v(je)(f.item))?"Already added":[f.name,f.area].filter(Boolean).join(" · ")),1)])],8,hv))),128))])])):H("",!0),i("div",yv,[u[7]||(u[7]=i("label",{class:"f-label",for:"topbar-search"},"An entity",-1)),ye(i("input",{id:"topbar-search","onUpdate:modelValue":u[1]||(u[1]=f=>t.value=f),type:"search",placeholder:"Search by name, room, or entity, e.g. temperature or door","aria-label":"Search for an entity for the top bar"},null,512),[[Ie,t.value]]),i("div",gv,[(h(!0),m(U,null,ie(a.value.slice(0,40),f=>(h(),m("button",{key:f.id,type:"button",class:"option",disabled:n.value.has(v(je)(r(f.id))),onClick:p=>v(yo)(r(f.id))},[i("span",wv,y(v(be)(v(Xt)(f.id))),1),i("span",_v,[i("strong",null,y(f.name),1),i("small",null,y([f.area,f.id].filter(Boolean).join(" · ")),1)])],8,bv))),128)),a.value.length?a.value.length>40?(h(),m("p",$v,y(a.value.length)+" results. Keep typing to narrow it down.",1)):H("",!0):(h(),m("p",kv,"No entities found."))])])]),i("div",xv,[u[8]||(u[8]=i("span",{class:"spacer"},null,-1)),i("button",{type:"button",class:"btn quiet",onClick:u[2]||(u[2]=(...f)=>v(Re)&&v(Re)(...f))},"Cancel")])],64))}}),Cv={class:"dr-head"},Av={class:"tx"},Tv={class:"dr-body",id:"inspector-section"},Ev={id:"inspection-summary"},Pv={key:0,class:"hint warn"},Ov={key:1,class:"hint"},Iv={id:"inspection"},Mv=Ce({__name:"InspectPanel",props:{entity:{}},setup(e){const t=e,n=fe(null),s=fe("Reading…"),o=fe("");async function l(){if(c.selected){n.value=null,o.value="",s.value="Fetching current HA status...";try{const r=await dt(`screens/${encodeURIComponent(c.selected)}/inspect`),d=t.entity?r.tiles.filter(u=>u.entity===t.entity):r.tiles;n.value=d,s.value=JSON.stringify(t.entity?d[0]:r,null,2)}catch(r){o.value=r.message,s.value="",Se(r.message)}}}const a=r=>{const d=c.layout?.tiles.find(u=>u.entity===r)?.options||{};return`Small slider: ${d.inline==="slider"?"yes":"no"} · Display: ${ba[d.display||"standard"]||d.display} · Width: ${d.size==="wide"?"double":"normal"} · Control: ${_c({entity:r,options:d},c.inventory)} · Background: ${c.inventory.backgrounds?.[d.background||"auto"]?.label||"Default"}`};return hn(l),an(()=>t.entity,l),(r,d)=>(h(),m(U,null,[i("div",Cv,[d[2]||(d[2]=i("span",{class:"av",style:{background:"var(--seg)",color:"var(--ink-2)","font-size":"16px"}},"⌕",-1)),i("span",Av,[d[1]||(d[1]=i("b",null,"Current data",-1)),i("small",{class:ue({mono:e.entity})},y(e.entity||"Connection, status, and supported properties"),3)]),i("button",{type:"button",class:"icon-btn","aria-label":"Close",onClick:d[0]||(d[0]=(...u)=>v(Re)&&v(Re)(...u))},"✕")]),i("div",Tv,[i("div",Ev,[o.value?(h(),m("p",Pv,y(o.value),1)):n.value?H("",!0):(h(),m("p",Ov,"Fetching current HA status...")),(h(!0),m(U,null,ie(n.value||[],u=>(h(),m("article",{key:u.entity,class:"inspection-tile"},[i("strong",null,y(u.entity),1),i("span",null,"Status: "+y(u.word||u.state),1),i("small",null,y(a(u.entity)),1)]))),128))]),i("pre",Iv,y(s.value),1)]),i("div",{class:"dr-foot"},[i("button",{type:"button",class:"btn quiet",onClick:l},"Read again"),d[3]||(d[3]=i("span",{class:"spacer"},null,-1))])],64))}}),Lv=["aria-hidden"],Dv=Ce({__name:"Drawer",setup(e){const t=k(()=>!!(c.inspector&&(c.inspector.kind!=="tile"||uo.value)));return(n,s)=>(h(),m("aside",{class:ue(["drawer",{open:t.value}]),id:"tile-sheet","aria-hidden":t.value?"false":"true",onClick:s[0]||(s[0]=it(()=>{},["stop"]))},[v(c).inspector?(h(),m(U,{key:0},[v(c).inspector.kind==="tile"&&v(uo)?(h(),Ke(Lh,{key:0,tile:v(uo)},null,8,["tile"])):v(c).inspector.kind==="bar"?(h(),Ke(sv,{key:1,index:v(c).inspector.index},null,8,["index"])):v(c).inspector.kind==="bar-add"?(h(),Ke(Sv,{key:2})):v(c).inspector.kind==="inspect"?(h(),Ke(Mv,{key:3,entity:v(c).inspector.entity},null,8,["entity"])):H("",!0)],64)):H("",!0)],10,Lv))}}),Fv={class:"main-head"},Nv={class:"eyebrow",id:"screen-name"},Rv=["title"],Hv={class:"head-right"},Uv={class:"seg",role:"tablist"},jv=["aria-pressed"],Bv=["aria-pressed"],Vv={key:1,id:"dirty",class:"chip dirty"},Wv=["disabled"],Kv={key:0,class:"spin small"},qv=["aria-expanded"],Yv={key:3,class:"menu",role:"menu"},zv=["disabled","title"],Jv=["disabled","aria-expanded"],Gv={key:0,class:"sub"},Xv=["onClick"],Qv=["disabled","title"],Zv={class:"body",id:"body"},em=Ce({__name:"ScreenView",setup(e){const t=k(()=>Ct.value),n=k(()=>t.value.online?`${t.value.delivery} · ${t.value.status}`:"Offline · changes are saved"),s=k(()=>t.value.update?.available&&t.value.online&&t.value.update?.profile&&t.value.update?.host),o=k(()=>c.inventory.screens.filter(I=>I.id!==t.value.id&&I.layout?.tiles?.length)),l=fe(!1),a=fe(null);function r(){c.menuOpen=!1,l.value=!1}function d(){r(),c.overrideProfile=t.value.update?.profile||null,c.overrideFriendly=t.value.name,Ae("#override")}function u(){r(),c.selectedTile=null,c.inspector={kind:"inspect"}}function f(I){r(),!(c.dirty&&!confirm("Replace the unsaved layout with a copy of the other screen's?"))&&Dc(I)}function p(){r(),a.value?.click()}async function _(I){const $=I.target,x=$.files?.[0];$.value="",x&&(c.dirty&&!confirm("Replace the unsaved layout with the imported one?")||Nc(await x.text()))}function T(I){if(I.key==="Escape")if(c.menuOpen)r();else{if(c.palette)return;c.inspector&&!I.target?.closest?.(".picker")&&Re()}else(I.metaKey||I.ctrlKey)&&I.key.toLowerCase()==="s"&&(I.preventDefault(),c.dirty&&Io())}function M(I){c.menuOpen&&!I.target.closest(".head-right .menu, #more")&&r()}return hn(()=>{document.addEventListener("keydown",T),document.addEventListener("click",M)}),An(()=>{document.removeEventListener("keydown",T),document.removeEventListener("click",M)}),(I,$)=>(h(),m(U,null,[i("header",Fv,[i("div",null,[i("span",Nv,y(t.value.name),1),i("h1",null,y(v(c).layout?.title||"Home"),1)]),i("span",{id:"delivery",class:ue(["chip",{off:!t.value.online}]),title:n.value},[$[9]||($[9]=i("span",{class:"dot"},null,-1)),ee(y(n.value),1)],10,Rv),i("div",Hv,[i("div",Uv,[i("button",{type:"button",id:"tab-layout",role:"tab","aria-pressed":v(c).tab==="layout"?"true":"false",onClick:$[0]||($[0]=x=>v(c).tab="layout")},"Layout",8,jv),i("button",{type:"button",id:"tab-settings",role:"tab","aria-pressed":v(c).tab==="settings"?"true":"false",onClick:$[1]||($[1]=x=>{v(c).tab="settings",v(Re)()})},"Screen settings",8,Bv)]),v(c).dirty?(h(),m("span",Vv,"Unsaved changes")):(h(),m("span",{key:0,id:"dirty",class:ue(["chip",{sent:v(c).saved}])},y(v(c).saved?"Saved · sent to screen":"All saved"),3)),v(c).dirty?(h(),m("button",{key:2,id:"save",type:"button",class:"btn primary",disabled:v(c).busy,title:"⌘S",onClick:$[2]||($[2]=x=>v(Io)())},[v(c).busy?(h(),m("span",Kv)):H("",!0),ee(y(v(c).busy?"Saving…":"Save & send"),1)],8,Wv)):H("",!0),i("button",{id:"more",type:"button",class:"icon-btn","aria-label":"More","aria-haspopup":"menu","aria-expanded":v(c).menuOpen?"true":"false",onClick:$[3]||($[3]=it(x=>{v(c).menuOpen=!v(c).menuOpen,l.value=!1},["stop"]))},"···",8,qv),v(c).menuOpen?(h(),m("div",Yv,[i("button",{type:"button",role:"menuitem",id:"identify",disabled:!v(dn)(t.value)||!t.value.online,title:v(dn)(t.value)?"":"Needs firmware 0.2.31 or newer",onClick:$[4]||($[4]=x=>{r(),v(Sa)(t.value)})},[...$[10]||($[10]=[ee("Identify ",-1),i("small",null,"blink the screen",-1)])],8,zv),i("button",{type:"button",role:"menuitem",id:"inspect",onClick:u},[...$[11]||($[11]=[ee("Read current data ",-1),i("small",null,"from Home Assistant",-1)])]),$[17]||($[17]=i("div",{class:"sep"},null,-1)),i("button",{type:"button",role:"menuitem",id:"copy-layout",disabled:!o.value.length,"aria-expanded":l.value?"true":"false",onClick:$[5]||($[5]=it(x=>l.value=!l.value,["stop"]))},[$[12]||($[12]=ee("Copy layout from… ",-1)),i("small",null,y(o.value.length?`${o.value.length} screen${o.value.length===1?"":"s"}`:"no other screen"),1)],8,Jv),l.value?(h(),m("div",Gv,[(h(!0),m(U,null,ie(o.value,x=>(h(),m("button",{key:x.id,type:"button",role:"menuitem",onClick:O=>f(x.id)},[ee(y(x.name)+" ",1),i("small",null,y(x.layout.tiles.length)+" tiles",1)],8,Xv))),128))])):H("",!0),i("button",{type:"button",role:"menuitem",id:"export-layout",onClick:$[6]||($[6]=x=>{r(),v(Aa)()})},[...$[13]||($[13]=[ee("Export layout ",-1),i("small",null,"JSON",-1)])]),i("button",{type:"button",role:"menuitem",id:"import-layout",onClick:p},[...$[14]||($[14]=[ee("Import layout… ",-1),i("small",null,"JSON",-1)])]),$[18]||($[18]=i("div",{class:"sep"},null,-1)),i("button",{type:"button",role:"menuitem",id:"open-override",disabled:!t.value.update?.profile,title:t.value.update?.profile?"":"No ESPHome profile found for this screen",onClick:d},[...$[15]||($[15]=[ee("Override YAML ",-1),i("small",null,"advanced",-1)])],8,Qv),i("button",{type:"button",role:"menuitem",onClick:$[7]||($[7]=x=>{r(),v(Ae)("#firmware")})},"Firmware & USB"),s.value?(h(),m("button",{key:1,type:"button",role:"menuitem",onClick:$[8]||($[8]=x=>{r(),v(Lo)(t.value)})},[$[16]||($[16]=ee("Update firmware ",-1)),i("small",null,y(t.value.update?.target),1)])):H("",!0)])):H("",!0),i("input",{ref_key:"fileInput",ref:a,type:"file",accept:"application/json,.json",hidden:"",onChange:_},null,544)])]),i("div",Zv,[v(c).tab==="layout"?(h(),Ke(cp,{key:0})):(h(),Ke(Cp,{key:1})),$e(Dv)])],64))}}),tm={key:0,id:"choose",class:"empty"},nm={key:1,id:"empty",class:"empty"},sm=Ce({__name:"EmptyState",setup(e){return(t,n)=>v(c).inventory.screens.length?(h(),m("section",tm,[...n[1]||(n[1]=[i("span",{class:"empty-icon"},"▦",-1),i("h2",null,"Choose a screen",-1),i("p",null,"Pick one of your screens on the left to change its tiles, top bar and settings.",-1)])])):(h(),m("section",nm,[n[2]||(n[2]=i("span",{class:"empty-icon"},"▦",-1)),n[3]||(n[3]=i("h2",null,"Start with a screen",-1)),n[4]||(n[4]=i("p",null,"Connect a CYD or Guition via USB to your Home Assistant machine. Profile, firmware, and the first flash happen in one go.",-1)),i("button",{id:"start",type:"button",class:"btn primary",onClick:n[0]||(n[0]=s=>v(Ae)("#new-screen"))},"Install new screen")]))}}),om={class:"panel",id:"settings-view"},im={class:"panel-head"},lm={class:"card-grid"},am={class:"card"},rm={class:"tools"},um={key:0,class:"card updates",id:"updates"},cm={id:"updates-hint"},dm=["aria-valuenow"],fm={class:"progress-text"},pm={key:0,class:"log-lines"},hm={key:2,class:"whatsnew"},vm={class:"check"},mm=["checked"],ym={class:"card"},gm={class:"tools"},bm={class:"card",id:"claude"},wm={class:"actions"},_m=["disabled"],km={id:"claude-path"},$m=Ce({__name:"AppSettingsView",setup(e){const t=k(()=>c.inventory.updates),n=k(()=>c.inventory.screens.filter(p=>p.update?.available).length),s=k(()=>t.value?t.value.busy?`Updating to firmware ${t.value.target}…`:c.inventory.screens.length?n.value?`Firmware ${t.value.target} is available for ${n.value} screen${n.value===1?"":"s"}.`:`All screens have firmware ${t.value.target}.`:`No screen paired yet. New screens get firmware ${t.value.target}.`:""),o=k(()=>c.inventory.screens.find(p=>p.update?.state==="running"||c.updating.includes(p.id))),l=k(()=>o.value?yn(o.value):null),a=k(()=>(c.firmwareJob?.logs||[]).slice(-12).join(` +`)),r=k(()=>{const p=t.value?.changelog,_=t.value?.target;return!p||!_?[]:p.filter(T=>T.firmware===_).flatMap(T=>T.lines).slice(0,10)}),d=k(()=>c.inventory.claude_skill),u=fe(!1);async function f(){u.value=!0;try{await Kc()}finally{u.value=!1}}return(p,_)=>(h(),m("div",om,[i("div",im,[_[6]||(_[6]=i("div",{class:"tx"},[i("span",{class:"eyebrow"},"Settings"),i("h1",{id:"settings-title"},"Everything around your screens.")],-1)),i("button",{type:"button",class:"btn quiet",id:"close-settings",onClick:_[0]||(_[0]=T=>v(Ae)(""))},"← My screens")]),i("div",lm,[i("section",am,[_[9]||(_[9]=i("h2",null,"Screens",-1)),_[10]||(_[10]=i("p",null,"Add a screen, or build and reinstall the firmware of one you already have.",-1)),i("div",rm,[i("button",{type:"button",class:"tool",onClick:_[1]||(_[1]=T=>v(Ae)("#new-screen"))},[..._[7]||(_[7]=[i("span",{class:"tool-icon"},"+",-1),i("span",{class:"tx"},[i("b",null,"New screen"),i("small",null,"Connect and install")],-1)])]),i("button",{type:"button",class:"tool",onClick:_[2]||(_[2]=T=>v(Ae)("#firmware"))},[..._[8]||(_[8]=[i("span",{class:"tool-icon"},"⇪",-1),i("span",{class:"tx"},[i("b",null,"Firmware & USB"),i("small",null,"Build and install via USB or Wi-Fi")],-1)])])])]),t.value?(h(),m("section",um,[_[12]||(_[12]=i("h2",null,"Firmware updates",-1)),i("p",cm,y(s.value),1),o.value&&l.value?(h(),m(U,{key:0},[i("div",{class:"progress",role:"progressbar","aria-valuenow":l.value.percent,"aria-valuemin":"0","aria-valuemax":"100"},[i("i",{style:Pe({width:l.value.percent+"%"})},null,4)],8,dm),i("div",fm,[i("span",null,y(o.value.name)+" · "+y(l.value.percent)+" %",1),i("span",null,y(l.value.text),1)]),a.value?(h(),m("pre",pm,y(a.value),1)):H("",!0)],64)):H("",!0),t.value.pending&&!t.value.busy&&t.value.pending>=2?(h(),m("button",{key:1,id:"update-all",type:"button",class:"btn primary",onClick:_[3]||(_[3]=(...T)=>v(el)&&v(el)(...T))},"Update all "+y(t.value.pending)+" screens",1)):H("",!0),r.value.length&&!v(Mo)()?(h(),m("details",hm,[i("summary",null,"What's new in firmware "+y(t.value.target),1),i("ul",null,[(h(!0),m(U,null,ie(r.value,T=>(h(),m("li",{key:T},y(T),1))),128))])])):H("",!0),i("label",vm,[i("input",{type:"checkbox",id:"auto-update",checked:!!t.value.auto,onChange:_[4]||(_[4]=T=>v(Wc)(T.target.checked))},null,40,mm),_[11]||(_[11]=i("span",null,[ee("Update automatically every night"),i("small",null,"Between 03:00 and 06:00, one screen at a time. Stops on an error and reports it in Home Assistant.")],-1))])])):H("",!0),i("section",ym,[_[14]||(_[14]=i("h2",null,"Alerts",-1)),_[15]||(_[15]=i("p",null,"A card over the whole screen from an automation, on one screen or on all of them. The cheatsheet has the action names, fields, icons, and colors, and a form to try one.",-1)),i("div",gm,[i("button",{type:"button",class:"tool",onClick:_[5]||(_[5]=T=>v(Ae)("#alerts"))},[..._[13]||(_[13]=[i("span",{class:"tool-icon"},"!",-1),i("span",{class:"tx"},[i("b",null,"Alerts"),i("small",null,"Full-screen notifications, from an automation")],-1)])])])]),i("section",bm,[_[18]||(_[18]=i("h2",null,"Claude",-1)),_[19]||(_[19]=i("p",null,'Teach Claude about ESP Screens, then ask: "Show an alert on all my screens when the mailbox is full." Claude knows the alert events, every field, color, and icon.',-1)),i("div",wm,[i("button",{type:"button",id:"claude-install",class:ue(["btn",d.value?.installed&&d.value.current?"quiet":"primary"]),disabled:!d.value||u.value,onClick:f},y(!d.value||!d.value.installed?"Install for Claude Code":d.value.current?"Install again":"Update the skill"),11,_m),i("span",{id:"claude-status",class:ue(["chip",d.value&&d.value.installed?d.value.current?"good":"update":""]),role:"status"},y(d.value?d.value.installed?d.value.current?"● Installed":"Installed · a newer version is ready":"Not installed":"Loading…"),3)]),i("small",null,[_[16]||(_[16]=ee("For Claude Code in Home Assistant. Writes one file to ",-1)),i("code",km,y(d.value?.path||"/homeassistant/.claude/skills/esp-screens"),1),_[17]||(_[17]=ee("; installing again replaces it.",-1))]),_[20]||(_[20]=i("div",{class:"actions"},[i("a",{class:"btn quiet",id:"claude-download",href:"api/claude-skill.zip",download:"esp-screens.zip"},"Download for claude.ai"),i("small",null,"Upload the zip in Claude under Customize → Skills.")],-1))])])]))}}),xm={class:"panel",id:"installer"},Sm={class:"panel-head"},Cm={class:"tx"},Am={id:"install-title"},Tm={key:0},Em={class:"boards"},Pm={class:"board"},Om={class:"board"},Im={class:"field"},Mm={class:"node-line"},Lm={id:"node-preview"},Dm={key:0,class:"field",id:"node-label"},Fm={key:1,id:"wifi-fields",class:"wifi"},Nm={class:"hint",id:"wifi-status"},Rm={key:0,class:"field",id:"wifi-ssid-label"},Hm={key:1,class:"field",id:"wifi-password-label"},Um={class:"field"},jm={key:0,value:"usb"},Bm=["value"],Vm={id:"target-hint"},Wm={key:2,class:"hint",id:"install-note"},Km={class:"actions"},qm=["disabled"],Ym={id:"install-status",class:"status-line error",role:"status"},zm={key:1,id:"install-progress",class:"card"},Jm={class:"progress-head"},Gm={key:0,class:"spin",id:"progress-spin"},Xm={id:"progress-title"},Qm={id:"progress-detail"},Zm={key:0,id:"install-download",class:"card",style:{background:"var(--surface-2)"}},ey=["href","download"],ty={class:"steps",id:"download-steps"},ny={key:1,id:"install-result",class:"field"},sy={class:"key-box"},oy={class:"steps",id:"install-steps"},iy=["open"],ly={id:"install-log",class:"log"},ay={class:"actions"},ry="https://web.esphome.io/?dashboard_install",uy="Download · flash from your own computer",cy=Ce({__name:"InstallerView",setup(e){const t=fn({board:"cyd",friendly_name:"",name:"",wifi_ssid:"",wifi_password:"",target:""}),n=fn({view:"setup",file:null,friendly:"",board:"cyd",target:"",apiKey:null,nodeEdited:!1,jobState:null,picked:!1,action:null}),s=fe(!1),o=fe(null),l=fe(null),a=fe([]),r=fe(""),d=fe(""),u=fe(!1),f=fe(!1),p=fe(null);let _=0;function T(pe){return pe.toLowerCase().normalize("NFD").replace(/[̀-ͯ]/g,"").replace(/[^a-z0-9]+/g,"-").replace(/^[^a-z]+/,"").slice(0,30).replace(/-+$/,"")||"screen"}function M(pe){const N=pe.replace(/^\/dev\/serial\/by-id\/usb-/,"").replace(/-if\d+(-port\d+)?$/,"").replace(/_/g," ");return`USB · ${N===pe?pe.replace(/^\/dev\//,""):N}`}an(()=>t.friendly_name,()=>{n.nodeEdited||(t.name=T(t.friendly_name))});const I=k(()=>t.name||"…"),$=k(()=>o.value?.ports||[]),x=k(()=>o.value?.wifi),O=k(()=>x.value?.state==="new"||x.value?.state==="missing"),J=k(()=>x.value?.missing||[]),C=k(()=>x.value?.state==="new"?"Fill in once: ESP Screens saves this in ESPHome secrets.yaml, later screens use it automatically.":"Your ESPHome secrets.yaml is still missing Wi-Fi details. ESP Screens only fills in the missing lines."),z=k(()=>x.value?.state==="ready"?"Wi-Fi comes from your ESPHome secrets.yaml.":x.value?.state==="invalid"?"secrets.yaml in the ESPHome folder isn't valid YAML. Fix the file first; it won't be overwritten.":""),P=k(()=>t.target==="usb"?"Connect the screen with a USB data cable to the Home Assistant machine; the list refreshes on its own. Or choose Download to use your own computer.":t.target==="download"?"Download the firmware and put it on the screen from your own computer, in Chrome or Edge. After that, updates go over Wi-Fi.":t.target?$.value.length>1?"More than one board connected: choose this screen's port.":"Once over USB; after that, everything is wireless.":"The profile goes into the ESPHome folder. You can install later via Firmware & USB, or from ESPHome Device Builder."),S=k(()=>t.target==="download"?"Build & download":t.target?"Install":"Save profile"),b=k(()=>o.value?.job?.state==="running"&&!(n.file&&o.value.job.file===n.file)),A=k(()=>u.value||x.value?.state==="invalid"||t.target==="usb"||!!t.target&&(b.value||!o.value?.available));function q(){const pe=t.target;(pe==="download"||pe===""?n.picked:$.value.includes(pe))||(t.target=$.value[0]||"usb")}async function W(){let pe;try{pe=await dt("firmware")}catch(et){r.value=et.message;return}o.value=pe;const N=pe.job,de=N&&n.file&&N.file===n.file;if(de&&(n.jobState=N.state),n.view==="setup"){if(de&&N.state==="running"){le(N,pe.logs||[]);return}q(),r.value=b.value?`A build or installation is already running (${N.file}). Wait for it to finish.`:!pe.available&&t.target?"The ESPHome CLI is missing from this installation; only saving the profile is possible.":z.value}else n.view==="progress"&&de&&(l.value=N,a.value=pe.logs||[],N.state!=="running"&&N.state!=="success"&&(f.value=!0))}function le(pe,N){n.view="progress",n.jobState=pe.state,n.action=pe.action,l.value=pe,a.value=N}const Z=k(()=>l.value?.state==="running"),B=k(()=>n.view==="done"||l.value?.state==="success"),X=k(()=>n.action==="download"),ce=k(()=>n.view==="done"?"Profile saved.":Z.value?"One moment…":B.value?X.value?"Ready to download.":"Done.":"That didn't work."),V=k(()=>n.view==="done"?`${n.file} is in the ESPHome folder`:Z.value?l.value?.stage==="upload"?`Writing firmware to ${n.friendly}…`:"Building firmware…":B.value?X.value?`Firmware for ${n.friendly} is ready`:`Firmware is on ${n.friendly}`:X.value?"Build failed":"Install failed"),Q=k(()=>n.view==="done"?"Install it later from Firmware & USB: choose this profile, then the USB port of the Home Assistant machine, or Download to put the firmware on the screen from your own computer. Save the API key for pairing:":Z.value?l.value?.stage==="upload"?"Don't disconnect the USB cable yet.":`A first build takes a few minutes on a Raspberry Pi. You can leave this page: the ${X.value?"build":"installation"} keeps running and you'll find it again under New screen.`:B.value?X.value?"Put it on the screen from your own computer, then pair the screen with Home Assistant.":`The screen boots up and connects to your Wi-Fi.${n.board==="cyd"?" The CYD first asks for a touch calibration: tap the crosshairs.":""} Pair it with Home Assistant now:`:a.value.filter(pe=>/error/i.test(pe)).pop()||a.value.filter(pe=>/failed/i.test(pe)).pop()||"See the log below."),Ee=k(()=>({href:`api/firmware/profiles/${encodeURIComponent(n.file||"")}/download`,name:(n.file||"").replace(/\.yaml$/,"")+".factory.bin"})),pt=k(()=>[["Go to Home Assistant → Settings → Devices & services.",` This happens outside ESP Screens. Home Assistant discovers ${n.friendly} as an ESPHome device; click Add. Not discovered? Add ESPHome manually with the screen's IP address. `],["Paste the API key"," above when Home Assistant asks for an encryption key."],["Allow HA actions:"," ESPHome integration → Configure → “Allow the device to perform Home Assistant actions”. Without this, the screen sees everything but controls nothing."],["Choose your tiles."," Back in ESP Screens, the screen appears in the list on the left within about thirty seconds; until then it's shown there as “not yet in Home Assistant”."]]);async function Ze(pe){const N=pe.target;if(n.nodeEdited||(t.name=T(t.friendly_name)),!!N.reportValidity()){u.value=!0,d.value="";try{const de={board:t.board,friendly_name:t.friendly_name,name:t.name,target:t.target};O.value&&(J.value.includes("wifi_ssid")&&(de.wifi_ssid=t.wifi_ssid),J.value.includes("wifi_password")&&(de.wifi_password=t.wifi_password));const et=await Xe("firmware/profiles","POST",de);Object.assign(n,{file:et.file,apiKey:et.api_key,friendly:t.friendly_name.trim(),board:t.board,target:t.target}),t.wifi_password="",et.job?le(et.job,[]):n.view="done"}catch(de){d.value=de.message}finally{u.value=!1}}}async function qe(){try{if(!X.value){const{ports:N}=await dt("firmware");!N.includes(n.target)&&N.length===1&&(n.target=N[0])}const pe=await Xe("firmware/jobs","POST",X.value?{file:n.file,action:"download"}:{file:n.file,action:"install",target:n.target});le(pe,[])}catch(pe){Se(pe.message)}}function ls(){Object.assign(n,{view:"setup",file:null,apiKey:null,nodeEdited:!1,jobState:null,target:"",picked:!1,action:null}),Object.assign(t,{board:"cyd",friendly_name:"",name:"",wifi_ssid:"",wifi_password:"",target:""}),s.value=!1,l.value=null,a.value=[],d.value="",r.value="",f.value=!1,W()}function as(){n.view==="progress"&&n.jobState!=="running"&&(n.view="done"),Ae("")}return hn(()=>{W(),_=window.setInterval(W,3e3)}),An(()=>clearInterval(_)),(pe,N)=>(h(),m("div",xm,[i("div",Sm,[i("div",Cm,[N[13]||(N[13]=i("span",{class:"eyebrow"},"New screen",-1)),i("h1",Am,y(n.view==="setup"?"Connect and install.":ce.value),1),n.view==="setup"?(h(),m("p",Tm,"ESP Screens creates the screen's own profile with unique keys and builds the firmware. Connect the screen with a USB data cable to the machine running Home Assistant, or download the firmware and put it on the screen from your own computer.")):H("",!0)]),i("button",{type:"button",class:"btn quiet",id:"close-install","aria-label":"Close",onClick:as},"← Back")]),n.view==="setup"?(h(),m("form",{key:0,id:"install-form",class:"card",onSubmit:it(Ze,["prevent"])},[i("fieldset",null,[N[16]||(N[16]=i("legend",null,"Which screen do you have?",-1)),i("div",Em,[i("label",Pm,[ye(i("input",{type:"radio",name:"board",value:"cyd","onUpdate:modelValue":N[0]||(N[0]=de=>t.board=de)},null,512),[[Bi,t.board]]),N[14]||(N[14]=i("span",null,[i("b",null,"CYD · 2.8 inch"),i("small",null,"ESP32-2432S028 · 320 × 240")],-1))]),i("label",Om,[ye(i("input",{type:"radio",name:"board",value:"guition","onUpdate:modelValue":N[1]||(N[1]=de=>t.board=de)},null,512),[[Bi,t.board]]),N[15]||(N[15]=i("span",null,[i("b",null,"Guition · 4 inch"),i("small",null,"ESP32-S3-4848S040 · 480 × 480 · GT911")],-1))])])]),i("div",Im,[N[18]||(N[18]=i("label",{class:"f-label",for:"friendly_name"},"Name",-1)),ye(i("input",{id:"friendly_name",name:"friendly_name","onUpdate:modelValue":N[2]||(N[2]=de=>t.friendly_name=de),required:"",maxlength:"60",placeholder:"Living room screen",autocomplete:"off"},null,512),[[Ie,t.friendly_name]]),i("small",Mm,[N[17]||(N[17]=ee("Device name ",-1)),i("code",Lm,y(I.value),1),i("button",{type:"button",class:"btn link mini",id:"edit-node",onClick:N[3]||(N[3]=de=>{n.nodeEdited=!0,s.value=!0})},"customize")]),N[19]||(N[19]=i("small",null,"Every screen gets its own profile with its own keys. Four screens? Go through this four times with a different name.",-1))]),s.value?(h(),m("div",Dm,[N[20]||(N[20]=i("label",{class:"f-label",for:"node-name"},"Device name",-1)),ye(i("input",{id:"node-name",name:"name","onUpdate:modelValue":N[4]||(N[4]=de=>t.name=de),pattern:"[a-z][a-z0-9\\-]{0,29}",maxlength:"30",autocomplete:"off",onInput:N[5]||(N[5]=de=>n.nodeEdited=!0)},null,544),[[Ie,t.name]]),N[21]||(N[21]=i("small",null,"Lowercase letters, digits, and dashes. A different name for each screen.",-1))])):H("",!0),O.value?(h(),m("fieldset",Fm,[N[24]||(N[24]=i("legend",null,"Wi-Fi",-1)),i("p",Nm,y(C.value),1),J.value.includes("wifi_ssid")?(h(),m("div",Rm,[N[22]||(N[22]=i("label",{class:"f-label",for:"wifi_ssid"},"Wi-Fi name (2.4 GHz)",-1)),ye(i("input",{id:"wifi_ssid",name:"wifi_ssid","onUpdate:modelValue":N[6]||(N[6]=de=>t.wifi_ssid=de),autocomplete:"off"},null,512),[[Ie,t.wifi_ssid]])])):H("",!0),J.value.includes("wifi_password")?(h(),m("div",Hm,[N[23]||(N[23]=i("label",{class:"f-label",for:"wifi_password"},"Wi-Fi password",-1)),ye(i("input",{id:"wifi_password",name:"wifi_password",type:"password","onUpdate:modelValue":N[7]||(N[7]=de=>t.wifi_password=de),autocomplete:"new-password"},null,512),[[Ie,t.wifi_password]])])):H("",!0)])):H("",!0),i("div",Um,[N[26]||(N[26]=i("label",{class:"f-label",for:"install-target"},"Install via",-1)),ye(i("select",{id:"install-target",name:"target","onUpdate:modelValue":N[8]||(N[8]=de=>t.target=de),onChange:N[9]||(N[9]=de=>{n.picked=!0,W()})},[$.value.length?H("",!0):(h(),m("option",jm,"USB · no board found on the Home Assistant machine yet")),(h(!0),m(U,null,ie($.value,de=>(h(),m("option",{key:de,value:de},y(M(de)),9,Bm))),128)),i("option",{value:"download"},y(uy)),N[25]||(N[25]=i("option",{value:""},"Later · save profile only",-1))],544),[[un,t.target]]),i("small",Vm,y(P.value),1)]),r.value?(h(),m("p",Wm,y(r.value),1)):H("",!0),i("div",Km,[i("button",{type:"submit",class:"btn primary",id:"install-go",disabled:A.value},y(S.value),9,qm),i("span",Ym,y(d.value),1)])],32)):(h(),m("div",zm,[i("div",Jm,[Z.value?(h(),m("span",Gm)):(h(),m("span",{key:1,class:ue(["outcome",B.value?"ok":"bad"]),id:"progress-mark"},y(B.value?"✓":"✕"),3)),i("strong",Xm,y(V.value),1)]),i("p",Qm,y(Q.value),1),B.value&&X.value&&n.view!=="done"?(h(),m("div",Zm,[i("a",{class:"btn primary",id:"download-firmware",href:Ee.value.href,download:Ee.value.name},"Download "+y(Ee.value.name),9,ey),i("ol",ty,[N[30]||(N[30]=i("li",null,[i("b",null,"Plug the screen into your computer"),ee(" with a USB data cable.")],-1)),i("li",null,[i("b",null,[N[27]||(N[27]=ee("Open ",-1)),i("a",{href:ry,target:"_blank",rel:"noopener"},"ESPHome Web")]),N[28]||(N[28]=ee(" in Chrome or Edge, click Connect and choose the screen's USB port.",-1))]),i("li",null,[N[29]||(N[29]=i("b",null,"Click Install",-1)),ee(" and select "+y(Ee.value.name)+". The screen restarts and joins your Wi-Fi."+y(n.board==="cyd"?" The CYD first asks for a touch calibration: tap the crosshairs.":""),1)])]),N[31]||(N[31]=i("small",null,"The file holds your Wi-Fi password and the screen's keys: keep it to yourself.",-1))])):H("",!0),B.value?(h(),m("div",ny,[i("div",sy,[N[32]||(N[32]=i("span",null,"API key",-1)),i("code",{id:"api-key",ref_key:"keyBox",ref:p},y(n.apiKey||""),513),i("button",{type:"button",class:"btn quiet mini",id:"copy-key",onClick:N[10]||(N[10]=de=>v(lt)(n.apiKey||"",p.value))},"Copy")]),i("ol",oy,[(h(!0),m(U,null,ie(pt.value,([de,et],Tn)=>(h(),m("li",{key:Tn},[i("b",null,y(de),1),ee(y(et),1),Tn===0?(h(),m("button",{key:0,type:"button",class:"btn quiet mini",onClick:N[11]||(N[11]=(...Zt)=>v(Ts)&&v(Ts)(...Zt))},"Open Devices & services")):H("",!0)]))),128))])])):H("",!0),n.view!=="done"?(h(),m("details",{key:2,id:"install-log-wrap",class:"log-wrap",open:f.value,onToggle:N[12]||(N[12]=de=>f.value=de.target.open)},[N[33]||(N[33]=i("summary",null,"ESPHome log",-1)),i("pre",ly,y(a.value.join(` +`)),1)],40,iy)):H("",!0),i("div",ay,[!Z.value&&!B.value?(h(),m("button",{key:0,type:"button",class:"btn primary",id:"install-retry",onClick:qe},"Retry")):H("",!0),i("button",{type:"button",class:"btn quiet",id:"install-close",onClick:ls},y(B.value?"Install another screen":"Start over"),1),i("button",{type:"button",class:ue(["btn",B.value?"primary":"quiet"]),onClick:as},y(B.value?"Done":"Close"),3)])]))]))}}),dy={class:"panel",id:"firmware-dialog"},fy={class:"panel-head"},py={class:"card"},hy={class:"card-grid"},vy={class:"field"},my=["value"],yy={class:"field"},gy={key:0,value:"usb"},by=["value"],wy={key:0,class:"field",id:"firmware-host-label"},_y=["placeholder"],ky={class:"actions"},$y=["disabled"],xy=["disabled"],Sy=["disabled"],Cy={key:0,class:"spin"},Ay={id:"firmware-status",class:"status-line",role:"status"},Ty={key:0,id:"firmware-download",class:"card",style:{background:"var(--surface-2)"}},Ey=["href","download"],Py={id:"firmware-log",class:"log"},Oy="https://web.esphome.io/?dashboard_install",Iy="Download · flash from your own computer",My=Ce({__name:"FirmwareView",setup(e){const t=fe(null),n=fe(""),s=fe("ota"),o=fe("");let l=0;async function a(I=!1){try{const $=await dt("firmware");t.value=$,(I||!n.value)&&(n.value=$.profiles[0]?.file||"");const x=$.ports||[];s.value.startsWith("/")&&!x.includes(s.value)&&(s.value=x[0]||"usb"),s.value==="usb"&&x.length&&(s.value=x[0])}catch($){Se($.message)}}const r=k(()=>t.value?.job?.state==="running"),d=k(()=>!t.value||r.value||!t.value.available||!t.value.profiles?.length),u=k(()=>d.value||s.value==="usb"),f=k(()=>t.value?.ports||[]),p=k(()=>t.value?t.value.available?t.value.job?`${t.value.job.file} · ${t.value.job.action} · ${t.value.job.state}`:"Choose the intended profile, then a USB port, an IP address, or Download.":"The ESPHome CLI is missing. Update the app to 0.2.0.":"Loading…"),_=k(()=>s.value==="download"&&!!n.value&&!!t.value?.downloads?.includes(n.value)),T=k(()=>({href:`api/firmware/profiles/${encodeURIComponent(n.value)}/download`,name:n.value.replace(/\.yaml$/,"")+".factory.bin"}));async function M(I){try{await Xe("firmware/jobs","POST",{file:n.value,action:I==="validate"?"validate":I==="build"?"build":s.value==="download"?"download":"install",target:s.value==="ota"?o.value.trim():s.value==="download"?"":s.value}),await a()}catch($){Se($.message)}}return hn(()=>{a(!0),l=window.setInterval(()=>a(),3e3)}),An(()=>clearInterval(l)),(I,$)=>(h(),m("div",dy,[i("div",fy,[$[7]||($[7]=ys('

Firmware & USB

Build and install screen firmware

The built-in ESPHome CLI uses your own profile (YAML with keys) and secrets. Choose the screen's profile, then a USB port (screen connected to the Home Assistant machine), Wi-Fi / OTA with the hostname, or Download to put the firmware on the screen from your own computer. Check only validates, Build only compiles, Build & install puts the firmware on the screen. Your tiles stay as they are in ESP Screens. The first build takes a few minutes.

',1)),i("button",{type:"button",class:"btn quiet",id:"close-firmware",onClick:$[0]||($[0]=x=>v(Ae)(""))},"← Back")]),i("div",py,[i("div",hy,[i("div",vy,[$[8]||($[8]=i("label",{class:"f-label",for:"firmware-file"},"ESPHome profile",-1)),ye(i("select",{id:"firmware-file","onUpdate:modelValue":$[1]||($[1]=x=>n.value=x)},[(h(!0),m(U,null,ie(t.value?.profiles||[],x=>(h(),m("option",{key:x.file,value:x.file},y(x.file),9,my))),128))],512),[[un,n.value]])]),i("div",yy,[$[10]||($[10]=i("label",{class:"f-label",for:"firmware-port"},"Install to",-1)),ye(i("select",{id:"firmware-port","onUpdate:modelValue":$[2]||($[2]=x=>s.value=x)},[$[9]||($[9]=i("option",{value:"ota"},"Wi-Fi / OTA",-1)),f.value.length?H("",!0):(h(),m("option",gy,"USB · no board found on the Home Assistant machine yet")),(h(!0),m(U,null,ie(f.value,x=>(h(),m("option",{key:x,value:x},y(x),9,by))),128)),i("option",{value:"download"},y(Iy))],512),[[un,s.value]])]),s.value==="ota"?(h(),m("div",wy,[$[11]||($[11]=i("label",{class:"f-label",for:"firmware-host"},"IP address or hostname",-1)),ye(i("input",{id:"firmware-host","onUpdate:modelValue":$[3]||($[3]=x=>o.value=x),placeholder:n.value?n.value.replace(/\.yaml$/,".local"):"screen-livingroom.local"},null,8,_y),[[Ie,o.value]])])):H("",!0)]),i("div",ky,[i("button",{type:"button",class:"btn quiet",id:"firmware-validate",disabled:d.value,onClick:$[4]||($[4]=x=>M("validate"))},"Check",8,$y),i("button",{type:"button",class:"btn quiet",id:"firmware-build",disabled:d.value,onClick:$[5]||($[5]=x=>M("build"))},"Build only",8,xy),i("button",{type:"button",class:"btn primary",id:"firmware-install",disabled:u.value,onClick:$[6]||($[6]=x=>M("install"))},y(s.value==="download"?"Build & download":"Build & install"),9,Sy),r.value?(h(),m("span",Cy)):H("",!0)]),i("p",Ay,y(p.value),1),_.value?(h(),m("div",Ty,[i("a",{class:"btn primary",id:"firmware-download-link",href:T.value.href,download:T.value.name},"Download "+y(T.value.name),9,Ey),i("small",null,[$[12]||($[12]=ee("Put it on the screen with ",-1)),i("a",{href:Oy,target:"_blank",rel:"noopener"},"ESPHome Web"),$[13]||($[13]=ee(" in Chrome or Edge: Connect, choose the screen's USB port, Install, and select this file. It holds your Wi-Fi password and the screen's keys: keep it to yourself.",-1))])])):H("",!0)]),i("pre",Py,y((t.value?.logs||[]).join(` +`)),1)]))}}),Ly={class:"panel wide alerts",id:"alerts-dialog"},Dy={class:"panel-head"},Fy={key:0,class:"hint"},Ny={class:"alert-hero"},Ry={class:"alert-mock",id:"alert-mock","aria-hidden":"true"},Hy={class:"mdi alert-mock-icon",id:"alert-mock-icon"},Uy={class:"alerts-nav","aria-label":"Sections"},jy=["data-jump","onClick"],By={id:"alerts-try",class:"card"},Vy={class:"field"},Wy={value:"all"},Ky=["value","disabled"],qy={class:"field"},Yy={class:"field"},zy={class:"field"},Jy={id:"try-icons"},Gy=["value"],Xy={class:"field"},Qy=["value"],Zy={class:"field"},eg={class:"field"},tg={class:"check field"},ng={class:"actions field wide"},sg=["disabled"],og={class:"status-line",id:"try-result",role:"status"},ig={id:"alerts-screens",class:"card"},lg={id:"alerts-min-firmware"},ag={id:"alerts-screen-list",class:"options"},rg={key:0,class:"hint"},ug={class:"alert-screen-head"},cg={class:"copy-label"},dg=["onClick"],fg={id:"alerts-howto",class:"card"},pg={class:"field"},hg=["value"],vg={key:0,value:""},mg={class:"copy-line"},yg={id:"alerts-example"},gg={id:"alerts-all",class:"card"},bg={id:"alerts-all-event"},wg={id:"alerts-all-dismiss"},_g={class:"copy-line"},kg={id:"alerts-all-example"},$g={id:"alerts-fields",class:"card"},xg={class:"table-scroll"},Sg={id:"alerts-field-table"},Cg={key:0},Ag={id:"alerts-icons",class:"card"},Tg={class:"chips",id:"alerts-suggested"},Eg=["onClick"],Pg={class:"mdi"},Og={class:"field"},Ig={id:"alerts-icon-groups"},Mg={class:"subhead"},Lg={class:"alert-icon-grid"},Dg=["title","onClick"],Fg={class:"mdi"},Ng={key:0},Rg={key:0,class:"hint"},Hg={id:"alerts-colors",class:"card"},Ug={class:"swatches",id:"alerts-swatches"},jg=["onClick"],Bg={id:"alerts-events",class:"card"},Vg={id:"alerts-event-name"},Wg={class:"table-scroll"},Kg={id:"alerts-ending-table"},qg={class:"copy-line"},Yg={id:"alerts-wait-example"},zg={id:"alerts-tips",class:"card"},Jg={class:"alerts-list"},Gg=Ce({__name:"AlertsView",setup(e){const t=k(()=>c.inventory.alerts),n=fn({screen:"all",title:"Someone is at the door",subtitle:"Door 3, back",icon:"doorbell",color:"orange",button_text:"Coming",timeout:30,flash:!0}),s=fe(!1),o=fe(""),l=k(()=>c.inventory.screens.filter(S=>dn(S)&&S.online));async function a(){s.value=!0,o.value="";try{const{screen:S,...b}=n,A=await Mc(S,b),q=S==="all"?`${A.sent} screen${A.sent===1?"":"s"}`:c.inventory.screens.find(W=>W.id===S)?.name||"the screen";o.value=A.sent?`Sent to ${q}.${A.skipped?` ${A.skipped} skipped (offline or old firmware).`:""}${A.unusable?.length?` Left empty: ${A.unusable.join(", ")}.`:""}`:"No screen could show it: check that a screen is online with firmware "+(t.value?.min_firmware||"0.2.31")+" or newer."}catch(S){o.value=S.message}finally{s.value=!1}}const r=k(()=>c.inventory.icons),d=fe(""),u=fe(""),f=S=>`"${String(S).replace(/\\/g,"\\\\").replace(/"/g,'\\"')}"`,p=S=>S.type==="string"?/^[a-z][a-z0-9-]*$/.test(S.example)?S.example:f(S.example):S.example===!0?"true":S.example===!1?"false":String(S.example),_=k(()=>c.inventory.screens.filter(S=>S.alert_action)),T=k(()=>d.value||_.value[0]?.alert_action||""),M=k(()=>{const S=(t.value?.fields||[]).map(b=>` ${b.name}: ${p(b)}`);return`action: ${T.value||"esphome._show_alert"} +data: +${S.join(` +`)}`}),I=k(()=>["# Doorbell: show the alert and wait until someone presses the button.","actions:",` - action: ${T.value||"esphome._show_alert"}`," data:",' title: "Someone is at the door"',' subtitle: "Door 3, back"'," icon: doorbell"," color: orange",' button_text: "Coming"'," timeout: 0"," flash: true"," - wait_for_trigger:"," - trigger: event",` event_type: ${t.value?.event||"esphome.screen_alert"}`," event_data:"," action: ok",' timeout: "00:05:00"'," - if:"," - condition: template",' value_template: "{{ wait.trigger is not none }}"'," then:"," - action: notify.notify"," data:",' message: "Someone is coming to the door."'].join(` +`)),$=k(()=>{const S=(t.value?.fields||[]).map(A=>` ${A.name}: ${p(A)}`),b=t.value?.camera;return b&&S.push(` # ${b.name}: ${b.example} # a Guition shows its picture on the card`),`event: ${t.value?.broadcast?.show||"esp_screens_show_alert"} +event_data: +${S.join(` +`)}`}),x=k(()=>{if(!t.value||!r.value)return[];const S=u.value.trim().toLowerCase();return[...r.value.groups,{label:"Also available: control and weather icons",icons:t.value.extra_icons}].map(A=>({label:A.label,icons:A.icons.filter(q=>!S||q.name.includes(S)||(q.label||"").toLowerCase().includes(S))})).filter(A=>A.icons.length)}),O=k(()=>t.value?.suggested_icons?.find(S=>S.name==="doorbell")),J=k(()=>t.value?.colors?.find(S=>S.name==="orange")),C={string:"text",int:"number",bool:"on / off"};function z(S){document.getElementById(S)?.scrollIntoView({behavior:"smooth",block:"start"})}const P=[["alerts-try","Try it"],["alerts-screens","Your screens"],["alerts-howto","In an automation"],["alerts-all","All screens"],["alerts-fields","The fields"],["alerts-icons","Icons"],["alerts-colors","Colors"],["alerts-behaviour","Behavior"],["alerts-events","Events"],["alerts-tips","Tips"]];return(S,b)=>(h(),m("div",Ly,[i("div",Dy,[b[15]||(b[15]=i("div",{class:"tx"},[i("span",{class:"eyebrow"},"Alerts · cheatsheet"),i("h1",null,"A full-screen notification, from an automation."),i("p",null,[ee("Every screen has the "),i("code",null,"show_alert"),ee(" action. It places a card over everything, wakes the screen, and keeps the backlight at normal brightness until someone taps the button or the timeout runs out. Home Assistant itself shows no explanation or dropdowns for ESPHome actions; everything you can fill in is listed here.")])],-1)),i("button",{type:"button",class:"btn quiet",id:"close-alerts",onClick:b[0]||(b[0]=A=>v(Ae)(""))},"← Back")]),t.value?(h(),m(U,{key:1},[i("div",Ny,[i("div",Ry,[i("div",{class:"alert-mock-card",style:Pe(J.value?{background:J.value.color}:void 0)},[i("span",Hy,y(O.value?v(be)(O.value.cp):""),1),b[16]||(b[16]=i("strong",{id:"alert-mock-title"},"Someone is at the door",-1)),b[17]||(b[17]=i("span",{id:"alert-mock-subtitle"},"Door 3, back",-1)),b[18]||(b[18]=i("span",{class:"fake",id:"alert-mock-button"},"Coming",-1))],4)]),i("nav",Uy,[(h(),m(U,null,ie(P,([A,q])=>i("button",{key:A,type:"button","data-jump":A,onClick:W=>z(A)},y(q),9,jy)),64))])]),i("section",By,[b[28]||(b[28]=i("h2",null,"Try it",-1)),b[29]||(b[29]=i("p",null,"Send one alert now, with the same fields an automation sends. The screen shows the card and, with blinking on, flashes its backlight.",-1)),i("form",{class:"try-grid",onSubmit:it(a,["prevent"])},[i("div",Vy,[b[19]||(b[19]=i("label",{class:"f-label",for:"try-screen"},"Screen",-1)),ye(i("select",{id:"try-screen","onUpdate:modelValue":b[1]||(b[1]=A=>n.screen=A)},[i("option",Wy,"All screens ("+y(l.value.length)+" ready)",1),(h(!0),m(U,null,ie(v(c).inventory.screens,A=>(h(),m("option",{key:A.id,value:A.id,disabled:!v(dn)(A)||!A.online},y(A.name)+y(v(dn)(A)&&A.online?"":" · not ready"),9,Ky))),128))],512),[[un,n.screen]])]),i("div",qy,[b[20]||(b[20]=i("label",{class:"f-label",for:"try-title"},"Title",-1)),ye(i("input",{id:"try-title","onUpdate:modelValue":b[2]||(b[2]=A=>n.title=A),maxlength:"64"},null,512),[[Ie,n.title]])]),i("div",Yy,[b[21]||(b[21]=i("label",{class:"f-label",for:"try-subtitle"},"Subtitle",-1)),ye(i("input",{id:"try-subtitle","onUpdate:modelValue":b[3]||(b[3]=A=>n.subtitle=A),maxlength:"240"},null,512),[[Ie,n.subtitle]])]),i("div",zy,[b[22]||(b[22]=i("label",{class:"f-label",for:"try-icon"},"Icon",-1)),ye(i("input",{id:"try-icon","onUpdate:modelValue":b[4]||(b[4]=A=>n.icon=A),list:"try-icons",placeholder:"doorbell"},null,512),[[Ie,n.icon]]),i("datalist",Jy,[(h(!0),m(U,null,ie(t.value.suggested_icons,A=>(h(),m("option",{key:A.name,value:A.name},y(A.label||A.name),9,Gy))),128))])]),i("div",Xy,[b[24]||(b[24]=i("label",{class:"f-label",for:"try-color"},"Color",-1)),ye(i("select",{id:"try-color","onUpdate:modelValue":b[5]||(b[5]=A=>n.color=A)},[b[23]||(b[23]=i("option",{value:""},"White (default)",-1)),(h(!0),m(U,null,ie(t.value.colors,A=>(h(),m("option",{key:A.name,value:A.name},y(A.label),9,Qy))),128))],512),[[un,n.color]])]),i("div",Zy,[b[25]||(b[25]=i("label",{class:"f-label",for:"try-button"},"Button text",-1)),ye(i("input",{id:"try-button","onUpdate:modelValue":b[6]||(b[6]=A=>n.button_text=A),maxlength:"16"},null,512),[[Ie,n.button_text]])]),i("div",eg,[b[26]||(b[26]=i("label",{class:"f-label",for:"try-timeout"},"Timeout (seconds, 0 waits for the button)",-1)),ye(i("input",{id:"try-timeout","onUpdate:modelValue":b[7]||(b[7]=A=>n.timeout=A),type:"number",min:"0",max:"86400"},null,512),[[Ie,n.timeout,void 0,{number:!0}]])]),i("label",tg,[ye(i("input",{type:"checkbox",id:"try-flash","onUpdate:modelValue":b[8]||(b[8]=A=>n.flash=A)},null,512),[[Qu,n.flash]]),b[27]||(b[27]=i("span",null,[ee("Blink the backlight"),i("small",null,"Four times when the alert arrives.")],-1))]),i("div",ng,[i("button",{type:"submit",class:"btn primary",id:"try-send",disabled:s.value||!l.value.length},y(s.value?"Sending…":"Send alert"),9,sg),i("span",og,y(o.value),1)])],32)]),i("section",ig,[b[32]||(b[32]=i("h2",null,"Your screens",-1)),i("p",null,[b[30]||(b[30]=ee("Every screen has its own action, with the device name in it. From firmware ",-1)),i("code",lg,y(t.value.min_firmware),1),b[31]||(b[31]=ee("; update an older screen with its Update button under Screens.",-1))]),i("div",ag,[v(c).inventory.screens.length?H("",!0):(h(),m("p",rg,"No screen paired yet. Install one via New screen; the action appears once Home Assistant sees the screen.")),(h(!0),m(U,null,ie(v(c).inventory.screens,A=>(h(),m("div",{key:A.id,class:"alert-screen"},[i("div",ug,[i("strong",null,y(A.name),1),i("span",{class:ue(["chip",v(Sn)(A.firmware,t.value.min_firmware)&&A.alert_action?"good":"update"])},y(v(Sn)(A.firmware,t.value.min_firmware)&&A.alert_action?`● firmware ${A.firmware}`:A.alert_action?`Update needed · firmware ${A.firmware||"unknown"}`:"Device name unknown · update the screen"),3)]),(h(!0),m(U,null,ie([["Show alert",A.alert_action],["Dismiss alert",A.dismiss_action]],([q,W])=>(h(),m("div",{key:q,class:"copy-line"},[i("span",cg,y(q),1),i("code",null,y(W||"esphome._show_alert"),1),W?(h(),m("button",{key:0,type:"button",class:"btn quiet mini",onClick:le=>v(lt)(W,void 0,"Action name")},"Copy",8,dg)):H("",!0)]))),128))]))),128))])]),i("section",fg,[b[34]||(b[34]=ys('

In an automation

  1. Add action and search for ESPHome. Choose your screen's action: Home Assistant calls it "Performs the action show_alert of the node device name".
  2. Fill in the fields. Home Assistant asks for all seven; leave what you don't use empty ("", 0, off).
  3. Prefer YAML? Choose Edit in YAML on the action and paste the example below.
',2)),i("div",pg,[b[33]||(b[33]=i("label",{class:"f-label",for:"alerts-example-screen"},"Example for",-1)),ye(i("select",{id:"alerts-example-screen","onUpdate:modelValue":b[9]||(b[9]=A=>d.value=A),style:{"max-width":"360px"}},[(h(!0),m(U,null,ie(_.value,A=>(h(),m("option",{key:A.id,value:A.alert_action},y(A.name),9,hg))),128)),_.value.length?H("",!0):(h(),m("option",vg,"a screen (not paired yet)"))],512),[[un,d.value]])]),i("div",mg,[i("pre",yg,y(M.value),1),i("button",{type:"button",class:"btn quiet mini",id:"alerts-example-copy",onClick:b[10]||(b[10]=A=>v(lt)(M.value,void 0,"YAML"))},"Copy YAML")])]),i("section",gg,[b[42]||(b[42]=i("h2",null,"All screens at once",-1)),i("p",null,[b[35]||(b[35]=ee("Fire the event ",-1)),i("code",bg,y(t.value.broadcast?.show||"esp_screens_show_alert"),1),b[36]||(b[36]=ee(" with the same fields, and ESP Screens passes the alert on to every screen that is online, including screens you add later. ",-1)),i("code",wg,y(t.value.broadcast?.dismiss||"esp_screens_dismiss_alert"),1),b[37]||(b[37]=ee(" clears it everywhere. In an automation, add the ",-1)),b[38]||(b[38]=i("b",null,"Event",-1)),b[39]||(b[39]=ee(" action or paste the example under ",-1)),b[40]||(b[40]=i("b",null,"Edit in YAML",-1)),b[41]||(b[41]=ee(". Leave out the fields you don't use. ESP Screens has to be running for this.",-1))]),i("div",_g,[i("pre",kg,y($.value),1),i("button",{type:"button",class:"btn quiet mini",id:"alerts-all-copy",onClick:b[11]||(b[11]=A=>v(lt)($.value,void 0,"YAML"))},"Copy YAML")])]),i("section",$g,[b[46]||(b[46]=i("h2",null,"The fields",-1)),b[47]||(b[47]=i("p",null,"Text is free-form; the limit is in bytes, and an accented letter counts as two. What doesn't fit gets an ellipsis (title) or is dropped (subtitle).",-1)),i("div",xg,[i("table",Sg,[b[45]||(b[45]=i("tr",null,[i("th",null,"Field"),i("th",null,"Type"),i("th",null,"What it does"),i("th",null,"Example"),i("th",null,"Limit")],-1)),(h(!0),m(U,null,ie(t.value.fields,A=>(h(),m("tr",{key:A.name},[i("td",null,[i("code",null,y(A.name),1),i("small",null,y(A.label),1)]),i("td",null,y(C[A.type]||A.type),1),i("td",null,y(A.help),1),i("td",null,[i("code",null,y(typeof A.example=="string"?A.example:String(A.example)),1)]),i("td",null,y(t.value.limits.cyd[A.name]?`CYD ${t.value.limits.cyd[A.name]} · Guition ${t.value.limits.guition[A.name]} bytes`:A.type==="int"?"0 to 86400 s":"—"),1)]))),128)),t.value.camera?(h(),m("tr",Cg,[i("td",null,[i("code",null,y(t.value.camera.name),1),i("small",null,y(t.value.camera.label),1)]),b[43]||(b[43]=i("td",null,"entity",-1)),i("td",null,y(t.value.camera.help),1),i("td",null,[i("code",null,y(t.value.camera.example),1)]),b[44]||(b[44]=i("td",null,"Guition, firmware 0.2.57+",-1))])):H("",!0)])])]),i("section",Ag,[b[49]||(b[49]=i("h2",null,"Icons",-1)),b[50]||(b[50]=i("p",null,[ee("Fill in the name in "),i("code",null,"icon"),ee(", for example "),i("code",null,"doorbell"),ee(". "),i("code",null,"mdi:doorbell"),ee(" and the hex codepoint ("),i("code",null,"F12E6"),ee(") also work. Only these icons are included in the firmware; any other name shows the warning triangle. Tap an icon to copy its name.")],-1)),b[51]||(b[51]=i("p",{class:"subhead"},"Handy for notifications",-1)),i("div",Tg,[(h(!0),m(U,null,ie(t.value.suggested_icons,A=>(h(),m("button",{key:A.name,type:"button",class:"chip",onClick:q=>v(lt)(A.name,void 0,"Icon name")},[i("span",Pg,y(v(be)(A.cp)),1),i("code",null,y(A.name),1)],8,Eg))),128))]),i("div",Og,[b[48]||(b[48]=i("label",{class:"f-label",for:"alerts-icon-search"},"Search for an icon",-1)),ye(i("input",{id:"alerts-icon-search","onUpdate:modelValue":b[12]||(b[12]=A=>u.value=A),type:"search",placeholder:"Search by name or description…",autocomplete:"off"},null,512),[[Ie,u.value]])]),i("div",Ig,[(h(!0),m(U,null,ie(x.value,A=>(h(),m("div",{key:A.label,class:"field"},[i("p",Mg,y(A.label)+" · "+y(A.icons.length),1),i("div",Lg,[(h(!0),m(U,null,ie(A.icons,q=>(h(),m("button",{key:q.name,type:"button",class:"alert-icon",title:`Copy ${q.name}`,onClick:W=>v(lt)(q.name,void 0,"Icon name")},[i("span",Fg,y(v(be)(q.cp)),1),i("code",null,y(q.name),1),q.label?(h(),m("small",Ng,y(q.label),1)):H("",!0)],8,Dg))),128))])]))),128)),x.value.length?H("",!0):(h(),m("p",Rg,'No icon for "'+y(u.value)+'". Unknown names show the warning triangle ('+y(t.value.fallback_icon)+").",1))])]),i("section",Hg,[b[53]||(b[53]=i("h2",null,"Colors",-1)),b[54]||(b[54]=i("p",null,[ee("Fill in the name in "),i("code",null,"color"),ee(". These are the pastel shades of the tiles, with dark text. Empty or unknown gives the white card. Tap to copy.")],-1)),i("div",Ug,[i("button",{type:"button",class:"swatch",onClick:b[13]||(b[13]=A=>v(lt)("",void 0,"Empty color"))},[...b[52]||(b[52]=[i("i",{style:{background:"#ffffff"}},null,-1),i("span",null,[i("code",null,"empty"),i("small",null,"White (default)")],-1)])]),(h(!0),m(U,null,ie(t.value.colors,A=>(h(),m("button",{key:A.name,type:"button",class:"swatch",onClick:q=>v(lt)(A.name,void 0,"Color name")},[i("i",{style:Pe({background:A.color})},null,4),i("span",null,[i("code",null,y(A.name),1),i("small",null,y(A.label)+" · "+y(A.color),1)])],8,jg))),128))])]),b[75]||(b[75]=ys('

Behavior

  • Wakes the screen. An alert immediately wakes a dimmed or dark screen and appears above every page, every open light card, and the standby layer.
  • On until the button. As long as the card is showing, the backlight stays at normal brightness. Standby and night hours wait. After the button, the regular standby time starts again.
  • Timeout. timeout: 0 waits for the button, however long that takes. With timeout: 60 the card disappears after a minute, but the button closes it sooner.
  • Blinking. flash: true blinks the backlight four times when the alert arrives (about a second) and leaves the screen on afterward.
  • Replacing. A new alert replaces the current one; there's no stack. The replaced alert reports itself as replaced.
  • Closing remotely. dismiss_alert clears the card, for example if the door is already open. Without an alert, that action does nothing.
  • Tapping beside the card does nothing; only the button closes it. That way a wake-up tap never accidentally dismisses the alert.
',1)),i("section",Bg,[b[66]||(b[66]=i("h2",null,"Events",-1)),i("p",null,[b[55]||(b[55]=ee("Every end fires the event ",-1)),i("code",Vg,y(t.value.event),1),b[56]||(b[56]=ee(" with ",-1)),b[57]||(b[57]=i("code",null,"action",-1)),b[58]||(b[58]=ee(", ",-1)),b[59]||(b[59]=i("code",null,"title",-1)),b[60]||(b[60]=ee(", ",-1)),b[61]||(b[61]=i("code",null,"screen",-1)),b[62]||(b[62]=ee(" (the device name) and the ",-1)),b[63]||(b[63]=i("code",null,"device_id",-1)),b[64]||(b[64]=ee(" that Home Assistant adds. Visible under Settings → Tools → Events.",-1))]),i("div",Wg,[i("table",Kg,[b[65]||(b[65]=i("tr",null,[i("th",null,"action"),i("th",null,"When")],-1)),(h(!0),m(U,null,ie(t.value.endings,A=>(h(),m("tr",{key:A.action},[i("td",null,[i("code",null,y(A.action),1)]),i("td",null,y(A.label),1)]))),128))])]),b[67]||(b[67]=i("p",{class:"subhead"},"Waiting until someone presses the button",-1)),i("div",qg,[i("pre",Yg,y(I.value),1),i("button",{type:"button",class:"btn quiet mini",id:"alerts-wait-copy",onClick:b[14]||(b[14]=A=>v(lt)(I.value,void 0,"YAML"))},"Copy YAML")])]),i("section",zg,[b[74]||(b[74]=i("h2",null,"Tips",-1)),i("ul",Jg,[b[72]||(b[72]=ys("
  • Use a color per kind of notification: orange for the door, red for smoke or water, green for "done". The text always stays dark and readable.
  • Keep the title short; a screen shows about twenty characters on one line and ends a longer title with an ellipsis. Put details in the subtitle.
  • A custom button text turns the notification into a question: "Coming", "Seen", "Turn off". The event then tells you who responded.
  • For an alert that resolves itself (the door opens, the laundry gets taken out) close it in the same automation with dismiss_alert.
  • ",4)),i("li",null,[b[68]||(b[68]=ee("Every screen? Fire ",-1)),i("code",null,y(t.value.broadcast?.show||"esp_screens_show_alert"),1),b[69]||(b[69]=ee(" once (see All screens at once). The screens still work independently and each reports with its own ",-1)),b[70]||(b[70]=i("code",null,"screen",-1)),b[71]||(b[71]=ee(".",-1))]),b[73]||(b[73]=i("li",null,[ee("Rather "),i("b",null,"ask Claude"),ee(" for the automation? Install the ESP Screens skill under Settings → Claude.")],-1))])])],64)):(h(),m("p",Fy,"The cheatsheet is still loading; one moment."))]))}}),Xg={class:"panel",id:"override-dialog"},Qg={class:"panel-head"},Zg={class:"tx"},eb={id:"override-title"},tb={class:"notice"},nb={class:"mdi"},sb={class:"file-row"},ob={id:"override-file"},ib={class:"yaml-editor",id:"yaml-editor-wrap"},lb={class:"actions"},ab={id:"override-count",class:"hint"},rb={class:"actions"},ub=["disabled"],cb=["disabled"],db=`# Hardware-specific changes for this screen. +# This file is kept when the shared firmware package updates. +# Do not add esphome:, api:, ota:, wifi: or packages: here. + +# Example: a CYD with the ST7789V display controller. +# "!extend" changes the display the shared package already defines; +# a bare id would add a second, incomplete display and fail the build. +display: + - id: !extend my_display + model: ST7789V +`,fb=Ce({__name:"OverrideView",setup(e){const t=k(()=>c.overrideProfile),n=fe(""),s=fe(""),o=fe(!1),l=fe("Loading…"),a=fe(""),r=fe(!1),d=fe(null),u=fe(null),f=k(()=>n.value.split(` +`).length),p=k(()=>Array.from({length:f.value},(P,S)=>S+1).join(` +`)),_=k(()=>`${n.value.length} characters · ${f.value} line${f.value===1?"":"s"}`);let T=!0;function M(P,S=""){l.value=P,a.value=S}async function I(){if(!t.value){M("No ESPHome profile was found for this screen.","error");return}M("Loading…");try{const P=await dt(`firmware/profiles/${encodeURIComponent(t.value)}/override`);s.value=P.override_file,o.value=!!P.attached,n.value=P.exists&&P.content!==`{} +`?P.content:"",M(P.attached?"Changes here apply on the next build.":"Save once to attach this file to the profile.")}catch(P){M(P.message,"error")}}async function $(P=!1){if(!(!t.value||r.value)){r.value=!0,M("Checking and saving…");try{const S=await Xe(`firmware/profiles/${encodeURIComponent(t.value)}/override`,"PUT",{content:n.value});if(s.value=S.override_file,o.value=!0,!P){M("Saved. The override is kept during firmware updates.","ok"),Se("Override YAML saved.");return}M("Saved. ESPHome is checking the complete profile…"),await Xe("firmware/jobs","POST",{file:t.value,action:"validate"}),x()}catch(S){M(S.message,"error")}finally{r.value=!1}}}function x(){const P=Date.now(),S=t.value,b=async()=>{if(!(!T||t.value!==S))try{const A=await dt("firmware"),q=A.job;if(q&&q.file===S&&q.state==="running")M(`ESPHome is checking the profile… ${q.stage||""}`.trim());else if(q&&q.file===S&&q.state==="success"){M("The complete profile is valid. Safe to build and install.","ok");return}else if(q&&q.file===S&&q.state==="failed"){const W=(A.logs||[]).filter(le=>/error|failed/i.test(le)).pop();M(W||"ESPHome rejected the complete profile. See Firmware & USB for the full log.","error");return}Date.now()-P<72e5&&setTimeout(b,1200)}catch(A){M(A.message,"error")}};b()}function O(){(!n.value.trim()||confirm("Replace the current text with the example?"))&&(n.value=db,M("Example loaded. Save it when you are ready."),d.value?.focus())}function J(){(!n.value.trim()||confirm("Clear the local override?"))&&(n.value="",M("The override will be empty after you save."),d.value?.focus())}function C(P){const S=d.value;if(P.key==="Tab"){P.preventDefault();const b=S.selectionStart,A=S.selectionEnd;S.setRangeText(" ",b,A,"end"),n.value=S.value}else(P.ctrlKey||P.metaKey)&&P.key.toLowerCase()==="s"&&(P.preventDefault(),$(!1))}function z(){u.value&&d.value&&(u.value.scrollTop=d.value.scrollTop)}return hn(I),An(()=>{T=!1}),(P,S)=>(h(),m("div",Xg,[i("div",Qg,[i("div",Zg,[S[4]||(S[4]=i("span",{class:"eyebrow"},"Advanced · local override",-1)),i("h1",eb,"Override YAML"+y(v(c).overrideFriendly?` · ${v(c).overrideFriendly}`:""),1),S[5]||(S[5]=i("p",null,"This small file is yours. It is loaded after the shared screen package and stays in place when ESP Screen Manager updates. Change hardware-specific details here, such as a display model.",-1))]),i("button",{type:"button",class:"btn quiet",id:"close-override",onClick:S[0]||(S[0]=b=>v(Ae)(""))},"← Back")]),i("div",tb,[i("span",nb,y(v(be)("F0493")),1),S[6]||(S[6]=i("div",null,[i("strong",null,"What is safe to change?"),i("span",null,"Display, touchscreen, substitutions, pins and other device details. Name, Wi-Fi, API, OTA and package links remain managed.")],-1))]),i("div",sb,[i("code",ob,y(s.value||t.value||""),1),i("span",{id:"override-state",class:ue(["chip",{good:o.value}])},y(o.value?"Active":"Ready to attach"),3)]),i("div",ib,[i("div",{ref_key:"gutter",ref:u,class:"yaml-gutter",id:"override-gutter","aria-hidden":"true"},y(p.value),513),ye(i("textarea",{ref_key:"editor",ref:d,id:"override-editor","onUpdate:modelValue":S[1]||(S[1]=b=>n.value=b),spellcheck:"false",autocapitalize:"off",autocomplete:"off",autocorrect:"off","aria-label":"Local override YAML",placeholder:`# Example +display: + - id: !extend my_display + model: ST7789V`,onKeydown:C,onScroll:z},null,544),[[Ie,n.value]])]),i("div",lb,[i("button",{type:"button",class:"btn quiet mini",id:"override-example",onClick:O},"Use example"),i("button",{type:"button",class:"btn quiet mini",id:"override-empty",onClick:J},"Clear"),i("span",ab,y(_.value),1)]),i("p",{id:"override-status",class:ue(["status-line",a.value]),role:"status"},y(l.value),3),i("div",rb,[i("button",{type:"button",class:"btn quiet",id:"override-check",disabled:r.value||!t.value,onClick:S[2]||(S[2]=b=>$(!0))},"Save & check",8,ub),i("button",{type:"button",class:"btn primary",id:"override-save",disabled:r.value||!t.value,onClick:S[3]||(S[3]=b=>$(!1))},"Save override",8,cb)])]))}}),pb={class:"main"},hb=Ce({__name:"App",setup(e){const t=k(()=>tt.value==="#settings"?$m:tt.value==="#new-screen"?cy:tt.value==="#firmware"?My:tt.value==="#alerts"?Gg:tt.value==="#override"?fb:Ct.value&&c.layout?em:sm);function n(s){(s.metaKey||s.ctrlKey)&&s.key.toLowerCase()==="k"&&(s.preventDefault(),c.palette=!c.palette)}return hn(()=>document.addEventListener("keydown",n)),An(()=>document.removeEventListener("keydown",n)),(s,o)=>(h(),m("div",{class:ue(["app",{dragging:v(c).drag.active}])},[$e(bd),i("main",pb,[(h(),Ke(jr(t.value)))]),$e(_d),$e(Od)],2))}});ic(hb).mount("#app");zc(); diff --git a/screen_manager/app/static/assets/index-D7h6hKdu.css b/screen_manager/app/static/assets/index-D7h6hKdu.css deleted file mode 100644 index 66dea48..0000000 --- a/screen_manager/app/static/assets/index-D7h6hKdu.css +++ /dev/null @@ -1 +0,0 @@ -:root{color-scheme:light dark;--ground: #f5f6f8;--surface: #ffffff;--surface-2: #f9fafb;--line: #e4e7ec;--line-strong: #d3d8e0;--ink: #16181d;--ink-2: #565d6b;--muted: #7a8290;--accent: #2f63f0;--accent-ink: #ffffff;--accent-soft: #edf2ff;--good: #1e9a5f;--good-soft: #e6f6ee;--warn: #b56d00;--warn-soft: #fff3df;--danger: #c6372e;--danger-soft: #fdecea;--seg: #eef0f3;--shadow: 0 12px 40px rgba(20, 24, 40, .12), 0 1px 2px rgba(20, 24, 40, .06);--code-bg: #f1f3f6;--ui-font: -apple-system, BlinkMacSystemFont, system-ui, "SF Pro Text", "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;--mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace}@media(prefers-color-scheme:dark){:root{--ground: #0e1014;--surface: #161a21;--surface-2: #1b2029;--line: #262c37;--line-strong: #333b49;--ink: #e9ecf1;--ink-2: #b4bbc7;--muted: #8a93a3;--accent: #6d93ff;--accent-ink: #0b1633;--accent-soft: #1b2540;--good: #3fbf7f;--good-soft: #14302a;--warn: #e0a03a;--warn-soft: #302610;--danger: #f07167;--danger-soft: #3a1b19;--seg: #222834;--shadow: 0 16px 48px rgba(0, 0, 0, .55), 0 1px 2px rgba(0, 0, 0, .4);--code-bg: #12151b}}@font-face{font-family:Tile Icons;src:url(./tile-icons-BawP5y9D.woff) format("woff");font-display:block}@font-face{font-family:Bar Roboto;font-weight:400;src:url(./bar-roboto-400-H0q_-5Ia.woff) format("woff");font-display:block}@font-face{font-family:Bar Roboto;font-weight:500;src:url(./bar-roboto-500-Bn7ZL9yA.woff) format("woff");font-display:block}*{box-sizing:border-box}html,body,#app{height:100%}body{margin:0;background:var(--ground);color:var(--ink);font:13px/1.45 var(--ui-font);-webkit-font-smoothing:antialiased;font-variant-numeric:tabular-nums}button,input,select,textarea{font:inherit;color:inherit}button{background:none;border:0;padding:0;cursor:pointer;border-radius:8px}button:disabled{opacity:.45;cursor:default}button:focus-visible,input:focus-visible,select:focus-visible,textarea:focus-visible,[tabindex]:focus-visible,summary:focus-visible{outline:2px solid var(--accent);outline-offset:2px}input,select,textarea{background:var(--surface);border:1px solid var(--line-strong);border-radius:8px;padding:7px 10px;width:100%;color:var(--ink)}input::placeholder,textarea::placeholder{color:var(--muted)}select{appearance:auto}h1,h2,h3,h4{margin:0;font-weight:600;letter-spacing:-.01em}h1{font-size:20px;letter-spacing:-.02em}h2{font-size:15px}h3,h4{font-size:13px}p{margin:0}small,.hint{display:block;color:var(--muted);font-size:11.5px;font-weight:400;line-height:1.4}.hint.warn,small.warn{color:var(--warn)}code{font-family:var(--mono);font-size:.92em;background:var(--code-bg);padding:1px 6px;border-radius:5px;overflow-wrap:anywhere}pre{margin:0;padding:12px 14px;background:var(--code-bg);border:1px solid var(--line);border-radius:10px;overflow:auto;font:12px/1.5 var(--mono);color:var(--ink);white-space:pre-wrap;overflow-wrap:anywhere}a{color:var(--accent);text-decoration:none}a:hover{text-decoration:underline}.mdi{font-family:Tile Icons;font-style:normal;font-weight:400;line-height:1}[hidden]{display:none!important}.app{display:grid;grid-template-columns:232px minmax(0,1fr);height:100%;min-height:100vh}.app.dragging{user-select:none;-webkit-user-select:none;cursor:grabbing}.main{display:flex;flex-direction:column;min-width:0;min-height:0}.side{background:var(--surface);border-right:1px solid var(--line);display:flex;flex-direction:column;padding:14px 10px;gap:4px;min-height:0;overflow:auto;position:sticky;top:0;height:100vh}.brand{display:flex;align-items:center;gap:9px;padding:4px 8px 6px;font-weight:600;font-size:13px}.brand .mark{width:22px;height:22px;border-radius:6px;background:var(--ink);color:var(--surface);display:grid;place-items:center;font-size:14px;line-height:1}.conn{display:block;padding:0 8px 8px;font-size:11px;color:var(--muted)}.conn:before{content:"●";margin-right:6px;color:var(--warn)}.conn.online:before{color:var(--good)}.side .label{font-size:10.5px;font-weight:600;letter-spacing:.08em;text-transform:uppercase;color:var(--muted);padding:10px 8px 4px}.nav-item{display:flex;align-items:center;gap:9px;width:100%;padding:7px 8px;border-radius:8px;text-align:left;color:var(--ink-2)}.nav-item:hover{background:var(--surface-2);color:var(--ink)}.nav-item[aria-current=true]{background:var(--seg);color:var(--ink);font-weight:500}.nav-item .dot{width:7px;height:7px;border-radius:50%;background:var(--good);flex:none}.nav-item .dot.off{background:var(--line-strong)}.nav-item .txt{display:grid;min-width:0;flex:1}.nav-item .txt small{font-size:11px;color:var(--muted);font-weight:400;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.nav-item .mdi{font-size:16px;width:18px;text-align:center;color:var(--muted)}.nav-item .plus{width:18px;text-align:center;font-size:14px}.nav-item.ghost{color:var(--muted)}.nav-item.ghost:hover{color:var(--accent);background:var(--accent-soft)}.pill{font-size:10.5px;font-weight:600;padding:2px 7px;border-radius:999px;background:var(--warn-soft);color:var(--warn);flex:none}.side .spacer{flex:1}.screen-item{display:grid;gap:4px}.screen-update{display:grid;gap:6px;padding:2px 8px 8px 24px}.screen-update.available{grid-template-columns:1fr auto;align-items:center}.screen-update.available:has(.screen-host){grid-template-columns:1fr}.screen-update small.failed{color:var(--danger)}.screen-host{display:flex;gap:6px;align-items:center}.screen-host input{padding:5px 8px;font-size:12px}.pending{margin:4px 0;padding:10px;border:1px dashed var(--line-strong);border-radius:10px;display:grid;gap:6px}.pending strong{font-size:12.5px}.pending-actions{display:flex;flex-wrap:wrap;gap:6px}.btn{display:inline-flex;align-items:center;justify-content:center;gap:6px;padding:6px 12px;border-radius:8px;font-weight:600;font-size:12.5px;white-space:nowrap}.btn.primary{background:var(--accent);color:var(--accent-ink)}.btn.primary:hover:not(:disabled){filter:brightness(1.06)}.btn.quiet{color:var(--ink-2);border:1px solid var(--line-strong);background:var(--surface)}.btn.quiet:hover:not(:disabled){background:var(--surface-2);color:var(--ink)}.btn.danger{color:var(--danger)}.btn.danger:hover:not(:disabled){background:var(--danger-soft)}.btn.mini{padding:4px 9px;font-size:11.5px}.btn.link{color:var(--accent);padding:0;font-weight:600}.icon-btn{width:30px;height:30px;display:grid;place-items:center;border-radius:8px;color:var(--ink-2);font-size:15px;flex:none}.icon-btn:hover{background:var(--seg);color:var(--ink)}.chip{display:inline-flex;align-items:center;gap:6px;padding:3px 9px;border-radius:999px;font-size:11.5px;font-weight:500;color:var(--ink-2);background:var(--surface-2);border:1px solid var(--line);white-space:nowrap}.chip .dot{width:6px;height:6px;border-radius:50%;background:var(--good);flex:none}.chip.off .dot{background:var(--line-strong)}.chip.dirty{color:var(--warn);background:var(--warn-soft);border-color:transparent}.chip.sent,.chip.good{color:var(--good);background:var(--good-soft);border-color:transparent}.chip.update{color:var(--warn);background:var(--warn-soft);border-color:transparent}.seg{display:inline-flex;padding:2px;background:var(--seg);border-radius:8px;gap:2px}.seg button{padding:4px 11px;border-radius:6px;font-size:12px;font-weight:500;color:var(--ink-2);white-space:nowrap}.seg button[aria-pressed=true]{background:var(--surface);color:var(--ink);box-shadow:0 1px 2px #14182824}.seg.wrap{flex-wrap:wrap}.seg button:hover:not(:disabled):not([aria-pressed=true]){color:var(--ink)}.spin{display:inline-block;width:14px;height:14px;border:2px solid var(--line-strong);border-top-color:var(--accent);border-radius:50%;animation:spin .8s linear infinite;flex:none}.spin.small{width:11px;height:11px;border-width:1.5px}@keyframes spin{to{transform:rotate(360deg)}}.switch{width:34px;height:20px;border-radius:10px;background:var(--line-strong);position:relative;flex:none;padding:0}.switch:after{content:"";position:absolute;top:2px;left:2px;width:16px;height:16px;border-radius:50%;background:#fff;box-shadow:0 1px 2px #0003;transition:left .12s}.switch[aria-checked=true]{background:var(--accent)}.switch[aria-checked=true]:after{left:16px}.switch.unknown:after{left:9px;opacity:.6}@media(prefers-reduced-motion:reduce){.switch:after,.drawer,.spin{transition:none;animation:none}}.main-head{display:flex;align-items:center;gap:12px;padding:0 18px;min-height:52px;border-bottom:1px solid var(--line);background:var(--surface);position:sticky;top:0;z-index:4}.main-head h1{font-size:15px}.main-head .eyebrow{font-size:10.5px;font-weight:600;letter-spacing:.08em;text-transform:uppercase;color:var(--muted)}.head-right{margin-left:auto;display:flex;align-items:center;gap:8px;position:relative}.menu{position:absolute;top:38px;right:0;min-width:210px;background:var(--surface);border:1px solid var(--line);border-radius:10px;box-shadow:var(--shadow);padding:6px;display:grid;z-index:6}.menu button{text-align:left;padding:7px 10px;border-radius:7px;color:var(--ink);display:flex;justify-content:space-between;gap:12px;width:100%}.menu button small{color:var(--muted);display:inline}.menu button:hover:not(:disabled){background:var(--surface-2)}.body{position:relative;display:grid;grid-template-columns:minmax(0,1fr) 300px;flex:1;min-height:0;overflow:hidden}.canvas{overflow:auto;padding:22px 22px 26px;min-width:0}.canvas-head{display:flex;align-items:baseline;gap:12px;margin-bottom:14px;color:var(--muted);font-size:12px;flex-wrap:wrap}.canvas-head b{color:var(--ink);font-weight:600;font-size:13px}.canvas-head .warn{color:var(--warn)}.pages{display:flex;gap:18px;align-items:flex-start}.page{flex:0 0 292px;display:grid;gap:8px}.page-label{display:flex;justify-content:space-between;align-items:center;font-size:11.5px;color:var(--muted);padding:0 4px;min-height:22px}.page-label .btn.mini{color:var(--muted)}.page-label .btn.mini:hover{color:var(--danger);background:var(--danger-soft)}.page.ghost .device{display:grid;place-items:center;border:1.5px dashed var(--line-strong);background:transparent;color:var(--muted);font-weight:500;cursor:pointer}.page.ghost .device:hover,.page.ghost .device:focus-visible{color:var(--accent);border-color:var(--accent)}.page.ghost .device.drop{color:var(--accent);border-color:var(--accent);background:var(--accent-soft)}.page.ghost.disabled .device{opacity:.5;cursor:default}.device{background:#e7e7e7;border-radius:18px;padding:10px;display:grid;grid-template-rows:auto minmax(0,1fr);gap:8px;color:#1b1b1b;aspect-ratio:1 / 1}.device.cyd{aspect-ratio:4 / 3}.bar-wrap{cursor:pointer;border-radius:8px;padding:0 2px}.bar-wrap:hover{background:#dedede}.bar-wrap.selected{outline:2px solid var(--accent);outline-offset:1px}.bar-wrap svg{display:block;width:100%;height:auto}.tiles{display:grid;grid-template-columns:1fr 1fr;grid-auto-rows:minmax(0,1fr);gap:8px;min-height:0}.tile{position:relative;background:#fff;border:1px solid #dcdcdc;border-radius:12px;padding:8px 9px;display:flex;flex-direction:column;justify-content:space-between;gap:4px;min-height:0;cursor:pointer;text-align:left;overflow:hidden;color:#1b1b1b;touch-action:pan-y}.tile:hover{border-color:#b9c4d3}.tile.chosen{outline:2px solid var(--accent);outline-offset:1px}.tile.wide{grid-column:span 2;flex-direction:row;align-items:center;gap:8px}.tile.bare{background:transparent;border-style:dashed;border-color:#c3c9d0}.tile.placeholder{opacity:.55;border:2px dashed var(--accent);background:var(--accent-soft);cursor:default}.tile .ic{font-size:18px;line-height:1;color:#1b1b1b;flex:none}.tile .lead{display:grid;gap:2px;min-width:0;flex:1;align-content:end}.tile.wide .lead{display:flex;align-items:center;gap:8px;align-content:initial}.tile.wide .lead .tx{display:grid;min-width:0;gap:1px}.tile .nm{font-size:11.5px;font-weight:600;line-height:1.2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.tile .st{font-size:10.5px;color:#5a5f66;line-height:1.2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.device.cyd .tile{padding:6px 7px}.device.cyd .tile .nm{font-size:10.5px}.device.cyd .tile .ic{font-size:15px}.tile .mini-slider{height:10px;border-radius:5px;background:linear-gradient(to right,#ffbf38 60%,#fff1d3 60%);flex:none;width:100%}.tile.wide .mini-slider{width:70px}.tile .ctl{flex:none;display:flex;align-items:center;gap:4px;color:#1b1b1b}.tile .tog{width:30px;height:17px;border-radius:9px;background:#2196f3;position:relative}.tile .tog:after{content:"";position:absolute;top:2px;right:2px;width:13px;height:13px;border-radius:50%;background:#fff}.tile .range{width:56px;height:14px;border-radius:7px;background:linear-gradient(to right,#2196f3 35%,#d3e8fb 35%)}.tile .key{height:20px;min-width:22px;padding:0 5px;border-radius:6px;background:#eceef1;display:grid;place-items:center;font-size:12px}.tile .stp{display:flex;align-items:center;gap:5px;height:20px;padding:0 7px;border-radius:10px;background:#eceef1;font-size:11px;font-weight:600}.tile .stp .mdi{font-size:12px}.tile .run{height:20px;padding:0 9px;border-radius:10px;background:#eceef1;font-size:11px;font-weight:600;line-height:20px}.tile .remove{position:absolute;top:5px;right:5px;width:22px;height:22px;border-radius:50%;background:#ffffffd9;color:#5a5f66;border:1px solid #dcdcdc;font-size:10px;line-height:1;display:grid;place-items:center;opacity:0;transition:opacity .12s}.tile:hover .remove,.tile:focus-within .remove{opacity:1}.tile .remove:hover{color:var(--danger);border-color:#e7b4b0;background:#fff}@media(hover:none){.tile .remove{opacity:1}}.tile .clockface{width:46px;height:46px;margin:auto}.tile.wide .clockface{margin:0;flex:none}.cell{min-height:0;border:1px dashed #cfd4da;border-radius:12px;background:transparent;color:#a3abb5;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:1px;font-weight:500;cursor:pointer;padding:6px}.cell span{font-size:18px;line-height:1}.cell small{font-size:10.5px;color:inherit}.cell:hover,.cell:focus-visible{border-color:#9eb6cf;color:#4b5563;background:#f6f7f9}.cell.insert-here{border:2px dashed var(--accent);color:var(--accent);background:var(--accent-soft)}.drag-ghost{position:fixed;left:0;top:0;pointer-events:none;z-index:50;opacity:.92;box-shadow:var(--shadow);border-radius:12px}.library{border-left:1px solid var(--line);background:var(--surface);display:flex;flex-direction:column;min-height:0}.lib-head{padding:14px 14px 10px;display:grid;gap:10px;border-bottom:1px solid var(--line)}.lib-title{display:flex;align-items:baseline;justify-content:space-between;font-weight:600;gap:8px}.lib-title small{color:var(--muted);font-weight:400;font-size:11.5px}.filters{display:flex;gap:6px;overflow-x:auto;scrollbar-width:none;padding-bottom:2px}.filters::-webkit-scrollbar{display:none}.filters button{flex:none;display:inline-flex;align-items:center;gap:5px;padding:4px 10px;border-radius:999px;font-size:11.5px;font-weight:500;color:var(--ink-2);background:var(--surface-2);border:1px solid var(--line)}.filters button[aria-pressed=true]{background:var(--ink);color:var(--surface);border-color:var(--ink)}.filters .domain-icon{width:16px;height:16px;font-size:11px;border-radius:50%;display:grid;place-items:center}.lib-list{overflow:auto;padding:8px;display:grid;gap:2px;align-content:start;flex:1}.ent{display:flex;align-items:center;gap:10px;padding:8px;border-radius:9px;width:100%;text-align:left;cursor:grab;touch-action:pan-y}.ent:hover:not(:disabled){background:var(--surface-2)}.ent:disabled{opacity:.55;cursor:default}.ent .av{width:30px;height:30px;border-radius:9px;display:grid;place-items:center;font-size:17px;flex:none}.ent .tx{display:grid;min-width:0;flex:1}.ent .tx b{font-weight:500;font-size:12.5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ent .tx small{font-size:11px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ent .add{width:24px;height:24px;border-radius:50%;display:grid;place-items:center;color:var(--accent);background:var(--accent-soft);font-size:15px;font-weight:600;flex:none}.ent .add.done{color:var(--good);background:var(--good-soft);font-size:12px}.lib-foot{padding:10px 14px;border-top:1px solid var(--line);font-size:11.5px;color:var(--muted)}.domain-icon{display:inline-grid;place-items:center;border-radius:50%;font-weight:500}.drawer{position:absolute;top:0;right:0;bottom:0;width:360px;max-width:100%;background:var(--surface);border-left:1px solid var(--line);box-shadow:var(--shadow);transform:translate(102%);transition:transform .18s cubic-bezier(.2,.7,.2,1);display:flex;flex-direction:column;min-height:0;z-index:5}.drawer.open{transform:none}.dr-head{display:flex;align-items:center;gap:10px;padding:12px 12px 12px 16px;border-bottom:1px solid var(--line)}.dr-head .av{width:34px;height:34px;border-radius:10px;display:grid;place-items:center;font-size:20px;flex:none}.dr-head .tx{flex:1;min-width:0;display:grid}.dr-head .tx b{font-weight:600;font-size:14px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.dr-head .tx small{color:var(--muted);font-size:11.5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.dr-head .tx small.mono{font-family:var(--mono)}.dr-body{overflow:auto;padding:14px 16px 18px;display:grid;gap:16px;align-content:start;flex:1}.f{display:grid;gap:7px}.f>.f-label{font-size:11px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;color:var(--muted)}.f input,.f select{font-size:13px}.row{display:flex;align-items:center;gap:10px;padding:7px 10px 7px 8px;border:1px solid var(--line-strong);border-radius:9px;background:var(--surface);width:100%;text-align:left}.row .av{width:30px;height:30px;border-radius:8px;background:var(--surface-2);display:grid;place-items:center;font-size:18px;flex:none}.row .tx{flex:1;min-width:0;display:grid}.row .tx b{font-weight:500}.row .tx small{font-size:11px}.row .link{color:var(--accent);font-weight:600;font-size:12px;flex:none}.sw{display:grid;grid-template-columns:repeat(4,1fr);gap:6px}.sw button{display:grid;justify-items:center;gap:4px;padding:6px 4px 5px;border-radius:9px;border:1.5px solid transparent;font-size:10.5px;color:var(--ink-2)}.sw button i{width:30px;height:22px;border-radius:6px;border:1px solid rgba(0,0,0,.08);display:block}.sw button i.auto{background:linear-gradient(135deg,#fff 50%,#e5e7eb 50%)}.sw button i.none{background:linear-gradient(135deg,transparent 46%,#8b95a1 46%,#8b95a1 54%,transparent 54%),#e7e7e7;border-style:dashed}.sw button[aria-pressed=true]{border-color:var(--accent);background:var(--accent-soft);color:var(--ink)}.picker{display:grid;gap:10px;padding:10px;border:1px solid var(--line);border-radius:10px;background:var(--surface-2)}.picker input{background:var(--surface)}.icon-list{display:grid;gap:12px;max-height:300px;overflow:auto;padding-right:2px}.icon-list small{margin-bottom:6px}.icon-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(40px,1fr));gap:6px}.icon-choice{display:grid;place-items:center;height:40px;background:var(--surface);color:var(--ink);border:1px solid var(--line);border-radius:9px}.icon-choice .mdi{font-size:22px}.icon-choice[aria-pressed=true]{background:var(--accent-soft);color:var(--accent);border-color:var(--accent)}.icon-choice.icon-auto{display:flex;justify-content:flex-start;gap:10px;padding:0 12px;font-size:12.5px;font-weight:500;height:38px}.action-list{display:grid;gap:6px;max-height:300px;overflow:auto;padding-right:2px}.action-choice{display:grid;gap:2px;padding:8px 12px;background:var(--surface);color:var(--ink);border:1px solid var(--line);border-radius:9px;font-size:12.5px;text-align:left}.action-choice strong{font-weight:600}.action-choice[aria-pressed=true]{background:var(--accent-soft);border-color:var(--accent)}.action-number{display:flex;align-items:center;gap:8px}.action-number input{flex:1;min-width:0}.items{display:grid;gap:6px}.item{display:flex;align-items:center;gap:8px;padding:7px 8px;border:1px solid var(--line-strong);border-radius:9px;background:var(--surface);width:100%;text-align:left;cursor:pointer;touch-action:pan-y}.item:hover{border-color:var(--accent)}.item.selected{border-color:var(--accent);background:var(--accent-soft)}.item.is-hidden{border-style:dashed}.item.is-hidden .av,.item.is-hidden b{opacity:.55}.item.is-overflow{border-style:dashed;border-color:var(--warn)}.item.is-overflow small{color:var(--warn)}.item.dragging-chip{border:2px dashed var(--accent);background:var(--accent-soft);cursor:grabbing}.item.just-added{animation:chip-added 1.2s ease-out}@keyframes chip-added{0%{background:var(--accent-soft)}to{background:var(--surface)}}.item .grip{color:var(--line-strong);font-size:13px;cursor:grab;letter-spacing:-2px;flex:none}.item .av{width:26px;height:26px;border-radius:7px;background:var(--surface-2);display:grid;place-items:center;font-size:15px;flex:none}.item .tx{flex:1;min-width:0;display:grid}.item .tx b{font-weight:500;font-size:12.5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.item .tx small{color:var(--muted);font-size:11px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.item .x{color:var(--muted);width:22px;height:22px;display:grid;place-items:center;border-radius:6px;flex:none;font-size:11px}.item .x:hover{color:var(--danger);background:var(--danger-soft)}.ghost-btn{border:1.5px dashed var(--line-strong);border-radius:9px;padding:8px;color:var(--accent);font-weight:600;width:100%;background:transparent}.ghost-btn:hover:not(:disabled){border-color:var(--accent);background:var(--accent-soft)}.dr-foot{margin-top:auto;display:flex;align-items:center;gap:8px;padding:10px 12px;border-top:1px solid var(--line);background:var(--surface-2);flex-wrap:wrap}.dr-foot .spacer{flex:1}.live{display:grid;gap:6px;padding:10px;border:1px solid var(--line);border-radius:10px;background:#e7e7e7;color:#1b1b1b;justify-items:start}.live small{color:#5a5f66}.live svg{display:block;height:28px}.option{display:flex;align-items:center;gap:10px;padding:8px 10px;border:1px solid var(--line);border-radius:9px;background:var(--surface);width:100%;text-align:left}.option:hover:not(:disabled){border-color:var(--accent)}.option .mdi{font-size:20px;width:26px;text-align:center;color:var(--ink-2);flex:none}.option .tx{display:grid;min-width:0}.option .tx strong{font-weight:500;font-size:12.5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.option .tx small{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.options{display:grid;gap:6px}.inspection-tile{display:grid;gap:3px;padding:8px 10px;border:1px solid var(--line);border-radius:9px;margin-bottom:6px}.inspection-tile strong{font-size:12.5px}.settings{padding:22px;overflow:auto;display:grid;gap:14px;align-content:start;grid-column:1 / -1}.settings .status{font-size:12px;color:var(--muted)}.set-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));gap:14px}.set-card{background:var(--surface);border:1px solid var(--line);border-radius:12px;padding:6px 14px 8px}.set-card h4{display:flex;align-items:center;gap:8px;padding:10px 0 8px}.set-card h4 .mdi{color:var(--muted);font-size:16px}.srow{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:8px 0;border-top:1px solid var(--line)}.srow>.s-label{color:var(--ink-2)}.srow.inactive .s-label,.srow.inactive .s-control{opacity:.45}.settings.offline .set-grid{opacity:.6}.step{display:inline-flex;align-items:center;gap:2px}.step button{width:26px;height:26px;border-radius:6px;color:var(--ink-2);background:var(--seg);display:grid;place-items:center}.step button .mdi{font-size:15px}.step button:hover:not(:disabled){color:var(--ink);background:var(--line-strong)}.step output{min-width:56px;text-align:center;font-weight:500}.panel{padding:22px 26px 40px;overflow:auto;display:grid;gap:18px;align-content:start;max-width:960px;width:100%}.panel.wide{max-width:1120px}.panel-head{display:flex;align-items:flex-start;gap:12px}.panel-head .tx{display:grid;gap:2px;flex:1;min-width:0}.panel-head h1{font-size:20px}.panel-head p{color:var(--muted);font-size:13px}.panel p,.panel li{color:var(--ink-2);font-size:13px}.card{background:var(--surface);border:1px solid var(--line);border-radius:12px;padding:16px 18px;display:grid;gap:12px;align-content:start}.card h2{font-size:14px}.card-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:14px}.field{display:grid;gap:6px}.field>.f-label,fieldset legend{font-size:11px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;color:var(--muted)}fieldset{border:0;padding:0;margin:0;display:grid;gap:8px;min-width:0}fieldset:disabled{opacity:.6}.boards{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:8px}.board{display:flex;align-items:center;gap:10px;padding:10px 12px;border:1px solid var(--line-strong);border-radius:10px;cursor:pointer}.board:has(input:checked){border-color:var(--accent);background:var(--accent-soft)}.board input{width:auto;margin:0;accent-color:var(--accent)}.board b{display:block;font-weight:600}.actions{display:flex;align-items:center;gap:8px;flex-wrap:wrap}.status-line{font-size:12.5px;color:var(--ink-2)}.status-line.ok{color:var(--good)}.status-line.error{color:var(--danger)}.progress-head{display:flex;align-items:center;gap:10px;font-weight:600;font-size:14px}.outcome{width:22px;height:22px;border-radius:50%;display:grid;place-items:center;color:#fff;font-size:12px;font-weight:700}.outcome.ok{background:var(--good)}.outcome.bad{background:var(--danger)}.steps{margin:0;padding-left:20px;display:grid;gap:8px}.steps li b{color:var(--ink)}.key-box{display:flex;align-items:center;gap:10px;padding:10px 12px;border:1px solid var(--line);border-radius:10px;background:var(--surface-2);flex-wrap:wrap}.key-box code{flex:1;min-width:0;background:none;padding:0;font-size:12px}.log{max-height:320px}details.log-wrap summary{cursor:pointer;font-weight:500;color:var(--ink-2);font-size:12.5px}details.log-wrap pre{margin-top:8px}.check{display:flex;align-items:flex-start;gap:10px;cursor:pointer}.check input{width:18px;height:18px;margin:1px 0 0;accent-color:var(--accent)}.check span{display:grid;gap:2px;font-weight:500}.node-line{display:flex;align-items:center;gap:6px;flex-wrap:wrap}.tools{display:flex;gap:10px;flex-wrap:wrap}.tool{display:flex;align-items:center;gap:10px;padding:10px 12px;border:1px solid var(--line);border-radius:10px;background:var(--surface);text-align:left;min-width:220px}.tool:hover{border-color:var(--accent)}.tool .tool-icon{width:30px;height:30px;border-radius:8px;background:var(--seg);display:grid;place-items:center;font-size:15px;color:var(--ink-2);flex:none}.tool .tx{display:grid}.tool .tx b{font-weight:600}.yaml-editor{display:grid;grid-template-columns:44px minmax(0,1fr);border:1px solid var(--line-strong);border-radius:10px;overflow:hidden;background:var(--code-bg);min-height:280px;max-height:60vh}.yaml-gutter{padding:12px 8px;text-align:right;color:var(--muted);font:12px/1.5 var(--mono);white-space:pre;user-select:none;overflow:hidden;border-right:1px solid var(--line)}.yaml-editor textarea{border:0;border-radius:0;background:transparent;resize:none;font:12px/1.5 var(--mono);padding:12px;white-space:pre;overflow:auto;min-height:280px;tab-size:2}.file-row{display:flex;align-items:center;gap:10px;flex-wrap:wrap}.file-row code{font-size:12px}.notice{display:flex;gap:12px;padding:12px 14px;border:1px solid var(--line);border-radius:10px;background:var(--surface-2)}.notice .mdi{font-size:20px;color:var(--ink-2)}.notice strong{display:block;font-weight:600;margin-bottom:2px}.alerts section{display:grid;gap:10px}.alerts h2{font-size:15px}.alerts-nav{display:flex;flex-wrap:wrap;gap:6px}.alerts-nav button{background:var(--accent-soft);color:var(--accent);padding:5px 11px;font-size:12px;border-radius:20px;font-weight:500}.alert-hero{display:grid;grid-template-columns:minmax(0,300px) 1fr;gap:20px;align-items:center}.alert-mock{background:#101820;border-radius:16px;padding:22px 18px;display:grid;place-items:center}.alert-mock-card{position:relative;width:100%;background:#ffe1c6;border:1px solid #0001;border-radius:14px;padding:12px 12px 48px 52px;color:#1b1b1b;display:grid;gap:2px}.alert-mock-icon{position:absolute;left:12px;top:12px;font-size:30px}.alert-mock-card strong{font-size:15px;line-height:1.2}.alert-mock-card>span{font-size:12px;color:#3a3a3c}.alert-mock-card .fake{position:absolute;right:10px;bottom:10px;padding:6px 16px;border-radius:999px;background:#1b1b1b;color:#fff;font-size:13px}.alert-screen{border:1px solid var(--line);border-radius:10px;padding:10px 12px;display:grid;gap:8px;background:var(--surface)}.alert-screen-head{display:flex;align-items:center;justify-content:space-between;gap:10px;flex-wrap:wrap}.copy-line{display:flex;align-items:flex-start;gap:8px;flex-wrap:wrap}.copy-line .copy-label{flex:none;width:96px;font-size:12px;color:var(--muted);padding-top:2px}.copy-line>code{flex:1;min-width:0;padding:4px 8px}.copy-line pre{flex:1;min-width:0}.table-scroll{overflow-x:auto}table{width:100%;border-collapse:collapse;font-size:12.5px;min-width:560px}th,td{text-align:left;vertical-align:top;padding:8px 12px 8px 0;border-bottom:1px solid var(--line)}th{font-size:10.5px;letter-spacing:.08em;text-transform:uppercase;color:var(--muted);font-weight:600}td code{white-space:nowrap}.chips{display:flex;flex-wrap:wrap;gap:6px}.chips .chip .mdi{font-size:16px}.chips .chip code{background:none;padding:0}.alert-icon-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(100px,1fr));gap:8px}.alert-icon{display:grid;justify-items:center;align-content:start;gap:4px;min-height:86px;padding:10px 6px 8px;background:var(--surface);color:var(--ink);border:1px solid var(--line);border-radius:10px;font-weight:500}.alert-icon:hover{border-color:var(--accent)}.alert-icon .mdi{font-size:26px}.alert-icon code{background:none;padding:0;font-size:11px;color:var(--accent);text-align:center;white-space:normal}.alert-icon small{font-size:11px;text-align:center}.swatches{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:8px}.swatch{display:flex;align-items:center;gap:10px;padding:7px;border:1px solid var(--line);border-radius:10px;background:var(--surface);color:var(--ink);font-size:12px;text-align:left;font-weight:500}.swatch:hover{border-color:var(--accent)}.swatch i{width:32px;height:32px;border-radius:8px;border:1px solid #0001;flex:none;display:block}.swatch span{display:grid;gap:2px;min-width:0}.swatch code{background:none;padding:0}.alerts-list{padding-left:18px;margin:0;display:grid;gap:8px}.alerts-list b{color:var(--ink)}.subhead{font-size:11px;font-weight:600;letter-spacing:.08em;text-transform:uppercase;color:var(--muted);margin-top:6px}.empty{margin:auto;max-width:420px;text-align:center;display:grid;gap:10px;justify-items:center;padding:60px 20px}.empty-icon{width:48px;height:48px;border-radius:14px;background:var(--seg);color:var(--muted);display:grid;place-items:center;font-size:26px}.empty h2{font-size:18px}.empty p{color:var(--muted)}.toast{position:fixed;left:50%;bottom:20px;transform:translate(-50%);display:flex;align-items:center;gap:14px;padding:10px 16px;background:var(--ink);color:var(--surface);border-radius:10px;box-shadow:var(--shadow);font-size:13px;z-index:60;max-width:min(92vw,560px)}.toast button{color:#9fc4ff;font-weight:650}@media(max-width:960px){.app{grid-template-columns:1fr;min-height:100vh}.side{position:static;height:auto;flex-direction:row;flex-wrap:wrap;align-items:center;border-right:0;border-bottom:1px solid var(--line);padding:10px;gap:4px 6px}.side .label,.side .spacer,.conn{display:none}.side #screens,.screen-item{display:contents}.screen-update{display:none}.side #pending{flex-basis:100%}.nav-item{width:auto}.more{display:contents}.main-head{flex-wrap:wrap;padding:10px 14px;gap:8px;position:static}.head-right{margin-left:0;width:100%}.body{grid-template-columns:1fr;overflow:visible}.canvas{padding:16px;overflow:visible}.pages{overflow-x:auto;padding-bottom:8px}.library{border-left:0;border-top:1px solid var(--line)}.lib-list{flex:none;max-height:360px}.drawer{position:fixed;top:0;width:100%}.panel{padding:16px}.alert-hero{grid-template-columns:1fr}} diff --git a/screen_manager/app/static/assets/index-DOjlT4hj.js b/screen_manager/app/static/assets/index-DOjlT4hj.js deleted file mode 100644 index 7d5bc61..0000000 --- a/screen_manager/app/static/assets/index-DOjlT4hj.js +++ /dev/null @@ -1,27 +0,0 @@ -(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const o of document.querySelectorAll('link[rel="modulepreload"]'))s(o);new MutationObserver(o=>{for(const l of o)if(l.type==="childList")for(const r of l.addedNodes)r.tagName==="LINK"&&r.rel==="modulepreload"&&s(r)}).observe(document,{childList:!0,subtree:!0});function n(o){const l={};return o.integrity&&(l.integrity=o.integrity),o.referrerPolicy&&(l.referrerPolicy=o.referrerPolicy),o.crossOrigin==="use-credentials"?l.credentials="include":o.crossOrigin==="anonymous"?l.credentials="omit":l.credentials="same-origin",l}function s(o){if(o.ep)return;o.ep=!0;const l=n(o);fetch(o.href,l)}})();function So(e){const t=Object.create(null);for(const n of e.split(","))t[n]=1;return n=>n in t}const be={},en=[],mt=()=>{},Yi=()=>!1,As=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&(e.charCodeAt(2)>122||e.charCodeAt(2)<97),Es=e=>e.startsWith("onUpdate:"),Oe=Object.assign,Co=(e,t)=>{const n=e.indexOf(t);n>-1&&e.splice(n,1)},ga=Object.prototype.hasOwnProperty,ve=(e,t)=>ga.call(e,t),ee=Array.isArray,Vt=e=>Gn(e)==="[object Map]",sn=e=>Gn(e)==="[object Set]",ei=e=>Gn(e)==="[object Date]",ne=e=>typeof e=="function",xe=e=>typeof e=="string",gt=e=>typeof e=="symbol",ge=e=>e!==null&&typeof e=="object",zi=e=>(ge(e)||ne(e))&&ne(e.then)&&ne(e.catch),Gi=Object.prototype.toString,Gn=e=>Gi.call(e),ya=e=>Gn(e).slice(8,-1),Ji=e=>Gn(e)==="[object Object]",To=e=>xe(e)&&e!=="NaN"&&e[0]!=="-"&&""+parseInt(e,10)===e,En=So(",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted"),Ps=e=>{const t=Object.create(null);return(n=>t[n]||(t[n]=e(n)))},ba=/-\w/g,Be=Ps(e=>e.replace(ba,t=>t.slice(1).toUpperCase())),wa=/\B([A-Z])/g,Yt=Ps(e=>e.replace(wa,"-$1").toLowerCase()),Os=Ps(e=>e.charAt(0).toUpperCase()+e.slice(1)),Us=Ps(e=>e?`on${Os(e)}`:""),ht=(e,t)=>!Object.is(e,t),rs=(e,...t)=>{for(let n=0;n{Object.defineProperty(e,t,{configurable:!0,enumerable:!1,writable:s,value:n})},Is=e=>{const t=parseFloat(e);return isNaN(t)?e:t};let ti;const Ms=()=>ti||(ti=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{});function Ne(e){if(ee(e)){const t={};for(let n=0;nn.startsWith("/*")?"":n).split(_a).forEach(n=>{if(n){const s=n.split(ka);s.length>1&&(t[s[0].trim()]=s[1].trim())}}),t}function re(e){let t="";if(xe(e))t=e;else if(ee(e))for(let n=0;nyt(n,t))}const Zi=e=>!!(e&&e.__v_isRef===!0),y=e=>xe(e)?e:e==null?"":ee(e)||ge(e)&&(e.toString===Gi||!ne(e.toString))?Zi(e)?y(e.value):JSON.stringify(e,el,2):String(e),el=(e,t)=>Zi(t)?el(e,t.value):Vt(t)?{[`Map(${t.size})`]:[...t.entries()].reduce((n,[s,o],l)=>(n[Vs(s,l)+" =>"]=o,n),{})}:sn(t)?{[`Set(${t.size})`]:[...t.values()].map(n=>Vs(n))}:gt(t)?Vs(t):ge(t)&&!ee(t)&&!Ji(t)?String(t):t,Vs=(e,t="")=>{var n;return gt(e)?`Symbol(${(n=e.description)!=null?n:t})`:e};let Pe;class Pa{constructor(t=!1){this.detached=t,this._active=!0,this._on=0,this.effects=[],this.cleanups=[],this._isPaused=!1,this._warnOnRun=!0,this.__v_skip=!0,!t&&Pe&&(Pe.active?(this.parent=Pe,this.index=(Pe.scopes||(Pe.scopes=[])).push(this)-1):(this._active=!1,this._warnOnRun=!1))}get active(){return this._active}pause(){if(this._active){this._isPaused=!0;let t,n;if(this.scopes){const s=this.scopes.slice();for(t=0,n=s.length;t0&&--this._on===0){if(Pe===this)Pe=this.prevScope;else{let t=Pe;for(;t;){if(t.prevScope===this){t.prevScope=this.prevScope;break}t=t.prevScope}}this.prevScope=void 0}}stop(t){if(this._active){this._active=!1;let n,s;for(n=0,s=this.effects.length;n0)return;if(On){let t=On;for(On=void 0;t;){const n=t.next;t.next=void 0,t.flags&=-9,t=n}}let e;for(;Pn;){let t=Pn;for(Pn=void 0;t;){const n=t.next;if(t.next=void 0,t.flags&=-9,t.flags&1)try{t.trigger()}catch(s){e||(e=s)}t=n}}if(e)throw e}function ol(e){for(let t=e.deps;t;t=t.nextDep)t.version=-1,t.prevActiveLink=t.dep.activeLink,t.dep.activeLink=t}function il(e){let t,n=e.depsTail,s=n;for(;s;){const o=s.prevDep;s.version===-1?(s===n&&(n=o),Po(s),Ia(s)):t=s,s.dep.activeLink=s.prevActiveLink,s.prevActiveLink=void 0,s=o}e.deps=t,e.depsTail=n}function io(e){for(let t=e.deps;t;t=t.nextDep)if(t.dep.version!==t.version||t.dep.computed&&(ll(t.dep.computed)||t.dep.version!==t.version))return!0;return!!e._dirty}function ll(e){if(e.flags&4&&!(e.flags&16)||(e.flags&=-17,e.globalVersion===Rn)||(e.globalVersion=Rn,!e.isSSR&&e.flags&128&&(!e.deps&&!e._dirty||!io(e))))return;e.flags|=2;const t=e.dep,n=we,s=st;we=e,st=!0;try{ol(e);const o=e.fn(e._value);(t.version===0||ht(o,e._value))&&(e.flags|=128,e._value=o,t.version++)}catch(o){throw t.version++,o}finally{we=n,st=s,il(e),e.flags&=-3}}function Po(e,t=!1){const{dep:n,prevSub:s,nextSub:o}=e;if(s&&(s.nextSub=o,e.prevSub=void 0),o&&(o.prevSub=s,e.nextSub=void 0),n.subs===e&&(n.subs=s,!s&&n.computed)){n.computed.flags&=-5;for(let l=n.computed.deps;l;l=l.nextDep)Po(l,!0)}!t&&!--n.sc&&n.map&&n.map.delete(n.key)}function Ia(e){const{prevDep:t,nextDep:n}=e;t&&(t.nextDep=n,e.prevDep=void 0),n&&(n.prevDep=t,e.nextDep=void 0)}let st=!0;const al=[];function Pt(){al.push(st),st=!1}function Ot(){const e=al.pop();st=e===void 0?!0:e}function oi(e){const{cleanup:t}=e;if(e.cleanup=void 0,t){const n=we;we=void 0;try{t()}finally{we=n}}}let Rn=0;class Ma{constructor(t,n){this.sub=t,this.dep=n,this.version=n.version,this.nextDep=this.prevDep=this.nextSub=this.prevSub=this.prevActiveLink=void 0}}class Oo{constructor(t){this.computed=t,this.version=0,this.activeLink=void 0,this.subs=void 0,this.map=void 0,this.key=void 0,this.sc=0,this.__v_skip=!0}track(t){if(!we||!st||we===this.computed)return;let n=this.activeLink;if(n===void 0||n.sub!==we)n=this.activeLink=new Ma(we,this),we.deps?(n.prevDep=we.depsTail,we.depsTail.nextDep=n,we.depsTail=n):we.deps=we.depsTail=n,rl(n);else if(n.version===-1&&(n.version=this.version,n.nextDep)){const s=n.nextDep;s.prevDep=n.prevDep,n.prevDep&&(n.prevDep.nextDep=s),n.prevDep=we.depsTail,n.nextDep=void 0,we.depsTail.nextDep=n,we.depsTail=n,we.deps===n&&(we.deps=s)}return n}trigger(t){this.version++,Rn++,this.notify(t)}notify(t){Ao();try{for(let n=this.subs;n;n=n.prevSub)n.sub.notify()&&n.sub.dep.notify()}finally{Eo()}}}function rl(e){if(e.dep.sc++,e.sub.flags&4){const t=e.dep.computed;if(t&&!e.dep.subs){t.flags|=20;for(let s=t.deps;s;s=s.nextDep)rl(s)}const n=e.dep.subs;n!==e&&(e.prevSub=n,n&&(n.nextSub=e)),e.dep.subs=e}}const lo=new WeakMap,tn=Symbol(""),ao=Symbol(""),Nn=Symbol("");function Ie(e,t,n){if(st&&we){let s=lo.get(e);s||lo.set(e,s=new Map);let o=s.get(n);o||(s.set(n,o=new Oo),o.map=s,o.key=n),o.track()}}function Tt(e,t,n,s,o,l){const r=lo.get(e);if(!r){Rn++;return}const u=a=>{a&&a.trigger()};if(Ao(),t==="clear")r.forEach(u);else{const a=ee(e),c=a&&To(n);if(a&&n==="length"){const f=Number(s);r.forEach((b,A)=>{(A==="length"||A===Nn||!gt(A)&&A>=f)&&u(b)})}else switch((n!==void 0||r.has(void 0))&&u(r.get(n)),c&&u(r.get(Nn)),t){case"add":a?c&&u(r.get("length")):(u(r.get(tn)),Vt(e)&&u(r.get(ao)));break;case"delete":a||(u(r.get(tn)),Vt(e)&&u(r.get(ao)));break;case"set":Vt(e)&&u(r.get(tn));break}}Eo()}function rn(e){const t=he(e);return t===e||(Ie(t,"iterate",Nn),Xe(e))?t:bt(e)?Wt(e)?t.map(n=>Kt(Ze(n))):t.map(Kt):t.map(Ze)}function Ds(e){return Ie(e=he(e),"iterate",Nn),e}function ft(e,t){return bt(e)?Kt(Wt(e)?Ze(t):t):Ze(t)}const Da={__proto__:null,[Symbol.iterator](){return Ks(this,Symbol.iterator,e=>ft(this,e))},concat(...e){return rn(this).concat(...e.map(t=>ee(t)?rn(t):t))},entries(){return Ks(this,"entries",e=>(e[1]=ft(this,e[1]),e))},every(e,t){return kt(this,"every",e,t,void 0,arguments)},filter(e,t){return kt(this,"filter",e,t,n=>n.map(s=>ft(this,s)),arguments)},find(e,t){return kt(this,"find",e,t,n=>ft(this,n),arguments)},findIndex(e,t){return kt(this,"findIndex",e,t,void 0,arguments)},findLast(e,t){return kt(this,"findLast",e,t,n=>ft(this,n),arguments)},findLastIndex(e,t){return kt(this,"findLastIndex",e,t,void 0,arguments)},forEach(e,t){return kt(this,"forEach",e,t,void 0,arguments)},includes(...e){return qs(this,"includes",e)},indexOf(...e){return qs(this,"indexOf",e)},join(e){return rn(this).join(e)},lastIndexOf(...e){return qs(this,"lastIndexOf",e)},map(e,t){return kt(this,"map",e,t,void 0,arguments)},pop(){return kn(this,"pop")},push(...e){return kn(this,"push",e)},reduce(e,...t){return ii(this,"reduce",e,t)},reduceRight(e,...t){return ii(this,"reduceRight",e,t)},shift(){return kn(this,"shift")},some(e,t){return kt(this,"some",e,t,void 0,arguments)},splice(...e){return kn(this,"splice",e)},toReversed(){return rn(this).toReversed()},toSorted(e){return rn(this).toSorted(e)},toSpliced(...e){return rn(this).toSpliced(...e)},unshift(...e){return kn(this,"unshift",e)},values(){return Ks(this,"values",e=>ft(this,e))}};function Ks(e,t,n){const s=Ds(e),o=s[t]();return s!==e&&!Xe(e)&&(o._next=o.next,o.next=()=>{const l=o._next();return l.done||(l.value=n(l.value)),l}),o}const La=Array.prototype;function kt(e,t,n,s,o,l){const r=Ds(e),u=r!==e&&!Xe(e),a=r[t];if(a!==La[t]){const b=a.apply(e,l);return u?Ze(b):b}let c=n;r!==e&&(u?c=function(b,A){return n.call(this,ft(e,b),A,e)}:n.length>2&&(c=function(b,A){return n.call(this,b,A,e)}));const f=a.call(r,c,s);return u&&o?o(f):f}function ii(e,t,n,s){const o=Ds(e),l=o!==e&&!Xe(e);let r=n,u=!1;o!==e&&(l?(u=s.length===0,r=function(c,f,b){return u&&(u=!1,c=ft(e,c)),n.call(this,c,ft(e,f),b,e)}):n.length>3&&(r=function(c,f,b){return n.call(this,c,f,b,e)}));const a=o[t](r,...s);return u?ft(e,a):a}function qs(e,t,n){const s=he(e);Ie(s,"iterate",Nn);const o=s[t](...n);return(o===-1||o===!1)&&Do(n[0])?(n[0]=he(n[0]),s[t](...n)):o}function kn(e,t,n=[]){Pt(),Ao();const s=he(e)[t].apply(e,n);return Eo(),Ot(),s}const Fa=So("__proto__,__v_isRef,__isVue"),ul=new Set(Object.getOwnPropertyNames(Symbol).filter(e=>e!=="arguments"&&e!=="caller").map(e=>Symbol[e]).filter(gt));function Ha(e){gt(e)||(e=String(e));const t=he(this);return Ie(t,"has",e),t.hasOwnProperty(e)}class cl{constructor(t=!1,n=!1){this._isReadonly=t,this._isShallow=n}get(t,n,s){if(n==="__v_skip")return t.__v_skip;const o=this._isReadonly,l=this._isShallow;if(n==="__v_isReactive")return!o;if(n==="__v_isReadonly")return o;if(n==="__v_isShallow")return l;if(n==="__v_raw")return s===(o?l?Ya:hl:l?pl:fl).get(t)||Object.getPrototypeOf(t)===Object.getPrototypeOf(s)?t:void 0;const r=ee(t);if(!o){let a;if(r&&(a=Da[n]))return a;if(n==="hasOwnProperty")return Ha}const u=Reflect.get(t,n,Le(t)?t:s);if((gt(n)?ul.has(n):Fa(n))||(o||Ie(t,"get",n),l))return u;if(Le(u)){const a=r&&To(n)?u:u.value;return o&&ge(a)?uo(a):a}return ge(u)?o?uo(u):hn(u):u}}class dl extends cl{constructor(t=!1){super(!1,t)}set(t,n,s,o){let l=t[n];const r=ee(t)&&To(n);if(!this._isShallow){const c=bt(l);if(!Xe(s)&&!bt(s)&&(l=he(l),s=he(s)),!r&&Le(l)&&!Le(s))return c||(l.value=s),!0}const u=r?Number(n)e,ss=e=>Reflect.getPrototypeOf(e);function Ua(e,t,n){return function(...s){const o=this.__v_raw,l=he(o),r=Vt(l),u=e==="entries"||e===Symbol.iterator&&r,a=e==="keys"&&r,c=o[e](...s),f=n?ro:t?Kt:Ze;return!t&&Ie(l,"iterate",a?ao:tn),Oe(Object.create(c),{next(){const{value:b,done:A}=c.next();return A?{value:b,done:A}:{value:u?[f(b[0]),f(b[1])]:f(b),done:A}}})}}function os(e){return function(...t){return e==="delete"?!1:e==="clear"?void 0:this}}function Va(e,t){const n={get(o){const l=this.__v_raw,r=he(l),u=he(o);e||(ht(o,u)&&Ie(r,"get",o),Ie(r,"get",u));const{has:a}=ss(r),c=t?ro:e?Kt:Ze;if(a.call(r,o))return c(l.get(o));if(a.call(r,u))return c(l.get(u));l!==r&&l.get(o)},get size(){const o=this.__v_raw;return!e&&Ie(he(o),"iterate",tn),o.size},has(o){const l=this.__v_raw,r=he(l),u=he(o);return e||(ht(o,u)&&Ie(r,"has",o),Ie(r,"has",u)),o===u?l.has(o):l.has(o)||l.has(u)},forEach(o,l){const r=this,u=r.__v_raw,a=he(u),c=t?ro:e?Kt:Ze;return!e&&Ie(a,"iterate",tn),u.forEach((f,b)=>o.call(l,c(f),c(b),r))}};return Oe(n,e?{add:os("add"),set:os("set"),delete:os("delete"),clear:os("clear")}:{add(o){const l=he(this),r=ss(l),u=he(o),a=!t&&!Xe(o)&&!bt(o)?u:o;return r.has.call(l,a)||ht(o,a)&&r.has.call(l,o)||ht(u,a)&&r.has.call(l,u)||(l.add(a),Tt(l,"add",a,a)),this},set(o,l){!t&&!Xe(l)&&!bt(l)&&(l=he(l));const r=he(this),{has:u,get:a}=ss(r);let c=u.call(r,o);c||(o=he(o),c=u.call(r,o));const f=a.call(r,o);return r.set(o,l),c?ht(l,f)&&Tt(r,"set",o,l):Tt(r,"add",o,l),this},delete(o){const l=he(this),{has:r,get:u}=ss(l);let a=r.call(l,o);a||(o=he(o),a=r.call(l,o)),u&&u.call(l,o);const c=l.delete(o);return a&&Tt(l,"delete",o,void 0),c},clear(){const o=he(this),l=o.size!==0,r=o.clear();return l&&Tt(o,"clear",void 0,void 0),r}}),["keys","values","entries",Symbol.iterator].forEach(o=>{n[o]=Ua(o,e,t)}),n}function Io(e,t){const n=Va(e,t);return(s,o,l)=>o==="__v_isReactive"?!e:o==="__v_isReadonly"?e:o==="__v_raw"?s:Reflect.get(ve(n,o)&&o in s?n:s,o,l)}const Wa={get:Io(!1,!1)},Ka={get:Io(!1,!0)},qa={get:Io(!0,!1)};const fl=new WeakMap,pl=new WeakMap,hl=new WeakMap,Ya=new WeakMap;function za(e){switch(e){case"Object":case"Array":return 1;case"Map":case"Set":case"WeakMap":case"WeakSet":return 2;default:return 0}}function hn(e){return bt(e)?e:Mo(e,!1,Na,Wa,fl)}function Ga(e){return Mo(e,!1,Ba,Ka,pl)}function uo(e){return Mo(e,!0,ja,qa,hl)}function Mo(e,t,n,s,o){if(!ge(e)||e.__v_raw&&!(t&&e.__v_isReactive)||e.__v_skip||!Object.isExtensible(e))return e;const l=o.get(e);if(l)return l;const r=za(ya(e));if(r===0)return e;const u=new Proxy(e,r===2?s:n);return o.set(e,u),u}function Wt(e){return bt(e)?Wt(e.__v_raw):!!(e&&e.__v_isReactive)}function bt(e){return!!(e&&e.__v_isReadonly)}function Xe(e){return!!(e&&e.__v_isShallow)}function Do(e){return e?!!e.__v_raw:!1}function he(e){const t=e&&e.__v_raw;return t?he(t):e}function Ja(e){return!ve(e,"__v_skip")&&Object.isExtensible(e)&&Xi(e,"__v_skip",!0),e}const Ze=e=>ge(e)?hn(e):e,Kt=e=>ge(e)?uo(e):e;function Le(e){return e?e.__v_isRef===!0:!1}function fe(e){return Xa(e,!1)}function Xa(e,t){return Le(e)?e:new Qa(e,t)}class Qa{constructor(t,n){this.dep=new Oo,this.__v_isRef=!0,this.__v_isShallow=!1,this._rawValue=n?t:he(t),this._value=n?t:Ze(t),this.__v_isShallow=n}get value(){return this.dep.track(),this._value}set value(t){const n=this._rawValue,s=this.__v_isShallow||Xe(t)||bt(t);t=s?t:he(t),ht(t,n)&&(this._rawValue=t,this._value=s?t:Ze(t),this.dep.trigger())}}function v(e){return Le(e)?e.value:e}const Za={get:(e,t,n)=>t==="__v_raw"?e:v(Reflect.get(e,t,n)),set:(e,t,n,s)=>{const o=e[t];return Le(o)&&!Le(n)?(o.value=n,!0):Reflect.set(e,t,n,s)}};function vl(e){return Wt(e)?e:new Proxy(e,Za)}class er{constructor(t,n,s){this.fn=t,this.setter=n,this._value=void 0,this.dep=new Oo(this),this.__v_isRef=!0,this.deps=void 0,this.depsTail=void 0,this.flags=16,this.globalVersion=Rn-1,this.next=void 0,this.effect=this,this.__v_isReadonly=!n,this.isSSR=s}notify(){if(this.flags|=16,!(this.flags&8)&&we!==this)return sl(this,!0),!0}get value(){const t=this.dep.track();return ll(this),t&&(t.version=this.dep.version),this._value}set value(t){this.setter&&this.setter(t)}}function tr(e,t,n=!1){let s,o;return ne(e)?s=e:(s=e.get,o=e.set),new er(s,o,n)}const is={},hs=new WeakMap;let Qt;function nr(e,t=!1,n=Qt){if(n){let s=hs.get(n);s||hs.set(n,s=[]),s.push(e)}}function sr(e,t,n=be){const{immediate:s,deep:o,once:l,scheduler:r,augmentJob:u,call:a}=n,c=m=>o?m:Xe(m)||o===!1||o===0?At(m,1):At(m);let f,b,A,D,I=!1,R=!1;if(Le(e)?(b=()=>e.value,I=Xe(e)):Wt(e)?(b=()=>c(e),I=!0):ee(e)?(R=!0,I=e.some(m=>Wt(m)||Xe(m)),b=()=>e.map(m=>{if(Le(m))return m.value;if(Wt(m))return c(m);if(ne(m))return a?a(m,2):m()})):ne(e)?t?b=a?()=>a(e,2):e:b=()=>{if(A){Pt();try{A()}finally{Ot()}}const m=Qt;Qt=f;try{return a?a(e,3,[D]):e(D)}finally{Qt=m}}:b=mt,t&&o){const m=b,H=o===!0?1/0:o;b=()=>At(m(),H)}const T=Oa(),$=()=>{f.stop(),T&&T.active&&Co(T.effects,f)};if(l&&t){const m=t;t=(...H)=>{const C=m(...H);return $(),C}}let x=R?new Array(e.length).fill(is):is;const w=m=>{if(!(!(f.flags&1)||!f.dirty&&!m))if(t){const H=f.run();if(m||o||I||(R?H.some((C,L)=>ht(C,x[L])):ht(H,x))){A&&A();const C=Qt;Qt=f;try{const L=[H,x===is?void 0:R&&x[0]===is?[]:x,D];x=H,a?a(t,3,L):t(...L)}finally{Qt=C}}}else f.run()};return u&&u(w),f=new tl(b),f.scheduler=r?()=>r(w,!1):w,D=m=>nr(m,!1,f),A=f.onStop=()=>{const m=hs.get(f);if(m){if(a)a(m,4);else for(const H of m)H();hs.delete(f)}},t?s?w(!0):x=f.run():r?r(w.bind(null,!0),!0):f.run(),$.pause=f.pause.bind(f),$.resume=f.resume.bind(f),$.stop=$,$}function At(e,t=1/0,n){if(t<=0||!ge(e)||e.__v_skip||(n=n||new Map,(n.get(e)||0)>=t))return e;if(n.set(e,t),t--,Le(e))At(e.value,t,n);else if(ee(e))for(let s=0;s{At(s,t,n)});else if(Ji(e)){for(const s in e)At(e[s],t,n);for(const s of Object.getOwnPropertySymbols(e))Object.prototype.propertyIsEnumerable.call(e,s)&&At(e[s],t,n)}return e}function Jn(e,t,n,s){try{return s?e(...s):e()}catch(o){Ls(o,t,n)}}function ot(e,t,n,s){if(ne(e)){const o=Jn(e,t,n,s);return o&&zi(o)&&o.catch(l=>{Ls(l,t,n)}),o}if(ee(e)){const o=[];for(let l=0;l>>1,o=Re[s],l=jn(o);l=jn(n)?Re.push(e):Re.splice(ir(t),0,e),e.flags|=1,gl()}}function gl(){vs||(vs=ml.then(bl))}function lr(e){if(!ee(e))Nt&&e.id===-1?Nt.splice(un+1,0,e):e.flags&1||(cn.push(e),e.flags|=1);else for(let t=0;tjn(n)-jn(s));if(cn.length=0,Nt){for(let n=0;ne.id==null?e.flags&2?-1:1/0:e.id;function bl(e){try{for(ct=0;ct{s._d&&yi(-1);const l=ms(t),r=nn.length;let u;try{u=e(...o)}finally{for(let a=nn.length;a>r;a--)Kl();ms(l),s._d&&yi(1)}return u};return s._n=!0,s._c=!0,s._d=!0,s}function Te(e,t){if(qe===null)return e;const n=js(qe),s=e.dirs||(e.dirs=[]);for(let o=0;o1)return n&&ne(t)?t.call(s&&s.proxy):t}}const ur=Symbol.for("v-scx"),cr=()=>us(ur);function In(e,t,n){return _l(e,t,n)}function _l(e,t,n=be){const{immediate:s,deep:o,flush:l,once:r}=n,u=Oe({},n),a=t&&s||!t&&l!=="post";let c;if(Vn){if(l==="sync"){const D=cr();c=D.__watcherHandles||(D.__watcherHandles=[])}else if(!a){const D=()=>{};return D.stop=mt,D.resume=mt,D.pause=mt,D}}const f=Me;u.call=(D,I,R)=>ot(D,f,I,R);let b=!1;l==="post"?u.scheduler=D=>{Ue(D,f&&f.suspense)}:l!=="sync"&&(b=!0,u.scheduler=(D,I)=>{I?D():Fo(D)}),u.augmentJob=D=>{t&&(D.flags|=4),b&&(D.flags|=2,f&&(D.id=f.uid,D.i=f))};const A=sr(e,t,u);return Vn&&(c?c.push(A):a&&A()),A}function dr(e,t,n){const s=this.proxy,o=xe(e)?e.includes(".")?kl(s,e):()=>s[e]:e.bind(s,s);let l;ne(t)?l=t:(l=t.handler,n=t);const r=Qn(this),u=_l(o,l.bind(s),n);return r(),u}function kl(e,t){const n=t.split(".");return()=>{let s=e;for(let o=0;oe.__isTeleport,Ys=Symbol("_leaveCb");function pr(e){let t=e[0];if(e.length>1){for(const n of e)if(n.type!==It){t=n;break}}return t}function $l(e){if(!Ro(e))return Fs(e.type)&&e.children?pr(e.children):e;if(e.component)return e.component.subTree;const{shapeFlag:t,children:n}=e;if(n){if(t&16)return n[0];if(t&32&&ne(n.default))return n.default()}}function Ho(e,t){if(e.shapeFlag&6&&e.component){e.transition=t;const n=e.component.subTree;Ho(Fs(n.type)&&$l(n)||n,t)}else e.shapeFlag&128?(e.ssContent.transition=t.clone(e.ssContent),e.ssFallback.transition=t.clone(e.ssFallback)):e.transition=t}function $e(e,t){return ne(e)?Oe({name:e.name},t,{setup:e}):e}function xl(e){e.ids=[e.ids[0]+e.ids[2]+++"-",0,0]}function ai(e,t){let n;return!!((n=Object.getOwnPropertyDescriptor(e,t))&&!n.configurable)}const gs=new WeakMap;function Mn(e,t,n,s,o=!1){if(ee(e)){e.forEach((R,T)=>Mn(R,t&&(ee(t)?t[T]:t),n,s,o));return}if(Dn(s)&&!o){s.shapeFlag&512&&s.type.__asyncResolved&&s.component.subTree.component&&Mn(e,t,n,s.component.subTree);return}const l=s.shapeFlag&4?js(s.component):s.el,r=o?null:l,{i:u,r:a}=e,c=t&&t.r,f=u.refs===be?u.refs={}:u.refs,b=u.setupState,A=he(b),D=b===be?Yi:R=>ai(f,R)?!1:ve(A,R),I=(R,T)=>!(T&&ai(f,T));if(c!=null&&c!==a){if(ri(t),xe(c))f[c]=null,D(c)&&(b[c]=null);else if(Le(c)){const R=t;I(c,R.k)&&(c.value=null),R.k&&(f[R.k]=null)}}if(ne(a))Jn(a,u,12,[r,f]);else{const R=xe(a),T=Le(a);if(R||T){const $=()=>{if(e.f){const x=R?D(a)?b[a]:f[a]:I()||!e.k?a.value:f[e.k];if(o)ee(x)&&Co(x,l);else if(ee(x))x.includes(l)||x.push(l);else if(R)f[a]=[l],D(a)&&(b[a]=f[a]);else{const w=[l];I(a,e.k)&&(a.value=w),e.k&&(f[e.k]=w)}}else R?(f[a]=r,D(a)&&(b[a]=r)):T&&(I(a,e.k)&&(a.value=r),e.k&&(f[e.k]=r))};if(r){const x=()=>{$(),gs.delete(e)};x.id=-1,gs.set(e,x),Ue(x,n)}else ri(e),$()}}}function ri(e){const t=gs.get(e);t&&(t.flags|=8,gs.delete(e))}Ms().requestIdleCallback;Ms().cancelIdleCallback;const Dn=e=>!!e.type.__asyncLoader,Ro=e=>e.type.__isKeepAlive;function hr(e,t){Sl(e,"a",t)}function vr(e,t){Sl(e,"da",t)}function Sl(e,t,n=Me){const s=e.__wdc||(e.__wdc=()=>{let o=n;for(;o;){if(o.isDeactivated)return;o=o.parent}return e()});if(Hs(t,s,n),n){let o=n.parent;for(;o&&o.parent;)Ro(o.parent.vnode)&&mr(s,t,n,o),o=o.parent}}function mr(e,t,n,s){const o=Hs(t,e,s,!0);Cl(()=>{Co(s[t],o)},n)}function Hs(e,t,n=Me,s=!1){if(n){const o=n[e]||(n[e]=[]),l=t.__weh||(t.__weh=(...r)=>{Pt();const u=Qn(n),a=ot(t,n,e,r);return u(),Ot(),a});return s?o.unshift(l):o.push(l),l}}const Lt=e=>(t,n=Me)=>{(!Vn||e==="sp")&&Hs(e,(...s)=>t(...s),n)},gr=Lt("bm"),bn=Lt("m"),yr=Lt("bu"),br=Lt("u"),Xn=Lt("bum"),Cl=Lt("um"),wr=Lt("sp"),_r=Lt("rtg"),kr=Lt("rtc");function $r(e,t=Me){Hs("ec",e,t)}const xr="components",Tl=Symbol.for("v-ndc");function Sr(e){return xe(e)?Cr(xr,e,!1)||e:e||Tl}function Cr(e,t,n=!0,s=!1){const o=qe||Me;if(o){const l=o.type;{const u=cu(l,!1);if(u&&(u===t||u===Be(t)||u===Os(Be(t))))return l}const r=ui(o[e]||l[e],t)||ui(o.appContext[e],t);return!r&&s?l:r}}function ui(e,t){return e&&(e[t]||e[Be(t)]||e[Os(Be(t))])}function le(e,t,n,s){let o;const l=n,r=ee(e);if(r||xe(e)){const u=r&&Wt(e);let a=!1,c=!1;u&&(a=!Xe(e),c=bt(e),e=Ds(e)),o=new Array(e.length);for(let f=0,b=e.length;ft(u,a,void 0,l));else{const u=Object.keys(e);o=new Array(u.length);for(let a=0,c=u.length;ae?Gl(e)?js(e):co(e.parent):null,Ln=Oe(Object.create(null),{$:e=>e,$el:e=>e.vnode.el,$data:e=>e.data,$props:e=>e.props,$attrs:e=>e.attrs,$slots:e=>e.slots,$refs:e=>e.refs,$parent:e=>co(e.parent),$root:e=>co(e.root),$host:e=>e.ce,$emit:e=>e.emit,$options:e=>El(e),$forceUpdate:e=>e.f||(e.f=()=>{Fo(e.update)}),$nextTick:e=>e.n||(e.n=Lo.bind(e.proxy)),$watch:e=>dr.bind(e)}),zs=(e,t)=>e!==be&&!e.__isScriptSetup&&ve(e,t),Tr={get({_:e},t){if(t==="__v_skip")return!0;const{ctx:n,setupState:s,data:o,props:l,accessCache:r,type:u,appContext:a}=e;if(t[0]!=="$"){const A=r[t];if(A!==void 0)switch(A){case 1:return s[t];case 2:return o[t];case 4:return n[t];case 3:return l[t]}else{if(zs(s,t))return r[t]=1,s[t];if(o!==be&&ve(o,t))return r[t]=2,o[t];if(ve(l,t))return r[t]=3,l[t];if(n!==be&&ve(n,t))return r[t]=4,n[t];fo&&(r[t]=0)}}const c=Ln[t];let f,b;if(c)return t==="$attrs"&&Ie(e.attrs,"get",""),c(e);if((f=u.__cssModules)&&(f=f[t]))return f;if(n!==be&&ve(n,t))return r[t]=4,n[t];if(b=a.config.globalProperties,ve(b,t))return b[t]},set({_:e},t,n){const{data:s,setupState:o,ctx:l}=e;return zs(o,t)?(o[t]=n,!0):s!==be&&ve(s,t)?(s[t]=n,!0):ve(e.props,t)||t[0]==="$"&&t.slice(1)in e?!1:(l[t]=n,!0)},has({_:{data:e,setupState:t,accessCache:n,ctx:s,appContext:o,props:l,type:r}},u){let a;return!!(n[u]||e!==be&&u[0]!=="$"&&ve(e,u)||zs(t,u)||ve(l,u)||ve(s,u)||ve(Ln,u)||ve(o.config.globalProperties,u)||(a=r.__cssModules)&&a[u])},defineProperty(e,t,n){return n.get!=null?e._.accessCache[t]=0:ve(n,"value")&&this.set(e,t,n.value,null),Reflect.defineProperty(e,t,n)}};function ci(e){return ee(e)?e.reduce((t,n)=>(t[n]=null,t),{}):e}let fo=!0;function Ar(e){const t=El(e),n=e.proxy,s=e.ctx;fo=!1,t.beforeCreate&&di(t.beforeCreate,e,"bc");const{data:o,computed:l,methods:r,watch:u,provide:a,inject:c,created:f,beforeMount:b,mounted:A,beforeUpdate:D,updated:I,activated:R,deactivated:T,beforeDestroy:$,beforeUnmount:x,destroyed:w,unmounted:m,render:H,renderTracked:C,renderTriggered:L,errorCaptured:pe,serverPrefetch:Ae,expose:J,inheritAttrs:q,components:ae,directives:z,filters:B}=t;if(c&&Er(c,s,null),r)for(const ie in r){const ue=r[ie];ne(ue)&&(s[ie]=ue.bind(n))}if(o){const ie=o.call(n,n);ge(ie)&&(e.data=hn(ie))}if(fo=!0,l)for(const ie in l){const ue=l[ie],ze=ne(ue)?ue.bind(n,n):ne(ue.get)?ue.get.bind(n,n):mt,an=!ne(ue)&&ne(ue.set)?ue.set.bind(n):mt,_t=k({get:ze,set:an});Object.defineProperty(s,ie,{enumerable:!0,configurable:!0,get:()=>_t.value,set:We=>_t.value=We})}if(u)for(const ie in u)Al(u[ie],s,n,ie);if(a){const ie=ne(a)?a.call(n):a;Reflect.ownKeys(ie).forEach(ue=>{rr(ue,ie[ue])})}f&&di(f,e,"c");function oe(ie,ue){ee(ue)?ue.forEach(ze=>ie(ze.bind(n))):ue&&ie(ue.bind(n))}if(oe(gr,b),oe(bn,A),oe(yr,D),oe(br,I),oe(hr,R),oe(vr,T),oe($r,pe),oe(kr,C),oe(_r,L),oe(Xn,x),oe(Cl,m),oe(wr,Ae),ee(J))if(J.length){const ie=e.exposed||(e.exposed={});J.forEach(ue=>{Object.defineProperty(ie,ue,{get:()=>n[ue],set:ze=>n[ue]=ze,enumerable:!0})})}else e.exposed||(e.exposed={});H&&e.render===mt&&(e.render=H),q!=null&&(e.inheritAttrs=q),ae&&(e.components=ae),z&&(e.directives=z),Ae&&xl(e)}function Er(e,t,n=mt){ee(e)&&(e=po(e));for(const s in e){const o=e[s];let l;ge(o)?"default"in o?l=us(o.from||s,o.default,!0):l=us(o.from||s):l=us(o),Le(l)?Object.defineProperty(t,s,{enumerable:!0,configurable:!0,get:()=>l.value,set:r=>l.value=r}):t[s]=l}}function di(e,t,n){ot(ee(e)?e.map(s=>s.bind(t.proxy)):e.bind(t.proxy),t,n)}function Al(e,t,n,s){let o=s.includes(".")?kl(n,s):()=>n[s];if(xe(e)){const l=t[e];ne(l)&&In(o,l)}else if(ne(e))In(o,e.bind(n));else if(ge(e))if(ee(e))e.forEach(l=>Al(l,t,n,s));else{const l=ne(e.handler)?e.handler.bind(n):t[e.handler];ne(l)&&In(o,l,e)}}function El(e){const t=e.type,{mixins:n,extends:s}=t,{mixins:o,optionsCache:l,config:{optionMergeStrategies:r}}=e.appContext,u=l.get(t);let a;return u?a=u:!o.length&&!n&&!s?a=t:(a={},o.length&&o.forEach(c=>ys(a,c,r,!0)),ys(a,t,r)),ge(t)&&l.set(t,a),a}function ys(e,t,n,s=!1){const{mixins:o,extends:l}=t;l&&ys(e,l,n,!0),o&&o.forEach(r=>ys(e,r,n,!0));for(const r in t)if(!(s&&r==="expose")){const u=Pr[r]||n&&n[r];e[r]=u?u(e[r],t[r]):t[r]}return e}const Pr={data:fi,props:pi,emits:pi,methods:Sn,computed:Sn,beforeCreate:Fe,created:Fe,beforeMount:Fe,mounted:Fe,beforeUpdate:Fe,updated:Fe,beforeDestroy:Fe,beforeUnmount:Fe,destroyed:Fe,unmounted:Fe,activated:Fe,deactivated:Fe,errorCaptured:Fe,serverPrefetch:Fe,components:Sn,directives:Sn,watch:Ir,provide:fi,inject:Or};function fi(e,t){return t?e?function(){return Oe(ne(e)?e.call(this,this):e,ne(t)?t.call(this,this):t)}:t:e}function Or(e,t){return Sn(po(e),po(t))}function po(e){if(ee(e)){const t={};for(let n=0;nt==="modelValue"||t==="model-value"?e.modelModifiers:e[`${t}Modifiers`]||e[`${Be(t)}Modifiers`]||e[`${Yt(t)}Modifiers`];function Fr(e,t,...n){if(e.isUnmounted)return;const s=e.vnode.props||be;let o=n;const l=t.startsWith("update:"),r=l&&Lr(s,t.slice(7));r&&(r.trim&&(o=n.map(f=>xe(f)?f.trim():f)),r.number&&(o=o.map(Is)));let u,a=s[u=Us(t)]||s[u=Us(Be(t))];!a&&l&&(a=s[u=Us(Yt(t))]),a&&ot(a,e,6,o);const c=s[u+"Once"];if(c){if(!e.emitted)e.emitted={};else if(e.emitted[u])return;e.emitted[u]=!0,ot(c,e,6,o)}}const Hr=new WeakMap;function Ol(e,t,n=!1){const s=n?Hr:t.emitsCache,o=s.get(e);if(o!==void 0)return o;const l=e.emits;let r={},u=!1;if(!ne(e)){const a=c=>{const f=Ol(c,t,!0);f&&(u=!0,Oe(r,f))};!n&&t.mixins.length&&t.mixins.forEach(a),e.extends&&a(e.extends),e.mixins&&e.mixins.forEach(a)}return!l&&!u?(ge(e)&&s.set(e,null),null):(ee(l)?l.forEach(a=>r[a]=null):Oe(r,l),ge(e)&&s.set(e,r),r)}function Rs(e,t){return!e||!As(t)?!1:(t=t.slice(2),t=t==="Once"?t:t.replace(/Once$/,""),ve(e,t[0].toLowerCase()+t.slice(1))||ve(e,Yt(t))||ve(e,t))}function hi(e){const{type:t,vnode:n,proxy:s,withProxy:o,propsOptions:[l],slots:r,attrs:u,emit:a,render:c,renderCache:f,props:b,data:A,setupState:D,ctx:I,inheritAttrs:R}=e,T=ms(e);let $,x;try{if(n.shapeFlag&4){const m=o||s,H=m;$=pt(c.call(H,m,f,b,D,A,I)),x=u}else{const m=t;$=pt(m.length>1?m(b,{attrs:u,slots:r,emit:a}):m(b,null)),x=t.props?u:Rr(u)}}catch(m){nn.length=0,Ls(m,e,1),$=_e(It)}let w=$;if(x&&R!==!1){const m=Object.keys(x),{shapeFlag:H}=w;m.length&&H&7&&(l&&m.some(Es)&&(x=Nr(x,l)),w=vn(w,x,!1,!0))}if(n.dirs&&(w=vn(w,null,!1,!0),w.dirs=w.dirs?w.dirs.concat(n.dirs):n.dirs),n.transition){const m=Fs(w.type)&&$l(w)||w;Ho(m,n.transition)}return $=w,ms(T),$}const Rr=e=>{let t;for(const n in e)(n==="class"||n==="style"||As(n))&&((t||(t={}))[n]=e[n]);return t},Nr=(e,t)=>{const n={};for(const s in e)(!Es(s)||!(s.slice(9)in t))&&(n[s]=e[s]);return n};function jr(e,t,n){const{props:s,children:o,component:l}=e,{props:r,children:u,patchFlag:a}=t,c=l.emitsOptions;if(t.dirs||t.transition)return!0;if(n&&a>=0){if(a&1024)return!0;if(a&16)return s?vi(s,r,c):!!r;if(a&8){const f=t.dynamicProps;for(let b=0;bObject.create(Ml),Ll=e=>Object.getPrototypeOf(e)===Ml;function Ur(e,t,n,s=!1){const o={},l=Dl();e.propsDefaults=Object.create(null),Fl(e,t,o,l);for(const r in e.propsOptions[0])r in o||(o[r]=void 0);n?e.props=s?o:Ga(o):e.type.props?e.props=o:e.props=l,e.attrs=l}function Vr(e,t,n,s){const{props:o,attrs:l,vnode:{patchFlag:r}}=e,u=he(o),[a]=e.propsOptions;let c=!1;if((s||r>0)&&!(r&16)){if(r&8){const f=e.vnode.dynamicProps;for(let b=0;b{a=!0;const[A,D]=Hl(b,t,!0);Oe(r,A),D&&u.push(...D)};!n&&t.mixins.length&&t.mixins.forEach(f),e.extends&&f(e.extends),e.mixins&&e.mixins.forEach(f)}if(!l&&!a)return ge(e)&&s.set(e,en),en;if(ee(l))for(let f=0;fe==="_"||e==="_ctx"||e==="$stable",jo=e=>ee(e)?e.map(pt):[pt(e)],Kr=(e,t,n)=>{if(t._n)return t;const s=ar((...o)=>jo(t(...o)),n);return s._c=!1,s},Rl=(e,t,n)=>{const s=e._ctx;for(const o in e){if(No(o))continue;const l=e[o];if(ne(l))t[o]=Kr(o,l,s);else if(l!=null){const r=jo(l);t[o]=()=>r}}},Nl=(e,t)=>{const n=jo(t);e.slots.default=()=>n},jl=(e,t,n)=>{for(const s in t)(n||!No(s))&&(e[s]=t[s])},qr=(e,t,n)=>{const s=e.slots=Dl();if(e.vnode.shapeFlag&32){const o=t._;o?(jl(s,t,n),n&&Xi(s,"_",o,!0)):Rl(t,s)}else t&&Nl(e,t)},Yr=(e,t,n)=>{const{vnode:s,slots:o}=e;let l=!0,r=be;if(s.shapeFlag&32){const u=t._;u?n&&u===1?l=!1:jl(o,t,n):(l=!t.$stable,Rl(t,o)),r=t}else t&&(Nl(e,t),r={default:1});if(l)for(const u in o)!No(u)&&r[u]==null&&delete o[u]},Ue=Qr;function zr(e){return Gr(e)}function Gr(e,t){const n=Ms();n.__VUE__=!0;const{insert:s,remove:o,patchProp:l,createElement:r,createText:u,createComment:a,setText:c,setElementText:f,parentNode:b,nextSibling:A,setScopeId:D=mt,insertStaticContent:I}=e,R=(p,_,S,F=null,E=null,O=null,U=void 0,j=null,N=!!_.dynamicChildren)=>{if(p===_)return;p&&!$n(p,_)&&(F=se(p),We(p,E,O,!0),p=null),_.patchFlag===-2&&(N=!1,_.dynamicChildren=null),_.dynamicChildren&&p&&p.dynamicChildren&&p.dynamicChildren.hasOnce&&(_.dynamicChildren===en&&(_.dynamicChildren=[]),_.dynamicChildren.hasOnce=!0);const{type:P,ref:X,shapeFlag:K}=_;switch(P){case Ns:T(p,_,S,F);break;case It:$(p,_,S,F);break;case cs:p==null&&x(_,S,F,U);break;case W:ae(p,_,S,F,E,O,U,j,N);break;default:K&1?H(p,_,S,F,E,O,U,j,N):K&6?z(p,_,S,F,E,O,U,j,N):(K&64||K&128)&&P.process(p,_,S,F,E,O,U,j,N,Gt)}X!=null&&E?Mn(X,p&&p.ref,O,_||p,!_):X==null&&p&&p.ref!=null&&Mn(p.ref,null,O,p,!0)},T=(p,_,S,F)=>{if(p==null)s(_.el=u(_.children),S,F);else{const E=_.el=p.el;_.children!==p.children&&c(E,_.children)}},$=(p,_,S,F)=>{p==null?s(_.el=a(_.children||""),S,F):_.el=p.el},x=(p,_,S,F)=>{[p.el,p.anchor]=I(p.children,_,S,F,p.el,p.anchor)},w=({el:p,anchor:_},S,F)=>{let E;for(;p&&p!==_;)E=A(p),s(p,S,F),p=E;s(_,S,F)},m=({el:p,anchor:_})=>{let S;for(;p&&p!==_;)S=A(p),o(p),p=S;o(_)},H=(p,_,S,F,E,O,U,j,N)=>{if(_.type==="svg"?U="svg":_.type==="math"&&(U="mathml"),p==null)C(_,S,F,E,O,U,j,N);else{const P=p.el&&p.el._isVueCE?p.el:null;try{P&&P._beginPatch(),Ae(p,_,E,O,U,j,N)}finally{P&&P._endPatch()}}},C=(p,_,S,F,E,O,U,j)=>{let N,P;const{props:X,shapeFlag:K,transition:G,dirs:te}=p;if(N=p.el=r(p.type,O,X&&X.is,X),K&8?f(N,p.children):K&16&&pe(p.children,N,null,F,E,Gs(p,O),U,j),te&&Jt(p,null,F,"created"),L(N,p,p.scopeId,U,F),X){for(const ye in X)ye!=="value"&&!En(ye)&&l(N,ye,null,X[ye],O,F);"value"in X&&l(N,"value",null,X.value,O),(P=X.onVnodeBeforeMount)&&ut(P,F,p)}te&&Jt(p,null,F,"beforeMount");const de=Jr(E,G);de&&G.beforeEnter(N),s(N,_,S),((P=X&&X.onVnodeMounted)||de||te)&&Ue(()=>{P&&ut(P,F,p),de&&G.enter(N),te&&Jt(p,null,F,"mounted")},E)},L=(p,_,S,F,E)=>{if(S&&D(p,S),F)for(let O=0;O{for(let P=N;P{const j=_.el=p.el;let{patchFlag:N,dynamicChildren:P,dirs:X}=_;N|=p.patchFlag&16;const K=p.props||be,G=_.props||be;let te;if(S&&Xt(S,!1),(te=G.onVnodeBeforeUpdate)&&ut(te,S,_,p),X&&Jt(_,p,S,"beforeUpdate"),S&&Xt(S,!0),P&&(!p.dynamicChildren||p.dynamicChildren.length!==P.length)&&(N=0,U=!1,P=null),(K.innerHTML&&G.innerHTML==null||K.textContent&&G.textContent==null)&&f(j,""),P?J(p.dynamicChildren,P,j,S,F,Gs(_,E),O):U||ue(p,_,j,null,S,F,Gs(_,E),O,!1),N>0){if(N&16)q(j,K,G,S,E);else if(N&2&&K.class!==G.class&&l(j,"class",null,G.class,E),N&4&&l(j,"style",K.style,G.style,E),N&8){const de=_.dynamicProps;for(let ye=0;ye{te&&ut(te,S,_,p),X&&Jt(_,p,S,"updated")},F)},J=(p,_,S,F,E,O,U)=>{for(let j=0;j<_.length;j++){const N=p[j],P=_[j],X=N.el&&(N.type===W||!$n(N,P)||N.shapeFlag&198)?b(N.el):S;R(N,P,X,null,F,E,O,U,!0)}},q=(p,_,S,F,E)=>{if(_!==S){if(_!==be)for(const O in _)!En(O)&&!(O in S)&&l(p,O,_[O],null,E,F);for(const O in S){if(En(O))continue;const U=S[O],j=_[O];U!==j&&O!=="value"&&l(p,O,j,U,E,F)}"value"in S&&l(p,"value",_.value,S.value,E)}},ae=(p,_,S,F,E,O,U,j,N)=>{const P=_.el=p?p.el:u(""),X=_.anchor=p?p.anchor:u("");let{patchFlag:K,dynamicChildren:G,slotScopeIds:te}=_;te&&(j=j?j.concat(te):te),p==null?(s(P,S,F),s(X,S,F),pe(_.children||[],S,X,E,O,U,j,N)):K>0&&K&64&&G&&p.dynamicChildren&&p.dynamicChildren.length===G.length?(J(p.dynamicChildren,G,S,E,O,U,j),(_.key!=null||E&&_===E.subTree)&&Bl(p,_,!0)):ue(p,_,S,X,E,O,U,j,N)},z=(p,_,S,F,E,O,U,j,N)=>{_.slotScopeIds=j,p==null?_.shapeFlag&512?E.ctx.activate(_,S,F,U,N):B(_,S,F,E,O,U,N):Y(p,_,N)},B=(p,_,S,F,E,O,U)=>{const j=p.component=ou(p,F,E);if(Ro(p)&&(j.ctx.renderer=Gt),lu(j,!1,U),j.asyncDep){if(E&&E.registerDep(j,oe,U),!p.el){const N=j.subTree=_e(It);$(null,N,_,S),p.placeholder=N.el}}else oe(j,p,_,S,E,O,U)},Y=(p,_,S)=>{const F=_.component=p.component;if(jr(p,_,S))if(F.asyncDep&&!F.asyncResolved){_.el=p.el,ie(F,_,S);return}else F.next=_,F.update();else _.el=p.el,F.vnode=_},oe=(p,_,S,F,E,O,U)=>{const j=()=>{if(p.isMounted){let{next:K,bu:G,u:te,parent:de,vnode:ye}=p;{const at=Ul(p);if(at){K&&(K.el=ye.el,ie(p,K,U)),at.asyncDep.then(()=>{Ue(()=>{p.isUnmounted||P()},E)});return}}let me=K,Ce;Xt(p,!1),K?(K.el=ye.el,ie(p,K,U)):K=ye,G&&rs(G),(Ce=K.props&&K.props.onVnodeBeforeUpdate)&&ut(Ce,de,K,ye),Xt(p,!0);const Ee=hi(p),lt=p.subTree;p.subTree=Ee,R(lt,Ee,b(lt.el),se(lt),p,E,O),K.el=Ee.el,me===null&&Br(p,Ee.el),te&&Ue(te,E),(Ce=K.props&&K.props.onVnodeUpdated)&&Ue(()=>ut(Ce,de,K,ye),E)}else{let K;const{el:G,props:te}=_,{bm:de,m:ye,parent:me,root:Ce,type:Ee}=p,lt=Dn(_);Xt(p,!1),de&&rs(de),!lt&&(K=te&&te.onVnodeBeforeMount)&&ut(K,me,_),Xt(p,!0);{Ce.ce&&Ce.ce._hasShadowRoot()&&Ce.ce._injectChildStyle(Ee,p.parent?p.parent.type:void 0);const at=p.subTree=hi(p);R(null,at,S,F,p,E,O),_.el=at.el}if(ye&&Ue(ye,E),!lt&&(K=te&&te.onVnodeMounted)){const at=_;Ue(()=>ut(K,me,at),E)}(_.shapeFlag&256||me&&Dn(me.vnode)&&me.vnode.shapeFlag&256)&&p.a&&Ue(p.a,E),p.isMounted=!0,_=S=F=null}};p.scope.on();const N=p.effect=new tl(j);p.scope.off();const P=p.update=N.run.bind(N),X=p.job=N.runIfDirty.bind(N);X.i=p,X.id=p.uid,N.scheduler=()=>Fo(X),Xt(p,!0),P()},ie=(p,_,S)=>{_.component=p;const F=p.vnode.props;p.vnode=_,p.next=null,Vr(p,_.props,F,S),Yr(p,_.children,S),Pt(),li(p),Ot()},ue=(p,_,S,F,E,O,U,j,N=!1)=>{const P=p&&p.children,X=p?p.shapeFlag:0,K=_.children,{patchFlag:G,shapeFlag:te}=_;if(G>0){if(G&128){an(P,K,S,F,E,O,U,j,N);return}else if(G&256){ze(P,K,S,F,E,O,U,j,N);return}}te&8?(X&16&&M(P,E,O),K!==P&&f(S,K)):X&16?te&16?an(P,K,S,F,E,O,U,j,N):M(P,E,O,!0):(X&8&&f(S,""),te&16&&pe(K,S,F,E,O,U,j,N))},ze=(p,_,S,F,E,O,U,j,N)=>{p=p||en,_=_||en;const P=p.length,X=_.length,K=Math.min(P,X);let G;for(G=0;GX?M(p,E,O,!0,!1,K):pe(_,S,F,E,O,U,j,N,K)},an=(p,_,S,F,E,O,U,j,N)=>{let P=0;const X=_.length;let K=p.length-1,G=X-1;for(;P<=K&&P<=G;){const te=p[P],de=_[P]=N?St(_[P]):pt(_[P]);if($n(te,de))R(te,de,S,null,E,O,U,j,N);else break;P++}for(;P<=K&&P<=G;){const te=p[K],de=_[G]=N?St(_[G]):pt(_[G]);if($n(te,de))R(te,de,S,null,E,O,U,j,N);else break;K--,G--}if(P>K){if(P<=G){const te=G+1,de=teG)for(;P<=K;)We(p[P],E,O,!0),P++;else{const te=P,de=P,ye=new Map;for(P=de;P<=G;P++){const Ke=_[P]=N?St(_[P]):pt(_[P]);Ke.key!=null&&ye.set(Ke.key,P)}let me,Ce=0;const Ee=G-de+1;let lt=!1,at=0;const _n=new Array(Ee);for(P=0;P=Ee){We(Ke,E,O,!0);continue}let rt;if(Ke.key!=null)rt=ye.get(Ke.key);else for(me=de;me<=G;me++)if(_n[me-de]===0&&$n(Ke,_[me])){rt=me;break}rt===void 0?We(Ke,E,O,!0):(_n[rt-de]=P+1,rt>=at?at=rt:lt=!0,R(Ke,_[rt],S,null,E,O,U,j,N),Ce++)}const Xo=lt?Xr(_n):en;for(me=Xo.length-1,P=Ee-1;P>=0;P--){const Ke=de+P,rt=_[Ke],Qo=_[Ke+1],Zo=Ke+1{const{el:O,type:U,transition:j,children:N,shapeFlag:P}=p;if(P&6){_t(p.component.subTree,_,S,F);return}if(P&128){p.suspense.move(_,S,F);return}if(P&64){U.move(p,_,S,Gt);return}if(U===W){s(O,_,S);for(let K=0;Kj.enter(O),E));else{const{leave:K,delayLeave:G,afterLeave:te}=j,de=()=>{p.ctx.isUnmounted?o(O):s(O,_,S)},ye=()=>{const me=O._isLeaving||!!O[Ys];O._isLeaving&&O[Ys](!0),j.persisted&&!me?de():K(O,()=>{de(),te&&te()})};G?G(O,de,ye):ye()}else s(O,_,S)},We=(p,_,S,F=!1,E=!1)=>{const{type:O,props:U,ref:j,children:N,dynamicChildren:P,shapeFlag:X,patchFlag:K,dirs:G,cacheIndex:te,memo:de}=p;if((K===-2||P&&P.hasOnce)&&(E=!1),j!=null&&(Pt(),Mn(j,null,S,p,!0),Ot()),te!=null&&(!p.ctx||p.ctx===_)&&(_.renderCache[te]=void 0),X&256){_.ctx.deactivate(p);return}const ye=X&1&&G,me=!Dn(p);let Ce;if(me&&(Ce=U&&U.onVnodeBeforeUnmount)&&ut(Ce,_,p),X&6)ce(p.component,S,F);else{if(X&128){p.suspense.unmount(S,F);return}ye&&Jt(p,null,_,"beforeUnmount"),X&64?p.type.remove(p,_,S,Gt,F):P&&!P.hasOnce&&(O!==W||K>0&&K&64)?M(P,_,S,!1,!0):(O===W&&K&384||!E&&X&16)&&M(N,_,S),F&&ts(p)}const Ee=de!=null&&te==null;(me&&(Ce=U&&U.onVnodeUnmounted)||ye||Ee)&&Ue(()=>{Ce&&ut(Ce,_,p),ye&&Jt(p,null,_,"unmounted"),Ee&&(p.el=null)},S)},ts=p=>{const{type:_,el:S,anchor:F,transition:E}=p;if(_===W){ns(S,F);return}if(_===cs){m(p),E&&!E.persisted&&E.afterLeave&&E.afterLeave();return}const O=()=>{o(S),E&&!E.persisted&&E.afterLeave&&E.afterLeave()};if(p.shapeFlag&1&&E&&!E.persisted){const{leave:U,delayLeave:j}=E,N=()=>U(S,O);j?j(p.el,O,N):N()}else O()},ns=(p,_)=>{let S;for(;p!==_;)S=A(p),o(p),p=S;o(_)},ce=(p,_,S)=>{const{bum:F,scope:E,job:O,subTree:U,um:j,m:N,a:P}=p;gi(N),gi(P),F&&rs(F),E.stop(),O?(O.flags|=8,We(U,p,_,S)):p.vnode.el&&U&&(U.transition=p.vnode.transition,We(U,p,_,S)),j&&Ue(j,_),Ue(()=>{p.isUnmounted=!0},_)},M=(p,_,S,F=!1,E=!1,O=0)=>{for(let U=O;U{if(p.shapeFlag&6)return se(p.component.subTree);if(p.shapeFlag&128)return p.suspense.next();const _=A(p.anchor||p.el),S=_&&_[fr];return S?A(S):_};let Ge=!1;const wn=(p,_,S)=>{let F;p==null?_._vnode&&(We(_._vnode,null,null,!0),F=_._vnode.component):R(_._vnode||null,p,_,null,null,null,S),_._vnode=p,Ge||(Ge=!0,li(F),yl(),Ge=!1)},Gt={p:R,um:We,m:_t,r:ts,mt:B,mc:pe,pc:ue,pbc:J,n:se,o:e};return{render:wn,hydrate:void 0,createApp:Dr(wn)}}function Gs({type:e,props:t},n){return n==="svg"&&e==="foreignObject"||n==="mathml"&&e==="annotation-xml"&&t&&t.encoding&&t.encoding.includes("html")?void 0:n}function Xt({effect:e,job:t},n){n?(e.flags|=32,t.flags|=4):(e.flags&=-33,t.flags&=-5)}function Jr(e,t){return(!e||e&&!e.pendingBranch)&&t&&!t.persisted}function Bl(e,t,n=!1){const s=e.children,o=t.children;if(ee(s)&&ee(o))for(let l=0;l>1,e[n[u]]0&&(t[s]=n[l-1]),n[l]=s)}}for(l=n.length,r=n[l-1];l-- >0;)n[l]=r,r=t[r];return n}function Ul(e){const t=e.subTree.component;if(t)return t.asyncDep&&!t.asyncResolved?t:Ul(t)}function gi(e){if(e)for(let t=0;te.__isSuspense;function Qr(e,t){t&&t.pendingBranch?ee(e)?t.effects.push(...e):t.effects.push(e):lr(e)}const W=Symbol.for("v-fgt"),Ns=Symbol.for("v-txt"),It=Symbol.for("v-cmt"),cs=Symbol.for("v-stc"),nn=[];let Ye=null;function h(e=!1){nn.push(Ye=e?null:[])}function Kl(){nn.pop(),Ye=nn[nn.length-1]||null}let Bn=1;function yi(e,t=!1){Bn+=e,e<0&&Ye&&t&&(Ye.hasOnce=!0)}function ql(e){return e.dynamicChildren=Bn>0?Ye||en:null,Kl(),Bn>0&&Ye&&Ye.push(e),e}function g(e,t,n,s,o,l){return ql(i(e,t,n,s,o,l,!0))}function Ve(e,t,n,s,o){return ql(_e(e,t,n,s,o,!0))}function Yl(e){return e?e.__v_isVNode===!0:!1}function $n(e,t){return e.type===t.type&&e.key===t.key}const zl=({key:e})=>e??null,ds=({ref:e,ref_key:t,ref_for:n})=>(typeof e=="number"&&(e=""+e),e!=null?xe(e)||Le(e)||ne(e)?{i:qe,r:e,k:t,f:!!n}:e:null);function i(e,t=null,n=null,s=0,o=null,l=e===W?0:1,r=!1,u=!1){const a={__v_isVNode:!0,__v_skip:!0,type:e,props:t,key:t&&zl(t),ref:t&&ds(t),scopeId:wl,slotScopeIds:null,children:n,component:null,suspense:null,ssContent:null,ssFallback:null,dirs:null,transition:null,el:null,anchor:null,target:null,targetStart:null,targetAnchor:null,staticCount:0,shapeFlag:l,patchFlag:s,dynamicProps:o,dynamicChildren:null,appContext:null,ctx:qe};return u?(bs(a,n),l&128&&e.normalize(a)):n&&(a.shapeFlag|=xe(n)?8:16),Bn>0&&!r&&Ye&&(a.patchFlag>0||l&6)&&a.patchFlag!==32&&Ye.push(a),a}const _e=Zr;function Zr(e,t=null,n=null,s=0,o=null,l=!1){if((!e||e===Tl)&&(e=It),Yl(e)){const u=vn(e,t,!0);return n&&bs(u,n),Bn>0&&!l&&Ye&&(u.shapeFlag&6?Ye[Ye.indexOf(e)]=u:Ye.push(u)),u.patchFlag=-2,u}if(du(e)&&(e=e.__vccOpts),t){t=eu(t);let{class:u,style:a}=t;u&&!xe(u)&&(t.class=re(u)),ge(a)&&(Do(a)&&!ee(a)&&(a=Oe({},a)),t.style=Ne(a))}const r=xe(e)?1:Wl(e)?128:Fs(e)?64:ge(e)?4:ne(e)?2:0;return i(e,t,n,s,o,r,l,!0)}function eu(e){return e?Do(e)||Ll(e)?Oe({},e):e:null}function vn(e,t,n=!1,s=!1){const{props:o,ref:l,patchFlag:r,children:u,transition:a}=e,c=t?tu(o||{},t):o,f={__v_isVNode:!0,__v_skip:!0,type:e.type,props:c,key:c&&zl(c),ref:t&&t.ref?n&&l?ee(l)?l.concat(ds(t)):[l,ds(t)]:ds(t):l,scopeId:e.scopeId,slotScopeIds:e.slotScopeIds,children:u,target:e.target,targetStart:e.targetStart,targetAnchor:e.targetAnchor,staticCount:e.staticCount,shapeFlag:e.shapeFlag,patchFlag:t&&e.type!==W?r===-1?16:r|16:r,dynamicProps:e.dynamicProps,dynamicChildren:e.dynamicChildren,appContext:e.appContext,dirs:e.dirs,transition:a,component:e.component,suspense:e.suspense,ssContent:e.ssContent&&vn(e.ssContent),ssFallback:e.ssFallback&&vn(e.ssFallback),placeholder:e.placeholder,el:e.el,anchor:e.anchor,ctx:e.ctx,ce:e.ce,cacheIndex:e.cacheIndex};return a&&s&&Ho(f,a.clone(f)),f}function Q(e=" ",t=0){return _e(Ns,null,e,t)}function fs(e,t){const n=_e(cs,null,e);return n.staticCount=t,n}function V(e="",t=!1){return t?(h(),Ve(It,null,e)):_e(It,null,e)}function pt(e){return e==null||typeof e=="boolean"?_e(It):ee(e)?_e(W,null,e.slice()):Yl(e)?St(e):_e(Ns,null,String(e))}function St(e){return e.el===null&&e.patchFlag!==-1||e.memo?e:vn(e)}function bs(e,t){let n=0;const{shapeFlag:s}=e;if(t==null)t=null;else if(ee(t))n=16;else if(typeof t=="object")if(s&65){const o=t.default;o&&(o._c&&(o._d=!1),bs(e,o()),o._c&&(o._d=!0));return}else{n=32;const o=t._;!o&&!Ll(t)?t._ctx=qe:o===3&&qe&&(qe.slots._===1?t._=1:(t._=2,e.patchFlag|=1024))}else if(ne(t)){if(s&65){bs(e,{default:t});return}t={default:t,_ctx:qe},n=32}else t=String(t),s&64?(n=16,t=[Q(t)]):n=8;e.children=t,e.shapeFlag|=n}function tu(...e){const t={};for(let n=0;nMe||qe;let ws,Un;{const e=Ms(),t=(n,s)=>{let o;return(o=e[n])||(o=e[n]=[]),o.push(s),l=>{o.length>1?o.forEach(r=>r(l)):o[0](l)}};ws=t("__VUE_INSTANCE_SETTERS__",n=>Me=n),Un=t("__VUE_SSR_SETTERS__",n=>Vn=n)}const Qn=e=>{const t=Me;return ws(e),e.scope.on(),()=>{e.scope.off(),ws(t)}},bi=()=>{Me&&Me.scope.off(),ws(null)};function Gl(e){return e.vnode.shapeFlag&4}let Vn=!1;function lu(e,t=!1,n=!1){t&&Un(t);const{props:s,children:o}=e.vnode,l=Gl(e);Ur(e,s,l,t),qr(e,o,n||t);const r=l?au(e,t):void 0;return t&&Un(!1),r}function au(e,t){const n=e.type;e.accessCache=Object.create(null),e.proxy=new Proxy(e.ctx,Tr);const{setup:s}=n;if(s){Pt();const o=e.setupContext=s.length>1?uu(e):null,l=Qn(e),r=Jn(s,e,0,[e.props,o]),u=zi(r);if(Ot(),l(),(u||e.sp)&&!Dn(e)&&xl(e),u){if(r.then(bi,bi),t)return r.then(a=>{Un(!0);try{wi(e,a,t)}finally{Un(!1)}}).catch(a=>{Ls(a,e,0)});e.asyncDep=r}else wi(e,r)}else Jl(e)}function wi(e,t,n){ne(t)?e.type.__ssrInlineRender?e.ssrRender=t:e.render=t:ge(t)&&(e.setupState=vl(t)),Jl(e)}function Jl(e,t,n){const s=e.type;e.render||(e.render=s.render||mt);{const o=Qn(e);Pt();try{Ar(e)}finally{Ot(),o()}}}const ru={get(e,t){return Ie(e,"get",""),e[t]}};function uu(e){const t=n=>{e.exposed=n||{}};return{attrs:new Proxy(e.attrs,ru),slots:e.slots,emit:e.emit,expose:t}}function js(e){return e.exposed?e.exposeProxy||(e.exposeProxy=new Proxy(vl(Ja(e.exposed)),{get(t,n){if(n in t)return t[n];if(n in Ln)return Ln[n](e)},has(t,n){return n in t||n in Ln}})):e.proxy}function cu(e,t=!0){return ne(e)?e.displayName||e.name:e.name||t&&e.__name}function du(e){return ne(e)&&"__vccOpts"in e}const k=(e,t)=>tr(e,t,Vn),fu="3.5.43";let vo;const _i=typeof window<"u"&&window.trustedTypes;if(_i)try{vo=_i.createPolicy("vue",{createHTML:e=>e})}catch{}const Xl=vo?e=>vo.createHTML(e):e=>e,pu="http://www.w3.org/2000/svg",hu="http://www.w3.org/1998/Math/MathML",$t=typeof document<"u"?document:null,ki=$t&&$t.createElement("template"),vu={insert:(e,t,n)=>{t.insertBefore(e,n||null)},remove:e=>{const t=e.parentNode;t&&t.removeChild(e)},createElement:(e,t,n,s)=>{const o=t==="svg"?$t.createElementNS(pu,e):t==="mathml"?$t.createElementNS(hu,e):n?$t.createElement(e,{is:n}):$t.createElement(e);return e==="select"&&s&&s.multiple!=null&&o.setAttribute("multiple",s.multiple),o},createText:e=>$t.createTextNode(e),createComment:e=>$t.createComment(e),setText:(e,t)=>{e.nodeValue=t},setElementText:(e,t)=>{e.textContent=t},parentNode:e=>e.parentNode,nextSibling:e=>e.nextSibling,querySelector:e=>$t.querySelector(e),setScopeId(e,t){e.setAttribute(t,"")},insertStaticContent(e,t,n,s,o,l){const r=n?n.previousSibling:t.lastChild;if(o&&(o===l||o.nextSibling))for(;t.insertBefore(o.cloneNode(!0),n),!(o===l||!(o=o.nextSibling)););else{ki.innerHTML=Xl(s==="svg"?`${e}`:s==="mathml"?`${e}`:e);const u=ki.content;if(s==="svg"||s==="mathml"){const a=u.firstChild;for(;a.firstChild;)u.appendChild(a.firstChild);u.removeChild(a)}t.insertBefore(u,n)}return[r?r.nextSibling:t.firstChild,n?n.previousSibling:t.lastChild]}},mu=Symbol("_vtc");function gu(e,t,n){const s=e[mu];s&&(t=(t?[t,...s]:[...s]).join(" ")),t==null?e.removeAttribute("class"):n?e.setAttribute("class",t):e.className=t}const $i=Symbol("_vod"),yu=Symbol("_vsh"),bu=Symbol(""),wu=/(?:^|;)\s*display\s*:/;function _u(e,t,n){const s=e.style,o=xe(n);let l=!1;if(n&&!o){if(t)if(xe(t))for(const r of t.split(";")){const u=r.slice(0,r.indexOf(":")).trim();n[u]==null&&Cn(s,u,"")}else for(const r in t)n[r]==null&&Cn(s,r,"");for(const r in n){r==="display"&&(l=!0);const u=n[r];u!=null?$u(e,r,!xe(t)&&t?t[r]:void 0,u)||Cn(s,r,u):Cn(s,r,"")}}else if(o){if(t!==n){const r=s[bu];r&&(n+=";"+r),s.cssText=n,l=wu.test(n)}}else t&&e.removeAttribute("style");$i in e&&(e[$i]=l?s.display:"",e[yu]&&(s.display="none"))}const ls=/\s*!important$/;function Cn(e,t,n){if(ee(n))n.forEach(s=>Cn(e,t,s));else if(n==null&&(n=""),t.startsWith("--"))ls.test(n)?e.setProperty(t,n.replace(ls,""),"important"):e.setProperty(t,n);else{const s=ku(e,t);ls.test(n)?e.setProperty(Yt(s),n.replace(ls,""),"important"):e[s]=n}}const xi=["Webkit","Moz","ms"],Js={};function ku(e,t){const n=Js[t];if(n)return n;let s=Be(t);if(s!=="filter"&&s in e)return Js[t]=s;s=Os(s);for(let o=0;oXs||(Eu.then(()=>Xs=0),Xs=Date.now());function Ou(e,t){const n=s=>{if(!s._vts)s._vts=Date.now();else if(s._vts<=n.attached)return;const o=n.value;if(ee(o)){const l=s.stopImmediatePropagation;s.stopImmediatePropagation=()=>{l.call(s),s._stopped=!0};const r=o.slice(),u=[s];for(let a=0;ae.charCodeAt(0)===111&&e.charCodeAt(1)===110&&e.charCodeAt(2)>96&&e.charCodeAt(2)<123,Iu=(e,t,n,s,o,l)=>{const r=o==="svg";t==="class"?gu(e,s,r):t==="style"?_u(e,n,s):As(t)?Es(t)||Su(e,t,n,s,l):(t[0]==="."?(t=t.slice(1),!0):t[0]==="^"?(t=t.slice(1),!1):Mu(e,t,s,r))?(Ti(e,t,s),!e.tagName.includes("-")&&(t==="value"||t==="checked"||t==="selected")&&Ci(e,t,s,r,l,t!=="value")):e._isVueCE&&(Du(e,t)||e._def.__asyncLoader&&(/[A-Z]/.test(t)||!xe(s)))?Ti(e,Be(t),s,l,t):(t==="true-value"?e._trueValue=s:t==="false-value"&&(e._falseValue=s),Ci(e,t,s,r))};function Mu(e,t,n,s){if(s)return!!(t==="innerHTML"||t==="textContent"||t in e&&Ei(t)&&ne(n));if(t==="spellcheck"||t==="draggable"||t==="translate"||t==="autocorrect"||t==="sandbox"&&e.tagName==="IFRAME"||t==="form"||t==="list"&&e.tagName==="INPUT"||t==="type"&&e.tagName==="TEXTAREA")return!1;if(t==="width"||t==="height"){const o=e.tagName;if(o==="IMG"||o==="VIDEO"||o==="CANVAS"||o==="SOURCE")return!1}return Ei(t)&&xe(n)?!1:t in e}function Du(e,t){const n=e._def.props;if(!n)return!1;const s=Be(t);return Array.isArray(n)?n.some(o=>Be(o)===s):Object.keys(n).some(o=>Be(o)===s)}const mn=e=>{const t=e.props["onUpdate:modelValue"]||!1;return ee(t)?n=>rs(t,n):t};function Lu(e){e.target.composing=!0}function Pi(e){const t=e.target;t.composing&&(t.composing=!1,t.dispatchEvent(new Event("input")))}const vt=Symbol("_assign"),as=Symbol("_initialValue");function Qs(e,t,n){return t&&(e=e.trim()),n&&(e=Is(e)),e}const Je={created(e,{modifiers:{lazy:t,trim:n,number:s}},o){e.parentNode&&(e.type==="text"?e[as]=e.defaultValue.replace(/[\r\n]/g,""):e.type==="textarea"&&(e[as]=e.defaultValue.replace(/\r\n?/g,` -`))),e[vt]=mn(o);const l=s||o.props&&o.props.type==="number";jt(e,t?"change":"input",r=>{r.target.composing||e[vt](Qs(e.value,n,l))}),(n||l)&&jt(e,"change",()=>{e.value=Qs(e.value,n,l)}),t||(jt(e,"compositionstart",Lu),jt(e,"compositionend",Pi),jt(e,"change",Pi))},mounted(e,{value:t,modifiers:{trim:n,number:s}}){const o=t??"",l=e[as];delete e[as],l!==void 0&&(e.type==="text"||e.type==="textarea")&&e.value!==l?e[vt](Qs(e.value,n,s)):e.value=o},beforeUpdate(e,{value:t,oldValue:n,modifiers:{lazy:s,trim:o,number:l}},r){if(e[vt]=mn(r),e.composing)return;const u=(l||e.type==="number")&&!/^0\d/.test(e.value)?Is(e.value):e.value,a=t??"";if(u===a)return;const c=e.getRootNode();(c instanceof Document||c instanceof ShadowRoot)&&c.activeElement===e&&e.type!=="range"&&(s&&t===n||o&&e.value.trim()===a)||(e.value=a)}},Oi={created(e,{value:t},n){e.checked=yt(t,n.props.value),e[vt]=mn(n),jt(e,"change",()=>{e[vt](Wn(e))})},beforeUpdate(e,{value:t,oldValue:n},s){e[vt]=mn(s),t!==n&&(e.checked=yt(t,s.props.value))}},_s={deep:!0,created(e,{value:t,modifiers:{number:n}},s){e._modelValue=t,jt(e,"change",()=>{const o=Array.prototype.filter.call(e.options,a=>a.selected).map(a=>n?Is(Wn(a)):Wn(a)),l=e.multiple,r=l?sn(e._modelValue)?new Set(o):o:o[0],u=e._pendingValue=[l,l?ee(r)?o.slice():o:r];try{e[vt](r)}finally{Lo(()=>{e._pendingValue===u&&(e._pendingValue=void 0)})}}),e[vt]=mn(s)},mounted(e,{value:t}){Ii(e,t)},beforeUpdate(e,{value:t},n){e._modelValue=t,e[vt]=mn(n)},updated(e,{value:t}){const n=e._pendingValue;e._pendingValue=void 0,(!n||n[0]!==e.multiple||!Fu(t,n[1],n[0]))&&Ii(e,t)}};function Fu(e,t,n){if(!n||ee(e))return yt(e,t);if(sn(e)){if(e.size!==t.length)return!1;for(const s of t)if(!e.has(s))return!1;return!0}return!1}function Ii(e,t){const n=e.multiple,s=ee(t);if(!(n&&!s&&!sn(t))){for(let o=0,l=e.options.length;oString(c)===String(u)):r.selected=Ea(t,u)>-1}else r.selected=t.has(u);else if(yt(Wn(r),t)){e.selectedIndex!==o&&(e.selectedIndex=o);return}}!n&&e.selectedIndex!==-1&&(e.selectedIndex=-1)}}function Wn(e){return"_value"in e?e._value:e.value}const Hu=["ctrl","shift","alt","meta"],Ru={stop:e=>e.stopPropagation(),prevent:e=>e.preventDefault(),self:e=>e.target!==e.currentTarget,ctrl:e=>!e.ctrlKey,shift:e=>!e.shiftKey,alt:e=>!e.altKey,meta:e=>!e.metaKey,left:e=>"button"in e&&e.button!==0,middle:e=>"button"in e&&e.button!==1,right:e=>"button"in e&&e.button!==2,exact:(e,t)=>Hu.some(n=>e[`${n}Key`]&&!t.includes(n))},Ft=(e,t)=>{if(!e)return e;const n=e._withMods||(e._withMods={}),s=t.join(".");return n[s]||(n[s]=((o,...l)=>{for(let r=0;r{const n=e._withKeys||(e._withKeys={}),s=t.join(".");return n[s]||(n[s]=(o=>{if(!("key"in o))return;const l=Yt(o.key);if(t.some(r=>r===l||Nu[r]===l))return e(o)}))},ju=Oe({patchProp:Iu},vu);let Mi;function Bu(){return Mi||(Mi=zr(ju))}const Uu=((...e)=>{const t=Bu().createApp(...e),{mount:n}=t;return t.mount=s=>{const o=Wu(s);if(!o)return;const l=t._component;!ne(l)&&!l.render&&!l.template&&(l.template=o.innerHTML),o.nodeType===1&&(o.textContent="");const r=n(o,!1,Vu(o));return o instanceof Element&&(o.removeAttribute("v-cloak"),o.setAttribute("data-v-app","")),r},t});function Vu(e){if(e instanceof SVGElement)return"svg";if(typeof MathMLElement=="function"&&e instanceof MathMLElement)return"mathml"}function Wu(e){return xe(e)?document.querySelector(e):e}const Ku=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],qu=["Su","Mo","Tu","We","Th","Fr","Sa"],Zl={clock:"clock-outline",analog:"clock-outline",date:"calendar"},He=e=>JSON.stringify(e),ke=e=>String.fromCodePoint(parseInt(e,16));function Bo(e,t=new Date){let n=t.getHours();return e||(n=n%12||12),`${String(n).padStart(2,"0")}:${String(t.getMinutes()).padStart(2,"0")}`}const Uo=(e=new Date)=>`${qu[e.getDay()]} ${e.getDate()} ${Ku[e.getMonth()]}`;function Yu(e,t=Math.floor(Date.now()/1e3)){const n=t-e,s=Math.abs(n),o=l=>Math.floor(s/l);return n<0?s<3600?`In ${Math.max(1,o(60))} min`:s<86400?o(3600)===1?"In 1 hour":`In ${o(3600)} hours`:s<172800?"Tomorrow":`In ${o(86400)} days`:s<60?"Just now":s<3600?`${o(60)} min ago`:s<86400?o(3600)===1?"1 hour ago":`${o(3600)} hours ago`:s<172800?"Yesterday":s<604800?`${o(86400)} days ago`:s<2592e3?o(604800)===1?"1 week ago":`${o(604800)} weeks ago`:s<31536e3?o(2592e3)===1?"1 month ago":`${o(2592e3)} months ago`:o(31536e3)===1?"1 year ago":`${o(31536e3)} years ago`}const zu={guition:{width:448,top:36,name:27,text:21,icon:26},cyd:{width:298,top:24,name:18,text:14,icon:18}},Di=document.createElement("canvas").getContext("2d"),mo=new Map,Gu=()=>mo.clear();function Zt(e,t){const n=`${t}|${e}`;let s=mo.get(n);if(!s){Di.font=t;const o=Di.measureText(e);s={left:-o.actualBoundingBoxLeft,right:o.actualBoundingBoxRight,top:-o.actualBoundingBoxAscent,bottom:o.actualBoundingBoxDescent,advance:o.width},mo.set(n,s)}return s}const Ju=e=>({name:`500 ${e.name}px "Bar Roboto"`,text:`400 ${e.text}px "Bar Roboto"`,icon:`${e.icon}px "Tile Icons"`});function Xu(e){return{icon:Math.max(2,Math.floor((e*4+5)/10)),item:Math.max(6,Math.floor((e*125+50)/100)),name:Math.max(8,Math.floor((e*16+5)/10))}}function ea(e,t,n,s){const o=Ju(t),l=Zt("0",o.text),r=Math.round(l.bottom-l.top),u=Xu(r),a=Zt(String.fromCodePoint(983376),o.icon),c=Math.round(a.bottom-a.top),f=e.map((m,H)=>{const C=s(m),L={index:H,item:m,view:C,shown:C.shown,width:0};return C.analog?(L.dial=c,L.width=c,L):(C.icon&&(L.icon={glyph:ke(C.icon),ink:Zt(ke(C.icon),o.icon)},L.width+=L.icon.ink.right-L.icon.ink.left),C.text&&(L.text={value:C.text,ink:Zt(C.text,o.text)},L.width+=(L.icon?u.icon:0)+L.text.ink.right-L.text.ink.left),L)}),b=f.filter(m=>m.shown),A=Zt(n,o.name).advance,D=Math.min(A,Math.floor(t.width*35/100)),I=m=>m.reduce((H,C)=>H+C.width,0)+Math.max(0,m.length-1)*u.item;let R=0;for(;Rt.width;)R++;const T=b.slice(R),$=new Set(b.slice(0,R).map(m=>m.index));let x=t.width-I(T);for(const m of T)m.x=x,x+=m.width+u.item;const w=T.length?T[0].x-u.name:t.width;return{metrics:t,fonts:o,cap:r,zero:l,gaps:u,parts:f,placed:T,dropped:$,nameText:n,natural:A,nameRoom:w}}function Qu(e,t,n){if(Zt(e,t).advance<=n)return e;const s=[...e];for(;s.length&&Zt(s.join("")+"...",t).advance>n;)s.pop();return s.join("")+"..."}function Zu(e){"fonts"in document&&Promise.all([document.fonts.load('500 27px "Bar Roboto"',"Studio 0"),document.fonts.load('400 21px "Bar Roboto"',"Away 0"),document.fonts.load('26px "Tile Icons"',String.fromCodePoint(983376))]).then(()=>{Gu(),e()}).catch(()=>{})}let ta="";function ec(e){ta=e||""}async function Vo(e,t={}){const n=await fetch(`api/${e}`,{...t,headers:{"Content-Type":"application/json","X-Screen-CSRF":ta,...t.headers}});if(!n.ok){let s="That didn't work. Refresh the page and try again.";try{s=(await n.json()).error||s}catch{}throw new Error(s)}return n}const Mt=async e=>(await Vo(e)).json(),it=async(e,t,n,s={})=>{const l=await(await Vo(e,{method:t,body:n===void 0?void 0:JSON.stringify(n),...s})).text();return l?JSON.parse(l):null},Et=6,gn=8,Wo=gn*Et,Qe=e=>e.options?.size==="wide",Fn=(e,t)=>t?[e,e+1]:[e],go=e=>e-e%2,ks=e=>Math.floor(e/Et),wt=e=>e.tiles.map(t=>({tile:t,slot:t.slot}));function na(e){let t=0;return e.map(n=>{const s=Qe(n);s&&t%2===1&&t++;const o=t;return t+=s?2:1,o})}function tc(e){const t=na(e);return e.some((n,s)=>n.slot!==t[s])}function Ko(e){if(e.tiles.some(t=>!Number.isInteger(t.slot))){const t=na(e.tiles);e.tiles.forEach((n,s)=>n.slot=t[s])}e.tiles.sort((t,n)=>t.slot-n.slot)}function qo(e){const t=new Set;for(const{tile:n,slot:s}of e)for(const o of Fn(s,Qe(n)))t.add(o);return t}const Kn=(e,t,n)=>Number.isInteger(t)&&t>=0&&t+(n?1:0)!e.has(s));function nc(e,t){for(let n=0;no.includes(c))?u.push(a):r.push({tile:a,slot:a.slot}));for(const a of u){const c=Qe(a),f=qo(r);let b=l.map(A=>c?go(A):A).find(A=>Kn(f,A,c));if(b===void 0&&(b=sa(f,c,a.slot)),b<0)return null;r.push({tile:a,slot:b})}return r.sort((a,c)=>a.slot-c.slot)}function zt(e,t=1){const n=Math.max(0,...e.map(({tile:s,slot:o})=>o+(Qe(s)?2:1)));return Math.min(gn,Math.max(1,Math.ceil(n/Et),t||1))}function sc(e){const t=e.split(".")[0];return t==="sun"?{options:{display:"sunpath",size:"wide"}}:t==="weather"?{options:{display:"forecast",size:"wide"}}:t==="screen"?{options:{display:"digital",size:"wide"}}:{}}const ia=e=>({entity:e,name:"",slot:-1,...sc(e)});function la(e,t){const n=e.entity.split(".")[0],s=t.controls?.[n],o=e.options||{};if(!s||o.size!=="wide"||(o.display||"standard")!=="standard"||o.inline==="slider")return null;const l=o.controls??s.default;return l==="none"?null:l}function oc(e,t){const n=la(e,t);return n?t.controls?.[e.entity.split(".")[0]]?.choices.find(s=>s.key===n)?.label.toLocaleLowerCase()||n:"none"}const yo=e=>(/^(\d+)\.(\d+)\.(\d+)$/.exec(e||"")||[]).slice(1).map(Number);function bo(e,t){const[n,s]=[yo(e),yo(t)];if(n.length!==3||s.length!==3)return!1;for(let o=0;o<3;o++)if(n[o]!==s[o])return n[o]>s[o];return!0}const ic=(e,t,n,s)=>bo(e,`${t}.${n}.${s}`);function lc(e){const t=yo(e);return t.length!==3?10:t[0]>0||t[1]>2||t[1]===2&&t[2]>=7?20:10}const aa={standard:"standard",watch:"large value",forecast:"weather forecast",graph:"graph",digital:"digital clock",analog:"analog clock",sunpath:"sun path"},Li=["light","switch","input_boolean","fan","media_player","climate"],ac=["light","fan","cover","number","input_number","media_player"],rc={light:["Light","☀","#ad7600","#fff3d3"],climate:["Climate","❄","#c86620","#ffebdc"],vacuum:["Vacuum","◉","#008577","#def3ed"],fan:["Fan","✣","#008aab","#def5fa"],cover:["Cover","▤","#8053af","#eee5f8"],media_player:["Media","▶","#007cad","#def2fc"],sensor:["Sensor","⌁","#3476b1","#e5effa"],binary_sensor:["Status","◈","#ad7600","#fff3d3"],switch:["Switch","⏻","#ad7600","#fff3d3"],input_boolean:["Switch","⏻","#ad7600","#fff3d3"],scene:["Scene","✦","#8053af","#eee5f8"],script:["Script","▷","#8053af","#eee5f8"],weather:["Weather","☁","#007cad","#def2fc"],number:["Value","±","#008577","#def3ed"],input_number:["Value","±","#008577","#def3ed"],select:["Select","≡","#5862af","#eaecfa"],input_select:["Select","≡","#5862af","#eaecfa"],button:["Action","↗","#5862af","#eaecfa"],input_button:["Action","↗","#5862af","#eaecfa"],screen:["Clock","◷","#25282c","#e9ecf1"],sun:["Sun","☼","#c86620","#ffebdc"],timer:["Timer","⏱","#008577","#def3ed"],person:["Person","☺","#2f7d32","#e1f2e2"],camera:["Camera","◧","#3d4a57","#e6ebf0"],image:["Image","◧","#3d4a57","#e6ebf0"]},xt=e=>rc[e.split(".")[0]]||["Entity","◇","#637184","#edf0f4"],d=hn({inventory:{screens:[],entities:[]},connected:!1,reachable:!0,selected:null,layout:null,dirty:!1,busy:!1,saved:0,tab:"layout",selectedTile:null,inspector:null,iconPickerOpen:!1,actionPickerOpen:!1,actionSearch:"",insertAt:-1,filter:"",search:"",capabilities:{},entityActions:{},topbarPreviews:{},topbarAdded:null,topbarOverflow:[],settingEdits:{},settingPending:!1,updating:[],toast:null,now:Date.now(),fontsVersion:0,route:location.hash,overrideProfile:null,overrideFriendly:"",drag:{active:!1,moving:null,preview:null},menuOpen:!1}),qt=k(()=>d.inventory.screens.find(e=>e.id===d.selected)),ra=k(()=>qt.value?.firmware||""),fn=(e,t,n)=>ic(ra.value,e,t,n),Hn=k(()=>lc(ra.value)),Yo=k(()=>qt.value?.board==="guition"),ua=k(()=>zu[Yo.value?"guition":"cyd"]),Zs=k(()=>d.selectedTile&&d.layout?d.layout.tiles.find(e=>e.entity===d.selectedTile):void 0);let Fi=0;function Se(e,t){d.toast={message:e,action:t},clearTimeout(Fi),Fi=window.setTimeout(()=>d.toast=null,t?8e3:5e3)}function uc(){d.toast=null}async function dt(e,t,n="API key"){try{if(!navigator.clipboard||!window.isSecureContext)throw new Error;await navigator.clipboard.writeText(e),Se(`${n} copied.`)}catch{if(t){const s=document.createRange();s.selectNodeContents(t);const o=window.getSelection();o?.removeAllRanges(),o?.addRange(s)}Se(document.execCommand("copy")?`${n} copied.`:`${n} is selected. Copy with Ctrl+C or Command+C.`)}}function $s(){const e="/config/integrations/dashboard";try{window.top.location.assign(e)}catch{window.open(e,"_blank")}}const cc=["","#settings","#new-screen","#firmware","#alerts","#override"],tt=k(()=>cc.includes(d.route)?d.route:"");function De(e){if(location.hash===e){d.route=e;return}location.hash=e}window.addEventListener("hashchange",()=>{d.route=location.hash,window.scrollTo(0,0)});function Zn(e){return d.inventory.entities.find(t=>t.id===e)?.name||d.inventory.builtin?.find(t=>t.id===e)?.name||e}let eo={source:null,byName:{}};function es(e){return eo.source!==d.inventory.icons&&(eo={source:d.inventory.icons,byName:Object.fromEntries((d.inventory.icons?.groups||[]).flatMap(t=>t.icons.map(n=>[n.name,n])))}),e?eo.byName[e]:void 0}function on(e){const t=d.inventory.icons;if(!t)return"F0335";const n=d.inventory.entities.find(o=>o.id===e),s=e.split(".")[0];return t.builtin?.[e]?t.builtin[e]:n?.icon?n.icon:s==="weather"?t.weather[n?.state||""]||t.weather.partlycloudy:s==="sun"?t.sun[n?.state||""]||t.sun.below_horizon:t.defaults[s]||t.fallback}const wo=e=>es(e.options?.icon)?.cp||on(e.entity),to=new Set;async function zo(e){const t=[...new Set(e)].filter(n=>!to.has(n)&&!n.startsWith("screen."));if(t.length){t.forEach(n=>to.add(n));try{for(let n=0;n`entity=${encodeURIComponent(o)}`).join("&");Object.assign(d.capabilities,(await Mt(`capabilities?${s}`)).capabilities||{})}}catch{t.forEach(n=>to.delete(n))}}}const no=new Set;async function dc(e){if(!no.has(e)){no.add(e);try{d.entityActions[e]=(await Mt(`entity-actions?entity=${encodeURIComponent(e)}`)).actions}catch{no.delete(e)}}}function et(){d.dirty=!0,d.saved=0}function fc(e){if(e!==d.selected&&d.dirty&&!confirm("You have unsaved changes. Open a different screen anyway?"))return;e!==d.selected&&(Yn(),d.settingEdits={}),d.selected=e,d.selectedTile=null,d.inspector=null,d.tab="layout",d.menuOpen=!1;const t=d.inventory.screens.find(n=>n.id===e);if(!t){d.layout=null;return}d.layout=JSON.parse(JSON.stringify(t.layout)),Ko(d.layout),d.layout.pages=zt(wt(d.layout),d.layout.pages),d.insertAt=-1,d.dirty=!1,d.saved=0,Go(0),zo(d.layout.tiles.map(n=>n.entity)),De("")}function pc(e){const t=d.layout,n=t.tiles.map(o=>`${o.entity}@${o.slot}`).join();for(const{tile:o,slot:l}of e)o.slot=l,t.tiles.includes(o)||t.tiles.push(o);Ko(t),t.pages=zt(wt(t),t.pages);const s=t.tiles.map(o=>`${o.entity}@${o.slot}`).join()!==n;return s&&et(),s}function Bs(e,t){if(!d.layout)return!1;zo([e.entity]);const n=oa(d.layout.tiles,e,t);return n?pc(n):!1}function hc(e){const t=d.layout;if(!t||t.tiles.some(o=>o.entity===e)||t.tiles.length>=Hn.value)return;const n=ia(e),s=d.insertAt>=0?d.insertAt:nc(qo(wt(t)),Qe(n));d.insertAt=-1,s>=0&&Bs(n,s)&&_o(e)}function ca(e){const t=d.layout;if(!t)return;const n=t.tiles.indexOf(e);n<0||(t.tiles.splice(n,1),d.selectedTile===e.entity&&je(),et(),t.pages=zt(wt(t),t.pages),Se(`${e.name||Zn(e.entity)} removed`,{label:"Undo",run:()=>Bs(e,e.slot)}))}function Hi(){const e=d.layout;e&&(e.pages=Math.min(gn,zt(wt(e),e.pages)+1),et())}function vc(e){const t=d.layout;if(t){for(const n of t.tiles)ks(n.slot)>e&&(n.slot-=Et);t.pages=Math.max(1,zt(wt(t),t.pages)-1),et()}}function mc(){const e=d.layout;if(!e)return 1;const t=d.drag.preview||wt(e),n=zt(t,e.pages);return d.drag.active&&nu.key!=="none"&&o.controls.includes(u.key))?.key||"none"),et(),d.layout&&Qe(e)&&!l){const u=qo(wt(d.layout).filter(f=>f.tile!==e)),a=go(e.slot),c=Kn(u,a,!0)?a:sa(u,!0,a);c>=0&&(e.slot=c),Ko(d.layout),d.layout.pages=zt(wt(d.layout),d.layout.pages)}}function _o(e){d.selectedTile!==e&&(d.iconPickerOpen=!1,d.actionPickerOpen=!1,d.actionSearch=""),d.selectedTile=e,d.inspector={kind:"tile"},zo([e])}function Ct(e){d.inspector?.kind==="bar"&&d.inspector.index===e||(d.iconPickerOpen=!1),d.selectedTile=null,d.inspector={kind:"bar",index:e}}function Ri(){d.selectedTile=null,d.inspector={kind:"bar-add"}}function je(){d.inspector=null,d.selectedTile=null}async function gc(){if(!(d.busy||!d.layout||!d.selected)){d.busy=!0;try{const{settings:e,...t}=d.layout;await it(`screens/${encodeURIComponent(d.selected)}`,"PUT",t),d.dirty=!1,d.saved=Date.now(),Se("Saved. Your screen is being updated."),await ln()}catch(e){Se(e.message)}finally{d.busy=!1}}}const Dt=()=>d.layout?.header?.items??(d.layout?.settings?.show_clock??!0?[{type:"clock"}]:[]),Bt=()=>d.inventory.header?.max_items||6;function qn(e){d.layout&&(d.layout.header={items:e},et(),Go())}let Ni=0;function Go(e=150){clearTimeout(Ni),Ni=window.setTimeout(async()=>{const t=Dt();if(t.some(n=>n.type==="entity"))try{const n=await it("header-preview","POST",{header:{items:t}});t.forEach((s,o)=>d.topbarPreviews[He(s)]=n.items[o])}catch{}},e)}function Tn(e){return e.type==="entity"?Zn(e.entity):d.inventory.header?.builtin.find(t=>t.type===e.type)?.label||e.type}function Rt(e){const t=new Date(d.now);if(e.type==="clock")return{text:Bo(yn().clock_24h!==!1,t),shown:!0};if(e.type==="date")return{text:Uo(t),shown:!0};if(e.type==="analog")return{analog:!0,shown:!0};const n=d.topbarPreviews[He(e)];return n?{icon:n.i||null,text:n.k==="ago"?Yu(n.e,Math.floor(d.now/1e3)):n.t,color:n.c?`#${n.c}`:null,shown:n.shown}:{icon:e.icon==="none"?null:es(e.icon)?.cp||on(e.entity),text:"…",shown:!0,loading:!0}}function so(e,t){const n=[...Dt()];return t<0||t>=n.length||e===t?!1:(n.splice(t,0,...n.splice(e,1)),qn(n),!0)}function ji(e){const t=[...Dt()],[n]=t.splice(e,1);n&&(d.inspector?.kind==="bar"&&je(),qn(t),Se(`${Tn(n)} removed from the top bar`,{label:"Undo",run:()=>{const s=[...Dt()];s.splice(Math.min(e,s.length),0,n),qn(s)}}))}function oo(e){const t=Dt();if(t.length>=Bt())return Se(`The top bar has room for ${Bt()} items.`);if(t.some(n=>He(n)===He(e)))return Se("This is already in the top bar.");d.topbarAdded={key:He(e),time:Date.now()},qn([...t,e]),Ct(t.length)}const yc=[{title:"Brightness",icon:"F0599",rows:[{key:"brightness",label:"Brightness",kind:"number",min:5,max:100,step:5,unit:"%"},{key:"dark_mode",label:"Dark mode",kind:"toggle"},{key:"standby_enabled",label:"Auto standby",kind:"toggle"},{key:"standby_seconds",label:"Standby after",kind:"duration",min:60,max:86400,needs:"standby_enabled"},{key:"standby_brightness",label:"Standby brightness",kind:"number",min:0,max:100,step:5,unit:"%",needs:"standby_enabled",cap:"brightness"}]},{title:"Night",icon:"F0594",rows:[{key:"night_enabled",label:"Night mode",kind:"toggle"},{key:"night_start",label:"Starts",kind:"moment",needs:"night_enabled"},{key:"night_end",label:"Ends",kind:"moment",needs:"night_enabled"},{key:"night_brightness",label:"Night brightness",kind:"number",min:0,max:100,step:5,unit:"%",needs:"night_enabled",cap:"brightness"}]},{title:"Screen",icon:"F0379",rows:[{key:"clock_24h",label:"Clock",kind:"choice",options:[[!1,"12 hour"],[!0,"24 hour"]]},{key:"auto_home",label:"Back to page 1",kind:"toggle"},{key:"auto_home_seconds",label:"After",kind:"duration",min:30,max:3600,needs:"auto_home"},{key:"home_on_standby",label:"Also on standby",kind:"toggle"},{key:"swipe_pages",label:"Swipe between pages",kind:"toggle"},{key:"rotation",label:"Rotation",kind:"choice",options:[[0,"0°"],[90,"90°"],[180,"180°"],[270,"270°"]]}]}],da=4e3;let Ut={},pn=null,xs=0,ps=null;const Jo=()=>qt.value?.settings;function yn(){const e=Jo(),t={...e?.values||{}};for(const[n,s]of Object.entries(d.settingEdits))t[n]=s.value;return t}const bc=e=>e<300?30:e<900?60:e<3600?300:e<7200?900:1800;function Bi(e,t,n,s,o){if(e.kind==="moment"){let u=s&&t%60?Math.floor(t/60)*60+(n>0?60:0):t+n*(s?60:15);return u%=1440,u<0?u+1440:u}const l=e.kind==="duration"?bc(n<0?t-1:t):e.step,r=e.cap?Math.min(e.max,o[e.cap]):e.max;return Math.min(r,Math.max(e.min,t+n*l))}function wc(e){if(e<60)return`${e} sec`;if(e<3600)return`${Math.floor(e/60)} min`;const t=Math.floor(e/3600),n=Math.floor(e%3600/60);return n?`${t} h ${String(n).padStart(2,"0")}`:`${t} h`}function _c(e,t){const n=Math.floor(e/60),s=String(e%60).padStart(2,"0");return t?`${String(n).padStart(2,"0")}:${s}`:`${n%12||12}:${s} ${n<12?"AM":"PM"}`}function kc(e,t){const n=t[e.key];return n==null?"—":e.kind==="number"?`${n}${e.unit||""}`:e.kind==="duration"?wc(n):e.kind==="moment"?_c(n,t.clock_24h!==!1):""}function An(e,t,n){if(pn&&pn!==d.selected&&Object.keys(Ut).length){Yn(),Se("Still saving the other screen's settings. Try again in a moment.");return}pn=d.selected;const s=yn();if(d.settingEdits[e]={value:t,at:Date.now()},Ut[e]=t,e==="brightness")for(const o of["standby_brightness","night_brightness"])s[o]>t&&(d.settingEdits[o]={value:t,at:Date.now()});d.settingPending=!0,clearTimeout(xs),xs=window.setTimeout(()=>Yn(),n)}async function Yn(e=!1){if(clearTimeout(xs),ps||!Object.keys(Ut).length||!pn)return;const t=pn,n=Ut;Ut={};const s=Vo(`screens/${encodeURIComponent(t)}/settings`,{method:"PUT",body:JSON.stringify({settings:n}),keepalive:e});ps=s;try{const o=await(await s).json(),l=d.inventory.screens.find(r=>r.id===t);l&&(l.settings=o)}catch(o){if(Se(o.message),t===d.selected)for(const l of Object.keys(n))delete d.settingEdits[l];if(t===d.selected&&n.brightness!==void 0)for(const l of["standby_brightness","night_brightness"])delete d.settingEdits[l]}finally{ps=null,Object.keys(Ut).length?xs=window.setTimeout(()=>Yn(),150):pn=null,d.settingPending=!!Object.keys(Ut).length,t===d.selected&&Ss(),setTimeout(()=>{t===d.selected&&Ss()},da+100)}}function Ss(){const e=Jo();for(const[t,n]of Object.entries(d.settingEdits))Ut[t]!==void 0||ps||(e&&e.values[t]===n.value||Date.now()-n.at>da)&&delete d.settingEdits[t]}const $c={install:"Building and installing…",verify:"Waiting for the screen to come back…",settle:"Checking that it stays stable…"};async function Ui(e,t){d.updating.push(e.id);try{await it(`screens/${encodeURIComponent(e.id)}/update`,"POST",t?{host:t}:{}),await ln()}catch(n){d.updating=d.updating.filter(s=>s!==e.id),Se(n.message)}}async function Vi(){try{await it("updates/run","POST"),await ln()}catch(e){Se(e.message)}}async function xc(e){try{await it("updates","PUT",{auto:e}),d.inventory.updates&&(d.inventory.updates.auto=e),Se(e?"Screens will now update automatically at night.":"Automatic updates are off.")}catch(t){Se(t.message)}}async function Sc(){try{d.inventory.claude_skill=await it("claude-skill","POST"),Se(d.inventory.claude_skill?.restart?"Skill installed. Restart Claude Code once so it finds the new skills folder.":"Skill installed. Claude Code picks it up right away.")}catch(e){Se(e.message)}}async function ln(e=!0){try{const t=await Mt(e?"inventory":"inventory?light=1");d.inventory=e?t:{...d.inventory,...t},t.csrf&&ec(t.csrf),d.connected=!!d.inventory.connected,d.reachable=!0;for(const n of d.inventory.screens)n.update?.state==="running"&&(d.updating=d.updating.filter(s=>s!==n.id));d.selected&&Ss()}catch{d.reachable=!1}}function Cc(e){d.inventory={...d.inventory,...e},d.connected=!!d.inventory.connected;for(const t of d.inventory.screens)t.update?.state==="running"&&(d.updating=d.updating.filter(n=>n!==t.id));d.selected&&Ss()}let Wi=0,ko=Date.now(),Cs=!1,xn=null;function Tc(){xn||typeof EventSource>"u"||(xn=new EventSource("api/events"),xn.onopen=()=>{Cs=!0,zn()},xn.onmessage=e=>{document.hidden||Cc(JSON.parse(e.data))},xn.onerror=()=>{Cs=!1,zn()})}function zn(){clearTimeout(Wi);const e=Cs?6e4:d.inventory.updates?.busy?3e3:1e4;Wi=window.setTimeout(async()=>{if(!document.hidden){const t=Date.now()-ko>=3e5;t&&(ko=Date.now()),(t||!Cs)&&await ln(t)}zn()},e)}let Ki=!1;function Ac(){Ki||(Ki=!0,ln(),Tc(),zn(),Zu(()=>d.fontsVersion++),setInterval(()=>{!d.layout||document.hidden||d.drag.active||(d.now=Date.now(),Go(0))},3e4),document.addEventListener("visibilitychange",async()=>{document.hidden||(ko=Date.now(),d.now=Date.now(),await ln(),zn())}),window.addEventListener("pagehide",()=>Yn(!0)),window.addEventListener("beforeunload",e=>{d.dirty&&(e.preventDefault(),e.returnValue="")}))}const Ec={class:"side"},Pc={id:"screens"},Oc=["aria-current","onClick"],Ic={class:"txt"},Mc={key:0,class:"pill"},Dc={key:1,class:"spin small"},Lc=["onSubmit"],Fc=["disabled","title","onClick"],Hc={id:"pending"},Rc={class:"pending-actions"},Nc=["onClick"],jc=["aria-current"],Bc={class:"more"},Uc=["aria-current"],Vc={class:"mdi"},Wc=["aria-current"],Kc={class:"mdi"},qc=["aria-current"],Yc={class:"mdi"},zc=$e({__name:"Sidebar",setup(e){const t=fe(null),n=fe("");function s(u){const a=u.update||{};return a.state==="running"||d.updating.includes(u.id)?{kind:"running",text:$c[a.phase||""]||"Starting update…"}:a.state==="queued"?{kind:"queued",text:"Queued for the update"}:a.available&&u.online?{kind:"available",text:`Update ${a.target}`}:a.result&&Date.now()/1e3-a.result.time<86400?{kind:a.result.state==="failed"?"failed":"done",text:a.result.message}:null}function o(u){const a=u.update||{};a.host&&a.profile?Ui(u):a.profile&&(t.value=u.id,n.value="")}function l(u){const a=n.value.trim();a&&(t.value=null,Ui(u,a))}const r=u=>u.installed?"Installed, but not yet in Home Assistant. Add the discovered ESPHome device under Settings → Devices & services, paste the API key there, and turn on “Allow the device to perform Home Assistant actions” under Configure.":u.downloaded?"Firmware downloaded, not yet in Home Assistant. Put it on the screen with ESPHome Web, then add the discovered ESPHome device under Settings → Devices & services, paste the API key there, and allow the Home Assistant actions under Configure.":`Not yet in Home Assistant. Already flashed? Add the ESPHome device under Settings → Devices & services, then allow the Home Assistant actions under Configure. Not flashed yet? Firmware & USB → ${u.file}.`;return(u,a)=>(h(),g("aside",Ec,[a[16]||(a[16]=i("div",{class:"brand"},[i("span",{class:"mark"},"▦"),i("span",null,"ESP Screens")],-1)),i("span",{id:"connection",class:re(["conn",{online:v(d).connected}]),role:"status"},y(v(d).reachable?v(d).connected?"Home Assistant connected":"Reconnecting to Home Assistant…":"Management page unreachable · retrying…"),3),a[17]||(a[17]=i("div",{class:"label"},"Screens",-1)),i("div",Pc,[(h(!0),g(W,null,le(v(d).inventory.screens,c=>(h(),g("div",{key:c.id,class:re(["screen-item",{selected:c.id===v(d).selected&&v(tt)===""}])},[i("button",{type:"button",class:"nav-item","aria-current":c.id===v(d).selected&&v(tt)===""?"true":"false",onClick:f=>v(fc)(c.id)},[i("span",{class:re(["dot",{off:!c.online}])},null,2),i("span",Ic,[i("span",null,y(c.name),1),i("small",null,y(c.online?"Online":"Offline")+y(c.area?" · "+c.area:"")+" · "+y(c.firmware||"unknown"),1)]),s(c)?.kind==="available"?(h(),g("span",Mc,"Update")):s(c)?.kind==="running"?(h(),g("span",Dc)):V("",!0)],8,Oc),s(c)?(h(),g("div",{key:0,class:re(["screen-update",s(c).kind])},[s(c).kind==="available"?(h(),g(W,{key:0},[t.value===c.id?(h(),g(W,{key:0},[a[9]||(a[9]=i("small",null,"The IP address, once; new firmware reports it itself.",-1)),i("form",{class:"screen-host",onSubmit:Ft(f=>l(c),["prevent"])},[Te(i("input",{"onUpdate:modelValue":a[0]||(a[0]=f=>n.value=f),placeholder:"IP address, e.g. 192.168.1.50",required:"",pattern:"[A-Za-z0-9][A-Za-z0-9.\\-]*","aria-label":"IP address",autofocus:""},null,512),[[Je,n.value]]),a[8]||(a[8]=i("button",{type:"submit",class:"btn mini primary"},"Start",-1)),i("button",{type:"button",class:"icon-btn","aria-label":"Cancel",onClick:a[1]||(a[1]=f=>t.value=null)},"✕")],40,Lc)],64)):(h(),g(W,{key:1},[i("small",null,y(s(c).text),1),i("button",{type:"button",class:"btn mini primary",disabled:!c.update?.profile,title:c.update?.profile?"":"No ESPHome profile found with this device name.",onClick:f=>o(c)},"Update",8,Fc)],64))],64)):(h(),g("small",{key:1,class:re({failed:s(c).kind==="failed"})},y(s(c).text),3))],2)):V("",!0)],2))),128))]),i("div",Hc,[(h(!0),g(W,null,le(v(d).inventory.pending||[],c=>(h(),g("div",{key:c.file,class:"pending"},[i("strong",null,y(c.friendly),1),i("small",null,y(r(c)),1),i("div",Rc,[i("button",{type:"button",class:"btn mini quiet",onClick:a[2]||(a[2]=(...f)=>v($s)&&v($s)(...f))},"Open Devices & services"),c.api_key?(h(),g("button",{key:0,type:"button",class:"btn mini quiet",onClick:f=>v(dt)(c.api_key)},"Copy API key",8,Nc)):V("",!0)])]))),128))]),i("button",{id:"new-screen",type:"button",class:"nav-item ghost","aria-current":v(tt)==="#new-screen"?"true":"false",onClick:a[3]||(a[3]=c=>v(De)("#new-screen"))},[...a[10]||(a[10]=[i("span",{class:"plus"},"+",-1),i("span",{class:"txt"},"New screen",-1)])],8,jc),a[18]||(a[18]=i("div",{class:"spacer"},null,-1)),i("div",Bc,[a[15]||(a[15]=i("div",{class:"label"},"More",-1)),i("button",{id:"open-firmware",type:"button",class:"nav-item","aria-current":v(tt)==="#firmware"?"true":"false",onClick:a[4]||(a[4]=c=>v(De)("#firmware"))},[i("span",Vc,y(v(ke)("F0241")),1),a[11]||(a[11]=i("span",{class:"txt"},"Firmware & USB",-1))],8,Uc),i("button",{id:"open-alerts",type:"button",class:"nav-item","aria-current":v(tt)==="#alerts"?"true":"false",onClick:a[5]||(a[5]=c=>v(De)("#alerts"))},[i("span",Kc,y(v(ke)("F0594")),1),a[12]||(a[12]=i("span",{class:"txt"},"Alerts",-1))],8,Wc),i("button",{id:"open-settings",type:"button",class:"nav-item","aria-current":v(tt)==="#settings"?"true":"false",onClick:a[6]||(a[6]=c=>v(De)("#settings"))},[i("span",Yc,y(v(ke)("F0493")),1),a[13]||(a[13]=i("span",{class:"txt"},"Settings",-1))],8,qc),i("button",{id:"refresh",type:"button",class:"nav-item ghost",onClick:a[7]||(a[7]=c=>v(ln)())},[...a[14]||(a[14]=[i("span",{class:"plus"},"↻",-1),i("span",{class:"txt"},"Refresh",-1)])])])]))}}),Gc={key:0,id:"toast",class:"toast",role:"status"},Jc=$e({__name:"Toast",setup(e){return(t,n)=>v(d).toast?(h(),g("div",Gc,[i("span",null,y(v(d).toast.message),1),v(d).toast.action?(h(),g("button",{key:0,type:"button",onClick:n[0]||(n[0]=s=>{v(d).toast.action.run(),v(uc)()})},y(v(d).toast.action.label),1)):V("",!0)])):V("",!0)}}),Z={source:null,element:null,ghost:null,timer:0,start:null,offset:{x:0,y:0},pointerId:null,suppressUntil:0,last:null,scroller:0,target:null},fa={mounted(e,t){e.__dragSource=t.value,e.addEventListener("pointerdown",s=>{const o=e.__dragSource;if(!(s.button!==0||e.disabled||s.target.closest(".remove"))){s.pointerType!=="touch"&&s.preventDefault(),Object.assign(Z,{source:o,element:e,start:{x:s.clientX,y:s.clientY},pointerId:s.pointerId});try{e.setPointerCapture(s.pointerId)}catch{}clearTimeout(Z.timer),s.pointerType==="touch"&&(Z.timer=window.setTimeout(()=>qi(s),260))}}),e.addEventListener("pointermove",s=>{if(d.drag.active||!Z.start||Z.element!==e)return;const o=Math.hypot(s.clientX-Z.start.x,s.clientY-Z.start.y);if(s.pointerType==="touch"){o>10&&(clearTimeout(Z.timer),Z.start=null);return}o>=6&&qi(s)});const n=()=>{Z.element===e&&!d.drag.active&&(clearTimeout(Z.timer),Z.start=null)};e.addEventListener("pointerup",n),e.addEventListener("pointercancel",n)},updated(e,t){e.__dragSource=t.value}};function qi(e){if(d.drag.active||!Z.start||!Z.source||!Z.element)return;d.drag.active=!0,d.drag.moving=Z.source.kind==="tile"?Z.source.tile:ia(Z.source.id),d.drag.preview=null,Z.target=null,getSelection()?.removeAllRanges();const t=Z.element.getBoundingClientRect(),n=Z.element.cloneNode(!0);n.classList.add("drag-ghost"),n.style.width=`${t.width}px`,n.style.height=`${t.height}px`,Z.offset={x:e.clientX-t.left,y:e.clientY-t.top},document.body.append(n),Z.ghost=n,document.addEventListener("pointermove",$o),document.addEventListener("pointerup",Ts),document.addEventListener("pointercancel",Ts);try{Z.element.releasePointerCapture(Z.pointerId)}catch{}try{document.documentElement.setPointerCapture(Z.pointerId)}catch{}document.addEventListener("touchmove",pa,{passive:!1}),Z.scroller=window.setInterval(()=>{if(!Z.last)return;const s=document.querySelector(".canvas");if(!s)return;const o=s.getBoundingClientRect(),l=Z.last.xo.right-60?12:0,r=Z.last.yo.bottom-60?12:0;(l||r)&&(s.scrollBy(l,r),xo(ha(Z.last.x,Z.last.y)))},16),xo(-1),$o(e)}function pa(e){d.drag.active&&e.preventDefault()}function Ts(e){e.pointerId===Z.pointerId&&Xc(e.type==="pointerup")}function $o(e){!Z.ghost||e.pointerId!==Z.pointerId||(Z.last={x:e.clientX,y:e.clientY},Z.ghost.style.transform=`translate(${e.clientX-Z.offset.x}px, ${e.clientY-Z.offset.y}px)`,xo(ha(e.clientX,e.clientY)))}function ha(e,t){let n=null,s=1/0;for(const l of document.querySelectorAll(".pages [data-slot]")){const r=l.getBoundingClientRect(),u=Math.hypot(Math.max(r.left-e,0,e-r.right),Math.max(r.top-t,0,t-r.bottom));u16)return-1;let o=Number(n.cell.dataset.slot);return n.cell.classList.contains("wide")&&e>(n.r.left+n.r.right)/2&&(o+=1),o}function xo(e){Z.target===e||!d.layout||!d.drag.moving||(Z.target=e,d.drag.preview=e>=0?oa(d.layout.tiles,d.drag.moving,e):null)}function Xc(e){const t=d.drag.preview,n=d.drag.moving;document.removeEventListener("pointermove",$o),document.removeEventListener("pointerup",Ts),document.removeEventListener("pointercancel",Ts),document.removeEventListener("touchmove",pa);try{document.documentElement.releasePointerCapture(Z.pointerId)}catch{}if(Z.ghost?.remove(),Object.assign(Z,{ghost:null,suppressUntil:Date.now()+400,last:null,start:null,target:null,element:null,source:null}),clearInterval(Z.scroller),d.drag.active=!1,d.drag.preview=null,d.drag.moving=null,e&&t&&n&&d.layout){const s=d.layout.tiles.map(o=>`${o.entity}@${o.slot}`).join();for(const{tile:o,slot:l}of t)o.slot=l,d.layout.tiles.includes(o)||d.layout.tiles.push(o);d.layout.tiles.sort((o,l)=>o.slot-l.slot),d.layout.tiles.map(o=>`${o.entity}@${o.slot}`).join()!==s&&et(),s.includes(`${n.entity}@`)||Bs(n,n.slot)}}window.addEventListener("click",e=>{Date.now()t.tile.name||Zn(t.tile.entity)),s=k(()=>Qe(t.tile)),o=k(()=>d.inventory.backgrounds?.[t.tile.options?.background||""]?.color),l=k(()=>t.tile.options?.background==="none"),r=k(()=>t.tile.options?.display||"standard"),u=k(()=>r.value!=="standard"?aa[r.value]||r.value:""),a=k(()=>la(t.tile,d.inventory)),c=k(()=>t.tile.entity.split(".")[0]),f=k(()=>d.inventory.icons?.controls||{}),b=w=>f.value[w]?ke(f.value[w]):"",A=k(()=>d.selectedTile===t.tile.entity&&d.inspector?.kind==="tile"),D=k(()=>!t.placeholder&&d.layout?.tiles.includes(t.tile)),I=k(()=>`${n.value}, slot ${t.slot%Et+1} on page ${ks(t.slot)+1}. Enter: configure, arrow keys: move`),R=k(()=>new Date(d.now)),T=k(()=>(R.value.getHours()%12+R.value.getMinutes()/60)*30),$=k(()=>R.value.getMinutes()*6);async function x(w){if(w.key==="Enter"||w.key===" "){w.preventDefault(),_o(t.tile.entity);return}const m={ArrowLeft:-1,ArrowRight:1,ArrowUp:-2,ArrowDown:2}[w.key];m&&(w.preventDefault(),Bs(t.tile,t.tile.slot+(s.value?Math.sign(m)*2:m))&&(await Lo(),document.querySelector(`.pages [data-slot="${t.tile.slot}"]`)?.focus()))}return(w,m)=>Te((h(),g("div",{class:re(["tile",{wide:s.value,bare:l.value,placeholder:e.placeholder||!D.value,chosen:A.value}]),"data-slot":e.slot,style:Ne(o.value&&!l.value?{backgroundColor:o.value}:void 0),tabindex:D.value?0:-1,role:D.value?"button":void 0,"aria-label":D.value?I.value:void 0,onClick:m[1]||(m[1]=H=>D.value&&v(_o)(e.tile.entity)),onKeydown:m[2]||(m[2]=H=>D.value&&x(H))},[r.value==="analog"?(h(),g(W,{key:0},[(h(),g("svg",Zc,[m[3]||(m[3]=i("circle",{cx:"30",cy:"30",r:"27",fill:"#fff",stroke:"#c9ccd1"},null,-1)),(h(),g(W,null,le([0,90,180,270],H=>i("line",{key:H,x1:"30",y1:"5",x2:"30",y2:"9",stroke:"#1b1b1b","stroke-width":"1.5",transform:`rotate(${H} 30 30)`},null,8,ed)),64)),i("line",{x1:"30",y1:"30",x2:"30",y2:"16",stroke:"#1b1b1b","stroke-width":"2.4","stroke-linecap":"round",transform:`rotate(${T.value} 30 30)`},null,8,td),i("line",{x1:"30",y1:"30",x2:"30",y2:"11",stroke:"#1b1b1b","stroke-width":"1.6","stroke-linecap":"round",transform:`rotate(${$.value} 30 30)`},null,8,nd),m[4]||(m[4]=i("circle",{cx:"30",cy:"30",r:"1.8",fill:"#1b1b1b"},null,-1))])),s.value?(h(),g("span",sd,[i("span",od,[i("span",id,y(n.value),1),i("span",ld,y(u.value),1)])])):V("",!0)],64)):s.value?(h(),g(W,{key:1},[i("span",ad,[i("span",rd,y(v(ke)(v(wo)(e.tile))),1),i("span",ud,[i("span",cd,y(n.value),1),u.value?(h(),g("span",dd,y(u.value),1)):V("",!0)])]),e.tile.options?.inline==="slider"?(h(),g("span",fd)):V("",!0),a.value?(h(),g("span",pd,[a.value==="toggle"?(h(),g("span",hd)):a.value==="setpoint"?(h(),g("span",vd,[i("span",md,y(b("minus")||"−"),1),m[5]||(m[5]=i("b",null,"20°",-1)),i("span",gd,y(b("plus")||"+"),1)])):a.value==="stepper"&&c.value.endsWith("select")?(h(),g(W,{key:2},[i("span",yd,y(b("chevron-left")),1),i("span",bd,y(b("chevron-right")),1)],64)):a.value==="stepper"?(h(),g("span",wd,[i("span",_d,y(b("minus")||"−"),1),m[6]||(m[6]=i("b",null,"50",-1)),i("span",kd,y(b("plus")||"+"),1)])):a.value==="mode"?(h(),g(W,{key:4},[i("span",$d,y(b("power")),1),i("span",xd,y(b("fire")),1),i("span",Sd,y(b("snowflake")),1)],64)):a.value==="volume"?(h(),g(W,{key:5},[m[7]||(m[7]=i("span",{class:"range"},null,-1)),i("span",Cd,y(b("volume-high")),1)],64)):a.value==="playback"?(h(),g(W,{key:6},[i("span",Td,y(b("skip-previous")),1),i("span",Ad,y(b("play")),1),i("span",Ed,y(b("skip-next")),1)],64)):a.value==="buttons"&&c.value==="cover"?(h(),g(W,{key:7},[i("span",Pd,y(b("arrow-expand-horizontal")),1),i("span",Od,y(b("stop")),1),i("span",Id,y(b("arrow-collapse-horizontal")),1)],64)):a.value==="buttons"&&c.value==="vacuum"?(h(),g(W,{key:8},[i("span",Md,y(b("play")),1),i("span",Dd,y(b("stop")),1),i("span",Ld,y(b("home-map-marker")),1)],64)):a.value==="buttons"&&c.value==="timer"?(h(),g(W,{key:9},[i("span",Fd,y(b("play")),1),i("span",Hd,y(b("close")),1)],64)):a.value==="run"?(h(),g("span",Rd,y({scene:"Activate",script:"Run"}[c.value]||"Press"),1)):(h(),g("span",Nd))])):V("",!0)],64)):(h(),g(W,{key:2},[i("span",jd,y(v(ke)(v(wo)(e.tile))),1),i("span",Bd,[i("span",Ud,y(n.value),1),u.value?(h(),g("span",Vd,y(u.value),1)):V("",!0),e.tile.options?.inline==="slider"?(h(),g("span",Wd)):V("",!0)])],64)),D.value?(h(),g("button",{key:3,type:"button",class:"remove",title:"Remove tile","aria-label":`Remove ${n.value}`,onClick:m[0]||(m[0]=Ft(H=>v(ca)(e.tile),["stop"]))},"✕",8,Kd)):V("",!0)],46,Qc)),[[v(fa),{kind:"tile",tile:e.tile}]])}}),Yd=["viewBox","aria-label"],zd=["y"],Gd=["cx","cy","r","stroke","stroke-width"],Jd=["x1","y1","x2","y2","stroke","stroke-width"],Xd=["x","y","fill"],Qd=["x","y"],va=$e({__name:"TopbarSvg",props:{items:{},nameText:{},single:{type:Boolean}},setup(e,{expose:t}){const n=e,s=k(()=>{d.fontsVersion,d.now,d.topbarPreviews;const T=n.items||Dt();return ea(T,ua.value,n.nameText??(d.layout?.title||"Home"),Rt)}),o=k(()=>s.value.metrics),l=k(()=>n.single?Math.round(o.value.text*1.4):o.value.top+Math.round(o.value.name*.45)),r=k(()=>n.single?Math.round(o.value.text*1.05):o.value.top),u=k(()=>{if(!n.single)return s.value.placed;const T=s.value.parts[0];return T&&(T.x=0),T?[T]:[]}),a=k(()=>n.single?`-2 0 ${Math.max(1,u.value[0]?.width||1)+4} ${l.value}`:`0 0 ${o.value.width} ${l.value}`),c=k(()=>r.value+(s.value.zero.top+s.value.zero.bottom)/2),f=k(()=>Qu(s.value.nameText,s.value.fonts.name,Math.min(s.value.natural,s.value.nameRoom))),b=k(()=>new Date(d.now));function A(T){const $=b.value;return[[($.getHours()%12+$.getMinutes()/60)*30,T*.24],[$.getMinutes()*6,T*.34]].map(([x,w])=>{const m=x*Math.PI/180;return{x2:w*Math.sin(m),y2:-w*Math.cos(m)}})}const D=T=>T.x-T.icon.ink.left,I=T=>(T.icon?T.x+(T.icon.ink.right-T.icon.ink.left)+s.value.gaps.icon:T.x)-T.text.ink.left,R=k(()=>`${(Math.max(1,u.value[0]?.width||1)+4)*(26/o.value.icon)}px`);return t({lay:s}),(T,$)=>(h(),g("svg",{viewBox:a.value,role:"img","aria-label":e.single?"How it looks on the screen":`Top bar: ${s.value.nameText}`,style:Ne(e.single?{width:R.value}:void 0)},[e.single?V("",!0):(h(),g("text",{key:0,x:"0",y:o.value.top,fill:"#1b1b1b",style:Ne({font:s.value.fonts.name})},y(f.value),13,zd)),i("g",null,[(h(!0),g(W,null,le(u.value,x=>(h(),g(W,{key:x.index},[x.dial?(h(),g(W,{key:0},[i("circle",{cx:x.x+x.dial/2,cy:c.value,r:x.dial/2-Math.max(1,Math.round(x.dial/10))/2,fill:"none",stroke:x.view.color||"#46525e","stroke-width":Math.max(1,Math.round(x.dial/10))},null,8,Gd),(h(!0),g(W,null,le(A(x.dial),(w,m)=>(h(),g("line",{key:m,x1:x.x+x.dial/2,y1:c.value,x2:x.x+x.dial/2+w.x2,y2:c.value+w.y2,stroke:x.view.color||"#46525e","stroke-width":Math.max(1,Math.round(x.dial*.075)),"stroke-linecap":"round"},null,8,Jd))),128))],64)):(h(),g(W,{key:1},[x.icon?(h(),g("text",{key:0,x:D(x),y:c.value-(x.icon.ink.top+x.icon.ink.bottom)/2,fill:x.view.color||"#46525e",style:Ne({font:s.value.fonts.icon})},y(x.icon.glyph),13,Xd)):V("",!0),x.text?(h(),g("text",{key:1,x:I(x),y:r.value,fill:"#46525e",style:Ne({font:s.value.fonts.text})},y(x.text.value),13,Qd)):V("",!0)],64))],64))),128))])],12,Yd))}}),Zd={class:"page"},ef={class:"page-label"},tf={key:1},nf={class:"tiles"},sf=["data-slot","aria-label","onClick"],of=$e({__name:"DevicePage",props:{page:{},entries:{},pages:{},moving:{}},setup(e){const t=e,n=k(()=>new Map(t.entries.map(c=>[c.slot,c]))),s=k(()=>new Set(t.entries.filter(c=>Qe(c.tile)).map(c=>c.slot+1))),o=k(()=>Array.from({length:Et},(c,f)=>t.page*Et+f).filter(c=>!s.value.has(c))),l=k(()=>t.pages>1&&!t.entries.some(c=>ks(c.slot)===t.page)),r=k(()=>d.inspector?.kind==="bar"||d.inspector?.kind==="bar-add"),u=k(()=>t.entries.filter(c=>ks(c.slot)===t.page).reduce((c,f)=>c+(Qe(f.tile)?2:1),0));function a(c){const f=d.insertAt===c;d.insertAt=f?-1:c,d.insertAt>=0&&document.querySelector("#search")?.focus()}return(c,f)=>(h(),g("div",Zd,[i("div",ef,[i("span",null,"Page "+y(e.page+1),1),l.value?(h(),g("button",{key:0,type:"button",class:"btn mini",title:"The pages after this one shift up one slot",onClick:f[0]||(f[0]=b=>v(vc)(e.page))},"Remove page")):(h(),g("span",tf,y(u.value)+" / "+y(v(Et)),1))]),i("div",{class:re(["device",{cyd:!v(Yo)}])},[i("div",{class:re(["bar-wrap",{selected:r.value}]),title:"Edit top bar",role:"button",tabindex:"0",onClick:f[1]||(f[1]=b=>v(Ct)(0)),onKeydown:f[2]||(f[2]=Ql(Ft(b=>v(Ct)(0),["prevent"]),["enter"]))},[_e(va)],34),i("div",nf,[(h(!0),g(W,null,le(o.value,b=>(h(),g(W,{key:b},[n.value.get(b)?(h(),Ve(qd,{key:0,tile:n.value.get(b).tile,slot:b,placeholder:n.value.get(b).tile===e.moving},null,8,["tile","slot","placeholder"])):(h(),g("button",{key:1,type:"button",class:re(["cell",{"insert-here":v(d).insertAt===b}]),"data-slot":b,title:"Empty slot. Click to add a tile here, or drag one over.","aria-label":`Empty slot ${b%v(Et)+1} on page ${e.page+1}: add the next tile here`,onClick:A=>a(b)},[f[3]||(f[3]=i("span",null,"+",-1)),i("small",null,y(v(d).insertAt===b?"Next tile goes here":"Empty"),1)],10,sf))],64))),128))])],2)]))}}),lf={class:"library",id:"library"},af={class:"lib-head"},rf={class:"lib-title"},uf={class:"filters",id:"filters"},cf=["aria-pressed","onClick"],df={class:"lib-list",id:"results","aria-live":"polite"},ff=["title","disabled","onClick"],pf={class:"tx"},hf={key:0,class:"hint"},vf={key:1,class:"hint"},mf={class:"lib-foot"},gf=$e({__name:"Library",setup(e){const t=[["","All"],["light","Lights"],["climate","Climate"],["switch","Switches"],["binary_sensor","Status"],["button","Actions"],["script","Scripts"],["fan","Fans"],["cover","Covers"],["scene","Scenes"],["vacuum","Vacuum"],["sensor","Sensors"],["media_player","Media"],["weather","Weather"],["number","Values"],["select","Selects"],["person","People"],["timer","Timers"],["screen","Clock"]],n={switch:"input_boolean",number:"input_number",select:"input_select",weather:"sun",button:"input_button"},s=k(()=>new Set(d.layout?.tiles.map(u=>u.entity)||[])),o=k(()=>{const u=d.search.toLocaleLowerCase(),a=d.filter;return[...d.inventory.builtin||[],...d.inventory.entities].filter(c=>c.tile!==!1&&(Yo.value||!["camera","image"].includes(c.id.split(".")[0]))&&(!a||c.id.startsWith(a+".")||n[a]===c.id.split(".")[0])&&`${c.name} ${c.id} ${c.device||""} ${c.area||""}`.toLocaleLowerCase().includes(u))}),l=k(()=>(d.layout?.tiles.length||0)>=Hn.value),r=k(()=>d.inventory.entities.length);return(u,a)=>(h(),g("aside",lf,[i("div",af,[i("div",rf,[a[1]||(a[1]=Q("Library ",-1)),i("small",null,y(r.value)+" entities",1)]),Te(i("input",{id:"search","onUpdate:modelValue":a[0]||(a[0]=c=>v(d).search=c),type:"search",placeholder:"Search by name, device, or room…",autocomplete:"off","aria-label":"Add an entity"},null,512),[[Je,v(d).search]]),i("div",uf,[(h(),g(W,null,le(t,([c,f])=>i("button",{key:c,type:"button","aria-pressed":v(d).filter===c?"true":"false",onClick:b=>v(d).filter=c},[c?(h(),g("span",{key:0,class:"domain-icon",style:Ne({color:v(xt)(c+".")[2],background:v(xt)(c+".")[3]}),"aria-hidden":"true"},y(v(xt)(c+".")[1]),5)):V("",!0),Q(y(f),1)],8,cf)),64))])]),i("div",df,[(h(!0),g(W,null,le(o.value.slice(0,80),c=>Te((h(),g("button",{key:c.id,type:"button",class:"ent",title:c.id,disabled:s.value.has(c.id)||l.value,onClick:f=>v(hc)(c.id)},[i("span",{class:"av mdi",style:Ne({color:v(xt)(c.id)[2],background:v(xt)(c.id)[3]})},y(v(d).inventory.icons?v(ke)(v(on)(c.id)):v(xt)(c.id)[1]),5),i("span",pf,[i("b",null,y(c.name),1),i("small",null,y([v(xt)(c.id)[0],c.area,c.device].filter(Boolean).join(" · ")),1)]),i("span",{class:re(["add",{done:s.value.has(c.id)}])},y(s.value.has(c.id)?"✓":"+"),3)],8,ff)),[[v(fa),{kind:"entity",id:c.id}]])),128)),o.value.length?o.value.length>80?(h(),g("p",vf,y(o.value.length)+" results. Keep typing to narrow it down.",1)):V("",!0):(h(),g("p",hf,"No entities found. Try a different name."))]),i("div",mf,y(l.value?`This screen holds ${v(Hn)} tiles${v(Hn)===10?"; update its firmware for 20":""}.`:"Drag onto a page, or tap + to add to the first free slot."),1)]))}}),yf={class:"canvas-head"},bf={id:"count"},wf={key:0,id:"no-tiles"},_f={key:1},kf={key:2,id:"positions-hint",class:"warn"},$f={class:"pages",id:"layout-preview","aria-label":"Screen layout"},xf={class:"page-label"},Sf=["tabindex"],Cf=$e({__name:"LayoutView",setup(e){const t=k(()=>d.layout),n=k(()=>d.drag.preview||wt(t.value)),s=k(()=>zt(n.value,t.value.pages)),o=k(()=>mc()),l=k(()=>s.valuetc(t.value.tiles)&&!fn(0,2,26)?`Empty slots and fixed positions work from firmware 0.2.26. This screen (firmware ${qt.value?.firmware||"unknown"}) shifts the tiles up to the first free slot until that update.`:"");function u(a){a.target.closest(".device, .page-label, .canvas-head")||d.inspector&&je()}return(a,c)=>(h(),g(W,null,[i("div",{class:"canvas",id:"canvas",onClick:u},[i("div",yf,[i("b",bf,y(s.value)+" "+y(s.value===1?"page":"pages")+" · "+y(t.value.tiles.length)+" / "+y(v(Hn))+" tiles",1),t.value.tiles.length?(h(),g("span",_f,"Tap the top bar or a tile to change it. Drag to move; drop on the next page for a new one.")):(h(),g("span",wf,"Add your first light, scene, or device from the library.")),r.value?(h(),g("span",kf,y(r.value),1)):V("",!0)]),i("div",$f,[(h(!0),g(W,null,le(o.value,f=>(h(),Ve(of,{key:f,page:f-1,entries:n.value,pages:s.value,moving:v(d).drag.moving},null,8,["page","entries","pages","moving"]))),128)),i("div",{class:re(["page ghost",{disabled:!l.value}])},[i("div",xf,[i("span",null,"Page "+y(o.value+1),1)]),i("div",{class:re(["device",{cyd:v(qt)?.board!=="guition"}]),id:"add-page",role:"button",tabindex:l.value?0:-1,onClick:c[0]||(c[0]=f=>l.value&&v(Hi)()),onKeydown:c[1]||(c[1]=Ql(Ft(f=>l.value&&v(Hi)(),["prevent"]),["enter"]))},y(l.value?"+ Add page":`${v(gn)} pages is the most`),43,Sf)],2)])]),_e(gf)],64))}}),Tf={class:"status",id:"settings-status",role:"status"},Af={key:0,class:"set-grid",id:"settings-groups"},Ef={class:"mdi"},Pf=["data-setting","title","onClick"],Of=["id"],If={class:"s-control"},Mf=["id","aria-checked","aria-labelledby","disabled","onClick"],Df=["aria-labelledby"],Lf=["aria-pressed","disabled","onClick"],Ff={key:2,class:"step"},Hf=["aria-label","disabled","onPointerdown","onClick"],Rf={class:"mdi"},Nf=["id","aria-labelledby"],jf=["aria-label","disabled","onPointerdown","onClick"],Bf={class:"mdi"},Uf=$e({__name:"SettingsTab",setup(e){const t=k(()=>Jo()),n=k(()=>yn()),s=k(()=>t.value?.owner==="screen"&&!qt.value?.online),o=k(()=>yc.map(I=>({...I,rows:I.rows.filter(R=>t.value?.keys.includes(R.key))})).filter(I=>I.rows.length)),l=I=>s.value||!!t.value?.unavailable.includes(I.key),r=I=>I.needs?!!n.value[I.needs]:!0,u=k(()=>s.value?"This screen is offline. Its settings can change once it's back.":d.settingPending?"Saving…":t.value?.owner==="screen"?"Changes apply on the screen at once, and show up here when they change there.":"Changes apply at once. Firmware 0.2.49 lets the screen keep them itself."),a=(I,R)=>{const T=n.value[I.key];return l(I)||!r(I)||T===null||T===void 0?!0:I.kind!=="moment"&&Bi(I,T,R,!1,n.value)===T},c=new WeakMap;function f(I,R,T){const $=yn(),x=Bi(I,$[I.key],R,T,$);x!==$[I.key]&&An(I.key,x,600)}function b(I,R,T){const $=I.currentTarget;if($.disabled||I.button!==0)return;const x={timer:0,held:!1};c.set($,x);let w=0;x.timer=window.setTimeout(function m(){x.held=!0,w+=1,f(R,T,w>5),x.timer=window.setTimeout(m,180)},450)}function A(I){const R=c.get(I.currentTarget);R&&clearTimeout(R.timer)}function D(I,R,T){const $=c.get(I.currentTarget);if($?.held){$.held=!1;return}f(R,T,!1)}return(I,R)=>(h(),g("div",{class:re(["settings",{offline:s.value}]),id:"general-settings"},[i("span",Tf,y(u.value),1),t.value?(h(),g("div",Af,[(h(!0),g(W,null,le(o.value,T=>(h(),g("section",{key:T.title,class:"set-card"},[i("h4",null,[i("span",Ef,y(v(ke)(T.icon)),1),Q(y(T.title),1)]),(h(!0),g(W,null,le(T.rows,$=>(h(),g("div",{key:$.key,class:re(["srow",[`setting-${$.kind}`,{inactive:!r($)||l($)}]]),"data-setting":$.key,title:l($)&&!s.value?"This entity is off in Home Assistant, or the screen is restarting.":"",onClick:x=>$.kind==="toggle"&&x.target.closest(".srow")===x.currentTarget&&!x.target.closest("button")&&!l($)&&v(An)($.key,!n.value[$.key],150)},[i("span",{class:"s-label",id:`setting-label-${$.key}`},y($.label),9,Of),i("div",If,[$.kind==="toggle"?(h(),g("button",{key:0,type:"button",class:re(["switch",{unknown:n.value[$.key]===null||n.value[$.key]===void 0}]),role:"switch",id:`setting-${$.key}`,"aria-checked":n.value[$.key]?"true":"false","aria-labelledby":`setting-label-${$.key}`,disabled:l($),onClick:Ft(x=>v(An)($.key,!n.value[$.key],150),["stop"])},null,10,Mf)):$.kind==="choice"?(h(),g("div",{key:1,class:"seg",role:"group","aria-labelledby":`setting-label-${$.key}`},[(h(!0),g(W,null,le($.options,([x,w])=>(h(),g("button",{key:String(x),type:"button","aria-pressed":n.value[$.key]===x?"true":"false",disabled:l($),onClick:m=>v(An)($.key,x,150)},y(w),9,Lf))),128))],8,Df)):(h(),g("div",Ff,[i("button",{type:"button","aria-label":`${$.label} lower`,disabled:a($,-1),onPointerdown:x=>b(x,$,-1),onPointerup:A,onPointercancel:A,onPointerleave:A,onClick:x=>D(x,$,-1)},[i("span",Rf,y(v(ke)("F0374")),1)],40,Hf),i("output",{id:`setting-${$.key}`,"aria-labelledby":`setting-label-${$.key}`},y(v(kc)($,n.value)),9,Nf),i("button",{type:"button","aria-label":`${$.label} higher`,disabled:a($,1),onPointerdown:x=>b(x,$,1),onPointerup:A,onPointercancel:A,onPointerleave:A,onClick:x=>D(x,$,1)},[i("span",Bf,y(v(ke)("F0415")),1)],40,jf)]))])],10,Pf))),128))]))),128))])):V("",!0)],2))}}),Vf={class:"seg wrap",role:"group"},Wf=["disabled","aria-pressed","onClick"],nt=$e({__name:"Segmented",props:{choices:{},value:{},disabled:{type:Boolean}},emits:["pick"],setup(e,{emit:t}){const n=t;return(s,o)=>(h(),g("div",Vf,[(h(!0),g(W,null,le(e.choices,([l,r])=>(h(),g("button",{key:String(l),type:"button",disabled:e.disabled,"aria-pressed":String(l)===String(e.value)?"true":"false",onClick:u=>n("pick",l)},y(r),9,Wf))),128))]))}}),Kf={class:"f"},qf={key:0},Yf={key:1,class:"warn"},zf=["aria-expanded"],Gf={class:"tx"},Jf={key:0,class:"mono"},Xf={class:"link"},Qf={key:0,class:"picker"},Zf={class:"action-list"},ep=["aria-pressed","onClick"],tp={key:0,class:"hint"},np={key:1,class:"warn"},sp={class:"f-label"},op=["aria-label","value","onChange"],ip=["value"],lp={key:3,class:"action-number"},ap=["aria-label","value","onInput"],rp=["onClick"],up={key:4,class:"action-number"},cp=["aria-label","min","max","step","value","placeholder","onInput"],dp={key:0},fp=["aria-label","value","placeholder","onInput"],pp={key:6},hp={key:0,class:"warn"},vp={key:3},mp=$e({__name:"ActionPicker",props:{tile:{}},setup(e){const t=e,n=k(()=>d.entityActions[t.tile.entity]),s=k(()=>t.tile.options?.action),o=k(()=>n.value?.find(m=>m.action===s.value?.action)),l=k(()=>d.actionPickerOpen||!s.value),r=k(()=>{const m=d.actionSearch.trim().toLocaleLowerCase();return(n.value||[]).filter(H=>`${H.name} ${H.action} ${H.description}`.toLocaleLowerCase().includes(m))});n.value===void 0&&dc(t.tile.entity);function u(m){const H=m.action===s.value?.action;t.tile.options={...t.tile.options,action:H?s.value:{action:m.action}},d.actionPickerOpen=!1,et()}function a(m,H){const C={...t.tile.options?.action?.data||{}};H===void 0?delete C[m]:C[m]=H,t.tile.options={...t.tile.options,action:{action:s.value.action,...Object.keys(C).length?{data:C}:{}}},et()}const c=k(()=>{if(!o.value)return[];const m=t.tile.options?.action?.data||{};return o.value.fields.filter(H=>H.required&&m[H.key]===void 0).map(H=>H.name)}),f=m=>Object.keys(m.selector||{})[0]||"text",b=m=>(m.selector||{})[f(m)]||{},A=m=>m.example===void 0?"":typeof m.example=="string"?m.example:JSON.stringify(m.example);function D(m){const H=b(m),C=f(m);return Array.isArray(m.options)?m.options.map(L=>[L,L]):C==="select"&&Array.isArray(H.options)&&!H.multiple?H.options.map(L=>L&&typeof L=="object"?[String(L.value),String(L.label??L.value)]:[String(L),String(L)]):null}const I=m=>"#"+m.map(H=>Math.max(0,Math.min(255,Number(H)||0)).toString(16).padStart(2,"0")).join(""),R=m=>Array.isArray(m)&&m.length===3?I(m):"#ffffff",T=m=>m===void 0?"":typeof m=="string"?m:JSON.stringify(m);function $(m,H){const C=H.trim();if(!C)return a(m.key,void 0);if(f(m)==="text")return a(m.key,H);try{a(m.key,JSON.parse(C))}catch{a(m.key,H)}}function x(m,H){a(m.key,H===""||!Number.isFinite(Number(H))?void 0:Number(H))}const w=m=>b(m).unit_of_measurement||f(m)==="color_temp"&&b(m).unit||"";return(m,H)=>(h(),g("div",Kf,[H[3]||(H[3]=i("span",{class:"f-label"},"Action",-1)),n.value===void 0?(h(),g("small",qf,"Asking Home Assistant which actions this entity has…")):n.value===null?(h(),g("small",Yf,"Home Assistant isn't answering right now. Try again in a moment.")):(h(),g(W,{key:2},[i("button",{type:"button",class:"row","aria-expanded":l.value?"true":"false",onClick:H[0]||(H[0]=C=>v(d).actionPickerOpen=!l.value)},[i("span",Gf,[i("b",null,y(o.value?o.value.name:s.value?s.value.action:"Choose an action"),1),s.value?(h(),g("small",Jf,y(s.value.action),1)):V("",!0)]),i("span",Xf,y(l.value?"Close":"Change"),1)],8,zf),l.value?(h(),g("div",Qf,[Te(i("input",{"onUpdate:modelValue":H[1]||(H[1]=C=>v(d).actionSearch=C),type:"search",placeholder:"Search, for example toggle, position, or play","aria-label":"Search for an action"},null,512),[[Je,v(d).actionSearch]]),i("div",Zf,[(h(!0),g(W,null,le(r.value,C=>(h(),g("button",{key:C.action,type:"button",class:"action-choice","aria-pressed":C.action===s.value?.action?"true":"false",onClick:L=>u(C)},[i("strong",null,y(C.name),1),i("small",null,y(C.description?`${C.action} · ${C.description}`:C.action),1)],8,ep))),128)),r.value.length?V("",!0):(h(),g("p",tp,"No action found."))])])):V("",!0),s.value&&!o.value?(h(),g("small",np,"Home Assistant doesn't offer this action for this entity any more, so a tap does nothing. Choose another one.")):V("",!0),o.value&&!l.value?(h(),g(W,{key:2},[(h(!0),g(W,null,le(o.value.fields,C=>(h(),g("div",{key:C.key,class:"f"},[i("span",sp,y(C.required?C.name:`${C.name} (optional)`),1),f(C)==="boolean"?(h(),Ve(nt,{key:0,choices:[["","Not set"],["true","On"],["false","Off"]],value:s.value?.data?.[C.key]===void 0?"":String(s.value?.data?.[C.key]),onPick:L=>a(C.key,L===""?void 0:L==="true")},null,8,["value","onPick"])):D(C)&&D(C).length<=4?(h(),Ve(nt,{key:1,choices:[["","Not set"],...D(C)],value:s.value?.data?.[C.key]===void 0?"":String(s.value?.data?.[C.key]),onPick:L=>a(C.key,L===""?void 0:L)},null,8,["choices","value","onPick"])):D(C)?(h(),g("select",{key:2,"aria-label":C.name,value:String(s.value?.data?.[C.key]??""),onChange:L=>a(C.key,L.target.value===""?void 0:L.target.value)},[H[2]||(H[2]=i("option",{value:""},"Not set",-1)),(h(!0),g(W,null,le(D(C),([L,pe])=>(h(),g("option",{key:L,value:L},y(pe),9,ip))),128))],40,op)):f(C)==="color_rgb"?(h(),g("div",lp,[i("input",{type:"color","aria-label":C.name,value:R(s.value?.data?.[C.key]),onInput:L=>a(C.key,[1,3,5].map(pe=>parseInt(L.target.value.slice(pe,pe+2),16)))},null,40,ap),i("button",{type:"button",class:"btn quiet mini",onClick:L=>a(C.key,void 0)},"Not set",8,rp)])):f(C)==="number"||f(C)==="color_temp"?(h(),g("div",up,[i("input",{type:"number","aria-label":C.name,min:b(C).min,max:b(C).max,step:b(C).step==="any"?"any":b(C).step,value:s.value?.data?.[C.key]??"",placeholder:A(C),onInput:L=>x(C,L.target.value)},null,40,cp),w(C)?(h(),g("span",dp,y(w(C)),1)):V("",!0)])):(h(),g("input",{key:5,type:"text","aria-label":C.name,value:T(s.value?.data?.[C.key]),placeholder:A(C),onInput:L=>$(C,L.target.value)},null,40,fp)),C.description?(h(),g("small",pp,y(C.description),1)):V("",!0)]))),128)),c.value.length?(h(),g("small",hp,"Home Assistant needs "+y(c.value.join(", "))+".",1)):V("",!0)],64)):V("",!0),v(fn)(0,2,58)?V("",!0):(h(),g("small",vp,"The screen performs an action from firmware 0.2.58: press Update on the screen. Until then a tap works as Automatic."))],64))]))}}),gp={class:"f"},yp=["aria-expanded"],bp={class:"av mdi"},wp={class:"tx"},_p={class:"link"},kp={key:0,class:"picker"},$p=["aria-pressed","title"],xp={class:"mdi"},Sp=["aria-pressed"],Cp={class:"icon-list"},Tp={class:"icon-grid"},Ap=["title","aria-label","aria-pressed","onClick"],Ep={class:"mdi"},Pp={key:0,class:"hint"},Op={key:1},ma=$e({__name:"IconPicker",props:{selected:{},automatic:{},autoLabel:{},allowNone:{type:Boolean},note:{}},emits:["pick"],setup(e,{emit:t}){const n=e,s=t,o=fe(""),l=k(()=>es(n.selected)),r=k(()=>n.selected==="none"?"":ke(l.value?.cp||n.automatic)),u=k(()=>n.selected==="none"?"No icon":l.value?.label||n.autoLabel),a=k(()=>{const c=o.value.trim().toLocaleLowerCase();return(d.inventory.icons?.groups||[]).map(f=>({label:f.label,icons:f.icons.filter(b=>!c||`${b.label} ${b.name.replaceAll("-"," ")} ${f.label}`.toLocaleLowerCase().includes(c))})).filter(f=>f.icons.length)});return(c,f)=>(h(),g("div",gp,[f[5]||(f[5]=i("span",{class:"f-label"},"Icon",-1)),i("button",{type:"button",class:"row","aria-expanded":v(d).iconPickerOpen?"true":"false",onClick:f[0]||(f[0]=b=>v(d).iconPickerOpen=!v(d).iconPickerOpen)},[i("span",bp,y(r.value),1),i("span",wp,[i("b",null,y(u.value),1)]),i("span",_p,y(v(d).iconPickerOpen?"Close":"Change"),1)],8,yp),v(d).iconPickerOpen?(h(),g("div",kp,[Te(i("input",{"onUpdate:modelValue":f[1]||(f[1]=b=>o.value=b),type:"search",placeholder:"Search, for example lamp, music, or door","aria-label":"Search for an icon"},null,512),[[Je,o.value]]),i("button",{type:"button",class:"icon-choice icon-auto","aria-pressed":e.selected==="auto"?"true":"false",title:e.autoLabel,onClick:f[2]||(f[2]=b=>s("pick","auto"))},[i("span",xp,y(v(ke)(e.automatic)),1),i("span",null,y(e.autoLabel),1)],8,$p),e.allowNone?(h(),g("button",{key:0,type:"button",class:"icon-choice icon-auto","aria-pressed":e.selected==="none"?"true":"false",title:"No icon",onClick:f[3]||(f[3]=b=>s("pick","none"))},[...f[4]||(f[4]=[i("span",{class:"mdi"},null,-1),i("span",null,"No icon, text only",-1)])],8,Sp)):V("",!0),i("div",Cp,[(h(!0),g(W,null,le(a.value,b=>(h(),g("section",{key:b.label},[i("small",null,y(b.label),1),i("div",Tp,[(h(!0),g(W,null,le(b.icons,A=>(h(),g("button",{key:A.name,type:"button",class:"icon-choice",title:A.label,"aria-label":`Icon: ${A.label}`,"aria-pressed":e.selected===A.name?"true":"false",onClick:D=>s("pick",A.name)},[i("span",Ep,y(v(ke)(A.cp)),1)],8,Ap))),128))])]))),128)),a.value.length?V("",!0):(h(),g("p",Pp,"No icon found."))])])):V("",!0),e.note?(h(),g("small",Op,y(e.note),1)):V("",!0)]))}}),Ip={class:"dr-head"},Mp={class:"tx"},Dp={class:"mono"},Lp={class:"dr-body"},Fp={class:"f"},Hp=["value","placeholder"],Rp={class:"f"},Np={key:0,class:"warn"},jp={class:"f"},Bp={key:1,class:"f"},Up={key:2,class:"f"},Vp={key:4,class:"f"},Wp={key:0,class:"warn"},Kp={key:5,class:"f"},qp={class:"f"},Yp={class:"sw"},zp=["aria-label","aria-pressed","onClick"],Gp={class:"dr-foot"},Jp=$e({__name:"TileInspector",props:{tile:{}},setup(e){const t=e,n=k(()=>t.tile.entity.split(".")[0]),s=k(()=>Zn(t.tile.entity)),o=k(()=>d.capabilities[t.tile.entity]),l=(J,q)=>t.tile.options?.[J]??q,r=k(()=>l("display",n.value==="screen"?"digital":"standard")),u=k(()=>{const J=n.value==="screen"?[["digital","Digital clock"],["analog","Analog clock"]]:[["standard","Name and status"],["watch","Large value"]],q=o.value;return n.value==="weather"&&(!q||q.displays.includes("forecast")||r.value==="forecast")&&J.push(["forecast","Weather forecast"]),n.value==="sensor"&&(!q||q.displays.includes("graph")||r.value==="graph")&&J.push(["graph","Graph"]),n.value==="sun"&&J.push(["sunpath","Sun path"]),J}),a=k(()=>{const J=o.value;return J&&r.value==="graph"&&!J.displays.includes("graph")?"Home Assistant has no numbers for this entity, so the graph stays empty. Choose another display.":J&&r.value==="forecast"&&!J.displays.includes("forecast")?"This weather service has no daily forecast in Home Assistant. Choose another display.":""}),c=k(()=>l("size","single")),f=k(()=>d.inventory.controls?.[n.value]),b=k(()=>l("controls",f.value?.default)),A=k(()=>{const J=o.value;return(f.value?.choices||[]).filter(q=>!J||q.key==="none"||q.key===b.value||J.controls.includes(q.key)).map(q=>[q.key,q.label])}),D=k(()=>{const J=o.value;return J&&b.value!=="none"&&!J.controls.includes(b.value)?{text:"Home Assistant doesn't offer this control for this entity, so it stays empty on the screen. Choose another one.",warn:!0}:{text:fn(0,2,19)?"On the right of the double-width tile, like the rows in Home Assistant. Tapping the name works as set below.":"The screen shows direct control from firmware 0.2.19; until then the tile stays as it was.",warn:!1}}),I=k(()=>l("tap","auto")),R=k(()=>{const J=[["auto","Automatic"],["detail","Open control"],["none","View only"]];return((o.value?o.value.toggle:Li.includes(n.value))||I.value==="toggle")&&J.push(["toggle","On / off"]),J.push(["action","Perform action"]),J}),T=k(()=>I.value==="toggle"&&o.value&&!o.value.toggle?{text:"Home Assistant can't turn this on and off, so a tap does nothing. Choose another option.",warn:!0}:I.value==="toggle"&&!Li.includes(n.value)&&!fn(0,2,58)?{text:"The screen switches this from firmware 0.2.58: press Update on the screen. Until then a tap opens its card.",warn:!1}:I.value==="toggle"?{text:"Hold the tile to open its card.",warn:!1}:null),$=k(()=>l("inline","none")),x=k(()=>ac.includes(n.value)&&(!o.value||o.value.inline||$.value==="slider")),w=k(()=>$.value==="slider"&&o.value&&!o.value.inline),m=k(()=>l("history_hours",24)),H=k(()=>Object.entries(d.inventory.backgrounds||{})),C=k(()=>!!d.inventory.entities.find(J=>J.id===t.tile.entity)?.icon),L=k(()=>!!d.inventory.icons&&n.value!=="screen"&&!["forecast","sunpath"].includes(r.value));function pe(J){t.tile.name=J,et()}function Ae(){d.inspector={kind:"inspect",entity:t.tile.entity}}return(J,q)=>(h(),g(W,null,[i("div",Ip,[i("span",{class:"av mdi",style:Ne({color:v(xt)(e.tile.entity)[2],background:v(xt)(e.tile.entity)[3]})},y(v(ke)(v(wo)(e.tile))),5),i("span",Mp,[i("b",null,y(e.tile.name||s.value),1),i("small",Dp,y(e.tile.entity),1)]),i("button",{type:"button",class:"icon-btn","aria-label":"Close",onClick:q[0]||(q[0]=(...ae)=>v(je)&&v(je)(...ae))},"✕")]),i("div",Lp,[i("div",Fp,[q[10]||(q[10]=i("label",{class:"f-label",for:"tile-name"},"Name on the screen",-1)),i("input",{id:"tile-name",value:e.tile.name,placeholder:s.value,maxlength:"60",onInput:q[1]||(q[1]=ae=>pe(ae.target.value))},null,40,Hp)]),L.value?(h(),Ve(ma,{key:0,selected:e.tile.options?.icon||"auto",automatic:v(on)(e.tile.entity),"auto-label":`Automatic (${C.value?"from Home Assistant":"default"})`,note:v(fn)(0,2,18)?"":"The screen shows a chosen icon from firmware 0.2.18.",onPick:q[2]||(q[2]=ae=>v(Ht)(e.tile,"icon",ae))},null,8,["selected","automatic","auto-label","note"])):V("",!0),i("div",Rp,[q[11]||(q[11]=i("span",{class:"f-label"},"Display",-1)),_e(nt,{choices:u.value,value:r.value,onPick:q[3]||(q[3]=ae=>v(Ht)(e.tile,"display",ae))},null,8,["choices","value"]),a.value?(h(),g("small",Np,y(a.value),1)):V("",!0)]),i("div",jp,[q[12]||(q[12]=i("span",{class:"f-label"},"Width",-1)),_e(nt,{choices:[["single","Normal"],["wide","Double-width"]],value:c.value,onPick:q[4]||(q[4]=ae=>v(Ht)(e.tile,"size",ae))},null,8,["value"])]),f.value&&c.value==="wide"?(h(),g("div",Bp,[q[13]||(q[13]=i("span",{class:"f-label"},"Direct control on the tile",-1)),_e(nt,{choices:A.value,value:b.value,onPick:q[5]||(q[5]=ae=>v(Ht)(e.tile,"controls",ae))},null,8,["choices","value"]),i("small",{class:re({warn:D.value.warn})},y(D.value.text),3)])):V("",!0),n.value!=="screen"?(h(),g("div",Up,[q[14]||(q[14]=i("span",{class:"f-label"},"On tap",-1)),_e(nt,{choices:R.value,value:I.value,onPick:q[6]||(q[6]=ae=>v(Ht)(e.tile,"tap",ae))},null,8,["choices","value"]),T.value?(h(),g("small",{key:0,class:re({warn:T.value.warn})},y(T.value.text),3)):V("",!0)])):V("",!0),n.value!=="screen"&&I.value==="action"?(h(),Ve(mp,{key:3,tile:e.tile},null,8,["tile"])):V("",!0),x.value?(h(),g("div",Vp,[q[15]||(q[15]=i("span",{class:"f-label"},"Small slider on the tile",-1)),_e(nt,{choices:[["none","No"],["slider","Yes, control directly"]],value:$.value,onPick:q[7]||(q[7]=ae=>v(Ht)(e.tile,"inline",ae))},null,8,["value"]),w.value?(h(),g("small",Wp,"Home Assistant has nothing a slider can change for this entity. Choose No.")):V("",!0)])):V("",!0),n.value==="sensor"?(h(),g("div",Kp,[q[16]||(q[16]=i("span",{class:"f-label"},"History",-1)),_e(nt,{choices:[[1,"1 hour"],[6,"6 hours"],[24,"24 hours"]],value:m.value,onPick:q[8]||(q[8]=ae=>v(Ht)(e.tile,"history_hours",Number(ae)))},null,8,["value"])])):V("",!0),i("div",qp,[q[17]||(q[17]=i("span",{class:"f-label"},"Pastel background",-1)),i("div",Yp,[(h(!0),g(W,null,le(H.value,([ae,z])=>(h(),g("button",{key:ae,type:"button","aria-label":`Background: ${z.label}`,"aria-pressed":(e.tile.options?.background||"auto")===ae?"true":"false",onClick:B=>v(Ht)(e.tile,"background",ae)},[i("i",{class:re(z.color?"":ae==="none"?"none":"auto"),style:Ne(z.color?{background:z.color}:void 0)},null,6),Q(y(z.label),1)],8,zp))),128))])])]),i("div",Gp,[i("button",{type:"button",class:"btn danger",onClick:q[9]||(q[9]=ae=>v(ca)(e.tile))},"Remove"),q[18]||(q[18]=i("span",{class:"spacer"},null,-1)),n.value!=="screen"?(h(),g("button",{key:0,type:"button",class:"btn quiet",onClick:Ae},"Read current data")):V("",!0)])],64))}}),Xp={class:"dr-head"},Qp={class:"av mdi",style:{background:"var(--seg)",color:"var(--ink-2)"}},Zp={class:"tx"},eh={class:"dr-body"},th={class:"f"},nh=["value"],sh={class:"f"},oh={class:"f-label",id:"topbar-caption"},ih={style:{"text-transform":"none","letter-spacing":"0","font-weight":"500"}},lh={class:"items",id:"topbar-chips",role:"list","aria-labelledby":"topbar-caption"},ah=["data-index","aria-label","onPointerdown","onClick","onKeydown"],rh={class:"tx"},uh=["aria-label","onClick"],ch=["disabled","title"],dh={class:"live",id:"topbar-live"},fh={class:"f"},ph={class:"f"},hh={key:1,class:"f"},vh={key:2},mh={key:0,class:"dr-foot"},gh=["disabled"],yh=["disabled"],bh=$e({__name:"TopbarInspector",props:{index:{}},setup(e){const t=e,n=k(()=>Dt()),s=k(()=>n.value[t.index]),o=k(()=>(d.fontsVersion,d.now,d.topbarPreviews,ea(n.value,ua.value,d.layout?.title||"Home",Rt))),l=k(()=>o.value.dropped),r=k(()=>d.inventory.header?.min_firmware||"0.2.32"),u=k(()=>{const[z,B,Y]=r.value.split(".").map(Number);return fn(z,B,Y)}),a=k(()=>u.value?l.value.size?"Not everything fits next to the name: the screen drops the dashed items. Remove one or choose a shorter name.":"Drag to reorder; tap an item to configure it.":`Sensors, the date, and the analog clock appear from firmware ${r.value}; until that update, this screen shows the name and, if the time is in the bar, the clock.`),c=(z,B)=>{const Y=Rt(z);return Y.shown?l.value.has(B)?"Doesn't fit next to the name":Y.analog?"Dial":Y.text:"Hidden: not active right now"},f=z=>{const B=Rt(z);return B.analog||z.type!=="entity"?es(Zl[z.type])?.cp:B.icon},b=z=>d.topbarAdded?.key===He(z)&&Date.now()-d.topbarAdded.time<1200;function A(z){d.layout&&(d.layout.title=z,et())}function D(z){const B=[...n.value];B[t.index]={...B[t.index],...z},qn(B)}const I=k(()=>s.value?Rt(s.value).shown?l.value.has(t.index)?"Doesn't currently fit next to the name":"How it looks on the screen":"Hidden right now: not active":""),R=k(()=>yn().clock_24h!==!1),T=k(()=>({clock:Bo(R.value,new Date(d.now)),analog:"Small dial with the time",date:Uo(new Date(d.now))})),$=fe({index:-1,active:!1,moved:!1});let x=null,w=0,m=null,H=0;function C(z,B){z.button!==0||z.target.closest(".x")||(z.pointerType!=="touch"&&z.preventDefault(),$.value={index:B,active:!1,moved:!1},x={x:z.clientX,y:z.clientY},m=z.pointerId,clearTimeout(w),z.pointerType==="touch"&&(w=window.setTimeout(L,260)),document.addEventListener("pointermove",Ae),document.addEventListener("pointerup",J),document.addEventListener("pointercancel",J))}function L(){$.value.active=!0,document.addEventListener("touchmove",pe,{passive:!1})}function pe(z){$.value.active&&z.preventDefault()}function Ae(z){if(z.pointerId!==m||!x)return;if(!$.value.active){const oe=Math.hypot(z.clientX-x.x,z.clientY-x.y);if(z.pointerType==="touch"){oe>10&&(clearTimeout(w),x=null);return}if(oe<6)return;L()}const B=[...document.querySelectorAll(".items .item[data-index]")];let Y=$.value.index;if(B.forEach((oe,ie)=>{const ue=oe.getBoundingClientRect();ie<$.value.index&&z.clientY$.value.index&&z.clientY>ue.top+ue.height/2&&(Y=Math.max(Y,ie))}),Y!==$.value.index&&d.layout){const oe=[...n.value];oe.splice(Y,0,...oe.splice($.value.index,1)),d.layout.header={items:oe};const ie=t.index===$.value.index;$.value.index=Y,$.value.moved=!0,ie&&Ct(Y)}}function J(z){z.pointerId===m&&(clearTimeout(w),document.removeEventListener("pointermove",Ae),document.removeEventListener("pointerup",J),document.removeEventListener("pointercancel",J),document.removeEventListener("touchmove",pe),$.value.active&&(H=Date.now()+400,$.value.moved&&et()),$.value={index:-1,active:!1,moved:!1},x=null,m=null)}function q(z){Date.now()(h(),g(W,null,[i("div",Xp,[i("span",Qp,y(s.value?v(ke)(f(s.value)||"F0150"):v(ke)("F0150")),1),i("span",Zp,[i("b",null,y(s.value?s.value.type==="entity"?v(Zn)(s.value.entity):v(Tn)(s.value):"Top bar"),1),i("small",{class:re({mono:s.value?.type==="entity"})},y(s.value?s.value.type==="entity"?s.value.entity:"From the screen itself, also works without Home Assistant":`${n.value.length} of ${v(Bt)()} items`),3)]),i("button",{type:"button",class:"icon-btn","aria-label":"Close",onClick:B[0]||(B[0]=(...Y)=>v(je)&&v(je)(...Y))},"✕")]),i("div",eh,[i("div",th,[B[10]||(B[10]=i("label",{class:"f-label",for:"title"},"Left: name",-1)),i("input",{id:"title",value:v(d).layout?.title,maxlength:"60",placeholder:"For example: Living room",onInput:B[1]||(B[1]=Y=>A(Y.target.value))},null,40,nh)]),i("div",sh,[i("span",oh,[B[11]||(B[11]=Q("Right: time, sensors, or a clock ",-1)),i("span",ih," · "+y(n.value.length)+" / "+y(v(Bt)()),1)]),i("div",lh,[(h(!0),g(W,null,le(n.value,(Y,oe)=>(h(),g("div",{key:v(He)(Y)+oe,class:re(["item",{selected:oe===e.index,"is-hidden":!v(Rt)(Y).shown,"is-overflow":l.value.has(oe),"just-added":b(Y),"dragging-chip":$.value.active&&$.value.index===oe}]),role:"listitem",tabindex:"0","data-index":oe,"aria-label":`${v(Tn)(Y)}, slot ${oe+1}. Enter: configure, arrows: move`,onPointerdown:ie=>C(ie,oe),onClick:ie=>q(oe),onKeydown:ie=>ae(ie,oe)},[B[12]||(B[12]=i("span",{class:"grip","aria-hidden":"true"},"⋮⋮",-1)),i("span",{class:"av mdi",style:Ne(v(Rt)(Y).color?{color:v(Rt)(Y).color}:void 0)},y(f(Y)?v(ke)(f(Y)):""),5),i("span",rh,[i("b",null,y(v(Tn)(Y)),1),i("small",null,y(c(Y,oe)),1)]),i("button",{type:"button",class:"x","aria-label":`Remove ${v(Tn)(Y)} from the top bar`,onClick:Ft(ie=>v(ji)(oe),["stop"])},"✕",8,uh)],42,ah))),128)),i("button",{type:"button",class:"ghost-btn",id:"topbar-add",disabled:n.value.length>=v(Bt)(),title:n.value.length>=v(Bt)()?`Maximum ${v(Bt)()} items`:"Add the time, date, analog clock, or an entity",onClick:B[2]||(B[2]=(...Y)=>v(Ri)&&v(Ri)(...Y))},"+ Add time, date, or an entity",8,ch)]),i("small",{id:"topbar-hint",class:re({warn:l.value.size>0&&u.value})},y(a.value),3)]),s.value?(h(),g(W,{key:0},[i("div",dh,[i("small",null,y(I.value),1),_e(va,{items:[s.value],single:""},null,8,["items"])]),s.value.type==="entity"?(h(),g(W,{key:0},[i("div",fh,[B[13]||(B[13]=i("span",{class:"f-label"},"What to show",-1)),_e(nt,{choices:(v(d).inventory.header?.contents||[]).map(Y=>[Y.key,Y.label]),value:s.value.content,onPick:B[3]||(B[3]=Y=>D({content:Y}))},null,8,["choices","value"]),B[14]||(B[14]=i("small",null,"Last changed keeps counting on the screen itself: “Just now”, “5 min ago”, “Yesterday”.",-1))]),_e(ma,{selected:s.value.icon||"auto",automatic:v(d).topbarPreviews[v(He)(s.value)]?.auto_icon||v(on)(s.value.entity),"auto-label":"Automatic (like Home Assistant)","allow-none":"",onPick:B[4]||(B[4]=Y=>D({icon:Y}))},null,8,["selected","automatic"]),i("div",ph,[B[15]||(B[15]=i("span",{class:"f-label"},"Show",-1)),_e(nt,{choices:(v(d).inventory.header?.shows||[]).map(Y=>[Y.key,Y.label]),value:s.value.show,onPick:B[5]||(B[5]=Y=>D({show:Y}))},null,8,["choices","value"]),B[16]||(B[16]=i("small",null,"Only when active hides the item as long as it's off, closed, away, or 0. Handy for an open door, a running washing machine, or who's home.",-1))])],64)):s.value.type!=="date"?(h(),g("div",hh,[B[17]||(B[17]=i("span",{class:"f-label"},"Format",-1)),_e(nt,{choices:[["24","24 hour"],["12","12 hour"]],value:R.value?"24":"12",onPick:B[6]||(B[6]=Y=>v(An)("clock_24h",Y==="24",150))},null,8,["value"]),B[18]||(B[18]=i("small",null,"The screen's own clock setting: it applies at once to every clock on this screen, including the clock tiles.",-1))])):(h(),g("small",vh,y(T.value.date)+" today. The date follows the screen's own clock.",1))],64)):V("",!0)]),s.value?(h(),g("div",mh,[i("button",{type:"button",class:"btn danger",onClick:B[7]||(B[7]=Y=>v(ji)(e.index))},"Remove"),B[19]||(B[19]=i("span",{class:"spacer"},null,-1)),i("button",{type:"button",class:"btn quiet",disabled:e.index===0,onClick:B[8]||(B[8]=Y=>v(so)(e.index,e.index-1)&&v(Ct)(e.index-1))},"↑ Up",8,gh),i("button",{type:"button",class:"btn quiet",disabled:e.index>=n.value.length-1,onClick:B[9]||(B[9]=Y=>v(so)(e.index,e.index+1)&&v(Ct)(e.index+1))},"↓ Down",8,yh)])):V("",!0)],64))}}),wh={class:"dr-head"},_h={class:"tx"},kh={class:"dr-body"},$h={class:"f"},xh={class:"options"},Sh=["disabled","onClick"],Ch={class:"mdi"},Th={class:"tx"},Ah={key:0,class:"f"},Eh={class:"options"},Ph=["disabled","onClick"],Oh={class:"mdi"},Ih={class:"tx"},Mh={class:"f"},Dh={class:"options"},Lh=["disabled","onClick"],Fh={class:"mdi"},Hh={class:"tx"},Rh={key:0,class:"hint"},Nh={key:1,class:"hint"},jh={class:"dr-foot"},Bh=$e({__name:"TopbarAdd",setup(e){const t=fe(""),n=k(()=>new Set(Dt().map(He))),s=k(()=>yn().clock_24h!==!1),o=k(()=>({clock:Bo(s.value,new Date(d.now)),analog:"Small dial with the time",date:Uo(new Date(d.now))})),l=k(()=>d.inventory.header?.suggestions?.[d.selected||""]||[]),r=k(()=>{const a=t.value.trim().toLocaleLowerCase();return d.inventory.entities.filter(c=>`${c.name} ${c.id} ${c.area||""} ${c.device||""}`.toLocaleLowerCase().includes(a))}),u=a=>({type:"entity",entity:a,content:"state",icon:"auto",show:"always"});return(a,c)=>(h(),g(W,null,[i("div",wh,[c[4]||(c[4]=i("span",{class:"av",style:{background:"var(--seg)",color:"var(--ink-2)","font-size":"18px"}},"+",-1)),i("span",_h,[c[3]||(c[3]=i("b",null,"Add to the top bar",-1)),i("small",null,y(v(Dt)().length)+" of "+y(v(Bt)())+" slots used",1)]),i("button",{type:"button",class:"icon-btn","aria-label":"Close",onClick:c[0]||(c[0]=(...f)=>v(je)&&v(je)(...f))},"✕")]),i("div",kh,[i("div",$h,[c[5]||(c[5]=i("span",{class:"f-label"},"From the screen itself",-1)),i("div",xh,[(h(!0),g(W,null,le(v(d).inventory.header?.builtin||[],f=>(h(),g("button",{key:f.type,type:"button",class:"option",disabled:n.value.has(v(He)({type:f.type})),onClick:b=>v(oo)({type:f.type})},[i("span",Ch,y(v(ke)(v(es)(v(Zl)[f.type])?.cp||"F0150")),1),i("span",Th,[i("strong",null,y(f.label),1),i("small",null,y(n.value.has(v(He)({type:f.type}))?"Already added":o.value[f.type]),1)])],8,Sh))),128))])]),l.value.length?(h(),g("div",Ah,[c[6]||(c[6]=i("span",{class:"f-label"},"Suggestions from Home Assistant",-1)),i("div",Eh,[(h(!0),g(W,null,le(l.value,f=>(h(),g("button",{key:v(He)(f.item),type:"button",class:"option",disabled:n.value.has(v(He)(f.item)),onClick:b=>v(oo)(f.item)},[i("span",Oh,y(v(ke)(f.icon||v(on)(f.item.entity))),1),i("span",Ih,[i("strong",null,y(f.label),1),i("small",null,y(n.value.has(v(He)(f.item))?"Already added":[f.name,f.area].filter(Boolean).join(" · ")),1)])],8,Ph))),128))])])):V("",!0),i("div",Mh,[c[7]||(c[7]=i("label",{class:"f-label",for:"topbar-search"},"An entity",-1)),Te(i("input",{id:"topbar-search","onUpdate:modelValue":c[1]||(c[1]=f=>t.value=f),type:"search",placeholder:"Search by name, room, or entity, e.g. temperature or door","aria-label":"Search for an entity for the top bar"},null,512),[[Je,t.value]]),i("div",Dh,[(h(!0),g(W,null,le(r.value.slice(0,40),f=>(h(),g("button",{key:f.id,type:"button",class:"option",disabled:n.value.has(v(He)(u(f.id))),onClick:b=>v(oo)(u(f.id))},[i("span",Fh,y(v(ke)(v(on)(f.id))),1),i("span",Hh,[i("strong",null,y(f.name),1),i("small",null,y([f.area,f.id].filter(Boolean).join(" · ")),1)])],8,Lh))),128)),r.value.length?r.value.length>40?(h(),g("p",Nh,y(r.value.length)+" results. Keep typing to narrow it down.",1)):V("",!0):(h(),g("p",Rh,"No entities found."))])])]),i("div",jh,[c[8]||(c[8]=i("span",{class:"spacer"},null,-1)),i("button",{type:"button",class:"btn quiet",onClick:c[2]||(c[2]=(...f)=>v(je)&&v(je)(...f))},"Cancel")])],64))}}),Uh={class:"dr-head"},Vh={class:"tx"},Wh={class:"dr-body",id:"inspector-section"},Kh={id:"inspection-summary"},qh={key:0,class:"hint warn"},Yh={key:1,class:"hint"},zh={id:"inspection"},Gh=$e({__name:"InspectPanel",props:{entity:{}},setup(e){const t=e,n=fe(null),s=fe("Reading…"),o=fe("");async function l(){if(d.selected){n.value=null,o.value="",s.value="Fetching current HA status...";try{const u=await Mt(`screens/${encodeURIComponent(d.selected)}/inspect`),a=t.entity?u.tiles.filter(c=>c.entity===t.entity):u.tiles;n.value=a,s.value=JSON.stringify(t.entity?a[0]:u,null,2)}catch(u){o.value=u.message,s.value="",Se(u.message)}}}const r=u=>{const a=d.layout?.tiles.find(c=>c.entity===u)?.options||{};return`Small slider: ${a.inline==="slider"?"yes":"no"} · Display: ${aa[a.display||"standard"]||a.display} · Width: ${a.size==="wide"?"double":"normal"} · Control: ${oc({entity:u,options:a},d.inventory)} · Background: ${d.inventory.backgrounds?.[a.background||"auto"]?.label||"Default"}`};return bn(l),In(()=>t.entity,l),(u,a)=>(h(),g(W,null,[i("div",Uh,[a[2]||(a[2]=i("span",{class:"av",style:{background:"var(--seg)",color:"var(--ink-2)","font-size":"16px"}},"⌕",-1)),i("span",Vh,[a[1]||(a[1]=i("b",null,"Current data",-1)),i("small",{class:re({mono:e.entity})},y(e.entity||"Connection, status, and supported properties"),3)]),i("button",{type:"button",class:"icon-btn","aria-label":"Close",onClick:a[0]||(a[0]=(...c)=>v(je)&&v(je)(...c))},"✕")]),i("div",Wh,[i("div",Kh,[o.value?(h(),g("p",qh,y(o.value),1)):n.value?V("",!0):(h(),g("p",Yh,"Fetching current HA status...")),(h(!0),g(W,null,le(n.value||[],c=>(h(),g("article",{key:c.entity,class:"inspection-tile"},[i("strong",null,y(c.entity),1),i("span",null,"Status: "+y(c.word||c.state),1),i("small",null,y(r(c.entity)),1)]))),128))]),i("pre",zh,y(s.value),1)]),i("div",{class:"dr-foot"},[i("button",{type:"button",class:"btn quiet",onClick:l},"Read again"),a[3]||(a[3]=i("span",{class:"spacer"},null,-1))])],64))}}),Jh=["aria-hidden"],Xh=$e({__name:"Drawer",setup(e){const t=k(()=>!!(d.inspector&&(d.inspector.kind!=="tile"||Zs.value)));return(n,s)=>(h(),g("aside",{class:re(["drawer",{open:t.value}]),id:"tile-sheet","aria-hidden":t.value?"false":"true",onClick:s[0]||(s[0]=Ft(()=>{},["stop"]))},[v(d).inspector?(h(),g(W,{key:0},[v(d).inspector.kind==="tile"&&v(Zs)?(h(),Ve(Jp,{key:0,tile:v(Zs)},null,8,["tile"])):v(d).inspector.kind==="bar"?(h(),Ve(bh,{key:1,index:v(d).inspector.index},null,8,["index"])):v(d).inspector.kind==="bar-add"?(h(),Ve(Bh,{key:2})):v(d).inspector.kind==="inspect"?(h(),Ve(Gh,{key:3,entity:v(d).inspector.entity},null,8,["entity"])):V("",!0)],64)):V("",!0)],10,Jh))}}),Qh={class:"main-head"},Zh={class:"eyebrow",id:"screen-name"},ev=["title"],tv={class:"head-right"},nv={class:"seg",role:"tablist"},sv=["aria-pressed"],ov=["aria-pressed"],iv={key:1,id:"dirty",class:"chip dirty"},lv=["disabled"],av={key:0,class:"spin small"},rv=["aria-expanded"],uv={key:3,class:"menu",role:"menu"},cv=["disabled","title"],dv={class:"body",id:"body"},fv=$e({__name:"ScreenView",setup(e){const t=k(()=>qt.value),n=k(()=>t.value.online?`${t.value.delivery} · ${t.value.status}`:"Offline · changes are saved"),s=k(()=>t.value.update?.available&&t.value.online&&t.value.update?.profile);function o(){d.menuOpen=!1,d.overrideProfile=t.value.update?.profile||null,d.overrideFriendly=t.value.name,De("#override")}function l(){d.menuOpen=!1,d.selectedTile=null,d.inspector={kind:"inspect"}}function r(a){a.key==="Escape"&&(d.menuOpen?d.menuOpen=!1:d.inspector&&!a.target?.closest?.(".picker")&&je())}function u(a){d.menuOpen&&!a.target.closest(".head-right .menu, #more")&&(d.menuOpen=!1)}return bn(()=>{document.addEventListener("keydown",r),document.addEventListener("click",u)}),Xn(()=>{document.removeEventListener("keydown",r),document.removeEventListener("click",u)}),(a,c)=>(h(),g(W,null,[i("header",Qh,[i("div",null,[i("span",Zh,y(t.value.name),1),i("h1",null,y(v(d).layout?.title||"Home"),1)]),i("span",{id:"delivery",class:re(["chip",{off:!t.value.online}]),title:n.value},[c[6]||(c[6]=i("span",{class:"dot"},null,-1)),Q(y(n.value),1)],10,ev),i("div",tv,[i("div",nv,[i("button",{type:"button",id:"tab-layout",role:"tab","aria-pressed":v(d).tab==="layout"?"true":"false",onClick:c[0]||(c[0]=f=>v(d).tab="layout")},"Layout",8,sv),i("button",{type:"button",id:"tab-settings",role:"tab","aria-pressed":v(d).tab==="settings"?"true":"false",onClick:c[1]||(c[1]=f=>{v(d).tab="settings",v(je)()})},"Screen settings",8,ov)]),v(d).dirty?(h(),g("span",iv,"Unsaved changes")):(h(),g("span",{key:0,id:"dirty",class:re(["chip",{sent:v(d).saved}])},y(v(d).saved?"Saved · sent to screen":"All saved"),3)),v(d).dirty?(h(),g("button",{key:2,id:"save",type:"button",class:"btn primary",disabled:v(d).busy,onClick:c[2]||(c[2]=f=>v(gc)())},[v(d).busy?(h(),g("span",av)):V("",!0),Q(y(v(d).busy?"Saving…":"Save & send"),1)],8,lv)):V("",!0),i("button",{id:"more",type:"button",class:"icon-btn","aria-label":"More","aria-haspopup":"menu","aria-expanded":v(d).menuOpen?"true":"false",onClick:c[3]||(c[3]=Ft(f=>v(d).menuOpen=!v(d).menuOpen,["stop"]))},"···",8,rv),v(d).menuOpen?(h(),g("div",uv,[i("button",{type:"button",role:"menuitem",id:"inspect",onClick:l},[...c[7]||(c[7]=[Q("Read current data ",-1),i("small",null,"from Home Assistant",-1)])]),i("button",{type:"button",role:"menuitem",id:"open-override",disabled:!t.value.update?.profile,title:t.value.update?.profile?"":"No ESPHome profile found for this screen",onClick:o},[...c[8]||(c[8]=[Q("Override YAML ",-1),i("small",null,"advanced",-1)])],8,cv),i("button",{type:"button",role:"menuitem",onClick:c[4]||(c[4]=f=>{v(d).menuOpen=!1,v(De)("#firmware")})},"Firmware & USB"),s.value?(h(),g("button",{key:0,type:"button",role:"menuitem",onClick:c[5]||(c[5]=f=>{v(d).menuOpen=!1,a.$emit("update")})},[c[9]||(c[9]=Q("Update firmware ",-1)),i("small",null,y(t.value.update?.target),1)])):V("",!0)])):V("",!0)])]),i("div",dv,[v(d).tab==="layout"?(h(),Ve(Cf,{key:0})):(h(),Ve(Uf,{key:1})),_e(Xh)])],64))}}),pv={key:0,id:"choose",class:"empty"},hv={key:1,id:"empty",class:"empty"},vv=$e({__name:"EmptyState",setup(e){return(t,n)=>v(d).inventory.screens.length?(h(),g("section",pv,[...n[1]||(n[1]=[i("span",{class:"empty-icon"},"▦",-1),i("h2",null,"Choose a screen",-1),i("p",null,"Pick one of your screens on the left to change its tiles, top bar and settings.",-1)])])):(h(),g("section",hv,[n[2]||(n[2]=i("span",{class:"empty-icon"},"▦",-1)),n[3]||(n[3]=i("h2",null,"Start with a screen",-1)),n[4]||(n[4]=i("p",null,"Connect a CYD or Guition via USB to your Home Assistant machine. Profile, firmware, and the first flash happen in one go.",-1)),i("button",{id:"start",type:"button",class:"btn primary",onClick:n[0]||(n[0]=s=>v(De)("#new-screen"))},"Install new screen")]))}}),mv={class:"panel",id:"settings-view"},gv={class:"panel-head"},yv={class:"card-grid"},bv={class:"card"},wv={class:"tools"},_v={key:0,class:"card updates",id:"updates"},kv={id:"updates-hint"},$v={class:"check"},xv=["checked"],Sv={class:"card"},Cv={class:"tools"},Tv={class:"card",id:"claude"},Av={class:"actions"},Ev=["disabled"],Pv={id:"claude-path"},Ov=$e({__name:"AppSettingsView",setup(e){const t=k(()=>d.inventory.updates),n=k(()=>d.inventory.screens.filter(u=>u.update?.available).length),s=k(()=>t.value?t.value.busy?`Updating to firmware ${t.value.target}…`:d.inventory.screens.length?n.value?`Firmware ${t.value.target} is available for ${n.value} screen${n.value===1?"":"s"}.`:`All screens have firmware ${t.value.target}.`:`No screen paired yet. New screens get firmware ${t.value.target}.`:""),o=k(()=>d.inventory.claude_skill),l=fe(!1);async function r(){l.value=!0;try{await Sc()}finally{l.value=!1}}return(u,a)=>(h(),g("div",mv,[i("div",gv,[a[6]||(a[6]=i("div",{class:"tx"},[i("span",{class:"eyebrow"},"Settings"),i("h1",{id:"settings-title"},"Everything around your screens.")],-1)),i("button",{type:"button",class:"btn quiet",id:"close-settings",onClick:a[0]||(a[0]=c=>v(De)(""))},"← My screens")]),i("div",yv,[i("section",bv,[a[9]||(a[9]=i("h2",null,"Screens",-1)),a[10]||(a[10]=i("p",null,"Add a screen, or build and reinstall the firmware of one you already have.",-1)),i("div",wv,[i("button",{type:"button",class:"tool",onClick:a[1]||(a[1]=c=>v(De)("#new-screen"))},[...a[7]||(a[7]=[i("span",{class:"tool-icon"},"+",-1),i("span",{class:"tx"},[i("b",null,"New screen"),i("small",null,"Connect and install")],-1)])]),i("button",{type:"button",class:"tool",onClick:a[2]||(a[2]=c=>v(De)("#firmware"))},[...a[8]||(a[8]=[i("span",{class:"tool-icon"},"⇪",-1),i("span",{class:"tx"},[i("b",null,"Firmware & USB"),i("small",null,"Build and install via USB or Wi-Fi")],-1)])])])]),t.value?(h(),g("section",_v,[a[12]||(a[12]=i("h2",null,"Firmware updates",-1)),i("p",kv,y(s.value),1),t.value.pending&&!t.value.busy&&t.value.pending>=2?(h(),g("button",{key:0,id:"update-all",type:"button",class:"btn primary",onClick:a[3]||(a[3]=(...c)=>v(Vi)&&v(Vi)(...c))},"Update all "+y(t.value.pending)+" screens",1)):V("",!0),i("label",$v,[i("input",{type:"checkbox",id:"auto-update",checked:!!t.value.auto,onChange:a[4]||(a[4]=c=>v(xc)(c.target.checked))},null,40,xv),a[11]||(a[11]=i("span",null,[Q("Update automatically every night"),i("small",null,"Between 03:00 and 06:00, one screen at a time. Stops on an error and reports it in Home Assistant.")],-1))])])):V("",!0),i("section",Sv,[a[14]||(a[14]=i("h2",null,"Alerts",-1)),a[15]||(a[15]=i("p",null,"A card over the whole screen from an automation, on one screen or on all of them. The cheatsheet has the action names, fields, icons, and colors.",-1)),i("div",Cv,[i("button",{type:"button",class:"tool",onClick:a[5]||(a[5]=c=>v(De)("#alerts"))},[...a[13]||(a[13]=[i("span",{class:"tool-icon"},"!",-1),i("span",{class:"tx"},[i("b",null,"Alerts"),i("small",null,"Full-screen notifications, from an automation")],-1)])])])]),i("section",Tv,[a[18]||(a[18]=i("h2",null,"Claude",-1)),a[19]||(a[19]=i("p",null,'Teach Claude about ESP Screens, then ask: "Show an alert on all my screens when the mailbox is full." Claude knows the alert events, every field, color, and icon.',-1)),i("div",Av,[i("button",{type:"button",id:"claude-install",class:re(["btn",o.value?.installed&&o.value.current?"quiet":"primary"]),disabled:!o.value||l.value,onClick:r},y(!o.value||!o.value.installed?"Install for Claude Code":o.value.current?"Install again":"Update the skill"),11,Ev),i("span",{id:"claude-status",class:re(["chip",o.value&&o.value.installed?o.value.current?"good":"update":""]),role:"status"},y(o.value?o.value.installed?o.value.current?"● Installed":"Installed · a newer version is ready":"Not installed":"Loading…"),3)]),i("small",null,[a[16]||(a[16]=Q("For Claude Code in Home Assistant. Writes one file to ",-1)),i("code",Pv,y(o.value?.path||"/homeassistant/.claude/skills/esp-screens"),1),a[17]||(a[17]=Q("; installing again replaces it.",-1))]),a[20]||(a[20]=i("div",{class:"actions"},[i("a",{class:"btn quiet",id:"claude-download",href:"api/claude-skill.zip",download:"esp-screens.zip"},"Download for claude.ai"),i("small",null,"Upload the zip in Claude under Customize → Skills.")],-1))])])]))}}),Iv={class:"panel",id:"installer"},Mv={class:"panel-head"},Dv={class:"tx"},Lv={id:"install-title"},Fv={key:0},Hv={class:"boards"},Rv={class:"board"},Nv={class:"board"},jv={class:"field"},Bv={class:"node-line"},Uv={id:"node-preview"},Vv={key:0,class:"field",id:"node-label"},Wv={key:1,id:"wifi-fields",class:"wifi"},Kv={class:"hint",id:"wifi-status"},qv={key:0,class:"field",id:"wifi-ssid-label"},Yv={key:1,class:"field",id:"wifi-password-label"},zv={class:"field"},Gv={key:0,value:"usb"},Jv=["value"],Xv={id:"target-hint"},Qv={key:2,class:"hint",id:"install-note"},Zv={class:"actions"},em=["disabled"],tm={id:"install-status",class:"status-line error",role:"status"},nm={key:1,id:"install-progress",class:"card"},sm={class:"progress-head"},om={key:0,class:"spin",id:"progress-spin"},im={id:"progress-title"},lm={id:"progress-detail"},am={key:0,id:"install-download",class:"card",style:{background:"var(--surface-2)"}},rm=["href","download"],um={class:"steps",id:"download-steps"},cm={key:1,id:"install-result",class:"field"},dm={class:"key-box"},fm={class:"steps",id:"install-steps"},pm=["open"],hm={id:"install-log",class:"log"},vm={class:"actions"},mm="https://web.esphome.io/?dashboard_install",gm="Download · flash from your own computer",ym=$e({__name:"InstallerView",setup(e){const t=hn({board:"cyd",friendly_name:"",name:"",wifi_ssid:"",wifi_password:"",target:""}),n=hn({view:"setup",file:null,friendly:"",board:"cyd",target:"",apiKey:null,nodeEdited:!1,jobState:null,picked:!1,action:null}),s=fe(!1),o=fe(null),l=fe(null),r=fe([]),u=fe(""),a=fe(""),c=fe(!1),f=fe(!1),b=fe(null);let A=0;function D(ce){return ce.toLowerCase().normalize("NFD").replace(/[̀-ͯ]/g,"").replace(/[^a-z0-9]+/g,"-").replace(/^[^a-z]+/,"").slice(0,30).replace(/-+$/,"")||"screen"}function I(ce){const M=ce.replace(/^\/dev\/serial\/by-id\/usb-/,"").replace(/-if\d+(-port\d+)?$/,"").replace(/_/g," ");return`USB · ${M===ce?ce.replace(/^\/dev\//,""):M}`}In(()=>t.friendly_name,()=>{n.nodeEdited||(t.name=D(t.friendly_name))});const R=k(()=>t.name||"…"),T=k(()=>o.value?.ports||[]),$=k(()=>o.value?.wifi),x=k(()=>$.value?.state==="new"||$.value?.state==="missing"),w=k(()=>$.value?.missing||[]),m=k(()=>$.value?.state==="new"?"Fill in once: ESP Screens saves this in ESPHome secrets.yaml, later screens use it automatically.":"Your ESPHome secrets.yaml is still missing Wi-Fi details. ESP Screens only fills in the missing lines."),H=k(()=>$.value?.state==="ready"?"Wi-Fi comes from your ESPHome secrets.yaml.":$.value?.state==="invalid"?"secrets.yaml in the ESPHome folder isn't valid YAML. Fix the file first; it won't be overwritten.":""),C=k(()=>t.target==="usb"?"Connect the screen with a USB data cable to the Home Assistant machine; the list refreshes on its own. Or choose Download to use your own computer.":t.target==="download"?"Download the firmware and put it on the screen from your own computer, in Chrome or Edge. After that, updates go over Wi-Fi.":t.target?T.value.length>1?"More than one board connected: choose this screen's port.":"Once over USB; after that, everything is wireless.":"The profile goes into the ESPHome folder. You can install later via Firmware & USB, or from ESPHome Device Builder."),L=k(()=>t.target==="download"?"Build & download":t.target?"Install":"Save profile"),pe=k(()=>o.value?.job?.state==="running"&&!(n.file&&o.value.job.file===n.file)),Ae=k(()=>c.value||$.value?.state==="invalid"||t.target==="usb"||!!t.target&&(pe.value||!o.value?.available));function J(){const ce=t.target;(ce==="download"||ce===""?n.picked:T.value.includes(ce))||(t.target=T.value[0]||"usb")}async function q(){let ce;try{ce=await Mt("firmware")}catch(Ge){u.value=Ge.message;return}o.value=ce;const M=ce.job,se=M&&n.file&&M.file===n.file;if(se&&(n.jobState=M.state),n.view==="setup"){if(se&&M.state==="running"){ae(M,ce.logs||[]);return}J(),u.value=pe.value?`A build or installation is already running (${M.file}). Wait for it to finish.`:!ce.available&&t.target?"The ESPHome CLI is missing from this installation; only saving the profile is possible.":H.value}else n.view==="progress"&&se&&(l.value=M,r.value=ce.logs||[],M.state!=="running"&&M.state!=="success"&&(f.value=!0))}function ae(ce,M){n.view="progress",n.jobState=ce.state,n.action=ce.action,l.value=ce,r.value=M}const z=k(()=>l.value?.state==="running"),B=k(()=>n.view==="done"||l.value?.state==="success"),Y=k(()=>n.action==="download"),oe=k(()=>n.view==="done"?"Profile saved.":z.value?"One moment…":B.value?Y.value?"Ready to download.":"Done.":"That didn't work."),ie=k(()=>n.view==="done"?`${n.file} is in the ESPHome folder`:z.value?l.value?.stage==="upload"?`Writing firmware to ${n.friendly}…`:"Building firmware…":B.value?Y.value?`Firmware for ${n.friendly} is ready`:`Firmware is on ${n.friendly}`:Y.value?"Build failed":"Install failed"),ue=k(()=>n.view==="done"?"Install it later from Firmware & USB: choose this profile, then the USB port of the Home Assistant machine, or Download to put the firmware on the screen from your own computer. Save the API key for pairing:":z.value?l.value?.stage==="upload"?"Don't disconnect the USB cable yet.":`A first build takes a few minutes on a Raspberry Pi. You can leave this page: the ${Y.value?"build":"installation"} keeps running and you'll find it again under New screen.`:B.value?Y.value?"Put it on the screen from your own computer, then pair the screen with Home Assistant.":`The screen boots up and connects to your Wi-Fi.${n.board==="cyd"?" The CYD first asks for a touch calibration: tap the crosshairs.":""} Pair it with Home Assistant now:`:r.value.filter(ce=>/error/i.test(ce)).pop()||r.value.filter(ce=>/failed/i.test(ce)).pop()||"See the log below."),ze=k(()=>({href:`api/firmware/profiles/${encodeURIComponent(n.file||"")}/download`,name:(n.file||"").replace(/\.yaml$/,"")+".factory.bin"})),an=k(()=>[["Go to Home Assistant → Settings → Devices & services.",` This happens outside ESP Screens. Home Assistant discovers ${n.friendly} as an ESPHome device; click Add. Not discovered? Add ESPHome manually with the screen's IP address. `],["Paste the API key"," above when Home Assistant asks for an encryption key."],["Allow HA actions:"," ESPHome integration → Configure → “Allow the device to perform Home Assistant actions”. Without this, the screen sees everything but controls nothing."],["Choose your tiles."," Back in ESP Screens, the screen appears in the list on the left within about thirty seconds; until then it's shown there as “not yet in Home Assistant”."]]);async function _t(ce){const M=ce.target;if(n.nodeEdited||(t.name=D(t.friendly_name)),!!M.reportValidity()){c.value=!0,a.value="";try{const se={board:t.board,friendly_name:t.friendly_name,name:t.name,target:t.target};x.value&&(w.value.includes("wifi_ssid")&&(se.wifi_ssid=t.wifi_ssid),w.value.includes("wifi_password")&&(se.wifi_password=t.wifi_password));const Ge=await it("firmware/profiles","POST",se);Object.assign(n,{file:Ge.file,apiKey:Ge.api_key,friendly:t.friendly_name.trim(),board:t.board,target:t.target}),t.wifi_password="",Ge.job?ae(Ge.job,[]):n.view="done"}catch(se){a.value=se.message}finally{c.value=!1}}}async function We(){try{if(!Y.value){const{ports:M}=await Mt("firmware");!M.includes(n.target)&&M.length===1&&(n.target=M[0])}const ce=await it("firmware/jobs","POST",Y.value?{file:n.file,action:"download"}:{file:n.file,action:"install",target:n.target});ae(ce,[])}catch(ce){Se(ce.message)}}function ts(){Object.assign(n,{view:"setup",file:null,apiKey:null,nodeEdited:!1,jobState:null,target:"",picked:!1,action:null}),Object.assign(t,{board:"cyd",friendly_name:"",name:"",wifi_ssid:"",wifi_password:"",target:""}),s.value=!1,l.value=null,r.value=[],a.value="",u.value="",f.value=!1,q()}function ns(){n.view==="progress"&&n.jobState!=="running"&&(n.view="done"),De("")}return bn(()=>{q(),A=window.setInterval(q,3e3)}),Xn(()=>clearInterval(A)),(ce,M)=>(h(),g("div",Iv,[i("div",Mv,[i("div",Dv,[M[13]||(M[13]=i("span",{class:"eyebrow"},"New screen",-1)),i("h1",Lv,y(n.view==="setup"?"Connect and install.":oe.value),1),n.view==="setup"?(h(),g("p",Fv,"ESP Screens creates the screen's own profile with unique keys and builds the firmware. Connect the screen with a USB data cable to the machine running Home Assistant, or download the firmware and put it on the screen from your own computer.")):V("",!0)]),i("button",{type:"button",class:"btn quiet",id:"close-install","aria-label":"Close",onClick:ns},"← Back")]),n.view==="setup"?(h(),g("form",{key:0,id:"install-form",class:"card",onSubmit:Ft(_t,["prevent"])},[i("fieldset",null,[M[16]||(M[16]=i("legend",null,"Which screen do you have?",-1)),i("div",Hv,[i("label",Rv,[Te(i("input",{type:"radio",name:"board",value:"cyd","onUpdate:modelValue":M[0]||(M[0]=se=>t.board=se)},null,512),[[Oi,t.board]]),M[14]||(M[14]=i("span",null,[i("b",null,"CYD · 2.8 inch"),i("small",null,"ESP32-2432S028 · 320 × 240")],-1))]),i("label",Nv,[Te(i("input",{type:"radio",name:"board",value:"guition","onUpdate:modelValue":M[1]||(M[1]=se=>t.board=se)},null,512),[[Oi,t.board]]),M[15]||(M[15]=i("span",null,[i("b",null,"Guition · 4 inch"),i("small",null,"ESP32-S3-4848S040 · 480 × 480 · GT911")],-1))])])]),i("div",jv,[M[18]||(M[18]=i("label",{class:"f-label",for:"friendly_name"},"Name",-1)),Te(i("input",{id:"friendly_name",name:"friendly_name","onUpdate:modelValue":M[2]||(M[2]=se=>t.friendly_name=se),required:"",maxlength:"60",placeholder:"Living room screen",autocomplete:"off"},null,512),[[Je,t.friendly_name]]),i("small",Bv,[M[17]||(M[17]=Q("Device name ",-1)),i("code",Uv,y(R.value),1),i("button",{type:"button",class:"btn link mini",id:"edit-node",onClick:M[3]||(M[3]=se=>{n.nodeEdited=!0,s.value=!0})},"customize")]),M[19]||(M[19]=i("small",null,"Every screen gets its own profile with its own keys. Four screens? Go through this four times with a different name.",-1))]),s.value?(h(),g("div",Vv,[M[20]||(M[20]=i("label",{class:"f-label",for:"node-name"},"Device name",-1)),Te(i("input",{id:"node-name",name:"name","onUpdate:modelValue":M[4]||(M[4]=se=>t.name=se),pattern:"[a-z][a-z0-9\\-]{0,29}",maxlength:"30",autocomplete:"off",onInput:M[5]||(M[5]=se=>n.nodeEdited=!0)},null,544),[[Je,t.name]]),M[21]||(M[21]=i("small",null,"Lowercase letters, digits, and dashes. A different name for each screen.",-1))])):V("",!0),x.value?(h(),g("fieldset",Wv,[M[24]||(M[24]=i("legend",null,"Wi-Fi",-1)),i("p",Kv,y(m.value),1),w.value.includes("wifi_ssid")?(h(),g("div",qv,[M[22]||(M[22]=i("label",{class:"f-label",for:"wifi_ssid"},"Wi-Fi name (2.4 GHz)",-1)),Te(i("input",{id:"wifi_ssid",name:"wifi_ssid","onUpdate:modelValue":M[6]||(M[6]=se=>t.wifi_ssid=se),autocomplete:"off"},null,512),[[Je,t.wifi_ssid]])])):V("",!0),w.value.includes("wifi_password")?(h(),g("div",Yv,[M[23]||(M[23]=i("label",{class:"f-label",for:"wifi_password"},"Wi-Fi password",-1)),Te(i("input",{id:"wifi_password",name:"wifi_password",type:"password","onUpdate:modelValue":M[7]||(M[7]=se=>t.wifi_password=se),autocomplete:"new-password"},null,512),[[Je,t.wifi_password]])])):V("",!0)])):V("",!0),i("div",zv,[M[26]||(M[26]=i("label",{class:"f-label",for:"install-target"},"Install via",-1)),Te(i("select",{id:"install-target",name:"target","onUpdate:modelValue":M[8]||(M[8]=se=>t.target=se),onChange:M[9]||(M[9]=se=>{n.picked=!0,q()})},[T.value.length?V("",!0):(h(),g("option",Gv,"USB · no board found on the Home Assistant machine yet")),(h(!0),g(W,null,le(T.value,se=>(h(),g("option",{key:se,value:se},y(I(se)),9,Jv))),128)),i("option",{value:"download"},y(gm)),M[25]||(M[25]=i("option",{value:""},"Later · save profile only",-1))],544),[[_s,t.target]]),i("small",Xv,y(C.value),1)]),u.value?(h(),g("p",Qv,y(u.value),1)):V("",!0),i("div",Zv,[i("button",{type:"submit",class:"btn primary",id:"install-go",disabled:Ae.value},y(L.value),9,em),i("span",tm,y(a.value),1)])],32)):(h(),g("div",nm,[i("div",sm,[z.value?(h(),g("span",om)):(h(),g("span",{key:1,class:re(["outcome",B.value?"ok":"bad"]),id:"progress-mark"},y(B.value?"✓":"✕"),3)),i("strong",im,y(ie.value),1)]),i("p",lm,y(ue.value),1),B.value&&Y.value&&n.view!=="done"?(h(),g("div",am,[i("a",{class:"btn primary",id:"download-firmware",href:ze.value.href,download:ze.value.name},"Download "+y(ze.value.name),9,rm),i("ol",um,[M[30]||(M[30]=i("li",null,[i("b",null,"Plug the screen into your computer"),Q(" with a USB data cable.")],-1)),i("li",null,[i("b",null,[M[27]||(M[27]=Q("Open ",-1)),i("a",{href:mm,target:"_blank",rel:"noopener"},"ESPHome Web")]),M[28]||(M[28]=Q(" in Chrome or Edge, click Connect and choose the screen's USB port.",-1))]),i("li",null,[M[29]||(M[29]=i("b",null,"Click Install",-1)),Q(" and select "+y(ze.value.name)+". The screen restarts and joins your Wi-Fi."+y(n.board==="cyd"?" The CYD first asks for a touch calibration: tap the crosshairs.":""),1)])]),M[31]||(M[31]=i("small",null,"The file holds your Wi-Fi password and the screen's keys: keep it to yourself.",-1))])):V("",!0),B.value?(h(),g("div",cm,[i("div",dm,[M[32]||(M[32]=i("span",null,"API key",-1)),i("code",{id:"api-key",ref_key:"keyBox",ref:b},y(n.apiKey||""),513),i("button",{type:"button",class:"btn quiet mini",id:"copy-key",onClick:M[10]||(M[10]=se=>v(dt)(n.apiKey||"",b.value))},"Copy")]),i("ol",fm,[(h(!0),g(W,null,le(an.value,([se,Ge],wn)=>(h(),g("li",{key:wn},[i("b",null,y(se),1),Q(y(Ge),1),wn===0?(h(),g("button",{key:0,type:"button",class:"btn quiet mini",onClick:M[11]||(M[11]=(...Gt)=>v($s)&&v($s)(...Gt))},"Open Devices & services")):V("",!0)]))),128))])])):V("",!0),n.view!=="done"?(h(),g("details",{key:2,id:"install-log-wrap",class:"log-wrap",open:f.value,onToggle:M[12]||(M[12]=se=>f.value=se.target.open)},[M[33]||(M[33]=i("summary",null,"ESPHome log",-1)),i("pre",hm,y(r.value.join(` -`)),1)],40,pm)):V("",!0),i("div",vm,[!z.value&&!B.value?(h(),g("button",{key:0,type:"button",class:"btn primary",id:"install-retry",onClick:We},"Retry")):V("",!0),i("button",{type:"button",class:"btn quiet",id:"install-close",onClick:ts},y(B.value?"Install another screen":"Start over"),1),i("button",{type:"button",class:re(["btn",B.value?"primary":"quiet"]),onClick:ns},y(B.value?"Done":"Close"),3)])]))]))}}),bm={class:"panel",id:"firmware-dialog"},wm={class:"panel-head"},_m={class:"card"},km={class:"card-grid"},$m={class:"field"},xm=["value"],Sm={class:"field"},Cm={key:0,value:"usb"},Tm=["value"],Am={key:0,class:"field",id:"firmware-host-label"},Em=["placeholder"],Pm={class:"actions"},Om=["disabled"],Im=["disabled"],Mm=["disabled"],Dm={key:0,class:"spin"},Lm={id:"firmware-status",class:"status-line",role:"status"},Fm={key:0,id:"firmware-download",class:"card",style:{background:"var(--surface-2)"}},Hm=["href","download"],Rm={id:"firmware-log",class:"log"},Nm="https://web.esphome.io/?dashboard_install",jm="Download · flash from your own computer",Bm=$e({__name:"FirmwareView",setup(e){const t=fe(null),n=fe(""),s=fe("ota"),o=fe("");let l=0;async function r(R=!1){try{const T=await Mt("firmware");t.value=T,(R||!n.value)&&(n.value=T.profiles[0]?.file||"");const $=T.ports||[];s.value.startsWith("/")&&!$.includes(s.value)&&(s.value=$[0]||"usb"),s.value==="usb"&&$.length&&(s.value=$[0])}catch(T){Se(T.message)}}const u=k(()=>t.value?.job?.state==="running"),a=k(()=>!t.value||u.value||!t.value.available||!t.value.profiles?.length),c=k(()=>a.value||s.value==="usb"),f=k(()=>t.value?.ports||[]),b=k(()=>t.value?t.value.available?t.value.job?`${t.value.job.file} · ${t.value.job.action} · ${t.value.job.state}`:"Choose the intended profile, then a USB port, an IP address, or Download.":"The ESPHome CLI is missing. Update the app to 0.2.0.":"Loading…"),A=k(()=>s.value==="download"&&!!n.value&&!!t.value?.downloads?.includes(n.value)),D=k(()=>({href:`api/firmware/profiles/${encodeURIComponent(n.value)}/download`,name:n.value.replace(/\.yaml$/,"")+".factory.bin"}));async function I(R){try{await it("firmware/jobs","POST",{file:n.value,action:R==="validate"?"validate":R==="build"?"build":s.value==="download"?"download":"install",target:s.value==="ota"?o.value.trim():s.value==="download"?"":s.value}),await r()}catch(T){Se(T.message)}}return bn(()=>{r(!0),l=window.setInterval(()=>r(),3e3)}),Xn(()=>clearInterval(l)),(R,T)=>(h(),g("div",bm,[i("div",wm,[T[7]||(T[7]=fs('
    Firmware & USB

    Build and install screen firmware

    The built-in ESPHome CLI uses your own profile (YAML with keys) and secrets. Choose the screen's profile, then a USB port (screen connected to the Home Assistant machine), Wi-Fi / OTA with the hostname, or Download to put the firmware on the screen from your own computer. Check only validates, Build only compiles, Build & install puts the firmware on the screen. Your tiles stay as they are in ESP Screens. The first build takes a few minutes.

    ',1)),i("button",{type:"button",class:"btn quiet",id:"close-firmware",onClick:T[0]||(T[0]=$=>v(De)(""))},"← Back")]),i("div",_m,[i("div",km,[i("div",$m,[T[8]||(T[8]=i("label",{class:"f-label",for:"firmware-file"},"ESPHome profile",-1)),Te(i("select",{id:"firmware-file","onUpdate:modelValue":T[1]||(T[1]=$=>n.value=$)},[(h(!0),g(W,null,le(t.value?.profiles||[],$=>(h(),g("option",{key:$.file,value:$.file},y($.file),9,xm))),128))],512),[[_s,n.value]])]),i("div",Sm,[T[10]||(T[10]=i("label",{class:"f-label",for:"firmware-port"},"Install to",-1)),Te(i("select",{id:"firmware-port","onUpdate:modelValue":T[2]||(T[2]=$=>s.value=$)},[T[9]||(T[9]=i("option",{value:"ota"},"Wi-Fi / OTA",-1)),f.value.length?V("",!0):(h(),g("option",Cm,"USB · no board found on the Home Assistant machine yet")),(h(!0),g(W,null,le(f.value,$=>(h(),g("option",{key:$,value:$},y($),9,Tm))),128)),i("option",{value:"download"},y(jm))],512),[[_s,s.value]])]),s.value==="ota"?(h(),g("div",Am,[T[11]||(T[11]=i("label",{class:"f-label",for:"firmware-host"},"IP address or hostname",-1)),Te(i("input",{id:"firmware-host","onUpdate:modelValue":T[3]||(T[3]=$=>o.value=$),placeholder:n.value?n.value.replace(/\.yaml$/,".local"):"screen-livingroom.local"},null,8,Em),[[Je,o.value]])])):V("",!0)]),i("div",Pm,[i("button",{type:"button",class:"btn quiet",id:"firmware-validate",disabled:a.value,onClick:T[4]||(T[4]=$=>I("validate"))},"Check",8,Om),i("button",{type:"button",class:"btn quiet",id:"firmware-build",disabled:a.value,onClick:T[5]||(T[5]=$=>I("build"))},"Build only",8,Im),i("button",{type:"button",class:"btn primary",id:"firmware-install",disabled:c.value,onClick:T[6]||(T[6]=$=>I("install"))},y(s.value==="download"?"Build & download":"Build & install"),9,Mm),u.value?(h(),g("span",Dm)):V("",!0)]),i("p",Lm,y(b.value),1),A.value?(h(),g("div",Fm,[i("a",{class:"btn primary",id:"firmware-download-link",href:D.value.href,download:D.value.name},"Download "+y(D.value.name),9,Hm),i("small",null,[T[12]||(T[12]=Q("Put it on the screen with ",-1)),i("a",{href:Nm,target:"_blank",rel:"noopener"},"ESPHome Web"),T[13]||(T[13]=Q(" in Chrome or Edge: Connect, choose the screen's USB port, Install, and select this file. It holds your Wi-Fi password and the screen's keys: keep it to yourself.",-1))])])):V("",!0)]),i("pre",Rm,y((t.value?.logs||[]).join(` -`)),1)]))}}),Um={class:"panel wide alerts",id:"alerts-dialog"},Vm={class:"panel-head"},Wm={key:0,class:"hint"},Km={class:"alert-hero"},qm={class:"alert-mock",id:"alert-mock","aria-hidden":"true"},Ym={class:"mdi alert-mock-icon",id:"alert-mock-icon"},zm={class:"alerts-nav","aria-label":"Sections"},Gm=["data-jump","onClick"],Jm={id:"alerts-screens",class:"card"},Xm={id:"alerts-min-firmware"},Qm={id:"alerts-screen-list",class:"options"},Zm={key:0,class:"hint"},eg={class:"alert-screen-head"},tg={class:"copy-label"},ng=["onClick"],sg={id:"alerts-howto",class:"card"},og={class:"field"},ig=["value"],lg={key:0,value:""},ag={class:"copy-line"},rg={id:"alerts-example"},ug={id:"alerts-all",class:"card"},cg={id:"alerts-all-event"},dg={id:"alerts-all-dismiss"},fg={class:"copy-line"},pg={id:"alerts-all-example"},hg={id:"alerts-fields",class:"card"},vg={class:"table-scroll"},mg={id:"alerts-field-table"},gg={key:0},yg={id:"alerts-icons",class:"card"},bg={class:"chips",id:"alerts-suggested"},wg=["onClick"],_g={class:"mdi"},kg={class:"field"},$g={id:"alerts-icon-groups"},xg={class:"subhead"},Sg={class:"alert-icon-grid"},Cg=["title","onClick"],Tg={class:"mdi"},Ag={key:0},Eg={key:0,class:"hint"},Pg={id:"alerts-colors",class:"card"},Og={class:"swatches",id:"alerts-swatches"},Ig=["onClick"],Mg={id:"alerts-events",class:"card"},Dg={id:"alerts-event-name"},Lg={class:"table-scroll"},Fg={id:"alerts-ending-table"},Hg={class:"copy-line"},Rg={id:"alerts-wait-example"},Ng={id:"alerts-tips",class:"card"},jg={class:"alerts-list"},Bg=$e({__name:"AlertsView",setup(e){const t=k(()=>d.inventory.alerts),n=k(()=>d.inventory.icons),s=fe(""),o=fe(""),l=x=>`"${String(x).replace(/\\/g,"\\\\").replace(/"/g,'\\"')}"`,r=x=>x.type==="string"?/^[a-z][a-z0-9-]*$/.test(x.example)?x.example:l(x.example):x.example===!0?"true":x.example===!1?"false":String(x.example),u=k(()=>d.inventory.screens.filter(x=>x.alert_action)),a=k(()=>s.value||u.value[0]?.alert_action||""),c=k(()=>{const x=(t.value?.fields||[]).map(w=>` ${w.name}: ${r(w)}`);return`action: ${a.value||"esphome._show_alert"} -data: -${x.join(` -`)}`}),f=k(()=>["# Doorbell: show the alert and wait until someone presses the button.","actions:",` - action: ${a.value||"esphome._show_alert"}`," data:",' title: "Someone is at the door"',' subtitle: "Door 3, back"'," icon: doorbell"," color: orange",' button_text: "Coming"'," timeout: 0"," flash: true"," - wait_for_trigger:"," - trigger: event",` event_type: ${t.value?.event||"esphome.screen_alert"}`," event_data:"," action: ok",' timeout: "00:05:00"'," - if:"," - condition: template",' value_template: "{{ wait.trigger is not none }}"'," then:"," - action: notify.notify"," data:",' message: "Someone is coming to the door."'].join(` -`)),b=k(()=>{const x=(t.value?.fields||[]).map(m=>` ${m.name}: ${r(m)}`),w=t.value?.camera;return w&&x.push(` # ${w.name}: ${w.example} # a Guition shows its picture on the card`),`event: ${t.value?.broadcast?.show||"esp_screens_show_alert"} -event_data: -${x.join(` -`)}`}),A=k(()=>{if(!t.value||!n.value)return[];const x=o.value.trim().toLowerCase();return[...n.value.groups,{label:"Also available: control and weather icons",icons:t.value.extra_icons}].map(m=>({label:m.label,icons:m.icons.filter(H=>!x||H.name.includes(x)||(H.label||"").toLowerCase().includes(x))})).filter(m=>m.icons.length)}),D=k(()=>t.value?.suggested_icons?.find(x=>x.name==="doorbell")),I=k(()=>t.value?.colors?.find(x=>x.name==="orange")),R={string:"text",int:"number",bool:"on / off"};function T(x){document.getElementById(x)?.scrollIntoView({behavior:"smooth",block:"start"})}const $=[["alerts-screens","Your screens"],["alerts-howto","In an automation"],["alerts-all","All screens"],["alerts-fields","The fields"],["alerts-icons","Icons"],["alerts-colors","Colors"],["alerts-behaviour","Behavior"],["alerts-events","Events"],["alerts-tips","Tips"]];return(x,w)=>(h(),g("div",Um,[i("div",Vm,[w[7]||(w[7]=i("div",{class:"tx"},[i("span",{class:"eyebrow"},"Alerts · cheatsheet"),i("h1",null,"A full-screen notification, from an automation."),i("p",null,[Q("Every screen has the "),i("code",null,"show_alert"),Q(" action. It places a card over everything, wakes the screen, and keeps the backlight at normal brightness until someone taps the button or the timeout runs out. Home Assistant itself shows no explanation or dropdowns for ESPHome actions; everything you can fill in is listed here.")])],-1)),i("button",{type:"button",class:"btn quiet",id:"close-alerts",onClick:w[0]||(w[0]=m=>v(De)(""))},"← Back")]),t.value?(h(),g(W,{key:1},[i("div",Km,[i("div",qm,[i("div",{class:"alert-mock-card",style:Ne(I.value?{background:I.value.color}:void 0)},[i("span",Ym,y(D.value?v(ke)(D.value.cp):""),1),w[8]||(w[8]=i("strong",{id:"alert-mock-title"},"Someone is at the door",-1)),w[9]||(w[9]=i("span",{id:"alert-mock-subtitle"},"Door 3, back",-1)),w[10]||(w[10]=i("span",{class:"fake",id:"alert-mock-button"},"Coming",-1))],4)]),i("nav",zm,[(h(),g(W,null,le($,([m,H])=>i("button",{key:m,type:"button","data-jump":m,onClick:C=>T(m)},y(H),9,Gm)),64))])]),i("section",Jm,[w[13]||(w[13]=i("h2",null,"Your screens",-1)),i("p",null,[w[11]||(w[11]=Q("Every screen has its own action, with the device name in it. From firmware ",-1)),i("code",Xm,y(t.value.min_firmware),1),w[12]||(w[12]=Q("; update an older screen with its Update button under Screens.",-1))]),i("div",Qm,[v(d).inventory.screens.length?V("",!0):(h(),g("p",Zm,"No screen paired yet. Install one via New screen; the action appears once Home Assistant sees the screen.")),(h(!0),g(W,null,le(v(d).inventory.screens,m=>(h(),g("div",{key:m.id,class:"alert-screen"},[i("div",eg,[i("strong",null,y(m.name),1),i("span",{class:re(["chip",v(bo)(m.firmware,t.value.min_firmware)&&m.alert_action?"good":"update"])},y(v(bo)(m.firmware,t.value.min_firmware)&&m.alert_action?`● firmware ${m.firmware}`:m.alert_action?`Update needed · firmware ${m.firmware||"unknown"}`:"Device name unknown · update the screen"),3)]),(h(!0),g(W,null,le([["Show alert",m.alert_action],["Dismiss alert",m.dismiss_action]],([H,C])=>(h(),g("div",{key:H,class:"copy-line"},[i("span",tg,y(H),1),i("code",null,y(C||"esphome._show_alert"),1),C?(h(),g("button",{key:0,type:"button",class:"btn quiet mini",onClick:L=>v(dt)(C,void 0,"Action name")},"Copy",8,ng)):V("",!0)]))),128))]))),128))])]),i("section",sg,[w[15]||(w[15]=fs('

    In an automation

    1. Add action and search for ESPHome. Choose your screen's action: Home Assistant calls it "Performs the action show_alert of the node device name".
    2. Fill in the fields. Home Assistant asks for all seven; leave what you don't use empty ("", 0, off).
    3. Prefer YAML? Choose Edit in YAML on the action and paste the example below.
    ',2)),i("div",og,[w[14]||(w[14]=i("label",{class:"f-label",for:"alerts-example-screen"},"Example for",-1)),Te(i("select",{id:"alerts-example-screen","onUpdate:modelValue":w[1]||(w[1]=m=>s.value=m),style:{"max-width":"360px"}},[(h(!0),g(W,null,le(u.value,m=>(h(),g("option",{key:m.id,value:m.alert_action},y(m.name),9,ig))),128)),u.value.length?V("",!0):(h(),g("option",lg,"a screen (not paired yet)"))],512),[[_s,s.value]])]),i("div",ag,[i("pre",rg,y(c.value),1),i("button",{type:"button",class:"btn quiet mini",id:"alerts-example-copy",onClick:w[2]||(w[2]=m=>v(dt)(c.value,void 0,"YAML"))},"Copy YAML")])]),i("section",ug,[w[23]||(w[23]=i("h2",null,"All screens at once",-1)),i("p",null,[w[16]||(w[16]=Q("Fire the event ",-1)),i("code",cg,y(t.value.broadcast?.show||"esp_screens_show_alert"),1),w[17]||(w[17]=Q(" with the same fields, and ESP Screens passes the alert on to every screen that is online, including screens you add later. ",-1)),i("code",dg,y(t.value.broadcast?.dismiss||"esp_screens_dismiss_alert"),1),w[18]||(w[18]=Q(" clears it everywhere. In an automation, add the ",-1)),w[19]||(w[19]=i("b",null,"Event",-1)),w[20]||(w[20]=Q(" action or paste the example under ",-1)),w[21]||(w[21]=i("b",null,"Edit in YAML",-1)),w[22]||(w[22]=Q(". Leave out the fields you don't use. ESP Screens has to be running for this.",-1))]),i("div",fg,[i("pre",pg,y(b.value),1),i("button",{type:"button",class:"btn quiet mini",id:"alerts-all-copy",onClick:w[3]||(w[3]=m=>v(dt)(b.value,void 0,"YAML"))},"Copy YAML")])]),i("section",hg,[w[27]||(w[27]=i("h2",null,"The fields",-1)),w[28]||(w[28]=i("p",null,"Text is free-form; the limit is in bytes, and an accented letter counts as two. What doesn't fit gets an ellipsis (title) or is dropped (subtitle).",-1)),i("div",vg,[i("table",mg,[w[26]||(w[26]=i("tr",null,[i("th",null,"Field"),i("th",null,"Type"),i("th",null,"What it does"),i("th",null,"Example"),i("th",null,"Limit")],-1)),(h(!0),g(W,null,le(t.value.fields,m=>(h(),g("tr",{key:m.name},[i("td",null,[i("code",null,y(m.name),1),i("small",null,y(m.label),1)]),i("td",null,y(R[m.type]||m.type),1),i("td",null,y(m.help),1),i("td",null,[i("code",null,y(typeof m.example=="string"?m.example:String(m.example)),1)]),i("td",null,y(t.value.limits.cyd[m.name]?`CYD ${t.value.limits.cyd[m.name]} · Guition ${t.value.limits.guition[m.name]} bytes`:m.type==="int"?"0 to 86400 s":"—"),1)]))),128)),t.value.camera?(h(),g("tr",gg,[i("td",null,[i("code",null,y(t.value.camera.name),1),i("small",null,y(t.value.camera.label),1)]),w[24]||(w[24]=i("td",null,"entity",-1)),i("td",null,y(t.value.camera.help),1),i("td",null,[i("code",null,y(t.value.camera.example),1)]),w[25]||(w[25]=i("td",null,"Guition, firmware 0.2.57+",-1))])):V("",!0)])])]),i("section",yg,[w[30]||(w[30]=i("h2",null,"Icons",-1)),w[31]||(w[31]=i("p",null,[Q("Fill in the name in "),i("code",null,"icon"),Q(", for example "),i("code",null,"doorbell"),Q(". "),i("code",null,"mdi:doorbell"),Q(" and the hex codepoint ("),i("code",null,"F12E6"),Q(") also work. Only these icons are included in the firmware; any other name shows the warning triangle. Tap an icon to copy its name.")],-1)),w[32]||(w[32]=i("p",{class:"subhead"},"Handy for notifications",-1)),i("div",bg,[(h(!0),g(W,null,le(t.value.suggested_icons,m=>(h(),g("button",{key:m.name,type:"button",class:"chip",onClick:H=>v(dt)(m.name,void 0,"Icon name")},[i("span",_g,y(v(ke)(m.cp)),1),i("code",null,y(m.name),1)],8,wg))),128))]),i("div",kg,[w[29]||(w[29]=i("label",{class:"f-label",for:"alerts-icon-search"},"Search for an icon",-1)),Te(i("input",{id:"alerts-icon-search","onUpdate:modelValue":w[4]||(w[4]=m=>o.value=m),type:"search",placeholder:"Search by name or description…",autocomplete:"off"},null,512),[[Je,o.value]])]),i("div",$g,[(h(!0),g(W,null,le(A.value,m=>(h(),g("div",{key:m.label,class:"field"},[i("p",xg,y(m.label)+" · "+y(m.icons.length),1),i("div",Sg,[(h(!0),g(W,null,le(m.icons,H=>(h(),g("button",{key:H.name,type:"button",class:"alert-icon",title:`Copy ${H.name}`,onClick:C=>v(dt)(H.name,void 0,"Icon name")},[i("span",Tg,y(v(ke)(H.cp)),1),i("code",null,y(H.name),1),H.label?(h(),g("small",Ag,y(H.label),1)):V("",!0)],8,Cg))),128))])]))),128)),A.value.length?V("",!0):(h(),g("p",Eg,'No icon for "'+y(o.value)+'". Unknown names show the warning triangle ('+y(t.value.fallback_icon)+").",1))])]),i("section",Pg,[w[34]||(w[34]=i("h2",null,"Colors",-1)),w[35]||(w[35]=i("p",null,[Q("Fill in the name in "),i("code",null,"color"),Q(". These are the pastel shades of the tiles, with dark text. Empty or unknown gives the white card. Tap to copy.")],-1)),i("div",Og,[i("button",{type:"button",class:"swatch",onClick:w[5]||(w[5]=m=>v(dt)("",void 0,"Empty color"))},[...w[33]||(w[33]=[i("i",{style:{background:"#ffffff"}},null,-1),i("span",null,[i("code",null,"empty"),i("small",null,"White (default)")],-1)])]),(h(!0),g(W,null,le(t.value.colors,m=>(h(),g("button",{key:m.name,type:"button",class:"swatch",onClick:H=>v(dt)(m.name,void 0,"Color name")},[i("i",{style:Ne({background:m.color})},null,4),i("span",null,[i("code",null,y(m.name),1),i("small",null,y(m.label)+" · "+y(m.color),1)])],8,Ig))),128))])]),w[56]||(w[56]=fs('

    Behavior

    • Wakes the screen. An alert immediately wakes a dimmed or dark screen and appears above every page, every open light card, and the standby layer.
    • On until the button. As long as the card is showing, the backlight stays at normal brightness. Standby and night hours wait. After the button, the regular standby time starts again.
    • Timeout. timeout: 0 waits for the button, however long that takes. With timeout: 60 the card disappears after a minute, but the button closes it sooner.
    • Blinking. flash: true blinks the backlight four times when the alert arrives (about a second) and leaves the screen on afterward.
    • Replacing. A new alert replaces the current one; there's no stack. The replaced alert reports itself as replaced.
    • Closing remotely. dismiss_alert clears the card, for example if the door is already open. Without an alert, that action does nothing.
    • Tapping beside the card does nothing; only the button closes it. That way a wake-up tap never accidentally dismisses the alert.
    ',1)),i("section",Mg,[w[47]||(w[47]=i("h2",null,"Events",-1)),i("p",null,[w[36]||(w[36]=Q("Every end fires the event ",-1)),i("code",Dg,y(t.value.event),1),w[37]||(w[37]=Q(" with ",-1)),w[38]||(w[38]=i("code",null,"action",-1)),w[39]||(w[39]=Q(", ",-1)),w[40]||(w[40]=i("code",null,"title",-1)),w[41]||(w[41]=Q(", ",-1)),w[42]||(w[42]=i("code",null,"screen",-1)),w[43]||(w[43]=Q(" (the device name) and the ",-1)),w[44]||(w[44]=i("code",null,"device_id",-1)),w[45]||(w[45]=Q(" that Home Assistant adds. Visible under Settings → Tools → Events.",-1))]),i("div",Lg,[i("table",Fg,[w[46]||(w[46]=i("tr",null,[i("th",null,"action"),i("th",null,"When")],-1)),(h(!0),g(W,null,le(t.value.endings,m=>(h(),g("tr",{key:m.action},[i("td",null,[i("code",null,y(m.action),1)]),i("td",null,y(m.label),1)]))),128))])]),w[48]||(w[48]=i("p",{class:"subhead"},"Waiting until someone presses the button",-1)),i("div",Hg,[i("pre",Rg,y(f.value),1),i("button",{type:"button",class:"btn quiet mini",id:"alerts-wait-copy",onClick:w[6]||(w[6]=m=>v(dt)(f.value,void 0,"YAML"))},"Copy YAML")])]),i("section",Ng,[w[55]||(w[55]=i("h2",null,"Tips",-1)),i("ul",jg,[w[53]||(w[53]=fs("
  • Use a color per kind of notification: orange for the door, red for smoke or water, green for "done". The text always stays dark and readable.
  • Keep the title short; a screen shows about twenty characters on one line and ends a longer title with an ellipsis. Put details in the subtitle.
  • A custom button text turns the notification into a question: "Coming", "Seen", "Turn off". The event then tells you who responded.
  • For an alert that resolves itself (the door opens, the laundry gets taken out) close it in the same automation with dismiss_alert.
  • ",4)),i("li",null,[w[49]||(w[49]=Q("Every screen? Fire ",-1)),i("code",null,y(t.value.broadcast?.show||"esp_screens_show_alert"),1),w[50]||(w[50]=Q(" once (see All screens at once). The screens still work independently and each reports with its own ",-1)),w[51]||(w[51]=i("code",null,"screen",-1)),w[52]||(w[52]=Q(".",-1))]),w[54]||(w[54]=i("li",null,[Q("Rather "),i("b",null,"ask Claude"),Q(" for the automation? Install the ESP Screens skill under Settings → Claude.")],-1))])])],64)):(h(),g("p",Wm,"The cheatsheet is still loading; one moment."))]))}}),Ug={class:"panel",id:"override-dialog"},Vg={class:"panel-head"},Wg={class:"tx"},Kg={id:"override-title"},qg={class:"notice"},Yg={class:"mdi"},zg={class:"file-row"},Gg={id:"override-file"},Jg={class:"yaml-editor",id:"yaml-editor-wrap"},Xg={class:"actions"},Qg={id:"override-count",class:"hint"},Zg={class:"actions"},ey=["disabled"],ty=["disabled"],ny=`# Hardware-specific changes for this screen. -# This file is kept when the shared firmware package updates. -# Do not add esphome:, api:, ota:, wifi: or packages: here. - -# Example: a CYD with the ST7789V display controller. -# "!extend" changes the display the shared package already defines; -# a bare id would add a second, incomplete display and fail the build. -display: - - id: !extend my_display - model: ST7789V -`,sy=$e({__name:"OverrideView",setup(e){const t=k(()=>d.overrideProfile),n=fe(""),s=fe(""),o=fe(!1),l=fe("Loading…"),r=fe(""),u=fe(!1),a=fe(null),c=fe(null),f=k(()=>n.value.split(` -`).length),b=k(()=>Array.from({length:f.value},(C,L)=>L+1).join(` -`)),A=k(()=>`${n.value.length} characters · ${f.value} line${f.value===1?"":"s"}`);let D=!0;function I(C,L=""){l.value=C,r.value=L}async function R(){if(!t.value){I("No ESPHome profile was found for this screen.","error");return}I("Loading…");try{const C=await Mt(`firmware/profiles/${encodeURIComponent(t.value)}/override`);s.value=C.override_file,o.value=!!C.attached,n.value=C.exists&&C.content!==`{} -`?C.content:"",I(C.attached?"Changes here apply on the next build.":"Save once to attach this file to the profile.")}catch(C){I(C.message,"error")}}async function T(C=!1){if(!(!t.value||u.value)){u.value=!0,I("Checking and saving…");try{const L=await it(`firmware/profiles/${encodeURIComponent(t.value)}/override`,"PUT",{content:n.value});if(s.value=L.override_file,o.value=!0,!C){I("Saved. The override is kept during firmware updates.","ok"),Se("Override YAML saved.");return}I("Saved. ESPHome is checking the complete profile…"),await it("firmware/jobs","POST",{file:t.value,action:"validate"}),$()}catch(L){I(L.message,"error")}finally{u.value=!1}}}function $(){const C=Date.now(),L=t.value,pe=async()=>{if(!(!D||t.value!==L))try{const Ae=await Mt("firmware"),J=Ae.job;if(J&&J.file===L&&J.state==="running")I(`ESPHome is checking the profile… ${J.stage||""}`.trim());else if(J&&J.file===L&&J.state==="success"){I("The complete profile is valid. Safe to build and install.","ok");return}else if(J&&J.file===L&&J.state==="failed"){const q=(Ae.logs||[]).filter(ae=>/error|failed/i.test(ae)).pop();I(q||"ESPHome rejected the complete profile. See Firmware & USB for the full log.","error");return}Date.now()-C<72e5&&setTimeout(pe,1200)}catch(Ae){I(Ae.message,"error")}};pe()}function x(){(!n.value.trim()||confirm("Replace the current text with the example?"))&&(n.value=ny,I("Example loaded. Save it when you are ready."),a.value?.focus())}function w(){(!n.value.trim()||confirm("Clear the local override?"))&&(n.value="",I("The override will be empty after you save."),a.value?.focus())}function m(C){const L=a.value;if(C.key==="Tab"){C.preventDefault();const pe=L.selectionStart,Ae=L.selectionEnd;L.setRangeText(" ",pe,Ae,"end"),n.value=L.value}else(C.ctrlKey||C.metaKey)&&C.key.toLowerCase()==="s"&&(C.preventDefault(),T(!1))}function H(){c.value&&a.value&&(c.value.scrollTop=a.value.scrollTop)}return bn(R),Xn(()=>{D=!1}),(C,L)=>(h(),g("div",Ug,[i("div",Vg,[i("div",Wg,[L[4]||(L[4]=i("span",{class:"eyebrow"},"Advanced · local override",-1)),i("h1",Kg,"Override YAML"+y(v(d).overrideFriendly?` · ${v(d).overrideFriendly}`:""),1),L[5]||(L[5]=i("p",null,"This small file is yours. It is loaded after the shared screen package and stays in place when ESP Screen Manager updates. Change hardware-specific details here, such as a display model.",-1))]),i("button",{type:"button",class:"btn quiet",id:"close-override",onClick:L[0]||(L[0]=pe=>v(De)(""))},"← Back")]),i("div",qg,[i("span",Yg,y(v(ke)("F0493")),1),L[6]||(L[6]=i("div",null,[i("strong",null,"What is safe to change?"),i("span",null,"Display, touchscreen, substitutions, pins and other device details. Name, Wi-Fi, API, OTA and package links remain managed.")],-1))]),i("div",zg,[i("code",Gg,y(s.value||t.value||""),1),i("span",{id:"override-state",class:re(["chip",{good:o.value}])},y(o.value?"Active":"Ready to attach"),3)]),i("div",Jg,[i("div",{ref_key:"gutter",ref:c,class:"yaml-gutter",id:"override-gutter","aria-hidden":"true"},y(b.value),513),Te(i("textarea",{ref_key:"editor",ref:a,id:"override-editor","onUpdate:modelValue":L[1]||(L[1]=pe=>n.value=pe),spellcheck:"false",autocapitalize:"off",autocomplete:"off",autocorrect:"off","aria-label":"Local override YAML",placeholder:`# Example -display: - - id: !extend my_display - model: ST7789V`,onKeydown:m,onScroll:H},null,544),[[Je,n.value]])]),i("div",Xg,[i("button",{type:"button",class:"btn quiet mini",id:"override-example",onClick:x},"Use example"),i("button",{type:"button",class:"btn quiet mini",id:"override-empty",onClick:w},"Clear"),i("span",Qg,y(A.value),1)]),i("p",{id:"override-status",class:re(["status-line",r.value]),role:"status"},y(l.value),3),i("div",Zg,[i("button",{type:"button",class:"btn quiet",id:"override-check",disabled:u.value||!t.value,onClick:L[2]||(L[2]=pe=>T(!0))},"Save & check",8,ey),i("button",{type:"button",class:"btn primary",id:"override-save",disabled:u.value||!t.value,onClick:L[3]||(L[3]=pe=>T(!1))},"Save override",8,ty)])]))}}),oy={class:"main"},iy=$e({__name:"App",setup(e){const t=k(()=>tt.value==="#settings"?Ov:tt.value==="#new-screen"?ym:tt.value==="#firmware"?Bm:tt.value==="#alerts"?Bg:tt.value==="#override"?sy:qt.value&&d.layout?fv:vv);return(n,s)=>(h(),g("div",{class:re(["app",{dragging:v(d).drag.active}])},[_e(zc),i("main",oy,[(h(),Ve(Sr(t.value)))]),_e(Jc)],2))}});Uu(iy).mount("#app");Ac(); diff --git a/screen_manager/app/static/assets/index-PqOTdpJB.css b/screen_manager/app/static/assets/index-PqOTdpJB.css new file mode 100644 index 0000000..96a8abc --- /dev/null +++ b/screen_manager/app/static/assets/index-PqOTdpJB.css @@ -0,0 +1 @@ +:root{color-scheme:light dark;--ground: #f5f6f8;--surface: #ffffff;--surface-2: #f9fafb;--line: #e4e7ec;--line-strong: #d3d8e0;--ink: #16181d;--ink-2: #565d6b;--muted: #7a8290;--accent: #2f63f0;--accent-ink: #ffffff;--accent-soft: #edf2ff;--good: #1e9a5f;--good-soft: #e6f6ee;--warn: #b56d00;--warn-soft: #fff3df;--danger: #c6372e;--danger-soft: #fdecea;--seg: #eef0f3;--shadow: 0 12px 40px rgba(20, 24, 40, .12), 0 1px 2px rgba(20, 24, 40, .06);--code-bg: #f1f3f6;--ui-font: -apple-system, BlinkMacSystemFont, system-ui, "SF Pro Text", "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;--mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace}@media(prefers-color-scheme:dark){:root{--ground: #0e1014;--surface: #161a21;--surface-2: #1b2029;--line: #262c37;--line-strong: #333b49;--ink: #e9ecf1;--ink-2: #b4bbc7;--muted: #8a93a3;--accent: #6d93ff;--accent-ink: #0b1633;--accent-soft: #1b2540;--good: #3fbf7f;--good-soft: #14302a;--warn: #e0a03a;--warn-soft: #302610;--danger: #f07167;--danger-soft: #3a1b19;--seg: #222834;--shadow: 0 16px 48px rgba(0, 0, 0, .55), 0 1px 2px rgba(0, 0, 0, .4);--code-bg: #12151b}}@font-face{font-family:Tile Icons;src:url(./tile-icons-BawP5y9D.woff) format("woff");font-display:block}@font-face{font-family:Bar Roboto;font-weight:400;src:url(./bar-roboto-400-H0q_-5Ia.woff) format("woff");font-display:block}@font-face{font-family:Bar Roboto;font-weight:500;src:url(./bar-roboto-500-Bn7ZL9yA.woff) format("woff");font-display:block}*{box-sizing:border-box}html,body,#app{height:100%}body{margin:0;background:var(--ground);color:var(--ink);font:13px/1.45 var(--ui-font);-webkit-font-smoothing:antialiased;font-variant-numeric:tabular-nums}button,input,select,textarea{font:inherit;color:inherit}button{background:none;border:0;padding:0;cursor:pointer;border-radius:8px}button:disabled{opacity:.45;cursor:default}button:focus-visible,input:focus-visible,select:focus-visible,textarea:focus-visible,[tabindex]:focus-visible,summary:focus-visible{outline:2px solid var(--accent);outline-offset:2px}input,select,textarea{background:var(--surface);border:1px solid var(--line-strong);border-radius:8px;padding:7px 10px;width:100%;color:var(--ink)}input::placeholder,textarea::placeholder{color:var(--muted)}select{appearance:auto}h1,h2,h3,h4{margin:0;font-weight:600;letter-spacing:-.01em}h1{font-size:20px;letter-spacing:-.02em}h2{font-size:15px}h3,h4{font-size:13px}p{margin:0}small,.hint{display:block;color:var(--muted);font-size:11.5px;font-weight:400;line-height:1.4}.hint.warn,small.warn{color:var(--warn)}code{font-family:var(--mono);font-size:.92em;background:var(--code-bg);padding:1px 6px;border-radius:5px;overflow-wrap:anywhere}pre{margin:0;padding:12px 14px;background:var(--code-bg);border:1px solid var(--line);border-radius:10px;overflow:auto;font:12px/1.5 var(--mono);color:var(--ink);white-space:pre-wrap;overflow-wrap:anywhere}a{color:var(--accent);text-decoration:none}a:hover{text-decoration:underline}.mdi{font-family:Tile Icons;font-style:normal;font-weight:400;line-height:1}[hidden]{display:none!important}.app{display:grid;grid-template-columns:232px minmax(0,1fr);height:100%;min-height:100vh}.app.dragging{user-select:none;-webkit-user-select:none;cursor:grabbing}.main{display:flex;flex-direction:column;min-width:0;min-height:0}.side{background:var(--surface);border-right:1px solid var(--line);display:flex;flex-direction:column;padding:14px 10px;gap:4px;min-height:0;overflow:auto;position:sticky;top:0;height:100vh}.brand{display:flex;align-items:center;gap:9px;padding:4px 8px 6px;font-weight:600;font-size:13px}.brand .mark{width:22px;height:22px;border-radius:6px;background:var(--ink);color:var(--surface);display:grid;place-items:center;font-size:14px;line-height:1}.conn{display:block;padding:0 8px 8px;font-size:11px;color:var(--muted)}.conn:before{content:"●";margin-right:6px;color:var(--warn)}.conn.online:before{color:var(--good)}.side .label{font-size:10.5px;font-weight:600;letter-spacing:.08em;text-transform:uppercase;color:var(--muted);padding:10px 8px 4px}.nav-item{display:flex;align-items:center;gap:9px;width:100%;padding:7px 8px;border-radius:8px;text-align:left;color:var(--ink-2)}.nav-item:hover{background:var(--surface-2);color:var(--ink)}.nav-item[aria-current=true]{background:var(--seg);color:var(--ink);font-weight:500}.nav-item .dot{width:7px;height:7px;border-radius:50%;background:var(--good);flex:none}.nav-item .dot.off{background:var(--line-strong)}.nav-item .txt{display:grid;min-width:0;flex:1}.nav-item .txt small{font-size:11px;color:var(--muted);font-weight:400;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.nav-item .mdi{font-size:16px;width:18px;text-align:center;color:var(--muted)}.nav-item .plus{width:18px;text-align:center;font-size:14px}.nav-item.ghost{color:var(--muted)}.nav-item.ghost:hover{color:var(--accent);background:var(--accent-soft)}.pill{font-size:10.5px;font-weight:600;padding:2px 7px;border-radius:999px;background:var(--warn-soft);color:var(--warn);flex:none}.side .spacer{flex:1}.screen-item{display:grid;gap:4px}.screen-update{display:grid;gap:6px;padding:2px 8px 8px 24px}.screen-update.available{grid-template-columns:1fr auto;align-items:center}.screen-update.available:has(.screen-host){grid-template-columns:1fr}.screen-update small.failed{color:var(--danger)}.screen-host{display:flex;gap:6px;align-items:center}.screen-host input{padding:5px 8px;font-size:12px}.pending{margin:4px 0;padding:10px;border:1px dashed var(--line-strong);border-radius:10px;display:grid;gap:6px}.pending strong{font-size:12.5px}.pending-actions{display:flex;flex-wrap:wrap;gap:6px}.btn{display:inline-flex;align-items:center;justify-content:center;gap:6px;padding:6px 12px;border-radius:8px;font-weight:600;font-size:12.5px;white-space:nowrap}.btn.primary{background:var(--accent);color:var(--accent-ink)}.btn.primary:hover:not(:disabled){filter:brightness(1.06)}.btn.quiet{color:var(--ink-2);border:1px solid var(--line-strong);background:var(--surface)}.btn.quiet:hover:not(:disabled){background:var(--surface-2);color:var(--ink)}.btn.danger{color:var(--danger)}.btn.danger:hover:not(:disabled){background:var(--danger-soft)}.btn.mini{padding:4px 9px;font-size:11.5px}.btn.link{color:var(--accent);padding:0;font-weight:600}.icon-btn{width:30px;height:30px;display:grid;place-items:center;border-radius:8px;color:var(--ink-2);font-size:15px;flex:none}.icon-btn:hover{background:var(--seg);color:var(--ink)}.chip{display:inline-flex;align-items:center;gap:6px;padding:3px 9px;border-radius:999px;font-size:11.5px;font-weight:500;color:var(--ink-2);background:var(--surface-2);border:1px solid var(--line);white-space:nowrap}.chip .dot{width:6px;height:6px;border-radius:50%;background:var(--good);flex:none}.chip.off .dot{background:var(--line-strong)}.chip.dirty{color:var(--warn);background:var(--warn-soft);border-color:transparent}.chip.sent,.chip.good{color:var(--good);background:var(--good-soft);border-color:transparent}.chip.update{color:var(--warn);background:var(--warn-soft);border-color:transparent}.seg{display:inline-flex;padding:2px;background:var(--seg);border-radius:8px;gap:2px}.seg button{padding:4px 11px;border-radius:6px;font-size:12px;font-weight:500;color:var(--ink-2);white-space:nowrap}.seg button[aria-pressed=true]{background:var(--surface);color:var(--ink);box-shadow:0 1px 2px #14182824}.seg.wrap{flex-wrap:wrap}.seg button:hover:not(:disabled):not([aria-pressed=true]){color:var(--ink)}.spin{display:inline-block;width:14px;height:14px;border:2px solid var(--line-strong);border-top-color:var(--accent);border-radius:50%;animation:spin .8s linear infinite;flex:none}.spin.small{width:11px;height:11px;border-width:1.5px}@keyframes spin{to{transform:rotate(360deg)}}.switch{width:34px;height:20px;border-radius:10px;background:var(--line-strong);position:relative;flex:none;padding:0}.switch:after{content:"";position:absolute;top:2px;left:2px;width:16px;height:16px;border-radius:50%;background:#fff;box-shadow:0 1px 2px #0003;transition:left .12s}.switch[aria-checked=true]{background:var(--accent)}.switch[aria-checked=true]:after{left:16px}.switch.unknown:after{left:9px;opacity:.6}@media(prefers-reduced-motion:reduce){.switch:after,.drawer,.spin{transition:none;animation:none}}.main-head{display:flex;align-items:center;gap:12px;padding:0 18px;min-height:52px;border-bottom:1px solid var(--line);background:var(--surface);position:sticky;top:0;z-index:4}.main-head h1{font-size:15px}.main-head .eyebrow{font-size:10.5px;font-weight:600;letter-spacing:.08em;text-transform:uppercase;color:var(--muted)}.head-right{margin-left:auto;display:flex;align-items:center;gap:8px;position:relative}.menu{position:absolute;top:38px;right:0;min-width:210px;background:var(--surface);border:1px solid var(--line);border-radius:10px;box-shadow:var(--shadow);padding:6px;display:grid;z-index:6}.menu button{text-align:left;padding:7px 10px;border-radius:7px;color:var(--ink);display:flex;justify-content:space-between;gap:12px;width:100%}.menu button small{color:var(--muted);display:inline}.menu button:hover:not(:disabled){background:var(--surface-2)}.body{position:relative;display:grid;grid-template-columns:minmax(0,1fr) 300px;flex:1;min-height:0;overflow:hidden}.canvas{overflow:auto;padding:22px 22px 26px;min-width:0}.canvas-head{display:flex;align-items:baseline;gap:12px;margin-bottom:14px;color:var(--muted);font-size:12px;flex-wrap:wrap}.canvas-head b{color:var(--ink);font-weight:600;font-size:13px}.canvas-head .warn{color:var(--warn)}.pages{display:flex;gap:18px;align-items:flex-start}.page{flex:0 0 292px;display:grid;gap:8px}.page-label{display:flex;justify-content:space-between;align-items:center;font-size:11.5px;color:var(--muted);padding:0 4px;min-height:22px}.page-label .btn.mini{color:var(--muted)}.page-label .btn.mini:hover{color:var(--danger);background:var(--danger-soft)}.page.ghost .device{display:grid;place-items:center;border:1.5px dashed var(--line-strong);background:transparent;color:var(--muted);font-weight:500;cursor:pointer}.page.ghost .device:hover,.page.ghost .device:focus-visible{color:var(--accent);border-color:var(--accent)}.page.ghost .device.drop{color:var(--accent);border-color:var(--accent);background:var(--accent-soft)}.page.ghost.disabled .device{opacity:.5;cursor:default}.device{background:#e7e7e7;border-radius:18px;padding:10px;display:grid;grid-template-rows:auto minmax(0,1fr);gap:8px;color:#1b1b1b;aspect-ratio:1 / 1}.device.cyd{aspect-ratio:4 / 3}.bar-wrap{cursor:pointer;border-radius:8px;padding:0 2px}.bar-wrap:hover{background:#dedede}.bar-wrap.selected{outline:2px solid var(--accent);outline-offset:1px}.bar-wrap svg{display:block;width:100%;height:auto}.tiles{display:grid;grid-template-columns:1fr 1fr;grid-auto-rows:minmax(0,1fr);gap:8px;min-height:0}.tile{position:relative;background:#fff;border:1px solid #dcdcdc;border-radius:12px;padding:8px 9px;display:flex;flex-direction:column;justify-content:space-between;gap:4px;min-height:0;cursor:pointer;text-align:left;overflow:hidden;color:#1b1b1b;touch-action:pan-y}.tile:hover{border-color:#b9c4d3}.tile.chosen{outline:2px solid var(--accent);outline-offset:1px}.tile.wide{grid-column:span 2;flex-direction:row;align-items:center;gap:8px}.tile.bare{background:transparent;border-style:dashed;border-color:#c3c9d0}.tile.placeholder{opacity:.55;border:2px dashed var(--accent);background:var(--accent-soft);cursor:default}.tile .ic{font-size:18px;line-height:1;color:#1b1b1b;flex:none}.tile .lead{display:grid;gap:2px;min-width:0;flex:1;align-content:end}.tile.wide .lead{display:flex;align-items:center;gap:8px;align-content:initial}.tile.wide .lead .tx{display:grid;min-width:0;gap:1px}.tile .nm{font-size:11.5px;font-weight:600;line-height:1.2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.tile .st{font-size:10.5px;color:#5a5f66;line-height:1.2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.device.cyd .tile{padding:6px 7px}.device.cyd .tile .nm{font-size:10.5px}.device.cyd .tile .ic{font-size:15px}.tile .mini-slider{height:10px;border-radius:5px;background:linear-gradient(to right,#ffbf38 60%,#fff1d3 60%);flex:none;width:100%}.tile.wide .mini-slider{width:70px}.tile .ctl{flex:none;display:flex;align-items:center;gap:4px;color:#1b1b1b}.tile .tog{width:30px;height:17px;border-radius:9px;background:#2196f3;position:relative}.tile .tog:after{content:"";position:absolute;top:2px;right:2px;width:13px;height:13px;border-radius:50%;background:#fff}.tile .tog.off{background:#c9ccd1}.tile .tog.off:after{right:auto;left:2px}.tile .ic.lit{color:#d9930f}.tile .big{font-size:19px;font-weight:600;letter-spacing:-.02em;line-height:1.05;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.tile .big small{display:inline;font-size:10.5px;font-weight:500;color:#5a5f66;margin-left:2px}.device.cyd .tile .big{font-size:16px}.tile .range{width:56px;height:14px;border-radius:7px;background:linear-gradient(to right,#2196f3 35%,#d3e8fb 35%)}.tile .key{height:20px;min-width:22px;padding:0 5px;border-radius:6px;background:#eceef1;display:grid;place-items:center;font-size:12px}.tile .stp{display:flex;align-items:center;gap:5px;height:20px;padding:0 7px;border-radius:10px;background:#eceef1;font-size:11px;font-weight:600}.tile .stp .mdi{font-size:12px}.tile .run{height:20px;padding:0 9px;border-radius:10px;background:#eceef1;font-size:11px;font-weight:600;line-height:20px}.tile .remove{position:absolute;top:5px;right:5px;width:22px;height:22px;border-radius:50%;background:#ffffffd9;color:#5a5f66;border:1px solid #dcdcdc;font-size:10px;line-height:1;display:grid;place-items:center;opacity:0;transition:opacity .12s}.tile:hover .remove,.tile:focus-within .remove{opacity:1}.tile .remove:hover{color:var(--danger);border-color:#e7b4b0;background:#fff}@media(hover:none){.tile .remove{opacity:1}}.tile .clockface{width:46px;height:46px;margin:auto}.tile.wide .clockface{margin:0;flex:none}.cell{min-height:0;border:1px dashed #cfd4da;border-radius:12px;background:transparent;color:#a3abb5;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:1px;font-weight:500;cursor:pointer;padding:6px}.cell span{font-size:18px;line-height:1}.cell small{font-size:10.5px;color:inherit}.cell:hover,.cell:focus-visible{border-color:#9eb6cf;color:#4b5563;background:#f6f7f9}.cell.insert-here{border:2px dashed var(--accent);color:var(--accent);background:var(--accent-soft)}.drag-ghost{position:fixed;left:0;top:0;pointer-events:none;z-index:50;opacity:.92;box-shadow:var(--shadow);border-radius:12px}.library{border-left:1px solid var(--line);background:var(--surface);display:flex;flex-direction:column;min-height:0}.lib-head{padding:14px 14px 10px;display:grid;gap:10px;border-bottom:1px solid var(--line)}.lib-title{display:flex;align-items:baseline;justify-content:space-between;font-weight:600;gap:8px}.lib-title small{color:var(--muted);font-weight:400;font-size:11.5px}.filters{display:flex;gap:6px;overflow-x:auto;scrollbar-width:none;padding-bottom:2px}.filters::-webkit-scrollbar{display:none}.filters button{flex:none;display:inline-flex;align-items:center;gap:5px;padding:4px 10px;border-radius:999px;font-size:11.5px;font-weight:500;color:var(--ink-2);background:var(--surface-2);border:1px solid var(--line)}.filters button[aria-pressed=true]{background:var(--ink);color:var(--surface);border-color:var(--ink)}.filters .domain-icon{width:16px;height:16px;font-size:11px;border-radius:50%;display:grid;place-items:center}.lib-list{overflow:auto;padding:8px;display:grid;gap:2px;align-content:start;flex:1}.ent{display:flex;align-items:center;gap:10px;padding:8px;border-radius:9px;width:100%;text-align:left;cursor:grab;touch-action:pan-y}.ent:hover:not(:disabled){background:var(--surface-2)}.ent:disabled{opacity:.55;cursor:default}.ent .av{width:30px;height:30px;border-radius:9px;display:grid;place-items:center;font-size:17px;flex:none}.ent .tx{display:grid;min-width:0;flex:1}.ent .tx b{font-weight:500;font-size:12.5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ent .tx small{font-size:11px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ent .add{width:24px;height:24px;border-radius:50%;display:grid;place-items:center;color:var(--accent);background:var(--accent-soft);font-size:15px;font-weight:600;flex:none}.ent .add.done{color:var(--good);background:var(--good-soft);font-size:12px}.lib-foot{padding:10px 14px;border-top:1px solid var(--line);font-size:11.5px;color:var(--muted)}.domain-icon{display:inline-grid;place-items:center;border-radius:50%;font-weight:500}.drawer{position:absolute;top:0;right:0;bottom:0;width:360px;max-width:100%;background:var(--surface);border-left:1px solid var(--line);box-shadow:var(--shadow);transform:translate(102%);transition:transform .18s cubic-bezier(.2,.7,.2,1);display:flex;flex-direction:column;min-height:0;z-index:5}.drawer.open{transform:none}.dr-head{display:flex;align-items:center;gap:10px;padding:12px 12px 12px 16px;border-bottom:1px solid var(--line)}.dr-head .av{width:34px;height:34px;border-radius:10px;display:grid;place-items:center;font-size:20px;flex:none}.dr-head .tx{flex:1;min-width:0;display:grid}.dr-head .tx b{font-weight:600;font-size:14px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.dr-head .tx small{color:var(--muted);font-size:11.5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.dr-head .tx small.mono{font-family:var(--mono)}.dr-body{overflow:auto;padding:14px 16px 18px;display:grid;gap:16px;align-content:start;flex:1}.f{display:grid;gap:7px}.f>.f-label{font-size:11px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;color:var(--muted)}.f input,.f select{font-size:13px}.row{display:flex;align-items:center;gap:10px;padding:7px 10px 7px 8px;border:1px solid var(--line-strong);border-radius:9px;background:var(--surface);width:100%;text-align:left}.row .av{width:30px;height:30px;border-radius:8px;background:var(--surface-2);display:grid;place-items:center;font-size:18px;flex:none}.row .tx{flex:1;min-width:0;display:grid}.row .tx b{font-weight:500}.row .tx small{font-size:11px}.row .link{color:var(--accent);font-weight:600;font-size:12px;flex:none}.sw{display:grid;grid-template-columns:repeat(4,1fr);gap:6px}.sw button{display:grid;justify-items:center;gap:4px;padding:6px 4px 5px;border-radius:9px;border:1.5px solid transparent;font-size:10.5px;color:var(--ink-2)}.sw button i{width:30px;height:22px;border-radius:6px;border:1px solid rgba(0,0,0,.08);display:block}.sw button i.auto{background:linear-gradient(135deg,#fff 50%,#e5e7eb 50%)}.sw button i.none{background:linear-gradient(135deg,transparent 46%,#8b95a1 46%,#8b95a1 54%,transparent 54%),#e7e7e7;border-style:dashed}.sw button[aria-pressed=true]{border-color:var(--accent);background:var(--accent-soft);color:var(--ink)}.picker{display:grid;gap:10px;padding:10px;border:1px solid var(--line);border-radius:10px;background:var(--surface-2)}.picker input{background:var(--surface)}.icon-list{display:grid;gap:12px;max-height:300px;overflow:auto;padding-right:2px}.icon-list small{margin-bottom:6px}.icon-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(40px,1fr));gap:6px}.icon-choice{display:grid;place-items:center;height:40px;background:var(--surface);color:var(--ink);border:1px solid var(--line);border-radius:9px}.icon-choice .mdi{font-size:22px}.icon-choice[aria-pressed=true]{background:var(--accent-soft);color:var(--accent);border-color:var(--accent)}.icon-choice.icon-auto{display:flex;justify-content:flex-start;gap:10px;padding:0 12px;font-size:12.5px;font-weight:500;height:38px}.action-list{display:grid;gap:6px;max-height:300px;overflow:auto;padding-right:2px}.action-choice{display:grid;gap:2px;padding:8px 12px;background:var(--surface);color:var(--ink);border:1px solid var(--line);border-radius:9px;font-size:12.5px;text-align:left}.action-choice strong{font-weight:600}.action-choice[aria-pressed=true]{background:var(--accent-soft);border-color:var(--accent)}.action-number{display:flex;align-items:center;gap:8px}.action-number input{flex:1;min-width:0}.items{display:grid;gap:6px}.item{display:flex;align-items:center;gap:8px;padding:7px 8px;border:1px solid var(--line-strong);border-radius:9px;background:var(--surface);width:100%;text-align:left;cursor:pointer;touch-action:pan-y}.item:hover{border-color:var(--accent)}.item.selected{border-color:var(--accent);background:var(--accent-soft)}.item.is-hidden{border-style:dashed}.item.is-hidden .av,.item.is-hidden b{opacity:.55}.item.is-overflow{border-style:dashed;border-color:var(--warn)}.item.is-overflow small{color:var(--warn)}.item.dragging-chip{border:2px dashed var(--accent);background:var(--accent-soft);cursor:grabbing}.item.just-added{animation:chip-added 1.2s ease-out}@keyframes chip-added{0%{background:var(--accent-soft)}to{background:var(--surface)}}.item .grip{color:var(--line-strong);font-size:13px;cursor:grab;letter-spacing:-2px;flex:none}.item .av{width:26px;height:26px;border-radius:7px;background:var(--surface-2);display:grid;place-items:center;font-size:15px;flex:none}.item .tx{flex:1;min-width:0;display:grid}.item .tx b{font-weight:500;font-size:12.5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.item .tx small{color:var(--muted);font-size:11px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.item .x{color:var(--muted);width:22px;height:22px;display:grid;place-items:center;border-radius:6px;flex:none;font-size:11px}.item .x:hover{color:var(--danger);background:var(--danger-soft)}.ghost-btn{border:1.5px dashed var(--line-strong);border-radius:9px;padding:8px;color:var(--accent);font-weight:600;width:100%;background:transparent}.ghost-btn:hover:not(:disabled){border-color:var(--accent);background:var(--accent-soft)}.dr-foot{margin-top:auto;display:flex;align-items:center;gap:8px;padding:10px 12px;border-top:1px solid var(--line);background:var(--surface-2);flex-wrap:wrap}.dr-foot .spacer{flex:1}.live{display:grid;gap:6px;padding:10px;border:1px solid var(--line);border-radius:10px;background:#e7e7e7;color:#1b1b1b;justify-items:start}.live small{color:#5a5f66}.live svg{display:block;height:28px}.option{display:flex;align-items:center;gap:10px;padding:8px 10px;border:1px solid var(--line);border-radius:9px;background:var(--surface);width:100%;text-align:left}.option:hover:not(:disabled){border-color:var(--accent)}.option .mdi{font-size:20px;width:26px;text-align:center;color:var(--ink-2);flex:none}.option .tx{display:grid;min-width:0}.option .tx strong{font-weight:500;font-size:12.5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.option .tx small{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.options{display:grid;gap:6px}.inspection-tile{display:grid;gap:3px;padding:8px 10px;border:1px solid var(--line);border-radius:9px;margin-bottom:6px}.inspection-tile strong{font-size:12.5px}.settings{padding:22px;overflow:auto;display:grid;gap:14px;align-content:start;grid-column:1 / -1}.settings .status{font-size:12px;color:var(--muted)}.set-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));gap:14px}.set-card{background:var(--surface);border:1px solid var(--line);border-radius:12px;padding:6px 14px 8px}.set-card h4{display:flex;align-items:center;gap:8px;padding:10px 0 8px}.set-card h4 .mdi{color:var(--muted);font-size:16px}.srow{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:8px 0;border-top:1px solid var(--line)}.srow>.s-label{color:var(--ink-2)}.srow.inactive .s-label,.srow.inactive .s-control{opacity:.45}.settings.offline .set-grid{opacity:.6}.step{display:inline-flex;align-items:center;gap:2px}.step button{width:26px;height:26px;border-radius:6px;color:var(--ink-2);background:var(--seg);display:grid;place-items:center}.step button .mdi{font-size:15px}.step button:hover:not(:disabled){color:var(--ink);background:var(--line-strong)}.step output{min-width:56px;text-align:center;font-weight:500}.panel{padding:22px 26px 40px;overflow:auto;display:grid;gap:18px;align-content:start;max-width:960px;width:100%}.panel.wide{max-width:1120px}.panel-head{display:flex;align-items:flex-start;gap:12px}.panel-head .tx{display:grid;gap:2px;flex:1;min-width:0}.panel-head h1{font-size:20px}.panel-head p{color:var(--muted);font-size:13px}.panel p,.panel li{color:var(--ink-2);font-size:13px}.card{background:var(--surface);border:1px solid var(--line);border-radius:12px;padding:16px 18px;display:grid;gap:12px;align-content:start}.card h2{font-size:14px}.card-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:14px}.field{display:grid;gap:6px}.field>.f-label,fieldset legend{font-size:11px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;color:var(--muted)}fieldset{border:0;padding:0;margin:0;display:grid;gap:8px;min-width:0}fieldset:disabled{opacity:.6}.boards{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:8px}.board{display:flex;align-items:center;gap:10px;padding:10px 12px;border:1px solid var(--line-strong);border-radius:10px;cursor:pointer}.board:has(input:checked){border-color:var(--accent);background:var(--accent-soft)}.board input{width:auto;margin:0;accent-color:var(--accent)}.board b{display:block;font-weight:600}.actions{display:flex;align-items:center;gap:8px;flex-wrap:wrap}.status-line{font-size:12.5px;color:var(--ink-2)}.status-line.ok{color:var(--good)}.status-line.error{color:var(--danger)}.progress-head{display:flex;align-items:center;gap:10px;font-weight:600;font-size:14px}.outcome{width:22px;height:22px;border-radius:50%;display:grid;place-items:center;color:#fff;font-size:12px;font-weight:700}.outcome.ok{background:var(--good)}.outcome.bad{background:var(--danger)}.steps{margin:0;padding-left:20px;display:grid;gap:8px}.steps li b{color:var(--ink)}.key-box{display:flex;align-items:center;gap:10px;padding:10px 12px;border:1px solid var(--line);border-radius:10px;background:var(--surface-2);flex-wrap:wrap}.key-box code{flex:1;min-width:0;background:none;padding:0;font-size:12px}.log{max-height:320px}details.log-wrap summary{cursor:pointer;font-weight:500;color:var(--ink-2);font-size:12.5px}details.log-wrap pre{margin-top:8px}.check{display:flex;align-items:flex-start;gap:10px;cursor:pointer}.check input{width:18px;height:18px;margin:1px 0 0;accent-color:var(--accent)}.check span{display:grid;gap:2px;font-weight:500}.node-line{display:flex;align-items:center;gap:6px;flex-wrap:wrap}.tools{display:flex;gap:10px;flex-wrap:wrap}.tool{display:flex;align-items:center;gap:10px;padding:10px 12px;border:1px solid var(--line);border-radius:10px;background:var(--surface);text-align:left;min-width:220px}.tool:hover{border-color:var(--accent)}.tool .tool-icon{width:30px;height:30px;border-radius:8px;background:var(--seg);display:grid;place-items:center;font-size:15px;color:var(--ink-2);flex:none}.tool .tx{display:grid}.tool .tx b{font-weight:600}.yaml-editor{display:grid;grid-template-columns:44px minmax(0,1fr);border:1px solid var(--line-strong);border-radius:10px;overflow:hidden;background:var(--code-bg);min-height:280px;max-height:60vh}.yaml-gutter{padding:12px 8px;text-align:right;color:var(--muted);font:12px/1.5 var(--mono);white-space:pre;user-select:none;overflow:hidden;border-right:1px solid var(--line)}.yaml-editor textarea{border:0;border-radius:0;background:transparent;resize:none;font:12px/1.5 var(--mono);padding:12px;white-space:pre;overflow:auto;min-height:280px;tab-size:2}.file-row{display:flex;align-items:center;gap:10px;flex-wrap:wrap}.file-row code{font-size:12px}.notice{display:flex;gap:12px;padding:12px 14px;border:1px solid var(--line);border-radius:10px;background:var(--surface-2)}.notice .mdi{font-size:20px;color:var(--ink-2)}.notice strong{display:block;font-weight:600;margin-bottom:2px}.alerts section{display:grid;gap:10px}.alerts h2{font-size:15px}.alerts-nav{display:flex;flex-wrap:wrap;gap:6px}.alerts-nav button{background:var(--accent-soft);color:var(--accent);padding:5px 11px;font-size:12px;border-radius:20px;font-weight:500}.alert-hero{display:grid;grid-template-columns:minmax(0,300px) 1fr;gap:20px;align-items:center}.alert-mock{background:#101820;border-radius:16px;padding:22px 18px;display:grid;place-items:center}.alert-mock-card{position:relative;width:100%;background:#ffe1c6;border:1px solid #0001;border-radius:14px;padding:12px 12px 48px 52px;color:#1b1b1b;display:grid;gap:2px}.alert-mock-icon{position:absolute;left:12px;top:12px;font-size:30px}.alert-mock-card strong{font-size:15px;line-height:1.2}.alert-mock-card>span{font-size:12px;color:#3a3a3c}.alert-mock-card .fake{position:absolute;right:10px;bottom:10px;padding:6px 16px;border-radius:999px;background:#1b1b1b;color:#fff;font-size:13px}.alert-screen{border:1px solid var(--line);border-radius:10px;padding:10px 12px;display:grid;gap:8px;background:var(--surface)}.alert-screen-head{display:flex;align-items:center;justify-content:space-between;gap:10px;flex-wrap:wrap}.copy-line{display:flex;align-items:flex-start;gap:8px;flex-wrap:wrap}.copy-line .copy-label{flex:none;width:96px;font-size:12px;color:var(--muted);padding-top:2px}.copy-line>code{flex:1;min-width:0;padding:4px 8px}.copy-line pre{flex:1;min-width:0}.table-scroll{overflow-x:auto}table{width:100%;border-collapse:collapse;font-size:12.5px;min-width:560px}th,td{text-align:left;vertical-align:top;padding:8px 12px 8px 0;border-bottom:1px solid var(--line)}th{font-size:10.5px;letter-spacing:.08em;text-transform:uppercase;color:var(--muted);font-weight:600}td code{white-space:nowrap}.chips{display:flex;flex-wrap:wrap;gap:6px}.chips .chip .mdi{font-size:16px}.chips .chip code{background:none;padding:0}.alert-icon-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(100px,1fr));gap:8px}.alert-icon{display:grid;justify-items:center;align-content:start;gap:4px;min-height:86px;padding:10px 6px 8px;background:var(--surface);color:var(--ink);border:1px solid var(--line);border-radius:10px;font-weight:500}.alert-icon:hover{border-color:var(--accent)}.alert-icon .mdi{font-size:26px}.alert-icon code{background:none;padding:0;font-size:11px;color:var(--accent);text-align:center;white-space:normal}.alert-icon small{font-size:11px;text-align:center}.swatches{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:8px}.swatch{display:flex;align-items:center;gap:10px;padding:7px;border:1px solid var(--line);border-radius:10px;background:var(--surface);color:var(--ink);font-size:12px;text-align:left;font-weight:500}.swatch:hover{border-color:var(--accent)}.swatch i{width:32px;height:32px;border-radius:8px;border:1px solid #0001;flex:none;display:block}.swatch span{display:grid;gap:2px;min-width:0}.swatch code{background:none;padding:0}.alerts-list{padding-left:18px;margin:0;display:grid;gap:8px}.alerts-list b{color:var(--ink)}.subhead{font-size:11px;font-weight:600;letter-spacing:.08em;text-transform:uppercase;color:var(--muted);margin-top:6px}.empty{margin:auto;max-width:420px;text-align:center;display:grid;gap:10px;justify-items:center;padding:60px 20px}.empty-icon{width:48px;height:48px;border-radius:14px;background:var(--seg);color:var(--muted);display:grid;place-items:center;font-size:26px}.empty h2{font-size:18px}.empty p{color:var(--muted)}.toast{position:fixed;left:50%;bottom:20px;transform:translate(-50%);display:flex;align-items:center;gap:14px;padding:10px 16px;background:var(--ink);color:var(--surface);border-radius:10px;box-shadow:var(--shadow);font-size:13px;z-index:60;max-width:min(92vw,560px)}.toast button{color:#9fc4ff;font-weight:650}@media(max-width:960px){.app{grid-template-columns:1fr;min-height:100vh}.side{position:static;height:auto;flex-direction:row;flex-wrap:wrap;align-items:center;border-right:0;border-bottom:1px solid var(--line);padding:10px;gap:4px 6px}.side .label,.side .spacer,.conn{display:none}.side #screens,.screen-item{display:contents}.screen-update{display:none}.side #pending{flex-basis:100%}.nav-item{width:auto}.more{display:contents}.main-head{flex-wrap:wrap;padding:10px 14px;gap:8px;position:static}.head-right{margin-left:0;width:100%}.body{grid-template-columns:1fr;overflow:visible}.canvas{padding:16px;overflow:visible}.pages{overflow-x:auto;padding-bottom:8px}.library{border-left:0;border-top:1px solid var(--line)}.lib-list{flex:none;max-height:360px}.drawer{position:fixed;top:0;width:100%}.panel{padding:16px}.alert-hero{grid-template-columns:1fr}}.progress{position:relative;height:6px;border-radius:3px;background:var(--seg);overflow:hidden}.progress i{position:absolute;inset:0 auto 0 0;background:var(--accent);border-radius:3px;transition:width .4s}.progress-text{display:flex;justify-content:space-between;gap:8px;font-size:11px;color:var(--muted)}.progress-text span:last-child{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;flex:1;text-align:right}.whatsnew summary{cursor:pointer;font-size:11.5px;color:var(--accent);font-weight:500;list-style:none}.whatsnew summary::-webkit-details-marker{display:none}.whatsnew ul{margin:6px 0 0;padding-left:14px;display:grid;gap:4px;font-size:11px;color:var(--ink-2)}.whatsnew ul li{line-height:1.35}.log-lines{max-height:160px;font-size:11px}.palette-backdrop{position:fixed;inset:0;background:#0a0c1247;z-index:70;display:grid;align-items:start;justify-items:center;padding:12vh 16px 16px}.palette{width:min(640px,100%);background:var(--surface);border:1px solid var(--line);border-radius:14px;box-shadow:var(--shadow);overflow:hidden;display:flex;flex-direction:column;max-height:70vh}.palette input{border:0;border-radius:0;border-bottom:1px solid var(--line);padding:14px 16px;font-size:15px;background:transparent}.palette-list{overflow:auto;padding:6px;display:grid;gap:2px}.palette-group{font-size:10.5px;font-weight:600;letter-spacing:.08em;text-transform:uppercase;color:var(--muted);padding:8px 10px 4px}.palette-item{display:flex;align-items:center;gap:10px;padding:8px 10px;border-radius:8px;width:100%;text-align:left;color:var(--ink)}.palette-item .mdi,.palette-item .glyph{width:22px;text-align:center;color:var(--muted);font-size:16px;flex:none}.palette-item .tx{flex:1;min-width:0;display:grid}.palette-item .tx small{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.palette-item .hint-key{font-size:10.5px;color:var(--muted);border:1px solid var(--line);border-radius:4px;padding:1px 5px}.palette-item.active,.palette-item:hover{background:var(--accent-soft)}.palette-empty{padding:18px;color:var(--muted);font-size:12.5px;text-align:center}.side .search-btn{display:flex;align-items:center;gap:8px;width:100%;margin:4px 0 6px;padding:7px 10px;border:1px solid var(--line);border-radius:8px;background:var(--surface-2);color:var(--muted);font-size:12px;text-align:left}.side .search-btn kbd{margin-left:auto;font:10.5px var(--ui-font);border:1px solid var(--line);border-radius:4px;padding:1px 5px;background:var(--surface)}.side .search-btn:hover{color:var(--ink);border-color:var(--line-strong)}.menu .sub{display:grid;padding:2px 0 4px 10px}.menu .sub button{font-size:12.5px;padding:6px 10px}.menu .sep{height:1px;background:var(--line);margin:4px 6px}.lib-row{display:flex;gap:6px;align-items:center}.lib-row select{padding:5px 8px;font-size:12px;flex:1;min-width:0}.lib-row .chip-toggle{flex:none;padding:5px 10px;border-radius:999px;font-size:11.5px;font-weight:500;color:var(--ink-2);background:var(--surface-2);border:1px solid var(--line)}.lib-row .chip-toggle[aria-pressed=true]{background:var(--ink);color:var(--surface);border-color:var(--ink)}.ent .av.on{background:#fff3d6!important;color:#b7791f!important}.ent .av.gone{background:var(--seg)!important;color:var(--muted)!important}.try-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:12px}.try-grid .field.wide{grid-column:1 / -1} diff --git a/screen_manager/app/static/index.html b/screen_manager/app/static/index.html index 03b82be..2ee78eb 100644 --- a/screen_manager/app/static/index.html +++ b/screen_manager/app/static/index.html @@ -5,8 +5,8 @@ ESP Screens - - + +
    diff --git a/screen_manager/app/updates.py b/screen_manager/app/updates.py index 08bdd9f..194cf91 100644 --- a/screen_manager/app/updates.py +++ b/screen_manager/app/updates.py @@ -7,6 +7,7 @@ import os from pathlib import Path import re import time +import changelog from core import FIRMWARE_VERSION LOG = logging.getLogger('screen_manager') @@ -31,6 +32,8 @@ class Updater: self.manager, self.path = manager, Path(path) self.auto, self.hosts, self.results, self.last_round = False, {}, {}, None self.task, self.current, self.queue, self.phase = None, None, [], None + # What's new since a screen's firmware, for the Update badge (app 0.2.74). + self.changelog = changelog.load() if self.path.exists(): raw = json.loads(self.path.read_text()) if raw.get('version') != 1: @@ -103,7 +106,7 @@ class Updater: def summary(self, screens=None, profiles=None): return {'auto': self.auto, 'target': FIRMWARE_VERSION, 'busy': self.current, - 'pending': len(self.pending(screens, profiles)), 'last_round': self.last_round} + 'pending': len(self.pending(screens, profiles)), 'last_round': self.last_round, 'changelog': self.changelog} def pending(self, screens=None, profiles=None): # Callers that already hold the inventory and profile list pass them in; the inventory diff --git a/tests/test_editor_live.py b/tests/test_editor_live.py new file mode 100644 index 0000000..361b264 --- /dev/null +++ b/tests/test_editor_live.py @@ -0,0 +1,149 @@ +"""Live values on the mockup, Identify, the test alert and the changelog for the Update badge (app 0.2.74). + +The editor asks /api/states for the tiles it shows and draws Home Assistant's values on the mockup; Identify and +Try it call a screen's own show_alert action, with the same field rules as an alert event; the update summary +carries the CHANGELOG sections so the badge can say what a screen gets. +""" +import importlib.util +import sys +import tempfile +import unittest +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[1] +sys.path.insert(0, str(ROOT / 'screen_manager/app')) +sys.path.insert(0, str(ROOT / 'tests')) +import changelog # noqa: E402 + +HAS_AIOHTTP = importlib.util.find_spec('aiohttp') is not None + +SAMPLE = '''## 0.2.74 (firmware 0.2.62) + +A new editor. + +- **One workspace.** Sidebar, pages, [library](docs/X.md) with `code`. +- Second line. + +## 0.2.71 (firmware 0.2.60) + +- **Slider stays.** Text. +''' + + +class Changelog(unittest.TestCase): + def test_sections_carry_plain_bullet_lines(self): + sections = changelog.parse(SAMPLE) + self.assertEqual([(s['app'], s['firmware']) for s in sections], [('0.2.74', '0.2.62'), ('0.2.71', '0.2.60')]) + self.assertEqual(sections[0]['lines'], ['One workspace. Sidebar, pages, library with code.', 'Second line.']) + self.assertEqual(changelog.parse(SAMPLE, limit=1)[0]['app'], '0.2.74') + + def test_the_real_changelog_is_found_and_shipped(self): + sections = changelog.load() + self.assertTrue(sections and sections[0]['lines'], 'CHANGELOG.md one folder up from the app') + self.assertIn('COPY CHANGELOG.md /app/CHANGELOG.md', (ROOT / 'screen_manager/Dockerfile').read_text()) + + +@unittest.skipUnless(HAS_AIOHTTP, 'Run using .venv-portal/bin/python for server tests') +class Endpoints(unittest.IsolatedAsyncioTestCase): + async def asyncSetUp(self): + import test_scaling + from aiohttp.test_utils import TestClient, TestServer + from server import Manager, create_app + self.ha = test_scaling.fake_ha(firmware='0.2.60', node='office-1') + self.ha.calls = [] + async def call(action, data): + self.ha.calls.append((action, data)) + self.ha.call = call + self.tmp = tempfile.TemporaryDirectory() + self.manager = Manager(self.ha, Path(self.tmp.name) / 'screens.json') + self.client = TestClient(TestServer(create_app(self.manager, True))) + await self.client.start_server() + inventory = await (await self.client.get('/api/inventory')).json() + self.csrf = inventory['csrf'] + self.screen = inventory['screens'][0] + self.headers = {'X-Screen-CSRF': self.csrf} + + async def asyncTearDown(self): + await self.client.close() + self.tmp.cleanup() + + async def test_states_give_the_value_word_and_attributes_per_entity(self): + response = await self.client.get('/api/states?entity=light.a&entity=sensor.t&entity=light.nope&entity=screen.clock') + states = (await response.json())['states'] + self.assertEqual(set(states), {'light.a', 'sensor.t'}, 'unknown entities and built-ins are left out') + self.assertEqual(states['light.a']['state'], 'on') + self.assertEqual(states['sensor.t']['state'], '21.5') + self.assertEqual(states['sensor.t']['a']['unit_of_measurement'], '°C') + self.assertIn('word', states['light.a']) + + async def test_identify_blinks_the_screen_through_its_alert_action(self): + response = await self.client.post(f"/api/screens/{self.screen['id']}/identify", headers=self.headers) + self.assertEqual(response.status, 200, await response.text()) + (action, data), = self.ha.calls + self.assertEqual(action, 'esphome.office_1_show_alert') + self.assertEqual((data['title'], data['flash'], data['timeout'], data['icon']), (f"This is {self.screen['name']}", True, 8, 'bell-ring')) + missing = await self.client.post('/api/screens/text.nope/identify', headers=self.headers) + self.assertEqual(missing.status, 400) + + async def test_the_test_alert_reaches_one_screen_or_all_with_the_event_rules(self): + body = {'screen': self.screen['id'], 'data': {'title': 'Door', 'timeout': 'soon', 'flash': 'yes'}} + response = await self.client.post('/api/alerts/test', headers=self.headers, json=body) + result = await response.json() + self.assertEqual((response.status, result['sent'], result['unusable']), (200, 1, ['timeout']), result) + action, data = self.ha.calls[-1] + self.assertEqual(action, 'esphome.office_1_show_alert') + self.assertEqual((data['title'], data['timeout'], data['flash'], data['subtitle']), ('Door', 0, True, '')) + everyone = await self.client.post('/api/alerts/test', headers=self.headers, json={'screen': 'all', 'data': {'title': 'Hi'}}) + self.assertEqual(everyone.status, 200, await everyone.text()) + self.assertEqual((await everyone.json())['sent'], 1) + self.assertEqual(len(self.ha.calls), 2) + bad = await self.client.post('/api/alerts/test', headers=self.headers, json={'screen': 'text.nope'}) + self.assertEqual(bad.status, 400) + + async def test_the_update_summary_carries_the_changelog(self): + inventory = await (await self.client.get('/api/inventory?light=1')).json() + sections = inventory['updates']['changelog'] + self.assertTrue(sections) + self.assertEqual(set(sections[0]), {'app', 'firmware', 'lines'}) + + +class Editor(unittest.TestCase): + """The page side of the same features, read from the Vue sources.""" + def setUp(self): + import editor_sources + self.store = editor_sources.source('store.ts') + self.page = editor_sources.PAGE + + def test_the_mockup_polls_live_values_and_draws_them(self): + self.assertIn('getJson(`states?${query}`)', self.store) + self.assertIn('if (!document.hidden && state.layout && state.tab === "layout" && route.value === "") loadStates();', self.store) + for marker in ('liveOf(props.tile.entity)', ':class="{ lit: isOn }"', ':style="sliderStyle"', "class=\"tog\" :class=\"{ off: !on }\""): + self.assertIn(marker, self.page, marker) + + def test_identify_and_the_test_alert_have_their_buttons(self): + self.assertIn('send(`screens/${encodeURIComponent(screen.id)}/identify`, "POST")', self.store) + self.assertIn('send("alerts/test", "POST", { screen: target, data })', self.store) + self.assertIn('id="identify"', self.page) + self.assertIn('id="alerts-try"', self.page) + self.assertIn('id="try-send"', self.page) + + def test_layouts_can_be_copied_exported_and_imported(self): + for name in ('export function copyLayoutFrom', 'export function exportLayout', 'export function importLayout'): + self.assertIn(name, self.store) + for marker in ('id="copy-layout"', 'id="export-layout"', 'id="import-layout"', 'accept="application/json,.json"'): + self.assertIn(marker, self.page, marker) + self.assertIn('.slice(0, tileLimit.value)', self.store, 'an imported layout never exceeds the firmware limit') + + def test_the_library_filters_by_room_and_placement_and_the_palette_exists(self): + for marker in ('id="room"', 'id="hide-placed"', 'id="open-palette"', 'id="palette-input"', "e.key.toLowerCase() === \"k\""): + self.assertIn(marker, self.page, marker) + + def test_updates_show_their_notes_and_progress(self): + self.assertIn('export function whatsNew', self.store) + self.assertIn('export function updateProgress', self.store) + for marker in ('class="whatsnew"', 'role="progressbar"', "go('#firmware')"): + self.assertIn(marker, self.page, marker) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/test_editor_startup.py b/tests/test_editor_startup.py index c302135..961394f 100644 --- a/tests/test_editor_startup.py +++ b/tests/test_editor_startup.py @@ -25,9 +25,10 @@ STORE = editor_sources.source('store.ts') class Startup(unittest.TestCase): def test_no_screen_opens_by_itself(self): self.assertNotIn('inventory.screens[0]', SCRIPT) - # The one way into a screen is its button in the list. - self.assertEqual(re.findall(r'(? select(screen.id)', editor_sources.component('CommandPalette')) for name in ('refresh', 'applyLive'): body = STORE[STORE.index(f'function {name}('):] self.assertNotRegex(body[:body.index('\n}\n')], r'(? -import { computed } from "vue"; +import { computed, onBeforeUnmount, onMounted } from "vue"; import Sidebar from "./components/Sidebar.vue"; import Toast from "./components/Toast.vue"; +import CommandPalette from "./components/CommandPalette.vue"; import ScreenView from "./components/ScreenView.vue"; import EmptyState from "./components/EmptyState.vue"; import AppSettingsView from "./components/AppSettingsView.vue"; @@ -19,6 +20,12 @@ const view = computed(() => { if (route.value === "#override") return OverrideView; return currentScreen.value && state.layout ? ScreenView : EmptyState; }); +// ⌘K (Ctrl+K) opens the search from anywhere. +function onKey(e: KeyboardEvent) { + if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === "k") { e.preventDefault(); state.palette = !state.palette; } +} +onMounted(() => document.addEventListener("keydown", onKey)); +onBeforeUnmount(() => document.removeEventListener("keydown", onKey)); diff --git a/web/src/components/AlertsView.vue b/web/src/components/AlertsView.vue index 65ac368..269d37c 100644 --- a/web/src/components/AlertsView.vue +++ b/web/src/components/AlertsView.vue @@ -1,11 +1,32 @@