Especificación · controles · 2026-08-09
Los cinco controles que faltan
Casilla, radio, interruptor, segmentado y buscador. No existe ninguno en el kit
ni en los seis sitios del grupo. Acá quedan dibujados con sus estados, con nombre de clase, con las
medidas al píxel y con la regla de cuándo se usan. Es lo que hay que copiar a
v7/base/components.css, sin volver a preguntar.
Decidido
- C1 casilla v1, sin radio. La tarjeta vale si todas miden lo mismo
- C2 radio igual que la casilla, con la misma condición de ancho
- C3 interruptor v1 · C4 segmentado, las cuatro variantes
- C5 buscador, las cuatro formas
Queda fuera de esta página
- Cuál buscador va en cada sitio: lo escribe
/v8/buscadores/ - El radio general del kit, que sigue en 6px en el token (T03)
- La gramática del foco en el resto del kit (T05)
C0
Lo que comparten los cinco
Cuatro reglas antes de mirar pieza por pieza. Las cuatro salen de decisiones que ya están tomadas, no de gusto de quien dibuja.
- Radio cero en todo lo que tiene esquinas. La casilla es cuadrada, el segmentado es cuadrado, el campo del buscador es cuadrado. Lo redondo se admite en dos sitios y por dos razones distintas: el anillo del radio y el riel del interruptor, donde la redondez es la señal del control; y la píldora del segmentado y del buscador, que es excepción evaluada caso a caso.
- Una sola gramática de foco:
outline: 2px solid var(--accent)conoutline-offset: 2px, sobre:focus-visible. Es la de la tarjeta de entrada. El anillo de 3px pegado al borde que hoy escriben por su cuentacatalogo.cssyfirmas.cssno se propaga acá. La convención T05 sigue abierta y esta ficha la empuja hacia una sola forma. - El estado marcado es el par tinta y papel. Marcada la casilla se rellena de
var(--ink)y el visto sale envar(--paper), que es exactamente el par del botón primario. Donde el relleno es de acento, el texto va envar(--paper), nunca en blanco fijo: en tema oscuro el acento es verde claro y el blanco cae a 1,7 a 1. - Se separa con borde completo de 1px. Ni una franja lateral pintada, ni una sombra. Es la convención T01 y vale igual para un control de 16 píxeles que para una tarjeta.
Por qué el prefijo x-. Estas clases todavía no son del kit: viven en la
propuesta. Redefinir una clase gr- desde fuera es lo que hizo divergir el CSS en
los seis sitios. Cuando el bloque entre a v7/base/components.css pierde el
prefijo o toma el del kit, y esta página pasa a ser el documento de la decisión, no la
fuente. Los nombres van en inglés porque el kit ya habla en inglés
(.btn, .input, .card, .gr-nav__theme) y
una API mitad castellano no ayuda a nadie. La prosa sí los nombra en castellano.
C1 · decidido: v1, sin radio
La casilla
La variante 1 de la galería, con una corrección: la galería dibujaba 2px de radio y la decisión es cero. La tarjeta seleccionable de la variante 5 queda aceptada con una condición, y la condición es la parte que hay que implementar bien.
Normal
Con foco
Marcada
Deshabilitada
Variante de tarjeta · x-check--card dentro de x-cards
La condición del ancho es estructural. Las tres tarjetas miden lo mismo porque la reja reparte pistas iguales, no porque alguien se acuerde de escribirlo. Abajo, la misma pareja fuera de la reja: es exactamente lo que Martín prohibió.
| Caja | 16 × 16 px, flex: none |
|---|---|
| Borde | 1px solid var(--line-strong) |
| Radio | 0. Es la decisión: v1 sin radio. La galería dibujaba 2px |
| Fondo | var(--paper-raised); marcada, var(--ink) |
| Visto | canto de 4 × 8 px, trazo 2px, girado 42°, en left 4.5px / top 1px |
| Color del visto | var(--paper), o sea el par tinta y papel del botón primario |
| Aire a la etiqueta | 9px |
| Etiqueta | var(--font-sans) 13.5px, interlínea 1.35 |
| Alto de la fila | min-height: 24px. El objetivo de pulsación es la etiqueta entera |
| Foco | outline: 2px solid var(--accent), outline-offset: 2px |
| Deshabilitada | opacity: .4 en la caja y var(--ink-soft) en la etiqueta, vía :has(:disabled) |
| Tarjeta | relleno 11px 13px, borde 1px var(--line), radio 0, marcada toma var(--accent) y var(--accent-soft) |
| Reja de tarjetas | repeat(auto-fit, minmax(230px, 1fr)), hueco 10px |
<label class="x-check">
<input class="x-check__box" type="checkbox" name="borrador"> Guardar el borrador
</label>
<div class="x-cards">
<label class="x-check x-check--card">
<input class="x-check__box" type="checkbox" name="firma" value="avanzada">
<span class="x-check__txt">Firma electrónica avanzada<small>Requiere clave única</small></span>
</label>
</div>
Se usa cuando
- Se elige cero, una o varias opciones de una lista.
- Hay un botón de Guardar y el cambio espera a que lo pulsen.
- Es un consentimiento suelto: términos, aviso de privacidad, mandato.
- Se selecciona una fila de una tabla, con la casilla en la primera celda.
- Cada opción necesita una línea de explicación, y ahí va la tarjeta.
No se usa cuando
- El cambio se aplica al momento y no hay Guardar. Eso es un interruptor.
- Las opciones son excluyentes y hay que elegir una. Eso es un radio.
- Son dos o tres vistas excluyentes que caben a la vista. Eso es el segmentado.
- Hay más de dos tarjetas de largo muy dispar y no se las mete en la reja: quedan de anchos distintos y la variante deja de valer.
C2 · decidido: igual que la casilla
El radio
Mismo tamaño, mismo borde, mismo aire, mismo foco, misma condición de ancho en las tarjetas. Cambian dos cosas y solo dos: el anillo es redondo y la marca es un punto en vez de un visto. Casilla y radio se dibujan juntos o no se dibujan.
Cuidado con la palabra. Acá radio es este control. El radio de las esquinas es otra cosa y es la convención T03, que sigue abierta. Cuando las dos aparezcan en la misma frase, esta se llama botón de opción y la otra, radio de esquina.
Normal
Con foco
Marcado
Deshabilitado
Variante de tarjeta · x-radio--card dentro de x-cards
| Anillo | 16 × 16 px, borde 1px solid var(--line-strong) |
|---|---|
| Forma | border-radius: 999px. Es la única redondez que no es decoración: sin ella el radio se lee como casilla |
| Punto | 8 × 8 px centrado con translate(-50%, -50%) |
| Color del punto | var(--ink), y el anillo pasa a var(--ink) al marcarse |
| Aire, etiqueta, alto, foco | idénticos a la casilla. Es el mismo par y no se separan nunca |
| Deshabilitado | opacity: .4 vía :has(:disabled) |
| Tarjeta | las mismas medidas de .x-check--card, incluida la reja de anchos iguales |
<label class="x-radio">
<input class="x-radio__dot" type="radio" name="tipo" value="natural" checked> Persona natural
</label>
<fieldset>
<legend>Tipo de persona</legend>
<div class="x-cards">
<label class="x-radio x-radio--card">
<input class="x-radio__dot" type="radio" name="tipo" value="juridica">
<span class="x-radio__txt">Persona jurídica<small>Requiere representante legal</small></span>
</label>
</div>
</fieldset>
Se usa cuando
- Hay que elegir exactamente una opción entre dos y cinco.
- Las opciones caben todas a la vista y conviene compararlas.
- Siempre con una preseleccionada, salvo que ninguna sea un default honesto.
- Todos los del grupo comparten el
name, que es lo que los hace excluyentes.
No se usa cuando
- Hay más de cinco opciones. Ahí va el desplegable v1.
- Hay una sola opción: eso es una casilla, porque se puede desmarcar.
- El usuario debe poder deshacer su elección dejando el grupo vacío. Un radio no se desmarca.
- Las opciones son dos vistas de lo mismo, no dos valores. Eso es el segmentado.
C3 · decidido: v1
El interruptor
Píldora de tinta, 38 por 22. La pregunta que hay que hacerse antes de usarlo no es cómo se ve, es si el cambio se aplica al momento. Si el formulario tiene botón de Guardar, la respuesta correcta casi siempre es una casilla.
Normal
Con foco
Encendido
Deshabilitado
| Riel | 38 × 22 px, borde 1px solid var(--line-strong), radio 999px |
|---|---|
| Pulgar | 16 × 16 px en top 2px / left 2px |
| Recorrido | translateX(16px). Sale de la cuenta: 38 menos 2 de borde son 36 de interior, menos 16 del pulgar y 2 de aire a cada lado |
| Apagado | riel var(--paper-raised), pulgar var(--line-strong) |
| Encendido | riel var(--ink), pulgar var(--paper) |
| Transición | .15s en fondo, borde y desplazamiento, anulada bajo prefers-reduced-motion |
| Foco y etiqueta | los mismos de la casilla: contorno de 2px y aire de 9px |
| Semántica | <input type="checkbox" role="switch">. El lector de pantalla dice activado o desactivado, no marcado |
<label class="x-switch"> <input class="x-switch__track" type="checkbox" role="switch" checked> Notificarme por correo </label>
Se usa cuando
- El cambio se aplica al momento, sin botón de Guardar.
- Es reversible al instante y sin consecuencia grave.
- Es un ajuste de preferencia: avisos, modo de un panel, visibilidad de una columna.
No se usa cuando
- El formulario tiene Guardar. Ahí la respuesta correcta es casi siempre una casilla.
- Es un consentimiento legal. Los términos se aceptan con casilla, no con interruptor.
- La operación tarda o puede fallar. El interruptor promete que ya quedó hecho y miente.
- Hay que elegir entre dos estados con nombre propio. Eso es el segmentado, que los muestra los dos.
C4 · decidido: se aceptan todas
El segmentado
Las cinco variantes de la galería entran como una base más cuatro modificadores. La de versalita cambia de fuente por la decisión E3, y la píldora entra marcada como excepción, que es lo que Martín concedió para las píldoras en general.
Reposo
Con foco
Seleccionado
Deshabilitado
Las cuatro variantes aceptadas
base · activo de acento
--ink · activo de tinta
--tabs · sin caja
--epi · voz de epígrafe
--pill · excepción evaluada
La variante de versalita cambió de fuente. En la galería de variantes era JetBrains Mono. La decisión E3 del 9 de agosto retiró la mono de los epígrafes y la dejó solo para código y rutas, así que la variante entra al kit con Plex Sans Condensed 600 y tracking 0,14em. Es el mismo dibujo con la voz corregida, no una sexta variante.
| Caja | borde 1px solid var(--line), radio 0, sin overflow: hidden |
|---|---|
| Segmento | alto 34px, relleno lateral 15px, sin borde propio |
| Separador | border-left: 1px solid var(--line) solo entre segmentos |
| Texto | var(--font-sans) 12.5px peso 600, sin ajuste de línea |
| Reposo | fondo var(--paper), texto var(--ink-muted) |
| Seleccionado | fondo var(--accent), texto var(--paper) |
| Por qué papel y no blanco | en tema oscuro el acento es verde claro. Con #fff fijo el par cae a 1,7:1; con var(--paper) da sobre 10:1 en los dos temas |
| Foco | outline-offset: -2px, hacia adentro. Hacia afuera lo tapa el segmento vecino |
| --tabs | sin caja, hueco 4px, línea inferior 1px y activo con 2px de acento |
| --epi | var(--font-epi) 11px 600, tracking .14em, versalita |
| --pill | riel 999px con relleno 3px y segmentos de 28px |
| Semántica | role="tablist" si cambia la vista. Si fija un valor del formulario, role="radiogroup" con role="radio" |
<div class="x-seg" role="tablist" aria-label="Vista de la tabla"> <button class="x-seg__opt" type="button" role="tab" aria-selected="true">Tabla</button> <button class="x-seg__opt" type="button" role="tab" aria-selected="false">Gráfico</button> </div>
Se usa cuando
- Hay entre dos y cuatro opciones excluyentes con etiquetas de una o dos palabras.
- Conviene ver todas las opciones sin abrir nada.
- Lo que cambia es la vista de lo que está abajo, no el dato que se guarda.
- Es el control ya aprobado para el paso de entrar o crear cuenta.
No se usa cuando
- Hay más de cuatro opciones, o las etiquetas son largas. Ahí va el desplegable v1.
- Sirve para navegar entre páginas. Eso es la barra, no un segmentado.
- Es un filtro con muchos valores posibles. Ahí va el desplegable o el buscador.
- Se puede elegir más de una a la vez. Eso son casillas.
C5 · decidido: se aceptan todas
El buscador
Cuatro formas, un solo campo por debajo. El botón adosado no inventa una voz de botón: es el botón v1 de tinta llena a la altura del campo. Cuál corresponde en cada sitio no se decide acá.
Reposo
Con foco
Con contenido
Deshabilitado
Las cuatro formas aceptadas
base · lupa dentro
con botón adosado
--line · solo línea inferior
--pill · excepción evaluada
disparador de paleta
Acá está la anatomía, no el criterio de selección. Cuál de
las cuatro corresponde en cada sitio lo decide la página /v8/buscadores/, que se escribe aparte.
Esta ficha fija las medidas para que esa decisión no tenga que volver a dibujarlas.
| Campo | alto 38px, borde 1px solid var(--line), radio 0 |
|---|---|
| Relleno | 0 12px 0 34px. Los 34 de la izquierda dejan sitio a la lupa |
| Lupa | 15 × 15 px, trazo 1.9, en left 11px, color var(--ink-soft), sin eventos de puntero |
| Ancho | max-width: 250px por defecto, o el de su contenedor |
| Texto | var(--font-sans) 13.5px. El texto de ayuda va en var(--ink-soft) |
| Botón adosado | es el botón v1 tinta llena bajado a 38px de alto. margin-left: -1px colapsa el borde doble. No es una voz de botón nueva |
| --line | sin caja: border-bottom: 1px y relleno izquierdo 26px, con la lupa en left 2px |
| Foco de --line | el mismo contorno de 2px. La línea NO engorda a 2px al enfocar: eso movería un píxel todo lo que va abajo |
| --pill | radio 999px, relleno izquierdo 38px, lupa en left 15px, borde var(--line-strong) |
| Disparador | botón de 38px con la tecla en var(--font-epi) 10px, alineada a la derecha |
| Semántica | <form role="search"> con <input type="search"> y su aria-label |
<form class="x-search" role="search" action="/archivo/tmp-6536a10/browse/buscar">
<span class="x-search__icon"><!-- lupa 15px, aria-hidden --></span>
<input class="x-search__input" type="search" name="q"
placeholder="Buscar documentos" aria-label="Buscar documentos">
</form>
Se usa cuando
- Hay más entradas de las que caben en pantalla y el usuario ya sabe qué busca.
- La búsqueda filtra en vivo: ahí basta el campo con lupa, sin botón.
- La búsqueda pega contra el servidor y hay que enviarla: ahí entra el botón adosado.
- La búsqueda es global y merece pantalla propia: ahí entra el disparador de paleta, y hay que construir la paleta.
No se usa cuando
- La lista es corta y cabe entera. Un segmentado o un desplegable filtran mejor.
- Se pone un disparador de paleta sin la paleta hecha: queda un botón que no lleva a ninguna parte.
- Se copia el buscador de Periodismo2, que hoy trae radio 8px y grises fijos de Tailwind y no lee los tokens del grupo.
- Se elige la píldora sin evaluarla caso a caso: es una excepción, no el valor por defecto.
C6
El bloque para copiar
Esto es literalmente el CSS que gobierna todo lo que se ve más arriba. La página lo carga desde
su propio <style>, así que lo dibujado y lo escrito no pueden divergir. Va tal
cual a v7/base/components.css.
Dos dependencias antes de pegarlo. Primero, --font-epi: la
variante .x-seg--epi lo usa y hoy solo existe en la hoja de esta propuesta. Entra
a v7/base/tokens.css con la decisión E3, junto con el woff2 de Plex Sans
Condensed. Segundo, --radius-ctl vale 6px en el token y estas piezas
escriben border-radius: 0 a mano: si T03 se cierra en cero, el 0
literal se reemplaza por el token y se borra de acá.
/* ==========================================================================
x-controles · propuesta para v7/base/components.css
Casilla, radio, interruptor, segmentado y buscador. Ninguno existe hoy en
el kit ni en los seis sitios. Decidido el 2026-08-09.
Prefijo x- mientras vive en la propuesta. Al entrar al kit pierde el
prefijo o toma el del kit, nunca gr- desde fuera.
========================================================================== */
/* --- Gramática común ------------------------------------------------------
Una sola forma de foco para los cinco: contorno de 2px en el acento,
separado 2px. Es la misma de la tarjeta de entrada. El anillo de 3px
pegado al borde que usan hoy catalogo.css y firmas.css NO se propaga acá:
la convención T05 sigue abierta y esto la empuja hacia una sola gramática.
El par de color del estado marcado es acento/papel, nunca acento/blanco:
en tema oscuro el acento es verde claro y el blanco fijo cae a 1,7:1.
La lista de abajo NO incluye .x-seg__opt ni las tarjetas: esas dos llevan el
mismo contorno pero en otro sitio, y cada una lo declara donde vive. Son las
tres únicas colocaciones del foco en todo el bloque. */
.x-check__box:focus-visible,
.x-radio__dot:focus-visible,
.x-switch__track:focus-visible,
.x-search__input:focus-visible,
.x-search__go:focus-visible,
.x-search-trigger:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 2px;
}
/* La fila: control, aire de 9px, etiqueta. La etiqueta entera es el objetivo
de pulsación, por eso el <label> envuelve al <input>. */
.x-check,
.x-radio,
.x-switch {
display: inline-flex;
align-items: center;
gap: 9px;
min-height: 24px;
font-family: var(--font-sans);
font-size: 13.5px;
line-height: 1.35;
color: var(--ink);
cursor: pointer;
}
.x-check:has(:disabled),
.x-radio:has(:disabled),
.x-switch:has(:disabled) {
color: var(--ink-soft);
cursor: not-allowed;
}
/* --- C1 · Casilla · v1 sin radio ----------------------------------------- */
.x-check__box {
appearance: none;
-webkit-appearance: none;
position: relative;
flex: none;
width: 16px;
height: 16px;
margin: 0;
border: 1px solid var(--line-strong);
border-radius: 0;
background: var(--paper-raised);
cursor: inherit;
}
.x-check__box::after {
content: "";
position: absolute;
left: 4.5px;
top: 1px;
width: 4px;
height: 8px;
border: solid transparent;
border-width: 0 2px 2px 0;
transform: rotate(42deg);
}
.x-check__box:checked {
background: var(--ink);
border-color: var(--ink);
}
.x-check__box:checked::after { border-color: var(--paper); }
.x-check__box:disabled { opacity: .4; }
/* --- C2 · Radio · igual que la casilla, salvo la forma ------------------- */
.x-radio__dot {
appearance: none;
-webkit-appearance: none;
position: relative;
flex: none;
width: 16px;
height: 16px;
margin: 0;
border: 1px solid var(--line-strong);
border-radius: 999px;
background: var(--paper-raised);
cursor: inherit;
}
.x-radio__dot::after {
content: "";
position: absolute;
left: 50%;
top: 50%;
width: 8px;
height: 8px;
border-radius: 999px;
background: transparent;
transform: translate(-50%, -50%);
}
.x-radio__dot:checked { border-color: var(--ink); }
.x-radio__dot:checked::after { background: var(--ink); }
.x-radio__dot:disabled { opacity: .4; }
/* --- C1b y C2b · la variante de tarjeta ----------------------------------
La condición de Martín: si hay varias, TODAS del mismo ancho. Eso no se
pide por escrito, se hace estructural. El contenedor es una reja de pistas
iguales; la tarjeta nunca lleva max-width propio. Con flex y anchos
intrínsecos la fila sale despareja y la regla se rompe sola. */
.x-cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
gap: 10px;
align-items: stretch;
}
.x-check--card,
.x-radio--card {
display: flex;
align-items: flex-start;
gap: 10px;
width: 100%;
padding: 11px 13px;
border: 1px solid var(--line);
border-radius: 0;
background: var(--paper-raised);
font-size: 13px;
}
.x-check--card:has(:checked),
.x-radio--card:has(:checked) {
border-color: var(--accent);
background: var(--accent-soft);
}
/* El contorno rodea la tarjeta, no la caja de 16px que lleva dentro. */
.x-check--card:has(:focus-visible),
.x-radio--card:has(:focus-visible) {
outline: 2px solid var(--accent);
outline-offset: 2px;
}
.x-check--card .x-check__box:focus-visible,
.x-radio--card .x-radio__dot:focus-visible { outline: 0; }
.x-check__txt,
.x-radio__txt { display: block; font-weight: 600; }
.x-check__txt small,
.x-radio__txt small {
display: block;
margin-top: 2px;
font-weight: 400;
font-size: 11.5px;
line-height: 1.4;
color: var(--ink-muted);
}
/* --- C3 · Interruptor · v1 ------------------------------------------------
38 por 22 con pulgar de 16: 2px de aire por lado, recorrido de 16px. La
píldora es la única forma redonda que el sistema acepta sin excepción,
porque acá la redondez es la señal del control, no decoración. */
.x-switch__track {
appearance: none;
-webkit-appearance: none;
position: relative;
flex: none;
width: 38px;
height: 22px;
margin: 0;
border: 1px solid var(--line-strong);
border-radius: 999px;
background: var(--paper-raised);
cursor: inherit;
transition: background .15s, border-color .15s;
}
.x-switch__track::before {
content: "";
position: absolute;
top: 2px;
left: 2px;
width: 16px;
height: 16px;
border-radius: 999px;
background: var(--line-strong);
transition: transform .15s, background .15s;
}
.x-switch__track:checked {
background: var(--ink);
border-color: var(--ink);
}
.x-switch__track:checked::before {
transform: translateX(16px);
background: var(--paper);
}
.x-switch__track:disabled { opacity: .4; }
@media (prefers-reduced-motion: reduce) {
.x-switch__track,
.x-switch__track::before { transition: none; }
}
/* --- C4 · Segmentado · las cuatro variantes aceptadas --------------------
Sin overflow:hidden: con radio 0 no hace falta y recortaba el contorno de
foco del primer y del último segmento. */
.x-seg {
display: inline-flex;
max-width: 100%;
border: 1px solid var(--line);
border-radius: 0;
}
.x-seg__opt {
height: 34px;
padding: 0 15px;
border: 0;
border-radius: 0;
background: var(--paper);
color: var(--ink-muted);
font-family: var(--font-sans);
font-size: 12.5px;
font-weight: 600;
line-height: 1;
white-space: nowrap;
cursor: pointer;
}
.x-seg__opt + .x-seg__opt { border-left: 1px solid var(--line); }
.x-seg__opt[aria-selected="true"] {
background: var(--accent);
color: var(--paper);
}
.x-seg__opt:disabled { opacity: .42; cursor: not-allowed; }
/* Contorno hacia adentro: hacia afuera lo tapaba el segmento vecino. */
.x-seg__opt:focus-visible {
outline: 2px solid var(--accent);
outline-offset: -2px;
}
/* Activo en tinta, para no gastar el acento dos veces en la misma tarjeta. */
.x-seg--ink .x-seg__opt[aria-selected="true"] {
background: var(--ink);
color: var(--paper);
}
/* Pestañas: sin caja, sobre contenido ancho. */
.x-seg--tabs {
gap: 4px;
border: 0;
border-bottom: 1px solid var(--line);
}
.x-seg--tabs .x-seg__opt {
padding: 0 10px;
background: transparent;
border-bottom: 2px solid transparent;
}
.x-seg--tabs .x-seg__opt + .x-seg__opt { border-left: 0; }
.x-seg--tabs .x-seg__opt[aria-selected="true"] {
background: transparent;
color: var(--ink);
border-bottom-color: var(--accent);
}
/* Voz de epígrafe. Era JetBrains Mono en la galería de variantes; la
decisión E3 retiró la mono de ese oficio, así que la variante migra a
Plex Sans Condensed 600. Necesita --font-epi en v7/base/tokens.css. */
.x-seg--epi .x-seg__opt {
font-family: var(--font-epi);
font-size: 11px;
font-weight: 600;
letter-spacing: .14em;
text-transform: uppercase;
}
/* Píldora: excepción evaluada caso a caso, no opción por defecto. */
.x-seg--pill {
padding: 3px;
border-radius: 999px;
background: var(--paper);
}
.x-seg--pill .x-seg__opt {
height: 28px;
border-radius: 999px;
background: transparent;
}
.x-seg--pill .x-seg__opt + .x-seg__opt { border-left: 0; }
.x-seg--pill .x-seg__opt[aria-selected="true"] {
background: var(--ink);
color: var(--paper);
}
/* --- C5 · Buscador · las cuatro formas aceptadas ------------------------- */
.x-search {
position: relative;
display: flex;
align-items: center;
width: 100%;
max-width: 250px;
}
.x-search__input {
width: 100%;
height: 38px;
padding: 0 12px 0 34px;
border: 1px solid var(--line);
border-radius: 0;
background: var(--paper-raised);
color: var(--ink);
font-family: var(--font-sans);
font-size: 13.5px;
}
.x-search__input::placeholder { color: var(--ink-soft); }
.x-search__input:disabled {
background: var(--paper);
color: var(--ink-soft);
cursor: not-allowed;
}
/* La lupa se queda arriba de todo: el campo enfocado sube de plano y, sin
esto, su fondo opaco la taparía. */
.x-search__icon {
position: absolute;
left: 11px;
z-index: 2;
display: inline-flex;
align-items: center;
color: var(--ink-soft);
pointer-events: none;
}
/* El botón adosado es un hermano posterior, así que pintaba encima del
contorno de foco del campo y le comía el canto derecho. Subir el campo de
plano al enfocarlo es todo el arreglo. */
.x-search__input:focus-visible {
position: relative;
z-index: 1;
}
/* El botón adosado es el botón v1 tinta llena a 38px de alto, no una sexta
voz de botón. El -1px de margen colapsa el borde doble. */
.x-search__go {
flex: none;
height: 38px;
margin-left: -1px;
padding: 0 15px;
border: 1px solid var(--ink);
border-radius: 0;
background: var(--ink);
color: var(--paper);
font-family: var(--font-sans);
font-size: 13.5px;
font-weight: 600;
cursor: pointer;
}
/* Solo línea inferior. El foco NO engorda la línea: 1px a 2px mueve el
contenido de abajo. Mantiene el contorno común. */
.x-search--line .x-search__input {
padding-left: 26px;
border: 0;
border-bottom: 1px solid var(--line);
background: transparent;
}
.x-search--line .x-search__icon { left: 2px; }
/* Píldora: la misma excepción evaluada que en el segmentado. */
.x-search--pill .x-search__input {
padding-left: 38px;
border-radius: 999px;
border-color: var(--line-strong);
}
.x-search--pill .x-search__icon { left: 15px; }
/* Disparador de paleta: no es un campo, es un botón que abre la búsqueda. */
.x-search-trigger {
display: inline-flex;
align-items: center;
gap: 10px;
width: 100%;
max-width: 250px;
height: 38px;
padding: 0 12px;
border: 1px solid var(--line);
border-radius: 0;
background: var(--paper-raised);
color: var(--ink-muted);
font-family: var(--font-sans);
font-size: 13px;
cursor: pointer;
}
.x-search-trigger__kbd {
margin-left: auto;
padding: 2px 5px;
border: 1px solid var(--line);
font-family: var(--font-epi);
font-size: 10px;
letter-spacing: .08em;
color: var(--ink-soft);
}
Ver las cinco variantes originales · Volver a las convenciones