# HTMX Examples
## PharmData Design System - Telas Completas com HTMX + Flask

> **Objetivo**: Exemplos práticos de telas completas usando HTMX para interatividade sem JavaScript

---

## Índice

1. [Setup HTMX + Flask](#setup-htmx--flask)
2. [Lista de Substâncias com Filtros](#lista-de-substâncias-com-filtros)
3. [Visualização de Substância (Read-only)](#visualização-de-substância-read-only)
4. [Formulário de Curadoria](#formulário-de-curadoria)
5. [Enriquecimento Assistido](#enriquecimento-assistido)
6. [Modal com HTMX](#modal-com-htmx)

---

## Setup HTMX + Flask

### Base Template

**`app/templates/base.html`**:

```html
<!DOCTYPE html>
<html lang="pt-BR">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{% block title %}PharmData{% endblock %}</title>

    <!-- Tailwind CSS -->
    <link rel="stylesheet" href="{{ url_for('static', filename='css/output.css') }}">

    <!-- Font Awesome -->
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">

    <!-- HTMX -->
    <script src="https://unpkg.com/htmx.org@1.9.10"></script>

    <!-- Custom Tokens -->
    <link rel="stylesheet" href="{{ url_for('static', filename='css/pharmdata-tokens.css') }}">

    {% block extra_head %}{% endblock %}
</head>
<body class="bg-cloud min-h-screen">

    <!-- Header -->
    <header class="bg-emerald-abyss text-white py-4 px-6 shadow-lg sticky top-0 z-50">
        <div class="max-w-7xl mx-auto flex items-center justify-between">
            <div class="flex items-center gap-3">
                <i class="fas fa-flask-vial text-2xl text-mint-signal"></i>
                <div>
                    <h1 class="text-lg font-display font-semibold">Pharm<sup>data</sup></h1>
                    <p class="text-xs text-mint-signal">Curadoria de Dados</p>
                </div>
            </div>

            <nav class="flex gap-6">
                <a href="{{ url_for('substances.list') }}" class="text-sm hover:text-mint-signal transition-colors">
                    Substâncias
                </a>
                <a href="{{ url_for('products.list') }}" class="text-sm hover:text-mint-signal transition-colors">
                    Produtos
                </a>
                <a href="{{ url_for('profile.index') }}" class="text-sm hover:text-mint-signal transition-colors">
                    Perfil
                </a>
            </nav>
        </div>
    </header>

    <!-- Main Content -->
    <main class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
        {% block content %}{% endblock %}
    </main>

    <!-- Toast Container (for notifications) -->
    <div id="toast-container" class="fixed bottom-4 right-4 space-y-2 z-50"></div>

    {% block extra_scripts %}{% endblock %}
</body>
</html>
```

### Flask Routes

**`app/routes/substances.py`**:

```python
from flask import Blueprint, render_template, request, jsonify
from app.models import Substance

bp = Blueprint('substances', __name__, url_prefix='/substances')

@bp.route('/')
def list():
    """Lista de substâncias"""
    return render_template('substances/list.html')

@bp.route('/search')
def search():
    """Busca com HTMX - retorna apenas linhas da tabela"""
    query = request.args.get('q', '')
    status = request.args.get('status', '')
    quality = request.args.get('quality', '')

    substances = Substance.query
    if query:
        substances = substances.filter(Substance.name.ilike(f'%{query}%'))
    if status:
        substances = substances.filter_by(status=status)
    if quality:
        substances = substances.filter_by(quality=quality)

    substances = substances.limit(50).all()

    return render_template('substances/_table_rows.html', substances=substances)

@bp.route('/<substance_id>')
def view(substance_id):
    """Visualização read-only de substância"""
    substance = Substance.query.get_or_404(substance_id)
    return render_template('substances/view.html', substance=substance)

@bp.route('/<substance_id>/edit')
def edit(substance_id):
    """Formulário de edição"""
    substance = Substance.query.get_or_404(substance_id)
    return render_template('substances/edit.html', substance=substance)

@bp.route('/<substance_id>/enrich', methods=['POST'])
def enrich(substance_id):
    """Enriquecimento assistido"""
    substance = Substance.query.get_or_404(substance_id)
    field_name = request.form.get('field')
    source = request.form.get('source', 'SPOR')

    # Simula busca em API externa
    suggestion = fetch_external_data(substance, field_name, source)

    return render_template('substances/_enrichment_suggestion.html',
                         substance=substance,
                         field=field_name,
                         suggestion=suggestion)
```

---

## Lista de Substâncias com Filtros

### Template Principal

**`app/templates/substances/list.html`**:

```html
{% extends "base.html" %}

{% block title %}Substâncias - PharmData{% endblock %}

{% block content %}
<div class="space-y-6">

    <!-- Page Header -->
    <div class="flex items-center justify-between">
        <div>
            <h1 class="text-h1">Substâncias Ativas</h1>
            <p class="text-body text-soft-steel">Curadoria de dados farmacêuticos</p>
        </div>
        <a href="{{ url_for('substances.new') }}" class="inline-flex items-center gap-2 px-4 py-2 bg-teal-intense text-white rounded-lg font-medium hover:bg-emerald-abyss transition-all">
            <i class="fas fa-plus"></i>
            Nova Substância
        </a>
    </div>

    <!-- Filtros com HTMX -->
    <div class="bg-white rounded-lg border border-soft-arctic p-6">
        <form
            id="filter-form"
            hx-get="{{ url_for('substances.search') }}"
            hx-trigger="input changed delay:300ms, change"
            hx-target="#results-tbody"
            hx-indicator="#loading-spinner"
            class="space-y-4"
        >
            <!-- Search Bar -->
            <div>
                <label for="search" class="block text-label text-graphite-depth mb-2">
                    <i class="fas fa-search text-soft-steel"></i>
                    Buscar
                </label>
                <input
                    type="text"
                    id="search"
                    name="q"
                    placeholder="Nome, fórmula, CAS..."
                    class="w-full px-4 py-2 border border-soft-arctic rounded-lg focus:outline-none focus:ring-2 focus:ring-teal-intense"
                />
            </div>

            <!-- Filter Buttons -->
            <div class="grid grid-cols-1 md:grid-cols-2 gap-4">

                <!-- Status Filter -->
                <div>
                    <p class="text-label text-graphite-depth mb-2">Status</p>
                    <div class="flex flex-wrap gap-2">
                        <label class="cursor-pointer">
                            <input type="radio" name="status" value="" class="peer sr-only" checked />
                            <span class="inline-block px-3 py-1 border border-soft-arctic rounded-md peer-checked:bg-teal-intense peer-checked:text-white peer-checked:border-teal-intense transition-all">
                                Todos
                            </span>
                        </label>
                        <label class="cursor-pointer">
                            <input type="radio" name="status" value="approved" class="peer sr-only" />
                            <span class="token-approved cursor-pointer peer-checked:ring-2 peer-checked:ring-teal-intense">
                                Approved
                            </span>
                        </label>
                        <label class="cursor-pointer">
                            <input type="radio" name="status" value="review" class="peer sr-only" />
                            <span class="token-review cursor-pointer peer-checked:ring-2 peer-checked:ring-teal-intense">
                                In Review
                            </span>
                        </label>
                        <label class="cursor-pointer">
                            <input type="radio" name="status" value="draft" class="peer sr-only" />
                            <span class="token-draft cursor-pointer peer-checked:ring-2 peer-checked:ring-teal-intense">
                                Draft
                            </span>
                        </label>
                    </div>
                </div>

                <!-- Quality Filter -->
                <div>
                    <p class="text-label text-graphite-depth mb-2">Qualidade</p>
                    <div class="flex flex-wrap gap-2">
                        <label class="cursor-pointer">
                            <input type="radio" name="quality" value="" class="peer sr-only" checked />
                            <span class="inline-block px-3 py-1 border border-soft-arctic rounded-md peer-checked:bg-teal-intense peer-checked:text-white peer-checked:border-teal-intense transition-all">
                                Todos
                            </span>
                        </label>
                        <label class="cursor-pointer">
                            <input type="radio" name="quality" value="complete" class="peer sr-only" />
                            <span class="token-complete cursor-pointer peer-checked:ring-2 peer-checked:ring-teal-intense">
                                Complete
                            </span>
                        </label>
                        <label class="cursor-pointer">
                            <input type="radio" name="quality" value="partial" class="peer sr-only" />
                            <span class="token-partial cursor-pointer peer-checked:ring-2 peer-checked:ring-teal-intense">
                                Partial
                            </span>
                        </label>
                        <label class="cursor-pointer">
                            <input type="radio" name="quality" value="missing" class="peer sr-only" />
                            <span class="token-missing cursor-pointer peer-checked:ring-2 peer-checked:ring-teal-intense">
                                Missing
                            </span>
                        </label>
                    </div>
                </div>
            </div>

            <!-- Loading Indicator -->
            <div id="loading-spinner" class="htmx-indicator flex items-center gap-2 text-soft-steel">
                <svg class="animate-spin h-4 w-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
                    <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
                    <path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
                </svg>
                <span class="text-sm">Buscando...</span>
            </div>
        </form>
    </div>

    <!-- Results Table -->
    <div class="bg-white rounded-lg border border-soft-arctic overflow-hidden">
        <table class="w-full">
            <thead class="bg-arctic-mist">
                <tr>
                    <th class="px-6 py-3 text-left text-label font-semibold">ID</th>
                    <th class="px-6 py-3 text-left text-label font-semibold">Nome</th>
                    <th class="px-6 py-3 text-left text-label font-semibold">Fórmula</th>
                    <th class="px-6 py-3 text-left text-label font-semibold">Status</th>
                    <th class="px-6 py-3 text-left text-label font-semibold">Qualidade</th>
                    <th class="px-6 py-3 text-right text-label font-semibold">Ações</th>
                </tr>
            </thead>
            <tbody id="results-tbody" class="divide-y divide-soft-arctic">
                {% include 'substances/_table_rows.html' %}
            </tbody>
        </table>
    </div>
</div>
{% endblock %}
```

### Partial - Table Rows

**`app/templates/substances/_table_rows.html`**:

```html
{% for substance in substances %}
<tr class="hover:bg-cloud transition-colors"
    hx-get="{{ url_for('substances.view', substance_id=substance.id) }}"
    hx-push-url="true"
    hx-target="body"
    class="cursor-pointer">

    <td class="px-6 py-4">
        <span class="token-sub">{{ substance.business_key }}</span>
    </td>

    <td class="px-6 py-4">
        <div>
            <p class="text-body font-medium">{{ substance.name }}</p>
            {% if substance.synonyms %}
            <p class="text-caption text-soft-steel">{{ substance.synonyms[0] }}</p>
            {% endif %}
        </div>
    </td>

    <td class="px-6 py-4">
        <span class="font-mono text-sm">{{ substance.formula or '-' }}</span>
    </td>

    <td class="px-6 py-4">
        <span class="token-{{ substance.status }}">
            {{ substance.status | title }}
        </span>
    </td>

    <td class="px-6 py-4">
        <div class="flex items-center gap-2">
            <span class="token-{{ substance.quality }}">
                {{ substance.quality | title }}
            </span>
            <div class="w-24 bg-soft-arctic rounded-full h-1.5">
                <div class="bg-teal-intense h-1.5 rounded-full" style="width: {{ substance.completeness }}%"></div>
            </div>
            <span class="text-caption text-soft-steel">{{ substance.completeness }}%</span>
        </div>
    </td>

    <td class="px-6 py-4">
        <div class="flex justify-end gap-2">
            <button
                class="w-8 h-8 flex items-center justify-center text-teal-intense hover:bg-teal-intense/10 rounded transition-all"
                title="Visualizar"
                onclick="event.stopPropagation()"
                hx-get="{{ url_for('substances.view', substance_id=substance.id) }}"
                hx-push-url="true"
            >
                <i class="fas fa-eye"></i>
            </button>
            <button
                class="w-8 h-8 flex items-center justify-center text-graphite-depth hover:bg-arctic-mist rounded transition-all"
                title="Editar"
                onclick="event.stopPropagation()"
                hx-get="{{ url_for('substances.edit', substance_id=substance.id) }}"
                hx-push-url="true"
            >
                <i class="fas fa-edit"></i>
            </button>
        </div>
    </td>
</tr>
{% else %}
<tr>
    <td colspan="6" class="px-6 py-12 text-center">
        <div class="text-soft-steel">
            <i class="fas fa-search text-4xl mb-4"></i>
            <p class="text-body">Nenhuma substância encontrada</p>
        </div>
    </td>
</tr>
{% endfor %}
```

---

## Visualização de Substância (Read-only)

**`app/templates/substances/view.html`**:

```html
{% extends "base.html" %}

{% block title %}{{ substance.name }} - PharmData{% endblock %}

{% block content %}
<div class="space-y-6">

    <!-- Breadcrumbs -->
    <nav class="flex items-center gap-2 text-sm text-soft-steel" aria-label="Breadcrumb">
        <a href="{{ url_for('substances.list') }}" class="hover:text-teal-intense transition-colors">
            Substâncias
        </a>
        <i class="fas fa-chevron-right text-xs"></i>
        <span class="text-graphite-depth font-medium">{{ substance.business_key }}</span>
    </nav>

    <!-- Header with Actions -->
    <div class="flex items-start justify-between">
        <div>
            <div class="flex items-center gap-3 mb-2">
                <h1 class="text-h1">{{ substance.name }}</h1>
                <span class="token-{{ substance.status }}">{{ substance.status | title }}</span>
                <span class="token-{{ substance.quality }}">{{ substance.quality | title }}</span>
            </div>
            <p class="text-body text-soft-steel">{{ substance.business_key }}</p>
        </div>

        <div class="flex gap-2">
            <a
                href="{{ url_for('substances.edit', substance_id=substance.id) }}"
                class="inline-flex items-center gap-2 px-4 py-2 bg-teal-intense text-white rounded-lg font-medium hover:bg-emerald-abyss transition-all"
            >
                <i class="fas fa-edit"></i>
                Editar
            </a>
            <button
                class="inline-flex items-center gap-2 px-4 py-2 bg-transparent text-graphite-depth border border-soft-arctic rounded-lg font-medium hover:bg-arctic-mist transition-all"
                hx-get="{{ url_for('substances.history', substance_id=substance.id) }}"
                hx-target="#modal-container"
                hx-swap="innerHTML"
            >
                <i class="fas fa-history"></i>
                Histórico
            </button>
        </div>
    </div>

    <!-- Grid Layout: 2 Columns -->
    <div class="grid grid-cols-1 lg:grid-cols-3 gap-6">

        <!-- Left Column: Estrutura Molecular -->
        <div class="lg:col-span-1">
            <div class="bg-white rounded-lg border border-soft-arctic p-6 sticky top-24">
                <h3 class="text-h3 mb-4">Estrutura Molecular</h3>

                <!-- Canvas para estrutura 2D (SmilesDrawer) -->
                <div id="structure-canvas" class="bg-cloud rounded-lg p-4 mb-4 flex items-center justify-center" style="min-height: 250px;">
                    {% if substance.smiles %}
                    <canvas id="smiles-canvas"></canvas>
                    {% else %}
                    <p class="text-caption text-soft-steel">Estrutura não disponível</p>
                    {% endif %}
                </div>

                <!-- Fórmula Molecular -->
                <div class="space-y-2">
                    <p class="text-label text-soft-steel">Fórmula Molecular</p>
                    <p class="text-xl font-mono">{{ substance.formula_html | safe }}</p>
                </div>
            </div>
        </div>

        <!-- Right Column: Propriedades -->
        <div class="lg:col-span-2 space-y-6">

            <!-- Identificação -->
            <div class="bg-white rounded-lg border border-soft-arctic p-6">
                <h3 class="text-h3 mb-4 pb-2 border-b-2 border-teal-intense">Identificação</h3>

                <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
                    <div class="flex justify-between py-2 border-b border-soft-arctic/50">
                        <span class="text-label text-soft-steel">CAS Number</span>
                        <span class="text-body font-medium">{{ substance.cas or '-' }}</span>
                    </div>

                    <div class="flex justify-between py-2 border-b border-soft-arctic/50">
                        <span class="text-label text-soft-steel">UNII (FDA)</span>
                        <span class="text-body font-medium">{{ substance.unii or '-' }}</span>
                    </div>

                    <div class="flex justify-between py-2 border-b border-soft-arctic/50">
                        <span class="text-label text-soft-steel">ChEMBL ID</span>
                        <span class="text-body font-medium">
                            {% if substance.chembl_id %}
                            <a href="https://www.ebi.ac.uk/chembl/compound_report_card/{{ substance.chembl_id }}" target="_blank" class="text-teal-intense hover:underline">
                                {{ substance.chembl_id }}
                                <i class="fas fa-external-link-alt text-xs"></i>
                            </a>
                            {% else %}
                            -
                            {% endif %}
                        </span>
                    </div>

                    <div class="flex justify-between py-2 border-b border-soft-arctic/50">
                        <span class="text-label text-soft-steel">PubChem CID</span>
                        <span class="text-body font-medium">
                            {% if substance.pubchem_cid %}
                            <a href="https://pubchem.ncbi.nlm.nih.gov/compound/{{ substance.pubchem_cid }}" target="_blank" class="text-teal-intense hover:underline">
                                {{ substance.pubchem_cid }}
                                <i class="fas fa-external-link-alt text-xs"></i>
                            </a>
                            {% else %}
                            -
                            {% endif %}
                        </span>
                    </div>
                </div>
            </div>

            <!-- Propriedades Físico-Químicas -->
            <div class="bg-white rounded-lg border border-soft-arctic p-6">
                <h3 class="text-h3 mb-4 pb-2 border-b-2 border-teal-intense">Propriedades Físico-Químicas</h3>

                <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
                    <div class="flex justify-between py-2 border-b border-soft-arctic/50">
                        <span class="text-label text-soft-steel">Massa Molecular</span>
                        <span class="text-body font-medium">{{ substance.molecular_weight }} g/mol</span>
                    </div>

                    <div class="flex justify-between py-2 border-b border-soft-arctic/50">
                        <span class="text-label text-soft-steel">LogP</span>
                        <span class="text-body font-medium">{{ substance.logp or '-' }}</span>
                    </div>

                    <div class="flex justify-between py-2 border-b border-soft-arctic/50">
                        <span class="text-label text-soft-steel">Ponto de Fusão</span>
                        <span class="text-body font-medium">{{ substance.melting_point or '-' }}</span>
                    </div>

                    <div class="flex justify-between py-2 border-b border-soft-arctic/50">
                        <span class="text-label text-soft-steel">Solubilidade</span>
                        <span class="text-body font-medium">{{ substance.solubility or '-' }}</span>
                    </div>
                </div>
            </div>

            <!-- Classificações -->
            <div class="bg-white rounded-lg border border-soft-arctic p-6">
                <h3 class="text-h3 mb-4 pb-2 border-b-2 border-teal-intense">Classificações</h3>

                <div class="space-y-3">
                    <div>
                        <p class="text-label text-soft-steel mb-2">ATC Code</p>
                        <div class="flex flex-wrap gap-2">
                            {% for atc in substance.atc_codes %}
                            <span class="token-base">{{ atc }}</span>
                            {% endfor %}
                        </div>
                    </div>

                    <div>
                        <p class="text-label text-soft-steel mb-2">SNOMED CT</p>
                        <div class="flex flex-wrap gap-2">
                            {% for snomed in substance.snomed_codes %}
                            <span class="token-snomed">{{ snomed }}</span>
                            {% endfor %}
                        </div>
                    </div>
                </div>
            </div>

            <!-- Fonte de Dados -->
            <div class="bg-white rounded-lg border border-soft-arctic p-6">
                <h3 class="text-h3 mb-4 pb-2 border-b-2 border-teal-intense">Rastreabilidade</h3>

                <div class="space-y-2">
                    <div class="flex items-center justify-between py-2">
                        <span class="text-label text-soft-steel">Fonte Principal</span>
                        <span class="token-{{ substance.source | lower }}">{{ substance.source }}</span>
                    </div>

                    <div class="flex items-center justify-between py-2">
                        <span class="text-label text-soft-steel">Última Atualização</span>
                        <span class="text-body">{{ substance.updated_at | format_datetime }}</span>
                    </div>

                    <div class="flex items-center justify-between py-2">
                        <span class="text-label text-soft-steel">Curado por</span>
                        <span class="text-body">{{ substance.curator.name }}</span>
                    </div>
                </div>
            </div>

        </div>
    </div>
</div>

<!-- Modal Container -->
<div id="modal-container"></div>

{% endblock %}

{% block extra_scripts %}
{% if substance.smiles %}
<script src="https://unpkg.com/smiles-drawer@2.0.1/dist/smiles-drawer.min.js"></script>
<script>
    let smilesDrawer = new SmilesDrawer.SmilesDrawer({
        width: 300,
        height: 250,
        bondThickness: 1.5,
        bondSpacing: 0.18 * 1.5
    });

    SmilesDrawer.parse('{{ substance.smiles }}', function(tree) {
        smilesDrawer.draw(tree, 'smiles-canvas', 'light', false);
    });
</script>
{% endif %}
{% endblock %}
```

---

## Formulário de Curadoria

Ver próximo arquivo para formulários com Progressive Disclosure e HTMX.

---

## Enriquecimento Assistido

**Partial para sugestão de enriquecimento**:

**`app/templates/substances/_enrichment_suggestion.html`**:

```html
<div class="bg-info-light/20 border border-info rounded-lg p-4 space-y-3">
    <div class="flex items-start justify-between">
        <div class="flex items-center gap-2">
            <i class="fas fa-lightbulb text-info"></i>
            <h4 class="text-body font-semibold">Sugestão de {{ source }}</h4>
        </div>
        <span class="text-caption text-soft-steel">Confiança: {{ suggestion.confidence }}%</span>
    </div>

    <!-- Comparação Antes/Depois -->
    <div class="grid grid-cols-2 gap-4">
        <div>
            <p class="text-caption text-soft-steel mb-1">Valor Atual</p>
            <p class="text-body font-mono bg-white px-3 py-2 rounded border border-soft-arctic">
                {{ substance[field] or '(vazio)' }}
            </p>
        </div>
        <div>
            <p class="text-caption text-soft-steel mb-1">Valor Sugerido</p>
            <p class="text-body font-mono bg-success-light/30 px-3 py-2 rounded border border-success">
                {{ suggestion.value }}
            </p>
        </div>
    </div>

    <!-- Ações -->
    <div class="flex gap-2 pt-2 border-t border-info/20">
        <button
            hx-post="{{ url_for('substances.approve_enrichment', substance_id=substance.id) }}"
            hx-vals='{"field": "{{ field }}", "value": "{{ suggestion.value }}", "source": "{{ source }}"}'
            hx-swap="outerHTML"
            class="inline-flex items-center gap-2 px-3 py-1.5 bg-success text-white rounded-md text-sm font-medium hover:bg-success/90 transition-all"
        >
            <i class="fas fa-check"></i>
            Aprovar
        </button>

        <button
            hx-delete="{{ url_for('substances.reject_enrichment', substance_id=substance.id) }}"
            hx-swap="outerHTML"
            class="inline-flex items-center gap-2 px-3 py-1.5 bg-transparent text-error border border-error rounded-md text-sm font-medium hover:bg-error/10 transition-all"
        >
            <i class="fas fa-times"></i>
            Rejeitar
        </button>

        <button
            class="inline-flex items-center gap-2 px-3 py-1.5 bg-transparent text-graphite-depth border border-soft-arctic rounded-md text-sm font-medium hover:bg-arctic-mist transition-all ml-auto"
            onclick="this.closest('.bg-info-light\\/20').remove()"
        >
            Modificar Manualmente
        </button>
    </div>
</div>
```

---

## Modal com HTMX

**Componente Modal Genérico**:

```html
<!-- Modal Background Overlay -->
<div
    id="modal-overlay"
    class="fixed inset-0 bg-black/50 z-40 flex items-center justify-center p-4"
    onclick="if(event.target === this) document.getElementById('modal-container').innerHTML = ''"
>
    <div class="bg-white rounded-lg shadow-xl max-w-2xl w-full max-h-[90vh] overflow-y-auto">

        <!-- Modal Header -->
        <div class="flex items-center justify-between p-6 border-b border-soft-arctic">
            <h2 class="text-h2">{% block modal_title %}Título{% endblock %}</h2>
            <button
                class="w-8 h-8 flex items-center justify-center text-graphite-depth hover:bg-arctic-mist rounded transition-all"
                onclick="document.getElementById('modal-container').innerHTML = ''"
            >
                <i class="fas fa-times"></i>
            </button>
        </div>

        <!-- Modal Body -->
        <div class="p-6">
            {% block modal_body %}{% endblock %}
        </div>

        <!-- Modal Footer -->
        <div class="flex justify-end gap-3 p-6 border-t border-soft-arctic">
            {% block modal_footer %}
            <button
                class="inline-flex items-center gap-2 px-4 py-2 bg-transparent text-graphite-depth border border-soft-arctic rounded-lg font-medium hover:bg-arctic-mist transition-all"
                onclick="document.getElementById('modal-container').innerHTML = ''"
            >
                Fechar
            </button>
            {% endblock %}
        </div>
    </div>
</div>
```

---

**Próximo**: Flask Integration completa e Compliance Map.
