cis-style · hub

kit v9 · f417275 · base/tokens.css

Tokens del design system

Todo color, tamaño, espacio, radio y tiempo de los sitios del grupo sale de una variable CSS declarada en base/tokens.css. Esta página lista los 47 tokens del archivo real, con su valor en tema claro, su valor en tema oscuro cuando cambia, para qué sirve cada uno y cómo se usa en código. Los swatches son vivos: pintan con la variable, no con el hex.

Regla cero: nunca un hex a mano en un sitio del grupo. Si necesitas un color que el kit no da, el diseño está mal planteado, no el kit.

Cómo cargar los tokens

Los tokens llegan con la hoja base/tokens.css del CDN del grupo, siempre por digest inmutable. La marca se aplica al final con brands/<marca>/tokens.css, que solo re-tiñe el acento. El orden importa: fuentes, tokens base, chrome, componentes, marca.

kit v9 · seis hojas · un script
<link rel=stylesheet href=".../v9/<digest>/fonts/css/ibm-plex-sans.css">
<link rel=stylesheet href=".../v9/<digest>/fonts/css/jetbrains-mono.css">
<link rel=stylesheet href=".../v9/<digest>/base/tokens.css">
<link rel=stylesheet href=".../v9/<digest>/base/chrome.css">
<link rel=stylesheet href=".../v9/<digest>/base/components.css">
<link rel=stylesheet href=".../v9/<digest>/brands/cis/tokens.css">
<script src=".../v9/<digest>/chrome.js" defer></script>

Tinta y papel

Cinco neutros forman la base: tres tintas para texto y dos papeles para fondo. En tema claro ambos papeles son blancos y la jerarquía la hacen los bordes; en oscuro los papeles sí se separan.

TokenClaroOscuroPara qué sirveUso
--ink#0e1418#f3f1eaTexto principal, titulares, iconos.color:var(--ink)
--ink-muted#5b6672#a9a69dTexto secundario: descripciones, metadatos, labels.color:var(--ink-muted)
--ink-soft#a3acb5#6b6863Texto terciario: placeholders, pies, notas al margen.color:var(--ink-soft)
--paper#ffffff#0a0a0aFondo de página.background:var(--paper)
--paper-raised#ffffff#111110Fondo de superficies elevadas: cards, nav, paneles.background:var(--paper-raised)
Titular en tinta plena
Descripción en tinta atenuada, para el cuerpo secundario.
Nota al pie en tinta suave.
<div style="border:1px solid var(--line);background:var(--paper-raised)">
  <div style="color:var(--ink)">Titular en tinta plena</div>
  <div style="color:var(--ink-muted)">Descripción en tinta atenuada</div>
  <div style="color:var(--ink-soft)">Nota al pie en tinta suave</div>
</div>

OJO · El comentario del archivo de marca menciona un papel crema #f6f5f1, pero el token desplegado declara #ffffff y la marca CIS no lo sobreescribe. Documenta y usa lo que declara el CSS vivo, no el comentario.

Líneas

El separador dominante de la casa es el borde de 1 píxel, no la sombra. Hay dos pesos: la línea normal para casi todo y la línea fuerte para reglas de énfasis, cabeceras de tabla y filetes editoriales.

TokenClaroOscuroPara qué sirveUso
--line#d4d1c9#2a2a27Borde estándar de cards, tablas, inputs y separadores.border:1px solid var(--line)
--line-strong#14181c#eaeae4Regla de énfasis: cabecera de tabla, filete de sección, botón ghost.border-bottom:1px solid var(--line-strong)
Separador estándar con --line
Regla de énfasis con --line-strong
<div style="border-bottom:1px solid var(--line)">Separador estándar</div>
<div style="border-bottom:1px solid var(--line-strong)">Regla de énfasis</div>

Acento y marca

El acento es el único color que cambia entre marcas: cada sitio carga brands/<marca>/tokens.css y esa hoja sobreescribe solo --accent y --accent-soft. En CIS el acento es dual por tema: navy en claro, verde claro en oscuro. El resto de la paleta no cambia nunca entre marcas.

TokenClaro (CIS)Oscuro (CIS)Para qué sirveUso
--accent#1e3a5f#7fc598Color de marca: links activos, hover de botón, énfasis en titulares, eyebrow.color:var(--accent)
--accent-soft#e7edf4#12261aFondo teñido de marca: chips, resaltados suaves, fondos de icono.background:var(--accent-soft)
eyebrow con acento

Énfasis en titulares por color, no cursiva

chip teñido
<span class=eyebrow>eyebrow con acento</span>
<h2>Énfasis en titulares <em>por color</em>, no cursiva</h2>
<span style="background:var(--accent-soft);color:var(--accent);
  border:1px solid var(--accent)">chip teñido</span>

NOTA · h1 em, h2 em, h3 em ya vienen mapeados a var(--accent) con font-style:normal desde la base: el énfasis de titular se marca con <em> y el kit pone el color.

Estado

Tres colores semánticos, iguales en claro y oscuro: el kit no los redefine en tema oscuro. El estado siempre va acompañado de texto, nunca es solo color.

TokenValor (ambos temas)Para qué sirveUso
--ok#0b7e59Éxito, en línea, verificado.color:var(--ok)
--warn#b45309Advertencia, degradado, pendiente.color:var(--warn)
--err#9a1b1bError, en falla, rechazado.color:var(--err)
en línea degradado en falla neutro
<span class="badge badge--ok">en línea</span>
<span class="badge badge--warn">degradado</span>
<span class="badge badge--err">en falla</span>
<span class="badge">neutro</span>

Superficie inversa

Para bloques oscuros dentro de una página clara (footers editoriales, franjas de cierre) existe una mini paleta propia. Así el bloque no depende del tema: se ve oscuro en claro y apenas más claro que el fondo en oscuro.

TokenClaroOscuroPara qué sirveUso
--surface-inverse#0c1116#17171aFondo del bloque inverso.background:var(--surface-inverse)
--on-inverse#c7cdd4#d4d0c5Texto corriente sobre superficie inversa.color:var(--on-inverse)
--on-inverse-strong#ffffff#ffffff (no cambia)Titulares y énfasis sobre superficie inversa.color:var(--on-inverse-strong)
Bloque inverso
Texto corriente en --on-inverse; el titular usa --on-inverse-strong. Nunca uses --ink aquí: en tema oscuro quedaría casi invisible.
<div style="background:var(--surface-inverse)">
  <div style="color:var(--on-inverse-strong)">Bloque inverso</div>
  <div style="color:var(--on-inverse)">Texto corriente</div>
</div>

Fuentes

Dos familias, self-hosted en /v9/<digest>/fonts/, nunca desde un CDN externo ni Google Fonts (CANON y ADR-021). La sans lleva la voz principal; la mono es la voz secundaria de la casa: eyebrows, labels, cifras, código.

TokenValorPara qué sirveUso
--font-sans"IBM Plex Sans", sans-serifTodo el texto de interfaz y prosa.font-family:var(--font-sans)
--font-mono"JetBrains Mono", monospaceEyebrows, labels uppercase, cifras, código, wordmark.font-family:var(--font-mono)
IBM Plex Sans lleva la prosa y la interfaz.
JetBrains Mono lleva cifras 0123456789 y etiquetas.
<p style="font-family:var(--font-sans)">IBM Plex Sans lleva la prosa.</p>
<p style="font-family:var(--font-mono)">JetBrains Mono lleva cifras.</p>

NOTA · El body de la base ya activa font-feature-settings: "ss01", "ss02", "tnum", "cv11": cifras tabulares y alternates de Plex vienen de fábrica.

Escala tipográfica

Siete pasos con nombre por función, no por tamaño. Los dos titulares son fluidos con clamp(); el resto es fijo. Cada token trae en el archivo su interlineado y tracking recomendados, anotados aquí.

TokenValorPara qué sirveUso
--fs-heroclamp(34px, 5vw, 60px)Titular hero de portada. Peso 800, lh .98, ls -.035em.font-size:var(--fs-hero)
--fs-sectionclamp(28px, 3.6vw, 44px)Título de sección. lh 1.05, ls -.025em.font-size:var(--fs-section)
--fs-prose15pxProsa larga. lh 1.6, max-width 68ch (clase .prose lo empaqueta).font-size:var(--fs-prose)
--fs-body14pxBase de interfaz, ya aplicada al body. lh 1.45.font-size:var(--fs-body)
--fs-small13.5pxLinks de nav, botones, texto secundario compacto.font-size:var(--fs-small)
--fs-micro11.5pxWordmark, eyebrows. Siempre mono uppercase.font-size:var(--fs-micro)
--fs-mono-label10.5pxh4 de footer, base legal, tags de card. Mono UPPERCASE.font-size:var(--fs-mono-label)
Hero
Título de sección

Prosa larga a 15 píxeles con interlineado 1.6 y ancho máximo de 68 caracteres, empaquetada en la clase .prose del kit.

Texto small para nav y botones.
micro · eyebrow
mono-label · base legal
<h1 style="font-size:var(--fs-hero);font-weight:800;line-height:.98">Hero</h1>
<h2 style="font-size:var(--fs-section);line-height:1.05">Título de sección</h2>
<p class=prose>Prosa larga...</p>
<small style="font-size:var(--fs-small)">Texto small</small>
<span style="font:var(--fs-micro) var(--font-mono);text-transform:uppercase;
  letter-spacing:var(--track-eyebrow)">micro · eyebrow</span>

Tracking mono

Tres anchos de tracking para la voz mono. A mayor tracking, más pequeño y más ceremonial el texto. Siempre con text-transform:uppercase.

TokenValorPara qué sirveUso
--track-eyebrow.18emEyebrows y kickers (la clase .eyebrow lo aplica).letter-spacing:var(--track-eyebrow)
--track-label.12emLabels de card, cabeceras de tabla, stats.letter-spacing:var(--track-label)
--track-legal.1emBase legal del footer, pies de página.letter-spacing:var(--track-legal)
eyebrow · .18em label · .12em legal · .1em
<span class=eyebrow>eyebrow</span>  <!-- ya trae --track-eyebrow -->
<span style="letter-spacing:var(--track-label)">label</span>
<span style="letter-spacing:var(--track-legal)">legal</span>

Espaciado

Escala de ocho pasos tomada de los sitios vivos. No es geométrica pura: crece de a 4 y luego de a 8. Úsala para padding, margin y gap; un espacio fuera de escala es un olor de maqueta.

--space-1 · 8px
--space-2 · 12px
--space-3 · 16px
--space-4 · 24px
--space-5 · 32px
--space-6 · 40px
--space-7 · 48px
--space-8 · 56px
--space-1: 8px   --space-2: 12px  --space-3: 16px  --space-4: 24px
--space-5: 32px  --space-6: 40px  --space-7: 48px  --space-8: 56px

.panel { padding: var(--space-4); }
.seccion { margin-bottom: var(--space-7); }
.grid { gap: var(--space-3); }

Radios

La geometría de la casa es recta. Las superficies (cards, paneles, modales) van a radio cero; los 6 píxeles son solo para controles (inputs, selects); la píldora es solo para chips de usuario y login. Cualquier otra esquina redondeada es ajena al sistema.

TokenValorPara qué sirveUso
--radius0Superficies: cards, paneles, botones. El cero es decisión, no omisión.border-radius:var(--radius)
--radius-ctl6pxSOLO controles de formulario.border-radius:var(--radius-ctl)
--radius-pill999pxSOLO pills: chip de usuario, login.border-radius:var(--radius-pill)
--radius · 0
--radius-ctl · 6px
--radius-pill · 999px
.card  { border-radius: var(--radius); }      /* superficie: recta */
.input { border-radius: var(--radius-ctl); }  /* control: 6px */
.chip  { border-radius: var(--radius-pill); } /* pill: 999px */

Sombras y transiciones

Las dos sombras existen como token y valen none a propósito: la jerarquía se construye con bordes y fondos, no con elevación. Referéncialas igual: si el sistema alguna vez introduce sombra, tu código la hereda solo. Las transiciones tienen tres tiempos.

TokenValorPara qué sirveUso
--shadownoneSombra de superficies. Deliberadamente ninguna.box-shadow:var(--shadow)
--shadow-modalnoneSombra de modales. Deliberadamente ninguna.box-shadow:var(--shadow-modal)
--t-fast.12sMicro interacción: hover de botón y link.transition:color var(--t-fast)
--t-base.15sTransición estándar: bordes de card, fondos.transition:border-color var(--t-base)
--t-slow.2sMovimientos mayores: paneles, despliegues.transition:transform var(--t-slow)
Pasa el cursor: el borde transiciona en --t-base. Sin sombra: la card se distingue por el borde.
.card {
  border: 1px solid var(--line);
  box-shadow: var(--shadow);              /* none, a propósito */
  transition: border-color var(--t-base);
}
.card:hover { border-color: var(--accent); }

Layout y grilla

Un contenedor canónico de 1240 píxeles con padding lateral que baja a 20 en móvil (media query a 640px dentro del propio tokens.css). La grilla de referencia es de columnas de 96 con calles de 24. La clase .container del kit ya empaqueta contenedor y padding.

TokenValorPara qué sirveUso
--container1240pxAncho máximo del contenido.max-width:var(--container)
--pad-x32px (20px si ≤640px)Padding lateral del contenedor. El kit lo baja solo en móvil.padding-inline:var(--pad-x)
--grid-col96pxAncho de columna de la grilla de referencia.grid-template-columns:repeat(auto-fill,var(--grid-col))
--grid-gap24pxCalle entre columnas.gap:var(--grid-gap)
<div class=container>  <!-- max-width:var(--container) + padding var(--pad-x) -->
  <div style="display:grid;
    grid-template-columns:repeat(auto-fill,var(--grid-col));
    gap:var(--grid-gap)">...</div>
</div>

Tema oscuro

El tema se resuelve en tres capas, todas sobre el elemento <html>:

1 · Automático: si el sistema pide oscuro y no hay override, aplica el bloque @media (prefers-color-scheme: dark) con selector :root:not([data-theme="light"]).
2 · Explícito: :root[data-theme="dark"] fuerza oscuro, data-theme="light" fuerza claro.
3 · Persistencia: chrome.js lee y escribe la clave group-theme en localStorage y estampa el atributo; el bootstrap anti-flash inline en el <head> lo aplica antes de que carguen las hojas.

OJO · Los selectores son de :root: poner data-theme=dark en un div interior NO cambia nada. El tema es por documento, no por bloque; para un bloque oscuro dentro de página clara usa la superficie inversa.

Qué se redefine en oscuro

TokenClaroOscuro
--ink#0e1418#f3f1ea
--ink-muted#5b6672#a9a69d
--ink-soft#a3acb5#6b6863
--paper#ffffff#0a0a0a
--paper-raised#ffffff#111110
--line#d4d1c9#2a2a27
--line-strong#14181c#eaeae4
--accent (CIS)#1e3a5f#7fc598
--accent-soft (CIS)#e7edf4#12261a
--surface-inverse#0c1116#17171a
--on-inverse#c7cdd4#d4d0c5
color-schemelightdark

NO se redefinen en oscuro: --warn, --err, --ok, --on-inverse-strong, y ningún token de tipografía, espaciado, radio, sombra, transición ni layout. Si tu diseño depende de que un color de estado cambie con el tema, está fuera del sistema.

cambia data-theme en <html>; toda la página se re-tiñe sola
<!-- bootstrap anti-flash, inline en el head ANTES de los stylesheets -->
<script>
(function(){try{var t=localStorage.getItem("group-theme");
if(t==="dark"||t==="light")document.documentElement.setAttribute("data-theme",t);
}catch(_){}})();
</script>

<!-- el toggle real lo pone chrome.js con [data-theme-toggle] -->
<button class="gr-nav__theme" data-theme-toggle aria-label="Cambiar tema">...</button>

Los que NO debes usar

Variables que verás en el código del ecosistema y que no son API pública del sistema:

VariableQué esQué hacer
--cis-* (legacy)Sistema viejo de CIS: Inter + verdes #0f5f2d. El propio archivo de marca ordena no propagarlo.Migrar a los tokens v9. No copiar de sitios sin migrar.
--cis-accent, --cis-linkAlias de compatibilidad que la marca CIS apunta a var(--accent) para código antiguo.En código nuevo usa --accent directo.
--card-colorPropiedad interna de .card y .feature-card en components.css: parametriza el color de UNA card.Sobreescríbela solo en el elemento card; nunca la uses como token global.
Hex literalesCualquier #rrggbb escrito a mano en un sitio del grupo.Prohibido. Todo color sale de un token; el linter del canon lo bloquea.
Google Fonts / CDN externoCargar Plex o cualquier fuente desde fuera del grupo.Prohibido (CANON, ADR-021). Las fuentes viven en /v9/<digest>/fonts/.
Mal · color a mano y alias legacy.
Bien · token del sistema.
/* mal: hex a mano y alias de compatibilidad */
a { color: #1e3a5f; }
a { color: var(--cis-link); }

/* bien: el token del sistema, que además cambia solo con el tema */
a { color: var(--accent); }