Boas práticas
7. Apresentações — biblioteca de componentes de slide
seed-praticas.md v0.1 · §07seção 9 de 1707-apresentacoes-biblioteca-de-componentes-de.md · MD5 2630813fTítulo completo no canon: Apresentações — biblioteca de componentes de slide (maio/2026)
Origem:
seed-ds-slide/references/componentes-slide-seed.md(skill de 2026-05-13, 18615 bytes, MD5a40d0b6bb931f85dfdad1259a7bffcf9; cópia preservada em09-pesquisa/skills-v1-2026-05/referencias/componentes-slide-seed.md) · Importado em 2026-09-06 sem edição — só os títulos foram rebaixados dois níveis (código intacto).Estado: ⚠ não auditado contra o DS v2. Contradições medidas — vale a regra de precedência do cabeçalho: 15 cor(es) em hex — só os tokens do
seed-tokens.jsonvalem (marca §3, §11) · cita a Indie Flower — fonte APOSENTADA em 2026-07-30 (marca §4.4); a celebratória é a Caveat (§4.3).
Componentes de slide SEED — biblioteca canônica#
Reference exclusiva da skill seed-ds-slide. Define os 10 layouts de slide aplicáveis em decks PPTX SEED, com regras visuais, dimensões explícitas e código python-pptx típico.
REGRA DURA: todo elemento posicionável em python-pptx (add_textbox, add_picture, add_shape) requer 4 valores explícitos — left, top, width, height em Inches. Sem isso, python-pptx empilha os elementos a partir do canto superior esquerdo e gera overlay/overflow. Issue identificado em produção: stat callout com 3 números sem coordenadas explícitas → números de 72pt sobrepondo os labels. Sempre declarar geometria.
Configuração base do Slide Master#
from pptx import Presentation
from pptx.util import Inches, Pt, Emu
from pptx.dml.color import RGBColor
from pptx.enum.text import PP_ALIGN
from pptx.enum.shapes import MSO_SHAPE
prs = Presentation()
prs.slide_width = Inches(10) # 16:9 widescreen
prs.slide_height = Inches(5.625)
# Paleta SEED canônica — 18 tokens (de paleta.md)
# Primárias
SEED_TURQUESA = RGBColor(0x11, 0xB0, 0xA0) # #11B0A0
BRANCO = RGBColor(0xFF, 0xFF, 0xFF) # #FFFFFF
# Secundárias
SEED_AMARELO = RGBColor(0xFA, 0xD6, 0x1D) # #FAD61D
SEED_VERDE = RGBColor(0x09, 0x84, 0x75) # #098475
# Terciárias
SEED_CINZA = RGBColor(0x61, 0x76, 0x83) # #617683
SEED_AMARELO_DOURADO = RGBColor(0xF9, 0xB1, 0x1C) # #F9B11C
SEED_AZUL = RGBColor(0x53, 0xC2, 0xE9) # #53C2E9
SEED_AZUL_CLARO = RGBColor(0xEC, 0xF4, 0xFC) # #ECF4FC
# Derivadas oficiais
SEED_TURQUESA_DEEP = RGBColor(0x0A, 0x84, 0x78) # #0a8478
SEED_TURQUESA_SOFT = RGBColor(0xE6, 0xF7, 0xF5) # #e6f7f5
SEED_CINZA_LIGHT = RGBColor(0xF4, 0xF6, 0xF7) # #f4f6f7
SEED_CINZA_BORDER = RGBColor(0xE1, 0xE6, 0xEA) # #e1e6ea
SEED_TEXT = RGBColor(0x2A, 0x39, 0x42) # #2a3942
Slide canvas — sistema de coordenadas#
Slide 16:9 = 10 inches × 5.625 inches. Pensar como grid:
0,0────────────────────────────────────10,0
│ Safe zone: │
│ 0.5" margem em todos os lados │
│ │
│ Área útil: 9.0 × 4.625 inches │
│ │
0,5.625──────────────────────────10,5.625
Safe zones (não negociáveis):
- Margem mínima esquerda/direita: 0.5 inch
- Margem mínima superior/inferior: 0.5 inch
- Logo no rodapé: respeita 0.4" da borda inferior (não colar na borda)
Logo — regras de geometria#
Issue identificado em produção: logo cortada por bounding box apertada. Resolução: margem de segurança 10% do lado menor do logo em todas as direções dentro da bounding box.
# CERTO — bounding box com margem interna implícita
logo_left = Inches(0.5)
logo_top = Inches(0.4)
logo_width = Inches(1.5) # margem 0.15" implícita
logo_height = Inches(0.45)
slide.shapes.add_picture(LOGO_PATH, logo_left, logo_top, logo_width, logo_height)
# ERRADO — bounding box justa, logo corta na renderização
slide.shapes.add_picture(LOGO_PATH, Inches(0.5), Inches(0.4),
Inches(1.2), Inches(0.36)) # justo demais
Tamanhos canônicos de logo por uso:
| Uso | Variante | Width | Height | Posição |
|---|---|---|---|---|
| Capa (grande, centralizado) | horizontal-fundo-turquesa.svg | 4.0" | 1.2" | center horizontal, top 1.2" |
| Agradecimento (grande, centralizado) | horizontal-fundo-turquesa.svg | 4.0" | 1.2" | center horizontal, top 1.5" |
| Rodapé de slide intermediário | símbolo (vertical-principal — só símbolo) | 0.35" | 0.35" | right 0.5", bottom 0.4" |
| Slide de seção | vertical-fundo-turquesa.svg | 1.5" | 1.5" | bottom-right 0.6", 0.5" |
10 layouts canônicos#
1. Capa#
Quando usar: sempre slide 1.
Dimensões:
# Fundo turquesa-deep
bg = slide.shapes.add_shape(MSO_SHAPE.RECTANGLE, 0, 0,
prs.slide_width, prs.slide_height)
bg.fill.solid()
bg.fill.fore_color.rgb = SEED_TURQUESA_DEEP
bg.line.fill.background()
# Logo horizontal grande, centralizado superior
logo = slide.shapes.add_picture(LOGO_FUNDO_TURQUESA, Inches(3.0), Inches(1.0),
width=Inches(4.0), height=Inches(1.2))
# Título centralizado
title_box = slide.shapes.add_textbox(Inches(1.0), Inches(2.6),
Inches(8.0), Inches(1.0))
tf = title_box.text_frame
tf.word_wrap = True
p = tf.paragraphs[0]
p.alignment = PP_ALIGN.CENTER
run = p.add_run()
run.text = "Título principal aqui"
run.font.name = "Montserrat"
run.font.size = Pt(44)
run.font.bold = True
run.font.color.rgb = BRANCO
# Subtítulo
sub_box = slide.shapes.add_textbox(Inches(1.0), Inches(3.7),
Inches(8.0), Inches(0.6))
# (mesmo padrão, Pt(22), Light, branco)
Regras:
- Fundo: turquesa-deep
#0a8478ou turquesa#11B0A0 - Logo: horizontal-fundo-turquesa.svg, 4.0×1.2 inch, centralizado superior
- Título: Montserrat Bold 44-54pt, branco, centralizado
- Subtítulo: Montserrat Light 20-24pt, branco semi-transparente
- Onda decorativa (opcional): SVG turquesa+verde na base do slide
- Sem rodapé (capa é "limpa")
2. Seção / Divisor#
Quando usar: entre blocos de 3-5 slides, em decks de 15+ slides.
# Fundo turquesa
bg = slide.shapes.add_shape(MSO_SHAPE.RECTANGLE, 0, 0,
prs.slide_width, prs.slide_height)
bg.fill.solid()
bg.fill.fore_color.rgb = SEED_TURQUESA
# Número grande à esquerda
num_box = slide.shapes.add_textbox(Inches(0.8), Inches(1.5),
Inches(2.5), Inches(2.5))
# Montserrat Bold 120pt, amarelo
# Título da seção à direita
title_box = slide.shapes.add_textbox(Inches(3.5), Inches(2.2),
Inches(6.0), Inches(1.2))
# Montserrat Bold 36-44pt, branco
3. Conteúdo texto#
Default para texto/listas.
# Fundo branco
bg = slide.shapes.add_shape(MSO_SHAPE.RECTANGLE, 0, 0,
prs.slide_width, prs.slide_height)
bg.fill.solid()
bg.fill.fore_color.rgb = BRANCO
bg.line.fill.background()
# Header turquesa horizontal (faixa superior)
header = slide.shapes.add_shape(MSO_SHAPE.RECTANGLE, 0, 0,
prs.slide_width, Inches(0.9))
header.fill.solid()
header.fill.fore_color.rgb = SEED_TURQUESA
# Título dentro do header
title_box = slide.shapes.add_textbox(Inches(0.5), Inches(0.2),
Inches(9.0), Inches(0.5))
# Montserrat Bold 28-32pt, branco
# Body content abaixo do header
body_box = slide.shapes.add_textbox(Inches(0.5), Inches(1.2),
Inches(9.0), Inches(3.8))
# Montserrat Regular 14-18pt, cinza
# Bullets ou parágrafos curtos
# Rodapé fino: símbolo direita + paginação
foot_logo = slide.shapes.add_picture(LOGO_SIMBOLO,
Inches(9.15), Inches(5.25),
Inches(0.35), Inches(0.35))
Regras:
- Regra 6×6 — máximo 6 bullets × 6 palavras por bullet
- Margens 0.5" mínimo
- Não bullet-explodir: parágrafos curtos podem ser mais legíveis
4. Dados / Stat callout — CORRIGIDO#
Quando usar: destacar 1 a 3 números.
Bug histórico: layouts com múltiplos números sem coordenadas explícitas geravam overlay (número de 72pt cobrindo o label). Correção: declarar left/top/width/height para CADA elemento, e respeitar o espaço vertical do número (72pt ≈ 1.0 inch).
Layout canônico para 3 stats (grid horizontal 33/33/33):
# Fundo branco
bg = slide.shapes.add_shape(MSO_SHAPE.RECTANGLE, 0, 0,
prs.slide_width, prs.slide_height)
bg.fill.solid()
bg.fill.fore_color.rgb = BRANCO
# Título do slide (opcional, no topo)
title_box = slide.shapes.add_textbox(Inches(0.5), Inches(0.5),
Inches(9.0), Inches(0.5))
# Montserrat Bold 24pt, turquesa
# Geometria das 3 colunas — IMPORTANTE: cada coluna tem 3 elementos verticais
# (número, linha separadora, label) cada um com seu retângulo distinto.
#
# Largura útil: 10.0 - 0.5 - 0.5 = 9.0 inches (3 colunas de 3.0 cada)
# Topo dos números: 1.7" (deixa espaço pro título acima)
# Altura do número (72pt fonte): 1.2"
# Topo da linha separadora: 3.0"
# Topo do label: 3.2"
# Topo do contexto: 3.8"
col_width = Inches(3.0)
col_lefts = [Inches(0.5), Inches(3.5), Inches(6.5)]
numbers = [("45.000 kWh", "CONSUMO MENSAL", "Indústria média região ES"),
("180 kVA", "DEMANDA CONTRATADA", "Grupo A4 cativo"),
("R$ 8.500", "ECONOMIA/MÊS", "Após otimização SEED")]
for i, (num, label, contexto) in enumerate(numbers):
# NÚMERO grande
n_box = slide.shapes.add_textbox(col_lefts[i], Inches(1.7),
col_width, Inches(1.2))
n_tf = n_box.text_frame
n_tf.word_wrap = True
n_p = n_tf.paragraphs[0]
n_p.alignment = PP_ALIGN.CENTER
n_run = n_p.add_run()
n_run.text = num
n_run.font.name = "Montserrat"
n_run.font.size = Pt(48) # 48-72pt — calibrar pelo tamanho do número
n_run.font.bold = True
n_run.font.color.rgb = SEED_TURQUESA
# SEPARADOR linha curta (opcional, decorativo)
sep = slide.shapes.add_shape(MSO_SHAPE.RECTANGLE,
col_lefts[i] + Inches(1.25), Inches(3.05),
Inches(0.5), Inches(0.03))
sep.fill.solid()
sep.fill.fore_color.rgb = SEED_CINZA_BORDER
sep.line.fill.background()
# LABEL UPPERCASE
l_box = slide.shapes.add_textbox(col_lefts[i], Inches(3.2),
col_width, Inches(0.4))
l_tf = l_box.text_frame
l_p = l_tf.paragraphs[0]
l_p.alignment = PP_ALIGN.CENTER
l_run = l_p.add_run()
l_run.text = label
l_run.font.name = "Montserrat"
l_run.font.size = Pt(14)
l_run.font.bold = True
l_run.font.color.rgb = SEED_CINZA
# CONTEXTO opcional
c_box = slide.shapes.add_textbox(col_lefts[i], Inches(3.8),
col_width, Inches(0.5))
c_tf = c_box.text_frame
c_p = c_tf.paragraphs[0]
c_p.alignment = PP_ALIGN.CENTER
c_run = c_p.add_run()
c_run.text = contexto
c_run.font.name = "Montserrat"
c_run.font.size = Pt(11)
c_run.font.color.rgb = SEED_CINZA
Tamanho do número por quantidade de stats:
| Stats | Tamanho do número | Largura por coluna |
|---|---|---|
| 1 stat (slide hero) | 96pt (max 4.0" altura) | 9.0" centralizado |
| 2 stats | 72pt (3.0" altura) | 4.0" cada (gap 1.0") |
| 3 stats | 48-56pt (1.2-1.5" altura) | 3.0" cada |
| 4+ stats | NÃO recomendado — quebrar em 2 slides |
Anti-padrão verificado: colocar número 72pt + label + contexto em coluna de 2.0" — texto vaza horizontal. Largura mínima 3.0" pra número 48-72pt.
5. Gráfico#
Quando usar: dados comparativos, tendências, distribuições.
Geometria:
- Título do slide: topo, 0.5" margem, altura 0.6"
- Subtítulo (opcional): topo após título, 0.4"
- Área do gráfico: 8.0×4.0 inches, centralizado, com 0.5" de margem
- Fonte/legenda abaixo: Montserrat Light 10pt, cinza
Regras:
- 1 chart por slide (não empilhar 2+)
- Highlight de insight: uma cor SEED (geralmente turquesa) destaca o ponto crítico, resto neutro (
SEED_CINZAouSEED_CINZA_BORDER) - Não pintar tudo de turquesa — anula o destaque
- Sempre incluir fonte citada (Aneel, EPE, IBGE, etc) no rodapé
6. Foto half-bleed#
Geometria:
- Imagem: 5.0×5.625 inches (lado direito, full-bleed vertical)
- Conteúdo lado esquerdo: 5.0×5.625 inches, fundo branco
- Margem interna 0.5"
- Título Montserrat Bold 24-32pt, turquesa
- Body Montserrat Regular 14-18pt, cinza
- Logo discreto no canto inferior do lado de texto
7. Comparativo (2 ou 3 colunas)#
Para 2 colunas (4.5×4.5 inches cada, gap 0.5"):
# Coluna 1
col1_bg = slide.shapes.add_shape(MSO_SHAPE.ROUNDED_RECTANGLE,
Inches(0.5), Inches(1.3),
Inches(4.5), Inches(3.6))
col1_bg.fill.solid()
col1_bg.fill.fore_color.rgb = SEED_TURQUESA_SOFT
col1_bg.line.color.rgb = SEED_CINZA_BORDER
# Header da coluna 1
col1_header = slide.shapes.add_shape(MSO_SHAPE.RECTANGLE,
Inches(0.5), Inches(1.3),
Inches(4.5), Inches(0.7))
col1_header.fill.solid()
col1_header.fill.fore_color.rgb = SEED_TURQUESA
# Título da coluna 1 dentro do header
# ... Montserrat Bold 18-22pt, branco
# Body da coluna 1 — bullets ou parágrafos
# ... Montserrat Regular 12-14pt, cinza ou text-dark
# Coluna 2 (lefts: 5.0", restante igual)
8. Citação / Depoimento#
# Fundo branco ou turquesa-soft
# Aspas grandes turquesa decorativas — em canto superior esquerdo
aspas_box = slide.shapes.add_textbox(Inches(0.5), Inches(0.6),
Inches(1.0), Inches(1.5))
# " em Montserrat Bold 120pt, turquesa
# Texto da citação centralizado
quote_box = slide.shapes.add_textbox(Inches(1.5), Inches(1.5),
Inches(7.0), Inches(2.5))
# Montserrat Regular 24-28pt, text-dark, itálico opcional
# Atribuição (autor + cargo)
author_box = slide.shapes.add_textbox(Inches(1.5), Inches(4.2),
Inches(7.0), Inches(0.5))
# Montserrat SemiBold 14pt, cinza
9. Timeline#
Geometria horizontal:
# Linha central
line = slide.shapes.add_shape(MSO_SHAPE.RECTANGLE,
Inches(0.8), Inches(2.7),
Inches(8.4), Inches(0.06))
line.fill.solid()
line.fill.fore_color.rgb = SEED_TURQUESA
# Marcos: círculos numerados sobre a linha
# Para 5 marcos, espaçar a cada 2.0 inches a partir de 0.8"
marcos = ["2016", "2018", "2020", "2023", "2026"]
labels = ["Fundação", "Pri. cliente PJ", "Sede Vitória", "Diagnóstico 360°", "Lançamento ERP"]
for i, (data, lbl) in enumerate(zip(marcos, labels)):
x = Inches(0.8 + i * 2.0)
# Círculo
circle = slide.shapes.add_shape(MSO_SHAPE.OVAL,
x - Inches(0.2), Inches(2.5),
Inches(0.4), Inches(0.4))
circle.fill.solid()
circle.fill.fore_color.rgb = SEED_TURQUESA
# Data (acima ou abaixo, alternar)
if i % 2 == 0:
# Acima
d_box = slide.shapes.add_textbox(x - Inches(0.6), Inches(1.7),
Inches(1.2), Inches(0.3))
lbl_box = slide.shapes.add_textbox(x - Inches(1.0), Inches(2.0),
Inches(2.0), Inches(0.4))
else:
# Abaixo
d_box = slide.shapes.add_textbox(x - Inches(0.6), Inches(3.0),
Inches(1.2), Inches(0.3))
lbl_box = slide.shapes.add_textbox(x - Inches(1.0), Inches(3.3),
Inches(2.0), Inches(0.4))
10. Agradecimento / Fechamento#
Quando usar: sempre slide final.
# Fundo turquesa-deep
bg = slide.shapes.add_shape(MSO_SHAPE.RECTANGLE, 0, 0,
prs.slide_width, prs.slide_height)
bg.fill.solid()
bg.fill.fore_color.rgb = SEED_TURQUESA_DEEP
# Logo grande centralizado
logo = slide.shapes.add_picture(LOGO_FUNDO_TURQUESA,
Inches(3.0), Inches(1.0),
Inches(4.0), Inches(1.2))
# "Obrigado." ou similar
obg_box = slide.shapes.add_textbox(Inches(1.0), Inches(2.5),
Inches(8.0), Inches(0.9))
# Montserrat Bold 48-64pt, branco, centralizado
# Contato — INCLUI 0800 SEMPRE
contato_box = slide.shapes.add_textbox(Inches(1.0), Inches(3.8),
Inches(8.0), Inches(0.5))
# Montserrat Regular 18pt, branco, centralizado
# Texto: "seed.eng.br · 0800 591 5374"
# Tagline opcional
tagline_box = slide.shapes.add_textbox(Inches(1.0), Inches(4.6),
Inches(8.0), Inches(0.5))
# Indie Flower 24pt, amarelo, centralizado
# Texto: "Provemos Eficiência Energética"
Regras:
- 0800 591 5374 obrigatório no slide de fechamento (issue conhecido: decks anteriores foram apenas com site, perdendo canal imediato)
- Logo grande centralizado (não no canto)
- Onda decorativa na base (opcional)
Speaker notes — padrão#
Quando briefing inclui speaker notes:
slide.notes_slide.notes_text_frame.text = """
Pontos pra falar neste slide:
- [Contexto que apoia o que está visível]
- [Exemplo ou case mencionado em voz]
- [Transição pro próximo slide]
"""
Speaker notes são pra Rafael falar, plateia não vê. Permite slide enxuto (1 takeaway visual) com narrativa rica na fala.
Restrições visuais (anti-AI-slop, alinhado com pptx oficial)#
- ❌ Sem accent lines sob títulos (hallmark de slides AI-generated)
- ❌ Sem decorative full-width colored bars como rodapé (rodapé SEED é fino, com símbolo)
- ❌ Sem slides text-only (sempre EEny, ondas, ícone Lucide ou gráfico complementando)
- ❌ Sem cream/beige como fundo (branco ou cores SEED apenas)
- ❌ Sem mais de 1 chart por slide
- ❌ Sem text overflow (validar via QA da
pptxskill) - ❌ Sem elementos sem geometria explícita (
left, top, width, heightobrigatórios) - ❌ Sem logo com bounding box justa (margem 10% interna mínima)
- ❌ Sem stat callout com números 72pt em coluna <3.0" (vaza horizontalmente)
Checklist de QA visual após geração#
Antes de entregar, verificar nos JPGs renderizados:
- [ ] Logo aparece COMPLETA (não cortada nas bordas da bounding box)
- [ ] Stat callout: NÚMEROS e LABELS não se sobrepõem (verificar 1.5"+ entre topo do número e topo do label)
- [ ] Margens 0.5" respeitadas em todos os lados
- [ ] Nenhum texto vaza da bounding box
- [ ] Rodapé: símbolo SEED no canto direito (não decorative bar)
- [ ] Capa: logo 4.0×1.2" centralizado, não cortado
- [ ] Agradecimento: contém "0800 591 5374"
- [ ] Paleta: cores 100% SEED (18 tokens), zero hex alheio
- [ ] Grafia "SEED engenharia" correta em todos os elementos visíveis