  :root{--ink:#23262b;--mut:#7c8088;--line:#ececed;--bg:#f7f8f9;--card:#fff;--accent:#1f9d57;--accent-d:#178045;--accent-grad:linear-gradient(180deg,#22ad61,#178045);--on-acc:#fff;--ok:#0a7d28}  /* theme-exempt: bloque de DEFINICION de tokens (sombrea el :root de theme.css en dia; deuda conocida) */
  *{box-sizing:border-box}
  html{-webkit-text-size-adjust:100%}
  body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;color:var(--ink);background:var(--bg);line-height:1.5}
  select,button,input,textarea{font:inherit}
  select,input,textarea{padding:.55rem .7rem;border:1px solid var(--line);border-radius:10px;background:var(--card);color:var(--ink);transition:border-color .12s,box-shadow .12s}
  select:focus,input:focus,textarea:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px color-mix(in srgb, var(--accent) 30%, transparent)}
  .btn{background:var(--accent-btn,var(--accent-grad,var(--accent)));color:var(--on-acc,#fff);border:none;border-radius:10px;padding:.55rem 1rem;cursor:pointer;font-weight:700;font-size:.92rem;transition:transform .1s,filter .12s;box-shadow:0 1px 2px rgba(0,0,0,.08)} /* theme-exempt: #fff es solo el respaldo de --on-acc antes de que corra skinApplySpec */
  .btn:hover{filter:brightness(1.06)}.btn:active{transform:translateY(1px)}
  .btn.sec{background:var(--card);color:var(--ink);border:1px solid var(--line);box-shadow:none;font-weight:600}
  .btn.sec:hover{background:var(--hover);border-color:var(--line)}
  .btn.sm{padding:.4rem .75rem;font-size:.84rem;border-radius:9px}
  .salir{color:var(--mut);text-decoration:none;font-size:.9rem;padding:.55rem .7rem;border-radius:9px}
  .salir:hover{background:var(--hover);color:var(--ink)}
  .buildtag{font-size:.66rem;color:var(--mut-2);text-align:center;padding:.35rem .7rem .1rem;letter-spacing:.02em;user-select:none;flex:none}

  /* ---- Layout dashboard ---- */
  .shell{display:flex;min-height:100vh}
  .side{width:244px;flex:none;background:var(--card);border-right:1px solid var(--line);display:flex;flex-direction:column;padding:1rem .75rem;position:sticky;top:0;height:100vh;height:100dvh}
  .brand{font-weight:800;font-size:1.18rem;letter-spacing:-.01em;margin:.2rem .5rem 1rem 0;display:flex;align-items:center;gap:.33rem}
  .brand::before{display:none}
  /* Franja del color del tema hasta arriba: fuerza a Safari (Mac) a tintar su barra parejo en todas las vistas (reversible: borrar esta regla). */
  body::before{content:"";position:fixed;top:0;left:0;right:0;height:4px;background:var(--accent);z-index:99999;pointer-events:none}
  /* Loader animado: reemplaza el "Cargando…" pelón del SPA. */
  .kload{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.7rem;padding:2.6rem 1rem;color:var(--mut);font-size:.92rem;font-weight:600}
  .kload::before{content:"";width:32px;height:32px;border-radius:50%;border:3px solid var(--line);border-top-color:var(--accent);animation:kspin .7s linear infinite}
  @keyframes kspin{to{transform:rotate(360deg)}}
  .side .marca{width:100%;margin-bottom:1.1rem}
  .side nav{display:flex;flex-direction:column;gap:.1rem;flex:1;min-height:0;overflow-y:auto;overscroll-behavior:contain}
  .nav{display:flex;align-items:center;gap:.7rem;padding:.62rem .75rem;border-radius:10px;color:var(--ink-mid);text-decoration:none;font-weight:600;font-size:.94rem;cursor:pointer;border:none;background:none;text-align:left;width:100%;transition:.12s}
  .nav:hover{background:var(--hover);color:var(--ink)}
  .nav.on{background:var(--acc-soft,#eaf6ef);color:var(--ink-strong,#1a1a2e)}
  .nav .ic{width:1.2rem;text-align:center;opacity:.85;font-size:1.05rem}
  .nav.on .ic{opacity:1}
  .nav .soon{margin-left:auto;font-size:.56rem;font-weight:800;color:var(--warn-ink);background:var(--warn-soft);padding:.1rem .4rem;border-radius:99px;letter-spacing:.03em}
  /* ---- Parpadeo "requiere atención" (Bot IA) ---- */
  @keyframes navpulse{0%,100%{background:transparent}50%{background:var(--danger-soft)}}
  .nav.pulsa{animation:navpulse 1.1s ease-in-out infinite}
  .navalert{display:none;margin-left:auto;background:var(--danger);color:#fff;font-size:.62rem;font-weight:800;min-width:18px;height:18px;border-radius:99px;padding:0 5px;align-items:center;justify-content:center;box-shadow:0 0 0 0 rgba(220,38,38,.5);animation:navdot 1.1s ease-in-out infinite}
  .nav.pulsa .navalert{display:inline-flex}
  @keyframes navdot{0%,100%{box-shadow:0 0 0 0 rgba(220,38,38,.45)}50%{box-shadow:0 0 0 5px rgba(220,38,38,0)}}
  .wafab{position:fixed;right:24px;top:16px;z-index:60;display:none;align-items:center;gap:.4rem;background:var(--accent);color:#fff;border:none;border-radius:99px;padding:.32rem .7rem;font-weight:800;font-size:.82rem;cursor:pointer;box-shadow:0 8px 22px -6px rgba(31,157,87,.6);animation:wafabpulse 1.1s ease-in-out infinite}
  .wafab .wafabic{font-size:1rem;line-height:1}
  .wafab .wafabn{background:var(--card);color:var(--accent);border-radius:99px;min-width:18px;height:18px;display:inline-flex;align-items:center;justify-content:center;font-size:.7rem;padding:0 5px}
  @keyframes wafabpulse{0%,100%{transform:scale(1);box-shadow:0 6px 18px -6px rgba(31,157,87,.5)}50%{transform:scale(1.06);box-shadow:0 12px 26px -4px rgba(31,157,87,.85)}}
  /* ---- Grupos acordeón del sidebar ---- */
  .navgrp{display:flex;flex-direction:column}
  .navgrphdr{display:flex;align-items:center;gap:.7rem;padding:.6rem .75rem;border-radius:10px;color:#7a7f87;background:none;border:none;cursor:pointer;text-align:left;width:100%;font-weight:800;font-size:.72rem;letter-spacing:.05em;text-transform:uppercase;transition:.12s}
  .navgrphdr:hover{background:var(--hover);color:var(--ink)}
  .navgrphdr .ic{width:1.2rem;text-align:center;opacity:.7;font-size:1rem}
  .navgrphdr .chev{margin-left:auto;font-size:.8rem;transition:transform .15s;opacity:.55}
  .navgrp.open .navgrphdr{color:var(--ink)}
  .navgrp.open .navgrphdr .chev{transform:rotate(90deg)}
  .navgrpitems{display:none;flex-direction:column;gap:.1rem;padding:.1rem 0 .3rem;margin:.05rem 0 .15rem .85rem;border-left:2px solid var(--line-2)}
  .navgrp.open .navgrpitems{display:flex}
  .navgrpitems .nav{font-size:.9rem;padding:.5rem .7rem}
  .livedot{display:inline-block;width:9px;height:9px;border-radius:50%;background:#e23b3b;animation:livepulse 1.4s infinite}
  .livedot.ok{background:var(--accent)}
  .livedot.mid{background:#e8a13d}
  .livedot.off{background:#9aa0a6;animation:none}
  .orweb{display:none;align-items:center;gap:.2rem;margin-left:6px;background:#2b6cb0;color:#fff;font-size:.64rem;font-weight:800;line-height:1;border-radius:999px;padding:.18rem .42rem;vertical-align:middle;box-shadow:0 0 0 0 rgba(43,108,176,.55);animation:orwebpulse 1.5s infinite}
  .orweb.on{display:inline-flex}
  @keyframes orwebpulse{0%{box-shadow:0 0 0 0 rgba(43,108,176,.55)}70%{box-shadow:0 0 0 6px rgba(43,108,176,0)}100%{box-shadow:0 0 0 0 rgba(43,108,176,0)}}
  @keyframes livepulse{0%{box-shadow:0 0 0 0 rgba(226,59,59,.55)}70%{box-shadow:0 0 0 7px rgba(226,59,59,0)}100%{box-shadow:0 0 0 0 rgba(226,59,59,0)}}
  .content{flex:1;min-width:0;display:flex;flex-direction:column}
  .topbar{position:sticky;top:0;z-index:5;background:rgba(255,255,255,.95);backdrop-filter:blur(8px);border-bottom:1px solid var(--line);padding:.9rem 1.6rem;display:flex;gap:.7rem;align-items:center;flex-wrap:wrap}
  .topbar h1{font-size:1.35rem;margin:0;font-weight:800;letter-spacing:-.02em}
  .topbar .sp{flex:1}
  .topbar label{font-size:.85rem;color:var(--mut);display:flex;align-items:center;gap:.4rem}
  .subnav{display:flex;flex-wrap:wrap;padding:.6rem 1.6rem;background:var(--card);border-bottom:1px solid var(--line)}
  .subnav,.tabsrow{gap:2px}
  .tabsrow{display:inline-flex;flex-wrap:wrap;background:var(--panel);border-radius:10px;padding:3px;margin-bottom:.8rem}
  .subnav .tab{background:transparent}
  .tab{background:transparent;border:none;border-radius:7px;padding:.5rem 1rem;cursor:pointer;color:var(--mut);font-weight:600;font-size:.92rem;transition:.15s}
  .tab:hover:not(.on){color:var(--ink)}
  .tab:hover{color:var(--ink)}
  .tab.on{color:var(--ink-strong,#1a1a2e);background:var(--card);font-weight:700;box-shadow:0 1px 2px rgba(16,24,40,.06),0 1px 3px rgba(16,24,40,.08)}
  main{max-width:1480px;margin:1.4rem auto;padding:0 1.5rem;width:100%}
  /* Tarjeta de ajuste estilo Maspedidos (título + descripción + cuerpo + footer) */
  .setcard{background:var(--card);border:1px solid var(--line);border-radius:14px;margin-bottom:1.1rem;box-shadow:0 1px 3px rgba(0,0,0,.04);overflow:hidden}
  .setcard h3{margin:0;padding:1.1rem 1.3rem .1rem;font-size:1.05rem;font-weight:800;letter-spacing:-.01em}
  .setcard .d{padding:0 1.3rem;color:var(--mut);font-size:.86rem;margin-top:.15rem}
  .setcard .b{padding:1rem 1.3rem}
  .setcard .b .field{margin-bottom:.8rem}.setcard .b .field:last-child{margin-bottom:0}
  .setcard .f{display:flex;justify-content:flex-end;gap:.6rem;padding:.8rem 1.3rem;border-top:1px solid var(--line);background:var(--wash)}
  .setcard.dirty{border-color:var(--warn-border);box-shadow:0 0 0 2px rgba(230,184,0,.14)}
  .setcard.dirty .f::before{content:"● Cambios sin guardar";color:var(--warn-ink);font-size:.8rem;font-weight:700;margin-right:auto;align-self:center}
  .hrow.dirty,.mrow2.dirty,.metrow.dirty,.crow.dirty{background:var(--warn-soft);box-shadow:inset 3px 0 0 var(--warn),0 0 0 1px var(--warn-border);border-radius:10px}
  .crow.dirty::after{content:"● Sin guardar";color:var(--warn-ink);font-weight:700;font-size:.75rem;align-self:center;margin-left:auto;white-space:nowrap}
  .hrow.dirty .hactions::before,.metrow.dirty .metrow-act::before{content:"● Sin guardar";color:var(--warn-ink);font-weight:700;font-size:.78rem;margin-right:.5rem;align-self:center}
  .mrow2.dirty::after{content:"● Sin guardar";color:var(--warn-ink);font-weight:700;font-size:.78rem;align-self:center;white-space:nowrap;margin-left:.2rem}
  .colhead{display:flex;align-items:center;gap:.5rem;margin:.2rem 0 .6rem;flex-wrap:wrap}
  /* ===== Panel maestro de Ventas ===== */
  .dgrid-kpi{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:10px;margin-bottom:1.2rem}
  .kpi2{background:var(--card);border:1px solid var(--line);border-radius:12px;padding:.85rem 1rem}
  .kpi2.alert{border-color:var(--danger-border);background:var(--danger-soft)}
  .k2{font-size:.78rem;color:var(--mut);font-weight:600}
  .v2{font-size:1.5rem;font-weight:800;letter-spacing:-.01em;margin-top:.1rem}
  .s2{font-size:.76rem;margin-top:.05rem}
  .dsec{display:flex;align-items:center;gap:.5rem;font-size:1.02rem;font-weight:800;margin:1.1rem 0 .7rem}
  .ddot{width:9px;height:9px;border-radius:50%;display:inline-block}
  .dmeta{font-size:.78rem;color:var(--mut);font-weight:500}
  .dgrid-area{display:grid;grid-template-columns:repeat(auto-fit,minmax(165px,1fr));gap:10px}
  .areacard{background:var(--card);border:1px solid var(--line);border-radius:12px;padding:.8rem}
  .areah{display:flex;justify-content:space-between;align-items:center;font-size:.9rem;font-weight:700;margin-bottom:.5rem}
  .evrow{border-top:1px solid var(--line-2);padding:.42rem 0;cursor:pointer}
  .evrow:first-of-type{border-top:none}
  .evtop{display:flex;justify-content:space-between;align-items:center;gap:.4rem}
  .evlbl{font-size:.84rem;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .evmin{font-size:.8rem;font-weight:800;white-space:nowrap}
  .evbot{display:flex;align-items:center;gap:.4rem;margin-top:.15rem;flex-wrap:wrap}
  .evbot>span:first-child{font-size:.82rem}
  .evcod{font-family:ui-monospace,monospace;font-size:.66rem;color:var(--mut);background:var(--soft);border-radius:4px;padding:0 .3rem;letter-spacing:.3px}
  .evchip{font-size:.66rem;padding:1px 7px;border-radius:99px;font-weight:700}
  .dsuc{font-size:.64rem;color:var(--mut);border:1px solid var(--line);border-radius:99px;padding:1px 6px}
  .dgrid2{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:1rem}
  /* ===== Tablero Ventas v2 ===== */
  .v2top{display:grid;grid-template-columns:1.05fr 1fr;gap:14px;margin-bottom:18px}
  .v2card{background:var(--card);border:1px solid var(--line);border-radius:14px;padding:15px 17px}
  .v2kstop{display:flex;align-items:center;gap:14px;margin-bottom:13px}
  .v2live{display:inline-flex;align-items:center;gap:6px;font-size:13px;font-weight:600}
  .v2live i{width:8px;height:8px;border-radius:50%;background:#e24b4a;display:inline-block}
  .v2krow{display:flex;align-items:flex-start}
  .v2km{flex:1;padding:2px 10px;min-width:0}
  .v2km+.v2km{border-left:1px solid var(--line)}
  .v2km:first-child{padding-left:2px}
  .v2kk{font-size:11px;color:var(--mut);line-height:1.25;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .v2kv{font-size:20px;font-weight:800;letter-spacing:-.3px;margin-top:2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .v2kd{font-size:10.5px;font-weight:700;margin-top:2px;white-space:nowrap}
  .v2flow{border-top:1px solid var(--line);margin-top:14px;padding-top:12px;display:flex;align-items:center;gap:8px}
  .v2pstep{flex:1;text-align:center}
  .v2pstep>.n{font-size:21px;font-weight:800}
  .v2pstep>.u{height:3px;border-radius:2px;margin:5px 12px}
  .v2pstep>.l{font-size:11px;color:var(--mut)}
  .v2parr{color:var(--mut-2)}
  .v2chart{display:flex;align-items:flex-end;gap:6px;height:92px;margin-top:13px}
  .v2chart>.bar{flex:1;border-radius:3px 3px 0 0}
  .v2lab{display:flex;gap:6px;margin-top:6px}
  .v2lab>span{flex:1;text-align:center;font-size:9.5px;font-weight:700;color:var(--mut)}
  .v2hrs{display:flex;gap:6px;margin-top:3px}
  .v2hrs>span{flex:1;text-align:center;font-size:10px;color:var(--mut-2)}
  .v2board{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:12px;margin-bottom:22px}
  /* Pedido dentro de la tarjeta de canal: SIEMPRE fue clickeable (abre el pop-up) pero
     no lo anunciaba. Manita + iluminación al hover (Ronel 27-jul). Tokens del tema, así
     que se ve bien en día y en noche; solo en dispositivos con puntero real (hover:hover)
     para no dejar el highlight pegado tras un tap en iPad. Solo se transiciona el
     background del hover (no anima nada en reposo — ver nota PERF de abajo). */
  .v2ev{cursor:pointer;border-radius:8px;transition:background-color .12s ease}
  @media(hover:hover){ .v2ev:hover{background:var(--soft)} }
  /* Latido de pedido urgente. PERF: no se animan ni background ni box-shadow — eso obliga
     a recalcular color y REPINTAR en cada frame, y con color-mix sobre una var() encima el
     motor tiene que resolver la mezcla 60 veces por segundo. En su lugar el color va
     ESTATICO en un ::after y solo se anima su opacity, que el compositor resuelve en GPU
     sin tocar el hilo principal. Se ve igual y cuesta una fraccion. */
  @keyframes v2pulseop{0%,100%{opacity:0}50%{opacity:1}}
  .v2ev.pulse{position:relative}
  .v2ev.pulse::after{
    content:'';position:absolute;inset:0;pointer-events:none;
    background:color-mix(in srgb,var(--danger) 22%,transparent);
    box-shadow:inset 4px 0 0 0 var(--danger);
    opacity:0;will-change:opacity;animation:v2pulseop 1.15s ease-in-out infinite}
  /* Parpadeo ~10s al cambiar de estado (cocina → por empacar): tarjeta + número del pipeline. */
  @keyframes v2flashcard{0%,100%{background:transparent;box-shadow:inset 3px 0 0 0 rgba(245,158,11,0)}50%{background:var(--warn-soft);box-shadow:inset 3px 0 0 0 rgba(245,158,11,.95)}}
  .v2ev.flashchg{animation:v2flashcard .8s ease-in-out infinite}
  @keyframes v2flashnum{0%,100%{transform:scale(1);opacity:1}50%{transform:scale(1.32);opacity:.4}}
  .v2pstep>.n.flashn{animation:v2flashnum .7s ease-in-out infinite;display:inline-block}
  /* Badge "estado del servicio" (opción B, Ronel 6 jun 26): punto vivo que late — verde lento, rojo rápido. */
  /* Halo del punto "en tiempo": anillo estatico, se anima opacity+transform. */
  @keyframes v2dotokring{0%{opacity:.8;transform:scale(.9)}70%,100%{opacity:0;transform:scale(1.7)}}
  @keyframes v2doturp{0%,100%{box-shadow:0 0 0 0 rgba(226,75,74,.5)}50%{box-shadow:0 0 0 5px rgba(226,75,74,0)}}
  /* Chip "N urgentes". Mismo criterio: el anillo es estatico y lo que se anima es
     opacity + transform, las dos propiedades que NO provocan repintado. */
  @keyframes v2urgring{0%{opacity:.85;transform:scale(.97)}70%,100%{opacity:0;transform:scale(1.09)}}
  /* El fondo vuelve a latir (Ronel lo pidio de vuelta: al pasar todo a ::after el chip
     habia quedado con fondo FIJO y solo el anillo en movimiento, o sea perdio dos de sus
     tres senales). Late entre --danger-soft y el 26% del rojo pleno, igual que antes de
     4d3ffe0 — pero ahora es un ::before al que se le anima la OPACIDAD, no la propiedad
     background. Se ve idéntico y no repinta.
     isolation:isolate es obligatorio: crea contexto de apilamiento para que el z-index:-1
     del ::before quede DENTRO del chip (encima de su fondo, debajo del texto). Sin eso el
     relleno se iria detras del fondo del ancestro y no se veria. */
  .v2urg{display:inline-flex;align-items:center;gap:6px;background:var(--danger-soft);color:var(--danger-ink);font-size:12.5px;font-weight:800;padding:6px 13px;border-radius:999px;cursor:pointer;white-space:nowrap;position:relative;isolation:isolate}
  @keyframes v2urgfill{0%,100%{opacity:0}50%{opacity:1}}
  .v2urg::before{content:'';position:absolute;inset:0;border-radius:inherit;pointer-events:none;z-index:-1;
    background:color-mix(in srgb,var(--danger) 26%,transparent);
    opacity:0;will-change:opacity;animation:v2urgfill 1.15s ease-in-out infinite}
  .v2urg::after{content:'';position:absolute;inset:0;border-radius:inherit;pointer-events:none;
    box-shadow:0 0 0 6px color-mix(in srgb,var(--danger) 45%,transparent);
    opacity:0;will-change:opacity,transform;animation:v2urgring 1.15s ease-out infinite}
  /* El punto ya no late por su cuenta: el chip entero tiene su anillo, y este halo era
     una segunda animacion de box-shadow (repintado) corriendo en permanente sobre el
     mismo elemento, redundante visualmente y cara. */
  /* El halo del puntito: era v2doturp y se elimino en 4d3ffe0 por "redundante y caro".
     Lo de caro era cierto (box-shadow); lo de redundante lo decidi yo, no Ronel. Vuelve,
     con el mismo aspecto pero como anillo de opacity+transform.
     De paso el halo sigue a var(--danger) con color-mix, en vez del rgba(226,75,74,.5)
     fijo que tenia — que ni siquiera coincidia con el rojo del token. */
  @keyframes v2doturing{0%{opacity:.6;transform:scale(1)}70%,100%{opacity:0;transform:scale(2.4)}}
  .v2urg i{width:9px;height:9px;border-radius:50%;background:var(--danger);display:inline-block;position:relative}
  .v2urg i::after{content:'';position:absolute;inset:0;border-radius:50%;pointer-events:none;
    background:color-mix(in srgb,var(--danger) 50%,transparent);
    opacity:0;will-change:opacity,transform;animation:v2doturing 1.1s ease-out infinite}
  .v2urg.on{outline:2px solid var(--danger-ink);outline-offset:1px}
  /* Quien pide movimiento reducido no debe QUEDARSE SIN el aviso: en vez de apagar la
     animacion y dejarlo invisible, se congela en el estado de mayor contraste. */
  @media (prefers-reduced-motion:reduce){
    .v2ev.pulse::after{animation:none;opacity:1}
    .v2urg::after{animation:none;opacity:.55;transform:none}
    .v2urg::before{animation:none;opacity:1}
    .v2urg i::after{animation:none;opacity:.5;transform:scale(1.6)}
    .v2ok i::after{animation:none;opacity:.7;transform:none}
  }
  /* Pill NEUTRO: el unico color es el punto, y asi el verde se lee como senal en vez de
     competir con un fondo verde palido. */
  .v2ok{display:inline-flex;align-items:center;gap:6px;background:var(--soft);color:var(--ink);font-size:12px;font-weight:700;padding:6px 12px;border-radius:999px;white-space:nowrap;border:1px solid var(--line)}
  /* El punto usa var(--ok), NO var(--accent). Con el skin "Rojo KERP" el acento es rojo,
     asi que "en tiempo" salia con un punto ROJO — el skin rompia el significado. theme.css
     lo dice en su cabecera: los semanticos son fijos para que ningun skin los pise. */
  .v2ok i{width:10px;height:10px;border-radius:50%;background:var(--ok);display:inline-block;position:relative}
  .v2ok i::after{content:'';position:absolute;inset:0;border-radius:50%;pointer-events:none;
    box-shadow:0 0 0 4px color-mix(in srgb,var(--ok) 55%,transparent);
    opacity:0;will-change:opacity,transform;animation:v2dotokring 1.25s ease-out infinite}
  .v2grid2{display:grid;grid-template-columns:1fr 1fr;gap:14px}
  .v2dcard{background:var(--card);border:1px solid var(--line);border-radius:14px;padding:14px 16px}
  .v2dcard h4{margin:0 0 11px;font-size:13.5px;font-weight:700}
  .v2fh{font-size:10.5px;color:var(--mut-2);font-weight:400}
  .v2sbar{display:flex;height:12px;border-radius:6px;overflow:hidden;margin:6px 0 13px}
  .v2legrow{display:flex;align-items:center;gap:9px;font-size:12.5px;margin-bottom:9px}
  .v2dot{width:10px;height:10px;border-radius:3px;flex-shrink:0;display:inline-block}
  .v2frow{cursor:pointer;border-radius:7px;padding:5px 7px;margin:0 -7px}
  .v2frow:hover{background:var(--hover)}
  .v2frow.on{background:var(--ok-soft);outline:1.5px solid var(--accent)}
  .v2tp{display:flex;align-items:center;gap:11px;padding:8px 0;border-top:1px solid var(--line)}
  .v2tp:first-of-type{border-top:0;padding-top:0}
  .v2tprank{width:22px;height:22px;border-radius:6px;background:var(--hover);display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:700;color:var(--mut);flex-shrink:0}
  @media(max-width:900px){.v2top,.v2grid2{grid-template-columns:1fr}}
  .dcard{background:var(--card);border:1px solid var(--line);border-radius:12px;padding:.9rem 1rem;margin-bottom:1rem}
  .dcard-h{font-size:.9rem;font-weight:700;margin-bottom:.6rem}
  .dbar{margin-bottom:.5rem}
  .dbar-h{display:flex;justify-content:space-between;font-size:.82rem;margin-bottom:.2rem}
  .dbar-t{height:8px;background:var(--soft);border-radius:99px;overflow:hidden}
  .dbar-f{height:8px;background:var(--accent);border-radius:99px}
  .fincard{background:var(--card);border:1px solid var(--line);border-radius:12px;padding:.8rem}
  .finv{font-size:1.25rem;font-weight:800;margin-top:.1rem}
  .catcard{background:var(--card);border:1px solid var(--line);border-radius:16px;margin:1rem 0;overflow:hidden;box-shadow:0 1px 3px rgba(0,0,0,.04)}
  .catcard-h{display:flex;align-items:center;gap:.6rem;padding:.95rem 1.2rem;background:var(--wash);border-bottom:1px solid var(--line)}
  .catcard-h .ct{font-weight:800;font-size:1.02rem;flex:1;letter-spacing:-.01em}
  .catcard-h .cn{font-size:.78rem;color:var(--mut);font-weight:600}
  .catcol{border:none;background:none;cursor:pointer;font-size:1.35rem;line-height:1;color:var(--ink);width:34px;height:34px;border-radius:8px;display:inline-flex;align-items:center;justify-content:center;transition:transform .15s,background .12s;flex:none}
  .catcol:hover{background:var(--panel)}
  .catcard.col .catcol{transform:rotate(-90deg)}
  .catcard.col .pgrid{display:none}
  .prow{display:flex;align-items:center;gap:.9rem;padding:.8rem 1.2rem;border-top:1px solid var(--line-2)}
  .prow:first-of-type{border-top:none}
  .prow .pimg{width:54px;height:54px;border-radius:11px;object-fit:cover;background:var(--soft);flex:none}
  .prow .pinfo{flex:1;min-width:0}
  .prow .pn2{font-weight:700}
  .prow .pmeta{font-size:.85rem;color:var(--mut);margin-top:.25rem;display:flex;gap:.6rem;align-items:center;flex-wrap:wrap}
  /* Productos en rejilla de tarjetas (3 columnas, estilo ERP) con número de orden */
  .pgrid{display:grid;grid-template-columns:repeat(3,1fr);gap:.75rem;padding:.9rem 1.1rem}
  @media(max-width:1100px){.pgrid{grid-template-columns:repeat(2,1fr)}}
  @media(max-width:680px){.pgrid{grid-template-columns:1fr}}
  .pcard{position:relative;border:1px solid var(--line);border-radius:13px;background:var(--card);padding:.55rem;display:flex;flex-direction:column;gap:.45rem;transition:box-shadow .12s,transform .08s}
  .pcard:hover{box-shadow:0 4px 14px rgba(0,0,0,.09)}
  .pcard .pcimg{width:100%;height:120px;border-radius:10px;object-fit:cover;background:var(--soft)}
  .pcard .pcimg-ph{display:flex;align-items:center;justify-content:center;font-size:1.8rem}
  .pcard .pcname{font-weight:700;font-size:.92rem;line-height:1.2;color:var(--ink)}
  .pcard .pcmeta{display:flex;align-items:center;justify-content:space-between;gap:.4rem;margin-top:auto}
  .pcard .pcedit{width:100%;margin-top:.15rem}
  .pnum{position:absolute;top:9px;left:9px;z-index:2;min-width:23px;height:23px;padding:0 .35rem;border-radius:99px;background:rgba(17,19,23,.8);color:#fff;font-size:.74rem;font-weight:800;display:inline-flex;align-items:center;justify-content:center}
  .pchnd{position:absolute;top:9px;right:9px;z-index:2;background:rgba(255,255,255,.92);border:1px solid var(--line);border-radius:7px;width:24px;height:24px;display:inline-flex;align-items:center;justify-content:center;font-size:.8rem}
  /* Configuración: menú vertical + contenido (estilo Maspedidos) */
  .cfgwrap{display:flex;gap:1.4rem;align-items:flex-start}
  .cfgnav{width:240px;flex:none;background:var(--card);border:1px solid var(--line);border-radius:14px;padding:.45rem;position:sticky;top:84px;box-shadow:0 1px 3px rgba(0,0,0,.04)}
  .cfgnav .grp{font-size:.66rem;font-weight:800;letter-spacing:.06em;text-transform:uppercase;color:var(--mut);padding:.8rem .65rem .35rem}
  .cfgnav button{display:flex;align-items:center;gap:.6rem;width:100%;text-align:left;border:none;background:none;padding:.55rem .65rem;border-radius:9px;font-weight:600;font-size:.9rem;color:var(--ink-mid);cursor:pointer;transition:.12s}
  .cfgnav button:hover{background:var(--hover);color:var(--ink)}
  .cfgnav button.on{background:var(--acc-soft,#eaf6ef);color:var(--ink-strong,#1a1a2e)}
  .cfgnav .ic{width:1.1rem;text-align:center}
  /* Configuración como panel de pantalla completa (estilo Maspedidos) */
  .cfgscreen{position:fixed;inset:0;background:var(--bg);z-index:60;overflow-y:auto;overflow-x:hidden;overscroll-behavior:contain}
  .cfghead{position:sticky;top:0;background:var(--card);border-bottom:1px solid var(--line);display:flex;align-items:center;justify-content:space-between;padding:1rem 1.6rem;z-index:3}
  .cfghead h2{margin:0;font-size:1.25rem;font-weight:800;color:var(--ink)}
  .cfgx{width:38px;height:38px;border-radius:50%;border:1px solid var(--line);background:var(--card);cursor:pointer;font-size:1.05rem;color:var(--ink);display:flex;align-items:center;justify-content:center;line-height:1;margin-right:55px}
  .cfgx:hover{background:var(--hover)}
  .cfgscreen .cfgwrap{padding:1.5rem 1.8rem 3rem;max-width:none;margin:0;align-items:flex-start}
  .cfgscreen .cfgnav{top:1.5rem}
  @media(max-width:760px){.cfgscreen .cfgnav{top:0}}
  .cfgbody{flex:1;min-width:0}
  .cfgbody .cat{font-size:1.05rem;text-transform:none;letter-spacing:-.01em;color:var(--ink);font-weight:800;margin:.2rem 0 .55rem}
  .cfgbody .cat:first-child{margin-top:.1rem}
  .cfgbody .card{padding:1.1rem 1.2rem}
  .cfgbody .card .btn{margin-top:.3rem}
  /* Iconos de marca junto al título */
  .mswrap{display:inline-flex;gap:.4rem;flex-wrap:wrap;align-items:center}
  .mswbtn{display:inline-flex;align-items:center;gap:.45rem;border:1px solid var(--line);background:var(--card);border-radius:99px;padding:.18rem .7rem .18rem .18rem;cursor:pointer;font-weight:700;font-size:.85rem;color:var(--ink-mid);transition:.12s}
  .mswbtn:hover{background:var(--hover)}
  .mswbtn.on{border-color:var(--accent);background:var(--ok-soft);color:var(--accent-d)}
  .mswbtn img,.mswbtn .msini{width:26px;height:26px;border-radius:50%;object-fit:cover;flex:none;display:inline-flex;align-items:center;justify-content:center;background:var(--soft);font-size:.7rem;font-weight:800;color:var(--mut);border:1px solid var(--line)}
  /* Chip de marca del switcher = MISMA presentación que el sidebar (.sclogo; regla unificada abajo).
     Botón sin decoración; la marca activa lleva un subrayado fino de acento (el logo queda intacto). */
  .mswlogo{display:inline-flex;align-items:center;border:0;background:none;padding:0;margin:0;cursor:pointer;position:relative}
  .mswlogo.on::after{content:"";position:absolute;left:5px;right:5px;bottom:-5px;height:2px;border-radius:2px;background:var(--accent)}
  .mswbtn>.mswname{padding:0 .28rem}
  /* Hub por entidad (sucursal / marca) */
  .hubchips{display:inline-flex;flex-wrap:wrap;gap:2px;background:var(--panel);border-radius:10px;padding:3px;margin:.1rem 0 .7rem}
  .dashlogos{display:inline-flex;gap:.45rem;align-items:center;flex-wrap:wrap}
  .dashlogos .sclogo{width:36px;height:36px}
  .hubchip{display:inline-flex;align-items:center;gap:.4rem;border:none;background:transparent;border-radius:7px;padding:.45rem .95rem;font-weight:600;font-size:.9rem;color:var(--mut);cursor:pointer;transition:.15s}
  .hubchip:hover:not(.on){color:var(--ink)}
  .hubchip:hover{background:var(--hover)}
  .hubchip.on{background:var(--card);color:var(--ink-strong,#1a1a2e);font-weight:700;box-shadow:0 1px 2px rgba(16,24,40,.06),0 1px 3px rgba(16,24,40,.08)}
  .hubchip.add{border-style:dashed;color:var(--mut);font-weight:600}
  .envmodoseg{display:inline-flex;flex-wrap:wrap;gap:6px;background:var(--panel);border-radius:12px;padding:5px;margin-top:.3rem}
  .emchip{border:none;background:transparent;border-radius:9px;padding:.55rem 1rem;font-weight:700;font-size:.9rem;color:var(--mut);cursor:pointer;transition:.15s;white-space:nowrap}
  .emchip:hover:not(.on){color:var(--ink);background:var(--hover)}
  .emchip.on{background:var(--accent);color:#fff;box-shadow:0 2px 8px rgba(16,24,40,.14)}
  /* Editor de empleado — tarjeta a 2 columnas (escritorio) / 1 columna (móvil) */
  .emp-modal-box{width:min(700px,calc(100vw - 28px))!important;max-width:700px!important;max-height:90vh;overflow:auto}
  .empgrid{display:grid;grid-template-columns:1fr 1fr;gap:20px}
  .empsec{font-size:11px;font-weight:800;color:var(--mut);text-transform:uppercase;letter-spacing:.05em;margin:0 0 .55rem}
  .emppanel{background:var(--bg);border:1px solid var(--line);border-radius:12px;padding:.85rem .95rem}
  .empro{display:block;font-size:11.5px;color:var(--mut);font-weight:600;margin-bottom:3px}
  .empval{font-size:15px;font-weight:700;color:var(--ink);font-variant-numeric:tabular-nums;line-height:1.25}
  .empinfo{background:var(--card);border:1px solid var(--line);border-radius:8px;padding:.42rem .55rem;font-size:12.5px;color:var(--ink);font-variant-numeric:tabular-nums}
  @media(max-width:680px){.empgrid{grid-template-columns:1fr}}
  .hubchip .hubmz{font-size:.62rem;font-weight:800;text-transform:uppercase;letter-spacing:.03em;color:var(--warn-ink);background:var(--warn-soft);border-radius:99px;padding:.05rem .4rem}
  .hrow{border:1px solid var(--line);border-radius:12px;padding:.85rem;margin-bottom:.7rem;background:var(--card)}
  .hrow-top{display:flex;gap:.7rem;flex-wrap:wrap;align-items:flex-end;margin-bottom:.75rem}
  .hrow .hn{flex:1;min-width:160px;font-weight:600}
  .htimes{display:flex;align-items:flex-end;gap:.5rem}
  .htimes label{display:flex;flex-direction:column;font-size:.7rem;color:var(--mut);gap:.2rem;font-weight:700}
  .htimes input[type=time]{width:130px}
  .hsep{color:var(--mut);padding-bottom:.45rem;font-size:1.1rem}
  .hrow-bot{display:flex;gap:.6rem;flex-wrap:wrap;align-items:center;justify-content:space-between}
  .hdias{display:flex;gap:.35rem;flex-wrap:wrap}
  .hday{width:34px;height:34px;border-radius:50%;border:1px solid var(--line);background:var(--card);color:var(--mut);font-weight:800;font-size:.8rem;cursor:pointer;transition:.12s}
  .hday:hover{background:var(--hover)}
  .hday.on{background:var(--accent);border-color:var(--accent);color:#fff}
  .hactions{display:flex;gap:.5rem;align-items:center}
  .hubtabs{display:flex;flex-wrap:wrap;gap:.2rem;border-bottom:1px solid var(--line);margin-bottom:1rem;position:sticky;top:63px;background:var(--bg);z-index:5;padding-top:.45rem}
  /* Barra flotante del hub de sucursal: chips (TANLUM/PACABTUN…) + pestañas, sticky como una sola unidad. */
  .suchubbar{position:sticky;top:63px;z-index:6;background:var(--bg);margin-bottom:1rem}
  .suchubbar .hubchips{margin:.1rem 0 .5rem}
  .suchubbar .hubtabs{position:static;top:auto;margin-bottom:0;z-index:auto;padding-top:0}
  .hubtab{border:none;background:none;padding:.5rem .8rem;border-radius:8px 8px 0 0;font-weight:700;font-size:.88rem;color:var(--mut);cursor:pointer;border-bottom:2px solid transparent;margin-bottom:-1px}
  .hubtab:hover{color:var(--ink)}
  .hubtab.on{color:var(--accent);border-bottom-color:var(--accent)}
  /* Secciones de sucursal en cascada (scroll + índice) */
  .hubsec{scroll-margin-top:120px;margin-bottom:1.5rem}
  .hubsec:last-child{margin-bottom:0}
  .hubsec-h{font-size:1rem;font-weight:800;color:var(--ink);margin:.2rem 0 .7rem;padding-bottom:.35rem;border-bottom:1px dashed var(--line)}
  @media(max-width:760px){.cfgwrap{flex-direction:column}.cfgnav{width:100%;position:static;display:flex;flex-wrap:wrap;gap:.2rem}.cfgnav .grp{width:100%}.cfgnav button{width:auto}}

  .cat{margin:1.5rem 0 .5rem;font-size:.76rem;font-weight:800;letter-spacing:.06em;color:var(--mut);text-transform:uppercase}
  .card{background:var(--card);border:1px solid var(--line);border-radius:14px;padding:.85rem;margin:.6rem 0;display:flex;gap:.8rem;box-shadow:0 1px 3px rgba(0,0,0,.04)}
  .thumb{width:56px;height:56px;border-radius:10px;object-fit:cover;background:var(--soft);flex:none}
  .body{flex:1;min-width:0}
  .pname{font-weight:700;margin:0 0 .15rem}
  .row{display:flex;gap:.5rem;align-items:center;flex-wrap:wrap;font-size:.9rem;color:var(--mut);margin-top:.4rem}
  .pres{display:flex;gap:.6rem;align-items:center;padding:.4rem 0;border-top:1px solid var(--line-2);font-size:.92rem}
  .pres .nm{flex:1;min-width:0}
  .price{font-weight:700;color:var(--ink)}
  .badge{font-size:.68rem;font-weight:700;padding:.16rem .55rem;border-radius:99px;text-transform:uppercase;letter-spacing:.02em}
  .b-publicado{background:var(--ok-soft);color:var(--ok-ink)}.b-borrador{background:var(--panel);color:var(--ink-mid)}.b-pausado{background:var(--warn-soft);color:var(--warn-ink)}
  .agot{display:flex;gap:.35rem;align-items:center;font-size:.82rem;color:var(--mut);cursor:pointer}
  /* Disponibilidad estilo Maspedidos */
  .dtools{display:flex;align-items:center;justify-content:space-between;gap:.6rem;margin:.2rem 0 .8rem;flex-wrap:wrap}
  .chips{display:flex;gap:.4rem}
  .chip{border:1px solid var(--line);background:var(--card);color:var(--mut);border-radius:99px;padding:.4rem .95rem;font-weight:700;font-size:.85rem;cursor:pointer}
  .chip.on{border-color:var(--accent);color:var(--accent);background:var(--ok-soft)}
  .dsearch{display:flex;align-items:center;gap:.4rem;border:1px solid var(--line);border-radius:10px;padding:.4rem .7rem;background:var(--card)}
  .dsearch input{border:none;outline:none;font-size:.9rem;min-width:160px}
  .drow{display:flex;align-items:center;gap:.75rem;padding:.55rem .2rem;border-top:1px solid var(--line-2)}
  .dthumb{width:46px;height:46px;border-radius:9px;object-fit:cover;background:var(--soft);flex:none;display:flex;align-items:center;justify-content:center;font-size:1.1rem;color:var(--mut-2)}
  .dname{flex:1;min-width:0;font-size:.94rem;font-weight:600}
  .dname small{display:block;font-weight:500;color:var(--mut);font-size:.8rem}
  .dpill{font-size:.72rem;font-weight:700;color:var(--ink-mid);background:var(--panel);border-radius:99px;padding:.2rem .6rem;white-space:nowrap}
  .dprice{font-weight:700;color:var(--ink);min-width:64px;text-align:right;font-size:.9rem}
  .dsw{position:relative;width:42px;height:24px;border-radius:99px;background:var(--line);border:none;cursor:pointer;flex:none;transition:background .15s}
  .dsw::after{content:"";position:absolute;top:2px;left:2px;width:20px;height:20px;border-radius:50%;background:var(--card);transition:left .15s;box-shadow:0 1px 2px rgba(0,0,0,.25)}
  .dsw.on{background:var(--accent)}.dsw.on::after{left:20px}
  .dthead{display:flex;align-items:center;gap:.75rem;padding:.4rem .2rem;color:var(--mut);font-size:.74rem;font-weight:800;letter-spacing:.04em;text-transform:uppercase;border-bottom:2px solid var(--line)}
  /* Tabla de pedidos estilo Maspedidos */
  .ptable{width:100%;table-layout:fixed;border-collapse:collapse;background:var(--card);border:1px solid var(--line);border-radius:14px;overflow:hidden;box-shadow:0 1px 3px rgba(0,0,0,.04)}
  .ptable td{word-wrap:break-word}
  .ptable th{text-align:left;font-size:.72rem;font-weight:800;letter-spacing:.04em;text-transform:uppercase;color:var(--mut);padding:.7rem .9rem;border-bottom:2px solid var(--line);background:var(--wash)}
  .ptable th.r,.ptable td.r{text-align:right}
  .ptable td{padding:.95rem 1rem;border-top:1px solid var(--line-2);font-size:.92rem;vertical-align:middle}
  .ptable tbody tr{cursor:pointer}
  .ptable tbody tr:hover{background:var(--hover)}
  .ptable tr.nv{background:var(--wash)}
  .ptable .fo{font-weight:800;white-space:nowrap}
  .ptable tr.pdgrp td{padding:.5rem 1rem .35rem;font-size:.68rem;font-weight:800;letter-spacing:.05em;color:var(--mut);background:var(--wash);cursor:default}
  .ptable tr.pdgrp.rojo td{color:var(--danger-ink)}
  .ptable tr.fin td{opacity:.6}
  .tagnew{font-size:.62rem;font-weight:800;color:var(--ok-ink);background:var(--ok-soft);border-radius:99px;padding:.1rem .45rem;margin-left:.35rem;text-transform:uppercase}
  .pp{font-size:.74rem;font-weight:700;padding:.18rem .55rem;border-radius:99px;white-space:nowrap}
  .pp.ok{background:var(--ok-soft);color:var(--ok-ink)}.pp.pend{background:var(--warn-soft);color:var(--warn-ink)}
  .tchip{display:inline-block;font-size:.78rem;font-weight:700;color:var(--info-ink);background:var(--info-soft);border:1px solid var(--info-border);border-radius:8px;padding:.2rem .6rem;white-space:nowrap}
  .ed-acc{display:flex;gap:.5rem;align-items:center;flex-wrap:wrap;padding:.7rem 1.1rem;border-bottom:1px solid var(--line);background:var(--wash)}
  /* KDS / comandas */
  .kdsgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:.9rem;align-items:start;background:var(--card)}
  .kdscard{border:1px solid var(--line);border-radius:14px;padding:.9rem 1rem;box-shadow:0 1px 3px rgba(0,0,0,.05);background:var(--card)}
  .kdsh{display:flex;justify-content:space-between;gap:.5rem;font-size:.95rem;font-weight:700}
  .kdst{color:var(--mut);font-weight:600;font-size:.82rem;white-space:nowrap}
  .kdssub{color:var(--mut);font-size:.82rem;margin:.1rem 0 .5rem}
  .kdsit{border-top:1px solid var(--line-2);padding:.4rem 0;font-size:.92rem}
  .kdsit .q{font-weight:800}
  .kdsnota{margin-top:.4rem;background:var(--warn-soft);border-radius:8px;padding:.35rem .55rem;font-size:.82rem;color:var(--warn-ink)}
  /* Mesas */
  .mesagrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(130px,1fr));gap:.7rem;margin-bottom:.6rem}
  .mesacard{border-radius:14px;padding:1rem;text-align:center;cursor:pointer;border:1.5px solid var(--line);background:var(--card);transition:transform .08s}
  .mesacard:hover{transform:translateY(-2px)}
  .mesacard .mesan{font-weight:800;font-size:1.05rem}
  .mesacard .mesae{font-size:.74rem;font-weight:700;text-transform:uppercase;letter-spacing:.03em;margin:.25rem 0}
  .mesacard .mesat{font-weight:800}
  .mesacard .mesat.libre{color:var(--accent)}
  .mesacard.libre{border-style:dashed;border-color:var(--ok-border)}.mesacard.libre .mesae{color:var(--accent-d)}
  .mesacard.ocup{background:var(--warn-soft);border-color:var(--warn-border)}.mesacard.ocup .mesae{color:var(--warn-ink)}
  /* Marcas (config) */
  .mkhead{display:flex;gap:1.1rem;align-items:flex-start;flex-wrap:wrap}
  .mklogobox{flex:none;width:64px;display:flex;flex-direction:column;gap:.4rem;align-items:stretch}
  .mklogobox .mkprev{width:64px;height:64px;border-radius:12px;object-fit:contain;background:var(--card);border:1px solid var(--line)}
  .mklogobox .mkph{width:64px;height:64px;border-radius:12px;display:flex;align-items:center;justify-content:center;font-size:1.6rem;background:var(--soft);border:1px dashed var(--line)}
  .mklogobox .btn{padding:.28rem .3rem;font-size:.7rem;white-space:nowrap}
  .mkfields{flex:1;min-width:240px;display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr) auto;gap:.9rem;align-items:end}
  .mkfields .field{min-width:0}
  @media(max-width:680px){.mkfields{grid-template-columns:1fr}}
  .mksub{margin-top:1rem;border:1px solid var(--line);border-radius:12px;padding:.9rem 1rem;background:var(--wash)}
  .mksub-h{font-size:.72rem;font-weight:800;letter-spacing:.05em;text-transform:uppercase;color:var(--mut);margin-bottom:.75rem}
  .mkappear{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:1rem;align-items:start}
  @media(max-width:680px){.mkappear{grid-template-columns:1fr}}
  .mkcol{display:flex;flex-direction:column;gap:.45rem;min-width:0}
  .mkcol>span{font-size:.8rem;color:var(--mut);font-weight:700}
  .mkcol small{font-size:.74rem;color:var(--mut-2);line-height:1.3}
  .mkcol .mkestilo{width:100%}
  .mkswatch{display:inline-flex;align-items:center;gap:.55rem;cursor:pointer;width:fit-content}
  .mkswatch input[type=color]{width:46px;height:34px;padding:2px;border:1px solid var(--line);border-radius:9px;cursor:pointer;background:var(--card);flex:none}
  .mkswatch .mkhex{font-family:ui-monospace,SFMono-Regular,monospace;font-size:.8rem;color:var(--ink);letter-spacing:.02em}
  .mksame{display:inline-flex;align-items:center;gap:.4rem;font-size:.78rem;color:var(--mut);cursor:pointer}
  .mksame input{width:15px;height:15px;accent-color:var(--accent)}
  .mkcol.dim .mkswatch{opacity:.4;pointer-events:none}
  /* ----- Sitio web de la marca: layout premium + preview en vivo ----- */
  .mkweb{background:var(--card);border-radius:14px;box-shadow:0 1px 3px rgba(0,0,0,.05)}
  .mkweb-grid{display:grid;grid-template-columns:minmax(0,1fr) clamp(270px,32%,400px);gap:1.1rem;align-items:start}
  @media(max-width:1100px){.mkweb-grid{grid-template-columns:1fr}.mkweb-side{position:static;order:-1}}
  .mkweb-form{display:flex;flex-direction:column;gap:.85rem;min-width:0}
  .wgrp{border:1px solid var(--line);border-radius:12px;padding:.8rem .9rem;background:var(--wash)}
  .wgrp-h{font-size:.7rem;font-weight:800;letter-spacing:.05em;text-transform:uppercase;color:var(--mut);margin-bottom:.6rem}
  .wgrp input:not([type]),.wgrp input[type=text],.wgrp textarea{width:100%;padding:.55rem .75rem;border:1px solid var(--line);border-radius:10px;font:inherit;background:var(--card);color:var(--ink)}
  .wgrp textarea{resize:vertical}
  .whint{font-size:.72rem;color:var(--mut-2);margin-top:.45rem;line-height:1.35}
  .wfield{margin-bottom:.7rem}
  .wfield:last-child{margin-bottom:0}
  .wfield-top{display:flex;align-items:center;justify-content:space-between;gap:.6rem;flex-wrap:wrap;margin-bottom:.35rem}
  .wlbl{font-size:.8rem;font-weight:700;color:var(--ink-mid)}
  .wq{display:inline-flex;align-items:center;justify-content:center;width:15px;height:15px;border-radius:50%;background:var(--soft);color:var(--mut);font-size:.62rem;font-style:normal;font-weight:800;cursor:help;vertical-align:1px}
  .wfield.wrow{display:flex;align-items:center;justify-content:space-between;gap:.6rem;flex-wrap:wrap}
  .wtools{display:inline-flex;align-items:center;gap:.45rem;flex:none;flex-direction:row}
  .wtools .mkswatch input[type=color]{width:34px;height:26px;border-radius:7px}
  .wtools .mkhex{font-size:.68rem;color:var(--mut)}
  .wdef{display:inline-flex;align-items:center;gap:.3rem;font-size:.72rem;color:var(--mut);cursor:pointer}
  .wdef input{width:13px;height:13px;accent-color:var(--accent)}
  .wbold{cursor:pointer}
  .wbold input{display:none}
  .wbold span{display:inline-flex;align-items:center;justify-content:center;width:26px;height:26px;border:1px solid var(--line);border-radius:7px;font-weight:900;font-size:.8rem;color:var(--mut);background:var(--card);transition:.12s}
  .wbold input:checked+span{background:var(--acc-soft,#eaf6ef);border-color:var(--acc-line,#bfe3cc);color:var(--ink)}
  .wsz{padding:3px 4px;border:1px solid var(--line);border-radius:7px;font-size:.72rem;background:var(--card);color:var(--ink)}
  .mkweb-side{position:sticky;top:.8rem}
  .wside-h{font-size:.7rem;font-weight:800;letter-spacing:.05em;text-transform:uppercase;color:var(--mut);margin-bottom:.45rem;display:flex;align-items:center;justify-content:space-between}
  .wlive{color:var(--accent,#1f9d55);font-size:.64rem;letter-spacing:.02em}
  .wpv{border-radius:14px;overflow:hidden;border:1px solid var(--line);box-shadow:0 10px 30px -12px rgba(0,0,0,.25)}
  .wpv-ban{padding:.45rem .8rem;text-align:center;font-size:.68rem;font-weight:700;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .wpv-hero{padding:1.4rem 1.1rem 1.2rem;text-align:center;background-image:radial-gradient(rgba(255,255,255,.05) 1px,transparent 1px);background-size:14px 14px}
  .wpv-k{letter-spacing:.14em;text-transform:uppercase;margin-bottom:.45rem}
  .wpv-t{line-height:1.12;letter-spacing:-.01em;margin-bottom:.5rem;overflow-wrap:break-word}
  .wpv-t i{font-style:normal;color:var(--wres);font-weight:var(--wresw,800);font-size:var(--wress,1em)}
  .wpv-d{line-height:1.45;max-width:34ch;margin:0 auto .8rem}
  .wpv-cta{display:inline-block;border-radius:999px;padding:.45rem 1.1rem;font-size:.7rem;font-weight:800}
  .wpv-cards{display:flex;gap:.5rem;justify-content:center;margin-top:1rem}
  .wpv-cards b{flex:1;max-width:74px;height:56px;border-radius:9px;display:flex;flex-direction:column;justify-content:flex-end;gap:4px;padding:7px;box-shadow:0 4px 12px -6px rgba(0,0,0,.4)}
  .wpv-cards u,.wpv-cards s{display:block;height:5px;border-radius:3px;background:currentColor;text-decoration:none}
  .wpv-cards u{opacity:.85;width:70%}
  .wpv-cards s{opacity:.45;width:45%}
  .phx{opacity:.5}
  /* Preview del sitio como teléfono: marco oscuro, notch, y viewport REAL de 390px escalado (mkWifrFit) */
  .mkwifrbox{display:none;width:min(100%,398px);margin:0 auto;padding:9px;background:#0b0b0f;border-radius:44px;box-shadow:0 18px 44px -14px rgba(0,0,0,.5),inset 0 0 0 2px rgba(255,255,255,.07);position:relative}
  .mkwifrbox:before{content:'';position:absolute;top:16px;left:50%;transform:translateX(-50%);width:92px;height:20px;background:#0b0b0f;border-radius:12px;z-index:2;pointer-events:none}
  .mkwifrscr{overflow:hidden;border-radius:35px;background:#111;position:relative}
  .mkwifr{border:0;display:block;background:#111}
  /* Sucursales (config) */
  /* Opciones elegidas de un renglón del pedido nuevo. Iban con .gmeta (gris claro, el mismo tono
     que las notas de ayuda) y el cajero no distinguía LO QUE PIDIÓ EL CLIENTE del texto decorativo
     — justo el dato que se lee en voz alta al confirmar. Mismo tamaño, más peso y más contraste. */
  .npopts{font-size:.78rem;font-weight:700;color:var(--ink-mid,#3d4350);letter-spacing:-.005em;line-height:1.35}
  .sclogos{display:inline-flex;gap:.3rem;margin-left:.4rem;vertical-align:middle}
  .sclogo{width:32px;height:32px;border-radius:50%;overflow:hidden;display:inline-flex;align-items:center;justify-content:center;background:var(--card);border:1px solid var(--line)}
  .sclogo img{width:100%;height:100%;object-fit:cover;display:block}
  .sclogo-ph{font-size:.78rem;font-weight:800;color:var(--mut);background:var(--soft)}
  /* Logos de marca en el header (junto a KERP): chip rectangular con el color primario de la marca.
     El logo va en BLANCO (knockout) para que nunca se funda con su propio color de fondo. Cada chip
     recibe --mk (color de la marca) inline desde renderDashLogos(). */
  #brandMarcaLogos .sclogo,#marcaSwitch .mswlogo .sclogo,.hubchip .sclogo{--mk:#0f1116;width:auto;min-width:36px;max-width:158px;height:34px;border-radius:8px;padding:3px 6px;background:var(--mk);border:none;overflow:hidden;box-shadow:0 1px 2px rgba(13,13,15,.18),inset 0 0 0 1px rgba(255,255,255,.08);transition:transform .12s,box-shadow .12s}
  #brandMarcaLogos .sclogo:hover,.hubchip:hover .sclogo{transform:translateY(-1px);box-shadow:0 3px 8px rgba(13,13,15,.22),inset 0 0 0 1px rgba(255,255,255,.10)}
  #brandMarcaLogos .sclogo img,#marcaSwitch .mswlogo .sclogo img{height:100%;width:auto;aspect-ratio:3.4/1;object-fit:cover;object-position:center;display:block}
  /* Fichas de marca en Config: contain para que la palabra entre completa (no se recorta) */
  .hubchip .sclogo img{height:100%;width:auto;max-width:100%;object-fit:contain;object-position:center;display:block}
  #brandMarcaLogos .sclogo-ph,#marcaSwitch .mswlogo .sclogo-ph,.hubchip .sclogo-ph{min-width:31px;padding:0 11px;color:#fff;font-weight:800;background:var(--mk);border-radius:7px}
  /* Variante suave (opcional): fondo tenue del color de marca + logo a su color real. Se activa con
     la clase .soft en #brandMarcaLogos (ver MK_STYLE en renderDashLogos). */
  #brandMarcaLogos.soft .sclogo{background:color-mix(in srgb,var(--mk) 13%,transparent);box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--mk) 32%,transparent)}
  #brandMarcaLogos.soft .sclogo:hover{background:color-mix(in srgb,var(--mk) 18%,transparent)}
  #brandMarcaLogos.soft .sclogo img{filter:none;opacity:1}
  #brandMarcaLogos.soft .sclogo-ph{background:color-mix(in srgb,var(--mk) 13%,transparent);color:var(--mk)}
  .scchips{display:flex;flex-wrap:wrap;gap:.5rem}
  .scchip{display:inline-flex;align-items:center;gap:.5rem;border:0.5px solid var(--line);border-radius:99px;padding:.35rem .5rem .35rem .85rem;background:var(--card)}
  .scchip.on{border-color:var(--acc-line);background:var(--acc-soft)}
  .scchip .scchk{display:inline-flex;align-items:center;gap:.4rem;font-size:.9rem;font-weight:600;color:var(--ink);cursor:pointer}
  .scchip .scchk input{accent-color:var(--accent)}
  .screl2{border:0.5px solid var(--info-border);background:var(--info-soft);color:var(--info-ink);border-radius:99px;font-size:.72rem;font-weight:700;padding:.26rem .7rem;cursor:pointer;transition:background .12s,color .12s,border-color .12s}
  .screl2:hover{filter:brightness(.97)}
  .screl2.mz{background:var(--warn-soft);color:var(--warn-ink);border-color:var(--warn-border)}
  .scfix{display:inline-block;margin-top:.5rem;font-size:.78rem;color:var(--ok-ink);background:var(--ok-soft);border-radius:8px;padding:.25rem .6rem}
  .mkorigopts{display:flex;flex-wrap:wrap;gap:.5rem;margin-top:.35rem}
  .mkorig{display:inline-flex;align-items:center;gap:.5rem;border:1.5px solid var(--line);border-radius:10px;padding:.55rem 1rem;font-size:.87rem;font-weight:600;color:var(--ink);cursor:pointer;background:var(--card);white-space:nowrap;transition:.12s}
  .mkorig:hover{border-color:var(--acc-line,#cfe2d8)}
  .mkorig:has(input:checked){border-color:var(--accent);background:var(--acc-soft,#eaf6ef)}
  /* El input global trae padding/borde/ancho de text-input: el radio debe volver a ser radio. */
  .mkorig input[type=radio]{appearance:auto;-webkit-appearance:radio;width:16px;height:16px;min-width:16px;flex:0 0 16px;padding:0;border:0;border-radius:50%;box-shadow:none;background:none;margin:0;accent-color:var(--accent)}
  /* Modal genérico del panel (Nueva marca, etc.) */
  .kmodal{position:fixed;inset:0;background:rgba(15,17,20,.45);z-index:80;display:flex;align-items:flex-start;justify-content:center;padding:4vh 16px;overflow:auto}
  .kmodal .kbox{background:var(--card);border-radius:16px;max-width:900px;width:100%;padding:1.1rem 1.3rem;box-shadow:0 24px 60px -12px rgba(0,0,0,.35);margin-bottom:4vh}
  .mkorig:has(input:checked){border-color:var(--accent);background:var(--ok-soft);color:var(--accent-d)}
  .mkorig input{width:auto}
  .switch{display:inline-flex;align-items:center;gap:.6rem;cursor:pointer;font-weight:700;font-size:.9rem;height:42px}
  .switch input{position:absolute;opacity:0;width:0;height:0}
  .switch .sl{position:relative;width:44px;height:24px;border-radius:99px;background:var(--line);transition:background .15s;flex:none}
  .switch .sl::after{content:"";position:absolute;top:2px;left:2px;width:20px;height:20px;border-radius:50%;background:var(--card);transition:left .15s;box-shadow:0 1px 2px rgba(0,0,0,.25)}
  .switch input:checked + .sl{background:var(--accent)}
  .switch input:checked + .sl::after{left:22px}
  .switch .sl-lbl{color:var(--mut)}
  .ckm{display:flex;gap:.55rem;align-items:center;border:1px solid var(--line);border-radius:10px;padding:.7rem .9rem;margin-bottom:.5rem;font-weight:600;font-size:.92rem;cursor:pointer}
  .ckm:has(input:checked){border-color:var(--accent);background:var(--ok-soft)}
  .ckserv{display:flex;flex-wrap:wrap;gap:.5rem}
  .ckchip{border:1px solid var(--line);border-radius:10px;padding:.6rem .95rem;font-weight:700;font-size:.9rem;cursor:pointer;background:var(--card);color:var(--ink)}
  .ckchip:hover{border-color:var(--line)}
  .ckchip.on{border-color:var(--accent);background:var(--ok-soft);color:var(--accent-d)}
  .envcard{border:1px solid var(--line);border-radius:10px;padding:.5rem .9rem;margin-bottom:.6rem;background:var(--wash)}
  .erow{display:flex;gap:.8rem;padding:.28rem 0;font-size:.9rem;border-top:1px solid var(--line-2)}
  .erow:first-child{border-top:none}
  .erow .ek{width:104px;color:var(--mut);font-weight:700;flex:none}
  .erow .ev{flex:1;min-width:0;word-break:break-word}
  .link{background:none;border:none;color:var(--info);cursor:pointer;font-size:.85rem;padding:0;font-weight:600}
  .link:hover{text-decoration:underline}
  .xclose{appearance:none;border:none;background:var(--soft);color:var(--mut);width:32px;height:32px;border-radius:50%;font-size:.95rem;line-height:1;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;transition:background .12s,color .12s}
  .xclose:hover{background:var(--danger-soft);color:var(--danger)}
  /* Buscador de direcciones (geocoder) */
  .geo{position:relative}
  .geoinput{width:100%;border:1px solid var(--line);border-radius:10px;padding:.62rem .8rem;font-size:.92rem}
  .geoinput:focus{outline:none;border-color:var(--info)}
  .geosug{position:absolute;left:0;right:0;top:calc(100% + 4px);background:var(--card);border:1px solid var(--line);border-radius:10px;box-shadow:0 8px 26px rgba(0,0,0,.13);z-index:1200;overflow:hidden;display:none}
  .geosug.show{display:block}
  .geoitem{padding:.55rem .8rem;cursor:pointer;font-size:.88rem;border-top:1px solid var(--line-2)}
  .geoitem:first-child{border-top:none}
  .geoitem:hover{background:var(--hover)}
  .geoitem b{font-weight:700}
  .geoitem small{display:block;color:var(--mut);font-size:.78rem;margin-top:1px}
  .geoitem.geomsg{color:var(--mut);cursor:default}
  .geoitem.geomsg:hover{background:none}
  /* Mapa: pin fijo al centro (estilo arrastrar-mapa) */
  .mapwrap{position:relative}
  .mappin{position:absolute;left:50%;top:50%;transform:translate(-50%,-100%);z-index:1000;pointer-events:none;filter:drop-shadow(0 2px 3px rgba(0,0,0,.35))}
  .grow{display:flex;align-items:center;justify-content:space-between;gap:.5rem}
  .gmeta{font-size:.83rem;color:var(--mut)}
  /* Tablero Inicio */
  .kpis{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:.8rem;margin:.2rem 0 1.2rem}
  .kpi{background:var(--card);border:1px solid var(--line);border-radius:14px;padding:1rem 1.1rem;box-shadow:0 1px 3px rgba(0,0,0,.04)}
  .kpi .k{font-size:.74rem;font-weight:800;letter-spacing:.04em;text-transform:uppercase;color:var(--mut)}
  .kpi .v{font-size:1.55rem;font-weight:800;color:var(--ink);margin-top:.25rem;line-height:1.1}
  .kpi .s{font-size:.78rem;color:var(--mut);margin-top:.15rem}
  .kpi.alert .v{color:#c0322c}
  /* ===== Cortes (Fase 1) ===== */
  .crtbar{display:flex;flex-wrap:wrap;gap:.5rem;align-items:center;margin:0 0 .9rem}
  .crtbar input[type=date]{padding:.45rem .6rem}
  .crttbl{width:100%;border-collapse:collapse;font-size:.88rem}
  .crttbl th{font-size:.68rem;text-transform:uppercase;letter-spacing:.04em;color:var(--mut);text-align:left;padding:.45rem .5rem;border-bottom:1px solid var(--line);font-weight:800}
  .crttbl td{padding:.6rem .5rem;border-bottom:1px solid var(--line)}
  .crttbl tbody tr{cursor:pointer;transition:background .1s}
  .crttbl tbody tr:hover{background:var(--bg)}
  .crttbl .rt{text-align:right}
  .crtchip{display:inline-block;border-radius:99px;padding:.14rem .55rem;font-size:.74rem;font-weight:700;white-space:nowrap}
  .crtsem-v{background:var(--ok-soft);color:var(--ok-ink)}.crtsem-a{background:var(--warn-soft);color:var(--warn-ink)}.crtsem-r{background:var(--danger-soft);color:var(--danger-ink)}
  .crtsuc{background:var(--panel);color:var(--ink-mid)}
  .crtcaja{display:grid;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));gap:.8rem;align-items:start;margin-bottom:1.2rem}
  .dgrid{display:grid;grid-template-columns:1fr 1fr;gap:1rem;align-items:start}
  @media(max-width:820px){.dgrid{grid-template-columns:1fr}}
  .panel{background:var(--card);border:1px solid var(--line);border-radius:14px;padding:1rem 1.1rem;box-shadow:0 1px 3px rgba(0,0,0,.04)}
  .panel h3{margin:0 0 .6rem;font-size:.95rem;font-weight:800}
  .mkrow{display:flex;align-items:center;gap:.6rem;padding:.5rem 0;border-top:1px solid var(--line-2)}
  .mkrow:first-of-type{border-top:none}
  .mkrow .nm{flex:1;font-weight:600;font-size:.92rem}
  .mkrow .pd{color:var(--mut);font-size:.82rem;min-width:74px;text-align:right}
  .mkrow .vt{font-weight:800;min-width:88px;text-align:right}
  .rcrow{display:flex;align-items:center;gap:.6rem;padding:.5rem 0;border-top:1px solid var(--line-2);font-size:.9rem}
  .rcrow:first-of-type{border-top:none}
  .rcrow .fo{font-weight:800;color:var(--mut);min-width:42px}
  .rcrow .cl{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .rcrow .tt{font-weight:800;min-width:74px;text-align:right}
  .est{font-size:.68rem;font-weight:800;padding:.16rem .5rem;border-radius:99px;white-space:nowrap}
  .pronto{background:var(--card);border:1px solid var(--line);border-radius:16px;padding:2.4rem;text-align:center;margin-top:1rem;box-shadow:0 1px 3px rgba(0,0,0,.04)}
  .pronto .em{font-size:2.2rem}.pronto h3{margin:.6rem 0 .2rem;font-weight:800}
  .pronto p{color:var(--mut);max-width:460px;margin:.3rem auto 0}
  .login{max-width:360px;margin:13vh auto;background:var(--card);border:1px solid var(--line);border-radius:16px;padding:1.8rem;box-shadow:0 8px 30px rgba(0,0,0,.08)}
  .login h1{font-size:1.25rem;margin:.2rem 0 1.1rem;font-weight:800}.login input{width:100%;margin-bottom:.7rem}
  .login .btn{width:100%;padding:.7rem}
  .err{color:var(--danger);font-size:.85rem;margin-bottom:.6rem}
  .ov{position:fixed;inset:0;background:rgba(0,0,0,.5);display:none;z-index:100}
  /* Zona de imagen: resalte al arrastrar una foto encima */
  #f_imgzone.drag{outline:2px dashed var(--accent);outline-offset:4px;border-radius:10px;background:color-mix(in srgb,var(--accent) 8%,transparent)}
  .ov.show{display:block}
  /* El mapa ("Elegir en el mapa") se abre desde Configuración (.cfgscreen z-index:60): debe ir POR ENCIMA, no detrás. */
  #ovm{z-index:70}
  @keyframes slideIn{from{transform:translateX(30px);opacity:.6}to{transform:translateX(0);opacity:1}}
  .modal{position:absolute;top:0;right:0;height:100%;width:min(860px,100%);background:var(--card);box-shadow:-12px 0 40px rgba(0,0,0,.16);display:flex;flex-direction:column;animation:slideIn .22s ease}
  .mhead{display:flex;align-items:center;justify-content:space-between;padding:.9rem 1.1rem;border-bottom:1px solid var(--line)}
  .mhead h2{font-size:1.1rem;margin:0;font-weight:800}
  .mbody{flex:1;overflow:auto;display:grid;grid-template-columns:1fr 290px;gap:1.3rem;padding:1.1rem}
  .field{margin-bottom:.85rem}
  .field>span{display:block;font-size:.8rem;color:var(--mut);margin-bottom:.3rem;font-weight:600}
  .field input,.field textarea,.field select{width:100%}
  .three{display:grid;grid-template-columns:1fr 1fr 1fr;gap:.7rem}
  @media(max-width:560px){.three{grid-template-columns:1fr}}
  .presedit{display:flex;gap:.5rem;align-items:center;margin-bottom:.55rem;background:var(--wash);border:1px solid var(--line);border-radius:10px;padding:.5rem .6rem;flex-wrap:wrap}
  .presedit .pn{flex:1;min-width:150px}.presedit .pp{width:96px}.presedit .pe{width:130px}
  .presedit input:not([type=checkbox]):not([type=radio]),.presedit select{border:1px solid var(--line);border-radius:8px;padding:.5rem .55rem;background:var(--card);font:inherit}
  .presedit input:not([type=checkbox]):not([type=radio]):focus,.presedit select:focus{outline:none;border-color:var(--info)}
  .presedit .link{padding:.42rem .8rem;border-radius:8px;border:1px solid var(--line);background:var(--card);font-weight:700;font-size:.8rem;flex:none}
  .presedit .link:hover{background:var(--soft);text-decoration:none}
  .dcol{display:flex;flex-direction:column;gap:.22rem;flex:1;min-width:90px}
  .dcol>span{font-size:.72rem;color:var(--mut);font-weight:600}
  .dcol>input{width:100%}
  #os_grid input[type=checkbox]{width:20px;height:20px;accent-color:var(--accent);cursor:pointer}
  .osrow{display:flex;align-items:center;gap:.7rem;padding:.6rem 0;border-bottom:1px solid var(--line-2);flex-wrap:wrap}
  .osrow:last-of-type{border-bottom:none}
  .osrow .osname{font-weight:600;font-size:.95rem;flex:0 1 200px;min-width:150px}
  .osmethods{display:flex;align-items:center;gap:.4rem;flex-wrap:wrap;flex:1 1 240px;padding-left:.5rem;border-left:1px solid var(--line)}
  .osmlbl{font-size:.74rem;color:var(--mut);font-weight:700;margin-right:.1rem}
  .pmrow{display:flex;gap:.6rem;align-items:flex-start;flex-wrap:wrap;margin-bottom:.6rem}
  .pmlbl{min-width:100px;font-weight:700;font-size:.85rem;color:var(--ink-mid);padding-top:.35rem}
  .pmchips{display:flex;flex-wrap:wrap;gap:.4rem;flex:1}
  .pmchip{border:1px solid var(--line);background:var(--card);border-radius:99px;padding:.32rem .85rem;font-weight:700;font-size:.82rem;color:var(--mut);cursor:pointer;transition:.12s}
  .pmchip:hover{background:var(--hover)}
  .pmchip.on{background:var(--accent);border-color:var(--accent);color:#fff}
  .metrow{background:var(--wash);border:1px solid var(--line);border-radius:11px;padding:.65rem .75rem;margin-bottom:.6rem;display:flex;flex-direction:column;gap:.55rem}
  .metrow-top{display:flex;gap:.6rem;align-items:center;flex-wrap:wrap}
  .metrow-top input.pn,.metrow-top select.pd{border:1px solid var(--line);border-radius:8px;padding:.5rem .55rem;background:var(--card);font:inherit}
  .metrow .mact{display:flex;gap:.3rem;align-items:center;font-size:.85rem;white-space:nowrap}
  .metrow-svc{display:flex;gap:.45rem;align-items:center;flex-wrap:wrap}
  .metrow-svc .msvlbl{color:var(--mut);font-weight:700;font-size:.78rem;margin-right:.1rem}
  .svchip{display:inline-flex;gap:.3rem;align-items:center;border:1px solid var(--line);border-radius:999px;padding:.34rem .8rem;cursor:pointer;background:var(--card);font-size:.82rem;font-weight:600;color:var(--ink);transition:background .14s,border-color .14s,color .14s;user-select:none}
  .svchip:hover{border-color:var(--acc-line)}
  .metrow-bank{display:flex;flex-wrap:wrap;gap:.4rem;margin-top:.1rem}
  .metrow-bank input{border:1px solid var(--line);border-radius:8px;padding:.5rem .55rem;background:var(--card);font:inherit;flex:1;min-width:150px}
  .bkrow{display:flex;align-items:center;justify-content:space-between;gap:1rem;padding:.4rem .65rem;font-size:.9rem;border:1px solid var(--line);border-radius:8px;margin-bottom:.35rem;background:var(--bg)}
  .bkrow>.bkname{flex:0 0 130px;font-weight:700;color:var(--ink);font-size:.9rem;margin:0}
  .bkrow>.three{flex:1}
  .bkrow span{color:var(--mut);font-weight:600}
  .bkrow b{font-variant-numeric:tabular-nums;letter-spacing:.02em}
  .svchip input{position:absolute;opacity:0;width:0;height:0;pointer-events:none}
  .svchip::before{content:"";width:14px;height:14px;border-radius:50%;border:1.5px solid var(--mut-2);background:var(--card);flex:none;transition:.14s}
  .svchip:has(input:checked){border-color:var(--accent);background:var(--acc-soft);color:var(--accent-d)}
  .svchip:has(input:checked)::before{border-color:var(--accent);background:var(--accent);box-shadow:inset 0 0 0 2.5px var(--card)}
  .metrow-act{display:flex;gap:.5rem;justify-content:flex-end}
  .metrow-act .link{padding:.42rem .8rem;border-radius:8px;border:1px solid var(--line);background:var(--card);font-weight:700;font-size:.8rem}
  .metrow-act .link:hover{background:var(--soft);text-decoration:none}
  .gpick{max-height:190px;overflow:auto;border:1px solid var(--line);border-radius:10px;padding:.5rem .7rem}
  .gpick label{display:flex;gap:.6rem;align-items:center;padding:.45rem .2rem;font-size:.92rem;border-bottom:1px solid var(--line-2)}
  .gpick label:last-child{border-bottom:none}
  .gpick label .nm{flex:1;min-width:0}
  .gpick label .ct{color:var(--mut-2);font-size:.84rem}
  .gpick input{width:auto;padding:0;border:0;box-shadow:none}
  .opt2{display:flex;align-items:center;gap:.7rem;padding:.6rem .2rem;border-bottom:1px solid var(--line-2);cursor:pointer}
  .opt2:last-child{border-bottom:none}
  .opt2 input{width:auto;padding:0;border:0;box-shadow:none}
  .opt2 .nm{flex:1}
  .gattach{display:flex;align-items:center;justify-content:space-between;gap:.6rem;padding:.55rem 0;border-bottom:1px solid var(--line-2)}
  .gattach .ghnd{cursor:grab;color:var(--mut-2);font-size:1.05rem;user-select:none;flex:none}
  .gattach:active{cursor:grabbing}
  .gattach .gn{font-weight:600}
  .gattach .gc{color:var(--mut-2);font-size:.82rem;margin-top:.12rem}
  #g_add{margin-top:.6rem;width:100%}
  .ckm{display:inline-flex;gap:.4rem;align-items:center;font-size:.9rem;font-weight:600}
  .npgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(118px,1fr));gap:.6rem}
  .npcard{border:1px solid var(--line);border-radius:12px;overflow:hidden;cursor:pointer;background:var(--card);transition:.12s}
  .npcard:hover{border-color:var(--accent);box-shadow:0 3px 10px rgba(0,0,0,.08)}
  .npcard:active{transform:translateY(1px)}
  .npcard img,.npcard .npnoimg{width:100%;height:88px;object-fit:cover;background:var(--soft);display:block}
  .npcard .npn{font-size:.82rem;font-weight:700;padding:.4rem .5rem 0;line-height:1.2}
  .npcard .npp{font-size:.84rem;font-weight:800;padding:.15rem .5rem .55rem}
  /* Nuevo pedido: tarjeta centrada horizontal + menú estilo carta */
  #ovn.show{display:flex;align-items:center;justify-content:center;padding:2vh 1rem}
  #ovn .modal{position:static;height:min(680px,92vh);width:min(980px,96vw);border-radius:16px;animation:none;box-shadow:0 18px 60px rgba(0,0,0,.25)}
  /* Editor de producto: tarjeta grande centrada (en vez de panel lateral) */
  #ov.show{display:flex;align-items:center;justify-content:center;padding:2vh 1rem}
  #ov .modal{position:static;height:auto;max-height:94vh;width:min(980px,96vw);border-radius:16px;animation:none;box-shadow:0 18px 60px rgba(0,0,0,.25)}
  /* ESCALA DE CAPAS DE LO QUE FLOTA — respetarla al crear un modal nuevo.
     Es la TERCERA vez que este mismo bug vuelve (jul-20, jul-21 y jul-30), siempre igual:
     alguien crea un overlay con un z mayor y entierra el modal de OPCIONES, que se abre
     ENCIMA de otros modales por naturaleza.
        100  .ov                       (base: captura de pedido #ovn, editar #ovd, cobro #ovk)
        120  #ovped #ovag              (pedido vivo / agregar ronda — inicio.js)
        125  #ovficha
        130  #ovaj #ovmap              (ajuste de renglón, mapa)
        140  reportes
      > 150  #ovo                      ESTE. Opciones y armado de COMBO (pedidos.js:1295 y 1422).
               Lo abren #ovn (100) Y #ovag (120): tiene que ganarle a los dos.
       100000 uiDlg / toast            (diálogos del sistema: siempre hasta arriba)

     Qué se veía en jul-30: al agregar productos a un pedido vivo, tocar algo con
     modificadores "trancaba" la pantalla — el modal SÍ abría, pero debajo del velo opaco
     de #ovag (z120), así que no se veía y no había forma de seguir ni de volver. */
  #ovo.show{display:flex;align-items:center;justify-content:center;padding:2vh 1rem;z-index:150}
  #ovo .modal{position:static;height:auto;max-height:90vh;width:min(460px,96vw);border-radius:16px;animation:none;box-shadow:0 18px 60px rgba(0,0,0,.25)}
  /* Recortador de foto: centrado como los demás modales; va por encima del editor de producto */
  #ovcrop.show{display:flex;align-items:center;justify-content:center;padding:2vh 1rem}
  #ovcrop .modal{position:static;height:auto;max-height:94vh;width:min(520px,96vw);border-radius:16px;animation:none;box-shadow:0 18px 60px rgba(0,0,0,.25)}
  #cropCv{display:block}
  #ovcaja.show{display:flex;align-items:center;justify-content:center;padding:2vh 1rem}
  #ovcaja .modal{position:static;height:auto;max-height:min(700px,92vh);width:auto;min-width:min(420px,94vw);max-width:min(980px,96vw);border-radius:16px;animation:none;box-shadow:0 18px 60px rgba(0,0,0,.25)}
  #ovcaja .mbody{display:block}
  .cajalock{background:var(--danger-soft);border:1px solid var(--danger-border);color:var(--danger-deep);border-radius:12px;padding:.75rem .95rem;margin-bottom:1rem;font-size:.93rem;line-height:1.45}
  .cajasuc{display:flex;align-items:center;gap:.45rem;flex-wrap:wrap;margin-bottom:.8rem}
  .cajasuclbl{font-size:.8rem;color:var(--mut);font-weight:700;margin-right:.1rem}
  #ovn .mbody{overflow:hidden}
  #ovn .mbody>div:last-child{min-height:0;overflow-y:auto}
  .npmenu{display:flex;flex-direction:column;min-height:0;overflow:hidden}
  .npsearch{flex:none;margin-bottom:.5rem}
  /* position:relative NO es cosmético: hace que .npcat sea hijo posicionado de la lista y que
     su offsetTop mida desde la lista. Sin esto el offsetParent es .ov (fixed) y npIrCat no puede
     calcular a dónde scrollear. No cambia el sticky de .npcat (su contenedor de pegado sigue
     siendo esta caja con scroll). */
  #ovn .nplist{flex:1;min-height:0;overflow-y:auto;overscroll-behavior:contain;border:1px solid var(--line);border-radius:10px;padding:.3rem .6rem;position:relative}
  .npcat{font-size:.72rem;font-weight:800;color:var(--mut);text-transform:uppercase;letter-spacing:.04em;margin:.2rem 0 .4rem;position:sticky;top:0;background:var(--card);padding:.35rem 0}
  .nprow{display:flex;gap:.6rem;align-items:center;border:1px solid var(--line);border-radius:10px;padding:.4rem .5rem;margin-bottom:.4rem;cursor:pointer;background:var(--card)}
  .nprow:hover{background:var(--bg)}
  .nprow img,.nprow .npni{width:46px;height:46px;border-radius:8px;object-fit:cover;background:var(--soft);flex:none}
  .nprow .nrn{flex:1;font-size:.86rem;font-weight:600;line-height:1.2}
  .nprow .nrp{font-size:.85rem;font-weight:800;color:var(--ink-mid)}
  .npcats{flex:none;display:flex;gap:.4rem;overflow-x:auto;padding:.15rem .25rem .5rem;scroll-padding-inline:.25rem;scrollbar-width:none}
  .npcats::-webkit-scrollbar{display:none}
  .npcats:empty{display:none}
  .npchip{flex:none;border:1px solid var(--line);background:var(--card);border-radius:99px;padding:.32rem .8rem;font-size:.8rem;font-weight:700;color:var(--mut);cursor:pointer;white-space:nowrap;transition:.15s}
  .npchip:hover{color:var(--ink)}
  .npchip.on{color:#fff;border-color:transparent}
  .prev{background:var(--soft);border:1px solid var(--line);border-radius:14px;padding:1.1rem;height:fit-content;position:sticky;top:0}
  .prev .lbl{font-size:.72rem;color:var(--mut);text-transform:uppercase;letter-spacing:.04em;margin-bottom:.5rem}
  .prev img{width:100%;height:150px;object-fit:cover;border-radius:10px;background:var(--soft);display:block}
  .prev h3{margin:.6rem 0 .2rem;font-size:1.05rem}.prev .pd{color:var(--mut);font-size:.9rem}
  .oblig{font-size:.7rem;color:var(--warn-ink);background:var(--warn-soft);padding:.12rem .45rem;border-radius:99px;font-weight:700}
  .mfoot{padding:.85rem 1.1rem;border-top:1px solid var(--line);display:flex;justify-content:flex-end;gap:.6rem}
  #toast{position:fixed;bottom:1.2rem;left:50%;transform:translateX(-50%);background:#15171c;color:#fff;padding:.65rem 1.1rem;border-radius:11px;opacity:0;transition:.2s;font-size:.88rem;pointer-events:none;z-index:100001;box-shadow:0 8px 24px rgba(0,0,0,.25)}
  #toast.show{opacity:1}
  /* ---- Pedidos (cajero) ---- */
  .toolbar{display:flex;gap:.4rem;flex-wrap:wrap;align-items:center;margin:.2rem 0 .9rem}
  .ped{border:1px solid var(--line);border-left:4px solid var(--pa,var(--line));border-radius:14px;padding:.9rem 1rem;margin:.7rem 0;background:var(--card);box-shadow:0 1px 3px rgba(0,0,0,.05)}
  .ped.nuevo{background:var(--warn-soft);border-color:var(--warn-border)}
  .ped-h{display:flex;align-items:center;justify-content:space-between;gap:.5rem}
  .ped-id{font-weight:800;font-size:1.08rem;display:flex;align-items:center;gap:.45rem;flex-wrap:wrap}
  .chip2{display:inline-flex;align-items:center;gap:.25rem;font-size:.74rem;font-weight:700;background:var(--panel);color:var(--ink-mid);padding:.16rem .55rem;border-radius:99px}
  .ped-sub{font-size:.84rem;color:var(--mut);margin-top:.35rem;line-height:1.5}
  .ped-mk{font-size:.72rem;font-weight:800;letter-spacing:.05em;text-transform:uppercase;color:var(--mut);margin:.7rem 0 .15rem}
  .ped-it{display:flex;justify-content:space-between;gap:.6rem;padding:.32rem 0;font-size:.92rem;border-top:1px solid var(--line-2)}
  .ped-tot{display:flex;justify-content:space-between;font-size:.9rem;color:var(--mut);padding:.18rem 0}
  .ped-tot.g{font-weight:800;color:var(--ink);font-size:1.05rem;border-top:1px solid var(--line);margin-top:.25rem;padding-top:.5rem}
  .ped-acc{display:flex;gap:.5rem;flex-wrap:wrap;margin-top:.8rem}
  .u-ok{color:var(--ok)}.u-warn{color:var(--warn-ink)}.u-late{color:var(--danger);font-weight:700}
  /* estados */
  .e-sin_confirmar{background:var(--warn-soft);color:var(--warn-ink)}.e-confirmado{background:var(--info-soft);color:var(--info-ink)}
  .e-en_preparacion{background:var(--info-soft);color:var(--info-ink)}.e-listo{background:var(--ok-soft);color:var(--ok-ink)}
  .e-en_camino{background:var(--viol-soft);color:var(--viol-ink)}.e-entregado{background:var(--panel);color:var(--ink-mid)}.e-cancelado{background:var(--danger-soft);color:var(--danger)}
  /* ---- Caja: stats ---- */
  .stat{display:grid;grid-template-columns:repeat(auto-fit,minmax(130px,1fr));gap:.6rem;margin:.3rem 0}
  .stat .s{background:var(--wash);border:1px solid var(--line);border-radius:12px;padding:.65rem .85rem}
  .stat .s span{font-size:.7rem;color:var(--mut);text-transform:uppercase;letter-spacing:.03em}
  .stat .s b{display:block;font-size:1.15rem;margin-top:.15rem;font-weight:800}
  .stat .s.hl{background:var(--accent);border-color:var(--accent)}
  .stat .s.hl span{color:rgba(255,255,255,.7)}.stat .s.hl b{color:#fff}
  @media(max-width:820px){
    .shell{flex-direction:column}
    /* iPhone: el lateral es un CAJÓN deslizante sobre el contenido (no un bloque arriba). */
    .side{position:fixed;left:0;top:0;height:100dvh;width:min(280px,82vw);z-index:80;box-shadow:0 0 44px rgba(0,0,0,.28);transition:transform .28s ease;margin-left:0}
    body.sbhide .side{transform:translateX(-108%);pointer-events:none;box-shadow:none}
    .modal{width:100%}
    .mbody{grid-template-columns:1fr}.prev{position:static}
    /* Dash Ventas: KPIs en 3+2 y flujo de cocina en 2x2 — nada se corta. */
    .v2top>*{min-width:0}
    .v2card{min-width:0}
    .v2krow{flex-wrap:wrap;row-gap:10px}
    .v2km{flex:1 1 32%;min-width:31%}
    .v2km+.v2km{border-left:none}
    .v2km:nth-child(2),.v2km:nth-child(3){border-left:1px solid var(--line)}
    .v2flow{flex-wrap:wrap;row-gap:10px}
    .v2pstep{flex:1 1 42%;min-width:42%}
    .v2parr{display:none}
    /* Panel Pedidos: cada pedido se vuelve TARJETA (la tabla de 7 columnas muere en 390px). */
    .ptable{display:block;background:none;border:none;box-shadow:none}
    .ptable colgroup,.ptable thead{display:none}
    .ptable tbody{display:block}
    .ptable tbody tr.ptr{display:grid;grid-template-columns:auto 1fr auto;gap:.15rem .6rem;background:var(--card);border:1px solid var(--line);border-radius:12px;padding:.6rem .75rem;margin-bottom:.5rem}
    .ptable tbody tr.ptr.nv{background:var(--wash)}
    .ptable tbody tr.ptr td{display:block;border:none;padding:0}
    .ptable tr.ptr td.fo{grid-area:1/1/2/3}
    .ptable tr.ptr td:nth-child(3){grid-area:1/3;justify-self:end}
    .ptable tr.ptr td:nth-child(2){grid-area:2/1/3/3}
    .ptable tr.ptr td:nth-child(4){grid-area:2/3;justify-self:end;text-align:right}
    .ptable tr.ptr td:nth-child(5){grid-area:3/1;align-self:end;font-size:.75rem}
    .ptable tr.ptr td:nth-child(6){grid-area:3/2;align-self:end;font-size:.75rem}
    .ptable tr.ptr td:nth-child(7){grid-area:3/3;justify-self:end;align-self:end}
    .ptable tr.pdgrp{display:block}
    .ptable tr.pdgrp td{display:block;background:none;border:none;padding:.5rem .25rem .25rem}
    /* Cortes (lista): en móvil solo lo esencial — Cerró/Efectivo/Contado viven en el detalle. */
    .crtlist th:nth-child(3),.crtlist td:nth-child(3),.crtlist th:nth-child(5),.crtlist td:nth-child(5),.crtlist th:nth-child(6),.crtlist td:nth-child(6){display:none}
    /* Avisos (microOk/microWarn): en el cel son notificación compacta ARRIBA, no un pildorón al centro. */
    #microok,#microwarn{top:max(.8rem,env(safe-area-inset-top))!important;left:50%!important;transform:translate(-50%,0)!important;font-size:.92rem!important;padding:.55rem .95rem!important;max-width:90vw;box-shadow:0 8px 24px rgba(0,0,0,.28)!important}
    #microok>span:first-child,#microwarn>span:first-child{width:22px!important;height:22px!important;font-size:.85rem!important;flex:none}
  }
/* ===== Resumen del día v3: canal×marca + métodos + top (cxm*) ===== */
.cxmtop{display:grid;grid-template-columns:1.62fr 1fr;gap:14px;margin:0 0 14px}
.cxmcard{background:var(--card);border:1px solid var(--line);border-radius:14px;padding:16px 18px}
.cxmh{display:flex;align-items:center;gap:7px;font-size:12.5px;font-weight:700;color:var(--ink);text-transform:uppercase;letter-spacing:.5px;margin-bottom:14px}
.cxmtbl{width:100%;border-collapse:collapse;font-size:12.5px}
.cxmtbl th{font-size:9px;font-weight:700;color:var(--mut-2);text-transform:uppercase;letter-spacing:.4px;text-align:left;padding:9px 12px;vertical-align:bottom}
.cxmtbl td{padding:10px 12px;border-top:1px solid var(--line);vertical-align:middle}
.cxmtbl th.rt,.cxmtbl td.rt{text-align:right}
.cxmtl{text-align:left;vertical-align:bottom;padding:4px 12px 12px}
.cxmtl-l{font-size:10px;color:var(--mut);text-transform:uppercase;letter-spacing:.6px;margin-bottom:3px;font-weight:700}
.cxmtl-b{font-size:24px;font-weight:700;color:var(--accent);letter-spacing:-.5px;line-height:1}
.cxmbrh{text-align:center;vertical-align:bottom;padding:6px 12px 11px;border-bottom:1px solid var(--line)}
.cxmbrh-in{display:inline-flex;align-items:center;gap:9px}
.cxmlogo{width:36px;height:36px;border-radius:9px;object-fit:cover;flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;font-weight:800;color:#fff;font-size:15px}
.cxmlogoph{border-radius:50%}
/* El color de marca entra por --bmk (día) / --bmk-dk (noche), que los pinta brandVars()
   en inicio.js. Sin esto el negro de identidad se perdía contra el fondo del modo noche. */
.cxmbrpct{font-size:16px;font-weight:800;color:var(--bmk,var(--ink))}
.cxmbrlg{box-shadow:0 1px 2px rgba(13,13,15,.18),inset 0 0 0 1px rgba(255,255,255,.08)}
.cxmsep{border-left:1px solid var(--line)}
.cxmg{background:var(--wash)}
.cxmname{display:flex;align-items:center;gap:11px;font-weight:600;white-space:nowrap}
.cxmico{width:30px;height:30px;border-radius:8px;display:flex;align-items:center;justify-content:center;flex-shrink:0}
.cxmico svg{width:17px;height:17px}
.cxmn{font-weight:700;white-space:nowrap}
.cxmpc{font-weight:700;white-space:nowrap;color:var(--mut)}
.cxmbn{font-weight:700;white-space:nowrap}
.cxmminib{height:4px;width:70px;background:var(--soft);border-radius:3px;overflow:hidden;margin-top:5px}
.cxmminib i{display:block;height:100%;border-radius:3px;background:var(--bmk,var(--accent))}
.cxmtbl tr.cxmtr td{border-top:1.5px solid var(--line);font-weight:800;background:var(--wash)}
.cxmtbl tr.cxmtr .cxmpc{color:var(--ink)}
.cxmp{display:flex;align-items:center;gap:13px;padding:10px 4px}
.cxmpico{width:38px;height:38px;border-radius:10px;background:var(--wash);display:flex;align-items:center;justify-content:center;flex-shrink:0}
.cxmpico svg{width:19px;height:19px}
.cxmpb{flex:1;min-width:0}
.cxmpt{display:flex;align-items:baseline;justify-content:space-between;gap:8px}
.cxmpn{font-size:13.5px;font-weight:600}
.cxmpr{display:flex;align-items:baseline;gap:14px}
.cxmpa{font-size:14px;font-weight:700}
.cxmpp{font-size:12.5px;font-weight:700;color:var(--mut);min-width:36px;text-align:right}
.cxmpbar{height:5px;background:var(--soft);border-radius:4px;overflow:hidden;margin-top:7px}
.cxmpbar i{display:block;height:100%;border-radius:4px}
.cxmptot{display:flex;align-items:center;justify-content:space-between;border-top:1px solid var(--line);margin-top:8px;padding-top:13px}
.cxmptot .l{font-size:10.5px;color:var(--mut);text-transform:uppercase;letter-spacing:.6px;font-weight:700}
.cxmptot .r{display:flex;gap:16px;font-weight:800}
.cxmptot .r .p{color:var(--mut)}
.cxmpsub{font-size:9.5px;font-weight:700;color:var(--mut-2);text-transform:uppercase;letter-spacing:.6px;margin:13px 0 5px;padding-top:12px;border-top:1px dashed var(--line)}
.cxmp.cxmtip{padding:7px 4px}
.cxmp.cxmtip .cxmpico{width:32px;height:32px}
.cxmptot.cxmtipt{border-top:0;margin-top:4px;padding-top:4px}
.cxmptot.cxmtipt .r{font-weight:700}
.cxmtptbl{width:100%;border-collapse:collapse;font-size:13px}
.cxmtptbl th{font-size:9px;font-weight:700;color:var(--mut-2);text-transform:uppercase;letter-spacing:.4px;text-align:left;padding:7px 12px}
.cxmtptbl td{padding:11px 12px;border-top:1px solid var(--line);vertical-align:middle}
.cxmtptbl th.rt,.cxmtptbl td.rt{text-align:right}
.cxmrk{width:24px;height:24px;border-radius:7px;background:var(--accent);color:#fff;display:inline-flex;align-items:center;justify-content:center;font-size:12px;font-weight:700}
.cxmpr2{font-weight:600;text-transform:uppercase;letter-spacing:.2px;font-size:12.5px}
.cxmqty{color:var(--mut);font-weight:600}
.cxmpart{width:32%}
.cxmpartb{height:8px;background:var(--soft);border-radius:5px;overflow:hidden}
.cxmpartb i{display:block;height:100%;background:var(--accent);border-radius:5px}
.cxmtptbl tr.cxmtr td{border-top:1.5px solid var(--line);font-weight:800;background:var(--wash)}
@media(max-width:900px){.cxmtop{grid-template-columns:1fr}}
/* ===== Ajustes tablet/iPad: sin desborde horizontal + barra lateral ocultable ===== */
html,body{overflow-x:hidden}
/* iPadOS ignora user-scalable=no para el pellizco: touch-action bloquea el zoom de página
   (el mapa Leaflet no se afecta: maneja sus propios gestos con touch-action propio). */
html,body{touch-action:pan-x pan-y}
.shell main,.shell #app{min-width:0}
.cxmcard{overflow-x:auto}
#sbtoggle{display:none;position:fixed;top:.55rem;right:.55rem;z-index:90;width:38px;height:38px;border-radius:10px;border:1px solid var(--line);background:var(--card);box-shadow:0 2px 8px rgba(0,0,0,.08);font-size:18px;line-height:1;cursor:pointer;align-items:center;justify-content:center}
@media(max-width:1366px){
  #sbtoggle{display:flex}
}
/* Ocultar/mostrar la barra lateral con transición sutil (desliza y se desvanece). iPad 821-1366. */
@media(min-width:821px) and (max-width:1366px){
  .side{transition:margin-left .5s cubic-bezier(.22,.61,.36,1),opacity .32s ease}
  body.sbhide .side{margin-left:-245px;opacity:0;visibility:hidden;pointer-events:none;transition:margin-left .5s cubic-bezier(.22,.61,.36,1),opacity .32s ease,visibility 0s .5s}
}
/* Modal abierto: el scroll interno del modal no "encadena" al fondo (iOS/desktop). */
.ov .modal,#ovped_body,#ovcli>div,.mbody{overscroll-behavior:contain}
/* Domicilio sin repartidor a los 15 min: aviso parpadeante en la tarjeta del tablero. */
.repwarn{background:var(--danger-soft);color:var(--danger-ink);font-weight:700;animation:repblink 1.5s ease-in-out infinite}
@keyframes repblink{50%{opacity:.45}}

/* ===================== Franja superior fija + barra lateral COLAPSABLE =====================
   Los logos de marca + los switchers viven en una franja de arriba que NO se colapsa; solo el
   nav (EN VIVO … Salir) se oculta con el botón ☰ o al asomar el mouse por el borde izquierdo. */
:root{ --topH:56px; --sideW:244px; }
.shell{display:block}
.topstrip{position:fixed;top:0;left:0;right:0;height:var(--topH);z-index:60;display:flex;align-items:center;gap:.55rem;padding:.32rem 1rem;background:rgba(255,255,255,.96);backdrop-filter:blur(8px);border-bottom:1px solid var(--line)}
.topstrip .brand{margin:0 .1rem 0 0}
.topstrip .topbar{position:static;flex:1;min-width:0;border:none;background:none;backdrop-filter:none;box-shadow:none;padding:0;top:auto;z-index:auto;height:auto}
.shellbody{display:flex;min-height:100vh;padding-top:var(--topH)}
#sbtoggle{position:static;display:flex;flex:none;width:40px;height:40px;border-radius:11px;border:1px solid var(--line);background:var(--card);font-size:20px;line-height:1;cursor:pointer;align-items:center;justify-content:center;color:var(--ink-mid);box-shadow:none;top:auto;right:auto}
#sbtoggle:hover{background:var(--hover,#eef0f2)}
/* Estado FIJADA (barra oculta): el botón queda marcado en gris humo. Abierta (normal) = blanco. */
body:not(.sbhide) #sbtoggle{background:color-mix(in srgb,var(--ink) 13%,transparent);border-color:color-mix(in srgb,var(--ink) 26%,transparent);color:var(--ink)}
body:not(.sbhide) #sbtoggle:hover{background:color-mix(in srgb,var(--ink) 20%,transparent)}
.peekzone{display:none}
@media(min-width:821px){
  .side{position:sticky;top:var(--topH);height:calc(100vh - var(--topH));transition:margin-left .3s cubic-bezier(.22,.61,.36,1),opacity .22s ease}
  /* La barra OCULTA ya sale del flujo con fixed, no con un margen negativo. Es el mismo
     resultado de layout —el contenido ocupa todo— pero evita que al cerrarse el peek la barra
     SALTE de fixed a sticky mientras se desvanece: el cambio de posicion se veria en el fundido. */
  body.sbhide .side{position:fixed;left:0;top:var(--topH);width:var(--sideW);
    height:calc(100vh - var(--topH));height:calc(100dvh - var(--topH));
    margin-left:0;opacity:0;visibility:hidden;pointer-events:none;z-index:55;
    transition:opacity .22s ease,visibility 0s .3s}
  .peekzone{position:fixed;top:var(--topH);left:0;width:16px;height:calc(100vh - var(--topH));z-index:40}
  body.sbhide .peekzone{display:block}
  /* EL PEEK APARECE DONDE ESTA EL USUARIO (ago-6, Ronel: «no importa en que parte de la pagina
     este, que aparezca donde estoy»).

     El sintoma: con la pagina scrolleada abajo —el catalogo, por ejemplo— asomabas el hover y la
     barra no estaba. Habia que subir a buscarla, y en el camino brincaba.

     LA CAUSA es que `.side` es `position:sticky` (arriba) y `admin.css:892` declara
     `html,body{overflow-x:hidden}`. Cuando overflow-x es hidden y overflow-y queda visible, la
     especificacion obliga a computar overflow-y como auto: html y body se vuelven contenedores de
     scroll, y sticky se pega a SU contenedor, no al viewport. Safari es especialmente estricto.
     La tira que dispara el peek si te sigue —es position:fixed, mas abajo— asi que el hover
     funcionaba y la clase se prendia: lo que se asomaba estaba arriba, fuera de tu vista.

     POR QUE FIXED Y NO ARREGLAR EL STICKY. Quitar el overflow-x global arreglaria esto y de paso
     los otros nueve sticky del archivo, pero ese recorte es del que viven las tablas anchas (ver
     la nota de la linea 1154) y no se puede tocar a ciegas. `fixed` esta anclado al viewport por
     definicion: no depende de ancestros, de overflow ni del navegador. Determinista.

     Y SIGUE EMPUJANDO, que era la razon por la que se le habia quitado el fixed la vez pasada: al
     salir del flujo, .shellbody compensa con el mismo ancho de la barra. El contenido se corre
     igual que antes y no queda ni un pixel tapado — que es lo que costo el arreglo anterior
     (se leia "vos" en vez de "Pedidos activos"). */
  body.sbhide.sbpeek .side{opacity:1;visibility:visible;pointer-events:auto;
    box-shadow:12px 0 40px rgba(0,0,0,.16);
    animation:sbPeekIn .22s cubic-bezier(.22,.61,.36,1)}
  @keyframes sbPeekIn{from{transform:translateX(-100%);opacity:0}to{transform:none;opacity:1}}
  /* La compensacion: el hueco que la barra ya no ocupa en el flex se lo pone .shellbody. */
  .shellbody{transition:padding-left .22s cubic-bezier(.22,.61,.36,1)}
  body.sbhide.sbpeek .shellbody{padding-left:var(--sideW)}
  /* Con la barra ya asomada, la tira de 16px queda debajo de ella y estorba: se retira
     para que el hover sobre .side sea el unico que sostiene el peek. */
  body.sbhide.sbpeek .peekzone{display:none}
}

/* Encabezado de tarjeta de canal (Mostrador/Domicilio/App): TODA la franja captura Nueva orden.
   Realce sutil al pasar el mouse para que se note que es clickeable. */
.areah[onclick]{border-radius:10px;transition:background .12s}
.areah[onclick]:hover{background:color-mix(in srgb, var(--ch,#7f7f7f) 10%, transparent)}
.areah[onclick]:active{background:color-mix(in srgb, var(--ch,#7f7f7f) 16%, transparent)}


/* ════════════════════════════════════════════════════════════════════════════════
   TANDA 1 · Parche transversal MÓVIL / TABLET  (auditoría 30-jul-2026)
   ────────────────────────────────────────────────────────────────────────────────
   CONTRATO: ninguna regla de este bloque aplica en >=1367px. El escritorio no se
   toca. Todo vive dentro de @media(max-width:820px) o de
   @media(min-width:821px) and (max-width:1366px).

   CASCADA: index.php:213-218 carga costeos.css e inventario.css ANTES que admin.css,
   así que aquí ganamos los empates contra ellos sin !important. Contra los <style>
   que los .js inyectan en runtime (nomina.js:5233, transferencias.js) y contra los
   atributos style= inline SÍ hace falta !important; va justificado regla por regla.

   Qué cierra: los 6 bloqueantes de captura/costeos/inventario, 8 graves y el
   agujero sistémico de safe-area (había UN solo env() en 86KB de CSS).
   ════════════════════════════════════════════════════════════════════════════════ */

/* Tokens. env() devuelve 0px en escritorio y en cualquier equipo sin notch, o sea
   declararlos aquí no mueve un pixel fuera de iOS. El fallback 0px NO es opcional:
   sin él un navegador sin soporte descarta la declaración entera. */
:root{
  --sat:env(safe-area-inset-top,0px);
  --sab:env(safe-area-inset-bottom,0px);
  --sal:env(safe-area-inset-left,0px);
  --sar:env(safe-area-inset-right,0px);
  --tap:44px;   /* mínimo táctil de piso (Apple HIG). WCAG AA pide 24; con dedo grasoso y prisa, 24 no alcanza. */
}

/* Utilidad ÚNICA de scroll horizontal para tablas. Hoy conviven tres patrones en el
   repo (tarjetas en .ptable, ocultar columnas en .crtlist, wrapper en inventario) y
   ninguno es el default: quien escribe una tabla nueva no hereda nada. Este es el
   default a partir de ahora. Inerte hasta que alguien le ponga la clase. */
.scrollx{overflow-x:auto;-webkit-overflow-scrolling:touch;overscroll-behavior-x:contain}
.scrollx::-webkit-scrollbar{height:6px}
.scrollx::-webkit-scrollbar-thumb{background:var(--line);border-radius:3px}

/* ═══════════════ A · CELULAR Y TABLET VERTICAL  (<= 820px) ═══════════════ */
@media(max-width:820px){

  /* ── A1 · ÁREA SEGURA en todas las capas fijas ─────────────────────────────
     index.php:80 declara viewport-fit=cover y el manifest es display:standalone,
     pero en todo admin.css había un único env() (línea 811, los micro-avisos).
     Resultado en iPhone con notch: la franja superior nace debajo del recorte y
     los pies de modal terminan sobre la barra de gestos. Se resuelve UNA vez. */
  .topstrip{
    height:calc(var(--topH) + var(--sat));
    padding-top:calc(.32rem + var(--sat));
    padding-left:calc(1rem + var(--sal));
    padding-right:calc(1rem + var(--sar));
  }
  /* .shellbody reserva exactamente --topH (admin.css:907). Si crece la franja y no
     crece la reserva, la franja tapa el contenido: van SIEMPRE juntas. */
  .shellbody{padding-top:calc(var(--topH) + var(--sat))}
  .side{padding-top:calc(1rem + var(--sat));padding-bottom:calc(1rem + var(--sab))}
  .cfghead{padding-top:calc(1rem + var(--sat))}
  .mfoot{
    padding-bottom:calc(.85rem + var(--sab));
    padding-left:calc(1.1rem + var(--sal));
    padding-right:calc(1.1rem + var(--sar));
  }
  #toast{bottom:calc(1.2rem + var(--sab))}

  /* ── A2 · La franja superior deja de partirse en 3 filas ───────────────────
     .topstrip tiene height RÍGIDO (56px) + align-items:center y no lleva wrap,
     pero su hijo .topbar hereda flex-wrap:wrap de admin.css:66. Con 2 marcas +
     chips de sucursal el contenido pide ~435px sobre 309px disponibles: envuelve
     a 2-3 filas, se centra vertical y la PRIMERA fila sale por arriba de la
     pantalla (inalcanzable) mientras la última flota sobre el dashboard.
     Una sola fila con scroll-x lo mata. Verificado: no hay ningún dropdown
     position:absolute dentro de .topbar, así que overflow:auto no recorta nada. */
  .topstrip>*{flex:none}
  .topstrip .topbar{
    flex:1 1 auto;min-width:0;flex-wrap:nowrap;align-items:center;gap:.4rem;
    overflow-x:auto;overscroll-behavior-x:contain;scrollbar-width:none;
  }
  .topstrip .topbar::-webkit-scrollbar{display:none}
  .topstrip .topbar>*{flex:none}
  .topstrip .hubchips{flex-wrap:nowrap}
  /* Los logos de marca son HERMANOS de .topbar: se comían ~220px del presupuesto
     antes de que el scroller viera un solo pixel. */
  #brandMarcaLogos{max-width:96px;overflow:hidden}

  /* ── A3 · VELO del cajón lateral ───────────────────────────────────────────
     Con el cajón abierto no existe backdrop: el toque que lo cierra (handler de
     index.php:357, sin stopPropagation) sigue viaje hasta su destino real y abre
     "Nueva orden" o el detalle de un pedido. El cajero cierra el menú y le brota
     un modal. El ::after es fixed => su bloque contenedor es el viewport; se
     hit-testea como .shellbody, que no tiene onclick, así que el disparo
     accidental muere aquí SIN tocar una línea de JS.
     z-index 79: debajo de .side (80) y muy debajo de .ov (100). */
  body:not(.sbhide) .shellbody::after{
    content:"";position:fixed;inset:0;background:rgba(0,0,0,.42);z-index:79;
  }

  /* ── A4 · 44px táctiles ────────────────────────────────────────────────────
     Solo min-height: un <button> ya centra su contenido vertical, así que NO
     cambiamos display a flex (eso reventaría el espaciado SVG+texto de los
     botones de movimiento de efectivo, caja.js:215-217). */
  .btn,.btn.sm,.facbtn,.txtab,.hubtab,.hubchip,.pchip,.hday,.presedit .link{min-height:var(--tap)}
  .hday{width:var(--tap)}            /* .hdias ya es flex-wrap: se reacomoda solo */
  .xclose{width:var(--tap);height:var(--tap);font-size:1.05rem}
  /* El margin-right:55px de .cfgx (admin.css:284) esquiva un #sbtoggle que hoy es
     position:static: es un fantasma que solo desperdicia 55px de pantalla. */
  .cfgx{width:var(--tap);height:var(--tap);margin-right:0}
  .navgrpitems{gap:.3rem}            /* 1.6px entre destinos de navegación era una ruleta */
  .navgrpitems .nav{min-height:var(--tap)}
  #sbtoggle{width:var(--tap);height:var(--tap)}
  /* Switch de disponibilidad: 42x24 reales, el control MÁS tocado del módulo.
     Se agranda el ÁREA, no el dibujo: ::after es el knob, ::before estaba libre.
     El padding de .drow sube con él; agrandar el área sin separar las filas
     crearía solape entre vecinas y el cajero apagaría el producto de arriba. */
  .drow{padding:.7rem .2rem}
  .dsw::before{content:"";position:absolute;inset:-10px;border-radius:99px}

  /* ── A5 · 16px en inputs: mata el auto-zoom de iOS al enfocar ──────────────
     HONESTIDAD: hoy no compra nada, porque index.php:80 lleva user-scalable=no.
     Es el PRERREQUISITO de la Tanda 3 (soltar el candado de zoom): sin esto, iOS
     reencuadraría la pantalla en cada foco. Se excluyen checkbox/radio/color/range
     porque min-height sobre ellos deforma switches y selectores de color. */
  input:not([type=checkbox]):not([type=radio]):not([type=color]):not([type=range]),
  select,textarea{min-height:var(--tap);font-size:16px}
  /* Estos traen font-size en atributo style= (reportes.js:51, inventario.js:463) o
     en CSS de módulo: sin !important el 16px de arriba pierde. */
  #dsh_d0,#dsh_d1,
  #page-inventario input,#page-inventario select,
  #page-costeos input,#page-costeos select{font-size:16px!important}
  /* Contrapartida: los color/checkbox microscópicos ganan área sin deformarse.
     min-width/min-height son propiedades DISTINTAS de width/height, así que vencen
     al inline width:24px de config.js:177 sin necesidad de !important. */
  input[type=color]{min-width:var(--tap);min-height:36px}
  input[type=checkbox],input[type=radio]{min-width:22px;min-height:22px}

  /* ── A6 · BLOQUEANTE: "Nueva orden" recupera la columna de productos ───────
     index.php:540 lleva style="grid-template-columns:1fr 380px" INLINE. El inline
     gana a cualquier selector sin !important, así que .mbody{1fr} de admin.css:781
     nunca entró: en 390px el ancho útil es 338.8px, la pista fija de 380px no cabe
     y la pista 1fr colapsa a 0px (.npmenu tiene overflow:hidden => su tamaño mínimo
     automático es 0). Buscador, chips de categoría y lista de productos: 0px de
     ancho. Y #ovn .mbody{overflow:hidden} (admin.css:721) borra el scroll de
     rescate. No se podía levantar un pedido desde el celular. Punto.
     El !important aquí no es pereza: es el único mecanismo que vence a un style=. */
  #ovn .modal{width:100vw;max-width:100vw;height:100dvh;border-radius:0}
  #ovn .mbody{grid-template-columns:1fr!important;overflow-y:auto!important;overflow-x:hidden!important}
  /* UN solo scroller (el .mbody), no tres anidados: en táctil los scrollers
     anidados son una tortura — el dedo nunca sabe cuál va a moverse. */
  #ovn .npmenu{overflow:visible;min-height:0}
  #ovn .nplist{flex:none;max-height:none;overflow:visible;min-height:0}
  #ovn .mbody>div:last-child{overflow-y:visible}
  /* Mismo mecanismo, otras instancias del grid de 3 columnas en línea
     (index.php:548, inicio.js:1379 y 1388: CP / Colonia / Envío en 140px). */
  .three{grid-template-columns:1fr!important}
  .three>.field{min-width:0}

  /* ── A7 · Overlays creados por JS con cssText inline ───────────────────────
     admin_core.js:143 e inventario.js:338 centran con align-items:center y SIN
     overflow. Cuando el contenido crece (19+ renglones en "Saldar reparto",
     5-6 entidades en "Ticket de conteo") el excedente se reparte arriba Y abajo:
     el encabezado se va por arriba y el pie con el botón deja de existir.
     Inline otra vez => !important. */
  #ovdlg,#inv-conteo-modal{
    align-items:flex-start!important;
    overflow-y:auto!important;
    padding-top:calc(1rem + var(--sat))!important;
    padding-bottom:calc(1rem + var(--sab))!important;
  }

  /* ── A8 · Configuración: mover su corte de 760 a 820 ───────────────────────
     El cascarón corta en 820 y Configuración en 760: la franja 761-820 es tierra
     de nadie y cae EXACTAMENTE en el iPad vertical (768px), donde la nav de 240px
     fijos se come el 32% de la pantalla. Se re-declaran las reglas de admin.css:353
     en el breakpoint correcto; arriba de 820 no cambia nada. */
  .cfgwrap{flex-direction:column}
  .cfgnav{width:100%;position:static;display:flex;flex-wrap:wrap;gap:.2rem}
  .cfgnav .grp{width:100%}
  .cfgnav button{width:auto}
  .cfgscreen .cfgnav{top:0}
  /* La barra del hub (chips de sucursal + 15 pestañas, ambas con wrap) es sticky y
     se comía media pantalla. Scoped a .suchubbar para no tocar el #sucSwitch que
     vive en la franja superior (mismo .hubchips, otro contexto). */
  .suchubbar{position:static}
  .suchubbar .hubchips{display:flex;width:100%}
  .suchubbar .hubchips,.hubtabs{flex-wrap:nowrap;overflow-x:auto;-webkit-overflow-scrolling:touch;scrollbar-width:none}
  .suchubbar .hubchips::-webkit-scrollbar,.hubtabs::-webkit-scrollbar{display:none}
  .hubtab,.hubchip{white-space:nowrap;flex:none}

  /* ── A9 · Tablas: el wrapper scrollea, la tabla conserva su ancho natural ──
     Sin el min-width, un width:100% deja al wrapper sin nada que desplazar y el
     scroll es decorativo. Esa es la trampa en la que ya cayó el repo dos veces. */
  .scrollx>table{min-width:640px}
  .scrollx.wide>table{min-width:780px}

  /* BLOQUEANTE · Inventario > Configuración: 8 columnas dentro de una tarjeta con
     overflow:hidden (inventario.css:948). COMPRA A / ALERTA / ACTIVO simplemente
     no existían en el teléfono. Es la única tabla del módulo sin wrapper. */
  #page-inventario .inv-ord-prov-body{overflow-x:auto;-webkit-overflow-scrolling:touch}
  #page-inventario .inv-cfg-tbl{min-width:640px}
  /* Inventario > Captura física: el rediseño en tarjetas YA existe, lo anulaba un
     min-width:700px heredado. (1,2,1) vence a (1,1,1) sin !important. */
  #page-inventario table.data-tbl.inv-cap-gridtable{min-width:0}
  /* Costeos > Catálogo de insumos: el inline min-width:0 mataba el min-width:700px
     de costeos.css:33 y dejaba la tabla clavada en 310px con columnas de 22px:
     los inputs se pintaban unos encima de otros. */
  #page-costeos #cst-precios table.data-tbl{min-width:760px!important}
  /* Transferencias: 3 tablas sin wrapper, recortadas por html,body{overflow-x:hidden}.
     display:block convierte la tabla en su propio scroller sin tocar el HTML.
     transferencias.js inyecta su <style> en runtime (gana por orden) => !important.
     Es un parche; el wrapper .scrollx es la solución correcta y va en Tanda 3. */
  table.txt{display:block!important;overflow-x:auto!important;-webkit-overflow-scrolling:touch}

  /* ── A10 · Grids fijos que nunca colapsan ──────────────────────────────────
     Los dos primeros son BLOQUEANTES: el editor de escandallo y el de platillo
     nacen fuera de pantalla y html,body{overflow-x:hidden} los recorta sin scroll
     posible. El layout vive en style= inline (costeos.js:131,167,198) => !important
     obligatorio hasta que la Tanda 3 lo pase a clases. */
  #page-costeos #cst-recetas-prep>div,
  #page-costeos #cst-recetas>div{grid-template-columns:1fr!important}
  #page-costeos #cst-menu>div{flex-direction:column!important;min-height:0!important}
  #page-costeos #cst-menu>div>div:first-child{width:auto!important}
  #page-costeos #menu-arbol{max-height:240px}
  #page-costeos .top10-grid{grid-template-columns:1fr}
  /* nomina.js inyecta su CSS en runtime (_NOM_CSS, nomina.js:5233): empata en
     especificidad y gana por orden => !important. Con auto-fit el escritorio
     sigue dando las mismas 4 columnas. */
  #page-nomina .nom-hr-kpis{grid-template-columns:repeat(auto-fit,minmax(150px,1fr))!important}

  /* ── A11 · Disponibilidad: el nombre deja de colapsar a 0px ────────────────
     .dname es flex:1 1 0% con min-width:0 y el espacio libre es NEGATIVO
     (190+64+54+gaps = 344 sobre 312 útiles): su peso de encogimiento es 0, se
     queda en 0px y el texto se pinta encima de la pastilla del grupo. */
  .dthead{display:none}
  .drow{flex-wrap:wrap;row-gap:.3rem}
  .drow>div{min-width:0}
  .drow .dname{flex:1 1 100%;order:-1;overflow-wrap:anywhere}

  /* ── A12 · Mínimos tipográficos ────────────────────────────────────────────
     9px en mayúsculas con letter-spacing, en una app donde el pellizco está
     bloqueado por CUATRO mecanismos distintos, es inaccesible por definición.
     Se suben solo las etiquetas; los datos ya estaban bien. */
  .cxmtbl th,.cxmtptbl th{font-size:11px;letter-spacing:.2px}
  .cxmpsub{font-size:11px}
  .v2lab>span{font-size:11px}
  .evchip,.evcod,.dsuc{font-size:.78rem}
  .v2kk{font-size:12px}

  /* ── A13 · Modales centrados: dvh en vez de vh ─────────────────────────────
     En iOS Safari vh es el viewport GRANDE (barras retraídas): un modal al tope de
     su max-height pierde ~40px por abajo, que es casi todo el .mfoot con el botón
     Guardar/Cobrar. .ov (fixed + inset:0) no se toca: ya se ancla al visible. */
  #ov .modal,#ovcrop .modal{max-height:94dvh}
  #ovo .modal{max-height:90dvh}
  /* #ovcaja: min-width:min(420px,94vw)=366.6px es un piso duro contra 358px de
     hueco => desborda 4px por lado y se ven las esquinas cortadas. */
  #ovcaja .modal{min-width:min(420px,100%)}
}

/* ═════════ B · TABLET HORIZONTAL Y LAPTOP CHICA  (821 - 1366px) ═════════ */
@media(min-width:821px) and (max-width:1366px){

  /* B1 · Área segura lateral: en iPad apaisado con notch, viewport-fit=cover mete
     el contenido debajo del recorte. Arriba el inset es 0 en este rango. */
  .topstrip{padding-left:calc(1rem + var(--sal));padding-right:calc(1rem + var(--sar))}
  .mfoot{padding-bottom:calc(.85rem + var(--sab))}
  main{padding-left:calc(1.5rem + var(--sal));padding-right:calc(1.5rem + var(--sar))}

  /* B2 · Pedidos a 1024: con .side abierta (el estado por defecto) quedan 732px
     para 8 columnas con table-layout:fixed. Sucursal recibe 41px útiles para
     "PACABTUN" con white-space:nowrap => el texto se pinta ENCIMA de la celda
     vecina y el chip de estado (fondo opaco) tapa el nombre de la sucursal.
     Bajar padding y permitir wrap es el mínimo; reajustar los % del colgroup
     (pedidos.js:802) es Tanda 2.
     OJO: esto también toca laptops de 1280. Es mejora, pero verifícalo. */
  .ptable td,.ptable th{padding:.6rem .45rem;font-size:.86rem}
  .ptable tr.ptr td,.ptable td .pp{white-space:normal}
}

/* B3 · La franja de peek de 16px solo tiene sentido con puntero fino. En iPad
   táctil no se dispara nunca (depende de mouseenter) y lo único que hace es
   interceptar los toques del borde izquierdo de la pantalla. */
@media(min-width:821px) and (max-width:1366px) and (pointer:coarse){
  .peekzone{display:none}
}
/* ══════════════════════════ FIN TANDA 1 ══════════════════════════ */


/* ═══════════ TANDA 2-3 · shell.css ═══════════ */
/* ════════════════════════════════════════════════════════════════════════════════
   TANDA 3 · Cascarón (index.php) — fragmento concatenado al final de admin.css.
   Va DESPUÉS de todo, así que pisa por orden a igual especificidad. Donde hay que
   vencer a un selector con #id de admin.css, la regla repite el #id: no se usa
   !important para eso.
   ════════════════════════════════════════════════════════════════════════════════ */

/* Botón ✕ del cajón lateral. Clase NUEVA (no existía en el repo), por eso la base
   puede ir suelta: en escritorio y en iPad 821-1366 el cajón no tapa el ☰ y este
   botón sobra. Solo se enciende en la rama móvil. */
.sideclose{display:none}

@media(max-width:820px){

  /* ── S1 · Salida del cajón ────────────────────────────────────────────────
     Con .side abierta (fixed, 280px, z-index:80) el ☰ queda debajo: es
     position:static dentro de .topstrip (z-index:60, x desde 16px). El único
     cierre disponible era tocar fuera, que además activaba lo de abajo.
     44px = --tap; align-self para que no se estire a todo el ancho del flex
     columna de .side sin tocar el align-items del contenedor. */
  .sideclose{
    display:flex;align-items:center;justify-content:center;
    align-self:flex-end;flex:none;
    width:var(--tap);height:var(--tap);margin:-.25rem -.15rem .35rem 0;
    border:1px solid var(--line);border-radius:11px;
    background:var(--card);color:var(--ink-mid);
    font-size:1.05rem;line-height:1;cursor:pointer;
  }
  .sideclose:active{background:var(--wash)}

  /* ── S2 · El teclado virtual deja de tapar el .mfoot ───────────────────────
     iOS no encoge el viewport de LAYOUT al abrir el teclado: .ov es fixed
     inset:0 y sigue midiendo la pantalla completa, así que el modal centrado
     se centra contra 844px mientras solo se ven ~400px. El botón de cobrar /
     guardar quedaba fuera de la pantalla y sin scroll que lo alcanzara.
     --vvh/--vvoff los publica el helper de visualViewport (index.php) SOLO en
     móvil; si no existen, cada var() cae en su fallback y esto es idéntico a
     antes de la Tanda 3.
     Anclar .ov al viewport visible resuelve de un golpe todos los modales de
     panel lateral (.modal es absolute height:100% dentro de .ov) y reencuadra
     el centrado flex de los que van centrados. bottom:auto es obligatorio: con
     el inset:0 heredado, top+bottom sobre-restringen y el height se ignora. */
  .ov{top:var(--vvoff,0px);bottom:auto;height:var(--vvh,100%)}
  /* REVISIÓN · el selector iba suelto (.modal) y .modal NO es un nombre exclusivo
     de este cascarón: costeos.js:256/270/278 monta su propio sistema de modales
     con class="modal" (backdrop fixed height:100%, costeos.css:53) y .modal-box
     dentro. Un max-height suelto le recortaba el backdrop y su .modal-box de
     90vh se desbordaba. Se acota a los 9 .modal que viven dentro de un .ov
     (index.php:530..762); (0,2,0) sigue perdiendo contra #page-costeos .modal. */
  .ov .modal{max-height:var(--vvh,none)}
  /* Los modales centrados traen su propio max-height con #id (admin.css:706-716
     y TANDA 1 A13): se repite el #id para empatar especificidad y ganar por
     orden, y se combina con min() para NO aflojar el presupuesto que ya tenían.
     REVISIÓN · el tope ya no es var(--vvh) sino 100%. Los cinco overlays son
     display:flex con padding:2vh 1rem (admin.css:705-715, regla SUELTA que la
     Tanda 1 no reencuadró): la caja de contenido del .ov mide --vvh menos 4vh,
     así que un hijo con max-height:--vvh se desborda ~34px y align-items:center
     los reparte 17px arriba y 17px ABAJO — justo encima del .mfoot que veníamos
     a rescatar. El porcentaje se resuelve contra esa caja de contenido, o sea
     contra el hueco real, y sale exacto con y sin teclado. */
  #ov .modal,#ovcrop .modal{max-height:min(94dvh,100%)}
  #ovo .modal{max-height:min(90dvh,100%)}
  #ovcaja .modal{max-height:min(700px,92dvh,100%)}
  /* #ovn va a pantalla completa (TANDA 1 A6: height:100dvh). El max-height lo
     recorta al alto visible sin quitarle el "pantalla completa" cuando no hay
     teclado, que es lo que hace usable levantar un pedido desde el celular.
     REVISIÓN · aquí el padding:2vh 1rem heredado de admin.css:702 no es un
     detalle: con width:100vw y height:100dvh (TANDA 1 A6) el modal ya se
     desbordaba 2rem en horizontal y 4vh en vertical, centrado, o sea que en
     "pantalla completa" se comía 17px de cabecera y 17px de pie. Se anula el
     padding SOLO en esta rama: 100vw/100% pasan a ser exactamente la pantalla
     visible, sin recortes y sin franjas de backdrop. */
  #ovn.show{padding:0}
  #ovn .modal{max-height:100%}

  /* NOTA (jul-30): el candado de zoom SE CONSERVA por decisión del dueño. Aquí vivía una
     regla touch-action:manipulation que lo soltaba en Android/iPad; se retiró junto con el
     cambio del meta en index.php. html,body{touch-action:pan-x pan-y} de admin.css:881
     sigue mandando. Si algún día se reabre el tema, la cuarta pata es esa. */
}


/* ═══════════ TANDA 2-3 · inicio.css ═══════════ */
/* ══════════════════════════════════════════════════════════════════════════════
   TANDA 2 · inicio.js — Paso 1 de Domicilio, encabezado de canal y filas En vivo
   ────────────────────────────────────────────────────────────────────────────────
   Contrato de la Tanda 1: fuera de estas media queries no se mueve el escritorio.
   La ÚNICA excepción son las cuatro clases nuevas de abajo (.cliov/.clibody/
   .clipanes/.clipane-*), que van sueltas porque son la copia literal de lo que
   hasta hoy viajaba en atributos style= — mismos valores, cero delta visual — y
   sin una base fuera de la media query el modal se quedaría sin layout en >820px.
   ══════════════════════════════════════════════════════════════════════════════ */

/* Portadas del modal "Domicilio · cliente" (inicio.js:1352 y 1366). Nadie más usa
   estos nombres. Se copian TAL CUAL del style= que sustituyen, incluido el 92vh
   (que en escritorio vale lo mismo que dvh) y el var(--wash) del panel izquierdo. */
.cliov{position:fixed;inset:0;background:rgba(0,0,0,.45);display:none;align-items:center;justify-content:center;z-index:125;padding:1rem}
.clibody{background:var(--card);border-radius:18px;width:min(900px,96vw);max-height:92vh;display:flex;flex-direction:column;overflow:hidden;box-shadow:0 24px 60px rgba(0,0,0,.28)}
.clipanes{flex:1 1 auto;min-height:0;overflow:auto;display:grid;grid-template-columns:1fr 1fr}
.clipane-l{padding:1rem 1.1rem 1rem 1.3rem;border-right:1px solid var(--line);background:var(--wash)}
.clipane-r{padding:1rem 1.3rem 1rem 1.1rem}

@media(max-width:820px){

  /* ── GRAVE · el Paso 1 del domicilio deja de ser una rejilla de 2 columnas fija ──
     El grid iba en el style= inline, o sea NUNCA colapsaba: en 390px el ancho útil
     del modal es ~358px y cada panel caía a ~140px descontando los paddings de
     1.1-1.3rem. Con 140px, "Entre calles" y el desplegable de colonias se pintan
     encima del vecino y el teléfono —el campo que manda en este paso— queda en tres
     caracteres. El iPad vertical (768px) cae en la misma rama y sufría igual.
     Ahora que el layout es una clase, basta con volver a declarar la pista. */
  .clipanes{grid-template-columns:1fr}
  /* Apilados, el filete vertical del panel izquierdo señala hacia la nada: pasa a
     ser el separador horizontal entre "cliente" y "dirección de entrega". */
  .clipane-l{border-right:0;border-bottom:1px solid var(--line);padding:.9rem 1rem}
  .clipane-r{padding:.9rem 1rem}
  /* REVISIÓN · los grid items de .clipanes son los DOS PANELES, no los .field (esos
     cuelgan de los paneles, un nivel más abajo). El min-width:0 que evita que el
     tamaño mínimo automático desborde la única columna tiene que ir aquí; sobre
     .field no hacía nada, y los .field que SÍ son grid items —los de .three— ya los
     cubre .three>.field{min-width:0} de la Tanda 1 (admin.css:1088). Se conserva la
     regla sobre .field porque es inocua y cubre cualquier .three futuro. */
  .clipane-l,.clipane-r{min-width:0}
  .clipanes .field{min-width:0}

  /* ── GRAVE · "Continuar a productos →" deja de nacer debajo del teclado ─────────
     iOS no encoge el viewport de LAYOUT al abrir el teclado: el overlay seguía
     creyendo que la pantalla mide 844px, se centraba contra esa altura y el pie del
     modal —el único botón que cierra el Paso 1— quedaba tapado. No había rescate
     posible: el scroll interior es el de .clipanes, el pie va FUERA de él, y el
     único gesto que baja el teclado (tocar fuera) no cierra este modal a propósito.
     Se reancla el overlay al viewport VISIBLE que publica index.php:400. Si el
     navegador no trae visualViewport, index.php no escribe las variables y el
     fallback del var() deja el comportamiento de hoy intacto. */
  .cliov{
    top:var(--vvoff,0px);height:var(--vvh,100dvh);bottom:auto;
    /* flex-start y no center: al encoger el hueco, "centrado" significa que el
       encabezado se sale por arriba y el pie por abajo a partes iguales. */
    align-items:flex-start;
    padding:.5rem calc(.5rem + var(--sar)) calc(.5rem + var(--sab)) calc(.5rem + var(--sal));
  }
  /* max-height:100% se mide contra la caja de contenido del .cliov, que ya vale el
     alto visible menos el área segura => el pie SIEMPRE cae dentro. El 92vh de la
     regla base era justo el valor que mentía. */
  .clibody{width:100%;max-height:100%}
  /* REVISIÓN · media arreglo no es arreglo: subir el pie al viewport visible lo deja
     VERTICALMENTE dentro, pero horizontalmente seguía cortado. El pie es un flex sin
     wrap con padding 1.3rem por lado (inicio.js:1404) y #cli_cont lleva
     min-width:230px INLINE, que es un piso duro: en 390px el ancho útil del pie es
     ~332px y el suelo de los dos botones (Cancelar ~96px + gap .6rem + 230px) son
     ~336px; en 360px son ~302px contra los mismos ~336px. Lo que sobra lo recorta el
     overflow:hidden de .clibody, así que "Continuar a productos →" se veía sin su
     borde derecho. Se suelta el piso y el botón toma el hueco que quede.
     El !important no es pereza: min-width viaja en un atributo style=, que ni
     siquiera un selector de id vence sin él (mismo criterio que la Tanda 1). */
  #cli_cont{min-width:0!important;flex:1 1 auto}

  /* ── El encabezado de cada tarjeta de canal alcanza el piso táctil ──────────────
     .areah[onclick] (inicio.js:340) es el ÚNICO disparador de "Nueva orden" desde
     que se retiró el "+", y medía los 34px que impone el chip del icono. Es la
     acción más repetida del turno y estaba 10px por debajo del mínimo. Crece el
     ÁREA, no el dibujo. Los márgenes negativos compensan el padding nuevo contra el
     .8rem de .areacard: así la zona tocable llega al borde de la tarjeta en vez de
     encogerse hacia dentro, y el resalte de :active (admin.css:934) la acompaña.
     El encabezado sin onclick (caja cerrada) no se toca: no dispara nada. */
  .areah[onclick]{min-height:var(--tap);padding:.3rem .4rem;margin:-.3rem -.4rem .5rem}

  /* ── Tablero En vivo: las filas dejan de ir pegadas ─────────────────────────────
     .v2ev (admin.css:148) solo declara cursor y radio: sin padding propio y sin
     separador, los pedidos se apilan a hueso en ~42px y a ojo no se distingue dónde
     acaba uno y empieza el siguiente — con el agravante de que cada fila abre un
     pop-up distinto, así que equivocarse cuesta un modal de más.
     Es SOLO presentación: ni el markup ni el refresco de 15s se tocan. El filete de
     color del borde izquierdo es inline y se respeta; el padding-left lo despeja. */
  .areacard .v2ev{padding:.45rem .55rem}
  .areacard .v2ev+.v2ev{margin-top:.4rem;border-top:1px solid var(--line)}
}


/* ═══════════ TANDA 2-3 · carta.css ═══════════ */
/* ════════════════════════════════════════════════════════════════════════════════
   TANDA 2 · carta.css — Catálogo / Promos / Combos / Menús TV
   Solo clases NUEVAS (no existían en el repo: verificado con grep sobre todo el
   proyecto). Las reglas sueltas de aquí abajo son la copia EXACTA de atributos
   style= que ya vivían en el HTML generado por catalogo.js y tv_menus.js: al
   mudarlos a clase el escritorio se pinta idéntico, pero dejan de ser inamovibles.
   Ese era el problema real: un style= gana a cualquier hoja, incluidas las media
   queries del parche móvil, así que los arreglos existentes no llegaban a entrar.
   ════════════════════════════════════════════════════════════════════════════════ */

/* ── Disponibilidad > Personalizaciones (catalogo.js) ────────────────────────────
   Mismos 190px y 54px que traía el inline. La utilidad está en poder pisarlos abajo. */
.dcolgrp{width:190px}
.dcolsw{width:54px;text-align:right}

/* ── Menús TV · fila de la playlist (tv_menus.js) ────────────────────────────────
   Réplica literal del style= de la fila y del bloque de detalle. .tvslide-ctl es el
   agrupador nuevo de los controles: con el mismo gap del padre y flex:none se ve
   igual que cuando los tres eran hermanos sueltos. */
.tvslide{display:flex;align-items:center;gap:.6rem;padding:.4rem 0;border-bottom:1px dashed var(--line)}
.tvslide-det{flex:1;min-width:120px;font-size:.86rem}
.tvslide-ctl{display:flex;align-items:center;gap:.6rem;flex:none}

@media(max-width:820px){

  /* Disponibilidad > Personalizaciones: la columna del grupo tenía 190px CLAVADOS sobre
     ~305px de fila, así que el parche A11 (.drow flex-wrap + .dname a línea completa)
     entraba en Productos y no aquí: el nombre de la opción se quedaba en 0px y su texto
     se pintaba encima de la pastilla del grupo. Ahora el grupo cede lo que haga falta y
     la pastilla parte en dos renglones antes que desbordar (tiene white-space:nowrap
     propio, admin.css:378, y con min-width:0 se saldría de la tarjeta). */
  .drow .dcolgrp{width:auto;flex:1 1 auto;min-width:0}
  .drow .dpill{white-space:normal;overflow-wrap:anywhere}
  .drow .dcolsw{width:auto;flex:none}

  /* Menús TV: la fila pedía ~527px mínimos dentro de 313px y, sin wrap ni scroll
     (html,body llevan overflow-x:hidden), el switch y los botones ↑ ↓ 🗑 quedaban fuera
     de la pantalla: no se podía apagar, mover ni borrar un slide desde el teléfono.
     Dos renglones: arriba número + miniatura + descripción, abajo los controles.
     Quien fuerza el corte donde debe es el min-width:0 del detalle (la basis ya era 0:
     el `flex:1` de la regla suelta de arriba es 1 1 0%, se repite aquí solo para dejar la
     declaración completa a la vista). Con el min-width:120px original, una descripción
     larga ("Menú · Kung Pao · todas las categorías") no puede encoger por debajo de esos
     120px y se lleva ella sola un renglón, partiendo la fila en tres. */
  .tvslide{flex-wrap:wrap;row-gap:.45rem}
  .tvslide-det{flex:1 1 0;min-width:0;overflow-wrap:anywhere}
  .tvslide-ctl{flex:1 1 100%;flex-wrap:wrap;justify-content:flex-end}
}


/* ═══════════ TANDA 2-3 · reordenar.css ═══════════ */
/* ════════════════════════════════════════════════════════════════════════════════
   TANDA 3 · reordenar.css — botones ↑ ↓ de la carta (productos.js)
   Reordenar la carta era imposible con el dedo: el arrastre es HTML5 drag-and-drop
   y ni Safari iOS ni Chrome Android disparan dragstart/drop. productos.js ahora pinta
   un par de ↑ ↓ junto al asa ⠿ en los tres niveles (categoría, producto y
   personalización adjunta). Todo lo de aquí cuelga de clases que NO existían
   (.mvg, .mvb, .pcact), salvo el bloque móvil del final, que sí está en media query.
   ════════════════════════════════════════════════════════════════════════════════ */

/* El par ↑ ↓ va pegado y no se estira ni se parte, esté donde esté (cabecera de
   categoría, fila de personalización o pie de tarjeta de producto). */
.mvg{display:inline-flex;gap:.2rem;flex:none}
.mvb{padding:.4rem .5rem;line-height:1;font-weight:700}
/* admin.css no tiene NINGUNA regla para [disabled]: sin esto, el ↑ del primero se ve
   idéntico al de los demás y parece que la app no responde al pulsarlo. */
.mvb[disabled]{opacity:.38;cursor:default}
.mvb[disabled]:hover{background:var(--card);filter:none}

/* Pie de la tarjeta de producto: ↑ ↓ + Editar en un solo renglón. .pcedit trae
   width:100% (admin.css:269) pensado para ser hijo único del flex vertical; dentro de
   .pcact eso lo haría empujar a los botones fuera de la tarjeta. Se neutraliza SOLO
   aquí dentro, por eso el selector va anclado a la clase nueva. */
.pcact{display:flex;align-items:center;gap:.35rem;margin-top:.15rem}
.pcact .pcedit{width:auto;flex:1 1 auto;margin-top:0}

@media(max-width:820px){
  /* 44px reales de blanco táctil. La altura ya la da TANDA 1 (.btn.sm min-height:--tap);
     falta el ancho: una flecha con padding .4rem mide ~30px y con el pulgar en marcha se
     falla, que es justo el escenario que este arreglo viene a resolver. */
  .mvb{min-width:var(--tap)}

  /* La cabecera de categoría ya iba justa a 390px (asa + ▾ + nombre + "N productos" +
     Editar + Eliminar) y no envuelve; con dos botones más los de la derecha se salían
     de la pantalla, y html/body llevan overflow-x:hidden, o sea quedaban inalcanzables.
     Con wrap y el nombre a renglón completo el corte cae donde debe, en vez de un
     título aplastado a dos letras por línea (con flex:1 y basis 0 nunca fuerza corte:
     se comprime él y deja fuera a los demás). */
  .catcard-h{flex-wrap:wrap;row-gap:.4rem}
  .catcard-h .ct{flex:1 1 100%}
}

/* REVISIÓN · tablet en horizontal (iPad 1180x820, iPad Pro 1024/1366) — el bloque de
   arriba es max-width:820px y NO alcanza a ninguna de ellas, pero .mvb{padding:.4rem .5rem}
   sí es global: en esas pantallas la flecha queda en ~30x28px, MÁS pequeña que el .btn.sm
   por defecto (padding .4rem .75rem). O sea el fragmento encogía el destino táctil justo
   en el equipo que el hallazgo nombra. Se repara con el mismo rango y la misma condición
   que ya usa TANDA 1 para el peek (admin.css:1215): min-width/height 821-1366 + pointer
   coarse. Un escritorio de 1440px con ratón falla las dos condiciones y no se entera; a
   1024px de ancho la cabecera de categoría sigue cabiendo con las flechas a 44px, así que
   esto no reintroduce el desborde que arregla el bloque de 820. */
@media(min-width:821px) and (max-width:1366px) and (pointer:coarse){
  .mvb{min-width:var(--tap);min-height:var(--tap)}
}


/* ═══════════ TANDA 2-3 · reportes-inv.css ═══════════ */
/* ════════ TANDA 2 · reportes + inventario (móvil/tablet) ════════ */

/* ── Configuración · Equipos: el nombre deja de colapsar a ~38px ─────────────
   La fila de cada equipo es punto·nombre(flex:1)·botonera, y la botonera es
   flex:none con max-width:240px (reportes.js, eqCard). En 390px la tarjeta
   ofrece ~311px útiles: 11 del punto + 25.6 de gaps + 240 de botonera = 276.6,
   y como la botonera NO encoge, al nombre le sobran 34px. "SUCURSAL PACABTUN ·
   192.168.1.40" se pintaba en columna de una letra por renglón y el estado
   quedaba ilegible. La botonera baja a su propio renglón completo: el nombre
   recupera los ~287px y los botones dejan de competir por el ancho.
   !important porque flex y max-width viven en el atributo style= inline.
   row-gap TAMBIÉN lo lleva: la fila trae gap:.8rem INLINE y el atajo `gap` fija row-gap,
   así que un row-gap de hoja de estilos pierde contra el inline y no haría absolutamente
   nada (quedaría el .8rem). */
@media(max-width:820px){
  .eqrow{flex-wrap:wrap;row-gap:.5rem!important}
  .eqacc{flex:1 1 100%!important;max-width:none!important;justify-content:flex-start!important}
}

/* ── Inventario · Captura física: el 16px del input de cantidad sí entra ─────
   La Tanda 1 apuntó a este control con #page-inventario input{font-size:16px
   !important} (1,0,1), pero inventario.css:1255 declara
   #page-inventario table.data-tbl input.cap-actual{font-size:13px!important}
   (1,2,2): entre dos !important gana la especificidad, así que el input más
   tocado del módulo seguía en 13px. Se re-declara con la MISMA especificidad;
   admin.css se carga después de inventario.css (index.php:220 vs 224), o sea
   aquí ganamos por orden. El alto ya lo resuelve el min-height:44px genérico:
   este input no trae height inline, solo padding.
   Sin esto, soltar el candado de zoom (Tanda 3) reencuadra la pantalla en cada
   celda que el almacenista toca.
   PENDIENTE consciente: el ancho sigue clavado en 80px por inventario.css:510
   (#page-inventario #inv-cap-tbody td.cap-side input.cap-actual, (2,2,2)), que
   con border-box y padding 6px 10px deja 58px de caja de texto: a 13px cabían
   ~7 dígitos, a 16px caben ~6. Un "1250.75" ya no se ve entero mientras se
   teclea (el input scrollea, no se pierde el dato). Ensancharlo desde aquí NO
   se puede: haría falta repetir esa cadena de (2,2,2) y eso ya es tocar el
   layout de la tarjeta de captura, que es trabajo de otra tanda. */
@media(max-width:820px){
  #page-inventario table.data-tbl input.cap-actual{font-size:16px!important}
}


/* ═══════════ TANDA 2-3 · transf-config.css ═══════════ */
/* ════════════════════════════════════════════════════════════════════════════════
   TANDA 3 · fragmento transferencias-config
   ────────────────────────────────────────────────────────────────────────────────
   Se concatena al final de admin.css, o sea después de la Tanda 1: aquí ganamos los
   empates contra ella sin !important. Contra los style= inline de config.js SÍ hace
   falta y va justificado regla por regla.
   Transferencias: sus tres tablas ya usan .scrollx / .scrollx.wide (Tanda 1 las
   define), pero además hay que RETIRAR el parche table.txt de la Tanda 1 — ver
   abajo. El resto es matriz de permisos.
   ════════════════════════════════════════════════════════════════════════════════ */

@media(max-width:820px){

  /* ── REVISIÓN · retiro del parche table.txt de la Tanda 1 (admin.css:1144) ───
     Tanda 1 puso table.txt{display:block!important;overflow-x:auto!important} como
     apaño mientras no hubiera wrapper. Ya lo hay, y los dos juntos NO son "feo pero
     inofensivo": con display:block la <table> deja de ser caja de tabla y los <tr>
     generan una tabla ANÓNIMA dentro. Esa tabla anónima es la que hace el layout, y
     con width:auto usa shrink-to-fit, así que ni table.txt{width:100%} ni el
     .scrollx>table{min-width:640px} la alcanzan: sizean el bloque, no la tabla. O
     las columnas no reparten los 640/780px y queda hueco a la derecha, o se pasan y
     salta un SEGUNDO scroller anidado dentro del .scrollx — uno sin el
     overscroll-behavior-x:contain ni el ::-webkit-scrollbar de .scrollx.
     Este fragmento va DESPUÉS de admin.css, así que empata en especificidad
     ((0,1,1) con !important en los dos) y gana por orden. table.txt existe
     únicamente en transferencias.js y sus tres tablas llevan wrapper: no hay ningún
     otro consumidor que dependa del apaño. Si alguien borra admin.css:1140-1144
     esto queda en no-op (display:table es el valor inicial de <table>). */
  table.txt{display:table!important;overflow:visible!important}

  /* ── Matriz de permisos del editor de usuarios (config.js, usuarioEditor) ────
     La fila era [▸][etiqueta][Sin acceso|Ver|Ver y hacer] en UNA sola línea flex.
     El segmento es flex:none y pide ~210px, el chevron 18px y los gaps 16px: sobre
     los ~300px útiles del modal en un 390px, a la etiqueta le quedaban ~40px. El
     administrador veía "Corte d…" al lado de tres casillas de 25px de alto pegadas
     entre sí, y las filas vecinas separadas por 8px. Es la pantalla donde se decide
     quién puede cobrar: elegir el permiso de la fila de arriba por error no es un
     defecto estético, es un agujero de seguridad.
     Se resuelve con el MISMO patrón que la Tanda 1 aplicó a .drow en Disponibilidad
     (admin.css A11): la etiqueta se queda con su renglón y el control se va al de
     abajo a ancho completo. Diferencia deliberada: aquí la etiqueta NO lleva
     order:-1 porque el chevron es su botón de desplegado y su marca de sangría en
     el árbol — separarlos dejaría un "▸" huérfano en la fila del control. */
  .upermrow{flex-wrap:wrap}

  /* El padding es un shorthand inline y su valor izquierdo codifica la sangría del
     árbol (0 / 1.1rem / calc(pad + 1.6rem)): no se puede reescribir entero sin
     aplanar la jerarquía. Solo se suben arriba y abajo, que son los 8px que hacían
     que dos permisos distintos parecieran el mismo bloque. */
  .upermrow{padding-top:.6rem!important;padding-bottom:.6rem!important}

  /* flex:none está en el style= del <div>: sin !important el segmento seguiría
     compartiendo renglón con la etiqueta y no habríamos arreglado nada. La base
     100% es justo lo que lo empuja abajo. No hace falta tocar el display: un
     inline-flex que es hijo de flex ya se blockifica solo. */
  .upermrow .upermseg{flex:1 1 100%!important}

  /* Cada opción a un tercio del ancho (un cuarto en las sub-pestañas, que llevan
     'Heredar') y con la altura táctil de piso. Antes eran tres zonas de ~25px sin
     más frontera que 1px de línea: el dedo no distinguía "Ver" de "Ver y hacer". */
  .upermrow .upermseg>span{
    flex:1;min-height:var(--tap);
    display:flex;align-items:center;justify-content:center;
    text-align:center;line-height:1.15;
    /* REVISIÓN · el !important es obligatorio: cada <span> trae font-size en su
       style= inline (config.js:1595 .76rem / :1708 .7rem) y sin él estas dos
       declaraciones eran letra muerta — el inline normal vence a la hoja de autor
       normal. flex / min-height / display sí entraban porque no están inline. */
    font-size:.8rem!important;
  }
  /* Las sub-pestañas reparten el mismo ancho entre 4: 'Sin acceso' necesita bajar
     un punto para no partirse en tres renglones. Mismo motivo para el !important:
     además, sin él la regla de arriba (ya con !important) las subiría a .8rem. */
  .upermrow .upermseg.sub>span{font-size:.72rem!important}
}


/* ═══════════ TANDA 2-3 · ptable.css ═══════════ */
/* ════════════════════════════════════════════════════════════════════════════════
   TANDA 1 · admin-css-extra — parches que PISAN a admin.css (este fragmento se
   concatena al final, así que gana los empates de especificidad por orden).
   ════════════════════════════════════════════════════════════════════════════════ */

/* ── Token: alto real de .cfghead ──────────────────────────────────────────────
   admin.css:341/343 y :287 posicionan barras sticky con top:63px / top:1.5rem,
   números escritos a ojo que no corresponden a nada medible. .cfghead (admin.css:282)
   mide: padding 1rem arriba + 1rem abajo (32px) + el hijo más alto, que es .cfgx
   (38px, box-sizing:border-box por admin.css:2) + 1px de border-bottom = 71px.
   El <h2> a 1.25rem no manda: su caja de línea es ~24px, más baja que el botón.
   Se declara como token para que el día que cambie el padding o el tamaño de .cfgx
   se corrija en UN lugar y no en tres tops mágicos regados. */
:root{ --cfgheadH:71px; }

/* En móvil TANDA 1 le suma DOS cosas al alto de .cfghead, no una:
     · admin.css:991  .cfghead{padding-top:calc(1rem + var(--sat))}  → el notch.
     · admin.css:1040 .cfgx{width:var(--tap);height:var(--tap)}      → el botón ✕
       pasa de 38px a 44px, y el ✕ ES el hijo más alto: la barra crece 6px.
   O sea abajo de 820 la barra mide 16 (padding-top) + var(--sat) + 44 (.cfgx) +
   16 (padding-bottom) + 1 (borde) = 77px + notch, NO 71px + notch.
   Medido en Chromium a 390px: .cfghead.offsetHeight = 77, .cfgx = 44.
   Hoy el token es inerte (abajo de 820 todas las barras de config son
   position:static), pero un token que miente es una trampa para el siguiente. */
@media(max-width:820px){
  .cfgscreen{ --cfgheadH:calc(77px + var(--sat)); }
}

/* ── FIX 1 · el "top:63px" mágico ──────────────────────────────────────────────
   .cfgscreen es position:fixed;inset:0 y overflow-y:auto (admin.css:281): ES el
   scrollport, y dentro de él .cfghead va sticky en top:0 ocupando los primeros
   71px. Todo lo que se pegue debajo tiene que arrancar en 71, no en 63 ni en 24.
   Síntoma: la nav de Configuración se clavaba a 24px del borde, o sea 47px de ella
   quedaban DEBAJO del encabezado — el rótulo de grupo y media primera entrada
   dejaban de ser clickeables en cuanto bajabas un poco (grave en tablet vertical y
   horizontal, donde la nav sí es sticky; abajo de 820 es static y no se notaba).
   La barra del hub de sucursal perdía 8px por la misma razón.
   VA FUERA DE MEDIA QUERY A PROPÓSITO: el 63px está mal en TODOS los anchos, es la
   misma barra de 71px en escritorio. No rompe nada porque solo baja el punto de
   anclaje de elementos que hoy se meten debajo del encabezado: descubre contenido,
   no lo tapa. Y la nav mide ~290px (7 entradas de CFG_SUBS), muy por debajo de la
   altura útil aun en un iPad apaisado de 768px, así que bajarla 71px no deja
   entradas fuera por abajo. */
.cfgscreen .cfgnav{ top:calc(var(--cfgheadH) + 1.5rem); }   /* +1.5rem = mismo respiro que le da el padding de .cfgwrap sin scroll */
.suchubbar{ top:var(--cfgheadH); }
.cfgscreen .hubtabs{ top:var(--cfgheadH); }
/* Fuera del panel de Configuración no hay .cfghead: lo que tapa es la franja fija
   superior. Hoy todos los .hubtabs nacen dentro de .suchubbar (config.js:133) y ahí
   son static, así que esta regla es preventiva: si alguien reusa .hubtabs en el
   cascarón, que se ancle a la franja real y no al 63 heredado. */
.hubtabs{ top:var(--topH); }

@media(max-width:820px){
  /* ── FIX 2 · Pedidos pierde una celda en la tarjeta móvil ────────────────────
     admin.css:799-805 arma la tarjeta mapeando td:nth-child(2..7), es decir da por
     hecho SIETE celdas. Pero pedFila() (pedidos.js:771-783) inserta la celda
     Sucursal en la posición 4 cuando pedSuc===0 ("Todas las sucursales", que es el
     default): la fila pasa a OCHO y todo se corre un lugar — Sucursal se sentaba en
     el hueco del Pago, Pago en el de la Hora, Tiempo en el del Total y el Total,
     que ya no tenía regla, caía por autoplacement encima de otra celda. En "Todas"
     el importe del pedido se leía pisado o directamente no se leía.
     Se cuenta desde el FINAL (nth-last-child): la cola Pago/Hora/Tiempo/Total es
     idéntica con 7 y con 8 celdas, y las tres primeras (Pedido/Cliente/Estado)
     tampoco se mueven; la única que baila es Sucursal, y se identifica sin ambigüedad
     porque es la 4ª por delante Y la 5ª por detrás (con 7 celdas la 4ª es la 5ª por
     detrás, así que el selector no la agarra).
     La fila de cierre va con grid-row:auto a propósito: dejando que el autoplacement
     le asigne la fila, cae en la 3 cuando no hay Sucursal y en la 4 cuando sí la hay,
     sin necesidad de :has() ni de duplicar el bloque. El grid-row:auto es obligatorio:
     sin él sobrevive el grid-area:3/x del admin.css base y el cálculo se rompe.
     Se re-declaran justify-self/align-self/text-align/font-size en cada celda porque
     el mapeo viejo los repartía por posición: con 8 celdas caían en la celda
     equivocada (Tiempo terminaba alineado a la derecha y el Pago en letra chica). */
  .ptable tr.ptr td:nth-child(4):nth-last-child(5){grid-row:auto;grid-column:1/3;justify-self:start;align-self:end;text-align:left;font-size:.75rem}  /* Sucursal (solo existe con 8 celdas) */
  .ptable tr.ptr td:nth-last-child(4){grid-row:2;grid-column:3;justify-self:end;align-self:auto;text-align:right;font-size:.92rem}                    /* Pago */
  .ptable tr.ptr td:nth-last-child(3){grid-row:auto;grid-column:1;justify-self:start;align-self:end;text-align:left;font-size:.75rem}                 /* Hora / Fecha */
  .ptable tr.ptr td:nth-last-child(2){grid-row:auto;grid-column:2;justify-self:start;align-self:end;text-align:left;font-size:.75rem}                 /* Tiempo */
  .ptable tr.ptr td:nth-last-child(1){grid-row:auto;grid-column:3;justify-self:end;align-self:end;text-align:right}                                   /* Total */
}


/* ═══════════ POST-REVISIÓN (jul-30) · dos correcciones sobre las tandas anteriores ═══════════ */

@media(max-width:820px){
  /* (1) MARGEN DE SEGURIDAD DE LA FRANJA SUPERIOR.
     La Tanda 1 subió a 44px los controles que viven dentro de .topstrip (☰, .btn,
     .hubchip) pero la franja conserva height:var(--topH)=56px RÍGIDO y align-items:center.
     Medido con el markup real: el .topbar queda en 50px de 56, o sea 3px de aire por lado.
     Eso funciona hoy y falla en silencio mañana: basta que un chip crezme unos píxeles para
     que el contenido, al estar centrado, se salga por ARRIBA del borde de la pantalla — que
     es EXACTAMENTE el defecto que la Tanda 1 vino a matar (el botón "+ Producto" se medía
     en y=-70px). Se sube --topH a 62px solo en móvil: .topstrip y el padding-top de
     .shellbody lo leen los dos de la variable, así que se mueven juntos y no hay forma de
     que se desincronicen. Cuesta 6px de alto útil; compra que el defecto no pueda volver. */
  :root{--topH:62px}
}

/* (2) La Tanda 2 dejó el ancla sticky de Configuración amarrada al token --cfgheadH.
   Ese token es un alto MEDIDO de .cfghead (padding + el hijo más alto, que es .cfgx).
   Si alguien cambia el padding de .cfghead o el tamaño de .cfgx, hay que actualizar el
   token — NO los tops. Queda anotado aquí porque es la trampa obvia para el siguiente
   que toque esa cabecera. config.js:138 (hubOffset) mide con offsetHeight y se ajusta solo. */


/* ═══════════ AJUSTES MÓVIL pedidos por Ronel (jul-30) ═══════════
   Tres cosas que se vieron mal en el iPhone la primera vez que se abrió:
   la luna encima del nombre de la sucursal, los logos de marca recortados,
   y el selector de sucursal como tira de chips que no cabía. ═══════════ */

@media(max-width:820px){

  /* (El interruptor de tema se movió FUERA de esta media query: ahora vive en la barra
     lateral en TODOS los anchos. Su bloque está al final del archivo.) */

  /* ── 2 · LOS LOGOS DE MARCA DEJAN DE VERSE RECORTADOS ──────────────────────
     Dos culpas encimadas. La vieja: admin.css:506 fuerza aspect-ratio:3.4/1 con
     object-fit:cover, o sea RECORTA el logo a una franja — por eso "Barapasta"
     salía comido. La mía: la TANDA 1 puso #brandMarcaLogos{max-width:96px;
     overflow:hidden} para recuperar ancho en la franja, y eso cortaba el segundo
     logo a la mitad. Ahora contain (se ve completo, nunca se recorta) y cada chip
     más chico; el ancho que hacía falta lo devuelve el punto 3, que convierte una
     tira de chips en un solo botón. */
  #brandMarcaLogos{max-width:none;overflow:visible;gap:.28rem}
  #brandMarcaLogos .sclogo{min-width:0;max-width:82px;height:28px;padding:2px 5px;border-radius:7px}
  #brandMarcaLogos .sclogo img{aspect-ratio:auto;object-fit:contain;max-width:100%}
  #brandMarcaLogos .sclogo-ph{min-width:26px;padding:0 8px;font-size:.8rem}

  /* ── 3 · SUCURSAL: UN BOTÓN, NO UNA TIRA ───────────────────────────────────
     El markup lo pinta renderSucSwitch() (catalogo.js) cuando el ancho es <=820.
     Con 2 sucursales la tira ya se cortaba contra el borde y a la segunda solo se
     llegaba con un scroll horizontal sin barra visible: nadie lo descubría. */
  .sucbtn{
    display:inline-flex;align-items:center;gap:.15rem;
    min-height:var(--tap);max-width:46vw;
    padding:.35rem .6rem;border:1px solid var(--line);border-radius:11px;
    background:var(--card);color:var(--ink);font-weight:700;font-size:.9rem;
    cursor:pointer;white-space:nowrap;
  }
  .sucbtn:active{background:var(--soft)}
  /* min-width:0 + ellipsis: un nombre largo encoge en vez de empujar la franja. */
  .sucbtn-t{overflow:hidden;text-overflow:ellipsis;min-width:0}
  .sucbtn-c{color:var(--mut);font-size:.78rem;flex:none;margin-left:.1rem}
}

/* La hoja se estila FUERA de media query: solo la dibuja renderSucSwitch en
   celular, así que en escritorio nunca existe y no hay nada que aislar. */
.sucsheet{
  background:var(--card);width:100%;
  border-radius:18px 18px 0 0;
  box-shadow:0 -14px 40px rgba(0,0,0,.28);
  display:flex;flex-direction:column;
  max-height:min(72dvh,560px);
  padding-bottom:var(--sab,0px);   /* la barra de gestos del iPhone se come el último renglón */
}
.sucsheet-h{display:flex;align-items:center;justify-content:space-between;padding:.9rem 1rem .6rem;border-bottom:1px solid var(--line)}
.sucsheet-h b{font-size:1.02rem}
.sucsheet-b{overflow-y:auto;overscroll-behavior:contain;padding:.4rem .6rem .8rem}
.sucopt{
  display:flex;align-items:center;gap:.7rem;width:100%;
  min-height:52px;padding:.5rem .7rem;margin:.15rem 0;
  border:none;background:none;border-radius:12px;
  font-size:1rem;color:var(--ink);text-align:left;cursor:pointer;
}
.sucopt:active{background:var(--soft)}
.sucopt.on{background:var(--wash);font-weight:800}
.sucopt-i{font-size:1.15rem;width:1.6rem;text-align:center;flex:none}
.sucopt-t{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sucopt-k{color:var(--accent);font-weight:800;flex:none;width:1.2rem;text-align:right}



/* ═══════════ INTERRUPTOR DE TEMA EN LA BARRA LATERAL (jul-30) ═══════════
   En TODOS los anchos, no solo en celular. Antes era un círculo flotante en
   top:11px/right:33px: en el iPhone caía encima del selector de sucursal y le robaba
   el toque, y en escritorio era un botón huérfano flotando sobre la franja, sin
   relación visual con el menú al que pertenece. index.php lo inserta en
   #sideThemeSlot (debajo de Configuración) y le pone .themetgl-side.

   Fuera de media query A PROPÓSITO: la posición ya no depende del ancho, depende de
   si la página TIENE barra lateral. errores.php, kds.php y voces.php no la tienen y
   conservan su propio botón flotante — esas reglas no los alcanzan porque no cargan
   admin.css y porque el JS solo pone .themetgl-side cuando encuentra la ranura.

   CONSECUENCIA ACEPTADA: con el menú plegado (body.sbhide) el botón no se ve. Se
   llega con un toque en ☰. Si algún día estorba, la salida es duplicarlo en la
   franja superior, NO devolverlo a flotante. */
.themetgl.themetgl-side{
  position:static;width:100%;height:auto;min-height:44px;
  border-radius:10px;border:1px solid var(--line);
  justify-content:flex-start;gap:.6rem;
  padding:.55rem .7rem;margin:.15rem 0 0;
  font-size:.95rem;font-weight:600;color:var(--ink-mid);
  box-shadow:none;
}
.themetgl.themetgl-side:hover{transform:none;background:var(--hover,var(--soft))}
.themetgl.themetgl-side:active{transform:none}
.themetgl.themetgl-side .tgic{font-size:1.05rem;width:1.4rem;text-align:center;flex:none}
.themetgl.themetgl-side .tglab{white-space:nowrap}
/* #sideThemeSlot vive dentro de <nav>, que es flex column: sin flex:none el botón se
   estira a toda la altura sobrante del nav. */
#sideThemeSlot{display:flex;flex-direction:column;flex:none}
