:root {
  /* Superficies: fondo blanco (rediseño 2026-09) y el «muted» de la plantilla
     animated-sidebar, en cálido. Lo hundido ya no es el fondo de la página:
     --sb-muted para píldoras, hover y segmentado; --col-bg para columnas y grupos. */
  --c-bg:#FFFFFF;--c-surface:#FFFFFF;--c-surface2:#F5F4F2;--c-sidebar:#FFFFFF;
  --sb-muted:#F1EFEC;--col-bg:#F8F7F5;
  --c-border:#ECEAE6;--c-border2:#DAD7D1;
  --c-text:#1C1B18;--c-text2:#6A6560;--c-text3:#5E5B57;--c-accent:#E8490A;--c-accent-bg:#FEF0EA;
  --c-green:#047857;--c-green-bg:#ECFDF5;--c-red:#DC2626;--c-warning:#B45309;
  --c-red-fill:#DC2626;--c-green-fill:#047857;--c-warning-fill:#B45309;--c-on-accent:#fff;   /* rellenos con texto blanco: no se aclaran en oscuro; on-accent = texto sobre el acento */
  --col-open:#9E9C94;--col-brief:#3B82F6;--col-preprod:#8B5CF6;--col-rodaje:#F59E0B;
  --col-edicion:#06B6D4;--col-revinterna:#EC4899;--col-pendiente:#F97316;--col-feedback:#EF4444;
  --col-editfb:#E8490A;--col-revinterna1:#D946EF;--col-pendiente2:#FB923C;--col-feedbackcli2:#DC2626;
  --col-revinterna2:#A855F7;--col-editfb2:#F43F5E;--col-color:#10B981;
  --col-postprod:#14B8A6;--col-master:#6366F1;--col-archivar:#6B6860;
  /* Estados de Budgo sin semántico propio (BUDGO_ESTADO_COLORS): punto, barra y serie del
     gráfico, ≥4:1 sobre blanco; las fichas mezclan el texto con tinta para llegar a AA */
  --budgo-enviado:#3A7BE8;--budgo-facturado:#8B5CF6;--budgo-preaprobado:#B45309;--budgo-cancelado:#A09C95;
  /* Radios: suben un escalón (8→10, 12→16) y aparece el de paneles y ventanas */
  --radius:10px;--radius-lg:16px;--radius-xl:20px;
  --shadow:0 1px 2px rgba(28,27,24,.05);
  --shadow-md:0 12px 32px -8px rgba(28,27,24,.20),0 2px 6px rgba(28,27,24,.05);
  --shadow-panel:0 28px 70px -18px rgba(28,27,24,.30),0 2px 6px rgba(28,27,24,.05);
  --font:'Inter',-apple-system,"system-ui","Segoe UI",Roboto,sans-serif;
  --font-mono:ui-monospace,'SF Mono','Fira Code',monospace;
  --tr:0.15s cubic-bezier(0.16,1,0.3,1);
  --ease-out:cubic-bezier(0.16,1,0.3,1);
  --ease-drawer:cubic-bezier(0.32,0.72,0,1);
  /* Los muelles de la plantilla (motion) como curvas linear() muestreadas de la
     física exacta: layout = k360 c32 m.6 (421 ms), morph = k380 c35 m.75 (413 ms) */
  --spring-layout:linear(0,0.068,0.205,0.353,0.487,0.6,0.692,0.764,0.821,0.864,0.897,0.922,0.941,0.956,0.966,0.975,0.981,0.986,0.989,0.992,0.994,0.995,0.997,0.997,1);
  --spring-morph:linear(0,0.058,0.18,0.318,0.449,0.564,0.66,0.738,0.799,0.847,0.884,0.913,0.934,0.951,0.963,0.972,0.979,0.985,0.988,0.991,0.994,0.995,0.996,0.997,1);
  /* Luz que sigue al cursor en los botones (--mx/--my los pone helpers.js) */
  --glint-sec:rgba(28,27,24,.06);--glint-fill:rgba(255,255,255,.24);
  /* El cambio de color de un hover, que es lo que anima casi todo. Sustituye a
     `transition:all`, que además de lo que quieres anima lo que no: anchos,
     alturas y filtros que cambian por otro motivo se ponen a interpolar solos. */
  --tr-colores:color var(--tr),background-color var(--tr),border-color var(--tr);

  /* ── Tracking ──
     El espaciado entre letras depende del tamaño: al crecer, las letras se
     leen demasiado sueltas y hay que apretarlas; al encoger, separarlas ayuda.
     Un valor fijo está mal en algún tamaño. En `em` para que acompañe siempre
     al tamaño del elemento que lo usa. */
  --tracking-display:-0.022em;  /* 28px y más: cifras y titulares grandes */
  --tracking-title:-0.014em;    /* 18-27px: títulos de ficha y de sección */
  --tracking-body:0;            /* 12-17px: texto corrido, no se toca */
  --tracking-small:0.02em;      /* 11px y menos: gana legibilidad separando */
  --tracking-caps:0.05em;       /* rótulos en mayúsculas, siempre sueltos */
}
/* ── Dark mode ── */
/* Semánticos con contraste AA sobre sus superficies (2026-09-19): verde 5,5:1 y ámbar 5,0:1 en claro; en oscuro verde 6,6:1, rojo 6,1:1, ámbar 5,3:1. El blanco sobre el acento (3,9:1) se queda: es la marca. */
body.dark{--c-green:#10B981;--c-red:#F87171;--c-warning:#D97706;--c-bg:#151411;--c-surface:#1E1D1A;--c-surface2:#262420;--c-sidebar:#151411;--sb-muted:#262420;--col-bg:#1A1917;
  --c-border:#2C2A25;--c-border2:#3C3A33;--c-text:#F0EDE8;--c-text2:#9A9590;--c-text3:#8C8985;--c-accent-bg:#281509;--c-green-bg:#0d1f17;
  --budgo-enviado:#60A5FA;--budgo-facturado:#A78BFA;   /* 7,3:1 y 6,8:1 sobre el fondo */
  --budgo-preaprobado:#FBBF24;--budgo-cancelado:#6B6862;
  --glint-sec:rgba(255,255,255,.07);--glint-fill:rgba(255,255,255,.6);
  --shadow:0 1px 2px rgba(0,0,0,.3);--shadow-md:0 12px 32px -8px rgba(0,0,0,.6);--shadow-panel:0 28px 70px -18px rgba(0,0,0,.7);color-scheme:dark}
/* Las paletas de usuario (themes.css) no traen los tokens de lo hundido: salen de
   las suyas. Van sobre body para resolverse con las variables de cada paleta. */
body[data-theme]{--sb-muted:color-mix(in srgb,var(--c-text) 7%,var(--c-surface));--col-bg:color-mix(in srgb,var(--c-text) 3%,var(--c-surface))}
body.dark .modal-overlay,body:is([data-theme=oceano],[data-theme=neon],[data-theme=terminal]) .modal-overlay{background:rgba(0,0,0,0.65)}
body.dark .form-input,body.dark .form-select,body.dark .form-textarea,body:is([data-theme=oceano],[data-theme=neon],[data-theme=terminal]) :is(.form-input,.form-select,.form-textarea){background:var(--c-surface2)}
.search-result-item:hover,.search-result-item.active{background:var(--sb-muted)}

*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
html,body{height:100%}
body{font-family:var(--font);background:var(--c-bg);color:var(--c-text);font-size:13px;line-height:1.5;-webkit-font-smoothing:antialiased;font-optical-sizing:auto;font-kerning:normal}
/* Rótulo de grupo: el de la barra lateral (pequeño, mayúsculas, suelto) */
.rotulo{font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.14em;color:var(--c-text3)}

/* ── Ventanas ──
   Entran y salen por el mismo camino y crecen desde el centro con el muelle.
   `allow-discrete` + @starting-style animan el display en los dos sentidos
   desde CSS: los 16 sitios que cierran quitando .open no esperan a nada. Sin
   soporte, aparecen y desaparecen de golpe. En móvil son hojas desde abajo. */
.modal-overlay{
  display:none;position:fixed;inset:0;z-index:1000;align-items:center;justify-content:center;padding:20px;
  background:rgba(20,19,17,.28);opacity:0;
  transition:opacity .2s var(--ease-out),display .2s var(--ease-out) allow-discrete;
}
.modal-overlay.open{display:flex;opacity:1}
/* Cada overlay tiene exactamente un hijo: la caja del diálogo. */
.modal-overlay>*{transform:translateY(6px) scale(.96);filter:blur(4px);transition:transform .421s var(--spring-layout),filter .2s var(--ease-out)}
.modal-overlay.open>*{transform:none;filter:none}
@starting-style{
  .modal-overlay.open{opacity:0}
  .modal-overlay.open>*{transform:translateY(6px) scale(.96);filter:blur(4px)}
}
/* Confirm dialog can be triggered from any modal (settings, template editor, popups up to z-index 4000) — must always win */
#confirm-overlay{z-index:5000}
.modal{width:520px;max-width:100%;max-height:90vh;overflow-y:auto;border:1px solid var(--c-border);border-radius:var(--radius-xl);background:var(--c-surface);box-shadow:var(--shadow-panel)}
.modal-header{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:18px 16px 0 22px}
.modal-title{font-size:16px;font-weight:700;letter-spacing:-0.01em}
.modal-close{display:grid;place-items:center;width:32px;height:32px;border:0;border-radius:9px;background:transparent;color:var(--c-text2);font-size:16px;cursor:pointer;transition:var(--tr-colores)}
.modal-close:hover{background:var(--sb-muted);color:var(--c-text)}
/* Cierre de ventana en icono Material «close»: arreglado en un sitio para los
   29 «✕» de texto que aún quedan en las ventanas (T4). Un .modal-close ya
   migrado a iconHtml('close') no lleva el pseudo-elemento encima (:has). Va en
   ::after, no en ::before: un modal-close que también es .btn-icon (el fondo
   redondo de hover) ya usa ::before para esa pastilla, y las dos reglas se
   mezclarían en el mismo pseudo-elemento (el icono heredaba su opacity:0 y
   position:absolute, y se quedaba invisible). */
.modal-close:not(:has(.material-symbols-rounded)){font-size:0}
.modal-close:not(:has(.material-symbols-rounded))::after{content:'close';font:400 20px/1 'Material Symbols Rounded';font-feature-settings:'liga'}
.modal-body{padding:16px 22px 6px}
.modal-body>:is(.aviso,.hint){margin-bottom:14px}
.modal-footer{display:flex;justify-content:flex-end;gap:8px;padding:12px 18px 18px}

/* ── Formularios ── campos de 36 px; foco con anillo suave del acento */
.form-group{margin-bottom:14px}
.form-label{display:block;margin-bottom:6px;font-size:12.5px;font-weight:500;color:var(--c-text2)}
.form-input,.form-select,.form-textarea{width:100%;height:36px;padding:0 12px;border:1px solid var(--c-border);border-radius:var(--radius);background:var(--c-surface);box-shadow:var(--shadow);
  font-family:var(--font);font-size:14px;color:var(--c-text);outline:none;transition:border-color .15s,box-shadow .15s}
.form-input:hover,.form-select:hover,.form-textarea:hover{border-color:var(--c-border2)}
.form-input:focus,.form-select:focus,.form-textarea:focus{border-color:var(--c-border2);box-shadow:0 0 0 4px color-mix(in srgb,var(--c-accent) 12%,transparent)}
.form-input::placeholder,.form-textarea::placeholder{color:var(--c-text3)}
.form-select{appearance:none;padding-right:34px;cursor:pointer;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12' fill='none' stroke='%238C8985' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 4.5l3 3 3-3'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 12px center}
.form-select.sel-barra{width:auto;height:34px}   /* select suelto en una barra (el periodo de Tiempo): mide lo que su texto */
.form-select[multiple]{height:auto;padding:6px 12px;background-image:none}
.form-textarea{height:auto;min-height:88px;padding:10px 12px;resize:vertical;line-height:1.5}
.form-row{display:grid;grid-template-columns:1fr 1fr;gap:12px}
.form-help{font-size:12px;color:var(--c-text3)}
.form-input.error,.form-select.error{border-color:var(--c-red);box-shadow:0 0 0 4px color-mix(in srgb,var(--c-red) 10%,transparent)}
.form-err{display:flex;align-items:center;gap:4px;font-size:12px;color:var(--c-red)}
.form-err .ic{font-size:15px}
/* Unidad al final: el recuadro es el contenedor, así cabe «€», «h» o «€/mes» */
.form-affix{display:flex;align-items:center;height:36px;border:1px solid var(--c-border);border-radius:var(--radius);background:var(--c-surface);box-shadow:var(--shadow);transition:border-color .15s,box-shadow .15s}
.form-affix:hover{border-color:var(--c-border2)}
.form-affix:focus-within{border-color:var(--c-border2);box-shadow:0 0 0 4px color-mix(in srgb,var(--c-accent) 12%,transparent)}
.form-affix:has(.error){border-color:var(--c-red);box-shadow:0 0 0 4px color-mix(in srgb,var(--c-red) 10%,transparent)}
.form-affix .form-input,.form-affix .form-input:focus,.form-affix .form-input.error{flex:1;min-width:0;height:100%;padding:0 6px 0 12px;border:0;background:transparent;box-shadow:none;text-align:right;font-variant-numeric:tabular-nums}
.form-affix>span{padding-right:12px;white-space:nowrap;font-size:13px;color:var(--c-text3)}
/* Interruptor: checkbox nativo por debajo */
.switch{display:inline-flex;align-items:center;gap:10px;cursor:pointer;font-size:13.5px;color:var(--c-text)}
.switch input{position:absolute;opacity:0;width:1px;height:1px}
.switch-t{position:relative;width:36px;height:22px;flex-shrink:0;border-radius:11px;background:var(--c-border2);transition:background .2s}
.switch-t::after{content:'';position:absolute;top:2px;left:2px;width:18px;height:18px;border-radius:50%;background:#fff;box-shadow:0 1px 3px rgba(0,0,0,.25);transition:transform .421s var(--spring-layout)}
.switch input:checked+.switch-t{background:var(--c-text)}
.switch input:checked+.switch-t::after{transform:translateX(14px);background:var(--c-bg)}   /* la pista encendida es tinta: el botón, el fondo, que contrasta en claro y en oscuro */
.switch input:focus-visible+.switch-t{outline:2px solid var(--c-accent);outline-offset:2px}
.switch input:disabled+.switch-t{opacity:.45;cursor:not-allowed}
.check{display:inline-flex;align-items:center;gap:8px;cursor:pointer;font-size:13.5px}
.check input{width:16px;height:16px;accent-color:var(--c-text);cursor:pointer}

/* ── Botones ──
   Principal en tinta; el coral (.btn-accent) queda para lo que no puede esperar
   (fichar). Como en iOS: al pulsar se hunden en 80 ms, en cuanto baja el dedo; al
   soltar vuelven con el muelle. Con ratón, una luz suave sigue al cursor. */
.btn,.btn-pill,.btn-pill-sec{position:relative;isolation:isolate;--glint:var(--glint-sec)}
.btn-primary,.btn-accent,.btn-danger-fill,.btn-pill{--glint:var(--glint-fill)}
.btn::after,.btn-pill::after,.btn-pill-sec::after{content:'';position:absolute;inset:-1px;z-index:-1;border-radius:inherit;pointer-events:none;opacity:0;
  background:radial-gradient(80px circle at var(--mx,50%) var(--my,50%),var(--glint),transparent 72%);transition:opacity .3s var(--ease-out)}
.btn{display:inline-flex;align-items:center;justify-content:center;gap:6px;height:36px;padding:0 14px;border:1px solid var(--c-border);border-radius:var(--radius);
  background:var(--c-surface);color:var(--c-text);font-family:var(--font);font-size:13px;font-weight:500;line-height:1;white-space:nowrap;cursor:pointer;box-shadow:var(--shadow);
  transition:background .2s var(--ease-out),border-color .2s var(--ease-out),color .2s var(--ease-out),filter .2s var(--ease-out),transform .421s var(--spring-layout)}
.btn .ic{font-size:17px;transition:transform .421s var(--spring-layout)}
.btn-sm{height:30px;padding:0 10px;border-radius:9px;font-size:12px}
.btn-primary,.btn-accent,.btn-danger-fill{border-color:transparent;box-shadow:none}
.btn-primary{background:var(--c-text);color:var(--c-bg)}
.btn-accent{background:var(--c-accent);color:var(--c-on-accent)}
.btn-danger-fill{background:var(--c-red-fill);color:#fff}
.btn-ghost{background:transparent;border-color:transparent;box-shadow:none;color:var(--c-text2)}
.btn-danger{color:var(--c-red)}
@media (hover:hover){
  .btn:hover{background:var(--c-surface2);border-color:var(--c-border2)}
  .btn-primary:hover{background:var(--c-text)} .btn-accent:hover{background:var(--c-accent)} .btn-danger-fill:hover{background:var(--c-red-fill)}
  .btn-ghost:hover{background:var(--sb-muted);border-color:transparent;color:var(--c-text)}
  .btn-danger:hover{background:color-mix(in srgb,var(--c-red) 7%,var(--c-surface));border-color:color-mix(in srgb,var(--c-red) 30%,transparent)}
  :is(.btn,.btn-pill,.btn-pill-sec):not(:disabled):hover::after{opacity:1}
  /* Un icono al final (Ver →) se adelanta un poco: dice hacia dónde va */
  :is(.btn,.btn-pill-sec):hover .ic:last-child:not(:first-child){transform:translateX(2px)}
}
.btn:active,.btn-pill:active,.btn-pill-sec:active{transform:scale(.97);transition-duration:.08s;transition-timing-function:ease-out}
:is(.btn-primary,.btn-accent,.btn-danger-fill,.btn-pill):active{filter:brightness(.9)}
.btn:disabled,.btn[aria-disabled=true]{opacity:.4;cursor:not-allowed;transform:none;filter:none}
/* Solo lectura (crmPanelSoloLectura…): el campo desactivado se lee, no parece editable */
.form-input:disabled::placeholder,.form-textarea:disabled::placeholder{color:transparent}   /* solo lectura: un campo vacío no invita a rellenarse */
:is(.form-input,.form-select,.form-textarea):disabled:disabled{background:transparent;border-color:transparent;box-shadow:none;resize:none;cursor:default}   /* :disabled doble: gana a .crm-grupo .form-* y a body.dark */
.form-affix:has(.form-input:disabled){background:transparent;border-color:transparent;box-shadow:none}
.form-select:disabled{background-image:none;padding-right:12px}
:is(.btn-icon,.chip):disabled{opacity:.4;cursor:default}
/* Botón de icono: el fondo crece desde el centro al pasar */
.btn-icon{position:relative;isolation:isolate;display:inline-grid;place-items:center;flex-shrink:0;width:32px;height:32px;border:0;border-radius:9px;background:transparent;color:var(--c-text2);cursor:pointer;
  transition:color .15s,transform .421s var(--spring-layout)}
.btn-icon::before{content:'';position:absolute;inset:0;z-index:-1;border-radius:inherit;background:var(--sb-muted);opacity:0;transform:scale(.7);
  transition:opacity .2s var(--ease-out),transform .421s var(--spring-layout)}
@media (hover:hover){.btn-icon:hover{color:var(--c-text)} .btn-icon:hover::before{opacity:1;transform:none}}
.btn-icon:active{transform:scale(.9);transition-duration:.08s}
.btn-icon:active::before{opacity:1;transform:none}
.btn-icon .material-symbols-rounded,.btn-icon .ic{font-size:19px}
/* Acciones de cabecera: ya no son píldoras; mismos botones, un poco más bajos */
.btn-pill,.btn-pill-sec{display:inline-flex;align-items:center;gap:6px;height:34px;padding:0 13px;border-radius:var(--radius);font-family:var(--font);font-size:13px;font-weight:600;white-space:nowrap;cursor:pointer;
  transition:background .2s var(--ease-out),border-color .2s var(--ease-out),filter .2s var(--ease-out),transform .421s var(--spring-layout)}
.btn-pill{border:0;background:var(--c-text);color:var(--c-bg)}
.btn-pill-sec{border:1px solid var(--c-border);background:var(--c-surface);color:var(--c-text);font-weight:500;box-shadow:var(--shadow)}
@media (hover:hover){.btn-pill-sec:hover{background:var(--c-surface2);border-color:var(--c-border2)}}
.btn-pill .ic,.btn-pill-sec .ic{font-size:17px;transition:transform .421s var(--spring-layout)}
.link-btn{border:0;background:none;padding:2px 0;font-family:var(--font);font-size:12.5px;font-weight:500;color:var(--c-text2);cursor:pointer;text-decoration:underline;text-decoration-color:var(--c-border2);text-underline-offset:3px;transition:color .15s,text-decoration-color .15s}
.link-btn:hover{color:var(--c-text);text-decoration-color:currentColor}

/* Assignee picker */
.assignee-picker{display:flex;flex-wrap:wrap;gap:8px}
.assignee-option{display:flex;align-items:center;gap:6px;padding:5px 10px;border:1px solid var(--c-border);border-radius:20px;cursor:pointer;font-size:13px;color:var(--c-text2);background:var(--c-surface);transition:var(--tr-colores)}
.assignee-option:hover{border-color:var(--c-border2);color:var(--c-text)}
.assignee-option.selected{border-color:var(--c-text);background:var(--c-text);color:var(--c-bg)}
.mini-avatar{width:18px;height:18px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:8px;font-weight:600;color:white}

/* Utilities */
/* Pantalla de carga: oculta salvo que haya sesión guardada (html.con-sesion, lo
   pone el script del principio de <body>) o que showScreen('loading') la enseñe;
   el estilo en línea de showScreen manda sobre estas dos reglas. */
.loading-screen{display:none;position:fixed;inset:0;z-index:9000;align-items:center;justify-content:center;flex-direction:column;gap:16px;background:var(--c-bg)}
html.con-sesion #auth-screen{display:none}
html.con-sesion .loading-screen{display:flex}
.loading-logo{border-radius:14px;animation:loading-latido 1.6s ease-in-out infinite}
@keyframes loading-latido{0%,100%{opacity:1}50%{opacity:.5}}
@media (prefers-reduced-motion: reduce){.loading-logo{animation:none}}
.loading-msg{margin:0;font-size:13px;color:var(--c-text2);text-align:center;max-width:280px}
.spinner{width:20px;height:20px;border:2px solid var(--c-border);border-top-color:var(--c-text);border-radius:50%;animation:spin .7s linear infinite}
@keyframes spin{to{transform:rotate(360deg)}}
.empty-col{display:flex;align-items:center;justify-content:center;padding:24px 12px;color:var(--c-text3);font-size:12px;text-align:center;border:1.5px dashed var(--c-border2);border-radius:var(--radius-lg)}
.coming-soon{display:flex;flex-direction:column;align-items:center;justify-content:center;height:400px;color:var(--c-text2);gap:12px}
.coming-soon h3{font-size:18px;letter-spacing:var(--tracking-title);font-weight:500}
.coming-soon p{font-size:13px;color:var(--c-text3)}

/* ── Primitivas de vista ─────────────────────────────────────────────────
   Compartidas por CRM, Budgo y los módulos del port (Fichaje, Finanzas, Oficina,
   KPIs, Status, 1:1, Comercial, Calendario, Ajustes). Documentadas en
   styleguide.html › «Primitivas de vista». Solo tokens: dark y paletas salen solos.
   Rediseño 2026-09 («lienzo abierto»): solo lleva caja lo que se coge o se abre
   (ventana, menú, toast, ficha de tablero). Las cifras van en fila con filete, la
   sección (.card) es título + contenido + aire, y para agrupar controles se usa un
   relleno sin borde (.card.relleno). Nunca caja dentro de caja; nunca borde +
   sombra + fondo a la vez. Por eso los bloques se separan a 36 px, no a 14. */
/* La vista: la cabecera arriba, a todo el ancho y pegada al desplazar; debajo, el
   contenido centrado a 1100 px (--vw-max). El contenedor que desplaza es la
   propia .view (#view-x), sin relleno: el aire lo pone .view-wrap. */
.view-wrap{width:100%;display:flex;flex-direction:column;gap:36px;padding-bottom:112px}   /* escritorio: el final sube por encima de la cápsula #dock (84 + 16 de margen) */
.view-wrap>*{width:min(var(--vw-max,1100px),100% - 64px);margin-inline:auto}
/* Un hijo directo de .view-wrap nunca se encoge: sin esto, cualquier vista con
   su propio scroll interno (Budgo: la lista se quedaba en 2px de alto) pierde
   su alto ante flex. */
.view-wrap>*{flex-shrink:0}
.view-body{display:flex;flex-direction:column;gap:36px}   /* cuerpo de pestaña (#fz-body, #ofn-body…): mismo ritmo que .view-wrap */
.view-body>:empty{display:none}                            /* un contenedor vacío (#rod-mis sin rodajes) no deja hueco */
.view-wrap>.card-h,.view-body>.card-h{margin-bottom:0}     /* cabecera de sección suelta (Tarjetas, Presupuesto): el gap ya separa */
/* Cabecera de vista (vistaHead, js/views.js): la barra de 56 px de arriba.
   Título y «?» (la explicación que antes iba debajo, en .view-sub) · pestañas ·
   acciones, en una fila; translúcida sobre lo que pasa por debajo. */
.view-head{position:sticky;top:0;z-index:30;display:flex;align-items:center;gap:12px;height:56px;padding:0 12px 0 16px;flex-shrink:0;
  border-bottom:1px solid var(--c-border);background:color-mix(in srgb,var(--c-bg) 86%,transparent);backdrop-filter:saturate(180%) blur(14px);-webkit-backdrop-filter:saturate(180%) blur(14px)}
.view-wrap>.view-head{width:100%}
.view-head-t{display:flex;align-items:center;gap:6px;min-width:0;flex-shrink:0}
.view-title{display:flex;align-items:center;gap:8px;margin:0;font-size:15px;font-weight:600;letter-spacing:-0.01em;line-height:1.3;white-space:nowrap;color:var(--c-text)}
.view-title .ic{font-size:20px;color:var(--mod-c,var(--c-text2));font-variation-settings:'FILL' 1,'wght' 500,'GRAD' 0,'opsz' 20}
.view-sub{display:none}
.view-sep{width:1px;height:20px;background:var(--c-border);flex-shrink:0}
.view-head>.vtabs{flex:0 1 auto}
.view-actions{margin-left:auto;display:flex;align-items:center;gap:8px;flex-shrink:0}
.view-toolbar{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}
/* Píldora que se desliza en .vtabs y .seg: la añade glideInit() (helpers.js).
   Sin ella las piezas se ven igual (fondo en .active/.on), solo que sin viajar. */
.glide{position:absolute;left:0;top:0;height:100%;border-radius:10px;pointer-events:none;z-index:0;opacity:0;
  transition:transform .421s var(--spring-layout),width .421s var(--spring-layout),opacity .2s}
/* Pestañas: texto y una píldora neutra que viaja; el número, en tinta */
.vtabs{position:relative;display:flex;align-items:center;gap:2px;min-width:0;overflow-x:auto;scrollbar-width:none}
.vtabs.desborda{mask-image:linear-gradient(90deg,#000 calc(100% - 32px),transparent)}   /* glideInit marca si no caben */
.vtabs::-webkit-scrollbar{display:none}
.vtabs>.glide{background:var(--sb-muted)}
.vtab{position:relative;z-index:1;display:inline-flex;align-items:center;gap:7px;height:32px;padding:0 12px;border:0;border-radius:10px;background:transparent;flex-shrink:0;
  font-family:var(--font);font-size:13.5px;font-weight:500;color:var(--c-text2);white-space:nowrap;cursor:pointer;transition:color .15s,background .15s,transform .421s var(--spring-layout)}
.vtab:hover,.vtab.active{color:var(--c-text)}
.vtab.active{background:var(--sb-muted)}
.vtabs:has(>.glide)>.vtab.active{background:transparent}
.vtab:active{transform:scale(.96);transition-duration:.08s}
.vtab .ic{font-size:18px;transition:font-variation-settings .2s}
.vtab.active .ic{font-variation-settings:'FILL' 1,'wght' 500,'GRAD' 0,'opsz' 20}
.vtab-n{display:inline-grid;place-items:center;min-width:18px;height:18px;padding:0 5px;border-radius:9px;background:var(--c-surface2);color:var(--c-text2);font-size:10.5px;font-weight:700;line-height:1;font-variant-numeric:tabular-nums}
.vtab.active .vtab-n{background:var(--c-text);color:var(--c-bg)}
.vtab-n.alerta,.vtab.active .vtab-n.alerta{background:var(--c-accent);color:var(--c-on-accent)}   /* el coral también en la pestaña activa */
/* Cifras: sin caja, en fila sobre el lienzo y separadas por un filete (como un
   informe). La alerta no se enmarca: se colorea. */
.tiles{display:flex;flex-wrap:wrap;align-items:stretch;row-gap:20px}   /* con poco ancho (barra lateral + 5 cifras) pasan a otra fila en vez de aplastarse */
.tile{flex:1 1 140px;min-width:0;padding:2px 24px 2px 0;container-type:inline-size}   /* contenedor: .tile-val baja de tamaño con su ancho */
.tile+.tile{padding-left:24px;border-left:1px solid var(--c-border)}
.tile:first-child{padding-right:48px}   /* mismo ancho útil que las demás: así todas las cifras de la fila bajan al mismo tamaño */
.tile.alerta .tile-lbl,.tile.alerta .tile-lbl .ic{color:var(--c-red)}
.tile.alerta .tile-lbl::before{content:'';width:6px;height:6px;border-radius:50%;background:currentColor;flex-shrink:0}
.tile-lbl{display:flex;align-items:center;gap:6px;margin-bottom:8px;font-size:12.5px;font-weight:500;color:var(--c-text2)}
.tile-lbl .ic{font-size:16px;color:var(--c-text3)}
.tile-val{white-space:nowrap;font-size:clamp(18px,18cqi,32px);font-weight:700;letter-spacing:-0.025em;line-height:1.1;font-variant-numeric:tabular-nums;color:var(--c-text)}
.tile-val.ok{color:var(--c-green)}
.tile-val.warn{color:var(--c-warning)}
.tile-val.bad{color:var(--c-red)}
.tile-val.acc{color:var(--c-accent)}
.tile-val small{font-size:14px;font-weight:500;letter-spacing:0;color:var(--c-text3)}
.tile-sub{display:flex;align-items:center;gap:6px;flex-wrap:wrap;margin-top:8px;font-size:12px;color:var(--c-text3)}
.tile-sub>span{display:block}   /* varias líneas de subtexto (Budgo: «↑ vs mes» y «Faltan…»), una por línea */
.tile-sub .up,.tile-sub .down{display:inline-flex;align-items:center;gap:2px;height:20px;padding:0 6px;border-radius:6px;font-weight:600;font-variant-numeric:tabular-nums}
.tile-sub .up{background:color-mix(in srgb,var(--c-green) 12%,transparent);color:var(--c-green)}
.tile-sub .down{background:color-mix(in srgb,var(--c-red) 10%,transparent);color:var(--c-red)}
.tile-barra{height:6px;margin-top:10px;border-radius:3px;background:var(--c-surface2);overflow:hidden}   /* avance hacia un objetivo */
.tile-barra i{display:block;height:100%;border-radius:3px;background:var(--c-text);transform-origin:left;animation:barra .7s var(--ease-out) backwards}
@keyframes barra{from{transform:scaleX(0)}}
/* Sección: .card deja de ser una caja. .card.relleno agrupa con un fondo gris,
   sin borde, como los grupos de Ajustes de iOS. */
.card{min-width:0;padding:0;border:0;border-radius:0;background:transparent}
.card.relleno{padding:14px 18px 16px;border-radius:var(--radius-lg);background:var(--col-bg)}
.card-h{display:flex;align-items:center;gap:8px;min-height:32px;margin-bottom:8px}
.card-h .section-title,.card-h h3{margin:0;padding:0;border:0;font-size:15px;font-weight:600;letter-spacing:-0.01em;text-transform:none;color:var(--c-text);cursor:default;user-select:text}
.card-h .section-title:active{opacity:1}
.card-h-r{margin-left:auto;display:flex;gap:6px;align-items:center}
/* Bloques dentro de una sección: se apilan a 12px (el margen colapsa con el de .card-h) */
.card>*+:is(.tiles,.aviso,.tabla-wrap){margin-top:12px}
.card>:is(.tiles,.aviso,.tabla-wrap)+.hint{margin-top:10px}
/* Rejilla de secciones: dos o tres a la par, con calle ancha en vez de marcos */
.secciones{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:36px 48px;align-items:start}
/* Filas de lista: filete entre filas, nunca alrededor */
.filas{display:flex;flex-direction:column}
.fila{display:flex;align-items:center;gap:12px;min-height:48px;padding:6px 0;border-top:1px solid var(--c-border)}
.fila:last-child{border-bottom:1px solid var(--c-border)}
.fila .hint{font-variant-numeric:tabular-nums}
.fila .hint:not(:has(~.hint)){margin-left:auto}   /* solo el último (la fecha): la nota va pegada a su enlace */
.card.relleno .fila{border-color:color-mix(in srgb,var(--c-border2) 60%,transparent)}
.card.relleno .fila:first-child{border-top:0}
.card.relleno .fila:last-child{border-bottom:0}
/* Segmentado: hueco gris, la opción marcada en blanco con sombra */
.seg{position:relative;display:inline-flex;align-items:center;gap:2px;padding:3px;border-radius:12px;background:var(--sb-muted)}
.seg>.glide{top:3px;height:calc(100% - 6px);border-radius:9px;background:var(--c-surface);box-shadow:0 1px 3px rgba(28,27,24,.12)}
.seg-b{position:relative;z-index:1;display:inline-flex;align-items:center;justify-content:center;gap:6px;height:30px;padding:0 12px;border:0;border-radius:9px;background:transparent;
  font-family:var(--font);font-size:12.5px;font-weight:600;color:var(--c-text2);white-space:nowrap;cursor:pointer;transition:color .15s,transform .421s var(--spring-layout)}
.seg-b:hover,.seg-b.on{color:var(--c-text)}
.seg-b.on{background:var(--c-surface);box-shadow:0 1px 3px rgba(28,27,24,.12)}
.seg:has(>.glide)>.seg-b.on{background:transparent;box-shadow:none}
.seg-b:active{transform:scale(.95);transition-duration:.08s}
.seg-b:disabled{opacity:.35;cursor:not-allowed}
:is(.view-body,.view-wrap)>.seg{align-self:flex-start}   /* hijo directo de una columna flex: no se estira a todo el ancho */
.seg-b .ic{font-size:17px}
/* Filtros: contorno fino; el activo, en tinta */
.filtros{display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.filtro{display:inline-flex;align-items:center;gap:5px;height:30px;padding:0 12px;border:1px solid var(--c-border);border-radius:15px;background:var(--c-surface);
  font-family:var(--font);font-size:12.5px;font-weight:500;color:var(--c-text2);white-space:nowrap;cursor:pointer;transition:background .15s,border-color .15s,color .15s,transform .421s var(--spring-layout)}
.filtro:hover{border-color:var(--c-border2);color:var(--c-text)}
.filtro:active{transform:scale(.95);transition-duration:.08s}
.filtro.activo{background:var(--c-text);border-color:var(--c-text);color:var(--c-bg)}
.filtro .ic{font-size:16px}
.filtro-n{font-size:11px;font-weight:600;opacity:.6;font-variant-numeric:tabular-nums}
/* Buscador: hueco gris que se vuelve campo al enfocarlo */
.buscador{display:flex;align-items:center;gap:6px;height:34px;width:220px;padding:0 10px;border-radius:var(--radius);background:var(--sb-muted);color:var(--c-text3);transition:background .15s,box-shadow .15s}
.buscador:focus-within{background:var(--c-surface);box-shadow:0 0 0 1px var(--c-border2),0 0 0 4px color-mix(in srgb,var(--c-accent) 12%,transparent)}
.buscador .ic{font-size:18px}
.buscador input{flex:1;min-width:0;border:0;outline:0;background:transparent;font-family:var(--font);font-size:13px;color:var(--c-text)}
.proy-buscador{width:280px;flex-shrink:0}   /* proyectos: nombres largos (en móvil, .buscador ocupa todo el ancho) */
/* Selector de proyecto con búsqueda (proyComboHtml): la lista cuelga del campo */
.proy-combo{position:relative}
.proy-combo>.menu{top:calc(100% + 4px);left:0;right:0;max-height:260px;overflow-y:auto;width:auto;min-width:240px}
.hint{font-size:12px;color:var(--c-text3)}
.cargando{padding:30px 0;text-align:center;color:var(--c-text3);font-size:13px}
.empty-state{display:flex;flex-direction:column;align-items:center;gap:4px;padding:44px 24px;text-align:center;font-size:13px;color:var(--c-text3)}
.empty-state>.ic{display:grid;place-items:center;width:44px;height:44px;margin-bottom:8px;border-radius:14px;background:var(--sb-muted);font-size:22px;color:var(--c-text2);vertical-align:0}
.empty-state-t{display:block;font-size:15px;font-weight:600;color:var(--c-text);text-wrap:balance}
.empty-state-act{margin-top:12px}
.skel{display:block;border-radius:8px;background:linear-gradient(90deg,var(--c-surface2) 30%,var(--sb-muted) 50%,var(--c-surface2) 70%);background-size:300% 100%;animation:skel 1.4s ease-in-out infinite}
@keyframes skel{from{background-position:100% 0}to{background-position:0 0}}
/* Avisos: sin borde; fondo teñido y el icono del color */
.aviso{display:flex;gap:12px;align-items:flex-start;padding:12px 14px;border:0;border-radius:12px;background:var(--sb-muted);font-size:13px;line-height:1.5;color:var(--c-text)}
.aviso>.ic{flex-shrink:0;margin-top:1px;font-size:19px;color:var(--c-text2)}
.aviso b{font-weight:600}
.aviso.ok{background:color-mix(in srgb,var(--c-green) 9%,var(--c-surface))}
.aviso.ok>.ic{color:var(--c-green)}
.aviso.warn{background:color-mix(in srgb,var(--c-warning) 10%,var(--c-surface))}
.aviso.warn>.ic{color:var(--c-warning)}
.aviso.bad{background:color-mix(in srgb,var(--c-red) 8%,var(--c-surface))}
.aviso.bad>.ic{color:var(--c-red)}
.aviso-acc{display:flex;gap:6px;flex-wrap:wrap;margin-top:8px}
/* Fichas y contadores: .chip y .badge generalizan los estados y contadores sueltos */
.chip{display:inline-flex;align-items:center;gap:6px;height:22px;padding:0 8px 0 7px;border-radius:7px;white-space:nowrap;font-size:11.5px;font-weight:600;
  background:color-mix(in srgb,var(--c,var(--c-text3)) 12%,transparent);color:var(--c,var(--c-text2))}
.chip i{width:6px;height:6px;border-radius:50%;background:currentColor;flex-shrink:0}
.chip.neutro{background:var(--c-surface2);color:var(--c-text2)}
.chip.neutro i{background:var(--c,var(--c-text3))}
.chip.hueco i{background:transparent;box-shadow:inset 0 0 0 1.5px currentColor}
.chip.sm{height:18px;padding:0 6px 0 5px;font-size:10.5px}
button.chip{border:0;font-family:inherit;cursor:pointer}   /* un chip que es botón: sin el borde ni la letra del navegador */
button.chip:disabled{cursor:default}
.badge{display:inline-grid;place-items:center;min-width:18px;height:18px;padding:0 5px;border-radius:9px;background:var(--c-accent);color:var(--c-on-accent);font-size:10.5px;font-weight:700;font-variant-numeric:tabular-nums}
.badge.tinta{background:var(--c-text);color:var(--c-bg)}
.badge.suave{background:var(--c-surface2);color:var(--c-text2)}
.avatars{display:inline-flex}
.avatar{position:relative;width:24px;height:24px;border-radius:50%;display:inline-grid;place-items:center;flex-shrink:0;font-size:9px;font-weight:700;color:#fff;font-style:normal;box-shadow:0 0 0 2px var(--c-surface)}
.avatars>.avatar+.avatar{margin-left:-6px}
.avatar.grande{width:36px;height:36px;font-size:12px}
.avatar-est{position:absolute;right:-2px;bottom:-2px;width:9px;height:9px;border-radius:50%;background:var(--est-c);box-shadow:0 0 0 2px var(--c-surface)}
/* Menú desplegable: uno para todos los «⋮» */
/* Punto en el botón que abre un menú de filtros cuando hay alguno puesto (Budgo, Finanzas › Proyectos) */
.btn-icon[data-menu].activo::after{content:'';position:absolute;top:6px;right:6px;width:7px;height:7px;border-radius:50%;background:var(--c-accent);box-shadow:0 0 0 2px var(--c-bg)}
.menu{position:absolute;z-index:600;min-width:210px;width:max-content;max-width:calc(100vw - 32px);padding:5px;border:1px solid var(--c-border);border-radius:14px;background:var(--c-surface);box-shadow:var(--shadow-md);
  transform-origin:top right;animation:menuIn .2s var(--ease-out)}
@keyframes menuIn{from{opacity:0;transform:translateY(-4px) scale(.96);filter:blur(3px)}}
.menu-i{display:flex;align-items:center;gap:10px;width:100%;min-height:34px;padding:6px 10px;line-height:1.35;border:0;border-radius:9px;background:transparent;text-align:left;cursor:pointer;
  font-family:var(--font);font-size:13.5px;color:var(--c-text);transition:background .12s}
.menu-i:hover,.menu-i:focus-visible{background:var(--sb-muted);outline:none}
.menu-i .ic{font-size:18px;color:var(--c-text2)}
.menu-i>.ic{width:18px;flex:none}   /* también el hueco vacío que alinea el texto con los que llevan icono */
.menu-i kbd{margin-left:auto;flex-shrink:0}   /* min-height, no height: un nombre largo baja de línea sin pisar la fila siguiente */
.menu-i>:is(.ic,.hint):last-child:not(:first-child){margin-left:auto}   /* la marca de elegido, a la derecha */
.menu-i.peligro,.menu-i.peligro .ic{color:var(--c-red)}
.menu-i.marcado::after{content:'check';font-family:'Material Symbols Rounded';margin-left:auto;font-size:18px;color:var(--c-text)}   /* opción elegida (el menú cuelga de body)  */
.menu-sep{height:1px;margin:5px 6px;background:var(--c-border)}
.menu .rotulo{display:block;padding:8px 10px 4px}   /* en bloque: si no, el ancho del menú suma rótulo y selects (947 px en KPIs) */
.menu>.form-select{display:block}
/* Ayuda contextual: botón «?» (ayudaHtml) → popover #ayuda-pop (initAyuda, helpers.js) */
.ayuda{display:inline-grid;place-items:center;width:22px;height:22px;padding:0;border:0;border-radius:50%;background:transparent;color:var(--c-text3);cursor:pointer;vertical-align:middle;flex-shrink:0;transition:background .15s,color .15s}
.ayuda .ic{font-size:17px;vertical-align:0}
.ayuda:hover,.ayuda[aria-expanded="true"]{background:var(--sb-muted);color:var(--c-text)}
#ayuda-pop{position:fixed;z-index:6000;max-width:320px;padding:10px 12px;border:1px solid var(--c-border);border-radius:12px;background:var(--c-surface);box-shadow:var(--shadow-md);
  font-size:12.5px;line-height:1.5;color:var(--c-text);white-space:pre-line;transform-origin:top left;animation:menuIn .18s var(--ease-out)}
/* [hidden] gana al display propio de las primitivas (si no, un .btn-pill-sec[hidden] se ve como píldora vacía) */
:is(.view-actions,.view-toolbar,.vtabs,.vtab,.tiles,.tile,.card,.aviso,.hint,.tabla-wrap,.seg,.seg-b,.filtros,.filtro,.btn-pill,.btn-pill-sec,.link-btn,.btn,.btn-icon,.menu,.chip,.badge,.avatar,.avatars,.fila,.filas,.secciones,.desp,.empty-state,.buscador)[hidden]{display:none}
/* Tabla: cabecera sin fondo, filas altas, números a la derecha */
.tabla-wrap{overflow-x:auto;-webkit-overflow-scrolling:touch}
.tabla{width:100%;border-collapse:collapse;font-size:13px}
.tabla th{height:36px;padding:0 12px;border-bottom:1px solid var(--c-border);background:transparent;text-align:left;white-space:nowrap;font-size:11.5px;font-weight:500;color:var(--c-text3)}
.tabla td{height:42px;padding:0 12px;border-bottom:1px solid var(--c-border);vertical-align:middle;color:var(--c-text)}
.tabla tbody tr{transition:background .12s}
.tabla tbody tr:hover td{background:color-mix(in srgb,var(--sb-muted) 60%,transparent)}
.tabla tbody tr:last-child td{border-bottom:0}
.tabla-n{text-align:right;white-space:nowrap;font-variant-numeric:tabular-nums}
.tabla th.tabla-n{text-align:right}
.tabla td.tabla-sang{padding-left:30px;color:var(--c-text2)}
.tabla .tabla-grp td{background:var(--col-bg);font-weight:600}
.tabla .tabla-tot td{border-top:1px solid var(--c-border2);font-weight:700}
/* Tablas anchas (P&L): la primera columna se queda quieta al deslizar; con filete
   mientras hay algo debajo (.desliza lo pone helpers.js) */
.tabla-wrap .tabla :is(th,td):first-child{position:sticky;left:0;z-index:1;background:var(--c-bg)}
.card.relleno .tabla-wrap .tabla :is(th,td):first-child,.tabla-wrap .tabla .tabla-grp td:first-child{background:var(--col-bg)}
.tabla-wrap .tabla tbody tr:hover td:first-child{background:color-mix(in srgb,var(--sb-muted) 60%,var(--c-surface))}
.tabla-wrap.desliza .tabla :is(th,td):first-child{box-shadow:1px 0 0 var(--c-border)}
.tabla .neg{color:var(--c-red)}
.tabla .muted{color:var(--c-text3)}
/* Desplegable de fila (.desp, portado de .claude/mockups/finanzas.html): filete
   arriba y en la última fila, resumen de 56px con icono/hint/chevron que gira.
   Sustituye a .mc-detalle y a los desplegables sueltos de Caja. */
.desp{border-top:1px solid var(--c-border)}
.desp:last-child{border-bottom:1px solid var(--c-border)}
.desp summary{display:flex;align-items:center;gap:10px;min-height:56px;cursor:pointer;list-style:none;font-family:var(--font);font-size:15px;font-weight:600;color:var(--c-text)}
.desp summary::-webkit-details-marker{display:none}
.desp summary .ic{font-size:20px;color:var(--c-text3);vertical-align:0}
.desp summary .hint{font-weight:400}
.desp .desp-chev{margin-left:auto;font-size:20px;color:var(--c-text3);transition:transform .421s var(--spring-layout)}
.desp[open] .desp-chev{transform:rotate(180deg)}
.desp-b{padding:0 0 22px}
/* Variante compacta: dentro de una .card el filete de la sección ya separa */
.card .desp summary{min-height:44px;font-size:13.5px}
.card .desp-b{padding:0 0 16px}
@media (max-width: 768px), ((hover: none) and (pointer: coarse) and (max-width: 1400px)) {
  /* Dedos de 44 px; pestañas y filtros en una fila que se desliza; cifras de dos en dos */
  .view-wrap{padding-bottom:48px}   /* en móvil no hay dock: la barra inferior pone su hueco */
  .view-wrap>*{width:calc(100% - 28px)}
  .view-head{position:static;height:auto;flex-wrap:wrap;gap:8px;padding:6px 14px 8px;border-bottom:0;background:none;backdrop-filter:none;-webkit-backdrop-filter:none}
  .view-head-t{width:100%}
  .view-sep{display:none}
  .view-head>.vtabs{flex:0 0 calc(100% + 28px);margin:0 -14px;padding:0 14px}   /* con 1 1 100% y el margen negativo cabía junto al título y lo tapaba: así ocupa justo una fila */
  .view-actions{margin-left:0;width:100%}
  /* Si en la fila de acciones no queda nada con texto (solo el ⋮ o iconos: lo demás está
     escondido o es el botón flotante), los iconos suben a la fila del título y no gastan 44 px */
  .view-head:not(:has(>.view-actions>:is(.btn,.btn-pill,.btn-pill-sec,.seg):not(.fab-movil):not([hidden])))>.view-head-t{width:auto;flex:1;min-width:0}
  .view-head:not(:has(>.view-actions>:is(.btn,.btn-pill,.btn-pill-sec,.seg):not(.fab-movil):not([hidden])))>.view-actions{width:auto}
  .view-head:not(:has(>.view-actions>:is(.btn,.btn-pill,.btn-pill-sec,.seg):not(.fab-movil):not([hidden])))>.vtabs{order:1}
  .view-actions>.btn-pill,.view-actions>.btn-pill-sec{flex:1;justify-content:center;height:44px}
  .vtab{height:38px}
  .btn{height:44px} .btn-sm{height:36px}
  .btn-icon{width:44px;height:44px}
  .filtros{flex-wrap:nowrap;overflow-x:auto;-webkit-overflow-scrolling:touch;scrollbar-width:none;margin:0 -14px;padding:0 14px}
  .filtros:has(.buscador){flex-wrap:wrap;overflow:visible;margin:0;padding:0}   /* con buscador, el resto de controles bajan (la tira se llevaba el periodo fuera de pantalla y recortaba el combo) */
  .filtro{height:38px;flex-shrink:0}
  .buscador{width:100%;height:44px}
  .card-h>.buscador:first-child{flex:1 1 0;width:auto;min-width:0}   /* barra de buscador + filtros (Registro de tiempo): en una fila, como en CRM */
  .tiles{display:grid;grid-template-columns:1fr 1fr;gap:20px 0}
  .tile,.tile+.tile,.tile:first-child{padding:2px 16px 2px 0;border-left:0}
  .tile:nth-child(even){padding-left:16px;border-left:1px solid var(--c-border)}
  .tiles>.tile:last-child:nth-child(odd){grid-column:1 / -1}   /* con 3 o 5 tiles, la última a todo el ancho, no sola a la mitad */
  .tile-val{font-size:clamp(18px,15cqi,26px)}   /* sin partir la cifra (nowrap): baja con el ancho de la tile */
  .secciones{gap:32px}
  .card-h{flex-wrap:wrap}   /* los controles de la cabecera (input, segmentado, botón) bajan de línea; el título no se estruja */
  .card-h-r:has(:is(.seg,.buscador)){flex-basis:100%;margin-left:0}
  .card-h-r:has(.buscador){flex-wrap:wrap}
  .card-h-r>.proy-buscador{flex-shrink:1;min-width:0}
  .seg{display:flex;width:100%}
  .seg-b{flex:1;height:38px}
  .seg.seg-ic{display:inline-flex;width:auto}   /* solo iconos (Tablero/Lista, Calendario/Lista): no se estira */
  .seg.seg-ic .seg-b{flex:0 0 44px}
  .form-input,.form-select,.form-affix{height:44px;font-size:16px}
  .form-textarea{font-size:16px}
  /* Todos los campos a 16px, para que iOS no haga zoom al enfocar: cubre los
     inputs propios de cada módulo, no solo .form-input. !important porque las
     reglas de módulo se cargan después y algún input lleva estilo en línea. */
  :is(input:not([type=checkbox],[type=radio],[type=range],[type=color]),select,textarea){font-size:16px!important}
  .form-row{grid-template-columns:1fr;row-gap:0}
  .aviso-acc>.btn,.aviso-acc>.btn-pill-sec{flex:1;justify-content:center}   /* acciones de un aviso: a todo el ancho, como .view-actions */
  #ayuda-pop{max-width:calc(100vw - 32px)}
  .tabla td{height:46px}
  .tabla-wrap table{min-width:max-content}   /* se desliza solo si de verdad no cabe */
  .modal-overlay{align-items:flex-end;padding:0}
  .modal{width:100%;max-height:92dvh;border-radius:22px 22px 0 0;padding-bottom:var(--safe-bottom,0px)}
  .modal-overlay>*{transform:translateY(100%);filter:none;transition:transform .36s var(--ease-drawer)}
  @starting-style{.modal-overlay.open>*{transform:translateY(100%);filter:none}}
  .modal-footer .btn{flex:1}
  /* Zona táctil de 44px en la «?», sin agrandar el icono visible */
  .ayuda{position:relative}
  .ayuda::after{content:'';position:absolute;inset:-11px}
  /* Botón flotante único del móvil: 56×56 redondo, en tinta, sobre la pill,
     solo el icono. Especificidad suficiente para ganar a
     .view-actions>.btn-pill{height:44px;gap:6px}, que si no deja el FAB
     ovalado y el icono descentrado por el hueco del texto y el gap. */
  .fab-movil,.view-actions>.btn-pill.fab-movil{position:fixed;right:16px;bottom:calc(var(--safe-bottom,0px) + var(--mtabbar-h,60px) + 26px);z-index:305;width:56px;height:56px;padding:0;border:0;border-radius:50%;background:var(--c-text);color:var(--c-bg);font-size:0;box-shadow:var(--shadow-md)}
  .fab-movil>:not(.ic):not(.material-symbols-rounded){display:none}
  /* El icono se centra solo, con inset:0: así da igual cómo el botón reparta
     sus hijos (flex de .btn-pill, o lo que quede sin migrar) y da igual el
     texto suelto que no se puede seleccionar con CSS (un nodo de texto, no un
     span) — con font-size:0 no se ve, pero seguía contando como hijo en un
     grid y descentraba el icono en vertical. */
  .fab-movil :is(.ic,.material-symbols-rounded){position:absolute;inset:0;display:grid;place-items:center;font-size:28px}
  .fab-movil:active{transform:scale(.92)}
  body:has(.view.active .fab-movil:not([hidden])) .view-wrap{padding-bottom:120px}   /* hueco al pie: el FAB (56 + 26 sobre la barra) no tapa lo último */
  .modal-close{position:relative}
  .modal-close::before{content:'';position:absolute;inset:-6px}   /* zona táctil de 44 px sin crecer a la vista */
  /* Una fila de acciones cuyo único botón es el flotante no ocupa sitio en la cabecera */
  .view-actions:not(:has(>:not(.fab-movil,[hidden]))){display:contents}
}

/* ── Toasts ── abajo en el centro: la esquina derecha es de avisos y buzón.
   pointer-events:none en el contenedor y en el toast: si una tarjeta del
   tablero queda debajo, no se bloquea su drag/click. El botón de acción
   (Deshacer) recupera pointer-events. */
#toast-container{position:fixed;left:50%;bottom:20px;z-index:9999;display:flex;flex-direction:column;align-items:center;gap:8px;transform:translateX(-50%);pointer-events:none}
/* Icono en línea con el texto (iconHtml en helpers.js) */
.ic{font-size:1.2em;line-height:1;vertical-align:-0.24em}
.toast{display:flex;align-items:center;gap:10px;min-height:44px;padding:0 8px 0 14px;border-radius:14px;background:var(--c-text);color:var(--c-bg);font-size:13.5px;font-weight:500;
  box-shadow:0 14px 34px -10px rgba(0,0,0,.4);pointer-events:none;animation:toastIn .421s var(--spring-layout)}
.toast:not(:has(.toast-action-btn)){padding-right:16px}
.toast>.ic{font-size:18px;vertical-align:0}
.toast.success>.ic{color:color-mix(in srgb,#10B981 75%,var(--c-bg))} .toast.error>.ic{color:color-mix(in srgb,#EF4444 75%,var(--c-bg))}
.toast.chat{background:var(--c-surface);color:var(--c-text);border:1px solid var(--c-border)}
.toast-action-btn{height:30px;padding:0 10px;border:0;border-radius:9px;background:color-mix(in srgb,var(--c-bg) 16%,transparent);color:inherit;font-family:var(--font);font-size:12.5px;font-weight:600;cursor:pointer;flex-shrink:0;pointer-events:auto;transition:background .15s}
.toast-action-btn:hover{background:color-mix(in srgb,var(--c-bg) 26%,transparent)}
@keyframes toastIn{from{opacity:0;transform:translateY(14px) scale(.96);filter:blur(4px)}}
/* Salida animada (showToast, helpers.js): el toast ya no desaparece de golpe */
.toast.sale{animation:toastOut .18s var(--ease-out) forwards}
@keyframes toastOut{to{opacity:0;transform:translateY(6px) scale(.97);filter:blur(3px)}}
@media (max-width: 768px), ((hover: none) and (pointer: coarse) and (max-width: 1400px)) {
  #toast-container{bottom:calc(var(--safe-bottom,0px) + 86px);width:calc(100% - 28px)}
  .toast{width:100%}
  /* Con el FAB visible, los toasts suben para no quedar debajo. Acotado a la
     vista activa: un FAB de otra vista (display:none, sin [hidden]) no debe
     subir los toasts en todas las demás. */
  body:has(.view.active .fab-movil:not([hidden]):not(body.ro-tablero .proy-nuevo)) #toast-container{bottom:calc(var(--safe-bottom,0px) + 152px)}
}

/* Focus rings — keyboard nav only */
:focus-visible{outline:2px solid var(--c-accent);outline-offset:2px}
.form-input:focus-visible,.form-select:focus-visible,.form-textarea:focus-visible{outline:none}

/* Scrollbar */
::-webkit-scrollbar{width:6px;height:6px}
::-webkit-scrollbar-track{background:transparent}
::-webkit-scrollbar-thumb{background:var(--c-border2);border-radius:3px}

@keyframes pulse{0%,100%{opacity:1}50%{opacity:0.3}}

/* ── Confirm dialog ── */
.confirm-modal{display:flex;flex-direction:column;align-items:center;gap:10px;width:360px;max-width:calc(100vw - 32px);padding:26px 22px 20px;border:1px solid var(--c-border);border-radius:var(--radius-xl);
  background:var(--c-surface);box-shadow:var(--shadow-panel);text-align:center}
.confirm-icon-wrap{display:flex;align-items:center;justify-content:center;flex-shrink:0;width:44px;height:44px;border-radius:14px;background:color-mix(in srgb,var(--c-red) 10%,transparent);color:var(--c-red)}
.confirm-icon-wrap .ic{font-size:22px}
.confirm-icon-wrap .confirm-ic-normal{display:none;font-size:22px}
.confirm-icon-wrap.normal{background:var(--sb-muted);color:var(--c-text)}
.confirm-icon-wrap.normal .confirm-ic-danger{display:none}
.confirm-icon-wrap.normal .confirm-ic-normal{display:block}
.confirm-title{margin:4px 0 0;font-size:15.5px;font-weight:700;line-height:1.35;color:var(--c-text);text-align:center}
.confirm-body{margin:0;font-size:13px;line-height:1.5;color:var(--c-text2);text-align:center}
.confirm-actions{display:flex;gap:8px;width:100%;margin-top:10px}
.confirm-actions .btn{flex:1;justify-content:center}

/* ── Shortcuts modal ─────────────────────────────────────────────────────────── */
.shortcuts-modal{background:var(--c-surface);border:1px solid var(--c-border);border-radius:var(--radius-xl);width:360px;max-width:calc(100vw - 32px);box-shadow:var(--shadow-panel);overflow:hidden}
.shortcuts-header{display:flex;align-items:center;justify-content:space-between;padding:16px 16px 12px}
.shortcuts-body{padding:0 16px 16px;display:flex;flex-direction:column;gap:16px}
.shortcuts-group{display:flex;flex-direction:column;gap:4px}
.shortcuts-group-label{font-size:11px;font-weight:600;color:var(--c-text3);text-transform:uppercase;letter-spacing:var(--tracking-caps);margin-bottom:4px}
.shortcuts-row{display:flex;align-items:center;gap:12px;padding:3px 0;font-size:13px;color:var(--c-text2)}
.shortcuts-row span:last-child{flex:1}
.shortcuts-combo{display:flex;gap:3px;min-width:44px}
kbd{display:inline-flex;align-items:center;justify-content:center;min-width:22px;height:22px;padding:0 6px;background:var(--c-surface);border:1px solid var(--c-border);border-radius:6px;font-family:var(--font);font-size:11px;font-weight:600;color:var(--c-text2);flex-shrink:0}

@media (pointer:coarse){
  .btn-icon{width:44px;height:44px}
}
/* ── Respuesta al pulsar ───────────────────────────────────────────────────
   De 212 elementos con `cursor:pointer`, 155 reaccionaban al ratón y solo 21
   al dedo. En una pantalla táctil no hay hover, así que la mayor parte de la
   app no daba señal de haber recibido el toque — y seis de ellos además
   anulaban el resalte por defecto de iOS sin poner nada en su lugar.

   Va en `opacity`, no en `transform:scale`: encoger un botón se ve bien, pero
   encoger una fila de 600px la desplaza. La opacidad se comporta igual a
   cualquier tamaño y no pelea con los transform que ya existen.

   Sin `transition` para esta propiedad, el cambio es inmediato al apretar, que
   es cuando tiene que verse — no al soltar.

   Los que ya traían su propio :active (.btn, .nav-btn, .project-card…) siguen
   como estaban, y los 8 que ya usan transform quedan fuera para no pisarlos. */
#app-update-dismiss:active, #app-update-reload:active, .assignee-option:active,
.board-dot:active, .board-tab-add:active, .boards-mgr-actions button:active,
.boards-mgr-icon:active, .breakdown-project:active, .brief-edit-cancel:active,
.brief-edit-save:active, .btn-add-task:active, .btn-archived-toggle:active, .btn-google:active,
.btn-timer:active, .budgo-add-part:active, .budgo-add-sec:active,
.budgo-cal-mbtn:active, .budgo-cmp-add-part:active, .budgo-cmp-close:active,
.budgo-dash-nav-btn:active, .budgo-dash-nav-today:active, .budgo-ed-back:active,
.budgo-ed-datos>summary:active, .budgo-ed-lang:active, .budgo-ed-mbar:active,
.budgo-ed-ver-arrow:active, .budgo-estado-clk:active, .budgo-estado-opt:active,
.budgo-p-del:active, .budgo-pap-del:active, .budgo-row:active, .budgo-row-x:active,
.budgo-sec-del:active, .budgo-top-head:active, .cal-more:active, .card-action-btn:active,
.chat-edit-actions button:active, .chat-file-card:active, .chat-file-label:active,
.chat-fmt-btn:active, .chat-icon-btn:active, .chat-img-preview:active, .chat-msg-action-btn:active,
.chat-pending-x:active, .chat-popup-close:active, .chat-quote:active, .chat-reaction-btn:active,
.chat-reply-bar-x:active, .chat-reply-btn:active, .chat-send-btn:active, .client-photo-btn:active,
.client-photo-slot.add:active, .col-add-ghost:active, .col-tools button:active,
.crm-btn-gen:active, .crm-btn-pri:active, .crm-btn-sec:active, .crm-cand-add:active,
.crm-cand-arch:active, .crm-ct-del:active, .crm-filtros-btn:active, .crm-tab:active,
.crm-tb-accbtn:active, .crm-tb-dot:active, .crm-tm-check:active, .crm-vista-chip:active,
.crm-vista-del:active, .dash-team-proj-row:active, .dcal-nav-btn:active, .dp-nav:active,
.dt-axis-card:active, .dt-card:active, .emoji-btn:active, .emoji-picker-tabs button:active,
.fb-file-del:active, .fb-more:active, .file-item-dl:active, .hero-menu-item:active,
.hero-timer-pill:active, .list-add-row:active, .list-bulk-btn:active, .list-group-header:active,
.mchat-tab:active, .member-chip:active, .mention-item:active, .modal-close:active,
.notif-item:active, .notif-mark-all:active, .proj-event-del:active,
.proj-event-sent-btn:active, .section-title:active, .settings-icon-btn:active,
.settings-palette:active, .settings-tab-btn:active, .sidebar-chat-add:active,
.sidebar-chat-item:active, .sidebar-ctxmenu-item:active,
.sidebar-user:active, .stpl-card:active, .stpl-card-new:active, .subtask-delete:active,
.toast-action-btn:active, .topbar-timer-stop:active, .tpl-add-partida:active,
.tpl-add-section:active, .tpl-btn-icon:active {
  opacity: 0.6;
}
/* Los clicables de los módulos del port (mismo criterio que arriba). Las
   primitivas (.vtab, .seg-b, .filtro, .btn…) ya se hunden con transform.
   .ofn-card.editable se queda junto a .ofn-fila: oficina.js todavía pinta
   .ofn-card.editable (T12 pedía el cambio, pero el módulo no lo ha migrado
   este mismo turno) — quitarlo dejaría esas filas sin respuesta al tacto. */
.ayuda:active, .link-btn:active, .menu-i:active,
.rrhh-fila:active, .aus-chip:active, .ofn-fila:active, .ofn-card.editable:active, .ofn-inc-h:active,
.ofn-sal:active, .ofn-maleta-h:active, .uno-rel:active, .obj-card:active, .pipe-card:active,
.ags-reservar:active, .ags-resumen:active, .cal-eq-cell.editable:active, .cal-seg:active,
.est-btn:active, .est-op:active { opacity: 0.6; }

/* ── Ajustes de accesibilidad del sistema ──────────────────────────────────
   Los tres son preferencias reales del SO, no un modo aparte de la app. */

/* Movimiento reducido NO es "sin respuesta visual": es la versión que no
   desplaza. Se van los recorridos, las escalas y los rebotes; se quedan los
   fundidos, que son los que dicen si algo se ha abierto o cerrado. Antes esto
   era un interruptor general y dejaba, por ejemplo, que el toast apareciera de
   golpe, que se lee como un fallo y no como una atención. */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{
    animation-duration:0.01ms!important;
    animation-iteration-count:1!important;
    transition-duration:0.01ms!important;
  }
  /* Capas que aparecen y desaparecen: se quedan con el fundido, sin la escala. */
  .modal-overlay,.tpl-overlay,.settings-popup-overlay,.user-dropdown,#notif-backdrop,.toast{
    transition-duration:.15s!important;
  }
  .modal-overlay>*,.tpl-overlay>*,.settings-popup-overlay>*,.user-dropdown{
    transform:none!important;filter:none!important;
  }
  .toast{animation:none;opacity:1}
  /* El muelle de los gestos vive en JS y mira esta misma preferencia por su
     cuenta (ver js/gesture.js): una media query no alcanza a un bucle de rAF. */
}

/* Transparencia reducida: las superficies translúcidas pasan a sólidas. El
   desenfoque es lo primero que estorba a quien pide esto. */
@media (prefers-reduced-transparency:reduce){
  .budgo-ed-mbar,.crm-panel-cerrar,
  #board-mag-btn,#mchat-tabs,#mobile-home-btn,.mfab,#mobile-tabbar{
    backdrop-filter:none!important;
    -webkit-backdrop-filter:none!important;
    background:var(--c-surface)!important;
  }
  .modal-overlay,.tpl-overlay,.settings-popup-overlay{background:rgba(26,25,22,0.75)}
}

/* Más contraste: fondos sólidos y bordes que se ven de verdad. */
@media (prefers-contrast:more){
  :root{--c-text2:#3A3733;--c-text3:#3A3733;--c-border:#8A867F;--c-border2:#5E5B57}
  body.dark{--c-text2:#DAD6D0;--c-text3:#DAD6D0;--c-border:#6E6A63;--c-border2:#9A9590}
  .budgo-ed-mbar,.crm-panel-cerrar,
  #board-mag-btn,#mchat-tabs,#mobile-home-btn,.mfab,#mobile-tabbar{
    backdrop-filter:none!important;
    -webkit-backdrop-filter:none!important;
    background:var(--c-surface)!important;
    border:1px solid var(--c-border2)!important;
  }
  .btn,.form-input,.form-select,.form-textarea{border-width:2px}
  .card.relleno,.aviso{box-shadow:inset 0 0 0 1px var(--c-border2)}
  :focus-visible{outline-width:3px}
}

/* Listas largas: lo que no cabe se recoge tras un <details> (ver collapseExtra
   en js/helpers.js). Usado en las versiones de la ficha y en el dashboard. */
.more-toggle>summary{list-style:none;cursor:pointer;display:inline-flex;align-items:center;gap:6px;margin:4px 0 2px;padding:3px 8px;border-radius:6px;font-size:11.5px;font-weight:600;color:var(--c-text3);transition:var(--tr-colores)}
.more-toggle>summary::-webkit-details-marker{display:none}
.more-toggle>summary::before{content:'';width:0;height:0;border-left:4px solid currentColor;border-top:3.5px solid transparent;border-bottom:3.5px solid transparent;transition:transform 0.2s ease}
.more-toggle[open]>summary::before{transform:rotate(90deg)}
.more-toggle>summary:hover{background:var(--sb-muted);color:var(--c-text)}
.more-toggle>summary:focus-visible{outline:2px solid var(--c-accent);outline-offset:2px}

/* Distintivo de entorno: cualquier origen que no sea workspace.keweke.com
   trabaja contra la base de datos de staging (ver index.html). */
html.is-staging::after{content:'STAGING';position:fixed;right:0;bottom:0;z-index:99999;pointer-events:none;background:#D97706;color:#fff;font-family:var(--font);font-size:10px;font-weight:700;letter-spacing:0.12em;padding:3px 10px;border-radius:6px 0 0 0;opacity:0.9}

/* Tooltip propio (tipInit, helpers.js): [data-tip] y los iconos de la barra
   plegada. position:fixed, así ningún overflow lo recorta. */
.kw-tip{position:fixed;z-index:1000;transform:translate(-50%,0);padding:4px 9px;border-radius:6px;background:var(--c-text);color:var(--c-sidebar);
  font-size:12px;font-weight:600;white-space:nowrap;pointer-events:none;box-shadow:0 4px 14px rgba(0,0,0,.18);opacity:0;transition:opacity .12s}
.kw-tip.lado{transform:translate(0,-50%)}
.kw-tip.on{opacity:1}
