primocode 9.8.0-beta.2 → 9.8.0-beta.21

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 (74) hide show
  1. package/README.md +33 -6
  2. package/app/ansi.js +55 -0
  3. package/app/app.css +482 -281
  4. package/app/app.js +888 -315
  5. package/app/index.html +176 -101
  6. package/app/primo-marca.js +58 -1
  7. package/bin/primocode.js +697 -118
  8. package/comandos/explicar.md +14 -0
  9. package/comandos/publicar.md +10 -0
  10. package/comandos/revisar.md +13 -0
  11. package/lib/act.js +130 -26
  12. package/lib/api.js +8 -1
  13. package/lib/app.js +317 -74
  14. package/lib/browser.js +79 -3
  15. package/lib/catalogo.js +11 -3
  16. package/lib/checkpoint-git.js +218 -0
  17. package/lib/checkpoint.js +249 -0
  18. package/lib/claude-engine.js +25 -3
  19. package/lib/comandos-extra.js +481 -0
  20. package/lib/comandos.js +104 -0
  21. package/lib/config.js +21 -4
  22. package/lib/estudio/acervo-site.js +157 -0
  23. package/lib/estudio/assets.js +77 -3
  24. package/lib/estudio/cinema.js +354 -0
  25. package/lib/estudio/composicao.js +470 -0
  26. package/lib/estudio/edicao.js +450 -0
  27. package/lib/estudio/impacto.js +263 -0
  28. package/lib/estudio/index.js +769 -5
  29. package/lib/estudio/plano.js +5 -2
  30. package/lib/estudio/remotion.js +228 -23
  31. package/lib/estudio/slides.js +34 -30
  32. package/lib/fala.js +95 -1
  33. package/lib/local/cerebro.json +361 -180
  34. package/lib/local/entrada.js +18 -8
  35. package/lib/local/motor-cli.js +1 -1
  36. package/lib/mencoes.js +98 -0
  37. package/lib/offline.js +168 -0
  38. package/lib/painel.js +291 -0
  39. package/lib/perigo.js +256 -0
  40. package/lib/pre-leitura.js +118 -0
  41. package/lib/repeticao.js +4 -2
  42. package/lib/skills.js +6 -1
  43. package/lib/tempos.js +62 -0
  44. package/lib/ui.js +171 -17
  45. package/package.json +3 -2
  46. package/skills/apresentacao-pptx/SKILL.md +52 -0
  47. package/skills/cartaz-de-arte/LICENSE.txt +202 -0
  48. package/skills/cartaz-de-arte/SKILL.md +47 -0
  49. package/skills/criar-skill/LICENSE.txt +202 -0
  50. package/skills/criar-skill/SKILL.md +49 -0
  51. package/skills/depurar-de-verdade/LICENSE.txt +21 -0
  52. package/skills/depurar-de-verdade/SKILL.md +14 -5
  53. package/skills/design-de-verdade/LICENSE.txt +177 -0
  54. package/skills/design-de-verdade/SKILL.md +42 -0
  55. package/skills/documento-word/SKILL.md +57 -0
  56. package/skills/interface-revisada/SKILL.md +47 -0
  57. package/skills/me-ensina/LICENSE.txt +21 -0
  58. package/skills/me-ensina/SKILL.md +27 -0
  59. package/skills/me-entrevista/LICENSE.txt +21 -0
  60. package/skills/me-entrevista/SKILL.md +27 -0
  61. package/skills/motion-de-primeira/SKILL.md +1 -1
  62. package/skills/pdf-bonito/SKILL.md +48 -0
  63. package/skills/planilha-excel/SKILL.md +47 -0
  64. package/skills/react-sem-dor/SKILL.md +48 -0
  65. package/skills/revisao-antes-de-entregar/LICENSE.txt +21 -0
  66. package/skills/revisao-antes-de-entregar/SKILL.md +6 -1
  67. package/skills/site-com-motion/SKILL.md +39 -0
  68. package/skills/temas-prontos/LICENSE.txt +202 -0
  69. package/skills/temas-prontos/SKILL.md +50 -0
  70. package/skills/testar-o-site/LICENSE.txt +202 -0
  71. package/skills/testar-o-site/SKILL.md +46 -0
  72. package/skills/video-no-remotion/SKILL.md +48 -0
  73. package/studio/narrar.py +111 -10
  74. package/studio/rostos.py +52 -0
package/app/index.html CHANGED
@@ -8,138 +8,213 @@
8
8
  <link rel="icon" href="/icone.svg">
9
9
  </head>
10
10
  <!--
11
- A janela do PrimoCode (/rc).
11
+ A janela do PrimoCode — /rc, /ide e `primo ide` abrem esta mesma página.
12
12
 
13
- É a MESMA interface da página /code do Conecta Primo — de propósito. Quem
14
- usa o terminal, abre a janela e depois entra pelo navegador tem de
15
- reconhecer onde está no primeiro olhar: mesma barra lateral, mesmo botão de
16
- novo chat, mesmo prompt `❯`, mesmo mascote na tela vazia.
13
+ O layout é o de um app de mesa de agente: barra lateral com novo chat,
14
+ projetos e recentes; a pergunta no meio da tela vazia; o compositor embaixo
15
+ com projeto, anexo, permissão, esforço e voz; e um painel à direita com a
16
+ prévia do site e os arquivos (a IDE antiga, sem o editor).
17
17
 
18
- O que muda é de onde vem o conteúdo: aqui o histórico vem do servidor local
19
- (/api/conversas), que usa o lib/nuvem.js — a mesma cifra e a mesma coleção
20
- que a web lê direto do Firestore.
18
+ Os ícones são SVG em linha, de propósito: sem fonte de ícone, sem CDN, sem
19
+ pedir nada fora da máquina (regra do AGENTS.md). Cada um é um <symbol> aqui
20
+ em cima e um <use> onde aparece — o mesmo desenho não é copiado dez vezes.
21
21
  -->
22
22
  <body>
23
23
 
24
- <div class="tela">
25
- <aside class="lado" id="lado" aria-label="Conversas e ajustes">
26
- <div class="lado-topo">
27
- <div class="marca-linha">
28
- <span id="marcaTopo"></span>
29
- <span class="nome">PrimoCode</span>
30
- <span class="versao" id="versao"></span>
31
- </div>
32
- <button class="novo" id="btnNovo">
33
- <svg width="15" height="15" viewBox="0 0 24 24" aria-hidden="true">
34
- <path d="M12 5v14M5 12h14" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/>
35
- </svg>
36
- Novo chat
24
+ <svg width="0" height="0" style="position:absolute" aria-hidden="true">
25
+ <defs>
26
+ <symbol id="i-lado" viewBox="0 0 24 24"><rect x="3.5" y="4.5" width="17" height="15" rx="3"/><path d="M9.5 4.5v15"/></symbol>
27
+ <symbol id="i-painel" viewBox="0 0 24 24"><rect x="3.5" y="4.5" width="17" height="15" rx="3"/><path d="M14.5 4.5v15"/></symbol>
28
+ <symbol id="i-chev" viewBox="0 0 24 24"><path d="m7 10 5 5 5-5"/></symbol>
29
+ <symbol id="i-busca" viewBox="0 0 24 24"><circle cx="11" cy="11" r="6"/><path d="m20 20-4.6-4.6"/></symbol>
30
+ <symbol id="i-sino" viewBox="0 0 24 24"><path d="M6.5 16.5V11a5.5 5.5 0 0 1 11 0v5.5l1.5 1.5H5z"/><path d="M10 20.5a2 2 0 0 0 4 0"/></symbol>
31
+ <symbol id="i-editar" viewBox="0 0 24 24"><path d="M11 4.5H7a2.5 2.5 0 0 0-2.5 2.5v10A2.5 2.5 0 0 0 7 19.5h10a2.5 2.5 0 0 0 2.5-2.5v-4"/><path d="M17.8 3.9a1.8 1.8 0 0 1 2.5 2.5L12 14.7l-3.3.8.8-3.3z"/></symbol>
32
+ <symbol id="i-mais-circ" viewBox="0 0 24 24"><circle cx="12" cy="12" r="8"/><path d="M12 8.5v7M8.5 12h7"/></symbol>
33
+ <symbol id="i-terminal" viewBox="0 0 24 24"><rect x="3.5" y="4.5" width="17" height="15" rx="3"/><path d="m7.5 10 2.5 2-2.5 2M12.5 14.5h4"/></symbol>
34
+ <symbol id="i-olho" viewBox="0 0 24 24"><path d="M2.8 12S6 5.8 12 5.8 21.2 12 21.2 12 18 18.2 12 18.2 2.8 12 2.8 12z"/><circle cx="12" cy="12" r="2.6"/></symbol>
35
+ <symbol id="i-barra" viewBox="0 0 24 24"><circle cx="12" cy="12" r="8.5"/><path d="m14 7.5-4 9"/></symbol>
36
+ <symbol id="i-ajuda" viewBox="0 0 24 24"><circle cx="12" cy="12" r="8.5"/><path d="M9.7 9.6a2.4 2.4 0 1 1 3.3 2.2c-.6.3-1 .8-1 1.5v.4"/><circle cx="12" cy="16.6" r=".4"/></symbol>
37
+ <symbol id="i-pasta" viewBox="0 0 24 24"><path d="M3.5 7.5A2 2 0 0 1 5.5 5.5h3.8l2 2h7.2a2 2 0 0 1 2 2v7a2 2 0 0 1-2 2h-13a2 2 0 0 1-2-2z"/></symbol>
38
+ <symbol id="i-mais" viewBox="0 0 24 24"><path d="M12 5v14M5 12h14"/></symbol>
39
+ <symbol id="i-perigo" viewBox="0 0 24 24"><circle cx="12" cy="12" r="8.5"/><path d="M12 7.8v5.2"/><circle cx="12" cy="16.3" r=".5"/></symbol>
40
+ <symbol id="i-escudo" viewBox="0 0 24 24"><path d="M12 3.5 5.5 6v5.2c0 4.3 2.8 7.6 6.5 9.3 3.7-1.7 6.5-5 6.5-9.3V6z"/><path d="m9.2 12 2 2 3.8-4"/></symbol>
41
+ <symbol id="i-mao" viewBox="0 0 24 24"><path d="M12 3.5 5.5 6v5.2c0 4.3 2.8 7.6 6.5 9.3 3.7-1.7 6.5-5 6.5-9.3V6z"/><path d="M12 8.5v4"/><circle cx="12" cy="15.6" r=".5"/></symbol>
42
+ <symbol id="i-mic" viewBox="0 0 24 24"><rect x="9" y="3.5" width="6" height="11" rx="3"/><path d="M5.8 11.5a6.2 6.2 0 0 0 12.4 0M12 17.7v2.8"/></symbol>
43
+ <symbol id="i-seta" viewBox="0 0 24 24"><path d="M12 19V5.5M6.5 11 12 5.5l5.5 5.5"/></symbol>
44
+ <symbol id="i-fechar" viewBox="0 0 24 24"><path d="m6.5 6.5 11 11M17.5 6.5l-11 11"/></symbol>
45
+ <symbol id="i-recarregar" viewBox="0 0 24 24"><path d="M19 12a7 7 0 1 1-2.1-5"/><path d="M19.2 4.5v4h-4"/></symbol>
46
+ <symbol id="i-arquivo" viewBox="0 0 24 24"><path d="M7 3.5h6.5l4.5 4.5v11a1.5 1.5 0 0 1-1.5 1.5h-9.5A1.5 1.5 0 0 1 5.5 19V5A1.5 1.5 0 0 1 7 3.5z"/><path d="M13.5 3.5V8H18"/></symbol>
47
+ <symbol id="i-ler" viewBox="0 0 24 24"><path d="M7 3.5h6.5l4.5 4.5v11a1.5 1.5 0 0 1-1.5 1.5h-9.5A1.5 1.5 0 0 1 5.5 19V5A1.5 1.5 0 0 1 7 3.5z"/><path d="M8.5 12.5h7M8.5 16h5"/></symbol>
48
+ <symbol id="i-rodar" viewBox="0 0 24 24"><path d="m6 8.5 4 3.5-4 3.5M12 16h6"/></symbol>
49
+ <symbol id="i-web" viewBox="0 0 24 24"><circle cx="12" cy="12" r="8.5"/><path d="M3.5 12h17M12 3.5c2.4 2.4 3.4 5.3 3.4 8.5s-1 6.1-3.4 8.5c-2.4-2.4-3.4-5.3-3.4-8.5s1-6.1 3.4-8.5z"/></symbol>
50
+ <symbol id="i-computador" viewBox="0 0 24 24"><rect x="3.5" y="4.5" width="17" height="11.5" rx="2"/><path d="M9 20h6M12 16v4"/></symbol>
51
+ <symbol id="i-plano" viewBox="0 0 24 24"><path d="M9.5 7h10M9.5 12h10M9.5 17h10"/><path d="m4 7 1.2 1.2L7 6.3M4 12l1.2 1.2L7 11.3"/><circle cx="5.5" cy="17" r=".8"/></symbol>
52
+ <symbol id="i-agente" viewBox="0 0 24 24"><rect x="5" y="7.5" width="14" height="11" rx="3"/><path d="M12 7.5V4.5"/><circle cx="9.5" cy="12.5" r=".9"/><circle cx="14.5" cy="12.5" r=".9"/></symbol>
53
+ <symbol id="i-pare" viewBox="0 0 24 24"><rect x="7.5" y="7.5" width="9" height="9" rx="1.6" fill="currentColor" stroke="none"/></symbol>
54
+ </defs>
55
+ </svg>
56
+
57
+ <div class="app" id="app">
58
+ <aside class="lado" id="lado" aria-label="Conversas e projetos">
59
+ <div class="lado-barra">
60
+ <button class="icone-btn" id="btnLado" type="button" aria-label="Recolher a barra lateral" title="Barra lateral (Ctrl+B)">
61
+ <svg class="ic"><use href="#i-lado"/></svg>
37
62
  </button>
38
63
  </div>
39
64
 
40
- <div class="rotulo">Conversas</div>
41
- <div class="recentes" id="recentes">
42
- <div class="vazio-lista" id="listaVazia">
43
- As conversas aparecem aqui quando você entra na sua conta com <code>/login</code>.
65
+ <div class="lado-marca">
66
+ <button class="marca-btn" id="btnMarca" type="button" aria-haspopup="menu">
67
+ <span>PrimoCode</span><svg class="ic ic-p"><use href="#i-chev"/></svg>
68
+ </button>
69
+ <div class="lado-acoes">
70
+ <button class="icone-btn" id="btnBusca" type="button" aria-label="Buscar nos recentes" title="Buscar"><svg class="ic"><use href="#i-busca"/></svg></button>
71
+ <button class="icone-btn" id="btnAvisos" type="button" aria-pressed="false" aria-label="Avisar quando terminar" title="Avisar quando o Primo terminar"><svg class="ic"><use href="#i-sino"/></svg></button>
44
72
  </div>
45
73
  </div>
46
74
 
47
- <div class="lado-pe">
48
- <button class="pe-btn" id="btnConfig">
49
- <svg width="15" height="15" viewBox="0 0 24 24" aria-hidden="true">
50
- <circle cx="12" cy="12" r="3.1" fill="none" stroke="currentColor" stroke-width="1.9"/>
51
- <path d="M12 2.8v2.4M12 18.8v2.4M21.2 12h-2.4M5.2 12H2.8M18.5 5.5l-1.7 1.7M7.2 16.8l-1.7 1.7M18.5 18.5l-1.7-1.7M7.2 7.2 5.5 5.5"
52
- fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round"/>
53
- </svg>
54
- Configurações
55
- </button>
56
- <div class="chips">
57
- <span class="chip" id="pasta" title="pasta de trabalho"></span>
58
- <span class="chip" id="modo"></span>
59
- <span class="chip" id="esforco"></span>
75
+ <div class="busca" id="busca" hidden>
76
+ <input id="campoBusca" type="search" placeholder="Buscar nos recentes" autocomplete="off">
77
+ </div>
78
+
79
+ <nav class="nav" aria-label="Principal">
80
+ <div class="nav-linha">
81
+ <button class="nav-item ativo" id="btnNovo" type="button"><svg class="ic"><use href="#i-editar"/></svg>Novo chat</button>
82
+ <button class="icone-btn" id="btnNovoProjeto" type="button" aria-label="Novo projeto" title="Novo projeto em ~/primocode"><svg class="ic"><use href="#i-mais-circ"/></svg></button>
60
83
  </div>
84
+ <button class="nav-item" id="navTerminal" type="button" aria-pressed="false"><svg class="ic"><use href="#i-terminal"/></svg>Terminal</button>
85
+ <button class="nav-item" id="navPrevia" type="button"><svg class="ic"><use href="#i-olho"/></svg>Prévia do site</button>
86
+ <button class="nav-item" id="navComandos" type="button"><svg class="ic"><use href="#i-barra"/></svg>Comandos</button>
87
+ </nav>
88
+
89
+ <div class="rolagem-lado">
90
+ <div class="secao" id="secaoProjetos">Projetos</div>
91
+ <div class="lista" id="listaProjetos"><div class="vazio-lista">Nenhum projeto</div></div>
92
+
93
+ <div class="secao" id="secaoRecentes">Recentes</div>
94
+ <div class="lista" id="listaRecentes"><div class="vazio-lista">Nenhuma conversa ainda</div></div>
95
+ </div>
96
+
97
+ <div class="lado-pe">
98
+ <div class="usuario"><span class="avatar" id="avatar">PC</span><span class="nome-usuario" id="nomeUsuario">Você</span></div>
99
+ <button class="icone-btn" id="btnAjuda" type="button" aria-label="Atalhos e comandos" title="Atalhos e comandos"><svg class="ic"><use href="#i-ajuda"/></svg></button>
61
100
  </div>
62
101
  </aside>
63
102
 
64
- <main class="conversa">
103
+ <main class="centro">
104
+ <header class="topo">
105
+ <button class="icone-btn" id="btnLadoAbrir" type="button" aria-label="Abrir a barra lateral" title="Barra lateral (Ctrl+B)"><svg class="ic"><use href="#i-lado"/></svg></button>
106
+ <div class="topo-titulo" id="topoTitulo"></div>
107
+ <button class="icone-btn" id="btnPainel" type="button" aria-pressed="false" aria-label="Abrir a prévia e os arquivos" title="Prévia e arquivos"><svg class="ic"><use href="#i-painel"/></svg></button>
108
+ </header>
109
+
65
110
  <div class="rolo" id="rolo">
66
- <div class="vazio" id="vazio">
67
- <span id="marcaGrande"></span>
68
- <h1>O que a gente vai construir?</h1>
69
- <p>Escreva do jeito que você falaria. Ele lê a pasta, escreve o código,
70
- roda o que precisar e conta o que fez.</p>
71
- <div class="sugestoes">
72
- <button class="sugestao" data-manda="/all">o que ele sabe fazer</button>
73
- <button class="sugestao" data-manda="/project">meus projetos</button>
74
- <button class="sugestao" data-manda="/effort">esforço</button>
75
- <button class="sugestao" data-manda="/help">comandos</button>
76
- </div>
77
- </div>
78
- <div id="conversa" class="tira" hidden></div>
111
+ <section class="vazio" id="vazio">
112
+ <span class="mascote" id="mascote"></span>
113
+ <h1>O que vamos criar?</h1>
114
+ </section>
115
+ <div class="chat" id="chat" hidden aria-live="polite"></div>
79
116
  </div>
80
117
 
81
- <div class="rodape">
82
- <div id="pensando" hidden><span class="pulso"></span><span id="pensando-txt">trabalhando</span></div>
83
- <form id="forma" class="caixa">
84
- <div class="campo-volta">
85
- <span class="chevron">❯</span>
86
- <textarea id="campo" rows="1" placeholder="Peça alguma coisa…"
87
- autocomplete="off" spellcheck="false"></textarea>
118
+ <section class="terminal" id="terminal" hidden aria-label="Terminal">
119
+ <header class="terminal-topo">
120
+ <span><b>Terminal</b> <small>o mesmo que aparece no CLI</small></span>
121
+ <button class="icone-btn" id="fecharTerminal" type="button" aria-label="Voltar para o chat"><svg class="ic"><use href="#i-fechar"/></svg></button>
122
+ </header>
123
+ <pre class="terminal-saida" id="terminalSaida"></pre>
124
+ </section>
125
+
126
+ <footer class="rodape">
127
+ <div class="compositor-zona" id="zona">
128
+ <div class="projeto-barra">
129
+ <button class="projeto-btn" id="btnProjeto" type="button" aria-haspopup="menu">
130
+ <svg class="ic"><use href="#i-pasta"/></svg><span id="projetoNome">Escolher projeto</span>
131
+ </button>
88
132
  </div>
89
- <button type="submit" id="mandar" class="enviar" title="Enviar (Enter)" aria-label="Enviar">
90
- <svg width="17" height="17" viewBox="0 0 24 24" aria-hidden="true">
91
- <path d="M5 12h13M12.5 6l6 6-6 6" fill="none" stroke="currentColor"
92
- stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/>
93
- </svg>
94
- </button>
95
- <button type="button" id="parar" class="enviar parar" title="Parar (Esc)" hidden aria-label="Parar">
96
- <svg width="15" height="15" viewBox="0 0 24 24" aria-hidden="true"><rect x="7" y="7" width="10" height="10" rx="2" fill="currentColor"/></svg>
97
- </button>
98
- </form>
99
- <div class="dica" id="dica">Enter manda · Shift+Enter quebra linha · arraste um arquivo aqui</div>
100
- </div>
133
+ <form class="compositor" id="forma">
134
+ <div class="anexos" id="anexos" hidden></div>
135
+ <textarea id="campo" rows="1" placeholder="Peça qualquer coisa" autocomplete="off" spellcheck="false" aria-label="Pedido"></textarea>
136
+ <div class="controles">
137
+ <button class="icone-btn grande" id="btnAnexar" type="button" aria-label="Anexar arquivo" title="Anexar arquivo"><svg class="ic"><use href="#i-mais"/></svg></button>
138
+ <input id="arquivo" type="file" multiple hidden>
139
+ <button class="chip-perm" id="btnPermissao" type="button" aria-haspopup="menu" data-modo="auto">
140
+ <svg class="ic" id="permIcone"><use href="#i-escudo"/></svg><span id="permRotulo">Pergunta antes do perigoso</span>
141
+ </button>
142
+ <span class="espaco"></span>
143
+ <button class="seletor" id="btnEsforco" type="button" aria-haspopup="menu" title="Esforço do agente (/effort)">
144
+ <b id="esforcoRotulo">Equilíbrio</b><span id="esforcoNome">medium</span><svg class="ic ic-p"><use href="#i-chev"/></svg>
145
+ </button>
146
+ <button class="icone-btn" id="btnMic" type="button" aria-pressed="false" aria-label="Ligar o modo voz" title="Modo voz (/voice)"><svg class="ic"><use href="#i-mic"/></svg></button>
147
+ <button class="enviar" id="btnEnviar" type="submit" disabled aria-label="Enviar" title="Enviar (Enter)"><svg class="ic"><use href="#i-seta"/></svg></button>
148
+ </div>
149
+ </form>
150
+ </div>
151
+ </footer>
101
152
  </main>
102
- </div>
103
153
 
104
- <dialog id="dlgConfig">
105
- <div class="dlg-topo">
106
- <h2>Configurações</h2>
107
- <button class="copiar" id="fecharConfig">Fechar</button>
108
- </div>
109
- <div class="dlg-corpo">
110
- <div class="grupo">
111
- <h3>Tema</h3>
112
- <div class="opcoes" id="temas">
113
- <button class="opcao" data-tema="escuro">Escuro</button>
114
- <button class="opcao" data-tema="claro">Claro</button>
115
- <button class="opcao" data-tema="sistema">Do sistema</button>
154
+ <aside class="painel" id="painel" hidden aria-label="Prévia e arquivos">
155
+ <header class="painel-topo">
156
+ <div class="abas" role="tablist">
157
+ <button class="aba" id="abaPrevia" type="button" role="tab" aria-selected="true">Prévia</button>
158
+ <button class="aba" id="abaArquivos" type="button" role="tab" aria-selected="false">Arquivos</button>
159
+ </div>
160
+ <span class="espaco"></span>
161
+ <button class="icone-btn" id="btnRecarregar" type="button" aria-label="Recarregar" title="Recarregar"><svg class="ic"><use href="#i-recarregar"/></svg></button>
162
+ <button class="icone-btn" id="fecharPainel" type="button" aria-label="Fechar o painel"><svg class="ic"><use href="#i-fechar"/></svg></button>
163
+ </header>
164
+ <div class="painel-corpo" id="corpoPrevia">
165
+ <iframe class="previa" id="previa" title="Prévia do site"
166
+ sandbox="allow-scripts allow-forms allow-modals allow-popups allow-pointer-lock"></iframe>
167
+ <div class="painel-vazio" id="previaVazia" hidden>
168
+ <span class="mascote pequeno" id="mascotePainel"></span>
169
+ <p>Ainda não tem site nesta pasta.</p>
170
+ <p class="fraco">Peça "crie uma página de…" e ele aparece aqui, atualizando sozinho.</p>
116
171
  </div>
117
172
  </div>
118
- <div class="grupo">
119
- <h3>Cor</h3>
120
- <div class="cores" id="cores">
121
- <button class="cor" data-cor="ciano" style="background:#22d3ee" aria-label="Ciano"></button>
122
- <button class="cor" data-cor="verde" style="background:#34d399" aria-label="Verde"></button>
123
- <button class="cor" data-cor="roxo" style="background:#a78bfa" aria-label="Roxo"></button>
124
- <button class="cor" data-cor="ambar" style="background:#fbbf24" aria-label="Âmbar"></button>
125
- <button class="cor" data-cor="rosa" style="background:#fb7185" aria-label="Rosa"></button>
173
+ <div class="painel-corpo arquivos" id="corpoArquivos" hidden>
174
+ <div class="arvore" id="arvore" role="tree"></div>
175
+ <div class="visor">
176
+ <div class="visor-topo" id="visorNome">Escolha um arquivo</div>
177
+ <pre class="visor-texto" id="visor"></pre>
126
178
  </div>
127
179
  </div>
128
- <div class="grupo">
129
- <h3>Esta janela</h3>
130
- <div class="linha-info"><span>Pasta</span><b id="pastaConfig">—</b></div>
131
- <div class="linha-info"><span>Modo</span><b id="modoConfig">—</b></div>
132
- <div class="linha-info"><span>Esforço</span><b id="esforcoConfig">—</b></div>
133
- <p style="margin:10px 0 0;font-size:13px;color:var(--fraco)">
134
- Estes três se mudam no terminal: <code>/dir</code>, <code>/mode</code> e <code>/effort</code>.
135
- </p>
180
+ </aside>
181
+ </div>
182
+
183
+ <div class="menu" id="menu" role="menu" hidden></div>
184
+
185
+ <dialog class="dialogo" id="dlgAjuda" aria-labelledby="tituloAjuda">
186
+ <header class="dlg-topo">
187
+ <h2 id="tituloAjuda">Atalhos e comandos</h2>
188
+ <button class="icone-btn" id="fecharAjuda" type="button" aria-label="Fechar"><svg class="ic"><use href="#i-fechar"/></svg></button>
189
+ </header>
190
+ <div class="dlg-corpo">
191
+ <h3>Teclado</h3>
192
+ <dl class="atalhos">
193
+ <dt><kbd>Enter</kbd></dt><dd>manda o pedido</dd>
194
+ <dt><kbd>Shift</kbd> <kbd>Enter</kbd></dt><dd>quebra a linha</dd>
195
+ <dt><kbd>Esc</kbd> <kbd>Esc</kbd></dt><dd>para o que o Primo está fazendo</dd>
196
+ <dt><kbd>Ctrl</kbd> <kbd>B</kbd></dt><dd>mostra ou esconde a barra lateral</dd>
197
+ <dt><kbd>Ctrl</kbd> <kbd>J</kbd></dt><dd>abre o terminal</dd>
198
+ </dl>
199
+ <h3>Comandos</h3>
200
+ <p class="fraco">Digite no campo, como no terminal. Clique para usar.</p>
201
+ <div class="comandos" id="listaComandos">
202
+ <button type="button" data-cmd="/help">/help <span>todos os comandos</span></button>
203
+ <button type="button" data-cmd="/novo ">/novo <span>projeto novo, do zero</span></button>
204
+ <button type="button" data-cmd="/abrir">/abrir <span>abre o site do projeto</span></button>
205
+ <button type="button" data-cmd="/desfazer">/desfazer <span>volta o que ele mexeu</span></button>
206
+ <button type="button" data-cmd="/status">/status <span>conta e servidor</span></button>
207
+ <button type="button" data-cmd="/mascot">/mascot <span>troca o mascote</span></button>
208
+ <button type="button" data-cmd="/login">/login <span>entra na sua conta</span></button>
209
+ <button type="button" data-cmd="/doctor">/doctor <span>confere o que costuma dar problema</span></button>
136
210
  </div>
137
211
  </div>
138
212
  </dialog>
139
213
 
140
- <div id="alvo-solto"><div><strong>Solte aqui</strong><span>o caminho entra no pedido</span></div></div>
214
+ <div class="alvo-solto" id="alvoSolto"><div><strong>Solte aqui</strong><span>o arquivo entra como anexo do pedido</span></div></div>
141
215
 
142
216
  <script src="/primo-marca.js"></script>
217
+ <script src="/ansi.js"></script>
143
218
  <script src="/app.js"></script>
144
219
  </body>
145
220
  </html>
@@ -131,5 +131,62 @@
131
131
  return "data:image/svg+xml," + encodeURIComponent(logo({ tamanho: 32 }));
132
132
  }
133
133
 
134
- raiz.PrimoMarca = { svg: svg, logo: logo, favicon: favicon, MATRIZ: MATRIZ, CORPO: CORPO, DETALHE: DETALHE };
134
+ /* ── O MASCOTE EM TRAÇO ────────────────────────────────────────────────
135
+ A tela vazia da janela pede um ícone de LINHA, fino e neutro, no lugar
136
+ do bicho em pixel colorido: a janela é cinza e calma, e um mascote de
137
+ blocos cianos no meio dela gritava mais alto que a pergunta. Um traço
138
+ por mascote de lib/ui.js (MASCOTS), mesmo nome de id — quem escolheu a
139
+ coruja no /mascot vê a coruja aqui também. Os três de orelha (primo,
140
+ raposa, gato) têm o ❯_ do prompt no rosto: é a marca do PrimoCode.
141
+
142
+ Tudo em `currentColor`, então a cor vem do CSS e segue o tema. */
143
+ var CORPO_LINHA = "M14 16h20a5 5 0 0 1 5 5v12a5 5 0 0 1-5 5H14a5 5 0 0 1-5-5V21a5 5 0 0 1 5-5z";
144
+ var ROSTO_PROMPT = "M17 23.5l4 3.5-4 3.5M24 31h7";
145
+ var PES = "M17 38v4M31 38v4";
146
+ var LINHAS = {
147
+ primo: [CORPO_LINHA, ROSTO_PROMPT, PES, "M16 16v-6h4v6M28 16v-6h4v6", "M9 26H5M39 26h4"],
148
+ fox: [CORPO_LINHA, ROSTO_PROMPT, PES, "M12 17 9 6l9 10M36 17l3-11-9 10"],
149
+ cat: [CORPO_LINHA, ROSTO_PROMPT, PES, "M14 16l1-7 6 7M34 16l-1-7-6 7"],
150
+ robo: ["M13 14h22a4 4 0 0 1 4 4v14a4 4 0 0 1-4 4H13a4 4 0 0 1-4-4V18a4 4 0 0 1 4-4z",
151
+ "M24 14V9", "c24 6.5 2", "c18 24 2.5", "c30 24 2.5", "M19 31h10", "M16 36v5M32 36v5"],
152
+ coruja: ["M12 11l6 5h12l6-5v19a12 12 0 0 1-24 0z", "c19 24 4", "c29 24 4", "M24 29l-2 3h4z"],
153
+ dragao: [CORPO_LINHA, PES, "M13 16 9 8M35 16l4-8", "M9 22 3 18v10l6-2M39 22l6-4v10l-6-2",
154
+ "c18.5 25 1.5", "c29.5 25 1.5", "M21 31h6"],
155
+ fantasma: ["M12 40V22a12 12 0 0 1 24 0v18l-4-3-4 3-4-3-4 3-4-3z", "c20 23 2", "c28 23 2"],
156
+ capivara: ["M8 24c0-6 5-9 11-9h13c6 0 9 5 9 11v5a6 6 0 0 1-6 6H14a6 6 0 0 1-6-6z",
157
+ "M14 16l1-4 4 3", "c14.5 22.5 1.5", "M8 27h3", "M15 37v4M33 37v4"],
158
+ polvo: ["M14 27a10 10 0 1 1 20 0v1H14z", "c20 22 1.5", "c28 22 1.5",
159
+ "M15 28c-4 4-6 8-3 12M20 28c-1 5-1 9 1 12M28 28c1 5 1 9-1 12M33 28c4 4 6 8 3 12"],
160
+ pinguim: ["M24 7c-8 0-12 8-12 18s4 15 12 15 12-5 12-15S32 7 24 7z",
161
+ "M24 18c-4 0-6 5-6 11s2 8 6 8 6-2 6-8-2-11-6-11z", "c20.5 14 1.2", "c27.5 14 1.2",
162
+ "M22 17l2 2 2-2", "M18 41h5M25 41h5"],
163
+ };
164
+
165
+ /**
166
+ * O mascote em traço, para a tela vazia.
167
+ * @param {object} op
168
+ * @param {string} [op.mascote] id de lib/ui.js (primo, fox, cat, robo…); desconhecido = primo
169
+ * @param {number} [op.tamanho] lado em px
170
+ * @param {string} [op.rotulo] texto alternativo; vazio = decorativo
171
+ */
172
+ function linha(op) {
173
+ op = op || {};
174
+ var lado = op.tamanho || 48;
175
+ var partes = LINHAS[op.mascote] || LINHAS.primo;
176
+ var acessivel = op.rotulo
177
+ ? ' role="img" aria-label="' + String(op.rotulo).replace(/"/g, "&quot;") + '"'
178
+ : ' aria-hidden="true"';
179
+ var corpo = partes.map(function (d) {
180
+ if (d.charAt(0) === "c") { // "cX Y R" = círculo
181
+ var n = d.slice(1).split(" ");
182
+ return '<circle cx="' + n[0] + '" cy="' + n[1] + '" r="' + n[2] + '"/>';
183
+ }
184
+ return '<path d="' + d + '"/>';
185
+ }).join("");
186
+ return '<svg viewBox="0 0 48 48" width="' + lado + '" height="' + lado + '"' + acessivel
187
+ + ' fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round">'
188
+ + corpo + "</svg>";
189
+ }
190
+
191
+ raiz.PrimoMarca = { svg: svg, logo: logo, linha: linha, LINHAS: LINHAS, favicon: favicon, MATRIZ: MATRIZ, CORPO: CORPO, DETALHE: DETALHE };
135
192
  })(typeof window !== "undefined" ? window : globalThis);