:root {
  --bg: #f0f4f8;
  --bg-deep: #e2e8f0;
  --card: #ffffff;
  --card-hover: #f8fafc;
  --card-elev: #f1f5f9;
  --accent: #cbd5e1;
  --accent-soft: #94a3b8;
  --text: #0f172a;
  --text-dim: #334155;
  --text-faint: #64748b;
  --primary: #2563eb;
  --primary-soft: rgba(37, 99, 235, 0.12);
  --warning: #d97706;
  --danger: #dc2626;
  --success: #16a34a;
  --radius: 14px;
  --radius-sm: 8px;
  --shadow: 0 4px 16px rgba(0, 0, 0, 0.10);
  --shadow-soft: 0 2px 8px rgba(0, 0, 0, 0.06);
  --transition: 0.2s cubic-bezier(0.4, 0, 0.2, 1);

  /* ---------- Display sizing (2026-09-29) ----------
     --cm-u scales the ENTIRE clock-mode composition as one piece.
     Reference design = 960x540 (today's 1920x1080 look / 2), so at
     1080p --cm-u resolves to 2px and the desktop appearance is
     pixel-identical. fit = min of the two viewport ratios, so portrait,
     landscape, any aspect — no overflow, no per-size re-testing.
     --cm-scale comes from the display class (see blocks below). */
  --cm-scale: 1;
  --cm-u: calc(min(100vw / 960, 100vh / 540) * var(--cm-scale));
  /* Dashboard viewport budget. Per-class values below; these are the
     medium (1080p) defaults and the no-JS fallback. */
  --grid-cols: 5;
  --card-h: 400px;

  /* ---------- Visual pass (2026-10-04) ----------
     --font-num: Bahnschrift (Windows built-in DIN 1451 descendant —
     the numerals of transit signage) for every number that updates:
     clock, weather temp, timers, power, stats. tabular-nums keeps
     digits from jittering as they tick. */
  --font-num: 'Bahnschrift', 'Segoe UI', system-ui, sans-serif;

  /* Domain accents — the Planner's paper-book type language extended
     to the whole dashboard: plan=blue ink, list=green, reminder/attention
     =amber, note=slate, sky=environment, media=violet, energy=gold.
     Light-theme values here; [data-scheme="dark"] (set from --bg
     luminance by updateColorScheme() in dashboard.js) swaps in the
     brighter variants. NEVER themed per-preset — these are semantic. */
  --dom-plan: #2b50a8;
  --dom-list: #1f7a3d;
  --dom-reminder: #b45309;
  --dom-note: #52607a;
  --dom-sky: #0369a1;
  --dom-media: #6d28d9;
  --dom-energy: #a16207;
  --dom-topic: #0f766e;
  --dom-food: #b91c1c;
}
/* Dark-scheme domain accents: brighter hues that read on dark cards
   (data-scheme is derived from the ACTIVE --bg, so custom themes and
   presets both land correctly without touching THEME_VARS). */
[data-scheme="dark"] {
  --dom-plan: #8ab0f8;
  --dom-list: #5fc98d;
  --dom-reminder: #e8a44c;
  --dom-note: #9dabc4;
  --dom-sky: #5db6e8;
  --dom-media: #b39af5;
  --dom-energy: #d9b44a;
  --dom-topic: #2dd4bf;
  --dom-food: #f27272;
}
/* Display classes — set pre-paint by the inline detector in index.html
   (a manual Screen Size choice in the Display modal overrules it).
   Ladder keys on min(width,height) in CSS px, so a 13" 1080p touch at
   125% OS scaling (reports 1536x864) lands in the smaller class. */
[data-display="small"]  { --grid-cols: 2; --card-h: 300px;                                        --cm-scale: 0.85; }
[data-display="tablet"] { --grid-cols: 4; --card-h: clamp(260px, calc((100vh - 220px) / 2), 340px); --cm-scale: 0.92; }
[data-display="medium"] { --grid-cols: 5; --card-h: clamp(280px, calc((100vh - 220px) / 2), 400px); --cm-scale: 1; }
[data-display="large"]  { --grid-cols: 5; --card-h: clamp(300px, calc((100vh - 220px) / 2), 420px); --cm-scale: 1.1; }
[data-display="xlarge"] { --grid-cols: 5; --card-h: clamp(320px, calc((100vh - 220px) / 2), 460px); --cm-scale: 1.25; }
/* Portrait orientation: fewer columns at the same class */
[data-display="small"][data-orientation="portrait"]  { --grid-cols: 1; }
[data-display="tablet"][data-orientation="portrait"] { --grid-cols: 2; }
[data-display="medium"][data-orientation="portrait"] { --grid-cols: 2; }
[data-display="large"][data-orientation="portrait"]  { --grid-cols: 3; }
[data-display="xlarge"][data-orientation="portrait"] { --grid-cols: 3; }
* { margin: 0; padding: 0; box-sizing: border-box; }
html, body { height: 100%; }
/* App shell: body is a fixed-height column — header + tabs pin at the top
   and the active panel fills the rest and scrolls internally (the Music
   tab's pattern, generalized to every tab). 100dvh tracks mobile browser
   chrome; 100vh is the fallback for older engines. Fixed-position
   children (modals, greeting banner, voice bubble, #clock-mode) are not
   flex items, so they are unaffected. */
body {
  background: var(--bg);
  background-image:
    radial-gradient(ellipse 80% 50% at 20% 0%, rgba(37, 99, 235, 0.05), transparent),
    radial-gradient(ellipse 60% 40% at 80% 100%, rgba(37, 99, 235, 0.04), transparent);
  background-attachment: fixed;
  color: var(--text);
  font-family: 'Segoe UI', system-ui, -apple-system, sans-serif;
  height: 100vh;
  height: 100dvh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  padding: 20px;
  -webkit-font-smoothing: antialiased;
  transition: background 2s ease;
}

/* Time-of-day gradient overlay */
body::before {
  content: '';
  position: fixed;
  top: 0; left: 0; right: 0; bottom: 0;
  z-index: -1;
  pointer-events: none;
  transition: opacity 2s ease;
  opacity: 0.3;
}
body.tod-morning::before {
  background: linear-gradient(180deg, rgba(255, 200, 100, 0.12) 0%, transparent 40%, rgba(100, 180, 255, 0.06) 100%);
}
body.tod-day::before {
  background: linear-gradient(180deg, rgba(100, 180, 255, 0.08) 0%, transparent 50%);
}
body.tod-evening::before {
  background: linear-gradient(180deg, rgba(255, 140, 60, 0.10) 0%, rgba(200, 100, 200, 0.06) 50%, transparent 100%);
}
body.tod-night::before {
  background: linear-gradient(180deg, rgba(20, 20, 60, 0.15) 0%, rgba(10, 10, 40, 0.08) 100%);
}

/* Greeting banner — white speech bubble anchored just after the header
   weather box (JS-measured at show time; falls back to the clock block
   when weather hasn't rendered). Explicit dark-on-white colors: it
   floats over any theme. Dashboard-only (clock mode, z-1800, covers it). */
.greeting-banner {
  position: fixed;
  top: 20px;
  left: 20px;
  z-index: 1500;
  padding: 10px 18px;
  border-radius: 18px;
  font-size: 0.95rem;
  background: #ffffff;
  color: #1f2937;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.28);
  opacity: 0;
  transform: translateY(-50%) translateY(-6px);
  transition: opacity 0.5s ease, transform 0.5s ease;
  pointer-events: none;
  max-width: 60%;
  text-align: left;
}
.greeting-banner.show {
  opacity: 1;
  transform: translateY(-50%) translateY(0);
}

/* Device card toggle animation */
@keyframes deviceGlow {
  0% { box-shadow: 0 0 0 0 var(--primary-soft); }
  50% { box-shadow: 0 0 12px 4px var(--primary-soft); }
  100% { box-shadow: 0 0 0 0 var(--primary-soft); }
}
.device-card.toggled {
  animation: deviceGlow 0.6s ease;
}
@keyframes countUp {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: translateY(0); }
}
.stat-value {
  animation: countUp 0.4s ease;
}

/* ===================== Clock Mode ===================== */
/* Fullscreen clock — opened by clicking the header clock block.
   z-index 1800: above normal content + greeting banner (1500),
   below modals (2000+) so ringing alarms / notifications still appear. */
#clock-mode {
  display: none;
  position: fixed;
  top: 0; left: 0; right: 0; bottom: 0;
  z-index: 1800;
  background: var(--bg);
  flex-direction: column;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  user-select: none;
  -webkit-user-select: none;
}
#clock-mode.active { display: flex; }
.clock-mode-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0;
  text-align: center;
  padding: 0 4vw;
  animation: clockModeIn 0.6s cubic-bezier(0.2, 0.8, 0.25, 1);
}
@keyframes clockModeIn {
  from { opacity: 0; transform: scale(0.92); }
  to { opacity: 1; transform: scale(1); }
}
.clock-mode-time {
  /* 19vw @1080p = 364.8px = 182.4u — pure proportional, no clamp: the
     fit-scale handles every size the clamp used to guess at */
  font-size: calc(182.4 * var(--cm-u));
  font-weight: 700;
  font-family: var(--font-num);
  line-height: 1;
  letter-spacing: 0.02em;
  font-variant-numeric: tabular-nums;
  color: var(--primary);
  white-space: nowrap;
}
.clock-mode-sec {
  font-size: 0.28em;
  font-weight: 600;
  color: var(--text-faint);
  margin-left: 0.12em;
  vertical-align: baseline;
}
.clock-mode-date {
  margin-top: 0.9em;
  /* 3.4vw @1080p = 65.28px = 32.64u */
  font-size: calc(32.64 * var(--cm-u));
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text);
  cursor: pointer;
}
.clock-mode-date:hover { color: var(--primary); }
.clock-mode-alarm {
  margin-top: 1.1em;
  /* 2vw @1080p = 38.4px = 19.2u */
  font-size: calc(19.2 * var(--cm-u));
  color: var(--text-dim);
  display: flex;
  align-items: center;
  gap: 0.5em;
  cursor: pointer;
}
.clock-mode-alarm:hover { color: var(--text); }
.clock-mode-alarm:empty { display: none; }
/* Oversized control buttons (larger than standard .btn) — laid out by
   .clock-mode-bottom */
.clock-mode-btn {
  padding: calc(7.5 * var(--cm-u)) calc(16 * var(--cm-u));
  min-height: calc(29 * var(--cm-u));
  font-size: calc(9.6 * var(--cm-u));
  font-weight: 600;
  font-family: inherit;
  border: 1px solid var(--accent-soft);
  background: var(--accent);
  color: var(--text);
  border-radius: calc(7 * var(--cm-u));
  cursor: pointer;
  transition: var(--transition);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: calc(5 * var(--cm-u));
  white-space: nowrap;
}
.clock-mode-btn:hover { background: var(--accent-soft); border-color: var(--primary); transform: translateY(-1px); }
.clock-mode-btn:active { transform: scale(0.97); }
/* Voice mode active — green with pulsing dot */
.clock-mode-btn.on {
  background: var(--success);
  border-color: var(--success);
  color: #fff;
}
.clock-mode-btn.on::after {
  content: '';
  width: calc(5 * var(--cm-u)); height: calc(5 * var(--cm-u));
  border-radius: 50%;
  background: #fff;
  animation: pulse 1.5s infinite;
}
/* DND active — amber, muted state */
.clock-mode-btn.dnd-on {
  background: var(--warning);
  border-color: var(--warning);
  color: #fff;
}
/* Night dim active — indigo */
.clock-mode-btn.dim-on {
  background: var(--primary);
  border-color: var(--primary);
  color: #fff;
}
/* Room lights on — warm amber */
.clock-mode-btn.lights-on {
  background: var(--warning);
  border-color: var(--warning);
  color: #fff;
}
/* Bottom control row: one centered strip — Exit, Display, Voice, Lights,
   DND, Dim */
.clock-mode-bottom {
  position: absolute;
  bottom: calc(14 * var(--cm-u));
  left: 0;
  right: 0;
  z-index: 2;
  display: flex;
  justify-content: center;
  align-items: center;
  gap: calc(7 * var(--cm-u));
  flex-wrap: wrap;
  padding: 0 calc(8 * var(--cm-u));
  animation: clockModeBottomIn 0.6s cubic-bezier(0.2, 0.8, 0.25, 1);
}
@keyframes clockModeBottomIn {
  from { opacity: 0; transform: translateY(calc(9 * var(--cm-u))); }
  to { opacity: 1; transform: translateY(0); }
}
/* While the voice-listening bubble (fixed bottom-center, z-2000) is
   visible, the button row shifts up above it. NOTE: the fullscreen
   overlay is #clock-mode with NO clock-mode class — the selector must
   be id-based or it never matches. 74px @1080p = 37u — identical on
   desktop. */
#clock-mode.voice-bubble .clock-mode-bottom { bottom: calc(37 * var(--cm-u)); }
/* Upper-left stack in clock mode: the SAME hero as the header block
   (buildWeatherHero) with the device name / room underneath */
.clock-mode-wx {
  position: absolute;
  top: calc(14 * var(--cm-u));
  left: calc(14 * var(--cm-u));
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: calc(5 * var(--cm-u));
  animation: clockModeCornerInLeft 0.6s cubic-bezier(0.2, 0.8, 0.25, 1);
}
.clock-mode-wx #clock-mode-weather {
  cursor: pointer;
}
.clock-mode-wx .wx-hero {
  margin: 0;
  border: 1px solid rgba(78, 158, 255, 0.08);
}
/* Corner hero sizing: between the compact header hero and the card
   hero — clock mode is read from across the room */
.clock-mode-wx .wx-hero-icon { font-size: 2.6rem; }
.clock-mode-wx .wx-hero-temp { font-size: 2.2rem; }
/* Device name / room — same color as the big clock time */
.clock-mode-device {
  font-size: calc(9.2 * var(--cm-u));
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--primary);
  padding: 0 calc(2 * var(--cm-u));
  max-width: 40vw;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Timers box in clock mode — upper-right, all active timers (any
   device), earliest expiry first. Same grey card as the weather hero
   in the upper-left (var(--bg-deep)). */
.clock-mode-timers {
  position: absolute;
  top: calc(14 * var(--cm-u));
  right: calc(14 * var(--cm-u));
  z-index: 2;
  background: var(--bg-deep);
  border: 1px solid rgba(78, 158, 255, 0.08);
  border-radius: var(--radius-sm);
  padding: calc(4 * var(--cm-u)) calc(6 * var(--cm-u));
  min-width: calc(75 * var(--cm-u));
  max-width: calc(125 * var(--cm-u));
  animation: clockModeCornerIn 0.6s cubic-bezier(0.2, 0.8, 0.25, 1);
}
.cm-timers-title {
  font-size: calc(5.44 * var(--cm-u));
  font-weight: 700;
  color: var(--primary);
  text-transform: uppercase;
  letter-spacing: calc(0.5 * var(--cm-u));
  margin-bottom: calc(2 * var(--cm-u));
}
.cm-timer-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: calc(6 * var(--cm-u));
  font-size: calc(7.04 * var(--cm-u));
  color: var(--text);
  padding: calc(0.5 * var(--cm-u)) 0;
}
.cm-timer-label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.cm-timer-remaining {
  font-variant-numeric: tabular-nums;
  color: var(--text-dim);
  white-space: nowrap;
}
.cm-timer-row.paused .cm-timer-remaining {
  color: var(--text-faint);
  font-style: italic;
}
@keyframes clockModeCornerIn {
  from { opacity: 0; transform: translateX(calc(9 * var(--cm-u))); }
  to { opacity: 1; transform: translateX(0); }
}
@keyframes clockModeCornerInLeft {
  from { opacity: 0; transform: translateX(calc(-9 * var(--cm-u))); }
  to { opacity: 1; transform: translateX(0); }
}
/* Night dim overlay — above every layer (incl. weather detail 9999);
   pointer-events none so nothing beneath is blocked */
#dim-overlay {
  position: fixed;
  top: 0; left: 0; right: 0; bottom: 0;
  z-index: 10000;
  background: #000;
  opacity: 0;
  pointer-events: none;
  transition: opacity 2s ease;
}

/* ---------- Display settings (dim / brightness / themes) ---------- */
.display-dim-toggle {
  width: 100%;
  padding: 12px 16px;
  min-height: 48px;
  font-size: 1rem;
  font-weight: 600;
  font-family: inherit;
  border: 1px solid var(--accent-soft);
  background: var(--accent);
  color: var(--text);
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: var(--transition);
}
.display-dim-toggle.on {
  background: var(--primary);
  border-color: var(--primary);
  color: #fff;
}
.theme-select-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
  gap: 10px;
  max-height: 55vh;
  overflow-y: auto;
}
.theme-select-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 10px 6px 8px;
  border: 2px solid var(--accent);
  border-radius: var(--radius-sm);
  background: var(--card);
  cursor: pointer;
  transition: var(--transition);
  position: relative;
}
.theme-select-item:hover { border-color: var(--accent-soft); transform: translateY(-1px); }
.theme-select-item.selected { border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-soft); }
.theme-select-swatch {
  width: 100%;
  height: 44px;
  border-radius: 6px;
  border: 1px solid rgba(0,0,0,0.08);
}
.theme-select-name {
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--text);
  text-align: center;
}
.theme-select-item.selected .theme-select-name::after { content: ' ✓'; color: var(--primary); }
/* Clock-mode small-screen breakpoint REMOVED (2026-09-29): the --cm-u
   fit-scale handles every size proportionally — fixed-px overrides here
   would fight it. */

/* ---------- Screen Size chips (Display modal) ---------- */
.size-select-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
}
.size-chip {
  padding: 8px 4px;
  min-height: 48px;
  font-size: 0.85rem;
  font-weight: 600;
  font-family: inherit;
  border: 2px solid var(--accent);
  border-radius: var(--radius-sm);
  background: var(--card);
  color: var(--text);
  cursor: pointer;
  transition: var(--transition);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
}
.size-chip:hover { border-color: var(--accent-soft); transform: translateY(-1px); }
.size-chip.selected { border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-soft); }
.size-chip-sub {
  font-size: 0.64rem;
  font-weight: 500;
  color: var(--text-faint);
  white-space: nowrap;
}
.size-chip.selected .size-chip-sub { color: var(--primary); }

/* ---------- Small-display modal polish (Phase 4) ----------
   Device Settings, alarms, calendar popup and friends on 5-7" panels:
   tighter chrome, touch-sized controls. */
[data-display="small"] .modal { padding: 12px; max-height: 94vh; overflow-y: auto; }
[data-display="small"] .modal-title { font-size: 0.95rem; }
[data-display="small"] .modal .btn,
[data-display="small"] .modal button.cal-nav-btn { min-height: 44px; }
[data-display="small"] .modal .btn { font-size: 0.8rem; padding: 8px 10px; }
[data-display="small"] .modal-actions { flex-wrap: wrap; gap: 6px; }
[data-display="small"] .cal-grid { font-size: 0.62rem; }
[data-display="small"] .cal-nav-btn { min-width: 34px; min-height: 34px; }
[data-display="small"] .device-alarms-list .alarm-row,
[data-display="small"] #device-alarms-list > div { font-size: 0.78rem; }

/* ---------- Header ---------- */
.header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  flex-shrink: 0;
  margin-bottom: 8px;
  padding: 0 4px 10px;
  border-bottom: 1px solid rgba(78, 158, 255, 0.12);
}
.header-left { display: flex; align-items: center; gap: 20px; }
.clock-block { display: flex; flex-direction: column; gap: 2px; }
.clock {
  font-size: 3.2rem;
  font-weight: 700;
  font-family: var(--font-num);
  letter-spacing: 3px;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  color: var(--primary);
}
.date {
  font-size: 1.05rem;
  color: var(--primary);
  letter-spacing: 0.5px;
  font-weight: 700;
}
.header-right { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; justify-content: flex-end; }
.header-controls { display: flex; flex-direction: column; align-items: stretch; gap: 2px; }
.status-row { display: flex; align-items: center; gap: 6px; justify-content: flex-start; }
/* Header icon buttons: two compact rows under the status indicator
   (row 1: voice / stop media / intercom / full screen; row 2: display /
   device / settings / customize). FIXED 30px squares + left-aligned
   rows — content-sized buttons rendered at different emoji widths and
   stair-stepped the columns. */
.header-btn-rows { display: flex; flex-direction: column; gap: 3px; }
.header-btn-row { display: flex; align-items: center; gap: 4px; justify-content: flex-start; }
.btn.header-btn {
  width: 30px;
  height: 30px;
  padding: 0;
  font-size: 0.88rem;
  line-height: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
}
.btn.header-btn[disabled] { opacity: 0.35; cursor: not-allowed; }
.header-btns { display: flex; align-items: center; gap: 6px; }
.header-btns .btn { width: 38px; height: 32px; display: flex; align-items: center; justify-content: center; padding: 0; }
/* Pinned header widgets */
.header-pinned { display: flex; gap: 8px; align-items: flex-start; }
.header-pin-widget {
  background: var(--card);
  border-radius: var(--radius-sm);
  padding: 6px 8px;
  border: 1px solid rgba(78, 158, 255, 0.08);
  box-shadow: var(--shadow-soft);
  min-width: 130px;
  max-width: 200px;
  height: 100px;
  box-sizing: border-box;
  overflow: hidden;
}
#header-pin-airquality {
  min-width: 280px;
  max-width: 300px;
}
#header-pin-climate {
  min-width: 190px;
  max-width: 220px;
}
.header-pin-title {
  font-size: 0.7rem;
  font-weight: 700;
  color: var(--text-faint);
  text-transform: uppercase;
  letter-spacing: 0.5px;
  margin-bottom: 4px;
}
/* Pinned-widget title row with inline controls (DND / Speak) */
.header-pin-row {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 4px;
}
.header-pin-row .header-pin-title {
  margin-bottom: 0;
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.header-pin-row .notif-w-dnd { flex-shrink: 0; }
.header-pin-row .notif-w-speak-label { flex-shrink: 0; font-size: 0.62rem; }
.header-aq-list, .header-climate-list { display: flex; flex-direction: column; gap: 2px; }
.header-aq-row {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 0.72rem;
}
.header-aq-room { font-weight: 600; color: var(--text); width: 80px; flex-shrink: 0; }
.header-aq-badge {
  font-size: 0.62rem;
  font-weight: 600;
  padding: 1px 6px;
  border-radius: 8px;
  width: 72px;
  text-align: center;
  flex-shrink: 0;
}
.header-aq-badge.excellent { background: rgba(22,163,74,0.15); color: var(--success); }
.header-aq-badge.good { background: rgba(22,163,74,0.1); color: var(--success); }
.header-aq-badge.moderate { background: rgba(217,119,6,0.15); color: var(--warning); }
.header-aq-badge.poor { background: rgba(220,38,38,0.15); color: var(--danger); }
.header-aq-badge.unknown { background: var(--accent-soft); color: var(--text-faint); }
.header-aq-filter {
  font-size: 0.6rem;
  font-weight: 600;
  padding: 1px 5px;
  border-radius: 8px;
  width: 52px;
  text-align: center;
  flex-shrink: 0;
}
.header-aq-filter.f-good { background: rgba(22,163,74,0.12); color: var(--success); }
.header-aq-filter.f-med { background: rgba(217,119,6,0.12); color: var(--warning); }
.header-aq-filter.f-low { background: rgba(220,38,38,0.12); color: var(--danger); }
.header-aq-pm { font-size: 0.65rem; color: var(--text-dim); margin-left: auto; text-align: right; }
/* Header climate rows */
.header-climate-row {
  display: flex;
  align-items: center;
  gap: 3px;
  font-size: 0.68rem;
  justify-content: flex-start;
}
.header-climate-room { font-weight: 600; color: var(--text); width: 90px; flex-shrink: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.header-climate-temp { font-size: 0.78rem; font-weight: 700; color: var(--text); width: 38px; text-align: center; flex-shrink: 0; }
.header-climate-hum { font-size: 0.62rem; color: var(--text-dim); text-align: right; display: flex; align-items: center; gap: 1px; flex-shrink: 0; }
.header-climate-hum::before { content: '💧'; font-size: 0.55rem; }
/* Pin checkbox in customize mode */
.pin-checkbox {
  display: none;
  align-items: center;
  gap: 4px;
  font-size: 0.65rem;
  color: var(--text-dim);
  white-space: nowrap;
}
body.customize-mode .pin-checkbox { display: flex; }
.pin-checkbox input { width: 14px; height: 14px; cursor: pointer; }
.header-timers {
  display: none;
  flex-direction: column;
  gap: 2px;
  padding: 5px 10px;
  background: var(--bg-deep);
  border-radius: var(--radius-sm);
  border: 1px solid rgba(78, 158, 255, 0.12);
  min-width: 140px;
  max-width: 220px;
}
.header-timers.has-timers { display: flex; }
.header-timers-title {
  font-size: 0.6rem;
  color: var(--text-faint);
  text-transform: uppercase;
  letter-spacing: 0.5px;
}
.header-timer-row {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 0.78rem;
}
.header-timer-label {
  color: var(--text-dim);
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.header-timer-remaining {
  font-weight: 600;
  color: var(--warning);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.header-timer-remaining.expired { color: var(--danger); }
/* Header weather block (original size) */
.weather-block {
  display: flex;
  align-items: center;
}
/* Header weather: the hero keeps its own card box look — background
   matching the forecast box beside it */
#weather-block .wx-hero {
  margin: 0;
  border: 1px solid rgba(78, 158, 255, 0.08);
}

/* Weather card */
.weather-card-body {
  padding: 8px 4px;
}
.weather-detail-pill {
  font-size: 0.68rem;
  color: var(--text-dim);
  background: var(--card);
  border-radius: 10px;
  padding: 2px 8px;
  border: 1px solid rgba(0, 0, 0, 0.06);
  white-space: nowrap;
  display: inline-block;
  line-height: 1.4;
}
/* ── Hourly forecast chart (forecast modal) ── */
#hourly-chart { position: relative; }
.hc-uv-note {
  font-size: 0.72rem;
  color: var(--text-dim);
  margin-bottom: 6px;
}
.hc-grid {
  display: flex;
  align-items: stretch;
  gap: 1px;
  position: relative;
}
.hc-col {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  border-radius: 4px;
  padding: 2px 0 0;
  cursor: default;
}
.hc-col:hover { background: var(--primary-soft); }
.hc-col.now { background: var(--primary-soft); box-shadow: inset 0 0 0 1px var(--accent-soft); }
.hc-temp {
  font-size: 0.55rem;
  color: var(--text-dim);
  height: 12px;
  line-height: 12px;
  white-space: nowrap;
}
.hc-icon {
  font-size: 0.72rem;
  height: 16px;
  line-height: 16px;
  filter: grayscale(0.15);
}
.hc-barzone {
  position: relative;
  width: 100%;
  height: 96px;
  display: flex;
  align-items: flex-end;
  justify-content: center;
}
.hc-rain {
  position: absolute;
  bottom: 0;
  width: 100%;
  background: rgba(78, 158, 255, 0.22);
  border-radius: 2px 2px 0 0;
}
.hc-bar {
  width: 72%;
  background: var(--primary);
  border-radius: 3px 3px 0 0;
  min-height: 4px;
}
.hc-col.now .hc-bar { background: var(--accent); }
.hc-time {
  font-size: 0.55rem;
  color: var(--text-faint);
  margin-top: 3px;
  height: 12px;
  white-space: nowrap;
}
.hc-legend {
  display: flex;
  gap: 12px;
  margin-top: 6px;
  font-size: 0.68rem;
  color: var(--text-faint);
}
.hc-swatch {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 2px;
  vertical-align: middle;
  margin-right: 3px;
}
.hc-swatch-now { background: var(--accent); }
.hc-swatch-temp { background: var(--primary); }
.hc-swatch-rain { background: rgba(78, 158, 255, 0.4); }
.hc-tooltip {
  display: none;
  position: absolute;
  z-index: 20;
  background: var(--text);
  color: var(--bg);
  border-radius: 8px;
  padding: 6px 9px;
  font-size: 0.68rem;
  line-height: 1.5;
  pointer-events: none;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
  max-width: 190px;
  white-space: nowrap;
}
.hc-tooltip .hc-tt-time {
  font-weight: 600;
  margin-bottom: 2px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.2);
  padding-bottom: 2px;
}
/* Weather card body fills the card and scrolls (consistent w/ calendar, notif) */
#dashboard-grid .weather-card-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
}
/* ── Current Weather card: hero + sections (Phase 6) ── */
.wx-hero {
  display: flex;
  align-items: center;
  gap: 12px;
  background: var(--bg-deep);
  border-radius: var(--radius-sm);
  padding: 10px 12px;
  margin-bottom: 8px;
  flex-shrink: 0;
}
.wx-hero-icon { font-size: 3.2rem; line-height: 1; }
.wx-hero-main {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
  flex: 1;
}
/* temp + UV bubble on one row (UV sits right of the temperature) */
.wx-hero-temp-row { display: flex; align-items: center; gap: 8px; min-width: 0; }
.wx-hero-temp {
  font-size: 2.6rem;
  font-weight: 600;
  font-family: var(--font-num);
  color: var(--text);
  line-height: 1;
  letter-spacing: 0.01em;
  font-variant-numeric: tabular-nums;
}
/* Header hero (beside the 3.2rem clock) stays compact */
#weather-block .wx-hero-icon { font-size: 2.2rem; }
#weather-block .wx-hero-temp { font-size: 2.1rem; }
/* the UV pill in the header hero — the blue-on-white bubble standard */
.wx-hero-uv {
  color: var(--primary);
  background: #ffffff;
  border: 1px solid rgba(0, 0, 0, 0.08);
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.14);
  flex-shrink: 0;
}
.wx-hero-cond {
  font-size: 0.75rem;
  color: var(--text-dim);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.wx-hero-range { font-size: 0.68rem; color: var(--text-faint); }
.wx-hero-norm { color: var(--text-faint); opacity: 0.8; }
.wx-hero-alert {
  flex-shrink: 0;
  align-self: stretch;
  display: flex;
  align-items: center;
  padding: 4px 10px;
  border-radius: 8px;
  font-size: 0.72rem;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
  max-width: 45%;
  overflow: hidden;
  text-overflow: ellipsis;
  border: 1px solid transparent;
}
.wx-hero-alert.alert-warn {
  color: var(--danger);
  border-color: var(--danger);
  background: rgba(220, 38, 38, 0.07);
}
.wx-hero-alert.alert-watch {
  color: var(--warning);
  border-color: var(--warning);
  background: rgba(217, 119, 6, 0.07);
}
.wx-alert-extra {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin: -2px 0 8px 0;
}
/* Weather card sections: ONE wrapping row — the label sits INLINE and
   the bubble pills flow right after it (user 2026-10-02). Labels + pill
   text are BLUE like the card title (grey was not visible). STANDARD:
   any variable data in this widget = blue text in a WHITE bubble. */
.wx-section {
  background: var(--bg-deep);
  border-radius: var(--radius-sm);
  padding: 8px 10px;
  margin-bottom: 8px;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 6px;
}
.wx-section-label {
  font-size: 0.6rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.8px;
  color: var(--primary);
  margin-right: 2px;
}
.wx-section .weather-detail-pill {
  color: var(--primary);
  background: #ffffff;
  border: 1px solid rgba(0, 0, 0, 0.08);
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.14);
}
/* insight + yesterday-comparison bubbles wrap their (longer) text */
.wx-section .weather-detail-pill.wx-insight-pill { white-space: normal; }
.wx-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 2px 6px;
}
.wx-cell {
  font-size: 0.72rem;
  color: var(--text-dim);
  line-height: 1.35;
  min-width: 0;
}
.wx-line-link {
  cursor: pointer;
  text-decoration: underline dotted rgba(120, 130, 145, 0.55);
  text-underline-offset: 3px;
}
/* Alert-aware card state */
.card[data-widget="weather"].has-warning {
  border-color: var(--danger);
  box-shadow: 0 1px 3px rgba(220, 38, 38, 0.25);
}
.card[data-widget="weather"].has-watch {
  border-color: var(--warning);
  box-shadow: 0 1px 3px rgba(217, 119, 6, 0.22);
}
/* Condition-tinted hero (2026-10-04): the hero wash now reflects WHAT'S
   HAPPENING (wxTintClass in dashboard.js) instead of the hour — a
   glance at the dashboard reads the sky, not the clock. Replaces the
   former body.tod-* hero washes. */
.wx-hero.wx-tint-sun {
  background: linear-gradient(135deg, rgba(245, 158, 11, 0.20), var(--bg-deep) 65%);
}
.wx-hero.wx-tint-partly {
  background: linear-gradient(135deg, rgba(245, 158, 11, 0.10), rgba(56, 132, 232, 0.14), var(--bg-deep) 65%);
}
.wx-hero.wx-tint-cloud {
  background: linear-gradient(135deg, rgba(100, 116, 139, 0.18), var(--bg-deep) 65%);
}
.wx-hero.wx-tint-rain {
  background: linear-gradient(135deg, rgba(56, 132, 232, 0.22), var(--bg-deep) 65%);
}
.wx-hero.wx-tint-snow {
  background: linear-gradient(135deg, rgba(147, 197, 253, 0.28), var(--bg-deep) 65%);
}
.wx-hero.wx-tint-storm {
  background: linear-gradient(135deg, rgba(124, 92, 214, 0.24), var(--bg-deep) 65%);
}
.wx-hero.wx-tint-fog {
  background: linear-gradient(135deg, rgba(148, 163, 184, 0.30), var(--bg-deep) 65%);
}
.wx-hero.wx-tint-night {
  background: linear-gradient(135deg, rgba(67, 74, 160, 0.26), var(--bg-deep) 65%);
}
/* ── Weather tab card grid (2026-10-04 restyle) ──
   The old forecast-modal 3-column blob became a responsive grid of
   auto-height cards — same visual language as the dashboard and news
   grids (sky domain bars, card titles, hover lift, skeletons). No
   widget machinery: it's one report, read top-to-bottom. The 24-hour
   chart card spans two columns; radar anchors the end. */
#wx-cards {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
  align-items: start;  /* auto-height cards — no row equalization */
}
#wx-cards .card.span2 { grid-column: span 2; }
#wx-cards .card { --dom: var(--dom-sky); }
#wx-cards .card-title { color: var(--dom-sky); }
#wx-cards .card::before {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 3px;
  background: var(--dom, var(--dom-sky));
  opacity: 0.9;
  border-radius: var(--radius) var(--radius) 0 0;
  pointer-events: none;
}
#wx-cards .card:hover {
  transform: translateY(-3px);
  box-shadow: 0 10px 24px rgba(0, 0, 0, 0.13);
  border-color: var(--dom, rgba(37, 99, 235, 0.25));
}
@media (max-width: 1100px) {
  #wx-cards { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 720px) {
  #wx-cards { grid-template-columns: 1fr; }
  #wx-cards .card.span2 { grid-column: span 1; }
}
/* Display-aware density — mirrors the dashboard/news grids */
[data-display="large"] #wx-cards { gap: 12px; }
[data-display="xlarge"] #wx-cards { gap: 14px; }
[data-display="large"] #wx-cards .card { padding: 14px; }
[data-display="xlarge"] #wx-cards .card { padding: 16px; }
/* Now card: hero reuses .wx-hero (+ wxTintClass tint); Hi/Lo row in
   DIN numerals with norm captions */
.wx-hilo { display: flex; gap: 16px; flex-wrap: wrap; margin-top: 10px; }
.wx-hilo-cap { font-size: 0.68rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.6px; color: var(--text-faint); margin-right: 2px; }
.wx-hilo-val { font-family: var(--font-num); font-variant-numeric: tabular-nums; font-weight: 600; font-size: 1.35rem; color: var(--text); }
.wx-hilo-norm { font-size: 0.72rem; color: var(--text-faint); }
/* Yesterday comparison line under Hi/Lo (Now card) */
.wx-yesterday { margin-top: 8px; font-size: 0.78rem; color: var(--text-faint); line-height: 1.45; }
/* Wrapping pill cloud inside weather cards (current conditions, sun &
   moon) — same flow as the dashboard card's .wx-section */
.wx-pills {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 6px;
}
/* Source footnote under the card grid */
.wx-source { margin-top: 8px; font-size: 0.8em; color: var(--text-faint); }
/* Weather modal alert banner */
.wx-modal-alert {
  display: flex;
  align-items: center;
  gap: 8px;
  border-radius: 8px;
  padding: 8px 12px;
  margin-bottom: 6px;
  cursor: pointer;
  font-weight: 600;
  font-size: 0.85rem;
}
.wx-modal-alert.warn {
  background: rgba(220, 38, 38, 0.12);
  border: 1px solid var(--danger);
  color: var(--danger);
}
.wx-modal-alert.watch {
  background: rgba(217, 119, 6, 0.12);
  border: 1px solid var(--warning);
  color: var(--warning);
}
.wx-modal-alert.info {
  background: rgba(78, 158, 255, 0.10);
  border: 1px solid var(--accent);
  color: var(--text-dim);
}
.wx-modal-alert-icon { font-size: 1.05rem; }
.wx-modal-alert-text {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.wx-modal-alert-exp {
  font-size: 0.7rem;
  font-weight: 400;
  opacity: 0.8;
  white-space: nowrap;
}
.wx-modal-alert-extra {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin: 0 0 10px;
}
/* Alert pills by EC severity */
.alert-pill.alert-warn {
  border-color: var(--danger);
  color: var(--danger);
  background: rgba(220, 38, 38, 0.06);
  font-weight: 500;
}
.alert-pill.alert-watch {
  border-color: var(--warning);
  color: var(--warning);
  background: rgba(217, 119, 6, 0.06);
  font-weight: 500;
}
.weather-aqhi-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 20px;
  height: 16px;
  border-radius: 4px;
  font-size: 0.62rem;
  font-weight: 600;
  padding: 0 4px;
}
.weather-aqhi-low { background: rgba(80, 250, 123, 0.15); color: var(--success); }
.weather-aqhi-mod { background: rgba(255, 179, 71, 0.15); color: var(--warning); }
.weather-aqhi-high { background: rgba(255, 85, 85, 0.15); color: var(--danger); }
.weather-aqhi-vhigh { background: rgba(167, 87, 202, 0.2); color: #a757ca; }
.weather-uv-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 20px;
  height: 16px;
  border-radius: 4px;
  font-size: 0.62rem;
  font-weight: 600;
  padding: 0 4px;
}
.weather-uv-low { background: rgba(80, 250, 123, 0.25); color: #1a1a1a; }
.weather-uv-mod { background: rgba(255, 215, 0, 0.3); color: #1a1a1a; }
.weather-uv-high { background: rgba(255, 140, 0, 0.3); color: #1a1a1a; }
.weather-uv-vhigh { background: rgba(255, 85, 85, 0.3); color: #1a1a1a; }
.weather-uv-extreme { background: rgba(167, 87, 202, 0.3); color: #1a1a1a; }
.weather-forecast-box {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 3px;
  padding: 8px 14px;
  background: var(--bg-deep);
  border-radius: var(--radius-sm);
  border: 1px solid rgba(78, 158, 255, 0.08);
  max-width: 100%;
  min-height: 100%;
}
.weather-forecast-title {
  font-size: 0.65rem;
  color: var(--text-faint);
  text-transform: uppercase;
  letter-spacing: 0.5px;
  cursor: pointer;
  text-decoration: underline;
  text-decoration-style: dotted;
  text-underline-offset: 2px;
}
.weather-forecast-title:hover { color: var(--primary); }
.weather-forecast-text {
  font-size: 0.75rem;
  color: var(--text-dim);
  line-height: 1.45;
}
.alert-modal-text {
  white-space: pre-wrap;
  font-size: 0.85rem;
  line-height: 1.5;
  color: var(--text);
  max-height: 50vh;
  overflow-y: auto;
  padding: 12px;
  background: var(--bg-deep);
  border-radius: var(--radius-sm);
}
.status-dot {
  width: 10px; height: 10px; border-radius: 50%;
  background: var(--success);
  box-shadow: 0 0 8px var(--success);
  animation: pulse 2s ease-in-out infinite;
}
.status-dot.offline { background: var(--danger); box-shadow: 0 0 8px var(--danger); }
@keyframes pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.5; }
}
.status-text { font-size: 0.85rem; color: var(--text-dim); }
/* HA connection chip (ha_health monitor) — sits with the server status
   row. Server dot = assistant↔browser; this chip = assistant↔HA. */
.ha-chip {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 0.68rem;
  font-weight: 700;
  color: var(--text-dim);
  padding: 1px 7px;
  border-radius: 9px;
  background: var(--bg-deep);
  border: 1px solid var(--border);
  white-space: nowrap;
  cursor: default;
}
.ha-chip .ha-chip-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--text-faint);
  flex-shrink: 0;
}
.ha-chip.up .ha-chip-dot { background: var(--success); }
.ha-chip.down .ha-chip-dot { background: var(--danger); }
.ha-chip.down { color: var(--danger); border-color: rgba(220, 38, 38, 0.35); }

/* ---------- Tabs ---------- */
.tabs {
  display: flex;
  gap: 4px;
  margin-bottom: 20px;
  flex-shrink: 0;
  background: var(--bg-deep);
  padding: 6px;
  border-radius: var(--radius);
  box-shadow: var(--shadow-soft);
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}
.tab {
  flex: 1;
  min-width: 110px;
  padding: 12px 16px;
  border: none;
  background: transparent;
  color: var(--text-dim);
  font-size: 1rem;
  font-weight: 500;
  cursor: pointer;
  border-radius: var(--radius-sm);
  transition: var(--transition);
  white-space: nowrap;
  font-family: inherit;
}
.tab:hover { color: var(--text); background: var(--accent-soft); }
.tab.active {
  background: var(--accent);
  color: var(--text);
  box-shadow: 0 2px 8px rgba(15, 52, 96, 0.5);
}
.tab-icon { margin-right: 6px; font-size: 1.1em; }
/* Tab reordering (any customize mode) */
body.customize-mode .tab,
body.cmd-customize .tab,
body.cam-customize .tab,
body.dev-customize .tab,
body.news-customize .tab { cursor: grab; }
.tab.dragging { opacity: 0.4; border: 2px dashed var(--primary); }
.tab.drag-over { outline: 2px dashed var(--primary); outline-offset: -2px; }

/* ---------- Panels ---------- */
.panel { display: none; animation: fadeIn 0.3s ease; }
/* Active panel = the shell's scroll area: fills the space under header +
   tabs and scrolls its own content (the page itself never scrolls).
   min-height: 0 lets the panel shrink past its content's intrinsic
   height so the panel scrollbar is the only one. */
.panel.active {
  display: block;
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
}
/* Music tab keeps its own app-style column (#panel-music.active in
   music.css: flex column + musicFitPanel height + #music-body scroller);
   the rules above compose with it — same px, no double scrollbar. */

/* ---------- Row snap (scroll one row at a time) ----------
   Gentle proximity snap on the list-style tabs: the browser only rounds
   to the nearest row when you stop near a boundary — free scrolling
   everywhere else. Music / Media / Weather stay free-scroll. Toolbars
   ride along with the content (no sticky). */
#panel-dashboard.active,
#panel-cameras.active,
#panel-commands.active,
#panel-news.active,
#panel-devices.active {
  scroll-snap-type: y proximity;
}
/* Snap targets: every row card, plus the Devices-tab sections so a stop
   can land on a section/room top rather than mid-card. */
#dashboard-grid > .card,
#dashboard-grid > .card-pair,
#news-widgets > .card,
.camera-grid > .camera-card,
.commands-grid > .command-card,
.device-grid > .device-card,
.domain-section,
.room-widget,
#battery-monitor-section,
#power-config-section {
  scroll-snap-align: start;
}
@keyframes fadeIn {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: translateY(0); }
}

/* ---------- Grid & Cards ---------- */
/* Columns come from the display class (--grid-cols, set pre-paint by
   the detector / Display-modal choice). The old width media queries
   are gone — one source of truth instead of four breakpoint blocks. */
.grid {
  display: grid;
  grid-template-columns: repeat(var(--grid-cols), 1fr);
  gap: 10px;
}
.card {
  background: var(--card);
  border-radius: var(--radius);
  padding: 11px;
  border: 1px solid rgba(0, 0, 0, 0.08);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08), 0 1px 2px rgba(0, 0, 0, 0.04);
  transition: var(--transition);
  position: relative;
}
/* Main-grid widgets: card height from the display class (--card-h,
   fluid clamp against the viewport so 2 rows fit without scrolling).
   Header stays fixed; content areas scroll internally where wired below.
   .card-pair (shopping + to-do) stacks two half-height cards in one slot. */
#dashboard-grid .card {
  box-sizing: border-box;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
#dashboard-grid > .card { height: var(--card-h); }
#dashboard-grid .card-pair {
  display: flex;
  flex-direction: column;
  gap: 10px;
  height: var(--card-h);
  box-sizing: border-box;
}
#dashboard-grid .card-pair > .card { flex: 1 1 0; min-height: 0; }
/* Shopping + to-do: side-by-side pair — two thinner full-height cards
   in ONE widget slot (one grid unit for moving AND hiding; the pair
   collapses entirely when both are hidden — see .card-pair.hidden-widget) */
#dashboard-grid .card-pair.card-pair-row { flex-direction: row; }
#dashboard-grid .card-pair.card-pair-row > .card { min-width: 0; }
/* A pair whose members are all hidden must not leave an empty 400px hole */
.card-pair.hidden-widget { display: none !important; }
body.customize-mode .card-pair.hidden-widget {
  display: flex !important;
  opacity: 0.5;
  outline: 1px dashed var(--text-faint);
  outline-offset: 2px;
}
/* Clickable widget titles — open the matching Planner view */
.card-title-link { cursor: pointer; transition: color var(--transition); }
.card-title-link .icon { transition: transform var(--transition); }
.card-title-link:hover { color: var(--text); text-decoration: underline; }
.card-title-link:hover .icon { transform: scale(1.1); }
/* Shopping / to-do widget bodies: fill the half card and scroll */
#dashboard-grid .list-scroll {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
}
.card-pair.dragging { opacity: 0.4; outline: 2px dashed var(--primary); outline-offset: 2px; }
.card-pair.drag-over { outline: 2px dashed var(--primary); outline-offset: 2px; }
#dashboard-grid .card-header { flex-shrink: 0; }
/* Calendar: month grid fixed, event list takes remaining space and scrolls */
#dashboard-grid .cal-nav,
#dashboard-grid .cal-grid { flex-shrink: 0; }
#dashboard-grid .cal-events-list {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
}
/* Notifications card: list fills remaining space and scrolls */
#dashboard-grid .notif-w-list {
  flex: 1;
  min-height: 0;
  max-height: none;
  overflow-y: auto;
}
.card:hover { border-color: rgba(37, 99, 235, 0.25); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.10); }
/* Hover lift (2026-10-04): dashboard cards rise to meet the cursor.
   Disabled in customize mode (dragging) and mid-drag. */
#dashboard-grid .card:hover {
  transform: translateY(-3px);
  box-shadow: 0 10px 24px rgba(0, 0, 0, 0.13);
  border-color: var(--dom, rgba(37, 99, 235, 0.25));
}
body.customize-mode #dashboard-grid .card:hover { transform: none; }
#dashboard-grid .card.dragging,
#dashboard-grid .card.drag-over { transform: none; }
.card.dragging { opacity: 0.4; border: 2px dashed var(--primary); }
.card.drag-over { border: 2px dashed var(--primary); }
.card.hidden-widget { display: none !important; }
/* In customize mode, show hidden widgets semi-transparent with a Show button */
body.customize-mode .card.hidden-widget { display: block !important; opacity: 0.5; border-style: dashed; }
body.customize-mode .card.hidden-widget .widget-settings::after { content: ' Show'; }
.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 9px;
}
.card-title {
  font-size: 0.76rem;
  font-weight: 700;
  color: var(--primary);
  text-transform: uppercase;
  letter-spacing: 0.8px;
  display: flex;
  align-items: center;
  gap: 6px;
  /* Narrow cards: let the title shrink and CLIP (the .news-updated
     stamp is nowrap) instead of spilling over the header controls.
     An overflowing title covered the ⚙ gear — the finger cursor and
     the dead "click" were the title-link eating the press. */
  min-width: 0;
  overflow: hidden;
}
.card-title .icon { font-size: 1.15rem; }
/* ---------- Domain accents (2026-10-04) ----------
   Every dashboard widget carries its domain's hue: a 3px top bar plus
   the card-title text itself. The mapping mirrors the Planner's type
   language (calendar=blue ink, lists=green, reminders/alerts=amber,
   notes=slate) extended to the non-planner widgets. Emoji icons keep
   their own color; the title + bar carry the coding. */
#dashboard-grid .card-title { color: var(--dom, var(--primary)); }
/* hover keeps the original text-color affordance (the domain rule above
   outranks the global .card-title-link:hover — restore it scoped) */
#dashboard-grid .card-title-link:hover { color: var(--text); }
#dashboard-grid .card::before {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 3px;
  background: var(--dom, var(--primary));
  opacity: 0.9;
  border-radius: var(--radius) var(--radius) 0 0;
  pointer-events: none;
}
#dashboard-grid .card[data-widget="calendar"] { --dom: var(--dom-plan); }
#dashboard-grid .card[data-widget="shopping"],
#dashboard-grid .card[data-widget="todo"],
#dashboard-grid .card[data-widget="lists"] { --dom: var(--dom-list); }
#dashboard-grid .card[data-widget="notes"],
#dashboard-grid .card[data-widget="memories"],
#dashboard-grid .card[data-widget="newstop"],
#dashboard-grid .card[data-widget="stats"] { --dom: var(--dom-note); }
#dashboard-grid .card[data-widget="weather"],
#dashboard-grid .card[data-widget="airquality"] { --dom: var(--dom-sky); }
#dashboard-grid .card[data-widget="cameras"] { --dom: var(--dom-media); }
#dashboard-grid .card[data-widget="lights"],
#dashboard-grid .card[data-widget="motion"],
#dashboard-grid .card[data-widget="climate"],
#dashboard-grid .card[data-widget="notifications"] { --dom: var(--dom-reminder); }
#dashboard-grid .card[data-widget="power"] { --dom: var(--dom-energy); }
#dashboard-grid .card[data-widget="recipes"] { --dom: var(--dom-food); }
/* ---------- Display-aware density (2026-10-04) ----------
   large/xlarge screens get airier cards (padding, grid gap) and
   larger in-card text; the 5-col grid keeps its shape — only the
   rhythm scales. medium (1080p) is the reference design. */
[data-display="large"] #dashboard-grid { gap: 12px; }
[data-display="xlarge"] #dashboard-grid { gap: 14px; }
[data-display="large"] #dashboard-grid .card-pair { gap: 12px; }
[data-display="xlarge"] #dashboard-grid .card-pair { gap: 14px; }
[data-display="large"] #dashboard-grid .card { padding: 14px; }
[data-display="xlarge"] #dashboard-grid .card { padding: 16px; }
[data-display="large"] #dashboard-grid .card-title { font-size: 0.8rem; }
[data-display="xlarge"] #dashboard-grid .card-title { font-size: 0.84rem; }
[data-display="large"] #dashboard-grid .event-title,
[data-display="large"] #dashboard-grid .list-item .text,
[data-display="large"] #dashboard-grid .note-title,
[data-display="large"] #dashboard-grid .light-on-row,
[data-display="large"] #dashboard-grid .motion-row,
[data-display="large"] #dashboard-grid .aq-room { font-size: 0.88rem; }
[data-display="xlarge"] #dashboard-grid .event-title,
[data-display="xlarge"] #dashboard-grid .list-item .text,
[data-display="xlarge"] #dashboard-grid .note-title,
[data-display="xlarge"] #dashboard-grid .light-on-row,
[data-display="xlarge"] #dashboard-grid .motion-row,
[data-display="xlarge"] #dashboard-grid .aq-room { font-size: 0.95rem; }
[data-display="large"] #dashboard-grid .cal-day { font-size: 0.74rem; }
[data-display="xlarge"] #dashboard-grid .cal-day { font-size: 0.8rem; }
[data-display="large"] .stat-big { font-size: 1.7rem; }
[data-display="xlarge"] .stat-big { font-size: 1.9rem; }
[data-display="xlarge"] #dashboard-grid .power-val { font-size: 0.92rem; }
/* ---------- Blank spacer widget (2026-10-04) ----------
   An empty grid slot that behaves like any other widget (⚙ hide,
   drag to move) but renders NOTHING when shown: no card, no border,
   no domain bar, no hover lift. Ships hidden; enable it in customize
   mode, where a dashed ghost + its controls become visible so it can
   be identified, dragged and hidden again. */
#dashboard-grid .card[data-widget="blank"] {
  background: transparent;
  border-color: transparent;
  box-shadow: none;
}
#dashboard-grid .card[data-widget="blank"]::before { display: none; }
#dashboard-grid .card[data-widget="blank"] .card-header { display: none; }
#dashboard-grid .card[data-widget="blank"]:hover {
  transform: none;
  border-color: transparent;
  box-shadow: none;
}
body.customize-mode #dashboard-grid .card[data-widget="blank"] {
  background: var(--card);
  border: 1px dashed var(--accent-soft);
  box-shadow: none;
}
body.customize-mode #dashboard-grid .card[data-widget="blank"]:hover {
  transform: none;
}
body.customize-mode #dashboard-grid .card[data-widget="blank"] .card-header { display: flex; }
/* Header controls never shrink or get pushed out of the card — the
   title clips instead (see .card-title). Without this the ⚙ gear
   squeezed to ~21px and slid outside narrow cards, unclickable. */
.card-actions { display: flex; gap: 6px; align-items: center; margin-left: auto; flex-shrink: 0; }
/* Header dropdowns (Lists list-picker, Lights room filter) ride the
 * RIGHT edge — select takes the auto margin, actions hug it after. */
.card-header .card-title + select { margin-left: auto; }
.card-header select + .card-actions { margin-left: 0; }
.widget-settings {
  display: none;
  background: transparent;
  border: 1px solid var(--text-faint);
  color: var(--text-dim);
  width: 28px; height: 28px;
  flex-shrink: 0;
  border-radius: 6px;
  cursor: pointer;
  font-size: 0.9rem;
  transition: var(--transition);
}
body.customize-mode .widget-settings { display: flex; align-items: center; justify-content: center; }
.widget-settings:hover { color: var(--warning); border-color: var(--warning); }
.widget-drag {
  display: none;
  cursor: grab;
  color: var(--text-faint);
  font-size: 1.1rem;
  padding: 0 4px;
  flex-shrink: 0;
}
body.customize-mode .widget-drag { display: block; }
body.news-customize #news-widgets .widget-drag { display: block; }
body.customize-mode .card { cursor: grab; }

/* ---------- List items / events / timers / notes ---------- */
.item-row {
  padding: 6px 0;
  border-bottom: 1px solid rgba(78, 158, 255, 0.06);
  display: flex;
  align-items: center;
  gap: 7px;
}
.item-row:last-child { border-bottom: none; }
.event-time {
  display: inline-block;
  min-width: 38px;
  color: var(--primary);
  font-weight: 600;
  font-size: 0.78rem;
  font-variant-numeric: tabular-nums;
}
.event-title { font-size: 0.82rem; flex: 1; }
.event-loc { font-size: 0.7rem; color: var(--text-dim); margin-top: 1px; }
.event-item:hover { background: rgba(78, 158, 255, 0.08); border-radius: 4px; }
/* Event detail modal */
.event-detail-row { display: flex; gap: 10px; padding: 4px 0; }
.event-detail-label { min-width: 70px; font-weight: 600; color: var(--text-dim); font-size: 0.82rem; }

/* ---------- Mini Calendar (2026-10-02 A-E rework) ---------- */
.cal-nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 5px;
}
.cal-nav-btn {
  background: transparent;
  border: none;
  color: var(--text-dim);
  font-size: 1rem;
  cursor: pointer;
  padding: 1px 6px;
  border-radius: 4px;
  transition: var(--transition);
}
.cal-nav-btn:hover { color: var(--primary); background: var(--accent-soft); }
.cal-nav-title { font-size: 0.78rem; font-weight: 700; color: var(--text); letter-spacing: 0.3px; }
.cal-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 2px;
  margin-bottom: 7px;
}
.cal-dow {
  text-align: center;
  font-size: 0.56rem;
  color: var(--primary);
  text-transform: uppercase;
  padding: 1px 0;
  font-weight: 700;
  letter-spacing: 0.5px;
}
.cal-day {
  text-align: center;
  font-size: 0.68rem;
  padding: 3px 0 9px;
  border-radius: 5px;
  color: var(--text-dim);
  position: relative;
  font-variant-numeric: tabular-nums;
}
.cal-day.in-month { cursor: pointer; }
.cal-day.in-month:hover { background: var(--accent-soft); }
.cal-day.other-month { color: var(--text-faint); opacity: 0.4; padding: 3px 0; }
.cal-day.today {
  background: var(--primary);
  color: #fff;
  font-weight: 700;
  box-shadow: 0 0 0 2px rgba(78, 158, 255, 0.35);
}
.cal-day.selected {
  background: var(--accent-soft);
  color: var(--primary);
  font-weight: 700;
  box-shadow: inset 0 0 0 1px var(--primary);
}
/* stacked event dots (up to 3 + a faded "more" dot) */
.cal-dots { position: absolute; bottom: 2px; left: 0; right: 0; display: flex; justify-content: center; gap: 2px; }
.cal-dots i { width: 3px; height: 3px; border-radius: 50%; background: var(--primary); display: block; }
.cal-dots i.more { opacity: 0.45; }
.cal-day.today .cal-dots i { background: #fff; }
.cal-events-list {
  border-top: 1px solid rgba(78, 158, 255, 0.1);
  padding-top: 6px;
}
.cal-events-list-title {
  font-size: 0.6rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.8px;
  color: var(--primary);
  margin-bottom: 4px;
}
.cal-clear { cursor: pointer; opacity: 0.75; font-weight: 600; }
.cal-clear:hover { opacity: 1; }
/* Next-up strip (C) — the widget's blue-on-white bubble standard */
.cal-next {
  display: flex;
  align-items: center;
  gap: 8px;
  background: #ffffff;
  color: var(--primary);
  border: 1px solid rgba(0, 0, 0, 0.06);
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.12);
  border-radius: 10px;
  padding: 7px 10px;
  margin-bottom: 8px;
  min-width: 0;
}
.cal-next-badge {
  background: var(--primary);
  color: #fff;
  border-radius: 4px;
  font-size: 0.52rem;
  font-weight: 700;
  letter-spacing: 0.6px;
  padding: 2px 5px;
}
.cal-next-title { flex: 1; font-weight: 700; font-size: 0.82rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cal-next-when { font-size: 0.7rem; font-weight: 600; white-space: nowrap; font-variant-numeric: tabular-nums; }
/* Day groups (A): white date chip + Today/Tomorrow/weekday label */
.cal-day-head { display: flex; align-items: center; gap: 7px; margin: 8px 0 3px; }
.cal-day-head:first-child { margin-top: 2px; }
.cal-date-chip {
  background: #ffffff;
  color: var(--primary);
  border: 1px solid rgba(0, 0, 0, 0.06);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
  border-radius: 8px;
  padding: 2px 7px;
  display: flex;
  flex-direction: column;
  align-items: center;
  line-height: 1.15;
  min-width: 30px;
}
.cal-date-chip b { font-size: 0.85rem; font-weight: 800; }
.cal-date-chip i { font-size: 0.5rem; font-style: normal; text-transform: uppercase; letter-spacing: 0.8px; font-weight: 700; opacity: 0.85; }
.cal-day-head-label { font-size: 0.62rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.8px; color: var(--primary); }
/* Event rows (B): colored type stripe, same blue time/title styling */
.evt-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 5px 7px;
  border-left: 3px solid var(--primary);
  border-radius: 6px;
  margin: 2px 0;
  cursor: pointer;
  min-width: 0;
}
.evt-row:hover { background: var(--accent-soft); }
.evt-k-event { border-left-color: var(--primary); }
.evt-k-reminder { border-left-color: var(--warning); }
.evt-k-list { border-left-color: #22c55e; }
.evt-k-note { border-left-color: var(--text-faint); }
/* Empty state (E) */
.cal-empty { text-align: center; font-size: 1.25rem; padding: 12px 0 6px; }
.cal-empty div { font-size: 0.75rem; color: var(--text-dim); margin-top: 3px; }
.cal-events-list-title {
  font-size: 0.6rem;
  color: var(--text-faint);
  text-transform: uppercase;
  letter-spacing: 0.5px;
  margin-bottom: 3px;
}

.timer-label { font-weight: 600; font-size: 1rem; flex: 1; }
.timer-remaining {
  font-size: 1.4rem;
  font-weight: 300;
  font-family: var(--font-num);
  color: var(--warning);
  font-variant-numeric: tabular-nums;
}
.timer-remaining.expired { color: var(--danger); }
.list-item { display: flex; align-items: center; gap: 7px; }
.list-item .check {
  color: var(--success);
  font-size: 0.9rem;
  cursor: pointer;
  min-width: 18px;
  text-align: center;
}
.list-item .check.unchecked { color: var(--text-faint); }
.list-item .text { flex: 1; font-size: 0.82rem; }
.list-item.completed .text { text-decoration: line-through; color: var(--text-dim); }
/* Dashboard list widgets: rows are clickable (toggle completed) and
   completed items collapse under a "Completed (N)" header — the same
   display language as the planner Lists view. */
#dashboard-grid .item-row.list-item.clickable { cursor: pointer; }
#dashboard-grid .item-row.list-item.clickable:hover {
  background: rgba(78, 158, 255, 0.07);
  border-radius: 4px;
}
.list-completed-head {
  margin-top: 8px;
  padding-top: 6px;
  border-top: 1.5px solid var(--border);
  font-size: 0.62rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 1px;
  color: var(--text-faint);
}
.note-title { font-weight: 600; font-size: 0.82rem; }
.note-body { font-size: 0.72rem; color: var(--text-dim); margin-top: 2px; line-height: 1.3; }
.empty { color: var(--text-dim); font-style: italic; padding: 8px 0; text-align: center; font-size: 0.78rem; }
.loading { color: var(--text-dim); padding: 8px 0; font-size: 0.78rem; }
/* Handwriting empty states (2026-10-04): the Planner's paper voice —
   Segoe Print, upright, quiet ink — for every widget's "nothing here
   yet" moment (dashboard grid + news tab). Modals keep the system
   style. */
#dashboard-grid .empty,
#dashboard-grid .news-empty,
#news-widgets .news-empty,
#panel-weather .empty {
  font-family: 'Segoe Print', 'Bradley Hand', 'Segoe UI', cursive;
  font-style: normal;
  font-size: 0.84rem;
  color: var(--text-faint);
  padding: 14px 6px;
  line-height: 1.5;
}
/* Big stat numerals (Today's Activity): DIN, tabular, scale with the
   display class — markup uses this class, not inline styles */
.stat-big {
  font-family: var(--font-num);
  font-variant-numeric: tabular-nums;
  font-size: 1.5rem;
  font-weight: 600;
  color: var(--text);
  line-height: 1.1;
}
/* Skeleton loading animation */
.skeleton {
  background: linear-gradient(90deg, var(--card-elev) 25%, var(--bg-deep) 50%, var(--card-elev) 75%);
  background-size: 200% 100%;
  animation: skeleton-shimmer 1.5s infinite;
  border-radius: var(--radius-sm);
  color: transparent;
  user-select: none;
}
@keyframes skeleton-shimmer {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}
.skeleton-line { height: 12px; margin: 6px 0; border-radius: 4px; }
.skeleton-line.w-60 { width: 60%; }
.skeleton-line.w-80 { width: 80%; }
.skeleton-line.w-40 { width: 40%; }
.skeleton-card { height: 60px; margin: 6px 0; border-radius: var(--radius-sm); }
.skeleton-row { display: flex; align-items: center; gap: 8px; margin: 6px 0; }
.skeleton-row .skeleton-dot { width: 16px; height: 16px; border-radius: 50%; flex-shrink: 0; }
.skeleton-row .skeleton-line { flex: 1; margin: 0; }

/* Settings category buttons */
.settings-category-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 12px 8px;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  cursor: pointer;
  font-size: 0.82rem;
  color: var(--text-dim);
  transition: var(--transition);
}
.settings-category-btn:hover {
  background: var(--card-hover);
  border-color: var(--primary);
  color: var(--text);
  transform: translateY(-1px);
  box-shadow: 0 2px 8px rgba(37, 99, 235, 0.15);
}
.settings-category-btn .cat-icon { font-size: 1.4rem; }

/* Offline mode — disable interactive controls */
body.is-offline .btn-icon,
body.is-offline .brightness-slider,
body.is-offline .light-color-btn-text,
body.is-offline .room-all-toggle,
body.is-offline .room-brightness,
body.is-offline .device-type-override,
body.is-offline #voice-btn,
body.is-offline #sync-btn,
body.is-offline .card-actions button,
body.is-offline .item-row { pointer-events: none; opacity: 0.5; }
body.is-offline .device-state::after { content: ' (offline)'; font-size: 0.6rem; opacity: 0.7; }
/* Lights On rows (2026-10-04): vertical item rows — the same display
   language as the shopping/to-do list widgets. The bulb leads, the
   name fills, and the amber room chip carries the lights-on hue. */
.light-on-row {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 5px 0;
  border-bottom: 1px solid rgba(217, 119, 6, 0.15);
  font-size: 0.78rem;
  color: var(--text);
}
.light-on-row:last-child { border-bottom: none; }
.light-on-row .bulb { font-size: 0.9rem; }
.light-on-row .name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.light-room-chip {
  font-size: 0.62rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--text-dim);
  background: rgba(217, 119, 6, 0.18);
  border: 1px solid rgba(217, 119, 6, 0.25);
  border-radius: 4px;
  padding: 1px 5px;
  white-space: nowrap;
}
#dash-lights { display: block; }
.motion-row {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 5px 0;
  border-bottom: 1px solid var(--accent-soft);
  font-size: 0.78rem;
}
.motion-row:last-child { border-bottom: none; }
.motion-row .motion-icon { font-size: 0.9rem; }
.motion-row .motion-name { flex: 1; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.motion-row .motion-time { font-size: 0.68rem; color: var(--text-faint); white-space: nowrap; font-variant-numeric: tabular-nums; font-family: var(--font-num); }
.motion-row .motion-det { font-size: 0.55rem; padding: 1px 5px; border-radius: 3px; white-space: nowrap; }
/* Power readings: DIN numerals, right-aligned (markup drops the old
   inline styles for this class) */
#dashboard-grid .power-val {
  margin-left: auto;
  font-weight: 600;
  font-size: 0.82rem;
  color: var(--text);
  font-family: var(--font-num);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.motion-det.on { background: rgba(22,163,74,0.15); color: var(--success); }
.motion-det.off { background: rgba(220,38,38,0.15); color: var(--danger); }
.motion-det.na { background: var(--accent-soft); color: var(--text-faint); }
/* Air quality widget */
.aq-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 0;
  border-bottom: 1px solid rgba(0,0,0,0.05);
}
.aq-row:last-child { border-bottom: none; }
.aq-room {
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--text);
  min-width: 70px;
}
.aq-badge {
  font-size: 0.68rem;
  font-weight: 600;
  padding: 2px 8px;
  border-radius: 10px;
  white-space: nowrap;
}
.aq-badge.excellent { background: rgba(22,163,74,0.15); color: var(--success); }
.aq-badge.good { background: rgba(22,163,74,0.1); color: var(--success); }
.aq-badge.moderate { background: rgba(217,119,6,0.15); color: var(--warning); }
.aq-badge.poor { background: rgba(220,38,38,0.15); color: var(--danger); }
.aq-badge.unknown { background: var(--accent-soft); color: var(--text-faint); }
.aq-pm25 {
  font-size: 0.72rem;
  color: var(--text-dim);
  margin-left: auto;
  white-space: nowrap;
}
.aq-fan-info {
  font-size: 0.68rem;
  color: var(--text-faint);
  white-space: nowrap;
}
.aq-filter {
  font-size: 0.68rem;
  font-weight: 600;
  padding: 2px 7px;
  border-radius: 10px;
  white-space: nowrap;
}
.aq-filter-good { background: rgba(22,163,74,0.12); color: var(--success); }
.aq-filter-med { background: rgba(217,119,6,0.12); color: var(--warning); }
.aq-filter-low { background: rgba(220,38,38,0.12); color: var(--danger); }
/* Room climate widget */
.climate-row {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 4px 0;
  border-bottom: 1px solid rgba(0,0,0,0.05);
}
.climate-row:last-child { border-bottom: none; }
.climate-room {
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--text);
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.climate-temp {
  font-size: 0.82rem;
  font-weight: 700;
  color: var(--text);
  white-space: nowrap;
}
/* Room climate grid: 3 rooms per line, room name above the gauges.
   Gauges sized so 6 rooms (2 rows x 3) fit the half-height card. */
.climate-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 6px;
  align-items: start;
}
.climate-cell {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  min-width: 0;
}
.climate-cell-room {
  font-size: 0.68rem;
  font-weight: 600;
  color: var(--text-dim);
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.climate-cell-gauges {
  display: flex;
  gap: 6px;
}
.climate-cell-gauges .gauge {
  width: 40px;
  height: 40px;
}
.climate-cell-gauges .gauge-label {
  font-size: 0.62rem;
}
/* Circular gauge */
.gauge {
  position: relative;
  width: 48px;
  height: 48px;
  flex-shrink: 0;
}
.gauge svg {
  transform: rotate(-90deg);
  width: 100%;
  height: 100%;
}
.gauge-bg {
  fill: none;
  stroke: rgba(0,0,0,0.08);
  stroke-width: 4;
}
.gauge-fg {
  fill: none;
  stroke-width: 4;
  stroke-linecap: round;
  transition: stroke-dashoffset 1s ease, stroke 0.5s ease;
}
.gauge-label {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  font-size: 0.7rem;
  font-weight: 700;
  text-align: center;
  line-height: 1;
}
.error-msg { color: var(--danger); padding: 12px 0; font-size: 0.9rem; }

/* ---------- Buttons ---------- */
.btn {
  padding: 10px 16px;
  border: 1px solid var(--accent-soft);
  background: var(--accent);
  color: var(--text);
  border-radius: var(--radius-sm);
  cursor: pointer;
  font-size: 0.92rem;
  font-weight: 500;
  font-family: inherit;
  transition: var(--transition);
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
}
.btn:hover { background: var(--accent-soft); border-color: var(--primary); }
.btn:active { transform: scale(0.97); }
.btn-primary { background: var(--primary); border-color: var(--primary); color: #fff; }
.btn-primary:hover { background: #3a8ae8; }
.btn-danger { background: transparent; border-color: rgba(255, 85, 85, 0.3); color: var(--danger); }
.btn-danger:hover { background: rgba(255, 85, 85, 0.1); border-color: var(--danger); }
.btn-sm { padding: 6px 10px; min-height: 36px; font-size: 0.82rem; }
.btn-icon {
  width: 36px; height: 36px;
  padding: 0;
  border: 1px solid transparent;
  background: transparent;
  color: var(--text-dim);
  border-radius: 6px;
  cursor: pointer;
  font-size: 1rem;
  transition: var(--transition);
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.btn-icon:hover { color: var(--danger); background: rgba(255, 85, 85, 0.08); }
.btn-icon.toggle-on { color: var(--success); }
.btn-icon.toggle-off { color: var(--text-faint); }
.btn-icon.toggle-off:hover { color: var(--primary); background: rgba(78, 158, 255, 0.08); }
.btn:disabled { opacity: 0.5; cursor: not-allowed; }

/* ---------- Forms / Inputs ---------- */
.input, .select, .textarea {
  width: 100%;
  padding: 10px 12px;
  background: var(--bg-deep);
  border: 1px solid var(--accent-soft);
  color: var(--text);
  border-radius: var(--radius-sm);
  font-size: 0.95rem;
  font-family: inherit;
  transition: var(--transition);
  min-height: 44px;
}
.input:focus, .select:focus, .textarea:focus {
  outline: none;
  border-color: var(--primary);
  box-shadow: 0 0 0 3px var(--primary-soft);
}
.textarea { resize: vertical; min-height: 80px; }
.form-row { display: flex; gap: 10px; margin-bottom: 10px; flex-wrap: wrap; }
.form-row > * { flex: 1; min-width: 120px; }
.form-group { margin-bottom: 10px; }
.form-group label {
  display: block;
  font-size: 0.78rem;
  color: var(--text-dim);
  margin-bottom: 4px;
  text-transform: uppercase;
  letter-spacing: 0.5px;
}
.add-form {
  display: flex;
  gap: 8px;
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid rgba(78, 158, 255, 0.06);
}
.add-form .input { flex: 1; }

/* ---------- Devices tab ---------- */
.devices-toolbar {
  display: flex;
  gap: 10px;
  margin-bottom: 16px;
  flex-wrap: wrap;
  align-items: center;
}
.devices-toolbar .select { max-width: 200px; }
.device-checkbox {
  display: flex;
  align-items: center;
  gap: 5px;
  font-size: 0.75rem;
  color: var(--text-dim);
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
}
.device-checkbox input { cursor: pointer; }
.device-show-checkbox {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 0.7rem;
  color: var(--text-dim);
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
}
.device-show-checkbox input { cursor: pointer; width: 14px; height: 14px; }
.domain-section { margin-bottom: 24px; }
.domain-header {
  font-size: 0.8rem;
  font-weight: 700;
  color: var(--primary);
  text-transform: uppercase;
  letter-spacing: 1.5px;
  margin-bottom: 10px;
  padding-bottom: 6px;
  border-bottom: 1px solid rgba(78, 158, 255, 0.1);
}
.device-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: 10px;
}
.room-widget-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 10px;
}
@media (max-width: 1100px) { .room-widget-grid { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 840px) { .room-widget-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 520px) { .room-widget-grid { grid-template-columns: 1fr; } }
.room-widget {
  background: var(--card);
  border-radius: var(--radius);
  padding: 10px;
  border: 1px solid rgba(78, 158, 255, 0.08);
  box-shadow: var(--shadow-soft);
}
.room-widget-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 6px;
  padding-bottom: 6px;
  border-bottom: 1px solid rgba(78, 158, 255, 0.08);
}
.room-widget-title { font-size: 0.85rem; font-weight: 600; }
.room-all-toggle {
  font-size: 0.65rem;
  padding: 2px 8px;
  border-radius: 10px;
  border: 1px solid var(--border);
  background: var(--bg-deep);
  color: var(--text);
  cursor: pointer;
  transition: var(--transition);
}
.room-all-toggle.on { background: var(--success); color: #fff; border-color: var(--success); }
.room-all-toggle:hover { opacity: 0.85; }
.room-widget .device-card { background: var(--bg-deep); padding: 6px 8px; gap: 4px; }
.room-widget-header .brightness-slider { height: 12px; }
.room-widget-header .brightness-label { font-size: 0.62rem; }
.room-color-btn { width: 14px; height: 14px; border-radius: 50%; border: 1px solid rgba(255,255,255,0.3); cursor: pointer; padding: 0; }
.room-color-btn:hover { transform: scale(1.3); border-color: #fff; }
.room-color-btn[data-label]::after { content: attr(data-label); position: absolute; bottom: -14px; left: 50%; transform: translateX(-50%); font-size: 0.55rem; white-space: nowrap; pointer-events: none; opacity: 0; transition: opacity 0.2s; }
.room-color-btn:hover[data-label]::after { opacity: 1; }
.room-color-btns { position: relative; }
.room-device-grid { grid-template-columns: repeat(4, 1fr); gap: 4px; }
.room-widget .device-name { font-size: 0.78rem; white-space: normal; word-break: break-word; }
.room-widget .device-area { font-size: 0.68rem; }
.room-widget .device-state { font-size: 0.65rem; padding: 1px 6px; }
.room-widget .brightness-slider { height: 12px; }
.room-widget .brightness-label { font-size: 0.65rem; }
.room-widget .light-brightness-slider { width: 40px; height: 4px; }
.room-widget .light-brightness-slider::-webkit-slider-thumb { width: 10px; height: 10px; }
.room-widget .light-color-btn { width: 18px; height: 18px; font-size: 0.75rem; border-radius: 4px; }
.device-card {
  background: var(--bg-deep);
  border-radius: var(--radius-sm);
  padding: 12px 14px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  border: 1px solid transparent;
  transition: var(--transition);
}
.device-card:hover { border-color: rgba(78, 158, 255, 0.15); }
body.dev-customize .device-card { cursor: grab; border-style: dashed; }
body.dev-customize .device-card.dragging { opacity: 0.4; }
body.dev-customize .device-card.drag-over { border-color: var(--primary); box-shadow: 0 0 0 2px rgba(78,158,255,0.3); }
body.dev-customize .room-widget { cursor: grab; border-style: dashed; }
body.dev-customize .room-widget.dragging { opacity: 0.4; }
body.dev-customize .room-widget.drag-over { border-color: var(--primary); box-shadow: 0 0 0 2px rgba(78,158,255,0.3); }
body.dev-customize .btn-icon { pointer-events: none; }
.light-color-btn-text {
  font-size: 0.68rem;
  padding: 2px 8px;
  background: var(--card-elev);
  color: var(--text-dim);
  border: 1px solid var(--accent);
  border-radius: 10px;
  cursor: pointer;
  white-space: nowrap;
  transition: var(--transition);
}
.light-color-btn-text:hover { border-color: var(--primary); color: var(--text); }
body.dev-customize .light-color-btn-text { pointer-events: none; }
body.dev-customize .brightness-slider { pointer-events: none; }
body.dev-customize .device-type-override { display: inline-block; }
body:not(.dev-customize) .device-type-override { display: none; }
.device-type-override { font-size: 0.65rem; }
body.dev-customize .room-color-btn { pointer-events: none; }
body.dev-customize .room-all-toggle { pointer-events: none; }
.device-info { flex: 1; min-width: 0; }
.device-name {
  font-size: 0.92rem;
  font-weight: 500;
  white-space: normal;
  word-break: break-word;
  width: 100%;
}
.device-controls-row {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
.device-area { font-size: 0.75rem; color: var(--text-faint); }
/* Semantic category (temperature, humidity, battery…) — chip after the
   name + label in the controls row */
.device-category-chip { font-size: 0.8rem; vertical-align: middle; }
.device-category-label {
  font-size: 0.68rem;
  color: var(--text-faint);
  background: var(--bg-deep);
  padding: 1px 7px;
  border-radius: 8px;
}
/* User-ignored entities (customize mode) — dimmed */
.device-card.device-ignored { opacity: 0.45; }
.device-state {
  font-size: 0.72rem;
  padding: 2px 8px;
  border-radius: 10px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  display: inline-block;
  margin-top: 3px;
}
.state-on { background: rgba(80, 250, 123, 0.15); color: var(--success); }
.state-off { background: rgba(136, 136, 170, 0.15); color: var(--text-dim); }
.state-unavailable { background: rgba(255, 85, 85, 0.15); color: var(--danger); }
.state-unknown { background: rgba(136, 136, 170, 0.1); color: var(--text-faint); }

/* ---------- Calendar tab ---------- */
.calendar-list { display: flex; flex-direction: column; gap: 8px; }
.cal-event {
  background: var(--bg-deep);
  border-radius: var(--radius-sm);
  padding: 14px 16px;
  display: flex;
  align-items: center;
  gap: 14px;
  border-left: 3px solid var(--primary);
  transition: var(--transition);
}
.cal-event:hover { background: var(--card-hover); }
.cal-date-block {
  text-align: center;
  min-width: 56px;
  padding: 6px 0;
  background: var(--accent);
  border-radius: var(--radius-sm);
}
.cal-date-day { font-size: 1.4rem; font-weight: 700; line-height: 1; }
.cal-date-month { font-size: 0.72rem; color: var(--text-dim); text-transform: uppercase; letter-spacing: 1px; }
.cal-event-body { flex: 1; min-width: 0; }
.cal-event-title { font-size: 1.05rem; font-weight: 600; }
.cal-event-meta { font-size: 0.82rem; color: var(--text-dim); margin-top: 3px; }

/* ---------- Notes tab ---------- */
.notes-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 14px;
}
.note-card {
  background: var(--bg-deep);
  border-radius: var(--radius-sm);
  padding: 16px;
  border: 1px solid transparent;
  transition: var(--transition);
  position: relative;
}
.note-card:hover { border-color: rgba(78, 158, 255, 0.15); }
.note-card .note-delete {
  position: absolute;
  top: 8px; right: 8px;
  opacity: 0;
  transition: var(--transition);
}
.note-card:hover .note-delete { opacity: 1; }
.note-card-title { font-weight: 600; font-size: 1rem; margin-bottom: 6px; padding-right: 24px; }
.note-card-body { font-size: 0.9rem; color: var(--text-dim); line-height: 1.5; white-space: pre-wrap; word-break: break-word; }
.note-card-date { font-size: 0.72rem; color: var(--text-faint); margin-top: 10px; }

/* ---------- Modal ---------- */
.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.6);
  backdrop-filter: blur(4px);
  display: none;
  align-items: center;
  justify-content: center;
  z-index: 2000;
  padding: 20px;
}
.modal-overlay.show { display: flex; animation: fadeIn 0.2s ease; }
.modal {
  background: var(--card);
  border-radius: var(--radius);
  padding: 24px;
  width: 100%;
  max-width: 480px;
  box-shadow: var(--shadow);
  border: 1px solid rgba(78, 158, 255, 0.15);
  max-height: 90vh;
  overflow-y: auto;
}
.modal-title {
  font-size: 1.2rem;
  font-weight: 600;
  margin-bottom: 18px;
  color: var(--primary);
}
/* Header row with title left, close ✕ top-right (forecast modal) */
.modal-head-row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
}
.modal-close-x {
  flex-shrink: 0;
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--accent-soft);
  background: var(--bg-deep);
  color: var(--text-dim);
  border-radius: 8px;
  font-size: 1rem;
  line-height: 1;
  cursor: pointer;
  padding: 0;
}
.modal-close-x:hover {
  color: var(--text);
  background: var(--card-hover);
}
.modal-actions {
  display: flex;
  gap: 10px;
  justify-content: flex-end;
  margin-top: 18px;
}

/* Settings category pop-up - higher z than main settings */
.modal-overlay[id="modal-settings-category"] {
  z-index: 2100;
}

/* Pop-up modals (opened from within other modals) - higher z-index */
.modal-overlay[id="modal-preferences"],
.modal-overlay[id="modal-patterns"],
.modal-overlay[id="modal-search"],
.modal-overlay[id="modal-history"],
.modal-overlay[id="modal-logs"],
.modal-overlay[id="modal-notif-history"],
.modal-overlay[id="modal-energy"],
.modal-overlay[id="modal-theme"] {
  z-index: 2100;
}
/* Planner application modal: above the base layer but below the
   settings stack (2100) and the weather alert (9999). Its form drawer
   lives INSIDE the planner shell, so no extra stacking is needed. */
.modal-overlay[id="modal-planner"] { z-index: 2050; }

/* Weather detail modal (alert warning text, UV, AQHI, pressure): opened from
   inside other modals (e.g. the forecast modal) — must render above every
   layer. This is the top of the stack. Double-width for the full alert text. */
.modal-overlay[id="modal-alert"] {
  z-index: 9999;
}
.modal-overlay[id="modal-alert"] .modal {
  max-width: 960px;
}
/* Severity-colored box: the modal's border area itself carries the severity
   color (warn = red, watch = amber, info = accent), with a soft halo */
.modal-overlay[id="modal-alert"].alert-sev-warn .modal {
  border: 3px solid var(--danger);
  box-shadow: 0 0 16px rgba(220, 38, 38, 0.18), var(--shadow);
}
.modal-overlay[id="modal-alert"].alert-sev-watch .modal {
  border: 3px solid var(--warning);
  box-shadow: 0 0 16px rgba(217, 119, 6, 0.18), var(--shadow);
}
.modal-overlay[id="modal-alert"].alert-sev-info .modal {
  border: 3px solid var(--accent);
}

/* ---------- Notification banner ---------- */
.notif-banner {
  position: fixed;
  top: 20px;
  right: 20px;
  background: var(--success);
  color: #000;
  padding: 14px 20px;
  border-radius: var(--radius-sm);
  font-weight: 600;
  box-shadow: 0 8px 24px rgba(0,0,0,0.4);
  animation: slideIn 0.3s ease;
  z-index: 3500;
  max-width: 360px;
  font-size: 0.95rem;
}
@keyframes slideIn {
  from { transform: translateX(120%); opacity: 0; }
  to { transform: translateX(0); opacity: 1; }
}
.notif-banner.dismissing { animation: slideOut 0.3s ease forwards; }
@keyframes slideOut {
  to { transform: translateX(120%); opacity: 0; }
}

/* ---------- Customization-mode bubble (fixed top-center; the ONE
   indicator + Done for every per-tab customize mode — replaces the
   old per-panel bars) ---------- */
.customize-bubble {
  position: fixed;
  top: 10px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 2400;
  display: none;
  align-items: center;
  gap: 12px;
  background: var(--accent);
  color: var(--text);
  padding: 7px 8px 7px 16px;
  border-radius: 999px;
  box-shadow: 0 4px 18px rgba(0, 0, 0, 0.4);
  font-size: 0.82rem;
  font-weight: 600;
  white-space: nowrap;
  max-width: 92vw;
}
.customize-bubble.show { display: flex; }
.customize-bubble .btn { min-height: 26px; padding: 3px 12px; font-size: 0.75rem; }

/* ---------- Scrollbar ---------- */
::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-track { background: var(--bg-deep); }
::-webkit-scrollbar-thumb { background: var(--accent-soft); border-radius: 4px; }
::-webkit-scrollbar-thumb:hover { background: var(--primary); }

/* ---------- Theme settings ---------- */
.theme-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 0;
  border-bottom: 1px solid rgba(78, 158, 255, 0.08);
}
.theme-row:last-child { border-bottom: none; }
.theme-row label { font-size: 0.9rem; color: var(--text-dim); }
.theme-color-input {
  width: 48px; height: 32px;
  border: 1px solid var(--accent-soft);
  border-radius: 6px;
  background: transparent;
  cursor: pointer;
  padding: 2px;
}
.theme-color-input::-webkit-color-swatch { border-radius: 4px; border: none; }
.theme-color-input::-moz-color-swatch { border-radius: 4px; border: none; }
.theme-presets {
  display: flex;
  gap: 8px;
  margin-bottom: 14px;
  flex-wrap: wrap;
}
.theme-preset {
  width: 36px; height: 36px;
  border-radius: 8px;
  border: 2px solid transparent;
  cursor: pointer;
  transition: var(--transition);
}
.theme-preset:hover { border-color: var(--primary); }
.theme-preset.active { border-color: var(--primary); box-shadow: 0 0 0 2px rgba(78,158,255,0.3); }

/* ---------- Brightness slider ---------- */
.brightness-row {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 4px;
}
.brightness-slider {
  -webkit-appearance: none;
  appearance: none;
  width: 80px;
  height: 6px;
  border-radius: 3px;
  background: var(--accent-soft);
  outline: none;
  cursor: pointer;
}
.light-brightness-slider {
  width: 50px;
  height: 5px;
}
.brightness-slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 14px; height: 14px;
  border-radius: 50%;
  background: var(--primary);
  cursor: pointer;
  border: 2px solid var(--bg-deep);
}
.light-brightness-slider::-webkit-slider-thumb {
  width: 12px; height: 12px;
}
.brightness-slider::-moz-range-thumb {
  width: 14px; height: 14px;
  border-radius: 50%;
  background: var(--primary);
  cursor: pointer;
  border: 2px solid var(--bg-deep);
}
.light-brightness-slider::-moz-range-thumb {
  width: 12px; height: 12px;
}
.brightness-label { font-size: 0.7rem; color: var(--text-dim); min-width: 28px; text-align: right; }

/* ---------- Light color button ---------- */
.light-color-btn {
  font-size: 0.9rem;
  width: 22px; height: 22px;
  border: 1px solid var(--accent-soft);
  border-radius: 5px;
  background: var(--bg-deep);
  cursor: pointer;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
}
.light-color-btn:hover { border-color: var(--primary); }

/* ---------- Cameras tab ---------- */
/* ---------- Music tab ---------- */
.music-now-playing {
  display: flex;
  gap: 20px;
  padding: 20px;
  background: var(--card);
  border-radius: var(--radius);
  border: 1px solid rgba(78, 158, 255, 0.08);
  box-shadow: var(--shadow-soft);
  margin-bottom: 18px;
}
.music-artwork {
  width: 180px;
  height: 180px;
  border-radius: var(--radius);
  background: var(--bg-deep);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 4rem;
  flex-shrink: 0;
  overflow: hidden;
  background-size: cover;
  background-position: center;
}
.music-track-info { flex: 1; display: flex; flex-direction: column; gap: 4px; }
.music-track-name { font-size: 1.3rem; font-weight: 600; }
.music-artist { font-size: 1rem; color: var(--text-dim); }
.music-album { font-size: 0.85rem; color: var(--text-faint); }
.music-progress-row { display: flex; align-items: center; gap: 8px; margin-top: 12px; }
.music-time { font-size: 0.75rem; color: var(--text-faint); min-width: 36px; }
.music-progress-bar {
  flex: 1; height: 6px; background: var(--accent-soft); border-radius: 3px;
  cursor: pointer; position: relative; overflow: hidden;
}
.music-progress-fill { height: 100%; background: var(--primary); border-radius: 3px; transition: width 0.5s; }
.music-controls { display: flex; align-items: center; gap: 12px; margin-top: 16px; }
.music-btn {
  width: 40px; height: 40px; border: none; background: var(--accent);
  color: var(--text); border-radius: 50%; cursor: pointer; font-size: 1.1rem;
  display: flex; align-items: center; justify-content: center; transition: var(--transition);
}
.music-btn:hover { background: var(--accent-soft); }
.music-btn-main { width: 52px; height: 52px; background: var(--primary); color: #fff; font-size: 1.3rem; }
.music-btn-main:hover { background: #3a8ae8; }
.music-volume-row { display: flex; align-items: center; gap: 6px; margin-left: auto; }
.music-volume-slider { width: 100px; }
.music-volume-label { font-size: 0.75rem; color: var(--text-faint); min-width: 30px; }
.music-search-section { margin-bottom: 18px; }
.music-search-row { display: flex; gap: 8px; margin-bottom: 12px; }
.music-search-input { flex: 1; }
.music-results { display: flex; flex-direction: column; gap: 6px; max-height: 300px; overflow-y: auto; }
.music-result-item {
  display: flex; align-items: center; gap: 10px; padding: 8px 12px;
  background: var(--bg-deep); border-radius: var(--radius-sm); cursor: pointer;
  transition: var(--transition); border: 1px solid transparent;
}
.music-result-item:hover { border-color: var(--primary); background: var(--card-hover); }
.music-result-art { width: 40px; height: 40px; border-radius: 4px; background-size: cover; background-position: center; flex-shrink: 0; background: var(--accent); }
.music-result-info { flex: 1; min-width: 0; }
.music-result-name { font-size: 0.9rem; font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.music-result-meta { font-size: 0.75rem; color: var(--text-faint); }
.music-playlists-section { margin-top: 18px; }
.music-section-title { font-size: 0.85rem; font-weight: 700; color: var(--primary); text-transform: uppercase; letter-spacing: 1px; margin-bottom: 10px; }
.music-playlist-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 12px; }
.music-playlist-card {
  background: var(--bg-deep); border-radius: var(--radius-sm); cursor: pointer;
  transition: var(--transition); border: 1px solid transparent; overflow: hidden;
}
.music-playlist-card:hover { border-color: var(--primary); }
.music-playlist-art { width: 100%; aspect-ratio: 1; background-size: cover; background-position: center; background: var(--accent); }
.music-playlist-name { padding: 8px 10px; font-size: 0.82rem; font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.music-playlist-meta { padding: 0 10px 8px; font-size: 0.7rem; color: var(--text-faint); }

/* ---------- Web voice ---------- */
#voice-btn.listening { background: var(--success); color: #fff; border-color: var(--success); }
#voice-btn.listening::after { content: ''; display: inline-block; width: 8px; height: 8px; border-radius: 50%; background: #fff; margin-left: 4px; animation: pulse 1.5s infinite; }
#voice-btn.mode-command { background: var(--warning); color: #fff; border-color: var(--warning); }
#voice-btn.mode-processing { background: var(--accent); color: #fff; border-color: var(--accent); }
#voice-btn.mode-speaking { background: #9b59b6; color: #fff; border-color: #9b59b6; }
#voice-btn.mode-speaking::after { content: ''; display: inline-block; width: 8px; height: 8px; border-radius: 50%; background: #fff; margin-left: 4px; animation: pulse 0.6s infinite; }
@keyframes pulse { 0% { opacity: 1; } 50% { opacity: 0.3; } 100% { opacity: 1; } }
@keyframes voiceWave { 0%, 100% { height: 4px; } 50% { height: 16px; } }
.voice-wave { display: inline-flex; align-items: center; gap: 2px; margin-right: 8px; vertical-align: middle; }
.voice-wave span { display: inline-block; width: 3px; height: 4px; background: var(--accent); border-radius: 2px; animation: voiceWave 0.8s ease-in-out infinite; }
.voice-wave span:nth-child(2) { animation-delay: 0.15s; }
.voice-wave span:nth-child(3) { animation-delay: 0.3s; }
.voice-wave span:nth-child(4) { animation-delay: 0.45s; }
.voice-status { position: fixed; bottom: 20px; left: 50%; transform: translateX(-50%); background: var(--bg-deep); border: 1px solid var(--accent-soft); border-radius: 20px; padding: 8px 20px; font-size: 0.85rem; color: var(--text-dim); z-index: 2000; display: none; align-items: center; gap: 6px; box-shadow: 0 4px 12px rgba(0,0,0,0.3); }
.voice-status.show { display: inline-flex; }
.voice-status.speaking { border-color: #9b59b6; }
.voice-status.command { border-color: var(--warning); }

.camera-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));
  gap: 14px;
}
.camera-card {
  background: var(--bg-deep);
  border-radius: var(--radius-sm);
  overflow: hidden;
  border: 1px solid rgba(78, 158, 255, 0.08);
  transition: var(--transition);
}
.camera-card:hover { border-color: rgba(78, 158, 255, 0.2); }
.camera-card.unavailable { opacity: 0.5; }
.camera-card.streaming .camera-overlay { background: #ef4444; }
.cam-live-btn { position: absolute; top: 6px; right: 36px; background: rgba(0,0,0,0.5); color: #fff; border: none; border-radius: 4px; padding: 3px 6px; cursor: pointer; font-size: 0.85rem; z-index: 5; }

/* ---------- Dashboard camera widget (main grid, 400px card) ---------- */
/* Two stacked displays: top = camera chosen in the dropdown (live relay
   for onvif cams, looping motion clip for cloud cams), bottom = the
   last camera with detected motion. */
.camw-body {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.camw-display {
  position: relative;
  flex: 1 1 0;
  min-height: 0;
  background: #000;
  border-radius: 6px;
  overflow: hidden;
  cursor: pointer;
}
.camw-display img,
.camw-display video {
  width: 100%;
  height: 100%;
  object-fit: contain;   /* whole frame visible — see who's there */
  display: block;
}
.camw-display.streaming { outline: 2px solid #ef4444; outline-offset: -2px; }
.camw-display.streaming .camera-overlay { background: #ef4444; }
/* Small-display floor: two 16:9 slots need ~140px each; below ~300px
   cards only the live feed fits — the motion slot drops and the top
   slot fills the card. */
[data-display="small"] #camw-motion { display: none; }
.camw-label {
  position: absolute;
  left: 6px;
  bottom: 5px;
  background: rgba(0, 0, 0, 0.55);
  color: #fff;
  font-size: 0.72rem;
  padding: 2px 7px;
  border-radius: 4px;
  z-index: 4;
  max-width: calc(100% - 12px);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.camw-empty {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-faint);
  font-size: 0.8rem;
}

.cam-live-btn:hover { background: rgba(239,68,68,0.7); }
body.cam-customize .camera-card { cursor: grab; border-style: dashed; }
body.cam-customize .camera-card.dragging { opacity: 0.4; }
body.cam-customize .camera-card.drag-over { border-color: var(--primary); box-shadow: 0 0 0 2px var(--primary); }
body.cam-customize .cam-refresh-btn { display: none; }
.camera-img-wrap {
  position: relative;
  width: 100%;
  aspect-ratio: 16/9;
  background: #000;
  overflow: hidden;
}
.camera-img-wrap img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.camera-img-wrap video.cam-clip {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  background: #000;
}
.camera-img-wrap .cam-placeholder {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-faint);
  font-size: 0.9rem;
}
.camera-overlay {
  position: absolute;
  top: 8px;
  left: 8px;
  background: rgba(0, 0, 0, 0.6);
  color: #fff;
  padding: 3px 10px;
  border-radius: 4px;
  font-size: 0.72rem;
  font-weight: 500;
}
.cam-refresh-btn {
  position: absolute;
  top: 8px;
  right: 8px;
  background: rgba(0, 0, 0, 0.6);
  color: #fff;
  border: none;
  border-radius: 4px;
  width: 28px;
  height: 28px;
  font-size: 1rem;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 0.2s;
}
.cam-refresh-btn:hover { background: rgba(0, 0, 0, 0.85); }
.camera-overlay.live {
  background: rgba(255, 85, 85, 0.8);
}
.camera-overlay.live::before {
  content: '● ';
}
.cam-footer {
  padding: 8px 12px;
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.cam-name { font-size: 0.85rem; font-weight: 500; }
.cam-state { font-size: 0.7rem; color: var(--text-faint); text-transform: uppercase; }

/* ---------- Commands Tab ---------- */
.commands-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 14px;
}
.command-card {
  background: var(--bg-deep);
  border-radius: var(--radius-sm);
  padding: 20px 16px;
  border: 1px solid rgba(78, 158, 255, 0.08);
  transition: var(--transition);
  display: flex;
  flex-direction: column;
  gap: 8px;
  text-align: center;
  cursor: pointer;
  position: relative;
}
.command-card:hover {
  border-color: var(--accent);
  transform: translateY(-2px);
  box-shadow: 0 4px 16px rgba(15, 52, 96, 0.3);
}
.command-card:active { transform: translateY(0); }
.command-card.running { opacity: 0.6; pointer-events: none; }
.command-icon { font-size: 2rem; line-height: 1; }
.command-name { font-size: 1rem; font-weight: 600; }
.command-desc { font-size: 0.75rem; color: var(--text-dim); }
.command-steps { font-size: 0.65rem; color: var(--text-faint); }
.command-card-actions {
  position: absolute;
  top: 6px;
  right: 6px;
  display: flex;
  gap: 2px;
  opacity: 0;
  transition: opacity 0.2s;
}
body.cmd-customize .command-card-actions { opacity: 1; }
.cmd-action-btn {
  background: none;
  border: none;
  color: var(--text-faint);
  font-size: 0.9rem;
  cursor: pointer;
  padding: 2px 6px;
  border-radius: 4px;
}
.cmd-action-btn:hover { color: var(--text); background: rgba(78,158,255,0.1); }
.cmd-action-btn.danger:hover { color: #ff5555; background: rgba(255,85,85,0.1); }
.command-card.dragging { opacity: 0.4; }
.command-card.drag-over { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent); }
.cmd-drag-handle {
  position: absolute;
  top: 6px;
  left: 6px;
  color: var(--text-faint);
  font-size: 0.8rem;
  cursor: grab;
  opacity: 0;
  transition: opacity 0.2s;
  padding: 2px 4px;
  line-height: 0.8;
  user-select: none;
}
body.cmd-customize .cmd-drag-handle { opacity: 0.6; }
body.cmd-customize .command-card { cursor: grab; }
.cmd-drag-handle:active { cursor: grabbing; }
#cmd-new-btn { display: none; }
body.cmd-customize #cmd-new-btn { display: inline-block; }
#auto-new-btn { display: none; }
body.cmd-customize #auto-new-btn { display: inline-block; }
#auto-template-btn { display: none; }
body.cmd-customize #auto-template-btn { display: inline-block; }
#power-config-section { display: none; }
body.dev-customize #power-config-section { display: block; }
.icon-pick-cell {
  font-size: 1.3rem;
  padding: 6px 4px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  text-align: center;
  background: transparent;
  border: none;
  transition: background 0.15s;
}
.icon-pick-cell:hover { background: var(--accent-soft); }
.icon-pick-cell.selected { background: var(--accent); }

/* Step editor */
.cmd-step-card {
  background: var(--bg-deep);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 10px 12px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.cmd-step-header {
  display: flex;
  align-items: center;
  gap: 8px;
  justify-content: space-between;
}
.cmd-step-title {
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--text-dim);
}
.cmd-step-fields {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}
.cmd-step-fields .full-row { grid-column: 1 / -1; }
.cmd-step-fields label {
  font-size: 0.65rem;
  color: var(--text-faint);
  display: block;
  margin-bottom: 2px;
}
.cmd-step-fields select,
.cmd-step-fields input {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text);
  padding: 6px 8px;
  font-size: 0.8rem;
  width: 100%;
  box-sizing: border-box;
}
.cmd-extra-data {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text);
  padding: 6px 8px;
  font-size: 0.8rem;
  width: 100%;
  box-sizing: border-box;
}
.remove-step {
  background: none;
  border: none;
  color: #ff5555;
  cursor: pointer;
  font-size: 1.1rem;
  padding: 2px 6px;
  border-radius: 4px;
}
.remove-step:hover { background: rgba(255,85,85,0.1); }
.input-label {
  font-size: 0.75rem;
  color: var(--text-dim);
  display: block;
  margin-bottom: 4px;
}
.form-input {
  background: var(--bg-deep);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text);
  padding: 8px 10px;
  font-size: 0.9rem;
  width: 100%;
  box-sizing: border-box;
}

/* ---------- Responsive ---------- */
@media (max-width: 720px) {
  body { padding: 8px; overflow-x: hidden; }
  .clock { font-size: 1.8rem; }
  .tab { min-width: 70px; font-size: 0.82rem; padding: 8px 10px; }
  .tabs { overflow-x: auto; -webkit-overflow-scrolling: touch; flex-wrap: nowrap; scrollbar-width: thin; }
  .tabs::-webkit-scrollbar { height: 3px; }
  .header-btns { gap: 2px; }
  .header-btns .btn { width: 34px; height: 28px; padding: 0; font-size: 0.8rem; }
  .card { padding: 10px; }
  .modal { margin: 4px; max-width: calc(100vw - 8px) !important; max-height: 92vh; overflow-y: auto; overflow-x: hidden; padding: 14px; box-sizing: border-box; }
  .modal-title { font-size: 1rem; }
  .modal-actions { flex-wrap: wrap; gap: 6px; }
  .cmd-step-fields { grid-template-columns: 1fr; }
  .cmd-step-fields .full-row { grid-column: 1; }
  .customize-bubble { font-size: 0.72rem; padding: 5px 6px 5px 12px; gap: 8px; }
  #header-pin-airquality { min-width: 0; max-width: 100%; }
  #header-pin-climate { min-width: 0; max-width: 100%; }
  .header-pin-widget { min-width: 0; max-width: 100%; }
  .device-grid { grid-template-columns: 1fr; }
  .music-playlist-grid { grid-template-columns: 1fr; }
  .settings-categories { font-size: 0.82rem; }
  .settings-categories select, .settings-categories input { max-width: 100%; }
}
/* Grid-column media queries REMOVED (2026-09-29): columns are set by
   the display class via --grid-cols (see :root blocks). */

/* Device name / room label (top of main screen). ONE line:
   "device name / room" — ellipsis when it can't fit. Informational
   only (not clickable — Settings opens from the header ⚙️ button). */
.device-badge {
  display: flex;
  flex-direction: row;
  align-items: baseline;
  gap: 0;
  line-height: 1.3;
  white-space: nowrap;
  max-width: 240px;
  overflow: hidden;
}
.device-badge #device-badge-name {
  font-size: 0.72rem;
  color: #1e40af;
  overflow: hidden;
  text-overflow: ellipsis;
}
.device-badge #device-badge-room {
  font-size: 0.72rem;
  color: #1e40af;
  opacity: 0.75;
}

/* Notifications widget card (dashboard grid) — controls live in the card header */
.notif-w-dnd {
  border: none;
  background: none;
  cursor: pointer;
  font-size: 0.9rem;
  padding: 0;
  line-height: 1;
  color: var(--text-dim);
  display: inline-flex;
  align-items: center;
}
.notif-w-dnd:hover { opacity: 0.8; }
.notif-w-dnd-active { opacity: 0.5; }
.notif-w-speak-label {
  font-size: 0.72rem;
  color: var(--text-dim);
  display: inline-flex;
  align-items: center;
  gap: 4px;
  cursor: pointer;
  white-space: nowrap;
  margin-right: 4px;
}
.notif-w-speak-label input { margin: 0; }
.notif-w-list {
  display: flex;
  flex-direction: column;
  gap: 2px;
  max-height: 240px;
  overflow-y: auto;
}
.notif-w-row {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 0.72rem;
  color: var(--text-dim);
  line-height: 1.4;
}
.notif-w-row span:first-child { flex-shrink: 0; }
.notif-w-row span:last-child {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.notif-w-row.sev-2 span:first-child { color: var(--danger); }
.notif-w-row.sev-1 span:first-child { color: var(--warning); }
.notif-w-empty {
  font-size: 0.72rem;
  color: var(--text-faint);
  font-style: italic;
}

/* Pinned header variant (📌 Pin on the notifications card).
   order:1 keeps it rightmost in the pinned row regardless of which
   other widgets are pinned. */
#header-pin-notifications {
  order: 1;
  min-width: 200px;
  max-width: 280px;
}
.notif-pin-list {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.notif-pin-list .notif-w-row { font-size: 0.68rem; }

/* ── Notification detail modal (🔔 Notifications 24h log) ──
   Single-line rows: icon • message • type badge • time. */
.notif-detail-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 4px 8px;
  border-radius: var(--radius-sm);
  font-size: 0.78rem;
  line-height: 1.5;
}
.notif-detail-row:hover { background: var(--bg-deep); }
.notif-detail-icon { flex-shrink: 0; }
.notif-detail-msg {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--text);
}
.notif-detail-time {
  flex-shrink: 0;
  font-size: 0.68rem;
  color: var(--text-faint);
}
.notif-type-badge {
  flex-shrink: 0;
  font-size: 0.62rem;
  padding: 1px 7px;
  border-radius: 8px;
  border: 1px solid var(--accent);
  background: var(--bg-deep);
  color: var(--text-dim);
  white-space: nowrap;
}
/* Type accents (badge + icon in rows, badges in the filter bar) */
.notif-type-timer, .notif-detail-row.notif-row-timer .notif-detail-icon { color: var(--warning); }
.notif-type-battery, .notif-detail-row.notif-row-battery .notif-detail-icon { color: var(--warning); }
.notif-type-error, .notif-detail-row.notif-row-error .notif-detail-icon { color: var(--danger); }
.notif-type-weather, .notif-detail-row.notif-row-weather .notif-detail-icon { color: #88ccff; }
.notif-type-voice, .notif-detail-row.notif-row-voice .notif-detail-icon { color: #bb88ff; }
.notif-type-suggestion, .notif-detail-row.notif-row-suggestion .notif-detail-icon { color: #ffdd88; }
.notif-type-automation, .notif-detail-row.notif-row-automation .notif-detail-icon,
.notif-type-sync, .notif-detail-row.notif-row-sync .notif-detail-icon { color: var(--primary); }
.notif-type-action, .notif-detail-row.notif-row-action .notif-detail-icon { color: var(--success); }
.notif-type-other { color: var(--text-dim); }
.notif-detail-group-label {
  font-size: 0.66rem;
  font-weight: 600;
  color: var(--text-faint);
  text-transform: uppercase;
  letter-spacing: 0.4px;
  margin: 10px 0 3px;
}
.notif-filter-chk {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  cursor: pointer;
  font-size: 0.72rem;
  user-select: none;
}
.notif-filter-chk input { margin: 0; }

/* ===================== News Tab ===================== */
/* Same structure as the dashboard grid: class-driven columns, fluid
   card height, internal scroll */
#news-widgets {
  display: grid;
  grid-template-columns: repeat(var(--grid-cols), 1fr);
  gap: 10px;
}
#news-widgets > .card {
  box-sizing: border-box;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  height: var(--card-h);
}
/* ---------- News tab visual pass (2026-10-04) ----------
   Same domain-accent language as the dashboard grid: 3px top bar +
   domain-colored titles. Feeds (📰) = slate (knowledge sources, like
   the dashboard Top Stories widget); topics (🔎) = teal — your curated
   searches. Hover lift, display-aware density and handwriting empties
   match the dashboard treatment. */
#news-widgets .card { --dom: var(--dom-note); }
#news-widgets .card[data-news-widget^="topic-"] { --dom: var(--dom-topic); }
#news-widgets .card-title { color: var(--dom, var(--dom-note)); }
#news-widgets .card::before {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 3px;
  background: var(--dom, var(--dom-note));
  opacity: 0.9;
  border-radius: var(--radius) var(--radius) 0 0;
  pointer-events: none;
}
#news-widgets .card:hover {
  transform: translateY(-3px);
  box-shadow: 0 10px 24px rgba(0, 0, 0, 0.13);
  border-color: var(--dom, rgba(37, 99, 235, 0.25));
}
body.news-customize #news-widgets .card:hover { transform: none; }
#news-widgets .card.dragging,
#news-widgets .card.drag-over { transform: none; }
/* Display-aware density — mirrors [data-display] #dashboard-grid */
[data-display="large"] #news-widgets { gap: 12px; }
[data-display="xlarge"] #news-widgets { gap: 14px; }
[data-display="large"] #news-widgets > .card { padding: 14px; }
[data-display="xlarge"] #news-widgets > .card { padding: 16px; }
[data-display="large"] #news-widgets .news-item { font-size: 0.88rem; }
[data-display="xlarge"] #news-widgets .news-item { font-size: 0.95rem; }
#news-widgets .card-header { flex-shrink: 0; }
/* Widget bodies scroll internally (dashboard-card behavior) */
.news-widget-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
}
/* Last-updated stamp after widget titles — normal lettering, DIN
   tabular digits (no jitter as minutes tick) */
.news-updated {
  font-size: 0.66rem;
  font-weight: 400;
  text-transform: none;
  letter-spacing: 0;
  color: var(--text-faint);
  white-space: nowrap;
  font-family: var(--font-num);
  font-variant-numeric: tabular-nums;
}
/* Per-widget refresh (the ↻ on a news card) */
.news-refresh {
  border: none;
  background: transparent;
  color: var(--text-faint);
  cursor: pointer;
  font-size: 0.85rem;
  padding: 2px 4px;
  line-height: 1;
}
.news-refresh:hover { color: var(--accent); }
.news-refresh:disabled { opacity: 0.5; cursor: default; }
/* Story popup loading state — centered inside the fixed-height frame so
   the modal opens as the full-size widget (no small→big growth) */
.news-story-loading {
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-faint);
  font-size: 0.85rem;
}
.news-item {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 6px 4px;
  border-bottom: 1px solid var(--border);
  font-size: 0.82rem;
  line-height: 1.35;
  cursor: pointer;
}
.news-item:hover { background: var(--bg-deep); border-radius: var(--radius-sm); }
.news-item:last-child { border-bottom: none; }
.news-item-text {
  color: var(--text);
  flex: 1;
  min-width: 0;
}
.news-item:hover .news-item-text { color: var(--primary); }
.news-src {
  flex-shrink: 0;
  font-size: 0.62rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.4px;
  color: var(--primary);
  background: rgba(37, 99, 235, 0.10);
  padding: 1px 6px;
  border-radius: 8px;
  max-width: 110px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.news-empty {
  color: var(--text-faint);
  font-size: 0.8rem;
  padding: 10px 0;
}
/* Readback karaoke highlight — the sentence being spoken */
.news-sentence {
  border-radius: 3px;
  transition: background-color 0.3s ease;
}
.news-sentence.reading {
  background: rgba(96, 165, 250, 0.32);   /* light blue */
}
/* News-tab customize mode (mirrors the dashboard's) */
body.news-customize #news-widgets .card { cursor: grab; }

/* ---------- Planner — a paper planner book (2026-10-03 redesign)
   One large center-screen modal styled as a paper planner: warm yellow
   paper, blue-ruled lines with a red margin, ballpoint-blue ink for
   handwritten bits (Segoe Print — Windows built-in, no web fonts),
   sticky-tab notes, and index-card form drawer. Tabs (top, right of the
   title) switch the content pane; a mini month calendar rides the right
   column on EVERY tab. Stacking (z-index 2050) lives with the other
   modal layers above. ---------------------------------------------------- */
.modal-overlay[id="modal-planner"] {
  padding: 14px;
  /* paper palette — scoped to the planner only */
  --ppr-paper: #fbf3d5;
  --ppr-paper-deep: #f1e4b2;
  --ppr-card: #fffdf4;
  --ppr-edge: #d8c88e;
  --ppr-line: rgba(43, 80, 168, 0.20);
  --ppr-margin: rgba(196, 74, 74, 0.45);
  --ppr-ink: #2b50a8;
  --ppr-ink-dark: #22366b;
  --ppr-ink-faint: #8fa0c4;
  --ppr-red: #b3402a;
  --ppr-hand: 'Segoe Print', 'Bradley Hand', 'Comic Sans MS', cursive;
}
.planner-shell {
  position: relative;
  background: var(--ppr-paper);
  background-image:
    radial-gradient(ellipse 120% 80% at 50% -10%, rgba(255, 255, 255, 0.55), transparent 60%),
    radial-gradient(ellipse 60% 40% at 100% 100%, rgba(163, 132, 42, 0.08), transparent 70%);
  border-radius: 18px;
  border: 1px solid var(--ppr-edge);
  box-shadow: 0 24px 64px rgba(0, 0, 0, 0.30), inset 0 1px 0 rgba(255, 255, 255, 0.6);
  width: min(1240px, 96vw);
  height: min(840px, 92vh);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  color: var(--ppr-ink-dark);
}
.planner-head {
  display: flex;
  align-items: flex-end;
  gap: 14px;
  padding: 14px 18px 0;
  border-bottom: 2px solid var(--ppr-ink);
  flex-shrink: 0;
  flex-wrap: wrap;
}
.planner-title {
  font-size: 1.15rem;
  font-weight: 800;
  color: var(--ppr-ink-dark);
  letter-spacing: 0.2px;
  padding-bottom: 10px;
  white-space: nowrap;
}
/* Index tabs — like a planner book's divider tabs, sitting ON the head
   rule; the active tab merges with the page below it */
.planner-tabs {
  display: flex;
  gap: 4px;
  align-items: flex-end;
  flex: 1;
  min-width: 0;
  overflow-x: auto;
  scrollbar-width: none;
}
.planner-tabs::-webkit-scrollbar { display: none; }
.planner-tab {
  border: 1.5px solid var(--ppr-ink);
  border-bottom: none;
  border-radius: 10px 10px 0 0;
  background: var(--ppr-paper-deep);
  color: var(--ppr-ink-dark);
  font-size: 0.8rem;
  font-weight: 700;
  font-family: inherit;
  padding: 8px 14px 9px;
  cursor: pointer;
  white-space: nowrap;
  position: relative;
  top: 2px;
  transition: background var(--transition), top var(--transition);
}
.planner-tab:hover { background: var(--ppr-card); }
.planner-tab.active {
  background: var(--ppr-card);
  top: 0;
  padding-bottom: 11px;
  box-shadow: 0 2px 0 var(--ppr-card);  /* masks the head rule → merged */
}
.planner-head-actions {
  display: flex;
  gap: 8px;
  align-items: center;
  padding-bottom: 10px;
}
.planner-body {
  display: flex;
  flex: 1;
  min-height: 0;
  background: var(--ppr-card);
  background-image: radial-gradient(ellipse 100% 60% at 50% 0%, rgba(255, 255, 255, 0.7), transparent 70%);
}
.planner-main {
  flex: 0 0 300px;           /* narrow sheet — the calendar owns the width */
  min-width: 0;
  display: flex;
  flex-direction: column;
  padding: 14px 16px;
  overflow: hidden;
  position: relative;
}
.planner-main.view-enter { animation: plannerViewIn 0.22s ease; }
@keyframes plannerViewIn {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: none; }
}
.planner-view-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 12px;
  flex-shrink: 0;
}
.planner-view-title {
  font-size: 1rem;
  font-weight: 800;
  color: var(--ppr-ink-dark);
}
.planner-view-title-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.planner-view-sub { font-size: 0.72rem; color: var(--ppr-ink-faint); }
.planner-scroll { flex: 1; min-height: 0; overflow-y: auto; }

/* -- Paper buttons + close x inside the planner -- */
#modal-planner .btn {
  background: var(--ppr-card);
  color: var(--ppr-ink-dark);
  border: 1.5px solid var(--ppr-ink-faint);
  font-weight: 700;
}
#modal-planner .btn:hover { border-color: var(--ppr-ink); background: #fff; }
#modal-planner .btn-primary {
  background: var(--ppr-ink);
  color: #fff;
  border-color: var(--ppr-ink);
}
#modal-planner .btn-primary:hover { background: var(--ppr-ink-dark); }
#modal-planner .btn-danger { background: var(--ppr-red); border-color: var(--ppr-red); color: #fff; }
#modal-planner .modal-close-x {
  background: var(--ppr-paper-deep);
  border-color: var(--ppr-ink-faint);
  color: var(--ppr-ink-dark);
}
#modal-planner .modal-close-x:hover { background: var(--ppr-paper); color: var(--ppr-red); }

/* -- Mini month calendar (LEFT column, every tab) -- */
.planner-mcal {
  width: 236px;
  flex-shrink: 0;
  border-right: 1.5px solid var(--ppr-line);
  padding: 14px 14px 14px 14px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  overflow-y: auto;
  background: var(--ppr-paper);
}
.mcal-head { display: flex; align-items: center; justify-content: space-between; gap: 6px; }
.mcal-title {
  font-size: 0.82rem;
  font-weight: 800;
  color: var(--ppr-ink-dark);
  letter-spacing: 0.3px;
  white-space: nowrap;
}
.mcal-btn {
  width: 26px; height: 26px;
  border: 1.5px solid var(--ppr-ink-faint);
  border-radius: 7px;
  background: var(--ppr-card);
  color: var(--ppr-ink-dark);
  font-size: 0.95rem;
  font-weight: 800;
  cursor: pointer;
  line-height: 1;
}
.mcal-btn:hover { border-color: var(--ppr-ink); background: #fff; }
.mcal-today-btn {
  border: 1.5px dashed var(--ppr-ink-faint);
  border-radius: 7px;
  background: transparent;
  color: var(--ppr-ink);
  font-size: 0.7rem;
  font-weight: 800;
  font-family: inherit;
  padding: 4px 0;
  cursor: pointer;
  letter-spacing: 0.5px;
  text-transform: uppercase;
}
.mcal-today-btn:hover { border-style: solid; border-color: var(--ppr-ink); }
.mcal-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 2px;
}
.mcal-dow {
  text-align: center;
  font-size: 0.58rem;
  font-weight: 800;
  color: var(--ppr-ink-faint);
  text-transform: uppercase;
  padding: 3px 0 4px;
  border-bottom: 1px solid var(--ppr-line);
}
.mcal-day {
  position: relative;
  height: 30px;
  border-radius: 7px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  border: 1.5px solid transparent;
}
.mcal-day:hover { background: rgba(43, 80, 168, 0.08); }
.mcal-day.other { opacity: 0.3; cursor: default; }
.mcal-day.other:hover { background: transparent; }
.mcal-day .mcal-num { font-size: 0.72rem; font-weight: 700; color: var(--ppr-ink-dark); font-variant-numeric: tabular-nums; }
.mcal-day.today { border-color: var(--ppr-red); border-radius: 40% 55% 45% 50%; }  /* hand-drawn ring */
.mcal-day.today .mcal-num { color: var(--ppr-red); }
.mcal-day.selected { background: rgba(43, 80, 168, 0.14); border-color: var(--ppr-ink); }
.mcal-dots {
  position: absolute;
  bottom: 2px;
  left: 0; right: 0;
  display: flex;
  justify-content: center;
  gap: 2px;
}
.mcal-dots i { width: 4px; height: 4px; border-radius: 50%; display: block; }
.mcal-dots .dk-event { background: var(--ppr-ink); }
.mcal-dots .dk-reminder { background: #b45309; }
.mcal-dots .dk-note { background: #64748b; }
.mcal-dots .dk-list { background: #15803d; }

/* -- Static upcoming strip under the mini calendar (space-limited) -- */
.mcal-up-head {
  margin-top: 12px;
  padding-top: 9px;
  border-top: 1.5px solid var(--ppr-line);
  font-size: 0.6rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 1px;
  color: var(--ppr-ink);
}
.mcal-up-item {
  display: flex;
  align-items: baseline;
  gap: 6px;
  padding: 3px 2px;
  cursor: pointer;
  border-radius: 5px;
  white-space: nowrap;
}
.mcal-up-item:hover { background: rgba(43, 80, 168, 0.08); }
.mcal-up-when {
  font-size: 0.6rem;
  font-weight: 700;
  color: var(--ppr-ink-faint);
  font-variant-numeric: tabular-nums;
  flex-shrink: 0;
  min-width: 34px;
}
.mcal-up-title {
  font-size: 0.68rem;
  color: var(--ppr-ink);
  font-family: var(--ppr-hand);
  overflow: hidden;
  text-overflow: ellipsis;
}
.mcal-up-empty {
  font-size: 0.66rem;
  color: var(--ppr-ink-faint);
  font-family: var(--ppr-hand);
  padding: 4px 2px;
}

/* -- Sheet paper: NO regular ruling — a clean sheet with a single rule
   separating each DATE group. (The repeating 24px ruled background was
   retired 2026-10-03: rows are single-line, so the ruling never aligned
   and read as noise. The index-card drawer keeps its own lines.) -- */

/* -- Big month calendar (CENTER column, FIXED — visible on every tab).
   Expands to fill the width the sheet gave up; day cells are SQUARE. -- */
.planner-bigcal {
  flex: 1 1 auto;
  min-width: 0;
  border-right: 1.5px solid var(--ppr-line);
  padding: 14px 16px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
}
/* Weekday labels: a row of their own OUTSIDE the day grid — the first
   week starts directly beneath them (a shared grid gave the label row
   a full 62px auto-row = the "blank row" under the labels) */
.planner-bigcal .pcal-dows {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 4px;
  flex-shrink: 0;
  padding-bottom: 5px;
  border-bottom: 1.5px solid var(--ppr-line);
  margin-bottom: 5px;
}
.planner-bigcal .pcal-grid {
  flex: 1;
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 4px;
  align-content: start;
}
.pcal-clear {
  cursor: pointer;
  opacity: 0.75;
  font-weight: 600;
  font-size: 0.7rem;
  color: var(--ppr-ink);
}
.pcal-clear:hover { opacity: 1; color: var(--ppr-red); }
.pcal-dow {
  text-align: center;
  font-size: 0.62rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 1px;
  color: var(--ppr-ink-faint);
  line-height: 1.4;
}
.pcal-day {
  border: 1px solid var(--ppr-line);
  border-radius: 10px;
  padding: 4px 5px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  overflow: hidden;
  cursor: pointer;
  background: rgba(255, 253, 244, 0.6);
  min-height: 0;
  aspect-ratio: 1;           /* square day cells */
  transition: border-color var(--transition), background var(--transition);
}
.pcal-day:hover { border-color: var(--ppr-ink); background: #fff; }
.pcal-day.other-month { opacity: 0.35; cursor: default; border-style: dashed; }
.pcal-day.today {
  border: 2px solid var(--ppr-red);
  border-radius: 12px 9px 13px 10px;  /* hand-drawn box */
}
.pcal-day.selected { background: rgba(43, 80, 168, 0.10); }
.pcal-daynum { font-size: 0.72rem; font-weight: 700; color: var(--ppr-ink-dark); }
.pcal-day.today .pcal-daynum { color: var(--ppr-red); }
.pcal-chip {
  font-size: 0.62rem;
  line-height: 1.35;
  font-weight: 600;
  padding: 1px 5px;
  border-radius: 4px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  border-left: 2px solid transparent;
}
.pcal-chip.k-event { background: rgba(43, 80, 168, 0.12); color: var(--ppr-ink); border-left-color: var(--ppr-ink); }
.pcal-chip.k-reminder { background: rgba(180, 83, 9, 0.12); color: #92400e; border-left-color: #b45309; }
.pcal-chip.k-note { background: rgba(100, 116, 139, 0.12); color: #475569; border-left-color: #64748b; }
.pcal-chip.k-list { background: rgba(21, 128, 61, 0.12); color: #166534; border-left-color: #15803d; }
.pcal-more { font-size: 0.58rem; font-weight: 700; color: var(--ppr-ink-faint); padding-left: 2px; }

/* -- Shared entry rows: ONE line per item (when · title · meta,
   ellipsized) -- */
.prow {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 5px 8px 5px 13px;
  border-radius: var(--radius-sm);
  margin-bottom: 1px;
  cursor: pointer;
  position: relative;
  background: transparent;
  white-space: nowrap;
  transition: background var(--transition);
}
.prow:hover { background: rgba(43, 80, 168, 0.08); }
.prow-stripe {
  position: absolute;
  left: 4px;
  top: 6px;
  bottom: 6px;
  width: 3px;
  border-radius: 2px;
}
.prow.k-event .prow-stripe { background: var(--ppr-ink); }
.prow.k-reminder .prow-stripe { background: #b45309; }
.prow.k-note .prow-stripe { background: #64748b; }
.prow.k-list .prow-stripe { background: #15803d; }
.prow-when {
  font-size: 0.68rem;
  font-weight: 700;
  color: var(--ppr-ink-faint);
  flex-shrink: 0;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.prow-line {
  flex: 1;
  min-width: 0;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--ppr-ink-dark);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.prow-actions {
  display: flex;
  gap: 4px;
  opacity: 0.45;
  transition: opacity var(--transition);
  flex-shrink: 0;
}
.prow:hover .prow-actions { opacity: 1; }
.prow-date {
  font-size: 0.66rem;
  color: var(--ppr-ink-faint);
  white-space: nowrap;
  font-weight: 600;
}
/* Date groups: the one rule on the sheet — between days */
.pday-head {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 10px 0 4px;
  padding-top: 9px;
  border-top: 1.5px solid var(--ppr-line);
}
.pday-head:first-child { margin-top: 0; padding-top: 0; border-top: none; }
.pday-label {
  font-size: 0.66rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.8px;
  color: var(--ppr-ink);
}
.pempty {
  text-align: center;
  font-size: 1.6rem;
  padding: 40px 0;
  color: var(--ppr-ink-faint);
  font-family: var(--ppr-hand);
}
.pempty div { font-size: 0.78rem; margin-top: 6px; }

/* -- Lists view: dropdown selector + items on lined paper -- */
.plists-select {
  padding: 5px 10px;
  border-radius: 8px;
  border: 1.5px solid var(--ppr-ink-faint);
  background: var(--ppr-card);
  color: var(--ppr-ink-dark);
  font-size: 0.8rem;
  font-weight: 700;
  font-family: inherit;
  cursor: pointer;
  max-width: 260px;
}
.plists-select:focus { outline: none; border-color: var(--ppr-ink); }
.plists-sync-line {
  min-height: 1.1em;
  font-size: 0.7rem;
  color: var(--ppr-ink);
  margin: -4px 0 6px;
  flex-shrink: 0;
}
.plists-items { padding-top: 6px; }
.plists-add { display: flex; gap: 8px; margin-top: 8px; flex-shrink: 0; }
.plists-add .input { flex: 1; }
/* Checkbox glyph for list items (planner + widgets). Clickable in the
   planner; display-only in the widgets. */
.pcheck {
  display: inline-block;
  width: 15px;
  height: 15px;
  border: 1.5px solid var(--text-faint);
  border-radius: 4px;
  flex-shrink: 0;
  position: relative;
  background: transparent;
}
.pcheck.on { border-color: var(--success); background: var(--success); }
.pcheck.on::after {
  content: '✓';
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  font-size: 11px;
  font-weight: 800;
  line-height: 1;
}
#modal-planner .pcheck { border-color: var(--ppr-ink-faint); cursor: pointer; }
#modal-planner .pcheck.on { border-color: var(--ppr-ink); background: var(--ppr-ink); }
/* Completed section at the end of a list */
.pitem-completed-head {
  margin-top: 10px;
  padding-top: 8px;
  border-top: 1.5px solid var(--ppr-line);
  font-size: 0.62rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 1px;
  color: var(--ppr-ink-faint);
}
.pitem {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 3px 8px 3px 4px;
}
.pitem-text {
  flex: 1;
  font-size: 0.92rem;
  color: var(--ppr-ink);      /* ballpoint blue, handwritten */
  font-family: var(--ppr-hand);
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.pitem.completed .pitem-text { text-decoration: line-through; opacity: 0.55; }
.pitem.completed .pcheck { opacity: 0.75; }

/* -- Notes view — sticky tab notes on lined paper, blue ink text -- */
.pnote-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(215px, 1fr));
  gap: 14px;
  align-content: start;
  padding-top: 8px;
}
.pnote-card {
  border: none;
  border-radius: 2px 2px 6px 2px;
  padding: 12px 12px 10px;
  cursor: pointer;
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-height: 118px;
  box-shadow: 2px 3px 8px rgba(60, 50, 20, 0.22), 1px 1px 2px rgba(60, 50, 20, 0.14);
  transition: transform var(--transition), box-shadow var(--transition);
  /* sticky pad variants (pastel assortment) */
  background: #fff7a6;
}
.pnote-card:nth-child(4n + 2) { background: #d9ecff; }
.pnote-card:nth-child(4n + 3) { background: #ffdfe5; }
.pnote-card:nth-child(4n + 4) { background: #e2f5d7; }
/* hand-placed feel: a gentle alternating tilt */
.pnote-card:nth-child(odd) { transform: rotate(-0.7deg); }
.pnote-card:nth-child(even) { transform: rotate(0.5deg); }
.pnote-card:hover {
  transform: rotate(0deg) translateY(-3px);
  box-shadow: 4px 7px 16px rgba(60, 50, 20, 0.30);
  z-index: 2;
}
.pnote-card.expired { opacity: 0.6; }
.pnote-title {
  font-size: 0.88rem;
  font-weight: 700;
  color: var(--ppr-ink);     /* blue ink, never black */
  font-family: var(--ppr-hand);
  padding-right: 18px;
  line-height: 1.35;
}
.pnote-body {
  font-size: 0.8rem;
  color: var(--ppr-ink);
  font-family: var(--ppr-hand);
  line-height: 1.55;
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 5;
  -webkit-box-orient: vertical;
}
.pnote-dates {
  font-size: 0.64rem;
  font-weight: 700;
  color: #33518f;
  margin-top: auto;
}
.pnote-dates.expired { color: var(--ppr-red); }
.pnote-actions {
  position: absolute;
  top: 4px;
  right: 4px;
  opacity: 0.35;
  transition: opacity var(--transition);
}
.pnote-card:hover .pnote-actions { opacity: 1; }
#modal-planner .btn-icon {
  background: rgba(255, 255, 255, 0.55);
  color: var(--ppr-ink-dark);
  border: 1px solid rgba(43, 80, 168, 0.25);
}

/* -- Form drawer — an index card sliding over the page -- */
.planner-drawer {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: 400px;
  max-width: 100%;
  background: var(--ppr-card);
  border-left: 2px solid var(--ppr-edge);
  box-shadow: -16px 0 40px rgba(60, 50, 20, 0.25);
  display: flex;
  flex-direction: column;
  transform: translateX(105%);
  transition: transform 0.26s cubic-bezier(0.4, 0, 0.2, 1);
  z-index: 6;
}
.planner-drawer.open { transform: none; }
.planner-drawer-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 8px;
  padding: 14px 16px 10px;
  flex-shrink: 0;
  border-top: 3px double var(--ppr-red);   /* index-card top rule */
}
.planner-drawer-title {
  font-size: 0.95rem;
  font-weight: 800;
  color: var(--ppr-ink-dark);
}
.pdrawer-sub { font-size: 0.7rem; font-weight: 600; color: var(--ppr-ink-faint); }
.planner-drawer-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 4px 16px;
  background-image: repeating-linear-gradient(to bottom,
    transparent, transparent 27px,
    var(--ppr-line) 27px, var(--ppr-line) 28px);
  background-attachment: local;
}
.planner-drawer-actions {
  display: flex;
  gap: 8px;
  justify-content: flex-end;
  padding: 12px 16px 14px;
  flex-shrink: 0;
  border-top: 1.5px solid var(--ppr-line);
}
.pform-group { margin-bottom: 14px; }
.pform-group label {
  display: block;
  font-size: 0.68rem;
  font-weight: 800;
  color: var(--ppr-ink);
  margin-bottom: 4px;
  text-transform: uppercase;
  letter-spacing: 0.5px;
}
.pform-hint { font-size: 0.68rem; color: var(--ppr-ink-faint); margin-top: 3px; }
.pform-row { display: flex; gap: 10px; }
.pform-col { flex: 1; }
.pform-static {
  font-size: 0.9rem;
  font-weight: 700;
  color: var(--ppr-ink);
  font-family: var(--ppr-hand);
  padding: 8px 12px;
  border: 1.5px dashed var(--ppr-ink-faint);
  border-radius: 8px;
  margin-bottom: 12px;
}
/* ink inputs inside the drawer */
#modal-planner .planner-drawer .input,
#modal-planner .planner-drawer .textarea {
  background: #fff;
  border: 1.5px solid var(--ppr-ink-faint);
  color: var(--ppr-ink-dark);
  border-radius: 8px;
}
#modal-planner .planner-drawer .input:focus,
#modal-planner .planner-drawer .textarea:focus {
  border-color: var(--ppr-ink);
  box-shadow: 0 0 0 2px rgba(43, 80, 168, 0.15);
}

/* -- Planner responsive / kiosk -- */
@media (max-width: 900px) {
  .planner-head { gap: 8px; }
  .planner-title { font-size: 0.95rem; }
  .planner-tab { padding: 7px 10px 8px; font-size: 0.72rem; }
  /* stack: mini cal (horizontal strip) / sheet / big calendar below */
  .planner-body { flex-direction: column; }
  .planner-mcal {
    width: auto;
    border-right: none;
    border-bottom: 1.5px solid var(--ppr-line);
    flex-direction: row;
    align-items: center;
    gap: 12px;
    padding: 10px 12px;
    overflow-x: auto;
  }
  .planner-mcal .mcal-grid { grid-auto-flow: column; }
  .planner-main { order: 2; flex: 1 1 auto; }   /* column layout: height, not width */
  .planner-bigcal {
    order: 3;
    flex: 0 0 auto;
    border-right: none;
    border-top: 1.5px solid var(--ppr-line);
    max-height: 52%;
  }
  .planner-drawer { width: 100%; }
}
[data-display="small"] .planner-shell {
  width: 100vw;
  height: 100vh;
  border-radius: 0;
  border: none;
}
[data-display="small"] .planner-main { padding: 10px; }

/* Narrow screens: the side-by-side shopping+todo pair stacks back to
   vertical so each list keeps a readable width */
@media (max-width: 720px) {
  #dashboard-grid .card-pair.card-pair-row { flex-direction: column; }
}

/* ---------- Recipes app (2026-10-04) --------------------------------------
   Planner-style application modal in the standard theme: shell + tabs,
   discover/cookbook/pantry/plan/sources views, recipe detail overlay,
   and the cooking-mode step pager. The food domain accent (--dom-food)
   carries the hue. */
.recipes-shell {
  position: relative;
  background: var(--bg-deep);
  border: 1px solid var(--border);
  border-radius: 16px;
  box-shadow: 0 24px 64px rgba(0, 0, 0, 0.4);
  width: min(1100px, 95vw);
  height: min(780px, 92vh);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  color: var(--text);
}
.recipes-head {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 16px 0;
  border-bottom: 2px solid var(--dom-food);
  flex-shrink: 0;
  flex-wrap: wrap;
}
.recipes-title {
  font-size: 1.05rem;
  font-weight: 800;
  color: var(--dom-food);
  padding-bottom: 10px;
  white-space: nowrap;
}
.recipes-tabs {
  display: flex;
  gap: 4px;
  align-items: flex-end;
  flex: 1;
  min-width: 0;
  overflow-x: auto;
  scrollbar-width: none;
}
.recipes-tabs::-webkit-scrollbar { display: none; }
.recipes-tab {
  border: 1.5px solid var(--border);
  border-bottom: none;
  border-radius: 10px 10px 0 0;
  background: var(--bg);
  color: var(--text-dim);
  font-size: 0.8rem;
  font-weight: 700;
  font-family: inherit;
  padding: 8px 14px 9px;
  cursor: pointer;
  white-space: nowrap;
  position: relative;
  top: 2px;
  transition: background var(--transition), color var(--transition);
}
.recipes-tab:hover { color: var(--text); }
.recipes-tab.active {
  background: var(--card);
  color: var(--dom-food);
  top: 0;
  padding-bottom: 11px;
  box-shadow: 0 2px 0 var(--card);
}
.recipes-head-actions {
  display: flex;
  gap: 8px;
  align-items: center;
  padding-bottom: 10px;
}
.recipes-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  background: var(--card);
  padding: 14px 16px;
}
.rpanel-title {
  font-size: 0.85rem;
  font-weight: 800;
  color: var(--text);
  text-transform: uppercase;
  letter-spacing: 0.5px;
  margin-bottom: 8px;
}
.rview-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 18px;
  align-items: start;
}
@media (max-width: 860px) { .rview-grid { grid-template-columns: 1fr; } }
.rsearch-row { display: flex; gap: 8px; margin-bottom: 10px; }
.rsearch-row .input { flex: 1; min-width: 0; }
.rhint {
  font-size: 0.72rem;
  color: var(--text-faint);
  line-height: 1.4;
}
.rsearch-results { margin-top: 4px; }
.rsearch-row-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: 8px;
  margin-bottom: 6px;
}
.rsearch-row-item:hover { background: var(--bg-deep); }
.rsearch-row-main { flex: 1; min-width: 0; }
.rsearch-title {
  font-size: 0.84rem;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.rsearch-snippet {
  font-size: 0.72rem;
  color: var(--text-dim);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.rcan-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 8px;
  border-radius: 6px;
  cursor: pointer;
}
.rcan-row:hover { background: var(--bg-deep); }
.rcan-title { flex: 1; font-size: 0.82rem; font-weight: 600; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rcan-pct { font-size: 0.72rem; font-weight: 700; color: var(--dom-list); white-space: nowrap; }
.rcan-missing { font-size: 0.7rem; color: var(--text-faint); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 40%; }
.rtoolbar {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 12px;
  flex-wrap: wrap;
}
.rtoolbar-count { font-size: 0.75rem; color: var(--text-faint); margin-left: auto; }
/* Cookbook grid */
.recipe-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: 10px;
}
.recipe-card {
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--bg-deep);
  overflow: hidden;
  cursor: pointer;
  transition: transform var(--transition), border-color var(--transition);
}
.recipe-card:hover { transform: translateY(-2px); border-color: var(--dom-food); }
.recipe-card-img {
  height: 84px;
  background-size: cover;
  background-position: center;
  background-color: var(--bg);
}
.recipe-card-img-blank {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.8rem;
  opacity: 0.6;
}
.recipe-card-title {
  font-size: 0.84rem;
  font-weight: 700;
  padding: 8px 10px 2px;
  line-height: 1.3;
  min-height: 2.6em;
}
.recipe-card-meta { font-size: 0.7rem; color: var(--text-dim); padding: 0 10px 8px; }
.recipe-card-cat {
  display: inline-block;
  font-size: 0.62rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--dom-food);
  border-top: 1px solid var(--border);
  padding: 5px 10px;
  width: 100%;
}
.recipe-card-stars { font-size: 0.7rem; color: var(--warning); padding: 0 10px 6px; }
/* Detail overlay (covers the body area) */
.recipes-detail {
  position: absolute;
  inset: 0;
  background: var(--card);
  z-index: 5;
  overflow-y: auto;
  padding: 16px 18px;
}
.rdetail-head {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 6px;
}
.rdetail-title { flex: 1; font-size: 1.25rem; font-weight: 800; color: var(--dom-food); }
.rdetail-actions { display: flex; gap: 8px; align-items: center; }
.rdetail-meta {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  font-size: 0.76rem;
  color: var(--text-dim);
  padding-bottom: 10px;
  border-bottom: 1px solid var(--border);
  margin-bottom: 12px;
}
.rdetail-meta a { color: var(--primary); }
.rserv-input { width: 56px; padding: 2px 6px; text-align: center; }
.rrate-star { cursor: pointer; color: var(--text-faint); font-size: 1rem; }
.rrate-star.on { color: var(--warning); }
.rdetail-cols {
  display: grid;
  grid-template-columns: 1fr 1.4fr;
  gap: 18px;
  align-items: start;
}
@media (max-width: 760px) { .rdetail-cols { grid-template-columns: 1fr; } }
.rdetail-col-title {
  font-size: 0.78rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.6px;
  color: var(--text-dim);
  margin-bottom: 6px;
}
.ring-row {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 5px 0;
  border-bottom: 1px solid var(--border);
  font-size: 0.82rem;
}
.ring-row:last-child { border-bottom: none; }
.ring-row.have .ring-text { color: var(--text-dim); }
.ring-text { flex: 1; }
.ring-pantry { color: var(--dom-list); font-weight: 800; font-size: 0.8rem; }
.rstep-row {
  display: flex;
  gap: 10px;
  padding: 7px 0;
  border-bottom: 1px solid var(--border);
  font-size: 0.84rem;
  line-height: 1.45;
}
.rstep-row:last-child { border-bottom: none; }
.rstep-n {
  flex-shrink: 0;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--dom-food);
  color: #fff;
  font-size: 0.72rem;
  font-weight: 800;
  display: flex;
  align-items: center;
  justify-content: center;
}
.rdetail-notes { margin-top: 14px; }
.rdetail-notes .input { width: 100%; resize: vertical; font-family: inherit; }
.rdetail-notes-row { display: flex; gap: 8px; align-items: center; margin-top: 6px; }
/* Cooking mode */
.rcook {
  display: flex;
  flex-direction: column;
  height: 100%;
  min-height: 380px;
}
.rcook-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 14px;
}
.rcook-title { font-size: 1.05rem; font-weight: 800; color: var(--dom-food); }
.rcook-count { font-size: 0.78rem; font-weight: 600; color: var(--text-dim); }
.rcook-step {
  flex: 1;
  font-size: 1.5rem;
  line-height: 1.55;
  font-weight: 600;
  padding: 24px;
  background: var(--bg-deep);
  border-radius: 14px;
  border: 1px solid var(--border);
}
.rcook-actions {
  display: flex;
  gap: 10px;
  justify-content: center;
  margin-top: 16px;
}
/* Pantry */
.rpantry-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 0;
  border-bottom: 1px solid var(--border);
  font-size: 0.84rem;
}
.rpantry-row:last-child { border-bottom: none; }
.rpantry-name { flex: 1; font-weight: 600; }
.rpantry-qty { color: var(--text-dim); font-size: 0.78rem; }
.rpantry-list { max-width: 620px; }
/* Meal plan */
.rplan-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 8px;
}
@media (max-width: 980px) { .rplan-grid { grid-template-columns: repeat(4, 1fr); } }
@media (max-width: 620px) { .rplan-grid { grid-template-columns: repeat(2, 1fr); } }
.rplan-day {
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--bg-deep);
  padding: 8px;
  min-height: 110px;
}
.rplan-day.today { border-color: var(--dom-food); }
.rplan-day-name {
  font-size: 0.7rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--text-dim);
  margin-bottom: 6px;
}
.rplan-cell { display: flex; flex-direction: column; gap: 6px; }
.rplan-recipe {
  font-size: 0.78rem;
  font-weight: 600;
  line-height: 1.3;
  cursor: pointer;
  color: var(--dom-food);
}
.rplan-recipe:hover { text-decoration: underline; }
.rplan-add { font-size: 0.7rem; }
.rplan-picker .rplan-pick-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: 8px;
  margin-bottom: 6px;
  cursor: pointer;
  font-size: 0.84rem;
}
.rplan-picker .rplan-pick-row:hover { background: var(--bg-deep); }
/* Sources */
.rsource-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 0;
  border-bottom: 1px solid var(--border);
}
.rsource-row:last-child { border-bottom: none; }
.rsource-main { flex: 1; min-width: 0; }
.rsource-name { font-size: 0.84rem; font-weight: 700; }
.rsource-url {
  font-size: 0.72rem;
  color: var(--text-faint);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.rsource-list { max-width: 720px; }
/* (620px max-widths on pantry/sources — 640px is a retired clock
   breakpoint value, pinned absent by test_display_sizing) */
/* Small displays: full-bleed recipes app */
[data-display="small"] .recipes-shell {
  width: 100vw;
  height: 100vh;
  border-radius: 0;
  border: none;
}

