/* ═══════════════════════════════════════════════════════════════
   CHRONOS · stylesheet

   Lifted out of a 1,196-line <style> block inside index.html. It is the
   same CSS, without a rule changed: it moved so that the markup can be
   read, and so the browser can cache it apart from the HTML, which
   changes on every deploy.

   Order matters, and that is why it has not been split into several
   files yet: some specificity depends on which rule comes after which.
   ═══════════════════════════════════════════════════════════════ */

  :root{
    /* NIEBLA · a cool grey base and a graphite ink, and colour carried
       by tone rather than hue. The obra states keep their token names
       (they are wired through the whole sheet) and go quiet: En obra is
       a steel grey, Revisión a lavender grey, Aprobado a moss grey, Por
       iniciar plain grey. `--amber` therefore means "the En obra hue",
       not the colour amber. Only red stays a colour: it warns. */
    --bg:#F3F4F5;
    --glow-a:rgba(31,33,36,.03); --glow-b:rgba(31,33,36,.03); --glow-c:rgba(31,33,36,.02);
    --glass:rgba(255,255,255,.64); --glass-strong:rgba(255,255,255,.92);
    --card:rgba(255,255,255,.82); --card-solid:#FFFFFF;
    --edge:rgba(31,33,36,.08); --line:rgba(31,33,36,.09); --line-strong:rgba(31,33,36,.18);
    --ink:#1F2124; --ink-soft:#3D4147; --muted:#7C8187; --faint:#A4A8AD;
    --black:#1F2124; --on-black:#F3F4F5;
    /* the primary call to action; it is the ink colour everywhere except
       in a theme that gives it a colour of its own */
    --cta:var(--black); --on-cta:var(--on-black);
    /* the activity chart's two series and the wash under the evidence
       line, and the fill of progress bars: the state hues and the ink
       unless a theme says otherwise */
    --chart-ev:var(--amber); --chart-ap:var(--violet); --chart-wash:transparent; --progress:var(--ink);
    --amber:#7A8A9C; --amber-ink:#4C5A6B; --amber-soft:rgba(76,90,107,.12);
    --violet:#8B84A6; --violet-ink:#5E5872; --violet-soft:rgba(94,88,114,.12);
    --green:#6E8A78; --green-ink:#476152; --green-soft:rgba(71,97,82,.12);
    --gray-acc:#9A9FA5; --gray-ink:#6A7076; --gray-soft:rgba(31,33,36,.05);
    --red:#C25A4A; --red-ink:#9A4234; --red-soft:rgba(194,90,74,.11);
    --wave:rgba(31,33,36,.12); --wave-hi:rgba(31,33,36,.55);
    --shadow:0 1px 2px rgba(31,33,36,.03),0 10px 30px rgba(31,33,36,.05);
    --shadow-lift:0 4px 12px rgba(31,33,36,.07),0 24px 60px rgba(31,33,36,.14);
    --overlay:rgba(31,33,36,.38);
    --blur:saturate(1.4) blur(20px);
    /* frosted glass for the schedule's fixed column. A heavier blur
       than --blur because this pane has to make the bars sliding
       underneath unreadable, not merely soft. The highlight is a token
       because it FLIPS: white light on a pale surface, and a whisper of
       it in the dark. */
    --blur-col:saturate(1.7) blur(22px);
    --gloss:rgba(255,255,255,.72);
    --gloss-edge:rgba(255,255,255,.35);
  }
  /* THE SYSTEM'S DARK, and whom it does NOT apply to. Any theme with a
     name of its own has to be excluded here: without its `:not(...)`,
     choosing it on a Mac in dark mode painted that theme and then let
     every dark variable fall on top of it. */
  @media (prefers-color-scheme: dark){
    :root:not([data-theme="light"]):not([data-theme="concreto"]){
      --bg:#141618;
      --glow-a:rgba(255,255,255,.03); --glow-b:rgba(255,255,255,.03); --glow-c:rgba(255,255,255,.02);
      --glass:rgba(30,32,35,.55); --glass-strong:rgba(34,36,40,.92);
      --card:rgba(38,40,44,.6); --card-solid:#222428;
      --edge:rgba(255,255,255,.08); --line:rgba(255,255,255,.08); --line-strong:rgba(255,255,255,.16);
      --ink:#E9EAEC; --ink-soft:#C5C8CC; --muted:#8D9298; --faint:#5F646A;
      --black:#E9EAEC; --on-black:#141618;
      --amber:#9AAABB; --amber-ink:#B9C6D3; --amber-soft:rgba(154,170,187,.16);
      --violet:#A9A2C4; --violet-ink:#C3BDDA; --violet-soft:rgba(169,162,196,.16);
      --green:#8FAA9A; --green-ink:#AFC8B9; --green-soft:rgba(143,170,154,.16);
      --gray-acc:#7F858C; --gray-ink:#A6ABB1; --gray-soft:rgba(255,255,255,.06);
      --red:#D9776A; --red-ink:#E8A095; --red-soft:rgba(217,119,106,.16);
      --wave:rgba(255,255,255,.13); --wave-hi:rgba(255,255,255,.55);
      --shadow:0 1px 2px rgba(0,0,0,.3),0 10px 30px rgba(0,0,0,.3);
      --shadow-lift:0 4px 12px rgba(0,0,0,.4),0 24px 60px rgba(0,0,0,.55);
      --overlay:rgba(0,0,0,.5);
      --gloss:rgba(255,255,255,.10);
      --gloss-edge:rgba(255,255,255,.06);
    }
  }
  :root[data-theme="dark"]{
    --bg:#141618;
    --glow-a:rgba(255,255,255,.03); --glow-b:rgba(255,255,255,.03); --glow-c:rgba(255,255,255,.02);
    --glass:rgba(30,32,35,.55); --glass-strong:rgba(34,36,40,.92);
    --card:rgba(38,40,44,.6); --card-solid:#222428;
    --edge:rgba(255,255,255,.08); --line:rgba(255,255,255,.08); --line-strong:rgba(255,255,255,.16);
    --ink:#E9EAEC; --ink-soft:#C5C8CC; --muted:#8D9298; --faint:#5F646A;
    --black:#E9EAEC; --on-black:#141618;
    --amber:#9AAABB; --amber-ink:#B9C6D3; --amber-soft:rgba(154,170,187,.16);
    --violet:#A9A2C4; --violet-ink:#C3BDDA; --violet-soft:rgba(169,162,196,.16);
    --green:#8FAA9A; --green-ink:#AFC8B9; --green-soft:rgba(143,170,154,.16);
    --gray-acc:#7F858C; --gray-ink:#A6ABB1; --gray-soft:rgba(255,255,255,.06);
    --red:#D9776A; --red-ink:#E8A095; --red-soft:rgba(217,119,106,.16);
    --wave:rgba(255,255,255,.13); --wave-hi:rgba(255,255,255,.55);
    --shadow:0 1px 2px rgba(0,0,0,.3),0 10px 30px rgba(0,0,0,.3);
    --shadow-lift:0 4px 12px rgba(0,0,0,.4),0 24px 60px rgba(0,0,0,.55);
    --overlay:rgba(0,0,0,.5);
    --gloss:rgba(255,255,255,.10);
    --gloss-edge:rgba(255,255,255,.06);
  }

  /* CONCRETO · Punto Paralelo's brand. The neutral greys of the palette
     (#313131 · #595959 · #929292 · #e5e5e5) carry everything, and the
     brand's sage (#6b7a6f) is the one accent: the primary action and
     approved work. Revisión borrows the pale sage (#a6bab4). Red stays
     red, because it warns. Light only: the system's dark does not apply
     to it (see the `:not(...)` above). */
  :root[data-theme="concreto"]{
    --bg:#F2F2F2;
    --glow-a:rgba(49,49,49,.02); --glow-b:rgba(49,49,49,.02); --glow-c:rgba(49,49,49,.015);
    --glass:rgba(255,255,255,.7); --glass-strong:rgba(255,255,255,.94);
    /* frosted: the cards let the page's fade show through (see the
       CONCRETO · the fade section at the end of the sheet) */
    --card:rgba(255,255,255,.58); --card-solid:#FFFFFF;
    --edge:rgba(49,49,49,.08); --line:rgba(49,49,49,.09); --line-strong:rgba(49,49,49,.18);
    --ink:#313131; --ink-soft:#595959; --muted:#767676; --faint:#A3A3A3;
    /* NO BLACK IN THE PUNTO PARALELO THEME (2026-10-08): what other
       themes fill in near-black — the costs tile, active pills, selected
       chips, badges, my own messages — takes the brand's stone, #E3DED1,
       with the ink on top */
    --black:#E3DED1; --on-black:#313131;
    --cta:#6B7A6F; --on-cta:#FFFFFF;
    --chart-ev:#6B7A6F; --chart-ap:#B9A77E; --chart-wash:rgba(107,122,111,.14); --progress:#6B7A6F;
    --amber:#595959; --amber-ink:#474747; --amber-soft:rgba(89,89,89,.10);
    --violet:#A6BAB4; --violet-ink:#56675F; --violet-soft:rgba(166,186,180,.24);
    --green:#6B7A6F; --green-ink:#4E5C52; --green-soft:rgba(107,122,111,.15);
    --gray-acc:#929292; --gray-ink:#595959; --gray-soft:rgba(49,49,49,.05);
    --wave:rgba(49,49,49,.12); --wave-hi:rgba(49,49,49,.55);
    --shadow:0 1px 2px rgba(49,49,49,.03),0 10px 30px rgba(49,49,49,.05);
    --shadow-lift:0 4px 12px rgba(49,49,49,.07),0 24px 60px rgba(49,49,49,.14);
    --overlay:rgba(49,49,49,.38);
  }

  *{box-sizing:border-box;margin:0;padding:0}
  [hidden]{display:none!important}
  html{height:100%}
  body{
    min-height:100%;
    background:var(--bg); color:var(--ink);
    font-family:"Plus Jakarta Sans",system-ui,-apple-system,"Segoe UI",sans-serif;
    font-size:13.5px; line-height:1.5;
    -webkit-font-smoothing:antialiased;
  }
  body::before{
    content:"";position:fixed;inset:0;z-index:-1;pointer-events:none;
    background:
      radial-gradient(640px 420px at 86% -4%, var(--glow-a), transparent 65%),
      radial-gradient(760px 520px at -6% 34%, var(--glow-b), transparent 65%),
      radial-gradient(700px 480px at 60% 108%, var(--glow-c), transparent 65%);
  }
  button{font:inherit;color:inherit;background:none;border:none;cursor:pointer}
  /* El foco se marcaba con una línea blanca de 2px: en oscuro es un
     recuadro que grita y no pertenece a nada de lo que hay alrededor.
     Ahora es un halo —una sombra difusa del mismo tono de la tinta—
     que se lee igual de bien y pesa lo que pesa el resto. */
  button:focus-visible,input:focus-visible,[tabindex]:focus-visible{
    outline:none;border-radius:10px;
    box-shadow:0 0 0 3px color-mix(in srgb, var(--ink) 16%, transparent), 0 2px 10px -4px rgba(0,0,0,.35);
  }

  .wrap{padding:0}

  .glass{
    background:var(--glass);
    -webkit-backdrop-filter:var(--blur);backdrop-filter:var(--blur);
    border:1px solid var(--edge);box-shadow:var(--shadow);
  }
  /* ───────── the panel ─────────
     The white surface a view uses to hold a unit of information: a
     Resumen card, an area's photos, a pending signature, the month, the
     team list. ONE definition — `.card` and `.panel` are the same rule —
     so every screen frames its content the same way. Avisos had it,
     Evidencias separated its groups with a hairline, Equipo re-declared
     it by hand, and the screens read as three products. A panel is a
     surface, not a button: whoever needs hover motion adds it. */
  .card,.panel{
    background:var(--card);
    border:1px solid var(--edge);border-radius:20px;box-shadow:var(--shadow);
  }
  .panel.tight{border-radius:16px}

  /* ───────── left rail nav (glass) ───────── */
  .shell{display:flex;align-items:flex-start}
  .sidenav{
    position:sticky;top:14px;height:calc(100vh - 28px);width:68px;flex:none;z-index:30;
    margin:14px 0 14px 14px;
    background:color-mix(in srgb, var(--card-solid) 30%, transparent);
    -webkit-backdrop-filter:var(--blur);backdrop-filter:var(--blur);
    border:1px solid var(--edge);border-radius:22px;box-shadow:var(--shadow);
    padding:14px 0 14px;display:flex;flex-direction:column;align-items:center;gap:6px;
  }
  .brand{display:flex;padding:0 0 12px}
  .brand .bt{display:none}
  /* Punto Paralelo's mark as the brand draws it: light grey (#E5E5E5)
     on its grey tile (#929292) at the door and on the browser tab
     (index.html), and in the menu except in PP (below). The shapes are
     traced from the brand's own file; only the framing is tighter. */
  .logo{
    width:38px;height:38px;border-radius:12px;background:#929292;color:#E5E5E5;
    display:flex;align-items:center;justify-content:center;flex:none;overflow:hidden;
  }
  .logo svg{width:100%;height:100%;display:block}
  /* except the menu's tile in PP, which keeps the brand's sage */
  :root[data-theme="concreto"] .sidenav .logo{background:#6B7A6F;color:#FFFFFF;box-shadow:inset 0 0 0 1px rgba(255,255,255,.28)}
  .sn-label{display:none}
  .nav-pills{display:flex;flex-direction:column;gap:6px;align-items:center}
  .nav-pill{
    width:44px;height:44px;justify-content:center;padding:0;border-radius:13px;
    display:flex;align-items:center;color:var(--muted);
  }
  .nav-pill .lbl{display:none}
  .nav-pill svg{width:18px;height:18px;flex:none}
  .nav-pill.active{
    background:var(--card-solid);color:var(--ink);border:1px solid var(--edge);
    box-shadow:var(--shadow-lift);
  }
  :root[data-theme="dark"] .nav-pills > .glide{box-shadow:0 1px 2px rgba(0,0,0,.35),0 8px 20px rgba(0,0,0,.5)}
  @media (prefers-color-scheme: dark){
    :root:not([data-theme="light"]):not([data-theme="concreto"]) .nav-pills > .glide{box-shadow:0 1px 2px rgba(0,0,0,.35),0 8px 20px rgba(0,0,0,.5)}
  }
  .nav-pill:not(.active):hover{color:var(--ink);background:var(--gray-soft)}
  /* El reporte va con el menú, pero no es una página: un filete lo
     separa de las cinco que sí lo son, y nunca se queda marcado. */
  .nav-pill.accion{position:relative;margin-top:7px}
  .nav-pill.accion::before{content:"";position:absolute;top:-8px;left:10px;right:10px;height:1px;background:var(--line)}
  .sn-spacer{flex:1}
  .sn-icons{display:flex;flex-direction:column;gap:4px;align-items:center}
  .sidenav .icon-btn{
    background:none;border:none;box-shadow:none;color:var(--muted);
    width:44px;height:44px;border-radius:13px;
  }
  .sidenav .icon-btn:hover{color:var(--ink);background:var(--gray-soft)}
  .sidenav .icon-btn.active{
    background:var(--card-solid);color:var(--ink);border:1px solid var(--edge);
    box-shadow:var(--shadow-lift);
  }
  .sidenav .icon-btn .dot{border-color:var(--card-solid);top:10px;right:11px}
  .sn-user{display:flex;justify-content:center;padding:12px 0 0;border-top:1px solid var(--line);margin-top:10px;width:38px}
  .sn-user .pavatar{box-shadow:var(--shadow)}
  .content{flex:1;min-width:0;padding:20px 28px 60px}
  .content .page > .hero:first-child{margin-top:8px}

  /* ───────── mobile bottom dock ───────── */
  .mobiledock{
    display:none;position:fixed;left:50%;transform:translateX(-50%);bottom:14px;z-index:35;
    background:color-mix(in srgb, var(--card-solid) 45%, transparent);
    -webkit-backdrop-filter:var(--blur);backdrop-filter:var(--blur);
    border:1px solid var(--edge);border-radius:22px;box-shadow:var(--shadow-lift);
    padding:7px;gap:2px;
  }
  .mdock-btn{
    position:relative;
    display:flex;align-items:center;justify-content:center;
    width:48px;height:44px;border-radius:15px;
    color:var(--muted);font-size:0;
    transition:transform 160ms var(--eo), background-color 150ms ease, color 150ms ease, box-shadow 150ms ease;
  }
  .mdock-btn:active{transform:scale(.94)}
  .mdock-btn svg{width:20px;height:20px}
  .mdock-btn.active{
    background:var(--card-solid);color:var(--ink);
    box-shadow:var(--shadow-lift);
  }
  .mdock-btn .badge{
    position:absolute;top:4px;right:5px;min-width:16px;height:16px;padding:0 4px;border-radius:8px;
    background:var(--red);color:#fff;font-size:9.5px;font-weight:800;line-height:1;
    display:inline-flex;align-items:center;justify-content:center;
    border:1.5px solid var(--card-solid);font-variant-numeric:tabular-nums;
  }
  @media (max-width:760px){
    .sidenav{display:none}
    .mobiledock{display:flex}
    .content{padding:14px 14px 104px}
    .toast{bottom:150px}
    .hero-actions .h-btn{padding:9px 13px;font-size:12px}
  }
  /* ───────── the phone's agenda (ui/timeline.js › agendaHTML) ───────── */
  .tl-inner.agenda{width:100%;min-width:0;padding:6px 0 4px}
  /* rows sized for a thumb: at least 64px tall, the title at 14.5px and
     the track thick enough to read at arm's length */
  /* «Fotos de hoy»: one tile per area, missing ones first; a tap opens
     the camera for that area. Thumb-sized: 2 columns, 92px tall. */
  .ag-hoy,.ag-hist{padding:14px 14px 4px}
  .ag-hoy header,.ag-hist header{display:flex;align-items:baseline;justify-content:space-between;gap:10px;margin:0 2px 10px}
  .ag-hoy header b{font-size:16px;font-weight:800;letter-spacing:-.01em}
  .ag-hist header b{font-size:10.5px;font-weight:800;letter-spacing:.08em;text-transform:uppercase;color:var(--muted)}
  .ag-hoy header span,.ag-hist header span{font-size:11.5px;font-weight:600;color:var(--muted);text-align:right}
  .ag-mosaico{display:grid;grid-template-columns:1fr 1fr;gap:10px}
  .ag-tile{
    min-height:96px;padding:12px;border-radius:16px;display:flex;flex-direction:column;justify-content:space-between;gap:10px;
    text-align:left;background:var(--card-solid);border:1px solid var(--edge);box-shadow:var(--shadow);color:var(--ink);
    transition:transform 120ms ease,background 120ms ease;
  }
  button.ag-tile:active{transform:scale(.97)}
  .ag-ico{width:42px;height:42px;border-radius:13px;display:grid;place-items:center;background:var(--cta);color:var(--on-cta)}
  .ag-ico svg{width:20px;height:20px}
  .ag-tile.hecha .ag-ico{background:var(--green-soft);color:var(--green-ink)}
  .ag-tx{display:flex;flex-direction:column;gap:3px;min-width:0}
  .ag-tx b{display:flex;align-items:center;gap:6px;font-size:13px;font-weight:700;line-height:1.25;overflow-wrap:anywhere}
  .ag-tx b i{width:7px;height:7px;border-radius:50%;flex:none}
  .ag-falta{font-size:11.5px;font-weight:700;color:var(--red-ink)}
  .ag-ok{font-size:11.5px;font-weight:700;color:var(--green-ink)}
  /* the last ten working days per area */
  .ag-hist{padding-top:18px;padding-bottom:12px}
  .ag-hist-a{padding:10px 2px 12px;border-top:1px solid var(--line)}
  .ag-hist-a:first-of-type{border-top:none}
  .ag-hist-h{display:flex;align-items:center;gap:8px;margin-bottom:8px}
  .ag-hist-h b{flex:1;min-width:0;font-size:12.5px;font-weight:700;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .ag-hist-h span{font-size:11px;font-weight:600;color:var(--muted);flex:none}
  .ag-log{width:36px;height:36px;margin:-6px -4px -6px 0;border-radius:10px;display:grid;place-items:center;color:var(--muted);flex:none}
  .ag-log svg{width:16px;height:16px}
  .ag-log:active{background:var(--gray-soft);color:var(--ink)}
  /* ten circles, one per working day: filled in the area's tone where
     there was evidence, today ringed */
  .ag-tira{display:grid;grid-template-columns:repeat(10,1fr);gap:4px;justify-items:center}
  .ag-dia{position:relative;width:100%;max-width:28px;aspect-ratio:1;border-radius:50%;background:var(--gray-soft);border:1px solid var(--line)}
  .ag-dia.fuera{opacity:.35}
  .ag-dia.con{background:var(--tono);border-color:transparent}
  .ag-dia.hoy{outline:1.5px solid var(--ink);outline-offset:2px}
  /* ── an area's state (ui/tl-estado.js, 0042) ── */
  .tl-area-meta{display:flex;align-items:center;flex-wrap:wrap;gap:4px 6px;margin-top:3px}
  .tl-area .nm .tl-area-meta small{display:inline;margin:0}
  .tl-estado{
    display:inline-flex;align-items:center;gap:4px;height:18px;padding:0 8px;border-radius:99px;
    font-size:10px;font-weight:700;white-space:nowrap;flex:none;
  }
  button.tl-estado{cursor:pointer;transition:filter 120ms ease}
  button.tl-estado::after{content:"";width:0;height:0;margin-left:1px;border:3px solid transparent;border-top:4px solid currentColor;transform:translateY(2px);opacity:.6}
  button.tl-estado:hover{filter:brightness(.96)}
  .tl-estado.e-obra{background:var(--green-soft);color:var(--green-ink)}
  .tl-estado.e-lista{background:#FFF1D6;color:#7A5200}
  .tl-estado.e-terminada{background:#0A0A0A;color:#FFFFFF}
  .tl-estado-menu{
    position:fixed;z-index:80;min-width:200px;padding:5px;border-radius:12px;display:flex;flex-direction:column;
    background:var(--glass-strong);-webkit-backdrop-filter:var(--blur);backdrop-filter:var(--blur);
    border:1px solid var(--edge);box-shadow:var(--shadow-lift);animation:tl-pop-in 140ms var(--eo);
  }
  .tl-estado-menu button{text-align:left;padding:9px 11px;border-radius:8px;font-size:12px;font-weight:600;color:var(--ink)}
  .tl-estado-menu button:hover{background:var(--gray-soft)}
  .tl-estado-menu button.fuerte{font-weight:800}
  /* a finished area's bar: quieter, closed by a black cap */
  .bar-area.terminada .dd-tramo{filter:saturate(.6) opacity(.62)}
  .dd-fin{
    position:absolute;right:-6px;top:50%;transform:translateY(-50%);z-index:3;height:24px;padding:0 10px;border-radius:99px;
    display:flex;align-items:center;font-size:10px;font-weight:800;white-space:nowrap;
    background:#0A0A0A;color:#FFFFFF;box-shadow:0 0 0 2px var(--card-solid);pointer-events:none;
  }
  .ag-hist-h .tl-estado{margin-right:auto}
  .ag-term{display:inline-flex;align-self:flex-start;margin-top:4px;padding:2px 8px;border-radius:99px;font-size:10px;font-weight:800;background:#0A0A0A;color:#FFFFFF}
  /* the client's «Últimas fotos»: each area's latest photo as a tile */
  .ag-ult{
    position:relative;min-height:132px;border-radius:16px;overflow:hidden;display:flex;align-items:flex-end;
    text-align:left;color:#FFFFFF;background:var(--gray-soft);box-shadow:var(--shadow);
  }
  .ag-ult img,.ag-ult video{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
  .ag-ult::after{content:"";position:absolute;inset:0;background:linear-gradient(180deg,transparent 40%,rgba(10,10,10,.68))}
  .ag-ult .ag-tx{position:relative;z-index:1;padding:10px 11px}
  .ag-ult .ag-tx b{color:#FFFFFF;font-size:12.5px}
  .ag-ult .ag-tx b i{box-shadow:0 0 0 1px rgba(255,255,255,.6)}
  .ag-cuando{font-size:11px;font-weight:600;opacity:.9}
  button.ag-ult:active{transform:scale(.97)}
  .ag-ult.vacia{color:var(--ink);background:var(--card-solid);border:1px dashed var(--line-strong);box-shadow:none}
  .ag-ult.vacia::after{display:none}
  .ag-ult.vacia .ag-tx b{color:var(--ink)}
  .ag-ult.vacia .ag-cuando{color:var(--muted)}
  /* «Hoy» / «Diario» (ui/tl-agenda.js) */
  .ag-vistas{display:flex;margin:14px 14px 0}
  .ag-vistas button{flex:1;justify-content:center}
  /* «Diario»: the obra as a camera roll (ui/tl-diario.js) */
  .ag-diario{padding:6px 0 14px}
  .ag-dia-d{padding:12px 0 6px}
  .ag-dia-d header{display:flex;align-items:baseline;justify-content:space-between;gap:10px;margin:0 16px 8px}
  .ag-dia-d header b{font-size:13.5px;font-weight:800;letter-spacing:-.01em}
  .ag-dia-d header span{font-size:11px;font-weight:600;color:var(--muted)}
  .ag-fila{display:flex;gap:8px;overflow-x:auto;padding:0 16px 4px;scroll-snap-type:x mandatory;scrollbar-width:none}
  .ag-fila::-webkit-scrollbar{display:none}
  .ag-foto{
    position:relative;flex:none;width:112px;height:112px;border-radius:14px;overflow:hidden;scroll-snap-align:start;
    background:var(--gray-soft);box-shadow:inset 0 0 0 1px var(--line);
  }
  .ag-foto img,.ag-foto video{display:block;width:100%;height:100%;object-fit:cover}
  .ag-foto:active{transform:scale(.97)}
  .ag-foto-a{
    position:absolute;left:6px;right:6px;bottom:6px;display:flex;align-items:center;gap:5px;padding:3px 7px;border-radius:99px;
    font-size:10px;font-weight:700;color:#FFFFFF;background:rgba(10,10,10,.6);
    white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:max-content;
  }
  .ag-foto-a i{width:6px;height:6px;border-radius:50%;flex:none;box-shadow:0 0 0 1px rgba(255,255,255,.6)}
  .ag-hueco{margin:6px 16px 6px 22px;padding:4px 0 4px 12px;border-left:2px dashed var(--line-strong);font-size:11px;font-weight:600;color:var(--faint)}
  .ag-mas{display:block;margin:12px auto 0;padding:10px 16px;border-radius:12px;font-size:12px;font-weight:700;color:var(--ink);background:var(--gray-soft)}
  @media (max-width:760px){.tl-legend-av{display:none}}
  .tl-empty{padding:40px 16px;text-align:center;font-size:12.5px;color:var(--muted);font-weight:600}
  .icon-btn{
    width:38px;height:38px;border-radius:13px;
    background:var(--glass-strong);border:1px solid var(--edge);box-shadow:var(--shadow);
    display:flex;align-items:center;justify-content:center;color:var(--ink-soft);position:relative;
  }
  .icon-btn:hover{color:var(--ink)}
  .icon-btn svg{width:16px;height:16px}
  .icon-btn .dot{position:absolute;top:8px;right:9px;width:6px;height:6px;border-radius:50%;background:var(--red);border:1.5px solid var(--card-solid)}
  /* la campana: un contador, no un punto fijo */
  .icon-btn .badge{
    position:absolute;top:3px;right:3px;min-width:16px;height:16px;padding:0 4px;border-radius:8px;
    background:var(--red);color:#fff;font-size:9.5px;font-weight:800;line-height:1;
    display:inline-flex;align-items:center;justify-content:center;
    border:1.5px solid var(--card-solid);font-variant-numeric:tabular-nums;
  }
  .icon-btn.active{background:var(--black);color:var(--on-black)}
  .pavatar{
    width:36px;height:36px;border-radius:13px;flex:none;position:relative;
    display:flex;align-items:center;justify-content:center;
    font-size:11px;font-weight:800;color:#fff;letter-spacing:.02em;
    border:1px solid var(--edge);box-shadow:var(--shadow);
    background-size:cover;background-position:center;
  }
  /* Con foto, las iniciales siguen ahí debajo — transparentes, no
     borradas. Si el almacén contesta 404 o la red se cae, vuelven a
     verse las letras en vez de quedar un cuadro vacío. */
  /* the photo fills the square: without `cover` a 256px image showed
     only its top-left corner, which for most photos is background */
  .pavatar.con-foto{color:transparent;background-size:cover;background-position:center;background-repeat:no-repeat}
  /* Con foto, NINGUNA línea alrededor. Poner el borde transparente NO
     bastaba: la imagen se dimensiona contra la caja de relleno y el
     COLOR de fondo —el gris de las iniciales, en línea en el marcado—
     se pinta hasta el borde, así que ese 1px transparente enseñaba un
     aro gris claro pegado al retrato. Se quita el borde y la imagen se
     ancla a la caja del borde. Sin foto, las iniciales conservan el
     borde tenue de `--edge`, que ahí sí dibuja el botón. */
  .pavatar.con-foto{border:0;background-origin:border-box;background-clip:border-box}
  .sidenav .pavatar{
    box-shadow:var(--shadow);
    transition:box-shadow 160ms ease, transform 160ms var(--eo);
  }
  .sidenav .pavatar:hover{box-shadow:var(--shadow-lift);transform:translateY(-1px)}

  /* ───────── tu foto, en Configuración ─────────
     El avatar del modal ES el control. Más grande, porque ahí no
     identifica sino que se edita, y con la cámara asomando en la
     esquina para que se vea que se puede tocar — un avatar sin ninguna
     señal es una imagen, no un botón. */
  .cfg .pavatar.foto-btn{
    width:52px;height:52px;border-radius:16px;cursor:pointer;
    font-size:14px;transition:box-shadow 140ms ease,transform 140ms ease;
  }
  .cfg .pavatar .cam{
    position:absolute;right:-4px;bottom:-4px;width:20px;height:20px;border-radius:50%;
    display:flex;align-items:center;justify-content:center;
    background:var(--card-solid);color:var(--ink);border:1px solid var(--edge);
    box-shadow:var(--shadow);
  }
  .cfg .pavatar .cam svg{width:11px;height:11px}
  @media (hover:hover) and (pointer:fine){
    .cfg .pavatar.foto-btn:hover{box-shadow:var(--shadow-lift);transform:translateY(-1px)}
  }
  .cfg .pavatar.foto-btn:focus-visible{outline:none;box-shadow:0 0 0 4px color-mix(in srgb, var(--ink) 16%, transparent)}
  /* mientras sube: la foto se apaga y las iniciales vuelven a asomar,
     que es más honesto que un giro sobre una imagen que ya no es la
     buena */
  .cfg .pavatar.subiendo{opacity:.55;pointer-events:none}
  .cfg .pavatar.subiendo.con-foto{color:#fff}

  /* ───────── hero ───────── */
  .hero{display:flex;align-items:flex-end;justify-content:space-between;gap:20px;margin:30px 4px 6px;flex-wrap:wrap}
  .hero h1{font-size:34px;font-weight:800;letter-spacing:-.03em;line-height:1.1;text-wrap:balance}
  .hero .sub{color:var(--muted);margin-top:6px;font-size:13px}
  .hero .sub b{color:var(--ink);font-weight:700}
  .hero-actions{display:flex;gap:10px;align-items:center;flex-wrap:wrap}
  .h-btn{
    display:flex;align-items:center;gap:8px;padding:10px 16px;border-radius:14px;
    font-weight:700;font-size:12.5px;
    background:var(--glass-strong);border:1px solid var(--edge);box-shadow:var(--shadow);color:var(--ink-soft);
  }
  .h-btn:hover{color:var(--ink)}
  .h-btn svg{width:15px;height:15px}
  .h-btn.cta{background:var(--cta);color:var(--on-cta);border-color:transparent}
  .h-btn.cta:hover{opacity:.88;color:var(--on-cta)}
  /* first paint only: the sparkline grows from its baseline, one bar every
     24ms — the same cadence the Cronograma bars use */

  /* ───────── layout columns ───────── */
  .cols{display:grid;grid-template-columns:minmax(0,1fr) 392px;gap:18px;align-items:start}
  @media (min-width:1700px){.cols{grid-template-columns:minmax(0,1fr) 400px;gap:24px}}
  @media (max-width:1080px){.cols{grid-template-columns:1fr}}
  .maincol{min-width:0;display:flex;flex-direction:column;gap:18px}
  .sidecol{display:flex;flex-direction:column;gap:14px}

  .card-head{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:18px 20px 0;flex-wrap:wrap}
  .card-head h2{font-size:15px;font-weight:800;letter-spacing:-.01em}
  .seg{display:flex;background:var(--gray-soft);border-radius:11px;padding:3px;gap:2px}
  .seg button{
    padding:6px 14px;border-radius:8px;font-weight:700;font-size:11.5px;color:var(--muted);
    transition:background .15s,color .15s;
  }
  .seg button.active{background:var(--black);color:var(--on-black)}

  /* chart */
  .chart-wrap{position:relative;padding:10px 14px 6px}
  .chart-wrap canvas{width:100%;height:230px;display:block}
  .chart-tip{
    position:absolute;transform:translate(-50%,0);
    background:var(--glass-strong);
    border:1px solid var(--edge);border-radius:14px;box-shadow:var(--shadow-lift);
    padding:9px 14px;text-align:center;pointer-events:none;white-space:nowrap;
  }
  .chart-tip .big{font-size:19px;font-weight:800;letter-spacing:-.02em}
  .chart-tip .sm{font-size:10.5px;color:var(--muted);font-weight:600;margin-top:1px}
  .chart-legend{display:flex;gap:16px;padding:0 20px 16px;flex-wrap:wrap}
  .chart-legend span{display:flex;align-items:center;gap:6px;font-size:11px;font-weight:600;color:var(--muted)}
  .chart-legend i{width:14px;height:3px;border-radius:2px}

  /* section head */
  .sec-head{display:flex;align-items:center;justify-content:space-between;gap:14px;margin:6px 4px 0;flex-wrap:wrap}
  .sec-head h2{font-size:15px;font-weight:800;letter-spacing:-.01em}
  .views{display:flex;background:var(--gray-soft);border-radius:12px;padding:3px;gap:2px}
  .views button{
    padding:7px 15px;border-radius:9px;font-weight:700;font-size:12px;color:var(--muted);
    transition:background .15s,color .15s;
  }
  .views button.active{background:var(--black);color:var(--on-black)}
  .board{display:grid;grid-template-columns:repeat(4,minmax(215px,1fr));gap:12px;min-width:900px;align-items:start}
  .col{
    background:var(--glass);
    border:1px solid var(--edge);border-radius:20px;padding:10px;box-shadow:var(--shadow);
  }
  .avatar{
    width:24px;height:24px;border-radius:50%;flex:none;
    display:flex;align-items:center;justify-content:center;
    font-size:9px;font-weight:800;color:#fff;letter-spacing:.03em;
  }
  .chip{
    display:inline-flex;align-items:center;gap:5px;border-radius:99px;
    font-size:10px;font-weight:700;padding:3px 9px;letter-spacing:.01em;
  }
  .chip svg{width:11px;height:11px}
  .chip.warn{background:var(--red-soft);color:var(--red-ink)}
  .chip.ok{background:var(--green-soft);color:var(--green-ink)}
  .chip.rev{background:var(--violet-soft);color:var(--violet-ink)}
  .chip.zero{background:var(--gray-soft);color:var(--faint)}
  @media (prefers-reduced-motion:no-preference){
    @keyframes shake{
      0%,100%{transform:translateX(0)}
      20%{transform:translateX(-6px)}40%{transform:translateX(6px)}
      60%{transform:translateX(-4px)}80%{transform:translateX(4px)}
    }
  }

  /* ───────── timeline ───────── */
  /* ───────── avance de obra ─────────
     A fixed column of areas, a band of months above the row of weeks,
     and one lane per area. The "hoy" line crosses all of it and its
     week is tinted. */
  /* ───────── el avance en la cabecera ─────────
     Ocupa el hueco que había entre el título y los botones — el mismo
     `spacer` vacío que empujaba las dos mitades a los extremos — así
     que la fila no crece: se llena. */
  .tl-head .tl-kpis{flex:1;min-width:190px;max-width:340px;margin:2px 4px 6px auto}
  .tl-prog-h{
    display:flex;align-items:baseline;justify-content:space-between;gap:10px;
    font-size:11px;font-weight:600;color:var(--muted);
  }
  .tl-prog-h b{font-size:17px;font-weight:800;letter-spacing:-.02em;color:var(--ink);font-variant-numeric:tabular-nums}
  /* the track has to read on its own: at 0% it is all there is */
  .tl-prog-bar{
    height:6px;border-radius:99px;background:color-mix(in srgb, var(--ink) 11%, transparent);overflow:hidden;margin-top:5px;
    box-shadow:inset 0 0 0 1px color-mix(in srgb, var(--ink) 6%, transparent);
  }
  .tl-prog-bar i{
    display:block;height:100%;border-radius:99px;background:var(--progress);
    transition:width 420ms var(--eo);
  }
  @media (prefers-reduced-motion:reduce){ .tl-prog-bar i{transition:none} }
  .tl-prog-d{margin-top:5px;font-size:11px;font-weight:600;color:var(--muted)}
  /* the Supervisor's rule strip (index.html .tl-regla, .en-obra) */
  .tl-regla{display:flex;align-items:center;gap:10px;margin:4px 4px 6px;padding:9px 14px;border-radius:12px;background:var(--card);font-size:13px;line-height:1.4;color:var(--ink)}
  .tl-regla svg{width:18px;height:18px;flex:none;color:var(--muted)}
  .tl-regla-sub{color:var(--muted)}
  /* ───────── la fila de controles ─────────
     Una sola fila, y en el orden en que se usan: buscar, acotar, y
     luego mirar. Lo que había en medio era un `<div class="spacer">` —
     un relleno flexible que empujaba las dos mitades a los extremos y
     dejaba un palmo de nada entre ellas, justo donde la búsqueda tenía
     sitio para crecer. Ahora crece ella. */
  .tl-tools{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin:8px 4px 14px}
  /* el separador dice dónde deja de filtrarse y empieza a mirarse */
  .tl-sep{width:1px;height:20px;background:var(--line-strong);flex:none;margin:0 2px}
  .tl-tools .spacer{flex:1}
  /* on a phone the cronograma is an agenda (ui/timeline.js): the
     grid's own controls have nothing to drive there */
  @media (max-width:760px){ #tl-mode,.tl-sep{display:none} }
  /* ON A PHONE: the actions go up by the title as two icon buttons, the
     two dropdowns fold into one filter button beside the search, and the
     toolbar is one row (ui/timeline.js pintaFiltrosMovil). */
  .tl-am,.tl-filtros{
    position:relative;width:40px;height:40px;border-radius:12px;flex:none;
    display:inline-flex;align-items:center;justify-content:center;
    border:1px solid var(--edge);background:var(--glass);color:var(--ink);box-shadow:var(--shadow);
  }
  .tl-am svg,.tl-filtros svg{width:17px;height:17px}
  .tl-am.cta{background:var(--cta);color:var(--on-cta);border-color:transparent}
  /* after the rule above, which sets display for both */
  .tl-acts-m,.tl-filtros{display:none}
  .tl-filtros-n{
    position:absolute;top:-5px;right:-5px;min-width:17px;height:17px;padding:0 4px;border-radius:9px;
    background:var(--black);color:var(--on-black);font-size:10px;font-weight:800;display:grid;place-items:center;
  }
  @media (max-width:760px){
    .tl-head{align-items:flex-start;flex-wrap:wrap}
    .tl-head > div:first-child{flex:1;min-width:0}
    .tl-acts-m{display:flex;gap:8px;flex:none}
    .tl-filtros{display:inline-flex}
    .tl-tools{flex-wrap:nowrap}
    .tl-tools .tl-dd,.tl-tools .spacer,
    .tl-tools > .h-btn[data-act="exportCronograma"],.tl-tools > .plan-only{display:none}
  }
  /* the sheet: chips, two sections, one way out */
  .tl-fs-h{display:flex;align-items:center;justify-content:space-between;margin:0 2px 6px}
  .tl-fs-h b{font-size:15px;font-weight:800;letter-spacing:-.01em}
  .tl-fs-clear{font-size:12.5px;font-weight:700;color:var(--muted);padding:6px 4px}
  .tl-fs-t{font-size:10.5px;font-weight:800;letter-spacing:.08em;text-transform:uppercase;color:var(--muted);margin:14px 2px 8px}
  .tl-fs-chips{display:flex;flex-wrap:wrap;gap:8px}
  .tl-chip{
    display:inline-flex;align-items:center;gap:7px;min-height:38px;padding:0 14px;border-radius:19px;
    border:1px solid var(--line-strong);background:var(--card-solid);color:var(--ink-soft);font-size:12.5px;font-weight:700;
    transition:background 120ms ease,color 120ms ease,border-color 120ms ease;
  }
  .tl-chip i{width:8px;height:8px;border-radius:50%;flex:none}
  .tl-chip.on{background:var(--black);color:var(--on-black);border-color:transparent}
  .tl-fs-ok{width:100%;justify-content:center;height:46px;margin-top:20px}
  .tl-dd .dd-menu{min-width:240px}

  .timeline{overflow-x:auto;border-radius:20px;scroll-behavior:smooth}
  .tl-inner{
    position:relative;width:max-content;min-width:100%;
    background:var(--glass);border:1px solid var(--edge);border-radius:20px;box-shadow:var(--shadow);
    padding:0 0 10px;
  }
  .tl-grid{display:grid;grid-template-columns:240px repeat(var(--tlN,10),var(--tlCol,110px))}
  .tl-grid > *{border-bottom:1px solid color-mix(in srgb, var(--line) 50%, transparent)}
  /* ───────── the fixed column ─────────
     Areas and, once expanded, their activities. It was flat white on a
     flat white grid, separated by one hairline: the thing you read the
     cronograma BY had less presence than the cells it was labelling,
     and on a wide screen the names floated with nothing holding them.

     It is a pane of frosted glass now. Three things make it read as
     one, rather than as a column of cells that happen to share a
     colour —

       the tint    a breath of ink mixed into the card, densest at the
                   outer edge and thinning towards the seam, so the pane
                   has a direction and the names sit on its solid end;
       the frost   a real backdrop blur. This column is sticky ON TOP of
                   the lanes, so bars slide behind it constantly; the
                   blur turns them into a wash of colour instead of
                   shapes with edges. That used to be handled by being
                   opaque, which is why it had to be flat white;
       the seam    a lit inner edge and a short cast shadow to the
                   right, which is what tells the eye the column is in
                   FRONT of the grid and not cut out of it.

     The cast shadow is on every cell rather than on the column (there
     is no column element — they are grid children); each one throws
     only to its right, so stacked they make one continuous edge. */
  .tl-corner,.tl-area{
    position:sticky;left:0;z-index:3;
    background:
      linear-gradient(90deg,
        color-mix(in srgb, var(--ink) 6%, var(--card-solid)),
        color-mix(in srgb, var(--ink) 2%, var(--card-solid)));
    -webkit-backdrop-filter:var(--blur-col);backdrop-filter:var(--blur-col);
    border-right:1px solid var(--edge);
    box-shadow:inset -1px 0 0 var(--gloss-edge), 10px 0 18px -14px var(--wave);
  }
  /* without backdrop-filter the pane must be opaque or the bars read
     through it, so it drops the translucency and keeps the tint */
  @supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
    .tl-corner,.tl-area{
      background:linear-gradient(90deg,
        color-mix(in srgb, var(--ink) 6%, var(--card-solid)),
        var(--card-solid));
    }
  }
  .tl-corner{
    grid-row:1 / span 2;padding:0 18px 12px;border-top-left-radius:20px;
    font-size:9.5px;font-weight:800;letter-spacing:.12em;color:var(--faint);text-transform:uppercase;
    display:flex;align-items:flex-end;
  }
  .tl-month{
    grid-row:1;padding:12px 12px 4px;border-left:1px solid var(--line);border-bottom:none!important;
    font-size:9.5px;font-weight:800;letter-spacing:.12em;color:var(--muted);text-transform:uppercase;
    white-space:nowrap;overflow:hidden;
  }
  .tl-month.first{border-left:none}
  .tl-week{
    grid-row:2;position:relative;padding:6px 4px 12px;text-align:center;
    font-size:9.5px;color:var(--faint);font-weight:600;font-variant-numeric:tabular-nums;
  }
  .tl-week b{display:block;font-size:11px;color:var(--ink-soft);font-weight:800;margin-bottom:1px}
  .tl-week.today b{color:var(--ink)}
  /* both of these are driven by --tlHoy / --tlFrac on .tl-grid, which a
     one-minute tick rewrites (ui/timeline.js). Positioning them in CSS
     off a variable rather than in the markup is what lets the line
     advance through the day without repainting the whole cronograma. */
  /* `em.hoy`, not `.hoy`: the day tick under it is also today's and
     must not inherit the pill (it did, and the clock filled it with a
     second pin) */
  .tl-week em.hoy{
    position:absolute;bottom:-12px;left:calc(var(--tlFrac,0) * 100%);transform:translateX(-50%);z-index:4;
    display:inline-flex;align-items:center;gap:5px;white-space:nowrap;
    font-style:normal;font-size:9.5px;font-weight:800;padding:3px 9px 3px 7px;border-radius:99px;
    background:var(--black);color:var(--on-black);box-shadow:var(--shadow-lift);
    font-variant-numeric:tabular-nums;
  }
  /* the «Hoy» pin stays black in Punto Paralelo, where --black is stone */
  :root[data-theme="concreto"] .tl-week em.hoy{background:#0A0A0A;color:#FFFFFF}
  /* sun by day, moon by night: a small, slow sign of the hour */
  .tl-week .hoy .astro{display:flex;width:11px;height:11px}
  .tl-week .hoy .astro svg{width:11px;height:11px}
  .tl-week .hoy .sol{color:#F2C46D}
  .tl-week .hoy .luna{color:#C9D3E3}
  @media (prefers-reduced-motion:no-preference){
    @keyframes sol-gira{to{transform:rotate(360deg)}}
    @keyframes luna-flota{from{transform:translateY(.4px);opacity:.85}to{transform:translateY(-.6px);opacity:1}}
    .tl-week .hoy .sol svg{animation:sol-gira 48s linear infinite}
    .tl-week .hoy .luna svg{animation:luna-flota 3.2s ease-in-out infinite alternate}
  }
  /* the seven days of the current week, today's marked */
  .tl-week .dias{position:absolute;left:6px;right:6px;bottom:9px;display:flex;justify-content:space-between;font-size:7.5px;font-weight:800;color:var(--faint);letter-spacing:0}
  .tl-week .dias i{font-style:normal;width:9px;text-align:center;opacity:.55}
  .tl-week .dias i.act{opacity:1;color:var(--ink)}
  .tl-week.today{padding-bottom:22px}
  .tl-meses .tl-week .dias{display:none}
  .tl-meses .tl-week{padding:4px 0 10px}
  /* DÍA: each week column carries its seven days — letter over date,
     weekends quieter, today's date filled — and the lanes draw a faint
     line between days. The week's own label stays above them. */
  .tl-dias .tl-week{padding-bottom:6px}
  .tl-7d{display:grid;grid-template-columns:repeat(6,1fr);margin-top:6px}
  .tl-7d i{font-style:normal;display:flex;flex-direction:column;align-items:center;gap:2px;font-size:8.5px;font-weight:700;color:var(--faint)}
  .tl-week .tl-7d i b{display:block;margin:0;font-size:11px;font-weight:700;color:var(--ink-soft);min-width:22px;line-height:18px;border-radius:7px}
  .tl-7d i.fin b{color:var(--faint)}
  .tl-week .tl-7d i.hoy{color:var(--ink)}
  .tl-week .tl-7d i.hoy b{background:var(--black);color:var(--on-black);font-weight:800}
  .tl-dias .tl-week.today{padding-bottom:18px}
  .tl-dias .tl-cell,.tl-dias .tl-cell.today{
    background-image:repeating-linear-gradient(90deg,transparent 0 calc(var(--tlCol) / 6 - 1px),color-mix(in srgb,var(--line) 45%,transparent) calc(var(--tlCol) / 6 - 1px) calc(var(--tlCol) / 6));
  }
  .tl-meses .tl-week span{display:none}
  .tl-meses .tl-week b{font-size:9px}
  .tl-meses .tl-month{padding-left:8px}

  /* the area cell spans the whole row (its background has to cover the
     bars passing underneath), but the button you see and light up is
     always the same size: 52 px centred, even when the row grows to
     several lanes */
  /* The heading fills its row. A collapsed area's row is as tall as its
     packed lanes — three bars, three rows — and the label used to sit in
     a 44px pill floating in the middle of it, so the hover and the open
     chip covered a third of the row and looked like a stray. The button
     stretches to the row now (4px inset), and the pill is the row. */
  .tl-area{grid-column:1;display:flex;align-items:stretch;min-height:52px;padding:4px 6px}
  /* the pill is `.hd`: label and arrow share it, so the open chip and
     the hover wash are one shape and not a chip with a loose box beside */
  .tl-area .hd{flex:1;min-width:0;display:flex;align-items:stretch;border-radius:12px;transition:background 140ms ease,box-shadow 140ms ease}
  .tl-area .tog{
    flex:1;min-width:0;min-height:44px;display:flex;align-items:center;gap:9px;padding:0 8px 0 8px;border-radius:12px;
    text-align:left;font-weight:700;font-size:12.5px;color:var(--ink);
  }
  .tl-area .go{min-height:44px;border-radius:10px;margin:4px 4px 4px 0}
  .tl-area .chev{display:flex;color:var(--muted);flex:none;transition:transform 180ms var(--eo)}
  .tl-area .chev svg{width:13px;height:13px}
  .tl-area.open .chev{transform:rotate(90deg)}
  /* --a is the AREA's own colour, handed down from the data by
     ui/timeline.js. It was only ever painted into the 9px dot; used as
     a variable it can tint the row that is open and the rail that hangs
     under it, which is what turns eleven identical rows into a
     structure you can read at a glance. */
  .tl-area i{
    width:9px;height:9px;border-radius:50%;flex:none;background:var(--a,var(--gray-acc));
    box-shadow:0 0 0 3px color-mix(in srgb, var(--a, var(--gray-acc)) 16%, transparent);
  }
  /* open: a frosted chip in the area's colour. Just enough that you can
     see which one you are inside without looking for the chevron. */
  .tl-area.open .hd{
    background:
      linear-gradient(90deg,
        color-mix(in srgb, var(--a, var(--ink)) 15%, transparent),
        color-mix(in srgb, var(--a, var(--ink)) 5%, transparent));
    box-shadow:
      inset 0 0 0 1px color-mix(in srgb, var(--a, var(--ink)) 24%, transparent),
      inset 0 1px 0 var(--gloss);
  }
  .tl-area.open .nm{font-weight:800}
  .tl-area.open .chev{color:var(--ink)}
  .tl-area .nm{flex:1;min-width:0;line-height:1.2;overflow:hidden;overflow-wrap:break-word;hyphens:auto}
  /* the area's reading under its name: days with evidence, cuts */
  .tl-area .nm small{display:block;margin-top:2px;font-size:10.5px;font-weight:600;color:var(--muted)}
  .tl-area.cortada .nm small{color:var(--red-ink);font-weight:700}
  .tl-area .tog{cursor:default}
  .tl-area[class*="tono-"] i{background:var(--tono);box-shadow:0 0 0 3px color-mix(in srgb, var(--tono) 18%, transparent)}
  .tl-area small{color:var(--faint);font-weight:600;font-size:10.5px;font-variant-numeric:tabular-nums;flex:none}
  /* the area's bitácora, always in view: it used to appear only under
     the mouse, so on a phone it was never there and on a desk nobody
     knew to look for it */
  /* two of them now (the area's camera and its bitácora): narrower */
  .tl-area .go{display:flex;align-items:center;padding:0 6px;color:var(--muted);transition:background 140ms ease,color 140ms ease}
  .tl-area .go:hover{background:color-mix(in srgb, var(--ink) 8%, transparent);color:var(--ink)}
  .tl-area .go svg{width:15px;height:15px}
  @media (hover:hover) and (pointer:fine){
    .tl-area .hd:hover{background:var(--gray-soft)}
    .tl-area.open .hd:hover{
      background:
        linear-gradient(90deg,
          color-mix(in srgb, var(--a, var(--ink)) 22%, transparent),
          color-mix(in srgb, var(--a, var(--ink)) 9%, transparent));
    }
  }
  /* There used to be a hairline in the area's colour running down its
     activities. The indent already says they belong to the heading
     above; the line read as a stray border and went. */
  /* the hover tint layers ON TOP now: the frost underneath is what
     hides the bars passing behind, so it no longer has to be mixed into
     an opaque colour to stay readable */
  .tl-empty{grid-column:1 / -1;padding:36px 20px;text-align:center;font-size:12.5px;color:var(--muted);font-weight:600;border-bottom:none!important}

  .tl-lane{grid-column:2 / -1;position:relative;display:flex;align-items:center;min-height:52px}
  .tl-lane.sub{min-height:38px}
  .tl-lane.sub .tl-bars{padding:4px 0}

  /* ───────── expanding an area ─────────
     The rows cascade in: each one grows from 0 to its height and slides
     a couple of pixels, with --i as the delay. Closing runs the same in
     reverse (--j counts back from the last one) and only then repaints. */
  .tl-lane[style*="height"] .tl-today{display:none}
  .tl-lane.head{min-height:52px}
  .tl-cells{position:absolute;inset:0;display:grid;grid-template-columns:repeat(var(--tlN,10),1fr);pointer-events:none}
  .tl-cell{border-right:1px solid color-mix(in srgb, var(--line) 40%, transparent)}
  .tl-cell:last-child{border-right:none}
  .tl-cell.today{background:color-mix(in srgb, var(--ink) 4%, transparent)}
  /* the bars sit ABOVE the today line: the line is a reference, the
     bar is the content, and dots running across a title read as noise */
  .tl-bars{
    position:relative;z-index:2;width:100%;display:grid;
    grid-template-columns:repeat(var(--tlN,10),1fr);
    grid-auto-rows:30px;gap:6px 0;align-items:center;padding:8px 0;
  }
  /* the today line: small dark-grey dots falling slowly, one drop of
     water after another — it reads without shouting */
  .tl-today{
    position:absolute;top:0;bottom:0;left:calc((100% / var(--tlN,10)) * var(--tlHoy,0));
    width:3px;margin-left:-.75px;pointer-events:none;z-index:1;
    background:radial-gradient(circle, var(--ink) 0 1.05px, transparent 1.45px) 50% 0 / 3px 9px repeat-y;
    opacity:.55;
    filter:drop-shadow(0 0 2.5px color-mix(in srgb, var(--ink) 35%, transparent));
  }
  @media (prefers-reduced-motion:no-preference){
    @keyframes tl-hoy-flow{from{background-position:50% 0}to{background-position:50% 9px}}
    @keyframes tl-hoy-breathe{from{opacity:.4}to{opacity:.75}}
    .tl-today{animation:tl-hoy-flow 1.4s linear infinite, tl-hoy-breathe 2.8s ease-in-out infinite alternate}
  }
  .h-btn.sq{padding:10px;width:40px;justify-content:center}

  /* area dropdown */
  .dd{position:relative}
  .dd-btn .chev{transition:transform 200ms var(--eo)}
  .dd.open .dd-btn .chev{transform:rotate(180deg)}
  .dd-dot{width:8px;height:8px;border-radius:50%;flex:none}
  .dd-menu{
    position:absolute;top:calc(100% + 8px);right:0;min-width:250px;z-index:40;
    background:var(--glass-strong);
    -webkit-backdrop-filter:var(--blur);backdrop-filter:var(--blur);
    border:1px solid var(--edge);border-radius:16px;box-shadow:var(--shadow-lift);
    padding:6px;
    opacity:0;transform:scale(.96) translateY(-4px);
    pointer-events:none;transition:opacity 160ms var(--eo),transform 160ms var(--eo);
    transform-origin:top right;
  }
  .dd.open .dd-menu{opacity:1;transform:none;pointer-events:auto}
  .dd-item{
    display:flex;align-items:center;gap:10px;width:100%;
    padding:9px 12px;border-radius:11px;font-size:12.5px;font-weight:600;color:var(--ink-soft);
    text-align:left;transition:background 120ms ease;
  }
  .dd-item:hover{background:var(--gray-soft)}
  .dd-item i{width:7px;height:7px;border-radius:50%;flex:none}
  .dd-item .cnt{margin-left:auto;font-size:10.5px;color:var(--faint);font-weight:700;font-variant-numeric:tabular-nums}
  .dd-item .ck{margin-left:auto;color:var(--ink);display:flex}
  .dd-item .ck svg{width:13px;height:13px}
  .dd-item.sel{color:var(--ink);font-weight:700}

  .bar{
    height:30px;border-radius:99px;margin:0 4px;padding:0 11px 0 4px;
    display:flex;align-items:center;gap:8px;min-width:0;
    font-size:11.5px;font-weight:600;white-space:nowrap;overflow:hidden;cursor:pointer;text-align:left;
    /* an outline in the state's own ink: the tints are light enough to
       vanish into the grid, and a pill with no edge reads as a smudge */
    border:1px solid color-mix(in srgb, currentColor 24%, transparent);
    transition:filter .15s, box-shadow .15s, transform .15s;
  }
  .bar:hover{box-shadow:var(--shadow);transform:translateY(-1px)}
  .bar.picked{border-color:currentColor;box-shadow:var(--shadow)}
  /* reprogramar arrastrando (ratón): la barra se mueve por semanas y el
     asa de la derecha la alarga o la acorta */
  .bar{position:relative}
  .bar.moviendo{cursor:grabbing;opacity:.9;box-shadow:var(--shadow-lift);transform:none;transition:none;z-index:3}
  .bar .tt,.bar .cam{position:relative;z-index:1}
  .bar .tt{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis}
  .bar .cam{
    display:inline-flex;align-items:center;gap:3px;margin-left:auto;flex:none;
    font-size:10px;font-weight:800;line-height:1;
    background:color-mix(in srgb, var(--card-solid) 70%, transparent);
    border-radius:99px;padding:3px 7px;
  }
  .bar .cam svg{width:10px;height:10px}
  /* ── PUNTO PARALELO'S TONES (ui/timeline.js › tonoDe) ──
     Each area one solid colour of the brand's palette, handed out in
     order: sage, charcoal, mist, grey, slate. --on-tono is the ink that
     reads on it. Used by the area's bar, its dot and its chips. */
  .tono-0{--tono:#6B7A6F;--on-tono:#FFFFFF}
  .tono-1{--tono:#313131;--on-tono:#FFFFFF}
  .tono-2{--tono:#A6BAB4;--on-tono:#24302B}
  .tono-3{--tono:#929292;--on-tono:#FFFFFF}
  .tono-4{--tono:#595959;--on-tono:#FFFFFF}
  i.tono-0,i.tono-1,i.tono-2,i.tono-3,i.tono-4{background:var(--tono)}
  .dd-dot[class*="tono-"]{background:var(--tono)}
  /* ── THE AREA'S BAR (ui/tl-jornadas.js) ──
     No fill of its own: the stretches with evidence are filled SOLID in
     the area's tone, a cut is a red rule on its day, and in Día each
     worked day carries a camera. */
  .bar.bar-dias{background:transparent;border-color:transparent;padding:0 10px;color:var(--ink-soft);overflow:visible;cursor:default}
  .bar.bar-dias:hover{box-shadow:none;transform:none}
  /* a run of worked days: solid, the hover and click target; it ends in
     a small «📷 N» chip, hidden when the run is too short to hold it */
  .bar-dias .dd-tramo{
    position:absolute;top:3px;bottom:3px;border-radius:99px;min-width:6px;cursor:pointer;
    background:var(--tono,var(--progress));container-type:inline-size;
    transition:box-shadow 160ms ease,filter 160ms ease;
  }
  .bar-dias .dd-tramo:hover{box-shadow:0 0 0 2px var(--card-solid),0 4px 14px color-mix(in srgb, var(--tono,#6B7A6F) 35%, transparent)}
  /* 1–2 days without evidence inside a stretch: a shadow in the area's
     tone joins the two runs (it slips under their rounded ends) */
  .bar-dias .dd-hueco{
    position:absolute;top:7px;bottom:7px;margin:0 -10px;padding:0 10px;box-sizing:content-box;
    background:var(--tono,var(--progress));opacity:.22;border-radius:99px;pointer-events:auto;
  }
  /* the cut, a red dotted thread with how long the area has gone without
     evidence — only while the row is hovered. Dots, not dashes: round
     dots drawn by a gradient, so every browser draws them the same */
  /* its own wine red, not the app's alert red (owner, 14 October 2026) */
  .bar-dias .dd-corte{
    --corte:#7A1E2C;
    position:absolute;top:calc(50% - 1.5px);height:3px;opacity:0;pointer-events:none;
    background:radial-gradient(circle, var(--corte) 1.3px, transparent 1.6px) left center / 7px 3px repeat-x;
    transition:opacity 160ms ease;
  }
  .dd-corte-t{
    position:absolute;left:6px;bottom:6px;white-space:nowrap;font-size:10px;font-weight:700;
    color:var(--corte);background:var(--card-solid);padding:1px 6px;border-radius:99px;
  }
  .tl-lane:hover .bar-dias .dd-corte{opacity:1}
  @media (prefers-reduced-motion:reduce){.bar-dias .dd-corte{transition:none}}
  .dd-chip{
    position:absolute;right:4px;top:50%;transform:translateY(-50%);height:16px;padding:0 6px 0 5px;border-radius:99px;
    display:flex;align-items:center;gap:3px;font-size:9.5px;font-weight:800;font-variant-numeric:tabular-nums;
    color:var(--on-tono,#FFFFFF);background:color-mix(in srgb, var(--on-tono,#FFFFFF) 20%, transparent);pointer-events:none;
  }
  .dd-chip svg{width:9px;height:9px}
  @container (max-width:46px){.dd-chip{display:none}}
  .tl-meses .bar{padding-right:6px;gap:4px}
  .tl-meses .bar{padding-left:3px}

  /* the detail card */
  @keyframes tl-pop-in{from{opacity:0;transform:translateY(4px) scale(.98)}to{opacity:1;transform:none}}

  .tl-legend{display:flex;gap:18px;padding:12px 8px 0;font-size:11px;font-weight:600;color:var(--muted);flex-wrap:wrap}
  .tl-legend span{display:flex;align-items:center;gap:7px}
  .tl-legend i{width:9px;height:9px;border-radius:50%}
  .tl-legend-av i.lg-tramo{width:22px;height:9px;border-radius:99px;background:#6B7A6F}
  .tl-legend-av i.lg-hueco{width:22px;height:5px;border-radius:99px;background:#6B7A6F;opacity:.3}
  .tl-legend-av i.lg-cam{width:22px;height:13px;border-radius:99px;background:#6B7A6F;position:relative}
  .tl-legend-av i.lg-cam::after{content:"";position:absolute;right:3px;top:3.5px;width:8px;height:6px;border-radius:3px;background:rgba(255,255,255,.45)}
  /* the day's photo on hover (ui/tl-preview.js): a framed thumbnail
     floating above the dot, joined to it by a hairline */
  .tl-prev{
    position:fixed;z-index:70;width:200px;height:132px;border-radius:12px;overflow:hidden;pointer-events:none;
    background:var(--card-solid);border:3px solid var(--card-solid);box-shadow:var(--shadow-lift);
    opacity:0;transform:translateY(4px) scale(.98);transition:opacity 140ms ease,transform 140ms var(--eo);
  }
  .tl-prev img,.tl-prev video{display:block;width:100%;height:100%;object-fit:cover;border-radius:9px}
  .tl-prev .n{
    position:absolute;right:7px;bottom:7px;padding:2px 7px;border-radius:99px;font-size:10.5px;font-weight:800;
    background:rgba(10,10,10,.72);color:#FFFFFF;
  }
  .tl-prev-linea{
    position:fixed;z-index:69;width:1px;margin-left:-.5px;pointer-events:none;background:var(--ink);opacity:0;
    transition:opacity 140ms ease;
  }
  .tl-prev .d{
    position:absolute;left:7px;bottom:7px;padding:2px 7px;border-radius:99px;font-size:10.5px;font-weight:700;
    background:rgba(10,10,10,.72);color:#FFFFFF;
  }
  .tl-prev-dia{position:fixed;z-index:4;pointer-events:none;border-radius:99px;background:rgba(255,255,255,.26);opacity:0;transition:opacity 120ms ease}
  .tl-prev-dia.on{opacity:1}
  .tl-prev.on{opacity:1;transform:none}
  .tl-prev-linea.on{opacity:.55}

  /* ───────── activity feed ───────── */
  .feed-card .filters{display:flex;gap:6px;padding:12px 20px 4px;flex-wrap:wrap}
  .fpill{
    padding:6px 14px;border-radius:99px;font-size:11.5px;font-weight:700;color:var(--muted);
    background:var(--gray-soft);
  }
  .fpill.active{background:var(--black);color:var(--on-black)}
  .feed-list{padding:8px 20px 16px;display:flex;flex-direction:column}
  .fitem{display:flex;align-items:center;gap:12px;padding:10px 0;border-bottom:1px solid var(--line)}
  .fitem:last-child{border-bottom:none}
  .fitem .fico{
    width:34px;height:34px;border-radius:12px;flex:none;
    display:flex;align-items:center;justify-content:center;
    border:1px solid var(--edge);box-shadow:var(--shadow);background:var(--glass-strong);
  }
  .fitem .fico svg{width:15px;height:15px}
  .fitem .ft{min-width:0;flex:1}
  .fitem .ft .t1{font-size:12.5px;font-weight:700;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .fitem .ft .t2{font-size:11px;color:var(--muted);margin-top:1px}
  .fitem .when{font-size:10.5px;color:var(--faint);font-weight:700;flex:none;font-variant-numeric:tabular-nums}

  /* ───────── side: estado por área ───────── */
  .areas-panel{padding:16px 18px 10px;display:flex;flex-direction:column}
  .ap-head{display:flex;justify-content:space-between;align-items:flex-start;padding:0 2px 10px}
  .ap-head h2{font-size:16px;font-weight:800;letter-spacing:-.02em}
  .ap-head p{font-size:11.5px;color:var(--muted);font-weight:600;margin-top:2px}
  .ap-tabs{display:flex;gap:2px;border-bottom:1px solid var(--line);margin:0 2px}
  .ap-tab{display:flex;align-items:center;gap:6px;padding:8px 10px 9px;font-size:12px;font-weight:700;color:var(--muted);border-bottom:2px solid transparent;margin-bottom:-1px}
  .ap-tab span{font-size:10px;font-weight:800;background:var(--gray-soft);color:var(--ink-soft);padding:1px 7px;border-radius:99px;font-variant-numeric:tabular-nums}
  .ap-tab.on{color:var(--ink);border-bottom-color:var(--ink)}
  .ap-tab:hover{color:var(--ink)}
  .ap-cols{display:flex;justify-content:space-between;padding:8px 6px 4px;font-size:10.5px;font-weight:700;color:var(--muted)}
  .ap-cols span{display:inline-flex;align-items:center;gap:4px;cursor:help}
  .ap-cols svg{width:12px;height:12px;color:var(--faint)}
  /* the rows are the part that scrolls; the tabs above and the footer
     below stay put */
  .ap-rows{display:flex;flex-direction:column;flex:1;min-height:0;overflow-y:auto;scrollbar-width:thin;margin:0 -4px;padding:0 4px}
  .ap-row{flex:1 0 auto;border-top:1px solid var(--line);border-radius:12px;padding:2px;position:relative}
  .ap-row:first-child{border-top:none}
  .ap-main{
    width:100%;text-align:left;display:grid;grid-template-columns:minmax(0,1fr) auto 16px;grid-template-rows:auto auto auto;
    column-gap:10px;row-gap:3px;align-items:center;padding:9px 6px 8px;border-radius:10px;color:var(--ink);transition:background 120ms ease;
  }
  .ap-main:hover{background:var(--gray-soft)}
  .ap-name{grid-column:1;font-size:13px;font-weight:800;letter-spacing:-.01em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .ap-pct{grid-column:2;grid-row:1;font-size:14px;font-weight:800;font-variant-numeric:tabular-nums;text-align:right}
  .ap-chev{grid-column:3;grid-row:1 / span 2;display:flex;color:var(--faint)}
  .ap-chev svg{width:14px;height:14px}
  .ap-st{grid-column:1;grid-row:2;display:inline-flex;align-items:center;gap:6px;font-size:11px;font-weight:600;color:var(--muted)}
  .ap-st i{width:7px;height:7px;border-radius:50%;background:var(--gray-acc)}
  .ap-st-pct{font-variant-numeric:tabular-nums;color:var(--muted)}
  .ap-st.obra i,.ap-st.warn i{background:var(--ink)}
  .ap-st.ok i{background:var(--green)}
  .ap-st.ok{color:var(--green-ink)}
  .ap-st.idle i{background:var(--line-strong)}
  .ap-bar{grid-column:1 / span 3;grid-row:3;height:6px;border-radius:99px;background:var(--line);overflow:hidden;display:block;margin-top:2px}
  .ap-bar i{display:block;height:100%;border-radius:99px;background:var(--progress);transition:width 600ms var(--eo)}
  /* the width transition never fires on first paint — the bar is written
     straight to its value by innerHTML — so the entrance is its own
     keyframe: it eases to the value it already has, 24ms per row */
  @media (prefers-reduced-motion:no-preference){
    @keyframes ap-bar-in{from{transform:scaleX(0)}to{transform:scaleX(1)}}
    .ap-bar.ap-bar-in i{transform-origin:left;animation:ap-bar-in 560ms var(--eo) both;animation-delay:calc(var(--bi,0) * 24ms)}
  }
  @media (prefers-reduced-motion:reduce){ .ap-bar i{transition:none} }
  .ap-row.warn .ap-bar i{background:var(--ink)}
  .ap-st.ok ~ .ap-bar i{background:var(--green)}
  .ap-empty{padding:26px 8px;font-size:12px;color:var(--faint);font-weight:600;text-align:center}
  .ap-foot{display:flex;align-items:center;gap:6px;padding:12px 6px 4px;font-size:12.5px;font-weight:800;color:var(--ink);border-top:1px solid var(--line);margin-top:auto}
  .ap-foot svg{width:14px;height:14px;transition:transform 160ms var(--eo)}
  .ap-foot:hover svg{transform:translateX(2px)}
  .apill{
    flex:1;display:flex;align-items:center;justify-content:center;gap:6px;
    padding:8px 10px;border-radius:12px;font-size:11px;font-weight:700;
    background:var(--glass-strong);border:1px solid var(--edge);box-shadow:var(--shadow);color:var(--ink-soft);
  }
  .apill:hover{color:var(--ink)}
  .apill svg{width:12px;height:12px}

  /* ───────── drawer ───────── */
  .scrim{position:fixed;inset:0;background:var(--overlay);opacity:0;pointer-events:none;transition:opacity .25s;z-index:40}
  .scrim.open{opacity:1;pointer-events:auto}
  .drawer{
    /* width: nearly 40% of the screen on desktop — the bitácora is for
       reading, and the photos deserve more than a strip of thumbnails */
    position:fixed;top:12px;right:12px;bottom:12px;width:clamp(440px,39vw,820px);max-width:92vw;
    background:var(--glass-strong);-webkit-backdrop-filter:var(--blur);backdrop-filter:var(--blur);
    border-radius:22px;border:1px solid var(--edge);
    box-shadow:var(--shadow-lift);z-index:50;transform:translateX(calc(100% + 24px));
    transition:transform .3s cubic-bezier(.32,.72,.24,1);display:flex;flex-direction:column;overflow:hidden;
  }
  .drawer.open{transform:none}
  .dr-head{padding:20px 22px 15px;border-bottom:1px solid var(--line);flex:none;position:relative}
  .dr-head .area{font-size:10.5px;font-weight:700;letter-spacing:.02em;color:var(--muted);display:flex;align-items:center;gap:6px}
  .dr-head .area i{width:7px;height:7px;border-radius:50%}
  .dr-head h2{font-size:17px;font-weight:800;margin-top:7px;line-height:1.3;letter-spacing:-.01em;text-wrap:balance;padding-right:36px}
  .dr-close{position:absolute;top:14px;right:14px;width:32px;height:32px;border-radius:10px;display:flex;align-items:center;justify-content:center;color:var(--muted)}
  .dr-close:hover{background:var(--gray-soft);color:var(--ink)}
  .dr-meta{display:flex;gap:16px;margin-top:13px;flex-wrap:wrap}
  .dr-meta .m .k{font-size:9.5px;color:var(--faint);letter-spacing:.08em;text-transform:uppercase;font-weight:800}
  .dr-meta .m .v{font-size:12px;font-weight:700;margin-top:2px;font-variant-numeric:tabular-nums;display:flex;align-items:center;gap:6px}
  .shot{border-radius:14px;overflow:hidden;position:relative;border:1px solid var(--edge);box-shadow:var(--shadow)}
  .shot img{width:100%;height:108px;object-fit:cover;display:block}
  .shot video{width:100%;height:130px;object-fit:cover;display:block;background:#000}
  .btn{
    flex:1;padding:11px 14px;border-radius:14px;font-weight:700;font-size:12.5px;
    display:flex;align-items:center;justify-content:center;gap:8px;transition:opacity .15s;
  }
  .btn svg{width:15px;height:15px}
  .btn.primary{background:var(--cta);color:var(--on-cta)}
  .btn.primary:hover{opacity:.85}
  .btn.approve{background:var(--green);color:#fff}
  :root[data-theme="dark"] .btn.approve{color:#10241A}
  @media (prefers-color-scheme: dark){:root:not([data-theme="light"]):not([data-theme="concreto"]) .btn.approve{color:#10241A}}
  .btn.approve:hover{opacity:.88}
  .btn:disabled{opacity:.4;cursor:not-allowed}

  /* ───────── motion ───────── */
  :root{--eo:cubic-bezier(.23,1,.32,1);--edrawer:cubic-bezier(.32,.72,0,1)}
  .h-btn,.icon-btn,.nav-pill,.views button,.seg button,.fpill,.apill,.btn,.mini,.dr-close{
    transition:transform 160ms var(--eo), background-color 150ms ease, color 150ms ease, border-color 150ms ease, opacity 150ms ease, box-shadow 150ms ease;
  }
  .h-btn:active,.icon-btn:active,.nav-pill:active,.views button:active,.seg button:active,.fpill:active,.apill:active,.btn:not(:disabled):active,.mini:active:active{
    transform:scale(.96);
  }
  .drawer{transition:transform 320ms var(--edrawer)}
  @media (prefers-reduced-motion:no-preference){
    .page-anim{animation:pageIn 280ms var(--eo) both}
    @keyframes pageIn{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
    .stag{opacity:0;animation:stagIn 260ms var(--eo) forwards}
    @keyframes stagIn{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
  }
  @media (prefers-reduced-motion:reduce){
    .page-anim{animation:pageFade 150ms ease both}
    @keyframes pageFade{from{opacity:.4}to{opacity:1}}
    .h-btn:active,.icon-btn:active,.nav-pill:active,.views button:active,.seg button:active,.fpill:active,.apill:active,.btn:not(:disabled):active,.mini:active:active{transform:none}
  }

  /* ───────── evidencias page ───────── */
  .ev-filters{display:flex;gap:7px;flex-wrap:wrap;margin:0 0 16px}
  .ev-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(235px,1fr));gap:14px}
  .ev-card{overflow:hidden;padding:0;cursor:pointer;text-align:left}
  .ev-card img{width:100%;height:150px;object-fit:cover;display:block}
  .ev-card .vwrap{position:relative;display:block}
  .ev-card video{width:100%;height:150px;object-fit:cover;display:block;background:#0E0E0D}
  .ev-card .vbadge{
    position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
  }
  .ev-card .vbadge svg{
    width:36px;height:36px;color:#fff;background:rgba(10,10,9,.55);border-radius:50%;padding:9px;
  }
  .ev-card .fwrap{
    height:150px;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;
    background:var(--gray-soft);color:var(--muted);
  }
  .ev-card .fwrap svg{width:30px;height:30px}
  .ev-card .fname{font-size:10.5px;font-weight:700;max-width:85%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .ev-card .body{padding:11px 13px 12px}
  .ev-card .body .t{font-size:12.5px;font-weight:700;line-height:1.35}
  .ev-card .body .m{display:flex;align-items:center;gap:6px;font-size:10.5px;color:var(--muted);font-weight:600;margin-top:5px}
  .ev-card .body .m i{width:6px;height:6px;border-radius:50%;flex:none}
  .ev-card .body .m .when{margin-left:auto;color:var(--faint);font-variant-numeric:tabular-nums}
  @media (hover:hover) and (pointer:fine){
    .ev-card:hover{box-shadow:var(--shadow-lift);transform:translateY(-2px)}
  }
  .ev-card{transition:box-shadow 180ms var(--eo),transform 180ms var(--eo)}


  /* ───────── documentos ─────────
     A filing cabinet: navigation column on the left, table on the
     right. The table is a grid with fixed columns so that Nombre,
     Origen, Modificado and Tamaño stay aligned row after row. */
  body.fill .content{min-height:100vh;display:flex;flex-direction:column;padding-bottom:20px}
  body.fill #page-documentos:not([hidden]){display:flex;flex-direction:column;flex:1;min-height:0}
  body.fill #page-documentos .hero{flex:none}
  .doc-shell{display:grid;grid-template-columns:230px 1fr;min-height:560px;padding:0;overflow:visible;flex:1}
  /* ───────── the client's Documentos (ui/doc-cliente.js) ─────────
     A bento grid: «Control de Gastos» the large dark tile with its
     $, the other categories around it. A tile opens in place (.abriendo
     while it moves, .abierto once it rests full width in the flow). */
  #page-documentos.doc-cliente .doc-shell{display:none}
  #page-documentos:not(.doc-cliente) .doc-cli{display:none}
  .doc-cli{max-width:1180px}
  .dbg{position:relative;display:grid;grid-template-columns:repeat(4,minmax(0,1fr));grid-auto-rows:150px;grid-auto-flow:dense;gap:12px}
  .dbg.abierta{grid-auto-rows:auto}
  .dbg.abierta > .dbt:not(.abierto){display:none}
  .dbt{position:relative;border-radius:22px;background:var(--card);border:1px solid var(--line);overflow:hidden;transition:border-color 160ms ease,transform 180ms var(--eo)}
  .dbt.costos{grid-column:span 2;grid-row:span 2;background:var(--black);color:var(--on-black);border-color:transparent}
  /* an empty category: a calm card that says what will arrive, with a
     «Pronto» tag — dashed read as switched off */
  .dbt.vacia:not(.costos){background:color-mix(in srgb, var(--card) 55%, transparent)}
  .dbt.recientes,.dbt.ancho{grid-column:span 2}
  /* wide and short: the title on the left, its latest two on the right */
  .dbt.con-pie .dbt-sum{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.15fr);grid-template-rows:auto 1fr;column-gap:18px;align-items:start}
  .dbt.con-pie .dbt-tt{align-self:end}
  .dbt.con-pie .dbt-pie{grid-column:2;grid-row:1/3;align-self:center;margin:0;min-width:0}
  .dbt.con-pie .dbt-pie span{color:var(--ink-soft);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:block;padding-left:16px;position:relative}
  .dbt.con-pie .dbt-pie i{position:absolute;left:0;top:50%;margin-top:-4px}
  .dbt-hueco{visibility:hidden}
  .dbt:not(.abierto):not(.abriendo):hover{border-color:var(--line-strong);transform:translateY(-2px)}
  .dbt.costos:not(.abierto):not(.abriendo):hover{border-color:transparent}
  .dbt-sum{position:absolute;inset:0;display:flex;flex-direction:column;align-items:flex-start;gap:6px;padding:18px;text-align:left;width:100%;color:inherit;transition:opacity 200ms ease}
  .dbt-ico{width:40px;height:40px;border-radius:12px;display:grid;place-items:center;flex:none}
  .dbt-ico svg{width:20px;height:20px}
  .dbt-reloj{background:var(--gray-soft);color:var(--ink-soft)}
  .dbt-dolar{background:color-mix(in srgb, var(--on-black) 14%, transparent);color:var(--on-black);width:52px;height:52px;border-radius:16px}
  .dbt-dolar svg{width:28px;height:28px}
  .dbt-tt{display:flex;flex-direction:column;gap:2px;min-width:0;max-width:100%}
  .dbt-tt b{font-size:15px;font-weight:800;letter-spacing:-.01em}
  .dbt.costos .dbt-tt b{font-size:22px;letter-spacing:-.02em}
  .dbt-tt small{font-size:11.5px;color:var(--muted);font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .dbt.costos .dbt-tt small{color:color-mix(in srgb, var(--on-black) 65%, transparent)}
  .dbt.vacia:not(.costos) .dbt-tt small{white-space:normal;line-height:1.4;color:var(--muted)}
  .dbt-marca.pronto{background:var(--gray-soft);color:var(--muted)}
  .dbt-lead{font-size:13px;font-weight:500;line-height:1.45;max-width:380px;color:color-mix(in srgb, var(--on-black) 82%, transparent)}
  .dbt-pie{margin-top:auto;display:flex;flex-direction:column;gap:6px}
  .dbt-pie span{display:flex;align-items:center;gap:8px;font-size:12.5px;font-weight:600}
  .dbt-pie i{width:8px;height:8px;border-radius:50%;background:currentColor;flex:none}
  .dbt-pie.espera span{color:color-mix(in srgb, var(--on-black) 70%, transparent)}
  .dbt-pie.espera i{background:transparent;border:1.5px solid currentColor}
  .dbt-marca{position:absolute;top:16px;right:16px;font-size:10.5px;font-weight:800;padding:4px 9px;border-radius:99px;background:var(--amber-soft);color:var(--amber-ink);white-space:nowrap}
  .dbt.costos .dbt-marca{background:color-mix(in srgb, var(--on-black) 16%, transparent);color:var(--on-black)}
  .dbt-det{display:none;flex-direction:column;gap:4px;padding:18px 22px 10px;transition:opacity 220ms ease}
  /* while it travels the tile is an empty surface: no hover lift easing
     out under it, no list re-wrapping at every frame of the resize */
  .dbt.abriendo{transition:none;transform:none}
  .dbt.abriendo .dbt-sum,.dbt.abierto .dbt-sum{opacity:0;pointer-events:none;transition-duration:120ms}
  .dbt.abierto .dbt-sum{display:none}
  .dbt.abriendo .dbt-det{display:none}
  .dbt.abierto .dbt-det{display:flex}
  .dbt.abierto{grid-column:1/-1;grid-row:auto}
  .dbt-h{display:flex;align-items:center;gap:12px;margin:8px 0 6px}
  .dbt-h h2{font-size:18px;font-weight:800;letter-spacing:-.01em}
  .dbt-h p{font-size:12.5px;color:var(--muted);font-weight:500;margin-top:2px}
  .dbt.costos .dbt-h p{color:color-mix(in srgb, var(--on-black) 70%, transparent)}
  /* THE PALETTE ON THE TILES (Punto Paralelo theme): costs in stone
     (--black), the categories a checkerboard of mist #A6BAB4 and light
     gray #E5E5E5, «Recién compartido» in mist like them — no white
     tiles, and no dark one */
  :root[data-theme="concreto"] .dbt.tono-niebla{background:#A6BAB4;border-color:transparent;color:#24302B}
  /* light gray sits close to the page's own gray: a hairline keeps the
     tile's edge */
  :root[data-theme="concreto"] .dbt.tono-gris{background:#E5E5E5;border-color:rgba(49,49,49,.1);color:#313131}
  :root[data-theme="concreto"] .dbt.tono-niebla .dbt-tt small{color:rgba(36,48,43,.72)}
  :root[data-theme="concreto"] .dbt.tono-gris .dbt-tt small{color:#5F5F5F}
  :root[data-theme="concreto"] .dbt.tono-niebla .dbt-ico{background:rgba(255,255,255,.42) !important;color:#24302B !important}
  :root[data-theme="concreto"] .dbt.tono-gris .dbt-ico{background:rgba(49,49,49,.07) !important;color:#4E5C52 !important}
  :root[data-theme="concreto"] .dbt.tono-niebla .dbt-pie span{color:inherit}
  :root[data-theme="concreto"] .dbt.tono-niebla .dbt-marca,:root[data-theme="concreto"] .dbt.tono-gris .dbt-marca{background:rgba(255,255,255,.55);color:inherit}
  :root[data-theme="concreto"] .dbt.tono-niebla.vacia,:root[data-theme="concreto"] .dbt.tono-gris.vacia{opacity:.88}
  :root[data-theme="concreto"] .dbt.tono-niebla .dcli-row{border-top-color:rgba(36,48,43,.14)}
  :root[data-theme="concreto"] .dbt.tono-niebla .dcli-tag,:root[data-theme="concreto"] .dbt.tono-niebla .dcli-back{background:rgba(255,255,255,.42);color:#24302B}
  :root[data-theme="concreto"] .dbt.tono-niebla .dcli-nm small,:root[data-theme="concreto"] .dbt.tono-niebla .dbt-h p{color:rgba(36,48,43,.72)}
  /* the costs tile opened keeps its ink: its rows follow it */
  .dbt.costos .dcli-row{border-top-color:color-mix(in srgb, var(--on-black) 14%, transparent);color:var(--on-black)}
  .dbt.costos .dcli-nm small,.dbt.costos .dcli-vacio{color:color-mix(in srgb, var(--on-black) 65%, transparent)}
  .dbt.costos .dcli-tag{background:color-mix(in srgb, var(--on-black) 12%, transparent);color:var(--on-black)}
  .dbt.costos .dcli-back{color:var(--on-black);background:color-mix(in srgb, var(--on-black) 14%, transparent)}
  .dbt.costos .dcli-back:hover{background:color-mix(in srgb, var(--on-black) 22%, transparent)}
  .dcli-list{display:flex;flex-direction:column}
  .dcli-row{display:flex;align-items:center;gap:12px;padding:11px 4px;border-top:1px solid var(--line);text-align:left;width:100%;border-radius:0;color:inherit}
  .dcli-row:hover .dcli-nm b{text-decoration:underline;text-underline-offset:3px}
  .dcli-tag{width:38px;height:38px;border-radius:10px;flex:none;display:grid;place-items:center;font-size:9.5px;font-weight:800;letter-spacing:.04em;background:var(--gray-soft);color:var(--ink-soft)}
  .dcli-nm{display:flex;flex-direction:column;min-width:0;flex:1}
  .dcli-nm b{font-size:13.5px;font-weight:700;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .dcli-nm small{font-size:11px;color:var(--muted);font-weight:600}
  .dcli-nuevo{font-size:10px;font-weight:800;padding:3px 8px;border-radius:99px;background:var(--black);color:var(--on-black);flex:none}
  .dcli-pill{font-size:10.5px;font-weight:800;padding:4px 9px;border-radius:99px;flex:none;white-space:nowrap}
  .dcli-pill.ok{background:var(--green-soft);color:var(--green-ink)}
  .dcli-pill.espera{background:var(--amber-soft);color:var(--amber-ink)}
  /* the way back is a real button: a pill a thumb finds, not a link-sized
     word in a corner */
  .dcli-back{
    display:inline-flex;align-items:center;gap:8px;align-self:flex-start;min-height:44px;
    padding:10px 18px 10px 14px;border-radius:99px;font-size:14px;font-weight:700;
    color:var(--ink);background:var(--gray-soft);transition:background 140ms ease,transform 140ms ease;
  }
  .dcli-back svg{width:18px;height:18px}
  .dcli-back:hover{background:color-mix(in srgb, var(--ink) 12%, transparent)}
  .dcli-back:active{transform:scale(.97)}
  .dcli-vacio{padding:24px 4px;font-size:13px;color:var(--muted);font-weight:500;line-height:1.5}
  /* two columns on a phone: costs across both, two rows tall */
  @media (max-width:640px){
    .dbg{grid-template-columns:1fr 1fr;grid-auto-rows:132px;gap:10px}
    .dbt-sum{padding:14px}
    .dbt-marca{top:12px;right:12px}
    .dbt.costos .dbt-tt b{font-size:19px}
    .dbt:not(.recientes) .dbt-tt small{white-space:normal}
    .dbt-lead{font-size:12px}
    .dbt-det{padding:14px 14px 8px}
  }
  .doc-side{padding:16px 12px;border-right:1px solid var(--line)}
  .doc-navi{
    display:flex;align-items:center;gap:11px;width:100%;padding:10px 12px;border-radius:12px;
    font-size:13px;font-weight:700;color:var(--ink-soft);text-align:left;transition:background 140ms ease,color 140ms ease;
    text-decoration:none;
  }
  .doc-navi svg{width:17px;height:17px;flex:none;color:var(--muted)}
  .doc-navi span{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .doc-navi.sm{font-size:12.5px;padding:8px 12px}
  .doc-navi.sm svg:last-child:not(:first-child){width:12px;height:12px;color:var(--faint)}
  .doc-navi:hover{background:var(--gray-soft);color:var(--ink)}
  .doc-navi.active{background:var(--gray-soft);color:var(--ink)}
  .doc-navi.active svg{color:var(--ink)}
  .doc-side-h{
    margin:18px 12px 6px;padding-top:14px;border-top:1px solid var(--line);
    font-size:9.5px;font-weight:800;letter-spacing:.12em;text-transform:uppercase;color:var(--faint);
  }
  .doc-hint{font-size:11.5px;color:var(--muted);font-weight:500;padding:6px 12px;line-height:1.45}

  .doc-main{padding:18px 22px 20px;min-width:0;position:relative;border-radius:0 20px 20px 0;transition:background 150ms ease;display:flex;flex-direction:column}
  .doc-main.dropping{background:color-mix(in srgb, var(--green) 6%, transparent)}
  .doc-main.dropping::after{
    content:"Suelta para subir a esta carpeta";position:absolute;inset:10px;border:2px dashed var(--green-ink);border-radius:16px;
    display:flex;align-items:center;justify-content:center;font-size:14px;font-weight:800;color:var(--green-ink);
    background:color-mix(in srgb, var(--card-solid) 70%, transparent);pointer-events:none;
  }
  .doc-crumb{display:flex;align-items:center;gap:8px;font-size:13px;font-weight:600;color:var(--muted);margin-bottom:14px;min-height:30px}
  .doc-back{width:28px;height:28px;border-radius:9px;display:flex;align-items:center;justify-content:center;color:var(--muted);margin-right:2px}
  .doc-back:hover:not(:disabled){background:var(--gray-soft);color:var(--ink)}
  .doc-back:disabled{opacity:.35;cursor:default}
  .doc-back svg{width:15px;height:15px}
  .doc-crumb .crumb{color:var(--muted);font-weight:600;font-size:13px}
  .doc-crumb button.crumb:hover{color:var(--ink)}
  .doc-crumb .crumb.now{color:var(--ink);font-weight:800}
  .doc-crumb .sep{color:var(--faint)}
  .doc-crumb .crumb-menu{margin-left:2px}

  .doc-tools{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-bottom:14px}
  .doc-search{
    display:flex;align-items:center;gap:8px;flex:0 1 420px;min-width:220px;height:40px;padding:0 12px;
    border:1px solid var(--edge);border-radius:12px;background:var(--glass);box-shadow:var(--shadow);
  }
  .doc-search svg{width:15px;height:15px;color:var(--muted);flex:none}
  .doc-search input{flex:1;min-width:0;background:none;border:none;outline:none;font:inherit;font-size:12.5px;font-weight:600;color:var(--ink)}
  .doc-search input::placeholder{color:var(--faint)}
  .doc-search input::-webkit-search-cancel-button{-webkit-appearance:none}
  .doc-tools .spacer{flex:1}
  .doc-tools .views{margin-left:auto}
  .doc-dd .dd-menu{min-width:220px}
  #doc-add .dd-menu{min-width:260px;right:0}
  #doc-add .dd-item kbd{
    margin-left:auto;font:inherit;font-size:10.5px;font-weight:700;color:var(--muted);
    background:var(--gray-soft);border-radius:6px;padding:2px 6px;
  }
  .dd-item svg{width:16px;height:16px;flex:none;color:var(--muted)}
  .dd-item .ck svg{color:var(--ink)}

  /* the table */
  .doc-table{border:1px solid var(--line);border-radius:14px;overflow:hidden;flex:1;display:flex;flex-direction:column}
  .doc-table .doc-cards{align-content:start}
  .doc-thead,.doc-tr{
    display:grid;grid-template-columns:40px minmax(240px,1.6fr) 130px 150px 100px 120px;
    align-items:center;gap:8px;padding:0 14px 0 12px;
  }
  .doc-thead{height:42px;background:var(--gray-soft);font-size:11.5px;font-weight:700;color:var(--muted);border-bottom:1px solid var(--line)}
  /* LA PAPELERA tiene su propia rejilla: aquí no hay carpetas que
     seleccionar ni tamaños que comparar, y sí dos botones por fila que
     necesitan sitio de verdad. */
  .doc-thead.pap,.doc-tr.pap{grid-template-columns:minmax(240px,1.6fr) 150px 130px 200px;padding-left:16px}
  .doc-tr.pap{cursor:default}
  .doc-tr.pap .c-name .nm b{color:var(--muted)}
  .pap-act{display:flex;justify-content:flex-end;gap:6px}
  .pap-act .apill{flex:none}
  .pap-act .apill svg{width:13px;height:13px}
  /* painted on a phone only: on a desktop it has a column of its own */
  .solo-cel{display:none}
  .doc-sort{display:inline-flex;align-items:center;gap:5px;font-size:11.5px;font-weight:700;color:var(--muted)}
  .doc-sort:hover,.doc-sort.on{color:var(--ink)}
  .doc-sort .si{display:flex;color:var(--faint)}
  .doc-sort .si svg{width:13px;height:13px}
  .doc-sort.on .si{color:var(--ink)}
  .doc-sort .si.flip svg{transform:scaleY(-1)}
  .doc-tr{min-height:58px;border-bottom:1px solid var(--line);cursor:pointer;transition:background 140ms ease;text-align:left}
  .doc-tr:last-child{border-bottom:none}
  @media (hover:hover) and (pointer:fine){.doc-tr:hover{background:var(--gray-soft)}}
  .doc-tr.sel{background:color-mix(in srgb, var(--green) 6%, transparent)}
  .doc-cb{
    width:18px;height:18px;border-radius:5px;border:1.5px solid var(--line-strong);background:var(--card-solid);
    display:flex;align-items:center;justify-content:center;color:transparent;transition:background 120ms ease,border-color 120ms ease;
  }
  .doc-cb svg{width:11px;height:11px}
  .doc-cb.on{background:var(--black);border-color:var(--black);color:var(--on-black)}
  .doc-tr:hover .doc-cb:not(.on){border-color:var(--muted)}
  .c-name{display:flex;align-items:center;gap:12px;min-width:0}
  .c-name .nm{min-width:0;display:flex;flex-direction:column;gap:1px}
  .c-name .nm b{font-size:13px;font-weight:700;color:var(--ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:flex;align-items:center;gap:6px}
  .c-name .nm b .ext{display:inline-flex;color:var(--muted)}
  .c-name .nm b .ext svg{width:12px;height:12px}
  .c-name .nm span{font-size:11px;color:var(--muted);font-weight:600}
  .c-name .fav-mark{display:flex;color:var(--amber);margin-left:2px}
  .c-name .fav-mark svg{width:12px;height:12px}
  .c-src,.c-mod,.c-size{font-size:12.5px;color:var(--muted);font-weight:600;white-space:nowrap;font-variant-numeric:tabular-nums}
  .c-act{display:flex;align-items:center;justify-content:flex-end;gap:8px;color:var(--muted)}
  .c-act > svg{width:14px;height:14px}
  .open-hint{font-size:12px;font-weight:700;color:var(--ink-soft);opacity:0;transition:opacity 140ms ease}
  .doc-tr.folder:hover .open-hint{opacity:1}
  .doc-dots{
    width:30px;height:30px;border-radius:9px;display:inline-flex;align-items:center;justify-content:center;color:var(--muted);
    transition:background 120ms ease,color 120ms ease;
  }
  .doc-dots svg{width:16px;height:16px}
  .doc-dots:hover,.doc-tr.menu-open .doc-dots,.doc-card.menu-open .doc-dots{background:var(--gray-soft);color:var(--ink)}
  .doc-ico{
    width:38px;height:38px;border-radius:11px;flex:none;
    display:flex;align-items:center;justify-content:center;font-size:8.5px;font-weight:800;letter-spacing:.06em;
  }
  .doc-ico.fold{width:40px;height:40px;border-radius:12px}
  .doc-ico.fold svg,.doc-ico.drive svg{width:24px;height:24px}
  .doc-ico.drive{background:transparent}
  .doc-empty{padding:48px 20px;text-align:center;font-size:12.5px;color:var(--muted);font-weight:600;line-height:1.5}

  .doc-foot{display:flex;align-items:center;justify-content:space-between;gap:14px;margin-top:14px;flex:none;font-size:12px;color:var(--muted);font-weight:600;flex-wrap:wrap}
  .doc-foot #doc-foot-l{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
  .doc-foot .apill.danger{color:var(--red-ink)}
  .doc-drop{display:flex;align-items:center;gap:8px;font-size:12px;font-weight:600;color:var(--muted);padding:6px 10px;border-radius:10px}
  .doc-drop:hover{background:var(--gray-soft);color:var(--ink)}
  .doc-drop svg{width:15px;height:15px}

  /* the three-dot menu lives on the body so the table cannot clip it */
  .doc-menu{
    position:fixed;z-index:70;min-width:230px;padding:6px;
    background:var(--glass-strong);-webkit-backdrop-filter:var(--blur);backdrop-filter:var(--blur);
    border:1px solid var(--edge);border-radius:14px;box-shadow:var(--shadow-lift);
    animation:tl-pop-in 140ms var(--eo);
  }
  .doc-menu .dd-item{width:100%}
  .doc-menu .dd-item.danger{color:var(--red-ink)}
  .doc-menu .dd-item.danger svg{color:var(--red-ink)}
  .doc-menu .dd-sub{border-top:1px solid var(--line);border-bottom:1px solid var(--line);margin:4px 0;padding:4px 0}
  .doc-menu .dd-h{display:flex;align-items:center;gap:10px;padding:6px 12px 4px;font-size:10.5px;font-weight:800;letter-spacing:.08em;text-transform:uppercase;color:var(--faint)}
  .doc-menu .dd-h svg{width:14px;height:14px}
  .doc-menu .dd-item.sub{padding-left:34px;font-size:12px}

  /* grid view */
  .doc-cards{display:grid;grid-template-columns:repeat(auto-fill,minmax(210px,1fr));gap:14px;padding:14px}
  .doc-card{
    overflow:visible;display:flex;flex-direction:column;text-align:left;padding:0;
    transition:box-shadow 180ms var(--eo),transform 180ms var(--eo);
  }
  @media (hover:hover) and (pointer:fine){
    .doc-card:hover{box-shadow:var(--shadow-lift);transform:translateY(-2px)}
  }
  .doc-prev{height:88px;display:flex;align-items:center;justify-content:center;position:relative;flex:none;border-radius:20px 20px 0 0}
  .doc-prev svg{width:30px;height:30px;opacity:.85}
  .doc-prev.fold svg{width:34px;height:34px}
  .doc-prev.drive{background:var(--gray-soft)}
  .doc-prev .tag{
    position:absolute;top:10px;right:10px;
    font-size:8.5px;font-weight:800;letter-spacing:.08em;
    background:color-mix(in srgb, var(--card-solid) 75%, transparent);
    border-radius:99px;padding:3px 8px;
  }
  .doc-card .body{padding:12px 14px 14px;display:flex;flex-direction:column;flex:1}
  .doc-card .body .n{font-size:12.5px;font-weight:700;line-height:1.35}
  .doc-card .body .m{font-size:10.5px;color:var(--muted);font-weight:600;margin-top:4px}
  .doc-card .body .row{display:flex;align-items:center;justify-content:space-between;margin-top:12px}
  .doc-card .body .apill{padding:7px 13px}
  .doc-card.fold .body{padding-bottom:16px}

  @media (max-width:900px){
    .doc-shell{grid-template-columns:1fr}
    .doc-side{border-right:none;border-bottom:1px solid var(--line);display:flex;gap:6px;overflow-x:auto;padding:10px}
    .doc-side nav{display:flex;gap:6px}
    .doc-side-h,#doc-shortcuts{display:none}
    .doc-thead,.doc-tr{grid-template-columns:32px minmax(0,1fr) 90px 36px}
    /* en la papelera se cae «borrado por» con las demás columnas de
       apoyo, pero los dos botones no se negocian: son la razón de la
       pantalla */
    .doc-thead.pap,.doc-tr.pap{grid-template-columns:minmax(0,1fr) 92px 172px;padding-left:12px}
    .c-src,.c-size{display:none}
  }

  /* ═══════════ THE CABINET ON A PHONE ═══════════
     A desktop table crammed into 375px: "Modificado" took 90 of them and
     the name came out clipped — "Contratc" instead of "Contratos y
     anexos", which is precisely what somebody scans a document list for.

     Here it stops being a table and becomes a list: the name rules its
     own line, and origen, tamaño and fecha drop underneath in grey
     (`.solo-cel`, not painted on a desktop because there they have
     columns). No header, no sorting by column — that moves to the
     filters — and no view switch: on a phone the list is the view. */
  @media (max-width:760px){
    .doc-thead{display:none}
    .doc-tr{grid-template-columns:28px minmax(0,1fr) 34px;gap:10px;padding:0 10px 0 12px;min-height:64px}
    .doc-tr .c-mod{display:none}
    .solo-cel{display:inline;font-style:normal}
    .doc-tr .c-name{gap:10px}
    .doc-tr .c-name .nm{min-width:0}
    .doc-tr .c-name .nm b{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:block}
    .doc-tr .c-name .nm span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:block}
    /* "Abrir carpeta" only fits on a desktop; the chevron already says it */
    .doc-tr .c-act .open-hint{display:none}
    /* THE SEAL GOES DOWN A LINE. "Esperando firma" sitting beside the
       name left it 40px and the row read «C…» — the state squeezing out
       the one thing the row is for. Under the name it has the width of
       the row, and the name has all of its own. */
    .doc-tr .c-name{flex-wrap:wrap}
    .doc-tr .c-name .nm{flex:1 1 0;min-width:0}
    .doc-tr .c-name .doc-sello{flex:0 0 100%;margin:3px 0 0;align-self:flex-start}
    .doc-tools .views{display:none}
    .doc-tools .spacer{display:none}
    .doc-search{flex:1 1 100%}
    .doc-tools .dd{flex:1 1 0;min-width:0}
    .doc-tools .dd .dd-btn{width:100%;justify-content:space-between}
    /* the trash: two buttons per row and nothing else */
    .doc-thead.pap,.doc-tr.pap{grid-template-columns:minmax(0,1fr) 150px;padding-left:12px}
    .doc-tr.pap .c-mod,.doc-tr.pap .c-src{display:none}
    /* so the last row and the footer clear the floating dock */
    body.fill .content{padding-bottom:96px}
  }

  /* ───────── login ───────── */
  .login{position:fixed;inset:0;z-index:60;background:var(--bg);overflow:auto;transition:opacity 450ms var(--eo)}
  .login.bye{opacity:0;pointer-events:none}
  /* Recargar con sesión: la puerta se queda, pero VACÍA — un velo del
     color del fondo mientras el servidor confirma quién es. Antes se
     pintaba la tarjeta entera y luego se desvanecía: un segundo de
     «inicien sesión» delante de alguien que ya la tiene. La clase la
     pone un script en <head> (leída de la visita anterior) y la quita
     login.js si el servidor contesta que no hay sesión. */
  html.con-sesion .login>*{display:none}
  .login .sweep{
    position:absolute;inset:0;pointer-events:none;
    background:
      linear-gradient(65deg, rgba(255,255,255,.95) 2%, rgba(255,255,255,.45) 13%, transparent 32%),
      linear-gradient(65deg, transparent 13%, rgba(255,255,255,.9) 20%, transparent 31%),
      linear-gradient(115deg, #FFFFFF 2%, transparent 15%),
      linear-gradient(115deg, transparent 16%, rgba(255,255,255,.7) 24%, transparent 35%),
      linear-gradient(115deg, rgba(25,25,24,.05) 6%, rgba(25,25,24,.06) 38%, transparent 66%);
  }
  :root[data-theme="dark"] .login .sweep{opacity:.07}
  @media (prefers-color-scheme: dark){
    :root:not([data-theme="light"]):not([data-theme="concreto"]) .login .sweep{opacity:.07}
  }
  .login-bg{
    position:absolute;top:0;right:0;height:100%;width:min(1150px,80vw);
    object-fit:cover;object-position:right bottom;pointer-events:none;
    -webkit-mask-image:linear-gradient(90deg, transparent 0%, #000 30%);
    mask-image:linear-gradient(90deg, transparent 0%, #000 30%);
  }
  .login-fade{
    position:absolute;inset:0;pointer-events:none;
    background:
      linear-gradient(90deg, var(--bg) 5%, color-mix(in srgb, var(--bg) 60%, transparent) 26%, transparent 50%),
      linear-gradient(0deg, color-mix(in srgb, var(--bg) 88%, transparent) 0%, color-mix(in srgb, var(--bg) 42%, transparent) 13%, transparent 38%),
      linear-gradient(180deg, color-mix(in srgb, var(--bg) 35%, transparent), transparent 20%);
  }
  /* CADA TEMA, SU FOTOGRAFÍA. Era una sola imagen con `filter:invert(1)`
     encima para el modo oscuro, y un negativo no es la misma escena de
     noche: la madera salía azul y el atardecer, cian. Ahora son dos
     tomas de la misma sala y sólo se enseña la que toca.

     La oscura NO se atenúa al 22% como se atenuaba el negativo: está
     hecha en penumbra, y bajarla más la dejaba en un rectángulo gris
     donde ya no se distinguía la sala. El velo de `.login-fade` es el
     que la deja pasar a la tarjeta. */
  .login-bg.oscuro{display:none}
  :root[data-theme="dark"] .login-bg.claro{display:none}
  :root[data-theme="dark"] .login-bg.oscuro{display:block;opacity:.85}
  @media (prefers-color-scheme: dark){
    :root:not([data-theme="light"]):not([data-theme="concreto"]) .login-bg.claro{display:none}
    :root:not([data-theme="light"]):not([data-theme="concreto"]) .login-bg.oscuro{display:block;opacity:.85}
  }
  /* THE VEIL WINS OVER THE THEME. The dark rules above are more specific
     than `html.con-sesion .login>*`, so with a remembered session on a
     dark phone the night photograph was painted on every refresh until
     the server answered — the one thing the veil exists to prevent.
     Written after them and heavier than them on purpose. */
  html.con-sesion .login>.login-bg.claro,
  html.con-sesion .login>.login-bg.oscuro{display:none}
  .login-inner{
    position:relative;min-height:100vh;
    display:flex;align-items:center;justify-content:center;gap:44px;
    padding:40px 28px;flex-wrap:wrap;
  }
  .login-card{
    width:min(440px,94vw);
    background:var(--glass-strong);
    -webkit-backdrop-filter:var(--blur);backdrop-filter:var(--blur);
    border:1px solid var(--edge);border-radius:26px;box-shadow:var(--shadow-lift);
    padding:34px 36px 30px;
  }
  .login-brand{display:flex;align-items:center;gap:11px;margin-bottom:26px}
  .login-brand .bn{font-size:16px;font-weight:800;letter-spacing:-.01em;line-height:1.15;display:block}
  .login-brand .by{font-size:10.5px;color:var(--muted);font-weight:600;letter-spacing:.02em;display:block}
  .login-card h1{font-size:28px;font-weight:800;letter-spacing:-.03em;line-height:1.15}
  .login-card .lsub{color:var(--muted);font-size:13.5px;margin:6px 0 24px}
  .fld{margin-bottom:16px}
  .fld label{display:block;font-size:12px;font-weight:700;margin-bottom:7px}
  .fld .fwrap{position:relative}
  .fld input{
    width:100%;padding:12px 14px;border-radius:14px;
    border:1px solid var(--line-strong);background:var(--card-solid);
    font:inherit;font-size:13.5px;color:var(--ink);
    transition:border-color 150ms ease, box-shadow 150ms ease;
  }
  .fld input:focus{outline:none;border-color:var(--ink);box-shadow:0 0 0 3px var(--gray-soft)}
  .fld input::placeholder{color:var(--faint)}
  .eye{
    position:absolute;right:8px;top:50%;transform:translateY(-50%);
    width:32px;height:32px;border-radius:10px;display:flex;align-items:center;justify-content:center;color:var(--muted);
  }
  .eye:hover{background:var(--gray-soft);color:var(--ink)}
  .eye svg{width:16px;height:16px}
  /* EVERY WARNING ON THE DOOR LOOKS THE SAME: light gray, and the only
     red is the dot. No tinted card and no red edge — the dot is enough
     to say "this needs you", and the copy says what. */
  .lg-err{
    display:flex;align-items:flex-start;gap:11px;
    color:var(--ink);background:var(--gray-soft);
    border:0;border-radius:12px;padding:12px 14px;margin:-2px 0 16px;
    animation:errIn .34s cubic-bezier(.23,1,.32,1) both;
  }
  .lg-err-mark{
    width:20px;height:20px;flex:none;border-radius:50%;margin-top:1px;
    background:var(--card-solid);position:relative;
  }
  .lg-err-mark::after{content:"";position:absolute;width:5px;height:5px;border-radius:50%;background:var(--red);inset:0;margin:auto}
  .lg-err-copy{display:grid;gap:2px;min-width:0}
  .lg-err-copy strong{font-size:11.5px;font-weight:700;line-height:1.35;color:var(--ink)}
  .lg-err-copy>span{font-size:11px;font-weight:500;line-height:1.45;color:var(--muted)}
  @keyframes errIn{from{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:none}}
  /* a notice, not a warning (the session ended): the same card with the
     brand's dot instead of the red one */
  .lg-err.info .lg-err-mark::after{background:var(--cta)}
  .lg-err.info.alerta .lg-err-mark::after{background:var(--red)}
  /* approving a document is the client's signature */
  body.no-approve [data-approve]{display:none}
  .login-btn{
    position:relative;width:100%;padding:14px;border-radius:16px;
    background:var(--black);color:var(--on-black);font-size:14px;font-weight:700;
    display:flex;align-items:center;justify-content:center;
    transition:transform 160ms var(--eo), opacity 150ms ease;
  }
  .login-btn:hover{opacity:.88}
  .login-btn:active{transform:scale(.98)}
  .login-btn svg{position:absolute;right:18px;width:17px;height:17px}
  .login-help{text-align:center;font-size:12px;color:var(--muted);margin-top:18px}
  /* El `button` va con la `a`: la salida de esta tarjeta era un botón sin
     una sola señal de serlo, gris sobre gris al final de la frase del
     mínimo de caracteres, y quien se había quedado encerrado la leía como
     parte del texto. Una salida que no se ve no es una salida. */
  .login-help a,.login-help button{
    color:var(--ink-soft);font-weight:700;text-decoration:underline;text-underline-offset:3px;cursor:pointer;
  }
  .login-help a:hover,.login-help button:hover{color:var(--ink)}
  /* y la de irse, en su propio renglón: no es una coletilla de la regla
     de los diez caracteres */
  .login-help #pw-otra{display:block;margin:12px auto 0;font-size:12.5px}

  .login-preview{
    width:330px;background:var(--card-solid);border:1px solid var(--edge);border-radius:20px;
    box-shadow:var(--shadow-lift);padding:20px 22px;position:relative;
  }
  .login-preview .pj{font-size:14px;color:var(--muted);font-weight:600}
  .login-preview .pj b{color:var(--ink);font-weight:800;font-size:15px}
  .login-preview .al{font-size:11px;color:var(--muted);font-weight:600;margin-top:14px}
  .login-preview .pct{font-size:28px;font-weight:800;letter-spacing:-.02em;font-variant-numeric:tabular-nums}
  .lp-bar{height:3px;border-radius:99px;background:var(--gray-soft);margin-top:10px;position:relative}
  .lp-bar i{position:absolute;left:0;top:0;bottom:0;border-radius:99px;background:var(--amber)}
  .lp-bar em{position:absolute;top:50%;transform:translate(-50%,-50%);width:7px;height:7px;border-radius:50%;background:var(--amber);border:2px solid var(--card-solid)}
  .lp-stats{display:flex;margin-top:18px;padding-top:14px;border-top:1px solid var(--line)}
  .lp-stats > div{flex:1;display:flex;align-items:flex-start;gap:7px}
  .lp-stats > div + div{border-left:1px solid var(--line);padding-left:12px}
  .lp-stats svg{width:14px;height:14px;color:var(--muted);margin-top:2px;flex:none}
  .lp-stats .n{font-size:13px;font-weight:800;font-variant-numeric:tabular-nums;line-height:1.2}
  .lp-stats .l{font-size:10.5px;color:var(--muted);font-weight:600}
  @media (max-width:900px){
    .login-bg{width:100%;opacity:.5}
    .login-preview{display:none}
  }

/* ───────── config modal ───────── */
  .cfg-wrap{
    position:fixed;inset:0;z-index:55;display:flex;align-items:center;justify-content:center;
    padding:20px;opacity:0;pointer-events:none;transition:opacity 220ms var(--eo);
  }
  .cfg-wrap::before{content:"";position:absolute;inset:0;background:var(--overlay)}
  .cfg-wrap.open{opacity:1;pointer-events:auto}
  .cfg.sm{width:min(400px,94vw)}
  .cfg{
    position:relative;width:min(440px,94vw);max-height:calc(100vh - 40px);overflow:auto;
    background:var(--glass-strong);
    -webkit-backdrop-filter:var(--blur);backdrop-filter:var(--blur);
    border:1px solid var(--edge);border-radius:24px;box-shadow:var(--shadow-lift);
    padding:24px 26px 22px;
    transform:scale(.96);transition:transform 220ms var(--eo);
  }
  .cfg-wrap.open .cfg{transform:none}
  .cfg h2{font-size:17px;font-weight:800;letter-spacing:-.01em}
  .cfg .who{display:flex;align-items:center;gap:13px;margin:18px 0;padding:14px;border:1px solid var(--line);border-radius:16px;background:var(--card)}
  .cfg .who .pavatar{width:44px;height:44px;border-radius:14px;font-size:13px}
  .cfg .who .nm{font-size:13.5px;font-weight:800}
  .cfg .who .rl{font-size:11.5px;color:var(--muted);font-weight:600}
  .cfg .who .em{font-size:11px;color:var(--faint);font-weight:600}
  .cfg-sec{margin-bottom:18px}
  .cfg-sec .t{font-size:10px;font-weight:800;letter-spacing:.11em;text-transform:uppercase;color:var(--muted);margin-bottom:10px}
  .cfg-row{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:10px 2px}
  .cfg-row + .cfg-row{border-top:1px solid var(--line)}
  .cfg-row .lab{font-size:13px;font-weight:600}
  .cfg-row .sub{font-size:11px;color:var(--muted);font-weight:500;margin-top:1px}
  /* four themes do not fit beside the label on a phone: the control
     goes under it, full width, the four sharing it evenly */
  @media (max-width:560px){
    .cfg-row:has(#theme-seg){flex-direction:column;align-items:stretch;gap:8px}
    #theme-seg button{flex:1;padding-left:4px;padding-right:4px}
  }
  .sw{
    width:40px;height:23px;border-radius:99px;flex:none;position:relative;
    background:var(--gray-soft);border:1px solid var(--line-strong);
    transition:background 200ms ease,border-color 200ms ease;cursor:pointer;
  }
  .sw i{
    position:absolute;top:2px;left:2px;width:17px;height:17px;border-radius:50%;
    background:var(--card-solid);box-shadow:0 1px 3px rgba(0,0,0,.2);
    transition:transform 200ms var(--eo);
  }
  .sw.on{background:var(--green);border-color:transparent}
  .sw.on i{transform:translateX(17px)}
  .cfg-foot{display:flex;gap:10px;margin-top:22px}
  /* the studio's signature under Configuración. The mark is a mask so it
     takes the text colour in every theme; «SIN» is the one part of the
     name in ink, as the studio writes it */
  .cfg-firma{
    display:flex;align-items:center;justify-content:center;gap:10px;margin:18px -4px -6px;padding:8px 0 2px;
    border-top:1px solid var(--line);color:var(--muted);text-decoration:none;
  }
  .cf-by{font-size:10.5px;font-weight:600;letter-spacing:.01em;white-space:nowrap}
  .cf-mark{
    width:16px;height:24px;flex:none;background:currentColor;opacity:.8;
    -webkit-mask:url("../brand/sintropia-mark.png") center / contain no-repeat;mask:url("../brand/sintropia-mark.png") center / contain no-repeat;
  }
  .cf-name{font-size:10.5px;font-weight:500;letter-spacing:.32em;white-space:nowrap}
  .cf-name b{color:var(--ink);font-weight:700}
  .cfg-firma:hover .cf-name,.cfg-firma:hover .cf-by{color:var(--ink-soft)}
  /* one line on a phone too: the name's tracking tightens rather than wrap */
  @media (max-width:420px){
    .cfg-firma{gap:7px}
    .cf-by{font-size:10px}
    .cf-name{font-size:10px;letter-spacing:.2em}
  }
  .cfg .dr-close{top:18px;right:18px}
  .btn.ghost-danger{background:var(--red-soft);color:var(--red-ink);flex:none;padding:11px 16px}

  /* ───────── Configuración as a tabbed panel ─────────
     A rail of sections on the left and one pane at a time on the right,
     at a fixed height so switching tabs never makes the window jump. On
     a phone the rail turns into a row of tabs on top and «Cerrar
     sesión» moves down to the foot, beside Listo. */
  .cfg.cfg-tabs{
    width:min(720px,95vw);height:min(540px,calc(100vh - 40px));padding:0;overflow:hidden;
    display:grid;grid-template-columns:200px minmax(0,1fr);
  }
  .cfg-nav{
    display:flex;flex-direction:column;gap:4px;padding:24px 14px 18px;
    border-right:1px solid var(--line);background:color-mix(in srgb, var(--ink) 3%, transparent);
  }
  .cfg-nav h2{padding:0 10px;margin-bottom:14px}
  .cfg-tablist{display:flex;flex-direction:column;gap:2px}
  .cfg-tab,.cfg-out{
    display:flex;align-items:center;gap:10px;padding:9px 10px;border-radius:12px;
    font-size:13px;font-weight:600;text-align:left;transition:background 160ms ease,color 160ms ease;
  }
  .cfg-tab{color:var(--muted)}
  .cfg-tab svg,.cfg-out svg{width:17px;height:17px;flex:none}
  .cfg-tab:hover{background:var(--gray-soft);color:var(--ink)}
  .cfg-tab.on{background:var(--card-solid);color:var(--ink);box-shadow:0 1px 2px rgba(0,0,0,.06),inset 0 0 0 1px var(--line)}
  .cfg-out{margin-top:auto;color:var(--red-ink)}
  .cfg-out:hover{background:var(--red-soft)}
  .cfg-main{display:flex;flex-direction:column;min-height:0;overflow:auto;padding:24px 26px 18px}
  .cfg-pane h3{font-size:17px;font-weight:800;letter-spacing:-.01em;margin-bottom:4px}
  .cfg-lead{font-size:12px;color:var(--muted);font-weight:500;margin-bottom:14px}
  /* FLAT, NOT BOXED. White cards inside the white panel read as empty
     placeholders: the groups are rows on hairlines, and the profile is
     the avatar beside its lines, the way a settings page reads. */
  .cfg-group{border-top:1px solid var(--line);border-bottom:1px solid var(--line);padding:0}
  .cfg-group .cfg-row{padding:12px 2px}
  .cfg-pane .who{
    display:grid;grid-template-columns:auto minmax(0,1fr);column-gap:16px;row-gap:1px;align-items:center;
    margin:14px 0 18px;padding:0;border:0;background:none;text-align:left;
  }
  .cfg-pane .who .pavatar{grid-row:1/5;width:64px;height:64px;border-radius:20px;font-size:19px}
  .cfg-pane .who .nm{font-size:16px}
  .cfg-pane .who .em{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .cfg-hint{font-size:10.5px;color:var(--faint);font-weight:600;margin-top:4px}
  /* «Listo» closes a panel; it is not the panel's purpose: a small pill
     on the right, not a bar across the whole width */
  /* one closing line: the studio's signature on the left, «Listo» on the
     right (owner, 13 October 2026) */
  .cfg-tabs .cfg-foot{margin-top:auto;padding-top:12px;justify-content:space-between;align-items:center;border-top:1px solid var(--line)}
  .cfg-tabs .cfg-foot .btn.primary{flex:none;min-width:0;padding:9px 22px;font-size:13px;border-radius:99px}
  .cfg-out-foot{display:none}
  .cfg-tabs .cfg-foot .cfg-firma{margin:0;padding:0;border-top:none;justify-content:flex-start;min-width:0}
  @media (max-width:640px){
    .cfg.cfg-tabs{grid-template-columns:minmax(0,1fr);grid-template-rows:auto minmax(0,1fr);height:min(640px,calc(100vh - 24px))}
    .cfg-nav{border-right:none;border-bottom:1px solid var(--line);padding:18px 14px 10px}
    .cfg-nav h2{margin-bottom:10px}
    /* the tabs share the row: four (three without Obra) fit at 375 px */
    .cfg-tablist{flex-direction:row;gap:4px}
    .cfg-tab{flex:1 1 0;min-width:0;justify-content:center;gap:6px;padding:8px 4px;font-size:12.5px}
    .cfg-tab svg{width:15px;height:15px}
    .cfg-out{display:none}
    .cfg-out-foot{display:inline-flex}
    .cfg-main{padding:18px 18px 14px}
    /* the phone's row already holds «Cerrar sesión» and «Listo»: the
       signature takes its own line under them */
    .cfg-tabs .cfg-foot{flex-wrap:wrap;row-gap:10px}
    .cfg-tabs .cfg-foot .cfg-firma{order:3;flex-basis:100%;justify-content:center}
  }
  .btn.ghost-danger:hover{opacity:.85}
  .btn.ghost-danger.armed{background:var(--red);color:#fff}

  /* ───────── resumen: one-view lock (desktop) ───────── */
  @media (min-width:1000px){
    body.lock{overflow:hidden;height:100vh}
    body.lock .content{height:100vh;overflow:hidden;display:flex;flex-direction:column;padding-bottom:14px}
    body.lock #page-resumen{display:flex;flex-direction:column;flex:1;min-height:0}
    body.lock #page-resumen .hero{flex:none}
    body.lock #page-resumen .cols{flex:1;min-height:0;overflow:hidden;align-items:stretch}
    body.lock .maincol{display:flex;flex-direction:column;min-height:0;overflow-y:auto;gap:14px;scrollbar-width:none}
    body.lock .maincol::-webkit-scrollbar{display:none}
    /* by class, not :first-child: the check-in host sits above it now */
    body.lock .maincol > .chart-card{flex:1;min-height:230px;display:flex;flex-direction:column}
    body.lock .maincol > .chart-card .chart-wrap{flex:1;min-height:120px}
    body.lock .maincol > .chart-card canvas{height:100%!important}
    body.lock .sidecol{display:flex;flex-direction:column}
    body.lock .sidecol #areas{flex:1;min-height:0;display:flex;flex-direction:column}
    body.lock .sidecol .areas-panel{flex:1;min-height:0;overflow:hidden}
    body.lock .pulse-head,body.lock .pulse{flex:none}
    body.lock .sidecol{min-height:0;overflow-y:auto;padding-right:3px;scrollbar-width:thin;scrollbar-color:var(--line-strong) transparent}
    body.lock .sidecol::-webkit-scrollbar{width:6px}
    body.lock .sidecol::-webkit-scrollbar-thumb{background:var(--line-strong);border-radius:99px}
    body.lock .sidecol::-webkit-scrollbar-track{background:transparent}
    body.lock .side-title{position:sticky;top:0;z-index:2;background:var(--bg);margin:0;padding:4px 4px 8px}
  }

  /* ───────── pulse of the obra ───────── */
  .pulse-head{margin-top:2px}
  .health{display:flex;gap:9px;align-items:flex-start}
  .health i{width:8px;height:8px;border-radius:50%;flex:none;margin-top:5px}
  .health .h1{font-size:12.5px;font-weight:700}
  .health .h2{font-size:11px;color:var(--muted);font-weight:500}
  .pulse{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px}
  @media (max-width:1080px){.pulse{grid-template-columns:repeat(2,minmax(0,1fr))}}
  @media (max-width:640px){.pulse{grid-template-columns:1fr}}
  .pcard{padding:12px 14px 11px;display:flex;flex-direction:column;min-width:0}
  .pcard .ph{font-size:9.5px;font-weight:800;letter-spacing:.12em;text-transform:uppercase;color:var(--faint);margin-bottom:6px}
  .pcard .big{font-size:13px;font-weight:800;line-height:1.3;letter-spacing:-.01em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .pcard .num{font-size:20px;font-weight:800;line-height:1;font-variant-numeric:tabular-nums}
  .pcard .num + .big{margin-top:4px!important;font-size:12.5px!important}
  .pcard .mut{font-size:11px;color:var(--muted);font-weight:600;margin-top:2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .pcard .meter{margin-top:auto;padding-top:8px}
  .pcard .meter-row{display:flex;align-items:center;gap:9px;margin-top:auto;padding-top:8px}
  .pcard .meter-row .meter{flex:1;padding:0;margin:0}
  .pcard .meter-row .pctv{font-size:11px;font-weight:800;font-variant-numeric:tabular-nums;color:var(--muted)}
  .p-link{
    display:flex;align-items:center;gap:6px;margin-top:auto;padding-top:8px;
    font-size:11.5px;font-weight:700;color:var(--amber-ink);
  }
  .p-link svg{width:13px;height:13px;transition:transform 160ms var(--eo)}
  .p-link:hover svg{transform:translateX(2px)}
  .pev{display:flex;gap:10px;align-items:center;cursor:pointer;min-width:0}
  .pev > span{min-width:0}
  .pev img{width:44px;height:44px;border-radius:10px;object-fit:cover;flex:none;box-shadow:var(--shadow)}
  .pev .t{font-size:12.5px;font-weight:700;line-height:1.3;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
  .pev .s{font-size:11px;color:var(--muted);font-weight:600;margin-top:3px;display:flex;align-items:center;gap:5px}
  .pev .s svg{width:12px;height:12px;color:var(--green)}
  .pact{display:flex;flex-direction:column;gap:5px}
  .pact .r{display:flex;align-items:center;gap:8px;font-size:11.5px;color:var(--ink-soft);font-weight:600;min-width:0}
  .pact .r span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .pact .r .mi{width:22px;height:22px;border-radius:7px;display:flex;align-items:center;justify-content:center;flex:none;background:var(--gray-soft)}
  .pact .r .mi svg{width:11px;height:11px}
  .chips-row{display:flex;flex-wrap:wrap;gap:7px}
  .chip-opt{
    display:flex;align-items:center;gap:7px;
    padding:7px 13px;border:1px solid var(--line-strong);border-radius:99px;
    font-size:12px;font-weight:600;color:var(--ink-soft);
    transition:background 150ms ease,color 150ms ease,border-color 150ms ease,transform 160ms var(--eo);
  }
  .chip-opt:active{transform:scale(.96)}
  .chip-opt i{width:7px;height:7px;border-radius:50%;flex:none}
  .chip-opt.sel{background:var(--black);color:var(--on-black);border-color:transparent}
  .fld select{
    width:100%;padding:12px 14px;border-radius:14px;
    border:1px solid var(--line-strong);background:var(--card-solid);
    font:inherit;font-size:13px;color:var(--ink);appearance:none;
    background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%23888' stroke-width='2'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
    background-repeat:no-repeat;background-position:right 12px center;
  }
  .fld select:focus{outline:none;border-color:var(--ink)}
  .nt-err{display:none;color:var(--red-ink);font-size:11.5px;font-weight:600;margin-top:6px}
  .nt-err.show{display:block}
  /* uploads in progress (ui/subidas.js): bottom right, above the page */
  @keyframes sb-in{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
  .subidas{
    position:fixed;right:20px;bottom:20px;z-index:60;width:min(340px,calc(100vw - 32px));
    padding:12px 14px 6px;border-radius:18px;
    /* nearly solid: whatever page sits under it must not read through */
    background:color-mix(in srgb, var(--card-solid) 96%, transparent);-webkit-backdrop-filter:var(--blur);backdrop-filter:var(--blur);
    border:1px solid var(--edge);box-shadow:var(--shadow-lift);animation:sb-in 200ms var(--eo);
    transition:opacity 200ms ease,transform 200ms ease;
  }
  .subidas.bye{opacity:0;transform:translateY(10px)}
  .sb-h{display:flex;align-items:center;gap:8px;margin-bottom:6px}
  .sb-h b{flex:1;font-size:13px;font-weight:800;letter-spacing:-.01em}
  .sb-h span{font-size:11px;font-weight:700;color:var(--muted);font-variant-numeric:tabular-nums}
  .sb-x{width:26px;height:26px;border-radius:8px;display:flex;align-items:center;justify-content:center;color:var(--muted)}
  .sb-x:hover{background:var(--gray-soft);color:var(--ink)}
  .sb-x svg{width:13px;height:13px}
  .sb-f{display:flex;gap:10px;padding:8px 0;border-top:1px solid var(--line)}
  .sb-f:first-of-type{border-top:0}
  .sb-ic{width:28px;height:28px;border-radius:8px;flex:none;display:flex;align-items:center;justify-content:center;background:var(--gray-soft);font-size:8.5px;font-weight:800;color:var(--ink-soft)}
  .sb-m{flex:1;min-width:0}
  .sb-n{display:flex;align-items:center;gap:8px;font-size:12px;font-weight:700;color:var(--ink)}
  .sb-n span{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .sb-n em{font-style:normal;font-size:11px;font-weight:800;font-variant-numeric:tabular-nums;color:var(--ink-soft);display:flex}
  .sb-n em svg{width:14px;height:14px;color:var(--green)}
  .sb-bar{height:5px;border-radius:99px;background:color-mix(in srgb, var(--ink) 10%, transparent);overflow:hidden;margin:6px 0 4px}
  .sb-bar i{display:block;height:100%;border-radius:99px;background:var(--progress);transition:width 160ms linear}
  :root[data-theme="concreto"] .sb-bar i{background:#6B7A6F}
  .sb-f.listo .sb-bar i{background:var(--green)}
  .sb-f.error .sb-bar{display:none}
  .sb-d{font-size:10.5px;font-weight:600;color:var(--muted);font-variant-numeric:tabular-nums}
  .sb-f.error .sb-d{color:var(--red-ink);margin-top:3px}
  .sb-f.espera .sb-n{color:var(--muted)}
  .sb-re{font-size:11px;font-weight:700;padding:4px 10px;border-radius:99px;background:var(--gray-soft);color:var(--ink)}
  .sb-re:hover{background:var(--line-strong)}
  /* on a phone it sits above the dock, the full width */
  @media (max-width:760px){
    .subidas{left:16px;right:16px;width:auto;bottom:calc(92px + env(safe-area-inset-bottom))}
  }
  /* signing an approval, and asking for changes (ui/firma.js) */
  .fi-l{display:block;font-size:12px;font-weight:700;margin:0 0 6px}
  .fi-in{width:100%;padding:11px 13px;border-radius:12px;border:1px solid var(--line-strong);background:var(--card-solid);font:inherit;font-size:14px;color:var(--ink);resize:vertical}
  .fi-in:focus{outline:none;border-color:var(--ink);box-shadow:0 0 0 3px var(--gray-soft)}
  textarea.fi-in{margin-bottom:12px}
  .fi-pad{position:relative;height:96px;margin:10px 0 4px;border-radius:12px;background:var(--gray-soft);display:flex;align-items:flex-end;padding:0 16px 22px;overflow:hidden}
  .fi-pad::after{content:"";position:absolute;left:16px;right:16px;bottom:20px;border-bottom:1px solid var(--line-strong);pointer-events:none}
  .fi-pad.dibujo{height:150px;padding:0;margin-top:0;touch-action:none}
  .fi-pad canvas{position:absolute;inset:0;width:100%;height:100%;color:var(--ink);cursor:crosshair}
  .fi-guia{position:absolute;left:18px;bottom:28px;font-size:12px;font-weight:600;color:var(--faint);pointer-events:none}
  .fi-borrar{margin-top:6px}
  .fi-script{font-family:"Snell Roundhand","Segoe Script","Brush Script MT","Apple Chancery",cursive;font-size:30px;line-height:1.1;color:var(--ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}
  .fi-ok{display:flex;gap:9px;align-items:flex-start;margin:14px 0 14px;font-size:12px;font-weight:600;color:var(--ink-soft);cursor:pointer}
  .fi-ok input{width:16px;height:16px;flex:none;margin-top:1px;accent-color:var(--black)}
  :root[data-theme="concreto"] .fi-ok input{accent-color:#6B7A6F}
  /* the signature in the thread, under «Aprobado por …» */
  .hilo-firma{
    margin:-2px auto 14px;padding:2px 22px 4px;border-bottom:1px solid var(--line-strong);
    width:max-content;max-width:85%;text-align:center;text-transform:none;letter-spacing:0;
  }
  .hilo-firma .fi-script{display:block;font-size:26px}
  .hilo-firma img{display:block;max-width:220px;max-height:70px}
  /* administration's side of a pending round: who it is waiting for */
  .hilo-espera{flex:1;font-size:12px;font-weight:600;color:var(--muted)}
  /* while somebody writes, or a draft waits to be sent, the decisions
     step aside: «Enviar» is the only button in reach */
  .hilo-pie:has(.hilo-escribe.con-texto) .hilo-acts,
  .hilo-cuerpo:has(.hilo-msg.borrador) ~ .hilo-pie .hilo-acts{display:none}
  /* who can see a document (ui/doc-acceso.js) */
  .acc-seg{display:flex;gap:2px;padding:3px;border-radius:99px;background:var(--gray-soft);margin-bottom:14px}
  .acc-seg button{flex:1;padding:8px 0;border-radius:99px;font-size:12.5px;font-weight:600;color:var(--ink-soft);transition:background 140ms ease,color 140ms ease}
  .acc-seg button.on{background:var(--black);color:var(--on-black)}
  :root[data-theme="concreto"] .acc-seg button.on{background:#6B7A6F;color:#FFFFFF}
  .acc-panel{margin-bottom:14px}
  .acc-nota{font-size:12.5px;color:var(--muted)}
  .acc-lista{max-height:260px;overflow:auto;margin:0 -4px;padding:0 4px}
  .acc-ck{display:flex;align-items:center;gap:10px;padding:9px 2px;border-bottom:1px solid var(--line);font-size:13px;font-weight:600;color:var(--ink);cursor:pointer}
  .acc-ck:last-child{border-bottom:0}
  .acc-ck input{width:17px;height:17px;flex:none;accent-color:var(--black)}
  :root[data-theme="concreto"] .acc-ck input{accent-color:#6B7A6F}
  .acc-ck small{display:block;font-size:11px;font-weight:600;color:var(--muted)}
  .acc-av{width:26px;height:26px;border-radius:50%;flex:none;display:flex;align-items:center;justify-content:center;background:#78847E;color:#FFFFFF;font-size:10px;font-weight:800}
  .acc-vacio{font-size:12.5px;color:var(--muted);padding:8px 0}
  /* the pill on a restricted row in Documentos */
  .doc-acc{display:inline-flex;align-items:center;gap:4px;flex:none;font-size:10.5px;font-weight:700;color:var(--card-solid);background:var(--ink-soft);border-radius:99px;padding:3px 8px;margin-left:6px;white-space:nowrap}
  .doc-acc svg{width:11px;height:11px}
  /* the password dialog (ui/cambio-pw.js) */
  .pw-sub{font-size:12px;color:var(--muted);margin:4px 0 18px}
  .pw-msg{color:var(--red-ink);font-size:12px;font-weight:600;margin:-4px 0 14px}

  /* delete an evidencia: discreet, only shows up on hover */
  .shot{position:relative}
  .shot .del{
    position:absolute;top:7px;right:7px;
    width:26px;height:26px;border-radius:9px;
    background:rgba(14,14,13,.55);color:#fff;
    display:flex;align-items:center;justify-content:center;
    opacity:0;transform:scale(.9);
    transition:opacity 150ms ease, transform 160ms var(--eo), background 150ms ease;
  }
  .shot .del svg{width:13px;height:13px}
  .shot .del:hover{background:var(--red)}
  .shot .del.armed{opacity:1;transform:none;background:var(--red);width:auto;padding:0 9px;font-size:10px;font-weight:800;gap:5px}
  @media (hover:hover) and (pointer:fine){ .shot:hover .del{opacity:1;transform:none} }
  @media (hover:none){ .shot .del{opacity:1;transform:none} }
  /* el pie de foto: el lápiz va a la izquierda del bote */
  .shot .edit{
    position:absolute;top:7px;right:38px;
    width:26px;height:26px;border-radius:9px;
    background:rgba(14,14,13,.55);color:#fff;
    display:flex;align-items:center;justify-content:center;
    opacity:0;transform:scale(.9);
    transition:opacity 150ms ease, transform 160ms var(--eo), background 150ms ease;
  }
  .shot .edit svg{width:13px;height:13px}
  .shot .edit:hover{background:var(--ink)}
  .shot.editing{outline:none;box-shadow:0 0 0 3px color-mix(in srgb, var(--ink) 25%, transparent)}
  @media (hover:hover) and (pointer:fine){ .shot:hover .edit{opacity:1;transform:none} }
  @media (hover:none){ .shot .edit{opacity:1;transform:none} }
  .cap-edit{display:flex;gap:6px;margin-top:8px}
  .cap-edit input{
    flex:1;min-width:0;padding:8px 11px;border-radius:10px;
    border:1px solid var(--line-strong);background:var(--card-solid);
    font:inherit;font-size:12px;color:var(--ink);
  }
  .cap-edit input:focus{outline:none;border-color:var(--ink);box-shadow:0 0 0 3px var(--gray-soft)}
  .cap-edit button{padding:0 11px;border-radius:10px;font-size:11.5px;font-weight:700;flex:none}
  .cap-edit .ok{background:var(--black);color:var(--on-black)}
  .cap-edit .ok:disabled{opacity:.5}
  .cap-edit .x{color:var(--muted)}
  .cap-edit .x:hover{background:var(--gray-soft);color:var(--ink)}
  .lbx-del{
    display:inline-flex;align-items:center;gap:6px;
    color:rgba(255,255,255,.72);font-size:11.5px;font-weight:700;
    padding:6px 12px;border-radius:99px;background:rgba(255,255,255,.1);
  }
  .lbx-del:hover{color:#fff;background:var(--red)}
  .lbx-del.armed{background:var(--red);color:#fff}
  .lbx-del svg{width:12px;height:12px}

  /* ───────── evidencia viewer (lightbox) ───────── */
  .lbx{
    position:fixed;inset:0;z-index:70;display:flex;align-items:center;justify-content:center;
    opacity:0;pointer-events:none;transition:opacity 200ms var(--eo);
  }
  .lbx::before{
    content:"";position:absolute;inset:0;background:rgba(14,14,13,.92);
    -webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);
  }
  .lbx.open{opacity:1;pointer-events:auto}
  .lbx-stage{
    position:relative;display:flex;flex-direction:column;align-items:center;gap:14px;
    max-width:min(1400px,94vw);
    transform:scale(.97);transition:transform 200ms var(--eo);
  }
  .lbx.open .lbx-stage{transform:none}
  .lbx-media{
    max-width:94vw;max-height:78vh;border-radius:14px;display:block;
    box-shadow:0 30px 80px rgba(0,0,0,.5);background:#0E0E0D;
  }
  .lbx-cap{
    display:flex;align-items:center;gap:12px;color:rgba(255,255,255,.92);
    font-size:12.5px;font-weight:600;max-width:94vw;
  }
  .lbx-cap .t{font-weight:800}
  .lbx-cap .m{color:rgba(255,255,255,.55);font-weight:600}
  .lbx-cap .n{
    margin-left:auto;color:rgba(255,255,255,.55);font-variant-numeric:tabular-nums;
    font-size:11.5px;font-weight:700;
  }
  .lbx-btn{
    position:absolute;top:50%;transform:translateY(-50%);
    width:46px;height:46px;border-radius:50%;
    background:rgba(255,255,255,.1);color:#fff;
    display:flex;align-items:center;justify-content:center;
    transition:background 150ms ease, transform 160ms var(--eo);
  }
  .lbx-btn:hover{background:rgba(255,255,255,.2)}
  .lbx-btn:active{transform:translateY(-50%) scale(.94)}
  .lbx-btn svg{width:20px;height:20px}
  .lbx-prev{left:-64px}
  .lbx-next{right:-64px}
  .lbx-close{
    position:fixed;top:18px;right:18px;width:42px;height:42px;border-radius:14px;
    background:rgba(255,255,255,.1);color:#fff;display:flex;align-items:center;justify-content:center;
    transition:background 150ms ease;
  }
  .lbx-close:hover{background:rgba(255,255,255,.2)}
  .lbx-close svg{width:18px;height:18px}
  .lbx-dl{
    display:inline-flex;align-items:center;gap:6px;color:rgba(255,255,255,.72);
    font-size:11.5px;font-weight:700;padding:6px 12px;border-radius:99px;
    background:rgba(255,255,255,.1);
  }
  .lbx-dl:hover{color:#fff;background:rgba(255,255,255,.18)}
  .lbx-dl svg{width:12px;height:12px}
  @media (max-width:900px){
    .lbx-prev{left:6px} .lbx-next{right:6px}
    .lbx-media{max-height:68vh}
  }
  @media (prefers-reduced-motion:reduce){
    .lbx,.lbx-stage{transition:none}
  }
  /* the photo in the detail card and in the gallery now opens */
  .shot{cursor:zoom-in}
  .ev-card{cursor:zoom-in}


  /* ───────── demo window ───────── */
  .ses{
    position:fixed;left:88px;bottom:22px;z-index:38;   /* left of the drawer; below scrims and modals */
    display:flex;align-items:center;gap:8px;
    padding:8px 13px 8px 11px;border-radius:13px;
    background:var(--glass-strong);border:1px solid var(--edge);box-shadow:var(--shadow);
    -webkit-backdrop-filter:var(--blur);backdrop-filter:var(--blur);
    font-size:11.5px;font-weight:700;color:var(--muted);letter-spacing:.01em;
    transition:color 200ms ease, border-color 200ms ease;
  }
  .ses i{width:7px;height:7px;border-radius:50%;background:var(--green);flex:none}
  .ses b{font-variant-numeric:tabular-nums;color:var(--ink);font-weight:800}
  .ses.warn i{background:var(--amber)}
  .ses.crit i{background:var(--red);animation:sespulse 1s var(--eo) infinite}
  .ses.crit b{color:var(--red-ink)}
  @keyframes sespulse{50%{opacity:.25}}
  @media (max-width:760px){.ses{bottom:96px;left:14px}}
  @media (prefers-reduced-motion:reduce){.ses.crit i{animation:none}}

  .slock{
    position:fixed;inset:0;z-index:200;display:grid;place-items:center;padding:28px;
    background:color-mix(in srgb, var(--bg) 72%, transparent);
    -webkit-backdrop-filter:saturate(1.1) blur(16px);backdrop-filter:saturate(1.1) blur(16px);
    opacity:0;transition:opacity 420ms var(--eo);
  }
  .slock.show{opacity:1}
  .slock-card{
    width:min(420px,100%);text-align:center;
    background:var(--glass-strong);border:1px solid var(--edge);border-radius:24px;
    box-shadow:var(--shadow-lift);padding:34px 34px 28px;
    transform:translateY(10px) scale(.985);transition:transform 480ms var(--eo);
  }
  .slock.show .slock-card{transform:none}
  .slock-card .mk{
    width:50px;height:50px;margin:0 auto 20px;border-radius:16px;
    border:1px solid var(--edge);display:grid;place-items:center;color:var(--ink-soft);
  }
  .slock-card .mk svg{width:23px;height:23px}
  .slock-card h2{font-size:21px;font-weight:800;letter-spacing:-.03em;margin-bottom:9px}
  .slock-card p{font-size:13.5px;line-height:1.6;color:var(--muted);margin:0 auto;max-width:32ch}
  .slock-card .btn{margin:22px auto 0;flex:none;min-width:170px}
  @media (prefers-reduced-motion:reduce){
    .slock,.slock-card{transition:none}
  }

  /* ───────── toast ───────── */
  .toast{
    position:fixed;bottom:30px;left:50%;transform:translate(-50%,16px);z-index:80;
    background:var(--black);color:var(--on-black);border-radius:14px;padding:12px 18px;
    display:flex;align-items:center;gap:10px;font-size:12.5px;font-weight:600;
    box-shadow:var(--shadow-lift);opacity:0;pointer-events:none;transition:opacity .25s,transform .25s;
    max-width:min(480px,90vw);
  }
  .toast.show{opacity:1;transform:translate(-50%,0)}
  .toast i{width:9px;height:9px;border-radius:50%;flex:none}
  .toast.err i{background:var(--red)}
  .toast.ok i{background:var(--green)}
  .toast.info i{background:var(--amber)}

  @media (max-width:980px){
    .hero h1{font-size:26px}
  }

  /* `.op-empty` sobrevive a Operaciones: es el "aquí no hay nada" que
     usan el portafolio y Documentos. El resto de esta sección —
     tablas de movimientos, barras por rubro, el saldo en la cabecera,
     el chip del importe en la tarjeta y en la barra del cronograma —
     se fue con el dinero. */
  .op-empty{padding:26px 20px;color:var(--faint);font-size:12.5px;font-weight:600;text-align:center}

  /* ───────── portfolio of obras ───────── */
  .pf-list{display:grid;grid-template-columns:repeat(auto-fill,minmax(316px,1fr));gap:14px}
  .pf-card{
    padding:20px 22px;cursor:pointer;text-align:left;
    transition:box-shadow 180ms var(--eo),transform 180ms var(--eo);
  }
  @media (hover:hover) and (pointer:fine){
    .pf-card:hover{box-shadow:var(--shadow-lift);transform:translateY(-2px)}
  }
  .pf-card.now{border-color:var(--line-strong)}
  .pf-card:focus-visible{outline:none;box-shadow:0 0 0 3px color-mix(in srgb, var(--ink) 16%, transparent), var(--shadow)}
  .pf-head{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}
  .pf-n{font-size:14.5px;font-weight:800;letter-spacing:-.015em;line-height:1.25}
  .pf-c{font-size:11.5px;color:var(--muted);font-weight:600;margin-top:3px}
  .pf-now{
    font-size:9px;font-weight:800;letter-spacing:.1em;text-transform:uppercase;flex:none;
    color:var(--green-ink);background:var(--green-soft);padding:4px 9px;border-radius:99px;
  }
  /* administration's «⋯» on each card, and the «Inactivas» section (0043) */
  .pf-head > div:first-child{flex:1;min-width:0}
  .pf-mas{
    flex:none;width:30px;height:30px;margin:-5px -8px 0 0;border-radius:9px;display:grid;place-items:center;
    font-size:16px;font-weight:800;line-height:1;color:var(--muted);transition:background 120ms ease,color 120ms ease;
  }
  .pf-mas:hover{background:var(--gray-soft);color:var(--ink)}
  .pf-sec{grid-column:1 / -1;margin:14px 2px 0;font-size:10.5px;font-weight:800;letter-spacing:.1em;text-transform:uppercase;color:var(--faint)}
  .pf-card.inactiva{opacity:.62;filter:saturate(.4)}
  .pf-card.inactiva:hover{opacity:.85}
  .pf-menu .peligro{color:var(--red-ink)}
  .pf-menu-nota{display:block;padding:8px 11px;font-size:11px;font-weight:600;color:var(--faint)}
  .pf-bar{height:6px;border-radius:99px;background:var(--gray-soft);overflow:hidden;margin:16px 0 10px}
  .pf-bar i{display:block;height:100%;background:var(--progress);border-radius:99px}
  .pf-meta{display:flex;flex-wrap:wrap;gap:12px;font-size:11px;color:var(--muted);font-weight:600}
  .pf-pct{color:var(--ink);font-weight:800;font-variant-numeric:tabular-nums}
  .pf-money{
    display:flex;align-items:baseline;gap:9px;margin-top:14px;padding-top:12px;
    border-top:1px solid var(--line);
  }
  .pf-money .k{font-size:9.5px;font-weight:800;letter-spacing:.12em;text-transform:uppercase;color:var(--faint)}
  .pf-money b{font-size:15px;font-weight:800;font-variant-numeric:tabular-nums;color:var(--green-ink)}
  .pf-money b.neg{color:var(--red-ink)}
  .pf-money .g{margin-left:auto;font-size:10.5px;color:var(--faint);font-weight:600;font-variant-numeric:tabular-nums}

  /* ───────── obra picker ("Avance" header) ─────────
     The name is the button: same weight and colour as the text it
     replaces, plus a chevron. No box around it — a title that happens
     to be interactive, not a control smuggled into a title. */
  .proj-btn{
    display:inline-flex;align-items:center;gap:5px;padding:2px 6px;margin:-2px -6px;
    border-radius:9px;color:var(--ink);font:inherit;font-size:13px;
    transition:background 140ms ease;
  }
  .proj-btn b{font-weight:700}
  .proj-btn .chev{width:13px;height:13px;color:var(--muted)}
  @media (hover:hover) and (pointer:fine){ .proj-btn:hover{background:var(--gray-soft)} }
  .dd-left .dd-menu{left:0;right:auto;transform-origin:top left;min-width:280px}
  .dd-item.sel{color:var(--ink);font-weight:700}
  .dd-sep{height:1px;background:var(--line);margin:5px 6px}
  .dd-all{color:var(--muted);font-size:11.5px}

  /* ───────── "elegir obra" mode ─────────
     With no obra open, the obra's rail makes no sense: everything that
     belongs to an obra is withdrawn (Avance, Tablero, Cronograma,
     Evidencias, Documentos) and what stays is the logo,
     the list and who signed in. Same shell: nothing unmounts, it just
     goes quiet. */
  body.choosing .nav-pill,
  body.choosing .mdock-btn[data-page]{display:none}

  .pf-hero{margin-bottom:26px}
  .pf-hero h1{font-size:40px}
  .pf-kicker{
    font-size:10px;font-weight:800;letter-spacing:.14em;text-transform:uppercase;
    color:var(--faint);margin-bottom:10px;
  }
  body.choosing .pf-list{grid-template-columns:repeat(auto-fill,minmax(340px,1fr));gap:16px}
  body.choosing .pf-card{padding:24px 26px}

  /* the picker sits ON the subtitle line: a <div> is a block and broke
     the sentence in two, stranding an orphan "·" at the start of the
     second line */
  #proj-switch .dd{display:inline-block;vertical-align:baseline}

  /* on the choose-an-obra screen there is nowhere for #btn-obras to go back to */
  body.choosing #btn-obras{display:none}

  /* ───────── portfolio modals ───────── */
  .nm-hint{font-size:11.5px;color:var(--muted);font-weight:500;margin-top:8px;line-height:1.45}
  /* admin-only bits: hidden here, and the server demands the role anyway */
  body:not(.is-admin) .admin-only{display:none}
  .nm-list{display:flex;flex-direction:column;gap:6px;margin-bottom:18px}
  .nm-row{
    display:flex;align-items:center;gap:12px;padding:9px 12px;
    border:1px solid var(--line);border-radius:14px;background:var(--gray-soft);
  }
  .nm-row i{
    width:30px;height:30px;border-radius:50%;flex:none;display:grid;place-items:center;
    font-style:normal;font-size:10.5px;font-weight:800;letter-spacing:.04em;
    background:var(--black);color:var(--on-black);
  }
  .nm-row .t{flex:1 1 auto;min-width:0}
  .nm-row b{display:block;font-size:13px;font-weight:800;letter-spacing:-.01em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .nm-row span{display:block;font-size:11px;color:var(--muted);font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .nm-row .rol{
    flex:none;font-size:9.5px;font-weight:800;letter-spacing:.1em;text-transform:uppercase;
    padding:4px 8px;border-radius:999px;background:var(--gray-soft);border:1px solid var(--line);color:var(--ink-soft);
  }
  .nm-row .rol.admin{background:var(--black);color:var(--on-black);border-color:transparent}
  .nm-row .apill{flex:none}
  .nm-row.me .apill{visibility:hidden}
  .nm-sep{
    font-size:9.5px;font-weight:800;letter-spacing:.14em;text-transform:uppercase;color:var(--faint);
    margin:4px 0 12px;padding-top:14px;border-top:1px solid var(--line);
  }
  /* ───────── áreas del proyecto ───────── */
  .ax-row{
    display:flex;align-items:center;gap:10px;padding:9px 10px 9px 6px;border-radius:12px;
    border:1px solid transparent;background:var(--card-solid);transition:background 120ms ease,box-shadow 120ms ease;
  }
  .ax-row:hover{background:var(--gray-soft)}
  .ax-row.moviendo{opacity:.55;box-shadow:var(--shadow-lift);border-color:var(--line)}
  .ax-grip{display:flex;color:var(--faint);cursor:grab;flex:none}
  .ax-grip svg{width:16px;height:16px}
  .ax-row i{width:9px;height:9px;border-radius:50%;flex:none}
  .ax-row b{flex:1;min-width:0;font-size:13px;font-weight:800;letter-spacing:-.01em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .ax-n{font-size:11px;font-weight:600;color:var(--muted);font-variant-numeric:tabular-nums;flex:none}
  .ax-x{width:26px;height:26px;border-radius:8px;display:flex;align-items:center;justify-content:center;color:var(--faint);flex:none;transition:background 120ms ease,color 120ms ease}
  .ax-x svg{width:13px;height:13px}
  button.ax-x:hover{background:var(--red-soft);color:var(--red-ink)}
  .ax-add{display:inline-flex;align-items:center;gap:6px;margin-bottom:4px}
  .ax-add svg{width:13px;height:13px}
  .ax-add.on{background:var(--black);color:var(--on-black)}
  /* the field is the wrapper, not the input: the app's inputs are styled
     under .fld and this one lives outside a field */
  .ax-buscar{
    display:flex;align-items:center;gap:8px;margin:14px 0 6px;padding:0 12px;border-radius:14px;
    border:1px solid var(--line-strong);background:var(--card-solid);transition:border-color 150ms ease,box-shadow 150ms ease;
  }
  .ax-buscar:focus-within{border-color:var(--ink);box-shadow:0 0 0 3px var(--gray-soft)}
  .ax-buscar svg{width:15px;height:15px;color:var(--faint);flex:none}
  .ax-buscar input{flex:1;min-width:0;width:100%;padding:12px 0;border:0;background:none;font:inherit;font-size:13.5px;color:var(--ink);outline:none;-webkit-appearance:none;appearance:none}
  .ax-buscar input::placeholder{color:var(--faint)}
  /* the wrapper draws the focus ring; the field itself must not add a
     second one inside it */
  .ax-buscar input:focus,.ax-buscar input:focus-visible{outline:none;box-shadow:none;border:0}
  .ax-buscar input::-webkit-search-cancel-button{-webkit-appearance:none;appearance:none}
  .ax-grid{max-height:min(46vh,380px);overflow-y:auto;scrollbar-width:thin;margin:0 -4px;padding:0 4px 4px}
  .ax-grupo{font-size:9.5px;font-weight:800;letter-spacing:.14em;text-transform:uppercase;color:var(--faint);margin:12px 0 7px}
  .ax-tiles{display:grid;grid-template-columns:repeat(auto-fill,minmax(168px,1fr));gap:6px}
  .ax-tile{
    display:flex;align-items:center;gap:7px;padding:8px 10px;border-radius:9px;text-align:left;
    border:1px solid var(--line);background:var(--card-solid);font-size:12px;font-weight:600;color:var(--ink);
    transition:background 120ms ease,border-color 120ms ease,transform 120ms var(--eo);
  }
  .ax-tile svg{width:12px;height:12px;flex:none;color:var(--faint)}
  button.ax-tile:hover{background:var(--gray-soft);border-color:var(--line-strong)}
  button.ax-tile:active{transform:scale(.98)}
  .ax-tile.en{background:var(--gray-soft);border-color:transparent;color:var(--muted);cursor:default}
  .ax-tile.en svg{color:var(--green)}
  /* «Crear …»: the name may be long and the host narrow (the desk's left
     pane), so the hint drops under the name instead of fighting it for
     the same line, and the name wraps as a whole */
  .ax-propia{
    display:grid;grid-template-columns:auto minmax(0,1fr);column-gap:9px;row-gap:1px;align-items:center;
    width:100%;margin-top:12px;padding:10px 12px;border-radius:10px;
    border:1px dashed var(--line-strong);font-size:12.5px;font-weight:600;color:var(--ink);text-align:left;
  }
  .ax-propia svg{width:14px;height:14px;color:var(--green);flex:none;grid-row:1 / span 2}
  .ax-propia .ax-pt{min-width:0;overflow-wrap:anywhere;line-height:1.35}
  .ax-propia b{font-weight:800}
  .ax-propia .ax-ph{grid-column:2;font-size:11px;color:var(--muted);font-weight:600}
  .ax-propia:hover{background:var(--gray-soft)}
  .ax-nada{padding:18px 4px;font-size:12px;color:var(--muted);font-weight:600}
  .ax-pie{font-size:11px;color:var(--faint);font-weight:600;margin-top:10px;padding-top:10px;border-top:1px solid var(--line)}
  /* ───────── planificar ───────── */
  /* areas only (2026-10-08): a compact column, as tall as its list */
  .cfg.pl{width:min(460px,95vw);max-height:calc(100vh - 40px);padding:0;overflow:hidden;display:flex;flex-direction:column}
  .pl-head{display:flex;align-items:flex-start;justify-content:space-between;padding:22px 26px 14px;border-bottom:1px solid var(--line)}
  .pl-head .dr-close{position:static}
  .pl-sub{font-size:12px;color:var(--muted);font-weight:600;margin-top:3px}
  .pl-lado{display:flex;flex-direction:column;min-height:0;overflow:auto;padding:16px 22px 18px;scrollbar-width:thin}
  .pl-lbl{display:flex;align-items:baseline;justify-content:space-between;gap:10px;font-size:9.5px;font-weight:800;letter-spacing:.12em;text-transform:uppercase;color:var(--faint);margin:0 0 8px}
  .pl-lbl span{letter-spacing:.02em;text-transform:none;font-weight:600;font-size:10.5px;opacity:.85}
  .pl-lbl .pl-tt{font-size:13px;font-weight:800;letter-spacing:-.01em;text-transform:none;color:var(--ink)}
  /* the area list: rows with room between them, lifted off the pane
     with a hairline, and the count, grip and ✕ in darker greys than the
     muted/faint defaults so they read at a glance */
  .pl-areas{margin:0 0 12px;display:flex;flex-direction:column;gap:8px}
  .pl-areas .ax-row{padding:12px 12px 12px 8px;border-color:var(--line);box-shadow:0 1px 2px rgba(20,22,20,.04)}
  .pl-areas .ax-row b{font-size:13.5px}
  .pl-areas .ax-n{color:var(--ink-soft)}
  .pl-areas .ax-grip,.pl-areas .ax-x{color:var(--muted)}
  .pl-izq .ax-add{flex:none;align-self:flex-start}
  .pl-izq .ax-catalogo{margin-bottom:10px}
  .pl-izq .ax-grid{max-height:none}
  .pl-izq .ax-tiles{grid-template-columns:1fr}
  .pl-vacio{padding:18px 4px;font-size:12.5px;color:var(--muted);font-weight:600;line-height:1.5}
  .pl-foot .btn{flex:none}
  .btn.sm{padding:8px 13px;font-size:12px;border-radius:10px}
  .pl-foot{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:12px 26px;border-top:1px solid var(--line);font-size:11.5px;color:var(--muted);font-weight:600}
  /* ───────── the resident's arrival (ui/llegada.js) ─────────
     body.sin-llegada is set by llegada.js — arrival owed and no absence
     noted. Inside an obra it raises THE GATE over everything (owner, 13
     October 2026): above the docks and the scrim, below the dialogs it
     opens (the absence, at 55) and the toast. The card under it keeps
     its own two buttons for the moment the gate is down. */
  .llegada-gate{
    display:none;position:fixed;inset:0;z-index:50;align-items:center;justify-content:center;padding:20px;
    background:var(--overlay);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);
  }
  body.sin-llegada:not(.choosing) .llegada-gate{display:flex}
  .lgate{
    width:min(380px,100%);display:flex;flex-direction:column;gap:10px;text-align:center;
    background:var(--card-solid);border:1px solid var(--edge);border-radius:24px;box-shadow:var(--shadow-lift);padding:26px 22px 16px;
  }
  .lgate-ico{width:56px;height:56px;border-radius:18px;margin:0 auto 4px;display:grid;place-items:center;background:var(--green-soft);color:var(--green-ink)}
  .lgate-ico svg{width:26px;height:26px}
  .lgate h2{margin:0;font-size:20px;font-weight:800;letter-spacing:-.02em;color:var(--ink)}
  .lgate p{margin:0 0 6px;font-size:13px;font-weight:600;color:var(--muted)}
  .lgate-go,.lgate-no{width:100%;justify-content:center;padding:13px 16px;font-size:14px}
  .lgate-pie{display:flex;justify-content:center;gap:20px;margin-top:4px}
  .lgate-link{font-size:12px;font-weight:700;color:var(--muted);padding:6px 2px}
  .lgate-link:hover{color:var(--ink)}
  .ck-ausente,.ck-espera{display:none}
  body.sin-llegada .ck-ausente{display:inline-flex}
  body.sin-llegada .ck-me .t .ck-espera{display:block}
  .nm-result{margin:6px 0 20px}
  .nm-who{display:flex;align-items:center;gap:12px;margin-bottom:16px}
  .nm-who i{
    width:40px;height:40px;border-radius:50%;background:#7D8F79;color:#fff;font-style:normal;
    font-size:12px;font-weight:800;display:flex;align-items:center;justify-content:center;flex:none;
  }
  .nm-who b{display:block;font-size:14px;font-weight:800;letter-spacing:-.01em}
  .nm-who span{font-size:11.5px;color:var(--muted);font-weight:600}
  .nm-pass{background:var(--amber-soft);border:1px solid color-mix(in srgb, var(--amber) 28%, transparent);border-radius:16px;padding:14px 16px}
  .nm-pass.soft{background:var(--gray-soft);border-color:var(--line)}
  .nm-pass .k{font-size:9.5px;font-weight:800;letter-spacing:.12em;text-transform:uppercase;color:var(--amber-ink)}
  .nm-pass.soft .k{color:var(--muted)}
  .nm-pass .row{display:flex;align-items:center;gap:10px;margin:9px 0 8px}
  .nm-pass code{
    font-family:ui-monospace,"SF Mono",Menlo,monospace;font-size:19px;font-weight:700;letter-spacing:.06em;
    color:var(--ink);background:var(--card-solid);padding:8px 12px;border-radius:11px;flex:1;
  }
  .nm-pass .m{font-size:11px;color:var(--muted);font-weight:500;line-height:1.45}

  /* a password read out loud must not break across two lines */
  .nm-pass code{white-space:nowrap;overflow-x:auto;flex:1 1 auto;min-width:0}
  .nm-pass .row .apill{flex:none}

  /* ═══════════ the drawer: bitácora ═══════════
     One thread per day. The rail on the left, one circle per entry
     coloured by type; the day header stays stuck. */
  .bt-bar{display:flex;align-items:center;gap:6px;padding:10px 22px 10px;border-bottom:1px solid var(--line);flex:none;overflow-x:auto;scrollbar-width:none}
  .bt-bar::-webkit-scrollbar{display:none}
  .bt-bar .chip{font-size:11px;font-weight:700;color:var(--muted);padding:6px 11px;border-radius:99px;background:var(--gray-soft);white-space:nowrap;display:flex;align-items:center;gap:5px;transition:background 120ms ease,color 120ms ease}
  .bt-bar .chip b{font-weight:800;opacity:.55}
  .bt-bar .chip:hover{color:var(--ink)}
  .bt-bar .chip.on{background:var(--black);color:var(--on-black)}

  .bt{flex:1;overflow-y:auto;padding:4px 26px 18px;scrollbar-width:thin}
  .bt-empty{display:flex;gap:10px;align-items:flex-start;padding:28px 6px;font-size:12.5px;color:var(--muted);line-height:1.5}
  .bt-empty svg{width:16px;height:16px;flex:none;margin-top:2px}
  .bt-empty b{color:var(--ink)}
  .bt .day{position:relative;padding-top:16px}
  /* El encabezado del día se queda pegado arriba mientras se lee. Su
     fondo llegaba a transparente en el 72% de su alto, así que una foto
     pasando por debajo se veía A TRAVÉS del texto: «18 sep viernes»
     sobre una losa. Ahora el fondo es opaco en todo el alto del
     encabezado —con desenfoque, para que lo que pasa por debajo se
     insinúe— y el degradado vive en una franja aparte, por debajo. */
  /* `top` cancels the list's 4px top padding: a sticky header stops at
     the padding edge, not the scroll edge, and in that 4px strip the
     entries passing underneath showed above the date */
  .bt .day-h{
    position:sticky;top:-4px;z-index:2;display:flex;align-items:center;gap:9px;
    padding:10px 0 8px;background:var(--glass-strong);
    -webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);
  }
  .bt .day-h::after{
    content:"";position:absolute;left:0;right:0;top:100%;height:12px;pointer-events:none;
    background:linear-gradient(var(--glass-strong), transparent);
  }
  .bt .day-h b{font-size:12px;font-weight:800;letter-spacing:-.01em}
  .bt .day-h span{font-size:11px;color:var(--muted);font-weight:600}
  .bt .day-h .hoy{font-size:9.5px;font-weight:800;letter-spacing:.1em;text-transform:uppercase;color:var(--green-ink);background:var(--green-soft);padding:3px 8px;border-radius:99px}
  .bt .day-h .n{margin-left:auto;font-size:10.5px;color:var(--faint);font-weight:700;font-variant-numeric:tabular-nums}

  .bt .en{position:relative;display:grid;grid-template-columns:28px 1fr;gap:0 12px;padding-bottom:16px}
  .bt .en::before{content:"";position:absolute;left:13.5px;top:30px;bottom:-2px;width:1.5px;background:var(--line)}
  .bt .day .en:last-child::before{display:none}
  .bt .en > div:last-child{min-width:0}
  .bt .en .ico{width:28px;height:28px;border-radius:50%;display:flex;align-items:center;justify-content:center;background:var(--gray-soft);color:var(--ink-soft);position:relative;z-index:1}
  .bt .en .ico svg{width:14px;height:14px}
  .bt .en.foto .ico,.bt .en.video .ico{background:var(--amber-soft);color:var(--amber-ink)}
  .bt .en.doc .ico{background:var(--violet-soft);color:var(--violet-ink)}
  .bt .en.estado .ico{background:var(--card-solid);border:1.5px solid var(--line-strong);color:var(--muted)}
  .bt .en.sistema .ico{background:var(--card-solid);border:1.5px solid var(--line);color:var(--faint)}
  .bt .en.apr .ico{background:var(--green);color:#fff}
  .bt .en.aviso .ico{background:var(--red-soft);color:var(--red-ink)}
  .bt .en .who{display:flex;align-items:center;gap:6px;font-size:12.5px;line-height:1.35;min-height:28px;flex-wrap:wrap}
  .bt .en .who b{font-weight:800}
  .bt .en .who .t{color:var(--muted);font-weight:500}
  .bt .en .who .t b{color:var(--ink)}
  .bt .en .who .hora{margin-left:auto;font-size:10.5px;color:var(--faint);font-weight:700;font-variant-numeric:tabular-nums;white-space:nowrap}
  .bt .en .body{margin-top:8px}
  .bt .en.aviso .who .t{color:var(--red-ink);font-weight:600}

  .bt .shots{display:grid;grid-template-columns:repeat(4,1fr);gap:8px}
  @media (max-width:560px){.bt .shots{grid-template-columns:repeat(3,1fr)}}
  /* a lone shot does not take the full width: a ~300 px card is enough
     to recognise it, and the viewer is one click away to see it big */
  .bt .shots.one{grid-template-columns:minmax(0,300px)}
  .bt .en.video .shots.one{grid-template-columns:minmax(0,380px)}
  .bt .shots .shot{aspect-ratio:4/3;border-radius:12px;overflow:hidden;position:relative;margin:0;border:1px solid var(--edge);background:var(--gray-soft);cursor:zoom-in}
  .bt .shots.one .shot{aspect-ratio:4/3}
  .bt .en.video .shots.one .shot{aspect-ratio:16/9}
  .bt .shot img,.bt .shot video{width:100%;height:100%;object-fit:cover;display:block}
  .bt .shot video{background:#000}
  .bt .shot .more{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:rgba(21,21,20,.55);color:#fff;font-size:14px;font-weight:800}
  .bt .shot .play{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);width:36px;height:36px;border-radius:50%;background:rgba(21,21,20,.7);display:flex;align-items:center;justify-content:center;color:#fff;pointer-events:none}
  .bt .shot .play svg{width:14px;height:14px;margin-left:2px}
  .bt .cap{font-size:11.5px;color:var(--ink-soft);margin-top:7px;line-height:1.45}
  .bt .cap em{font-style:normal;color:var(--muted)}

  .bt .file{display:flex;align-items:center;gap:11px;padding:10px 12px;border:1px solid var(--line);border-radius:13px;background:var(--gray-soft);text-decoration:none;color:inherit}
  .bt .file:hover{border-color:var(--faint)}
  .bt .file .fk{width:34px;height:34px;border-radius:10px;display:flex;align-items:center;justify-content:center;font-size:8.5px;font-weight:800;letter-spacing:.06em;flex:none;background:var(--card-solid);color:var(--gray-ink)}
  .bt .file .fk.pdf{background:var(--red-soft);color:var(--red-ink)}
  .bt .file .fk.xls{background:var(--green-soft);color:var(--green-ink)}
  .bt .file .fk.doc{background:var(--violet-soft);color:var(--violet-ink)}
  .bt .file .ft{flex:1;min-width:0;display:flex;flex-direction:column}
  .bt .file .fn{font-size:12.5px;font-weight:700;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .bt .file .fm{font-size:10.5px;color:var(--muted);font-weight:600;margin-top:1px}
  .bt .file .fo{font-size:11px;font-weight:800;color:var(--ink);padding:6px 10px;border-radius:99px;background:var(--card-solid);flex:none}

  .bt .note{position:relative;font-size:12.5px;line-height:1.55;color:var(--ink-soft);padding:10px 13px;border-radius:4px 14px 14px 14px;background:var(--gray-soft);white-space:pre-wrap;word-break:break-word}
  .bt .note .re{display:flex;align-items:center;gap:6px;font-size:10.5px;font-weight:700;color:var(--muted);margin-bottom:5px}
  .bt .note .re svg{width:11px;height:11px}
  .bt .note .acts{display:flex;gap:10px;margin-top:6px;opacity:0;transition:opacity 120ms ease}
  .bt .note:hover .acts,.bt .note:focus-within .acts{opacity:1}
  @media (hover:none){.bt .note .acts{opacity:1}}
  .bt .note .acts button{font-size:10.5px;font-weight:800;color:var(--muted)}
  .bt .note .acts button:hover{color:var(--ink)}
  .bt .note .acts .del:hover{color:var(--red-ink)}

  .bt .pill{display:inline-flex;align-items:center;gap:6px;font-size:10.5px;font-weight:800;padding:3px 9px;border-radius:99px}
  .bt .pill.gray{background:var(--gray-soft);color:var(--gray-ink)}
  .bt .pill.amber{background:var(--amber-soft);color:var(--amber-ink)}
  .bt .pill.violet{background:var(--violet-soft);color:var(--violet-ink)}
  .bt .pill.green{background:var(--green-soft);color:var(--green-ink)}
  .bt .arrow{color:var(--faint);font-weight:700}

  .bt .firma{padding:12px 14px;border-radius:14px;background:var(--green-soft);border:1px solid color-mix(in srgb, var(--green) 25%, transparent);display:flex;align-items:center;gap:12px}
  .bt .firma .mk{width:30px;height:30px;border-radius:50%;background:var(--green);color:#fff;display:flex;align-items:center;justify-content:center;flex:none}
  .bt .firma .mk svg{width:14px;height:14px}
  .bt .firma .t1{font-size:12.5px;font-weight:800;color:var(--green-ink)}
  .bt .firma .t2{font-size:11px;color:var(--green-ink);opacity:.8;font-weight:600;margin-top:1px}

  .bt .gasto-row{display:flex;align-items:center;gap:10px;padding:9px 12px;border-radius:12px;border:1px dashed var(--line-strong);font-size:12px}
  .bt .gasto-row .c{flex:1;min-width:0;font-weight:700;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .bt .gasto-row .w{color:var(--muted);font-weight:600;font-size:11px;white-space:nowrap}
  .bt .gasto-row .v{font-weight:800;font-variant-numeric:tabular-nums;white-space:nowrap}
  .bt .gasto-row .adm{font-size:9px;font-weight:800;letter-spacing:.1em;text-transform:uppercase;color:var(--faint);border:1px solid var(--line);padding:2px 6px;border-radius:6px}

  /* the pluma: where an entry gets written */
  .pluma{flex:none;padding:12px 16px 12px;border-top:1px solid var(--line)}
  .pluma.cerrada{display:flex;align-items:center;gap:9px;font-size:11.5px;color:var(--muted);font-weight:600;padding:10px 22px;line-height:1.4}
  .pluma.cerrada svg{width:14px;height:14px;flex:none}
  .pluma .box{border:1px solid var(--line-strong);border-radius:16px;background:var(--card-solid);padding:10px 12px;box-shadow:var(--shadow)}
  .pluma .box:focus-within{border-color:var(--ink)}
  .pluma textarea{display:block;width:100%;resize:none;border:none;outline:none;background:none;font:inherit;font-size:12.5px;line-height:1.5;color:var(--ink);min-height:22px;max-height:140px}
  .pluma textarea::placeholder{color:var(--faint)}
  .pluma .re{display:flex;align-items:center;gap:6px;font-size:10.5px;font-weight:700;color:var(--muted);margin-bottom:6px}
  .pluma .re svg{width:11px;height:11px}
  .pluma .re b{color:var(--ink)}
  .pluma .re button{margin-left:auto;display:flex;color:var(--faint)}
  .pluma .re button svg{width:12px;height:12px}
  .pluma .row{display:flex;align-items:center;gap:4px;margin-top:8px}
  .pluma .mini{width:30px;height:30px;border-radius:9px;display:flex;align-items:center;justify-content:center;color:var(--muted)}
  .pluma .mini svg{width:15px;height:15px}
  .pluma .mini:hover{background:var(--gray-soft);color:var(--ink)}
  .pluma .send{margin-left:auto;background:var(--black);color:var(--on-black);border-radius:99px;font-size:11.5px;font-weight:800;padding:7px 15px;display:flex;align-items:center;gap:6px}
  .pluma .send:disabled{opacity:.5}
  .pluma .send svg{width:12px;height:12px}
  .pluma .hint{font-size:10.5px;color:var(--faint);font-weight:600;margin-top:8px;display:flex;gap:14px;flex-wrap:wrap}
  .pluma .hint b{color:var(--muted);font-weight:800}
  @media (max-width:760px){

    .pluma{padding:8px 10px calc(8px + env(safe-area-inset-bottom))}
    .pluma .box{display:flex;flex-wrap:wrap;align-items:flex-end;gap:4px;border-radius:24px;padding:5px 5px 5px 14px}
    .pluma .box .re{flex-basis:100%;margin:4px 0 2px}
    .pluma textarea{flex:1;min-width:0;width:auto;font-size:16px;line-height:1.35;padding:8px 0;min-height:38px}
    .pluma .row{margin-top:0;gap:2px;flex:none}
    .pluma .mini{width:36px;height:36px;border-radius:50%}
    .pluma .send{width:38px;height:38px;padding:0;border-radius:50%;justify-content:center;font-size:0;gap:0}
    .pluma .send svg{width:15px;height:15px}
    .pluma .hint{display:none}
  }

  /* ═══════════ evidencias: by workday ═══════════ */
  .ev-hero{align-items:center}
  .ev-tools{gap:8px}
  .ev-search{
    display:flex;align-items:center;gap:8px;width:210px;height:40px;padding:0 12px;
    border:1px solid var(--edge);border-radius:12px;background:var(--glass);box-shadow:var(--shadow);
  }
  .ev-search svg{width:15px;height:15px;color:var(--muted);flex:none}
  .ev-search input{flex:1;min-width:0;background:none;border:none;outline:none;font:inherit;font-size:12.5px;font-weight:600;color:var(--ink)}
  .ev-search input::placeholder{color:var(--faint)}
  .ev-search input::-webkit-search-cancel-button{-webkit-appearance:none}
  .ev-dd .dd-menu{min-width:220px}
  /* back to the right edge: the row held the view tabs on its left and
     they are gone, and `space-between` with one child is just left */
  .ev-sortrow{display:flex;justify-content:flex-end;align-items:center;gap:12px;margin:2px 4px 6px}
  /* the sort control only appears where there is a feed to sort */
  .ev-sortrow .dd{display:none}
  .ev-sortrow.con-orden .dd{display:block}
  .ev-sort{display:flex;align-items:center;gap:7px;font-size:11.5px;font-weight:700;color:var(--muted);padding:6px 10px;border-radius:10px}
  .ev-sort:hover{background:var(--gray-soft);color:var(--ink)}
  .ev-sort svg{width:14px;height:14px}
  .ev-sortrow .dd-menu{left:auto;right:0}

  /* ═══════════ ARCHIVO VISUAL ═══════════
     A rail and a stage. The rail says WHERE in the obra you are — the
     month, the days that have something, the ways in — and never
     scrolls away; the stage shows one day at a time, big enough to
     actually look at. Evidencias reads the record in order; this one is
     for going to a place you already remember. */
  .ar-cuerpo{display:grid;grid-template-columns:270px minmax(0,1fr);gap:18px;align-items:start}
  .ar-rail{
    position:sticky;top:12px;background:var(--card);border:1px solid var(--line);
    border-radius:18px;padding:16px 16px 14px;display:flex;flex-direction:column;gap:16px;
  }
  .ar-main{display:flex;flex-direction:column;gap:22px;min-width:0}

  /* ── the little month ── */
  .ar-cal header{display:flex;align-items:center;justify-content:space-between;gap:6px;margin-bottom:10px}
  .ar-cal header b{font-size:13.5px;font-weight:800;letter-spacing:-.01em}
  .ar-nav{
    width:26px;height:26px;display:grid;place-items:center;flex:none;cursor:pointer;
    background:none;border:0;border-radius:8px;color:var(--muted);transition:background 140ms ease,color 140ms ease;
  }
  .ar-nav:hover{background:var(--gray-soft);color:var(--ink)}
  .ar-nav svg{width:15px;height:15px}
  .ar-sem,.ar-rejilla{display:grid;grid-template-columns:repeat(7,1fr);gap:2px}
  .ar-sem span{font-size:9.5px;font-weight:800;color:var(--faint);text-align:center;padding-bottom:4px}
  .ar-d{
    aspect-ratio:1;display:grid;place-items:center;border:0;background:none;font:inherit;
    font-size:11.5px;font-weight:600;color:var(--faint);border-radius:9px;position:relative;
  }
  /* A DOT, NOT A FILL. The month is 270px wide: shading the squares
     turns it into a heat map you cannot read at that size, and what is
     being asked here is only «is there anything on the 11th». */
  .ar-d.con{color:var(--ink);font-weight:800;cursor:pointer;transition:background 140ms ease}
  .ar-d.con::after{
    content:"";position:absolute;bottom:3px;left:50%;transform:translateX(-50%);
    width:3px;height:3px;border-radius:50%;background:var(--green);
  }
  .ar-d.con:hover{background:var(--gray-soft)}
  .ar-d.con.puesto{background:var(--black);color:var(--on-black)}
  .ar-d.con.puesto::after{background:var(--on-black)}

  /* ── the days that have something, by name ── */
  .ar-regs h3,.ar-explorar h3{
    font-size:10px;font-weight:800;letter-spacing:.08em;text-transform:uppercase;
    color:var(--faint);margin:0 0 7px;
  }
  .ar-reg,.ar-exp,.ar-todo{
    display:flex;align-items:center;gap:7px;width:100%;text-align:left;cursor:pointer;
    background:none;border:0;padding:7px 9px;border-radius:10px;font:inherit;font-size:12.5px;
    color:var(--ink-soft);transition:background 140ms ease,color 140ms ease;
  }
  .ar-reg i{width:6px;height:6px;border-radius:50%;background:var(--green);flex:none}
  .ar-reg b{font-weight:700}
  .ar-reg span{color:var(--muted);font-weight:600}
  .ar-reg:hover,.ar-exp:hover,.ar-todo:hover{background:var(--gray-soft);color:var(--ink)}
  .ar-reg.puesto,.ar-exp.puesto{background:var(--gray-soft);color:var(--ink);font-weight:700}
  .ar-exp svg,.ar-todo svg{width:16px;height:16px;flex:none;color:var(--muted)}
  .ar-todo{color:var(--muted);font-weight:700;font-size:12px;margin-top:2px}
  .ar-todo svg{margin-left:auto}
  .ar-vacio{font-size:12px;color:var(--faint);font-weight:600;margin:0}

  /* ── the stage ── */
  /* The photographs sit on paper, the way they do in «Por área» and in
     the feed. They were the only thing on this screen laid straight
     onto the desk, and a grid of images with no sheet under it reads as
     the page having lost its panel rather than as a choice. */
  .ar-bloque{display:flex;flex-direction:column;gap:13px;padding:16px 18px 18px}
  .ar-bh{display:flex;align-items:flex-start;justify-content:space-between;gap:14px}
  .ar-bh h2{font-size:21px;font-weight:800;letter-spacing:-.02em;margin:0}
  /* a title with no panel under it: the month feed's own panels are the
     jornadas, so its heading has to stand on the desk */
  .ar-suelto{padding:0 2px}
  .ar-sub2{display:flex;align-items:center;gap:12px;margin-top:4px;font-size:12.5px;color:var(--muted);font-weight:600}
  .ar-sub2 span{display:flex;align-items:center;gap:6px}
  .ar-sub2 span + span::before{content:"·";color:var(--faint);margin-right:2px}
  .ar-sub2 i{width:7px;height:7px;border-radius:50%;flex:none}
  .ar-act,.ar-vertodo{
    display:flex;align-items:center;gap:6px;flex:none;cursor:pointer;
    background:none;border:0;padding:4px 2px;font:inherit;font-size:12.5px;font-weight:700;color:var(--muted);
  }
  .ar-act:hover,.ar-vertodo:hover{color:var(--ink)}
  .ar-act svg,.ar-vertodo svg{width:15px;height:15px}
  .ar-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(250px,1fr));gap:14px}
  /* the tile is Evidencias' own — checkbox, menu and all — so it keeps
     working here for selection, download and delete; the archive only
     changes what is laid out around it, and adds the kind to its foot */
  .ar-grid .ev-toma figcaption{display:flex;align-items:center;gap:7px}
  .ev-tipo{display:flex;flex:none;color:var(--faint)}
  .ev-tipo svg{width:15px;height:15px}
  .ar-mas{display:flex;flex-direction:column;gap:13px;padding:16px 18px 18px}
  .ar-mas header{display:flex;align-items:center;justify-content:space-between;gap:12px}
  .ar-mas h2{font-size:17px;font-weight:800;letter-spacing:-.01em;margin:0}
  .ar-pie{font-size:12px;color:var(--faint);font-weight:600;margin:0}

  /* ON A PHONE THE RAIL GOES ON TOP and stops sticking: a 270px column
     beside a 375px screen is not a column, and a calendar glued to the
     top of a phone eats the half of it the photographs need. */
  @media (max-width:900px){
    .ar-cuerpo{grid-template-columns:1fr}
    .ar-rail{position:static}
    .ar-bh h2{font-size:18px}
  }

  /* ───────── dar de alta · el papel primero ─────────
     The decision that changes every field after it gets a screen of its
     own, with the sentence that says what each papel actually does.
     Chips would have fitted in one line and said nothing. */
  .nc-pregunta{font-size:12px;color:var(--muted);margin:4px 0 16px}
  .nc-papeles{display:flex;flex-direction:column;gap:8px;margin-bottom:4px}
  .nc-papel{
    display:block;width:100%;text-align:left;cursor:pointer;font:inherit;
    padding:12px 14px;border:1px solid var(--line);border-radius:14px;background:none;
    transition:border-color 140ms ease,background 140ms ease,transform 120ms var(--eo);
  }
  .nc-papel:hover{background:var(--gray-soft);border-color:var(--edge)}
  .nc-papel:active{transform:scale(.995)}
  .nc-papel b{display:block;font-size:14px;font-weight:800;letter-spacing:-.01em;margin-bottom:2px}
  .nc-papel span{display:block;font-size:12px;color:var(--muted);font-weight:500;line-height:1.5}
  .nc-volver{
    display:flex;align-items:center;gap:5px;cursor:pointer;font:inherit;
    background:none;border:0;padding:0 0 10px;font-size:12px;font-weight:700;color:var(--muted);
  }
  .nc-volver:hover{color:var(--ink)}
  .nc-opt{font-weight:600;color:var(--faint)}
  .nc-nota{font-size:11.5px;color:var(--muted);font-weight:500;line-height:1.5;margin-top:6px}
  /* who is already here, the thing that made the admins dialog read as
     a place instead of a form */
  .nc-lista{display:flex;flex-direction:column;gap:2px;margin-bottom:4px}
  .nc-ya{display:flex;align-items:center;gap:9px;padding:6px 2px;font-size:12.5px}
  .nc-ya .avatar{width:24px;height:24px;font-size:9px;flex:none}
  .nc-ya b{font-weight:700}
  .nc-ya-rol{margin-left:auto;font-size:11px;color:var(--muted);font-weight:600}
  .nc-nadie{font-size:12px;color:var(--faint);font-weight:600;padding:4px 2px}
  @media (prefers-reduced-motion:reduce){ .nc-papel{transition:none} }

  .ev-groups{display:flex;flex-direction:column;gap:16px}

  /* ───────── the record along the obra ─────────
     One panel per area, busiest first. The header is the whole button:
     a ring with the board's progress, the name, and what it holds. The
     ring is the number the photographs are evidence FOR, which is why
     it comes from the board and not from the count of shots. */
  .ev-zona{padding:16px 18px 18px;display:flex;flex-direction:column;gap:12px}
  .ev-zona-h{
    display:flex;align-items:center;gap:13px;width:100%;text-align:left;
    background:none;border:0;padding:0;font:inherit;color:inherit;cursor:pointer;
  }
  .ev-anillo{width:26px;height:26px;flex:none}
  .ev-zona-t{flex:1;min-width:0}
  .ev-zona-t h2{font-size:15px;font-weight:800;letter-spacing:-.01em;margin:0}
  .ev-chev{color:var(--faint);display:flex;transition:transform 200ms var(--eo)}
  .ev-chev svg{width:17px;height:17px}
  .ev-zona.abierta .ev-chev{transform:rotate(180deg)}
  .ev-zona-h:hover .ev-chev{color:var(--muted)}
  .ev-mas{
    align-self:flex-start;background:none;border:0;padding:4px 0;font:inherit;
    font-size:12px;font-weight:700;color:var(--muted);cursor:pointer;
  }
  .ev-mas:hover{color:var(--ink)}

  /* ───────── the month ─────────
     A square for every day, including the ones nobody photographed:
     this is the only view in Evidencias that can show an absence,
     because a feed lists what exists and a grid has a place for what
     does not. The shade says how much there is without a legend —
     nobody reads a legend on a calendar. */
  .ev-mes{padding:16px 18px 18px}
  .ev-mes-h{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:12px}
  /* NO `capitalize`: capitalises every word and the month came out
     «Septiembre De 2026». The first letter is done where the string is
     built, which is the only place that knows where the name ends. */
  .ev-mes-h h2{font-size:15px;font-weight:800;letter-spacing:-.01em;margin:0}
  .ev-mes-b{
    width:30px;height:30px;display:grid;place-items:center;flex:none;cursor:pointer;
    background:none;border:1px solid var(--line);border-radius:9px;color:var(--muted);
    transition:background 140ms ease,color 140ms ease;
  }
  .ev-mes-b:hover{background:var(--gray-soft);color:var(--ink)}
  .ev-mes-b svg{width:15px;height:15px}
  .ev-sem,.ev-rejilla{display:grid;grid-template-columns:repeat(7,1fr);gap:5px}
  .ev-sem{margin-bottom:5px}
  .ev-sem span{font-size:10px;font-weight:800;letter-spacing:.06em;color:var(--faint);text-align:center}
  .ev-dia{
    /* The tile fills its column and the HEIGHT is what is capped. With
       `aspect-ratio` it shrank to a square and left a gap in every
       column; and without a cap, a seventh of a wide panel is 170px and
       a month of those is a wall, not a calendar. */
    height:clamp(54px,7.2vw,94px);border-radius:9px;border:1px solid var(--line);background:var(--card-solid);
    display:flex;flex-direction:column;align-items:flex-start;justify-content:space-between;
    padding:5px 6px;font:inherit;cursor:default;color:var(--faint);
    transition:transform 200ms var(--eo),border-color 140ms ease;
  }
  .ev-dia b{font-size:10.5px;font-weight:700;font-variant-numeric:tabular-nums}
  .ev-dia i{font-size:11px;font-weight:800;font-style:normal;align-self:flex-end}
  .ev-dia.hueco{border:0;background:none}
  .ev-dia.n1,.ev-dia.n2,.ev-dia.n3{cursor:pointer;color:var(--on-black);border-color:transparent}
  .ev-dia.n1{background:color-mix(in srgb,var(--green) 34%,var(--card-solid))}
  .ev-dia.n2{background:color-mix(in srgb,var(--green) 64%,var(--card-solid))}
  .ev-dia.n3{background:var(--green)}
  .ev-dia.n1{color:var(--ink)}
  .ev-dia.n1:hover,.ev-dia.n2:hover,.ev-dia.n3:hover{transform:translateY(-2px)}
  .ev-dia.puesto{outline:2px solid var(--ink);outline-offset:2px}
  /* the chosen day's panels arrive from underneath, once */
  .ev-deldia{display:flex;flex-direction:column;gap:16px;animation:ev-sube 260ms var(--eo) both}
  @keyframes ev-sube{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
  @media (prefers-reduced-motion:reduce){
    .ev-deldia{animation:none}
    .ev-dia,.ev-chev{transition:none}
  }
  .ev-day{padding:20px 22px 22px}
  .ev-h{display:flex;align-items:flex-end;justify-content:space-between;gap:16px;margin-bottom:16px}
  .ev-date{font-size:12.5px;font-weight:600;color:var(--muted);font-variant-numeric:tabular-nums}
  .ev-h h2{font-size:24px;font-weight:800;letter-spacing:-.025em;line-height:1.15;margin-top:2px;text-wrap:balance}
  .ev-meta{display:flex;align-items:center;gap:14px;margin-top:6px;font-size:12.5px;color:var(--muted);font-weight:600;flex-wrap:wrap}
  .ev-meta span{display:flex;align-items:center;gap:7px}
  .ev-meta span + span::before{content:"·";color:var(--faint);margin-right:2px}
  .ev-meta i{width:7px;height:7px;border-radius:50%}
  .ev-meta .st{font-size:10px;font-weight:800;letter-spacing:.08em;text-transform:uppercase;padding:3px 8px;border-radius:99px;background:var(--gray-soft);color:var(--gray-ink)}
  .ev-meta .st::before{display:none}
  .ev-act{display:flex;align-items:center;gap:7px;font-size:12.5px;font-weight:700;color:var(--ink-soft);padding:8px 10px;border-radius:10px;white-space:nowrap;flex:none}
  .ev-act:hover{background:var(--gray-soft);color:var(--ink)}
  .ev-act svg{width:14px;height:14px}
  .ev-act svg:last-child{width:12px;height:12px;color:var(--muted)}

  /* small cards, many to a row: a photo from the obra reads better at
     260 px than stretched to 430, and the viewer is one click away */
  .ev-strip{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,260px));gap:12px}
  @media (max-width:700px){.ev-strip{grid-template-columns:repeat(2,1fr)}}
  .ev-toma{position:relative;margin:0;min-width:0}
  .ev-media{display:block;width:100%;aspect-ratio:4/3;border-radius:10px;overflow:hidden;position:relative;background:var(--gray-soft);cursor:zoom-in;border:1px solid var(--edge)}
  .ev-media img,.ev-media video{width:100%;height:100%;object-fit:cover;display:block}
  .ev-media video{background:#000}
  .ev-media .play{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);width:48px;height:48px;border-radius:50%;background:rgba(21,21,20,.72);color:#fff;display:flex;align-items:center;justify-content:center;pointer-events:none}
  .ev-media .play svg{width:18px;height:18px;margin-left:2px}
  .ev-media .fwrap{width:100%;height:100%;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;color:var(--muted)}
  .ev-media .fwrap svg{width:30px;height:30px}
  .ev-media .fname{font-size:10.5px;font-weight:700;max-width:85%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .ev-toma figcaption{font-size:11px;color:var(--muted);font-weight:600;margin-top:8px;font-variant-numeric:tabular-nums;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .ev-toma figcaption .cap{color:var(--ink-soft)}
  .ev-cb,.ev-dots{
    position:absolute;top:10px;width:28px;height:28px;border-radius:8px;display:flex;align-items:center;justify-content:center;
    background:var(--glass-strong);color:var(--ink);box-shadow:var(--shadow);opacity:0;transition:opacity 120ms ease;
  }
  .ev-cb{left:10px;color:transparent;border:1.5px solid var(--line-strong)}
  .ev-cb svg,.ev-dots svg{width:14px;height:14px}
  .ev-dots{right:10px}
  @media (hover:hover) and (pointer:fine){
    .ev-toma:hover .ev-cb,.ev-toma:hover .ev-dots{opacity:1}
    .ev-media img,.ev-media video{transition:transform 260ms var(--eo)}
    .ev-media:hover img,.ev-media:hover video{transform:scale(1.03)}
  }
  .ev-toma.selecting .ev-cb,.ev-toma.on .ev-cb,.ev-toma.menu-open .ev-dots{opacity:1}
  .ev-toma.on .ev-cb{background:var(--black);border-color:var(--black);color:var(--on-black)}
  .ev-toma.on .ev-media{outline:none;box-shadow:0 0 0 3px color-mix(in srgb, var(--ink) 30%, transparent)}
  /* the empty expediente: one panel, full width, the rail stepped aside */
  .ar-cuerpo.vacio{grid-template-columns:1fr}
  .ev-vacio{
    display:flex;flex-direction:column;align-items:center;text-align:center;
    padding:56px 24px 52px;max-width:520px;margin:0 auto;
  }
  .ev-vacio-ico{
    width:64px;height:64px;border-radius:20px;background:var(--gray-soft);color:var(--ink);
    display:flex;align-items:center;justify-content:center;margin-bottom:18px;
  }
  .ev-vacio-ico svg{width:26px;height:26px}
  .ev-vacio h2{font-size:18px;font-weight:800;letter-spacing:-.01em;margin:0 0 8px}
  .ev-vacio p{font-size:13px;color:var(--muted);font-weight:500;line-height:1.55;margin:0;max-width:420px}
  .ev-vacio-nota{margin-top:14px !important;font-size:12px !important;color:var(--faint) !important}
  .ev-vacio-cta{flex:none;margin-top:22px;padding:11px 18px}
  .ev-vacio-cta svg{width:15px;height:15px}
  .ev-empty{display:flex;gap:10px;align-items:flex-start;padding:48px 20px;justify-content:center;font-size:12.5px;color:var(--muted);line-height:1.5;text-align:center}
  .ev-empty svg{width:16px;height:16px;flex:none;margin-top:2px}
  .ev-empty b{color:var(--ink)}

  .ev-foot{
    position:sticky;bottom:14px;z-index:20;margin:14px 4px 0;padding:10px 14px;
    display:flex;align-items:center;gap:10px;font-size:12.5px;color:var(--ink-soft);font-weight:600;
    background:var(--glass-strong);-webkit-backdrop-filter:var(--blur);backdrop-filter:var(--blur);
    border:1px solid var(--edge);border-radius:16px;box-shadow:var(--shadow-lift);
  }
  .ev-foot .sp{flex:1}
  .ev-foot .apill.danger{color:var(--red-ink)}
  .ev-foot .apill:disabled{opacity:.45;cursor:default}
  .ev-menu{
    position:fixed;z-index:70;min-width:220px;padding:6px;
    background:var(--glass-strong);-webkit-backdrop-filter:var(--blur);backdrop-filter:var(--blur);
    border:1px solid var(--edge);border-radius:14px;box-shadow:var(--shadow-lift);animation:tl-pop-in 140ms var(--eo);
  }
  .ev-menu .dd-item{width:100%;text-decoration:none}
  .ev-menu .dd-item.danger,.ev-menu .dd-item.danger svg{color:var(--red-ink)}

  /* pick the area before uploading */
  .evp-list{display:flex;flex-direction:column;gap:2px;max-height:min(56vh,520px);overflow:auto;margin:0 -6px;padding:0 6px}
  .evp-opt{display:flex;flex-direction:column;align-items:flex-start;gap:2px;width:100%;padding:9px 10px;border-radius:11px;text-align:left;font-size:12.5px;font-weight:700;color:var(--ink)}
  .evp-opt small{font-size:10.5px;color:var(--muted);font-weight:600}
  .evp-opt span{display:flex;align-items:center;gap:8px}
  .evp-dot{width:8px;height:8px;border-radius:50%;flex:none}
  .evp-opt:hover{background:var(--gray-soft)}

  /* ═══════════ equipo ═══════════ */
  .eq-body{display:flex;flex-direction:column;gap:26px}
  .eq-h{display:flex;align-items:flex-end;justify-content:space-between;gap:16px;margin-bottom:14px}
  .eq-h h2{font-size:18px;font-weight:800;letter-spacing:-.02em}
  .eq-h p{font-size:12.5px;color:var(--muted);font-weight:500;margin-top:3px}
  .eq-h .h-btn svg{width:15px;height:15px}
  .eq-list{padding:6px 8px}
  .eq-row{display:flex;align-items:center;gap:12px;padding:11px 12px;border-radius:14px}
  .eq-row + .eq-row{border-top:1px solid var(--line)}
  .eq-row .av{
    width:34px;height:34px;border-radius:50%;flex:none;display:grid;place-items:center;
    font-style:normal;font-size:10.5px;font-weight:800;letter-spacing:.04em;background:var(--black);color:var(--on-black);
  }
  .eq-row .t{flex:1;min-width:0}
  .eq-row .t b{display:block;font-size:13px;font-weight:800;letter-spacing:-.01em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .eq-row .t b .yo{font-size:9.5px;font-weight:800;letter-spacing:.1em;text-transform:uppercase;color:var(--faint);margin-left:6px}
  .eq-row .t span{display:block;font-size:11px;color:var(--muted);font-weight:600}
  /* «tú» is a span too, and the rule above put it on a line of its own
     under the name; it belongs beside it */
  .eq-row .t b .yo{display:inline}
  /* ── la lista de PERSONAS: una fila por persona ──
     Las cifras van en medio y sólo las tiene quien sube fotos; el
     hueco vacío de quien no las sube mantiene alineada la columna del
     acceso, que es la que se lee de arriba abajo. */
  .eq-cifras{display:flex;gap:18px;flex:none;width:190px;justify-content:flex-end}
  .eq-cifras span{display:flex;flex-direction:column;align-items:flex-end;font-size:10px;color:var(--faint);font-weight:600;line-height:1.3}
  .eq-cifras span b{font-size:13px;font-weight:800;color:var(--ink);font-variant-numeric:tabular-nums}
  .eq-acceso{display:flex;align-items:center;gap:6px;flex:none;width:210px;justify-content:flex-end}
  .rol.sin{color:var(--faint);background:none;border:1px dashed var(--line)}
  /* «Dar acceso» es una invitación, no una acción de peso: se ve al
     pasar por la fila y no compite con la pastilla del papel. */
  .apill.fantasma{border-style:dashed;color:var(--muted)}
  .eq-row:hover .apill.fantasma{border-style:solid;color:var(--ink)}
  @media (max-width:1100px){
    .eq-cifras{display:none}
    .eq-acceso{width:auto}
  }
  .eq-row .rol{flex:none;font-size:9.5px;font-weight:800;letter-spacing:.1em;text-transform:uppercase;padding:4px 8px;border-radius:999px;background:var(--gray-soft);border:1px solid var(--line);color:var(--ink-soft)}
  .eq-row .rol.admin{background:var(--black);color:var(--on-black);border-color:transparent}
  .eq-row .rol.cliente{background:var(--green-soft);color:var(--green-ink);border-color:transparent}
  .eq-row .rol.equipo{background:var(--amber-soft);color:var(--amber-ink);border-color:transparent}
  .eq-row .apill{flex:none}
  .eq-row .apill.ghost{visibility:hidden}
  .eq-empty{padding:28px 16px;text-align:center;font-size:12.5px;color:var(--muted);font-weight:600}

  /* ═══════════ the floating camera button ═══════════ */
  .fab{
    position:fixed;right:26px;bottom:26px;z-index:40;
    width:58px;height:58px;border-radius:50%;
    background:var(--black);color:var(--on-black);
    display:flex;align-items:center;justify-content:center;
    box-shadow:var(--shadow-lift),inset 0 1px 0 rgba(255,255,255,.14);
    transition:transform 220ms var(--eo),box-shadow 220ms var(--eo),opacity 200ms ease;
    -webkit-tap-highlight-color:transparent;
  }
  .fab svg{width:24px;height:24px;position:relative;z-index:1}
  /* the ring: a halo that breathes slowly and opens out on hover */
  .fab .ring{
    position:absolute;inset:-6px;border-radius:50%;
    border:1.5px solid color-mix(in srgb, var(--ink) 22%, transparent);
    opacity:.55;transition:inset 260ms var(--eo),opacity 260ms ease;
  }
  @media (prefers-reduced-motion:no-preference){
    @keyframes fab-breathe{from{transform:scale(1);opacity:.55}to{transform:scale(1.12);opacity:.15}}
    .fab .ring{animation:fab-breathe 2.8s ease-in-out infinite alternate}
  }
  @media (hover:hover) and (pointer:fine){
    .fab:hover{transform:translateY(-2px) scale(1.04);box-shadow:var(--shadow-lift),inset 0 1px 0 rgba(255,255,255,.16)}
    .fab:hover .ring{inset:-10px;opacity:.9;animation:none}
  }
  .fab:active{transform:scale(.96)}
  .fab:focus-visible{outline:none;box-shadow:0 0 0 5px color-mix(in srgb, var(--ink) 16%, transparent), var(--shadow-lift)}
  /* it withdraws whenever it would get in the way: drawer open, in the
     portfolio, inside a modal, or with no obra open */
  body.choosing .fab,
  body:has(.drawer.open) .fab,
  body:has(.cfg-wrap.open) .fab,
  body:has(.lbx.open) .fab,
  body:has(.login:not(.bye)) .fab{opacity:0;transform:scale(.6);pointer-events:none}
  /* on the phone the button sits on the same line as the dock, to its
     right, and the pair (dock + camera) ends up centred: the dock shifts
     half a camera to the left to make up for it */
  /* ON THE PHONE the pair goes flat and apart. The dock takes the width
     from the left edge to the camera, with a hairline instead of glass
     and lift shadows — on a phone those read as a different product
     from the rest of the screen — and the camera sits alone at the
     right with a clear gap. Five buttons used to push the dock's right
     edge under the camera. */
  @media (max-width:760px){
    /* LA CÁMARA, ENCIMA DE LA BARRA. Compartiendo renglón le robaba a la
       barra 148 px de los 375 del teléfono, y con seis destinos cada
       botón quedaba en 34 px: menos de lo que mide un dedo. Arriba, la
       barra recupera el ancho entero y la cámara sigue a un pulgar de
       distancia. */
    .fab{
      width:52px;height:52px;left:auto;right:14px;
      bottom:calc(80px + env(safe-area-inset-bottom));
      box-shadow:var(--shadow-lift);
    }
    .fab .ring{display:none}
    /* the camera lives in the resident's bar now (ui/menu.js); the
       floating one would sit on top of the content it photographs */
    #fab-cam{display:none !important}
    /* a little frost, no lift: the content shows through the dock as
       it scrolls under, and the hairline still says where it ends */
    /* CENTRADO. Estaba anclado a la izquierda (`left:14; right:80`) para
       dejarle sitio a la cámara, y el hueco de la derecha se leía como un
       error de alineación: la barra parecía corrida, no apartada.

       Ahora va al centro y lo que cede es el ANCHO, el mismo por los dos
       lados, así que la cámara sigue teniendo su sitio despejado y la
       barra se ve centrada. Quien no tiene cámara —el cliente, sin
       `can-plan`— no necesita ceder nada y la usa más ancha. */
    .mobiledock{
      left:50%;right:auto;transform:translateX(-50%);width:min(calc(100vw - 28px),420px);
      bottom:calc(14px + env(safe-area-inset-bottom));
      justify-content:space-between;padding:6px;border-radius:18px;
      background:color-mix(in srgb, var(--card-solid) 76%, transparent);border:1px solid var(--line-strong);box-shadow:none;
      -webkit-backdrop-filter:saturate(1.4) blur(14px);backdrop-filter:saturate(1.4) blur(14px);
    }
    .mdock-btn{flex:1;width:auto;height:48px;border-radius:13px}
    .mdock-btn.active{background:var(--gray-soft);box-shadow:none}
  }
  /* four tabs and a face (ui/menu.js). The icons carry the bar on their
     own, larger; the label stays in the button for screen readers and is
     hidden from the eye, so each tab still has a name. */
  .mdock-btn{flex-direction:column;gap:0}
  .mdock-btn svg{width:24px;height:24px}
  .mdock-lbl{
    position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
    clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0;
  }
  .mdock-av{
    width:30px;height:30px;border-radius:50%;display:grid;place-items:center;flex:none;
    background:#78847E;color:#fff;font-size:10px;font-weight:800;letter-spacing:.02em;
    box-shadow:0 0 0 1.5px var(--card-solid),0 0 0 2.5px var(--line-strong);
  }
  .mdock-mas.active .mdock-av{box-shadow:0 0 0 1.5px var(--card-solid),0 0 0 3px var(--ink)}
  .mdock-mas .badge{top:2px;right:calc(50% - 22px)}
  /* the resident's camera: the bar's centre slot, raised out of it */
  .mdock-cam{overflow:visible}
  .mdock-cam-o{
    width:52px;height:52px;border-radius:50%;display:grid;place-items:center;flex:none;
    background:var(--black);color:var(--on-black);margin-top:-22px;
    box-shadow:0 0 0 4px var(--bg),var(--shadow-lift);
    transition:transform 160ms var(--eo);
  }
  .mdock-cam-o svg{width:24px;height:24px}
  .mdock-cam:active .mdock-cam-o{transform:scale(.94)}
  .mdock-cam.active{background:none}

  /* ───────── «Más»: the sheet ───────── */
  .mas-wrap{position:fixed;inset:0;z-index:60;background:var(--overlay);opacity:0;pointer-events:none;transition:opacity 200ms var(--eo)}
  .mas-wrap.open{opacity:1;pointer-events:auto}
  .mas-sheet{
    position:absolute;left:0;right:0;bottom:0;max-height:78vh;overflow:auto;
    background:var(--card-solid);border-radius:24px 24px 0 0;box-shadow:var(--shadow-lift);
    padding:8px 14px calc(18px + env(safe-area-inset-bottom));
    transform:translateY(100%);transition:transform 280ms var(--eo);
  }
  .mas-wrap.open .mas-sheet{transform:none}
  .mas-grab{width:36px;height:4px;border-radius:2px;background:var(--line-strong);margin:4px auto 12px}
  .mas-perfil{display:flex;align-items:center;gap:12px;width:100%;text-align:left;padding:10px;border-radius:16px;background:var(--gray-soft);color:var(--ink)}
  .mas-av{
    width:44px;height:44px;border-radius:50%;display:grid;place-items:center;flex:none;
    background:#78847E;color:#fff;font-size:13px;font-weight:800;
  }
  .mas-quien{flex:1;min-width:0}
  .mas-quien b{display:block;font-size:14px;font-weight:800;letter-spacing:-.01em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .mas-quien span{display:block;font-size:11.5px;color:var(--muted);font-weight:600;margin-top:1px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .mas-cfg{display:inline-flex;align-items:center;gap:2px;font-size:11.5px;font-weight:700;color:var(--muted);flex:none}
  .mas-cfg svg{width:14px;height:14px}
  .mas-obras{
    display:flex;align-items:center;gap:12px;width:100%;text-align:left;margin-top:8px;
    padding:10px 12px;border-radius:14px;border:1px solid var(--line);color:var(--ink);
  }
  .mas-obras > svg:first-child{width:18px;height:18px;flex:none;color:var(--ink)}
  .mas-obras > svg:last-child{width:14px;height:14px;flex:none;color:var(--muted)}
  .mas-obras > span{flex:1;min-width:0}
  .mas-obras b{display:block;font-size:13px;font-weight:800}
  .mas-obras > span > span{display:block;font-size:11px;color:var(--muted);font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  /* six columns, three tiles a row; a row left short (one tile, or two)
     stretches so the sheet never shows an empty slot */
  .mas-grid{display:grid;grid-template-columns:repeat(6,1fr);gap:8px;margin-top:12px}
  .mas-grid > .mas-item{grid-column:span 2}
  .mas-grid > .mas-item:last-child:nth-child(3n+1){grid-column:1 / -1}
  .mas-grid > .mas-item:nth-last-child(2):nth-child(3n+1),
  .mas-grid > .mas-item:last-child:nth-child(3n+2){grid-column:span 3}
  .mas-item{
    position:relative;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:7px;
    height:78px;border-radius:16px;border:1px solid var(--line);background:var(--card-solid);
    font-size:11.5px;font-weight:700;color:var(--ink-soft);transition:background 120ms ease,transform 120ms var(--eo);
  }
  .mas-item svg{width:22px;height:22px;color:var(--ink)}
  .mas-item:active{transform:scale(.97)}
  .mas-item.active{background:var(--gray-soft);border-color:transparent;color:var(--ink)}
  .mas-item .badge{
    position:absolute;top:8px;right:10px;min-width:16px;height:16px;padding:0 4px;border-radius:8px;
    background:var(--red);color:#fff;font-size:9.5px;font-weight:800;display:inline-flex;align-items:center;justify-content:center;
  }
  @media (min-width:761px){ .mas-wrap{display:none} }

  /* select and textarea fields in the modals, treated just like the inputs */
  .fld select.sel,.fld textarea{
    width:100%;font:inherit;font-size:13px;color:var(--ink);background:var(--card-solid);
    border:1px solid var(--line-strong);border-radius:12px;padding:10px 12px;outline:none;
  }
  .fld textarea{resize:vertical;min-height:84px;line-height:1.5}
  .fld select.sel:focus,.fld textarea:focus{border-color:var(--ink);box-shadow:0 0 0 3px var(--gray-soft)}

  /* ═══════════ the drawer: the area's diary ═══════════ */
  .bt .en .of{
    display:inline-flex;align-items:center;gap:6px;max-width:100%;margin:6px 0 2px;
    font-size:10.5px;font-weight:800;letter-spacing:.02em;color:var(--muted);
    padding:3px 9px 3px 7px;border-radius:99px;background:var(--gray-soft);text-align:left;
  }
  .bt .en .of i{width:6px;height:6px;border-radius:50%;flex:none}
  .bt .en .of:hover{color:var(--ink);background:color-mix(in srgb, var(--ink) 9%, transparent)}
  .pluma .row .sel{
    flex:1;min-width:0;height:30px;font:inherit;font-size:11.5px;font-weight:700;color:var(--ink-soft);
    background:var(--gray-soft);border:1px solid transparent;border-radius:9px;padding:0 8px;outline:none;
    text-overflow:ellipsis;
  }
  .pluma .row .sel:focus{border-color:var(--ink);background:var(--card-solid)}

  /* ═══════════ accessibility and overflow ═══════════ */

  /* All three search boxes set `outline:none` on the input and, by
     cascade order, were beating the global rule: they ended up with no
     focus signal at all. The signal is painted on the container, which
     is what you actually see. */
  .doc-search:focus-within,.ev-search:focus-within{
    border-color:var(--ink);box-shadow:0 0 0 3px var(--gray-soft);
  }
  /* the pill already shows focus; the global input halo drew a second
     ring around the text inside it */
  .doc-search input:focus-visible,.ev-search input:focus-visible{box-shadow:none;border-radius:0}

  /* A 280 px absolute menu pushed over by a button already halfway
     across the row put a horizontal scrollbar on the whole page. */
  .dd-menu{max-width:calc(100vw - 28px)}

  @media (max-width:760px){
    .tl-head .tl-kpis{max-width:none;margin:10px 0 4px;flex-basis:100%}
  }
  /* a 340 px minimum overflows on a 360-wide Android: make it always fit */
  body.choosing .pf-list{grid-template-columns:repeat(auto-fill,minmax(min(340px,100%),1fr))}
  .doc-tr:focus-visible,.bt .shot:focus-visible{outline:none;box-shadow:inset 0 0 0 2px color-mix(in srgb, var(--ink) 22%, transparent)}

/* ── the state of an account, in Equipo ──
   Administration handles the credentials from there: you have to see at
   a glance which one is suspended and which is still on its handed-out
   password. */
.eq-row .rol.baja{ background:var(--gray-soft); color:var(--ink-soft); }
.eq-row .rol.nueva{ background:color-mix(in srgb, var(--amber) 16%, transparent); color:var(--amber); }
.eq-row.baja{ opacity:.62; }
.eq-row.baja .av{ filter:grayscale(1); }
.eq-row .acts{ display:flex; align-items:center; gap:6px; flex:none; }
/* EDITAR Y QUITAR SE ESTABAN PINTANDO CON ANCHO CERO. Al fundir las dos
   listas en una sola fila de Personas, los dos botones de icono se
   quedaron con la única regla que les daba tamaño escrita para las
   tarjetas viejas (`.eq-card .acts .mini svg`), y un SVG sin medidas
   colapsa: el botón medía 0 px de ancho. Estaban en el marcado, se
   podían pulsar con el teclado, y no los veía nadie — que es como
   preguntar «¿cómo quito a una persona?» teniendo el botón delante. */
.eq-row .acts .mini{
  width:30px;height:30px;border-radius:9px;flex:none;
  display:flex;align-items:center;justify-content:center;color:var(--muted);
}
.eq-row .acts .mini:hover{background:var(--gray-soft);color:var(--ink)}
.eq-row .acts .mini svg{width:15px;height:15px}
/* quitar es rojo al acercarse: es lo único de esta fila que no se
   deshace */
.eq-row .acts .mini[data-act="quitarPersona"]:hover{background:var(--red-soft);color:var(--red-ink)}

/* ── what each role sees ──
   The CSS mirror of domain/permisos.js. `data-approve` and `.admin-only`
   already existed; the two missing ones cover most of the controls:
   planning (uploading evidencia, marking areas, keeping documents) and
   deleting. */
body:not(.can-plan) .plan-only{ display:none !important; }
/* the expediente (Documentos) is administration's to keep: can.keepDocs */
body:not(.is-admin) .docs-only{ display:none !important; }
/* THE FLOATING CAMERA BELONGS TO WHOEVER IS STANDING IN THE OBRA.
   Anyone who could plan saw it — administration included, from a desk —
   and there it is not a shortcut: it is a camera button over a screen
   with nothing to photograph. They still upload evidence from Evidencias
   and from the area's bitácora. */
body:not(.es-residente) .en-obra{ display:none !important; }
body:not(.can-delete) .delete-only{ display:none !important; }

/* ───────── aviso de versión nueva ─────────
   Abajo a la izquierda, lejos del botón de la cámara y de los avisos de
   evidencia: no compite con nada que se esté usando. Entra deslizando y
   se queda; no desaparece sola, porque lo que dice sigue siendo verdad
   hasta que se recargue. */
.nueva-version{
  /* 14 de margen del rail + 68 de ancho + 14 de aire = 96. Con
     `left:18px` el aviso quedaba DEBAJO del rail, encima de los iconos
     de tema y notificaciones. En móvil el rail no existe (se oculta a
     partir de cierto ancho) y vuelve al margen normal. */
  position:fixed;left:96px;bottom:18px;z-index:60;max-width:min(380px,calc(100vw - 114px));
  display:flex;align-items:center;gap:12px;padding:12px 12px 12px 16px;
  background:var(--glass-strong);-webkit-backdrop-filter:var(--blur);backdrop-filter:var(--blur);
  border:1px solid var(--edge);border-radius:16px;box-shadow:var(--shadow-lift);
  font-size:12.5px;color:var(--ink);
  opacity:0;transform:translateY(10px);
  transition:opacity 220ms var(--eo),transform 220ms var(--eo);
}
.nueva-version.entra{opacity:1;transform:none}
.nueva-version b{font-weight:700}
.nueva-version .sub{color:var(--muted);font-size:11.5px}
.nueva-version .nv-ok{
  flex:none;padding:8px 13px;border-radius:11px;font-size:12px;font-weight:700;
  background:var(--black);color:var(--on-black);
}
/* Punto Paralelo's --black is stone, which left «Actualizar» looking
   like a chip; the one call to action here is true black */
:root[data-theme="concreto"] .nueva-version .nv-ok{background:#0A0A0A;color:#FFFFFF}
.nueva-version .nv-x{flex:none;display:flex;padding:6px;color:var(--muted);border-radius:9px}
.nueva-version .nv-x svg{width:14px;height:14px}
@media (hover:hover) and (pointer:fine){
  .nueva-version .nv-x:hover{background:var(--gray-soft);color:var(--ink)}
}
@media (prefers-reduced-motion:reduce){
  .nueva-version{transition:none;opacity:1;transform:none}
}
@media (max-width:860px){
  .nueva-version{left:14px;right:14px;max-width:none}
}

/* ───────── avisos · la bandeja ───────── */
.ib{margin:8px 4px 40px}
.ib .ib-head{max-width:820px}
/* dos columnas que empiezan juntas: el contenido a su ancho de lectura y
   el calendario pegado a él con un hueco normal, no arrinconado contra
   el borde derecho de una pantalla ancha */
/* la bandeja ocupa el ancho de la pantalla como todo lo demás; el
   calendario, cuando está, se queda en su columna */
.ib-cols{display:grid;grid-template-columns:minmax(0,1fr);gap:48px;align-items:start}
.ib.con-lado .ib-cols{grid-template-columns:minmax(0,1fr) minmax(360px,440px)}
.ib-main{min-width:0}
/* nivelado con la primera tarjeta, no con el título de su sección */
.ib-side{position:sticky;top:18px;min-width:0;margin-top:28px}
@media (max-width:1180px){
  .ib.con-lado .ib-cols{grid-template-columns:minmax(0,1fr)}
  .ib-side{position:static;order:-1;margin-top:0}
}
.ib-head{display:flex;align-items:center;justify-content:space-between;gap:12px;margin:8px 0 18px}
.ib-count{font-size:13.5px;font-weight:700}
.ib-head .h-btn:disabled{opacity:.45;cursor:default}
.ib-sec{margin-bottom:22px}
.ib-sec-h{display:flex;align-items:center;gap:8px;font-size:12px;font-weight:800;letter-spacing:.02em;margin:0 0 10px 2px}
.ib-sec-h svg{width:15px;height:15px}
.ib-warn{color:var(--violet-ink)}
.ib-amber{color:var(--amber-ink)}
.ib-pends{display:flex;flex-direction:column;gap:8px}
.ib-pend{
  display:flex;align-items:center;gap:12px;width:100%;text-align:left;
  padding:12px 14px;
  transition:transform 160ms var(--eo),box-shadow 160ms ease;
}
.ib-pend:hover{transform:translateY(-1px);box-shadow:var(--shadow-lift)}
.ib-pend i{width:8px;height:8px;border-radius:50%;flex:none}
.ib-pend .tt{display:flex;flex-direction:column;gap:1px;min-width:0;flex:1}
.ib-pend .tt b{font-size:13px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ib-pend .tt span{font-size:11px;color:var(--muted);font-weight:600}
.ib-pend .go{font-size:11.5px;font-weight:800;color:var(--ink);white-space:nowrap}
.ib-chips{display:flex;gap:6px;flex-wrap:wrap;margin:4px 0 6px}
.ib-day{margin-top:14px}
.ib-day-h{display:flex;align-items:baseline;gap:10px;padding:10px 2px 4px}
.ib-day-h b{font-size:11px;font-weight:800;letter-spacing:.08em;text-transform:uppercase;color:var(--muted)}
.ib-day-h span{font-size:11px;color:var(--faint);margin-left:auto}
.ib-ev{
  display:flex;align-items:center;gap:12px;padding:10px 10px;border-radius:14px;
  transition:background 140ms ease;
}
.ib-ev[role="button"]{cursor:pointer}
.ib-ev[role="button"]:hover{background:var(--gray-soft)}
.ib-ev .fico{
  width:34px;height:34px;border-radius:12px;flex:none;
  display:flex;align-items:center;justify-content:center;
  border:1px solid var(--edge);box-shadow:var(--shadow);background:var(--glass-strong);
}
.ib-ev .fico svg{width:15px;height:15px}
.ib-body{min-width:0;flex:1}
.ib-txt{font-size:12.5px;line-height:1.4;color:var(--ink-soft)}
.ib-txt b{color:var(--ink)}
.ib-of{display:flex;align-items:center;gap:6px;font-size:11px;font-weight:700;color:var(--muted);margin-top:2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ib-of i{width:6px;height:6px;border-radius:50%;flex:none}
.ib-when{font-size:10.5px;color:var(--faint);font-weight:700;flex:none;font-variant-numeric:tabular-nums}
.ib-dot{width:7px;height:7px;border-radius:50%;background:transparent;flex:none}
.ib-ev.unread .ib-dot{background:var(--red)}
.ib-ev.unread .ib-txt{color:var(--ink)}
.ib-ev.unread .ib-txt b{font-weight:800}
.ib-ev:not(.unread){opacity:.78}

/* ───────── avisos · el calendario ───────── */
.ib-controles{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;margin:4px 0 14px}
.ib-controles .ib-chips{margin:0}
.ib-vista button{padding:6px 12px;font-size:12px}
.cal{padding:16px 16px 12px}
.cal-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:12px}
.cal-title{font-size:14px;font-weight:800;letter-spacing:-.01em;text-transform:capitalize}
.cal-nav-g{display:inline-flex;gap:5px}
.cal-nav{width:30px;height:30px;border:1px solid var(--line-strong);border-radius:9px;color:var(--muted);font-size:16px;line-height:1;display:flex;align-items:center;justify-content:center}
.cal-nav:hover{color:var(--ink);background:var(--gray-soft)}
.cal-wd{display:grid;grid-template-columns:repeat(7,1fr);gap:4px;margin-bottom:4px}
.cal-wd span{text-align:center;font-size:10px;font-weight:800;letter-spacing:.06em;color:var(--faint)}
.cal-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:4px}
.cal-cell{
  position:relative;aspect-ratio:1;border:1px solid transparent;border-radius:10px;
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;padding:0;
  transition:border-color 120ms ease,background 120ms ease;cursor:default;
}
.cal-blank{visibility:hidden}
.cal-n{font-size:13px;color:var(--faint);font-variant-numeric:tabular-nums}
.cal-cell.has{cursor:pointer;background:var(--card-solid);border-color:var(--line)}
.cal-cell.has .cal-n{color:var(--ink);font-weight:600}
.cal-cell.has:hover{border-color:var(--line-strong)}
.cal-cell.today{border-color:var(--ink)}
.cal-cell.today .cal-n{font-weight:800}
.cal-cell.sel{background:var(--black);border-color:var(--black)}
.cal-cell.sel .cal-n{color:var(--on-black)}
.cal-dots{display:flex;gap:3px;height:5px;align-items:center}
.cal-dot{width:5px;height:5px;border-radius:50%}
.cal-cell.sel .cal-dot{background:var(--on-black) !important;opacity:.85}
.cal-new{
  position:absolute;top:-5px;right:-5px;min-width:16px;height:16px;padding:0 4px;border-radius:8px;
  background:var(--red);color:#fff;font-size:9.5px;font-weight:800;line-height:16px;text-align:center;
  border:1.5px solid var(--card-solid);font-variant-numeric:tabular-nums;
}
.cal-foot{margin-top:10px;font-size:11px;color:var(--faint);font-weight:600}
.cal-day-h{display:flex;align-items:baseline;gap:10px;padding:6px 2px 8px}
.cal-day-h b{font-size:11px;font-weight:800;letter-spacing:.08em;text-transform:uppercase;color:var(--muted)}
.cal-day-h span{font-size:11px;color:var(--faint);margin-left:auto}
.cal-day{margin-top:6px}
.cal-list{min-height:120px}
.cal-empty{color:var(--faint);font-size:12.5px;padding:22px 8px}

/* ───────── tu foto · el encuadre ───────── */
.cfg-wrap.recorte{z-index:57}
/* the client's decisions open from the thread (.recorte): above it */
#firmadlg,#cambiosdlg{z-index:58}
/* the forced password change opens right after sign-in, while the door
   (#login, 60) is still on its way out: it has to be on top of it */
#pwdlg{z-index:61}
.rc-stage{
  position:relative;width:280px;height:280px;margin:0 auto;border-radius:22px;overflow:hidden;
  background:var(--gray-soft);cursor:grab;touch-action:none;user-select:none;
  box-shadow:inset 0 0 0 1px var(--edge);
}
.rc-stage.moviendo{cursor:grabbing}
.rc-stage canvas{display:block;width:280px;height:280px}
.rc-zoom-row{display:flex;align-items:center;gap:10px;margin:16px 6px 0;color:var(--muted)}
.rc-zoom-row svg{width:15px;height:15px;flex:none}
.rc-zoom-row input{flex:1;accent-color:var(--ink)}
.rc-hint{text-align:center;font-size:11px;color:var(--faint);font-weight:600;margin-top:8px}
.rc-row{display:flex;align-items:center;gap:10px;margin-top:14px}
.rc-prev{width:56px;height:56px;border-radius:16px;overflow:hidden;flex:none;box-shadow:inset 0 0 0 1px var(--edge);background:var(--gray-soft)}
.rc-prev canvas{display:block;width:56px;height:56px}
.rc-row .lbl{font-size:11px;font-weight:700;color:var(--muted)}
.rc-row .sp{flex:1}
.rc-link{font-size:12px;font-weight:700;color:var(--ink-soft);padding:6px 10px;border-radius:9px;white-space:nowrap}
.rc-link:hover{background:var(--gray-soft);color:var(--ink)}
.rc-link.danger{color:var(--red-ink)}
.rc-link.danger:hover{background:var(--red-soft)}

/* ───────── varias fotos · el collage ───────── */
.cl-previa{border-radius:16px;overflow:hidden;background:var(--gray-soft);min-height:120px;box-shadow:inset 0 0 0 1px var(--edge)}
.cl-previa canvas{display:block}
.cl-opciones{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-top:16px}
.cl-opt{
  display:flex;flex-direction:column;align-items:flex-start;gap:4px;text-align:left;
  padding:12px 14px;border-radius:14px;border:1px solid var(--line-strong);background:var(--card-solid);
  transition:border-color 140ms ease,background 140ms ease,transform 160ms var(--eo);
}
.cl-opt b{font-size:13px}
.cl-opt span{font-size:11px;color:var(--muted);font-weight:500;line-height:1.4}
.cl-opt:hover{border-color:var(--ink);transform:translateY(-1px)}
.cl-opt:disabled{opacity:.5;transform:none}
@media (max-width:480px){ .cl-opciones{grid-template-columns:1fr} }

/* ───────── the camera button is for the site ─────────
   On a phone or a tablet the person is standing in the obra and the
   photo is one tap away. At a desk there is the Evidencias page and the
   drawer's camera; the floating button only covered the content. */
@media (min-width:1024px){
  .fab{display:none !important}
}

/* ───────── first paint: the bars come in ───────── */
@media (prefers-reduced-motion:no-preference){
  @keyframes bar-in{from{opacity:0;transform:translateX(-8px)}to{opacity:1;transform:none}}
  .bar.bar-in{animation:bar-in 360ms var(--eo) both;animation-delay:calc(var(--bi,0) * 24ms)}
}
#chart-tip{transition:opacity 200ms ease}

/* ═══════════════════════════════════════════════════════════════
   CHECK-INS · who was on site each day (ui/checkins.js)
   ═══════════════════════════════════════════════════════════════ */
/* ── the card on Avance ── */
.ck-card{padding-bottom:16px}
.ck-card .card-head{align-items:baseline}
.ck-date{font-size:12px;color:var(--muted);font-weight:600}
.ck-date b{color:var(--ink)}
.ck-empty{padding:26px 20px;font-size:12.5px;color:var(--faint);font-weight:600;text-align:center}
.ck-av{width:32px;height:32px;border-radius:50%;flex:none;display:grid;place-items:center;font-size:10px;font-weight:800;color:#fff;letter-spacing:.02em;overflow:hidden;background:var(--gray-acc)}
.ck-av.big{width:44px;height:44px;border-radius:15px;font-size:12px}
.ck-av img{width:100%;height:100%;object-fit:cover;display:block}
.ck-av.photo{background:var(--gray-soft)}
.ck-me{display:flex;align-items:center;gap:12px;padding:16px 20px 12px}
.ck-me .t{flex:1;min-width:0}
.ck-me .t b{display:block;font-size:14px;font-weight:800;letter-spacing:-.01em}
.ck-me .t span{display:block;font-size:11.5px;color:var(--muted);font-weight:600;margin-top:1px}
.ck-me.in .t span{color:var(--green-ink)}
.ck-me .t span b{font-weight:800;font-size:inherit;display:inline;color:inherit}
.ck-btn{white-space:nowrap;flex:none}
.ck-btn svg{width:15px;height:15px}
.ck-me .apill{flex:none}
.ck-me .apill svg{width:13px;height:13px;margin-right:5px}
/* the strip's buttons: arrival, «Otra foto», the exit */
.ck-me-acts{display:flex;align-items:center;gap:6px;flex:none}
/* the day's span once the exit is in: arrival → exit */
.ck-jornada{font-size:11px;font-weight:800;color:var(--green-ink);background:var(--green-soft);padding:5px 10px;border-radius:99px;font-variant-numeric:tabular-nums;white-space:nowrap;align-self:center}
.ck-out{margin-left:6px}
.ck-week{display:flex;justify-content:space-between;gap:6px;padding:0 20px 4px;max-width:360px}
.ck-week i{width:30px;height:30px;border-radius:50%;display:grid;place-items:center;font-style:normal;font-size:10px;font-weight:800;color:var(--faint);border:1.5px dashed var(--line-strong)}
.ck-week i.in{border:none;background:var(--green-soft);color:var(--green-ink)}
.ck-week i.off,.ck-week i.future,.ck-week i.none{border-color:var(--line);color:var(--line-strong)}
.ck-week i.none{border-style:dotted}
.ck-week i.today{border:1.5px solid var(--ink);color:var(--ink)}
.ck-week i.in.today{background:var(--green-soft);border-color:var(--green-ink);color:var(--green-ink)}
.ck-list{margin:10px 12px 0;padding:6px 0 0;border-top:1px solid var(--line)}
.ck-label{font-size:9.5px;font-weight:800;letter-spacing:.12em;text-transform:uppercase;color:var(--faint);padding:8px 8px 4px}
.ck-row{display:flex;align-items:center;gap:10px;padding:7px 8px;border-radius:12px}
.ck-row .t{flex:1;min-width:0}
.ck-row .t b{display:block;font-size:12.5px;font-weight:800;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ck-row .t span{display:block;font-size:10.5px;color:var(--muted);font-weight:600}
.ck-time{font-size:11px;font-weight:800;color:var(--green-ink);background:var(--green-soft);padding:4px 9px;border-radius:99px;font-variant-numeric:tabular-nums}
.ck-cam{width:34px;height:34px;border-radius:11px;background:var(--gray-soft);color:var(--ink-soft);display:grid;place-items:center;border:1px solid var(--line)}
.ck-cam:hover{background:var(--black);color:var(--on-black);border-color:transparent}
.ck-cam svg{width:15px;height:15px}

/* ── the one-line version, for administration ── */
.ck-mini{display:flex;align-items:center;gap:14px;padding:10px 14px;flex-wrap:wrap}
.ck-mini-t b{display:block;font-size:13px;font-weight:800;letter-spacing:-.01em}
.ck-mini-t span{display:block;font-size:10.5px;color:var(--muted);font-weight:600}
.ck-mini-n{font-size:12px;color:var(--muted);font-weight:600;padding-left:14px;border-left:1px solid var(--line)}
.ck-mini-n b{color:var(--ink);font-weight:800}
.ck-faces{display:flex;align-items:center;flex:1;min-width:0}
.ck-face{width:28px;height:28px;border-radius:50%;overflow:hidden;border:2px solid var(--card-solid);margin-left:-8px;background:var(--gray-soft);display:grid;place-items:center;font-size:9.5px;font-weight:800;color:var(--ink-soft);flex:none;transition:transform 120ms var(--eo)}
.ck-face:first-child{margin-left:0}
.ck-face img{width:100%;height:100%;object-fit:cover;display:block}
.ck-face:not(.more){cursor:zoom-in}
.ck-face:not(.more):hover{transform:translateY(-2px);z-index:1}
.ck-mini-acts{display:flex;gap:6px;margin-left:auto}
.ck-mini-acts .apill{white-space:nowrap}
.ck-mini-acts .apill svg{width:13px;height:13px;margin-right:5px}
.ck-mini .ck-empty{padding:4px 0}

/* ── the grid on Equipo ── */
.ck-nav{display:flex;align-items:center;gap:6px}
.ck-nav b{font-size:13px;font-weight:800;letter-spacing:-.01em;min-width:132px;text-align:center;text-transform:capitalize}
.ck-nav .apill.sq{width:28px;padding:0;justify-content:center;font-size:15px}
.ck-nav .h-btn{margin-left:6px}
.ck-nav .h-btn svg{width:14px;height:14px}
.ck-grid{padding:14px 16px 16px;overflow-x:auto}
.ck-legend{display:flex;gap:14px;align-items:center;font-size:10.5px;color:var(--muted);font-weight:700;margin-bottom:12px;flex-wrap:wrap}
.ck-legend i{display:inline-block;width:10px;height:10px;border-radius:50%;margin-right:5px;vertical-align:-1px;box-sizing:border-box}
.ck-legend .in{background:var(--green)}
.ck-legend .out{border:1.5px solid var(--line-strong)}
.ck-legend .none{background:var(--line)}
.ck-legend-n{margin-left:auto;color:var(--faint)}
.ck-table{display:grid;grid-template-columns:180px repeat(var(--n,26),minmax(18px,1fr)) 62px;gap:5px 3px;align-items:center;min-width:760px}
.ck-dh{font-size:9px;font-weight:800;color:var(--faint);text-align:center;font-variant-numeric:tabular-nums;line-height:1.1}
.ck-dh em{display:block;font-style:normal;font-size:8px;letter-spacing:.04em;color:var(--line-strong)}
.ck-dh.today{color:var(--ink)}
.ck-total-h{font-size:9px;font-weight:800;color:var(--faint);text-align:right;text-transform:uppercase;letter-spacing:.1em}
.ck-who{display:flex;align-items:center;gap:9px;min-width:0;padding-right:8px}
.ck-who .ck-av{width:26px;height:26px;font-size:9px}
.ck-who b{display:block;font-size:12px;font-weight:800;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ck-who span{display:block;font-size:10px;color:var(--muted);font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ck-who > div{min-width:0}
.ck-c{aspect-ratio:1;width:100%;max-width:26px;border-radius:50%;justify-self:center;position:relative;overflow:hidden;box-sizing:border-box;display:block;padding:0}
.ck-c.in{background:var(--green);cursor:zoom-in;transition:transform 120ms var(--eo)}
.ck-c.in:hover{transform:scale(1.18);z-index:1}
.ck-c img{width:100%;height:100%;object-fit:cover;display:block}
.ck-c.out{border:1.5px solid var(--line-strong)}
.ck-c.out.today{border-color:var(--red);border-style:dashed}
.ck-c.none{width:8px;max-width:8px;height:8px;background:var(--line);opacity:.7;aspect-ratio:auto}
.ck-c.future{border:1.5px dashed var(--line);opacity:.5}
.ck-total{font-size:12px;font-weight:800;text-align:right;font-variant-numeric:tabular-nums;line-height:1.1}
.ck-total span{display:block;font-size:9px;color:var(--muted);font-weight:700}
.ck-total.low{color:var(--red)}
.ck-total.none{color:var(--faint)}
.ck-tip{position:fixed;z-index:60;background:var(--card-solid);border:1px solid var(--edge);box-shadow:var(--shadow-lift);border-radius:14px;padding:6px;display:flex;flex-direction:column;gap:6px;pointer-events:none;width:150px;animation:fade-in 120ms ease}
.ck-tip img{width:138px;height:138px;border-radius:10px;object-fit:cover;display:block}
.ck-tip span{font-size:10.5px;font-weight:700;color:var(--ink-soft);padding:0 2px 2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
@keyframes fade-in{from{opacity:0}to{opacity:1}}

/* ── the strip on Evidencias ── */
.ck-day{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:8px 12px;border-radius:16px;background:var(--gray-soft);margin:2px 0 12px}
.ck-day .ck-label{padding:0 4px 0 2px}
.ck-chip{display:inline-flex;align-items:center;gap:7px;padding:3px 10px 3px 3px;border-radius:99px;background:var(--card-solid);border:1px solid var(--edge);font-size:11.5px;color:var(--ink)}
.ck-chip .ck-av{width:22px;height:22px;font-size:8px}
.ck-chip b{font-weight:800}
.ck-chip span{font-size:10.5px;font-weight:800;color:var(--green-ink);font-variant-numeric:tabular-nums}
.ck-chip.in{cursor:zoom-in}
.ck-chip.in:hover{border-color:var(--line-strong)}
.ck-chip.out{background:transparent;border-style:dashed}
.ck-chip.out .ck-av{background:transparent;border:1.5px dashed var(--line-strong);color:var(--faint)}
.ck-chip.out b,.ck-chip.out span{color:var(--muted)}
.ck-sep{width:1px;height:18px;background:var(--line);margin:0 2px}
.ck-nobody{font-size:11.5px;color:var(--muted);font-weight:600}
@media (max-width:760px){
  .ck-mini-acts{margin-left:0;width:100%}
  .ck-mini-n{border-left:none;padding-left:0}
  .ck-me{padding:14px 16px 10px;flex-wrap:wrap}
  .ck-me .ck-btn{width:100%;justify-content:center;margin-top:4px}
  .ck-me-acts{width:100%;flex-wrap:wrap}
  .ck-me-acts .ck-btn{flex:1;width:auto;margin-top:0}
  .ck-me-acts .ck-ausente{flex:1;justify-content:center}
  .ck-week{max-width:none;padding:2px 16px 6px}
  .ck-week i{width:34px;height:34px}
  .ck-nav b{min-width:0}

  /* EQUIPO ON A PHONE. The section headers put a paragraph and a row of
     controls side by side, so on a phone the paragraph became a column
     four words wide and «Dar de alta» a tall box with its icon on a line
     of its own; the person rows put name, role and actions on one line
     and the name was cut to «Danie…». Here the header stacks, the
     month bar takes the width with the month in the middle, the add
     button becomes a full-width primary, and each row keeps the name on
     the line beside the face with the role and actions underneath. */
  .eq-h{flex-direction:column;align-items:stretch;gap:12px}
  .eq-h > .h-btn.cta{width:100%;justify-content:center;white-space:nowrap}
  .ck-nav{width:100%}
  .ck-nav b{flex:1;white-space:nowrap}
  /* the arrows are apills, which grow by default: here they keep their size */
  .ck-nav .apill.sq{flex:none;width:34px;height:34px}
  .ck-nav .h-btn{margin-left:auto;white-space:nowrap}
  .eq-row{flex-wrap:wrap;row-gap:8px}
  .eq-row .t{flex:1 1 calc(100% - 56px)}
  .eq-row .t span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .eq-acceso{width:auto;margin-left:48px;justify-content:flex-start}
  .eq-row .acts{margin-left:auto}
}

/* ═══════════════════════════════════════════════════════════════
   THE REPORT WINDOW (ui/report.js)
   ═══════════════════════════════════════════════════════════════ */
/* El cuadro es ancho porque enseña el documento: elegir a ciegas y
   descargar para ver si quedó bien era el trabajo que hacía el cliente.
   La columna de la izquierda manda; la derecha es el papel. */
.cfg.rep{width:min(1040px,95vw);height:min(760px,calc(100vh - 40px));padding:0;overflow:hidden}
.rep-cols{display:grid;grid-template-columns:minmax(0,356px) minmax(0,1fr);height:100%}
.rep-lado{display:flex;flex-direction:column;min-height:0;overflow:auto;padding:24px 26px 22px}
.rep-sub{font-size:12px;color:var(--muted);margin:4px 0 14px}
.rep-lbl{display:flex;align-items:baseline;justify-content:space-between;gap:10px;font-size:9.5px;font-weight:800;letter-spacing:.12em;text-transform:uppercase;color:var(--faint);margin:14px 0 8px}
.rep-lbl span{letter-spacing:.02em;text-transform:none;font-weight:600;font-size:10.5px;opacity:.85}
.rep-rango{display:flex}
.rep-rango button{flex:1;text-align:center}
.rep-fechas{font-size:11.5px;color:var(--muted);font-weight:600;margin-top:8px;padding-left:2px}
.rep-secciones{display:flex;flex-direction:column;gap:6px}
.rep-sec{display:flex;align-items:flex-start;gap:8px;padding:9px 11px;border-radius:12px;border:1px solid var(--line);cursor:pointer;transition:border-color 120ms ease,background 120ms ease,opacity 120ms ease}
.rep-sec:hover{background:var(--gray-soft)}
/* marcada = elevada, no enmarcada en blanco */
.rep-sec:has(input:checked){border-color:var(--edge);background:var(--gray-soft);box-shadow:var(--shadow)}
.rep-sec input{margin-top:3px;accent-color:var(--ink);width:15px;height:15px;flex:none}
.rep-sec>span:last-child{display:flex;flex-direction:column;gap:1px;min-width:0}
.rep-sec b{font-size:12.5px;font-weight:800}
.rep-sec small{font-size:11px;color:var(--muted);font-weight:500;line-height:1.35}
/* el asa: sólo se ve cuando el cursor está encima de su fila */
.rep-grip{display:block;width:14px;height:16px;flex:none;color:var(--faint);opacity:.45;cursor:grab;transition:opacity 120ms ease}
.rep-grip svg{width:14px;height:16px;display:block}
.rep-sec:hover .rep-grip{opacity:1}
/* la fila que se lleva el cursor queda como hueco: punteada y plana,
   para que se lea dónde va a caer y no como una fila apagada */
/* con el prefijo para ganarle a `:has(input:checked)`, que trae su
   sombra: un hueco con sombra no parece un hueco */
.rep-secciones .rep-sec.moviendo{opacity:.5;border-style:dashed;box-shadow:none;cursor:grabbing}
.rep-sec.moviendo .rep-grip{cursor:grabbing}
.rep-acts{display:flex;justify-content:flex-end;gap:8px;margin-top:auto;padding-top:18px}
.rep-acts .apill{flex:none}
.rep-acts .h-btn svg{width:14px;height:14px}

/* ── el papel ── */
/* `min-height:0` NO ES DECORACIÓN. Sin él, esta columna de la rejilla
   mide lo que miden sus hojas —1522px para dos páginas— en vez de la
   altura del cuadro: el marco crecía, `.rep-hojas` con su `height:100%`
   crecía con él, y lo que tenía que desplazarse se quedaba quieto
   mientras el cuadro recortaba la segunda página. */
.rep-previa{display:flex;flex-direction:column;min-width:0;min-height:0;background:var(--gray-soft);box-shadow:inset 1px 0 0 var(--line)}
.rep-previa-h{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:20px 54px 12px 22px;font-size:9.5px;font-weight:800;letter-spacing:.12em;text-transform:uppercase;color:var(--faint)}
.rep-previa-h span:last-child{letter-spacing:.02em;text-transform:none;font-size:11px;font-weight:700;color:var(--muted);font-variant-numeric:tabular-nums}
.rep-marco{position:relative;flex:1;min-height:0;margin:0 22px 22px;border-radius:16px;overflow:hidden;background:var(--card-solid);box-shadow:var(--shadow-lift)}
.rep-hojas{width:100%;height:100%;overflow:auto;border-radius:inherit}
/* Las hojas del reporte usan el mismo molde que las del visor; aquí sólo
   se aprieta el aire, porque la columna es más estrecha. */
.rep-hojas .visor-pdf{padding:14px 16px 18px;gap:12px}
.rep-marco.vacio .rep-hojas{visibility:hidden}
/* mientras se arma: el papel de antes se queda, atenuado */
/* el radio va repetido a propósito: un hijo con backdrop-filter se sale
   del `overflow:hidden` redondeado del padre y le deja las esquinas
   cuadradas mientras carga */
.rep-cargando{
  position:absolute;inset:0;display:flex;align-items:center;justify-content:center;gap:10px;
  border-radius:inherit;
  font-size:12px;font-weight:700;color:var(--muted);
  background:color-mix(in srgb,var(--card-solid) 78%,transparent);
  -webkit-backdrop-filter:var(--blur);backdrop-filter:var(--blur);
  opacity:0;pointer-events:none;transition:opacity 160ms ease;
}
.rep-marco.cargando .rep-cargando{opacity:1}
/* nada marcado: el cuadro lo dice, sin recado ni ruleta */
.rep-vacio{
  position:absolute;inset:0;display:flex;align-items:center;justify-content:center;border-radius:inherit;
  padding:0 40px;text-align:center;font-size:12.5px;font-weight:600;color:var(--faint);
  background:var(--card-solid);opacity:0;pointer-events:none;transition:opacity 160ms ease;
}
.rep-marco.vacio .rep-vacio{opacity:1}
.rep-spin{width:14px;height:14px;flex:none;border-radius:50%;border:2px solid var(--line);border-top-color:var(--ink);animation:rep-gira 700ms linear infinite}
@keyframes rep-gira{to{transform:rotate(360deg)}}
@media (prefers-reduced-motion:reduce){.rep-spin{animation-duration:2s}}

/* En pantalla angosta el documento no cabe al lado: se elige aquí y se
   ve al abrirlo. Nada de un cuadro de vista previa de tres centímetros. */
@media (max-width:900px){
  .cfg.rep{width:min(440px,94vw);height:auto;max-height:calc(100vh - 40px);overflow:auto}
  .rep-cols{display:block}
  .rep-lado{padding:24px 26px 22px;overflow:visible}
  /* el dedo no arrastra: el asa del ratón no existe aquí, y prometerlo
     sería mentir. El orden elegido en el escritorio sigue valiendo. */
  .rep-lbl span,.rep-grip{display:none}
  .rep-previa{display:none}
}

/* ═══════════════════════════════════════════════════════════════
   EL AVANCE · lo dice quien sube la evidencia (ui/progress.js)
   ═══════════════════════════════════════════════════════════════ */
.cfg.av{width:min(440px,94vw)}

/* ═══════════════════════════════════════════════════════════════
   EL VISOR · mirar un documento sin bajarlo (ui/viewer.js)
   ═══════════════════════════════════════════════════════════════ */
/* ── LA ESPERA ──
   Un hueco vacío que de golpe se llena es un parpadeo. Un esqueleto con
   la forma de lo que viene, y un fundido al llegar, es una carga: nada
   cambia de sitio y la vista no tiene que volver a buscar dónde estaba.
   El barrido es lentísimo a propósito — 1.6s — porque un brillo rápido
   llama la atención hacia la espera en vez de disimularla. */
/* El hueso NO puede ser del color de su hueco: `--gray-soft` es
   justamente el fondo de las dos columnas, así que el esqueleto salía
   invisible y la espera se veía como un panel vacío — el parpadeo que
   venía a tapar. Va un escalón por encima de donde se apoya. */
.sk{position:relative;overflow:hidden;background:color-mix(in srgb,var(--line) 65%,transparent);border-radius:10px}
.sk::after{
  content:"";position:absolute;inset:0;transform:translateX(-100%);
  background:linear-gradient(90deg,transparent,color-mix(in srgb,var(--card-solid) 70%,transparent),transparent);
}
@media (prefers-reduced-motion:no-preference){
  .sk::after{animation:sk-barrido 1600ms ease-in-out infinite}
}
@keyframes sk-barrido{100%{transform:translateX(100%)}}
/* the screens' first load (ui/carga.js): a skeleton shaped like the
   rows, tiles, cards or grid that are coming */
/* hosts like the documents table are fixed-height flex columns: the
   skeleton must not shrink to fit them */
.sk-wrap{display:flex;flex-direction:column;flex:none;padding:4px 14px}
.sk-wrap > *{flex:none}
.sk-l{display:block;height:11px;border-radius:99px}
.sk-l.fina{height:8px;margin-top:7px}
.sk-renglon{display:flex;align-items:center;gap:12px;padding:12px 4px;border-bottom:1px solid var(--line)}
.sk-renglon:last-child{border-bottom:0}
.sk-ic{width:32px;height:32px;border-radius:10px;flex:none}
.sk-ic.redondo{border-radius:50%;width:28px;height:28px}
.sk-txt{flex:1;min-width:0}
.sk-pill{width:64px;height:22px;border-radius:99px;flex:none}
.sk-tomas{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:10px}
.sk-toma{aspect-ratio:4/3;border-radius:14px}
/* the portfolio list is already a grid: the cards take its cells */
.sk-wrap.sk-obras{display:contents}
.sk-obra{border:1px solid var(--line);border-radius:20px;padding:20px 22px;background:var(--card)}
.sk-barra{display:block;height:6px;border-radius:99px;margin:18px 0 6px}
.sk-rj{display:flex;align-items:center;gap:10px;padding:9px 4px}
.sk-rj .sk-l{width:90px;flex:none}
.sk-celdas{display:flex;gap:6px;flex:1;min-width:0;overflow:hidden}
.sk-celda{width:22px;height:22px;border-radius:50%;flex:none}
.visor-skel{padding:22px 24px;display:flex;flex-direction:column;gap:10px}
.visor-skel.pagina{align-items:center;padding:24px}
.sk-pagina{background:var(--card-solid);width:min(760px,100%);aspect-ratio:1/1.1;padding:44px 52px;display:flex;flex-direction:column;gap:14px;border-radius:12px}
.sk-linea{height:11px;border-radius:99px;background:color-mix(in srgb,var(--line) 70%,transparent);width:70%}
.sk-linea.larga{width:92%;height:16px}
.sk-linea.corta{width:44%}
/* the loading panel over the page skeleton (ui/viewer.js) */
.visor-skel.pagina{position:relative}
.visor-carga{
  position:absolute;left:50%;top:min(38%,240px);transform:translateX(-50%);
  width:min(300px,calc(100% - 48px));display:flex;flex-direction:column;align-items:center;gap:8px;
  padding:18px 20px 16px;border-radius:16px;background:var(--card-solid);box-shadow:var(--shadow-lift);text-align:center;
}
.visor-carga b{font-size:13px;font-weight:700;color:var(--ink)}
.visor-carga small{font-size:11px;font-weight:600;color:var(--muted);font-variant-numeric:tabular-nums;min-height:14px}
@keyframes vc-giro{to{transform:rotate(360deg)}}
.vc-spin{width:26px;height:26px;border-radius:50%;border:2.5px solid color-mix(in srgb, var(--ink) 14%, transparent);border-top-color:var(--ink);animation:vc-giro 800ms linear infinite}
:root[data-theme="concreto"] .vc-spin{border-top-color:#6B7A6F}
.vc-bar{width:100%;height:5px;border-radius:99px;background:color-mix(in srgb, var(--ink) 10%, transparent);overflow:hidden}
.vc-bar i{display:block;height:100%;width:0;border-radius:99px;background:var(--progress);transition:width 160ms linear}
:root[data-theme="concreto"] .vc-bar i{background:#6B7A6F}
@media (prefers-reduced-motion:reduce){ .vc-spin{animation-duration:2400ms} }
.sk-cab{height:34px}
.sk-fila{height:26px;opacity:.7}
.hilo-skel{display:flex;flex-direction:column;gap:12px}
.sk-corte{height:10px;width:66%;align-self:center;border-radius:99px}
.sk-burbuja{height:58px;width:72%;border-radius:16px}
.sk-burbuja.mia{align-self:flex-end;width:60%}
/* lo que llega, llega subiendo un poco */
.visor-entra{opacity:0;transform:translateY(6px);transition:opacity 260ms var(--eo),transform 260ms var(--eo)}
.visor-entra.puesto{opacity:1;transform:none}
.visor-skel.se-va{opacity:0;transition:opacity 220ms ease}
/* el esqueleto y lo de verdad comparten hueco mientras se cruzan */
.visor-cuerpo,.hilo-cuerpo{position:relative}
.visor-cuerpo>.visor-skel,.hilo-cuerpo>.hilo-skel{position:absolute;inset:0}
.hilo-cuerpo>.hilo-skel{padding:18px 24px}
@media (prefers-reduced-motion:reduce){
  .visor-entra{transition:opacity 140ms ease;transform:none}
  .visor-entra.puesto{transform:none}
}

.visor-wrap{z-index:60;padding:0}
.visor{
  position:relative;width:min(1100px,96vw);height:min(92vh,960px);
  display:flex;flex-direction:column;overflow:hidden;
  background:var(--glass-strong);-webkit-backdrop-filter:var(--blur);backdrop-filter:var(--blur);
  border:1px solid var(--edge);border-radius:20px;box-shadow:var(--shadow-lift);
  transform:scale(.97);transition:transform 220ms var(--eo);
}
.cfg-wrap.open .visor{transform:none}
/* Una hoja de obra reparte diez columnas; un contrato, una. El cuadro se
   ensancha para la primera y deja a la segunda como estaba. */
/* Y EL CUADRO SE AJUSTA A LA HOJA. Un resumen de obra cabe entero en
   media pantalla: dejarle debajo doscientos píxeles de mesa vacía
   porque el cuadro mide siempre lo mismo es enseñar un documento dentro
   de una habitación. Crece con lo que lleva hasta donde da la pantalla,
   y no baja de un mínimo para que una hoja de tres filas no salga en un
   cuadro del tamaño de un sello. */
.visor:has(.visor-libro){
  width:min(max(560px,calc(var(--hoja-ancho,1100px) + 48px)),96vw);
  height:auto;max-height:min(92vh,960px);min-height:min(440px,70vh);
}
.visor-h{display:flex;align-items:center;gap:16px;padding:16px 56px 16px 22px;border-bottom:1px solid var(--line);flex:none}
.visor-t{flex:1;min-width:0}
.visor-t b{display:block;font-size:14.5px;font-weight:800;letter-spacing:-.01em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* La advertencia va arriba y siempre, no escondida al pie: quien mira un
   presupuesto tiene que saber ANTES de sacar conclusiones que esto es una
   aproximación del archivo, no el archivo. */
.visor-t span{display:block;font-size:11.5px;color:var(--muted);font-weight:600;margin-top:2px}
.visor-h .h-btn{flex:none}
.visor-cuerpo{flex:1;min-height:0;overflow:auto;background:var(--gray-soft)}
.visor-foto{min-height:100%;display:flex;align-items:center;justify-content:center;padding:24px}
.visor-foto img{max-width:100%;max-height:100%;border-radius:12px;box-shadow:var(--shadow-lift)}
.visor-cargando,.visor-error{
  height:100%;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:6px;
  font-size:13px;font-weight:600;color:var(--muted);text-align:center;padding:0 40px;
}
.visor-error span{font-size:12px;color:var(--faint);font-weight:600}
.visor-nota{font-size:11.5px;color:var(--faint);font-weight:600;padding:12px 24px 22px;margin:0}
/* ── una hoja de cálculo ──
   ES UNA REJILLA, NO UNA TABLA. Antes la primera fila hacía de
   encabezado y las demás se recortaban a su ancho; en una exportación de
   Google Sheets la primera fila es el membrete, y por ahí se perdían las
   columnas del dinero. Ahora se pinta la cuadrícula entera —sus letras,
   sus números de fila, sus celdas combinadas— y se puede decir «mira la
   C14» sabiendo que al otro lado hay una C14.

   UN SOLO HUECO QUE SE DESPLAZA. La rejilla ocupa el cuerpo del visor y
   se desplaza ella, en los dos ejes. Si el vertical viviera fuera y el
   horizontal dentro, `sticky` no tendría contra qué pegarse y el
   encabezado se iría hacia arriba con todo lo demás. */
.visor-cuerpo:has(>.visor-libro),
.cfg.hilo.con-visor .hilo-visor:has(>.visor-libro){display:flex;flex-direction:column;overflow:hidden}
.visor-libro{flex:1;min-height:0;display:flex;flex-direction:column}
.hoja-tabs{display:flex;flex:none;gap:4px;padding:14px 20px 12px;overflow-x:auto;scrollbar-width:none}
.hoja-tabs::-webkit-scrollbar{display:none}
.hoja-tab{
  flex:none;border:0;background:none;font:inherit;cursor:pointer;white-space:nowrap;
  padding:7px 13px;border-radius:9px;font-size:12px;font-weight:700;color:var(--muted);
  transition:background 140ms ease,color 140ms ease;
}
.hoja-tab:hover{background:var(--gray-soft);color:var(--ink-soft)}
.hoja-tab.puesta{background:var(--card-solid);color:var(--ink);box-shadow:0 0 0 1px var(--line)}
/* la hoja es papel y el hueco es la mesa: así se ve dónde termina la
   cuadrícula, en vez de parecer que los bordes se cortan solos */
.visor-hoja-host{flex:1;min-height:0;overflow:auto;background:var(--gray-soft)}
/* LA BARRA SE VE SIEMPRE. En un Mac las barras de desplazamiento están
   escondidas hasta que algo se mueve, y una hoja más ancha que la
   ventana no tiene entonces ninguna señal de que siga a la derecha:
   parece un archivo cortado. Se desplazaba —dos dedos sobre la rejilla—
   pero nadie tiene por qué adivinar eso.

   Pintar la barra la fija: deja de flotar y pasa a ocupar su sitio. Y
   NO se declara aquí `scrollbar-width`, aunque el resto de la hoja lo
   use: la propiedad estándar desactiva estos pseudoelementos y devuelve
   la barra flotante de siempre. */
.visor-hoja-host::-webkit-scrollbar{width:12px;height:12px}
.visor-hoja-host::-webkit-scrollbar-track,
.visor-hoja-host::-webkit-scrollbar-corner{background:var(--gray-soft)}
.visor-hoja-host::-webkit-scrollbar-thumb{
  background:var(--line-strong);border-radius:99px;
  border:3px solid transparent;background-clip:padding-box;
}
.visor-hoja-host::-webkit-scrollbar-thumb:hover{background:var(--muted);background-clip:padding-box}
/* `max-content` y no `auto`: una tabla de ancho automático encoge hasta
   el hueco que tiene y reparte el recorte entre las columnas, con lo que
   los anchos del archivo dejan de ser los anchos del archivo. Con
   `min-width` además rellena el hueco cuando la hoja es estrecha. */
/* NI SE ESTIRA NI SE ENCOGE: la hoja mide lo que mide y se pone en
   medio de la mesa. Con `min-width:100%` un documento de novecientos
   píxeles se repartía por los mil cuatrocientos del cuadro, y lo que
   estaba alineado en el archivo dejaba de estarlo — columnas separadas
   por huecos que nadie puso ahí. Una hoja centrada se lee como una
   página; una estirada, como una tabla mal hecha. */
.rejilla{border-collapse:separate;border-spacing:0;table-layout:fixed;width:max-content;margin-inline:auto;font-size:12.5px;background:var(--card-solid)}
/* un rótulo combinado a lo alto se centra: pegado arriba deja debajo un
   bloque de filas que parecen vacías por error */
.rejilla td[rowspan]{vertical-align:middle}
.rejilla th,.rejilla td{
  padding:6px 10px;text-align:left;vertical-align:top;overflow-wrap:break-word;
  border-right:1px solid var(--line);border-bottom:1px solid var(--line);
}
.rejilla td{color:var(--ink);font-weight:500}
/* el sitio que guarda un trozo sin pintar: mide y no se ve */
.rejilla tr.hueco td{padding:0;border:0}
/* ── el archivo, como lo hizo quien lo hizo ──
   En modo fiel manda el documento: los estilos en línea vienen del
   .xlsx y ganan a todo lo de aquí. Lo que queda por decir es la
   GEOMETRÍA. Una celda de hoja de cálculo no tiene el aire de una celda
   de tabla: su altura la fija la fila, su relleno son dos píxeles, y el
   texto que no cabe se derrama sobre la vecina en vez de partirse.
   Con nuestro relleno de 6px cada fila crecía un tercio y el documento
   se estiraba hasta no parecerse a sí mismo. */
/* EN MODO FIEL LA HOJA ES PAPEL, y el papel es blanco en los cuatro
   temas. El archivo eligió sus colores dando por hecho una hoja blanca
   —negro para el texto, #EFEFEF para las bandas— y sobre un tema oscuro
   eso se lee exactamente igual de bien que tinta negra sobre pizarra.
   Es lo mismo que hace el visor de PDF: la página es blanca aunque la
   mesa esté a oscuras. El marco —letras, números, pestañas— sí sigue al
   tema, porque el marco es nuestro. */
.rejilla.fiel{background:#fff;color:#000;font-family:Calibri,Carlito,"Segoe UI",system-ui,sans-serif}
.rejilla.fiel td{padding:0 3px;line-height:1.15;white-space:nowrap;overflow:visible;font-weight:400;color:inherit}
/* EL MARCO NO MANDA SOBRE LA ALTURA DE LA FILA. La columna de números
   se quedaba con el relleno de 6px de la rejilla normal y ponía a cada
   fila un suelo de 28 píxeles: en una hoja de filas de 15 eso es el
   documento un 87% más alto de lo que es, y además rompe el sitio que
   se reserva para lo que todavía no se ha pintado. */
.rejilla.fiel tbody th.num{padding:0 5px;line-height:1;font-size:9px}
.rejilla.fiel td.corta{overflow:hidden;text-overflow:clip}
/* el membrete cuelga de su celda y se sale de ella a propósito: la
   columna A mide veintiocho píxeles y el logo ciento treinta y dos */
.rejilla.fiel td:has(.hoja-img),.rejilla.fiel td.nota{position:relative}
/* alguien le dejó un recado a quien abriera el archivo; hasta ahora se
   tiraba sin avisar. La esquina roja es la de toda la vida, y el texto
   está en el `title` porque es donde lo busca quien ya la ha visto */
.rejilla.fiel td.nota::after{
  content:"";position:absolute;top:0;right:0;width:0;height:0;
  border-top:5px solid #C0392B;border-left:5px solid transparent;
}
.hoja-img{position:absolute;max-width:none;pointer-events:none;user-select:none}
/* la cuadrícula la pone el archivo o no la pone nadie */
.rejilla.sin-rejilla td{border-right:0;border-bottom:0}
.rejilla td.n{text-align:right;font-variant-numeric:tabular-nums}
/* una fórmula sin datos no es un dato: se ve, pero no compite */
.rejilla td.err{color:var(--faint)}
/* los encabezados van en color sólido a propósito: `sticky` sobre un
   fondo translúcido deja pasar por debajo lo que se desplaza */
.rejilla thead th,.rejilla tbody th.num{
  background:var(--card-solid);color:var(--faint);
  font-size:10px;font-weight:700;letter-spacing:.04em;font-variant-numeric:tabular-nums;
}
.rejilla thead th{position:sticky;top:0;z-index:2;text-align:center;border-bottom:1px solid var(--line-strong)}
.rejilla tbody th.num{position:sticky;left:0;z-index:1;text-align:right;border-right:1px solid var(--line-strong)}
.rejilla thead th.esq{position:sticky;left:0;z-index:3;border-right:1px solid var(--line-strong)}
.rejilla col.c-num{width:46px}
/* ── un documento de texto ── */
.visor-doc{
  max-width:760px;margin:24px auto;padding:44px 52px;background:var(--card-solid);
  border-radius:12px;box-shadow:var(--shadow);font-size:14px;line-height:1.7;color:var(--ink);
}
.visor-doc h1{font-size:22px;font-weight:800;letter-spacing:-.02em;margin:0 0 14px}
.visor-doc h2{font-size:17px;font-weight:800;margin:24px 0 10px}
.visor-doc h3{font-size:15px;font-weight:800;margin:20px 0 8px}
.visor-doc p{margin:0 0 12px}
.visor-doc ul,.visor-doc ol{margin:0 0 12px;padding-left:22px}
.visor-doc li{margin-bottom:5px}
.visor-doc table{border-collapse:collapse;width:100%;margin:0 0 14px;font-size:13px}
.visor-doc th,.visor-doc td{border:1px solid var(--line);padding:7px 10px;text-align:left}
.visor-doc img{max-width:100%;height:auto;border-radius:8px}
@media (max-width:760px){
  .visor{width:100vw;height:100vh;border-radius:0;border:0}
  .visor-doc{margin:0;padding:24px 20px;border-radius:0;box-shadow:none}
}

/* ═══════════════════════════════════════════════════════════════
   APROBACIONES · la bandeja y el hilo (ui/approvals.js)
   ═══════════════════════════════════════════════════════════════ */
.nav-pill{position:relative}
/* el punto de la píldora: cuántas esperan a quien mira */
.nav-punto{
  position:absolute;top:6px;right:6px;min-width:15px;height:15px;padding:0 4px;
  display:flex;align-items:center;justify-content:center;
  border-radius:99px;background:var(--red);color:#fff;
  font-size:9.5px;font-weight:800;line-height:1;font-variant-numeric:tabular-nums;
}
.ap-filtro{flex:none}
.ap-lista{display:flex;flex-direction:column;gap:10px;margin-top:22px}
.ap-vacio{padding:44px 20px;text-align:center;font-size:12.5px;color:var(--faint);font-weight:600}
.ap-fila{
  display:grid;grid-template-columns:minmax(0,1fr) 210px;gap:18px;align-items:center;
  padding:16px 18px;border:1px solid var(--line);border-radius:16px;background:var(--card);
  text-align:left;cursor:pointer;
  transition:border-color 140ms ease,box-shadow 140ms ease,transform 140ms var(--eo);
}
/* La fila entera es el botón, así que se comporta como uno: se levanta al
   pasar, se hunde al pulsar y tiene su anillo al llegar con el teclado. */
.ap-fila:hover{border-color:var(--edge);box-shadow:var(--shadow)}
.ap-fila:active{transform:scale(.995)}
.ap-fila:focus-visible{outline:none;border-color:var(--edge);box-shadow:var(--shadow-lift)}
.ap-col{min-width:0}
.ap-n{display:flex;align-items:baseline;gap:8px;min-width:0}
.ap-n b{font-size:14px;font-weight:800;letter-spacing:-.01em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ap-ronda{font-size:10px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;color:var(--faint);flex:none}
.ap-m{font-size:11.5px;color:var(--muted);font-weight:600;margin-top:3px}
.ap-nota{font-size:12px;color:var(--ink);font-weight:500;margin-top:7px;opacity:.85;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.ap-estado{display:flex;flex-direction:column;gap:4px;align-items:flex-start}
.ap-toca{font-size:11px;color:var(--faint);font-weight:700}
/* La pastilla de estado: un punto de color y la palabra. Nunca una caja
   de color entera — el expediente se imprime. */
.ap-chip{
  display:inline-flex;align-items:center;gap:7px;padding:5px 11px 5px 9px;border-radius:99px;
  border:1px solid var(--line);background:var(--card-solid);
  font-size:11px;font-weight:700;color:var(--muted);white-space:nowrap;
}
.ap-chip i{width:7px;height:7px;border-radius:50%;background:var(--faint);flex:none}
.ap-chip.espera i{background:var(--amber)}
.ap-chip.cambios i{background:var(--red)}
.ap-chip.listo i{background:var(--green)}
.ap-chip.cambios{color:var(--red-ink)}
.ap-chip.listo{color:var(--green-ink)}
/* Sin filete de color a la izquierda. La pastilla de estado ya lo dice
   con su punto y su palabra, y una barra de color en el borde repite esa
   información gritándola — la misma nota que se quitó de la bitácora. */

/* el sello en la fila del expediente */
.doc-sello{
  flex:none;margin-left:10px;padding:3px 9px;border-radius:99px;
  border:1px solid var(--line);background:var(--card-solid);
  font-size:10px;font-weight:800;letter-spacing:.02em;color:var(--muted);white-space:nowrap;
}
/* solid, so the state reads from across the room: the text takes the
   card's colour, which is light on light themes and dark on dark ones,
   and stays legible on each state's full colour */
.doc-sello.listo,.doc-sello.cambios,.doc-sello.espera{border-color:transparent;color:var(--card-solid)}
.doc-sello.listo{background:var(--green)}
.doc-sello.cambios{background:var(--red)}
.doc-sello.espera{background:var(--amber)}
/* as a button it opens the thread (rounds, comments, signature) */
button.doc-sello{font:inherit;font-size:10px;font-weight:800;letter-spacing:.02em;cursor:pointer;transition:filter 120ms ease}
button.doc-sello:hover{filter:brightness(1.08)}

/* ── el hilo ── */
.cfg.hilo{width:min(680px,95vw);height:min(740px,calc(100vh - 40px));padding:0;overflow:hidden;display:flex;flex-direction:column}
/* CON EL DOCUMENTO AL LADO. Se ensancha sólo cuando hay algo que
   enseñar: a quien le piden una firma, el papel a la izquierda y la
   conversación a la derecha, sin salir ni bajar nada. */
.cfg.hilo.con-visor{width:min(1240px,96vw);height:min(860px,calc(100vh - 40px));display:grid;grid-template-columns:minmax(0,1fr) minmax(380px,440px)}
/* Sin filete entre las dos columnas: el documento ya es blanco y la
   conversación gris, y el cambio de tono separa mejor que una línea. */
.hilo-visor{display:none;min-width:0;overflow:auto;background:var(--gray-soft)}
.cfg.hilo.con-visor .hilo-visor{display:block}
/* `flex:1` para el cuadro estrecho (sin documento al lado): sin él la
   columna medía sólo lo que ocupaba, y el pie quedaba flotando a media
   altura con el cuadro vacío por debajo */
.hilo-lado{display:flex;flex-direction:column;flex:1;min-height:0;min-width:0}
/* ── el PDF, dibujado por nosotros ──
   Cada página es un lienzo sobre el fondo de la columna, con su sombra y
   su canto redondeado: papel sobre la mesa. Ya no hay marco del
   navegador, ni su barra, ni su fondo asomando por los lados — que fue
   lo que costó tres intentos desde fuera antes de traer PDF.js. */
.visor-pdf{display:flex;flex-direction:column;align-items:center;gap:14px;padding:18px 24px 24px}
.visor-pag{
  width:100%;max-width:980px;min-height:180px;border-radius:8px;overflow:hidden;
  background:var(--card-solid);box-shadow:var(--shadow);
}
.visor-pag canvas{display:block;width:100%;height:auto}
.hilo-visor .visor-pdf{padding:14px 16px 18px;gap:12px}
.hilo-visor .visor-doc{margin:18px;padding:30px 32px}
.hilo-visor .hoja-tabs{padding:12px 14px 10px}
.hilo-visor .rejilla{font-size:12px}
@media (max-width:1000px){
  /* una sola columna: la conversación manda, y el documento se abre con
     Descargar como antes */
  .cfg.hilo.con-visor{width:min(680px,95vw);display:flex;flex-direction:column}
  /* la hoja de cálculo sube la especificidad allá arriba, así que aquí
     hay que nombrarla igual o el visor no se esconde en el teléfono */
  .cfg.hilo.con-visor .hilo-visor,
  .cfg.hilo.con-visor .hilo-visor:has(>.visor-libro){display:none}
}
/* ONE SURFACE. The header was a white band, the thread a grey one and
   the footer white again, each divided by a hairline: the panel read as
   three slabs stacked rather than one column. The whole side is the same
   surface now, and only what is genuinely raised — a message, the
   composer — sits on top of it.

   The header itself: the name rules, and under it, in one line, what
   used to be a separate pill (state and round). Download and close are
   two quiet tools, not two decisions. */
.cfg.hilo .hilo-lado{background:var(--gray-soft)}
.hilo-h{display:flex;align-items:center;gap:10px;padding:14px 12px 10px 16px}
.hilo-doc{min-width:0;flex:1}
.hilo-doc b{display:block;font-size:14.5px;font-weight:800;letter-spacing:-.01em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* el estado ya no es una pastilla: es este renglón, con su punto */
.hilo-meta{display:flex;align-items:center;gap:6px;margin-top:3px;font-size:11.5px;font-weight:600;color:var(--muted)}
.hilo-meta .pt{width:6px;height:6px;border-radius:50%;background:var(--faint);flex:none}
.hilo-meta .pt.espera{background:var(--amber)}
.hilo-meta .pt.cambios{background:var(--red)}
.hilo-meta .pt.listo{background:var(--green)}
.hilo-tools{display:flex;align-items:center;gap:2px;flex:none}
.hilo-ic{width:30px;height:30px;border-radius:9px;display:flex;align-items:center;justify-content:center;color:var(--muted)}
.hilo-ic:hover{background:var(--card-solid);color:var(--ink)}
.hilo-ic svg{width:16px;height:16px}
/* MÁS AIRE. La conversación iba a 8px del borde y las burbujas se
   apretaban contra la cabecera en una columna que sobra de alta: el
   contenido parecía amontonado arriba de un hueco. */
.hilo-cuerpo{flex:1;min-height:0;overflow:auto;padding:16px 18px 10px;display:flex;flex-direction:column;gap:18px}
/* EL CORTE DE RONDA: un filete con la frase encima, no una caja. Y con
   aire propio: es un rótulo de sección, no otro renglón de la
   conversación, así que respira más que el hueco de 18px que separa dos
   mensajes — y más por debajo que por arriba, porque pertenece a lo que
   viene después. El primero del hilo no empuja: ya está la cabecera. */
.hilo-corte{display:flex;align-items:center;gap:10px;font-size:10.5px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;color:var(--faint);
  margin:10px 0 14px}
.hilo-hilo > .hilo-corte:first-child{margin-top:0}
/* LA LISTA DE VERDAD ES ESTA. El hueco entre mensajes estaba puesto en
   `.hilo-cuerpo`, que sólo tiene un hijo —esta caja—, así que nunca
   llegó a las burbujas: estaban pegadas una a otra y lo único que las
   separaba era el pie de cada una. Con la columna aquí, el hueco separa
   lo que tiene que separar y el corte de ronda suma su margen encima. */
.hilo-hilo{display:flex;flex-direction:column;gap:14px}
.hilo-corte::before,.hilo-corte::after{content:"";flex:1;height:1px;background:var(--line)}
.hilo-corte.listo{color:var(--green-ink)}
.hilo-corte.cambios{color:var(--red-ink)}
.hilo-msg{max-width:88%;padding:12px 15px;border-radius:17px;background:var(--card-solid);border:1px solid var(--line);align-self:flex-start}
.hilo-msg.mio{align-self:flex-end;background:var(--black);border-color:var(--black);color:var(--on-black)}
.hilo-quien{display:flex;align-items:baseline;gap:8px;font-size:11px;font-weight:800;margin-bottom:3px}
.hilo-quien span{font-weight:600;opacity:.6;font-size:10.5px}
.hilo-txt{font-size:13px;line-height:1.5;font-weight:500;white-space:pre-wrap;word-break:break-word}
/* THE FOOT, ONE ROW. The column is 392px wide and every row of chrome
   costs conversation: the field, the verdict beside it, nothing else.

   ONE FILLED BUTTON in the whole panel. There used to be two blacks —
   the send button and Aprobar — in a narrow column, and the eye could
   not tell which was the real action. Sending is now a quiet button that
   only exists once something has been typed; the rest of the time the
   only weighted thing on screen is the decision.

   When the actions do not fit — whoever sent it can also withdraw it —
   they wrap onto their own line instead of squeezing the field. */
/* EL PIE DE UN MENSAJE: si lo leyeron, si se corrigió, y el lápiz
   mientras siga a tiempo. Debajo del texto y en pequeño — es el dato que
   se busca cuando se busca, no algo que competir con lo dicho. */
.hilo-pie-msg{display:flex;align-items:center;justify-content:flex-end;gap:8px;margin-top:6px;font-size:10.5px;font-weight:700}
.hilo-pie-msg .apill,.hilo-pie-msg .h-btn{flex:none}
.hilo-msg:not(.mio) .hilo-pie-msg:empty{display:none}
.hilo-editado{color:var(--faint);font-weight:600}
.hilo-msg.mio .hilo-editado{color:color-mix(in srgb,var(--on-black) 55%,transparent)}
.hilo-visto{color:color-mix(in srgb,var(--on-black) 55%,transparent);font-weight:600}
.hilo-visto.si{color:color-mix(in srgb,var(--on-black) 80%,transparent)}
.hilo-lapiz{width:22px;height:22px;border-radius:7px;display:flex;align-items:center;justify-content:center;
  color:color-mix(in srgb,var(--on-black) 60%,transparent)}
.hilo-lapiz:hover{background:color-mix(in srgb,var(--on-black) 14%,transparent);color:var(--on-black)}
.hilo-lapiz svg{width:13px;height:13px}

/* EL BORRADOR. Discontinuo y sobre el papel, no relleno: todavía no es
   un mensaje, y no se parece a uno. */
.hilo-msg.borrador{
  background:none;border:1px dashed var(--line-strong);color:var(--ink-soft);
  align-self:flex-end;max-width:92%;
}
.hilo-msg.borrador .hilo-txt{color:var(--ink-soft)}
.hilo-msg.borrador .hilo-pie-msg{gap:6px;margin-top:9px}
.hilo-solo-tu{margin-right:auto;color:var(--muted);font-weight:600;font-size:10.5px}
.hilo-msg.borrador .apill{flex:none;height:30px;padding:0 11px;border-radius:15px;font-size:11.5px;
  background:var(--card-solid);border:1px solid var(--edge);box-shadow:none;color:var(--ink-soft)}
.hilo-msg.borrador .h-btn{flex:none;height:30px;padding:0 13px;border-radius:15px;font-size:11.5px}

/* corregirse dentro de la propia burbuja.

   LA BURBUJA SE ESTIRA MIENTRAS SE EDITA. Una burbuja mide lo que mide
   su texto, y un <textarea> no tiene texto que medir: su ancho
   intrínseco son sus `cols` —veinte caracteres— así que al cambiar el
   párrafo por el campo, el mensaje se encogía a una columna estrecha y
   las palabras se partían de tres en tres. Editando ocupa el ancho
   entero que se le permite, que es donde el texto se lee como se va a
   leer después. */
.hilo-msg:has(.hilo-edita){width:88%}
.hilo-edita{
  width:100%;min-height:54px;resize:none;border:0;border-radius:10px;padding:8px 10px;
  background:color-mix(in srgb,var(--on-black) 12%,transparent);color:inherit;
  font:inherit;font-size:13px;line-height:1.5;
}
.hilo-edita:focus{outline:none;background:color-mix(in srgb,var(--on-black) 18%,transparent)}
/* Dentro de una burbuja PROPIA el fondo es tinta, así que los botones de
   la corrección se pintan al revés. El borrador no: es papel con
   trazo discontinuo, y ahí los botones son los de siempre. */
.hilo-msg.mio:not(.borrador) .hilo-pie-msg .apill{background:none;border-color:color-mix(in srgb,var(--on-black) 30%,transparent);color:var(--on-black)}
.hilo-msg.mio:not(.borrador) .hilo-pie-msg .h-btn{background:var(--on-black);color:var(--black);border-color:transparent}

.hilo-pie{padding:10px 14px 14px;display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:8px}
.hilo-escribe{
  flex:1 1 170px;display:flex;align-items:flex-end;gap:6px;padding:4px 5px 4px 14px;min-width:0;
  border:1px solid var(--line);border-radius:20px;background:var(--card-solid);
  transition:border-color .16s,box-shadow .16s;
}
.hilo-escribe:focus-within{border-color:var(--edge);box-shadow:var(--shadow)}
/* WHILE SOMEBODY IS WRITING, the field owns the row and the decisions
   drop below it. Sharing the row with two buttons leaves 170px, and a
   sentence of any length turns into a tall narrow column of three
   words. At rest it goes back to one row, which is the state the panel
   spends its life in. */
.hilo-pie:has(.hilo-escribe.con-texto) .hilo-escribe{flex:1 1 100%}
.hilo-pie textarea{
  flex:1;min-width:0;height:30px;max-height:132px;resize:none;border:0;background:none;padding:6px 0;
  color:var(--ink);font:inherit;font-size:13px;line-height:1.45;overflow-y:hidden;
}
.hilo-pie textarea:focus{outline:none}
/* aparece cuando hay algo que mandar, y no antes */
.hilo-send{
  display:none;flex:none;width:30px;height:30px;border-radius:50%;align-items:center;justify-content:center;
  background:var(--gray-soft);color:var(--ink);
}
.hilo-escribe.con-texto .hilo-send{display:flex}
.hilo-send:hover{background:var(--line)}
.hilo-send svg{width:15px;height:15px}
/* sin decisiones que tomar no hay nada que enseñar */
.hilo-acts{display:flex;align-items:center;gap:4px;flex:0 1 auto}
.hilo-acts:empty{display:none}
/* Las secundarias son BOTONES, con su caja: sin ella parecían enlaces
   sueltos entre el campo y Aprobar, y «Cancelar el envío» —que retira un
   documento de la bandeja del cliente— no es una nota al pie. Lo que
   sigue distinguiendo a la decisión es el relleno: una sola sólida, las
   demás sobre el papel. */
.hilo-acts .apill{
  flex:none;height:38px;padding:0 14px;border-radius:19px;font-size:12.5px;
  background:var(--card-solid);border:1px solid var(--edge);box-shadow:var(--shadow);color:var(--ink-soft);
}
.hilo-acts .apill:hover{color:var(--ink)}
.hilo-acts .apill.danger{color:var(--red-ink);border-color:color-mix(in srgb,var(--red) 26%,var(--edge))}
.hilo-acts .h-btn{flex:none;height:38px;padding:0 16px;border-radius:19px;font-size:12.5px}
.hilo-acts svg{width:14px;height:14px}

@media (max-width:760px){
  .ap-fila{grid-template-columns:minmax(0,1fr);gap:10px}
  .cfg.hilo{width:min(440px,94vw);height:calc(100vh - 40px)}
  /* on a phone the field takes its own line and the decisions sit under
     it, wide enough to hit with a thumb */
  .hilo-escribe{flex:1 1 100%}
  .hilo-acts{flex:1 1 100%;justify-content:flex-end}
}

/* ═══════════════════════════════════════════════════════════════
   THE CONFIRMATION WINDOW (ui/confirm.js)
   ═══════════════════════════════════════════════════════════════ */
.cf-wrap{z-index:70}
.cfg.cf{width:min(380px,92vw);text-align:center;padding-top:28px}
.cf-ico{width:48px;height:48px;border-radius:16px;margin:0 auto 14px;display:grid;place-items:center;background:color-mix(in srgb,var(--red) 10%,transparent);color:var(--red)}
.cf-ico svg{width:22px;height:22px}
/* not destructive: the icon in ink on the soft grey, the button in ink */
.cfg.cf.suave .cf-ico{background:var(--gray-soft);color:var(--ink)}
.cfg.cf h2{font-size:17px;font-weight:800;letter-spacing:-.02em}
.cf-texto{font-size:12.5px;color:var(--muted);line-height:1.55;margin:8px auto 0;max-width:300px}
.cf-acts{display:flex;justify-content:center;gap:8px;margin-top:20px}
.cf-acts .apill{flex:none;padding:9px 16px}
.cf-acts .h-btn.danger{background:var(--red);color:#fff;border-color:transparent}
.cf-acts .h-btn.danger:hover{filter:brightness(.94)}

/* ── asistencia sin una sola llegada: se explica en vez de dibujar una
   rejilla vacía (ui/checkins.js) ── */
.ck-blank{padding:38px 24px 32px;display:flex;flex-direction:column;align-items:center;gap:13px;text-align:center}
.ck-blank-ico{width:52px;height:52px;border-radius:17px;background:var(--gray-soft);color:var(--muted);display:grid;place-items:center}
.ck-blank-ico svg{width:24px;height:24px}
.ck-blank h3{font-size:15px;font-weight:800;letter-spacing:-.01em}
.ck-blank p{font-size:12.5px;color:var(--muted);line-height:1.6;max-width:440px}
.ck-steps{display:flex;gap:10px;flex-wrap:wrap;justify-content:center;margin-top:2px}
.ck-step{display:flex;align-items:center;gap:8px;padding:8px 12px;border-radius:12px;background:var(--gray-soft);font-size:11.5px;font-weight:600;color:var(--ink-soft)}
.ck-step i{width:18px;height:18px;border-radius:50%;background:var(--black);color:var(--on-black);display:grid;place-items:center;font-size:9px;font-weight:800;font-style:normal;flex:none}
.ck-roster{display:flex;gap:8px;flex-wrap:wrap;justify-content:center;margin-top:2px}
.ck-chip-p{display:flex;align-items:center;gap:7px;padding:4px 11px 4px 4px;border-radius:99px;background:var(--gray-soft);font-size:11.5px;font-weight:700}
.ck-chip-p .ck-av{width:22px;height:22px;font-size:8px}
.ck-blank .h-btn.cta{margin-top:6px}
.ck-blank .h-btn.cta svg{width:15px;height:15px}
@media (max-width:760px){.ck-steps{flex-direction:column;width:100%}.ck-step{justify-content:flex-start}}

/* The Word preview has its own opaque origin and scroll container. */
.visor-doc-host{max-width:760px;margin:24px auto;width:100%;}
.visor-doc-frame{display:block;width:100%;height:70vh;min-height:320px;border:0;border-radius:12px;background:white;box-shadow:var(--shadow);}
.hilo-visor .visor-doc-host{margin:18px;width:calc(100% - 36px);}

/* ───────── the tile that glides (ui/menu.js desliza) ─────────
   One tile per menu carries the active item's background and slides to
   the item that becomes active. While it is there (`con-glide`) the
   active item paints only its colour, above the tile. The tile wears
   what the active item used to wear, per menu: a lifted card on the
   rail, the soft wash the phone dock uses. */
/* the rail becomes the tile's frame; the dock already is one (it is
   fixed), and giving it `relative` would drop it into the page */
.nav-pills.con-glide{position:relative}
.con-glide > .nav-pill,.con-glide > .mdock-btn{position:relative;z-index:1}
.con-glide > .nav-pill.active,.con-glide > .mdock-btn.active{background:transparent;border-color:transparent;box-shadow:none}
.glide{
  position:absolute;left:0;top:0;z-index:0;pointer-events:none;border-radius:13px;
  background:var(--card-solid);border:1px solid var(--edge);box-shadow:var(--shadow-lift);
  opacity:0;transition:transform 420ms cubic-bezier(.32,.72,0,1),opacity 180ms ease;
}
.glide.on{opacity:1}
.mobiledock > .glide{border-radius:15px;background:var(--gray-soft);border-color:transparent;box-shadow:none}
@media (prefers-reduced-motion:reduce){ .glide{transition:opacity 120ms ease} }

/* ───────── CONCRETO · the fade ─────────
   The page is not one flat colour: it fades from the brand's sage
   (#6b7a6f) at the top, through its light grey (#e5e5e5), to its sand
   (#e3ded1) at the bottom, both ends softened toward the grey. It lives on the fixed layer behind the page
   (body::before), so it stays put while the content scrolls, and the
   cards are frosted white over it — translucent, blurred, with a white
   edge — so the colour shows through them softly.

   The subtitle under each page title sits on the sage end, where the
   usual muted grey falls to about 2.9:1; it takes a darker grey there
   (#4A4A4A, over 5:1). */
:root[data-theme="concreto"] body::before{
  /* the top is the brand's sage (#6b7a6f) 78% of the way toward the
     middle grey, the bottom its sand 60% of the way: the brand's
     colours as a tint, not a field */
  background:linear-gradient(180deg,#CACDCB 0%,#E5E5E5 55%,#E4E2DD 100%);
}
:root[data-theme="concreto"] .card,
:root[data-theme="concreto"] .panel{
  border-color:rgba(255,255,255,.72);
  -webkit-backdrop-filter:saturate(1.2) blur(14px);backdrop-filter:saturate(1.2) blur(14px);
}
:root[data-theme="concreto"] .hero .sub{color:#4A4A4A}

/* ───────── CONCRETO · colour where it means something ─────────
   Over the fade: the chart and the progress bars are sage (tokens in
   the Concreto block), each area's state is a soft tinted chip — grey
   before it starts, sand while it is worked, sage once complete — the
   selected option of every segmented control and filter is sage, the
   logo tile is sage, and the big figures are light, in deep sage. */
:root[data-theme="concreto"] .ap-st{justify-self:start;width:max-content;padding:2px 9px 2px 7px;border-radius:99px;background:rgba(49,49,49,.07);color:#595959}
:root[data-theme="concreto"] .ap-st.idle i{background:#929292}
:root[data-theme="concreto"] .ap-st.obra,
:root[data-theme="concreto"] .ap-st.warn{background:#E3DED1;color:#595959}
:root[data-theme="concreto"] .ap-st.obra i,
:root[data-theme="concreto"] .ap-st.warn i{background:#595959}
:root[data-theme="concreto"] .ap-st.ok{background:#DCE6E2;color:#4E5C52}
:root[data-theme="concreto"] .ap-st.ok i{background:#6B7A6F}
:root[data-theme="concreto"] .ap-st-pct{color:inherit}

:root[data-theme="concreto"] .seg button.active,
:root[data-theme="concreto"] .views button.active,
:root[data-theme="concreto"] .fpill.active,
:root[data-theme="concreto"] .bt-bar .chip.on,
:root[data-theme="concreto"] .chip-opt.sel,
:root[data-theme="concreto"] .tl-chip.on{background:#6B7A6F;color:#FFFFFF;border-color:transparent}
:root[data-theme="concreto"] .ap-tab.on{color:#4E5C52;border-bottom-color:#6B7A6F}

/* the menu's active tile is glass, not a white card: a thin translucent
   pane with a white edge, and the icon in deep sage says which it is */
:root[data-theme="concreto"] .nav-pills > .glide{background:rgba(255,255,255,.28);border-color:rgba(255,255,255,.6);box-shadow:none}
:root[data-theme="concreto"] .nav-pill.active{color:#4E5C52}

:root[data-theme="concreto"] .pcard .num,
:root[data-theme="concreto"] .ap-pct,
:root[data-theme="concreto"] .tl-prog-h b{font-weight:300;color:#4E5C52;letter-spacing:-.01em}
:root[data-theme="concreto"] .pcard .num{font-size:24px}

/* ───────── PP (concreto) · frosted buttons ─────────
   The white buttons — Exportar, Ver asistencia, Cambiar, the icon
   buttons, the Cronograma's phone buttons — are frosted glass over the
   fade instead of solid white: a thin white pane, a white edge, a blur
   of what is behind. The primary, the danger and the selected ones
   keep their fills. */
:root[data-theme="concreto"] .icon-btn:not(.active),
:root[data-theme="concreto"] .h-btn:not(.cta):not(.danger),
:root[data-theme="concreto"] .apill:not(.fantasma),
:root[data-theme="concreto"] .tl-am:not(.cta),
:root[data-theme="concreto"] .tl-filtros{
  background:rgba(255,255,255,.34);border-color:rgba(255,255,255,.66);
  box-shadow:0 1px 2px rgba(49,49,49,.04);
  -webkit-backdrop-filter:saturate(1.2) blur(12px);backdrop-filter:saturate(1.2) blur(12px);
}
:root[data-theme="concreto"] .icon-btn:not(.active):hover,
:root[data-theme="concreto"] .h-btn:not(.cta):not(.danger):hover,
:root[data-theme="concreto"] .apill:not(.fantasma):hover,
:root[data-theme="concreto"] .tl-am:not(.cta):hover,
:root[data-theme="concreto"] .tl-filtros:hover{background:rgba(255,255,255,.55)}
:root[data-theme="concreto"] .sidenav .icon-btn:not(.active){background:none;border-color:transparent;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none}

/* ───────── the sign-in · form panel and full-bleed photograph ─────────
   Two halves with no frame between them: a quiet panel on the left with
   the mark, the form and a one-line signature pinned to its foot; the
   photograph fills the right half edge to edge, top to bottom, with the
   line and its tags over the bottom of it and the studio's motto in the
   corner. Under 760px the photograph goes and the form has the page. */
/* The photograph runs under the whole screen; the form's panel is
   frosted white glass over its left part, so the room still shows
   through it, softly. */
.login-editorial{background:var(--bg);--lg-panel:clamp(380px,41vw,620px)}
.login-editorial .login-inner{position:relative;min-height:100svh;padding:0;display:grid;grid-template-columns:var(--lg-panel) minmax(0,1fr);gap:0;align-items:stretch;max-width:none;margin:0}
.login-editorial .login-card{
  position:relative;z-index:2;grid-column:1;grid-row:1;
  width:100%;max-width:none;align-self:stretch;justify-self:stretch;display:flex;flex-direction:column;justify-content:center;
  padding:56px clamp(40px,5.4vw,80px) 40px;border:0;
  /* a sheet laid over the photograph: full height, its right edge
     rounded like the platform's panels */
  border-radius:0 28px 28px 0;
  background:color-mix(in srgb,var(--card-solid) 80%,transparent);border-right:1px solid color-mix(in srgb,var(--card-solid) 60%,transparent);
  box-shadow:12px 0 40px rgba(20,22,20,.10);
  -webkit-backdrop-filter:saturate(1.3) blur(26px);backdrop-filter:saturate(1.3) blur(26px);
}
.login-editorial .login-card > *{max-width:360px}
.login-editorial .login-brand{flex-direction:column;align-items:flex-start;gap:10px;margin-bottom:56px}
/* the door and the platform are one product: the sizes, weights,
   radii and colours below follow the platform's own (.hero h1, .fld,
   .btn.primary) */
/* at the door the same tile as the menu, larger */
.login-editorial .login-brand .logo{width:60px;height:60px;border-radius:17px}
.login-editorial .login-brand .bn{font-size:20px;font-weight:800;letter-spacing:-.03em}
.login-editorial .login-brand .by{font-size:11.5px;font-weight:600;color:var(--muted);margin-top:2px}
.login-kicker{display:block;font-size:10px;font-weight:600;letter-spacing:.17em;color:var(--muted);margin-bottom:16px}
.login-editorial .login-card h1{font-size:clamp(28px,2.4vw,34px);font-weight:800;line-height:1.1;letter-spacing:-.03em}
.login-editorial .login-card .lsub{font-size:13px;line-height:1.6;color:var(--muted);margin:8px 0 34px}
.login-editorial .fld{margin-bottom:18px}
.login-editorial .fld label{font-weight:700;font-size:12px;margin-bottom:7px}
/* the fields are white, lifted off the frosted panel by a very soft
   shadow and no line; the one in use takes a soft border and a faint
   halo, only while it is clicked into */
.login-editorial .fld input{min-height:48px;border-radius:14px;font-size:16px;padding:12px 14px;background:var(--card-solid);border:1px solid transparent;box-shadow:0 1px 2px rgba(20,22,20,.04),0 4px 14px rgba(20,22,20,.05)}
.login-editorial #lg-pass{padding-right:56px}
/* FLOATING LABELS. The label lies inside the field like a placeholder
   and, when the field is focused or has a value, glides up to its top
   edge and shrinks; the field takes a sage ring while focused. The
   input carries placeholder=" " so :placeholder-shown tells empty
   from filled, which also catches the browser's autofill. */
.login-editorial .fld.flt .fwrap{position:relative}
.login-editorial .fld.flt input{min-height:56px;padding:22px 14px 8px;transition:box-shadow .2s ease,border-color .2s ease}
.login-editorial .fld.flt label{
  position:absolute;left:15px;top:18px;margin:0;pointer-events:none;
  font-size:14px;font-weight:500;color:var(--muted);transform-origin:left top;
  transition:transform .22s cubic-bezier(.32,.72,0,1),color .2s ease;
}
.login-editorial .fld.flt input:focus + label,
.login-editorial .fld.flt input:not(:placeholder-shown) + label,
.login-editorial .fld.flt input:-webkit-autofill + label{transform:translateY(-10px) scale(.76);font-weight:700}
.login-editorial .fld.flt input:focus + label{color:var(--cta)}
.login-editorial .fld.flt input:focus{border-color:color-mix(in srgb,var(--cta) 30%,transparent);box-shadow:0 0 0 4px color-mix(in srgb,var(--cta) 7%,transparent),0 6px 18px rgba(20,22,20,.07)}
.login-editorial .fld.flt .eye{top:50%}
/* a field left empty only shakes; what is missing is said, calmly,
   in the notice under the fields */
.login-editorial .fld.falta .fwrap{animation:falta-shake .36s cubic-bezier(.36,.07,.19,.97) both}
@keyframes falta-shake{20%,60%{transform:translateX(-4px)}40%,80%{transform:translateX(4px)}}
@media(prefers-reduced-motion:reduce){.login-editorial .fld.flt label{transition:none}.login-editorial .fld.falta .fwrap{animation:none}}
/* DARK. The panel is frosted from the theme's own card colour, so in
   dark it is dark glass and its light text reads; the fields sit a step
   lighter than the panel so they still show where to type. */
:root[data-theme="dark"] .login-editorial .fld input{background:rgba(255,255,255,.06);box-shadow:0 1px 2px rgba(0,0,0,.2)}
/* the door in the Punto Paralelo theme: the brand stone, #E3DED1, very
   light through the frosted sheet; the fields stay white on it */
:root[data-theme="concreto"] .login-editorial .login-card{
  background:color-mix(in srgb,color-mix(in srgb,#E3DED1 38%,var(--card-solid)) 82%,transparent);
  border-right-color:color-mix(in srgb,#E3DED1 55%,transparent);
}
:root[data-theme="dark"] .login-editorial .login-card{box-shadow:12px 0 40px rgba(0,0,0,.35)}
@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]):not([data-theme="concreto"]) .login-editorial .fld input{background:rgba(255,255,255,.06);box-shadow:0 1px 2px rgba(0,0,0,.2)}
  :root:not([data-theme="light"]):not([data-theme="concreto"]) .login-editorial .login-card{box-shadow:12px 0 40px rgba(0,0,0,.35)}
}
.login-editorial .eye{width:40px;height:40px;right:4px;border-radius:10px}
/* the space «¿Olvidaste tu contraseña?» used to hold above the button */
.login-editorial .login-btn{margin-top:10px;min-height:50px;border-radius:14px;font-size:13.5px;font-weight:700;justify-content:center;gap:10px;background:var(--cta);color:var(--on-cta)}
.login-editorial .login-btn:disabled{opacity:.55;cursor:wait}
.login-editorial .login-btn svg{position:static;margin:0;transform:none}
.login-editorial button:focus-visible{outline:2px solid var(--ink);outline-offset:4px}

.login-scene{position:absolute;inset:0;z-index:0;min-height:100svh;border-radius:0;overflow:hidden;background:#8C8C8A;isolation:isolate}
/* a deeper shade at the foot of the photograph, where the words sit */
.login-scene::after{content:"";position:absolute;inset:0;background:linear-gradient(180deg,transparent 34%,rgba(20,22,20,.2) 52%,rgba(20,22,20,.62) 74%,rgba(16,18,16,.9) 100%);z-index:1}
.login-scene-photo{position:absolute;width:100%;height:100%;object-fit:cover;object-position:60% center;inset:0}
.login-scene-photo.oscuro{display:none}
:root[data-theme="dark"] .login-scene-photo.claro{display:none}
:root[data-theme="dark"] .login-scene-photo.oscuro{display:block}
.login-scene-copy{position:absolute;z-index:2;bottom:clamp(56px,11vh,110px);left:calc(var(--lg-panel) + clamp(40px,5vw,72px));right:220px;color:#fff}
.login-scene-copy h2{font-size:clamp(36px,3.8vw,56px);font-weight:600;letter-spacing:-.035em;line-height:1.08;margin:0}
.login-scene-tags{display:block;margin-top:22px;font-size:11px;font-weight:500;letter-spacing:.26em;text-transform:uppercase;color:rgba(255,255,255,.85)}
.login-scene-motto{
  position:absolute;z-index:2;right:clamp(28px,4vw,56px);bottom:clamp(28px,5vh,48px);
  font-size:9.5px;font-weight:500;letter-spacing:.24em;line-height:1.9;text-transform:uppercase;color:rgba(255,255,255,.82);
}
.login-scene-motto::before{content:"";display:block;width:26px;height:1px;background:rgba(255,255,255,.7);margin-bottom:14px}
@media(prefers-color-scheme:dark){
 :root:not([data-theme="light"]):not([data-theme="concreto"]) .login-scene-photo.claro{display:none}
 :root:not([data-theme="light"]):not([data-theme="concreto"]) .login-scene-photo.oscuro{display:block}
}
@media(max-width:1080px){
 .login-editorial{--lg-panel:clamp(340px,46vw,460px)}
 .login-editorial .login-card{padding:40px 36px 32px}
 .login-scene-copy{left:calc(var(--lg-panel) + 36px);right:36px;bottom:110px}
 /* no room for the corner motto beside the line and its tags */
 .login-scene-motto{display:none}
}
@media(max-width:760px){
 .login-editorial .login-inner{display:flex;flex-direction:column;min-height:100svh}
 .login-editorial .login-card{flex:1;padding:40px 28px 28px;background:var(--card-solid);box-shadow:none;border-right:0;border-radius:0}
 :root[data-theme="concreto"] .login-editorial .login-card{background:color-mix(in srgb,#E3DED1 38%,var(--card-solid))}
 .login-editorial .login-card > *{max-width:none}
 .login-editorial .login-brand{margin-bottom:44px}
 .login-editorial .login-card h1{font-size:32px}
 .login-scene{display:none}
}
@media(prefers-reduced-motion:reduce){.login-editorial,.login-editorial *{animation:none;transition:none}}
@media(min-width:761px) and (max-height:800px){
 .login-editorial .login-card{padding-top:28px;padding-bottom:24px}
 .login-editorial .login-brand{margin-bottom:32px}
 .login-editorial .login-card .lsub{margin:8px 0 24px}
 .login-editorial .fld{margin-bottom:16px}
}
