:root {
  --bg: #ffffff;
  --surface: #f6f8f8;
  --text: #263238;
  --text-2: #5f6f75;
  --teal: #0f766e;
  --teal-hover: #0d9488;
  --teal-light: #e6f4f2;
  --border: #e3e9ea;
  --online: #10897b;
  --amber: #c98a1a;
  --offline: #c0483c;
  --radius: 8px;
  --shadow: 0 1px 2px rgba(38, 50, 56, 0.06), 0 1px 3px rgba(38, 50, 56, 0.05);
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--text);
  font-family: system-ui, -apple-system, 'Segoe UI', Inter, Roboto, sans-serif;
  font-size: 15px;
  line-height: 1.5;
}

a { color: var(--teal); text-decoration: none; }
a:hover { color: var(--teal-hover); text-decoration: underline; }

button {
  font-family: inherit;
  font-size: 14px;
  cursor: pointer;
  border-radius: var(--radius);
  border: 1px solid var(--border);
  background: #fff;
  color: var(--text);
  padding: 9px 16px;
  transition: background 0.12s, border-color 0.12s;
}
button:hover { background: var(--surface); }
button:focus-visible { outline: 2px solid var(--teal); outline-offset: 2px; }

button.primary {
  background: var(--teal);
  border-color: var(--teal);
  color: #fff;
  font-weight: 600;
}
button.primary:hover { background: var(--teal-hover); border-color: var(--teal-hover); }

.hidden { display: none !important; }

/* ---------- Login ---------- */
.login-wrap {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--surface);
  padding: 24px;
}
.login-card {
  background: #fff;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 32px;
  width: 100%;
  max-width: 360px;
}
.login-card h1 {
  margin: 0 0 4px;
  font-size: 20px;
  font-weight: 600;
  color: var(--teal);
}
.login-card p.sub { margin: 0 0 24px; color: var(--text-2); font-size: 13px; }
.field { margin-bottom: 16px; }
.field-row { display: flex; gap: 12px; }
.field-row .field { flex: 1; }
.field label {
  display: block;
  font-size: 13px;
  font-weight: 600;
  margin-bottom: 6px;
  color: var(--text);
}
.field input,
.field select {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  font-size: 15px;
  font-family: inherit;
  color: var(--text);
  background: #fff;
}
.field input:focus-visible,
.field select:focus-visible { outline: 2px solid var(--teal); outline-offset: 0; border-color: var(--teal); }
.error-msg { color: var(--offline); font-size: 13px; margin: 8px 0 0; min-height: 18px; }

/* ---------- Layout ---------- */
.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 24px;
  border-bottom: 1px solid var(--border);
  background: #fff;
  position: sticky;
  top: 0;
  z-index: 10;
}
.brand { display: flex; align-items: baseline; gap: 10px; }
.brand .name { font-weight: 600; font-size: 18px; color: var(--teal); }
.brand .tag { font-size: 12px; color: var(--text-2); }
.topbar .right { display: flex; align-items: center; gap: 14px; }
.conn { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--text-2); }

.dot { width: 9px; height: 9px; border-radius: 50%; display: inline-block; flex: none; }
.dot.online { background: var(--online); }
.dot.offline { background: var(--offline); }
.dot.amber { background: var(--amber); }

main { max-width: 1120px; margin: 0 auto; padding: 24px; }

.section-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 16px;
}
.section-head h2 { margin: 0; font-size: 16px; font-weight: 600; }
.muted { color: var(--text-2); font-size: 13px; }

/* ---------- Cards por sala ---------- */
.cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 16px;
}
.card {
  background: #fff;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 16px;
  cursor: pointer;
  transition: border-color 0.12s, box-shadow 0.12s;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.card:hover { border-color: var(--teal); }
.card:focus-visible { outline: 2px solid var(--teal); outline-offset: 2px; }
.card .card-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 8px; }
.card .room { font-weight: 600; font-size: 16px; }
.card .block { color: var(--text-2); font-size: 13px; margin-top: 2px; }

.badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  font-weight: 600;
  padding: 4px 9px;
  border-radius: 999px;
  white-space: nowrap;
}
.badge.online { background: var(--teal-light); color: var(--online); }
.badge.offline { background: #f7ecea; color: var(--offline); }

.card .count-row { display: flex; align-items: baseline; gap: 8px; }
.card .count { font-size: 28px; font-weight: 600; color: var(--text); line-height: 1; }
.card .count-label { color: var(--text-2); font-size: 13px; }
.card .count.zero { color: var(--text-2); }

.card .card-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  border-top: 1px solid var(--border);
  padding-top: 10px;
  font-size: 12px;
  color: var(--text-2);
}

.empty {
  border: 1px dashed var(--border);
  border-radius: var(--radius);
  padding: 40px;
  text-align: center;
  color: var(--text-2);
  background: var(--surface);
}

/* ---------- Detalhe da sala ---------- */
.back-link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  margin-bottom: 16px;
  background: none;
  border: none;
  padding: 0;
  color: var(--teal);
}
.detail-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  margin-bottom: 20px;
}
.detail-head h2 { margin: 0; font-size: 20px; }
.detail-head .meta { color: var(--text-2); font-size: 13px; margin-top: 4px; }
.detail-actions { display: flex; gap: 10px; flex-wrap: wrap; }

.panel {
  background: #fff;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  margin-bottom: 20px;
  overflow: hidden;
}
.panel h3 {
  margin: 0;
  font-size: 14px;
  font-weight: 600;
  padding: 14px 16px;
  border-bottom: 1px solid var(--border);
  background: var(--surface);
}

table { width: 100%; border-collapse: collapse; font-size: 14px; }
.table-scroll { overflow-x: auto; }
th, td { text-align: left; padding: 10px 16px; border-bottom: 1px solid var(--border); white-space: nowrap; }
th { font-size: 12px; font-weight: 600; color: var(--text-2); text-transform: uppercase; letter-spacing: 0.03em; }
tr:last-child td { border-bottom: none; }
tbody tr:hover { background: var(--surface); }

.type-pill {
  display: inline-block;
  font-size: 12px;
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--teal-light);
  color: var(--teal);
  font-weight: 600;
}
.type-pill.esp32 { background: #eef2f7; color: #4a5b6b; }
.type-pill.unknown { background: var(--surface); color: var(--text-2); }
/* Tipo REAL (RN-13): decidido pelo registro de beacon do maqueiro, não pela
   tecnologia do anúncio — crachá e pulseira são ambos Eddystone. */
.type-pill.paciente { background: var(--teal-light); color: var(--teal); }
.type-pill.maqueiro { background: #eef2f7; color: #4a5b6b; }
.type-pill.desconhecido { background: var(--surface); color: var(--text-2); }
/* RN-13: chamado sem paciente (apoio a sala). */
.type-pill.apoio { background: var(--surface); color: var(--text-2); }

.rssi { font-variant-numeric: tabular-nums; }
.mono { font-family: ui-monospace, 'SF Mono', Menlo, monospace; font-size: 13px; }
.no-rows td { color: var(--text-2); text-align: center; padding: 24px; }

.detail-info {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 4px 24px;
  padding: 16px;
}
.detail-info .k { font-size: 12px; color: var(--text-2); }
.detail-info .v { font-size: 14px; margin-bottom: 8px; }

/* ---------- Tabs (nav) ---------- */
.tabs { display: flex; gap: 4px; }
.tabs .tab {
  border: 1px solid transparent;
  background: none;
  color: var(--text-2);
  font-weight: 600;
  padding: 7px 14px;
}
.tabs .tab:hover { background: var(--surface); color: var(--text); }
.tabs .tab.active {
  background: var(--teal-light);
  color: var(--teal);
  border-color: var(--teal-light);
}

/* ---------- Whitelist ---------- */
.wl-form {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  padding: 16px;
  align-items: center;
}
.wl-form input {
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  font-size: 14px;
  font-family: inherit;
  color: var(--text);
  min-width: 200px;
}
.wl-form input#wl-mac { font-family: ui-monospace, 'SF Mono', Menlo, monospace; }
.wl-form input:focus-visible { outline: 2px solid var(--teal); outline-offset: 0; border-color: var(--teal); }
.wl-form .error-msg { padding: 0 16px; }
.row-actions { display: flex; gap: 8px; justify-content: flex-end; }
.row-actions button { padding: 5px 12px; font-size: 13px; }
.row-actions button.danger { color: var(--offline); border-color: var(--border); }
.row-actions button.danger:hover { background: #f7ecea; border-color: var(--offline); }

/* ---------- Chamados de maqueiro (RN-10) ---------- */
.tab-badge {
  display: inline-block;
  margin-left: 6px;
  min-width: 18px;
  padding: 0 5px;
  border-radius: 999px;
  background: var(--amber);
  color: #fff;
  font-size: 11px;
  font-weight: 600;
  line-height: 18px;
  text-align: center;
}

.card .card-call {
  border-top: 1px solid var(--border);
  padding-top: 12px;
  margin-top: -2px;
}
.call-btn {
  width: 100%;
  font-weight: 600;
  color: var(--teal);
  border-color: var(--border);
}
.call-btn:hover { background: var(--teal-light); border-color: var(--teal); }
.call-btn[disabled] { color: var(--text-2); cursor: default; background: var(--surface); }

.call-note {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 8px;
  font-size: 12px;
  color: var(--text-2);
  border-radius: var(--radius);
  padding: 6px 8px;
  background: var(--surface);
}
.call-note.wait { background: #fbf3e3; color: #8a6212; }
.call-note.ok { background: var(--teal-light); color: var(--online); }
.call-note.err { background: #f7ecea; color: var(--offline); }

.countdown {
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  color: var(--amber);
}
.countdown.big { font-size: 18px; }
.countdown.urgente { color: var(--offline); }

.status-pill {
  display: inline-block;
  font-size: 12px;
  font-weight: 600;
  padding: 2px 9px;
  border-radius: 999px;
  background: var(--surface);
  color: var(--text-2);
}
.status-pill.pendente { background: #fbf3e3; color: #8a6212; }
.status-pill.aceito { background: var(--teal-light); color: var(--online); }
.status-pill.recusado_auto { background: #f7ecea; color: var(--offline); }

td .muted { font-size: 12px; }
.status-pill.aguardando { background: #fbf3e3; color: #8a6212; }
.status-pill.expirado { background: #f7ecea; color: var(--offline); }
.status-pill.cancelado { background: var(--surface); color: var(--text-2); }
.status-pill.concluido { background: var(--teal-light); color: var(--teal); }
/* RN-13: paciente em maos — fase final do transporte, antes da conclusao. */
.status-pill.com_paciente { background: var(--teal-light); color: var(--online); }

/* ---------- RN-11: Quadro de salas ---------- */
.head-actions { display: flex; align-items: center; gap: 14px; }

main { max-width: 1240px; }

/* Zoom do quadro: salas distantes cabem na tela sem perder a posição real. */
.board-wrap { position: relative; }
.board-zoom {
  position: absolute;
  top: 10px; right: 10px;
  z-index: 4;
  display: flex;
  align-items: center;
  gap: 2px;
  padding: 3px;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}
.board-zoom button {
  min-width: 28px;
  height: 26px;
  padding: 0 8px;
  font-size: 14px;
  line-height: 1;
  color: var(--text);
  background: transparent;
  border: 0;
  border-radius: 5px;
  cursor: pointer;
}
.board-zoom button:hover { background: var(--teal-light); color: var(--teal); }
.board-zoom span {
  min-width: 44px;
  text-align: center;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  color: var(--text-2);
}
/* A camada é o que escala; o quadro em si continua do tamanho da tela. */
.board-layer {
  position: absolute;
  top: 0; left: 0;
  width: 100%; height: 100%;
  transform-origin: 0 0;
}

/* A malha existe para ALINHAR sala, então só aparece quando há o que alinhar.
   No modo planta ela era ruído puro em cima de uma tela de leitura. */
.board.editando {
  background-image:
    linear-gradient(to right, rgba(38, 50, 56, 0.045) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(38, 50, 56, 0.045) 1px, transparent 1px);
  background-size: 40px 40px;
}

.board {
  position: relative;
  overflow: hidden;
  min-height: 620px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background-color: var(--surface);
  margin-bottom: 24px;
  touch-action: none;
}
.board.drop-alvo { border-color: var(--teal); box-shadow: inset 0 0 0 1px var(--teal); }
.board-empty {
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  max-width: 380px;
  text-align: center;
  color: var(--text-2);
  font-size: 13px;
  pointer-events: none;
}

.sala-card {
  width: 230px;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 12px 14px;
  display: flex;
  flex-direction: column;
  gap: 9px;
  user-select: none;
  touch-action: none;
}

.sala-card:hover { border-color: var(--teal); }
.sala-card:focus-visible { outline: 2px solid var(--teal); outline-offset: 2px; }
.sala-card.arrastando {
  position: fixed;
  z-index: 50;
  cursor: grabbing;
  border-color: var(--teal);
  box-shadow: 0 8px 20px rgba(38, 50, 56, 0.16);
  opacity: 0.96;
}
.sala-card.sem-gateway { border-style: dashed; }

.sala-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 8px; }
.sala-nome { font-weight: 600; font-size: 15px; line-height: 1.25; cursor: grab; }
.sala-bloco { color: var(--text-2); font-size: 12px; margin-top: 2px; }
.badge.semgw { background: var(--surface); color: var(--text-2); }
.dot.semgw { background: var(--text-2); }

.sala-count { display: flex; align-items: baseline; gap: 7px; }
.sala-count .count { font-size: 22px; font-weight: 600; line-height: 1; }
.sala-count .count.zero { color: var(--text-2); }
.sala-count .count-label { color: var(--text-2); font-size: 12px; }
.sala-count.sem-cobertura { color: var(--offline); font-size: 12px; font-weight: 600; }

.sala-acts { display: flex; flex-wrap: wrap; gap: 6px; border-top: 1px solid var(--border); padding-top: 9px; }
.sala-acts button {
  padding: 4px 9px;
  font-size: 12px;
  color: var(--text-2);
  border-color: var(--border);
}
.sala-acts button:hover { color: var(--teal); border-color: var(--teal); background: var(--teal-light); }
.sala-acts button.danger:hover { color: var(--offline); border-color: var(--offline); background: #f7ecea; }
.sala-card .call-btn { padding: 6px 10px; font-size: 13px; }
.sala-card .call-btn[disabled] { color: var(--text-2); border-color: var(--border); background: var(--surface); }

.sala-pos { font-size: 11px; color: var(--text-2); font-variant-numeric: tabular-nums; }

/* Faixa "não posicionadas" */
.unpos {
  border: 1px dashed var(--border);
  border-radius: var(--radius);
  background: #fff;
  padding: 14px 16px;
  margin-bottom: 24px;
}
.unpos.vazia { display: none; }
.unpos-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin-bottom: 12px; }
.unpos-head h3 { margin: 0; font-size: 14px; font-weight: 600; }
.unpos-list { display: flex; flex-wrap: wrap; gap: 12px; }

/* Gateways sem sala */
.gw-livres { padding: 4px 0; }
.gw-livre {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  padding: 11px 16px;
  border-bottom: 1px solid var(--border);
}
.gw-livre:last-child { border-bottom: none; }
.gw-livre .gw-id { font-weight: 600; font-size: 14px; }
.gw-livre .gw-meta { font-size: 12px; color: var(--text-2); }
.gw-livre .gw-meta .mono { font-size: 12px; }
.gw-livre .row-actions { justify-content: flex-start; }
.gw-vazio { padding: 18px 16px; color: var(--text-2); font-size: 13px; }

/* ---------- Modal ---------- */
.modal-wrap {
  position: fixed;
  inset: 0;
  background: rgba(38, 50, 56, 0.35);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  z-index: 100;
}
.modal {
  background: #fff;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: 0 10px 30px rgba(38, 50, 56, 0.18);
  width: 100%;
  max-width: 460px;
  max-height: 82vh;
  display: flex;
  flex-direction: column;
}
.modal-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 16px;
  border-bottom: 1px solid var(--border);
  background: var(--surface);
  border-radius: var(--radius) var(--radius) 0 0;
}
.modal-head h3 { margin: 0; font-size: 15px; font-weight: 600; }
.icon-btn { border: none; background: none; font-size: 20px; line-height: 1; padding: 2px 8px; color: var(--text-2); }
.icon-btn:hover { background: var(--border); }
.modal-body { padding: 16px; overflow-y: auto; }
.modal-body .field:last-of-type { margin-bottom: 20px; }
.modal-actions { display: flex; justify-content: flex-end; gap: 10px; }
.modal-hint { color: var(--text-2); font-size: 13px; margin: 0 0 14px; }

.gw-opcoes { display: flex; flex-direction: column; gap: 8px; margin-bottom: 16px; }
.gw-opcao {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 10px 12px;
  text-align: left;
  width: 100%;
  background: #fff;
}
.gw-opcao:hover { border-color: var(--teal); background: var(--teal-light); }
.gw-opcao .gw-id { font-weight: 600; font-size: 14px; }
.gw-opcao .gw-meta { font-size: 12px; color: var(--text-2); margin-top: 2px; }

/* ---------- Mapa isométrico (RN-14) ----------------------------------------
   TEMA CLARO, conversando com o dashboard da §8: fundo claro, caixas em
   azul-acinzentado suave com profundidade, piso das salas com tinta bem leve e
   paredes MAIS CLARAS que o piso. As três cores do avatar são as da RN-14:
   VERDE = livre · ÂMBAR = a caminho do chamado · AZUL = em transporte.      */
.mapa-surface {
  --m-bg: #eef1f8;          /* fundo da maquete (claro) */
  --m-panel: #ffffff;       /* placas, pastilhas, núcleo dos ícones */
  --m-panel-2: #e9eff9;     /* piso das salas: tinta bem leve */
  --m-line: #e1e6f0;
  --m-wall: #c3cee0;        /* traço de contorno (azul-acinzentado) */
  --m-wall-2: #f7fafe;      /* topo das paredes: MAIS CLARO que o piso */
  --m-text: #161d2e;
  --m-muted: #5b6478;
  --m-muted-2: #94a0b8;
  --m-blue: #2f6fe4;        /* rádio BLE / gateway */
  --m-livre: #10897b;       /* verde (mesmo verde-teal do status da §8) */
  --m-chamado: #c8791e;     /* âmbar */
  --m-transporte: #2f6fe4;  /* azul */
  --m-paciente: #b8547f;
  --m-off: #c0483c;

  background: var(--m-bg);
  border: 1px solid #dde3ee;
  border-radius: 12px;
  padding: 14px 14px 12px;
  box-shadow: 0 1px 2px rgba(38, 50, 56, 0.06), 0 8px 24px rgba(20, 30, 60, 0.08);
}
.mapa-top {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0 4px 10px;
}
.mapa-title {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11px;
  letter-spacing: 0.06em;
  color: var(--m-muted);
}
.mapa-live {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 10.5px;
  color: var(--m-livre);
}
.mapa-pulse {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--m-livre);
  animation: mapa-blink 1.8s infinite;
}
@keyframes mapa-blink { 0%, 100% { opacity: 1 } 50% { opacity: 0.25 } }

.mapa-svg {
  display: block;
  width: 100%;
  height: auto;
  min-height: 260px;
  border-radius: 9px;
  background:
    linear-gradient(180deg, rgba(47, 111, 228, 0.05), transparent 55%),
    radial-gradient(ellipse at 50% 38%, rgba(47, 111, 228, 0.07), transparent 62%);
  touch-action: none;   /* o arrasto é nosso (pointer events) */
}
/* Mapa 3D (WebGL) — mesma área do SVG, alternado pelo toggle.
   No modo 3D o SVG some com !important: vence qualquer re-render do app.js
   (que faz svg.remove('hidden')), senão 2D e 3D apareciam empilhados. */
#view-mapa.modo-3d #mapa-svg,
#view-mapa.modo-3d #mapa-vazio { display: none !important; }
#view-mapa:not(.modo-3d) #mapa3d-wrap { display: none !important; }
.mapa-top-dir { display: flex; align-items: center; gap: 12px; }
.mapa-3d-btn {
  font: 600 12px ui-monospace, Menlo, monospace;
  color: var(--m-text, #1e2637); background: var(--m-panel, #fff);
  border: 1px solid var(--m-wall, #c3cee0); border-radius: 8px;
  padding: 6px 12px; cursor: pointer; letter-spacing: 0.02em;
}
.mapa-3d-btn:hover { border-color: var(--m-blue, #2f6bd6); }
.mapa-3d-btn[aria-pressed="true"] { background: var(--m-blue, #2f6bd6); color: #fff; border-color: var(--m-blue, #2f6bd6); }
.mapa3d-wrap {
  width: 100%; height: 540px; border-radius: 9px; overflow: hidden;
  background: linear-gradient(180deg, #eef3fb, #e4ebf6);
  touch-action: none; cursor: grab; position: relative;
}
.mapa3d-wrap canvas { display: block; width: 100% !important; height: 100% !important; }
/* Travado prende as salas, não a câmera: o cursor segue 'grab' porque o arrasto
   para girar a vista continua valendo. */

/* RN-17 — COMO LEVAR: maca ou cadeira de rodas.
   Dois botões lado a lado, sem padrão escolhido: a decisão fica visível e
   deliberada, porque é ela que manda o maqueiro pegar um equipamento ou outro
   antes de sair. */
/* Os seletores carregam `.mod-escolha` na frente de propósito. Dentro de um
   `.field` do modal, `.field label` e `.field input` são mais específicos que
   uma classe sozinha: o rótulo virava bloco e o rádio esticava a 100% com o
   padding de campo de texto, jogando a bolinha para cima do nome. Empatar em
   especificidade e vir depois no arquivo resolve sem !important. */
.mod-escolha { display: flex; gap: 6px; }
.mod-escolha .mod-op {
  flex: 1; display: flex; align-items: center; justify-content: center; gap: 7px;
  border: 1px solid var(--border); border-radius: 7px;
  margin: 0; padding: 9px 10px; cursor: pointer;
  font: 600 12px ui-monospace, Menlo, monospace; color: var(--text);
  background: #fff; user-select: none;
}
.mod-escolha .mod-op:hover { border-color: var(--teal); color: var(--teal); }
.mod-escolha .mod-op input {
  flex: 0 0 auto;
  width: auto; margin: 0; padding: 0;
  accent-color: var(--teal);
}
/* :has é o que permite pintar o rótulo a partir do rádio dentro dele, sem JS
   para espelhar o estado marcado numa classe. */
.mod-escolha .mod-op:has(input:checked) {
  background: var(--teal-light); border-color: var(--teal); color: var(--teal);
}
.mod-escolha.inativo { opacity: 0.45; }
.mod-escolha.inativo .mod-op { cursor: not-allowed; }
.mod-escolha.inativo .mod-op:hover { border-color: var(--border); color: var(--text); }

/* BARRA DE EDIÇÃO — a mesma no quadro de salas e no topo do mapa.
   Trava à esquerda; setas, Salvar e Descartar só aparecem quando há algo
   pendente para navegar. */
.edit-bar { display: inline-flex; align-items: center; gap: 4px; }
.eb-btn {
  font: 600 12px ui-monospace, Menlo, monospace;
  color: var(--text); background: #fff;
  border: 1px solid var(--border); border-radius: 7px;
  padding: 5px 9px; cursor: pointer; line-height: 1.2;
}
.eb-btn:hover:not(:disabled) { border-color: var(--teal); color: var(--teal); }
.eb-btn:disabled { opacity: 0.45; cursor: not-allowed; }
.eb-trava[aria-pressed="true"] { background: var(--surface); color: var(--text-2); }
.eb-trava[aria-pressed="false"] { background: #fdeee0; border-color: var(--amber); color: #8a5a10; }
.eb-salvar:not(:disabled) {
  background: var(--teal); border-color: var(--teal); color: #fff;
}
.eb-salvar:not(:disabled):hover { background: var(--teal-hover); border-color: var(--teal-hover); color: #fff; }

/* ÍNDICE LATERAL — a lista de salas e maqueiros que serve aos DOIS mapas.
   Mora dentro da .mapa-surface, então acompanha a tela cheia. */
.mapa-corpo { display: flex; gap: 12px; align-items: stretch; }
.mapa-palco { flex: 1; min-width: 0; position: relative; }
.mapa-indice {
  flex: none; width: 212px; max-height: 540px;
  display: flex; flex-direction: column; gap: 7px;
  background: var(--m-panel); border: 1px solid #dde3ee;
  border-radius: 10px; padding: 8px;
}
.mapa-indice-busca {
  width: 100%; box-sizing: border-box;
  font: 600 11.5px ui-monospace, Menlo, monospace;
  color: var(--m-text); background: var(--m-bg);
  border: 1px solid var(--m-wall); border-radius: 7px; padding: 5px 8px;
}
.mapa-indice-busca:focus { outline: 2px solid var(--teal); outline-offset: -1px; }
.mapa-indice-lista { overflow-y: auto; min-height: 0; }
/* Cabeçalho de grupo — é um botão: clicar recolhe. */
.mi-grupo {
  display: flex; align-items: center; gap: 6px; width: 100%;
  font: 700 9.5px ui-monospace, Menlo, monospace; letter-spacing: 0.08em;
  color: var(--m-muted-2); text-transform: uppercase; text-align: left;
  border: 0; background: none; cursor: pointer;
  padding: 8px 6px 3px; margin-top: 2px;
}
.mi-grupo:hover { color: var(--teal); }
.mi-seta { flex: none; font-size: 9px; width: 8px; }
.mi-conta {
  margin-left: auto; flex: none;
  font-size: 9px; color: var(--m-muted-2);
  background: var(--m-bg); border-radius: 999px; padding: 1px 6px;
}
.mi-item {
  display: flex; align-items: center; gap: 7px;
  padding: 5px 7px; border-radius: 7px; cursor: pointer;
  font: 600 11.5px ui-monospace, Menlo, monospace; color: var(--m-text);
  border: 0; background: none; width: 100%; text-align: left;
}
.mi-item:hover { background: var(--teal-light); }
.mi-item[aria-current="true"] { background: var(--teal); color: #fff; }
.mi-item[aria-current="true"] .mi-meta { color: #cfe8e3; }
.mi-ic { width: 15px; height: 15px; flex: none; }
.mi-nome { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mi-meta { margin-left: auto; flex: none; font-size: 9.5px; color: var(--m-muted-2); }
.mi-ponto { width: 7px; height: 7px; border-radius: 50%; flex: none; }
.mi-vazio { padding: 10px 7px; font-size: 11px; color: var(--m-muted-2); }

/* SUBMENU do selecionado — ao lado do índice. Só aparece com algo selecionado,
   senão roubaria largura do mapa o tempo todo. */
.mapa-detalhe {
  position: relative;   /* âncora do × de fechar */
  flex: none; width: 252px; max-height: 540px; overflow-y: auto;
  display: flex; flex-direction: column; gap: 9px;
  background: var(--m-panel); border: 1px solid #dde3ee;
  border-radius: 10px; padding: 11px;
}
.mapa-detalhe.hidden { display: none; }
/* Mesmo × do painel do 3D: fechar é o mesmo gesto nos dois lugares. */
.md-x {
  position: absolute; top: 5px; right: 7px; border: 0; background: none;
  font-size: 19px; line-height: 1; color: #6b7a95; cursor: pointer; padding: 2px 6px;
}
.md-x:hover { color: var(--m-text); }
.md-tit {
  font: 700 14px ui-monospace, Menlo, monospace; color: var(--m-text);
  display: flex; align-items: center; gap: 7px; margin: 0 22px 0 0;
}
.md-tit .mi-ic { width: 17px; height: 17px; color: var(--teal); }
.md-sub { font: 600 10.5px ui-monospace, Menlo, monospace; color: var(--m-muted-2); letter-spacing: 0.04em; }
.md-badge {
  align-self: flex-start; font: 700 9.5px ui-monospace, Menlo, monospace;
  letter-spacing: 0.06em; text-transform: uppercase;
  padding: 3px 7px; border-radius: 5px; background: var(--m-bg); color: var(--m-muted);
}
.md-badge.ok { background: #e3f4f1; color: var(--m-livre); }
.md-badge.alerta { background: #fdeee0; color: var(--m-chamado); }
.md-badge.erro { background: #fbe9e7; color: var(--m-off); }
.md-badge.azul { background: #e7eefb; color: var(--m-blue); }
.md-grupo {
  font: 700 9.5px ui-monospace, Menlo, monospace; letter-spacing: 0.08em;
  color: var(--m-muted-2); text-transform: uppercase; margin-top: 2px;
}
.md-pessoa {
  display: flex; align-items: center; gap: 7px;
  font: 600 11.5px ui-monospace, Menlo, monospace; color: var(--m-text);
  padding: 4px 6px; border-radius: 6px; background: var(--m-bg);
}
.md-pessoa .mi-ic { width: 13px; height: 13px; color: var(--m-paciente); }
.md-pessoa .mi-meta { font-size: 9.5px; }
.md-linhas { display: grid; grid-template-columns: auto 1fr; gap: 4px 10px; margin: 0; }
.md-linhas dt { font-size: 10.5px; color: var(--m-muted-2); }
.md-linhas dd { margin: 0; font: 600 11px ui-monospace, Menlo, monospace; color: var(--m-text); word-break: break-word; }
.md-acoes { display: flex; flex-direction: column; gap: 6px; margin-top: 3px; }
.md-acoes button {
  font: 700 11.5px ui-monospace, Menlo, monospace;
  padding: 7px 10px; border-radius: 7px; cursor: pointer;
  border: 1px solid var(--teal); background: var(--teal); color: #fff;
}
.md-acoes button.secundario { background: var(--m-panel); color: var(--m-text); border-color: var(--m-wall); }
.md-acoes button:hover:not(:disabled) { filter: brightness(1.07); }
.md-acoes button:disabled { opacity: 0.5; cursor: not-allowed; }
.md-vazio { font-size: 11px; color: var(--m-muted-2); line-height: 1.4; }
.md-rotulo {
  font: 700 9.5px ui-monospace, Menlo, monospace; letter-spacing: 0.06em;
  color: var(--m-muted-2); text-transform: uppercase; margin-top: 2px;
}
.md-campo {
  width: 100%; box-sizing: border-box;
  font: 600 11px ui-monospace, Menlo, monospace; color: var(--m-text);
  background: var(--m-bg); border: 1px solid var(--m-wall);
  border-radius: 7px; padding: 6px 7px;
  /* O select fechado corta no meio da palavra quando o rótulo não cabe; as
     reticências deixam claro que há mais texto (e o title mostra inteiro). */
  text-overflow: ellipsis;
}
.md-campo:focus { outline: 2px solid var(--teal); outline-offset: -1px; }
.mapa-detalhe .error-msg { font-size: 11px; margin: 0; }

/* Telas estreitas: o índice deixa de roubar largura do mapa e vira uma tira
   rolável em cima dele. */
@media (max-width: 880px) {
  .mapa-corpo { flex-direction: column; }
  .mapa-indice { width: auto; max-height: 168px; }
  .mapa-detalhe { width: auto; max-height: 260px; }
}

/* TELA CHEIA — vale para o 2D e para o 3D, porque quem vai a tela cheia é a
   .mapa-surface inteira (ver o botão em .mapa-top-dir).
   A superfície vira uma coluna: a barra do topo fica com a altura dela e o
   corpo (índice + mapa) toma o resto. Sem isso valeriam as alturas fixas de
   tela normal (540px no 3D, proporção do viewBox no 2D) e sobraria tarja preta,
   que é a cor com que o navegador pinta o fundo do :fullscreen. */
.mapa-surface:fullscreen {
  display: flex; flex-direction: column;
  width: 100vw; height: 100vh;
  box-sizing: border-box; border-radius: 0;
}
/* `min-height: 0` destrava o encolhimento: item de flex não encolhe abaixo do
   conteúdo por padrão, e sem isto o mapa estouraria a altura da tela. */
.mapa-surface:fullscreen .mapa-corpo { flex: 1; min-height: 0; }
.mapa-surface:fullscreen .mapa-indice,
.mapa-surface:fullscreen .mapa-detalhe { max-height: none; }
.mapa-surface:fullscreen .mapa3d-wrap,
.mapa-surface:fullscreen .mapa-svg,
.mapa-surface:fullscreen .mapa-vazio {
  height: 100%; min-height: 0;
}
/* Controles de câmera do 3D — canto superior esquerdo, fora do caminho do card. */
.m3d-cam {
  position: absolute; left: 14px; top: 14px; z-index: 5;
  display: flex; align-items: center; gap: 3px;
  padding: 3px; border-radius: 9px;
  background: rgba(255, 255, 255, 0.95);
  border: 1px solid #46587a33;
  box-shadow: 0 4px 14px rgba(20, 30, 50, 0.12);
}
.m3d-cam button {
  font: 600 12px ui-monospace, Menlo, monospace;
  color: #1e2637; background: transparent;
  border: 0; border-radius: 6px; padding: 5px 9px; cursor: pointer;
  min-width: 28px; line-height: 1.2;
}
.m3d-cam button:hover { background: #e7eefb; color: #2f6bd6; }
/* Dica do teclado: discreta, mas presente — deslocar a câmera pelas setas não
   se descobre sozinho, e era o que faltava para a navegação não depender só do
   arrasto do mouse. */
.m3d-dica {
  font: 600 10.5px ui-monospace, Menlo, monospace;
  color: #7a88a0; padding: 0 7px 0 4px; cursor: help; white-space: nowrap;
}
.m3d-cam button[aria-pressed="true"] { background: #2f6bd6; color: #fff; }
/* Painel de detalhes do item selecionado — canto inferior direito do 3D */
.m3d-info {
  position: absolute; right: 14px; bottom: 14px; z-index: 5;
  width: 290px; max-height: calc(100% - 28px); overflow: auto;
  background: rgba(255, 255, 255, 0.97); border: 1px solid #46587a55;
  border-radius: 10px; padding: 14px 16px 12px;
  box-shadow: 0 8px 26px rgba(20, 30, 50, 0.18);
  font-size: 12.5px; color: #16243c; cursor: default;
}
.m3d-info.hidden { display: none; }
.m3d-info-x {
  position: absolute; top: 6px; right: 8px; border: 0; background: none;
  font-size: 19px; line-height: 1; color: #6b7a95; cursor: pointer; padding: 2px 6px;
}
.m3d-info-x:hover { color: #16243c; }
.m3d-tit { font: 700 15px ui-monospace, Menlo, monospace; color: #080d18; margin: 0 20px 2px 0; }
.m3d-sub { font: 600 11.5px ui-monospace, Menlo, monospace; letter-spacing: .04em; margin-bottom: 10px; }
.m3d-info dl { display: grid; grid-template-columns: auto 1fr; gap: 5px 12px; margin: 0; }
.m3d-info dt { color: #63708a; font-size: 11.5px; }
.m3d-info dd { margin: 0; color: #16243c; font-weight: 600; font-size: 12px; word-break: break-word; }
.mapa-vazio {
  color: var(--m-muted);
  font-size: 13px;
  text-align: center;
  padding: 34px 16px;
}
.mapa-vazio strong { color: var(--m-text); font-weight: 600; }

/* Piso / paredes / plataforma */
.m-plinth-top { fill: url(#m-slab-top); }
.m-plinth-side { fill: url(#m-plinth); }
/* Sombra de contato: descola a sala da laje (borrada pelo filtro #m-soft). */
.m-contact { fill: #33415a; opacity: 0.20; }
/* Piso da sala: brilho radial suave em vez de tinta chapada. */
.m-tile { fill: url(#m-floor); stroke: var(--m-wall); stroke-width: 1.1; stroke-linejoin: round; }
.m-tile.corr { fill: #e7edf7; stroke: #d3dcea; }
.m-tile.sem-cobertura { fill: #edeff3; stroke: var(--m-muted-2); stroke-dasharray: 5 4; }
.m-tile.offline { fill: #f1edee; }
.m-tile.arrastando { stroke: var(--m-blue); stroke-width: 2.4; }
/* RN-15: sala de DESTINO destacada enquanto há transporte a caminho. */
.m-tile.destino { fill: #e8f0fe; stroke: var(--m-transporte); stroke-width: 2.4; }
/* Ladrilho isométrico do piso (linhas quase invisíveis, dão textura de chão). */
.m-floor-grid { fill: none; stroke: #8ea1bd; stroke-width: 0.6; opacity: 0.16; }
.m-wall-top { fill: url(#m-wall-top); stroke: var(--m-wall); stroke-width: 0.5; }
.m-wall-side { fill: url(#m-wall-side); }
.m-wall-side.v { fill: url(#m-wall-side-v); }
.m-corr-lbl {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 10px; fill: var(--m-muted-2); letter-spacing: 0.22em;
}
.m-bed { color: var(--m-muted-2); opacity: 0.5; }

/* Placa com o nome da sala */
.m-plate { fill: var(--m-panel); stroke: var(--m-wall); stroke-width: 1.1; }
.m-plate-nome {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11.5px; font-weight: 700; fill: var(--m-text);
}
.m-plate-meta {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 8.5px; fill: var(--m-muted-2); letter-spacing: 0.04em;
}

/* RÓTULOS (camada .m-rotulos, desenhada por último).
   Antes as placas iam para a camada do piso e o pino do gateway e os avatares
   passavam por cima do texto: "Tomografia" aparecia como "mografia". Agora o
   texto é sempre o último a ser desenhado.
   Sempre visível é só o CHIP: ícone + número/nome curto. A placa cheia (bloco,
   presentes, quem está dentro) aparece apenas no item selecionado — com uma
   sala por leito, mostrar tudo de uma vez empilha rótulo sobre rótulo. */
.m-chip { fill: var(--m-panel); stroke: var(--m-wall); stroke-width: 1; }
.m-chip.sel { stroke: var(--teal); stroke-width: 1.7; }
.m-chip-t {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 10.5px; font-weight: 700; fill: var(--m-text);
}
.m-chip-t.sel { fill: var(--teal); }
.m-chip-ic { color: var(--m-muted-2); }
.m-chip-ic.sel { color: var(--teal); }
/* Linhas de gente dentro do balão da sala selecionada. */
.m-plate-pessoa {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 9.5px; font-weight: 600; fill: var(--m-text);
}
.m-plate-pessoa.pac { fill: var(--m-paciente); }
.m-plate-pessoa.maq { fill: var(--m-livre); }
/* Contorno do item selecionado: o piso da sala acende no perímetro dela. */
.m-sel-halo {
  fill: none; stroke: var(--teal); stroke-width: 2.2;
  stroke-linejoin: round; opacity: 0.95;
}
.m-av-sel { fill: none; stroke: var(--teal); stroke-width: 2.2; }

/* Gateway no teto */
.m-gw-mount { stroke: var(--m-blue); stroke-width: 1.2; stroke-dasharray: 3 4; opacity: 0.42; }
.m-gw-mount.off { stroke: var(--m-muted-2); opacity: 0.28; }
.m-gw-box { fill: var(--m-panel); stroke: var(--m-blue); stroke-width: 1.8; }
.m-gw-box.off { stroke: var(--m-off); }
.m-gw-box.sem { stroke: var(--m-muted-2); stroke-dasharray: 3 3; }
.m-gw-ic { color: var(--m-blue); }
.m-gw-ic.off { color: var(--m-off); }
.m-gw-ic.sem { color: var(--m-muted-2); }
.m-gw-cover { fill: var(--m-blue); opacity: 0.05; }
.m-rf {
  fill: none; stroke: var(--m-blue); stroke-width: 2;
  transform-box: fill-box; transform-origin: center;
  animation: mapa-rf 2.4s ease-out infinite;
}
/* Pulso de rádio BLE no PISO (círculo suave sob o gateway). */
.m-rf-piso {
  fill: none; stroke: var(--m-blue); stroke-width: 1.6;
  transform-box: fill-box; transform-origin: center;
  animation: mapa-rf-piso 3s ease-out infinite;
}
@keyframes mapa-rf {
  0%   { transform: scale(0.18); opacity: 0.42; }
  100% { transform: scale(1);    opacity: 0; }
}
@keyframes mapa-rf-piso {
  0%   { transform: scale(0.12); opacity: 0.34; }
  100% { transform: scale(1);    opacity: 0; }
}

/* Pacientes na sala */
.m-pac-core { fill: var(--m-panel); stroke: var(--m-paciente); stroke-width: 2; }
.m-pac-ic { color: var(--m-paciente); }
.m-pac-lbl {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 8.5px; fill: var(--m-muted);
}

/* Avatar do maqueiro — VERDE livre · ÂMBAR a caminho · AZUL em transporte */
.m-av-shadow { fill: url(#m-shadow); }
.m-av-stem { stroke: var(--m-muted-2); stroke-width: 2; opacity: 0.55; }
.m-av-ring { fill: none; stroke-width: 3.4; stroke: var(--m-livre); }
.m-av-core { fill: var(--m-livre); stroke: var(--m-panel); stroke-width: 3; }
.m-av-ic { color: #fff; }
.m-av.e-a_caminho .m-av-ring { stroke: var(--m-chamado); }
.m-av.e-a_caminho .m-av-core { fill: var(--m-chamado); }
.m-av.e-em_transporte .m-av-ring { stroke: var(--m-transporte); }
.m-av.e-em_transporte .m-av-core { fill: var(--m-transporte); }
/* Nenhum gateway o ouve AGORA, mas faz menos de 5 min (RN-14): está em trânsito
   pelo corredor. Mantém a cor do estado — ele continua trabalhando — e só marca
   o anel tracejado: "esta posição não está sendo medida neste instante". */
.m-av.sem-sinal .m-av-ring { stroke-dasharray: 4 4; }
/* CINZA (RN-14): 5 min sem nenhum gateway ouvi-lo, ou crachá sem heartbeat. Não
   está disponível NEM localizável, então perde a cor de estado — não pode ser
   confundido com um maqueiro livre.
   Cinza é diferente de invisível: a 0.38 de opacidade no tema claro ele sumia do
   mapa e ninguém percebia que havia um maqueiro perdido. Fica opaco o bastante
   para ser LIDO, e o cinza é que o manda para o segundo plano. */
.m-av.offline { opacity: 0.85; }
.m-av.offline .m-av-shadow { opacity: 0.35; }
.m-av.offline .m-av-ring { stroke: var(--m-muted); stroke-dasharray: 3 4; }
.m-av.offline .m-av-core { fill: var(--m-muted-2); }
.m-av.offline .m-av-chip-t { fill: var(--m-muted); }
.m-av.offline .m-carga-lbl { fill: var(--m-muted); }
.m-av-chip { fill: var(--m-panel); stroke: var(--m-line); stroke-width: 1; }
.m-av-chip-t {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 10px; font-weight: 700; fill: var(--m-text);
}
/* Segundo corpo: o paciente em mãos (fase com_paciente da RN-13) */
.m-carga-link { stroke: var(--m-paciente); stroke-width: 2; stroke-dasharray: 2 3; opacity: 0.75; }
.m-carga-core { fill: var(--m-panel); stroke: var(--m-paciente); stroke-width: 2.4; }
.m-carga-ic { color: var(--m-paciente); }
.m-carga-lbl {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 9px; font-weight: 700; fill: var(--m-paciente);
}
/* Trajeto PONTILHADO até o alvo */
.m-rota {
  fill: none; stroke-width: 3.2; stroke-linecap: round; stroke-linejoin: round;
  stroke-dasharray: 1 9; opacity: 0.9;
  animation: mapa-dash 1s linear infinite;
}
.m-rota.e-a_caminho { stroke: var(--m-chamado); }
.m-rota.e-em_transporte { stroke: var(--m-transporte); }
.m-rota.e-livre { stroke: var(--m-muted-2); }
@keyframes mapa-dash { to { stroke-dashoffset: -20; } }

/* Badge de ETA sobre o avatar a caminho ("ETA 7s") */
.m-eta-pill { fill: var(--m-chamado); }
.m-eta-pill.e-em_transporte { fill: var(--m-transporte); }
.m-eta-txt {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 10px; font-weight: 700; fill: #fff;
}

@media (prefers-reduced-motion: reduce) {
  .m-rf, .m-rf-piso, .m-rota, .mapa-pulse { animation: none; }
}

/* Legenda discreta */
.mapa-legenda {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 16px;
  padding: 12px 4px 2px;
  font-size: 11.5px;
  color: var(--m-muted);
}
.mapa-legenda .lg-dot {
  display: inline-block;
  width: 9px; height: 9px;
  border-radius: 50%;
  border: 2px solid var(--m-livre);
  margin-right: 6px;
  vertical-align: -1px;
}
.mapa-legenda .lg-dot.chamado { border-color: var(--m-chamado); }
.mapa-legenda .lg-dot.transporte { border-color: var(--m-transporte); }
.mapa-legenda .lg-dot.paciente { border-color: var(--m-paciente); }
.mapa-legenda .lg-gw {
  display: inline-block;
  width: 12px; height: 8px;
  border: 1.5px solid var(--m-blue);
  border-radius: 2px;
  margin-right: 6px;
  vertical-align: 0;
}
.mapa-legenda .lg-gw.off { border-color: var(--m-muted-2); border-style: dashed; }
.mapa-legenda .lg-sep { width: 1px; height: 12px; background: var(--m-line); }

/* ---------- Toast ---------- */
.toast {
  position: fixed;
  right: 20px;
  bottom: 20px;
  background: var(--text);
  color: #fff;
  font-size: 13px;
  padding: 9px 14px;
  border-radius: var(--radius);
  box-shadow: 0 6px 18px rgba(38, 50, 56, 0.22);
  z-index: 200;
  opacity: 1;
  transition: opacity 0.25s;
}
.toast.saindo { opacity: 0; }
.toast.erro { background: var(--offline); }

@media (max-width: 600px) {
  main { padding: 16px; }
  .topbar { padding: 12px 16px; flex-wrap: wrap; gap: 8px; }
  .brand .tag { display: none; }
  .wl-form input { min-width: 0; flex: 1 1 140px; }
  .board { min-height: 460px; }
  .section-head { flex-wrap: wrap; gap: 10px; }
}

/* Modo simulação (SGMH_DEMO): âmbar, largura inteira, logo abaixo do topo.
   Numa demonstração projetada ninguém pode confundir dado inventado com real. */
.demo-banner {
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
  padding: 9px 24px;
  background: #fdf4e3;
  border-bottom: 1px solid #eddcb8;
  color: #7a5312;
  font-size: 13px;
}
.demo-banner strong {
  font-weight: 600;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  font-size: 12px;
}

/* Calibração do gateway (RN-07) */
.panel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.panel-sub {
  margin: 4px 0 14px;
  color: var(--text-2);
  font-size: 13px;
  max-width: 78ch;
}
.calib-padrao {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--text-2);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 1px 7px;
  margin-left: 6px;
  vertical-align: middle;
}
.calib-campos { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; }
.calib-campos .field { margin: 0; }
.calib-hint { color: var(--text-2); font-size: 12px; margin-top: 2px; }
@media (max-width: 560px) { .calib-campos { grid-template-columns: 1fr; } }

/* RN-16 — corredor: faixa de circulação, mais discreta que uma sala. */
.m-tile.corredor { fill: #eef2f8; stroke: #cfd9e8; }
.sala-card.corredor { border-left: 3px solid var(--teal); }
.sala-nota {
  font-size: 12px;
  color: var(--text-2);
  padding: 6px 0 2px;
  line-height: 1.4;
}
.sala-gws {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-top: 2px;
}
.sala-gw {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11px;
  padding: 1px 6px;
  border-radius: 999px;
  border: 1px solid var(--border);
  color: var(--text-2);
}
.sala-gw.online { color: var(--teal); background: var(--teal-light); border-color: var(--teal-light); }

/* --- Planta baixa: a ÁREA do espaço, do tamanho configurado ---------------
   O card continua legível e do tamanho de sempre; quem carrega a escala real
   é o retângulo atrás dele. Assim dá para reconhecer um corredor pelo formato,
   e o quadro passa a descrever o andar em vez de só listar salas. */
.sala-espaco {
  position: absolute;
  /* Ancorado pelo CENTRO: assim o painel cresce para os dois lados quando
     precisa passar do tamanho configurado, em vez de esticar só para a direita
     e para baixo. O card fica no meio nos dois casos. */
  transform: translate(-50%, -50%);
  display: flex;
  align-items: center;
  justify-content: center;
  /* O painel NUNCA é menor que o card que ele abriga: a largura e a altura
     configuradas são um piso, e o conteúdo empurra o resto. É isso que mantém
     o card dentro da área em vez de transbordando dela. */
  min-width: min-content;
  min-height: min-content;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: rgba(15, 118, 110, 0.045);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.6);
}
.sala-espaco.corredor {
  background: rgba(38, 50, 56, 0.05);
  border-style: dashed;
}
/* Centrado na área: o card representa o espaço, então fica no meio dele. Ele é
   um filho normal do flex, e não posicionado, para poder empurrar o painel
   quando o espaço configurado for menor que ele. */
.sala-espaco .sala-card {
  position: static;
  flex: 0 0 auto;
}
.sala-espaco.arrastando { z-index: 30; }
/* Sobreposição: o lugar já é de outro espaço. */
.sala-espaco.colidindo { border-color: var(--offline); background: rgba(192, 72, 60, 0.1); }
.sala-espaco.colidindo .sala-card { border-color: var(--offline); }


/* --- Desenhar e redimensionar espaços -------------------------------------- */
.board-zoom button[aria-pressed="true"] { background: var(--teal); color: #fff; }
.board.desenhando { cursor: crosshair; }
.board.desenhando .sala-espaco { pointer-events: none; }

/* Retângulo elástico enquanto o operador arrasta para criar. */
.desenho-previa {
  position: absolute;
  border: 1px dashed var(--teal);
  background: rgba(15, 118, 110, 0.1);
  border-radius: 6px;
  pointer-events: none;
}
.desenho-previa.colidindo { border-color: var(--offline); background: rgba(192, 72, 60, 0.12); }
.desenho-medida {
  position: absolute;
  right: 4px; bottom: 4px;
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  color: var(--teal);
  background: #fff;
  border-radius: 4px;
  padding: 0 4px;
}

/* Alças de redimensionamento na borda da área. */
.puxador {
  position: absolute;
  background: transparent;
  z-index: 5;
}
.puxador.leste  { top: 0; right: -4px; width: 9px; height: 100%; cursor: ew-resize; }
.puxador.sul    { left: 0; bottom: -4px; height: 9px; width: 100%; cursor: ns-resize; }
.puxador.sudeste{ right: -5px; bottom: -5px; width: 14px; height: 14px; cursor: nwse-resize; }
.sala-espaco:hover .puxador.sudeste {
  background: var(--teal);
  border-radius: 3px;
  box-shadow: 0 0 0 2px #fff;
}

/* O espaço que barrou um movimento acende por um instante: sem isso a recusa
   parece arbitrária quando o culpado está longe na planta. */
.sala-espaco.barrou {
  border-color: var(--offline);
  background: rgba(192, 72, 60, 0.14);
  box-shadow: 0 0 0 3px rgba(192, 72, 60, 0.25);
}

/* --- Card do quadro: etiqueta, não painel de controle ----------------------
   Com 1 unidade do plano = 1 px, um card de 230x235 não cabe num quarto de
   190x130: o painel era obrigado a crescer, a planta virava um mosaico de
   etiquetas e a colisão passava a ser entre rótulos, não entre ambientes.
   No quadro o card mostra só o que identifica o espaço; as ações aparecem ao
   passar o mouse, num painel que flutua e não empurra o tamanho de nada. */
.board-layer .sala-card {
  width: auto;
  min-width: 104px;
  max-width: 190px;
  padding: 7px 10px;
  gap: 4px;
  background: rgba(255, 255, 255, 0.94);
}
.board-layer .sala-card .sala-head { gap: 8px; }
.board-layer .sala-card .sala-nome { font-size: 13px; }
.board-layer .sala-card .sala-bloco { font-size: 11px; }
.board-layer .sala-card .sala-count { font-size: 11px; }
.board-layer .sala-card .sala-count .count { font-size: 18px; }
.board-layer .sala-card .sala-pos,
.board-layer .sala-card .sala-nota,
.board-layer .sala-card .sala-gws { display: none; }

/* Ações: flutuam sob o card, sem entrar na conta do tamanho.
   Abrem no CLIQUE (classe .acoes-abertas) e não ao passar o mouse: entre o card
   e o balão há um vão, e atravessá-lo desfazia o hover antes do clique chegar.
   Fechado ele sai do fluxo de foco por `visibility`, senão o Tab entraria num
   menu invisível. */
.board-layer .sala-card .sala-acts {
  position: absolute;
  top: calc(100% + 6px);
  left: 50%;
  transform: translateX(-50%);
  /* Lista vertical, e não uma fila que quebra: em linha, "Excluir" e o X
     sobravam sozinhos numa terceira fila torta, e cada sala quebrava num lugar
     diferente porque os rótulos têm larguras diferentes (um corredor tem
     "Desvincular todos"). Empilhado, todo menu tem a mesma forma. */
  flex-direction: column;
  align-items: stretch;
  width: max-content;
  min-width: 158px;
  max-width: 240px;
  gap: 2px;
  border-top: 0;
  padding: 6px;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity var(--dur, 0.12s) ease;
  z-index: 20;
}
.board-layer .sala-espaco.acoes-abertas .sala-card .sala-acts {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
}
/* O balão aberto passa por cima de qualquer vizinho, inclusive do que estiver
   sob o mouse; o hover só levanta o card o bastante para ele não ficar atrás. */
.board-layer .sala-espaco:hover { z-index: 20; }
.board-layer .sala-espaco.acoes-abertas { z-index: 40; }
.board-layer .sala-espaco.acoes-abertas .sala-card { border-color: var(--teal); }

/* Aberto para cima: última fila do quadro, onde não sobra altura embaixo. */
.board-layer .sala-espaco.acoes-acima .sala-card .sala-acts {
  top: auto;
  bottom: calc(100% + 6px);
}

/* Cabeçalho do menu: o nome da sala e a saída. O menu flutua por cima dos
   vizinhos, então precisa dizer a quem pertence. */
.acts-topo {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 1px 2px 6px 6px;
  margin-bottom: 4px;
  border-bottom: 1px solid var(--border);
}
.acts-tit {
  font-size: 11px; font-weight: 700; color: var(--text-2);
  letter-spacing: .03em; text-transform: uppercase;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* O X fecha sem escolher nada: discreto, sem borda, longe do peso das ações. */
.sala-acts .acts-x {
  flex: 0 0 auto;
  padding: 2px 6px;
  line-height: 1;
  font-size: 15px;
  color: var(--text-2);
  border-color: transparent;
  background: transparent;
}
/* Empilhadas, as ações são alvos de largura inteira e alinhados à esquerda,
   como em qualquer menu de contexto. */
.board-layer .sala-card .sala-acts button {
  width: 100%;
  justify-content: flex-start;
  text-align: left;
  padding: 6px 8px;
}
.board-layer .sala-card .sala-acts .acts-x { width: auto; }
.board-layer .sala-card .sala-acts .call-btn { font-size: 12px; font-weight: 600; }
/* A nota do corredor some do card compacto, mas dentro do menu ela é a resposta
   para "por que não dá para chamar maqueiro daqui?". */
.board-layer .sala-card .sala-acts .sala-nota {
  display: block;
  font-size: 11px;
  padding: 2px 8px 4px;
}


/* RN-18 — ESCOLHA DO LADO DA PORTA
   Um quadrado com as quatro faces clicáveis, em vez de um select. A decisão é
   espacial: o operador aponta o lado olhando para o desenho, e não traduz
   "norte" para "a face de cima" na cabeça. */
.porta-escolha { display: flex; justify-content: center; padding: 6px 0 2px; }
.porta-sala {
  position: relative; width: 132px; height: 96px;
  border: 2px solid var(--border); border-radius: 8px; background: var(--surface);
}
.porta-lado {
  position: absolute; border: 0; padding: 0; cursor: pointer;
  background: var(--border); border-radius: 3px; transition: background .12s;
}
.porta-lado:hover { background: var(--teal-light); }
.porta-lado[aria-pressed="true"] { background: var(--teal); }
/* Cada face encosta na borda que representa, com um respiro nas quinas. */
.porta-lado.n { top: -6px; left: 22%; right: 22%; height: 8px; }
.porta-lado.s { bottom: -6px; left: 22%; right: 22%; height: 8px; }
.porta-lado.o { left: -6px; top: 24%; bottom: 24%; width: 8px; }
.porta-lado.l { right: -6px; top: 24%; bottom: 24%; width: 8px; }
.porta-auto {
  position: absolute; inset: 22% 18%;
  border: 1px dashed var(--border); border-radius: 6px; background: #fff;
  font: 600 11px ui-monospace, Menlo, monospace; color: var(--text-2);
  cursor: pointer; letter-spacing: .06em;
}
.porta-auto[aria-pressed="true"] { border-color: var(--teal); color: var(--teal); }
.sr {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap;
}


/* ---------- Quadro de salas: planta (padrão) e edição ----------
   O quadro nasce como PLANTA: uma tela de leitura onde se clica no quarto e se
   pede maqueiro. As ferramentas de arrastar, redimensionar e desenhar só
   aparecem ao entrar em Editar, e é isso que tira o risco de reposicionar o
   andar sem querer enquanto se procura um paciente. */
.quadro-modo { display: flex; align-items: center; gap: 10px; }
.quadro-modo select {
  font-size: 13px; font-family: inherit; color: var(--text);
  padding: 7px 10px; border: 1px solid var(--border);
  border-radius: var(--radius); background: #fff;
}
#view-rooms:not(.editando) .board-zoom { display: none; }
#view-rooms:not(.editando) #quadro-edit { display: none; }
/* Na planta o cartão é alvo de clique, não de arrasto. */
#view-rooms:not(.editando) .sala-espaco { cursor: pointer; }
#view-rooms:not(.editando) .sala-espaco [data-resize] { display: none; }
#view-rooms.editando .board { min-height: 620px; }
