---
name: lume-pdf-export
description: >
  Use esta skill quando precisar exportar uma aula Lume (o index.html da unidade
  SCORM, montado em React) para um PDF A4 pronto para impressão ou salvamento.
  O desafio central é que a versão web esconde conteúdo dentro de componentes
  interativos — sliders, flashcards, accordions, quiz, glossário, referências —
  e embute vídeos/áudios que não rodam em PDF. Esta skill ensina a IA a gerar um
  "modo PDF" que revela TODO o conteúdo oculto, adapta o layout fluido ao formato
  A4 e substitui mídias embutidas por um quadro estático com o link do recurso
  logo abaixo. Vale para Claude, GPT, Gemini ou qualquer agente que produza o
  artefato Lume.
lang: pt-BR
---

# Lume — Skill de Exportação para PDF A4

> **O que esta skill resolve**
> A aula Lume na web é *interativa*: o aluno clica, vira cards, abre seções, dá
> play em vídeos. No papel nada disso acontece. Se você simplesmente mandar
> imprimir o `index.html`, **perde conteúdo** — só o primeiro flashcard aparece,
> os accordions ficam fechados, o slider mostra um passo só, o gabarito do quiz
> some e os vídeos viram retângulos pretos. Esta skill descreve o **Modo PDF**
> do Lume: um caminho de renderização que expande tudo, achata a interação em
> leitura linear e formata o resultado em páginas A4.

> **Princípio único**
> No PDF, **nenhum conteúdo pode ficar escondido atrás de um clique.** Tudo o
> que a interação revelaria — todas as faces, todos os slides, todas as
> respostas, todas as definições — precisa estar visível e impresso. Mídia que
> não toca no papel vira um quadro estático **com o link do recurso logo abaixo**.

---

## 1. Como acionar o Modo PDF

O Modo PDF é uma **variação de renderização do mesmo `index.html`** — não um
arquivo paralelo que pode ficar desatualizado. Acione-o por *query param* na URL:

```
index.html            → versão web interativa (padrão)
index.html?pdf=1      → versão expandida para impressão A4
```

No script de montagem do `index.html`, leia o flag e propague-o:

```jsx
const isPDF = new URLSearchParams(location.search).has("pdf");
if (isPDF) document.documentElement.setAttribute("data-pdf", "");
const root = ReactDOM.createRoot(document.getElementById("app"));
root.render(<LessonContent pdf={isPDF} />);
```

Distribua o flag por um **contexto** (assim nenhum componente precisa receber
prop manualmente):

```jsx
const PDFContext = React.createContext(false);
const usePDF = () => React.useContext(PDFContext);

function LessonContent({ pdf = false }) {
  return (
    <PDFContext.Provider value={pdf}>
      {/* … toda a aula … */}
    </PDFContext.Provider>
  );
}
// exponha: Object.assign(window, { PDFContext, usePDF });
```

Cada componente interativo passa a ter dois ramos: `if (usePDF()) return <versão de papel/>`.
As seções 4 e 5 dão a receita de papel de cada um.

> **Atributo no `<html>`:** o `data-pdf` no elemento raiz liga a folha de estilo
> de impressão (seção 3) sem depender de `@media print` — útil para conferir o
> resultado na tela antes de gerar o PDF.

---

## 2. Fluxo de geração do PDF (passo a passo para o agente)

1. **Garanta o Modo PDF nos componentes.** Se o kit ainda não tem os ramos
   `usePDF()`, adicione-os seguindo as seções 4–5. Sem isso, flashcards e
   slider continuam mostrando um item só.
2. **Inclua a folha `lume-pdf.css`** (seção 3) no `<head>` do `index.html`,
   depois de `colors_and_type.css`.
3. **Abra `index.html?pdf=1`** e confira na tela: tudo expandido, sem barra de
   topo, sem botões, vídeos/áudios como quadro + link.
4. **Gere o PDF** com a ação *Salvar como PDF* / imprimir, em **tamanho A4,
   margens padrão e "Gráficos de plano de fundo" ATIVADO** (senão as faixas
   coloridas e marca-textos somem).
5. **Confira o resultado:** nada cortado no meio de um bloco, nenhum link de
   recurso faltando, gabarito do quiz presente, glossário legível.

> Para o agente: a versão para imprimir é sempre `index.html?pdf=1`. Ao usar a
> ação de salvar/imprimir PDF, aponte para esse endereço, não para o
> `index.html` cru.

---

## 3. Folha de estilo A4 — `lume-pdf.css`

Cria a página A4, esconde a navegação, controla quebras e neutraliza efeitos que
não imprimem bem. Aplica-se tanto via `html[data-pdf]` (preview na tela) quanto
via `@media print` (no momento de gerar o PDF).

```css
/* ───────── Página A4 ───────── */
@page {
  size: A4;                 /* 210 × 297 mm */
  margin: 16mm 15mm 18mm;   /* topo/laterais/base — respiro editorial */
}

html[data-pdf], html[data-pdf] body {
  background: #fff;
}

/* O bloco de regras vale na tela (data-pdf) E na impressão (print). */
html[data-pdf] {

  /* 1 ─ Esconder o chrome que não pertence ao papel */
  --pdf-hide: none;
}
html[data-pdf] .lume-topbar,
html[data-pdf] .lume-progressbar,
html[data-pdf] [data-pdf-hide],
@media print {
  .lume-topbar, .lume-progressbar, [data-pdf-hide] { display: none !important; }
}

@media print {
  /* 2 ─ Largura: solta a medida de leitura de 68ch para ocupar o A4 */
  :root { --measure: 100%; --page-pad: 0; }

  /* 3 ─ Tipografia de papel: corpo em 10.5–11pt, títulos proporcionais */
  html, body { font-size: 11pt; line-height: 1.5; }

  /* 4 ─ Imprimir as cores de fundo e os marca-textos */
  * { -webkit-print-color-adjust: exact; print-color-adjust: exact; }

  /* 5 ─ Faixas full-bleed: tirar o sangramento e dar respiro vertical menor */
  .lume-fullbleed { padding: 18px 0 !important; }

  /* 6 ─ Controle de quebra de página
     Nunca partir um bloco didático, uma figura, um card, uma citação. */
  figure, aside, blockquote, table,
  .lume-card, .lume-destaque, .lume-atencao, .lume-reflexao,
  .lume-citacao, .lume-flashcard-print, .lume-step-print,
  .lume-quiz-q, .lume-video-print, .lume-audio-print {
    break-inside: avoid;
    page-break-inside: avoid;
  }
  /* Título nunca fica órfão no fim da página */
  h1, h2, h3, h4 { break-after: avoid; page-break-after: avoid; }
  /* Não deixar viúvas/órfãs em prosa */
  p, li { orphans: 3; widows: 3; }

  /* 7 ─ Sombras e blur não imprimem — remover para não virar cinza sujo */
  * { box-shadow: none !important; backdrop-filter: none !important; }
  /* devolve uma hairline a quem dependia só da sombra para separar */
  .lume-card, .lume-destaque, .lume-reflexao, .lume-video-print,
  .lume-audio-print, .lume-flashcard-print {
    border: 1px solid var(--rule) !important;
  }

  /* 8 ─ Quebra de seção opcional: comece o fechamento em página nova */
  .lume-pagebreak-before { break-before: page; page-break-before: always; }

  /* 9 ─ Links: o href já aparece como legenda (ver RecursoLink); não usar
     o truque content:" (url)" para não duplicar. */
  a { color: var(--ink); text-decoration-color: var(--rule-strong); }
}
```

> **Marque o chrome.** Para a regra 1 funcionar, dê à `TopBar` a classe
> `lume-topbar` e à `ProgressBar` a classe `lume-progressbar`. Qualquer outro
> elemento de tela que não deva imprimir recebe `data-pdf-hide`.

> **Faixas coloridas.** Dê a classe `lume-fullbleed` ao `<section>` do
> `FullBleedSection`. As faixas **suaves** (sage, lavender, coral…) imprimem bem
> e devem ser mantidas — elas são a assinatura do Lume. As faixas **escuras**
> (ink, petrol, terracotta) gastam muito toner; é aceitável mantê-las (com
> *background graphics* ligado) ou, se o usuário pedir economia, convertê-las
> para fundo claro com texto escuro.

---

## 4. Receita de papel — componentes que ESCONDEM conteúdo

Para cada componente interativo, o Modo PDF troca a interação por uma forma
estática que mostra **tudo de uma vez**. Tabela-resumo:

| Componente | Na web esconde… | No PDF deve mostrar… |
|---|---|---|
| `Slider` | todos os slides menos o atual | **todos os slides empilhados**, com marcador ou ícone preservado |
| `FlashCardDeck` / `FlashCard` | só a frente do card atual | **todos os cards**, frente **e** verso lado a lado |
| `Accordion` | corpo de cada item (fechado) | **todos os itens abertos**, pergunta + resposta |
| `Quiz` | gabarito e explicações | enunciado, alternativas, **resposta correta marcada + explicação** |
| `Termo` (glossário) | a definição (no popover) | termo + **definição visível** (nota ou glossário final) |
| `ReferenciasABNT` | a lista (recolhida) | **lista aberta**, completa |

### 4.1 `Slider` → slides empilhados

A web mostra um slide por vez num carrossel. No papel, renderize a lista inteira
como blocos verticais. Preserve o título livre do componente e o marcador textual
ou ícone Font Awesome de cada slide.

```jsx
function Slider({ steps = [], label = "Passo a passo" }) {
  if (usePDF()) {
    return (
      <div className="lume-card" style={{ border: "1px solid var(--rule)", borderRadius: 14, padding: 24, margin: "28px 0" }}>
        {label && <div style={sliderStyles.label}><span>{label}</span></div>}
        <ol style={{ listStyle: "none", margin: "12px 0 0", padding: 0 }}>
          {steps.map((s, idx) => (
            <li key={idx} className="lume-step-print" style={{ display: "grid", gridTemplateColumns: "auto 1fr", gap: 18, padding: "16px 0", borderTop: idx ? "1px solid var(--rule)" : "none" }}>
              <span className="lume-step-print__num">
                {s.icon ? <i className={`fa-solid fa-${s.icon}`}></i> : (s.marker || String(idx + 1).padStart(2, "0"))}
              </span>
              <div>
                <h3 style={{ fontFamily: "var(--font-serif)", fontSize: "1.25rem", margin: "0 0 6px" }}>{s.title}</h3>
                <p style={{ fontFamily: "var(--font-serif)", lineHeight: 1.55, margin: 0, color: "var(--ink-soft)" }}>{s.body}</p>
              </div>
            </li>
          ))}
        </ol>
      </div>
    );
  }
  /* … render web interativo original … */
}
```

### 4.2 `FlashCardDeck` → grade de cartões com frente e verso

**Por que CSS sozinho não basta:** o `FlashCardDeck` só monta o card atual
(`<FlashCard key={i} />`). Os outros nem existem no DOM — então é preciso
renderizar a partir dos dados, não tentar "desvirar" com CSS.

No PDF, percorra `cards` e mostre cada um como uma linha **Pergunta → Resposta**:

```jsx
function FlashCardDeck({ cards = [], tones = [] }) {
  if (usePDF()) {
    return (
      <div style={{ margin: "28px 0" }}>
        <div style={deckStyles.label}><span>Flashcards</span></div>
        <div style={{ display: "grid", gridTemplateColumns: "1fr", gap: 12, marginTop: 12 }}>
          {cards.map((c, i) => (
            <div key={i} className="lume-flashcard-print" style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 0, border: "1px solid var(--rule)", borderRadius: 12, overflow: "hidden" }}>
              <div style={{ padding: "16px 18px", borderRight: "1px solid var(--rule)", background: "var(--bone)" }}>
                <div style={{ fontFamily: "var(--font-sans)", fontSize: 10, fontWeight: 700, letterSpacing: "0.16em", textTransform: "uppercase", color: "var(--ink-mute)", marginBottom: 6 }}>Pergunta</div>
                <div style={{ fontFamily: "var(--font-serif)", fontSize: "1.05rem", lineHeight: 1.35, color: "var(--ink)" }}>{c.front}</div>
              </div>
              <div style={{ padding: "16px 18px", background: "var(--sand)" }}>
                <div style={{ fontFamily: "var(--font-sans)", fontSize: 10, fontWeight: 700, letterSpacing: "0.16em", textTransform: "uppercase", color: "var(--ink-mute)", marginBottom: 6 }}>Resposta</div>
                <div style={{ fontFamily: "var(--font-serif)", fontSize: "1rem", lineHeight: 1.45, color: "var(--ink-soft)" }}>{c.back}</div>
              </div>
            </div>
          ))}
        </div>
      </div>
    );
  }
  /* … render web interativo original … */
}
```

### 4.3 `Accordion` → tudo aberto

Todos os itens já estão no DOM; basta renderizar o corpo aberto e sem o
mecanismo de clique.

```jsx
function Accordion({ items = [] }) {
  if (usePDF()) {
    return (
      <div style={{ margin: "28px 0", borderTop: "1px solid var(--rule)" }}>
        {items.map((it, idx) => (
          <div key={idx} className="lume-card" style={{ padding: "16px 4px", borderBottom: "1px solid var(--rule)" }}>
            <div style={{ display: "grid", gridTemplateColumns: "auto 1fr", gap: 16, alignItems: "baseline" }}>
              <span style={{ fontFamily: "var(--font-sans)", fontSize: 12, fontWeight: 600, color: "var(--ink-mute)" }}>{String(idx + 1).padStart(2, "0")}</span>
              <div>
                <div style={{ fontFamily: "var(--font-serif)", fontSize: "1.2rem", fontWeight: 500, marginBottom: 8 }}>{it.q}</div>
                <div style={{ fontFamily: "var(--font-serif)", fontSize: "1rem", lineHeight: 1.55, color: "var(--ink-soft)" }}>{it.a}</div>
              </div>
            </div>
          </div>
        ))}
      </div>
    );
  }
  /* … render web interativo original … */
}
```

### 4.4 `Quiz` → enunciado + gabarito + explicação

No papel mostre cada questão com a alternativa correta destacada (✓) e a
explicação sempre visível. **Decisão do usuário:** se o PDF for um material de
estudo, mostre o gabarito (padrão). Se for uma prova em branco para aplicar,
passe `pdfGabarito={false}` e apenas liste as alternativas sem marcar a correta.

```jsx
function Quiz({ title = "Quiz", intro, questions = [], pdfGabarito = true }) {
  if (usePDF()) {
    return (
      <section className="lume-card" style={{ border: "1px solid var(--rule)", borderRadius: 16, padding: 28, margin: "32px 0" }}>
        <div style={quizStyles.kicker}><span>{title}</span></div>
        {intro && <p style={quizStyles.intro}>{intro}</p>}
        <ol style={{ listStyle: "none", margin: 0, padding: 0 }}>
          {questions.map((q, qi) => (
            <li key={qi} className="lume-quiz-q" style={{ paddingTop: 20, marginTop: 20, borderTop: "1px solid var(--rule)" }}>
              <div style={{ display: "flex", gap: 10, marginBottom: 10 }}>
                <span style={quizStyles.qNum}>{qi + 1}</span>
                <span style={quizStyles.qText}>{q.q}</span>
              </div>
              <ul style={{ listStyle: "none", margin: 0, padding: 0, display: "flex", flexDirection: "column", gap: 6 }}>
                {q.options.map((opt, oi) => {
                  const correct = pdfGabarito && oi === q.answer;
                  return (
                    <li key={oi} style={{ display: "flex", gap: 10, padding: "9px 12px", borderRadius: 8, border: "1px solid var(--rule)", background: correct ? "var(--sage-soft)" : "transparent", fontFamily: "var(--font-serif)" }}>
                      <span style={{ fontFamily: "var(--font-sans)", fontWeight: 700, color: correct ? "var(--sage-deep)" : "var(--ink-mute)" }}>{correct ? "✓" : String.fromCharCode(97 + oi) + ")"}</span>
                      <span>{opt}</span>
                    </li>
                  );
                })}
              </ul>
              {pdfGabarito && q.explanation && (
                <p style={{ fontFamily: "var(--font-sans)", fontSize: "0.9rem", lineHeight: 1.5, color: "var(--ink-soft)", margin: "10px 0 0", paddingLeft: 12, borderLeft: "2px solid var(--sage)" }}>{q.explanation}</p>
              )}
            </li>
          ))}
        </ol>
      </section>
    );
  }
  /* … render web interativo original … */
}
```

### 4.5 `Termo` (glossário) → definição visível

O popover não existe no papel. Mantenha o termo com o sublinhado pontilhado para
o leitor saber que é um termo-chave, e **revele a definição**. Duas estratégias
— escolha uma e seja consistente na aula inteira:

- **(a) Nota inline** (recomendada — preserva o contexto): logo após o termo, em
  texto pequeno e discreto.
- **(b) Glossário no fim** da aula: o termo recebe um número e a definição vai
  para uma lista "Glossário" antes das Referências.

Receita da nota inline:

```jsx
function Termo({ children, def, termo }) {
  if (usePDF()) {
    return (
      <span>
        <span className="termo" style={{ textDecoration: "underline", textDecorationStyle: "dotted", textDecorationColor: "var(--rule-strong)" }}>{children}</span>
        <span style={{ fontFamily: "var(--font-sans)", fontSize: "0.78em", color: "var(--ink-mute)", margin: "0 0.15em" }}> — {def}</span>
      </span>
    );
  }
  /* … render web interativo (popover) original … */
}
```

### 4.6 `ReferenciasABNT` → lista aberta

Force `defaultOpen` no Modo PDF (ou renderize a `<ol>` sem o mecanismo de
recolher). Comece em página nova se quiser separar o fechamento:

```jsx
function ReferenciasABNT({ title = "Referências", items = [] }) {
  if (usePDF()) {
    return (
      <section className="lume-pagebreak-before" style={{ borderTop: "1px solid var(--rule)", margin: "16px 0" }}>
        <h2 style={{ fontFamily: "var(--font-serif)", fontSize: "1.5rem", margin: "16px 0" }}>{title}</h2>
        <ol style={{ listStyle: "none", margin: 0, padding: 0, display: "flex", flexDirection: "column", gap: 12 }}>
          {items.map((r, i) => (
            <li key={i} style={{ fontFamily: "var(--font-sans)", fontSize: "0.9rem", lineHeight: 1.6, color: "var(--ink-soft)", paddingLeft: "2.2em", textIndent: "-2.2em" }} dangerouslySetInnerHTML={{ __html: r }} />
          ))}
        </ol>
      </section>
    );
  }
  /* … render recolhível original … */
}
```

---

## 5. Receita de papel — MÍDIA que não roda no PDF

Vídeos e áudios embutidos viram um retângulo morto no papel. A regra do Lume:
**mostre um quadro estático identificável e, logo abaixo, o link do recurso de
forma sutil** — assim quem está lendo no papel (ou num PDF sem internet)
consegue digitar/escanear o endereço e acessar.

### 5.1 Componente auxiliar — `RecursoLink`

Uma legenda discreta, abaixo do elemento, com rótulo, ícone de link e a URL
completa em fonte monoespaçada (fácil de transcrever). Use em **todo** vídeo e
áudio externo.

```jsx
function RecursoLink({ rotulo = "Assista em", href }) {
  if (!href) return null;
  return (
    <div className="lume-recurso-link" style={{ display: "flex", alignItems: "baseline", gap: 6, justifyContent: "center", marginTop: 8, fontFamily: "var(--font-sans)", fontSize: "0.8rem", color: "var(--ink-mute)" }}>
      <span style={{ fontWeight: 600 }}>{rotulo}:</span>
      <a href={href} style={{ fontFamily: "var(--font-mono)", fontSize: "0.78rem", color: "var(--ink-soft)", wordBreak: "break-all" }}>{href}</a>
    </div>
  );
}
```

### 5.2 `VideoYouTube` → pôster + link

Monte a URL pública a partir do `id` (e do `start`, se houver). Mostre a
miniatura do YouTube como quadro estático, com o ícone de play "morto" só para
sinalizar que é vídeo.

```jsx
function VideoYouTube({ id, title = "Vídeo", caption, credit, start }) {
  if (usePDF()) {
    const url = `https://youtu.be/${id}${start ? `?t=${start}` : ""}`;
    const thumb = `https://i.ytimg.com/vi/${id}/maxresdefault.jpg`;
    return (
      <figure className="lume-video-print" style={{ margin: "28px 0" }}>
        <div style={{ position: "relative", aspectRatio: "16/9", borderRadius: 12, overflow: "hidden", border: "1px solid var(--rule)", background: "var(--ink)" }}>
          <img src={thumb} alt={title} style={{ width: "100%", height: "100%", objectFit: "cover" }} />
          <span style={{ position: "absolute", inset: 0, display: "grid", placeItems: "center" }}>
            <span style={{ width: 64, height: 64, borderRadius: "50%", background: "var(--terracotta)", display: "grid", placeItems: "center", color: "var(--paper)", fontSize: 24 }}>▶</span>
          </span>
        </div>
        {caption && <figcaption style={videoStyles.cap}>{caption}{credit && <span style={videoStyles.credit}> — {credit}</span>}</figcaption>}
        <RecursoLink rotulo="Assista em" href={url} />
      </figure>
    );
  }
  /* … render web interativo (iframe) original … */
}
```

### 5.3 `AudioPodcast` → capa/card + link

Cubra os dois modos do componente:

- **Spotify** (`spotify` é URL ou URI): se vier URI `spotify:episode:ID`,
  converta para `https://open.spotify.com/episode/ID`; se já for URL, use direto.
  Mostre o cabeçalho (show + título + descrição) e o link.
- **Arquivo nativo** (`src`): mostre o card do podcast e, abaixo, o caminho do
  arquivo. Se for um arquivo local (relativo), o "link" é informativo — rotule
  como `Áudio` em vez de `Ouça em`; se for uma URL absoluta, vira link real.

```jsx
function AudioPodcast({ src, spotify, title, show, description }) {
  if (usePDF()) {
    let href = null, rotulo = "Ouça em";
    if (spotify) {
      const m = spotify.match(/spotify:(episode|show|track|playlist):([A-Za-z0-9]+)/);
      href = m ? `https://open.spotify.com/${m[1]}/${m[2]}` : spotify;
    } else if (src) {
      href = src;
      if (!/^https?:\/\//.test(src)) rotulo = "Arquivo de áudio"; // caminho local
    }
    return (
      <div className="lume-audio-print" style={{ display: "grid", gridTemplateColumns: "72px 1fr", gap: 18, alignItems: "center", border: "1px solid var(--rule)", borderRadius: 14, padding: 18, margin: "28px 0", background: "var(--bone)" }}>
        <div style={{ width: 72, height: 72, borderRadius: 10, background: "linear-gradient(140deg, var(--ocean), var(--ocean-deep))", display: "grid", placeItems: "center", color: "var(--paper)", fontSize: 24 }}>♪</div>
        <div>
          <div style={{ fontFamily: "var(--font-sans)", fontSize: 11, fontWeight: 700, letterSpacing: "0.14em", textTransform: "uppercase", color: "var(--ocean)" }}>{show || "Podcast"}</div>
          {title && <div style={{ fontFamily: "var(--font-serif)", fontSize: "1.2rem", fontWeight: 600, margin: "2px 0" }}>{title}</div>}
          {description && <p style={{ fontFamily: "var(--font-serif)", fontSize: "0.95rem", color: "var(--ink-soft)", margin: "2px 0 0" }}>{description}</p>}
          <div style={{ marginTop: 6 }}><RecursoLink rotulo={rotulo} href={href} /></div>
        </div>
      </div>
    );
  }
  /* … render web interativo (iframe/player) original … */
}
```

> **Generalize a regra.** Qualquer `<iframe>`, `<video>` ou `<audio>` embutido
> que você encontre numa aula (mesmo fora destes componentes) segue o mesmo
> tratamento: quadro estático identificável + `RecursoLink` com a URL pública
> abaixo. Se não houver URL pública (mídia só embutida), renderize ao menos o
> título e uma nota "disponível na versão online da aula".

---

## 6. Componentes que NÃO precisam de ramo especial

Estes já imprimem bem como estão — só herdam a folha `lume-pdf.css`:

- `LessonHero`, `Prose`, `Eyebrow`, `Destaque`, `Atencao`, `Reflexao`,
  `Citacao`, `PitacoDo`, `ChapterDivider`, `MateriaisExtras`, `CaseCards`,
  `ImagemLegenda`, `FeatureGrid` e `Tabela`.
- **`LessonHero`:** se `authorImage` existir, a foto deve aparecer no círculo;
  caso contrário, preserve a inicial do nome.
- **`Citacao`:** respeite `showAttribution`; olhos editoriais não devem ganhar
  autor ou ano no PDF.
- **`Tabela`:** preserve a superfície clara própria e evite divisão de linhas ou
  cartões mobile entre páginas.
- **`Reflexao`:** o `<textarea>` de resposta do aluno pode virar **linhas em
  branco para escrita à mão** no papel (mais útil que uma caixa vazia). Opcional:
  no Modo PDF, troque o textarea por 3–4 linhas `border-bottom: 1px solid var(--rule)`.
- **`ImagemLegenda` com `image-slot`:** se a imagem não foi preenchida, o
  placeholder imprime como um retângulo com o texto-guia — aceitável, mas avise
  o usuário para preencher as imagens antes de gerar o PDF final.
- **Chrome:** `TopBar` e `ProgressBar` somem (classes `lume-topbar` /
  `lume-progressbar`). O `LessonComplete` (botão de concluir no Moodle) não faz
  sentido no papel — dê a ele `data-pdf-hide` para ocultá-lo, mantendo o
  `CreditsFooter` (autoria, licença) que **deve** aparecer.

---

## 7. Checklist final do PDF Lume

Rode esta lista antes de entregar o PDF:

- [ ] Abriu via `index.html?pdf=1` (não o `index.html` cru)?
- [ ] Tamanho **A4**, margens padrão e **"gráficos de plano de fundo" ligado**?
- [ ] **Slider:** todos os slides aparecem empilhados, com título superior e
      marcador/ícone preservados?
- [ ] **Flashcards:** todos os cards aparecem, com frente **e** verso?
- [ ] **Accordion:** todos os itens abertos (pergunta + resposta)?
- [ ] **Quiz:** alternativas listadas e gabarito + explicação conforme combinado?
- [ ] **Glossário:** cada termo tem a definição visível (nota inline ou lista)?
- [ ] **Referências:** lista completa, aberta?
- [ ] **Vídeos:** quadro estático com a URL do YouTube logo abaixo?
- [ ] **Áudios/podcasts:** card com a URL do Spotify (ou caminho do arquivo) abaixo?
- [ ] Nenhum bloco (figura, card, citação, questão) **cortado** entre páginas?
- [ ] Sem barra de topo, sem barra de progresso, sem botão "concluir"?
- [ ] `CreditsFooter` (autoria + licença CC) presente no fim?
- [ ] Hero preserva foto do autor ou fallback de inicial?
- [ ] Citações respeitam a opção de ocultar autoria?
- [ ] Tabelas permanecem em superfície clara e legível?

---

## 8. Resumo para o agente

1. **Modo PDF = `?pdf=1`** no mesmo `index.html`, distribuído por `PDFContext`.
2. Cada componente que **esconde** conteúdo ganha um ramo `if (usePDF())` que
   **expande tudo** (seção 4).
3. Cada **mídia embutida** vira quadro estático + `RecursoLink` com a URL pública
   abaixo (seção 5).
4. **`lume-pdf.css`** cria a página A4, esconde o chrome e controla as quebras
   (seção 3).
5. Gere com *Salvar como PDF* em **A4 + fundo ligado**; confira pela seção 7.

O PDF é uma saída de leitura. Nos pacotes HTML e SCORM, o exportador também deve
incluir o arquivo `.lume.json` original do projeto; não remova esse arquivo ao
montar ou pós-processar o ZIP.

*Lume Design System · Skill de Exportação PDF A4 · junho 2026 · Autor do sistema: Lindner*
*Skills relacionadas: `SKILL.md` (sistema), `LUME_CONTENT_SKILL.md` (marcação de conteúdo).*
