sagadeck 1.2.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 (233) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +305 -0
  3. package/SKILL.md +148 -0
  4. package/bin/sagadeck.js +511 -0
  5. package/docs/ANDAMENTO.md +1255 -0
  6. package/docs/EXPERIENCIAS.md +39 -0
  7. package/docs/PLANO-EXPERIENCIAS.md +39 -0
  8. package/docs/PLANO-TESTE-AULAS-TECNICAS.md +44 -0
  9. package/docs/PLANO-TESTE-DESINFORMACAO.md +38 -0
  10. package/docs/REFERENCIA.md +1131 -0
  11. package/package.json +59 -0
  12. package/src/adaptive-layouts.js +18 -0
  13. package/src/ai/art-direction.js +8 -0
  14. package/src/ai/commands.js +130 -0
  15. package/src/ai/context.js +245 -0
  16. package/src/ai/deck-ai.js +1135 -0
  17. package/src/ai/directions.js +74 -0
  18. package/src/ai/document-materials.js +49 -0
  19. package/src/ai/document-visuals.js +215 -0
  20. package/src/ai/evaluation.js +31 -0
  21. package/src/ai/ground.js +55 -0
  22. package/src/ai/llm.js +292 -0
  23. package/src/ai/quality.js +51 -0
  24. package/src/ai/relay.js +45 -0
  25. package/src/ai/staged-generation.js +24 -0
  26. package/src/ai/transform.js +858 -0
  27. package/src/ai/usage.js +17 -0
  28. package/src/ai/variety.js +80 -0
  29. package/src/ai/video-frames.js +24 -0
  30. package/src/ai/video-generation.js +126 -0
  31. package/src/ai/web-operation.js +31 -0
  32. package/src/algo-catalog.js +153 -0
  33. package/src/algo-trace.js +139 -0
  34. package/src/api-client.js +514 -0
  35. package/src/api-collections.js +14 -0
  36. package/src/api-demo.js +222 -0
  37. package/src/aspect.js +40 -0
  38. package/src/build.js +323 -0
  39. package/src/carousel.js +56 -0
  40. package/src/chrome.js +65 -0
  41. package/src/code-highlight.js +68 -0
  42. package/src/code-lab-browser.js +22 -0
  43. package/src/code-lab.js +3 -0
  44. package/src/code-language.js +52 -0
  45. package/src/csv.js +74 -0
  46. package/src/decision-lab.js +20 -0
  47. package/src/deck-file.js +119 -0
  48. package/src/diagram/napkin-examples.js +13 -0
  49. package/src/diagram/napkin.js +539 -0
  50. package/src/docx.js +128 -0
  51. package/src/dynamics/git-sim.js +200 -0
  52. package/src/dynamics/layouts.js +112 -0
  53. package/src/elements.js +554 -0
  54. package/src/experiences.js +124 -0
  55. package/src/exploration.js +31 -0
  56. package/src/export/browser.js +53 -0
  57. package/src/export/estudo.js +67 -0
  58. package/src/export/pptx.js +475 -0
  59. package/src/export/roteiro.js +40 -0
  60. package/src/export/shots.js +182 -0
  61. package/src/figures/charts.js +383 -0
  62. package/src/figures/diagrams.js +117 -0
  63. package/src/figures/icons.js +166 -0
  64. package/src/figures/material-pictos.js +20 -0
  65. package/src/figures/pictos.js +255 -0
  66. package/src/figures/points.js +106 -0
  67. package/src/figures/qr.js +29 -0
  68. package/src/figures/ufmap.js +48 -0
  69. package/src/fiscal/autofix.js +377 -0
  70. package/src/fiscal/normalize.js +115 -0
  71. package/src/graph-lab.js +24 -0
  72. package/src/hologram.js +30 -0
  73. package/src/identity.js +86 -0
  74. package/src/import/crop.js +59 -0
  75. package/src/import/index.js +132 -0
  76. package/src/import/legacy-word.js +42 -0
  77. package/src/import/merge.js +45 -0
  78. package/src/import/office.js +123 -0
  79. package/src/import/omml.js +69 -0
  80. package/src/import/pdf-render.js +56 -0
  81. package/src/import/pptx.js +701 -0
  82. package/src/import/xml.js +42 -0
  83. package/src/infographic.js +401 -0
  84. package/src/layouts.js +723 -0
  85. package/src/lessons.js +171 -0
  86. package/src/library.js +399 -0
  87. package/src/markup.js +116 -0
  88. package/src/master.js +214 -0
  89. package/src/mcp/server.js +371 -0
  90. package/src/meeting.js +42 -0
  91. package/src/motion.js +56 -0
  92. package/src/package.js +116 -0
  93. package/src/playground.js +19 -0
  94. package/src/portal-scene.js +20 -0
  95. package/src/preferences.js +61 -0
  96. package/src/protect.js +51 -0
  97. package/src/purpose.js +24 -0
  98. package/src/pytrace.js +1092 -0
  99. package/src/research/duckduckgo.js +73 -0
  100. package/src/research/research.js +202 -0
  101. package/src/research/svg-image.js +17 -0
  102. package/src/research/visuals.js +52 -0
  103. package/src/runtime/api-collection-ui.js +5 -0
  104. package/src/runtime/api-collections.js +28 -0
  105. package/src/runtime/api-core.js +530 -0
  106. package/src/runtime/api-ui.js +966 -0
  107. package/src/runtime/base.css +1774 -0
  108. package/src/runtime/calc.js +139 -0
  109. package/src/runtime/code-lab.js +371 -0
  110. package/src/runtime/decision-lab.js +49 -0
  111. package/src/runtime/diagram.js +341 -0
  112. package/src/runtime/fit.js +268 -0
  113. package/src/runtime/fonts/caveat.css +2 -0
  114. package/src/runtime/fonts/comic-neue.css +3 -0
  115. package/src/runtime/fonts/fredoka.css +2 -0
  116. package/src/runtime/fonts/index.json +10 -0
  117. package/src/runtime/fonts/inter.css +2 -0
  118. package/src/runtime/fonts/patrick-hand.css +2 -0
  119. package/src/runtime/fonts/plus-jakarta-sans.css +2 -0
  120. package/src/runtime/fonts/press-start-2p.css +2 -0
  121. package/src/runtime/fonts/vt323.css +2 -0
  122. package/src/runtime/formula.js +148 -0
  123. package/src/runtime/graph-lab.js +72 -0
  124. package/src/runtime/meeting.css +7 -0
  125. package/src/runtime/meeting.js +10 -0
  126. package/src/runtime/motion.js +15 -0
  127. package/src/runtime/playground.js +11 -0
  128. package/src/runtime/points.js +19 -0
  129. package/src/runtime/portal-scene.css +6 -0
  130. package/src/runtime/portal-scene.js +22 -0
  131. package/src/runtime/runtime.js +827 -0
  132. package/src/runtime/science.js +89 -0
  133. package/src/runtime/skins/aluminio.css +31 -0
  134. package/src/runtime/skins/arcade.css +25 -0
  135. package/src/runtime/skins/aurora.css +17 -0
  136. package/src/runtime/skins/bauhaus.css +19 -0
  137. package/src/runtime/skins/editorial.css +19 -0
  138. package/src/runtime/skins/jornal.css +17 -0
  139. package/src/runtime/skins/manual-noite.css +14 -0
  140. package/src/runtime/skins/manual.css +14 -0
  141. package/src/runtime/skins/noite.css +21 -0
  142. package/src/runtime/skins/oceano.css +17 -0
  143. package/src/runtime/skins/pop.css +23 -0
  144. package/src/runtime/skins/prata.css +18 -0
  145. package/src/runtime/skins/prisma.css +28 -0
  146. package/src/runtime/skins/rabisco.css +18 -0
  147. package/src/runtime/skins/relevo.css +33 -0
  148. package/src/runtime/skins/sinal.css +16 -0
  149. package/src/runtime/skins/terminal.css +23 -0
  150. package/src/runtime/vendor/KATEX-LICENSE.txt +21 -0
  151. package/src/runtime/vendor/MERMAID-LICENSE.txt +21 -0
  152. package/src/runtime/vendor/PLOTLY-LICENSE.txt +21 -0
  153. package/src/runtime/vendor/katex.css +1 -0
  154. package/src/runtime/vendor/mermaid.min.js +3636 -0
  155. package/src/runtime/vendor/plotly.min.js +3620 -0
  156. package/src/runtime/video-player.js +35 -0
  157. package/src/science.js +162 -0
  158. package/src/studio/ai-response.js +36 -0
  159. package/src/studio/api-routes.js +152 -0
  160. package/src/studio/assets/contexto/leia-me.md +12 -0
  161. package/src/studio/assets/contexto/vendas.csv +7 -0
  162. package/src/studio/assets/imagens/colecao-arquitetura.png +0 -0
  163. package/src/studio/assets/imagens/colecao-cor.png +0 -0
  164. package/src/studio/assets/imagens/colecao-equipe.png +0 -0
  165. package/src/studio/assets/imagens/lavanda-cover.jpg +0 -0
  166. package/src/studio/code-routes.js +32 -0
  167. package/src/studio/command-approval.js +48 -0
  168. package/src/studio/demo-decks.js +98 -0
  169. package/src/studio/direction-routes.js +29 -0
  170. package/src/studio/errors.js +65 -0
  171. package/src/studio/exploration-demo.js +17 -0
  172. package/src/studio/exporting.js +105 -0
  173. package/src/studio/generation-report.js +10 -0
  174. package/src/studio/instance.js +48 -0
  175. package/src/studio/layout-samples.js +152 -0
  176. package/src/studio/project.js +371 -0
  177. package/src/studio/public/api-collections.js +28 -0
  178. package/src/studio/public/app.js +5265 -0
  179. package/src/studio/public/art-preview.js +10 -0
  180. package/src/studio/public/calc-fields.js +11 -0
  181. package/src/studio/public/chat-progress.js +47 -0
  182. package/src/studio/public/developer-fields.js +22 -0
  183. package/src/studio/public/explorer.js +443 -0
  184. package/src/studio/public/history.js +58 -0
  185. package/src/studio/public/index.html +867 -0
  186. package/src/studio/public/inspector.js +270 -0
  187. package/src/studio/public/lab-fields.js +5 -0
  188. package/src/studio/public/library.css +275 -0
  189. package/src/studio/public/library.html +55 -0
  190. package/src/studio/public/library.js +471 -0
  191. package/src/studio/public/merge-decks.js +155 -0
  192. package/src/studio/public/review-ui.js +100 -0
  193. package/src/studio/public/screenshot-editor.js +140 -0
  194. package/src/studio/public/share-ui.js +72 -0
  195. package/src/studio/public/slide-clipboard.js +23 -0
  196. package/src/studio/public/slide-form.js +1263 -0
  197. package/src/studio/public/studio-awareness.js +154 -0
  198. package/src/studio/public/studio-next.css +303 -0
  199. package/src/studio/public/style.css +1262 -0
  200. package/src/studio/public/ui-icons.js +2 -0
  201. package/src/studio/public/viewers.js +372 -0
  202. package/src/studio/public/visual-editor.js +326 -0
  203. package/src/studio/public/workspace.js +18 -0
  204. package/src/studio/public-files.js +1 -0
  205. package/src/studio/request-helpers.js +41 -0
  206. package/src/studio/server.js +1583 -0
  207. package/src/studio/share-routes.js +146 -0
  208. package/src/studio/slide-copy-routes.js +26 -0
  209. package/src/studio/slide-copy.js +30 -0
  210. package/src/studio/snapshot.js +160 -0
  211. package/src/studio/style-routes.js +103 -0
  212. package/src/studio/template-collections.js +97 -0
  213. package/src/studio/versions.js +95 -0
  214. package/src/studio/video-download.js +29 -0
  215. package/src/studio/visual-keys.js +52 -0
  216. package/src/studio/workspaces.js +39 -0
  217. package/src/table.js +93 -0
  218. package/src/templates/scaffold.js +372 -0
  219. package/src/themes.js +604 -0
  220. package/src/trace-view.js +450 -0
  221. package/src/uid.js +19 -0
  222. package/src/video-player.js +40 -0
  223. package/src/visual-edits.js +99 -0
  224. package/src/ws.js +134 -0
  225. package/templates/cenario/Texto no cen/303/241rio.yaml" +171 -0
  226. package/templates/cenario/imagens/cidade.svg +30 -0
  227. package/templates/cenario/imagens/pessoa.svg +15 -0
  228. package/templates/cenario-e-ciencia.yaml +47 -0
  229. package/templates/ensaio-api.yaml +160 -0
  230. package/templates/exemplo-alegre.yaml +75 -0
  231. package/templates/exemplo-keynote.yaml +90 -0
  232. package/templates/exemplo-napkin.yaml +139 -0
  233. package/templates/exemplo.yaml +228 -0
@@ -0,0 +1,154 @@
1
+ // Consciência ambiente do Studio: carimbo do motor, vigia de clipes e versões.
2
+ // Módulo próprio (não no app.js) por causa da trava de tamanho dos monolitos.
3
+ // Uso: window.SagaAwareness.mount({ state, showToast, hydrateIcons, fitRendered, ensureSlideStyles }).
4
+ (function () {
5
+ function mount(ctx) {
6
+ mount.ctx = ctx;
7
+ // delegação no document: a barra de título pode ser redesenhada e trocar os nós
8
+ document.addEventListener("click", (e) => {
9
+ if (e.target.closest("#btn-versions")) openVersions();
10
+ else if (e.target.closest("#versions-close") || e.target.id === "versions-modal") closeVersions();
11
+ else if (e.target.closest("#btn-direction-save")) saveDirection();
12
+ });
13
+ window.addEventListener("focus", loadDirections);
14
+ refreshBuildStamp();
15
+ watchVideoJobs();
16
+ loadDirections();
17
+ setInterval(refreshBuildStamp, 30000);
18
+ setInterval(watchVideoJobs, 30000);
19
+ }
20
+
21
+ // direções aprovadas: a capa atual vira receita que a IA usa ao ouvir o nome
22
+ async function loadDirections() {
23
+ const ctx = mount.ctx;
24
+ try {
25
+ const j = await (await fetch("api/directions")).json();
26
+ ctx.state.directions = j.directions || [];
27
+ ctx.state.directionsError = j.error || "";
28
+ } catch { ctx.state.directions = []; ctx.state.directionsError = ""; }
29
+ syncDirections();
30
+ }
31
+ function syncDirections() {
32
+ const ctx = mount.ctx;
33
+ const sel = document.getElementById("direction-select"), note = document.getElementById("direction-note");
34
+ if (!sel) return;
35
+ const list = ctx.state.directions || [];
36
+ sel.innerHTML = `<option value="">Nenhuma</option>` + list.map((d) => `<option value="${d.name.replace(/"/g, "&quot;")}">${d.name.replace(/</g, "&lt;")}</option>`).join("");
37
+ if (ctx.state.directionsError) { note.textContent = ctx.state.directionsError; note.hidden = false; }
38
+ else { note.textContent = list.length ? "Cite o nome no chat e a IA veste a capa com ela." : ""; note.hidden = !list.length; }
39
+ }
40
+ async function saveDirection() {
41
+ const ctx = mount.ctx;
42
+ const name = (prompt("Nome da direção (ex.: Stark dourado):", "") || "").trim();
43
+ if (!name) return;
44
+ try {
45
+ const r = await fetch("api/directions", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ name }) });
46
+ const j = await r.json();
47
+ if (!r.ok) throw new Error(j.error || r.statusText);
48
+ ctx.showToast(`Direção "${j.name}" salva. Cite o nome no chat para a IA usar.`, 9000);
49
+ loadDirections();
50
+ } catch (e) { ctx.showToast(`Não deu para salvar: ${e.message}`, 8000); }
51
+ }
52
+
53
+ // carimbo do código rodando (para o "é antigão?" nunca mais)
54
+ async function refreshBuildStamp() {
55
+ try {
56
+ const info = await (await fetch("api/instance")).json();
57
+ const el = document.getElementById("build-stamp");
58
+ if (!el) return;
59
+ const when = info.started ? new Date(info.started) : null;
60
+ el.textContent = `Motor ${info.version || "?"} · #${info.commit || "?"}`;
61
+ el.title = `Código rodando neste Studio: versão ${info.version || "?"} (commit ${info.commit || "?"}), no ar desde ${when ? when.toLocaleString("pt-BR") : "?"} (processo ${info.pid || "?"}). Se não bater com seu último push, reinicie o Studio.`;
62
+ } catch { /* barra de status não pode quebrar a sessão */ }
63
+ }
64
+
65
+ // vigia de clipes: o servidor baixa sozinho o que terminou; aqui só avisamos uma vez por job
66
+ async function watchVideoJobs() {
67
+ const ctx = mount.ctx;
68
+ let jobs = [];
69
+ try { jobs = (await (await fetch("api/video/jobs")).json()).jobs || []; } catch { return; }
70
+ ctx.state.seenVideoJobs ||= {};
71
+ for (const j of jobs) {
72
+ const before = ctx.state.seenVideoJobs[j.id];
73
+ ctx.state.seenVideoJobs[j.id] = j.status;
74
+ if (!before || before === j.status) continue;
75
+ if ((j.status === "completed" || j.status === "downloaded") && j.video) {
76
+ ctx.showToast(`Clipe pronto: ${j.video} — já baixado na pasta.`, 12000);
77
+ } else if (j.status === "failed") {
78
+ ctx.showToast("A geração do clipe falhou — veja o motivo no chat.", 12000);
79
+ }
80
+ }
81
+ }
82
+
83
+ // Versões: cada salvamento fotografa o deck; aqui compara lado a lado e restaura
84
+ let versionsCurrent = null;
85
+ function closeVersions() { document.getElementById("versions-modal")?.classList.add("hidden"); }
86
+ async function openVersions() {
87
+ const ctx = mount.ctx;
88
+ const modal = document.getElementById("versions-modal");
89
+ const list = modal.querySelector(".versions-list"), cmp = modal.querySelector(".versions-compare");
90
+ modal.classList.remove("hidden");
91
+ ctx.hydrateIcons(modal);
92
+ list.innerHTML = "<p>Carregando…</p>"; cmp.innerHTML = ""; versionsCurrent = null;
93
+ document.getElementById("versions-restore").disabled = true;
94
+ let versions = [];
95
+ try { versions = (await (await fetch("api/versions")).json()).versions || []; }
96
+ catch { list.innerHTML = "<p>Não deu para listar.</p>"; return; }
97
+ if (!versions.length) { list.innerHTML = "<p>Nenhuma versão ainda. Salve o deck para fotografar a primeira.</p>"; return; }
98
+ list.innerHTML = "";
99
+ versions.forEach((v) => {
100
+ const b = document.createElement("button");
101
+ b.type = "button"; b.className = "ver-item";
102
+ const when = new Date(v.at);
103
+ b.innerHTML = `<b></b><small></small>`;
104
+ b.querySelector("b").textContent = when.toLocaleString("pt-BR");
105
+ b.querySelector("small").textContent = "comparar";
106
+ b.setAttribute("role", "option");
107
+ b.onclick = () => { list.querySelectorAll(".ver-item").forEach((x) => x.classList.remove("active")); b.classList.add("active"); compareVersion(v); };
108
+ list.appendChild(b);
109
+ });
110
+ }
111
+ async function compareVersion(v) {
112
+ const ctx = mount.ctx;
113
+ const cmp = document.querySelector(".versions-compare");
114
+ const count = document.querySelector(".versions-count");
115
+ cmp.innerHTML = "<p>Comparando…</p>";
116
+ document.getElementById("versions-restore").disabled = true;
117
+ versionsCurrent = v;
118
+ try {
119
+ const show = await (await fetch("api/versions/show", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ name: v.name }) })).json();
120
+ const cur = ctx.state.deck.slides || [], ver = show.slides || [];
121
+ const n = Math.max(cur.length, ver.length), changed = [];
122
+ for (let i = 0; i < n; i++) if (JSON.stringify(cur[i] ?? null) !== JSON.stringify(ver[i] ?? null)) changed.push(i);
123
+ count.textContent = changed.length ? `${changed.length} slide(s) diferente(s)` : "Nenhuma diferença";
124
+ if (!changed.length) { cmp.innerHTML = "<p>Idêntica à atual.</p>"; return; }
125
+ cmp.innerHTML = "";
126
+ for (const i of changed.slice(0, 8)) {
127
+ const row = document.createElement("div");
128
+ row.className = "ver-row";
129
+ row.innerHTML = `<figure class="ver-cell changed"><figcaption>Atual · slide ${i + 1}</figcaption><div class="thumb-screen"><div class="thumb-render"></div></div></figure><figure class="ver-cell changed"><figcaption>Versão · slide ${i + 1}</figcaption><div class="thumb-screen"><div class="thumb-render"></div></div></figure>`;
130
+ cmp.appendChild(row);
131
+ const [cellA, cellB] = row.querySelectorAll(".thumb-render");
132
+ const render = async (slide, spec, el) => {
133
+ const r = await (await fetch("api/render-slide", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ slide, index: i, spec }) })).json();
134
+ ctx.ensureSlideStyles(r.baseCSS, r.themeCSS);
135
+ el.innerHTML = r.html;
136
+ ctx.fitRendered(el.closest(".thumb-screen"));
137
+ };
138
+ await render(cur[i] || { layout: "statement", text: "(removido)" }, ctx.state.deck, cellA);
139
+ await render(ver[i] || { layout: "statement", text: "(removido)" }, { theme: show.theme, palette: show.palette, slides: ver }, cellB);
140
+ }
141
+ if (changed.length > 8) { const more = document.createElement("p"); more.textContent = `+ ${changed.length - 8} slide(s). Restaure para ver tudo.`; cmp.appendChild(more); }
142
+ const rb = document.getElementById("versions-restore");
143
+ rb.disabled = false;
144
+ rb.onclick = async () => {
145
+ if (!confirm(`Voltar o deck para a versão de ${new Date(versionsCurrent.at).toLocaleString("pt-BR")}? O estado atual vira versão antes.`)) return;
146
+ const r = await fetch("api/versions/restore", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ name: versionsCurrent.name }) });
147
+ if (!r.ok) { ctx.showToast("Não deu para restaurar.", 8000); return; }
148
+ location.reload();
149
+ };
150
+ } catch { cmp.innerHTML = "<p>Não deu para comparar.</p>"; }
151
+ }
152
+
153
+ window.SagaAwareness = { mount };
154
+ })();
@@ -0,0 +1,303 @@
1
+ /* Um estúdio silencioso em volta de um palco expressivo. */
2
+ .shot-dialog{margin:auto;width:min(1200px,96vw);height:min(800px,94dvh);max-width:96vw;max-height:94dvh;border:1px solid var(--ui-line);border-radius:18px;padding:0;background:var(--chrome);color:var(--text);box-shadow:0 30px 100px #0005;font:13px var(--font-sans)}
3
+ .shot-dialog[open]{display:flex;flex-direction:column}
4
+ .shot-dialog::backdrop{background:#14101c99;backdrop-filter:blur(4px)}
5
+ .shot-dialog header{display:flex;align-items:center;justify-content:space-between;padding:22px 26px;border-bottom:1px solid var(--ui-line)}
6
+ .shot-dialog header small{color:var(--brand);letter-spacing:.14em;font-size:10px;font-weight:700}
7
+ .shot-dialog h2{font-size:25px;letter-spacing:-.035em;font-weight:600;margin-top:5px}
8
+ .shot-dialog button{padding:9px 13px;border-radius:8px;border:1px solid var(--ui-line);background:var(--chrome);color:var(--text);cursor:pointer}
9
+ .shot-dialog button:hover{background:var(--hover)}
10
+ .shot-dialog button:disabled{opacity:.35;cursor:default}
11
+ .shot-tools{display:flex;align-items:center;gap:8px;padding:12px 24px;flex-wrap:wrap}
12
+ .shot-divider{height:25px;width:1px;background:var(--ui-line);margin:0 5px}
13
+ .shot-tools [aria-pressed=true]{background:var(--selected);border-color:var(--brand);color:var(--brand)}
14
+ .shot-hint{font-size:11px;color:var(--text-2);margin-left:auto}
15
+ .shot-work{display:grid;grid-template-columns:minmax(0,1fr) 280px;flex:1;min-height:0;border-top:1px solid var(--ui-line)}
16
+ .shot-stage{display:flex;align-items:center;justify-content:center;min-height:0;overflow:hidden;background:var(--canvas-bg);background-image:radial-gradient(var(--ui-line-strong) .6px,transparent .6px);background-size:16px 16px}
17
+ .shot-empty{display:flex;flex-direction:column;text-align:center;gap:12px;padding:24px;color:var(--text-2)}
18
+ .shot-empty b{font-size:23px;color:var(--text);font-weight:500}.shot-empty small{font-size:11px}
19
+ .shot-dialog [hidden]{display:none!important}
20
+ .shot-image-wrap{position:relative;flex-shrink:0;touch-action:none;user-select:none;cursor:crosshair;box-shadow:0 12px 50px #0002}
21
+ .shot-image-wrap img{width:100%;height:100%;display:block;pointer-events:none}
22
+ .shot-marks{position:absolute;inset:0;pointer-events:none}
23
+ .shot-dialog .shot-mark{position:absolute;pointer-events:auto;background:#7352c72a;border:2px solid #a78bfa;color:#fff;padding:0;text-shadow:0 1px 3px #000;font-weight:700;touch-action:none;cursor:move;min-width:0;border-radius:5px}
24
+ .shot-dialog .shot-mark.point{transform:translate(-50%,-50%);border-radius:50%;background:#7352c7;box-shadow:0 0 0 5px #7352c740}
25
+ .shot-dialog .shot-mark.active{outline:2px solid #fff;outline-offset:2px}
26
+ .shot-work aside{padding:20px;overflow-y:auto;border-left:1px solid var(--ui-line)}
27
+ .shot-dialog label{display:block;font-size:11px;color:var(--text-2);margin-bottom:13px}
28
+ .shot-dialog input:not([type=file]),.shot-dialog textarea{display:block;width:100%;padding:9px 10px;margin-top:6px;border:1px solid var(--ui-line-strong);border-radius:7px;background:var(--chrome);color:var(--text);font:13px var(--font-sans)}
29
+ .shot-dialog textarea{resize:vertical;max-height:180px}
30
+ .shot-steps-head{display:flex;justify-content:space-between;margin:20px 0 9px;font-size:11px}
31
+ .shot-dialog .shot-step{display:block;width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:left;padding:10px;margin-bottom:5px;font-size:12px}
32
+ .shot-dialog .shot-step.active{color:var(--brand);background:var(--selected);border-color:var(--brand)}
33
+ .shot-fields{margin-top:16px}.shot-order{display:flex;gap:5px}.shot-order button{font-size:11px;padding:7px 10px}
34
+ .shot-tip{font-size:11px;color:var(--text-3);line-height:1.6;margin-top:20px}
35
+ .shot-dialog footer{display:flex;align-items:center;justify-content:flex-end;gap:9px;padding:14px 24px;border-top:1px solid var(--ui-line)}
36
+ .shot-status{flex:1;font-size:11px;color:var(--text-2)}
37
+ .shot-dialog .shot-primary{background:var(--brand-fill);color:white;border-color:transparent}
38
+ @media(max-width:760px){.shot-dialog header{padding:16px}.shot-dialog h2{font-size:20px}.shot-tools{padding:10px}.shot-hint{width:100%;margin:0}.shot-work{grid-template-columns:1fr;overflow-y:auto;display:block}.shot-stage{height:320px;min-height:260px}.shot-work aside{border-left:0;border-top:1px solid var(--ui-line);overflow:visible}.shot-dialog footer{padding:12px;flex-wrap:wrap}.shot-status{flex-basis:100%}.shot-dialog{height:94dvh}}
39
+ :root {
40
+ --chrome: #fffefa; --chrome-2: #f6f5f1; --canvas-bg: #eeede8;
41
+ --text: #25242b; --text-2: #686670; --text-3: #77757e;
42
+ --ui-line: #e5e3df; --ui-line-strong: #cbc8d0;
43
+ --brand: #7352c7; --brand-hover: #5935b4; --brand-fill: #7352c7;
44
+ --brand-fill-hover: #5935b4; --brand-soft: #eee8fa; --selected: #eee8fa;
45
+ --hover: #f0edf5; --ui-radius: 8px;
46
+ }
47
+ :root[data-theme="dark"] {
48
+ --chrome: #222127; --chrome-2: #29282e; --canvas-bg: #19181d;
49
+ --text: #f0edf5; --text-2: #b6b2c1; --text-3: #a39bad;
50
+ --ui-line: #38353e; --ui-line-strong: #57505f;
51
+ --brand: #b69aec; --brand-fill: #805bcc; --brand-fill-hover: #9470dc;
52
+ --brand-soft: #383044; --selected: #383044; --hover: #35303f;
53
+ }
54
+ .studio-next .titlebar { height: 64px; padding: 0 22px; gap: 16px; }
55
+ .studio-next .app-mark { background: var(--text); color: var(--chrome); width: 34px; height: 34px; border-radius: 10px; }
56
+ .studio-next .app-mark .ic { width: 20px; height: 20px; }
57
+ .studio-next .doc-title { font-size: 14px; font-weight: 650; max-width: 330px; }
58
+ .studio-next .save-status { font-size: 11px; }
59
+ .studio-next .save-status:not(.unsaved)::before { content: ""; display: inline-block; width: 7px; height: 7px; border-radius: 50%; background: #76a385; margin-right: 6px; vertical-align: middle; }
60
+ .studio-next .search-box { background: var(--chrome-2); border-color: transparent; border-radius: 8px; }
61
+ .studio-next #btn-present { height: 36px; padding: 0 18px; }
62
+ .studio-next .split-button .btn-caret { height: 36px; }
63
+ .studio-next .ribbon-tabs { height: 40px; padding: 0 20px; gap: 5px; }
64
+ .studio-next .ribbon-tab { height: 35px; padding: 0 14px; font-size: 12px; }
65
+ .studio-next .ribbon-tab.active::after { height: 2px; }
66
+ .studio-next .ribbon { height: 76px; padding: 6px 16px; box-shadow: none; }
67
+ .studio-next .rgroup { padding: 0 12px; }
68
+ @media (max-width: 1440px) { .studio-next .rgroup { padding: 0 6px; } } /* notebook: 3 temas e 3 paletas à vista, nada transborda */
69
+ .studio-next .rgroup-body { align-items: center; gap: 7px; }
70
+ .studio-next .rgroup-label { display: none; }
71
+ .studio-next .rbtn { border-radius: 7px; }
72
+ .studio-next .rbtn-lg { height: 56px; min-width: 65px; padding: 7px 10px; gap: 5px; font-size: 11px; }
73
+ .studio-next .rbtn-lg > .ic { width: 21px; height: 21px; }
74
+ .studio-next .rgroup-fields { gap: 5px; }
75
+ .studio-next .rfield > span { font-size: 11px; }
76
+ .studio-next .workspace { grid-template-columns: 200px minmax(0, 1fr) auto; }
77
+ .studio-next .slide-rail { background: var(--chrome); }
78
+ .studio-next .rail-header { height: 47px; padding: 0 16px; font-size: 11px; text-transform: uppercase; letter-spacing: .09em; }
79
+ .studio-next .thumb-list { padding: 0 14px 20px 6px; }
80
+ .studio-next .thumb-card { padding: 8px 0; gap: 6px; }
81
+ .studio-next .thumb-screen { border-radius: 5px; box-shadow: 0 1px 4px #17102416; outline-offset: 3px; }
82
+ .studio-next .thumb-num { font-size: 10px; }
83
+ .studio-next .canvas-viewport { background-image: radial-gradient(var(--ui-line-strong) .6px, transparent .6px); background-size: 18px 18px; }
84
+ .studio-next .stage-16-9 { box-shadow: 0 18px 60px #24183414, 0 2px 8px #2418340c; }
85
+ .studio-next .safe-box { border-color: #8867ca40; }
86
+ .studio-next .inspector-sidebar { background: var(--chrome); }
87
+ .studio-next .task-pane { width: 304px; }
88
+ .studio-next .statusbar { min-height: 34px; font-size: 11px; }
89
+ .studio-next .notes-bar { background: var(--chrome); border-top-color: var(--ui-line); }
90
+ .studio-next .theme-card { border-radius: 7px; }
91
+ .studio-next .form-control { border-radius: 7px; }
92
+ .studio-next .advanced-density { align-items: center; }
93
+ .studio-next .advanced-density .rfield { align-items: flex-start; flex-direction: column; gap: 2px; }
94
+ .studio-next .advanced-guide { align-items: flex-start; justify-content: center; gap: 4px; color: var(--text-2); font-size: 10px; white-space: nowrap; }
95
+ .studio-next .advanced-guide .rbtn { color: var(--brand); font-weight: 600; }
96
+ .studio-next .modal-dialog-box { border-radius: 16px; }
97
+ .studio-next .modal-dialog-header { padding: 20px 24px; }
98
+ .studio-next .chat-empty { line-height: 1.7; }
99
+ .motion-control { display: flex; align-items: center; gap: 6px; padding: 0 10px; height: 34px; border: 1px solid var(--ui-line); border-radius: 20px; color: var(--text-2); }
100
+ .motion-control .ic { width: 14px; height: 14px; color: var(--brand); }
101
+ .motion-control select { border: 0; background: transparent; font-size: 11px; outline-offset: 3px; cursor: pointer; max-width: 110px; }
102
+ .motion-control option { background: var(--chrome); color: var(--text); }
103
+ .scene-launch { position: relative; }
104
+ .new-dot { position: absolute; right: 12px; top: 6px; width: 5px; height: 5px; border-radius: 50%; background: var(--brand); }
105
+ .scene-dialog { width: min(1040px, calc(100vw - 40px)); height: min(88dvh, 980px); max-height: calc(100dvh - 56px); display: flex; flex-direction: column; }
106
+ .scene-eyebrow { display: block; color: var(--brand); font-size: 10px; letter-spacing: .16em; font-weight: 700; margin-bottom: 8px; }
107
+ .scene-dialog #scene-title { font-size: 27px; font-weight: 550; letter-spacing: -.03em; }
108
+ .scene-tools { display: flex; justify-content: space-between; align-items: center; gap: 12px; padding: 0 24px 20px; }
109
+ .scene-tools > span { color: var(--text-3); font-size: 11px; }
110
+ .scene-filters { display: flex; gap: 4px; flex-wrap: wrap; }
111
+ .scene-filters button { padding: 7px 12px; font-size: 11px; border-radius: 20px; }
112
+ .scene-filters button:hover { background: var(--hover); }
113
+ .scene-filters button.active { background: var(--text); color: var(--chrome); }
114
+ .scene-grid { display: grid; flex: 1; min-height: 0; grid-template-columns: repeat(2, minmax(0, 1fr)); grid-auto-rows: max-content; align-content: start; overflow-y: auto; gap: 18px; padding: 2px 24px 24px; }
115
+ .scene-card { text-align: left; border: 1px solid var(--ui-line); background: var(--chrome); border-radius: 11px; overflow: hidden; transition: border-color .15s, box-shadow .15s; min-width: 0; }
116
+ .scene-card { cursor: pointer; }
117
+ .scene-card:hover { border-color: var(--brand); box-shadow: 0 6px 20px #23123312; }
118
+ .scene-card[hidden] { display: none; }
119
+ .scene-preview { width: 100%; aspect-ratio: var(--aspect, 16/9); position: relative; overflow: hidden; background: var(--chrome-2); pointer-events: none; }
120
+ .scene-render { width: 1920px; height: var(--sh, 1080px); position: absolute; left: 0; top: 0; transform-origin: 0 0; }
121
+ .scene-render .slide { opacity: 1 !important; visibility: visible !important; }
122
+ .scene-render .slide .e, .scene-render .slide [data-step] { opacity: 1 !important; transform: none !important; visibility: visible !important; }
123
+ .scene-insert { position: absolute; bottom: 10px; right: 10px; padding: 7px 12px; background: var(--chrome); color: var(--brand); border-radius: 20px; font-size: 11px; opacity: 0; box-shadow: 0 2px 10px #0002; }
124
+ .scene-card:hover .scene-insert, .scene-card:focus-visible .scene-insert { opacity: 1; }
125
+ .scene-card-copy { display: flex; flex-direction: column; padding: 14px 16px; gap: 6px; }
126
+ .scene-card-copy b { font-size: 13px; font-weight: 650; }
127
+ .scene-card-copy span { font-size: 11px; color: var(--text-2); line-height: 1.5; }
128
+ .scene-card-copy small { font-size: 9px; text-transform: uppercase; letter-spacing: .09em; color: var(--brand); padding-top: 5px; }
129
+ .scene-footer { padding: 15px 24px; border-top: 1px solid var(--ui-line); color: var(--text-3); font-size: 11px; display: flex; gap: 8px; align-items: center; }
130
+ .scene-loading { grid-column: 1/-1; min-height: 180px; padding: 60px 0; color: var(--text-2); text-align: center; }
131
+ @media (max-width: 1100px) {
132
+ .studio-next .titlebar { padding: 0 12px; gap: 9px; }
133
+ .studio-next .search-box { width: 36px; min-width: 36px; padding: 0 10px; }
134
+ .studio-next .search-box span, .studio-next .search-box kbd { display: none; }
135
+ .studio-next .doc-title { max-width: 280px; }
136
+ .scene-tools > span { display: none; }
137
+ }
138
+ @media (max-width: 900px) {
139
+ .studio-next .titlebar { height: 54px; }
140
+ .studio-next .titlebar .doc-title { max-width: none; min-width: 40px; flex: 1; }
141
+ .studio-next .save-status, .studio-next .search-box { display: none; }
142
+ .studio-next .ribbon-tabs { padding: 0 7px; gap: 0; overflow-x: auto; }
143
+ .studio-next .ribbon-tab { padding: 0 10px; }
144
+ .studio-next .ribbon { padding: 5px; height: 70px; }
145
+ .studio-next .workspace { grid-template-columns: minmax(0, 1fr); }
146
+ .studio-next .rgroup { padding: 0 7px; }
147
+ .studio-next .rgroup-body { gap: 3px; }
148
+ .motion-control { padding: 0 6px; gap: 2px; }
149
+ .motion-control .ic { display: none; }
150
+ .motion-control select { max-width: 89px; font-size: 10px; }
151
+ .studio-next #btn-present { padding: 0 9px; }
152
+ .scene-dialog { width: calc(100vw - 20px); height: calc(100dvh - 28px); max-height: calc(100dvh - 28px); }
153
+ .scene-dialog #scene-title { font-size: 23px; }
154
+ .scene-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; padding: 0 14px 18px; }
155
+ .scene-card-copy { padding: 11px; }
156
+ .scene-card-copy b { font-size: 12px; }
157
+ .scene-card-copy span { display: none; }
158
+ .scene-tools { padding: 0 14px 16px; }
159
+ .scene-filters button { padding: 7px 9px; font-size: 10px; }
160
+ }
161
+ @media (prefers-reduced-motion: reduce) {
162
+ .studio-next *, .studio-next *::before, .studio-next *::after { scroll-behavior: auto !important; transition-duration: .01ms !important; animation-duration: .01ms !important; }
163
+ }
164
+ .shot-dialog .ic { display: inline-flex; width: 16px; height: 16px; vertical-align: -3px; }
165
+ .shot-dialog .ic svg { width: 100%; height: 100%; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
166
+ .visual-tools{display:flex;align-items:center;gap:5px;min-width:max-content}.visual-tools .rbtn-lg{min-width:52px;height:56px;padding:5px 7px;font-size:11px}.visual-tools-hint{max-width:160px;color:var(--text-3);font-size:10px;line-height:1.3}.visual-toolbar{display:flex;align-items:center;gap:5px;padding-left:7px;border-left:1px solid var(--ui-line)}.visual-toolbar[hidden]{display:none}.visual-toolbar input{width:58px;padding:7px 9px;border:1px solid var(--ui-line-strong);border-radius:7px;background:var(--chrome);color:var(--text)}.visual-toolbar input[type=color]{width:34px;padding:2px;height:32px}.visual-action-button{padding:5px 7px;border:1px solid var(--ui-line);border-radius:7px;background:var(--chrome);color:var(--text-2);font-size:10px;white-space:nowrap;cursor:pointer}.visual-mode [data-vkey]{cursor:move!important}.visual-mode [data-vkey]:hover{outline:2px dashed #9a7bff;outline-offset:5px}.visual-mode .visual-selected{outline:3px solid #8060ed!important;outline-offset:5px}.visual-handle{position:absolute;right:-12px;bottom:-12px;width:24px;height:24px;padding:0;border:3px solid white;border-radius:4px;background:#8060ed;cursor:nwse-resize;z-index:999}.visual-mode [data-vkey]{touch-action:none}.visual-mode .visual-selected:not([style*="position:absolute"]){position:relative}.visual-mode [data-writing]{cursor:text!important}.theme-toggle{flex:none;width:36px;height:36px;border:1px solid var(--ui-line);border-radius:8px;background:var(--chrome);color:var(--text-2)}.theme-toggle:hover{background:var(--hover);color:var(--text)}.theme-toggle .ic{width:18px;height:18px}.ai-settings-dialog{width:min(1100px,94vw);height:auto;max-height:90vh;border:1px solid #d8d9e4;border-radius:18px;padding:24px;background:#fff;color:#252938}.ai-settings-dialog::backdrop{background:#111a3d77;backdrop-filter:blur(5px)}.ai-settings-head{display:flex;align-items:center;justify-content:space-between}.ai-settings-head h2{margin:0}.ai-settings-dialog button,.ai-settings-dialog a{display:inline-block;padding:9px 12px;border:1px solid #d8d9e4;border-radius:8px;margin-right:8px}.ai-settings-dialog iframe{margin-top:16px;width:100%;height:calc(100% - 155px);border:1px solid #e8e9ef;border-radius:10px}.ai-settings-dialog [hidden]{display:none}
167
+ #slide-stage:has(.visual-mode)~.inspector-layer,#slide-stage:has(.visual-mode) .issue-bounding-box{pointer-events:none}.visual-mode [data-vkey]{transition:none!important}
168
+ .visual-handle{display:none}.visual-mode .visual-selected>.visual-handle{display:block}.layout-help{font-size:12px;line-height:1.4;margin:0 14px 12px;color:var(--text-muted)}
169
+ /* menu de formas (Inserir → Formas): grade de desenhos, fora do recorte da faixa */
170
+ .shape-menu{position:fixed;z-index:1200;display:grid;grid-template-columns:repeat(4,78px);gap:4px;padding:8px;border:1px solid var(--ui-line-strong);border-radius:10px;background:var(--chrome);box-shadow:var(--shadow-2,0 12px 32px #0004)}
171
+ .shape-menu[hidden]{display:none}
172
+ .shape-option{display:flex;flex-direction:column;align-items:center;gap:3px;padding:7px 4px 5px;border:1px solid transparent;border-radius:7px;background:none;color:var(--text-2);font-size:10px;cursor:pointer}
173
+ .shape-option:hover,.shape-option:focus-visible{background:var(--hover);border-color:var(--ui-line);color:var(--text);outline:none}
174
+ .shape-option svg{width:40px;height:32px;fill:color-mix(in srgb,var(--brand) 22%,transparent);stroke:var(--brand);stroke-width:5;stroke-linejoin:round;vector-effect:non-scaling-stroke}
175
+ /* galeria única "Novo slide": busca, categorias e três colunas */
176
+ .scene-dialog { width: min(1320px, calc(100vw - 40px)); }
177
+ .scene-tools { flex-direction: column; align-items: stretch; }
178
+ .scene-search { max-width: 420px; height: 36px; }
179
+ .scene-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
180
+ .scene-group { grid-column: 1 / -1; margin: 10px 0 -6px; font-size: 12px; font-weight: 650; letter-spacing: .06em; text-transform: uppercase; color: var(--text-2); }
181
+ .scene-group:first-child { margin-top: 0; }
182
+ .scene-group[hidden] { display: none; }
183
+ @media (max-width: 900px) { .scene-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
184
+ /* seletor de Layout: as mesmas categorias da galeria */
185
+ .lp-group { grid-column: 1 / -1; padding: 10px 2px 0; font-size: 11px; font-weight: 650; letter-spacing: .06em; text-transform: uppercase; color: var(--text-2); }
186
+ .lp-group:first-child { padding-top: 0; }
187
+
188
+ /* Novo slide dividido (como no PowerPoint): em cima, em branco; embaixo, a galeria de tipos */
189
+ .rsplit { display: flex; flex-direction: column; align-items: stretch; min-width: 64px; border-radius: 6px; }
190
+ .rsplit-main, .rsplit-more { border: 1px solid transparent; background: none; color: var(--text); cursor: pointer; }
191
+ .rsplit-main { height: 32px; display: grid; place-items: center; border-radius: 6px 6px 0 0; }
192
+ .rsplit-main .ic { width: 20px; height: 20px; }
193
+ .rsplit-more { display: flex; align-items: center; justify-content: center; gap: 2px; padding: 3px 6px; font-size: 11px; border-radius: 0 0 6px 6px; white-space: nowrap; }
194
+ .rsplit-more .ic { width: 12px; height: 12px; }
195
+ .rsplit:hover .rsplit-main, .rsplit:hover .rsplit-more { border-color: var(--ui-line); }
196
+ .rsplit-main:hover, .rsplit-more:hover { background: var(--hover); }
197
+ /* Animações no menu Apresentar */
198
+ .menu-sep { height: 1px; margin: 6px 0; background: var(--ui-line); }
199
+ .menu-head { padding: 4px 12px 2px; font-size: 10px; font-weight: 650; letter-spacing: .06em; text-transform: uppercase; color: var(--text-3); }
200
+ .motion-opt { align-items: flex-start; }
201
+ .motion-opt > span { display: flex; flex-direction: column; gap: 1px; text-align: left; }
202
+ .motion-opt small { color: var(--text-3); font-size: 11px; }
203
+ .motion-opt .ic { visibility: hidden; margin-top: 2px; }
204
+ .motion-opt[aria-checked="true"] .ic { visibility: visible; color: var(--brand); }
205
+ /* retângulo de seleção de vários objetos */
206
+ .visual-marquee { position: absolute; z-index: 1000; border: 1px dashed #8060ed; background: #8060ed1f; pointer-events: none; }
207
+
208
+ /* prévia de modelo de fábrica */
209
+ .preview-banner { display: flex; align-items: center; gap: 10px; margin: 8px 12px 0; padding: 8px 12px; border: 1px solid color-mix(in srgb, var(--brand) 45%, transparent); border-radius: 8px; background: color-mix(in srgb, var(--brand) 12%, var(--chrome)); color: var(--text); font-size: 12px; line-height: 1.4; }
210
+ .preview-banner.hidden { display: none; }
211
+ .preview-banner .ic { flex: none; width: 16px; height: 16px; color: var(--brand); }
212
+ .preview-banner span { flex: 1; }
213
+ .preview-banner .btn { flex: none; }
214
+
215
+ /* barra do objeto selecionado: flutua junto da seleção */
216
+ .visual-toolbar { position: fixed; z-index: 1150; display: flex; align-items: center; gap: 4px; padding: 5px 6px; border: 1px solid var(--ui-line-strong); border-radius: 10px; background: var(--chrome); box-shadow: var(--shadow-2, 0 10px 28px #0004); }
217
+ .visual-toolbar[hidden], .visual-toolbar [hidden] { display: none !important; }
218
+ .visual-toolbar .vt-field { display: flex; align-items: center; gap: 4px; padding: 0 6px; height: 30px; border: 1px solid var(--ui-line); border-radius: 7px; color: var(--text-2); cursor: pointer; }
219
+ .visual-toolbar .vt-field .ic { width: 15px; height: 15px; }
220
+ .visual-toolbar input[type=number] { width: 52px; height: 24px; padding: 0 4px; border: 0; background: transparent; color: var(--text); }
221
+ .visual-toolbar input[type=color] { width: 26px; height: 22px; padding: 0; border: 0; background: none; cursor: pointer; }
222
+ .visual-toolbar .vt-sep { width: 1px; height: 22px; background: var(--ui-line); margin: 0 2px; }
223
+ .visual-toolbar .vt-btn { width: 30px; height: 30px; display: grid; place-items: center; border: 1px solid transparent; border-radius: 7px; background: none; color: var(--text-2); cursor: pointer; }
224
+ .visual-toolbar .vt-btn:hover, .visual-toolbar .vt-field:hover { background: var(--hover); color: var(--text); }
225
+ .visual-toolbar .vt-btn .ic { width: 16px; height: 16px; }
226
+
227
+ /* Preferências: busca, seções à esquerda, linhas com rótulo, explicação e controle */
228
+ .prefs-dialog { width: min(920px, calc(100vw - 40px)); height: min(80dvh, 720px); display: flex; flex-direction: column; }
229
+ .prefs-top { display: flex; align-items: center; gap: 12px; padding: 0 20px 12px; }
230
+ .prefs-top input { max-width: 360px; height: 34px; }
231
+ .prefs-status { color: var(--text-3); font-size: 12px; }
232
+ .prefs-body { flex: 1; min-height: 0; display: grid; grid-template-columns: 190px 1fr; border-top: 1px solid var(--ui-line); }
233
+ .prefs-nav { display: flex; flex-direction: column; gap: 2px; padding: 10px; border-right: 1px solid var(--ui-line); overflow: auto; }
234
+ .prefs-nav button { text-align: left; padding: 7px 10px; border: 0; border-radius: 6px; background: none; color: var(--text-2); font-size: 12px; cursor: pointer; }
235
+ .prefs-nav button:hover { background: var(--hover); color: var(--text); }
236
+ .prefs-list { overflow: auto; padding: 6px 20px 20px; }
237
+ .prefs-sec[hidden], .pref-row[hidden] { display: none; }
238
+ .prefs-sec h4 { margin: 14px 0 4px; font-size: 12px; font-weight: 650; letter-spacing: .06em; text-transform: uppercase; color: var(--text-2); }
239
+ .pref-row { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 9px 0; border-bottom: 1px solid var(--ui-line); }
240
+ .pref-label { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
241
+ .pref-label b { font-size: 13px; font-weight: 550; }
242
+ .pref-label small { font-size: 11px; color: var(--text-3); line-height: 1.4; }
243
+ .pref-ctl { flex: none; }
244
+ .pref-ctl select { min-width: 200px; }
245
+ .pref-ctl input[type=text] { width: 240px; }
246
+ .pref-num { display: inline-flex; align-items: center; gap: 6px; }
247
+ .pref-num input { width: 72px; }
248
+ .pref-num span { font-size: 12px; color: var(--text-3); }
249
+ .prefs-foot { padding: 10px 20px; border-top: 1px solid var(--ui-line); color: var(--text-3); font-size: 11px; }
250
+
251
+ /* a IA perguntou para que serve o material (Deck com IA) */
252
+ .ai-ask { display: flex; flex-direction: column; gap: 8px; padding: 10px 12px; border: 1px solid var(--brand); border-radius: 8px; color: var(--text); }
253
+ .ai-ask b { font-size: 13px; font-weight: 600; }
254
+ .ai-ask-opts { display: flex; flex-wrap: wrap; gap: 6px; }
255
+ .ai-ask-free { display: flex; gap: 6px; }
256
+ .ai-ask-free input { flex: 1; }
257
+ /* Inspetor de propriedades: grade compacta (Object Inspector), categorias recolhíveis */
258
+ .inspector-panel { overflow-y: auto; padding: 8px 10px 20px; }
259
+ .ip-hint { margin: 4px 2px 10px; color: var(--text-3); font-size: 12px; line-height: 1.45; }
260
+ .ip-sec { margin-bottom: 10px; }
261
+ .ip-sec h4 { display: flex; align-items: center; gap: 6px; margin: 2px 2px 6px; font-size: 13px; font-weight: 600; color: var(--text); }
262
+ .ip-sec h4 .ic { width: 14px; height: 14px; color: var(--brand); }
263
+ .ip-sec h4 span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
264
+ .ip-cat { border: 1px solid var(--ui-line); border-radius: 7px; margin-bottom: 6px; overflow: hidden; background: var(--chrome); }
265
+ .ip-cat > summary { padding: 5px 8px; font-size: 11px; font-weight: 650; letter-spacing: .05em; text-transform: uppercase; color: var(--text-2); cursor: pointer; list-style: none; background: var(--chrome-2); user-select: none; }
266
+ .ip-cat > summary::-webkit-details-marker { display: none; }
267
+ .ip-cat > summary::before { content: ""; display: inline-block; width: 6px; height: 6px; margin-right: 7px; border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor; transform: rotate(-45deg); transition: transform .15s; vertical-align: 1px; }
268
+ .ip-cat[open] > summary::before { transform: rotate(45deg); }
269
+ .ip-row { display: grid; grid-template-columns: 44% 1fr 22px; align-items: center; min-height: 26px; border-top: 1px solid var(--ui-line); }
270
+ .ip-l { padding: 0 8px; font-size: 12px; color: var(--text-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
271
+ .ip-v { min-width: 0; padding: 1px 4px 1px 0; }
272
+ .ip-v input[type=number], .ip-v input[type=text], .ip-v select { width: 100%; height: 22px; padding: 0 5px; border: 1px solid transparent; border-radius: 3px; background: transparent; color: var(--text); font-size: 12px; }
273
+ .ip-v input:hover, .ip-v select:hover { border-color: var(--ui-line); }
274
+ .ip-v input:focus, .ip-v select:focus { border-color: var(--brand); background: var(--chrome); outline: none; }
275
+ .ip-v select option { background: var(--chrome); color: var(--text); }
276
+ .ip-num, .ip-color, .ip-range { display: flex; align-items: center; gap: 4px; }
277
+ .ip-unit, .ip-hex { flex: none; font-size: 11px; color: var(--text-3); }
278
+ .ip-color input[type=color] { width: 26px; height: 20px; padding: 0; border: 1px solid var(--ui-line); border-radius: 3px; background: none; cursor: pointer; }
279
+ .ip-range input { flex: 1; min-width: 0; }
280
+ .ip-ro { display: block; padding: 0 5px; font: 11px var(--font-mono); color: var(--text-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
281
+ .ip-action { height: 22px; padding: 0 8px; border: 1px solid var(--ui-line); border-radius: 4px; background: none; color: var(--text-2); font-size: 11px; cursor: pointer; }
282
+ .ip-action:hover { color: var(--err); border-color: var(--err); }
283
+ .ip-reset { width: 20px; height: 20px; padding: 0; display: grid; place-items: center; border: 0; background: none; color: var(--text-3); cursor: pointer; }
284
+ .ip-reset[hidden] { display: none; }
285
+ .ip-reset:hover { color: var(--brand); }
286
+ .ip-reset .ic { width: 12px; height: 12px; }
287
+ /* alinhar / distribuir, guias do arrasto, objeto travado, lista de objetos */
288
+ .visual-toolbar .vt-group { display: inline-flex; align-items: center; gap: 2px; }
289
+ .visual-toolbar .vt-btn:disabled { opacity: .35; cursor: default; }
290
+ .visual-guide { position: absolute; z-index: 1001; background: #e5487d; pointer-events: none; }
291
+ .visual-mode [data-locked] { cursor: default !important; }
292
+ .visual-mode [data-locked]:hover { outline: none; }
293
+ .visual-mode .visual-selected[data-locked] { outline-style: dashed !important; }
294
+ .ip-layers { display: flex; flex-direction: column; gap: 1px; max-height: 240px; overflow: auto; padding: 4px 0; }
295
+ .ip-layer { display: flex; align-items: center; gap: 6px; min-height: 26px; padding: 0 6px; border-radius: 5px; font-size: 12px; color: var(--text); cursor: pointer; }
296
+ .ip-layer:hover { background: var(--hover); }
297
+ .ip-layer.sel { background: var(--selected); color: var(--brand); }
298
+ .ip-layer.off .ip-layer-name { opacity: .45; text-decoration: line-through; }
299
+ .ip-layer .ic { width: 14px; height: 14px; flex: none; }
300
+ .ip-layer-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
301
+ .ip-layer button { display: grid; place-items: center; width: 22px; height: 22px; padding: 0; border: 0; border-radius: 4px; background: none; color: var(--text-3); cursor: pointer; }
302
+ .ip-layer button:hover { background: var(--chrome-2); color: var(--text); }
303
+ .ip-layer button.on { color: var(--brand); }