feat(formacoes): módulo 2 (DHT22 + LCD 16x2 no Wokwi), PDFs e página de entrada
Release / Plano (reaproveitar a imagem?) (push) Successful in 7s
CI / Lint e auditorias (push) Successful in 1m48s
CI / Trivy (dependências e segredos) (push) Successful in 12s
CI / Imagem Docker (linux/arm64) (push) Failing after 2m27s
Release / ci (push) Failing after 4m31s
Release / Publica a imagem (linux/arm64) (push) Skipped
Release / Cria a release no Gitea (push) Skipped

- Formação 2 da LASER: slides visuais, apostila, projeto do Wokwi e scanner
  I2C, validados no simulador (leitura normal, temperatura negativa e sensor
  desconectado). Circuito com pull-ups de 10 kΩ e 4,7 kΩ para 3V3 e aviso
  sobre os pull-ups de 5 V da plaquinha PCF8574.
- PDFs prontos dos slides e das apostilas dos módulos 1 e 2;
  slides-pdf agora também exporta a apostila.
- Página de entrada em /formacoes e /formacoes/N, gerada por
  scripts/formacoes-viewer.mjs a partir do formacao.json de cada pasta.
- A apostila passou de index.html para apostila.html.
- Corrige o link do Fritzing da apostila 1 (/apostilas/1 não existe).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Lucas RayanandClaude Opus 5.5 committed 2026-11-02 13:11:28 -03:00
1 parent 71c5708726
commit 1860e34cbb
32 files changed
+6469 -1943

No files matched your search

+252
View File
@@ -0,0 +1,252 @@
/* =========================================================================
Página de entrada de cada formação (/formacoes/N).
Mesma identidade dos slides: base escura tirada do prussiano da marca, o
feixe como traço de assinatura e as três famílias tipográficas da LASER.
A página é gerada por scripts/formacoes-viewer.mjs a partir do
formacao.json de cada pasta; não edite o index.html à mão.
========================================================================= */
:root {
color-scheme: dark;
--breu: #041d2b;
--breu-2: #06283a;
--breu-3: #0a3a53;
--prussiano: #003049;
--vermelho: #D62828;
--laranja: #F77F00;
--ambar: #FCBF49;
--creme: #EAE2B7;
--gelo: #f2f8fb;
--texto: #cddde6;
--texto-2: #93aebd;
--linha: rgba(146, 187, 207, 0.18);
--linha-forte: rgba(146, 187, 207, 0.38);
--painel: rgba(255, 255, 255, 0.04);
--painel-2: rgba(255, 255, 255, 0.07);
--feixe: linear-gradient(90deg, #1b6d92, var(--creme), var(--ambar), var(--laranja), var(--vermelho));
--display: "Outfit", system-ui, sans-serif;
--corpo: "Inter", system-ui, sans-serif;
--mono: "JetBrains Mono", ui-monospace, monospace;
--largura: 1120px;
}
* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
margin: 0;
background: var(--breu);
color: var(--texto);
font-family: var(--corpo);
font-size: 16px;
line-height: 1.6;
-webkit-font-smoothing: antialiased;
}
body::before {
content: "";
position: fixed;
inset: 0;
pointer-events: none;
z-index: -1;
background:
radial-gradient(50% 40% at 85% 0%, rgba(252, 191, 73, 0.10), transparent 70%),
radial-gradient(45% 45% at 0% 100%, rgba(0, 48, 73, 0.6), transparent 70%);
}
a { color: var(--ambar); text-decoration-thickness: 1px; text-underline-offset: 3px; }
a:hover { color: var(--creme); }
:focus-visible { outline: 2px solid var(--ambar); outline-offset: 3px; border-radius: 6px; }
code, kbd {
font-family: var(--mono);
font-size: 0.86em;
padding: 0.1em 0.42em;
border-radius: 5px;
background: var(--painel-2);
border: 1px solid var(--linha);
color: var(--gelo);
}
kbd { border-bottom-width: 2px; }
.envoltorio { max-width: var(--largura); margin: 0 auto; padding: 0 24px; }
/* -------------------------------------------------------------------------
Barra do topo
------------------------------------------------------------------------- */
.topo { border-bottom: 1px solid var(--linha); }
.topo .envoltorio { display: flex; align-items: center; gap: 16px; min-height: 68px; }
.topo img { height: 26px; display: block; }
.topo-liga { font-family: var(--mono); font-size: 11px; letter-spacing: 0.16em; text-transform: uppercase; color: var(--texto-2); line-height: 1.4; border-left: 1px solid var(--linha-forte); padding-left: 16px; }
.topo nav { margin-left: auto; display: flex; gap: 20px; }
.topo nav a { color: var(--texto); text-decoration: none; font-size: 14px; }
.topo nav a:hover { color: var(--ambar); }
/* -------------------------------------------------------------------------
Abertura
------------------------------------------------------------------------- */
.abertura { padding: 64px 0 56px; }
.abertura .envoltorio { display: grid; grid-template-columns: 1.25fr 0.75fr; gap: 48px; align-items: center; }
.selo {
display: inline-flex; gap: 10px; align-items: center;
font-family: var(--mono); font-size: 12px; font-weight: 600; letter-spacing: 0.2em; text-transform: uppercase;
color: var(--ambar);
}
.selo::after { content: ""; width: 48px; height: 1px; background: var(--ambar); opacity: 0.5; }
h1 {
font-family: var(--display);
font-weight: 300;
font-size: clamp(38px, 5.4vw, 60px);
line-height: 1.04;
letter-spacing: -0.02em;
color: var(--gelo);
margin: 18px 0 18px;
}
h1 strong { display: block; font-weight: 800; }
.abertura-sub { font-size: 18px; color: var(--texto); max-width: 54ch; margin: 0 0 24px; }
.fichas { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 30px; padding: 0; list-style: none; }
.fichas li { font-size: 13px; padding: 5px 12px; border-radius: 999px; border: 1px solid var(--linha-forte); color: var(--texto); background: var(--painel); }
.fichas li b { color: var(--gelo); font-weight: 600; }
.acoes { display: flex; flex-wrap: wrap; gap: 12px; }
.botao {
display: inline-flex; align-items: center; gap: 10px;
padding: 12px 20px; border-radius: 10px;
font-family: var(--corpo); font-weight: 600; font-size: 15px; text-decoration: none;
border: 1px solid var(--linha-forte); color: var(--gelo); background: var(--painel);
transition: background 0.15s, border-color 0.15s, transform 0.15s;
}
.botao:hover { background: var(--painel-2); border-color: var(--ambar); color: var(--gelo); transform: translateY(-1px); }
.botao svg { width: 18px; height: 18px; flex: none; }
.botao.primario { background: var(--ambar); border-color: var(--ambar); color: #1d1300; }
.botao.primario:hover { background: var(--creme); border-color: var(--creme); color: #1d1300; }
.botao.pequeno { padding: 8px 14px; font-size: 14px; }
/* Pilha das duas prévias: o slide na frente, a apostila atrás. */
.previas { position: relative; aspect-ratio: 4 / 3.3; }
.previas a { position: absolute; display: block; border-radius: 10px; overflow: hidden; box-shadow: 0 24px 60px rgba(0, 0, 0, 0.55); border: 1px solid var(--linha-forte); transition: transform 0.2s; }
.previas img { display: block; width: 100%; height: auto; }
.previas .p-apostila { width: 46%; right: 0; top: 0; transform: rotate(4deg); }
.previas .p-slides { width: 88%; left: 0; bottom: 6%; }
.previas a:hover { transform: translateY(-4px) rotate(0deg); z-index: 2; }
.feixe { height: 3px; background: var(--feixe); border: 0; margin: 0; }
/* -------------------------------------------------------------------------
Seções
------------------------------------------------------------------------- */
section.bloco { padding: 64px 0 8px; }
.rotulo {
font-family: var(--mono); font-size: 12px; font-weight: 600; letter-spacing: 0.2em; text-transform: uppercase;
color: var(--ambar); margin: 0 0 8px;
}
h2 { font-family: var(--display); font-weight: 700; font-size: 32px; line-height: 1.15; color: var(--gelo); margin: 0 0 8px; letter-spacing: -0.01em; }
.bloco-sub { color: var(--texto-2); margin: 0 0 28px; max-width: 70ch; }
h3 { font-family: var(--display); font-weight: 700; font-size: 20px; color: var(--gelo); margin: 0 0 6px; }
/* Três portas de entrada. */
.portas { display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px; }
.porta { display: flex; flex-direction: column; border: 1px solid var(--linha); border-radius: 14px; background: var(--painel); overflow: hidden; }
.porta-imagem { aspect-ratio: 16 / 9; background: var(--breu-2); border-bottom: 1px solid var(--linha); overflow: hidden; display: grid; place-items: center; }
.porta-imagem img { width: 100%; height: 100%; object-fit: cover; object-position: top; display: block; }
.porta-imagem.clara img { object-fit: contain; background: #2f2f2f; }
.porta-corpo { padding: 20px 20px 22px; display: flex; flex-direction: column; gap: 10px; flex: 1; }
.porta-corpo p { margin: 0; color: var(--texto); font-size: 15px; }
.porta-meta { font-family: var(--mono); font-size: 12px; color: var(--texto-2); letter-spacing: 0.04em; }
.porta .acoes { margin-top: auto; padding-top: 6px; gap: 8px; }
/* Lista de arquivos. */
.grupo-arquivos { margin: 0 0 30px; }
.grupo-arquivos h3 { font-size: 14px; font-family: var(--mono); letter-spacing: 0.16em; text-transform: uppercase; color: var(--texto-2); font-weight: 600; margin: 0 0 10px; }
.arquivos { list-style: none; margin: 0; padding: 0; border: 1px solid var(--linha); border-radius: 12px; overflow: hidden; }
.arquivo { display: grid; grid-template-columns: 44px minmax(0, 1fr) auto auto; gap: 16px; align-items: center; padding: 14px 18px; background: var(--painel); }
.arquivo + .arquivo { border-top: 1px solid var(--linha); }
.arquivo:hover { background: var(--painel-2); }
.icone { width: 44px; height: 44px; border-radius: 10px; display: grid; place-items: center; background: var(--breu-3); color: var(--ambar); }
.icone svg { width: 22px; height: 22px; }
.icone.pdf { color: #ff8b8b; background: rgba(214, 40, 40, 0.14); }
.icone.codigo { color: #6fdcb0; background: rgba(111, 220, 176, 0.1); }
.icone.imagem { color: #7cc4ff; background: rgba(78, 168, 255, 0.12); }
.arquivo-nome { font-family: var(--mono); font-size: 14.5px; color: var(--gelo); font-weight: 600; word-break: break-all; }
.arquivo-desc { font-size: 14px; color: var(--texto-2); margin-top: 2px; }
.arquivo-tam { font-family: var(--mono); font-size: 12.5px; color: var(--texto-2); white-space: nowrap; text-align: right; }
.arquivo-acoes { display: flex; gap: 6px; }
.arquivo-acoes a { font-size: 13px; font-weight: 600; text-decoration: none; padding: 6px 12px; border-radius: 8px; border: 1px solid var(--linha-forte); color: var(--gelo); white-space: nowrap; }
.arquivo-acoes a:hover { border-color: var(--ambar); color: var(--ambar); }
/* Código embutido: .ino e .txt costumam baixar em vez de abrir, então o
conteúdo vem na própria página. */
.codigo-fonte { margin-top: 8px; }
.codigo-fonte summary { cursor: pointer; font-size: 13px; font-weight: 600; color: var(--ambar); width: max-content; }
.codigo-fonte pre { margin: 10px 0 0; max-height: 420px; overflow: auto; padding: 14px 16px; border-radius: 10px; background: rgba(0, 14, 22, 0.7); border: 1px solid var(--linha); border-left: 3px solid var(--laranja); font-family: var(--mono); font-size: 13px; line-height: 1.55; color: #dbeaf2; tab-size: 2; }
.codigo-fonte pre code { background: none; border: 0; padding: 0; font-size: inherit; }
/* Como usar. */
.guias { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 18px; }
.guia { border: 1px solid var(--linha); border-radius: 14px; padding: 22px 22px 18px; background: var(--painel); }
.guia ol, .guia ul { margin: 10px 0 0; padding-left: 20px; }
.guia li { margin: 6px 0; font-size: 15px; }
.guia li::marker { color: var(--ambar); font-family: var(--mono); }
.guia p { margin: 8px 0 0; font-size: 15px; }
.atalhos { display: grid; grid-template-columns: auto 1fr; gap: 8px 14px; margin-top: 12px; font-size: 14.5px; align-items: center; }
.atalhos dt { display: flex; gap: 4px; }
.atalhos dd { margin: 0; color: var(--texto); }
/* Roteiro da aula. */
.roteiro { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 12px; counter-reset: parte; }
.roteiro a { display: flex; gap: 14px; align-items: baseline; padding: 14px 16px; border-radius: 12px; border: 1px solid var(--linha); background: var(--painel); text-decoration: none; color: var(--texto); height: 100%; }
.roteiro a:hover { border-color: var(--ambar); background: var(--painel-2); }
.roteiro b { font-family: var(--display); font-size: 26px; line-height: 1; color: var(--ambar); min-width: 1.4em; }
.roteiro span { font-weight: 600; color: var(--gelo); }
.roteiro small { display: block; font-family: var(--mono); font-size: 12px; color: var(--texto-2); font-weight: 400; margin-top: 2px; }
/* Hub /formacoes. */
.formacoes { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: 22px; }
/* Rodapé. */
.rodape { margin-top: 80px; border-top: 1px solid var(--linha); padding: 28px 0 40px; font-size: 14px; color: var(--texto-2); }
.rodape .envoltorio { display: flex; flex-wrap: wrap; gap: 12px 32px; justify-content: space-between; }
.rodape strong { color: var(--texto); }
/* -------------------------------------------------------------------------
Telas menores
------------------------------------------------------------------------- */
@media (max-width: 900px) {
.abertura { padding: 40px 0; }
.abertura .envoltorio { grid-template-columns: 1fr; gap: 40px; }
.previas { max-width: 520px; }
.portas, .guias { grid-template-columns: 1fr; }
}
@media (max-width: 640px) {
.envoltorio { padding: 0 16px; }
.topo-liga { display: none; }
.topo nav { gap: 14px; }
.arquivo { grid-template-columns: 40px minmax(0, 1fr); row-gap: 10px; padding: 14px; }
.icone { width: 40px; height: 40px; }
.arquivo-tam { grid-column: 2; text-align: left; }
.arquivo-acoes { grid-column: 2; }
h2 { font-size: 26px; }
}
@media (prefers-reduced-motion: reduce) {
html { scroll-behavior: auto; }
.botao, .previas a { transition: none; }
}