From 210264be25dee373a469d47beeaccd2d9629f752 Mon Sep 17 00:00:00 2001 From: Higor Date: Wed, 14 Oct 2026 21:54:38 -0300 Subject: [PATCH 1/8] feat(ui): implementar navbar responsiva (#01), secao sobre (#02) e pagina do CDC (#03) --- ISSUES.md | 40 ++- pages/cdc.j2 | 189 +++++++++++ pages/index.j2 | 46 +++ static/css/main.css | 745 ++++++++++++++++++++++++++++++++++++++++++++ static/js/navbar.js | 70 +++++ templates/base.j2 | 74 ++++- tests/test_site.py | 52 ++++ variables.yaml | 39 +++ 8 files changed, 1239 insertions(+), 16 deletions(-) create mode 100644 pages/cdc.j2 create mode 100644 static/js/navbar.js diff --git a/ISSUES.md b/ISSUES.md index 6b83921..dee1cc9 100644 --- a/ISSUES.md +++ b/ISSUES.md @@ -64,48 +64,62 @@ Para organizar as contribuições da comunidade no GitHub, utilizamos a seguinte - Geração automática de `dist/robots.txt` com `Disallow: /`. - Desativação do Google Analytics em ambiente de staging. - Criação de `dist/.nojekyll` para compatibilidade com o GitHub Pages. +- [x] **Barra de Navegação Fixa e Responsiva (Issue #01)** + - Navbar fixa no topo com efeito vidro translúcido (`backdrop-filter: blur`) com scroll listener (`static/js/navbar.js`). + - Links de navegação suaves para as seções da página (*Início*, *Sobre*, *Destino*) e link dedicado para o *Código de Conduta*. + - Ícones de redes sociais da comunidade à direita e suporte a botão CTA de ingressos. + - Menu hambúrguer animado e responsivo para celulares (< 860px) com controle via teclado (`Escape`) e fechamento ao clicar fora. +- [x] **Seção "Sobre a Python Nordeste" (Issue #02)** + - Bloco institucional em `pages/index.j2` contextualizando a história itinerante de mais de 10 anos pelos 9 estados do Nordeste e a chegada ao litoral do Piauí. + - Grid de estatísticas comunitárias parametrizáveis via `variables.yaml` com hover interativo. + - Card de citação em destaque celebrando o lema histórico *Pessoas > Tecnologia*. +- [x] **Página Dedicada do Código de Conduta (`/cdc.html`) (Issue #03)** + - Página dedicada `pages/cdc.j2` compilada automaticamente para `dist/cdc.html`. + - Texto oficial e integral do CDC baseado nas diretrizes da APyB e PSF. + - Cartão de reporte de incidentes em destaque com e-mail seguro da comissão (`conduta@pythonnordeste.org`). + - Navegação consistente herdando de `templates/base.j2` e botão de retorno para a home. --- ## 🟡 Próximas Prioridades (To Do / In Progress) -### #01 — Barra de Navegação (Navbar Fixa e Responsiva) +### #01 — Barra de Navegação (Navbar Fixa e Responsiva) — ✅ CONCLUÍDO - **Tipo:** `type: feat` - **Labels:** `scope: ui/ux`, `good first issue` - **Milestone:** `v0.2.0 - Navegação & Identidade` - **Esforço:** `Médio` - **Descrição:** Adicionar barra de navegação no topo com logo, links de rolagem suave para as seções da página (*Início*, *Sobre*, *Destino*, *CDC*) e atalhos para as redes sociais. - **Critérios de Aceite:** - - [ ] Navbar fixa no topo com efeito vidro/blur translúcido ao rolar a página. - - [ ] Links âncora funcionando com rolagem suave (`scroll-behavior: smooth`). - - [ ] Ícones sociais do GitHub, Instagram, LinkedIn e YouTube à direita. - - [ ] Menu hambúrguer responsivo para celulares (< 768px). + - [x] Navbar fixa no topo com efeito vidro/blur translúcido ao rolar a página. + - [x] Links âncora funcionando com rolagem suave (`scroll-behavior: smooth`). + - [x] Ícones sociais do GitHub, Instagram, LinkedIn e YouTube à direita. + - [x] Menu hambúrguer responsivo para celulares (< 768px). --- -### #02 — Seção "Sobre a Python Nordeste" +### #02 — Seção "Sobre a Python Nordeste" — ✅ CONCLUÍDO - **Tipo:** `type: feat` - **Labels:** `scope: content`, `good first issue` - **Milestone:** `v0.2.0 - Navegação & Identidade` - **Esforço:** `Pequeno` - **Descrição:** Criar um bloco institucional contextualizando a história itinerante de mais de 10 anos do evento, o compromisso com diversidade e inclusão, e a celebração da chegada inédita ao litoral do Piauí. - **Critérios de Aceite:** - - [ ] Texto e títulos configuráveis via `variables.yaml`. - - [ ] Layout harmonizado com a paleta oficial (fundo Areia/Off-white e tipografia *Outfit*). - - [ ] Destaques em números ou marcos da comunidade (anos de história, edições passadas). + - [x] Texto e títulos configuráveis via `variables.yaml`. + - [x] Layout harmonizado com a paleta oficial (fundo Areia/Off-white e tipografia *Outfit*). + - [x] Destaques em números ou marcos da comunidade (anos de história, edições passadas). --- -### #03 — Página Dedicada do Código de Conduta (`/cdc.html`) +### #03 — Página Dedicada do Código de Conduta (`/cdc.html`) — ✅ CONCLUÍDO - **Tipo:** `type: feat` - **Labels:** `scope: community`, `type: docs`, `good first issue` - **Milestone:** `v0.2.0 - Navegação & Identidade` - **Esforço:** `Pequeno` - **Descrição:** Implementar uma página dedicada (`pages/cdc.j2`) com o texto completo do Código de Conduta da APyB e canais de contato da comissão de resposta a incidentes. - **Critérios de Aceite:** - - [ ] Página acessível diretamente pela rota `/cdc.html`. - - [ ] Texto integral com formatação limpa e legível. - - [ ] Informações claras sobre como reportar incidentes de forma segura. + - [x] Página acessível diretamente pela rota `/cdc.html`. + - [x] Texto integral com formatação limpa e legível. + - [x] Informações claras sobre como reportar incidentes de forma segura. --- diff --git a/pages/cdc.j2 b/pages/cdc.j2 new file mode 100644 index 0000000..1e4b483 --- /dev/null +++ b/pages/cdc.j2 @@ -0,0 +1,189 @@ +{% extends "templates/base.j2" %} + +{% block title %}Código de Conduta | {{ event_name }} {{ event_edition }}{% endblock %} + +{% block content %} +
+ +
+
+ + Voltar à Página Inicial + + +
+ Diretriz Oficial da Comunidade +
+ +

Código de Conduta

+

+ A {{ event_name }} {{ event_edition }} é dedicada a proporcionar uma experiência livre de assédio, acolhedora, inclusiva e segura para todas as pessoas, independentemente de idade, gênero, orientação sexual, deficiência, aparência física, etnia, raça ou crença religiosa. +

+
+
+ + +
+ + +
+
+ +
+
+

Precisa de Ajuda ou Quer Reportar um Incidente?

+

+ Se você estiver sofrendo assédio, presenciou alguma violação a estas diretrizes ou tem dúvidas sobre sua segurança, entre em contato imediatamente com a Comissão de Resposta a Incidentes. +

+
+ {% set email_cdc = code_of_conduct.report_email if code_of_conduct and code_of_conduct.report_email else 'conduta@pythonnordeste.org' %} + + Enviar E-mail: {{ email_cdc }} + +
+ + Todas as comunicações são tratadas com sigilo absoluto e prioridade máxima pela organização. + +
+
+ +
+

+ 1 Nosso Propósito & Valores +

+

+ A Python Nordeste acredita no lema «Pessoas > Tecnologia». Mais do que linguagens, frameworks ou arquiteturas de software, nossa comunidade é feita de seres humanos. Valorizamos o compartilhamento generoso de conhecimento, a empatia entre pares e a construção de um espaço onde todas as pessoas se sintam respeitadas, bem-vindas e incentivadas a crescer. +

+

+ Não toleramos nenhuma forma de assédio, discriminação, constrangimento ou desrespeito em nossas atividades presenciais ou virtuais. +

+
+ +
+

+ 2 Comportamentos Esperados +

+

Incentivamos e esperamos que todas as pessoas participantes, palestrantes, organizadoras, voluntárias e patrocinadoras adotem as seguintes práticas:

+
    +
  • + +
    + Ser gentil e respeitoso(a): Use linguagem acolhedora, respeitosa e inclusiva em todas as conversas, apresentações e interações sociais. +
    +
  • +
  • + +
    + Valorizar a diversidade de perspectivas: Respeite diferentes pontos de vista, experiências de vida e níveis técnicos de experiência. +
    +
  • +
  • + +
    + Aceitar críticas construtivas graciosamente: Esteja aberto(a) a ouvir, aprender e evoluir continuamente a partir do diálogo colaborativo. +
    +
  • +
  • + +
    + Cuidar do coletivo: Se você notar alguém em situação desconfortável, ofereça apoio ou notifique imediatamente uma pessoa da equipe organizadora. +
    +
  • +
+
+ +
+

+ 3 Comportamentos Inaceitáveis +

+

São expressamente proibidos em qualquer atividade ou espaço associado ao evento:

+
    +
  • + +
    + Assédio de qualquer natureza: Comportamento ofensivo, humilhação, comentários degradantes ou piadas relacionadas a raça, gênero, orientação sexual, deficiência, idade ou religião. +
    +
  • +
  • + +
    + Sexualização inadequada: Uso de imagens, piadas ou linguagem de conotação sexual em palestras, slides, materiais promocionais, estandes de empresas ou roupas inadequadas ao ambiente profissional comunitário. +
    +
  • +
  • + +
    + Intimidação e toque não consensual: Perseguição deliberada (stalking), contato físico não solicitado, avanços sexuais indesejados ou gravação/fotografia de pessoas após solicitação de interrupção. +
    +
  • +
  • + +
    + Interrupção intencional: Boicote, interrupção sustentada de palestras, mesas redondas, oficinas ou de atividades oficiais da programação. +
    +
  • +
+
+ +
+

+ 4 Onde Este Código se Aplica +

+

+ Este Código de Conduta aplica-se a todos os ambientes e momentos vinculados à Python Nordeste 2027, incluindo: +

+
+
+ +

Espaços Físicos

+

Auditórios, salas de workshop, corredores, áreas de convivência, estandes, alimentação e banheiros.

+
+
+ +

Canais Digitais

+

Grupos no Telegram/WhatsApp, servidores Discord, comentários em lives e redes sociais oficiais.

+
+
+ +

Eventos Sociais

+

Happy hours oficiais, jantares comunitários, atividades culturais e translados oficiais da conferência.

+
+
+
+ +
+

+ 5 Procedimento de Aplicação & Consequências +

+

+ Pessoas participantes que forem solicitadas a cessar qualquer comportamento inadequado devem obedecer imediatamente. +

+

+ Caso ocorra violação ao Código de Conduta, a organização e a Comissão de Resposta a Incidentes tomarão as medidas proporcionais e cabíveis para restabelecer a segurança coletiva, incluindo: +

+
    +
  1. Advertência formal e direta à pessoa infratora;
  2. +
  3. Expulsão imediata da atividade ou do evento como um todo, sem qualquer direito a reembolso do valor de ingresso;
  4. +
  5. Banimento temporário ou permanente de futuros eventos organizados pela comunidade Python Nordeste;
  6. +
  7. Acionamento das forças de segurança pública e autoridades policiais competentes em caso de conduta criminosa.
  8. +
+
+ + + + +
+
+{% endblock %} diff --git a/pages/index.j2 b/pages/index.j2 index 171e514..db8521e 100644 --- a/pages/index.j2 +++ b/pages/index.j2 @@ -95,6 +95,52 @@ + + {% if about %} +
+
+
+ {% if about.tag %} + + {% endif %} +

{{ about.title }}

+ {% if about.subtitle %} +

{{ about.subtitle }}

+ {% endif %} +
+ +
+
+ {% for paragraph in about.paragraphs %} +

{{ paragraph }}

+ {% endfor %} +
+ +

Não estamos aqui apenas por código. Estamos aqui pelas conexões humanas que o código torna possíveis.

+ — Comunidade Python +
+
+ + {% if about.stats %} +
+
+ {% for stat in about.stats %} +
+
+ +
+
{{ stat.number }}
+
{{ stat.label }}
+
+ {% endfor %} +
+
+ {% endif %} +
+
+
+ {% endif %} +
diff --git a/static/css/main.css b/static/css/main.css index e6b0f9b..f6731b8 100644 --- a/static/css/main.css +++ b/static/css/main.css @@ -540,3 +540,748 @@ body { } } +/* ========================================================================== + Barra de Navegação Superior (Navbar Fixa e Responsiva - Issue #01) + ========================================================================== */ + +.site-header { + position: sticky; + top: 0; + left: 0; + width: 100%; + z-index: 1000; +} + +.navbar { + background: rgba(43, 27, 34, 0.75); + backdrop-filter: blur(12px); + -webkit-backdrop-filter: blur(12px); + border-bottom: 1px solid rgba(228, 122, 159, 0.18); + transition: background 0.3s ease, box-shadow 0.3s ease, border-color 0.3s ease; +} + +.navbar.navbar-scrolled { + background: rgba(43, 27, 34, 0.94); + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15); + border-bottom-color: rgba(228, 122, 159, 0.35); +} + +.navbar-container { + max-width: 1140px; + margin: 0 auto; + padding: 0.75rem 1.5rem; + display: flex; + align-items: center; + justify-content: space-between; + gap: 1.5rem; +} + +.navbar-brand { + display: flex; + align-items: center; + gap: 0.65rem; + text-decoration: none; + color: #FFFFFF; + transition: transform 0.2s ease; +} + +.navbar-brand:hover { + transform: scale(1.02); +} + +.navbar-logo { + display: block; + width: 36px; + height: 36px; + object-fit: contain; + filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.2)); +} + +.navbar-brand-text { + font-family: var(--font-display); + font-size: 1.15rem; + font-weight: 700; + letter-spacing: -0.01em; + color: #FFFFFF; +} + +.navbar-edition { + color: var(--primary-color); + font-weight: 800; +} + +.navbar-menu { + display: flex; + align-items: center; + justify-content: space-between; + flex: 1; + margin-left: 2rem; +} + +.navbar-links { + display: flex; + align-items: center; + gap: 1.5rem; + list-style: none; + margin: 0; + padding: 0; +} + +.nav-link { + color: rgba(249, 244, 232, 0.88); + text-decoration: none; + font-size: 0.95rem; + font-weight: 500; + position: relative; + padding: 0.35rem 0; + transition: color 0.2s ease; +} + +.nav-link::after { + content: ""; + position: absolute; + bottom: 0; + left: 0; + width: 0%; + height: 2px; + background: var(--primary-color); + border-radius: 2px; + transition: width 0.25s ease; +} + +.nav-link:hover { + color: #FFFFFF; +} + +.nav-link:hover::after { + width: 100%; +} + +.navbar-actions { + display: flex; + align-items: center; + gap: 1.25rem; +} + +.navbar-social { + display: flex; + align-items: center; + gap: 0.75rem; +} + +.nav-social-icon { + display: inline-flex; + align-items: center; + justify-content: center; + width: 32px; + height: 32px; + border-radius: 50%; + background: rgba(249, 244, 232, 0.12); + color: rgba(249, 244, 232, 0.9); + text-decoration: none; + font-size: 0.95rem; + transition: background 0.2s ease, transform 0.2s ease, color 0.2s ease; +} + +.nav-social-icon:hover { + background: var(--primary-color); + color: #FFFFFF; + transform: translateY(-2px); +} + +.btn-nav-cta { + display: inline-flex; + align-items: center; + gap: 0.4rem; + background: var(--primary-color); + color: #FFFFFF; + text-decoration: none; + font-size: 0.85rem; + font-weight: 600; + padding: 0.45rem 1rem; + border-radius: 9999px; + box-shadow: 0 4px 12px rgba(228, 122, 159, 0.3); + transition: background 0.2s ease, transform 0.2s ease; +} + +.btn-nav-cta:hover { + background: var(--secondary-color); + transform: translateY(-1px); +} + +.navbar-toggle { + display: none; + flex-direction: column; + justify-content: space-around; + width: 38px; + height: 38px; + background: rgba(249, 244, 232, 0.1); + border: 1px solid rgba(255, 255, 255, 0.2); + border-radius: 8px; + padding: 8px; + cursor: pointer; + transition: background 0.2s ease; +} + +.navbar-toggle:hover { + background: rgba(249, 244, 232, 0.2); +} + +.hamburger-bar { + width: 100%; + height: 2px; + background-color: #FFFFFF; + border-radius: 2px; + transition: transform 0.25s ease, opacity 0.25s ease; +} + +.navbar-toggle.toggle-active .hamburger-bar:nth-child(1) { + transform: translateY(7px) rotate(45deg); +} + +.navbar-toggle.toggle-active .hamburger-bar:nth-child(2) { + opacity: 0; +} + +.navbar-toggle.toggle-active .hamburger-bar:nth-child(3) { + transform: translateY(-7px) rotate(-45deg); +} + +/* Offset para âncoras não ficarem sob a navbar fixa */ +section[id], article[id] { + scroll-margin-top: 80px; +} + +@media (max-width: 860px) { + .navbar-toggle { + display: flex; + } + + .navbar-menu { + position: absolute; + top: 100%; + left: 0; + width: 100%; + background: rgba(43, 27, 34, 0.98); + backdrop-filter: blur(20px); + -webkit-backdrop-filter: blur(20px); + border-bottom: 2px solid var(--primary-color); + box-shadow: 0 10px 30px rgba(0, 0, 0, 0.25); + flex-direction: column; + align-items: stretch; + gap: 1.5rem; + padding: 1.5rem 1.5rem 2rem; + margin-left: 0; + display: none; + } + + .navbar-menu.navbar-menu-open { + display: flex; + animation: menuDropdown 0.25s cubic-bezier(0.16, 1, 0.3, 1) both; + } + + @keyframes menuDropdown { + from { + opacity: 0; + transform: translateY(-10px); + } + to { + opacity: 1; + transform: translateY(0); + } + } + + .navbar-links { + flex-direction: column; + align-items: flex-start; + gap: 1rem; + width: 100%; + } + + .nav-link { + font-size: 1.05rem; + padding: 0.5rem 0; + width: 100%; + display: block; + border-bottom: 1px solid rgba(249, 244, 232, 0.08); + } + + .navbar-actions { + flex-direction: column; + align-items: flex-start; + gap: 1rem; + width: 100%; + padding-top: 0.5rem; + } + + .navbar-social { + width: 100%; + gap: 1rem; + } + + .btn-nav-cta { + width: 100%; + justify-content: center; + padding: 0.65rem 1rem; + } +} + +/* ========================================================================== + Seção Sobre a Python Nordeste (Issue #02) + ========================================================================== */ + +.about-section { + position: relative; + background-color: #FFFFFF; + color: var(--text-dark); + padding: 5rem 1.5rem; + border-bottom: 1px solid rgba(43, 27, 34, 0.06); +} + +.about-container { + max-width: 1140px; + margin: 0 auto; +} + +.about-grid { + display: grid; + grid-template-columns: 1.25fr 1fr; + gap: 3.5rem; + align-items: center; + margin-top: 2.5rem; +} + +.about-text-column { + display: flex; + flex-direction: column; + gap: 1.25rem; +} + +.about-paragraph { + font-size: 1.05rem; + line-height: 1.7; + color: #403037; +} + +.about-quote-card { + position: relative; + background: #FAF6EF; + border-left: 4px solid var(--primary-color); + padding: 1.25rem 1.5rem 1.25rem 2rem; + border-radius: 0 12px 12px 0; + margin-top: 0.5rem; +} + +.quote-icon { + color: var(--primary-color); + font-size: 1.35rem; + margin-bottom: 0.5rem; + opacity: 0.8; +} + +.quote-text { + font-size: 1.05rem; + font-weight: 600; + font-style: italic; + color: var(--text-dark); + line-height: 1.45; + margin-bottom: 0.35rem; +} + +.quote-author { + font-size: 0.85rem; + color: var(--secondary-color); + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.05em; +} + +.about-stats-column { + display: flex; + justify-content: center; +} + +.stats-grid { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 1.25rem; + width: 100%; +} + +.stat-card { + background: #FAF6EF; + border: 1px solid rgba(228, 122, 159, 0.2); + border-radius: 16px; + padding: 1.75rem 1.25rem; + text-align: center; + transition: transform 0.25s ease, box-shadow 0.25s ease, border-color 0.25s ease; + box-shadow: 0 4px 16px rgba(43, 27, 34, 0.04); +} + +.stat-card:hover { + transform: translateY(-4px); + border-color: var(--primary-color); + box-shadow: 0 10px 24px rgba(228, 122, 159, 0.15); +} + +.stat-icon-wrapper { + display: inline-flex; + align-items: center; + justify-content: center; + width: 48px; + height: 48px; + border-radius: 12px; + background: rgba(228, 122, 159, 0.15); + color: var(--secondary-color); + font-size: 1.35rem; + margin-bottom: 0.85rem; +} + +.stat-number { + font-family: var(--font-display); + font-size: 2.25rem; + font-weight: 800; + color: var(--secondary-color); + line-height: 1.1; + margin-bottom: 0.35rem; +} + +.stat-label { + font-size: 0.95rem; + font-weight: 600; + color: var(--text-dark); +} + +@media (max-width: 860px) { + .about-grid { + grid-template-columns: 1fr; + gap: 2.5rem; + } + + .about-section { + padding: 3.5rem 1.25rem; + } +} + +@media (max-width: 500px) { + .stats-grid { + grid-template-columns: 1fr; + } +} + +/* ========================================================================== + Página Dedicada do Código de Conduta (Issue #03) + ========================================================================== */ + +.cdc-page { + background: var(--accent-color); + min-height: calc(100vh - 200px); + padding-bottom: 5rem; +} + +.cdc-hero-section { + background: linear-gradient(145deg, var(--primary-color) 0%, var(--secondary-color) 100%); + color: #FFFFFF; + padding: 3.5rem 1.5rem 4rem; + text-align: center; + position: relative; + box-shadow: 0 8px 24px rgba(159, 53, 92, 0.35); +} + +.cdc-hero-container { + max-width: 800px; + margin: 0 auto; +} + +.cdc-back-btn { + display: inline-flex; + align-items: center; + gap: 0.5rem; + color: rgba(255, 255, 255, 0.9); + text-decoration: none; + font-size: 0.9rem; + font-weight: 600; + background: rgba(249, 244, 232, 0.18); + padding: 0.4rem 1rem; + border-radius: 9999px; + margin-bottom: 1.5rem; + border: 1px solid rgba(255, 255, 255, 0.3); + transition: background 0.2s ease, transform 0.2s ease; +} + +.cdc-back-btn:hover { + background: rgba(249, 244, 232, 0.3); + transform: translateX(-3px); + color: #FFFFFF; +} + +.cdc-hero-badge { + display: inline-flex; + align-items: center; + gap: 0.5rem; + font-size: 0.85rem; + font-weight: 700; + text-transform: uppercase; + letter-spacing: 0.05em; + color: #FFF2C0; + margin-bottom: 0.85rem; +} + +.cdc-title { + font-family: var(--font-display); + font-size: clamp(2rem, 5vw, 3rem); + font-weight: 900; + color: #FFFFFF; + margin-bottom: 1.25rem; +} + +.cdc-lead { + font-size: 1.15rem; + line-height: 1.6; + color: rgba(249, 244, 232, 0.95); +} + +.cdc-article-container { + max-width: 860px; + margin: -2.5rem auto 0; + padding: 0 1.25rem; + position: relative; + z-index: 5; +} + +/* Cartão de Alerta para Denúncia */ +.cdc-alert-card { + background: #FFFDF9; + border: 2px solid #E69D45; + border-radius: 16px; + padding: 1.75rem 2rem; + display: flex; + gap: 1.5rem; + align-items: flex-start; + box-shadow: 0 10px 30px rgba(43, 27, 34, 0.08); + margin-bottom: 2.5rem; +} + +.cdc-alert-card .alert-icon { + font-size: 2rem; + color: #D97706; + background: #FEF3C7; + width: 52px; + height: 52px; + display: flex; + align-items: center; + justify-content: center; + border-radius: 12px; + flex-shrink: 0; +} + +.cdc-alert-card h3 { + font-family: var(--font-display); + font-size: 1.25rem; + color: #92400E; + margin-bottom: 0.5rem; +} + +.cdc-alert-card p { + color: #553C28; + font-size: 0.98rem; + line-height: 1.6; + margin-bottom: 1rem; +} + +.btn-cdc-report { + display: inline-flex; + align-items: center; + gap: 0.5rem; + background: #D97706; + color: #FFFFFF; + text-decoration: none; + font-weight: 700; + padding: 0.65rem 1.25rem; + border-radius: 10px; + font-size: 0.95rem; + transition: background 0.2s ease, transform 0.2s ease; +} + +.btn-cdc-report:hover { + background: #B45309; + transform: translateY(-2px); +} + +.alert-note { + display: block; + margin-top: 0.75rem; + color: #78350F; + font-size: 0.85rem; + font-weight: 500; +} + +/* Seções de Conteúdo do CDC */ +.cdc-content-section { + background: #FFFFFF; + border: 1px solid rgba(43, 27, 34, 0.08); + border-radius: 16px; + padding: 2.25rem 2.5rem; + margin-bottom: 1.75rem; + box-shadow: 0 4px 16px rgba(43, 27, 34, 0.03); +} + +.cdc-section-heading { + display: flex; + align-items: center; + gap: 0.85rem; + font-family: var(--font-display); + font-size: 1.45rem; + color: var(--text-dark); + margin-bottom: 1.25rem; + padding-bottom: 0.75rem; + border-bottom: 2px solid rgba(228, 122, 159, 0.2); +} + +.heading-number { + display: inline-flex; + align-items: center; + justify-content: center; + width: 32px; + height: 32px; + border-radius: 8px; + background: var(--primary-color); + color: #FFFFFF; + font-size: 1rem; + font-weight: 800; +} + +.cdc-content-section p { + font-size: 1.02rem; + line-height: 1.75; + color: #403037; + margin-bottom: 1rem; +} + +.cdc-content-section p:last-child { + margin-bottom: 0; +} + +.cdc-checklist, +.cdc-prohibited-list { + list-style: none; + margin: 1.25rem 0 0.5rem; + padding: 0; + display: flex; + flex-direction: column; + gap: 1rem; +} + +.cdc-checklist li, +.cdc-prohibited-list li { + display: flex; + gap: 0.85rem; + align-items: flex-start; + font-size: 0.98rem; + line-height: 1.6; + color: #37282F; +} + +.cdc-checklist i { + color: #10B981; + font-size: 1.2rem; + margin-top: 0.15rem; + flex-shrink: 0; +} + +.cdc-prohibited-list i { + color: #EF4444; + font-size: 1.2rem; + margin-top: 0.15rem; + flex-shrink: 0; +} + +.cdc-scope-grid { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 1rem; + margin-top: 1.25rem; +} + +.scope-card { + background: #FAF6EF; + border: 1px solid rgba(228, 122, 159, 0.15); + border-radius: 12px; + padding: 1.25rem 1rem; + text-align: center; +} + +.scope-card i { + font-size: 1.5rem; + color: var(--secondary-color); + margin-bottom: 0.5rem; +} + +.scope-card h4 { + font-size: 1rem; + font-weight: 700; + margin-bottom: 0.35rem; + color: var(--text-dark); +} + +.scope-card p { + font-size: 0.85rem; + line-height: 1.45; + color: #634F58; +} + +.cdc-steps-list { + margin: 1rem 0 0 1.5rem; + padding: 0; + display: flex; + flex-direction: column; + gap: 0.65rem; +} + +.cdc-steps-list li { + font-size: 1rem; + line-height: 1.6; + color: #37282F; +} + +.cdc-credits-footer { + text-align: center; + background: #FFFFFF; + border: 1px solid rgba(43, 27, 34, 0.08); + border-radius: 16px; + padding: 2rem 1.5rem; + margin-top: 2rem; +} + +.cdc-credits-footer p { + font-size: 0.95rem; + line-height: 1.6; + color: #634F58; + margin-bottom: 1.5rem; +} + +.cdc-credits-footer a { + color: var(--secondary-color); + font-weight: 600; +} + +@media (max-width: 768px) { + .cdc-hero-section { + padding: 2.5rem 1rem 3.5rem; + } + + .cdc-alert-card { + flex-direction: column; + padding: 1.25rem; + } + + .cdc-content-section { + padding: 1.5rem 1.25rem; + } + + .cdc-scope-grid { + grid-template-columns: 1fr; + } +} + + diff --git a/static/js/navbar.js b/static/js/navbar.js new file mode 100644 index 0000000..af7ef1d --- /dev/null +++ b/static/js/navbar.js @@ -0,0 +1,70 @@ +/** + * Python Nordeste 2027 (PyNE 2027) - Interatividade da Barra de Navegação (Navbar) + * Suporte a efeito translúcido no scroll, menu responsivo mobile e acessibilidade ARIA. + */ + +document.addEventListener('DOMContentLoaded', () => { + const navbar = document.getElementById('navbar'); + const toggleBtn = document.getElementById('navbar-toggle'); + const navMenu = document.getElementById('navbar-menu'); + const navLinks = document.querySelectorAll('.nav-link'); + + if (!navbar) return; + + // 1. Efeito translúcido / vidro no scroll da página + const handleScroll = () => { + if (window.scrollY > 25) { + navbar.classList.add('navbar-scrolled'); + } else { + navbar.classList.remove('navbar-scrolled'); + } + }; + + window.addEventListener('scroll', handleScroll, { passive: true }); + handleScroll(); // Checagem inicial caso a página recarregue já rolada + + // 2. Menu hambúrguer para mobile + if (toggleBtn && navMenu) { + const toggleMenu = (open) => { + const isOpen = open !== undefined ? open : !navMenu.classList.contains('navbar-menu-open'); + navMenu.classList.toggle('navbar-menu-open', isOpen); + toggleBtn.classList.toggle('toggle-active', isOpen); + toggleBtn.setAttribute('aria-expanded', String(isOpen)); + + if (isOpen) { + document.body.classList.add('nav-locked'); + } else { + document.body.classList.remove('nav-locked'); + } + }; + + toggleBtn.addEventListener('click', (e) => { + e.stopPropagation(); + toggleMenu(); + }); + + // Fechar ao clicar em qualquer link de navegação + navLinks.forEach((link) => { + link.addEventListener('click', () => { + if (navMenu.classList.contains('navbar-menu-open')) { + toggleMenu(false); + } + }); + }); + + // Fechar ao clicar fora da navbar + document.addEventListener('click', (e) => { + if (navMenu.classList.contains('navbar-menu-open') && !navbar.contains(e.target)) { + toggleMenu(false); + } + }); + + // Fechar com a tecla ESC para acessibilidade + document.addEventListener('keydown', (e) => { + if (e.key === 'Escape' && navMenu.classList.contains('navbar-menu-open')) { + toggleMenu(false); + toggleBtn.focus(); + } + }); + } +}); diff --git a/templates/base.j2 b/templates/base.j2 index cf98ac0..838a919 100644 --- a/templates/base.j2 +++ b/templates/base.j2 @@ -39,7 +39,7 @@ - {{ event_name }} {{ event_edition }}{% if event_city %} | {{ event_city }} - {{ event_state }}{% endif %} + {% block title %}{{ event_name }} {{ event_edition }}{% if event_city %} | {{ event_city }} - {{ event_state }}{% endif %}{% endblock %} @@ -84,17 +84,84 @@ + {% block navbar %} + {% set repo_url = github_repo_url | default(social.github if social and social.github else '') %} + + {% endblock %} + {% block content %} {% endblock %} {% block footer %} {% set repo_url = github_repo_url | default(social.github if social and social.github else '') %} + {% set cdc_link = 'cdc.html' if code_of_conduct and code_of_conduct.page_url else (code_of_conduct_url | default('#')) %} {% endblock %} + {% block extra_js %} {% endblock %} diff --git a/tests/test_site.py b/tests/test_site.py index 047eff9..e81e761 100644 --- a/tests/test_site.py +++ b/tests/test_site.py @@ -64,3 +64,55 @@ def test_staging_environment_blocks_search_engines(): assert (output_folder / ".nojekyll").exists(), ( "O arquivo dist/.nojekyll deve ser gerado para o GitHub Pages." ) + + +def test_navbar_rendered_and_responsive(): + render() + index_html = (output_folder / "index.html").read_text(encoding="utf-8") + assert '
+ + + {% endblock %} @@ -158,6 +169,10 @@ {% set cdc_link = 'cdc.html' if code_of_conduct and code_of_conduct.page_url else (code_of_conduct_url | default('#')) %}
{% endblock %} + + + {% block extra_js %} {% endblock %} diff --git a/tests/test_site.py b/tests/test_site.py index e81e761..7330a72 100644 --- a/tests/test_site.py +++ b/tests/test_site.py @@ -19,7 +19,7 @@ def test_referenced_theme_assets_exist(): settings = load_settings() theme = settings.get("theme", {}) - for key in ["logo", "favicon", "preview_image"]: + for key in ["logo", "logo_horizontal", "favicon", "preview_image"]: asset_path = theme.get(key) if asset_path: assert Path(asset_path).exists(), ( @@ -116,3 +116,93 @@ def test_cdc_page_rendered(): assert '
{% endif %} + {# ========================================================================= + [EM ESPERA] Seção Destino com Casinhas do Porto das Barcas & Guará Interativo + Comentada para manter a versão oficial de produção (Destino 2027 da main). + Não remover — preservada para reativação futura. + -
-
-
- -

{{ destination.title if destination and destination.title else 'Parnaíba espera por você' }}

-

- {{ destination.subtitle if destination and destination.subtitle else 'O litoral do Piauí combina natureza exuberante, dunas paradisíacas e o acolhimento caloroso da nossa comunidade.' }} -

-
+
+
+ Centro Histórico & Delta +

Às margens do Rio Igaraçu, casarões coloniais do século XIX encontram o santuário ecológico do Delta do Parnaíba.

+
- -
-
- Centro Histórico & Delta -

Às margens do Rio Igaraçu, casarões coloniais do século XIX encontram o santuário ecológico do Delta do Parnaíba.

+
+ +
+
+ Clique em mim para a Revoada! 🪶 +
- -
- -
-
- Clique em mim para a Revoada! 🪶 - -
-
-
- - Guará-vermelho -
-
- -
- - -
-
- Casinha colonial coral - Artesanato & Memória -
-
- Casinha colonial amarela - Porto das Barcas -
-
- Casinha colonial azul - Cultura Piauiense -
-
- - - - - {% if destination_slides %} - + ========================================================================= #} - -