/* ============================================================
   SHIDA · SHIneray Dealer Assistance — design system
   Light Control-Tower · Shineray red/charcoal · brand-native
   Ported from the demo (8. Demo/shineraydemo/assets/css/app.css)
   ============================================================ */

:root{
  /* Acento de la barra izquierda del tooltip de LionBytes.UI. */
  --tip-accent:var(--red);
  /* brand */
  --red:#EF3340; --red-600:#D4212E; --red-050:#FDECEC;
  --char:#2D2926; --char-900:#1E1B18; --char-700:#3A3532;

  /* ink */
  --ink:#221F1D; --ink-2:#6E6863; --ink-3:#9A938C;

  /* surfaces */
  --page:#F1F1EF; --card:#FFFFFF; --card-2:#FAFAF9;
  --line:rgba(45,41,38,.11); --line-2:rgba(45,41,38,.06);

  /* status */
  --occard-bg:#FCF8F1; --occard-line:#EFE6D8;   /* tarjeta de parcialidad: marfil cálido, ni blanco ni gris */
  --ok:#2E9E6B; --ok-bg:#E7F4EE;
  --warn:#B9791A; --warn-bg:#FAF0DC;
  --bad:#C8353F; --bad-bg:#FBEAEB;
  --info:#3A6EA5; --info-bg:#E9F0F7;
  /* Vistas de alcance (módulos Borrador, 2026-09-24): un azul VIVO, a propósito lejos del --info apagado y del
     rojo de la marca, para que ninguna se confunda con un módulo que ya opera. */
  --draft:#1F6FEB; --draft-bg:#EAF2FE; --draft-line:rgba(31,111,235,.45); --uc:#C8102E; --uc-sign:#FFC72C;
  --neutral:#6E6863; --neutral-bg:#EFEDEA;

  /* barra superior (translúcida sobre el fondo de la página) */
  --topbar:rgba(241,241,239,.82);

  /* sidebar — CLARO en tema claro, carbón en tema oscuro (2026-09-14, a petición del cliente).
     El único bloque que conserva el carbón en los dos temas es el rectángulo de marca de la esquina
     superior izquierda (.sb-brand): ahí vive el logotipo y ahí se queda el color oscuro.
     Todo matiz del menú sale de un token —hover, activo, acento, barra de desplazamiento— porque un
     rgba(255,255,255,…) escrito a mano desaparece en cuanto el fondo deja de ser oscuro. */
  --sb:#FFFFFF; --sb-2:#F5F4F2; --sb-line:rgba(45,41,38,.10);
  --sb-ink:#221F1D; --sb-ink-2:#5E5852; --sb-ink-3:#9A938C;
  --sb-hover:rgba(45,41,38,.05); --sb-active:rgba(239,51,64,.09);
  --sb-active-ink:var(--red-600); --sb-accent:var(--red);
  --sb-scroll:rgba(45,41,38,.16);

  --radius:14px; --radius-sm:10px; --radius-pill:999px;
  --shadow:0 1px 2px rgba(30,27,24,.04), 0 4px 18px rgba(30,27,24,.05);
  --shadow-lg:0 18px 50px rgba(30,27,24,.14);
  --ring:0 0 0 3px rgba(239,51,64,.28);

  --font:'Inter',system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;
  --font-display:'Sora','Inter',system-ui,sans-serif;
  --font-cjk:'PingFang SC','Hiragino Sans GB','Microsoft YaHei','Noto Sans SC',sans-serif;
  --font-mono:ui-monospace,'SF Mono','SFMono-Regular',Menlo,Consolas,monospace;
}

/* dark theme override (SHIDA Blazor addition — toggled via shidaTheme.toggle()) */
html.theme-dark{
  /* --red-050 es un tinte CLARO y vivía sólo en :root. Sin este override, .kpi.accent y .badge.accent
     pintaban un chip casi blanco (#FDECEC) sobre la tarjeta oscura. */
  --red-050:#3E2328;
  --page:#1E1B18; --card:#2A2724; --card-2:#232019;
  --ink:#EAE7E3; --ink-2:#A29B94; --ink-3:#726B65;
  --line:rgba(255,255,255,.09); --line-2:rgba(255,255,255,.05);
  --neutral-bg:#3A3532;
  --occard-bg:#322D27; --occard-line:#453E36;
  --topbar:rgba(30,27,24,.82);

  /* el menú vuelve a ser carbón: aquí el oscuro ya no es la excepción, es el tema */
  --sb:#211E1C; --sb-2:#2A2724; --sb-line:rgba(255,255,255,.08);
  --sb-ink:#EAE7E3; --sb-ink-2:#A29B94; --sb-ink-3:#726B65;
  --sb-hover:rgba(255,255,255,.05); --sb-active:rgba(255,255,255,.07);
  --sb-active-ink:#FFFFFF; --sb-accent:#ff7a83;
  --sb-scroll:rgba(255,255,255,.10);
  --draft:#5B9BFF; --draft-bg:rgba(91,155,255,.12); --draft-line:rgba(91,155,255,.5); --uc:#FF5A6E; --uc-sign:#FFC72C;
}

*{margin:0;padding:0;box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{
  font-family:var(--font); color:var(--ink); background:var(--page);
  font-size:14px; line-height:1.5; -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
}
:lang(zh), .zh{font-family:var(--font-cjk)}
a{color:inherit;text-decoration:none}
button{font-family:inherit;cursor:pointer;border:none;background:none}
::selection{background:rgba(239,51,64,.18)}
:focus-visible{outline:none;box-shadow:var(--ring);border-radius:8px}

/* fade the shell in once rendered (avoids flash) */
body:not(.ready){opacity:0}
body.ready{opacity:1;transition:opacity .25s ease}

/* ============ ambient background ============ */
.ambient{position:fixed;inset:0;z-index:0;pointer-events:none;overflow:hidden}
.ambient::before,.ambient::after{content:"";position:absolute;border-radius:50%;filter:blur(60px);opacity:.5}
.ambient::before{width:620px;height:620px;left:-160px;top:-220px;
  background:radial-gradient(circle at 30% 30%,rgba(239,51,64,.10),transparent 62%);
  animation:drift1 82s ease-in-out infinite}
.ambient::after{width:560px;height:560px;right:-160px;bottom:-200px;
  background:radial-gradient(circle at 60% 60%,rgba(45,41,38,.10),transparent 62%);
  animation:drift2 96s ease-in-out infinite}
@keyframes drift1{50%{transform:translate(60px,50px) scale(1.08)}}
@keyframes drift2{50%{transform:translate(-50px,-40px) scale(1.06)}}
@media (prefers-reduced-motion:reduce){.ambient::before,.ambient::after{animation:none}}

/* ============ app shell ============ */
.app{position:relative;z-index:1;display:grid;grid-template-columns:254px 1fr;min-height:100vh}

.sidebar{
  background:var(--sb);color:var(--sb-ink);border-right:1px solid var(--sb-line);
  display:flex;flex-direction:column;position:sticky;top:0;height:100vh;
}
/* El rectángulo oscuro de la esquina superior izquierda: lo único que conserva el carbón cuando el resto
   del menú es claro. Lleva exactamente los 64 px de alto de la barra superior para que los dos bloques
   cierren la esquina en una sola línea y no como un escalón. */
.sb-brand{display:flex;align-items:center;gap:11px;flex:none;height:64px;padding:0 18px;
  background:var(--char-900);border-bottom:1px solid rgba(255,255,255,.08)}
.sb-mark{width:34px;height:34px;border-radius:10px;flex:none;
  background:linear-gradient(150deg,var(--red),var(--red-600));
  display:grid;place-items:center;box-shadow:0 6px 16px rgba(239,51,64,.35)}
.sb-mark svg{width:19px;height:19px;color:#fff}
.sb-brand .name{font-family:var(--font-display);font-weight:800;font-size:18px;letter-spacing:.02em;color:#fff;line-height:1}
/* nowrap y no .13em de espaciado: el rectángulo mide 64 px de alto y la marca completa partida en dos
   renglones se sale de él. Antes cabía porque el bloque crecía a su gusto; ahora tiene altura fija. */
.sb-brand .sub{font-size:8.5px;letter-spacing:.07em;text-transform:uppercase;color:rgba(255,255,255,.46);
  margin-top:3px;white-space:nowrap}

.sb-portal{margin:2px 14px 12px;padding:9px 12px;border-radius:var(--radius-sm);
  background:var(--sb-2);border:1px solid var(--sb-line);display:flex;align-items:center;gap:9px}
.sb-portal .ic{width:26px;height:26px;border-radius:7px;display:grid;place-items:center;flex:none;
  background:var(--sb-active);color:var(--sb-accent)}
.sb-portal .ic svg{width:15px;height:15px}
.sb-portal .t1{font-size:9.5px;letter-spacing:.13em;text-transform:uppercase;color:var(--sb-ink-3)}
.sb-portal .t2{font-size:13px;font-weight:600;color:var(--sb-ink);line-height:1.25}

.sb-nav{flex:1;overflow-y:auto;padding:6px 12px 14px}
.sb-nav::-webkit-scrollbar{width:6px}
.sb-nav::-webkit-scrollbar-thumb{background:var(--sb-scroll);border-radius:3px}

/* Encabezado de sección = botón de plegar. Es un <button> y no un rótulo para que se alcance con el
   tabulador y lo anuncie un lector de pantalla; el aspecto sigue siendo el de un rótulo. */
.sb-sec{width:100%;display:flex;align-items:center;gap:8px;text-align:left;
  font-family:inherit;font-size:10px;letter-spacing:.15em;text-transform:uppercase;color:var(--sb-ink-3);
  padding:14px 12px 6px;border-radius:9px;transition:color .12s}
.sb-sec:hover{color:var(--sb-ink-2)}
.sb-sec .n{font-size:9px;letter-spacing:.04em;font-weight:700;padding:1px 6px;
  border-radius:var(--radius-pill);background:var(--sb-hover);color:var(--sb-ink-3)}
.sb-sec .n.on{background:var(--sb-active);color:var(--sb-accent)}
.sb-sec .chev{margin-left:auto;display:grid;place-items:center;
  /* Abajo cuando la sección está abierta, a la derecha cuando está plegada: el giro de todo árbol de
     carpetas. El glifo base apunta a la derecha, así que abierto es el que gira. */
  transform:rotate(90deg);transition:transform .16s ease}
.sb-sec .chev svg{width:14px;height:14px;display:block}
.sb-sec.col .chev{transform:rotate(0deg)}

.sb-grp{display:flex;flex-direction:column;animation:sbOpen .16s ease}
@keyframes sbOpen{from{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:none}}
@media (prefers-reduced-motion:reduce){.sb-grp{animation:none}.sb-sec .chev{transition:none}}

.sb-link{display:flex;align-items:center;gap:11px;padding:9px 12px;border-radius:10px;
  color:var(--sb-ink-2);font-size:13.5px;font-weight:500;position:relative;
  transition:background .12s,color .12s;margin-bottom:1px}
.sb-link svg{width:18px;height:18px;flex:none;opacity:.85}
.sb-link:hover{background:var(--sb-hover);color:var(--sb-ink)}
.sb-link.active{background:var(--sb-active);color:var(--sb-active-ink);font-weight:600}
.sb-link.active::before{content:"";position:absolute;left:-12px;top:8px;bottom:8px;width:3px;
  border-radius:0 3px 3px 0;background:var(--red)}
.sb-link.active svg{opacity:1;color:var(--sb-accent)}
.sb-link .tag{margin-left:auto;font-size:9px;font-weight:600;letter-spacing:.04em;
  padding:2px 7px;border-radius:var(--radius-pill);background:var(--sb-hover);color:var(--sb-ink-2)}
.sb-link .tag.f{background:var(--sb-active);color:var(--sb-accent)}

/* Subsección (2026-10-01): rótulo menor dentro de una sección grande —«Refacciones» dentro de Postventa—.
   Más chico y sin versalitas fuertes que el de la sección, con una raya que lo separa del bloque anterior. */
.sb-sub{display:flex;align-items:center;gap:8px;font-size:10.5px;font-weight:600;color:var(--sb-ink-3);
  padding:10px 12px 4px;letter-spacing:.02em}
.sb-sub::after{content:"";flex:1;height:1px;background:var(--sb-line)}
/* Grupo de favoritos: la estrella en el encabezado lo distingue de las secciones del sistema. */
.sb-sec .star{display:grid;place-items:center;color:#F2B233}
.sb-sec .star svg{width:12px;height:12px;fill:currentColor}

/* Vistas de alcance: azul, con un punto a la derecha. Activa conserva el azul (no el rojo de la marca), porque
   lo que importa es que se lea como «borrador» también cuando uno está parado en ella. */
.sb-link.draft,.sb-link.draft svg{color:var(--draft)}
.sb-link.draft:hover{background:var(--draft-bg);color:var(--draft)}
.sb-link.draft.active{background:var(--draft-bg);color:var(--draft)}
.sb-link.draft.active::before{background:var(--draft)}
.sb-link.draft.active svg{color:var(--draft)}
.sb-link .dr,.sb-legend .dr{width:6px;height:6px;border-radius:50%;background:var(--draft);flex:none;margin-left:auto;
  box-shadow:0 0 0 3px var(--draft-bg)}
.sb-sec.draft,.sb-sec.draft:hover{color:var(--draft)}
.sb-legend{display:flex;align-items:center;gap:9px;margin:14px 4px 2px;padding:9px 11px;border-radius:10px;
  border:1px dashed var(--draft-line);color:var(--draft);font-size:11px;line-height:1.35;background:var(--draft-bg)}
.sb-legend .dr{margin-left:0}

/* Banner de la vista de alcance (BorradorAviso) y tarjetas del tablero que también son borrador. */
.draft-banner{display:flex;gap:14px;align-items:flex-start;padding:14px 18px;margin-bottom:20px;border-radius:var(--radius);
  border:1.5px dashed var(--draft-line);background:var(--draft-bg);color:var(--ink)}
.draft-banner .ic{width:34px;height:34px;border-radius:10px;display:grid;place-items:center;flex:none;background:var(--draft);color:#fff}
.draft-banner .ic svg{width:18px;height:18px}
.draft-banner .t{font-weight:700;color:var(--draft);font-size:13.5px}
.draft-banner .uc{display:inline-flex;align-items:center;gap:6px;color:var(--uc);white-space:nowrap}
.draft-banner .uc::before{content:"\2013";margin:0 2px 0 1px;color:var(--uc)}
.draft-banner .uc-ic{width:20px;height:20px;border-radius:5px;display:inline-grid;place-items:center;background:var(--uc-sign);color:#1A1A1A}
.draft-banner .uc-ic svg{width:14px;height:14px}
.draft-banner .d{font-size:12.5px;color:var(--ink-2);margin-top:2px}
.draft-banner .ph{margin-left:auto;flex:none;align-self:center}
.card.draft{border:1.5px solid var(--draft);box-shadow:0 0 0 4px var(--draft-bg), var(--shadow)}
.badge.draft{background:var(--draft-bg);color:var(--draft)} .badge.draft .d{background:var(--draft)}
.pill.draft{background:var(--draft);color:#fff}

/* ============ content column ============ */
.content{display:flex;flex-direction:column;min-width:0}
.topbar{position:sticky;top:0;z-index:20;display:flex;align-items:center;gap:16px;
  padding:0 32px;height:64px;background:var(--topbar);backdrop-filter:blur(12px);
  border-bottom:1px solid var(--line)}
.tb-crumb{font-size:12.5px;color:var(--ink-3);display:flex;align-items:center;gap:8px}
.tb-crumb b{color:var(--ink-2);font-weight:600}
.tb-crumb .sep{opacity:.5}
.tb-search{margin-left:8px;flex:1;max-width:340px;display:flex;align-items:center;gap:9px;
  padding:8px 13px;border-radius:var(--radius-pill);background:var(--card);border:1px solid var(--line);color:var(--ink-3)}
.tb-search svg{width:15px;height:15px;flex:none}
.tb-search input{border:none;background:none;outline:none;font-size:13px;color:var(--ink);width:100%}
/* Aviso de ambiente de pruebas. Ámbar y en versalitas: tiene que leerse como una cinta de obra y no como un
   elemento más de la aplicación. Se encoge con puntos suspensivos en vez de desaparecer —en una pantalla
   estrecha lo que sobra es la migaja, no la advertencia— y nunca empuja a los controles de la derecha. */
.tb-env{
  flex:1 1 auto;min-width:0;text-align:center;
  font-size:11px;font-weight:800;letter-spacing:.09em;line-height:1.2;
  color:#7A4A00;background:#FFF3D4;border:1px solid #F0C670;border-radius:var(--radius-pill);
  padding:6px 14px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis
}
html.theme-dark .tb-env{color:#FFD98A;background:rgba(240,198,112,.14);border-color:rgba(240,198,112,.42)}

/* La misma advertencia en la pantalla de entrada, donde no hay barra superior: cinta de ancho completo. */
.env-strip{
  position:relative;z-index:30;text-align:center;
  font-size:11.5px;font-weight:800;letter-spacing:.09em;
  color:#7A4A00;background:#FFF3D4;border-bottom:1px solid #F0C670;padding:8px 16px
}
html.theme-dark .env-strip{color:#FFD98A;background:#2A2010;border-bottom-color:rgba(240,198,112,.42)}

.tb-right{margin-left:auto;display:flex;align-items:center;gap:10px}
.tb-btn{width:38px;height:38px;border-radius:10px;display:grid;place-items:center;color:var(--ink-2);
  border:1px solid var(--line);background:var(--card);position:relative;transition:.12s}
.tb-btn:hover{color:var(--ink);border-color:rgba(45,41,38,.2)}
.tb-btn svg{width:18px;height:18px}
.tb-btn .dot{position:absolute;top:8px;right:9px;width:7px;height:7px;border-radius:50%;
  background:var(--red);border:2px solid var(--card)}

/* Favoritos: la estrella de la barra superior y su lista. Encendida (pantalla actual en favoritos) se rellena
   en ámbar; el ámbar y no el rojo de la marca, porque el rojo ya significa «aviso» en la campana de al lado. */
.tb-favwrap{position:relative}
.tb-fav.on{color:#D99A1B;border-color:rgba(217,154,27,.42)}
.tb-fav.on svg{fill:#F2B233}
.fav-scrim{position:fixed;inset:0;z-index:40}
.fav-pop{position:absolute;right:0;top:calc(100% + 8px);z-index:41;width:320px;max-width:calc(100vw - 32px);
  background:var(--card);border:1px solid var(--line);border-radius:var(--radius);box-shadow:var(--shadow-lg);
  padding:8px;animation:sbOpen .14s ease}
.fav-act{width:100%;display:flex;align-items:center;gap:11px;text-align:left;padding:10px 11px;border-radius:10px;
  background:var(--card-2);border:1px solid var(--line);color:var(--ink-2);font-family:inherit;cursor:pointer}
.fav-act:hover{border-color:rgba(217,154,27,.5)}
.fav-act svg{width:18px;height:18px;flex:none}
.fav-act.on svg{color:#D99A1B;fill:#F2B233}
.fav-act b{display:block;font-size:13px;color:var(--ink);font-weight:600;line-height:1.25}
.fav-act small{display:block;font-size:11.5px;color:var(--ink-3);margin-top:1px}
.fav-act.na{cursor:default;font-size:12px;color:var(--ink-3)}
.fav-act.na:hover{border-color:var(--line)}
.fav-h{font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:var(--ink-3);padding:12px 6px 6px}
.fav-empty{font-size:12.5px;color:var(--ink-3);padding:4px 6px 10px;line-height:1.45}
.fav-list{display:flex;flex-direction:column;gap:1px;max-height:300px;overflow-y:auto}
.fav-row{display:flex;align-items:center;border-radius:9px}
.fav-row:hover{background:var(--card-2)}
.fav-row.active{background:var(--red-050)}
.fav-row a{flex:1;min-width:0;display:flex;align-items:center;gap:10px;padding:8px 8px;font-size:13px;color:var(--ink)}
.fav-row a svg{width:16px;height:16px;flex:none;color:var(--ink-3)}
.fav-row a span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.fav-x{width:28px;height:28px;flex:none;display:grid;place-items:center;border-radius:7px;color:var(--ink-3);
  opacity:0;transition:opacity .12s}
.fav-row:hover .fav-x,.fav-x:focus-visible{opacity:1}
.fav-x:hover{color:var(--red);background:var(--card)}
.fav-x svg{width:14px;height:14px}
@media (hover:none){.fav-x{opacity:1}}
.fav-sw{display:flex;align-items:center;gap:10px;margin-top:8px;padding:10px 8px 4px;border-top:1px solid var(--line);
  font-size:12.5px;color:var(--ink-2);cursor:pointer;user-select:none}
.fav-sw input{position:absolute;opacity:0;pointer-events:none}
.fav-sw .sw{width:32px;height:18px;border-radius:999px;background:var(--line-2);position:relative;flex:none;transition:background .14s}
.fav-sw .sw::after{content:"";position:absolute;top:2px;left:2px;width:14px;height:14px;border-radius:50%;
  background:#fff;box-shadow:0 1px 2px rgba(0,0,0,.25);transition:transform .14s}
.fav-sw input:checked + .sw{background:var(--red)}
.fav-sw input:checked + .sw::after{transform:translateX(14px)}
.fav-sw input:focus-visible + .sw{box-shadow:var(--ring)}

/* Identidad de quien está dentro — inicial, nombre, puesto y rol— y la salida. Vivía al pie del menú
   lateral; subió aquí el 2026-09-14 para que no se pierda cuando el menú se pliega ni cuando, en una
   pantalla estrecha, el menú es un cajón que está cerrado casi siempre. */
.tb-sep{width:1px;height:26px;background:var(--line);margin:0 2px;flex:none}
.tb-user{display:flex;align-items:center;gap:9px;min-width:0}
.tb-ava{width:34px;height:34px;border-radius:50%;flex:none;display:grid;place-items:center;
  font-weight:700;font-size:12.5px;color:#fff;background:linear-gradient(150deg,#4a4540,#2f2b28)}
.tb-id{min-width:0;max-width:210px}
.tb-id .n{font-size:13px;font-weight:600;color:var(--ink);line-height:1.2;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.tb-id .r{font-size:10.5px;color:var(--ink-3);line-height:1.3;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.tb-out:hover{color:var(--red);border-color:rgba(239,51,64,.34)}

/* language switch */
.lang{display:flex;align-items:center;background:var(--card);border:1px solid var(--line);
  border-radius:var(--radius-pill);padding:3px;gap:2px}
.lang button{padding:5px 12px;border-radius:var(--radius-pill);font-size:12px;font-weight:600;
  color:var(--ink-3);transition:.14s;line-height:1.3}
.lang button.on{background:var(--char);color:#fff}
.lang button.zh{font-family:var(--font-cjk)}

.hamb{display:none}

/* main scroll region */
.view{flex:1;padding:28px 32px 56px;max-width:1360px;width:100%;margin:0 auto}

/* El catálogo de refacciones es la única pantalla de tres tableros: renuncia al ancho máximo y al colchón
   inferior, y se ancla a la ventana para que cada tablero tenga su propio scroll.
   La altura sale del armazón (.app pasa de min-height a height) y no de restarle a mano los 64px de la
   barra superior: así sigue cuadrando si esa barra cambia de alto. */
.app:has(.cat-wide){height:100vh;overflow:hidden}
.view:has(.cat-wide){max-width:none;padding:16px 20px;flex:1;min-height:0;overflow:hidden}
/* El tablero ocupa TODO el ancho del área de contenido. Un panel de indicadores centrado a 1360 deja dos
   bandas muertas a los lados y las tarjetas se estrechan justo donde tienen que respirar; la referencia de
   Shineray llega de borde a borde.
   Se hace con marcador y no subiendo el tope de `.view` porque las pantallas de tabla y de formulario SÍ
   dependen de ese límite: un renglón de 1900 px de ancho es ilegible. Y va aparte de `.cat-wide` porque
   aquélla además congela el alto y corta el desbordamiento, que es del catálogo de tres tableros, no de
   una página que se desplaza. */
.view:has(.tablero-wide){max-width:none;padding:26px 28px 56px}
@media (max-width:900px){ .view:has(.tablero-wide){padding:18px 16px 40px} }

/* ============ page header ============ */
.phead{display:flex;justify-content:space-between;align-items:flex-end;gap:20px;flex-wrap:wrap;margin-bottom:22px}
.phead h1{font-family:var(--font-display);font-size:29px;font-weight:700;letter-spacing:-.02em;line-height:1.05}
.phead .lede{color:var(--ink-2);font-size:14px;margin-top:7px;max-width:640px}
.phead .actions{display:flex;gap:10px;align-items:center}

/* ============ buttons ============ */
.btn{display:inline-flex;align-items:center;gap:8px;padding:9px 16px;border-radius:11px;
  font-size:13.5px;font-weight:600;transition:.14s;border:1px solid transparent;white-space:nowrap}
.btn svg{width:16px;height:16px}
.btn-primary{background:var(--red);color:#fff;box-shadow:0 6px 16px rgba(239,51,64,.24)}
.btn-primary:hover{background:var(--red-600);transform:translateY(-1px)}
.btn-primary:disabled{opacity:.6;cursor:default;transform:none}
.btn-ghost{background:var(--card);color:var(--ink);border-color:var(--line)}
.btn-ghost:hover{border-color:rgba(45,41,38,.22);background:var(--card-2)}
.btn-dark{background:var(--char);color:#fff}
.btn-dark:hover{background:var(--char-900)}
.btn-danger{background:var(--card);color:var(--bad,#C8353F);border-color:rgba(200,53,63,.42)}
.btn-danger:hover{background:rgba(200,53,63,.10);border-color:var(--bad,#C8353F)}
.btn-danger:disabled{opacity:.55;cursor:default}
.btn-sm{padding:6px 12px;font-size:12.5px;border-radius:9px}

/* ============ cards / grid ============ */
.grid{display:grid;gap:18px}
.g-4{grid-template-columns:repeat(4,1fr)}
.g-3{grid-template-columns:repeat(3,1fr)}
.g-2{grid-template-columns:repeat(2,1fr)}
.span-2{grid-column:span 2}
.mb{margin-bottom:18px}
.mb-l{margin-bottom:28px}

.card{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);box-shadow:var(--shadow)}
.card-p{padding:22px}
.card-h{display:flex;align-items:center;justify-content:space-between;gap:12px;
  padding:16px 20px;border-bottom:1px solid var(--line-2)}
.card-h h3{font-size:15px;font-weight:700;letter-spacing:-.01em}
.card-h .hint{font-size:12px;color:var(--ink-3)}
.card-b{padding:20px}

/* entry stagger */
.enter{opacity:0;transform:translateY(8px);animation:enter .4s ease forwards}
@keyframes enter{to{opacity:1;transform:none}}
@media (prefers-reduced-motion:reduce){.enter{animation:none;opacity:1;transform:none}}

/* ============ KPI tiles ============ */
.kpi{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);
  box-shadow:var(--shadow);padding:18px 20px;position:relative;overflow:hidden;transition:.16s}
.kpi:hover{border-color:rgba(45,41,38,.18);box-shadow:var(--shadow-lg)}
.kpi .ico{width:34px;height:34px;border-radius:10px;display:grid;place-items:center;margin-bottom:14px;
  background:var(--neutral-bg);color:var(--ink-2)}
.kpi .ico svg{width:18px;height:18px}
.kpi.accent .ico{background:var(--red-050);color:var(--red-600)}
.kpi .klabel{font-size:11px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;color:var(--ink-3)}
.kpi .kval{font-family:var(--font-display);font-size:31px;font-weight:700;letter-spacing:-.02em;line-height:1.05;margin-top:6px}
.kpi .kval .u{font-size:15px;font-weight:600;color:var(--ink-3);margin-left:3px}
.kpi .ktrend{display:inline-flex;align-items:center;gap:5px;font-size:12px;font-weight:600;margin-top:9px}
.kpi .ktrend.up{color:var(--ok)} .kpi .ktrend.down{color:var(--bad)} .kpi .ktrend.flat{color:var(--ink-3)}
.kpi .ktrend svg{width:13px;height:13px}
.kpi .kfoot{font-size:11.5px;color:var(--ink-3);margin-top:2px}

/* Tarjeta KPI «con tinte» — la del tablero: lavado de color al fondo, arco en la esquina superior derecha
   y el icono suelto y a color, sin el chip gris.
   Es un MODIFICADOR y no un cambio a .kpi a propósito: cuatro paneles (inventario, taller, PDI, entradas)
   ya dependen del estilo sobrio, y el tablero no tiene por qué arrastrarlos.
   El tono de cada tarjeta entra por --k-tint/--k-ink desde la página, así que la paleta sigue siendo del
   tema y esto funciona igual en claro y en oscuro. */
.kpi.tinte{background:
    radial-gradient(150px 110px at calc(100% - 10px) -26px, var(--k-tint,var(--neutral-bg)) 0%, transparent 70%),
    var(--card)}
.kpi.tinte::after{content:"";position:absolute;top:-40px;right:-40px;width:104px;height:104px;
  border-radius:50%;background:var(--k-tint,var(--neutral-bg));opacity:.45;pointer-events:none}
.kpi.tinte > *{position:relative;z-index:1}
.kpi.tinte .ico{background:none;width:auto;height:auto;margin-bottom:10px;place-items:start;
  color:var(--k-ink,var(--ink-2))}
.kpi.tinte .ico svg{width:21px;height:21px}

/* Rejilla de seis tarjetas de los tableros (corporativo y distribuidor). `.grid` llega hasta g-4, y forzar
   seis con g-4 dejaría dos huérfanas en el segundo renglón.
   Va GLOBAL y no en el `.razor.css` de una página: el CSS aislado de Blazor sólo marca el marcado que ese
   componente renderiza, así que la segunda pantalla que la usara se quedaría sin la regla —y sin rejilla,
   las tarjetas se apilan a todo lo ancho. */
.kpis6{display:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:14px}
@media (max-width:1400px){ .kpis6{grid-template-columns:repeat(3,minmax(0,1fr))} }
@media (max-width:760px){ .kpis6{grid-template-columns:repeat(2,minmax(0,1fr))} }
@media (max-width:420px){ .kpis6{grid-template-columns:1fr} }
/* En seis columnas el número de 31px se encima con la etiqueta; baja a 26 sin tocar el resto del sistema. */
.kpis6 .kval{font-size:26px}
/* Tarjeta cuyo módulo todavía no existe: se ve, pero no finge tener un dato. */
.soon{display:flex;align-items:center;gap:8px;margin-top:6px}
.soon .kval{color:var(--ink-3)}

/* ============ tables ============ */
.tbl-wrap{overflow-x:auto}
/* El pie de una tabla dentro de una .card «desnuda». La tarjeta que sólo lleva tabla no trae padding a
   propósito —lo pone cada celda, y así los renglones llegan de borde a borde—, pero el paginador que va
   debajo sí lo necesita: sin esto queda pegado a la izquierda y a los pocos pixeles del borde inferior.
   Las tarjetas con .card-p / .card-b ya tienen su propio padding y no lo usan. */
.tbl-foot{padding:10px 16px}
table.tbl{width:100%;border-collapse:collapse;font-size:13.5px}
.tbl thead th{text-align:left;font-size:10.5px;font-weight:600;letter-spacing:.07em;text-transform:uppercase;
  color:var(--ink-3);padding:11px 16px;border-bottom:1px solid var(--line);white-space:nowrap;background:var(--card-2)}
.tbl thead th.num{text-align:right}
/* Sortable headers */
.tbl thead th.sortable{cursor:pointer;user-select:none;transition:color .12s}
.tbl thead th.sortable:hover{color:var(--ink)}
.tbl thead th.sortable.sorted{color:var(--red)}
.tbl thead th .th-s{display:inline-flex;align-items:center;gap:5px}
.tbl thead th.num .th-s{flex-direction:row-reverse}
.tbl thead th .th-arr{font-size:11px;line-height:1;width:8px;display:inline-block}
.tbl thead th.sortable:not(.sorted):hover .th-arr::before{content:"↕";opacity:.4}
.tbl tbody td{padding:12px 16px;border-bottom:1px solid var(--line-2);color:var(--ink);vertical-align:middle}
.tbl tbody tr{transition:background .12s}
.tbl tbody tr:hover{background:var(--card-2)}
.tbl tbody tr:last-child td{border-bottom:none}
.tbl td.num{text-align:right;font-variant-numeric:tabular-nums}
/* Columna centrada (p.ej. Acciones cuando lleva un solo botón): encabezado y contenido alineados entre sí. */
.tbl thead th.ctr{text-align:center}
.tbl td.ctr{text-align:center}
.acts.ctr{justify-content:center}

/* ---- editable line-item table (.tbl.tbl-edit) ----
   Rows of controls inside a modal (e.g. las partidas de una orden de compra). Reuses the .f control
   tokens at a denser scale so the row reads as one band of fields instead of raw browser widgets. */
.tbl.tbl-edit thead th{padding-top:10px;padding-bottom:10px}
.tbl.tbl-edit tbody td{padding:8px 16px;vertical-align:middle}
.tbl.tbl-edit tbody tr:hover{background:transparent}          /* row hover is noise on an input grid */
.tbl.tbl-edit td input,
.tbl.tbl-edit td select{font-family:var(--font);font-size:13.5px;color:var(--ink);background:var(--card);
  border:1px solid var(--line);border-radius:10px;padding:9px 12px;width:100%;transition:.14s}
.tbl.tbl-edit td input:focus,
.tbl.tbl-edit td select:focus{outline:none;border-color:var(--red);box-shadow:var(--ring)}
.tbl.tbl-edit td select{appearance:none;-webkit-appearance:none;cursor:pointer;padding-right:32px;
  background-image:url("data:image/svg+xml;charset=UTF-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%239A938C' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 11px center}
.tbl.tbl-edit td.num input{text-align:right;font-variant-numeric:tabular-nums}
/* kill the native number spinners: they eat width and break the right alignment */
.tbl.tbl-edit td input[type=number]{-moz-appearance:textfield}
.tbl.tbl-edit td input[type=number]::-webkit-outer-spin-button,
.tbl.tbl-edit td input[type=number]::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}
/* column sizing — set on the <th> so table layout honours it */
.tbl.tbl-edit .col-qty{width:92px}
.tbl.tbl-edit .col-price{width:138px}
.tbl.tbl-edit .col-sub{width:112px}
.tbl.tbl-edit .col-act{width:52px}
.tbl.tbl-edit td.col-act{text-align:right}
@media (max-width:640px){
  .tbl.tbl-edit tbody td{padding:7px 10px}
  .tbl.tbl-edit .col-qty{width:78px}
  .tbl.tbl-edit .col-price{width:112px}
}
/* Orden de compra detail sections */
/* Detalle de la OC a dos columnas: el proceso (línea de tiempo) a la izquierda y todos los datos a la derecha.
   La línea de tiempo tiene alto fijo —son los pasos del Proceso 02— así que corre en paralelo a los datos en
   vez de sumarse debajo de ellos. Por debajo de 1100px vuelve a apilarse, con los datos primero. */
.ocsplit{display:grid;grid-template-columns:330px minmax(0,1fr);gap:26px;align-items:start}
/* Columnas asignadas a mano: en el DOM los datos van primero (para que al apilarse queden arriba), pero en
   pantalla ancha el proceso ocupa la izquierda. */
.ocsplit>.ocflow{grid-column:1;grid-row:1;min-width:0}
.ocsplit>.ocdata{grid-column:2;grid-row:1;min-width:0}
/* En columna propia la primera sección no necesita el filete de separación que la despegaba de la anterior. */
.ocsplit>.ocflow>.ocsec:first-child{margin-top:0;padding-top:0;border-top:0}
@media (max-width:1100px){
  .ocsplit{grid-template-columns:1fr;gap:0}
  .ocsplit>.ocdata{grid-column:1;grid-row:auto}
  .ocsplit>.ocflow{grid-column:1;grid-row:auto}
  .ocsplit>.ocflow>.ocsec:first-child{margin-top:16px;padding-top:14px;border-top:1px solid var(--line-2)}
}

.ocsec{margin-top:16px;padding-top:14px;border-top:1px solid var(--line-2)}
.ocsec-h{font-size:11px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--ink-3);margin-bottom:10px}
.ocgrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:12px}
.ocgrid>div{display:flex;flex-direction:column;gap:2px}
.ocl{font-size:11px;color:var(--ink-3)}
/* Línea de tiempo de la Orden de Compra — los 14 pasos del Proceso 02.
   Un riel vertical con un punto por paso: cumplido (rojo lleno), actual (aro rojo con halo),
   pendiente (hueco gris). El riel se pinta con un ::before por renglón para que la línea
   quede continua sin depender de una altura fija. */
.octl{margin:2px 0 0;padding:0;list-style:none}
.octl li{position:relative;padding:0 0 14px 26px;font-size:12.5px;color:var(--ink-3)}
.octl li:last-child{padding-bottom:0}
.octl li::before{content:"";position:absolute;left:6px;top:13px;bottom:-4px;width:1px;background:var(--line-2)}
.octl li:last-child::before{display:none}
.octl li::after{content:"";position:absolute;left:2px;top:4px;width:9px;height:9px;border-radius:50%;
  background:var(--surface);border:1.5px solid var(--line-1);box-sizing:border-box}
.octl li.done{color:var(--ink-2)}
.octl li.done::after{background:var(--red);border-color:var(--red)}
.octl li.done::before{background:var(--red)}
.octl li.now{color:var(--ink-1);font-weight:600}
.octl li.now::after{background:var(--surface);border:2.5px solid var(--red);
  box-shadow:0 0 0 3px var(--red-050)}
.octl li.off{color:var(--ink-3);opacity:.55}

/* Tarjetas de parcialidad (entregas parciales): una por tanda, con su propio estado y acciones.
   Fondo marfil cálido + filete rojo a la izquierda: sobre el blanco del modal, cada tanda se distingue
   de un vistazo sin volverse gris. Una cancelada pierde el filete y se atenúa. */
.occard{border:1px solid var(--occard-line);border-left:3px solid var(--red);border-radius:10px;
  padding:12px 14px;margin-bottom:12px;background:var(--occard-bg)}
.occard:last-child{margin-bottom:0}
.occard.off{opacity:.62;border-left-color:var(--ink-3)}
/* Varios estatus apilados en una celda de la lista (uno por grupo de parcialidades que lo comparten). */
.stbadges{display:flex;flex-direction:column;gap:4px;align-items:flex-start}
.occard-h{display:flex;justify-content:space-between;align-items:center;gap:12px;flex-wrap:wrap}
.occard-t{font-size:13px;color:var(--ink-1)}
.occard-l{font-size:12px;color:var(--ink-3);margin-top:3px}
.occard-a{display:flex;gap:8px;margin-top:12px;flex-wrap:wrap}
/* Casilla dentro del modal genérico de acción (p. ej. «autorizar surtido parcial»). La regla del input va con
   especificidad de tres partes porque `.f input{width:100%}` (más abajo) ganaría por orden de archivo. */
.chkline{display:flex;align-items:center;justify-content:flex-start;gap:9px;font-size:13px;color:var(--ink-1);cursor:pointer}
.f label.chkline{font-size:13px;font-weight:600}
.f label.chkline input{width:15px;height:15px;flex:0 0 auto;accent-color:var(--red);margin:0}
.octl .octl-m{display:block;font-size:11px;font-weight:400;color:var(--ink-3);margin-top:1px;line-height:1.35}
.octl .octl-w{display:block;font-size:10.5px;color:var(--ink-3);opacity:.85;margin-top:1px}
/* Subrenglón de celda: el dato secundario SIEMPRE baja de línea. */
.subline{display:block;font-size:10.5px;color:var(--ink-3);margin-top:2px;font-weight:400}

/* Campo partido: a la izquierda un segmento fijo de sólo lectura (el folio que asigna SHIDA),
   a la derecha lo capturable. Existe para que no se confundan dos folios distintos. */
.fsplit{display:flex;align-items:stretch}
.fsplit-pre{display:flex;align-items:center;padding:0 10px;white-space:nowrap;
  font-family:var(--mono,ui-monospace,monospace);font-size:12.5px;color:var(--ink-3);
  background:var(--neutral-bg);border:1px solid var(--line-2);border-right:none;
  border-radius:8px 0 0 8px}
.fsplit input{border-radius:0 8px 8px 0!important;flex:1;min-width:0}

/* Vista previa del folio: el resultado de la plantilla, en la misma tipografía en que se verá impreso.
   Va en una cápsula para que se lea como un dato y no como parte de la frase que lo introduce. */
.fpreview{display:inline-block;padding:3px 9px;border-radius:7px;background:var(--neutral-bg);
  border:1px solid var(--line-2);color:var(--ink);font-size:12.5px;font-weight:700;letter-spacing:.01em}

/* Aviso de la ventana de envío (día 15 al 20) en el portal del distribuidor. */
.ocwin{display:flex;gap:9px;align-items:flex-start;padding:10px 12px;border-radius:8px;
  font-size:12.5px;line-height:1.45;margin-bottom:12px}
.ocwin.open{background:var(--ok-bg);color:#1c7a4f}
.ocwin.shut{background:var(--warn-bg);color:#8a5a10}
.ocwin svg{width:16px;height:16px;flex:none;margin-top:1px}

/* Precio unitario no editable: el Instructivo 3.1 lo define como campo calculado. */
.ocfix{display:inline-flex;align-items:center;gap:6px;color:var(--ink-2);font-variant-numeric:tabular-nums}
.ocfix svg{width:12px;height:12px;opacity:.5}

/* Notification recipients config */
.ntf-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:16px}
.ntf-list{margin-top:14px;border-top:1px solid var(--line-2);padding-top:6px}
.ntf-row{display:flex;align-items:center;gap:12px;padding:9px 2px;cursor:pointer;border-bottom:1px solid var(--line-2)}
.ntf-row:last-child{border-bottom:none}
.ntf-row input[type=checkbox]{width:17px;height:17px;flex:none;accent-color:var(--red)}
.tbl .mono{font-family:var(--font-mono);font-size:12.5px;letter-spacing:-.01em;color:var(--ink-2)}
.tbl .strong{font-weight:600;color:var(--ink)}
.num2{font-family:var(--font-display);font-weight:700;font-size:15px}
.num2 .u{font-size:11px;font-weight:600;color:var(--ink-3);margin-left:2px}
.cellhead{display:flex;align-items:center;gap:11px}
.thumb{width:40px;height:30px;border-radius:6px;flex:none;display:grid;place-items:center;
  background:var(--neutral-bg);color:var(--ink-3);font-size:9px;font-weight:700;letter-spacing:.03em;overflow:hidden}
.thumb.red{background:var(--char);color:#fff}
.av{width:30px;height:30px;border-radius:50%;flex:none;display:grid;place-items:center;
  font-size:11px;font-weight:700;color:#fff}

/* ============ badges / status ============ */
.badge{display:inline-flex;align-items:center;gap:6px;font-size:11.5px;font-weight:600;
  padding:3px 10px 3px 8px;border-radius:var(--radius-pill);line-height:1.5;white-space:nowrap}
.badge .d{width:6px;height:6px;border-radius:50%;flex:none}
.badge.ok{background:var(--ok-bg);color:#1c7a4f} .badge.ok .d{background:var(--ok)}
.badge.warn{background:var(--warn-bg);color:#8a5a10} .badge.warn .d{background:var(--warn)}
.badge.bad{background:var(--bad-bg);color:#a5262f} .badge.bad .d{background:var(--bad)}
.badge.info{background:var(--info-bg);color:#2c567f} .badge.info .d{background:var(--info)}
.badge.neutral{background:var(--neutral-bg);color:var(--ink-2)} .badge.neutral .d{background:var(--ink-3)}
.badge.accent{background:var(--red-050);color:var(--red-600)} .badge.accent .d{background:var(--red)}

.pill{display:inline-flex;align-items:center;gap:6px;font-size:11px;font-weight:600;letter-spacing:.03em;
  padding:3px 9px;border-radius:var(--radius-pill);background:var(--neutral-bg);color:var(--ink-2)}
.pill.phase{background:var(--char);color:#fff}

/* progress */
.prog{height:7px;border-radius:5px;background:var(--neutral-bg);overflow:hidden}
.prog>span{display:block;height:100%;border-radius:5px;background:var(--char)}
.prog>span.a{background:var(--red)}
.prog>span.ok{background:var(--ok)}.prog>span.warn{background:var(--warn)}

/* list rows */
.rows{display:flex;flex-direction:column}
.row{display:flex;align-items:center;gap:13px;padding:13px 0;border-bottom:1px solid var(--line-2)}
.row:last-child{border-bottom:none}
.row .rt{font-weight:600;font-size:13.5px}.row .rs{font-size:12px;color:var(--ink-3)}
.row .rright{margin-left:auto;text-align:right}

/* ============ demo ribbon ============ */
.demo-flag{position:fixed;z-index:60;left:50%;bottom:16px;transform:translateX(-50%);
  display:flex;align-items:center;gap:9px;padding:7px 15px;border-radius:var(--radius-pill);
  background:rgba(33,30,28,.92);color:#fff;font-size:11.5px;font-weight:500;letter-spacing:.02em;
  box-shadow:var(--shadow-lg);backdrop-filter:blur(6px)}
.demo-flag .d{width:7px;height:7px;border-radius:50%;background:var(--red);flex:none;
  box-shadow:0 0 0 0 rgba(239,51,64,.5);animation:pulse 2.4s infinite}
@keyframes pulse{50%{box-shadow:0 0 0 6px rgba(239,51,64,0)}}
@media (prefers-reduced-motion:reduce){.demo-flag .d{animation:none}}

/* helpers */
.muted{color:var(--ink-3)} .sec{color:var(--ink-2)} .rt-red{color:var(--red-600)}
.flex{display:flex;align-items:center;gap:10px}.between{justify-content:space-between}
.wrap{flex-wrap:wrap}.gap-s{gap:6px}.mt{margin-top:14px}.mt-l{margin-top:22px}
.right{margin-left:auto}.tar{text-align:right}.nowrap{white-space:nowrap}

/* ============ responsive ============ */
@media (max-width:1120px){ .g-4{grid-template-columns:repeat(2,1fr)} }
@media (max-width:900px){
  .app{grid-template-columns:1fr}
  .sidebar{position:fixed;left:0;top:0;width:280px;z-index:80;transform:translateX(-100%);
    transition:transform .25s ease;box-shadow:var(--shadow-lg)}
  body.nav-open .sidebar{transform:none}
  .scrim{position:fixed;inset:0;background:rgba(20,18,16,.4);z-index:70;opacity:0;visibility:hidden;transition:.2s}
  body.nav-open .scrim{opacity:1;visibility:visible}
  .hamb{display:grid}
  .view{padding:22px 18px 48px}.topbar{padding:0 18px}
  .g-3,.g-2,.span-2{grid-template-columns:1fr;grid-column:auto}
  .tb-search{display:none}
}
/* Lo primero que sobra en una barra estrecha es el texto del nombre: la inicial ya identifica la cuenta y
   el nombre completo sigue disponible en el title del bloque. */
@media (max-width:1080px){ .tb-id{display:none} }
@media (max-width:640px){ .tb-crumb{display:none} .topbar{gap:10px} }
@media (min-width:901px){.scrim{display:none}}

/* ============================================================
   SHIDA Blazor additions (not part of the demo) — framework UI
   ============================================================ */
#blazor-error-ui{
  background:var(--char-900);color:#fff;bottom:0;box-shadow:var(--shadow-lg);display:none;
  left:0;padding:.85rem 1.25rem;position:fixed;width:100%;z-index:1000;font-size:13.5px;
}
#blazor-error-ui .reload{color:#ff8a92;font-weight:600;margin-left:8px;text-decoration:underline}
#blazor-error-ui .dismiss{cursor:pointer;position:absolute;right:1rem;top:.5rem}

.validation-message{color:var(--bad);font-size:12px;margin-top:4px;display:block}

/* ============================================================
   Admin / CRUD pages (Distribuidores · Usuarios · Textos)
   Built on the same tokens as the demo design system above.
   ============================================================ */

/* toolbar above a table: search + filters (left) · actions (right) */
.toolbar{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-bottom:16px}
.toolbar .right{margin-left:auto;display:flex;align-items:center;gap:10px}
.finput{display:flex;align-items:center;gap:9px;padding:8px 14px;border-radius:var(--radius-pill);
  background:var(--card);border:1px solid var(--line);color:var(--ink-3);min-width:250px;transition:.14s}
.finput:focus-within{border-color:var(--red);box-shadow:var(--ring)}
.finput svg{width:16px;height:16px;flex:none}
.finput input{border:none;background:none;outline:none;font-size:13.5px;color:var(--ink);width:100%;font-family:var(--font)}

/* segmented filter (All / Active / Inactive) — mirrors .lang */
.seg{display:inline-flex;align-items:center;background:var(--card);border:1px solid var(--line);
  border-radius:var(--radius-pill);padding:3px;gap:2px}
.seg button{padding:6px 13px;border-radius:var(--radius-pill);font-size:12.5px;font-weight:600;
  color:var(--ink-3);transition:.14s;line-height:1.3;white-space:nowrap}
.seg button.on{background:var(--char);color:#fff}

/* styled native select */
.selin{appearance:none;-webkit-appearance:none;font-family:var(--font);font-size:13.5px;color:var(--ink);
  background:var(--card) url("data:image/svg+xml;charset=UTF-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%239A938C' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E") no-repeat right 12px center;
  border:1px solid var(--line);border-radius:11px;padding:9px 34px 9px 13px;transition:.14s;cursor:pointer}
.selin:focus{outline:none;border-color:var(--red);box-shadow:var(--ring)}

/* table action buttons */
.acts{display:flex;align-items:center;gap:6px;justify-content:flex-end}
/* Fila de botones con etiqueta, alineada a la izquierda y que dobla cuando no cabe. Vive AQUÍ y no en un
   .razor.css: el CSS aislado de Blazor sólo marca el marcado que renderiza ESE componente, así que la segunda
   pantalla que la usara se quedaba sin la regla —sin error y sin aviso—. Eso fue justo lo que pasó en la ficha
   de la venta: sus dos botones de PDI salían a todo lo ancho y con el texto centrado, porque .iconbtn es
   display:grid y sin un padre flexible un grid de nivel bloque ocupa todo el renglón. */
.rowacts{display:inline-flex;align-items:center;gap:6px;flex-wrap:wrap}
.iconbtn{width:32px;height:32px;border-radius:9px;display:grid;place-items:center;color:var(--ink-2);
  border:1px solid var(--line);background:var(--card);transition:.12s;flex:none}
.iconbtn svg{width:16px;height:16px}
.iconbtn:hover{color:var(--ink);border-color:rgba(45,41,38,.22);background:var(--card-2)}
.iconbtn.danger:hover{color:var(--bad);border-color:var(--bad);background:var(--bad-bg)}
/* Variante con etiqueta. Cuando dos botones comparten el mismo icono —bajar el PDF y bajar el XML del mismo
   CFDI— el icono solo no los distingue y el title obliga a pasar el ratón por cada uno para saber cuál es cuál.
   El formato va escrito. "PDF"/"XML" no se traducen: son el nombre del formato en cualquier idioma. */
.iconbtn.lbl{width:auto;min-width:32px;padding:0 9px;grid-auto-flow:column;gap:5px}
.iconbtn.lbl b{font-size:10px;font-weight:700;letter-spacing:.05em}

/* clickable name cell */
.linklike{font-weight:600;color:var(--ink);cursor:pointer}
.linklike:hover{color:var(--red-600)}
/* A .linklike may carry a leading icon (e.g. a document download link). Constrain it like the other
   icon+text controls (.btn, .iconbtn): an inline SVG with no width/height renders at its natural box. */
.linklike svg{width:15px;height:15px;vertical-align:-3px}

/* ============ modal / dialog ============ */
.ov{position:fixed;inset:0;z-index:120;background:rgba(20,18,16,.46);backdrop-filter:blur(3px);
  display:flex;align-items:flex-start;justify-content:center;padding:6vh 18px 18px;overflow-y:auto;
  animation:ovin .16s ease}
@keyframes ovin{from{opacity:0}to{opacity:1}}
.dlg{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);box-shadow:var(--shadow-lg);
  width:100%;max-width:560px;overflow:hidden;animation:dlgin .2s cubic-bezier(.2,.8,.3,1)}
.dlg.wide{max-width:720px}
/* xwide: for dialogs holding a wide data table (e.g. precios por año, 7 columns) that would
   otherwise force a horizontal scrollbar inside the dialog. */
.dlg.xwide{max-width:980px}
.dlg.narrow{max-width:440px}
/* xxwide: el expediente de una orden a dos columnas (proceso | datos). Apilado medía ~1750px de alto y había
   que alejar el zoom para verlo entero; en paralelo la altura es la de la columna más alta. */
.dlg.xxwide{max-width:1320px}
@keyframes dlgin{from{opacity:0;transform:translateY(14px) scale(.98)}to{opacity:1;transform:none}}
.dlg-h{display:flex;align-items:center;gap:12px;padding:18px 22px;border-bottom:1px solid var(--line-2)}
.dlg-h h3{font-family:var(--font-display);font-size:17px;font-weight:700;letter-spacing:-.01em;flex:1}
.dlg-h .x{width:32px;height:32px;border-radius:9px;display:grid;place-items:center;color:var(--ink-3);flex:none}
.dlg-h .x:hover{background:var(--card-2);color:var(--ink)}
.dlg-h .x svg{width:18px;height:18px}
.dlg-b{padding:22px}
.dlg-f{display:flex;align-items:center;justify-content:flex-end;gap:10px;padding:16px 22px;
  border-top:1px solid var(--line-2);background:var(--card-2)}
.dlg-f .left{margin-right:auto}

/* Acciones dentro del CUERPO del modal. Cuando debajo va una ficha larga de referencia (el «Formato del
   archivo»), dejar los botones en el pie del diálogo los manda al fondo de un cuadro de 1,600 px: hay que
   pasar toda la especificación para poder importar. Mismo trazo que .dlg-f, sin su fondo, porque aquí no
   cierran el diálogo sino que quedan a media altura. */
.dlg-acts{display:flex;align-items:center;justify-content:flex-end;gap:10px;
  margin:18px 0 2px;padding-top:16px;border-top:1px solid var(--line-2)}

/* ============ forms ============ */
.frm{display:grid;grid-template-columns:1fr 1fr;gap:15px 16px}
.f{display:flex;flex-direction:column;gap:7px;min-width:0}
.f.col-2{grid-column:span 2}
.f label{font-size:12px;font-weight:600;color:var(--ink-2);letter-spacing:.02em}
.f label .opt{font-weight:500;color:var(--ink-3);margin-left:5px}
.f input,.f textarea,.f select{font-family:var(--font);font-size:14px;color:var(--ink);background:var(--card);
  border:1px solid var(--line);border-radius:11px;padding:10px 13px;width:100%;transition:.14s}
.f textarea{resize:vertical;min-height:76px;line-height:1.5}
.f input:focus,.f textarea:focus,.f select:focus{outline:none;border-color:var(--red);box-shadow:var(--ring)}
.f select{appearance:none;-webkit-appearance:none;cursor:pointer;padding-right:34px;
  background-image:url("data:image/svg+xml;charset=UTF-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%239A938C' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 12px center}
.f .fld-err{border-color:var(--bad)}

/* form field groups — a labelled section break inside a .frm grid */
.fgroup{grid-column:1/-1;margin-top:8px}
.fgroup:first-child{margin-top:0}
.fgroup-t{display:flex;align-items:center;gap:9px;font-family:var(--font-display);font-size:11.5px;font-weight:700;
  letter-spacing:.09em;text-transform:uppercase;color:var(--red-600);white-space:nowrap}
.fgroup-t svg{width:15px;height:15px;flex:none}
.fgroup-t::after{content:"";flex:1;height:1px;background:var(--line);margin-left:2px}

/* toggle switch */
.switch{display:flex;align-items:center;gap:11px;cursor:pointer;user-select:none}
.switch input{position:absolute;opacity:0;width:0;height:0}
.switch .track{width:40px;height:23px;border-radius:var(--radius-pill);background:var(--neutral-bg);
  border:1px solid var(--line);position:relative;transition:.16s;flex:none}
.switch .track::after{content:"";position:absolute;top:2px;left:2px;width:17px;height:17px;border-radius:50%;
  background:#fff;box-shadow:0 1px 3px rgba(0,0,0,.25);transition:.16s}
.switch input:checked + .track{background:var(--red);border-color:var(--red)}
.switch input:checked + .track::after{transform:translateX(17px)}
.switch .st{font-size:13px;font-weight:600;color:var(--ink-2)}

/* role/multi checkboxes */
.checks{display:flex;flex-direction:column;gap:8px}
.check{display:flex;align-items:flex-start;gap:10px;padding:11px 13px;border:1px solid var(--line);
  border-radius:11px;cursor:pointer;transition:.12s}
.check:hover{border-color:rgba(45,41,38,.22);background:var(--card-2)}
.check.on{border-color:var(--red);background:var(--red-050)}
.check input{margin-top:2px;accent-color:var(--red);width:16px;height:16px;flex:none}
.check .ct{font-weight:600;font-size:13.5px}
.check .cs{font-size:11.5px;color:var(--ink-3);margin-top:2px}

/* inline message banner */
.msg{display:flex;align-items:center;gap:9px;font-size:13px;font-weight:500;
  border-radius:11px;padding:11px 14px;margin-bottom:16px}
.msg.error{background:var(--bad-bg);color:#a5262f}
.msg.ok{background:var(--ok-bg);color:#1c7a4f}
.msg.warn{background:var(--warn-bg);color:#8a5a10}
.msg .d{width:7px;height:7px;border-radius:50%;flex:none;background:currentColor}

/* ============ tabs ============ */
.tabs{display:flex;gap:4px;border-bottom:1px solid var(--line);margin-bottom:20px}
.tab{padding:11px 16px;font-size:13.5px;font-weight:600;color:var(--ink-3);position:relative;
  transition:.12s;border-radius:9px 9px 0 0}
.tab:hover{color:var(--ink-2)}
.tab.on{color:var(--ink)}
.tab.on::after{content:"";position:absolute;left:12px;right:12px;bottom:-1px;height:2.5px;
  border-radius:3px;background:var(--red)}
.tab .n{margin-left:7px;font-size:11px;padding:1px 7px;border-radius:var(--radius-pill);
  background:var(--neutral-bg);color:var(--ink-2)}

/* ============ pagination ============ */
.pager{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-top:16px;flex-wrap:wrap}
.pager .info{font-size:12.5px;color:var(--ink-3)}
.pager .pg{display:flex;align-items:center;gap:6px}
.pgbtn{min-width:34px;height:34px;padding:0 10px;border-radius:9px;display:grid;place-items:center;
  font-size:13px;font-weight:600;color:var(--ink-2);border:1px solid var(--line);background:var(--card);transition:.12s}
/* Excluir `.on`: si no, el hover le pisa el fondo oscuro y deja el texto blanco sobre papel. */
.pgbtn:hover:not(:disabled):not(.on){border-color:rgba(45,41,38,.22);background:var(--card-2)}
.pgbtn:disabled{opacity:.4;cursor:default}
.pgbtn.on{background:var(--char);color:#fff;border-color:var(--char)}
.pgbtn.on:hover{background:var(--char-900);border-color:var(--char-900)}
.pgbtn svg{width:15px;height:15px}

/* ============ empty state ============ */
.empty{display:flex;flex-direction:column;align-items:center;gap:10px;padding:48px 20px;text-align:center}
.empty .ei{width:48px;height:48px;border-radius:13px;display:grid;place-items:center;
  background:var(--neutral-bg);color:var(--ink-3)}
.empty .ei svg{width:24px;height:24px}
.empty .et{font-size:14px;color:var(--ink-3);max-width:360px}

/* expediente header card */
.exp-head{display:flex;align-items:flex-start;gap:18px;flex-wrap:wrap}
.exp-head .exp-id{width:56px;height:56px;border-radius:14px;flex:none;display:grid;place-items:center;color:#fff;
  font-family:var(--font-display);font-weight:700;font-size:20px;background:linear-gradient(150deg,var(--red),var(--red-600))}
.exp-meta{display:flex;flex-wrap:wrap;gap:18px;margin-top:12px}
.exp-meta .m .k{font-size:10.5px;letter-spacing:.06em;text-transform:uppercase;color:var(--ink-3)}
.exp-meta .m .v{font-size:13.5px;font-weight:600;color:var(--ink);margin-top:2px}

.spin{width:34px;height:34px;border-radius:50%;border:3px solid var(--line);border-top-color:var(--red);
  animation:spin .7s linear infinite;margin:44px auto}
@keyframes spin{to{transform:rotate(360deg)}}
@media (prefers-reduced-motion:reduce){.spin{animation:none}}

@media (max-width:640px){
  .frm{grid-template-columns:1fr}
  .f.col-2{grid-column:auto}
  .toolbar .right{margin-left:0;width:100%}
  .finput{min-width:0;flex:1}
}

/* --- UX polish (Gabriel feedback 2026-08-04) --- */
/* Never show a focus ring on programmatically-focused (tabindex=-1) elements */
[tabindex="-1"]:focus,[tabindex="-1"]:focus-visible{outline:none!important;box-shadow:none!important}
/* Keep Chrome/Safari autofilled inputs white (kill the blue/yellow autofill wash) */
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus,
input:-webkit-autofill:active{
  -webkit-box-shadow:0 0 0 1000px var(--card,#fff) inset!important;
  box-shadow:0 0 0 1000px var(--card,#fff) inset!important;
  -webkit-text-fill-color:var(--ink)!important;
  caret-color:var(--ink);
  transition:background-color 600000s 0s, color 600000s 0s;
}
