/* =========================================================
   Difereti Master Dashboard · tema shadcn/ui
   Tokens basados en shadcn/ui (zinc, light por defecto).
   ========================================================= */

:root {
  --background: hsl(0 0% 100%);
  --foreground: hsl(240 10% 3.9%);
  --card: hsl(0 0% 100%);
  --card-foreground: hsl(240 10% 3.9%);
  --popover: hsl(0 0% 100%);
  --popover-foreground: hsl(240 10% 3.9%);
  --primary: hsl(240 5.9% 10%);
  --primary-foreground: hsl(0 0% 98%);
  --secondary: hsl(240 4.8% 95.9%);
  --secondary-foreground: hsl(240 5.9% 10%);
  --muted: hsl(240 4.8% 95.9%);
  --muted-foreground: hsl(240 3.8% 46.1%);
  --accent: hsl(240 4.8% 95.9%);
  --accent-foreground: hsl(240 5.9% 10%);
  --destructive: hsl(0 84.2% 60.2%);
  --destructive-foreground: hsl(0 0% 98%);
  --border: hsl(240 5.9% 90%);
  --input: hsl(240 5.9% 90%);
  --ring: hsl(240 10% 3.9%);
  --radius: 0.5rem;
  --sidebar-w: 14.5rem;
  --success: hsl(152 76% 40%);
  --success-foreground: hsl(0 0% 98%);
  --warning: hsl(32 95% 44%);
  --chart-1: #f97316;
  --chart-2: #3b82f6;
  --chart-3: #8b5cf6;
  --chart-4: #22c55e;
  --chart-5: #eab308;
  --salud-rango-normal: hsl(24 95% 55%);
  --salud-gauge-linea: hsl(240 10% 3.9%);
  --salud-gauge-punto: hsl(240 10% 3.9%);
  --finanzas-tabbar-bg: hsl(0 0% 100% / 0.92);
  --finanzas-tabbar-fg: hsl(240 3.8% 46.1%);
  --finanzas-tabbar-fg-activo: hsl(240 5.9% 10%);
  --finanzas-tabbar-borde: hsl(240 5.9% 90%);
  --finanzas-hoy: #f97316;
  /* Acciones circulares del editor rápido: verde para confirmar, rojo para
     descartar. No se reutilizan --success/--destructive crudos porque sobre
     fondo blanco quedan en 2,71:1 y 3,76:1 — por debajo del 4,5:1 que exige
     AA para un glifo que se lee como texto; aquí se declaran las variantes con
     contraste medido (5,48:1 y 6,64:1). */
  --finanzas-rapida-guardar: hsl(152 62% 29%);
  --finanzas-rapida-cancelar: hsl(0 74% 41%);
  --font-sans: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI", system-ui, sans-serif;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-tema]) {
    /* Acciones circulares del editor rápido: el mismo par, en la variante
       clara que pide el fondo oscuro (9,03:1 y 5,86:1 de contraste medido). */
    --finanzas-rapida-guardar: hsl(152 62% 48%);
    --finanzas-rapida-cancelar: hsl(0 84% 64%);
    --background: hsl(240 10% 3.9%);
    --foreground: hsl(0 0% 98%);
    --card: hsl(240 10% 3.9%);
    --card-foreground: hsl(0 0% 98%);
    --popover: hsl(240 10% 3.9%);
    --popover-foreground: hsl(0 0% 98%);
    --primary: hsl(0 0% 98%);
    --primary-foreground: hsl(240 5.9% 10%);
    --secondary: hsl(240 3.7% 15.9%);
    --secondary-foreground: hsl(0 0% 98%);
    --muted: hsl(240 3.7% 15.9%);
    --muted-foreground: hsl(240 5% 64.9%);
    --accent: hsl(240 3.7% 15.9%);
    --accent-foreground: hsl(0 0% 98%);
    --destructive: hsl(0 62.8% 30.6%);
    --destructive-foreground: hsl(0 0% 98%);
    --border: hsl(240 3.7% 15.9%);
    --input: hsl(240 3.7% 15.9%);
    --ring: hsl(240 4.9% 83.9%);
    --salud-gauge-linea: hsl(0 0% 98%);
    --salud-gauge-punto: hsl(0 0% 98%);
    --finanzas-tabbar-bg: hsl(240 10% 3.9% / 0.9);
    --finanzas-tabbar-fg: hsl(240 5% 64.9%);
    --finanzas-tabbar-fg-activo: hsl(0 0% 98%);
    --finanzas-tabbar-borde: hsl(240 3.7% 15.9%);
  }
}

/* Modo oscuro manual (toggle del masthead): mismos tokens que el oscuro por
   sistema, gobernados por el atributo data-tema en <html>. La media query de
   arriba queda anulada en cuanto existe elección explícita. */
:root[data-tema="oscuro"] {
  color-scheme: dark;
  /* Acciones circulares del editor rápido (mismo par que el oscuro por
     sistema). */
  --finanzas-rapida-guardar: hsl(152 62% 48%);
  --finanzas-rapida-cancelar: hsl(0 84% 64%);
  --background: hsl(240 10% 3.9%);
  --foreground: hsl(0 0% 98%);
  --card: hsl(240 10% 3.9%);
  --card-foreground: hsl(0 0% 98%);
  --popover: hsl(240 10% 3.9%);
  --popover-foreground: hsl(0 0% 98%);
  --primary: hsl(0 0% 98%);
  --primary-foreground: hsl(240 5.9% 10%);
  --secondary: hsl(240 3.7% 15.9%);
  --secondary-foreground: hsl(0 0% 98%);
  --muted: hsl(240 3.7% 15.9%);
  --muted-foreground: hsl(240 5% 64.9%);
  --accent: hsl(240 3.7% 15.9%);
  --accent-foreground: hsl(0 0% 98%);
  --destructive: hsl(0 62.8% 30.6%);
  --destructive-foreground: hsl(0 0% 98%);
  --border: hsl(240 3.7% 15.9%);
  --input: hsl(240 3.7% 15.9%);
  --ring: hsl(240 4.9% 83.9%);
  --salud-gauge-linea: hsl(0 0% 98%);
  --salud-gauge-punto: hsl(0 0% 98%);
  --finanzas-tabbar-bg: hsl(240 10% 3.9% / 0.9);
  --finanzas-tabbar-fg: hsl(240 5% 64.9%);
  --finanzas-tabbar-fg-activo: hsl(0 0% 98%);
  --finanzas-tabbar-borde: hsl(240 3.7% 15.9%);
}

:root[data-tema="claro"] {
  color-scheme: light;
}

* {
  box-sizing: border-box;
  border-color: var(--border);
}

[hidden] {
  display: none !important;
}

html {
  scroll-behavior: smooth;
}

body {
  margin: 0;
  overflow-x: hidden;
  background: var(--background);
  color: var(--foreground);
  font-family: var(--font-sans);
  font-size: 16px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

a {
  color: inherit;
}

:focus-visible {
  outline: 2px solid var(--ring);
  outline-offset: 2px;
  border-radius: 2px;
}

.skip-link {
  position: absolute;
  top: -3rem;
  left: 0.75rem;
  z-index: 20;
  padding: 0.5rem 0.75rem;
  border-radius: var(--radius);
  background: var(--primary);
  color: var(--primary-foreground);
  font-size: 0.8rem;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

.skip-link:focus {
  top: 0.75rem;
}

/* ─── Header sticky (legado dashboard). En shell iOS de Cadushi no se usa:
   la marca vive en el ícono PWA y la navegación en la tab bar inferior. ─── */

.masthead {
  display: none;
}

.identity-mark {
  display: grid;
  width: 1.75rem;
  height: 1.75rem;
  place-items: center;
  border-radius: 0.4rem;
  background: var(--primary);
  color: var(--primary-foreground);
  font-size: 0.8rem;
  font-weight: 800;
}

.clock-block {
  display: grid;
  gap: 0.05rem;
  min-width: 6.5rem;
  text-align: right;
}

.clock-block span {
  color: var(--muted-foreground);
  font-size: 0.68rem;
}

.clock-block time {
  font-size: 0.85rem;
  font-variant-numeric: tabular-nums;
  font-weight: 600;
}

/* Toggle día/noche: sol visible en modo día, luna en modo noche. El ícono
   indica el modo ACTUAL y el clic alterna. En móvil se empuja al borde
   derecho (el reloj se oculta por espacio). */
.tema-toggle {
  display: grid;
  place-items: center;
  width: 2.25rem;
  height: 2.25rem;
  margin-left: auto;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: transparent;
  color: var(--foreground);
  cursor: pointer;
}

.tema-toggle:hover {
  background: var(--accent);
  color: var(--accent-foreground);
}

.tema-toggle:focus-visible {
  outline: 2px solid var(--ring);
  outline-offset: 2px;
}

.tema-toggle .icono-luna {
  display: none;
}

:root[data-tema="oscuro"] .tema-toggle .icono-luna {
  display: block;
}

:root[data-tema="oscuro"] .tema-toggle .icono-sol {
  display: none;
}

/* Accesos rápidos de solo-icono: visibles únicamente en móvil, donde el
   sidebar fijo se convierte en cajón. En desktop el sidebar ya da acceso. */
.masthead-nav {
  display: none;
}

/* Iconos de la cabecera móvil un poco más gruesos para leerse mejor al toque. */
.masthead-nav svg path,
.masthead-nav svg rect,
.sidebar-burger svg path {
  stroke-width: 2.4;
}

/* ─── Lienzo ─── */

.dashboard-canvas {
  flex: 1;
  width: 100%;
  max-width: none;
  min-width: 0;
  padding: 0.25rem 0 2rem;
  /* Los gestos horizontales quedan reservados para la navegación por
     deslizamiento; el scroll vertical sigue siendo nativo. */
  touch-action: pan-y;
}

/* ─── Navegación por deslizamiento entre módulos ─── */

/* Cada vista muestra un único módulo, acotado para que las tarjetas no se
   estiren de más en pantallas ultrawide. Vive en el carril de módulos: cada
   vista ocupa exactamente el ancho del lienzo (flex) y el arrastre táctil
   desplaza el carril completo. */
.module-view {
  flex: 0 0 100%;
  min-width: 100%;
  max-width: 1900px;
}

/* ─── Carril de módulos (navegación por deslizamiento) ──────────────────── */
/* El carril se mueve con transform (px) controlado por JS: 1:1 con el dedo
   durante el gesto y con transición al soltar o al navegar por el sidebar.
   La altura del envoltorio se fija a la vista activa (evita el scroll
   fantasma de las vecinas) y se libera durante el arrastre. */
.module-track-wrap {
  overflow-x: hidden;
  overflow-y: hidden;
  width: 100%;
  transition: height 220ms cubic-bezier(0.22, 1, 0.36, 1);
}

.module-track-wrap.arrastrando {
  transition: none;
}

.module-track {
  display: flex;
  /* Cada vista conserva su altura natural: sin esto, el flex estira todas las
     vistas a la altura de la más alta y los módulos cortos dejan un hueco
     fantasma hasta la franja de avisos (reportado por Santiago). */
  align-items: flex-start;
  width: 100%;
  transform: translateX(0);
  will-change: transform;
}

.module-track.animando {
  transition: transform 260ms cubic-bezier(0.22, 1, 0.36, 1);
}

/* ─── Shell: sidebar fijo al borde + marco del contenido ─── */

.app-frame {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  margin-left: var(--sidebar-w);
  min-width: 0;
  transition: margin-left 0.18s ease;
}

.sidebar-burger {
  display: none;
}

.app-sidebar {
  position: fixed;
  top: 0;
  bottom: 0;
  left: 0;
  z-index: 40;
  display: flex;
  flex-direction: column;
  gap: 1rem;
  width: var(--sidebar-w);
  padding: 0.85rem;
  overflow-y: auto;
  overscroll-behavior: contain;
  border-right: 1px solid var(--border);
  background: var(--card);
  color: var(--card-foreground);
  transition: width 0.18s ease;
}

.sidebar-brand {
  display: flex;
  align-items: center;
  gap: 0.55rem;
}

.sidebar-brand-name {
  margin: 0;
  font-size: 0.85rem;
  font-weight: 650;
}

.sidebar-brand-sub {
  margin: 0;
  color: var(--muted-foreground);
  font-size: 0.66rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.sidebar-nav {
  display: grid;
  gap: 0.7rem;
}

.sidebar-group-title {
  margin: 0;
  color: var(--muted-foreground);
  font-size: 0.6rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.sidebar-nav ul {
  display: grid;
  gap: 2px;
  margin: 0.25rem 0 0;
  padding: 0;
  list-style: none;
}

.sidebar-link-row {
  display: flex;
  align-items: stretch;
  gap: 0.1rem;
}

.sidebar-link-row .sidebar-link {
  flex: 1;
  min-width: 0;
}

.sidebar-sublist-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.75rem;
  border: none;
  border-radius: var(--radius);
  background: transparent;
  color: var(--muted-foreground);
  cursor: pointer;
}

.sidebar-sublist-toggle:hover {
  color: var(--foreground);
}

.sidebar-sublist-chevron {
  transition: transform 0.15s ease;
}

.sidebar-sublist-toggle[aria-expanded="false"] .sidebar-sublist-chevron {
  transform: rotate(-90deg);
}

.sidebar-link {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.5rem 0.6rem;
  border-radius: var(--radius);
  color: var(--muted-foreground);
  font-size: 0.84rem;
  font-weight: 550;
  text-decoration: none;
}

.sidebar-link svg {
  flex: none;
  opacity: 0.85;
}

.sidebar-link:hover {
  background: var(--accent);
  color: var(--accent-foreground);
}

.sidebar-link[aria-current="page"] {
  background: var(--muted);
  color: var(--foreground);
}

.sidebar-planned {
  display: flex;
  align-items: center;
  padding: 0.45rem 0.6rem;
  border: 1px dashed var(--border);
  border-radius: var(--radius);
  color: var(--muted-foreground);
  font-size: 0.78rem;
  opacity: 0.75;
  cursor: default;
}

.sidebar-note {
  margin: auto 0 0;
  padding-top: 0.75rem;
  border-top: 1px solid var(--border);
  color: var(--muted-foreground);
  font-size: 0.66rem;
  line-height: 1.4;
}

.sidebar-backdrop {
  display: none;
}

/* ─── Card base ─── */

.module-card {
  min-width: 0;
  border: 1px solid var(--border);
  border-radius: calc(var(--radius) + 2px);
  background: var(--card);
  color: var(--card-foreground);
  box-shadow: 0 1px 2px hsl(240 5% 65% / 0.08);
}

/* Cada tarjeta de módulo es un contenedor: sus componentes se adaptan al
   ancho real de la tarjeta (no del viewport) para que los valores nunca se
   trunquen cuando el sidebar estrecha el lienzo. */
.operations-board {
  container-type: inline-size;
}

/* ─── Cabecera de módulo ─── */

.board-header,
.ds-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  padding: 1.1rem 1.25rem 0.9rem;
}

/* La identidad del servidor (M01) cae en su propia fila completa bajo el
   título: una sola línea, con ellipsis solo como respaldo extremo. */
.board-header {
  flex-wrap: wrap;
}

.board-title {
  flex: 1 1 auto;
  min-width: 0;
}

.board-identity {
  flex-basis: 100%;
  margin: 0.05rem 0 0;
  color: var(--muted-foreground);
  font-size: 0.82rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.board-title h2,
.ds-header-title h2 {
  margin: 0.1rem 0 0.25rem;
  font-size: 1.35rem;
  font-weight: 700;
  letter-spacing: -0.015em;
}

.board-title p,
.ds-header-title p {
  margin: 0;
  color: var(--muted-foreground);
  font-size: 0.82rem;
}

.module-eyebrow {
  color: var(--muted-foreground);
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* Botones shadcn */

.btn-outline {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  min-height: 2rem;
  padding: 0.35rem 0.8rem;
  border: 1px solid var(--input);
  border-radius: calc(var(--radius) - 2px);
  background: var(--background);
  color: var(--foreground);
  cursor: pointer;
  font-size: 0.8rem;
  font-weight: 550;
  box-shadow: 0 1px 2px hsl(240 5% 65% / 0.08);
}

.btn-outline:hover {
  background: var(--accent);
}

.btn-outline:disabled {
  opacity: 0.5;
  pointer-events: none;
}

/* Botón Actualizar: etiqueta y última lectura apiladas en dos líneas */
.refresh-text {
  display: grid;
  justify-items: start;
  gap: 0.05rem;
  line-height: 1.15;
}

.refresh-button {
  padding: 0.3rem 0.7rem;
}

.refresh-button time {
  color: var(--muted-foreground);
  font-size: 0.62rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.ds-button {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  min-height: 2rem;
  padding: 0.35rem 0.85rem;
  border: none;
  border-radius: calc(var(--radius) - 2px);
  cursor: pointer;
  font-size: 0.8rem;
  font-weight: 600;
}

.ds-button-white {
  background: var(--primary);
  color: var(--primary-foreground);
}

.ds-button-white:hover {
  opacity: 0.9;
}

.ds-button-white:disabled {
  opacity: 0.5;
}

/* ─── M01 · VPS ─── */

.vps-overview {
  padding: 1rem 1.25rem;
  border-top: 1px solid var(--border);
}

.vps-server-strip {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.3rem 0.9rem;
  margin-bottom: 0.9rem;
}

.vps-server-primary {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  min-width: 0;
}

.vps-server-primary strong,
.vps-server-primary p {
  margin: 0;
}

.vps-server-primary strong {
  overflow: hidden;
  font-size: 0.9rem;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.vps-server-primary p {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  color: var(--muted-foreground);
  font-size: 0.78rem;
}

/* Servidor e IPv4 viven en la misma línea del sistema operativo y el plan. */
.vps-server-facts {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem 0.9rem;
  margin: 0;
}

.vps-server-facts div {
  display: flex;
  align-items: baseline;
  gap: 0.3rem;
  min-width: 0;
}

.vps-server-facts dt {
  color: var(--muted-foreground);
  font-size: 0.66rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.vps-server-facts dd {
  overflow: hidden;
  margin: 0;
  font-size: 0.8rem;
  font-weight: 600;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Badge / status pill */

.status-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.12rem 0.5rem;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--secondary);
  color: var(--secondary-foreground);
  font-size: 0.68rem;
  font-weight: 650;
  white-space: nowrap;
}

.status-pill[data-state="running"] {
  border-color: color-mix(in srgb, var(--success) 30%, transparent);
  background: color-mix(in srgb, var(--success) 8%, transparent);
  color: color-mix(in srgb, var(--success) 78%, var(--foreground));
}

/* KPI tiles */

.vps-metric-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0.7rem;
}

.swap-strip .vps-metric-tile {
  min-height: 7.4rem;
}

.swap-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.7rem;
}

/* Dispositivos de swap: una sola fila horizontal, un donut por dispositivo. */
#swap-dispositivos {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(0, 1fr);
  gap: 0.45rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.swap-dispositivo {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.28rem;
  min-width: 0;
  padding: 0.45rem 0.2rem;
  text-align: center;
}

.swap-dispositivo .swap-dispositivo-ring {
  width: 3.1rem;
  height: 3.1rem;
  flex: none;
}

.swap-dispositivo-ruta {
  overflow: hidden;
  max-width: 100%;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 0.72rem;
  font-weight: 600;
}

.swap-dispositivo-capacidad {
  color: var(--foreground);
  font-size: 0.68rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.swap-dispositivo-prio {
  color: var(--muted-foreground);
  font-size: 0.62rem;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.swap-tuning {
  margin: 0.5rem 0 0.25rem;
  color: var(--muted-foreground);
  font-size: 0.7rem;
  font-variant-numeric: tabular-nums;
}

.swap-scope-note {
  margin: -0.15rem 0 0.45rem;
  color: var(--muted-foreground);
  font-size: 0.68rem;
  line-height: 1.35;
}

/* Filas de la ficha zram: la columna de valores queda alineada en el borde
   derecho con un grid de dos columnas, sin importar el largo de la etiqueta. */
.zram-fila {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: baseline;
  gap: 0.15rem 0.8rem;
  padding: 0.25rem 0;
  font-size: 0.78rem;
}

.zram-fila-label {
  overflow: hidden;
  color: var(--muted-foreground);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.zram-fila-valor {
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

/* Los popovers de intercambio son compactos: no necesitan estirarse. La
   doble clase gana en cascada al ancho base de .disco-popover. */
.disco-popover.swap-popover {
  width: min(20rem, calc(100vw - 2.5rem));
  max-height: 60vh;
  overflow-y: auto;
}

.disco-popover.zram-popover {
  width: min(16rem, calc(100vw - 2.5rem));
}

.vps-metric-tile {
  display: grid;
  gap: 0.4rem;
  min-width: 0;
  min-height: 8.2rem;
  padding: 0.8rem 0.9rem;
  border: 1px solid var(--border);
  border-radius: calc(var(--radius) + 2px);
  background: var(--card);
}

.vps-metric-tile[data-severity="warning"] .tile-reading strong {
  color: var(--warning);
}

.vps-metric-tile[data-severity="critical"] .tile-reading strong {
  color: var(--destructive);
}

.tile-label {
  color: var(--muted-foreground);
  font-size: 0.68rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.tile-reading {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  min-width: 0;
}

.tile-reading strong {
  overflow: hidden;
  font-size: 1.7rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

.vps-metric-tile small,
.ds-card-note {
  overflow: hidden;
  color: var(--muted-foreground);
  font-size: 0.7rem;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.mini-chart {
  width: 4.2rem;
  height: 2.6rem;
  flex: none;
}

.mini-chart path {
  fill: none;
  stroke: var(--chart-2);
  stroke-width: 1.6;
  stroke-linecap: round;
}

.capacity-ring {
  --ring-value: 0;
  display: inline-block;
  width: 2.2rem;
  height: 2.2rem;
  flex: none;
  border-radius: 50%;
  background: conic-gradient(var(--primary) calc(var(--ring-value) * 1%), var(--muted) 0);
}

.capacity-ring[data-empty="true"] {
  background: var(--muted);
}

.vps-strip {
  padding: 0.9rem 1.25rem;
  border-bottom: 1px solid var(--border);
}

.strip-heading {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 0.6rem;
}

.strip-heading h2 {
  margin: 0;
  font-size: 0.9rem;
  font-weight: 650;
  letter-spacing: -0.01em;
}

.strip-heading p {
  margin: 0;
  color: var(--muted-foreground);
  font-size: 0.74rem;
}

.activity-list-h {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(11rem, 1fr);
  align-items: start;
  gap: 0.6rem;
  margin: 0;
  padding: 0;
  overflow-x: auto;
  list-style: none;
}

.backup-chip {
  display: grid;
  gap: 0.3rem;
  min-width: 0;
  padding: 0.65rem 0.75rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--card);
}

.backup-chip[data-current="true"] {
  border-color: color-mix(in srgb, var(--ring) 65%, var(--border));
}

.backup-chip time {
  display: grid;
  gap: 0.05rem;
  font-variant-numeric: tabular-nums;
}

.backup-chip time strong {
  font-size: 0.88rem;
  font-weight: 650;
}

.backup-chip time span {
  color: var(--muted-foreground);
  font-size: 0.74rem;
}

.backup-chip small {
  color: var(--muted-foreground);
  font-size: 0.68rem;
}

.backup-badge {
  justify-self: start;
  padding: 0.1rem 0.45rem;
  border-radius: calc(var(--radius) - 2px);
  background: var(--secondary);
  color: var(--secondary-foreground);
  font-size: 0.58rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.activity-list-h li {
  display: grid;
  grid-template-columns: 0.55rem minmax(0, 1fr);
  gap: 0.55rem;
  align-items: start;
  min-width: 0;
  padding: 0.65rem 0.75rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--card);
}

.activity-list-h li > div {
  display: grid;
  gap: 0.1rem;
  min-width: 0;
}

.activity-list-h strong {
  overflow: hidden;
  font-size: 0.78rem;
  font-weight: 600;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.activity-list-h time {
  color: var(--muted-foreground);
  font-size: 0.68rem;
  font-variant-numeric: tabular-nums;
}

.activity-marker {
  width: 0.5rem;
  height: 0.5rem;
  margin-top: 0.28rem;
  border-radius: 50%;
  background: var(--success);
}

.activity-list-h li[data-state="failed"] .activity-marker {
  background: var(--destructive);
}

.activity-list-h li[data-state="pending"] .activity-marker {
  background: var(--warning);
}

.strip-empty {
  padding: 0.65rem 0.75rem;
  border: 1px dashed var(--border);
  border-radius: var(--radius);
  color: var(--muted-foreground);
  font-size: 0.76rem;
}

/* Error panel */

.error-panel {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin: 0 1.25rem 0.9rem;
  padding: 0.8rem 1rem;
  border: 1px solid color-mix(in srgb, var(--destructive) 30%, transparent);
  border-radius: var(--radius);
  background: color-mix(in srgb, var(--destructive) 4%, transparent);
}

.error-panel strong {
  font-size: 0.85rem;
}

.error-panel p {
  margin: 0.2rem 0 0;
  color: var(--muted-foreground);
  font-size: 0.78rem;
}

.error-panel button {
  min-height: 2rem;
  padding: 0.35rem 0.8rem;
  border: 1px solid var(--input);
  border-radius: calc(var(--radius) - 2px);
  background: var(--background);
  cursor: pointer;
  font-size: 0.78rem;
  font-weight: 600;
  white-space: nowrap;
}

/* Headline operativo */

.operational-headline {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin: 0 1.25rem 0.9rem;
  padding: 0.7rem 1rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--muted);
}

.signal-block {
  width: 0.4rem;
  height: 2.2rem;
  flex: none;
  border-radius: 999px;
  background: var(--muted-foreground);
}

.operational-headline[data-severity="normal"] .signal-block {
  background: var(--success);
}

.operational-headline[data-severity="warning"] .signal-block {
  background: var(--warning);
}

.operational-headline[data-severity="critical"] .signal-block {
  background: var(--destructive);
}

.operational-headline h2 {
  margin: 0;
  font-size: 0.85rem;
  font-weight: 650;
}

.operational-headline p {
  margin: 0.15rem 0 0;
  color: var(--muted-foreground);
  font-size: 0.75rem;
}

.operational-headline .freshness {
  display: grid;
  gap: 0.05rem;
  margin-left: auto;
  text-align: right;
}

.freshness span {
  color: var(--muted-foreground);
  font-size: 0.66rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.freshness time {
  font-size: 0.76rem;
  font-weight: 600;
}

/* Detalle plegable (M02) */

.usage-detail {
  border-top: 1px solid var(--border);
}

.usage-detail > summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  min-height: 2.9rem;
  padding: 0.6rem 1.25rem;
  color: var(--foreground);
  cursor: pointer;
  font-size: 0.78rem;
  font-weight: 600;
  list-style-position: inside;
}

.usage-detail > summary small {
  color: var(--muted-foreground);
  font-weight: 500;
}

.section-heading h2 {
  margin: 0 0 0.15rem;
  font-size: 0.9rem;
  font-weight: 650;
  letter-spacing: -0.01em;
}

.section-heading p {
  margin: 0;
  color: var(--muted-foreground);
  font-size: 0.75rem;
}

.table-scroll {
  overflow-x: auto;
}

table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.78rem;
}

caption {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
}

thead tr {
  border-bottom: 1px solid var(--border);
}

th {
  padding: 0.55rem 0.8rem;
  color: var(--muted-foreground);
  font-size: 0.68rem;
  font-weight: 650;
  text-align: left;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

td {
  padding: 0.5rem 0.8rem;
  border-bottom: 1px solid var(--border);
  font-variant-numeric: tabular-nums;
}

tbody tr:hover {
  background: color-mix(in srgb, var(--accent) 55%, transparent);
}

/* ─── M02 · Consumo (shadcn) ─── */

.ds-banner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin: 0 1.25rem 0.9rem;
  padding: 0.55rem 0.9rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--muted);
  color: var(--muted-foreground);
  font-size: 0.75rem;
}

.ds-banner-close {
  border: none;
  background: transparent;
  color: var(--foreground);
  cursor: pointer;
  font-size: 0.75rem;
  font-weight: 600;
  text-decoration: underline;
}

.ds-filter-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0 1.25rem 0.9rem;
}

.ds-select {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  min-height: 2.1rem;
  padding: 0.2rem 0.6rem;
  border: 1px solid var(--input);
  border-radius: calc(var(--radius) - 2px);
  background: var(--background);
  box-shadow: 0 1px 2px hsl(240 5% 65% / 0.08);
}

.ds-select-label {
  color: var(--muted-foreground);
  font-size: 0.75rem;
}

.ds-select-value {
  border: none;
  background: transparent;
  color: var(--foreground);
  font-size: 0.8rem;
  font-weight: 600;
  cursor: pointer;
  appearance: none;
  padding-right: 1rem;
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%), linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: calc(100% - 0.6rem) 55%, calc(100% - 0.35rem) 55%;
  background-size: 4px 4px;
  background-repeat: no-repeat;
}

.ds-filter-spacer {
  flex: 1;
}

.ds-top-cards {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.8rem;
  padding: 0 1.25rem 0.9rem;
}

@media (min-width: 1180px) {
  /* El primer escritorio amplio ya tiene espacio para mantener la identidad
     del VPS y la actualización junto al título, incluso con el sidebar. */
  #infraestructura .board-header {
    display: grid;
    grid-template-columns: max-content minmax(0, 1fr) max-content;
    align-items: center;
    gap: clamp(0.75rem, 1.5vw, 2rem);
    flex-wrap: nowrap;
  }

  #infraestructura .board-title {
    display: flex;
    align-items: baseline;
    gap: 0.65rem;
    min-width: max-content;
    white-space: nowrap;
  }

  #infraestructura .board-title h2 {
    margin: 0;
  }

  #infraestructura .board-identity {
    flex-basis: auto;
    min-width: 0;
    margin: 0;
    overflow: visible;
    text-overflow: clip;
    white-space: nowrap;
  }

  #infraestructura .refresh-button {
    white-space: nowrap;
  }

  #infraestructura .refresh-text {
    display: flex;
    align-items: baseline;
    gap: 0.4rem;
  }

  .ds-top-cards {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

@media (min-width: 1180px) and (max-width: 1799px) {
  #infraestructura .board-header {
    gap: 0.65rem;
    padding-inline: 0.75rem;
  }

  #infraestructura .board-title {
    gap: 0.45rem;
  }

  #infraestructura .module-eyebrow {
    font-size: 0.58rem;
    letter-spacing: 0.06em;
  }

  #infraestructura .board-title h2 {
    font-size: 1.1rem;
  }

  #infraestructura .board-identity {
    font-size: 0.72rem;
  }

  #infraestructura .refresh-button {
    padding-inline: 0.5rem;
    font-size: 0.72rem;
  }

  #infraestructura .refresh-button time {
    font-size: 0.56rem;
  }

  #infraestructura .refresh-text {
    gap: 0.25rem;
  }
}

.ds-card {
  min-width: 0;
  padding: 0.95rem 1.05rem;
  border: 1px solid var(--border);
  border-radius: calc(var(--radius) + 2px);
  background: var(--card);
  box-shadow: 0 1px 2px hsl(240 5% 65% / 0.08);
}

.ds-card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem;
}

.ds-card-header h3 {
  margin: 0;
  font-size: 0.85rem;
  font-weight: 600;
}

.ds-badge {
  padding: 0.14rem 0.5rem;
  border-radius: 999px;
  border: 1px solid color-mix(in srgb, var(--warning) 45%, transparent);
  background: color-mix(in srgb, var(--warning) 12%, transparent);
  color: var(--warning);
  font-size: 0.64rem;
  font-weight: 650;
  white-space: nowrap;
}

.ds-card-value {
  display: flex;
  align-items: baseline;
  gap: 0.4rem;
  margin-top: 0.7rem;
}

.ds-card-value strong {
  overflow: hidden;
  font-size: 1.9rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

.ds-card-unit {
  color: var(--muted-foreground);
  font-size: 0.8rem;
  font-weight: 550;
}

/* Métricas del rango: cuarta tarjeta del consumo, apiladas en vertical para
   ganar altura y que la gráfica quede a la vista de inmediato. */
.ds-metrics-stack {
  display: grid;
  gap: 0.4rem;
  margin: 0.7rem 0 0;
}

.ds-metrics-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.4rem;
  min-width: 0;
}

.ds-metrics-row dt {
  color: var(--muted-foreground);
  font-size: 0.64rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  line-height: 1.3;
}

.ds-metrics-row dd {
  margin: 0;
  overflow: hidden;
  font-size: 1.1rem;
  font-weight: 700;
  letter-spacing: -0.015em;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

.ds-chart-card {
  margin: 0 1.25rem 0.9rem;
  padding: 0.95rem 1.05rem 0.8rem;
}

.ds-chart-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 0.5rem;
}

.ds-chart-header h3 {
  margin: 0;
  font-size: 0.85rem;
  font-weight: 600;
}

.ds-chart-header h3 span {
  color: var(--muted-foreground);
  font-weight: 500;
}

.ds-toggle {
  display: inline-flex;
  gap: 0.15rem;
  padding: 0.2rem;
  border-radius: calc(var(--radius) - 2px);
  background: var(--muted);
}

.ds-toggle-option {
  min-height: 1.7rem;
  padding: 0.2rem 0.7rem;
  border: none;
  border-radius: calc(var(--radius) - 3px);
  background: transparent;
  color: var(--muted-foreground);
  cursor: pointer;
  font-size: 0.75rem;
  font-weight: 600;
}

.ds-toggle-option.is-active {
  background: var(--background);
  color: var(--foreground);
  box-shadow: 0 1px 2px hsl(240 5% 65% / 0.18);
}

.ds-chart-area {
  position: relative;
}

.usage-bar-chart {
  display: block;
  width: 100%;
  /* Alto único (tope) e igual al alto del viewBox dinámico: el SVG se dibuja
     1:1 sin estiramiento del texto de los ejes en ningún ancho. */
  height: 260px;
}

.usage-bar-chart text {
  fill: var(--muted-foreground);
  font-size: 12px;
  font-weight: 500;
}

.usage-chart-empty {
  fill: var(--muted-foreground);
  font-size: 13px;
  font-weight: 600;
}

.ds-tooltip {
  position: absolute;
  z-index: 4;
  min-width: 13rem;
  max-width: 15rem;
  padding: 0.6rem 0.7rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--popover);
  color: var(--popover-foreground);
  box-shadow: 0 4px 12px hsl(240 5% 45% / 0.18);
  pointer-events: none;
}

.ds-tooltip-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.75rem;
  margin-bottom: 0.35rem;
  padding-bottom: 0.35rem;
  border-bottom: 1px solid var(--border);
}

.ds-tooltip-header strong {
  font-size: 0.76rem;
  font-weight: 700;
}

.ds-tooltip-header span {
  font-size: 0.76rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.ds-tooltip-row {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 0.45rem;
  padding: 0.12rem 0;
  font-size: 0.7rem;
}

.ds-tooltip-swatch {
  width: 0.55rem;
  height: 0.55rem;
  border-radius: 2px;
}

.ds-tooltip-row span:last-child {
  font-variant-numeric: tabular-nums;
}

.usage-ledger-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(19rem, 1fr));
  gap: 0.8rem;
  padding: 0.9rem 1.25rem;
}

.usage-table-panel {
  min-width: 0;
  padding: 0.9rem;
  border: 1px solid var(--border);
  border-radius: calc(var(--radius) + 2px);
}

.usage-table-panel .section-heading h2 {
  font-size: 0.82rem;
}

.usage-table-panel .section-heading p {
  font-size: 0.7rem;
}

/* ─── Footer ─── */

footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-inline: auto;
  width: calc(100% - clamp(1rem, 2vw, 3rem));
  max-width: none;
  padding: 1rem 0 1.5rem;
  border-top: 1px solid var(--border);
  color: var(--muted-foreground);
  font-size: 0.72rem;
}

footer p {
  margin: 0;
}

.footer-link {
  color: var(--foreground);
  font-weight: 550;
}

/* ─── Responsive ─── */

@media (max-width: 720px) {
  .masthead {
    padding: 0.5rem 0.9rem;
    flex-wrap: wrap;
    row-gap: 0.3rem;
    justify-content: flex-start;
  }

  .btn-outline,
  .ds-button,
  .error-panel button {
    min-height: 44px;
  }

  .clock-block {
    display: none;
  }

  .tema-toggle {
    width: 2.5rem;
    height: 2.5rem;
  }

  /* En móvil los cuatro módulos aparecen como iconos junto a la hamburguesa,
     sin crecer la altura del masthead: una sola fila compacta. */
  .masthead-nav {
    display: flex;
    gap: 0.35rem;
  }

  .masthead-link {
    display: grid;
    place-items: center;
    width: 2.5rem;
    height: 2.5rem;
    flex: none;
    border-radius: var(--radius);
    color: var(--muted-foreground);
    text-decoration: none;
  }

  .masthead-link:hover {
    background: var(--accent);
    color: var(--accent-foreground);
  }

  .masthead-link[aria-current="page"] {
    background: var(--accent);
    color: var(--foreground);
  }

  /* El botón Actualizar sube a la esquina superior derecha del módulo: el
     header se rejilla en dos columnas (título | botón) y la última lectura
     queda integrada en el propio botón. En el M01 la identidad del servidor
     ocupa su propia fila completa, en una sola línea. */
  .board-header,
  .ds-header {
    align-items: start;
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas: "title refresh";
  }

  .board-header {
    grid-template-areas:
      "title refresh"
      "identity identity";
  }

  /* M01 conserva módulo y VPS en la misma línea; el estado remoto vive en
     la segunda, así no convierte la cabecera en tres bloques en móvil. */
  #infraestructura .board-title {
    display: flex;
    align-items: baseline;
    gap: 0.35rem;
    white-space: nowrap;
  }

  #infraestructura .board-header {
    grid-template-areas:
      "title title"
      "identity refresh";
  }

  #infraestructura .board-title h2 {
    margin: 0;
    font-size: 1rem;
    white-space: nowrap;
  }

  #infraestructura .module-eyebrow {
    flex: none;
    font-size: 0.58rem;
    letter-spacing: 0.05em;
  }

  /* El mismo estado aparece completo en .board-identity; no lo repetimos
     dentro del botón deshabilitado, donde forzaría una tercera línea. */
  #infraestructura #freshness-time {
    display: none;
  }

  #infraestructura .refresh-button {
    width: 2.5rem;
    min-width: 2.5rem;
    padding-inline: 0;
    justify-content: center;
  }

  #infraestructura .refresh-text {
    display: none;
  }

  .board-identity {
    grid-area: identity;
    min-width: 0;
    font-size: 0.72rem;
  }

  .board-title,
  .ds-header-title {
    grid-area: title;
    min-width: 0;
  }

  .refresh-button {
    grid-area: refresh;
    justify-self: end;
    align-self: start;
  }

  .activity-list-h {
    grid-auto-flow: row;
    grid-auto-columns: auto;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    overflow-x: hidden;
  }

  .ds-card-value {
    flex-wrap: wrap;
  }

  .ds-card-value strong {
    overflow: visible;
    font-size: 1.45rem;
    text-overflow: clip;
    white-space: normal;
  }

  .ds-card-header {
    flex-wrap: wrap;
    gap: 0.35rem;
  }

  .ds-badge {
    white-space: normal;
  }

  /* La franja del servidor ya es flex con wrap: en móvil la identidad, los
     hechos (Servidor, IPv4) y el plan fluyen en una línea compacta. */

  .vps-metric-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.6rem;
  }

  /* Swap y ZRAM comparten UNA sola fila en móvil, con el mismo tamaño de los
     tiles de recursos (CPU, memoria, disco): el bloque conserva su estructura. */
  .swap-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.6rem;
  }

  .swap-strip .vps-metric-tile {
    min-height: 8.2rem;
  }

  .vps-server-facts,
  .ds-top-cards {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  /* La franja de cuatro tarjetas del consumo se compacta en móvil para que la
     gráfica quede a la vista sin desplazarse. */
  .ds-top-cards {
    gap: 0.6rem;
    padding-bottom: 0.7rem;
  }

  .ds-card {
    padding: 0.7rem 0.8rem;
  }

  .ds-card-value {
    margin-top: 0.45rem;
  }

  .ds-metrics-row dd {
    font-size: 1rem;
  }

  .vps-metric-tile {
    padding: 0.6rem 0.55rem;
  }

  .mini-chart {
    height: 30px;
  }

  .strip-heading {
    align-items: flex-start;
    flex-direction: column;
    gap: 0.2rem;
  }

  /* Rango y API Key conviven en una sola línea aunque la opción elegida sea
     larga (p. ej. "Histórico total"): cada selector cede al 50%, la etiqueta
     se apila encima para darle todo el ancho del grupo al <select> y así el
     texto elegido cabe completo sin recortarse. */
  .ds-filter-row {
    flex-wrap: nowrap;
    gap: 0.4rem;
  }

  .ds-select {
    flex: 1 1 0;
    min-width: 0;
    flex-direction: column;
    align-items: stretch;
    gap: 0.15rem;
    padding: 0.3rem 0.5rem;
  }

  .ds-select-label {
    white-space: nowrap;
  }

  .ds-select-value {
    width: 100%;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  /* El botón Actualizar del consumo replica al M01: icono, etiqueta y hora de
     la lectura apilados, sin ocultar nada en pantallas angostas. */

  /* Shell iOS móvil: sin sidebar ni hamburguesa. Navegación = tab bar +
     «Ver todos» hacia Movimientos. El sidebar queda solo en desktop. */
  .app-frame {
    margin-left: 0;
  }

  .sidebar-burger,
  .app-sidebar,
  .sidebar-backdrop {
    display: none !important;
  }

  body.sidebar-open {
    overflow: auto;
  }

  .shell-ios #contenido,
  .shell-ios .dashboard-canvas {
    padding-left: max(0.85rem, env(safe-area-inset-left, 0px));
    padding-right: max(0.85rem, env(safe-area-inset-right, 0px));
  }

  .shell-ios .finanzas-header {
    padding-top: calc(0.55rem + env(safe-area-inset-top, 0px));
  }

  .shell-ios .finanzas-module {
    border: none;
    border-radius: 0;
    background: transparent;
    box-shadow: none;
  }

  /* La franja de avisos muestra dos tarjetas a la vez en móvil. */
  .notice-item {
    width: calc(50vw - 22px);
  }
}

/* El costo por día vive ahora en el tooltip y en la card de costo; la línea
   punteada que cruzaba las barras se eliminó del gráfico. */

.ds-legend-cost {
  margin-left: auto;
  color: var(--muted-foreground);
  font-size: 11.5px;
  font-variant-numeric: tabular-nums;
}

.ds-tooltip-cost {
  margin-top: 6px;
  padding-top: 6px;
  border-top: 1px dashed var(--border);
  color: var(--muted-foreground);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
}

@media (prefers-reduced-motion: reduce) {
  * {
    scroll-behavior: auto !important;
    transition: none !important;
  }

  .notice-flow {
    animation: none;
  }
}

/* ── Avisos operativos (franja corrida al final) ──────────────────────── */

.notice-bar {
  border-top: 1px solid var(--border);
  background: var(--card);
  display: flex;
  align-items: stretch;
}

/* Contenedor que recorta la pista y desvanece los bordes. */
.notice-marquee {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 3%, #000 97%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 3%, #000 97%, transparent);
}

/* Botón de recarga discreto, anclado al extremo derecho de la franja. */
.notice-reload {
  flex: none;
  display: grid;
  place-items: center;
  width: 2.4rem;
  border: none;
  border-left: 1px solid var(--border);
  background: transparent;
  color: var(--muted-foreground);
  cursor: pointer;
}

.notice-reload:hover {
  color: var(--foreground);
}

.notice-reload:disabled {
  opacity: 0.4;
  pointer-events: none;
}

/* La pista corre de izquierda a derecha en bucle: dos copias idénticas y un
   desplazamiento de -50% ↔ 0 hacen el salto invisible. */
.notice-flow {
  display: flex;
  width: max-content;
  animation: notice-slide 38s linear infinite;
}

.notice-marquee:hover .notice-flow {
  animation-play-state: paused;
}

@keyframes notice-slide {
  from { transform: translateX(-50%); }
  to { transform: translateX(0); }
}

.notice-track {
  list-style: none;
  display: flex;
  gap: 10px;
  margin: 0;
  padding: 8px 16px;
}

.notice-item {
  display: flex;
  flex-direction: column;
  gap: 2px;
  width: 24rem;
  max-width: calc(100vw - 32px);
  padding: 6px 10px;
  border: 1px solid var(--border);
  border-radius: calc(var(--radius) - 2px);
  background: var(--background);
}

.notice-head {
  display: flex;
  align-items: center;
  gap: 7px;
}

.notice-head strong {
  color: var(--foreground);
  font-size: 12.5px;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.notice-body {
  color: var(--muted-foreground);
  font-size: 12px;
  line-height: 1.45;
}

.notice-date {
  color: var(--muted-foreground);
  font-size: 10.5px;
  font-variant-numeric: tabular-nums;
  opacity: 0.85;
}

.notice-dot {
  flex: none;
  width: 8px;
  height: 8px;
  border-radius: 9999px;
  background: var(--muted-foreground);
}

.notice-dot.ok { background: hsl(142 76% 36%); }
.notice-dot.warning { background: hsl(25 95% 53%); }
.notice-dot.info { background: hsl(217 91% 60%); }

/* ── Gráfica de consumo refinada ──────────────────────────────────────── */

.usage-bar-chart {
  transition: opacity 160ms ease;
}

.usage-bar-chart.is-switching {
  opacity: 0.35;
}

.usage-bar-seg {
  transform-box: fill-box;
  transform-origin: center bottom;
  transition: opacity 140ms ease, filter 140ms ease, transform 320ms ease;
}

.usage-bar-chart.is-ready .usage-bar-seg {
  animation: usage-bar-rise 420ms ease both;
}

@keyframes usage-bar-rise {
  from {
    transform: scaleY(0.08);
    opacity: 0;
  }
  to {
    transform: scaleY(1);
    opacity: 1;
  }
}

.usage-bar-seg.is-hot {
  filter: brightness(1.22);
}

.usage-bar-seg.is-dimmed {
  opacity: 0.22;
}

.ds-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 14px;
  margin-top: 10px;
}

.ds-legend-item {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-height: 32px;
  padding: 2px 8px;
  border-radius: var(--radius);
  border: 1px solid transparent;
  background: transparent;
  color: var(--muted-foreground);
  font-size: 12.5px;
  cursor: pointer;
}

.ds-legend-item:hover {
  border-color: var(--border);
}

.ds-legend-item.is-focused {
  border-color: var(--foreground);
  color: var(--foreground);
}

.ds-legend-item:focus-visible {
  outline: 2px solid var(--foreground);
  outline-offset: 2px;
}

.ds-legend-swatch {
  flex: none;
  width: 9px;
  height: 9px;
  border-radius: 2px;
}

.ds-legend-total {
  color: var(--foreground);
  font-weight: 600;
}

/* La cabecera M02 mantiene título y acción en una fila compacta. */
.usage-module .ds-header {
  align-items: center;
  gap: 0.5rem;
  flex-wrap: nowrap;
}

.usage-module .ds-header-title {
  min-width: 0;
  flex: 1 1 auto;
}

.usage-module #usage-title {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  letter-spacing: 0.04em;
  font-size: 0.62rem;
}

.usage-module .refresh-button {
  flex: 0 0 auto;
  min-height: 44px;
  white-space: nowrap;
  gap: 0.25rem;
  padding-inline: 0.35rem;
  font-size: 0.7rem;
}

.usage-module .refresh-text {
  gap: 0;
}

.usage-module .refresh-button time {
  font-size: 0.5rem;
}

/* ── Vista única: los módulos conviven en una sola página ──────────────── */

@media (prefers-reduced-motion: reduce) {
  .usage-bar-chart.is-ready .usage-bar-seg {
    animation: none;
  }

  .usage-bar-seg,
  .usage-bar-chart {
    transition: none;
  }
}

@media (max-width: 720px) {
  .ds-legend-item {
    font-size: 12px;
  }
}



/* ─── M03 · Salud ─── */

.salud-module {
  padding-bottom: 0.5rem;
}

/* Identidad del paciente en la cabecera del módulo (todos los anchos), a la
   derecha de «M03 · Salud»; en ultrawide recibe además la lectura clínica. */
.salud-header-datos {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  flex: 1 1 auto;
  min-width: 0;
}

.salud-header-identidad {
  min-width: 0;
}

/* El encabezado «M03 · Salud» nunca se parte en dos líneas. */
.salud-module .ds-header-title h2 {
  white-space: nowrap;
}

/* Tarjeta del paciente: la lectura clínica resumida y las métricas de
   seguimiento; la identidad vive en la cabecera del módulo. */
.salud-paciente {
  min-width: 0;
  margin: 0.9rem 1.25rem 0;
  overflow: hidden;
  border: 1px solid var(--border);
  border-radius: calc(var(--radius) + 2px);
  background: var(--card);
  color: var(--card-foreground);
}

.salud-paciente-identidad {
  display: flex;
  align-items: baseline;
  gap: 0.25rem;
  min-width: 0;
}

.salud-paciente-nombre {
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  white-space: nowrap;
}

.salud-paciente-detalles {
  color: var(--muted-foreground);
  font-size: 0.78rem;
  white-space: nowrap;
}

.salud-paciente-detalles::before {
  content: '· ';
}

.salud-section {
  min-width: 0;
}

/* La lectura clínica vive dentro de la tarjeta del paciente. */
.salud-resumen {
  padding: 0.75rem 0.9rem 0.9rem;
}

.salud-resumen-cabecera {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  min-height: 2.75rem;
  margin: -0.35rem -0.45rem 0.1rem 0;
}

.salud-resumen-cabecera > h3 {
  margin: 0;
}

.salud-resumen-toggle {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 2.75rem;
  width: 2.75rem;
  min-height: 2.75rem;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--muted-foreground);
  cursor: pointer;
}

.salud-resumen-toggle:hover {
  color: var(--foreground);
}

.salud-resumen-toggle:focus-visible {
  outline: 2px solid var(--ring);
  outline-offset: -2px;
}

.salud-resumen-toggle[aria-expanded="true"] .salud-chevron {
  transform: rotate(90deg);
}

.salud-resumen > p {
  margin: 0;
  font-size: 0.84rem;
  line-height: 1.55;
}

/* Rejilla inferior: exámenes a la izquierda y hormonas a la derecha. En
   tarjetas angostas colapsa a una sola columna. */
.salud-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  grid-template-areas:
    'tandas hormonas';
  gap: 0.75rem;
  align-items: start;
  padding: 0.9rem 1.25rem 1.25rem;
}

.salud-tandas-col {
  grid-area: tandas;
}

.salud-hormonas-col {
  grid-area: hormonas;
}

.salud-section > h3 {
  margin: 0 0 0.6rem;
  color: var(--muted-foreground);
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

#salud-resumen-texto {
  margin: 0;
  padding: 0;
  color: var(--card-foreground);
  font-size: 0.84rem;
  line-height: 1.55;
}

.salud-tanda {
  margin-bottom: 0.9rem;
  border: 1px solid var(--border);
  border-radius: calc(var(--radius) + 2px);
  background: var(--card);
  overflow: hidden;
}

.salud-tanda:last-child {
  margin-bottom: 0;
}

.salud-tanda-cabecera {
  margin: 0;
  border-bottom: 1px solid var(--border);
  background: var(--secondary);
}

.salud-tanda-toggle {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  width: 100%;
  padding: 0.7rem 0.9rem;
  border: 0;
  background: transparent;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.salud-tanda-toggle:hover {
  background: color-mix(in srgb, var(--foreground) 4%, transparent);
}

.salud-tanda-toggle:focus-visible {
  outline: 2px solid var(--ring);
  outline-offset: -2px;
}

.salud-tanda-rotulo {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5rem;
  min-width: 0;
}

.salud-tanda-titulo {
  font-size: 0.88rem;
  font-weight: 700;
}

.salud-tanda-meta {
  flex: 0 0 auto;
  color: var(--muted-foreground);
  font-size: 0.72rem;
  font-weight: 600;
  white-space: nowrap;
}

.salud-chevron {
  flex: 0 0 auto;
  color: var(--muted-foreground);
  transition: transform 0.18s ease;
}

.salud-tanda-toggle.is-open .salud-chevron {
  transform: rotate(90deg);
}

.salud-tabla {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.8rem;
}

.salud-tabla th {
  padding: 0.45rem 0.9rem;
  border-bottom: 1px solid var(--border);
  color: var(--muted-foreground);
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-align: left;
  text-transform: uppercase;
}

.salud-tabla th:last-child,
.salud-tabla td:last-child {
  text-align: center;
}

.salud-tabla td {
  padding: 0.38rem 0.9rem;
  vertical-align: top;
}

.salud-tabla tr + tr td {
  border-top: 1px solid var(--border);
}

.salud-parametro {
  font-weight: 600;
  color: var(--card-foreground);
}

.salud-valor {
  font-variant-numeric: tabular-nums;
  font-weight: 600;
}

.salud-rango {
  color: var(--muted-foreground);
  font-size: 0.76rem;
  font-variant-numeric: tabular-nums;
}

/* Gauge de rango de referencia (M03): línea con tramo naranja del rango
   normal y punto en la posición de la medición. Vive dentro de la celda
   "Rango de referencia" y conserva la altura de una línea de texto. */
.salud-rango-gauge {
  min-width: 7rem;
  max-width: 14rem;
  width: 100%;
  font-variant-numeric: tabular-nums;
}

.salud-rango-gauge-linea {
  position: relative;
  height: 6px;
  margin-top: 2px;
  border-radius: 999px;
  background: var(--salud-gauge-linea);
}

.salud-rango-gauge-segmento {
  position: absolute;
  top: 0;
  bottom: 0;
  border-radius: 999px;
  background: var(--salud-rango-normal);
}

.salud-rango-gauge-punto {
  position: absolute;
  top: 50%;
  width: 10px;
  height: 10px;
  border-radius: 999px;
  background: var(--salud-gauge-punto);
  box-shadow: 0 0 0 2px var(--card);
  transform: translate(-50%, -50%);
}

.salud-rango-gauge-escala {
  display: flex;
  justify-content: space-between;
  gap: 0.4rem;
  margin-top: 3px;
  font-size: 0.62rem;
  line-height: 1.2;
  color: var(--muted-foreground);
}

.salud-rango-gauge-max {
  text-align: right;
}

/* Entrada animada del gauge al abrir la tanda: la línea se dibuja de
   izquierda a derecha, el tramo naranja crece sobre ella y el punto se
   desliza desde el origen hasta la posición de la medición. */
@keyframes salud-gauge-linea {
  from { transform: scaleX(0); }
  to { transform: scaleX(1); }
}

@keyframes salud-gauge-segmento {
  from { transform: scaleX(0); }
  to { transform: scaleX(1); }
}

@keyframes salud-gauge-punto {
  from { left: 0%; opacity: 0; transform: translate(-50%, -50%) scale(0.3); }
  to { left: var(--gauge-punto, 0%); opacity: 1; transform: translate(-50%, -50%) scale(1); }
}

@keyframes salud-gauge-escala {
  from { opacity: 0; }
  to { opacity: 1; }
}

.salud-rango-gauge-linea {
  animation: salud-gauge-linea 550ms cubic-bezier(0.22, 1, 0.36, 1) both;
  transform-origin: left center;
}

.salud-rango-gauge-segmento {
  animation: salud-gauge-segmento 650ms cubic-bezier(0.22, 1, 0.36, 1) 120ms both;
  transform-origin: left center;
}

.salud-rango-gauge-punto {
  animation: salud-gauge-punto 700ms cubic-bezier(0.34, 1.56, 0.64, 1) 400ms both;
}

.salud-rango-gauge-escala {
  animation: salud-gauge-escala 350ms ease-out 550ms both;
}

.salud-rango-gauge-anot {
  display: inline-block;
  margin-left: 0.3rem;
  white-space: nowrap;
}

@media (prefers-reduced-motion: reduce) {
  .salud-rango-gauge-punto {
    transition: none;
  }
}

.salud-estado {
  width: 4.5rem;
}

.salud-nota-row td {
  padding-top: 0.2rem;
  color: var(--muted-foreground);
  font-size: 0.74rem;
  line-height: 1.45;
}

.salud-grupo-row td {
  padding: 0.55rem 0.9rem 0.3rem;
  background: var(--secondary);
  color: var(--muted-foreground);
  font-size: 0.64rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.salud-chip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.9rem;
  padding: 0.12rem 0.45rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--secondary);
  font-size: 0.74rem;
  line-height: 1.4;
  animation: salud-chip-aparece 320ms ease-out both;
}

/* Iconos de estado SVG: trazo estilo lucide con entrada sutil. */
@keyframes salud-chip-aparece {
  from { opacity: 0; transform: scale(0.65); }
  to { opacity: 1; transform: scale(1); }
}

@keyframes salud-icono-trazo {
  to { stroke-dashoffset: 0; }
}

.salud-chip svg {
  width: 0.85rem;
  height: 0.85rem;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.2;
  stroke-linecap: round;
  stroke-linejoin: round;
  flex: none;
}

.salud-chip .salud-icono-trazo {
  stroke-dasharray: 10;
  stroke-dashoffset: 10;
  animation: salud-icono-trazo 480ms ease-out 280ms forwards;
}

.salud-chip[data-estado="ok"] {
  border-color: color-mix(in srgb, var(--success) 35%, transparent);
  background: color-mix(in srgb, var(--success) 10%, transparent);
}

.salud-chip[data-estado="warn"] {
  border-color: color-mix(in srgb, var(--warning) 45%, transparent);
  background: color-mix(in srgb, var(--warning) 12%, transparent);
}

.salud-chip[data-estado="info"] {
  border-color: color-mix(in srgb, var(--chart-2) 35%, transparent);
  background: color-mix(in srgb, var(--chart-2) 10%, transparent);
}

.salud-chip[data-estado="pendiente"] {
  border-color: var(--border);
  background: var(--secondary);
}

.salud-hormonas-pendiente {
  display: grid;
  gap: 0.7rem;
  padding: 0.9rem;
  border: 1px dashed var(--border);
  border-radius: calc(var(--radius) + 2px);
  background: var(--card);
}

.salud-hormonas-cabecera {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
}

.salud-hormonas-cabecera strong {
  font-size: 0.92rem;
}

.salud-hormonas-nota {
  margin: 0;
  color: var(--muted-foreground);
  font-size: 0.8rem;
  line-height: 1.5;
}

.salud-chip-lista {
  display: grid;
  gap: 0.4rem;
}

.salud-chip-lista-etiqueta {
  color: var(--muted-foreground);
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.salud-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
}

.salud-chip-neutral {
  padding: 0.25rem 0.6rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--secondary);
  color: var(--secondary-foreground);
  font-size: 0.74rem;
  font-weight: 600;
}

.salud-pendiente-nota {
  margin: 0;
  color: var(--muted-foreground);
  font-size: 0.76rem;
}

/* Panel hormonal con valores: unidad y fecha llevan su propia columna. */
.salud-unidad {
  color: var(--muted-foreground);
  font-size: 0.76rem;
  font-variant-numeric: tabular-nums;
}

.salud-fecha {
  color: var(--muted-foreground);
  font-size: 0.74rem;
  white-space: nowrap;
}

.salud-hormonas-pie {
  margin: 0;
  padding: 0.7rem 0.9rem;
  border-top: 1px solid var(--border);
  color: var(--muted-foreground);
  font-size: 0.76rem;
  line-height: 1.5;
}

/* Métricas de seguimiento: una sola fila horizontal dentro de la tarjeta
   del paciente, con desplazamiento propio si el ancho no alcanza. */
.salud-metricas-fila {
  padding: 0.75rem 0.9rem 0.9rem;
  border-top: 1px solid var(--border);
}

.salud-metricas-fila > h3 {
  margin: 0 0 0.6rem;
  color: var(--muted-foreground);
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.salud-metricas-grid {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(8rem, 1fr);
  gap: 0.45rem;
  overflow-x: auto;
  overscroll-behavior-x: contain;
}

.salud-metrica {
  display: grid;
  gap: 0.2rem;
  align-content: start;
  min-width: 0;
  padding: 0.45rem 0.55rem;
  border: 1px solid var(--border);
  border-radius: calc(var(--radius) + 2px);
  background: var(--card);
}

.salud-metrica-etiqueta {
  color: var(--muted-foreground);
  font-size: 0.6rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}

.salud-metrica-valor {
  font-size: 0.86rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
}

.salud-metrica-detalle {
  color: var(--muted-foreground);
  font-size: 0.64rem;
  line-height: 1.35;
}

.salud-metricas-contexto {
  margin: 0.8rem 0 0;
  color: var(--muted-foreground);
  font-size: 0.78rem;
  line-height: 1.5;
}

/* ─── M03 · Salud — densidad ultrawide (≥1800px) ───
   La vista aprovecha todo el ancho de la pantalla: el título grande y su
   descripción se compactan, la identidad con la lectura clínica suben a la
   derecha de la cabecera y los tres exámenes de sangre se ven en simultáneo
   junto al panel hormonal, cada uno en su propia columna. */

@media (min-width: 1800px) {
  /* La vista de salud no se acota al ancho legible: usa todo el largo. */
  #vista-salud {
    max-width: none;
  }

  /* Identidad + lectura clínica a la derecha de la cabecera. */
  .salud-header-datos {
    display: grid;
    grid-template-columns: minmax(10rem, auto) minmax(22rem, 1fr);
    gap: 0 1.25rem;
    align-items: center;
    flex: 1 1 auto;
    min-width: 0;
    max-width: 64rem;
    margin-left: auto;
  }

  .salud-header-identidad {
    min-width: 0;
  }

  .salud-header-identidad .salud-paciente-identidad {
    display: flex;
    align-items: baseline;
    gap: 0.3rem;
    min-width: 0;
  }

  .salud-header-identidad .salud-paciente-nombre {
    font-size: 0.92rem;
    font-weight: 700;
    letter-spacing: -0.01em;
    white-space: nowrap;
  }

  .salud-header-identidad .salud-paciente-detalles {
    color: var(--muted-foreground);
    font-size: 0.78rem;
    white-space: nowrap;
  }

  .salud-header-resumen .salud-resumen-cabecera {
    margin: 0;
  }

  .salud-header-resumen .salud-resumen-toggle {
    min-height: 2.75rem;
  }

  .salud-header-resumen p {
    margin: 0;
    font-size: 0.8rem;
    line-height: 1.45;
  }

  /* La tarjeta del paciente conserva las métricas; la lectura clínica sube a
     la cabecera en ultrawide (la identidad ya vive allí en todos los anchos). */
  .salud-paciente #salud-resumen-slot {
    display: none;
  }

  /* Cinco columnas simultáneas: cuatro exámenes y el panel hormonal. */
  .salud-grid {
    grid-template-columns: repeat(5, minmax(0, 1fr));
    grid-template-areas: 'tandas tandas tandas tandas hormonas';
  }

  #salud-tandas {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 0.75rem;
    align-items: start;
  }

  .salud-tandas-col .salud-tanda {
    margin-bottom: 0;
  }
}

@media (min-width: 1800px) {
  /* M01 · Infraestructura en ultrawide: la cabecera del módulo ocupa la fila
     completa y, debajo, el bloque de recursos (tiles de CPU/memoria/disco/red/
     ancho de banda + franjas de swap/zram y actividad reciente) se limita a la
     mitad izquierda mientras el mapa de puertos ocupa la mitad derecha, en la
     misma fila, para verlo todo a la vez sin desplazarse. El DOM no cambia de
     orden: el rejilla reparte visualmente las secciones por área. */
  #vista-infraestructura {
    max-width: none;
  }

  #infraestructura {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    grid-template-areas:
      'cabecera  cabecera'
      'overview  puertos'
      'swap      puertos'
      'actividad puertos'
      'historico historico';
  }

  #infraestructura .board-header {
    grid-area: cabecera;
  }

  #infraestructura .vps-overview {
    grid-area: overview;
    min-width: 0;
  }

  #infraestructura .swap-strip {
    grid-area: swap;
    min-width: 0;
  }

  #infraestructura .activity-strip {
    grid-area: actividad;
    min-width: 0;
  }

  #infraestructura .puertos-strip {
    grid-area: puertos;
    min-width: 0;
    border-left: 1px solid var(--border);
  }

  #infraestructura .historico-panel {
    grid-area: historico;
  }
}

@media (max-width: 720px) {
  .salud-tabla {
    font-size: 0.72rem;
  }

  .salud-tabla th,
  .salud-tabla td {
    padding-left: 0.55rem;
    padding-right: 0.55rem;
  }

  .salud-rango {
    font-size: 0.68rem;
  }

  /* Las métricas dejan la fila deslizable y se reparten en dos columnas
     compactas: las ocho caben de una sola vista, sin deslizar. */
  .salud-metricas-grid {
    grid-auto-flow: row;
    grid-auto-columns: auto;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.4rem;
    overflow-x: visible;
  }

  .salud-metrica {
    padding: 0.4rem 0.5rem;
  }

  .salud-rango-gauge {
    min-width: 5rem;
  }

  .salud-estado {
    width: 3.4rem;
  }

  /* Densidad del encabezado de Salud en móvil: título compacto en una sola
     línea y la identidad del paciente legible a su derecha. */
  #salud .ds-header-title h2 {
    font-size: 0.7rem;
  }

  .salud-paciente-nombre {
    font-size: 0.76rem;
  }

  .salud-paciente-detalles {
    font-size: 0.7rem;
  }
}

/* ─── M04 · Finanzas personales ─── */

.finanzas-top-cards {
  padding: 0 1.25rem 0.9rem;
}

.finanzas-card .ds-card-value strong {
  font-size: clamp(1.25rem, 2vw, 1.6rem);
}

.finanzas-form {
  padding: 0.25rem 1.25rem 1rem;
}

.finanzas-form > h3,
.finanzas-recientes > h3 {
  margin: 0.9rem 0 0.6rem;
  color: var(--muted-foreground);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.finanzas-fields {
  display: grid;
  grid-template-columns: minmax(8.5rem, 0.9fr) minmax(0, 1.5fr) minmax(0, 1.1fr) minmax(8.5rem, 0.9fr);
  gap: 0.6rem;
}

.finanzas-field {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  min-width: 0;
}

.finanzas-field-label {
  color: var(--muted-foreground);
  font-size: 0.68rem;
  font-weight: 650;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.finanzas-field input,
.finanzas-field select {
  width: 100%;
  min-height: 44px;
  padding: 0.5rem 0.65rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--background);
  color: var(--foreground);
  font: inherit;
  font-size: 0.88rem;
}

.finanzas-field input::placeholder {
  color: var(--muted-foreground);
}

.finanzas-field input:focus-visible,
.finanzas-field select:focus-visible {
  outline: 2px solid var(--ring);
  outline-offset: 1px;
}

/* Ronda 6 (t_0ca41d80): un solo alto para todos los campos de la captura —los
   44 px del mínimo táctil—: la fecha y el concepto dejan sus 30 px y suben al
   alto de la moneda y del monto. La fecha sigue siendo el selector nativo
   (type=date: el toque abre el calendario del sistema) y conserva su relleno
   lateral; en pantallas de 390 (≤ 420 px) se recorta al mínimo para que el
   valor dd/mm/aaaa —92.22 px de texto a 16 px— entre sin truncarse. */
#finanzas-fecha {
  min-height: 44px;
  padding: 0.1rem 0.35rem;
}

/* El concepto conserva su letra (16px en táctil, el umbral anti-autozoom de
   iOS) y su relleno lateral; el rótulo que lo envuelve mantiene el área
   táctil. */
#finanzas-concepto {
  min-height: 44px;
  padding: 0.1rem 0.65rem;
}

.finanzas-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  margin-top: 0.75rem;
}

.finanzas-form-status {
  margin: 0;
  min-height: 1.2em;
  font-size: 0.8rem;
}

.finanzas-form-status.is-ok {
  color: var(--success);
}

.finanzas-form-status.is-error {
  color: var(--destructive);
}

.finanzas-recientes {
  padding: 0 1.25rem 1.1rem;
}

.finanzas-lista {
  display: grid;
  gap: 0.35rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.finanzas-fila {
  display: grid;
  grid-template-columns: 5.6rem minmax(0, 1fr) auto auto auto;
  gap: 0.6rem;
  align-items: center;
  padding: 0.5rem 0.65rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  font-size: 0.84rem;
}

.finanzas-fila time {
  color: var(--muted-foreground);
  font-variant-numeric: tabular-nums;
}

.finanzas-fila .finanzas-concepto {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Alta rápida de categorías: el + vive en la fila del select y el editor
   ocupa la misma celda sin estirar la fila del formulario. */
.finanzas-categoria-campo {
  min-width: 0;
}

/* El guardar del formulario se pinta según el tipo de registro: rojo de
   gasto, verde de ingreso (gana en cascada a los estilos base del botón). */
.finanzas-boton-gasto {
  background: var(--destructive);
  border-color: var(--destructive);
  color: var(--destructive-foreground);
}

.finanzas-boton-ingreso {
  background: var(--success);
  border-color: var(--success);
  color: var(--success-foreground);
}

/* Gastos fijos: fila con icono, estado del mes y acciones compactas. */
.finanzas-fijos-header-datos {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.6rem;
}

.finanzas-fijo-mostrar {
  min-height: 34px;
}

.finanzas-fijo-form {
  margin: 0 0 1rem;
  padding: 0.9rem 1rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--card);
}

.finanzas-fijo-form-title {
  margin: 0 0 0.7rem;
  color: var(--muted-foreground);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.finanzas-fijo-fields {
  grid-template-columns: minmax(0, 1.6fr) minmax(7.5rem, 0.7fr) minmax(0, 1fr) minmax(8.5rem, 0.9fr);
}

.finanzas-fija-fila {
  grid-template-columns: minmax(0, 1fr) auto auto auto auto;
}

.finanzas-fija-fila .finanzas-concepto {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
}

.finanzas-fija-fila .finanzas-concepto svg {
  flex: none;
  color: var(--muted-foreground);
}

.finanzas-fija-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
}

.finanzas-fijo-estado {
  justify-self: end;
  padding: 0.15rem 0.5rem;
  border-radius: 999px;
  font-size: 0.68rem;
  font-weight: 650;
  white-space: nowrap;
}

.finanzas-fijo-estado.es-pagado {
  background: var(--success);
  color: var(--success-foreground);
}

.finanzas-fijo-estado.es-pendiente {
  background: var(--secondary);
  color: var(--muted-foreground);
}

.finanzas-fijo-acciones {
  display: inline-flex;
  gap: 0.3rem;
  justify-self: end;
}

.finanzas-fijo-accion {
  min-height: 30px;
  padding: 0.15rem 0.55rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: transparent;
  color: var(--muted-foreground);
  cursor: pointer;
  font: inherit;
  font-size: 0.72rem;
  font-weight: 650;
  white-space: nowrap;
}

.finanzas-fijo-accion:hover {
  border-color: var(--ring);
  color: var(--foreground);
}

.finanzas-fijo-accion.es-pagar {
  border-color: var(--success);
  color: var(--success);
}

.finanzas-fijo-accion.es-eliminar:hover {
  border-color: var(--destructive);
  color: var(--destructive);
}

.finanzas-fijos-totales {
  display: grid;
  gap: 0.35rem;
  margin-top: 0.7rem;
}

.finanzas-fijos-mes {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 0.6rem;
  padding: 0.25rem 0.65rem;
  font-size: 0.84rem;
}

.finanzas-fijos-mes strong {
  font-size: 1rem;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.finanzas-fijos-mes:has(#finanzas-fijos-pagado) strong {
  color: var(--success);
}

/* Chips de categoría con icono. */
.finanzas-categoria-chip,
.finanzas-categorias-nombre {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
}

/* Selector de iconos en Configuración. */
.finanzas-categoria-icono-boton {
  min-height: 30px;
  padding: 0.15rem 0.55rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: transparent;
  color: var(--muted-foreground);
  cursor: pointer;
  font: inherit;
  font-size: 0.72rem;
  font-weight: 650;
}

.finanzas-categoria-icono-boton:hover {
  border-color: var(--ring);
  color: var(--foreground);
}

.finanzas-icono-catalogo {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(2.4rem, 1fr));
  gap: 0.3rem;
  margin: 0.3rem 0 0.6rem;
  padding: 0.6rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--card);
}

.finanzas-icono-item {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 2.4rem;
  border: 1px solid transparent;
  border-radius: var(--radius);
  background: transparent;
  color: var(--muted-foreground);
  cursor: pointer;
}

.finanzas-icono-item:hover {
  border-color: var(--ring);
  color: var(--foreground);
}

.finanzas-icono-item.es-actual {
  border-color: var(--primary);
  background: var(--secondary);
  color: var(--primary);
}

.finanzas-categoria-select-fila {
  display: flex;
  align-items: stretch;
  gap: 0.4rem;
}

.finanzas-categoria-select-fila select {
  flex: 1;
  min-width: 0;
}

.finanzas-categoria-mas {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  min-height: 44px;
  border: 1px solid var(--primary);
  border-radius: var(--radius);
  background: var(--secondary);
  color: var(--primary);
  cursor: pointer;
}

.finanzas-categoria-mas:hover {
  background: var(--primary);
  color: var(--primary-foreground);
}

.finanzas-categoria-rapida {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  min-width: 0;
}

.finanzas-categoria-rapida-fila {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem;
}

.finanzas-categoria-rapida input {
  flex: 1 1 7.5rem;
  min-width: 0;
  min-height: 44px;
  padding: 0.5rem 0.65rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--background);
  color: var(--foreground);
  font: inherit;
  font-size: 0.88rem;
}

.finanzas-categoria-rapida input:focus-visible {
  outline: 2px solid var(--ring);
  outline-offset: 1px;
}

.finanzas-categoria-rapida-acciones {
  display: flex;
  align-items: center;
  gap: 0.4rem;
}

.finanzas-categoria-rapida-acciones .ds-button,
.finanzas-categoria-rapida-acciones .finanzas-boton-ghost {
  min-height: 38px;
}

.finanzas-categoria-rapida-status {
  flex-basis: 100%;
  min-height: 1em;
}

.finanzas-categoria-chip {
  justify-self: start;
  padding: 0.15rem 0.5rem;
  border-radius: 999px;
  /* Tono característico por categoría (SPEC 006 · iteración): el JS fija
     --cat-hue; sin él, el fallback queda en un azul neutro legible. */
  background: hsl(var(--cat-hue, 240) 72% 93%);
  color: hsl(var(--cat-hue, 240) 45% 28%);
  border: 1px solid hsl(var(--cat-hue, 240) 55% 84%);
  font-size: 0.66rem;
  font-weight: 600;
  white-space: nowrap;
}

.finanzas-monto {
  justify-self: end;
  font-weight: 650;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.finanzas-fijos {
  padding: 1rem 1.25rem 1.1rem;
}

.finanzas-fijos-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.6rem;
  margin-bottom: 0.3rem;
}

.finanzas-fijos-note {
  margin: 0 0 0.7rem;
  color: var(--muted-foreground);
  font-size: 0.76rem;
}

.finanzas-fijos-caption {
  margin: 0 0 0.6rem;
  color: var(--muted-foreground);
  font-size: 0.78rem;
  font-weight: 600;
}

/* Cabecera de fijos: «Importar gastos fijos de <mes>» (primero) en línea con
   «＋ Agregar gasto fijo». Importar conserva la línea punteada, ahora con
   fondito naranja claro para que se lea como botón (revisión de Santiago). */
.finanzas-fijos-botones {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
}

.finanzas-fijos-importar {
  min-height: 34px;
  padding: 0.35rem 0.7rem;
  border: 1px dashed color-mix(in srgb, var(--finanzas-hoy) 45%, var(--border));
  border-radius: calc(var(--radius) - 2px);
  background: color-mix(in srgb, var(--finanzas-hoy) 14%, transparent);
  color: var(--foreground);
  cursor: pointer;
  font: inherit;
  font-size: 0.78rem;
  font-weight: 600;
}

.finanzas-fijos-importar[hidden] {
  display: none;
}

.finanzas-fijos-importar:hover {
  border-color: var(--finanzas-hoy);
  background: color-mix(in srgb, var(--finanzas-hoy) 24%, transparent);
}

.finanzas-fija-fila {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  gap: 0.6rem;
  align-items: center;
  padding: 0.5rem 0.65rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  font-size: 0.84rem;
}

.finanzas-fija-sub {
  display: block;
  font-size: 0.7rem;
  font-weight: 500;
  color: var(--muted-foreground);
  text-align: right;
}

.finanzas-fijos-total {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 0.6rem;
  margin-top: 0.7rem;
  padding: 0.6rem 0.65rem 0;
  border-top: 1px dashed var(--border);
  font-size: 0.84rem;
}

.finanzas-fijos-total strong {
  font-size: 1.05rem;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

@media (max-width: 720px) {
  .finanzas-fields {
    grid-template-columns: 1fr 1fr;
  }

  .finanzas-field-concepto {
    /* El concepto comparte línea con la fecha en móvil (fecha corta · concepto
       ancho, categoría · moneda y monto · par): filas parejas, sin apilar. */
  }

  /* La fecha móvil va sin el icono del calendario de Chrome: el toque en el
     campo entero sigue abriendo el selector nativo (iOS nunca lo mostró) y a
     6.9rem el valor dd/mm/aaaa cabe completo sin él. */
  .finanzas-form-en-tarjeta #finanzas-fecha::-webkit-calendar-picker-indicator {
    display: none;
  }

  .finanzas-actions {
    flex-direction: column;
    align-items: stretch;
  }

  .finanzas-actions .ds-button {
    width: 100%;
    min-height: 44px;
  }

  .finanzas-fila {
    grid-template-columns: 4.9rem minmax(0, 1fr) auto;
  }

  /* Solo el chip de tipo se oculta en móvil: el de categoría se queda visible
     con su color (revisión de Santiago, 14-sep-2026). */
  .finanzas-tipo-chip {
    display: none;
  }

  .finanzas-categoria-chip {
    max-width: 7.5rem;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  .finanzas-fijos-total {
    flex-direction: column;
    align-items: flex-start;
    gap: 0.15rem;
  }

  .finanzas-fija-sub {
    font-size: 0.64rem;
  }
}

/* ─── M04 · Mini-app de finanzas: período, tarjetas y categorías ─── */

/* Cabecera estilo iOS large title: título de pantalla a la izquierda y
   selector de período a la derecha, sin chrome de marca/hamburguesa. */
.finanzas-header {
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding-top: 0.35rem;
  padding-bottom: 0.85rem;
}

.finanzas-large-title {
  margin: 0;
  min-width: 0;
  font-size: clamp(1.55rem, 4.5vw, 2rem);
  font-weight: 700;
  letter-spacing: -0.035em;
  line-height: 1.12;
  color: var(--foreground);
}

.finanzas-header .module-eyebrow {
  margin: 0;
  line-height: 1.4;
}

.finanzas-periodo {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.2rem;
  min-width: 0;
}

.finanzas-periodo-selector {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.42rem 0.8rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--background);
  color: var(--foreground);
  cursor: pointer;
  font: inherit;
  font-size: 0.78rem;
  font-weight: 650;
  white-space: nowrap;
}

.finanzas-periodo-selector:hover,
.finanzas-periodo-selector[aria-expanded="true"] {
  border-color: var(--ring);
}

.finanzas-periodo-chevron {
  flex: none;
  transition: transform 0.15s ease;
}

.finanzas-periodo-selector[aria-expanded="true"] .finanzas-periodo-chevron {
  transform: rotate(180deg);
}

.finanzas-freshness {
  color: var(--muted-foreground);
  font-size: 0.68rem;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* Panel del calendario de rango, anclado al selector. */
.finanzas-calendario {
  position: absolute;
  top: calc(100% + 0.45rem);
  right: 0;
  z-index: 30;
  width: min(19rem, calc(100vw - 2.5rem));
  padding: 0.75rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--card);
  box-shadow: 0 12px 32px -12px rgb(0 0 0 / 0.35);
}

.finanzas-calendario-nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  margin-bottom: 0.5rem;
}

.finanzas-calendario-titulo {
  font-size: 0.82rem;
  font-weight: 700;
}

.finanzas-calendario-nav-boton {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.9rem;
  height: 1.9rem;
  border: 1px solid transparent;
  border-radius: var(--radius);
  background: transparent;
  color: var(--foreground);
  cursor: pointer;
  font-size: 1.05rem;
  line-height: 1;
}

.finanzas-calendario-nav-boton:hover {
  border-color: var(--border);
  background: var(--secondary);
}

.finanzas-calendario-grid {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 2px;
}

.finanzas-calendario-dia-semana {
  padding: 0.25rem 0;
  color: var(--muted-foreground);
  font-size: 0.64rem;
  font-weight: 700;
  text-align: center;
  text-transform: uppercase;
}

.finanzas-calendario-vacio {
  aspect-ratio: 1;
}

.finanzas-calendario-dia {
  aspect-ratio: 1;
  min-width: 0;
  border: 1px solid transparent;
  border-radius: var(--radius);
  background: transparent;
  color: var(--foreground);
  cursor: pointer;
  font: inherit;
  font-size: 0.78rem;
  font-variant-numeric: tabular-nums;
}

.finanzas-calendario-dia:hover {
  border-color: var(--ring);
}

.finanzas-calendario-dia.en-rango {
  background: var(--secondary);
  border-radius: 0;
}

.finanzas-calendario-dia.en-rango.es-inicio,
.finanzas-calendario-dia.en-rango.es-fin {
  background: var(--primary);
  color: var(--primary-foreground);
}

.finanzas-calendario-dia.en-rango.es-inicio {
  border-radius: var(--radius) 0 0 var(--radius);
}

.finanzas-calendario-dia.en-rango.es-fin {
  border-radius: 0 var(--radius) var(--radius) 0;
}

.finanzas-calendario-dia.en-rango.es-inicio.es-fin {
  border-radius: var(--radius);
}

/* Primer clic de un período nuevo: el día queda «en blanco» (blanco literal,
   legible en cualquier tema) con su marco, esperando el segundo clic. */
.finanzas-calendario-dia.es-seleccion-inicio {
  background: #fff;
  color: hsl(240 5.9% 10%);
  border-color: hsl(240 5.9% 10%);
  border-radius: var(--radius);
  font-weight: 700;
}

/* Mes completo seleccionado: los días interiores forman una banda continua
   con relleno uniforme; el día 1 y el último quedan en blanco como remate
   contrastado (blanco literal #fff: no se funde con el fondo en tema oscuro)
   y el día de hoy es la única pieza naranja (token --finanzas-hoy), siempre
   visible con o sin rango. */
.finanzas-calendario-grid-mes .finanzas-calendario-dia.en-rango {
  background: color-mix(in srgb, var(--primary) 20%, transparent);
  border-radius: 0;
}

.finanzas-calendario-grid-mes .finanzas-calendario-dia.en-rango.es-inicio,
.finanzas-calendario-grid-mes .finanzas-calendario-dia.en-rango.es-fin {
  background: #fff;
  color: hsl(240 5.9% 10%);
}

.finanzas-calendario-grid-mes .finanzas-calendario-dia.en-rango.es-inicio {
  border-radius: var(--radius) 0 0 var(--radius);
}

.finanzas-calendario-grid-mes .finanzas-calendario-dia.en-rango.es-fin {
  border-radius: 0 var(--radius) var(--radius) 0;
}

/* El día de hoy es naranja SIEMPRE (con o sin rango aplicado, y también
   mientras se elige un período nuevo): es la única pieza naranja. */
.finanzas-calendario-dia.es-hoy,
.finanzas-calendario-dia.en-rango.es-hoy,
.finanzas-calendario-grid-mes .finanzas-calendario-dia.en-rango.es-hoy {
  background: var(--finanzas-hoy);
  color: #fff;
  border-radius: var(--radius);
  font-weight: 800;
}

.finanzas-calendario-atajos {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  margin-top: 0.6rem;
  padding-top: 0.6rem;
  border-top: 1px dashed var(--border);
}

.finanzas-calendario-atajo {
  padding: 0.32rem 0.6rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: transparent;
  color: var(--muted-foreground);
  cursor: pointer;
  font: inherit;
  font-size: 0.68rem;
  font-weight: 600;
}

.finanzas-calendario-atajo:hover {
  border-color: var(--ring);
  color: var(--foreground);
}

/* Desglose por categorías dentro de las tarjetas de resumen. */
.finanzas-categorias-lista {
  display: grid;
  gap: 0.2rem;
  margin: 0.6rem 0 0;
  padding: 0.6rem 0 0;
  border-top: 1px dashed var(--border);
  list-style: none;
}

.finanzas-categorias-fila {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.6rem;
  font-size: 0.76rem;
}

.finanzas-categorias-nombre {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--muted-foreground);
}

.finanzas-categorias-monto {
  font-weight: 650;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.finanzas-card {
  position: relative;
}

.finanzas-card-gasto {
  border-top: 3px solid var(--destructive);
}

.finanzas-card-gasto .ds-card-value strong {
  color: var(--destructive);
}

.finanzas-card-ingreso {
  border-top: 3px solid var(--success);
}

.finanzas-card-ingreso .ds-card-value strong {
  color: var(--success);
}

.finanzas-card-boton {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.9rem;
  height: 1.9rem;
  border: none;
  border-radius: 999px;
  cursor: pointer;
  font-size: 1.15rem;
  line-height: 1;
  font-weight: 700;
}

.finanzas-card-gasto .finanzas-card-boton {
  background: var(--destructive);
  color: var(--destructive-foreground);
}

.finanzas-card-ingreso .finanzas-card-boton {
  background: var(--success);
  color: #fff;
}

.finanzas-card-boton:hover {
  opacity: 0.88;
}

.finanzas-actions-botones {
  display: flex;
  gap: 0.5rem;
}

.finanzas-boton-ghost {
  display: inline-flex;
  align-items: center;
  min-height: 2rem;
  padding: 0.35rem 0.85rem;
  border: 1px solid var(--border);
  border-radius: calc(var(--radius) - 2px);
  background: transparent;
  color: var(--foreground);
  cursor: pointer;
  font-size: 0.8rem;
  font-weight: 600;
}

.finanzas-boton-ghost:hover {
  background: var(--secondary);
}

.finanzas-boton-ghost:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

.finanzas-tipo-chip {
  justify-self: start;
  padding: 0.15rem 0.5rem;
  border-radius: 999px;
  font-size: 0.64rem;
  font-weight: 700;
  white-space: nowrap;
}

.finanzas-tipo-chip.tipo-gasto {
  background: color-mix(in srgb, var(--destructive) 14%, transparent);
  color: var(--destructive);
}

.finanzas-tipo-chip.tipo-ingreso {
  background: color-mix(in srgb, var(--success) 16%, transparent);
  color: var(--success);
}

.finanzas-monto.monto-gasto {
  color: var(--destructive);
}

.finanzas-monto.monto-ingreso {
  color: var(--success);
}

/* Configuración: sub-vista de categorías dentro de #vista-finanzas */

.finanzas-configuracion {
  padding: 0.25rem 1.25rem 1.2rem;
}

/* Sub-vistas (gastos fijos y configuración): cabecera compartida con
   enlace de vuelta y título. */
.finanzas-subvista-header {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  margin-bottom: 0.9rem;
}

.finanzas-volver {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  align-self: flex-start;
  color: var(--muted-foreground);
  font-size: 0.8rem;
  font-weight: 650;
  text-decoration: none;
}

.finanzas-volver:hover {
  color: var(--foreground);
}

.finanzas-subvista-header h3 {
  margin: 0;
  color: var(--muted-foreground);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.finanzas-configuracion-note {
  margin: 0.3rem 0 0;
  color: var(--muted-foreground);
  font-size: 0.78rem;
}

.finanzas-categoria-form {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 0.6rem;
  margin-bottom: 0.8rem;
}

.finanzas-categoria-nueva {
  flex: 1 1 16rem;
  min-width: 0;
}

.finanzas-categoria-form .finanzas-form-status {
  flex-basis: 100%;
}

.finanzas-categoria-lista {
  gap: 0.45rem;
}

.finanzas-categoria-fila {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  gap: 0.6rem;
  align-items: center;
  padding: 0.5rem 0.65rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  font-size: 0.86rem;
}

.finanzas-categoria-nombre {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.finanzas-categoria-chip {
  padding: 0.15rem 0.5rem;
  border-radius: 999px;
  background: var(--secondary);
  color: var(--muted-foreground);
  font-size: 0.64rem;
  font-weight: 600;
  white-space: nowrap;
}

/* Submenú del sidebar: Configuración bajo Finanzas personales */

.sidebar-nav ul.sidebar-sublist {
  margin: 0.1rem 0 0;
  padding: 0 0 0 1.9rem;
  list-style: none;
}

.sidebar-sublink {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.38rem 0.7rem;
  border-radius: var(--radius);
  color: var(--muted-foreground);
  font-size: 0.78rem;
  font-weight: 550;
  text-decoration: none;
}

.sidebar-sublink:hover {
  background: var(--accent);
  color: var(--accent-foreground);
}

.sidebar-sublink[aria-current="page"] {
  background: var(--muted);
  color: var(--foreground);
  font-weight: 650;
}

@media (max-width: 720px) {
  .finanzas-periodo-selector {
    font-size: 0.72rem;
    padding: 0.4rem 0.65rem;
  }

  .finanzas-fijo-fields {
    grid-template-columns: 1fr 1fr;
  }

  .finanzas-fija-fila {
    grid-template-columns: minmax(0, 1fr) auto;
  }

  .finanzas-fija-fila .finanzas-fija-chip {
    display: none;
  }

  .finanzas-fija-fila .finanzas-fijo-estado {
    grid-column: 1;
    justify-self: start;
  }

  .finanzas-fija-fila .finanzas-fijo-acciones {
    grid-column: 2;
    justify-self: end;
  }

  .finanzas-fijos-botones.con-importar {
    width: 100%;
    align-items: stretch;
  }

  .finanzas-fijos-botones.con-importar .finanzas-fijos-importar {
    flex: 1 1 0;
    min-width: 0;
    white-space: normal;
    text-align: center;
    font-size: 0.76rem;
  }

  .finanzas-actions-botones {
    width: 100%;
    /* El par ✓/✗ del formulario de registro se queda a la derecha (pulgar) y
       conserva sus 44 px: no se estira como los botones rotulados. */
    justify-content: flex-end;
  }

  .finanzas-actions-botones .ds-button,
  .finanzas-actions-botones .finanzas-boton-ghost {
    flex: 1;
    min-height: 44px;
    justify-content: center;
  }
}

/* ─── Botón de histórico dentro de cada tile + popover de disco ─── */

.vps-metric-tile {
  position: relative;
}

.tile-historico-boton {
  position: absolute;
  top: 0.45rem;
  right: 0.45rem;
  z-index: 2;
  display: grid;
  width: 1.65rem;
  height: 1.65rem;
  place-items: center;
  border: 1px solid var(--border);
  border-radius: calc(var(--radius) - 2px);
  background: var(--background);
  color: var(--muted-foreground);
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.15s ease;
}

.vps-metric-tile:hover .tile-historico-boton,
.tile-historico-boton:focus-visible,
.tile-historico-boton[aria-expanded="true"] {
  opacity: 1;
}

.tile-historico-boton:hover {
  color: var(--foreground);
  border-color: var(--ring);
}

.tile-historico-boton:focus-visible {
  outline: 2px solid var(--ring);
  outline-offset: 1px;
}

.tile-detalle-target {
  position: absolute;
  inset: 0;
  z-index: 1;
  padding: 0;
  border: 0;
  border-radius: inherit;
  background: transparent;
  cursor: pointer;
}

.tile-detalle-target:focus-visible,
.popover-cerrar:focus-visible {
  outline: 2px solid var(--ring);
  outline-offset: -2px;
}

.disco-popover {
  position: absolute;
  top: 100%;
  left: 0;
  z-index: 20;
  width: min(18rem, calc(100vw - 2.5rem));
  margin-top: 0.35rem;
  padding: 0.7rem 0.8rem;
  border: 1px solid var(--border);
  border-radius: calc(var(--radius) + 2px);
  background: var(--popover);
  color: var(--popover-foreground);
  box-shadow: 0 8px 24px hsl(240 10% 8% / 0.18);
}

.popover-cerrar {
  position: absolute;
  top: 0.35rem;
  right: 0.45rem;
  display: grid;
  width: 1.65rem;
  height: 1.65rem;
  place-items: center;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--secondary);
  color: var(--foreground);
  font: inherit;
  font-size: 1rem;
  line-height: 1;
  cursor: pointer;
}

.disco-popover-titulo {
  margin: 0 0 0.55rem;
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted-foreground);
}

/* Selector de usuarios: chips con la ocupación de cada home. */
.disco-usuarios {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem;
  margin: 0 0 0.55rem;
}

.disco-usuario-chip {
  padding: 0.14rem 0.55rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--secondary);
  color: var(--muted-foreground);
  font: inherit;
  font-size: 0.72rem;
  font-variant-numeric: tabular-nums;
  cursor: pointer;
}

.disco-usuario-chip:hover,
.disco-usuario-chip:focus-visible {
  color: var(--foreground);
  outline: 2px solid var(--ring);
  outline-offset: 1px;
}

.disco-usuario-chip[aria-current='page'] {
  border-color: var(--ring);
  color: var(--foreground);
  font-weight: 600;
}

/* Grupo de usuarios de sistema: círculo con icono + badge contador. */
.disco-usuarios-grupo {
  display: contents; /* botón y lista expandida participan del flex principal */
}

.disco-usuario-grupo-boton {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.7rem;
  height: 1.7rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--secondary);
  color: var(--muted-foreground);
  cursor: pointer;
}

.disco-usuario-grupo-boton:hover,
.disco-usuario-grupo-boton:focus-visible {
  color: var(--foreground);
  outline: 2px solid var(--ring);
  outline-offset: 1px;
}

.disco-usuario-grupo-badge {
  position: absolute;
  top: -0.3rem;
  right: -0.35rem;
  min-width: 0.95rem;
  height: 0.95rem;
  padding: 0 0.18rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 999px;
  background: var(--accent);
  color: var(--accent-foreground);
  font-size: 0.55rem;
  font-weight: 700;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

.disco-usuarios-grupo-lista {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem;
}

#disco-carpetas {
  display: grid;
  gap: 0.45rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.disco-carpeta-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 0.15rem 0.6rem;
  align-items: baseline;
  font-size: 0.78rem;
}

.disco-carpeta-ruta {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: 600;
}

.disco-carpeta-bytes {
  color: var(--muted-foreground);
  font-variant-numeric: tabular-nums;
}

.disco-carpeta-barra {
  grid-column: 1 / -1;
  height: 4px;
  border-radius: 999px;
  background: var(--secondary);
  overflow: hidden;
}

.disco-carpeta-barra-relleno {
  display: block;
  height: 100%;
  border-radius: 999px;
  background: var(--chart-2);
}

.disco-carpeta-vacio {
  font-size: 0.78rem;
  color: var(--muted-foreground);
}

.disco-popover-fecha {
  margin: 0.6rem 0 0;
  padding-top: 0.5rem;
  border-top: 1px solid var(--border);
  color: var(--muted-foreground);
  font-size: 0.68rem;
}

/* Pie de coherencia del popover de Memoria: explica por qué la suma de los
   procesos listados no alcanza el total usado del anillo del tile. */
.disco-popover-pie {
  margin: 0.55rem 0 0;
  padding-top: 0.5rem;
  border-top: 1px solid var(--border);
  color: var(--muted-foreground);
  font-size: 0.7rem;
  line-height: 1.4;
}

/* ─── Popover de disco: breadcrumb y filas navegables ─── */

.disco-breadcrumb {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.25rem;
  margin: 0 0 0.5rem;
  padding: 0;
  font-size: 0.72rem;
}

.disco-breadcrumb-link {
  padding: 0.1rem 0.3rem;
  border: 0;
  border-radius: calc(var(--radius) - 4px);
  background: var(--secondary);
  color: var(--muted-foreground);
  font: inherit;
  cursor: pointer;
}

.disco-breadcrumb-link:hover,
.disco-breadcrumb-link:focus-visible {
  color: var(--foreground);
  outline: 2px solid var(--ring);
  outline-offset: 1px;
}

.disco-breadcrumb-actual {
  font-weight: 700;
  color: var(--foreground);
}

.disco-carpeta-row {
  cursor: pointer;
  border-radius: calc(var(--radius) - 4px);
  padding: 0.1rem 0.25rem;
}

.disco-carpeta-row:hover {
  background: var(--secondary);
}

.disco-carpeta-row:focus-visible {
  background: var(--secondary);
  outline: 2px solid var(--ring);
  outline-offset: 1px;
}

/* En móvil los popovers se vuelven una hoja inferior a todo el ancho:
   nunca se desbordan por la derecha. */
@media (max-width: 720px) {
  /* RAM y disco se abren tocando la tarjeta completa; en la hoja móvil la
     equis duplica el cierre exterior/Escape, por eso no se presenta. */
  #memoria-popover .popover-cerrar,
  #disco-popover .popover-cerrar {
    display: none;
  }

  .disco-popover,
  .memoria-popover {
    position: fixed;
    top: auto;
    left: 0.75rem;
    right: 0.75rem;
    bottom: 0.75rem;
    width: auto;
    max-width: none;
    margin-top: 0;
    max-height: 60vh;
    overflow-y: auto;
  }

  /* Las fichas de recursos usan más del alto real disponible cuando su
     contenido lo necesita. Conservan scroll solo en pantallas bajas. */
  #memoria-popover,
  #disco-popover,
  #swap-popover,
  #zram-popover {
    max-height: min(72dvh, calc(100dvh - 1.5rem));
  }

  /* Los popovers de intercambio van centrados y angostos: no ocupan todo el
     ancho de la pantalla. */
  .disco-popover.swap-popover,
  .disco-popover.zram-popover {
    left: 50%;
    right: auto;
    transform: translateX(-50%);
    width: min(21rem, calc(100vw - 1.5rem));
    max-width: none;
  }

  .swap-dispositivo .swap-dispositivo-ring {
    width: 2.65rem;
    height: 2.65rem;
  }

  /* Previsualización densa en la hoja de memoria: filas a dos columnas con
     barras cortas del ancho de cada celda — caben más procesos por pantalla.
     La fila sintética Kernel + ZRAM abarca ambas columnas. */
  .memoria-popover #memoria-procesos {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.4rem 0.5rem;
  }

  /* Celda móvil: la etiqueta en una sola línea y, debajo, la barra GRUESA
     con el valor y el porcentaje dentro. Sin PID: la línea meta, bytes y %
     se ocultan en la hoja (el PID sigue en el tooltip de escritorio). */
  .memoria-popover .proceso-row {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto auto;
    gap: 0.12rem;
  }

  .memoria-popover .proceso-cuerpo {
    grid-column: 1;
    grid-row: 1;
  }

  .memoria-popover .proceso-meta,
  .memoria-popover .proceso-bytes,
  .memoria-popover .proceso-pct {
    display: none;
  }

  .memoria-popover .proceso-row .disco-carpeta-barra {
    grid-row: 2;
    position: relative;
    height: 1.1rem;
  }

  .memoria-popover .proceso-barra-texto {
    display: block;
    position: absolute;
    inset: 0;
    margin: auto;
    width: fit-content;
    max-width: 100%;
    overflow: hidden;
    padding: 0 0.45rem;
    border-radius: 999px;
    background: var(--popover);
    font-size: 0.62rem;
    font-weight: 650;
    font-variant-numeric: tabular-nums;
    line-height: 1rem;
    color: var(--foreground);
    white-space: nowrap;
    pointer-events: none;
  }

  .memoria-popover .proceso-row-kernel {
    grid-column: 1 / -1;
  }
}

/* ─── Popover de memoria: procesos por RAM ─── */

.memoria-popover {
  width: min(24rem, calc(100vw - 2.5rem));
}

/* Cabecera del popover de memoria: título + toggle segmentado Top/Resto. */
.memoria-cabecera {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  margin-bottom: 0.55rem;
}

.memoria-cabecera .disco-popover-titulo {
  margin: 0;
}

.memoria-toggle {
  display: inline-flex;
  flex: none;
  gap: 2px;
  padding: 2px;
  border: 1px solid var(--border);
  border-radius: 999px;
}

.memoria-toggle-boton {
  border: none;
  background: transparent;
  color: var(--muted-foreground);
  font-size: 0.68rem;
  font-weight: 600;
  line-height: 1;
  padding: 0.3rem 0.6rem;
  border-radius: 999px;
  cursor: pointer;
  min-height: 24px;
}

.memoria-toggle-boton:hover {
  background: var(--secondary);
}

.memoria-toggle-boton[aria-pressed="true"] {
  background: var(--accent);
  color: var(--accent-foreground);
}

/* La fila sintética Kernel + ZRAM se separa visualmente de los grupos. */
.proceso-row-kernel {
  border-top: 1px dashed var(--border);
  padding-top: 0.4rem;
}

/* La lista anula el padding por defecto del <ol> del navegador (40px) que
   desaprovechaba la izquierda del popover y empujaba todo a la derecha. */
#memoria-procesos {
  display: grid;
  gap: 0.45rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.proceso-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  gap: 0.15rem 0.6rem;
  align-items: center;
  font-size: 0.78rem;
}

.proceso-cuerpo {
  display: flex;
  flex-direction: column;
  min-width: 0;
  gap: 0.1rem;
}

.proceso-etiqueta {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: 600;
}

.proceso-meta {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--muted-foreground);
  font-size: 0.72rem;
  font-variant-numeric: tabular-nums;
}

.proceso-bytes,
.proceso-pct {
  color: var(--muted-foreground);
  font-variant-numeric: tabular-nums;
}

/* El texto dentro de la barra solo existe en la celda móvil. */
.proceso-barra-texto {
  display: none;
}

.vps-metric-tile.fijado {
  border-color: var(--ring);
  box-shadow: 0 0 0 1px var(--ring);
}

/* En táctil (sin hover) el botón queda visible siempre. */
@media (hover: none) {
  .tile-historico-boton {
    opacity: 1;
  }
}

/* ─── Densidad por tarjeta (container queries) ───
   Tarjeta angosta (rejilla de dos columnas junto al sidebar): los tiles
   pasan a dos columnas, los hechos del servidor a dos por fila y las cards
   de consumo a dos, devolviéndole a cada valor el ancho que necesita.
   Van al final del archivo para ganar en cascada a las reglas base. */
@container (max-width: 1100px) {
  /* La franja de identidad ya es flex con wrap: en tarjetas angostas los
     hechos (Servidor, IPv4) fluyen solos a la línea siguiente. */
  .vps-server-facts dd {
    font-size: 0.72rem;
  }

  .vps-metric-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .ds-top-cards {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .tile-reading strong {
    font-size: 1.32rem;
  }

  .mini-chart {
    width: 3rem;
  }

  .ds-card-value strong {
    font-size: 1.7rem;
  }

  .salud-resumen-franja {
    grid-template-columns: minmax(0, 1fr);
  }

  .salud-grid {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas:
      'tandas'
      'hormonas'
      'metricas';
  }
}

/* La mini-app de finanzas apila sus dos tarjetas (ingresos arriba, gastos
   debajo) a ancho COMPLETO, en celular y escritorio: no hereda las cuatro
   columnas del consumo ni el contenedor angosto. Con las dos columnas la
   información no cabía (títulos y montos del desglose cortados en 390) y
   Santiago pidió fila completa para ver los datos sin apretujar
   (23-sep-2026). En escritorio se midió el tope centrado (88rem) y se
   descartó: el resto del Resumen (pendientes, últimos movimientos) ya usa
   todo el ancho del módulo y las tarjetas quedaban desalineadas del
   conjunto. */
.finanzas-top-cards {
  grid-template-columns: minmax(0, 1fr);
}

/* En móvil el valor va arriba y el mini-gráfico debajo a todo el ancho:
   ningún valor se trunca en pantallas angostas. */
@media (max-width: 720px) {
  .tile-reading {
    flex-direction: column;
    align-items: stretch;
    gap: 0.35rem;
  }

  .mini-chart {
    width: 100%;
  }
}

/* ─── F1 · Sidebar colapsable (rail de iconos) ─────────────────────────
   El botón chevron contrae el sidebar fijo a un rail de 3.5rem con solo
   iconos. El estado vive en body.is-collapsed y las reglas van al final
   para ganar la cascada. Solo aplica en escritorio: en móvil el sidebar ya
   es un cajón y el botón se oculta. */

.sidebar-collapse {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 1.5rem;
  height: 1.5rem;
  margin-left: auto;
  padding: 0;
  border: none;
  border-radius: calc(var(--radius) - 2px);
  background: transparent;
  color: var(--muted-foreground);
  cursor: pointer;
}

.sidebar-collapse:hover {
  background: var(--accent);
  color: var(--accent-foreground);
}

.sidebar-collapse svg {
  transition: transform 0.18s ease;
}

/* El rail solo tiene sentido en escritorio; en pantallas angostas el
   sidebar es un cajón que se abre completo y no se puede colapsar. */
@media (min-width: 721px) {
  body.is-collapsed {
    --sidebar-w: 3.5rem;
  }

  body.is-collapsed .sidebar-brand {
    flex-direction: column;
    align-items: center;
    gap: 0.5rem;
  }

  body.is-collapsed .sidebar-brand-name,
  body.is-collapsed .sidebar-brand-sub,
  body.is-collapsed .sidebar-group-title,
  body.is-collapsed .sidebar-link span,
  body.is-collapsed .sidebar-planned,
  body.is-collapsed .sidebar-note {
    display: none;
  }

  /* El rail de iconos no tiene espacio para submenús: el sub-ítem de
     finanzas (Configuración) se oculta del todo cuando está contraído y
     vuelve a aparecer como submenú indentado al expandir. */
  body.is-collapsed .sidebar-sublist {
    display: none;
  }

  body.is-collapsed .sidebar-sublist-toggle {
    display: none;
  }

  body.is-collapsed .sidebar-link {
    justify-content: center;
    gap: 0;
    padding: 0.5rem;
    min-height: 44px;
  }

  body.is-collapsed .sidebar-collapse {
    margin-left: 0;
  }

  body.is-collapsed .sidebar-collapse svg {
    transform: rotate(180deg);
  }
}

@media (prefers-reduced-motion: reduce) {
  .app-sidebar,
  .app-frame,
  .sidebar-collapse svg {
    transition: none;
  }
}

@media (max-width: 720px) {
  .sidebar-collapse {
    display: none;
  }
}

/* ─── M01 · Histórico on-demand ──────────────────────────────────────────
   Tarjeta anidada que se abre al pulsar una tile de recurso. Va al final
   para ganar en cascada y respeta el movimiento reducido. */

.historico-panel {
  margin: 0 1.25rem 1.25rem;
  padding: 1rem 1.25rem;
  border: 1px solid var(--border);
  border-radius: calc(var(--radius) + 2px);
  background: var(--card);
}

.historico-panel .ds-header {
  padding: 0 0 0.9rem;
}

.historico-panel .ds-header-title h3 {
  margin: 0.1rem 0 0.25rem;
  font-size: 1rem;
  font-weight: 700;
  letter-spacing: -0.015em;
}

.historico-controles {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.historico-panel .ds-select select {
  border: none;
  background: transparent;
  color: var(--foreground);
  font-size: 0.8rem;
  font-weight: 600;
  cursor: pointer;
}

.historico-chart {
  display: block;
  width: 100%;
  height: 200px;
}

.historico-chart path {
  fill: none;
  stroke: var(--chart-2);
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.historico-estado {
  min-height: 1.2rem;
  margin: 0.6rem 0 0;
  color: var(--muted-foreground);
  font-size: 0.78rem;
}

/* Las tiles de recurso son objetivos táctiles con cursor de enlace. */
.vps-metric-tile[role="button"] {
  cursor: pointer;
}

.vps-metric-tile[role="button"]:hover {
  border-color: var(--ring);
}

@media (max-width: 720px) {
  .historico-panel {
    margin: 0 0.75rem 1rem;
    padding: 0.85rem 0.75rem;
  }

  .historico-panel .ds-header {
    display: flex;
    flex-direction: column;
    align-items: stretch;
  }

  .historico-controles {
    width: 100%;
    justify-content: space-between;
  }
}

@media (prefers-reduced-motion: reduce) {
  .historico-chart path {
    transition: none;
  }

  .salud-rango-gauge-linea,
  .salud-rango-gauge-segmento,
  .salud-rango-gauge-punto,
  .salud-rango-gauge-escala,
  .salud-chip,
  .salud-chip .salud-icono-trazo,
  .module-view.swipe-in-izq,
  .module-view.swipe-in-der {
    animation: none;
  }
}

/* ─── Mapa de puertos (M01) ──────────────────────────────────────────────
   Agregado por puerto único (TCP+UDP). El color codifica la exposición:
   pública (todas las interfaces), interna (Docker/Tailscale) o solo local. */

.puertos-strip {
  padding: 0.9rem 1.25rem;
  border-bottom: 1px solid var(--border);
}

.puertos-heading {
  margin-bottom: 0.4rem;
  align-items: flex-start;
}

.puertos-heading-texto {
  min-width: 0;
  flex: 1 1 auto;
}

.puertos-heading-controles {
  display: flex;
  align-items: center;
  gap: 0.2rem;
  flex: none;
}

.puertos-toggle {
  display: grid;
  place-items: center;
  width: 2.4rem;
  height: 2.4rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: transparent;
  color: var(--muted-foreground);
  cursor: pointer;
}

.puertos-toggle:hover {
  color: var(--foreground);
  border-color: var(--ring);
}

.puertos-toggle svg {
  transition: transform 180ms ease;
}

.puertos-toggle[aria-expanded="false"] svg {
  transform: rotate(-90deg);
}

.puertos-heading h2 {
  display: flex;
  align-items: center;
  flex-wrap: nowrap;
  gap: 0.5rem;
  min-width: 0;
  overflow: hidden;
}

.puertos-heading p {
  margin-top: 0.1rem;
}

.status-pill[data-state="error"] {
  border-color: color-mix(in srgb, var(--destructive) 30%, transparent);
  background: color-mix(in srgb, var(--destructive) 8%, transparent);
  color: color-mix(in srgb, var(--destructive) 78%, var(--foreground));
}

.puertos-resumen {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0.5rem;
  margin: 0 0 0.6rem;
}

.puertos-kpi {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 0.4rem 0.6rem;
  background: var(--card);
  min-width: 0;
}

.puertos-kpi[data-exposicion="publica"] { border-left: 3px solid var(--destructive); }
.puertos-kpi[data-exposicion="interna"] { border-left: 3px solid var(--warning); }
.puertos-kpi[data-exposicion="local"] { border-left: 3px solid var(--success); }

.puertos-kpi dt {
  margin: 0;
  font-size: 0.68rem;
  color: var(--muted-foreground);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.puertos-kpi dd {
  margin: 0.1rem 0 0;
  font-size: 1.05rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  line-height: 1.2;
}

.puertos-mapa-wrap {
  position: relative;
  margin-bottom: 0.4rem;
}

.puertos-mapa {
  display: block;
  width: 100%;
  height: auto;
}

.puertos-mapa .puerto-eje {
  stroke: var(--border);
  stroke-width: 1;
  stroke-dasharray: 2 3;
}

.puertos-mapa text {
  font-size: 9px;
  fill: var(--muted-foreground);
}

.puertos-mapa .puerto-punto {
  cursor: default;
  transition: opacity 140ms ease;
}

.puertos-mapa .puerto-punto[data-exposicion="publica"] { fill: var(--destructive); }
.puertos-mapa .puerto-punto[data-exposicion="interna"] { fill: var(--warning); }
.puertos-mapa .puerto-punto[data-exposicion="local"] { fill: var(--success); }

.puertos-mapa .puerto-punto.is-dimmed { opacity: 0.12; }
.puertos-mapa .puerto-punto.is-resaltado {
  stroke: var(--foreground);
  stroke-width: 1.5;
}

.puertos-histograma {
  display: none;
  width: 100%;
  height: 120px;
}

.puertos-histograma rect {
  fill: var(--border);
  opacity: 0.55;
  transition: opacity 140ms ease;
}

.puertos-histograma rect[data-exposicion] { opacity: 1; }

.puertos-histograma rect[data-exposicion="publica"] { fill: var(--destructive); }
.puertos-histograma rect[data-exposicion="interna"] { fill: var(--warning); }
.puertos-histograma rect[data-exposicion="local"] { fill: var(--success); }

.puertos-histograma rect:hover,
.puertos-histograma rect:focus {
  opacity: 0.72;
}

.puertos-histograma text {
  font-size: 8px;
  fill: var(--muted-foreground);
  text-anchor: middle;
}

.puertos-histograma text.barra-conteo {
  font-size: 10px;
  font-weight: 650;
  fill: var(--foreground);
}

.puertos-tooltip {
  min-width: 11rem;
}

.puertos-leyenda {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-bottom: 0.6rem;
}

.puertos-leyenda button {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  min-height: 30px;
  border: 1px solid var(--border);
  background: var(--card);
  color: var(--foreground);
  border-radius: 999px;
  padding: 0.15rem 0.65rem;
  font-size: 0.72rem;
  font-weight: 600;
  cursor: pointer;
}

.puertos-leyenda button[aria-pressed="true"] {
  border-color: var(--primary);
  background: var(--primary);
  color: var(--primary-foreground);
}

.puertos-leyenda .leyenda-dot {
  width: 0.55rem;
  height: 0.55rem;
  border-radius: 50%;
  display: inline-block;
  flex: none;
}

.puertos-lista {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(10.5rem, 1fr));
  gap: 0.4rem;
}

.puertos-lista.is-colapsada {
  display: none;
}

.puerto-chip {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  border: 1px solid var(--border);
  border-left-width: 3px;
  border-radius: var(--radius);
  padding: 0.35rem 0.55rem;
  background: var(--card);
  min-width: 0;
  cursor: pointer;
  width: 100%;
  color: inherit;
  font: inherit;
  text-align: left;
}

.puerto-chip[data-exposicion="publica"] { border-left-color: var(--destructive); }
.puerto-chip[data-exposicion="interna"] { border-left-color: var(--warning); }
.puerto-chip[data-exposicion="local"] { border-left-color: var(--success); }

.puerto-chip.is-oculto { display: none; }
.puertos-lista > li.is-oculto { display: none; }

.puerto-chip:hover,
.puerto-chip:focus-visible {
  border-color: var(--ring);
  border-left-width: 3px;
}

.puerto-chip-cabecera {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.4rem;
  min-width: 0;
}

.puerto-chip-numero {
  font-weight: 700;
  font-size: 1rem;
  font-variant-numeric: tabular-nums;
}

.puerto-chip-protocolo {
  font-size: 0.6rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  color: var(--muted-foreground);
  text-transform: uppercase;
}

.puerto-chip-etiqueta {
  font-size: 0.72rem;
  color: var(--muted-foreground);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.puerto-chip-meta {
  font-size: 0.66rem;
  color: var(--muted-foreground);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.puerto-detalle {
  position: fixed;
  right: 1rem;
  bottom: 1rem;
  z-index: 70;
  width: 20rem;
  max-width: min(21rem, calc(100vw - 1.5rem));
  max-height: 60vh;
  overflow-y: auto;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--card);
  padding: 0.85rem 1rem;
  box-shadow: 0 14px 40px rgb(0 0 0 / 0.22);
}

.puerto-detalle-cabecera {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
}

.puerto-detalle-cabecera h3 {
  margin: 0;
  font-size: 0.95rem;
  font-variant-numeric: tabular-nums;
}

.puerto-detalle-cerrar {
  display: grid;
  place-items: center;
  width: 1.9rem;
  height: 1.9rem;
  flex: none;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: transparent;
  color: var(--muted-foreground);
  cursor: pointer;
}

.puerto-detalle-cerrar:hover {
  color: var(--foreground);
  border-color: var(--ring);
}

.puerto-detalle-cuerpo {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 0.3rem 0.8rem;
  margin: 0.6rem 0 0;
}

.puerto-detalle-fila {
  display: contents;
}

.puerto-detalle-cuerpo dt {
  font-size: 0.7rem;
  color: var(--muted-foreground);
}

.puerto-detalle-cuerpo dd {
  margin: 0;
  font-size: 0.78rem;
  overflow-wrap: anywhere;
  min-width: 0;
}

@media (prefers-reduced-motion: reduce) {
  .puertos-mapa .puerto-punto { transition: none; }
}

@media (max-width: 720px) {
  .puertos-heading {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
  }

  .puertos-resumen {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .puertos-lista {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  .puertos-mapa {
    display: none;
  }

  .puertos-histograma {
    display: block;
    height: 120px;
  }

  .puertos-leyenda {
    flex-wrap: nowrap;
  }

  .puertos-leyenda button {
    font-size: 0.66rem;
    gap: 0.25rem;
    padding: 0.15rem 0.5rem;
  }

  .puerto-detalle {
    --puerto-inset-top: env(safe-area-inset-top, 0px);
    --puerto-inset-right: env(safe-area-inset-right, 0px);
    --puerto-inset-bottom: env(safe-area-inset-bottom, 0px);
    --puerto-inset-left: env(safe-area-inset-left, 0px);
    left: 50%;
    right: auto;
    bottom: 0.75rem;
    transform: translateX(-50%);
    width: min(21rem, calc(100vw - var(--puerto-inset-left) - var(--puerto-inset-right) - 1.5rem));
    max-height: calc(100dvh - 1rem);
  }

  .puerto-detalle.is-anclado {
    right: auto;
    bottom: auto;
    transform: none;
  }
}

/* ═══ Barra inferior de finanzas (estilo iOS, solo móvil/tablet) ═══════════ */

/* En escritorio no existe: el sidebar ya navega. */
.finanzas-tabbar {
  display: none;
}

.finanzas-tabbar[hidden] {
  display: none;
}

@media (max-width: 720px) {
  /* La barra vive dentro del módulo finanzas: si la vista está oculta, su
     barra no se ve. Cápsula flotante estilo iOS: separada de los bordes,
     esquinas redondeadas, desenfoque y sombra; respeta el área segura del
     home indicator en iPhone. */
  .finanzas-tabbar {
    position: fixed;
    left: 0.75rem;
    right: 0.75rem;
    bottom: calc(0.6rem + env(safe-area-inset-bottom, 0px));
    z-index: 40;
    display: grid;
    grid-template-columns: 1fr 1fr 3rem 1fr 1fr;
    align-items: center;
    padding: 0.28rem 0.3rem;
    border-radius: 2rem;
    background: var(--finanzas-tabbar-bg);
    -webkit-backdrop-filter: blur(16px) saturate(1.4);
    backdrop-filter: blur(16px) saturate(1.4);
    border: 1px solid var(--finanzas-tabbar-borde);
    box-shadow: 0 8px 28px hsl(0 0% 0% / 0.14);
  }

  .finanzas-tabbar-tab {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.1rem;
    min-height: 40px;
    padding: 0.25rem 0.05rem;
    border: none;
    border-radius: 1.4rem;
    background: none;
    color: var(--finanzas-tabbar-fg);
    font-family: var(--font-sans);
    font-size: 0.58rem;
    font-weight: 500;
    line-height: 1;
    text-decoration: none;
  }

  .finanzas-tabbar-tab[aria-current="page"] {
    color: var(--finanzas-tabbar-fg-activo);
    font-weight: 600;
  }

  .finanzas-tabbar-tab:focus-visible,
  .finanzas-tabbar-alta:focus-visible {
    outline: 2px solid var(--ring);
    outline-offset: 2px;
  }

  /* Botón central de alta rápida, al ras de la cápsula (estilo Instagram):
     acento circular sin sobresalir de la barra. */
  .finanzas-tabbar-alta {
    display: grid;
    place-items: center;
    justify-self: center;
    width: 2.4rem;
    height: 2.4rem;
    border: none;
    border-radius: 999px;
    background: var(--primary);
    color: var(--primary-foreground);
    box-shadow: 0 3px 10px hsl(0 0% 0% / 0.2);
    cursor: pointer;
  }

  .finanzas-tabbar-alta[aria-expanded="true"] {
    transform: rotate(45deg);
  }

  /* Selector gasto/ingreso: hoja pequeña que flota sobre el botón central. */
  .finanzas-tabbar-alta-menu {
    position: absolute;
    left: 50%;
    bottom: calc(100% - 0.5rem);
    transform: translateX(-50%);
    display: grid;
    gap: 0.2rem;
    width: 11rem;
    padding: 0.4rem;
    background: var(--popover);
    border: 1px solid var(--finanzas-tabbar-borde);
    border-radius: var(--radius);
    box-shadow: 0 10px 32px hsl(0 0% 0% / 0.18);
  }

  .finanzas-tabbar-alta-menu[hidden] {
    display: none;
  }

  .finanzas-tabbar-alta-opcion {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    min-height: 44px;
    padding: 0.55rem 0.75rem;
    border: none;
    border-radius: calc(var(--radius) - 0.15rem);
    background: none;
    color: var(--foreground);
    font-family: var(--font-sans);
    font-size: 0.92rem;
    text-align: left;
    cursor: pointer;
  }

  .finanzas-tabbar-alta-opcion:hover,
  .finanzas-tabbar-alta-opcion:focus-visible {
    background: var(--accent);
    outline: none;
  }

  .finanzas-tabbar-alta-simbolo {
    display: grid;
    place-items: center;
    width: 1.6rem;
    height: 1.6rem;
    border-radius: 999px;
    font-size: 1rem;
    font-weight: 700;
    line-height: 1;
    color: #fff;
  }

  .finanzas-tabbar-alta-opcion[data-tabbar-alta-tipo="gasto"] .finanzas-tabbar-alta-simbolo {
    background: var(--destructive);
  }

  .finanzas-tabbar-alta-opcion[data-tabbar-alta-tipo="ingreso"] .finanzas-tabbar-alta-simbolo {
    background: var(--success);
  }

  /* Aire inferior: la barra fija no debe tapar los últimos movimientos. */
  #vista-finanzas .finanzas-module {
    padding-bottom: calc(6.4rem + env(safe-area-inset-bottom, 0px));
  }

  /* El '+' de cada tarjeta de resumen queda en línea con el título, arriba
     a la derecha del contenedor (sin saltar de fila en pantallas angostas). */
  .finanzas-card .ds-card-header {
    flex-wrap: nowrap;
  }

  .finanzas-card .ds-card-header h3 {
    flex: 1 1 auto;
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
}

/* ─── Correo → Pendientes por aprobar (M04) ──────────────────────────────── */

.finanzas-pendientes {
  padding: 0 1.25rem 0.4rem;
}

.finanzas-pendientes-cabecera {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  margin: 0.9rem 0 0.6rem;
}

.finanzas-pendientes-cabecera h3 {
  margin: 0;
  color: var(--muted-foreground);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.finanzas-pendientes-contador {
  color: var(--primary);
}

.finanzas-pendientes-estado {
  margin: 0 0 0.55rem;
  color: var(--muted-foreground);
  font-size: 0.78rem;
}

/* La pista implícita del grid resolvía al min-content de la fila más larga
   (628 px medidos en una lista de 348 px): la fila corta del aviso cabía en
   UNA línea de esa pista y sus acciones quedaban más allá del borde de la
   lista, recortadas por .module-track-wrap y sin scroll (hallazgo móvil
   390/428, t_449c2e0c). La pista se acota al ancho disponible y la fila
   puede encogerse: con eso toda fila envuelve dentro de la lista. */
.finanzas-pendientes-lista {
  grid-template-columns: minmax(0, 1fr);
}

.finanzas-pendiente-fila {
  display: grid;
  min-width: 0;
  grid-template-columns: 5.6rem minmax(0, 1fr) minmax(7rem, 9rem) auto auto;
  gap: 0.55rem;
  align-items: center;
  padding: 0.5rem 0.65rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--card);
}

.finanzas-pendiente-fecha {
  color: var(--muted-foreground);
  font-size: 0.78rem;
  white-space: nowrap;
}

.finanzas-pendiente-detalle {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.finanzas-pendiente-concepto {
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.finanzas-pendiente-origen {
  color: var(--muted-foreground);
  font-size: 0.72rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.finanzas-pendiente-categoria {
  min-height: 34px;
  padding: 0.2rem 0.35rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--background);
  color: var(--foreground);
  font: inherit;
  font-size: 0.8rem;
}

.finanzas-pendiente-monto {
  font-weight: 650;
  color: var(--destructive);
  white-space: nowrap;
}

.finanzas-pendiente-monto.monto-pendiente-completar {
  color: var(--muted-foreground);
  font-weight: 550;
}

.finanzas-pendiente-acciones {
  display: flex;
  gap: 0.3rem;
}

.finanzas-pendiente-boton {
  min-width: 34px;
  min-height: 34px;
  padding: 0 0.4rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--secondary);
  color: var(--primary);
  font: inherit;
  font-size: 0.8rem;
  font-weight: 650;
  cursor: pointer;
}

.finanzas-pendiente-boton:hover {
  border-color: var(--primary);
}

.finanzas-pendiente-boton.boton-aprobar {
  color: var(--success);
}

.finanzas-pendiente-boton.boton-descartar {
  color: var(--destructive);
}

/* ─── Conciliación bancaria (SPEC 007) ───────────────────────────────────── */
/* El aviso del banco que coincide con un movimiento registrado: la línea del
   cruce y la acción «Conciliar» (un toque, sin duplicar el gasto). */
.finanzas-pendiente-cruce {
  font-size: 0.78rem;
  color: var(--success);
}

.finanzas-pendiente-cobro {
  font-size: 0.78rem;
  color: var(--muted-foreground);
}

.finanzas-pendiente-boton.boton-conciliar {
  color: var(--success);
  font-weight: 600;
}

.finanzas-ingesta {
  margin-top: 1.4rem;
}

.finanzas-ingesta-token {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 0.5rem;
}

.finanzas-ingesta-token .finanzas-field {
  flex: 1 1 16rem;
}

.finanzas-ingesta-acciones {
  display: flex;
  gap: 0.5rem;
}

.finanzas-atajo {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.6rem;
  margin: 0.9rem 0 0.3rem;
}

.finanzas-atajo-descargar {
  text-decoration: none;
}

.finanzas-atajo-descargar[aria-disabled='true'] {
  opacity: 0.55;
  pointer-events: none;
}

.finanzas-ingesta-pasos {
  margin: 0.8rem 0;
  font-size: 0.85rem;
  color: var(--muted-foreground);
}

.finanzas-ingesta-pasos summary {
  cursor: pointer;
  color: var(--foreground);
}

.finanzas-ingesta-pasos ol {
  margin: 0.5rem 0 0 1.1rem;
  padding: 0;
  display: grid;
  gap: 0.35rem;
}

.finanzas-ingesta-pasos code {
  font-size: 0.78rem;
}

.finanzas-pendiente-edicion {
  display: grid;
  grid-template-columns: 8.6rem minmax(0, 1fr) minmax(6.5rem, 8rem) auto auto;
  gap: 0.4rem;
  align-items: center;
  grid-column: 1 / -1;
}

.finanzas-pendiente-input {
  min-height: 40px;
  width: 100%;
  padding: 0.35rem 0.5rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--background);
  color: var(--foreground);
  font: inherit;
  font-size: 0.85rem;
}

/* ─── Multi-moneda (SPEC 004) ────────────────────────────────────────────── */
/* El símbolo de la moneda como chip delante del valor («US$ 6,99»): se lee
   de un vistazo que el cobro es extranjero (revisión del preview). */
.finanzas-moneda-chip {
  display: inline-block;
  padding: 0.02rem 0.34rem;
  margin-right: 0.1rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--muted-foreground);
  white-space: nowrap;
}

/* ≈ COP: segunda línea pequeña bajo el monto original. */
.finanzas-monto-aprox {
  display: block;
  font-size: 0.68rem;
  font-weight: 500;
  color: var(--muted-foreground);
}

/* «sin convertir»: el movimiento espera conciliación bancaria. */
.finanzas-monto-aprox.sin-convertir {
  font-style: italic;
}

/* Ronda 2 (t_18a88f2a, 23-sep-2026): el subtotal de monedas del período va EN
   LÍNEA con el total en COP —dentro de la misma fila de valor— y la fila
   envuelve a una segunda línea legible antes que encoger en pantallas
   angostas (con separación horizontal explícita; nada se trunca). */
.finanzas-card .ds-card-value {
  flex-wrap: wrap;
  column-gap: 0.55rem;
  row-gap: 0.2rem;
}

.finanzas-subtotales-moneda {
  margin: 0;
  font-size: 1.05rem;
  font-weight: 650;
  font-variant-numeric: tabular-nums;
  color: var(--destructive);
  white-space: normal;
}

/* Formularios: nota de procedencia de la tasa y el equivalente calculado. */
.finanzas-tasa-nota {
  font-size: 0.72rem;
  color: var(--muted-foreground);
}

.finanzas-tasa-nota.is-error {
  color: var(--destructive);
}

.finanzas-conversion input {
  background: var(--secondary);
  color: var(--muted-foreground);
}

/* Aprobación de un recibo extranjero: la fila se vuelve formulario de tasa. */
.finanzas-pendiente-tasa {
  grid-template-columns: minmax(0, 1.3fr) minmax(5.5rem, 7.5rem) auto auto;
}

.finanzas-pendiente-tasa-campo {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  min-width: 0;
}

.finanzas-pendiente-conversion {
  font-weight: 650;
  font-variant-numeric: tabular-nums;
  color: var(--destructive);
  white-space: nowrap;
}

/* Desglose de ítems del recibo: panel plegable dentro de la fila. */
.finanzas-pendiente-desglose {
  grid-column: 1 / -1;
  flex: 1 1 100%;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  margin-top: 0.15rem;
  padding: 0.55rem 0.65rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--secondary);
}

.finanzas-pendiente-items {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}

.finanzas-pendiente-item {
  display: flex;
  flex-direction: column;
  gap: 0.05rem;
  min-width: 0;
}

.finanzas-pendiente-item-principal {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 0.6rem;
}

.finanzas-pendiente-item-nombre {
  min-width: 0;
  font-size: 0.84rem;
  overflow-wrap: anywhere;
}

.finanzas-pendiente-item-nota {
  color: var(--muted-foreground);
  font-size: 0.7rem;
}

.finanzas-pendiente-item-monto {
  font-size: 0.84rem;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.finanzas-pendiente-totales {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 0.15rem 0.6rem;
  padding-top: 0.35rem;
  border-top: 1px solid var(--border);
  color: var(--muted-foreground);
  font-size: 0.78rem;
}

.finanzas-pendiente-total-monto {
  font-variant-numeric: tabular-nums;
  text-align: right;
  white-space: nowrap;
}

.finanzas-pendiente-totales .total-fuerte {
  color: var(--foreground);
  font-weight: 650;
}

.finanzas-pendiente-boton.boton-detalle {
  color: var(--primary);
}

.finanzas-pendientes-pie {
  padding: 0.2rem 0.1rem 0;
  color: var(--muted-foreground);
  font-size: 0.74rem;
}

/* Configuración: cuentas de correo y ajustes de búsqueda */

.finanzas-correo {
  margin-top: 1.4rem;
}

.finanzas-correo-titulo {
  margin: 0 0 0.2rem;
  color: var(--muted-foreground);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.finanzas-correo-cuentas {
  grid-template-columns: minmax(0, 1fr);
  margin: 0.4rem 0 0.8rem;
}

.finanzas-correo-cuenta {
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.5rem 0.65rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
}

.finanzas-correo-cuenta-datos {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.finanzas-correo-cuenta-direccion {
  display: block;
  min-width: 0;
  font-size: 0.86rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.finanzas-correo-cuenta-detalle {
  color: var(--muted-foreground);
  font-size: 0.74rem;
}

.finanzas-correo-cuenta-error {
  color: var(--destructive);
  font-size: 0.74rem;
}

.finanzas-correo-cuenta-botones {
  display: flex;
  gap: 0.35rem;
  align-items: center;
  flex: none;
}

.finanzas-correo-cuenta-chip {
  padding: 0.15rem 0.55rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  color: var(--muted-foreground);
  font-size: 0.72rem;
}

.finanzas-correo-fields {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0.6rem;
  margin: 0.2rem 0 0.6rem;
}

@media (max-width: 720px) {
  .finanzas-pendientes-cabecera {
    flex-wrap: wrap;
  }

  .finanzas-pendientes-cabecera h3 {
    white-space: nowrap;
  }

  .finanzas-pendientes-cabecera .finanzas-boton-ghost {
    white-space: nowrap;
  }

  .finanzas-pendiente-fila {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
  }

  .finanzas-pendiente-detalle {
    flex: 1 1 8rem;
  }

  .finanzas-pendiente-categoria {
    order: 4;
    flex: 1 1 8rem;
    min-height: 40px;
  }

  .finanzas-pendiente-monto {
    order: 3;
  }

  /* El concepto (título del gasto) baja 2px: más densidad en el ancho de
     pantalla (revisión de Santiago, 12-sep-2026). */
  .finanzas-pendiente-concepto {
    font-size: 0.875rem;
  }

  .finanzas-pendiente-acciones {
    order: 5;
  }

  .finanzas-pendiente-edicion {
    grid-template-columns: 1fr;
  }

  .finanzas-pendiente-edicion .finanzas-pendiente-input {
    min-height: 44px;
  }

  .finanzas-correo-fields {
    grid-template-columns: 1fr;
  }
}

/* WebKit/iOS amplía la página (autozoom) al enfocar un control con letra
   menor a 16px: el encuadre salta y la vista queda descoordinada. En
   pantallas angostas o punteros táctiles los campos del módulo de finanzas
   suben a 1rem; en escritorio conservan su densidad (0.88rem). */
@media (max-width: 720px), (pointer: coarse) {
  .finanzas-field input,
  .finanzas-field select,
  .finanzas-categoria-rapida input,
  .finanzas-pendiente-input,
  .finanzas-pendiente-categoria,
  .finanzas-field .finanzas-calendario-campo {
    font-size: 1rem;
  }

  /* Los select de categoría de los flujos de Fijos y Pendientes se dibujan
     ~14px con el truco de transform: el control conserva su font-size de 16px
     (el umbral de iOS se evalúa sobre lo declarado) y queda alineado con el
     resto de la fila (revisión de Santiago, 12-sep-2026). Ronda 6
     (t_0ca41d80): el select de la CAPTURA sale del truco —con todos los campos
     a 16px y 44px de alto, encogerlo lo dejaría como la única caja de 38.5 px
     y rompería el alto único del formulario. */
  #finanzas-fijo-categoria,
  .finanzas-pendiente-categoria {
    transform: scale(0.875);
    transform-origin: left center;
  }

  /* Ronda 8 (t_3f3dff4b): el alto de los OCHO controles de la captura es UNO
     solo —44 px, el mínimo táctil— y EXPLÍCITO, no emergente. Medido en
     Chrome los ocho ya daban 44.00 px (Δ0): la diferencia visible entre el
     selector y los campos era el line-height (normal vs 24px) y la apariencia
     nativa, no el alto. Con la altura clavada, el control nativo del selector
     o del date picker no puede desviarla al dibujarse. */
  .finanzas-form-en-tarjeta #finanzas-fecha,
  .finanzas-form-en-tarjeta #finanzas-concepto,
  .finanzas-form-en-tarjeta #finanzas-categoria,
  .finanzas-form-en-tarjeta #finanzas-moneda,
  .finanzas-form-en-tarjeta #finanzas-monto,
  .finanzas-form-en-tarjeta #finanzas-monto-ext,
  .finanzas-form-en-tarjeta .finanzas-categoria-mas,
  .finanzas-form-en-tarjeta #finanzas-guardar,
  .finanzas-form-en-tarjeta #finanzas-cancelar {
    height: 44px;
  }
}

/* ─── Movimientos: línea de tiempo del módulo ─── */

.finanzas-recientes-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.6rem;
}

.finanzas-ver-todos {
  color: var(--muted-foreground);
  font-size: 0.78rem;
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
}

.finanzas-ver-todos:hover {
  color: var(--foreground);
}

.finanzas-movimientos-filtros {
  display: grid;
  /* Los filtros (Tipo · Moneda · Categoría · Origen) van en UNA sola fila en
     cualquier ancho (revisión de Santiago, 14-sep-2026: columnas iguales;
     22-sep-2026: entra Origen). Desde la ronda 3 (23-sep-2026) Origen es una
     píldora MÁS de la fila —mismo aspecto, control y tamaño que los selects.
     Ronda 5 (t_b95c50a8 · 23-sep-2026): Santiago decide que los cuatro van en
     UNA fila TAMBIÉN en el celular («sé que caben»): el ancho que falta se
     paga con rótulos acortados y elididos («…»), jamás envolviendo. */
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0.6rem;
  margin: 0.6rem 0 0.8rem;
}

/* ─── La caja de los CUATRO controles es UNA sola (ronda 5b · t_d16192a7) ───
   Los tres selects y la píldora de Origen comparten la MISMA regla —no copias
   que puedan divergir—: alto, borde (grosor y color), fondo, radios, relleno
   simétrico y letra idénticos, y el texto CENTRADO en la caja. El relleno en
   línea (0.875rem) reserva el sitio del chevron en los dos costados, así que
   la etiqueta queda centrada sin quedar pegada a la flecha ni recortada; lo
   que no entra se ELIDE con «…» (nunca se desborda ni envuelve la fila).

   Los selects sueltan la apariencia nativa (`appearance: none`): en iOS el
   select se dibuja con métricas propias —por eso el mismo `rect` se veía más
   grande en Origen— y el chevron pasa a ser el MISMO svg en los cuatro, del
   mismo tamaño y color, al borde derecho. */
.finanzas-movimientos-filtros select,
.finanzas-movimientos-origen-pill {
  width: 100%;
  min-height: 44px;
  padding: 0.5rem 0.875rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--background);
  color: var(--foreground);
  font: inherit;
  font-size: 0.88rem;
  text-align: center;
  text-overflow: ellipsis;
  appearance: none;
  -webkit-appearance: none;
  overflow: hidden;
  cursor: pointer;
}

/* El select de la fila viaja en su envoltura: el ancla del chevron. */
.finanzas-movimientos-control {
  position: relative;
  display: block;
  min-width: 0;
}

/* El chevron de la fila: el mismo svg para los cuatro (mismo tamaño y color),
   flotando dentro del relleno derecho —fuera del texto y sin robar el toque—. */
.finanzas-filtro-chevron {
  position: absolute;
  right: 0.25rem;
  top: 50%;
  transform: translateY(-50%);
  color: var(--foreground);
  pointer-events: none;
  transition: transform 0.15s ease;
}

/* La píldora de Origen: la caja de arriba y, dentro, su etiqueta centrada (el
   span crece a todo lo ancho). Cerrada muestra el estado; al tocarla abre la
   lista de casillas. */
.finanzas-movimientos-origen-pill {
  position: relative;
  display: flex;
  align-items: center;
}

.finanzas-movimientos-origen-pill:hover,
.finanzas-movimientos-origen-pill[aria-expanded="true"] {
  border-color: var(--ring);
}

.finanzas-movimientos-origen-pill-texto {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Abierta, la flecha de Origen gira —y conserva su centrado vertical—. */
.finanzas-movimientos-origen-pill[aria-expanded="true"] .finanzas-filtro-chevron {
  transform: translateY(-50%) rotate(180deg);
}

/* Lista de casillas: panel flotante anclado a la píldora (no empuja la
   maquetación). Cada fila es un toque de 44 px que alterna SIN cerrarse; el
   estado marcado se distingue por relleno, borde Y la marca «✓». */
.finanzas-origen-panel {
  position: fixed;
  z-index: 40;
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  padding: 0.3rem;
  border: 1px solid var(--border);
  border-radius: calc(var(--radius) + 4px);
  background: var(--card);
  box-shadow: 0 18px 44px hsl(240 10% 3.9% / 0.3);
}

.finanzas-origen-panel[hidden] {
  display: none;
}

.finanzas-origen-opcion {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  min-height: 44px;
  padding: 0.25rem 0.55rem;
  border: 0;
  border-radius: var(--radius);
  background: transparent;
  color: var(--foreground);
  font: inherit;
  font-size: 0.88rem;
  font-weight: 600;
  text-align: left;
  cursor: pointer;
}

.finanzas-origen-opcion:hover {
  background: var(--secondary);
}

.finanzas-origen-casilla {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 22px;
  height: 22px;
  border: 1.5px solid var(--border);
  border-radius: 6px;
  background: var(--background);
  color: transparent;
  font-size: 0.8rem;
  font-weight: 700;
  line-height: 1;
}

.finanzas-origen-opcion[aria-checked="true"] {
  background: var(--secondary);
}

.finanzas-origen-opcion[aria-checked="true"] .finanzas-origen-casilla {
  border-color: var(--primary);
  background: var(--primary);
  color: var(--primary-foreground);
}

/* Uniformidad de la fila en el celular (ronda 4 · 23-sep-2026). Va DESPUÉS de
   las bases de la píldora y de las filas de su lista: la misma regla escrita
   antes (en el bloque de autozoom) la anulaba el orden de la cascada y la
   píldora quedaba en 0.88rem mientras los selects subían a 1rem.

   Ronda 5b (t_d16192a7): los CUATRO suben juntos a 1rem —también los selects,
   que ahora declaran su letra en la caja común— y el relleno en línea ya no se
   recorta aquí: la reserva del chevron (0.875rem en la caja común) es la misma
   en todos los anchos y así la etiqueta sigue centrada. Lo que no entra —la
   categoría, los rótulos largos— se ELIDE con «…», nunca se envuelve. */
@media (max-width: 720px), (pointer: coarse) {
  .finanzas-movimientos-filtros select,
  .finanzas-movimientos-origen-pill,
  .finanzas-origen-opcion {
    font-size: 1rem;
  }
}

@media (max-width: 720px) {
  .finanzas-movimientos-filtros {
    /* Ronda 5 (t_b95c50a8): los CUATRO comparten UNA sola fila también aquí
       —decisión de Santiago—: mismas cuatro columnas que en escritorio, con
       el aire entre columnas recortado (0.3rem) para que quepan. */
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 0.3rem;
  }
  .finanzas-movimientos-filtros .finanzas-field-label {
    font-size: 0.62rem;
  }
}

.finanzas-movimientos-totales {
  display: flex;
  flex-wrap: wrap;
  gap: 0.9rem 1.4rem;
  padding: 0.6rem 0.7rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--secondary);
}

.finanzas-movimientos-total {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
}

.finanzas-movimientos-total strong {
  font-size: 0.95rem;
  font-variant-numeric: tabular-nums;
}

.finanzas-movimientos-controles {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  margin: 0.7rem 0 0.4rem;
}

.finanzas-movimientos-conteo {
  color: var(--muted-foreground);
  font-weight: 600;
}

.finanzas-movimientos-lista {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  list-style: none;
  margin: 0;
  padding: 0;
}

.finanzas-movimiento {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  /* Fila minimalista (22-sep-2026): sin botones de acción el aire vertical se
     recorta y las zonas táctiles absorben la diferencia con márgenes negativos
     —la densidad sube sin perder áreas de 44 px. */
  gap: 0.35rem 0.5rem;
  padding: 0.4rem 0.5rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
}

.finanzas-movimiento-descartado {
  border-style: dashed;
  color: var(--muted-foreground);
}

/* Zonas táctiles de la edición rápida —fecha · concepto/categoría · valor—:
   el control mide 44 px de alto real (el mínimo cómodo), pero ocupa 32 px de
   rejilla gracias al margen negativo: la fila no crece por ellos. */
.finanzas-movimiento-fecha[data-rapida],
.finanzas-movimiento-cuerpo[data-rapida],
.finanzas-movimiento-monto[data-rapida] {
  appearance: none;
  background: none;
  border: 0;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
  min-height: 44px;
  margin-block: -6px;
  padding: 0.15rem 0.2rem;
  border-radius: var(--radius);
  transition: background-color 0.15s ease;
}

.finanzas-movimiento-fecha[data-rapida]:hover,
.finanzas-movimiento-cuerpo[data-rapida]:hover,
.finanzas-movimiento-monto[data-rapida]:hover {
  background: var(--secondary);
}

.finanzas-movimiento-fecha[data-rapida]:focus-visible,
.finanzas-movimiento-cuerpo[data-rapida]:focus-visible,
.finanzas-movimiento-monto[data-rapida]:focus-visible {
  outline: 2px solid var(--ring);
  outline-offset: 2px;
}

/* Cuña del extremo derecho: el afordante visible de la ficha. */
.finanzas-movimiento-cuna {
  appearance: none;
  background: none;
  border: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  min-width: 44px;
  min-height: 44px;
  margin: -6px -4px -6px 0;
  border-radius: var(--radius);
  color: var(--muted-foreground);
  cursor: pointer;
}

.finanzas-movimiento-cuna:hover {
  color: var(--foreground);
  background: var(--secondary);
}

/* Los descartados solo se ven con el toggle: conservan su única acción. */
.finanzas-movimiento-restaurar {
  flex: none;
  min-height: 34px;
}

.finanzas-movimiento-fecha {
  color: var(--muted-foreground);
  font-size: 0.78rem;
  white-space: nowrap;
  min-width: 3.2rem;
}

@media (max-width: 720px) {
  .finanzas-movimiento-fecha {
    min-width: 0;
  }
}

.finanzas-movimiento-cuerpo {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  min-width: 0;
  flex: 1 1 10rem;
}

.finanzas-movimiento-concepto {
  font-size: 0.88rem;
  overflow-wrap: anywhere;
}

.finanzas-movimiento-chips {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.3rem;
}

.finanzas-movimiento-chip {
  padding: 0.05rem 0.45rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  font-size: 0.68rem;
  color: var(--muted-foreground);
}

.finanzas-movimiento-chip.chip-descartado {
  border-color: var(--destructive);
  color: var(--destructive);
}

.finanzas-movimiento-monto {
  font-size: 0.88rem;
  font-weight: 650;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* Valor + cuña: un solo bloque que se pega al extremo derecho de la fila. */
.finanzas-movimiento-final {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  gap: 0.5rem;
  margin-left: auto;
}

/* ─── Edición rápida por secciones (22-sep-2026) ───
   El toque sobre una sección de la tarjeta la convierte en su control ahí
   mismo, con Guardar/Cancelar al lado. Todo el modo es cancelable (tocar fuera
   o «Cancelar») y nunca escribe por accidente.
   Fluidez (22-sep-2026, revisión de Santiago en el iPhone): el editor es una
   CAPA FLOTANTE sobre la fila —la fila conserva su contenido y su alto, y la
   lista no se mueve—, no un formulario en el flujo. */
.finanzas-rapida-abierta {
  position: relative;
  z-index: 6;
}

.finanzas-rapida {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  display: flex;
  flex-wrap: wrap;
  align-items: end;
  gap: 0.35rem 0.45rem;
  width: calc(100% - 4px);
  padding: 0.35rem 0.4rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  /* Tapa lo que deja debajo: la fila sigue ahí, intacta, sin saltar. */
  background: var(--card);
  box-shadow: 0 14px 34px hsl(240 10% 3.9% / 0.22);
}

.finanzas-rapida-campo {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  min-width: 0;
  flex: 1 1 8rem;
}

.finanzas-rapida-valor .finanzas-rapida-campo {
  flex: 1 1 7rem;
}

/* Editor del concepto: concepto y categoría se reparten la línea con anchos
   EXPLÍCITOS (4 partes / 3 partes, cada uno con mínimo legible) y las dos
   acciones circulares cierran la fila. La línea no se envuelve ni desborda:
   eso es lo que hace que el editor quepa dentro de la tarjeta, a 320 px
   incluidos. Antes los dos campos iban a 1:1 y las acciones caían a un segundo
   renglón (la fila medía 90,8 px de alto con el editor abierto). */
.finanzas-rapida-concepto {
  flex-wrap: nowrap;
}

.finanzas-rapida-concepto .finanzas-rapida-campo-concepto {
  flex: 4 1 0;
  min-width: 5.5rem;
}

.finanzas-rapida-concepto .finanzas-rapida-campo-categoria {
  flex: 3 1 0;
  min-width: 4.5rem;
}

.finanzas-rapida-label {
  color: var(--muted-foreground);
  font-size: 0.68rem;
  line-height: 1.1;
}

.finanzas-rapida-control {
  min-height: 44px;
  padding: 0.25rem 0.5rem;
  border: 1px solid var(--input);
  border-radius: var(--radius);
  background: var(--background);
  color: var(--foreground);
  font-size: 0.88rem;
  font-variant-numeric: tabular-nums;
}

/* El campo de fecha no es un input: es el botón que abre el calendario propio.
   Se dibuja como el resto de los controles del editor. */
.finanzas-rapida-fecha-campo,
.finanzas-calendario-campo {
  text-align: left;
  cursor: pointer;
}

.finanzas-rapida-acciones {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  gap: 0.4rem;
  flex: none;
}

.finanzas-rapida-acciones button {
  min-height: 44px;
  flex: none;
}

/* ✓ y ✗: un círculo de 44 px cada uno, sin texto — el mismo par en los tres
   editores rápidos, al final de la línea de los campos. Ocupan 94 px donde los
   dos botones rotulados ocupaban 167: eso es lo que deja la línea en UNA sola.
   El color no es la única información: llevan aria-label y title. */
.finanzas-rapida-accion {
  appearance: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  min-width: 44px;
  height: 44px;
  min-height: 44px;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: 50%;
  background: var(--background);
  cursor: pointer;
}

.finanzas-rapida-accion svg {
  width: 22px;
  height: 22px;
  display: block;
}

.finanzas-rapida-accion:hover {
  background: var(--accent);
}

.finanzas-rapida-accion:focus-visible {
  outline: 2px solid var(--ring);
  outline-offset: 2px;
}

.finanzas-rapida-accion-guardar {
  color: var(--finanzas-rapida-guardar);
  border-color: color-mix(in srgb, var(--finanzas-rapida-guardar) 45%, var(--border));
}

.finanzas-rapida-accion-cancelar {
  color: var(--finanzas-rapida-cancelar);
  border-color: color-mix(in srgb, var(--finanzas-rapida-cancelar) 45%, var(--border));
}

/* Chip del tipo en el editor del valor: muestra el tipo deducido del signo y
   lo corrige con un toque. Ancho estable: digitar no lo redimensiona. */
.finanzas-rapida-tipo {
  appearance: none;
  flex: none;
  min-width: 4.6rem;
  min-height: 44px;
  padding: 0.3rem 0.7rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: transparent;
  color: var(--muted-foreground);
  font: inherit;
  font-size: 0.78rem;
  font-weight: 600;
  cursor: pointer;
}

.finanzas-rapida-tipo.tipo-gasto {
  color: var(--destructive);
  border-color: color-mix(in srgb, var(--destructive) 45%, var(--border));
}

.finanzas-rapida-tipo.tipo-ingreso {
  color: var(--success);
  border-color: color-mix(in srgb, var(--success) 45%, var(--border));
}

/* iOS/iPadOS amplía la página (autozoom) al enfocar un control cuya letra
   declarada baja de 16 px: el encuadre salta, los botones parecen agrandarse y
   la interfaz se siente torpe. En pantallas angostas o punteros táctiles el
   editor rápido DECLARA 1rem (el umbral que evalúa iOS) y se DIBUJA a 0.875
   —el mismo truco ya validado en los selects de categoría—, así el texto queda
   del tamaño del resto de la fila sin que la pantalla se vuelva a encuadrar.
   Ojo: esta regla va DESPUÉS de la base; antes quedaba tapada por ella, y el
   recorte se limita al editor rápido: el campo de fecha del formulario
   detallado se dibuja como los demás campos (16 px, 44 px de alto). */
@media (max-width: 720px), (pointer: coarse) {
  .finanzas-rapida .finanzas-rapida-control {
    font-size: 1rem;
    transform: scale(0.875);
    transform-origin: left center;
  }
}

/* ─── Calendario compacto propio (edición rápida y formulario detallado) ───
   Sustituye al selector nativo de iOS: flota anclado a su campo (~344 px,
   celdas de 44 px), no cambia el tamaño de la pantalla, no empuja la
   maquetación y se cierra al elegir el día. */
.finanzas-calendario-mini {
  position: fixed;
  z-index: 40;
  width: min(344px, calc(100vw - 12px));
  padding: 0.3rem;
  border: 1px solid var(--border);
  border-radius: calc(var(--radius) + 4px);
  background: var(--card);
  box-shadow: 0 18px 44px hsl(240 10% 3.9% / 0.3);
}

.finanzas-calendario-mini[hidden] {
  display: none;
}

.finanzas-calendario-mini-nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.2rem;
}

.finanzas-calendario-mini-titulo {
  font-size: 0.82rem;
  font-weight: 600;
}

.finanzas-calendario-mini-flecha {
  appearance: none;
  flex: none;
  min-width: 44px;
  min-height: 44px;
  border: 0;
  border-radius: var(--radius);
  background: transparent;
  color: var(--foreground);
  font: inherit;
  font-size: 1.05rem;
  cursor: pointer;
}

.finanzas-calendario-mini-flecha:hover {
  background: var(--secondary);
}

.finanzas-calendario-mini-grid {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 2px;
}

.finanzas-calendario-mini-dia-semana {
  text-align: center;
  color: var(--muted-foreground);
  font-size: 0.62rem;
  font-weight: 700;
  padding: 0.15rem 0;
}

.finanzas-calendario-mini-vacio {
  display: block;
}

.finanzas-calendario-mini-dia {
  appearance: none;
  min-height: 44px;
  border: 0;
  border-radius: var(--radius);
  background: transparent;
  color: var(--foreground);
  font: inherit;
  font-size: 0.82rem;
  font-variant-numeric: tabular-nums;
  cursor: pointer;
}

.finanzas-calendario-mini-dia:hover {
  background: var(--secondary);
}

.finanzas-calendario-mini-dia.es-hoy {
  color: var(--finanzas-hoy);
  font-weight: 700;
}

.finanzas-calendario-mini-dia.es-elegido {
  background: var(--primary);
  color: var(--primary-foreground);
  font-weight: 700;
}

/* Editor en la fila · rejilla responsiva (pedido de Santiago, 22-sep-2026):
   en el celular los campos dejaron de apilarse uno por fila — cada campo
   declara su tamaño (corto · tres por fila, medio · dos por fila, dos-tercios ·
   dos por fila con el ancho a favor de la categoría, ancho · bloque propio) y
   la rejilla reparte. Desde 320 px los campos cortos y medios comparten fila
   (fecha + tipo, categoría + monto, moneda + tasa/acciones) sin recortar
   ninguna etiqueta; la nota larga (Concepto) conserva su bloque. En pantallas
   anchas (≥1100 px) campos y acciones caben en una sola línea. */
.finanzas-movimiento-edicion {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: 0.5rem 0.6rem;
  width: 100%;
  align-items: end;
}

.finanzas-movimiento-edicion .finanzas-campo-corto {
  grid-column: span 2;
}

.finanzas-movimiento-edicion .finanzas-campo-medio {
  grid-column: span 3;
}

/* Dos tercios: para el campo que necesita ancho sin llegar al bloque propio
   (la categoría, con nombres largos reales: a 320 px sigue entrando entera). */
.finanzas-movimiento-edicion .finanzas-campo-dos-tercios {
  grid-column: span 4;
}

.finanzas-movimiento-edicion .finanzas-campo-ancho {
  grid-column: 1 / -1;
}

.finanzas-movimiento-edicion-acciones {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  align-items: center;
  grid-column: span 3;
}

@media (min-width: 1100px) {
  /* Escritorio ancho: una sola línea de campos con el monto junto a la fecha,
     el concepto al centro y las acciones al final; Tasa y COP cobrado (solo
     movimientos extranjeros) bajan a su propia fila sin dejar huérfanos. */
  .finanzas-movimiento-edicion {
    /* Los selectores se miden por contenido (`auto`): su etiqueta entra com-
       pleta incluso con el nombre de categoría más largo. El ancho sobrante va
       a los campos de texto (concepto, monto, fecha), que no recortan. */
    grid-template-columns:
      minmax(7rem, 0.9fr) auto minmax(0, 1.6fr) auto
      minmax(7rem, 0.9fr) auto auto;
  }

  .finanzas-movimiento-edicion .finanzas-movimiento-campo {
    grid-column: auto;
  }

  .finanzas-movimiento-edicion-acciones {
    grid-column: 7 / 8;
    grid-row: 1;
  }
}

/* Conexión de Outlook (código de dispositivo) */
.finanzas-correo-outlook {
  display: grid;
  gap: 8px;
  margin-top: 12px;
}
.finanzas-correo-outlook-codigo {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 1.35rem;
  letter-spacing: 0.14em;
}

/* Cuentas de correo: chips de proveedor e iconos de origen */
.finanzas-correo [hidden] {
  display: none;
}
.finanzas-correo-conectar {
  display: flex;
  gap: 0.6rem;
  margin: 0.2rem 0 0.8rem;
}
.finanzas-correo-proveedor {
  color: var(--foreground);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 56px;
  height: 56px;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: transparent;
  cursor: pointer;
  transition: border-color 150ms ease;
}
.finanzas-correo-proveedor:hover,
.finanzas-correo-proveedor:focus-visible {
  border-color: var(--primary);
}
.finanzas-correo-cuenta-principal {
  flex: 1;
  display: flex;
  align-items: center;
  gap: 0.6rem;
  min-width: 0;
}
.finanzas-correo-cuenta-icono {
  flex: none;
  width: 22px;
  height: 22px;
}
.finanzas-pendiente-icono {
  display: inline-block;
  width: 14px;
  height: 14px;
  vertical-align: -2px;
}

.finanzas-correo-outlook-enlace {
  display: inline-block;
  margin-top: 0.35rem;
  color: var(--primary);
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 2px;
}

.finanzas-correo-outlook-codigo-fila {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin: 0.35rem 0;
}

.finanzas-correo-cuenta-linea {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  min-width: 0;
}
.finanzas-correo-cuenta-check {
  flex: none;
}

.finanzas-correo-cuenta-botones .finanzas-boton-ghost {
  padding: 0.2rem 0.5rem;
  font-size: 0.74rem;
}
.finanzas-correo-cuenta .finanzas-correo-cuenta-linea {
  flex: 1;
}

/* ─── Ficha de gasto (SPEC 006): popup de detalle por movimiento ─── */

.finanzas-movimiento-tocable {
  cursor: pointer;
}
.finanzas-movimiento-tocable:focus-visible {
  outline: 2px solid var(--ring);
  outline-offset: 2px;
}

.finanzas-ficha-overlay {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem;
  background: hsl(240 10% 3.9% / 0.5);
}
.finanzas-ficha-overlay[hidden] {
  display: none;
}

.finanzas-ficha {
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
  width: min(100%, 28rem);
  max-height: min(85vh, 40rem);
  overflow-y: auto;
  padding: 1rem 1.1rem 1.2rem;
  border: 1px solid var(--border);
  border-radius: calc(var(--radius) + 8px);
  background: var(--card);
  color: var(--card-foreground);
  box-shadow: 0 24px 60px -20px hsl(240 10% 3.9% / 0.5);
}

.finanzas-ficha-cabecera {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 0.75rem;
}
.finanzas-ficha-titulo {
  margin: 0;
  font-size: 1.05rem;
  line-height: 1.25;
}
.finanzas-ficha-cerrar {
  flex: none;
  width: 2rem;
  height: 2rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--secondary);
  color: var(--secondary-foreground);
  font-size: 0.8rem;
  cursor: pointer;
}
.finanzas-ficha-cerrar:hover {
  background: var(--accent);
}

/* Acciones de la ficha (22-sep-2026): Editar y Eliminar —ya no viven en la
   fila—; eliminar pide confirmación en el mismo pie. */
.finanzas-ficha-acciones {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  padding-top: 0.75rem;
  border-top: 1px solid var(--border);
}

.finanzas-ficha-acciones button {
  min-height: 44px;
}

/* Eliminar es destructivo donde viva (antes en la fila, ahora en la ficha). */
.finanzas-ficha-acciones .boton-eliminar {
  color: var(--destructive);
}

.finanzas-ficha-confirmacion {
  flex: 1 1 100%;
  color: var(--destructive);
  font-size: 0.85rem;
  line-height: 1.35;
}

.finanzas-ficha-monto {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.45rem;
  margin: 0;
  font-size: 1.35rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.finanzas-ficha-monto-aprox {
  font-size: 0.9rem;
  font-weight: 500;
  color: var(--muted-foreground);
}
.finanzas-ficha-monto-aprox.sin-convertir {
  color: var(--warning);
}

.finanzas-ficha-campos,
.finanzas-ficha-lineas {
  display: grid;
  grid-template-columns: auto 1fr;
  column-gap: 0.75rem;
  row-gap: 0.3rem;
  margin: 0;
  font-size: 0.9rem;
}
.finanzas-ficha-etiqueta {
  color: var(--muted-foreground);
}
.finanzas-ficha-valor {
  margin: 0;
  text-align: right;
  overflow-wrap: anywhere;
}

.finanzas-ficha-origen {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  padding-top: 0.75rem;
  border-top: 1px solid var(--border);
}
.finanzas-ficha-origen-titulo {
  margin: 0;
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted-foreground);
}
.finanzas-ficha-aviso {
  margin: 0;
  font-size: 0.85rem;
  color: var(--muted-foreground);
}
.finanzas-ficha-items {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  margin: 0.15rem 0 0;
  padding: 0;
  list-style: none;
  font-size: 0.9rem;
}
.finanzas-ficha-item {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
}
.finanzas-ficha-item-nombre {
  flex: 1;
  min-width: 0;
}
.finanzas-ficha-item-cantidad {
  font-size: 0.82rem;
  color: var(--muted-foreground);
}
.finanzas-ficha-item-subtotal {
  font-variant-numeric: tabular-nums;
}

/* Móvil: la ficha entra como panel inferior deslizante. */
@media (max-width: 720px) {
  .finanzas-ficha-overlay {
    align-items: flex-end;
    padding: 0;
  }
  .finanzas-ficha {
    width: 100%;
    max-height: 88vh;
    border-bottom: none;
    border-radius: calc(var(--radius) + 10px) calc(var(--radius) + 10px) 0 0;
    padding-bottom: calc(1.2rem + env(safe-area-inset-bottom));
  }
}

/* Con la ficha abierta, el fondo no scrollea. */
body.finanzas-ficha-abierta {
  overflow: hidden;
}

/* ─── Tono característico de categoría (SPEC 006 · iteración) ─── */
/* El chip de la ficha comparte el lenguaje visual del chip de las filas:
   mismo hue estable por categoría, tamaño mayor para destacar a simple vista. */

.finanzas-ficha-categoria {
  justify-self: start;
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.2rem 0.6rem;
  border-radius: 999px;
  background: hsl(var(--cat-hue, 240) 72% 93%);
  color: hsl(var(--cat-hue, 240) 45% 28%);
  border: 1px solid hsl(var(--cat-hue, 240) 55% 84%);
  font-size: 0.78rem;
  font-weight: 600;
  white-space: nowrap;
}

:root[data-tema="oscuro"] .finanzas-categoria-chip,
:root[data-tema="oscuro"] .finanzas-ficha-categoria {
  background: hsl(var(--cat-hue, 240) 32% 24%);
  color: hsl(var(--cat-hue, 240) 70% 78%);
  border-color: hsl(var(--cat-hue, 240) 28% 38%);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-tema]) .finanzas-categoria-chip,
  :root:not([data-tema]) .finanzas-ficha-categoria {
    background: hsl(var(--cat-hue, 240) 32% 24%);
    color: hsl(var(--cat-hue, 240) 70% 78%);
    border-color: hsl(var(--cat-hue, 240) 28% 38%);
  }
}

/* ─── Filtro de tipo (SPEC 006 · iteración 2): Gasto en rojo, Ingreso en verde ─── */

#finanzas-movimientos-tipo.es-gasto {
  color: var(--destructive);
  border-color: color-mix(in srgb, var(--destructive) 45%, var(--border));
}
#finanzas-movimientos-tipo.es-ingreso {
  color: var(--success);
  border-color: color-mix(in srgb, var(--success) 45%, var(--border));
}
#finanzas-movimientos-tipo option[value="gasto"] {
  color: var(--destructive);
}
#finanzas-movimientos-tipo option[value="ingreso"] {
  color: var(--success);
}

/* ─── Selector de color de categoría (SPEC 006 · iteración 3) ─── */

.finanzas-categoria-color-boton {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.1rem;
  height: 2.1rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--secondary);
  cursor: pointer;
  flex: none;
}
.finanzas-color-swatch {
  width: 1.15rem;
  height: 1.15rem;
  border-radius: 999px;
  background: hsl(var(--cat-hue, 240) 65% 52%);
  border: 1px solid hsl(var(--cat-hue, 240) 60% 42% / 0.55);
}

.finanzas-color-catalogo {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  margin: 0.3rem 0 0;
  padding: 0.6rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--background);
}
.finanzas-color-item {
  width: 2rem;
  height: 2rem;
  border: 2px solid transparent;
  border-radius: 999px;
  background: hsl(var(--cat-hue, 240) 65% 52%);
  cursor: pointer;
  flex: none;
}
.finanzas-color-item.es-actual {
  border-color: var(--foreground);
  box-shadow: inset 0 0 0 2px var(--background);
}
.finanzas-color-automatico {
  width: auto;
  padding: 0 0.7rem;
  border: 2px solid var(--border);
  border-radius: 999px;
  background: var(--secondary);
  color: var(--secondary-foreground);
  font-size: 0.72rem;
  font-weight: 650;
}
.finanzas-color-automatico.es-actual {
  border-color: var(--foreground);
  box-shadow: none;
}

/* ─── Captura en la tarjeta y pop-up de confirmación (ronda 2 · t_d2d66a4e) ──
   Un toque en − / + transforma la tarjeta: a la izquierda del botón pulsado
   aparecen cámara y micrófono —44 px reales de área táctil— y los campos de
   alta se mudan DENTRO de la tarjeta (una sola instancia del formulario).
   Las tres vías —manual · foto · voz— terminan en el pop-up de confirmación;
   nada se guarda sin confirmar. */

.finanzas-card-botones {
  display: flex;
  flex: none;
  align-items: center;
  gap: 0.375rem;
}

.finanzas-card-accion {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--secondary);
  color: var(--foreground);
  cursor: pointer;
}

/* Ronda 2f: la cabecera no cambia de alto al entrar al modo captura. Las dos
   cajas altas (44 px de toque) se centran sobre el renglón del − / + (1.9rem)
   con margen negativo: aportan su área táctil sin empujar la fila, así el
   encabezado y los tres botones conservan su sitio (Δ = 0). */
.finanzas-card-botones .finanzas-card-accion {
  margin-block: calc((1.9rem - 44px) / 2);
}

.finanzas-card-accion[hidden] {
  display: none;
}

.finanzas-card-accion:hover {
  background: var(--accent);
}

.finanzas-card-accion:focus-visible {
  outline: 2px solid var(--ring);
  outline-offset: 2px;
}

/* Grabando: el micrófono queda marcado (aria-pressed) y late sin cambiar de
   tamaño —el estado se ve, no salta la maquetación—. */
.finanzas-card-accion[aria-pressed="true"] {
  border-color: var(--destructive);
  background: color-mix(in srgb, var(--destructive) 16%, transparent);
  color: var(--destructive);
}

@keyframes finanzas-captura-entra {
  from {
    opacity: 0;
    transform: translateX(8px) scale(0.92);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@keyframes finanzas-captura-late {
  0%, 100% {
    box-shadow: 0 0 0 0 color-mix(in srgb, var(--destructive) 55%, transparent);
  }
  50% {
    box-shadow: 0 0 0 7px color-mix(in srgb, var(--destructive) 0%, transparent);
  }
}

/* Aparición breve de los dos botones: solo al desplegarse, reversible. */
.finanzas-card-botones .finanzas-card-accion:not([hidden]) {
  animation: finanzas-captura-entra 160ms ease-out;
}

.finanzas-card-accion[aria-pressed="true"] {
  animation: finanzas-captura-late 1.2s ease-in-out infinite;
}

/* Área táctil del − / + al menos 44 px sin agrandar su círculo visible. */
.finanzas-card-boton {
  position: relative;
}

.finanzas-card-boton::after {
  content: '';
  position: absolute;
  inset: -7px;
  border-radius: 999px;
}

.finanzas-card-boton[aria-expanded="true"] {
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--ring) 45%, transparent);
}

/* El formulario vive DENTRO de la tarjeta: sin padding lateral propio (la
   tarjeta ya lo trae) y separado del contenido por una línea de puntos. */
.finanzas-form-en-tarjeta {
  margin-top: 0.7rem;
  padding: 0.15rem 0 0.3rem;
  border-top: 1px dashed var(--border);
}

.finanzas-form-en-tarjeta > h3 {
  margin-top: 0.35rem;
}

/* Ronda 8 (t_3f3dff4b): la fecha y la moneda bajan a su ancho MÍNIMO medido
   con píxeles y TODO lo liberado pasa a la categoría y al monto. La fecha
   muestra «dd/mm/aaaa» (92.22 px de valor, 16 px —umbral anti-autozoom de
   iOS—) más su relleno y el icono de calendario (10 px de tinta): por debajo
   de 118 px el valor se comprime contra el icono, así que su ancho es el
   mínimo con aire, 120.4 px. La moneda solo muestra la divisa («COP $»,
   48.7 px): con 70 px queda con aire frente a su flecha. Ambas cajas son de
   ancho FIJO (su contenido no crece); el resto del grid es elástico.

   El grid sigue siendo el de SEIS medias columnas, ahora repartidas así:
   C1 = 70 px (la moneda, la columna entera) y C2 = 44 px cierran juntas la
   caja de la fecha (70 + 6.4 de hueco + 44 = 120.4 px, la fecha ocupa C1–C2);
   el monto ocupa C2–C5; la C6 = 96 px clava el par ✗/✓ (44 + 8 + 44) al
   borde derecho; y C3–C5 (elásticas, 1fr) son las columnas que absorben la
   categoría (C3–C6) y el monto (C2–C5). A 390 el panel mide 320.41 px: la
   fecha queda en 120.4 (antes 157), la celda de la categoría en 193.61 (antes
   157), la moneda en 70 (antes 102.53) y el monto en 141.61 (antes 102.55)
   —el monto necesita 81.44 px para «8.500.000»: ahora le sobra aire—. A 428:
   fecha 120.4, categoría 231.61, moneda 70 y monto 179.61. Los controles de
   cada fila se alinean al fondo (align-items: end) para compartir top aunque
   un rótulo se parta en dos líneas. */
.finanzas-form-en-tarjeta .finanzas-fields {
  grid-template-columns: minmax(0, 70px) minmax(0, 44px) minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1fr) 96px;
  gap: 0.4rem;
  align-items: end;
}

.finanzas-form-en-tarjeta .finanzas-fields-fila,
.finanzas-form-en-tarjeta .finanzas-categoria-campo {
  display: contents;
}

/* Fila 1 (celular): la fecha ocupa C1–C2 (su ancho mínimo medido) y la celda
   de la categoría C3–C6 (todo el resto). Ojo: el hook va en la CELDA (el
   label #finanzas-fecha-campo), no en el input: el input no es ítem del grid
   y su ancho sale del 100 % de la celda (la regla de la ronda 6 apuntaba al
   input y no colocaba nada). */
.finanzas-form-en-tarjeta #finanzas-fecha-campo {
  grid-column: 1 / 3;
  grid-row: 1;
}

.finanzas-form-en-tarjeta #finanzas-categoria-field {
  grid-column: 3 / 7;
  grid-row: 1;
}

/* Fila 2 (celular): el concepto, solo, a fila completa. */
.finanzas-form-en-tarjeta .finanzas-field-concepto {
  grid-column: 1 / -1;
  grid-row: 2;
}

/* El editor del alta rápida se queda con la fila entera (las cajas de las
   filas de arriba son medias filas: ahí no cabe). Su fila es automática: cae
   debajo de las tres filas ocupadas, así que no empuja nada ni necesita
   condición: mientras está [hidden] no participa del grid. */
.finanzas-form-en-tarjeta #finanzas-categoria-rapida {
  grid-column: 1 / -1;
}

/* Fila 3 (celular): la moneda (C1, su ancho mínimo medido), el monto (C2–C5,
   todo el resto) y el par ✗/✓ (C6, 96 px exactos). */
.finanzas-form-en-tarjeta #finanzas-moneda-campo {
  grid-column: 1 / 2;
  grid-row: 3;
}

.finanzas-form-en-tarjeta #finanzas-monto-cop-campo,
.finanzas-form-en-tarjeta #finanzas-monto-ext-campo {
  grid-column: 2 / 6;
  grid-row: 3;
}

/* Los campos de apoyo de la moneda extranjera ocupan la fila completa. */
.finanzas-form-en-tarjeta #finanzas-tasa-campo,
.finanzas-form-en-tarjeta #finanzas-conversion-campo {
  grid-column: 1 / -1;
}

.finanzas-form-en-tarjeta .finanzas-actions-botones {
  grid-column: 6 / 7;
  grid-row: 3;
  align-self: end;
  justify-self: end;
  justify-content: flex-end;
  width: max-content;
}

@media (min-width: 721px) {
  /* Escritorio (ronda 6): los cinco campos en UNA fila de columnas iguales
     —fecha, concepto, categoría (con su «+» dentro), moneda y monto— y el par
     ✗/✓ al cierre, en la columna corta del borde. El reparto móvil en tres
     filas (rondas 7–8) no aplica: la fecha y el concepto conservan su sitio
     en la única fila. El editor del alta rápida sigue cayendo debajo, a fila
     completa. */
  .finanzas-form-en-tarjeta .finanzas-fields {
    grid-template-columns: repeat(5, minmax(0, 1fr)) auto;
    gap: 0.6rem;
  }

  .finanzas-form-en-tarjeta #finanzas-fecha-campo {
    grid-column: 1;
    grid-row: 1;
  }

  .finanzas-form-en-tarjeta .finanzas-field-concepto {
    grid-column: 2;
    grid-row: 1;
  }

  .finanzas-form-en-tarjeta #finanzas-categoria-field {
    grid-column: 3;
    grid-row: 1;
  }

  .finanzas-form-en-tarjeta #finanzas-moneda-campo {
    grid-column: 4;
    grid-row: 1;
  }

  .finanzas-form-en-tarjeta #finanzas-monto-cop-campo,
  .finanzas-form-en-tarjeta #finanzas-monto-ext-campo {
    grid-column: 5;
    grid-row: 1;
  }

  .finanzas-form-en-tarjeta #finanzas-tasa-campo,
  .finanzas-form-en-tarjeta #finanzas-conversion-campo {
    grid-column: 1 / 6;
  }

  .finanzas-form-en-tarjeta .finanzas-actions-botones {
    grid-column: 6;
    grid-row: 1;
  }
}

/* Ronda 6 (t_0ca41d80): los píxeles muertos del pie. El status —y su línea—
   no reservan alto mientras están vacíos: sin mensaje el formulario termina en
   la fila del valor, y cuando lo hay el mensaje aparece con su separación.
   Medición: antes el pie sumaba 15.36 px de línea vacía + 12 px de margen +
   4.8 px de relleno; ahora el relleno de la tarjeta es el único colchón. */
.finanzas-form-en-tarjeta .finanzas-actions {
  margin-top: 0;
}

.finanzas-form-en-tarjeta .finanzas-form-status:empty {
  display: none;
}

.finanzas-form-en-tarjeta .finanzas-actions .finanzas-form-status:not(:empty) {
  margin-top: 0.6rem;
}

/* Ronda 6: en móvil los campos de la captura ceden relleno lateral para que
   los valores entren en las cajas iguales. La fecha necesita 92.22 px de texto
   (16 px) y a 390 su caja mide 102.54: con 0.35rem por lado el valor se
   cortaba; el monto necesita 81.44 px (8.500.000) y los selectores, todo el
   ancho posible para el nombre de la categoría. */
@media (max-width: 720px) {
  .finanzas-form-en-tarjeta #finanzas-fecha {
    padding-left: 0.1rem;
    padding-right: 0.1rem;
  }

  .finanzas-form-en-tarjeta #finanzas-monto {
    padding-left: 0.4rem;
    padding-right: 0.4rem;
  }

  .finanzas-form-en-tarjeta .finanzas-field select {
    padding-left: 0.25rem;
    padding-right: 0.25rem;
  }
}

/* Ronda 2f: mientras la tarjeta registra, su título cede el sitio al rótulo
   del formulario («Registrar gasto» / «Registrar ingreso»). El rótulo viaja
   como capa absoluta sobre el título (que se apaga SIN soltar su caja): las
   dos capas comparten sitio, el cruce dura 180 ms y nada se desplaza. */
.finanzas-card .ds-card-header {
  position: relative;
}

.finanzas-rotulo-en-cabecera {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  display: flex;
  align-items: center;
  margin: 0;
  pointer-events: none;
}

@keyframes finanzas-rotulo-entra {
  from {
    opacity: 0;
    transform: translateY(4px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@keyframes finanzas-rotulo-sale {
  from {
    opacity: 1;
    transform: none;
  }
  to {
    opacity: 0;
    transform: translateY(-4px);
    visibility: hidden;
  }
}

/* El cruce (entra y sale) es reversible: la clase manda y la animación se
   re-ejecuta al alternar. La clase de salida declara también su estado final
   (opacity 0 + visibility: hidden): fuera de render, el literal no cuenta ni
   aparece en innerText; con `prefers-reduced-motion` el estado es el mismo sin
   cruce. */
.finanzas-rotulo-entra {
  animation: finanzas-rotulo-entra 180ms ease-out both;
}

.finanzas-rotulo-sale {
  opacity: 0;
  visibility: hidden;
  animation: finanzas-rotulo-sale 180ms ease-in both;
}

/* Mientras la tarjeta registra, su fila de montos (total en COP y subtotales
   por moneda) se oculta TEMPORALMENTE: el espacio liberado lo ocupan los
   campos. Al salir del modo vuelve idéntica, en el mismo nodo. */
.finanzas-card-captura-abierta .ds-card-value {
  display: none;
}

/* Ronda 5c (t_e60505b8): el MISMO tratamiento para la lista de categorías con
   sus valores —ese era el bloque que faltaba liberar y hacía crecer la
   tarjeta—. Viaja el `ul` completo, así que el borde punteado de separación y
   sus márgenes se van con él: no queda hueco ni rótulo huérfanos. Es puro
   `display` sobre la clase que ya marca la tarjeta en captura: al salir, el
   mismo nodo vuelve idéntico —textos, orden y montos formateados byte a
   byte— en todas las salidas. */
.finanzas-card-captura-abierta .finanzas-categorias-lista {
  display: none;
}

/* Barra de grabación dentro de la tarjeta: contador y corte explícito. */
.finanzas-captura-grabacion {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  margin-top: 0.7rem;
  padding: 0.5rem 0.65rem;
  border: 1px solid color-mix(in srgb, var(--destructive) 55%, var(--border));
  border-radius: var(--radius);
  background: color-mix(in srgb, var(--destructive) 8%, transparent);
}

.finanzas-captura-grabacion[hidden] {
  display: none;
}

.finanzas-captura-grabacion-punto {
  width: 0.6rem;
  height: 0.6rem;
  border-radius: 999px;
  background: var(--destructive);
  animation: finanzas-captura-late-punto 1.1s ease-in-out infinite;
}

@keyframes finanzas-captura-late-punto {
  0%, 100% {
    opacity: 1;
  }
  50% {
    opacity: 0.35;
  }
}

.finanzas-captura-grabacion-texto {
  flex: 1 1 auto;
  font-size: 0.85rem;
  font-variant-numeric: tabular-nums;
}

.finanzas-captura-detener {
  min-height: 44px;
  flex: none;
}

/* Pop-up de confirmación: mismo lenguaje de la ficha (panel inferior en
   móvil), con los campos en dos columnas dentro del panel. */
.finanzas-captura .finanzas-captura-campos {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

.finanzas-captura-sub {
  margin: 0;
  color: var(--muted-foreground);
  font-size: 0.82rem;
  line-height: 1.35;
}

/* Lectura sin costo (dictado/recibo ➜ campos): bloque propio del pop-up, en
   columna, botones de 44 px y el resultado línea a línea (aplicado, vacíos,
   notas, ignorados del recibo, avisos). */
.finanzas-captura-lectura {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin-top: 0.2rem;
  padding-top: 0.6rem;
  border-top: 1px dashed var(--border);
}

.finanzas-captura-lectura-titulo {
  margin: 0;
  color: var(--muted-foreground);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.finanzas-captura-lectura-ayuda {
  margin: 0;
  color: var(--muted-foreground);
  font-size: 0.78rem;
  line-height: 1.35;
}

.finanzas-captura-lectura-texto {
  width: 100%;
  min-height: 4.25rem;
  resize: vertical;
  padding: 0.55rem 0.6rem;
  border: 1px solid var(--border);
  border-radius: 0.5rem;
  background: var(--background);
  color: var(--foreground);
  font: inherit;
  font-size: 0.9rem;
  line-height: 1.4;
}

.finanzas-captura-lectura-texto:focus-visible {
  outline: 2px solid var(--ring);
  outline-offset: 1px;
}

.finanzas-captura-lectura-botones {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.finanzas-captura-lectura-botones button {
  flex: 1 1 auto;
  min-height: 44px;
  justify-content: center;
}

.finanzas-captura-dictar.is-dictando {
  border-color: var(--destructive);
  color: var(--destructive);
}

.finanzas-captura-lectura-estado {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
}

.finanzas-captura-lectura-linea {
  margin: 0;
  font-size: 0.8rem;
  line-height: 1.4;
}

.finanzas-captura-lectura-linea[data-tipo='aplicados'] {
  color: var(--success);
}

.finanzas-captura-lectura-linea[data-tipo='vacios'],
.finanzas-captura-lectura-linea[data-tipo='notas'] {
  color: var(--muted-foreground);
}

.finanzas-captura-lectura-linea[data-tipo='avisos'],
.finanzas-captura-lectura-estado.is-error .finanzas-captura-lectura-linea[data-tipo='mensaje'] {
  color: var(--destructive);
}

/* Campo que la lectura no pudo llenar: punteado hasta que la persona lo toca. */
.finanzas-captura [data-lectura='vacio'] {
  border-style: dashed;
  border-color: var(--destructive);
}

.finanzas-captura-acciones {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  padding-top: 0.75rem;
  border-top: 1px solid var(--border);
}

.finanzas-captura-acciones button {
  flex: 1 1 auto;
  min-height: 44px;
  justify-content: center;
}

.finanzas-boton-gasto {
  background: var(--destructive);
  color: var(--destructive-foreground);
}

.finanzas-boton-ingreso {
  background: var(--success);
  color: #fff;
}

.finanzas-boton-gasto:disabled,
.finanzas-boton-ingreso:disabled {
  opacity: 0.55;
}

.finanzas-captura-adjuntos {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin-top: 0.2rem;
  padding-top: 0.6rem;
  border-top: 1px dashed var(--border);
}

.finanzas-captura-adjuntos-titulo {
  margin: 0;
  color: var(--muted-foreground);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.finanzas-captura-adjunto {
  display: flex;
  align-items: center;
  gap: 0.6rem;
}

.finanzas-captura-foto {
  width: 3.5rem;
  height: 3.5rem;
  object-fit: cover;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  flex: none;
}

.finanzas-captura-audio {
  max-width: 11rem;
  height: 2.5rem;
  flex: none;
}

.finanzas-captura-adjunto-datos {
  display: flex;
  flex-direction: column;
  min-width: 0;
  flex: 1 1 auto;
}

.finanzas-captura-adjunto-nombre {
  overflow: hidden;
  font-size: 0.85rem;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.finanzas-captura-adjunto-meta {
  color: var(--muted-foreground);
  font-size: 0.75rem;
}

.finanzas-captura-quitar {
  flex: none;
  min-height: 44px;
}

.finanzas-captura-adjunto-nota {
  margin: 0;
  color: var(--muted-foreground);
  font-size: 0.75rem;
  line-height: 1.4;
}

/* El input real de la foto: presente y tocable por el navegador, invisible. */
.finanzas-captura-foto-input {
  position: fixed;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
  .finanzas-card-botones .finanzas-card-accion:not([hidden]),
  .finanzas-card-accion[aria-pressed="true"],
  .finanzas-rotulo-entra,
  .finanzas-rotulo-sale,
  .finanzas-captura-grabacion-punto {
    animation: none;
  }
}

/* =========================================================
   Cadushi · identidad Pilo-clara (blanco / negro / lima)
   Inspiración de contraste Pilo; marca y copy propios de Cadushi.
   Forzado en claro: alto contraste, cards hero lima, tipografía bold.
   ========================================================= */

body.shell-ios {
  color-scheme: light;
  --cadushi-black: #0a0a0a;
  --cadushi-white: #ffffff;
  --cadushi-lime: #c8f542;
  --cadushi-lime-deep: #a8d92a;
  --cadushi-ink: #111111;
  --cadushi-mute: #5c5c5c;
  --cadushi-line: #e6e6e6;
  --cadushi-wash: #f3f3f3;
  --cadushi-bloom: #e11d48;
  --cadushi-cactus: var(--cadushi-black);
  --cadushi-cactus-bright: var(--cadushi-lime-deep);
  --cadushi-leaf: #3f6b1a;
  --background: var(--cadushi-white);
  --foreground: var(--cadushi-black);
  --card: var(--cadushi-white);
  --card-foreground: var(--cadushi-black);
  --primary: var(--cadushi-black);
  --primary-foreground: var(--cadushi-white);
  --secondary: var(--cadushi-wash);
  --secondary-foreground: var(--cadushi-black);
  --muted: var(--cadushi-wash);
  --muted-foreground: var(--cadushi-mute);
  --accent: var(--cadushi-lime);
  --accent-foreground: var(--cadushi-black);
  --border: var(--cadushi-line);
  --input: var(--cadushi-line);
  --ring: var(--cadushi-black);
  --success: var(--cadushi-leaf);
  --success-foreground: var(--cadushi-white);
  --destructive: var(--cadushi-bloom);
  --destructive-foreground: var(--cadushi-white);
  --radius: 1.35rem;
  --finanzas-tabbar-bg: hsl(0 0% 100% / 0.94);
  --finanzas-tabbar-fg: #6b6b6b;
  --finanzas-tabbar-fg-activo: var(--cadushi-black);
  --finanzas-tabbar-borde: #ececec;
  --finanzas-rapida-guardar: #2f5d12;
  --finanzas-rapida-cancelar: #b91c1c;
  background: var(--cadushi-white);
  color: var(--cadushi-black);
}

/* Anula el oscuro automático del sistema: Cadushi queda en Pilo-claro. */
@media (prefers-color-scheme: dark) {
  :root:not([data-tema]) body.shell-ios,
  :root[data-tema="oscuro"] body.shell-ios {
    --background: var(--cadushi-white);
    --foreground: var(--cadushi-black);
    --card: var(--cadushi-white);
    --card-foreground: var(--cadushi-black);
    --primary: var(--cadushi-black);
    --primary-foreground: var(--cadushi-white);
    --secondary: var(--cadushi-wash);
    --secondary-foreground: var(--cadushi-black);
    --muted: var(--cadushi-wash);
    --muted-foreground: var(--cadushi-mute);
    --accent: var(--cadushi-lime);
    --accent-foreground: var(--cadushi-black);
    --border: var(--cadushi-line);
    --input: var(--cadushi-line);
    --ring: var(--cadushi-black);
    --finanzas-tabbar-bg: hsl(0 0% 100% / 0.94);
    --finanzas-tabbar-fg: #6b6b6b;
    --finanzas-tabbar-fg-activo: var(--cadushi-black);
    --finanzas-tabbar-borde: #ececec;
    background: var(--cadushi-white);
    color: var(--cadushi-black);
  }
}

body.shell-ios .finanzas-large-title {
  color: var(--cadushi-black);
  font-size: clamp(1.9rem, 7.5vw, 2.45rem);
  font-weight: 780;
  letter-spacing: -0.05em;
}

body.shell-ios .finanzas-periodo-selector {
  border: 1.5px solid var(--cadushi-black);
  border-radius: 999px;
  background: var(--cadushi-white);
  color: var(--cadushi-black);
  font-weight: 700;
}

body.shell-ios .finanzas-freshness {
  color: var(--cadushi-mute);
}

body.shell-ios .finanzas-top-cards {
  display: grid;
  gap: 0.85rem;
  padding: 0 0 0.95rem;
}

body.shell-ios .finanzas-card.ds-card {
  padding: 1.15rem 1.2rem 1.2rem;
  border: 1.5px solid var(--cadushi-black);
  border-radius: 1.5rem;
  box-shadow: none;
  overflow: hidden;
}

/* Hero ingresos: lima sólida + tinta negra (patrón Pilo). */
body.shell-ios .finanzas-card-ingreso.ds-card {
  border-color: var(--cadushi-black);
  background: var(--cadushi-lime);
  color: var(--cadushi-black);
}

body.shell-ios .finanzas-card-ingreso .ds-card-header h3,
body.shell-ios .finanzas-card-ingreso .ds-card-unit,
body.shell-ios .finanzas-card-ingreso .finanzas-categorias-lista {
  color: color-mix(in srgb, var(--cadushi-black) 72%, transparent);
}

body.shell-ios .finanzas-card-ingreso .ds-card-value strong {
  color: var(--cadushi-black);
  font-size: clamp(1.9rem, 8vw, 2.5rem);
  font-weight: 800;
  letter-spacing: -0.05em;
}

body.shell-ios .finanzas-card-ingreso .finanzas-card-boton {
  background: var(--cadushi-black);
  color: var(--cadushi-lime);
}

/* Gastos: card blanca, tipografía negra, acento coral solo en el monto. */
body.shell-ios .finanzas-card-gasto.ds-card {
  border-color: var(--cadushi-black);
  background: var(--cadushi-white);
}

body.shell-ios .finanzas-card-gasto .ds-card-header h3 {
  color: var(--cadushi-mute);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
}

body.shell-ios .finanzas-card-ingreso .ds-card-header h3 {
  color: color-mix(in srgb, var(--cadushi-black) 70%, transparent);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
}

body.shell-ios .finanzas-card-gasto .ds-card-value strong {
  color: var(--cadushi-bloom);
  font-size: clamp(1.75rem, 7vw, 2.25rem);
  font-weight: 800;
  letter-spacing: -0.045em;
}

body.shell-ios .finanzas-card-gasto .finanzas-card-boton {
  background: var(--cadushi-black);
  color: var(--cadushi-white);
}

body.shell-ios .finanzas-card .ds-card-value {
  margin-top: 0.4rem;
  margin-bottom: 0.4rem;
}

body.shell-ios .finanzas-card .ds-card-unit {
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.04em;
}

body.shell-ios #finanzas-recientes-title,
body.shell-ios #finanzas-pendientes-title {
  color: var(--cadushi-black);
  font-size: 1.1rem;
  font-weight: 750;
  letter-spacing: -0.025em;
  text-transform: none;
}

body.shell-ios .finanzas-ver-todos {
  color: var(--cadushi-black);
  font-weight: 700;
  text-decoration: none;
  border-bottom: 1.5px solid var(--cadushi-lime);
}

body.shell-ios .finanzas-lista {
  border: 1.5px solid var(--cadushi-black);
  border-radius: 1.25rem;
  background: var(--cadushi-white);
  overflow: hidden;
}

body.shell-ios .finanzas-pendientes {
  padding: 0.85rem 0 0;
}

body.shell-ios .finanzas-boton-ghost {
  border: 1.5px solid var(--cadushi-black);
  border-radius: 999px;
  background: var(--cadushi-white);
  color: var(--cadushi-black);
  font-weight: 650;
}

body.shell-ios .finanzas-tabbar {
  border: 1.5px solid var(--cadushi-black);
  background: var(--cadushi-white);
  box-shadow: 0 10px 28px hsl(0 0% 0% / 0.12);
}

body.shell-ios .finanzas-tabbar-tab[aria-current="page"] {
  color: var(--cadushi-black);
  font-weight: 750;
}

body.shell-ios .finanzas-tabbar-alta {
  background: var(--cadushi-lime);
  color: var(--cadushi-black);
  border: 1.5px solid var(--cadushi-black);
  box-shadow: none;
}

body.shell-ios .app-sidebar {
  border-right: 1.5px solid var(--cadushi-black);
  background: var(--cadushi-white);
}

body.shell-ios .sidebar-brand-name {
  color: var(--cadushi-black);
  font-weight: 800;
}

body.shell-ios .identity-mark {
  background: var(--cadushi-lime);
  color: var(--cadushi-black);
  border: 1.5px solid var(--cadushi-black);
}

body.shell-ios .finanzas-module {
  border: none;
  background: transparent;
  box-shadow: none;
}

@media (max-width: 720px) {
  body.shell-ios .finanzas-card.ds-card {
    box-shadow: none;
  }

  body.shell-ios .finanzas-tabbar {
    border-color: var(--cadushi-black);
  }
}

/* Transiciones entre subvistas / large title (Pilo-claro) */
@keyframes cadushi-subvista-in {
  from {
    opacity: 0;
    transform: translate3d(14px, 0, 0);
  }
  to {
    opacity: 1;
    transform: translate3d(0, 0, 0);
  }
}

@keyframes cadushi-title-in {
  from {
    opacity: 0;
    transform: translate3d(0, 6px, 0);
  }
  to {
    opacity: 1;
    transform: translate3d(0, 0, 0);
  }
}

@keyframes cadushi-tab-pop {
  from { transform: scale(0.92); opacity: 0.65; }
  to { transform: scale(1); opacity: 1; }
}

.finanzas-subvista-animar {
  animation: cadushi-subvista-in 280ms cubic-bezier(0.22, 1, 0.36, 1) both;
}

.finanzas-title-animar {
  animation: cadushi-title-in 240ms cubic-bezier(0.22, 1, 0.36, 1) both;
}

.finanzas-tabbar-tab.finanzas-tab-animar[aria-current="page"] {
  animation: cadushi-tab-pop 220ms cubic-bezier(0.22, 1, 0.36, 1) both;
}

@media (prefers-reduced-motion: reduce) {
  .finanzas-subvista-animar,
  .finanzas-title-animar,
  .finanzas-tabbar-tab.finanzas-tab-animar[aria-current="page"] {
    animation: none;
  }
}

/* Apertura: el lockup entra con opacidad y una escala corta (0.96 → 1);
   el velo se funde un poco más para entregar la interfaz.
   Space Grotesk solo vive en el wordmark. El resto de la app no cambia. */
@font-face {
  font-family: "Space Grotesk";
  font-style: normal;
  font-weight: 700;
  font-display: block;
  src: url("/space-grotesk-700.woff2") format("woff2");
}

.cadushi-apertura {
  position: fixed;
  inset: 0;
  z-index: 80;
  display: flex;
  align-items: center;
  justify-content: center;
  padding:
    max(1.25rem, env(safe-area-inset-top))
    max(1.25rem, env(safe-area-inset-right))
    max(1.25rem, env(safe-area-inset-bottom))
    max(1.25rem, env(safe-area-inset-left));
  background: #ffffff;
  pointer-events: auto;
  animation: cadushi-apertura-velo 1.9s linear both;
}

.cadushi-apertura-lockup {
  display: flex;
  align-items: center;
  gap: 0.28em;
  max-width: 100%;
  font-size: clamp(2.4rem, 14vw, 4.85rem);
  animation: cadushi-apertura-entra 0.7s cubic-bezier(0.33, 0, 0.2, 1) both;
}

.cadushi-apertura-icono {
  display: block;
  width: 1.38em;
  height: auto;
  flex: none;
}

.cadushi-apertura-nombre {
  margin: 0;
  color: #111111;
  font-family: "Space Grotesk", sans-serif;
  font-size: 1em;
  font-weight: 700;
  letter-spacing: -0.03em;
  line-height: 0.9;
  white-space: nowrap;
  user-select: none;
}

@keyframes cadushi-apertura-entra {
  from {
    opacity: 0;
    transform: scale(0.96);
  }
  to {
    opacity: 1;
    transform: scale(1);
  }
}

@keyframes cadushi-apertura-velo {
  0%,
  50% {
    opacity: 1;
    visibility: visible;
    animation-timing-function: cubic-bezier(0.33, 0, 0.2, 1);
  }
  100% {
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .cadushi-apertura-lockup {
    animation: none;
  }

  .cadushi-apertura {
    animation: cadushi-apertura-velo 0.35s linear 0.25s both;
  }
}
