$P@D$3RV£R commited on
Commit
e8f9ef2
·
1 Parent(s): 6c48c49

Release v1.1.8: mail-forwarded landing feedback (no mail app)

Browse files
README.md CHANGED
@@ -7,15 +7,15 @@ sdk: static
7
  pinned: false
8
  ---
9
 
10
- # careTalk **v1.1.7**
11
 
12
- Public demo — speech-to-text care notes, custom training, live webhooks.
13
 
14
- **Feedback:** landing form opens an email draft to **pd3rvr@icloud.com**.
15
 
16
  | | |
17
  |---|---|
18
  | Test admin | `admin@don.local` |
19
  | Password / PIN | `2473` |
20
 
21
- Source: https://github.com/2000pd3rvr/careTalk/releases/tag/v1.1.7
 
7
  pinned: false
8
  ---
9
 
10
+ # careTalk **v1.1.8**
11
 
12
+ Public demo — speech-to-text care notes, training & live webhooks.
13
 
14
+ **Send feedback** emails the careTalk inbox via mail forwarding (no device mail app).
15
 
16
  | | |
17
  |---|---|
18
  | Test admin | `admin@don.local` |
19
  | Password / PIN | `2473` |
20
 
21
+ Source: https://github.com/2000pd3rvr/careTalk
admin.html CHANGED
@@ -14,10 +14,10 @@
14
  href="https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,550;9..144,700&family=Source+Sans+3:wght@400;600;700&display=swap"
15
  rel="stylesheet"
16
  />
17
- <script type="module" crossorigin src="./assets/admin-vg_JNeHI.js"></script>
18
  <link rel="modulepreload" crossorigin href="./assets/modulepreload-polyfill-B5Qt9EMX.js">
19
- <link rel="modulepreload" crossorigin href="./assets/subscribers-BDwoJ2Wh.js">
20
- <link rel="stylesheet" crossorigin href="./assets/subscribers--ZiVSqeN.css">
21
  <link rel="manifest" href="./manifest.webmanifest"><script id="vite-plugin-pwa:register-sw" src="./registerSW.js"></script></head>
22
  <body class="admin-page">
23
  <header class="site-header">
@@ -32,7 +32,7 @@
32
 
33
  <main class="section band">
34
  <div class="section-inner admin-wrap">
35
- <p class="version-pill">Version <span data-app-version>1.1.7</span></p>
36
 
37
  <section id="adminLogin" class="admin-card" aria-labelledby="admin-login-title">
38
  <h1 id="admin-login-title">Updates access</h1>
@@ -60,7 +60,7 @@
60
  <h1 id="admin-panel-title">Subscribers</h1>
61
  <p class="lede">
62
  <strong id="subscriberCount">0</strong> email(s) on this browser
63
- · careTalk <span data-app-version>1.1.7</span>
64
  </p>
65
  </div>
66
  <div class="admin-actions">
@@ -97,7 +97,7 @@
97
 
98
  <footer class="site-footer">
99
  <div class="section-inner">
100
- <p>careTalk ops · v<span data-app-version>1.1.7</span></p>
101
  </div>
102
  </footer>
103
 
 
14
  href="https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,550;9..144,700&family=Source+Sans+3:wght@400;600;700&display=swap"
15
  rel="stylesheet"
16
  />
17
+ <script type="module" crossorigin src="./assets/admin-BoC_GjKf.js"></script>
18
  <link rel="modulepreload" crossorigin href="./assets/modulepreload-polyfill-B5Qt9EMX.js">
19
+ <link rel="modulepreload" crossorigin href="./assets/subscribers-DauO8VtY.js">
20
+ <link rel="stylesheet" crossorigin href="./assets/subscribers-Sa7xbXRt.css">
21
  <link rel="manifest" href="./manifest.webmanifest"><script id="vite-plugin-pwa:register-sw" src="./registerSW.js"></script></head>
22
  <body class="admin-page">
23
  <header class="site-header">
 
32
 
33
  <main class="section band">
34
  <div class="section-inner admin-wrap">
35
+ <p class="version-pill">Version <span data-app-version>1.1.8</span></p>
36
 
37
  <section id="adminLogin" class="admin-card" aria-labelledby="admin-login-title">
38
  <h1 id="admin-login-title">Updates access</h1>
 
60
  <h1 id="admin-panel-title">Subscribers</h1>
61
  <p class="lede">
62
  <strong id="subscriberCount">0</strong> email(s) on this browser
63
+ · careTalk <span data-app-version>1.1.8</span>
64
  </p>
65
  </div>
66
  <div class="admin-actions">
 
97
 
98
  <footer class="site-footer">
99
  <div class="section-inner">
100
+ <p>careTalk ops · v<span data-app-version>1.1.8</span></p>
101
  </div>
102
  </footer>
103
 
app.html CHANGED
@@ -23,7 +23,7 @@
23
  if (!isDemo) return;
24
  sessionStorage.removeItem("don.session.userId");
25
  sessionStorage.removeItem("don.train.authed");
26
- var appVer = "1.1.7";
27
  var flag = "don.demo.appVer";
28
  if (localStorage.getItem(flag) === appVer) return;
29
  localStorage.setItem(flag, appVer);
@@ -46,7 +46,7 @@
46
  } catch (e) {}
47
  })();
48
  </script>
49
- <script type="module" crossorigin src="./assets/app-Cw1kdNnU.js"></script>
50
  <link rel="modulepreload" crossorigin href="./assets/modulepreload-polyfill-B5Qt9EMX.js">
51
  <link rel="stylesheet" crossorigin href="./assets/app-CTsfb-0l.css">
52
  <link rel="manifest" href="./manifest.webmanifest"><script id="vite-plugin-pwa:register-sw" src="./registerSW.js"></script></head>
 
23
  if (!isDemo) return;
24
  sessionStorage.removeItem("don.session.userId");
25
  sessionStorage.removeItem("don.train.authed");
26
+ var appVer = "1.1.8";
27
  var flag = "don.demo.appVer";
28
  if (localStorage.getItem(flag) === appVer) return;
29
  localStorage.setItem(flag, appVer);
 
46
  } catch (e) {}
47
  })();
48
  </script>
49
+ <script type="module" crossorigin src="./assets/app-BoDOH5ck.js"></script>
50
  <link rel="modulepreload" crossorigin href="./assets/modulepreload-polyfill-B5Qt9EMX.js">
51
  <link rel="stylesheet" crossorigin href="./assets/app-CTsfb-0l.css">
52
  <link rel="manifest" href="./manifest.webmanifest"><script id="vite-plugin-pwa:register-sw" src="./registerSW.js"></script></head>
assets/{admin-vg_JNeHI.js → admin-BoC_GjKf.js} RENAMED
@@ -1,4 +1,4 @@
1
- import"./modulepreload-polyfill-B5Qt9EMX.js";import{A as g,i as f,s as v,a as p,c as y,r as E,b as h,d as L}from"./subscribers-BDwoJ2Wh.js";function d(e){return String(e||"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}function B(e){if(!e)return"—";try{return new Date(e).toLocaleString("en-GB",{day:"numeric",month:"short",year:"numeric",hour:"2-digit",minute:"2-digit"})}catch{return e}}function a(e){const r=document.getElementById("adminLogin"),n=document.getElementById("adminPanel");r&&(r.hidden=e),n&&(n.hidden=!e)}function o(){const e=h(),r=document.getElementById("subscriberRows"),n=document.getElementById("subscriberEmpty"),t=document.getElementById("subscriberCount");t&&(t.textContent=String(e.length)),r&&(r.innerHTML=e.map(s=>`<tr data-id="${d(s.id)}">
2
  <td>${d(s.email)}</td>
3
  <td>${d(s.name||"—")}</td>
4
  <td>${d(B(s.at))}</td>
 
1
+ import"./modulepreload-polyfill-B5Qt9EMX.js";import{A as g,i as f,s as v,a as p,c as y,r as E,b as h,d as L}from"./subscribers-DauO8VtY.js";function d(e){return String(e||"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}function B(e){if(!e)return"—";try{return new Date(e).toLocaleString("en-GB",{day:"numeric",month:"short",year:"numeric",hour:"2-digit",minute:"2-digit"})}catch{return e}}function a(e){const r=document.getElementById("adminLogin"),n=document.getElementById("adminPanel");r&&(r.hidden=e),n&&(n.hidden=!e)}function o(){const e=h(),r=document.getElementById("subscriberRows"),n=document.getElementById("subscriberEmpty"),t=document.getElementById("subscriberCount");t&&(t.textContent=String(e.length)),r&&(r.innerHTML=e.map(s=>`<tr data-id="${d(s.id)}">
2
  <td>${d(s.email)}</td>
3
  <td>${d(s.name||"—")}</td>
4
  <td>${d(B(s.at))}</td>
assets/{app-Cw1kdNnU.js → app-BoDOH5ck.js} RENAMED
@@ -1,5 +1,5 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./web-DyS4cL83.js","./modulepreload-polyfill-B5Qt9EMX.js","./web-CXyz-Izy.js","./web-CgUdoTZR.js"])))=>i.map(i=>d[i]);
2
- import"./modulepreload-polyfill-B5Qt9EMX.js";/*! Capacitor: https://capacitorjs.com/ - MIT License */var De;(function(e){e.Unimplemented="UNIMPLEMENTED",e.Unavailable="UNAVAILABLE"})(De||(De={}));class vt extends Error{constructor(t,n,i){super(t),this.message=t,this.code=n,this.data=i}}const Fr=e=>{var t,n;return e!=null&&e.androidBridge?"android":!((n=(t=e==null?void 0:e.webkit)===null||t===void 0?void 0:t.messageHandlers)===null||n===void 0)&&n.bridge?"ios":"web"},Hr=e=>{const t=e.CapacitorCustomPlatform||null,n=e.Capacitor||{},i=n.Plugins=n.Plugins||{},r=()=>t!==null?t.name:Fr(e),o=()=>r()!=="web",a=f=>{const g=d.get(f);return!!(g!=null&&g.platforms.has(r())||s(f))},s=f=>{var g;return(g=n.PluginHeaders)===null||g===void 0?void 0:g.find(w=>w.name===f)},l=f=>e.console.error(f),d=new Map,u=(f,g={})=>{const w=d.get(f);if(w)return console.warn(`Capacitor plugin "${f}" already registered. Cannot register plugins twice.`),w.proxy;const y=r(),k=s(f);let v;const $=async()=>(!v&&y in g?v=typeof g[y]=="function"?v=await g[y]():v=g[y]:t!==null&&!v&&"web"in g&&(v=typeof g.web=="function"?v=await g.web():v=g.web),v),C=(R,U)=>{var K,Y;if(k){const J=k==null?void 0:k.methods.find(Z=>U===Z.name);if(J)return J.rtype==="promise"?Z=>n.nativePromise(f,U.toString(),Z):(Z,Te)=>n.nativeCallback(f,U.toString(),Z,Te);if(R)return(K=R[U])===null||K===void 0?void 0:K.bind(R)}else{if(R)return(Y=R[U])===null||Y===void 0?void 0:Y.bind(R);throw new vt(`"${f}" plugin is not implemented on ${y}`,De.Unimplemented)}},D=R=>{let U;const K=(...Y)=>{const J=$().then(Z=>{const Te=C(Z,R);if(Te){const pe=Te(...Y);return U=pe==null?void 0:pe.remove,pe}else throw new vt(`"${f}.${R}()" is not implemented on ${y}`,De.Unimplemented)});return R==="addListener"&&(J.remove=async()=>U()),J};return K.toString=()=>`${R.toString()}() { [capacitor code] }`,Object.defineProperty(K,"name",{value:R,writable:!1,configurable:!1}),K},re=D("addListener"),N=D("removeListener"),x=(R,U)=>{const K=re({eventName:R},U),Y=async()=>{const Z=await K;N({eventName:R,callbackId:Z},U)},J=new Promise(Z=>K.then(()=>Z({remove:Y})));return J.remove=async()=>{console.warn("Using addListener() without 'await' is deprecated."),await Y()},J},z=new Proxy({},{get(R,U){switch(U){case"$$typeof":return;case"toJSON":return()=>({});case"addListener":return k?x:re;case"removeListener":return N;default:return D(U)}}});return i[f]=z,d.set(f,{name:f,proxy:z,platforms:new Set([...Object.keys(g),...k?[y]:[]])}),z};return n.convertFileSrc||(n.convertFileSrc=f=>f),n.getPlatform=r,n.handleError=l,n.isNativePlatform=o,n.isPluginAvailable=a,n.registerPlugin=u,n.Exception=vt,n.DEBUG=!!n.DEBUG,n.isLoggingEnabled=!!n.isLoggingEnabled,n},qr=e=>e.Capacitor=Hr(e),xe=qr(typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{}),Ae=xe.registerPlugin;class Jn{constructor(){this.listeners={},this.retainedEventArguments={},this.windowListeners={}}addListener(t,n){let i=!1;this.listeners[t]||(this.listeners[t]=[],i=!0),this.listeners[t].push(n);const o=this.windowListeners[t];o&&!o.registered&&this.addWindowListener(o),i&&this.sendRetainedArgumentsForEvent(t);const a=async()=>this.removeListener(t,n);return Promise.resolve({remove:a})}async removeAllListeners(){this.listeners={};for(const t in this.windowListeners)this.removeWindowListener(this.windowListeners[t]);this.windowListeners={}}notifyListeners(t,n,i){const r=this.listeners[t];if(!r){if(i){let o=this.retainedEventArguments[t];o||(o=[]),o.push(n),this.retainedEventArguments[t]=o}return}r.forEach(o=>o(n))}hasListeners(t){var n;return!!(!((n=this.listeners[t])===null||n===void 0)&&n.length)}registerWindowListener(t,n){this.windowListeners[n]={registered:!1,windowEventName:t,pluginEventName:n,handler:i=>{this.notifyListeners(n,i)}}}unimplemented(t="not implemented"){return new xe.Exception(t,De.Unimplemented)}unavailable(t="not available"){return new xe.Exception(t,De.Unavailable)}async removeListener(t,n){const i=this.listeners[t];if(!i)return;const r=i.indexOf(n);this.listeners[t].splice(r,1),this.listeners[t].length||this.removeWindowListener(this.windowListeners[t])}addWindowListener(t){window.addEventListener(t.windowEventName,t.handler),t.registered=!0}removeWindowListener(t){t&&(window.removeEventListener(t.windowEventName,t.handler),t.registered=!1)}sendRetainedArgumentsForEvent(t){const n=this.retainedEventArguments[t];n&&(delete this.retainedEventArguments[t],n.forEach(i=>{this.notifyListeners(t,i)}))}}const en=e=>encodeURIComponent(e).replace(/%(2[346B]|5E|60|7C)/g,decodeURIComponent).replace(/[()]/g,escape),tn=e=>e.replace(/(%[\dA-F]{2})+/gi,decodeURIComponent);class Wr extends Jn{async getCookies(){const t=document.cookie,n={};return t.split(";").forEach(i=>{if(i.length<=0)return;let[r,o]=i.replace(/=/,"CAP_COOKIE").split("CAP_COOKIE");r=tn(r).trim(),o=tn(o).trim(),n[r]=o}),n}async setCookie(t){try{const n=en(t.key),i=en(t.value),r=t.expires?`; expires=${t.expires.replace("expires=","")}`:"",o=(t.path||"/").replace("path=",""),a=t.url!=null&&t.url.length>0?`domain=${t.url}`:"";document.cookie=`${n}=${i||""}${r}; path=${o}; ${a};`}catch(n){return Promise.reject(n)}}async deleteCookie(t){try{document.cookie=`${t.key}=; Max-Age=0`}catch(n){return Promise.reject(n)}}async clearCookies(){try{const t=document.cookie.split(";")||[];for(const n of t)document.cookie=n.replace(/^ +/,"").replace(/=.*/,`=;expires=${new Date().toUTCString()};path=/`)}catch(t){return Promise.reject(t)}}async clearAllCookies(){try{await this.clearCookies()}catch(t){return Promise.reject(t)}}}Ae("CapacitorCookies",{web:()=>new Wr});const Gr=async e=>new Promise((t,n)=>{const i=new FileReader;i.onload=()=>{const r=i.result;t(r.indexOf(",")>=0?r.split(",")[1]:r)},i.onerror=r=>n(r),i.readAsDataURL(e)}),Vr=(e={})=>{const t=Object.keys(e);return Object.keys(e).map(r=>r.toLocaleLowerCase()).reduce((r,o,a)=>(r[o]=e[t[a]],r),{})},zr=(e,t=!0)=>e?Object.entries(e).reduce((i,r)=>{const[o,a]=r;let s,l;return Array.isArray(a)?(l="",a.forEach(d=>{s=t?encodeURIComponent(d):d,l+=`${o}=${s}&`}),l.slice(0,-1)):(s=t?encodeURIComponent(a):a,l=`${o}=${s}`),`${i}&${l}`},"").substr(1):null,Kr=(e,t={})=>{const n=Object.assign({method:e.method||"GET",headers:e.headers},t),r=Vr(e.headers)["content-type"]||"";if(typeof e.data=="string")n.body=e.data;else if(r.includes("application/x-www-form-urlencoded")){const o=new URLSearchParams;for(const[a,s]of Object.entries(e.data||{}))o.set(a,s);n.body=o.toString()}else if(r.includes("multipart/form-data")||e.data instanceof FormData){const o=new FormData;if(e.data instanceof FormData)e.data.forEach((s,l)=>{o.append(l,s)});else for(const s of Object.keys(e.data))o.append(s,e.data[s]);n.body=o;const a=new Headers(n.headers);a.delete("content-type"),n.headers=a}else(r.includes("application/json")||typeof e.data=="object")&&(n.body=JSON.stringify(e.data));return n};class Yr extends Jn{async request(t){const n=Kr(t,t.webFetchExtra),i=zr(t.params,t.shouldEncodeUrlParams),r=i?`${t.url}?${i}`:t.url,o=await fetch(r,n),a=o.headers.get("content-type")||"";let{responseType:s="text"}=o.ok?t:{};a.includes("application/json")&&(s="json");let l,d;switch(s){case"arraybuffer":case"blob":d=await o.blob(),l=await Gr(d);break;case"json":l=await o.json();break;case"document":case"text":default:l=await o.text()}const u={};return o.headers.forEach((f,g)=>{u[g]=f}),{data:l,headers:u,status:o.status,url:o.url}}async get(t){return this.request(Object.assign(Object.assign({},t),{method:"GET"}))}async post(t){return this.request(Object.assign(Object.assign({},t),{method:"POST"}))}async put(t){return this.request(Object.assign(Object.assign({},t),{method:"PUT"}))}async patch(t){return this.request(Object.assign(Object.assign({},t),{method:"PATCH"}))}async delete(t){return this.request(Object.assign(Object.assign({},t),{method:"DELETE"}))}}Ae("CapacitorHttp",{web:()=>new Yr});const Jr="modulepreload",Zr=function(e,t){return new URL(e,t).href},nn={},Nt=function(t,n,i){let r=Promise.resolve();if(n&&n.length>0){let a=function(u){return Promise.all(u.map(f=>Promise.resolve(f).then(g=>({status:"fulfilled",value:g}),g=>({status:"rejected",reason:g}))))};const s=document.getElementsByTagName("link"),l=document.querySelector("meta[property=csp-nonce]"),d=(l==null?void 0:l.nonce)||(l==null?void 0:l.getAttribute("nonce"));r=a(n.map(u=>{if(u=Zr(u,i),u in nn)return;nn[u]=!0;const f=u.endsWith(".css"),g=f?'[rel="stylesheet"]':"";if(!!i)for(let k=s.length-1;k>=0;k--){const v=s[k];if(v.href===u&&(!f||v.rel==="stylesheet"))return}else if(document.querySelector(`link[href="${u}"]${g}`))return;const y=document.createElement("link");if(y.rel=f?"stylesheet":Jr,f||(y.as="script"),y.crossOrigin="",y.href=u,d&&y.setAttribute("nonce",d),document.head.appendChild(y),f)return new Promise((k,v)=>{y.addEventListener("load",k),y.addEventListener("error",()=>v(new Error(`Unable to preload CSS for ${u}`)))})}))}function o(a){const s=new Event("vite:preloadError",{cancelable:!0});if(s.payload=a,window.dispatchEvent(s),!s.defaultPrevented)throw a}return r.then(a=>{for(const s of a||[])s.status==="rejected"&&o(s.reason);return t().catch(o)})},fe=Ae("SpeechRecognition",{web:()=>Nt(()=>import("./web-DyS4cL83.js"),__vite__mapDeps([0,1]),import.meta.url).then(e=>new e.SpeechRecognitionWeb)});function Je(){return xe.isNativePlatform()}function Qr({onFinal:e,onPartial:t,onStart:n,onEnd:i,onError:r,lang:o="en-GB"}){let a=!1,s=null,l=null,d=null,u=!1,f="",g=0,w="",y=null,k=null,v=o,$=!1,C=!1,D=!1,re=0,N="";function x(I){const b=String(I||"").trim();if(!b)return!0;try{if(b===window.location.href||b===window.location.origin||b===window.location.host||b===`${window.location.protocol}//${window.location.host}`)return!0}catch{}return!!(/^https?:\/\//i.test(b)||/\blocalhost(:\d+)?\b/i.test(b)||/\b127\.0\.0\.1\b/.test(b)||/mic (issue|blocked|busy)|speech needs internet|no microphone|asking for microphone/i.test(b)||!/[a-zA-Z]{2,}/.test(b))}function z(I){const b=String(I||"").trim();if(!b||x(b)||D||C)return;const S=Date.now();b.toLowerCase()===w.toLowerCase()&&S-g<1200||(w=b,g=S,f="",clearTimeout(y),e==null||e(b))}function R(I){const b=String(I||"").trim();if(!b||x(b))return;f=b,t==null||t(b),clearTimeout(y);const S=b.split(/\s+/).filter(Boolean).length,_=S<=3?1100:S<=8?1500:1900;y=setTimeout(()=>{f===b&&!D&&!C&&z(b)},_)}function U(I){var S;let b="";for(let _=0;_<I.length;_+=1){const E=(((S=I[_])==null?void 0:S.transcript)||"").trim();if(E&&(b||(b=E),/\b(don|dawn|done|dom|dun|donn|donald)\b/i.test(E))){b=E;break}}return b}async function K(){var S,_;if(!window.isSecureContext)throw new Error("Mic blocked on insecure URL — open http://localhost:5173 in Chrome");if(!((S=navigator.mediaDevices)!=null&&S.getUserMedia))throw new Error("This window can’t use the mic — open the app in Chrome or Edge");let I;try{I=await navigator.mediaDevices.getUserMedia({audio:{echoCancellation:!0,noiseSuppression:!0,autoGainControl:!0}})}catch(E){const te=(E==null?void 0:E.name)||"";throw te==="NotFoundError"||te==="DevicesNotFoundError"?new Error("No microphone detected — plug one in (System Settings → Sound → Input)"):te==="NotAllowedError"||te==="PermissionDeniedError"?new Error("Microphone permission denied — click the lock icon → Microphone → Allow"):te==="NotReadableError"||te==="TrackStartError"?new Error("Microphone is busy — quit Zoom/Teams/FaceTime/OBS, then tap the mic again"):new Error((E==null?void 0:E.message)||"Could not open microphone")}const b=I.getAudioTracks()[0];if(N=(b==null?void 0:b.label)||"Microphone",b&&b.readyState!=="live")throw I.getTracks().forEach(E=>E.stop()),new Error("Microphone track inactive — check Mac Sound input device");I.getTracks().forEach(E=>E.stop()),await new Promise(E=>setTimeout(E,180));try{if(!(await navigator.mediaDevices.enumerateDevices()).filter(Mr=>Mr.kind==="audioinput").length)throw new Error("No audio input devices listed — check System Settings → Sound → Input")}catch(E){if((_=E==null?void 0:E.message)!=null&&_.startsWith("No audio"))throw E}return N}function Y(){if(!(!u||!s||$||C)){$=!0;try{s.lang=v,s.start()}catch(I){const b=String((I==null?void 0:I.message)||I||"");/already started|InvalidStateError/i.test(b)||r==null||r(b||"Could not start mic")}finally{setTimeout(()=>{$=!1},300)}}}function J(I=300){!u||C||(clearTimeout(k),k=setTimeout(()=>{!u||C||Y()},I))}function Z(){if(s)return s;const I=window.SpeechRecognition||window.webkitSpeechRecognition;if(!I)throw new Error("Speech not supported here — use Chrome or Edge (not Safari), or type to careTalk");return s=new I,s.continuous=!0,s.interimResults=!0,s.maxAlternatives=5,s.lang=v,s.onstart=()=>{a=!0,$=!1,re=0,n==null||n()},s.onend=()=>{a=!1,i==null||i(),!C&&(clearTimeout(y),f="",J(320))},s.onerror=b=>{const S=b.error;if(S!=="aborted"&&S!=="no-speech"){if(S==="audio-capture"){if(re+=1,re<=2&&u){r==null||r("Mic busy — retrying… close other apps using the mic"),clearTimeout(k),k=setTimeout(async()=>{if(u)try{await K(),Y()}catch(_){u=!1,r==null||r((_==null?void 0:_.message)||"no microphone available")}},600);return}u=!1,r==null||r(N?`Can’t capture “${N}” — quit Zoom/Teams/FaceTime, allow mic for this site, tap again`:"Can’t open microphone — allow mic in the address bar, quit apps using the mic, use Chrome on localhost");return}if(S==="not-allowed"||S==="service-not-allowed"){u=!1,r==null||r("Mic blocked — lock icon in address bar → Microphone → Allow, then tap mic");return}if(S==="network"){r==null||r("Speech needs internet (Chrome voice service)"),J(1200);return}if(S==="language-not-supported"&&v!=="en-US"){v="en-US",s.lang=v,J(300);return}r==null||r(S),J(500)}},s.onresult=b=>{let S="";for(let _=b.resultIndex;_<b.results.length;_+=1){const E=b.results[_],te=U(E);!te||x(te)||(E.isFinal?!D&&!C&&z(te):S+=`${te} `)}S.trim()&&!D&&(t==null||t(S.trim()),f=S.trim(),R(S.trim()))},s}async function Te(){const I=await fe.available();if(!(I!=null&&I.available))throw new Error("Speech recognition unavailable on this device");if((await fe.checkPermissions()).speechRecognition!=="granted"&&(await fe.requestPermissions()).speechRecognition!=="granted")throw new Error("Microphone / speech permission denied")}async function pe(){await Te(),f="",l=await fe.addListener("partialResults",I=>{const b=((I==null?void 0:I.matches)||[]).filter(Boolean).join(" ").trim();b&&R(b)}),d=await fe.addListener("listeningState",I=>{I.status==="started"&&(a=!0,n==null||n()),I.status==="stopped"&&(a=!1,i==null||i(),u&&!C&&(clearTimeout(k),k=setTimeout(()=>{u&&pe().catch(b=>r==null?void 0:r((b==null?void 0:b.message)||"mic restart failed"))},400)))}),await fe.start({language:v,maxResults:5,partialResults:!0,popup:!1}),a=!0,n==null||n()}async function jr(){clearTimeout(y),clearTimeout(k);try{await fe.stop()}catch{}f&&!x(f)&&z(f);try{await(l==null?void 0:l.remove()),await(d==null?void 0:d.remove())}catch{}l=null,d=null,a=!1,i==null||i()}return{get listening(){return a},get micLabel(){return N},setInputBlocked(I){D=!!I,D&&(clearTimeout(y),f="")},async start(){if(u=!0,C=!1,f="",re=0,Je()){await pe();return}await K(),Z(),Y()},async pause(){if(C=!0,D=!0,clearTimeout(k),clearTimeout(y),Je()){try{await fe.stop()}catch{}a=!1,i==null||i();return}try{s==null||s.stop()}catch{}a=!1,i==null||i()},async resume(){if(C=!1,D=!1,u=!0,Je()){await pe();return}Y()},async stop(){if(u=!1,C=!1,clearTimeout(k),clearTimeout(y),$=!1,Je()){await jr();return}const I=f;f="";try{s==null||s.stop()}catch{}I&&!x(I)&&z(I),a=!1,i==null||i()}}}var It;(function(e){e.Dark="DARK",e.Light="LIGHT",e.Default="DEFAULT"})(It||(It={}));var rn;(function(e){e.None="NONE",e.Slide="SLIDE",e.Fade="FADE"})(rn||(rn={}));const on=Ae("StatusBar"),Xr=Ae("SplashScreen",{web:()=>Nt(()=>import("./web-CXyz-Izy.js"),__vite__mapDeps([2,1]),import.meta.url).then(e=>new e.SplashScreenWeb)});var an;(function(e){e.Dark="DARK",e.Light="LIGHT",e.Default="DEFAULT"})(an||(an={}));var At;(function(e){e.Body="body",e.Ionic="ionic",e.Native="native",e.None="none"})(At||(At={}));const ei=Ae("Keyboard"),sn=Ae("App",{web:()=>Nt(()=>import("./web-CgUdoTZR.js"),__vite__mapDeps([3,1]),import.meta.url).then(e=>new e.AppWeb)});async function ti(){if(xe.isNativePlatform()){document.documentElement.classList.add("native"),document.documentElement.dataset.platform=xe.getPlatform();try{await on.setStyle({style:It.Dark}),await on.setBackgroundColor({color:"#061114"})}catch{}try{await ei.setResizeMode({mode:At.Body})}catch{}try{await Xr.hide()}catch{}sn.addListener("backButton",({canGoBack:e})=>{e?window.history.back():sn.exitApp()})}}const P={pinHash:"don.train.pinHash",pinSet:"don.train.pinSet",sessionAuth:"don.train.authed",knowledge:"don.train.knowledge",agency:"don.agency",outbox:"don.agency.outbox",incidents:"don.train.incidents",customTopics:"don.train.customTopics"},Ut="2473";function Qe(e){const t=`don|${String(e||"").trim()}`;let n=2166136261;for(let i=0;i<t.length;i+=1)n^=t.charCodeAt(i),n=Math.imul(n,16777619);return(n>>>0).toString(16)}function Ve(e,t){try{const n=localStorage.getItem(e);return n?JSON.parse(n):t}catch{return t}}function ze(e,t){localStorage.setItem(e,JSON.stringify(t))}function ni(){return localStorage.getItem(P.pinSet)==="1"}function _t(){ni()||(localStorage.setItem(P.pinHash,Qe(Ut)),localStorage.setItem(P.pinSet,"1"))}function ri(e){_t();const t=localStorage.getItem(P.pinHash)||Qe(Ut);return Qe(e)===t}function ii(e){const t=String(e||"").trim();if(t.length<4)throw new Error("PIN must be at least 4 digits");localStorage.setItem(P.pinHash,Qe(t)),localStorage.setItem(P.pinSet,"1")}function be(e){e?sessionStorage.setItem(P.sessionAuth,"1"):sessionStorage.removeItem(P.sessionAuth)}function Zn(){return sessionStorage.getItem(P.sessionAuth)==="1"}function de(){return Ve(P.knowledge,[])}function Qn(e){ze(P.knowledge,e)}function Xn(e){const t=de(),n=r=>Array.isArray(r)?r.map(o=>String(o).trim()).filter(Boolean):String(r||"").split(`
3
  `).map(o=>o.trim()).filter(Boolean),i={id:`k_${Date.now()}`,title:String(e.title||"").trim(),body:String(e.body||"").trim(),doList:n(e.doList),dontList:n(e.dontList),keywords:String(e.keywords||"").split(",").map(r=>r.trim().toLowerCase()).filter(Boolean),sourceUrl:String(e.sourceUrl||"").trim(),images:Array.isArray(e.images)?e.images.map(r=>String(r).trim()).filter(Boolean):String(e.images||"").split(`
4
  `).map(r=>r.trim()).filter(Boolean),addedBy:e.addedBy||"Head nurse",addedAt:new Date().toISOString()};if(!i.title||!i.body)throw new Error("Title and guidance text are required");return t.unshift(i),Qn(t),i}function oi(e){Qn(de().filter(t=>t.id!==e))}function it(){return Ve(P.agency,{name:"Care agency",email:"",webhookUrl:"",autoForward:!0})}function ai(e){ze(P.agency,{name:String(e.name||"Care agency").trim()||"Care agency",email:String(e.email||"").trim(),webhookUrl:String(e.webhookUrl||"").trim(),autoForward:e.autoForward!==!1})}function er(){return Ve(P.outbox,[])}function tr(e){const t=er();t.unshift(e),ze(P.outbox,t.slice(0,50))}function nr(){return Ve(P.incidents,[])}function si(e){ze(P.incidents,Array.isArray(e)?e:[])}function he(){return Ve(P.customTopics,[])}function jt(e){ze(P.customTopics,Array.isArray(e)?e:[])}function rr({title:e,keywords:t="",notes:n=""}){const i=String(e||"").trim();if(!i)throw new Error("Topic title is required");const r=he(),o={id:`topic_${Date.now()}`,title:i,keywords:String(t||"").split(",").map(a=>a.trim().toLowerCase()).filter(Boolean),notes:String(n||"").trim(),addedAt:new Date().toISOString(),lastTrainedAt:null};return r.unshift(o),jt(r),o}function li(e){jt(he().filter(t=>t.id!==e))}function ci(e){const t=he(),n=t.findIndex(i=>i.id===e);n<0||(t[n].lastTrainedAt=new Date().toISOString(),jt(t))}const Lt={fall:[{id:"fall-assess",title:"Assess first",caption:"Stay with them, check responsiveness and injury before any move.",src:"/guides/fall-assess.svg",alt:"Carer kneeling beside a person on the floor after a fall, asking if they are hurt"},{id:"fall-no-lift",title:"Don’t haul them up",caption:"If injury may be present, keep them comfortable and get clinical advice.",src:"/guides/fall-no-lift.svg",alt:"Warning not to lift a fallen person without assessment"}],dysphagia:[{id:"dysphagia-upright",title:"Sit upright",caption:"Upright posture for eating and drinking; follow texture plan.",src:"/guides/dysphagia-upright.svg",alt:"Person sitting upright in a chair for safe eating and drinking"},{id:"dysphagia-stop",title:"Stop if choking signs",caption:"Coughing, wet voice or colour change — stop intake and call for help.",src:"/guides/dysphagia-stop.svg",alt:"Stop cup or food when choking warning signs appear"}],distress:[{id:"distress-space",title:"Give space",caption:"Reduce stimulation, keep a calm distance, use care-plan strategies.",src:"/guides/distress-space.svg",alt:"Carer giving a person space during distress"}],skin:[{id:"skin-check",title:"Note site & look",caption:"Record exact site, appearance and pain; escalate for grading/dressings.",src:"/guides/skin-check.svg",alt:"Diagram highlighting checking pressure areas on the body"}]};function di(e,t=[]){const n=Lt[e]||[],i=[];for(const o of t)(Array.isArray(o.images)?o.images:[]).forEach((s,l)=>{const d=String(s||"").trim();d&&i.push({id:`trained_${o.id||l}_${l}`,title:o.title||"Home training image",caption:"From your home’s trained knowledge",src:d,alt:`${o.title||"Training"} illustration ${l+1}`})});const r=new Set;return[...n,...i].filter(o=>r.has(o.src)?!1:(r.add(o.src),!0))}function ui(e,t){return e!=null&&e.length?`
5
  <div class="guide-strip">
@@ -15,7 +15,7 @@ import"./modulepreload-polyfill-B5Qt9EMX.js";/*! Capacitor: https://capacitorjs.
15
  </figcaption>
16
  </figure>`).join("")}</div>
17
  </div>
18
- `:""}const ir={version:"1.1.7",disclaimer:"careTalk supports record-keeping and safe practice reminders. Follow your home’s policy, escalate to the nurse in charge, and call 999 in an emergency."},Mt=[{id:"pmva_mapa",title:"PMVA / MAPA (BILD-accredited)",notes:"Physical intervention and de-escalation for mental health settings is a specialised, assessed course (typically multi-day, BILD-accredited). Prefer prevention, communication, and least-restrictive options. Only use techniques you are currently trained and authorised to use."},{id:"oliver_mcgowan",title:"Oliver McGowan Mandatory Training (Tier 2 + online)",notes:"Learning disability and autism awareness: assume competence, adapt communication, reduce sensory load, involve familiar supporters, avoid diagnostic overshadowing, and escalate concerns about distress or unmet need."},{id:"ligature",title:"Ligature awareness",notes:"Remove or reduce ligature risks where safe and authorised; do not leave someone in danger to ‘finish paperwork’. Observe, report environmental risks, stay with the person if unsafe to leave, and escalate immediately per policy."},{id:"dysphagia",title:"Dysphagia awareness",notes:"Follow IDDSI / care-plan texture and fluid guidance. Never rush feeding, never mix consistencies against the plan, sit upright, watch for coughing/wet voice/colour change, and stop and escalate if aspiration is suspected."},{id:"seniors",title:"Caring for older adults",notes:"Person-centred, dignity-first care: explain what you are doing, offer choice, watch for delirium, falls, skin, hydration, and loneliness. Document facts, not judgements."},{id:"moving_assisting",title:"Moving and assisting people",notes:"Use agreed handling plans, equipment you are trained on, and enough staff. Do not lift manually against policy. After a fall, do not haul someone up if injury is possible — assess, reassure, follow fallen-person procedure."},{id:"hswa",title:"Health and Safety at Work etc. Act",notes:"Take reasonable care of yourself and others, follow training, report hazards, and do not carry out tasks you are not competent or authorised to do."}];function pi(e,t){const n=`${e} ${t||""}`.toLowerCase(),i=de().filter(r=>{var o;return(o=r.keywords)!=null&&o.length?r.keywords.some(a=>n.includes(a)||e.includes(a)):e==="general"||e==="medication"});if(e==="medication"){const r=i.filter(o=>/\b(medicine|medication|meds|refus|tablet|mar)\b/i.test(`${o.title} ${o.body} ${(o.keywords||[]).join(" ")}`));return r.length?r:i}return i}function fi(e,t=""){var u,f;const n=["Stay calm and reassure the person.","Check for immediate danger to them and you.","Follow your service’s escalation pathway (nurse in charge / on-call / 999).","Document facts: what you saw, what you did, time, who was informed."],i=["Don’t leave an unsafe situation to ‘write the note first’.","Don’t use restrictive holds unless you are currently trained, authorised, and it is a last resort under policy.","Don’t blame the person in the record — stick to observable facts."],r={fall:{pillars:["moving_assisting","seniors","hswa"],do:[...n,"If injury may be present, do not pull them up — keep them comfortable, check responsiveness, and get clinical advice.","Look for head injury signs, pain, limb deformity, bleeding, and sudden confusion.","After safe recovery, review footwear, mobility aid, lighting, and observation level."],dont:[...i,"Don’t use a fireman’s lift or unplanned manual lift.","Don’t dismiss an unwitnessed fall — treat it seriously until assessed.","Don’t delay informing the nurse in charge / family when policy requires it."]},skin:{pillars:["seniors","hswa"],do:[...n,"Note exact site, size/appearance if trained to, pain, and whether skin is broken.","Reposition as care plan allows; keep pressure off the area.","Inform nurse in charge for grading / dressing decisions if required."],dont:[...i,"Don’t apply creams or dressings outside your role/competence.","Don’t ignore unbroken redness over a bony area."]},dysphagia:{pillars:["dysphagia","oliver_mcgowan","seniors"],do:[...n,"Stop oral intake if coughing, choking, wet voice, or colour change.","Keep upright; follow prescribed texture/fluid level only.","Call for help early — choking is time-critical."],dont:[...i,"Don’t give food/drink against the dysphagia plan.","Don’t leave someone alone while eating if supervision is required.","Don’t do blind finger sweeps if choking."]},distress:{pillars:["pmva_mapa","oliver_mcgowan","ligature","hswa"],do:[...n,"Reduce stimulation, give space, use calm simple language, and offer known soothing strategies from the care plan.","Scan for environmental risk (ligature points, weapons, exits) without escalating conflict.","Call for trained support early; protect yourself and others."],dont:[...i,"Don’t crowd, shout, or threaten.","Don’t use physical intervention unless trained, authorised, proportionate, and necessary as a last resort.","Don’t ignore ligature risk to ‘talk it out’ from a distance if the person is in immediate danger — get help now."]},wellbeing:{pillars:["seniors","oliver_mcgowan"],do:[...n,"Ask about pain, mood, appetite, and what matters to them today.","Note changes from their usual baseline."],dont:[...i,"Don’t skip hydration/nutrition checks when someone seems ‘fine’ but quieter than usual."]},medication:{pillars:["hswa","seniors"],do:["Stay calm and do not force medicine.","Follow your home’s medication / MAR policy and the person’s care plan.","Inform the nurse in charge / on-call promptly.","Document facts: what was offered, what was refused, time, and who was informed."],dont:["Don’t hide medicine in food/drink unless the care plan and policy explicitly allow covert administration by authorised staff.","Don’t force, threaten, or restrain someone to take medicine.","Don’t leave a refused critical dose unreported."]},general:{pillars:["hswa","seniors"],do:n,dont:i}},o={...r[e]||r.general},a=pi(e,t);for(const g of a)(u=g.doList)!=null&&u.length&&(o.do=[...o.do,...g.doList]),(f=g.dontList)!=null&&f.length&&(o.dont=[...o.dont,...g.dontList]);const s=Mt.filter(g=>o.pillars.includes(g.id)).map(g=>`${g.title}: ${g.notes}`),l=a.map(g=>`${g.title}: ${g.body}`),d=di(e,a);return{...o,pillarText:s,trainedText:l,custom:a,images:d}}async function gi(e,t={}){const n=it(),i={id:`fwd_${Date.now()}`,at:new Date().toISOString(),agencyName:n.name,agencyEmail:n.email,carer:t.carer||"",person:t.person||"",scenario:t.scenario||"",report:e,status:"queued",channels:[]};if(i.channels.push("outbox"),n.webhookUrl)try{const r=await fetch(n.webhookUrl,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({type:"don.support_worker_report",...i})});if(!r.ok)throw new Error(`HTTP ${r.status}`);i.channels.push("webhook")}catch(r){i.webhookError=(r==null?void 0:r.message)||"webhook failed"}if(n.email){const r=encodeURIComponent(`careTalk support worker report — ${t.person||"resident"} — ${t.scenario||"care"}`),o=encodeURIComponent(e.slice(0,1800)),a=`mailto:${encodeURIComponent(n.email)}?subject=${r}&body=${o}`;i.mailto=a,i.channels.push("email");try{const s=document.createElement("a");s.href=a,s.rel="noopener",document.body.appendChild(s),s.click(),s.remove()}catch{}}return i.status=i.channels.includes("webhook")||i.channels.includes("email")?"sent":"saved_local",tr(i),{packet:i,agency:n}}function ln(e){return String(e||"").trim().toLowerCase().replace(/[^a-z'-]/g,"")}function mi(e,t){const n=ln(e),i=ln(t);if(!n||!i)return!1;if(n===i)return!0;const r=n.split(/\s+/)[0],o=i.split(/\s+/)[0];return r.length>1&&r===o}function ot(e){const t=String(e||"").trim();return t?t.split(/\s+/)[0]:""}function at(e,t){return mi(e,t)}function hi(e,t){const n=String(e||"").trim().toLowerCase().replace(/[^\w\s'-]/g,""),i=String(t||"").trim().toLowerCase().replace(/[^\w\s'-]/g,"");return!n||!i?!1:!!(n===i||n.length>8&&i.includes(n)||i.length>12&&n.includes(i.slice(0,Math.min(24,i.length))))}function yi(e,t){return t!=="waiting_answer"?!1:/^(yes|yeah|yep|yup|no|nope|nah|ok|okay|correct|right|wrong)$/i.test(String(e||"").trim())}const ke=[{id:"fall",label:"Fall",match:/\b(fall|fell|fallen|slipped|trip(?:ped)?)\b/i,questions:[{id:"when",ask:"When did it happen — just now, or roughly what time?"},{id:"where",ask:"Where did it happen? Bedroom, bathroom, corridor…?"},{id:"witnessed",ask:"Did anyone see it, or was it unwitnessed?"},{id:"how",ask:"What were they doing right before — standing up, walking, reaching…?"},{id:"injury",ask:"Any pain, bleeding, bumps, or odd limb position — or none that you can see?"},{id:"response",ask:"What have you done so far?"},{id:"obs",ask:"How are they now — alert, dizzy, confused, calm?"},{id:"informed",ask:"Who have you told, and who still needs telling — nurse in charge, GP, family, 999?"},{id:"prevent",ask:"Anything you want in place now for safety — mat, closer checks, footwear…?"}]},{id:"dysphagia",label:"Eating / choking / swallow",match:/\b(chok(?:e|ing)?|swallow|dysphagia|coughing (?:on|while) (?:eat|drink)|aspirat)/i,questions:[{id:"what",ask:"What happened with eating or drinking?"},{id:"texture",ask:"Were they on a special texture or fluid level?"},{id:"signs",ask:"Any coughing, colour change, wet voice, or distress?"},{id:"stopped",ask:"Did you stop food and drink?"},{id:"now",ask:"How are they now?"},{id:"informed",ask:"Who have you informed?"}]},{id:"distress",label:"Distress / behaviour support",match:/\b(distress|agitated|aggression|hitting|ligature|self[- ]harm|restrain|mapa|pmva|difficult|challenging|behaviour|behavior)\b/i,questions:[{id:"what",ask:"What’s happening for them right now, in plain words?"},{id:"trigger",ask:"Anything that seemed to trigger it?"},{id:"risk",ask:"Is anyone in immediate danger — including ligature or weapons risk?"},{id:"done",ask:"What have you tried — space, calm talk, care-plan strategies?"},{id:"help",ask:"Who is supporting you on the floor right now?"},{id:"now",ask:"How is the person now?"}]},{id:"medication",label:"Medication / refusal",match:/\b((refuse[ds]?|refusing|won'?t take|will not take|not taking|declined?).{0,40}\b(medicine|medication|meds|tablet|tablets|pill|pills|dose)\b|\b(medicine|medication|meds|tablet|tablets|pill|pills).{0,40}\b(refuse[ds]?|refusing|won'?t|not taking|declined?)\b|\b(medication|medicine|meds|mar)\b)/i,questions:[{id:"what",ask:"Which medicine was refused or not taken — if you know the name or time slot?"},{id:"when",ask:"When was this — which round / roughly what time?"},{id:"how",ask:"What exactly happened — refused, spat out, asleep, not present…?"},{id:"reason",ask:"Did they say why, or seem unwell / distressed?"},{id:"done",ask:"What have you tried so far (offer again, nurse, wait)?"},{id:"now",ask:"How are they now?"},{id:"informed",ask:"Who have you told — nurse in charge / on-call?"},{id:"next",ask:"What needs to happen next according to the home’s policy?"}]},{id:"skin",label:"Skin / pressure concern",match:/\b(skin|pressure|sore|redness|bruise|wound|mark)\b/i,questions:[{id:"where",ask:"Where on the body is the mark or sore?"},{id:"looks",ask:"What does it look like?"},{id:"pain",ask:"Are they sore there?"},{id:"found",ask:"When did you notice it?"},{id:"done",ask:"What have you done so far?"},{id:"next",ask:"What do you think needs to happen next?"}]},{id:"wellbeing",label:"Wellbeing check",match:/\b(wellbeing|well-being|mood|check(?:ed)? on|how .+ (?:is|are))\b/i,questions:[{id:"mood",ask:"How is their mood and engagement?"},{id:"eat",ask:"Eating and drinking okay?"},{id:"mobility",ask:"Any mobility notes?"},{id:"care",ask:"Any personal care done or needed?"},{id:"concerns",ask:"Anything worrying you?"},{id:"plan",ask:"What should the next shift know?"}]},{id:"general",label:"Care situation",match:/./,questions:[{id:"what",ask:"In one line, what happened?"},{id:"when",ask:"When was this?"},{id:"where",ask:"Where?"},{id:"response",ask:"What did you do?"},{id:"now",ask:"How is the person now?"},{id:"informed",ask:"Who knows / who still needs to know?"},{id:"next",ask:"What needs to happen next?"}]}],wi=/^(?:(?:hi|hii|hey|hello|yo|ok|okay|hiya|oi|excuse me)\s+)+(?:care\s*talk|caretalk|don|dawn|done|dom|dun|donn)\b[, ]*/i,bi=/^(?:care\s*talk|caretalk|don|dawn|done|dom|dun|donn)\b[, ]*/i;function st(e){return String(e||"").toLowerCase().replace(/["""']/g,"").replace(/[^\w\s']/g," ").replace(/\bcare\s*talk\b/g,"caretalk").replace(/\b(dawn|done|dom|dun|donn|donnie|donald)\b/g,"don").replace(/\s+/g," ").trim()}function Oe(e){const t=st(e);return/^(?:(?:(?:hi|hii|hey|hello|yo|ok|okay|hiya|oi)\s+)?(?:caretalk|don)\s*)+$/.test(t)}function F(e){let t=String(e||"").trim();t=t.replace(wi,"").replace(bi,"").trim();const n=st(t);return n.startsWith("caretalk ")&&(t=t.replace(/^(?:care\s*talk|caretalk)\s+/i,"").trim()),n.startsWith("don ")&&(t=t.replace(/^(?:don|dawn|done)\s+/i,"").trim()),t}function Ft(e){const t=String(e||"");if(/\bcare\s*talk\b/i.test(t)||/\bcaretalk\b/i.test(t)||/\bdon\b/i.test(t)||/\b(?:hi|hey|hello|yo|ok|okay|hiya|oi|excuse me)\s+(?:dawn|done|dom|dun|donn|donnie|donald|dan|donn?e)\b/i.test(t)||/^(?:dawn|done|dom|dun|donn|donald)\b/i.test(t.trim())||/,\s*(?:dawn|done|dom|dun|donn|donald)\b/i.test(t))return!0;const n=st(t);return!!/^(?:(?:hi|hii|hey|hello|yo|ok|okay|hiya|oi)\s+)?(?:caretalk|don)(?:\s+(?:caretalk|don))*$/.test(n)}function St(e){const t=F(e).trim();return t?Be(t).id!=="general"||/\b(help|need|advice|record|document|fell|fall|hurt|pain|chok|bleed|resident|patient|check|incident|report)\b/i.test(t)?!0:t.split(/\s+/).filter(Boolean).length>=4:!1}function or(e){return!Ft(e)||Oe(e)?!1:!St(e)}const ki=new Set(["i","we","you","he","she","it","they","them","him","her","his","my","our","your","the","a","an","this","that","these","those","someone","somebody","anyone","anybody","everyone","everybody","resident","client","service","user","carer","nurse","staff","today","just","please","okay","ok","alright","don","caretalk","hey","hi","hello","yes","yeah","yep","yup","no","nope","nah","not","nothing","something","else","fall","distress","swallow","skin","mood","wellbeing","medication","meds","urgent","safe","unsafe","danger","right","got","still","here","there","when","where","what","why","how","who","which","because","about","with","for","from","after","before","during","maybe","kind","sort","really","actually","saying","said","tell","told","need","help","advice","report","record","document"].map(e=>e.toLowerCase()));function Fe(e){const t=String(e||"").trim();return!(!t||t.length<2||t.length>24||/\d/.test(t)||ki.has(t.toLowerCase())||!/^[A-Za-z][A-Za-z'-]*$/.test(t))}function Ke(e,{carerName:t=""}={}){const n=F(e);if(!n)return"";function i(s){return!s||!Fe(s)||t&&at(s,t)?"":s}const r=[/(?:with|for|about|attending(?: to)?|resident|service user|client|called)\s+([A-Z][a-z]+(?:\s+[A-Z][a-z]+)?)/,/\b([A-Z][a-z]+)\s+(?:just |has |had |fell|was |is |seems |refused |won'?t )/];for(const s of r){const l=n.match(s);if(l){const d=i(l[1].split(/\s+/)[0]);if(d)return d}}const o=n.match(/\b([a-z]{2,})\s+(?:just |has |had |fell|seems|refused|won'?t)/i);if(o){const s=i(Fe(o[1])?o[1].charAt(0).toUpperCase()+o[1].slice(1).toLowerCase():"");if(s)return s}const a=n.match(/^([A-Za-z][A-Za-z'-]{1,23})(?:\s+(?:please|thanks))?[.!?]?$/);if(a){const s=i(a[1].charAt(0).toUpperCase()+a[1].slice(1).toLowerCase());if(s)return s}return""}function Be(e){const t=F(e);for(const n of ke)if(n.id!=="general"&&n.match.test(t))return n;return ke.find(n=>n.id==="general")}function vi(e,t){return t&&/^Where did it happen/i.test(e)?`Where was ${t}? Bedroom, bathroom, corridor…?`:e}function $i({opening:e,carer:t,carerProfileName:n=""}){const i=e.trim(),r=Be(i);let a=Ke(i,{carerName:n||t});const s=F(i)||i,l=fi(r.id,s),d=r.questions.map(u=>({...u,ask:vi(u.ask,a)}));return{id:`sess_${Date.now()}`,opening:s,carer:t||"Staff",person:a,scenarioId:r.id,scenarioLabel:r.label,advice:l,questions:d,answers:{},voiceNotes:[{at:new Date().toISOString(),text:s}],step:0,phase:"advice",adviceAwaitingOk:!1,docTurn:"waiting_answer",pendingAnswer:"",pendingDocumented:"",correctionNote:"",recordedAt:new Date().toLocaleString("en-GB")}}function Ii(){const e=["I’m here. Do you need any help?","Hi — it’s careTalk. What do you need?","Listening. Are you okay — want help documenting something, or advice on what to do next?"];return e[Math.floor(Math.random()*e.length)]}function lt(e){return e.questions[e.step]||null}function Ai(e,t,{person:n=""}={}){const i=String(t||"").trim().replace(/\s+/g," ");if(!i)return"—";const r=String((e==null?void 0:e.ask)||"Note").replace(/\?$/,"").trim();return`${n?`Service user ${n}: `:""}${r} — ${i}`}function cn(e){const t=String(e||"").trim().toLowerCase();return!t||/\b(no|nope|not right|wrong|incorrect|change)\b/.test(t)&&!/^yes\b/.test(t)?!1:/^(yes|yeah|yep|yup|correct|right|spot on|that'?s right|that is right|good|fine|ok|okay|absolutely|affirmative)\b/.test(t)}function dn(e){const t=String(e||"").trim().toLowerCase();return/^(no|nope|nah|not quite|wrong|incorrect)\b/.test(t)||/\b(not right|that'?s wrong|change that|needs changing)\b/.test(t)}function un(e){let t=String(e||"").trim();return t=t.replace(/^(no(,)?\s*)(actually|i mean|it'?s|it is)?\s*/i,"").trim(),t||String(e||"").trim()}function Li(e){return String(e||"").trim().length<2}function Si(e,{raw:t,documented:n}){const i=lt(e);if(!i)return{session:e,done:!0};const r=String(n||t||"").trim();return e.answers[i.id]=r,e.voiceNotes||(e.voiceNotes=[]),e.voiceNotes.push({at:new Date().toISOString(),text:t?`${i.id} (voice): ${t}`:`${i.id}: ${r}`}),n&&t&&n!==t&&e.voiceNotes.push({at:new Date().toISOString(),text:`${i.id} (record): ${r}`}),e.step+=1,e.pendingAnswer="",e.pendingDocumented="",e.docTurn="waiting_answer",{session:e,done:e.step>=e.questions.length}}function Ti(e,t){if(!e)return;const n=String(t||"").trim();n&&(e.voiceNotes||(e.voiceNotes=[]),e.voiceNotes.push({at:new Date().toISOString(),text:n}))}function ar(e,t){const n=e.questions.map(r=>{const o=e.answers[r.id];return o?`<li><span class="muted-line">${t(r.ask)}</span><br /><strong>${t(o)}</strong></li>`:""}).filter(Boolean).join(""),i=e.correctionNote?`<li><span class="muted-line">Correction noted</span><br /><strong>${t(e.correctionNote)}</strong></li>`:"";return n||i?`<ul class="record-review">${n}${i}</ul>`:"<p>Nothing captured yet.</p>"}function Ci(e){return Ei(e)}function Ei(e){var r;const t=e.answers,n=e.person||"the resident",i=["SUPPORT WORKER REPORT — GENERATED BY careTalk","========================================",`Service user: ${e.person||"—"}`,`Support worker / carer: ${e.carer}`,`Incident / topic: ${e.scenarioLabel}`,`Date & time recorded: ${e.recordedAt}`,`Session id: ${e.id}`,"","1. OPENING STATEMENT (VOICE)",e.opening||"—","","2. WHAT HAPPENED (STRUCTURED)"];if(e.scenarioId==="fall")i.push(`${n} had a fall${t.when?` (${t.when})`:""}${t.where?` — location: ${t.where}`:""}.`,t.how?`Beforehand: ${t.how}.`:"",t.witnessed?`Witnessed / presence: ${t.witnessed}.`:"","","3. INJURY / PRESENTATION",t.injury||"—","","4. IMMEDIATE RESPONSE",t.response||"—","","5. CURRENT CONDITION",t.obs||"—","","6. NOTIFICATIONS",t.informed||"—","","7. SAFETY / FOLLOW-UP",t.prevent||"—");else for(const o of e.questions)i.push(`${o.ask}`,t[o.id]||"—","");return i.push("","8. VOICE NOTES (VERBATIM CAPTURE)",...(e.voiceNotes||[]).map((o,a)=>`${a+1}. [${new Date(o.at).toLocaleTimeString("en-GB")}] ${o.text}`),"","9. NARRATIVE SUMMARY FOR AGENCY"),e.scenarioId==="fall"?i.push([`${n} had a fall${t.when?` ${t.when}`:""}${t.where?` at ${t.where}`:""}.`,t.how?`Prior activity: ${t.how}.`:null,t.witnessed?`Presence: ${t.witnessed}.`:null,t.injury?`Injury/marks: ${t.injury}.`:null,t.response?`Actions: ${t.response}.`:null,t.obs?`Now: ${t.obs}.`:null,t.informed?`Informed: ${t.informed}.`:null,t.prevent?`Safety: ${t.prevent}.`:null].filter(Boolean).join(" ")):i.push(e.questions.map(o=>`${o.ask.replace(/\?$/,"")}: ${t[o.id]||"not stated"}`).join(". ")+"."),i.push("","10. SAFE PRACTICE REMINDERS APPLIED (careTalk)",`Do: ${(e.advice.do||[]).slice(0,4).join(" | ")}`,`Don’t: ${(e.advice.dont||[]).slice(0,4).join(" | ")}`),(r=e.advice.trainedText)!=null&&r.length&&i.push("","11. HOME-TRAINED KNOWLEDGE USED",...e.advice.trainedText),e.correctionNote&&i.push("","CORRECTION / AMENDMENT (VOICE)",e.correctionNote),i.push("",Ri),i.filter((o,a,s)=>!(o===""&&s[a-1]==="")).join(`
19
  `)}const Ri="Note: careTalk supports documentation and safe-practice reminders from adult care / support-worker training themes (including moving & assisting, dysphagia, ligature awareness, Oliver McGowan, PMVA/MAPA principles, HSWA). Follow local policy and clinical advice. This report is for the care agency / nurse in charge.",Ht=[{id:"medication_refusal",label:"Medication refusal",match:/\b((refuse[ds]?|refusing|won'?t take|will not take|not taking|declined?|spit(?:ting)? out).{0,40}\b(medicine|medication|meds|tablet|tablets|pill|pills|dose|mar)\b|\b(medicine|medication|meds|tablet|tablets|pill|pills).{0,40}\b(refuse[ds]?|refusing|won'?t|will not|not taking|declined?)\b)/i,keywords:["medicine","medication","meds","refuse","refusal","refused","tablet","tablets","pill","mar"]}];function Xe(e){const t=String(e||"");for(const n of Ht)if(n.match.test(t))return n;return null}function sr(e,t=""){if(!e)return[];`${t} ${e.label}`.toLowerCase();const n=de(),i=[];for(const r of n){let o=0;const a=`${r.title} ${r.body} ${(r.keywords||[]).join(" ")} ${(r.doList||[]).join(" ")}`.toLowerCase();for(const s of e.keywords)a.includes(s)&&(o+=2),(r.keywords||[]).includes(s)&&(o+=2);/\b(refus|not taking|declin|won'?t take)\b/i.test(a)&&(o+=3),/\b(medicine|medication|meds|tablet|mar)\b/i.test(a)&&(o+=2),(r.doList||[]).length>=1&&(o+=2),r.body&&r.body.length>60&&(o+=1),o>=5&&i.push({entry:r,score:o})}return i.sort((r,o)=>o.score-r.score).map(r=>r.entry)}function Tt(e,t=""){return sr(e,t).some(i=>(i.doList||[]).length>=1||(i.body||"").length>=80)}function lr(e,t=""){const i=String(e||t||"this subject").trim().replace(/\s+/g," ").slice(0,80)||"this subject";return{id:`unsure_${i.toLowerCase().replace(/[^a-z0-9]+/g,"_").replace(/^_|_$/g,"").slice(0,40)||"subject"}`,label:i,keywords:i.toLowerCase().split(/\W+/).filter(o=>o.length>3).slice(0,8),question:`careTalk was not sure about this subject: ${i}. What should carers do?`}}function Di(e=""){const t=String(e||"").toLowerCase();if(!t||t.split(/\s+/).length<3)return!1;const n=t.split(/\W+/).filter(i=>i.length>3);return n.length?de().some(i=>{const r=`${i.title} ${i.body} ${(i.keywords||[]).join(" ")}`.toLowerCase();return n.filter(a=>r.includes(a)).length>=2&&((i.doList||[]).length>=1||(i.body||"").length>=60)}):!1}function ct(){return nr()}function qt(e){si(e)}function cr(){return ct().filter(e=>e.status==="unresolved")}function dr({topic:e,utterance:t,person:n="",carer:i=""}){const r=ct(),o=Date.now()-1440*60*1e3,a=r.find(l=>l.status==="unresolved"&&l.topicId===e.id&&(l.person||"").toLowerCase()===(n||"").toLowerCase()&&new Date(l.createdAt).getTime()>o);if(a)return{incident:a,created:!1};const s={id:`inc_${Date.now()}`,status:"unresolved",topicId:e.id,topicLabel:e.label,question:e.question||(e.id==="medication_refusal"?`What should carers do when ${n||"a client"} refuses / does not take their medicine?`:`careTalk was unsure about: ${e.label}. What should carers do?`),person:n||"",carer:i||"",utterance:String(t||"").trim(),createdAt:new Date().toISOString(),resolvedAt:null,resolvedBy:null,knowledgeId:null,agencyNotified:!1};return r.unshift(s),qt(r),{incident:s,created:!0}}function xi(e,{knowledgeId:t=null,note:n=""}={}){const i=ct(),r=i.findIndex(o=>o.id===e);if(r<0)throw new Error("Incident not found");return i[r]={...i[r],status:"resolved",resolvedAt:new Date().toISOString(),resolvedBy:"Head nurse",knowledgeId:t,resolveNote:n},qt(i),i[r]}async function ur(e){const t=it(),n=["careTalk — TRAINING REQUEST (UNRESOLVED)","===================================",`Incident id: ${e.id}`,`Topic: ${e.topicLabel}`,"Question careTalk could not answer from training:",e.question,"",`Person / client: ${e.person||"—"}`,`Reported by carer: ${e.carer||"—"}`,`Carer said: ${e.utterance||"—"}`,`Logged: ${new Date(e.createdAt).toLocaleString("en-GB")}`,"","careTalk told the carer he will ask for training on this.","Please open Give careTalk more knowledge in careTalk, resolve this incident, and add clear do/don’t guidance.","",`Agency: ${t.name}`].join(`
20
  `),i={id:`gap_${Date.now()}`,type:"don.training_gap",at:new Date().toISOString(),incidentId:e.id,agencyName:t.name,agencyEmail:t.email,report:n,channels:["outbox"]};if(t.webhookUrl)try{(await fetch(t.webhookUrl,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(i)})).ok&&i.channels.push("webhook")}catch(a){i.webhookError=(a==null?void 0:a.message)||"webhook failed"}if(t.email){const a=encodeURIComponent(`careTalk needs training — ${e.topicLabel}${e.person?` — ${e.person}`:""}`),s=encodeURIComponent(n.slice(0,1800)),l=`mailto:${encodeURIComponent(t.email)}?subject=${a}&body=${s}`;i.mailto=l,i.channels.push("email");try{const d=document.createElement("a");d.href=l,d.rel="noopener",document.body.appendChild(d),d.click(),d.remove()}catch{}}tr(i);const r=ct(),o=r.findIndex(a=>a.id===e.id);return o>=0&&(r[o].agencyNotified=!0,qt(r)),{packet:i,agency:t,report:n}}const Pi=[{id:"mood",label:"Mood & engagement",voice:["mood","engagement","wellbeing"],prompt:"How is their mood and engagement right now?"},{id:"mobility",label:"Mobilisation",voice:["mobility","mobilisation","transfer","zimmer","hoist"],prompt:"How did they mobilise / transfer?"},{id:"nutrition",label:"Nutrition & fluids",voice:["nutrition","hydration","ate","drank","meal"],prompt:"What did they eat and drink?"},{id:"personal",label:"Personal care",voice:["personal care","washed","dressed","continence","pad"],prompt:"What personal care was completed?"},{id:"skin",label:"Skin integrity",voice:["skin","pressure","sore","redness"],prompt:"Any skin changes or pressure areas?"},{id:"clinical",label:"Clinical / PRN",voice:["medication","prn","obs","pain","gp"],prompt:"Any medication, pain, or clinical observations?"},{id:"risk",label:"Risks & safety",voice:["risk","fall","wander","safeguarding","incident"],prompt:"Any safety or safeguarding concerns?"},{id:"plan",label:"Plan / escalate",voice:["plan","action","escalate","handover"],prompt:"What should happen next?"}],Oi=[{key:"resident",re:/(?:resident|service user|client|with)\s+([A-Z][a-z]+(?:\s+[A-Z][a-z]+)?)/i},{key:"when",re:/(?:at|around|about)\s+(\d{1,2}(?::\d{2})?\s*(?:am|pm)?|\d{1,2}\s*(?:am|pm)|this morning|this afternoon|this evening|overnight|during night shift)/i}],Bi=[["fall","Falls risk"],["slipped","Falls risk"],["wander","Exit-seeking / wandering"],["exit-seeking","Exit-seeking / wandering"],["exit seeking","Exit-seeking / wandering"],["distress","Emotional distress"],["agitated","Emotional distress"],["aggressive","Behavioural escalation"],["chok","Choking / swallow risk"],["pressure","Skin integrity watch"],["sore","Skin integrity watch"],["refus","Care preference / declined support"],["declined","Care preference / declined support"],["low mood","Mood concern"],["confused","Cognitive change"],["delirium","Cognitive change"],["safeguard","Safeguarding pathway"],["bruise","Injury / mark observed"],["unwitnessed","Unwitnessed event — verify"]],Ni=[[/refused care/gi,"declined care; support and choices were offered"],[/refused/gi,"declined"],[/non[- ]compliant/gi,"needed extra encouragement and adapted support"],[/aggressive resident/gi,"showed distressed behaviour"],[/wandering/gi,"walking with purpose / exit-seeking"],[/fed/gi,"supported with meals"],[/toileted/gi,"supported with continence care"],[/put to bed/gi,"supported to settle for bed"],[/challenging behaviour/gi,"distressed behaviour"]];function Ct(e){const t=e.trim().replace(/\s+/g," ");return t?t.charAt(0).toUpperCase()+t.slice(1):""}function ye(e,t,n=[]){const i=e.toLowerCase();for(const r of t){const o=i.indexOf(r);if(o===-1)continue;let a=e.slice(o+r.length).replace(/^[\s:,-]+/,""),s=a.length;for(const d of n){const u=a.toLowerCase().indexOf(d);u!==-1&&(s=Math.min(s,u))}const l=a.slice(0,s).trim().replace(/[.;]+$/,"");if(l)return Ct(l)}return""}function Ui(e){let t=e||"";for(const[n,i]of Ni)t=t.replace(n,i);return t}function pn(e){const t=(e||"").toLowerCase();return Pi.map(n=>({...n,covered:n.voice.some(i=>t.includes(i))}))}function _i(e,t){const n=t.filter(o=>!o.covered).map(o=>o.label),i=e.flags.filter(o=>!/No acute/i.test(o)),r=[];return e.resident?r.push(`${e.resident}: ${e.mood||e.narrative.slice(0,90)||"see full note"}`):e.narrative&&r.push(e.narrative.slice(0,110)),i.length&&r.push(`Watch: ${i.slice(0,3).join("; ")}`),e.actions?r.push(`Next: ${e.actions}`):n.length&&r.push(`Still to capture: ${n.slice(0,3).join(", ")}`),e.clinical&&r.push(`Clinical: ${e.clinical}`),r.slice(0,4)}function ji(e){const t=e.flags.filter(n=>/safeguard|fall|chok|injury|behavioural|skin integrity|cognitive/i.test(n));return t.length?{title:"Nurse-in-charge brief",lines:[`Person: ${e.resident||"Resident (name not yet captured)"}`,`Flags: ${t.join("; ")}`,`Facts noted: ${e.risks||e.narrative||"See body of note"}`,`Already done: ${e.actions||"Document response and who was informed"}`,"Ask: Do we need GP / 111 / safeguarding referral / family call now?"]}:null}function dt(e,t="wellbeing"){const n=Ui(e||""),i=n.replace(/\s+/g," ").trim(),r={resident:"",when:"",mood:"",mobility:"",nutrition:"",care:"",clinical:"",risks:"",actions:"",flags:[],narrative:"",confidence:0,coverage:pn(""),handover:[],escalation:null,dignityApplied:n!==(e||""),noteType:t};if(!i)return r;let o="",a="";for(const{key:x,re:z}of Oi){const R=i.match(z);R&&(x==="resident"&&(o=R[1]),x==="when"&&(a=Ct(R[1])))}if(!o){const x=i.match(/\b([A-Z][a-z]+)\s+(?:was|is|appeared|seemed|had|ate|declined|refused)\b/);x&&(o=x[1])}const s=ye(i,["mood","appeared","seemed","engagement","engaged","wellbeing"],["mobility","transfer","ate","drink","medication","action","plan","risk"]),l=ye(i,["mobility","mobilis","transfer","zimmer","frame","hoist","walked"],["ate","drink","nutrition","hydration","personal care","medication","action"]),d=ye(i,["nutrition","hydration","ate","eaten","drank","fluid","meal","lunch","breakfast","dinner","supper"],["personal care","washed","continence","medication","action","plan"]),u=ye(i,["personal care","washed","shower","continence","pad","skin","dressed"],["medication","clinical","obs","action","plan","risk"]),f=ye(i,["medication","prn","clinical","obs","blood pressure","temperature","gp","nurse","pain"],["action","plan","next","risk","incident"]),g=ye(i,["risk","incident","concern","safeguarding","near miss"],["action","plan","we ","staff "]),w=ye(i,["action","plan","we ","staff ","escalated","informed","documented","handover"],[]),y=[],k=i.toLowerCase();for(const[x,z]of Bi)k.includes(x)&&!y.includes(z)&&y.push(z);!y.length&&/settled|comfortable|no concerns|stable/i.test(i)&&y.push("No acute escalation flagged");const v=a||"this shift",$=[];t==="family"?$.push(o?`${o} has been supported ${v}.`:`Your relative has been supported ${v}.`):t==="handover"?$.push(o?`Handover — ${o} (${v}).`:`Handover note (${v}).`):$.push(o?`${o} was reviewed ${v}.`:`Resident reviewed ${v}.`);const C=[s,l,d,u,f].filter(Boolean).map(x=>x.endsWith(".")?x:`${x}.`);$.push(...C),g&&$.push(`Risks/incidents: ${g}${g.endsWith(".")?"":"."}`),w&&$.push(`Actions/plan: ${w}${w.endsWith(".")?"":"."}`),!C.length&&!g&&!w&&$.push(Ct(i)+(i.endsWith(".")?"":"."));const D=[o,a,s,l,d,u,f,g,w].filter(Boolean).length,re=Math.min(98,35+D*8+Math.min(20,Math.floor(i.length/40))),N={resident:o,when:a,mood:s,mobility:l,nutrition:d,care:u,clinical:f,risks:g,actions:w,flags:y,narrative:$.join(" ").replace(/\s+/g," ").trim(),confidence:re,noteType:t,dignityApplied:n!==(e||"").replace(/\s+/g," ").trim()};return N.coverage=pn(i),N.handover=_i(N,N.coverage),N.escalation=ji(N),N}const He={users:"don.users",sessionUser:"don.session.userId"},Mi=1800*1e3;function ve(e){const t=`don.user|${String(e||"").trim()}`;let n=2166136261;for(let i=0;i<t.length;i+=1)n^=t.charCodeAt(i),n=Math.imul(n,16777619);return(n>>>0).toString(16)}function Fi(e,t){try{const n=localStorage.getItem(e);return n?JSON.parse(n):t}catch{return t}}function Hi(e,t){localStorage.setItem(e,JSON.stringify(t))}function qi(e){const t={...e};return t.emailVerified===void 0&&(t.emailVerified=t.status==="approved"),t.requestedRole||(t.requestedRole=t.role==="admin"?"admin":"carer"),t}function O(){return Fi(He.users,[]).map(qi)}function le(e){Hi(He.users,Array.isArray(e)?e:[])}function q(e){if(!e)return null;const{passwordHash:t,verificationCodeHash:n,verificationExpiresAt:i,...r}=e;return r}function Wt(){return sessionStorage.getItem(He.sessionUser)||""}function T(){const e=Wt();if(!e)return null;const t=q(O().find(n=>n.id===e)||null);return t&&t.status!=="approved"?(ie(""),null):t}function ie(e){e?sessionStorage.setItem(He.sessionUser,e):sessionStorage.removeItem(He.sessionUser)}function pr(){ie("")}function ut(e=T()){return!!(e&&e.status==="approved")}function Le(e=T()){return ut(e)&&e.role==="admin"}function fr(e=T()){return ut(e)}function qe(e,t=T()){return ut(t)?e==="learn"?!0:e==="train"||e==="reports"?Le(t):!1:!1}function Wi(){return String(Math.floor(1e5+Math.random()*9e5))}function Gi(e,t){const n=e[t];n.requestedRole!=="admin"&&n.role!=="admin"?e[t]={...n,status:"approved",role:"carer",emailVerified:!0,approvedAt:new Date().toISOString(),approvedBy:"email_verified",verificationCodeHash:null,verificationExpiresAt:null}:e[t]={...n,emailVerified:!0,verificationCodeHash:null,verificationExpiresAt:null}}function gr(e){const t=String(e||"").trim().toLowerCase(),n=O(),i=n.findIndex(l=>l.email===t);if(i<0)throw new Error("No registration found for that email");const r=Wi();n[i].verificationCodeHash=ve(r),n[i].verificationExpiresAt=new Date(Date.now()+Mi).toISOString(),le(n);const o=encodeURIComponent("careTalk — verify your email"),a=encodeURIComponent(`Your careTalk verification code is: ${r}
21
 
 
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./web-Bmj3o-P9.js","./modulepreload-polyfill-B5Qt9EMX.js","./web-BmkooPm-.js","./web-DodVBXGv.js"])))=>i.map(i=>d[i]);
2
+ import"./modulepreload-polyfill-B5Qt9EMX.js";/*! Capacitor: https://capacitorjs.com/ - MIT License */var De;(function(e){e.Unimplemented="UNIMPLEMENTED",e.Unavailable="UNAVAILABLE"})(De||(De={}));class vt extends Error{constructor(t,n,i){super(t),this.message=t,this.code=n,this.data=i}}const Fr=e=>{var t,n;return e!=null&&e.androidBridge?"android":!((n=(t=e==null?void 0:e.webkit)===null||t===void 0?void 0:t.messageHandlers)===null||n===void 0)&&n.bridge?"ios":"web"},Hr=e=>{const t=e.CapacitorCustomPlatform||null,n=e.Capacitor||{},i=n.Plugins=n.Plugins||{},r=()=>t!==null?t.name:Fr(e),o=()=>r()!=="web",a=f=>{const g=d.get(f);return!!(g!=null&&g.platforms.has(r())||s(f))},s=f=>{var g;return(g=n.PluginHeaders)===null||g===void 0?void 0:g.find(w=>w.name===f)},l=f=>e.console.error(f),d=new Map,u=(f,g={})=>{const w=d.get(f);if(w)return console.warn(`Capacitor plugin "${f}" already registered. Cannot register plugins twice.`),w.proxy;const y=r(),k=s(f);let v;const $=async()=>(!v&&y in g?v=typeof g[y]=="function"?v=await g[y]():v=g[y]:t!==null&&!v&&"web"in g&&(v=typeof g.web=="function"?v=await g.web():v=g.web),v),C=(R,U)=>{var K,Y;if(k){const J=k==null?void 0:k.methods.find(Z=>U===Z.name);if(J)return J.rtype==="promise"?Z=>n.nativePromise(f,U.toString(),Z):(Z,Te)=>n.nativeCallback(f,U.toString(),Z,Te);if(R)return(K=R[U])===null||K===void 0?void 0:K.bind(R)}else{if(R)return(Y=R[U])===null||Y===void 0?void 0:Y.bind(R);throw new vt(`"${f}" plugin is not implemented on ${y}`,De.Unimplemented)}},D=R=>{let U;const K=(...Y)=>{const J=$().then(Z=>{const Te=C(Z,R);if(Te){const pe=Te(...Y);return U=pe==null?void 0:pe.remove,pe}else throw new vt(`"${f}.${R}()" is not implemented on ${y}`,De.Unimplemented)});return R==="addListener"&&(J.remove=async()=>U()),J};return K.toString=()=>`${R.toString()}() { [capacitor code] }`,Object.defineProperty(K,"name",{value:R,writable:!1,configurable:!1}),K},re=D("addListener"),N=D("removeListener"),x=(R,U)=>{const K=re({eventName:R},U),Y=async()=>{const Z=await K;N({eventName:R,callbackId:Z},U)},J=new Promise(Z=>K.then(()=>Z({remove:Y})));return J.remove=async()=>{console.warn("Using addListener() without 'await' is deprecated."),await Y()},J},z=new Proxy({},{get(R,U){switch(U){case"$$typeof":return;case"toJSON":return()=>({});case"addListener":return k?x:re;case"removeListener":return N;default:return D(U)}}});return i[f]=z,d.set(f,{name:f,proxy:z,platforms:new Set([...Object.keys(g),...k?[y]:[]])}),z};return n.convertFileSrc||(n.convertFileSrc=f=>f),n.getPlatform=r,n.handleError=l,n.isNativePlatform=o,n.isPluginAvailable=a,n.registerPlugin=u,n.Exception=vt,n.DEBUG=!!n.DEBUG,n.isLoggingEnabled=!!n.isLoggingEnabled,n},qr=e=>e.Capacitor=Hr(e),xe=qr(typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{}),Ae=xe.registerPlugin;class Jn{constructor(){this.listeners={},this.retainedEventArguments={},this.windowListeners={}}addListener(t,n){let i=!1;this.listeners[t]||(this.listeners[t]=[],i=!0),this.listeners[t].push(n);const o=this.windowListeners[t];o&&!o.registered&&this.addWindowListener(o),i&&this.sendRetainedArgumentsForEvent(t);const a=async()=>this.removeListener(t,n);return Promise.resolve({remove:a})}async removeAllListeners(){this.listeners={};for(const t in this.windowListeners)this.removeWindowListener(this.windowListeners[t]);this.windowListeners={}}notifyListeners(t,n,i){const r=this.listeners[t];if(!r){if(i){let o=this.retainedEventArguments[t];o||(o=[]),o.push(n),this.retainedEventArguments[t]=o}return}r.forEach(o=>o(n))}hasListeners(t){var n;return!!(!((n=this.listeners[t])===null||n===void 0)&&n.length)}registerWindowListener(t,n){this.windowListeners[n]={registered:!1,windowEventName:t,pluginEventName:n,handler:i=>{this.notifyListeners(n,i)}}}unimplemented(t="not implemented"){return new xe.Exception(t,De.Unimplemented)}unavailable(t="not available"){return new xe.Exception(t,De.Unavailable)}async removeListener(t,n){const i=this.listeners[t];if(!i)return;const r=i.indexOf(n);this.listeners[t].splice(r,1),this.listeners[t].length||this.removeWindowListener(this.windowListeners[t])}addWindowListener(t){window.addEventListener(t.windowEventName,t.handler),t.registered=!0}removeWindowListener(t){t&&(window.removeEventListener(t.windowEventName,t.handler),t.registered=!1)}sendRetainedArgumentsForEvent(t){const n=this.retainedEventArguments[t];n&&(delete this.retainedEventArguments[t],n.forEach(i=>{this.notifyListeners(t,i)}))}}const en=e=>encodeURIComponent(e).replace(/%(2[346B]|5E|60|7C)/g,decodeURIComponent).replace(/[()]/g,escape),tn=e=>e.replace(/(%[\dA-F]{2})+/gi,decodeURIComponent);class Wr extends Jn{async getCookies(){const t=document.cookie,n={};return t.split(";").forEach(i=>{if(i.length<=0)return;let[r,o]=i.replace(/=/,"CAP_COOKIE").split("CAP_COOKIE");r=tn(r).trim(),o=tn(o).trim(),n[r]=o}),n}async setCookie(t){try{const n=en(t.key),i=en(t.value),r=t.expires?`; expires=${t.expires.replace("expires=","")}`:"",o=(t.path||"/").replace("path=",""),a=t.url!=null&&t.url.length>0?`domain=${t.url}`:"";document.cookie=`${n}=${i||""}${r}; path=${o}; ${a};`}catch(n){return Promise.reject(n)}}async deleteCookie(t){try{document.cookie=`${t.key}=; Max-Age=0`}catch(n){return Promise.reject(n)}}async clearCookies(){try{const t=document.cookie.split(";")||[];for(const n of t)document.cookie=n.replace(/^ +/,"").replace(/=.*/,`=;expires=${new Date().toUTCString()};path=/`)}catch(t){return Promise.reject(t)}}async clearAllCookies(){try{await this.clearCookies()}catch(t){return Promise.reject(t)}}}Ae("CapacitorCookies",{web:()=>new Wr});const Gr=async e=>new Promise((t,n)=>{const i=new FileReader;i.onload=()=>{const r=i.result;t(r.indexOf(",")>=0?r.split(",")[1]:r)},i.onerror=r=>n(r),i.readAsDataURL(e)}),Vr=(e={})=>{const t=Object.keys(e);return Object.keys(e).map(r=>r.toLocaleLowerCase()).reduce((r,o,a)=>(r[o]=e[t[a]],r),{})},zr=(e,t=!0)=>e?Object.entries(e).reduce((i,r)=>{const[o,a]=r;let s,l;return Array.isArray(a)?(l="",a.forEach(d=>{s=t?encodeURIComponent(d):d,l+=`${o}=${s}&`}),l.slice(0,-1)):(s=t?encodeURIComponent(a):a,l=`${o}=${s}`),`${i}&${l}`},"").substr(1):null,Kr=(e,t={})=>{const n=Object.assign({method:e.method||"GET",headers:e.headers},t),r=Vr(e.headers)["content-type"]||"";if(typeof e.data=="string")n.body=e.data;else if(r.includes("application/x-www-form-urlencoded")){const o=new URLSearchParams;for(const[a,s]of Object.entries(e.data||{}))o.set(a,s);n.body=o.toString()}else if(r.includes("multipart/form-data")||e.data instanceof FormData){const o=new FormData;if(e.data instanceof FormData)e.data.forEach((s,l)=>{o.append(l,s)});else for(const s of Object.keys(e.data))o.append(s,e.data[s]);n.body=o;const a=new Headers(n.headers);a.delete("content-type"),n.headers=a}else(r.includes("application/json")||typeof e.data=="object")&&(n.body=JSON.stringify(e.data));return n};class Yr extends Jn{async request(t){const n=Kr(t,t.webFetchExtra),i=zr(t.params,t.shouldEncodeUrlParams),r=i?`${t.url}?${i}`:t.url,o=await fetch(r,n),a=o.headers.get("content-type")||"";let{responseType:s="text"}=o.ok?t:{};a.includes("application/json")&&(s="json");let l,d;switch(s){case"arraybuffer":case"blob":d=await o.blob(),l=await Gr(d);break;case"json":l=await o.json();break;case"document":case"text":default:l=await o.text()}const u={};return o.headers.forEach((f,g)=>{u[g]=f}),{data:l,headers:u,status:o.status,url:o.url}}async get(t){return this.request(Object.assign(Object.assign({},t),{method:"GET"}))}async post(t){return this.request(Object.assign(Object.assign({},t),{method:"POST"}))}async put(t){return this.request(Object.assign(Object.assign({},t),{method:"PUT"}))}async patch(t){return this.request(Object.assign(Object.assign({},t),{method:"PATCH"}))}async delete(t){return this.request(Object.assign(Object.assign({},t),{method:"DELETE"}))}}Ae("CapacitorHttp",{web:()=>new Yr});const Jr="modulepreload",Zr=function(e,t){return new URL(e,t).href},nn={},Nt=function(t,n,i){let r=Promise.resolve();if(n&&n.length>0){let a=function(u){return Promise.all(u.map(f=>Promise.resolve(f).then(g=>({status:"fulfilled",value:g}),g=>({status:"rejected",reason:g}))))};const s=document.getElementsByTagName("link"),l=document.querySelector("meta[property=csp-nonce]"),d=(l==null?void 0:l.nonce)||(l==null?void 0:l.getAttribute("nonce"));r=a(n.map(u=>{if(u=Zr(u,i),u in nn)return;nn[u]=!0;const f=u.endsWith(".css"),g=f?'[rel="stylesheet"]':"";if(!!i)for(let k=s.length-1;k>=0;k--){const v=s[k];if(v.href===u&&(!f||v.rel==="stylesheet"))return}else if(document.querySelector(`link[href="${u}"]${g}`))return;const y=document.createElement("link");if(y.rel=f?"stylesheet":Jr,f||(y.as="script"),y.crossOrigin="",y.href=u,d&&y.setAttribute("nonce",d),document.head.appendChild(y),f)return new Promise((k,v)=>{y.addEventListener("load",k),y.addEventListener("error",()=>v(new Error(`Unable to preload CSS for ${u}`)))})}))}function o(a){const s=new Event("vite:preloadError",{cancelable:!0});if(s.payload=a,window.dispatchEvent(s),!s.defaultPrevented)throw a}return r.then(a=>{for(const s of a||[])s.status==="rejected"&&o(s.reason);return t().catch(o)})},fe=Ae("SpeechRecognition",{web:()=>Nt(()=>import("./web-Bmj3o-P9.js"),__vite__mapDeps([0,1]),import.meta.url).then(e=>new e.SpeechRecognitionWeb)});function Je(){return xe.isNativePlatform()}function Qr({onFinal:e,onPartial:t,onStart:n,onEnd:i,onError:r,lang:o="en-GB"}){let a=!1,s=null,l=null,d=null,u=!1,f="",g=0,w="",y=null,k=null,v=o,$=!1,C=!1,D=!1,re=0,N="";function x(I){const b=String(I||"").trim();if(!b)return!0;try{if(b===window.location.href||b===window.location.origin||b===window.location.host||b===`${window.location.protocol}//${window.location.host}`)return!0}catch{}return!!(/^https?:\/\//i.test(b)||/\blocalhost(:\d+)?\b/i.test(b)||/\b127\.0\.0\.1\b/.test(b)||/mic (issue|blocked|busy)|speech needs internet|no microphone|asking for microphone/i.test(b)||!/[a-zA-Z]{2,}/.test(b))}function z(I){const b=String(I||"").trim();if(!b||x(b)||D||C)return;const S=Date.now();b.toLowerCase()===w.toLowerCase()&&S-g<1200||(w=b,g=S,f="",clearTimeout(y),e==null||e(b))}function R(I){const b=String(I||"").trim();if(!b||x(b))return;f=b,t==null||t(b),clearTimeout(y);const S=b.split(/\s+/).filter(Boolean).length,_=S<=3?1100:S<=8?1500:1900;y=setTimeout(()=>{f===b&&!D&&!C&&z(b)},_)}function U(I){var S;let b="";for(let _=0;_<I.length;_+=1){const E=(((S=I[_])==null?void 0:S.transcript)||"").trim();if(E&&(b||(b=E),/\b(don|dawn|done|dom|dun|donn|donald)\b/i.test(E))){b=E;break}}return b}async function K(){var S,_;if(!window.isSecureContext)throw new Error("Mic blocked on insecure URL — open http://localhost:5173 in Chrome");if(!((S=navigator.mediaDevices)!=null&&S.getUserMedia))throw new Error("This window can’t use the mic — open the app in Chrome or Edge");let I;try{I=await navigator.mediaDevices.getUserMedia({audio:{echoCancellation:!0,noiseSuppression:!0,autoGainControl:!0}})}catch(E){const te=(E==null?void 0:E.name)||"";throw te==="NotFoundError"||te==="DevicesNotFoundError"?new Error("No microphone detected — plug one in (System Settings → Sound → Input)"):te==="NotAllowedError"||te==="PermissionDeniedError"?new Error("Microphone permission denied — click the lock icon → Microphone → Allow"):te==="NotReadableError"||te==="TrackStartError"?new Error("Microphone is busy — quit Zoom/Teams/FaceTime/OBS, then tap the mic again"):new Error((E==null?void 0:E.message)||"Could not open microphone")}const b=I.getAudioTracks()[0];if(N=(b==null?void 0:b.label)||"Microphone",b&&b.readyState!=="live")throw I.getTracks().forEach(E=>E.stop()),new Error("Microphone track inactive — check Mac Sound input device");I.getTracks().forEach(E=>E.stop()),await new Promise(E=>setTimeout(E,180));try{if(!(await navigator.mediaDevices.enumerateDevices()).filter(Mr=>Mr.kind==="audioinput").length)throw new Error("No audio input devices listed — check System Settings → Sound → Input")}catch(E){if((_=E==null?void 0:E.message)!=null&&_.startsWith("No audio"))throw E}return N}function Y(){if(!(!u||!s||$||C)){$=!0;try{s.lang=v,s.start()}catch(I){const b=String((I==null?void 0:I.message)||I||"");/already started|InvalidStateError/i.test(b)||r==null||r(b||"Could not start mic")}finally{setTimeout(()=>{$=!1},300)}}}function J(I=300){!u||C||(clearTimeout(k),k=setTimeout(()=>{!u||C||Y()},I))}function Z(){if(s)return s;const I=window.SpeechRecognition||window.webkitSpeechRecognition;if(!I)throw new Error("Speech not supported here — use Chrome or Edge (not Safari), or type to careTalk");return s=new I,s.continuous=!0,s.interimResults=!0,s.maxAlternatives=5,s.lang=v,s.onstart=()=>{a=!0,$=!1,re=0,n==null||n()},s.onend=()=>{a=!1,i==null||i(),!C&&(clearTimeout(y),f="",J(320))},s.onerror=b=>{const S=b.error;if(S!=="aborted"&&S!=="no-speech"){if(S==="audio-capture"){if(re+=1,re<=2&&u){r==null||r("Mic busy — retrying… close other apps using the mic"),clearTimeout(k),k=setTimeout(async()=>{if(u)try{await K(),Y()}catch(_){u=!1,r==null||r((_==null?void 0:_.message)||"no microphone available")}},600);return}u=!1,r==null||r(N?`Can’t capture “${N}” — quit Zoom/Teams/FaceTime, allow mic for this site, tap again`:"Can’t open microphone — allow mic in the address bar, quit apps using the mic, use Chrome on localhost");return}if(S==="not-allowed"||S==="service-not-allowed"){u=!1,r==null||r("Mic blocked — lock icon in address bar → Microphone → Allow, then tap mic");return}if(S==="network"){r==null||r("Speech needs internet (Chrome voice service)"),J(1200);return}if(S==="language-not-supported"&&v!=="en-US"){v="en-US",s.lang=v,J(300);return}r==null||r(S),J(500)}},s.onresult=b=>{let S="";for(let _=b.resultIndex;_<b.results.length;_+=1){const E=b.results[_],te=U(E);!te||x(te)||(E.isFinal?!D&&!C&&z(te):S+=`${te} `)}S.trim()&&!D&&(t==null||t(S.trim()),f=S.trim(),R(S.trim()))},s}async function Te(){const I=await fe.available();if(!(I!=null&&I.available))throw new Error("Speech recognition unavailable on this device");if((await fe.checkPermissions()).speechRecognition!=="granted"&&(await fe.requestPermissions()).speechRecognition!=="granted")throw new Error("Microphone / speech permission denied")}async function pe(){await Te(),f="",l=await fe.addListener("partialResults",I=>{const b=((I==null?void 0:I.matches)||[]).filter(Boolean).join(" ").trim();b&&R(b)}),d=await fe.addListener("listeningState",I=>{I.status==="started"&&(a=!0,n==null||n()),I.status==="stopped"&&(a=!1,i==null||i(),u&&!C&&(clearTimeout(k),k=setTimeout(()=>{u&&pe().catch(b=>r==null?void 0:r((b==null?void 0:b.message)||"mic restart failed"))},400)))}),await fe.start({language:v,maxResults:5,partialResults:!0,popup:!1}),a=!0,n==null||n()}async function jr(){clearTimeout(y),clearTimeout(k);try{await fe.stop()}catch{}f&&!x(f)&&z(f);try{await(l==null?void 0:l.remove()),await(d==null?void 0:d.remove())}catch{}l=null,d=null,a=!1,i==null||i()}return{get listening(){return a},get micLabel(){return N},setInputBlocked(I){D=!!I,D&&(clearTimeout(y),f="")},async start(){if(u=!0,C=!1,f="",re=0,Je()){await pe();return}await K(),Z(),Y()},async pause(){if(C=!0,D=!0,clearTimeout(k),clearTimeout(y),Je()){try{await fe.stop()}catch{}a=!1,i==null||i();return}try{s==null||s.stop()}catch{}a=!1,i==null||i()},async resume(){if(C=!1,D=!1,u=!0,Je()){await pe();return}Y()},async stop(){if(u=!1,C=!1,clearTimeout(k),clearTimeout(y),$=!1,Je()){await jr();return}const I=f;f="";try{s==null||s.stop()}catch{}I&&!x(I)&&z(I),a=!1,i==null||i()}}}var It;(function(e){e.Dark="DARK",e.Light="LIGHT",e.Default="DEFAULT"})(It||(It={}));var rn;(function(e){e.None="NONE",e.Slide="SLIDE",e.Fade="FADE"})(rn||(rn={}));const on=Ae("StatusBar"),Xr=Ae("SplashScreen",{web:()=>Nt(()=>import("./web-BmkooPm-.js"),__vite__mapDeps([2,1]),import.meta.url).then(e=>new e.SplashScreenWeb)});var an;(function(e){e.Dark="DARK",e.Light="LIGHT",e.Default="DEFAULT"})(an||(an={}));var At;(function(e){e.Body="body",e.Ionic="ionic",e.Native="native",e.None="none"})(At||(At={}));const ei=Ae("Keyboard"),sn=Ae("App",{web:()=>Nt(()=>import("./web-DodVBXGv.js"),__vite__mapDeps([3,1]),import.meta.url).then(e=>new e.AppWeb)});async function ti(){if(xe.isNativePlatform()){document.documentElement.classList.add("native"),document.documentElement.dataset.platform=xe.getPlatform();try{await on.setStyle({style:It.Dark}),await on.setBackgroundColor({color:"#061114"})}catch{}try{await ei.setResizeMode({mode:At.Body})}catch{}try{await Xr.hide()}catch{}sn.addListener("backButton",({canGoBack:e})=>{e?window.history.back():sn.exitApp()})}}const P={pinHash:"don.train.pinHash",pinSet:"don.train.pinSet",sessionAuth:"don.train.authed",knowledge:"don.train.knowledge",agency:"don.agency",outbox:"don.agency.outbox",incidents:"don.train.incidents",customTopics:"don.train.customTopics"},Ut="2473";function Qe(e){const t=`don|${String(e||"").trim()}`;let n=2166136261;for(let i=0;i<t.length;i+=1)n^=t.charCodeAt(i),n=Math.imul(n,16777619);return(n>>>0).toString(16)}function Ve(e,t){try{const n=localStorage.getItem(e);return n?JSON.parse(n):t}catch{return t}}function ze(e,t){localStorage.setItem(e,JSON.stringify(t))}function ni(){return localStorage.getItem(P.pinSet)==="1"}function _t(){ni()||(localStorage.setItem(P.pinHash,Qe(Ut)),localStorage.setItem(P.pinSet,"1"))}function ri(e){_t();const t=localStorage.getItem(P.pinHash)||Qe(Ut);return Qe(e)===t}function ii(e){const t=String(e||"").trim();if(t.length<4)throw new Error("PIN must be at least 4 digits");localStorage.setItem(P.pinHash,Qe(t)),localStorage.setItem(P.pinSet,"1")}function be(e){e?sessionStorage.setItem(P.sessionAuth,"1"):sessionStorage.removeItem(P.sessionAuth)}function Zn(){return sessionStorage.getItem(P.sessionAuth)==="1"}function de(){return Ve(P.knowledge,[])}function Qn(e){ze(P.knowledge,e)}function Xn(e){const t=de(),n=r=>Array.isArray(r)?r.map(o=>String(o).trim()).filter(Boolean):String(r||"").split(`
3
  `).map(o=>o.trim()).filter(Boolean),i={id:`k_${Date.now()}`,title:String(e.title||"").trim(),body:String(e.body||"").trim(),doList:n(e.doList),dontList:n(e.dontList),keywords:String(e.keywords||"").split(",").map(r=>r.trim().toLowerCase()).filter(Boolean),sourceUrl:String(e.sourceUrl||"").trim(),images:Array.isArray(e.images)?e.images.map(r=>String(r).trim()).filter(Boolean):String(e.images||"").split(`
4
  `).map(r=>r.trim()).filter(Boolean),addedBy:e.addedBy||"Head nurse",addedAt:new Date().toISOString()};if(!i.title||!i.body)throw new Error("Title and guidance text are required");return t.unshift(i),Qn(t),i}function oi(e){Qn(de().filter(t=>t.id!==e))}function it(){return Ve(P.agency,{name:"Care agency",email:"",webhookUrl:"",autoForward:!0})}function ai(e){ze(P.agency,{name:String(e.name||"Care agency").trim()||"Care agency",email:String(e.email||"").trim(),webhookUrl:String(e.webhookUrl||"").trim(),autoForward:e.autoForward!==!1})}function er(){return Ve(P.outbox,[])}function tr(e){const t=er();t.unshift(e),ze(P.outbox,t.slice(0,50))}function nr(){return Ve(P.incidents,[])}function si(e){ze(P.incidents,Array.isArray(e)?e:[])}function he(){return Ve(P.customTopics,[])}function jt(e){ze(P.customTopics,Array.isArray(e)?e:[])}function rr({title:e,keywords:t="",notes:n=""}){const i=String(e||"").trim();if(!i)throw new Error("Topic title is required");const r=he(),o={id:`topic_${Date.now()}`,title:i,keywords:String(t||"").split(",").map(a=>a.trim().toLowerCase()).filter(Boolean),notes:String(n||"").trim(),addedAt:new Date().toISOString(),lastTrainedAt:null};return r.unshift(o),jt(r),o}function li(e){jt(he().filter(t=>t.id!==e))}function ci(e){const t=he(),n=t.findIndex(i=>i.id===e);n<0||(t[n].lastTrainedAt=new Date().toISOString(),jt(t))}const Lt={fall:[{id:"fall-assess",title:"Assess first",caption:"Stay with them, check responsiveness and injury before any move.",src:"/guides/fall-assess.svg",alt:"Carer kneeling beside a person on the floor after a fall, asking if they are hurt"},{id:"fall-no-lift",title:"Don’t haul them up",caption:"If injury may be present, keep them comfortable and get clinical advice.",src:"/guides/fall-no-lift.svg",alt:"Warning not to lift a fallen person without assessment"}],dysphagia:[{id:"dysphagia-upright",title:"Sit upright",caption:"Upright posture for eating and drinking; follow texture plan.",src:"/guides/dysphagia-upright.svg",alt:"Person sitting upright in a chair for safe eating and drinking"},{id:"dysphagia-stop",title:"Stop if choking signs",caption:"Coughing, wet voice or colour change — stop intake and call for help.",src:"/guides/dysphagia-stop.svg",alt:"Stop cup or food when choking warning signs appear"}],distress:[{id:"distress-space",title:"Give space",caption:"Reduce stimulation, keep a calm distance, use care-plan strategies.",src:"/guides/distress-space.svg",alt:"Carer giving a person space during distress"}],skin:[{id:"skin-check",title:"Note site & look",caption:"Record exact site, appearance and pain; escalate for grading/dressings.",src:"/guides/skin-check.svg",alt:"Diagram highlighting checking pressure areas on the body"}]};function di(e,t=[]){const n=Lt[e]||[],i=[];for(const o of t)(Array.isArray(o.images)?o.images:[]).forEach((s,l)=>{const d=String(s||"").trim();d&&i.push({id:`trained_${o.id||l}_${l}`,title:o.title||"Home training image",caption:"From your home’s trained knowledge",src:d,alt:`${o.title||"Training"} illustration ${l+1}`})});const r=new Set;return[...n,...i].filter(o=>r.has(o.src)?!1:(r.add(o.src),!0))}function ui(e,t){return e!=null&&e.length?`
5
  <div class="guide-strip">
 
15
  </figcaption>
16
  </figure>`).join("")}</div>
17
  </div>
18
+ `:""}const ir={version:"1.1.8",disclaimer:"careTalk supports record-keeping and safe practice reminders. Follow your home’s policy, escalate to the nurse in charge, and call 999 in an emergency."},Mt=[{id:"pmva_mapa",title:"PMVA / MAPA (BILD-accredited)",notes:"Physical intervention and de-escalation for mental health settings is a specialised, assessed course (typically multi-day, BILD-accredited). Prefer prevention, communication, and least-restrictive options. Only use techniques you are currently trained and authorised to use."},{id:"oliver_mcgowan",title:"Oliver McGowan Mandatory Training (Tier 2 + online)",notes:"Learning disability and autism awareness: assume competence, adapt communication, reduce sensory load, involve familiar supporters, avoid diagnostic overshadowing, and escalate concerns about distress or unmet need."},{id:"ligature",title:"Ligature awareness",notes:"Remove or reduce ligature risks where safe and authorised; do not leave someone in danger to ‘finish paperwork’. Observe, report environmental risks, stay with the person if unsafe to leave, and escalate immediately per policy."},{id:"dysphagia",title:"Dysphagia awareness",notes:"Follow IDDSI / care-plan texture and fluid guidance. Never rush feeding, never mix consistencies against the plan, sit upright, watch for coughing/wet voice/colour change, and stop and escalate if aspiration is suspected."},{id:"seniors",title:"Caring for older adults",notes:"Person-centred, dignity-first care: explain what you are doing, offer choice, watch for delirium, falls, skin, hydration, and loneliness. Document facts, not judgements."},{id:"moving_assisting",title:"Moving and assisting people",notes:"Use agreed handling plans, equipment you are trained on, and enough staff. Do not lift manually against policy. After a fall, do not haul someone up if injury is possible — assess, reassure, follow fallen-person procedure."},{id:"hswa",title:"Health and Safety at Work etc. Act",notes:"Take reasonable care of yourself and others, follow training, report hazards, and do not carry out tasks you are not competent or authorised to do."}];function pi(e,t){const n=`${e} ${t||""}`.toLowerCase(),i=de().filter(r=>{var o;return(o=r.keywords)!=null&&o.length?r.keywords.some(a=>n.includes(a)||e.includes(a)):e==="general"||e==="medication"});if(e==="medication"){const r=i.filter(o=>/\b(medicine|medication|meds|refus|tablet|mar)\b/i.test(`${o.title} ${o.body} ${(o.keywords||[]).join(" ")}`));return r.length?r:i}return i}function fi(e,t=""){var u,f;const n=["Stay calm and reassure the person.","Check for immediate danger to them and you.","Follow your service’s escalation pathway (nurse in charge / on-call / 999).","Document facts: what you saw, what you did, time, who was informed."],i=["Don’t leave an unsafe situation to ‘write the note first’.","Don’t use restrictive holds unless you are currently trained, authorised, and it is a last resort under policy.","Don’t blame the person in the record — stick to observable facts."],r={fall:{pillars:["moving_assisting","seniors","hswa"],do:[...n,"If injury may be present, do not pull them up — keep them comfortable, check responsiveness, and get clinical advice.","Look for head injury signs, pain, limb deformity, bleeding, and sudden confusion.","After safe recovery, review footwear, mobility aid, lighting, and observation level."],dont:[...i,"Don’t use a fireman’s lift or unplanned manual lift.","Don’t dismiss an unwitnessed fall — treat it seriously until assessed.","Don’t delay informing the nurse in charge / family when policy requires it."]},skin:{pillars:["seniors","hswa"],do:[...n,"Note exact site, size/appearance if trained to, pain, and whether skin is broken.","Reposition as care plan allows; keep pressure off the area.","Inform nurse in charge for grading / dressing decisions if required."],dont:[...i,"Don’t apply creams or dressings outside your role/competence.","Don’t ignore unbroken redness over a bony area."]},dysphagia:{pillars:["dysphagia","oliver_mcgowan","seniors"],do:[...n,"Stop oral intake if coughing, choking, wet voice, or colour change.","Keep upright; follow prescribed texture/fluid level only.","Call for help early — choking is time-critical."],dont:[...i,"Don’t give food/drink against the dysphagia plan.","Don’t leave someone alone while eating if supervision is required.","Don’t do blind finger sweeps if choking."]},distress:{pillars:["pmva_mapa","oliver_mcgowan","ligature","hswa"],do:[...n,"Reduce stimulation, give space, use calm simple language, and offer known soothing strategies from the care plan.","Scan for environmental risk (ligature points, weapons, exits) without escalating conflict.","Call for trained support early; protect yourself and others."],dont:[...i,"Don’t crowd, shout, or threaten.","Don’t use physical intervention unless trained, authorised, proportionate, and necessary as a last resort.","Don’t ignore ligature risk to ‘talk it out’ from a distance if the person is in immediate danger — get help now."]},wellbeing:{pillars:["seniors","oliver_mcgowan"],do:[...n,"Ask about pain, mood, appetite, and what matters to them today.","Note changes from their usual baseline."],dont:[...i,"Don’t skip hydration/nutrition checks when someone seems ‘fine’ but quieter than usual."]},medication:{pillars:["hswa","seniors"],do:["Stay calm and do not force medicine.","Follow your home’s medication / MAR policy and the person’s care plan.","Inform the nurse in charge / on-call promptly.","Document facts: what was offered, what was refused, time, and who was informed."],dont:["Don’t hide medicine in food/drink unless the care plan and policy explicitly allow covert administration by authorised staff.","Don’t force, threaten, or restrain someone to take medicine.","Don’t leave a refused critical dose unreported."]},general:{pillars:["hswa","seniors"],do:n,dont:i}},o={...r[e]||r.general},a=pi(e,t);for(const g of a)(u=g.doList)!=null&&u.length&&(o.do=[...o.do,...g.doList]),(f=g.dontList)!=null&&f.length&&(o.dont=[...o.dont,...g.dontList]);const s=Mt.filter(g=>o.pillars.includes(g.id)).map(g=>`${g.title}: ${g.notes}`),l=a.map(g=>`${g.title}: ${g.body}`),d=di(e,a);return{...o,pillarText:s,trainedText:l,custom:a,images:d}}async function gi(e,t={}){const n=it(),i={id:`fwd_${Date.now()}`,at:new Date().toISOString(),agencyName:n.name,agencyEmail:n.email,carer:t.carer||"",person:t.person||"",scenario:t.scenario||"",report:e,status:"queued",channels:[]};if(i.channels.push("outbox"),n.webhookUrl)try{const r=await fetch(n.webhookUrl,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({type:"don.support_worker_report",...i})});if(!r.ok)throw new Error(`HTTP ${r.status}`);i.channels.push("webhook")}catch(r){i.webhookError=(r==null?void 0:r.message)||"webhook failed"}if(n.email){const r=encodeURIComponent(`careTalk support worker report — ${t.person||"resident"} — ${t.scenario||"care"}`),o=encodeURIComponent(e.slice(0,1800)),a=`mailto:${encodeURIComponent(n.email)}?subject=${r}&body=${o}`;i.mailto=a,i.channels.push("email");try{const s=document.createElement("a");s.href=a,s.rel="noopener",document.body.appendChild(s),s.click(),s.remove()}catch{}}return i.status=i.channels.includes("webhook")||i.channels.includes("email")?"sent":"saved_local",tr(i),{packet:i,agency:n}}function ln(e){return String(e||"").trim().toLowerCase().replace(/[^a-z'-]/g,"")}function mi(e,t){const n=ln(e),i=ln(t);if(!n||!i)return!1;if(n===i)return!0;const r=n.split(/\s+/)[0],o=i.split(/\s+/)[0];return r.length>1&&r===o}function ot(e){const t=String(e||"").trim();return t?t.split(/\s+/)[0]:""}function at(e,t){return mi(e,t)}function hi(e,t){const n=String(e||"").trim().toLowerCase().replace(/[^\w\s'-]/g,""),i=String(t||"").trim().toLowerCase().replace(/[^\w\s'-]/g,"");return!n||!i?!1:!!(n===i||n.length>8&&i.includes(n)||i.length>12&&n.includes(i.slice(0,Math.min(24,i.length))))}function yi(e,t){return t!=="waiting_answer"?!1:/^(yes|yeah|yep|yup|no|nope|nah|ok|okay|correct|right|wrong)$/i.test(String(e||"").trim())}const ke=[{id:"fall",label:"Fall",match:/\b(fall|fell|fallen|slipped|trip(?:ped)?)\b/i,questions:[{id:"when",ask:"When did it happen — just now, or roughly what time?"},{id:"where",ask:"Where did it happen? Bedroom, bathroom, corridor…?"},{id:"witnessed",ask:"Did anyone see it, or was it unwitnessed?"},{id:"how",ask:"What were they doing right before — standing up, walking, reaching…?"},{id:"injury",ask:"Any pain, bleeding, bumps, or odd limb position — or none that you can see?"},{id:"response",ask:"What have you done so far?"},{id:"obs",ask:"How are they now — alert, dizzy, confused, calm?"},{id:"informed",ask:"Who have you told, and who still needs telling — nurse in charge, GP, family, 999?"},{id:"prevent",ask:"Anything you want in place now for safety — mat, closer checks, footwear…?"}]},{id:"dysphagia",label:"Eating / choking / swallow",match:/\b(chok(?:e|ing)?|swallow|dysphagia|coughing (?:on|while) (?:eat|drink)|aspirat)/i,questions:[{id:"what",ask:"What happened with eating or drinking?"},{id:"texture",ask:"Were they on a special texture or fluid level?"},{id:"signs",ask:"Any coughing, colour change, wet voice, or distress?"},{id:"stopped",ask:"Did you stop food and drink?"},{id:"now",ask:"How are they now?"},{id:"informed",ask:"Who have you informed?"}]},{id:"distress",label:"Distress / behaviour support",match:/\b(distress|agitated|aggression|hitting|ligature|self[- ]harm|restrain|mapa|pmva|difficult|challenging|behaviour|behavior)\b/i,questions:[{id:"what",ask:"What’s happening for them right now, in plain words?"},{id:"trigger",ask:"Anything that seemed to trigger it?"},{id:"risk",ask:"Is anyone in immediate danger — including ligature or weapons risk?"},{id:"done",ask:"What have you tried — space, calm talk, care-plan strategies?"},{id:"help",ask:"Who is supporting you on the floor right now?"},{id:"now",ask:"How is the person now?"}]},{id:"medication",label:"Medication / refusal",match:/\b((refuse[ds]?|refusing|won'?t take|will not take|not taking|declined?).{0,40}\b(medicine|medication|meds|tablet|tablets|pill|pills|dose)\b|\b(medicine|medication|meds|tablet|tablets|pill|pills).{0,40}\b(refuse[ds]?|refusing|won'?t|not taking|declined?)\b|\b(medication|medicine|meds|mar)\b)/i,questions:[{id:"what",ask:"Which medicine was refused or not taken — if you know the name or time slot?"},{id:"when",ask:"When was this — which round / roughly what time?"},{id:"how",ask:"What exactly happened — refused, spat out, asleep, not present…?"},{id:"reason",ask:"Did they say why, or seem unwell / distressed?"},{id:"done",ask:"What have you tried so far (offer again, nurse, wait)?"},{id:"now",ask:"How are they now?"},{id:"informed",ask:"Who have you told — nurse in charge / on-call?"},{id:"next",ask:"What needs to happen next according to the home’s policy?"}]},{id:"skin",label:"Skin / pressure concern",match:/\b(skin|pressure|sore|redness|bruise|wound|mark)\b/i,questions:[{id:"where",ask:"Where on the body is the mark or sore?"},{id:"looks",ask:"What does it look like?"},{id:"pain",ask:"Are they sore there?"},{id:"found",ask:"When did you notice it?"},{id:"done",ask:"What have you done so far?"},{id:"next",ask:"What do you think needs to happen next?"}]},{id:"wellbeing",label:"Wellbeing check",match:/\b(wellbeing|well-being|mood|check(?:ed)? on|how .+ (?:is|are))\b/i,questions:[{id:"mood",ask:"How is their mood and engagement?"},{id:"eat",ask:"Eating and drinking okay?"},{id:"mobility",ask:"Any mobility notes?"},{id:"care",ask:"Any personal care done or needed?"},{id:"concerns",ask:"Anything worrying you?"},{id:"plan",ask:"What should the next shift know?"}]},{id:"general",label:"Care situation",match:/./,questions:[{id:"what",ask:"In one line, what happened?"},{id:"when",ask:"When was this?"},{id:"where",ask:"Where?"},{id:"response",ask:"What did you do?"},{id:"now",ask:"How is the person now?"},{id:"informed",ask:"Who knows / who still needs to know?"},{id:"next",ask:"What needs to happen next?"}]}],wi=/^(?:(?:hi|hii|hey|hello|yo|ok|okay|hiya|oi|excuse me)\s+)+(?:care\s*talk|caretalk|don|dawn|done|dom|dun|donn)\b[, ]*/i,bi=/^(?:care\s*talk|caretalk|don|dawn|done|dom|dun|donn)\b[, ]*/i;function st(e){return String(e||"").toLowerCase().replace(/["""']/g,"").replace(/[^\w\s']/g," ").replace(/\bcare\s*talk\b/g,"caretalk").replace(/\b(dawn|done|dom|dun|donn|donnie|donald)\b/g,"don").replace(/\s+/g," ").trim()}function Oe(e){const t=st(e);return/^(?:(?:(?:hi|hii|hey|hello|yo|ok|okay|hiya|oi)\s+)?(?:caretalk|don)\s*)+$/.test(t)}function F(e){let t=String(e||"").trim();t=t.replace(wi,"").replace(bi,"").trim();const n=st(t);return n.startsWith("caretalk ")&&(t=t.replace(/^(?:care\s*talk|caretalk)\s+/i,"").trim()),n.startsWith("don ")&&(t=t.replace(/^(?:don|dawn|done)\s+/i,"").trim()),t}function Ft(e){const t=String(e||"");if(/\bcare\s*talk\b/i.test(t)||/\bcaretalk\b/i.test(t)||/\bdon\b/i.test(t)||/\b(?:hi|hey|hello|yo|ok|okay|hiya|oi|excuse me)\s+(?:dawn|done|dom|dun|donn|donnie|donald|dan|donn?e)\b/i.test(t)||/^(?:dawn|done|dom|dun|donn|donald)\b/i.test(t.trim())||/,\s*(?:dawn|done|dom|dun|donn|donald)\b/i.test(t))return!0;const n=st(t);return!!/^(?:(?:hi|hii|hey|hello|yo|ok|okay|hiya|oi)\s+)?(?:caretalk|don)(?:\s+(?:caretalk|don))*$/.test(n)}function St(e){const t=F(e).trim();return t?Be(t).id!=="general"||/\b(help|need|advice|record|document|fell|fall|hurt|pain|chok|bleed|resident|patient|check|incident|report)\b/i.test(t)?!0:t.split(/\s+/).filter(Boolean).length>=4:!1}function or(e){return!Ft(e)||Oe(e)?!1:!St(e)}const ki=new Set(["i","we","you","he","she","it","they","them","him","her","his","my","our","your","the","a","an","this","that","these","those","someone","somebody","anyone","anybody","everyone","everybody","resident","client","service","user","carer","nurse","staff","today","just","please","okay","ok","alright","don","caretalk","hey","hi","hello","yes","yeah","yep","yup","no","nope","nah","not","nothing","something","else","fall","distress","swallow","skin","mood","wellbeing","medication","meds","urgent","safe","unsafe","danger","right","got","still","here","there","when","where","what","why","how","who","which","because","about","with","for","from","after","before","during","maybe","kind","sort","really","actually","saying","said","tell","told","need","help","advice","report","record","document"].map(e=>e.toLowerCase()));function Fe(e){const t=String(e||"").trim();return!(!t||t.length<2||t.length>24||/\d/.test(t)||ki.has(t.toLowerCase())||!/^[A-Za-z][A-Za-z'-]*$/.test(t))}function Ke(e,{carerName:t=""}={}){const n=F(e);if(!n)return"";function i(s){return!s||!Fe(s)||t&&at(s,t)?"":s}const r=[/(?:with|for|about|attending(?: to)?|resident|service user|client|called)\s+([A-Z][a-z]+(?:\s+[A-Z][a-z]+)?)/,/\b([A-Z][a-z]+)\s+(?:just |has |had |fell|was |is |seems |refused |won'?t )/];for(const s of r){const l=n.match(s);if(l){const d=i(l[1].split(/\s+/)[0]);if(d)return d}}const o=n.match(/\b([a-z]{2,})\s+(?:just |has |had |fell|seems|refused|won'?t)/i);if(o){const s=i(Fe(o[1])?o[1].charAt(0).toUpperCase()+o[1].slice(1).toLowerCase():"");if(s)return s}const a=n.match(/^([A-Za-z][A-Za-z'-]{1,23})(?:\s+(?:please|thanks))?[.!?]?$/);if(a){const s=i(a[1].charAt(0).toUpperCase()+a[1].slice(1).toLowerCase());if(s)return s}return""}function Be(e){const t=F(e);for(const n of ke)if(n.id!=="general"&&n.match.test(t))return n;return ke.find(n=>n.id==="general")}function vi(e,t){return t&&/^Where did it happen/i.test(e)?`Where was ${t}? Bedroom, bathroom, corridor…?`:e}function $i({opening:e,carer:t,carerProfileName:n=""}){const i=e.trim(),r=Be(i);let a=Ke(i,{carerName:n||t});const s=F(i)||i,l=fi(r.id,s),d=r.questions.map(u=>({...u,ask:vi(u.ask,a)}));return{id:`sess_${Date.now()}`,opening:s,carer:t||"Staff",person:a,scenarioId:r.id,scenarioLabel:r.label,advice:l,questions:d,answers:{},voiceNotes:[{at:new Date().toISOString(),text:s}],step:0,phase:"advice",adviceAwaitingOk:!1,docTurn:"waiting_answer",pendingAnswer:"",pendingDocumented:"",correctionNote:"",recordedAt:new Date().toLocaleString("en-GB")}}function Ii(){const e=["I’m here. Do you need any help?","Hi — it’s careTalk. What do you need?","Listening. Are you okay — want help documenting something, or advice on what to do next?"];return e[Math.floor(Math.random()*e.length)]}function lt(e){return e.questions[e.step]||null}function Ai(e,t,{person:n=""}={}){const i=String(t||"").trim().replace(/\s+/g," ");if(!i)return"—";const r=String((e==null?void 0:e.ask)||"Note").replace(/\?$/,"").trim();return`${n?`Service user ${n}: `:""}${r} — ${i}`}function cn(e){const t=String(e||"").trim().toLowerCase();return!t||/\b(no|nope|not right|wrong|incorrect|change)\b/.test(t)&&!/^yes\b/.test(t)?!1:/^(yes|yeah|yep|yup|correct|right|spot on|that'?s right|that is right|good|fine|ok|okay|absolutely|affirmative)\b/.test(t)}function dn(e){const t=String(e||"").trim().toLowerCase();return/^(no|nope|nah|not quite|wrong|incorrect)\b/.test(t)||/\b(not right|that'?s wrong|change that|needs changing)\b/.test(t)}function un(e){let t=String(e||"").trim();return t=t.replace(/^(no(,)?\s*)(actually|i mean|it'?s|it is)?\s*/i,"").trim(),t||String(e||"").trim()}function Li(e){return String(e||"").trim().length<2}function Si(e,{raw:t,documented:n}){const i=lt(e);if(!i)return{session:e,done:!0};const r=String(n||t||"").trim();return e.answers[i.id]=r,e.voiceNotes||(e.voiceNotes=[]),e.voiceNotes.push({at:new Date().toISOString(),text:t?`${i.id} (voice): ${t}`:`${i.id}: ${r}`}),n&&t&&n!==t&&e.voiceNotes.push({at:new Date().toISOString(),text:`${i.id} (record): ${r}`}),e.step+=1,e.pendingAnswer="",e.pendingDocumented="",e.docTurn="waiting_answer",{session:e,done:e.step>=e.questions.length}}function Ti(e,t){if(!e)return;const n=String(t||"").trim();n&&(e.voiceNotes||(e.voiceNotes=[]),e.voiceNotes.push({at:new Date().toISOString(),text:n}))}function ar(e,t){const n=e.questions.map(r=>{const o=e.answers[r.id];return o?`<li><span class="muted-line">${t(r.ask)}</span><br /><strong>${t(o)}</strong></li>`:""}).filter(Boolean).join(""),i=e.correctionNote?`<li><span class="muted-line">Correction noted</span><br /><strong>${t(e.correctionNote)}</strong></li>`:"";return n||i?`<ul class="record-review">${n}${i}</ul>`:"<p>Nothing captured yet.</p>"}function Ci(e){return Ei(e)}function Ei(e){var r;const t=e.answers,n=e.person||"the resident",i=["SUPPORT WORKER REPORT — GENERATED BY careTalk","========================================",`Service user: ${e.person||"—"}`,`Support worker / carer: ${e.carer}`,`Incident / topic: ${e.scenarioLabel}`,`Date & time recorded: ${e.recordedAt}`,`Session id: ${e.id}`,"","1. OPENING STATEMENT (VOICE)",e.opening||"—","","2. WHAT HAPPENED (STRUCTURED)"];if(e.scenarioId==="fall")i.push(`${n} had a fall${t.when?` (${t.when})`:""}${t.where?` — location: ${t.where}`:""}.`,t.how?`Beforehand: ${t.how}.`:"",t.witnessed?`Witnessed / presence: ${t.witnessed}.`:"","","3. INJURY / PRESENTATION",t.injury||"—","","4. IMMEDIATE RESPONSE",t.response||"—","","5. CURRENT CONDITION",t.obs||"—","","6. NOTIFICATIONS",t.informed||"—","","7. SAFETY / FOLLOW-UP",t.prevent||"—");else for(const o of e.questions)i.push(`${o.ask}`,t[o.id]||"—","");return i.push("","8. VOICE NOTES (VERBATIM CAPTURE)",...(e.voiceNotes||[]).map((o,a)=>`${a+1}. [${new Date(o.at).toLocaleTimeString("en-GB")}] ${o.text}`),"","9. NARRATIVE SUMMARY FOR AGENCY"),e.scenarioId==="fall"?i.push([`${n} had a fall${t.when?` ${t.when}`:""}${t.where?` at ${t.where}`:""}.`,t.how?`Prior activity: ${t.how}.`:null,t.witnessed?`Presence: ${t.witnessed}.`:null,t.injury?`Injury/marks: ${t.injury}.`:null,t.response?`Actions: ${t.response}.`:null,t.obs?`Now: ${t.obs}.`:null,t.informed?`Informed: ${t.informed}.`:null,t.prevent?`Safety: ${t.prevent}.`:null].filter(Boolean).join(" ")):i.push(e.questions.map(o=>`${o.ask.replace(/\?$/,"")}: ${t[o.id]||"not stated"}`).join(". ")+"."),i.push("","10. SAFE PRACTICE REMINDERS APPLIED (careTalk)",`Do: ${(e.advice.do||[]).slice(0,4).join(" | ")}`,`Don’t: ${(e.advice.dont||[]).slice(0,4).join(" | ")}`),(r=e.advice.trainedText)!=null&&r.length&&i.push("","11. HOME-TRAINED KNOWLEDGE USED",...e.advice.trainedText),e.correctionNote&&i.push("","CORRECTION / AMENDMENT (VOICE)",e.correctionNote),i.push("",Ri),i.filter((o,a,s)=>!(o===""&&s[a-1]==="")).join(`
19
  `)}const Ri="Note: careTalk supports documentation and safe-practice reminders from adult care / support-worker training themes (including moving & assisting, dysphagia, ligature awareness, Oliver McGowan, PMVA/MAPA principles, HSWA). Follow local policy and clinical advice. This report is for the care agency / nurse in charge.",Ht=[{id:"medication_refusal",label:"Medication refusal",match:/\b((refuse[ds]?|refusing|won'?t take|will not take|not taking|declined?|spit(?:ting)? out).{0,40}\b(medicine|medication|meds|tablet|tablets|pill|pills|dose|mar)\b|\b(medicine|medication|meds|tablet|tablets|pill|pills).{0,40}\b(refuse[ds]?|refusing|won'?t|will not|not taking|declined?)\b)/i,keywords:["medicine","medication","meds","refuse","refusal","refused","tablet","tablets","pill","mar"]}];function Xe(e){const t=String(e||"");for(const n of Ht)if(n.match.test(t))return n;return null}function sr(e,t=""){if(!e)return[];`${t} ${e.label}`.toLowerCase();const n=de(),i=[];for(const r of n){let o=0;const a=`${r.title} ${r.body} ${(r.keywords||[]).join(" ")} ${(r.doList||[]).join(" ")}`.toLowerCase();for(const s of e.keywords)a.includes(s)&&(o+=2),(r.keywords||[]).includes(s)&&(o+=2);/\b(refus|not taking|declin|won'?t take)\b/i.test(a)&&(o+=3),/\b(medicine|medication|meds|tablet|mar)\b/i.test(a)&&(o+=2),(r.doList||[]).length>=1&&(o+=2),r.body&&r.body.length>60&&(o+=1),o>=5&&i.push({entry:r,score:o})}return i.sort((r,o)=>o.score-r.score).map(r=>r.entry)}function Tt(e,t=""){return sr(e,t).some(i=>(i.doList||[]).length>=1||(i.body||"").length>=80)}function lr(e,t=""){const i=String(e||t||"this subject").trim().replace(/\s+/g," ").slice(0,80)||"this subject";return{id:`unsure_${i.toLowerCase().replace(/[^a-z0-9]+/g,"_").replace(/^_|_$/g,"").slice(0,40)||"subject"}`,label:i,keywords:i.toLowerCase().split(/\W+/).filter(o=>o.length>3).slice(0,8),question:`careTalk was not sure about this subject: ${i}. What should carers do?`}}function Di(e=""){const t=String(e||"").toLowerCase();if(!t||t.split(/\s+/).length<3)return!1;const n=t.split(/\W+/).filter(i=>i.length>3);return n.length?de().some(i=>{const r=`${i.title} ${i.body} ${(i.keywords||[]).join(" ")}`.toLowerCase();return n.filter(a=>r.includes(a)).length>=2&&((i.doList||[]).length>=1||(i.body||"").length>=60)}):!1}function ct(){return nr()}function qt(e){si(e)}function cr(){return ct().filter(e=>e.status==="unresolved")}function dr({topic:e,utterance:t,person:n="",carer:i=""}){const r=ct(),o=Date.now()-1440*60*1e3,a=r.find(l=>l.status==="unresolved"&&l.topicId===e.id&&(l.person||"").toLowerCase()===(n||"").toLowerCase()&&new Date(l.createdAt).getTime()>o);if(a)return{incident:a,created:!1};const s={id:`inc_${Date.now()}`,status:"unresolved",topicId:e.id,topicLabel:e.label,question:e.question||(e.id==="medication_refusal"?`What should carers do when ${n||"a client"} refuses / does not take their medicine?`:`careTalk was unsure about: ${e.label}. What should carers do?`),person:n||"",carer:i||"",utterance:String(t||"").trim(),createdAt:new Date().toISOString(),resolvedAt:null,resolvedBy:null,knowledgeId:null,agencyNotified:!1};return r.unshift(s),qt(r),{incident:s,created:!0}}function xi(e,{knowledgeId:t=null,note:n=""}={}){const i=ct(),r=i.findIndex(o=>o.id===e);if(r<0)throw new Error("Incident not found");return i[r]={...i[r],status:"resolved",resolvedAt:new Date().toISOString(),resolvedBy:"Head nurse",knowledgeId:t,resolveNote:n},qt(i),i[r]}async function ur(e){const t=it(),n=["careTalk — TRAINING REQUEST (UNRESOLVED)","===================================",`Incident id: ${e.id}`,`Topic: ${e.topicLabel}`,"Question careTalk could not answer from training:",e.question,"",`Person / client: ${e.person||"—"}`,`Reported by carer: ${e.carer||"—"}`,`Carer said: ${e.utterance||"—"}`,`Logged: ${new Date(e.createdAt).toLocaleString("en-GB")}`,"","careTalk told the carer he will ask for training on this.","Please open Give careTalk more knowledge in careTalk, resolve this incident, and add clear do/don’t guidance.","",`Agency: ${t.name}`].join(`
20
  `),i={id:`gap_${Date.now()}`,type:"don.training_gap",at:new Date().toISOString(),incidentId:e.id,agencyName:t.name,agencyEmail:t.email,report:n,channels:["outbox"]};if(t.webhookUrl)try{(await fetch(t.webhookUrl,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(i)})).ok&&i.channels.push("webhook")}catch(a){i.webhookError=(a==null?void 0:a.message)||"webhook failed"}if(t.email){const a=encodeURIComponent(`careTalk needs training — ${e.topicLabel}${e.person?` — ${e.person}`:""}`),s=encodeURIComponent(n.slice(0,1800)),l=`mailto:${encodeURIComponent(t.email)}?subject=${a}&body=${s}`;i.mailto=l,i.channels.push("email");try{const d=document.createElement("a");d.href=l,d.rel="noopener",document.body.appendChild(d),d.click(),d.remove()}catch{}}tr(i);const r=ct(),o=r.findIndex(a=>a.id===e.id);return o>=0&&(r[o].agencyNotified=!0,qt(r)),{packet:i,agency:t,report:n}}const Pi=[{id:"mood",label:"Mood & engagement",voice:["mood","engagement","wellbeing"],prompt:"How is their mood and engagement right now?"},{id:"mobility",label:"Mobilisation",voice:["mobility","mobilisation","transfer","zimmer","hoist"],prompt:"How did they mobilise / transfer?"},{id:"nutrition",label:"Nutrition & fluids",voice:["nutrition","hydration","ate","drank","meal"],prompt:"What did they eat and drink?"},{id:"personal",label:"Personal care",voice:["personal care","washed","dressed","continence","pad"],prompt:"What personal care was completed?"},{id:"skin",label:"Skin integrity",voice:["skin","pressure","sore","redness"],prompt:"Any skin changes or pressure areas?"},{id:"clinical",label:"Clinical / PRN",voice:["medication","prn","obs","pain","gp"],prompt:"Any medication, pain, or clinical observations?"},{id:"risk",label:"Risks & safety",voice:["risk","fall","wander","safeguarding","incident"],prompt:"Any safety or safeguarding concerns?"},{id:"plan",label:"Plan / escalate",voice:["plan","action","escalate","handover"],prompt:"What should happen next?"}],Oi=[{key:"resident",re:/(?:resident|service user|client|with)\s+([A-Z][a-z]+(?:\s+[A-Z][a-z]+)?)/i},{key:"when",re:/(?:at|around|about)\s+(\d{1,2}(?::\d{2})?\s*(?:am|pm)?|\d{1,2}\s*(?:am|pm)|this morning|this afternoon|this evening|overnight|during night shift)/i}],Bi=[["fall","Falls risk"],["slipped","Falls risk"],["wander","Exit-seeking / wandering"],["exit-seeking","Exit-seeking / wandering"],["exit seeking","Exit-seeking / wandering"],["distress","Emotional distress"],["agitated","Emotional distress"],["aggressive","Behavioural escalation"],["chok","Choking / swallow risk"],["pressure","Skin integrity watch"],["sore","Skin integrity watch"],["refus","Care preference / declined support"],["declined","Care preference / declined support"],["low mood","Mood concern"],["confused","Cognitive change"],["delirium","Cognitive change"],["safeguard","Safeguarding pathway"],["bruise","Injury / mark observed"],["unwitnessed","Unwitnessed event — verify"]],Ni=[[/refused care/gi,"declined care; support and choices were offered"],[/refused/gi,"declined"],[/non[- ]compliant/gi,"needed extra encouragement and adapted support"],[/aggressive resident/gi,"showed distressed behaviour"],[/wandering/gi,"walking with purpose / exit-seeking"],[/fed/gi,"supported with meals"],[/toileted/gi,"supported with continence care"],[/put to bed/gi,"supported to settle for bed"],[/challenging behaviour/gi,"distressed behaviour"]];function Ct(e){const t=e.trim().replace(/\s+/g," ");return t?t.charAt(0).toUpperCase()+t.slice(1):""}function ye(e,t,n=[]){const i=e.toLowerCase();for(const r of t){const o=i.indexOf(r);if(o===-1)continue;let a=e.slice(o+r.length).replace(/^[\s:,-]+/,""),s=a.length;for(const d of n){const u=a.toLowerCase().indexOf(d);u!==-1&&(s=Math.min(s,u))}const l=a.slice(0,s).trim().replace(/[.;]+$/,"");if(l)return Ct(l)}return""}function Ui(e){let t=e||"";for(const[n,i]of Ni)t=t.replace(n,i);return t}function pn(e){const t=(e||"").toLowerCase();return Pi.map(n=>({...n,covered:n.voice.some(i=>t.includes(i))}))}function _i(e,t){const n=t.filter(o=>!o.covered).map(o=>o.label),i=e.flags.filter(o=>!/No acute/i.test(o)),r=[];return e.resident?r.push(`${e.resident}: ${e.mood||e.narrative.slice(0,90)||"see full note"}`):e.narrative&&r.push(e.narrative.slice(0,110)),i.length&&r.push(`Watch: ${i.slice(0,3).join("; ")}`),e.actions?r.push(`Next: ${e.actions}`):n.length&&r.push(`Still to capture: ${n.slice(0,3).join(", ")}`),e.clinical&&r.push(`Clinical: ${e.clinical}`),r.slice(0,4)}function ji(e){const t=e.flags.filter(n=>/safeguard|fall|chok|injury|behavioural|skin integrity|cognitive/i.test(n));return t.length?{title:"Nurse-in-charge brief",lines:[`Person: ${e.resident||"Resident (name not yet captured)"}`,`Flags: ${t.join("; ")}`,`Facts noted: ${e.risks||e.narrative||"See body of note"}`,`Already done: ${e.actions||"Document response and who was informed"}`,"Ask: Do we need GP / 111 / safeguarding referral / family call now?"]}:null}function dt(e,t="wellbeing"){const n=Ui(e||""),i=n.replace(/\s+/g," ").trim(),r={resident:"",when:"",mood:"",mobility:"",nutrition:"",care:"",clinical:"",risks:"",actions:"",flags:[],narrative:"",confidence:0,coverage:pn(""),handover:[],escalation:null,dignityApplied:n!==(e||""),noteType:t};if(!i)return r;let o="",a="";for(const{key:x,re:z}of Oi){const R=i.match(z);R&&(x==="resident"&&(o=R[1]),x==="when"&&(a=Ct(R[1])))}if(!o){const x=i.match(/\b([A-Z][a-z]+)\s+(?:was|is|appeared|seemed|had|ate|declined|refused)\b/);x&&(o=x[1])}const s=ye(i,["mood","appeared","seemed","engagement","engaged","wellbeing"],["mobility","transfer","ate","drink","medication","action","plan","risk"]),l=ye(i,["mobility","mobilis","transfer","zimmer","frame","hoist","walked"],["ate","drink","nutrition","hydration","personal care","medication","action"]),d=ye(i,["nutrition","hydration","ate","eaten","drank","fluid","meal","lunch","breakfast","dinner","supper"],["personal care","washed","continence","medication","action","plan"]),u=ye(i,["personal care","washed","shower","continence","pad","skin","dressed"],["medication","clinical","obs","action","plan","risk"]),f=ye(i,["medication","prn","clinical","obs","blood pressure","temperature","gp","nurse","pain"],["action","plan","next","risk","incident"]),g=ye(i,["risk","incident","concern","safeguarding","near miss"],["action","plan","we ","staff "]),w=ye(i,["action","plan","we ","staff ","escalated","informed","documented","handover"],[]),y=[],k=i.toLowerCase();for(const[x,z]of Bi)k.includes(x)&&!y.includes(z)&&y.push(z);!y.length&&/settled|comfortable|no concerns|stable/i.test(i)&&y.push("No acute escalation flagged");const v=a||"this shift",$=[];t==="family"?$.push(o?`${o} has been supported ${v}.`:`Your relative has been supported ${v}.`):t==="handover"?$.push(o?`Handover — ${o} (${v}).`:`Handover note (${v}).`):$.push(o?`${o} was reviewed ${v}.`:`Resident reviewed ${v}.`);const C=[s,l,d,u,f].filter(Boolean).map(x=>x.endsWith(".")?x:`${x}.`);$.push(...C),g&&$.push(`Risks/incidents: ${g}${g.endsWith(".")?"":"."}`),w&&$.push(`Actions/plan: ${w}${w.endsWith(".")?"":"."}`),!C.length&&!g&&!w&&$.push(Ct(i)+(i.endsWith(".")?"":"."));const D=[o,a,s,l,d,u,f,g,w].filter(Boolean).length,re=Math.min(98,35+D*8+Math.min(20,Math.floor(i.length/40))),N={resident:o,when:a,mood:s,mobility:l,nutrition:d,care:u,clinical:f,risks:g,actions:w,flags:y,narrative:$.join(" ").replace(/\s+/g," ").trim(),confidence:re,noteType:t,dignityApplied:n!==(e||"").replace(/\s+/g," ").trim()};return N.coverage=pn(i),N.handover=_i(N,N.coverage),N.escalation=ji(N),N}const He={users:"don.users",sessionUser:"don.session.userId"},Mi=1800*1e3;function ve(e){const t=`don.user|${String(e||"").trim()}`;let n=2166136261;for(let i=0;i<t.length;i+=1)n^=t.charCodeAt(i),n=Math.imul(n,16777619);return(n>>>0).toString(16)}function Fi(e,t){try{const n=localStorage.getItem(e);return n?JSON.parse(n):t}catch{return t}}function Hi(e,t){localStorage.setItem(e,JSON.stringify(t))}function qi(e){const t={...e};return t.emailVerified===void 0&&(t.emailVerified=t.status==="approved"),t.requestedRole||(t.requestedRole=t.role==="admin"?"admin":"carer"),t}function O(){return Fi(He.users,[]).map(qi)}function le(e){Hi(He.users,Array.isArray(e)?e:[])}function q(e){if(!e)return null;const{passwordHash:t,verificationCodeHash:n,verificationExpiresAt:i,...r}=e;return r}function Wt(){return sessionStorage.getItem(He.sessionUser)||""}function T(){const e=Wt();if(!e)return null;const t=q(O().find(n=>n.id===e)||null);return t&&t.status!=="approved"?(ie(""),null):t}function ie(e){e?sessionStorage.setItem(He.sessionUser,e):sessionStorage.removeItem(He.sessionUser)}function pr(){ie("")}function ut(e=T()){return!!(e&&e.status==="approved")}function Le(e=T()){return ut(e)&&e.role==="admin"}function fr(e=T()){return ut(e)}function qe(e,t=T()){return ut(t)?e==="learn"?!0:e==="train"||e==="reports"?Le(t):!1:!1}function Wi(){return String(Math.floor(1e5+Math.random()*9e5))}function Gi(e,t){const n=e[t];n.requestedRole!=="admin"&&n.role!=="admin"?e[t]={...n,status:"approved",role:"carer",emailVerified:!0,approvedAt:new Date().toISOString(),approvedBy:"email_verified",verificationCodeHash:null,verificationExpiresAt:null}:e[t]={...n,emailVerified:!0,verificationCodeHash:null,verificationExpiresAt:null}}function gr(e){const t=String(e||"").trim().toLowerCase(),n=O(),i=n.findIndex(l=>l.email===t);if(i<0)throw new Error("No registration found for that email");const r=Wi();n[i].verificationCodeHash=ve(r),n[i].verificationExpiresAt=new Date(Date.now()+Mi).toISOString(),le(n);const o=encodeURIComponent("careTalk — verify your email"),a=encodeURIComponent(`Your careTalk verification code is: ${r}
21
 
assets/main-C6D7HP12.js ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ import"./modulepreload-polyfill-B5Qt9EMX.js";import{e as F,A as S}from"./subscribers-DauO8VtY.js";const I="pd3rvr@icloud.com",E=`https://formsubmit.co/ajax/${encodeURIComponent(I)}`;async function $({subject:e,fields:t}){const n={...t,_subject:e,_template:"table",_captcha:"false",_honey:""};try{const a=await fetch(E,{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify(n)});let r=null;try{r=await a.json()}catch{r=null}if(!a.ok){const o=r&&(r.message||r.error)||`Mail forward failed (${a.status})`;return{ok:!1,error:String(o)}}return r&&r.error?{ok:!1,error:String(r.error)}:{ok:!0}}catch(a){return{ok:!1,error:a&&a.message||"Network error while sending feedback"}}}const y="caretalk.landing.feedback";function u(){try{const e=localStorage.getItem(y),t=e?JSON.parse(e):[];return Array.isArray(t)?t:[]}catch{return[]}}function p(e){localStorage.setItem(y,JSON.stringify(e.slice(0,40)))}function d(e){return String(e||"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}function f(e){return e==="assistant"?"Care assistant / support worker":e==="supervisor"?"Supervisor / manager / nurse":"Other / interested visitor"}function m(e){const t=document.getElementById("feedbackWall"),n=document.getElementById("feedbackWallEmpty");if(!t)return;const a=e.slice(0,8);t.innerHTML=a.map(r=>{const o=r.at?new Date(r.at).toLocaleDateString("en-GB",{day:"numeric",month:"short",year:"numeric"}):"",s=[r.name,r.org].filter(Boolean).join(" · ");return`<article class="feedback-item">
2
+ <p class="feedback-meta">${d(f(r.role))}${o?` · ${d(o)}`:""}</p>
3
+ <p class="feedback-body">${d(r.message)}</p>
4
+ ${s?`<p class="feedback-who">${d(s)}</p>`:""}
5
+ </article>`}).join(""),n&&(n.hidden=a.length>0)}function x(e){return{form:"careTalk landing feedback",version:String(e.version||S),role:f(e.role),name:e.name||"(not given)",organisation:e.org||"(not given)",submitted_at:e.at||new Date().toISOString(),message:e.message||""}}function c(e,{ok:t,text:n}){e&&(e.hidden=!1,e.className=`feedback-status ${t?"ok":"error"}`,e.textContent=n)}function A(){const e=document.getElementById("feedbackForm"),t=document.getElementById("feedbackStatus"),n=e==null?void 0:e.querySelector('button[type="submit"]');e&&(m(u()),e.addEventListener("submit",async a=>{var b,k;a.preventDefault();const r=new FormData(e),o=String(r.get("role")||"").trim(),s=String(r.get("message")||"").trim(),w=String(r.get("name")||"").trim(),v=String(r.get("org")||"").trim();if(String(r.get("_honey")||"").trim()){c(t,{ok:!0,text:"Thanks — your note was sent."}),e.reset();return}if(!o||s.length<12){c(t,{ok:!1,text:"Please choose your role and write at least a short note (12+ characters)."});return}const i={id:`fb_${Date.now()}`,at:new Date().toISOString(),version:S,role:o,name:w,org:v,message:s};n&&(n.disabled=!0,n.textContent="Sending…"),c(t,{ok:!0,text:"Sending your feedback…"});const l=await $({subject:`[careTalk feedback] ${f(i.role)} — v${i.version}`,fields:x(i)});if(n&&(n.disabled=!1,n.textContent="Send feedback"),!l.ok){const h=[i,...u()];p(h),m(h),c(t,{ok:!1,text:(b=l.error)!=null&&b.includes("confirm")||(k=l.error)!=null&&k.includes("Activation")?"Almost there — check pd3rvr@icloud.com for a one-time FormSubmit confirmation, then send again.":`Saved on this device, but email send failed (${l.error||"unknown error"}). Please try again.`});return}const g=[i,...u()];p(g),m(g),e.reset(),c(t,{ok:!0,text:"Thanks — your feedback was emailed to the careTalk inbox and saved on this device."})}))}function B(){const e=document.getElementById("subscribeForm"),t=document.getElementById("subscribeStatus");e&&e.addEventListener("submit",n=>{n.preventDefault();const a=new FormData(e),r=String(a.get("email")||"").trim(),o=String(a.get("name")||"").trim(),s=F({email:r,name:o,source:"landing"});if(!s.ok){t&&(t.hidden=!1,t.className="feedback-status error",t.textContent=s.error);return}e.reset(),t&&(t.hidden=!1,t.className="feedback-status ok",t.textContent=s.created?"You’re on the list — we’ll use this email for careTalk update notes on this device.":"You’re already subscribed with that email on this device.")})}typeof document<"u"&&(B(),A());
assets/main-nC7DZYuB.js DELETED
@@ -1,6 +0,0 @@
1
- import"./modulepreload-polyfill-B5Qt9EMX.js";import{e as p,A as i}from"./subscribers-BDwoJ2Wh.js";const g="caretalk.landing.feedback",h="pd3rvr@icloud.com";function u(){try{const e=localStorage.getItem(g),t=e?JSON.parse(e):[];return Array.isArray(t)?t:[]}catch{return[]}}function k(e){localStorage.setItem(g,JSON.stringify(e.slice(0,40)))}function c(e){return String(e||"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}function l(e){return e==="assistant"?"Care assistant / support worker":e==="supervisor"?"Supervisor / manager / nurse":"Other / interested visitor"}function f(e){const t=document.getElementById("feedbackWall"),n=document.getElementById("feedbackWallEmpty");if(!t)return;const a=e.slice(0,8);t.innerHTML=a.map(o=>{const s=o.at?new Date(o.at).toLocaleDateString("en-GB",{day:"numeric",month:"short",year:"numeric"}):"",r=[o.name,o.org].filter(Boolean).join(" · ");return`<article class="feedback-item">
2
- <p class="feedback-meta">${c(l(o.role))}${s?` · ${c(s)}`:""}</p>
3
- <p class="feedback-body">${c(o.message)}</p>
4
- ${r?`<p class="feedback-who">${c(r)}</p>`:""}
5
- </article>`}).join(""),n&&(n.hidden=a.length>0)}function S(e){const t=encodeURIComponent(`[careTalk feedback] ${l(e.role)} — v${e.version||i}`),n=encodeURIComponent([`careTalk feedback (v${e.version||i})`,"",`Role: ${l(e.role)}`,e.name?`Name: ${e.name}`:null,e.org?`Organisation: ${e.org}`:null,e.at?`Submitted: ${e.at}`:null,"","How careTalk might help:",e.message||"","","— Sent from the careTalk landing page"].filter(a=>a!==null).join(`
6
- `));return`mailto:${h}?subject=${t}&body=${n}`}function w(e){const t=S(e);try{const n=document.createElement("a");n.href=t,n.rel="noopener",document.body.appendChild(n),n.click(),n.remove()}catch{window.location.href=t}}function v(){const e=document.getElementById("feedbackForm"),t=document.getElementById("feedbackStatus");e&&(f(u()),e.addEventListener("submit",n=>{n.preventDefault();const a=new FormData(e),o=String(a.get("role")||"").trim(),s=String(a.get("message")||"").trim(),r=String(a.get("name")||"").trim(),b=String(a.get("org")||"").trim();if(!o||s.length<12){t&&(t.hidden=!1,t.className="feedback-status error",t.textContent="Please choose your role and write at least a short note (12+ characters).");return}const d={id:`fb_${Date.now()}`,at:new Date().toISOString(),version:i,role:o,name:r,org:b,message:s},m=[d,...u()];k(m),f(m),e.reset(),t&&(t.hidden=!1,t.className="feedback-status ok",t.textContent="Thanks — your note is saved on this device. Your email app will open so the message can be sent to pd3rvr@icloud.com."),w(d)}))}function E(){const e=document.getElementById("subscribeForm"),t=document.getElementById("subscribeStatus");e&&e.addEventListener("submit",n=>{n.preventDefault();const a=new FormData(e),o=String(a.get("email")||"").trim(),s=String(a.get("name")||"").trim(),r=p({email:o,name:s,source:"landing"});if(!r.ok){t&&(t.hidden=!1,t.className="feedback-status error",t.textContent=r.error);return}e.reset(),t&&(t.hidden=!1,t.className="feedback-status ok",t.textContent=r.created?"You’re on the list — we’ll use this email for careTalk update notes on this device.":"You’re already subscribed with that email on this device.")})}typeof document<"u"&&(E(),v());
 
 
 
 
 
 
 
assets/{subscribers-BDwoJ2Wh.js → subscribers-DauO8VtY.js} RENAMED
@@ -1,2 +1,2 @@
1
- const m="1.1.7",l="caretalk.landing.subscribers",a="caretalk.updates.authed",g="caretalk.ops",f="b5879926";function b(e){const t=`caretalk.updates|${String(e||"").trim()}`;let s=2166136261;for(let r=0;r<t.length;r+=1)s^=t.charCodeAt(r),s=Math.imul(s,16777619);return(s>>>0).toString(16)}function i(){try{const e=localStorage.getItem(l),t=e?JSON.parse(e):[];return Array.isArray(t)?t:[]}catch{return[]}}function o(e){localStorage.setItem(l,JSON.stringify(e.slice(0,500)))}function S(e){return String(e||"").trim().toLowerCase()}function A(e){const t=S(e);return/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(t)&&t.length<=160}function I({email:e,name:t="",source:s="landing"}={}){const r=S(e);if(!A(r))return{ok:!1,error:"Please enter a valid email address."};const n=i(),c=n.find(d=>d.email===r);if(c)return{ok:!0,entry:c,created:!1};const u={id:`sub_${Date.now()}_${Math.random().toString(36).slice(2,8)}`,email:r,name:String(t||"").trim().slice(0,80),at:new Date().toISOString(),version:m,source:s};return o([u,...n]),{ok:!0,entry:u,created:!0}}function p(e){const t=i().filter(s=>s.id!==e);return o(t),t}function h(){o([])}function _(){return sessionStorage.getItem(a)==="1"}function k(e,t){const s=String(e||"").trim().toLowerCase(),r=String(t||"");return s!==g.toLowerCase()?{ok:!1,error:"Incorrect username or password."}:b(r)!==f?{ok:!1,error:"Incorrect username or password."}:(sessionStorage.setItem(a,"1"),{ok:!0})}function E(){sessionStorage.removeItem(a)}function v(e=i()){const t="email,name,subscribed_at,version,source",s=e.map(r=>[r.email,r.name||"",r.at||"",r.version||"",r.source||""].map(n=>`"${String(n).replace(/"/g,'""')}"`).join(","));return[t,...s].join(`
2
  `)}export{m as A,E as a,i as b,h as c,v as d,I as e,_ as i,p as r,k as s};
 
1
+ const m="1.1.8",l="caretalk.landing.subscribers",a="caretalk.updates.authed",g="caretalk.ops",f="b5879926";function b(e){const t=`caretalk.updates|${String(e||"").trim()}`;let s=2166136261;for(let r=0;r<t.length;r+=1)s^=t.charCodeAt(r),s=Math.imul(s,16777619);return(s>>>0).toString(16)}function i(){try{const e=localStorage.getItem(l),t=e?JSON.parse(e):[];return Array.isArray(t)?t:[]}catch{return[]}}function o(e){localStorage.setItem(l,JSON.stringify(e.slice(0,500)))}function S(e){return String(e||"").trim().toLowerCase()}function A(e){const t=S(e);return/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(t)&&t.length<=160}function I({email:e,name:t="",source:s="landing"}={}){const r=S(e);if(!A(r))return{ok:!1,error:"Please enter a valid email address."};const n=i(),c=n.find(d=>d.email===r);if(c)return{ok:!0,entry:c,created:!1};const u={id:`sub_${Date.now()}_${Math.random().toString(36).slice(2,8)}`,email:r,name:String(t||"").trim().slice(0,80),at:new Date().toISOString(),version:m,source:s};return o([u,...n]),{ok:!0,entry:u,created:!0}}function p(e){const t=i().filter(s=>s.id!==e);return o(t),t}function h(){o([])}function _(){return sessionStorage.getItem(a)==="1"}function k(e,t){const s=String(e||"").trim().toLowerCase(),r=String(t||"");return s!==g.toLowerCase()?{ok:!1,error:"Incorrect username or password."}:b(r)!==f?{ok:!1,error:"Incorrect username or password."}:(sessionStorage.setItem(a,"1"),{ok:!0})}function E(){sessionStorage.removeItem(a)}function v(e=i()){const t="email,name,subscribed_at,version,source",s=e.map(r=>[r.email,r.name||"",r.at||"",r.version||"",r.source||""].map(n=>`"${String(n).replace(/"/g,'""')}"`).join(","));return[t,...s].join(`
2
  `)}export{m as A,E as a,i as b,h as c,v as d,I as e,_ as i,p as r,k as s};
assets/{subscribers--ZiVSqeN.css → subscribers-Sa7xbXRt.css} RENAMED
@@ -1 +1 @@
1
- :root{--bg: #f4f7fb;--bg-deep: #dce6f2;--ink: #142033;--muted: #5a6b7d;--line: rgba(30, 58, 95, .16);--accent: #1e3a5f;--accent-deep: #0f2744;--accent-rgb: 30, 58, 95;--panel: #ffffff;--font: "Source Sans 3", system-ui, sans-serif;--display: "Fraunces", Georgia, serif}*{box-sizing:border-box}html{scroll-behavior:smooth}body{margin:0;min-height:100%;color:var(--ink);font-family:var(--font);background:#fff;line-height:1.55}img{max-width:100%;display:block}a{color:var(--accent-deep)}.site-header{position:absolute;inset:0 0 auto;z-index:5;display:flex;align-items:center;justify-content:space-between;gap:1rem;padding:1.1rem clamp(1rem,4vw,2.5rem)}.brand-lockup{display:inline-flex;align-items:center;gap:.65rem;text-decoration:none;color:inherit}.avatar{width:2.5rem;height:2.5rem;border-radius:50%;display:grid;place-items:center;font-family:var(--display);font-weight:700;font-size:1.2rem;color:#fff;background:linear-gradient(145deg,#3b6ea5,#1e3a5f);box-shadow:0 0 0 3px rgba(var(--accent-rgb),.16)}.brand-name{font-family:var(--display);font-weight:700;font-size:1.25rem;letter-spacing:-.02em}.nav-links{display:flex;align-items:center;gap:.75rem}.nav-links a:not(.btn){text-decoration:none;color:var(--muted);font-weight:600;font-size:.95rem}.nav-links a:not(.btn):hover{color:var(--ink)}.btn{display:inline-flex;align-items:center;justify-content:center;gap:.4rem;min-height:2.75rem;padding:.65rem 1.15rem;border-radius:999px;border:1px solid transparent;font:inherit;font-weight:700;text-decoration:none;cursor:pointer;transition:transform .18s ease,box-shadow .18s ease,background .18s ease}.btn:hover{transform:translateY(-1px)}.btn-primary{background:var(--accent-deep);color:#fff;box-shadow:0 10px 24px #0f274447}.btn-primary:hover{background:#0a1c33}.btn-ghost{background:#ffffffb8;color:var(--ink);border-color:var(--line);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px)}.btn-ghost:hover{background:#fff}.hero{position:relative;min-height:100svh;display:grid;align-items:end;overflow:hidden;background:radial-gradient(900px 520px at 18% 8%,rgba(var(--accent-rgb),.22),transparent 58%),linear-gradient(180deg,#ffffff 0%,var(--bg) 48%,var(--bg-deep) 100%)}.hero-media{position:absolute;top:0;right:0;bottom:0;left:0;z-index:0}.hero-media img{width:100%;height:100%;object-fit:cover;object-position:62% center;animation:heroDrift 18s ease-in-out infinite alternate}.hero-scrim{position:absolute;top:0;right:0;bottom:0;left:0;background:linear-gradient(90deg,#f3f6f5f2,#f3f6f5cc 42%,#f3f6f52e 72%,#f3f6f50d),linear-gradient(180deg,#ffffff38,#dde6e38c);z-index:1}.hero-copy{position:relative;z-index:2;width:min(640px,calc(100% - 2rem));margin:0 0 0 clamp(1rem,4vw,2.5rem);padding:7.5rem 0 4.5rem;animation:riseIn .7s ease both}.hero-brand{margin:0 0 .85rem;font-family:var(--display);font-size:clamp(3rem,8vw,5.4rem);line-height:.95;letter-spacing:-.035em;color:var(--ink)}.hero-theme{margin:0 0 .75rem;max-width:22ch;font-family:var(--display);font-size:clamp(1.55rem,3.6vw,2.2rem);font-weight:700;line-height:1.18;letter-spacing:-.025em;color:var(--accent-deep)}.hero-headline{margin:0;max-width:28ch;font-family:var(--font);font-size:clamp(1.05rem,2.2vw,1.2rem);font-weight:600;line-height:1.35;letter-spacing:-.01em;color:var(--ink)}.hero-lede{margin:.9rem 0 0;max-width:34ch;color:var(--muted);font-size:1.08rem}.hero-cta{display:flex;flex-wrap:wrap;gap:.75rem;margin-top:1.5rem}.version-pill{display:inline-flex;margin-top:1.35rem;padding:.3rem .7rem;border-radius:999px;border:1px solid var(--line);background:#ffffffb3;color:var(--muted);font-size:.82rem;font-weight:600;letter-spacing:.02em}.section{padding:clamp(3.5rem,8vw,5.5rem) clamp(1rem,4vw,2.5rem)}.section-inner{width:min(1080px,100%);margin:0 auto}.section h2{margin:0;font-family:var(--display);font-size:clamp(1.7rem,3.5vw,2.35rem);letter-spacing:-.025em;line-height:1.15}.section .lede{margin:.75rem 0 0;max-width:46ch;color:var(--muted);font-size:1.05rem}.band{background:radial-gradient(700px 280px at 90% 0%,rgba(var(--accent-rgb),.14),transparent 60%),linear-gradient(180deg,#fff 0%,var(--bg) 100%)}.band-alt{background:linear-gradient(180deg,var(--bg) 0%,#fff 100%)}.split{display:grid;gap:1.75rem;margin-top:2rem}@media(min-width:800px){.split{grid-template-columns:1fr 1fr;gap:2.5rem;align-items:start}}.feature-list{list-style:none;margin:0;padding:0;display:grid;gap:1rem}.feature-list li{padding:0 0 1rem;border-bottom:1px solid var(--line)}.feature-list li:last-child{border-bottom:0;padding-bottom:0}.feature-list strong{display:block;margin-bottom:.2rem;font-size:1.05rem}.feature-list span{color:var(--muted)}.steps{counter-reset:step;list-style:none;margin:2rem 0 0;padding:0;display:grid;gap:1.25rem}@media(min-width:800px){.steps{grid-template-columns:repeat(3,1fr);gap:1.5rem}}.steps li{position:relative;padding-top:2.6rem;animation:riseIn .7s ease both}.steps li:nth-child(2){animation-delay:80ms}.steps li:nth-child(3){animation-delay:.16s}.steps li:before{counter-increment:step;content:counter(step);position:absolute;top:0;left:0;width:2rem;height:2rem;border-radius:50%;display:grid;place-items:center;background:rgba(var(--accent-rgb),.12);color:var(--accent-deep);font-weight:700;font-size:.95rem}.steps strong{display:block;margin-bottom:.3rem;font-family:var(--display);font-size:1.2rem}.steps p{margin:0;color:var(--muted)}.privacy-note{margin-top:2rem;max-width:58ch;padding:1.25rem 0 0;border-top:1px solid var(--line);color:var(--muted)}.cta-band{text-align:left;background:linear-gradient(135deg,rgba(var(--accent-rgb),.14),transparent 55%),linear-gradient(180deg,#e8f3ff,#f7fbff)}.cta-band .hero-cta{margin-top:1.25rem}.subscribe-band .lede{max-width:52ch}.subscribe-form{margin-top:1.5rem;display:grid;gap:1rem;max-width:40rem}.subscribe-grid{display:grid;gap:1rem}@media(min-width:640px){.subscribe-grid{grid-template-columns:1.3fr 1fr}}.subscribe-form label{display:grid;gap:.35rem;font-weight:600;font-size:.95rem}.subscribe-form .optional{font-weight:500;color:var(--muted);font-size:.85rem}.subscribe-form input{width:100%;padding:.75rem .85rem;border:1px solid var(--line);border-radius:.65rem;background:#fff;color:var(--ink);font:inherit;font-weight:500}.subscribe-form input:focus{outline:2px solid rgba(var(--accent-rgb),.35);outline-offset:1px;border-color:rgba(var(--accent-rgb),.55)}.footer-row{width:100%;display:flex;flex-wrap:wrap;gap:.75rem 1.5rem;justify-content:space-between;align-items:flex-end}.footer-ops{display:inline-flex;align-items:center;justify-content:center;width:2rem;height:2rem;border-radius:999px;color:#1e3a5f59;transition:color .15s ease,background .15s ease}.footer-ops:hover,.footer-ops:focus-visible{color:var(--accent-deep);background:rgba(var(--accent-rgb),.12);outline:none}.admin-page .admin-wrap{max-width:56rem}.admin-card{margin-top:.5rem}.admin-card h1{margin:.35rem 0 .5rem;font-family:var(--display);font-size:clamp(1.75rem,3vw,2.25rem);letter-spacing:-.03em}.admin-privacy{margin-top:1.25rem;color:var(--muted);font-size:.9rem}.admin-panel-head{display:flex;flex-wrap:wrap;gap:1rem;justify-content:space-between;align-items:flex-start;margin-bottom:1.25rem}.admin-actions{display:flex;flex-wrap:wrap;gap:.5rem}.btn-tiny{padding:.35rem .65rem;font-size:.85rem}.subscriber-table-wrap{margin-top:1rem;overflow-x:auto;border-top:1px solid var(--line)}.subscriber-table{width:100%;border-collapse:collapse;font-size:.95rem}.subscriber-table th,.subscriber-table td{padding:.75rem .65rem;text-align:left;border-bottom:1px solid var(--line);vertical-align:top}.subscriber-table th{font-size:.8rem;text-transform:uppercase;letter-spacing:.04em;color:var(--muted)}.feedback-form{margin-top:2rem;display:grid;gap:1.25rem;max-width:40rem}.feedback-roles{margin:0;padding:0;border:0;display:grid;gap:.65rem}.feedback-roles legend{margin:0 0 .55rem;font-weight:700;font-size:1rem}.role-option{display:flex;align-items:flex-start;gap:.65rem;padding:.7rem .85rem;border-bottom:1px solid var(--line);cursor:pointer;font-weight:600}.role-option:last-of-type{border-bottom:0}.role-option input{margin-top:.2rem;accent-color:var(--accent-deep)}.feedback-grid{display:grid;gap:1rem}@media(min-width:640px){.feedback-grid{grid-template-columns:1fr 1fr}}.feedback-form label{display:grid;gap:.35rem;font-weight:600;font-size:.95rem}.feedback-form .optional{font-weight:500;color:var(--muted);font-size:.85rem}.feedback-form input,.feedback-form textarea{width:100%;padding:.75rem .85rem;border:1px solid var(--line);border-radius:.65rem;background:#fff;color:var(--ink);font:inherit;font-weight:500}.feedback-form textarea{resize:vertical;min-height:8rem}.feedback-form input:focus,.feedback-form textarea:focus{outline:2px solid rgba(var(--accent-rgb),.35);outline-offset:1px;border-color:rgba(var(--accent-rgb),.55)}.feedback-actions{display:grid;gap:.75rem;justify-items:start}.feedback-status{margin:0;font-size:.95rem;font-weight:600}.feedback-status.ok{color:#1f6a45}.feedback-status.error{color:#9b2c2c}.feedback-wall-wrap{margin-top:2.75rem;padding-top:1.75rem;border-top:1px solid var(--line)}.feedback-wall-title{margin:0;font-family:var(--display);font-size:1.25rem;letter-spacing:-.02em}.feedback-wall-empty{margin:.65rem 0 0;color:var(--muted)}.feedback-wall{margin-top:1.15rem;display:grid;gap:1rem}.feedback-item{padding:0 0 1rem;border-bottom:1px solid var(--line)}.feedback-item:last-child{border-bottom:0;padding-bottom:0}.feedback-meta{margin:0;color:var(--accent-deep);font-size:.85rem;font-weight:700}.feedback-body{margin:.35rem 0 0;color:var(--ink)}.feedback-who{margin:.35rem 0 0;color:var(--muted);font-size:.9rem}.site-footer{padding:1.5rem clamp(1rem,4vw,2.5rem) 2rem;border-top:1px solid var(--line);color:var(--muted);font-size:.92rem}.site-footer .section-inner{display:flex;flex-wrap:wrap;gap:.75rem 1.5rem;justify-content:space-between;align-items:center}.site-footer a{color:var(--muted);text-decoration:none;font-weight:600}.site-footer a:hover{color:var(--ink)}@keyframes riseIn{0%{opacity:0;transform:translateY(14px)}to{opacity:1;transform:translateY(0)}}@keyframes heroDrift{0%{transform:scale(1.02) translateZ(0)}to{transform:scale(1.06) translate3d(-1.2%,-.8%,0)}}@media(prefers-reduced-motion:reduce){html{scroll-behavior:auto}.hero-copy,.steps li,.hero-media img{animation:none}.btn:hover{transform:none}}@media(max-width:720px){.nav-about{display:none}.hero-scrim{background:linear-gradient(180deg,#ffffff8c,#f4f9ffe0 42%,#dceaf8f5)}.hero-media img{object-position:70% center}.hero-copy{width:min(100%,calc(100% - 2rem));margin:0 auto;padding-bottom:3rem}}
 
1
+ :root{--bg: #f4f7fb;--bg-deep: #dce6f2;--ink: #142033;--muted: #5a6b7d;--line: rgba(30, 58, 95, .16);--accent: #1e3a5f;--accent-deep: #0f2744;--accent-rgb: 30, 58, 95;--panel: #ffffff;--font: "Source Sans 3", system-ui, sans-serif;--display: "Fraunces", Georgia, serif}*{box-sizing:border-box}html{scroll-behavior:smooth}body{margin:0;min-height:100%;color:var(--ink);font-family:var(--font);background:#fff;line-height:1.55}img{max-width:100%;display:block}a{color:var(--accent-deep)}.site-header{position:absolute;inset:0 0 auto;z-index:5;display:flex;align-items:center;justify-content:space-between;gap:1rem;padding:1.1rem clamp(1rem,4vw,2.5rem)}.brand-lockup{display:inline-flex;align-items:center;gap:.65rem;text-decoration:none;color:inherit}.avatar{width:2.5rem;height:2.5rem;border-radius:50%;display:grid;place-items:center;font-family:var(--display);font-weight:700;font-size:1.2rem;color:#fff;background:linear-gradient(145deg,#3b6ea5,#1e3a5f);box-shadow:0 0 0 3px rgba(var(--accent-rgb),.16)}.brand-name{font-family:var(--display);font-weight:700;font-size:1.25rem;letter-spacing:-.02em}.nav-links{display:flex;align-items:center;gap:.75rem}.nav-links a:not(.btn){text-decoration:none;color:var(--muted);font-weight:600;font-size:.95rem}.nav-links a:not(.btn):hover{color:var(--ink)}.btn{display:inline-flex;align-items:center;justify-content:center;gap:.4rem;min-height:2.75rem;padding:.65rem 1.15rem;border-radius:999px;border:1px solid transparent;font:inherit;font-weight:700;text-decoration:none;cursor:pointer;transition:transform .18s ease,box-shadow .18s ease,background .18s ease}.btn:hover{transform:translateY(-1px)}.btn-primary{background:var(--accent-deep);color:#fff;box-shadow:0 10px 24px #0f274447}.btn-primary:hover{background:#0a1c33}.btn-ghost{background:#ffffffb8;color:var(--ink);border-color:var(--line);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px)}.btn-ghost:hover{background:#fff}.hero{position:relative;min-height:100svh;display:grid;align-items:end;overflow:hidden;background:radial-gradient(900px 520px at 18% 8%,rgba(var(--accent-rgb),.22),transparent 58%),linear-gradient(180deg,#ffffff 0%,var(--bg) 48%,var(--bg-deep) 100%)}.hero-media{position:absolute;top:0;right:0;bottom:0;left:0;z-index:0}.hero-media img{width:100%;height:100%;object-fit:cover;object-position:62% center;animation:heroDrift 18s ease-in-out infinite alternate}.hero-scrim{position:absolute;top:0;right:0;bottom:0;left:0;background:linear-gradient(90deg,#f3f6f5f2,#f3f6f5cc 42%,#f3f6f52e 72%,#f3f6f50d),linear-gradient(180deg,#ffffff38,#dde6e38c);z-index:1}.hero-copy{position:relative;z-index:2;width:min(640px,calc(100% - 2rem));margin:0 0 0 clamp(1rem,4vw,2.5rem);padding:7.5rem 0 4.5rem;animation:riseIn .7s ease both}.hero-brand{margin:0 0 .85rem;font-family:var(--display);font-size:clamp(3rem,8vw,5.4rem);line-height:.95;letter-spacing:-.035em;color:var(--ink)}.hero-theme{margin:0 0 .75rem;max-width:22ch;font-family:var(--display);font-size:clamp(1.55rem,3.6vw,2.2rem);font-weight:700;line-height:1.18;letter-spacing:-.025em;color:var(--accent-deep)}.hero-headline{margin:0;max-width:28ch;font-family:var(--font);font-size:clamp(1.05rem,2.2vw,1.2rem);font-weight:600;line-height:1.35;letter-spacing:-.01em;color:var(--ink)}.hero-lede{margin:.9rem 0 0;max-width:34ch;color:var(--muted);font-size:1.08rem}.hero-cta{display:flex;flex-wrap:wrap;gap:.75rem;margin-top:1.5rem}.version-pill{display:inline-flex;margin-top:1.35rem;padding:.3rem .7rem;border-radius:999px;border:1px solid var(--line);background:#ffffffb3;color:var(--muted);font-size:.82rem;font-weight:600;letter-spacing:.02em}.section{padding:clamp(3.5rem,8vw,5.5rem) clamp(1rem,4vw,2.5rem)}.section-inner{width:min(1080px,100%);margin:0 auto}.section h2{margin:0;font-family:var(--display);font-size:clamp(1.7rem,3.5vw,2.35rem);letter-spacing:-.025em;line-height:1.15}.section .lede{margin:.75rem 0 0;max-width:46ch;color:var(--muted);font-size:1.05rem}.band{background:radial-gradient(700px 280px at 90% 0%,rgba(var(--accent-rgb),.14),transparent 60%),linear-gradient(180deg,#fff 0%,var(--bg) 100%)}.band-alt{background:linear-gradient(180deg,var(--bg) 0%,#fff 100%)}.split{display:grid;gap:1.75rem;margin-top:2rem}@media(min-width:800px){.split{grid-template-columns:1fr 1fr;gap:2.5rem;align-items:start}}.feature-list{list-style:none;margin:0;padding:0;display:grid;gap:1rem}.feature-list li{padding:0 0 1rem;border-bottom:1px solid var(--line)}.feature-list li:last-child{border-bottom:0;padding-bottom:0}.feature-list strong{display:block;margin-bottom:.2rem;font-size:1.05rem}.feature-list span{color:var(--muted)}.steps{counter-reset:step;list-style:none;margin:2rem 0 0;padding:0;display:grid;gap:1.25rem}@media(min-width:800px){.steps{grid-template-columns:repeat(3,1fr);gap:1.5rem}}.steps li{position:relative;padding-top:2.6rem;animation:riseIn .7s ease both}.steps li:nth-child(2){animation-delay:80ms}.steps li:nth-child(3){animation-delay:.16s}.steps li:before{counter-increment:step;content:counter(step);position:absolute;top:0;left:0;width:2rem;height:2rem;border-radius:50%;display:grid;place-items:center;background:rgba(var(--accent-rgb),.12);color:var(--accent-deep);font-weight:700;font-size:.95rem}.steps strong{display:block;margin-bottom:.3rem;font-family:var(--display);font-size:1.2rem}.steps p{margin:0;color:var(--muted)}.privacy-note{margin-top:2rem;max-width:58ch;padding:1.25rem 0 0;border-top:1px solid var(--line);color:var(--muted)}.cta-band{text-align:left;background:linear-gradient(135deg,rgba(var(--accent-rgb),.14),transparent 55%),linear-gradient(180deg,#e8f3ff,#f7fbff)}.cta-band .hero-cta{margin-top:1.25rem}.subscribe-band .lede{max-width:52ch}.subscribe-form{margin-top:1.5rem;display:grid;gap:1rem;max-width:40rem}.subscribe-grid{display:grid;gap:1rem}@media(min-width:640px){.subscribe-grid{grid-template-columns:1.3fr 1fr}}.subscribe-form label{display:grid;gap:.35rem;font-weight:600;font-size:.95rem}.subscribe-form .optional{font-weight:500;color:var(--muted);font-size:.85rem}.subscribe-form input{width:100%;padding:.75rem .85rem;border:1px solid var(--line);border-radius:.65rem;background:#fff;color:var(--ink);font:inherit;font-weight:500}.subscribe-form input:focus{outline:2px solid rgba(var(--accent-rgb),.35);outline-offset:1px;border-color:rgba(var(--accent-rgb),.55)}.footer-row{width:100%;display:flex;flex-wrap:wrap;gap:.75rem 1.5rem;justify-content:space-between;align-items:flex-end}.footer-ops{display:inline-flex;align-items:center;justify-content:center;width:2rem;height:2rem;border-radius:999px;color:#1e3a5f59;transition:color .15s ease,background .15s ease}.footer-ops:hover,.footer-ops:focus-visible{color:var(--accent-deep);background:rgba(var(--accent-rgb),.12);outline:none}.admin-page .admin-wrap{max-width:56rem}.admin-card{margin-top:.5rem}.admin-card h1{margin:.35rem 0 .5rem;font-family:var(--display);font-size:clamp(1.75rem,3vw,2.25rem);letter-spacing:-.03em}.admin-privacy{margin-top:1.25rem;color:var(--muted);font-size:.9rem}.admin-panel-head{display:flex;flex-wrap:wrap;gap:1rem;justify-content:space-between;align-items:flex-start;margin-bottom:1.25rem}.admin-actions{display:flex;flex-wrap:wrap;gap:.5rem}.btn-tiny{padding:.35rem .65rem;font-size:.85rem}.subscriber-table-wrap{margin-top:1rem;overflow-x:auto;border-top:1px solid var(--line)}.subscriber-table{width:100%;border-collapse:collapse;font-size:.95rem}.subscriber-table th,.subscriber-table td{padding:.75rem .65rem;text-align:left;border-bottom:1px solid var(--line);vertical-align:top}.subscriber-table th{font-size:.8rem;text-transform:uppercase;letter-spacing:.04em;color:var(--muted)}.feedback-form{margin-top:2rem;display:grid;gap:1.25rem;max-width:40rem}.hp-field{position:absolute;left:-10000px;top:auto;width:1px;height:1px;overflow:hidden;opacity:0;pointer-events:none}.feedback-roles{margin:0;padding:0;border:0;display:grid;gap:.65rem}.feedback-roles legend{margin:0 0 .55rem;font-weight:700;font-size:1rem}.role-option{display:flex;align-items:flex-start;gap:.65rem;padding:.7rem .85rem;border-bottom:1px solid var(--line);cursor:pointer;font-weight:600}.role-option:last-of-type{border-bottom:0}.role-option input{margin-top:.2rem;accent-color:var(--accent-deep)}.feedback-grid{display:grid;gap:1rem}@media(min-width:640px){.feedback-grid{grid-template-columns:1fr 1fr}}.feedback-form label{display:grid;gap:.35rem;font-weight:600;font-size:.95rem}.feedback-form .optional{font-weight:500;color:var(--muted);font-size:.85rem}.feedback-form input,.feedback-form textarea{width:100%;padding:.75rem .85rem;border:1px solid var(--line);border-radius:.65rem;background:#fff;color:var(--ink);font:inherit;font-weight:500}.feedback-form textarea{resize:vertical;min-height:8rem}.feedback-form input:focus,.feedback-form textarea:focus{outline:2px solid rgba(var(--accent-rgb),.35);outline-offset:1px;border-color:rgba(var(--accent-rgb),.55)}.feedback-actions{display:grid;gap:.75rem;justify-items:start}.feedback-status{margin:0;font-size:.95rem;font-weight:600}.feedback-status.ok{color:#1f6a45}.feedback-status.error{color:#9b2c2c}.feedback-wall-wrap{margin-top:2.75rem;padding-top:1.75rem;border-top:1px solid var(--line)}.feedback-wall-title{margin:0;font-family:var(--display);font-size:1.25rem;letter-spacing:-.02em}.feedback-wall-empty{margin:.65rem 0 0;color:var(--muted)}.feedback-wall{margin-top:1.15rem;display:grid;gap:1rem}.feedback-item{padding:0 0 1rem;border-bottom:1px solid var(--line)}.feedback-item:last-child{border-bottom:0;padding-bottom:0}.feedback-meta{margin:0;color:var(--accent-deep);font-size:.85rem;font-weight:700}.feedback-body{margin:.35rem 0 0;color:var(--ink)}.feedback-who{margin:.35rem 0 0;color:var(--muted);font-size:.9rem}.site-footer{padding:1.5rem clamp(1rem,4vw,2.5rem) 2rem;border-top:1px solid var(--line);color:var(--muted);font-size:.92rem}.site-footer .section-inner{display:flex;flex-wrap:wrap;gap:.75rem 1.5rem;justify-content:space-between;align-items:center}.site-footer a{color:var(--muted);text-decoration:none;font-weight:600}.site-footer a:hover{color:var(--ink)}@keyframes riseIn{0%{opacity:0;transform:translateY(14px)}to{opacity:1;transform:translateY(0)}}@keyframes heroDrift{0%{transform:scale(1.02) translateZ(0)}to{transform:scale(1.06) translate3d(-1.2%,-.8%,0)}}@media(prefers-reduced-motion:reduce){html{scroll-behavior:auto}.hero-copy,.steps li,.hero-media img{animation:none}.btn:hover{transform:none}}@media(max-width:720px){.nav-about{display:none}.hero-scrim{background:linear-gradient(180deg,#ffffff8c,#f4f9ffe0 42%,#dceaf8f5)}.hero-media img{object-position:70% center}.hero-copy{width:min(100%,calc(100% - 2rem));margin:0 auto;padding-bottom:3rem}}
assets/{web-DyS4cL83.js → web-Bmj3o-P9.js} RENAMED
@@ -1 +1 @@
1
- import{W as e}from"./app-Cw1kdNnU.js";import"./modulepreload-polyfill-B5Qt9EMX.js";class t extends e{available(){throw this.unimplemented("Method not implemented on web.")}start(o){throw this.unimplemented("Method not implemented on web.")}stop(){throw this.unimplemented("Method not implemented on web.")}getSupportedLanguages(){throw this.unimplemented("Method not implemented on web.")}hasPermission(){throw this.unimplemented("Method not implemented on web.")}isListening(){throw this.unimplemented("Method not implemented on web.")}requestPermission(){throw this.unimplemented("Method not implemented on web.")}checkPermissions(){throw this.unimplemented("Method not implemented on web.")}requestPermissions(){throw this.unimplemented("Method not implemented on web.")}}const s=new t;export{s as SpeechRecognition,t as SpeechRecognitionWeb};
 
1
+ import{W as e}from"./app-BoDOH5ck.js";import"./modulepreload-polyfill-B5Qt9EMX.js";class t extends e{available(){throw this.unimplemented("Method not implemented on web.")}start(o){throw this.unimplemented("Method not implemented on web.")}stop(){throw this.unimplemented("Method not implemented on web.")}getSupportedLanguages(){throw this.unimplemented("Method not implemented on web.")}hasPermission(){throw this.unimplemented("Method not implemented on web.")}isListening(){throw this.unimplemented("Method not implemented on web.")}requestPermission(){throw this.unimplemented("Method not implemented on web.")}checkPermissions(){throw this.unimplemented("Method not implemented on web.")}requestPermissions(){throw this.unimplemented("Method not implemented on web.")}}const s=new t;export{s as SpeechRecognition,t as SpeechRecognitionWeb};
assets/{web-CXyz-Izy.js → web-BmkooPm-.js} RENAMED
@@ -1 +1 @@
1
- import{W as n}from"./app-Cw1kdNnU.js";import"./modulepreload-polyfill-B5Qt9EMX.js";class i extends n{async show(e){}async hide(e){}}export{i as SplashScreenWeb};
 
1
+ import{W as n}from"./app-BoDOH5ck.js";import"./modulepreload-polyfill-B5Qt9EMX.js";class i extends n{async show(e){}async hide(e){}}export{i as SplashScreenWeb};
assets/{web-CgUdoTZR.js → web-DodVBXGv.js} RENAMED
@@ -1 +1 @@
1
- import{W as t}from"./app-Cw1kdNnU.js";import"./modulepreload-polyfill-B5Qt9EMX.js";class o extends t{constructor(){super(),this.handleVisibilityChange=()=>{const e={isActive:document.hidden!==!0};this.notifyListeners("appStateChange",e),document.hidden?this.notifyListeners("pause",null):this.notifyListeners("resume",null)},document.addEventListener("visibilitychange",this.handleVisibilityChange,!1)}exitApp(){throw this.unimplemented("Not implemented on web.")}async getInfo(){throw this.unimplemented("Not implemented on web.")}async getLaunchUrl(){return{url:""}}async getState(){return{isActive:document.hidden!==!0}}async minimizeApp(){throw this.unimplemented("Not implemented on web.")}async toggleBackButtonHandler(){throw this.unimplemented("Not implemented on web.")}}export{o as AppWeb};
 
1
+ import{W as t}from"./app-BoDOH5ck.js";import"./modulepreload-polyfill-B5Qt9EMX.js";class o extends t{constructor(){super(),this.handleVisibilityChange=()=>{const e={isActive:document.hidden!==!0};this.notifyListeners("appStateChange",e),document.hidden?this.notifyListeners("pause",null):this.notifyListeners("resume",null)},document.addEventListener("visibilitychange",this.handleVisibilityChange,!1)}exitApp(){throw this.unimplemented("Not implemented on web.")}async getInfo(){throw this.unimplemented("Not implemented on web.")}async getLaunchUrl(){return{url:""}}async getState(){return{isActive:document.hidden!==!0}}async minimizeApp(){throw this.unimplemented("Not implemented on web.")}async toggleBackButtonHandler(){throw this.unimplemented("Not implemented on web.")}}export{o as AppWeb};
index.html CHANGED
@@ -22,10 +22,10 @@
22
  href="https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,550;9..144,700&family=Source+Sans+3:wght@400;600;700&display=swap"
23
  rel="stylesheet"
24
  />
25
- <script type="module" crossorigin src="./assets/main-nC7DZYuB.js"></script>
26
  <link rel="modulepreload" crossorigin href="./assets/modulepreload-polyfill-B5Qt9EMX.js">
27
- <link rel="modulepreload" crossorigin href="./assets/subscribers-BDwoJ2Wh.js">
28
- <link rel="stylesheet" crossorigin href="./assets/subscribers--ZiVSqeN.css">
29
  <link rel="manifest" href="./manifest.webmanifest"><script id="vite-plugin-pwa:register-sw" src="./registerSW.js"></script></head>
30
  <body>
31
  <header class="site-header">
@@ -59,7 +59,7 @@
59
  <a class="btn btn-primary" href="./app.html">Try the live demo</a>
60
  <a class="btn btn-ghost" href="https://github.com/2000pd3rvr/careTalk">View on GitHub</a>
61
  </div>
62
- <p class="version-pill">Version 1.1.7</p>
63
  </div>
64
  </section>
65
 
@@ -171,10 +171,19 @@
171
  <h2 id="feedback-title">Would careTalk help on your shift?</h2>
172
  <p class="lede">
173
  Care assistants and supervisors — tell us how you think this could support your day-to-day work.
174
- Your note stays on this device and opens an email draft to <strong>pd3rvr@icloud.com</strong>.
175
  </p>
176
 
177
  <form id="feedbackForm" class="feedback-form" novalidate>
 
 
 
 
 
 
 
 
 
178
  <fieldset class="feedback-roles">
179
  <legend>I am mainly a…</legend>
180
  <label class="role-option">
@@ -243,7 +252,7 @@
243
  <footer class="site-footer">
244
  <div class="section-inner footer-row">
245
  <div>
246
- <p>careTalk v1.1.7 · MIT · Not a clinical system of record</p>
247
  <p>
248
  <a href="./app.html">App</a>
249
  ·
 
22
  href="https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,550;9..144,700&family=Source+Sans+3:wght@400;600;700&display=swap"
23
  rel="stylesheet"
24
  />
25
+ <script type="module" crossorigin src="./assets/main-C6D7HP12.js"></script>
26
  <link rel="modulepreload" crossorigin href="./assets/modulepreload-polyfill-B5Qt9EMX.js">
27
+ <link rel="modulepreload" crossorigin href="./assets/subscribers-DauO8VtY.js">
28
+ <link rel="stylesheet" crossorigin href="./assets/subscribers-Sa7xbXRt.css">
29
  <link rel="manifest" href="./manifest.webmanifest"><script id="vite-plugin-pwa:register-sw" src="./registerSW.js"></script></head>
30
  <body>
31
  <header class="site-header">
 
59
  <a class="btn btn-primary" href="./app.html">Try the live demo</a>
60
  <a class="btn btn-ghost" href="https://github.com/2000pd3rvr/careTalk">View on GitHub</a>
61
  </div>
62
+ <p class="version-pill">Version 1.1.8</p>
63
  </div>
64
  </section>
65
 
 
171
  <h2 id="feedback-title">Would careTalk help on your shift?</h2>
172
  <p class="lede">
173
  Care assistants and supervisors — tell us how you think this could support your day-to-day work.
174
+ Send feedback is emailed straight to the careTalk inbox (no mail app needed) and kept on this device.
175
  </p>
176
 
177
  <form id="feedbackForm" class="feedback-form" novalidate>
178
+ <!-- Honeypot for bots — leave empty -->
179
+ <input
180
+ class="hp-field"
181
+ type="text"
182
+ name="_honey"
183
+ tabindex="-1"
184
+ autocomplete="off"
185
+ aria-hidden="true"
186
+ />
187
  <fieldset class="feedback-roles">
188
  <legend>I am mainly a…</legend>
189
  <label class="role-option">
 
252
  <footer class="site-footer">
253
  <div class="section-inner footer-row">
254
  <div>
255
+ <p>careTalk v1.1.8 · MIT · Not a clinical system of record</p>
256
  <p>
257
  <a href="./app.html">App</a>
258
  ·
sw.js CHANGED
@@ -1 +1 @@
1
- if(!self.define){let e,s={};const i=(i,n)=>(i=new URL(i+".js",n).href,s[i]||new Promise(s=>{if("document"in self){const e=document.createElement("script");e.src=i,e.onload=s,document.head.appendChild(e)}else e=i,importScripts(i),s()}).then(()=>{let e=s[i];if(!e)throw new Error(`Module ${i} didn’t register its module`);return e}));self.define=(n,r)=>{const c=e||("document"in self?document.currentScript.src:"")||location.href;if(s[c])return;let o={};const d=e=>i(e,c),l={module:{uri:c},exports:o,require:d};s[c]=Promise.all(n.map(e=>l[e]||d(e))).then(e=>(r(...e),o))}}define(["./workbox-7e792205"],function(e){"use strict";e.setCacheNameDetails({prefix:"caretalk-v1.1.7"}),self.skipWaiting(),e.clientsClaim(),e.precacheAndRoute([{url:"registerSW.js",revision:"402b66900e731ca748771b6fc5e7a068"},{url:"hero-care.svg",revision:"a9d97d192cde2661e3e4d52723d03ae7"},{url:"icons/maskable-512.png",revision:"41eb5c903fd29f4a552b55122c39d7a6"},{url:"icons/icon-96.png",revision:"c7063d694b7210675979642d3cc4bd9b"},{url:"icons/icon-72.png",revision:"40325cc62c852106f90fcc870cbc1943"},{url:"icons/icon-512.png",revision:"9e9241bfc9b4635ef53377151d7d80aa"},{url:"icons/icon-48.png",revision:"e285578e036bdb9ce72e90c74d81e32f"},{url:"icons/icon-384.png",revision:"c68ce1a6dc0d17e06addd8b808b106ca"},{url:"icons/icon-256.png",revision:"36af64867752330984fa76459c7b6f91"},{url:"icons/icon-192.png",revision:"0d97f74e5177647fbde6ac7c70e3e9bb"},{url:"icons/icon-180.png",revision:"dd4bbc3f77afe698d21e73da037d28e3"},{url:"icons/icon-152.png",revision:"afa4984306b9851dbc21a20991a4e508"},{url:"icons/icon-144.png",revision:"e6613e2654691995cd27d7315464c900"},{url:"icons/icon-128.png",revision:"ca020be4893dc4d974b52c419c55aba6"},{url:"icons/favicon.png",revision:"4526b965ff5b8d72db16968924f1b3db"},{url:"guides/skin-check.svg",revision:"ba8e861a7c76aa3a69999503b88f3170"},{url:"guides/fall-no-lift.svg",revision:"b82c2c9c8472a82ae241ed8faed4e2f8"},{url:"guides/fall-assess.svg",revision:"3b8f26a7674ddab515bf6ed041176d2e"},{url:"guides/dysphagia-upright.svg",revision:"b20b993fecc2242aea0d2ced2cce5eac"},{url:"guides/dysphagia-stop.svg",revision:"6ce96fc1300d0267b7ae463bd96c9ad1"},{url:"guides/distress-space.svg",revision:"f2fbd3081bd5bfb99101fd8f3a3e7916"},{url:"assets/web-DyS4cL83.js",revision:null},{url:"assets/web-CgUdoTZR.js",revision:null},{url:"assets/web-CXyz-Izy.js",revision:null},{url:"assets/subscribers-BDwoJ2Wh.js",revision:null},{url:"assets/subscribers--ZiVSqeN.css",revision:null},{url:"assets/modulepreload-polyfill-B5Qt9EMX.js",revision:null},{url:"assets/main-nC7DZYuB.js",revision:null},{url:"assets/app-Cw1kdNnU.js",revision:null},{url:"assets/app-CTsfb-0l.css",revision:null},{url:"assets/admin-vg_JNeHI.js",revision:null},{url:"hero-care.svg",revision:"a9d97d192cde2661e3e4d52723d03ae7"},{url:"icons/favicon.png",revision:"4526b965ff5b8d72db16968924f1b3db"},{url:"icons/icon-192.png",revision:"0d97f74e5177647fbde6ac7c70e3e9bb"},{url:"icons/icon-512.png",revision:"9e9241bfc9b4635ef53377151d7d80aa"},{url:"icons/maskable-512.png",revision:"41eb5c903fd29f4a552b55122c39d7a6"},{url:"manifest.webmanifest",revision:"7e7f6001ed44fd4390e69de1a5d67214"}],{}),e.cleanupOutdatedCaches()});
 
1
+ if(!self.define){let e,s={};const i=(i,n)=>(i=new URL(i+".js",n).href,s[i]||new Promise(s=>{if("document"in self){const e=document.createElement("script");e.src=i,e.onload=s,document.head.appendChild(e)}else e=i,importScripts(i),s()}).then(()=>{let e=s[i];if(!e)throw new Error(`Module ${i} didn’t register its module`);return e}));self.define=(n,r)=>{const c=e||("document"in self?document.currentScript.src:"")||location.href;if(s[c])return;let o={};const d=e=>i(e,c),a={module:{uri:c},exports:o,require:d};s[c]=Promise.all(n.map(e=>a[e]||d(e))).then(e=>(r(...e),o))}}define(["./workbox-7e792205"],function(e){"use strict";e.setCacheNameDetails({prefix:"caretalk-v1.1.8"}),self.skipWaiting(),e.clientsClaim(),e.precacheAndRoute([{url:"registerSW.js",revision:"402b66900e731ca748771b6fc5e7a068"},{url:"hero-care.svg",revision:"a9d97d192cde2661e3e4d52723d03ae7"},{url:"icons/maskable-512.png",revision:"41eb5c903fd29f4a552b55122c39d7a6"},{url:"icons/icon-96.png",revision:"c7063d694b7210675979642d3cc4bd9b"},{url:"icons/icon-72.png",revision:"40325cc62c852106f90fcc870cbc1943"},{url:"icons/icon-512.png",revision:"9e9241bfc9b4635ef53377151d7d80aa"},{url:"icons/icon-48.png",revision:"e285578e036bdb9ce72e90c74d81e32f"},{url:"icons/icon-384.png",revision:"c68ce1a6dc0d17e06addd8b808b106ca"},{url:"icons/icon-256.png",revision:"36af64867752330984fa76459c7b6f91"},{url:"icons/icon-192.png",revision:"0d97f74e5177647fbde6ac7c70e3e9bb"},{url:"icons/icon-180.png",revision:"dd4bbc3f77afe698d21e73da037d28e3"},{url:"icons/icon-152.png",revision:"afa4984306b9851dbc21a20991a4e508"},{url:"icons/icon-144.png",revision:"e6613e2654691995cd27d7315464c900"},{url:"icons/icon-128.png",revision:"ca020be4893dc4d974b52c419c55aba6"},{url:"icons/favicon.png",revision:"4526b965ff5b8d72db16968924f1b3db"},{url:"guides/skin-check.svg",revision:"ba8e861a7c76aa3a69999503b88f3170"},{url:"guides/fall-no-lift.svg",revision:"b82c2c9c8472a82ae241ed8faed4e2f8"},{url:"guides/fall-assess.svg",revision:"3b8f26a7674ddab515bf6ed041176d2e"},{url:"guides/dysphagia-upright.svg",revision:"b20b993fecc2242aea0d2ced2cce5eac"},{url:"guides/dysphagia-stop.svg",revision:"6ce96fc1300d0267b7ae463bd96c9ad1"},{url:"guides/distress-space.svg",revision:"f2fbd3081bd5bfb99101fd8f3a3e7916"},{url:"assets/web-DodVBXGv.js",revision:null},{url:"assets/web-BmkooPm-.js",revision:null},{url:"assets/web-Bmj3o-P9.js",revision:null},{url:"assets/subscribers-Sa7xbXRt.css",revision:null},{url:"assets/subscribers-DauO8VtY.js",revision:null},{url:"assets/modulepreload-polyfill-B5Qt9EMX.js",revision:null},{url:"assets/main-C6D7HP12.js",revision:null},{url:"assets/app-CTsfb-0l.css",revision:null},{url:"assets/app-BoDOH5ck.js",revision:null},{url:"assets/admin-BoC_GjKf.js",revision:null},{url:"hero-care.svg",revision:"a9d97d192cde2661e3e4d52723d03ae7"},{url:"icons/favicon.png",revision:"4526b965ff5b8d72db16968924f1b3db"},{url:"icons/icon-192.png",revision:"0d97f74e5177647fbde6ac7c70e3e9bb"},{url:"icons/icon-512.png",revision:"9e9241bfc9b4635ef53377151d7d80aa"},{url:"icons/maskable-512.png",revision:"41eb5c903fd29f4a552b55122c39d7a6"},{url:"manifest.webmanifest",revision:"7e7f6001ed44fd4390e69de1a5d67214"}],{}),e.cleanupOutdatedCaches()});