// Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
// SPDX-License-Identifier: AGPL-3.0-or-later
//
// GENERATED by src/web/wizard/build_assets.py - DO NOT EDIT BY HAND.
// Edit the source documents under src/web/input/ and re-run the generator.

#include "network_drivers/application/web_assets.h"

// ---- html ----
const char DETWS_DASHBOARD_PAGE[] =
    "<!doctype html><html lang=\"en\"><head><meta charset=\"utf-8\" /><meta name=\"viewport\" content=\"width=devic"
    "e-width, initial-scale=1\" /><title>Dashboard</title> <style>*{box-sizing:border-box;}body{margin:0;font-famil"
    "y:system-ui,\"Segoe UI\",Roboto,sans-serif;background:#0e1116;color:#e6edf3;}header{display:flex;align-items:c"
    "enter;gap:10px;padding:14px 20px;font-size:18px;font-weight:600;border-bottom:1px solid #30363d;}#dot{width:10"
    "px;height:10px;border-radius:50%;background:#f85149;}#dot.live{background:#3fb950;}#status{font-size:13px;font"
    "-weight:400;color:#8b949e;}#grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:14"
    "px;padding:18px;}.card{background:#1b2230;border:1px solid #30363d;border-radius:10px;padding:14px;}.card .lab"
    "el{margin-bottom:8px;font-size:13px;color:#8b949e;}.card .num{font-size:30px;font-weight:600;font-variant-nume"
    "ric:tabular-nums;}.card .unit{margin-left:4px;font-size:14px;color:#8b949e;}svg{display:block;width:100%;heigh"
    "t:auto;}svg text{fill:#e6edf3;font-family:inherit;}canvas{display:block;width:100%;height:auto;}.btn{padding:8"
    "px 14px;font:inherit;color:#fff;background:#238636;border:0;border-radius:6px;cursor:pointer;}.btn:active{back"
    "ground:#2ea043;}input[type=\"range\"]{width:100%;accent-color:#3fb950;}.sw{width:42px;height:22px;cursor:point"
    "er;accent-color:#3fb950;}</style> </head><body><header><span id=\"dot\"></span> Dashboard <span id=\"status\">"
    "</span></header><div id=\"grid\"></div> <script>(function () {\nvar NS = \"http://www.w3.org/2000/svg\";\nvar "
    "base = location.pathname.replace(/\\/+$/, \"\");\nvar grid = document.getElementById(\"grid\");\nvar dot = doc"
    "ument.getElementById(\"dot\");\nvar status = document.getElementById(\"status\");\nvar widgets = {};\nvar ws ="
    " null;\nfunction sendCtrl(k, v) {\nif (ws && ws.readyState === 1)\nws.send(JSON.stringify({ k: k, v: v }));\n}"
    "\nfunction clamp(f) {\nreturn f < 0 ? 0 : f > 1 ? 1 : f;\n}\nfunction frac(v, mn, mx) {\nreturn mx > mn ? clam"
    "p((v - mn) / (mx - mn)) : 0;\n}\nfunction fmt(v) {\nreturn Math.abs(v) >= 100 ? v.toFixed(0) : v.toFixed(1);\n"
    "}\nfunction el(tag, attrs) {\nvar e = document.createElementNS(NS, tag);\nfor (var k in attrs) e.setAttribute("
    "k, attrs[k]);\nreturn e;\n}\nfunction polar(cx, cy, r, deg) {\nvar a = (deg * Math.PI) / 180;\nreturn [cx + r "
    "* Math.cos(a), cy - r * Math.sin(a)];\n}\nfunction arc(cx, cy, r, f) {\nvar s = polar(cx, cy, r, 180),\ne = po"
    "lar(cx, cy, r, 180 - 180 * f);\nreturn (\n\"M\" +\ns[0] +\n\" \" +\ns[1] +\n\" A\" +\nr +\n\" \" +\nr +\n\" 0 "
    "0 1 \" +\ne[0] +\n\" \" +\ne[1]\n);\n}\nfunction card(w) {\nvar c = document.createElement(\"div\");\nc.classN"
    "ame = \"card\";\nvar lab = document.createElement(\"div\");\nlab.className = \"label\";\nlab.textContent = w.l"
    "abel;\nc.appendChild(lab);\nvar upd;\nif (w.type === \"gauge\") {\nvar g = el(\"svg\", { viewBox: \"0 0 120 72"
    "\" });\ng.appendChild(\nel(\"path\", {\nd: arc(60, 62, 50, 1),\nfill: \"none\",\nstroke: \"#30363d\",\n\"strok"
    "e-width\": 10,\n\"stroke-linecap\": \"round\",\n}),\n);\nvar gv = el(\"path\", {\nd: arc(60, 62, 50, 0),\nfill"
    ": \"none\",\nstroke: \"#3fb950\",\n\"stroke-width\": 10,\n\"stroke-linecap\": \"round\",\n});\ng.appendChild(g"
    "v);\nvar gt = el(\"text\", {\nx: 60,\ny: 58,\n\"text-anchor\": \"middle\",\n\"font-size\": 16,\n\"font-weight"
    "\": 600,\n});\ngt.textContent = \"-\";\ng.appendChild(gt);\nc.appendChild(g);\nupd = function (v) {\ngv.setAtt"
    "ribute(\n\"d\",\narc(60, 62, 50, frac(v, w.min, w.max)),\n);\ngt.textContent = fmt(v) + w.unit;\n};\n} else if"
    " (w.type === \"bar\") {\nvar b = el(\"svg\", { viewBox: \"0 0 200 40\" });\nb.appendChild(\nel(\"rect\", {\nx:"
    " 0,\ny: 16,\nwidth: 200,\nheight: 12,\nrx: 6,\nfill: \"#30363d\",\n}),\n);\nvar bf = el(\"rect\", {\nx: 0,\ny:"
    " 16,\nwidth: 0,\nheight: 12,\nrx: 6,\nfill: \"#3fb950\",\n});\nb.appendChild(bf);\nvar bt = el(\"text\", { x: "
    "0, y: 11, \"font-size\": 12 });\nbt.textContent = \"-\";\nb.appendChild(bt);\nc.appendChild(b);\nupd = functio"
    "n (v) {\nbf.setAttribute(\n\"width\",\n200 * frac(v, w.min, w.max),\n);\nbt.textContent = fmt(v) + w.unit;\n};"
    "\n} else if (w.type === \"sparkline\") {\nvar s = el(\"svg\", { viewBox: \"0 0 200 50\" });\nvar pl = el(\"pol"
    "yline\", {\nfill: \"none\",\nstroke: \"#3fb950\",\n\"stroke-width\": 2,\npoints: \"\",\n});\ns.appendChild(pl)"
    ";\nc.appendChild(s);\nvar sn = document.createElement(\"div\");\nsn.className = \"num\";\nsn.textContent = \"-"
    "\";\nc.appendChild(sn);\nvar hist = [];\nupd = function (v) {\nhist.push(v);\nif (hist.length > 40) hist.shift"
    "();\nvar pts = hist\n.map(function (y, i) {\nreturn (\n(200 * i) / 39 +\n\",\" +\n(50 - 50 * frac(y, w.min, w."
    "max))\n);\n})\n.join(\" \");\npl.setAttribute(\"points\", pts);\nsn.textContent = fmt(v) + \" \" + w.unit;\n};"
    "\n} else if (w.type === \"chart\") {\nvar cv = document.createElement(\"canvas\");\ncv.width = 240;\ncv.height"
    " = 64;\nc.appendChild(cv);\nvar cn = document.createElement(\"div\");\ncn.className = \"num\";\ncn.textContent"
    " = \"-\";\nc.appendChild(cn);\nvar ctx = cv.getContext(\"2d\");\nvar ch = [];\nupd = function (v) {\nch.push(v"
    ");\nif (ch.length > cv.width) ch.shift();\nctx.clearRect(0, 0, cv.width, cv.height);\nctx.strokeStyle = \"#3fb"
    "950\";\nctx.lineWidth = 2;\nctx.beginPath();\nfor (var i = 0; i < ch.length; i++) {\nvar x = (cv.width * i) / "
    "(cv.width - 1);\nvar y =\ncv.height -\ncv.height * frac(ch[i], w.min, w.max);\nif (i === 0) ctx.moveTo(x, y);"
    "\nelse ctx.lineTo(x, y);\n}\nctx.stroke();\ncn.textContent = fmt(v) + \" \" + w.unit;\n};\n} else if (w.type ="
    "== \"button\") {\nvar btn = document.createElement(\"button\");\nbtn.className = \"btn\";\nbtn.textContent = "
    "\"Press\";\nbtn.onclick = function () {\nsendCtrl(w.key, 1);\n};\nc.appendChild(btn);\nupd = function () {};\n"
    "} else if (w.type === \"toggle\") {\nvar tg = document.createElement(\"input\");\ntg.type = \"checkbox\";\ntg."
    "className = \"sw\";\ntg.onchange = function () {\nsendCtrl(w.key, tg.checked ? 1 : 0);\n};\nc.appendChild(tg);"
    "\nupd = function (v) {\ntg.checked = v >= 0.5;\n};\n} else if (w.type === \"slider\") {\nvar sl = document.cre"
    "ateElement(\"input\");\nsl.type = \"range\";\nsl.min = w.min;\nsl.max = w.max;\nsl.value = w.min;\nvar sv = do"
    "cument.createElement(\"span\");\nsv.className = \"unit\";\nsv.textContent = fmt(w.min) + w.unit;\nsl.oninput ="
    " function () {\nsv.textContent = fmt(+sl.value) + w.unit;\n};\nsl.onchange = function () {\nsendCtrl(w.key, +s"
    "l.value);\n};\nc.appendChild(sl);\nc.appendChild(sv);\nupd = function () {};\n} else {\nvar n = document.creat"
    "eElement(\"div\");\nn.className = \"num\";\nvar tn = document.createTextNode(\"-\");\nn.appendChild(tn);\nvar "
    "u = document.createElement(\"span\");\nu.className = \"unit\";\nu.textContent = w.unit;\nn.appendChild(u);\nc."
    "appendChild(n);\nupd = function (v) {\ntn.nodeValue = fmt(v);\n};\n}\ngrid.appendChild(c);\nreturn upd;\n}\nfe"
    "tch(base + \"/layout\")\n.then(function (r) {\nreturn r.json();\n})\n.then(function (list) {\nlist.forEach(fun"
    "ction (w) {\nwidgets[w.key] = card(w);\n});\nif (\nlist.some(function (w) {\nreturn (\nw.type === \"button\" |"
    "|\nw.type === \"toggle\" ||\nw.type === \"slider\"\n);\n})\n) {\nvar proto =\nlocation.protocol === \"https:\""
    "\n? \"wss://\"\n: \"ws://\";\nws = new WebSocket(\nproto + location.host + base + \"/ws\",\n);\n}\nvar es = ne"
    "w EventSource(base + \"/stream\");\nes.onopen = function () {\ndot.className = \"live\";\nstatus.textContent ="
    " \"live\";\n};\nes.onerror = function () {\ndot.className = \"\";\nstatus.textContent = \"reconnecting...\";\n"
    "};\nes.onmessage = function (ev) {\ntry {\nvar d = JSON.parse(ev.data);\nfor (var k in d)\nif (widgets[k]) wid"
    "gets[k](d[k]);\n} catch (e) {}\n};\n});\n})();</script> </body></html>";

const char DETWS_PROV_FORM[] =
    "<!doctype html><html><head><meta name=\"viewport\" content=\"width=device-width\" /><title>WiFi setup</title><"
    "/head><body><h2>WiFi setup</h2><form method=\"POST\" action=\"/save\"> SSID:<br /><input name=\"ssid\" maxleng"
    "th=\"32\" /><br /> Password:<br /><input name=\"psk\" type=\"password\" maxlength=\"63\" /><br /><br /><input "
    "type=\"submit\" value=\"Save\" /></form></body></html>";

const char DETWS_PROV_SAVED_HTML[] = "<html><body> Saved. Rebooting... </body></html>";

const char DETWS_TERMINAL_PAGE[] =
    "<!doctype html><html><head><meta charset=\"utf-8\" /><meta name=\"viewport\" content=\"width=device-width,init"
    "ial-scale=1\" /><title>DetWS Terminal</title> <style>:root{--g:#2bb35a;--g2:#00c000;--bg:#080c08;}*{box-sizing"
    ":border-box;}html,body{margin:0;height:100%;background:var(--bg);color:var(--g);font:14px/1.45 \"Consolas\",\""
    "DejaVu Sans Mono\",monospace;}#wrap{display:flex;flex-direction:column;height:100%;position:relative;}#out{fle"
    "x:1;overflow:auto;padding:10px;white-space:pre-wrap;word-break:break-word;text-shadow:0 0 4px rgba(43,179,90,0"
    ".55);}#bar{display:flex;border-top:1px solid #14401f;background:#0a0f0a;}#ps{padding:8px 4px 8px 10px;color:va"
    "r(--g2);}#in{flex:1;background:transparent;border:0;color:var(--g);font:inherit;padding:8px;outline:none;}#st{"
    "padding:4px 10px;font-size:11px;color:#1c6e38;border-top:1px solid #14401f;}#crt{position:absolute;inset:0;poi"
    "nter-events:none;z-index:9;background:repeating-linear-gradient( rgba(0,0,0,0) 0 2px,rgba(0,0,0,0.18) 3px );bo"
    "x-shadow:inset 0 0 120px rgba(0,0,0,0.6);}.e{color:#d2553a;}</style> </head><body><div id=\"wrap\"><div id=\"o"
    "ut\"></div><div id=\"bar\"><span id=\"ps\">&gt;</span ><input id=\"in\" autocomplete=\"off\" autofocus /></div"
    "><div id=\"st\">connecting…</div><div id=\"crt\"></div></div> <script>var out = document.getElementById(\"out"
    "\"),\ninp = document.getElementById(\"in\"),\nst = document.getElementById(\"st\");\nvar hist = [],\nhi = 0,\n"
    "ws,\nurl =\n(location.protocol == \"https:\" ? \"wss\" : \"ws\") +\n\"://\" +\nlocation.host +\nlocation.pathn"
    "ame.replace(/\\/$/, \"\") +\n\"/ws\";\nfunction add(t, c) {\nvar b =\nout.scrollHeight - out.clientHeight - ou"
    "t.scrollTop < 40;\nvar s = document.createElement(\"span\");\nif (c) s.className = c;\ns.textContent = t;\nout"
    ".appendChild(s);\nif (b) out.scrollTop = out.scrollHeight;\n}\nfunction conn() {\nws = new WebSocket(url);\nws"
    ".onopen = function () {\nst.textContent = \"connected\";\n};\nws.onmessage = function (e) {\nadd(e.data);\n};"
    "\nws.onclose = function () {\nst.textContent = \"disconnected — retrying…\";\nsetTimeout(conn, 1000);\n};\nws."
    "onerror = function () {\ntry {\nws.close();\n} catch (_) {}\n};\n}\ninp.addEventListener(\"keydown\", function"
    " (e) {\nif (e.key == \"Enter\") {\nvar v = inp.value;\nif (v) {\nif (ws && ws.readyState == 1) {\nws.send(v);"
    "\nadd(\"> \" + v + \"\\n\");\n} else add(\"> \" + v + \" (offline)\\n\", \"e\");\nhist.push(v);\nhi = hist.len"
    "gth;\n}\ninp.value = \"\";\n} else if (e.key == \"ArrowUp\") {\nif (hi > 0) {\nhi--;\ninp.value = hist[hi] || "
    "\"\";\n}\n} else if (e.key == \"ArrowDown\") {\nif (hi < hist.length) {\nhi++;\ninp.value = hist[hi] || \"\";"
    "\n}\n}\n});\nconn();</script> </body></html>";

// ---- json ----
const char DETWS_STATS_JSON[] =
    "{\"uptime_ms\":{{uptime_ms}},\"requests\":{{requests}},\"http_2xx\":{{http_2xx}},\"http_4xx\":{{http_4xx}},\"h"
    "ttp_5xx\":{{http_5xx}},\"active_conns\":{{active_conns}},\"free_heap\":{{free_heap}}}";

// ---- text ----
const char DETWS_METRICS_PROM[] =
    "# HELP detws_uptime_seconds Device uptime in seconds.\n# TYPE detws_uptime_seconds gauge\ndetws_uptime_seconds"
    " {{uptime_seconds}}\n# HELP detws_http_requests_total Total HTTP responses sent.\n# TYPE detws_http_requests_t"
    "otal counter\ndetws_http_requests_total {{requests_total}}\n# HELP detws_http_responses_total HTTP responses b"
    "y status class.\n# TYPE detws_http_responses_total counter\ndetws_http_responses_total{class=\"2xx\"} {{resp_2"
    "xx}}\ndetws_http_responses_total{class=\"4xx\"} {{resp_4xx}}\ndetws_http_responses_total{class=\"5xx\"} {{resp"
    "_5xx}}\n# HELP detws_active_connections Currently active connection slots.\n# TYPE detws_active_connections ga"
    "uge\ndetws_active_connections {{active_conns}}\n# HELP detws_max_connections Connection slot capacity.\n# TYPE"
    " detws_max_connections gauge\ndetws_max_connections {{max_conns}}\n# HELP detws_free_heap_bytes Free heap in b"
    "ytes.\n# TYPE detws_free_heap_bytes gauge\ndetws_free_heap_bytes {{free_heap}}\n# HELP detws_min_free_heap_byt"
    "es Lowest free heap observed since boot, in bytes.\n# TYPE detws_min_free_heap_bytes gauge\ndetws_min_free_hea"
    "p_bytes {{min_free_heap}}\n# HELP detws_heap_size_bytes Total heap size, in bytes.\n# TYPE detws_heap_size_byt"
    "es gauge\ndetws_heap_size_bytes {{heap_size}}\n# HELP detws_max_alloc_heap_bytes Largest contiguous allocatabl"
    "e heap block, in bytes.\n# TYPE detws_max_alloc_heap_bytes gauge\ndetws_max_alloc_heap_bytes {{max_alloc_heap}"
    "}\n";
