sagadeck 1.7.1 → 1.9.0

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.
Files changed (105) hide show
  1. package/README.md +55 -4
  2. package/SKILL.md +10 -3
  3. package/bin/sagadeck.js +23 -0
  4. package/docs/ANDAMENTO.md +483 -1
  5. package/docs/PLANO-MELHORIAS.md +180 -0
  6. package/docs/REFERENCIA.md +184 -105
  7. package/package.json +34 -2
  8. package/src/ai/commands.js +2 -2
  9. package/src/ai/deck-ai.js +14 -5
  10. package/src/ai/ia-check.js +127 -0
  11. package/src/ai/ia-config.js +2 -2
  12. package/src/ai/llm.js +5 -1
  13. package/src/ai/map-analysis-run.js +119 -0
  14. package/src/ai/map-data.js +221 -0
  15. package/src/ai/quality.js +1 -1
  16. package/src/ai/video-generation.js +70 -25
  17. package/src/build.js +51 -15
  18. package/src/elements.js +39 -1
  19. package/src/export/browser.js +23 -1
  20. package/src/export/pptx.js +9 -3
  21. package/src/export/shots.js +10 -3
  22. package/src/fiscal/normalize.js +19 -0
  23. package/src/fs-retry.js +37 -2
  24. package/src/import/office.js +5 -4
  25. package/src/layouts.js +114 -99
  26. package/src/lessons.js +1 -1
  27. package/src/library.js +7 -7
  28. package/src/map-analysis.js +109 -0
  29. package/src/map-config.js +89 -0
  30. package/src/map-routing.js +82 -0
  31. package/src/map-services.js +60 -0
  32. package/src/map.js +274 -0
  33. package/src/mcp/server.js +17 -0
  34. package/src/motion.js +20 -6
  35. package/src/purpose.js +1 -1
  36. package/src/runtime/base.css +105 -329
  37. package/src/runtime/fit.js +3 -2
  38. package/src/runtime/fonts/amatic-sc.css +3 -0
  39. package/src/runtime/fonts/bebas-neue.css +2 -0
  40. package/src/runtime/fonts/cabin-sketch.css +2 -0
  41. package/src/runtime/fonts/fraunces.css +3 -0
  42. package/src/runtime/fonts/gelasio.css +3 -0
  43. package/src/runtime/fonts/ibm-plex-mono.css +4 -0
  44. package/src/runtime/fonts/index.json +10 -1
  45. package/src/runtime/fonts/itim.css +2 -0
  46. package/src/runtime/fonts/montserrat.css +2 -0
  47. package/src/runtime/fonts/space-grotesk.css +2 -0
  48. package/src/runtime/map-background.js +91 -0
  49. package/src/runtime/map.js +266 -0
  50. package/src/runtime/runtime.js +81 -100
  51. package/src/runtime/skins/caderno.css +33 -0
  52. package/src/runtime/skins/cartaz.css +27 -0
  53. package/src/runtime/skins/infografico.css +29 -0
  54. package/src/runtime/skins/lousa.css +22 -0
  55. package/src/runtime/skins/musgo.css +42 -0
  56. package/src/runtime/vendor/LEAFLET-LICENSE.txt +26 -0
  57. package/src/runtime/vendor/MAPLIBRE-LEAFLET-LICENSE.txt +15 -0
  58. package/src/runtime/vendor/MAPLIBRE-LICENSE.txt +116 -0
  59. package/src/runtime/vendor/geo-contornos.json +1 -0
  60. package/src/runtime/vendor/leaflet.css +661 -0
  61. package/src/runtime/vendor/leaflet.js +6 -0
  62. package/src/runtime/vendor/maplibre-gl.css +1 -0
  63. package/src/runtime/vendor/maplibre-gl.js +825 -0
  64. package/src/runtime/vendor/maplibre-leaflet.js +234 -0
  65. package/src/runtime/vendor/maplibre-worker.js +10 -0
  66. package/src/studio/ai-chat-route.js +20 -0
  67. package/src/studio/assets/imagens/tour-mapa-botao.jpg +0 -0
  68. package/src/studio/assets/imagens/tour-mapa-editor.jpg +0 -0
  69. package/src/studio/command-approval.js +2 -3
  70. package/src/studio/demo-decks.js +6 -2
  71. package/src/studio/export-jobs.js +86 -0
  72. package/src/studio/exporting.js +36 -18
  73. package/src/studio/feature-demos.js +144 -0
  74. package/src/studio/geo-routes.js +138 -0
  75. package/src/studio/ia-routes.js +9 -0
  76. package/src/studio/layout-samples.js +78 -16
  77. package/src/studio/library-routes.js +0 -9
  78. package/src/studio/project.js +2 -1
  79. package/src/studio/public/ai-settings.js +6 -3
  80. package/src/studio/public/app.js +46 -52
  81. package/src/studio/public/explorer.js +23 -8
  82. package/src/studio/public/export-status.js +154 -0
  83. package/src/studio/public/index.html +17 -10
  84. package/src/studio/public/library.css +12 -3
  85. package/src/studio/public/library.html +3 -0
  86. package/src/studio/public/library.js +39 -12
  87. package/src/studio/public/map-data.js +158 -0
  88. package/src/studio/public/map-editor.js +676 -0
  89. package/src/studio/public/map-fields.js +21 -0
  90. package/src/studio/public/map-settings.js +86 -0
  91. package/src/studio/public/slide-form.js +19 -16
  92. package/src/studio/public/style.css +58 -0
  93. package/src/studio/public/ui-icons.js +1 -1
  94. package/src/studio/public/viewers.js +2 -1
  95. package/src/studio/public/visual-editor.js +1 -1
  96. package/src/studio/server.js +34 -9
  97. package/src/studio/snapshot.js +8 -4
  98. package/src/studio/template-collections.js +1 -1
  99. package/src/studio/tour.js +158 -0
  100. package/src/themes.js +154 -0
  101. package/templates/cenario-e-ciencia.yaml +1 -21
  102. package/templates/ensaio-api.yaml +3 -3
  103. package/templates/cenario/Texto no cen/303/241rio.yaml" +0 -171
  104. package/templates/cenario/imagens/cidade.svg +0 -30
  105. package/templates/cenario/imagens/pessoa.svg +0 -15
package/src/motion.js CHANGED
@@ -5,13 +5,17 @@ const number=(x,f,min,max)=>Math.min(max,Math.max(min,Number.isFinite(Number(x))
5
5
  const color=(x,f)=>/^#?[0-9a-f]{6}$/i.test(x||'')?'#'+String(x).replace('#',''):f;
6
6
  export function motionOptions(value,colors={}){
7
7
  const o=typeof value==='string'?{type:value}:value||{};
8
- if(!['wireframe','hologram','trace','requests','flow','chat','terminal'].includes(o.type))throw new Error('motion.type: wireframe, hologram, trace, requests, flow, chat ou terminal.');
8
+ if(!['wireframe','hologram','trace','requests','flow','chat','terminal','console'].includes(o.type))throw new Error('motion.type: wireframe, hologram, trace, requests, flow, chat, terminal ou console.');
9
+ // console: janela de terminal com cenas (comando digitado letra a letra, depois a saída linha a linha), em ciclo
10
+ const con=o.type==='console';
11
+ const scenes=(Array.isArray(o.scenes)?o.scenes:con&&Array.isArray(o.lines)?o.lines:[]).slice(0,12).map(sc=>typeof sc==='string'?{cmd:sc,out:[]}:{cmd:String(sc?.cmd??''),out:(Array.isArray(sc?.out)?sc.out:String(sc?.out??'').split('\n')).map(String).filter(x=>x!=='').slice(0,8)}).filter(sc=>sc.cmd);
12
+ if(con&&!scenes.length)throw new Error('motion console: scenes: [{cmd: "comando", out: ["linha de saída", ...]}].');
9
13
  const aliases={fg:'ink',bg:'paper',hi:'accent',em:'alert'};
10
14
  const resolved=(v,f)=>color(colors[aliases[v]||v]||v,f);
11
15
  const trace=(Array.isArray(o.path)&&o.path.length>=2?o.path:[[.05,.5],[.95,.5]]).slice(0,64).map(p=>[number(Array.isArray(p)?p[0]:p?.x,0,0,1),number(Array.isArray(p)?p[1]:p?.y,0,0,1)]);
12
16
  const transparent=o.background==='transparent';
13
17
  const layers=(Array.isArray(o.layers)&&o.layers.length?o.layers:[{shape:o.shape,x:.5,y:.5,scale:.24}]).slice(0,6).map(l=>({shape:['sphere','cube','plane','ring'].includes(l.shape)?l.shape:'sphere',x:number(l.x,.5,-.5,1.5),y:number(l.y,.5,-.5,1.5),scale:number(l.scale,.24,.03,1),speed:number(l.speed,1,.1,4),rotation:number(l.rotation,0,-10,10)}));
14
- return {type:o.type,path:trace,closed:o.closed===true,pulses:Math.round(number(o.pulses,2,1,8)),lineWidth:number(o.lineWidth,1.2,.5,6),layers,opacity:number(o.opacity,.7,.05,1),lines:Array.isArray(o.lines)?o.lines.map(String):String(o.code||'').split('\n'),fontSize:number(o.fontSize,16,10,40),shape:o.shape==='cube'?'cube':'sphere',speed:number(o.speed,1,.1,8),recognition:number(o.recognition,1,0,10),thinking:number(o.thinking,.8,0,10),read:number(o.read,2,0,15),typing:number(o.typing,.035,.01,.2),caption:String(o.caption||''),user:String(o.user||''),assistant:String(o.assistant||''),background:transparent?'transparent':resolved(o.background,'#111e30'),foreground:resolved(o.foreground,transparent?color(colors.ink,'#182642'):'#b5c9db'),accent:resolved(o.accent,color(colors.alert,'#cc092f')),secondary:resolved(o.secondary,transparent?color(colors.accent,'#3769e8'):'#aa9ccf'),manual:o.start!=='auto',finish:['next','video','hold'].includes(o.finish)?o.finish:'hold'};
18
+ return {type:o.type,path:trace,closed:o.closed===true,pulses:Math.round(number(o.pulses,2,1,8)),lineWidth:number(o.lineWidth,1.2,.5,6),layers,opacity:number(o.opacity,.7,.05,1),lines:Array.isArray(o.lines)?o.lines.map(String):String(o.code||'').split('\n'),fontSize:number(o.fontSize,con?20:16,10,40),shape:o.shape==='cube'?'cube':'sphere',speed:number(o.speed,1,.1,8),recognition:number(o.recognition,1,0,10),thinking:number(o.thinking,.8,0,10),read:number(o.read,2,0,15),typing:number(o.typing,con?.016:.035,.005,.2),scenes,hold:number(o.hold,3.2,.5,30),caption:String(o.caption||''),user:String(o.user||''),assistant:String(o.assistant||''),background:transparent?'transparent':resolved(o.background,con?color(colors.surfaceDark||colors.surface,'#12160f'):'#111e30'),foreground:resolved(o.foreground,con?color(colors.ink,'#ece8db'):transparent?color(colors.ink,'#182642'):'#b5c9db'),accent:resolved(o.accent,con?color(colors.accent,'#f0b24a'):color(colors.alert,'#cc092f')),secondary:resolved(o.secondary,con?color(colors.c2||colors.accent,'#a9c79b'):transparent?color(colors.accent,'#3769e8'):'#aa9ccf'),muted:color(colors.muted,'#9fa89a'),line:color(colors.line,'#2b352c'),alert:color(colors.alert,'#e07a55'),manual:o.start!=='auto',finish:['next','video','hold'].includes(o.finish)?o.finish:'hold'};
15
19
  }
16
20
  function drawTrace(ctx,o,t,w,h){
17
21
  const points=o.path.map(p=>[p[0]*w,p[1]*h]);if(o.closed)points.push(points[0]);
@@ -26,11 +30,21 @@ function scene(o){
26
30
  const message=(kind)=>parent.postMessage({sagaMotion:kind},'*');
27
31
  const chat=document.querySelector('.chat'),input=document.querySelector('.input'),thread=document.querySelector('.thread'),status=document.querySelector('.status');
28
32
  function reset(){started=false;phase='idle';elapsed=0;chat.hidden=true;input.textContent='';thread.replaceChildren();status.textContent='';}
29
- window.__sagaMotion=()=>({active,reduced,started,serial,phase});message('ready');window.addEventListener('message',e=>{if(e.source!==parent)return;if(e.data?.sagaMotion==='poster'){still=e.data.active!==false;recompute();if(reduced&&o.type==='terminal')document.querySelector('.feed').textContent=o.lines.join('\n');}if(e.data?.sagaMotion==='active')active=!!e.data.active;if(e.data?.sagaMotion==='reset')reset();if(e.data?.sagaMotion==='start'){reset();started=true;active=true;phase='recognize';chat.hidden=false;}});
33
+ window.__sagaMotion=()=>({active,reduced,started,serial,phase});message('ready');window.addEventListener('message',e=>{if(e.source!==parent)return;if(e.data?.sagaMotion==='poster'){still=e.data.active!==false;recompute();if(reduced&&o.type==='terminal')document.querySelector('.feed').textContent=o.lines.join('\n');if(reduced&&o.type==='console')consoleFull();}if(e.data?.sagaMotion==='active')active=!!e.data.active;if(e.data?.sagaMotion==='reset')reset();if(e.data?.sagaMotion==='start'){reset();started=true;active=true;phase='recognize';chat.hidden=false;}});
30
34
  if(o.type==='chat'&&o.manual){const request=e=>{if(!active)return;if(e.type==='keydown'&&![' ','Enter','ArrowRight','PageDown'].includes(e.key))return;e.preventDefault();message('start-request');};document.addEventListener('click',request);document.addEventListener('keydown',request);}
31
35
  if(o.type==='chat'&&!o.manual){started=true;phase='recognize';chat.hidden=false;}
32
36
  function bubble(text,kind){const el=document.createElement('div');el.className='bubble '+kind;el.textContent=text;thread.append(el);return el;}
33
37
  let terminalElapsed=0;const terminalText=o.lines.join('\n');
38
+ let ci=0,cphase='wait',ct=0,shown='';const conBody=document.querySelector('.con-body'),conNum=document.querySelector('.con-n');
39
+ function showConsole(cmdLen,outN){const sc=o.scenes[ci],key=ci+':'+cmdLen+':'+outN;if(!sc||key===shown)return;shown=key;const cmd=document.createElement('p');cmd.className='cmd';const pr=document.createElement('span');pr.className='pr';cmd.append(pr,document.createTextNode(sc.cmd.slice(0,cmdLen)));if(cmdLen<sc.cmd.length){const cur=document.createElement('span');cur.className='cur';cmd.append(cur);}const outs=sc.out.slice(0,outN).map((l,i)=>{const e=document.createElement('p');e.className='out'+(i===0?' first':'');const arr=document.createElement('span');arr.className='arr';e.append(arr,document.createTextNode(l));return e;});conBody.replaceChildren(cmd,...outs);conNum.textContent=String(ci+1).padStart(2,'0')+'/'+String(o.scenes.length).padStart(2,'0');}
40
+ function consoleFull(){ci=0;cphase='wait';ct=0;showConsole(o.scenes[0].cmd.length,o.scenes[0].out.length);}
41
+ function tickConsole(dt){const sc=o.scenes[ci];if(reduced){consoleFull();return;}ct+=dt;
42
+ if(cphase==='wait'){showConsole(0,0);if(ct>=.3){cphase='type';ct=0;}}
43
+ else if(cphase==='type'){const n=Math.min(sc.cmd.length,Math.floor(ct/o.typing));showConsole(n,0);if(n>=sc.cmd.length){cphase='gap';ct=0;}}
44
+ else if(cphase==='gap'){showConsole(sc.cmd.length,0);if(ct>=.38){cphase='out';ct=0;}}
45
+ else if(cphase==='out'){const n=Math.min(sc.out.length,1+Math.floor(ct/.26));showConsole(sc.cmd.length,n);if(n>=sc.out.length&&ct>=Math.max(0,sc.out.length-1)*.26){cphase='hold';ct=0;}}
46
+ else if(cphase==='hold'&&ct>=o.hold){ci=(ci+1)%o.scenes.length;cphase='wait';ct=0;}}
47
+ if(o.type==='console'){if(reduced)consoleFull();else showConsole(0,0);}
34
48
  let bot;
35
49
  function tickChat(dt){if(!started||phase==='done')return;elapsed+=dt;
36
50
  if(phase==='recognize'&&elapsed>=o.recognition){phase='input';elapsed=0;}
@@ -40,7 +54,7 @@ function scene(o){
40
54
  else if(phase==='read'&&elapsed>=o.read){phase='done';message('done');}}
41
55
  function requestLine(){serial++;const ops=['GET /silent-cloud','POST /paper-moon','PUT /silver-orbit','PATCH /soft-vector','GET /tiny-comet','DELETE /ghost-frame'];const el=document.createElement('div');el.textContent=String(serial).padStart(6,'0')+' '+ops[(serial*7+Math.floor(serial/9))%ops.length].padEnd(23,' ')+' '+(serial*2654435761>>>0).toString(16)+' '+(17+serial*37%981)+'ms 200 OK';document.querySelector('.feed').append(el);while(document.querySelector('.feed').children.length>14)document.querySelector('.feed').firstChild.remove();document.querySelector('.feed').scrollTop=1e6;}
42
56
  if(o.type==='requests'){for(let i=0;i<8;i++)requestLine();setInterval(()=>{if(active&&!document.hidden&&!reduced){requestLine();requestLine();}},Math.max(35,240/o.speed));}
43
- function draw(ts){requestAnimationFrame(draw);if(!active||document.hidden){previous=ts;return;}const dt=Math.min(.1,(ts-(previous||ts))/1000);previous=ts;if(o.type==='chat'){tickChat(dt);return;}if(o.type==='terminal'){terminalElapsed+=dt*o.speed;const count=reduced?terminalText.length:Math.floor(terminalElapsed/o.typing);document.querySelector('.feed').textContent=terminalText.slice(0,count)+(count<terminalText.length?'_':'');document.querySelector('.feed').scrollTop=1e6;if(count>terminalText.length+3/o.typing)terminalElapsed=0;return;}if(o.type==='requests'||(reduced&&serial))return;serial++;
57
+ function draw(ts){requestAnimationFrame(draw);if(!active||document.hidden){previous=ts;return;}const dt=Math.min(.1,(ts-(previous||ts))/1000);previous=ts;if(o.type==='chat'){tickChat(dt);return;}if(o.type==='console'){tickConsole(dt*o.speed);return;}if(o.type==='terminal'){terminalElapsed+=dt*o.speed;const count=reduced?terminalText.length:Math.floor(terminalElapsed/o.typing);document.querySelector('.feed').textContent=terminalText.slice(0,count)+(count<terminalText.length?'_':'');document.querySelector('.feed').scrollTop=1e6;if(count>terminalText.length+3/o.typing)terminalElapsed=0;return;}if(o.type==='requests'||(reduced&&serial))return;serial++;
44
58
  const w=main.clientWidth,h=main.clientHeight,dpr=devicePixelRatio||1;if(canvas.width!==Math.round(w*dpr)||canvas.height!==Math.round(h*dpr)){canvas.width=Math.round(w*dpr);canvas.height=Math.round(h*dpr);}ctx.setTransform(dpr,0,0,dpr,0,0);ctx.clearRect(0,0,w,h);const t=reduced?0:(ts-epoch)/1000*o.speed,r=Math.min(w*.25,h*.32),cy=h*.55;if(o.type==='hologram'){drawHologram(ctx,o,t,w,h);return;}if(o.type==='trace'){drawTrace(ctx,o,t,w,h);return;}
45
59
  function p(x,y,z){let a=t*.15+.4,xx=x*Math.cos(a)+z*Math.sin(a),zz=-x*Math.sin(a)+z*Math.cos(a),yy=y*Math.cos(.3)-zz*Math.sin(.3);const f=4/(4+zz);return[w/2+xx*r*f,cy+yy*r*f];}
46
60
  function line(v,c){ctx.beginPath();v.forEach((q,i)=>{let a=p(...q);i?ctx.lineTo(...a):ctx.moveTo(...a);});ctx.strokeStyle=c;ctx.lineWidth=.9;ctx.stroke();}
@@ -53,6 +67,6 @@ function scene(o){
53
67
  }
54
68
  // still: o deck pediu movimento nenhum (motion: none). A cena já nasce parada e completa; antes ela só sabia pela
55
69
  // mensagem da página, que sob carga chegava depois de o terminal começar a digitar.
56
- export function motionHTML(value,colors,{still=false}={}){const o={...motionOptions(value,colors),...(still?{still:true}:{})};const css=`html,body{height:100%;background:${o.type==='chat'?'transparent':o.background};color:${o.foreground};overflow:hidden}main{height:100%;position:relative}canvas{position:absolute;inset:0;width:100%;height:100%}.caption{position:absolute;top:12px;left:16px;color:${o.secondary};font:11px monospace;letter-spacing:1.5px}.feed{position:absolute;top:36px;left:16px;right:16px;bottom:12px;overflow:hidden;font:${o.type==='terminal'?o.fontSize:12}px/1.5 monospace;white-space:pre}.chat{position:absolute;inset:0;border:1px solid ${o.secondary};border-radius:16px;padding:18px;background:${o.background};display:flex;flex-direction:column;gap:12px}.chat[hidden]{display:none}.thread{flex:1;overflow:auto;display:flex;flex-direction:column;gap:12px}.bubble{font:18px/1.45 system-ui;max-width:90%;padding:10px 14px;border-radius:10px;white-space:pre-wrap}.user{align-self:flex-end;background:#263a51}.assistant{align-self:flex-start}.status{font:14px system-ui;color:${o.secondary};min-height:18px}.input{border:1px solid #51617b;border-radius:9px;min-height:48px;padding:12px;font:17px system-ui;white-space:pre-wrap}.chat-title{font:12px system-ui;letter-spacing:2px;color:${o.secondary}}`;
57
- const html=`<main><canvas aria-hidden="true"></canvas><div class="caption">${esc(o.type==='chat'?'':o.caption)}</div><div class="feed" aria-hidden="true"></div><section class="chat" hidden><div class="chat-title">${esc(o.caption||'ASSISTENTE')}</div><div class="thread" aria-live="polite"></div><div class="status"></div><div class="input" aria-label="Mensagem digitada"></div></section></main>`;
70
+ export function motionHTML(value,colors,{still=false}={}){const o={...motionOptions(value,colors),...(still?{still:true}:{})};const css=`html,body{height:100%;background:${['chat','console'].includes(o.type)?'transparent':o.background};color:${o.foreground};overflow:hidden}main{height:100%;position:relative}canvas{position:absolute;inset:0;width:100%;height:100%}.caption{position:absolute;top:12px;left:16px;color:${o.secondary};font:11px monospace;letter-spacing:1.5px}.feed{position:absolute;top:36px;left:16px;right:16px;bottom:12px;overflow:hidden;font:${o.type==='terminal'?o.fontSize:12}px/1.5 monospace;white-space:pre}.chat{position:absolute;inset:0;border:1px solid ${o.secondary};border-radius:16px;padding:18px;background:${o.background};display:flex;flex-direction:column;gap:12px}.chat[hidden]{display:none}.thread{flex:1;overflow:auto;display:flex;flex-direction:column;gap:12px}.bubble{font:18px/1.45 system-ui;max-width:90%;padding:10px 14px;border-radius:10px;white-space:pre-wrap}.user{align-self:flex-end;background:#263a51}.assistant{align-self:flex-start}.status{font:14px system-ui;color:${o.secondary};min-height:18px}.input{border:1px solid #51617b;border-radius:9px;min-height:48px;padding:12px;font:17px system-ui;white-space:pre-wrap}.chat-title{font:12px system-ui;letter-spacing:2px;color:${o.secondary}}`+(o.type==='console'?`.caption{display:none}.con{position:absolute;left:0;right:0;top:50%;transform:translateY(-50%);max-height:100%;display:flex;flex-direction:column;border:1px solid ${o.line};border-radius:14px;overflow:hidden;background:${o.background};font-family:'IBM Plex Mono','Cascadia Mono',Consolas,'SF Mono',Menlo,monospace}.con-bar{flex:none;display:flex;align-items:center;gap:9px;height:44px;padding:0 18px;border-bottom:1px solid ${o.line}}.con-bar i{width:13px;height:13px;border-radius:50%;opacity:.72}.con-bar i:nth-child(1){background:${o.alert}}.con-bar i:nth-child(2){background:${o.accent}}.con-bar i:nth-child(3){background:${o.secondary}}.con-cap{margin-left:10px;font-size:13px;letter-spacing:2.5px;text-transform:uppercase;color:${o.muted};white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.con-n{margin-left:auto;font-size:13px;color:${o.muted}}.con-body{flex:1;min-height:calc(${o.fontSize}px * 1.6 * 6 + 36px);overflow:hidden;padding:18px 22px;font-size:${o.fontSize}px;line-height:1.6}.con-body p{margin:0 0 .4em;white-space:pre-wrap;word-break:break-all}.cmd{color:${o.foreground}}.pr{display:inline-block;width:.42em;height:.42em;margin:0 .85em .12em .1em;border-top:.13em solid ${o.accent};border-right:.13em solid ${o.accent};transform:rotate(45deg)}.cur{display:inline-block;width:.55em;height:1.05em;margin-left:2px;vertical-align:-.18em;background:${o.accent};animation:bl 1s steps(1) infinite}@keyframes bl{50%{opacity:0}}.out{color:${o.muted}}.out.first{color:${o.secondary}}.arr{position:relative;display:inline-block;width:.8em;height:0;margin-right:.7em;vertical-align:.3em;border-top:.09em solid ${o.muted}}.arr::before{content:"";position:absolute;left:0;top:-.24em;width:.4em;height:.4em;border-left:.09em solid ${o.muted};border-bottom:.09em solid ${o.muted};transform:translateY(-.03em) rotate(45deg)}@media(prefers-reduced-motion:reduce){.cur{animation:none}}`:'');
71
+ const html=`<main><canvas aria-hidden="true"></canvas><div class="caption">${esc(o.type==='chat'?'':o.caption)}</div><div class="feed" aria-hidden="true"></div><section class="chat" hidden><div class="chat-title">${esc(o.caption||'ASSISTENTE')}</div><div class="thread" aria-live="polite"></div><div class="status"></div><div class="input" aria-label="Mensagem digitada"></div></section>${o.type==='console'?`<div class="con"><div class="con-bar"><i></i><i></i><i></i><span class="con-cap">${esc(o.caption)}</span><span class="con-n"></span></div><div class="con-body" aria-hidden="true"></div></div>`:''}</main>`;
58
72
  const doc=playgroundDocument({html,css,javascript:`${drawHologram.toString()}\n${drawTrace.toString()}\n(${scene.toString()})(${JSON.stringify(o)});`});return `<iframe data-motion="${o.type}" data-motion-manual="${o.manual}" data-motion-finish="${o.finish}" title="${esc(o.caption||'Detalhe animado')}" sandbox="allow-scripts" style="width:100%;height:100%;border:0" srcdoc="${esc(doc)}"></iframe>`;}
package/src/purpose.js CHANGED
@@ -12,7 +12,7 @@ export const PURPOSES = {
12
12
  executiva: { label: "Executiva (antigo)", hint: "", maxWords: 40, dense: false, legacy: true },
13
13
  };
14
14
 
15
- const LAYOUT_WORDS = { onepage: 120, status: 90, solution: 140, calc: 90, algo: 60 }; // densos por natureza (uma página com tudo; exercício resolvido se revela aos poucos)
15
+ const LAYOUT_WORDS = { onepage: 120, status: 90, solution: 140, calc: 90, algo: 60, calendar: 240 }; // densos por natureza (uma página com tudo; exercício resolvido se revela aos poucos)
16
16
 
17
17
  // Limite de palavras na tela de um slide: o do slide > o do deck > o do propósito (ou do layout, se maior) > 40
18
18
  export function wordLimit(s = {}, spec = {}, layout = s.layout) {