/*** TOKENS (alias legacy → DS; el reset de elementos vive en ds/reset.css) ***/
:root{
	/* ============================================================
	 * ALIAS LEGACY -> DESIGN SYSTEM  (migración 2026-07-16)
	 *
	 * Los VALORES ya no viven aquí: viven en assets/css/ds/, leídos
	 * del panel de Variables del Figma. Este bloque solo traduce los
	 * nombres viejos a los del DS para no romper main.css ni
	 * gwfields.css mientras se migran sus usos. Cada alias que se
	 * quede sin usos, se borra.
	 *
	 * Nombres: el DS llama a las cosas por su color (--red-500,
	 * --ui-500), no por su intención (--error-500, --gw-500). La
	 * intención vive en la capa semántica (--action-error-default).
	 *
	 * PENDIENTES de migrar (siguen con valor a mano porque cambiarlos
	 * SE VE; ΔE contra el valor del DS, 2.3 = umbral de percepción):
	 *   --neutral-400  #38474F  48 usos (36 aquí + 12 en gwfields.css)
	 *                  Nunca fue el 400 del DS (#78838F, ΔE 25.2):
	 *                  es casi el neutral/500 (#3E4349, ΔE 4.15).
	 *   --gw-300       #89F262  5 usos (solo gwfields) -> ΔE 36.9
	 *
	 * LIMPIEZA 2026-07-20 (plan docs/05-diseno/08-plan-debug-css, paquete #1):
	 * borrados los alias sin usos —--gw-200/500/600/700, las familias
	 * --warning-* y --success-* completas, --error-300/400/700, --info-300/400/700,
	 * --sidebar-fg y --swiper-pagination-color—. El fantasma --danger-600 (1 uso
	 * real en L1373, no los 2 que decía la nota) ya apunta a --error-600.
	 * ========================================================== */

	/* ---- Marca: las primitivas --brand-* viven en el BLOQUE BRAND
	   al final (capa swappable por vertical de la familia Juicy). ---- */

	/* ---- Neutral ---- */

	/* ---- UI Actions ---- */
	--gw-300:#89F262;
	--gw-400: var(--ui-400);
	--gw-800: var(--ui-800);

	/* ---- Primitivos · Feedback (AA) — solo los alias con usos vivos ---- */
	--error-500: var(--red-500);
	--error-600: var(--red-600);

	--info-500: var(--blue-500);
	--info-600: var(--blue-600);

}

/* ============================================================
 * BRAND THEME — capa de marca por vertical (familia Juicy).
 * El DASHBOARD (estructura, grises, feedback, componentes) es
 * COMPARTIDO; cada vertical cambia SOLO este bloque (+ logo).
 * La paleta de cada MARCA vive en su capa de vertical
 * (verticals/<brand>/brand.css); el core solo trae :root, el default
 * neutro de la familia Juicy. Nueva marca = nuevo brand.css en su vertical.
 *   --brand-500/600 : acento de marca (CTA, nav activo, links, focus)
 *   --brand-sidebar     : fondo del sidebar
 *   --brand-login-bg    : fondo de la pantalla de login
 * ========================================================== */

.svg_icon{
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 1em;
	height: 1em;
}

/*** SCROLL BAR ***/
/* Las tres reglas de la barra de scroll se MUDARON a ds/reset.css (2026-08-09). Eran reglas BASE
   del navegador —no dan forma a ningún componente— viviendo en el CSS legacy, que el front nuevo no
   importa a propósito: allá salían las barras por defecto, 15px medidos contra los 5 de aquí. Mismo
   patrón que se llevó `.container`, `.page_header` y el `line-height` de los uicons.
   ds/reset.css carga ANTES que este archivo y nadie más las declara, así que aplican igual: los
   valores no cambiaron, y el ancho del pseudo se comprobó idéntico en PHP antes y después. */

/*** MISC ***/
/* `.container` se reconcilió en ds/grid.css (2026-07-26): este override existía
   porque el contenedor del grid traía el padding de gutter de Bootstrap y el
   producto no lo quiere. Ahora lo declara el propio DS, así que el front nuevo
   —que no carga este archivo— deja de salir 24px más estrecho. */

/* El `line-height` de los glifos de uicons se mudó a ds/reset.css (2026-07-27): era una
   regla BASE de la tipografía de iconos y vivía en el CSS legacy, que el front nuevo no
   importa — así que allá TODOS los iconos tenían otra caja (la campana medía 20 de alto
   contra 27 aquí). Es el mismo patrón que ya se llevó `.container` y `.page_header`. */
/* Los botones viven en ds/button.css y ds/icon-chip.css. Aquí no queda nada de
   botones: este bloque tenía 212 líneas y se borró entero (juicy-core 0.7.0).
   Lo que había aquí y el DS no tenía se PORTÓ, no se perdió:
     .btn::after + .loading   -> .btn::after          (spinner de carga)
     .ghost_button:hover         -> .btn--outline:hover  (se rellena)
     semidisabled                -> .btn--muted          (apagado pero clickeable)
     hover_clear                 -> .btn--no-hover-fill
     fullwidth_button            -> .btn--full           (OJO: NO es --wide)
     big_botton                  -> .btn--lg             (la errata muere aquí)
     light_gray_button           -> .btn--quiet
     input_button                -> .icon-chip--in-field
   Lo de abajo es LAYOUT, no botones: por eso se queda. */
/* `.buttons_list` se MUDÓ a ds/form.css (2026-07-28): es el pie de CUALQUIER formulario —lo
   emiten los dos renderers de gw-fields— y el front nuevo no importa este archivo.
   `.actions_list` decía aquí "se queda: es la barra de acciones de los archives, no del
   formulario". **Medido el 2026-08-07: es falso.** Su ÚNICO emisor en todo el producto es
   `gw_POS::posHeaderActions()` — la fila de la sesión en la cabecera de la caja—; ningún archive
   la pinta. Así que se MUDÓ a ds/pos.css, con su familia. Lo destapó el espejo en cuanto la caja
   de React empezó a emitirla: `gap 5px` en PHP contra `normal` en React, y 10px de diferencia de
   ancho en la fila. Ver ds/pos.css. */

/** TEXTS COLORS ***/
/* `.text-red` se MUDÓ a ds/utilities.css (0.9.157). Era una utilidad de color viviendo en la hoja
   legacy que el front nuevo no importa, así que el mismo marcado salía rojo en PHP y gris en React
   — medido con el espejo en Ajustes › Registradoras: el aviso de contraste del logo
   (`.juicy-logo-preview-warn`) daba `rgb(240,68,56)` contra `rgb(62,67,73)`. Se movió con
   `--red-500` en vez de `--error-500` (ese alias lo define ESTA hoja, así que en el front no
   existe y la declaración entera se caía en silencio); el valor es el mismo #F04438.
   `.text-300` se queda: no la usa ninguna pantalla migrada, y mover lo que no hace falta es
   trabajo sin medida que lo respalde. */
.text-300{
	color: var(--neutral-300) !important;
}

/*** ALERTS -> ds/alert.css ***/
/* El toast era `.dashboard_alert {mood}` con los colores equivocados: success
   era CYAN (--gw-500) y warning era ROJO oscuro (--error-600). Ahora es
   `.toast .tone-*` (Figma 1:3116): success verde, warning naranja con texto
   oscuro (AA), info azul. El mapeo mood->tono vive en $.fn.pop_alert. Borrado
   en 0.8.1. */

/** FORMAT HELPERS **/
/* `.spacer` -> gw-fields/assets/css/gwfields.css (bloque juicy:fileuploader), 2026-07-29.
   Su unico emisor es el `changeInput` del uploader de imagen (gwfields.js:495), y de ahi sale
   tambien el pegamento del front nuevo, que no importa esta hoja: mientras la regla vivio aqui, el
   campo `image` de React salia con la caja colapsada. */

.after_form_link{
	margin-top: 20px;
}
.after_form_link .or_text{
	display: block;
	margin-bottom: 20px;
}
.after_form_link .or_text span{
	position: relative;
	font-size: 14px;
    font-weight: 600;
}
.after_form_link .or_text span::before{
	content:'';
	position: absolute;
	top:50%;
	left:-15px;
	width: 60px;
	height: 1px;
	background: var(--neutral-300);
	transform: translateX(-100%);
}
.after_form_link .or_text span::after{
	content:'';
	position: absolute;
	top:50%;
	right:-15px;
	width: 60px;
	height: 1px;
	background: var(--neutral-300);
	transform: translateX(100%);
}
.after_form_link a{
	font-size: 14px;
    font-weight: 600;
    text-decoration: underline;
	color: var(--text-primary);
}

/*** TAGS -> ds/badge.css ***/
/* Los tags eran `.badge badge--soft tone-*` con otro nombre: mismo padding
   (5/10) y mismo radio (3). Borrados en 0.7.2.

   Lo que había aquí NO era estilo, era LÓGICA DE NEGOCIO:
     .tag.publish, .tag.active, .tag.success, .tag.green { … }
     .tag.cancelled, .tag.trash, .tag.red, .tag.error    { … }
   Una hoja de estilos decidiendo que "publish" es bueno y "trash" es malo, y
   conociendo los estados de WordPress. El markup le pasaba el estado en crudo
   (`class="tag <?php echo $status ?>"`), así que cambiar un color obligaba a
   leer PHP y añadir un estado obligaba a tocar CSS. Ese mapeo vive ahora en
   `juicy_tone_for_status()` (includes/helpers.php) y el markup pide un TONO.

   El fondo cambia a propósito: el tag usaba la rampa 300 y el Badge del DS usa
   la 200 (ΔE 4.5–14.7 según el tono). Los dos pasan AA de sobra; el nuevo es más
   claro. Decisión del dueño: el DS manda en colores.

   Debajo sigue el MENÚ BURBUJA, que compartía bloque con los tags sin tener nada
   que ver. El DS no tiene menú contextual todavía, así que se queda. */
/** BUBBLE (menu + box) -> ds/bubble.css **/
/* Eran DOS componentes copiados línea a línea: `.bubble_menu` y `.bubble_box`
   declaraban el MISMO shell (absolute, ancla, blanco, radio, sombra, borde de
   3, pico, transform, z-index, oculto, transición) y cada uno repetía su
   ::before, su .active, su .open_upward y su .open_upward.active. Ahora es un
   solo shell `.bubble` con dos contenidos (`--menu` / `--box`), y el item de
   menú es opt-in: se acabó el `.bubble_menu > *` que obligaba a la caja de
   notificaciones a ANULAR el padding/uppercase de sus propios hijos.
   Borrado en 0.8.2. */

/** TRIGGERS — el cursor. El look del trigger ya es del DS: `.actions_button`
    (el clon de 35) murió en F2c y hoy es un icon-chip.
    `.applied_filters .bubble_trigger` (el aviso morado de "hay filtros puestos")
    se mudó a `ds/bubble.css`: el front nuevo no importa este archivo, así que
    aquí la señal no le llegaba y su chip salía apagado con filtros aplicados. **/
.bubble_trigger{
	cursor: pointer;
}

/* El POS pide su menú más angosto que el default. El DS no define tamaños de
   menú (ds/bubble.css, nota 10) y `small` (120px) murió con 0 usos; este tiene
   uno (gw_POS.php:81) y muere con F2g. */
.bubble--menu.medium{
	width: 180px;
}

/*** GRAVITY FORMS ***/
.gform_description:empty{
	display: none;
}

/*** AVATAR -> ds/avatar.css ***/
/* Se MOVIÓ al DS (0.9.160). Lo destapó migrar `propinas`: el front no importa
   esta hoja a propósito, así que su celda de mesero pintaba el avatar sin fondo,
   sin redondear y en `display:block`. No es de una pantalla —la usan la caja, la
   reja de mesas y el informe de propinas—, así que su sitio es el DS. */

/*** DASHBOARD MENU -> ds/sidebar.css ***/
/* La barra entera se fue a su archivo (F2e). No se rediseñó NADA —ya era el
   Figma— pero al mudarla salieron tres cosas que aquí no se veían:

   · EL 70 Y EL 230 ESTABAN A MANO EN 11 SITIOS de 5 bloques distintos, y el
     móvil metía un tercer riel (50) con su propio logo. Ahora son
     `--sidebar-rail` / `--sidebar-panel`, y lo que el layout RESERVA es un token
     aparte (`--sidebar-reserved`), porque no es lo mismo: en hover la barra
     crece por encima del contenido, a ≥1920 lo empuja.
   · LA RECETA DE "EXPANDIR" ESTABA COPIADA 3 VECES (hover, táctil, ≥1920), y su
     propio comentario contaba que eso ya la rompió una vez. Ahora hay UN
     interruptor `--sidebar-open` y los tres disparadores solo lo encienden.
   · LAS 5 REGLAS DE `.menu-item`/`.sub-menu`/`.menu-link` ERAN GLOBALES — las
     mismas clases que genera `wp_nav_menu()`. Medido contra los 6 blogs: el
     bloque `gw/navigation-menu` tiene 0 usos y no hay ningún menú registrado, o
     sea que la fuga existía y no le pegaba a nadie. Quedan acotadas allá.
   Ver ds/sidebar.css y sus notas 1-4. */
/*** DASHBOARD CONTENT -> ds/sidebar.css ***/
/* El hueco que le deja la barra SE FUE a ds/sidebar.css (junto con su override de
   móvil). Estaba aquí por la razón correcta —es producto, no sistema— pero el front
   nuevo (React) tiene que pintar el mismo marco y NO importa main.css a propósito
   (es el CSS legacy; hay una prueba que lo verifica). Una copia de estas 8 líneas
   en el front habría sido la tercera divergencia de la semana, después de la X del
   lightbox y de los iconos. Vive donde vive el token que consume. */

/** DASHBOARD HEADER -> ds/header.css **/
/* Se fue a su archivo (F2e), igual que la barra y por la misma razón: ya era el
   Figma, solo estaba suelto aquí. Buena parte venía migrada de antes — la campana
   es una `.bubble` (F2b) y sus slots miden `--control-md` (F2c nota 9).
   Al tokenizarlo apareció un `font-size: var(--neutral-500)` — un COLOR en
   font-size — que llevaba años sin hacer nada. Ver ds/header.css nota 3. */


/*** FORMS -> ds/form.css ***/
/* SE MUDÓ ENTERO (2026-07-28, 0.9.115): el velo de guardado de un `ajax_form`
   (`:before`/`:after` + los keyframes `loadingRotate`) es el estado "guardando" de
   cualquier formulario, y el front nuevo no importa este archivo. Los keyframes se
   llevaron con él porque `ds/pos.css` también los anima y allá estaban rotos.
   Ver ds/form.css, sección 1. */

/*** INPUTS / SELECT / TEXTAREA -> ds/field.css ***/
/* SE MUDARON (2026-07-26). Estaban aquí marcadas "TRANSICIONAL" desde la
   extracción del DS, con la deuda contada: lo que cuelga de ellas son los ~26
   `<select>` de los toolbars de los archives y los controles del POS, que no
   tienen la envoltura `.input` (era F3 del plan del DS).
   Lo que cambió y forzó la mudanza: el front nuevo (React) pinta estas mismas
   pantallas y NO importa main.css a propósito, así que un control a pelo suyo
   salía con el borde del navegador. No se han matado —eso sigue siendo F3— se
   han movido al DS, que es el suelo que comparten los dos mundos.
   Ver ds/field.css, sección "LOS CONTROLES A PELO". */

/*** TABS ***/
/* Los PANELES (`.tab_content` y sus variantes) se MUDARON a ds/form.css (2026-07-28):
   son lo único que oculta los paneles inactivos de un `form_panel`, y sin ellos un
   formulario con pestañas en el front nuevo pinta todos los paneles apilados.
   La OTRA barra de pestañas —la horizontal, `.tabs_header`/`.tab`/`.tab.active`— se quedaba
   aquí con esta nota: *"su ÚNICO emisor es el lightbox de buscar cliente del POS … El POS es
   F4 y cruzará con su familia"*. **Cruzó** (2026-08-07): vive en ds/pos.css, junto al resto
   de la caja. La empujó un defecto medido — el modal de cliente del front nuevo salió sin
   pestañas y sin el alta de cliente, y sin la regla tampoco podía pintarlas.
   `.lightbox_content .tab_content` se BORRÓ en vez de mudarse: `.lightbox_content` tiene
   CERO emisores desde que F2d renombró el modal a `.lightbox__content`. */

/*** WIDGETS ***/
/* La familia `.widget` entera vive ahora en assets/css/ds/widget.css, que se
   encola DESPUÉS de este archivo. Aquí solo queda el `.widget_header/_body/
   _title/…` de abajo, que es OTRA cosa: el panel de formulario, no la tarjeta.

   Se fueron de aquí:
     .widget                         -> carcasa del DS (era lo mismo sin radio ni trazo)
     .widget.dark_widget             -> .widget--raised  (0 usos ya)
     .widget.dark_widget .field_label / .switch_label  -> muerta con dark_widget
   Ver ds/widget.css notas 2, 12 y 15. */
.widget_header{
	padding: 20px 0;
	background: rgba(0, 0, 0, 0.1);
}
.widget_header h1,
.widget_header h2,
.widget_header h3{
	font-size: 20px;
	text-transform: uppercase;
	margin: 0;
}
.widget_body .widget_header{
	padding: 0;
	background: none;
	margin-bottom: 30px;
	padding-bottom: 10px;
	border-bottom: 1px solid var(--neutral-200);
}
/* `.widget_body{padding:30px}` se MUDÓ a ds/widget.css (2026-07-28): es el relleno del
   panel de formulario (`form_panel` emite `.widget > .widget_body`) y el front nuevo no
   importa este archivo.
   `.widget_body p` TAMBIÉN CRUZÓ (2026-07-29), y esta nota decía lo contrario: se dejó aquí por si
   mover la regla movía el Hub. Se comprobó y no lo mueve — el Hub no emite ni un `<p>` dentro de un
   `.widget_body` (grep sobre su repo). Lo que sí movía era el front nuevo: un campo `html` dentro
   del cuerpo del widget salía a 16px/24px en vez de 14px/21px y arrastraba 6px hacia abajo todo lo
   que iba debajo. Vive en `ds/widget.css`. */
.widget_title{
	font-size: 20px;
    text-transform: uppercase;
    color: var(--text-primary);
}
/* `.widget_subtitle` se mudó a `ds/widget.css`: el front nuevo no importa este
   archivo, y el encabezado de sección del lightbox de detalle salía sin estilo. */
.widget_outside_header{
	height: 40px;
	margin-bottom: 15px;
}
.widget_outside_header h2{
	margin: 0;
	font-weight: 500;
	font-size: 20px;
	text-transform: uppercase;
	color: var(--text-primary);
}
/* `.widgets_grid .widget` + `.widget_label` + `.widget_value` MIGRADOS al DS.
   Eran el Information Box escrito con utilidades de Bootstrap: 36 cajas con
   `text-center d-flex flex-column align-items-center w-100` encima. Hoy:
     .widget.widget--info.widget--light    (era .widget a secas dentro del grid)
     .widget.widget--info.widget--raised   (era .dark_widget)
     .widget.widget--info.widget--red      (era .red_widget)
   `.widgets_grid` no tenía NINGUNA regla propia — solo existía para dar
   especificidad (0,2,0) a estas tres. Sin ellas, el wrapper sobra: se quitó de
   los 6 templates. Ver assets/css/ds/widget.css. */

/*** ARQUEO DE EFECTIVO (cierre de caja) ***/
/* Estos dos NO son cajas del DS y por eso no usan `.widget__info-label`: el
   summary es un encabezado plegable y cada denominación es la etiqueta de su
   input. Usaban `.widget_label` (la etiqueta del Information Box) por parecido
   visual, no porque lo fueran. */
.arqueo_toggle{
	cursor: pointer;
	text-transform: uppercase;
	font-size: 13px;
	font-weight: 500;
	color: var(--text-primary);
}
.arqueo_denom_label{
	min-width: 70px;
	font-size: 13px;
	font-weight: 500;
	color: var(--text-primary);
}

/*** PROGRESO DE LA IMPORTACIÓN -> ds/import.css ***/
/* `.process_title` y `.progress_bar` (con sus dos pseudo y su @keyframes) CRUZARON a
   `assets/css/ds/import.css` (2026-08-01), que es donde ya vive el resto de la familia
   Importar. Son los dos diálogos de progreso del paso 3, y mientras vivieron aquí —una
   hoja que el front nuevo NO importa— la pantalla migrada los habría pintado sin barra
   y con el título en 16px heredados en vez de 15 en versalitas.
   Diff mecánico tras mover: 0 diferencias · 10/10 selectores con algo que medir. */

/*** LIGHTBOX + DIALOG -> ds/lightbox.css ***/
/* Lo único que se queda aquí es lo que el DS NO debe saber: que este dashboard
   tiene un sidebar de 70px. El componente cubre su contenedor y pregunta por
   `--lightbox-inset-start`; quien la contesta es el producto, que es quien
   tiene la barra. Con eso, los dos parches que existían solo para DES-hacer el
   offset (`allblock`/`partialblock`) se vuelven una línea cada uno.
   Lo que murió: el shell duplicado, tres tamaños con CERO usos (medium, big,
   full), un `border-bottom:#eaedf0` que no es ningún token y que el Figma no
   dibuja, DOS overlays distintos para un mismo velo, y la tarjeta del confirm
   —que se llamaba a sí misma "Design System"— con su radio de 8 fuera de
   escala y sus botones clonados del `.btn`. Borrado en 0.8.7. */
.lightbox{
	/* Lo que la barra le reserva al layout — el mismo dato que lee el contenido. Un
	   ancho a mano se desincronizaba con la barra a ≥1920. Ver ds/sidebar.css nota 4. */
	--lightbox-inset-start: var(--sidebar-reserved);
}
/* Los modales que tapan TODO (el bloqueo del POS): sin offset y por encima. */
.allblock_lightbox{
	--lightbox-inset-start: 0px;
	z-index: 999 !important;
}
.partialblock_lightbox .lightbox__overlay,
.allblock_lightbox .lightbox__overlay{
	background: color-mix(in srgb, var(--brand-charcoal) 95%, transparent);
}
/* El diálogo de confirmación tampoco cede espacio al sidebar: es del sistema. */
.confirm_lightbox{
	--lightbox-inset-start: 0px;
	z-index: 9999;
}

/*** NOTA DE CRÉDITO — confirmación (lightbox creditNoteConfirm) ***/
.je_cn_confirm .je_cn_lead{
	margin: 0 0 18px;
	color: var(--text-primary);
	line-height: 1.5;
}
.je_cn_data{
	margin: 0;
	border: 1px solid var(--neutral-200);
	border-radius: 8px;
	overflow: hidden;
	background: var(--neutral-100);
}
.je_cn_data .je_cn_row{
	display: flex;
	justify-content: space-between;
	align-items: baseline;
	gap: 16px;
	margin: 0;
	padding: 11px 16px;
}
.je_cn_data .je_cn_row + .je_cn_row{
	border-top: 1px solid var(--neutral-200);
}
.je_cn_data dt{
	margin: 0;
	flex: 0 0 auto;
	color: var(--neutral-300);
	font-size: 13px;
	font-weight: 500;
}
.je_cn_data dd{
	margin: 0;
	color: var(--neutral-500);
	font-weight: 600;
	text-align: right;
	word-break: break-word;
}
.je_cn_data .je_cn_uuid{
	font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
	font-size: 12px;
	font-weight: 400;
	color: var(--text-primary);
}
.je_cn_data .je_cn_total{
	background: var(--neutral-white);
	padding: 14px 16px;
}
.je_cn_data .je_cn_total dt{
	color: var(--text-primary);
	font-size: 14px;
}
.je_cn_data .je_cn_total dd{
	font-size: 20px;
	font-weight: 700;
	color: var(--neutral-600);
}
.je_cn_confirm .buttons_list{
	margin-top: 20px;
}
.je_cn_note{
	margin: 14px 0 0;
	color: var(--neutral-300);
	font-size: 12px;
	line-height: 1.5;
	text-align: center;
}

/*** LOGIN PAGE ***/
/* NO HAY FIGMA DEL LOGIN. El archivo del DS tiene 21 frames de nivel superior y
   ninguno es esta pantalla; el doc 01 §9 la lista como "⏳ Opcional: componentizar
   Login". Así que esta fase no copió un diseño: MATÓ CLONES. El login se había
   reimplementado a mano el campo, el label, el checkbox, el botón y DOS avisos
   —todo lo que el DS ya tenía— y aquí queda solo lo que el DS no sabe: que esta
   pantalla es la PUERTA (fondo de marca, caja centrada) y que su caja es una
   superficie INVERSA.

   LA CAJA OSCURA NO ERA UNA INVENCIÓN DEL LOGIN: `--login-box` valía neutral/700,
   que es EXACTAMENTE `--surface-inverse` del DS. El token ya existía; el login lo
   deletreaba con otro nombre. Por eso esto no cambia el aspecto: no había que
   rediseñar nada, había que NOMBRARLO.

   El volteo de tinta de abajo es el contrato de superficie inversa en miniatura,
   y se queda en el PRODUCTO a propósito (regla 8: un caso no es una regla). El
   login es hoy su ÚNICO consumidor. Si F2e (sidebar) o F2g (el POS, que ya tiene
   `--surface-raised`) traen más superficies oscuras CON componentes encima, se
   promueve a `ds/` con los tres casos medidos. Antes no. */
.login_page{
	min-height: 100vh;
	padding: 40px 20px;
	/* Fondo = charcoal del preset (`custom-600`), mismo origen que la sidebar
	   (sidebar.css:97) → login y sidebar coinciden. Antes salía de
	   `--brand-login-bg` de brand.css (POS en slate #1e293b), archivo RETIRADO por
	   muerto; el color de marca real vive en theme.json (custom-500/600). */
	background: var(--wp--preset--color--custom-600, #22333B);
}
.login_box_wrapper{
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 30px;
	width: 100%;
	max-width: 460px;
}

/* LA CAJA — superficie inversa. Voltea SU tinta y no la de sus hijos: los campos
   son islas CLARAS y conservan la suya, porque `.input` ya viaja con su par
   papel+tinta (`--text-field`, resuelto en :root — semantics.css y field.css
   nota 33). Por eso aquí no hay que des-voltear nada campo por campo: sin ese
   arreglo, este bloque habría necesitado un parche por cada componente. */
.login_form_box{
	display: flex;
	flex-direction: column;
	gap: 18px;
	width: 100%;
	padding: 32px;
	border-radius: 32px;
	background: var(--surface-inverse);

	--text-primary:   var(--neutral-white);
	--text-secondary: rgba(255, 255, 255, 0.85);
	color: var(--text-primary);
}

/* La TINTA del checkbox se invierte con el papel. El DS dice que checkbox y radio
   son MARCAS —tinta sobre papel— y por eso su tono es `neutral-lv1`, el charcoal
   (choice.css). Sobre esta caja eso era literalmente un cuadro negro sobre negro:
   medido, #3E4349 sobre #212326. Invertir el par conserva la idea (sigue siendo
   tinta) con el papel al revés. Antes el checkbox era CARMESÍ de marca, que no es
   lo que el DS dice que es un checkbox — el color de marca aquí lo llevan los
   enlaces (`--text-brand`), que es justo para lo que ese token existe.
   SE APUNTA AL CONTROL, no a `.tone-neutral-lv1`: ese tono es el DEFAULT del
   checkbox y lo declara `:where(.choice__input)` (choice.css), así que el markup
   NO lleva la clase y una regla que la buscara no engancharía nada. Lo aprendí
   por la foto: escribí la regla contra la clase y el checkbox se quedó negro. */
.login_form_box .choice__input{
	--tone-fill: var(--neutral-white);
	--tone-fg:   var(--neutral-700);
}

.login_title{
	margin: 0 0 12px;
	font-size: 26px;
	font-weight: 700;
	text-align: center;
}
.login_hint{
	margin: -4px 0 4px;
	font-size: 14px;
	line-height: 1.4;
	color: var(--text-secondary);
	text-align: center;
}

/* EL OJITO. Es lo único que el DS no puede resolver solo, porque es un ESTADO
   con dos glifos: main.js voltea `aria-pressed` (y el type del input) y el CSS
   elige cuál se ve. El botón en sí ya es del DS — `icon-chip--ghost` es el tipo
   `single` del Figma: un icono pelón, sin caja, que toma su color del tono. Y
   vive EN FLUJO dentro del `.input` (field.css baja el padding derecho con
   `:has(> .icon-chip)`), así que se acabaron el `position:relative` del wrapper
   y el botón absoluto de 44px.
   Los dos glifos son TIPOGRAFÍA (fi-rr-eye / fi-rr-eye-crossed), no los dos SVG
   dibujados a mano que había aquí — que eran 4 de los 5 <svg> de todo el
   producto. Ver foundation.css. */
.login-password-toggle .login-password-eye-off{
	display: none;
}
.login-password-toggle[aria-pressed="true"] .login-password-eye{
	display: none;
}
.login-password-toggle[aria-pressed="true"] .login-password-eye-off{
	display: inline-block;
}


/* `.form_errors` ES UN HOOK DE JS, NO UN ESTILO — y por eso su nombre no se toca:
   `$.fn.print_errors` (main.js) la BUSCA en el formulario y, si no está, la CREA.
   El pintado ya lo hace el DS: las clases `alert-banner tone-error` las trae el
   markup y también las emite main.js al crearla. Aquí solo queda quitarle a sus
   <p> el margen del navegador.
   Ojo con el alcance: el handler es genérico (cualquier `validate_form`), pero
   los 12 `print_errors` del backend viven todos en gw_Users.php, o sea que esta
   caja HOY solo aparece en el login. Si algún día otro handler lo devuelve, ya
   hereda el banner del DS y no un aviso blanco sobre velo blanco. */
/* Sus dos reglas se MUDARON a ds/form.css (2026-07-28): son el estado "con errores" de
   cualquier formulario, y el front nuevo no importa este archivo. */

.login_remember_row{
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 12px;
}
.login_forgot{
	font-size: 13px;
	font-weight: 600;
	color: var(--text-brand);
	white-space: nowrap;
}
.login_submit_row{
	display: flex;
	justify-content: center;
	margin-top: 6px;
}
.login_register{
	margin: 0;
	font-size: 13px;
	text-align: center;
}
.login_register a{
	color: var(--text-brand);
	font-weight: 600;
}

/* Pie con el logo de la plataforma */
.login_footer{
	margin-top: 12px;
	padding-top: 20px;
	text-align: center;
	/* #090D0F está FUERA de la rampa del DS (la neutral termina en 700 = #212326).
	   Se llamaba "neutral/900": un token que no existe. Se conserva el valor —es
	   el que se ve hoy— pero sin la etiqueta falsa. Cuando el contrato de
	   superficie inversa se promueva al DS, este divisor es candidato a velo. */
	border-top: 0.85px solid #090D0F;
}
.login_footer img{
	width: 120px;
	height: auto;
	opacity: 0.45;
	filter: brightness(0) invert(1); /* el SVG es #090D0F; lo aclaramos para que se lea sobre la caja oscura */
}

/* MUERTOS QUE SE LLEVA ESTA FASE (no se migra lo que nadie usa):
     · `.login_client_logo` (+ img) — 0 usos. El logo white-label por tenant se
       retiró (86e29t343) y su CSS se quedó 18 líneas huérfanas.
     · `.btn.alt_button` — la clase no tenía NI UNA regla; su único rastro era el
       override de aquí. Ver abajo.
     · `--login-box`, `--login-border`, `--login-placeholder`, `--login-divider`,
       `--login-brand`, `--login-bg` — seis alias locales de tokens que ya
       existían en el DS, o de literales.

   EL BOTÓN LLEVABA AÑOS DEL COLOR EQUIVOCADO Y NADIE PODÍA VERLO. Aquí había una
   regla `.login_page .login_form_box .btn.alt_button` que le fijaba
   `--btnColor: var(--login-brand)` (carmesí) y un hover #8a2c2c.
   `--btnColor` es una variable MUERTA: se escribe en 6 sitios de este archivo y
   NO LA LEE NADIE — murió cuando el botón pasó al contrato de tonos. O sea que
   el CSS pedía un botón carmesí y el navegador pintaba el cian del `:where(.btn)`
   por defecto. El cian resulta ser lo correcto (es `tone-primary`, el primario del
   DS, igual que todos los demás botones del producto), así que el aspecto no
   cambia: solo dejan de convivir la intención y el hecho. Los otros 4 `--btnColor`
   siguen vivos-muertos en POS y widgets → F2g/F3. */
/*** CABECERA DE PÁGINA -> ds/header.css ***/
/* `.page_header`, su `h1` y `.page_header_actions` se mudaron (2026-07-26). El
   `.page_header_subtitle` ya vivía allá desde F2e, así que el componente estaba
   partido en dos archivos; ahora está entero. Lo forzó el front nuevo, que pinta
   el mismo título y no carga este archivo: su h1 salía con el tamaño y el peso
   por defecto del navegador (32px/700 contra 20px/500 del producto). */

/*** ARCHIVE CHROME (nav + paginación + toolbar) -> ds/archive.css ***/
/* Aquí vivían tres overrides que le PELEABAN al propio DS y que nadie había
   visto juntos:
     · `.archive_header input/select{height:35px}` aplastaba los campos a 35 —
       pero NO a los botones, que seguían en 40. O sea que la barra tenía
       selects de 35 pegados a botones de 40, y un buscador cuyo input y cuyo
       botón medían distinto. El Figma instancia los componentes del DS a 40;
       subirlos ALINEA la barra (aprobado por el dueño 2026-07-17).
     · `.archive_bulk_actions .btn{padding:10px}` aplastaba el padding del botón
       (20). Con el suyo mide los 116 exactos del Figma.
     · `.pagination .icon-chip{width:30;height:30}` encogía por CSS un chip que
       el markup pedía de 40. Ahora el markup dice `--sm` y se acabó.
   Y el buscador (`.search_input_wrapper` + su botón pegado con border-radius a
   mano) era un clon del `.search` de ds/field.css. Borrado en 0.8.4. */

.archive_term_name .fi-rr-caret-right{
	font-size:18px
}
/*** .no_post — LEGACY, y NO es la tabla vacía del archive ***/
/* Casi lo mato con la tabla, y habría dejado 14 sitios sin estilo: `.no_post`
   NO solo pintaba "no hay contenido". También pinta cosas que el DS todavía no
   modela y que no son un archive:
     · "No tienes permiso…"  ×5   (páginas de edición) -> F3
     · "Orden no encontrada", "Factura no encontrada"… ×6 (lightboxes) -> F2d
     · la lista vacía del lightbox de factura global    ×1 -> F2d
     · "Sin resultados" de la búsqueda del POS          ×1 -> F2g
     · la pantalla de "función no disponible"           ×1 -> F3
   La tabla vacía del archive (lo único que el Figma sí define) ya es
   `.archive-empty` en ds/archive.css, con este mismo tratamiento.
   Ojo al borrarlo: `.no_post` estaba declarado DOS VECES, a 1500 líneas de
   distancia — el de arriba sin `font-size` y el de abajo con él (el mismo
   patrón de los tags, que tenían dos bloques a 2200 líneas). Esto es la SUMA
   de los dos, que es lo que se veía. `.no_content` era su gemela con 0 usos:
   muerta. Cuando F2d/F3/F2g decidan qué son esos estados, esto muere. */
.no_post{
	font-size: 12px;
	font-style: italic;
	color: var(--text-muted);
}

/*** ARCHIVE TABLE + TOTALS -> ds/archive.css ***/
/* El producto YA medía lo que dice el Figma: header de 50 en #939FAC, hueco de
   10 entre filas y filas de 75 (en órdenes, clientes y usuarios). Esto no fue
   un rediseño: fue sacarlo de aquí y ponerle nombre. Lo que sí cambió: el
   `.actions_button` de 35 era un clon de `.icon-chip--sm --round --soft
   tone-neutral-lv3` (30, lo que mide el Figma), y `productos` era el único
   archive con filas de 90 — se las estiraba su imagen. Ahora el alto se declara
   y el contenido se centra, así que el chip encoge sin mover la fila.
   Sigue aquí el CHROME del archive (nav de estatus, paginación, toolbar):
   muere en el siguiente tramo de F2c. Borrado en 0.8.3. */

/*** POS -> ds/pos.css + ds/cart.css ***/
/* F2g.1 — "el carrito vacío". La pantalla se partió como la parte el Figma:
   `ds/pos.css` = buscador + tabs + reja · `ds/cart.css` = header del carrito +
   carcasa + vacío. Los renglones, los totales y el footer SIGUEN ABAJO: son
   F2g.2 (carrito con productos) y F2g.3 (el checkout, que se rehace por pasos).

   Cuatro piezas nuevas, solo HTML+CSS (la funcionalidad va después, dicho por el
   dueño): ORDENAR en la barra de tabs · el + de alta al vuelo FUERA del campo ·
   la ✕ de limpiar cliente · vaciar carrito y órdenes en espera.

   Lo que salió al mudarlo — ver las notas de los dos archivos:
   · EL BOTÓN ROJO DE HOY NO ERA LO QUE PARECÍA. El círculo rojo con ✕ vaciaba el
     carrito; en el Figma ese círculo limpia el CLIENTE y vaciar es otro botón.
     Re-estilar sin mirar habría dejado un botón que dice una cosa y hace otra.
   · EL ICONO QUE EL FIGMA PIDE NO ESTÁ EN LA TIPOGRAFÍA, pero SÍ en el repo:
     `shopping-cart-clear.svg` existía y su clase estaba HUÉRFANA — el botón
     mostraba un `fi-rr-cross` prestado. Recuperado, y por `mask` para que tome el
     color del tono en vez de traerlo cocido.
   · LA BARRA DE TABS ES `--surface-raised`, y semantics.css ya lo decía en su
     comentario ("oscuro: barra de tabs del POS") mientras la barra pintaba el
     primitivo a pelo.
   · LA REJA CONTABA COLUMNAS a mano en 3 media queries (6/5/4). Ahora `auto-fill`.
   · DOS `--btnColor` MUERTOS MÁS (los chips del toggle nombre/código, que además
     están ocultos en el markup): variable que no lee nadie, sobre un control que
     no se ve. Quedan 2 en widgets → F3. */
/*** CART BODY -> ds/cart.css ***/
/* F2g.2 — el carrito CON productos. Sin cambios de diseño (el dueño: "sin
   cambios más que usar tokens de color"): ya era el Figma. Lo único que hacía mal
   era pintar primitivos y alias legacy a pelo teniendo la semántica al lado —
   `--error-500` y `--gw-400` eran `--action-error-default` y
   `--action-secondary-default` con otro nombre y una indirección de más.
   Nuevo: el chip de guardar la orden, hermano de "Crear Orden". Y el cliente
   estrena estado: con cliente el avatar se enciende y el email ya no se muestra.
   Ver ds/cart.css y sus notas 8-10. */
/*** LIGHTBOXES DE ORDEN — NO son del carrito, estaban mal archivadas ***/
/* Vivían dentro del bloque CART BODY y F2g.2 se las llevó por delante al mudarlo:
   yo aserté lo que MOVÍA y no lo que dejaba atrás. Las cazó el dueño mirando la
   pantalla. Son de `orderCompleteLightbox.php` y `orderDetails.php` —el ticket y
   el detalle de una orden ya creada—, así que vuelven aquí y su casa es F2g.3
   (el checkout), no ds/cart.css. */
/* MOVIDAS A ds/checkout.css el 2026-08-07. `.order_customer` y `.send_ticket_email`
   son de la tarjeta de «Orden Registrada», y este mismo bloque ya decía que su casa
   era F2g.3 — el checkout. Lo que las movió no fue el orden: el espejo midió esa
   tarjeta por primera vez (para verla hay que VENDER) y el icono del recibo por
   email salía en React sin píldora, sin color y sin relleno, siendo la ÚNICA puerta
   del producto a mandar un recibo. Ver ds/checkout.css. */

/*** PRODUCT EDIT ***/
.optional_products_box {
	padding: 15px;
	background: var(--neutral-150);
	border-radius: 5px;
}

/*** ORDERS — los tags se fueron a ds/badge.css ***/
/* Aquí había un SEGUNDO mapeo de estado->color (completed / on-hold / refunded /
   fail / blueColor600), 2200 líneas por debajo del primero y decidiendo lo mismo.
   Nadie que leyera el bloque TAGS habría sabido que este existía. Los dos están
   ahora en juicy_tone_for_status(). */

/*** CUSTOMERS — MOVIDO AL DESIGN SYSTEM ***/
/* `.customer_result` y sus tres hijos viven ahora en `ds/pos.css`. Se MOVIERON, no se
   copiaron: sus únicos emisores son los dos lightboxes de la caja (buscar cupón y buscar
   cliente), el front nuevo no importa esta hoja, y sin ellas la fila de un cupón salía en
   React SIN la caja gris del DS — fondo transparente, sin radio, sin relleno y 30px más
   baja. Medido con el espejo el 2026-08-07; el porqué está en ds/pos.css nota 5. */

/*** PRODUCTS — MOVIDO AL DESIGN SYSTEM ***/
/* `#product_title_input` (y su `::placeholder`) viven ahora en `ds/field-types.css`. Se movieron,
   NO se copiaron: el front nuevo no importa esta hoja, y sin ellas el campo de nombre salía en
   React a 12px normales donde el producto lo pinta a 18px en negrita. Medido: 3 regiones (el mismo
   input en reposo, sucio e inválido) en `/puntos-de-venta/editar`. Lo comparten el editor de
   producto y el de punto de venta, así que el arreglo vale para los dos. */

/*** TOUCH DEVICES -> ds/sidebar.css ***/
/* Todo este bloque era la barra: la copia TÁCTIL de la receta de expandir, el
   `display:inline-flex` del toggle, y un parche que cancelaba el hover devolviendo
   la barra a su ancho de riel. Ese parche ya no hace falta:
   con el disparador gateado en `(hover:hover) and (pointer:fine)`, en un puntero
   grueso el hover no enciende nada y no hay nada que deshacer. */


/*** TABLETS ***/

/*** MOBILE ***/
@media (max-width: 768px) {
	/* El padding de móvil de #dashboard_page_content se fue con su regla base a
	   ds/sidebar.css (lo necesita también el front nuevo). */
	/* El scroll horizontal de la tabla en móvil se fue a ds/archive.css: es el
	   componente de la archive y lo necesita también el front nuevo. */
}

/* ============================================================
   DASHBOARD HOME — MOVIDA AL DESIGN SYSTEM.
   La rejilla del resumen (`.dashboard_home`, `.dash_kpis`,
   `.dash_main_row`, `.dash_chart_card`, `.dash_lowstock_card` y los
   dos realces de celda) vive ahora en `assets/css/ds/dashboard.css`.
   Se MOVIÓ, no se copió: el front nuevo NO importa esta hoja, y sin
   la rejilla la pantalla de React salía con los cuatro KPIs en
   columna. Quinta vez del mismo modo de fallo.

   Y se fueron BORRADAS, no mudadas, `.dash_header`, `.dash_header h1`
   y `.dash_subtitle`: cero emisores en todo el repo — el bloque usa
   `.page_header` y `.page_header_subtitle`. Es el S-1 del doc 37.
   ============================================================ */

/* ============================================================
   AJUSTES > GENERALES — referencia de horas: MOVIDA AL DESIGN SYSTEM.
   Las reglas de `.juicy_timezone_reference` viven ahora en
   `assets/css/ds/field-types.css`. Se movieron, NO se copiaron: el
   front nuevo NO importa esta hoja, y esa caja es un campo `html` del
   formulario de Ajustes Generales, que ya cruza a React. Mientras la
   única definición viviera aquí, salía sin separación, a 12px del
   navegador y con los dos <code> sin fondo. Es lo mismo que pasó con
   `.avatar` al cruzar propinas y con `.text-red` al cruzar
   registradoras.
   ============================================================ */


/*** SIDEBAR ALWAYS OPEN IN BIG SCREENS -> ds/sidebar.css ***/
/* Era la TERCERA copia de la receta de expandir. Ahora son dos líneas allá:
   `--sidebar-open: 1` y `--sidebar-reserved: var(--sidebar-panel)`. Lo segundo
   arregla de paso un bug real: el lightbox se quedaba en 70 mientras la barra
   medía 230. Ver ds/sidebar.css nota 4. */


/*** NOTIFICATIONS (campana del header — U3) ***/
/* NOTIFICACIONES -> ds/notifications.css (0.9.242). La CAMPANA y su badge ya se habían
   mudado a ds/header.css en 2026-07-27; ahora se va la CAJA con ellos, por la misma razón:
   el front nuevo no importa main.css, y la campana de React necesita estas reglas para que
   la caja tenga ancho, scroll, separadores y el atenuado de "ya leida".
   Al mudarlas se resolvieron DOS alias que declara ESTA hoja y el DS no: --info-600 y
   --error-600. Alla van como sus primitivos (--blue-600 / --red-600), que es el mismo valor;
   copiarlos tal cual habria dejado tres `color:` cayendose en silencio en el front. */

/* El margen del resumen de costo/margen se fue a `ds/table.css`, con el resto de su bloque (el
   `> h4` ya vivía allí). Lo pidió la paridad del editor de producto: el front NO importa main.css,
   así que su pestaña de Costos salía 20px más corta —los 6+14 de este margen— y era la única
   diferencia real de esa pantalla. */

/* Campo presente en el DOM pero invisible. Lo usa el selector "Tipo de producto"
   cuando el vertical solo ofrece un tipo: el motor de `logic` de gw-fields necesita
   el wrapper (data-wrapper-id) para resolver el input, y un campo `hidden` no lo emite. */
.juicy_field_hidden{ display: none; }
