/* ISTMOFLOW interface. Tokens adapted from the Istmoflow localhost prototype
   (tokens.css): side colours, status palette, motion scale. Brand colours
   are BOYD Steamship's navy and gold, sampled from the official logo by
   tools/brand-assets.mjs. Dark mode follows the OS unless the user picks one. */

:root {
  color-scheme: light dark;
  --font: Inter, "Segoe UI", system-ui, -apple-system, sans-serif;
  --font-display: Manrope, Inter, "Segoe UI", system-ui, sans-serif;
  --mono: ui-monospace, "Cascadia Mono", Consolas, monospace;

  --ink: #1e3551; /* BOYD navy */
  --ink-2: #172b44;
  --ink-3: #2a4668;
  --accent: #1e3551;
  --accent-strong: #142540;
  --accent-soft: #e3e8f0;
  --gold: #d4a35f; /* BOYD gold: decoration and text on navy only */
  --on-ink: #dbe7f3; /* text on the navy panel and phone bar */
  --on-ink-muted: #9fb6cc; /* descriptions and group titles on navy */

  --paper: #eef1f5;
  --surface: #ffffff;
  --surface-2: #f6f8fa;
  --surface-3: #e9eef3;
  --line: #d9e1e8;
  --line-strong: #b3c1cc;
  --line-ctrl: #7f8f9f;
  --text-strong: #16283a;
  --text: #2a3b4c;
  --muted: #5b6d80;

  --atl: #246fb5;
  --atl-soft: #e3eefa;
  --pac: #b65a2b; /* was #c2602e: 4.19:1 on white */
  --pac-soft: #fbeae1;
  --ctl: #5b6d80;
  --ctl-soft: #e9eef3;

  --ok: #1d845b; /* was #1e8a5f: 4.32:1 on white */
  --info: #2b6cb0;
  --warn: #9b6010; /* was #c47a14: 3.09:1 on --warn-soft */
  --danger: #bc3939; /* was #c23b3b: 4.41:1 on --danger-soft */
  --on-accent: #ffffff; /* text on --accent (primary buttons) */
  --on-danger: #ffffff; /* text on --danger (danger buttons) */
  --warn-soft: #fdf2e0;
  --danger-soft: #fbe6e6;

  /* The Canal classes (web/visit-chips.mjs sizeChip): text and icon in the
     class colour on its soft fill, away from the status palette. */
  --class-regular: #2d419a;
  --class-regular-soft: #e7e9f8;
  --class-super: #0a6a66;
  --class-super-soft: #dcf1ee;
  --class-neo: #a3420f;
  --class-neo-soft: #fbe8dc;

  --r-s: 8px;
  --r-m: 12px;
  --r-l: 16px;
  --r-xl: 20px;
  --pill: 999px;

  --sh-card: 0 0 0 1px rgb(13 34 56 / .07), 0 1px 2px rgb(13 34 56 / .06), 0 4px 14px rgb(13 34 56 / .05);
  --sh-raised: 0 10px 30px rgb(13 34 56 / .18);
  --glass: color-mix(in srgb, var(--surface) 84%, transparent);

  --d-fast: 160ms;
  --d-base: 240ms;
  --d-slow: 320ms;
  --ease: cubic-bezier(.16, 1, .3, 1);
  --ease-open: cubic-bezier(.32, .72, 0, 1);

  --rail-w: 264px;
  --rail-w-collapsed: 72px;
  --rail-bar-h: 60px;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --paper: #091220;
    --surface: #1a3148;
    --surface-2: #121e2d;
    --surface-3: #26405a;
    --line: #2a4561;
    --line-strong: #3b5a78;
    --line-ctrl: #6f8aa5;
    --text-strong: #eef4fa;
    --text: #d3dfeb;
    --muted: #9db1c6;
    --accent: #d4a35f;
    --accent-strong: #e4bd85;
    --accent-soft: #3a2f1c;
    --atl: #5aa2e6;
    --atl-soft: #142d47;
    --pac: #e8835a;
    --pac-soft: #3a2218;
    --ctl-soft: #1d2f43;
    --warn-soft: #3a2a12;
    --danger-soft: #3d1c1e;
    --sh-card: 0 0 0 1px rgb(255 255 255 / .06), 0 4px 16px rgb(0 0 0 / .35);
    --ok: #76b89d;
    --warn: #d5a158;
    --danger: #df9999;
    --on-accent: #1e3551; /* navy on the gold accent */
    --on-danger: #2a0d0f;
    --on-ink: #dbe7f3;
    --on-ink-muted: #9fb6cc;
    --class-regular: #b4bef6;
    --class-regular-soft: #252e5e;
    --class-super: #80d6ca;
    --class-super-soft: #113f42;
    --class-neo: #f4ae7e;
    --class-neo-soft: #4a2915;
  }
}
:root[data-theme="dark"] {
  --paper: #091220;
  --surface: #1a3148;
  --surface-2: #121e2d;
  --surface-3: #26405a;
  --line: #2a4561;
  --line-strong: #3b5a78;
  --line-ctrl: #6f8aa5;
  --text-strong: #eef4fa;
  --text: #d3dfeb;
  --muted: #9db1c6;
  --accent: #d4a35f;
  --accent-strong: #e4bd85;
  --accent-soft: #3a2f1c;
  --atl: #5aa2e6;
  --atl-soft: #142d47;
  --pac: #e8835a;
  --pac-soft: #3a2218;
  --ctl-soft: #1d2f43;
  --warn-soft: #3a2a12;
  --danger-soft: #3d1c1e;
  --sh-card: 0 0 0 1px rgb(255 255 255 / .06), 0 4px 16px rgb(0 0 0 / .35);
  --ok: #76b89d;
  --warn: #d5a158;
  --danger: #df9999;
  --on-accent: #1e3551;
  --on-danger: #2a0d0f;
  --on-ink: #dbe7f3;
  --on-ink-muted: #9fb6cc;
  --class-regular: #b4bef6;
  --class-regular-soft: #252e5e;
  --class-super: #80d6ca;
  --class-super-soft: #113f42;
  --class-neo: #f4ae7e;
  --class-neo-soft: #4a2915;
}

*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; height: 100%; }
body {
  background: var(--paper);
  color: var(--text);
  font: 14px/1.45 var(--font);
  -webkit-font-smoothing: antialiased;
}
button, input, select, textarea { font: inherit; color: inherit; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.num, time, .mono { font-variant-numeric: tabular-nums; }
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.ico { flex: none; vertical-align: middle; }

/* ---------- shell ---------- */
.app { display: grid; grid-template-columns: var(--rail-w) minmax(0, 1fr); min-height: 100vh; transition: grid-template-columns var(--d-slow) var(--ease); }
.app.rail-collapsed { grid-template-columns: var(--rail-w-collapsed) minmax(0, 1fr); }
/* Side panel (web/nav.mjs): head, groups that scroll on short screens, foot.
   Navy in both themes; the focus ring is gold there (navy would vanish). */
.rail {
  position: sticky; top: 0; height: 100vh; height: 100dvh; min-width: 0;
  display: flex; flex-direction: column; padding: 12px 10px 10px;
  background: linear-gradient(180deg, var(--ink) 0%, var(--ink-2) 100%); color: var(--on-ink);
}
.rail :focus-visible, .tabbar :focus-visible { outline-color: var(--gold); }
/* Head: the agency's logo, «ISTMOFLOW · BOYD» and, outside production, a
   discreet mark under the name. */
.rail-head {
  display: grid; grid-template-columns: auto minmax(0, 1fr); grid-template-areas: "plate text" "plate mark";
  align-items: center; gap: 4px 10px; padding: 0 2px 12px; margin-bottom: 4px; border-bottom: 1px solid rgb(255 255 255 / .1);
}
/* BOYD brand: the official logo always sits on a white plate, so its navy
   and gold read the same on the navy panel and in either theme. */
.brand-plate { grid-area: plate; display: grid; place-items: center; width: 64px; height: 52px; padding: 4px 6px; border-radius: 12px; background: #fff; box-shadow: 0 0 0 1px color-mix(in srgb, var(--gold) 60%, transparent); }
.brand-emblem { width: 100%; height: 100%; object-fit: contain; }
.brand-mark { display: none; width: 36px; height: 36px; object-fit: contain; }
/* An agency logo of any shape fits the same plate (web/brand.mjs). */
.brand-plate .tenant-logo, .topbar-logo.tenant-logo { object-fit: contain; }
.brand-text { grid-area: text; align-self: end; min-width: 0; }
.rail-head:has(> .env-mark[hidden]) .brand-text { grid-row: 1 / 3; align-self: center; }
.env-mark { grid-area: mark; justify-self: start; align-self: start; padding: 1px 7px; border-radius: var(--pill); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--gold) 70%, transparent); color: var(--gold); font: 700 10px/1.5 var(--font); letter-spacing: .06em; text-transform: uppercase; white-space: nowrap; }
.env-mark[hidden], .env-short { display: none; }
.topbar-logo { display: none; height: 36px; width: auto; padding: 2px 6px; border-radius: 9px; background: #fff; box-shadow: 0 0 0 1px var(--line); }
.boot {
  position: fixed; inset: 0; z-index: 200; display: grid; place-content: center; justify-items: center; gap: 16px; padding: 24px;
  background: #fff; transition: opacity var(--d-slow) var(--ease), visibility var(--d-slow) var(--ease);
}
.boot img { width: min(220px, 56vw); height: auto; }
.boot-name { margin: 0; font: 700 12px/1.3 var(--font-display); letter-spacing: .16em; text-transform: uppercase; color: var(--brand-on-white, #1e3551); text-align: center; }
.boot-bar { width: 148px; height: 3px; border-radius: 3px; background: #e3e8f0 linear-gradient(90deg, transparent, var(--gold), transparent) no-repeat; background-size: 55% 100%; animation: boot-bar 1.1s linear infinite; }
@keyframes boot-bar { from { background-position: -120% 0; } to { background-position: 220% 0; } }
.boot.done { opacity: 0; visibility: hidden; pointer-events: none; }
/* The new shell on its way, or a start that failed (web/recover.mjs): plain
   words on the launch screen, always light like it. #16283a on white is
   15:1, #5b6d80 5.3:1, white on the navy 12.5:1. */
.boot-status, .boot-fail-title, .boot-fail-help { margin: 0; max-width: 36ch; text-align: center; }
.boot-status { color: #5b6d80; font-size: 14px; }
.boot-fail { display: grid; justify-items: center; gap: 14px; }
.boot-fail-words { display: grid; gap: 6px; }
.boot-fail-title { color: #16283a; font: 800 19px/1.25 var(--font-display); }
.boot-fail-help { color: #5b6d80; font-size: 14.5px; line-height: 1.45; }
.boot .btn.boot-retry { min-height: 48px; padding: 10px 26px; font-size: 15px; font-weight: 700; background: var(--brand-on-white, #1e3551); border-color: var(--brand-on-white, #1e3551); color: #fff; }
.boot :focus-visible { outline-color: var(--brand-on-white, #1e3551); }
.brand-name { font: 800 15px/1.2 var(--font-display); letter-spacing: .03em; color: #fff; }
.brand-tenant { color: var(--gold); font-weight: 700; white-space: nowrap; }
.brand-sub { display: none; font-size: 11px; line-height: 1.3; color: var(--on-ink-muted); margin-top: 3px; }
@media (min-height: 860px) { .brand-sub { display: block; } }
.rail-nav { flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin; scrollbar-color: rgb(255 255 255 / .25) transparent; margin: 0 -4px; padding: 6px 4px; }
.rail-group + .rail-group { margin-top: 6px; }
.rail-group-title { display: block; padding: 6px 10px 3px; font: 700 10.5px/1.2 var(--font); letter-spacing: .12em; text-transform: uppercase; color: var(--on-ink-muted); }
.rail-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 1px; }
/* One entry: icon, name and its line of description; never cut (they wrap). */
.rail-btn {
  position: relative; display: flex; align-items: center; gap: 10px; width: 100%; min-height: 40px;
  padding: 4px 8px 4px 4px; border: 0; border-radius: 10px; background: transparent; color: inherit;
  text-align: left; text-decoration: none; cursor: pointer; transition: background var(--d-fast) var(--ease);
}
.rail-btn[hidden] { display: none; }
.rail-btn:hover { background: rgb(255 255 255 / .07); }
.rail-btn:focus-visible { outline-offset: -2px; }
.rail-btn[aria-current="page"] { background: color-mix(in srgb, var(--gold) 16%, transparent); box-shadow: inset 3px 0 0 var(--gold); }
.rail-ico { flex: none; display: grid; place-items: center; width: 32px; height: 32px; border-radius: 9px; color: var(--on-ink); }
.rail-btn[aria-current="page"] .rail-ico { color: var(--gold); }
.rail-text { display: grid; flex: 1; min-width: 0; }
.rail-label { font-size: 13.5px; font-weight: 600; line-height: 1.2; color: #fff; overflow-wrap: break-word; }
.rail-desc { font-size: 11.5px; line-height: 1.25; color: var(--on-ink-muted); overflow-wrap: break-word; }
.rail-count { flex: none; min-width: 22px; padding: 1px 6px; border-radius: var(--pill); background: var(--gold); color: var(--ink); font: 800 11px/1.45 var(--font); text-align: center; font-variant-numeric: tabular-nums; }
.rail-count[hidden] { display: none; }
/* The foot: theme, language, install and contract, as icons with tooltips. */
.rail-foot { display: flex; align-items: center; gap: 4px; padding: 8px 0 0; margin-top: 4px; border-top: 1px solid rgb(255 255 255 / .1); }
.rail-icon { position: relative; display: inline-flex; align-items: center; justify-content: center; gap: 2px; min-width: 44px; height: 40px; padding: 0 8px; border: 0; border-radius: 10px; background: transparent; color: var(--on-ink); cursor: pointer; transition: background var(--d-fast) var(--ease); }
.rail-icon:hover { background: rgb(255 255 255 / .08); }
.rail-icon[aria-pressed="true"] { color: var(--gold); }
.rail-icon-glyph { display: inline-grid; }
.rail-icon-code { font: 800 10.5px/1 var(--font); letter-spacing: .04em; }
.rail-collapse { margin-left: auto; }
/* Contracted (72 px): icons only, with the name as tooltip and accessible name. */
.app.rail-collapsed .rail { padding: 12px 8px 10px; }
.app.rail-collapsed .rail-head { grid-template-columns: minmax(0, 1fr); grid-template-areas: "plate" "mark"; justify-items: center; }
.app.rail-collapsed .brand-plate { width: 48px; height: 48px; padding: 4px; border-radius: 10px; }
.app.rail-collapsed .brand-emblem, .app.rail-collapsed .brand-text, .app.rail-collapsed .rail-text, .app.rail-collapsed .rail-group-title, .app.rail-collapsed .env-full { display: none; }
.app.rail-collapsed .brand-mark, .app.rail-collapsed .env-short { display: block; }
.app.rail-collapsed .env-mark { justify-self: center; padding: 1px 6px; }
.app.rail-collapsed .rail-group + .rail-group { margin-top: 6px; padding-top: 6px; border-top: 1px solid rgb(255 255 255 / .1); }
.app.rail-collapsed .rail-btn { justify-content: center; min-height: 40px; padding: 4px; }
.app.rail-collapsed .rail-count { position: absolute; top: 1px; right: 2px; min-width: 18px; padding: 0 4px; font-size: 10px; }
.app.rail-collapsed .rail-foot { flex-direction: column; }
.app.rail-collapsed .rail-collapse { margin-left: 0; }
/* Short laptop screens: every entry still fits without scrolling (the owner
   sees eleven); under 600 px the descriptions stay in the tooltip and the name. */
@media (max-height: 760px) and (min-width: 721px) {
  .rail-btn { min-height: 34px; padding-top: 3px; padding-bottom: 3px; }
  .rail-ico { width: 28px; height: 28px; }
  .rail-group-title { padding: 4px 10px 2px; }
  .rail-group + .rail-group { margin-top: 4px; }
  .brand-plate { width: 58px; height: 46px; }
  .app.rail-collapsed .rail-btn { min-height: 36px; }
  .rail-icon { height: 36px; }
}
@media (max-height: 600px) and (min-width: 721px) {
  .rail-desc { display: none; }
}
/* Keyboard tooltip of icon-only buttons (the mouse gets the title). */
.rail-tip { position: fixed; z-index: 95; max-width: 260px; padding: 6px 10px; border-radius: 8px; background: var(--ink); color: #fff; box-shadow: var(--sh-raised), 0 0 0 1px rgb(255 255 255 / .12); font-size: 12px; line-height: 1.35; pointer-events: none; transform: translateY(-50%); }
.rail-tip[data-side="top"] { transform: translate(-50%, -100%); }
.rail-tip[hidden] { display: none; }

.main { min-width: 0; display: flex; flex-direction: column; }
/* Header: the section (its name, its modes, «＋ Buque») on the left; search,
   undo, the save state, presence and role on the right. When the two do not
   fit in one line, the right one moves below, whole. */
.topbar {
  position: sticky; top: 0; z-index: 30; display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px;
  padding: 10px 18px; background: var(--glass); backdrop-filter: blur(14px); border-bottom: 1px solid var(--line);
}
.topbar-title { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px; min-width: 0; }
.topbar h1 { margin: 0; font: 800 18px/1.1 var(--font-display); color: var(--text-strong); }
.section-tools { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.section-tools[hidden], .view-switch[hidden], .btn[hidden] { display: none; }
.topbar-tools { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 8px; margin-left: auto; min-width: 0; }
.env-banner { font-size: 12px; color: var(--warn); background: var(--warn-soft); border-radius: var(--pill); padding: 4px 10px; }
.env-banner[hidden] { display: none; }
/* On the desktop the panel carries the discreet mark instead (phones keep it). */
@media (min-width: 721px) { .env-banner { display: none; } }
/* A passkey added to the person's own account (web/key-notice.mjs): a row of
   its own at the foot of the header, so it stays in sight on every screen
   until «Fui yo». Text on --surface, the edge and the icon in --warn: pairs
   the contrast report already checks in both themes. */
.key-notice { flex: 1 0 100%; display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; padding: 10px 12px; border: 1px solid var(--warn); border-left-width: 5px; border-radius: var(--r-m); background: var(--surface); color: var(--text-strong); font-size: 13.5px; line-height: 1.4; }
.key-notice > .ico { flex: none; color: var(--warn); }
.key-notice-text { flex: 1 1 260px; min-width: 0; overflow-wrap: anywhere; }
.key-notice-text p { margin: 0; }
.key-notice-text ul { margin: 4px 0; padding-left: 20px; }
.key-notice-actions { display: flex; flex-wrap: wrap; gap: 8px; }
.search { min-width: 160px; flex: 0 1 280px; padding: 8px 12px; border: 1px solid var(--line-ctrl); border-radius: 10px; background: var(--surface); }
/* The search filters the board: it shows where a board is on screen. */
body[data-view]:not([data-view="compact"]):not([data-view="full"]):not([data-view="split"]) .topbar .search { display: none; }
.btn {
  display: inline-flex; align-items: center; gap: 6px; min-height: 36px; padding: 6px 12px;
  border: 1px solid var(--line-ctrl); border-radius: 10px; background: var(--surface); color: var(--text-strong);
  cursor: pointer; transition: background var(--d-fast) var(--ease), border-color var(--d-fast) var(--ease), transform var(--d-fast) var(--ease);
}
.btn:hover { border-color: var(--accent); }
.btn:active { transform: translateY(1px); }
.btn:disabled { opacity: .45; cursor: not-allowed; }
/* Busy while the server answers: it keeps the focus (never «disabled»). */
.btn[aria-disabled="true"], .btn[aria-busy="true"] { opacity: .7; cursor: progress; }
.btn.primary { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
a.btn { text-decoration: none; }
.btn.quiet { border-color: transparent; background: transparent; }
.btn.sm { min-height: 30px; padding: 4px 9px; font-size: 13px; }
.btn.icon { padding: 6px; min-width: 36px; justify-content: center; }

.save-pill {
  display: inline-flex; align-items: center; gap: 6px; padding: 5px 11px; border-radius: var(--pill);
  font-size: 12px; font-weight: 600; background: var(--surface-3); color: var(--text);
  transition: background var(--d-base) var(--ease), color var(--d-base) var(--ease);
}
.save-pill[data-state="saved"] { background: color-mix(in srgb, var(--ok) 16%, var(--surface)); color: var(--ok); }
.save-pill[data-state="pending"] { background: color-mix(in srgb, var(--info) 14%, var(--surface)); color: var(--info); }
.save-pill[data-state="offline"], .save-pill[data-state="held"] { background: var(--warn-soft); color: var(--warn); }
.save-pill[data-state="conflict"], .save-pill[data-state="error"] { background: var(--danger-soft); color: var(--danger); }
.save-pill[data-state="saved"] .ico { animation: pop var(--d-slow) var(--ease); }
.save-pill[data-state="conflict"], .save-pill[data-state="error"] { cursor: pointer; }
.save-short, .save-time { white-space: nowrap; }
@keyframes pop { from { transform: scale(.6); } to { transform: scale(1); } }

.identity { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--muted); }
/* The local test identities: outside the local environment the label is
   [hidden], which display: inline-flex would beat (an empty selector in the
   published header, and a whole row of it on phones). */
.identity[hidden] { display: none; }
.identity select { padding: 4px 8px; border-radius: 8px; border: 1px solid var(--line-ctrl); background: var(--surface); }

/* ---------- views ---------- */
.views { display: grid; grid-template-columns: 1fr; gap: 0; flex: 1; min-height: 0; }
.views[data-view="split"] { grid-template-columns: minmax(360px, 1fr) minmax(320px, 46%); }
.board-pane { min-width: 0; padding: 14px 18px 60px; }
.map-pane { position: relative; min-height: 420px; border-left: 1px solid var(--line); }
.views[data-view="split"] .map-pane { position: sticky; top: var(--topbar-h, 57px); height: calc(100vh - var(--topbar-h, 57px)); }
.views[data-view="map"] .map-pane { height: calc(100vh - var(--topbar-h, 57px)); }
.views[data-view="map"] .board-pane, .views:not([data-view="map"]):not([data-view="split"]) .map-pane { display: none; }

/* ---------- board toolbar (counters, side switch, manager code) ---------- */
.board-toolbar { margin: 0 0 14px; }
.new-visit-slot:empty { display: none; }
.new-visit-slot > .inline-ask { margin: 0 0 12px; max-width: 560px; }
/* Counters: one strip of chips (each one filters). «Contadores y managers»
   folds them together with the manager code (stage B0): folded, only the
   counter and the manager that filter stay. On phones both slide sideways. */
.kpi-strip { display: flex; align-items: flex-start; gap: 8px; margin: 0 0 10px; }
.kpi-toggle { flex: none; display: inline-flex; align-items: center; gap: 6px; min-height: 34px; padding: 4px 12px 4px 8px; border: 1px solid var(--line-ctrl); border-radius: var(--pill); background: var(--surface); color: var(--text-strong); font: 700 11px/1 var(--font); letter-spacing: .08em; text-transform: uppercase; cursor: pointer; }
.kpi-toggle:hover { border-color: var(--accent); }
.kpi-toggle .chev { transition: transform var(--d-base) var(--ease); }
.kpi-toggle .kpi-ico { color: var(--muted); }
.board-toolbar[data-folded="true"] .kpi-toggle .chev { transform: rotate(-90deg); }
.board-toolbar[data-folded="true"] .kpi-chip:not([aria-pressed="true"]),
.board-toolbar[data-folded="true"] .mgr-legend > :not([aria-pressed="true"]):not(.mgr-legend-title),
.board-toolbar[data-folded="true"] .kpi-chips:not(:has(> [aria-pressed="true"])),
.board-toolbar[data-folded="true"] .mgr-legend:not(:has(> [aria-pressed="true"])) { display: none; }
.kpi-chips { flex: 1; min-width: 0; display: flex; flex-wrap: wrap; gap: 6px; }
/* «Contraer todo» and «Expandir todo»: icon and words; on phones the icon,
   with the words for screen readers and as tooltip. */
.fold-all .fold-label, .band-toggle .band-label { white-space: nowrap; }
.kpi-chip { display: inline-flex; align-items: baseline; gap: 6px; min-height: 34px; padding: 6px 12px; border: 1px solid var(--line); border-radius: var(--pill); background: var(--surface); color: var(--text); font: inherit; font-size: 12.5px; line-height: 1.2; white-space: nowrap; cursor: pointer; transition: border-color var(--d-fast) var(--ease), background var(--d-fast) var(--ease); }
.kpi-chip b { font: 800 15px/1 var(--font-display); color: var(--text-strong); }
.kpi-chip.zero b { color: var(--muted); }
.kpi-chip:hover { border-color: var(--accent); }
.kpi-chip[aria-pressed="true"] { border-color: var(--accent); background: var(--accent-soft); color: var(--text-strong); box-shadow: inset 0 0 0 1px var(--accent); }
.filter-row { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.segmented { display: inline-flex; padding: 3px; border-radius: 11px; background: var(--surface-3); gap: 2px; }
.segmented button { border: 0; background: transparent; padding: 6px 12px; border-radius: 8px; cursor: pointer; color: var(--text); font-size: 13px; }
.segmented button[aria-pressed="true"] { background: var(--surface); color: var(--text-strong); box-shadow: var(--sh-card); font-weight: 600; }
/* The section's modes are links (each mode has its address). */
.segmented a { display: inline-flex; align-items: center; justify-content: center; gap: 6px; min-height: 30px; padding: 5px 12px; border-radius: 8px; color: var(--text); font-size: 13px; text-decoration: none; white-space: nowrap; }
.segmented a:hover { color: var(--text-strong); background: color-mix(in srgb, var(--surface) 55%, transparent); }
.segmented a[aria-current="page"] { background: var(--surface); color: var(--text-strong); box-shadow: var(--sh-card); font-weight: 600; }
.side-band { position: relative; isolation: isolate; height: 230px; margin: 0 0 12px; border-radius: var(--r-xl); overflow: hidden; background: #0b1b2c; box-shadow: var(--sh-card); }
.side-band-map { position: absolute; inset: 0; }
.side-band[hidden] { display: none; }
.band-toggle { margin-left: auto; }

/* ---------- blocks and stages ---------- */
.block { margin: 0 0 22px; }
.block-head { display: flex; align-items: baseline; gap: 10px; margin: 6px 2px 10px; }
.block-head h2 { margin: 0; font: 800 13px/1.2 var(--font-display); letter-spacing: .12em; color: var(--text-strong); }
.block-head { align-items: center; flex-wrap: wrap; }
.block-toggle { display: inline-flex; align-items: center; gap: 8px; padding: 4px 6px; border: 0; border-radius: 8px; background: none; color: inherit; font: inherit; letter-spacing: inherit; text-align: left; cursor: pointer; }
.block-toggle:hover { background: var(--surface-3); }
.block-toggle .chev { transition: transform var(--d-base) var(--ease); }
.block[data-collapsed="true"] .block-toggle .chev { transform: rotate(-90deg); }
.block[data-collapsed="true"] { margin-bottom: 12px; }
/* Section chips: enter straight into one section of the side. */
.stage-nav { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 2px 10px; }
.stage-jump { display: inline-flex; align-items: center; gap: 6px; padding: 4px 9px 4px 4px; border: 1px solid var(--line); border-radius: var(--pill); background: var(--surface); color: var(--text-strong); font-size: 11.5px; font-weight: 700; letter-spacing: .02em; cursor: pointer; transition: border-color var(--d-fast) var(--ease); }
.stage-jump:hover { border-color: var(--side); }
.stage-jump .stage-no { padding: 3px 5px; }
.stage-jump b { min-width: 18px; text-align: center; padding: 1px 6px; border-radius: var(--pill); background: var(--side-soft); color: var(--side); }
.jump-alert { display: inline-flex; align-items: center; gap: 2px; color: var(--danger); }
.stage { scroll-margin-top: calc(var(--topbar-h, 57px) + 8px); }
.stage.flash { animation: flash 1.2s var(--ease); }
.side-band-hint { position: absolute; z-index: 500; left: 10px; top: 10px; padding: 4px 10px; border-radius: var(--pill); background: rgb(7 21 38 / .72); color: #fff; font-size: 11.5px; font-weight: 600; pointer-events: none; }
@media (max-width: 900px) {
  .stage-nav { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; padding-bottom: 2px; }
  .stage-nav::-webkit-scrollbar { display: none; }
  .stage-jump { flex: none; }
  .stage { scroll-margin-top: 8px; }
}
.block-head .block-count { font-size: 12px; color: var(--muted); }
.block[data-side="atlantic"] { --side: var(--atl); --side-soft: var(--atl-soft); }
.block[data-side="pacific"] { --side: var(--pac); --side-soft: var(--pac-soft); }
.block[data-side="control"] { --side: var(--ctl); --side-soft: var(--ctl-soft); }

.stage {
  background: var(--surface); border-radius: var(--r-l); box-shadow: var(--sh-card);
  margin-bottom: 10px; border-left: 4px solid var(--side); overflow: clip;
  transition: box-shadow var(--d-base) var(--ease);
}
.stage.drop-target { box-shadow: 0 0 0 2px var(--accent), var(--sh-card); }
.stage-head {
  position: sticky; top: var(--topbar-h, 57px); z-index: 5; display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 9px 12px; background: var(--glass); backdrop-filter: blur(14px);
}
.stage-toggle { display: inline-flex; align-items: center; gap: 8px; border: 0; background: none; padding: 2px; cursor: pointer; text-align: left; min-width: 0; }
.stage-toggle .ico { transition: transform var(--d-base) var(--ease); }
.stage[data-collapsed="true"] .stage-toggle .ico.chev { transform: rotate(-90deg); }
.stage-no { font: 700 11px/1 var(--mono); color: var(--side); background: var(--side-soft); border-radius: 6px; padding: 4px 6px; }
.stage-title { font: 800 13.5px/1.2 var(--font-display); letter-spacing: .03em; color: var(--text-strong); }
.stage-desc { display: block; font-size: 11.5px; color: var(--muted); font-weight: 400; letter-spacing: 0; margin-top: 2px; }
.stage-count { font: 700 12px/1 var(--font); min-width: 24px; text-align: center; padding: 4px 7px; border-radius: var(--pill); background: var(--side-soft); color: var(--side); }
.stage-alert { font-size: 11px; font-weight: 700; color: var(--danger); background: var(--danger-soft); border-radius: var(--pill); padding: 3px 8px; }
.stage-tools { margin-left: auto; display: flex; gap: 4px; }
.stage-body { display: grid; grid-template-rows: 1fr; transition: grid-template-rows var(--d-slow) var(--ease-open); }
.stage[data-collapsed="true"] .stage-body { grid-template-rows: 0fr; }
.stage-body > .stage-inner { overflow: hidden; min-height: 0; }
.stage-cards { display: grid; gap: 8px; padding: 4px 12px 12px; min-height: 44px; }
.view-full .stage-cards { grid-template-columns: repeat(auto-fill, minmax(min(320px, 100%), 1fr)); }
.stage-empty { color: var(--muted); font-size: 12.5px; padding: 10px 2px; }
/* Arrival group headings (redesign §4): «Llegan en 5 días o menos», «En 6 a
   9 días», «En 10 días o más», «ETA por confirmar». */
.run-head { grid-column: 1 / -1; margin: 0; font: 700 10.5px/1.3 var(--font); letter-spacing: .08em; text-transform: uppercase; color: var(--muted); padding: 8px 2px 0; border-top: 1px dashed var(--line); }
.stage-cards > .run-head:first-child { border-top: 0; padding-top: 2px; }
/* Far arrivals (V28 time-order.js): 6–9 days as one-line rows (compact cards
   with their order number, .arr-row, below), 10 days or more (and no ETA)
   as small tiles in a grid, about 7 in a row at 1440 px and always 2 on a
   phone: a tile is 148 px wide or more, unless half the line is less (a
   320 px phone has 272 px: two tiles of 132 px). Both keep the manager
   colour on the left edge. */
.future-minis { grid-column: 1 / -1; display: grid; gap: 6px; }
.future-cubes { grid-column: 1 / -1; display: grid; gap: 8px; grid-template-columns: repeat(auto-fill, minmax(min(148px, calc(50% - 4px)), 1fr)); container-type: inline-size; }
.arr-rank { font: 700 11px/1 var(--mono); color: var(--muted); white-space: nowrap; }
/* The tile (web/card-html.mjs tileHtml): one link to the dossier, at most
   ~120 px tall. The drawing «en camino» on the left with the size and the
   name (two lines at most) beside it; under them the ETA with its distance,
   then the beam and the pre-arrival bar once VUMPA started. */
.card.arr-tile.tile {
  grid-template-columns: 52px minmax(0, 1fr); grid-template-rows: auto 1fr auto auto;
  grid-template-areas: "art head" "art name" "eta eta" "foot foot"; gap: 2px 8px; align-items: start;
  padding: 5px 7px 5px 11px; color: var(--text); text-decoration: none; cursor: pointer;
  transition: border-color var(--d-fast) var(--ease), box-shadow var(--d-base) var(--ease);
}
.card.arr-tile.tile:hover { border-color: var(--accent); box-shadow: var(--sh-card); }
.card.arr-tile.tile:focus-visible { outline-offset: 2px; }
.tile-art { grid-area: art; display: grid; }
.tile-art > .ship-art.ship-tile { width: 52px; height: 52px; border-radius: 9px; }
.tile-head { grid-area: head; display: flex; flex-wrap: wrap; align-items: center; gap: 3px; min-width: 0; }
.tile-head .badge { padding: 1px 6px; font-size: 10.5px; }
/* The class beside the drawing: icon and word within the ~68 px a tile of
   148 px leaves there. */
.tile-head .badge.tier { gap: 2px; padding: 1px 4px 1px 3px; font-size: 10px; letter-spacing: 0; }
.tile-head .badge.tier .tier-ico { width: 11px; height: 11px; }
.tile-name {
  grid-area: name; align-self: start; min-width: 0; overflow: hidden; font: 700 12.5px/1.25 var(--font); color: var(--text-strong); overflow-wrap: break-word;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2;
}
.tile-name .arr-rank { font-size: 10.5px; }
.tile-eta { grid-area: eta; display: flex; flex-wrap: wrap; align-items: center; gap: 2px 4px; margin-top: 2px; font-size: 11.5px; color: var(--text); min-width: 0; }
.tile-eta b { font-size: 10px; letter-spacing: .06em; color: var(--muted); }
.tile-eta .eta-signal { margin: 0; padding: 1px 6px; font-size: 10.5px; }
.tile-foot { grid-area: foot; display: flex; flex-wrap: wrap; align-items: center; gap: 2px 6px; font-size: 11px; color: var(--text); min-width: 0; }
.tile-foot .badge { padding: 0 5px; font-size: 10.5px; line-height: 14px; }
.tile-beam { white-space: nowrap; }
/* The tiny pre-arrival bar of a tile; in alert, «Prearribo pendiente» with
   its sign and count, the words wrapping between them when the tile is narrow. */
.pa-chip.tiny { gap: 4px; padding: 1px 6px; font-size: 10.5px; }
.pa-chip.tiny .pa-bar { width: 26px; height: 5px; }
.pa-chip.tiny.alert { flex-wrap: nowrap; white-space: normal; line-height: 1.2; padding: 2px 8px 2px 6px; }
/* Tiles narrower than ~146 px (two in a row on a 320 px phone): a smaller
   drawing beside the size, and the name on the whole width under them, so
   it still reads in two lines (.future-cubes is the container). */
@container (max-width: 299px) {
  .card.arr-tile.tile { grid-template-columns: 40px minmax(0, 1fr); grid-template-areas: "art head" "name name" "eta eta" "foot foot"; column-gap: 6px; }
  .tile-art > .ship-art.ship-tile { width: 40px; height: 40px; border-radius: 8px; }
  .tile-head { align-self: center; }
  /* ~66 px beside the smaller drawing: a smaller icon and padding keep
     «REGULAR» whole on a 320 px phone. */
  .tile-head .badge.tier { padding: 1px 3px 1px 2px; }
  .tile-head .badge.tier .tier-ico { width: 10px; height: 10px; }
}
/* ETA closeness (V28 etaSignal): words always, colour as support. */
.eta-signal { display: inline-block; margin-left: 4px; padding: 1px 7px; border-radius: var(--pill); font-size: 11px; font-weight: 700; background: var(--surface-3); color: var(--text); white-space: nowrap; }
.eta-signal.tone-h24 { background: var(--warn-soft); color: var(--warn); }
.eta-signal.tone-overdue, .eta-signal.tone-overdue-6, .eta-signal.tone-overdue-24 { background: var(--danger-soft); color: var(--danger); }
.card-time .eta-signal { margin: 3px 0 0; }
/* Manager code (V28 "CÓDIGO DE MANAGERS"): legend chips that filter. */
.mgr-legend { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 10px; }
.mgr-legend-title { font-size: 10.5px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--muted); margin-right: 2px; }
.mgr-chip { display: inline-flex; align-items: center; gap: 6px; padding: 3px 10px 3px 6px; border-radius: var(--pill); border: 1px solid var(--line-ctrl); background: var(--surface); color: var(--text-strong); font-size: 12px; font-weight: 700; cursor: pointer; }
.mgr-chip i { width: 12px; height: 12px; border-radius: 50%; background: var(--mgr); box-shadow: 0 0 0 1px rgb(255 255 255 / .5); }
.mgr-chip b { font-weight: 600; color: var(--muted); }
.mgr-chip[aria-pressed="true"] { border-color: var(--mgr); box-shadow: inset 0 0 0 1px var(--mgr); background: color-mix(in srgb, var(--mgr) 14%, var(--surface)); }
.mgr-chip.quiet { cursor: default; border-style: dashed; }
.mgr-chip.zero b { font-weight: 400; }
/* «Por asignar»: grey and dashed, never a manager colour. */
.mgr-chip.unassigned i { box-sizing: border-box; background: transparent; border: 2px dashed var(--muted); box-shadow: none; }
.mgr-chip.unassigned[aria-pressed="true"] { border-color: var(--muted); box-shadow: inset 0 0 0 1px var(--muted); background: var(--surface-3); }
.mgr-tag { display: inline-flex; align-items: center; padding: 1px 8px 1px 6px; border-left: 5px solid var(--mgr); border-radius: 6px; background: color-mix(in srgb, var(--mgr) 15%, var(--surface)); color: var(--text-strong); font-size: 11.5px; font-weight: 700; white-space: nowrap; }
/* Up to two managers on a card (§6): each chip in its colour; one a line
   rule added has a dashed outline (and says «por línea» in words). */
.mgr-chips { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 4px; min-width: 0; }
.mgr-tag.m2 { border-left-color: var(--mgr2, var(--mgr)); background: color-mix(in srgb, var(--mgr2, var(--mgr)) 15%, var(--surface)); }
.mgr-tag.by-rule { border-top: 1px dashed var(--line-ctrl); border-right: 1px dashed var(--line-ctrl); border-bottom: 1px dashed var(--line-ctrl); }
.mgr-tag.unassigned { border: 1px dashed var(--muted); padding-left: 7px; background: transparent; color: var(--muted); font-weight: 600; }
.mgr-more { display: inline-flex; align-items: center; padding: 1px 6px; border-radius: 6px; background: var(--surface-3); color: var(--text); font-size: 11px; font-weight: 700; }
.stage-minimap { height: 180px; margin: 0 12px 12px; border-radius: var(--r-m); overflow: hidden; background: var(--surface-3); position: relative; }

/* ---------- vessel card ---------- */
.card {
  position: relative; display: grid; grid-template-columns: auto 1fr auto; gap: 4px 10px; align-items: start;
  padding: 12px 10px 9px; border-radius: var(--r-m); background: var(--surface-2); border: 1px solid var(--line);
  transition: transform var(--d-base) var(--ease), box-shadow var(--d-base) var(--ease), background var(--d-base) var(--ease);
}
/* Manager colour across the top of the card, as in the production Pending;
   two managers split it in two halves; nobody assigned, dashed grey. */
.card::before { content: ""; position: absolute; inset: -1px -1px auto; height: 4px; border-radius: var(--r-m) var(--r-m) 0 0; background: var(--mgr, var(--line-strong)); }
.card.two-mgr::before { background: linear-gradient(90deg, var(--mgr) 0 50%, var(--mgr2) 50% 100%); }
.card.no-mgr::before { background: repeating-linear-gradient(90deg, var(--muted) 0 6px, transparent 6px 10px); }
/* Compact cards and arrival rows and tiles: the bar on the left edge, split
   top and bottom with two managers (redesign §4). */
.card.compact-card::before, .card.arr-tile::before { inset: -1px auto -1px -1px; width: 4px; height: auto; border-radius: var(--r-m) 0 0 var(--r-m); background: linear-gradient(180deg, var(--mgr, var(--line-strong)) 0 50%, var(--mgr2, var(--mgr, var(--line-strong))) 50% 100%); }
.card.compact-card.no-mgr::before, .card.arr-tile.no-mgr::before { background: repeating-linear-gradient(180deg, var(--muted) 0 5px, transparent 5px 9px); }
.card:hover { box-shadow: var(--sh-card); }
/* Off-screen cards are not laid out or painted until scrolled near (large
   boards: it halves the time of a redraw). Each kind keeps a size close to
   its real one until it is drawn, so a jump lands where it should; and a
   jump straight to a section draws its cards at once (.cv-now, set for a
   moment by web/board.mjs jumpTo), never empty boxes on screen. The sizes
   were measured on the anonymized board of 211 active visits (RENDIMIENTO.md). */
.stage-cards > .card, .future-minis > .card, .future-cubes > .card { content-visibility: auto; }
.stage-cards > .card { contain-intrinsic-size: auto 280px; }
.stage-cards > .card.full-card { contain-intrinsic-size: auto 420px; }
.stage-cards > .card.compact-card { contain-intrinsic-size: auto 58px; }
.future-minis > .card { contain-intrinsic-size: auto 42px; }
.future-cubes > .card { contain-intrinsic-size: auto 87px; }
.stage.cv-now .stage-cards > .card, .stage.cv-now .future-minis > .card, .stage.cv-now .future-cubes > .card { content-visibility: visible; }
.card.selected { box-shadow: 0 0 0 2px var(--accent); background: var(--surface); }
/* V28 tint: BUNKER or CHARTER calls in gold (text stays AA on it). */
.card.tint-gold { background: color-mix(in srgb, var(--gold) 10%, var(--surface-2)); border-color: color-mix(in srgb, var(--gold) 45%, var(--line)); }
.card.flash { animation: flash 1.2s var(--ease); }
@keyframes flash { 0% { box-shadow: 0 0 0 0 var(--accent); } 30% { box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent) 45%, transparent); } 100% { box-shadow: 0 0 0 0 transparent; } }
.card.dragging { opacity: .4; }
.grip {
  grid-row: span 2; display: grid; place-items: center; width: 28px; height: 40px; border: 0; border-radius: 8px;
  background: transparent; color: var(--muted); cursor: grab; touch-action: none;
}
.grip:hover { background: var(--surface-3); color: var(--text-strong); }
.grip:active { cursor: grabbing; }
.card-id { min-width: 0; }
.vessel { font: 700 14px/1.2 var(--font); color: var(--text-strong); display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.vessel .ico { color: var(--muted); }
.meta { font-size: 12px; color: var(--muted); display: flex; flex-wrap: wrap; gap: 4px 10px; margin-top: 2px; }
.status-chip { display: inline-flex; align-items: center; gap: 5px; font-size: 11px; font-weight: 700; padding: 2px 8px 2px 4px; border-radius: var(--pill); background: color-mix(in srgb, var(--st) 16%, var(--surface)); color: var(--text-strong); white-space: nowrap; }
.status-chip .glyph { display: inline-grid; place-items: center; width: 16px; height: 16px; border-radius: 50%; background: var(--st); color: #fff; font-size: 9.5px; }
.badge { display: inline-flex; align-items: center; gap: 4px; font-size: 11px; padding: 2px 7px; border-radius: 6px; background: var(--surface-3); color: var(--text); white-space: nowrap; }
.badge.pending { background: transparent; border: 1px dashed var(--line-ctrl); color: var(--muted); }
.badge.warn { background: var(--warn-soft); color: var(--warn); }
.badge.danger { background: var(--danger-soft); color: var(--danger); }
.badge.scope-owners { background: color-mix(in srgb, #b2367b 14%, var(--surface)); color: color-mix(in srgb, #b2367b 50%, var(--text-strong)); } /* AA in both themes (5.1:1 dark, 8.1:1 light) */
.badge.scope-charter { background: color-mix(in srgb, #6d4fc2 14%, var(--surface)); color: color-mix(in srgb, #6d4fc2 50%, var(--text-strong)); }
.badge.scope-full { background: color-mix(in srgb, #3b5c80 14%, var(--surface)); color: var(--text-strong); }
.card-time { text-align: right; font-size: 12px; color: var(--text); white-space: nowrap; }
.card-time strong { display: block; font-size: 13px; color: var(--text-strong); }
.card-next { grid-column: 2 / 4; font-size: 12.5px; color: var(--text); display: flex; gap: 8px; align-items: baseline; flex-wrap: wrap; }
.card-next .label { font-size: 10.5px; text-transform: uppercase; letter-spacing: .08em; color: var(--muted); }
.card-actions { grid-column: 2 / 4; display: flex; gap: 4px; flex-wrap: wrap; margin-top: 2px; }
.view-compact .card-next .extra, .view-compact .card-reqs { display: none; }
.card-reqs { grid-column: 2 / 4; margin: 2px 0 0; padding: 0; list-style: none; font-size: 12px; }
.card-reqs li { display: flex; gap: 6px; }
.card-reqs li.done { color: var(--muted); text-decoration: line-through; }
.move-select { padding: 4px 6px; border-radius: 8px; border: 1px solid var(--line-ctrl); background: var(--surface); font-size: 12.5px; max-width: 220px; }
.placeholder { border: 2px dashed var(--accent); border-radius: var(--r-m); min-height: 44px; background: color-mix(in srgb, var(--accent) 8%, transparent); }
.drag-ghost { position: fixed; z-index: 100; pointer-events: none; transform: rotate(1.5deg) scale(1.02); box-shadow: var(--sh-raised); width: min(420px, 80vw); }
/* The vessel name is a link to its dossier (keyboard, new tab). */
.card-name { font: 700 14px/1.25 var(--font); color: var(--text-strong); text-decoration: none; overflow-wrap: anywhere; border-radius: 4px; }
.card-name:hover { text-decoration: underline; }
/* Full card: the drawing over the main time. */
.card-time .ship-art { display: block; margin: 0 0 5px auto; }

/* ---------- compact card (redesign §4, stage B0) ----------
   Line 1: drawing, name, size, type, scope, managers. Line 2: the time and
   its distance, the status and the chips. The card opens the dossier; «⋯»
   unfolds the rest in place (never over other cards). Each part has its own
   place in the grid, so the card keeps its shape when the handle is hidden. */
.card.compact-card { grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: 2px 8px; padding: 6px 6px 6px 10px; cursor: pointer; }
.card.compact-card > .grip { grid-column: 1; grid-row: 1; height: 38px; }
.card.compact-card > .cc-body { grid-column: 2; grid-row: 1; }
.card.compact-card > .more-btn { grid-column: 3; grid-row: 1; }
/* The drawing is the thumbnail of both lines (72 × 40). */
.cc-body { min-width: 0; display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 4px 10px; align-items: center; }
.cc-body > .ship-art { grid-row: span 2; }
.cc-line1, .cc-line2 { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; min-width: 0; }
/* The groups of a line are only for the phone layout: elsewhere their
   pieces sit in the line one by one, as before. */
.cc-tags, .cc-chips { display: contents; }
.cc-when { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 2px 6px; min-width: 0; }
.cc-type { font-size: 12px; color: var(--muted); }
.status-chip.glyph-only { padding: 2px; }
.cc-time { font-size: 12.5px; color: var(--text-strong); white-space: nowrap; }
.cc-time b { font-size: 10.5px; letter-spacing: .06em; color: var(--muted); margin-right: 2px; }
.cc-kind { font-size: 11px; color: var(--muted); }
.cc-line2 .eta-signal { margin: 0; }
.more-btn { align-self: start; }
.card-more { grid-column: 2 / -1; display: grid; gap: 6px; margin-top: 4px; padding-top: 6px; border-top: 1px dashed var(--line); cursor: auto; }
/* Wide boards (the board itself, at least ~1000 px): compact cards in two
   columns, in reading order (left to right, then down), so an arrival list
   is about half as long. A card that opens «⋯» grows alone. */
.stage-inner { container-type: inline-size; }
@container (min-width: 1000px) {
  .view-compact .stage-cards { grid-template-columns: repeat(auto-fill, minmax(440px, 1fr)); align-items: start; }
  .view-compact .stage-cards > :not(.card) { grid-column: 1 / -1; } /* headings, tiles, rows, registers, notices */
  .view-compact .stage-cards > .card.compact-card { contain-intrinsic-size: auto 70px; }
}
/* The arrival row of 6 to 9 days (.arr-row): the compact card in one line
   (at most 52 px): order number, small drawing, status, name, size, scope,
   the ETA and its distance, the pre-arrival progress, the managers and «⋯».
   When the line is short it wraps in that order; nothing is hidden. */
.card.compact-card.arr-row { padding: 4px 6px 4px 10px; }
.card.compact-card.arr-row > .grip { height: 32px; }
.arr-row > .cc-body { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; }
.arr-row .cc-line1, .arr-row .cc-line2 { display: contents; }
.arr-row .cc-body > .ship-art { width: 56px; height: 31px; }
.arr-row .card-name { flex: 1 1 9em; min-width: 6em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.arr-row .cc-line1 > .status-chip { order: 1; }
.arr-row .cc-line1 > .card-name { order: 2; }
.arr-row .cc-tags > * { order: 3; }
.arr-row .cc-when { order: 4; }
.arr-row .cc-chips > * { order: 5; }
.arr-row .cc-line1 > .mgr-chips { order: 6; }
.card-more[hidden] { display: none; }
.card-more .card-next, .card-more .card-actions, .card-more .card-watch { grid-column: auto; }
/* Chips of line 2. Every one says it in words; colour only supports. */
/* The Canal class (web/visit-chips.mjs sizeChip), wherever a vessel shows:
   the class icon and its word, REGULAR, SUPER or NEO, in the class colour
   on its soft fill (AA in both themes, tools/design-tokens.mjs). To confirm
   with the ACP: dashed, on the surface, with «?». The word gives way with
   «…» before the chip leaves a narrow box; the tile's label keeps it whole. */
.badge.tier {
  gap: 3px; max-width: 100%; padding: 2px 7px 2px 5px; vertical-align: middle; font-weight: 700; letter-spacing: .04em;
  background: var(--tier-soft, var(--accent-soft)); color: var(--tier-ink, var(--accent-strong)); box-shadow: inset 0 0 0 1px color-mix(in srgb, currentColor 28%, transparent);
}
.badge.tier-regular { --tier-ink: var(--class-regular); --tier-soft: var(--class-regular-soft); }
.badge.tier-super { --tier-ink: var(--class-super); --tier-soft: var(--class-super-soft); }
.badge.tier-neo { --tier-ink: var(--class-neo); --tier-soft: var(--class-neo-soft); }
.badge.tier .tier-ico { width: 14px; height: 14px; color: inherit; }
.badge.tier .tier-word { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.badge.tier.pending { padding: 1px 6px 1px 4px; background: var(--tier-paper, var(--surface)); border: 1px dashed currentColor; box-shadow: none; }
.badge.tier.icon-only { gap: 1px; padding: 2px; }
.badge.tier.icon-only.pending { padding: 1px 3px 1px 1px; }
/* Papers that stay white in both themes (the print view, the map's popups
   and labels over the imagery, the report paper): the light colours of the
   classes, whatever the theme (the same values as :root). */
.print-doc, .leaflet-container, .rp-paper {
  --class-regular: #2d419a; --class-regular-soft: #e7e9f8;
  --class-super: #0a6a66; --class-super-soft: #dcf1ee;
  --class-neo: #a3420f; --class-neo-soft: #fbe8dc;
  --tier-paper: #ffffff;
}
.print-doc .badge.tier { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
.badge.validate { background: transparent; border: 1px dashed var(--warn); color: var(--warn); font-weight: 700; }
.badge.bunker { background: color-mix(in srgb, var(--gold) 22%, var(--surface)); color: var(--text-strong); }
.badge.bunker.active { box-shadow: inset 0 0 0 1px var(--gold); font-weight: 700; }
.badge.marker { font-weight: 700; }
/* On the narrowest cards the bar and the count go under the words instead
   of overflowing the card (stage B0). */
.pa-chip { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 2px 5px; max-width: 100%; font-size: 11px; font-weight: 700; padding: 2px 8px; border-radius: var(--pill); background: var(--surface-3); color: var(--text); white-space: nowrap; }
.pa-chip.mini { padding: 2px 6px; }
.pa-chip.alert { background: var(--danger-soft); color: var(--danger); }
.pa-chip.done { background: color-mix(in srgb, var(--ok) 14%, var(--surface)); color: var(--text-strong); }
/* The checklist by sections: done filled, received half, pending a trace. */
.pa-bar { display: inline-flex; gap: 2px; width: 46px; height: 6px; }
.pa-bar i { flex: 1; border-radius: 2px; background: color-mix(in srgb, currentColor 22%, transparent); }
.pa-bar i.pa-done { background: currentColor; }
.pa-bar i.pa-progress { background: color-mix(in srgb, currentColor 55%, transparent); }
.chip-btn { display: inline-flex; align-items: center; gap: 4px; padding: 2px 8px; border-radius: var(--pill); border: 1px solid var(--line-ctrl); background: var(--surface); color: var(--text-strong); font: 600 11px/1.4 var(--font); cursor: pointer; white-space: nowrap; }
.chip-btn:hover { border-color: var(--accent); }
.chip-btn.report-chip { border-color: var(--warn); background: var(--warn-soft); color: var(--warn); }
.chip-btn.steps-chip { border-color: var(--danger); background: var(--danger-soft); color: var(--danger); }

/* ---------- dossier head: the ship in its scene (§5) ---------- */
.dossier-hero { position: relative; display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px; margin: 0 0 12px; padding: 10px 12px 10px 16px; border-radius: var(--r-l); background: var(--surface-2); border: 1px solid var(--line); }
.dossier-hero::before { content: ""; position: absolute; inset: 8px auto 8px 0; width: 4px; border-radius: 0 4px 4px 0; background: linear-gradient(180deg, var(--mgr, var(--line-strong)) 0 50%, var(--mgr2, var(--mgr, var(--line-strong))) 50% 100%); }
.dossier-hero.no-mgr::before { background: repeating-linear-gradient(180deg, var(--muted) 0 5px, transparent 5px 9px); }
.dossier-hero .ship-art { flex: 0 1 280px; }
.hero-text { display: grid; grid-template-columns: minmax(0, 1fr); gap: 4px; min-width: 160px; flex: 1 1 160px; }
.hero-state { font: 800 15px/1.2 var(--font-display); color: var(--text-strong); }
.hero-type { font-size: 12.5px; color: var(--muted); }
.hero-badges { display: flex; flex-wrap: wrap; gap: 4px; }
.hero-badges:empty { display: none; }
/* Its stage and «Mover a…» (stage B0); the question opens under the head. */
/* min-width 0 (and the column above): once «Mover a…» gets its destinations,
   its longest one no longer widens the head past the dossier's 560 px. */
.hero-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; margin-top: 2px; min-width: 0; }
.hero-actions:empty { display: none; }
.hero-stage { font-size: 12px; font-weight: 700; color: var(--text-strong); }
.hero-stage .num { font-family: var(--mono); font-size: 11px; color: var(--muted); }
.hero-stage-label { font-size: 10.5px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.hero-actions .move-select { max-width: 100%; }
.hero-ask:empty { display: none; }
.hero-ask > .inline-ask { margin: -4px 0 12px; }

/* ---------- drawer (dossier / cameras) ---------- */
.drawer {
  position: fixed; inset: 0 0 0 auto; z-index: 60; width: min(560px, 100vw); background: var(--surface);
  box-shadow: var(--sh-raised); display: flex; flex-direction: column; transform: translateX(100%);
  transition: transform var(--d-slow) var(--ease-open); visibility: hidden;
}
.drawer.open { transform: none; visibility: visible; }
.drawer.wide { width: min(760px, 100vw); }
.drawer-head { display: flex; align-items: center; gap: 10px; padding: 14px 16px; border-bottom: 1px solid var(--line); }
.drawer-head h2 { margin: 0; font: 800 16px/1.2 var(--font-display); color: var(--text-strong); flex: 1; min-width: 0; }
.drawer-body { overflow-y: auto; padding: 14px 16px 40px; flex: 1; }
.scrim { position: fixed; inset: 0; z-index: 55; background: rgb(7 21 38 / .35); opacity: 0; pointer-events: none; transition: opacity var(--d-base) var(--ease); }
.scrim.open { opacity: 1; pointer-events: auto; }
.group { border: 1px solid var(--line); border-radius: var(--r-m); margin: 0 0 10px; }
/* Dossier tools: expand / collapse all and the field search. */
.dossier-tools { position: sticky; top: -14px; z-index: 6; display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin: -14px -16px 12px; padding: 10px 16px; background: var(--glass); backdrop-filter: blur(14px); border-bottom: 1px solid var(--line); }
.dossier-find { position: relative; flex: 1 1 220px; display: flex; align-items: center; }
.dossier-find > .ico { position: absolute; left: 9px; color: var(--muted); pointer-events: none; }
.dossier-find input { width: 100%; padding: 7px 10px 7px 32px; border: 1px solid var(--line-ctrl); border-radius: 10px; background: var(--surface); }
.dossier-results { position: absolute; z-index: 10; top: calc(100% + 4px); left: 0; right: 0; margin: 0; padding: 4px; list-style: none; border-radius: var(--r-m); background: var(--surface); box-shadow: var(--sh-raised); border: 1px solid var(--line); max-height: 300px; overflow-y: auto; }
.dossier-results li { display: flex; justify-content: space-between; gap: 10px; padding: 7px 9px; border-radius: 8px; cursor: pointer; font-size: 12.5px; }
.dossier-results li span { color: var(--muted); font-size: 11.5px; text-align: right; }
.dossier-results li[aria-selected="true"], .dossier-results li:hover { background: var(--accent-soft); }
.dossier-results li.none { cursor: default; color: var(--muted); }
.found { animation: found 1.6s var(--ease); border-radius: 8px; }
@keyframes found { 0%, 40% { box-shadow: 0 0 0 3px var(--accent); } 100% { box-shadow: 0 0 0 0 transparent; } }
.group > summary { cursor: pointer; padding: 9px 12px; font: 800 12px/1.2 var(--font-display); letter-spacing: .1em; color: var(--text-strong); list-style: none; display: flex; justify-content: space-between; }
.group > summary::-webkit-details-marker { display: none; }
.group[open] > summary { border-bottom: 1px solid var(--line); }
.group-body { padding: 10px 12px; display: grid; gap: 8px; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); }
.field { display: grid; gap: 3px; font-size: 12px; }
.field > span:not(.dt24, .ask-error) { color: var(--muted); font-size: 11px; text-transform: uppercase; letter-spacing: .06em; }
.field input, .field select, .field textarea { width: 100%; padding: 7px 9px; border: 1px solid var(--line-ctrl); border-radius: 8px; background: var(--surface-2); }
.field textarea { min-height: 64px; resize: vertical; }
.field.wide { grid-column: 1 / -1; }
.field .ro { padding: 7px 0; color: var(--text-strong); }
/* Tier UNSPECIFIED: the class beam and length give, with its hint in words
   (shown, never written into the field). */
.tier-derived { display: flex; flex-wrap: wrap; align-items: center; gap: 2px 6px; font-size: 12px; color: var(--muted); }
.note { font-size: 12px; color: var(--muted); background: var(--surface-2); border-radius: 8px; padding: 8px 10px; }
.note.warn { color: var(--warn); background: var(--warn-soft); }
.field > label { color: var(--muted); font-size: 11px; text-transform: uppercase; letter-spacing: .06em; }
.field [aria-invalid="true"], .sup-table [aria-invalid="true"] { border-color: var(--danger); box-shadow: 0 0 0 1px var(--danger); }
.btn.danger { background: var(--danger); border-color: var(--danger); color: var(--on-danger); }

/* Inline question (replaces prompt / confirm) */
.inline-ask {
  grid-column: 1 / -1; display: grid; gap: 8px; margin-top: 6px; padding: 10px 12px; border-radius: var(--r-m);
  border: 1px solid var(--accent); background: var(--surface); box-shadow: var(--sh-card); animation: rise var(--d-base) var(--ease);
}
.inline-ask.danger { border-color: var(--danger); }
.ask-title { font-weight: 700; font-size: 13px; color: var(--text-strong); }
.ask-actions { display: flex; gap: 6px; flex-wrap: wrap; }
.ask-error { color: var(--danger); font-size: 11.5px; }
.ask-error:empty { display: none; }
.sup-table tr.ask-slot > td { padding: 0 10px 10px; }
.sup-table tr.ask-slot:not(:has(form)) { display: none; }
td > [data-cancel-reason] { display: block; width: 100%; margin-top: 4px; padding: 5px 7px; border: 1px solid var(--line-ctrl); border-radius: 8px; background: var(--surface-2); }
td > [data-cancel-reason][hidden] { display: none; }

/* 24-hour Panama date-time field (replaces datetime-local) */
.dt24 { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 6px; }
.dt24 .dt24-date { flex: 1 1 128px; width: auto; min-width: 0; }
.dt24 .dt24-time { flex: none; width: 9ch; text-align: center; font-variant-numeric: tabular-nums; }
.dt24 input { padding: 6px 8px; border: 1px solid var(--line-ctrl); border-radius: 8px; background: var(--surface-2); }
.dt24 .dt24-now { min-height: 30px; }
.dt24-read { flex-basis: 100%; font-size: 11px; color: var(--muted); }
.dt24-read:empty { display: none; }
.dt24.invalid .dt24-read { color: var(--danger); font-weight: 600; }
.sup-table.times.editing thead { display: none; }
.sup-table.times.editing tr[data-code] { display: grid; grid-template-columns: 44px repeat(3, minmax(0, 1fr)); gap: 6px 8px; padding: 8px 10px; border-bottom: 1px solid var(--line); }
.sup-table.times.editing td { display: block; border: 0; padding: 0; min-width: 0; }
.sup-table.times.editing td:first-child { grid-row: span 2; font: 700 12px/30px var(--mono); color: var(--text-strong); }
.sup-table.times.editing td:nth-child(2) { grid-column: 2 / -1; }
.sup-table.times.editing td input, .sup-table.times.editing td select { width: 100%; padding: 5px 7px; border: 1px solid var(--line-ctrl); border-radius: 8px; background: var(--surface-2); }
.sup-table.times.editing td .dt24 input.dt24-date { width: auto; }
.sup-table.times.editing td .dt24 input.dt24-time { width: 9ch; }
@media (max-width: 480px) {
  .sup-table.times.editing tr[data-code] { grid-template-columns: 40px minmax(0, 1fr); }
  .sup-table.times.editing td:first-child { grid-row: span 4; }
  .sup-table.times.editing td:nth-child(n+3) { grid-column: 2; }
}
/* Positioned, like the composer's scrolling parts: a header read only by a
   screen reader (.sr-only, absolute) stays inside the box instead of
   stretching a phone's page (Ajustes · Managers measured 571 px at 375; the
   sort buttons of «Lista del Canal», 1617 px at 1280). */
.table-scroll { position: relative; overflow-x: auto; max-width: 100%; border-radius: var(--r-l); }
.group-body > .field { min-width: 0; } /* lets a wide table scroll inside its field */
.history-list { list-style: none; margin: 0; padding: 0; font-size: 12px; display: grid; gap: 6px; }
.history-list li { padding: 6px 8px; border-radius: 8px; background: var(--surface-2); }
.history-list code { font-family: var(--mono); font-size: 11.5px; }

/* ---------- cameras ---------- */
.cam-grid { display: grid; gap: 10px; }
.cam {
  display: grid; grid-template-columns: 1fr auto; gap: 6px 10px; padding: 12px; border-radius: var(--r-m);
  border: 1px solid var(--line); background: var(--surface-2); transition: border-color var(--d-fast) var(--ease);
}
.cam.recommended { border-color: var(--accent); box-shadow: inset 3px 0 0 var(--accent); }
.cam h3 { margin: 0; font: 800 14px/1.2 var(--font-display); color: var(--text-strong); }
.cam .sector { font-size: 12px; color: var(--muted); grid-column: 1 / -1; }
.cam .cam-status { font-size: 11.5px; }
.cam .cam-actions { grid-column: 1 / -1; display: flex; gap: 6px; flex-wrap: wrap; }
.obs-form { display: grid; gap: 8px; margin-top: 12px; padding: 12px; border-radius: var(--r-m); border: 1px dashed var(--line-ctrl); }

/* ---------- map ---------- */
.map-root { position: absolute; inset: 0; }
.map-fallback { position: absolute; inset: 0; display: grid; place-items: center; text-align: center; padding: 20px; color: var(--muted); background: var(--surface-3); }
.map-legend {
  position: absolute; z-index: 500; left: 10px; bottom: 26px; max-width: 260px; padding: 8px 10px; border-radius: var(--r-m);
  background: var(--glass); backdrop-filter: blur(14px); font-size: 11.5px; box-shadow: var(--sh-card); color: var(--text);
}
.map-legend ul { list-style: none; margin: 4px 0 0; padding: 0; display: grid; grid-template-columns: 1fr 1fr; gap: 3px 10px; }
.map-legend .sw { display: inline-grid; place-items: center; width: 14px; height: 14px; border-radius: 50%; color: #fff; font-size: 8.5px; margin-right: 4px; vertical-align: -2px; background: var(--c, #95a7b3); }
/* Former inline styles (the CSP has no 'unsafe-inline'; web/data-vars.mjs). */
.map-legend.low { bottom: 8px; }
.map-legend .legend-note { margin: 4px 0 0; }
.group-body.flush { padding: 0; }
input.num-input { width: 90px; }
.toast-text { flex: 1; }
.map-tools { position: absolute; z-index: 500; top: 10px; right: 10px; display: flex; flex-direction: column; gap: 6px; }
.place-label { font: 700 11px/1.15 var(--font); color: #fff; text-shadow: 0 1px 3px rgb(0 0 0 / .8); white-space: nowrap; }
.area-chip { display: inline-flex; align-items: center; gap: 4px; padding: 3px 8px; border-radius: var(--pill); background: rgb(7 21 38 / .78); color: #fff; font: 700 11px/1 var(--font); border: 1px solid rgb(255 255 255 / .35); white-space: nowrap; cursor: pointer; }
.area-chip .n { background: var(--gold); color: #1e3551; border-radius: var(--pill); padding: 2px 6px; }
.ship-marker { display: grid; place-items: center; }
.ship-marker .hull { width: 18px; height: 18px; border-radius: 50%; border: 2px solid #fff; background: var(--st); box-shadow: 0 1px 4px rgb(0 0 0 / .5); display: grid; place-items: center; color: #fff; font-size: 9px; font-weight: 800; }
.ship-marker.stale .hull { border-style: dashed; opacity: .75; }
.ship-marker.moving .hull::after { content: ""; position: absolute; width: 0; height: 0; border-left: 5px solid transparent; border-right: 5px solid transparent; border-bottom: 9px solid #fff; transform: translateY(-15px) rotate(var(--hdg, 0deg)); transform-origin: 50% 24px; }
.ship-label { font: 700 11px/1 var(--font); color: #fff; text-shadow: 0 1px 3px rgb(0 0 0 / .9); white-space: nowrap; margin-top: 2px; }
/* The class as its icon before the name (its word as tooltip and for screen readers). */
.ship-label .badge.tier { margin-right: 3px; padding: 1px; text-shadow: none; }
.ship-label .badge.tier .tier-ico { width: 12px; height: 12px; }
/* isolation: Leaflet's panes use z-index 400–1000; without their own stacking
   context they painted over the dossier drawer (z-index 60). */
.leaflet-container { font: inherit; background: var(--surface-3); isolation: isolate; }
.leaflet-control-attribution { max-width: none !important; white-space: normal !important; font-size: 10px; }
.map-popup h4 { margin: 0 0 4px; font: 800 13px/1.2 var(--font-display); }
.map-popup p { margin: 2px 0; font-size: 12px; }
.map-popup .src { font-size: 11px; color: #5b6d80; }

/* ---------- supervision ---------- */
.kpis { display: grid; grid-template-columns: repeat(auto-fill, minmax(170px, 1fr)); gap: 10px; margin-bottom: 16px; }
.kpi { background: var(--surface); border-radius: var(--r-l); box-shadow: var(--sh-card); padding: 12px 14px; }
.kpi b { display: block; font: 800 26px/1.1 var(--font-display); color: var(--text-strong); }
.kpi span { font-size: 12px; color: var(--muted); }
.sup-table { width: 100%; border-collapse: collapse; background: var(--surface); border-radius: var(--r-l); overflow: hidden; box-shadow: var(--sh-card); font-size: 12.5px; }
.sup-table th, .sup-table td { text-align: left; padding: 8px 10px; border-bottom: 1px solid var(--line); vertical-align: top; }
.sup-table th { font-size: 11px; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); background: var(--surface-2); }

/* ---------- presence and team ---------- */
.presence-btn { border: 0; background: none; padding: 0; cursor: pointer; }
.presence-chip { display: inline-flex; align-items: center; gap: 6px; padding: 4px 10px; border-radius: var(--pill); font-size: 12px; font-weight: 600; background: var(--surface-3); color: var(--text-strong); white-space: nowrap; }
.presence-chip .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--muted); }
.presence-chip.tone-ok .dot { background: var(--ok); }
.presence-chip.tone-info .dot { background: var(--info); }
.presence-chip.tone-warn .dot { background: var(--warn); }
.team-section { margin: 0 0 26px; }
.team-section .block-head { flex-wrap: wrap; }
.presence-form, .handover-form { display: grid; gap: 8px 12px; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); align-items: end; background: var(--surface); padding: 12px; border-radius: var(--r-l); box-shadow: var(--sh-card); margin-bottom: 10px; }
.presence-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.presence-list li { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 12px; padding: 8px 12px; border-radius: var(--r-m); background: var(--surface); box-shadow: var(--sh-card); font-size: 13px; }
.presence-list li.me { box-shadow: 0 0 0 2px var(--accent), var(--sh-card); }
.presence-list .who { font-weight: 700; color: var(--text-strong); }
.presence-list .assign { color: var(--text); }
.cover-badge { display: inline-flex; align-items: center; gap: 5px; font-size: 11.5px; font-weight: 600; padding: 2px 8px; border-radius: var(--pill); background: color-mix(in srgb, var(--c) 18%, var(--surface)); color: var(--text-strong); border: 1px solid color-mix(in srgb, var(--c) 55%, transparent); white-space: nowrap; }
.cover-badge > span { color: var(--c); font-weight: 800; }
.sup-table tr.cover-group > th { background: var(--surface-3); color: var(--text-strong); font-size: 11px; letter-spacing: .1em; }
.week-nav { display: inline-flex; align-items: center; gap: 6px; margin-left: auto; font-size: 12.5px; }
.week-table th.today, .week-table td.today { background: color-mix(in srgb, var(--accent) 9%, var(--surface)); }
.week-table td { padding: 4px; min-width: 104px; }
.shift-cell { display: grid; gap: 2px; justify-items: start; width: 100%; min-height: 48px; padding: 6px; border: 1px dashed transparent; border-radius: 8px; background: transparent; text-align: left; cursor: pointer; font-size: 12px; }
.shift-cell:not([disabled]):hover { border-color: var(--accent); background: var(--surface-2); }
.shift-cell[disabled] { cursor: default; }
.shift-cell b { font-size: 12px; color: var(--text-strong); }
/* Wide tables scroll sideways: names stay visible and forms stay in view. */
.week-table th[scope="row"], .week-table thead th:first-child { position: sticky; left: 0; z-index: 1; background: var(--surface); min-width: 120px; }
.sup-table .ask-slot > td > .inline-ask { position: sticky; left: 0; max-width: min(640px, calc(100vw - 64px)); }

/* ---------- watch actions, next steps, closeout ---------- */
.card-watch { grid-column: 2 / 4; display: flex; flex-wrap: wrap; gap: 4px; }
.watch-pill { display: inline-flex; align-items: center; gap: 5px; max-width: 100%; padding: 3px 9px; border-radius: var(--pill); border: 1px solid var(--line-ctrl); background: var(--surface); color: var(--text-strong); font-size: 11.5px; cursor: pointer; text-align: left; }
.watch-pill span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.watch-pill b { font-size: 10.5px; text-transform: uppercase; letter-spacing: .06em; }
.watch-pill.st-overdue { border-color: var(--danger); background: var(--danger-soft); color: var(--danger); }
.watch-pill.st-due { border-color: var(--warn); background: var(--warn-soft); color: var(--warn); }
.watch-pill.st-verify { border-style: dashed; }
.steps { list-style: none; margin: 0 0 8px; padding: 0; display: grid; gap: 6px; }
.steps .step { display: grid; grid-template-columns: 1fr auto auto; gap: 4px 10px; align-items: center; padding: 8px 10px; border-radius: var(--r-m); background: var(--surface-2); border-left: 3px solid var(--line-ctrl); }
.steps .step.st-overdue { border-left-color: var(--danger); }
.steps .step.st-due { border-left-color: var(--warn); }
.steps .step.flash { animation: flash 1.2s var(--ease); }
.step-when { font-size: 12px; white-space: nowrap; }
.step-to { color: var(--muted); font-size: 11.5px; }
.gates { list-style: none; margin: 4px 0 10px; padding: 0; display: grid; gap: 3px; font-size: 12.5px; }
.gates li.ok { color: var(--ok); }
.gates li.no { color: var(--danger); font-weight: 600; }
/* Cash to master and collections (dossier) and the printed receipt. */
.cash-box { display: grid; gap: 10px; }
.cash-item { border: 1px solid var(--line); border-radius: var(--r-m, 10px); padding: 8px 10px; display: grid; gap: 6px; background: var(--surface-2); }
.cash-item.open { border-left: 3px solid var(--warn); }
.cash-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px; }
.cash-actions { display: flex; flex-wrap: wrap; gap: 6px; }
.cash-steps { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 4px; font-size: 11.5px; }
.cash-steps li { padding: 2px 8px; border-radius: var(--pill, 999px); border: 1px solid var(--line-ctrl); color: var(--muted); }
.cash-steps li.done { color: var(--ok); border-color: color-mix(in srgb, var(--ok) 50%, transparent); }
.cash-steps li.now { color: var(--text-strong); border-color: var(--accent); background: color-mix(in srgb, var(--accent) 16%, transparent); font-weight: 700; }
.receipt-copy { position: relative; border: 1px solid #b3c1cc; border-radius: 8px; padding: 14px 18px; margin: 0 0 18px; overflow: hidden; break-inside: avoid; }
.receipt-copy + .receipt-copy { border-top-style: dashed; }
.receipt-mark { position: absolute; inset: 0; display: grid; place-items: center; font: 900 88px/1 var(--font-display); letter-spacing: .2em; color: rgba(165, 42, 42, .08); transform: rotate(-18deg); pointer-events: none; }
.receipt-top { display: flex; justify-content: space-between; align-items: baseline; }
.receipt-date { margin: 0 0 8px; color: #5b6d80; }
.receipt-signs { display: grid; grid-template-columns: 1fr 1fr; gap: 28px; margin-top: 34px; font-size: 11.5px; }
.receipt-line { border-top: 1px solid #16283a; margin-bottom: 4px; }
.cash-totals tr.today > * { background: color-mix(in srgb, var(--accent) 10%, var(--surface)); }
.cash-totals tr.total > * { border-top: 2px solid var(--line-strong); font-weight: 700; }
.sup-table .late { color: var(--danger); font-weight: 600; }

/* Access administration and register / archive. */
.access-tools { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px; margin: 0 0 10px; }
.check { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; color: var(--text); }
/* A checkbox alone in a table cell (its name in aria-label): the label around
   it is its target, 44 × 44 px on touch screens. */
.check-cell { display: inline-flex; align-items: center; justify-content: center; cursor: pointer; }
.access-table td.actions { white-space: normal; }
.access-table td.actions .btn { margin: 0 2px 4px 0; }
.access-table tr.muted-row > td { opacity: .72; }
.role-matrix th[scope="col"] { font-size: 10.5px; letter-spacing: .04em; text-transform: none; white-space: nowrap; }
.role-matrix td { text-align: center; position: relative; } /* keeps the screen-reader text inside the scrolled table */
.role-matrix td.yes { color: var(--ok); }
.role-matrix td.no { color: var(--muted); }
.rule-list { margin: 0; padding: 12px 14px 12px 32px; background: var(--surface); border-radius: var(--r-l); box-shadow: var(--sh-card); display: grid; gap: 6px; font-size: 13px; }
.archive-search { display: grid; gap: 8px 12px; grid-template-columns: minmax(200px, 2fr) repeat(auto-fill, minmax(130px, 1fr)); align-items: end; background: var(--surface); padding: 12px; border-radius: var(--r-l); box-shadow: var(--sh-card); margin-bottom: 10px; }
.pager { display: flex; align-items: center; justify-content: center; gap: 10px; margin: 10px 0; }
.sup-table tr.ask-slot:has(.history-list, .archive-file, .invite-box) { display: table-row; }
.archive-file { display: grid; gap: 8px; padding: 10px 0 4px; }
.file-grid { display: grid; grid-template-columns: max-content 1fr; gap: 4px 14px; margin: 0; font-size: 12.5px; }
.file-grid dt { color: var(--muted); font-size: 11px; text-transform: uppercase; letter-spacing: .06em; padding-top: 2px; }
.file-grid dd { margin: 0; color: var(--text-strong); }

@media (max-width: 600px) {
  .steps .step { grid-template-columns: 1fr; }
  /* Account and register rows become cards with their labels. */
  .access-table thead, .archive-table thead { display: none; }
  .access-table tr[data-account], .archive-table tr[data-reg] { display: grid; grid-template-columns: 1fr 1fr; gap: 6px 10px; padding: 10px; border-bottom: 1px solid var(--line); }
  .access-table tr[data-account] > td, .archive-table tr[data-reg] > td { display: block; border: 0; padding: 0; min-width: 0; }
  .access-table tr[data-account] > td:first-child, .access-table tr[data-account] > td:last-child, .archive-table tr[data-reg] > td:first-child, .archive-table tr[data-reg] > td:last-child { grid-column: 1 / -1; }
  .access-table td[data-label]::before, .archive-table td[data-label]::before { content: attr(data-label); display: block; font-size: 10.5px; text-transform: uppercase; letter-spacing: .06em; color: var(--muted); }
  .access-table tr.ask-slot:has(form, .history-list, .invite-box) > td, .archive-table tr.file-slot:has(.archive-file, form) > td { display: block; }
  .archive-search { grid-template-columns: 1fr 1fr; }
  .archive-search .field.grow { grid-column: 1 / -1; }
  /* Coverage rows become cards with their labels. */
  .cover-table thead { display: none; }
  .cover-table tr[data-row] { display: grid; grid-template-columns: 1fr 1fr; gap: 6px 10px; padding: 10px; border-bottom: 1px solid var(--line); }
  .cover-table tr[data-row] > td { display: block; border: 0; padding: 0; min-width: 0; }
  .cover-table tr[data-row] > td:first-child, .cover-table tr[data-row] > td:last-child { grid-column: 1 / -1; }
  .cover-table td[data-label]::before { content: attr(data-label); display: block; font-size: 10.5px; text-transform: uppercase; letter-spacing: .06em; color: var(--muted); }
  .cover-table tr.cover-group > th { display: block; }
  .cover-table tr.ask-slot:has(form) > td { display: block; }
}

/* ---------- printable documents ---------- */
#print-view { position: fixed; inset: 0; z-index: 90; display: flex; flex-direction: column; background: rgb(7 21 38 / .55); }
.print-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 10px 14px; background: var(--surface); border-bottom: 1px solid var(--line); }
.print-toolbar .spacer { flex: 1; }
.print-doc { flex: 1; overflow: auto; margin: 0 auto; width: min(1100px, 100%); padding: 24px 28px 60px; background: #fff; color: #16283a; font: 12.5px/1.45 var(--font); }
.print-doc h1 { font: 800 19px/1.2 var(--font-display); margin: 4px 0; }
.print-doc h2 { font: 800 13px/1.2 var(--font-display); letter-spacing: .06em; margin: 16px 0 6px; padding-bottom: 3px; border-bottom: 1px solid #b3c1cc; }
.print-doc h3 { font: 700 13.5px/1.3 var(--font); margin: 0 0 2px; }
.print-doc h3 > span:not(.badge) { font-weight: 400; color: #5b6d80; margin-left: 8px; }
.print-doc ul { margin: 4px 0 0; padding-left: 18px; }
.print-doc .muted, .print-doc .doc-meta { color: #5b6d80; }
.print-doc .alert, .print-doc .late { color: #a52a2a; }
.doc-brand { font: 800 11px/1 var(--font-display); letter-spacing: .14em; color: #1e3551; }
.doc-env { display: inline-block; font-size: 11px; color: #8a5a00; background: #fdf2e0; border-radius: 999px; padding: 2px 10px; }
.doc-box { border: 1px solid #b3c1cc; border-radius: 8px; padding: 8px 10px; margin: 10px 0; }
.doc-cover { border-collapse: collapse; margin: 6px 0 10px; width: 100%; }
.doc-cover th { text-align: left; width: 150px; padding: 3px 8px 3px 0; font-size: 11px; letter-spacing: .06em; }
.doc-cover td { padding: 3px 0; }
.doc-stage { background: #e9eef3; padding: 4px 8px; border: 0 !important; border-radius: 6px; }
.doc-vessel { padding: 8px 10px; margin: 6px 0; border-radius: 8px; border-left: 4px solid #246fb5; background: #f3f7fc; break-inside: avoid; }
.doc-vessel.pac { border-left-color: #c2602e; background: #fdf6ef; }
.doc-vessel.owners { border-left-color: #b2367b; background: #fbf1f6; }
.doc-table { width: 100%; border-collapse: collapse; font-size: 12px; }
.doc-table th, .doc-table td { border: 1px solid #d9e1e8; padding: 4px 6px; text-align: left; vertical-align: top; }
.doc-table th { background: #f6f8fa; font-size: 10.5px; letter-spacing: .06em; text-transform: uppercase; }
.doc-gates { list-style: none; padding: 0; }
.doc-gates li.ok { color: #1e8a5f; }
.doc-foot { margin-top: 18px; padding-top: 8px; border-top: 1px solid #b3c1cc; font-size: 11px; color: #5b6d80; }
@media print {
  @page { size: A4 landscape; margin: 10mm; }
  body.printing-view > :not(#print-view) { display: none !important; }
  body.printing-view { background: #fff; }
  #print-view { position: static; background: none; display: block; }
  .print-toolbar { display: none; }
  .print-doc { width: auto; padding: 0; overflow: visible; }
}

/* ---------- sign-in and invitation (web/auth.mjs) ---------- */
.auth-screen { position: fixed; inset: 0; z-index: 210; display: grid; place-items: center; padding: 20px; overflow-y: auto; background: #fff; color: #16283a; }
.auth-box { width: min(440px, 100%); display: grid; justify-items: center; gap: 10px; text-align: center; }
.auth-logo { width: min(200px, 54vw); height: auto; }
.auth-logo.tenant-logo { max-height: 200px; object-fit: contain; }
.auth-product { margin: 0; font: 700 11.5px/1.3 var(--font-display); letter-spacing: .16em; text-transform: uppercase; color: var(--brand-on-white, #1e3551); }
.auth-box h1 { margin: 6px 0 0; font: 800 22px/1.2 var(--font-display); color: var(--brand-on-white, #1e3551); }
.auth-sub { margin: 0; color: #5b6d80; }
.auth-box .btn.auth-go { min-height: 48px; padding: 10px 22px; font-size: 15px; font-weight: 700; background: var(--brand-on-white, #1e3551); border-color: var(--brand-on-white, #1e3551); color: #fff; }
.auth-box .btn.auth-go .ico { color: var(--brand-accent-on-white, #d4a35f); }
.auth-box .btn:not(.auth-go) { background: #fff; color: var(--brand-on-white, #1e3551); border-color: #7f8f9f; }
.auth-error { margin: 0; min-height: 1em; color: #bc3939; font-weight: 600; }
.auth-error:empty { display: none; }
.auth-help { margin: 4px 0 0; font-size: 12.5px; color: #5b6d80; }
.auth-steps { text-align: left; margin: 4px 0; padding-left: 22px; display: grid; gap: 4px; font-size: 13.5px; }
.auth-device { width: 100%; text-align: left; }
.auth-device input { width: 100%; padding: 9px 11px; border: 1px solid #7f8f9f; border-radius: 10px; background: #f6f8fa; color: #16283a; }
.auth-device > span { color: #5b6d80; }
/* Whose account an invitation's passkey goes on, and why the sign-in asks
   again (incident of 28 Oct 2026). Fixed colours: the sign-in is always
   light; #16283a on #fdf2e0 is 13.5:1, the #9b6010 edge 5.2:1 on white. */
.auth-whom, .auth-notice { width: 100%; display: flex; align-items: flex-start; gap: 10px; margin: 2px 0; padding: 10px 12px; text-align: left; border-radius: 10px; border: 1px solid #9b6010; border-left-width: 5px; background: #fdf2e0; color: #16283a; font-size: 14px; }
.auth-whom .ico, .auth-notice .ico { flex: none; margin-top: 1px; color: #9b6010; }
.auth-whom p { margin: 0; }
.auth-whom p + p { margin-top: 4px; }
.auth-whom-for { font-weight: 700; }
.role-actions { display: flex; flex-wrap: wrap; gap: 6px; }
.invite-box { display: grid; gap: 8px; padding: 10px 12px; border-radius: var(--r-m); border: 1px solid var(--gold); background: color-mix(in srgb, var(--gold) 10%, var(--surface)); }
.invite-actions { display: flex; flex-wrap: wrap; gap: 6px; }
.invite-link { width: 100%; padding: 7px 9px; border: 1px solid var(--line-ctrl); border-radius: 8px; background: var(--surface); font: 12px/1.3 var(--mono); }
/* The owner's link for one of his own devices: a red edge and a red warning
   (--danger on --danger-soft: 4.6:1 light, 6.6:1 dark), and the one-line note
   under his own row's button (--warn on --surface: 5.2:1 light, 5.8:1 dark). */
.invite-box.own-device { border-color: var(--danger); border-width: 2px; }
.invite-warning { display: flex; align-items: flex-start; gap: 8px; margin: 0; padding: 8px 10px; border-radius: 8px; border: 1px solid var(--danger); background: var(--danger-soft); color: var(--danger); font-size: 13px; font-weight: 700; }
.invite-warning .ico, .own-device-note .ico { flex: none; margin-top: 1px; }
.own-device-note { display: flex; align-items: flex-start; gap: 6px; margin: 2px 0 0; font-size: 12px; font-weight: 600; color: var(--warn); }
.device-list { list-style: none; margin: 4px 0 0; padding: 0; display: grid; gap: 3px; font-size: 12px; }
.device-list li { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; }

/* ---------- popovers (install, role) and offline page ---------- */
.pop {
  position: fixed; z-index: 75; top: 64px; right: 12px; width: min(440px, calc(100vw - 24px)); max-height: calc(100vh - 90px); overflow-y: auto;
  padding: 14px 16px; border-radius: var(--r-l); background: var(--surface); color: var(--text); box-shadow: var(--sh-raised); border: 1px solid var(--line);
  animation: rise var(--d-base) var(--ease);
}
.pop-head { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.pop-head h2 { flex: 1; margin: 0; display: flex; align-items: center; gap: 8px; font: 800 15px/1.25 var(--font-display); color: var(--text-strong); }
.pop h3 { margin: 10px 0 4px; font: 800 12.5px/1.3 var(--font-display); letter-spacing: .04em; color: var(--text-strong); }
.pop ol, .pop ul { margin: 0; padding-left: 20px; display: grid; gap: 4px; font-size: 13px; }
.install-steps { padding: 2px 10px 8px; border-radius: var(--r-m); }
.install-steps.here { background: var(--accent-soft); }
.note.ok-note { color: var(--ok); }
/* Role badge (header) and what the role can and cannot do. */
.role-badge { display: inline-flex; align-items: center; gap: 6px; padding: 4px 10px; border-radius: var(--pill); border: 1px solid var(--line-ctrl); background: var(--surface); color: var(--text-strong); font-size: 12px; font-weight: 700; cursor: pointer; white-space: nowrap; }
.role-badge[hidden] { display: none; }
.role-badge.owner { border-color: var(--gold); box-shadow: inset 0 0 0 1px var(--gold); }
.role-badge.owner .ico { color: var(--gold); }
.role-line { margin: 0 0 6px; }
.role-name { font: 800 13px/1.2 var(--font-display); color: var(--text-strong); }
.role-list { list-style: none; padding: 0 !important; }
.role-list li { display: flex; gap: 8px; align-items: flex-start; }
.role-list li.yes .ico, .role-list li.only .ico { color: var(--ok); flex: none; margin-top: 2px; }
.role-list li.no { color: var(--muted); }
.role-list li.no .ico { color: var(--muted); flex: none; margin-top: 2px; }
.role-list li.only { font-weight: 700; color: var(--text-strong); }
.only-title { display: flex; align-items: center; gap: 6px; }
.only-title .ico { color: var(--gold); }
/* The owner's panel ("only you"). */
.only-you { display: inline-flex; align-items: center; padding: 2px 10px; border-radius: var(--pill); border: 1px solid var(--gold); color: var(--text-strong); background: color-mix(in srgb, var(--gold) 16%, var(--surface)); font-size: 11.5px; font-weight: 800; letter-spacing: .04em; }
.owner-panel { padding: 12px 14px; border-radius: var(--r-l); background: var(--surface); box-shadow: var(--sh-card), inset 3px 0 0 var(--gold); }
.owner-panel .block-head h2 { display: inline-flex; align-items: center; gap: 6px; }
.only-list { list-style: none; margin: 8px 0 12px; padding: 0; display: grid; gap: 4px; font-size: 13px; }
.only-list li { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.only-list li > .ico { color: var(--ok); }
.sub-title { margin: 6px 0 2px; font: 800 12.5px/1.3 var(--font-display); letter-spacing: .06em; color: var(--text-strong); }
.mgr-table input[type="text"] { width: 140px; padding: 5px 7px; border: 1px solid var(--line-ctrl); border-radius: 8px; background: var(--surface-2); }
.mgr-table input[type="color"] { width: 42px; height: 30px; padding: 2px; border: 1px solid var(--line-ctrl); border-radius: 8px; background: var(--surface-2); vertical-align: middle; }
.mgr-table tr.new td { background: var(--surface-2); }
.offline-page { display: grid; place-items: center; min-height: 100vh; background: #fff; color: #16283a; }
.offline-box { max-width: 420px; padding: 24px; text-align: center; display: grid; justify-items: center; gap: 6px; }
.offline-box h1 { margin: 8px 0 0; font: 800 20px/1.2 var(--font-display); color: #1e3551; }
.offline-box a.btn { text-decoration: none; background: #1e3551; border-color: #1e3551; color: #fff; }
@media (max-width: 900px) { .pop { top: auto; bottom: 12px; right: 8px; left: 8px; width: auto; max-height: 72vh; } }
@media (max-width: 720px) { .pop { bottom: calc(var(--rail-bar-h) + env(safe-area-inset-bottom) + 8px); } }

/* ---------- toast ---------- */
.toasts { position: fixed; z-index: 80; bottom: 16px; left: 50%; transform: translateX(-50%); display: grid; gap: 8px; width: min(480px, calc(100vw - 32px)); }
.toast { display: flex; align-items: center; gap: 10px; padding: 10px 12px; border-radius: var(--r-m); background: var(--ink); color: #fff; box-shadow: var(--sh-raised); font-size: 13px; animation: rise var(--d-slow) var(--ease); }
.toast.error { background: #7a1f24; }
.toast .btn { background: transparent; color: #fff; border-color: rgb(255 255 255 / .4); }
@keyframes rise { from { transform: translateY(12px); opacity: 0; } to { transform: none; opacity: 1; } }

/* ---------- phone bar and «Más» (web/nav.mjs) ---------- */
.tabbar { display: none; }
.tab {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px; min-width: 0; min-height: 52px;
  padding: 4px 2px; border: 0; border-radius: 12px; background: transparent; color: inherit;
  font: 600 11px/1.15 var(--font); text-decoration: none; cursor: pointer; -webkit-tap-highlight-color: transparent;
}
.tab-ico { position: relative; display: grid; place-items: center; width: 48px; height: 28px; border-radius: var(--pill); transition: background var(--d-fast) var(--ease); }
/* Short labels that always fit (shared/nav.mjs MOBILE_LABEL_MAX): never cut. */
.tab-label { white-space: nowrap; }
.tab[aria-current="page"], .tab[aria-expanded="true"], .tab.here { color: #fff; }
.tab[aria-current="page"] .tab-ico, .tab[aria-expanded="true"] .tab-ico, .tab.here .tab-ico { background: color-mix(in srgb, var(--gold) 24%, transparent); color: var(--gold); }
.tab:focus-visible { outline-offset: -2px; }
.tab-dot { position: absolute; top: 1px; right: 9px; width: 9px; height: 9px; border-radius: 50%; background: var(--gold); box-shadow: 0 0 0 2px var(--ink); }
.tab-dot[hidden] { display: none; }
/* «Más»: a modal sheet from the bottom (the page behind is inert). */
.sheet { position: fixed; inset: auto 0 0; width: 100%; max-width: 100%; max-height: min(88vh, 760px); margin: 0; padding: 0; border: 0; border-radius: 20px 20px 0 0; background: var(--surface); color: var(--text); box-shadow: var(--sh-raised); overflow: hidden; }
.sheet[open] { display: flex; flex-direction: column; animation: sheet-up var(--d-slow) var(--ease-open); }
.sheet::backdrop { background: rgb(7 21 38 / .5); }
@keyframes sheet-up { from { transform: translateY(100%); } to { transform: none; } }
.sheet-grip { flex: none; width: 40px; height: 4px; margin: 8px auto 0; border-radius: 2px; background: var(--line-strong); }
/* The × lines up with the items under it: the same 12 px from the edge as
   .sheet-body (final QA of 28 Oct: it sat 4 px further right). */
.sheet-head { flex: none; display: flex; align-items: center; gap: 8px; padding: 4px 12px 4px 18px; }
.sheet-head h2 { flex: 1; margin: 0; font: 800 17px/1.2 var(--font-display); color: var(--text-strong); }
.sheet-close { min-width: 44px; min-height: 44px; }
.sheet-body { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding: 0 12px calc(16px + env(safe-area-inset-bottom)); }
.sheet-group h3 { margin: 14px 6px 6px; font: 700 11px/1.2 var(--font); letter-spacing: .12em; text-transform: uppercase; color: var(--muted); }
.sheet-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.sheet-item, .sheet-me {
  display: flex; align-items: center; gap: 12px; width: 100%; min-height: 56px; padding: 8px 12px 8px 8px;
  border: 1px solid var(--line); border-radius: 14px; background: var(--surface-2); color: var(--text-strong);
  font: inherit; text-align: left; text-decoration: none; cursor: pointer;
}
.sheet-item:hover, .sheet-me:hover { border-color: var(--accent); }
.sheet-item[aria-current="page"] { border-color: var(--accent); box-shadow: inset 3px 0 0 var(--accent); }
.sheet-ico { flex: none; display: grid; place-items: center; width: 38px; height: 38px; border-radius: 11px; background: var(--accent-soft); color: var(--accent); }
.sheet-item[aria-pressed="true"] .sheet-ico { background: var(--accent); color: var(--on-accent); }
.sheet-text { display: grid; flex: 1; min-width: 0; }
.sheet-label { font-size: 14.5px; font-weight: 700; line-height: 1.25; }
.sheet-desc { font-size: 12.5px; line-height: 1.3; color: var(--muted); }
.sheet-count { flex: none; min-width: 24px; padding: 2px 7px; border-radius: var(--pill); background: var(--warn-soft); color: var(--warn); font: 800 12px/1.3 var(--font); text-align: center; }
.sheet-count[hidden] { display: none; }
/* On/off of a preference: the shape says it too (the knob moves), not only the colour. */
.switch { flex: none; position: relative; width: 40px; height: 24px; border-radius: var(--pill); background: var(--surface-3); box-shadow: inset 0 0 0 1px var(--line-ctrl); transition: background var(--d-fast) var(--ease); }
.switch::after { content: ""; position: absolute; top: 3px; left: 3px; width: 18px; height: 18px; border-radius: 50%; background: var(--muted); transition: transform var(--d-fast) var(--ease), background var(--d-fast) var(--ease); }
[aria-pressed="true"] > .switch { background: var(--accent); box-shadow: none; }
[aria-pressed="true"] > .switch::after { transform: translateX(16px); background: var(--on-accent); }
.sheet-me { margin: 4px 0 2px; padding-left: 12px; }
.sheet-me > .ico { color: var(--muted); }
.sheet-foot { margin: 16px 6px 4px; font-size: 11.5px; color: var(--muted); }

/* ---------- responsive ---------- */
/* Tablets and narrow windows (the panel stays on the left). */
@media (max-width: 900px) {
  .topbar { position: relative; padding: 8px 12px; backdrop-filter: none; background: var(--surface-2); }
  .board-pane { padding: 10px 10px 40px; }
  .views[data-view="split"] { grid-template-columns: minmax(0, 1fr); }
  .views[data-view="split"] .map-pane { position: relative; top: 0; height: 46vh; order: -1; border-left: 0; border-bottom: 1px solid var(--line); }
  .stage-head { top: 0; position: relative; }
  .view-full .stage-cards { grid-template-columns: 1fr; }
  .card { grid-template-columns: auto 1fr; }
  .card-time { grid-column: 2; text-align: left; }
  .card-next, .card-actions, .card-reqs, .card-watch { grid-column: 1 / -1; }
  .card-time .ship-art { margin-left: 0; }
}
/* Phones: the bar at the bottom replaces the panel; the header keeps the
   save state (it never floats over the content) in three short lines (stage
   B0): name, state and role; the section's modes, «＋ Buque», undo and
   redo; the search. Nothing is removed: icons keep their names for screen
   readers and as tooltips. */
@media (max-width: 720px) {
  .app, .app.rail-collapsed { grid-template-columns: minmax(0, 1fr); }
  .rail { display: none; }
  .tabbar {
    position: fixed; inset: auto 0 0; z-index: 40; display: grid; grid-template-columns: repeat(5, minmax(0, 1fr));
    min-height: calc(var(--rail-bar-h) + env(safe-area-inset-bottom));
    padding: 4px max(4px, env(safe-area-inset-right)) env(safe-area-inset-bottom) max(4px, env(safe-area-inset-left));
    background: linear-gradient(180deg, var(--ink) 0%, var(--ink-2) 100%); color: var(--on-ink); box-shadow: 0 -6px 18px rgb(7 21 38 / .22);
  }
  .main { padding-bottom: calc(var(--rail-bar-h) + env(safe-area-inset-bottom)); }
  /* The lines are spaced by margins: the zero-height break after the first
     line (::after) must not add a gap of its own. */
  .topbar { gap: 0 6px; padding: 8px 12px; }
  .topbar::after { content: ""; order: 5; flex: 1 0 100%; height: 0; }
  .topbar-title, .topbar-tools { display: contents; }
  .topbar-logo { display: block; order: 1; height: 34px; }
  /* The name keeps room for one word of the longest title; a long one wraps between words. */
  .topbar h1 { order: 2; flex: 1 1 8em; min-width: 6em; font-size: 17px; overflow-wrap: break-word; hyphens: auto; }
  .save-pill { order: 3; }
  .save-time { display: none; }
  .role-badge { order: 4; }
  .role-badge > span { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .presence-btn { display: none; } /* «Más» → Mi estado */
  .section-tools { order: 6; flex: 0 1 auto; flex-wrap: nowrap; gap: 6px; margin-top: 6px; }
  .section-tools .segmented a { padding-inline: 10px; }
  #undo { order: 7; margin: 6px 0 0 auto; }
  #redo { order: 8; margin-top: 6px; }
  .search { order: 9; flex: 1 1 100%; min-width: 0; margin-top: 6px; }
  .identity { order: 10; flex: 1 1 100%; margin-top: 6px; }
  .identity select { flex: 1; min-width: 0; }
  .env-banner { order: 11; flex: 1 1 100%; margin-top: 6px; }
  .key-notice { order: 12; margin-top: 8px; }
  .new-visit .new-visit-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .btn.new-visit { min-width: 44px; justify-content: center; padding-inline: 10px; }
  .views[data-view="map"] .map-pane { height: calc(100dvh - var(--topbar-h, 57px) - var(--rail-bar-h) - env(safe-area-inset-bottom)); min-height: 320px; }
  .toasts { bottom: calc(var(--rail-bar-h) + env(safe-area-inset-bottom) + 10px); }
  /* The board's header in one line: «Contadores y managers» (its icon),
     the sides and «Contraer / Expandir todo» (their icons); the counters and
     the manager code unfold under it and slide sideways. */
  .board-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 6px; margin-bottom: 10px; }
  .board-toolbar > .new-visit-slot { flex: 1 0 100%; }
  .board-toolbar .kpi-strip, .board-toolbar .filter-row { display: contents; }
  .kpi-toggle { order: 1; padding: 4px 8px; gap: 2px; }
  .kpi-toggle .kpi-toggle-label, .fold-all .fold-label, .side-switch .side-long, .band-toggle .band-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .side-switch { order: 2; flex: 1 1 auto; min-width: 0; }
  .side-switch button { flex: 1 1 auto; padding: 6px 8px; }
  .fold-all { order: 3; min-width: 44px; justify-content: center; }
  .board-toolbar .btn.fold-all { min-height: 44px; }
  .kpi-chips { order: 4; flex: 1 0 100%; flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; scroll-snap-type: x proximity; padding-bottom: 2px; }
  .kpi-chips::-webkit-scrollbar { display: none; }
  .kpi-chip { flex: none; scroll-snap-align: start; }
  .mgr-legend { order: 5; flex: 1 0 100%; margin-top: 0; flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; padding-bottom: 2px; }
  .mgr-legend::-webkit-scrollbar { display: none; }
  .mgr-legend > * { flex: none; }
  .clear-filters { order: 6; }
  /* Folded with something filtering: the counter and the manager that
     filter and «Quitar filtros» share one line. */
  .board-toolbar[data-folded="true"] .kpi-chips, .board-toolbar[data-folded="true"] .mgr-legend { flex: 0 1 auto; }
  /* A side's head in one line: its name with the count under it, and the map
     as an icon. */
  .block-head { display: grid; grid-template-columns: minmax(0, 1fr) auto; column-gap: 8px; row-gap: 0; margin: 4px 2px 8px; }
  .block-head h2 { grid-column: 1; grid-row: 1; }
  .block-head .block-count { grid-column: 1; grid-row: 2; padding-left: 32px; font-size: 11.5px; }
  .block-head .band-toggle { grid-column: 2; grid-row: 1 / span 2; margin-left: 0; min-width: 44px; justify-content: center; }
  /* Compact cards and arrival rows in three short lines (at most ~104 px):
     the drawing, the name and «⋯»; the time and its distance; one row of
     small chips that wraps. The handle gives way: «Mover a…» is in «⋯». */
  .card.compact-card, .card.compact-card.arr-row { grid-template-columns: minmax(0, 1fr); padding: 5px 6px 5px 10px; }
  .card.compact-card > .cc-body { grid-column: 1; }
  .card.compact-card > .more-btn { position: absolute; top: 2px; right: 2px; }
  .card.compact-card > .card-more { grid-column: 1 / -1; }
  .card.compact-card > .cc-body, .arr-row > .cc-body { display: flex; flex-wrap: wrap; align-items: center; gap: 3px 5px; }
  .compact-card .cc-line1, .compact-card .cc-line2, .compact-card .cc-tags, .compact-card .cc-chips { display: contents; }
  .compact-card .cc-body > .ship-art { order: 1; width: 56px; height: 31px; }
  .compact-card .arr-rank { order: 0; }
  .compact-card .cc-line1 > .status-chip.glyph-only { order: 2; }
  .compact-card .card-name { order: 3; flex: 1 1 0; min-width: 0; margin-right: 44px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .compact-card .cc-when { order: 4; flex: 1 0 100%; padding-right: 40px; }
  .compact-card .cc-line1 > .mgr-chips { order: 5; }
  .compact-card .cc-tags > *, .compact-card .cc-chips > * { order: 6; }
  .compact-card .cc-type { display: none; }
  /* The chips of the third line, small: 16 px high, so even two lines of
     them keep the card within ~104 px. */
  .compact-card .cc-body .badge, .compact-card .cc-body .status-chip, .compact-card .cc-body .pa-chip, .compact-card .cc-body .mgr-tag, .compact-card .cc-body .mgr-more, .compact-card .cc-body .chip-btn { font-size: 10.5px; line-height: 14px; padding-top: 1px; padding-bottom: 1px; }
  .compact-card .cc-body .status-chip .glyph { width: 14px; height: 14px; font-size: 8.5px; }
  .compact-card .cc-body .badge.tier .tier-ico { width: 12px; height: 12px; }
  .compact-card .cc-body .mgr-tag { padding-left: 4px; padding-right: 6px; border-left-width: 4px; }
  .compact-card .cc-body .mgr-chips { gap: 3px; }
  .compact-card .cc-chips > .chip-btn { min-height: 0; padding-left: 7px; padding-right: 7px; }
  .card.compact-card > .grip { display: none; }
  .stage-cards > .card.compact-card { contain-intrinsic-size: auto 100px; }
  .stage-cards > .card.full-card { contain-intrinsic-size: auto 470px; }
  .future-minis > .card { contain-intrinsic-size: auto 84px; }
}
/* Touch screens wider than a phone (tablets): the handle gives way as well;
   «Mover a…» in «⋯» does the same without dragging. */
@media (pointer: coarse) and (min-width: 721px) {
  .card.compact-card > .grip { display: none; }
  .card.compact-card, .card.compact-card.arr-row { grid-template-columns: minmax(0, 1fr) auto; }
  .card.compact-card > .cc-body { grid-column: 1; }
  .card.compact-card > .more-btn { grid-column: 2; }
  .card.compact-card > .card-more { grid-column: 1 / -1; }
}
@media (max-width: 420px) {
  .topbar h1 { font-size: 16px; }
  .stage-desc { display: none; }
}
/* Up to 440 px the modes say their names without icons, so they share the
   line with «＋ Buque», undo and redo in every section and language. */
@media (max-width: 440px) { .section-tools .segmented .ico { display: none; } }
/* The narrowest phones: the save state as its icon (the words stay for screen readers and the tooltip). */
@media (max-width: 360px) {
  .save-short { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  /* The modes as their icons, with their names for screen readers and as tooltips. */
  .section-tools .segmented .ico { display: inline-block; }
  .section-tools .segmented .mode-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .section-tools .segmented a { min-width: 44px; padding-inline: 8px; }
  /* The sides and «Contraer / Expandir todo» keep their line; «Contadores y
     managers» opens the next one, with what it unfolds. */
  .kpi-toggle { order: 3; }
  .side-switch { order: 1; }
  .fold-all { order: 2; }
  /* The dossier's head: the name keeps the first line beside «Cerrar»; its
     status and «Cámaras» go under it (in one line they left the name ~20 px). */
  #dossier .drawer-head { display: grid; grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "title close" "state cams"; align-items: center; gap: 6px 10px; }
  #dossier .drawer-head > h2 { grid-area: title; }
  #dossier .drawer-head > .status-chip { grid-area: state; justify-self: start; }
  #dossier .drawer-head > [data-act="cameras"] { grid-area: cams; justify-self: end; }
  #dossier .drawer-head > [data-act="close"] { grid-area: close; justify-self: end; }
}

/* Touch screens (pointer: coarse): a larger, labelled drag handle (easy for
   every age) and EVERY control at least 44 × 44 px. A mouse keeps the
   desktop sizes; only a touch screen gets this.
   - The floor: buttons (small ones too), fields, selectors, summaries, tabs,
     modes, counters, toggles and the labels of checkboxes and options. It
     holds over every component (!important, like reduced motion below): a
     component may be bigger, never smaller.
   - Inside a card, its chips, pills and name keep their small look: their
     touch area grows to 44 px around them instead (::after), laid under the
     card's other content (z-index -1 in the card, isolation), so it only
     takes the empty space: a chip never takes the tap meant for its
     neighbour, and the card itself is the bigger target behind them.
   - Section and side heads keep their height: the 44 px toggle takes the
     room of their padding. */
@media (pointer: coarse) {
  .grip { width: 44px; height: 52px; }
  button.grip::after { content: "⇅"; font-size: 11px; display: block; }
  .btn, summary, select, textarea, .settings-tab, .segmented a, .segmented button, .kpi-chip, .kpi-toggle, .mgr-chip, .stage-jump, .stage-toggle, .block-toggle, .role-badge, .rail-btn, .chip-btn:not(.card .chip-btn),
  input:not([type="checkbox"], [type="radio"], [type="range"], [type="hidden"], .sr-file),
  label:has(input[type="checkbox"], input[type="radio"]) { min-height: 44px !important; }
  .btn, .role-badge, input[type="color"], .check-cell { min-width: 44px !important; }
  /* A label around a checkbox is the target: the whole line, centred. */
  label:not([class]):has(> input[type="checkbox"], > input[type="radio"]) { display: inline-flex; align-items: center; gap: 6px; }
  .group > summary { align-items: center; }
  .settings-tab { display: inline-flex; align-items: center; }
  .stage-head { padding-block: 0; row-gap: 0; }
  .block-head h2 { display: flex; }
  .card { isolation: isolate; }
  .card .chip-btn, .card a.pa-chip, .card .watch-pill, .card .card-name { position: relative; }
  .card .chip-btn::after, .card a.pa-chip::after, .card .watch-pill::after, .card .card-name::after { content: ""; position: absolute; z-index: -1; inset: calc(50% - 22px) -3px; }
  .rail-icon { height: 44px; }
  /* The map's zoom buttons (Leaflet draws them at 30 px on touch screens). */
  .leaflet-container.leaflet-touch .leaflet-bar a { width: 44px; height: 44px; line-height: 44px; }
}

/* Reduced motion: nothing moves (an infinite animation with a short duration
   would still loop); transitions end at once. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition-duration: 1ms !important; scroll-behavior: auto !important; }
}

/* ---------- agency brand (web/brand.mjs, shared/settings.mjs) ----------
   Only when the owner chose colours other than the built-in ones: each
   theme's tokens take the agency's values (the server checked them for AA).
   The values come as --brand-* custom properties set through CSSOM. */
:root[data-brand] {
  --ink: var(--brand-primary-light);
  --ink-2: color-mix(in srgb, var(--brand-primary-light) 82%, #000);
  --ink-3: color-mix(in srgb, var(--brand-primary-light) 88%, #fff);
  --gold: var(--brand-accent-light);
  --accent: var(--brand-primary-light);
  --accent-strong: color-mix(in srgb, var(--brand-primary-light) 78%, #000);
  --accent-soft: color-mix(in srgb, var(--brand-primary-light) 12%, #fff);
  --on-accent: #ffffff;
  /* The server checks only the panel's main text on another agency's colour
     (shared/settings.mjs): its descriptions take that same text. */
  --on-ink-muted: var(--on-ink);
  /* Screens that stay white in both themes (sign-in, launch). */
  --brand-on-white: var(--brand-primary-light);
  --brand-accent-on-white: var(--brand-accent-light);
}
@media (prefers-color-scheme: dark) {
  :root[data-brand]:not([data-theme="light"]) {
    --ink: var(--brand-primary-dark);
    --ink-2: color-mix(in srgb, var(--brand-primary-dark) 82%, #000);
    --ink-3: color-mix(in srgb, var(--brand-primary-dark) 88%, #fff);
    --gold: var(--brand-accent-dark);
    --accent: var(--brand-accent-dark);
    --accent-strong: color-mix(in srgb, var(--brand-accent-dark) 80%, #fff);
    --accent-soft: color-mix(in srgb, var(--brand-accent-dark) 22%, #091220);
    --on-accent: var(--brand-primary-dark);
  }
}
:root[data-brand][data-theme="dark"] {
  --ink: var(--brand-primary-dark);
  --ink-2: color-mix(in srgb, var(--brand-primary-dark) 82%, #000);
  --ink-3: color-mix(in srgb, var(--brand-primary-dark) 88%, #fff);
  --gold: var(--brand-accent-dark);
  --accent: var(--brand-accent-dark);
  --accent-strong: color-mix(in srgb, var(--brand-accent-dark) 80%, #fff);
  --accent-soft: color-mix(in srgb, var(--brand-accent-dark) 22%, #091220);
  --on-accent: var(--brand-primary-dark);
}

/* ---------- Ajustes (web/settings-page.mjs) ---------- */
.settings-tabs { display: flex; flex-wrap: wrap; gap: 4px; margin: 10px 0 14px; border-bottom: 1px solid var(--line); }
.settings-tab { padding: 8px 14px; border-radius: 10px 10px 0 0; color: var(--text); text-decoration: none; font-weight: 600; border-bottom: 3px solid transparent; }
.settings-tab:hover { background: var(--surface-2); }
.settings-tab[aria-selected="true"] { color: var(--text-strong); border-bottom-color: var(--accent); background: var(--surface-2); }
.settings-panel, .settings-form { display: grid; gap: 10px; }
/* Each block may shrink to the panel: a wide table (manager colours, line
   rules) scrolls inside its own box instead of widening the page on a phone. */
.settings-panel > *, .settings-form > * { min-width: 0; }
.settings-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 10px 14px; align-items: end; }
.settings-actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.field > span.hint { color: var(--muted); font-size: 11.5px; text-transform: none; letter-spacing: 0; }
.color-table th, .color-table td { vertical-align: middle; }
.color-pair { display: inline-flex; align-items: center; gap: 6px; }
.color-pair input[type="color"] { width: 42px; height: 32px; padding: 2px; border: 1px solid var(--line-ctrl); border-radius: 8px; background: var(--surface-2); }
.color-pair .hex { width: 11ch; padding: 6px 8px; border: 1px solid var(--line-ctrl); border-radius: 8px; background: var(--surface-2); }
.color-pair .hex[aria-invalid="true"] { border-color: var(--danger); box-shadow: 0 0 0 1px var(--danger); }
/* A phone (600 px or less): one card per colour and a line per theme with its
   name, so the table fits a 320 px phone with no sideways scroll (final QA of
   28 Oct: at 375 px it scrolled inside its box). Checked pairs only: the
   colour's name in --text-strong and the theme's in --muted, on --surface. */
@media (max-width: 600px) {
  .color-table thead { display: none; }
  .color-table tbody tr { display: grid; gap: 4px; padding: 10px; border-bottom: 1px solid var(--line); }
  .color-table tbody tr:last-child { border-bottom: 0; }
  .color-table tbody th[scope="row"] { display: block; padding: 0; border: 0; background: none; color: var(--text-strong); }
  .color-table tbody td { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-width: 0; padding: 0; border: 0; }
  .color-table td[data-label]::before { content: attr(data-label); min-width: 0; font-size: 10.5px; text-transform: uppercase; letter-spacing: .06em; color: var(--muted); }
}
/* Preview of both themes at once, whatever theme is on screen. */
.brand-preview { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 10px; }
.pv { display: grid; gap: 8px; justify-items: start; padding: 10px; border-radius: var(--r-m); border: 1px solid var(--line); }
.pv-light { background: #eef1f5; color: #2a3b4c; }
.pv-dark { background: #1a3148; color: #d3dfeb; }
.pv-theme { font-size: 11px; letter-spacing: .06em; text-transform: uppercase; }
.pv-rail { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 6px; width: 100%; padding: 8px 10px; border-radius: 10px; color: #dbe7f3; font-size: 12px; }
.pv-light .pv-rail { background: var(--pv-primary-light, #1e3551); }
.pv-dark .pv-rail { background: var(--pv-primary-dark, #1e3551); }
.pv-product { color: #fff; font: 800 13px/1 var(--font-display); letter-spacing: .04em; }
.pv-name { font-weight: 700; }
.pv-light .pv-name { color: var(--pv-accent-light, #d4a35f); }
.pv-dark .pv-name { color: var(--pv-accent-dark, #d4a35f); }
.pv-item { flex-basis: 100%; }
.pv-btn { display: inline-block; padding: 6px 12px; border-radius: 10px; font-weight: 700; font-size: 12.5px; }
.pv-light .pv-btn { background: var(--pv-primary-light, #1e3551); color: #fff; }
.pv-dark .pv-btn { background: var(--pv-accent-dark, #d4a35f); color: var(--pv-primary-dark, #1e3551); }
.pv-link { font-weight: 600; text-decoration: underline; font-size: 12.5px; }
.pv-light .pv-link { color: var(--pv-primary-light, #1e3551); }
.pv-dark .pv-link { color: var(--pv-accent-dark, #d4a35f); }
.aa-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 3px; font-size: 12.5px; }
.aa-list li { display: flex; gap: 6px; align-items: baseline; }
.aa-list li.ok > .ico { color: var(--ok); }
.aa-list li.fail { color: var(--danger); font-weight: 600; }
.inline-meta { color: var(--muted); font-size: 12px; font-weight: 400; }
.logo-box { display: flex; flex-wrap: wrap; gap: 14px; align-items: flex-start; }
.logo-plate { display: grid; place-items: center; width: 170px; height: 150px; padding: 10px; border-radius: 14px; background: #fff; box-shadow: 0 0 0 1px var(--line); }
.logo-plate img { max-width: 100%; max-height: 100%; width: auto; height: auto; object-fit: contain; }
.logo-controls { display: grid; gap: 8px; flex: 1 1 260px; }
.tpl-items { margin: 0; padding: 0; list-style: none; display: grid; gap: 6px; }
.tpl-item { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; padding: 6px 8px; border-radius: 10px; background: var(--surface-2); }
.tpl-item input[type="text"] { flex: 1 1 240px; min-width: 0; padding: 6px 8px; border: 1px solid var(--line-ctrl); border-radius: 8px; background: var(--surface); }
.tpl-item input[data-label-en] { flex-basis: 200px; }
@media (pointer: coarse) { .tpl-item input[type="text"] { min-height: 44px; } }
.tpl-n { min-width: 2ch; color: var(--muted); font-weight: 700; }
.tpl-move { display: inline-flex; gap: 2px; }
.tpl-preview { margin: 4px 0 8px; padding-left: 22px; display: grid; gap: 3px; }
.canal-rule th { width: 110px; }
/* Line rules (Ajustes · Managers, §6): the list, and the form in place. */
.rules-table td { vertical-align: middle; }
.rules-table tr.off td { color: var(--muted); }
.rule-actions { white-space: nowrap; }
.rule-form { display: grid; gap: 10px; margin: 8px 0; padding: 10px 12px; border-radius: var(--r-m); border: 1px solid var(--accent); background: var(--surface); }
.rf-fields { border: 0; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 6px 14px; align-items: center; }
.rf-fields > legend { padding: 0; margin-bottom: 4px; color: var(--muted); font-size: 11px; text-transform: uppercase; letter-spacing: .06em; }
.rf-fields input[type="checkbox"], .rule-form .check input { width: auto; }

/* ---------- Expediente: find a vessel (web/pages.mjs) ---------- */
.dossier-search { max-width: 860px; }
.ds-find { display: flex; align-items: center; gap: 8px; padding: 4px 10px; margin: 8px 0; border: 1px solid var(--line-ctrl); border-radius: 10px; background: var(--surface); }
.ds-find:focus-within { box-shadow: 0 0 0 2px var(--accent); }
.ds-find input { flex: 1; min-width: 0; border: 0; padding: 8px 2px; background: transparent; font-size: 15px; outline: none; }
.ds-results { list-style: none; margin: 0; padding: 0; display: grid; gap: 4px; }
.ds-results li.none { padding: 8px; color: var(--muted); }
.ds-row { display: flex; align-items: center; gap: 10px; width: 100%; padding: 8px 10px; border: 1px solid var(--line); border-radius: 10px; background: var(--surface); color: var(--text-strong); text-align: left; cursor: pointer; }
.ds-row:hover { border-color: var(--accent); }
.ds-main { display: grid; flex: 1; min-width: 0; }
.ds-main .meta { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* The vessel's name with its class chip beside it. */
.ds-head { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 6px; min-width: 0; }

/* ---------- «Enviar reporte» (stage S6, web/report-composer.mjs) ----------
   A modal dialog: the form on the left, the live preview on the right; one
   column under 960 px and a full-screen sheet on phones. The actions stay
   at the foot. Colours are the app tokens, in both themes. */
.composer { width: min(1200px, calc(100vw - 32px)); max-width: none; height: min(92vh, 960px); max-height: none; margin: auto; padding: 0; border: 1px solid var(--line); border-radius: var(--r-l); background: var(--surface); color: var(--text); box-shadow: var(--sh-raised); overflow: hidden; }
.composer[open] { display: flex; flex-direction: column; animation: rc-in var(--d-base) var(--ease-open); }
.composer::backdrop { background: rgb(7 21 38 / .55); }
@keyframes rc-in { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
.rc-head { flex: none; display: flex; align-items: flex-start; gap: 10px; padding: 12px 16px 10px; border-bottom: 1px solid var(--line); }
.rc-titles { flex: 1; min-width: 0; }
.rc-head h2 { margin: 0; display: flex; align-items: center; gap: 8px; font: 800 18px/1.25 var(--font-display); color: var(--text-strong); }
.rc-head h2 .ico { flex: none; color: var(--accent); }
.rc-head .meta { margin: 4px 0 0; font-size: 12.5px; }
.rc-close { min-width: 44px; min-height: 44px; }
/* Every scrolling part is positioned: what a screen reader alone reads
   (.sr-only, absolute) stays inside it instead of stretching the dialog. */
.rc-body { position: relative; flex: 1; min-height: 0; display: grid; grid-template-columns: minmax(360px, 1fr) minmax(0, 1.12fr); overflow: hidden; }
.rc-form { position: relative; overflow-y: auto; overscroll-behavior: contain; padding: 12px 16px 24px; display: grid; gap: 12px; align-content: start; border-right: 1px solid var(--line); }
.rc-preview { position: relative; min-height: 0; display: flex; flex-direction: column; background: var(--surface-3); }
.rc-preview > h3 { flex: none; display: flex; align-items: center; gap: 6px; margin: 0; padding: 10px 16px; font: 700 12px/1.3 var(--font); letter-spacing: .08em; text-transform: uppercase; color: var(--text); }
.rc-paper-wrap { position: relative; flex: 1; min-height: 0; overflow: auto; overscroll-behavior: contain; padding: 0 16px 24px; }
.rc-block { display: grid; gap: 8px; padding: 12px; border: 1px solid var(--line); border-radius: var(--r-m); background: var(--surface-2); min-width: 0; }
.rc-block h3 { margin: 0; font: 700 12px/1.3 var(--font); letter-spacing: .08em; text-transform: uppercase; color: var(--text); }
.rc-row { display: flex; flex-wrap: wrap; gap: 10px; align-items: flex-end; }
.rc-row > .rc-field { flex: 1 1 170px; }
.rc-row > .rc-grow { flex: 2 1 240px; }
.rc-field { display: grid; gap: 4px; min-width: 0; }
.rc-field > label, .rc-label { font-size: 12.5px; font-weight: 700; color: var(--text-strong); }
.rc-field input, .rc-field select, .rc-field textarea, .rc-add input { width: 100%; min-height: 40px; padding: 8px 10px; border: 1px solid var(--line-ctrl); border-radius: 8px; background: var(--surface); color: var(--text-strong); font: inherit; }
.rc-field textarea { min-height: 72px; resize: vertical; }
.rc-field .hint, .rc-block .hint { font-size: 12px; color: var(--muted); }
.rc-field .btn { justify-self: start; }
.rc-lang { display: flex; flex-wrap: wrap; gap: 6px; margin: 0; padding: 0; border: 0; }
.rc-lang legend { padding: 0; margin-bottom: 4px; font-size: 12.5px; font-weight: 700; color: var(--text-strong); }
.rc-lang label { display: inline-flex; align-items: center; gap: 6px; min-height: 40px; padding: 4px 12px; border: 1px solid var(--line-ctrl); border-radius: var(--pill); background: var(--surface); color: var(--text-strong); font-size: 13px; cursor: pointer; }
.rc-lang label:has(input:checked) { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); font-weight: 700; }
.rc-lang label:has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }
.rc-pending { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.rc-pending:empty { display: none; }
.chip-btn.report-chip.current, .chip-btn.report-chip[aria-pressed="true"] { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
.rc-addr { display: grid; gap: 6px; }
.rc-chips { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 6px; }
.rc-chip { display: inline-flex; align-items: center; gap: 2px; max-width: 100%; padding: 2px 2px 2px 10px; border: 1px solid var(--line-ctrl); border-radius: var(--pill); background: var(--surface); color: var(--text-strong); font-size: 12.5px; }
.rc-chip > span { overflow-wrap: anywhere; }
.rc-chip-x { display: inline-grid; place-items: center; min-width: 30px; min-height: 30px; border: 0; border-radius: var(--pill); background: transparent; color: var(--text); cursor: pointer; }
.rc-chip-x:hover { background: var(--surface-3); color: var(--text-strong); }
.rc-none { font-size: 12.5px; color: var(--muted); }
.rc-add { display: flex; gap: 6px; align-items: center; }
.rc-add input { flex: 1; min-width: 0; }
.rc-rcpt-foot { align-items: center; }
.rc-ready { display: flex; gap: 8px; align-items: flex-start; margin: 0; padding: 8px 10px; border-radius: var(--r-s); font-size: 13px; color: var(--text-strong); }
.rc-ready .ico { flex: none; margin-top: 1px; }
.rc-ready.ok { background: color-mix(in srgb, var(--ok) 12%, var(--surface)); }
.rc-ready.ok .ico { color: var(--ok); }
.rc-ready.warn { background: var(--warn-soft); }
.rc-ready.warn .ico { color: var(--warn); }
.rc-missing, .rc-warnings { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.rc-missing li { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; font-size: 13px; color: var(--text-strong); }
.rc-warnings li { display: flex; gap: 6px; align-items: flex-start; font-size: 12.5px; color: var(--text); }
.rc-warnings .ico { flex: none; margin-top: 2px; color: var(--warn); }
.rc-suggest > summary { min-height: 36px; padding: 6px 0; cursor: pointer; font-size: 12.5px; color: var(--text-strong); }
.rc-suggest ol, .rc-items { margin: 0; padding-left: 22px; font-size: 13px; }
.rc-foot { flex: none; display: grid; gap: 8px; padding: 10px 16px 12px; border-top: 1px solid var(--line); background: var(--surface); }
.rc-status { margin: 0; font-size: 13px; line-height: 1.45; color: var(--text-strong); }
.rc-status:empty { display: none; }
.rc-status .ico { vertical-align: -3px; }
.rc-status.ok .ico { color: var(--ok); }
.rc-status.warn .ico { color: var(--warn); }
.rc-mailto { font-weight: 700; color: var(--accent); }
.rc-actions { display: flex; flex-wrap: wrap; gap: 8px; }
.rc-actions .btn { min-height: 42px; }
.rc-sent { position: relative; max-height: 45vh; overflow-y: auto; }
.rc-sent:empty { display: none; }
@media (max-width: 960px) {
  .rc-body { display: block; overflow-y: auto; overscroll-behavior: contain; }
  .rc-form { overflow: visible; border-right: 0; }
  .rc-paper-wrap { overflow: visible; }
}
@media (max-width: 720px) {
  .composer { width: 100vw; height: 100dvh; border: 0; border-radius: 0; margin: 0; }
  .rc-head { padding-top: calc(10px + env(safe-area-inset-top)); }
  .rc-foot { padding-bottom: calc(10px + env(safe-area-inset-bottom)); }
  .rc-actions .btn { flex: 1 1 calc(50% - 8px); justify-content: center; min-height: 44px; }
  .rc-paper-wrap { padding: 0 8px 16px; }
}
/* Phones and short windows: the head never leaves the screen and the foot
   never takes it. The foot scrolls as one piece (no box inside a box) and
   keeps at most half the height for the form. «Marcar como enviado» is a
   step of its own: while its question is open, the form, the copy message
   and the other actions give way to it (its «Cancelar» goes back), so
   «Sí, ya lo envié» is in view. */
@media (max-width: 720px), (max-height: 720px) {
  .rc-foot { flex: 0 1 auto; min-height: 0; max-height: 50%; overflow-y: auto; overscroll-behavior: contain; }
  .rc-sent { max-height: none; overflow: visible; }
  .composer:has(.rc-sent .inline-ask) .rc-body { flex: 0 0 0; visibility: hidden; }
  .composer:has(.rc-sent .inline-ask) .rc-foot { flex: 1 1 auto; max-height: none; }
  .composer:has(.rc-sent .inline-ask) .rc-status,
  .composer:has(.rc-sent .inline-ask) .rc-actions { display: none; }
}
@media (pointer: coarse) {
  .rc-chip-x { min-width: 44px; min-height: 44px; }
  .rc-lang label, .rc-field input, .rc-field select, .rc-add input { min-height: 44px; }
}

/* The preview paper (web/report-preview.mjs): the look of the e-mail, white
   in both themes, with the Reporting Studio colours (AA on their backgrounds,
   docs/REPORTES.md §11); the agency navy and gold come in --rp-navy and
   --rp-gold (data-vars) when it changed them. A datum printed «TBC» is
   underlined in red dots. */
.rp-paper { --rp-navy: #17314c; --rp-gold: #d7a65e; color-scheme: light; max-width: 680px; margin: 0 auto; background: #ffffff; color: #263d52; border: 1px solid #d6e1e9; font: 12px/1.55 Arial, Helvetica, sans-serif; overflow-wrap: anywhere; }
.rp-paper.rp-dope { border-color: #d1e0ea; color: #1f344b; }
.rp-header { display: flex; align-items: center; gap: 12px; padding: 9px 18px; background: #f4f7fa; border-top: 5px solid var(--rp-navy); border-bottom: 3px solid var(--rp-gold); }
.rp-logo { display: block; max-width: 124px; max-height: 96px; width: auto; height: auto; }
.rp-header-dope .rp-logo { max-width: 95px; max-height: 74px; }
.rp-brandname { font: 700 26px/30px Arial, Helvetica, sans-serif; color: var(--rp-navy); }
.rp-header-text { margin-left: auto; display: grid; text-align: right; font-size: 12px; line-height: 18px; color: var(--rp-navy); }
.rp-legal { letter-spacing: .4px; }
.rp-tagline { color: #51677b; }
.rp-since { color: #926830; font-size: 10px; letter-spacing: .6px; }
.rp-office { color: #526a7e; font-size: 10px; }
.rp-meta { margin: 0; padding: 8px 20px; background: #f7fafc; color: #506a80; font-size: 10px; line-height: 14px; }
.rp-dope .rp-meta { background: #ffffff; }
.rp-vessel { padding: 18px 20px 13px; background: #eef3f6; }
.rp-vname { margin: 0; font: 700 23px/28px Arial, Helvetica, sans-serif; color: var(--rp-navy); }
.rp-vline { margin: 7px 0 0; font: 700 12px/16px Arial, Helvetica, sans-serif; color: #315d7c; }
.rp-route { margin: 8px 0 0; font-size: 11px; line-height: 15px; color: #516981; }
.rp-band { margin: 0; padding: 10px 20px; background: #fff8e9; color: #6f542e; font: 700 12px/18px Arial, Helvetica, sans-serif; }
.rp-title-band { padding: 15px 20px; background: #0f2538; color: #ffffff; }
.rp-title-band .rp-vname { color: #ffffff; font-size: 22px; line-height: 27px; }
.rp-title-band p { margin: 6px 0 0; }
.rp-sec { padding: 0 20px 8px; }
.rp-h { margin: 0; padding: 15px 0 7px; font: 700 10px/14px Arial, Helvetica, sans-serif; letter-spacing: 1px; color: #285a79; }
.rp-dope .rp-h { color: #234563; font-size: 11px; letter-spacing: 0; }
.rp-table { width: 100%; border-collapse: collapse; font-size: 12px; line-height: 17px; color: #243b52; }
.rp-table th, .rp-table td { padding: 8px 9px; text-align: left; vertical-align: top; border-bottom: 1px solid #e2e8ef; }
.rp-chrono thead th { background: #e6edf2; color: #405c76; font-size: 10px; }
.rp-chrono tbody tr:nth-child(odd) td { background: #f5f8fa; }
.rp-chrono-dope th, .rp-chrono-dope td { border: 1px solid #d4dfe7; font-size: 11px; }
.rp-chrono-dope tbody tr:nth-child(odd) td { background: #ffffff; }
.rp-when { white-space: nowrap; font-size: 11px; }
.rp-st { font-size: 10px; font-weight: 700; }
.rp-st-actual { color: #23794e; }
.rp-st-expected { color: #97671a; }
.rp-st-pending { color: #627282; }
.rp-st-alert { color: #a93a44; }
.rp-remark { display: block; margin-top: 4px; font-size: 11px; color: #5f7285; }
.rp-rows th { width: 39%; padding: 5px 10px; font-size: 11px; font-weight: 400; color: #577084; border-bottom-color: #e7edf2; }
.rp-rows td { padding: 5px 10px; font-size: 11px; font-weight: 700; color: #243c53; border-bottom-color: #e7edf2; }
.rp-details th, .rp-details td { border: 1px solid #d4dfe7; padding: 7px 9px; }
.rp-details th { width: 30%; background: #f4f7fa; font-weight: 700; }
.rp-particulars th, .rp-particulars td { padding: 5px 8px; border: 1px solid #abb8c4; font-size: 11px; color: #1f344b; }
.rp-particulars th { width: 38%; }
.rp-text { margin: 0; color: #263d52; }
.rp-notice { color: #203a52; }
.rp-link { color: #24658c; }
.rp-note { margin: 0; padding: 8px 20px; color: #62768a; font-size: 10px; line-height: 15px; }
.rp-further { border-top: 1px solid #dbe4ec; color: #1f344b; font-size: 12px; }
.rp-marine { display: grid; grid-template-columns: 1fr 1fr; }
.rp-mcell { display: grid; gap: 4px; align-content: start; padding: 9px 11px; border: 1px solid #e1e8ef; color: #183550; }
.rp-mlabel { font-size: 10px; color: #395973; }
.rp-mband { justify-self: start; padding: 3px 6px; font-size: 10px; font-weight: 700; }
.rp-mband.lv-0 { background: #eef2f5; color: #5d6d7d; }
.rp-mband.lv-1 { background: #e4f4e9; color: #16603e; }
.rp-mband.lv-2 { background: #fcf3d4; color: #886016; }
.rp-mband.lv-3 { background: #ffecd8; color: #a35712; }
.rp-mband.lv-4 { background: #fde8e8; color: #a12b35; }
.rp-mvalid { font-size: 10px; color: #566a7d; }
.rp-position { margin: 0; padding: 6px 20px 9px; font-size: 11px; color: #31506c; }
.rp-contact { display: flex; flex-wrap: wrap; align-items: center; gap: 12px 16px; padding: 17px 16px 18px; border-top: 1px solid #dce5eb; color: #263d52; }
.rp-signer { display: grid; gap: 3px; flex: 1 1 150px; font-size: 11px; }
.rp-signer-name { font: 700 17px/20px Arial, Helvetica, sans-serif; color: var(--rp-navy); }
.rp-lines { flex: 2 1 220px; display: grid; gap: 4px; margin: 0; padding: 2px 13px; list-style: none; border-left: 2px solid var(--rp-gold); border-right: 2px solid var(--rp-gold); font-size: 11px; color: #152941; }
.rp-lines li { display: flex; gap: 7px; }
.rp-lines .rp-small { font-size: 10px; }
.rp-icon { flex: none; color: #976c32; }
.rp-logo-foot { max-width: 129px; max-height: 100px; }
.rp-contact-short { display: block; padding: 8px 20px; border-top: 1px solid #dbe4ec; font-size: 12px; color: #1f344b; }
.rp-brandbar { margin: 0; padding: 9px 20px; background: var(--rp-navy); color: #ffffff; font-size: 10px; }
.rp-missing, .rp-paper .rp-missing td, .rp-paper .rp-missing th { text-decoration: underline dotted #a93a44; text-decoration-thickness: 2px; text-underline-offset: 3px; }
@media (max-width: 520px) { .rp-marine { grid-template-columns: 1fr; } .rp-header { flex-wrap: wrap; } .rp-header-text { margin-left: 0; text-align: left; } }

/* ---------- the report data in the dossier (web/report-fields-ui.mjs) ---------- */
.rf-field { display: grid; gap: 8px; }
.rf-title { color: var(--muted); font-size: 11px; text-transform: uppercase; letter-spacing: .06em; }
.rf-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 8px 10px; }
.rf-cell { display: grid; gap: 3px; min-width: 0; }
.rf-cell.wide { grid-column: 1 / -1; }
.rf-cell > label, .rf-label, .rf-list-title { font-size: 11.5px; font-weight: 600; color: var(--text); }
.rf-cell input, .rf-cell select, .rf-cell textarea, .rf-row input, .rf-row select, .rf-event input[type="text"], .rf-event select { width: 100%; min-width: 0; padding: 6px 8px; border: 1px solid var(--line-ctrl); border-radius: 8px; background: var(--surface-2); color: var(--text-strong); font: inherit; font-size: 12.5px; }
.rf-cell textarea { min-height: 60px; resize: vertical; }
.rf-stack { display: grid; gap: 8px; }
.rf-set { margin: 0; padding: 8px 10px; border: 1px solid var(--line); border-radius: var(--r-s); }
.rf-set > legend { padding: 0 4px; font-size: 12px; font-weight: 700; color: var(--text-strong); }
.rf-stage { border: 1px solid var(--line); border-radius: var(--r-s); background: var(--surface); }
.rf-stage > summary { display: flex; align-items: center; gap: 8px; min-height: 40px; padding: 6px 10px; cursor: pointer; font-size: 13px; font-weight: 700; color: var(--text-strong); }
.rf-stage-body { display: grid; gap: 8px; padding: 0 10px 10px; }
.rf-check { display: inline-flex; align-items: center; gap: 6px; min-height: 32px; font-size: 12.5px; color: var(--text-strong); }
.rf-check input { width: auto; }
.rf-list { display: grid; gap: 6px; }
.rf-list > .btn { justify-self: start; }
.rf-rows { display: grid; gap: 6px; margin: 0; padding: 0; list-style: none; }
.rf-row { display: grid; grid-template-columns: minmax(96px, 1.4fr) minmax(64px, 1fr) minmax(64px, 1fr) minmax(60px, .7fr) auto; gap: 6px; align-items: center; }
.rf-event { display: grid; grid-template-columns: minmax(100px, .9fr) minmax(0, 2fr) auto auto; grid-template-areas: "when when when when" "status event alert remove" "remark remark remark remark"; gap: 6px; align-items: center; padding: 8px; border: 1px solid var(--line); border-radius: var(--r-s); background: var(--surface); }
.rf-event > .dt24 { grid-area: when; }
.rf-event > [data-rp="status"] { grid-area: status; }
.rf-event > [data-rp="event"] { grid-area: event; }
.rf-event > [data-rp="remark"] { grid-area: remark; }
.rf-event > .rf-check { grid-area: alert; }
.rf-event > [data-rf-remove] { grid-area: remove; }
.rf-hint { grid-column: 1 / -1; margin: 0; font-size: 11.5px; color: var(--muted); }
.rf-ro { white-space: pre-line; }
.field.flash, .rf-field.flash { animation: flash 1.2s var(--ease); border-radius: 8px; }
@media (max-width: 480px) {
  .rf-row { grid-template-columns: 1fr 1fr; }
  .rf-event { grid-template-columns: 1fr 1fr; grid-template-areas: "when when" "status event" "remark remark" "alert remove"; }
}

/* ---------- reports section, evidence box and «⋯» links (stage S6) ---------- */
.rp-send-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.rp-recipients { display: grid; gap: 6px; }
.rp-rcpt { display: grid; gap: 3px; }
.rp-rcpt textarea { min-height: 44px; font-size: 12.5px; }
.rp-recipients > .btn { justify-self: start; }
.report-log li { line-height: 1.45; }
.step-buttons { display: inline-flex; flex-wrap: wrap; gap: 6px; }
.ev-box { display: grid; gap: 8px; }
.ev-open-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; }
.btn.big { min-height: 48px; padding: 10px 18px; font-size: 15px; font-weight: 700; }
.ev-hint { flex-basis: 100%; margin: 0; }
.ev-head { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.ev-head .btn { margin-left: auto; }
.ev-ask:empty { display: none; }
.ev-list { display: grid; gap: 6px; margin: 0; padding: 0; list-style: none; }
.ev-item { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; padding: 8px 10px; border: 1px solid var(--line); border-radius: var(--r-s); background: var(--surface-2); font-size: 13px; color: var(--text-strong); }
.ev-item.removed { background: transparent; border-style: dashed; color: var(--muted); }
.ev-item.removed del { text-decoration-thickness: 2px; }
.ev-cat { background: var(--accent-soft); color: var(--text-strong); }
.ev-note { flex: 1 1 200px; min-width: 0; overflow-wrap: anywhere; }
.ev-link { display: inline-flex; align-items: center; gap: 4px; font-weight: 600; color: var(--accent); }
.ev-meta, .ev-removed { flex-basis: 100%; }
.ev-item .btn { margin-left: auto; }
.card-more-links { display: flex; flex-wrap: wrap; gap: 6px; }
/* Ajustes · Marca: the reports contact, one block per office: side by side
   from 300 px each, one under the other (never wider than the screen) below. */
.ct-offices { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr)); gap: 10px; }
.ct-office { margin: 0; padding: 10px 12px; border: 1px solid var(--line); border-radius: var(--r-m); }
.ct-office > legend { padding: 0 4px; font-weight: 700; color: var(--text-strong); }

/* ---------- the Canal list (stage S8; web/canal-view.mjs, canal-search.mjs, canal-panel.mjs) ----------
   Colours are tokens of both themes (AA on the surfaces they sit on); the
   coast is told by a coloured edge and its words, never by colour alone. */
.canal-search { margin-top: 18px; display: grid; gap: 8px; }
.canal-search-head { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; }
.canal-search-head .sub-title { margin: 0; }
.canal-row { align-items: flex-start; }
.canal-row.static { cursor: default; }
.canal-row.static:hover { border-color: var(--line); }
.canal-row-head { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 6px; }
.canal-row .ds-main .meta { white-space: normal; }
.canal-row-eta { display: flex; flex-wrap: wrap; align-items: center; gap: 2px 6px; }
.canal-rel { font-weight: 600; color: var(--text-strong); }
.badge.agency { background: color-mix(in srgb, var(--ok) 14%, var(--surface)); color: var(--text-strong); border: 1px solid var(--ok); font-weight: 700; }
.side-chip { display: inline-flex; align-items: center; padding: 0 7px; border-radius: 6px; border-left: 3px solid var(--atl); background: var(--atl-soft); color: var(--text-strong); font-size: 11px; font-weight: 600; white-space: nowrap; }
.side-chip.pac { border-left-color: var(--pac); background: var(--pac-soft); }
.canal-age { display: inline-flex; align-items: center; gap: 4px; padding: 1px 8px; border-radius: var(--pill); border: 1px solid var(--line-ctrl); background: var(--surface); color: var(--text-strong); font-size: 11.5px; font-weight: 600; }
.canal-age.tone-fresh { border-color: var(--ok); color: var(--ok); }
.canal-age.tone-old { border-color: var(--warn); color: var(--warn); }
.canal-age.tone-stale, .canal-age.tone-future { border-color: var(--danger); color: var(--danger); }
.canal-empty { display: flex; gap: 12px; align-items: flex-start; padding: 14px; border: 1px dashed var(--line-ctrl); border-radius: var(--r-m); background: var(--surface); color: var(--text-strong); }
.canal-empty p { margin: 4px 0 8px; }
.canal-detail { display: grid; gap: 8px; padding: 12px 14px; border: 1px solid var(--accent); border-radius: var(--r-m); background: var(--surface); box-shadow: var(--sh-card); }
.canal-detail:focus-visible { outline-offset: 3px; }
.canal-detail-head { display: flex; align-items: center; gap: 8px; }
.canal-detail-head h4 { margin: 0; flex: 1; display: flex; align-items: center; gap: 6px; font: 800 15px/1.3 var(--font-display); color: var(--text-strong); overflow-wrap: anywhere; }
.canal-detail-actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.canal-dl { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 6px 14px; margin: 0; }
.canal-dl-row { display: grid; gap: 1px; align-content: start; padding: 6px 0; border-bottom: 1px solid var(--line); min-width: 0; }
.canal-facts .canal-dl-row:last-child { grid-column: 1 / -1; }
.canal-dl dt { font-size: 11px; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.canal-dl dd { margin: 0; color: var(--text-strong); font-size: 13px; overflow-wrap: anywhere; }
.canal-facts { grid-template-columns: repeat(auto-fill, minmax(min(280px, 100%), 1fr)); }
.canal-eta-note { display: flex; align-items: center; gap: 6px; margin: 6px 0 0; padding: 7px 10px; border-radius: var(--r-s); border-left: 3px solid var(--warn); background: var(--warn-soft); color: var(--text-strong); font-size: 13px; }
/* Under the dossier's head the sticky tools bar comes next, pulled up 14 px
   (margin -14px): the note keeps a 12 px gap so the bar never covers its
   last line (finding r2-cx-4). A move question open under it takes that gap. */
.drawer-body > .canal-eta-note { margin-bottom: 26px; }
.drawer-body > .canal-eta-note + .hero-ask > .inline-ask { margin-top: -14px; }
.canal-panel { display: grid; gap: 14px; }
.canal-block { display: grid; gap: 8px; padding: 12px 0 4px; border-top: 1px solid var(--line); }
/* The switch of a source (Tiempos del Canal, Transit Table): three choices
   with what each one does (docs/TRANSIT_TABLE_Y_CANAL.md §3.6). */
.source-modes { display: grid; gap: 6px; margin: 0; padding: 0; border: 0; }
.source-modes label { display: flex; align-items: flex-start; gap: 8px; min-height: 44px; padding: 8px 12px; border: 1px solid var(--line-ctrl); border-radius: var(--r-s); background: var(--surface); color: var(--text-strong); font-size: 13px; cursor: pointer; }
.source-modes label > span { display: grid; gap: 2px; }
.source-modes label:has(input:checked) { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
.source-modes label:has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }
.note-list { margin: 0; padding-left: 18px; font-size: 13px; color: var(--text); display: grid; gap: 4px; }
/* «Movida por R1 · Transit Table · corte …» under the managers of the dossier's head. */
.hero-auto { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 4px; font-size: 12px; }
.fuentes-cases li { display: grid; gap: 4px; }
.fuentes-cases .settings-actions { margin: 0; }
/* Ajustes · Transit Table: the preview of a cut, one block under another
   (lists that scroll in their own box on a phone, never the page). */
.transit-preview { display: grid; gap: 8px; min-width: 0; padding: 10px 12px; border-radius: var(--r-m); border-left: 4px solid var(--accent); background: var(--surface); box-shadow: var(--sh-card); color: var(--text-strong); }
.transit-preview > *, .transit-preview .history-list li { min-width: 0; overflow-wrap: anywhere; }
.transit-preview .history-list { margin: 0; }
/* The board's «Por revisar · N» and its list under the toolbar. */
.review-chip { border-color: var(--warn); }
.fuentes-review { grid-column: 1 / -1; display: grid; gap: 8px; padding: 10px 12px; border: 1px solid var(--line); border-left: 3px solid var(--warn); border-radius: var(--r-s); background: var(--surface); }
.fuentes-review[hidden] { display: none; }
/* Grid items shrink to the screen: a wide table scrolls in its own box
   instead of widening the page (phones). */
.canal-panel, .canal-block, .canal-block > *, .canal-search, .canal-search > * { min-width: 0; }
.canal-block .sub-title { display: flex; align-items: center; gap: 6px; }
.canal-drop { display: flex; flex-wrap: wrap; align-items: center; gap: 12px 16px; padding: 18px; border: 2px dashed var(--line-ctrl); border-radius: var(--r-l); background: var(--surface); color: var(--text-strong); }
.canal-drop.over { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 8%, var(--surface)); }
.canal-drop.busy { opacity: .7; }
.canal-drop-text { display: grid; gap: 2px; flex: 1 1 220px; }
.canal-drop label.btn { min-height: 44px; }
.sr-file { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.sr-file:focus-visible + label { outline: 2px solid var(--accent); outline-offset: 2px; }
.sr-file:disabled + label { opacity: .55; pointer-events: none; }
.canal-progress { position: relative; height: 10px; border-radius: var(--pill); background: var(--surface-3); overflow: hidden; }
.canal-progress[hidden] { display: none; }
.canal-progress > i { display: block; height: 100%; width: var(--pct, 0%); border-radius: inherit; background: var(--accent); transition: width var(--d-fast) linear; }
.canal-progress.working > i { width: 100%; background: repeating-linear-gradient(-45deg, var(--accent) 0 12px, color-mix(in srgb, var(--accent) 60%, var(--surface)) 12px 24px); background-size: 34px 100%; animation: canal-work 1s linear infinite; }
@keyframes canal-work { from { background-position: 0 0; } to { background-position: 34px 0; } }
@media (prefers-reduced-motion: reduce) { .canal-progress.working > i { animation: none; } }
.canal-progress-text:empty { display: none; }
.canal-progress-text.error { color: var(--danger); font-weight: 600; }
.canal-result { display: flex; gap: 10px; align-items: flex-start; padding: 10px 12px; border-radius: var(--r-m); border-left: 4px solid var(--ok); background: var(--surface); box-shadow: var(--sh-card); color: var(--text-strong); }
.canal-result ul { margin: 0; padding-left: 18px; display: grid; gap: 3px; font-size: 13px; }
.canal-changes { border: 1px solid var(--line); border-radius: var(--r-m); background: var(--surface); }
.canal-changes > summary { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 6px; padding: 8px 10px; cursor: pointer; font-size: 13px; color: var(--text-strong); min-height: 44px; }
.canal-changes > summary::-webkit-details-marker { display: none; }
.canal-changes[open] > summary svg { transform: rotate(180deg); }
.canal-changes .history-list { margin: 0 10px 10px; }
.canal-history td { white-space: nowrap; }
.canal-feeds { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.canal-feed { display: flex; gap: 10px; align-items: flex-start; padding: 10px 12px; border: 1px solid var(--line); border-radius: var(--r-m); background: var(--surface); color: var(--text-strong); }
.canal-feed p { margin: 4px 0 0; }
.canal-feed-no { flex: none; display: inline-grid; place-items: center; width: 26px; height: 26px; border-radius: 50%; background: var(--accent-soft); color: var(--accent-strong); font-weight: 800; }
@media (max-width: 720px) {
  .canal-drop { padding: 14px; }
  .canal-drop > label.btn { flex: 1 1 100%; justify-content: center; }
  .canal-dl, .canal-facts { grid-template-columns: 1fr; }
}
.canal-line { display: flex; align-items: center; gap: 6px; }

/* ---------- the required arrival and the transit estimate (web/transit-plan.mjs) ----------
   Display only: never a time of the visit, never the board's order. The
   required arrival is a solid chip; each time of the transit says its kind:
   the agency's estimate in the muted colour over a dashed line, after «≈»;
   the Canal's schedule under its tag «Programa del Canal»; a recorded time
   with its code (TX, ETC, ATD…). Every colour is a pair measured AA in both
   themes (tools/design-tokens.mjs); the pieces wrap between them, never
   inside, so a 320 px phone never scrolls sideways; nothing moves. */
.tp-line { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 3px 6px; min-width: 0; max-width: 100%; font-size: 11.5px; color: var(--text); }
.tp-line .ico { flex: none; }
.badge.tp-req { background: var(--surface-3); color: var(--text-strong); font-weight: 600; white-space: normal; }
.badge.tp-req b { font-weight: 700; white-space: nowrap; }
.badge.tp-late, .badge.tp-ask { white-space: normal; }
.tp-transit { display: inline-flex; align-items: center; gap: 4px; min-width: 0; color: var(--text); }
.tp-vis { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 1px 4px; min-width: 0; }
.tp-t { white-space: nowrap; }
.tp-t b { font-size: 10px; font-weight: 700; letter-spacing: .06em; color: var(--muted); margin-right: 1px; }
.tp-t.k-estimate { color: var(--muted); border-bottom: 1px dashed currentColor; }
.tp-t.k-schedule, .tp-t.k-recorded, .tp-t.k-actual { color: var(--text-strong); }
.tp-t.k-schedule { font-weight: 600; }
.tp-t.k-stays { color: var(--text-strong); }
.tp-sep { color: var(--muted); }
.tp-t .tp-sep { margin: 0 2px; }
.tp-src { display: inline-flex; align-items: center; padding: 0 5px; border-radius: 4px; background: var(--surface-3); color: var(--text-strong); font-size: 10px; font-weight: 700; letter-spacing: .02em; white-space: nowrap; }
/* The full card: under the main time, one piece per line, to the right. */
.card-time .tp-card { display: flex; flex-direction: column; align-items: flex-end; gap: 3px; margin-top: 5px; white-space: normal; text-align: right; }
.card-time .tp-card .tp-vis { justify-content: flex-end; }
/* Narrow windows (900 px and less): the full card's time reads from the
   left (its column moves under the name), and so does the line under it. */
@media (max-width: 900px) {
  .card-time .tp-card { align-items: flex-start; text-align: left; }
  .card-time .tp-card .tp-vis { justify-content: flex-start; }
}
/* The compact card: its own line under the time, beside the drawing. */
.cc-body > .cc-plan { grid-column: 2; }
.arr-row .cc-plan { order: 4; }
/* «⋯» of a card or a row, beside BOOKED. */
.tp-more { align-items: center; }
/* The dossier: the foot of its head, and its section. */
.dossier-hero > .tp-hero { display: flex; flex: 1 0 100%; margin: 0; font-size: 12.5px; }
.canal-dl .tp-wide { grid-column: 1 / -1; }
.tp-why { color: var(--muted); font-size: 12px; }
p.tp-why, .tp-rule, .tp-avg { margin: 3px 0 0; }
.tp-rule, .tp-avg { font-size: 12.5px; color: var(--text); }
.tp-cite { color: var(--muted); }
.tp-notes { margin: 4px 0 0; padding-left: 18px; font-size: 12px; color: var(--text); }
.tp-block .tp-avg { margin-top: 8px; }
.canal-dl .tp-head dd { font-size: 12px; }
@media (max-width: 720px) {
  /* Phones: the line of a booked vessel under the time, small like the chips. */
  .compact-card .cc-plan { order: 4; flex: 1 0 100%; }
  .compact-card .cc-body .tp-line { font-size: 10.5px; line-height: 14px; }
}

/* ---------- «Lista del Canal» (web/canal-list-page.mjs) ----------
   The whole list of every agency, filtered from the pending. Its filters
   are chips (44 px on touch screens: .kpi-chip and .chip-btn are in the
   floor), the table scrolls sideways in its own box when the window is
   narrower than it, with the vessel's name kept in view (never the page),
   phones get the rows as lines (320 px without a sideways scroll), the
   colours are the app's tokens (pairs measured AA in both themes) and
   nothing moves. */
.cl-page { display: grid; gap: 10px; }
.cl-page, .cl-page > *, .cl-tools, .cl-panel-body, .cl-groups, .cl-group, .cl-results { min-width: 0; }
.cl-page > .block-head { margin-bottom: 0; }
.cl-page > .block-head h2 { display: flex; align-items: center; gap: 8px; }
.cl-page > .block-head h2:focus, .cl-results-title:focus { outline: none; }
.cl-page > .block-head h2:focus-visible, .cl-results-title:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }
.cl-intro, .cl-facts, .cl-hint { margin: 0; }
.cl-facts { align-items: center; }
.cl-hint { font-size: 12px; color: var(--muted); }
.cl-note { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; margin: 0; }
.cl-tools { display: grid; gap: 8px; }
.cl-tools[hidden], .cl-bar[hidden] { display: none; }
.cl-find { margin: 0; }
.cl-panel { border: 1px solid var(--line); border-radius: var(--r-m); background: var(--surface); }
.cl-panel > summary { display: flex; align-items: center; gap: 8px; padding: 8px 12px; cursor: pointer; list-style: none; font-weight: 700; color: var(--text-strong); }
.cl-panel > summary::-webkit-details-marker { display: none; }
.cl-panel > summary .chev { margin-left: auto; color: var(--muted); }
.cl-panel[open] > summary .chev { transform: rotate(180deg); }
.cl-panel-n { font-weight: 600; color: var(--muted); }
.cl-panel-body { display: grid; gap: 10px; padding: 2px 12px 12px; }
.cl-groups { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(300px, 100%), 1fr)); gap: 14px 20px; }
.cl-group { display: grid; gap: 6px; align-content: start; }
.cl-group-title { font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.cl-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.kpi-chip.cl-chip { align-items: center; max-width: 100%; white-space: normal; text-align: left; }
.cl-chip .cl-n { font-size: 11.5px; font-weight: 700; color: var(--muted); }
.cl-chip[aria-pressed="true"] .cl-n { color: var(--text-strong); }
.cl-chip:disabled { opacity: .55; cursor: not-allowed; }
.cl-range { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px 10px; }
.cl-range input, .cl-type select, .cl-bar select { min-width: 0; }
.cl-active { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.chip-btn.cl-off { max-width: 100%; white-space: normal; text-align: left; }
.cl-bar { display: flex; flex-wrap: wrap; align-items: end; gap: 8px 12px; }
.cl-bar .field { flex: 0 1 180px; min-width: 0; }
.cl-results { display: grid; gap: 8px; }
.cl-results[aria-busy="true"] .cl-table, .cl-results[aria-busy="true"] .cl-cards { opacity: .65; }
.cl-results-title { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; margin: 0; }
/* «Actualizando…» is always in the heading, shown while the next answer
   comes (the slot's aria-busy): a request never changes the markup, so the
   table is not drawn again (its sideways scroll and its focus stay). */
.cl-busy { display: none; align-items: center; gap: 4px; margin: 0; font-weight: 400; letter-spacing: 0; }
.cl-results[aria-busy="true"] .cl-busy { display: inline-flex; }
.cl-table-wrap { box-shadow: var(--sh-card); }
/* Its box clips the corners: the table itself must not (overflow: hidden
   would make it the box its sticky column sticks to). */
.cl-table { min-width: 1200px; box-shadow: none; overflow: visible; }
.cl-table th { white-space: nowrap; vertical-align: bottom; }
/* The vessel's name stays in view while the table scrolls sideways. */
.cl-table thead th:first-child, .cl-table td.cl-vessel { position: sticky; left: 0; box-shadow: 1px 0 0 var(--line); }
.cl-table thead th:first-child { z-index: 2; background: var(--surface-2); }
.cl-table td.cl-vessel { z-index: 1; min-width: 200px; max-width: 260px; background: var(--surface); }
.cl-stack { display: grid; gap: 2px; justify-items: start; }
.cl-name { display: inline-flex; align-items: center; padding: 0; border: 0; background: transparent; color: var(--text-strong); font: 700 13px/1.3 var(--font); text-align: left; text-decoration: underline; text-decoration-color: var(--line-ctrl); text-underline-offset: 3px; cursor: pointer; overflow-wrap: anywhere; }
.cl-name:hover { text-decoration-color: currentColor; }
.cl-tags { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 3px; }
.cl-sorts { display: inline-flex; flex-wrap: wrap; gap: 2px 10px; }
.cl-sort { display: inline-flex; align-items: center; gap: 3px; padding: 2px 4px; margin: -2px -4px; border: 0; border-radius: 6px; background: transparent; color: inherit; font: inherit; letter-spacing: inherit; text-transform: inherit; cursor: pointer; }
.cl-sort:hover, .cl-sort.on { color: var(--text-strong); }
.cl-sort .ico { opacity: .35; }
.cl-sort.on .ico { opacity: 1; }
.cl-sort.on.asc .ico { transform: rotate(180deg); }
.cl-pager { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 8px 12px; }
.ico.flip { transform: scaleX(-1); }
/* «Tr Flg» in words: a local call (N) stands out by its frame and its word,
   never by colour alone; no flag is dashed and quiet. */
.badge.tr-flag { font-weight: 600; }
.badge.tr-y { color: var(--text-strong); }
.badge.tr-n { background: var(--surface); color: var(--text-strong); box-shadow: inset 0 0 0 1.5px var(--text-strong); font-weight: 700; }
.badge.tr-none { background: transparent; border: 1px dashed var(--line-ctrl); color: var(--muted); }
.badge.tr-other { background: var(--surface); border: 1px solid var(--line-ctrl); color: var(--text-strong); }
.badge.cl-eta-diff { white-space: normal; }
.canal-row-facts { display: flex; flex-wrap: wrap; align-items: center; gap: 2px 8px; }
.canal-search-head .canal-all { margin-left: auto; }
.canal-all-line { margin: 0; }
@media (max-width: 720px) {
  .cl-groups { grid-template-columns: minmax(0, 1fr); }
  .cl-bar .field { flex: 1 1 130px; }
}
@media (pointer: coarse) {
  .cl-name, .cl-sort { min-height: 44px; }
  /* «GT» alone is narrower than a finger: every header that sorts is 44 px
     wide too, without the negative margins that bring its neighbours in. */
  .cl-sort { min-width: 44px; justify-content: center; margin: 0; }
}

/* ---------- the Canal list's health on the board (web/canal-strip.mjs) ----------
   One chip at the end of the filter row: «Lista del Canal · preparada hace
   45 min». Its tone is the list's age, in a colour measured AA on the
   surface and in its words and icon too (never colour alone); under it,
   what is wrong in plain words on the warning fill. On a phone the chip
   keeps one line of the board's header (its words cut with «…», the name
   before the age; the whole text stays its accessible name; beside
   «Contadores y managers» on the narrowest), with the owner's door to
   Ajustes in the same line; 44 px on a touch screen; 320 px never scroll
   sideways; nothing moves. */
.canal-strip { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; margin-left: auto; min-width: 0; max-width: 100%; }
.canal-strip.has-warn { flex: 1 1 100%; margin-left: 0; }
.canal-strip-row { display: flex; align-items: center; gap: 8px; min-width: 0; max-width: 100%; }
.canal-chip { display: inline-flex; flex: 0 1 auto; align-items: center; gap: 6px; min-width: 0; max-width: 100%; min-height: 30px; padding: 4px 12px 4px 9px; border: 1px solid var(--line-ctrl); border-radius: var(--pill); background: var(--surface); color: var(--text-strong); font-size: 12.5px; line-height: 1.2; text-decoration: none; }
a.canal-chip:hover { border-color: var(--accent); }
.canal-chip-ico { flex: none; color: var(--muted); }
.canal-chip-text { display: flex; min-width: 0; white-space: nowrap; }
.canal-chip-text > * { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
/* The age is what the chip is for: the name gives way first (down to
   «Lis…»), and the age is cut only past what is left after it. */
.canal-chip-name { flex: 0 1 auto; font-weight: 700; }
.canal-chip-sep { flex: none; white-space: pre; }
.canal-chip-age { flex: none; max-width: calc(100% - 3.5em); font-weight: 600; }
.canal-chip.tone-fresh { border-color: var(--ok); }
.canal-chip.tone-fresh .canal-chip-ico, .canal-chip.tone-fresh [data-canal-age] { color: var(--ok); }
.canal-chip.tone-old { border-color: var(--warn); }
.canal-chip.tone-old .canal-chip-ico, .canal-chip.tone-old [data-canal-age] { color: var(--warn); }
.canal-chip.tone-stale, .canal-chip.tone-future { border-color: var(--danger); box-shadow: inset 0 0 0 1px var(--danger); }
.canal-chip.tone-stale .canal-chip-ico, .canal-chip.tone-stale [data-canal-age], .canal-chip.tone-future .canal-chip-ico, .canal-chip.tone-future [data-canal-age] { color: var(--danger); }
.canal-chip.tone-none { border-style: dashed; }
/* The owner's door to Ajustes stays beside the chip; the warnings follow. */
.canal-strip-settings { flex: none; white-space: nowrap; }
.canal-warn { flex: 1 1 100%; display: flex; align-items: flex-start; gap: 6px; min-width: 0; margin: 0; padding: 6px 10px; border-left: 3px solid var(--warn); border-radius: var(--r-s); background: var(--warn-soft); color: var(--text-strong); font-size: 12.5px; line-height: 1.35; overflow-wrap: anywhere; }
.canal-warn > .ico { flex: none; margin-top: 1px; color: var(--warn); }
.canal-warn > span { min-width: 0; }
@media (max-width: 720px) {
  .canal-strip { order: 3; flex: 1 1 220px; margin-left: 0; }
  /* A warning, or a list a day old or dated ahead (more words, the owner's
     door beside them): a line of their own, so the age stays in sight. */
  .canal-strip.has-warn, .canal-strip.is-alert { flex-basis: 100%; }
  .canal-strip-settings { min-width: 44px; justify-content: center; }
  .canal-strip-settings .canal-strip-settings-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
}
@media (pointer: coarse) {
  .canal-chip { min-height: 44px; }
}

/* ---------- Ajustes · Lista del Canal: load attempts and transit averages ----------
   (web/canal-panel.mjs attemptsHtml, web/canal-estimates.mjs). The table
   of attempts scrolls in its own box; the classes side by side from 260 px
   each, one under the other on a phone; the start is a 24-hour text field
   (web/time24.mjs), the duration two small numbers. */
.canal-attempts tbody th { color: var(--text-strong); background: var(--surface); font-size: 12.5px; font-weight: 600; letter-spacing: 0; text-transform: none; }
.canal-attempts td { white-space: nowrap; }
.canal-code { color: var(--muted); font-size: 11px; font-weight: 400; overflow-wrap: anywhere; }
.canal-unsigned { margin: 0; font-size: 12.5px; color: var(--text); }
.est-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(260px, 100%), 1fr)); gap: 10px 14px; }
.est-class { display: grid; gap: 8px; align-content: start; min-width: 0; margin: 0; padding: 6px 12px 10px; border: 1px solid var(--line); border-radius: var(--r-m); background: var(--surface); }
.est-class > legend { padding: 0 4px; }
.est-dur { min-width: 0; margin: 0; padding: 0; border: 0; }
.est-dur > legend { padding: 0; margin-bottom: 3px; color: var(--muted); font-size: 11px; text-transform: uppercase; letter-spacing: .06em; }
.est-dur-row { display: flex; flex-wrap: wrap; gap: 6px 14px; }
.est-unit { display: inline-flex; align-items: center; gap: 6px; color: var(--text-strong); font-size: 12.5px; }
.field .est-unit input { width: 5.5em; }
.field input.est-start { max-width: 9em; }
.field > span.hint.est-err { color: var(--danger); font-weight: 600; }
.est-err:empty { display: none; }
.est-preview { margin: 0; color: var(--text); font-size: 12.5px; overflow-wrap: anywhere; }
.est-etd { max-width: 440px; }

/* ---------- Biblioteca del Canal (web/library-page.mjs, web/library-dossier.mjs) ----------
   Only tokens of both themes, in pairs that meet AA on the surfaces they sit
   on (tests/design-system.test.mjs); a kind, a status or a quiz answer is
   told by its icon and its words, never by colour alone. 44 px targets on
   touch screens, one column from 320 px without a horizontal scroll, and
   nothing moves under prefers-reduced-motion. */
.lib-page { max-width: 960px; }
.lib-page, .lib-filters, .lib-content, .lib-content > *, .lib-entry > *, .lib-dossier { min-width: 0; }
.lib-intro { margin: 0 2px 4px; }
.lib-filters { display: grid; gap: 6px; margin: 0 0 12px; }
.lib-filters:empty { display: none; }
.lib-kinds, .lib-topic-list { display: flex; flex-wrap: wrap; gap: 6px; }
.lib-chip { display: inline-flex; align-items: center; gap: 6px; min-height: 34px; padding: 5px 11px; border: 1px solid var(--line); border-radius: var(--pill); background: var(--surface); color: var(--text); font: inherit; font-size: 12.5px; line-height: 1.2; cursor: pointer; transition: border-color var(--d-fast) var(--ease), background var(--d-fast) var(--ease); }
.lib-chip b { font: 800 13px/1 var(--font-display); color: var(--text-strong); }
.lib-chip:hover { border-color: var(--accent); }
.lib-chip[aria-pressed="true"] { border-color: var(--accent); background: var(--accent-soft); color: var(--text-strong); box-shadow: inset 0 0 0 1px var(--accent); }
.lib-topics > summary, .lib-translation > summary { display: inline-flex; align-items: center; gap: 6px; min-height: 34px; padding: 4px 2px; cursor: pointer; color: var(--text-strong); font-size: 13px; font-weight: 600; list-style: none; }
.lib-topics > summary::-webkit-details-marker, .lib-translation > summary::-webkit-details-marker, .lib-faq-item > summary::-webkit-details-marker { display: none; }
.lib-topics[open] > summary .ico, .lib-translation[open] > summary .ico, .lib-faq-item[open] > summary .ico { transform: rotate(180deg); }
.lib-topic-list { padding: 4px 0 2px; }
.lib-content { display: grid; gap: 10px; }
.lib-kind { display: inline-flex; align-items: center; gap: 4px; padding: 2px 7px; border-radius: 6px; background: var(--accent-soft); color: var(--text-strong); font-size: 11px; font-weight: 700; white-space: nowrap; }
.lib-page mark, .lib-dossier mark { background: color-mix(in srgb, var(--gold) 35%, var(--surface)); color: var(--text-strong); border-radius: 3px; padding: 0 1px; }
.lib-page mark.lib-gap { background: var(--warn-soft); color: var(--warn); font-weight: 700; box-shadow: inset 0 -1px 0 var(--warn); }
/* Home: what the library holds, one card per kind. */
.lib-cards { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(min(240px, 100%), 1fr)); gap: 8px; }
.lib-card { display: flex; align-items: flex-start; gap: 10px; width: 100%; height: 100%; padding: 12px; border: 1px solid var(--line); border-radius: var(--r-m); background: var(--surface); color: var(--text); text-align: left; font: inherit; cursor: pointer; }
.lib-card:hover { border-color: var(--accent); }
.lib-card-ico { flex: none; display: inline-grid; place-items: center; width: 36px; height: 36px; border-radius: 10px; background: var(--accent-soft); color: var(--text-strong); }
.lib-card-text { display: grid; gap: 2px; flex: 1; min-width: 0; }
.lib-card-text b { color: var(--text-strong); }
.lib-card-count { flex: none; font: 800 18px/1 var(--font-display); color: var(--text-strong); }
.lib-all-title { margin: 6px 2px 0; }
/* Results. */
.lib-results { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.lib-hit { display: grid; gap: 4px; padding: 10px 12px; border: 1px solid var(--line); border-radius: var(--r-m); background: var(--surface); color: var(--text); text-decoration: none; }
.lib-hit:hover { border-color: var(--accent); }
.lib-hit-head { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; }
.lib-hit-title { color: var(--text-strong); font-size: 14.5px; overflow-wrap: anywhere; }
.lib-snippet { font-size: 13px; color: var(--text); overflow-wrap: anywhere; }
.lib-hit .meta { margin: 0; }
.lib-more { justify-self: start; }
.lib-empty { display: flex; gap: 12px; align-items: flex-start; padding: 14px; border: 1px dashed var(--line-ctrl); border-radius: var(--r-m); background: var(--surface); color: var(--text-strong); }
.lib-empty p { margin: 4px 0 8px; }
.lib-empty .ico { flex: none; }
.lib-group { display: grid; gap: 6px; }
.lib-group .sub-title { margin: 6px 2px 0; }
/* One entry. */
.lib-entry { display: grid; gap: 14px; padding: 14px 16px; border-radius: var(--r-l); background: var(--surface); box-shadow: var(--sh-card); color: var(--text); }
.lib-back { margin: 0; }
.lib-back a { display: inline-flex; align-items: center; gap: 4px; min-height: 32px; color: var(--accent); font-weight: 600; text-decoration: none; }
.lib-back a:hover { text-decoration: underline; }
.ico.lib-flip { transform: scaleX(-1); }
.lib-entry-head { display: grid; gap: 6px; }
.lib-entry-tags { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.lib-tag { display: inline-flex; align-items: center; min-height: 26px; padding: 1px 9px; border: 1px solid var(--line-ctrl); border-radius: var(--pill); color: var(--text-strong); font-size: 12px; text-decoration: none; }
.lib-tag:hover { border-color: var(--accent); }
.lib-adv { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 4px; font-size: 12px; color: var(--text-strong); }
.lib-status-badge { display: inline-flex; padding: 1px 7px; border: 1px solid var(--line-ctrl); border-radius: 6px; color: var(--text-strong); font-size: 11px; font-weight: 700; }
.lib-status-badge.status-vigente { border-color: var(--ok); }
.lib-status-badge.status-pospuesto { border-color: var(--warn); background: var(--warn-soft); color: var(--warn); }
.lib-status-badge.status-reemplazado, .lib-status-badge.status-historico { border-style: dashed; color: var(--muted); }
.lib-entry h3 { margin: 0; font: 800 19px/1.3 var(--font-display); color: var(--text-strong); overflow-wrap: anywhere; }
.lib-entry h3:focus-visible { outline-offset: 4px; }
.lib-lead { margin: 0; font-size: 15px; color: var(--text-strong); overflow-wrap: anywhere; }
.lib-text { display: grid; gap: 8px; font-size: 14px; line-height: 1.55; overflow-wrap: anywhere; }
.lib-text p, .lib-text ul, .lib-faq-body p, .lib-faq-body ul { margin: 0; }
.lib-list { padding-left: 20px; display: grid; gap: 4px; }
.lib-note { display: flex; gap: 8px; align-items: flex-start; margin: 0; padding: 8px 10px; border-left: 3px solid var(--accent); border-radius: var(--r-s); background: var(--surface-2); color: var(--text-strong); }
.lib-note .ico { flex: none; margin-top: 2px; }
.lib-sources, .lib-ships, .lib-related, .lib-lesson, .lib-tpl { display: grid; gap: 6px; padding-top: 10px; border-top: 1px solid var(--line); }
.lib-sources .sub-title, .lib-ships .sub-title, .lib-related .sub-title, .lib-lesson .sub-title, .lib-tpl .sub-title, .lib-dossier .sub-title { display: flex; align-items: center; gap: 6px; margin: 0; }
.lib-sources > .meta, .lib-ships .meta, .lib-tpl > .meta, .lib-dossier > .meta { margin: 0; }
.lib-source-list { margin: 0; padding-left: 20px; display: grid; gap: 8px; }
.lib-source-list li { display: grid; gap: 2px; overflow-wrap: anywhere; }
.lib-source-list b { color: var(--text-strong); }
.lib-source-list .meta { margin: 0; }
.lib-ext { display: inline-flex; align-items: center; gap: 4px; min-height: 24px; color: var(--accent); font-weight: 600; text-decoration: underline; text-underline-offset: 2px; }
.lib-file { display: inline-flex; align-items: center; gap: 4px; color: var(--muted); font-size: 12.5px; }
.lib-ship-list, .lib-rel-list, .lib-readings, .lib-dossier-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 4px; }
.lib-ship { display: flex; align-items: center; gap: 10px; width: 100%; min-height: 44px; padding: 6px 10px; border: 1px solid var(--line); border-radius: 10px; background: var(--surface-2); color: var(--text-strong); text-align: left; font: inherit; cursor: pointer; }
.lib-ship:hover { border-color: var(--accent); }
.lib-ship-main { display: grid; flex: 1; min-width: 0; }
.lib-ship-head { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 6px; min-width: 0; } /* the name and its class chip */
.lib-ship-main .meta { margin: 0; }
/* A list of entries: the kind on the left and the title beside it, wrapping
   in its own column (never under the kind of the next line), one hairline
   between entries. In the dossier the group above names the kind. */
.lib-rel-list a, .lib-readings a, .lib-dossier-list a { display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: start; gap: 8px; min-height: 32px; padding: 5px 0; color: var(--text-strong); text-decoration: none; overflow-wrap: anywhere; }
.lib-dossier-list a { grid-template-columns: minmax(0, 1fr); }
.lib-rel-list li + li, .lib-dossier-list li + li { border-top: 1px solid var(--line); }
.lib-dossier-kind { display: flex; align-items: center; gap: 6px; margin: 10px 0 0; font-size: 11.5px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: var(--muted); }
.lib-dossier-count { padding: 0 6px; border-radius: 999px; background: var(--surface-3); color: var(--text-strong); font-size: 11px; letter-spacing: 0; }
.lib-rel-list a:hover, .lib-readings a:hover, .lib-dossier-list a:hover { text-decoration: underline; }
.lib-readings li { display: flex; flex-wrap: wrap; align-items: center; gap: 2px 10px; }
.lib-readings .meta { margin: 0; align-items: center; }
.lib-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.lib-entry-actions { padding-top: 10px; border-top: 1px solid var(--line); }
.lib-status { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 4px 6px; margin: 0; font-size: 12.5px; color: var(--text-strong); }
.lib-status:empty { display: none; }
.lib-inline-link { color: var(--accent); font-weight: 600; }
.lib-manual-copy { width: 100%; min-height: 120px; padding: 8px; border: 1px solid var(--line-ctrl); border-radius: 8px; background: var(--surface-2); color: var(--text-strong); font: 13px/1.45 var(--mono); }
.lib-copy-buffer { position: fixed; top: 0; left: -9999px; width: 1px; height: 1px; opacity: 0; }
/* A template: the vessel, its data, the message and its actions. */
.lib-tpl-top { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 8px 14px; }
.lib-tpl-top .field { flex: 1 1 260px; min-width: 0; }
.lib-tpl-pick { max-width: 560px; }
.lib-fields { margin: 0; padding: 8px 10px 10px; border: 1px solid var(--line); border-radius: var(--r-m); min-width: 0; }
.lib-fields > legend { padding: 0 4px; font-size: 12px; font-weight: 700; color: var(--text-strong); }
.lib-fields-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(220px, 100%), 1fr)); gap: 8px 12px; }
.lib-caveats { display: grid; gap: 6px; }
.lib-caveats:empty { display: none; }
.lib-preview { display: grid; gap: 6px; padding: 10px 12px; border: 1px solid var(--line-ctrl); border-radius: var(--r-m); background: var(--surface-2); }
.lib-subject { display: grid; gap: 2px; margin: 0; color: var(--text-strong); overflow-wrap: anywhere; }
.lib-subject .meta { margin: 0; }
.lib-mail { margin: 0; white-space: pre-wrap; overflow-wrap: anywhere; font: 13.5px/1.55 var(--font); color: var(--text-strong); }
.lib-missing[hidden] { display: none; }
.lib-translation[open] { display: grid; gap: 6px; }
/* The learning path and its quiz. */
.lib-path { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.lib-step-link { display: flex; align-items: center; gap: 12px; padding: 10px 12px; border: 1px solid var(--line); border-radius: var(--r-m); background: var(--surface); color: var(--text); text-decoration: none; }
.lib-step-link:hover { border-color: var(--accent); }
.lib-step-no { flex: none; display: inline-grid; place-items: center; width: 30px; height: 30px; border-radius: 50%; background: var(--accent-soft); color: var(--text-strong); font-weight: 800; }
.lib-step.done .lib-step-no { background: color-mix(in srgb, var(--ok) 18%, var(--surface)); box-shadow: inset 0 0 0 1px var(--ok); }
.lib-step-main { display: grid; gap: 2px; flex: 1; min-width: 0; }
.lib-step-main b { color: var(--text-strong); }
.lib-step-main .meta { margin: 0; }
.lib-step-sum { font-size: 13px; }
.lib-quiz { display: grid; gap: 10px; }
.lib-q { margin: 0; padding: 10px 12px; border: 1px solid var(--line); border-radius: var(--r-m); min-width: 0; }
.lib-q > legend { padding: 0 4px; font-weight: 700; color: var(--text-strong); }
.lib-opts { display: grid; gap: 4px; }
.lib-opt { display: flex; align-items: center; gap: 8px; min-height: 36px; padding: 4px 8px; border-radius: 8px; color: var(--text-strong); cursor: pointer; }
.lib-opt:hover { background: var(--surface-2); }
.lib-opt:has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 1px; }
.lib-feedback { display: flex; gap: 6px; align-items: flex-start; margin: 6px 0 0; padding: 7px 10px; border-left: 3px solid var(--line-ctrl); border-radius: var(--r-s); background: var(--surface-2); color: var(--text-strong); font-size: 13px; }
.lib-feedback:empty { display: none; }
.lib-feedback .ico { flex: none; margin-top: 2px; }
.lib-feedback.ok { border-left-color: var(--ok); }
.lib-feedback.ok .ico { color: var(--ok); }
.lib-feedback.bad { border-left-color: var(--danger); }
.lib-feedback.bad .ico { color: var(--danger); }
.lib-score { margin: 0; font-weight: 700; color: var(--text-strong); }
/* Glossary A-Z and questions. */
.lib-az { display: flex; flex-wrap: wrap; gap: 4px; }
.lib-az-btn { min-width: 36px; min-height: 36px; padding: 4px 8px; border: 1px solid var(--line-ctrl); border-radius: 8px; background: var(--surface); color: var(--text-strong); font-weight: 700; cursor: pointer; }
.lib-az-btn:hover { border-color: var(--accent); }
.lib-glossary { display: grid; gap: 12px; }
.lib-letter-head { margin: 0 0 4px; font: 800 18px/1.2 var(--font-display); color: var(--text-strong); scroll-margin-top: calc(var(--topbar-h, 56px) + 12px); }
.lib-terms { margin: 0; display: grid; gap: 6px; }
.lib-term { padding: 8px 10px; border: 1px solid var(--line); border-radius: var(--r-m); background: var(--surface); overflow-wrap: anywhere; }
.lib-term dt a { color: var(--text-strong); font-weight: 700; }
.lib-term dd { margin: 2px 0 0; font-size: 13px; color: var(--text); }
.lib-faq { display: grid; gap: 6px; }
.lib-faq-item { border: 1px solid var(--line); border-radius: var(--r-m); background: var(--surface); }
.lib-faq-item > summary { display: flex; align-items: center; gap: 8px; min-height: 44px; padding: 8px 12px; cursor: pointer; color: var(--text-strong); font-weight: 700; list-style: none; overflow-wrap: anywhere; }
.lib-faq-body { display: grid; gap: 8px; padding: 0 12px 12px; overflow-wrap: anywhere; }
.lib-faq-body > .lib-inline-link { justify-self: start; }
/* The block of a dossier (web/library-dossier.mjs): its section's body is a
   grid of 200 px tracks, and the block takes the whole width of it. */
.lib-dossier { display: grid; gap: 6px; }
.group-body > .lib-dossier { grid-column: 1 / -1; }
.lib-dossier-actions { margin: 4px 0 0; }
@media (pointer: coarse) {
  .lib-chip, .lib-az-btn, .lib-tag, .lib-back a, .lib-opt, .lib-ext, .lib-rel-list a, .lib-readings a, .lib-dossier-list a, .lib-topics > summary, .lib-translation > summary, .lib-term dt a, .lib-faq-body > .lib-inline-link { min-height: 44px; }
  .lib-term dt a, .lib-faq-body > .lib-inline-link { display: inline-flex; align-items: center; }
  .lib-az-btn { min-width: 44px; }
}
@media (max-width: 420px) {
  .lib-entry { padding: 12px; }
  .lib-entry h3 { font-size: 17px; }
  .lib-hit, .lib-step-link, .lib-card { padding: 9px 10px; }
  .lib-actions .btn { flex: 1 1 auto; justify-content: center; }
}
@media (prefers-reduced-motion: reduce) {
  .lib-chip { transition: none; }
}
/* ---------- end of Biblioteca del Canal ---------- */
