/* ===== ENTOMIRA · identidad visual grodi (tema claro) ===== */
:root{
  /* --- paleta corporativa grodi --- */
  --teal:#006F66;        /* Deep Teal · color primario / interfaz */
  --teal-700:#00544D;    /* teal oscuro · hover */
  --teal-tint:#E7F0EF;   /* fondo teal muy suave */
  --lima:#B4FF48;        /* Vibrant Lime · acento / detección */
  --lima-ink:#5C9A0E;    /* lima legible sobre blanco (texto/segmentos) */
  --rojo:#E04449;        /* Yield Bloom · alertas / plaga */
  --smoke:#F5F4F2;       /* White Smoke · fondo de página */
  --tinta:#1D1E1C;       /* Dark Grodi · texto principal */
  --gris:#878787;        /* Grey Grodi · texto atenuado */

  /* --- alias semánticos (usados por los componentes) --- */
  --panel:#FFFFFF; --panel-2:#FAFAF9; --linea:#E4E3DF; --linea-2:#D4D3CE;
  --texto:var(--tinta); --texto-mute:var(--gris);
  --sombra:0 6px 22px rgba(29,30,28,.08);
  --radio:14px; --radio-s:10px;
  --fuente:'Satoshi','Open Sans',system-ui,-apple-system,Roboto,sans-serif;
  --fuente-titulo:'Chillax','Nunito','Satoshi',system-ui,sans-serif;
}
*{box-sizing:border-box}
html,body{margin:0;padding:0}
body{
  font-family:var(--fuente); color:var(--texto);
  background:
    radial-gradient(1200px 600px at 85% -10%, rgba(0,111,102,.06), transparent 60%),
    radial-gradient(900px 500px at -10% 8%, rgba(180,255,72,.10), transparent 55%),
    var(--smoke);
  min-height:100vh;
}
a{color:inherit;text-decoration:none}
h1,h2,h3{margin:0 0 .4em;font-family:var(--fuente-titulo);font-weight:600;letter-spacing:.2px}

/* ---- Topbar ---- */
.topbar{
  display:flex;align-items:center;gap:20px;flex-wrap:wrap;
  padding:12px 22px;position:sticky;top:0;z-index:30;
  background:linear-gradient(180deg, rgba(255,255,255,.96), rgba(255,255,255,.82));
  backdrop-filter:blur(8px);border-bottom:1px solid var(--linea);
}
.brand{display:flex;align-items:center;gap:10px}
.brand-mark{width:40px;height:40px}
.brand-name{font-family:var(--fuente-titulo);font-weight:600;font-size:20px;letter-spacing:2px;color:var(--teal)}
.brand-sub{color:var(--texto-mute);font-size:12px;margin-left:4px;display:none}
@media(min-width:900px){.brand-sub{display:inline}}
.mainnav{display:flex;gap:6px;margin-left:auto;flex-wrap:wrap}
.mainnav a{
  padding:8px 16px;border-radius:999px;color:var(--texto-mute);font-weight:600;
  transition:.15s;
}
.mainnav a:hover{color:var(--teal);background:var(--teal-tint)}
.mainnav a.active{color:#fff;background:var(--teal)}
.status-pills{display:flex;gap:8px}
.pill{
  font-size:11px;font-weight:700;padding:5px 10px;border-radius:999px;
  border:1px solid var(--linea);color:var(--texto-mute);white-space:nowrap;
  background:#fff;cursor:default;
}
.pill.ok{color:var(--teal-700);background:var(--lima);border-color:transparent}
.pill.off{color:#fff;background:var(--rojo);border-color:transparent}
button.pill{cursor:pointer}

/* --- gadget de almacenamiento (pastilla + panel) --- */
.pill.disk.ok{color:var(--teal);background:var(--teal-tint);border-color:transparent}
.pill.disk.aviso{color:#8A5A00;background:#FFE9B8;border-color:transparent}
.pill.disk.critico{color:#fff;background:var(--rojo);border-color:transparent}
.storage{min-width:min(420px,78vw)}
.st-big{font-family:var(--fuente-titulo);color:var(--texto);margin-bottom:10px}
.st-big b{font-size:30px;line-height:1}
.st-big span{color:var(--texto-mute);font-size:14px}
.st-bar{height:14px;border-radius:999px;background:var(--teal-tint);overflow:hidden;
  border:1px solid var(--linea)}
.st-fill{height:100%;border-radius:999px;transition:width .4s ease}
.st-fill.ok{background:linear-gradient(90deg,var(--teal),var(--lima-ink))}
.st-fill.aviso{background:linear-gradient(90deg,#E8871B,#F7A93B)}
.st-fill.critico{background:linear-gradient(90deg,#B4262A,var(--rojo))}
.st-legend{margin-top:6px;font-size:12px;color:var(--texto-mute)}
.st-alert{margin-top:12px;padding:10px 12px;border-radius:var(--radio-s);font-size:13px;
  line-height:1.45}
.st-alert.aviso{background:#FFF6E2;color:#8A5A00}
.st-alert.critico{background:#FDECEC;color:#9B2B2E}
.st-rows{margin-top:14px;border-top:1px solid var(--linea)}
.st-row{display:flex;align-items:baseline;gap:8px;padding:9px 2px;
  border-bottom:1px solid var(--linea);font-size:13px}
.st-k{flex:1;color:var(--texto-mute)}
.st-v{font-weight:700}
.st-x{color:var(--texto-mute);font-size:12px}
.st-note{margin-top:12px;font-size:12px;color:var(--texto-mute);line-height:1.5}

/* ---- Layout ---- */
.app{max-width:1280px;margin:0 auto;padding:24px 22px 60px}
.view-head{display:flex;align-items:center;gap:16px;flex-wrap:wrap;margin-bottom:18px}
/* Ritmo vertical: el espacio entre bloques venia de estilos sueltos en cada vista y salia
   distinto en cada pantalla. Un solo valor, aqui, para que todas respiren igual. */
.app>h2,.app>.view-head{margin-top:28px}
.app>h2:first-child,.app>.view-head:first-child{margin-top:0}
.card+.card{margin-top:0}
.view-head h1{font-size:26px}
.view-head .spacer{flex:1}
.muted{color:var(--texto-mute)}
.filters{display:flex;gap:10px;flex-wrap:wrap;align-items:center;margin-bottom:18px}

/* ---- Controles ---- */
select,input,textarea{
  font-family:inherit;font-size:14px;color:var(--texto);
  background:#fff;border:1px solid var(--linea-2);border-radius:var(--radio-s);
  padding:9px 12px;outline:none;transition:.15s;
}
select:focus,input:focus,textarea:focus{border-color:var(--teal);box-shadow:0 0 0 3px rgba(0,111,102,.12)}
label.field{display:flex;flex-direction:column;gap:5px;font-size:12px;color:var(--texto-mute)}
/* UN BOTON DESACTIVADO TIENE QUE PARECERLO.
   No habia ninguna regla `:disabled` en toda la hoja, asi que un boton desactivado se veia
   exactamente igual que uno pulsable: se podia avisar «la IA no esta en marcha» y dejar al
   lado un boton que invitaba a pulsarlo igualmente. Afecta a todos los que se desactivan
   mientras trabajan —«Tomar foto», «Reiniciar placa», «Analizar»—, no solo a la demo. */
.btn:disabled,.btn[disabled]{opacity:.45;cursor:not-allowed;box-shadow:none;filter:grayscale(.35)}
.btn:disabled:hover,.btn[disabled]:hover{transform:none;filter:grayscale(.35)}

/* Un boton no parte su texto en dos lineas: crece a lo ancho o se acorta la etiqueta.
   «Sin correccion» partia en dos y dejaba su fila con un boton mas alto que los demas. */
.btn{white-space:nowrap;
  display:inline-flex;align-items:center;gap:8px;cursor:pointer;font-weight:700;
  font-size:14px;padding:9px 16px;border-radius:var(--radio-s);border:1px solid transparent;
  background:var(--teal);color:#fff;transition:.15s;
}
.btn:hover{background:var(--teal-700)}
.btn.amber{background:var(--lima);color:var(--teal-700)}
.btn.amber:hover{background:#a2ef2f}
.btn.ghost{background:#fff;border-color:var(--linea-2);color:var(--texto)}
.btn.ghost:hover{border-color:var(--teal);color:var(--teal)}
.btn.danger{background:#fff;border-color:var(--rojo);color:var(--rojo)}
.btn.danger:hover{background:var(--rojo);color:#fff}
.btn.sm{padding:6px 11px;font-size:12px}

/* ---- Tarjetas / grid ---- */
/* Rejillas que RELLENAN el ancho.
   Con `auto-fill` una sola tarjeta se quedaba a 300 px en una pantalla de 1280, con un
   desierto a la derecha; `auto-fit` colapsa las pistas vacias y deja que la tarjeta crezca.
   El `max` evita el extremo contrario: una tarjeta unica de 1.200 px de ancho tampoco se lee. */
.grid{display:grid;gap:16px}
.grid.gal{grid-template-columns:repeat(auto-fill,minmax(240px,1fr))}
.grid.traps{grid-template-columns:repeat(auto-fit,minmax(min(100%,340px),1fr))}
.grid.gh{grid-template-columns:repeat(auto-fit,minmax(min(100%,360px),1fr))}
.grid.users{grid-template-columns:repeat(auto-fit,minmax(min(100%,420px),1fr))}
/* El tope va en la TARJETA, no en la pista: `min(1fr,520px)` mezcla flex con longitud dentro de
   `minmax()`, que es CSS invalido — el navegador tira la regla entera y la rejilla se quedaba
   como estaba. Con el tope aqui, una tarjeta sola crece hasta un ancho legible y para. */
.grid.traps>.card{max-width:560px}
.grid.gh>.card{max-width:600px}
.grid.users>.card{max-width:680px}
.card{
  background:var(--panel);
  border:1px solid var(--linea);border-radius:var(--radio);overflow:hidden;
  box-shadow:var(--sombra);transition:.15s;
}
.card:hover{border-color:var(--teal);transform:translateY(-2px);box-shadow:0 10px 26px rgba(0,111,102,.12)}
.card .body{padding:14px}
.card .row{display:flex;justify-content:space-between;align-items:center;gap:12px}
/* Fila de botones: AGRUPADOS a la izquierda, no repartidos por el ancho de la tarjeta.
   Con `space-between` heredado, «Panel · Config · Editar · borrar» quedaban a distancias
   distintas segun lo ancha que fuera la tarjeta, y el de borrar acababa lejisimos, como si no
   fuera del mismo grupo. Se separa solo el destructivo, y a proposito. */
.card .acciones{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-top:12px;
    padding-top:12px;border-top:1px solid var(--linea)}
.card .acciones .peligro{margin-left:auto}
/* Las etiquetas se leian con dificultad: gris claro sobre blanco roto es ~2:1 de contraste.
   Se les sube el peso y el color, y la gris pasa a tener fondo propio en vez de casi ninguno. */
.tag{font-size:11px;font-weight:700;padding:4px 10px;border-radius:999px;letter-spacing:.2px;
  background:var(--teal-tint);color:var(--teal)}
.tag.amber{background:rgba(180,255,72,.28);color:var(--lima-ink)}
.tag.gray{background:rgba(135,135,135,.16);color:var(--gris)}

/* ---- Galería ---- */
/* Galeria: el pie de cada celda medía casi lo mismo que la miniatura. Con 120 fotos por
   pagina eso son miles de pixeles de scroll por informacion que casi nunca se lee entera. */
.gal-card .body{padding:8px 10px 9px}
.gal-card b{font-size:13px}
.gal-sitio{font-size:11.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.thumb-wrap{position:relative;aspect-ratio:4/3;background:#ECEBE7;overflow:hidden}
.thumb-wrap img{width:100%;height:100%;object-fit:cover;display:block}
.thumb-wrap .count{
  position:absolute;top:8px;right:8px;background:rgba(29,30,28,.82);
  color:var(--lima);font-weight:800;font-size:13px;padding:4px 9px;border-radius:999px;
  border:1px solid rgba(180,255,72,.5);
}
.thumb-wrap .demo-badge{position:absolute;top:8px;left:8px;background:var(--lima);
  color:var(--teal-700);font-weight:800;font-size:10px;padding:3px 8px;border-radius:6px}
.bbox-layer{position:absolute;inset:0;pointer-events:none}
.bbox{position:absolute;border:2px solid var(--lima);border-radius:3px;
  box-shadow:0 0 0 1px rgba(0,0,0,.35)}
.bbox span{position:absolute;top:-16px;left:-2px;background:var(--teal);
  color:#fff;font-size:9px;font-weight:800;padding:0 4px;border-radius:3px;white-space:nowrap}

/* ---- Paginador (galería) ---- */
.pager{display:flex;align-items:center;gap:6px;flex-wrap:wrap;justify-content:center;margin-top:24px}
.page-btn{min-width:38px;height:38px;padding:0 10px;border-radius:var(--radio-s);border:1px solid var(--linea-2);
  background:#fff;color:var(--texto);font-weight:700;font-size:14px;cursor:pointer;transition:.15s}
.page-btn:hover{border-color:var(--teal);color:var(--teal)}
.page-btn.active{background:var(--teal);border-color:var(--teal);color:#fff;cursor:default}
.page-btn.disabled{opacity:.4;cursor:not-allowed}
.page-gap{color:var(--texto-mute);padding:0 2px}
.page-info{margin-left:10px;color:var(--texto-mute);font-size:13px}

/* ---- Mapa de calor ---- */
.heat-wrap{display:flex;gap:20px;flex-wrap:wrap;align-items:flex-start}
.heat-svg{background:var(--panel);border:1px solid var(--linea);border-radius:var(--radio);padding:10px}
.heat-legend{display:flex;flex-direction:column;gap:8px;font-size:13px}
.heat-legend .sw{width:26px;height:14px;border-radius:4px;display:inline-block;margin-right:8px;vertical-align:middle}

/* ---- KPIs ---- */
.kpis{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:14px;margin-bottom:18px}
.kpi{background:var(--panel);border:1px solid var(--linea);
  border-radius:var(--radio);padding:16px 18px;border-left:4px solid var(--teal);box-shadow:var(--sombra)}
.kpi.amber{border-left-color:var(--lima-ink)}
.kpi.blue{border-left-color:var(--lima-ink)}
.kpi .k-lbl{font-size:12px;color:var(--texto-mute);text-transform:uppercase;letter-spacing:.5px;font-weight:700}
.kpi .k-val{font-family:var(--fuente-titulo);font-size:34px;font-weight:600;line-height:1.1;margin:4px 0}
.kpi .k-sub{font-size:12px;color:var(--texto-mute)}
.compbar{display:flex;height:16px;border-radius:999px;overflow:hidden;margin:6px 0 10px}
.compbar span{display:block}
.complegend{display:flex;gap:18px;flex-wrap:wrap;font-size:13px}
.complegend .dot{width:10px;height:10px;border-radius:50%;display:inline-block;margin-right:6px}

/* ---- Mapa sector×línea ---- */
.mapgrid{display:grid;gap:8px;margin-top:8px}
.map-h{text-align:center;font-weight:800;color:var(--texto-mute);padding-bottom:4px}
.map-row{display:flex;align-items:center;justify-content:center;color:var(--texto-mute);font-weight:700;font-size:13px}
.map-cell{border-radius:10px;min-height:76px;display:flex;flex-direction:column;align-items:center;
  justify-content:center;border:1px solid var(--linea)}
.map-cell.empty{background:repeating-linear-gradient(45deg,#F0EFEC,#F0EFEC 8px,#E7E6E2 8px,#E7E6E2 16px)}
.map-n{font-size:24px;font-weight:800}
.map-tr{font-size:11px;opacity:.85}
.map-pasillo{background:#EFEEEA;border:1px solid var(--linea);border-radius:8px;display:flex;
  align-items:center;justify-content:center;min-width:34px}
.map-pasillo span{writing-mode:vertical-rl;transform:rotate(180deg);font-size:10px;letter-spacing:2px;color:var(--texto-mute)}

/* ---- Panel de salud / worker ---- */
.hpanel{display:flex;gap:22px;flex-wrap:wrap;font-size:14px}
.hpanel .hi{display:flex;align-items:center;gap:7px;color:var(--texto-mute)}
.hpanel .hi b{color:var(--texto)}
.statgrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:10px 20px;margin-top:8px}
.statgrid .st{display:flex;justify-content:space-between;font-size:13px;border-bottom:1px dashed var(--linea);padding:4px 0}
.statgrid .st b{color:var(--texto)}
.client-mode .app{max-width:1100px}

/* ---- Modal ---- */
.modal-back{position:fixed;inset:0;background:rgba(29,30,28,.42);display:flex;
  align-items:center;justify-content:center;z-index:50;padding:20px}
.modal{background:var(--panel);border:1px solid var(--linea);border-radius:var(--radio);
  width:min(560px,100%);max-height:90vh;overflow:auto;box-shadow:0 18px 50px rgba(29,30,28,.22)}
.modal .head{display:flex;justify-content:space-between;align-items:center;
  padding:16px 18px;border-bottom:1px solid var(--linea)}
.modal .content{padding:18px}
.modal .foot{display:flex;justify-content:flex-end;gap:10px;padding:14px 18px;border-top:1px solid var(--linea)}
.form-grid{display:grid;grid-template-columns:1fr 1fr;gap:14px}
.form-grid .full{grid-column:1/-1}

/* ---- Demo ---- */
.demo-stage{position:relative;max-width:760px;margin:0 auto;background:#ECEBE7;
  border:1px solid var(--linea);border-radius:var(--radio);overflow:hidden;
  min-height:300px;display:flex;align-items:center;justify-content:center}
/* la imagen define el tamaño del recuadro → las cajas se alinean exactas */
.demo-stage img{width:100%;height:auto;display:block}
.scanline{position:absolute;left:0;right:0;height:3px;
  background:linear-gradient(90deg,transparent,var(--lima),transparent);
  box-shadow:0 0 18px 4px rgba(180,255,72,.6);top:0}
.scan-grid{position:absolute;inset:0;background-image:
  linear-gradient(rgba(0,111,102,.08) 1px,transparent 1px),
  linear-gradient(90deg,rgba(0,111,102,.08) 1px,transparent 1px);
  background-size:32px 32px;pointer-events:none}
@keyframes sweepdown{0%{top:0;opacity:0}8%{opacity:1}92%{opacity:1}100%{top:calc(100% - 3px);opacity:0}}
.sweeping .scanline{animation:sweepdown 1.8s ease-in-out forwards}
.demo-stage img{opacity:0;transition:opacity .35s ease}
.demo-stage img.shown{opacity:1}
.bbox-layer .bbox{opacity:0;animation:bboxin .35s ease forwards}
@keyframes bboxin{from{opacity:0;transform:scale(1.15)}to{opacity:1;transform:none}}

/* ---- Chips de especie (Demo) ---- */
.sp-chips{display:flex;gap:12px;flex-wrap:wrap;justify-content:center;margin-top:8px}
.sp-chip{display:flex;align-items:center;gap:10px;background:var(--panel);
  border:1px solid var(--linea);border-left-width:4px;border-radius:12px;
  padding:10px 16px;min-width:150px;box-shadow:var(--sombra)}
.sp-emoji{font-size:24px}
.sp-name{font-weight:800;font-size:15px}
.sp-tipo{font-size:11px;color:var(--texto-mute)}

/* ---- Toast ---- */
#toast-root{position:fixed;bottom:20px;right:20px;display:flex;flex-direction:column;gap:10px;z-index:60}
.toast{background:var(--panel);border:1px solid var(--linea);border-left:4px solid var(--teal);
  padding:12px 16px;border-radius:var(--radio-s);box-shadow:var(--sombra);font-size:14px;color:var(--texto);
  animation:slidein .2s ease}
.toast.err{border-color:var(--rojo);border-left-color:var(--rojo)}
@keyframes slidein{from{transform:translateX(20px);opacity:0}to{transform:none;opacity:1}}

/* ---- Estados vacíos / carga ---- */
.empty{text-align:center;padding:60px 20px;color:var(--texto-mute)}
.empty .big{font-size:44px;margin-bottom:10px;opacity:.7}
.spinner{width:34px;height:34px;border:3px solid var(--linea);border-top-color:var(--teal);
  border-radius:50%;animation:spin .8s linear infinite;margin:40px auto}
@keyframes spin{to{transform:rotate(360deg)}}
/* Etiqueta y valor, juntos y legibles.
   `space-between` a secas funciona en una tarjeta estrecha y se rompe en una ancha: en 1.200 px
   la etiqueta queda pegada al borde izquierdo y su valor al derecho, y hay que cruzar la
   pantalla para emparejarlos. El `gap` grande los separa lo justo y la linea de puntos los une. */
/* Ficha de fauna: titulo y parrafo, no etiqueta y valor. */
.ficha-bloque{padding:8px 0;border-top:1px dashed var(--linea)}
.ficha-bloque b{display:block;font-size:13px;margin-bottom:3px}
.ficha-bloque p{margin:0;font-size:13px;line-height:1.5}
.nota-pendiente{margin:0 0 16px;padding:9px 12px;border-radius:var(--radio-s);
  background:#FFF6E5;border:1px solid #F2D9A8;color:#7A5B1E;font-size:13px}

.kv{display:flex;justify-content:space-between;gap:24px;padding:5px 0;
    border-bottom:1px dashed var(--linea);font-size:13px}
.kv>:first-child{flex:0 1 auto;min-width:0}
.kv>:last-child{flex:0 0 auto;text-align:right}
.kv:last-child{border-bottom:0}
.kv b{color:var(--texto)}

/* ---- Usuarios ---- */
.user-form{display:grid;grid-template-columns:1fr 1fr;gap:14px}
.user-form .field{display:flex;flex-direction:column;gap:5px;font-size:13px}
.user-form input,.user-form select{width:100%}
@media(max-width:560px){.user-form{grid-template-columns:1fr}}

/* ---- Login (página de inicio, estilo invernadero + glass) ---- */
body.logged-out{margin:0}
body.logged-out .topbar{display:none}
body.logged-out #app.app{max-width:none;margin:0;padding:0}
.login-wrap{min-height:100vh;display:flex;align-items:center;justify-content:center;padding:24px;
  background:linear-gradient(rgba(20,40,30,.28),rgba(20,40,30,.42)),url('/assets/login-bg.jpg') center/cover no-repeat fixed}
.login-card{width:100%;max-width:400px;padding:38px 34px;border-radius:22px;text-align:center;
  background:rgba(255,255,255,.72);backdrop-filter:blur(14px) saturate(1.1);-webkit-backdrop-filter:blur(14px) saturate(1.1);
  border:1px solid rgba(255,255,255,.6);box-shadow:0 22px 60px rgba(15,35,25,.35)}
.login-logo{width:76px;height:76px;display:block;margin:0 auto 6px}
.login-brand{font-family:var(--fuente-titulo);font-weight:700;letter-spacing:3px;color:var(--teal);font-size:24px}
.login-title{font-family:var(--fuente-titulo);font-weight:600;color:var(--tinta,#1D1E1C);font-size:22px;margin:6px 0 22px}
.login-input{width:100%;box-sizing:border-box;margin-bottom:14px;padding:14px 16px;border:1px solid rgba(0,0,0,.08);
  border-radius:12px;background:rgba(255,255,255,.92);font:inherit;font-size:15px;color:var(--tinta,#1D1E1C)}
.login-input::placeholder{color:#8A8A8A}
.login-input:focus{border-color:var(--teal);box-shadow:0 0 0 3px rgba(0,111,102,.15);outline:none}
.login-btn{width:100%;margin-top:6px;padding:14px;font-size:16px;border-radius:12px;
  display:flex;align-items:center;justify-content:center;text-align:center}
.login-err{color:#fff;background:rgba(224,68,73,.92);border-radius:10px;padding:10px 12px;font-size:13px;margin:0 0 12px}
.login-forgot{display:block;margin-top:20px;color:var(--teal);font-size:13.5px;font-weight:500;text-decoration:none}
.login-forgot:hover{text-decoration:underline}

/* ---- Ajuste de color ---- */
.color-layout{display:grid;grid-template-columns:340px 1fr;gap:18px;align-items:start}
.color-slider{margin:10px 0}
.color-slider input[type=range]{width:100%;margin-top:6px;accent-color:var(--teal)}
.color-compare{display:grid;grid-template-columns:1fr 1fr;gap:14px}
.color-compare figure{margin:0}
.color-compare figcaption{margin-top:6px;font-size:12px;text-align:center}
.color-preview{width:100%;border-radius:12px;border:1px solid var(--linea);display:block;background:#ECEBE7}
@media(max-width:820px){.color-layout{grid-template-columns:1fr}.color-compare{grid-template-columns:1fr}}

/* ---- Panel de control por trampa ---- */
.ctrl-layout{display:grid;grid-template-columns:1.6fr 1fr;gap:18px;align-items:start}
.ctrl-card{box-shadow:var(--sombra)}
/* Etiqueta sobre la cámara: en vivo o foto vieja. Sin esto, los tres caminos del snapshot
   —empuje, directo y archivo— se veían exactamente igual. */
.cam-caja{position:relative}
.cam-estado{position:absolute;left:10px;top:10px;display:inline-flex;align-items:center;
  gap:6px;padding:4px 10px;border-radius:999px;font-size:12px;font-weight:600;
  background:rgba(27,67,50,.88);color:#fff;backdrop-filter:blur(2px)}
.cam-estado.archivo{background:rgba(232,135,27,.94)}
.ctrl-cam{width:100%;border-radius:12px;border:1px solid var(--linea);background:#ECEBE7;display:block;aspect-ratio:4/3;object-fit:cover}
.ctrl-controls{display:grid;grid-template-columns:1fr 1fr 1fr;gap:12px;margin-top:14px}
.ctrl-controls .slrow{display:flex;align-items:center;gap:8px}
.ctrl-controls input[type=range]{flex:1;accent-color:var(--teal)}
.ctrl-batbox{margin-bottom:6px}
.bat-bar{margin-top:8px;height:22px;border-radius:999px;background:var(--linea);overflow:hidden;border:1px solid var(--linea-2)}
.bat-fill{height:100%;background:var(--teal);border-radius:999px;transition:width .3s}
.ctrl-hr{border:none;border-top:1px solid var(--linea);margin:14px 0}
.ctrl-stat{display:flex;justify-content:space-between;align-items:center;gap:24px;padding:7px 0;
    border-bottom:1px dashed var(--linea);font-size:14px}
.ctrl-stat>:last-child{flex:0 0 auto;text-align:right}
.ctrl-stat:last-child{border-bottom:none}
@media(max-width:820px){.ctrl-layout{grid-template-columns:1fr}.ctrl-controls{grid-template-columns:1fr}}

/* ---- Lightbox (imagen completa + cajas, con zoom) ---- */
.lightbox{position:fixed;inset:0;background:rgba(10,15,12,.94);z-index:100;
  display:flex;align-items:center;justify-content:center;overflow:auto;padding:20px;cursor:zoom-out}
.lb-stage{position:relative;flex:0 0 auto;cursor:zoom-in;border-radius:4px;overflow:hidden;
  box-shadow:0 12px 48px rgba(0,0,0,.55)}
.lb-stage.zoomed{cursor:zoom-out}
.lb-img{width:100%;height:100%;display:block;object-fit:contain}
.lb-tools{position:fixed;top:16px;right:18px;display:flex;gap:10px;z-index:101}
.lb-btn{width:42px;height:42px;border-radius:999px;border:none;background:rgba(255,255,255,.16);
  color:#fff;font-size:17px;cursor:pointer;display:grid;place-items:center;text-decoration:none}
.lb-btn:hover{background:rgba(255,255,255,.3)}

/* ---- Selección y descarga en grupo + arrastrar-soltar ---- */
.thumb-wrap .gal-sel{position:absolute;top:8px;left:8px;width:20px;height:20px;cursor:pointer;
  z-index:3;accent-color:var(--teal);filter:drop-shadow(0 1px 2px rgba(0,0,0,.4))}
.card.selected{border-color:var(--teal);box-shadow:0 0 0 2px var(--teal)}
.gal-selbar{display:flex;align-items:center;gap:8px;background:var(--teal-tint);
  border:1px solid var(--teal);border-radius:999px;padding:5px 8px 5px 14px;font-size:13px;color:var(--teal)}
.grid.gal.dropping{outline:3px dashed var(--teal);outline-offset:6px;border-radius:14px;background:var(--teal-tint)}

/* ---- Barra de progreso de subida ---- */
.up-panel{position:fixed;left:50%;bottom:26px;transform:translateX(-50%);z-index:60;
  width:min(420px,calc(100vw - 32px));background:#fff;border:1px solid var(--linea);
  border-radius:14px;box-shadow:0 12px 40px rgba(29,30,28,.20);padding:14px 16px;
  animation:up-in .22s ease}
@keyframes up-in{from{opacity:0;transform:translate(-50%,10px)}to{opacity:1;transform:translate(-50%,0)}}
.up-top{display:flex;align-items:center;gap:8px;font-weight:700;color:var(--teal);font-size:14px}
.up-top b{color:var(--tinta);font-variant-numeric:tabular-nums}
.up-track{height:9px;background:var(--linea);border-radius:999px;overflow:hidden;margin:10px 0 8px}
.up-fill{height:100%;width:0;border-radius:999px;
  background:linear-gradient(90deg,var(--teal),var(--lima-ink));transition:width .18s ease}
.up-name{font-size:12px;color:var(--texto-mute);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.up-panel.up-ok .up-fill{background:linear-gradient(90deg,var(--teal),var(--lima))}
.up-panel.up-ok .up-top b{color:var(--lima-ink)}
.up-panel.up-err .up-fill{background:var(--rojo)}
.up-panel.up-err .up-top b{color:var(--rojo)}

/* ---- Plano del invernadero ----
   Sustituye a la rejilla sector×línea: un técnico se orienta por la forma de la nave, el
   pasillo y las líneas de cultivo, no por una matriz. */
.plano{background:#fff;border:1px solid var(--linea);border-radius:var(--radio);padding:10px;
  overflow-x:auto}
.plano svg{display:block;min-width:420px}
.plano-leyenda{margin-top:10px}
.lg-fila{display:flex;align-items:center;gap:14px;flex-wrap:wrap;font-size:13px}
.lg-item{display:inline-flex;align-items:center;gap:6px;color:var(--muted);font-size:12px}
.lg-item i{width:16px;height:12px;border-radius:3px;display:inline-block;
  border:1px solid rgba(0,0,0,.15)}

/* ---- Detecciones: color por especie, etiqueta solo cuando cabe ----
   Con cientos de insectos, las etiquetas se tapaban entre ellas y tapaban la foto. El color
   dice la especie sin ocupar sitio; la leyenda de abajo dice cuántas hay de cada una. */
.bbox{border-color:var(--c,var(--lima))}
.bbox span{background:var(--c,var(--teal))}
.bbox.sin-etiqueta span{display:none}
.esp-leyenda{display:flex;gap:10px;flex-wrap:wrap;align-items:center}
.esp-chip{display:inline-flex;align-items:center;gap:7px;background:var(--panel);
  border:1px solid var(--linea);border-radius:999px;padding:4px 12px;font-size:13px}
.esp-chip i{width:12px;height:12px;border-radius:3px;display:inline-block}
.esp-chip b{font-size:14px}

/* ---- Gasto de datos móviles ---- */
.datos-caja{margin-top:14px;padding:12px;border:1px solid var(--linea);border-radius:var(--radio-s);
  background:var(--panel)}
.barra-datos{display:flex;height:10px;border-radius:999px;overflow:hidden;margin-top:8px;
  background:var(--linea)}
.barra-datos i{display:block;height:100%}
.barra-datos .d-ingesta{background:#2D6A4F}
.barra-datos .d-telemetria{background:#F7A93B}
.barra-datos .d-vivo{background:#52B788}
.barra-datos .d-ota{background:#E8871B}
.barra-datos .d-config{background:#9AA79A}

/* Un valor que ya no se toca: se enseña, no se ofrece. */
.fijo{display:inline-flex;align-items:center;gap:6px;font-weight:700;color:var(--teal)}

/* Usuario dado de baja: se ve, pero apagado. */
.card.inactivo{opacity:.62}
.card.inactivo .body b{text-decoration:line-through}
