AULA 9

♿ Acessibilidade Web

Aprenda a criar sites inclusivos e acessíveis para todos os usuários, usando ARIA, navegação por teclado e as melhores práticas de inclusão digital.

⏱️ 60 minutos
🎯 Avançado
📝 4 Exercícios

🎯 Objetivos de Aprendizagem

🌍 1. Fundamentos da Acessibilidade

🎯 O que é Acessibilidade Web?

Acessibilidade web significa tornar sites e aplicações utilizáveis por todas as pessoas, incluindo aquelas com deficiências visuais, auditivas, motoras ou cognitivas.

🌟 Por que Acessibilidade É Essencial?

Acessibilidade não é apenas "coisa de especialista" - é um direito humano fundamental e uma necessidade de mercado. Imagine que 23% da população brasileira tem alguma deficiência. Isso significa que 1 em cada 4 pessoas pode ter dificuldades para usar seu site!

Benefícios reais da acessibilidade:

  • 💰 Mercado maior: Alcança 45 milhões de brasileiros com deficiência
  • 🎯 SEO melhor: Google prioriza sites acessíveis nos resultados
  • 👥 Usabilidade geral: Beneficia todos os usuários, não apenas PCDs
  • ⚖️ Conformidade legal: Lei Brasileira de Inclusão (LBI) exige acessibilidade
  • 🏆 Reputação: Demonstra responsabilidade social e inclusão

Mito quebrado: "Acessibilidade é cara e complexa". Na verdade, quando implementada desde o início, custa apenas 1% a mais do projeto total e evita retrabalho futuro.

📊 Dados sobre Deficiência

📈 A Realidade dos Números

Os números sobre deficiência no Brasil são impressionantes e mostram a importância real da acessibilidade web. Não são apenas estatísticas - são pessoas reais que precisam acessar informações, comprar produtos, estudar e trabalhar online.

Tipos de deficiências mais comuns:

  • 👁️ Visual: 6,5M pessoas (cegueira, baixa visão, daltonismo)
  • 👂 Auditiva: 2,3M pessoas (surdez, perda auditiva)
  • 🚶 Motora: 7M pessoas (problemas de mobilidade, tremores)
  • 🧠 Cognitiva: Dislexia, TDAH, deficiência intelectual

Insight importante: Muitas deficiências são invisíveis. Daltonismo atinge 8% dos homens, dislexia afeta 5-10% da população, e deficiências temporárias (braço quebrado, olho inflamado) podem afetar qualquer pessoa.

<section aria-labelledby="estatisticas-titulo">
    <h3 id="estatisticas-titulo">Estatísticas de Deficiência no Brasil</h3>
    
    <div class="stats-grid">
        <div class="stat-card">
            <div class="stat-number" aria-label="45 milhões">45M</div>
            <div class="stat-label">Pessoas com algum tipo de deficiência</div>
            <div class="stat-source">Fonte: IBGE 2019</div>
        </div>
        
        <div class="stat-card">
            <div class="stat-number" aria-label="6,5 milhões">6,5M</div>
            <div class="stat-label">Pessoas com deficiência visual</div>
            <div class="stat-source">Incluindo cegueira e baixa visão</div>
        </div>
        
        <div class="stat-card">
            <div class="stat-number" aria-label="23%">23%</div>
            <div class="stat-label">Da população brasileira</div>
            <div class="stat-source">Possui alguma deficiência</div>
        </div>
    </div>
</section>

🎯 Princípios WCAG 2.1

🏛️ As 4 Colunas da Acessibilidade

WCAG (Web Content Accessibility Guidelines) são as diretrizes internacionais para acessibilidade web, como uma "constituição" da inclusão digital. São 4 princípios fundamentais que funcionam como pilares de sustentação.

Analogia prática: Imagine um cinema acessível:

  • 🎬 Perceptível: Legendas para surdos, áudiodescrição para cegos
  • 🎮 Operável: Controles que funcionam sem mouse, tempo adequado
  • 📖 Compreensível: Instruções claras, interface previsível
  • 🔧 Robusto: Funciona em diferentes equipamentos e tecnologias

Níveis de conformidade:

  • 🥉 A: Básico (mínimo aceitável)
  • 🥈 AA: Padrão recomendado (exigido por leis)
  • 🥇 AAA: Avançado (ideal mas nem sempre prático)
<section aria-labelledby="principios-wcag">
    <h3 id="principios-wcag">Os 4 Princípios da Acessibilidade</h3>
    
    <dl class="principles-list">
        <dt>
            <span class="principle-number">1</span>
            <strong>Perceptível</strong>
        </dt>
        <dd>
            Informações e componentes da interface devem ser apresentados 
            de forma que os usuários possam percebê-los.
            <ul>
                <li>Texto alternativo para imagens</li>
                <li>Legendas para vídeos</li>
                <li>Contraste de cores adequado</li>
                <li>Conteúdo redimensionável</li>
            </ul>
        </dd>
        
        <dt>
            <span class="principle-number">2</span>
            <strong>Operável</strong>
        </dt>
        <dd>
            Componentes da interface e navegação devem ser operáveis.
            <ul>
                <li>Funcionalidade via teclado</li>
                <li>Tempo suficiente para leitura</li>
                <li>Sem conteúdo que cause convulsões</li>
                <li>Navegação e localização de conteúdo</li>
            </ul>
        </dd>
        
        <dt>
            <span class="principle-number">3</span>
            <strong>Compreensível</strong>
        </dt>
        <dd>
            Informações e operação da interface devem ser compreensíveis.
            <ul>
                <li>Texto legível e compreensível</li>
                <li>Conteúdo previsível</li>
                <li>Assistência na entrada de dados</li>
                <li>Prevenção e correção de erros</li>
            </ul>
        </dd>
        
        <dt>
            <span class="principle-number">4</span>
            <strong>Robusto</strong>
        </dt>
        <dd>
            Conteúdo deve ser robusto para interpretação por tecnologias assistivas.
            <ul>
                <li>Compatibilidade com leitores de tela</li>
                <li>Código válido e semântico</li>
                <li>Funcionamento em diferentes dispositivos</li>
                <li>Futuro-compatível</li>
            </ul>
        </dd>
    </dl>
</section>

💡 Benefícios da Acessibilidade

  • Inclusão: Atende mais usuários e clientes
  • SEO: Melhora indexação e ranking
  • Usabilidade: Beneficia todos os usuários
  • Legal: Cumpre legislação de inclusão

🏋️‍♂️ Exercício 1: Auditoria de Acessibilidade

Faça uma auditoria de acessibilidade em um site existente:

🎭 2. ARIA (Accessible Rich Internet Applications)

🎪 ARIA - O Tradutor Universal

ARIA é como um "tradutor simultâneo" entre seu código JavaScript moderno e as tecnologias assistivas (leitores de tela, navegação por voz, etc.). Enquanto HTML básico funciona naturalmente com essas tecnologias, elementos customizados precisam de "legendas" ARIA.

Quando usar ARIA:

  • 🚫 Nunca primeiro: HTML semântico sempre tem prioridade
  • Componentes dinâmicos: Modais, dropdowns, tabs personalizados
  • 📱 SPAs modernas: React, Vue, Angular com interações complexas
  • 🎯 Estados temporários: Loading, erro, sucesso

Regra de ouro: "Se não quebrar sem ARIA, não precisa de ARIA". Use apenas quando HTML semântico não for suficiente.

🏷️ Atributos ARIA Essenciais

🏷️ Os Rótulos que Salvam Vidas

Atributos ARIA são como etiquetas explicativas que você cola nos elementos para que leitores de tela entendam o que são e como funcionam. É a diferença entre um usuário cego ouvir "botão" vs "botão fechar janela modal".

Hierarquia de nomeação (ordem de prioridade):

  1. aria-labelledby: Referencia outro elemento (mais flexível)
  2. aria-label: Nome direto (mais simples)
  3. Conteúdo do elemento: Texto visível
  4. title: Tooltip (último recurso)

Dica profissional: Use aria-labelledby quando já existe um título visível na página. Use aria-label para elementos que não têm texto visível (como botão "×" para fechar).

<!-- aria-label: fornece nome acessível -->
<button aria-label="Fechar janela modal">×</button>
<input type="search" aria-label="Buscar produtos">

<!-- aria-labelledby: referencia elemento que rotula -->
<h2 id="billing-title">Informações de Cobrança</h2>
<fieldset aria-labelledby="billing-title">
    <!-- campos do formulário -->
</fieldset>

<!-- aria-describedby: referencia descrição adicional -->
<input type="password" 
       id="password" 
       aria-describedby="pwd-help pwd-error">
<div id="pwd-help">Mínimo 8 caracteres</div>
<div id="pwd-error" role="alert">Senha muito fraca</div>

<!-- aria-expanded: estado de expansão -->
<button aria-expanded="false" 
        aria-controls="menu-list"
        onclick="toggleMenu()">
    Menu ☰
</button>
<ul id="menu-list" hidden>
    <li><a href="/home">Home</a></li>
    <li><a href="/about">Sobre</a></li>
</ul>

<!-- aria-current: indica item atual -->
<nav aria-label="Breadcrumb">
    <ol>
        <li><a href="/">Home</a></li>
        <li><a href="/categoria">Categoria</a></li>
        <li aria-current="page">Produto Atual</li>
    </ol>
</nav>

<!-- aria-hidden: oculta de leitores de tela -->
<span aria-hidden="true">👤</span> Perfil do Usuário
<img src="decorative.jpg" alt="" aria-hidden="true">

🎯 Roles ARIA Importantes

🎭 Papéis que Elementos Representam

Roles ARIA são como "profissões" que você atribui aos elementos HTML. É como dizer: "este div não é apenas um div, ele é um botão", ou "esta ul não é uma lista comum, é um menu de navegação".

Principais categorias de roles:

  • 🏗️ Landmark roles: navigation, main, banner, contentinfo (estruturam a página)
  • 🎮 Widget roles: button, tab, menu, dialog (elementos interativos)
  • 📄 Document roles: article, note, tooltip (conteúdo informativo)
  • 🏷️ Abstract roles: widget, input (bases para outros roles)

Tabs vs Accordion: Tabs permitem navegar entre seções relacionadas (como abas de navegador), enquanto accordions mostram/escondem seções independentes (como FAQs expansíveis).

Dialog vs Alertdialog: Dialog é para interações complexas (formulários), alertdialog é para confirmações simples que exigem resposta imediata.

<!-- Navegação com tabs -->
<div role="tablist" aria-label="Configurações da conta">
    <button role="tab" 
            aria-selected="true" 
            aria-controls="panel-perfil"
            id="tab-perfil">
        Perfil
    </button>
    <button role="tab" 
            aria-selected="false" 
            aria-controls="panel-seguranca"
            id="tab-seguranca">
        Segurança
    </button>
    <button role="tab" 
            aria-selected="false" 
            aria-controls="panel-notificacoes"
            id="tab-notificacoes">
        Notificações
    </button>
</div>

<div role="tabpanel" 
     id="panel-perfil" 
     aria-labelledby="tab-perfil">
    <h3>Configurações de Perfil</h3>
    <!-- conteúdo do painel -->
</div>

<div role="tabpanel" 
     id="panel-seguranca" 
     aria-labelledby="tab-seguranca" 
     hidden>
    <h3>Configurações de Segurança</h3>
    <!-- conteúdo do painel -->
</div>

<!-- Alertas e status -->
<div role="alert" aria-live="assertive">
    Erro: Falha ao salvar as configurações
</div>

<div role="status" aria-live="polite">
    Salvando configurações...
</div>

<!-- Dialog modal -->
<div role="dialog" 
     aria-modal="true" 
     aria-labelledby="dialog-title"
     aria-describedby="dialog-description">
    <h2 id="dialog-title">Confirmar Exclusão</h2>
    <p id="dialog-description">
        Esta ação não pode ser desfeita. Tem certeza?
    </p>
    <button>Cancelar</button>
    <button>Excluir</button>
</div>

<!-- Toolbar -->
<div role="toolbar" aria-label="Ferramentas de formatação">
    <button aria-pressed="false" aria-label="Negrito">
        <strong>B</strong>
    </button>
    <button aria-pressed="false" aria-label="Itálico">
        <em>I</em>
    </button>
    <button aria-pressed="false" aria-label="Sublinhado">
        <u>U</u>
    </button>
</div>

<!-- Lista com opções -->
<ul role="listbox" aria-label="Escolher cor">
    <li role="option" aria-selected="true">Azul</li>
    <li role="option" aria-selected="false">Verde</li>
    <li role="option" aria-selected="false">Vermelho</li>
</ul>

🔄 Live Regions

📢 Anúncios Automáticos Inteligentes

Live Regions são "alto-falantes automáticos" que avisam usuários de leitores de tela quando algo muda na página. É essencial para SPAs e interfaces dinâmicas onde conteúdo aparece/desaparece sem recarregar a página.

Tipos de urgência:

  • 🔇 off: Não anuncia (padrão)
  • 😌 polite: Espera usuário terminar de ler (status, progresso)
  • 🚨 assertive: Interrompe imediatamente (erros críticos)

Casos de uso práticos:

  • Formulários: "Campo salvo", "Erro de validação"
  • 🛒 E-commerce: "Item adicionado ao carrinho"
  • 💬 Chat: "Nova mensagem recebida"
  • 📊 Dashboards: "Dados atualizados"

Cuidado: Use com moderação! Muitos anúncios irritam usuários. É como ter alguém falando no seu ouvido o tempo todo.

<!-- Região que atualiza automaticamente -->
<div aria-live="polite" id="status-updates">
    <!-- Conteúdo será anunciado quando mudar -->
</div>

<!-- Alertas urgentes -->
<div aria-live="assertive" id="error-messages">
    <!-- Erros serão anunciados imediatamente -->
</div>

<!-- Exemplo: formulário com feedback -->
<form>
    <label for="username">Nome de usuário</label>
    <input type="text" 
           id="username" 
           required
           aria-describedby="username-error">
    
    <div id="username-error" 
         aria-live="polite" 
         aria-atomic="true"
         style="display: none;">
        <!-- Mensagens de erro aparecerão aqui -->
    </div>
    
    <button type="submit">Enviar</button>
</form>

<script>
// Exemplo de atualização de live region
function showError(message) {
    const errorDiv = document.getElementById('username-error');
    errorDiv.textContent = message;
    errorDiv.style.display = 'block';
    // Será anunciado automaticamente pelo screen reader
}

function clearError() {
    const errorDiv = document.getElementById('username-error');
    errorDiv.textContent = '';
    errorDiv.style.display = 'none';
}
</script>

⚠️ ARIA - Boas Práticas

  • Use HTML semântico primeiro, ARIA apenas quando necessário
  • Sempre teste com leitores de tela reais
  • Mantenha aria-expanded sincronizado com estado visual
  • Use aria-hidden com cuidado, pode ocultar conteúdo importante

🏋️‍♂️ Exercício 2: Sistema de Tabs Acessível

Crie um sistema de tabs completamente acessível:

⌨️ 3. Navegação por Teclado

🎹 A Arte da Navegação Sem Mouse

Navegação por teclado é como "dirigir sem volante" - precisa ser intuitiva e previsível. Muitos usuários dependem exclusivamente do teclado: pessoas cegas, com deficiências motoras, ou mesmo usuários avançados que preferem atalhos.

Quem usa navegação por teclado:

  • 👁️ Usuários cegos: Com leitores de tela
  • 🤲 Deficiências motoras: Dificuldade para usar mouse
  • 💻 Power users: Programadores e usuários avançados
  • 🎮 Situacionais: Mouse quebrado, touchpad ruim
  • 📱 Mobile/TV: Controles remotos e direcionais

Estatística importante: Cerca de 15% dos usuários web usam navegação por teclado regularmente, não apenas PCDs.

🎯 Teclas Padrão

🗺️ O Mapa Universal do Teclado

Existe um "código da estrada" para navegação por teclado que todos os sites devem seguir. É como sinais de trânsito - funcionam porque são universais.

Teclas fundamentais e suas funções:

  • Tab/Shift+Tab: Navegar entre elementos (mais importante!)
  • ↩️ Enter: Ativar links e botões de submit
  • Espaço: Ativar botões, marcar checkboxes, scroll
  • 🔤 Setas: Navegar em grupos (tabs, menus, sliders)
  • 🏠 Home/End: Início/fim de listas ou conteúdo
  • 🚪 Escape: Fechar modais, cancelar ações

Regra importante: Se funciona com mouse, deve funcionar com teclado. Se não tem equivalente no teclado, repense o design.

<!-- Elemento focável personalizado -->
<div class="custom-button" 
     tabindex="0" 
     role="button"
     aria-label="Abrir menu de configurações"
     onkeydown="handleKeyDown(event)"
     onclick="openSettings()">
    ⚙️ Configurações
</div>

<script>
function handleKeyDown(event) {
    // Enter ou Space ativam o botão
    if (event.key === 'Enter' || event.key === ' ') {
        event.preventDefault();
        openSettings();
    }
    // Escape fecha menus/modals
    else if (event.key === 'Escape') {
        closeMenu();
    }
}

// Padrões de navegação por teclado
const keyboardPatterns = {
    // Tab: próximo elemento focável
    // Shift + Tab: elemento anterior
    // Enter: ativar botão/link
    // Space: ativar botão, marcar checkbox
    // Arrow keys: navegação em grupos (tabs, menus)
    // Escape: fechar modal/menu
    // Home/End: primeiro/último item
    // Page Up/Down: navegação em listas longas
};
</script>

🎯 Focus Management

🎯 Controlando a Atenção Digital

Focus management é como ser um "diretor de cinema" da web - você controla onde a "câmera" (foco) está apontando. Para usuários de teclado e leitores de tela, o foco é literalmente onde eles "estão" na página.

Situações que exigem focus management:

  • 🪟 Modais: Foco deve ir para modal e ficar "preso" lá
  • 📱 SPAs: Mudanças de rota precisam mover foco
  • Elementos removidos: Se elemento focado desaparece, mover foco
  • Ações completas: Após salvar, focar na mensagem de sucesso
  • 📋 Formulários longos: Mover para primeiro erro de validação

Focus trap é como um "cercadinho digital" - o foco fica circulando apenas entre elementos do modal/dialog, sem escapar para o fundo da página.

Regra importante: Sempre restaure o foco para onde estava antes quando modal/menu fecha. É como voltar para onde parou na leitura de um livro.

<!-- Modal com focus trap -->
<div id="modal" 
     role="dialog" 
     aria-modal="true"
     aria-labelledby="modal-title"
     tabindex="-1">
     
    <div class="modal-content">
        <h2 id="modal-title">Editar Perfil</h2>
        
        <form>
            <label for="modal-name">Nome:</label>
            <input type="text" id="modal-name" name="name">
            
            <label for="modal-email">E-mail:</label>
            <input type="email" id="modal-email" name="email">
            
            <div class="modal-actions">
                <button type="button" onclick="closeModal()">Cancelar</button>
                <button type="submit">Salvar</button>
            </div>
        </form>
        
        <button class="modal-close" 
                aria-label="Fechar modal"
                onclick="closeModal()">×</button>
    </div>
</div>

<script>
class FocusTrap {
    constructor(element) {
        this.element = element;
        this.focusableElements = this.getFocusableElements();
        this.firstFocusable = this.focusableElements[0];
        this.lastFocusable = this.focusableElements[this.focusableElements.length - 1];
        this.previousFocus = document.activeElement;
    }
    
    getFocusableElements() {
        const selectors = [
            'button:not([disabled])',
            'input:not([disabled])',
            'select:not([disabled])',
            'textarea:not([disabled])',
            'a[href]',
            '[tabindex]:not([tabindex="-1"])'
        ].join(', ');
        
        return Array.from(this.element.querySelectorAll(selectors));
    }
    
    activate() {
        this.element.addEventListener('keydown', this.handleKeyDown.bind(this));
        this.firstFocusable.focus();
    }
    
    deactivate() {
        this.element.removeEventListener('keydown', this.handleKeyDown);
        this.previousFocus.focus();
    }
    
    handleKeyDown(event) {
        if (event.key === 'Tab') {
            if (event.shiftKey) {
                // Shift + Tab - voltar
                if (document.activeElement === this.firstFocusable) {
                    event.preventDefault();
                    this.lastFocusable.focus();
                }
            } else {
                // Tab - avançar
                if (document.activeElement === this.lastFocusable) {
                    event.preventDefault();
                    this.firstFocusable.focus();
                }
            }
        } else if (event.key === 'Escape') {
            this.deactivate();
            closeModal();
        }
    }
}

let currentFocusTrap;

function openModal() {
    const modal = document.getElementById('modal');
    modal.style.display = 'block';
    
    // Criar e ativar focus trap
    currentFocusTrap = new FocusTrap(modal);
    currentFocusTrap.activate();
    
    // Prevenir scroll da página de fundo
    document.body.style.overflow = 'hidden';
}

function closeModal() {
    const modal = document.getElementById('modal');
    modal.style.display = 'none';
    
    // Desativar focus trap
    if (currentFocusTrap) {
        currentFocusTrap.deactivate();
        currentFocusTrap = null;
    }
    
    // Restaurar scroll
    document.body.style.overflow = 'auto';
}
</script>

🧭 Skip Links Avançados

<!-- Skip links no topo da página -->
<nav class="skip-links" aria-label="Links de navegação rápida">
    <a href="#main-content">Pular para conteúdo principal</a>
    <a href="#main-navigation">Pular para navegação</a>
    <a href="#search">Pular para busca</a>
    <a href="#sidebar">Pular para barra lateral</a>
    <a href="#footer">Pular para rodapé</a>
</nav>

<style>
.skip-links {
    position: absolute;
    top: -200px;
    left: 0;
    right: 0;
    z-index: 1000;
    background: #000;
    text-align: center;
}

.skip-links:focus-within {
    top: 0;
}

.skip-links a {
    display: inline-block;
    color: #fff;
    background: #000;
    padding: 12px 16px;
    text-decoration: none;
    margin: 0 4px;
    border-radius: 0 0 4px 4px;
    transition: background-color 0.3s;
}

.skip-links a:focus {
    background: #007bff;
    outline: 2px solid #fff;
    outline-offset: 2px;
}

/* Estilo de foco visível para todos os elementos interativos */
button:focus,
input:focus,
select:focus,
textarea:focus,
a:focus,
[tabindex]:focus {
    outline: 2px solid #007bff;
    outline-offset: 2px;
}

/* Indicador de foco personalizado */
.focus-indicator {
    position: relative;
}

.focus-indicator:focus::after {
    content: '';
    position: absolute;
    top: -4px;
    left: -4px;
    right: -4px;
    bottom: -4px;
    border: 2px solid #007bff;
    border-radius: 4px;
    pointer-events: none;
}

/* Ordem de tabulação customizada */
.custom-tab-order {
    /* Use tabindex para controlar ordem quando necessário */
}

.first-tab { tabindex: 1; }
.second-tab { tabindex: 2; }
.third-tab { tabindex: 3; }
</style>

🏋️‍♂️ Exercício 3: Aplicação Complexa Acessível

Desenvolva uma aplicação to-do acessível com:

🧪 4. Testes de Acessibilidade

🔬 A Ciência da Validação Acessível

Testar acessibilidade é como "controle de qualidade" para inclusão. Não basta implementar ARIA e torcer para funcionar - é preciso validar com ferramentas automáticas, testes manuais e, idealmente, usuários reais.

Pirâmide de testes de acessibilidade:

  1. 🤖 Automáticos (30%): axe, Lighthouse - detectam problemas óbvios
  2. �‍💻 Manuais (40%): Navegação por teclado, leitores de tela
  3. 👥 Usuários reais (30%): Pessoas com deficiência testando

Realidade importante: Ferramentas automáticas detectam apenas 20-30% dos problemas de acessibilidade. O resto precisa de olho humano!

Frequência ideal: Testes automáticos em cada build, manuais semanalmente, usuários reais antes de releases importantes.

�🛠️ Ferramentas de Teste

🧰 Seu Kit de Ferramentas Essencial

Cada ferramenta tem sua especialidade, como médicos especialistas. axe é o "clínico geral", WAVE é o "radiologista", e leitores de tela são os "especialistas em experiência real".

Ranking das ferramentas por utilidade:

  1. 🥇 axe DevTools: Mais preciso, menos falsos positivos
  2. 🥈 Lighthouse: Integrado ao Chrome, fácil de usar
  3. 🥉 WAVE: Visual, bom para iniciantes
  4. 🏅 Screen readers: NVDA (grátis), JAWS (pago), VoiceOver (Mac/iOS)

Workflow profissional: Comece com axe para encontrar problemas óbvios, depois teste manualmente com teclado e leitor de tela.

<!-- Instalar extensões do navegador -->
<!-- 
1. axe DevTools (Deque Systems)
2. WAVE (Web Accessibility Evaluation Tool)
3. Lighthouse (Google)
4. Color Contrast Analyzer
5. Screen Reader Testing
-->

<!-- Teste automatizado com axe-core -->
<script src="https://unpkg.com/axe-core@latest/axe.min.js"></script>
<script>
// Executar auditoria de acessibilidade
axe.run(document, {
    tags: ['wcag2a', 'wcag2aa', 'wcag21aa']
}).then(results => {
    if (results.violations.length === 0) {
        console.log('✅ Nenhuma violação de acessibilidade encontrada!');
    } else {
        console.log('❌ Violações encontradas:', results.violations);
        
        results.violations.forEach(violation => {
            console.group(`🚨 ${violation.description}`);
            console.log(`Impacto: ${violation.impact}`);
            console.log(`Ajuda: ${violation.helpUrl}`);
            
            violation.nodes.forEach(node => {
                console.log(`Elemento: ${node.target[0]}`);
                console.log(`HTML: ${node.html}`);
            });
            console.groupEnd();
        });
    }
});
</script>

📋 Checklist de Testes Manuais

✅ A Lista Definitiva de Verificação

Um checklist de acessibilidade é como uma "lista de pré-voo" de piloto - sem ela, você pode esquecer algo crítico. Esta lista cobre os pontos que ferramentas automáticas não conseguem detectar.

Como usar este checklist:

  1. 🖱️ Primeiro sem mouse: Desconecte o mouse e navegue só com teclado
  2. 👁️ Depois sem visão: Feche os olhos e use leitor de tela
  3. 🎨 Então sem cores: Use modo alto contraste ou escala de cinza
  4. 📱 Por fim responsivo: Teste em diferentes tamanhos de tela

Dica profissional: Grave sua navegação por teclado em vídeo. Você vai se surpreender com quantos problemas só percebe assistindo depois!

Tempo necessário: Uma auditoria completa leva 2-4 horas para um site médio, mas evita semanas de retrabalho depois.

<section aria-labelledby="checklist-title">
    <h3 id="checklist-title">Lista de Verificação Manual</h3>
    
    <form>
        <fieldset>
            <legend>🖱️ Navegação por Teclado</legend>
            
            <label>
                <input type="checkbox" name="keyboard[]" value="tab-order">
                Ordem de tabulação lógica
            </label>
            
            <label>
                <input type="checkbox" name="keyboard[]" value="focus-visible">
                Indicador de foco visível em todos os elementos
            </label>
            
            <label>
                <input type="checkbox" name="keyboard[]" value="skip-links">
                Skip links funcionando
            </label>
            
            <label>
                <input type="checkbox" name="keyboard[]" value="focus-trap">
                Focus trap em modais/dialogs
            </label>
            
            <label>
                <input type="checkbox" name="keyboard[]" value="keyboard-shortcuts">
                Atalhos de teclado documentados
            </label>
        </fieldset>
        
        <fieldset>
            <legend>👁️ Conteúdo Visual</legend>
            
            <label>
                <input type="checkbox" name="visual[]" value="alt-text">
                Texto alternativo em todas as imagens informativas
            </label>
            
            <label>
                <input type="checkbox" name="visual[]" value="contrast">
                Contraste mínimo 4.5:1 para texto normal
            </label>
            
            <label>
                <input type="checkbox" name="visual[]" value="color-only">
                Informação não dependente apenas de cor
            </label>
            
            <label>
                <input type="checkbox" name="visual[]" value="zoom">
                Conteúdo legível com zoom até 200%
            </label>
        </fieldset>
        
        <fieldset>
            <legend>📱 Screen Reader</legend>
            
            <label>
                <input type="checkbox" name="screen-reader[]" value="headings">
                Estrutura de cabeçalhos lógica (H1-H6)
            </label>
            
            <label>
                <input type="checkbox" name="screen-reader[]" value="landmarks">
                Landmarks ARIA identificados
            </label>
            
            <label>
                <input type="checkbox" name="screen-reader[]" value="labels">
                Todos os formulários têm labels
            </label>
            
            <label>
                <input type="checkbox" name="screen-reader[]" value="live-regions">
                Mudanças dinâmicas anunciadas
            </label>
        </fieldset>
        
        <fieldset>
            <legend>🧠 Usabilidade Cognitiva</legend>
            
            <label>
                <input type="checkbox" name="cognitive[]" value="language">
                Linguagem clara e simples
            </label>
            
            <label>
                <input type="checkbox" name="cognitive[]" value="instructions">
                Instruções claras para tarefas complexas
            </label>
            
            <label>
                <input type="checkbox" name="cognitive[]" value="error-prevention">
                Prevenção e correção de erros
            </label>
            
            <label>
                <input type="checkbox" name="cognitive[]" value="timeout">
                Tempo suficiente para completar tarefas
            </label>
        </fieldset>
        
        <button type="submit">Gerar Relatório de Acessibilidade</button>
    </form>
</section>

🔧 Configuração de Screen Readers

🎧 Entrando no Mundo dos Leitores de Tela

Testar com screen readers é como "aprender um novo idioma" - no início parece confuso, mas depois você entende como milhões de pessoas navegam na web. É a diferença entre "achar que funciona" e "saber que funciona".

Por que testar com screen readers:

  • 🎯 Realidade dos usuários: Como PCDs realmente usam seu site
  • 🔍 Problemas invisíveis: Issues que ferramentas automáticas não detectam
  • 💡 Insights de UX: Descobre fluxos confusos e melhorias
  • 📚 Educação: Torna você um desenvolvedor mais consciente

Expectativa vs realidade: Primeira vez vai ser frustrante e lento. Isso é normal! Usuários experientes são 10x mais rápidos que você.

Dica de ouro: Comece testando sites que você conhece bem (Google, YouTube) para entender os comandos antes de testar seus projetos.

<!-- Guia de teste com screen readers -->
<section aria-labelledby="screen-reader-guide">
    <h3 id="screen-reader-guide">Testando com Leitores de Tela</h3>
    
    <div class="platform-guides">
        <article>
            <h4>🪟 Windows - NVDA (Gratuito)</h4>
            <ol>
                <li>Baixe NVDA em <a href="https://www.nvaccess.org">nvaccess.org</a></li>
                <li>Instale e configure voz em português</li>
                <li>Comandos básicos:
                    <ul>
                        <li><kbd>NVDA + F12</kbd>: Parar/iniciar fala</li>
                        <li><kbd>H</kbd>: Navegar por cabeçalhos</li>
                        <li><kbd>D</kbd>: Navegar por landmarks</li>
                        <li><kbd>F</kbd>: Navegar por campos de formulário</li>
                        <li><kbd>B</kbd>: Navegar por botões</li>
                    </ul>
                </li>
            </ol>
        </article>
        
        <article>
            <h4>🍎 macOS - VoiceOver (Nativo)</h4>
            <ol>
                <li>Ativar: <kbd>Cmd + F5</kbd> ou Configurações > Acessibilidade</li>
                <li>Comandos básicos:
                    <ul>
                        <li><kbd>VO + Setas</kbd>: Navegar</li>
                        <li><kbd>VO + Espaço</kbd>: Ativar</li>
                        <li><kbd>VO + U</kbd>: Rotor (navegar por elementos)</li>
                        <li><kbd>VO + H</kbd>: Próximo cabeçalho</li>
                    </ul>
                </li>
            </ol>
        </article>
        
        <article>
            <h4>📱 Mobile - TalkBack/VoiceOver</h4>
            <ol>
                <li><strong>Android TalkBack:</strong> Configurações > Acessibilidade</li>
                <li><strong>iOS VoiceOver:</strong> Configurações > Acessibilidade</li>
                <li>Teste gestos básicos: deslizar para navegar, tocar duas vezes para ativar</li>
            </ol>
        </article>
    </div>
    
    <div class="testing-scenarios">
        <h4>🧪 Cenários de Teste</h4>
        <ol>
            <li><strong>Navegação estrutural:</strong> Use cabeçalhos para navegar</li>
            <li><strong>Preenchimento de formulários:</strong> Teste labels e instruções</li>
            <li><strong>Interação com componentes:</strong> Buttons, modals, tabs</li>
            <li><strong>Feedback dinâmico:</strong> Verificar anúncios de mudanças</li>
            <li><strong>Tabelas:</strong> Navegação por células e cabeçalhos</li>
        </ol>
    </div>
</section>

🏋️‍♂️ Exercício 4: Auditoria Completa

Faça uma auditoria completa de acessibilidade:

📋 Resumo da Aula

🌍 Fundamentos

Princípios WCAG 2.1, inclusão digital e benefícios para todos.

🎭 ARIA

Roles, properties, states e live regions para apps dinâmicas.

⌨️ Teclado

Focus management, skip links e navegação eficiente.

🧪 Testes

Ferramentas automáticas, testes manuais e screen readers.

✅ Checklist de Acessibilidade