primocode 10.12.0 → 10.14.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 (207) hide show
  1. package/README.md +74 -12
  2. package/bin/primocode.js +148 -8
  3. package/lib/act.js +48 -1
  4. package/lib/catalogo.js +12 -1
  5. package/lib/config.js +1 -0
  6. package/lib/estudio/assinaturas/gerativo.json +1 -1
  7. package/lib/estudio/camadas.js +4 -0
  8. package/lib/estudio/cota.js +150 -0
  9. package/lib/estudio/dados/projetos/clube-ad5.json +105 -0
  10. package/lib/estudio/dados/projetos/clube-ae-sem-memoria.json +107 -0
  11. package/lib/estudio/dados/projetos/clube-agent.json +120 -0
  12. package/lib/estudio/dados/projetos/clube-antes-e-agora.json +86 -0
  13. package/lib/estudio/dados/projetos/clube-apresentando-clube.json +110 -0
  14. package/lib/estudio/dados/projetos/clube-bluevisa.json +106 -0
  15. package/lib/estudio/dados/projetos/clube-caught-in-the-fire.json +127 -0
  16. package/lib/estudio/dados/projetos/clube-chat-cliente-satisfeito.json +98 -0
  17. package/lib/estudio/dados/projetos/clube-chatgpt-anuncios.json +120 -0
  18. package/lib/estudio/dados/projetos/clube-claude-dj.json +140 -0
  19. package/lib/estudio/dados/projetos/clube-claude-mcp.json +142 -0
  20. package/lib/estudio/dados/projetos/clube-cleanui.json +106 -0
  21. package/lib/estudio/dados/projetos/clube-clinica-take-unico.json +128 -0
  22. package/lib/estudio/dados/projetos/clube-clinica.json +104 -0
  23. package/lib/estudio/dados/projetos/clube-clube-opener.json +125 -0
  24. package/lib/estudio/dados/projetos/clube-clube.json +108 -0
  25. package/lib/estudio/dados/projetos/clube-codigo.json +101 -0
  26. package/lib/estudio/dados/projetos/clube-distilbook.json +104 -0
  27. package/lib/estudio/dados/projetos/clube-drive-upload.json +115 -0
  28. package/lib/estudio/dados/projetos/clube-dub.json +119 -0
  29. package/lib/estudio/dados/projetos/clube-enxovaly.json +105 -0
  30. package/lib/estudio/dados/projetos/clube-fecha7.json +118 -0
  31. package/lib/estudio/dados/projetos/clube-filatov.json +128 -0
  32. package/lib/estudio/dados/projetos/clube-frame.json +108 -0
  33. package/lib/estudio/dados/projetos/clube-glass.json +118 -0
  34. package/lib/estudio/dados/projetos/clube-letra-em-apps.json +84 -0
  35. package/lib/estudio/dados/projetos/clube-letra-globo-3d.json +111 -0
  36. package/lib/estudio/dados/projetos/clube-letra-nos-apps.json +146 -0
  37. package/lib/estudio/dados/projetos/clube-letra-seis-mundos.json +100 -0
  38. package/lib/estudio/dados/projetos/clube-lula-3.json +146 -0
  39. package/lib/estudio/dados/projetos/clube-morph.json +119 -0
  40. package/lib/estudio/dados/projetos/clube-motion-designer.json +115 -0
  41. package/lib/estudio/dados/projetos/clube-motion-pacote.json +112 -0
  42. package/lib/estudio/dados/projetos/clube-movimento.json +103 -0
  43. package/lib/estudio/dados/projetos/clube-not-like-us.json +117 -0
  44. package/lib/estudio/dados/projetos/clube-pinterest-inspiracao.json +86 -0
  45. package/lib/estudio/dados/projetos/clube-pixel-e-tinta.json +108 -0
  46. package/lib/estudio/dados/projetos/clube-ponte.json +118 -0
  47. package/lib/estudio/dados/projetos/clube-processo-edit-tonal.json +126 -0
  48. package/lib/estudio/dados/projetos/clube-processo-motion-100-ia.json +109 -0
  49. package/lib/estudio/dados/projetos/clube-promo.json +114 -0
  50. package/lib/estudio/dados/projetos/clube-proposito.json +115 -0
  51. package/lib/estudio/dados/projetos/clube-rankhog.json +128 -0
  52. package/lib/estudio/dados/projetos/clube-recursao.json +116 -0
  53. package/lib/estudio/dados/projetos/clube-revelar.json +118 -0
  54. package/lib/estudio/dados/projetos/clube-robo.json +125 -0
  55. package/lib/estudio/dados/projetos/clube-shelby-ep2.json +144 -0
  56. package/lib/estudio/dados/projetos/clube-shelby.json +97 -0
  57. package/lib/estudio/dados/projetos/clube-solar-eclipse.json +96 -0
  58. package/lib/estudio/dados/projetos/clube-soldier.json +128 -0
  59. package/lib/estudio/dados/projetos/clube-som-de-cena.json +108 -0
  60. package/lib/estudio/dados/projetos/clube-spotify-candidatura.json +112 -0
  61. package/lib/estudio/dados/projetos/clube-tda-app.json +118 -0
  62. package/lib/estudio/dados/projetos/clube-tda-ia.json +75 -0
  63. package/lib/estudio/dados/projetos/clube-telegram-chat.json +118 -0
  64. package/lib/estudio/dados/projetos/clube-telegram-ilha.json +106 -0
  65. package/lib/estudio/dados/projetos/clube-tennessee-nike.json +132 -0
  66. package/lib/estudio/dados/projetos/clube-tudo-se-move.json +112 -0
  67. package/lib/estudio/dados/projetos/clube-uiad.json +107 -0
  68. package/lib/estudio/dados/projetos/clube-viralgrow.json +108 -0
  69. package/lib/estudio/dados/projetos/clube-whose-side.json +140 -0
  70. package/lib/estudio/dados/projetos/clube-youtube-inscrever.json +108 -0
  71. package/lib/estudio/dados/projetos/elementos-do-site-em-movimento.json +49 -0
  72. package/lib/estudio/dados/projetos/explainer-narrado.json +51 -0
  73. package/lib/estudio/dados/projetos/lancamento-de-produto.json +51 -0
  74. package/lib/estudio/dados/projetos/motion-so-com-sons.json +50 -0
  75. package/lib/estudio/dados/projetos/titulo-em-after-effects.json +51 -0
  76. package/lib/estudio/dados/projetos/tour-de-saas.json +50 -0
  77. package/lib/estudio/dados/projetos-ae/antes-e-agora/ae/cenas.jsx +733 -0
  78. package/lib/estudio/dados/projetos-ae/antes-e-agora/assets/fazer_assets.py +88 -0
  79. package/lib/estudio/dados/projetos-ae/letra-em-apps/ae/cenas.jsx +402 -0
  80. package/lib/estudio/dados/projetos-ae/letra-em-apps/assets/preparar_assets.py +17 -0
  81. package/lib/estudio/dados/projetos-ae/letra-em-apps/assets/svg_para_ae.py +25 -0
  82. package/lib/estudio/dados/projetos-ae/letra-nos-apps/BRIEF-AGENTES.md +31 -0
  83. package/lib/estudio/dados/projetos-ae/letra-nos-apps/README.md +53 -0
  84. package/lib/estudio/dados/projetos-ae/letra-nos-apps/ROTEIRO-CENAS.md +69 -0
  85. package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/A-agenda.jsx +148 -0
  86. package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/B-docs.jsx +174 -0
  87. package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/C-alttab.jsx +113 -0
  88. package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/D-spotify.jsx +118 -0
  89. package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/E-notas.jsx +146 -0
  90. package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/F-jornal1.jsx +144 -0
  91. package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/G-google.jsx +153 -0
  92. package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/H-mapa.jsx +176 -0
  93. package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/I-imagens.jsx +132 -0
  94. package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/J-jornal2.jsx +191 -0
  95. package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/K-maps.jsx +184 -0
  96. package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/camera-movimentos.jsx +48 -0
  97. package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/camera.jsx +57 -0
  98. package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/card-spotify.jsx +98 -0
  99. package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/digitar.jsx +38 -0
  100. package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/jornal-comum.jsx +196 -0
  101. package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/letra.jsx +23 -0
  102. package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/letra_automatica.py +83 -0
  103. package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/montagem.jsx +74 -0
  104. package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/w-agenda/render_html.py +13 -0
  105. package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/w-agenda/util.jsx +162 -0
  106. package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/w-midia-comum.jsx +114 -0
  107. package/lib/estudio/dados/projetos-ae/letra-nos-apps/ae/wg-util.jsx +360 -0
  108. package/lib/estudio/dados/projetos-ae/letra-nos-apps/assets/F-jornal1/render_html.py +13 -0
  109. package/lib/estudio/dados/projetos-ae/letra-nos-apps/assets/render_w-midia.py +26 -0
  110. package/lib/estudio/dados/projetos-ae/letra-nos-apps/assets/w-midia-ferramentas/inclin.py +30 -0
  111. package/lib/estudio/dados/projetos-ae/letra-nos-apps/assets/w-midia-ferramentas/medir_d.py +36 -0
  112. package/lib/estudio/dados/projetos-ae/letra-nos-apps/assets/w-midia-ferramentas/medir_e.py +27 -0
  113. package/lib/estudio/dados/projetos-ae/letra-nos-apps/camera/ajustar_movimentos.py +61 -0
  114. package/lib/estudio/dados/projetos-ae/letra-nos-apps/camera/ancorar.py +74 -0
  115. package/lib/estudio/dados/projetos-ae/letra-nos-apps/camera/assar.py +47 -0
  116. package/lib/estudio/dados/projetos-ae/letra-nos-apps/camera/camera3d_jornal.py +172 -0
  117. package/lib/estudio/dados/projetos-ae/letra-nos-apps/camera/comparar.py +32 -0
  118. package/lib/estudio/dados/projetos-ae/letra-nos-apps/camera/dados_ae_jornal.py +46 -0
  119. package/lib/estudio/dados/projetos-ae/letra-nos-apps/camera/folha_contato.py +28 -0
  120. package/lib/estudio/dados/projetos-ae/letra-nos-apps/camera/homografia_jornal.py +74 -0
  121. package/lib/estudio/dados/projetos-ae/letra-nos-apps/camera/integrar.py +44 -0
  122. package/lib/estudio/dados/projetos-ae/letra-nos-apps/camera/medir_quadro_a_quadro.py +32 -0
  123. package/lib/estudio/dados/projetos-ae/letra-nos-apps/camera/mesa_2d.py +64 -0
  124. package/lib/estudio/dados/projetos-ae/letra-nos-apps/camera/plot_cenas.py +11 -0
  125. package/lib/estudio/dados/projetos-ae/letra-nos-apps/camera/retificar_quadros.py +38 -0
  126. package/lib/estudio/dados/projetos-ae/letra-nos-apps/camera/w-agenda/assar_ab.py +52 -0
  127. package/lib/estudio/dados/projetos-ae/letra-nos-apps/camera/w-agenda/medir_ab.py +59 -0
  128. package/lib/estudio/dados/projetos-ae/letra-nos-apps/camera/wg_ajustar_h.py +111 -0
  129. package/lib/estudio/dados/projetos-ae/letra-nos-apps/camera/wg_corrige_cam.py +17 -0
  130. package/lib/estudio/dados/projetos-ae/letra-nos-apps/camera/wg_ecc_cadeia.py +80 -0
  131. package/lib/estudio/dados/projetos-ae/letra-nos-apps/camera/wg_finalizar_cam.py +65 -0
  132. package/lib/estudio/dados/projetos-ae/letra-nos-apps/camera/wg_mosaico.py +61 -0
  133. package/lib/estudio/dados/projetos-ae/letra-nos-apps/guia-do-metodo/tutorial-lyric-edit-interfaces/01-gramatica-e-roteiro.md +55 -0
  134. package/lib/estudio/dados/projetos-ae/letra-nos-apps/guia-do-metodo/tutorial-lyric-edit-interfaces/02-camera.md +66 -0
  135. package/lib/estudio/dados/projetos-ae/letra-nos-apps/guia-do-metodo/tutorial-lyric-edit-interfaces/03-montagem-no-ae.md +50 -0
  136. package/lib/estudio/dados/projetos-ae/letra-nos-apps/guia-do-metodo/tutorial-lyric-edit-interfaces/04-render-e-conferencia.md +43 -0
  137. package/lib/estudio/dados/projetos-ae/letra-nos-apps/guia-do-metodo/tutorial-lyric-edit-interfaces/05-abertura-celular-mergulho.md +43 -0
  138. package/lib/estudio/dados/projetos-ae/letra-nos-apps/guia-do-metodo/tutorial-lyric-edit-interfaces.md +42 -0
  139. package/lib/estudio/dados/projetos-ae/letra-nos-apps/transicao/atraso_imagem.py +31 -0
  140. package/lib/estudio/dados/projetos-ae/letra-nos-apps/transicao/fundo.py +56 -0
  141. package/lib/estudio/dados/projetos-ae/letra-nos-apps/transicao/juntar.py +45 -0
  142. package/lib/estudio/dados/projetos-ae/letra-nos-apps/transicao/montar.py +177 -0
  143. package/lib/estudio/dados/projetos-ae/letra-nos-apps/transicao/rastreio.py +74 -0
  144. package/lib/estudio/dados/projetos-ae/letra-nos-apps/transicao/sincronia.py +18 -0
  145. package/lib/estudio/dados/projetos-ae/pinterest-inspiracao/ae/cenas.jsx +530 -0
  146. package/lib/estudio/dados/projetos-ae/pinterest-inspiracao/assets/fazer_assets.py +107 -0
  147. package/lib/estudio/dados/projetos-ae/processo-motion-100-ia/assets/pessoas/figurinha.py +46 -0
  148. package/lib/estudio/dados/projetos-ae/processo-motion-100-ia/comp-a/BRIEF-A.md +83 -0
  149. package/lib/estudio/dados/projetos-ae/processo-motion-100-ia/comp-a/audio.py +179 -0
  150. package/lib/estudio/dados/projetos-ae/processo-motion-100-ia/comp-a/confere.py +20 -0
  151. package/lib/estudio/dados/projetos-ae/processo-motion-100-ia/comp-a/dados/tempo-parte1.js +1 -0
  152. package/lib/estudio/dados/projetos-ae/processo-motion-100-ia/comp-a/dados/tempo-parte2.js +1 -0
  153. package/lib/estudio/dados/projetos-ae/processo-motion-100-ia/comp-a/gerar_emojis.py +11 -0
  154. package/lib/estudio/dados/projetos-ae/processo-motion-100-ia/comp-a/img/filmes/_indice.js +122 -0
  155. package/lib/estudio/dados/projetos-ae/processo-motion-100-ia/comp-a/js/base.js +380 -0
  156. package/lib/estudio/dados/projetos-ae/processo-motion-100-ia/comp-a/js/main.js +86 -0
  157. package/lib/estudio/dados/projetos-ae/processo-motion-100-ia/comp-a/js/p1a.js +169 -0
  158. package/lib/estudio/dados/projetos-ae/processo-motion-100-ia/comp-a/js/p1b.js +455 -0
  159. package/lib/estudio/dados/projetos-ae/processo-motion-100-ia/comp-a/js/p1c.js +389 -0
  160. package/lib/estudio/dados/projetos-ae/processo-motion-100-ia/comp-a/js/p2.js +379 -0
  161. package/lib/estudio/dados/projetos-ae/processo-motion-100-ia/comp-a/video.py +62 -0
  162. package/lib/estudio/dados/projetos-ae/processo-motion-100-ia/take-unico/README.md +65 -0
  163. package/lib/estudio/dados/projetos-ae/processo-motion-100-ia/take-unico/oraculo_take.py +137 -0
  164. package/lib/estudio/dados/projetos-ae/processo-motion-100-ia/take-unico/render_take.py +388 -0
  165. package/lib/estudio/dados/projetos-ae/processo-motion-100-ia/take-unico/take.js +235 -0
  166. package/lib/estudio/diretor.js +2 -1
  167. package/lib/estudio/editor.js +285 -0
  168. package/lib/estudio/efeitos-fabrica/terminal-digitando.jsx +2 -1
  169. package/lib/estudio/effectcraft.js +152 -0
  170. package/lib/estudio/exportar.js +181 -0
  171. package/lib/estudio/gerativo.js +44 -15
  172. package/lib/estudio/index.js +126 -5
  173. package/lib/estudio/kit/gerativo.jsx +15 -0
  174. package/lib/estudio/kit-ae/base.jsx +1146 -0
  175. package/lib/estudio/kit-ae/cenas.jsx +395 -0
  176. package/lib/estudio/kit-ae/primitivas.jsx +911 -0
  177. package/lib/estudio/kokoro.js +3 -1
  178. package/lib/estudio/maquina-diretor.js +393 -0
  179. package/lib/estudio/maquina-elementos.js +134 -0
  180. package/lib/estudio/maquina-layout.js +198 -0
  181. package/lib/estudio/maquina-som.js +478 -0
  182. package/lib/estudio/maquina-trilha.js +160 -0
  183. package/lib/estudio/maquina-voz.js +429 -0
  184. package/lib/estudio/maquina.js +516 -0
  185. package/lib/estudio/projetos.js +60 -0
  186. package/lib/estudio/remotion.js +6 -4
  187. package/lib/estudio/revisor.js +61 -0
  188. package/lib/estudio/voicestudio.js +81 -0
  189. package/lib/headless.js +71 -0
  190. package/lib/hooks.js +72 -0
  191. package/lib/local/cerebro.json +398 -12
  192. package/lib/local/entrada.js +46 -2
  193. package/lib/marca-kit.js +309 -0
  194. package/lib/mcp.js +286 -6
  195. package/lib/perigo.js +31 -3
  196. package/lib/planos.js +47 -19
  197. package/lib/preparar.js +111 -0
  198. package/lib/retomar.js +55 -0
  199. package/lib/sandbox.js +197 -0
  200. package/lib/skills.js +3 -1
  201. package/lib/tools.js +13 -4
  202. package/lib/ui.js +1 -1
  203. package/lib/video/auto.js +18 -3
  204. package/package.json +4 -2
  205. package/skills/after-effects/SKILL.md +52 -0
  206. package/skills/maquina-de-motion/SKILL.md +84 -0
  207. package/skills/motion-de-primeira/SKILL.md +33 -51
@@ -0,0 +1,389 @@
1
+ /* p1c.js — Parte 1, falas 14–22 (91,4 s → fim): Passo 3 "Som e trilha", em MODO PALCO (STORYBOARD-B.md).
2
+ * Legenda curta embaixo; o palco desenha a palavra-chave de cada frase:
3
+ * herói 🔊 + "3" · "batendo" = tecla "sound design" afundando 3× · "conversem" = 🎬 e 🔊 trocando ondas · "vivo" = ECG reto
4
+ * que ganha pulso · régua de sincronia (agulha para no marcador verde em "momento certo") · "ensinar" = 🤷 + "?" apagado no
5
+ * quadro-negro · busca real do YouTube · "difícil" = nó que se desfaz · "duas" = ✌️ → ① ② · notificação entra/sai/volta →
6
+ * vira o círculo → G (morto cinza em silêncio / vivo colorido com caneta) · "visão" = óculos pixelados descendo · "cada coisa
7
+ * com o seu som" · fecho "Passo 3 de 4 ✓ / Parte 2 →". A coluna fica oculta no trecho todo. */
8
+ (function () {
9
+ const OR = '#D97757', AZ = '#2F55F4', TINTA = '#131313', CZ = '#A19E96', VERDE = '#22B85A', CY = 830; // centro do palco neste trecho: mais baixo, perto da legenda (pedido 17/10)
10
+ const temEmoji = id => !!(window.EMOJI && EMOJI[id]);
11
+ const umDe = (...ids) => ids.find(temEmoji) || ids[ids.length - 1];
12
+ const ondas = (cor = AZ) => `<g class="o" fill="none" stroke="${cor}" stroke-width="2.1" stroke-linecap="round"><path class="o1" d="M16 9a4 4 0 010 6"/><path class="o2" d="M18.6 6.4a7.6 7.6 0 010 11.2"/></g>`;
13
+ const ALTO = (tam = 88, cor = AZ) => `<svg viewBox="0 0 24 24" width="${tam}" height="${tam}" style="position:absolute;left:0;top:0;display:block"><g transform="translate(2.6 2.4) scale(.8)">
14
+ <path d="M3.5 9h4l5-4v14l-5-4h-4z" fill="${TINTA}"/><g class="x" stroke="${CZ}" stroke-width="2.2" stroke-linecap="round" opacity="0"><path d="M16 9.2l5 5.6M21 9.2l-5 5.6"/></g>${ondas(cor)}</g></svg>`;
15
+ const caixa = (pai, css = {}) => $('div', 'janela', pai, Object.assign({ background: '#fff' }, css));
16
+ const pos = (e, x, y, w, h) => Object.assign(e.style, { position: 'absolute', left: (x - w / 2) + 'px', top: (y - h / 2) + 'px', width: w + 'px', height: h + 'px' });
17
+ // escala do palco: cada elemento principal ocupa ~70–80% da largura; grande(el, s) = camada escalada em torno do centro
18
+ const grande = (el, s) => { const d = $('div', null, el, { position: 'absolute', inset: '0', transformOrigin: `540px ${CY}px` }); d.style.transform = `scale(${s})`; return d; };
19
+ const maior = (el, s, h) => { const d = $('div', null, el, { position: 'absolute', inset: '0', transformOrigin: `456px ${h / 2}px` }); d.style.transform = `scale(${s})`; return d; };
20
+ const sombra = (el, x, y, w) => $('div', null, el, { position: 'absolute', left: (x - w / 2) + 'px', top: (y - w * 0.09) + 'px', width: w + 'px', height: (w * 0.18) + 'px', borderRadius: '50%', background: 'radial-gradient(closest-side, rgba(30,30,50,.22), rgba(30,30,50,0))' });
21
+ const vivo = (t, k = 0, a = 5) => ({ x: a * Math.sin(t * 0.9 + k * 2.3), y: a * 0.8 * Math.cos(t * 0.7 + k * 1.7), r: 1.2 * Math.sin(t * 0.6 + k) });
22
+
23
+ const T14 = F0('14'), TFIMP = F1('22') + 0.07; // 17/10: era 173,32 (antes do respiro de 1,8 s)
24
+ ocultaColuna(T14 - 0.35, TEMPO.dur + 2, 0.3);
25
+
26
+ // ═══ 14 · herói do passo 3 ═══
27
+ const tH3 = PF('14', 'o') - 0.12;
28
+ passoHeroi(3, umDe('u1f50a', 'u1f3a7', 'u1f3b5'), T14 - 0.08, tH3, { ate: TFIMP });
29
+ legenda('14', [pula(2), ['o', 'af|som', 'e a', 'af|trilha', 'sonora.']]);
30
+ // "o som e a trilha": 🔔 nasce em "som" e 🎶 em "trilha", lado a lado, balançando no ritmo
31
+ const TSOM = PF('14', 'som'), TTRI = PF('14', 'trilha');
32
+ ev(TSOM, 'pop', -0.3, 0.22); ev(TTRI, 'pop', 0.3, 0.22);
33
+ palco(tH3 + 0.02, PF('15', 'batendo') - 0.35, (el, P) => {
34
+ el = grande(el, 1.22); P.s = [sombra(el, 330, CY + 190, 260), sombra(el, 750, CY + 190, 260)]; P.a = $('div', null, el); pos(P.a, 330, CY, 330, 330); P.la = emojiLot(P.a, umDe('u1f514', 'u1f3b5'), 330);
35
+ P.b = $('div', null, el); pos(P.b, 750, CY, 330, 330); P.lb = emojiLot(P.b, 'u1f3b6', 330);
36
+ }, (t, P) => {
37
+ [[P.a, P.la, TSOM, 0], [P.b, P.lb, TTRI, 1]].forEach(([e, l, t0, i]) => { const n = nasce(t, t0, 0.45), v = vivo(t, i, 6);
38
+ tf(e, { op: n.op, s: n.s, x: v.x, y: n.y + v.y + 8 * Math.sin((t - t0) * 5.4 + i * 1.6), r: 6 * Math.sin((t - t0) * 2.7 + i), blur: n.blur }); l.toca(t, t0); });
39
+ }, { entra: false });
40
+
41
+ // ═══ 15 · "batendo" = tecla "sound design" afundando 3× · "conversem" = 🎬 e 🔊 trocando ondas ═══
42
+ legenda('15', [['Eu já venho', 'f|batendo'], 'há um tempo,', 'nos vídeos anteriores,', 'sobre af|sound af|design.', 'Isso é muito f|importante', 'para que o seu a|vídeo', 'e o áudio do seu vídeo', 'af|conversem.']);
43
+ const HITS = [PF('15', 'batendo') + 0.03, PF('15', 'um') - 0.02, PF('15', 'tempo') + 0.2], TSD = PF('15', 'sound'), TIMP = PF('15', 'importante');
44
+ HITS.forEach((h, i) => { ev(h, 'tecla', 0, 0.7); ev(h + 0.01, 'pancada', 0, 0.22); });
45
+ palco(HITS[0] - 0.45, PF('15', 'para') - 0.1, (el, P) => {
46
+ el = grande(el, 1.32); P.k = $('div', null, el); pos(P.k, 540, CY + 40, 640, 300);
47
+ P.base = $('div', null, P.k, { position: 'absolute', left: '0', right: '0', top: '26px', bottom: '-26px', borderRadius: '56px', background: '#D9D5CB', boxShadow: '0 40px 70px -24px rgba(30,30,50,.35)' });
48
+ P.top = $('div', null, P.k, { position: 'absolute', inset: '0', borderRadius: '56px', background: 'linear-gradient(#FFFFFF,#F3F1EB)', boxShadow: 'inset 0 -6px 0 rgba(0,0,0,.05), 0 0 0 1px rgba(0,0,0,.05)',
49
+ display: 'grid', placeItems: 'center', font: '600 76px/1 GS', letterSpacing: '-0.035em', color: TINTA }, '<span>sound design</span>');
50
+ P.lab = P.top.firstChild;
51
+ P.pau = $('div', null, el, { position: 'absolute', left: '0', top: '0', width: '360px', height: '40px', transformOrigin: '340px 20px' },
52
+ `<svg width="360" height="40" viewBox="0 0 360 40"><rect x="10" y="12" width="330" height="16" rx="8" fill="#C98B4E"/><rect x="10" y="12" width="330" height="6" rx="3" fill="#fff" opacity=".25"/><circle cx="22" cy="20" r="19" fill="#E9C9A0"/><circle cx="16" cy="14" r="6" fill="#fff" opacity=".45"/></svg>`);
53
+ P.ondas = [0, 1, 2].map(() => $('div', null, el, { position: 'absolute', borderRadius: '70px', border: `4px solid ${AZ}`, opacity: 0 }));
54
+ }, (t, P) => {
55
+ let fundo = 0; HITS.forEach(h => { const d = t - h; if (d > -0.02 && d < 0.32) fundo = Math.max(fundo, d < 0.05 ? (d + 0.02) / 0.07 : Math.exp(-(d - 0.05) * 14)); });
56
+ const v = vivo(t, 2, 4), imp = Math.sin(Math.PI * seg(t, TIMP - 0.05, TIMP + 0.35));
57
+ tf(P.k, { x: v.x, y: v.y, s: 1 + 0.035 * imp, r: v.r * 0.4 });
58
+ P.top.style.transform = `translateY(${(22 * fundo).toFixed(2)}px)`; P.base.style.top = (26 + 0).toFixed(0) + 'px';
59
+ const kS = ILL(seg(t, TSD - 0.05, TSD + 0.4)); P.lab.style.color = kS > 0.5 ? AZ : TINTA;
60
+ // baqueta: levanta (antecipação) e desce em cada batida; depois sai pela direita
61
+ let ang = -38; HITS.forEach((h, i) => { const a = seg(t, h - 0.2, h), b = seg(t, h, h + 0.22); if (t > h - 0.2 && t < h + 0.22) ang = t < h ? lerp(-30, 2, ILL(a) ** 2) - 10 * Math.sin(Math.PI * a) : lerp(2, -30, ILL(b)); });
62
+ const sa = ILL(seg(t, HITS[2] + 0.3, HITS[2] + 0.75)), en = ILL(seg(t, HITS[0] - 0.45, HITS[0] - 0.2));
63
+ tf(P.pau, { x: 540 + 40 + 400 * (1 - en) + 500 * sa, y: CY - 210 + v.y, r: ang, op: en * (1 - sa) });
64
+ // anel de impacto em cada batida
65
+ P.ondas.forEach((o, i) => { const u = seg(t, HITS[i], HITS[i] + 0.5), k = ILL(u); Object.assign(o.style, { left: (540 - 320 - 30 * k) + 'px', top: (CY + 40 - 150 - 30 * k) + 'px', width: (640 + 60 * k) + 'px', height: (300 + 60 * k) + 'px', opacity: (u > 0 && u < 1 ? 0.5 * (1 - u) : 0).toFixed(3) }); });
66
+ });
67
+ // conversem: 🎬 (vídeo) e 🔊 (áudio) como dois personagens; as ondas vão de um para o outro, em turnos
68
+ const TVID = PF('15', 'video'), TAUD = PF('15', 'audio'), TCV = PF('15', 'conversem');
69
+ const TURNOS = [0, 1, 2, 3, 4].map(i => TAUD + 0.45 + i * 0.36);
70
+ TURNOS.forEach((tt, i) => ev(tt + 0.05, 'pop', i % 2 ? 0.4 : -0.4, 0.15));
71
+ palco(TVID - 0.1, F0('16') - 0.15, (el, P) => {
72
+ el = grande(el, 1.18); P.a = $('div', 'sq', el, { width: '240px', height: '240px', borderRadius: '70px', top: '0' }); pos(P.a, 290, CY, 240, 240);
73
+ P.la = emojiLot(P.a, 'u1f3ac', 190); P.la.style.left = '25px'; P.la.style.top = '25px';
74
+ P.b = $('div', 'sq', el, { top: '0' }, ALTO(240)); pos(P.b, 790, CY, 240, 240); P.b.style.borderRadius = '70px';
75
+ P.o1 = P.b.querySelector('.o1'); P.o2 = P.b.querySelector('.o2');
76
+ P.w = TURNOS.map((_, i) => $('div', null, el, { position: 'absolute', left: '0', top: (CY - 100) + 'px', width: '200px', height: '200px' },
77
+ `<svg viewBox="0 0 60 60" width="200" height="200"><g fill="none" stroke="${i % 2 ? OR : AZ}" stroke-width="4.5" stroke-linecap="round"><path d="M18 18a17 17 0 010 24"/><path d="M30 10a29 29 0 010 40"/><path d="M42 3a41 41 0 010 54"/></g></svg>`));
78
+ }, (t, P) => {
79
+ const na = nasce(t, TVID, 0.45), nb = nasce(t, TAUD, 0.45);
80
+ const fala = (i) => TURNOS.reduce((m, tt, j) => (j % 2 === i ? Math.max(m, Math.sin(Math.PI * seg(t, tt - 0.05, tt + 0.3))) : m), 0);
81
+ const va = vivo(t, 3), vb = vivo(t, 4);
82
+ tf(P.a, { op: na.op, s: na.s * (1 + 0.07 * fala(0)), x: va.x + 18 * fala(1), y: va.y - 16 * fala(0), r: -5 * fala(0), blur: na.blur }); P.la.toca(t, TVID);
83
+ tf(P.b, { op: nb.op, s: nb.s * (1 + 0.07 * fala(1)), x: vb.x - 18 * fala(0), y: vb.y - 16 * fala(1), r: 5 * fala(1), blur: nb.blur });
84
+ P.o1.style.opacity = (0.35 + 0.65 * fala(1)).toFixed(3); P.o2.style.opacity = (0.2 + 0.8 * fala(1)).toFixed(3);
85
+ P.w.forEach((w, i) => { const u = seg(t, TURNOS[i], TURNOS[i] + 0.4), k = IO(u), dir = i % 2 ? -1 : 1, x0 = dir > 0 ? 400 : 680;
86
+ tf(w, { x: x0 + dir * 150 * k - 100, op: u > 0 && u < 1 ? Math.sin(Math.PI * u) : 0, s: lerp(0.7, 1.1, k) * (dir < 0 ? -1 : 1) }); });
87
+ });
88
+
89
+ // ═══ 16 · "vivo" = ECG reto que ganha pulso · régua de sincronia · "momento certo" = agulha para no marcador verde ═══
90
+ legenda('16', ['Não adianta nada você ter', 'um a|vídeo que seja muito bom', 'e muito bem editado', 'se ele não estiver af|vivo.', 'Quem dá esse f|avivamento', 'para o seu vídeo',
91
+ 'é justamente a sua', ['af|trilha', 'af|sonora', logo('spotify-icon.svg', { gira: false, tam: 84 })], 'e os seus af|elementos sonoros,', 'que você usa em cada', 'componente que aparece', 'na tela, no af|momento af|certo.']);
92
+ const TV16 = PF('16', 'vivo') + 0.05, PER = 0.82, VPX = 260;
93
+ const BIPS = [0, 1, 2, 3].map(k => TV16 + 0.246 + k * PER).filter(t => t < PF('16', 'trilha') - 0.1);
94
+ BIPS.forEach(b => ev(b, 'toque', 0.3, 0.32));
95
+ const ecgF = p => 0.1 * Math.exp(-(((p - 0.15) / 0.03) ** 2)) - 0.12 * Math.exp(-(((p - 0.27) / 0.012) ** 2)) + 1 * Math.exp(-(((p - 0.3) / 0.012) ** 2))
96
+ - 0.28 * Math.exp(-(((p - 0.33) / 0.014) ** 2)) + 0.24 * Math.exp(-(((p - 0.52) / 0.05) ** 2));
97
+ palco(F0('16') - 0.05, PF('16', 'trilha') - 0.1, (el, P) => {
98
+ el = grande(el, 1.12); P.c = caixa(el, { inset: 'auto' }); pos(P.c, 540, CY, 860, 470);
99
+ P.c.style.backgroundImage = 'linear-gradient(rgba(19,19,19,.045) 1px, transparent 1px), linear-gradient(90deg, rgba(19,19,19,.045) 1px, transparent 1px)'; P.c.style.backgroundSize = '43px 43px';
100
+ P.hd = $('div', null, P.c, { position: 'absolute', left: '40px', top: '34px', display: 'flex', alignItems: 'center', gap: '16px', font: '600 46px/1 GS', letterSpacing: '-0.02em', color: CZ },
101
+ `<svg viewBox="0 0 24 24" width="50" height="50"><path class="cor" d="M12 20.5s-7.4-4.5-9.3-9C1.4 8.4 3.4 5 6.8 5c2 0 3.6 1.1 5.2 3 1.6-1.9 3.2-3 5.2-3 3.4 0 5.4 3.4 4.1 6.5-1.9 4.5-9.3 9-9.3 9z" fill="${CZ}"/></svg><span class="bpm">— bpm</span>`);
102
+ P.cor = P.hd.querySelector('.cor'); P.bpm = P.hd.querySelector('.bpm'); P.ic = P.hd.firstChild;
103
+ P.svg = $('div', null, P.c, { position: 'absolute', left: '0', top: '120px', width: '860px', height: '300px' }, `<svg width="860" height="300"><polyline class="ln" fill="none" stroke="${CZ}" stroke-width="9" stroke-linejoin="round" stroke-linecap="round"/><circle class="pt" r="10" fill="${CZ}"/></svg>`);
104
+ P.ln = P.svg.querySelector('.ln'); P.pt = P.svg.querySelector('.pt');
105
+ }, (t, P) => {
106
+ const W2 = 780, X0 = 40, base = 175, A = 150, liga = t >= TV16, kc = ILL(seg(t, TV16, TV16 + 0.3)), cor = liga ? '#E5484D' : CZ;
107
+ const pts = []; for (let x = 0; x <= W2; x += 5) { const tau = t - (W2 - x) / VPX, amp = tau >= TV16 ? 1 : 0, p = (((tau - TV16) % PER) + PER) % PER / PER;
108
+ const y = base - amp * A * ecgF(p) + 1.2 * Math.sin(tau * 31 + x * 0.05) * (1 - amp); pts.push(`${(X0 + x).toFixed(1)},${y.toFixed(1)}`); }
109
+ P.ln.setAttribute('points', pts.join(' ')); P.ln.setAttribute('stroke', cor);
110
+ const last = pts[pts.length - 1].split(','); P.pt.setAttribute('cx', last[0]); P.pt.setAttribute('cy', last[1]); P.pt.setAttribute('fill', cor);
111
+ let bate = 0; BIPS.forEach(b => { const d = t - b; if (d > 0 && d < 0.3) bate = Math.max(bate, Math.exp(-d * 12)); });
112
+ P.cor.setAttribute('fill', cor); P.bpm.textContent = liga ? '72 bpm' : '— bpm'; P.hd.style.color = liga ? TINTA : CZ;
113
+ tf(P.ic, { s: 1 + 0.25 * bate + 0.2 * Math.sin(Math.PI * seg(t, TV16, TV16 + 0.3)) });
114
+ tf(P.c, { s: 1 + 0.012 * bate + 0.02 * kc * (1 - seg(t, TV16 + 0.3, TV16 + 0.8)) });
115
+ });
116
+ // régua de sincronia: a agulha passa por WhatsApp, Instagram e Spotify (cada um nasce com o seu som no instante exato)
117
+ // e, em "momento certo", para em cima do marcador, que acende verde
118
+ const T0A = PF('16', 'que', 1) + 0.02, T1A = PF('16', 'aparece') + 0.1, TMC0 = PF('16', 'momento') - 0.2, TMC1 = PF('16', 'certo') + 0.05;
119
+ const X0A = 150, XS = [300, 520, 730], XM = 850, LOGOS = ['whatsapp-icon.svg', 'instagram-icon.svg', 'spotify-icon.svg'];
120
+ const agulha = t => t < TMC0 ? lerp(X0A, 760, IO(seg(t, T0A, T1A))) : lerp(760, XM, ILL(seg(t, TMC0, TMC1)));
121
+ const TC = XS.map(x => { for (let t = T0A; t <= T1A; t += 0.004) if (agulha(t) >= x) return t; return T1A; });
122
+ TC.forEach((t, i) => ev(t, 'pop', (XS[i] - 456) / 456 * 0.6, 0.32)); ev(TMC1, 'clique', 0.5, 0.45);
123
+ const barras = (n, alt, cor, sem) => Array.from({ length: n }, (_, i) => { const h = alt * (0.25 + 0.75 * Math.abs(Math.sin(i * 1.7 + sem) * Math.cos(i * 0.6 + sem * 2))); return `<i style="display:block;width:6px;border-radius:3px;height:${h.toFixed(0)}px;background:${cor}"></i>`; }).join('');
124
+ const linhaBarras = (pai, x, w, n, alt, cor, sem) => $('div', null, pai, { position: 'absolute', left: x + 'px', top: '318px', width: w + 'px', height: '0px', display: 'flex', alignItems: 'center', justifyContent: 'space-between' }, barras(n, alt, cor, sem));
125
+ palco(PF('16', 'trilha') - 0.1, F0('17') - 0.2, bloco({ h: 420, kind: 'abre',
126
+ monta(el, B) { el = maior(el, 1.1, 420);
127
+ B.c = caixa(el);
128
+ const ico = (svg, y) => $('div', null, B.c, { position: 'absolute', left: '40px', top: y + 'px', width: '56px', height: '56px' }, svg);
129
+ ico(`<svg viewBox="0 0 24 24" width="56" height="56"><rect x="2.5" y="5" width="19" height="14" rx="3.6" fill="none" stroke="${CZ}" stroke-width="1.9"/><path d="M10 9.2l5 2.8-5 2.8z" fill="${CZ}"/></svg>`, 104);
130
+ ico(`<svg viewBox="0 0 24 24" width="56" height="56"><path d="M3.5 9h4l5-4v14l-5-4h-4z" fill="${CZ}"/>${ondas(CZ)}</svg>`, 290);
131
+ $('div', null, B.c, { position: 'absolute', left: X0A + 'px', right: '50px', top: '224px', height: '2px', background: 'rgba(19,19,19,.07)' });
132
+ B.trilha = linhaBarras(B.c, X0A, 862 - X0A, 64, 26, 'rgba(19,19,19,.13)', 0.3);
133
+ B.comps = XS.map((x, i) => { const q = $('div', 'sq', B.c, { left: (x - 52) + 'px', top: '78px', width: '104px', height: '104px', borderRadius: '30px' });
134
+ const im = $('img', null, q, { left: '0', top: '0', width: '104px', height: '104px', objectFit: 'cover' }); im.src = LOGO(LOGOS[i]); return q; });
135
+ B.blips = XS.map((x, i) => linhaBarras(B.c, x - 60, 120, 13, 92, i === 1 ? OR : AZ, i * 2.3));
136
+ B.mk = $('div', null, B.c, { position: 'absolute', left: (XM - 34) + 'px', top: '96px', width: '68px', height: '68px', borderRadius: '50%', boxSizing: 'border-box', border: `4px dashed ${CZ}`, display: 'grid', placeItems: 'center' },
137
+ `<svg viewBox="0 0 24 24" width="40" height="40"><path d="M6.5 12.4l3.6 3.6 7.4-7.6" fill="none" stroke="#fff" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" pathLength="1" stroke-dasharray="0 1"/></svg>`);
138
+ B.mkp = B.mk.querySelector('path');
139
+ B.ag = $('div', null, B.c, { position: 'absolute', left: '0', top: '34px', width: '4px', height: '356px', borderRadius: '2px', background: TINTA },
140
+ `<i style="position:absolute;left:-9px;top:-10px;width:22px;height:22px;border-radius:50%;background:${TINTA}"></i>`);
141
+ B.halo = $('div', null, B.c, { position: 'absolute', left: (XM - 80) + 'px', top: '50px', width: '160px', height: '160px', borderRadius: '50%', background: `radial-gradient(closest-side, rgba(34,184,90,.35), rgba(34,184,90,0))`, opacity: 0 });
142
+ },
143
+ seek(t, B) {
144
+ abreJanela(t, B.c, B.t);
145
+ const x = agulha(t); tf(B.ag, { x: x - 2, op: seg(t, T0A - 0.35, T0A - 0.05) });
146
+ B.trilha.style.clipPath = `inset(-100px ${(100 - 100 * clamp((x - X0A) / (862 - X0A))).toFixed(2)}% -100px 0)`;
147
+ B.comps.forEach((q, i) => { const n = nasce(t, TC[i]); tf(q, { op: n.op, s: n.s, y: n.y + 3 * Math.sin((t + i) * 1.6), blur: n.blur }); });
148
+ B.blips.forEach((b, i) => { const k = ILL(seg(t, TC[i], TC[i] + 0.22)), d = 1 - 0.35 * ILL(seg(t, TC[i] + 0.3, TC[i] + 1.2)); b.style.transform = `scaleY(${(k * d).toFixed(3)})`; b.style.opacity = clamp(k * 3).toFixed(3); });
149
+ const nm = nasce(t, TMC0 - 0.3, 0.4), kv = ILL(seg(t, TMC1 - 0.02, TMC1 + 0.25)), pr = Math.sin(Math.PI * seg(t, TMC1 - 0.02, TMC1 + 0.3));
150
+ tf(B.mk, { op: nm.op, s: nm.s * (1 + 0.18 * pr) }); B.mk.style.background = kv > 0.02 ? `rgba(34,184,90,${kv.toFixed(3)})` : 'transparent'; B.mk.style.borderColor = kv > 0.5 ? VERDE : CZ;
151
+ B.mk.style.borderStyle = kv > 0.5 ? 'solid' : 'dashed'; B.mkp.setAttribute('stroke-dasharray', `${ILL(seg(t, TMC1 + 0.05, TMC1 + 0.35)).toFixed(3)} 1`);
152
+ B.halo.style.opacity = (kv * (0.7 + 0.3 * Math.sin((t - TMC1) * 4))).toFixed(3);
153
+ B.ag.style.background = kv > 0.5 ? VERDE : TINTA; B.ag.firstChild.style.background = kv > 0.5 ? VERDE : TINTA;
154
+ } }), { y: CY });
155
+
156
+ // ═══ 17 · "ensinar" = 🤷 + "?" no quadro-negro, apagado com humor · busca real do YouTube ═══
157
+ legenda('17', ['Como eu já falei', 'nos vídeos anteriores,', ['não tem como eu te', 'f|ensinar'], 'af|sound af|design.', 'Isso é algo muito', 'f|particular seu,', 'mas dá para você praticar', 'pesquisando sobre sound design',
158
+ ['no', logo('youtube-icon.svg', { gira: false, tam: 84 }), 'f|YouTube.']]);
159
+ const TES = PF('17', 'ensinar'), TAP = TES + 0.85, TGZ = F0('17') + 0.5;
160
+ ev(TGZ, 'risco', -0.2, 0.25); ev(TES + 0.02, 'traco', 0.1, 0.3); ev(TES + 0.25, 'pop', 0.4, 0.25); ev(TAP, 'papel', 0, 0.3);
161
+ palco(F0('17') - 0.05, PF('17', 'mas') - 0.1, (el, P) => {
162
+ el = grande(el, 1.14); P.q = $('div', null, el, { position: 'absolute', borderRadius: '30px', background: '#8B6A48', boxShadow: '0 50px 90px -30px rgba(40,30,20,.45)' }); pos(P.q, 500, CY, 820, 540);
163
+ P.lousa = $('div', null, P.q, { position: 'absolute', left: '22px', top: '22px', right: '22px', bottom: '22px', borderRadius: '14px', background: 'radial-gradient(120% 120% at 30% 20%, #2F4A3B, #1F3329)', overflow: 'hidden' });
164
+ P.esc = $('div', null, P.lousa, { position: 'absolute', inset: '0' });
165
+ P.tx = $('div', null, P.esc, { position: 'absolute', left: '60px', top: '58px', font: '600 72px/1 GS', letterSpacing: '-0.02em', color: 'rgba(245,245,235,.88)', filter: 'blur(.6px)', whiteSpace: 'nowrap' }, 'sound design =');
166
+ P.qm = $('div', null, P.esc, { position: 'absolute', left: '290px', top: '150px', width: '220px', height: '300px' },
167
+ `<svg viewBox="0 0 22 30" width="220" height="300" style="overflow:visible"><path d="M4 9a7 7 0 1 1 10.5 6c-2.6 1.6-3.5 3-3.5 6.4" fill="none" stroke="rgba(245,245,235,.9)" stroke-width="2.6" stroke-linecap="round" pathLength="1" stroke-dasharray="0 1"/><circle cx="11" cy="27.2" r="1.7" fill="rgba(245,245,235,.9)" opacity="0"/></svg>`);
168
+ P.qp = P.qm.querySelector('path'); P.qd = P.qm.querySelector('circle');
169
+ P.mancha = $('div', null, P.lousa, { position: 'absolute', inset: '0', opacity: 0, background: 'radial-gradient(60% 40% at 45% 45%, rgba(245,245,235,.13), rgba(245,245,235,0))' });
170
+ P.apag = $('div', null, P.q, { position: 'absolute', left: '0', top: '0', width: '200px', height: '96px', borderRadius: '18px', background: 'linear-gradient(#5B6B8C 0 58%, #F1EEE6 58%)', boxShadow: '0 20px 30px -10px rgba(0,0,0,.4)' });
171
+ P.sh = $('div', null, el); pos(P.sh, 840, CY + 190, 340, 340); P.shl = emojiLot(P.sh, 'u1f937-200d-2642', 340);
172
+ }, (t, P) => {
173
+ const v = vivo(t, 5, 4); tf(P.q, { x: v.x, y: v.y, r: v.r * 0.5 });
174
+ const kt = seg(t, TGZ, TGZ + 0.9); P.tx.style.clipPath = `inset(0 ${(100 - 100 * kt).toFixed(1)}% 0 0)`;
175
+ P.qp.setAttribute('stroke-dasharray', `${IO(seg(t, TES - 0.05, TES + 0.4)).toFixed(3)} 1`); P.qd.setAttribute('opacity', seg(t, TES + 0.4, TES + 0.45).toFixed(2));
176
+ // apagador: passa em 2 vaivéns da esquerda para a direita; o que fica para trás some (sobra a mancha de giz)
177
+ const ua = seg(t, TAP, TAP + 0.7), ax = lerp(-40, 700, ua), ay = 170 + 110 * Math.sin(ua * Math.PI * 4);
178
+ tf(P.apag, { x: ax, y: ay, r: -8 + 10 * Math.sin(ua * 12), op: ua > 0 && ua < 1 ? 1 : 0 });
179
+ P.esc.style.webkitMaskImage = P.esc.style.maskImage = ua > 0 ? `linear-gradient(90deg, transparent ${(ua * 120 - 14).toFixed(1)}%, #000 ${(ua * 120 + 4).toFixed(1)}%)` : 'none';
180
+ P.mancha.style.opacity = (0.9 * seg(t, TAP + 0.1, TAP + 0.6)).toFixed(3);
181
+ const n = nasce(t, TES + 0.25, 0.5); tf(P.sh, { op: n.op, s: n.s, y: n.y + 6 * Math.sin(t * 1.5), blur: n.blur }); P.shl.toca(t, TES + 0.25);
182
+ });
183
+ // busca do YouTube: a barra digita "sound design" e o resultado real (NaughtyyJuan) nasce embaixo
184
+ const BUSCA = 'sound design', TD = PF('17', 'pesquisando') + 0.12, CPS = 13, TR = PF('17', 'youtube');
185
+ ev(TD, 'digita', 0.2, 0.3); ev(TD + 0.45, 'digita', 0.2, 0.3); ev(TR, 'aparece', 0, 0.25);
186
+ palco(PF('17', 'mas') - 0.1, F0('18') - 0.2, bloco({ h: 470, kind: 'abre',
187
+ monta(el, B) { el = maior(el, 1.1, 470);
188
+ B.c = caixa(el, { fontFamily: 'Roboto, Arial, sans-serif', color: '#0F0F0F' });
189
+ const wm = $('img', null, B.c, { position: 'absolute', left: '36px', top: '46px', height: '44px', width: 'auto' }); wm.src = LOGO('youtube-wordmark.svg');
190
+ B.barra = $('div', null, B.c, { position: 'absolute', left: '300px', right: '36px', top: '34px', height: '68px', borderRadius: '34px', boxShadow: 'inset 0 0 0 1.5px #D3D3D3', overflow: 'hidden' });
191
+ B.txt = $('span', null, B.barra, { position: 'absolute', left: '30px', top: '16px', font: '400 32px/36px Roboto, Arial, sans-serif', whiteSpace: 'nowrap' });
192
+ $('div', null, B.barra, { position: 'absolute', right: '0', top: '0', width: '92px', height: '68px', background: '#F8F8F8', boxShadow: 'inset 1.5px 0 0 #D3D3D3' },
193
+ '<svg viewBox="0 0 24 24" width="34" height="34" style="position:absolute;left:28px;top:17px"><circle cx="10.5" cy="10.5" r="6.5" fill="none" stroke="#0F0F0F" stroke-width="2"/><path d="M15.5 15.5L21 21" stroke="#0F0F0F" stroke-width="2.2" stroke-linecap="round"/></svg>');
194
+ B.res = $('div', null, B.c, { position: 'absolute', left: '36px', top: '136px', right: '36px', height: '300px' });
195
+ const th = $('img', null, B.res, { position: 'absolute', left: '0', top: '0', width: '480px', height: '270px', borderRadius: '18px', objectFit: 'cover' }); th.src = 'img/p1c/yt-naughtyyjuan-thumb.jpg';
196
+ $('div', null, B.res, { position: 'absolute', left: '508px', top: '4px', width: '332px', font: '500 32px/1.28 Roboto, Arial, sans-serif', color: '#0F0F0F' }, 'Everything I Know About Sound Design');
197
+ $('div', null, B.res, { position: 'absolute', left: '508px', top: '182px', display: 'flex', alignItems: 'center', gap: '14px', font: '400 25px/1 Roboto, Arial, sans-serif', color: '#606060' },
198
+ '<i style="display:block;width:44px;height:44px;border-radius:50%;background:linear-gradient(135deg,#B06BFF,#3B1A73)"></i>NaughtyyJuan');
199
+ },
200
+ seek(t, B) {
201
+ abreJanela(t, B.c, B.t);
202
+ const n = clamp(Math.floor((t - TD) * CPS), 0, BUSCA.length), car = n < BUSCA.length || Math.floor(t * 2.2) % 2 === 0;
203
+ B.txt.innerHTML = (n ? BUSCA.slice(0, n) : '<span style="color:#888">Pesquisar</span>') + (t > TD - 0.3 && car ? '<i style="display:inline-block;width:2px;height:34px;background:#0F0F0F;vertical-align:-6px;margin-left:2px"></i>' : '');
204
+ const k = ILL(seg(t, TR, TR + 0.45)); tf(B.res, { op: clamp(k * 2), y: (1 - k) * 40, blur: Math.pow(1 - k, 2) * 16 });
205
+ } }), { y: CY });
206
+
207
+ // ═══ 18 · "difícil" = nó que se desfaz · "duas" = ✌️ → ① ② · (o palco da notificação começa em "com uma entrada") ═══
208
+ legenda('18', [['Não é tão', 'f|difícil', 'quanto parece,'], 'e é muito mais af|simples,', 'porque você só tem que', ['entender', 'f|duas', 'coisas:'], 'o elemento tem que ser', 'af|vivo no seu vídeo,',
209
+ 'com uma af|entrada e uma af|saída;', 'e, nesse meio-tempo', 'que ele está na tela,', 'ele tem que af|conversar', 'com o seu vídeo.']);
210
+ const TDF = PF('18', 'dificil'), TDS0 = PF('18', 'quanto'), TDS1 = PF('18', 'simples') + 0.1;
211
+ ev(TDF - 0.05, 'risco', 0, 0.2); ev(TDS1, 'pop', 0.2, 0.18);
212
+ palco(F0('18') - 0.05, PF('18', 'duas') - 0.25, (el, P) => {
213
+ P.s = $('div', null, el, { position: 'absolute', left: '0', top: '0', width: '1080px', height: '1500px' }, `<svg width="1080" height="1500"><path class="fio" fill="none" stroke="${OR}" stroke-width="24" stroke-linecap="round" stroke-linejoin="round" pathLength="1" stroke-dasharray="0 1"/><circle class="p1" r="26" fill="${OR}"/><circle class="p2" r="26" fill="${OR}"/></svg>`);
214
+ P.f = P.s.querySelector('.fio'); P.p1 = P.s.querySelector('.p1'); P.p2 = P.s.querySelector('.p2');
215
+ }, (t, P) => {
216
+ // trocoide: com r grande ela dá laços (nó); r → 0 vira uma linha reta. Puxada pelas pontas enquanto desfaz
217
+ const k = IO(seg(t, TDS0, TDS1)), r = lerp(118, 0, k), n = 5, L = lerp(800, 940, k), x0 = 540 - L / 2, tremor = (1 - k) * 4 * Math.sin(t * 23);
218
+ const pts = []; for (let i = 0; i <= 240; i++) { const s = i / 240, a = 2 * Math.PI * n * s, env = Math.sin(Math.PI * s) ** 0.6;
219
+ const x = x0 + L * s - r * env * Math.sin(a) * 1.15, y = CY + r * env * (Math.cos(a) - 1) * 0.9 + r * env * 0.9 + tremor * Math.sin(a * 0.5) - r * 0.45 * env; pts.push((i ? 'L' : 'M') + x.toFixed(1) + ' ' + y.toFixed(1)); }
220
+ P.f.setAttribute('d', pts.join(' ')); P.f.setAttribute('stroke-dasharray', `${ILL(seg(t, TDF - 0.1, TDF + 0.5)).toFixed(3)} 1`);
221
+ const vis = seg(t, TDF + 0.3, TDF + 0.5); [P.p1, P.p2].forEach((c, i) => { c.setAttribute('cx', (i ? x0 + L : x0).toFixed(1)); c.setAttribute('cy', CY); c.setAttribute('opacity', vis.toFixed(2)); });
222
+ P.f.setAttribute('stroke', k > 0.98 ? TINTA : OR); [P.p1, P.p2].forEach(c => c.setAttribute('fill', k > 0.98 ? TINTA : OR));
223
+ });
224
+ const TDU = PF('18', 'duas'), TSPL = PF('18', 'elemento') - 0.15;
225
+ ev(TDU, 'pop', 0, 0.28); ev(TSPL + 0.05, 'pop', -0.4, 0.22); ev(TSPL + 0.17, 'pop', 0.4, 0.22);
226
+ const ID_V = umDe('u270c', 'u270c-fe0f');
227
+ palco(TDU - 0.1, PF('18', 'com') - 0.15, (el, P) => {
228
+ el = grande(el, 1.55); sombra(el, 540, CY + 225, 300); P.v = $('div', null, el); pos(P.v, 540, CY, 400, 400);
229
+ if (temEmoji(ID_V)) P.vl = emojiLot(P.v, ID_V, 400); else P.v.innerHTML = '<div style="font:330px/400px \'Segoe UI Emoji\',\'Apple Color Emoji\',sans-serif;text-align:center">✌️</div>';
230
+ P.n = [1, 2].map(i => { const d = $('div', null, el, { position: 'absolute', borderRadius: '50%', boxSizing: 'border-box', border: `10px solid ${AZ}`, color: AZ, font: '600 190px/1 GS', letterSpacing: '-0.04em', display: 'grid', placeItems: 'center', background: '#fff', boxShadow: '0 40px 70px -24px rgba(47,85,244,.35)' }, String(i)); pos(d, 540, CY, 300, 300); return d; });
231
+ }, (t, P) => {
232
+ const nv = nasce(t, TDU, 0.45), kd = ILL(seg(t, TSPL - 0.1, TSPL + 0.25));
233
+ tf(P.v, { op: nv.op * (1 - kd), s: nv.s * (1 - 0.5 * kd), r: 8 * Math.sin((t - TDU) * 3.4) * (1 - kd), y: nv.y, blur: nv.blur + 12 * kd }); if (P.vl) P.vl.toca(t, TDU);
234
+ const vi = PF('18', 'vivo') - 0.1;
235
+ P.n.forEach((d, i) => { const n = nasce(t, TSPL + i * 0.12, 0.45), dx = (i ? 1 : -1) * 168 * ILL(seg(t, TSPL + i * 0.12, TSPL + 0.4 + i * 0.12));
236
+ const foco = i === 0 ? ILL(seg(t, vi, vi + 0.3)) : 0; tf(d, { x: dx, y: n.y + 6 * Math.sin(t * 1.6 + i), op: n.op * (i === 1 ? 1 - 0.55 * ILL(seg(t, vi, vi + 0.3)) : 1), s: n.s * (1 + 0.1 * foco), blur: n.blur }); });
237
+ });
238
+
239
+ // ═══ palco 18–21: notificação entra/sai/volta e conversa → encolhe e vira o CÍRCULO → card do G → demo morto / demo vivo ═══
240
+ const TA = PF('18', 'com') - 0.05, TE = PF('18', 'entrada'), TS = PF('18', 'saida'), TMEIO = PF('18', 'meio-tempo'), TCONV = PF('18', 'conversar');
241
+ const TCIRC = PF('19', 'circulo') - 0.4, TPART = PF('19', 'particula'), TG0 = PF('19', 'escorrer'), TG1 = PF('19', 'tela') + 0.05, TGOO = PF('19', 'google');
242
+ const DM = CN('demo_morto'), DV = CN('demo_vivo'), TM0 = DM.t0 + 0.08, TV0 = DV.t0 + 0.08, DG = 2.6, TFIM = DV.t1 + 0.12;
243
+ const C = { x: 540, y: CY }, A = { x: 84, y: CY - 256, w: 912, h: 513, r: 34 }, D = { x: 540 - 36, y: CY - 36, w: 72, h: 72, r: 36 }, GC = { x: 160, y: CY - 380, w: 760, h: 760, r: 44 };
244
+ const lr = (P, Q, k) => ({ x: lerp(P.x, Q.x, k), y: lerp(P.y, Q.y, k), w: lerp(P.w, Q.w, k), h: lerp(P.h, Q.h, k), r: lerp(P.r, Q.r, k) });
245
+ const uG = k => { k = clamp(k); return 0.35 * k + 0.65 * (1 - Math.cos(Math.PI * k)) / 2; };
246
+ const GSEG = ['M18.223 5.777 A8.8 8.8 0 0 0 4.159 8.005', 'M4.159 8.005 A8.8 8.8 0 0 0 4.159 15.995', 'M4.159 15.995 A8.8 8.8 0 0 0 16.921 19.296', 'M16.921 19.296 A8.8 8.8 0 0 0 20.800 12.000 H12'];
247
+ const GCOR = ['#EA4335', '#FBBC05', '#34A853', '#4285F4'], GPAN = [0.3, -0.6, -0.1, 0.6], GPATH = 'M18.223 5.777 A8.8 8.8 0 1 0 20.800 12.000 H12';
248
+ VIDEOS.push({ nome: 'silencio-demo-morto', t0: DM.t0, t1: DM.t1, trilha: 'para', alvo: -20 }); // sem arquivo: só faz a trilha PARAR (silêncio total)
249
+ ev(TA, 'abre', 0, 0.22); ev(TE, 'notifica', 0, 0.35); ev(TS + 0.08, 'sai', 0, 0.22); ev(TMEIO, 'notifica', 0, 0.28);
250
+ ev(TCONV + 0.02, 'pop', -0.2, 0.18); ev(TCONV + 0.5, 'pop', 0.2, 0.18); ev(TCIRC, 'encolhe', 0, 0.25); ev(TPART, 'abre', 0, 0.22); ev(TGOO, 'pop', -0.3, 0.2);
251
+ legenda('19', ['Por exemplo:', ['olha esse', 'f|círculo', 'aqui.'], 'Eu quero que ele seja', ['como se fosse uma', 'f|partícula'], 'que vai af|escorrer', 'pelo vídeo inteiro,', 'fazendo um f|G', 'no meio da tela',
252
+ 'para construir a marca', ['do', logo('google-g.svg', { gira: false, tam: 84 }), 'f|Google.']]);
253
+ legenda('20', ['Se essa partícula for', 'apenas um elemento', 'sem c|som, sem efeito sonoro,', 'desenhando na tela,', ['ela é um elemento', 'cf|morto.', emoji('u1fae0')]], { ate: DM.t0 - 0.1 });
254
+ legenda('21', ['Agora, a mesma partícula,', 'fazendo a mesma coisa,', 'só que agora sendo um', 'elemento af|vivo.'], { ate: DV.t0 - 0.1 });
255
+
256
+ palco(TA - 0.1, TFIM + 0.7, (r, c) => {
257
+ r = grande(r, 1.08);
258
+ c.w = $('div', null, r, { position: 'absolute', inset: '0', transformOrigin: `${C.x}px ${C.y}px` });
259
+ c.sh = $('div', 'janela', c.w, { inset: 'auto', background: '#111' });
260
+ c.vid = $('div', null, c.sh, { position: 'absolute', inset: '0' }); c.f = filme(c.vid, 'glass-hub');
261
+ c.nt = $('div', null, c.sh, { position: 'absolute', left: '36px', top: '0', width: '840px', height: '150px', borderRadius: '34px', background: 'rgba(250,250,248,.9)', backdropFilter: 'blur(18px)',
262
+ boxShadow: '0 24px 50px -12px rgba(0,0,0,.45)', fontFamily: 'GS, sans-serif', color: TINTA },
263
+ `<img src="${LOGO('instagram-icon-5000.png')}" style="position:absolute;left:26px;top:31px;width:88px;height:88px;border-radius:22px">
264
+ <div style="position:absolute;left:140px;top:26px;right:30px;display:flex;justify-content:space-between;font:500 23px/1 GS;color:#7A786F;letter-spacing:.04em"><span>INSTAGRAM</span><span>agora</span></div>
265
+ <div style="position:absolute;left:140px;top:60px;font:600 33px/1.15 GS;letter-spacing:-.01em">Nova mensagem</div>
266
+ <div style="position:absolute;left:140px;top:100px;font:500 29px/1.2 GS;color:#3D3C38">como você fez esse vídeo?</div>`);
267
+ c.g = $('div', null, c.w, { position: 'absolute', left: (C.x - 300) + 'px', top: (C.y - 300) + 'px', width: '600px', height: '600px' },
268
+ `<svg viewBox="0 0 24 24" width="600" height="600" style="overflow:visible">
269
+ <defs><mask id="p1cGM" maskUnits="userSpaceOnUse" x="-4" y="-4" width="32" height="32"><path d="${GPATH}" fill="none" stroke="#fff" stroke-width="1.6" pathLength="1" stroke-dasharray="0 1"/></mask>
270
+ <filter id="p1cGlow" x="-50%" y="-50%" width="200%" height="200%"><feGaussianBlur stdDeviation=".7"/></filter></defs>
271
+ <g class="guia" mask="url(#p1cGM)"><path d="${GPATH}" fill="none" stroke="rgba(19,19,19,.30)" stroke-width=".3" stroke-dasharray=".02 .7" stroke-linecap="round"/></g>
272
+ <path class="cz" d="${GPATH}" fill="none" stroke="#C9C6BE" stroke-width="4.4" pathLength="1" stroke-dasharray="0 1"/>
273
+ <g class="glow" filter="url(#p1cGlow)" fill="none" stroke-width="5.2">${GSEG.map((d, i) => `<path d="${d}" stroke="${GCOR[i]}" pathLength="1" stroke-dasharray="0 1"/>`).join('')}</g>
274
+ <g class="tr" fill="none" stroke-width="4.4">${GSEG.map((d, i) => `<path d="${d}" stroke="${GCOR[i]}" pathLength="1" stroke-dasharray="0 1"/>`).join('')}</g>
275
+ <image class="logo" href="${LOGO('google-g.svg')}" x="0" y="0" width="24" height="24" opacity="0"/>
276
+ <circle class="halo" r="2.2" fill="#4285F4" opacity="0" filter="url(#p1cGlow)"/><circle class="dot" r="1.05" fill="${TINTA}"/>
277
+ <path class="cam" d="${GPATH}" fill="none" stroke="none"/></svg>`);
278
+ const q = s => c.g.querySelector(s);
279
+ c.guiaM = q('mask path'); c.guia = q('.guia'); c.cz = q('.cz'); c.glow = q('.glow'); c.glowP = [...c.glow.querySelectorAll('path')]; c.tr = [...q('.tr').querySelectorAll('path')];
280
+ c.logo = q('.logo'); c.dot = q('.dot'); c.halo = q('.halo'); c.cam = q('.cam');
281
+ const ls = GSEG.map(d => { const p = document.createElementNS('http://www.w3.org/2000/svg', 'path'); p.setAttribute('d', d); q('svg').appendChild(p); const L = p.getTotalLength(); p.remove(); return L; });
282
+ c.LT = ls.reduce((a, b) => a + b, 0); c.C0 = ls.map((_, i) => ls.slice(0, i).reduce((a, b) => a + b, 0)); c.LS = ls;
283
+ // demo vivo: um som de caneta por traço de cor (v = duração do traço)
284
+ const kDe = s => { let lo = 0, hi = 1; for (let i = 0; i < 40; i++) { const m = (lo + hi) / 2; if (uG(m) < s) lo = m; else hi = m; } return (lo + hi) / 2; };
285
+ c.TSEG = c.C0.map(c0 => TV0 + kDe(c0 / c.LT) * DG);
286
+ c.TSEG.forEach((ts, i) => { const te = i < 3 ? c.TSEG[i + 1] : TV0 + DG; ev(ts, 'desenha', GPAN[i], +(te - ts).toFixed(3)); });
287
+ c.gl = $('img', null, c.w, { position: 'absolute', left: (GC.x + 34) + 'px', top: (GC.y + 34) + 'px', width: '64px', height: '64px' }); c.gl.src = LOGO('google-g.svg');
288
+ }, (t, c) => {
289
+ // forma: palco 16:9 → círculo → card do G
290
+ const kab = ILL(seg(t, TA, TA + 0.55)), kc = ILL(seg(t, TCIRC, TCIRC + 0.5)), kg = ILL(seg(t, TPART - 0.05, TPART + 0.55));
291
+ const R = lr(lr(A, D, kc), GC, kg); Object.assign(c.sh.style, { left: R.x.toFixed(1) + 'px', top: R.y.toFixed(1) + 'px', width: R.w.toFixed(1) + 'px', height: R.h.toFixed(1) + 'px', borderRadius: R.r.toFixed(1) + 'px' });
292
+ const respira = kc > 0.99 && kg < 0.01 ? 1 + 0.08 * Math.sin((t - TCIRC) * 3.2) : 1;
293
+ const conv = Math.max(0, Math.sin(Math.PI * seg(t, TCONV, TCONV + 0.32))) + Math.max(0, Math.sin(Math.PI * seg(t, TCONV + 0.48, TCONV + 0.8)));
294
+ tf(c.sh, { op: clamp(seg(t, TA, TA + 0.25) * 3), s: lerp(0.93, 1, kab) * respira * (1 + 0.025 * conv), y: (1 - kab) * 30, blur: Math.pow(1 - kab, 2) * 20 });
295
+ c.sh.style.clipPath = kab < 1 ? `inset(${((1 - kab) * 50).toFixed(2)}% ${((1 - kab) * 6).toFixed(2)}% round 34px)` : 'none';
296
+ const cor = kg > 0 ? [lerp(19, 255, kg), lerp(19, 254, kg), lerp(19, 251, kg)] : [lerp(17, 19, kc), lerp(17, 19, kc), lerp(17, 19, kc)];
297
+ c.sh.style.background = `rgb(${cor.map(v => v | 0).join(',')})`;
298
+ c.f.toca(TA + (t - TA) * 0.5, TA, true); tf(c.vid, { s: 1 + 0.035 * conv, op: 1 - seg(t, TCIRC, TCIRC + 0.2) });
299
+ // notificação: entra (entrada) → sai (saída) → volta (meio-tempo) → conversa com o vídeo → some no círculo
300
+ const ent = t0 => ILL(seg(t, t0, t0 + 0.45)), sa = ILLIN(seg(t, TS + 0.08, TS + 0.42));
301
+ const v = t < TMEIO ? ent(TE) * (1 - sa) : ent(TMEIO), dsc = t < TMEIO ? (t < TS + 0.08 ? 1 - ent(TE) : sa) : 1 - ent(TMEIO);
302
+ tf(c.nt, { y: lerp(34, -200, dsc), op: clamp(v * 1.6) * (1 - seg(t, TCIRC, TCIRC + 0.15)), blur: dsc * 14, s: 1 + 0.04 * conv + 0.006 * Math.sin(t * 2.4) });
303
+ // G
304
+ const vg = kg > 0.6; c.g.style.visibility = vg ? 'visible' : 'hidden'; c.gl.style.visibility = vg ? 'visible' : 'hidden';
305
+ if (vg) {
306
+ const kGuia = uG(seg(t, TG0, TG1)), kM = uG(seg(t, TM0, TM0 + DG)), kV = uG(seg(t, TV0, TV0 + DG));
307
+ const volta1 = IO(seg(t, DM.t0 - 0.55, DM.t0 - 0.05)), volta2 = IO(seg(t, DM.t1 + 0.05, DM.t1 + 0.6));
308
+ let p, cinza = 0, colorido = 0, centro = 0;
309
+ if (t < TG0) { centro = 1 - ILL(seg(t, TPART + 0.1, TG0 - 0.08)); p = 0; }
310
+ else if (t < DM.t0 - 0.55) p = kGuia;
311
+ else if (t < TM0) p = 1 - volta1;
312
+ else if (t < DM.t1 + 0.05) { p = kM; cinza = kM; }
313
+ else if (t < TV0) { p = cinza = 1 - volta2; }
314
+ else { p = colorido = kV; }
315
+ if (t >= DM.t1 + 0.6 && t < TV0) { p = 0; cinza = 0; }
316
+ const pt = c.cam.getPointAtLength(clamp(p) * c.LT), px = lerp(pt.x, 12, centro), py = lerp(pt.y, 12, centro);
317
+ c.dot.setAttribute('cx', px.toFixed(3)); c.dot.setAttribute('cy', py.toFixed(3));
318
+ const naVivo = t >= TV0 && t < TV0 + DG, si = Math.max(0, c.C0.filter(x => x <= kV * c.LT).length - 1);
319
+ const bate = naVivo ? Math.exp(-Math.pow((t - (c.TSEG[si] ?? TV0)) / 0.08, 2)) : 0;
320
+ c.dot.setAttribute('fill', naVivo ? GCOR[si] : TINTA); c.dot.setAttribute('r', (1.05 * (naVivo ? 1.15 + 0.35 * bate : 1) * (1 + 0.06 * Math.sin(t * 3))).toFixed(3));
321
+ c.halo.setAttribute('cx', px.toFixed(3)); c.halo.setAttribute('cy', py.toFixed(3)); c.halo.setAttribute('fill', naVivo ? GCOR[si] : '#4285F4'); c.halo.setAttribute('opacity', (naVivo ? 0.55 + 0.3 * bate : 0).toFixed(3));
322
+ c.dot.setAttribute('opacity', (1 - seg(t, TV0 + DG - 0.05, TV0 + DG + 0.3)).toFixed(3));
323
+ c.guiaM.setAttribute('stroke-dasharray', `${kGuia.toFixed(4)} 1`); c.guia.style.opacity = (1 - seg(t, TV0 + DG, TV0 + DG + 0.3)).toFixed(3);
324
+ c.cz.setAttribute('stroke-dasharray', `${clamp(cinza).toFixed(4)} 1`);
325
+ const s = colorido * c.LT;
326
+ c.tr.forEach((pth, i) => { const f = clamp((s - c.C0[i]) / c.LS[i]); pth.setAttribute('stroke-dasharray', `${f.toFixed(4)} 1`); c.glowP[i].setAttribute('stroke-dasharray', `${f.toFixed(4)} 1`); });
327
+ c.glow.setAttribute('opacity', (t >= TV0 ? 0.55 * (1 - 0.6 * seg(t, TV0 + DG, TV0 + DG + 0.8)) : 0).toFixed(3));
328
+ c.logo.setAttribute('opacity', ILL(seg(t, TV0 + DG - 0.05, TV0 + DG + 0.4)).toFixed(3));
329
+ const kl = nasce(t, TGOO), saiL = seg(t, TGOO + 1.6, TGOO + 2.0); tf(c.gl, { op: kl.op * (1 - saiL), s: kl.s, y: kl.y, blur: kl.blur + 10 * saiL });
330
+ }
331
+ // demos (sem fala): o card cresce no centro; no fim encolhe e some em "Pegou a visão?"
332
+ const kD = Math.max(ILL(seg(t, DM.t0 - 0.3, DM.t0 + 0.1)) * (1 - ILL(seg(t, DM.t1, DM.t1 + 0.45))), ILL(seg(t, DV.t0 - 0.3, DV.t0 + 0.1)));
333
+ const fora = ILLIN(seg(t, TFIM, TFIM + 0.4)), fim = ILL(seg(t, TV0 + DG, TV0 + DG + 0.6));
334
+ tf(c.w, { y: 60 * kD + 4 * Math.sin(t * 0.8), s: (1 + 0.16 * kD + 0.03 * fim) * (1 - 0.15 * fora), op: 1 - fora, blur: 18 * fora });
335
+ c.sh.style.boxShadow = `0 ${(60 + 40 * kD).toFixed(0)}px ${(120 + 60 * kD).toFixed(0)}px -30px rgba(30,30,60,${(0.30 + 0.1 * kD).toFixed(2)}), 0 14px 34px rgba(30,30,60,.10), 0 0 0 1px rgba(0,0,0,.05)`;
336
+ }, { entra: false, sai: false });
337
+
338
+ // ═══ 22 · "visão" = óculos pixelados descendo ("deal with it") · cada coisa com o seu som · fecho ═══
339
+ legenda('22', [['Pegou a', 'f|visão?'], 'Não é difícil.', 'Só tem que entender que', 'cada coisa tem que ter', 'um af|som af|específico', 'de assimilação,', ['por mais', 'f|sutil', 'que ele seja,'], 'para não atrapalhar', 'o andamento do seu a|vídeo.'], { ate: TFIMP - 0.05 });
340
+ const TVI = PF('22', 'visao'), TOC = TVI + 0.12;
341
+ ev(TVI - 0.1, 'pop', 0, 0.25); ev(TOC + 0.4, 'pouso', 0, 0.3);
342
+ const PIX = (() => { const L = ['1111111111111111111111', '1111111111111111111111', '0111222211000112222110', '0011222211000112222110', '0001111110000011111100']; let s = '';
343
+ L.forEach((r, y) => [...r].forEach((ch, x) => { if (ch !== '0') s += `<rect x="${x}" y="${y}" width="1.02" height="1.02" fill="${ch === '1' ? '#0B0B0C' : '#fff'}"/>`; })); return `<svg viewBox="0 0 22 5" width="330" height="75" shape-rendering="crispEdges">${s}</svg>`; })();
344
+ palco(TVI - 0.2, PF('22', 'cada') - 0.25, (el, P) => {
345
+ el = grande(el, 1.8); sombra(el, 540, CY + 230, 300); P.e = $('div', null, el); pos(P.e, 540, CY, 420, 420); P.l = emojiLot(P.e, umDe('u1f60c', 'u1f610'), 420);
346
+ P.oc = $('div', null, el, { position: 'absolute', left: (540 - 165) + 'px', top: (CY - 72) + 'px', width: '330px', height: '75px' }, PIX);
347
+ }, (t, P) => {
348
+ const n = nasce(t, TVI - 0.1, 0.45), v = vivo(t, 6, 5);
349
+ const uo = seg(t, TOC, TOC + 0.55), ko = uo < 1 ? uo * uo : 1, bump = Math.sin(Math.PI * seg(t, TOC + 0.55, TOC + 0.75));
350
+ tf(P.e, { op: n.op, s: n.s * (1 - 0.03 * bump), x: v.x, y: n.y + v.y + 6 * bump, blur: n.blur }); P.l.toca(t, TVI - 0.1);
351
+ tf(P.oc, { x: v.x, y: v.y + lerp(-760, 0, ko) + 6 * bump, op: seg(t, TOC - 0.05, TOC + 0.05), r: 0 });
352
+ });
353
+ // cada coisa com o seu som: 3 peças, cada uma com uma onda diferente; em "sutil" as ondas baixam; em "andamento" a barra do vídeo corre lisa
354
+ const TCC = PF('22', 'cada'), TESP = PF('22', 'especifico'), TSUT = PF('22', 'sutil'), TAND = PF('22', 'andamento');
355
+ const PECAS = [{ id: 'u1f514', cor: AZ }, { id: 'u2728', cor: OR }, { id: 'u1f3af', cor: AZ }];
356
+ PECAS.forEach((_, i) => ev(TCC + i * 0.3, 'pop', (i - 1) * 0.5, 0.22));
357
+ palco(TCC - 0.15, TFIMP - 0.05, (el, P) => {
358
+ el = grande(el, 1.18);
359
+ P.p = PECAS.map((pc, i) => { const d = $('div', 'sq', el, { width: '220px', height: '220px', borderRadius: '64px', top: '0' }); pos(d, 230 + i * 310, CY - 110, 220, 220);
360
+ const l = emojiLot(d, temEmoji(pc.id) ? pc.id : 'u2728', 170); l.style.left = '25px'; l.style.top = '25px';
361
+ const w = linhaBarras(el, 230 + i * 310 - 100, 200, 15, 110, pc.cor, i * 1.9 + 0.7); w.style.top = (CY + 90) + 'px';
362
+ return { d, l, w }; });
363
+ P.bar = $('div', null, el, { position: 'absolute', left: '140px', width: '800px', top: (CY + 270) + 'px', height: '12px', borderRadius: '6px', background: 'rgba(19,19,19,.10)' },
364
+ `<b style="position:absolute;left:0;top:0;bottom:0;border-radius:6px;background:${TINTA}"></b><i style="position:absolute;top:-10px;width:32px;height:32px;border-radius:50%;background:${TINTA};box-shadow:0 6px 14px rgba(0,0,0,.25)"></i>`);
365
+ P.bf = P.bar.querySelector('b'); P.bk = P.bar.querySelector('i');
366
+ }, (t, P) => {
367
+ const ks = ILL(seg(t, TSUT - 0.05, TSUT + 0.5)), ke = Math.sin(Math.PI * seg(t, TESP, TESP + 0.5));
368
+ P.p.forEach((o, i) => { const t0 = TCC + i * 0.3, n = nasce(t, t0, 0.45), v = vivo(t, 7 + i, 4);
369
+ tf(o.d, { op: n.op, s: n.s * (1 + 0.06 * ke), x: v.x, y: n.y + v.y, blur: n.blur }); o.l.toca(t, t0);
370
+ const kw = ILL(seg(t, t0 + 0.15, t0 + 0.5)); o.w.style.transform = `translateX(${v.x.toFixed(1)}px) scaleY(${(kw * lerp(1, 0.3, ks) * (1 + 0.1 * Math.sin(t * 7 + i))).toFixed(3)})`; o.w.style.opacity = clamp(kw * 2).toFixed(3); });
371
+ const kb = nasce(t, TAND - 0.2, 0.4), u = seg(t, TAND - 0.1, TFIMP);
372
+ tf(P.bar, { op: kb.op, y: kb.y, blur: kb.blur }); P.bf.style.width = (100 * u).toFixed(2) + '%'; P.bk.style.left = (800 * u - 16).toFixed(1) + 'px';
373
+ });
374
+ // fecho: "Passo 3 de 4 ✓" e "Parte 2 →"
375
+ const TF0 = TFIMP + 0.05, TCK = TF0 + 0.45, TP2 = TF0 + 0.9;
376
+ ev(TCK, 'check', 0, 0.3); ev(TP2 + 0.2, 'seta', 0.4, 0.22);
377
+ palco(TF0, TEMPO.dur + 1, (el, P) => {
378
+ P.a = $('div', null, el, { position: 'absolute', left: '0', right: '0', top: (CY - 150) + 'px', display: 'flex', justifyContent: 'center', alignItems: 'center', gap: '30px', font: '600 120px/1 GS', letterSpacing: '-0.045em', color: TINTA },
379
+ `<span>3 de 4</span><span class="ck" style="display:block;width:132px;height:132px;border-radius:50%;background:${AZ};position:relative"><svg viewBox="0 0 24 24" width="132" height="132" style="display:block;position:absolute;left:0;top:0"><path d="M6.5 12.4l3.6 3.6 7.4-7.6" fill="none" stroke="#fff" stroke-width="2.6" stroke-linecap="round" stroke-linejoin="round" pathLength="1" stroke-dasharray="0 1"/></svg></span>`);
380
+ P.ck = P.a.querySelector('.ck'); P.ckp = P.ck.querySelector('path'); P.tx = P.a.firstChild;
381
+ P.b = $('div', null, el, { position: 'absolute', left: '0', right: '0', top: (CY + 60) + 'px', display: 'flex', justifyContent: 'center', alignItems: 'center', gap: '26px', font: '600 96px/1 GS', letterSpacing: '-0.04em', color: AZ },
382
+ `<span>Parte 2</span><svg viewBox="0 0 60 36" width="140" height="84" style="display:block"><path d="M4 18h46M36 6l14 12-14 12" fill="none" stroke="${AZ}" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/></svg>`);
383
+ P.seta = P.b.lastChild;
384
+ }, (t, P) => {
385
+ const ta = palavraVida(t, TF0, true), nc = nasce(t, TCK, 0.4), tb = palavraVida(t, TP2, true);
386
+ tf(P.tx, ta); tf(P.ck, { op: nc.op, s: nc.s, blur: nc.blur }); P.ckp.setAttribute('stroke-dasharray', `${ILL(seg(t, TCK + 0.08, TCK + 0.4)).toFixed(3)} 1`);
387
+ tf(P.b, { op: tb.op, y: tb.y, s: tb.s, blur: tb.blur }); tf(P.seta, { x: 10 * Math.max(0, Math.sin((t - TP2) * 3.4)) });
388
+ }, { sai: false });
389
+ })();