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
@@ -15,7 +15,7 @@ Mídia paga não é proibida por padrão. Quando for apropriada, proponha seu us
15
15
  ```yaml
16
16
  title: Nome da palestra # obrigatório (vira rodapé e título da janela)
17
17
  author: Seu Nome · Cargo
18
- theme: sinal # sinal | editorial | noite | bauhaus | terminal | jornal | rabisco | oceano | pop | aurora | prata | aluminio | arcade | relevo (ou customizado, ver fim)
18
+ theme: sinal # sinal | editorial | noite | bauhaus | terminal | jornal | rabisco | oceano | pop | aurora | prata | aluminio | arcade | relevo | musgo | wine | caderno | lousa | cartaz | infografico (ou customizado, ver fim)
19
19
  palette: floresta # opcional: só as cores, vale em qualquer tema (ver "Temas e paletas"); sem ela, as cores do tema
20
20
  duration: 50 # minutos — o modo apresentador mostra se você está adiantado/atrasado
21
21
  event: Summit de Dados 2026 # opcional — para {evento} no rodapé/cabeçalho
@@ -60,7 +60,8 @@ slides:
60
60
  | `background` | figura de fundo atrás do conteúdo |
61
61
  | `bg` / `fg` | cor de fundo / texto (hex) só neste slide |
62
62
  | `transition` | `fade` (padrão), `cut` (seca), `saida` (o anterior recua e dissolve, o próximo entra de baixo) ou `morph` (crossfade longo com respiro de escala; combine com `continuity:` nos elementos que continuam) — só no HTML; PPTX/PDF usam o quadro final |
63
- | `ambient` | eco ambiente nos slides estáticos: `pontos` (poeira de luz à deriva) ou `grade` (grade em perspectiva deslizando) — lembra a capa sem repeti-la; parado com movimento reduzido ou na exportação |
63
+ | `ambient` | eco ambiente nos slides estáticos: `pontos` (poeira de luz à deriva), `grade` (grade em perspectiva deslizando) ou `rede` (nós à deriva que se ligam por linhas finas quando se aproximam, na cor de destaque; no tema `musgo` ela já vem atrás da capa, e `ambient: false` tira) — lembra a capa sem repeti-la; parado com movimento reduzido ou na exportação |
64
+ | `ticker` | só na capa: faixa que corre devagar no pé, com os itens separados por losangos (`ticker: [Pesquisa, Arquitetura, Plano]`). No tema `musgo` ela vem sozinha, com os títulos das seções; `ticker: false` tira. Para no mouse; parada com movimento reduzido, `motion: none` e na exportação (só no HTML) |
64
65
  | `footer: false` | esconde o rodapé neste slide |
65
66
  | `id` | nome curto do slide, destino dos links (`goto`, `back`, `next`, `[texto](#id)`); ver [Navegação por caminhos](#navegação-por-caminhos-hub-goto-back-next) |
66
67
  | `back` | id (ou número) do slide para onde o botão **Voltar** do canto leva; o botão mostra o título do destino |
@@ -81,21 +82,22 @@ Tabela em markdown no meio de um texto (`problem`, `body`, `text`, passo do `sol
81
82
  | `cover` | `kicker, title, subtitle, author, role, figure` | capa |
82
83
  | `section` | `number, kicker, title, subtitle, figure` | abertura de ato/capítulo (tom `accent` por padrão) |
83
84
  | `statement` | `text` **ou** `lines: [ {text, as, color, step} ]`, `by`, `center` | uma frase de impacto; `lines` + `build` revelam linha a linha |
84
- | `calendar` | `kicker, title, events: [{date, title, text, tag, color}], undated: [{title, text}], undatedTitle, cols, build` | datas num **calendário** (agenda, lançamentos, cronograma, "infográfico em forma de calendário"): um cartão por mês que tem evento, com o mini calendário do mês (os dias marcados na cor do tipo) e a lista; `date`: `2026-12-18`, `18/12/2026` ou só o mês `2026-12`; cada `tag` (Filme, Série…) ganha uma cor e entra na legenda; o que não tem data vai no cartão "sem data" (`undated`). Para "calendário", este; `timeline` é para uma sequência de marcos sem a grade dos dias |
85
+ | `calendar` | `kicker, title, events: [{date, time, title, text, tag, color}], undated: [{title, text}], undatedTitle, view, month, week, cols, build` | datas num **calendário** (agenda, lançamentos, cronograma, programação, "infográfico em forma de calendário"). `view`: `meses` (um cartão por mês com o mini calendário e a lista; poucos eventos por mês), `mes` (um mês grande, como calendário de parede, com os eventos escritos nos dias; muitos eventos num mês só), `semana` (uma coluna por dia com o horário; programação de um evento; fim de semana vazio some), `lista` (agenda compacta em colunas, agrupada por mês; muitos meses cheios). Sem `view`, o sagadeck escolhe pelo que cabe; muitos eventos em vários meses ficam melhores em **um slide por mês** (`view: mes` + `month: 2026-11` em cada slide, só com os eventos daquele mês). `week: 2026-11-16` escolhe a semana. `date`: `2026-12-18`, `18/12/2026`, `2026-12-18 14:00` ou só o mês `2026-12`; `time` ("14:00") também dá a hora; cada `tag` (Filme, Série…) ganha uma cor e entra na legenda; o que não tem data vai em "sem data" (`undated`). Para "calendário", este; `timeline` é para uma sequência de marcos sem a grade dos dias |
85
86
  | `poster` | `kicker, title, subtitle, hero` (ilustração principal: `{ image_prompt }`, imagem, gráfico…), `panels: [{label, title, text, icon` ou `figure` ou `image_prompt, facts: [{value, label}]}], flow, cols, key, build` | infográfico de UMA página no estilo de figura de revista científica (Nature, Scientific American): a ilustração principal e painéis com letra (a, b, c…), cada um com um desenho, título, texto curto e números com unidade; `flow: true` põe setas na ordem (receita, processo, protocolo); `key` é a nota de rodapé (fonte, condições). Para "infográfico de uma página", "pôster" ou "como fazer X numa página", este e não o `onepage` (que é jornada, problema e solução de um projeto). Ilustre os painéis com `image_prompt` no mesmo estilo (ex.: "clean scientific illustration, flat, white background") |
86
87
  | `definition` | `kicker, term, origin, parts: [{word, meaning}], text, icon` (ou `figure`), `build`, `termSize` (px do termo) | definição de um termo, como verbete: o termo em destaque, a origem da palavra em partes (`origin: do grego`, `parts: [{word: hydor, meaning: água}, {word: logos, meaning: ciência}]`) e a definição; para "o que é X", use este e não um `statement` com o parágrafo inteiro |
87
88
  | `quote` | `quote, by, role, after, afterStep` | citação; `after` aparece num clique |
88
89
  | `number` | `value, prefix, suffix, decimals, from, label, context, side, valueColor` | número gigante animado (conta de `from` até `value`) |
89
90
  | `split` | `title, body, bullets, content, figure, ratio: "1.2:1", reverse, build` | texto + figura |
90
- | `cards` | `title, items: [{icon, picto, number, title, text, foot, hl, goto}], cols, build` | 2–4 cartões |
91
+ | `cards` | `title, items: [{icon, picto, number, title, text, foot, hl, goto, flip}], cols, build` | 2–4 cartões; com `flip` o cartão **vira** no clique (ver abaixo) |
91
92
  | `list` | `title, items: [texto ou {text, sub, goto}], numbered, size, build` | lista numerada grande |
92
93
  | `hub` | `kicker, title, question, options: [{icon, title, text, meta, goto}], cols, build` | mapa de caminhos: cada opção leva (`goto`) à parte da apresentação daquele caminho; ver [Navegação por caminhos](#navegação-por-caminhos-hub-goto-back-next) |
93
94
  | `onepage` | `kicker, title, subtitle, journey: [texto ou {icon, title, text, goto}], journeyTitle, problem: {title, text, numbers: [{value, label}], items}, solution: {…}, dashboard: {numbers: [{value, label, trend, title}], figures: [gráfico ou ufmap, com title]}` | tudo numa página (jornada, problema, solução, painel); ver [One-page](#one-page-onepage) |
94
95
  | `status` | `kicker, title, health: ok\|risco\|atrasado, healthLabel, progress (0–100), highlight, done, doing, blocked, risks, upcoming: [texto ou {text, owner, due}], shots: [{image, caption}]` | status semanal; ver [Status semanal](#status-semanal-status) |
95
96
  | `stats` | `title, stats: [{value, label, text, icon, trend, trendUp, color}], cols, build` | indicadores (KPIs) em cartões, com tendência (`trend: "+12%"`) |
96
- | `timeline` | `title, events: [{when, title, text, tag}], highlight, after, build` | linha do tempo |
97
+ | `timeline` | `title, events: [{when, title, text, tag, more}], highlight, after, build` | linha do tempo; `more` põe um botão + no marco que abre um balão (ver abaixo) |
97
98
  | `chart` | `title, chart: {…}, side (texto ou elemento), chartHeight` | gráfico + comentário |
98
99
  | `table` | `title, head, rows, style, color, highlight, total, side, caption, source` | tabela de verdade nas cores do tema |
100
+ | `map` | `kicker, title, basemap, layers: [{name, points \| geojson \| gpx \| kml \| areas, color, size, label, colors, popup, step, view}], build, view, caption` | **mapa ao vivo** com pontos, linhas e áreas (sensores, medidores, unidades de atendimento, cinemas, trajetos, regiões…): os dados vêm da planilha do projeto ou de arquivos GeoJSON/GPX/KML; ver [Mapa](#mapa-map) |
99
101
  | `compare` | `title, left: {label, value, title, text, items, figure, hl}, right: {…}, vs, after, build` | A × B |
100
102
  | `matrix` | `title, x: [esq, dir], y: [cima, baixo], cells: [4 × {title, text, example, hl}], build` | matriz 2×2 |
101
103
  | `question` | `question, options: [texto ou {key, text, sub}], keys, cols, timer, hint, optionSize` | pergunta para a plateia (com timer) |
@@ -112,7 +114,6 @@ Tabela em markdown no meio de um texto (`problem`, `body`, `text`, passo do `sol
112
114
  | `references` | `title, items` | fontes (2 colunas) |
113
115
  | `headline` | `kicker, text, as, size, caption` | manchete: uma frase CURTA (até ~12 palavras) enorme ocupando o slide; frase longa sai menor (como no `statement`) e conta como slide de frase única (no máximo 2 por deck) |
114
116
  | `full` | `figure` (ou `image`/`image_prompt`), `kicker, title, caption, overlay: bottom\|left\|center\|none, fit, titleSize` | figura/imagem de página inteira com texto por cima; com `image_prompt` a IA gera a página toda. Figura do documento (`contexto/visuais/…`) ou `fit: contain` com texto não leva véu: sai com o título no alto, a figura inteira e a legenda embaixo (como `image`) |
115
- | `kinetic` | `figure, beats: [{text, style, position, color, size, tag}], autoplay, interval` | frases curtas em sequência sobre uma cena; avanço manual ou automático |
116
117
  | `bento` | `title, tiles: [{title, text, value, icon, figure, size: big\|wide\|tall, hl}], cols, build` | mosaico de blocos de tamanhos diferentes |
117
118
  | `funnel` | `title, stages: [{title, value, text, hl}], build` | funil que afunila etapa a etapa |
118
119
  | `pyramid` | `title, levels: [{title, text, hl}], build` | pirâmide (topo → base) |
@@ -193,37 +194,6 @@ paginação automática de apostila ainda não fazem parte deste editor.
193
194
  No YAML, um ponto usa `kind: point`, `x` e `y` em porcentagens. Áreas usam `kind: area` (ou omitem `kind`)
194
195
  e acrescentam `width` e `height`. Ambos aceitam `title` e `text` dentro de `hotspots` do layout `spotlight`.
195
196
 
196
- ## Slide `kinetic`: tipografia em cena
197
-
198
- O layout `kinetic` combina uma figura de fundo com frases curtas que entram em sequência, podendo variar
199
- estilo, posição, cor e escala em cada batida. No Studio, adicione a cena e edite cada frase; a sequência
200
- interativa roda em **Apresentar** e avança pelos botões ou automaticamente. A prévia no editor mostra
201
- apenas o primeiro quadro. Ao trocar outro layout para `kinetic`, o SagaDeck reaproveita o título ou os
202
- itens existentes como frases e mantém a figura do slide. Sem título, frase ou itens, começa com
203
- “Uma ideia em movimento”.
204
-
205
- `autoplay` é `true` por padrão para duas ou mais frases e `interval` define o tempo em milissegundos
206
- (450–5000, padrão 1000). Movimento automático começa ao entrar no slide, para ao sair ou ao chegar à
207
- última frase, e respeita a preferência do sistema por movimento reduzido; o botão ainda permite iniciar
208
- manualmente. Para uma frase estática, use `autoplay: false`.
209
-
210
- Os estilos disponíveis são `clean`, `poster`, `editorial`, `outline` e `marker`; o estilo limpo é o padrão,
211
- sem brilho ou sombra exagerada. Posições: `left`, `center`,
212
- `right`, `top` e `bottom`; cores: `white`, `gold`, `pink` e `cyan`; escalas: `small`, `medium` e `large`.
213
- Campos omitidos variam com a batida para criar ritmo visual. Em impressão/exportação estática, os controles
214
- e a animação são substituídos por uma lista das frases.
215
-
216
- ```yaml
217
- - layout: kinetic
218
- figure: { image: palco.jpg }
219
- autoplay: true
220
- interval: 1100
221
- beats:
222
- - { text: "A IDEIA", style: poster, position: left, color: white, size: large, tag: "COMEÇA PEQUENA" }
223
- - { text: "ACENDE", style: clean, position: right, color: white, size: large }
224
- - { text: "E MUDA", style: editorial, position: bottom, color: gold, size: medium }
225
- ```
226
-
227
197
  ## Slide `api`: requisição ao vivo
228
198
 
229
199
  Um slide tipo Postman: mostra o pedido (URL, corpo, cabeçalhos) e o código equivalente (curl, JavaScript,
@@ -234,8 +204,9 @@ Os pedidos saem do **Studio** (Node, na sua máquina), nunca do navegador: sem p
234
204
  certificado da empresa e com o token fora da página. Sem o Studio (HTML exportado, PDF, servidor
235
205
  multiusuário), o slide mostra a **última resposta gravada** e o botão vira *Reproduzir gravação*.
236
206
 
237
- No Studio: **Biblioteca → Nova → Exemplo: aula de APIs ao vivo** cria um deck com um slide de cada tipo;
238
- no editor, **Inserir → Slide de API** insere um deles e **Inserir → Ambientes** edita os ambientes. Os
207
+ No Studio: a demo **APIs com curl** (Demos oficiais, ou Nova → Modelo pronto) mostra as chamadas mais comuns com o curl;
208
+ o ensaio completo, com um slide de cada tipo (upload, OCR, embeddings, voz, tempo real), sai pelo comando
209
+ `sagadeck ensaio-api`. No editor, **Inserir → Slide de API** insere um deles e **Inserir → Ambientes** edita os ambientes. Os
239
210
  exemplos rodam no ambiente embutido **ENSAIO**, uma API de mentira que o Studio local sobe sozinho (não vai
240
211
  para o seu arquivo de ambientes; o seu ambiente com o mesmo nome, se existir, vence).
241
212
 
@@ -385,7 +356,7 @@ Executar só funciona no Studio **local**: escutando em `127.0.0.1`, chamado pel
385
356
 
386
357
  ## Navegação por caminhos (`hub`, `goto`, `back`, `next`)
387
358
 
388
- Para processo com vários caminhos ("é experimento ou projeto? DEV, HOM ou PROD?", "o que muda conforme o
359
+ Para conteúdo com vários caminhos ("é a primeira vez ou já usa?", "o que muda conforme o
389
360
  front-end?"), em vez de uma sequência única: um **mapa** (`layout: hub`) com as opções, cada uma levando à sua
390
361
  seção; cada seção termina voltando ao mapa. Funciona ao apresentar (clique), no PDF (links entre páginas) e no
391
362
  PowerPoint (clique pula para o slide).
@@ -403,24 +374,24 @@ PowerPoint (clique pula para o slide).
403
374
  - layout: hub
404
375
  id: mapa
405
376
  title: Qual é o seu caso?
406
- question: Cada caminho tem prazos e responsáveis diferentes
377
+ question: Cada caminho tem passos diferentes
407
378
  options:
408
- - { icon: flask-conical, title: Experimento, text: Dados fictícios, meta: 30 dias, goto: experimento }
409
- - { icon: rocket, title: Projeto, text: DEV, HOM e PROD, goto: projeto }
379
+ - { icon: user, title: Primeira vez, text: Do zero ao primeiro resultado, meta: 4 passos, goto: inicio }
380
+ - { icon: rocket, title: Já uso, text: Atalhos e automação, goto: atalhos }
410
381
  - layout: steps
411
- id: experimento
382
+ id: inicio
412
383
  back: mapa
413
- title: Experimento
414
- steps: [{ title: Pedido }, { title: 30 dias }, { title: Renovar ou virar projeto, goto: projeto }]
384
+ title: Primeira vez
385
+ steps: [{ title: Instalar }, { title: Primeiro projeto }, { title: Pronto? Veja os atalhos, goto: atalhos }]
415
386
  - layout: statement
416
- text: Passou de 30 dias? Renove ou [vire projeto](#projeto).
387
+ text: Já fez o primeiro? Conheça os [atalhos](#atalhos).
417
388
  next: mapa # fim do caminho: volta ao mapa
418
389
  - layout: cards
419
- id: projeto
390
+ id: atalhos
420
391
  back: mapa
421
392
  next: mapa
422
- title: Projeto
423
- items: [{ title: DEV, text: 30 dias }, { title: HOM, text: 30 dias }, { title: PROD, text: sem prazo }]
393
+ title: Já uso
394
+ items: [{ title: Teclado, text: sem o mouse }, { title: Modelos, text: reaproveite }, { title: Automação, text: sem cliques }]
424
395
  ```
425
396
 
426
397
  ## One-page (`onepage`)
@@ -436,23 +407,23 @@ aparece como frase curta em destaque. É denso de propósito: o limite de palavr
436
407
  ```yaml
437
408
  - layout: onepage
438
409
  kicker: Proposta
439
- title: Cadastro digital de clientes
440
- subtitle: Menos papel, menos fila, menos retrabalho
410
+ title: Agendamento online de consultas
411
+ subtitle: Menos telefone, menos espera, menos falta
441
412
  journey:
442
- - { icon: user, title: Cliente chega, text: Fila de 40 min }
443
- - { icon: file-text, title: Preenche papel, text: 3 formulários }
444
- - { icon: check, title: Conta aberta, text: Até 5 dias }
413
+ - { icon: user, title: Paciente liga, text: Espera de 15 min }
414
+ - { icon: file-text, title: Preenche a ficha, text: 3 formulários }
415
+ - { icon: check, title: Consulta marcada, text: Até 5 dias }
445
416
  problem:
446
- text: O cadastro em papel atrasa a abertura de contas.
447
- numbers: [{ value: 5 dias, label: para abrir uma conta }, { value: 20%, label: dos cadastros refeitos }]
417
+ text: Marcar por telefone atrasa as consultas.
418
+ numbers: [{ value: 5 dias, label: para marcar uma consulta }, { value: 20%, label: de faltas }]
448
419
  solution:
449
- text: Cadastro no tablet, com validação na hora e assinatura digital.
450
- items: [Conta aberta no mesmo dia, Zero papel na agência]
420
+ text: Agendamento pelo celular, com confirmação automática e lembrete.
421
+ items: [Consulta marcada no mesmo dia, Zero ligação para remarcar]
451
422
  dashboard:
452
- numbers: [{ value: 1,2 mi, label: cadastros por ano, trend: +8% }]
423
+ numbers: [{ value: 1,2 mi, label: consultas por ano, trend: +8% }]
453
424
  figures:
454
- - { title: Tempo por etapa (min), chart: bar, data: [{ label: Fila, value: 40 }, { label: Papel, value: 25 }] }
455
- - { title: Cadastros por UF (mil), ufmap: { SP: 320, RJ: 140, MG: 150, BA: 90 }, highlight: [SP] }
425
+ - { title: Tempo por etapa (min), chart: bar, data: [{ label: Telefone, value: 15 }, { label: Ficha, value: 10 }] }
426
+ - { title: Consultas por UF (mil), ufmap: { SP: 320, RJ: 140, MG: 150, BA: 90 }, highlight: [SP] }
456
427
  ```
457
428
 
458
429
  ## Status semanal (`status`)
@@ -470,15 +441,29 @@ status por projeto, um slide `status` para cada.
470
441
  title: Portal do cliente
471
442
  health: risco
472
443
  progress: 65
473
- highlight: Login novo em homologação
444
+ highlight: Login novo em teste com usuários
474
445
  done: [Tela de login, { text: Integração com o cadastro, owner: Ana }]
475
446
  doing: [Recuperação de senha]
476
- blocked: [{ text: Liberação de firewall, owner: Infra, due: 30/09 }]
477
- risks: [Prazo de HOM apertado]
478
- upcoming: [Homologar com o negócio]
447
+ blocked: [{ text: Aprovação do texto de privacidade, owner: Jurídico, due: 30/09 }]
448
+ risks: [Prazo do teste apertado]
449
+ upcoming: [Teste com 20 usuários]
479
450
  shots: [{ image: imagens/login.png, caption: Nova tela de login }]
480
451
  ```
481
452
 
453
+ ### Cartão que vira e botão + (interatividade de infográfico)
454
+
455
+ Cartão com `flip` gira no clique e mostra o verso: `flip: "texto"` ou `flip: { title: "Clique, descubra", text: "…" }` (ou `flipTitle`). (Não confunda com `back`, o botão Voltar da navegação.) Um ícone de girar no canto avisa que vira; Enter/Espaço também viram; sair do slide desvira. Use para a ideia principal na frente e o detalhe, o exemplo ou a pista no verso — a plateia descobre explorando. No PDF e no PPTX sai a frente (ponha o verso nas notas se ele precisar aparecer impresso).
456
+
457
+ ```yaml
458
+ - layout: cards
459
+ title: Três movimentos
460
+ items:
461
+ - { icon: clock, title: Visualizar ideias, flip: "Desenhe antes de escrever." }
462
+ - { icon: bar-chart-3, title: Ativar a experiência, flip: { title: "Clique, descubra", text: "Os detalhes ficam para quem explora." } }
463
+ ```
464
+
465
+ O botão + (`more` no marco da linha do tempo, ou o elemento `pop` em qualquer lugar) faz o mesmo papel para pontos soltos: o detalhe fica guardado até alguém clicar.
466
+
482
467
  ## Elementos (dentro de `content`, `side`, `add`, `figure`, `elements`…)
483
468
 
484
469
  Todo elemento aceita: `step` (clique em que aparece), `exit` (clique em que some), `anim` (`up` padrão, `fade`, `pop`, `left`, `right`, `down`, `zoom`, `none`), `w`, `h`, `flex`, `color`, `bg`, `align`, `pad`, `card: true|hi`, `class`, `style` e, no `canvas`, `x`, `y`.
@@ -497,6 +482,7 @@ Todo elemento aceita: `step` (clique em que aparece), `exit` (clique em que some
497
482
  | pontos | `{ points: fone }` ou `{ points: { de: fone, para: mic, legenda: "Ouvindo", legendaPara: "Agindo" } }` — ícone desenhado com luzinhas que viajam de uma forma a outra no clique (só no HTML; PPTX/PDF usam a inicial). Formas: `fone`, `mic`, `doc`, `planilha`, `busca`, `chat` |
498
483
  | forma | `{ shape: rect|rounded|circle|pill|line|triangle|diamond|hexagon|star|arrow|chevron|bubble, fill: hi, stroke: fg, strokeWidth, w, h, content }` (circle vira elipse se w ≠ h; triangle…bubble são desenhos com preenchimento e contorno) |
499
484
  | selo | `{ badge: "NOVO" }` |
485
+ | botão + com balão | `{ pop: { title: "Planejar", text: "Estruture antes de desenhar.", side: above }, x: 1400, y: 300 }` (atalho: `{ pop: "texto" }`) — botão redondo com +; o clique abre um balãozinho com título e texto e escurece o resto do slide; clicar de novo, fora ou trocar de slide fecha. `side`: `above` (padrão), `below`, `left`, `right`. Bom em cima de mapa, foto ou diagrama (ponto a explorar); fechado no PDF e no PPTX |
500
486
  | aviso | `{ aviso: { tipo: dica, titulo: "Dica", texto: "…" } }` — tipos: `importante`, `atencao`, `dica`, `perigo` (atalho: `{ aviso: "texto" }` vira dica). Caixa com ícone e cor do tema para o que não pode passar batido; slide denso fecha com 1 takeaway em ==destaque== mais um aviso quando couber |
501
487
  | vídeo | `{ video: "https://…", label: "Assistir" }` · loop silencioso de fundo/detalhe: `{ video: cena.mp4, loop: true, poster: capa.jpg }` (repete sozinho, sem controles; PPTX/PDF usam o `poster` ou o primeiro quadro) |
502
488
  | HTML livre | `{ html: "<div>…</div>" }` |
@@ -563,8 +549,8 @@ Linhas que começam com PALAVRAS EM MAIÚSCULAS seguidas de `:` viram etiquetas
563
549
 
564
550
  Como no PowerPoint, são duas escolhas independentes:
565
551
 
566
- - **Tema** (`theme`): fontes, raio das bordas, textura e uma **pele** própria que rearruma capa, seção e encerramento, muda o jeito dos slides de conteúdo (título, cartões, marcadores da lista, citação, número grande, frase) e põe ornamentos (`sinal`: faixa zebrada e selo no chapéu; `editorial`: fios e capa centralizada; `noite`: moldura fina; `bauhaus`: círculo, quadrado e triângulo; `terminal`: janela com barra e prompt; `jornal`: fios de jornal e manchete sublinhada; `rabisco`: fitas adesivas e títulos inclinados; `oceano`: ondas e chapéu em pílula; `pop`: adesivos e sombra chapada; `aurora`: brilhos e traço em gradiente; `prata`: limpo e centralizado; `relevo`: ficção científica sóbria (sala de controle de filme, sem néon): grafite profundo, curvas de nível ao fundo, cantoneiras de mira, título leve embaixo à esquerda, rótulos técnicos em monoespaçada; combina com ilustração 3D realista (terreno, cidade, água) e gráfico 3D (`science` com superfície); `arcade`: videogame e fliperama, tela de tubo com linhas de varredura, neon, título em pixel no meio e chão de tijolos de jogo de plataforma; `aluminio`: prata metálico de lançamento de aparelho premium, título cromado embaixo à esquerda e um disco de metal polido; `manual` e `manual-noite`: documentação técnica, sem ornamento, código e texto corrido legíveis — o par claro/escuro do mesmo arranjo, para material de consulta, tutorial e apostila: `manual` imprime bem, `manual-noite` descansa a vista). Nos slides de conteúdo: `sinal` barra de aviso e placas; `editorial` fios finos e citação centralizada; `noite` tudo centralizado e cartões vazados; `bauhaus` faixas de cor primária e círculos; `terminal` título como comando e cartões-janela; `jornal` fios duplos e colunas; `oceano` cartões flutuando e balões; `pop` contorno grosso e sombra dura; `prata` centralizado e sem caixa; `aluminio` cartões de alumínio com chanfro de luz; `relevo` painéis de vidro fosco com traço gelo; `arcade` cartões de 8 bits com borda de pixel e sombra dura; `rabisco` tracejados e números circulados; `aurora` vidro com brilho. Trocar o tema já muda o arranjo: não reescreva slides só para "combinar" com o tema.
567
- - **Paleta** (`palette`): só as cores, em qualquer tema. `tinta`, `floresta`, `mar`, `entardecer`, `lavanda`, `grafite`, `neon`, `areia`, `cereja`, `corporativo`, `luzquente`, ou as suas: `palette: { paper: "F4F1EA", ink: "161616", accent: "D7263D", alert: "1B998B" }`. Os quatro tons saem dessas quatro cores, com contraste garantido. A paleta troca também o fundo: em tema escuro por natureza (`relevo`, `arcade`, `aurora`, `noite`, `terminal`), uma paleta de papel claro (`safira`, `corporativo`, `tinta`…) deixa o tema claro; para manter o visual escuro que o pedido quer, não ponha paleta (ou use uma de papel escuro, como `neon`).
552
+ - **Tema** (`theme`): fontes, raio das bordas, textura e uma **pele** própria que rearruma capa, seção e encerramento, muda o jeito dos slides de conteúdo (título, cartões, marcadores da lista, citação, número grande, frase) e põe ornamentos (`sinal`: faixa zebrada e selo no chapéu; `editorial`: fios e capa centralizada; `noite`: moldura fina; `bauhaus`: círculo, quadrado e triângulo; `terminal`: janela com barra e prompt; `jornal`: fios de jornal e manchete sublinhada; `rabisco`: fitas adesivas e títulos inclinados; `oceano`: ondas e chapéu em pílula; `pop`: adesivos e sombra chapada; `aurora`: brilhos e traço em gradiente; `prata`: limpo e centralizado; `relevo`: ficção científica sóbria (sala de controle de filme, sem néon): grafite profundo, curvas de nível ao fundo, cantoneiras de mira, título leve embaixo à esquerda, rótulos técnicos em monoespaçada; combina com ilustração 3D realista (terreno, cidade, água) e gráfico 3D (`science` com superfície); `arcade`: videogame e fliperama, tela de tubo com linhas de varredura, neon, título em pixel no meio e chão de tijolos de jogo de plataforma; `aluminio`: prata metálico de lançamento de aparelho premium, título cromado embaixo à esquerda e um disco de metal polido; `wine`: o `musgo` em vinho (mesmo arranjo, fontes, faixa e rede na capa): fundo vinho quase preto, vermelho-rosado e rosé, com o vermelho forte só no detalhe; `caderno`: visual thinking em papel claro — título em letra de mão alta (Amatic SC) com traço de lápis, chapéu coral em serifada (Gelasio), frase em lilás, rabiscos de ícones em pastel nos cantos (lupa, ampulheta, engrenagem, lápis, chave, lâmpada); `lousa`: quadro-negro verde com giz — título em giz amarelo (Cabin Sketch) com traço laranja, linha de giz sob o título, poeira e marcas de giz apagado, lâmpada e lápis de giz na capa; `cartaz`: cartaz de protesto em papel cinza com grão — condensada pesada (Bebas Neue) em faixa vermelha torta, chapéu como etiqueta amarela, moldura preta grossa na capa, número da seção num disco amarelo; `infografico`: dados chapados — capa azul com chão verde e nuvem, títulos em maiúsculas, chapéu numa tarja verde, números enormes em condensada; `musgo`: laboratório noturno de bom gosto (verde-musgo quase preto, âmbar e sálvia, serifada Fraunces com o destaque do título em âmbar itálico, rótulos em IBM Plex Mono com fio âmbar, texto em Space Grotesk): grade de pontos que some nas bordas e luz âmbar na capa, seção como separador com o número entre fios na linha do chapéu e o título grande embaixo, e a faixa que corre no pé da capa com os títulos das seções (`ticker`); combina com o terminal de cenas (`motion: {type: console}`) na figura da capa ou num `canvas`; `manual` e `manual-noite`: documentação técnica, sem ornamento, código e texto corrido legíveis — o par claro/escuro do mesmo arranjo, para material de consulta, tutorial e apostila: `manual` imprime bem, `manual-noite` descansa a vista). Nos slides de conteúdo: `sinal` barra de aviso e placas; `editorial` fios finos e citação centralizada; `noite` tudo centralizado e cartões vazados; `bauhaus` faixas de cor primária e círculos; `terminal` título como comando e cartões-janela; `jornal` fios duplos e colunas; `oceano` cartões flutuando e balões; `pop` contorno grosso e sombra dura; `prata` centralizado e sem caixa; `aluminio` cartões de alumínio com chanfro de luz; `relevo` painéis de vidro fosco com traço gelo; `arcade` cartões de 8 bits com borda de pixel e sombra dura; `rabisco` tracejados e números circulados; `aurora` vidro com brilho; `caderno` cartões brancos com moldura grossa pastel (menta, lilás, amarelo, coral) e marcador amarelo contornado; `lousa` cartões contornados a giz com borda torta e marcadores em pingo de giz; `cartaz` cartões brancos girados como fotos coladas, números de lista em etiqueta e destaque em vermelho; `infografico` cartões com a faixa da cor do grupo, números em cartões coloridos e números de lista em círculos coloridos; `musgo`/`wine` cartões vazados que sobem no mouse, números em monoespaçada âmbar, marcador em losango, código em janela com três bolinhas e botões âmbar. Trocar o tema já muda o arranjo: não reescreva slides só para "combinar" com o tema.
553
+ - **Paleta** (`palette`): só as cores, em qualquer tema. `tinta`, `floresta`, `mar`, `entardecer`, `lavanda`, `grafite`, `neon`, `areia`, `cereja`, `corporativo`, `luzquente`, ou as suas: `palette: { paper: "F4F1EA", ink: "161616", accent: "D7263D", alert: "1B998B" }`. Os quatro tons saem dessas quatro cores, com contraste garantido. A paleta troca também o fundo: em tema escuro por natureza (`relevo`, `arcade`, `aurora`, `noite`, `terminal`, `musgo`, `wine`, `lousa`), uma paleta de papel claro (`safira`, `corporativo`, `tinta`…) deixa o tema claro; para manter o visual escuro que o pedido quer, não ponha paleta (ou use uma de papel escuro, como `neon`).
568
554
  - **Paletas de família** (para identidade de marca sem cansar a vista): a cor forte da marca fica só no detalhe (`alert`, a ênfase pontual) e a página trabalha com os parentes mais agradáveis dela (`accent` e `family`). `rubi` (rosas, magenta e vinho; vermelho só no detalhe), `ametista` (roxos e lilases), `tangerina` (laranja com azul-marinho), `safira` (azuis com um toque âmbar), `esmeralda` (verdes). Na sua: `palette: { paper: "FFFFFF", ink: "3B2B33", accent: "B83A6E", alert: "CC092F", family: ["F9DCE5", "EFA3BC", "D9668F", "7E2349"] }` (de 2 a 8 parentes). `family` pinta as séries extras dos gráficos e os grupos e ramos dos diagramas. Pedido de "cores da empresa X": monte uma paleta de família assim, com a cor forte em `alert`. Para clima futurista de bom gosto (luz quente de prédios e shows de drones, nunca neon barato): `luzquente` — brancos quentes e âmbar que funcionam no claro e, no `tone: dark`, viram HUD âmbar sobre carvão quente.
569
555
 
570
556
  - **Identidade** (`identity: trabalho`, no deck): as fontes da empresa da pessoa (e a paleta preferida), configuradas só no computador dela (`~/.sagadeck/identidades.yaml`; no Studio, aba Design, grupo Identidade). Corpo, rótulos e código sempre na fonte da empresa; títulos também, menos nos temas com personalidade (`rabisco`, `pop`, `terminal`, `jornal`, `bauhaus`), que mantêm o título deles. A paleta da identidade vale quando o deck não escolheu outra. Nunca invente o nome de uma identidade: use só a que a pessoa pedir ou a que o deck já tem; numa máquina sem ela, a apresentação sai com as fontes do tema.
@@ -625,25 +611,20 @@ Sagadeck.widget("contador", {
625
611
  ```
626
612
  No YAML: `widgets: [widgets/contador.js]` e `{ widget: contador, rotulo: "Votos" }`. No PowerPoint o widget vira uma imagem do estado final.
627
613
 
628
- ## Texto no cenário (`scenography`)
629
-
630
- Composição estática: o texto permanece editável, integrado a planos, luz e profundidade. `scene`: `stage` (letras monumentais atrás de uma escultura), `floor` (texto no chão), `signs` (placa em perspectiva), `terminal` (terminal hacker), `cafe` (lousa de café com letreiro neon), `travel` (cartão de embarque), `ticker` (pregão com cotações e candles), `marquee` (letreiro de cinema com lâmpadas), `blueprint` (planta técnica), `magazine` (capa de revista), `orbit` (planeta e estrelas), `synthwave` (neon anos 80) ou `gallery` (parede de galeria). Cada uma tem um tamanho de título padrão; `titleSize` vence. Campos: `title` (frase curta, quebra de linha permitida), `kicker`, `subtitle`, `caption`, `titleSize`, `image` (fundo opcional), `imageOpacity` (transparência do fundo, de 0 a 1; padrão 0.85), `foreground` (recorte PNG transparente colocado à frente das letras). Um fundo arbitrário não é segmentado automaticamente: para oclusão de uma pessoa, forneça o recorte em `foreground`.
631
-
632
- Demonstração com todas: biblioteca, Nova, "Exemplo: texto no cenário".
633
-
634
- ```yaml
635
- - layout: scenography
636
- scene: floor
637
- title: "NOVOS\nCAMINHOS"
638
- kicker: APRENDER PARA TRANSFORMAR
639
- caption: WORKSHOP / BRIDGE
640
- deco: none
641
- ```
642
-
643
614
  ## Projeto: a pasta da apresentação
644
615
 
645
616
  No Studio, a pasta do deck é um projeto (aba **Arquivos**, à esquerda): o `.yaml`, `imagens/`, `contexto/` (anexos, prints colados, planilhas, anotações `.md`) e `.sagadeck/` (a conversa do chat, o cache e a lixeira do projeto, do próprio Studio). O texto do que está em `contexto/` chega a você junto do pedido, como material anexado (com o caminho, ex.: `contexto/vendas.csv`): use os números e fatos de lá. Uma planilha de `contexto/` pode alimentar um gráfico com `csv: contexto/vendas.csv` (CSV) ou pela sugestão de gráficos da planilha no Studio (que grava `from:`).
646
617
 
618
+ ## Exportação pelo Studio
619
+
620
+ Arquivo › Baixar PowerPoint, PDF, roteiro, material de estudo ou Baixar tudo inicia a geração **no servidor do
621
+ Studio** (na própria máquina no modo local). O painel **Exportações** mostra a etapa, o slide atual, o tempo
622
+ decorrido e **Pronto para baixar**, ou a falha. Ele também acompanha os downloads pelo menu do cartão da biblioteca.
623
+ A geração continua ao fechar/recarregar a aba; ao voltar ao editor ou à biblioteca, o arquivo pode ser baixado
624
+ pela mesma lista. Guarda as dez exportações mais recentes da pessoa, por até 24 h enquanto o Studio estiver ligado.
625
+ Exportar a demo em prévia não cria uma cópia pessoal. Não há aviso por email. Ao orientar a pessoa a obter o PPTX,
626
+ indique o menu e o painel; só afirme que o arquivo foi gerado quando houver resultado real de exportação.
627
+
647
628
  ## Apresentação importada de PowerPoint
648
629
 
649
630
  Um `.pptx` importado (Biblioteca › Importar apresentação, ou `sagadeck importar arquivo.pptx`) chega **fiel ao original**: cada slide é um `canvas` com os elementos na mesma posição, e o deck tem `import: { from, slides, fonts, snapshots }` e `footer: false` (o original tem o próprio rodapé). Cada slide traz `original: { slide: 7, image: original/slide-07.png }` (a foto do slide original, quando o PowerPoint ou o LibreOffice estavam disponíveis) e a pasta `original/` guarda a cópia do arquivo. Elementos que só aparecem em slides importados:
@@ -665,6 +646,71 @@ Como o slide mestre do PowerPoint: `master:` no deck desenha em todo slide o que
665
646
 
666
647
  Quando melhorar ou reescrever uma apresentação que já existia (principalmente uma importada), marque cada slide que mudou para a pessoa validar: `review: { status: alterado, note: "o que mudou, em uma frase", original: 7 }` (`original` = o número do slide no original) ou `review: { status: novo, note: "por que entrou" }` para slide que não existia. O Studio mostra um selo na miniatura, uma faixa no slide com **Ver original**, **Aceitar** e **Desfazer** (volta ao slide de `original/original.yaml`; slide novo sai) e a lista em Revisar › **Mudanças**. A transformação da apresentação inteira ainda usa dois estados: `pendente` (a proposta ficou ao lado do original porque faltava algo dele; aceitar tira o original, desfazer tira a proposta) e `revisar` (a conferência pela foto achou um problema de desenho). A apresentação e a exportação não mostram as marcas. Nunca apague dados do original: números, nomes, fórmulas, fontes e figuras específicas (um mapa, um experimento de uma cidade) continuam, só mais claros.
667
648
 
649
+ ## Mapa (`map`)
650
+
651
+ Mapa ao vivo (ruas por baixo, arrastável e com zoom ao apresentar) com **camadas** por cima. A planilha é a fonte e o
652
+ mapa é a vista: os pontos vêm de um CSV do projeto (normalmente em `contexto/`), e as linhas e áreas de GeoJSON, GPX
653
+ (rastro de GPS) ou KML. Serve para qualquer ponto de interesse (sensor, medidor, placa solar, unidade de atendimento,
654
+ escola, cinema…) e qualquer traçado ou área (rede, trajeto, bairro, área de obra).
655
+
656
+ ```yaml
657
+ - layout: map
658
+ kicker: Monitoramento
659
+ title: Onde estão os ==sensores==
660
+ basemap: claro # ruas (padrão) | claro | escuro | satelite (se configurado) | nenhum
661
+ build: true # uma camada por clique
662
+ layers:
663
+ - name: Sensores # nome na legenda
664
+ points: contexto/sensores.csv # colunas de latitude e longitude achadas pelo nome (lat/latitude, lon/longitude)
665
+ color: status # coluna: categoria vira cor (legenda clicável); número vira escala
666
+ colors: { ativo: s3, sem sinal: alert } # cor de cada categoria (opcional)
667
+ size: vazao # coluna numérica vira o tamanho do ponto (opcional)
668
+ label: nome # rótulo fixo ao lado de cada ponto (até 60 pontos)
669
+ popup: [nome, status, vazao] # campos do cartão ao clicar (padrão: as primeiras colunas)
670
+ - name: Rede de água
671
+ geojson: contexto/rede.geojson # linhas e polígonos; ou gpx: / kml:
672
+ color: material
673
+ view: fit # quando a camada aparece, a câmera enquadra ela
674
+ - name: Consumo por estado
675
+ areas: { SP: 320, RJ: 140, MG: 150 } # siglas de UF ou códigos de país (BR, PT…): pinta pela escala
676
+ legend: mil m³
677
+ ```
678
+
679
+ - `geojson:` também aceita o GeoJSON escrito no próprio slide (FeatureCollection, Feature ou só a geometria), para um
680
+ desenho pequeno; dados de verdade ficam num arquivo do projeto. Nunca invente o traçado de algo real.
681
+ - `points:` também aceita a lista no próprio slide: `[{ nome: Centro, lat: -23.55, lon: -46.63, status: ativo }]`.
682
+ Uma coluna só com "lat, lon" vale (`coordenadas`, `posicao`). Use ponto ou vírgula decimal; nunca invente
683
+ coordenadas: elas vêm da planilha, do arquivo ou de uma busca. Linha sem posição válida fica de fora (o fiscal avisa).
684
+ - `color:` aceita também uma cor fixa (`s1`, `em`, `hi`, `alert`, `#1F6FB2`). `step` (número) diz em que clique a
685
+ camada aparece; `view` da camada (`fit` ou `{ center: [lat, lon], zoom }`) leva a câmera até ela nesse clique.
686
+ - `view:` do slide fixa o enquadramento (`{ center: [-23.55, -46.63], zoom: 13 }`); sem ele, o mapa enquadra os dados.
687
+ - `basemap: claro` e `escuro` usam fundos vetoriais do OpenFreeMap, sem chave: o mar tem cor própria e a fronteira
688
+ marítima não aparece, preservando o litoral e as divisas terrestres. `ruas` continua no OpenStreetMap. Em
689
+ **Configurar mapa**, os fundos claro e escuro podem usar outro estilo vetorial (JSON) ou tiles com `{z}/{x}/{y}`.
690
+ - Planilha só com endereço (sem latitude e longitude): no Studio, a planilha aberta (aba Arquivos) tem **Achar
691
+ coordenadas**, que pergunta antes de mandar os endereços para o serviço de fora e grava as colunas `latitude` e
692
+ `longitude`; **Pôr no mapa** cria o slide a partir dela. Sugira esses botões em vez de inventar coordenadas.
693
+ Com um slide de mapa selecionado, a planilha fica ao lado dele: clicar num ponto seleciona a linha e selecionar
694
+ uma linha abre o cartão do ponto. O enquadramento automático deixa os pontos livres da legenda.
695
+ - **Editar mapa** (botão na prévia do slide, ou dois cliques no mapa, no Studio): abre uma tela só do mapa. À esquerda
696
+ as camadas; no meio o mapa grande com Selecionar, Ponto, Linha, Área e Régua; à direita as propriedades do que está
697
+ selecionado (os campos de um ponto, linha, área ou região, com o que cada um faz no mapa) ou, sem seleção, da camada
698
+ (cor, tamanho, rótulo, cartão, quando aparece) e do mapa (fundo, enquadramento). Pontos novos vão para a planilha da
699
+ camada, com o endereço preenchido, ou para a lista do slide; linhas e áreas para o GeoJSON da camada ou para o slide
700
+ ("Seguir as ruas" liga os cliques pelo serviço de rotas). Arrasta pontos e vértices, divide e junta linhas e grava o
701
+ enquadramento ("Usar a vista de agora"). Quando a pessoa quiser marcar ou corrigir algo à mão no mapa, indique esse botão.
702
+ - **Dados de fora** (lugares de um tipo, linhas como ciclovias, o contorno de um lugar com nome, uma lista da web,
703
+ coordenadas da planilha da pessoa): peça com o bloco `mapa:` (as regras vêm no prompt); o Studio busca, grava os
704
+ arquivos em `contexto/` com a fonte de cada linha e te devolve o que gravou. Nunca invente coordenada nem contorno.
705
+ - **Análises** (o mais próximo e a distância, quantos num raio ou numa área, faixa em volta de uma linha, onde
706
+ instalar o próximo, rota com tempo, área alcançável em X minutos, rastro de GPS encaixado nas ruas): também pelo
707
+ bloco `mapa:`; o Studio calcula e devolve os números. Nunca calcule distância, contagem ou tempo de cabeça.
708
+ - Serviços (Configurar mapa, opcional): sem chave, os fundos usam OpenStreetMap/OpenFreeMap e os dados vêm dos serviços públicos do OpenStreetMap; a chave
709
+ gratuita do OpenRouteService só acrescenta rotas a pé/de carro/de bicicleta confiáveis e área alcançável.
710
+ - Ao apresentar: clicar num ponto, linha ou área abre o cartão com os dados; clicar na legenda liga e desliga uma
711
+ categoria ou a camada inteira. O fundo vem da internet; sem rede, aparece um aviso e as camadas continuam. No PDF e
712
+ no PowerPoint o mapa sai como estava na tela.
713
+
668
714
  ## Tabelas (`table`)
669
715
 
670
716
  Tabela é tabela, nunca imagem: dados de um livro ou de um PowerPoint que vieram como figura viram `table` quando os valores estão legíveis (o sagadeck alinha os números à direita, com algarismos de mesma largura, e pinta nas cores do tema). Layout `table` (o slide inteiro) ou o elemento `{ table: {…} }` em qualquer lugar (`content`, `add`, `canvas`).
@@ -817,9 +863,9 @@ Os três aceitam `kicker`, `title` e `items: [{title, text, value, icon, code, f
817
863
  - `ribbon`: os mesmos campos em cápsulas arredondadas, centralizadas. Para serviços, etapas ou pilares.
818
864
  - `dossier`: página de consulta, compacta: letra menor e blocos de código (`code`) com quebra de linha. Para material de referência (documentação, payloads, instruções); não imponha a ela o limite de palavras de uma palestra quando a pessoa pede material denso.
819
865
 
820
- No Studio, todo tipo de slide (página de consulta, grade adaptável, diagrama, tipografia cinética, status semanal…) sai da galeria **Novo slide** (Início › Escolher tipo ou Inserir › Novo slide), com busca e categorias; **Layout** troca o formato do slide atual e leva o conteúdo junto. A aba **Avançado** muda a densidade do slide atual: **Padrão**, **Compacta** ou **Mais conteúdo**. A densidade reduz espaçamentos e tamanhos sem apagar o conteúdo; para explicações longas com seções, prefira `dossier`.
866
+ No Studio, todo tipo de slide (página de consulta, grade adaptável, diagrama, status semanal…) sai da galeria **Novo slide** (Início › Escolher tipo ou Inserir › Novo slide), com busca e categorias; **Layout** troca o formato do slide atual e leva o conteúdo junto. A aba **Avançado** muda a densidade do slide atual: **Padrão**, **Compacta** ou **Mais conteúdo**. A densidade reduz espaçamentos e tamanhos sem apagar o conteúdo; para explicações longas com seções, prefira `dossier`.
821
867
 
822
- Para apresentações completas de exemplo, abra **Abrir demos completos** na aba Avançado (ou **Nova → Modelo pronto → Recursos avançados** na biblioteca). Esse demo reúne código denso, página de consulta, grade com oito itens, aviso de segurança, diagrama e tipografia cinética.
868
+ Para apresentações completas de exemplo, abra **Abrir demos completos** na aba Avançado (ou **Demos oficiais** na biblioteca): uma demo por assunto — mapas, programação (código denso, página de consulta, Git a dois, diagramas), APIs com curl, aula de hidráulica, aula de algoritmos e diagramas vivos.
823
869
 
824
870
  Modelos, estilos, demos e exemplos de **Modelo pronto** (na vitrine, "Visuais para começar" e "Recursos do SagaDeck", com a capa de cada um) abrem em **prévia**: dá para navegar, apresentar e experimentar sem criar arquivo. A primeira mudança (ou o botão **Usar como base**) cria uma cópia na biblioteca, no tópico de onde veio (padrão `Modelos`), com as imagens; o modelo de fábrica nunca muda.
825
871
 
@@ -843,13 +889,13 @@ As formas clássicas de slide de consultoria, desenhadas na hora para a quantida
843
889
  ```yaml
844
890
  - layout: infographic
845
891
  shape: metro
846
- title: Os caminhos de um projeto na Bridge
847
- center: { title: Bridge, text: Um pedido, vários caminhos }
892
+ title: Os canais de uma loja
893
+ center: { title: Loja, text: Um pedido, vários caminhos }
848
894
  items:
849
- - { title: Lote, text: Databricks chama a Bridge de madrugada, icon: moon }
850
- - { title: Teams, text: Copilot Studio + Power Automate, icon: message-square }
851
- - { title: App próprio, text: Wave, arquitetura, infra e rede, icon: app-window }
852
- - { title: SaaS externo, text: Túnel mTLS e serviço extra, icon: globe }
895
+ - { title: Balcão, text: Atendimento na hora, icon: store }
896
+ - { title: App, text: Pede e retira na loja, icon: smartphone }
897
+ - { title: Site, text: Entrega em casa, icon: truck }
898
+ - { title: Parceiros, text: Vitrine em outros sites, icon: globe }
853
899
  ```
854
900
 
855
901
  Infográfico × diagrama: infográfico é para itens paralelos em volta de uma ideia (sem fluxo entre eles, ou com o fluxo simples de `trilhas`) e para **ciclos** (`ciclo`: num fluxograma, a volta ao começo vira setas longas cruzando o desenho); `diagram` (Mermaid) é para processo com decisões, sequência entre sistemas, arquitetura e UML.
@@ -860,7 +906,7 @@ Para processo, fluxo, arquitetura, UML, sequência entre sistemas, ciclo de vida
860
906
 
861
907
  Direção automática: em fluxogramas o sagadeck desenha deitado (`LR`) e em pé (`TB`) e usa o que deixa a letra maior na área do slide. Escreva a direção que fizer sentido; `autoDirection: false` no slide mantém a do código (use só se a pessoa pedir uma direção).
862
908
 
863
- Tipos (primeira linha do código): `flowchart LR` / `flowchart TB` (fluxo, processo, arquitetura), `sequenceDiagram` (quem chama quem, pedido e resposta), `stateDiagram-v2` (ciclo de vida: DEV → HOM → PROD), `classDiagram` e `erDiagram` (UML e modelo de dados), `journey` (jornada com notas), `mindmap` (mapa de ideias, sopa de letrinhas organizada), `timeline`, `block-beta` (blocos de arquitetura), `gantt`, `quadrantChart`, `gitGraph` (branches e commits do Git: `commit`, `branch nome`, `checkout nome`, `merge nome`, `cherry-pick id: "…"`; é o diagrama certo para "linhas de commits", rebase × merge e fluxo de branches).
909
+ Tipos (primeira linha do código): `flowchart LR` / `flowchart TB` (fluxo, processo, arquitetura), `sequenceDiagram` (quem chama quem, pedido e resposta), `stateDiagram-v2` (ciclo de vida: rascunho → revisão → publicado), `classDiagram` e `erDiagram` (UML e modelo de dados), `journey` (jornada com notas), `mindmap` (mapa de ideias, sopa de letrinhas organizada), `timeline`, `block-beta` (blocos de arquitetura), `gantt`, `quadrantChart`, `gitGraph` (branches e commits do Git: `commit`, `branch nome`, `checkout nome`, `merge nome`, `cherry-pick id: "…"`; é o diagrama certo para "linhas de commits", rebase × merge e fluxo de branches).
864
910
 
865
911
  ```yaml
866
912
  - layout: diagram
@@ -885,26 +931,26 @@ Setas no `flowchart`: `-->` normal, `-.->` pontilhada (opcional, eventual), `==>
885
931
 
886
932
  ```yaml
887
933
  - layout: diagram
888
- kicker: Governança
889
- title: Do pedido de acesso à ==produção==
890
- caption: Experimento é prorrogável; em HOM e PROD as chaves ficam no Key Vault
934
+ kicker: Processo
935
+ title: Do pedido à ==entrega==
936
+ caption: Sob medida leva mais tempo; o fornecedor entrega o material da montagem
891
937
  mermaid: |
892
938
  flowchart LR
893
- A([:key-round: Pedido de acesso]):::hi --> B{Experimento ou projeto?}
894
- subgraph EXP[Experimento]
895
- C[:flask-conical: 30 dias, dados fictícios]
939
+ A([:shopping-cart: Pedido]):::hi --> B{Tem em estoque?}
940
+ subgraph EST[Estoque]
941
+ C[:package: Separar e embalar]
896
942
  end
897
- subgraph PRJ[Projeto]
898
- D[DEV 30 dias] ==> E[HOM 30 dias] ==> F[:rocket: PROD]:::em
943
+ subgraph PRD[Sob medida]
944
+ D[Cortar] ==> E[Montar] ==> F[:truck: Enviar]:::em
899
945
  end
900
- B -->|experimento| C
901
- B -->|projeto| D
902
- C -.->|deu certo| D
903
- K[(Key Vault via RITM)]:::suave -.- E
946
+ B -->|sim| C
947
+ B -->|não| D
948
+ C -.->|pronto| F
949
+ K[(Fornecedor)]:::suave -.- E
904
950
  ```
905
951
 
906
952
  Regras de bom desenho (siga sempre):
907
- - Agrupe com `subgraph` o que é da mesma área, time, camada ou fase (Front-end, Bridge, Segurança; DEV, HOM, PROD): é o que dá cor e organização ao desenho. 2 a 5 grupos por slide.
953
+ - Agrupe com `subgraph` o que é da mesma área, time, camada ou fase (Front-end, Back-end, Segurança; rascunho, revisão, publicado): é o que dá cor e organização ao desenho. 2 a 5 grupos por slide.
908
954
  - Coisas de fora (usuário, sistema externo, banco de terceiros) com `:::suave`, fora dos grupos.
909
955
  - Rótulos curtos: 1 a 4 palavras por nó (detalhe vai em `caption`, nas `notes` ou em outro slide). Rótulo de seta com 1 a 3 palavras.
910
956
  - No máximo ~12 nós por slide. Processo maior: divida em slides (visão geral primeiro, depois um slide por fase) em vez de encolher tudo.
@@ -934,6 +980,8 @@ ficam na pasta `imagens/` da apresentação.
934
980
 
935
981
  ## Ajustes diretos no Studio
936
982
 
983
+ No editor, **Assistente** fica por último à direita no cabeçalho do painel, separado de Formatar, Propriedades e Variáveis. Seu nome permanece visível ao usar qualquer opção. O editor abre no Assistente, respeitando quem fechou o painel; nesse caso, o atalho flutuante reabre o chat. Trocar de opção mantém a conversa e o rascunho.
984
+
937
985
  Em **Inserir → Neste slide**: Texto, Formas (menu com 12 desenhos: retângulo, arredondado, elipse, pílula, linha, triângulo, losango, hexágono, estrela, seta, chevron, balão), Imagem e Ícone adicionam elementos sem trocar o layout. Um clique em qualquer ponto de um objeto (texto, forma, imagem) o seleciona; clicar de novo no texto selecionado (ou duplo clique) escreve. Arrastar numa área vazia desenha um retângulo que seleciona vários; Shift+clique soma. Selecionados, dá para arrastar juntos, mover com as setas, redimensionar pela alça (um só) e usar a barra que flutua acima da seleção: tamanho e cor do texto, preenchimento da forma (`visualEdits.fill`), trazer para frente, enviar para trás (fica atrás dos outros objetos, nunca do fundo), excluir, alinhar (esquerda, centro, direita, em cima, meio, embaixo: vários entre si; um só, no slide), distribuir (3 ou mais, mesmo espaço), copiar e colar estilo (Ctrl+Alt+C / Ctrl+Alt+V), travar (o clique atravessa) e, numa imagem, trocar a imagem (`visualEdits.image`, com `fit: cover|contain` e `focus`: center, top, bottom, left, right, top left…). Ao arrastar, guias grudam nas bordas e no centro do slide e dos outros objetos (Alt solta). Na aba Propriedades, **Objetos do slide** lista tudo o que está no slide: seleciona até o travado, oculta/mostra e trava/destrava (`locked`; a decoração que veio do PowerPoint, `deco: true`, já vem travada). Tab/Shift+Tab passam de um objeto para outro; Escape solta. A aba **Propriedades** do painel lateral é o inspetor (como o Object Inspector): mostra só as categorias que fazem sentido para o que está selecionado (Posição e tamanho; Texto; Preenchimento e contorno; Aparência; Animação; Avançado) e, sempre, as do Slide e da Apresentação. Os ajustes de objeto ficam em `visualEdits` (`dx, dy, w, h, rotate, z, size, color, weight, italic, align, lineHeight, letterSpacing, uppercase, fill, stroke, strokeWidth, radius, opacity, shadow: suave|forte, step, anim, hidden, locked, image, fit, focus`); não os invente ao criar um deck. Delete/Backspace excluem o objeto selecionado (fica em `visualEdits` como `hidden`, recuperável); Ctrl+Z / Ctrl+Y desfazem e refazem qualquer mudança da apresentação (a da tela, a do formulário, a do assistente), com os botões ao lado do título. Duplo clique permite voltar a escrever. Os ajustes são persistidos em `visualEdits`, com chaves geradas pelo renderizador; não invente essas chaves ao criar um deck. Prefira alterar os campos semânticos. A exclusão visual usa `hidden` para preservar conteúdo recuperável. Mudanças estruturais grandes podem invalidar ajustes: remova `visualEdits` ao reconstruir um slide.
938
986
 
939
987
  `Arrumar layout` (aba Revisar) é local e baseado em regras: corrige sobreposição, margem, título comprido e texto que não coube, diz o que fez e se desfaz. `Revisar com IA` envia a imagem renderizada do slide ao modelo configurado e solicita melhorias; usa tokens. O status de IA abre Configurar IA (provedor, chave e modelos desta máquina). Um modelo sem visão é identificado na resposta; conectividade com `/models` não comprova que uma geração será aceita pelo provedor.
@@ -1066,6 +1114,20 @@ elements:
1066
1114
 
1067
1115
  Integre o movimento à direção de arte: geometria ligada a uma figura, pulsos numa linha de processo, detalhe que acompanha uma moldura ou tipografia, cores e escala da mesma composição. Não traduza “eco animado” em retângulos opacos soltos e repetidos no canto. Uma identidade tecnológica deve existir também nas cores, formas e hierarquia do slide; um widget não resolve uma página genérica. Use elementos `motion` posicionados em `add`/`canvas` quando uma integração específica pedir outro lugar/tamanho, mantendo conteúdo e controles livres. Estas são escolhas pelo briefing e assunto, não uma receita obrigatória para toda apresentação.
1068
1116
 
1117
+ `type: console` é a janela de terminal em cenas: barra com três bolinhas, legenda (`caption`) e contador (01/03); em cada cena o comando (`cmd`) é digitado letra a letra depois do prompt, e a saída (`out`, lista de linhas; a primeira em destaque, como o status de uma resposta) aparece linha a linha; segura a leitura (`hold`, segundos, padrão 3.2) e passa para a próxima cena, em ciclo. Bom para mostrar chamadas de API (`curl`) e suas respostas, ou comandos e resultados. Parado (movimento reduzido, `motion: none`, exportação), mostra a primeira cena completa. Aceita `typing` (segundos por letra, padrão 0.016), `speed`, `fontSize` (padrão 20) e as cores de sempre (fundo, texto, `accent` no prompt e no cursor, `secondary` na primeira linha da saída). É ilustração, não execução: para chamar a API de verdade, use o slide `api`.
1118
+
1119
+ ```yaml
1120
+ figure:
1121
+ motion:
1122
+ type: console
1123
+ caption: contrato do agente — ao vivo
1124
+ scenes:
1125
+ - cmd: "curl -X POST /api/memorias -d '{\"texto\":\"usar pnpm\"}'"
1126
+ out: ["201 Created", "{ \"id\": \"9f3a\" }"]
1127
+ - cmd: "curl '/api/memorias?q=pnpm'"
1128
+ out: ["200 OK · 4 ms", "{ \"total\": 0.74 }"]
1129
+ ```
1130
+
1069
1131
  `type: terminal` digita lentamente um roteiro fornecido em `lines: [linha, linha]` ou `code: texto`, com cursor e rolagem, sem executar o código. Aceita `typing` (segundos por caractere), `speed` e `fontSize` (10–40). Repete após uma pausa de leitura e pausa fora do slide. Para um painel legível de código ao lado de logs rápidos, combine terminal com requests, reservando área suficiente para ambos. O roteiro é do conteúdo solicitado, nunca uma API real inventada sem identificação de exemplo.
1070
1132
 
1071
1133
  ### Abertura com chat preciso e filme separado
@@ -1111,6 +1173,23 @@ No chat, `run.language: web` recebe `code` como JSON: `{"action":"search","query
1111
1173
 
1112
1174
  ## Diagnósticos e suporte
1113
1175
 
1176
+ **O que de IA funciona nesta máquina:** `sagadeck ia-check` (também `POST /api/ia/check` no Studio local e a ferramenta
1177
+ `sagadeck_ia_check` do MCP). Cada recurso com uma chamada de verdade ao provedor configurado, todos ao mesmo tempo, e
1178
+ cada resultado sai assim que chega:
1179
+ - **texto**: pergunta curta com resposta conhecida;
1180
+ - **visão**: uma imagem com duas faixas de cor sorteadas; o modelo precisa dizer as cores na ordem (modelo que não
1181
+ aceita imagem falha, em vez de responder sem ver);
1182
+ - **imagem**: gera uma imagem pequena e confere que voltou PNG, JPEG, WebP ou GIF (grava o arquivo e diz onde);
1183
+ - **pesquisa**: o modelo de pesquisa precisa dizer a data de hoje;
1184
+ - **vídeo**: sem `--video-real`, só confere o modelo no catálogo, de graça, e sai `SEM PROVA`; com `--video-real`,
1185
+ gera o clipe mais curto e leve que o modelo aceita, acompanha, baixa e confere o MP4 (cobrado; leva minutos).
1186
+
1187
+ `--rapido` pula imagem e vídeo; `--so=texto,visao` escolhe; `--json` para máquina (o andamento vai para o stderr); sai
1188
+ com código 1 se algo falhou. O vídeo usa a mesma camada da IA quando há um **modelo de vídeo** em Configurar IA
1189
+ (endereço, chave e adaptador de lá); sem ele, o OpenRouter com `SAGADECK_VIDEO_KEY` ou `OPENROUTER_API_KEY`.
1190
+ `SAGADECK_VIDEO_URL` e `SAGADECK_VIDEO_MODEL` trocam endereço e modelo. Sem catálogo no provedor, o vídeo é gerado
1191
+ assim mesmo (o catálogo só valida quando existe).
1192
+
1114
1193
  Falhas do Studio e da IA devem explicar a operação, distinguir causa comprovada de causa desconhecida e informar código + referência para suporte. Motivos informados pelo provedor são preservados, inclusive em streaming: limite de tokens não é timeout. Nunca atribua uma falha a tokens sem finish_reason: length. Visão de documentos usa SAGADECK_DOCUMENT_VISION_TOKENS (padrão 5000 por página, entre 256 e 32000); quando o provedor informa limite, tenta uma vez com o dobro, até 32000. SAGADECK_LLM_TIMEOUT controla espera sem resposta (padrão 180 s); SAGADECK_LLM_FIRST_TIMEOUT controla primeira resposta em streaming (padrão 600 s). Nenhuma resposta parcial é apresentada como extração completa. Cancelamento é uma ação normal, sem aviso de erro de suporte.
1115
1194
 
1116
1195
  ### Prioridade das figuras e Word legado
package/package.json CHANGED
@@ -1,15 +1,32 @@
1
1
  {
2
2
  "name": "sagadeck",
3
- "version": "1.7.1",
3
+ "version": "1.9.0",
4
4
  "description": "Gerador de apresentações: YAML -> HTML animado + PowerPoint editável, com temas e figuras geradas na hora.",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "sagadeck": "bin/sagadeck.js"
8
8
  },
9
9
  "engines": {
10
- "node": ">=18"
10
+ "node": ">=22.13.0"
11
11
  },
12
12
  "license": "MIT",
13
+ "homepage": "https://github.com/naruminho/sagadeck#readme",
14
+ "bugs": {
15
+ "url": "https://github.com/naruminho/sagadeck/issues"
16
+ },
17
+ "keywords": [
18
+ "apresentacoes",
19
+ "slides",
20
+ "presentation",
21
+ "pptx",
22
+ "powerpoint",
23
+ "pdf",
24
+ "yaml",
25
+ "llm",
26
+ "ai",
27
+ "generator",
28
+ "cli"
29
+ ],
13
30
  "dependencies": {
14
31
  "jszip": "^3.10.2",
15
32
  "katex": "^0.18.9",
@@ -21,18 +38,33 @@
21
38
  "qrcode-generator": "^2.0.4",
22
39
  "yaml": "^2.9.1"
23
40
  },
41
+ "overrides": {
42
+ "image-size": "^2.0.4"
43
+ },
24
44
  "devDependencies": {
25
45
  "@fontsource-variable/caveat": "^5.3.0",
46
+ "@fontsource-variable/fraunces": "^5.3.0",
26
47
  "@fontsource-variable/fredoka": "^5.3.0",
48
+ "@fontsource-variable/gelasio": "^5.3.0",
27
49
  "@fontsource-variable/inter": "^5.3.0",
50
+ "@fontsource-variable/montserrat": "^5.3.0",
28
51
  "@fontsource-variable/plus-jakarta-sans": "^5.3.0",
52
+ "@fontsource-variable/space-grotesk": "^5.3.0",
53
+ "@fontsource/amatic-sc": "^5.3.0",
54
+ "@fontsource/bebas-neue": "^5.3.0",
55
+ "@fontsource/cabin-sketch": "^5.3.0",
29
56
  "@fontsource/comic-neue": "^5.3.0",
57
+ "@fontsource/ibm-plex-mono": "^5.3.0",
58
+ "@fontsource/itim": "^5.3.0",
30
59
  "@fontsource/patrick-hand": "^5.3.0",
31
60
  "@fontsource/press-start-2p": "^5.3.0",
32
61
  "@fontsource/vt323": "^5.3.0",
62
+ "@maplibre/maplibre-gl-leaflet": "0.1.4",
33
63
  "@material-symbols/svg-400": "^0.47.5",
34
64
  "esbuild": "^0.28.2",
35
65
  "jsqr": "^1.4.0",
66
+ "leaflet": "1.9.4",
67
+ "maplibre-gl": "6.13.0",
36
68
  "mermaid": "^11.17.2"
37
69
  },
38
70
  "scripts": {
@@ -11,7 +11,7 @@ import { spawn } from "node:child_process";
11
11
  import fs from "node:fs";
12
12
  import path from "node:path";
13
13
  import os from "node:os";
14
- import { videoOperation } from './video-generation.js';
14
+ import { videoOperation, videoSetup } from './video-generation.js';
15
15
  import { webOperation } from './web-operation.js';
16
16
 
17
17
  // Registro de auditoria: cada comando pedido pela IA (aprovado, recusado ou executado), uma linha JSON em
@@ -69,7 +69,7 @@ export async function runCommand(request, { cwd, env = {}, mask = (s) => s, time
69
69
  }
70
70
  if(language==='video'){
71
71
  let args; try { args = typeof code === 'object' && code !== null ? code : JSON.parse(code); } catch(e) { return {language,exitCode:1,stdout:'',stderr:mask(`run.code precisa de JSON válido: ${e.message}`),timedOut:false}; }
72
- try{return{language,exitCode:0,stdout:mask(JSON.stringify(await videoOperation(args,{cwd,key:env.SAGADECK_VIDEO_KEY||env.OPENROUTER_API_KEY||process.env.SAGADECK_VIDEO_KEY||process.env.OPENROUTER_API_KEY}))),stderr:'',timedOut:false};}
72
+ try{return{language,exitCode:0,stdout:mask(JSON.stringify(await videoOperation(args,{cwd,setup:videoSetup({env:{...process.env,...env}})}))),stderr:'',timedOut:false};}
73
73
  catch(e){return{language,exitCode:1,stdout:'',stderr:mask(e.message),timedOut:false};}
74
74
  }
75
75
  const win = process.platform === "win32";