# Optidata Design System

Referência legível por máquinas para o sistema visual da Optidata. Este arquivo espelha a página humana em [optidata.cloud/optidata-design-system](https://optidata.cloud/optidata-design-system) e o contrato de origem em `design-system.md`.

## Uso por agentes

1. Trate o tema claro como padrão.
2. Use os tokens com os nomes e valores exatos deste arquivo.
3. Use Manrope em todos os textos e escolha apenas os nove papéis tipográficos documentados.
4. Monte cada dobra com um bloco de texto e uma mídia dominante.
5. Use `#8d0de3` como único acento de marca. Limite o violeta a dois papéis saturados por viewport.
6. Use amarelo somente em warning semântico.
7. Reutilize logos e SpotIcons sem redesenhar a geometria.
8. Atenda contraste, foco, alvos e movimento reduzido antes de considerar uma interface pronta.
9. Use ícones, títulos e relações espaciais para sequências. Não use `01`, `02` e `03` como decoração de etapas, cards ou pilares.

## Identidade

```yaml
public_name: Optidata Design System
company_name: Optidata
primary_language: pt-BR
default_theme: light
optional_theme: dark
font_family: Manrope
primary_color: "#8d0de3"
content_max_width: 1208px
```

Regras de nome:

- Escreva Optidata com essa capitalização.
- O tom é confiante, técnico e concreto.
- Títulos declaram capacidade, consequência ou decisão. Evite hype sem prova.
- Nunca use os caracteres Unicode em dash ou en dash em nenhum idioma.

## Logos

| Arquivo | Uso | Download |
| --- | --- | --- |
| Logo branco | Fundos escuros | [optidata-logo-white.svg](https://optidata.cloud/design/logos/optidata-logo-white.svg) |
| Logo preto | Fundos claros | [optidata-logo-black.svg](https://optidata.cloud/design/logos/optidata-logo-black.svg) |
| Logo colorido | Símbolo `#8d0de3` e wordmark `#13191F` em fundo neutro | [optidata-logo.svg](https://optidata.cloud/design/logos/optidata-logo.svg) |
| Símbolo com `currentColor` | Favicon, avatar e espaços compactos | [optidata-mark.svg](https://optidata.cloud/design/logos/optidata-mark.svg) |

Contratos da marca:

- Escale sempre de forma proporcional.
- Preserve área livre mínima equivalente a um círculo do símbolo.
- Não aplique brilho, contorno, sombra ou gradiente ao logo.
- Não recolora os wordmarks fora das versões branca, preta e colorida.
- O símbolo isolado herda `currentColor`.

## Cores

### Marca

| Token | Claro | Escuro | Uso |
| --- | --- | --- | --- |
| `--color-primary` | `#8d0de3` | `#8d0de3` | Ação principal, foco de marca e estado selecionado |
| `--color-primary-hover` | `#7800c6` | `#a13de8` | Hover |
| `--color-primary-active` | `#6500a8` | `#7800c6` | Estado pressionado |
| `--color-primary-soft` | `#f4e9fb` | `#35203f` | Fundo selecionado |
| `--color-primary-soft-strong` | `#ead5f8` | `#452650` | Hover selecionado |
| `--color-on-primary` | `#ffffff` | `#ffffff` | Texto e ícone sobre primário |

### Superfícies, texto e bordas

| Token | Claro | Escuro |
| --- | --- | --- |
| `--color-canvas` | `#f8f7fa` | `#151018` |
| `--color-surface` | `#ffffff` | `#1f1823` |
| `--color-surface-subtle` | `#f2eef5` | `#29202e` |
| `--color-surface-raised` | `#ffffff` | `#32273a` |
| `--color-surface-inverse` | `#1b1320` | `#faf8fb` |
| `--color-text-primary` | `#201525` | `#f7f2f9` |
| `--color-text-secondary` | `#584d5e` | `#d3c8d7` |
| `--color-text-muted` | `#6f6475` | `#b0a2b5` |
| `--color-text-inverse` | `#ffffff` | `#201525` |
| `--color-icon-primary` | `#2b2030` | `#f7f2f9` |
| `--color-icon-secondary` | `#685d6e` | `#c2b5c8` |
| `--color-border-subtle` | `#ebe5ee` | `#342a39` |
| `--color-border` | `#d9d0de` | `#52455a` |
| `--color-border-strong` | `#8b7d92` | `#897890` |
| `--color-focus` | `#8d0de3` | `#cf8cff` |
| `--color-focus-offset` | `#ffffff` | `#151018` |

Contrastes medidos sobre a superfície principal:

```yaml
light:
  text_primary: "17.57:1"
  text_secondary: "7.96:1"
  text_muted: "5.59:1"
  icon_secondary: "6.21:1"
  border_strong: "3.86:1"
dark:
  text_primary: "15.68:1"
  text_secondary: "10.73:1"
  text_muted: "7.16:1"
  icon_secondary: "8.85:1"
  border_strong: "4.25:1"
  focus: "7.29:1"
```

### Estados semânticos

| Estado | Fundo claro | Conteúdo claro | Borda clara | Fundo escuro | Conteúdo escuro | Borda escura |
| --- | --- | --- | --- | --- | --- | --- |
| Sucesso | `--color-success-surface: #eaf8f1` | `--color-success: #147a52` | `--color-success-border: #9cd9bd` | `--color-success-surface: #173329` | `--color-success: #59dfa5` | `--color-success-border: #2a7659` |
| Alerta | `--color-warning-surface: #fff8df` | `--color-warning: #a45a00` | `--color-warning-border: #e8c769` | `--color-warning-surface: #3a2c13` | `--color-warning: #ffc35c` | `--color-warning-border: #866522` |
| Erro | `--color-danger-surface: #fff0f2` | `--color-danger: #b42332` | `--color-danger-border: #efb4bc` | `--color-danger-surface: #3d2026` | `--color-danger: #ff8793` | `--color-danger-border: #8c3f4a` |
| Informação | `--color-info-surface: #edf7ff` | `--color-info: #1469a8` | `--color-info-border: #a9d5f4` | `--color-info-surface: #172e40` | `--color-info: #71bfff` | `--color-info-border: #2e678d` |

Amarelo tem dois papéis, e eles não se misturam. `--color-warning` e seus derivados são o estado semântico de alerta. `--color-accent` é o acento de marca.

### Acento de marca

Amarelo Optidata, Pantone 7404 C. Vive apenas sobre superfície escura: eyebrow, palavra de destaque em título e ícone de selo. Nunca como fundo de bloco, nunca como cor de ação, nunca em corpo de texto.

| Token | Valor | Uso |
| --- | --- | --- |
| `--color-accent` | `#fde116` | Acento sobre superfície escura |
| `--color-accent-strong` | `#a87f00` | Mesmo papel em tema claro, onde o amarelo cheio não atinge 4.5:1 |
| `--color-on-accent` | `#201525` | Texto sobre o amarelo cheio |

### Rampa Ultravioleta

Paleta das dobras escuras: hero, header e bandas. `--color-primary` sozinho não cobre nem o fundo profundo nem os realces claros. Não muda entre temas, porque ela já é a paleta escura.

| Token | Valor |
| --- | --- |
| `--color-brand-100` | `#ecd9ff` |
| `--color-brand-200` | `#d9b3ff` |
| `--color-brand-300` | `#cba5fd` |
| `--color-brand-400` | `#af63fd` |
| `--color-brand-600` | `#8d0de3` |
| `--color-brand-900` | `#3f026a` |
| `--color-brand-950` | `#1e002f` |
| `--color-brand-ink` | `#0b0019` |

### Arte dos SpotIcons

| Token | Valor |
| --- | --- |
| `--color-spot-dark-canvas` | `#151018` |
| `--color-spot-dark-surface` | `#1f1823` |
| `--color-spot-dark-panel` | `#32273a` |
| `--color-spot-dark-ink` | `#f7f2f9` |
| `--color-spot-dark-ink-secondary` | `#c2b5c8` |
| `--color-spot-dark-hairline` | `#897890` |
| `--color-spot-dark-hairline-soft` | `#52455a` |
| `--color-spot-dark-success` | `#59dfa5` |
| `--color-spot-light-canvas` | `#f4e9fb` |
| `--color-spot-light-surface` | `#ffffff` |
| `--color-spot-light-panel` | `#ead5f8` |
| `--color-spot-light-ink` | `#2b2030` |
| `--color-spot-light-ink-secondary` | `#685d6e` |
| `--color-spot-light-hairline` | `#8b7d92` |
| `--color-spot-light-hairline-soft` | `#d9d0de` |
| `--color-spot-light-success` | `#147a52` |

## Tipografia

Token: `--font-family-sans`.

Família exata: `"Manrope", ui-sans-serif, system-ui, sans-serif`.

Pesos permitidos: 400, 500, 600 e 700.

| Papel | Tamanho | Entrelinha | Tracking | Peso |
| --- | --- | --- | --- | --- |
| Display | `--font-size-display: clamp(2.25rem, 3.4vw, 3rem)` | `--line-height-display: 1.06` | `--tracking-display: -0.035em` | 600 |
| Editorial | `--font-size-editorial: clamp(1.75rem, 2.6vw, 2.25rem)` | `--line-height-editorial: 1.14` | `--tracking-editorial: -0.025em` | 600 |
| Título 1 | `--font-size-heading-1: 1.75rem` | `--line-height-heading-1: 1.2` | `--tracking-heading-1: -0.02em` | 600 |
| Título 2 | `--font-size-heading-2: 1.375rem` | `--line-height-heading-2: 1.3` | `--tracking-heading-2: -0.015em` | 600 |
| Título 3 | `--font-size-heading-3: 1.125rem` | `--line-height-heading-3: 1.4` | `--tracking-heading-3: -0.01em` | 600 |
| Corpo grande | `--font-size-body-lg: 1.125rem` | `--line-height-body: 1.6` | `0` | 400 |
| Corpo | `--font-size-body: 1rem` | `--line-height-body: 1.6` | `0` | 400 |
| Corpo pequeno | `--font-size-body-sm: 0.875rem` | `--line-height-body-sm: 1.55` | `0` | 400 |
| Rótulo | `--font-size-label: 0.75rem` | `--line-height-label: 1.4` | `--tracking-label: 0.1em` | 600 |

A escala tem oito degraus e base 16 px. Cada degrau e um salto perceptivel: 48/36 = 1.33, 36/28 = 1.29, 28/22 = 1.27, 22/18 = 1.22. Nao existe degrau de 17 px. Titulo de dobra usa Editorial, subsecao usa Titulo 1, titulo de card usa Titulo 3, e paragrafo usa Corpo. O Display fica reservado para a primeira dobra da pagina, e so ele pode passar de 36 px.


Gramática editorial:

- Afirmação e explicação podem compartilhar tamanho, entrelinha, tracking e peso.
- A afirmação usa `--color-text-primary`.
- A explicação usa `--color-text-secondary`.
- Uma expressão curta pode usar `--color-primary`.
- A medida fica entre 45 e 75 caracteres por linha no desktop e entre 35 e 60 em telas menores.
- Use `text-wrap: balance` em títulos e `text-wrap: pretty` em telas pequenas.

## Espaçamento e layout

```yaml
space:
  "--space-1": 4px
  "--space-2": 8px
  "--space-3": 12px
  "--space-4": 16px
  "--space-5": 24px
  "--space-6": 32px
  "--space-7": 48px
  "--space-8": 64px
  "--space-9": 96px
  "--space-10": 128px
content:
  "--content-max": 1208px
  "--content-gutter":
    default: 16px
    min_width_768px: 24px
    min_width_1280px: 32px
fold:
  desktop_minimum_vertical_space: 96px
  compact_minimum_vertical_space: 64px
```

Regras:

- Use um único rail por dobra.
- Não aninhe outro rail dentro do primeiro.
- Em split, reserve 37 por cento para texto e 63 por cento para visual.
- A mídia dominante ocupa 55 a 70% da largura útil.
- A página não pode criar rolagem horizontal em 320 px.

## Raios e elevação

| Token | Valor | Uso |
| --- | --- | --- |
| `--radius-control` | `8px` | Inputs, botões compactos e chips |
| `--radius-card` | `12px` | Cards densos e itens aninhados |
| `--radius-card-lg` | `16px` | Cards editoriais |
| `--radius-panel` | `24px` | Painéis, mídia e contextos de tema |
| `--radius-pill` | `9999px` | Ações principais, filtros e estados |

Um elemento aninhado nunca usa raio maior que o contêiner pai.

```yaml
shadow_light:
  "--shadow-1": "0 1px 2px rgba(32,21,37,0.06), 0 8px 24px rgba(32,21,37,0.06)"
  "--shadow-2": "0 2px 6px rgba(32,21,37,0.08), 0 20px 48px rgba(32,21,37,0.1)"
  "--shadow-3": "0 4px 12px rgba(32,21,37,0.1), 0 32px 80px rgba(32,21,37,0.14)"
shadow_dark:
  "--shadow-1": "0 1px 2px rgba(0,0,0,0.28), 0 10px 28px rgba(0,0,0,0.2)"
  "--shadow-2": "0 2px 8px rgba(0,0,0,0.36), 0 24px 56px rgba(0,0,0,0.28)"
  "--shadow-3": "0 6px 18px rgba(0,0,0,0.42), 0 36px 88px rgba(0,0,0,0.34)"
```

## Movimento e foco

| Token | Valor | Uso |
| --- | --- | --- |
| `--duration-fast` | `160ms` | Hover, press e foco |
| `--duration-base` | `240ms` | Trocas de estado e conteúdo |
| `--duration-slow` | `360ms` | Entrada de painel e mudança de contexto |
| `--ease-standard` | `cubic-bezier(0.2, 0.8, 0.2, 1)` | Entrada e resposta |
| `--ease-exit` | `cubic-bezier(0.4, 0, 1, 1)` | Saída curta |

Anime somente `transform` e `opacity`. Hover altera cor, borda ou sombra sem deslocar o componente. Press usa escala mínima de `0.98`. Entrada usa no máximo 16 px de deslocamento. `prefers-reduced-motion: reduce` remove movimento não essencial.

Token `--focus-ring`. Valor exato:

```css
box-shadow: 0 0 0 2px var(--color-focus-offset), 0 0 0 4px var(--color-focus);
```

Use em `:focus-visible`. Nunca remova o foco visível.

## Contratos de componentes

### Button

Arquivo: `app/src/components/design-system/Button.astro`.

```yaml
props:
  as: [a, button]
  href: string_optional
  variant: [primary, secondary, ghost]
  size: [sm, md, lg]
  type: [button, submit, reset]
  disabled: boolean
  loading: boolean
  class: string_optional
defaults:
  variant: primary
  size: md
  type: button
minimum_heights:
  sm: 44px
  md: 48px
  lg: 56px
```

Primary é a ação principal. Secondary é a alternativa visível. Ghost é a ação de menor peso. Todos os estados incluem repouso, hover, active, focus-visible, disabled e loading. Hover nunca desloca o controle. Rótulo e ícone permanecem na mesma linha.

### EditorialStatement

Arquivo: `app/src/components/design-system/EditorialStatement.astro`.

```yaml
props:
  as: [h1, h2, h3]
  eyebrow: string_optional
  title: string_required
  accent: string_optional
  explanation: string_required
  align: [start, center]
  size: [editorial, heading]
  class: string_optional
defaults:
  as: h2
  align: start
  size: editorial
```

Título, acento e explicação compartilham a escala. A hierarquia vem da cor.

### Surface

Arquivo: `app/src/components/design-system/Surface.astro`.

```yaml
props:
  as: [article, div, li, aside]
  tone: [base, subtle, raised]
  padding: [sm, md, lg]
  radius: [card, large]
  theme: [inherit, light, dark]
  class: string_optional
defaults:
  as: article
  tone: base
  padding: md
  radius: large
  theme: inherit
slots: [default, header, footer]
```

### MediaPanel

Arquivo: `app/src/components/design-system/MediaPanel.astro`.

```yaml
props:
  label: string_required
  tone: [inherit, light, dark]
  ratio: [auto, wide, standard]
  caption: string_optional
  padding: [none, sm, md]
  class: string_optional
defaults:
  tone: inherit
  ratio: auto
  padding: md
```

O painel usa raio de 24 px no desktop e 16 px no mobile. Use `Surface theme="light"` para preservar uma interface clara dentro de mídia escura.

### Fold

Arquivo: `app/src/components/design-system/Fold.astro`.

```yaml
props:
  id: string_optional
  tone: [light, neutral, dark-contained, dark-full]
  layout: [split, stacked]
  visualSide: [start, end]
  class: string_optional
defaults:
  tone: light
  layout: split
  visualSide: end
slots_required: [copy, visual]
```

Tons:

- `light`: superfície branca e estado principal.
- `neutral`: canvas claro para separar capítulos.
- `dark-contained`: painel escuro arredondado dentro da página clara.
- `dark-full`: contexto escuro de largura integral para mudança narrativa real.

Nunca coloque duas dobras `dark-full` em sequência.

## Guia de composição

### Matriz de decisão

| Situação | Tom | Regra |
| --- | --- | --- |
| Conteúdo, produto ou navegação | `light` ou `neutral` | Use como padrão |
| Visualização densa ou prova local | `dark-contained` | Escureça somente o painel. Preserve interface interna clara e ícones claros |
| Mudança real de contexto narrativo | `dark-full` | Use uma única vez e retorne ao claro na dobra seguinte |

### Três receitas

```yaml
all_light:
  sequence: [light, light, neutral]
  use_for: leitura, comparação, fluxos longos
mixed:
  sequence: [light, dark-full, light]
  use_for: prova operacional decisiva
contained_focus:
  sequence: [light, dark-contained, neutral]
  use_for: mídia que precisa de contraste local
```

Continuidade entre claro e escuro:

- Preserve o mesmo rail e o mesmo alinhamento.
- Use pelo menos 96 px de respiro no desktop.
- Faça um motivo visual atravessar a transição, como painel, trilho, moldura ou visualização.
- Retorne ao claro depois de uma dobra escura integral.

### Faça

- Use uma mídia dominante por dobra.
- Mantenha título e explicação na mesma escala.
- Limite o violeta a dois papéis saturados por viewport.
- Mantenha densidade alta dentro da visualização principal.
- Use ícones claros em fundos escuros.

### Evite

- Não use duas dobras escuras integrais em sequência.
- Não use amarelo como decoração.
- Não troque uma prova por uma grade de cards equivalentes.
- Não use mais de uma ação primária por dobra.
- Não deixe ícones de baixo contraste desaparecerem no fundo.

## Sistema de ícones

Família: SpotIcon. Total: 49 ícones.

```yaml
view_box: "0 0 64 64"
stroke_width: 1.5
optical_box: 46
optical_center: [32, 32]
minimum_review_size: 26px
dark_component: app/src/components/SpotIcon.astro
light_component: app/src/components/SpotIconLight.astro
geometry_directory: app/src/components/icons/spot
measure_command: npm run icons:measure
export_command: npm run icons:export
dark_download_base: https://optidata.cloud/design/icons/
light_download_base: https://optidata.cloud/design/icons/light/
file_extension: .svg
```

O componente `SpotIcon` usa tinta clara sobre fundos escuros. O componente `SpotIconLight` usa violeta e neutros escuros sobre fundos claros. Ambos reutilizam exatamente os mesmos 49 desenhos.

Nomes válidos:

```yaml
icons:
  - compute
  - storage
  - gpu
  - inference
  - private-cloud
  - self-serve
  - price
  - speed
  - support
  - security
  - regions
  - sla
  - account
  - configure
  - deploy
  - workspace
  - object-storage
  - backup
  - snapshots
  - vpc
  - load-balancer
  - ip
  - security-groups
  - dns
  - kubernetes
  - database
  - bare-metal
  - owned-stack
  - no-lock-in
  - migration
  - anti-ddos
  - waf
  - pentest
  - vulnerability-scan
  - soc
  - zero-trust
  - iso-27001
  - erp
  - bandwidth
  - console-view
  - scale
  - access-key
  - restore
  - failover
  - schedule
  - article
  - video
  - mig
  - root-access
```

Para obter um arquivo escuro, concatene `dark_download_base`, o nome e `.svg`. Exemplo: [compute escuro](https://optidata.cloud/design/icons/compute.svg).

Para obter um arquivo claro, concatene `light_download_base`, o nome e `.svg`. Exemplo: [compute claro](https://optidata.cloud/design/icons/light/compute.svg).

Regras da família:

1. Não redesenhe silhuetas existentes.
2. Declare o traço somente no SVG raiz.
3. Use uma forma essencial clara ou violeta por ícone. Demais formas ficam nos níveis neutros.
4. Cores semânticas aparecem apenas quando codificam um estado real.
5. Mantenha pelo menos um traço de distância entre formas separadas.
6. Preserve marcas de terceiros sem efeitos, gradientes ou alteração de silhueta.
7. SVG decorativo usa `aria-hidden="true"` e `focusable="false"`.
8. O nome acessível de um controle com ícone fica no controle, não dentro do SVG.

## Acessibilidade

```yaml
minimum_text_contrast: "4.5:1"
minimum_graphic_contrast: "3:1"
minimum_interactive_target: "44x44 CSS px"
focus_visible: required
reduced_motion: required
decorative_svg:
  aria_hidden: true
  focusable: false
```

Texto, ícone, borda e foco precisam ser medidos sobre o fundo real em que aparecem. Uma cor aprovada em branco não é automaticamente aprovada em um painel escuro.

## Links oficiais

- Página humana: [Optidata Design System](https://optidata.cloud/optidata-design-system)
- Este contrato: [design.md](https://optidata.cloud/design.md)
- Logos: [diretório público](https://optidata.cloud/design/logos/optidata-logo.svg)
- Ícones para fundo escuro: [compute.svg](https://optidata.cloud/design/icons/compute.svg)
- Ícones para fundo claro: [compute.svg](https://optidata.cloud/design/icons/light/compute.svg)

Optidata, 2026. Os logos da Optidata são marcas da Optidata. Marcas de terceiros pertencem aos seus respectivos titulares.
