primocode 9.8.0-beta.6 → 9.8.0-beta.8

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.
package/app/ide.css DELETED
@@ -1,345 +0,0 @@
1
- /* A PrimoCode IDE.
2
- *
3
- * "Um app ao invés de CLI, aí fica uma IDE e uma CLI."
4
- *
5
- * Esta folha vem DEPOIS do app.css e não define cor nenhuma: tokens, o
6
- * `.saida` com as cores ANSI, a bolha `.voce`, o campo com o `❯` e o botão
7
- * de enviar são os mesmos da janela do /rc. Aqui só mora a planta da IDE —
8
- * árvore à esquerda, editor e prévia no meio, chat à direita, terminal
9
- * embaixo — e o que só ela tem (abas, calha de linhas, o acender da árvore).
10
- */
11
-
12
- body.ide {
13
- --w-arvore: 236px;
14
- --w-chat: 368px;
15
- --h-term: 188px;
16
- --linha: 20px; /* altura de uma linha do editor — a calha depende dela */
17
- --codigo-tam: 13px;
18
- --editor-fundo: #0b121b;
19
- --realce: rgba(251, 191, 36, .16); /* amber: "o agente mexeu aqui" */
20
-
21
- display: grid;
22
- grid-template-columns: var(--w-arvore) minmax(0, 1fr) var(--w-chat);
23
- grid-template-rows: 44px minmax(0, 1fr) var(--h-term) 26px;
24
- grid-template-areas:
25
- "topo topo topo"
26
- "arvore centro chat"
27
- "arvore terminal chat"
28
- "barra barra barra";
29
- background-image: none;
30
- }
31
- html[data-tema="claro"] body.ide { --editor-fundo: #fbfdfe; --realce: rgba(217, 119, 6, .14); }
32
- body.ide.sem-terminal { grid-template-rows: 44px minmax(0, 1fr) 0 26px; }
33
- body.ide.sem-terminal .terminal { display: none; }
34
-
35
- /* ── cabeçalhos de painel ─────────────────────────────────────────────── */
36
- .painel-cabeca {
37
- display: flex; align-items: center; gap: 8px; flex: 0 0 auto;
38
- height: 34px; padding: 0 10px 0 14px;
39
- font-size: 11px; letter-spacing: .08em; text-transform: uppercase; color: var(--apagado);
40
- border-bottom: 1px solid var(--borda);
41
- }
42
- .painel-cabeca > span:first-child { font-weight: 600; }
43
- .icone-btn {
44
- margin-left: auto; display: grid; place-items: center; width: 26px; height: 26px;
45
- border: 0; border-radius: 7px; background: none; color: var(--apagado); cursor: pointer;
46
- }
47
- .icone-btn:hover { background: var(--alto); color: var(--texto); }
48
- :focus-visible { outline: 2px solid var(--azul); outline-offset: 1px; }
49
-
50
- /* ── topo ─────────────────────────────────────────────────────────────── */
51
- .topo {
52
- grid-area: topo; display: flex; align-items: center; gap: 18px; padding: 0 12px 0 14px;
53
- background: var(--barra); border-bottom: 1px solid var(--borda); min-width: 0;
54
- -webkit-app-region: drag;
55
- }
56
- .topo button, .topo a { -webkit-app-region: no-drag; }
57
- .topo-marca { display: flex; align-items: center; gap: 8px; flex: 0 0 auto; }
58
- .topo-marca .nome { font-weight: 620; letter-spacing: -.01em; }
59
- .selo {
60
- font-family: var(--mono); font-size: 10.5px; font-weight: 600; letter-spacing: .06em;
61
- color: var(--azul); border: 1px solid color-mix(in srgb, var(--azul) 45%, transparent);
62
- border-radius: 5px; padding: 1px 6px;
63
- }
64
- .topo-projeto {
65
- display: flex; align-items: center; gap: 7px; min-width: 0; color: var(--fraco); font-size: 13px;
66
- }
67
- .topo-projeto b { color: var(--texto); font-weight: 560; white-space: nowrap; }
68
- .topo-projeto .caminho {
69
- font-family: var(--mono); font-size: 11.5px; color: var(--apagado);
70
- white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
71
- }
72
- .topo-dir { margin-left: auto; display: flex; align-items: center; gap: 8px; flex: 0 0 auto; }
73
- .botao-topo {
74
- display: flex; align-items: center; gap: 6px; height: 28px; padding: 0 10px;
75
- font: inherit; font-size: 12.5px; color: var(--fraco); text-decoration: none; cursor: pointer;
76
- background: none; border: 1px solid var(--borda-viva); border-radius: 8px;
77
- }
78
- .botao-topo:hover { color: var(--texto); border-color: var(--azul); }
79
- .botao-topo[aria-pressed="true"] { color: var(--texto); background: var(--alto); }
80
-
81
- /* ── árvore ───────────────────────────────────────────────────────────── */
82
- .arvore {
83
- grid-area: arvore; display: flex; flex-direction: column; min-height: 0;
84
- background: var(--barra); border-right: 1px solid var(--borda);
85
- }
86
- .lista { flex: 1 1 0; overflow: auto; padding: 6px 6px 12px; font-size: 13px; }
87
- .lista::-webkit-scrollbar, .chat-rolo::-webkit-scrollbar, .terminal-saida::-webkit-scrollbar,
88
- #codigo::-webkit-scrollbar { width: 10px; height: 10px; }
89
- .lista::-webkit-scrollbar-thumb, .chat-rolo::-webkit-scrollbar-thumb, .terminal-saida::-webkit-scrollbar-thumb,
90
- #codigo::-webkit-scrollbar-thumb { background: var(--borda-viva); border-radius: 8px; border: 3px solid transparent; background-clip: padding-box; }
91
- #codigo::-webkit-scrollbar-corner { background: transparent; }
92
-
93
- .no {
94
- position: relative; display: flex; align-items: center; gap: 6px; width: 100%;
95
- height: 26px; padding: 0 8px 0 calc(8px + var(--nivel, 0) * 14px);
96
- border: 0; border-radius: 6px; background: none; color: var(--fraco);
97
- font: inherit; font-size: 13px; text-align: left; cursor: pointer; white-space: nowrap;
98
- }
99
- .no:hover { background: var(--alto); color: var(--texto); }
100
- .no[aria-selected="true"] { background: color-mix(in srgb, var(--azul) 13%, transparent); color: var(--texto); }
101
- .no .nome-no { overflow: hidden; text-overflow: ellipsis; }
102
- .seta {
103
- flex: 0 0 12px; display: grid; place-items: center; color: var(--apagado);
104
- transition: transform .14s ease;
105
- }
106
- .no[aria-expanded="true"] .seta { transform: rotate(90deg); }
107
- .no.pasta { color: var(--texto); }
108
-
109
- /* O tipo de arquivo numa etiqueta de duas letras, e não num ícone: quem está
110
- começando aprende a extensão lendo "js", "css", "md" — um desenhinho não
111
- ensina nada. */
112
- .tipo {
113
- flex: 0 0 22px; font-family: var(--mono); font-size: 9.5px; font-weight: 700;
114
- text-transform: uppercase; letter-spacing: .02em; text-align: center; color: var(--apagado);
115
- }
116
- .tipo.t-html { color: var(--alerta); }
117
- .tipo.t-css { color: var(--azul); }
118
- .tipo.t-js, .tipo.t-ts, .tipo.t-mjs { color: #fde68a; }
119
- .tipo.t-json { color: var(--fraco); }
120
- .tipo.t-img { color: #fda4af; }
121
- .tipo.t-py { color: #7dd3fc; }
122
- html[data-tema="claro"] .tipo.t-js, html[data-tema="claro"] .tipo.t-ts { color: #a16207; }
123
- html[data-tema="claro"] .tipo.t-img { color: #be123c; }
124
- html[data-tema="claro"] .tipo.t-py { color: #0369a1; }
125
-
126
- /* O acender de "o agente mexeu aqui". Âmbar porque é aviso — o cyan já é a
127
- cor do que está selecionado. A etiqueta "agora" garante que o estado não
128
- depende só de cor. */
129
- .no.mexido { background: var(--realce); color: var(--texto); }
130
- .no.mexido::after {
131
- content: "agora"; margin-left: auto; padding-left: 8px;
132
- font-family: var(--mono); font-size: 10px; color: var(--alerta);
133
- }
134
- @media (prefers-reduced-motion: no-preference) {
135
- .no.mexido { animation: acender 3.6s ease-out forwards; }
136
- @keyframes acender {
137
- 0% { background: color-mix(in srgb, var(--alerta) 34%, transparent); }
138
- 100% { background: var(--realce); }
139
- }
140
- }
141
- .arvore-pe {
142
- flex: 0 0 auto; padding: 8px 14px 10px; border-top: 1px solid var(--borda);
143
- font-size: 11.5px; color: var(--apagado); line-height: 1.45;
144
- }
145
- .arvore-pe:empty { display: none; }
146
-
147
- /* ── centro: abas ─────────────────────────────────────────────────────── */
148
- .centro { grid-area: centro; display: flex; flex-direction: column; min-width: 0; min-height: 0; background: var(--editor-fundo); }
149
- .abas {
150
- flex: 0 0 auto; display: flex; align-items: stretch; height: 36px;
151
- background: var(--barra); border-bottom: 1px solid var(--borda);
152
- }
153
- .abas-rolo { flex: 1 1 auto; display: flex; overflow-x: auto; scrollbar-width: none; }
154
- .abas-rolo::-webkit-scrollbar { display: none; }
155
- .aba {
156
- position: relative; flex: 0 0 auto; display: flex; align-items: center; gap: 7px;
157
- max-width: 220px; padding: 0 8px 0 12px; cursor: pointer;
158
- border: 0; border-right: 1px solid var(--borda); background: none;
159
- color: var(--apagado); font: inherit; font-size: 12.5px;
160
- }
161
- .aba:hover { color: var(--texto); }
162
- .aba[aria-selected="true"] { background: var(--editor-fundo); color: var(--texto); }
163
- .aba[aria-selected="true"]::before {
164
- content: ""; position: absolute; left: 0; right: 0; top: 0; height: 2px; background: var(--azul);
165
- }
166
- .aba .nome-aba { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
167
- .aba .fechar {
168
- display: grid; place-items: center; width: 18px; height: 18px; border-radius: 5px;
169
- color: var(--apagado); font-size: 14px; line-height: 1;
170
- }
171
- .aba .fechar:hover { background: var(--alto); color: var(--texto); }
172
- /* Não salvo: a bolinha no lugar do ×, como em todo editor — e o título da
173
- aba diz "não salvo" para quem não conhece a convenção. */
174
- .aba.sujo .fechar::before { content: "●"; font-size: 10px; color: var(--alerta); }
175
- .aba.sujo .fechar > span { display: none; }
176
- .aba.sujo:hover .fechar::before { display: none; }
177
- .aba.sujo:hover .fechar > span { display: inline; }
178
-
179
- .aba-previa {
180
- flex: 0 0 auto; display: flex; align-items: center; gap: 7px; margin: 5px 6px; padding: 0 12px;
181
- border: 1px solid var(--borda-viva); border-radius: 8px; background: none; cursor: pointer;
182
- color: var(--fraco); font: inherit; font-size: 12.5px;
183
- }
184
- .aba-previa:hover { color: var(--texto); border-color: var(--azul); }
185
- .aba-previa[aria-pressed="true"] {
186
- color: var(--azul); border-color: color-mix(in srgb, var(--azul) 55%, transparent);
187
- background: color-mix(in srgb, var(--azul) 9%, transparent);
188
- }
189
-
190
- /* ── centro: editor + prévia lado a lado ──────────────────────────────── */
191
- .palco { flex: 1 1 0; display: flex; min-height: 0; }
192
- .area-editor { position: relative; flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; }
193
- .area-previa {
194
- flex: 1 1 0; min-width: 0; display: flex; flex-direction: column;
195
- border-left: 1px solid var(--borda); background: var(--painel);
196
- }
197
- /* Janela estreita: editor e prévia não cabem juntos com a árvore e o chat.
198
- A prévia passa a ocupar o palco inteiro e o botão dela vira a troca. */
199
- @media (max-width: 1240px) {
200
- .centro.com-previa .area-editor { display: none; }
201
- .area-previa { border-left: 0; }
202
- }
203
-
204
- .editor { flex: 1 1 0; display: flex; min-height: 0; font-family: var(--mono); font-size: var(--codigo-tam); }
205
- .calha {
206
- flex: 0 0 auto; min-width: 48px; padding: 10px 12px 10px 10px; overflow: hidden;
207
- text-align: right; color: var(--apagado); opacity: .7; line-height: var(--linha);
208
- font-variant-numeric: tabular-nums; user-select: none; white-space: pre;
209
- border-right: 1px solid var(--borda);
210
- }
211
- .calha .viva { color: var(--texto); opacity: 1; }
212
- .texto-volta { position: relative; flex: 1 1 0; min-width: 0; }
213
- .linha-atual {
214
- position: absolute; left: 0; right: 0; top: 10px; height: var(--linha);
215
- background: color-mix(in srgb, var(--azul) 6%, transparent); pointer-events: none;
216
- }
217
- #codigo {
218
- position: absolute; inset: 0; width: 100%; height: 100%;
219
- padding: 10px 16px; margin: 0; border: 0; outline: none; resize: none;
220
- background: transparent; color: var(--texto); caret-color: var(--azul);
221
- font: inherit; line-height: var(--linha); tab-size: 2; white-space: pre; overflow: auto;
222
- }
223
- #codigo::selection { background: color-mix(in srgb, var(--azul) 26%, transparent); }
224
-
225
- .faixa {
226
- flex: 0 0 auto; display: flex; align-items: center; gap: 10px; padding: 8px 14px;
227
- font-size: 12.5px; color: var(--texto);
228
- background: color-mix(in srgb, var(--alerta) 12%, transparent);
229
- border-bottom: 1px solid color-mix(in srgb, var(--alerta) 32%, transparent);
230
- }
231
- .faixa > span { flex: 1 1 auto; }
232
- .faixa > span::before { content: "⚠ "; color: var(--alerta); }
233
- .faixa-btn {
234
- font: inherit; font-size: 12px; padding: 4px 10px; border-radius: 7px; cursor: pointer;
235
- border: 1px solid var(--borda-viva); background: var(--painel); color: var(--texto);
236
- }
237
- .faixa-btn:hover { border-color: var(--alerta); }
238
-
239
- .aviso-arquivo {
240
- flex: 1 1 0; display: flex; flex-direction: column; align-items: center; justify-content: center;
241
- gap: 14px; padding: 24px; color: var(--fraco); text-align: center;
242
- }
243
- .aviso-arquivo img {
244
- max-width: min(100%, 560px); max-height: 60%; border-radius: 8px; border: 1px solid var(--borda);
245
- background: repeating-conic-gradient(var(--alto) 0 25%, transparent 0 50%) 0 0 / 16px 16px;
246
- }
247
- .aviso-arquivo p { margin: 0; max-width: 46ch; line-height: 1.55; }
248
-
249
- .boas-vindas {
250
- flex: 1 1 0; display: flex; flex-direction: column; align-items: center; justify-content: center;
251
- gap: 14px; padding: 28px; text-align: center;
252
- }
253
- .boas-vindas h1 { margin: 6px 0 0; font-size: 22px; font-weight: 620; letter-spacing: -.02em; text-wrap: balance; }
254
- .boas-vindas p { margin: 0; max-width: 50ch; color: var(--fraco); line-height: 1.6; }
255
- .atalhos { display: flex; flex-wrap: wrap; justify-content: center; gap: 10px 22px; margin: 10px 0 0; }
256
- .atalhos > div { display: flex; align-items: center; gap: 8px; }
257
- .atalhos dt { display: flex; gap: 3px; }
258
- .atalhos dd { margin: 0; font-size: 12.5px; color: var(--apagado); }
259
- kbd {
260
- font-family: var(--mono); font-size: 11px; color: var(--texto);
261
- padding: 1px 6px; border-radius: 5px; border: 1px solid var(--borda-viva);
262
- border-bottom-width: 2px; background: var(--alto);
263
- }
264
-
265
- .previa-barra {
266
- flex: 0 0 auto; display: flex; align-items: center; gap: 8px; height: 34px; padding: 0 8px 0 12px;
267
- border-bottom: 1px solid var(--borda); background: var(--barra); font-size: 12px;
268
- }
269
- .bolinha { width: 8px; height: 8px; border-radius: 50%; background: var(--azul); flex: 0 0 auto; }
270
- .previa-endereco {
271
- font-family: var(--mono); color: var(--fraco); padding: 3px 10px; border-radius: 6px;
272
- background: var(--painel); border: 1px solid var(--borda);
273
- min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
274
- }
275
- .previa-estado { font-family: var(--mono); font-size: 11px; color: var(--apagado); white-space: nowrap; }
276
- .previa-estado.fresco { color: var(--azul); }
277
- #previa { flex: 1 1 0; width: 100%; border: 0; background: #fff; }
278
- .previa-vazia { flex: 1 1 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px; color: var(--fraco); padding: 24px; text-align: center; }
279
- .previa-vazia p { margin: 0; line-height: 1.8; }
280
-
281
- /* ── terminal ─────────────────────────────────────────────────────────── */
282
- .terminal {
283
- grid-area: terminal; display: flex; flex-direction: column; min-height: 0; min-width: 0;
284
- border-top: 1px solid var(--borda); background: var(--fundo);
285
- }
286
- .terminal-dica { text-transform: none; letter-spacing: 0; font-size: 11.5px; color: var(--apagado); opacity: .8; }
287
- .terminal-saida {
288
- flex: 1 1 0; overflow: auto; padding: 8px 14px 12px; font-size: 12px; line-height: 1.55;
289
- }
290
-
291
- /* ── chat ─────────────────────────────────────────────────────────────── */
292
- .chat {
293
- grid-area: chat; display: flex; flex-direction: column; min-height: 0; min-width: 0;
294
- border-left: 1px solid var(--borda); background: var(--painel);
295
- }
296
- .chat-estado {
297
- margin-left: auto; display: none; align-items: center; gap: 7px;
298
- text-transform: none; letter-spacing: 0; font-family: var(--mono); font-size: 11.5px; color: var(--azul);
299
- }
300
- body.ocupado .chat-estado { display: flex; }
301
- .chat-rolo { flex: 1 1 0; overflow-y: auto; }
302
- .chat-vazio { padding: 28px 18px 8px; text-align: center; color: var(--fraco); }
303
- .chat-vazio p { margin: 0 0 12px; }
304
- .chat-vazio .sugestoes { display: flex; flex-direction: column; align-items: stretch; gap: 7px; }
305
- .chat-tira { padding: 4px 14px 18px; }
306
- .chat-tira .voce { margin: 16px 0 10px; }
307
- .chat-tira .voce > div { max-width: 92%; font-size: 13.5px; }
308
- .chat-tira .saida { font-size: 12.2px; }
309
- .chat-tira .aviso-erro { font-size: 13px; }
310
-
311
- .chat-caixa { flex: 0 0 auto; display: flex; flex-direction: column; gap: 7px; padding: 10px 12px 12px; border-top: 1px solid var(--borda); }
312
- .chat-caixa .campo-volta { align-items: flex-end; padding: 7px 7px 7px 11px; }
313
- .chat-caixa .enviar { width: 30px; height: 30px; border-radius: 8px; }
314
- .anexo {
315
- display: flex; align-items: center; gap: 7px; font-size: 12px; color: var(--fraco); cursor: pointer;
316
- min-width: 0;
317
- }
318
- .anexo input { accent-color: var(--azul); margin: 0; }
319
- .anexo span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
320
- .anexo b { font-family: var(--mono); font-weight: 500; color: var(--texto); }
321
-
322
- /* ── barra de status ──────────────────────────────────────────────────── */
323
- .barra {
324
- grid-area: barra; display: flex; align-items: center; gap: 16px; padding: 0 12px;
325
- font-family: var(--mono); font-size: 11.5px; color: var(--apagado);
326
- background: var(--barra); border-top: 1px solid var(--borda); white-space: nowrap; min-width: 0;
327
- }
328
- .barra-espaco { flex: 1 1 auto; }
329
- .barra-item { display: flex; align-items: center; gap: 6px; font-variant-numeric: tabular-nums; }
330
- .barra-item:empty { display: none; }
331
- .ponto { width: 7px; height: 7px; border-radius: 50%; background: var(--apagado); }
332
- body.ocupado .ponto { background: var(--azul); }
333
- .barra-aviso { color: var(--alerta); overflow: hidden; text-overflow: ellipsis; min-width: 0; }
334
- .barra-salvo.sujo { color: var(--alerta); }
335
-
336
- /* ── janelas menores ──────────────────────────────────────────────────── */
337
- @media (max-width: 1100px) {
338
- body.ide { --w-arvore: 200px; --w-chat: 316px; --h-term: 160px; }
339
- .topo-projeto .caminho, .terminal-dica, #esforco { display: none; }
340
- }
341
- @media (max-width: 760px) {
342
- /* Abaixo disso não é mais IDE: é o chat. A janela do /rc faz isso melhor. */
343
- body.ide { grid-template-columns: 0 minmax(0, 1fr) 0; }
344
- .arvore, .chat { display: none; }
345
- }
package/app/ide.html DELETED
@@ -1,183 +0,0 @@
1
- <!doctype html>
2
- <html lang="pt-BR" data-tema="escuro">
3
- <head>
4
- <meta charset="utf-8">
5
- <meta name="viewport" content="width=device-width,initial-scale=1">
6
- <title>PrimoCode IDE</title>
7
- <link rel="stylesheet" href="/app.css">
8
- <link rel="stylesheet" href="/ide.css">
9
- <link rel="icon" href="/icone.svg">
10
- </head>
11
- <!--
12
- A PrimoCode IDE (/ide, ou `primo ide` no terminal).
13
-
14
- "Um app ao invés de CLI, aí fica uma IDE e uma CLI."
15
-
16
- Mesmo servidor, mesma chave e mesmo fluxo da janela do /rc (lib/app.js);
17
- o que ela tem a mais mora em lib/ide.js. As cores vêm do app.css — a IDE
18
- não define paleta própria, para as duas janelas serem o mesmo produto.
19
-
20
- Sem CDN de propósito: nada de CodeMirror nem Monaco. A regra da casa é "sem
21
- dependência externa", e um editor que some quando a internet cai é o pior
22
- editor para quem está começando. O editor abaixo é um <textarea> com número
23
- de linha, Tab e Ctrl+S — leve, e sempre funciona.
24
- -->
25
- <body class="ide">
26
-
27
- <header class="topo">
28
- <div class="topo-marca">
29
- <span id="marcaTopo"></span>
30
- <span class="nome">PrimoCode</span>
31
- <span class="selo">IDE</span>
32
- </div>
33
- <div class="topo-projeto" title="pasta do projeto">
34
- <svg width="14" height="14" viewBox="0 0 24 24" aria-hidden="true"><path d="M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"/></svg>
35
- <b id="nomeProjeto">—</b>
36
- <span id="pastaProjeto" class="caminho"></span>
37
- </div>
38
- <div class="topo-dir">
39
- <span class="chip" id="modo"></span>
40
- <span class="chip" id="esforco"></span>
41
- <button class="botao-topo" id="btnTerminal" aria-pressed="true" title="Mostrar ou esconder o terminal (Ctrl+J)">
42
- <svg width="14" height="14" viewBox="0 0 24 24" aria-hidden="true"><rect x="3" y="4" width="18" height="16" rx="2.5" fill="none" stroke="currentColor" stroke-width="1.8"/><path d="m7 9 3 3-3 3M12.5 15H17" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg>
43
- Terminal
44
- </button>
45
- <a class="botao-topo" id="linkChat" href="/" title="Abrir a janela só de chat">Só o chat</a>
46
- </div>
47
- </header>
48
-
49
- <aside class="arvore" aria-label="Arquivos do projeto">
50
- <div class="painel-cabeca">
51
- <span>Arquivos</span>
52
- <button class="icone-btn" id="btnRecarregar" title="Recarregar a lista" aria-label="Recarregar a lista">
53
- <svg width="14" height="14" viewBox="0 0 24 24" aria-hidden="true"><path d="M20 11a8 8 0 1 0-2.3 5.7M20 4v7h-7" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"/></svg>
54
- </button>
55
- </div>
56
- <div class="lista" id="lista" role="tree"></div>
57
- <div class="arvore-pe" id="arvorePe"></div>
58
- </aside>
59
-
60
- <main class="centro" id="centro">
61
- <div class="abas" role="tablist" id="abas">
62
- <div class="abas-rolo" id="abasRolo"></div>
63
- <button class="aba-previa" id="btnPrevia" aria-pressed="false" title="Mostrar a prévia do site (atualiza sozinha)">
64
- <svg width="14" height="14" viewBox="0 0 24 24" aria-hidden="true"><path d="M2.5 12S6 5.5 12 5.5 21.5 12 21.5 12 18 18.5 12 18.5 2.5 12 2.5 12Z" fill="none" stroke="currentColor" stroke-width="1.8"/><circle cx="12" cy="12" r="2.8" fill="none" stroke="currentColor" stroke-width="1.8"/></svg>
65
- Prévia
66
- </button>
67
- </div>
68
-
69
- <div class="palco">
70
- <section class="area-editor" id="areaEditor">
71
- <div class="faixa" id="faixa" hidden>
72
- <span id="faixaTexto"></span>
73
- <button class="faixa-btn" id="faixaRecarregar">Ver a versão do disco</button>
74
- <button class="faixa-btn" id="faixaManter">Manter a minha</button>
75
- </div>
76
-
77
- <div class="editor" id="editor" hidden>
78
- <div class="calha" id="calha" aria-hidden="true"></div>
79
- <div class="texto-volta">
80
- <div class="linha-atual" id="linhaAtual" aria-hidden="true"></div>
81
- <textarea id="codigo" spellcheck="false" autocomplete="off" autocapitalize="off"
82
- wrap="off" aria-label="Editor de código"></textarea>
83
- </div>
84
- </div>
85
-
86
- <div class="aviso-arquivo" id="avisoArquivo" hidden>
87
- <img id="avisoImagem" alt="" hidden>
88
- <p id="avisoTexto"></p>
89
- </div>
90
-
91
- <div class="boas-vindas" id="boasVindas">
92
- <span id="marcaGrande"></span>
93
- <h1>Seu projeto, o Primo e o site, lado a lado.</h1>
94
- <p>Abra um arquivo na lista à esquerda, ou peça ao Primo no chat. Quando ele
95
- mexer num arquivo, a lista acende e a prévia se atualiza sozinha.</p>
96
- <dl class="atalhos">
97
- <div><dt><kbd>Ctrl</kbd> <kbd>S</kbd></dt><dd>salva o arquivo</dd></div>
98
- <div><dt><kbd>Tab</kbd></dt><dd>indenta a linha</dd></div>
99
- <div><dt><kbd>Ctrl</kbd> <kbd>J</kbd></dt><dd>mostra o terminal</dd></div>
100
- </dl>
101
- </div>
102
- </section>
103
-
104
- <section class="area-previa" id="areaPrevia" hidden>
105
- <div class="previa-barra">
106
- <span class="bolinha" aria-hidden="true"></span>
107
- <span class="previa-endereco" id="previaEndereco">index.html</span>
108
- <span class="previa-estado" id="previaEstado"></span>
109
- <button class="icone-btn" id="btnRecarregarPrevia" title="Recarregar a prévia" aria-label="Recarregar a prévia">
110
- <svg width="14" height="14" viewBox="0 0 24 24" aria-hidden="true"><path d="M20 11a8 8 0 1 0-2.3 5.7M20 4v7h-7" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"/></svg>
111
- </button>
112
- </div>
113
- <!-- Sandbox SEM a mesma origem da IDE: ver lib/ide.js. O código da
114
- prévia não pode herdar a chave e dar ordens ao agente. -->
115
- <iframe id="previa" title="Prévia do site"
116
- sandbox="allow-scripts allow-forms allow-modals allow-popups allow-pointer-lock"></iframe>
117
- <div class="previa-vazia" id="previaVazia" hidden>
118
- <p><b>Ainda não há um index.html neste projeto.</b></p>
119
- <p>Peça ao Primo: <button class="sugestao" data-manda="crie uma página inicial simples em index.html">crie uma página inicial</button></p>
120
- </div>
121
- </section>
122
- </div>
123
- </main>
124
-
125
- <section class="terminal" id="terminal" aria-label="Terminal">
126
- <div class="painel-cabeca">
127
- <span>Terminal</span>
128
- <span class="terminal-dica">a mesma saída do PrimoCode no terminal</span>
129
- <button class="icone-btn" id="btnFecharTerminal" title="Esconder o terminal" aria-label="Esconder o terminal">
130
- <svg width="14" height="14" viewBox="0 0 24 24" aria-hidden="true"><path d="m6 9 6 6 6-6" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>
131
- </button>
132
- </div>
133
- <pre class="saida terminal-saida" id="terminalSaida"></pre>
134
- </section>
135
-
136
- <aside class="chat" aria-label="Chat com o Primo">
137
- <div class="painel-cabeca">
138
- <span>Primo</span>
139
- <span class="chat-estado" id="chatEstado"><span class="pulso"></span> trabalhando</span>
140
- </div>
141
- <div class="chat-rolo" id="chatRolo">
142
- <div class="chat-vazio" id="chatVazio">
143
- <p>Peça do jeito que você falaria.</p>
144
- <div class="sugestoes">
145
- <button class="sugestao" data-manda="explica o que este projeto faz">explica este projeto</button>
146
- <button class="sugestao" data-manda="crie um site de uma página sobre mim, em index.html">crie um site sobre mim</button>
147
- <button class="sugestao" data-manda="/help">comandos</button>
148
- </div>
149
- </div>
150
- <div class="chat-tira" id="chatTira"></div>
151
- </div>
152
- <form class="chat-caixa" id="forma">
153
- <label class="anexo" id="anexo" hidden>
154
- <input type="checkbox" id="anexar" checked>
155
- <span>incluir <b id="anexoNome"></b></span>
156
- </label>
157
- <div class="campo-volta">
158
- <span class="chevron">❯</span>
159
- <textarea id="campo" rows="1" placeholder="Peça alguma coisa…" autocomplete="off" spellcheck="false"></textarea>
160
- <button type="submit" id="mandar" class="enviar" title="Enviar (Enter)" aria-label="Enviar">
161
- <svg width="16" height="16" viewBox="0 0 24 24" aria-hidden="true"><path d="M5 12h13M12.5 6l6 6-6 6" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></svg>
162
- </button>
163
- <button type="button" id="parar" class="enviar parar" title="Parar (Esc)" aria-label="Parar" hidden>
164
- <svg width="14" height="14" viewBox="0 0 24 24" aria-hidden="true"><rect x="7" y="7" width="10" height="10" rx="2" fill="currentColor"/></svg>
165
- </button>
166
- </div>
167
- </form>
168
- </aside>
169
-
170
- <footer class="barra">
171
- <span class="barra-item" id="barraAgente"><span class="ponto"></span> <span id="barraAgenteTxt">Primo pronto</span></span>
172
- <span class="barra-item barra-aviso" id="barraAviso"></span>
173
- <span class="barra-espaco"></span>
174
- <span class="barra-item" id="barraPosicao"></span>
175
- <span class="barra-item" id="barraLingua"></span>
176
- <span class="barra-item" id="barraSalvo"></span>
177
- </footer>
178
-
179
- <script src="/primo-marca.js"></script>
180
- <script src="/ansi.js"></script>
181
- <script src="/ide.js"></script>
182
- </body>
183
- </html>