index.html
por Gibran S. Christo
—
última modificação
29/05/2026 15h40
index.html
—
HTML,
49 KB (50210 bytes)
Conteúdo do arquivo
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Envio de Projetos – Câmara Municipal de Marechal Floriano</title>
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--verde: #2e7d32;
--verde-claro:#4caf50;
--verde-hover:#1b5e20;
--amarelo: #f9a825;
--cinza-bg: #f4f6f4;
--cinza-card: #ffffff;
--cinza-borda:#d0d7d0;
--texto: #1a1a1a;
--texto-leve: #555;
--erro: #c62828;
--sucesso: #2e7d32;
--radius: 10px;
--sombra: 0 4px 24px rgba(0,0,0,.10);
}
body {
font-family: 'Segoe UI', Arial, sans-serif;
background: var(--cinza-bg);
color: var(--texto);
min-height: 100vh;
}
/* ===== HEADER ===== */
header {
background: linear-gradient(135deg, var(--verde) 60%, var(--verde-claro));
color: #fff;
padding: 0;
box-shadow: 0 2px 12px rgba(0,0,0,.18);
}
.header-top {
padding: 20px 40px;
border-bottom: 2px solid rgba(255,255,255,.15);
text-align: center;
}
.header-top h1 {
font-size: 1.6rem;
font-weight: 800;
letter-spacing: .5px;
text-transform: uppercase;
}
.header-top p {
font-size: .95rem;
opacity: .9;
margin-top: 4px;
}
.header-banner {
background: var(--amarelo);
color: #1a1a1a;
text-align: center;
padding: 10px 20px;
font-size: .97rem;
font-weight: 600;
letter-spacing: .2px;
}
/* ===== HERO ===== */
.hero {
background: linear-gradient(135deg, #1b5e20 0%, #2e7d32 50%, #388e3c 100%);
color: #fff;
text-align: center;
padding: 48px 20px 36px;
}
.hero h2 {
font-size: 2rem;
font-weight: 800;
margin-bottom: 10px;
text-shadow: 0 2px 8px rgba(0,0,0,.2);
}
.hero p {
font-size: 1.08rem;
opacity: .92;
max-width: 620px;
margin: 0 auto;
line-height: 1.6;
}
.hero-badges {
display: flex;
justify-content: center;
gap: 14px;
margin-top: 22px;
flex-wrap: wrap;
}
.badge {
background: rgba(255,255,255,.18);
border: 1.5px solid rgba(255,255,255,.4);
border-radius: 50px;
padding: 6px 18px;
font-size: .85rem;
font-weight: 600;
backdrop-filter: blur(4px);
}
/* ===== STEPS ===== */
.steps-bar {
background: #fff;
border-bottom: 1px solid var(--cinza-borda);
padding: 18px 40px;
}
.steps {
display: flex;
align-items: center;
justify-content: center;
gap: 0;
max-width: 700px;
margin: 0 auto;
}
.step {
display: flex;
align-items: center;
gap: 8px;
flex: 1;
}
.step-num {
width: 32px; height: 32px;
border-radius: 50%;
background: var(--cinza-borda);
color: var(--texto-leve);
display: flex; align-items: center; justify-content: center;
font-weight: 700; font-size: .9rem;
flex-shrink: 0;
transition: background .3s, color .3s;
}
.step.active .step-num { background: var(--verde); color: #fff; }
.step.done .step-num { background: var(--verde-claro); color: #fff; }
.step-label {
font-size: .82rem;
color: var(--texto-leve);
font-weight: 600;
white-space: nowrap;
}
.step.active .step-label { color: var(--verde); }
.step.done .step-label { color: var(--verde-claro); }
.step-line {
flex: 1;
height: 2px;
background: var(--cinza-borda);
margin: 0 6px;
}
/* ===== MAIN LAYOUT ===== */
main {
max-width: 960px;
margin: 36px auto 60px;
padding: 0 16px;
}
/* ===== CARD ===== */
.card {
background: var(--cinza-card);
border-radius: var(--radius);
box-shadow: var(--sombra);
overflow: hidden;
margin-bottom: 28px;
}
.card-header {
background: linear-gradient(90deg, var(--verde), var(--verde-claro));
color: #fff;
padding: 16px 28px;
display: flex;
align-items: center;
gap: 12px;
}
.card-header .icon {
font-size: 1.5rem;
}
.card-header h3 {
font-size: 1.1rem;
font-weight: 700;
}
.card-header p {
font-size: .83rem;
opacity: .88;
margin-top: 2px;
}
.card-body {
padding: 28px 28px 24px;
}
/* ===== FORM GRID ===== */
.form-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 18px 22px;
}
.form-grid .full { grid-column: 1 / -1; }
.form-group {
display: flex;
flex-direction: column;
gap: 6px;
}
label {
font-size: .88rem;
font-weight: 600;
color: var(--texto);
}
label .obrig { color: var(--erro); margin-left: 2px; }
input[type="text"],
input[type="email"],
input[type="tel"],
input[type="date"],
select,
textarea {
width: 100%;
padding: 11px 14px;
border: 1.5px solid var(--cinza-borda);
border-radius: 7px;
font-size: .95rem;
color: var(--texto);
background: #fafafa;
transition: border .2s, box-shadow .2s;
font-family: inherit;
outline: none;
}
input:focus, select:focus, textarea:focus {
border-color: var(--verde-claro);
box-shadow: 0 0 0 3px rgba(76,175,80,.15);
background: #fff;
}
input.invalid, select.invalid, textarea.invalid {
border-color: var(--erro);
box-shadow: 0 0 0 3px rgba(198,40,40,.10);
}
.field-hint {
font-size: .78rem;
color: var(--texto-leve);
}
.field-error {
font-size: .78rem;
color: var(--erro);
display: none;
}
.field-error.show { display: block; }
textarea { resize: vertical; min-height: 100px; }
/* ===== UPLOAD ===== */
.upload-area {
border: 2px dashed var(--cinza-borda);
border-radius: 9px;
padding: 28px 20px;
text-align: center;
cursor: pointer;
transition: border .2s, background .2s;
position: relative;
background: #fafafa;
}
.upload-area:hover, .upload-area.dragover {
border-color: var(--verde-claro);
background: rgba(76,175,80,.05);
}
.upload-area input[type="file"] {
position: absolute;
inset: 0;
opacity: 0;
cursor: pointer;
width: 100%; height: 100%;
border: none;
box-shadow: none;
background: transparent;
padding: 0;
}
.upload-icon { font-size: 2.2rem; color: var(--verde-claro); }
.upload-label { font-size: .97rem; font-weight: 600; color: var(--texto); margin-top: 8px; }
.upload-hint { font-size: .8rem; color: var(--texto-leve); margin-top: 4px; }
.file-list {
margin-top: 14px;
display: flex;
flex-direction: column;
gap: 8px;
}
.file-item {
display: flex;
align-items: center;
gap: 10px;
background: #f1f8f1;
border: 1px solid #c8e6c9;
border-radius: 7px;
padding: 9px 14px;
font-size: .87rem;
}
.file-item .fi-name { flex: 1; color: var(--texto); font-weight: 500; word-break: break-all; }
.file-item .fi-size { color: var(--texto-leve); white-space: nowrap; }
.file-item .fi-remove {
background: none; border: none; cursor: pointer;
color: var(--erro); font-size: 1.1rem; line-height: 1;
padding: 0 2px; flex-shrink: 0;
}
.file-item .fi-remove:hover { opacity: .7; }
/* ===== CHECKBOX / RADIO ===== */
.check-group {
display: flex;
flex-direction: column;
gap: 8px;
}
.check-item {
display: flex;
align-items: flex-start;
gap: 10px;
cursor: pointer;
}
.check-item input[type="checkbox"],
.check-item input[type="radio"] {
width: 18px; height: 18px;
accent-color: var(--verde);
margin-top: 1px;
flex-shrink: 0;
border: none; box-shadow: none; padding: 0; background: transparent;
}
.check-item span {
font-size: .9rem;
color: var(--texto);
line-height: 1.45;
}
/* ===== RATING ===== */
.rating-row {
display: flex;
align-items: center;
gap: 8px;
flex-wrap: wrap;
}
.rating-row label.star-label {
font-size: .85rem;
font-weight: 400;
color: var(--texto-leve);
cursor: pointer;
}
.rating-row input[type="radio"] {
display: none;
}
.star { font-size: 1.7rem; cursor: pointer; color: #ccc; transition: color .15s; }
.star.on { color: var(--amarelo); }
/* ===== PROGRESS BAR ===== */
.progress-wrap { margin-bottom: 8px; }
.progress-label {
font-size: .82rem;
color: var(--texto-leve);
margin-bottom: 5px;
}
.progress-bar {
height: 7px;
background: #e0e0e0;
border-radius: 50px;
overflow: hidden;
}
.progress-fill {
height: 100%;
background: linear-gradient(90deg, var(--verde), var(--verde-claro));
border-radius: 50px;
width: 0%;
transition: width .4s ease;
}
/* ===== TERMS ===== */
.terms-box {
background: #f9fbe7;
border: 1px solid #dce775;
border-radius: 8px;
padding: 16px 18px;
font-size: .87rem;
color: #4e4e2a;
line-height: 1.6;
}
/* ===== BUTTONS ===== */
.btn-row {
display: flex;
gap: 14px;
justify-content: flex-end;
margin-top: 24px;
flex-wrap: wrap;
}
.btn {
padding: 12px 32px;
border-radius: 8px;
font-size: 1rem;
font-weight: 700;
cursor: pointer;
border: none;
transition: background .2s, transform .1s, box-shadow .2s;
display: inline-flex;
align-items: center;
gap: 8px;
font-family: inherit;
}
.btn:active { transform: scale(.98); }
.btn-outline {
background: #fff;
border: 2px solid var(--cinza-borda);
color: var(--texto-leve);
}
.btn-outline:hover { border-color: var(--verde); color: var(--verde); }
.btn-primary {
background: linear-gradient(135deg, var(--verde), var(--verde-claro));
color: #fff;
box-shadow: 0 4px 14px rgba(46,125,50,.30);
}
.btn-primary:hover {
background: linear-gradient(135deg, var(--verde-hover), var(--verde));
box-shadow: 0 6px 20px rgba(46,125,50,.40);
}
.btn-primary:disabled {
opacity: .6; cursor: not-allowed; transform: none;
}
/* ===== TOAST / ALERT ===== */
.toast {
position: fixed;
top: 24px; right: 24px;
background: #fff;
border-radius: 10px;
box-shadow: 0 6px 28px rgba(0,0,0,.16);
padding: 18px 22px;
max-width: 360px;
display: flex;
gap: 14px;
align-items: flex-start;
z-index: 9999;
transform: translateX(120%);
transition: transform .35s cubic-bezier(.34,1.56,.64,1);
}
.toast.show { transform: translateX(0); }
.toast-icon { font-size: 1.6rem; flex-shrink: 0; }
.toast-title { font-weight: 700; font-size: 1rem; }
.toast-msg { font-size: .87rem; color: var(--texto-leve); margin-top: 3px; }
/* ===== SUCCESS SCREEN ===== */
.success-screen {
display: none;
text-align: center;
padding: 60px 28px;
}
.success-screen.show { display: block; }
.success-circle {
width: 90px; height: 90px;
background: linear-gradient(135deg, var(--verde), var(--verde-claro));
border-radius: 50%;
display: flex; align-items: center; justify-content: center;
font-size: 2.8rem;
margin: 0 auto 24px;
box-shadow: 0 8px 28px rgba(46,125,50,.30);
}
.success-screen h2 { font-size: 1.8rem; color: var(--verde); margin-bottom: 10px; }
.success-screen p { color: var(--texto-leve); font-size: 1rem; line-height: 1.6; max-width: 480px; margin: 0 auto 8px; }
.protocol-box {
background: #f1f8f1;
border: 1.5px solid #c8e6c9;
border-radius: 8px;
padding: 14px 24px;
display: inline-block;
margin: 20px auto 0;
font-size: 1rem;
}
.protocol-box strong { color: var(--verde); font-size: 1.3rem; display: block; letter-spacing: 1px; }
/* ===== INFO BOX ===== */
.info-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 16px;
margin-bottom: 28px;
}
.info-card {
background: #fff;
border-radius: 10px;
box-shadow: var(--sombra);
padding: 20px 18px;
text-align: center;
border-top: 3px solid var(--verde-claro);
}
.info-card .ic-icon { font-size: 1.8rem; margin-bottom: 8px; }
.info-card h4 { font-size: .95rem; color: var(--texto); font-weight: 700; margin-bottom: 5px; }
.info-card p { font-size: .82rem; color: var(--texto-leve); line-height: 1.5; }
/* ===== FOOTER ===== */
footer {
background: #1b2e1b;
color: rgba(255,255,255,.75);
text-align: center;
padding: 24px 20px;
font-size: .85rem;
}
footer a { color: var(--verde-claro); text-decoration: none; }
/* ===== RESPONSIVE ===== */
@media (max-width: 680px) {
.header-top { padding: 14px 18px; }
.header-top h1 { font-size: 1.2rem; }
.hero h2 { font-size: 1.4rem; }
.form-grid { grid-template-columns: 1fr; }
.form-grid .full { grid-column: 1; }
.info-grid { grid-template-columns: 1fr; }
.steps-bar { padding: 14px 18px; }
.step-label { display: none; }
.card-body { padding: 18px 16px; }
.btn-row { justify-content: stretch; }
.btn { width: 100%; justify-content: center; }
main { margin-top: 20px; }
}
</style>
</head>
<body>
<!-- ===== HEADER ===== -->
<header>
<div class="header-top">
<h1>Câmara Municipal de Marechal Floriano</h1>
<p>Estado do Espírito Santo</p>
</div>
<div class="header-banner">
📋 Portal de Participação Cidadã — Envio de Projetos e Sugestões
</div>
</header>
<!-- ===== HERO ===== -->
<div class="hero">
<h2>Sua ideia pode transformar Marechal Floriano</h2>
<p>Participe do Legislativo Municipal! Envie seu projeto ou sugestão e contribua para o desenvolvimento da nossa cidade.</p>
<div class="hero-badges">
<span class="badge">🤝 Participação Popular</span>
<span class="badge">📬 Envio direto para a Câmara</span>
<span class="badge">🔒 Dados protegidos (LGPD)</span>
</div>
</div>
<!-- ===== STEPS ===== -->
<div class="steps-bar">
<div class="steps" id="stepsBar">
<div class="step active" id="s1">
<div class="step-num">1</div>
<span class="step-label">Dados Pessoais</span>
</div>
<div class="step-line"></div>
<div class="step" id="s2">
<div class="step-num">2</div>
<span class="step-label">Projeto / Sugestão</span>
</div>
<div class="step-line"></div>
<div class="step" id="s3">
<div class="step-num">3</div>
<span class="step-label">Anexos</span>
</div>
<div class="step-line"></div>
<div class="step" id="s4">
<div class="step-num">4</div>
<span class="step-label">Revisão & Envio</span>
</div>
</div>
</div>
<!-- ===== MAIN ===== -->
<main>
<!-- Info Cards -->
<div class="info-grid">
<div class="info-card">
<div class="ic-icon">📝</div>
<h4>Como funciona?</h4>
<p>Preencha o formulário com seus dados e descreva seu projeto em detalhes.</p>
</div>
<div class="info-card">
<div class="ic-icon">🔍</div>
<h4>Análise</h4>
<p>A Câmara Municipal analisará sua sugestão conforme as normas legislativas.</p>
</div>
<div class="info-card">
<div class="ic-icon">✅</div>
<h4>Registro</h4>
<p>Sua proposta ficará registrada no e-mail oficial da Câmara Municipal.</p>
</div>
</div>
<!-- ===== FORM ===== -->
<!-- IMPORTANTE: action usa mailto para enviar ao email da Câmara -->
<form id="mainForm" novalidate>
<!-- PROGRESSO -->
<div class="progress-wrap card" style="padding:16px 24px;">
<div class="progress-label" id="progressLabel">Progresso do formulário: 0%</div>
<div class="progress-bar"><div class="progress-fill" id="progressFill"></div></div>
</div>
<!-- ======== SEÇÃO 1: DADOS PESSOAIS ======== -->
<div class="card" id="sec1">
<div class="card-header">
<span class="icon">👤</span>
<div>
<h3>1. Dados Pessoais do Cidadão</h3>
<p>Informações necessárias para identificação e retorno da análise.</p>
</div>
</div>
<div class="card-body">
<div class="form-grid">
<div class="form-group full">
<label for="nome">Nome completo <span class="obrig">*</span></label>
<input type="text" id="nome" name="nome" placeholder="Digite seu nome completo" autocomplete="name"/>
<span class="field-error" id="err-nome">Por favor, informe seu nome completo.</span>
</div>
<div class="form-group">
<label for="cpf">CPF <span class="obrig">*</span></label>
<input type="text" id="cpf" name="cpf" placeholder="000.000.000-00" maxlength="14" autocomplete="off"/>
<span class="field-error" id="err-cpf">CPF inválido ou não preenchido.</span>
</div>
<div class="form-group">
<label for="rg">RG</label>
<input type="text" id="rg" name="rg" placeholder="Ex: 1234567 SSP/ES"/>
</div>
<div class="form-group">
<label for="nascimento">Data de nascimento <span class="obrig">*</span></label>
<input type="date" id="nascimento" name="nascimento"/>
<span class="field-error" id="err-nascimento">Informe sua data de nascimento.</span>
</div>
<div class="form-group">
<label for="sexo">Gênero</label>
<select id="sexo" name="sexo">
<option value="">Selecione (opcional)</option>
<option>Masculino</option>
<option>Feminino</option>
<option>Não-binário</option>
<option>Prefiro não informar</option>
</select>
</div>
<div class="form-group">
<label for="tel">Telefone / WhatsApp <span class="obrig">*</span></label>
<input type="tel" id="tel" name="tel" placeholder="(28) 99999-9999" maxlength="15" autocomplete="tel"/>
<span class="field-error" id="err-tel">Informe um telefone válido.</span>
</div>
<div class="form-group">
<label for="email">E-mail <span class="obrig">*</span></label>
<input type="email" id="email" name="email" placeholder="seu@email.com" autocomplete="email"/>
<span class="field-error" id="err-email">Informe um e-mail válido.</span>
</div>
<div class="form-group full">
<label for="endereco">Endereço completo <span class="obrig">*</span></label>
<input type="text" id="endereco" name="endereco" placeholder="Rua, número, bairro"/>
<span class="field-error" id="err-endereco">Informe seu endereço.</span>
</div>
<div class="form-group">
<label for="bairro">Bairro / Localidade <span class="obrig">*</span></label>
<select id="bairro" name="bairro">
<option value="">Selecione o bairro</option>
<option>Centro</option>
<option>Bairro dos Estados</option>
<option>São João</option>
<option>Bela Vista</option>
<option>Vila Nova</option>
<option>Santa Terezinha</option>
<option>São Luiz</option>
<option>Jardim América</option>
<option>Outro</option>
</select>
<span class="field-error" id="err-bairro">Selecione o bairro.</span>
</div>
<div class="form-group">
<label for="cep">CEP</label>
<input type="text" id="cep" name="cep" placeholder="29.000-000" maxlength="10"/>
</div>
<div class="form-group full">
<label>Vínculo com o município <span class="obrig">*</span></label>
<div class="check-group" style="flex-direction:row;flex-wrap:wrap;gap:14px;">
<label class="check-item">
<input type="radio" name="vinculo" value="Morador"/> <span>Morador(a)</span>
</label>
<label class="check-item">
<input type="radio" name="vinculo" value="Comerciante"/> <span>Comerciante</span>
</label>
<label class="check-item">
<input type="radio" name="vinculo" value="Servidor público"/> <span>Servidor público</span>
</label>
<label class="check-item">
<input type="radio" name="vinculo" value="Outro"/> <span>Outro</span>
</label>
</div>
<span class="field-error" id="err-vinculo">Selecione seu vínculo.</span>
</div>
</div>
</div>
</div>
<!-- ======== SEÇÃO 2: PROJETO ======== -->
<div class="card" id="sec2">
<div class="card-header">
<span class="icon">💡</span>
<div>
<h3>2. Projeto ou Sugestão</h3>
<p>Descreva detalhadamente sua ideia para que possa ser avaliada adequadamente.</p>
</div>
</div>
<div class="card-body">
<div class="form-grid">
<div class="form-group full">
<label for="titulo">Título do projeto / sugestão <span class="obrig">*</span></label>
<input type="text" id="titulo" name="titulo" placeholder="Ex: Construção de academia ao ar livre no bairro X"/>
<span class="field-error" id="err-titulo">Informe o título do projeto.</span>
</div>
<div class="form-group">
<label for="categoria">Área temática <span class="obrig">*</span></label>
<select id="categoria" name="categoria">
<option value="">Selecione a área</option>
<option>🏗️ Infraestrutura e obras</option>
<option>🎓 Educação</option>
<option>🏥 Saúde</option>
<option>🌿 Meio Ambiente</option>
<option>🌾 Agricultura e rural</option>
<option>🚌 Transporte e mobilidade</option>
<option>🏘️ Habitação</option>
<option>🎭 Cultura, esporte e lazer</option>
<option>🔒 Segurança pública</option>
<option>💼 Emprego e renda</option>
<option>👴 Assistência social</option>
<option>💻 Tecnologia e inovação</option>
<option>🏛️ Gestão pública</option>
<option>Outra</option>
</select>
<span class="field-error" id="err-categoria">Selecione a área temática.</span>
</div>
<div class="form-group">
<label for="prioridade">Nível de urgência / prioridade</label>
<select id="prioridade" name="prioridade">
<option value="">Selecione</option>
<option>🔴 Urgente – afeta segurança imediata</option>
<option>🟠 Alta – impacto significativo</option>
<option>🟡 Média – melhoria importante</option>
<option>🟢 Baixa – melhoria progressiva</option>
</select>
</div>
<div class="form-group full">
<label for="local">Local específico de aplicação</label>
<input type="text" id="local" name="local" placeholder="Ex: Rua, bairro, ponto de referência"/>
</div>
<div class="form-group full">
<label for="descricao">Descrição detalhada <span class="obrig">*</span></label>
<textarea id="descricao" name="descricao" rows="5"
placeholder="Descreva o problema identificado, a solução proposta, a população beneficiada e os possíveis impactos positivos..."></textarea>
<span class="field-hint" id="charCount">0 / 2000 caracteres</span>
<span class="field-error" id="err-descricao">Descreva o projeto com pelo menos 30 caracteres.</span>
</div>
<div class="form-group full">
<label for="justificativa">Justificativa / Por que é importante?</label>
<textarea id="justificativa" name="justificativa" rows="3"
placeholder="Explique por que essa proposta é necessária e quem se beneficiará..."></textarea>
</div>
<div class="form-group full">
<label for="custo">Estimativa de custo (se souber)</label>
<input type="text" id="custo" name="custo" placeholder="Ex: R$ 50.000,00 ou Não sei informar"/>
</div>
<div class="form-group full">
<label>Beneficiários estimados</label>
<div class="check-group" style="flex-direction:row;flex-wrap:wrap;gap:14px;">
<label class="check-item"><input type="checkbox" name="benef" value="Crianças"/><span>Crianças</span></label>
<label class="check-item"><input type="checkbox" name="benef" value="Jovens"/><span>Jovens</span></label>
<label class="check-item"><input type="checkbox" name="benef" value="Adultos"/><span>Adultos</span></label>
<label class="check-item"><input type="checkbox" name="benef" value="Idosos"/><span>Idosos</span></label>
<label class="check-item"><input type="checkbox" name="benef" value="PCDs"/><span>PCDs</span></label>
<label class="check-item"><input type="checkbox" name="benef" value="Agricultores"/><span>Agricultores</span></label>
<label class="check-item"><input type="checkbox" name="benef" value="Comunidade geral"/><span>Comunidade geral</span></label>
</div>
</div>
<div class="form-group full">
<label>Avalie a urgência do tema (1 a 5 estrelas)</label>
<div class="rating-row" id="starRating">
<span class="star" data-val="1">★</span>
<span class="star" data-val="2">★</span>
<span class="star" data-val="3">★</span>
<span class="star" data-val="4">★</span>
<span class="star" data-val="5">★</span>
<span id="starLabel" style="font-size:.85rem;color:var(--texto-leve);margin-left:6px;"></span>
</div>
<input type="hidden" id="rating" name="rating" value="0"/>
</div>
</div>
</div>
</div>
<!-- ======== SEÇÃO 3: ANEXOS ======== -->
<div class="card" id="sec3">
<div class="card-header">
<span class="icon">📎</span>
<div>
<h3>3. Documentos e Anexos</h3>
<p>Fotos, mapas, planilhas ou qualquer material de suporte.</p>
</div>
</div>
<div class="card-body">
<div class="upload-area" id="uploadArea">
<input type="file" id="fileInput" name="arquivos" multiple
accept=".pdf,.doc,.docx,.xls,.xlsx,.jpg,.jpeg,.png,.gif,.mp4,.ppt,.pptx"/>
<div class="upload-icon">📂</div>
<div class="upload-label">Arraste arquivos aqui ou clique para selecionar</div>
<div class="upload-hint">Formatos aceitos: PDF, Word, Excel, Imagens (JPG, PNG), PPT · Máx. 10 MB por arquivo · Até 10 arquivos</div>
</div>
<div class="file-list" id="fileList"></div>
<div style="margin-top:20px;">
<label for="linkExterno">Link externo (Google Drive, YouTube, etc.)</label>
<input type="text" id="linkExterno" name="linkExterno"
placeholder="https://drive.google.com/..."/>
<span class="field-hint">Caso tenha material armazenado em nuvem, cole o link compartilhável aqui.</span>
</div>
<div style="margin-top:18px;">
<label for="obsAnexo">Observações sobre os anexos</label>
<textarea id="obsAnexo" name="obsAnexo" rows="2"
placeholder="Descreva brevemente cada anexo, se necessário..."></textarea>
</div>
</div>
</div>
<!-- ======== SEÇÃO 4: REVISÃO & ENVIO ======== -->
<div class="card" id="sec4">
<div class="card-header">
<span class="icon">📋</span>
<div>
<h3>4. Revisão, Declarações e Envio</h3>
<p>Leia com atenção antes de confirmar o envio.</p>
</div>
</div>
<div class="card-body">
<!-- Resumo dinâmico -->
<div id="resumo" style="margin-bottom:22px;">
<h4 style="margin-bottom:12px;color:var(--verde);font-size:1rem;">📄 Resumo do formulário</h4>
<div id="resumoContent" style="background:#f9f9f9;border:1px solid #e0e0e0;border-radius:8px;padding:16px;font-size:.89rem;color:var(--texto-leve);line-height:1.8;">
Preencha as seções anteriores para visualizar o resumo aqui.
</div>
</div>
<div class="terms-box" style="margin-bottom:18px;">
<strong>📜 Termos e Condições de uso</strong><br/><br/>
Ao submeter este formulário, o(a) cidadão(ã) declara que as informações prestadas são
verdadeiras e assume total responsabilidade pelo conteúdo enviado. A Câmara Municipal
de Marechal Floriano se compromete a analisar a sugestão e a proteger os dados pessoais
conforme a <strong>Lei Geral de Proteção de Dados (LGPD – Lei 13.709/2018)</strong>.
</div>
<div class="check-group">
<label class="check-item">
<input type="checkbox" id="chkVeracidade" name="chkVeracidade"/>
<span>Declaro que as informações prestadas são verdadeiras e de minha responsabilidade. <span class="obrig">*</span></span>
</label>
<label class="check-item">
<input type="checkbox" id="chkLGPD" name="chkLGPD"/>
<span>Autorizo o tratamento dos meus dados pessoais pela Câmara Municipal de Marechal Floriano conforme a LGPD. <span class="obrig">*</span></span>
</label>
<label class="check-item">
<input type="checkbox" id="chkPublico" name="chkPublico"/>
<span>Concordo que minha sugestão poderá ser divulgada publicamente (sem meus dados pessoais identificáveis).</span>
</label>
<label class="check-item">
<input type="checkbox" id="chkNewsletter" name="chkNewsletter"/>
<span>Desejo receber atualizações por e-mail sobre o andamento da minha sugestão.</span>
</label>
</div>
<span class="field-error" id="err-terms">Você deve aceitar os termos obrigatórios para enviar.</span>
<div class="btn-row">
<button type="button" class="btn btn-outline" onclick="limparForm()">🗑️ Limpar formulário</button>
<button type="button" class="btn btn-outline" onclick="salvarRascunho()">💾 Salvar rascunho</button>
<button type="submit" class="btn btn-primary" id="btnEnviar">
📬 Enviar projeto
</button>
</div>
</div>
</div>
</form>
<!-- ===== TELA DE SUCESSO (apenas visual) ===== -->
<div class="card success-screen" id="successScreen">
<div class="success-circle">✅</div>
<h2>Projeto pronto para envio!</h2>
<p>Seu projeto foi montado e está pronto para ser enviado ao e-mail da Câmara Municipal de Marechal Floriano.</p>
<p>Se o aplicativo de e-mail não abrir automaticamente, copie e cole as informações no seu e-mail e envie para <strong>camara@cmmarechalfloriano</strong>.</p>
<div class="protocol-box">
Referência gerada:<br/>
<strong id="numProtocolo"></strong>
</div>
<p style="margin-top:20px;font-size:.85rem;">Guarde esta referência para seu controle pessoal.</p>
<div class="btn-row" style="justify-content:center;margin-top:28px;">
<button class="btn btn-primary" onclick="novoEnvio()">➕ Enviar nova sugestão</button>
</div>
</div>
</main>
<!-- ===== FOOTER ===== -->
<footer>
<p><strong>Câmara Municipal de Marechal Floriano</strong> | Estado do Espírito Santo</p>
<p style="margin-top:6px;">E-mail oficial para envio de sugestões: <a href="mailto:camara@cmmarechalfloriano">camara@cmmarechalfloriano</a></p>
<p style="margin-top:8px;font-size:.78rem;opacity:.6;">
© 2025 Câmara Municipal de Marechal Floriano · Todos os direitos reservados ·
Dados protegidos pela LGPD
</p>
</footer>
<!-- ===== TOAST ===== -->
<div class="toast" id="toast">
<div class="toast-icon" id="toastIcon"></div>
<div>
<div class="toast-title" id="toastTitle"></div>
<div class="toast-msg" id="toastMsg"></div>
</div>
</div>
<!-- ===== SCRIPTS ===== -->
<script>
/* -------- MÁSCARAS -------- */
document.getElementById('cpf').addEventListener('input', function(){
let v = this.value.replace(/\D/g,'').slice(0,11);
v = v.replace(/(\d{3})(\d)/,'$1.$2')
.replace(/(\d{3})(\d)/,'$1.$2')
.replace(/(\d{3})(\d{1,2})
$
/,'$1-$2');
this.value = v;
});
document.getElementById('tel').addEventListener('input', function(){
let v = this.value.replace(/\D/g,'').slice(0,11);
if(v.length >= 11) v = v.replace(/(\d{2})(\d{5})(\d{4})/,'($1) $2-$3');
else if(v.length >= 7) v = v.replace(/(\d{2})(\d{4,5})(\d*)/,'($1) $2-$3');
else if(v.length >= 3) v = v.replace(/(\d{2})(\d*)/,'($1) $2');
this.value = v;
});
document.getElementById('cep').addEventListener('input', function(){
let v = this.value.replace(/\D/g,'').slice(0,8);
v = v.replace(/(\d{5})(\d)/,'$1-$2');
this.value = v;
});
/* -------- CONTADOR DE CARACTERES -------- */
document.getElementById('descricao').addEventListener('input', function(){
const l = this.value.length;
document.getElementById('charCount').textContent = l + ' / 2000 caracteres';
if(l > 2000) this.value = this.value.slice(0,2000);
updateProgress();
});
/* -------- ESTRELAS -------- */
const stars = document.querySelectorAll('.star');
const starLabels = ['','Muito baixa','Baixa','Média','Alta','Muito alta'];
let ratingVal = 0;
stars.forEach(s => {
s.addEventListener('click', ()=>{
ratingVal = parseInt(s.dataset.val);
document.getElementById('rating').value = ratingVal;
document.getElementById('starLabel').textContent = starLabels[ratingVal];
updateStars(ratingVal);
});
s.addEventListener('mouseenter',()=> updateStars(parseInt(s.dataset.val)));
s.addEventListener('mouseleave',()=> updateStars(ratingVal));
});
function updateStars(n){
stars.forEach(s => s.classList.toggle('on', parseInt(s.dataset.val) <= n));
}
/* -------- UPLOAD (apenas visual; mailto não envia anexos) -------- */
const fileInput = document.getElementById('fileInput');
const fileList = document.getElementById('fileList');
const uploadArea = document.getElementById('uploadArea');
let files = [];
fileInput.addEventListener('change', e => addFiles(e.target.files));
uploadArea.addEventListener('dragover', e=>{ e.preventDefault(); uploadArea.classList.add('dragover'); });
uploadArea.addEventListener('dragleave',()=> uploadArea.classList.remove('dragover'));
uploadArea.addEventListener('drop', e=>{
e.preventDefault();
uploadArea.classList.remove('dragover');
addFiles(e.dataTransfer.files);
});
function addFiles(newFiles){
for(const f of newFiles){
if(files.length >= 10){ showToast('⚠️','Limite atingido','Máximo de 10 arquivos (serão apenas indicados no e-mail).','#e65100'); break; }
if(f.size > 10*1024*1024){ showToast('⚠️','Arquivo grande',`"${f.name}" excede 10 MB.','#e65100'); continue; }
if(files.find(x=>x.name===f.name)) continue;
files.push(f);
}
renderFiles();
updateProgress();
}
function renderFiles(){
fileList.innerHTML = '';
files.forEach((f,i)=>{
const div = document.createElement('div');
div.className = 'file-item';
div.innerHTML = `<span>📄</span>
<span class="fi-name">${f.name}</span>
<span class="fi-size">${(f.size/1024).toFixed(0)} KB</span>
<button type="button" class="fi-remove" onclick="removeFile(${i})" title="Remover">✕</button>`;
fileList.appendChild(div);
});
}
function removeFile(i){
files.splice(i,1);
renderFiles();
updateProgress();
}
/* -------- PROGRESSO -------- */
const progressFields = ['nome','cpf','nascimento','tel','email','endereco','bairro','titulo','categoria','descricao'];
function updateProgress(){
let filled = 0;
progressFields.forEach(id=>{
const el = document.getElementById(id);
if(el && el.value.trim().length > 0) filled++;
});
if(document.querySelector('input[name="vinculo"]:checked')) filled++;
if(files.length > 0) filled++;
if(document.getElementById('chkVeracidade').checked &&
document.getElementById('chkLGPD').checked) filled++;
const pct = Math.round((filled / (progressFields.length + 3)) * 100);
document.getElementById('progressFill').style.width = Math.min(pct,100)+'%';
document.getElementById('progressLabel').textContent = `Progresso do formulário: ${Math.min(pct,100)}%`;
const s1done = ['nome','cpf','nascimento','tel','email','endereco','bairro'].every(id=>document.getElementById(id).value.trim());
const s2done = ['titulo','categoria','descricao'].every(id=>document.getElementById(id).value.trim());
setStep(1, s1done ? 'done' : 'active');
setStep(2, s2done ? 'done' : s1done ? 'active' : '');
setStep(3, files.length>0 ? 'done' : s2done ? 'active' : '');
setStep(4, (document.getElementById('chkVeracidade').checked && document.getElementById('chkLGPD').checked) ? 'active' : '');
updateResumo();
}
function setStep(n, state){
const el = document.getElementById('s'+n);
el.classList.remove('active','done');
if(state) el.classList.add(state);
}
/* -------- RESUMO -------- */
function updateResumo(){
const nome = document.getElementById('nome').value || '–';
const email = document.getElementById('email').value || '–';
const tel = document.getElementById('tel').value || '–';
const titulo= document.getElementById('titulo').value || '–';
const cat = document.getElementById('categoria').value || '–';
const desc = document.getElementById('descricao').value || '–';
const vinc = (document.querySelector('input[name="vinculo"]:checked') || {}).value || '–';
const nArq = files.length;
document.getElementById('resumoContent').innerHTML = `
<b>👤 Cidadão:</b> ${nome} | <b>Tel:</b> ${tel} | <b>E-mail:</b> ${email}<br/>
<b>🔗 Vínculo:</b> ${vinc}<br/>
<b>💡 Título:</b> ${titulo}<br/>
<b>📂 Área:</b> ${cat}<br/>
<b>📝 Descrição:</b> ${desc.slice(0,200)}${desc.length>200?'…':''}<br/>
<b>📎 Anexos selecionados:</b> ${nArq} arquivo(s)
`;
}
document.querySelectorAll('input, select, textarea').forEach(el=>{
el.addEventListener('change', updateProgress);
el.addEventListener('input', updateProgress);
});
/* -------- VALIDAÇÃO -------- */
function validarCPF(cpf){
cpf = cpf.replace(/\D/g,'');
if(cpf.length!==11 || /^(\d)\1+$/.test(cpf)) return false;
let s=0, r;
for(let i=1;i<=9;i++) s+= parseInt(cpf[i-1])*(11-i);
r=(s*10)%11; if(r===10||r===11) r=0;
if(r!==parseInt(cpf[9])) return false;
s=0;
for(let i=1;i<=10;i++) s+=parseInt(cpf[i-1])*(12-i);
r=(s*10)%11; if(r===10||r===11) r=0;
return r===parseInt(cpf[10]);
}
function setErr(id, show){
const el = document.getElementById('err-'+id);
const inp= document.getElementById(id) || document.querySelector(`[name="${id}"]`);
if(el) el.classList.toggle('show', show);
if(inp) inp.classList.toggle('invalid', show);
return show;
}
function validarForm(){
let ok = true;
if(!document.getElementById('nome').value.trim()) ok = !setErr('nome',true);
else setErr('nome',false);
if(!validarCPF(document.getElementById('cpf').value)) ok = !setErr('cpf',true);
else setErr('cpf',false);
if(!document.getElementById('nascimento').value) ok = !setErr('nascimento',true);
else setErr('nascimento',false);
const tel = document.getElementById('tel').value.replace(/\D/g,'');
if(tel.length < 10) ok = !setErr('tel',true);
else setErr('tel',false);
const emailRe = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if(!emailRe.test(document.getElementById('email').value)) ok = !setErr('email',true);
else setErr('email',false);
if(!document.getElementById('endereco').value.trim()) ok = !setErr('endereco',true);
else setErr('endereco',false);
if(!document.getElementById('bairro').value) ok = !setErr('bairro',true);
else setErr('bairro',false);
if(!document.querySelector('input[name="vinculo"]:checked')) ok = !setErr('vinculo',true);
else setErr('vinculo',false);
if(!document.getElementById('titulo').value.trim()) ok = !setErr('titulo',true);
else setErr('titulo',false);
if(!document.getElementById('categoria').value) ok = !setErr('categoria',true);
else setErr('categoria',false);
if(document.getElementById('descricao').value.trim().length < 30) ok = !setErr('descricao',true);
else setErr('descricao',false);
const termsOk = document.getElementById('chkVeracidade').checked && document.getElementById('chkLGPD').checked;
document.getElementById('err-terms').classList.toggle('show', !termsOk);
if(!termsOk) ok = false;
return ok;
}
/* -------- ENVIO VIA MAILTO -------- */
document.getElementById('mainForm').addEventListener('submit', function(e){
e.preventDefault();
if(!validarForm()){
showToast('❗','Atenção','Preencha todos os campos obrigatórios corretamente.','#c62828');
document.querySelector('.invalid')?.scrollIntoView({behavior:'smooth',block:'center'});
return;
}
const btn = document.getElementById('btnEnviar');
btn.disabled = true;
btn.textContent = '⏳ Preparando e-mail...';
const form = this;
// Monta corpo do e-mail em texto simples
const nome = form.nome.value;
const assunto = encodeURIComponent('[Portal Cidadão] Sugestão de Projeto - ' + (form.titulo.value || 'Sem título'));
let corpo = '';
corpo += 'DADOS DO CIDADÃO:%0D%0A';
corpo += 'Nome: ' + form.nome.value + '%0D%0A';
corpo += 'CPF: ' + form.cpf.value + '%0D%0A';
corpo += 'RG: ' + (form.rg.value || '-') + '%0D%0A';
corpo += 'Data de Nascimento: ' + (form.nascimento.value || '-') + '%0D%0A';
corpo += 'Gênero: ' + (form.sexo.value || '-') + '%0D%0A';
corpo += 'Telefone: ' + form.tel.value + '%0D%0A';
corpo += 'E-mail: ' + form.email.value + '%0D%0A';
corpo += 'Endereço: ' + form.endereco.value + '%0D%0A';
corpo += 'Bairro: ' + form.bairro.value + '%0D%0A';
corpo += 'CEP: ' + (form.cep.value || '-') + '%0D%0A';
corpo += 'Vínculo: ' + ((document.querySelector('input[name="vinculo"]:checked')||{}).value || '-') + '%0D%0A';
corpo += '%0D%0A';
corpo += 'DADOS DO PROJETO / SUGESTÃO:%0D%0A';
corpo += 'Título: ' + (form.titulo.value || '-') + '%0D%0A';
corpo += 'Área temática: ' + (form.categoria.value || '-') + '%0D%0A';
corpo += 'Prioridade: ' + (form.prioridade.value || '-') + '%0D%0A';
corpo += 'Local de aplicação: ' + (form.local.value || '-') + '%0D%0A';
corpo += '%0D%0ADescrição:%0D%0A' + (form.descricao.value || '-') + '%0D%0A';
corpo += '%0D%0AJustificativa:%0D%0A' + (form.justificativa.value || '-') + '%0D%0A';
corpo += '%0D%0AEstimativa de custo: ' + (form.custo.value || '-') + '%0D%0A';
const benefs = Array.from(document.querySelectorAll('input[name="benef"]:checked')).map(b=>b.value);
corpo += 'Beneficiários estimados: ' + (benefs.length ? benefs.join(', ') : '-') + '%0D%0A';
corpo += 'Urgência (1-5): ' + (form.rating.value || '0') + '%0D%0A';
corpo += '%0D%0AANEXOS (APENAS LISTA – anexar manualmente ao e-mail):%0D%0A';
if(files.length){
files.forEach((f,i)=>{ corpo += (i+1) + ') ' + f.name + ' (' + Math.round(f.size/1024) + ' KB)%0D%0A'; });
}else{
corpo += 'Nenhum arquivo selecionado.%0D%0A';
}
corpo += '%0D%0ALink externo: ' + (form.linkExterno.value || '-') + '%0D%0A';
corpo += 'Observações sobre anexos: ' + (form.obsAnexo.value || '-') + '%0D%0A';
corpo += '%0D%0ADECLARAÇÕES:%0D%0A';
corpo += 'Veracidade das informações: ' + (form.chkVeracidade.checked ? 'SIM' : 'NÃO') + '%0D%0A';
corpo += 'Autorização LGPD: ' + (form.chkLGPD.checked ? 'SIM' : 'NÃO') + '%0D%0A';
corpo += 'Autorização para divulgação pública (sem dados pessoais): ' + (form.chkPublico.checked ? 'SIM' : 'NÃO') + '%0D%0A';
corpo += 'Deseja receber atualizações: ' + (form.chkNewsletter.checked ? 'SIM' : 'NÃO') + '%0D%0A';
const corpoEncoded = encodeURIComponent('').replace('%20',' ') + corpo;
const mailtoLink = `mailto:camara@cmmarechalfloriano?subject=${assunto}&body=${corpoEncoded}`;
// Gera uma referência simples
const protocolo = 'CMF-' + new Date().getFullYear() + '-' + Math.floor(100000+Math.random()*900000);
document.getElementById('numProtocolo').textContent = protocolo;
// Exibe tela de sucesso (orientação) e abre e-mail
document.getElementById('mainForm').style.display = 'none';
document.getElementById('successScreen').classList.add('show');
window.scrollTo({top:0,behavior:'smooth'});
showToast('✅','Formulário pronto','Seu e-mail será aberto para envio à Câmara.','#2e7d32');
// Abre o app de e-mail
window.location.href = mailtoLink;
btn.disabled = false;
btn.textContent = '📬 Enviar projeto';
});
/* -------- TOAST -------- */
function showToast(icon, title, msg, color){
const t = document.getElementById('toast');
document.getElementById('toastIcon').textContent = icon;
document.getElementById('toastTitle').textContent = title;
document.getElementById('toastMsg').textContent = msg;
t.style.borderLeft = '4px solid ' + color;
t.classList.add('show');
setTimeout(()=> t.classList.remove('show'), 4000);
}
/* -------- LIMPAR -------- */
function limparForm(){
if(!confirm('Tem certeza que deseja limpar todos os dados preenchidos?')) return;
document.getElementById('mainForm').reset();
files = [];
renderFiles();
ratingVal = 0;
updateStars(0);
document.getElementById('starLabel').textContent = '';
document.querySelectorAll('.invalid').forEach(el=>el.classList.remove('invalid'));
document.querySelectorAll('.field-error').forEach(el=>el.classList.remove('show'));
updateProgress();
showToast('🗑️','Formulário limpo','Todos os dados foram removidos.','#555');
}
/* -------- RASCUNHO -------- */
function salvarRascunho(){
const data = {
nome: document.getElementById('nome').value,
cpf: document.getElementById('cpf').value,
email: document.getElementById('email').value,
tel: document.getElementById('tel').value,
endereco: document.getElementById('endereco').value,
titulo: document.getElementById('titulo').value,
categoria: document.getElementById('categoria').value,
descricao: document.getElementById('descricao').value,
savedAt: new Date().toLocaleString('pt-BR')
};
localStorage.setItem('cmf_rascunho', JSON.stringify(data));
showToast('💾','Rascunho salvo',`Salvo às ${data.savedAt}`,'#1565c0');
}
// Carrega rascunho se existir
(function(){
const d = localStorage.getItem('cmf_rascunho');
if(!d) return;
try{
const r = JSON.parse(d);
if(confirm(`Encontramos um rascunho salvo em ${r.savedAt}. Deseja carregá-lo?`)){
['nome','cpf','email','tel','endereco','titulo','categoria','descricao'].forEach(k=>{
if(r[k]) document.getElementById(k).value = r[k];
});
updateProgress();
}
}catch(e){}
})();
/* -------- NOVO ENVIO -------- */
function novoEnvio(){
document.getElementById('successScreen').classList.remove('show');
document.getElementById('mainForm').style.display = '';
document.getElementById('mainForm').reset();
files = [];
renderFiles();
ratingVal = 0;
updateStars(0);
document.getElementById('starLabel').textContent = '';
document.querySelectorAll('.invalid').forEach(el=>el.classList.remove('invalid'));
document.querySelectorAll('.field-error').forEach(el=>el.classList.remove('show'));
updateProgress();
}
</script>
</body>
</html>