/* css/glian-design-system.css — FUENTE ÚNICA de los tokens de diseño de Glian.
 *
 * Referencia y reglas de uso: DESIGN_SYSTEM.md (raíz del monorepo). Léelo antes de añadir o
 * cambiar un token.
 *
 * Qué es este archivo HOY:
 *  · Variables en :root + clases de rol tipográfico (`.glian-*`), iconografía (`.g-icon`),
 *    botones (`.g-btn`, `.g-icon-btn`, `.g-segmented`) y estructura de página (`.g-page`,
 *    `.g-page-header`, `.g-tabs`, `.g-card`, `.g-field`, `.g-check`, `.g-notice`), al final. Ningún selector de elemento →
 *    cargarlo no cambia NADA de lo que se ve: solo cambia lo que use una de esas clases a
 *    propósito. Las pantallas siguen con sus valores escritos a mano hasta que se migren una
 *    por una.
 *  · Los valores salen de la interfaz profesional ACTUAL (expedix.js `--exp-*`, los `:root` de
 *    index/pacientes/agenda y el `--sh` de Clinimetrix), no de los documentos de marca viejos.
 *  · Inter es la fuente OFICIAL de la interfaz (oct-2026). Hoy se ve en Agenda, Pacientes y la
 *    portada de Clinimetrix, que la piden con `.glian-font-ui`; el resto sigue en Hanken Grotesk
 *    (legacy) hasta que se migre pantalla por pantalla.
 *
 * Cómo llega a las páginas: `js/expedix.js` lo inyecta una sola vez (ensureDesignSystem), así
 * que lo tiene toda página que cargue el armazón — Expedix, Clinimetrix profesional y Recursos
 * profesional. Una página puede además enlazarlo en su <head> (recomendado al migrarla, para
 * que no haya destello); el inyector detecta el <link> y no lo duplica.
 *
 * Vive en la raíz de Expedix (/css/…) a propósito: el armado (scripts/unificar.mjs) deja sin
 * prefijo lo que un módulo anidado NO tiene y la raíz sí, así que /clinimetrix, /formx y
 * /recursos lo piden con la misma ruta. Ningún módulo debe crear su propia carpeta /css/.
 *
 * Nombres: siempre `--glian-<grupo>-<nombre>`. `.g-*` y `--glian-*` son SOLO de este sistema
 * (DESIGN_SYSTEM.md §2.1): un módulo usa su propio prefijo, y scripts/check-namespace.mjs lo revisa.
 */

/* Inter (fuente oficial). Un solo archivo variable 400–700: los pesos de los tokens.
 * Mecanismo PROVISIONAL: antes de migrar todo Glian a Inter se evalúa una carga más eficiente
 * (DESIGN_SYSTEM.md §4.6); no se cambia mientras tanto.
 * Ojo: CSS exige que @import sea la PRIMERA regla del archivo. El navegador solo descarga la
 * fuente en una página que la use; en las demás cuesta únicamente esta hoja de Google (pocos
 * KB). La CSP global ya permite fonts.googleapis.com (style-src) y fonts.gstatic.com (font-src).
 * Un peso pedido de más (800/900, que el CSS viejo usa mucho) se pinta con 700. */
@import url("https://fonts.googleapis.com/css2?family=Inter:wght@400..700&display=swap");

:root {
  /* ── Marca ───────────────────────────────────────────────────────────────
   * primary  = el cian de Glian: rellenos, iconos, bordes de lo seleccionado, foco.
   * text     = el mismo cian, oscurecido para LETRA (enlaces, navegación activa): #0891b2
   *            sobre blanco da 3.68:1 y no alcanza AA; #0e7490 da 5.36:1.
   * strong   = el navy de Glian (final del degradado, superficies oscuras).
   * gradient = el botón principal tal como se ve hoy en todo Expedix. */
  --glian-brand-primary: #0891b2;
  --glian-brand-primary-hover: #0e7490;
  --glian-brand-primary-active: #155e75;
  --glian-brand-soft: #ecfeff;
  --glian-brand-soft-border: #a5f3fc;
  --glian-brand-text: #0e7490;
  --glian-brand-strong: #123b44;
  --glian-brand-gradient: linear-gradient(135deg, #0891b2, #123b44);

  /* ── Acción ──────────────────────────────────────────────────────────────────
   * brand-primary es IDENTIDAD (color de marca: iconos, bordes de lo seleccionado, foco).
   * action-primary es una SUPERFICIE INTERACTIVA con texto blanco encima: debe cumplir AA (≥4.5:1)
   * con --glian-text-inverse. Son alias de la escala de marca, no colores nuevos. */
  --glian-action-primary: var(--glian-brand-primary-hover);          /* #0e7490 · 5.36:1 con blanco */
  --glian-action-primary-hover: var(--glian-brand-primary-active);   /* #155e75 · 7.27:1 */
  --glian-action-primary-active: var(--glian-brand-strong);          /* #123b44 · 12.1:1 */

  /* ── Superficies ───────────────────────────────────────────────────────── */
  --glian-bg-page: #f6f8fa;
  --glian-bg-surface: #ffffff;
  --glian-bg-subtle: #f8fafc;
  --glian-bg-backdrop: rgba(15, 23, 42, .55);

  /* ── Texto ─────────────────────────────────────────────────────────────────
   * tertiary sobre --glian-bg-page queda en 4.47:1: úsalo sobre superficie blanca.
   * muted (2.56:1) es SOLO para placeholder y deshabilitado, nunca para información. */
  --glian-text-primary: #123b44;
  --glian-text-secondary: #475569;
  --glian-text-tertiary: #64748b;
  --glian-text-muted: #94a3b8;
  --glian-text-inverse: #ffffff;
  --glian-text-link: var(--glian-brand-text);

  /* ── Bordes ────────────────────────────────────────────────────────────── */
  --glian-border: #e2e8f0;
  --glian-border-strong: #cbd5e1;
  --glian-border-focus: var(--glian-brand-primary);
  /* Borde de un CONTROL (campo, casilla): lo que permite ver que ahí se escribe o se marca. WCAG 1.4.11
   * pide 3:1 contra lo que lo rodea; --glian-border-strong da 1.48:1 sobre blanco y no alcanza. Es el
   * gris neutro más claro que pasa en todas las superficies: 3.37:1 sobre surface, 3.22 sobre subtle,
   * 3.16 sobre bg-page y 3.05 sobre el #f0f4f8 heredado de Configuración. SOLO para controles:
   * tarjetas, tablas y separadores siguen con --glian-border. */
  --glian-control-border: #7f8da2;

  /* ── Estados semánticos ────────────────────────────────────────────────────
   * <estado>       relleno, icono, borde, punto de estado.
   * <estado>-soft  fondo de chip, aviso o fila.
   * <estado>-text  letra sobre <estado>-soft (todas ≥ 4.5:1). Donde el color base ya pasa,
   *                -text es el mismo color. */
  --glian-info: #0369a1;
  --glian-info-soft: #e0f2fe;
  --glian-info-text: #0369a1;

  --glian-success: #059669;
  --glian-success-soft: #ecfdf5;
  --glian-success-text: #047857;

  --glian-warning: #b45309;
  --glian-warning-soft: #fffbeb;
  --glian-warning-text: #b45309;

  --glian-danger: #dc2626;
  --glian-danger-soft: #fef2f2;
  --glian-danger-text: #b91c1c;

  --glian-neutral: #64748b;
  --glian-neutral-soft: #f1f5f9;
  --glian-neutral-text: #475569;

  /* ── Tipografía ────────────────────────────────────────────────────────────
   * --glian-font-ui (Inter) es la fuente OFICIAL; se carga arriba (@import). Hanken Grotesk va
   * de respaldo: si Inter no llegara, la pantalla se ve como antes y no con la del sistema. */
  --glian-font-ui: "Inter", "Hanken Grotesk", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --glian-font-mono: ui-monospace, SFMono-Regular, Menlo, monospace;

  --glian-text-page-title: 26px;
  --glian-text-section-title: 18px;
  --glian-text-card-title: 15px;
  --glian-text-body: 14px;
  --glian-text-small: 13px;
  --glian-text-caption: 12px;
  --glian-text-button: 14px;
  /* EXCEPCIÓN, no un paso de la escala: SOLO metadata secundaria (hora, contador) dentro de un
   * elemento .glian-dense. Prohibido para texto principal, etiquetas y botones. Existe porque la
   * Agenda semanal lo demostró midiendo (DESIGN_SYSTEM.md §4.4). */
  --glian-text-dense-meta: 11px;

  --glian-weight-regular: 400;
  --glian-weight-medium: 500;
  --glian-weight-semibold: 600;
  --glian-weight-bold: 700;

  --glian-leading-tight: 1.25;
  --glian-leading-normal: 1.5;
  --glian-leading-dense: 1.2;   /* solo para el rol .glian-dense */

  /* Tracking de títulos. Inter está dibujada para texto de ~14px: a 18–26px se ve suelta si no
   * se cierra un poco (es la curva que recomienda su autor: ≈ −0.02em a 26px, −0.01em a 15–18). */
  --glian-tracking-tight: -0.02em;
  --glian-tracking-snug: -0.01em;

  /* ── Espaciado (base 4px) ──────────────────────────────────────────────── */
  --glian-space-1: 4px;
  --glian-space-2: 8px;
  --glian-space-3: 12px;
  --glian-space-4: 16px;
  --glian-space-5: 20px;
  --glian-space-6: 24px;
  --glian-space-8: 32px;
  --glian-space-10: 40px;
  --glian-space-12: 48px;

  /* ── Radios ────────────────────────────────────────────────────────────── */
  --glian-radius-sm: 6px;
  --glian-radius-md: 10px;
  --glian-radius-lg: 14px;
  --glian-radius-xl: 18px;
  --glian-radius-pill: 999px;

  /* ── Sombras ───────────────────────────────────────────────────────────────
   * sm      superficies apenas elevadas (tarjetas). Es el `--sh` de Clinimetrix/index.
   * md      lo que flota sobre el contenido (menú desplegable, popover).
   * overlay modal, panel lateral, paleta de comandos. Es la sombra de modal más repetida. */
  --glian-shadow-none: none;
  --glian-shadow-sm: 0 1px 2px rgba(18, 59, 68, .05), 0 4px 14px rgba(18, 59, 68, .05);
  --glian-shadow-md: 0 8px 24px rgba(18, 59, 68, .14);
  --glian-shadow-overlay: 0 20px 60px rgba(0, 0, 0, .30);

  /* Foco: el halo de los campos va JUNTO con `border-color: var(--glian-border-focus)`
   * (solo el halo, a .12, no se distingue). Botones y enlaces usan el contorno. */
  --glian-focus-ring: 0 0 0 3px rgba(8, 145, 178, .12);
  --glian-focus-outline: 2px solid var(--glian-brand-primary);

  /* ── Iconografía (DESIGN_SYSTEM.md §10) ──────────────────────────────────────
   * Geometría: css/glian-icons.svg. Tamaño: estos tokens vía .g-icon--*. Color: currentColor.
   * xs (12px) es SOLO para superficies densas (Agenda): no es un tamaño normal de controles. */
  --glian-icon-xs: 12px;
  --glian-icon-sm: 16px;
  --glian-icon-md: 18px;
  --glian-icon-lg: 20px;
  --glian-icon-xl: 24px;
  --glian-icon-stroke: 2;

  /* ── Controles (DESIGN_SYSTEM.md §11) ────────────────────────────────────────
   * Alto de todo control interactivo: botones, botones de icono, controles segmentados (y, más
   * adelante, campos). SOLO dos tamaños. 36px no existe en la escala de espaciado; por eso estos
   * dos tokens propios, que comparten todos los controles para alinearse en una misma fila. */
  --glian-control-sm: 36px;
  --glian-control-md: 40px;
  /* Ancho de la paleta de comandos en escritorio (§15); en un teléfono manda el ancho de la pantalla. */
  --glian-command-width: 600px;

  /* ── Página (DESIGN_SYSTEM.md §19) ───────────────────────────────────────────
   * Ancho máximo de .g-page, con su relleno incluido. Dos medidas y no más: las pantallas usaban 19
   * anchos distintos, pero se agrupan en dos familias. page-width (1400) es el de 28 pantallas de
   * datos (Agenda, Pacientes, Clinimetrix); page-width-narrow (960) es el de formularios y
   * configuración, que hoy viven entre 720 y 980. */
  --glian-page-width: 1400px;
  --glian-page-width-narrow: 960px;

  /* ── Armazón: barra superior global (DESIGN_SYSTEM.md §16) ───────────────────
   * Alto de la barra (48px, el de la escala) y ancho del disparador de búsqueda en escritorio. */
  --glian-topbar-h: var(--glian-space-12);
  --glian-topbar-search-w: 360px;
  /* Desde dónde se pega lo «sticky» de una página. 0 aquí y el alto de la barra solo cuando la
   * página tiene barra (html.has-topbar, abajo): una página de documento o una vista embebida
   * en un marco no tiene barra, y sus sticky deben quedarse arriba del todo. */
  --glian-sticky-top: 0px;

  /* ── Superficies públicas (DESIGN_SYSTEM.md §18) ───────────────────────────────
   * Lo que abre un paciente (agenda pública, recursos). Una sola columna, del mismo ancho en todas;
   * zona táctil mínima de 44px (no es un tercer tamaño de botón profesional: solo existe aquí) y el
   * botón principal a 48px. El texto corrido va a 15px (el paso card-title de la escala): se lee en
   * un teléfono. Los campos a 16px: con menos, Safari en iPhone hace zoom al enfocarlos. */
  --glian-public-width: 480px;
  --glian-public-touch: 44px;
  --glian-public-cta-h: 48px;
  --glian-public-text: var(--glian-text-card-title);
  --glian-public-input: 16px;

  /* ── Movimiento ────────────────────────────────────────────────────────── */
  --glian-duration-fast: 120ms;
  --glian-duration-normal: 180ms;
  --glian-ease-standard: cubic-bezier(.2, 0, 0, 1);
  --glian-ease-enter: cubic-bezier(0, 0, .2, 1);
  --glian-ease-exit: cubic-bezier(.4, 0, 1, 1);

  /* ── Capas (z-index) ───────────────────────────────────────────────────────
   * Orden: base < sticky < armazón < dropdown < popover < modal < toast < command.
   * Los valores conviven con las capas viejas que siguen en pie (ver DESIGN_SYSTEM.md):
   *  · sticky (30) queda DEBAJO del menú lateral (45–80): en móvil el menú abierto lo cubre.
   *  · modal (1500) queda ENCIMA de los modales viejos (1000–1400): un diálogo nuevo abierto
   *    desde uno viejo no queda escondido.
   *  · toast (6000) iguala a Exp.toast: el aviso se ve aunque haya un modal abierto. */
  --glian-z-base: 0;
  --glian-z-sticky: 30;
  --glian-z-shell: 50;
  --glian-z-dropdown: 300;
  --glian-z-popover: 400;
  --glian-z-modal-backdrop: 1500;
  --glian-z-modal: 1510;
  --glian-z-toast: 6000;
  --glian-z-command: 7000;
}

/* Con barra superior —expedix.js pone html.has-topbar ANTES del primer pintado (§16)— lo sticky
 * de la página empieza debajo de ella: `top: calc(var(--glian-sticky-top) + Npx)`. */
html.has-topbar { --glian-sticky-top: var(--glian-topbar-h); scroll-padding-top: var(--glian-sticky-top); }
html.has-topbar body { padding-top: var(--glian-topbar-h); }

/* Movimiento reducido: los componentes que usen los tokens de duración se vuelven instantáneos.
 * No afecta a nada que hoy escriba sus duraciones a mano. */
@media (prefers-reduced-motion: reduce) {
  :root {
    --glian-duration-fast: 0ms;
    --glian-duration-normal: 0ms;
  }
}

/* ── Tipografía: fuente y roles ───────────────────────────────────────────────────────────────
 * .glian-font-ui pone Inter a un CONTENEDOR (la zona de contenido de una pantalla); todo lo de
 * adentro la hereda. Va en el contenedor y no en <body> para no tocar el menú lateral ni los
 * modales, que viven fuera de él y siguen en Hanken mientras no se migren.
 *
 * Los roles fijan SOLO tamaño, peso, interlineado y tracking:
 *  · no fijan la fuente (la pone el contenedor), así un rol en una pantalla sin migrar no mezcla
 *    dos fuentes;
 *  · no fijan color (lo pone el componente con --glian-text-*), así aplicar un rol nunca cambia
 *    el color de un texto.
 * Una regla vieja de la página con la misma especificidad gana (este archivo va antes): al
 * aplicar un rol, quita font-size/font-weight de la regla vieja de ese elemento.
 *
 *   rol              tamaño  peso  uso
 *   page-title       26      600   título de la pantalla (uno por pantalla)
 *   page-subtitle    14      400   la línea que lo explica, debajo del título
 *   section-title    18      600   título de sección
 *   card-title       15      600   título de tarjeta, panel o modal
 *   body             14      400   texto de lectura
 *   small            13      400   apoyo, metadatos
 *   caption          12      400   lo más pequeño permitido
 *   label            13      500   etiqueta de campo o de grupo
 *   dense            12      600   SOLO superficies de alta densidad (ver abajo)
 *   dense-meta       11      400   SOLO metadata secundaria dentro de lo denso (token, sin clase)
 *   (botones: 14/600 con --glian-text-button; llegan con el componente de botón) */
.glian-font-ui { font-family: var(--glian-font-ui); }

.glian-page-title,
.g-page-header__title {
  font-size: var(--glian-text-page-title);
  font-weight: var(--glian-weight-semibold);
  line-height: var(--glian-leading-tight);
  letter-spacing: var(--glian-tracking-tight);
}
.glian-page-subtitle,
.g-page-header__subtitle {
  font-size: var(--glian-text-body);
  font-weight: var(--glian-weight-regular);
  line-height: var(--glian-leading-normal);
}
.glian-section-title {
  font-size: var(--glian-text-section-title);
  font-weight: var(--glian-weight-semibold);
  line-height: var(--glian-leading-tight);
  letter-spacing: var(--glian-tracking-snug);
}
.glian-card-title,
.g-card__title {
  font-size: var(--glian-text-card-title);
  font-weight: var(--glian-weight-semibold);
  line-height: var(--glian-leading-tight);
  letter-spacing: var(--glian-tracking-snug);
}
.glian-body {
  font-size: var(--glian-text-body);
  font-weight: var(--glian-weight-regular);
  line-height: var(--glian-leading-normal);
}
.glian-small {
  font-size: var(--glian-text-small);
  font-weight: var(--glian-weight-regular);
  line-height: var(--glian-leading-normal);
}
.glian-caption {
  font-size: var(--glian-text-caption);
  font-weight: var(--glian-weight-regular);
  line-height: var(--glian-leading-normal);
}
.glian-label,
.g-field__label {
  font-size: var(--glian-text-small);
  font-weight: var(--glian-weight-medium);
  line-height: var(--glian-leading-tight);
}

/* Rol DENSO: citas de calendario, tablas muy densas, metadata operacional compacta. NO es el
 * estilo normal del sistema: úsalo solo donde el espacio es fijo y cada carácter cuenta.
 * Inter es más ancha que Hanken (≈ 6–10 % en nombres, 12–14 % en dígitos a 12.5/700); con
 * 12/600 y −0.01em recupera casi todo ese ancho sin cambiar el tamaño del contenedor.
 * Dentro de un elemento denso, el dato principal (p. ej. el nombre del paciente) conserva
 * semibold; los símbolos bajan a --glian-weight-medium, y la metadata secundaria (la hora) usa
 * la excepción --glian-text-dense-meta (11px) con --glian-weight-regular. Sin 700 dentro de lo
 * denso. */
.glian-dense {
  font-size: var(--glian-text-caption);
  font-weight: var(--glian-weight-semibold);
  line-height: var(--glian-leading-dense);
  letter-spacing: var(--glian-tracking-snug);
}

/* ── Iconografía (DESIGN_SYSTEM.md §10) ───────────────────────────────────────────────────────
 * Un icono = <svg class="g-icon"><use href="/css/glian-icons.svg#nombre"/></svg>, o Glian.icon().
 * El sprite solo trae geometría: trazo, relleno y color se ponen AQUÍ y llegan a la geometría por
 * herencia (el árbol de <use> hereda del <svg>). No lleva color propio: toma el del texto. */
.g-icon {
  width: var(--glian-icon-md);
  height: var(--glian-icon-md);
  fill: none;
  stroke: currentColor;
  stroke-width: var(--glian-icon-stroke);
  stroke-linecap: round;
  stroke-linejoin: round;
  flex-shrink: 0;
  vertical-align: middle;
  overflow: visible;
}
.g-icon--xs { width: var(--glian-icon-xs); height: var(--glian-icon-xs); }   /* solo superficies densas */
.g-icon--sm { width: var(--glian-icon-sm); height: var(--glian-icon-sm); }   /* acciones compactas, tablas */
.g-icon--md { width: var(--glian-icon-md); height: var(--glian-icon-md); }   /* botones (por omisión) */
.g-icon--lg { width: var(--glian-icon-lg); height: var(--glian-icon-lg); }   /* navegación, menú lateral */
.g-icon--xl { width: var(--glian-icon-xl); height: var(--glian-icon-xl); }   /* indicadores destacados */

/* ── Botones (DESIGN_SYSTEM.md §11) ───────────────────────────────────────────────────────────
 * UN solo sistema: .g-btn (con texto), .g-icon-btn (solo icono) y .g-segmented (opción excluyente).
 * Comparten alto (--glian-control-sm/md), radio, transiciones, foco, deshabilitado y la regla de
 * no usar sombras. Variante obligatoria en .g-btn: --primary, --secondary, --ghost, --danger o
 * --danger-secondary.
 * Tamaños: --sm (36px) y --md (40px, por omisión). El icono lo dimensiona el BOTÓN: 16px en sm y
 * 18px en md, aunque Glian.icon() se haya llamado con otro tamaño. */
.g-btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--glian-space-2);
  height: var(--glian-control-md);
  padding: 0 var(--glian-space-4);
  margin: 0;
  border: 1px solid transparent;
  border-radius: var(--glian-radius-md);
  background: transparent;
  color: var(--glian-text-primary);
  font-family: var(--glian-font-ui);
  font-size: var(--glian-text-button);
  font-weight: var(--glian-weight-semibold);
  line-height: var(--glian-leading-tight);
  white-space: nowrap;
  text-decoration: none;
  vertical-align: middle;
  cursor: pointer;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
}
.g-btn .g-icon { width: var(--glian-icon-md); height: var(--glian-icon-md); }
.g-btn--md { height: var(--glian-control-md); padding: 0 var(--glian-space-4); }
.g-btn--sm { height: var(--glian-control-sm); padding: 0 var(--glian-space-3); }
.g-btn--sm .g-icon { width: var(--glian-icon-sm); height: var(--glian-icon-sm); }

/* Contador dentro de un botón (icono + texto + contador: «Espera 17») o de una pestaña (§19.3).
 * Solo forma y alineación; los colores con significado llegan con el sistema de contadores. */
.g-btn__badge,
.g-tabs__count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: var(--glian-space-5);
  height: var(--glian-space-5);
  padding: 0 var(--glian-space-1);
  border-radius: var(--glian-radius-pill);
  background: var(--glian-neutral-soft);
  color: var(--glian-text-secondary);
  font-size: var(--glian-text-caption);
  font-weight: var(--glian-weight-semibold);
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

/* Primary: la acción dominante del contexto (idealmente UNA por pantalla, modal o tarjeta).
 * Usa --glian-action-primary*, no --glian-brand-primary: el blanco sobre #0891b2 da 3.68:1 (no
 * alcanza AA a 14px); la superficie de acción sí cumple. */
.g-btn--primary { background: var(--glian-action-primary); color: var(--glian-text-inverse); }
.g-btn--primary:hover:not(:disabled):not([aria-disabled="true"]) { background: var(--glian-action-primary-hover); }
.g-btn--primary:active:not(:disabled):not([aria-disabled="true"]) { background: var(--glian-action-primary-active); }

/* Secondary: importante pero subordinada a la primaria. */
.g-btn--secondary { background: var(--glian-bg-surface); border-color: var(--glian-border); color: var(--glian-text-primary); }
.g-btn--secondary:hover:not(:disabled):not([aria-disabled="true"]) { background: var(--glian-bg-subtle); border-color: var(--glian-border-strong); }
.g-btn--secondary:active:not(:disabled):not([aria-disabled="true"]) { background: var(--glian-neutral-soft); border-color: var(--glian-border-strong); }

/* Ghost: acciones frecuentes de menor jerarquía. Sin borde ni fondo hasta el hover. */
.g-btn--ghost { color: var(--glian-text-secondary); }
.g-btn--ghost:hover:not(:disabled):not([aria-disabled="true"]) { background: var(--glian-neutral-soft); color: var(--glian-text-primary); }
.g-btn--ghost:active:not(:disabled):not([aria-disabled="true"]) { background: var(--glian-border); color: var(--glian-text-primary); }

/* Seleccionado (aria-pressed="true"): un modo, filtro o vista que SIGUE activo («ver canceladas»).
 * No es una variante: es un estado de Ghost y Secondary, con el lenguaje de selección del sistema
 * (el de la opción activa de .g-segmented). Hover y presionado duran lo que el puntero; esto dura
 * hasta que se vuelve a tocar. Encima del seleccionado, el hover solo marca el borde: el botón no
 * deja de verse seleccionado ni salta al gris del hover normal. Nunca Primary, Danger ni sombra. */
.g-btn--ghost[aria-pressed="true"],
.g-btn--secondary[aria-pressed="true"] { background: var(--glian-brand-soft); border-color: var(--glian-brand-soft-border); color: var(--glian-brand-text); }
.g-btn--ghost[aria-pressed="true"]:hover:not(:disabled):not([aria-disabled="true"]),
.g-btn--ghost[aria-pressed="true"]:active:not(:disabled):not([aria-disabled="true"]),
.g-btn--secondary[aria-pressed="true"]:hover:not(:disabled):not([aria-disabled="true"]),
.g-btn--secondary[aria-pressed="true"]:active:not(:disabled):not([aria-disabled="true"]) { background: var(--glian-brand-soft); border-color: var(--glian-brand-primary); color: var(--glian-brand-text); }

/* Danger: SOLO acciones destructivas o graves (borrar, anular). Nunca para «canceladas»,
 * pendientes, cantidades ni navegación. Solo tokens de peligro: --glian-danger (4.83:1 con blanco)
 * y, en hover y presionado, --glian-danger-text (5.91:1). No hay un tercer tono: comparten. */
.g-btn--danger { background: var(--glian-danger); color: var(--glian-text-inverse); }
.g-btn--danger:hover:not(:disabled):not([aria-disabled="true"]),
.g-btn--danger:active:not(:disabled):not([aria-disabled="true"]) { background: var(--glian-danger-text); }

/* Danger secondary: destructiva de énfasis bajo o medio (pidió la primera: «Quitar consultorio»).
 * Quita algo de un formulario que todavía se guarda o se descarta después, o abre la confirmación
 * de algo destructivo. El botón que borra o confirma YA sigue siendo Danger sólido. Superficie,
 * borde --glian-danger (4.83:1) y texto --glian-danger-text (6.47:1; 5.91:1 sobre el hover). Solo
 * tokens de peligro: el hover pone --glian-danger-soft y el presionado oscurece además el borde. */
.g-btn--danger-secondary { background: var(--glian-bg-surface); border-color: var(--glian-danger); color: var(--glian-danger-text); }
.g-btn--danger-secondary:hover:not(:disabled):not([aria-disabled="true"]) { background: var(--glian-danger-soft); }
.g-btn--danger-secondary:active:not(:disabled):not([aria-disabled="true"]) { background: var(--glian-danger-soft); border-color: var(--glian-danger-text); }

/* Preparado para «cargando» (sin implementar todavía): con aria-busy="true" el botón no admite
 * otro clic y conserva su ancho; el indicador visual llega después. */
.g-btn[aria-busy="true"] { cursor: progress; pointer-events: none; }

/* Botón que SOLO tiene icono. Lleva aria-label (el nombre va en el botón, no en el SVG) y, si la
 * acción no es evidente, title. Mismo alto que .g-btn (36px; --md 40px) para alinearse en una
 * fila, icono de 18px, y los estados de .g-btn--ghost. Su zona táctil llega 4px más allá por
 * cada lado (44/48px) con un ::after invisible que no ocupa sitio en el layout: deja al menos
 * --glian-space-2 entre dos de estos botones. Sin color propio: toma el del texto del contexto.
 * (El botón de contraer del menú lateral fija su propio tamaño de 32px.) */
.g-icon-btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: var(--glian-control-sm);
  height: var(--glian-control-sm);
  padding: 0;
  margin: 0;
  border: 1px solid transparent;
  border-radius: var(--glian-radius-md);
  background: transparent;
  color: inherit;
  font: inherit;
  line-height: 1;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.g-icon-btn--md { width: var(--glian-control-md); height: var(--glian-control-md); }
.g-icon-btn .g-icon { width: var(--glian-icon-md); height: var(--glian-icon-md); }
.g-icon-btn::after {
  content: "";
  position: absolute;
  inset: calc(var(--glian-space-1) * -1 - 1px);
}
.g-icon-btn:hover:not(:disabled):not([aria-disabled="true"]) { background: var(--glian-neutral-soft); }
.g-icon-btn:active:not(:disabled):not([aria-disabled="true"]) { background: var(--glian-border); }

/* Control segmentado: UNA opción activa entre varias excluyentes («Mes | Semana | Día»). No son
 * botones primarios: pista neutra; la activa con fondo suave de marca, borde de marca y texto de
 * marca (forma Y color, no solo color). Marca la activa con aria-pressed="true" (botones) o
 * aria-checked="true" (role="radio"); .is-active también vale. */
.g-segmented {
  display: inline-flex;
  align-items: stretch;
  height: var(--glian-control-sm);
  padding: var(--glian-space-1);
  border: 1px solid var(--glian-border);
  border-radius: var(--glian-radius-md);
  background: var(--glian-neutral-soft);
  vertical-align: middle;
}
.g-segmented--md { height: var(--glian-control-md); }
.g-segmented__item {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--glian-space-1);
  padding: 0 var(--glian-space-3);
  margin: 0;
  border: 1px solid transparent;
  border-radius: var(--glian-radius-sm);
  background: transparent;
  color: var(--glian-text-secondary);
  font-family: var(--glian-font-ui);
  font-size: var(--glian-text-button);
  font-weight: var(--glian-weight-medium);
  line-height: var(--glian-leading-tight);
  white-space: nowrap;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.g-segmented__item .g-icon { width: var(--glian-icon-sm); height: var(--glian-icon-sm); }
.g-segmented__item:hover:not(:disabled):not([aria-pressed="true"]):not([aria-checked="true"]):not(.is-active) { background: var(--glian-border); color: var(--glian-text-primary); }
.g-segmented__item[aria-pressed="true"],
.g-segmented__item[aria-checked="true"],
.g-segmented__item.is-active { background: var(--glian-brand-soft); border-color: var(--glian-brand-soft-border); color: var(--glian-brand-text); }

/* Comunes a TODO el sistema de botones: medida, transición, foco visible y deshabilitado.
 * border-box explícito: el alto debe ser 36/40px en cualquier página, aunque no fije box-sizing
 * (un <a> o un <div> miden content-box por omisión y el borde y el relleno se sumarían). */
.g-btn, .g-icon-btn, .g-segmented, .g-segmented__item { box-sizing: border-box; }
.g-btn, .g-icon-btn, .g-segmented__item {
  transition: background-color var(--glian-duration-fast) var(--glian-ease-standard),
              border-color var(--glian-duration-fast) var(--glian-ease-standard),
              color var(--glian-duration-fast) var(--glian-ease-standard);
}
.g-btn:focus-visible, .g-icon-btn:focus-visible, .g-segmented__item:focus-visible { outline: var(--glian-focus-outline); outline-offset: 2px; }
.g-btn:disabled, .g-btn[aria-disabled="true"],
.g-icon-btn:disabled, .g-icon-btn[aria-disabled="true"],
.g-segmented__item:disabled { opacity: .45; cursor: not-allowed; }
/* Zona táctil en pantallas táctiles, sin cambiar el tamaño en escritorio (área invisible ::after).
 * Un ::after absoluto se mide desde DENTRO del borde de 1px del control: cada inset suma ese 1px.
 *  · .g-btn (md, 40px) → 44px: 2px más arriba y abajo.
 *  · .g-btn--sm (36px) → 44px: 4px más arriba y abajo.
 *  · .g-segmented__item (26px; 30px en --md) → 44px (48px): cubre el relleno de la pista (4px) y su
 *    borde (1px) y sale 4px más, como .g-btn--sm. Solo en vertical: a los lados las opciones se
 *    tocan entre sí.
 *  · .g-icon-btn → 6px por lado (48px). */
@media (pointer: coarse) {
  .g-btn::after { content: ""; position: absolute; inset: calc(var(--glian-space-1) / -2 - 1px) 0; }
  .g-btn--sm::after { content: ""; position: absolute; inset: calc(var(--glian-space-1) * -1 - 1px) 0; }
  .g-segmented__item::after { content: ""; position: absolute; inset: calc(var(--glian-space-2) * -1 - 2px) 0; }
  .g-icon-btn::after { inset: calc(var(--glian-space-1) * -1.5 - 1px); }
}

/* ── Estructura de página (DESIGN_SYSTEM.md §19) ─────────────────────────────────────────────
 * Cinco primitivas (oleada 0A): .g-page (el contenedor), .g-page-header (título, subtítulo, volver y
 * acciones), .g-tabs (pestañas; --sub para el segundo nivel), .g-card (superficie) y .g-field
 * (etiqueta, control, ayuda y error; .g-field-grid para acomodarlos). Y lo que pidió el primer
 * consumidor real (Mi consultorio → Perfil): .g-check (casilla) y .g-notice (aviso). Puntos de corte: los del
 * armazón, 860px (menú lateral oculto) y 560px (teléfono). Ningún selector de elemento suelto:
 * solo cambia lo que usa una de estas clases a propósito. */

/* Página. Sustituye a .page-body/.container/.wrap y sus anchos locales. La barra superior ya
 * reservó su alto en el body (html.has-topbar): .g-page no la compensa. */
.g-page {
  box-sizing: border-box;
  width: 100%;
  max-width: var(--glian-page-width);
  margin: 0 auto;
  padding: var(--glian-space-6) var(--glian-space-6) var(--glian-space-10);
  font-family: var(--glian-font-ui);
  color: var(--glian-text-primary);
}
.g-page--narrow { max-width: var(--glian-page-width-narrow); }

/* Encabezado de página: lo principal (volver + título y subtítulo) a la izquierda y las acciones a
 * la derecha, alineadas arriba con el título. En el teléfono (≤560px) las acciones bajan. El lugar de
 * las acciones NO depende del largo del subtítulo (el subtítulo se parte en su columna), y el título
 * nunca se achica para caber. */
.g-page-header {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: start;
  gap: var(--glian-space-3) var(--glian-space-4);
  margin: 0 0 var(--glian-space-6);
  font-family: var(--glian-font-ui);
}
.g-page-header__main {
  display: flex;
  align-items: flex-start;
  gap: var(--glian-space-2);
  min-width: 0;
}
/* Volver: un .g-icon-btn (chevron-left + aria-label). Se centra con la PRIMERA línea del título,
 * no con el bloque título+subtítulo. */
.g-page-header__back {
  flex-shrink: 0;
  margin-top: calc((var(--glian-text-page-title) * var(--glian-leading-tight) - var(--glian-control-sm)) / 2);
  color: var(--glian-text-secondary);
}
.g-page-header__titles { min-width: 0; }
.g-page-header__title { margin: 0; color: var(--glian-text-primary); overflow-wrap: anywhere; }
.g-page-header__subtitle { margin: var(--glian-space-1) 0 0; color: var(--glian-text-secondary); }
.g-page-header__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: var(--glian-space-2);
}

/* Pestañas. Primer nivel: subrayado de marca bajo la activa sobre una línea gris. Segundo nivel
 * (--sub): el MISMO dibujo, más bajo y sin la línea gris completa, para que se lea subordinado. Muchas
 * opciones se DESPLAZAN de lado, nunca se parten en varios renglones. Activa: aria-selected="true"
 * (tabs en la misma página), aria-current="page" (enlaces entre páginas) o .is-active. */
.g-tabs {
  display: flex;
  flex-wrap: nowrap;
  gap: var(--glian-space-1);
  margin: 0 0 var(--glian-space-4);
  padding: 0;
  border-bottom: 1px solid var(--glian-border);
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scrollbar-width: thin;
  font-family: var(--glian-font-ui);
}
.g-tabs__item {
  position: relative;
  display: inline-flex;
  align-items: center;
  flex: none;
  gap: var(--glian-space-2);
  box-sizing: border-box;
  height: var(--glian-control-md);
  margin: 0 0 -1px;
  padding: 0 var(--glian-space-3);
  border: 0;
  border-bottom: 2px solid transparent;
  border-radius: var(--glian-radius-sm) var(--glian-radius-sm) 0 0;
  background: transparent;
  color: var(--glian-text-secondary);
  font-family: var(--glian-font-ui);
  font-size: var(--glian-text-button);
  font-weight: var(--glian-weight-medium);
  line-height: var(--glian-leading-tight);
  white-space: nowrap;
  text-decoration: none;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: color var(--glian-duration-fast) var(--glian-ease-standard),
              border-color var(--glian-duration-fast) var(--glian-ease-standard),
              background-color var(--glian-duration-fast) var(--glian-ease-standard);
}
.g-tabs__item .g-icon { width: var(--glian-icon-sm); height: var(--glian-icon-sm); }
.g-tabs__item:hover { color: var(--glian-text-primary); border-bottom-color: var(--glian-border-strong); }
.g-tabs__item[aria-selected="true"],
.g-tabs__item[aria-current="page"],
.g-tabs__item[aria-current="true"],
.g-tabs__item.is-active { color: var(--glian-brand-text); border-bottom-color: var(--glian-brand-primary); }
/* Dentro del contenedor que se desplaza, el contorno va hacia adentro: afuera lo recortaría. */
.g-tabs__item:focus-visible { outline: var(--glian-focus-outline); outline-offset: -2px; }
.g-tabs__item:disabled, .g-tabs__item[aria-disabled="true"] { opacity: .45; cursor: not-allowed; }
.g-tabs--sub { border-bottom: 0; }
/* Segundo nivel justo debajo del primero: 8px entre los dos, no los 16 de una sección. */
.g-tabs:not(.g-tabs--sub) + .g-tabs--sub { margin-top: calc(var(--glian-space-2) - var(--glian-space-4)); }
.g-tabs--sub .g-tabs__item { height: var(--glian-control-sm); margin-bottom: 0; padding: 0 var(--glian-space-2); font-size: var(--glian-text-small); }
/* Con ratón la barra de desplazamiento se ve (fina): sin ella, una pestaña escondida a la derecha no
 * se alcanza con la rueda. En pantallas táctiles se desliza con el dedo y se oculta. */
@media (pointer: coarse) {
  .g-tabs { scrollbar-width: none; }
  .g-tabs::-webkit-scrollbar { display: none; }
  .g-tabs__item { min-height: calc(var(--glian-control-md) + var(--glian-space-1)); }
}

/* Tarjeta: UNA familia (sustituye a .card, .panel, .rc-panel, .fx-card, .scale-card…). Plana: borde
 * y la sombra discreta de tarjeta, nada más. Las diferencias las pone el contenido, no variantes. */
.g-card {
  box-sizing: border-box;
  min-width: 0;
  background: var(--glian-bg-surface);
  border: 1px solid var(--glian-border);
  border-radius: var(--glian-radius-lg);
  box-shadow: var(--glian-shadow-sm);
  color: var(--glian-text-primary);
  font-family: var(--glian-font-ui);
}
.g-card__header {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--glian-space-2) var(--glian-space-3);
  padding: var(--glian-space-4) var(--glian-space-4) 0;
}
.g-card__title { margin: 0; color: var(--glian-text-primary); }
.g-card__body { padding: var(--glian-space-4); }
.g-card__header + .g-card__body { padding-top: var(--glian-space-3); }
.g-card__footer {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: var(--glian-space-2);
  padding: var(--glian-space-3) var(--glian-space-4);
  border-top: 1px solid var(--glian-border);
}

/* Campo: etiqueta (rol label), control, ayuda y error. El control lleva .g-field__control
 * (input, select, textarea o uno propio): los <input> sueltos de la página no cambian. 40px de alto;
 * 44px en pantallas táctiles. Foco oficial: borde de marca + halo. Error: aria-invalid="true" en el
 * control y el texto en .g-field__error, ligado con aria-describedby. */
.g-field {
  display: flex;
  flex-direction: column;
  gap: var(--glian-space-2);
  min-width: 0;
  font-family: var(--glian-font-ui);
}
.g-field__label { color: var(--glian-text-primary); }
.g-field__control {
  box-sizing: border-box;
  width: 100%;
  min-height: var(--glian-control-md);
  margin: 0;
  padding: var(--glian-space-2) var(--glian-space-3);
  border: 1px solid var(--glian-control-border);
  border-radius: var(--glian-radius-md);
  background: var(--glian-bg-surface);
  color: var(--glian-text-primary);
  font-family: var(--glian-font-ui);
  font-size: var(--glian-text-body);
  font-weight: var(--glian-weight-regular);
  line-height: var(--glian-leading-normal);
  transition: border-color var(--glian-duration-fast) var(--glian-ease-standard),
              box-shadow var(--glian-duration-fast) var(--glian-ease-standard);
}
.g-field__control::placeholder { color: var(--glian-text-muted); opacity: 1; }
.g-field__control:focus { outline: none; border-color: var(--glian-border-focus); box-shadow: var(--glian-focus-ring); }
.g-field__control[aria-invalid="true"] { border-color: var(--glian-danger); }
.g-field__control:disabled { background: var(--glian-bg-subtle); color: var(--glian-text-muted); cursor: not-allowed; }
textarea.g-field__control { min-height: calc(var(--glian-control-md) * 2); resize: vertical; }
/* El select se dibuja igual en todos los navegadores (Safari ignora alto y relleno del nativo): sin
 * apariencia propia y con el chevrón en el color del texto. */
select.g-field__control {
  appearance: none;
  -webkit-appearance: none;
  padding-right: var(--glian-space-8);
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%), linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: calc(100% - var(--glian-space-4)) 50%, calc(100% - var(--glian-space-3)) 50%;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
}
.g-field__help { margin: 0; color: var(--glian-text-tertiary); font-size: var(--glian-text-small); line-height: var(--glian-leading-normal); }
.g-field__error { margin: 0; color: var(--glian-danger-text); font-size: var(--glian-text-small); font-weight: var(--glian-weight-medium); line-height: var(--glian-leading-normal); }
.g-field__error:empty { display: none; }
@media (pointer: coarse) { .g-field__control { min-height: calc(var(--glian-control-md) + var(--glian-space-1)); } }
/* En un teléfono el campo va a 16px: con menos, Safari en iPhone hace zoom al enfocarlo (el mismo
 * motivo y el mismo token que en las superficies públicas, §18). */
@media (pointer: coarse) and (max-width: 560px) { .g-field__control { font-size: var(--glian-public-input); } }

/* Casilla (§19.6): una elección o confirmación DENTRO de un formulario, que se guarda con él. El
 * <input type="checkbox"> nativo va a la vista (accesible tal cual) con el color de marca al marcarse;
 * toda la fila es la etiqueta, así que se marca tocando el texto. Ayuda opcional debajo del texto. */
.g-check {
  display: flex;
  align-items: flex-start;
  gap: var(--glian-space-2);
  color: var(--glian-text-primary);
  font-family: var(--glian-font-ui);
  cursor: pointer;
}
.g-check__input {
  flex-shrink: 0;
  width: var(--glian-icon-md);
  height: var(--glian-icon-md);
  margin: calc((var(--glian-text-body) * var(--glian-leading-normal) - var(--glian-icon-md)) / 2) 0 0;
  accent-color: var(--glian-brand-primary);
  cursor: pointer;
}
.g-check__input:focus-visible { outline: var(--glian-focus-outline); outline-offset: 2px; }
.g-check__text { display: flex; flex-direction: column; gap: var(--glian-space-1); min-width: 0; }
.g-check__label { font-size: var(--glian-text-body); line-height: var(--glian-leading-normal); }
.g-check__help { color: var(--glian-text-tertiary); font-size: var(--glian-text-small); line-height: var(--glian-leading-normal); }
.g-check:has(.g-check__input:disabled) { color: var(--glian-text-muted); cursor: not-allowed; }
@media (pointer: coarse) { .g-check { min-height: calc(var(--glian-control-md) + var(--glian-space-1)); } }

/* Aviso en la página (§19.7): algo que la persona tiene que saber o decidir AHÍ, que se queda a la
 * vista (no es un toast). Dos tonos, cada uno con su consumidor: --warning (revisar o decidir) y
 * --danger (algo falló). Fondo y letra del estado semántico; el borde es el mismo color, rebajado.
 * Icono del sprite opcional al principio; acciones opcionales (botones .g-btn) en __actions. */
.g-notice {
  display: flex;
  align-items: flex-start;
  gap: var(--glian-space-2);
  padding: var(--glian-space-3) var(--glian-space-4);
  border: 1px solid transparent;
  border-radius: var(--glian-radius-md);
  font-family: var(--glian-font-ui);
  font-size: var(--glian-text-small);
  line-height: var(--glian-leading-normal);
}
.g-notice > .g-icon {
  width: var(--glian-icon-md);
  height: var(--glian-icon-md);
  margin-top: calc((var(--glian-text-small) * var(--glian-leading-normal) - var(--glian-icon-md)) / 2);
}
.g-notice__text { flex: 1 1 auto; min-width: 0; }
.g-notice__actions { display: flex; flex-wrap: wrap; gap: var(--glian-space-2); margin-top: var(--glian-space-2); }
.g-notice--warning {
  background: var(--glian-warning-soft);
  border-color: color-mix(in srgb, var(--glian-warning) 30%, transparent);
  color: var(--glian-warning-text);
}
.g-notice--danger {
  background: var(--glian-danger-soft);
  border-color: color-mix(in srgb, var(--glian-danger) 30%, transparent);
  color: var(--glian-danger-text);
}

/* Rejilla de campos: 2 o 3 columnas, y una sola en el teléfono. La de 3 baja a 2 sin menú lateral. */
.g-field-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--glian-space-4); }
.g-field-grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.g-field-grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }

@media (max-width: 860px) {
  .g-field-grid--3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 560px) {
  .g-page { padding: var(--glian-space-4) var(--glian-space-4) var(--glian-space-8); }
  .g-page-header { grid-template-columns: minmax(0, 1fr); margin-bottom: var(--glian-space-4); }
  .g-page-header__actions { justify-content: flex-start; }
  .g-field-grid--2, .g-field-grid--3 { grid-template-columns: minmax(0, 1fr); }
}
/* En papel: sin navegación ni acciones, y la página a todo el ancho de la hoja. */
@media print {
  .g-page { max-width: none; padding: 0; }
  .g-page-header__back, .g-page-header__actions, .g-tabs { display: none !important; }
  .g-card { box-shadow: none; }
}

/* ── Paleta de comandos (DESIGN_SYSTEM.md §15) ────────────────────────────────────────────────
 * UNA superficie modal para buscar y navegar (js/glian-command.js): fondo, panel, campo, lista
 * agrupada y estado. Por encima de todo (--glian-z-command). En escritorio mide
 * --glian-command-width; en un teléfono, el ancho de la pantalla menos --glian-space-4 por lado.
 * El campo va a 18px: con menos de 16px, Safari en iPhone/iPad hace zoom al enfocarlo. La opción
 * activa usa el lenguaje de selección del sistema (fondo brand-soft, texto brand-text). */
.g-command { position: fixed; inset: 0; z-index: var(--glian-z-command); font-family: var(--glian-font-ui); }
.g-command[hidden] { display: none; }
.g-command__fondo { position: absolute; inset: 0; background: var(--glian-bg-backdrop); }
.g-command__panel {
  position: absolute;
  top: max(var(--glian-space-4), 12vh);
  left: 50%;
  transform: translateX(-50%);
  box-sizing: border-box;
  width: min(var(--glian-command-width), calc(100vw - 2 * var(--glian-space-4)));
  max-height: calc(100vh - max(var(--glian-space-4), 12vh) - var(--glian-space-4));
  max-height: calc(100dvh - max(var(--glian-space-4), 12vh) - var(--glian-space-4));
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: var(--glian-bg-surface);
  border: 1px solid var(--glian-border);
  border-radius: var(--glian-radius-lg);
  box-shadow: var(--glian-shadow-overlay);
  color: var(--glian-text-primary);
}
.g-command__campo {
  display: flex;
  align-items: center;
  gap: var(--glian-space-3);
  flex-shrink: 0;
  padding: var(--glian-space-2) var(--glian-space-2) var(--glian-space-2) var(--glian-space-4);
  border-bottom: 1px solid var(--glian-border);
}
.g-command__lupa { width: var(--glian-icon-md); height: var(--glian-icon-md); flex-shrink: 0; color: var(--glian-text-tertiary); }
.g-command__input {
  flex: 1;
  min-width: 0;
  height: var(--glian-control-md);
  margin: 0;
  padding: 0;
  border: 0;
  outline: none;
  background: transparent;
  font-family: inherit;
  font-size: var(--glian-text-section-title);
  font-weight: var(--glian-weight-regular);
  color: var(--glian-text-primary);
}
.g-command__input::placeholder { color: var(--glian-text-tertiary); }
.g-command__cerrar { color: var(--glian-text-tertiary); }
.g-command__lista { flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding: var(--glian-space-2); }
.g-command__lista:empty { display: none; }
.g-command__grupo + .g-command__grupo { margin-top: var(--glian-space-2); }
.g-command__titulo {
  padding: var(--glian-space-2) var(--glian-space-3) var(--glian-space-1);
  font-size: var(--glian-text-caption);
  font-weight: var(--glian-weight-semibold);
  line-height: var(--glian-leading-tight);
  text-transform: uppercase;
  color: var(--glian-text-tertiary);
}
.g-command__op {
  display: flex;
  align-items: center;
  gap: var(--glian-space-3);
  min-height: var(--glian-control-md);
  padding: var(--glian-space-1) var(--glian-space-3);
  border-radius: var(--glian-radius-md);
  color: var(--glian-text-primary);
  cursor: pointer;
}
.g-command__op[aria-selected="true"] { background: var(--glian-brand-soft); color: var(--glian-brand-text); }
.g-command__ico { display: flex; flex-shrink: 0; color: var(--glian-text-tertiary); }
.g-command__op[aria-selected="true"] .g-command__ico { color: var(--glian-brand-text); }
.g-command__ico .g-icon { width: var(--glian-icon-md); height: var(--glian-icon-md); }
.g-command__txt { display: flex; flex-direction: column; min-width: 0; }
.g-command__op-titulo {
  overflow: hidden;
  font-size: var(--glian-text-body);
  font-weight: var(--glian-weight-medium);
  line-height: var(--glian-leading-tight);
  white-space: nowrap;
  text-overflow: ellipsis;
}
.g-command__op-sub { font-size: var(--glian-text-caption); line-height: var(--glian-leading-tight); color: var(--glian-text-tertiary); }
.g-command__estado { margin: 0; padding: var(--glian-space-4); font-size: var(--glian-text-small); color: var(--glian-text-tertiary); }
.g-command__nota {
  flex-shrink: 0;
  margin: 0;
  padding: var(--glian-space-2) var(--glian-space-4);
  border-top: 1px solid var(--glian-border);
  background: var(--glian-bg-subtle);
  font-size: var(--glian-text-caption);
  color: var(--glian-text-secondary);
}
/* Solo para lectores de pantalla (el número de resultados). */
.g-command__sr { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
@media (pointer: coarse) { .g-command__op { min-height: calc(var(--glian-control-sm) + var(--glian-space-2)); } }
/* Teléfono: arriba, con el margen seguro, para dejar sitio al teclado. */
@media (max-width: 560px) { .g-command__panel { top: var(--glian-space-4); } }

/* ── Menú desplegable (DESIGN_SYSTEM.md §17) ─────────────────────────────────────────────────
 * UN componente para todo menú de acciones: un botón (aria-haspopup="menu") y una lista
 * role="menu" con opciones .g-menu__item. El comportamiento (abrir, cerrar con Escape o al tocar
 * fuera, flechas, devolver el foco) lo da Glian.menu() en js/expedix.js. Nació como el «Más» de la
 * Agenda y se subió aquí cuando la barra superior necesitó el mismo (menú del usuario).
 * Se alinea a la derecha de su botón; .g-menu--izq lo alinea a la izquierda si no cabe. */
.g-menu {
  position: absolute;
  top: calc(100% + var(--glian-space-1));
  right: 0;
  z-index: var(--glian-z-dropdown);
  display: flex;
  flex-direction: column;
  min-width: 100%;
  padding: var(--glian-space-1);
  box-sizing: border-box;
  background: var(--glian-bg-surface);
  border: 1px solid var(--glian-border);
  border-radius: var(--glian-radius-md);
  box-shadow: var(--glian-shadow-md);
  font-family: var(--glian-font-ui);
}
.g-menu[hidden] { display: none; }
.g-menu.g-menu--izq { right: auto; left: 0; }
.g-menu__item {
  display: flex;
  align-items: center;
  gap: var(--glian-space-2);
  box-sizing: border-box;
  width: 100%;
  min-height: var(--glian-control-sm);
  margin: 0;
  padding: 0 var(--glian-space-3);
  border: 0;
  border-radius: var(--glian-radius-sm);
  background: transparent;
  color: var(--glian-text-primary);
  font-family: inherit;
  font-size: var(--glian-text-body);
  font-weight: var(--glian-weight-medium);
  line-height: var(--glian-leading-tight);
  text-align: left;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color var(--glian-duration-fast) var(--glian-ease-standard);
}
.g-menu__item .g-icon { width: var(--glian-icon-sm); height: var(--glian-icon-sm); flex-shrink: 0; color: var(--glian-text-secondary); }
.g-menu__item .g-btn__badge { margin-left: auto; }
.g-menu__item:hover, .g-menu__item:focus-visible { background: var(--glian-neutral-soft); }
.g-menu__item:focus-visible { outline: var(--glian-focus-outline); outline-offset: -2px; }
.g-menu__sep { height: 1px; margin: var(--glian-space-1) 0; background: var(--glian-border); }
@media (pointer: coarse) { .g-menu__item { min-height: calc(var(--glian-control-sm) + var(--glian-space-2)); } }

/* ── Barra superior global (DESIGN_SYSTEM.md §16) ────────────────────────────────────────────
 * Es del ARMAZÓN, no de la página: la monta Exp.mountHeader() junto al menú lateral, en Expedix,
 * Clinimetrix y Recursos. Lleva el disparador de la paleta de comandos, un hueco central para el
 * contexto (vacío por ahora) y el menú del usuario. NO lleva título ni acciones de la página.
 * Fija arriba, 48px, desde el borde del menú lateral (--glian-topbar-left lo pone el armazón:
 * 220 / 64 contraído / 0 en el teléfono). El espacio lo reserva expedix.js antes del primer
 * pintado (html.has-topbar → body con padding-top), así que montarla no mueve el contenido. */
.g-topbar {
  position: fixed;
  top: 0;
  left: var(--glian-topbar-left, 0);
  right: 0;
  z-index: var(--glian-z-shell);
  box-sizing: border-box;
  height: var(--glian-topbar-h);
  display: flex;
  align-items: center;
  gap: var(--glian-space-3);
  padding: 0 var(--glian-space-6);
  background: var(--glian-bg-surface);
  border-bottom: 1px solid var(--glian-border);
  color: var(--glian-text-primary);
  font-family: var(--glian-font-ui);
}
/* Solo en el teléfono: la hamburguesa (abre el menú lateral) y la marca. */
.g-topbar .exp-ham, .g-topbar__marca { display: none; }
.g-topbar__marca { align-items: center; flex-shrink: 0; height: var(--glian-control-md); }
.g-topbar__marca img { height: var(--glian-icon-xl); width: auto; display: block; }
/* Disparador de la paleta de comandos (Glian.command): un botón con aspecto de campo. */
.g-topbar__buscar {
  display: flex;
  align-items: center;
  gap: var(--glian-space-2);
  box-sizing: border-box;
  width: var(--glian-topbar-search-w);
  min-width: 0;
  max-width: 100%;
  height: var(--glian-control-md);
  margin: 0;
  padding: 0 var(--glian-space-2) 0 var(--glian-space-3);
  border: 1px solid var(--glian-border);
  border-radius: var(--glian-radius-md);
  background: var(--glian-bg-subtle);
  color: var(--glian-text-tertiary);
  font-family: inherit;
  font-size: var(--glian-text-body);
  font-weight: var(--glian-weight-regular);
  text-align: left;
  cursor: pointer;
  transition: background-color var(--glian-duration-fast) var(--glian-ease-standard), border-color var(--glian-duration-fast) var(--glian-ease-standard);
}
.g-topbar__buscar:hover { background: var(--glian-bg-surface); border-color: var(--glian-border-strong); }
.g-topbar__buscar:focus-visible { outline: var(--glian-focus-outline); outline-offset: 2px; }
.g-topbar__buscar .g-icon { width: var(--glian-icon-sm); height: var(--glian-icon-sm); flex-shrink: 0; }
.g-topbar__buscar-txt { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.g-topbar__buscar-corto { display: none; }
.g-topbar__kbd {
  flex-shrink: 0;
  padding: 0 var(--glian-space-1);
  border: 1px solid var(--glian-border);
  border-radius: var(--glian-radius-sm);
  background: var(--glian-bg-surface);
  font-family: inherit;
  font-size: var(--glian-text-caption);
  font-weight: var(--glian-weight-medium);
  line-height: var(--glian-space-5);
  color: var(--glian-text-tertiary);
}
/* Hueco del contexto (paciente activo, en una fase posterior). Vacío ocupa el espacio que separa
 * la búsqueda del usuario; puede encogerse hasta 0 sin dejar un hueco propio. */
.g-topbar__context { flex: 1 1 0; min-width: 0; display: flex; align-items: center; }
/* Usuario: iniciales (o un icono si no hay nombre) y su menú (.g-menu). Sin el nombre en el botón: así
 * su ancho no cambia al llegar /api/auth/me (no salta). Quién es va en la cabecera del menú. */
.g-topbar__usuario { position: relative; flex-shrink: 0; }
/* El botón es angosto (solo iniciales): el menú toma el ancho de su contenido, no el del botón. */
.g-topbar__usuario .g-menu { width: max-content; min-width: calc(var(--glian-space-12) * 4); max-width: calc(100vw - var(--glian-space-6)); }
.g-topbar__yo {
  display: flex;
  align-items: center;
  gap: var(--glian-space-2);
  box-sizing: border-box;
  height: var(--glian-control-md);
  margin: 0;
  padding: 0 var(--glian-space-2) 0 var(--glian-space-1);
  border: 1px solid transparent;
  border-radius: var(--glian-radius-md);
  background: transparent;
  color: var(--glian-text-primary);
  font-family: inherit;
  font-size: var(--glian-text-body);
  font-weight: var(--glian-weight-medium);
  cursor: pointer;
  transition: background-color var(--glian-duration-fast) var(--glian-ease-standard);
}
.g-topbar__yo:hover { background: var(--glian-neutral-soft); }
.g-topbar__yo:focus-visible { outline: var(--glian-focus-outline); outline-offset: 2px; }
.g-topbar__yo > .g-icon { width: var(--glian-icon-sm); height: var(--glian-icon-sm); color: var(--glian-text-tertiary); }
.g-topbar__ini {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: var(--glian-space-8);
  height: var(--glian-space-8);
  border-radius: var(--glian-radius-pill);
  background: var(--glian-brand-soft);
  color: var(--glian-brand-text);
  font-size: var(--glian-text-caption);
  font-weight: var(--glian-weight-semibold);
}
.g-topbar__ini .g-icon { width: var(--glian-icon-sm); height: var(--glian-icon-sm); }
/* Cabecera del menú del usuario: quién trabaja (y si es cuenta de equipo). */
.g-topbar__quien { display: flex; flex-direction: column; gap: var(--glian-space-1); padding: var(--glian-space-2) var(--glian-space-3); overflow-wrap: anywhere; }
.g-topbar__quien b { font-size: var(--glian-text-body); font-weight: var(--glian-weight-semibold); color: var(--glian-text-primary); }
.g-topbar__quien span { font-size: var(--glian-text-caption); color: var(--glian-text-tertiary); }
.g-topbar__equipo {
  align-self: flex-start;
  margin-top: var(--glian-space-1);
  padding: 0 var(--glian-space-2);
  border-radius: var(--glian-radius-pill);
  background: var(--glian-neutral-soft);
  color: var(--glian-text-secondary);
  font-size: var(--glian-text-caption);
  font-weight: var(--glian-weight-semibold);
  line-height: var(--glian-space-5);
}
/* Teléfono (≤860px, sin menú lateral visible): de borde a borde, con la hamburguesa y la marca. */
@media (max-width: 860px) {
  .g-topbar { gap: var(--glian-space-2); padding: 0 var(--glian-space-3); }
  .g-topbar .exp-ham, .g-topbar__marca { display: flex; }
  .g-topbar__buscar { flex: 1 1 auto; width: auto; }
  .g-topbar__context, .g-topbar__kbd, .g-topbar__yo > .g-icon { display: none; }
}
@media (max-width: 560px) {
  .g-topbar__buscar-largo { display: none; }
  .g-topbar__buscar-corto { display: inline; }
}
/* En papel no hay armazón. */
@media print {
  .g-topbar { display: none !important; }
  html.has-topbar body { padding-top: 0 !important; }
}
