claude-artifact-framework 0.19.2 → 0.20.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,14 +1,14 @@
1
- var ArtifactKit=(()=>{var G=Object.defineProperty;var bt=Object.getOwnPropertyDescriptor;var ht=Object.getOwnPropertyNames;var gt=Object.prototype.hasOwnProperty;var yt=(e,t)=>{for(var a in t)G(e,a,{get:t[a],enumerable:!0})},wt=(e,t,a,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of ht(t))!gt.call(e,o)&&o!==a&&G(e,o,{get:()=>t[o],enumerable:!(r=bt(t,o))||r.enumerable});return e};var kt=e=>wt(G({},"__esModule",{value:!0}),e);var fa={};yt(fa,{contrast:()=>te,createApp:()=>pt,createPersistedStore:()=>ge,createSharedStore:()=>ye,createStore:()=>he,hasReact:()=>K,palette:()=>ae,storage:()=>S,themeCss:()=>P,useReact:()=>we});function I(){return typeof window<"u"&&typeof window.storage=="object"&&window.storage!==null}function pe(e){return{async get(t,a=void 0){if(!I())return a;try{let r=await window.storage.get(t,e);if(r?.value===void 0||r?.value===null)return a;try{return JSON.parse(r.value)}catch{return r.value}}catch{return a}},async set(t,a,{raw:r=!1}={}){if(!I())throw new Error("window.storage is not available (is this a Code Artifact rather than a published Chat Artifact?)");let o=r?a:JSON.stringify(a);if(typeof o!="string")throw new Error("window.storage only accepts strings \u2014 the value must be JSON-serializable");return window.storage.set(t,o,e)},async delete(t){if(I())try{await window.storage.delete(t,e)}catch{}},async list(t){if(!I())return[];try{return(await window.storage.list(t,e))?.keys||[]}catch{return[]}}}}var S={...pe(!1),shared:pe(!0),available:I};function X(e){let t=e,a=new Set;function r(){return t}function o(i){t=typeof i=="function"?i(t):i,a.forEach(c=>c(t))}function s(i){return a.add(i),()=>a.delete(i)}return{get:r,set:o,subscribe:s}}function be(e,t){let a;return(...r)=>{clearTimeout(a),a=setTimeout(()=>e(...r),t)}}function he(e){return X(e)}function ge(e,t,{debounceMs:a=300}={}){let r=X(t),o=be(i=>S.set(e,i),a),s=S.get(e,t).then(i=>r.set(i));return r.subscribe(o),{...r,ready:s}}function ye(e,t,{pollMs:a=2e3,debounceMs:r=300}={}){let o=X(t),s=be(d=>S.shared.set(e,d),r),i=!1;o.subscribe(d=>{i||s(d)});async function c(){let d=await S.shared.get(e,t);JSON.stringify(d)!==JSON.stringify(o.get())&&(i=!0,o.set(d),i=!1)}let f=c(),l=setInterval(c,a);return{...o,ready:f,stop:()=>clearInterval(l)}}var L=typeof globalThis<"u"?globalThis.React:void 0;function we(e){return L=e,e}function K(){return!!L}function ke(){return M()}function M(){if(!L)throw new Error(`claude-artifact-framework: React not found. Hand it over once, before createApp:
1
+ var ArtifactKit=(()=>{var X=Object.defineProperty;var ht=Object.getOwnPropertyDescriptor;var bt=Object.getOwnPropertyNames;var gt=Object.prototype.hasOwnProperty;var yt=(e,t)=>{for(var a in t)X(e,a,{get:t[a],enumerable:!0})},wt=(e,t,a,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of bt(t))!gt.call(e,n)&&n!==a&&X(e,n,{get:()=>t[n],enumerable:!(r=ht(t,n))||r.enumerable});return e};var kt=e=>wt(X({},"__esModule",{value:!0}),e);var fa={};yt(fa,{contrast:()=>ae,createApp:()=>pt,createPersistedStore:()=>ye,createSharedStore:()=>we,createStore:()=>ge,hasReact:()=>K,palette:()=>re,storage:()=>j,themeCss:()=>J,useReact:()=>ke});function I(){return typeof window<"u"&&typeof window.storage=="object"&&window.storage!==null}function he(e){return{async get(t,a=void 0){if(!I())return a;try{let r=await window.storage.get(t,e);if(r?.value===void 0||r?.value===null)return a;try{return JSON.parse(r.value)}catch{return r.value}}catch{return a}},async set(t,a,{raw:r=!1}={}){if(!I())throw new Error("window.storage is not available (is this a Code Artifact rather than a published Chat Artifact?)");let n=r?a:JSON.stringify(a);if(typeof n!="string")throw new Error("window.storage only accepts strings \u2014 the value must be JSON-serializable");return window.storage.set(t,n,e)},async delete(t){if(I())try{await window.storage.delete(t,e)}catch{}},async list(t){if(!I())return[];try{return(await window.storage.list(t,e))?.keys||[]}catch{return[]}}}}var j={...he(!1),shared:he(!0),available:I};function Q(e){let t=e,a=new Set;function r(){return t}function n(i){t=typeof i=="function"?i(t):i,a.forEach(c=>c(t))}function s(i){return a.add(i),()=>a.delete(i)}return{get:r,set:n,subscribe:s}}function be(e,t){let a;return(...r)=>{clearTimeout(a),a=setTimeout(()=>e(...r),t)}}function ge(e){return Q(e)}function ye(e,t,{debounceMs:a=300}={}){let r=Q(t),n=be(i=>j.set(e,i),a),s=j.get(e,t).then(i=>r.set(i));return r.subscribe(n),{...r,ready:s}}function we(e,t,{pollMs:a=2e3,debounceMs:r=300}={}){let n=Q(t),s=be(d=>j.shared.set(e,d),r),i=!1;n.subscribe(d=>{i||s(d)});async function c(){let d=await j.shared.get(e,t);JSON.stringify(d)!==JSON.stringify(n.get())&&(i=!0,n.set(d),i=!1)}let l=c(),f=setInterval(c,a);return{...n,ready:l,stop:()=>clearInterval(f)}}var L=typeof globalThis<"u"?globalThis.React:void 0;function ke(e){return L=e,e}function K(){return!!L}function ve(){return M()}function M(){if(!L)throw new Error(`claude-artifact-framework: React not found. Hand it over once, before createApp:
2
2
 
3
3
  import React from "react";
4
4
  ArtifactKit.useReact(React);
5
- `);return L}var n=(...e)=>M().createElement(...e),$=(...e)=>M().useState(...e),A=(...e)=>M().useEffect(...e);var ve=(...e)=>M().useRef(...e),ba=L&&L.Component||class{render(){return M()}};var Q="caf:data",xe="caf:viewer",Ne="caf:view",$e={screen:null,arg:null,stack:[],step:0,selected:null,tabs:{},collapsed:{}};function Y(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function Z(e,t){if(!Y(e)||!Y(t))return t===void 0?e:t;let a={...e};for(let r of Object.keys(t))a[r]=Y(e[r])?Z(e[r],t[r]):t[r];return a}function Ee(e,t){let a;return(...r)=>{clearTimeout(a),a=setTimeout(()=>e(...r),t)}}function Se(e,{debounceMs:t=400,shared:a=!1,pollMs:r=2500}={}){let o=a?S.shared:S,s=ee(e),i={...$e},c=!1,f=null,l=0,d=0,p=new Set,h=!1;function k(){h||(h=!0,Promise.resolve().then(()=>{h=!1;for(let u of p)u()}))}let g=Ee(()=>{let u=l;Promise.resolve(o.set(Q,s)).then(()=>{d=Math.max(d,u)}).catch(()=>{})},t),x=Ee(()=>S.set(Ne,i),t);a&&setInterval(async()=>{if(!(!c||l>d))try{let u=await o.get(Q,void 0);u!==void 0&&JSON.stringify(u)!==JSON.stringify(s)&&(s=Z(e,u),k())}catch{}},r);let y=(async()=>{let[u,w,b]=await Promise.all([o.get(Q,void 0),S.get(Ne,void 0),S.get(xe,void 0)]);typeof b=="string"&&b?f=b:(f="v"+Math.random().toString(36).slice(2,10)+Math.random().toString(36).slice(2,6),S.set(xe,f).catch?.(()=>{})),u!==void 0&&(s=Z(e,u)),w!==void 0&&(i={...$e,...w}),c=!0,k()})();function j(u){let w=u(s);w!==void 0&&(s=w),s={...s},l++,g(),k()}function m(u){i={...i,...u},x(),k()}return{ready:y,isHydrated:()=>c,getViewerId:()=>f,getData:()=>s,getView:()=>i,update:j,setView:m,go(u,w){m({stack:[...i.stack,{screen:i.screen,arg:i.arg}],screen:u,arg:w})},back(){let u=i.stack.slice(),w=u.pop()||{screen:null,arg:null};m({stack:u,screen:w.screen,arg:w.arg})},subscribe(u){return p.add(u),()=>p.delete(u)}}}function ee(e){if(Array.isArray(e))return e.map(ee);if(Y(e)){let t={};for(let a of Object.keys(e))t[a]=ee(e[a]);return t}return e}function _(e,t,a){return Math.min(a,Math.max(t,e))}function F(e){let t=String(e).replace("#","").trim();t.length===3&&(t=t.split("").map(r=>r+r).join(""));let a=parseInt(t,16);return Number.isFinite(a)?[a>>16&255,a>>8&255,a&255]:[59,110,246]}function vt(e){return"#"+e.map(t=>_(Math.round(t),0,255).toString(16).padStart(2,"0")).join("")}function Ae([e,t,a]){e/=255,t/=255,a/=255;let r=Math.max(e,t,a),o=Math.min(e,t,a),s=(r+o)/2,i=r-o,c=0,f=0;return i&&(f=s>.5?i/(2-r-o):i/(r+o),r===e?c=(t-a)/i+(t<a?6:0):r===t?c=(a-e)/i+2:c=(e-t)/i+4,c/=6),[c*360,f*100,s*100]}function xt(e,t,a){if(e=(e%360+360)%360/360,t=_(t,0,100)/100,a=_(a,0,100)/100,!t)return[a*255,a*255,a*255];let r=a<.5?a*(1+t):a+t-a*t,o=2*a-r,s=i=>(i<0&&(i+=1),i>1&&(i-=1),i<1/6?o+(r-o)*6*i:i<1/2?r:i<2/3?o+(r-o)*(2/3-i)*6:o);return[s(e+1/3)*255,s(e)*255,s(e-1/3)*255]}function v(e,t,a){return vt(xt(e,t,a))}function je(e){let t=e.map(a=>(a/=255,a<=.03928?a/12.92:Math.pow((a+.055)/1.055,2.4)));return .2126*t[0]+.7152*t[1]+.0722*t[2]}function te(e,t){let a=je(F(e)),r=je(F(t));return(Math.max(a,r)+.05)/(Math.min(a,r)+.05)}function O(e,t,a,r,o,s){for(let i=o;i>=4&&i<=96;i+=s){let c=v(e,t,i);if(te(c,a)>=r)return c}return v(e,t,s<0?24:82)}function ae(e="#3b6ef6"){let[t,a]=Ae(F(e)),r=_(a,30,88),o=_(r*.1,3,9),s=v(t,o*.4,100),i=v(t,o*1.4,13);return{light:{bg:v(t,o,96.5),surface:s,sunken:v(t,o,93),border:v(t,o,86),text:v(t,o*1.6,11),muted:v(t,o*1.2,41),accent:O(t,r,"#ffffff",4.5,54,-2),accentText:"#ffffff",danger:O(2,68,"#ffffff",4.5,54,-2),ok:O(148,62,"#ffffff",4.5,44,-2),warn:O(38,88,"#ffffff",4.5,44,-2)},dark:{bg:v(t,o*1.5,9),surface:i,sunken:v(t,o*1.5,7),border:v(t,o*1.3,24),text:v(t,o*.6,95),muted:v(t,o*.8,66),accent:O(t,_(r,40,80),i,4.5,62,2),accentText:v(t,o*2,8),danger:O(2,70,i,4.5,62,2),ok:O(148,55,i,4.5,62,2),warn:O(38,80,i,4.5,62,2)}}}function H(e){return Object.entries(e).map(([t,a])=>`--caf-${t}: ${a};`).join("")}function P(e){let t=ae(e);return`
5
+ `);return L}var o=(...e)=>M().createElement(...e),E=(...e)=>M().useState(...e),A=(...e)=>M().useEffect(...e);var Y=(...e)=>M().useRef(...e),ha=L&&L.Component||class{render(){return M()}};var Z="caf:data",xe="caf:viewer",Ne="caf:view",Ee={screen:null,arg:null,stack:[],step:0,selected:null,tabs:{},collapsed:{}};function F(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function ee(e,t){if(!F(e)||!F(t))return t===void 0?e:t;let a={...e};for(let r of Object.keys(t))a[r]=F(e[r])?ee(e[r],t[r]):t[r];return a}function $e(e,t){let a;return(...r)=>{clearTimeout(a),a=setTimeout(()=>e(...r),t)}}function Se(e,{debounceMs:t=400,shared:a=!1,pollMs:r=2500}={}){let n=a?j.shared:j,s=te(e),i={...Ee},c=!1,l=null,f=0,d=0,b=new Set,h=!1;function u(){h||(h=!0,Promise.resolve().then(()=>{h=!1;for(let y of b)y()}))}let m=$e(()=>{let y=f;Promise.resolve(n.set(Z,s)).then(()=>{d=Math.max(d,y)}).catch(()=>{})},t),v=$e(()=>j.set(Ne,i),t),w=null;a&&setInterval(async()=>{if(!(!c||f>d))try{let y=await n.get(Z,void 0);if(y!==void 0&&JSON.stringify(y)!==JSON.stringify(s)){let p=ee(e,y),x=[...new Set([...Object.keys(s||{}),...Object.keys(p||{})])].filter(N=>JSON.stringify(s[N])!==JSON.stringify(p[N]));s=p,w={keys:x,at:Date.now()},u()}}catch{}},r);let S=(async()=>{let[y,p,x]=await Promise.all([n.get(Z,void 0),j.get(Ne,void 0),j.get(xe,void 0)]);typeof x=="string"&&x?l=x:(l="v"+Math.random().toString(36).slice(2,10)+Math.random().toString(36).slice(2,6),j.set(xe,l).catch?.(()=>{})),y!==void 0&&(s=ee(e,y)),p!==void 0&&(i={...Ee,...p}),c=!0,u()})();function g(y){let p=y(s);p!==void 0&&(s=p),s={...s},f++,m(),u()}function k(y){i={...i,...y},v(),u()}return{ready:S,isHydrated:()=>c,getViewerId:()=>l,getRemote:()=>w,getData:()=>s,getView:()=>i,update:g,setView:k,go(y,p){k({stack:[...i.stack,{screen:i.screen,arg:i.arg}],screen:y,arg:p})},back(){let y=i.stack.slice(),p=y.pop()||{screen:null,arg:null};k({stack:y,screen:p.screen,arg:p.arg})},subscribe(y){return b.add(y),()=>b.delete(y)}}}function te(e){if(Array.isArray(e))return e.map(te);if(F(e)){let t={};for(let a of Object.keys(e))t[a]=te(e[a]);return t}return e}function R(e,t,a){return Math.min(a,Math.max(t,e))}function P(e){let t=String(e).replace("#","").trim();t.length===3&&(t=t.split("").map(r=>r+r).join(""));let a=parseInt(t,16);return Number.isFinite(a)?[a>>16&255,a>>8&255,a&255]:[59,110,246]}function vt(e){return"#"+e.map(t=>R(Math.round(t),0,255).toString(16).padStart(2,"0")).join("")}function Ae([e,t,a]){e/=255,t/=255,a/=255;let r=Math.max(e,t,a),n=Math.min(e,t,a),s=(r+n)/2,i=r-n,c=0,l=0;return i&&(l=s>.5?i/(2-r-n):i/(r+n),r===e?c=(t-a)/i+(t<a?6:0):r===t?c=(a-e)/i+2:c=(e-t)/i+4,c/=6),[c*360,l*100,s*100]}function xt(e,t,a){if(e=(e%360+360)%360/360,t=R(t,0,100)/100,a=R(a,0,100)/100,!t)return[a*255,a*255,a*255];let r=a<.5?a*(1+t):a+t-a*t,n=2*a-r,s=i=>(i<0&&(i+=1),i>1&&(i-=1),i<1/6?n+(r-n)*6*i:i<1/2?r:i<2/3?n+(r-n)*(2/3-i)*6:n);return[s(e+1/3)*255,s(e)*255,s(e-1/3)*255]}function $(e,t,a){return vt(xt(e,t,a))}function je(e){let t=e.map(a=>(a/=255,a<=.03928?a/12.92:Math.pow((a+.055)/1.055,2.4)));return .2126*t[0]+.7152*t[1]+.0722*t[2]}function ae(e,t){let a=je(P(e)),r=je(P(t));return(Math.max(a,r)+.05)/(Math.min(a,r)+.05)}function O(e,t,a,r,n,s){for(let i=n;i>=4&&i<=96;i+=s){let c=$(e,t,i);if(ae(c,a)>=r)return c}return $(e,t,s<0?24:82)}function re(e="#3b6ef6"){let[t,a]=Ae(P(e)),r=R(a,30,88),n=R(r*.1,3,9),s=$(t,n*.4,100),i=$(t,n*1.4,13);return{light:{bg:$(t,n,96.5),surface:s,sunken:$(t,n,93),border:$(t,n,86),text:$(t,n*1.6,11),muted:$(t,n*1.2,41),accent:O(t,r,"#ffffff",4.5,54,-2),accentText:"#ffffff",danger:O(2,68,"#ffffff",4.5,54,-2),ok:O(148,62,"#ffffff",4.5,44,-2),warn:O(38,88,"#ffffff",4.5,44,-2)},dark:{bg:$(t,n*1.5,9),surface:i,sunken:$(t,n*1.5,7),border:$(t,n*1.3,24),text:$(t,n*.6,95),muted:$(t,n*.8,66),accent:O(t,R(r,40,80),i,4.5,62,2),accentText:$(t,n*2,8),danger:O(2,70,i,4.5,62,2),ok:O(148,55,i,4.5,62,2),warn:O(38,80,i,4.5,62,2)}}}function H(e){return Object.entries(e).map(([t,a])=>`--caf-${t}: ${a};`).join("")}function J(e){let t=re(e);return`
6
6
  :root { ${H(t.light)} }
7
7
  @media (prefers-color-scheme: dark) { :root { ${H(t.dark)} } }
8
8
  :root[data-theme="dark"] { ${H(t.dark)} }
9
9
  :root[data-theme="light"] { ${H(t.light)} }
10
- `}function Te(e,t){let[a,r]=Ae(F(e||"#3b6ef6")),o=_(r,45,70);return Array.from({length:t},(s,i)=>v((a+i*137.5)%360,o,52))}var ne=["system","greeting","placeholder","tools","model","maxTokens"],Nt="claude-sonnet-4-6",$t=8;async function Et({model:e,maxTokens:t,system:a,messages:r,onText:o}){let s=await fetch("https://api.anthropic.com/v1/messages",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({model:e,max_tokens:t,system:a,messages:r,stream:!0})});if(!s.ok||!s.body){let d="";try{let p=await s.json();d=p&&p.error&&p.error.message||JSON.stringify(p)}catch{d=await s.text().catch(()=>"")}throw new Error(`HTTP ${s.status}${d?": "+d:""}`)}let i=s.body.getReader(),c=new TextDecoder,f="",l="";for(;;){let{done:d,value:p}=await i.read();if(d)break;l+=c.decode(p,{stream:!0});let h=l.split(`
11
- `);l=h.pop();for(let k of h)if(k.startsWith("data: "))try{let g=JSON.parse(k.slice(6));g.type==="content_block_delta"&&g.delta&&g.delta.text&&(f+=g.delta.text,o&&o(f))}catch{}}return f}function St(e){let t=e.match(/```tool_call\s*\n?([\s\S]*?)```/);if(!t)return null;try{let a=JSON.parse(t[1]);return Array.isArray(a)&&a.length?a:null}catch{return null}}function Ce(e){return e.replace(/```tool_call\s*\n?[\s\S]*?```/,"").trim()}function jt(e){return`
10
+ `}function Te(e,t){let[a,r]=Ae(P(e||"#3b6ef6")),n=R(r,45,70);return Array.from({length:t},(s,i)=>$((a+i*137.5)%360,n,52))}var oe=["system","greeting","placeholder","tools","model","maxTokens"],Nt="claude-sonnet-4-6",Et=8;async function $t({model:e,maxTokens:t,system:a,messages:r,onText:n}){let s=await fetch("https://api.anthropic.com/v1/messages",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({model:e,max_tokens:t,system:a,messages:r,stream:!0})});if(!s.ok||!s.body){let d="";try{let b=await s.json();d=b&&b.error&&b.error.message||JSON.stringify(b)}catch{d=await s.text().catch(()=>"")}throw new Error(`HTTP ${s.status}${d?": "+d:""}`)}let i=s.body.getReader(),c=new TextDecoder,l="",f="";for(;;){let{done:d,value:b}=await i.read();if(d)break;f+=c.decode(b,{stream:!0});let h=f.split(`
11
+ `);f=h.pop();for(let u of h)if(u.startsWith("data: "))try{let m=JSON.parse(u.slice(6));m.type==="content_block_delta"&&m.delta&&m.delta.text&&(l+=m.delta.text,n&&n(l))}catch{}}return l}function St(e){let t=e.match(/```tool_call\s*\n?([\s\S]*?)```/);if(!t)return null;try{let a=JSON.parse(t[1]);return Array.isArray(a)&&a.length?a:null}catch{return null}}function Ce(e){return e.replace(/```tool_call\s*\n?[\s\S]*?```/,"").trim()}function jt(e){return`
12
12
 
13
13
  You have tools available:
14
14
  ${Object.entries(e).map(([a,r])=>`- ${a}: ${r.description}
@@ -21,15 +21,15 @@ This environment does not support native function calling. To use a tool, reply
21
21
  [{ "name": "tool_name", "input": { "param": "value" } }]
22
22
  \`\`\`
23
23
 
24
- You may include several calls in one array. NEVER invent a tool's result \u2014 emit the pure tool_call block and wait for the real result, which arrives in the next message tagged [TOOL_RESULT]. When you have everything you need, answer in natural language with no tool_call block.`}function At(e,t,a){return e.map(r=>{let o=t[r.name];if(!o)return{name:r.name,error:`unknown tool "${r.name}". Valid tools: ${Object.keys(t).join(", ")}`};try{let s=o.run(r.input||{},a);return{name:r.name,result:s===void 0?{ok:!0}:s}}catch(s){return{name:r.name,error:String(s&&s.message||s)}}})}var Oe=e=>String(e).replace(/[&<>"]/g,t=>({"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;"})[t]);function re(e){let t=[],a=String(e).replace(/```[a-z]*\n?([\s\S]*?)```/g,(r,o)=>(t.push(o.replace(/\n$/,"")),"\0"+(t.length-1)+"\0"));return a=Oe(a),a=a.replace(/`([^`]+)`/g,"<code>$1</code>"),a=a.replace(/\*\*([^*]+)\*\*/g,"<strong>$1</strong>"),a=a.replace(/(^|[^*])\*([^*\n]+)\*/g,"$1<em>$2</em>"),a=a.replace(/^#{1,3} (.+)$/gm,'<strong class="caf-md-h">$1</strong>'),a=a.replace(/^[-•*] (.+)$/gm,'<span class="caf-md-li">$1</span>'),a=a.replace(/^\d+\. (.+)$/gm,'<span class="caf-md-li caf-md-num">$1</span>'),a=a.replace(/\n/g,"<br>"),a=a.replace(/\u0000(\d+)\u0000/g,(r,o)=>'<pre class="caf-code">'+Oe(t[Number(o)])+"</pre>"),a}function Tt({m:e}){return e.role==="tools"?n("div",{className:"caf-msg-tools"},`used: ${e.tools.join(", ")}`):e.role==="error"?n("div",{className:"caf-msg caf-msg-error"},n("strong",null,"The call failed"),n("span",null,e.content),n("span",{className:"caf-hint"},"Your message is kept \u2014 send again to retry.")):e.role==="user"?n("div",{className:"caf-msg caf-msg-user"},e.content):n("div",{className:"caf-msg caf-msg-assistant",dangerouslySetInnerHTML:{__html:re(e.content)}})}function oe({cfg:e,ctx:t,title:a}){let r=e,[o,s]=$(""),[i,c]=$(!1),[f,l]=$(null),d=ve(null),p=t.data.chat||{api:[],log:[]},h=p.log||[];A(()=>{d.current&&d.current.scrollIntoView({block:"end"})},[h.length,f]);async function k(){let g=o.trim();if(!g||i)return;s(""),c(!0);let x=[...p.api||[],{role:"user",content:g}],y=[...h,{role:"user",content:g}],j=()=>t.update(m=>{m.chat={api:x,log:y}});j();try{let m=(typeof r.system=="function"?r.system(t.data):r.system||"")+(r.tools?jt(r.tools):"");for(let u=0;u<$t;u++){let w=await Et({model:r.model||Nt,maxTokens:r.maxTokens||2e3,system:m,messages:x,onText:T=>l(Ce(T))});x=[...x,{role:"assistant",content:w}];let b=Ce(w),E=r.tools?St(w):null;if(!E){y=[...y,{role:"assistant",content:b||w}],j();break}let N=At(E,r.tools,t);b&&(y=[...y,{role:"assistant",content:b}]),y=[...y,{role:"tools",tools:E.map(T=>T.name)}],x=[...x,{role:"user",content:`[TOOL_RESULT]
24
+ You may include several calls in one array. NEVER invent a tool's result \u2014 emit the pure tool_call block and wait for the real result, which arrives in the next message tagged [TOOL_RESULT]. When you have everything you need, answer in natural language with no tool_call block.`}function At(e,t,a){return e.map(r=>{let n=t[r.name];if(!n)return{name:r.name,error:`unknown tool "${r.name}". Valid tools: ${Object.keys(t).join(", ")}`};try{let s=n.run(r.input||{},a);return{name:r.name,result:s===void 0?{ok:!0}:s}}catch(s){return{name:r.name,error:String(s&&s.message||s)}}})}var Oe=e=>String(e).replace(/[&<>"]/g,t=>({"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;"})[t]);function ne(e){let t=[],a=String(e).replace(/```[a-z]*\n?([\s\S]*?)```/g,(r,n)=>(t.push(n.replace(/\n$/,"")),"\0"+(t.length-1)+"\0"));return a=Oe(a),a=a.replace(/`([^`]+)`/g,"<code>$1</code>"),a=a.replace(/\*\*([^*]+)\*\*/g,"<strong>$1</strong>"),a=a.replace(/(^|[^*])\*([^*\n]+)\*/g,"$1<em>$2</em>"),a=a.replace(/^#{1,3} (.+)$/gm,'<strong class="caf-md-h">$1</strong>'),a=a.replace(/^[-•*] (.+)$/gm,'<span class="caf-md-li">$1</span>'),a=a.replace(/^\d+\. (.+)$/gm,'<span class="caf-md-li caf-md-num">$1</span>'),a=a.replace(/\n/g,"<br>"),a=a.replace(/\u0000(\d+)\u0000/g,(r,n)=>'<pre class="caf-code">'+Oe(t[Number(n)])+"</pre>"),a}function Tt({m:e}){return e.role==="tools"?o("div",{className:"caf-msg-tools"},`used: ${e.tools.join(", ")}`):e.role==="error"?o("div",{className:"caf-msg caf-msg-error"},o("strong",null,"The call failed"),o("span",null,e.content),o("span",{className:"caf-hint"},"Your message is kept \u2014 send again to retry.")):e.role==="user"?o("div",{className:"caf-msg caf-msg-user"},e.content):o("div",{className:"caf-msg caf-msg-assistant",dangerouslySetInnerHTML:{__html:ne(e.content)}})}function se({cfg:e,ctx:t,title:a}){let r=e,[n,s]=E(""),[i,c]=E(!1),[l,f]=E(null),d=Y(null),b=t.data.chat||{api:[],log:[]},h=b.log||[];A(()=>{d.current&&d.current.scrollIntoView({block:"end"})},[h.length,l]);async function u(){let m=n.trim();if(!m||i)return;s(""),c(!0);let v=[...b.api||[],{role:"user",content:m}],w=[...h,{role:"user",content:m}],S=()=>t.update(g=>{g.chat={api:v,log:w}});S();try{let g=(typeof r.system=="function"?r.system(t.data):r.system||"")+(r.tools?jt(r.tools):"");for(let k=0;k<Et;k++){let y=await $t({model:r.model||Nt,maxTokens:r.maxTokens||2e3,system:g,messages:v,onText:T=>f(Ce(T))});v=[...v,{role:"assistant",content:y}];let p=Ce(y),x=r.tools?St(y):null;if(!x){w=[...w,{role:"assistant",content:p||y}],S();break}let N=At(x,r.tools,t);p&&(w=[...w,{role:"assistant",content:p}]),w=[...w,{role:"tools",tools:x.map(T=>T.name)}],v=[...v,{role:"user",content:`[TOOL_RESULT]
25
25
  ${JSON.stringify(N)}
26
26
  [/TOOL_RESULT]
27
27
 
28
- Continue with this information. If you have everything you need, answer in natural language without further tool_call.`}],j(),l(null)}}catch(m){y=[...y,{role:"error",content:String(m&&m.message||m)}],j()}finally{l(null),c(!1)}}return n("div",{className:"caf-chat-panel"},n("div",{className:"caf-block caf-chat-log"},a?n("h2",{className:"caf-block-title"},a):null,r.greeting?n("div",{className:"caf-msg caf-msg-assistant",dangerouslySetInnerHTML:{__html:re(r.greeting)}}):null,h.map((g,x)=>n(Tt,{key:x,m:g})),f!==null?n("div",{className:"caf-msg caf-msg-assistant caf-msg-live",dangerouslySetInnerHTML:{__html:re(f||"\u2026")}}):null,i&&f===null?n("div",{className:"caf-msg-tools"},"thinking\u2026"):null,n("div",{ref:d})),n("div",{className:"caf-chat-input"},n("input",{value:o,placeholder:r.placeholder||"Message\u2026",disabled:i,enterKeyHint:"send",onChange:g=>s(g.target.value),onKeyDown:g=>{g.key==="Enter"&&(g.preventDefault(),k())},"aria-label":"Message"}),n("button",{type:"button",className:"caf-btn caf-btn-primary",disabled:i||!o.trim(),onClick:k},"Send")))}function _e({spec:e,ctx:t}){return n("div",{className:"caf-panel caf-panel-single"},n(oe,{cfg:e.chat,ctx:t}))}var se=["text","textarea","number","money","percent","check","date","select","file"];function z(e,t){if(e==null||e===""||typeof e=="number"&&!Number.isFinite(e))return"\u2014";let a=Number(e);switch(t){case"money":return Number.isFinite(a)?a.toLocaleString(void 0,{style:"currency",currency:"USD",maximumFractionDigits:2}):String(e);case"percent":return Number.isFinite(a)?`${a.toLocaleString(void 0,{maximumFractionDigits:2})}%`:String(e);case"number":return Number.isFinite(a)?a.toLocaleString(void 0,{maximumFractionDigits:2}):String(e);case"date":return e instanceof Date?e.toLocaleDateString():String(e);case"text":case void 0:case null:return String(e);default:throw new Error(`claude-artifact-framework: unknown format "${t}". Valid formats: money, percent, number, date, text.`)}}function ie(e,t){if(e.required&&(t===""||t===null||t===void 0))return"Required";if(t===""||t===null||t===void 0)return null;if(e.type==="number"||e.type==="money"||e.type==="percent"){let a=Number(t);if(!Number.isFinite(a))return"Must be a number";if(e.min!==void 0&&a<e.min)return`Must be at least ${e.min}`;if(e.max!==void 0&&a>e.max)return`Must be at most ${e.max}`}return null}function B({field:e,value:t,onChange:a,data:r}){let o=ie(e,t),s=`caf-f-${e.key}`,i=e.type==="number"||e.type==="money"||e.type==="percent";if(e.type==="file")return n("div",{className:"caf-field"},n("label",{htmlFor:s},e.label||e.key),n("input",{id:s,type:"file",accept:e.accept,onChange:l=>a(l.target.files&&l.target.files[0]?l.target.files[0]:null)}),t&&t.name?n("small",{className:"caf-hint"},`${t.name} (${Math.round((t.size||0)/1024)} KB)${t.stale?" \u2014 re-pick after reload":""}`):e.hint?n("small",{className:"caf-hint"},e.hint):null);if(e.type==="check")return n("label",{className:"caf-check"},n("input",{id:s,type:"checkbox",checked:!!t,onChange:l=>a(l.target.checked)}),n("span",null,e.label||e.key));let c={id:s,value:t??"","aria-invalid":o?"true":void 0,onChange:l=>a(i?Ct(l.target.value):l.target.value)},f;if(e.type==="textarea")f=n("textarea",{...c,rows:e.rows||3});else if(e.type==="select"){let l=typeof e.options=="function"?e.options(r)||[]:e.options||[];f=n("select",c,n("option",{value:""},e.placeholder||"Select\u2026"),l.map(d=>{let p=typeof d=="string"?d:d.value,h=typeof d=="string"?d:d.label;return n("option",{key:p,value:p},h)}))}else f=n("input",{...c,type:e.type==="date"?"date":i?"number":"text",min:e.min,max:e.max,step:e.step||(e.type==="money"||e.type==="percent"?"any":void 0),placeholder:e.placeholder});return n("div",{className:"caf-field"},n("label",{htmlFor:s},e.label||e.key),f,e.hint&&!o?n("small",{className:"caf-hint"},e.hint):null,o?n("small",{className:"caf-error"},o):null)}function Ct(e){if(e==="")return"";let t=Number(e);return Number.isFinite(t)?t:e}function ce(e,t,a,r,o){if(a.type==="file"){e.files[t]=r||null;let s=r?{name:r.name,size:r.size,type:r.type}:null;e.update(i=>o(i,s));return}e.update(s=>o(s,r))}function Ot({spec:e,ctx:t}){let a=e.fields||[];return n("div",{className:"caf-block caf-fields"},e.title?n("h2",{className:"caf-block-title"},e.title):null,a.map(r=>n(B,{key:r.key,field:r,data:t.data,value:t.data[r.key],onChange:o=>ce(t,r.key,r,o,(s,i)=>{s[r.key]=i})})))}function V({items:e,title:t}){let a=e.some(r=>r&&r.big);return n("div",{className:a?"caf-block caf-output caf-block-feature":"caf-block caf-output"},t?n("h2",{className:"caf-block-title"},t):null,n("div",{className:"caf-output-grid"},e.map((r,o)=>n("div",{key:r.label||o,className:r.big?"caf-stat caf-stat-big":"caf-stat"},n("span",{className:"caf-stat-label"},r.label),n("span",{className:"caf-stat-value"},z(r.value,r.format)),r.hint?n("small",{className:"caf-hint"},r.hint):null))))}function _t({spec:e,ctx:t}){let a=typeof e.output=="function"?e.output(t.data):e.output||[];return a.length?n(V,{items:a,title:e.title}):n("div",{className:"caf-block caf-empty"},e.empty||"Nothing to show yet.")}function Rt({spec:e}){let t=typeof e.banner=="string"?{title:e.banner}:e.banner||{},a=t.image?`linear-gradient(rgba(0,0,0,0.35), rgba(0,0,0,0.35)), url(${JSON.stringify(t.image)}) center / cover`:"linear-gradient(135deg, color-mix(in srgb, var(--caf-accent) 82%, #000), var(--caf-accent) 55%, color-mix(in srgb, var(--caf-accent) 72%, #fff))";return n("div",{className:"caf-banner",style:{background:a}},t.title?n("h2",{className:"caf-banner-title"},t.title):null,t.subtitle?n("p",{className:"caf-banner-sub"},t.subtitle):null)}function Lt({spec:e}){let t=typeof e.image=="string"?{src:e.image}:e.image||{},a=typeof t.src=="string"&&t.src.trim().startsWith("<svg");return n("figure",{className:"caf-block caf-image"},e.title?n("h2",{className:"caf-block-title"},e.title):null,a?n("div",{className:"caf-image-svg",dangerouslySetInnerHTML:{__html:t.src}}):n("img",{src:t.src,alt:t.caption||e.title||"",style:{objectFit:t.fit||"cover",maxHeight:t.height?`${t.height}px`:void 0}}),t.caption?n("figcaption",{className:"caf-hint"},t.caption):null)}function Mt({spec:e,ctx:t}){let a=typeof e.text=="function"?e.text(t.data):e.text;return n("div",{className:"caf-block caf-text"},e.title?n("h2",{className:"caf-block-title"},e.title):null,n("p",null,a))}function zt({spec:e,ctx:t}){let a=(typeof e.list=="function"?e.list(t.data):e.list)||[],r=typeof e.title=="string"?e.title:null,o=typeof e.title=="function"?e.title:s=>s.title??s.name??s.label??s.text??String(s);return a.length?n("div",{className:"caf-block caf-list"},r?n("h2",{className:"caf-block-title"},r):null,a.map((s,i)=>n("button",{key:s.id??i,className:"caf-row",type:"button",onClick:e.onSelect?()=>e.onSelect(s,t):void 0},n("span",{className:"caf-row-title"},o(s)),e.subtitle?n("span",{className:"caf-row-sub"},e.subtitle(s)):null))):n("div",{className:"caf-block caf-empty"},e.empty||"Nothing here yet.")}var Re=["bar","line","donut"];function Bt({spec:e,ctx:t}){let a=typeof e.chart=="function"?e.chart(t.data):e.chart,r=a&&a.items||[];if(!r.length)return n("div",{className:"caf-block caf-empty"},e.empty||"No data to chart yet.");let o=a.type||"bar";if(!Re.includes(o))throw new Error(`unknown chart type "${o}". Valid types: ${Re.join(", ")}.`);let s=t.colors(r.length),i=o==="bar"?It(r,a,s):o==="line"?Vt(r,a):Dt(r,a,s);return n("div",{className:"caf-block caf-chart"},e.title?n("h2",{className:"caf-block-title"},e.title):null,i)}function It(e,t,a){let r=Math.max(...e.map(o=>Number(o.value)||0),0)||1;return n("div",{className:"caf-bars"},e.map((o,s)=>n("div",{key:o.label??s,className:"caf-bar-row"},n("span",{className:"caf-bar-label"},o.label),n("div",{className:"caf-bar-track"},n("div",{className:"caf-bar-fill",style:{width:`${Math.max(2,(Number(o.value)||0)/r*100)}%`,background:a[s]}})),n("span",{className:"caf-bar-value"},z(o.value,t.format)))))}function Vt(e,t){let a=e.map(d=>Number(d.value)||0),r=Math.min(...a),s=Math.max(...a)-r||1,i=100,c=36,f=a.map((d,p)=>[a.length===1?i/2:p/(a.length-1)*i,c-3-(d-r)/s*(c-6)]),l=f[f.length-1];return n("div",{className:"caf-line"},n("svg",{viewBox:`0 0 ${i} ${c}`,className:"caf-line-svg",preserveAspectRatio:"none","aria-hidden":"true"},[.25,.5,.75].map(d=>n("line",{key:d,x1:0,x2:i,y1:c*d,y2:c*d,className:"caf-line-grid"})),n("polyline",{points:f.map(d=>d.join(",")).join(" "),className:"caf-line-path"}),n("circle",{cx:l[0],cy:l[1],r:1.6,className:"caf-line-dot"})),n("div",{className:"caf-line-meta"},n("span",{className:"caf-hint"},String(e[0].label??"")),n("span",{className:"caf-line-last"},z(a[a.length-1],t.format)),n("span",{className:"caf-hint"},String(e[e.length-1].label??""))))}function Dt(e,t,a){let r=e.reduce((c,f)=>c+(Number(f.value)||0),0)||1,o=15.9155,s=25,i=e.map((c,f)=>{let l=(Number(c.value)||0)/r*100,d=n("circle",{key:c.label??f,cx:21,cy:21,r:o,className:"caf-donut-seg",stroke:a[f],strokeDasharray:`${l} ${100-l}`,strokeDashoffset:s});return s-=l,d});return n("div",{className:"caf-donut"},n("svg",{viewBox:"0 0 42 42",className:"caf-donut-svg","aria-hidden":"true"},i),n("div",{className:"caf-donut-legend"},e.map((c,f)=>n("div",{key:c.label??f,className:"caf-legend-row"},n("span",{className:"caf-legend-swatch",style:{background:a[f]}}),n("span",{className:"caf-legend-label"},c.label),n("span",{className:"caf-legend-value"},z(c.value,t.format))))))}function Kt({spec:e,ctx:t}){let a=e.timer||{},r=Math.max(1,Math.round((a.minutes||0)*60+(a.seconds||0))||300),[o,s]=$(r),[i,c]=$(!1);A(()=>{if(!i)return;let p=setInterval(()=>s(h=>Math.max(0,h-1)),1e3);return()=>clearInterval(p)},[i]),A(()=>{o===0&&i&&(c(!1),typeof a.onDone=="function"&&t.update(p=>a.onDone(p)))},[o,i]);let f=String(Math.floor(o/60)).padStart(2,"0"),l=String(o%60).padStart(2,"0"),d=o===0;return n("div",{className:"caf-block caf-timer"},e.title?n("h2",{className:"caf-block-title"},e.title):null,a.label?n("span",{className:"caf-hint"},a.label):null,n("div",{className:d?"caf-timer-time caf-timer-done":"caf-timer-time"},d?a.doneText||"Done!":`${f}:${l}`),n("div",{className:"caf-bar-track"},n("div",{className:"caf-bar-fill caf-timer-fill",style:{width:`${o/r*100}%`}})),n("div",{className:"caf-timer-controls"},n("button",{type:"button",className:"caf-btn caf-btn-primary",disabled:d,onClick:()=>c(p=>!p)},i?"Pause":"Start"),n("button",{type:"button",className:"caf-btn",onClick:()=>{c(!1),s(r)}},"Reset")))}function Yt({spec:e,ctx:t}){let r=(e.actions||[]).filter(o=>!o.when||o.when(t.data,t.viewerId));return n("div",{className:"caf-block caf-actions"},e.title?n("h2",{className:"caf-block-title"},e.title):null,n("div",{className:"caf-actions-row"},r.map(o=>n("button",{key:o.label,type:"button",className:o.kind==="danger"?"caf-btn caf-btn-danger":o.kind==="primary"?"caf-btn caf-btn-primary":"caf-btn",onClick:()=>t.update(s=>o.run(s,t.viewerId))},o.label))))}function Ht({spec:e,ctx:t}){let a=e.custom(t),r=e.fill?"caf-block caf-block-fill caf-custom":"caf-block caf-custom";return typeof a=="string"?n("div",{className:r,dangerouslySetInnerHTML:{__html:a}}):n("div",{className:r},a)}var le={fields:Ot,output:_t,text:Mt,list:zt,chart:Bt,timer:Kt,actions:Yt,banner:Rt,image:Lt,chat:({spec:e,ctx:t})=>n(oe,{cfg:e.chat,ctx:t,title:e.title}),custom:Ht},U=Object.keys(le);function Be(e){return Object.entries(e.compute||{}).map(([t,a])=>[t,typeof a=="function"?{value:a}:a])}function J(e,t){if(!e.compute)return t;let a={...t};for(let[r,o]of Be(e))try{a[r]=o.value(t)}catch{a[r]=void 0}return a}function Ie(e){let t={};for(let a of e)t[a.key]=a.value!==void 0?a.value:a.type==="check"?!1:"";return t}function fe(){return"r"+Date.now().toString(36)+Math.random().toString(36).slice(2,8)}var Le=new WeakMap;function Me(e,t,a,r){let o=Le.get(e);if(o===void 0){let s=String(e),i=s.match(/^\s*(?:async\s+)?([\w$]+)\s*=>/),c=s.match(/^[^(]*\(([^)]*)\)/),f=i?[i[1]]:c?c[1].split(",").map(l=>l.trim().split(/[=\s:]/)[0]):[];o=/viewer|voter|usuario|user/i.test(f[1]||""),Le.set(e,o)}return o?e(t,r):e(t,a,r)}function Ft({title:e,ctx:t}){let a=String(e).split(/\s+/).map(s=>s[0]).filter(Boolean).slice(0,2).join("").toUpperCase()||"?",r=0;for(let s of String(e))r=r*31+s.charCodeAt(0)>>>0;let o=t.colors(8);return n("span",{className:"caf-avatar",style:{background:o[r%o.length]}},a)}function ze(e,t){if(e.title)return e.title(t);let a=e.fields.find(o=>!o.type||o.type==="text"||o.type==="textarea"||o.type==="select"),r=a&&t[a.key];return r===""||r===void 0||r===null?"(untitled)":String(r)}function Ve({spec:e,records:t}){if(!e.summary)return null;let a=e.summary(t)||[];return a.length?n(V,{items:a}):null}function De({spec:e,ctx:t}){let a=e.label||"item",[r,o]=$("");A(()=>{(t.data.records||[]).some(l=>l&&!l.id)&&t.update(l=>{for(let d of l.records||[])d&&!d.id&&(d.id=fe())})});let s=t.data.records.map(l=>J(e,l));e.sort&&(s=s.slice().sort(e.sort));let i=s.length,c=r.trim().toLowerCase();e.search&&c&&(s=s.filter(l=>e.fields.some(d=>String(l[d.key]??"").toLowerCase().includes(c))));function f(){let l={id:fe(),...Ie(e.fields)};e.items&&(l.items=[]),t.update(d=>{d.records=[...d.records,l]}),t.go("record",l.id)}return n("div",{className:"caf-block caf-list"},n("div",{className:"caf-toolbar"},n("span",{className:"caf-count"},e.search&&c?`${s.length} of ${i}`:`${i} ${a}${i===1?"":"s"}`),n("button",{type:"button",className:"caf-btn caf-btn-primary",onClick:f},`Add ${a}`)),e.search?n("input",{className:"caf-search",value:r,placeholder:`Search ${a}s\u2026`,"aria-label":"Search",onChange:l=>o(l.target.value)}):null,e.search&&c&&s.length===0&&i>0?n("div",{className:"caf-empty"},`Nothing matches "${r}".`):null,s.length===0?n("div",{className:"caf-empty"},e.empty||`No ${a}s yet. Add the first one.`):s.map(l=>n("div",{key:l.id,className:"caf-row-wrap"},n("button",{type:"button",className:e.avatar?"caf-row caf-row-avatar":"caf-row",onClick:()=>t.go("record",l.id)},e.avatar?n(Ft,{title:ze(e,l),ctx:t}):null,n("span",{className:"caf-row-main"},n("span",{className:"caf-row-title"},ze(e,l)),e.subtitle?n("span",{className:"caf-row-sub"},e.subtitle(l)):null)),e.actions?n("div",{className:"caf-row-actions"},e.actions.filter(d=>!d.when||Me(d.when,l,t.data,t.viewerId)).map(d=>n("button",{key:d.label,type:"button",className:d.kind==="danger"?"caf-btn caf-btn-danger caf-btn-sm":"caf-btn caf-btn-sm",onClick:()=>t.update(p=>{let h=p.records.find(k=>k.id===l.id);h&&Me(d.run,h,p,t.viewerId)})},d.label))):null)))}function Ke({spec:e,ctx:t,record:a}){let r=e.label||"item";function o(){t.update(s=>{s.records=s.records.filter(i=>i.id!==a.id)}),t.back()}return n("div",{className:"caf-block caf-fields"},n("div",{className:"caf-toolbar"},n("button",{type:"button",className:"caf-btn",onClick:t.back},"\u2039 Back"),n("button",{type:"button",className:"caf-btn caf-btn-danger",onClick:o},`Delete ${r}`)),e.fields.map(s=>n(B,{key:s.key,field:s,data:t.data,value:a[s.key],onChange:i=>t.update(c=>{let f=c.records.find(l=>l.id===a.id);f&&(f[s.key]=i)})})),e.items?n(Pt,{spec:e,ctx:t,record:a}):null,e.compute?n("div",{className:"caf-output-grid caf-computed"},Be(e).map(([s,i])=>{let c=J(e,a);return n("div",{key:s,className:"caf-stat"},n("span",{className:"caf-stat-label"},i.label||s),n("span",{className:"caf-stat-value"},z(c[s],i.format)))})):null)}function Pt({spec:e,ctx:t,record:a}){let r=e.items,o=r.label||"item";function s(c){t.update(f=>{let l=f.records.find(d=>d.id===a.id);l&&(Array.isArray(l.items)||(l.items=[]),c(l))})}let i=Array.isArray(a.items)?a.items:[];return n("div",{className:"caf-items"},n("div",{className:"caf-toolbar"},n("span",{className:"caf-count"},`${i.length} ${o}${i.length===1?"":"s"}`),n("button",{type:"button",className:"caf-btn caf-btn-sm",onClick:()=>s(c=>c.items.push({id:fe(),...Ie(r.fields)}))},`Add ${o}`)),i.length===0?n("div",{className:"caf-empty caf-empty-sm"},r.empty||`No ${o}s yet.`):i.map(c=>n("div",{key:c.id,className:"caf-item-row"},r.fields.map(f=>n(B,{key:f.key,field:f,data:t.data,value:c[f.key],onChange:l=>s(d=>{let p=d.items.find(h=>h.id===c.id);p&&(p[f.key]=l)})})),n("button",{type:"button",className:"caf-btn caf-btn-danger caf-btn-sm caf-item-remove","aria-label":`Remove ${o}`,onClick:()=>s(f=>{f.items=f.items.filter(l=>l.id!==c.id)})},"\u2715"))))}function Ut(e,t){return t==="records"?e:new Proxy(e,{get:(a,r,o)=>r==="records"?a[t]:Reflect.get(a,r,o),set:(a,r,o)=>Reflect.set(a,r==="records"?t:r,o),has:(a,r)=>r==="records"?t in a:r in a})}function Ye({spec:e,ctx:t}){let a=e.records,r=a.key||"records",o=Array.isArray(t.data[r])?t.data[r]:[],s="caf:rec:"+r,i=t.view.tabs?t.view.tabs[s]:void 0,c={...t,data:{...t.data,records:o},update:l=>t.update(d=>l(Ut(d,r))),go:(l,d)=>t.setTab(s,d),back:()=>t.setTab(s,void 0)},f=i?o.find(l=>l.id===i):null;return n("div",{className:"caf-records-block"},e.title?n("h2",{className:"caf-block-title"},e.title):null,f?n(Ke,{key:"d",spec:a,ctx:c,record:f}):[n(Ve,{key:"s",spec:a,records:o.map(l=>J(a,l))}),n(De,{key:"l",spec:a,ctx:c})])}function He({spec:e,ctx:t}){let a=e.records;if(t.view.screen==="record"){let r=t.data.records.find(o=>o.id===t.view.arg);if(r)return n("div",{className:"caf-panel caf-panel-single"},n(Ke,{spec:a,ctx:t,record:r}))}return n("div",{className:"caf-panel caf-panel-single"},n(Ve,{spec:a,records:t.data.records.map(r=>J(a,r))}),n(De,{spec:a,ctx:t}))}function Jt(e,t){return(e.fields||[]).some(a=>ie(a,t[a.key])!==null)}function Wt({step:e,ctx:t}){let a=e.result(t.data)||[],r=t._Block;return n("div",{className:"caf-steps-result"},n(V,{items:a,title:e.title}),(e.blocks||[]).map((o,s)=>n(r,{key:"rb"+s,block:o,ctx:t})),n("div",{className:"caf-step-nav"},n("button",{type:"button",className:"caf-btn",onClick:()=>t.setStep(0)},"Start over")))}function Fe({spec:e,ctx:t}){let a=e.steps,r=Math.min(Math.max(t.view.step||0,0),a.length-1),o=a[r],s=typeof o.result=="function",i=r===a.length-1;return n("div",{className:"caf-panel caf-panel-single"},n("div",{className:"caf-steps-progress"},n("span",{className:"caf-hint"},s?"Result":`Step ${r+1} of ${a.length}`),n("div",{className:"caf-bar-track"},n("div",{className:"caf-bar-fill caf-steps-fill",style:{width:`${(r+1)/a.length*100}%`}}))),s?n(Wt,{step:o,ctx:t}):n("div",{className:"caf-block caf-fields"},o.title?n("h2",{className:"caf-block-title"},o.title):null,o.text?n("p",{className:"caf-step-text"},typeof o.text=="function"?o.text(t.data):o.text):null,(o.fields||[]).map(c=>n(B,{key:c.key,field:c,data:t.data,value:t.data[c.key],onChange:f=>ce(t,c.key,c,f,(l,d)=>{l[c.key]=d})})),n("div",{className:"caf-step-nav"},r>0?n("button",{type:"button",className:"caf-btn",onClick:()=>t.setStep(r-1)},"\u2039 Back"):n("span"),i?null:n("button",{type:"button",className:"caf-btn caf-btn-primary",disabled:Jt(o,t.data),onClick:()=>t.setStep(r+1)},"Next \u203A"))))}var Pe=["panel","records","steps","chat","workspace","documents"],qt=["title","empty","wide","onSelect","subtitle","when","collapsible","fill","state","icon"],Ue=["logo","footer"],Je=["image","title","subtitle"],We=["src","caption","fit","height"],qe=["title","subtitle","theme","layout","blocks","records","steps","chat","data","shared","main","sidebar","libs","documents","machine","brand","mobile"],Ge=["nav"],Xe=["key","initial","states","events"],Qe=["after"],Ze=["seconds","then","do"],et=["from","do","then"],tt=["label","title","blocks","empty","types"],at=["label","fields","title","subtitle","sort","summary","empty","search","compute","items","actions","avatar"],rt=["label","fields","empty"];function q(e,t){for(let a of e||[]){if(!a||!a.key)throw new Error(`claude-artifact-framework: every field in ${t} needs a \`key\`.`);if(a.type!==void 0&&!se.includes(a.type))throw new Error(`claude-artifact-framework: field "${a.key}" in ${t} has unknown type "${a.type}". Valid types: ${se.join(", ")}.`);if(a.type==="select"&&a.options!==void 0&&!Array.isArray(a.options)&&typeof a.options!="function")throw new Error(`claude-artifact-framework: field "${a.key}" in ${t}: \`options\` must be an array or a function of data returning one.`)}}function it(e,t){if(!e||typeof e.system!="string"&&typeof e.system!="function")throw new Error(`claude-artifact-framework: ${t} needs \`{ system: "..." }\` (a string or a function of data).`);let a=Object.keys(e).filter(r=>!ne.includes(r));if(a.length)throw new Error(`claude-artifact-framework: ${t} has unknown keys (${a.join(", ")}). Valid keys: ${ne.join(", ")}.`);for(let[r,o]of Object.entries(e.tools||{}))if(!o||typeof o.description!="string"||typeof o.run!="function")throw new Error(`claude-artifact-framework: chat tool "${r}" needs a \`description\` string and a \`run(input, ctx)\` function.`)}var nt=["label","run","when","kind"];function ct(e,t){if(!Array.isArray(e))throw new Error(`claude-artifact-framework: ${t} must be an array of { label, run }.`);e.forEach((a,r)=>{if(!a||typeof a.label!="string"||typeof a.run!="function")throw new Error(`claude-artifact-framework: ${t}[${r}] needs a \`label\` string and a \`run\` function.`);let o=Object.keys(a).filter(s=>!nt.includes(s));if(o.length)throw new Error(`claude-artifact-framework: ${t}[${r}] has unknown keys (${o.join(", ")}). Valid keys: ${nt.join(", ")}.`)})}function R(e){if(!Array.isArray(e))throw new Error("claude-artifact-framework: `blocks` must be an array.");e.forEach((t,a)=>{if(!t||typeof t!="object")throw new Error(`claude-artifact-framework: blocks[${a}] must be an object like { fields: [...] }.`);let r=Object.keys(t).filter(s=>!qt.includes(s)),o=r.filter(s=>U.includes(s)||s==="tabs"||s==="records");if(o.length===0)throw new Error(`claude-artifact-framework: blocks[${a}] has no recognised block type (found: ${r.join(", ")||"nothing"}). Valid block types: ${[...U,"tabs","records"].join(", ")}.`);if(o.length>1)throw new Error(`claude-artifact-framework: blocks[${a}] declares more than one block type (${o.join(", ")}). Split them into separate entries of \`blocks\`.`);if(q(t.fields,`blocks[${a}]`),o[0]==="actions"&&ct(t.actions,`blocks[${a}].actions`),o[0]==="chat"&&it(t.chat,`blocks[${a}].chat`),o[0]==="records"&&ft(t.records,`blocks[${a}].records`,!0),o[0]==="banner"&&typeof t.banner=="object"&&t.banner!==null){let s=Object.keys(t.banner).filter(i=>!Je.includes(i));if(s.length)throw new Error(`claude-artifact-framework: blocks[${a}].banner has unknown keys (${s.join(", ")}). Valid keys: ${Je.join(", ")}.`)}if(o[0]==="image"&&typeof t.image=="object"&&t.image!==null){let s=Object.keys(t.image).filter(i=>!We.includes(i));if(s.length)throw new Error(`claude-artifact-framework: blocks[${a}].image has unknown keys (${s.join(", ")}). Valid keys: ${We.join(", ")}.`)}if(t.icon!==void 0&&typeof t.icon!="string")throw new Error(`claude-artifact-framework: blocks[${a}].icon must be a string (an emoji works best).`);if(o[0]==="tabs"){let s=t.tabs;if(!Array.isArray(s)||s.length===0)throw new Error(`claude-artifact-framework: blocks[${a}].tabs needs an array of { label, blocks: [...] }.`);s.forEach((i,c)=>{if(!i||typeof i.label!="string"||!Array.isArray(i.blocks)||i.blocks.length===0)throw new Error(`claude-artifact-framework: tabs[${c}] needs a \`label\` string and a non-empty \`blocks\` array.`);if(i.blocks.some(f=>f&&f.tabs))throw new Error("claude-artifact-framework: tabs cannot nest inside tabs.");R(i.blocks)})}if(t.when!==void 0&&typeof t.when!="function")throw new Error(`claude-artifact-framework: blocks[${a}].when must be a function of data returning true/false.`);if(t.fill!==void 0&&o[0]!=="custom")throw new Error(`claude-artifact-framework: \`fill\` is only valid on custom blocks \u2014 blocks[${a}] is "${o[0]}".`)})}function Gt(e){let t=Object.keys(e).filter(s=>!Xe.includes(s));if(t.length)throw new Error(`claude-artifact-framework: machine has unknown keys (${t.join(", ")}). Valid keys: ${Xe.join(", ")}.`);if(e.key!==void 0&&(typeof e.key!="string"||!e.key))throw new Error("claude-artifact-framework: machine.key must be a non-empty string (where the current state lives in data).");let a=Object.keys(e.states||{});if(!a.length)throw new Error("claude-artifact-framework: machine needs `states: { nombre: {...} }` with at least one state.");let r=(s,i)=>{if(!a.includes(s))throw new Error(`claude-artifact-framework: ${i} names unknown state "${s}". Valid states: ${a.join(", ")}.`)};if(typeof e.initial!="string")throw new Error('claude-artifact-framework: machine needs `initial: "..."` naming the starting state.');r(e.initial,"machine.initial");for(let[s,i]of Object.entries(e.states)){let c=Object.keys(i||{}).filter(f=>!Qe.includes(f));if(c.length)throw new Error(`claude-artifact-framework: machine.states.${s} has unknown keys (${c.join(", ")}). Valid keys: ${Qe.join(", ")}.`);if(i&&i.after!==void 0){let f=i.after,l=Object.keys(f||{}).filter(d=>!Ze.includes(d));if(l.length)throw new Error(`claude-artifact-framework: machine.states.${s}.after has unknown keys (${l.join(", ")}). Valid keys: ${Ze.join(", ")}.`);if(typeof f.seconds!="number"||f.seconds<=0)throw new Error(`claude-artifact-framework: machine.states.${s}.after needs \`seconds\` > 0.`);if(typeof f.then!="string")throw new Error(`claude-artifact-framework: machine.states.${s}.after needs \`then: "estado"\`.`);if(r(f.then,`machine.states.${s}.after.then`),f.do!==void 0&&typeof f.do!="function")throw new Error(`claude-artifact-framework: machine.states.${s}.after.do must be a function of data.`)}}if(!Object.keys(e.events||{}).length)throw new Error("claude-artifact-framework: machine needs `events: { nombre: {...} }` \u2014 ctx.send() is the only way to move it.");for(let[s,i]of Object.entries(e.events)){let c=Object.keys(i||{}).filter(f=>!et.includes(f));if(c.length)throw new Error(`claude-artifact-framework: machine.events.${s} has unknown keys (${c.join(", ")}). Valid keys: ${et.join(", ")}.`);if(i.from!==void 0&&i.from!=="*")for(let f of[].concat(i.from))r(f,`machine.events.${s}.from`);if(typeof i.then=="string")r(i.then,`machine.events.${s}.then`);else if(i.then!==void 0&&typeof i.then!="function")throw new Error(`claude-artifact-framework: machine.events.${s}.then must be a state name or a function of data returning one.`);if(i.do!==void 0&&typeof i.do!="function")throw new Error(`claude-artifact-framework: machine.events.${s}.do must be a function (data, payload).`)}}function lt(e){for(let t of[e.blocks,e.main]){if(!Array.isArray(t))continue;let a=t.find(r=>r&&Array.isArray(r.tabs));if(a)return a}return null}function Xt(e){let t=Object.keys(e).filter(r=>!qe.includes(r));if(t.length)throw new Error(`claude-artifact-framework: unknown top-level keys (${t.join(", ")}). Valid keys: ${qe.join(", ")}.`);if(e.machine!==void 0&&Gt(e.machine),e.brand!==void 0){let r=Object.keys(e.brand||{}).filter(o=>!Ue.includes(o));if(r.length)throw new Error(`claude-artifact-framework: brand has unknown keys (${r.join(", ")}). Valid keys: ${Ue.join(", ")}.`);if(e.brand.logo!==void 0&&typeof e.brand.logo!="string")throw new Error("claude-artifact-framework: brand.logo must be a string \u2014 an emoji, an inline <svg>...</svg>, or an https URL. Omit it for an automatic monogram.")}if(e.libs!==void 0&&(!Array.isArray(e.libs)||e.libs.some(r=>typeof r!="string"||!/^https?:\/\//.test(r))))throw new Error("claude-artifact-framework: `libs` must be an array of https:// script URLs.");if(e.mobile!==void 0){let r=Object.keys(e.mobile||{}).filter(o=>!Ge.includes(o));if(r.length)throw new Error(`claude-artifact-framework: mobile has unknown keys (${r.join(", ")}). Valid keys: ${Ge.join(", ")}.`);if(e.mobile.nav!==void 0&&e.mobile.nav!=="bottom")throw new Error('claude-artifact-framework: mobile.nav only accepts "bottom" (omit `mobile` for the default top tab bar).');if(e.mobile.nav==="bottom"&&!lt(e))throw new Error('claude-artifact-framework: mobile.nav: "bottom" moves a top-level `tabs` block\'s bar to the bottom of the phone screen \u2014 this spec has no top-level tabs block (in `blocks` or `main`) to move.')}let a=e.layout||"panel";if(!Pe.includes(a))throw new Error(`claude-artifact-framework: unknown layout "${a}". Valid layouts: ${Pe.join(", ")}.`);if(a==="steps"){let r=e.steps;if(!Array.isArray(r)||r.length===0)throw new Error('claude-artifact-framework: layout "steps" needs `steps: [...]` with at least one step.');let o=["title","text","fields","result","blocks"],s=new Set;return r.forEach((i,c)=>{if(!i||typeof i!="object")throw new Error(`claude-artifact-framework: steps[${c}] must be an object.`);let f=Object.keys(i).filter(l=>!o.includes(l));if(f.length)throw new Error(`claude-artifact-framework: steps[${c}] has unknown keys (${f.join(", ")}). Valid keys: ${o.join(", ")}.`);if(!i.fields&&!i.text&&!i.result)throw new Error(`claude-artifact-framework: steps[${c}] needs \`fields\`, \`text\`, or \`result\`.`);if(i.blocks!==void 0){if(typeof i.result!="function")throw new Error(`claude-artifact-framework: steps[${c}].blocks only renders on a result step \u2014 add \`result\` or move the blocks to the step's fields.`);R(i.blocks)}q(i.fields,`steps[${c}]`);for(let l of i.fields||[]){if(s.has(l.key))throw new Error(`claude-artifact-framework: field key "${l.key}" appears in more than one step \u2014 keys share one data pool and must be unique.`);s.add(l.key)}}),a}if(a==="chat")return it(e.chat,"chat"),a;if(a==="workspace"){if(!Array.isArray(e.main)||e.main.length===0)throw new Error('claude-artifact-framework: layout "workspace" needs `main: [...]` (an array of blocks). `sidebar: [...]` is optional.');if(R(e.main),e.sidebar!==void 0){if(!Array.isArray(e.sidebar))throw new Error("claude-artifact-framework: workspace `sidebar` must be an array of blocks.");R(e.sidebar)}let r=C([...e.main,...e.sidebar||[]]);if(r.filter(s=>s&&s.chat).length>1)throw new Error("claude-artifact-framework: only one chat block per app \u2014 the conversation persists under data.chat and there is exactly one.");return de(r),a}if(a==="documents"){let r=e.documents;if(!r||typeof r!="object"||!r.blocks&&!r.types)throw new Error('claude-artifact-framework: layout "documents" needs `documents: { blocks: [...] }` (every document repeats the same blocks) or `documents: { types: {...} }` (each document is one of several kinds).');if(r.blocks&&r.types)throw new Error("claude-artifact-framework: documents takes `blocks` (uniform documents) OR `types` (typed documents) \u2014 not both.");let o=Object.keys(r).filter(i=>!tt.includes(i));if(o.length)throw new Error(`claude-artifact-framework: documents has unknown keys (${o.join(", ")}). Valid keys: ${tt.join(", ")}.`);if(r.title!==void 0&&typeof r.title!="function")throw new Error("claude-artifact-framework: documents.title must be a function of the document's data returning the tab label.");let s=(i,c)=>{R(i);let f=C(i);if(f.filter(l=>l&&l.chat).length>1)throw new Error(`claude-artifact-framework: only one chat block per document (${c}) \u2014 each document's conversation persists under its own data.chat and there is exactly one.`);de(f)};if(r.blocks){if(!Array.isArray(r.blocks)||r.blocks.length===0)throw new Error("claude-artifact-framework: documents.blocks must be a non-empty array of blocks.");s(r.blocks,"documents.blocks")}else{let i=Object.keys(r.types||{});if(!i.length)throw new Error("claude-artifact-framework: documents.types needs at least one type, e.g. `types: { nota: { blocks: [...] } }`.");for(let c of i){let f=r.types[c],l=["label","title","blocks","empty","icon"],d=Object.keys(f||{}).filter(p=>!l.includes(p));if(d.length)throw new Error(`claude-artifact-framework: documents.types.${c} has unknown keys (${d.join(", ")}). Valid keys: ${l.join(", ")}.`);if(!f||!Array.isArray(f.blocks)||f.blocks.length===0)throw new Error(`claude-artifact-framework: documents.types.${c} needs a non-empty \`blocks\` array.`);if(f.title!==void 0&&typeof f.title!="function")throw new Error(`claude-artifact-framework: documents.types.${c}.title must be a function of the document's data.`);s(f.blocks,`documents.types.${c}`)}}return a}if(a==="records"){if(ft(e.records,"records",!1),e.blocks&&(R(e.blocks),C(e.blocks).some(r=>r&&r.records)))throw new Error("claude-artifact-framework: a records BLOCK below a records LAYOUT is ambiguous \u2014 the layout already owns the collection. Use panel/workspace/documents to embed records blocks.");return a}return R(e.blocks||[]),de(C(e.blocks||[])),a}function ft(e,t,a){if(!e||!Array.isArray(e.fields)||e.fields.length===0)throw new Error(`claude-artifact-framework: ${t} needs \`records: { fields: [...] }\` \u2014 the same field declarations the fields block uses.`);let r=a?[...at,"key"]:at,o=Object.keys(e).filter(i=>!r.includes(i));if(o.length)throw new Error(`claude-artifact-framework: ${t} has unknown keys (${o.join(", ")}). Valid keys: ${r.join(", ")}.`);if(a&&e.key!==void 0&&(typeof e.key!="string"||!e.key))throw new Error(`claude-artifact-framework: ${t}.key must be a non-empty string naming the collection in data.`);if(q(e.fields,t),e.fields.some(i=>i.type==="file")||e.items&&e.items.fields.some(i=>i.type==="file"))throw new Error("claude-artifact-framework: `file` fields live in the flat data pool (panel blocks or steps) \u2014 they are not supported inside records or items.");let s=new Set;for(let i of e.fields){if(i.key==="id")throw new Error('claude-artifact-framework: "id" is reserved on records \u2014 the framework assigns it.');if(s.has(i.key))throw new Error(`claude-artifact-framework: duplicate ${t} field key "${i.key}".`);s.add(i.key)}if(e.actions&&ct(e.actions,`${t}.actions`),e.items){let i=Object.keys(e.items).filter(c=>!rt.includes(c));if(i.length)throw new Error(`claude-artifact-framework: ${t}.items has unknown keys (${i.join(", ")}). Valid keys: ${rt.join(", ")}.`);if(!Array.isArray(e.items.fields)||e.items.fields.length===0)throw new Error(`claude-artifact-framework: ${t}.items needs \`fields: [...]\` \u2014 the same field declarations as everywhere else.`);q(e.items.fields,`${t}.items`);for(let c of e.items.fields)if(c.key==="id")throw new Error('claude-artifact-framework: "id" is reserved on items \u2014 the framework assigns it.');if(s.has("items")||e.fields.some(c=>c.key==="items"))throw new Error(`claude-artifact-framework: a ${t} field cannot be named "items" when \`items\` is declared \u2014 that key holds the child collection.`)}for(let[i,c]of Object.entries(e.compute||{})){if(s.has(i)||i==="id"||e.items&&i==="items")throw new Error(`claude-artifact-framework: compute key "${i}" collides with a field key \u2014 computed values are derived, never stored.`);if(typeof c!="function"&&typeof(c&&c.value)!="function")throw new Error(`claude-artifact-framework: compute "${i}" must be a function of the record, or { label, format, value: (r) => ... }.`)}}function de(e){let t=new Set;for(let a of e){if(!a||!a.records)continue;let r=a.records.key||"records";if(t.has(r))throw new Error(`claude-artifact-framework: two records blocks share the collection key "${r}" \u2014 give each a distinct \`key\`.`);t.add(r)}}function C(e){let t=[];for(let a of e||[])if(t.push(a),a&&Array.isArray(a.tabs))for(let r of a.tabs)t.push(...C(r.blocks));return t}function Qt(e){let t={...e.data||{}};if((e.layout||"panel")==="records"&&!Array.isArray(t.records)&&(t.records=[]),(e.layout||"panel")==="documents"&&!Array.isArray(t.docs)&&(t.docs=[]),e.machine){let o=e.machine.key||"fase";o in t||(t[o]=e.machine.initial)}let a=C([...e.blocks||[],...e.main||[],...e.sidebar||[]]);((e.layout||"panel")==="chat"||a.some(o=>o&&o.chat))&&!t.chat&&(t.chat={api:[],log:[]});for(let o of[...a,...e.steps||[]])for(let s of o.fields||[])s&&s.key!==void 0&&!(s.key in t)&&(t[s.key]=s.value!==void 0?s.value:s.type==="check"?!1:"");for(let o of a)if(o&&o.records){let s=o.records.key||"records";Array.isArray(t[s])||(t[s]=[])}return t}var ue=null;function dt(e){return ue||(ue=class extends e.Component{constructor(t){super(t),this.state={error:null}}static getDerivedStateFromError(t){return{error:t}}render(){return this.state.error?n("div",{className:"caf-block caf-block-error"},n("strong",null,"This section failed to render"),n("code",null,String(this.state.error.message||this.state.error))):this.props.children}}),ue}function Zt({spec:e,ctx:t,bottomNav:a}){let r=e.tabs,o=r.map(f=>f.label).join("|"),s=t.view.tabs?t.view.tabs[o]:void 0,i=Math.min(s===void 0?0:s,r.length-1),c=!!a&&t.viewport==="mobile";return n("div",{className:"caf-tabs"},n("div",{className:c?"caf-tabbar caf-tabbar-bottom":"caf-tabbar",role:"tablist"},r.map((f,l)=>n("button",{key:f.label,type:"button",role:"tab","aria-selected":l===i,className:l===i?"caf-tab caf-tab-active":"caf-tab",onClick:()=>t.setTab(o,l)},c&&f.icon?[n("span",{key:"i",className:"caf-tab-ico","aria-hidden":!0},f.icon),n("span",{key:"l",className:"caf-tab-lbl"},f.label)]:f.icon?`${f.icon} ${f.label}`:f.label))),n("div",{className:"caf-tabs-body"},r[i].blocks.map((f,l)=>n(D,{key:i+":"+l,block:f,ctx:t}))))}var ea={...le,tabs:Zt,records:Ye},ta=[...U,"tabs","records"];function D({block:e,ctx:t}){if(typeof e.when=="function"&&!e.when(t.data)||e.state!==void 0&&t.machine&&t.data[t.machine.key||"fase"]!==e.state)return null;let a=t._navTabs!==void 0&&t._navTabs===e;e.icon&&typeof e.title=="string"&&(e={...e,title:`${e.icon} ${e.title}`});let r=Object.keys(e).find(f=>ta.includes(f)),o=ea[r],s=n(dt(t.React),null,n(o,{spec:e.collapsible?{...e,title:void 0}:e,ctx:t,bottomNav:a}));if(!e.collapsible)return s;let i=typeof e.title=="string"&&e.title?e.title:r,c=t.view.collapsed&&i in t.view.collapsed?t.view.collapsed[i]:e.collapsible==="collapsed";return n("div",{className:"caf-collapse"},n("button",{type:"button",className:"caf-collapse-head","aria-expanded":!c,onClick:()=>t.toggleCollapsed(i,!c)},n("span",null,e.title||r),n("span",{className:c?"caf-chevron caf-chevron-closed":"caf-chevron"},"\u25BE")),c?null:n("div",{className:"caf-collapse-body"},s))}function ut({spec:e,ctx:t}){return n("div",{className:"caf-panel"},(e.blocks||[]).map((a,r)=>n("section",{key:r,className:a.wide||a.collapsible||a.banner?"caf-slot caf-slot-wide":"caf-slot"},n(D,{block:a,ctx:t}))))}function aa({spec:e,ctx:t}){let a=t.view.screen==="record"&&(t.data.records||[]).some(r=>r.id===t.view.arg);return n("div",null,n(He,{spec:e,ctx:t}),!a&&Array.isArray(e.blocks)&&e.blocks.length?n("div",{className:"caf-panel caf-records-blocks"},e.blocks.map((r,o)=>n("section",{key:o,className:r.wide||r.collapsible||r.banner?"caf-slot caf-slot-wide":"caf-slot"},n(D,{block:r,ctx:t})))):null)}function ra({spec:e,ctx:t}){let a=r=>(r||[]).map((o,s)=>n("section",{key:s,className:"caf-ws-slot"},n(D,{block:o,ctx:t})));return n("div",{className:"caf-workspace"},n("div",{className:"caf-ws-main"},a(e.main)),e.sidebar&&e.sidebar.length?n("div",{className:"caf-ws-side"},a(e.sidebar)):null)}function me(e){let t={};for(let a of C(e.blocks)){for(let r of a.fields||[])r&&r.key!==void 0&&!(r.key in t)&&(t[r.key]=r.value!==void 0?r.value:r.type==="check"?!1:"");if(a.records){let r=a.records.key||"records";Array.isArray(t[r])||(t[r]=[])}}return t}function na(){return"d"+Date.now().toString(36)+Math.random().toString(36).slice(2,8)}var W="caf:doc";function oa(e,t,a){if(e.title)try{let r=e.title(t);if(r!=null&&r!=="")return String(r)}catch{}for(let r of C(e.blocks))for(let o of r.fields||[])if(!o.type||o.type==="text"||o.type==="textarea"||o.type==="select"){let s=t[o.key];return s!==""&&s!==void 0&&s!==null?String(s):a||"(untitled)"}return a||"(untitled)"}function sa({spec:e,ctx:t}){let a=e.documents,r=a.label||"document",o=Array.isArray(t.data.docs)?t.data.docs:[],s=a.types||null,i=s?Object.keys(s):[],c=b=>s?s[b.type]:a,f=b=>{let E=s[b]||{};return(E.icon?E.icon+" ":"")+(E.label||b)},[l,d]=$(!1),p=t.view.tabs?t.view.tabs[W]:void 0,h=o.find(b=>b.id===p)||o[0];function k(b){let E=s?s[b]:a,N={id:na(),...s?{type:b}:{},data:me(E)};t.update(T=>{T.docs=[...T.docs||[],N]}),t.setTab(W,N.id),d(!1)}function g(){if(!s)return k();if(i.length===1)return k(i[0]);d(b=>!b)}function x(b){let E=o.findIndex(N=>N.id===b);if(t.update(N=>{N.docs=N.docs.filter(T=>T.id!==b)}),delete t.files["doc:"+b],h&&h.id===b){let N=o[E+1]||o[E-1];N&&t.setTab(W,N.id)}}let y=s&&l?n("div",{className:"caf-doc-typemenu"},i.map(b=>n("button",{key:b,type:"button",className:"caf-btn caf-btn-sm",onClick:()=>k(b)},f(b)))):null;if(!h)return n("div",{className:"caf-panel caf-panel-single"},n("div",{className:"caf-block caf-empty"},n("p",null,a.empty||`No ${r}s yet. Create the first one.`),s?n("div",{className:"caf-doc-typemenu"},i.map(b=>n("button",{key:b,type:"button",className:"caf-btn caf-btn-primary",onClick:()=>k(b)},`New ${f(b)}`))):n("button",{type:"button",className:"caf-btn caf-btn-primary",onClick:()=>k()},`New ${r}`)));let j=c(h);if(!j)return n("div",{className:"caf-documents"},n(ot,{docs:o,active:h,dspec:a,types:s,close:x,onAdd:g,label:r,ctx:t}),y,n("div",{className:"caf-block caf-block-error"},n("strong",null,`This ${r}'s type "${h.type}" no longer exists`),n("code",null,`valid types: ${i.join(", ")}`)));let u={...me(j),...h.data},w={...t,data:u,update:b=>t.update(E=>{let N=(E.docs||[]).find(T=>T.id===h.id);N&&b(N.data)}),files:t.files["doc:"+h.id]=t.files["doc:"+h.id]||{}};return n("div",{className:"caf-documents"},n(ot,{docs:o,active:h,dspec:a,types:s,close:x,onAdd:g,label:r,ctx:t}),y,n(ut,{key:h.id,spec:{blocks:j.blocks},ctx:w}))}function ot({docs:e,active:t,dspec:a,types:r,close:o,onAdd:s,label:i,ctx:c}){let f=l=>{let d=r?r[l.type]:a;if(!d)return l.type;let p={...me(d),...l.data},h=r?d.label||l.type:void 0;return oa(d,p,h)};return n("div",{className:"caf-tabbar",role:"tablist"},e.map(l=>n("span",{key:l.id,className:"caf-doc-tab"},n("button",{type:"button",role:"tab","aria-selected":l.id===t.id,className:l.id===t.id?"caf-tab caf-tab-active":"caf-tab",onClick:()=>c.setTab(W,l.id)},f(l)),n("button",{type:"button",className:"caf-doc-close","aria-label":`Close ${i}`,onClick:()=>o(l.id)},"\u2715"))),n("button",{type:"button",className:"caf-tab caf-doc-add","aria-label":`New ${i}`,onClick:s},"+"))}var ia={panel:ut,records:aa,steps:Fe,chat:_e,workspace:ra,documents:sa};function mt(e){return new Promise((t,a)=>{let r=document.querySelector(`script[src="${e}"]`);if(r){if(r.dataset.cafReady==="1")return t();r.addEventListener("load",t),r.addEventListener("error",()=>a(new Error(`failed to load ${e}`)));return}let o=document.createElement("script");o.src=e,o.onload=()=>{o.dataset.cafReady="1",t()},o.onerror=()=>{let s=e.match(/^(https:\/\/cdn\.jsdelivr\.net\/npm\/(?:@[^/]+\/)?[^/]+)\/.+/);s&&s[1]!==e?mt(s[1]).then(t,()=>a(new Error(`failed to load ${e} (also tried package default ${s[1]})`))):a(new Error(`failed to load ${e}`))},document.head.appendChild(o)})}function st(e){let t=e.documents?e.documents.blocks||Object.values(e.documents.types||{}).flatMap(a=>a.blocks||[]):[];return C([...e.blocks||[],...e.main||[],...e.sidebar||[],...t])}function ca(e,t,a,r){let o=e.events[a];if(!o)throw new Error(`claude-artifact-framework: unknown machine event "${a}". Valid events: ${Object.keys(e.events).join(", ")}.`);let s=e.key||"fase";t(i=>{let c=i[s],f=o.from===void 0?"*":o.from;if(f!=="*"&&![].concat(f).includes(c))return;o.do&&o.do(i,r);let l=typeof o.then=="function"?o.then(i):o.then;if(l!=null){if(!e.states[l])throw new Error(`claude-artifact-framework: machine event "${a}" resolved to unknown state "${l}". Valid states: ${Object.keys(e.states).join(", ")}.`);i[s]=l}})}function pt(e={}){let t=Xt(e);if(e.machine){let s=Object.keys(e.machine.states);for(let i of st(e))if(i&&i.state!==void 0&&!s.includes(i.state))throw new Error(`claude-artifact-framework: a block declares state: "${i.state}" but the machine's states are: ${s.join(", ")}.`)}else for(let s of st(e))if(s&&s.state!==void 0)throw new Error("claude-artifact-framework: `state:` on a block needs a `machine` declared at the top level.");let a=Se(Qt(e),{shared:!!e.shared}),r=P(e.theme&&e.theme.seed)+la,o={};return function(){if(!K())throw new Error(`claude-artifact-framework: React not found. Hand it over once, before rendering:
28
+ Continue with this information. If you have everything you need, answer in natural language without further tool_call.`}],S(),f(null)}}catch(g){w=[...w,{role:"error",content:String(g&&g.message||g)}],S()}finally{f(null),c(!1)}}return o("div",{className:"caf-chat-panel"},o("div",{className:"caf-block caf-chat-card"},a?o("h2",{className:"caf-block-title"},a):null,o("div",{className:"caf-chat-log"},r.greeting?o("div",{className:"caf-msg caf-msg-assistant",dangerouslySetInnerHTML:{__html:ne(r.greeting)}}):null,h.map((m,v)=>o(Tt,{key:v,m})),l!==null?o("div",{className:"caf-msg caf-msg-assistant caf-msg-live",dangerouslySetInnerHTML:{__html:ne(l||"\u2026")}}):null,i&&l===null?o("div",{className:"caf-msg-tools"},"thinking\u2026"):null,o("div",{ref:d})),o("div",{className:"caf-chat-input"},o("input",{value:n,placeholder:r.placeholder||"Message\u2026",disabled:i,enterKeyHint:"send",onChange:m=>s(m.target.value),onKeyDown:m=>{m.key==="Enter"&&(m.preventDefault(),u())},"aria-label":"Message"}),o("button",{type:"button",className:"caf-btn caf-btn-primary",disabled:i||!n.trim(),onClick:u},"Send"))))}function Re({spec:e,ctx:t}){return o("div",{className:"caf-panel caf-panel-single"},o(se,{cfg:e.chat,ctx:t}))}var ie=["text","textarea","number","money","percent","check","date","select","file"];function B(e,t){if(e==null||e===""||typeof e=="number"&&!Number.isFinite(e))return"\u2014";let a=Number(e);switch(t){case"money":return Number.isFinite(a)?a.toLocaleString(void 0,{style:"currency",currency:"USD",maximumFractionDigits:2}):String(e);case"percent":return Number.isFinite(a)?`${a.toLocaleString(void 0,{maximumFractionDigits:2})}%`:String(e);case"number":return Number.isFinite(a)?a.toLocaleString(void 0,{maximumFractionDigits:2}):String(e);case"date":return e instanceof Date?e.toLocaleDateString():String(e);case"text":case void 0:case null:return String(e);default:throw new Error(`claude-artifact-framework: unknown format "${t}". Valid formats: money, percent, number, date, text.`)}}function ce(e,t){if(e.required&&(t===""||t===null||t===void 0))return"Required";if(t===""||t===null||t===void 0)return null;if(e.type==="number"||e.type==="money"||e.type==="percent"){let a=Number(t);if(!Number.isFinite(a))return"Must be a number";if(e.min!==void 0&&a<e.min)return`Must be at least ${e.min}`;if(e.max!==void 0&&a>e.max)return`Must be at most ${e.max}`}return null}function z({field:e,value:t,onChange:a,data:r}){let[n,s]=E(!1),i=ce(e,t),l=!n&&(t===""||t===null||t===void 0)?null:i,f=`caf-f-${e.key}`,d=e.type==="number"||e.type==="money"||e.type==="percent";if(e.type==="file")return o("div",{className:"caf-field"},o("label",{htmlFor:f},e.label||e.key),o("input",{id:f,type:"file",accept:e.accept,onChange:u=>a(u.target.files&&u.target.files[0]?u.target.files[0]:null)}),t&&t.name?o("small",{className:"caf-hint"},`${t.name} (${Math.round((t.size||0)/1024)} KB)${t.stale?" \u2014 re-pick after reload":""}`):e.hint?o("small",{className:"caf-hint"},e.hint):null);if(e.type==="check")return o("label",{className:"caf-check"},o("input",{id:f,type:"checkbox",checked:!!t,onChange:u=>a(u.target.checked)}),o("span",null,e.label||e.key));let b={id:f,value:t??"","aria-invalid":l?"true":void 0,onBlur:()=>s(!0),onChange:u=>a(d?Ct(u.target.value):u.target.value)},h;if(e.type==="textarea")h=o("textarea",{...b,rows:e.rows||3});else if(e.type==="select"){let u=typeof e.options=="function"?e.options(r)||[]:e.options||[];h=o("select",{...b,className:t?void 0:"caf-select-empty"},o("option",{value:""},e.placeholder||"Select\u2026"),u.map(m=>{let v=typeof m=="string"?m:m.value,w=typeof m=="string"?m:m.label;return o("option",{key:v,value:v},w)}))}else h=o("input",{...b,type:e.type==="date"?"date":d?"number":"text",min:e.min,max:e.max,step:e.step||(e.type==="money"||e.type==="percent"?"any":void 0),placeholder:e.placeholder});return o("div",{className:"caf-field"},o("label",{htmlFor:f},e.label||e.key),h,e.hint&&!l?o("small",{className:"caf-hint"},e.hint):null,l?o("small",{className:"caf-error"},l):null)}function Ct(e){if(e==="")return"";let t=Number(e);return Number.isFinite(t)?t:e}function le(e,t,a,r,n){if(a.type==="file"){e.files[t]=r||null;let s=r?{name:r.name,size:r.size,type:r.type}:null;e.update(i=>n(i,s));return}e.update(s=>n(s,r))}function Ot({spec:e,ctx:t}){let a=e.fields||[],r=(e.actions||[]).filter(n=>!n.when||n.when(t.data,t.viewerId));return o("div",{className:"caf-block caf-fields"},e.title?o("h2",{className:"caf-block-title"},e.title):null,a.map(n=>o(z,{key:n.key,field:n,data:t.data,value:t.data[n.key],onChange:s=>le(t,n.key,n,s,(i,c)=>{i[n.key]=c})})),r.length?o("div",{className:"caf-actions-row caf-fields-footer"},r.map(n=>o("button",{key:n.label,type:"button",className:n.kind==="danger"?"caf-btn caf-btn-danger":n.kind==="primary"?"caf-btn caf-btn-primary":"caf-btn",onClick:()=>t.update(s=>n.run(s,t.viewerId))},n.label))):null)}function D({items:e,title:t}){let a=e.some(r=>r&&r.big);return o("div",{className:a?"caf-block caf-output caf-block-feature":"caf-block caf-output"},t?o("h2",{className:"caf-block-title"},t):null,o("div",{className:"caf-output-grid"},e.map((r,n)=>{let s=(r.format==="money"||r.format==="number")&&Number(r.value)<0;return o("div",{key:r.label||n,className:r.big?"caf-stat caf-stat-big":"caf-stat"},o("span",{className:"caf-stat-label"},r.label),o("span",{className:s?"caf-stat-value caf-stat-neg":"caf-stat-value"},B(r.value,r.format)),r.hint?o("small",{className:"caf-hint"},r.hint):null)})))}function Rt({spec:e,ctx:t}){let a=typeof e.output=="function"?e.output(t.data):e.output||[];return a.length?o(D,{items:a,title:e.title}):o("div",{className:"caf-block caf-empty"},e.empty||"Nothing to show yet.")}function _t({spec:e}){let t=typeof e.banner=="string"?{title:e.banner}:e.banner||{},a=t.image?`linear-gradient(rgba(0,0,0,0.35), rgba(0,0,0,0.35)), url(${JSON.stringify(t.image)}) center / cover`:"linear-gradient(135deg, color-mix(in srgb, var(--caf-accent) 82%, #000), var(--caf-accent) 55%, color-mix(in srgb, var(--caf-accent) 72%, #fff))";return o("div",{className:"caf-banner",style:{background:a}},t.title?o("h2",{className:"caf-banner-title"},t.title):null,t.subtitle?o("p",{className:"caf-banner-sub"},t.subtitle):null)}function Lt({spec:e}){let t=typeof e.image=="string"?{src:e.image}:e.image||{},a=typeof t.src=="string"&&t.src.trim().startsWith("<svg");return o("figure",{className:"caf-block caf-image"},e.title?o("h2",{className:"caf-block-title"},e.title):null,a?o("div",{className:"caf-image-svg",dangerouslySetInnerHTML:{__html:t.src}}):o("img",{src:t.src,alt:t.caption||e.title||"",style:{objectFit:t.fit||"cover",maxHeight:t.height?`${t.height}px`:void 0}}),t.caption?o("figcaption",{className:"caf-hint"},t.caption):null)}function Mt({spec:e,ctx:t}){let a=typeof e.text=="function"?e.text(t.data):e.text;return o("div",{className:"caf-block caf-text"},e.title?o("h2",{className:"caf-block-title"},e.title):null,o("p",null,a))}function Bt({spec:e,ctx:t}){let a=(typeof e.list=="function"?e.list(t.data):e.list)||[],r=typeof e.title=="string"?e.title:null,n=typeof e.title=="function"?e.title:s=>s.title??s.name??s.label??s.text??String(s);return a.length?o("div",{className:"caf-block caf-list"},r?o("h2",{className:"caf-block-title"},r):null,a.map((s,i)=>o("button",{key:s.id??i,className:"caf-row",type:"button",onClick:e.onSelect?()=>e.onSelect(s,t):void 0},o("span",{className:"caf-row-title"},n(s)),e.subtitle?o("span",{className:"caf-row-sub"},e.subtitle(s)):null))):o("div",{className:"caf-block caf-empty"},e.empty||"Nothing here yet.")}var _e=["bar","line","donut"];function zt({spec:e,ctx:t}){let a=typeof e.chart=="function"?e.chart(t.data):e.chart,r=a&&a.items||[];if(!r.length)return o("div",{className:"caf-block caf-empty"},e.empty||"No data to chart yet.");let n=a.type||"bar";if(!_e.includes(n))throw new Error(`unknown chart type "${n}". Valid types: ${_e.join(", ")}.`);let s=t.colors(r.length),i=n==="bar"?It(r,a,s):n==="line"?Dt(r,a):Vt(r,a,s);return o("div",{className:"caf-block caf-chart"},e.title?o("h2",{className:"caf-block-title"},e.title):null,i)}function It(e,t,a){let r=Math.max(...e.map(n=>Number(n.value)||0),0)||1;return o("div",{className:"caf-bars"},e.map((n,s)=>o("div",{key:n.label??s,className:"caf-bar-row"},o("span",{className:"caf-bar-label"},n.label),o("div",{className:"caf-bar-track"},o("div",{className:"caf-bar-fill",style:{width:`${Math.max(2,(Number(n.value)||0)/r*100)}%`,background:a[s]}})),o("span",{className:"caf-bar-value"},B(n.value,t.format)))))}function Dt(e,t){let a=e.map(d=>Number(d.value)||0),r=Math.min(...a),s=Math.max(...a)-r||1,i=100,c=36,l=a.map((d,b)=>[a.length===1?i/2:b/(a.length-1)*i,c-3-(d-r)/s*(c-6)]),f=l[l.length-1];return o("div",{className:"caf-line"},o("svg",{viewBox:`0 0 ${i} ${c}`,className:"caf-line-svg",preserveAspectRatio:"none","aria-hidden":"true"},[.25,.5,.75].map(d=>o("line",{key:d,x1:0,x2:i,y1:c*d,y2:c*d,className:"caf-line-grid"})),o("polyline",{points:l.map(d=>d.join(",")).join(" "),className:"caf-line-path"}),o("circle",{cx:f[0],cy:f[1],r:1.6,className:"caf-line-dot"})),o("div",{className:"caf-line-meta"},o("span",{className:"caf-hint"},String(e[0].label??"")),o("span",{className:"caf-line-last"},B(a[a.length-1],t.format)),o("span",{className:"caf-hint"},String(e[e.length-1].label??""))))}function Vt(e,t,a){let r=e.reduce((c,l)=>c+(Number(l.value)||0),0)||1,n=15.9155,s=25,i=e.map((c,l)=>{let f=(Number(c.value)||0)/r*100,d=o("circle",{key:c.label??l,cx:21,cy:21,r:n,className:"caf-donut-seg",stroke:a[l],strokeDasharray:`${f} ${100-f}`,strokeDashoffset:s});return s-=f,d});return o("div",{className:"caf-donut"},o("svg",{viewBox:"0 0 42 42",className:"caf-donut-svg","aria-hidden":"true"},i),o("div",{className:"caf-donut-legend"},e.map((c,l)=>o("div",{key:c.label??l,className:"caf-legend-row"},o("span",{className:"caf-legend-swatch",style:{background:a[l]}}),o("span",{className:"caf-legend-label"},c.label),o("span",{className:"caf-legend-value"},B(c.value,t.format))))))}function Kt({spec:e,ctx:t}){let a=e.timer||{},r=Math.max(1,Math.round((a.minutes||0)*60+(a.seconds||0))||300),[n,s]=E(r),[i,c]=E(!1);A(()=>{if(!i)return;let b=setInterval(()=>s(h=>Math.max(0,h-1)),1e3);return()=>clearInterval(b)},[i]),A(()=>{n===0&&i&&(c(!1),typeof a.onDone=="function"&&t.update(b=>a.onDone(b)))},[n,i]);let l=String(Math.floor(n/60)).padStart(2,"0"),f=String(n%60).padStart(2,"0"),d=n===0;return o("div",{className:"caf-block caf-timer"},e.title?o("h2",{className:"caf-block-title"},e.title):null,a.label?o("span",{className:"caf-hint"},a.label):null,o("div",{className:d?"caf-timer-time caf-timer-done":"caf-timer-time"},d?a.doneText||"Done!":`${l}:${f}`),o("div",{className:"caf-bar-track"},o("div",{className:"caf-bar-fill caf-timer-fill",style:{width:`${n/r*100}%`}})),o("div",{className:"caf-timer-controls"},o("button",{type:"button",className:"caf-btn caf-btn-primary",disabled:d,onClick:()=>c(b=>!b)},i?"Pause":"Start"),o("button",{type:"button",className:"caf-btn",onClick:()=>{c(!1),s(r)}},"Reset")))}function Yt({spec:e,ctx:t}){let r=(e.actions||[]).filter(n=>!n.when||n.when(t.data,t.viewerId));return o("div",{className:"caf-block caf-actions"},e.title?o("h2",{className:"caf-block-title"},e.title):null,o("div",{className:"caf-actions-row"},r.map(n=>o("button",{key:n.label,type:"button",className:n.kind==="danger"?"caf-btn caf-btn-danger":n.kind==="primary"?"caf-btn caf-btn-primary":"caf-btn",onClick:()=>t.update(s=>n.run(s,t.viewerId))},n.label))))}function Ft({spec:e,ctx:t}){let a=e.custom(t),r=e.fill?"caf-block caf-block-fill caf-custom":"caf-block caf-custom";return typeof a=="string"?o("div",{className:r,dangerouslySetInnerHTML:{__html:a}}):o("div",{className:r},a)}var fe={fields:Ot,output:Rt,text:Mt,list:Bt,chart:zt,timer:Kt,actions:Yt,banner:_t,image:Lt,chat:({spec:e,ctx:t})=>o(se,{cfg:e.chat,ctx:t,title:e.title}),custom:Ft},U=Object.keys(fe);function ze(e){return Object.entries(e.compute||{}).map(([t,a])=>[t,typeof a=="function"?{value:a}:a])}function W(e,t){if(!e.compute)return t;let a={...t};for(let[r,n]of ze(e))try{a[r]=n.value(t)}catch{a[r]=void 0}return a}function Ie(e){let t={};for(let a of e)t[a.key]=a.value!==void 0?a.value:a.type==="check"?!1:"";return t}function de(){return"r"+Date.now().toString(36)+Math.random().toString(36).slice(2,8)}var Le=new WeakMap;function Me(e,t,a,r){let n=Le.get(e);if(n===void 0){let s=String(e),i=s.match(/^\s*(?:async\s+)?([\w$]+)\s*=>/),c=s.match(/^[^(]*\(([^)]*)\)/),l=i?[i[1]]:c?c[1].split(",").map(f=>f.trim().split(/[=\s:]/)[0]):[];n=/viewer|voter|usuario|user/i.test(l[1]||""),Le.set(e,n)}return n?e(t,r):e(t,a,r)}function Ht({title:e,ctx:t}){let a=String(e).split(/\s+/).map(s=>s[0]).filter(Boolean).slice(0,2).join("").toUpperCase()||"?",r=0;for(let s of String(e))r=r*31+s.charCodeAt(0)>>>0;let n=t.colors(8);return o("span",{className:"caf-avatar",style:{background:n[r%n.length]}},a)}function Be(e,t){if(e.title)return e.title(t);let a=e.fields.find(n=>!n.type||n.type==="text"||n.type==="textarea"||n.type==="select"),r=a&&t[a.key];return r===""||r===void 0||r===null?"(untitled)":String(r)}function De({spec:e,records:t}){if(!e.summary)return null;let a=e.summary(t)||[];return a.length?o(D,{items:a}):null}function Ve({spec:e,ctx:t}){let a=e.label||"item",[r,n]=E("");A(()=>{(t.data.records||[]).some(u=>u&&!u.id)&&t.update(u=>{for(let m of u.records||[])m&&!m.id&&(m.id=de())})});let s=t.data.records.map(u=>W(e,u));e.sort&&(s=s.slice().sort(e.sort));let i=s.length,c=r.trim().toLowerCase();e.search&&c&&(s=s.filter(u=>e.fields.some(m=>String(u[m.key]??"").toLowerCase().includes(c))));function l(){let u={id:de(),...Ie(e.fields)};e.items&&(u.items=[]),t.update(m=>{m.records=[...m.records,u]}),t.go("record",u.id)}let f=Y(null),d={};for(let u of t.data.records||[])u&&u.id&&(d[u.id]=JSON.stringify(u));let b=t.remote&&Date.now()-t.remote.at<4e3&&t.remote.keys.includes(t._recordsKey||"records"),h=new Set;if(b&&f.current)for(let u in d)f.current[u]!==d[u]&&h.add(u);return A(()=>{f.current=d}),o("div",{className:"caf-block caf-list"},o("div",{className:"caf-toolbar"},o("span",{className:"caf-count"},e.search&&c?`${s.length} of ${i}`:`${i} ${a}${i===1?"":"s"}`),o("button",{type:"button",className:"caf-btn caf-btn-primary",onClick:l},`Add ${a}`)),e.search?o("input",{className:"caf-search",value:r,placeholder:`Search ${a}s\u2026`,"aria-label":"Search",onChange:u=>n(u.target.value)}):null,e.search&&c&&s.length===0&&i>0?o("div",{className:"caf-empty"},`Nothing matches "${r}".`):null,s.length===0?o("div",{className:"caf-empty"},e.empty||`No ${a}s yet. Add the first one.`):s.map(u=>o("div",{key:u.id,className:"caf-row-wrap"},o("button",{type:"button",className:(e.avatar?"caf-row caf-row-avatar":"caf-row")+(h.has(u.id)?" caf-row-pulse":""),onClick:()=>t.go("record",u.id)},e.avatar?o(Ht,{title:Be(e,u),ctx:t}):null,o("span",{className:"caf-row-main"},o("span",{className:"caf-row-title"},Be(e,u)),e.subtitle?o("span",{className:"caf-row-sub"},e.subtitle(u)):null)),e.actions?o("div",{className:"caf-row-actions"},e.actions.filter(m=>!m.when||Me(m.when,u,t.data,t.viewerId)).map(m=>o("button",{key:m.label,type:"button",className:m.kind==="danger"?"caf-btn caf-btn-danger caf-btn-sm":"caf-btn caf-btn-sm",onClick:()=>t.update(v=>{let w=v.records.find(S=>S.id===u.id);w&&Me(m.run,w,v,t.viewerId)})},m.label))):null)))}function Ke({spec:e,ctx:t,record:a}){let r=e.label||"item";function n(){t.update(s=>{s.records=s.records.filter(i=>i.id!==a.id)}),t.back()}return o("div",{className:"caf-block caf-fields"},o("div",{className:"caf-toolbar"},o("button",{type:"button",className:"caf-btn",onClick:t.back},"\u2039 Back"),o("button",{type:"button",className:"caf-btn caf-btn-danger",onClick:n},`Delete ${r}`)),e.fields.map(s=>o(z,{key:s.key,field:s,data:t.data,value:a[s.key],onChange:i=>t.update(c=>{let l=c.records.find(f=>f.id===a.id);l&&(l[s.key]=i)})})),e.items?o(Pt,{spec:e,ctx:t,record:a}):null,e.compute?o("div",{className:"caf-output-grid caf-computed"},ze(e).map(([s,i])=>{let c=W(e,a);return o("div",{key:s,className:"caf-stat"},o("span",{className:"caf-stat-label"},i.label||s),o("span",{className:"caf-stat-value"},B(c[s],i.format)))})):null)}function Pt({spec:e,ctx:t,record:a}){let r=e.items,n=r.label||"item";function s(c){t.update(l=>{let f=l.records.find(d=>d.id===a.id);f&&(Array.isArray(f.items)||(f.items=[]),c(f))})}let i=Array.isArray(a.items)?a.items:[];return o("div",{className:"caf-items"},o("div",{className:"caf-toolbar"},o("span",{className:"caf-count"},`${i.length} ${n}${i.length===1?"":"s"}`),o("button",{type:"button",className:"caf-btn caf-btn-sm",onClick:()=>s(c=>c.items.push({id:de(),...Ie(r.fields)}))},`Add ${n}`)),i.length===0?o("div",{className:"caf-empty caf-empty-sm"},r.empty||`No ${n}s yet.`):i.map(c=>o("div",{key:c.id,className:"caf-item-row"},r.fields.map(l=>o(z,{key:l.key,field:l,data:t.data,value:c[l.key],onChange:f=>s(d=>{let b=d.items.find(h=>h.id===c.id);b&&(b[l.key]=f)})})),o("button",{type:"button",className:"caf-btn caf-btn-danger caf-btn-sm caf-item-remove","aria-label":`Remove ${n}`,onClick:()=>s(l=>{l.items=l.items.filter(f=>f.id!==c.id)})},"\u2715"))))}function Jt(e,t){return t==="records"?e:new Proxy(e,{get:(a,r,n)=>r==="records"?a[t]:Reflect.get(a,r,n),set:(a,r,n)=>Reflect.set(a,r==="records"?t:r,n),has:(a,r)=>r==="records"?t in a:r in a})}function Ye({spec:e,ctx:t}){let a=e.records,r=a.key||"records",n=Array.isArray(t.data[r])?t.data[r]:[],s="caf:rec:"+r,i=t.view.tabs?t.view.tabs[s]:void 0,c={...t,data:{...t.data,records:n},update:f=>t.update(d=>f(Jt(d,r))),go:(f,d)=>t.setTab(s,d),back:()=>t.setTab(s,void 0),_recordsKey:r},l=i?n.find(f=>f.id===i):null;return o("div",{className:"caf-records-block"},e.title?o("h2",{className:"caf-block-title"},e.title):null,l?o(Ke,{key:"d",spec:a,ctx:c,record:l}):[o(De,{key:"s",spec:a,records:n.map(f=>W(a,f))}),o(Ve,{key:"l",spec:a,ctx:c})])}function Fe({spec:e,ctx:t}){let a=e.records;if(t.view.screen==="record"){let r=t.data.records.find(n=>n.id===t.view.arg);if(r)return o("div",{className:"caf-panel caf-panel-single"},o(Ke,{spec:a,ctx:t,record:r}))}return o("div",{className:"caf-panel caf-panel-single"},o(De,{spec:a,records:t.data.records.map(r=>W(a,r))}),o(Ve,{spec:a,ctx:t}))}function Ut(e,t){return(e.fields||[]).some(a=>ce(a,t[a.key])!==null)}function Wt({step:e,ctx:t}){let a=e.result(t.data)||[],r=t._Block;return o("div",{className:"caf-steps-result"},o(D,{items:a,title:e.title}),(e.blocks||[]).map((n,s)=>o(r,{key:"rb"+s,block:n,ctx:t})),o("div",{className:"caf-step-nav"},o("button",{type:"button",className:"caf-btn",onClick:()=>t.setStep(0)},"Start over")))}function He({spec:e,ctx:t}){let a=e.steps,r=Math.min(Math.max(t.view.step||0,0),a.length-1),n=a[r],s=typeof n.result=="function",i=r===a.length-1;return o("div",{className:"caf-panel caf-panel-single"},o("div",{className:"caf-steps-progress"},o("span",{className:"caf-hint"},s?"Result":`Step ${r+1} of ${a.length}`),o("div",{className:"caf-bar-track"},o("div",{className:"caf-bar-fill caf-steps-fill",style:{width:`${(r+1)/a.length*100}%`}}))),s?o(Wt,{step:n,ctx:t}):o("div",{className:"caf-block caf-fields"},n.title?o("h2",{className:"caf-block-title"},n.title):null,n.text?o("p",{className:"caf-step-text"},typeof n.text=="function"?n.text(t.data):n.text):null,(n.fields||[]).map(c=>o(z,{key:c.key,field:c,data:t.data,value:t.data[c.key],onChange:l=>le(t,c.key,c,l,(f,d)=>{f[c.key]=d})})),o("div",{className:"caf-step-nav"},r>0?o("button",{type:"button",className:"caf-btn",onClick:()=>t.setStep(r-1)},"\u2039 Back"):o("span"),i?null:o("button",{type:"button",className:"caf-btn caf-btn-primary",disabled:Ut(n,t.data),onClick:()=>t.setStep(r+1)},"Next \u203A"))))}var Pe=["panel","records","steps","chat","workspace","documents"],qt=["title","empty","wide","onSelect","subtitle","when","collapsible","fill","state","icon"],Je=["logo","footer"],Ue=["image","title","subtitle"],We=["src","caption","fit","height"],qe=["title","subtitle","theme","layout","blocks","records","steps","chat","data","shared","main","sidebar","libs","documents","machine","brand","mobile"],Ge=["nav"],Xe=["key","initial","states","events"],Qe=["after"],Ze=["seconds","then","do"],et=["from","do","then"],tt=["label","title","blocks","empty","types"],at=["label","fields","title","subtitle","sort","summary","empty","search","compute","items","actions","avatar"],rt=["label","fields","empty"];function G(e,t){for(let a of e||[]){if(!a||!a.key)throw new Error(`claude-artifact-framework: every field in ${t} needs a \`key\`.`);if(a.type!==void 0&&!ie.includes(a.type))throw new Error(`claude-artifact-framework: field "${a.key}" in ${t} has unknown type "${a.type}". Valid types: ${ie.join(", ")}.`);if(a.type==="select"&&a.options!==void 0&&!Array.isArray(a.options)&&typeof a.options!="function")throw new Error(`claude-artifact-framework: field "${a.key}" in ${t}: \`options\` must be an array or a function of data returning one.`)}}function it(e,t){if(!e||typeof e.system!="string"&&typeof e.system!="function")throw new Error(`claude-artifact-framework: ${t} needs \`{ system: "..." }\` (a string or a function of data).`);let a=Object.keys(e).filter(r=>!oe.includes(r));if(a.length)throw new Error(`claude-artifact-framework: ${t} has unknown keys (${a.join(", ")}). Valid keys: ${oe.join(", ")}.`);for(let[r,n]of Object.entries(e.tools||{}))if(!n||typeof n.description!="string"||typeof n.run!="function")throw new Error(`claude-artifact-framework: chat tool "${r}" needs a \`description\` string and a \`run(input, ctx)\` function.`)}var nt=["label","run","when","kind"];function ct(e,t){if(!Array.isArray(e))throw new Error(`claude-artifact-framework: ${t} must be an array of { label, run }.`);e.forEach((a,r)=>{if(!a||typeof a.label!="string"||typeof a.run!="function")throw new Error(`claude-artifact-framework: ${t}[${r}] needs a \`label\` string and a \`run\` function.`);let n=Object.keys(a).filter(s=>!nt.includes(s));if(n.length)throw new Error(`claude-artifact-framework: ${t}[${r}] has unknown keys (${n.join(", ")}). Valid keys: ${nt.join(", ")}.`)})}function _(e){if(!Array.isArray(e))throw new Error("claude-artifact-framework: `blocks` must be an array.");e.forEach((t,a)=>{if(!t||typeof t!="object")throw new Error(`claude-artifact-framework: blocks[${a}] must be an object like { fields: [...] }.`);let r=Object.keys(t).filter(i=>!qt.includes(i)),n=r.filter(i=>U.includes(i)||i==="tabs"||i==="records");if(n.length===0)throw new Error(`claude-artifact-framework: blocks[${a}] has no recognised block type (found: ${r.join(", ")||"nothing"}). Valid block types: ${[...U,"tabs","records"].join(", ")}.`);let s=n.length===2&&n.includes("fields")&&n.includes("actions");if(n.length>1&&!s)throw new Error(`claude-artifact-framework: blocks[${a}] declares more than one block type (${n.join(", ")}). Split them into separate entries of \`blocks\` \u2014 the one exception is { fields, actions }, which renders the actions as the fields card's footer.`);if(G(t.fields,`blocks[${a}]`),n.includes("actions")&&ct(t.actions,`blocks[${a}].actions`),n[0]==="chat"&&it(t.chat,`blocks[${a}].chat`),n[0]==="records"&&ft(t.records,`blocks[${a}].records`,!0),n[0]==="banner"&&typeof t.banner=="object"&&t.banner!==null){let i=Object.keys(t.banner).filter(c=>!Ue.includes(c));if(i.length)throw new Error(`claude-artifact-framework: blocks[${a}].banner has unknown keys (${i.join(", ")}). Valid keys: ${Ue.join(", ")}.`)}if(n[0]==="image"&&typeof t.image=="object"&&t.image!==null){let i=Object.keys(t.image).filter(c=>!We.includes(c));if(i.length)throw new Error(`claude-artifact-framework: blocks[${a}].image has unknown keys (${i.join(", ")}). Valid keys: ${We.join(", ")}.`)}if(t.icon!==void 0&&typeof t.icon!="string")throw new Error(`claude-artifact-framework: blocks[${a}].icon must be a string (an emoji works best).`);if(n[0]==="tabs"){let i=t.tabs;if(!Array.isArray(i)||i.length===0)throw new Error(`claude-artifact-framework: blocks[${a}].tabs needs an array of { label, blocks: [...] }.`);i.forEach((c,l)=>{if(!c||typeof c.label!="string"||!Array.isArray(c.blocks)||c.blocks.length===0)throw new Error(`claude-artifact-framework: tabs[${l}] needs a \`label\` string and a non-empty \`blocks\` array.`);if(c.blocks.some(f=>f&&f.tabs))throw new Error("claude-artifact-framework: tabs cannot nest inside tabs.");_(c.blocks)})}if(t.when!==void 0&&typeof t.when!="function")throw new Error(`claude-artifact-framework: blocks[${a}].when must be a function of data returning true/false.`);if(t.fill!==void 0&&n[0]!=="custom")throw new Error(`claude-artifact-framework: \`fill\` is only valid on custom blocks \u2014 blocks[${a}] is "${n[0]}".`)})}function Gt(e){let t=Object.keys(e).filter(s=>!Xe.includes(s));if(t.length)throw new Error(`claude-artifact-framework: machine has unknown keys (${t.join(", ")}). Valid keys: ${Xe.join(", ")}.`);if(e.key!==void 0&&(typeof e.key!="string"||!e.key))throw new Error("claude-artifact-framework: machine.key must be a non-empty string (where the current state lives in data).");let a=Object.keys(e.states||{});if(!a.length)throw new Error("claude-artifact-framework: machine needs `states: { nombre: {...} }` with at least one state.");let r=(s,i)=>{if(!a.includes(s))throw new Error(`claude-artifact-framework: ${i} names unknown state "${s}". Valid states: ${a.join(", ")}.`)};if(typeof e.initial!="string")throw new Error('claude-artifact-framework: machine needs `initial: "..."` naming the starting state.');r(e.initial,"machine.initial");for(let[s,i]of Object.entries(e.states)){let c=Object.keys(i||{}).filter(l=>!Qe.includes(l));if(c.length)throw new Error(`claude-artifact-framework: machine.states.${s} has unknown keys (${c.join(", ")}). Valid keys: ${Qe.join(", ")}.`);if(i&&i.after!==void 0){let l=i.after,f=Object.keys(l||{}).filter(d=>!Ze.includes(d));if(f.length)throw new Error(`claude-artifact-framework: machine.states.${s}.after has unknown keys (${f.join(", ")}). Valid keys: ${Ze.join(", ")}.`);if(typeof l.seconds!="number"||l.seconds<=0)throw new Error(`claude-artifact-framework: machine.states.${s}.after needs \`seconds\` > 0.`);if(typeof l.then!="string")throw new Error(`claude-artifact-framework: machine.states.${s}.after needs \`then: "estado"\`.`);if(r(l.then,`machine.states.${s}.after.then`),l.do!==void 0&&typeof l.do!="function")throw new Error(`claude-artifact-framework: machine.states.${s}.after.do must be a function of data.`)}}if(!Object.keys(e.events||{}).length)throw new Error("claude-artifact-framework: machine needs `events: { nombre: {...} }` \u2014 ctx.send() is the only way to move it.");for(let[s,i]of Object.entries(e.events)){let c=Object.keys(i||{}).filter(l=>!et.includes(l));if(c.length)throw new Error(`claude-artifact-framework: machine.events.${s} has unknown keys (${c.join(", ")}). Valid keys: ${et.join(", ")}.`);if(i.from!==void 0&&i.from!=="*")for(let l of[].concat(i.from))r(l,`machine.events.${s}.from`);if(typeof i.then=="string")r(i.then,`machine.events.${s}.then`);else if(i.then!==void 0&&typeof i.then!="function")throw new Error(`claude-artifact-framework: machine.events.${s}.then must be a state name or a function of data returning one.`);if(i.do!==void 0&&typeof i.do!="function")throw new Error(`claude-artifact-framework: machine.events.${s}.do must be a function (data, payload).`)}}function lt(e){for(let t of[e.blocks,e.main]){if(!Array.isArray(t))continue;let a=t.find(r=>r&&Array.isArray(r.tabs));if(a)return a}return null}function Xt(e){let t=Object.keys(e).filter(r=>!qe.includes(r));if(t.length)throw new Error(`claude-artifact-framework: unknown top-level keys (${t.join(", ")}). Valid keys: ${qe.join(", ")}.`);if(e.machine!==void 0&&Gt(e.machine),e.brand!==void 0){let r=Object.keys(e.brand||{}).filter(n=>!Je.includes(n));if(r.length)throw new Error(`claude-artifact-framework: brand has unknown keys (${r.join(", ")}). Valid keys: ${Je.join(", ")}.`);if(e.brand.logo!==void 0&&typeof e.brand.logo!="string")throw new Error("claude-artifact-framework: brand.logo must be a string \u2014 an emoji, an inline <svg>...</svg>, or an https URL. Omit it for an automatic monogram.")}if(e.libs!==void 0&&(!Array.isArray(e.libs)||e.libs.some(r=>typeof r!="string"||!/^https?:\/\//.test(r))))throw new Error("claude-artifact-framework: `libs` must be an array of https:// script URLs.");if(e.mobile!==void 0){let r=Object.keys(e.mobile||{}).filter(n=>!Ge.includes(n));if(r.length)throw new Error(`claude-artifact-framework: mobile has unknown keys (${r.join(", ")}). Valid keys: ${Ge.join(", ")}.`);if(e.mobile.nav!==void 0&&e.mobile.nav!=="bottom")throw new Error('claude-artifact-framework: mobile.nav only accepts "bottom" (omit `mobile` for the default top tab bar).');if(e.mobile.nav==="bottom"&&!lt(e))throw new Error('claude-artifact-framework: mobile.nav: "bottom" moves a top-level `tabs` block\'s bar to the bottom of the phone screen \u2014 this spec has no top-level tabs block (in `blocks` or `main`) to move.')}let a=e.layout||"panel";if(!Pe.includes(a))throw new Error(`claude-artifact-framework: unknown layout "${a}". Valid layouts: ${Pe.join(", ")}.`);if(a==="steps"){let r=e.steps;if(!Array.isArray(r)||r.length===0)throw new Error('claude-artifact-framework: layout "steps" needs `steps: [...]` with at least one step.');let n=["title","text","fields","result","blocks"],s=new Set;return r.forEach((i,c)=>{if(!i||typeof i!="object")throw new Error(`claude-artifact-framework: steps[${c}] must be an object.`);let l=Object.keys(i).filter(f=>!n.includes(f));if(l.length)throw new Error(`claude-artifact-framework: steps[${c}] has unknown keys (${l.join(", ")}). Valid keys: ${n.join(", ")}.`);if(!i.fields&&!i.text&&!i.result)throw new Error(`claude-artifact-framework: steps[${c}] needs \`fields\`, \`text\`, or \`result\`.`);if(i.blocks!==void 0){if(typeof i.result!="function")throw new Error(`claude-artifact-framework: steps[${c}].blocks only renders on a result step \u2014 add \`result\` or move the blocks to the step's fields.`);_(i.blocks)}G(i.fields,`steps[${c}]`);for(let f of i.fields||[]){if(s.has(f.key))throw new Error(`claude-artifact-framework: field key "${f.key}" appears in more than one step \u2014 keys share one data pool and must be unique.`);s.add(f.key)}}),a}if(a==="chat")return it(e.chat,"chat"),a;if(a==="workspace"){if(!Array.isArray(e.main)||e.main.length===0)throw new Error('claude-artifact-framework: layout "workspace" needs `main: [...]` (an array of blocks). `sidebar: [...]` is optional.');if(_(e.main),e.sidebar!==void 0){if(!Array.isArray(e.sidebar))throw new Error("claude-artifact-framework: workspace `sidebar` must be an array of blocks.");_(e.sidebar)}let r=C([...e.main,...e.sidebar||[]]);if(r.filter(s=>s&&s.chat).length>1)throw new Error("claude-artifact-framework: only one chat block per app \u2014 the conversation persists under data.chat and there is exactly one.");return ue(r),a}if(a==="documents"){let r=e.documents;if(!r||typeof r!="object"||!r.blocks&&!r.types)throw new Error('claude-artifact-framework: layout "documents" needs `documents: { blocks: [...] }` (every document repeats the same blocks) or `documents: { types: {...} }` (each document is one of several kinds).');if(r.blocks&&r.types)throw new Error("claude-artifact-framework: documents takes `blocks` (uniform documents) OR `types` (typed documents) \u2014 not both.");let n=Object.keys(r).filter(i=>!tt.includes(i));if(n.length)throw new Error(`claude-artifact-framework: documents has unknown keys (${n.join(", ")}). Valid keys: ${tt.join(", ")}.`);if(r.title!==void 0&&typeof r.title!="function")throw new Error("claude-artifact-framework: documents.title must be a function of the document's data returning the tab label.");let s=(i,c)=>{_(i);let l=C(i);if(l.filter(f=>f&&f.chat).length>1)throw new Error(`claude-artifact-framework: only one chat block per document (${c}) \u2014 each document's conversation persists under its own data.chat and there is exactly one.`);ue(l)};if(r.blocks){if(!Array.isArray(r.blocks)||r.blocks.length===0)throw new Error("claude-artifact-framework: documents.blocks must be a non-empty array of blocks.");s(r.blocks,"documents.blocks")}else{let i=Object.keys(r.types||{});if(!i.length)throw new Error("claude-artifact-framework: documents.types needs at least one type, e.g. `types: { nota: { blocks: [...] } }`.");for(let c of i){let l=r.types[c],f=["label","title","blocks","empty","icon"],d=Object.keys(l||{}).filter(b=>!f.includes(b));if(d.length)throw new Error(`claude-artifact-framework: documents.types.${c} has unknown keys (${d.join(", ")}). Valid keys: ${f.join(", ")}.`);if(!l||!Array.isArray(l.blocks)||l.blocks.length===0)throw new Error(`claude-artifact-framework: documents.types.${c} needs a non-empty \`blocks\` array.`);if(l.title!==void 0&&typeof l.title!="function")throw new Error(`claude-artifact-framework: documents.types.${c}.title must be a function of the document's data.`);s(l.blocks,`documents.types.${c}`)}}return a}if(a==="records"){if(ft(e.records,"records",!1),e.blocks&&(_(e.blocks),C(e.blocks).some(r=>r&&r.records)))throw new Error("claude-artifact-framework: a records BLOCK below a records LAYOUT is ambiguous \u2014 the layout already owns the collection. Use panel/workspace/documents to embed records blocks.");return a}return _(e.blocks||[]),ue(C(e.blocks||[])),a}function ft(e,t,a){if(!e||!Array.isArray(e.fields)||e.fields.length===0)throw new Error(`claude-artifact-framework: ${t} needs \`records: { fields: [...] }\` \u2014 the same field declarations the fields block uses.`);let r=a?[...at,"key"]:at,n=Object.keys(e).filter(i=>!r.includes(i));if(n.length)throw new Error(`claude-artifact-framework: ${t} has unknown keys (${n.join(", ")}). Valid keys: ${r.join(", ")}.`);if(a&&e.key!==void 0&&(typeof e.key!="string"||!e.key))throw new Error(`claude-artifact-framework: ${t}.key must be a non-empty string naming the collection in data.`);if(G(e.fields,t),e.fields.some(i=>i.type==="file")||e.items&&e.items.fields.some(i=>i.type==="file"))throw new Error("claude-artifact-framework: `file` fields live in the flat data pool (panel blocks or steps) \u2014 they are not supported inside records or items.");let s=new Set;for(let i of e.fields){if(i.key==="id")throw new Error('claude-artifact-framework: "id" is reserved on records \u2014 the framework assigns it.');if(s.has(i.key))throw new Error(`claude-artifact-framework: duplicate ${t} field key "${i.key}".`);s.add(i.key)}if(e.actions&&ct(e.actions,`${t}.actions`),e.items){let i=Object.keys(e.items).filter(c=>!rt.includes(c));if(i.length)throw new Error(`claude-artifact-framework: ${t}.items has unknown keys (${i.join(", ")}). Valid keys: ${rt.join(", ")}.`);if(!Array.isArray(e.items.fields)||e.items.fields.length===0)throw new Error(`claude-artifact-framework: ${t}.items needs \`fields: [...]\` \u2014 the same field declarations as everywhere else.`);G(e.items.fields,`${t}.items`);for(let c of e.items.fields)if(c.key==="id")throw new Error('claude-artifact-framework: "id" is reserved on items \u2014 the framework assigns it.');if(s.has("items")||e.fields.some(c=>c.key==="items"))throw new Error(`claude-artifact-framework: a ${t} field cannot be named "items" when \`items\` is declared \u2014 that key holds the child collection.`)}for(let[i,c]of Object.entries(e.compute||{})){if(s.has(i)||i==="id"||e.items&&i==="items")throw new Error(`claude-artifact-framework: compute key "${i}" collides with a field key \u2014 computed values are derived, never stored.`);if(typeof c!="function"&&typeof(c&&c.value)!="function")throw new Error(`claude-artifact-framework: compute "${i}" must be a function of the record, or { label, format, value: (r) => ... }.`)}}function ue(e){let t=new Set;for(let a of e){if(!a||!a.records)continue;let r=a.records.key||"records";if(t.has(r))throw new Error(`claude-artifact-framework: two records blocks share the collection key "${r}" \u2014 give each a distinct \`key\`.`);t.add(r)}}function C(e){let t=[];for(let a of e||[])if(t.push(a),a&&Array.isArray(a.tabs))for(let r of a.tabs)t.push(...C(r.blocks));return t}function Qt(e){let t={...e.data||{}};if((e.layout||"panel")==="records"&&!Array.isArray(t.records)&&(t.records=[]),(e.layout||"panel")==="documents"&&!Array.isArray(t.docs)&&(t.docs=[]),e.machine){let n=e.machine.key||"fase";n in t||(t[n]=e.machine.initial)}let a=C([...e.blocks||[],...e.main||[],...e.sidebar||[]]);((e.layout||"panel")==="chat"||a.some(n=>n&&n.chat))&&!t.chat&&(t.chat={api:[],log:[]});for(let n of[...a,...e.steps||[]])for(let s of n.fields||[])s&&s.key!==void 0&&!(s.key in t)&&(t[s.key]=s.value!==void 0?s.value:s.type==="check"?!1:"");for(let n of a)if(n&&n.records){let s=n.records.key||"records";Array.isArray(t[s])||(t[s]=[])}return t}var me=null;function dt(e){return me||(me=class extends e.Component{constructor(t){super(t),this.state={error:null}}static getDerivedStateFromError(t){return{error:t}}render(){return this.state.error?o("div",{className:"caf-block caf-block-error"},o("strong",null,"This section failed to render"),o("code",null,String(this.state.error.message||this.state.error))):this.props.children}}),me}function Zt({spec:e,ctx:t,bottomNav:a}){let r=e.tabs,n=r.map(l=>l.label).join("|"),s=t.view.tabs?t.view.tabs[n]:void 0,i=Math.min(s===void 0?0:s,r.length-1),c=!!a&&t.viewport==="mobile";return o("div",{className:"caf-tabs"},o("div",{className:c?"caf-tabbar caf-tabbar-bottom":"caf-tabbar",role:"tablist"},r.map((l,f)=>o("button",{key:l.label,type:"button",role:"tab","aria-selected":f===i,className:f===i?"caf-tab caf-tab-active":"caf-tab",onClick:()=>t.setTab(n,f)},c&&l.icon?[o("span",{key:"i",className:"caf-tab-ico","aria-hidden":!0},l.icon),o("span",{key:"l",className:"caf-tab-lbl"},l.label)]:l.icon?`${l.icon} ${l.label}`:l.label))),o("div",{className:"caf-tabs-body"},r[i].blocks.map((l,f)=>o(V,{key:i+":"+f,block:l,ctx:t}))))}var ea={...fe,tabs:Zt,records:Ye},ta=[...U,"tabs","records"];function V({block:e,ctx:t}){if(typeof e.when=="function"&&!e.when(t.data)||e.state!==void 0&&t.machine&&t.data[t.machine.key||"fase"]!==e.state)return null;let a=t._navTabs!==void 0&&t._navTabs===e;e.icon&&typeof e.title=="string"&&(e={...e,title:`${e.icon} ${e.title}`});let r=e.fields&&e.actions?"fields":Object.keys(e).find(l=>ta.includes(l)),n=ea[r],s=o(dt(t.React),null,o(n,{spec:e.collapsible?{...e,title:void 0}:e,ctx:t,bottomNav:a}));if(!e.collapsible)return s;let i=typeof e.title=="string"&&e.title?e.title:r,c=t.view.collapsed&&i in t.view.collapsed?t.view.collapsed[i]:e.collapsible==="collapsed";return o("div",{className:"caf-collapse"},o("button",{type:"button",className:"caf-collapse-head","aria-expanded":!c,onClick:()=>t.toggleCollapsed(i,!c)},o("span",null,e.title||r),o("span",{className:c?"caf-chevron caf-chevron-closed":"caf-chevron"},"\u25BE")),c?null:o("div",{className:"caf-collapse-body"},s))}function ut({spec:e,ctx:t}){return o("div",{className:"caf-panel"},(e.blocks||[]).map((a,r)=>o("section",{key:r,className:a.wide||a.collapsible||a.banner?"caf-slot caf-slot-wide":"caf-slot"},o(V,{block:a,ctx:t}))))}function aa({spec:e,ctx:t}){let a=t.view.screen==="record"&&(t.data.records||[]).some(r=>r.id===t.view.arg);return o("div",null,o(Fe,{spec:e,ctx:t}),!a&&Array.isArray(e.blocks)&&e.blocks.length?o("div",{className:"caf-panel caf-records-blocks"},e.blocks.map((r,n)=>o("section",{key:n,className:r.wide||r.collapsible||r.banner?"caf-slot caf-slot-wide":"caf-slot"},o(V,{block:r,ctx:t})))):null)}function ra({spec:e,ctx:t}){let a=n=>(n||[]).map((s,i)=>o("section",{key:i,className:"caf-ws-slot"},o(V,{block:s,ctx:t}))),r=Array.isArray(e.main)&&e.main[0]&&Array.isArray(e.main[0].tabs);return o("div",{className:"caf-workspace"},o("div",{className:"caf-ws-main"},a(e.main)),e.sidebar&&e.sidebar.length?o("div",{className:r?"caf-ws-side caf-ws-side-tabs":"caf-ws-side"},a(e.sidebar)):null)}function pe(e){let t={};for(let a of C(e.blocks)){for(let r of a.fields||[])r&&r.key!==void 0&&!(r.key in t)&&(t[r.key]=r.value!==void 0?r.value:r.type==="check"?!1:"");if(a.records){let r=a.records.key||"records";Array.isArray(t[r])||(t[r]=[])}}return t}function na(){return"d"+Date.now().toString(36)+Math.random().toString(36).slice(2,8)}var q="caf:doc";function oa(e,t,a){if(e.title)try{let r=e.title(t);if(r!=null&&r!=="")return String(r)}catch{}for(let r of C(e.blocks))for(let n of r.fields||[])if(!n.type||n.type==="text"||n.type==="textarea"||n.type==="select"){let s=t[n.key];return s!==""&&s!==void 0&&s!==null?String(s):a||"(untitled)"}return a||"(untitled)"}function sa({spec:e,ctx:t}){let a=e.documents,r=a.label||"document",n=Array.isArray(t.data.docs)?t.data.docs:[],s=a.types||null,i=s?Object.keys(s):[],c=p=>s?s[p.type]:a,l=p=>{let x=s[p]||{};return(x.icon?x.icon+" ":"")+(x.label||p)},[f,d]=E(!1),b=t.view.tabs?t.view.tabs[q]:void 0,h=n.find(p=>p.id===b)||n[0];function u(p){let x=s?s[p]:a,N={id:na(),...s?{type:p}:{},data:pe(x)};t.update(T=>{T.docs=[...T.docs||[],N]}),t.setTab(q,N.id),d(!1)}function m(){if(!s)return u();if(i.length===1)return u(i[0]);d(p=>!p)}function v(p){let x=n.findIndex(N=>N.id===p);if(t.update(N=>{N.docs=N.docs.filter(T=>T.id!==p)}),delete t.files["doc:"+p],h&&h.id===p){let N=n[x+1]||n[x-1];N&&t.setTab(q,N.id)}}let w=s&&f?o("div",{className:"caf-doc-typemenu"},i.map(p=>o("button",{key:p,type:"button",className:"caf-btn caf-btn-sm",onClick:()=>u(p)},l(p)))):null;if(!h)return o("div",{className:"caf-panel caf-panel-single"},o("div",{className:"caf-block caf-empty"},o("p",null,a.empty||`No ${r}s yet. Create the first one.`),s?o("div",{className:"caf-doc-typemenu"},i.map(p=>o("button",{key:p,type:"button",className:"caf-btn caf-btn-primary",onClick:()=>u(p)},`New ${l(p)}`))):o("button",{type:"button",className:"caf-btn caf-btn-primary",onClick:()=>u()},`New ${r}`)));let S=c(h);if(!S)return o("div",{className:"caf-documents"},o(ot,{docs:n,active:h,dspec:a,types:s,close:v,onAdd:m,label:r,ctx:t}),w,o("div",{className:"caf-block caf-block-error"},o("strong",null,`This ${r}'s type "${h.type}" no longer exists`),o("code",null,`valid types: ${i.join(", ")}`)));let k={...pe(S),...h.data},y={...t,data:k,update:p=>t.update(x=>{let N=(x.docs||[]).find(T=>T.id===h.id);N&&p(N.data)}),files:t.files["doc:"+h.id]=t.files["doc:"+h.id]||{}};return o("div",{className:"caf-documents"},o(ot,{docs:n,active:h,dspec:a,types:s,close:v,onAdd:m,label:r,ctx:t}),w,o(ut,{key:h.id,spec:{blocks:S.blocks},ctx:y}))}function ot({docs:e,active:t,dspec:a,types:r,close:n,onAdd:s,label:i,ctx:c}){let l=f=>{let d=r?r[f.type]:a;if(!d)return f.type;let b={...pe(d),...f.data},h=r?d.label||f.type:void 0;return oa(d,b,h)};return o("div",{className:"caf-tabbar",role:"tablist"},e.map(f=>o("span",{key:f.id,className:"caf-doc-tab"},o("button",{type:"button",role:"tab","aria-selected":f.id===t.id,className:f.id===t.id?"caf-tab caf-tab-active":"caf-tab",onClick:()=>c.setTab(q,f.id)},l(f)),o("button",{type:"button",className:"caf-doc-close","aria-label":`Close ${i}`,onClick:()=>n(f.id)},"\u2715"))),o("button",{type:"button",className:"caf-tab caf-doc-add","aria-label":`New ${i}`,onClick:s},"+"))}var ia={panel:ut,records:aa,steps:He,chat:Re,workspace:ra,documents:sa};function mt(e){return new Promise((t,a)=>{let r=document.querySelector(`script[src="${e}"]`);if(r){if(r.dataset.cafReady==="1")return t();r.addEventListener("load",t),r.addEventListener("error",()=>a(new Error(`failed to load ${e}`)));return}let n=document.createElement("script");n.src=e,n.onload=()=>{n.dataset.cafReady="1",t()},n.onerror=()=>{let s=e.match(/^(https:\/\/cdn\.jsdelivr\.net\/npm\/(?:@[^/]+\/)?[^/]+)\/.+/);s&&s[1]!==e?mt(s[1]).then(t,()=>a(new Error(`failed to load ${e} (also tried package default ${s[1]})`))):a(new Error(`failed to load ${e}`))},document.head.appendChild(n)})}function st(e){let t=e.documents?e.documents.blocks||Object.values(e.documents.types||{}).flatMap(a=>a.blocks||[]):[];return C([...e.blocks||[],...e.main||[],...e.sidebar||[],...t])}function ca(e,t,a,r){let n=e.events[a];if(!n)throw new Error(`claude-artifact-framework: unknown machine event "${a}". Valid events: ${Object.keys(e.events).join(", ")}.`);let s=e.key||"fase";t(i=>{let c=i[s],l=n.from===void 0?"*":n.from;if(l!=="*"&&![].concat(l).includes(c))return;n.do&&n.do(i,r);let f=typeof n.then=="function"?n.then(i):n.then;if(f!=null){if(!e.states[f])throw new Error(`claude-artifact-framework: machine event "${a}" resolved to unknown state "${f}". Valid states: ${Object.keys(e.states).join(", ")}.`);i[s]=f}})}function pt(e={}){let t=Xt(e);if(e.machine){let s=Object.keys(e.machine.states);for(let i of st(e))if(i&&i.state!==void 0&&!s.includes(i.state))throw new Error(`claude-artifact-framework: a block declares state: "${i.state}" but the machine's states are: ${s.join(", ")}.`)}else for(let s of st(e))if(s&&s.state!==void 0)throw new Error("claude-artifact-framework: `state:` on a block needs a `machine` declared at the top level.");let a=Se(Qt(e),{shared:!!e.shared}),r=J(e.theme&&e.theme.seed)+la,n={};return function(){if(!K())throw new Error(`claude-artifact-framework: React not found. Hand it over once, before rendering:
29
29
 
30
30
  import React from "react";
31
31
  ArtifactKit.useReact(React);
32
- `);let[,i]=$(0),[c,f]=$(()=>typeof window<"u"&&window.matchMedia("(max-width: 719px)").matches);A(()=>{let m=window.matchMedia("(max-width: 719px)"),u=w=>f(w.matches);return m.addEventListener("change",u),()=>m.removeEventListener("change",u)},[]);let[l,d]=$(e.libs&&e.libs.length?"loading":"ready"),[p,h]=$(null);A(()=>{!e.libs||!e.libs.length||Promise.all(e.libs.map(mt)).then(()=>d("ready"),m=>{h(String(m&&m.message||m)),d("error")})},[]),A(()=>{let m=a.subscribe(()=>i(u=>u+1));return a.isHydrated()&&i(u=>u+1),m},[]);let k=e.machine?a.getData()[e.machine.key||"fase"]:null;A(()=>{if(!e.machine||!a.isHydrated())return;let m=e.machine.states[k];if(!m||!m.after)return;let u=setTimeout(()=>{a.update(w=>{let b=e.machine.key||"fase";w[b]===k&&(m.after.do&&m.after.do(w),w[b]=m.after.then)})},m.after.seconds*1e3);return()=>clearTimeout(u)},[k,a.isHydrated()]);let g={React:ke(),data:a.getData(),view:a.getView(),update:a.update,go:a.go,back:a.back,setStep:m=>a.setView({step:m}),files:o,viewerId:a.getViewerId(),setTab:(m,u)=>a.setView({tabs:{...a.getView().tabs,[m]:u}}),toggleCollapsed:(m,u)=>a.setView({collapsed:{...a.getView().collapsed,[m]:u}}),colors:m=>Te(e.theme&&e.theme.seed,m),viewport:c?"mobile":"desktop",_navTabs:c&&e.mobile&&e.mobile.nav==="bottom"?lt(e):null,_Block:D,machine:e.machine||null,send:e.machine?(m,u)=>ca(e.machine,a.update,m,u):()=>{throw new Error("claude-artifact-framework: ctx.send() needs a `machine` declared at the top level.")}},x=ia[t],y=e.brand&&e.brand.logo,j=e.brand?y&&y.trim().startsWith("<svg")?n("span",{className:"caf-logo caf-logo-svg",dangerouslySetInnerHTML:{__html:y}}):y&&/^https?:\/\//.test(y)?n("img",{className:"caf-logo",src:y,alt:""}):y?n("span",{className:"caf-logo caf-logo-emoji","aria-hidden":!0},y):n("span",{className:"caf-logo caf-logo-mono","aria-hidden":!0},(e.title||"?").split(/\s+/).map(m=>(m.match(/[\p{L}\p{N}]/u)||[])[0]).filter(Boolean).slice(0,2).join("").toUpperCase()||"?"):null;return n("div",{className:`caf-root caf-layout-${t}${g._navTabs?" caf-has-bottomnav":""}`},n("style",{dangerouslySetInnerHTML:{__html:r}}),n("header",{className:e.brand?"caf-header caf-header-brand":"caf-header"},j,n("div",{className:"caf-header-text"},e.title?n("h1",null,e.title):null,e.subtitle?n("p",null,e.subtitle):null)),l==="error"?n("div",{className:"caf-block caf-block-error"},n("strong",null,"A library failed to load"),n("code",null,p)):!a.isHydrated()||l==="loading"?n("div",{className:"caf-block caf-loading"},l==="loading"?"Loading libraries\u2026":"Loading\u2026"):n(dt(g.React),null,n(x,{spec:e,ctx:g})),e.brand&&e.brand.footer?n("footer",{className:"caf-footer"},e.brand.footer):null)}}var la=`
32
+ `);let[,i]=E(0),[c,l]=E(()=>typeof window<"u"&&window.matchMedia("(max-width: 719px)").matches);A(()=>{let g=window.matchMedia("(max-width: 719px)"),k=y=>l(y.matches);return g.addEventListener("change",k),()=>g.removeEventListener("change",k)},[]);let[f,d]=E(e.libs&&e.libs.length?"loading":"ready"),[b,h]=E(null);A(()=>{!e.libs||!e.libs.length||Promise.all(e.libs.map(mt)).then(()=>d("ready"),g=>{h(String(g&&g.message||g)),d("error")})},[]),A(()=>{let g=a.subscribe(()=>i(k=>k+1));return a.isHydrated()&&i(k=>k+1),g},[]);let u=e.machine?a.getData()[e.machine.key||"fase"]:null;A(()=>{if(!e.machine||!a.isHydrated())return;let g=e.machine.states[u];if(!g||!g.after)return;let k=setTimeout(()=>{a.update(y=>{let p=e.machine.key||"fase";y[p]===u&&(g.after.do&&g.after.do(y),y[p]=g.after.then)})},g.after.seconds*1e3);return()=>clearTimeout(k)},[u,a.isHydrated()]);let m={React:ve(),data:a.getData(),view:a.getView(),update:a.update,go:a.go,back:a.back,setStep:g=>a.setView({step:g}),files:n,viewerId:a.getViewerId(),setTab:(g,k)=>a.setView({tabs:{...a.getView().tabs,[g]:k}}),toggleCollapsed:(g,k)=>a.setView({collapsed:{...a.getView().collapsed,[g]:k}}),colors:g=>Te(e.theme&&e.theme.seed,g),viewport:c?"mobile":"desktop",remote:a.getRemote(),_navTabs:c&&e.mobile&&e.mobile.nav==="bottom"?lt(e):null,_Block:V,machine:e.machine||null,send:e.machine?(g,k)=>ca(e.machine,a.update,g,k):()=>{throw new Error("claude-artifact-framework: ctx.send() needs a `machine` declared at the top level.")}},v=ia[t],w=e.brand&&e.brand.logo,S=e.brand?w&&w.trim().startsWith("<svg")?o("span",{className:"caf-logo caf-logo-svg",dangerouslySetInnerHTML:{__html:w}}):w&&/^https?:\/\//.test(w)?o("img",{className:"caf-logo",src:w,alt:""}):w?o("span",{className:"caf-logo caf-logo-emoji","aria-hidden":!0},w):o("span",{className:"caf-logo caf-logo-mono","aria-hidden":!0},(e.title||"?").split(/\s+/).map(g=>(g.match(/[\p{L}\p{N}]/u)||[])[0]).filter(Boolean).slice(0,2).join("").toUpperCase()||"?"):null;return o("div",{className:`caf-root caf-layout-${t}${m._navTabs?" caf-has-bottomnav":""}`},o("style",{dangerouslySetInnerHTML:{__html:r}}),o("header",{className:e.brand?"caf-header caf-header-brand":"caf-header"},S,o("div",{className:"caf-header-text"},e.title?o("h1",null,e.title):null,e.subtitle?o("p",null,e.subtitle):null)),f==="error"?o("div",{className:"caf-block caf-block-error"},o("strong",null,"A library failed to load"),o("code",null,b)):!a.isHydrated()||f==="loading"?o("div",{className:"caf-block caf-loading"},f==="loading"?"Loading libraries\u2026":"Loading\u2026"):o(dt(m.React),null,o(v,{spec:e,ctx:m})),e.brand&&e.brand.footer?o("footer",{className:"caf-footer"},e.brand.footer):null)}}var la=`
33
33
  .caf-root {
34
34
  --caf-radius: 10px;
35
35
  --caf-control-radius: 7px; /* one radius for every control: buttons, inputs, rows */
@@ -67,6 +67,10 @@ Continue with this information. If you have everything you need, answer in natur
67
67
  flex-direction: column;
68
68
  gap: 0.8rem;
69
69
  height: 100%;
70
+ /* The one depth cue cards get \u2014 same as collapsible heads, so every
71
+ raised surface floats exactly the same amount (audited: buttons had
72
+ depth, cards didn't). */
73
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06);
70
74
  }
71
75
  .caf-block-title { margin: 0; font-size: 0.78rem; font-weight: 650; text-transform: uppercase; letter-spacing: 0.06em; color: var(--caf-muted); }
72
76
  .caf-field { display: flex; flex-direction: column; gap: 0.3rem; }
@@ -78,6 +82,11 @@ Continue with this information. If you have everything you need, answer in natur
78
82
  border-radius: var(--caf-control-radius); border: 1px solid var(--caf-border);
79
83
  background: var(--caf-sunken); color: var(--caf-text); width: 100%;
80
84
  }
85
+ /* "Has a value" and "is empty" must read differently at a glance \u2014
86
+ audited: a filled "0" and the neighboring placeholder shared one gray. */
87
+ .caf-field input::placeholder, .caf-field textarea::placeholder,
88
+ .caf-chat-input input::placeholder { color: var(--caf-muted); opacity: 0.75; }
89
+ .caf-field select.caf-select-empty { color: var(--caf-muted); }
81
90
  .caf-field input:focus-visible, .caf-field select:focus-visible, .caf-field textarea:focus-visible,
82
91
  .caf-row:focus-visible { outline: 2px solid var(--caf-accent); outline-offset: 1px; }
83
92
  .caf-field input[aria-invalid="true"] { border-color: var(--caf-danger); }
@@ -157,7 +166,8 @@ Continue with this information. If you have everything you need, answer in natur
157
166
  .caf-steps-fill { transition: width 0.25s ease; }
158
167
  .caf-step-text { margin: 0; color: var(--caf-muted); font-size: 0.92rem; line-height: 1.55; }
159
168
  .caf-step-nav { display: flex; justify-content: space-between; gap: 0.6rem; margin-top: 0.4rem; }
160
- .caf-chat-log { min-height: 320px; max-height: 62vh; overflow-y: auto; gap: 0.55rem; }
169
+ .caf-chat-card { min-width: 0; }
170
+ .caf-chat-log { display: flex; flex-direction: column; min-height: 320px; max-height: 62vh; overflow-y: auto; gap: 0.55rem; }
161
171
  .caf-msg { max-width: 85%; padding: 0.55rem 0.75rem; border-radius: 12px; font-size: 0.92rem; line-height: 1.5; white-space: pre-wrap; word-break: break-word; }
162
172
  .caf-msg-user { align-self: flex-end; background: var(--caf-accent); color: var(--caf-accentText); border-bottom-right-radius: 4px; }
163
173
  .caf-msg-assistant { align-self: flex-start; background: var(--caf-sunken); border-bottom-left-radius: 4px; }
@@ -165,9 +175,12 @@ Continue with this information. If you have everything you need, answer in natur
165
175
  .caf-msg-tools { align-self: flex-start; font-size: 0.74rem; color: var(--caf-muted); padding: 0.15rem 0.55rem; border: 1px solid var(--caf-border); border-radius: 999px; }
166
176
  .caf-msg-error { align-self: stretch; max-width: none; display: flex; flex-direction: column; gap: 0.2rem; background: transparent; border: 1px solid var(--caf-danger); }
167
177
  .caf-msg-error strong { color: var(--caf-danger); font-size: 0.85rem; }
178
+ /* The composer belongs to the conversation: a hairline continuation of the
179
+ same card, not a second bordered box floating 1rem below (audited: log
180
+ and input read as unrelated siblings). */
168
181
  .caf-chat-input {
169
- display: flex; gap: 0.6rem; margin-top: 1rem; padding: 0.6rem;
170
- background: var(--caf-surface); border: 1px solid var(--caf-border); border-radius: var(--caf-radius);
182
+ display: flex; gap: 0.6rem; margin-top: 0.2rem; padding: 0.7rem 0 0;
183
+ background: transparent; border: none; border-top: 1px solid var(--caf-border); border-radius: 0;
171
184
  }
172
185
  .caf-chat-input input { flex: 1; font: inherit; font-size: 0.95rem; padding: 0.55rem 0.7rem; border-radius: var(--caf-control-radius); border: 1px solid var(--caf-border); background: var(--caf-sunken); color: var(--caf-text); }
173
186
  .caf-chat-input input:focus-visible { outline: 2px solid var(--caf-accent); outline-offset: 1px; }
@@ -181,6 +194,14 @@ Continue with this information. If you have everything you need, answer in natur
181
194
  .caf-computed { border-top: 1px solid var(--caf-border); padding-top: 0.7rem; }
182
195
  .caf-records-blocks { margin-top: 1rem; }
183
196
  .caf-row-wrap { display: flex; align-items: center; gap: 0.4rem; }
197
+ /* A teammate's change announces itself: rows another viewer just added or
198
+ edited flash the accent tint once (shared mode \u2014 round 20's dropped
199
+ "notice teammates' changes" requirement, framework-owned). */
200
+ @keyframes caf-remote-pulse {
201
+ 0% { background: var(--caf-accent-tint); box-shadow: 0 0 0 2px var(--caf-accent); }
202
+ 100% { background: transparent; box-shadow: none; }
203
+ }
204
+ .caf-row-pulse { animation: caf-remote-pulse 2.4s ease-out; }
184
205
  .caf-row-wrap .caf-row { flex: 1; min-width: 0; }
185
206
  .caf-row-actions { display: flex; gap: 0.35rem; flex: none; padding-right: 0.3rem; }
186
207
  /* min-width keeps row actions' left edges aligned across rows even when
@@ -193,6 +214,9 @@ Continue with this information. If you have everything you need, answer in natur
193
214
  .caf-item-remove { flex: none; margin-bottom: 0.15rem; }
194
215
  .caf-empty-sm { padding: 0.6rem; font-size: 0.82rem; }
195
216
  .caf-actions-row { display: flex; flex-wrap: wrap; gap: 0.6rem; }
217
+ /* Footer actions inside a fields card: a hairline marks "this submits the
218
+ inputs above", the same attachment grammar as the chat composer. */
219
+ .caf-fields-footer { border-top: 1px solid var(--caf-border); padding-top: 0.8rem; margin-top: 0.2rem; }
196
220
  .caf-code { background: var(--caf-sunken); border-radius: 6px; padding: 0.55rem 0.7rem; font-size: 0.8rem; overflow-x: auto; margin: 0.3rem 0; font-family: ui-monospace, monospace; }
197
221
  .caf-msg code { background: color-mix(in srgb, currentColor 12%, transparent); border-radius: 4px; padding: 0.05rem 0.3rem; font-size: 0.85em; font-family: ui-monospace, monospace; }
198
222
  .caf-md-h { display: block; margin-top: 0.3rem; }
@@ -201,6 +225,12 @@ Continue with this information. If you have everything you need, answer in natur
201
225
  .caf-workspace { max-width: 1200px; margin: 0 auto; display: flex; gap: 1rem; align-items: flex-start; }
202
226
  .caf-ws-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: var(--caf-block-gap); }
203
227
  .caf-ws-side { width: 340px; flex: none; display: flex; flex-direction: column; gap: var(--caf-block-gap); position: sticky; top: 1rem; }
228
+ /* Tab bar height (2\xD70.45rem pad + ~1.02rem line + 1px border) plus the
229
+ .caf-tabs gap \u2014 so the sidebar's first card tops out level with main's
230
+ first card, not with the tab bar. Phones stack, no offset needed. */
231
+ @media (min-width: 901px) {
232
+ .caf-ws-side-tabs { margin-top: calc(1.92rem + 1px + 0.8rem); }
233
+ }
204
234
  .caf-ws-slot { min-width: 0; }
205
235
  .caf-chat-panel { display: flex; flex-direction: column; min-height: 0; }
206
236
  .caf-ws-side .caf-chat-log { max-height: calc(100vh - 220px); }
@@ -245,11 +275,22 @@ Continue with this information. If you have everything you need, answer in natur
245
275
  .caf-doc-close:hover { color: var(--caf-danger); }
246
276
  .caf-doc-add { font-size: 1rem; font-weight: 650; }
247
277
  .caf-empty .caf-btn { margin-top: 0.6rem; }
248
- .caf-records-block { display: flex; flex-direction: column; gap: 1rem; min-width: 0; }
278
+ /* Tight gap: the block title is a SECTION head for the cards below \u2014 it
279
+ must hug its group, not float equidistant (audited on the retro board). */
280
+ .caf-records-block { display: flex; flex-direction: column; gap: 0.6rem; min-width: 0; }
281
+ .caf-stat-neg, .caf-stat-big .caf-stat-value.caf-stat-neg { color: var(--caf-danger); }
249
282
  .caf-doc-typemenu { display: flex; gap: 0.5rem; flex-wrap: wrap; }
250
283
  .caf-header-brand { display: flex; align-items: center; gap: 0.8rem; }
284
+ /* Where the page has a gutter, the logo lives in it: the title keeps the
285
+ exact left axis of tabs and cards below (audited twice \u2014 a logo pushed
286
+ every heading onto a third axis). On phones there is no gutter, so the
287
+ logo stays inline. */
288
+ @media (min-width: 720px) {
289
+ .caf-header-brand { position: relative; }
290
+ .caf-header-brand .caf-logo { position: absolute; right: 100%; margin-right: 0.85rem; top: 0.1rem; }
291
+ }
251
292
  .caf-header-text { min-width: 0; }
252
- .caf-logo { flex: none; width: 40px; height: 40px; border-radius: 9px; object-fit: contain; }
293
+ .caf-logo { flex: none; width: 40px; height: 40px; border-radius: 9px; object-fit: contain; overflow: hidden; }
253
294
  .caf-logo-emoji { display: flex; align-items: center; justify-content: center; font-size: 1.7rem; background: var(--caf-surface); border: 1px solid var(--caf-border); }
254
295
  .caf-logo-mono {
255
296
  display: flex; align-items: center; justify-content: center;
@@ -267,7 +308,9 @@ Continue with this information. If you have everything you need, answer in natur
267
308
  .caf-image { margin: 0; }
268
309
  .caf-image img { width: 100%; border-radius: 7px; display: block; }
269
310
  .caf-image-svg svg { width: 100%; height: auto; display: block; }
270
- .caf-footer { max-width: 760px; margin: 2rem auto 0; padding-top: 0.8rem; border-top: 1px solid var(--caf-border); color: var(--caf-muted); font-size: 0.78rem; text-align: center; }
311
+ /* Left, like every other axis on the page \u2014 a centered footer was the one
312
+ element breaking the single left axis (audited). */
313
+ .caf-footer { max-width: 760px; margin: 2rem auto 0; padding-top: 0.8rem; border-top: 1px solid var(--caf-border); color: var(--caf-muted); font-size: 0.78rem; }
271
314
  .caf-layout-workspace .caf-footer { max-width: 1200px; }
272
315
  .caf-avatar {
273
316
  flex: none; width: 30px; height: 30px; border-radius: 50%;