/* Bareezy POS Design System v1.0.0 — generado por 'task build' a partir de tokens/*.css + go-templates/components.css. No editar a mano: los cambios van en el origen. */
/* ════════════════════════════════════════════════════════════
   FUENTES WEB · Sora (display) + Manrope (sans)
   Servidas desde Google Fonts — las familias exactas de app.css.
   ════════════════════════════════════════════════════════════ */
@import url("https://fonts.googleapis.com/css2?family=Manrope:wght@400;500;600;700;800&family=Sora:wght@400;600;700;800&display=swap");
/* ════════════════════════════════════════════════════════════
   TIPOGRAFÍA
   Display = Sora (títulos, números/totales).
   Sans    = Manrope (todo lo demás).
   ════════════════════════════════════════════════════════════ */
:root {
  --font-display: "Sora", system-ui, -apple-system, sans-serif;
  --font-sans:    "Manrope", system-ui, -apple-system, sans-serif;

  /* ── Escala de tamaños (TPV mobile-first) ── */
  --text-2xs:  10px;
  --text-xs:   11px;
  --text-sm:   13px;
  --text-base: 15px;
  --text-md:   16px;
  --text-lg:   18px;
  --text-xl:   22px;
  --text-2xl:  26px;   /* títulos de pantalla              */
  --text-3xl:  34px;   /* totales / importes grandes       */

  /* ── Pesos ── */
  --weight-regular:  400;
  --weight-medium:   500;
  --weight-semibold: 600;
  --weight-bold:     700;
  --weight-extra:    800;

  /* ── Interlineado ── */
  --leading-tight:  1.15;
  --leading-snug:   1.3;
  --leading-normal: 1.5;

  /* ── Espaciado entre letras ── */
  --tracking-display: -0.01em;
  --tracking-eyebrow:  0.10em;
  --tracking-label:    0.06em;
}
/* ════════════════════════════════════════════════════════════
   ESPACIADO · RADIOS · TAMAÑOS
   Rejilla base de 4px. Objetivos táctiles ≥ 44px (TPV táctil).
   ════════════════════════════════════════════════════════════ */
:root {
  --space-0:  0;
  --space-1:  2px;
  --space-2:  4px;
  --space-3:  6px;
  --space-4:  8px;
  --space-5:  10px;
  --space-6:  12px;
  --space-7:  14px;
  --space-8:  16px;
  --space-10: 20px;
  --space-12: 24px;
  --space-16: 32px;
  --space-20: 40px;

  /* ── Radios (derivados de los tokens DaisyUI de app.css) ── */
  --radius-field:    8px;    /* inputs, controles pequeños     */
  --radius-control:  12px;   /* botones de icono, track seg.   */
  --radius-box:      16px;   /* tarjetas, tiles, sheets        */
  --radius-pill:     999px;  /* chips, fab, badges             */

  /* ── Tamaños táctiles ── */
  --touch-min:   44px;   /* objetivo mínimo de toque         */
  --touch-btn:   52px;   /* altura de acción primaria        */
  --touch-input: 50px;   /* inputs de búsqueda / texto       */
  --icon-btn:    40px;   /* botón de icono en appbar         */

  /* ── Ritmo de pantalla ── */
  --gutter:      14px;   /* margen horizontal de pantalla    */
  --tile-gap:    10px;   /* separación en cuadrícula (mesas/prods) */
}
/* ════════════════════════════════════════════════════════════
   ELEVACIÓN Y MOVIMIENTO
   Sombras suaves y tintadas. Pulsación = reducción de escala
   (sin bloom de sombra). Todas las transiciones son cortas —
   el TPV debe sentirse instantáneo.
   ════════════════════════════════════════════════════════════ */
:root {
  --shadow-soft: 0 2px 10px -4px oklch(50% 0.05 260 / 0.25);
  --shadow-card: 0 1px 3px oklch(0% 0 0 / 0.10);
  --shadow-lg:   0 14px 40px -16px oklch(40% 0.06 260 / 0.40);
  --shadow-pop:  0 12px 32px -10px oklch(30% 0.05 260 / 0.32);
  --shadow-badge:0 2px 6px oklch(0% 0 0 / 0.25);
  --shadow-seg:  0 1px 3px oklch(0% 0 0 / 0.12);

  /* ── Movimiento ── */
  --ease-out:    cubic-bezier(0.22, 1, 0.36, 1); /* @kind other */
  --ease-standard: cubic-bezier(0.4, 0, 0.2, 1); /* @kind other */
  --dur-press:   80ms; /* @kind other */
  --dur-fast:    150ms; /* @kind other */
  --dur-normal:  240ms; /* @kind other */

  /* ── Feedback de pulsación (reducción de escala al tocar) ── */
  --press-scale: 0.96; /* @kind other */
  --press-scale-sm: 0.97; /* @kind other */
  --press-scale-row: 0.99; /* @kind other */
}
/* ════════════════════════════════════════════════════════════
   TEMAS · Variocolor (claro + oscuro por familia)
   Derivado de app.css (DaisyUI sysme-light / sysme-dark).
   Aplicar en <html data-theme="…">. Defecto = Cobalto (claro).

   Familias:  Cobalto (azul · defecto) · Carmesí (rojo) · Esmeralda
   (verde) · Amatista (violeta) · Turquesa (cian) · Ámbar (festival).
   Cada una: "<slug>" = claro, "<slug>-dark" = oscuro.
   ════════════════════════════════════════════════════════════ */

/* Cobalto · claro */
[data-theme="cobalto"], :root {
  color-scheme: light;
  --color-base-100:        oklch(99%   0.002 258);
  --color-base-200:        oklch(96.5% 0.004 258);
  --color-base-300:        oklch(92%   0.008 258);
  --color-base-content:    oklch(30%   0.025 258);

  --color-primary:         oklch(57%   0.17 258);
  --color-primary-content: oklch(99% 0 0);
  --color-secondary:       oklch(64%   0.11 195);
  --color-secondary-content: oklch(99% 0 0);
  --color-accent:          oklch(72% 0.15 70);
  --color-accent-content:  oklch(26% 0.05 70);
  --color-neutral:         oklch(32%   0.02 258);
  --color-neutral-content: oklch(98%   0.002 258);

  --color-info:            oklch(60%   0.13 240);
  --color-info-content:    oklch(99%   0 0);
  --color-success:         oklch(62%   0.14 155);
  --color-success-content: oklch(99%   0 0);
  --color-warning:         oklch(75%   0.14 75);
  --color-warning-content: oklch(28%   0.05 70);
  --color-error:           oklch(58%   0.20 22);
  --color-error-content:   oklch(99%   0 0);
}

/* Carmesí · claro */
[data-theme="carmesi"] {
  color-scheme: light;
  --color-base-100:        oklch(99%   0.002 22);
  --color-base-200:        oklch(96.5% 0.004 22);
  --color-base-300:        oklch(92%   0.008 22);
  --color-base-content:    oklch(30%   0.025 22);

  --color-primary:         oklch(57%   0.205 22);
  --color-primary-content: oklch(99% 0 0);
  --color-secondary:       oklch(64%   0.11 195);
  --color-secondary-content: oklch(99% 0 0);
  --color-accent:          oklch(72% 0.15 70);
  --color-accent-content:  oklch(26% 0.05 70);
  --color-neutral:         oklch(32%   0.02 22);
  --color-neutral-content: oklch(98%   0.002 22);

  --color-info:            oklch(60%   0.13 240);
  --color-info-content:    oklch(99%   0 0);
  --color-success:         oklch(62%   0.14 155);
  --color-success-content: oklch(99%   0 0);
  --color-warning:         oklch(75%   0.14 75);
  --color-warning-content: oklch(28%   0.05 70);
  --color-error:           oklch(58%   0.20 22);
  --color-error-content:   oklch(99%   0 0);
}

/* Esmeralda · claro */
[data-theme="esmeralda"] {
  color-scheme: light;
  --color-base-100:        oklch(99%   0.002 155);
  --color-base-200:        oklch(96.5% 0.004 155);
  --color-base-300:        oklch(92%   0.008 155);
  --color-base-content:    oklch(30%   0.025 155);

  --color-primary:         oklch(57%   0.14 155);
  --color-primary-content: oklch(99% 0 0);
  --color-secondary:       oklch(64%   0.11 195);
  --color-secondary-content: oklch(99% 0 0);
  --color-accent:          oklch(72% 0.15 70);
  --color-accent-content:  oklch(26% 0.05 70);
  --color-neutral:         oklch(32%   0.02 155);
  --color-neutral-content: oklch(98%   0.002 155);

  --color-info:            oklch(60%   0.13 240);
  --color-info-content:    oklch(99%   0 0);
  --color-success:         oklch(62%   0.14 155);
  --color-success-content: oklch(99%   0 0);
  --color-warning:         oklch(75%   0.14 75);
  --color-warning-content: oklch(28%   0.05 70);
  --color-error:           oklch(58%   0.20 22);
  --color-error-content:   oklch(99%   0 0);
}

/* Amatista · claro */
[data-theme="amatista"] {
  color-scheme: light;
  --color-base-100:        oklch(99%   0.002 295);
  --color-base-200:        oklch(96.5% 0.004 295);
  --color-base-300:        oklch(92%   0.008 295);
  --color-base-content:    oklch(30%   0.025 295);

  --color-primary:         oklch(57%   0.155 295);
  --color-primary-content: oklch(99% 0 0);
  --color-secondary:       oklch(64%   0.11 195);
  --color-secondary-content: oklch(99% 0 0);
  --color-accent:          oklch(72% 0.15 70);
  --color-accent-content:  oklch(26% 0.05 70);
  --color-neutral:         oklch(32%   0.02 295);
  --color-neutral-content: oklch(98%   0.002 295);

  --color-info:            oklch(60%   0.13 240);
  --color-info-content:    oklch(99%   0 0);
  --color-success:         oklch(62%   0.14 155);
  --color-success-content: oklch(99%   0 0);
  --color-warning:         oklch(75%   0.14 75);
  --color-warning-content: oklch(28%   0.05 70);
  --color-error:           oklch(58%   0.20 22);
  --color-error-content:   oklch(99%   0 0);
}

/* Turquesa · claro */
[data-theme="turquesa"] {
  color-scheme: light;
  --color-base-100:        oklch(99%   0.002 195);
  --color-base-200:        oklch(96.5% 0.004 195);
  --color-base-300:        oklch(92%   0.008 195);
  --color-base-content:    oklch(30%   0.025 195);

  --color-primary:         oklch(57%   0.115 195);
  --color-primary-content: oklch(99% 0 0);
  --color-secondary:       oklch(64%   0.11 195);
  --color-secondary-content: oklch(99% 0 0);
  --color-accent:          oklch(72% 0.15 70);
  --color-accent-content:  oklch(26% 0.05 70);
  --color-neutral:         oklch(32%   0.02 195);
  --color-neutral-content: oklch(98%   0.002 195);

  --color-info:            oklch(60%   0.13 240);
  --color-info-content:    oklch(99%   0 0);
  --color-success:         oklch(62%   0.14 155);
  --color-success-content: oklch(99%   0 0);
  --color-warning:         oklch(75%   0.14 75);
  --color-warning-content: oklch(28%   0.05 70);
  --color-error:           oklch(58%   0.20 22);
  --color-error-content:   oklch(99%   0 0);
}

/* Ámbar · claro */
[data-theme="ambar"] {
  color-scheme: light;
  --color-base-100:        oklch(99%   0.002 80);
  --color-base-200:        oklch(96.5% 0.004 80);
  --color-base-300:        oklch(92%   0.008 80);
  --color-base-content:    oklch(30%   0.025 80);

  --color-primary:         oklch(80%   0.165 88);
  --color-primary-content: oklch(28% 0.05 70);
  --color-secondary:       oklch(64%   0.11 195);
  --color-secondary-content: oklch(99% 0 0);
  --color-accent:          oklch(70% 0.18 55);
  --color-accent-content:  oklch(26% 0.05 70);
  --color-neutral:         oklch(32%   0.02 80);
  --color-neutral-content: oklch(98%   0.002 80);

  --color-info:            oklch(60%   0.13 240);
  --color-info-content:    oklch(99%   0 0);
  --color-success:         oklch(62%   0.14 155);
  --color-success-content: oklch(99%   0 0);
  --color-warning:         oklch(75%   0.14 75);
  --color-warning-content: oklch(28%   0.05 70);
  --color-error:           oklch(58%   0.20 22);
  --color-error-content:   oklch(99%   0 0);
}

/* Cobalto · oscuro */
[data-theme="cobalto-dark"] {
  color-scheme: dark;
  --color-base-100:        oklch(20%   0.012 258);
  --color-base-200:        oklch(24%   0.014 258);
  --color-base-300:        oklch(30%   0.016 258);
  --color-base-content:    oklch(93%   0.012 258);

  --color-primary:         oklch(70%   0.15 258);
  --color-primary-content: oklch(16% 0.03 258);
  --color-secondary:       oklch(70%   0.11 195);
  --color-secondary-content: oklch(16% 0.03 230);
  --color-accent:          oklch(76% 0.14 72);
  --color-accent-content:  oklch(20%   0.04 70);
  --color-neutral:         oklch(28%   0.014 258);
  --color-neutral-content: oklch(94%   0.01 258);

  --color-info:            oklch(68%   0.13 240);
  --color-info-content:    oklch(16%   0.03 240);
  --color-success:         oklch(66%   0.14 158);
  --color-success-content: oklch(16%   0.03 160);
  --color-warning:         oklch(78%   0.14 75);
  --color-warning-content: oklch(22%   0.05 70);
  --color-error:           oklch(64%   0.19 22);
  --color-error-content:   oklch(99%   0 0);
}

/* Carmesí · oscuro */
[data-theme="carmesi-dark"] {
  color-scheme: dark;
  --color-base-100:        oklch(20%   0.012 22);
  --color-base-200:        oklch(24%   0.014 22);
  --color-base-300:        oklch(30%   0.016 22);
  --color-base-content:    oklch(93%   0.012 22);

  --color-primary:         oklch(70%   0.19 22);
  --color-primary-content: oklch(16% 0.03 22);
  --color-secondary:       oklch(70%   0.11 195);
  --color-secondary-content: oklch(16% 0.03 230);
  --color-accent:          oklch(76% 0.14 72);
  --color-accent-content:  oklch(20%   0.04 70);
  --color-neutral:         oklch(28%   0.014 22);
  --color-neutral-content: oklch(94%   0.01 22);

  --color-info:            oklch(68%   0.13 240);
  --color-info-content:    oklch(16%   0.03 240);
  --color-success:         oklch(66%   0.14 158);
  --color-success-content: oklch(16%   0.03 160);
  --color-warning:         oklch(78%   0.14 75);
  --color-warning-content: oklch(22%   0.05 70);
  --color-error:           oklch(64%   0.19 22);
  --color-error-content:   oklch(99%   0 0);
}

/* Esmeralda · oscuro */
[data-theme="esmeralda-dark"] {
  color-scheme: dark;
  --color-base-100:        oklch(20%   0.012 158);
  --color-base-200:        oklch(24%   0.014 158);
  --color-base-300:        oklch(30%   0.016 158);
  --color-base-content:    oklch(93%   0.012 158);

  --color-primary:         oklch(70%   0.14 158);
  --color-primary-content: oklch(16% 0.03 158);
  --color-secondary:       oklch(70%   0.11 195);
  --color-secondary-content: oklch(16% 0.03 230);
  --color-accent:          oklch(76% 0.14 72);
  --color-accent-content:  oklch(20%   0.04 70);
  --color-neutral:         oklch(28%   0.014 158);
  --color-neutral-content: oklch(94%   0.01 158);

  --color-info:            oklch(68%   0.13 240);
  --color-info-content:    oklch(16%   0.03 240);
  --color-success:         oklch(66%   0.14 158);
  --color-success-content: oklch(16%   0.03 160);
  --color-warning:         oklch(78%   0.14 75);
  --color-warning-content: oklch(22%   0.05 70);
  --color-error:           oklch(64%   0.19 22);
  --color-error-content:   oklch(99%   0 0);
}

/* Amatista · oscuro */
[data-theme="amatista-dark"] {
  color-scheme: dark;
  --color-base-100:        oklch(20%   0.012 292);
  --color-base-200:        oklch(24%   0.014 292);
  --color-base-300:        oklch(30%   0.016 292);
  --color-base-content:    oklch(93%   0.012 292);

  --color-primary:         oklch(70%   0.15 292);
  --color-primary-content: oklch(16% 0.03 292);
  --color-secondary:       oklch(70%   0.11 195);
  --color-secondary-content: oklch(16% 0.03 230);
  --color-accent:          oklch(76% 0.14 72);
  --color-accent-content:  oklch(20%   0.04 70);
  --color-neutral:         oklch(28%   0.014 292);
  --color-neutral-content: oklch(94%   0.01 292);

  --color-info:            oklch(68%   0.13 240);
  --color-info-content:    oklch(16%   0.03 240);
  --color-success:         oklch(66%   0.14 158);
  --color-success-content: oklch(16%   0.03 160);
  --color-warning:         oklch(78%   0.14 75);
  --color-warning-content: oklch(22%   0.05 70);
  --color-error:           oklch(64%   0.19 22);
  --color-error-content:   oklch(99%   0 0);
}

/* Turquesa · oscuro */
[data-theme="turquesa-dark"] {
  color-scheme: dark;
  --color-base-100:        oklch(20%   0.012 195);
  --color-base-200:        oklch(24%   0.014 195);
  --color-base-300:        oklch(30%   0.016 195);
  --color-base-content:    oklch(93%   0.012 195);

  --color-primary:         oklch(70%   0.11 195);
  --color-primary-content: oklch(16% 0.03 195);
  --color-secondary:       oklch(70%   0.11 195);
  --color-secondary-content: oklch(16% 0.03 230);
  --color-accent:          oklch(76% 0.14 72);
  --color-accent-content:  oklch(20%   0.04 70);
  --color-neutral:         oklch(28%   0.014 195);
  --color-neutral-content: oklch(94%   0.01 195);

  --color-info:            oklch(68%   0.13 240);
  --color-info-content:    oklch(16%   0.03 240);
  --color-success:         oklch(66%   0.14 158);
  --color-success-content: oklch(16%   0.03 160);
  --color-warning:         oklch(78%   0.14 75);
  --color-warning-content: oklch(22%   0.05 70);
  --color-error:           oklch(64%   0.19 22);
  --color-error-content:   oklch(99%   0 0);
}

/* Ámbar · oscuro */
[data-theme="ambar-dark"] {
  color-scheme: dark;
  --color-base-100:        oklch(20%   0.012 80);
  --color-base-200:        oklch(24%   0.014 80);
  --color-base-300:        oklch(30%   0.016 80);
  --color-base-content:    oklch(93%   0.012 80);

  --color-primary:         oklch(82%   0.16 88);
  --color-primary-content: oklch(22% 0.05 70);
  --color-secondary:       oklch(70%   0.11 195);
  --color-secondary-content: oklch(16% 0.03 230);
  --color-accent:          oklch(73% 0.17 55);
  --color-accent-content:  oklch(20%   0.04 70);
  --color-neutral:         oklch(28%   0.014 80);
  --color-neutral-content: oklch(94%   0.01 80);

  --color-info:            oklch(68%   0.13 240);
  --color-info-content:    oklch(16%   0.03 240);
  --color-success:         oklch(66%   0.14 158);
  --color-success-content: oklch(16%   0.03 160);
  --color-warning:         oklch(78%   0.14 75);
  --color-warning-content: oklch(22%   0.05 70);
  --color-error:           oklch(64%   0.19 22);
  --color-error-content:   oklch(99%   0 0);
}
/* ════════════════════════════════════════════════════════════
   ALIAS SEMÁNTICOS
   Nombres independientes del tema que resuelven a los tokens
   base/marca del tema activo. Preferir estos en el código de
   producto para que las pantallas cambien de tema automáticamente.
   ════════════════════════════════════════════════════════════ */
:root {
  /* ── Superficies ── */
  --surface-app:        var(--color-base-100); /* fondo de pantalla           */
  --surface-card:       var(--color-base-100); /* fondo de tarjeta / sheet    */
  --surface-sunken:     var(--color-base-200); /* inputs, track segmentado    */
  --surface-raised:     var(--color-base-300); /* fill de hover / pulsado     */

  /* ── Texto ── */
  --text-strong:        var(--color-base-content);
  --text-body:          color-mix(in oklch, var(--color-base-content), transparent 12%);
  --text-muted:         color-mix(in oklch, var(--color-base-content), transparent 40%);
  --text-faint:         color-mix(in oklch, var(--color-base-content), transparent 55%);
  --text-on-primary:    var(--color-primary-content);

  /* ── Rellenos e tintes de marca ── */
  --brand:              var(--color-primary);
  --brand-content:      var(--color-primary-content);
  --brand-tint:         color-mix(in oklch, var(--color-primary), transparent 88%);
  --brand-tint-strong:  color-mix(in oklch, var(--color-primary), transparent 78%);
  --brand-press:        color-mix(in oklch, var(--color-primary), black 14%);

  --accent:             var(--color-accent);
  --accent-content:     var(--color-accent-content);
  --accent-press:       color-mix(in oklch, var(--color-accent), black 12%);

  /* ── Bordes / separadores ── */
  --border-subtle:      var(--color-base-300);
  --border-strong:      color-mix(in oklch, var(--color-base-content), transparent 78%);
  --border-focus:       var(--color-primary);
  --focus-ring:         color-mix(in oklch, var(--color-primary), transparent 80%);

  /* ── Tintes de estado (mesas / ventas) ── */
  --state-free:         var(--text-muted);
  --state-busy-fill:    color-mix(in oklch, var(--color-primary), transparent 88%);
  --state-busy-border:  color-mix(in oklch, var(--color-primary), transparent 65%);
  --state-busy-text:    var(--color-primary);
  --state-charge-fill:  color-mix(in oklch, var(--color-warning), transparent 84%);
  --state-charge-border:color-mix(in oklch, var(--color-warning), transparent 55%);
  --state-charge-text:  var(--color-warning);
}
/* ════════════════════════════════════════════════════════════
   RESET BASE + UTILIDADES DE MARCA
   Reset mínimo global y ayudantes sy-* de app.css.
   ════════════════════════════════════════════════════════════ */
*, *::before, *::after { box-sizing: border-box; }

html, body {
  margin: 0;
  font-family: var(--font-sans);
  background: var(--surface-app);
  color: var(--text-body);
  -webkit-tap-highlight-color: transparent;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1, h2, h3, .font-display {
  font-family: var(--font-display);
  letter-spacing: var(--tracking-display);
  font-weight: var(--weight-bold);
  margin: 0;
}

/* Cifras tabulares para precios / totales */
.num {
  font-family: var(--font-display);
  font-feature-settings: "tnum" 1;
}

/* Etiqueta eyebrow / de sección */
.sy-eyebrow {
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--text-faint);
}

.sy-shadow-soft { box-shadow: var(--shadow-soft); }
.sy-shadow-lg   { box-shadow: var(--shadow-lg); }

/* Degradado de AppBar (primario, oscureciéndose hacia abajo) */
.sy-appbar {
  background: linear-gradient(180deg,
    var(--color-primary) 0%,
    color-mix(in oklch, var(--color-primary), black 16%) 100%);
  color: var(--color-primary-content);
}

/* Baño hero (panel con tinta primaria sutil) */
.sy-hero {
  background: linear-gradient(180deg,
    color-mix(in oklch, var(--color-primary), transparent 88%), transparent);
  border: 1px solid color-mix(in oklch, var(--color-primary), transparent 75%);
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    transition-duration: 0.001ms !important;
  }
}
/* ════════════════════════════════════════════════════════════
   CAPA DE COMPONENTES — propia, sin DaisyUI
   Construida sobre los tokens existentes (--brand, --surface-*,
   --radius-*, etc.). Para fragmentos Go (html/template):
   · clases .ui-* estables como contrato (no utilidades sueltas)
   · feedback de pulsación en CSS PURO (:active) — sin JS
   · switch y segmented interactivos con checkbox/radio (sin JS)
   · iconos: fragments/icons/*.html, SVG de Lucide ya resuelto
     en el propio HTML (sin CDN ni JS)
   · layout (flex/grid/gap): utilidades .u-* — ver sección
     "VISUALIZACIÓN · LAYOUT" al final del fichero. Ningún
     fragmento debe llevar style="display:flex;gap:...", siempre
     estas clases.
   ════════════════════════════════════════════════════════════ */

/* ── Icono (SVG inline vía fragments/icons/*, sin CDN) ───── */
.ui-icon { display: inline-flex; line-height: 0; flex: 0 0 auto; }
.ui-icon svg { width: 100%; height: 100%; display: block; }

/* Tamaños fijos — el SVG de fragments/icons/* no trae width/height propios
   (se retiran al copiarlo de Lucide), así que el tamaño real lo pone
   siempre esta clase, nunca un atributo/estilo inline. */
.ui-icon--13 { width: 13px; height: 13px; }
.ui-icon--14 { width: 14px; height: 14px; }
.ui-icon--16 { width: 16px; height: 16px; }
.ui-icon--18 { width: 18px; height: 18px; }
.ui-icon--19 { width: 19px; height: 19px; }
.ui-icon--20 { width: 20px; height: 20px; }
.ui-icon--22 { width: 22px; height: 22px; }
.ui-icon--24 { width: 24px; height: 24px; }
.ui-icon--26 { width: 26px; height: 26px; }
.ui-icon--28 { width: 28px; height: 28px; }
.ui-icon--32 { width: 32px; height: 32px; }
.ui-icon--40 { width: 40px; height: 40px; }
.ui-icon--48 { width: 48px; height: 48px; }

/* Tintes — cuando el icono necesita un color fijo distinto de currentColor
   (que por defecto hereda del texto que lo rodea). */
.ui-icon--faint  { color: var(--text-faint); }
.ui-icon--muted  { color: var(--text-muted); }
.ui-icon--brand  { color: var(--brand); }
.ui-icon--success{ color: var(--color-success); }

/* ── Botón ──────────────────────────────────────────────── */
.ui-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: var(--touch-input);            /* 50px — dedo */
  padding: 0 22px;
  font-family: var(--font-sans); font-size: var(--text-base); font-weight: var(--weight-bold); line-height: 1;
  border: 1px solid transparent; border-radius: var(--radius-box); text-decoration: none;
  cursor: pointer; user-select: none; -webkit-tap-highlight-color: transparent;
  transition: transform var(--dur-press) var(--ease-out), background var(--dur-fast) var(--ease-standard);
}
.ui-btn:active:not(:disabled) { transform: scale(var(--press-scale-sm)); }  /* relieve al pulsar */
.ui-btn:disabled { opacity: .55; cursor: not-allowed; }
.ui-btn--block { width: 100%; }
.ui-btn--sm { min-height: 40px; padding: 0 16px; font-size: var(--text-sm); }
.ui-btn--lg { min-height: var(--touch-btn); font-size: var(--text-lg); }
.ui-btn--primary   { background: var(--brand);        color: var(--brand-content); }
.ui-btn--primary:active:not(:disabled)   { background: var(--brand-press); }
.ui-btn--accent    { background: var(--accent);       color: var(--accent-content); }
.ui-btn--accent:active:not(:disabled)    { background: var(--accent-press); }
.ui-btn--secondary { background: var(--brand-tint);   color: var(--brand); }
.ui-btn--ghost     { background: transparent;         color: var(--text-body); }
.ui-btn--ghost:active:not(:disabled)     { background: var(--surface-sunken); }
.ui-btn--outline   { background: var(--surface-card);  color: var(--text-body); border-color: var(--border-subtle); }
.ui-btn--outline:active:not(:disabled)   { background: var(--surface-sunken); }
/* ── Variantes semánticas ─────────────────────────────────
   Mismos tokens que Badge (info/success/warning/error), pero sólidas.
   danger se conserva como alias histórico de error. */
.ui-btn--success  { background: var(--color-success); color: var(--color-success-content); }
.ui-btn--success:active:not(:disabled)  { background: color-mix(in oklch, var(--color-success), black 12%); }
.ui-btn--warning  { background: var(--color-warning); color: var(--color-warning-content); }
.ui-btn--warning:active:not(:disabled)  { background: color-mix(in oklch, var(--color-warning), black 12%); }
.ui-btn--error,
.ui-btn--danger    { background: var(--color-error);   color: var(--color-error-content); }
.ui-btn--error:active:not(:disabled),
.ui-btn--danger:active:not(:disabled)    { background: color-mix(in oklch, var(--color-error), black 12%); }
.ui-btn--info     { background: var(--color-info);    color: var(--color-info-content); }
.ui-btn--info:active:not(:disabled)     { background: color-mix(in oklch, var(--color-info), black 12%); }

/* ── Botón con estado de carga (spinner superpuesto) ─────── */
.ui-btn { position: relative; }
.btn-content { display: inline-flex; align-items: center; justify-content: center; gap: 8px; }
.btn-content--hidden { visibility: hidden; }
.btn-spinner-overlay { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; }
.ui-spinner { width: 20px; height: 20px; border: 2.5px solid color-mix(in oklch, currentColor, transparent 70%);
  border-top-color: currentColor; border-radius: 50%; animation: ui-spin 0.7s linear infinite; }
@keyframes ui-spin { to { transform: rotate(360deg); } }

/* ── Botón de icono ─────────────────────────────────────── */
.ui-iconbtn {
  flex: 0 0 auto; width: var(--icon-btn); height: var(--icon-btn);
  display: inline-flex; align-items: center; justify-content: center;
  border: 0; border-radius: var(--radius-control);
  background: transparent; color: var(--text-body); text-decoration: none;
  cursor: pointer; -webkit-tap-highlight-color: transparent;
  transition: background var(--dur-fast) var(--ease-standard);
}
.ui-iconbtn:active:not(:disabled) { background: var(--surface-sunken); }
.ui-iconbtn:disabled { opacity: .5; cursor: not-allowed; }
.ui-iconbtn--40 { width: 40px; height: 40px; }
.ui-iconbtn--filled { background: var(--surface-sunken); }
.ui-iconbtn--filled:active:not(:disabled) { background: var(--surface-raised); }
.ui-iconbtn--on-primary { color: var(--color-primary-content); background: color-mix(in oklch, var(--color-primary-content), transparent 84%); }
.ui-iconbtn--on-primary:active { background: color-mix(in oklch, var(--color-primary-content), transparent 70%); }

/* ── Badge ──────────────────────────────────────────────── */
.ui-badge {
  display: inline-flex; align-items: center; gap: 5px; height: 24px; padding: 0 10px;
  border-radius: var(--radius-pill);
  font-family: var(--font-sans); font-size: var(--text-xs); font-weight: var(--weight-bold); white-space: nowrap;
}
.ui-badge--neutral { background: color-mix(in oklch, var(--color-base-content), transparent 86%); color: var(--text-strong); }
.ui-badge--brand   { background: var(--brand-tint);  color: var(--brand); }
.ui-badge--success { background: color-mix(in oklch, var(--color-success), transparent 86%); color: var(--color-success); }
.ui-badge--warning { background: color-mix(in oklch, var(--color-warning), transparent 84%); color: var(--color-warning); }
.ui-badge--error   { background: color-mix(in oklch, var(--color-error),   transparent 86%); color: var(--color-error); }
.ui-badge--info    { background: color-mix(in oklch, var(--color-info),    transparent 86%); color: var(--color-info); }
.ui-badge--solid   { background: var(--brand); color: var(--brand-content); }

/* ── Badge · punto de estado con ping (indicador "en vivo") ──
   Punto sólido + halo que se expande y desvanece en bucle, mismo
   patrón que el "ping" de Tailwind. El color del punto/halo hereda
   currentColor, así que sigue automáticamente el tone del badge
   (--color-success en success, --color-error en error, etc.). */
/* margin-top: el centrado flex del badge centra respecto a la altura de
   línea, no respecto al centro óptico del texto (ascendentes/descendentes
   de --text-xs lo desplazan) — este ajuste fino baja el punto para que su
   centro coincida de verdad con el centro visual del texto de al lado. */
.ui-badge__dot { position: relative; display: inline-flex; width: 7px; height: 7px; flex: 0 0 auto; margin-top: 0.2px; }
.ui-badge__dot::before, .ui-badge__dot::after {
  content: ""; position: absolute; inset: 0; border-radius: 50%; background: currentColor;
}
/* ::before = halo que crece y se desvanece, detrás; ::after = punto fijo,
   delante — sin z-index el punto (pintado después en el árbol) tapa el
   halo por completo durante toda la animación y el ping no se ve. */
.ui-badge__dot::before { z-index: 0; animation: ui-ping 1.6s cubic-bezier(0, 0, 0.2, 1) infinite; }
.ui-badge__dot::after { z-index: 1; }
@keyframes ui-ping {
  0%   { transform: scale(1);   opacity: .8; }
  75%, 100% { transform: scale(3); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .ui-badge__dot::before { animation: none; }
}

/* ── CountBadge (burbuja flotante sobre tiles) ──────────── */
.ui-countbadge {
  position: absolute; min-width: 26px; height: 26px; padding: 0 7px; border-radius: 13px;
  display: inline-flex; align-items: center; justify-content: center;
  font-family: var(--font-display); font-size: var(--text-sm); font-weight: var(--weight-extra);
  background: var(--brand); color: var(--brand-content); box-shadow: var(--shadow-badge);
}
.ui-countbadge--tr { top: -7px; right: -7px; }
.ui-countbadge--tl { top: -7px; left: -7px; }
.ui-countbadge--neutral { background: var(--surface-raised); color: var(--text-strong); }

/* ── Chip ───────────────────────────────────────────────── */
.ui-chip {
  display: inline-flex; align-items: center; gap: 7px; min-height: 44px; padding: 9px 16px;
  border-radius: var(--radius-pill);
  font-family: var(--font-sans); font-size: var(--text-sm); font-weight: var(--weight-semibold); white-space: nowrap;
  cursor: pointer; border: 1px solid var(--border-subtle); background: var(--surface-card); color: var(--text-body);
  -webkit-tap-highlight-color: transparent; transition: transform var(--dur-press) var(--ease-out);
}
.ui-chip:active { transform: scale(var(--press-scale)); }
.ui-chip[aria-pressed="true"] { border-color: var(--brand); background: var(--brand); color: var(--brand-content); }

/* ── Campo de búsqueda ──────────────────────────────────── */
.ui-search { position: relative; }
.ui-search__icon { position: absolute; left: 14px; top: 50%; transform: translateY(-50%); color: var(--text-faint); pointer-events: none; display: inline-flex; }
.ui-search__input {
  width: 100%; height: var(--touch-input); padding: 0 44px;
  font-family: var(--font-sans); font-size: var(--text-base); color: var(--text-strong);
  background: var(--surface-sunken); border: 1px solid transparent; border-radius: var(--radius-box); outline: none;
  transition: background var(--dur-fast), border-color var(--dur-fast), box-shadow var(--dur-fast);
}
/* input[type=search] trae su propia X nativa en WebKit/Blink — la
   ocultamos porque el fragmento ya dibuja su propio .ui-search__clear
   (icono Lucide); sin esto se ven dos X distintas superpuestas. */
.ui-search__input::-webkit-search-cancel-button,
.ui-search__input::-webkit-search-decoration { -webkit-appearance: none; appearance: none; }
.ui-search__input:focus { background: var(--surface-card); border-color: var(--border-focus); box-shadow: 0 0 0 3.5px var(--focus-ring); }
.ui-search__clear { position: absolute; right: 8px; top: 50%; transform: translateY(-50%); width: 34px; height: 34px;
  border: 0; border-radius: 50%; background: transparent; color: var(--text-faint); cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center; }

/* ── Campo de texto ─────────────────────────────────────── */
.ui-field { display: block; }
.ui-field__label { display: block; margin-bottom: 8px; font-size: var(--text-sm); font-weight: var(--weight-bold); color: var(--text-strong); }
.ui-field__input {
  width: 100%; height: var(--touch-input); padding: 0 16px;
  font-family: var(--font-sans); font-size: var(--text-base); color: var(--text-strong);
  background: var(--brand-tint); border: 1px solid transparent; border-radius: var(--radius-box); outline: none;
  transition: background var(--dur-fast), border-color var(--dur-fast), box-shadow var(--dur-fast);
}
.ui-field__input:focus { background: var(--surface-card); border-color: var(--border-focus); box-shadow: 0 0 0 3.5px var(--focus-ring); }
.ui-field--error .ui-field__input { border-color: var(--color-error); }

/* ── Textarea (multilínea) ─────────────────────────────────
   No hereda .ui-field__input: esa clase fija height (pensada
   para 1 línea con padding vertical 0, el texto se centra solo
   por line-height). En un <textarea> eso deja el texto pegado
   arriba — aquí height es auto y el padding vertical hace de
   aire simétrico arriba/abajo. */
.ui-field__textarea {
  width: 100%; min-height: calc(var(--touch-input) * 2); padding: 12px 16px; resize: vertical;
  font-family: var(--font-sans); font-size: var(--text-base); line-height: 1.5; color: var(--text-strong);
  background: var(--brand-tint); border: 1px solid transparent; border-radius: var(--radius-box); outline: none;
  transition: background var(--dur-fast), border-color var(--dur-fast), box-shadow var(--dur-fast);
}
.ui-field__textarea:focus { background: var(--surface-card); border-color: var(--border-focus); box-shadow: 0 0 0 3.5px var(--focus-ring); }
.ui-field--error .ui-field__textarea { border-color: var(--color-error); }
.ui-field__hint { display: block; margin-top: 6px; font-size: var(--text-xs); color: var(--text-muted); }
.ui-field--error .ui-field__hint { color: var(--color-error); }

/* ── Multiselect (desplegable de selección múltiple) ─────── */
.ui-multiselect { position: relative; }
.ui-multiselect__toggle {
  width: 100%; min-height: var(--touch-input); padding: 0 14px; text-align: left;
  background: var(--surface-sunken); border: 1px solid var(--border-subtle); border-radius: var(--radius-field);
  font-family: var(--font-sans); font-size: var(--text-base); color: var(--text-strong);
  cursor: pointer; -webkit-tap-highlight-color: transparent;
}
.ui-multiselect__menu {
  position: absolute; z-index: 20; top: calc(100% + 6px); left: 0; right: 0;
  max-height: 260px; overflow-y: auto; padding: var(--space-3);
  background: var(--surface-card); border: 1px solid var(--border-subtle); border-radius: var(--radius-box);
  box-shadow: var(--shadow-pop); display: flex; flex-direction: column; gap: 2px;
}
.ui-multiselect__opt { display: flex; align-items: center; gap: var(--space-4); min-height: 40px; padding: 0 var(--space-4);
  border-radius: var(--radius-field); font-size: var(--text-base); color: var(--text-body); cursor: pointer;
  text-decoration: none; -webkit-tap-highlight-color: transparent; }
.ui-multiselect__opt:active { background: var(--surface-sunken); }
.ui-multiselect__opt input { width: 18px; height: 18px; accent-color: var(--brand); flex: 0 0 auto; }

/* ── Popover (clic para revelar contenido flotante) ───────
   Genérico: úsalo cuando un valor de celda/resumen no cabe en su
   espacio y hace falta un detalle expandible bajo demanda (p. ej.
   lista de precios por formato en una tabla). */
.ui-popover { position: relative; display: inline-block; max-width: 100%; }
.ui-popover__trigger {
  display: block; max-width: 100%; padding: 0; border: 0; background: none; text-align: left;
  font: inherit; color: inherit; cursor: pointer; -webkit-tap-highlight-color: transparent;
}
.ui-popover__trigger:hover .ui-cell-truncate,
.ui-popover__trigger[aria-expanded="true"] .ui-cell-truncate { color: var(--brand); text-decoration: underline; text-underline-offset: 3px; }
.ui-popover__panel {
  position: absolute; z-index: 20; top: calc(100% + 6px); left: 0; min-width: 180px; max-width: 260px;
  padding: var(--space-8); background: var(--surface-card); border: 1px solid var(--border-subtle);
  border-radius: var(--radius-box); box-shadow: var(--shadow-pop);
}
.ui-popover__list { display: flex; flex-direction: column; gap: var(--space-2); list-style: none; margin: 0; padding: 0; }
.ui-popover__list li { display: flex; align-items: center; justify-content: space-between; gap: var(--space-4);
  font-size: var(--text-sm); color: var(--text-body); }

/* Contenido de celda truncado a 1 línea — combínalo con .ui-table__col-fixed
   en el th/td y con .ui-popover cuando el valor completo deba quedar
   accesible bajo demanda (p. ej. precios/indicadores de una tabla). */
.ui-cell-truncate { display: block; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ── Checkbox real (selección múltiple en listas, no on/off) ─
   Úsalo cuando el control representa "seleccionado" dentro de un
   conjunto (p. ej. filas de una lista para una acción en lote), no
   un estado binario permanente — para eso usa .ui-switch. */
.ui-checkbox { width: 20px; height: 20px; accent-color: var(--brand); flex: 0 0 auto; cursor: pointer; }

/* ── Switch (checkbox, interactivo sin JS) ──────────────── */
.ui-switch { position: relative; display: inline-block; width: 54px; height: 32px; flex: 0 0 auto; cursor: pointer; }
.ui-switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.ui-switch__track { position: absolute; inset: 0; border-radius: var(--radius-pill);
  border: 2px solid var(--border-strong); background: var(--surface-card);
  transition: background var(--dur-fast) var(--ease-standard), border-color var(--dur-fast); }
.ui-switch__track::after { content: ""; position: absolute; top: 50%; left: 3px; width: 22px; height: 22px; margin-top: -11px;
  border-radius: 50%; background: var(--border-strong); box-shadow: var(--shadow-card);
  transition: left var(--dur-fast) var(--ease-out), background var(--dur-fast); }
.ui-switch input:checked + .ui-switch__track { background: var(--brand); border-color: var(--brand); }
.ui-switch input:checked + .ui-switch__track::after { left: calc(100% - 25px); background: var(--brand-content); }
.ui-switch--sm { width: 38px; height: 22px; }
.ui-switch--sm .ui-switch__track::after { width: 14px; height: 14px; margin-top: -7px; left: 3px; }
.ui-switch--sm input:checked + .ui-switch__track::after { left: calc(100% - 17px); }

/* ── Grupo de switches (checkbox real, apariencia de switch) ─
   Genérico para listas cortas de propiedades booleanas (p. ej.
   indicadores de producto). A partir de 6 elementos se reparte
   en 2 columnas de arriba a abajo (el 6º pasa a la 2ª columna). */
.ui-switch-group { display: block; }
.ui-switch-group--cols2 { columns: 2; column-gap: var(--space-5); }
.ui-switch-item { display: flex; align-items: center; gap: var(--space-3); break-inside: avoid; margin-bottom: var(--space-3); }
.ui-switch-item:last-child { margin-bottom: 0; }
.ui-switch-item__label { font-size: var(--text-sm); color: var(--text-strong); }

/* ── Tri-switch (3 estados, interactivo sin JS) ─────────────
   Mismo patrón que .ui-switch pero con 3 radios ocultos en vez
   de 1 checkbox: el thumb desliza a 1 de 3 posiciones según cuál
   esté marcado. Genérico (no/parcial/sí) — el color de cada
   estado se pasa como modificador (--warn / --danger) para que
   el llamador elija qué semántica encaja (alérgeno, disponibilidad,
   nivel de alerta…). */
.ui-triswitch { position: relative; display: inline-flex; width: 78px; height: 32px; flex: 0 0 auto;
  border-radius: var(--radius-pill); border: 2px solid var(--border-strong); background: var(--surface-card);
  transition: border-color var(--dur-fast) var(--ease-standard); }
.ui-triswitch input { position: absolute; opacity: 0; width: 0; height: 0; }
.ui-triswitch__thumb { position: absolute; top: 50%; left: 3px; width: 22px; height: 22px; margin-top: -11px;
  border-radius: 50%; background: var(--border-strong); box-shadow: var(--shadow-card);
  transition: left var(--dur-fast) var(--ease-out), background var(--dur-fast) var(--ease-standard); }
.ui-triswitch__opt { position: relative; flex: 1 1 0; z-index: 1; display: flex; align-items: center; justify-content: center;
  cursor: pointer; -webkit-tap-highlight-color: transparent; }
.ui-triswitch__opt .ui-icon { color: var(--text-faint); transition: color var(--dur-fast); pointer-events: none; }
/* Compensación óptica: el trazo "minus" (línea fina), el triángulo
   (vértice estrecho) y el círculo (relleno pesado a la derecha por
   el punto ".01") se perciben desplazados aunque su bbox SVG esté
   centrado. */
.ui-triswitch__opt:nth-of-type(1) .ui-icon { transform: translateX(1px); }
.ui-triswitch__opt:nth-of-type(2) .ui-icon { transform: translateX(0.5px); }
.ui-triswitch__opt:nth-of-type(3) .ui-icon { transform: translateX(-1px); }
/* Posición 1/2/3 del thumb — activada por :checked en cualquiera de los 3
   radios (selector de hermano general ~ para llegar desde cualquier opción). */
.ui-triswitch:has(input:nth-of-type(1):checked) .ui-triswitch__thumb { left: 3px; }
.ui-triswitch:has(input:nth-of-type(2):checked) .ui-triswitch__thumb { left: calc(50% - 11px); background: var(--color-warning); }
.ui-triswitch:has(input:nth-of-type(3):checked) .ui-triswitch__thumb { left: calc(100% - 25px); background: var(--color-error); }
.ui-triswitch:has(input:nth-of-type(2):checked) { border-color: var(--color-warning); }
.ui-triswitch:has(input:nth-of-type(3):checked) { border-color: var(--color-error); }
.ui-triswitch input:nth-of-type(2):checked ~ .ui-triswitch__opt:nth-of-type(2) .ui-icon,
.ui-triswitch input:nth-of-type(3):checked ~ .ui-triswitch__opt:nth-of-type(3) .ui-icon { color: var(--color-base-100); }
.ui-triswitch input:nth-of-type(1):checked ~ .ui-triswitch__opt:nth-of-type(1) .ui-icon { color: var(--text-strong); }

/* ── Stepper (estado por servidor; +/- cablea JS más tarde) ─ */
.ui-stepper { display: flex; align-items: center; gap: 16px; }
.ui-stepper__btn { width: 48px; height: 48px; flex: 0 0 auto; border: 0; border-radius: var(--radius-box);
  background: var(--surface-sunken); color: var(--text-strong); cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center; -webkit-tap-highlight-color: transparent;
  transition: transform var(--dur-press) var(--ease-out), background var(--dur-fast); }
.ui-stepper__btn:active:not(:disabled) { transform: scale(var(--press-scale)); background: var(--surface-raised); }
.ui-stepper__btn:disabled { opacity: .4; cursor: not-allowed; }
.ui-stepper__val { flex: 1 1 auto; text-align: center; font-family: var(--font-display); font-feature-settings: "tnum" 1;
  font-size: var(--text-xl); font-weight: var(--weight-extra); color: var(--text-strong); }
.ui-stepper--lg .ui-stepper__btn { width: 64px; height: 64px; }
.ui-stepper--lg .ui-stepper__val { font-size: var(--text-3xl); }

/* ── Segmented (radios, interactivo sin JS) ─────────────── */
.ui-seg { display: flex; gap: 4px; padding: 4px; border-radius: var(--radius-control); background: var(--surface-sunken); }
.ui-seg__opt { flex: 1 1 0; position: relative; }
.ui-seg__opt input { position: absolute; opacity: 0; inset: 0; cursor: pointer; }
.ui-seg__opt span { display: flex; align-items: center; justify-content: center; min-height: 42px; padding: 0 var(--space-8); border-radius: 9px;
  color: var(--text-muted); font-family: var(--font-sans); font-size: var(--text-sm); font-weight: var(--weight-semibold);
  white-space: nowrap; transition: color var(--dur-fast), background var(--dur-fast); }
.ui-seg__opt input:checked + span { background: var(--surface-card); color: var(--brand); box-shadow: var(--shadow-seg); }
.ui-seg--tall .ui-seg__opt span { min-height: 52px; }

/* ── Range doble (slider con dos mangos) ─────────────────
   Dos <input type=range> superpuestos sobre una misma pista: la pista y el
   relleno van detrás y solo el mango (thumb) captura el puntero, así ambos
   mangos son arrastrables sin librerías. */
.ui-range__header { display: flex; justify-content: space-between; margin-bottom: var(--space-4);
  font-family: var(--font-display); font-weight: var(--weight-bold); color: var(--text-strong); }
.ui-range__slider { position: relative; height: 24px; }
.ui-range__track, .ui-range__fill { position: absolute; top: 50%; transform: translateY(-50%); height: 4px; border-radius: 2px; }
.ui-range__track { left: 0; right: 0; background: var(--surface-sunken); }
.ui-range__fill { background: var(--brand); }
.ui-range__slider input[type="range"] {
  position: absolute; top: 0; left: 0; width: 100%; height: 24px; margin: 0;
  -webkit-appearance: none; appearance: none; background: transparent; pointer-events: none; }
.ui-range__slider input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none; pointer-events: auto;
  width: 20px; height: 20px; border-radius: 50%; background: var(--brand);
  border: 2px solid var(--surface-card); box-shadow: var(--shadow-seg); cursor: pointer; }
.ui-range__slider input[type="range"]::-moz-range-thumb {
  pointer-events: auto; width: 20px; height: 20px; border-radius: 50%; background: var(--brand);
  border: 2px solid var(--surface-card); box-shadow: var(--shadow-seg); cursor: pointer; }
.ui-range__slider input[type="range"]::-moz-range-track { background: transparent; border: 0; }

/* ── Tarjeta ────────────────────────────────────────────── */
.ui-card { background: var(--surface-card); border: 1px solid var(--border-subtle); border-radius: var(--radius-box); padding: 14px; }
.ui-card--interactive { cursor: pointer; -webkit-tap-highlight-color: transparent; transition: transform var(--dur-press) var(--ease-out); }
.ui-card--interactive:active { transform: scale(var(--press-scale-row)); }
.ui-card--row { display: flex; align-items: center; gap: var(--space-3); min-height: 64px; }

/* ── Lista de tarjetas (contenedor genérico de listados) ── */
.ui-list { margin-top: var(--space-4); display: flex; flex-direction: column; gap: var(--space-6); }
.ui-list a { text-decoration: none; }

/* ── Asa de arrastre para listas reordenables ────────────── */
.ui-drag-handle { display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto;
  color: var(--text-faint); cursor: grab; touch-action: none; -webkit-tap-highlight-color: transparent; }
.ui-drag-handle:active { cursor: grabbing; }
.sortable-ghost { opacity: .4; }

/* ── Modal ──────────────────────────────────────────────── */
.ui-modal-backdrop {
  position: fixed; inset: 0; z-index: 60;
  background: color-mix(in oklch, black, transparent 45%);
  display: flex; align-items: center; justify-content: center;
  padding: var(--gutter);
}
.ui-modal {
  background: var(--surface-card); border-radius: var(--radius-box);
  padding: 20px; width: 100%; max-width: 420px; max-height: 85vh; overflow-y: auto;
  box-shadow: var(--shadow-pop);
}
.ui-modal-actions { display: flex; gap: 8px; margin-top: 4px; }
.ui-modal-actions__cancel { flex: 1; }
.ui-modal-actions__submit { flex: 2; }
.ui-modal--form { max-width: 440px; display: flex; flex-direction: column; gap: 14px; }
.ui-modal--form-wide { max-width: 620px; }
.ui-modal-title { margin: 0; }
.ui-modal-actions--sticky { position: sticky; bottom: 0; background: var(--surface-card); padding-top: 8px; }

/* ── Etiqueta de sección ────────────────────────────────── */
.ui-section-label { font-size: var(--text-xs); font-weight: var(--weight-bold); letter-spacing: var(--tracking-label);
  text-transform: uppercase; color: var(--text-faint); margin: 2px 2px 8px; }

/* ── App bar ────────────────────────────────────────────── */
.ui-appbar { flex: 0 0 auto; display: flex; align-items: center; gap: 10px; padding: 12px 14px;
  background: var(--surface-card); color: var(--text-strong); border-bottom: 1px solid var(--border-subtle); }
.ui-appbar--brand { background: var(--color-primary);
  color: var(--color-primary-content); border-bottom: 0; }
.ui-appbar__body { flex: 1 1 auto; min-width: 0; }
.ui-appbar__title { font-family: var(--font-display); font-size: var(--text-xl); font-weight: var(--weight-bold); line-height: 1.15;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ui-appbar__subtitle { font-size: var(--text-sm); color: var(--text-muted); margin-top: 1px; }
.ui-appbar--brand .ui-appbar__subtitle { color: color-mix(in oklch, var(--color-primary-content), transparent 25%); }

/* ── Selector de tema (app bar) ─────────────────────────── */
.ui-theme-picker { position: relative; flex: 0 0 auto; }
.ui-theme-picker__trigger { display: flex; align-items: center; justify-content: center; width: var(--icon-btn); height: var(--icon-btn);
  border: 1px solid var(--border-subtle); border-radius: 50%; background: var(--surface-sunken); padding: 0; cursor: pointer; }
.ui-theme-picker__swatch { width: 20px; height: 20px; border-radius: 50%; background: var(--color-primary); }

.ui-theme-picker__menu { position: absolute; top: calc(100% + 8px); right: 0; z-index: 20; width: 240px;
  background: var(--surface-card); border: 1px solid var(--border-subtle); border-radius: var(--radius-box);
  box-shadow: var(--shadow-pop); padding: var(--space-8); }
.ui-theme-picker__menu .ui-section-label { margin-top: var(--space-6); }
.ui-theme-picker__menu .ui-section-label:first-child { margin-top: 0; }

.ui-theme-picker__grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-4); }
.ui-theme-picker__option { display: flex; flex-direction: column; align-items: center; gap: var(--space-2);
  padding: var(--space-4) var(--space-2); border: 1px solid transparent; border-radius: var(--radius-control);
  background: transparent; color: var(--text-muted); font-size: var(--text-2xs); font-weight: var(--weight-semibold); cursor: pointer; }
.ui-theme-picker__option.is-active { border-color: var(--color-primary); background: var(--surface-sunken); color: var(--text-strong); }
.ui-theme-picker__option-swatch { width: 24px; height: 24px; border-radius: 50%; background: var(--color-primary); border: 1px solid var(--border-subtle); }

.ui-mode-toggle { display: flex; gap: 4px; padding: 4px; border-radius: var(--radius-control); background: var(--surface-sunken); }
.ui-mode-toggle__opt { flex: 1 1 0; display: flex; align-items: center; justify-content: center; min-height: 42px;
  border: 0; border-radius: 9px; background: transparent; color: var(--text-muted); cursor: pointer;
  -webkit-tap-highlight-color: transparent; transition: color var(--dur-fast), background var(--dur-fast); }
.ui-mode-toggle__opt.is-active { background: var(--surface-card); color: var(--brand); box-shadow: var(--shadow-seg); }

.ui-theme-picker__divider { height: 1px; background: var(--border-subtle); margin: var(--space-6) 0; }
.ui-theme-picker__logout { display: flex; align-items: center; justify-content: center; width: 100%; min-height: 42px;
  border: 0; border-radius: 9px; background: transparent; color: var(--color-error);
  font-family: var(--font-sans); font-size: var(--text-sm); font-weight: var(--weight-bold); text-decoration: none;
  cursor: pointer; -webkit-tap-highlight-color: transparent; transition: background var(--dur-fast); }
.ui-theme-picker__logout:active { background: color-mix(in oklch, var(--color-error), transparent 90%); }
.ui-theme-picker__action { display: flex; align-items: center; justify-content: center; width: 100%; min-height: 42px;
  border: 0; border-radius: 9px; background: transparent; color: var(--text-body);
  font-family: var(--font-sans); font-size: var(--text-sm); font-weight: var(--weight-bold); text-decoration: none;
  cursor: pointer; -webkit-tap-highlight-color: transparent; transition: background var(--dur-fast); }
.ui-theme-picker__action:active { background: var(--surface-sunken); }

/* ── Tabs (subrayado; swap de contenido cablea JS) ──────── */
.ui-tabs { display: flex; gap: 6px; padding: 10px 14px 0; background: var(--surface-card); border-bottom: 1px solid var(--border-subtle); }
.ui-tabs__tab { position: relative; flex: 1 1 0; border: 0; background: transparent; padding: 11px 4px;
  font-family: var(--font-sans); font-size: var(--text-base); font-weight: var(--weight-bold); color: var(--text-muted);
  border-radius: 11px 11px 0 0; cursor: pointer; -webkit-tap-highlight-color: transparent; transition: color var(--dur-fast); }
.ui-tabs__tab[aria-selected="true"] { color: var(--brand); }
.ui-tabs__tab[aria-selected="true"]::after { content: ""; position: absolute; left: 14px; right: 14px; bottom: -1px; height: 3px; background: var(--brand); border-radius: 3px; }

/* ── Acordeón (secciones plegables) ──────────────────────── */
.ui-accordion { display: flex; flex-direction: column; gap: var(--space-6); margin-bottom: var(--space-8); }
.ui-accordion__section { background: var(--surface-card); border: 1px solid var(--border-subtle); border-radius: var(--radius-box); overflow: visible; }
.ui-accordion__trigger {
  width: 100%; display: flex; align-items: center; justify-content: space-between; gap: var(--space-6);
  min-height: var(--touch-input); padding: 0 14px; border: 0; border-radius: inherit; background: transparent;
  font-family: var(--font-sans); font-size: var(--text-base); font-weight: var(--weight-bold); color: var(--text-strong);
  cursor: pointer; -webkit-tap-highlight-color: transparent; transition: background var(--dur-fast) var(--ease-standard);
}
.ui-accordion__trigger:active { background: var(--surface-sunken); }
.ui-accordion__chevron { width: 8px; height: 8px; flex: 0 0 auto; border-right: 2px solid var(--text-muted); border-bottom: 2px solid var(--text-muted);
  transform: rotate(45deg); transition: transform var(--dur-fast) var(--ease-standard); }
.ui-accordion__trigger.is-open .ui-accordion__chevron { transform: rotate(-135deg); }
.ui-accordion__panel { padding: 0 14px 14px; display: flex; flex-direction: column; gap: var(--space-3); }

/* ── TabBar (nav inferior) ──────────────────────────────── */
/* El fondo sigue al tema como el resto del sistema (--surface-card). Lo
   que es fijo es el icono: inactivo siempre negro sólido, activo siempre
   el color primario del tema (--brand), para que cada variocolor se note. */
.ui-tabbar { flex: 0 0 auto; display: flex; background: var(--surface-card); border-top: 1px solid var(--border-subtle);
  padding: 8px 4px calc(8px + env(safe-area-inset-bottom)); }
.ui-tabbar__item { flex: 1 1 0; display: flex; flex-direction: column; align-items: center; gap: 5px;
  border: 0; background: transparent; padding: 6px 0; color: oklch(0% 0 0); cursor: pointer; -webkit-tap-highlight-color: transparent;
  text-decoration: none; }
.ui-tabbar__item[aria-current="page"] { color: var(--brand); }
.ui-tabbar__dot { width: 18px; height: 2px; border-radius: 2px; background: transparent; }
.ui-tabbar__item[aria-current="page"] .ui-tabbar__dot { background: var(--brand); }

/* ── Selection bar (dock de acciones sobre selección) ────── */
.ui-selection-bar { position: fixed; left: 0; right: 0; bottom: 0; z-index: 55;
  display: flex; align-items: center; gap: var(--space-4);
  background: var(--surface-card); border-top: 1px solid var(--border-subtle);
  padding: 10px var(--gutter) calc(10px + env(safe-area-inset-bottom));
  box-shadow: var(--shadow-pop); }
.ui-selection-bar__count { flex: 1 1 auto; font-size: var(--text-sm); font-weight: var(--weight-semibold); color: var(--text-body); }

/* ── Pager (paginación) ──────────────────────────────────── */
.ui-pager { display: flex; align-items: center; justify-content: space-between; gap: var(--space-6); margin-bottom: var(--space-12); }
.ui-pager__info { font-size: var(--text-sm); color: var(--text-muted); font-weight: var(--weight-semibold); }

/* ── Skeleton ───────────────────────────────────────────── */
.ui-skel { display: block; border-radius: var(--radius-field);
  background: linear-gradient(100deg, var(--surface-sunken) 30%, var(--surface-raised) 50%, var(--surface-sunken) 70%);
  background-size: 200% 100%; animation: ui-shimmer 1.3s ease-in-out infinite; }
.ui-skel--tile { border-radius: var(--radius-box); }
@keyframes ui-shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }

/* ── Empty state ────────────────────────────────────────── */
.ui-empty { text-align: center; color: var(--text-muted); padding: 40px 20px; }
.ui-empty__icon { display: inline-flex; margin-bottom: 8px; opacity: .5; }
.ui-empty__title { font-size: var(--text-base); font-weight: var(--weight-semibold); color: var(--text-body); }
.ui-empty__hint { font-size: var(--text-sm); margin-top: 4px; }

/* ── Avatar ─────────────────────────────────────────────── */
.ui-avatar { width: 56px; height: 56px; flex: 0 0 auto; border-radius: 50%;
  background: var(--brand-tint); color: var(--brand); text-transform: uppercase;
  display: inline-flex; align-items: center; justify-content: center;
  font-family: var(--font-display); font-weight: var(--weight-bold); font-size: 22px; }
.ui-avatar--neutral { background: var(--surface-sunken); color: var(--text-body); }
.ui-avatar--sm { width: 32px; height: 32px; font-size: var(--text-sm); }
.ui-avatar--xs { width: 28px; height: 28px; font-size: var(--text-xs); }

/* ── Mesa (compuesto) ───────────────────────────────────── */
.ui-mesa { aspect-ratio: 1 / 1; min-width: 0; padding: 4px;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
  border-radius: var(--radius-box); border: 1px solid var(--border-subtle); background: var(--surface-card);
  cursor: pointer; overflow: hidden; -webkit-tap-highlight-color: transparent; transition: transform var(--dur-press) var(--ease-out); }
.ui-mesa:active { transform: scale(var(--press-scale)); }
.ui-mesa__name { font-family: var(--font-display); font-size: var(--text-md); font-weight: var(--weight-bold);
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ui-mesa__meta { font-size: var(--text-xs); font-weight: var(--weight-semibold); opacity: .85;
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ui-mesa--free   { border-style: dashed; color: var(--state-free); }
.ui-mesa--busy   { border-color: var(--state-busy-border);   background: var(--state-busy-fill);   color: var(--state-busy-text); }
.ui-mesa--charge { border-color: var(--state-charge-border); background: var(--state-charge-fill); color: var(--state-charge-text); }

/* ── Tile de producto (compuesto) ───────────────────────── */
.ui-product { position: relative; min-height: 96px; min-width: 0; padding: 13px;
  display: flex; flex-direction: column; justify-content: space-between; text-align: left;
  border-radius: var(--radius-box); border: 1px solid var(--border-subtle); background: var(--surface-card);
  cursor: pointer; -webkit-tap-highlight-color: transparent; transition: transform var(--dur-press) var(--ease-out); }
.ui-product:active { transform: scale(var(--press-scale-sm)); }
.ui-product--in-order { border-color: var(--brand); background: var(--brand-tint); box-shadow: inset 0 0 0 1px var(--brand); }
.ui-product__name { font-size: var(--text-sm); font-weight: var(--weight-bold); line-height: 1.2; color: var(--text-strong);
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; }
.ui-product__price { font-size: var(--text-xs); font-weight: var(--weight-extra); color: var(--brand); margin-top: 8px; }
.ui-product__add { position: absolute; bottom: 11px; right: 11px; width: 30px; height: 30px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center; background: var(--surface-sunken); color: var(--brand); }
.ui-product--in-order .ui-product__add { background: var(--brand); color: var(--brand-content); }

/* ── Fila de venta (compuesto) ──────────────────────────── */
.ui-salerow { display: flex; align-items: center; gap: 12px; padding: 13px 12px;
  border-radius: var(--radius-box); background: var(--surface-card); border: 1px solid var(--border-subtle);
  cursor: pointer; -webkit-tap-highlight-color: transparent; transition: transform var(--dur-press) var(--ease-out); }
.ui-salerow:active { transform: scale(var(--press-scale-row)); }
.ui-salerow__stripe { width: 5px; align-self: stretch; border-radius: var(--radius-pill); background: var(--brand); }
.ui-salerow--charge .ui-salerow__stripe, .ui-salerow--cancelled .ui-salerow__stripe { background: var(--color-warning); }
.ui-salerow__num { width: 46px; height: 46px; flex: 0 0 auto; border-radius: 13px; background: var(--brand-tint); color: var(--brand);
  font-family: var(--font-display); font-feature-settings: "tnum" 1; font-weight: var(--weight-extra); font-size: var(--text-md);
  display: flex; align-items: center; justify-content: center; }
.ui-salerow__body { flex: 1 1 auto; min-width: 0; }
.ui-salerow__table { font-size: var(--text-base); font-weight: var(--weight-bold); color: var(--text-strong); }
.ui-salerow__meta { font-size: var(--text-xs); color: var(--text-muted); margin-top: 2px; display: flex; gap: 10px; }
.ui-salerow__right { text-align: right; display: flex; flex-direction: column; align-items: flex-end; gap: 4px; }
.ui-salerow__amount { font-family: var(--font-display); font-feature-settings: "tnum" 1; font-size: var(--text-md); font-weight: var(--weight-extra); color: var(--text-strong); }

/* ── Fila de acción / ajuste (compuesto) ────────────────── */
.ui-listaction { width: 100%; display: flex; align-items: center; gap: 14px; text-align: left; padding: 14px 16px;
  border-radius: var(--radius-box); background: var(--surface-card); border: 1px solid var(--border-subtle);
  cursor: pointer; -webkit-tap-highlight-color: transparent; transition: background var(--dur-fast) var(--ease-standard); }
.ui-listaction:active { background: var(--surface-sunken); }
.ui-listaction__icon { color: var(--brand); flex: 0 0 auto; }
.ui-listaction__body { flex: 1 1 auto; min-width: 0; }
.ui-listaction__title { display: block; font-size: var(--text-lg); font-weight: var(--weight-bold); color: var(--text-strong); }
.ui-listaction__desc { display: block; font-size: var(--text-sm); color: var(--text-muted); margin-top: 2px; }
.ui-listaction__chev { color: var(--text-faint); flex: 0 0 auto; }
.ui-listaction--danger { border-color: color-mix(in oklch, var(--color-error), transparent 70%); }
.ui-listaction--danger .ui-listaction__icon, .ui-listaction--danger .ui-listaction__title { color: var(--color-error); }

/* ── Action bar + total pill ────────────────────────────── */
.ui-actionbar { flex: 0 0 auto; display: flex; align-items: center; gap: 8px;
  padding: 12px 12px calc(12px + env(safe-area-inset-bottom)); background: var(--surface-card); border-top: 1px solid var(--border-subtle); }
.ui-totalpill { margin-left: auto; text-align: right; padding-right: 4px; }
.ui-totalpill__label { font-size: var(--text-2xs); text-transform: uppercase; letter-spacing: var(--tracking-label); color: var(--text-muted); font-weight: var(--weight-bold); }
.ui-totalpill__amount { font-family: var(--font-display); font-feature-settings: "tnum" 1; font-size: var(--text-lg); font-weight: var(--weight-extra); line-height: 1; color: var(--text-strong); }

/* ── Helper: número tabular ─────────────────────────────── */
.ui-num { font-family: var(--font-display); font-feature-settings: "tnum" 1; }

/* ════════════════════════════════════════════════════════════
   FESTIVAL ARENA — componentes específicos de producto
   Patrones de composición de coins.festival-arena.com: no son
   primitivas de propósito general (por eso viven en su propia
   sección), pero sí se reutilizan entre pantallas del producto.
   ════════════════════════════════════════════════════════════ */

/* ── Estructura de pantalla (shell → screen → page + dock) ──
   .shell ocupa el viewport; .screen es la columna flex de una
   pantalla con dock inferior; .page es la única zona con scroll,
   dejando AppBar/dock siempre fijos. */
.shell { height: 100vh; height: 100dvh; overflow-y: auto; overscroll-behavior-y: contain; }
@media (display-mode: standalone), (display-mode: fullscreen) { .shell { height: 100svh; } }
.screen { display: flex; flex-direction: column; height: 100%; min-height: 0; }
.page { flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior-y: contain; padding: var(--gutter); }

/* ── Iconos: tamaños (para el set inlineado como partials Go,
   ver sección Icon) — equivalente a size-N de Tailwind ──── */
.size-4 { width: 16px; height: 16px; flex: 0 0 auto; }
.size-5 { width: 20px; height: 20px; flex: 0 0 auto; }
.size-6 { width: 24px; height: 24px; flex: 0 0 auto; }
.size-8 { width: 32px; height: 32px; flex: 0 0 auto; }

/* ── Utilidades de estado ────────────────────────────────── */
.is-hidden { opacity: 0; pointer-events: none; }
.fade-out { transition: opacity var(--dur-fast) var(--ease-standard); }
.fade-out.is-hidden { opacity: 0; pointer-events: none; }
.gap-4 { display: flex; flex-direction: column; gap: var(--space-4); }

/* ── Escáner QR (cámara en vivo) ─────────────────────────── */
.scanner-slot { min-height: 256px; }
#scanner-singleton { display: flex; flex-direction: column; gap: var(--space-8); }
#scanner {
  width: 256px; height: 256px; margin: 0 auto; overflow: hidden; border-radius: var(--radius-box);
  -webkit-mask-image: -webkit-radial-gradient(white, black); transform: translateZ(0);
}
#scanner video { width: 100% !important; height: 100% !important; object-fit: cover; }
#qr-shaded-region { border-radius: var(--radius-box); }
.scanner-controls { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-6); margin: var(--space-6) 0; }
.scan-status { display: flex; align-items: center; gap: var(--space-6); padding: var(--space-6) var(--space-8);
  border-radius: var(--radius-box); background: var(--surface-sunken); border: 1px solid var(--border-subtle); }
.scan-status__icon { color: var(--color-success); flex: 0 0 auto; }
.scan-status__label { font-size: var(--text-2xs); font-weight: var(--weight-bold); letter-spacing: var(--tracking-label);
  text-transform: uppercase; color: var(--text-faint); margin-bottom: 2px; }
.scan-status__value { font-family: ui-monospace, monospace; font-size: var(--text-base); font-weight: var(--weight-bold);
  color: var(--text-strong); letter-spacing: .04em; overflow-wrap: anywhere; }

/* ── Login (pantalla pública sin dock) ───────────────────── */
.login-bg { display: flex; align-items: center; justify-content: center; min-height: 100%; padding: 24px 16px; background: var(--brand); }
.login-card { background: var(--surface-card); border-radius: var(--radius-box); padding: 32px 28px; width: 100%; max-width: 360px; box-shadow: var(--shadow-pop); }
.login-title { font-family: var(--font-display); font-size: var(--text-2xl); font-weight: var(--weight-extra); color: var(--text-strong);
  text-align: center; line-height: var(--leading-tight); margin: 0 0 28px; }
.login-fields { display: flex; flex-direction: column; gap: 16px; }
.login-alert { min-height: 20px; margin-bottom: 4px; }
.login-btn { margin-top: 24px; }

/* ── Onboarding (wizard de alta de organización) ─────────── */
.onboarding-card { max-width: 480px; }
.onboarding-steps { display: flex; gap: 8px; margin-bottom: 16px; }
.onboarding-intro { text-align: center; font-size: var(--text-sm); color: var(--text-muted); margin-bottom: 16px; }
.onboarding-fields-row { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.onboarding-actions { display: flex; justify-content: space-between; align-items: center; gap: 16px; margin-top: 8px; }
.onboarding-actions__submit { flex: 1; }
.onboarding-back-icon { display: inline-flex; transform: rotate(90deg); }
.onboarding-domain-preview { display: flex; align-items: center; gap: 6px; }
.onboarding-domain-suffix { color: var(--text-faint); font-weight: var(--weight-bold); white-space: nowrap; }
.onboarding-textarea { min-height: 96px; }

/* ── Enlace de vuelta (páginas públicas sin dock) ────────── */
.back-link { display: inline-block; margin-bottom: var(--space-6); color: var(--text-muted); font-size: var(--text-sm); font-weight: var(--weight-semibold); text-decoration: none; }
.back-link:active { opacity: .7; }

/* ── Landing (página principal) + página de error ────────── */
.landing-bg { min-height: 100%; display: flex; flex-direction: column; background: var(--brand); }
.landing-main { flex: 1 1 auto; display: flex; align-items: center; justify-content: center; padding: 24px 16px; }
.landing-card { background: var(--surface-card); border-radius: var(--radius-box); padding: 40px 28px; width: 100%; max-width: 380px; box-shadow: var(--shadow-pop); text-align: center; }
.landing-title { font-family: var(--font-display); font-size: var(--text-3xl); font-weight: var(--weight-extra); color: var(--text-strong); line-height: var(--leading-tight); margin: 0; }
.landing-title__year { color: var(--brand); }
.landing-tagline { margin: 12px 0 32px; color: var(--text-muted); font-size: var(--text-sm); }
.landing-actions { display: flex; flex-direction: column; gap: 14px; }
.landing-footer { flex: 0 0 auto; padding: 16px; text-align: center; color: color-mix(in oklch, var(--brand-content), transparent 15%); font-size: var(--text-xs); }
.landing-footer p { margin: 2px 0; }
.error-code { font-family: var(--font-display); font-size: 64px; font-weight: var(--weight-extra); line-height: 1; color: var(--brand); margin: 0 0 4px; }

/* ── Barra superior de administración (volver) + cuadrícula
   de secciones de /app/management ───────────────────────── */
.mgmt-topbar { display: flex; align-items: center; gap: var(--space-6); margin-bottom: var(--space-8); }
.mgmt-topbar__back {
  display: inline-flex; align-items: center; justify-content: center;
  width: var(--icon-btn); height: var(--icon-btn); flex: 0 0 auto;
  border-radius: var(--radius-control); color: var(--text-strong); text-decoration: none;
  -webkit-tap-highlight-color: transparent; transition: background var(--dur-fast) var(--ease-standard);
}
.mgmt-topbar__back:active { background: var(--surface-sunken); }
.mgmt-topbar__title { font-family: var(--font-display); font-size: var(--text-xl); font-weight: var(--weight-bold); color: var(--text-strong); }
.mgmt-grid { margin-top: var(--space-4); display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-6); }
.mgmt-tile {
  display: flex; align-items: center; justify-content: center; text-align: center;
  min-height: 100px; padding: var(--space-6);
  background: var(--surface-card); border: 1px solid var(--border-subtle); border-radius: var(--radius-box);
  font-family: var(--font-sans); font-size: var(--text-base); font-weight: var(--weight-bold); color: var(--text-strong);
  text-decoration: none; -webkit-tap-highlight-color: transparent;
  transition: transform var(--dur-press) var(--ease-out), background var(--dur-fast);
}
.mgmt-tile:active { transform: scale(var(--press-scale-row)); background: var(--surface-sunken); }
.mgmt-tile--wide { grid-column: 1 / -1; }

/* ── Fila de permiso (etiqueta + interruptor u acción) ───── */
.perm-row { display: flex; align-items: center; gap: var(--space-3); }
.perm-row__label { flex: 1 1 auto; }
.perm-cat-list { display: flex; flex-direction: column; gap: var(--space-3); }
.perm-cat-row { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-4); background: var(--surface-sunken); border-radius: var(--radius-control); }

/* ── Cuadrícula de catálogo (Vender) ─────────────────────── */
.product-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--tile-gap); margin-bottom: var(--space-12); }

/* ── Saldo disponible de la tarjeta escaneada (Vender) ───── */
.sell-balance { display: flex; align-items: baseline; justify-content: space-between; margin-top: var(--space-4); }
.sell-balance__label { font-size: var(--text-sm); color: var(--text-body); }
.sell-balance__amount { font-size: var(--text-lg); font-weight: var(--weight-bold); color: var(--brand); }
.sell-balance--warning .sell-balance__label { color: var(--color-warning); font-weight: var(--weight-semibold); }
.sell-total { display: flex; align-items: baseline; justify-content: space-between; margin: var(--space-8) 0; }
.sell-total__label { font-size: var(--text-base); font-weight: var(--weight-bold); color: var(--text-body); }
.sell-total__amount { font-size: var(--text-xl); font-weight: var(--weight-extra); color: var(--text-strong); }

/* ── Importe grande (saldo, teclado de recarga) ──────────── */
.amount-wrap { width: 100%; margin-top: var(--space-8); display: flex; flex-direction: column; align-items: center; transition: transform var(--dur-normal) var(--ease-out); }
.amount-wrap--zoom { transform: scale(1.08); }
.amount-display { cursor: pointer; user-select: none; display: block; text-align: center; }
.amount-display--block { margin: var(--space-8) 0 var(--space-6); cursor: default; }
.amount-display.is-faint .amount-display__value, .amount-display.is-faint .amount-display__symbol { color: var(--text-faint); }
.amount-display__value { font-family: var(--font-display); font-size: 52px; font-weight: var(--weight-extra); color: var(--text-strong); letter-spacing: var(--tracking-display); }
.amount-display__symbol { font-family: var(--font-display); font-size: 40px; font-weight: var(--weight-extra); color: var(--text-strong); margin-left: 4px; }
.amount-input { position: absolute; width: 0; height: 0; opacity: 0; border: 0; padding: 0; margin: 0; }

/* ── Teclado numérico en pantalla ─────────────────────────── */
.keypad-hint { display: flex; align-items: center; justify-content: center; gap: var(--space-4);
  margin-top: var(--space-12); font-size: var(--text-xs); font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-label); text-transform: uppercase; color: var(--text-faint);
  transition: opacity var(--dur-fast) var(--ease-standard); }
.keypad { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-4); }
.key { min-height: 56px; display: flex; align-items: center; justify-content: center;
  border-radius: var(--radius-box); border: 1px solid var(--border-subtle); background: var(--surface-card);
  color: var(--text-strong); font-size: var(--text-xl); font-weight: var(--weight-bold);
  cursor: pointer; -webkit-tap-highlight-color: transparent;
  transition: transform var(--dur-press) var(--ease-out), background var(--dur-fast) var(--ease-standard); }
.key:active { transform: scale(var(--press-scale-sm)); background: var(--surface-raised); }
.key--action { color: var(--text-muted); font-size: var(--text-2xl); }
.topup-back { display: inline-flex; align-items: center; gap: 6px; background: none; border: 0;
  color: var(--text-muted); font-size: var(--text-sm); font-weight: var(--weight-bold);
  cursor: pointer; padding: 4px 0; margin-bottom: var(--space-4); }
.topup-back span[aria-hidden] { font-size: var(--text-lg); line-height: 1; }

/* ── Accesos rápidos de importe (chips de importe fijo) ──── */
.preset-grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-6); }
.preset { min-height: 90px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  border-radius: var(--radius-box); border: 1px solid var(--border-subtle); background: var(--surface-card);
  cursor: pointer; -webkit-tap-highlight-color: transparent;
  transition: transform var(--dur-press) var(--ease-out), background var(--dur-fast) var(--ease-standard), border-color var(--dur-fast) var(--ease-standard); }
.preset:active { transform: scale(var(--press-scale-sm)); }
.preset--on { border: 2px solid var(--brand); background: var(--brand-tint); }
.preset__num { font-size: var(--text-3xl); font-weight: var(--weight-extra); color: var(--text-strong); line-height: 1; }
.preset--on .preset__num { color: var(--brand); }
.preset__unit { font-size: var(--text-sm); font-weight: var(--weight-semibold); color: var(--text-muted); }
.preset--on .preset__unit { color: var(--brand); }
.preset__promo { font-size: var(--text-xs); font-weight: var(--weight-semibold); color: var(--brand); margin-top: 2px; }
.otro-btn { margin-top: var(--space-6); }

/* ── Selector de método de pago ──────────────────────────── */
.payment-methods { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-6); margin-top: var(--space-16); }

/* ── Saldo real vs. promocional ──────────────────────────── */
.balance-split { display: flex; justify-content: center; gap: var(--space-4); margin-top: var(--space-2); font-size: var(--text-sm); color: var(--text-muted); }
.balance-split__item { display: inline-flex; gap: 6px; align-items: baseline; font-weight: var(--weight-semibold); }
.balance-split__item--promo { color: var(--brand); }

/* ── Perfil: resumen + historial ──────────────────────────── */
.profile-user { display: flex; align-items: center; gap: var(--space-6); margin-bottom: var(--space-12); }
.profile-user__icon { width: 44px; height: 44px; border-radius: 50%; background: var(--brand-tint); color: var(--brand);
  display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto; }
.profile-user__name { font-family: var(--font-display); font-size: var(--text-lg); font-weight: var(--weight-extra); color: var(--text-strong); }
.profile-stat { margin-bottom: var(--space-12); }
.profile-stat__head { display: flex; align-items: baseline; justify-content: space-between; }
.profile-stat__count { font-family: var(--font-display); font-size: var(--text-3xl); font-weight: var(--weight-extra); color: var(--text-strong); line-height: 1; }
.profile-stat__total { font-family: var(--font-display); font-size: var(--text-lg); font-weight: var(--weight-extra); color: var(--brand); }
.profile-stat__label { font-size: var(--text-sm); color: var(--text-muted); }
.profile-stat__breakdown { margin-top: var(--space-6); display: flex; flex-direction: column; gap: 4px; }
.profile-stat__row { display: flex; justify-content: space-between; align-items: center; font-size: var(--text-sm); color: var(--text-body); }
.profile-stat__row .ui-num { color: var(--text-strong); font-weight: var(--weight-bold); }
.profile-stat__empty { font-size: var(--text-sm); color: var(--text-faint); }

/* ── Historial de transacciones (recargas / ventas) ──────── */
.txn-list { display: flex; flex-direction: column; gap: var(--space-6); margin-bottom: var(--space-8); }
.txn { padding: 12px 14px; }
.txn__head { display: flex; align-items: center; gap: 8px; }
.txn__code { font-size: var(--text-sm); font-weight: var(--weight-bold); color: var(--text-strong); letter-spacing: .04em; }
.txn__amount { margin-left: auto; font-family: var(--font-display); font-weight: var(--weight-extra); font-size: var(--text-md); color: var(--text-strong); }
.txn--refund .txn__amount { color: var(--color-warning); }
.txn__promo { font-size: var(--text-sm); font-weight: var(--weight-semibold); color: var(--brand); }
.txn__products { margin-top: 8px; font-size: var(--text-sm); color: var(--text-body); }
.txn__meta { margin-top: 8px; display: flex; align-items: center; justify-content: space-between; gap: 10px; font-size: var(--text-xs); color: var(--text-muted); }
.txn__balance { font-weight: var(--weight-bold); color: var(--text-body); }
.txn-empty { padding: var(--space-8); text-align: center; font-size: var(--text-sm); color: var(--text-faint); }

/* ── Tarjeta de resultado (venta/recarga completada o anulada) ── */
.result-card { padding: 22px 18px; box-shadow: var(--shadow-soft); margin-top: var(--space-8); }
.result-card__title { font-family: var(--font-display); font-size: var(--text-2xl); font-weight: var(--weight-extra); color: var(--text-strong); text-align: center; }
.result-card__subtitle { font-size: var(--text-sm); color: var(--text-muted); text-align: center; margin-top: 6px; }
.result-card__rows { background: var(--surface-sunken); border-radius: var(--radius-box); padding: 0 var(--space-8); margin: var(--space-16) 0; }
.result-card__row { display: flex; align-items: center; justify-content: space-between; padding: var(--space-8) 0; border-bottom: 1px solid var(--border-subtle); }
.result-card__row:last-child { border-bottom: 0; }
.result-card__row-label { font-size: var(--text-lg); color: var(--text-body); }
.result-card__row-value { font-family: var(--font-display); font-feature-settings: "tnum" 1; font-size: var(--text-lg); font-weight: var(--weight-extra); color: var(--text-strong); }
.result-card__actions { display: flex; flex-direction: column; gap: var(--space-6); margin-top: var(--space-8); }

/* ════════════════════════════════════════════════════════════
   ERP · TABLAS DE DATOS
   Componentes de back-office (no TPV): tablas densas, filtrado,
   selección y edición inline/modal. Comparten tokens del sistema
   (superficies, bordes, tipografía) para heredar los 12 temas.
   ════════════════════════════════════════════════════════════ */

/* ── Contenedor: borde redondeado + scroll horizontal ────── */
.ui-table-wrap {
  border: 1px solid var(--border-subtle); border-radius: var(--radius-box);
  background: var(--surface-card); overflow: hidden;
}
/* Variante con scroll horizontal (muchas columnas). El borde exterior
   lo pone .ui-table-wrap; aquí sólo desbordamos en X. */
.ui-table-wrap--scroll { overflow-x: auto; overflow-y: hidden; }
/* Variante con cabecera fija: fija una altura y deja el cuerpo hacer scroll. */
.ui-table-wrap--sticky { overflow-y: auto; max-height: var(--table-max-h, 340px); }

/* ── Tabla ───────────────────────────────────────────────── */
.ui-table { width: 100%; border-collapse: collapse; font-size: var(--text-sm); color: var(--text-body); }
.ui-table th, .ui-table td { text-align: left; padding: 12px 14px; white-space: nowrap; }

/* Cabecera: etiqueta MAYÚSCULAS atenuada sobre superficie hundida. */
.ui-table thead th {
  font-size: var(--text-xs); font-weight: var(--weight-bold); letter-spacing: var(--tracking-label);
  text-transform: uppercase; color: var(--text-faint);
  background: var(--surface-sunken); border-bottom: 1px solid var(--border-subtle);
  vertical-align: middle;
}
/* Cabecera fija: sticky dentro de .ui-table-wrap--sticky. */
.ui-table-wrap--sticky .ui-table thead th { position: sticky; top: 0; z-index: 2; }

/* Cuerpo: separador hairline entre filas; la última sin borde. */
.ui-table tbody td { border-bottom: 1px solid var(--border-subtle); vertical-align: middle; color: var(--text-body); }
.ui-table tbody tr:last-child td { border-bottom: 0; }
.ui-table tbody td .ui-num, .ui-table .is-numeric { font-family: var(--font-display); font-feature-settings: "tnum" 1; }

/* Alineación numérica (precios, stock, %). */
.ui-table th.is-numeric, .ui-table td.is-numeric { text-align: right; }
.ui-table td.is-strong { color: var(--text-strong); font-weight: var(--weight-semibold); }
.ui-table td.is-muted  { color: var(--text-muted); }

/* Variantes de densidad y realce. */
.ui-table--compact th, .ui-table--compact td { padding: 7px 12px; }
.ui-table--zebra tbody tr:nth-child(even) td { background: color-mix(in oklch, var(--surface-sunken), transparent 45%); }
@media (hover: hover) {
  .ui-table--hover tbody tr:hover td { background: var(--brand-tint); }
}
.ui-table--fixed { table-layout: fixed; }
.ui-table--fixed td { white-space: normal; }

/* Fila seleccionada (checkbox) — tinte de marca. */
.ui-table tbody tr.is-selected td { background: var(--brand-tint); }

/* Celda de checkbox y de acciones. */
.ui-table__check { width: 44px; text-align: center; padding-right: 0; }
.ui-table__check input { width: 18px; height: 18px; accent-color: var(--brand); cursor: pointer; vertical-align: middle; }
.ui-table__actions { text-align: right; width: 1%; }
.ui-table__actions .ui-btn { vertical-align: middle; }

/* Columna de ancho máximo fijo — para valores potencialmente largos
   (precios por formato, indicadores…) que deben truncarse en vez de
   estirar la tabla; combínala con .ui-cell-truncate en el contenido. */
.ui-table__col-fixed { max-width: 200px; }

/* Columna fija a la izquierda (scroll horizontal con 1ª col pegada). */
.ui-table .is-sticky-col {
  position: sticky; left: 0; z-index: 1; background: var(--surface-card);
  box-shadow: 1px 0 0 var(--border-subtle);
}
.ui-table thead th.is-sticky-col { z-index: 3; background: var(--surface-sunken); }
.ui-table tbody tr.is-selected td.is-sticky-col { background: color-mix(in oklch, var(--brand-tint), var(--surface-card) 30%); }

/* Cabecera ordenable: botón que ocupa la celda + chevron de dirección. */
.ui-table__sort {
  display: inline-flex; align-items: center; gap: 5px; border: 0; background: transparent; padding: 0;
  font: inherit; color: inherit; text-transform: inherit; letter-spacing: inherit; cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.ui-table__sort:hover { color: var(--text-muted); }
.ui-table th.is-numeric .ui-table__sort { flex-direction: row-reverse; }
.ui-table__sort-ico { width: 14px; height: 14px; opacity: 0; transition: opacity var(--dur-fast); }
.ui-table th[aria-sort] .ui-table__sort { color: var(--brand); }
.ui-table th[aria-sort] .ui-table__sort-ico { opacity: 1; }

/* Input de edición inline (misma altura visual que la celda). */
.ui-table__cell-input {
  width: 100%; min-width: 80px; height: 38px; padding: 0 10px;
  background: var(--surface-card); color: var(--text-strong);
  border: 1px solid var(--border-focus); border-radius: var(--radius-field);
  font-family: var(--font-sans); font-size: var(--text-sm); outline: none;
  box-shadow: 0 0 0 3.5px var(--focus-ring);
}
.ui-table__cell-input.is-numeric { text-align: right; font-family: var(--font-display); font-feature-settings: "tnum" 1; }
.ui-table tr.is-editing td { background: var(--brand-tint); }

/* Celda vacía a todo el ancho (sin resultados). */
.ui-table__empty { text-align: center; color: var(--text-faint); padding: 34px 14px; white-space: normal; }

/* Pie de tabla (recuento / resumen). */
.ui-table tfoot td { border-top: 1px solid var(--border-subtle); background: var(--surface-sunken);
  font-size: var(--text-xs); color: var(--text-muted); font-weight: var(--weight-semibold); }

/* ── Select nativo estilizado (desplegable de filtro / formulario) ── */
.ui-select { position: relative; display: inline-flex; align-items: center; }
.ui-select__field {
  appearance: none; -webkit-appearance: none;
  min-height: 40px; padding: 0 38px 0 12px;
  background: var(--surface-sunken); color: var(--text-strong);
  border: 1px solid var(--border-subtle); border-radius: var(--radius-field);
  font-family: var(--font-sans); font-size: var(--text-sm); font-weight: var(--weight-semibold);
  cursor: pointer; width: 100%;
}
.ui-select__field:focus { background: var(--surface-card); border-color: var(--border-focus); box-shadow: 0 0 0 3.5px var(--focus-ring); outline: none; }
.ui-select__chevron { position: absolute; right: 12px; top: 50%; transform: translateY(-50%); color: var(--text-faint); pointer-events: none; display: inline-flex; }
.ui-select--block { display: flex; }
.ui-select--lg .ui-select__field { min-height: var(--touch-input); font-size: var(--text-base); }

/* ── Fila de precio por formato (select + importe + quitar) ─
   Patrón para formularios con una fila repetible que combina un
   .ui-select (2/3) y un .ui-field__input (1/3) a la misma altura
   — igualarla requiere .ui-select--lg en el select de la fila. */
.ui-price-row { display: flex; align-items: center; gap: var(--space-4); margin-bottom: var(--space-4); }
.ui-price-row .ui-select { flex: 2 1 0; min-width: 0; }
.ui-price-row .ui-field__input { flex: 1 1 0; min-width: 0; }

/* ── Grid de toggles (tri_switch/switch + etiqueta) ───────
   2 columnas en móvil/tablet, 3 en escritorio — genérico para
   listas cortas de propiedades tri-estado (alérgenos,
   disponibilidad…) en el ancho de un modal. */
.ui-toggle-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--space-4) var(--space-5); }
@media (min-width: 768px) {
  .ui-toggle-grid { grid-template-columns: repeat(3, 1fr); }
}
.ui-toggle-item { display: flex; align-items: center; gap: var(--space-4); min-width: 0; }
.ui-toggle-item__label { font-size: var(--text-sm); color: var(--text-strong); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ── Toolbar de tabla (búsqueda + filtros + acciones) ─────── */
.ui-toolbar { display: flex; align-items: center; gap: var(--space-5); flex-wrap: wrap; margin-bottom: var(--space-6); }
.ui-toolbar__search { flex: 1 1 220px; min-width: 180px; }
.ui-toolbar__filters { display: flex; align-items: center; gap: var(--space-5); flex-wrap: wrap; }
.ui-toolbar__actions { margin-left: auto; display: flex; align-items: center; gap: var(--space-4); }
.ui-toolbar__label { font-size: var(--text-xs); font-weight: var(--weight-bold); letter-spacing: var(--tracking-label);
  text-transform: uppercase; color: var(--text-faint); margin-right: 2px; }

/* ── Barra de selección masiva (aparece con filas marcadas) ── */
.ui-bulkbar {
  display: flex; align-items: center; gap: var(--space-6); flex-wrap: wrap;
  padding: 10px 14px; margin-bottom: var(--space-6);
  background: var(--brand-tint); border: 1px solid var(--brand-tint-strong); border-radius: var(--radius-control);
}
.ui-bulkbar__count { font-size: var(--text-sm); font-weight: var(--weight-bold); color: var(--brand); }
.ui-bulkbar__actions { margin-left: auto; display: flex; align-items: center; gap: var(--space-4); }

/* ════════════════════════════════════════════════════════════
   APP SHELL RESPONSIVO
   Un mismo layout que se adapta al ANCHO DE SU PROPIO CONTENEDOR
   (container query, no al viewport): por debajo de 640px muestra
   AppBar de marca + TabBar inferior (móvil y tablet pequeña); a
   partir de 640px muestra Sidebar lateral + barra superior, con la
   sidebar colapsable a solo iconos. Como usa container queries se
   comporta igual ocupando el viewport (height:100dvh en <body>) que
   embebido en una caja menor (la vista previa del showcase).
   Distinto de .shell (scaffold sólo-móvil de Festival Arena).
   ════════════════════════════════════════════════════════════ */
.ui-shell {
  container-type: inline-size;
  container-name: shell;
  display: flex; flex-direction: column;
  height: 100%; min-height: 0;
  background: var(--surface-app); overflow: hidden;
}
/* Cuando .ui-shell es la raíz de la página (no embebido en una caja
   ajena, como la vista previa del showcase) necesita fijar su propia
   altura de viewport en vez de heredar un 100% sin ancestro con altura. */
.ui-shell--fill {
  height: 100vh; height: 100dvh;
}

/* Barra superior (solo escritorio) */
.ui-shell__topbar {
  display: none; flex: 0 0 auto; align-items: center; gap: var(--space-6);
  padding: 10px 16px; min-height: 60px;
  background: var(--surface-card); border-bottom: 1px solid var(--border-subtle);
}
.ui-shell__toggle { flex: 0 0 auto; }
.ui-shell__title { flex: 1 1 auto; min-width: 0; font-family: var(--font-display); font-size: var(--text-lg);
  font-weight: var(--weight-bold); color: var(--text-strong);
  display: flex; justify-content: center; }
.ui-shell__title--text { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ui-shell__topbar-actions { flex: 0 0 auto; display: flex; align-items: center; gap: var(--space-5); }

[x-cloak] { display: none !important; }

/* ── Selector de espacio de trabajo (topbar, solo escritorio) ── */
.ui-workspace-switch { position: relative; display: inline-block; }
.ui-workspace-switch__toggle {
  display: inline-flex; align-items: center; gap: 6px; max-width: 100%;
  padding: 6px 10px; border: 0; border-radius: var(--radius-field); background: transparent;
  font-family: var(--font-display); font-size: var(--text-base); font-weight: var(--weight-bold); color: var(--text-strong);
  cursor: pointer; -webkit-tap-highlight-color: transparent; transition: background var(--dur-fast) var(--ease-standard);
}
.ui-workspace-switch__toggle:hover { background: var(--surface-sunken); }
.ui-workspace-switch__label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ui-workspace-switch__chevron { flex: 0 0 auto; transition: transform var(--dur-fast) var(--ease-standard); }
.ui-workspace-switch__chevron.is-open { transform: rotate(180deg); }
.ui-workspace-switch__menu {
  position: absolute; z-index: 20; top: calc(100% + 6px); left: 0;
  min-width: 200px; max-height: 260px; overflow-y: auto; padding: var(--space-3);
  background: var(--surface-card); border: 1px solid var(--border-subtle); border-radius: var(--radius-box);
  box-shadow: var(--shadow-pop); display: flex; flex-direction: column; gap: 2px; text-align: left;
}
.ui-workspace-switch__opt { display: flex; align-items: center; min-height: 36px; padding: 0 var(--space-4); border-radius: var(--radius-field);
  font-size: var(--text-sm); font-weight: var(--weight-semibold); color: var(--text-body);
  text-decoration: none; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.ui-workspace-switch__opt:hover { background: var(--surface-sunken); }
.ui-workspace-switch__opt[aria-current="page"] { background: var(--brand-tint); color: var(--brand); }

/* Variante móvil: vive en el appbar de marca, el menú cuelga a la derecha
   (el toggle está pegado al borde, alinearlo a la izquierda lo cortaría). */
.ui-workspace-switch--mobile .ui-workspace-switch__menu { left: auto; right: 0; }

/* Cuerpo: sidebar + columna de contenido */
.ui-shell__body { flex: 1 1 auto; min-height: 0; display: flex; }

/* Sidebar (solo escritorio) */
.ui-shell__sidebar {
  display: none; flex-direction: column;
  min-width: 0; min-height: 0; overflow: hidden;
  background: var(--surface-card); border-right: 1px solid var(--border-subtle);
}
.ui-shell__brand { display: flex; align-items: center; gap: 10px; padding: 0 16px; min-height: 60px; flex: 0 0 auto;
  border-bottom: 1px solid var(--border-subtle); transition: padding var(--dur-normal) var(--ease-standard); }
.ui-shell__brand-mark { width: 30px; height: 30px; flex: 0 0 auto; border-radius: 8px;
  background: linear-gradient(150deg, var(--color-primary), var(--brand-press));
  color: var(--color-primary-content); display: flex; align-items: center; justify-content: center; }
.ui-shell__brand-name { font-family: var(--font-display); font-size: var(--text-base); font-weight: var(--weight-extra);
  color: var(--text-strong); white-space: nowrap; letter-spacing: -0.01em;
  transition: opacity var(--dur-fast) var(--ease-standard); }
.ui-shell__nav { flex: 1 1 auto; overflow-y: auto; padding: 10px; display: flex; flex-direction: column; gap: 2px; }
.ui-shell__nav--footer { flex: 0 0 auto; border-top: 1px solid var(--border-subtle); }
.ui-shell__navitem {
  display: flex; align-items: center; gap: 12px; width: 100%;
  padding: 10px 12px; border: 0; border-radius: var(--radius-field); background: transparent;
  color: var(--text-body); font-family: var(--font-sans); font-size: var(--text-base); font-weight: var(--weight-semibold);
  cursor: pointer; white-space: nowrap; text-align: left; text-decoration: none; -webkit-tap-highlight-color: transparent;
  transition: background var(--dur-fast), color var(--dur-fast), padding var(--dur-normal) var(--ease-standard);
}
.ui-shell__navitem:hover { background: var(--surface-sunken); }
.ui-shell__navitem[aria-current="page"] { background: var(--brand-tint); color: var(--brand); }
.ui-shell__navitem .ui-icon { flex: 0 0 auto; }
.ui-shell__navlabel { flex: 1 1 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  transition: opacity var(--dur-fast) var(--ease-standard); }

/* Columna de contenido.
   min-height:0 es LO QUE HABILITA EL SCROLL en escritorio: como grid item
   (body pasa a grid ≥640px) su min-height por defecto es 'auto', así que no
   se encoge por debajo de su contenido y .ui-shell__main nunca acota su
   overflow — el contenido largo quedaba atrapado bajo el clip de .ui-shell.
   Con min-height:0 la columna se ciñe a la altura del track y .ui-shell__main
   (overflow-y:auto) recupera su scroll propio. Igual efecto como flex item
   en móvil. */
.ui-shell__content { flex: 1 1 auto; min-width: 0; min-height: 0; display: flex; flex-direction: column; }

/* AppBar de marca (solo móvil) */
.ui-shell__appbar {
  display: flex; flex: 0 0 auto; align-items: center; gap: 10px;
  padding: 12px 16px; min-height: 56px;
  background: var(--color-primary);
  color: var(--color-primary-content);
}
.ui-shell__appbar-title { flex: 1 1 auto; min-width: 0; font-family: var(--font-display); font-size: var(--text-lg);
  font-weight: var(--weight-bold); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* Zona principal — única con scroll propio */
.ui-shell__main { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: var(--gutter); }

/* Dock inferior (TabBar; solo móvil) */
.ui-shell__dock { display: block; flex: 0 0 auto; }

/* Sidebar colapsada a solo iconos (escritorio). El ancho transiciona
   (var(--dur-normal)); las etiquetas NO se ocultan con display:none —se
   desvanecen (opacity) y la propia sidebar (overflow:hidden) las recorta al
   estrecharse, así el colapso/expansión es continuo en vez de dar un salto.
   El padding se desliza para centrar el icono en el riel de 72px. */
.ui-shell.is-collapsed .ui-shell__navlabel,
.ui-shell.is-collapsed .ui-shell__brand-name { opacity: 0; }
.ui-shell.is-collapsed .ui-shell__navitem { padding-inline: 16px 0; }
.ui-shell.is-collapsed .ui-shell__brand { padding-inline: 21px 0; }

/* ── Corte: contenedor ≥ 640px = tablet grande / escritorio ── */
@container shell (min-width: 640px) {
  .ui-shell__topbar  { display: flex; }
  .ui-shell__sidebar { display: flex; }
  .ui-shell__appbar  { display: none; }
  .ui-shell__dock    { display: none; }
  /* El ancho del sidebar es una COLUMNA de grid del body: animar
     grid-template-columns sí interpola de forma fiable (a diferencia de
     width/flex-basis en un flex item, que dan un salto). El sidebar es la
     1ª columna; al colapsar pasa de 232px a 72px con transición suave. */
  .ui-shell__body { display: grid; grid-template-columns: 232px 1fr;
    transition: grid-template-columns var(--dur-normal) var(--ease-standard); }
  .ui-shell.is-collapsed .ui-shell__body { grid-template-columns: 72px 1fr; }
}

/* ════════════════════════════════════════════════════════════
   VISUALIZACIÓN · LAYOUT
   Wrappers de organización (flex/grid + gap) — prefijo .u- para
   distinguirlos de los componentes .ui-*. Sustituyen los
   style="display:flex;gap:...;align-items:..." repetidos por
   toda la app: ningún fragmento debe generar ese layout inline,
   siempre vía estas clases. Valores de gap = escala --space-*
   existente (tokens/spacing.css) — nunca un px suelto.
   ════════════════════════════════════════════════════════════ */

/* ── Fila / columna flex ──────────────────────────────────── */
.u-row { display: flex; align-items: center; }
.u-row--top      { align-items: flex-start; }
.u-row--stretch  { align-items: stretch; }
.u-row--baseline { align-items: baseline; }
.u-col { display: flex; flex-direction: column; }
.u-col--center { align-items: center; }

/* ── Distribución en el eje principal ─────────────────────── */
.u-justify-between { justify-content: space-between; }
.u-justify-center   { justify-content: center; }
.u-justify-end       { justify-content: flex-end; }

/* ── Envoltura ─────────────────────────────────────────────── */
.u-wrap { flex-wrap: wrap; }

/* ── Grid ──────────────────────────────────────────────────── */
.u-grid { display: grid; }
.u-grid-cols-2 { grid-template-columns: repeat(2, 1fr); }
.u-grid-cols-3 { grid-template-columns: repeat(3, 1fr); }
.u-grid-cols-4 { grid-template-columns: repeat(4, 1fr); }

/* ── Gap (misma escala que --space-*, tokens/spacing.css) ──── */
.u-gap-0  { gap: var(--space-0); }
.u-gap-2  { gap: var(--space-2); }
.u-gap-3  { gap: var(--space-3); }
.u-gap-4  { gap: var(--space-4); }
.u-gap-5  { gap: var(--space-5); }
.u-gap-6  { gap: var(--space-6); }
.u-gap-7  { gap: var(--space-7); }
.u-gap-8  { gap: var(--space-8); }
.u-gap-10 { gap: var(--space-10); }
.u-gap-12 { gap: var(--space-12); }
.u-gap-16 { gap: var(--space-16); }
.u-gap-20 { gap: var(--space-20); }

/* ── Ancho ─────────────────────────────────────────────────── */
.u-w-full { width: 100%; }
.u-flex-1 { flex: 1 1 auto; }

/* ── Tamaño cuadrado — consume los tokens táctiles ya definidos
   en tokens/spacing.css en vez de repetir su valor en px suelto
   (avatares, botones de icono, tiles pequeños). ──────────────── */
.u-size-icon-btn    { width: var(--icon-btn);    height: var(--icon-btn); }
.u-size-touch-min   { width: var(--touch-min);   height: var(--touch-min); }
.u-size-touch-btn   { width: var(--touch-btn);   height: var(--touch-btn); }
.u-size-touch-input { width: var(--touch-input); height: var(--touch-input); }
