:root {
  --bg: #0b0d10;
  --panel: #12151b;
  --card: #171b22;
  --line: #2a3140;
  --ink: #e8e4d9;
  --mute: #8b8f9a;
  --amber: #e8a54b;
  --teal: #3dcdc0;
  --rose: #ef6b6b;
  --violet: #8b7cff;
  --ok: #6fbf73;
}
* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
html, body { margin: 0; height: 100%; height: 100dvh; overflow: hidden; background: var(--bg); color: var(--ink); font-family: Manrope, sans-serif; }
body { display: flex; min-height: 0; }
button, .chip, .mini, .toggle { touch-action: manipulation; }
.rail {
  width: 76px; background: #0e1014; border-right: 1px solid var(--line);
  display: flex; flex-direction: column; align-items: center; padding: 18px 0; gap: 18px;
}
.brand {
  width: 48px; height: 48px; border-radius: 14px; overflow: hidden;
  background: #0b1220; padding: 0; flex-shrink: 0;
}
.brand img { width: 100%; height: 100%; display: block; object-fit: cover; }
.rail nav { display: flex; flex-direction: column; gap: 8px; }
.rail button {
  width: 44px; height: 44px; border: 0; border-radius: 12px; background: transparent; color: var(--mute);
  font-size: 18px; cursor: pointer; display: grid; place-items: center;
}
.rail .lbl { display: none; }
.rail button.on, .rail button:hover { background: #1d232d; color: var(--ink); }
main {
  flex: 1; min-width: 0; min-height: 0; height: 100%;
  padding: 28px 36px 0; overflow: hidden;
  display: flex; flex-direction: column;
}
.top {
  display: flex; justify-content: space-between; align-items: end; gap: 24px;
  flex-shrink: 0; z-index: 11; background: var(--bg);
  padding-bottom: 16px; margin-bottom: 0;
  border-bottom: 1px solid var(--line);
}
#view { flex: 1; min-height: 0; min-width: 0; overflow: auto; overflow-x: hidden; padding: 16px 0 48px; }
.kicker { margin: 0; color: var(--amber); letter-spacing: .14em; text-transform: uppercase; font-size: 11px; }
h1 { margin: 4px 0 0; font-family: Fraunces, serif; font-size: 38px; font-weight: 500; }
.top-actions { display: flex; gap: 10px; align-items: center; position: relative; }
#btn-more { display: none; }
#btn-vista {
  width: 44px; height: 44px; padding: 0; flex-shrink: 0;
  display: grid; place-items: center; font-size: 18px; line-height: 1;
}
.pila-wrap { position: relative; flex-shrink: 0; }
.pila-wrap[hidden] { display: none !important; }
#btn-pila {
  width: 44px; height: 44px; padding: 0; position: relative;
  display: grid; place-items: center; color: var(--rose);
  border-color: #4a2a2a;
}
#btn-pila svg { display: block; pointer-events: none; }
.campana-n {
  position: absolute; top: 4px; right: 4px;
  min-width: 15px; height: 15px; padding: 0 4px; border-radius: 99px;
  background: var(--rose); color: #fff; font-size: 10px; font-weight: 700;
  line-height: 15px; text-align: center;
}
.campana-n:empty { display: none; }
.pila-lista {
  position: absolute; right: 0; top: calc(100% + 6px); z-index: 20;
  min-width: 240px; max-width: min(360px, 92vw); max-height: min(50vh, 380px);
  overflow: auto; display: flex; flex-direction: column; gap: 4px;
  background: var(--panel); border: 1px solid var(--line); border-radius: 14px;
  padding: 8px; box-shadow: 0 12px 32px #0008;
}
.pila-lista[hidden] { display: none !important; }
.pila-item {
  display: flex; justify-content: space-between; align-items: center; gap: 12px;
  width: 100%; text-align: left; min-height: 44px; padding: 8px 12px;
  border: 0; border-radius: 10px; background: transparent; color: var(--ink);
  font: inherit; cursor: pointer;
}
.pila-item:hover { background: #1d232d; }
.pila-item span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pila-item b { flex-shrink: 0; color: var(--rose); font-size: 12px; }
.top-extra { display: flex; gap: 10px; align-items: center; }
.search-wrap { position: relative; width: 260px; }
#search {
  width: 100%; background: var(--panel); border: 1px solid var(--line); color: var(--ink);
  border-radius: 999px; padding: 10px 38px 10px 16px;
}
#search-clear {
  position: absolute; right: 6px; top: 50%; transform: translateY(-50%);
  width: 28px; height: 28px; padding: 0; border: 0; border-radius: 50%;
  background: #2a3140; color: var(--mute); cursor: pointer; font-size: 18px; line-height: 1;
}
#search-clear:hover { color: var(--ink); }
#search-clear[hidden] { display: none !important; }
button.ghost, button.solid, .chip, .mini {
  border: 1px solid var(--line); background: var(--panel); color: var(--ink); border-radius: 999px;
  padding: 10px 16px; cursor: pointer; font-family: inherit;
}
button.solid { background: var(--amber); color: #1a1206; border-color: var(--amber); font-weight: 700; }
.clock { font-variant-numeric: tabular-nums; color: var(--mute); min-width: 72px; text-align: right; }
.grid { display: grid; gap: 14px; }
.grid.stats { grid-template-columns: repeat(4, 1fr); margin-bottom: 18px; }
.grid.cards { grid-template-columns: repeat(auto-fill, minmax(min(240px, 100%), 1fr)); }
.grid.wide { grid-template-columns: minmax(0, 1.4fr) minmax(0, .8fr); }
.grid.wide > *, .grid.cards > * { min-width: 0; max-width: 100%; }
.card, .stat {
  background: var(--card); border: 1px solid var(--line); border-radius: 18px; padding: 16px 18px;
}
.stat b { display: block; font-size: 28px; font-family: Fraunces, serif; }
.stat span { color: var(--mute); font-size: 12px; }
.badge {
  display: inline-flex; align-items: center; gap: 6px; font-size: 11px; letter-spacing: .06em;
  text-transform: uppercase; color: var(--mute);
}
.badge i { width: 7px; height: 7px; border-radius: 50%; background: var(--ok); display: inline-block; }
.badge.tuya i { background: #ff5a1f; }
.badge.lsc i { background: #3dcdc0; }
.badge.sonoff i { background: #e8a54b; }
.device { min-height: 168px; display: flex; flex-direction: column; gap: 10px; }
.device header { display: flex; justify-content: space-between; align-items: start; }
.device h3 { margin: 6px 0 0; font-size: 18px; }
.toggle {
  --knob: 22px;
  width: 48px; height: 28px; padding: 0; border: 0; border-radius: 999px; flex-shrink: 0;
  background: #12161d; box-shadow: inset 0 0 0 1px #2c3442, inset 0 2px 5px #0007;
  position: relative; cursor: pointer; transition: background .22s ease, box-shadow .22s ease;
}
.toggle::before {
  content: ""; position: absolute; inset: 0; border-radius: inherit; opacity: 0;
  background: radial-gradient(120% 80% at 80% 50%, #ffe3ad 0%, var(--amber) 55%, #c47d28 100%);
  transition: opacity .22s ease;
}
.toggle.on { box-shadow: 0 0 0 1px #e8a54b55, 0 6px 18px #e8a54b33, inset 0 1px 0 #fff3; }
.toggle.on::before { opacity: 1; }
.toggle::after {
  content: ""; position: absolute; top: 3px; left: 3px; z-index: 1;
  width: var(--knob); height: var(--knob); border-radius: 50%;
  background: linear-gradient(180deg, #fff, #ece7dc);
  box-shadow: 0 1px 2px #0003, 0 3px 8px #0004;
  transition: transform .22s cubic-bezier(.22,1,.36,1);
}
.toggle.on::after { transform: translateX(20px); }
.toggle:hover { filter: brightness(1.08); }
.toggle:active::after { transform: translateX(2px) scaleX(1.12); }
.toggle.on:active::after { transform: translateX(18px) scaleX(1.12); }
.toggle:focus-visible { outline: 2px solid var(--amber); outline-offset: 3px; }
.sensor-flag {
  font-size: 11px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase;
  color: var(--mute); background: #10141a; border: 1px solid var(--line);
  border-radius: 999px; padding: 6px 10px; white-space: nowrap;
}
input[type=range] { width: 100%; accent-color: var(--amber); }
.row { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.settings { display: grid; gap: 14px; max-width: 920px; }
.settings-side { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.tuya-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
#scan-out:empty { display: none; }
.swatch { width: 22px; height: 22px; border-radius: 50%; border: 1px solid var(--line); cursor: pointer; }
.rango-ct { accent-color: #e8d4b0; }
.ct-leyenda { display: flex; justify-content: space-between; font-size: 11px; color: var(--mute); }
.scene { cursor: pointer; min-height: 110px; }
.scene h3 { margin: 20px 0 0; font-family: Fraunces, serif; }
.filtros-wrap {
  display: flex; align-items: center; gap: 6px; margin-bottom: 16px;
  min-width: 0; max-width: 100%;
}
.filtros-wrap .filters {
  flex: 1; min-width: 0; max-width: 100%; margin: 0;
  display: flex; flex-wrap: nowrap; gap: 8px;
  overflow-x: auto; overflow-y: hidden; padding: 4px 12px 8px 2px;
  -webkit-overflow-scrolling: touch; touch-action: pan-x;
  overscroll-behavior-x: contain;
  scrollbar-width: thin; scrollbar-color: #3a4352 transparent;
}
.filtros-wrap .filters .chip {
  flex-shrink: 0; touch-action: pan-x;
  user-select: none; -webkit-user-select: none; -webkit-touch-callout: none;
}
.filtros-nav {
  flex-shrink: 0; width: 34px; height: 34px; padding: 0; border-radius: 50%;
  border: 1px solid var(--line); background: var(--panel); color: var(--ink);
  cursor: pointer; font-size: 20px; line-height: 1; display: grid; place-items: center;
}
.filtros-nav:hover { background: #1d232d; }
.filtros-nav[hidden] { visibility: hidden; pointer-events: none; }
body.reordenando .filtros-wrap .filters,
body.reordenando .filtros-wrap .filters .chip,
.filtros-wrap .filters .chip-orden.agarrada { touch-action: none; }
.chip-orden.esperando {
  transform: scale(1.05); border-color: var(--amber);
}
.chip-orden.agarrada {
  transform: scale(1.08); border-color: var(--amber);
  box-shadow: 0 8px 20px #0008, 0 0 0 1px #e8a54b55;
  z-index: 5; position: relative;
}
.orden-salas {
  display: flex; flex-direction: column; gap: 8px;
  max-height: min(60dvh, 480px); overflow: auto; margin-top: 8px;
  padding-right: 4px;
}
.orden-sala {
  display: flex; align-items: center; gap: 8px;
  padding: 10px 12px; min-height: 52px;
  background: #10141a; border: 1px solid var(--line); border-radius: 14px;
}
.orden-sala.marcada { border-color: var(--amber); }
.orden-sala.agarrada { border-color: var(--amber); box-shadow: 0 8px 20px #0008; pointer-events: none; }
.orden-asa {
  flex-shrink: 0; width: 28px; text-align: center; cursor: grab;
  color: var(--mute); font-size: 18px; line-height: 1; touch-action: none;
  user-select: none;
}
.orden-nombre { flex: 1; min-width: 0; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.orden-sala .mini { min-width: 42px; min-height: 42px; padding: 0; flex-shrink: 0; }
.orden-sala .mini:disabled { opacity: .35; }
.filters { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 16px; }
.chip.on { background: var(--ink); color: #111; }
.muted { color: var(--mute); }
.list { display: flex; flex-direction: column; gap: 8px; }
.log { display: flex; justify-content: space-between; gap: 12px; font-size: 14px; }
form.stack { display: grid; gap: 10px; }
form.stack input:not([type=checkbox]), form.stack select, form.stack textarea {
  width: 100%; background: #0f1217; border: 1px solid var(--line); color: var(--ink); border-radius: 12px; padding: 10px 12px;
  font-family: inherit;
}
.check-row {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 10px 2px; border-bottom: 1px solid var(--line); cursor: pointer; flex-wrap: nowrap;
}
.check-row[hidden] { display: none !important; }
.scene-dev[hidden] { display: none !important; }
.scene-acts { padding: 0 2px 10px; }
.scene-ch, .scene-one { display: flex; justify-content: space-between; align-items: center; gap: 10px; padding: 6px 0 2px; }
.scene-ch span, .scene-one span { color: var(--mute); font-size: 13px; }
.seg { display: flex; gap: 6px; flex-shrink: 0; }
.seg .mini { padding: 6px 12px; }
.seg .mini.on { background: var(--amber); color: #1a1206; border-color: var(--amber); font-weight: 700; }
.scene h3 { display: flex; justify-content: space-between; align-items: center; gap: 8px; }
.check-row span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.check-row input[type=checkbox] {
  width: 18px; height: 18px; margin: 0; flex-shrink: 0; accent-color: var(--amber); cursor: pointer;
}
.modal {
  position: fixed; inset: 0; background: #0008; display: flex; align-items: flex-start; justify-content: center;
  z-index: 20; padding: 18px; overflow: auto;
}
.modal .box {
  width: min(560px, 92vw); margin: auto; display: flex; flex-direction: column;
  overflow: visible; background: #151922; border: 1px solid var(--line); border-radius: 20px; padding: 22px;
}
.modal .box.wide { width: min(680px, 94vw); }
.sc-body { display: flex; flex-direction: column; gap: 10px; }
.sec { margin: 6px 0 0; font-size: 12px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--mute); }
.trig { background: #0f1217; border: 1px solid var(--line); border-radius: 12px; padding: 10px; display: grid; gap: 8px; }
.days { display: flex; gap: 4px; flex-wrap: wrap; }
.days .mini { min-width: 32px; padding: 6px 0; }
.inline { display: flex; align-items: center; gap: 8px; color: var(--mute); font-size: 13px; }
.inline input { width: 80px !important; }
form.stack input[type=time], form.stack input[type=number] { width: auto; min-width: 110px; }
.modal-bar { display: flex; justify-content: space-between; align-items: center; gap: 12px; flex-shrink: 0; padding-bottom: 12px; }
.modal-bar h2 { margin: 0; }
.modal form.stack { display: flex; flex-direction: column; overflow: visible; }
.modal .list { max-height: min(36vh, 320px); overflow: auto; padding-right: 4px; }
#view, .modal .list {
  scrollbar-width: thin;
  scrollbar-color: #3a4352 transparent;
}
#view::-webkit-scrollbar, .modal .list::-webkit-scrollbar { width: 8px; }
#view::-webkit-scrollbar-track, .modal .list::-webkit-scrollbar-track { background: transparent; }
#view::-webkit-scrollbar-thumb, .modal .list::-webkit-scrollbar-thumb {
  background: #2c3442; border-radius: 99px; border: 2px solid transparent; background-clip: padding-box;
}
#view::-webkit-scrollbar-thumb:hover, .modal .list::-webkit-scrollbar-thumb:hover { background: #3d4656; background-clip: padding-box; }
.hidden { display: none !important; }
.bar { height: 8px; background: #222833; border-radius: 99px; overflow: hidden; }
.bar > span { display: block; height: 100%; background: linear-gradient(90deg, var(--amber), var(--teal)); }
table { width: 100%; border-collapse: collapse; font-size: 14px; }
th, td { text-align: left; padding: 10px 8px; border-bottom: 1px solid var(--line); }
.danger { color: var(--rose); }
.login-body { display: grid; place-items: center; overflow: auto; padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left); }
.login-box { width: min(380px, 92vw); padding: 28px; text-align: center; }
.login-box .brand { width: 96px; height: 96px; border-radius: 24px; }
.login-box h1 { font-size: 32px; margin: 8px 0 0; }
.login-box input { text-align: left; font-size: 16px; }
.login-box button { width: 100%; min-height: 46px; }
.table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
@media (max-width: 980px) {
  .grid.wide, .settings-side, .tuya-grid { grid-template-columns: minmax(0, 1fr); }
  main { padding: 18px 18px 0; }
  #view { padding: 12px 0 18px; }
  .search-wrap { width: 160px; }
  .grid.stats:not(.consumo-cifras) { grid-template-columns: repeat(4, 1fr); gap: 6px; margin-bottom: 12px; }
  .grid.stats:not(.consumo-cifras) .stat { padding: 8px 4px; border-radius: 12px; text-align: center; }
  .grid.stats:not(.consumo-cifras) .stat b { font-size: 18px; }
  .grid.stats:not(.consumo-cifras) .stat span { font-size: 9px; letter-spacing: 0; line-height: 1.15; }
  .filtros-wrap { margin-bottom: 12px; }
}
@media (max-width: 820px) {
  html, body { height: 100dvh; }
  body { flex-direction: column; }
  .rail {
    order: 2; width: 100%; flex-direction: row; align-items: stretch; justify-content: stretch;
    padding: 4px 4px calc(6px + env(safe-area-inset-bottom)); gap: 0;
    border-right: 0; border-top: 1px solid var(--line); z-index: 12;
  }
  .rail .brand { display: none; }
  .rail nav { flex-direction: row; width: 100%; justify-content: space-between; gap: 2px; overflow: hidden; }
  .rail button {
    width: auto; flex: 1; min-width: 0; height: 52px; border-radius: 10px; font-size: 16px;
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1px;
  }
  .rail button.on { flex: 1.5; }
  .rail .lbl { display: none; }
  .rail button.on .lbl {
    display: block; font-size: 9px; letter-spacing: .02em; text-transform: uppercase; font-weight: 600; line-height: 1.1;
  }
  html, body { overflow-x: hidden; }
  main {
    order: 1; flex: 1; overflow: hidden;
    padding: max(12px, env(safe-area-inset-top)) 14px 0;
    overscroll-behavior: contain;
  }
  #view { padding: 10px 0 10px; overscroll-behavior: contain; overflow-x: hidden; }
  #view, .grid, .grid.cards, .card, .card.device { min-width: 0; max-width: 100%; }
  .top { flex-direction: column; align-items: stretch; gap: 10px; margin-bottom: 0; padding-bottom: 10px; }
  h1 { font-size: 26px; }
  .top-actions { display: grid; grid-template-columns: 1fr auto auto auto; gap: 8px; align-items: center; }
  .search-wrap { width: auto; min-width: 0; }
  #search { width: 100%; min-height: 44px; font-size: 16px; }
  #search-clear { width: 32px; height: 32px; }
  #btn-more { display: grid; place-items: center; width: 44px; height: 44px; padding: 0; font-size: 22px; line-height: 1; }
  .top-extra {
    display: none; position: absolute; right: 0; top: calc(100% + 6px);
    flex-direction: column; align-items: stretch; gap: 8px; min-width: 200px;
    background: var(--panel); border: 1px solid var(--line); border-radius: 14px; padding: 10px; z-index: 16;
    box-shadow: 0 12px 32px #0008;
  }
  .top-actions.open .top-extra { display: flex; }
  .top-extra button { width: 100%; min-height: 42px; }
  .clock { text-align: center; min-width: 0; }
  .grid.cards { grid-template-columns: 1fr; width: 100%; }
  .grid.stats:not(.consumo-cifras) .stat b { font-size: 16px; }
  .device { min-height: 0; }
  .device h3 { font-size: 16px; }
  .device .muted { word-break: break-word; }
  .filtros-wrap { margin: 0 0 12px; padding: 0; width: 100%; max-width: 100%; }
  .filtros-nav { display: none; }
  .filters .chip { min-height: 40px; }
  .log { flex-direction: column; gap: 2px; }
  .card.row { flex-wrap: wrap; }
  .settings .row { flex-wrap: wrap; }
  .settings .row button { flex: 1 1 auto; min-height: 42px; }
  .modal { padding: 0; align-items: flex-end; }
  .modal .box, .modal .box.wide {
    width: 100%; max-height: 92dvh; margin: 0; overflow: auto;
    border-radius: 20px 20px 0 0; padding: 16px 16px calc(16px + env(safe-area-inset-bottom));
  }
  .modal .list { max-height: min(50dvh, 380px); }
  .seg { flex-wrap: wrap; width: 100%; }
  .seg .mini { flex: 1; text-align: center; min-height: 40px; }
  .days { justify-content: space-between; }
  .days .mini { flex: 1; min-width: 0; }
  form.stack input:not([type=checkbox]), form.stack select, form.stack textarea { font-size: 16px; min-height: 44px; }
  .toggle { --knob: 24px; width: 52px; height: 32px; }
  .toggle.on::after { transform: translateX(22px); }
  .toggle.on:active::after { transform: translateX(20px) scaleX(1.12); }
  #scan-out { overflow: auto; white-space: pre-wrap; word-break: break-word; }
}
@media (max-width: 820px) and (hover: hover) and (pointer: fine) {
  .filtros-nav { display: grid; }
  .filtros-wrap .filters { cursor: grab; }
}

/* ---------- Avisos y estado de conexión ---------- */

.toast {
  position: fixed; left: 50%; bottom: 28px; transform: translate(-50%, 16px);
  max-width: min(420px, calc(100vw - 32px));
  background: var(--panel); color: var(--ink);
  border: 1px solid var(--line); border-radius: 14px;
  padding: 12px 18px; font-size: 14px; line-height: 1.4;
  box-shadow: 0 12px 32px rgba(0, 0, 0, .45);
  opacity: 0; pointer-events: none; z-index: 60;
  transition: opacity .18s ease, transform .18s ease;
}
.toast.show { opacity: 1; transform: translate(-50%, 0); }
.toast.error { border-color: var(--rose); color: #ffd9d9; }

.banner {
  position: fixed; top: 0; left: 0; right: 0; z-index: 70;
  padding: 9px 16px; text-align: center; font-size: 13px; font-weight: 600;
  background: var(--amber); color: #1a1206;
}
.banner.error { background: var(--rose); color: #2a0b0b; }
body:has(.banner) main { padding-top: 60px; }

/* Tarjeta esperando confirmación del equipo: se ve que algo está pasando. */
.card.device.pending { border-color: var(--amber); }
.card.device.pending .toggle { opacity: .75; }
.card.device.is-offline { opacity: .62; }

/* Botón que abre un selector de fichero (restaurar copia). */
.file-btn {
  display: inline-flex; align-items: center; cursor: pointer;
  border: 1px solid var(--line); background: var(--panel); color: var(--ink);
  border-radius: 999px; padding: 9px 16px; font-size: 14px; font-family: inherit;
}
.file-btn:hover { border-color: var(--amber); }

@media (prefers-reduced-motion: reduce) {
  .toast { transition: none; }
}

@media (max-width: 720px) {
  .toast { bottom: 16px; }
}

/* Versión en el pie del login: para saber qué código corre en cada sitio. */
.login-box .build {
  margin: 14px 0 0;
  text-align: center;
  color: var(--mute);
  font-size: 11px;
  letter-spacing: .06em;
  font-variant-numeric: tabular-nums;
}

/* ===================================================================
   Ficha de dispositivo rediseñada
   Prefijadas con .device porque las reglas antiguas (.device header,
   .device h3) son más específicas que una clase suelta y ganarían.
   =================================================================== */

.card.device { gap: 0; padding: 18px 20px 20px; min-width: 0; max-width: 100%; }

.device .dev-head {
  display: flex; align-items: center; justify-content: space-between;
  /* 10px y no 12: con la estrella, esos dos píxeles son los que separan
     «TUYA · INTERRUPTOR» de «TUYA · INTERRUPT…» en las columnas estrechas. */
  gap: 10px; margin-bottom: 14px;
}
.device .dev-actions { display: flex; align-items: center; gap: 10px; }

/* El punto indica conexión, no marca: la marca ya está escrita al lado. */
.card.device .badge i { background: var(--ok); }
.card.device.is-offline .badge i { background: #4a5261; }

.device .icon-btn {
  width: 34px; height: 30px; padding: 0; border-radius: 9px;
  border: 1px solid var(--line); background: #12161d; color: var(--mute);
  font-size: 13px; line-height: 1; cursor: pointer; flex-shrink: 0;
  display: grid; place-items: center;
  transition: color .15s ease, border-color .15s ease;
}
.device .icon-btn:hover { color: var(--ink); border-color: #3a4354; }

.device .pill {
  font-size: 11px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
  color: var(--ink); background: #10141a; border: 1px solid var(--line);
  border-radius: 999px; padding: 7px 13px; white-space: nowrap;
}
.device .pill-off { color: var(--mute); }

.device .dev-title {
  margin: 0; font-family: Manrope, sans-serif; font-size: 22px; font-weight: 700;
  line-height: 1.2; letter-spacing: -.01em;
  overflow: hidden; text-overflow: ellipsis;
}
.device .dev-sub {
  margin: 7px 0 0; font-size: 13px; color: var(--mute);
  display: flex; align-items: center; gap: 7px; flex-wrap: wrap;
}
.device .dev-sub .ok { color: var(--ok); }
.device .dev-sub .off { color: var(--mute); }
.device .dev-sub .sep { opacity: .5; }
.device .dev-sub .ip { font-variant-numeric: tabular-nums; opacity: .8; }

.device .dev-body { margin-top: 18px; display: flex; flex-direction: column; gap: 12px; }
.device .dev-body:empty { margin-top: 0; }

.device .dev-foot {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  font-size: 14px;
}
.device .dev-foot b { font-weight: 700; }
.device .dev-foot b.danger { color: var(--rose); }
.device .dev-foot.ch { padding: 2px 0; }

/* Aviso de dato viejo: importante cuando el equipo lleva horas mudo. */
.device .stale {
  margin: 0; font-size: 13px; color: var(--mute);
  display: flex; align-items: center; gap: 8px;
}
.device .stale .i { opacity: .7; }

/* ---- Control segmentado ---- */

.device .seg-wide {
  display: flex; gap: 4px; padding: 4px;
  background: #10141a; border: 1px solid var(--line); border-radius: 13px;
}
.device .seg-opt {
  flex: 1; border: 0; background: transparent; color: var(--mute);
  border-radius: 9px; padding: 11px 8px; font: inherit; font-size: 14px;
  cursor: pointer; white-space: nowrap;
  transition: background .16s ease, color .16s ease;
}
.device .seg-opt:hover { color: var(--ink); }
.device .seg-opt.on {
  background: #f4f1ea; color: #12151b; font-weight: 700;
  box-shadow: 0 0 0 1px #ffffff26, 0 4px 12px #0006;
}
.device.is-offline .seg-opt.on {
  background: #232a35; color: var(--ink); box-shadow: none;
}
.device .seg-opt:focus-visible { outline: 2px solid var(--amber); outline-offset: 2px; }

/* ---- Termostato ---- */

.device .stepper {
  display: flex; align-items: center; gap: 4px; padding: 5px;
  background: #10141a; border: 1px solid var(--line); border-radius: 13px;
}
.device .step {
  width: 46px; height: 46px; flex-shrink: 0; border: 0; border-radius: 10px;
  background: #1a1f28; color: var(--ink); font-size: 20px; line-height: 1;
  cursor: pointer; transition: background .15s ease;
}
.device .step:hover { background: #232a35; }
.device .step-val {
  flex: 1; text-align: center; font-size: 30px; font-weight: 700;
  font-variant-numeric: tabular-nums; letter-spacing: -.02em;
}
.device .step-val small { font-size: 14px; font-weight: 600; margin-left: 3px; opacity: .75; }

/* La tarjeta apagada se atenúa, pero el texto sigue legible. */
.card.device.is-offline { opacity: 1; }
.card.device.is-offline .dev-title,
.card.device.is-offline .dev-foot b { color: #9aa1ad; }
/* Sin conexión, la tarjeta se atenúa PERO el interruptor tiene que seguir
   diciendo si el aparato se quedó encendido o apagado. Antes se le aplicaba
   un `grayscale(.8)` que se comía el ámbar entero: un interruptor encendido
   quedaba idéntico a uno apagado, y la única pista era hacia qué lado miraba
   la bolita. Justo cuando la ficha enseña el último estado conocido es cuando
   más falta hace leerlo. Se apaga el resplandor —que es lo que dice «esto
   está vivo»— y se baja el ámbar, pero ámbar se queda. */
.card.device.is-offline .toggle { opacity: .92; }
.card.device.is-offline .toggle.on { box-shadow: 0 0 0 1px #e8a54b44, inset 0 1px 0 #fff2; }
.card.device.is-offline .toggle.on::before { opacity: .62; filter: saturate(.75); }
.card.device.is-offline .seg-opt:not(.on) { opacity: .45; }

@media (max-width: 720px) {
  .device .dev-title { font-size: 20px; }
  .device .seg-opt { padding: 10px 4px; font-size: 13px; }
  .device .step { width: 42px; height: 42px; }
  .device .step-val { font-size: 26px; }
}

/* Bolita oscura sobre el ámbar cuando está encendido, como en la maqueta. */
.device .toggle.on::after { background: linear-gradient(180deg, #2a2113, #140f06); }
/* El SVG no intercepta el clic: el destino siempre es el boton. */
.device .icon-btn svg { display: block; pointer-events: none; }

/* ===================================================================
   Ficha: encaje en columnas estrechas
   El grid admite tarjetas de 300 px, y antes la botonera no podía
   encogerse por debajo de su contenido, así que se salía de la ficha.
   =================================================================== */

/* Con la ficha rediseñada, 240 px se quedaban cortos. En el móvil manda
   una sola columna (ver el @media de 820px); aquí sólo escritorio. */
@media (min-width: 821px) {
  .grid.cards { grid-template-columns: repeat(auto-fill, minmax(min(300px, 100%), 1fr)); }
}

body.vista-compacta .grid.cards.equipos {
  gap: 8px; grid-template-columns: 1fr;
}
body.vista-compacta .card.device.compacta {
  min-height: 0; padding: 10px 14px; gap: 0;
  display: flex; flex-direction: column; align-items: stretch;
  border-radius: 14px; cursor: pointer;
}
body.vista-compacta .card.device.compacta .comp-fila {
  display: flex; align-items: center; gap: 10px; min-width: 0;
}
body.vista-compacta .card.device.compacta .dev-title {
  margin: 0; font-size: 16px; font-weight: 650; flex: 1; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
body.vista-compacta .card.device.compacta .comp-chev {
  flex-shrink: 0; color: var(--mute); font-size: 12px; width: 12px;
}
body.vista-compacta .card.device.compacta .dev-actions { flex-shrink: 0; }
body.vista-compacta .card.device.compacta .pill {
  max-width: 42vw; overflow: hidden; text-overflow: ellipsis;
}
body.vista-compacta .card.device.compacta .comp-extra {
  margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--line);
  display: flex; flex-direction: column; gap: 8px;
}
body.vista-compacta .card.device.compacta .comp-extra .seg-wide { width: 100%; }
body.vista-compacta .card.device.compacta .comp-extra input[type=range] { width: 100%; }
body.vista-compacta .card.device.compacta .comp-extra .swatch {
  width: 32px; height: 32px;
}
@media (min-width: 821px) {
  body.vista-compacta .grid.cards.equipos {
    grid-template-columns: repeat(auto-fill, minmax(min(280px, 100%), 1fr));
  }
}

/* Cabecera: la marca cede espacio, los controles nunca. */
.device .dev-head { flex-wrap: nowrap; }
.device .dev-head .badge {
  min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.device .dev-actions { flex-shrink: 0; }
/* Nada de max-width en % aqui: .dev-actions se ajusta al contenido y el
   porcentaje se resuelve contra si mismo, dejando la pastilla en nada.
   Quien cede espacio es la marca, que ya recorta con puntos suspensivos. */
.device .pill { white-space: nowrap; }

/* Subtítulo en una línea, recortado por el final. */
.device .dev-sub {
  display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.device .dev-sub .sep { opacity: .45; }

/* La clave del desbordamiento: sin min-width:0 un flex-item con
   white-space:nowrap se niega a encoger y empuja fuera del contenedor. */
.device .seg-wide { flex-wrap: nowrap; max-width: 100%; }
.device .seg-opt {
  min-width: 0; overflow: hidden; text-overflow: ellipsis;
  padding: 10px 6px; font-size: 13.5px;
}

/* El termostato también se adapta. */
.device .stepper { max-width: 100%; }
.device .step { width: 44px; height: 44px; }
.device .step-val { min-width: 0; overflow: hidden; }

/* Los pies de ficha no se descuadran con textos largos. */
.device .dev-foot { min-width: 0; }
.device .dev-foot > span:first-child {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.device .dev-foot b { flex-shrink: 0; }
.device .stale { align-items: flex-start; }
.device .stale .i { flex-shrink: 0; line-height: 1.5; }

@media (max-width: 720px) {
  /* En móvil hay una sola columna: caben holgados. */
  .device .seg-opt { font-size: 14px; padding: 11px 6px; }
}

/* Las dos vías de los Sonoff (Ajustes). Se envuelve en vez de desbordar. */
.vias { display: flex; flex-wrap: wrap; gap: 8px; margin: 12px 0 10px; }
.vias .pill {
  font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  color: var(--mute); background: #10141a; border: 1px solid var(--line);
  border-radius: 999px; padding: 7px 13px;
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.vias .pill.ok { color: var(--ok); border-color: #2f4a35; }
.vias .pill.warn { color: var(--amber); border-color: #4a3c22; }
.vias .pill.danger { color: var(--rose); border-color: #4a2a2a; }
.via-motivo {
  margin: 0 0 10px; font-size: 12.5px; color: var(--rose); opacity: .85;
  overflow-wrap: anywhere;
}

/* Pila baja: la ficha se marca en rojo. Se mantiene legible a propósito —
   el borde y el aviso bastan para que salte a la vista sin estorbar. */
.card.device.pila-baja {
  border-color: var(--rose);
  box-shadow: inset 0 0 0 1px rgba(239, 107, 107, .18);
}
.card.device.pila-baja .dev-title { color: var(--rose); }
.device .aviso-pila {
  margin: 0 0 4px; font-size: 13px; font-weight: 600; color: var(--rose);
  display: flex; align-items: flex-start; gap: 8px; min-width: 0;
}
.device .aviso-pila .i { flex-shrink: 0; font-size: 11px; line-height: 1.6; }
/* Aunque esté sin conexión, la pila baja se sigue viendo. */
.card.device.is-offline.pila-baja .dev-title { color: var(--rose); }

/* Pantalla de configuración. Una fila por ajuste: explicación a la izquierda,
   control a la derecha, y en móvil uno encima de otro. */
.ajuste-grupo { border-top: 1px solid var(--line); padding-top: 14px; margin-top: 4px; }
.ajuste-grupo:first-child { border-top: 0; padding-top: 0; }
.ajuste {
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; padding: 10px 0; min-width: 0;
}
.ajuste + .ajuste { border-top: 1px solid rgba(42, 49, 64, .5); }
.ajuste-txt { min-width: 0; flex: 1; }
.ajuste-txt label { display: block; font-size: 14px; font-weight: 600; }
.ajuste-txt p { margin: 3px 0 0; font-size: 12.5px; line-height: 1.45; }
.ajuste-txt .marca {
  font-size: 10px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  color: var(--amber); border: 1px solid #4a3c22; border-radius: 999px;
  padding: 2px 7px; margin-left: 6px; vertical-align: 1px; white-space: nowrap;
}
.ajuste-val { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
.ajuste-val input[type=number] { width: 104px; text-align: right; }
.ajuste-val input[type=text],
.ajuste-val input[type=password] { width: min(320px, 42vw); }
.ajuste-val select { min-width: 150px; }
.ajuste-val .uni { font-size: 12.5px; color: var(--mute); min-width: 30px; }
@media (max-width: 620px) {
  .ajuste { flex-direction: column; align-items: stretch; gap: 8px; }
  .ajuste-val { justify-content: flex-end; }
  .ajuste-val input[type=number],
  .ajuste-val input[type=text],
  .ajuste-val input[type=password],
  .ajuste-val select { flex: 1; min-width: 0; width: auto; }
}

/* Usuarios, roles y el editor de alcance. */
.box.ancho { width: min(720px, 94vw); }
.fila-acciones { white-space: nowrap; text-align: right; }
.fila-acciones .ghost { padding: 6px 12px; font-size: 13px; }
.ok-txt { color: var(--ok); }
td .marca {
  font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em;
  color: var(--rose); border: 1px solid #4a2a2a; border-radius: 999px; padding: 2px 7px;
  white-space: nowrap; display: inline-block; margin-top: 4px;
}
.caps { display: grid; gap: 8px; }
.cap {
  display: flex; align-items: flex-start; gap: 10px; padding: 9px 11px;
  border: 1px solid var(--line); border-radius: 11px; cursor: pointer; min-width: 0;
}
.cap:hover { border-color: #3a4354; }
.cap input { margin-top: 3px; flex-shrink: 0; }
.cap span { min-width: 0; font-size: 13.5px; }
.cap .muted { font-size: 12px; }
.cap-admin { border-color: #4a3c22; background: rgba(232, 165, 75, .05); }

.alcance { display: grid; gap: 8px; }
.alc-defecto {
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  padding: 11px; border: 1px solid var(--line); border-radius: 11px;
  background: #10141a; min-width: 0;
}
.alc-defecto > span { min-width: 0; font-size: 13.5px; }
.alc-sala { border: 1px solid var(--line); border-radius: 11px; overflow: hidden; }
.alc-sala summary {
  display: flex; align-items: center; gap: 12px; padding: 10px 12px;
  cursor: pointer; list-style: none; min-width: 0;
}
.alc-sala summary::-webkit-details-marker { display: none; }
.alc-sala summary::before { content: "▸"; color: var(--mute); flex-shrink: 0; font-size: 11px; }
.alc-sala[open] summary::before { content: "▾"; }
.alc-nombre { font-weight: 600; font-size: 14px; flex: 1; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.alc-sala summary .muted { font-size: 12px; flex-shrink: 0; }
.alc-sala summary select, .alc-defecto select { flex-shrink: 0; min-width: 132px; }
.alc-equipos { padding: 2px 12px 12px 30px; display: grid; gap: 6px; }
.alc-equipo {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  font-size: 13px; min-width: 0;
}
.alc-equipo > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.alc-equipo select { flex-shrink: 0; min-width: 132px; }

.device .solo-ver {
  margin: 0 0 4px; font-size: 12.5px; color: var(--mute);
  display: flex; align-items: center; gap: 7px;
}
@media (max-width: 620px) {
  .alc-sala summary { flex-wrap: wrap; }
  .alc-sala summary select, .alc-defecto select, .alc-equipo select { min-width: 110px; }
  .alc-equipos { padding-left: 14px; }
}

/* Los hijos de un grid no encogen por defecto (min-width:auto) y se salen de
   la caja. Con 39 equipos y nombres largos, esto se nota enseguida. */
.alcance > *, .caps > *, .ajuste-grupo > * { min-width: 0; }
.alc-sala, .alc-defecto { max-width: 100%; overflow: hidden; }
.alc-sala summary { flex-wrap: wrap; }
.alc-equipos { padding-left: 24px; }
.alc-equipos, .alc-equipo { max-width: 100%; }
.box.ancho .alcance select { max-width: 100%; }

/* Corrección: `min-width:0` deja encoger, pero sin `flex:1` el texto se
   estrangula hasta una palabra por línea y los nombres desaparecen. */
.alc-defecto > span, .alc-equipo > span { flex: 1 1 auto; min-width: 0; }
.alc-equipo > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.alc-defecto > span { white-space: normal; }
.alc-nombre { flex: 1 1 auto; }
/* Las etiquetas vuelven a su línea sólo cuando de verdad no caben. */
.alc-sala summary { flex-wrap: nowrap; }
.alc-sala summary select { flex: 0 0 auto; width: 148px; min-width: 0; }
.alc-equipo select { flex: 0 0 auto; width: 148px; min-width: 0; }
.alc-defecto select { flex: 0 0 auto; width: 148px; min-width: 0; }
@media (max-width: 560px) {
  .alc-sala summary { flex-wrap: wrap; }
  .alc-sala summary select, .alc-equipo select, .alc-defecto select { width: 128px; }
  .alc-equipo { gap: 8px; }
}

/* `form.stack select` pone width:100% y gana por especificidad, así que el
   desplegable se comía la etiqueta. Se contrarresta desde el formulario. */
form.stack .alcance select,
form.stack .alc-sala summary select,
form.stack .alc-equipo select,
form.stack .alc-defecto select {
  width: 148px; flex: 0 0 auto; min-width: 0; max-width: 100%;
}
form.stack .alc-defecto > span,
form.stack .alc-equipo > span { flex: 1 1 auto; min-width: 0; }
@media (max-width: 560px) {
  form.stack .alcance select,
  form.stack .alc-sala summary select,
  form.stack .alc-equipo select,
  form.stack .alc-defecto select { width: 126px; }
}

/* Por dónde va cada equipo. Discreto: es un dato de apoyo, no el titular. */
.device .via-lan { color: var(--teal); font-weight: 600; }
.device .via-nube { color: var(--amber); font-weight: 600; }

/* Botón trabajando: se nota que ha pasado algo y no se puede pulsar dos veces. */
button.ocupado { opacity: .7; cursor: progress; }

/* Ajustes por secciones: menu a la izquierda y solo lo que se mira. */
.ajustes-marco { display: grid; grid-template-columns: 260px 1fr; gap: 20px; align-items: start; min-width: 0; }
.ajustes-menu { display: grid; gap: 6px; position: sticky; top: 0; min-width: 0; }
.ajustes-sec {
  display: flex; align-items: center; gap: 12px; text-align: left; width: 100%;
  padding: 11px 13px; border: 1px solid transparent; border-radius: 12px;
  background: transparent; color: var(--ink); cursor: pointer; font-family: inherit;
  min-width: 0; transition: background .15s ease, border-color .15s ease;
}
.ajustes-sec:hover { background: #141922; }
.ajustes-sec.on { background: var(--card); border-color: var(--line); }
.ajustes-sec .ico {
  width: 30px; height: 30px; flex-shrink: 0; display: grid; place-items: center;
  border-radius: 9px; background: #10141a; border: 1px solid var(--line);
  font-size: 14px; color: var(--mute);
}
.ajustes-sec.on .ico { color: var(--amber); border-color: #4a3c22; }
.ajustes-sec .txt { display: grid; gap: 1px; min-width: 0; }
.ajustes-sec .txt b { font-size: 14px; font-weight: 600; }
.ajustes-sec .txt .muted { font-size: 11.5px; line-height: 1.3;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ajustes-panel { display: grid; gap: 16px; min-width: 0; }
.ajustes-panel > * { min-width: 0; }
.ajustes-titulo {
  margin: 0; font-family: Fraunces, serif; font-size: 24px; font-weight: 500;
}
@media (max-width: 900px) {
  /* En pantalla estrecha el menu pasa a ser una fila de pestanas. */
  .ajustes-marco { grid-template-columns: 1fr; }
  .ajustes-menu {
    display: flex; gap: 8px; overflow-x: auto; padding-bottom: 4px; position: static;
    scrollbar-width: none;
  }
  .ajustes-menu::-webkit-scrollbar { display: none; }
  .ajustes-sec { width: auto; flex-shrink: 0; border-color: var(--line); padding: 9px 13px; }
  .ajustes-sec .ico { display: none; }
  .ajustes-sec .txt .muted { display: none; }
  .ajustes-sec .txt b { white-space: nowrap; }
}

/* ===================================================================
   Configuración dentro de la ficha
   El lápiz despliega esto en la propia tarjeta en vez de abrir una
   ventana: cambiar el nombre o la sala de varios equipos seguidos era
   abrir y cerrar un modal por cada uno.
   =================================================================== */

.card.device.configurando { border-color: #4a3c22; }
.device .icon-btn.on { color: var(--amber); border-color: #4a3c22; background: #1a1610; }

.device .dev-config {
  margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--line);
  display: grid; gap: 10px; min-width: 0;
}
.device .cfg-fila {
  display: grid; grid-template-columns: 70px 1fr; align-items: center;
  gap: 10px; min-width: 0;
}
.device .cfg-fila > span { font-size: 12.5px; color: var(--mute); }
.device .dev-config input:not([type=checkbox]),
.device .dev-config select {
  width: 100%; min-width: 0; background: #0f1217; border: 1px solid var(--line);
  color: var(--ink); border-radius: 10px; padding: 8px 10px;
  font-family: inherit; font-size: 14px;
}
.device .dev-config input:focus, .device .dev-config select:focus {
  outline: none; border-color: var(--amber);
}
.device .cfg-check {
  display: flex; align-items: center; gap: 9px; font-size: 13.5px;
  color: var(--mute); cursor: pointer;
}
.device .cfg-check input { accent-color: var(--amber); }

.device .cfg-canales {
  display: grid; gap: 10px; min-width: 0;
  padding-top: 10px; border-top: 1px solid rgba(42, 49, 64, .6);
}
.device .cfg-canales p { margin: 0; font-size: 12px; line-height: 1.4; }

.device .cfg-pie { display: flex; gap: 8px; margin-top: 2px; }
.device .cfg-pie button { padding: 8px 16px; font-size: 13px; }

@media (max-width: 520px) {
  /* Etiqueta encima del campo: con 70px de columna el nombre no cabe. */
  .device .cfg-fila { grid-template-columns: 1fr; gap: 5px; }
  .device .dev-config input:not([type=checkbox]),
  .device .dev-config select { font-size: 16px; min-height: 42px; }
}

/* ===================================================================
   Salas dentro de salas
   =================================================================== */

/* Segunda fila de filtros: la que baja un escalón dentro de una sala.
   Va pegada a la de arriba y más apagada para que se lea como «lo que hay
   dentro de esto» y no como otra lista de salas al mismo nivel. */
.filters.sub {
  margin-top: -8px; padding-left: 2px;
  align-items: center;
}
.filters.sub .chip { font-size: 12.5px; padding: 6px 12px; }
.filtros-madre {
  font-size: 12px; color: var(--mute); font-weight: 600;
  white-space: nowrap; flex-shrink: 0; margin-right: 2px;
  max-width: 180px; overflow: hidden; text-overflow: ellipsis;
}

/* El árbol de salas. La sangría dice de quién cuelga cada una; en una sola
   columna (móvil) se nota por el margen, y en varias por el nivel escrito. */
/* Un renglón por sala, no una tarjeta alta: con veinte salas, cada línea de
   más es otra pantalla de desplazamiento y el árbol deja de verse de un
   vistazo, que era justo lo que se quería. */
.salas-arbol { display: grid; gap: 8px; }
.card.sala {
  display: flex; align-items: center; justify-content: space-between;
  gap: 14px; min-width: 0; padding: 12px 16px;
}
.card.sala[data-nivel="2"] { margin-left: 24px; border-left: 2px solid #3a4354; }
.card.sala[data-nivel="3"] { margin-left: 48px; border-left: 2px solid #3a4354; }
.sala-txt { min-width: 0; }
.card.sala h3 {
  margin: 0; font-family: Manrope, sans-serif; font-size: 17px; font-weight: 700;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.card.sala .muted { margin: 2px 0 0; font-size: 12.5px; }
.sala-acciones { display: flex; gap: 7px; flex-shrink: 0; flex-wrap: wrap; justify-content: flex-end; }
.sala-madre {
  display: block; font-family: Manrope, sans-serif; font-size: 10.5px;
  font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  color: var(--mute); margin-bottom: 1px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Editor de alcance: las subsalas sangradas, porque la sangría es justo lo
   que heredan (lo de la madre vale para lo que tenga dentro). */
.alc-sala[data-nivel="2"] { margin-left: 18px; }
.alc-sala[data-nivel="3"] { margin-left: 36px; }

/* Campo con su etiqueta encima, para el «Dentro de» del formulario de sala. */
form.stack .campo { display: grid; gap: 5px; min-width: 0; }
form.stack .campo > span { font-size: 12.5px; }

@media (max-width: 720px) {
  /* Los botones bajan a su propia línea: en el móvil no caben al lado del
     nombre sin dejar el nombre en tres letras y puntos suspensivos. */
  .card.sala { flex-direction: column; align-items: stretch; gap: 10px; }
  .sala-acciones { justify-content: flex-start; }
  .sala-acciones .mini { flex: 1 1 auto; min-height: 38px; }
  .card.sala[data-nivel="2"] { margin-left: 12px; }
  .card.sala[data-nivel="3"] { margin-left: 24px; }
  .alc-sala[data-nivel="2"] { margin-left: 10px; }
  .alc-sala[data-nivel="3"] { margin-left: 20px; }
}

/* ===================================================================
   Fichas que se colocan arrastrando
   =================================================================== */

/* Mientras se arrastra, la página no se mueve ni se selecciona texto: en el
   móvil, sin esto, el dedo desplaza la pantalla en vez de mover la ficha. */
body.reordenando { touch-action: none; user-select: none; -webkit-user-select: none; }
body.reordenando .grid.cards { cursor: grabbing; }

/* La ficha agarrada se levanta y las demás le dejan sitio al pasar por encima. */
.card.device.agarrada {
  transform: scale(1.03) rotate(.6deg);
  border-color: var(--amber);
  box-shadow: 0 18px 40px #000a, 0 0 0 1px #e8a54b55;
  opacity: .96; z-index: 5; position: relative; cursor: grabbing;
}
.card.device.agarrada .toggle { pointer-events: none; }
body.reordenando .card.device:not(.agarrada) { transition: transform .16s ease; }

/* Botón de eliminar dentro de la ficha: separado de Guardar y Cancelar, para
   no pulsarlo de carrerilla. */
.device .cfg-pie { flex-wrap: wrap; }
.device .cfg-borrar { margin-left: auto; }

/* Lista de equipos excluidos, en Ajustes → Equipos. */
.excluido {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; padding: 10px 0; min-width: 0;
}
.excluido + .excluido { border-top: 1px solid rgba(42, 49, 64, .6); }
.excluido .txt { min-width: 0; display: grid; gap: 1px; }
.excluido .txt b { font-size: 14px; }
.excluido .txt .muted { font-size: 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.excluido .mini { flex-shrink: 0; }

/* ===================================================================
   Consumo de API
   =================================================================== */

/* `.dev-foot` está escrita para la ficha de un equipo (`.device .dev-foot`),
   así que dentro de Ajustes se quedaba sin formato y el nombre y el número
   salían pegados: «Consultar estado886.788». */
.ajustes-panel .dev-foot {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 16px; font-size: 14px; padding: 4px 0; min-width: 0;
}
.ajustes-panel .dev-foot + .dev-foot { border-top: 1px solid rgba(42, 49, 64, .5); }
.ajustes-panel .dev-foot b { font-variant-numeric: tabular-nums; white-space: nowrap; }

.card.consumo.ojo { border-color: #4a3c22; }
.card.consumo.mal { border-color: var(--rose); box-shadow: inset 0 0 0 1px rgba(239,107,107,.18); }
.consumo-titular {
  margin: 2px 0 10px; font-family: Manrope, sans-serif;
  font-size: 19px; font-weight: 700; letter-spacing: -.01em;
}
.card.consumo.mal .consumo-titular { color: var(--rose); }
.aviso-ojo { margin: 0 0 8px; font-size: 13px; font-weight: 600; color: var(--amber); }

.barra {
  height: 8px; border-radius: 999px; background: #10141a;
  border: 1px solid var(--line); overflow: hidden; margin-bottom: 12px;
}
.barra > span { display: block; height: 100%; background: var(--amber); }
.card.consumo.mal .barra > span { background: var(--rose); }

.grid.stats.consumo-cifras { grid-template-columns: repeat(4, 1fr); margin: 10px 0 14px; }
.consumo-cifras .stat { display: grid; gap: 2px; }
.consumo-cifras .stat b { font-size: 20px; font-variant-numeric: tabular-nums; }
.consumo-cifras .stat .muted { font-size: 11.5px; }

/* Barras por hora. Sin librería: 24 columnas y alturas en porcentaje. */
.barras-horas {
  display: flex; align-items: flex-end; gap: 3px; height: 110px; margin-top: 10px;
}
.barra-hora {
  flex: 1; min-width: 0; height: 100%;
  display: flex; flex-direction: column; justify-content: flex-end; align-items: center; gap: 4px;
}
.barra-hora i {
  display: block; width: 100%; min-height: 2px; border-radius: 3px 3px 0 0;
  background: linear-gradient(180deg, var(--amber), #a9763a);
}
.barra-hora em {
  font-style: normal; font-size: 9.5px; color: var(--mute);
  font-variant-numeric: tabular-nums;
}

@media (max-width: 720px) {
  .grid.stats.consumo-cifras { grid-template-columns: repeat(2, 1fr); }
  .barras-horas { height: 90px; gap: 2px; }
  /* Con 24 etiquetas no cabe ni una: se dejan las horas pares. */
  .barra-hora:nth-child(odd) em { visibility: hidden; }
}

/* Nota bajo el selector de vía: explica lo que hace la opción elegida. */
.device .cfg-nota { margin: -2px 0 2px; font-size: 11.5px; line-height: 1.4; }
.device .cfg-ojo {
  margin: 0; font-size: 11.5px; line-height: 1.4; color: var(--amber); font-weight: 600;
}

/* ===================================================================
   Favoritos
   =================================================================== */

/* La estrella de la ficha. Apagada es un contorno discreto; encendida, ámbar,
   igual que el resto de lo que está «activo» en el panel. */
/* La estrella va sin recuadro: tres botones con caja en una cabecera tan
   pequeña son ruido, y además dejaban la etiqueta de marca sin sitio
   («TUYA · INTERRUPT…»). Como icono suelto ocupa la mitad y se lee mejor. */
.device .dev-actions { gap: 6px; }
.device .icon-btn.estrella {
  width: 22px; height: 26px; border: 0; background: none;
  font-size: 16px; line-height: 1; color: #5c6473;
}
.device .icon-btn.estrella.on { color: var(--amber); }
.device .icon-btn.estrella:hover { color: var(--amber); background: none; }

/* Pantalla vacía: se explica qué hacer, no sólo que no hay nada. */
/* Línea de ayuda sobre una lista. No es un filtro, así que no se recorta. */
.pista { margin: 0 0 14px; font-size: 12.5px; color: var(--mute); }

.card.vacio { text-align: center; padding: 34px 22px; }
.card.vacio h3 { margin: 0 0 6px; font-family: Manrope, sans-serif; font-size: 17px; }
.card.vacio .muted { margin: 0; max-width: 46ch; margin-inline: auto; line-height: 1.5; }
