Cartões de Diálogo
Cards com imagens ou situações que estimulam diálogo e discussão. O aprendiz usa os cards como gatilho para praticar conversação, reflexão oral ou debate estruturado.
Experimente
Dilemas de Tecnologia
1/2Situação
Uma empresa usa um algoritmo de IA para pré-selecionar currículos, e ele passa a rejeitar sistematicamente candidatos de um determinado bairro — sem que ninguém tenha programado essa regra explicitamente.
Perguntas para reflexão
Isso é discriminação, mesmo sem nenhuma intenção humana direta?
Quem deveria ser responsabilizado: quem programou o algoritmo, quem o usa, ou ninguém?
Código-fonte
Dados de exemplo
Duas situações fixas, cada uma com duas perguntas abertas.
| 1 |
<?php
|
| 2 |
$titulo = 'Decisões em Grupo';
|
| 3 |
$cartoes = [
|
| 4 |
[
|
| 5 |
'situacao' => 'Sua equipe precisa escolher entre dois projetos igualmente bons, mas só há recursos para um.',
|
| 6 |
'perguntas' => [
|
| 7 |
'Como vocês decidiriam qual priorizar?',
|
| 8 |
'O que fazer com quem defendia a opção não escolhida?',
|
| 9 |
],
|
| 10 |
],
|
| 11 |
[
|
| 12 |
'situacao' => 'Um membro do grupo discorda da decisão da maioria, mas topa seguir em frente mesmo assim.',
|
| 13 |
'perguntas' => [
|
| 14 |
'Isso é um bom sinal de trabalho em equipe, ou algo a se preocupar?',
|
| 15 |
'Como garantir que a opinião dele continue sendo ouvida no futuro?',
|
| 16 |
],
|
| 17 |
],
|
| 18 |
];
|
| 19 |
?>
|
Título e cartões
Cada cartão junta a situação com suas perguntas; só o primeiro começa visível.
| 1 |
<div class="dialogo" data-tipo="dialogue-cards" data-titulo="<?= htmlspecialchars($titulo) ?>">
|
| 2 |
|
| 3 |
<div class="dialogo-cabecalho">
|
| 4 |
<p><?= htmlspecialchars($titulo) ?></p>
|
| 5 |
<span class="dialogo-posicao">1/<?= count($cartoes) ?></span>
|
| 6 |
</div>
|
| 7 |
|
| 8 |
<div class="dialogo-corpo">
|
| 9 |
<?php foreach ($cartoes as $i => $cartao): ?>
|
| 10 |
<div class="dialogo-card<?= $i > 0 ? ' escondido' : '' ?>">
|
| 11 |
<div class="dialogo-situacao">
|
| 12 |
<p class="dialogo-rotulo">Situação</p>
|
| 13 |
<p class="dialogo-texto-situacao"><?= htmlspecialchars($cartao['situacao']) ?></p>
|
| 14 |
</div>
|
| 15 |
<div class="dialogo-perguntas">
|
| 16 |
<p class="dialogo-rotulo">Perguntas para reflexão</p>
|
| 17 |
<?php foreach ($cartao['perguntas'] as $pergunta): ?>
|
| 18 |
<div class="dialogo-pergunta-item">
|
| 19 |
<p class="dialogo-pergunta"><?= htmlspecialchars($pergunta) ?></p>
|
| 20 |
<textarea class="dialogo-resposta" rows="3" placeholder="Sua reflexão..."></textarea>
|
| 21 |
</div>
|
| 22 |
<?php endforeach; ?>
|
| 23 |
</div>
|
| 24 |
</div>
|
| 25 |
<?php endforeach; ?>
|
Navegação e download
Anterior/próximo, bolinhas clicáveis para pular direto, e um botão que baixa tudo em .md.
| 1 |
<div class="dialogo-nav">
|
| 2 |
<button type="button" class="dialogo-anterior" disabled>← Anterior</button>
|
| 3 |
<div class="dialogo-bolinhas">
|
| 4 |
<?php for ($i = 0; $i < count($cartoes); $i++): ?>
|
| 5 |
<button type="button" class="dialogo-bolinha" data-estado="<?= $i === 0 ? 'ativo' : 'inativo' ?>" data-indice="<?= $i ?>"></button>
|
| 6 |
<?php endfor; ?>
|
| 7 |
</div>
|
| 8 |
<button type="button" class="dialogo-proximo">Próximo →</button>
|
| 9 |
</div>
|
| 10 |
|
| 11 |
<button type="button" class="dialogo-download">Download em Markdown</button>
|
| 12 |
<p class="dialogo-confirmacao" hidden>Reflexões baixadas em .md!</p>
|
| 13 |
</div>
|
| 14 |
|
| 15 |
</div>
|
Card e cabeçalho
Contêiner geral e a caixa de título centralizada, com o contador de posição embaixo.
| 1 |
.dialogo {
|
| 2 |
max-width: 480px;
|
| 3 |
border: 1px solid #e2e8f0;
|
| 4 |
border-radius: 16px;
|
| 5 |
background: #fff;
|
| 6 |
font-family: sans-serif;
|
| 7 |
overflow: hidden;
|
| 8 |
}
|
| 9 |
|
| 10 |
.dialogo-cabecalho {
|
| 11 |
padding: 20px 24px;
|
| 12 |
border-bottom: 1px solid #cbd5e1;
|
| 13 |
background: rgba(241, 245, 249, .6);
|
| 14 |
text-align: center;
|
| 15 |
}
|
| 16 |
|
| 17 |
.dialogo-cabecalho p {
|
| 18 |
margin: 0;
|
| 19 |
font-weight: 700;
|
| 20 |
font-size: 18px;
|
| 21 |
color: #0f172a;
|
| 22 |
}
|
| 23 |
|
| 24 |
.dialogo-posicao {
|
| 25 |
display: inline-block;
|
| 26 |
margin-top: 6px;
|
| 27 |
font-size: 12px;
|
| 28 |
font-family: monospace;
|
| 29 |
color: #64748b;
|
| 30 |
}
|
| 31 |
|
| 32 |
.dialogo-corpo { padding: 20px; }
|
| 33 |
.dialogo-card.escondido { display: none; }
|
Situação e perguntas
A situação fica num tom neutro; cada pergunta ganha um tom indigo sutil pra se destacar dela.
| 1 |
.dialogo-rotulo {
|
| 2 |
margin: 0 0 8px;
|
| 3 |
font-size: 12px;
|
| 4 |
font-weight: 700;
|
| 5 |
text-transform: uppercase;
|
| 6 |
letter-spacing: .03em;
|
| 7 |
color: #64748b;
|
| 8 |
}
|
| 9 |
|
| 10 |
.dialogo-situacao {
|
| 11 |
padding: 16px;
|
| 12 |
margin-bottom: 16px;
|
| 13 |
border: 1px solid #cbd5e1;
|
| 14 |
border-radius: 12px;
|
| 15 |
background: rgba(241, 245, 249, .4);
|
| 16 |
}
|
| 17 |
|
| 18 |
.dialogo-texto-situacao { margin: 0; color: #334155; line-height: 1.6; }
|
| 19 |
|
| 20 |
.dialogo-pergunta-item {
|
| 21 |
padding: 16px;
|
| 22 |
margin-bottom: 12px;
|
| 23 |
border: 1px solid rgba(99, 102, 241, .25);
|
| 24 |
border-radius: 12px;
|
| 25 |
background: rgba(99, 102, 241, .04);
|
| 26 |
}
|
| 27 |
|
| 28 |
.dialogo-pergunta { margin: 0 0 10px; color: #334155; }
|
| 29 |
|
| 30 |
.dialogo-resposta {
|
| 31 |
width: 100%;
|
| 32 |
padding: 8px 10px;
|
| 33 |
border: 1px solid #cbd5e1;
|
| 34 |
border-radius: 8px;
|
| 35 |
background: #fff;
|
| 36 |
font: inherit;
|
| 37 |
font-size: 14px;
|
| 38 |
color: #334155;
|
| 39 |
resize: none;
|
| 40 |
box-sizing: border-box;
|
| 41 |
}
|
Navegação e botão de download
Anterior/próximo do mesmo tamanho, com as bolinhas de posição entre os dois.
| 1 |
.dialogo-nav {
|
| 2 |
display: flex;
|
| 3 |
align-items: center;
|
| 4 |
gap: 12px;
|
| 5 |
margin-top: 8px;
|
| 6 |
}
|
| 7 |
|
| 8 |
.dialogo-anterior,
|
| 9 |
.dialogo-proximo {
|
| 10 |
padding: 8px 14px;
|
| 11 |
border: 1px solid #cbd5e1;
|
| 12 |
border-radius: 8px;
|
| 13 |
background: #f1f5f9;
|
| 14 |
font: inherit;
|
| 15 |
font-size: 13px;
|
| 16 |
cursor: pointer;
|
| 17 |
}
|
| 18 |
|
| 19 |
.dialogo-anterior:disabled,
|
| 20 |
.dialogo-proximo:disabled { opacity: .4; cursor: not-allowed; }
|
| 21 |
|
| 22 |
.dialogo-bolinhas {
|
| 23 |
flex: 1;
|
| 24 |
display: flex;
|
| 25 |
justify-content: center;
|
| 26 |
gap: 6px;
|
| 27 |
}
|
| 28 |
|
| 29 |
.dialogo-bolinha {
|
| 30 |
width: 8px;
|
| 31 |
height: 8px;
|
| 32 |
border: none;
|
| 33 |
border-radius: 999px;
|
| 34 |
padding: 0;
|
| 35 |
cursor: pointer;
|
| 36 |
transition: width .15s, background .15s;
|
| 37 |
}
|
| 38 |
|
| 39 |
.dialogo-bolinha[data-estado="inativo"] { background: #e2e8f0; }
|
| 40 |
.dialogo-bolinha[data-estado="ativo"] { background: #6366f1; width: 16px; }
|
| 41 |
|
| 42 |
.dialogo-download {
|
| 43 |
display: block;
|
| 44 |
width: 100%;
|
| 45 |
margin-top: 16px;
|
| 46 |
padding: 12px 16px;
|
| 47 |
border: none;
|
| 48 |
border-radius: 10px;
|
| 49 |
background: #4f46e5;
|
| 50 |
color: #fff;
|
| 51 |
font: inherit;
|
| 52 |
font-weight: 600;
|
| 53 |
cursor: pointer;
|
| 54 |
}
|
| 55 |
|
| 56 |
.dialogo-confirmacao {
|
| 57 |
margin-top: 10px;
|
| 58 |
text-align: center;
|
| 59 |
font-size: 14px;
|
| 60 |
color: #15803d;
|
| 61 |
}
|
Trocar de cartão
Só alterna a classe "escondido" — o conteúdo dos outros cartões continua no DOM, então nada se perde ao ir e voltar.
| 1 |
document.addEventListener('DOMContentLoaded', function () {
|
| 2 |
var dialogo = document.querySelector('[data-tipo="dialogue-cards"]');
|
| 3 |
var cartoes = dialogo.querySelectorAll('.dialogo-card');
|
| 4 |
var bolinhas = dialogo.querySelectorAll('.dialogo-bolinha');
|
| 5 |
var posicao = dialogo.querySelector('.dialogo-posicao');
|
| 6 |
var anterior = dialogo.querySelector('.dialogo-anterior');
|
| 7 |
var proximo = dialogo.querySelector('.dialogo-proximo');
|
| 8 |
var total = cartoes.length;
|
| 9 |
var atual = 0;
|
| 10 |
|
| 11 |
function irPara(indice) {
|
| 12 |
cartoes[atual].classList.add('escondido');
|
| 13 |
bolinhas[atual].dataset.estado = 'inativo';
|
| 14 |
|
| 15 |
atual = (indice + total) % total;
|
| 16 |
|
| 17 |
cartoes[atual].classList.remove('escondido');
|
| 18 |
bolinhas[atual].dataset.estado = 'ativo';
|
| 19 |
posicao.textContent = (atual + 1) + '/' + total;
|
| 20 |
anterior.disabled = atual === 0;
|
| 21 |
proximo.disabled = atual === total - 1;
|
| 22 |
}
|
| 23 |
|
| 24 |
anterior.addEventListener('click', function () { irPara(atual - 1); });
|
| 25 |
proximo.addEventListener('click', function () { irPara(atual + 1); });
|
| 26 |
bolinhas.forEach(function (bolinha, i) {
|
| 27 |
bolinha.addEventListener('click', function () { irPara(i); });
|
| 28 |
});
|
Baixar todas as reflexões em Markdown
Percorre TODOS os cartões (não só o visível) e junta cada situação com suas perguntas e respostas.
| 1 |
function gerarMarkdown() {
|
| 2 |
var linhas = ['# ' + dialogo.dataset.titulo, ''];
|
| 3 |
cartoes.forEach(function (cartao) {
|
| 4 |
var situacao = cartao.querySelector('.dialogo-texto-situacao');
|
| 5 |
linhas.push('## ' + situacao.textContent.trim(), '');
|
| 6 |
cartao.querySelectorAll('.dialogo-pergunta-item').forEach(function (item) {
|
| 7 |
var pergunta = item.querySelector('.dialogo-pergunta');
|
| 8 |
var resposta = item.querySelector('.dialogo-resposta');
|
| 9 |
linhas.push('### ' + pergunta.textContent.trim(), '', resposta.value.trim(), '');
|
| 10 |
});
|
| 11 |
});
|
| 12 |
return linhas.join('\n');
|
| 13 |
}
|
| 14 |
|
| 15 |
var botaoDownload = dialogo.querySelector('.dialogo-download');
|
| 16 |
var confirmacao = dialogo.querySelector('.dialogo-confirmacao');
|
| 17 |
|
| 18 |
botaoDownload.addEventListener('click', function () {
|
| 19 |
var blob = new Blob([gerarMarkdown()], { type: 'text/markdown;charset=utf-8' });
|
| 20 |
var url = URL.createObjectURL(blob);
|
| 21 |
var link = document.createElement('a');
|
| 22 |
link.href = url;
|
| 23 |
link.download = 'dialogue-cards.md';
|
| 24 |
document.body.appendChild(link);
|
| 25 |
link.click();
|
| 26 |
document.body.removeChild(link);
|
| 27 |
URL.revokeObjectURL(url);
|
| 28 |
|
| 29 |
confirmacao.hidden = false;
|
| 30 |
setTimeout(function () { confirmacao.hidden = true; }, 3000);
|
| 31 |
});
|