/* ── Park61 AC Control — Green Park Theme ── */

:root {
  --green-900: #1b5e20;
  --green-800: #2e7d32;
  --green-700: #388e3c;
  --green-600: #43a047;
  --green-500: #4caf50;
  --green-400: #66bb6a;
  --green-300: #81c784;
  --green-200: #a5d6a7;
  --green-100: #c8e6c9;
  --green-50:  #e8f5e9;

  --cool:  #42a5f5;
  --heat:  #ef5350;
  --dry:   #ffa726;
  --fan:   #78909c;
  --auto:  #ab47bc;

  --bg:       #f1f8e9;
  --card-bg:  #ffffff;
  --shadow:   0 2px 12px rgba(0,0,0,0.08);
  --shadow-lg: 0 4px 24px rgba(0,0,0,0.12);
  --radius:   16px;
  --radius-sm: 10px;

  --safe-top:    env(safe-area-inset-top, 0px);
  --safe-bottom: env(safe-area-inset-bottom, 0px);
}

* { box-sizing: border-box; margin: 0; padding: 0; }

[hidden] { display: none !important; }

body {
  font-family: -apple-system, BlinkMacSystemFont, 'SF Pro', 'Segoe UI', Roboto, sans-serif;
  background: var(--bg);
  color: #333;
  min-height: 100vh;
  min-height: 100dvh;
  -webkit-user-select: none;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
  overflow-x: hidden;
}

/* ── Header ──
   Dual-mode. By default it shows the app icon and brand. When
   the JS adds `.is-remote`, the brand is hidden and the remote-mode
   block (back button + AC name + status chips) takes over. Same vertical
   real estate carries everything the user needs in either context. */

.header {
  background: linear-gradient(135deg, var(--green-800), var(--green-600));
  color: #fff;
  padding: calc(var(--safe-top) + 12px) 16px 12px;
  position: sticky;
  top: 0;
  z-index: 100;
  box-shadow: var(--shadow);
}

/* — Dashboard mode — */

.header-dashboard {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  max-width: 800px;
  margin: 0 auto;
  padding: 4px 4px;
}

.header-dashboard-brand {
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 10px;
}

.header-icon { display: block; width: 36px; height: 36px; border-radius: 9px; flex-shrink: 0; }

.header h1 {
  font-size: 1.25rem;
  font-weight: 600;
  letter-spacing: -0.02em;
}

.header-actions {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
}

.header-action {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 30px;
  padding: 6px 10px;
  border: 1px solid rgba(255, 255, 255, 0.20);
  border-radius: 16px;
  background: rgba(255, 255, 255, 0.14);
  color: #fff;
  font: inherit;
  font-size: 0.78rem;
  font-weight: 700;
  line-height: 1;
  text-decoration: none;
  cursor: pointer;
}

.header-action:hover {
  background: rgba(255, 255, 255, 0.22);
}

/* — Reconnect strip —
   Sits just under the header (both views). Hidden by [hidden] unless app.js
   shows it while the live link is catching up. Calm blue, not an alarm. */
.connection-banner {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 7px 12px;
  background: #eaf3fc;
  color: #2d5b85;
  font-size: 0.82rem;
  font-weight: 750;
  border-bottom: 1px solid rgba(66, 165, 245, 0.18);
}
.connection-banner-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--cool);
  animation: reconnectPulse 1.2s ease-in-out infinite;
}

/* — Remote mode — */

.header-remote {
  display: none;             /* shown only when .is-remote */
  align-items: center;
  gap: 12px;
  max-width: 800px;
  margin: 0 auto;
}

.header.is-remote .header-dashboard { display: none; }
.header.is-remote .header-remote    { display: flex; }

.header-remote-body {
  flex: 1 1 auto;
  min-width: 0;              /* allow the name to ellipsize */
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.header-remote-name {
  font-size: 1.1rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: #fff;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  line-height: 1.2;
}

.header-remote-chips {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}

/* In-header chip variants — the standard chip palette assumes a light
   background, so against the green gradient we recolor them to a frosted
   look. The colored dot still carries the state signal. */
.header-remote-chips .chip {
  font-size: 0.66rem;
  padding: 2px 8px 2px 7px;
  background: rgba(255, 255, 255, 0.14);
  color: rgba(255, 255, 255, 0.92);
  border-color: rgba(255, 255, 255, 0.18);
}

.header-remote-chips .chip.on {
  background: rgba(255, 255, 255, 0.22);
  border-color: rgba(255, 255, 255, 0.28);
  color: #fff;
}

.header-remote-chips .chip.warn {
  background: rgba(255, 196, 102, 0.22);
  border-color: rgba(255, 196, 102, 0.45);
  color: #fff7e6;
}

.header-remote-chips .chip.warn .chip-dot { background: #ffc266; }

.header-remote-chips .chip.standby {
  background: rgba(255, 255, 255, 0.12);
  border-color: rgba(255, 255, 255, 0.18);
  color: rgba(255, 255, 255, 0.85);
}

.header-remote-chips .chip.standby .chip-dot { background: rgba(255, 255, 255, 0.6); }

.header-remote-chips .chip-dot {
  background: rgba(255, 255, 255, 0.45);
}

.header-remote-chips .chip.on .chip-dot {
  background: #b9f6ca;
  box-shadow: 0 0 6px rgba(185, 246, 202, 0.65);
}

/* ── Views ── */

.view { display: none; }
.view.active { display: block; }

/* ── Dashboard ── */

.device-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
  gap: 14px;
  padding: 16px;
  max-width: 1240px;
  margin: 0 auto;
}

/* ── Device tile ──
   Each tile carries a state-driven visual identity: a 4px left-edge
   accent stripe colored by plug state, a small dot in the top-left
   that mirrors that color, and a subtle background tint. The dashboard
   reads at a glance — running cards pop, the rest fade into the green
   wash background. */

.device-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 12px;
  min-height: 160px;
  padding: 14px 16px 14px 18px;
  background: var(--card-bg);
  border: 1px solid rgba(46, 125, 50, 0.08);
  border-radius: var(--radius-sm);
  box-shadow: 0 2px 10px rgba(46, 125, 50, 0.05);
  cursor: pointer;
  overflow: hidden;
  transition:
    transform 0.18s ease,
    box-shadow 0.22s ease,
    background 0.22s ease,
    border-color 0.22s ease;
}

/* Left-edge accent stripe — color set per state below. */
.device-card::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 4px;
  background: transparent;
  transition: background 0.22s ease;
}

.device-card:active {
  transform: scale(0.97);
}

.device-card:focus-visible {
  outline: 3px solid rgba(66, 165, 245, 0.55);
  outline-offset: 3px;
}

@media (hover: hover) {
  .device-card:hover {
    transform: translateY(-2px);
    box-shadow: 0 8px 22px rgba(46, 125, 50, 0.13);
  }
}

/* — State variants — */

.device-card.state-running {
  background: linear-gradient(135deg, rgba(232, 245, 233, 0.88), var(--card-bg) 68%);
  border-color: rgba(76, 175, 80, 0.34);
  box-shadow: 0 8px 24px rgba(46, 125, 50, 0.16);
}
.device-card.state-running::before { background: var(--green-500); }

.device-card.state-standby {
  background: var(--card-bg);
}
.device-card.state-standby::before { background: rgba(155, 178, 155, 0.35); }

.device-card.state-stale {
  background: linear-gradient(135deg, #fff7e6, var(--card-bg) 75%);
  border-color: rgba(217, 149, 0, 0.22);
}
.device-card.state-stale::before { background: #d99500; }

.device-card.state-metering {
  background: linear-gradient(135deg, #fff2e8, var(--card-bg) 75%);
  border-color: rgba(207, 95, 33, 0.28);
}
.device-card.state-metering::before { background: #cf5f21; }

.device-card.state-none {
  background: #fbfbfb;
  border-color: rgba(0, 0, 0, 0.04);
}
.device-card.state-none::before { background: #d8d8d8; }

/* Transient "catching up" state shown while the live link reconnects after
   the app was backgrounded. Calm blue with a gently pulsing stripe/dot — it
   reads as "refreshing", never as the amber "stale/error" alarm. */
.device-card.state-reconnecting {
  background: linear-gradient(135deg, #eef4fb, var(--card-bg) 78%);
  border-color: rgba(66, 165, 245, 0.20);
}
.device-card.state-reconnecting::before {
  background: var(--cool);
  animation: reconnectPulse 1.4s ease-in-out infinite;
}
.card-primary.reconnecting .card-primary-value { color: #3f6489; }
.device-grid.catching-up .device-card { opacity: 0.65; }

@keyframes reconnectPulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.35; }
}

/* Relay deliberately switched off at the plug — calm slate tint that
   reads as "intentional off", distinct from the warm greens (live) and
   amber (stale/error) elsewhere in the palette. */
.device-card.state-relay-off {
  background: linear-gradient(135deg, #eef2f7, var(--card-bg) 78%);
  border-color: rgba(100, 116, 139, 0.20);
}
.device-card.state-relay-off::before { background: #64748b; }

/* "Dead" = nothing reachable in either direction. Stacks on top of the
   state class to mute the whole card — read as "nothing to look at". */
.device-card.dead {
  opacity: 0.62;
  filter: saturate(0.4);
}

/* — Top row: state dot + AC name — */

.card-top {
  display: flex;
  align-items: center;
  gap: 8px;
}

.card-name {
  flex: 1;
  min-width: 0;
  font-size: 1rem;
  font-weight: 700;
  letter-spacing: -0.015em;
  color: var(--green-900);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* — Primary block — the loud middle.
   Running cards stack a big wattage value on top of a small "RUNNING"
   caption. Other states show just the value, larger or smaller as
   appropriate. The block grows to fill remaining space so the chip
   always anchors to the bottom. */

.card-main {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: start;
  gap: 10px;
  flex: 1 1 auto;
}

.card-primary {
  display: flex;
  flex-direction: column;
  gap: 2px;
  justify-content: center;
  min-width: 0;
}

/* Setpoint chip — small, subordinate to the wattage. Rendered only when
   the app has authored the AC's current state and intent isn't stale, so
   when it appears it's trustworthy and we lean into the trustworthiness
   visually (filled, not muted). See updateDashboardCards for the gating. */
.card-setpoint {
  align-self: start;
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  margin: 1px 0 0;
  padding: 4px 9px;
  border-radius: 999px;
  background: rgba(46, 125, 50, 0.10);
  color: var(--green-800);
  font-size: 0.74rem;
  font-weight: 600;
  letter-spacing: 0.005em;
  line-height: 1.1;
}

.card-setpoint-sep {
  opacity: 0.55;
  font-weight: 500;
}

.card-setpoint-temp {
  font-variant-numeric: tabular-nums;
}

/* On muted/dead cards the chip would be the only thing carrying full
   color — knock it back so it doesn't shout. */
.device-card.dead .card-setpoint {
  background: rgba(46, 125, 50, 0.06);
  color: var(--green-700);
  opacity: 0.85;
}

.card-primary-value {
  font-size: 1.85rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.05;
}

.card-primary-caption {
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--green-600);
  opacity: 0.8;
  margin-top: 2px;
}

.card-primary.running  .card-primary-value   { color: var(--green-800); }
.card-primary.running  .card-primary-caption { color: var(--green-600); }
.device-card.state-running .card-primary-value {
  font-size: 2.35rem;
  font-weight: 800;
}

.card-energy-line {
  margin-top: auto;
  padding-top: 2px;
  color: #6d806f;
  font-size: 0.76rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.card-primary.standby  .card-primary-value {
  color: #8aa18b;
  font-weight: 600;
  font-size: 1.65rem;
}
.card-primary.standby  .card-primary-caption {
  color: #9bb29b;
  opacity: 0.85;
}

.card-primary.stale    .card-primary-value {
  color: #a37200;
  font-weight: 700;
  font-size: 1.2rem;
}

.card-primary.none     .card-primary-value {
  color: #8d988d;
  font-weight: 700;
  font-size: 1.2rem;
}

.card-primary.relay-off .card-primary-value {
  color: #475569;
  font-weight: 700;
  font-size: 1.45rem;
}
.card-primary.relay-off .card-primary-caption {
  color: #64748b;
  opacity: 0.92;
}

.card-transport-row {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  padding-top: 9px;
  border-top: 1px solid rgba(46, 125, 50, 0.08);
}

.card-transport {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  min-width: 0;
  color: #6f806f;
  font-size: 0.68rem;
  font-weight: 750;
  line-height: 1.25;
  white-space: nowrap;
}

.card-transport-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  flex: 0 0 auto;
  background: #b9c3b9;
}

.card-transport.online,
.card-transport.plug-live { color: var(--green-800); }
.card-transport.online .card-transport-dot,
.card-transport.plug-live .card-transport-dot {
  background: var(--green-500);
}

.card-transport.offline,
.card-transport.plug-never { color: #9ca79c; }
.card-transport.offline .card-transport-dot,
.card-transport.plug-never .card-transport-dot {
  background: #c4cbc4;
}

.card-transport.plug-stale { color: #9a6700; }
.card-transport.plug-stale .card-transport-dot {
  background: #d99500;
}

.card-transport.plug-metering { color: #9b4a16; }
.card-transport.plug-metering .card-transport-dot {
  background: #cf5f21;
}

/* ── Status chip (Control / Power) ──
   Used both on dashboard cards and in the remote header. */

.chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 9px 3px 8px;
  border-radius: 999px;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  background: #f3f4f3;
  color: #6a6f6a;
  border: 1px solid transparent;
  white-space: nowrap;
  line-height: 1.4;
}

.chip-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: #bdbdbd;
  flex-shrink: 0;
}

.chip.on {
  background: var(--green-50);
  color: var(--green-800);
  border-color: var(--green-200);
}

.chip.on .chip-dot {
  background: var(--green-500);
  box-shadow: 0 0 5px var(--green-300);
}

/* "warn" = something is plumbed but unhealthy (e.g. plug is stale). */
.chip.warn {
  background: #fff7e6;
  color: #8a5a00;
  border-color: #ffd596;
}

.chip.warn .chip-dot {
  background: #d99500;
}

.chip.standby {
  background: #f1f5f1;
  color: #5b6b5c;
  border-color: #dde4dd;
}

.chip.standby .chip-dot {
  background: #9bb29b;
}

.chip.off { /* default greys are already set above */ }

/* ── Remote control ── */

/* Back button — sits inside the green header. Frosted-white over the
   gradient so it reads as a tap target without competing with the title. */
.back-btn {
  background: rgba(255, 255, 255, 0.16);
  border: 1px solid rgba(255, 255, 255, 0.22);
  border-radius: 50%;
  width: 38px;
  height: 38px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  color: #fff;
  flex-shrink: 0;
  padding: 0;
  transition: background 0.15s ease, transform 0.15s ease;
}

.back-btn:active {
  background: rgba(255, 255, 255, 0.26);
  transform: scale(0.94);
}

#remote-controls {
  display: flex;
  flex-direction: column;
}

/* ── Offline recovery ── */

.remote-offline-panel {
  width: min(calc(100% - 32px), 420px);
  margin: 16px auto 0;
  padding: 16px;
  border-radius: var(--radius-sm);
  background: #fff;
  border: 1px solid rgba(217, 119, 6, 0.28);
  box-shadow: 0 6px 20px rgba(46, 125, 50, 0.08);
}

.remote-offline-panel[hidden] {
  display: none;
}

.remote-offline-head {
  display: flex;
  align-items: flex-start;
  gap: 12px;
}

.remote-offline-icon {
  width: 42px;
  height: 42px;
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: #fff7e6;
  color: #b45309;
  border: 1px solid rgba(217, 119, 6, 0.22);
}

.remote-offline-copy {
  min-width: 0;
}

.remote-offline-copy h3 {
  font-size: 1rem;
  line-height: 1.2;
  color: #3a4d3b;
  margin-bottom: 4px;
}

.remote-offline-copy p {
  font-size: 0.82rem;
  line-height: 1.4;
  color: #657368;
}

.offline-power-card {
  display: grid;
  gap: 3px;
  margin-top: 14px;
  padding: 12px;
  border-radius: var(--radius-sm);
  background: #f7fbf4;
  border: 1px solid rgba(46, 125, 50, 0.10);
}

.offline-power-label {
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: #728574;
}

.offline-power-value {
  font-size: 1.45rem;
  font-weight: 750;
  letter-spacing: -0.01em;
  color: var(--green-900);
}

.offline-power-detail {
  font-size: 0.76rem;
  font-weight: 650;
  color: #728574;
}

.offline-power-card.running .offline-power-value { color: var(--green-800); }
.offline-power-card.stale .offline-power-value,
.offline-power-card.stale .offline-power-detail { color: #9a6700; }
.offline-power-card.none .offline-power-value { color: #8a8a8a; }

/* ── Remote summary ── */

.remote-summary {
  width: min(calc(100% - 32px), 440px);
  margin: 12px auto 20px;
}

.truth-hint {
  margin: 0 0 10px;
  padding: 8px 10px;
  border-radius: var(--radius-sm);
  background: rgba(255, 255, 255, 0.72);
  border: 1px solid rgba(46, 125, 50, 0.08);
  color: #5e7061;
  font-size: 0.76rem;
  font-weight: 600;
  line-height: 1.35;
  text-align: center;
}

.truth-hint.caution {
  background: #fffaf0;
  border-color: rgba(217, 119, 6, 0.24);
  color: #7c4a03;
}

.truth-hint.warning {
  background: #fff4e5;
  border-color: rgba(217, 119, 6, 0.42);
  color: #7c4a03;
}

.truth-hint.success {
  background: #eef8ef;
  border-color: rgba(46, 125, 50, 0.22);
  color: var(--green-800);
}

.truth-hint:empty { display: none; }

.remote-summary-grid {
  display: block;
}

.setpoint-panel {
  min-width: 0;
}

.setpoint-panel {
  background: #fff;
  border: 1px solid rgba(46, 125, 50, 0.10);
  border-radius: var(--radius-sm);
  box-shadow: 0 4px 16px rgba(46, 125, 50, 0.08);
}

.setpoint-panel {
  padding: 14px 14px 12px;
}

.summary-label {
  display: block;
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--green-700);
}

.power-meter {
  min-width: 116px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: flex-end;
  gap: 3px;
  padding: 10px 0 10px 14px;
  border-left: 1px solid rgba(46, 125, 50, 0.16);
  text-align: right;
}

.power-meter-label {
  font-size: 0.62rem;
  font-weight: 800;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: currentColor;
  opacity: 0.68;
}

.power-meter-value {
  font-size: 1.42rem;
  font-weight: 800;
  line-height: 1.05;
  letter-spacing: -0.02em;
  color: currentColor;
}

.power-meter-detail {
  font-size: 0.76rem;
  font-weight: 750;
  color: currentColor;
  opacity: 0.72;
}

.power-meter.stale {
  color: #ffe8ad;
}

.power-meter.metering {
  color: #ffd3b8;
}

.power-meter.none,
.power-meter.standby {
  color: currentColor;
}

.control-lock-note {
  margin-top: 10px;
  color: #6a7a6c;
  font-size: 0.76rem;
  line-height: 1.35;
  text-align: center;
}

.control-lock-note[hidden] {
  display: none;
}

/* Power button */

.power-row {
  display: flex;
  justify-content: stretch;
  padding: 0 0 12px;
}

.power-btn {
  width: 100%;
  min-width: 0;
  padding: 12px 16px;
  border-radius: 18px;
  border: 2px solid rgba(46, 125, 50, 0.18);
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.98), rgba(232, 245, 233, 0.96));
  color: var(--green-900);
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 16px;
  cursor: pointer;
  box-shadow:
    0 12px 28px rgba(46, 125, 50, 0.14),
    inset 0 1px 0 rgba(255, 255, 255, 0.9);
  transition:
    transform 0.18s ease,
    box-shadow 0.22s ease,
    background 0.22s ease,
    color 0.22s ease,
    border-color 0.22s ease;
}

.power-action {
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 13px;
}

.power-btn-icon {
  width: 54px;
  height: 54px;
  flex-shrink: 0;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(255, 255, 255, 0.92);
  border: 2px solid rgba(46, 125, 50, 0.12);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.95),
    0 8px 20px rgba(46, 125, 50, 0.10);
  transition: inherit;
}

.power-btn-copy {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 5px;
  min-width: 0;
}

.power-btn-label {
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  opacity: 0.62;
}

.power-btn-state {
  font-size: 1.3rem;
  font-weight: 800;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  line-height: 1;
}

.power-btn.on {
  border-color: transparent;
  background: linear-gradient(135deg, var(--green-700), var(--green-500));
  color: #fff;
  box-shadow:
    0 16px 34px rgba(46, 125, 50, 0.26),
    inset 0 1px 0 rgba(255, 255, 255, 0.18);
}

.power-btn.on .power-btn-icon {
  background: rgba(255, 255, 255, 0.16);
  border-color: rgba(255, 255, 255, 0.18);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.22),
    0 12px 24px rgba(17, 74, 22, 0.22);
}

.power-btn.on .power-meter {
  border-left-color: rgba(255, 255, 255, 0.28);
}

.power-btn:not(.on) .power-meter {
  color: #5f7461;
}

.power-btn:not(.on) .power-meter.stale {
  color: #9a6700;
}

.power-btn:not(.on) .power-meter.metering {
  color: #9b4a16;
}

.power-btn:not(.on) .power-meter.none {
  color: #8a8a8a;
}

.power-btn.on .power-btn-label {
  opacity: 0.72;
}

.power-btn.unconfirmed-off {
  border-color: rgba(217, 119, 6, 0.5);
  background: linear-gradient(135deg, #fff7e6, #fffdf7);
  color: #7c4a03;
  box-shadow:
    0 12px 28px rgba(217, 119, 6, 0.13),
    inset 0 1px 0 rgba(255, 255, 255, 0.9);
}

.power-btn.unconfirmed-off .power-btn-icon {
  border-color: rgba(217, 119, 6, 0.22);
}

.power-btn:active { transform: translateY(1px) scale(0.985); }

.power-btn:disabled {
  cursor: not-allowed;
  opacity: 0.55;
  box-shadow: none;
}

/* ── Footer: resend + the honest hint about state ──
   This block makes the "last command sent / may have changed" reality
   visible, instead of letting the controls pretend they reflect truth. */

.remote-footer {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  padding: 2px 20px 4px;
  max-width: 420px;
  margin: 0 auto;
}

/* Quiet secondary action — pill-shaped, outlined. Loud enough to be
   clearly tappable, quiet enough not to compete with the controls. */
.resend-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 10px 20px;
  border-radius: 22px;
  border: 1.5px solid var(--green-300);
  background: var(--card-bg);
  color: var(--green-800);
  font-size: 0.82rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  cursor: pointer;
  box-shadow:
    0 3px 10px rgba(46, 125, 50, 0.08),
    inset 0 1px 0 rgba(255, 255, 255, 0.9);
  transition:
    transform 0.15s ease,
    background 0.18s ease,
    border-color 0.18s ease,
    color 0.18s ease,
    box-shadow 0.18s ease;
}

.resend-btn-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--green-600);
}

.resend-btn:active {
  transform: translateY(1px) scale(0.98);
  background: var(--green-50);
}

.resend-btn.attention {
  border-color: rgba(217, 119, 6, 0.62);
  background: #fff7e6;
  color: #7c4a03;
  box-shadow:
    0 6px 16px rgba(217, 119, 6, 0.13),
    inset 0 1px 0 rgba(255, 255, 255, 0.9);
}

.resend-btn.attention .resend-btn-icon {
  color: #b45309;
}

.resend-btn.settling {
  border-color: rgba(217, 119, 6, 0.34);
  background: #fffaf0;
  color: #7c4a03;
}

.resend-btn.settling .resend-btn-icon {
  color: #b45309;
}

.resend-btn:disabled {
  color: #b0b0b0;
  border-color: #e0e0e0;
  background: #f7f7f7;
  cursor: not-allowed;
  box-shadow: none;
}

.resend-btn:disabled .resend-btn-icon { color: #c8c8c8; }

/* ── More disclosure + smart-plug relay control ──
   The plug power button switches mains at the smart plug. For IR-capable
   ACs it stays behind "More" by default; when the IR controller is offline
   the JS adds .force-open, which removes the disclosure and surfaces the
   button directly. */

.remote-more {
  width: min(100%, 420px);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  margin: 6px auto 0;
  padding: 0 20px calc(var(--safe-bottom) + 30px);
}

.remote-more-toggle {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 14px;
  border: none;
  background: transparent;
  color: #6a7a6c;
  font-size: 0.78rem;
  font-weight: 500;
  cursor: pointer;
  border-radius: 12px;
  transition: background 0.15s ease, color 0.15s ease;
}

.remote-more-toggle:hover {
  background: rgba(46, 125, 50, 0.06);
  color: var(--green-800);
}

.remote-more-chevron { transition: transform 0.2s ease; }
.remote-more.open .remote-more-chevron { transform: rotate(180deg); }

.remote-more-panel {
  width: 100%;
  display: none;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  padding: 4px 0 0;
}

.remote-more.open .remote-more-panel,
.remote-more.force-open .remote-more-panel {
  display: flex;
}

.remote-more.force-open .remote-more-toggle { display: none; }

.remote-more-hint {
  font-size: 0.74rem;
  line-height: 1.45;
  color: #6a7a6c;
  text-align: center;
  max-width: 320px;
  padding: 0 4px;
}

/* ── Smart-plug relay button ──
   Color follows the current relay state: red means the next click switches
   mains off; green means the next click restores mains power. */

.plug-power-btn {
  position: relative;
  overflow: hidden;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: min(100%, 280px);
  padding: 12px 22px;
  border-radius: 24px;
  border: 1.5px solid #d8d8d8;
  background: #f7f7f7;
  color: #8a8a8a;
  font-size: 0.84rem;
  font-weight: 600;
  cursor: pointer;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
  touch-action: manipulation;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.9);
  transition: transform 0.12s ease, border-color 0.18s ease, background 0.18s ease, color 0.18s ease;
}

.plug-power-btn::before {
  content: '';
  position: absolute;
  inset: 0;
  background: rgba(100, 116, 139, 0.14);
  transform: scaleX(0);
  transform-origin: left center;
  pointer-events: none;
}

.plug-power-btn.plug-on::before {
  background: rgba(239, 83, 80, 0.16);
}

.plug-power-btn.plug-off::before {
  background: rgba(46, 125, 50, 0.16);
}

.plug-power-btn.holding {
  cursor: progress;
}

.plug-power-btn.holding::before {
  animation: plug-power-hold-fill var(--plug-power-hold-ms, 3000ms) linear forwards;
}

.plug-power-btn.plug-on {
  border-color: var(--heat);
  background: #fff5f5;
  color: var(--heat);
  box-shadow:
    0 3px 10px rgba(239, 83, 80, 0.10),
    inset 0 1px 0 rgba(255, 255, 255, 0.9);
}

.plug-power-btn.plug-off {
  border-color: var(--green-600);
  background: var(--green-50);
  color: var(--green-800);
  box-shadow:
    0 3px 10px rgba(76, 175, 80, 0.12),
    inset 0 1px 0 rgba(255, 255, 255, 0.9);
}

.plug-power-btn.unknown {
  border-color: #d8d8d8;
  background: #f7f7f7;
  color: #8a8a8a;
  box-shadow: none;
}

.plug-power-btn:not(:disabled):active {
  transform: translateY(1px) scale(0.98);
}

.plug-power-btn:disabled {
  cursor: not-allowed;
}

.plug-power-btn.sending {
  cursor: wait;
}

.plug-power-btn.sending .plug-power-content {
  animation: plug-power-pending-pulse 1.1s ease-in-out infinite;
}

.plug-power-content {
  position: relative;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

.plug-power-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

@keyframes plug-power-pending-pulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.65; }
}

@keyframes plug-power-hold-fill {
  from { transform: scaleX(0); }
  to   { transform: scaleX(1); }
}

/* ── Hint variants ──
   Two paragraphs live in the More panel; only one is shown, picked by
   the body class set in updateRemoteView. */
.hint-plug-only { display: none; }
body.mode-plug-only .hint-ir-plug   { display: none; }
body.mode-plug-only .hint-plug-only { display: block; }

/* Native AC devices have their own controller state and no smart-plug
   fallback in this app, so the More panel would only show a dead plug relay
   control. */
body.mode-native-ac .remote-more {
  display: none !important;
}

/* ── Plug-only mode ──
   When the active device has no IR remote, the entire IR control surface
   is irrelevant. We hide it via this single body class instead of forking
   the markup, which keeps the DOM identical for every device and avoids
   re-rendering the remote view on navigation. The plug power button is
   promoted from "fallback under More" to the primary action: the
   disclosure toggle disappears and the panel is always shown. */

body.mode-plug-only #ack-banner,
body.mode-plug-only #btn-power,
body.mode-plug-only #remote-offline-panel,
body.mode-plug-only .remote-summary,
body.mode-plug-only .command-surface,
body.mode-plug-only .temp-section,
body.mode-plug-only .control-group,
body.mode-plug-only #btn-resend,
body.mode-plug-only #last-action-hint,
body.mode-plug-only #ctrl-pill,
body.mode-plug-only .remote-more-toggle {
  display: none !important;
}

/* The More panel is always visible in plug-only mode — there is no other
   control to surface, so disclosure adds noise without any payoff. */
body.mode-plug-only .remote-more-panel {
  display: flex !important;
}

/* In plug-only mode the plug power button is the *only* control, so it
   earns more visual weight: a touch larger, slightly bolder, more breathing
   room. */
body.mode-plug-only .plug-power-btn {
  width: min(100%, 320px);
  padding: 16px 28px;
  font-size: 0.92rem;
  border-width: 2px;
  margin-top: 4px;
}

body.mode-plug-only .remote-more {
  /* Pull the panel up — without IR controls above it, the footer would
     otherwise float oddly low on the page. */
  margin-top: 24px;
}

body.mode-plug-only .remote-more-hint {
  /* The hint is the only labelling left; size it like guidance, not fine
     print. */
  font-size: 0.86rem;
  font-style: normal;
  color: #4a5a4c;
  max-width: 360px;
}

/* ── Plug-only live readout ──
   Hidden in IR+plug mode (the dashboard card already carries this info,
   and the remote view uses the space for IR controls). In plug-only
   mode it's the body of the view: a big wattage number, a state caption,
   and a Today / Yesterday energy row beneath. */

.plug-readout { display: none; }
body.mode-plug-only .plug-readout {
  display: block;
  text-align: center;
  padding: 36px 20px 8px;
  max-width: 420px;
  margin: 0 auto;
}

.plug-readout-primary {
  margin-bottom: 28px;
}

.plug-readout-value {
  display: block;
  font-size: 4rem;
  font-weight: 200;
  letter-spacing: -0.04em;
  line-height: 1;
  color: var(--green-900);
  /* When the value is "Standby" / "Plug signal lost" / "Waiting for
     plug…", JS adds .alt to make it read like a status line instead of
     a metric. */
}

.plug-readout-value.alt {
  font-size: 1.6rem;
  font-weight: 500;
  color: #6a7a6c;
  letter-spacing: -0.01em;
}

.plug-readout-caption {
  display: block;
  margin-top: 10px;
  font-size: 0.78rem;
  font-weight: 600;
  color: #6a7a6c;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.plug-readout-energy {
  display: flex;
  justify-content: center;
  gap: 14px;
  flex-wrap: wrap;
}

.plug-readout-energy:empty { display: none; }

.plug-readout-energy-row {
  display: flex;
  flex-direction: column;
  align-items: center;
  background: var(--card-bg);
  border-radius: var(--radius-sm);
  padding: 12px 18px;
  min-width: 120px;
  box-shadow: var(--shadow);
}

.plug-readout-energy-label {
  font-size: 0.7rem;
  font-weight: 600;
  color: #6a7a6c;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  margin-bottom: 4px;
}

.plug-readout-energy-value {
  font-size: 1.15rem;
  font-weight: 600;
  color: var(--green-800);
  letter-spacing: -0.01em;
}

/* "More" panel kWh tiles — same row markup as the plug-only readout,
   different container. Reuses .plug-readout-energy-row/-label/-value
   styles for visual consistency between the two surfaces.
   Plug-only mode hides this copy because the primary readout above
   already shows the same figures, and we'd otherwise render them
   twice on the same page. */
.more-energy {
  display: flex;
  justify-content: center;
  gap: 12px;
  flex-wrap: wrap;
  width: 100%;
}

.more-energy:empty { display: none; }

body.mode-plug-only .more-energy { display: none; }

/* Temperature */

.temp-section {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  padding: 6px 0 0;
}

.temp-btn {
  width: 46px;
  height: 46px;
  border-radius: 50%;
  border: 2px solid var(--green-300);
  background: #fff;
  font-size: 1.5rem;
  font-weight: 600;
  color: var(--green-800);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 0.15s;
}

.temp-btn:active { background: var(--green-100); }

.temp-btn:disabled {
  cursor: not-allowed;
  background: #f7faf6;
  border-color: #dde7dc;
  color: #aeb8af;
}

.temp-display {
  display: flex;
  align-items: flex-start;
  gap: 2px;
}

#temp-value {
  font-size: 4.35rem;
  font-weight: 700;
  color: var(--green-800);
  line-height: 1;
}

.temp-unit {
  font-size: 1.3rem;
  font-weight: 500;
  color: var(--green-600);
  margin-top: 6px;
}

/* Control groups */

.control-group {
  max-width: 420px;
  margin: 0 auto 14px;
  padding: 0 20px;
}

.control-label {
  display: block;
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--green-700);
  margin-bottom: 8px;
}

.btn-row {
  display: flex;
  gap: 6px;
}

.mode-btn {
  flex: 1;
  min-height: 44px;
  padding: 10px 4px;
  border: 2px solid var(--green-200);
  border-radius: var(--radius-sm);
  background: #fff;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  font-size: 0.7rem;
  font-weight: 600;
  color: #888;
  transition: all 0.15s;
}

.mode-name {
  font-size: 0.78rem;
  line-height: 1.05;
  font-weight: 800;
  color: inherit;
}

.mode-btn.active {
  border-color: var(--green-500);
  background: var(--green-50);
  color: var(--green-800);
}

.mode-btn.active[data-mode="cool"] { border-color: var(--cool); color: var(--cool); background: #e3f2fd; }
.mode-btn.active[data-mode="heat"] { border-color: var(--heat); color: var(--heat); background: #ffebee; }
.mode-btn.active[data-mode="dry"]  { border-color: var(--dry);  color: var(--dry);  background: #fff3e0; }
.mode-btn.active[data-mode="fan"]  { border-color: var(--fan);  color: var(--fan);  background: #eceff1; }
.mode-btn.active[data-mode="auto"] { border-color: var(--auto); color: var(--auto); background: #f3e5f5; }

.mode-btn:disabled {
  cursor: not-allowed;
  border-color: #e1e8e1;
  background: #f8faf7;
  color: #aab5ab;
  box-shadow: none;
}

.mode-btn.active:disabled {
  border-color: #dbe5db;
  background: #eef4ec;
  color: #8fa08f;
}

/* ── Command acknowledgment banner ── */

.ack-banner {
  position: fixed;
  left: 50%;
  bottom: calc(var(--safe-bottom) + 18px);
  width: min(calc(100vw - 32px), 360px);
  padding: 12px 18px;
  text-align: center;
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.03em;
  line-height: 1.2;
  opacity: 0;
  transform: translate(-50%, 18px) scale(0.97);
  transition:
    transform 0.22s ease,
    opacity 0.22s ease,
    background 0.22s ease,
    color 0.22s ease,
    box-shadow 0.22s ease;
  border-radius: 999px;
  pointer-events: none;
  z-index: 180;
  box-shadow: 0 16px 30px rgba(0,0,0,0.14);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
}

.ack-banner.pending {
  opacity: 1;
  transform: translate(-50%, 0) scale(1);
  color: var(--green-900);
  background: rgba(255, 255, 255, 0.92);
  border: 1px solid rgba(129, 199, 132, 0.8);
}

.ack-banner.confirmed,
.ack-banner.remote-synced {
  opacity: 1;
  transform: translate(-50%, 0) scale(1);
  color: #fff;
  background: linear-gradient(135deg, rgba(46, 125, 50, 0.96), rgba(76, 175, 80, 0.92));
  border: 1px solid rgba(255, 255, 255, 0.16);
}

.ack-banner.timeout,
.ack-banner.not-sent {
  opacity: 1;
  transform: translate(-50%, 0) scale(1);
  color: #7f1d1d;
  background: rgba(255, 245, 245, 0.96);
  border: 1px solid rgba(239, 83, 80, 0.3);
}

/* ── Offline / disabled controls ──
   When the IR controller is offline, hide the inert remote surface and
   let the recovery panel plus plug relay control take the first screen. */

#remote-controls.disabled .remote-summary,
#remote-controls.disabled .command-surface {
  display: none;
}

#remote-controls.disabled .remote-more {
  margin-top: 14px;
}

#remote-controls.disabled .remote-more-panel {
  display: flex;
}

#remote-controls.disabled .remote-more-toggle {
  display: none;
}

#remote-controls.disabled .remote-more-hint {
  font-size: 0.82rem;
  color: #4f5e51;
  max-width: 360px;
}

/* ── Powered-off state ── */

#remote-controls.powered-off .control-group,
#remote-controls.powered-off .temp-section {
  opacity: 0.68;
  transition: opacity 0.3s ease;
}

/* ── Stale-intent banner + dimmed intent-only controls ──
   Shown only when plug wattage changes and no complete controller frame
   arrives during the grace window. A decoded physical-remote frame clears
   this state; the fallback warning is reserved for genuinely missed frames. */

.intent-stale-banner {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 12px 14px;
  margin: 0 0 14px;
  border-radius: var(--radius-sm);
  background: rgba(255, 244, 214, 0.96);
  border: 1px solid rgba(217, 119, 6, 0.45);
  color: #7c4a03;
  font-size: 0.82rem;
  line-height: 1.4;
  box-shadow: 0 1px 6px rgba(120, 70, 0, 0.08);
}

.intent-stale-banner[hidden] {
  display: none;
}

.intent-stale-banner-icon {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: #b45309;
  margin-top: 1px;
}

.intent-stale-banner-text {
  flex: 1 1 auto;
}

/* Dim the intent-only controls — everything except .power-row, whose
   button reflects plug-fused truth and is therefore still believable.
   Less aggressive than .powered-off so the controls stay tappable
   (the user is being invited to override them). */
#remote-controls.intent-stale .temp-section,
#remote-controls.intent-stale .control-group {
  opacity: 0.55;
  transition: opacity 0.3s ease;
}

/* Plug-only devices have no IR settings to be stale about — the banner
   would never fire there, but suppress it defensively in case the flag
   ever gets set (e.g. a device being reclassified at runtime). */
body.mode-plug-only #intent-stale-banner {
  display: none !important;
}

/* ── Responsive ── */

@media (min-width: 500px) {
  .device-grid {
    grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  }
}

@media (min-width: 1240px) {
  .device-grid {
    grid-template-columns: repeat(5, minmax(0, 1fr));
  }
}

@media (max-width: 430px) {
  #temp-value {
    font-size: 4rem;
  }

  .power-btn {
    gap: 10px;
    padding: 12px;
  }

  .power-btn-icon {
    width: 48px;
    height: 48px;
  }

  .power-meter {
    min-width: 98px;
    padding-left: 10px;
  }

  .power-meter-value {
    font-size: 1.2rem;
  }

}

/* ── Office wall kiosk ──
   `?view=kiosk` adds body.mode-kiosk in app.js. Office 2 gives this unified
   page the full left half of a 3840x2160 display, so the iframe itself is
   1920x2160. Four equal columns leave enough width for glanceable AC cards;
   flexible rows use whatever height remains below heating and temperatures.
   The normal web/mobile dashboard is intentionally untouched. */
body.mode-kiosk {
  width: 100%;
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
}

body.mode-kiosk #app {
  display: flex;
  flex-direction: column;
  width: 100%;
  height: 100%;
  min-height: 0;
}

body.mode-kiosk .header,
body.mode-kiosk .connection-banner {
  flex: 0 0 auto;
}

body.mode-kiosk .header {
  position: static;
  padding: 8px 12px;
}

body.mode-kiosk .header-dashboard,
body.mode-kiosk .header-remote {
  max-width: none;
  padding: 0;
}

body.mode-kiosk .header h1 {
  font-size: 1.35rem;
}

body.mode-kiosk .header-action {
  font-size: 0.9rem;
}

body.mode-kiosk #stats-link {
  display: none;
}

body.mode-kiosk .view.active {
  flex: 1 1 auto;
  min-height: 0;
}

body.mode-kiosk #dashboard.view.active {
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

body.mode-kiosk .device-grid {
  flex: 1 1 auto;
  width: 100%;
  height: auto;
  min-width: 0;
  min-height: 0;
  max-width: none;
  margin: 0;
  padding: 10px;
  gap: 10px;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  grid-auto-rows: minmax(0, 1fr);
}

/* ── Temperature + Nagyterem heating ── */

.nagyterem-panel,
.temperature-panel {
  max-width: 1210px;
  margin: 16px auto 0;
  padding: 18px;
  background: var(--card-bg);
  border: 1px solid rgba(46, 125, 50, 0.12);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}

.nagyterem-head,
.temperature-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 20px;
  margin-bottom: 16px;
}

.nagyterem-head h2,
.temperature-head h2 {
  font-size: 1.25rem;
  color: #263b28;
}

.nagyterem-title-copy { min-width: 0; }

.nagyterem-subtitle {
  margin-top: 3px;
  color: #708173;
  font-size: 0.75rem;
  font-weight: 650;
}

.temperature-head > span {
  color: #607563;
  font-size: 0.78rem;
}

.heating-state {
  align-self: center;
  padding: 8px 13px;
  border-radius: 999px;
  font-size: 0.85rem;
  font-weight: 850;
  background: #edf1ed;
  color: #536356;
  flex-shrink: 0;
}

.heating-state.on { background: #fff0e4; color: #a64700; }
.heating-state.off { background: #edf1ed; color: #405044; }
.heating-state.unknown { background: #f0f2f0; color: #657067; }

.heating-summary {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  justify-content: space-between;
  gap: 10px 20px;
  margin-bottom: 14px;
  padding: 14px 16px;
  background: #f7f9f7;
  border: 1px solid #dce4dd;
  border-radius: 12px;
}

.heating-summary.on {
  background: #fff8f0;
  border-color: #edc79f;
}

.heating-summary.unknown {
  background: #fff8e8;
  border-color: #eed49b;
}

.heating-summary-state {
  display: flex;
  align-items: center;
  min-width: 0;
  gap: 13px;
}

.heating-summary-state > div { min-width: 0; }

.heating-summary-health span,
.heating-summary-health small { display: block; }

.heating-demand-sources {
  display: flex;
  flex-wrap: wrap;
  gap: 5px 18px;
  color: #607563;
  font-size: 0.76rem;
  line-height: 1.5;
}

.heating-demand-sources strong {
  color: #2e3c30;
  margin-left: 4px;
}

.heating-demand-sources .warning strong { color: #9b443b; }

.heating-summary-health small {
  margin-top: 3px;
  color: #738075;
  font-size: 0.67rem;
  line-height: 1.35;
}

.heating-summary-health {
  flex: 0 0 auto;
  text-align: right;
}

.heating-pending {
  grid-column: 1 / -1;
  color: #935600;
  font-size: 0.78rem;
  font-weight: 700;
}

.heating-details {
  grid-column: 1 / -1;
  color: #607563;
  font-size: 0.74rem;
  line-height: 1.5;
}

.heating-details summary { cursor: pointer; width: fit-content; padding: 4px 0; }
.heating-details[open] summary { margin-bottom: 8px; }
.heating-details p + p { margin-top: 8px; }
.heating-observations { display: grid; gap: 4px; margin: 10px 0; }
.heating-observations > div { display: flex; flex-wrap: wrap; gap: 4px 12px; }
.heating-observations dt { min-width: 115px; }
.heating-observations dd { margin: 0; font-weight: 700; }

.heating-health {
  color: #526555;
  font-size: 0.71rem;
  font-weight: 750;
}

.heating-health::before {
  display: inline-block;
  width: 7px;
  height: 7px;
  margin-right: 6px;
  border-radius: 50%;
  background: #88938a;
  content: '';
}

.heating-health.online::before { background: #43a047; }
.heating-health.offline { color: #9b443b; }
.heating-health.offline::before { background: #c45146; }

.heating-mode-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  margin-bottom: 14px;
}

.heating-mode-row {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}

.heating-mode {
  min-height: 42px;
  padding: 8px 16px;
  border: 1px solid #b9c9bb;
  border-radius: 10px;
  background: #fff;
  color: #304833;
  font: inherit;
  font-size: 0.78rem;
  font-weight: 800;
  cursor: pointer;
  transition: background 140ms ease, border-color 140ms ease, box-shadow 140ms ease, color 140ms ease;
}

.heating-mode:hover { border-color: #758c79; }

.heating-mode.active {
  border-color: #4c5b50;
  background: #4c5b50;
  color: #fff;
  box-shadow: 0 2px 8px rgba(51, 62, 54, 0.18);
}

.heating-mode[data-heating-mode="auto"].active {
  border-color: #34763b;
  background: #34763b;
}

.heating-mode.force { border-color: #ddb38d; color: #934200; }
.heating-mode.force.active { border-color: #a84f00; background: #a84f00; color: #fff; }

.heating-message {
  min-height: 0;
  padding: 6px 10px;
  border-radius: 8px;
  color: #607563;
  font-size: 0.72rem;
  font-weight: 700;
  opacity: 0;
  transition: opacity 140ms ease;
}

.heating-message.visible { background: #f0f6f0; opacity: 1; }
.heating-message.error { background: #fff0ee; color: #a33c32; }
.heating-message:empty { display: none; }

.heating-metric {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 8px 20px;
  min-width: 0;
  padding: 10px 14px;
  background: #f7faf7;
  border: 1px solid transparent;
  border-radius: 10px;
}

.heating-metric.warning {
  background: #fff8e8;
  border-color: #eed49b;
}

.heating-metric span,
.heating-metric small {
  display: block;
  color: #6a796c;
  font-size: 0.72rem;
}

.heating-metric strong {
  display: block;
  margin: 5px 0;
  color: #2e3c30;
  font-size: 1.18rem;
}

.heating-metric small {
  line-height: 1.4;
  overflow-wrap: anywhere;
}

.heating-auto-settings {
  margin-top: 12px;
  padding: 14px;
  background: #f7faf7;
  border: 1px solid #dce7dd;
  border-radius: 12px;
  transition: background 140ms ease, border-color 140ms ease;
}

.heating-setting > small {
  margin-top: 3px;
  color: #748076;
  font-size: 0.67rem;
}

.heating-settings {
  display: grid;
  grid-template-columns: 220px 170px 170px;
  align-items: end;
  justify-content: start;
  gap: 10px;
}

.heating-setting {
  display: grid;
  width: 100%;
  max-width: 170px;
  gap: 5px;
  color: #5f7061;
  font-size: 0.68rem;
  font-weight: 700;
}

.heating-setting-target { max-width: 220px; }

.heating-setting-label { display: block; }

.heating-setting > small {
  min-height: 1em;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.heating-stepper {
  display: grid;
  grid-template-columns: 44px minmax(0, 1fr) 44px;
  min-height: 44px;
  overflow: hidden;
  background: #fff;
  border: 1px solid #becbbe;
  border-radius: 10px;
  transition: border-color 140ms ease, box-shadow 140ms ease;
}

.heating-stepper:focus-within {
  border-color: var(--green-600);
  box-shadow: 0 0 0 3px rgba(76, 175, 80, 0.12);
}

.heating-stepper > button {
  min-width: 44px;
  min-height: 44px;
  padding: 0;
  border: 0;
  background: #f1f6f1;
  color: #36503a;
  font: inherit;
  font-size: 1.25rem;
  font-weight: 800;
  cursor: pointer;
  touch-action: manipulation;
  transition: background 120ms ease, color 120ms ease;
}

.heating-stepper > button:first-child { border-right: 1px solid #d7e0d8; }
.heating-stepper > button:last-child { border-left: 1px solid #d7e0d8; }
.heating-stepper > button:hover:not(:disabled) { background: #e4efe5; }
.heating-stepper > button:active:not(:disabled) { background: #d6e8d8; }
.heating-stepper > button:disabled { color: #aeb8af; cursor: default; }

.heating-input {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 42px;
  padding: 0 7px;
  color: #738075;
  font-size: 0.72rem;
  font-weight: 750;
}

.heating-input > span { white-space: nowrap; }

.heating-settings input {
  width: 3.2em;
  min-width: 0;
  min-height: 40px;
  padding: 7px 3px;
  border: 0;
  outline: 0;
  background: transparent;
  color: #263b28;
  font: inherit;
  font-size: 0.92rem;
  font-weight: 750;
  text-align: right;
}

.heating-settings input::-webkit-inner-spin-button,
.heating-settings input::-webkit-outer-spin-button { margin: 0; appearance: none; }

.heating-setting-target .heating-setting-label {
  color: #344b37;
  font-size: 0.74rem;
  font-weight: 800;
}

.heating-setting-target .heating-stepper {
  grid-template-columns: 48px minmax(0, 1fr) 48px;
  min-height: 50px;
  border-color: #9fbaa3;
}

.heating-setting-target .heating-stepper > button {
  min-width: 48px;
  min-height: 48px;
  font-size: 1.4rem;
}

.heating-setting-target input {
  font-size: 1.12rem;
  font-weight: 850;
}

.heating-hysteresis-note {
  margin-top: 12px;
  color: #68776b;
  font-size: 0.66rem;
  line-height: 1.35;
}

.heating-settings-error {
  margin-top: 7px;
  color: #a33c32;
  font-size: 0.67rem;
  font-weight: 700;
}

.heating-history {
  margin-top: 16px;
  padding-top: 14px;
  border-top: 1px solid #e3e9e4;
  color: #526555;
  font-size: 0.74rem;
}

.heating-history-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 6px;
}

.heating-history-head h3 { color: #3b503e; font-size: 0.79rem; }
.heating-history-head span { color: #879088; font-size: 0.64rem; }
.heating-events { display: grid; }

.heating-event {
  display: grid;
  grid-template-columns: 82px 1fr;
  gap: 12px;
  padding: 6px 0;
  border-bottom: 1px solid #f0f3f0;
}

.heating-event time { color: #7b897d; font-variant-numeric: tabular-nums; }
.heating-event span { color: #334a36; }
.heating-events-empty { padding: 8px 0; color: #7b897d; }

.heating-technical-history { margin-top: 8px; }

.heating-technical-history summary {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 0;
  color: #5f7362;
  font-size: 0.7rem;
  font-weight: 750;
  cursor: pointer;
  list-style: none;
}

.heating-technical-history summary::-webkit-details-marker { display: none; }
.heating-technical-history summary::before { content: '›'; font-size: 1rem; transition: transform 120ms ease; }
.heating-technical-history[open] summary::before { transform: rotate(90deg); }
.heating-events.technical { max-height: 340px; margin-top: 4px; overflow-y: auto; }
.heating-events.technical .heating-event { grid-template-columns: 135px 1fr; padding: 4px 0; font-size: 0.68rem; }

.temperature-buildings {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 10px;
}

.temperature-building {
  padding: 10px;
  background: #f7faf7;
  border-radius: 10px;
}

.temperature-building h3 { margin-bottom: 7px; color: #415544; font-size: 0.82rem; }
.temperature-sensors { display: grid; gap: 5px; }
.temperature-sensor { display: grid; grid-template-columns: 1fr auto; align-items: baseline; gap: 2px 8px; }
.temperature-sensor span { overflow: hidden; color: #526555; font-size: 0.75rem; text-overflow: ellipsis; white-space: nowrap; }
.temperature-sensor strong { color: #263b28; font-size: 1rem; }
.temperature-sensor small { grid-column: 1 / -1; color: #849086; font-size: 0.62rem; }
.temperature-sensor.stale strong { color: #ba7900; }
.temperature-sensor.expired strong,
.temperature-sensor.none strong { color: #9b5555; }
.thermostat-details { grid-column: 1 / -1; display: flex; flex-wrap: wrap; gap: 3px 10px; margin-bottom: 5px; }
.thermostat-details span { font-size: 0.66rem; }
.thermostat-relay { border-radius: 4px; padding: 1px 4px; background: #edf0ec; }
.thermostat-relay.on { color: #246637; background: #dff1df; }

@media (max-width: 760px) {
  .nagyterem-panel,
  .temperature-panel { margin: 10px; }
  .heating-summary { grid-template-columns: minmax(0, 1fr); gap: 10px; }
  .heating-summary-health { text-align: left; }
  .heating-mode-bar { align-items: flex-start; flex-direction: column; }
  .heating-message { min-height: 0; }
  .heating-settings { grid-template-columns: repeat(2, 170px); }
  .heating-setting-target { grid-column: 1 / -1; }
}

@media (max-width: 480px) {
  .nagyterem-head { align-items: stretch; flex-direction: column; }
  .heating-summary-state { align-items: flex-start; flex-direction: column; }
  .heating-mode-row { width: 100%; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .heating-mode { padding: 8px 7px; }
  .btn-row { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .heating-settings { grid-template-columns: minmax(0, 1fr); }
  .heating-setting-target { grid-column: auto; }
  .heating-event { grid-template-columns: 68px 1fr; gap: 8px; }
}

body.mode-kiosk .nagyterem-panel,
body.mode-kiosk .temperature-panel {
  flex: 0 0 auto;
  width: calc(100% - 20px);
  max-width: none;
  margin: 10px 10px 0;
  padding: 12px;
}

body.mode-kiosk .nagyterem-panel { min-height: 260px; }
body.mode-kiosk .temperature-panel { min-height: 330px; }
body.mode-kiosk .nagyterem-head,
body.mode-kiosk .temperature-head { margin-bottom: 10px; }
body.mode-kiosk .nagyterem-head h2,
body.mode-kiosk .temperature-head h2 { font-size: 1.35rem; }
body.mode-kiosk .heating-metric strong { font-size: 1.35rem; }
body.mode-kiosk .temperature-buildings { grid-template-columns: repeat(5, minmax(0, 1fr)); }
body.mode-kiosk .device-grid { padding-top: 10px; }

body.mode-kiosk .device-card {
  min-height: 0;
  gap: 10px;
  padding: 14px 16px 14px 18px;
}

body.mode-kiosk .card-name {
  font-size: 1.25rem;
}

body.mode-kiosk .card-main {
  align-items: center;
}

body.mode-kiosk .card-primary-value {
  font-size: 2.4rem;
}

body.mode-kiosk .device-card.state-running .card-primary-value {
  font-size: 3rem;
}

body.mode-kiosk .card-primary-caption,
body.mode-kiosk .card-energy-line,
body.mode-kiosk .card-transport {
  font-size: 0.85rem;
}

body.mode-kiosk .card-setpoint {
  font-size: 0.9rem;
}

/* Opening a device still exposes the full remote. It scrolls inside its own
   pane if necessary instead of re-enabling scrolling on the embedded page. */
body.mode-kiosk #remote.view.active {
  overflow-y: auto;
}

/* ── Animations ── */

@keyframes fadeIn {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}

.device-card { animation: fadeIn 0.3s ease both; }
