Pular para o conteúdo
Versão 1.1

O Design System da SiteIncrível

Tokens, componentes e padrões em CSS puro. Uma folha de estilo, sem build no consumidor, sem framework — funciona igual num site em Astro e numa tela em PHP.

Marca

O símbolo é o raio dentro do anel. Ele é vetorial e vive em src/logo/ — nunca reconstrua a marca a partir de um PNG.

Símbolo da SiteIncrível Símbolo em versão selo
A versão monocromática precisa ser inlinada Ela pinta com currentColor, e um SVG carregado por <img src> é um documento isolado: não herda a cor da página. Cole o conteúdo do arquivo direto no HTML (ou use um componente que faça isso) — pela tag <img> ela sai sempre preta.
ArquivoQuando usar
si-mark.svgPadrão. Fundo claro, disco branco próprio.
si-mark-badge.svgAvatar, favicon, perfil de rede social — onde a marca precisa do próprio fundo indigo.
si-mark-mono.svgUma cor só, herdada por currentColor. Fundo escuro, carimbo, fax.
Área de proteção Deixe em volta do símbolo, livre de qualquer elemento, uma margem igual a 12% da largura dele. Tamanho mínimo: 24px de lado em tela, 8mm em impresso.
O que não fazer com a marca Não recolorir fora da paleta, não distorcer a proporção, não aplicar sombra ou contorno, não girar, não separar o raio do anel, não usar a versão colorida sobre fundo escuro (existe a monocromática para isso).

Lockup horizontal

A assinatura com o nome não é um arquivo — é composição, para o texto continuar sendo texto (selecionável, traduzível, legível por leitor de tela).

SiteIncrível®
HTML
<a class="si-cluster" href="/" style="--si-gap: 12px">
  <img src="/si-mark.svg" alt="" width="40" height="40">
  <strong>SiteIncrível<sup>®</sup></strong>
</a>
Grafia Sempre SiteIncrível, com acento e as duas maiúsculas. Nunca "Site Incrível" separado, nunca "siteincrivel" em texto corrido — isso é domínio, não marca. O ® aparece na primeira ocorrência de cada página e no rodapé.

Cores e contraste

As duas cores da marca saíram do símbolo. As razões de contraste abaixo são calculadas no build a partir do 00-tokens.css — se um par cair abaixo do mínimo WCAG, o build quebra.

Marca

Aa texto branco
--si-color-primary
Valor
#3A59AE
vs branco
6.52:1 · AA
Indigo do símbolo. Serve como texto sobre branco e como fundo de texto branco.
Aa texto branco
--si-color-primary-dark
Valor
#2B438A
vs branco
9.24:1 · AAA
Hover do botão de marca, faixas escuras.
Aa texto branco
--si-color-accent
Valor
#0179CE
vs branco
4.54:1 · AA
Azul do raio. Preenchimento: fundo de botão, ícone grande, faixa.
Aa texto branco
--si-color-accent-ink
Valor
#01599F
vs branco
7.17:1 · AAA
Texto e link. É a cor azul que se lê, não a de cima.
Aa indigo escuro
--si-color-highlight
Valor
#B8DBF5
vs indigo
8.47:1 · AAA
Só superfície e detalhe. Nunca cor de texto.
Aa sobre a marca
--si-color-on-brand
Valor
#DDE5F7
vs indigo claro
5.16:1 · AA
vs indigo escuro
9.71:1 · AAA
Texto sobre .si-surface-brand. Medido contra o ponto mais claro do gradiente — é lá que o contraste aperta.
Texto sobre a faixa indigo mede-se no ponto mais claro O --si-gradient-deep vai de #1E3268 a #3A59AE. Uma cor de texto conferida só contra o escuro passa no rodapé e reprova no topo do hero — é assim que --si-color-highlight (4.50:1 · reprovado sobre o indigo claro) deixa de servir para texto. Use --si-color-on-brand.
A regra que mais se erra: accent não é cor de texto --si-color-accent mede 4.54:1 · AA sobre branco: passa AA para texto normal por uma margem de 0,04 e reprova em AAA. Link, label e texto pequeno usam --si-color-accent-ink (7.17:1 · AAA). O accent fica para fundo de botão, onde é o branco por cima que precisa contrastar.

Neutros

--si-color-ink
Valor
#111827
vs branco
17.74:1 · AAA
Texto principal, títulos.
--si-color-ink-soft
Valor
#374151
vs branco
10.31:1 · AAA
Corpo de texto secundário.
--si-color-muted
Valor
#5B6472
vs branco
5.98:1 · AA
Apoio, legenda, placeholder. Ainda passa AA.
--si-color-surface-alt
Valor
#F6F8FC
Fundo de seção alternada.
--si-color-line
Valor
#E3E8EF
Bordas e divisores.

Feedback

--si-color-success
vs branco
5.39:1 · AA
--si-color-warning
vs branco
5.38:1 · AA
Âmbar escuro de propósito: o âmbar claro reprova em texto.
--si-color-danger
vs branco
5.57:1 · AA

Tipografia

Lexend, escala 1.200. Os dois maiores tamanhos usam clamp() e encolhem sozinhos no celular — não existe media query de tipografia.

--si-text-4xlGestão pública digital
--si-text-3xlTítulo de seção
--si-text-2xlSubtítulo
--si-text-xlTítulo de card
--si-text-lgParágrafo de abertura
--si-text-mdCorpo de texto padrão
--si-text-smApoio, label, legenda
--si-text-xsBadge, nota de rodapé
Medida de leitura Parágrafo longo fica em no máximo 68 caracteres por linha — a classe .si-measure faz isso. Acima disso o olho perde a linha ao voltar.
CSS dos títulos
h1 {
  margin: 0;
}

h1 {
  font-weight: var(--si-weight-bold);
  line-height: var(--si-leading-tight);
  letter-spacing: var(--si-tracking-tight);
  color: var(--si-color-ink);
  text-wrap: balance;
}

h1 {
  font-size: var(--si-text-4xl);
}

h2 {
  margin: 0;
}

h2 {
  font-weight: var(--si-weight-bold);
  line-height: var(--si-leading-tight);
  letter-spacing: var(--si-tracking-tight);
  color: var(--si-color-ink);
  text-wrap: balance;
}

h2 {
  font-size: var(--si-text-3xl);
}

h3 {
  margin: 0;
}

h3 {
  font-weight: var(--si-weight-bold);
  line-height: var(--si-leading-tight);
  letter-spacing: var(--si-tracking-tight);
  color: var(--si-color-ink);
  text-wrap: balance;
}

h3 {
  font-size: var(--si-text-2xl);
}

a {
  color: var(--si-color-accent-ink);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
  transition: color var(--si-dur-fast) var(--si-ease);
}

a:hover {
  color: var(--si-color-primary);
}

Espaçamento

Base de 4px. O número no token é o multiplicador: --si-space-4 é 4×4=16px.

--si-space-14px
--si-space-28px
--si-space-312px
--si-space-416px — respiro padrão dentro de componente
--si-space-624px — padding de card
--si-space-832px
--si-space-1248px
--si-space-1664px — entre seções no mobile
--si-space-2496px — entre seções no desktop

Raio e sombra

--si-radius-sm · 6px
badge, tag
--si-radius-md · 10px
botão, input
--si-radius-lg · 16px
card, painel
--si-radius-xl · 24px
bloco de destaque
--si-shadow-sm
separação sutil
--si-shadow-md
card elevado
--si-shadow-lg
hover, painel flutuante
As sombras são tingidas de indigo Não é preto com opacidade: é rgba(30,50,104,…). Preto puro sobre uma paleta azul suja a cor e deixa a interface com aparência de fotocópia.

Grid e breakpoints

Quatro primitivas cobrem toda a composição. Nenhuma delas define cor.

.si-grid

Colunas que se reorganizam sozinhas. Você controla a largura mínima da coluna pela variável --si-grid-min; não há media query.

Um
Dois
Três
Quatro
CSS
.si-grid {
  display: grid;
  gap: var(--si-space-6);
  grid-template-columns: repeat(auto-fit, minmax(min(var(--si-grid-min, 260px), 100%), 1fr));
}

.si-stack {
  display: flex;
  flex-direction: column;
  gap: var(--si-gap, var(--si-space-4));
}

.si-cluster {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--si-gap, var(--si-space-3));
}

.si-container {
  width: 100%;
  max-width: var(--si-container);
  margin-inline: auto;
  padding-inline: var(--si-container-pad);
}

.si-section {
  padding-block: var(--si-space-16);
}

@media (min-width: 900px) {
  .si-section {
    padding-block: var(--si-space-24);
  }
}
BreakpointValorO que muda
sm640pxduas colunas em grades densas
md900pxmenu vira horizontal, painel de nav passa a flutuar, seções ganham respiro
lg1200pxlargura máxima do container
Breakpoint não é token @media não lê var(). Os três números acima aparecem crus no CSS, e é por isso que estão documentados aqui: esta tabela é a fonte de verdade deles.

Botão

Funciona igual em <button> e <a>. Altura mínima de 44px em todas as variantes — é o alvo de toque do WCAG 2.5.8.

HTML
<button class="si-btn si-btn--primary">Falar com especialista</button>
<a class="si-btn si-btn--outline" href="/solucoes">Ver soluções</a>
<button class="si-btn si-btn--primary si-btn--lg si-btn--block">Ocupa a linha</button>
CSS
.si-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--si-space-2);
  min-height: 44px;
  padding: var(--si-space-3) var(--si-space-5);
  border: 1px solid transparent;
  border-radius: var(--si-radius-md);
  font-size: var(--si-text-md);
  font-weight: var(--si-weight-semibold);
  line-height: 1.2;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  transition: background-color var(--si-dur) var(--si-ease),
              border-color var(--si-dur) var(--si-ease),
              color var(--si-dur) var(--si-ease),
              box-shadow var(--si-dur) var(--si-ease),
              transform var(--si-dur-fast) var(--si-ease);
}

.si-btn:focus-visible {
  outline: none;
  box-shadow: var(--si-focus-ring);
}

.si-btn--primary {
  background: var(--si-color-accent);
  color: #FFFFFF;
}

.si-btn--primary:hover {
  background: var(--si-color-accent-ink);
  color: #FFFFFF;
}

.si-btn--outline {
  background: transparent;
  border-color: var(--si-color-line-strong);
  color: var(--si-color-accent-ink);
}

.si-btn--outline:hover {
  border-color: var(--si-color-accent-ink);
  background: var(--si-color-accent-soft);
  color: var(--si-color-accent-ink);
}

.si-btn--invert {
  background: #FFFFFF;
  color: var(--si-color-primary);
}

.si-btn--outline-invert {
  background: transparent;
  border-color: var(--si-color-on-brand-line);
  color: #FFFFFF;
}

.si-btn--lg {
  min-height: 52px;
  padding: var(--si-space-4) var(--si-space-8);
  font-size: var(--si-text-lg);
}
VarianteQuando usarQuantas por tela
--primaryA ação que a página quer que aconteçauma por bloco
--brandAção principal em contexto institucional (indigo em vez de azul)uma por bloco
--outlineAlternativa legítima à ação principalà vontade
--ghostAção terciária, dentro de tabela ou toolbarà vontade
--invertSobre fundo escuro ou faixa de marcauma por faixa
--outline-invertO secundário do --invert, na mesma faixa escuraà vontade
Acessibilidade O anel de foco é duplo (branco por dentro, azul por fora) para aparecer tanto sobre branco quanto sobre a faixa indigo. Nunca troque por outline:none. Botão que só tem ícone precisa de aria-label.

Card

Superfície de conteúdo. --interactive faz o card inteiro responder ao clique, mas quem recebe o foco continua sendo o link de dentro — card não vira botão.

Meio Ambiente

Licenciamento, fiscalização e denúncias ambientais num fluxo só, do protocolo ao parecer.

Card elevado

Sem borda, com sombra. Use sobre fundo alternado.

HTML
<article class="si-card si-card--interactive">
  <div class="si-card__body">
    <span class="si-card__icon" aria-hidden="true"><svg …></svg></span>
    <h3 class="si-card__title"><a href="/solucoes/meio-ambiente">Meio Ambiente</a></h3>
    <p class="si-card__text">Licenciamento, fiscalização e denúncias…</p>
  </div>
</article>
CSS
.si-card {
  display: flex;
  flex-direction: column;
  background: var(--si-color-surface);
  border: 1px solid var(--si-color-line);
  border-radius: var(--si-radius-lg);
  overflow: hidden;
}

.si-card__body {
  display: flex;
  flex-direction: column;
  gap: var(--si-space-3);
  padding: var(--si-space-6);
  flex: 1;
}

.si-card__icon {
  display: grid;
  place-items: center;
  width: 48px;
  height: 48px;
  border-radius: var(--si-radius-md);
  background: var(--si-color-accent-soft);
  color: var(--si-color-accent-ink);
  margin-bottom: var(--si-space-1);
}

.si-card__title {
  font-size: var(--si-text-xl);
  margin: 0;
}

.si-card--interactive {
  position: relative;
  transition: border-color var(--si-dur) var(--si-ease),
              box-shadow var(--si-dur) var(--si-ease),
              transform var(--si-dur) var(--si-ease);
}

.si-card--interactive:hover {
  border-color: var(--si-color-accent);
  box-shadow: var(--si-shadow-lg);
  transform: translateY(-2px);
}

.si-card--interactive:focus-within {
  box-shadow: var(--si-focus-ring);
}
Por que o link estica em vez do card virar <a> Envolver o card inteiro num <a> faz o leitor de tela anunciar todo o conteúdo como um único rótulo gigante. O ::after no título mantém o alvo de clique grande e o rótulo do link curto.

Badge

Rótulo curto, nunca clicável. Se precisar clicar, é .si-btn--sm.

Padrão Prefeitura Novo Ativo Pendente Vencido Contorno Pílula
Dentro de um card O badge acompanha o texto, não a largura da coluna. Prefeituras
CSS
.si-badge {
  display: inline-flex;
  align-items: center;
  gap: var(--si-space-1);
  padding: 3px var(--si-space-2);
  border-radius: var(--si-radius-sm);
  font-size: var(--si-text-xs);
  font-weight: var(--si-weight-semibold);
  line-height: 1.5;
  white-space: nowrap;
  background: var(--si-color-surface-sunken);
  color: var(--si-color-ink-soft);
  width: fit-content;
}

.si-badge--accent {
  background: var(--si-color-accent-soft);
  color: var(--si-color-accent-ink);
}

.si-badge--pill {
  border-radius: var(--si-radius-full);
  padding-inline: var(--si-space-3);
}

.si-badge--eyebrow {
  background: transparent;
  color: var(--si-color-accent-ink);
  padding: 0;
  text-transform: uppercase;
  letter-spacing: var(--si-tracking-wide);
}
Badge dentro de card não estica Ele traz width: fit-content porque num container flex em coluna — como o .si-card__body — o item esticaria para a linha inteira, e inline-flex não protege disso: quem decide o tamanho do item é o container. Note que não é align-self: flex-start: isso impediria o esticão mas também sequestraria o alinhamento do pai, e um --eyebrow dentro de um cabeçalho centralizado iria parar na esquerda.
Cor não é informação Badge verde e badge vermelho parecem iguais para 1 em cada 12 homens. O texto dentro é que comunica o estado — nunca use um badge sem palavra.

Formulário

Todo campo tem <label> real ligado por for/id. Placeholder não substitui rótulo: some quando a pessoa começa a digitar.

Ajuda a direcionar seu contato para a pessoa certa.
Informe um e-mail completo, com domínio.
HTML de um campo com erro
<div class="si-field">
  <label class="si-field__label" for="email" data-required>E-mail</label>
  <input class="si-input" id="email" type="email"
         aria-invalid="true" aria-describedby="email-erro">
  <span class="si-field__error" id="email-erro">Informe um e-mail completo.</span>
</div>
CSS
.si-field {
  display: flex;
  flex-direction: column;
  gap: var(--si-space-2);
}

.si-field__label {
  font-size: var(--si-text-sm);
  font-weight: var(--si-weight-medium);
  color: var(--si-color-ink);
}

.si-input {
  width: 100%;
  min-height: 44px;
  padding: var(--si-space-3) var(--si-space-4);
  border: 1px solid var(--si-color-line-strong);
  border-radius: var(--si-radius-md);
  background: var(--si-color-surface);
  color: var(--si-color-ink);
  font-size: var(--si-text-md);
  transition: border-color var(--si-dur-fast) var(--si-ease),
              box-shadow var(--si-dur-fast) var(--si-ease);
}

.si-select {
  width: 100%;
  min-height: 44px;
  padding: var(--si-space-3) var(--si-space-4);
  border: 1px solid var(--si-color-line-strong);
  border-radius: var(--si-radius-md);
  background: var(--si-color-surface);
  color: var(--si-color-ink);
  font-size: var(--si-text-md);
  transition: border-color var(--si-dur-fast) var(--si-ease),
              box-shadow var(--si-dur-fast) var(--si-ease);
}

.si-select {
  appearance: none;
  padding-right: var(--si-space-10);
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
                    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: calc(100% - 22px) calc(50% + 2px), calc(100% - 16px) calc(50% + 2px);
  background-size: 6px 6px, 6px 6px;
  background-repeat: no-repeat;
}

.si-textarea {
  width: 100%;
  min-height: 44px;
  padding: var(--si-space-3) var(--si-space-4);
  border: 1px solid var(--si-color-line-strong);
  border-radius: var(--si-radius-md);
  background: var(--si-color-surface);
  color: var(--si-color-ink);
  font-size: var(--si-text-md);
  transition: border-color var(--si-dur-fast) var(--si-ease),
              box-shadow var(--si-dur-fast) var(--si-ease);
}

.si-textarea {
  min-height: 120px;
  resize: vertical;
  line-height: var(--si-leading-normal);
}

.si-field__error {
  display: flex;
  align-items: flex-start;
  gap: var(--si-space-1);
  font-size: var(--si-text-sm);
  font-weight: var(--si-weight-medium);
  color: var(--si-color-danger);
}

.si-check {
  display: flex;
  align-items: flex-start;
  gap: var(--si-space-3);
  cursor: pointer;
  font-size: var(--si-text-sm);
  line-height: var(--si-leading-snug);
}
Erro nunca é só a borda vermelha Precisa de três coisas juntas: aria-invalid="true" no controle, aria-describedby apontando para a mensagem, e a mensagem em texto. Borda vermelha sozinha reprova no WCAG 1.4.1 — quem não distingue a cor não fica sabendo de nada.

Alerta

Implantação em duas semanas O prazo conta a partir da assinatura, incluindo migração de dados e treinamento.
Solicitação enviada. Respondemos em até 1 dia útil.
Este módulo depende de integração com o sistema de protocolo do órgão.
CSS
.si-alert {
  display: flex;
  gap: var(--si-space-3);
  padding: var(--si-space-4) var(--si-space-5);
  border-radius: var(--si-radius-md);
  border-left: 3px solid var(--si-color-line-strong);
  background: var(--si-color-surface-alt);
  color: var(--si-color-ink-soft);
  font-size: var(--si-text-sm);
  line-height: var(--si-leading-snug);
}

.si-alert__title {
  font-weight: var(--si-weight-semibold);
  color: var(--si-color-ink);
}

.si-alert--info {
  border-left-color: var(--si-color-info);
  background: var(--si-color-info-soft);
  color: var(--si-color-accent-ink);
}

.si-alert--success {
  border-left-color: var(--si-color-success);
  background: var(--si-color-success-soft);
  color: var(--si-color-success);
}

.si-alert--warning {
  border-left-color: var(--si-color-warning);
  background: var(--si-color-warning-soft);
  color: var(--si-color-warning);
}

.si-alert--danger {
  border-left-color: var(--si-color-danger);
  background: var(--si-color-danger-soft);
  color: var(--si-color-danger);
}
role no HTML, não no CSS Use role="status" para informação e sucesso (anuncia sem interromper) e role="alert" só para erro (interrompe o leitor de tela). A cor do alerta não diz nada a quem usa leitor.

Texto longo

.si-prose é o envelope para conteúdo vindo de CMS ou markdown, onde não dá para pôr classe em cada elemento. Escopo fechado: só afeta os filhos.

Desde 2013 desenvolvemos software de gestão para o setor público brasileiro.

Atendemos prefeituras, câmaras municipais e hospitais com sistemas que nascem da rotina de quem opera o serviço, não de um catálogo genérico.

Como trabalhamos

  • Implantação acompanhada, com migração dos dados existentes
  • Treinamento das equipes que vão operar o sistema
  • Suporte contínuo durante todo o contrato
O sistema precisa caber na rotina do servidor, não o contrário.
CSS
.si-prose {
  max-width: 68ch;
  color: var(--si-color-ink-soft);
}

.si-prose__lead {
  font-size: var(--si-text-lg);
  color: var(--si-color-ink);
  line-height: var(--si-leading-snug);
}

.si-prose blockquote {
  border-left: 3px solid var(--si-color-accent);
  padding-left: var(--si-space-5);
  color: var(--si-color-ink);
  font-size: var(--si-text-lg);
}

Utilitários

O conjunto mínimo — só o que um componente não expressa sozinho. Isto não é um framework utilitário e não vai virar um.

ClasseO que faz
.si-visually-hiddenSome da tela, continua no leitor de tela. Para rótulos que a interface comunica visualmente.
.si-skip-link"Pular para o conteúdo". Invisível até receber foco pelo teclado. Primeiro elemento do <body>.
.si-measureLimita a 68 caracteres por linha.
.si-leadParágrafo de abertura, maior e em cinza.
.si-surface-alt / .si-surface-brandFundo de seção alternada / faixa de marca com texto branco.
.si-hidden@sm / .si-hidden@lgEsconde abaixo de 900px / a partir de 900px.
CSS
.si-visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.si-skip-link {
  position: absolute;
  left: var(--si-space-4);
  top: -100px;
  z-index: var(--si-z-overlay);
  padding: var(--si-space-3) var(--si-space-5);
  background: var(--si-color-surface);
  border-radius: var(--si-radius-md);
  box-shadow: var(--si-shadow-lg);
  font-weight: var(--si-weight-semibold);
  transition: top var(--si-dur) var(--si-ease);
}

.si-skip-link:focus {
  top: var(--si-space-4);
}

.si-measure {
  max-width: 68ch;
}

.si-lead {
  font-size: var(--si-text-lg);
  color: var(--si-color-muted);
  line-height: var(--si-leading-snug);
}

Padrões

Composições recorrentes do site institucional. Não são componentes novos: são arranjos das classes acima. Se você precisar de um padrão que não está aqui, monte-o com o que existe antes de escrever CSS.

Hero

Gestão pública

Software de gestão feito para quem atende o cidadão

Desde 2013 atendendo prefeituras, câmaras municipais e hospitais.

HTML
<section class="si-surface-brand si-section">
  <div class="si-container">
    <div class="si-stack si-measure">
      <span class="si-badge si-badge--eyebrow">Gestão pública</span>
      <h1>Software de gestão feito para quem atende o cidadão</h1>
      <p class="si-lead">Desde 2013 atendendo prefeituras, câmaras e hospitais.</p>
      <div class="si-cluster">
        <a class="si-btn si-btn--invert si-btn--lg" href="…">Falar com especialista</a>
        <a class="si-btn si-btn--outline-invert si-btn--lg" href="…">Ver soluções</a>
      </div>
    </div>
  </div>
</section>

Grade de soluções

.si-grid com .si-card--interactive. Uma coluna no celular, duas no tablet, três ou quatro no desktop — sem media query.

Quiosques

Gestão e locação de áreas de lazer públicas.

Faixa de CTA

Vamos conversar sobre a gestão do seu município?

Falar no WhatsApp

Como consumir

Num projeto Node (Astro, Vite, Next)

package.json + import
// package.json — sempre travado numa tag
"dependencies": {
  "siteincrivel-ds": "github:kayquer/siteincrivel-design-system#v1.0.0"
}

// no layout base, uma vez só
import 'siteincrivel-ds/css';

Num sistema PHP ou HTML estático

Baixar e linkar
# no deploy DAQUELE projeto, travado na mesma tag
curl -L -o assets/siteincrivel.min.css \
  https://raw.githubusercontent.com/kayquer/siteincrivel-design-system/v1.0.0/dist/siteincrivel.min.css
HTML
<link rel="stylesheet" href="/assets/siteincrivel.min.css">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet"
      href="https://fonts.googleapis.com/css2?family=Lexend:wght@400;500;600;700&display=swap">
A fonte não vem no CSS O Design System declara --si-font-sans: "Lexend", system-ui, … mas não carrega a Lexend. Quem consome decide: Google Fonts, self-host ou nada — sem a Lexend o fallback de sistema assume e nada quebra.

Regras da casa

Nunca edite o dist/ dist/siteincrivel.css é gerado. O CI roda git diff --exit-code dist/ depois do build: qualquer edição manual derruba o pipeline. Mexa no src/css/.
Nunca copie o CSS para dentro de outro projeto Duas cópias editáveis com um humano no meio é como uma produção acaba meses à frente do repositório. Consuma pela tag; se precisa de mudança, ela vem para cá.
Nenhum hex fora do 00-tokens.css Precisou de uma cor que não existe? Ela vira token aqui, com o contraste conferido. O npm run lint:tokens falha se um hex aparecer solto num componente — e o site consumidor tem o mesmo grep no CI dele.
Não reestilize um componente do DS de fora Se o .si-card precisa variar num projeto, ele ganha um modificador --variant aqui. Sobrescrever de fora quebra em silêncio na próxima versão e o próximo consumidor não herda a correção.
Esta página é gerada Os blocos de CSS e as razões de contraste saem do src/css/ no npm run docs. Não os escreva à mão: npm run docs:check compara e falha. Documentação que diverge do código é pior que documentação nenhuma.

Comandos

ComandoO que faz
npm run buildConcatena src/css/ em dist/. Falha se dois arquivos tiverem o mesmo prefixo numérico.
npm run docsPreenche esta página a partir do CSS real.
npm run docs:checkSó confere, não escreve. É o gate do CI.
npm run lint:tokensProcura hex cru fora do 00-tokens.css.
npm run checkOs três acima + git diff --exit-code dist/. Rode antes de abrir PR.
npm run devRebuild automático a cada save no src/.

Como adicionar um componente

  1. Crie src/css/NN-nome.css com um prefixo numérico livre — a posição define a cascata.
  2. Escreva em BEM com prefixo si-: .si-nome, .si-nome__parte, .si-nome--variante.
  3. Use só var(--si-*). Faltou um token? Crie no 00-tokens.css com o comentário de uso.
  4. Adicione a seção aqui no index.html, com o exemplo vivo e um <code data-ds-css="…"> vazio.
  5. npm run check. Se o seletor não existir, o build avisa.