Files
ealmeida a33c5e1b05 feat(design-media): /clone-style — extracção de design tokens (web + pptx)
Resolve dor real: clonar estilos visuais de sites e slides para propostas.
Tentativas anteriores (Penpot, scrapers HTML, Figma import) falharam porque
tentavam reproduzir layouts. Esta skill extrai tokens (cores, fontes,
espaçamento, raios, sombras) e alimenta gerador (Stitch / design-engine).

Modos:
- /clone-style web <url>: extract-web-tokens.js via chrome real (CSS computado)
- /clone-style slides <pptx>: extract-pptx-theme.py (theme1.xml + slideMasters)
- /clone-style apply <tokens.json>: mapeia para Stitch / design-engine / pptx

Validado: PPTX (Calibri/Calibri Light + 6 accent colors do Office default theme).
Web: aguarda primeiro teste end-to-end com browser real.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 05:13:16 +01:00

9.9 KiB

name, description
name description
clone-style Clona o estilo visual de um site ou apresentação extraindo design tokens (cores, tipografia, espaçamento, raios, sombras) e gerando JSON compatível com Stitch, design-engine e pptx-generator. Usar quando "clonar estilo", "clone style", "extrair design", "copiar visual", "tokens design", "clone web", "clone slides", "design tokens".

/clone-style — Extrair Design Tokens de Sites e Slides

Princípio fundamental

Não tentes recriar visualmente — extrai o sistema. Captura os tokens (cores, fontes, espaçamentos, raios) e alimenta uma ferramenta generativa. A fidelidade vem do sistema, não da imitação pixel a pixel.

Modos

Comando Fonte Output
/clone-style web <url> Site live (browser real, CSS computado) tokens.json + screenshots componentes
/clone-style slides <pptx_path> Ficheiro PPTX local tokens.json (theme1.xml + slideMasters)
/clone-style apply <tokens.json> Design tokens já extraídos Aplicação no Stitch / design-engine / pptx-generator

Modo 1 — Web

Workflow

  1. Abrir URL no Chrome real via mcp__claude-in-chrome__navigate (preferido — captura sessões logged-in se necessário) ou mcp__chrome-devtools__navigate_page.

  2. Aguardar render completo (wait_for "load" + 2s extra para JS).

  3. Injectar script de extracção via mcp__claude-in-chrome__javascript_tool ou mcp__chrome-devtools__evaluate_script. O script está em references/extract-web-tokens.js. Cola-o dentro do tool call.

  4. O script devolve JSON estruturado com:

    • colors: paleta deduplicada + ranking por frequência (top 12)
    • fonts: famílias únicas + tamanhos + pesos + line-heights
    • spacing: gaps/paddings/margins agrupados (encontra grid base 4px/8px)
    • borderRadius: pequeno/médio/grande/full (clusters)
    • shadows: box-shadows únicas
    • componentes: HTML+CSS de buttons, cards, nav, hero (capturados como referência)
  5. Capturar screenshots dos componentes detectados via mcp__chrome-devtools__take_screenshot ou mcp__claude-in-chrome__computer (full + por componente).

  6. Mapear para Stitch (ver secção "Mapeamento Stitch" abaixo) — cores → primary seed, fonte mais usada → enum match, raio dominante → ROUND_*.

  7. Guardar em ~/.claude-work/clone-style/<dominio>-<timestamp>/tokens.json + screenshots/.

Comando exemplo

/clone-style web https://linear.app

Output esperado:

  • ~/.claude-work/clone-style/linear-app-20260407/tokens.json
  • ~/.claude-work/clone-style/linear-app-20260407/screenshots/full.png
  • ~/.claude-work/clone-style/linear-app-20260407/screenshots/hero.png
  • ~/.claude-work/clone-style/linear-app-20260407/screenshots/buttons.png
  • Resumo no terminal: paleta + fontes + sugestão de aplicação

Modo 2 — Slides (PPTX)

PPTX é um ZIP de XML. Toda a informação de tema está em ppt/theme/theme1.xml e ppt/slideMasters/slideMaster1.xml.

Workflow

  1. Verificar input existe e é PPTX válido (unzip -l <file> para listar entradas).

  2. Extrair em tmp: unzip -o <file> -d /tmp/clone-style-pptx-<ts>/.

  3. Parsear theme1.xml (Python ou xmllint):

    import xml.etree.ElementTree as ET
    ns = {'a': 'http://schemas.openxmlformats.org/drawingml/2006/main'}
    tree = ET.parse('ppt/theme/theme1.xml')
    root = tree.getroot()
    
    # Cores tema (accent1-6, dark1, dark2, light1, light2, hyperlink, followedHyperlink)
    colors = {}
    for child in root.iter('{http://schemas.openxmlformats.org/drawingml/2006/main}clrScheme'):
        for color_node in child:
            name = color_node.tag.split('}')[1]
            srgb = color_node.find('a:srgbClr', ns)
            sysclr = color_node.find('a:sysClr', ns)
            if srgb is not None:
                colors[name] = '#' + srgb.get('val')
            elif sysclr is not None:
                colors[name] = '#' + sysclr.get('lastClr', '000000')
    
    # Fontes (major = headlines, minor = body)
    fonts = {}
    for fs in root.iter('{http://schemas.openxmlformats.org/drawingml/2006/main}fontScheme'):
        major = fs.find('a:majorFont/a:latin', ns)
        minor = fs.find('a:minorFont/a:latin', ns)
        if major is not None: fonts['headline'] = major.get('typeface')
        if minor is not None: fonts['body'] = minor.get('typeface')
    
  4. Parsear slideMaster1.xml para layouts dominantes (background, posições, sizes default).

  5. Output tokens.json no mesmo formato do Modo 1 (para que apply seja unificado).

Comando exemplo

/clone-style slides /home/ealmeida/Downloads/template-cliente.pptx

Modo 3 — Apply

Recebe tokens.json e aplica numa das 3 ferramentas:

A) Stitch (web/UI)

Limitação importante: Stitch só aceita um conjunto restrito de tokens (ver schema mcp__stitch__create_design_system):

  • 1 customColor (seed) + opcionais overridePrimaryColor/overrideSecondaryColor/overrideTertiaryColor/overrideNeutralColor
  • headlineFont / bodyFont / labelFont de enum fixo (29 Google Fonts: INTER, ROBOTO, MANROPE, GEIST, etc.)
  • roundness: ROUND_4 / ROUND_8 / ROUND_12 / ROUND_FULL
  • colorMode: LIGHT / DARK
  • designMd: markdown livre para tudo o que não cabe nos campos acima

Mapeamento Stitch:

tokens.colors.dominant → customColor (seed)
tokens.colors.top[1..3] → overridePrimary/Secondary/Tertiary
tokens.colors.neutral → overrideNeutralColor

tokens.fonts.headline.family
  → match com enum Stitch (fuzzy: "Helvetica" → INTER, "Söhne" → INTER, etc.)
  → headlineFont

tokens.fonts.body.family
  → match enum → bodyFont

tokens.borderRadius.dominant
  → 4px → ROUND_4
  → 8-10px → ROUND_8
  → 12-14px → ROUND_12
  → ≥16px ou full → ROUND_FULL

tokens.background.dark? → colorMode: DARK, else LIGHT

# Tudo o resto vai para designMd:
designMd: |
  ## Estilo extraído de <fonte>

  ### Tipografia adicional
  - Display: <font> <size> <weight>
  - Caption: <font> <size> <weight>

  ### Espaçamento
  Grid base: <Npx>
  Escala: 4, 8, 16, 24, 32, 48, 64

  ### Sombras
  - sm: <box-shadow>
  - md: <box-shadow>
  - lg: <box-shadow>

  ### Tom visual
  <descrição em prosa: minimalista, denso, colorido, monocromático, etc.>

Depois chama mcp__stitch__create_design_system com este payload.

B) design-engine (brand pack)

Cria um JSON brand pack em /media/ealmeida/Dados/Hub/04-Recursos/Design/brands/<nome>.json com formato:

{
  "name": "<nome>",
  "source": "cloned from <url|pptx>",
  "extracted_at": "2026-04-07",
  "colors": { "primary": "#...", "secondary": "#...", "neutral": "#...", "accent": "#..." },
  "fonts": { "headline": "Inter", "body": "Inter" },
  "borderRadius": "8px",
  "tone": "minimalista, profissional, denso"
}

Depois mcp__design-engine__brand_load(<nome>) para usar em generate_image.

C) pptx-generator (slides)

Aplica os tokens via XML manipulation no template Descomplicar (ver /pptx-generator). Substitui:

  • Cores accent1-6 do theme1.xml pelos extraídos
  • Fontes major/minor pelas extraídas
  • Mantém layouts/positioning do template Descomplicar (não copia layouts da fonte original — só estilo)

Mapeamento de fontes (fuzzy → Stitch enum)

Quando tokens.fonts.headline.family não está no enum Stitch, mapear:

Família detectada Stitch enum
Helvetica, Helvetica Neue, Arial, sans-serif genérico INTER
Söhne, Inter, system-ui INTER
Roboto, Roboto Flex (não existe — usar INTER)
SF Pro, -apple-system INTER
GT Walsheim, Geist, Mona Sans GEIST
Manrope MANROPE
Plus Jakarta, Jakarta PLUS_JAKARTA_SANS
DM Sans DM_SANS
IBM Plex Sans IBM_PLEX_SANS
Sora SORA
Times, serif genérico NEWSREADER
Garamond, EB Garamond EB_GARAMOND
Playfair, Domine DOMINE

Se nenhum match óbvio, default INTER (mais neutro). Adicionar nota em designMd com a fonte original detectada.


Anti-patterns

Não fazer Razão
Tentar reproduzir layout pixel a pixel Impossível e gera "AI slop"
Usar cssstats.com ou scrapers HTML estáticos Falham em sites JS-rendered (Next.js, React, etc.)
Importar HTML inteiro como Stitch screen Stitch não importa HTML; gera de prompt+tokens
Aplicar Stitch design-system sem customColor válido Validation error — customColor é obrigatório
Esquecer de usar designMd para tokens fora do enum Perde-se 50% da informação extraída

Validação (critérios para "OK")

Antes de declarar a clonagem completa:

  1. tokens.json existe e tem colors, fonts, borderRadius no mínimo
  2. Pelo menos 1 screenshot guardado
  3. Mapeamento Stitch produz customColor válido (hex format)
  4. Pelo menos 1 fonte mapeada para enum Stitch
  5. designMd tem ≥3 secções (tipografia, espaçamento, tom)
  6. Se modo apply: validação visual pelo utilizador antes de marcar "concluído"

Exemplos práticos

Clonar Linear

/clone-style web https://linear.app

Esperado: paleta dominante azul/roxo, fontes Inter ou similar, raios 6-8px, dark mode default.

Clonar template cliente

/clone-style slides ~/Downloads/cliente-deck.pptx

Esperado: cores accent do tema PPTX, fontes major/minor, proposta de paleta unificada.

Aplicar a novo projecto Stitch

/clone-style apply ~/.claude-work/clone-style/linear-app-20260407/tokens.json

Cria design system Stitch + brand pack design-engine.


Referências internas

  • references/extract-web-tokens.js — script JS de extracção CSS computado
  • references/extract-pptx-theme.py — script Python para parsear theme1.xml
  • ~/.claude-work/clone-style/ — cache de extracções (timestamped)

Versão: 1.0.0 | Data: 2026-04-07 | Autor: Descomplicar (sessão 5) Origem: Necessidade real — clonagem de estilos em propostas comerciais. Substitui tentativas falhadas com Penpot, scrapers HTML, screenshots+AI, Figma import.