/* Liquid glass over a soft, colourful backdrop, after Apple's fluid-interface guidance: materials of three
   weights (thick chrome, regular cards, thin chips) with solid controls on top, feedback on the press, type
   sized and tracked per size, and quieter variants for reduced motion, reduced transparency and more contrast. */
:root {
  color-scheme: light dark;
  --bg: #e9edf6; --bg-warm: #ffe9d6; --bg-cool: #dcefff; --bg-mint: #e2f7ee;
  --material-thick: rgba(255, 255, 255, 0.7); --material: rgba(255, 255, 255, 0.52); --material-thin: rgba(255, 255, 255, 0.38);
  /* The floating header's glass: thicker than a card's, so its text reads over the palest or darkest tile under it. */
  --material-chrome: rgba(255, 255, 255, 0.84);
  --material-solid: #f7f8fb;
  --control: rgba(255, 255, 255, 0.82); --field: rgba(255, 255, 255, 0.6);
  /* A search field's fill, as iOS's search bars: grey, so it reads on a white card too. */
  --search-fill: rgba(118, 118, 128, 0.14); --search-glyph: rgba(60, 60, 67, 0.6);
  --search-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238a8a92' stroke-width='2.2' stroke-linecap='round'%3E%3Ccircle cx='10.5' cy='10.5' r='6'/%3E%3Cpath d='m15 15 5 5'/%3E%3C/svg%3E");
  --edge: rgba(255, 255, 255, 0.85); --edge-light: rgba(255, 255, 255, 0.6);
  --shadow-thick: 0 10px 30px rgba(25, 34, 56, 0.16); --shadow: 0 12px 36px rgba(25, 34, 56, 0.12); --shadow-control: 0 2px 8px rgba(25, 34, 56, 0.08);
  --sheen: linear-gradient(180deg, rgba(255, 255, 255, 0.45), rgba(255, 255, 255, 0) 45%);
  --text: #15171c; --muted: #596170; --line: rgba(20, 30, 50, 0.1);
  --accent: #ff7a1a; --accent-2: #ffb15c; --accent-text: #ffffff; --ok: #157a42; --warn: #a65a0f; --error: #c0302f; --paused: #5856d6;
  /* Orange that carries text, held to WCAG AA (4.5:1): --accent-ink for orange words on light glass, and
     --accent-fill-top to --accent-fill for orange surfaces under white words (a button, the current tab, the avatar).
     The bright --accent stays for what is not read: borders, focus rings, switches, glows. */
  --accent-ink: #b0460a; --accent-fill-top: #c4500c; --accent-fill: #ab3f0a;
  /* Chart series, slots 1 and 2 of a palette checked for colour-blind separation and contrast, each mode its own step. */
  --series-1: #2a78d6; --series-2: #eb6834;
  /* Slots 3 to 7, the same validated palette (aqua, yellow, magenta, green, violet), for the Energy section's roles and
     its battery lines; each mode its own step. */
  --series-3: #1baf7a; --series-4: #eda100; --series-5: #e87ba4; --series-6: #008300; --series-7: #6250d6;
  /* Blue that carries small text (the Encrypted pill) at 4.5:1 on its tint; --series-1 stays for marks and bars. */
  --series-1-ink: #1d5fae;
  --font: system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --mono: ui-monospace, SFMono-Regular, Menlo, monospace;
  --radius: 22px; --blur-thick: 32px; --blur: 20px;
  /* Shape, on a 4 px rhythm: chips and swatches, small controls and icon tiles, controls and rows, groups and
     menus, a card's --radius, then sheets, panels and dialogs; --radius-pill for capsules (a radius of half the
     height). A shape nested in another keeps the outer radius minus the inset between them, so the two curves stay
     concentric. Only hairline marks (bars, ticks, grabbers) go under --radius-xs. */
  --radius-xs: 6px; --radius-sm: 10px; --radius-md: 14px; --radius-lg: 18px; --radius-xl: 26px; --radius-pill: 999px;
  /* Spacing for gaps, padding and margins, on a 2 px grid and named by size (--space-8 is 8 px): 4 to 8 inside a
     control, 10 to 14 between controls and rows, 16 to 24 around groups and cards. Odd and 1 to 3 px values are
     optical nudges (a border, a thumb's inset) and stay literal. */
  --space-4: 4px; --space-6: 6px; --space-8: 8px; --space-10: 10px; --space-12: 12px; --space-14: 14px;
  --space-16: 16px; --space-18: 18px; --space-20: 20px; --space-24: 24px;
  /* Type, a ramp in rem from an 11 px caption to a 22 px title around the body's --text-base (15 px), so it follows
     the browser's text size. Weights by role, --weight-figure for numbers set large (stats, readings, charts).
     Fields stay at 16 px on touch screens, where less makes iOS zoom the page. */
  --text-2xs: 0.6875rem; --text-xs: 0.75rem; --text-sm: 0.8125rem; --text-md: 0.875rem; --text-base: 0.9375rem;
  --text-lg: 1rem; --text-xl: 1.0625rem; --text-2xl: 1.25rem; --text-3xl: 1.375rem;
  --weight-regular: 400; --weight-medium: 500; --weight-semibold: 600; --weight-figure: 650; --weight-bold: 700;
  /* Layers for what floats over the page: the phone's tab bar, side panels, menus and pop-overs, a widget being
     dragged, tooltips. A scrim sits one below what it dims. */
  --layer-tabbar: 15; --layer-panel: 20; --layer-menu: 30; --layer-drag: 40; --layer-tip: 50;
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1); --fast: 120ms; --normal: 200ms;
}
@media (prefers-color-scheme: dark) {
  :root:not(:where([data-theme="light"])) {
    --bg: #0f1218; --bg-warm: #3a2a1e; --bg-cool: #15243a; --bg-mint: #14302a;
    --material-thick: rgba(28, 31, 40, 0.74); --material: rgba(34, 38, 48, 0.54); --material-thin: rgba(255, 255, 255, 0.06);
    --material-chrome: rgba(24, 27, 35, 0.88);
    --material-solid: #1d2129;
    --control: rgba(70, 76, 92, 0.75); --field: rgba(0, 0, 0, 0.28);
    --search-fill: rgba(118, 118, 128, 0.26); --search-glyph: rgba(235, 235, 245, 0.6);
    --search-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23a7a7b0' stroke-width='2.2' stroke-linecap='round'%3E%3Ccircle cx='10.5' cy='10.5' r='6'/%3E%3Cpath d='m15 15 5 5'/%3E%3C/svg%3E");
    --edge: rgba(255, 255, 255, 0.16); --edge-light: rgba(255, 255, 255, 0.14);
    --shadow-thick: 0 10px 30px rgba(0, 0, 0, 0.5); --shadow: 0 14px 40px rgba(0, 0, 0, 0.42); --shadow-control: 0 2px 8px rgba(0, 0, 0, 0.3);
    --sheen: linear-gradient(180deg, rgba(255, 255, 255, 0.10), rgba(255, 255, 255, 0) 45%);
    --text: #f3f4f7; --muted: #a2a9b5; --line: rgba(255, 255, 255, 0.1);
    --warn: #e9a04a; --paused: #8e8cff; --ok: #3ccf7a; --error: #ff6b6b; --accent-ink: #ff8f3d;
    --series-1: #3987e5; --series-2: #d95926; --series-1-ink: #6aa6ee;
    --series-3: #199e70; --series-4: #c98500; --series-5: #d55181; --series-6: #008300; --series-7: #9085e9;
  }
}
/* A theme chosen in the web UI (/appearance) rather than the system's: common.js sets data-theme. */
:root:where([data-theme="light"]) { color-scheme: light; }
:root:where([data-theme="dark"]) {
  color-scheme: dark;
  --bg: #0f1218; --bg-warm: #3a2a1e; --bg-cool: #15243a; --bg-mint: #14302a;
  --material-thick: rgba(28, 31, 40, 0.74); --material: rgba(34, 38, 48, 0.54); --material-thin: rgba(255, 255, 255, 0.06);
  --material-chrome: rgba(24, 27, 35, 0.88);
  --material-solid: #1d2129;
  --control: rgba(70, 76, 92, 0.75); --field: rgba(0, 0, 0, 0.28);
  --search-fill: rgba(118, 118, 128, 0.26); --search-glyph: rgba(235, 235, 245, 0.6);
  --search-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23a7a7b0' stroke-width='2.2' stroke-linecap='round'%3E%3Ccircle cx='10.5' cy='10.5' r='6'/%3E%3Cpath d='m15 15 5 5'/%3E%3C/svg%3E");
  --edge: rgba(255, 255, 255, 0.16); --edge-light: rgba(255, 255, 255, 0.14);
  --shadow-thick: 0 10px 30px rgba(0, 0, 0, 0.5); --shadow: 0 14px 40px rgba(0, 0, 0, 0.42); --shadow-control: 0 2px 8px rgba(0, 0, 0, 0.3);
  --sheen: linear-gradient(180deg, rgba(255, 255, 255, 0.10), rgba(255, 255, 255, 0) 45%);
  --text: #f3f4f7; --muted: #a2a9b5; --line: rgba(255, 255, 255, 0.1);
  --warn: #e9a04a; --paused: #8e8cff; --ok: #3ccf7a; --error: #ff6b6b; --accent-ink: #ff8f3d;
  --series-1: #3987e5; --series-2: #d95926; --series-1-ink: #6aa6ee;
  --series-3: #199e70; --series-4: #c98500; --series-5: #d55181; --series-6: #008300; --series-7: #9085e9;
}
* { box-sizing: border-box; }
/* Hidden means hidden, whatever display a component's class gives it. */
[hidden] { display: none !important; }
html { min-height: 100%; background: var(--bg); }
body {
  margin: 0; font: 400 0.9375rem/1.45 var(--font); font-optical-sizing: auto; color: var(--text);
  -webkit-tap-highlight-color: transparent;
}
/* The backdrop is a fixed layer of its own: `background-attachment: fixed` repaints the page on every scroll
   frame under the blurred surfaces. */
body::before {
  content: ""; position: fixed; inset: 0; z-index: -1; pointer-events: none;
  background:
    radial-gradient(55% 45% at 8% 6%, var(--bg-warm) 0%, transparent 62%),
    radial-gradient(50% 42% at 92% 16%, var(--bg-cool) 0%, transparent 60%),
    radial-gradient(60% 55% at 50% 100%, var(--bg-mint) 0%, transparent 65%),
    var(--bg);
}
.hidden { display: none !important; }

/* Materials. Content scrolls under the floating header (thick); cards hold content (regular); chips and
   groups are tinted only (thin); controls are solid, since a blur on a blur loses contrast and frames. */
.card, .log, .banner {
  background-color: var(--material); background-image: var(--sheen);
  -webkit-backdrop-filter: blur(var(--blur)) saturate(180%); backdrop-filter: blur(var(--blur)) saturate(180%);
  border: 1px solid var(--edge); box-shadow: var(--shadow), inset 0 1px 0 var(--edge-light);
  border-radius: var(--radius);
}
header {
  position: sticky; top: 12px; z-index: 2; margin: var(--space-12) auto 0; max-width: 1100px; width: calc(100% - 24px);
  display: flex; align-items: center; gap: var(--space-14); padding: var(--space-8) var(--space-10) var(--space-8) var(--space-20); border-radius: var(--radius-pill);
  background-color: var(--material-chrome); background-image: var(--sheen);
  -webkit-backdrop-filter: blur(var(--blur-thick)) saturate(180%); backdrop-filter: blur(var(--blur-thick)) saturate(180%);
  border: 1px solid var(--edge); box-shadow: var(--shadow-thick), inset 0 1px 0 var(--edge-light);
}
.brand { display: inline-flex; align-items: center; gap: var(--space-10); font-weight: var(--weight-bold); letter-spacing: -0.01em; color: var(--text); text-decoration: none; }
.logo { width: 36px; height: 36px; border-radius: var(--radius-sm); box-shadow: 0 2px 8px color-mix(in srgb, var(--accent) 35%, transparent); }
.logo.large { width: 72px; height: 72px; border-radius: var(--radius-lg); margin-bottom: var(--space-4); }
nav { display: flex; gap: 2px; }
/* Let navigation shrink before it can push the account control out of the header. */
header .brand { flex: none; margin-inline-start: var(--space-4); }
header nav { min-width: 0; overflow-x: auto; scrollbar-width: none; }
header nav::-webkit-scrollbar { display: none; }
header nav a { flex: none; white-space: nowrap; }
header .spacer { min-width: 0; }
@media (min-width: 641px) and (max-width: 900px) {
  header { gap: var(--space-8); padding-left: var(--space-10); }
  header nav { flex: 1 1 auto; }
  header .spacer { display: none; }
  header .user-name { display: none; }
}
nav a {
  color: var(--text); text-decoration: none; padding: 7px var(--space-14); border-radius: var(--radius-pill); touch-action: manipulation;
  transition: background-color var(--fast) var(--ease-out), transform var(--fast) var(--ease-out);
}
nav a:hover { background-color: var(--material-thin); }
nav a:active { transform: scale(0.96); }
nav a.active { background: linear-gradient(180deg, var(--accent-fill-top), var(--accent-fill)); color: var(--accent-text); box-shadow: 0 6px 16px color-mix(in srgb, var(--accent) 35%, transparent), inset 0 1px 0 rgba(255, 255, 255, 0.5); }
.spacer { flex: 1; }
/* The account button at the header's right end: the user's initial on the accent and their name, opening its menu. */
.user-button {
  flex: none; display: inline-flex; align-items: center; gap: var(--space-8); padding: 3px var(--space-12) 3px 3px; max-width: 14em;
  border: 0; border-radius: var(--radius-pill); background: none; box-shadow: none; color: var(--text); font-weight: var(--weight-medium);
}
.user-button:hover, .user-button[aria-expanded="true"] { background: var(--material-thin); transform: none; }
.user-avatar {
  flex: none; display: grid; place-items: center; width: 30px; height: 30px; border-radius: 50%;
  font-size: var(--text-md); font-weight: var(--weight-figure); color: var(--accent-text);
  background: linear-gradient(145deg, var(--accent-fill-top), var(--accent-fill)); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.45), 0 2px 8px color-mix(in srgb, var(--accent) 30%, transparent);
}
.user-avatar svg { width: 17px; height: 17px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.user-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Without sign-in there is no name: the avatar alone, round. */
.user-name:empty { display: none; }
.user-button:has(.user-name:empty) { padding: 3px; }
.menu-heading { display: grid; gap: 2px; padding: var(--space-8) var(--space-12) var(--space-10); margin-bottom: var(--space-4); border-bottom: 1px solid var(--line); }
.menu-heading strong { font-size: var(--text-base); }
.menu-heading span { color: var(--muted); font-size: var(--text-sm); }
/* A plugin's settings page: the form in a card, a save bar that floats at the bottom of the window while the
   form scrolls (a thick material, like the header), and removal set apart at the end. */
.settings-head { align-items: center; }
.settings-head .tools { margin-left: auto; }
.form-card { margin: 0; }
.form-card > .server-head { margin-bottom: var(--space-14); }
.page-note { display: flex; align-items: center; gap: var(--space-14); justify-content: space-between; margin: 0 0 var(--space-14); padding: var(--space-12) var(--space-16) var(--space-12) var(--space-18); }
.page-note p { margin: 0; font-size: var(--text-md); }
.page-note .button, .danger-zone button { flex: none; white-space: nowrap; }
/* A plugin page's Expert part, last: the block as a form or as JSON, in the UI's own settings view. */
.expert .page-note { flex-wrap: wrap; }
/* A plugin card's name opens its page; Pause sits at the right of a plugin page's breadcrumb. */
.card-title { color: inherit; text-decoration: none; }
.card-title:hover strong { text-decoration: underline; }
button.small.pause-toggle { flex: none; min-height: 0; height: 28px; padding: 0 11px; gap: var(--space-6); font-size: var(--text-xs); }
button.small.pause-toggle.action-with-icon::before { width: 12px; height: 12px; }

/* A tooltip: `data-tip` on a control, shown under it on hover and on keyboard focus; `data-tip-align="end"` lines it
   up with the control's end, for one at the edge of the page. */
[data-tip] { position: relative; }
[data-tip]::after {
  content: attr(data-tip); position: absolute; z-index: 20; top: calc(100% + 8px); left: 50%; translate: -50% -4px;
  width: max-content; max-width: min(280px, 80vw); padding: var(--space-8) var(--space-12); border-radius: var(--radius-md); pointer-events: none;
  font-size: var(--text-sm); font-weight: var(--weight-regular); line-height: 1.4; text-align: left; white-space: normal; color: var(--text);
  background: var(--material-solid); border: 1px solid var(--line); box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18);
  opacity: 0; visibility: hidden; transition: opacity var(--fast) var(--ease-out), translate var(--fast) var(--ease-out), visibility 0s linear var(--fast);
}
[data-tip-align="end"]::after { left: auto; right: 0; translate: 0 -4px; }
[data-tip]:focus-visible::after { opacity: 1; visibility: visible; translate: -50% 0; transition-delay: 0s; }
[data-tip-align="end"]:focus-visible::after { translate: 0 0; }
@media (hover: hover) and (pointer: fine) {
  [data-tip]:hover::after { opacity: 1; visibility: visible; translate: -50% 0; transition-delay: 0s; }
  [data-tip-align="end"]:hover::after { translate: 0 0; }
}
@media (prefers-reduced-motion: reduce) { [data-tip]::after { transition: opacity var(--fast) linear; } }
.expert-links { display: flex; gap: var(--space-8); flex: none; }
.settings-bar {
  position: sticky; bottom: 14px; z-index: 3; display: flex; align-items: center; gap: var(--space-10); margin: var(--space-14) 0 0;
  padding: var(--space-8) var(--space-8) var(--space-8) var(--space-20); border-radius: var(--radius-pill);
  background-color: var(--material-thick); background-image: var(--sheen);
  -webkit-backdrop-filter: blur(var(--blur-thick)) saturate(180%); backdrop-filter: blur(var(--blur-thick)) saturate(180%);
  border: 1px solid var(--edge); box-shadow: var(--shadow-thick), inset 0 1px 0 var(--edge-light);
}
.settings-bar > span:first-child { flex: 1; min-width: 0; font-size: var(--text-md); }
.settings-bar > .dirty, .save-bar > .dirty { color: var(--warn); font-weight: var(--weight-medium); }
.danger-zone { display: flex; align-items: center; justify-content: space-between; gap: var(--space-16); margin: 32px 0 0; }
.danger-zone p { margin: var(--space-4) 0 0; font-size: var(--text-md); }
button.danger { color: var(--error); border-color: rgba(208, 56, 59, 0.35); }
button.danger:hover:not(:disabled) { background: rgba(208, 56, 59, 0.08); }

/* Forms stay calm: list entries (lights, TVs) are rows that open to edit, and options left unset wait under
   "More options". */
details.entry { border: 1px solid var(--line); border-radius: var(--radius-lg); margin: var(--space-8) 0; background: var(--material-thin); }
details.entry > summary { display: flex; align-items: center; gap: var(--space-10); padding: var(--space-10) var(--space-14); list-style: none; color: var(--text); }
details.entry > summary::-webkit-details-marker { display: none; }
details.entry > summary::before { content: "›"; color: var(--muted); transition: transform var(--fast) var(--ease-out); }
details.entry[open] > summary::before { transform: rotate(90deg); }
details.entry > summary .entry-name { font-weight: var(--weight-semibold); }
details.entry > summary .entry-detail { color: var(--muted); font-size: var(--text-sm); flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
details.entry > .fields, details.entry > .entry-body { padding: 0 var(--space-14) var(--space-12); }
details.more-options { margin: var(--space-10) 0 2px; }
details.more-options > summary { font-size: var(--text-sm); color: var(--accent-ink); font-weight: var(--weight-medium); padding: var(--space-6) 0; }
details.more-options[open] > summary { margin-bottom: var(--space-4); }

/* Plugin pages: a heading with the plugin's tile, card feet with their links, and panels (an editor that opens
   under the cards) with a head and two columns. A button working for a moment shows a spinner (act()). */
.page-head:has(> .tile) { align-items: center; }
.panel { margin-top: var(--space-14); display: grid; gap: var(--space-16); animation: materialize var(--normal) var(--ease-out); scroll-margin-top: 90px; }
.panel-head { display: flex; justify-content: space-between; align-items: flex-start; gap: var(--space-12); }
.panel-head h2 { margin: 0 0 var(--space-4); }
.panel-head p { margin: 0; font-size: var(--text-sm); }
.panel-columns { display: grid; grid-template-columns: minmax(0, 3fr) minmax(0, 2fr); gap: var(--space-20); align-items: start; }
button.busy::after {
  content: ""; display: inline-block; width: 0.9em; height: 0.9em; margin-left: var(--space-8); vertical-align: -0.12em;
  border-radius: 50%; border: 2px solid currentColor; border-right-color: transparent; animation: spin 0.8s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
/* A remote's keys (widgets.js "remote"): a key lights at once as its button is pressed and fades out slowly; the tile
   gives a small press. Under reduced motion only the colour changes. */
.remote-keys { display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-10); margin-top: var(--space-12); }
.remote-key-row { display: flex; flex-wrap: wrap; gap: var(--space-8); }
.remote-battery { font-size: var(--text-sm); font-weight: var(--weight-medium); color: var(--warn); }
.remote-key {
  min-width: 36px; height: 36px; padding: 0 var(--space-10); border-radius: var(--radius-sm); display: inline-grid; place-items: center;
  background: var(--material-thin); border: 1px solid var(--line); font-weight: var(--weight-semibold); font-variant-numeric: tabular-nums;
  transition: background-color 600ms var(--ease-out), color 600ms var(--ease-out), transform 300ms var(--ease-out);
}
/* On a tall tile the keys sit between its icon and its name (widgets.js `middle`). */
.w-middle .remote-key-row { gap: var(--space-6); flex-wrap: nowrap; }
.w-middle .remote-key { min-width: 28px; height: 28px; padding: 0 var(--space-8); border-radius: var(--radius-sm); font-size: var(--text-sm); }
.remote-key.pressed { background: var(--accent); color: var(--accent-text); transform: scale(0.94); transition-duration: 60ms; }
.widget .tile.pressed { transform: scale(0.94); transition: transform 60ms var(--ease-out); }
@media (prefers-reduced-motion: reduce) { .remote-key.pressed, .widget .tile.pressed { transform: none; } }
/* Something loading: a ring that turns, faded in after 150 ms so a quick load does not flash it; a page's in the middle
   of the view. */
.spinner {
  display: inline-block; width: 22px; height: 22px; border-radius: 50%; border: 2px solid var(--line); border-top-color: var(--accent);
  vertical-align: middle; animation: spin 0.8s linear infinite, fade var(--normal) var(--ease-out) 150ms both;
}
.view-loading { display: grid; place-items: center; min-height: 40vh; }
.view-loading .spinner, .log-loading .spinner { width: 30px; height: 30px; border-width: 3px; }
.log-loading { display: grid; place-items: center; height: 100%; min-height: 160px; }
@media (prefers-reduced-motion: reduce) {
  .panel { animation: none; }
  button.busy::after { animation: none; border-right-color: currentColor; opacity: 0.5; }
  .spinner { animation: fade var(--normal) var(--ease-out) 150ms both; border-color: var(--accent); opacity: 0.5; }
}
@media (max-width: 640px) { .panel-columns { grid-template-columns: 1fr; } }

/* The password strength: the ANSSI's bands along 0 to 128 bits as one gradient, from red through amber to green,
   lit up to the password's entropy as you type; the 85-bit bar marked. Its own names: the widgets' dial is .gauge. */
:root { --entropy: linear-gradient(90deg, #ff453a 0%, #ff6a2b 30%, #ff9f0a 50.8%, #ffd60a 66.4%, #30d158 78.1%, #20c4a8 100%); }
.strength { margin-top: var(--space-10); display: grid; gap: var(--space-6); }
.strength-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-10); font-variant-numeric: tabular-nums; }
.strength-level { font-size: var(--text-base); font-weight: var(--weight-semibold); transition: color var(--normal) var(--ease-out); }
.strength-bits { font-size: var(--text-sm); color: var(--muted); }
.strength-track { position: relative; height: 12px; border-radius: var(--radius-pill); background: var(--material-thin); box-shadow: inset 0 0 0 1px var(--line); }
/* The whole scale shows faintly; the fill is the same gradient, cut at the entropy, so each band keeps its colour. */
.strength-track::before { content: ""; position: absolute; inset: 0; border-radius: inherit; background: var(--entropy); opacity: 0.2; }
.strength-fill {
  position: absolute; inset: 0; border-radius: inherit; background: var(--entropy);
  clip-path: inset(0 calc(100% - var(--lit, 0%)) 0 0 round 999px);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.45);
  transition: clip-path var(--normal) var(--ease-out);
}
.strength-tick { position: absolute; top: 3px; bottom: 3px; width: 1px; background: rgba(255, 255, 255, 0.75); mix-blend-mode: overlay; }
.strength-mark { position: absolute; top: -5px; bottom: -5px; width: 3px; margin-left: -1.5px; border-radius: 2px; background: var(--text); box-shadow: 0 0 0 2px var(--material-solid); }
.strength-scale { position: relative; height: 1.2em; font-size: var(--text-2xs); color: var(--muted); }
.strength-scale span { position: absolute; top: 0; text-align: center; white-space: nowrap; }
.strength[data-level="veryWeak"] .strength-level { color: var(--error); }
.strength[data-level="lowToMedium"] .strength-level { color: var(--warn); }
.strength[data-level="mediumToStrong"] .strength-level, .strength[data-level="strongToVeryStrong"] .strength-level { color: var(--ok); }
.strength-rules { list-style: none; margin: var(--space-4) 0 0; padding: 0; display: grid; gap: 3px; font-size: var(--text-sm); color: var(--muted); }
.strength-rules li::before { content: "○"; display: inline-block; width: 1.3em; }
.strength-rules li.met { color: var(--ok); }
.strength-rules li.met::before { content: "✓"; }
.strength-hint { margin: 2px 0 0; min-height: 1em; }
@media (prefers-reduced-motion: reduce) { .strength-fill, .strength-level { transition: none; } }

/* Account: who is signed in, then the password form with the new password's entropy beside its fields. */
.account { display: grid; gap: var(--space-14); max-width: 920px; }
.account .card { margin: 0; }
.account h2 { margin: 0; }
.account-profile { display: flex; align-items: center; gap: var(--space-16); }
.account-avatar {
  flex: none; display: grid; place-items: center; width: 52px; height: 52px; border-radius: 50%;
  font-size: var(--text-3xl); font-weight: var(--weight-semibold); color: var(--accent-text);
  background: linear-gradient(145deg, var(--accent-fill-top), var(--accent-fill));
  box-shadow: 0 8px 20px color-mix(in srgb, var(--accent) 32%, transparent), inset 0 1px 0 rgba(255, 255, 255, 0.5);
}
.account-who { flex: 1; min-width: 0; }
.account-who p { margin: 3px 0 0; }
.account-lead { margin: var(--space-4) 0 0; }
.account-password { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 22px; align-items: start; margin-top: var(--space-16); }
.account-fields .field:first-child { margin-top: 0; }
/* A form card starts at its title and ends at its buttons: no heading margin above, no empty message line below. */
.account-form > h2:first-child { margin-top: 0; }
.account-form .status-line:empty { margin: 0; min-height: 0; }
/* A side panel (openSheet in app.js: Add a user, Edit, Create a token): a task over the dimmed page, floating at
   the right edge as the header floats at the top, full height, its buttons kept at the bottom. It slides in from the
   right with the drawer curve and leaves the same way, faster (the leaving motion is openSheet's, from wherever a
   drag left it). A phone gets a sheet from the bottom edge, with a grabber to swipe it down. Reduced motion: fades. */
.admin-dialog.sheet {
  margin: var(--space-12) var(--space-12) var(--space-12) auto; width: min(460px, calc(100% - 24px)); height: calc(100% - 24px); max-height: none;
  padding: 22px var(--space-24) var(--space-20); border-radius: var(--radius); overscroll-behavior: contain; touch-action: pan-y;
}
.admin-dialog.sheet[open] { display: flex; flex-direction: column; animation: sheet-in 320ms cubic-bezier(0.32, 0.72, 0, 1); }
.admin-dialog.sheet[open]::backdrop { animation: sheet-dim 240ms var(--ease-out); }
.admin-dialog.sheet.leaving::backdrop { animation: sheet-undim 220ms var(--ease-out) forwards; }
.sheet-grabber { display: none; }
.admin-dialog.sheet > .account-form { flex: 1; display: flex; flex-direction: column; min-height: 0; }
.admin-dialog.sheet .account-form > h2:first-child { font-size: var(--text-2xl); letter-spacing: -0.015em; margin-bottom: var(--space-14); }
.admin-dialog.sheet .account-form > .actions { margin-top: auto; padding-top: var(--space-18); }
.admin-dialog.sheet .status-line:not(:empty) { margin-top: var(--space-14); }
.admin-dialog.sheet .fields { grid-template-columns: 1fr; }
@keyframes sheet-in { from { transform: translateX(calc(100% + 12px)); } }
@keyframes sheet-up { from { transform: translateY(calc(100% + 12px)); } }
@keyframes sheet-dim { from { opacity: 0; } }
@keyframes sheet-undim { to { opacity: 0; } }
@media (max-width: 640px) {
  .admin-dialog.sheet {
    margin: auto 0 0; width: 100%; max-width: 100%; height: calc(100% - 16px - env(safe-area-inset-top)); max-height: 100%;
    border-radius: var(--radius) var(--radius) 0 0; border-bottom: 0;
    padding: 26px var(--space-18) calc(var(--space-18) + env(safe-area-inset-bottom));
  }
  .admin-dialog.sheet[open] { animation-name: sheet-up; }
  .sheet-grabber { display: block; position: absolute; top: 0; left: 0; right: 0; height: 26px; touch-action: none; cursor: grab; }
  .sheet-grabber::before { content: ""; position: absolute; top: 8px; left: 50%; width: 36px; height: 5px; margin-left: -18px; border-radius: 3px; background: var(--line); }
  .admin-dialog.sheet .account-form > h2:first-child { touch-action: none; }
  .admin-dialog.sheet .account-form > .actions > button { flex: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .admin-dialog.sheet[open] { animation: sheet-dim 160ms ease; }
}
/* The password gauge unfolds once there is a password (Users' form): its height eased open, not jumped. */
.unfold { display: grid; grid-template-rows: 0fr; opacity: 0; transition: grid-template-rows 200ms var(--ease-out), opacity 160ms ease-out; }
.unfold.open { grid-template-rows: 1fr; opacity: 1; }
.unfold > div { min-height: 0; overflow: hidden; }
@media (prefers-reduced-motion: reduce) { .unfold { transition: opacity 160ms ease-out; } }
/* The card just added or changed: an accent ring that fades out, where the eye lands after the panel goes. */
.card.just-changed { animation: just-changed 1.6s var(--ease-out); }
.card.just-changed:focus { outline: none; }
@keyframes just-changed { from { box-shadow: 0 0 0 3px var(--accent), var(--shadow); } }
.facts.two { grid-template-columns: repeat(2, minmax(0, 1fr)); }
/* A heading's add button (Add user, Create token): a small round + right after the title, tinted with the accent;
   the accent fills it under a pointer. */
.title-add { display: flex; align-items: center; gap: var(--space-10); }
.title-add > :is(h1, h2) { margin: 0; }
button.add-button {
  display: inline-grid; place-items: center; flex: none; width: 28px; height: 28px; min-height: 0; padding: 0; border-radius: 50%;
  color: var(--accent-ink); background: color-mix(in srgb, var(--accent) 14%, transparent); border: 1px solid color-mix(in srgb, var(--accent) 35%, transparent);
  background: color-mix(in srgb, var(--accent) 14%, transparent); border-color: color-mix(in srgb, var(--accent) 35%, transparent);
  box-shadow: none; transition: background-color var(--fast) var(--ease-out), color var(--fast) var(--ease-out), transform 120ms var(--ease-out);
}
.page-head button.add-button { width: 30px; height: 30px; }
button.add-button svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 2.4; stroke-linecap: round; }
@media (hover: hover) and (pointer: fine) {
  button.add-button:hover { background: var(--accent-fill); color: var(--accent-text); }
}
@media (pointer: coarse) { button.add-button { position: relative; } button.add-button::after { content: ""; position: absolute; inset: -8px; } }
.pill.status.admin { color: var(--accent-ink); border-color: color-mix(in srgb, var(--accent) 40%, transparent); }
.pill.status.bad { color: var(--error); border-color: rgba(208, 56, 59, 0.4); }
.section-head > div > h2 { margin: 0; }
.section-head > div > .muted { display: block; margin-top: 2px; }
.section-head .actions { margin: 0; }
.section-head code, .account-form .help code { font-family: var(--mono); font-size: 0.92em; }
.card-foot a:not(.button) { color: var(--accent-ink); text-decoration: none; font-weight: var(--weight-medium); }
.card-foot a:not(.button):hover { text-decoration: underline; }
.strength-panel {
  padding: var(--space-16) var(--space-18); border-radius: calc(var(--radius) - var(--radius-xs));
  background: var(--material-thin); box-shadow: inset 0 0 0 1px var(--line);
}
.strength-panel .strength { margin-top: var(--space-10); gap: var(--space-8); }
.strength-panel .strength-level { font-size: var(--text-2xl); letter-spacing: -0.01em; }
.strength-panel .strength-bits { font-size: var(--text-base); }
.strength-panel .strength-track { height: 14px; }
@media (max-width: 720px) {
  /* One column, the entropy right under the new password, where the eyes are while typing it. */
  .account-password { grid-template-columns: 1fr; gap: 0; }
  .account-fields { display: contents; }
  .account-fields > :nth-child(-n+2) { order: 1; }
  .strength-panel { order: 2; margin: var(--space-8) 0 var(--space-4); }
  .account-fields > :nth-child(n+3) { order: 3; }
  .account-profile { flex-wrap: wrap; }
  .account-profile > button { width: 100%; }
}
.stack { display: grid; gap: var(--space-14); align-content: start; min-width: 0; }
.check { display: flex; gap: var(--space-8); align-items: center; margin: var(--space-14) 0 var(--space-4); font-weight: var(--weight-medium); }
.secret { word-break: break-all; user-select: all; }
main { max-width: 1100px; margin: 0 auto; padding: 22px var(--space-12) 40px; }

/* Type: the system font with its optical sizes, sizes in rem so the reader's text size applies, tracking
   and leading per size (tight and negative when large, a little wider when small), hierarchy by weight. */
h1 { font-size: 1.625rem; line-height: 1.15; letter-spacing: -0.02em; font-weight: var(--weight-bold); margin: var(--space-6) 0 var(--space-16); }
h2 { font-size: var(--text-xl); line-height: 1.25; letter-spacing: -0.01em; font-weight: var(--weight-semibold); margin: var(--space-24) 0 var(--space-10); }
strong { font-weight: var(--weight-semibold); }
.help, .pill, dt, legend, .log { letter-spacing: 0.01em; }
.card { padding: var(--space-18) var(--space-20); margin-bottom: var(--space-14); }
.muted { color: var(--muted); }
.value { font-variant-numeric: tabular-nums; color: var(--muted); min-width: 52px; text-align: right; }

/* Controls: feedback on the press, at once, and a focus ring for the keyboard. */
button, a.button {
  font: inherit; font-weight: var(--weight-medium); padding: var(--space-8) var(--space-16); border-radius: var(--radius-pill); cursor: pointer; color: var(--text); touch-action: manipulation;
  background: var(--control); border: 1px solid var(--edge); box-shadow: inset 0 1px 0 var(--edge-light), var(--shadow-control);
  transition: transform var(--fast) var(--ease-out), box-shadow var(--fast) var(--ease-out), opacity var(--fast) var(--ease-out);
}
a.button { display: inline-flex; align-items: center; justify-content: center; text-align: center; text-decoration: none; line-height: normal; }
button:active:not(:disabled), a.button:active { transform: scale(0.97); transition-duration: 80ms; }
button.primary, a.button.primary { background: linear-gradient(180deg, var(--accent-fill-top), var(--accent-fill)); color: var(--accent-text); border-color: rgba(255, 255, 255, 0.4); box-shadow: 0 8px 20px color-mix(in srgb, var(--accent) 35%, transparent), inset 0 1px 0 rgba(255, 255, 255, 0.5); }
button.link { border: 0; background: none; box-shadow: none; color: var(--accent-ink); padding: var(--space-4) var(--space-6); }
button.link:active:not(:disabled) { transform: none; opacity: 0.6; }
/* A smaller button, for a line of small text such as a page's breadcrumb. */
button.small, a.button.small { padding: var(--space-4) var(--space-12); font-size: var(--text-sm); }
button.small.action-with-icon::before, a.button.small.action-with-icon::before { width: 14px; height: 14px; }
button:disabled { opacity: .5; cursor: default; transform: none; }
button:focus-visible, a.button:focus-visible, nav a:focus-visible, summary:focus-visible, .switch input:focus-visible + span { outline: 2px solid var(--accent); outline-offset: 2px; }
input, select, textarea {
  font: inherit; color: var(--text); width: 100%; padding: var(--space-8) var(--space-12); border-radius: var(--radius-md);
  background: var(--field); border: 1px solid var(--edge); box-shadow: inset 0 1px 2px rgba(25, 34, 56, 0.08);
  transition: border-color var(--fast) var(--ease-out), box-shadow var(--fast) var(--ease-out);
}
input:focus, select:focus, textarea:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent) 18%, transparent); }
input[type=checkbox] { width: auto; box-shadow: none; accent-color: var(--accent); }
input[type=range] { padding: 0; width: 160px; background: none; border: 0; box-shadow: none; accent-color: var(--accent); }
/* Selects as pop-up buttons, after macOS: the platform's arrows replaced by one up-and-down chevron in the
   text's colour, the field's shape kept; a toolbar's (.popup) is a solid pill like the controls next to it. The
   accent ring shows for the keyboard, not for a click. */
:root { --chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 16' fill='none' stroke='%23596170' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2 6l3-3 3 3M2 10l3 3 3-3'/%3E%3C/svg%3E"); }
@media (prefers-color-scheme: dark) {
  :root:not(:where([data-theme="light"])) { --chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 16' fill='none' stroke='%23a2a9b5' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2 6l3-3 3 3M2 10l3 3 3-3'/%3E%3C/svg%3E"); }
}
:root:where([data-theme="dark"]) { --chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 16' fill='none' stroke='%23a2a9b5' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2 6l3-3 3 3M2 10l3 3 3-3'/%3E%3C/svg%3E"); }
select {
  -webkit-appearance: none; appearance: none; touch-action: manipulation; cursor: pointer; padding-right: 34px;
  background-image: var(--chevron); background-repeat: no-repeat; background-position: right 13px center; background-size: 9px 14px;
  text-overflow: ellipsis; white-space: nowrap; overflow: hidden;
}
select:focus:not(:focus-visible) { border-color: var(--edge); box-shadow: inset 0 1px 2px rgba(25, 34, 56, 0.08); }
select.popup {
  width: auto; border-radius: var(--radius-pill); padding: 7px 34px 7px 15px; font-weight: var(--weight-medium);
  background-color: var(--control); border-color: var(--edge); box-shadow: var(--shadow-control), inset 0 1px 0 var(--edge-light);
  transition: transform var(--fast) var(--ease-out), box-shadow var(--fast) var(--ease-out), border-color var(--fast) var(--ease-out);
}
select.popup:active { transform: scale(0.97); transition-duration: 80ms; }
select.popup:focus:not(:focus-visible) { border-color: var(--edge); box-shadow: var(--shadow-control), inset 0 1px 0 var(--edge-light); }
select.popup:focus-visible { border-color: var(--accent); box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent) 18%, transparent); }
select.popup.chosen { color: var(--accent-ink); }
textarea { font-family: var(--mono); font-size: var(--text-sm); min-height: 420px; white-space: pre; border-radius: var(--radius); }
label { display: block; margin: var(--space-10) 0 var(--space-6); }
label > input, label > select { margin-top: 5px; }
.help { font-size: var(--text-sm); color: var(--muted); margin: 3px 0 0; }
.error { color: var(--error); min-height: 1.2em; }
.ok { color: var(--ok); }
.pill { display: inline-block; padding: 2px var(--space-10); border-radius: var(--radius-pill); font-size: var(--text-xs); font-weight: var(--weight-medium); border: 1px solid var(--edge); background: var(--material-thin); color: var(--muted); vertical-align: middle; }
.pill.on { color: var(--ok); border-color: rgba(31, 157, 85, 0.4); }
.pill.status { white-space: nowrap; display: inline-flex; align-items: center; gap: var(--space-6); flex: none; }
.pill.status::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: currentColor; }
.pill.status.standby { color: var(--muted); }
.pill.status.away { color: var(--warn); border-color: rgba(201, 115, 26, 0.35); }
.pill.status.paused { color: var(--paused); border-color: rgba(88, 86, 214, 0.35); }

/* Tiles: an icon on a colour, like the Home app's (common.js's tile()): the accent by default, and tone-* classes
   that no control's class can collide with. */
.tile {
  width: 40px; height: 40px; flex: none; border-radius: var(--radius-sm); display: flex; align-items: center; justify-content: center; color: #fff;
  background: linear-gradient(160deg, var(--accent-2), var(--accent)); box-shadow: 0 6px 16px rgba(25, 34, 56, 0.18), inset 0 1px 0 rgba(255, 255, 255, 0.4);
}
/* A block of fixed size, centred by flexbox: Safari left an inline SVG at the top of a grid cell. */
.tile svg { display: block; flex: none; width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
/* The EcoFlow letters are the platform's wordmark: larger than the symbols, to read on the tile. */
.tile svg.icon-logo-ecoflow { width: 28px; height: 28px; }
.tile.large { width: 48px; height: 48px; border-radius: var(--radius-md); }
.tile.large svg { width: 26px; height: 26px; }
.tile.tone-violet { background: linear-gradient(160deg, #a78bfa, #7c4ddb); }
.tile.tone-blue { background: linear-gradient(160deg, #4aa3ff, #1f6fe0); }
.tile.tone-grey { background: linear-gradient(160deg, #9aa3b2, #687284); }
.tile.tone-yellow { background: linear-gradient(160deg, #ffd66b, #f0a01e); color: #5c3b00; }
.tile.tone-teal { background: linear-gradient(160deg, #4fd1c5, #1c9c91); }
.tile.tone-green { background: linear-gradient(160deg, #6ee7a0, #23a55a); }

/* Breadcrumb, on plugin pages: where the page sits, each level a way back. */
.breadcrumb { display: flex; align-items: center; justify-content: space-between; gap: var(--space-12); margin: 2px 0 var(--space-10); }
.breadcrumb ol { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-6); font-size: var(--text-sm); color: var(--muted); }
.breadcrumb li { display: inline-flex; align-items: center; gap: var(--space-6); min-width: 0; }
.breadcrumb li + li::before { content: "›"; color: var(--muted); }
.breadcrumb a { color: var(--accent-ink); text-decoration: none; font-weight: var(--weight-medium); }
.breadcrumb a:hover { text-decoration: underline; }
.breadcrumb [aria-current] span { color: var(--text); font-weight: var(--weight-medium); }

/* Page heads: the title, one line on what the page is for, and the page's tools on the right. */
.page-head { display: flex; align-items: flex-end; gap: var(--space-16); margin: var(--space-6) 0 var(--space-20); flex-wrap: wrap; }
.page-head h1 { margin: 0; }
.page-head p { margin: var(--space-4) 0 0; max-width: 62ch; }
.page-head .tools { display: flex; gap: var(--space-10); align-items: center; }
/* The title and its line keep room to read (the tools go under them when both do not fit), not a word a line. */
.page-head > .who { flex: 1 1 280px; }
.section-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-12); margin: 26px 0 var(--space-10); }
.section-head h2 { margin: 0; }
.section-head .muted { font-size: var(--text-sm); }
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 340px), 1fr)); gap: var(--space-14); }
.grid > .card { margin: 0; min-width: 0; }
.card.empty { text-align: center; padding: 28px var(--space-20); grid-column: 1 / -1; }
.card.empty p { margin: 0; }
.scenes-empty > .button { margin-top: var(--space-12); }
/* An empty state's glyph: what would be here, in a soft disc above the words. */
.empty-glyph { display: grid; place-items: center; width: 52px; height: 52px; margin: 0 auto var(--space-12); border-radius: 50%; color: var(--accent-ink); background: color-mix(in srgb, var(--accent) 12%, transparent); }
.empty-glyph svg { width: 26px; height: 26px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.card.empty:has(> .empty-glyph) p { max-width: 34em; margin-inline: auto; }
.card.notice { color: var(--warn); font-weight: var(--weight-medium); }
.card.notice p { margin: 0; }
.search { width: 240px; max-width: 100%; }
/* Search fields: a grey pill with a magnifier, the text after it; the edge only on focus. */
input[type=search] {
  -webkit-appearance: none; appearance: none; border-radius: var(--radius-pill); padding-left: 34px;
  background: var(--search-fill) var(--search-icon) no-repeat 12px center / 16px 16px; border-color: transparent; box-shadow: none;
}
input[type=search]:focus { border-color: var(--accent); box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent) 18%, transparent); }
input[type=search]::placeholder { color: var(--search-glyph); }
input[type=search]::-webkit-search-decoration { -webkit-appearance: none; }
.note { margin: 0; font-size: var(--text-sm); }
.spacer { flex: 1; }
.link.danger { color: var(--error); }
/* The Assistant, after Apple Intelligence: the sparkle and its colours, a glow that turns around the card while
   it thinks, then a glass card with a thin rainbow edge and the answer typeset. Reduced motion keeps the colours
   still; reduced transparency makes the card solid. */
@property --ai-angle { syntax: "<angle>"; inherits: false; initial-value: 0deg; }
:root { --ai-colors: #ff9f0a, #ff375f, #bf5af2, #5e5ce6, #64d2ff, #ff9f0a; }
.explain { margin-top: var(--space-8); }
.sparkle { width: 16px; height: 16px; flex: none; display: block; }
.ai-button { display: inline-flex; align-items: center; gap: var(--space-6); padding: var(--space-6) var(--space-14) var(--space-6) 11px; }
.ai-button span {
  font-weight: var(--weight-semibold); background: linear-gradient(90deg, #ff9f0a, #ff375f 35%, #bf5af2 70%, #5e5ce6);
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.ai-card {
  position: relative; isolation: isolate; margin-top: var(--space-4); padding: 1.5px; border-radius: var(--radius);
  background: conic-gradient(from var(--ai-angle), var(--ai-colors));
  animation: materialize var(--normal) var(--ease-out);
}
/* The glow: the same colours, blurred, behind the card; it turns while the Assistant thinks and fades after. */
.ai-card::before {
  content: ""; position: absolute; inset: -4px; z-index: -1; border-radius: calc(var(--radius) + 4px);
  background: conic-gradient(from var(--ai-angle), var(--ai-colors)); filter: blur(14px);
  opacity: 0; transition: opacity 600ms var(--ease-out);
}
.ai-card.thinking, .ai-card.thinking::before { animation: ai-turn 3s linear infinite; }
.ai-card.thinking::before { opacity: 0.55; }
.ai-card.answered { background: conic-gradient(from 210deg, var(--ai-colors)); }
.ai-card.failed { background: linear-gradient(var(--line), var(--line)); }
@keyframes ai-turn { to { --ai-angle: 360deg; } }
.ai-inner {
  border-radius: calc(var(--radius) - 1.5px); padding: var(--space-14) var(--space-18) var(--space-12); background: var(--material-solid);
  background-image: linear-gradient(160deg, rgba(255, 159, 10, 0.06), rgba(191, 90, 242, 0.06) 60%, rgba(100, 210, 255, 0.05));
}
.ai-head { display: flex; align-items: center; gap: var(--space-8); margin-bottom: var(--space-8); font-size: var(--text-sm); color: var(--muted); }
.ai-label { font-weight: var(--weight-semibold); letter-spacing: 0.01em; }
.ai-close { padding: 0; width: 26px; height: 26px; display: grid; place-items: center; font-size: var(--text-lg); line-height: 1; border-radius: 50%; }
.ai-thinking {
  margin: var(--space-4) 0 var(--space-6); font-weight: var(--weight-medium); background: linear-gradient(90deg, var(--muted) 20%, var(--text) 50%, var(--muted) 80%);
  background-size: 250% 100%; -webkit-background-clip: text; background-clip: text; color: transparent; animation: ai-shimmer 1.8s linear infinite;
}
@keyframes ai-shimmer { from { background-position: 100% 0; } to { background-position: -150% 0; } }
.ai-body { font-size: var(--text-base); line-height: 1.55; animation: fade var(--normal) var(--ease-out); }
.ai-body.clamped { max-height: 15em; overflow: hidden; -webkit-mask-image: linear-gradient(#000 65%, transparent); mask-image: linear-gradient(#000 65%, transparent); }
.ai-more { padding: var(--space-6) 0 2px; font-weight: var(--weight-medium); }
.md > :first-child { margin-top: 0; }
.md h3 { font-size: var(--text-lg); letter-spacing: -0.01em; margin: var(--space-14) 0 var(--space-4); }
.md h4 { font-size: var(--text-base); margin: var(--space-12) 0 2px; color: var(--muted); font-weight: var(--weight-semibold); }
.md p { margin: var(--space-6) 0; }
.md ul, .md ol { margin: var(--space-6) 0; padding-left: 1.3em; }
.md li { margin: var(--space-4) 0; }
.md li::marker { color: var(--muted); }
.md strong { font-weight: var(--weight-semibold); }
.md code { font-family: var(--mono); font-size: 0.85em; padding: 1px var(--space-6); border-radius: var(--radius-xs); background: var(--material-thin); border: 1px solid var(--line); overflow-wrap: anywhere; }
.md pre { margin: var(--space-8) 0; padding: var(--space-10) var(--space-12); border-radius: var(--radius-md); background: var(--material-thin); border: 1px solid var(--line); overflow: auto; }
.md pre code { padding: 0; border: 0; background: none; }
.md a { color: var(--accent-ink); }
.md .md-table { margin: var(--space-8) 0; overflow-x: auto; border: 1px solid var(--line); border-radius: var(--radius-md); }
.md table { width: 100%; border-collapse: collapse; font-size: var(--text-md); font-variant-numeric: tabular-nums; }
.md th, .md td { padding: var(--space-6) var(--space-10); text-align: left; vertical-align: top; border-bottom: 1px solid var(--line); }
.md th { font-weight: var(--weight-semibold); background: var(--material-thin); white-space: nowrap; }
.md tbody tr:last-child td { border-bottom: 0; }
.md th + th, .md td + td { border-left: 1px solid var(--line); }
.md .align-center { text-align: center; }
.md .align-right { text-align: right; }
.md blockquote { margin: var(--space-8) 0; padding: 2px 0 2px var(--space-12); border-left: 3px solid var(--line); color: var(--muted); }
.md hr { margin: var(--space-12) 0; border: 0; border-top: 1px solid var(--line); }
.md del { color: var(--muted); }
.md li.task { list-style: none; margin-left: -1.3em; }
.md li.task input { margin: 0 var(--space-6) 0 0; vertical-align: -2px; accent-color: var(--accent); }
@media (prefers-reduced-motion: reduce) {
  .ai-card { animation-name: fade; }
  .ai-card.thinking, .ai-card.thinking::before, .ai-thinking, .ai-body { animation: none; }
  .ai-thinking { color: var(--muted); background: none; }
}
@media (prefers-reduced-transparency: reduce) { .ai-card::before { display: none; } .ai-inner { background-image: none; } }

/* A group of buttons in one pill (a segmented control); `.on` marks the chosen one. */
.group {
  display: inline-flex; gap: 2px; padding: 3px; border-radius: var(--radius-pill); flex: none;
  background: var(--control); border: 1px solid var(--edge); box-shadow: inset 0 1px 0 var(--edge-light), var(--shadow-control);
}
.group button { border: 0; background: none; box-shadow: none; padding: 5px 13px; white-space: nowrap; transition: background-color var(--fast) var(--ease-out), transform var(--fast) var(--ease-out); }
.group button:hover:not(:disabled):not(.on) { background: var(--material-thin); }
.group button.on { background: linear-gradient(180deg, var(--accent-fill-top), var(--accent-fill)); color: var(--accent-text); }
/* A segmented control whose choices carry a glyph before their name (a phone shows the glyph alone). */

/* The mini remote (remote.js): a round pad with OK in the middle, round keys and a volume rocker. Keys give
   way under the press at once and the one that sent flashes the accent; a TV that cannot take keys dims it. */
.mini-remote { display: grid; grid-template-columns: auto auto auto; align-items: center; justify-content: start; gap: var(--space-14); }
.mini-remote svg { display: block; width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.mini-remote button { touch-action: manipulation; transition: transform var(--fast) var(--ease-out), color var(--fast) var(--ease-out), background-color var(--fast) var(--ease-out); }
.mini-remote button:active:not(:disabled) { transform: scale(0.9); transition-duration: 60ms; }
.mini-remote button.sent { color: var(--accent-ink); }
.mini-remote.is-disabled .pad, .mini-remote.is-disabled .round-keys, .mini-remote.is-disabled .remote-side { opacity: 0.45; }
.pad {
  width: 124px; height: 124px; border-radius: 50%; display: grid; grid-template: repeat(3, 1fr) / repeat(3, 1fr);
  background: var(--control); border: 1px solid var(--edge); box-shadow: inset 0 1px 0 var(--edge-light), var(--shadow-control);
  transition: border-color var(--normal) var(--ease-out);
}
.pad:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.mini-remote.failed .pad { border-color: var(--error); }
.pad-key { border: 0; background: none; box-shadow: none; padding: 0; border-radius: var(--radius-md); display: grid; place-items: center; color: var(--muted); }
.pad-key:hover:not(:disabled) { color: var(--text); }
.pad-key.up { grid-area: 1 / 2; } .pad-key.left { grid-area: 2 / 1; } .pad-key.right { grid-area: 2 / 3; } .pad-key.down { grid-area: 3 / 2; }
.pad-ok {
  grid-area: 2 / 2; place-self: center; width: 48px; height: 48px; padding: 0; border-radius: 50%; display: grid; place-items: center;
  font-size: var(--text-sm); font-weight: var(--weight-semibold); letter-spacing: 0.02em; background: var(--material-solid); border: 1px solid var(--edge);
  box-shadow: 0 2px 6px rgba(25, 34, 56, 0.12), inset 0 1px 0 var(--edge-light);
}
.round-keys { display: grid; grid-template-columns: repeat(2, 42px); gap: var(--space-8); }
.round-key { width: 42px; height: 42px; padding: 0; border-radius: 50%; display: grid; place-items: center; }
.remote-side { display: flex; flex-direction: column; align-items: center; gap: var(--space-10); }
.rocker {
  display: flex; flex-direction: column; border-radius: var(--radius); overflow: hidden;
  background: var(--control); border: 1px solid var(--edge); box-shadow: inset 0 1px 0 var(--edge-light), var(--shadow-control);
}
.rocker-key { width: 42px; height: 44px; padding: 0; border: 0; border-radius: 0; background: none; box-shadow: none; display: grid; place-items: center; }
.rocker-key + .rocker-key { border-top: 1px solid var(--line); }
/* Only a remote with side buttons gets the row for them, so a card without any keeps no empty gap. */
.remote-extra { grid-column: 1 / -1; display: flex; gap: var(--space-10); flex-wrap: wrap; }
@media (prefers-reduced-motion: reduce) { .mini-remote button:active:not(:disabled) { transform: none; opacity: 0.7; } }
@media (max-width: 400px) { .pad { width: 112px; height: 112px; } .mini-remote { gap: var(--space-10); } }

/* Accessories: a card per accessory, its power in the header, readable rows below. */
.accessory-card { display: grid; gap: var(--space-10); align-content: start; }
.controls { display: grid; }
.control { display: flex; align-items: center; justify-content: space-between; gap: var(--space-12); min-height: 42px; padding: var(--space-4) 0; border-top: 1px solid var(--line); }
.controls > .control:first-child, .service-name + .control { border-top: 0; }
.control > span:first-child { color: var(--muted); flex: none; }
.control select, .control input[type=text] { width: auto; max-width: 62%; }
.control .range { flex: 1; justify-content: flex-end; min-width: 0; }
.control input[type=range] { flex: 1 1 auto; width: auto; min-width: 60px; max-width: 190px; }
/* A value wraps anywhere rather than widen its card: no text a device sends can push the page sideways. */
.control .value { min-width: 0; overflow-wrap: anywhere; }
.control .range .value { flex: none; min-width: 3.6em; text-align: right; }
.keys { display: flex; flex-wrap: wrap; gap: var(--space-6); justify-content: flex-end; }
.keys button { padding: 5px 11px; font-size: var(--text-sm); }
.more > summary { font-size: var(--text-sm); padding: var(--space-4) 0; }
.service-name { font-size: var(--text-xs); font-weight: var(--weight-semibold); letter-spacing: 0.04em; text-transform: uppercase; color: var(--muted); margin: var(--space-12) 0 2px; }
.card-remote { padding: var(--space-8) 0 2px; display: flex; justify-content: center; }
.card-foot { display: flex; align-items: center; justify-content: space-between; gap: var(--space-10); padding-top: var(--space-10); border-top: 1px solid var(--line); font-size: var(--text-sm); }
.card-foot .link { padding: 0; font-size: inherit; }
/* A card's facts as a line of glyphs and values (a plugin's accessories and bridge). */
.meta { display: flex; flex-wrap: wrap; gap: var(--space-6) var(--space-16); color: var(--muted); font-size: var(--text-sm); min-width: 0; }
.meta > span { display: inline-flex; align-items: center; gap: var(--space-6); min-width: 0; }
.meta svg { flex: none; width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
/* A card with a foot, or the catalog's Add: a column whose last row sits at the bottom, so the dividers and
   menus of cards side by side line up whatever each card holds. */
.server:has(> .card-foot), .accessory-card, .server.catalog { display: flex; flex-direction: column; }
.card > .card-foot, .server.catalog > .actions { margin-top: auto; }
.accessory-section + .accessory-section { margin-top: var(--space-8); }

/* Apple Home proportions: compact rows and taller tiles in the same column width. A medium tile spans two
   compact rows; large and extra large keep two columns and fit their controls into as many rows as they need. */
:root {
  --heat: #f2711c; --cool: #1f7fe8; --auto: #1f9d55; --track: rgba(120, 128, 142, 0.2);
  --tile-on: #ffffff; --tile-on-text: #15171c; --tile-on-muted: rgba(21, 23, 28, 0.6); --knob: #ffffff;
  --unit: 176px; --unit-gap: 10px; --tile-row: max(64px, calc(var(--unit) * 0.36));
}
@media (prefers-color-scheme: dark) {
  :root { --heat: #ff8d3a; --cool: #4aa3ff; --auto: #3ccf7a; --track: rgba(255, 255, 255, 0.12); --tile-on: rgba(255, 255, 255, 0.92); --knob: #f3f4f7; }
}
.accessory-walls { container-type: inline-size; }
/* --unit until widgets.js sets each wall's from its width (the columns that fit, widened to fill it). */
.wall { --tile-row: max(64px, calc(var(--unit) * 0.36)); --unit: min(176px, calc((100cqw - var(--unit-gap)) / 2)); display: grid; grid-template-columns: repeat(auto-fill, var(--unit)); grid-auto-rows: var(--tile-row);
  grid-auto-flow: row dense; gap: var(--unit-gap); }
.wall > .widget { width: auto; height: auto; }
/* A phone: two columns that fill the width. */
@container (max-width: 520px) { .wall { --unit: calc((100cqw - var(--unit-gap)) / 2); } }
/* The Accessories page's tools on a phone: the search on a line of its own. */
@media (max-width: 600px) {
  .page-head .tools:has(> .search) { flex-wrap: wrap; width: 100%; }
  .page-head .tools > .search { flex: 1 1 100%; width: 100%; }
}
.wall > .size-medium { grid-row: span 2; }
.wall > .size-large { grid-column: span 2; grid-row: span var(--card-rows, 3); }
.wall > .size-xlarge { grid-column: span 2; grid-row: span var(--card-rows, 5); }
/* A control a widget hides (Close while the door is closed) stays hidden whatever its display. */

.widget:not(.widget-full) { position: relative; margin: 0; padding: var(--space-12); min-width: 0; display: flex; flex-direction: column; gap: var(--space-8); overflow: hidden; border-radius: var(--radius); }
.widget.size-small { width: var(--unit); height: var(--tile-row); justify-content: space-between; gap: var(--space-6);
  transition: background-color var(--normal) var(--ease-out), color var(--normal) var(--ease-out), transform var(--fast) var(--ease-out); }
.widget.size-medium { width: var(--unit); height: calc(var(--tile-row) * 2 + var(--unit-gap)); }
.widget.size-large { width: calc(var(--unit) * 2 + var(--unit-gap)); height: calc(var(--tile-row) * var(--card-rows, 3) + var(--unit-gap) * (var(--card-rows, 3) - 1)); }
.widget.size-xlarge { width: calc(var(--unit) * 2 + var(--unit-gap)); height: calc(var(--tile-row) * var(--card-rows, 5) + var(--unit-gap) * (var(--card-rows, 5) - 1)); }
.widget .tile { transition: background var(--normal) var(--ease-out), box-shadow var(--normal) var(--ease-out), color var(--normal) var(--ease-out), transform 300ms var(--ease-out); }
.widget:not(.widget-full) .tile { width: 34px; height: 34px; border-radius: var(--radius-sm); }
.widget:not(.widget-full) .tile svg { width: 19px; height: 19px; }
.tile.tone-heat { background: linear-gradient(160deg, #ffb15c, #f2711c); }
.tile.tone-light { background: var(--light, linear-gradient(160deg, #ffd66b, #f0a01e)); color: #3a2600; box-shadow: 0 4px 14px color-mix(in srgb, var(--glow, #f0a01e) 45%, transparent), inset 0 1px 0 rgba(255, 255, 255, 0.4); }
/* Off: grey, whatever the tone (after the tones, which it overrides). */
.tile.is-off { background: linear-gradient(160deg, #b4bbc7, #8b94a4); color: #fff; box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.35); }

.w-head { display: flex; align-items: center; gap: var(--space-10); min-width: 0; }
.w-head .who, .w-bottom .who { flex: 1; min-width: 0; display: grid; }
.widget:not(.widget-full) .who strong { font-size: var(--text-md); line-height: 1.25; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.widget.size-medium:not(.widget-full) .who strong { white-space: normal; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
/* Compact: icon and name in one row; tall: icon above the name, as in Apple Home. */
.widget.widget-summary { border-radius: var(--radius); }
.widget.size-small { flex-direction: row; align-items: center; padding: var(--space-10); gap: var(--space-10); }
.size-small .w-top { flex: none; }
.size-small .w-bottom { flex: 1; align-items: center; min-width: 0; }
.size-small .w-hero { display: none; }
.widget.size-small .tile { width: 40px; height: 40px; border-radius: 50%; }
.widget.size-medium { justify-content: space-between; }
.widget.size-medium .tile { width: 40px; height: 40px; border-radius: 50%; }
/* The ⋯ button sits over the compact tile's corner: the name and status end before it. */
.size-small .w-bottom .who { padding-right: 22px; }
.size-small .w-bottom .menu-button { position: absolute; right: -6px; bottom: -6px; width: 26px; height: 26px; margin: 0; opacity: 1; color: var(--text); background: rgba(255, 255, 255, 0.92); border: 1px solid var(--line); box-shadow: 0 1px 3px rgba(0, 0, 0, 0.18); }
/* Another controller's accessory (Apple Home's, through Wingman): a house badge on the tile's corner, ringed with the
   card's material so it reads as sitting on the tile. */
.widget .tile { position: relative; }
.widget .mirror-mark {
  position: absolute; right: -5px; bottom: -5px; width: 17px; height: 17px; border-radius: 50%; display: grid; place-items: center;
  background: var(--material-solid); color: var(--muted); box-shadow: 0 0 0 1.5px var(--material-solid), var(--shadow-control);
}
.widget .mirror-mark svg { width: 10px; height: 10px; stroke-width: 2.6; }
.widget .status { font-size: var(--text-sm); color: var(--muted); transition: color var(--normal) var(--ease-out); }
.widget:not(.widget-full) .status { font-size: var(--text-xs); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.status[data-tone="heat"] { color: var(--heat); } .status[data-tone="cool"] { color: var(--cool); } .status[data-tone="auto"], .status[data-tone="ok"] { color: var(--ok); }
.status[data-tone="warn"] { color: var(--warn); } .status[data-tone="bad"] { color: var(--error); }
.w-body { flex: 1; min-height: 0; display: flex; flex-direction: column; justify-content: center; gap: var(--space-10); }
/* Each part keeps its height; a large body that holds more scrolls rather than squeezing them. */
.w-body > * { flex-shrink: 0; }
.widget:not(.widget-full) .seg > button { white-space: nowrap; padding-inline: 2px; }
.size-large .w-body { padding-right: 26px; overflow: hidden; justify-content: safe center; }
/* A large light's swatches on one line, as large as the line allows for the eight colours and the sun. */
.size-large .swatches { gap: 5px; flex-wrap: nowrap; }
.widget.size-large .swatch { width: min(28px, calc((100% - 40px) / 9)); height: auto; aspect-ratio: 1; }
.size-xlarge .w-body { justify-content: safe center; gap: var(--space-8); overflow-y: auto; scrollbar-width: none; }
.size-xlarge .w-body > :last-child { margin-right: 26px; }
/* A large box's chips on one line, swiped sideways when there are more than fit. */
.widget.size-xlarge .chips { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; padding: 2px; margin: -2px; }
.widget.size-xlarge .chips > * { flex: none; }
.head-only { justify-content: center; }
.powered-off .w-body, .powered-off .w-main { opacity: 0.55; transition: opacity var(--normal) var(--ease-out); }
/* The menu at the bottom right of the box, over its content's corner. */
.w-corner { position: absolute; right: 6px; bottom: 6px; z-index: 2; }
/* An ellipsis in a circle, as iOS's ⋯ buttons: a chip tinted from the text, so it reads on a light, dark or lit tile
   alike, firmer under the pointer and while its menu is open. */
.widget:not(.widget-full) .menu-button { width: 28px; height: 28px; background: color-mix(in srgb, currentColor 10%, transparent); border-color: transparent; box-shadow: none; color: inherit;
  transition: background-color var(--fast) var(--ease-out), transform var(--fast) var(--ease-out); }
.widget:not(.widget-full) .menu-button:hover { background: color-mix(in srgb, currentColor 17%, transparent); }
.widget:not(.widget-full) .menu-button[aria-expanded="true"] { background: color-mix(in srgb, currentColor 22%, transparent); }
.widget:not(.widget-full) .menu-button svg { width: 18px; height: 18px; }
@media (prefers-contrast: more) { .widget:not(.widget-full) .menu-button { border: 1px solid currentColor; } }
/* A phone holds every button to 40px tall (the phone rules below); a widget's own controls keep their shapes,
   a swatch round, a step a bar, the corner's glyph 28px, its hit area grown under a finger instead. */
.widget .swatch, .widget .steps > button, .widget .seg > button, .widget .round, .widget .w-hit, .widget:not(.widget-full) .menu-button, .edit-bar button { min-height: 0; }
.widget .swatch { flex: none; }
.widget button { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
@media (pointer: coarse) {
  .widget:not(.widget-full) .menu-button { position: relative; }
  .widget:not(.widget-full) .menu-button::after { content: ""; position: absolute; inset: -8px; }
  .edit-bar button { min-width: 36px; height: 36px; }
}

/* Summary tiles: a tap anywhere acts (or a hold confirms); the whole tile lights up when on, as the Home app's do. */
.widget-summary.on { background-color: var(--tile-on); background-image: none; color: var(--tile-on-text); }
.widget-summary.on .status, .widget-summary.on .w-hero small { color: var(--tile-on-muted); }
.widget-summary:has(> .w-hit:active) { transform: scale(0.97); }
.w-hit { position: absolute; inset: 0; z-index: 0; width: 100%; height: 100%; padding: 0; border: 0; border-radius: inherit; background: none; box-shadow: none; }
.widget .w-hit:hover, .widget .w-hit:active:not(:disabled) { transform: none; }
.w-hit:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.w-top, .w-bottom { position: relative; z-index: 1; display: flex; gap: var(--space-8); min-width: 0; pointer-events: none; }
/* A tall tile's middle line (a remote's keys), above the tap target like the others and shown only by it. */
.w-middle { position: relative; z-index: 1; flex: none; min-width: 0; padding: 2px 0; overflow: hidden; pointer-events: none; }
.w-top { align-items: flex-start; justify-content: space-between; }
.w-bottom { align-items: flex-end; }
.w-bottom .menu-button { pointer-events: auto; margin: 0 -6px -6px 0; flex: none; }
.w-hero { font-size: var(--text-3xl); font-weight: var(--weight-semibold); letter-spacing: -0.02em; line-height: 1; text-align: right; font-variant-numeric: tabular-nums; }
.w-hero small { display: block; margin-top: 3px; font-size: var(--text-2xs); font-weight: var(--weight-medium); letter-spacing: 0; color: var(--muted); }
.w-hero svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.w-hero-word { font-size: var(--text-base); }
/* A shutter's tile: its closed part drawn from the top. */
.w-shade { position: absolute; inset: 0 0 auto 0; z-index: 0; height: var(--closed, 0%); pointer-events: none;
  background: repeating-linear-gradient(180deg, rgba(120, 128, 142, 0.16) 0 7px, rgba(120, 128, 142, 0.26) 7px 8px); transition: height 300ms var(--ease-out); }
/* Held to confirm: a fill crosses the tile; let go early and it goes back. */
.w-veil { position: absolute; inset: 0; z-index: 0; pointer-events: none; background: color-mix(in srgb, var(--warn) 30%, transparent); clip-path: inset(0 100% 0 0); transition: clip-path 200ms var(--ease-out); }
.holding > .w-veil { clip-path: inset(0 0 0 0); transition: clip-path 900ms linear; }
/* A shutter's tile slid: the shade follows the pointer one to one; held on a phone, it lifts a little first. */
.widget-summary.sliding > .w-shade { transition: none; }
.widget-summary.slide-ready, .widget-summary.sliding { transform: scale(1.02); box-shadow: var(--shadow-thick); }
.widget-cover.widget-summary > .w-hit { cursor: ns-resize; user-select: none; -webkit-user-select: none; }

/* A paused plugin's accessory: quiet and striped, its controls out of reach; the menu stays to resume it. */
.widget.paused { background-image: repeating-linear-gradient(135deg, transparent 0 10px, color-mix(in srgb, var(--muted) 9%, transparent) 10px 20px); }
.widget.paused > :not(.w-corner):not(.w-bottom):not(.w-head), .widget.paused .w-bottom .who, .widget.paused .w-head > .tile, .widget.paused .w-head > .switch { opacity: 0.45; filter: grayscale(1); }
.widget.paused.widget-summary.on { background-color: var(--material); color: var(--text); }
.widget.paused .w-hit { cursor: default; }

/* Medium and large bodies */
.w-row { display: flex; align-items: center; justify-content: space-between; gap: var(--space-10); min-width: 0; min-height: 32px; }
.w-row .steps { flex: 0 1 200px; }
.w-row select { width: auto; min-width: 0; max-width: 62%; }
.w-label { color: var(--muted); font-size: var(--text-sm); }
.w-grow { flex: 1; min-width: 0; }
.w-keys { display: flex; align-items: center; gap: var(--space-6); }
.w-actions { display: grid; min-width: 130px; }
.w-figure { display: grid; line-height: 1.1; }
.w-big { font-size: 2.125rem; font-weight: var(--weight-semibold); letter-spacing: -0.03em; font-variant-numeric: tabular-nums; }
.w-figure span { font-size: var(--text-xs); color: var(--muted); }
.w-state { font-size: 1.625rem; font-weight: var(--weight-bold); letter-spacing: -0.02em; line-height: 1.1; }
.w-line { font-size: var(--text-xs); color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.big-state { display: flex; align-items: center; gap: var(--space-10); flex-wrap: wrap; }
.big-state b { font-size: 1.625rem; letter-spacing: -0.02em; line-height: 1.1; }
.widget .w-button { width: 100%; border-radius: var(--radius-md); padding: 9px var(--space-14); font-weight: var(--weight-semibold); }
.light-large, .cover-large { flex: 1; min-height: 0; display: flex; gap: var(--space-16); align-items: stretch; }
/* A useful drag distance without stretching simple controls to an otherwise empty XL card. */
.size-xlarge .light-large, .size-xlarge .cover-large { min-height: 144px; }
.widget.widget-measuring { position: absolute; visibility: hidden; pointer-events: none; }
.widget-measuring .w-body { flex: none; overflow: visible; }
.light-large > .level.vertical { width: 96px; flex: none; }
.light-tall { display: flex; flex-direction: column; gap: var(--space-8); flex: none; width: 96px; }
.light-tall > .level { flex: 1; }
.light-tall > .adaptive-chip { justify-content: center; }
.light-colours { flex: 1; display: grid; align-content: center; gap: var(--space-12); min-width: 0; }
.cover-large > .level.vertical { width: 112px; flex: none; border-radius: var(--radius-md); }
.cover-buttons { display: grid; align-content: center; gap: var(--space-10); flex: 1; min-width: 0; }
.cover-buttons .level { width: 100%; }
.toggles { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-8); }
.widget .mini-toggle { display: grid; gap: 1px; text-align: left; border-radius: var(--radius-md); padding: 9px 11px; background: var(--material-thin); transition: background-color var(--normal) var(--ease-out); }
.mini-toggle b { font-size: var(--text-sm); font-weight: var(--weight-semibold); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mini-toggle span { font-size: var(--text-2xs); color: var(--muted); }
.widget .mini-toggle[aria-pressed="true"] { background: var(--tile-on); color: var(--tile-on-text); }
.mini-toggle[aria-pressed="true"] span { color: var(--tile-on-muted); }
.widget .power-button { align-self: center; width: 112px; height: 112px; flex: none; padding: 0; border-radius: 50%; display: grid; place-items: center; }
.power-button svg { width: 40px; height: 40px; fill: none; stroke: currentColor; stroke-width: 2.4; stroke-linecap: round; }
.widget .power-button[aria-pressed="true"] { background: linear-gradient(180deg, var(--accent-fill-top), var(--accent-fill)); color: var(--accent-text); border-color: transparent; }
.switch.big { width: 60px; height: 34px; }
.switch.big span { border-radius: var(--radius-pill); }
.switch.big span::before { width: 28px; height: 28px; }
.switch.big input:checked + span::before { transform: translateX(26px); }

/* A camera on the wall: its picture fills the box. */
.widget.camera-tile { padding: 0; }
.camera-tile .camera-view { position: absolute; inset: 0; margin: 0; aspect-ratio: auto; border-radius: inherit; }
.camera-tile .camera-controls { padding-right: 46px; }
.camera-tile .w-corner .menu-button { color: #fff; background: rgba(20, 22, 30, 0.45); }
.camera-tile.size-small .camera-controls, .camera-tile.size-small .camera-badge:not(.motion):not(.ring) { display: none; }
.camera-tile .w-hit { z-index: 1; }

/* The sheet: every control of one accessory, over the dimmed page. */
.widget-sheet { width: min(600px, calc(100vw - 24px)); max-height: calc(100dvh - 32px); padding: 0; border: 0; background: none; color: inherit; overflow: visible; }
.widget-sheet::backdrop { background: rgba(15, 18, 24, 0.35); -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px); }
.widget-sheet[open] { animation: materialize var(--normal) var(--ease-out); }
.sheet-bar { display: flex; justify-content: flex-end; padding: 0 var(--space-6) var(--space-8); }
/* Done on a glass pill: white words alone were lost over a light page behind the blur. */
.sheet-bar .link {
  padding: var(--space-6) var(--space-16); border-radius: var(--radius-pill); color: var(--accent-ink); font-weight: var(--weight-semibold);
  background-color: var(--material-thick); -webkit-backdrop-filter: blur(var(--blur)) saturate(180%); backdrop-filter: blur(var(--blur)) saturate(180%);
  border: 1px solid var(--edge); box-shadow: var(--shadow-control), inset 0 1px 0 var(--edge-light);
}
.widget-sheet .widget-full { margin: 0; max-height: calc(100dvh - 90px); overflow-y: auto; overscroll-behavior: contain; box-shadow: 0 30px 80px rgba(0, 0, 0, 0.35); }
/* On a phone, a sheet rising from the bottom edge, within the thumb's reach, its last control above the home
   indicator. */
@media (max-width: 640px) {
  .widget-sheet { width: 100%; max-width: none; margin: auto 0 0; max-height: calc(100dvh - max(12px, env(safe-area-inset-top))); }
  .widget-sheet[open] { animation: sheet-up 340ms cubic-bezier(0.32, 0.72, 0, 1); }
  .widget-sheet .widget-full { max-height: calc(100dvh - max(12px, env(safe-area-inset-top)) - 44px); border-radius: var(--radius-xl) var(--radius-xl) 0 0; border-bottom: 0; padding-bottom: calc(var(--space-16) + env(safe-area-inset-bottom)); }
  .sheet-bar { padding: 0 var(--space-14) var(--space-8); }
  /* Its grabber over the card's top edge, and the name row that drags with it. */
  .widget-sheet .widget-full { position: relative; padding-top: 22px; }
  .widget-sheet .widget-full > .w-head { touch-action: none; }
}
@keyframes sheet-up { from { transform: translateY(100%); } }
.w-main, .w-side { display: grid; gap: var(--space-14); align-content: start; min-width: 0; }
.w-split { display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); gap: var(--space-20); align-items: start; }
@media (max-width: 640px) { .w-split { grid-template-columns: minmax(0, 1fr); } }
.w-block { display: grid; gap: var(--space-10); padding-top: var(--space-12); border-top: 1px solid var(--line); }
.w-main > .w-block:first-child, .w-side > .w-block:first-child { border-top: 0; padding-top: 0; }
.w-block-body { display: grid; gap: var(--space-10); }

/* Edit: each widget shows its sizes and arrows; the widget itself rests, and drags into place. */
.wall.editing > .widget { cursor: grab; }
.wall.editing > .widget > :not(.edit-bar):not(.resize-handle) { pointer-events: none; }
.wall.editing > .widget::after { content: ""; position: absolute; inset: 0; z-index: 2; border-radius: inherit; background: color-mix(in srgb, var(--bg) 40%, transparent); pointer-events: none; }
.edit-bar { position: absolute; z-index: 3; left: 50%; top: 50%; transform: translate(-50%, -50%); display: flex; gap: 0; padding: var(--space-4); border-radius: var(--radius-pill); max-width: calc(100% - 8px); width: max-content;
  background: var(--material-thick); border: 1px solid var(--edge); box-shadow: var(--shadow-thick); }
.edit-bar button { min-width: 0; width: 26px; flex: 1 1 26px; height: 28px; padding: 0 2px; border: 0; background: none; box-shadow: none; border-radius: var(--radius-pill); font-size: var(--text-xs); font-weight: var(--weight-semibold); color: var(--muted); }
.edit-bar button:hover { color: var(--text); }
.edit-bar button[aria-pressed="true"] { background: linear-gradient(180deg, var(--accent-fill-top), var(--accent-fill)); color: var(--accent-text); }
/* Dragged: the widget lifts over the page and follows the pointer; a dashed slot shows where it will land. In
   Edit, a finger on a widget drags it rather than scrolling the page. */
.wall.editing { user-select: none; -webkit-user-select: none; -webkit-touch-callout: none; }
.wall.editing > .widget { touch-action: none; }
.widget.lifted { position: fixed; z-index: var(--layer-drag); margin: 0; pointer-events: none; cursor: grabbing; box-shadow: 0 24px 60px rgba(15, 18, 24, 0.3); }
.widget.lifted::after { display: none; }
.wall > .drag-slot::after { display: none; }
.wall > .drag-slot { border: 2px dashed color-mix(in srgb, var(--accent) 55%, transparent); border-radius: var(--radius); background: color-mix(in srgb, var(--accent) 6%, transparent); box-shadow: none; }

/* Segmented: equal columns, a thumb sliding to the one chosen. */
.seg { position: relative; display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; padding: 3px; border-radius: var(--radius-md); background: var(--track); }
.seg-thumb { position: absolute; top: 3px; bottom: 3px; left: 3px; width: calc((100% - 6px) / var(--n)); border-radius: calc(var(--radius-md) - 3px); background: var(--control);
  box-shadow: var(--shadow-control), inset 0 1px 0 var(--edge-light); transform: translateX(calc(var(--i, 0) * 100%)); transition: transform 220ms var(--ease-out); }
.seg.unset .seg-thumb { opacity: 0; }
.widget .seg > button { position: relative; z-index: 1; border: 0; background: none; box-shadow: none; color: var(--muted); font-size: var(--text-sm); padding: 7px var(--space-6); border-radius: calc(var(--radius-md) - 3px); transform: none; transition: color var(--normal) var(--ease-out); }
.widget .seg > button[aria-checked="true"] { color: var(--text); font-weight: var(--weight-semibold); }
.widget .seg > button:focus-visible { outline-offset: -2px; }

/* Level: a pill the fill grows in, dragged one to one; a track variant (white temperature) has a mark. */
.level { position: relative; height: 44px; border-radius: var(--radius-md); background: var(--track); overflow: hidden; touch-action: none; cursor: ew-resize; user-select: none; -webkit-user-select: none; }
.level-fill { position: absolute; inset: 0; transform-origin: left center; background: var(--fill, linear-gradient(90deg, var(--accent-2), var(--accent))); }
.level:not(.dragging) .level-fill { transition: transform var(--normal) var(--ease-out); }
.level-label, .level-text { position: absolute; top: 0; bottom: 0; display: flex; align-items: center; font-size: var(--text-sm); font-weight: var(--weight-semibold); pointer-events: none; }
.level-label { left: 14px; }
.level-text { right: 14px; font-variant-numeric: tabular-nums; }
.level.track { background: var(--track); }
.level.track .level-label, .level.track .level-text { color: #2a2620; }
.level-mark { position: absolute; top: 6px; bottom: 6px; width: 6px; margin-left: -3px; border-radius: 3px; background: var(--knob); box-shadow: 0 1px 4px rgba(0, 0, 0, 0.35); }
/* Several values (a group's members): solid to the lowest, the same colour lighter to the highest; on a gradient
   track, a frosted band between them in place of the knob. */
.level-range { position: absolute; top: 0; bottom: 0; display: none; background: var(--fill, linear-gradient(90deg, var(--accent-2), var(--accent))); opacity: .4; }
.level.ranged .level-range { display: block; }
.level.track .level-range { top: 6px; bottom: 6px; border-radius: 4px; opacity: 1; background: rgba(255, 255, 255, 0.5); box-shadow: inset 0 0 0 2px var(--knob), 0 1px 4px rgba(0, 0, 0, 0.25); }
.level.track.ranged .level-mark { display: none; }
/* Tall: filled from the bottom, the value at the top, the label at the foot. */
.level.vertical { height: auto; border-radius: var(--radius); cursor: ns-resize; }
.level.vertical .level-fill { transform-origin: center bottom; }
.level.vertical .level-label, .level.vertical .level-text { left: 0; right: 0; justify-content: center; }
.level.vertical .level-label { top: auto; bottom: 12px; }
.level.vertical .level-text { top: 12px; bottom: auto; font-size: var(--text-base); }
.level.vertical .level-mark { top: auto; bottom: auto; left: 10px; right: 10px; width: auto; height: 6px; margin: -3px 0 0; }
.level:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.level.thin { height: 28px; border-radius: var(--radius-sm); }
.level.thin .level-text { right: 10px; font-size: var(--text-xs); }

/* Steps: a few positions as rising bars. */
.steps { display: flex; align-items: flex-end; gap: var(--space-6); height: 32px; }
.widget .steps > button { flex: 1; padding: 0; border: 0; border-radius: var(--radius-xs); background: var(--track); box-shadow: none; transform: none; transition: background-color var(--fast) var(--ease-out); }
.widget .steps > button.lit { background: var(--steps, var(--accent)); }

/* Setpoint and gauge */
.setpoints { display: grid; gap: var(--space-14); justify-items: center; align-content: center; }
.row-setpoints { justify-items: start; }
.setpoint { display: grid; grid-template-columns: 36px auto 36px; align-items: center; gap: var(--space-8); justify-items: center; }
.sp-value { display: grid; justify-items: center; line-height: 1.15; min-width: 4.4em; }
.sp-value b { font-size: var(--text-3xl); font-variant-numeric: tabular-nums; letter-spacing: -0.01em; }
.sp-value span { font-size: var(--text-xs); color: var(--muted); }
.widget .round { width: 36px; height: 36px; padding: 0; border-radius: 50%; display: grid; place-items: center; }
.widget .round svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 2.4; stroke-linecap: round; }
.climate-hero { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: var(--space-12); }
@container widgets (max-width: 400px) { .climate-hero { grid-template-columns: minmax(0, 1fr); } }
.gauge { width: 100%; max-width: 230px; height: auto; display: block; margin: 0 auto; overflow: visible; }
.gauge-track, .gauge-band { fill: none; stroke-width: 12; stroke-linecap: round; }
.gauge-track { stroke: var(--track); }
.gauge-band { transition: stroke var(--normal) var(--ease-out); }
.gauge-value { fill: var(--text); font: 600 40px var(--font); letter-spacing: -0.03em; font-variant-numeric: tabular-nums; }
.gauge-caption, .gauge-end { fill: var(--muted); font: 500 12px var(--font); }
.gauge-dot { fill: var(--knob); stroke: var(--text); stroke-width: 2; }
.gauge-target { stroke: var(--text); stroke-width: 3; stroke-linecap: round; }

/* Facets: readouts, meters, chips, swatches, pills */
.readouts { display: grid; grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); gap: var(--space-8); }
.readouts.three { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.readouts.four { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.widget:not(.widget-full) .readouts { gap: var(--space-6); }
.widget:not(.widget-full) .readout { padding: 7px 9px; border-radius: var(--radius-md); }
.widget:not(.widget-full) .readout-value { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.widget:not(.widget-full) .readout-value b { font-size: var(--text-lg); }
.readouts.four .readout-value b { font-size: var(--text-md); }
.readouts.four .readout { padding: var(--space-6) 7px; }
.widget:not(.widget-full) .readout-label { font-size: var(--text-2xs); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.readout { padding: var(--space-10) var(--space-12); border-radius: var(--radius-md); background: var(--material-thin); border: 1px solid var(--edge); display: grid; gap: 2px; min-width: 0; }
.readout-value b { font-size: 1.125rem; font-variant-numeric: tabular-nums; letter-spacing: -0.01em; overflow-wrap: anywhere; }
.readout-value small { font-size: var(--text-xs); font-weight: var(--weight-medium); color: var(--muted); margin-left: 3px; }
.readout-label { font-size: var(--text-xs); color: var(--muted); overflow-wrap: anywhere; }
.readout[data-tone="warn"] b { color: var(--warn); } .readout[data-tone="ok"] b { color: var(--ok); } .readout[data-tone="muted"] b { color: var(--muted); }
.readout-extra { display: flex; gap: 3px; }
.readout-extra:empty { display: none; }
.readout-extra i { flex: 1; height: 4px; border-radius: 2px; background: var(--track); }
.readout-extra i.lit { background: var(--ok); }
.meter { display: grid; gap: var(--space-6); font-size: var(--text-sm); }
.meter-row { display: flex; justify-content: space-between; color: var(--muted); }
.meter-row b { color: var(--text); font-variant-numeric: tabular-nums; }
.meter-bar { height: 6px; border-radius: 3px; background: var(--track); overflow: hidden; }
.meter-bar i { display: block; height: 100%; transform-origin: left; background: var(--ok); border-radius: 3px; }
.meter.low .meter-bar i { background: var(--warn); }
.chips { display: flex; flex-wrap: wrap; gap: var(--space-6); }
.chips:empty { display: none; }
.widget .chip { font-size: var(--text-sm); padding: var(--space-6) var(--space-12); transition: background-color var(--normal) var(--ease-out), color var(--normal) var(--ease-out), transform var(--fast) var(--ease-out); }
.widget .chip[aria-pressed="true"] { background: var(--accent-fill); border-color: transparent; color: var(--accent-text); }
.swatches { display: flex; flex-wrap: wrap; gap: var(--space-8); }
.swatches.grid { display: grid; grid-template-columns: repeat(4, 30px); gap: var(--space-10); }
/* Adaptive Lighting: the day's whites, a sun on them; dimmed until the Home app has sent a schedule to resume. */
.widget .swatch.adaptive { display: grid; place-items: center; color: #5c3b00; background: linear-gradient(135deg, #ffb24d, #fff1d6 55%, #cfe3ff); }
.widget .swatch.adaptive svg, .widget .round.adaptive svg, .adaptive-chip svg { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; }
.size-large .swatch.adaptive svg { width: 13px; height: 13px; }
.widget .round.adaptive[aria-pressed="true"] { background: linear-gradient(135deg, #ffb24d, #fff1d6 55%, #cfe3ff); color: #5c3b00; border-color: transparent; }
.widget .adaptive-chip { display: inline-flex; align-items: center; gap: var(--space-6); }
.widget .adaptive.unset { opacity: 0.55; }
.widget .swatch { width: 30px; height: 30px; padding: 0; border-radius: 50%; background: var(--swatch); border: 2px solid var(--edge); }
.widget .swatch[aria-checked="true"] { outline: 2px solid var(--text); outline-offset: 1px; }
/* Room for that ring: a box that clips (a fixed widget's body) would cut it. */
.widget .swatches { padding: 3px; }
.pill { display: inline-flex; align-items: center; gap: var(--space-6); padding: 3px var(--space-10); border-radius: var(--radius-pill); font-size: var(--text-xs); font-weight: var(--weight-semibold); background: var(--material-thin); border: 1px solid var(--edge); }
.pill::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: var(--muted); }
.pill.ok::before { background: var(--ok); } .pill.warn::before { background: var(--warn); } .pill.bad::before { background: var(--error); }
.lock-row { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: var(--space-10); padding-top: var(--space-12); border-top: 1px solid var(--line); }
.w-main > .lock-row:first-child { border-top: 0; padding-top: 0; }
.lock-name { display: grid; gap: var(--space-4); justify-items: start; }
.lock-row .hold, .lock-row .w-button { width: auto; }

/* Hold to confirm: the fill runs while held and snaps back when let go early. */
.widget .hold { position: relative; overflow: hidden; width: 100%; border-radius: var(--radius-md); padding: var(--space-10) var(--space-16); font-weight: var(--weight-semibold); touch-action: none; user-select: none; -webkit-user-select: none; }
.hold-fill { position: absolute; inset: 0; display: grid; place-items: center; background: var(--warn); color: #fff; clip-path: inset(0 100% 0 0); transition: clip-path 200ms var(--ease-out); }
.hold.holding .hold-fill { clip-path: inset(0 0 0 0); transition: clip-path 900ms linear; }

/* Valve: a round run button whose ring empties as the time runs out. */
.valve { display: grid; justify-items: center; gap: var(--space-14); }
.valve .seg { width: 100%; }
.widget .valve-button { position: relative; width: 128px; height: 128px; padding: 0; border-radius: 50%; display: grid; place-items: center; }
.valve-button svg { position: absolute; inset: 0; width: 100%; height: 100%; transform: rotate(-90deg); }
.valve-button .ring-track, .valve-button .ring { fill: none; stroke-width: 6; }
.valve-button .ring-track { stroke: var(--track); }
.valve-button .ring { stroke: var(--cool); stroke-linecap: round; transition: stroke-dashoffset 1s linear; }
.valve-text { display: grid; justify-items: center; line-height: 1.2; }
.valve-text b { font-size: 1.125rem; }
.valve-text span { font-size: var(--text-xs); color: var(--muted); font-variant-numeric: tabular-nums; }

@media (prefers-reduced-motion: reduce) {
  .seg-thumb, .level-fill, .widget .tile, .widget.size-small, .w-shade, .valve-button .ring { transition-duration: 0ms !important; }
  .widget-summary:has(> .w-hit:active) { transform: none; }
  .widget-sheet[open] { animation-name: fade; }
}
@media (prefers-contrast: more) { .tile.is-off { background: #687284; } }

/* Plugins: a card per block; the settings form opens across the grid. */
.server .actions { display: flex; align-items: center; gap: var(--space-10); flex-wrap: wrap; }
.server.editor { grid-column: 1 / -1; gap: var(--space-18); }
.fields { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 280px), 1fr)); gap: var(--space-4) var(--space-18); align-items: start; }
.fields > fieldset, .fields > .group-box { grid-column: 1 / -1; }
.field { margin: var(--space-10) 0 var(--space-4); }
.field-title { display: block; font-weight: var(--weight-medium); margin-bottom: var(--space-6); }
.field > input, .field > select { margin-top: 0; }
.toggle { display: flex; align-items: flex-start; gap: var(--space-12); margin: var(--space-14) 0 var(--space-6); cursor: pointer; }
.toggle .field-title { margin: 3px 0 2px; }
.toggle.compact { align-items: center; margin: 0; gap: var(--space-8); white-space: nowrap; }
.group-box { border: 1px solid var(--line); border-radius: var(--radius-lg); padding: var(--space-4) var(--space-16) var(--space-12); margin: var(--space-12) 0; background: var(--material-thin); }
.group-box > summary { font-weight: var(--weight-semibold); color: var(--text); padding: var(--space-10) 0 var(--space-6); }
.item .item-head strong { font-weight: var(--weight-semibold); }
textarea.short { min-height: 220px; }
.save-bar { display: flex; align-items: center; gap: var(--space-12); flex-wrap: wrap; padding-top: var(--space-14); border-top: 1px solid var(--line); }
.save-bar > span:first-child { flex: 1; font-size: var(--text-sm); }
.status-line { margin: var(--space-12) 0 0; min-height: 1.2em; font-size: var(--text-md); }

/* Config and logs: a toolbar on top of the content, inside one card. */
.editor-card, .log-card { padding: 0; overflow: hidden; }
.editor-bar { display: flex; align-items: center; gap: var(--space-12); flex-wrap: wrap; padding: var(--space-12) var(--space-16); border-bottom: 1px solid var(--line); background: var(--material-thin); }
.editor-bar .search { width: 220px; }
.editor-bar .popup { max-width: 240px; }

/* A menu of actions (common.js menu()): thick material over the page, out of its button. */
.menu-button { flex: none; width: 32px; height: 32px; padding: 0; display: grid; place-items: center; border-radius: 50%; }
.menu-button svg { width: 18px; height: 18px; fill: currentColor; stroke: none; }
.menu-button[aria-expanded="true"] { background: var(--material-thin); }
.menu {
  position: fixed; z-index: var(--layer-menu); min-width: 210px; padding: var(--space-6); display: grid; gap: 1px; border-radius: calc(var(--radius-sm) + 6px);
  background-color: var(--material-thick); background-image: var(--sheen);
  -webkit-backdrop-filter: blur(var(--blur-thick)) saturate(180%); backdrop-filter: blur(var(--blur-thick)) saturate(180%);
  border: 1px solid var(--edge); box-shadow: 0 18px 44px rgba(25, 34, 56, 0.24), inset 0 1px 0 var(--edge-light);
  animation: menu-in 180ms var(--ease-out);
}
.menu { max-height: min(480px, calc(100dvh - 24px)); overflow-y: auto; overflow-x: hidden; overscroll-behavior: contain; grid-auto-rows: max-content; touch-action: pan-y; }
.menu:focus { outline: none; }
.menu.closing { animation: menu-out 140ms var(--ease-out) forwards; pointer-events: none; }
@keyframes menu-in { from { opacity: 0; transform: scale(0.92); } }
@keyframes menu-out { to { opacity: 0; transform: scale(0.95); } }
.menu [role="menuitem"], .menu [role="menuitemradio"], .menu [role="menuitemcheckbox"] {
  display: flex; align-items: center; gap: var(--space-10); width: 100%; padding: var(--space-8) var(--space-12); border: 0; border-radius: var(--radius-sm);
  background: none; box-shadow: none; color: var(--text); font: inherit; font-size: var(--text-md); text-align: left; text-decoration: none; cursor: pointer;
}
.menu [role="menuitem"]:hover, .menu [role="menuitem"]:focus-visible, .menu [role="menuitemradio"]:hover, .menu [role="menuitemradio"]:focus-visible, .menu [role="menuitemcheckbox"]:hover, .menu [role="menuitemcheckbox"]:focus-visible { background: var(--accent-fill); color: var(--accent-text); outline: none; transform: none; }
/* A choice among several (a widget's size): the chosen one ticked at the right. */
.menu-check { margin-left: auto; font-weight: var(--weight-bold); color: var(--accent-ink); }
.menu [role="menuitemradio"]:hover .menu-check, .menu [role="menuitemradio"]:focus-visible .menu-check { color: inherit; }
/* Choices without a glyph (Small, Medium) line up with the items that have one. */
.menu:has([role="menuitem"] svg) [role="menuitemradio"]:not(.menu-choice-badge):not(:has(svg))::before { content: ""; flex: none; width: 17px; }
/* Widget sizes: one segmented control across the menu, as the widgets' own (.seg), the current size on a raised
   thumb; its caption lines up with the items' labels. */
.menu-choices { display: grid; gap: var(--space-6); padding: var(--space-6) var(--space-6) var(--space-8); }
.menu-choice-label { padding: 0 var(--space-6); font-size: var(--text-xs); font-weight: var(--weight-semibold); color: var(--muted); }
.menu-choice-row { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: 2px; padding: 3px; border-radius: var(--radius-md); background: var(--track, var(--search-fill)); }
.menu .menu-choice-badge { display: grid; place-items: center; height: 32px; min-height: 0; padding: 0; border: 0; border-radius: calc(var(--radius-md) - 3px);
  background: none; box-shadow: none; color: var(--muted); font-weight: var(--weight-semibold); font-size: var(--text-md); text-align: center; cursor: pointer;
  transition: background-color var(--fast) var(--ease-out), color var(--fast) var(--ease-out), transform var(--fast) var(--ease-out); }
.menu .menu-choice-badge:hover { background: var(--material-thin); color: var(--text); }
.menu .menu-choice-badge:active { transform: scale(0.96); }
.menu .menu-choice-badge[aria-checked="true"] { background: var(--control); color: var(--text); box-shadow: var(--shadow-control); }
.menu .menu-choice-badge:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
@media (pointer: coarse) { .menu .menu-choice-badge { height: 40px; } }
@media (prefers-reduced-motion: reduce) { .menu .menu-choice-badge:active { transform: none; } }
@media (prefers-contrast: more) { .menu .menu-choice-badge[aria-checked="true"] { outline: 1px solid var(--text); } }
.menu-separator { border: 0; border-top: 1px solid var(--line); margin: var(--space-4) var(--space-8); }
.menu [role="menuitem"].danger { color: var(--error); }
.menu [role="menuitem"].danger:hover, .menu [role="menuitem"].danger:focus-visible { background: var(--error); color: #fff; }
.menu :is([role="menuitem"], [role="menuitemradio"], [role="menuitemcheckbox"]) svg { width: 17px; height: 17px; flex: none; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
/* A phone's action sheet: across the bottom over a dimmed page, rising on the drawer curve and leaving faster;
   scrolls when it is taller than the window. */
.menu-scrim { position: fixed; inset: 0; z-index: calc(var(--layer-menu) - 1); background: rgba(10, 14, 24, 0.28); animation: sheet-dim 200ms var(--ease-out); }
.menu-scrim.closing { animation: sheet-undim 180ms var(--ease-out) forwards; }
.menu.sheet-menu {
  left: 10px; right: 10px; bottom: max(10px, env(safe-area-inset-bottom)); max-height: calc(100dvh - 24px - env(safe-area-inset-top));
  overflow-y: auto; overscroll-behavior: contain; padding: var(--space-8); border-radius: var(--radius-xl); transform-origin: 50% 100%;
  animation: menu-sheet-in 280ms cubic-bezier(0.32, 0.72, 0, 1);
}
.menu.sheet-menu.closing { animation: menu-sheet-out 180ms var(--ease-out) forwards; }
.menu.sheet-menu { padding-top: 22px; }
@keyframes menu-sheet-in { from { transform: translateY(calc(100% + 12px)); } }
@keyframes menu-sheet-out { to { transform: translateY(calc(100% + 12px)); } }
@media (prefers-reduced-motion: reduce) { .menu, .menu.closing, .menu.sheet-menu, .menu.sheet-menu.closing { animation-name: fade; } }
@media (prefers-reduced-transparency: reduce) { .menu { background: var(--material-solid); -webkit-backdrop-filter: none; backdrop-filter: none; } }
/* A custom time range: from and to, under the toolbar, as the material arriving. */
.editor-bar .count { font-size: var(--text-sm); font-variant-numeric: tabular-nums; }
.editor-card textarea { display: block; border: 0; border-radius: 0; box-shadow: none; background: transparent; min-height: 62vh; padding: var(--space-16) var(--space-18); resize: vertical; tab-size: 2; line-height: 1.55; }
.editor-card textarea:focus { box-shadow: none; }
.editor-card .status-line { padding: var(--space-12) var(--space-18) var(--space-14); margin: 0; }
.editor-card .status-line:empty { display: none; }

/* Facts: label over value in thin chips, three to a row; long values end in an ellipsis with the whole
   value in the tooltip. */
.facts { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-8); }
.fact { padding: var(--space-8) var(--space-12); border-radius: var(--radius-md); background: var(--material-thin); border: 1px solid var(--line); min-width: 0; }
.fact span { display: block; font-size: var(--text-xs); color: var(--muted); letter-spacing: 0.01em; }
.fact b { display: block; font-weight: var(--weight-medium); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fact.wide { grid-column: 1 / -1; }
.facts.lead { grid-template-columns: minmax(0, 2fr) repeat(2, minmax(0, 1fr)); }
.mono { font-family: var(--mono); font-size: var(--text-sm); letter-spacing: 0; }
.chips { display: flex; flex-wrap: wrap; gap: var(--space-6); }
.chip { padding: 3px var(--space-10); border-radius: var(--radius-pill); font-size: var(--text-sm); background: var(--material-thin); border: 1px solid var(--line); }

/* Status: a summary that says whether all is well, the numbers that matter, then a card per server. */
/* A newer release, under the summary: how to upgrade this install, its command with Copy, the notes folded. */
.update-card { margin-top: var(--space-14); display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-12); }
.update-card > p { margin: 0; }
.update-card .actions { margin-top: 0; flex-wrap: wrap; }
.update-command { display: flex; align-items: center; gap: var(--space-8); padding: 5px 5px 5px var(--space-14); border-radius: var(--radius-md); background: var(--material-thin); border: 1px solid var(--line); }
.update-command code { flex: 1; min-width: 0; overflow-x: auto; white-space: nowrap; font: 0.8125rem/1.5 var(--mono); scrollbar-width: none; }
.update-command button { flex: none; padding: 5px var(--space-12); font-size: var(--text-sm); }
.update-card details.more-options { margin: 0; }
.who { flex: 1; min-width: 0; }
.health { font-weight: var(--weight-medium); display: flex; align-items: flex-start; gap: var(--space-8); }
/* The dot on the first line's middle, when the text wraps. */
.health::before { content: ""; width: 8px; height: 8px; margin-top: calc(0.725em - var(--space-4)); border-radius: 50%; background: currentColor; flex: none; }
.health.on { color: var(--ok); }
.health.away { color: var(--warn); }
.stats { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--space-12); margin: 0 0 var(--space-14); }
.stat {
  padding: var(--space-14) var(--space-16); border-radius: var(--radius-lg); background: var(--material); border: 1px solid var(--edge);
  box-shadow: var(--shadow-control), inset 0 1px 0 var(--edge-light);
}
.stat { position: relative; display: block; color: inherit; text-decoration: none; }
a.stat { touch-action: manipulation; transition: transform var(--fast) var(--ease-out); }
a.stat:active { transform: scale(0.97); transition-duration: 80ms; }
.stat > svg { position: absolute; top: 14px; right: 14px; width: 20px; height: 20px; fill: none; stroke: var(--muted); stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; opacity: 0.7; }
.stat b { display: block; font-size: 1.5rem; line-height: 1.1; letter-spacing: -0.02em; font-weight: var(--weight-figure); font-variant-numeric: tabular-nums; }
.stat span { color: var(--muted); font-size: var(--text-sm); letter-spacing: 0.01em; }
.stat .short { display: none; }
/* The Status page's activity charts: the filters in one row above them, two charts a row, one on a phone. */
.activity { transition: opacity var(--normal) var(--ease-out); }
.activity.loading .chart-grid { opacity: 0.55; }
.filter-bar { display: flex; align-items: center; gap: var(--space-10); flex-wrap: wrap; margin: 0 0 var(--space-12); }
.filter-bar .popup { max-width: 260px; }
.chart-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 420px), 1fr)); gap: var(--space-14); transition: opacity var(--normal) var(--ease-out); }
/* A Status section's time range (app.js's rangeControl): the segmented control, scrolling sideways when its choices
   outgrow a phone, and Custom…'s pop-over in the menus' material, growing from the segment. A day range is one band,
   rounded at its first and last day; today is ringed; days without history are dimmed. */
.range-control { max-width: 100%; overflow-x: auto; scrollbar-width: none; }
.range-control::-webkit-scrollbar { display: none; }
.range-control.more-after { -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 32px), transparent); mask-image: linear-gradient(90deg, #000 calc(100% - 32px), transparent); }
.range-control.more-before { -webkit-mask-image: linear-gradient(90deg, transparent, #000 32px); mask-image: linear-gradient(90deg, transparent, #000 32px); }
.range-control.more-before.more-after { -webkit-mask-image: linear-gradient(90deg, transparent, #000 32px, #000 calc(100% - 32px), transparent); mask-image: linear-gradient(90deg, transparent, #000 32px, #000 calc(100% - 32px), transparent); }
.range-control .range-custom { font-variant-numeric: tabular-nums; }
.range-popover {
  position: fixed; z-index: var(--layer-menu); width: min(320px, calc(100vw - 16px)); padding: var(--space-14); display: grid; gap: var(--space-12); border-radius: var(--radius);
  background-color: var(--material-thick); background-image: var(--sheen);
  -webkit-backdrop-filter: blur(var(--blur-thick)) saturate(180%); backdrop-filter: blur(var(--blur-thick)) saturate(180%);
  border: 1px solid var(--edge); box-shadow: 0 18px 44px rgba(25, 34, 56, 0.24), inset 0 1px 0 var(--edge-light);
  animation: menu-in 180ms var(--ease-out);
}
.range-popover.closing { animation: menu-out 140ms var(--ease-out) forwards; pointer-events: none; }
.range-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-8); }
.range-month { font-size: var(--text-base); text-transform: capitalize; }
.range-head .menu-button svg { fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.range-days { display: grid; grid-template-columns: repeat(7, 1fr); row-gap: 2px; }
.range-weekday { text-align: center; font-size: var(--text-2xs); font-weight: var(--weight-semibold); color: var(--muted); padding-bottom: var(--space-4); text-transform: uppercase; }
.range-day {
  height: 36px; padding: 0; border: 0; border-radius: 0; background: none; box-shadow: none; color: var(--text);
  font-size: var(--text-md); font-variant-numeric: tabular-nums; position: relative; z-index: 0;
}
.range-day::after { content: ""; position: absolute; inset: 2px; border-radius: 50%; z-index: -1; transition: background-color var(--fast) var(--ease-out); }
.range-day:hover:not(:disabled)::after { background: var(--material-thin); }
.range-day.outside { color: var(--muted); }
.range-day:disabled { opacity: 0.35; }
.range-day.today::after { box-shadow: inset 0 0 0 1.5px var(--accent); }
.range-day.in { background: color-mix(in srgb, var(--accent) 16%, transparent); }
.range-day.start { border-radius: var(--radius-lg) 0 0 var(--radius-lg); }
.range-day.end { border-radius: 0 var(--radius-lg) var(--radius-lg) 0; }
.range-day.start.end { border-radius: var(--radius-lg); }
.range-day.in.row-start { border-top-left-radius: var(--radius-lg); border-bottom-left-radius: var(--radius-lg); }
.range-day.in.row-end { border-top-right-radius: var(--radius-lg); border-bottom-right-radius: var(--radius-lg); }
.range-day.start::after, .range-day.end::after { background: linear-gradient(180deg, var(--accent-fill-top), var(--accent-fill)); }
.range-day.start, .range-day.end { color: var(--accent-text); font-weight: var(--weight-figure); }
.range-day:active:not(:disabled) { transform: none; }
.range-day:active:not(:disabled)::after { transform: scale(0.92); }
.range-times { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-8) var(--space-10); }
.range-times label { display: grid; gap: var(--space-4); margin: 0; font-size: var(--text-xs); color: var(--muted); }
.range-times input[type=time] { padding: 7px var(--space-12); border-radius: var(--radius-md); font-variant-numeric: tabular-nums; }
.range-times input[type=time]::-webkit-calendar-picker-indicator { display: none; }
.range-times input:disabled { opacity: 0.45; }
.range-times .range-now { grid-column: 1 / -1; display: flex; align-items: center; gap: var(--space-8); font-size: var(--text-sm); color: var(--text); }
.range-message { margin: 0; font-size: var(--text-xs); min-height: 1.2em; }
.range-message.error { color: var(--error); }
.range-actions { display: flex; justify-content: flex-end; gap: var(--space-8); }
@media (prefers-reduced-motion: reduce) { .range-popover, .range-popover.closing { animation-duration: 1ms; } }

/* The Energy section's days: one card the width of the row, its table under the head. */
/* Today's figures above the charts: a small tile and the label on one row, the proportional figure the card's width
   under them, a note in muted ink. */
.energy-today { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: var(--space-14); margin-bottom: var(--space-14); }
.energy-today .card { margin: 0; padding: var(--space-14) var(--space-16); display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: center; gap: var(--space-8) var(--space-10); align-content: start; }
.energy-today .card > div { display: contents; }
.energy-today .tile { width: 30px; height: 30px; border-radius: var(--radius-sm); }
.energy-today .tile svg { width: 17px; height: 17px; }
.energy-today .card > div > span { font-size: var(--text-sm); color: var(--muted); }
.energy-today b, .energy-today small { grid-column: 1 / -1; }
.energy-today b { font-size: 1.75rem; line-height: 1.1; font-weight: var(--weight-figure); letter-spacing: -0.02em; white-space: nowrap; }
.energy-today small { font-size: var(--text-xs); color: var(--muted); margin-top: -4px; }
.energy .chart-head .who { flex: 1; min-width: 0; }
/* A phone: two figures a row, tighter cards, smaller tiles, the range across the width. */
@media (max-width: 640px) {
  .energy-today { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-10); margin-bottom: var(--space-12); }
  .energy-today .card { padding: var(--space-12) var(--space-14); }
  .energy-today b { font-size: var(--text-3xl); }
  .energy .chart-grid { gap: var(--space-10); }
  .energy .chart-card { padding: var(--space-14); gap: var(--space-8); }
  .energy .chart-head { gap: var(--space-10); }
  .energy .chart-head .tile { width: 32px; height: 32px; border-radius: var(--radius-sm); }
  .energy .chart-head .tile svg { width: 18px; height: 18px; }
  .energy .chart-head .muted { font-size: var(--text-xs); }
  .energy .range-control { display: flex; width: 100%; }
  .energy-history-bar > .group { display: flex; width: 100%; }
  .energy-history-bar > .group button { flex: 1; }
  .energy-period-nav { width: 100%; justify-content: space-between; }
  .energy-totals { gap: var(--space-8) var(--space-18); }
  .energy-total b { font-size: var(--text-lg); }
  .energy .range-control button { flex: 1 0 auto; padding-inline: var(--space-10); }
}
.energy .chart-table { margin-top: var(--space-12); }
.chart-grid.energy-days { grid-template-columns: minmax(0, 1fr); margin-top: var(--space-14); }
/* The history's period: Week, Month or Year on the left, the period with its arrows on the right. */
.energy-history-bar { display: flex; align-items: center; justify-content: space-between; gap: var(--space-10); flex-wrap: wrap; }
.energy-period-nav { display: flex; align-items: center; gap: var(--space-6); }
.energy-period { min-width: 12ch; text-align: center; font-size: var(--text-base); font-variant-numeric: tabular-nums; }
/* An import of the history: while it runs, its progress in a thin accent bar; done, one quiet line; failed, a warning. */
.energy-imports { display: grid; gap: var(--space-8); }
.energy-imports:empty { display: none; }
.energy-import { display: flex; align-items: center; gap: var(--space-8); font-size: var(--text-sm); }
.energy-import > svg { width: 16px; height: 16px; flex: none; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.energy-import.running { display: grid; gap: var(--space-6); padding: var(--space-10) var(--space-12); border-radius: var(--radius-md); background: var(--material-thin); }
.energy-import-line { display: flex; justify-content: space-between; gap: var(--space-12); }
.energy-import-line b { font-variant-numeric: tabular-nums; font-weight: var(--weight-semibold); }
.energy-import progress { -webkit-appearance: none; appearance: none; width: 100%; height: 6px; border: 0; border-radius: 3px; overflow: hidden; background: var(--line); }
.energy-import progress::-webkit-progress-bar { background: var(--line); border-radius: 3px; }
.energy-import progress::-webkit-progress-value { background: var(--accent); border-radius: 3px; transition: width var(--normal) var(--ease-out); }
.energy-import progress::-moz-progress-bar { background: var(--accent); border-radius: 3px; }
.energy-import.failed { color: var(--warn); }

/* The period's totals over the bars: a muted label with its colour key over a proportional figure. */
.energy-totals { display: flex; flex-wrap: wrap; align-items: flex-start; gap: var(--space-8) 28px; padding: 2px 0 var(--space-4); }
.energy-total { display: grid; gap: 2px; align-content: start; }
.energy-total span { display: inline-flex; align-items: center; gap: var(--space-6); font-size: var(--text-xs); color: var(--muted); }
.energy-total .key { display: inline-block; width: 10px; height: 10px; border-radius: 3px; }
.energy-total b { font-size: 1.125rem; font-weight: var(--weight-figure); letter-spacing: -0.01em; }
.energy-total small { font-size: var(--text-2xs); color: var(--muted); }
.chart .tick.current { fill: var(--text); font-weight: var(--weight-figure); }
.energy-period-nav .menu-button svg { fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.energy-days .chart-table { margin-top: 0; }
.energy-days .chart-table thead th.time { text-align: left; }
.chart-card { margin: 0; display: grid; gap: var(--space-10); align-content: start; min-width: 0; }
.chart-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-12); }
.chart-head .muted { font-size: var(--text-sm); }
.chart-figure { font-size: var(--text-3xl); line-height: 1.1; font-weight: var(--weight-figure); letter-spacing: -0.02em; white-space: nowrap; }
.chart-detail { font-size: var(--text-sm); font-variant-numeric: tabular-nums; min-height: 1.2em; }
.chart-body { min-width: 0; }
.chart-frame { position: relative; }
.chart { display: block; max-width: 100%; overflow: visible; border-radius: var(--radius-sm); }
.chart:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; }
.chart .grid { stroke: var(--line); stroke-width: 1; shape-rendering: crispEdges; }
.chart .tick { fill: var(--muted); font-size: var(--text-2xs); font-variant-numeric: tabular-nums; }
.chart .line { fill: none; stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.chart .area { stroke: none; opacity: 0.1; }
.chart .dot { stroke: var(--material-solid); stroke-width: 2; }
.chart .crosshair { stroke: var(--muted); stroke-width: 1; opacity: 0.6; }
.chart .grid.zero { stroke: var(--muted); opacity: 0.5; }
.chart .line.tone-1 { stroke: var(--series-1); }
.chart .line.tone-2 { stroke: var(--series-2); }
.chart .line.tone-3 { stroke: var(--series-3); }
.chart .line.tone-4 { stroke: var(--series-4); }
.chart .line.tone-5 { stroke: var(--series-5); }
.chart .line.tone-6 { stroke: var(--series-6); }
.chart .line.tone-7 { stroke: var(--series-7); }
.chart .area.tone-1, .chart .dot.tone-1 { fill: var(--series-1); }
.chart .area.tone-2, .chart .dot.tone-2 { fill: var(--series-2); }
.chart .area.tone-3, .chart .dot.tone-3 { fill: var(--series-3); }
.chart .area.tone-4, .chart .dot.tone-4 { fill: var(--series-4); }
.chart .area.tone-5, .chart .dot.tone-5 { fill: var(--series-5); }
.chart .area.tone-6, .chart .dot.tone-6 { fill: var(--series-6); }
.chart .area.tone-7, .chart .dot.tone-7 { fill: var(--series-7); }
.chart .bar.tone-1 { fill: var(--series-1); }
.chart .bar.tone-2 { fill: var(--series-2); }
.chart .bar.tone-3 { fill: var(--series-3); }
.chart .bar.tone-4 { fill: var(--series-4); }
.chart .bar.tone-5 { fill: var(--series-5); }
.chart .bar.tone-6 { fill: var(--series-6); }
.chart .bar.tone-7 { fill: var(--series-7); }
/* A part with no source (an imported hour's home use not split): neutral, never a series colour. */
.chart .bar.tone-8 { fill: var(--muted); opacity: 0.45; }
.chart .bar-hover { fill: var(--material-thin); }
.chart-legend .key.bar, .chart-tooltip .key.bar { width: 10px; height: 10px; border-radius: 3px; }
.chart-legend { display: flex; flex-wrap: wrap; gap: var(--space-4) var(--space-14); font-size: var(--text-sm); color: var(--muted); }
.chart-legend span { display: inline-flex; align-items: center; gap: var(--space-6); white-space: nowrap; }
.chart-legend .key, .chart-tooltip .key { display: inline-block; width: 12px; height: 2px; border-radius: 1px; }
.key.tone-1 { background: var(--series-1); }
.key.tone-2 { background: var(--series-2); }
.key.tone-3 { background: var(--series-3); }
.key.tone-4 { background: var(--series-4); }
.key.tone-5 { background: var(--series-5); }
.key.tone-6 { background: var(--series-6); }
.key.tone-7 { background: var(--series-7); }
.key.tone-8 { background: var(--muted); opacity: 0.45; }
.chart-tooltip {
  position: absolute; top: 4px; z-index: 2; pointer-events: none; padding: var(--space-8) var(--space-10); border-radius: var(--radius-md); min-width: 132px;
  background: var(--material-solid); border: 1px solid var(--edge); box-shadow: var(--shadow-control); font-size: var(--text-sm);
}
.chart-tooltip .chart-time { color: var(--muted); margin-bottom: var(--space-4); white-space: nowrap; }
.chart-tooltip .chart-row { display: flex; align-items: center; gap: var(--space-8); white-space: nowrap; }
.chart-tooltip b { font-variant-numeric: tabular-nums; }
/* The charts as a table: a card of its own, the header pinned while the rows scroll, the groups (homeswift, Home app
   requests, plugin device calls) under a header each with a rule between them, numbers right-aligned in tabular
   figures, an empty cell quiet. */
.chart-table { margin-top: var(--space-12); }
.chart-table .table-scroll {
  overflow: auto; max-height: 420px; margin-top: var(--space-10); border-radius: var(--radius-md); border: 1px solid var(--edge);
  background: var(--material-solid); box-shadow: var(--shadow-control);
}
.chart-table table { width: 100%; border-collapse: separate; border-spacing: 0; font-size: var(--text-sm); font-variant-numeric: tabular-nums; white-space: nowrap; }
.chart-table thead { position: sticky; top: 0; z-index: 1; background: var(--material-solid); }
.chart-table th, .chart-table td { padding: 7px var(--space-14); text-align: right; border-bottom: 1px solid var(--line); }
.chart-table thead th { color: var(--muted); font-weight: var(--weight-medium); font-size: var(--text-xs); }
.chart-table thead .groups th { color: var(--text); font-weight: var(--weight-semibold); font-size: var(--text-sm); text-align: center; padding-bottom: var(--space-4); border-bottom-color: transparent; }
.chart-table thead .groups th.time { text-align: left; vertical-align: bottom; padding-bottom: 7px; border-bottom-color: var(--line); }
.chart-table .group-start { border-left: 1px solid var(--line); }
.chart-table tbody th.time { text-align: left; font-weight: var(--weight-medium); color: var(--text); }
.chart-table td.empty { color: var(--muted); opacity: 0.55; }
.chart-table tbody tr:last-child > * { border-bottom: 0; }
.chart-table tbody tr:hover > * { background: var(--material-thin); }
.servers { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 420px), 1fr)); gap: var(--space-14); }
.server { margin: 0; display: grid; gap: var(--space-14); align-content: start; }
.servers .server, .card.server { animation: materialize var(--normal) var(--ease-out); }
.server-head { display: flex; align-items: center; gap: var(--space-12); min-width: 0; }
.server-head strong { display: block; font-size: var(--text-xl); letter-spacing: -0.01em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.server-head .muted { font-size: var(--text-sm); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.setup { display: flex; gap: var(--space-16); align-items: center; padding-top: var(--space-14); border-top: 1px solid var(--line); }
.setup p { margin: 0 0 var(--space-6); }
.setup .code { margin: 0; }
.server .actions { margin-top: 0; }
.banner { margin: var(--space-14) auto 0; max-width: 1100px; width: calc(100% - 24px); padding: var(--space-10) var(--space-20); text-align: center; color: var(--warn); font-weight: var(--weight-semibold); animation: materialize var(--normal) var(--ease-out); }
.auth { min-height: 100vh; min-height: 100dvh; display: grid; place-items: center; padding: var(--space-20); }
.auth .card { width: min(400px, 100%); padding: 26px 26px 22px; animation: materialize 320ms var(--ease-out); }
.auth h1 { margin-top: var(--space-6); }
.auth button { width: 100%; margin-top: var(--space-10); }
.auth p.error:empty { display: none; }
/* The sign-in page's language flags, quiet under the button; the page's own is lit. */
.auth .auth-languages { display: flex; justify-content: center; gap: var(--space-4); margin-top: var(--space-14); }
.auth .auth-languages button { width: auto; margin: 0; padding: var(--space-4) var(--space-8); min-height: 0; font-size: var(--text-2xl); line-height: 1; background: none; border-color: transparent; box-shadow: none; opacity: 0.5; transition: opacity var(--fast, 150ms) ease; }
.auth .auth-languages button:hover, .auth .auth-languages button[aria-pressed="true"] { opacity: 1; }
.auth .auth-languages button[aria-pressed="true"] { background: var(--material-thin); border-color: var(--line); }
.menu-flag { width: 18px; flex: none; text-align: center; font-size: var(--text-lg); line-height: 1; }
/* The OAuth sign-in page (authorize.html): one choice per scope, each saying what it allows; Deny and Allow side by side. */
.auth .scopes { display: grid; gap: var(--space-8); margin: var(--space-14) 0 var(--space-8); padding: 0; border: 0; background: none; }
.auth .scopes legend { padding: 0; margin-bottom: 2px; }
.auth .scope {
  display: grid; grid-template-columns: auto 1fr; gap: 2px var(--space-10); align-items: start; margin: 0; padding: var(--space-10) var(--space-12); cursor: pointer;
  border-radius: var(--radius-md); border: 1px solid var(--edge); background: var(--material-thin);
  transition: border-color var(--fast) var(--ease-out), box-shadow var(--fast) var(--ease-out);
}
.auth .scope:has(input:checked) { border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent); }
.auth .scope input { width: auto; margin: 3px 0 0; box-shadow: none; accent-color: var(--accent); grid-row: span 2; }
.auth .scope .help { grid-column: 2; color: var(--muted); font-size: var(--text-sm); }
.auth .actions button { margin-top: 0; }
.auth button.switch-user { display: block; width: auto; margin: var(--space-12) auto 0; }
.connected-app { margin-top: var(--space-12); }
.qr { width: 148px; height: 148px; border-radius: var(--radius-md); background: #fff; padding: var(--space-6); box-shadow: var(--shadow-control); }
.code { font-family: var(--mono); font-size: 1.875rem; letter-spacing: 0.1em; font-variant-numeric: tabular-nums; margin: var(--space-10) 0; padding: var(--space-10) var(--space-16); border-radius: var(--radius-lg); display: inline-block; background: var(--material-thin); border: 1px solid var(--edge); box-shadow: inset 0 1px 0 var(--edge-light); }

/* A glass surface arrives as a material: blur and scale settle together, not a plain fade. */
@keyframes materialize {
  from { opacity: 0; transform: scale(0.97); filter: blur(8px); }
  to { opacity: 1; transform: none; filter: none; }
}
@keyframes fade { from { opacity: 0; } }

/* Switch: the knob slides with a strong ease-out and no overshoot (a tap carries no momentum) and widens
   while pressed, the way a real one gives under the finger. */
.switch { position: relative; width: 48px; height: 28px; margin: 0; flex: none; touch-action: manipulation; }
.switch input { opacity: 0; width: 0; height: 0; }
.switch span {
  position: absolute; inset: 0; border-radius: var(--radius-md); background-color: rgba(120, 128, 142, 0.35); border: 1px solid var(--edge);
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.15); transition: background-color var(--normal) var(--ease-out), box-shadow var(--normal) var(--ease-out);
}
.switch span::before {
  content: ""; position: absolute; width: 22px; height: 22px; left: 2px; top: 2px; border-radius: 50%;
  background: linear-gradient(180deg, #fff, #eef0f4); box-shadow: 0 2px 6px rgba(0, 0, 0, 0.25);
  transition: transform var(--normal) var(--ease-out), width var(--fast) var(--ease-out);
}
.switch input:checked + span { background-color: var(--accent); box-shadow: 0 4px 12px color-mix(in srgb, var(--accent) 40%, transparent), inset 0 1px 0 rgba(255, 255, 255, 0.35); }
.switch input:checked + span::before { transform: translateX(20px); }
.switch input:active + span::before { width: 26px; }
.switch input:checked:active + span::before { transform: translateX(16px); }
.range { display: inline-flex; align-items: center; gap: var(--space-10); }

/* Log: a row per line, its time and source in columns, warnings and errors tinted. */
/* Inside the Logs card the list is the card's own content: no second material, corners, edge or shadow. */
.log-card .log { border: 0; border-radius: 0; box-shadow: none; background: none; -webkit-backdrop-filter: none; backdrop-filter: none; }
.log { font-size: var(--text-sm); line-height: 1.45; padding: var(--space-6) 0; height: calc(100vh - 290px); height: calc(100dvh - 290px); min-height: 320px; overflow: auto; overscroll-behavior: contain; }
.log-line { display: grid; grid-template-columns: auto minmax(0, 11em) minmax(0, 1fr); gap: var(--space-12); padding: 3px var(--space-16); align-items: baseline; }
.log-line:hover { background: var(--material-thin); }
.log-line time { font-family: var(--mono); font-size: var(--text-xs); color: var(--muted); font-variant-numeric: tabular-nums; }
.log-line .label { color: var(--muted); font-weight: var(--weight-medium); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.log-line .text { overflow-wrap: anywhere; white-space: pre-wrap; }
/* A payload taken out of a line: a small JSON button after its marker, the JSON formatted under the line. */
.log-details-toggle {
  padding: 0 7px; margin: 0; border-radius: var(--radius-xs); font: 600 0.6875rem/1.5 var(--mono); letter-spacing: 0.02em; vertical-align: baseline;
  color: var(--muted); background: var(--material-thin); border: 1px solid var(--line); box-shadow: none;
}
.log-details-toggle:hover { color: var(--text); }
.log-details-toggle[aria-expanded="true"] { color: var(--accent-ink); border-color: var(--accent); }
.log-line .log-details { grid-column: 1 / -1; margin: var(--space-4) 0 var(--space-6); max-height: 420px; overflow: auto; font-size: var(--text-xs); }
.log-line.warning { background: rgba(201, 115, 26, 0.08); }
.log-line.warning .text { color: var(--warn); }
.log-line.error, .log-line.critical { background: rgba(208, 56, 59, 0.08); }
.log-line.error .text, .log-line.critical .text { color: var(--error); }
.log-line.debug .text, .log-line.trace .text { color: var(--muted); }
.empty-log { padding: var(--space-20); text-align: center; }

/* Forms */
fieldset { min-width: 0; border: 1px solid var(--line); border-radius: var(--radius-lg); padding: var(--space-8) var(--space-16) var(--space-14); margin: var(--space-14) 0; background: var(--material-thin); }
legend { color: var(--muted); padding: 0 var(--space-8); font-weight: var(--weight-medium); }
.item { border: 1px solid var(--line); border-radius: var(--radius-lg); padding: var(--space-6) var(--space-14) var(--space-12); margin: var(--space-10) 0; background: var(--material-thin); }
.item-head { display: flex; justify-content: space-between; align-items: center; gap: var(--space-10); }
.actions { display: flex; gap: var(--space-10); margin-top: var(--space-16); align-items: center; }
details > summary { cursor: pointer; color: var(--muted); padding: var(--space-8) 0; touch-action: manipulation; }
dl { display: grid; grid-template-columns: max-content 1fr; gap: 5px var(--space-16); margin: 0; }
dt { color: var(--muted); font-weight: var(--weight-medium); }
dd { margin: 0; }

/* Preferences. Reduced motion keeps fades and colour changes, which aid comprehension, and drops what
   moves, scales or blurs in. Reduced transparency makes the frosted surfaces solid. More contrast gives
   them a defined edge and lifts the secondary text. */
@media (prefers-reduced-motion: reduce) {
  .banner, .auth .card { animation: fade var(--normal) ease; }
  button, nav a { transition-property: background-color, box-shadow, opacity; }
  button:hover, button:active:not(:disabled), a.button:hover, a.button:active, nav a:active { transform: none; }
  button:active:not(:disabled) { opacity: 0.7; }
  .switch span::before { transition: none; }
  .switch input:active + span::before { width: 22px; }
  .switch input:checked:active + span::before { transform: translateX(20px); }
}
@media (prefers-reduced-transparency: reduce) {
  :root { --material: var(--material-solid); --material-thick: var(--material-solid); --material-chrome: var(--material-solid); --material-thin: var(--field); --sheen: none; }
  .card, header, .log, .banner { -webkit-backdrop-filter: none; backdrop-filter: none; }
}
@media (prefers-contrast: more) {
  :root { --material: var(--material-solid); --material-thick: var(--material-solid); --material-chrome: var(--material-solid); --sheen: none; --edge: rgba(20, 30, 50, 0.55); --line: rgba(20, 30, 50, 0.3); --muted: #3a4150; }
  @media (prefers-color-scheme: dark) { :root:not(:where([data-theme="light"])) { --edge: rgba(255, 255, 255, 0.6); --line: rgba(255, 255, 255, 0.3); --muted: #cfd4dc; } }
  :root:where([data-theme="dark"]) { --edge: rgba(255, 255, 255, 0.6); --line: rgba(255, 255, 255, 0.3); --muted: #cfd4dc; }
  .card, header, .log, .banner { -webkit-backdrop-filter: none; backdrop-filter: none; }
  button, input, select, textarea, .pill { border-color: var(--edge); }
}
@media (max-width: 640px) {
  /* The header stays one line: the brand keeps its icon, the links scroll sideways. */
  header { flex-wrap: nowrap; }
  header .brand { font-size: 0; gap: 0; }
  header nav { flex: 1 1 auto; min-width: 0; overflow-x: auto; scrollbar-width: none; }
  header nav::-webkit-scrollbar { display: none; }
  header .spacer { display: none; }
  .user-button { padding: 3px; }
  .user-name { display: none; }
  .page-head .tools, .page-head .search, .editor-bar .search { width: 100%; }
  /* A line's time and source on top, its text across the width under them. */
  .log-line { grid-template-columns: auto minmax(0, 1fr); gap: 1px var(--space-8); padding: 5px var(--space-12); }
  .log-line .label { font-size: var(--text-xs); }
  .log-line .text { grid-column: 1 / -1; }
  .facts { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .setup { flex-direction: column; align-items: flex-start; }
}
@media (prefers-reduced-motion: reduce) { .servers .server, .card.server { animation: fade var(--normal) ease; } }
@media (max-width: 640px) { header { gap: var(--space-6); padding: var(--space-6) var(--space-8); } nav a { padding: var(--space-6) var(--space-10); white-space: nowrap; } main { padding: var(--space-14) var(--space-10) 30px; } input[type=range] { width: 110px; } }

/* The Assistant's chat (chat.js). On a wide window a panel floats beside the page under the header, no scrim,
   so the page stays usable; on a phone it is a sheet over a scrim, dragged by its head. Thick material like
   the header, controls solid on top; the Apple Intelligence glow turns around the panel only while the
   Assistant works or listens. chat.js moves it on a spring, from the button and back to it. */
/* The Assistant's sparkle, round, beside the account button. */
.chat-open { flex: none; display: grid; place-items: center; width: 36px; height: 36px; padding: 0; border-radius: 50%; }
.chat-open .sparkle { width: 19px; height: 19px; }
/* Open: a violet ring, an outline (Safari draws a spread shadow square inside the blurred header). */
.chat-open[aria-expanded="true"] { outline: 3px solid rgba(191, 90, 242, 0.22); outline-offset: 0; }
.chat {
  position: fixed; z-index: var(--layer-panel); top: 84px; right: max(16px, calc((100vw - 1100px) / 2));
  width: min(420px, calc(100vw - 32px)); height: min(740px, calc(100dvh - 100px));
  transform-origin: top right; will-change: transform; isolation: isolate; --open: 1; --glow: 0;
}
.chat-surface {
  position: relative; height: 100%; display: flex; flex-direction: column; overflow: hidden; border-radius: var(--radius-xl);
  background-color: var(--material-thick); background-image: var(--sheen);
  -webkit-backdrop-filter: blur(var(--blur-thick)) saturate(180%); backdrop-filter: blur(var(--blur-thick)) saturate(180%);
  border: 1px solid var(--edge); box-shadow: 0 24px 64px rgba(25, 34, 56, 0.24), inset 0 1px 0 var(--edge-light);
  opacity: var(--open);
}
.chat-glow {
  position: absolute; inset: -3px; z-index: -1; border-radius: calc(var(--radius-xl) + 3px); pointer-events: none;
  background: conic-gradient(from var(--ai-angle), var(--ai-colors)); filter: blur(18px);
  opacity: calc(var(--glow) * var(--open));
}
/* Registered, so the glow eases in and out instead of switching. */
@property --glow { syntax: "<number>"; inherits: true; initial-value: 0; }
.chat { transition: --glow 700ms var(--ease-out); }
.chat.working { --glow: 0.5; }
.chat.listening { --glow: 0.8; }
.chat.working .chat-glow, .chat.listening .chat-glow { animation: ai-turn 3s linear infinite; }
.chat.listening .chat-glow { animation-duration: 2s; }
.chat-scrim { position: fixed; inset: 0; z-index: calc(var(--layer-panel) - 1); background: rgba(10, 14, 22, 0.35); opacity: 0; }

.chat-head { position: relative; display: flex; align-items: center; gap: var(--space-8); padding: var(--space-14) var(--space-12) var(--space-10) var(--space-18); }
.chat-head .sparkle { width: 18px; height: 18px; }
.chat-head strong { font-size: var(--text-xl); letter-spacing: -0.015em; }
.chat-model { color: var(--muted); font-size: var(--text-xs); letter-spacing: 0.01em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chat-icon { width: 32px; height: 32px; padding: 0; display: grid; place-items: center; border-radius: 50%; font-size: var(--text-2xl); line-height: 1; }
.chat-icon svg, .chat-mic svg, .chat-send svg { width: 17px; height: 17px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.chat-grabber { display: none; }

.chat-log {
  flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding: var(--space-8) var(--space-18) var(--space-16);
  display: flex; flex-direction: column; gap: var(--space-12);
  -webkit-mask-image: linear-gradient(transparent, #000 12px, #000 calc(100% - 16px), transparent);
  mask-image: linear-gradient(transparent, #000 12px, #000 calc(100% - 16px), transparent);
}
.chat-log > * { animation: chat-in var(--normal) var(--ease-out); }
@keyframes chat-in { from { opacity: 0; transform: translateY(6px); } }
.chat-user { align-self: flex-end; max-width: 86%; }
.chat-user p {
  margin: 0; padding: 9px var(--space-14); border-radius: var(--radius-lg) var(--radius-lg) var(--radius-xs) var(--radius-lg); white-space: pre-wrap; overflow-wrap: anywhere;
  background: linear-gradient(180deg, var(--accent-fill-top), var(--accent-fill)); color: var(--accent-text);
  box-shadow: 0 6px 16px color-mix(in srgb, var(--accent) 25%, transparent), inset 0 1px 0 rgba(255, 255, 255, 0.4);
}
.chat-answer { line-height: 1.55; overflow-wrap: anywhere; }
.chat-answer .chat-text > :last-child { margin-bottom: 0; }
.chat-step { display: flex; align-items: flex-start; gap: var(--space-8); font-size: var(--text-sm); color: var(--muted); line-height: 1.35; }
.chat-step + .chat-step { margin-top: -6px; }
.chat-step-title { color: var(--text); font-weight: var(--weight-medium); }
.chat-step-summary { overflow-wrap: anywhere; }
.chat-step-mark {
  position: relative; flex: none; width: 15px; height: 15px; margin-top: 1px; border-radius: 50%;
  border: 2px solid var(--line); border-top-color: #bf5af2; animation: spin 0.8s linear infinite;
}
.chat-step:is(.done, .failed, .declined) .chat-step-mark { animation: none; border: 0; background: var(--ok); transition: background-color var(--normal) var(--ease-out); }
.chat-step.failed .chat-step-mark { background: var(--error); }
.chat-step.declined .chat-step-mark { background: var(--muted); }
.chat-step.declined .chat-step-mark::after { content: ""; position: absolute; left: 4px; right: 4px; top: 6.5px; height: 2px; border-radius: 1px; background: #fff; }
.chat-step.declined .chat-step-title { color: var(--muted); }
.chat-step.done .chat-step-mark::after {
  content: ""; position: absolute; left: 5px; top: 2.5px; width: 3.5px; height: 7px; border: solid #fff; border-width: 0 2px 2px 0; transform: rotate(45deg);
}
.chat-step.failed .chat-step-mark::after { content: "×"; position: absolute; inset: 0; display: grid; place-items: center; color: #fff; font-size: var(--text-xs); font-weight: var(--weight-bold); line-height: 1; }
.chat-thinking {
  margin: 0; font-size: var(--text-md); font-weight: var(--weight-medium);
  background: linear-gradient(90deg, var(--muted) 20%, var(--text) 50%, var(--muted) 80%); background-size: 250% 100%;
  -webkit-background-clip: text; background-clip: text; color: transparent; animation: ai-shimmer 1.8s linear infinite;
}
.chat-error { margin: 0; color: var(--error); font-size: var(--text-md); }

/* A change waiting for the user: solid, set apart by an accent edge, the answer within reach of the thumb. */
.chat-confirm {
  padding: var(--space-12) var(--space-14); border-radius: var(--radius-lg); background: var(--material-solid); border: 1px solid var(--edge);
  box-shadow: var(--shadow-control);
}
.chat-confirm.pending { border-color: rgba(191, 90, 242, 0.45); box-shadow: 0 0 0 3px rgba(191, 90, 242, 0.12), var(--shadow-control); }
.chat-confirm-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-8); }
.chat-confirm-head strong { font-size: var(--text-base); letter-spacing: -0.01em; }
.chat-confirm p { margin: var(--space-6) 0 var(--space-4); font-size: var(--text-md); color: var(--muted); }
.chat-confirm summary { cursor: pointer; font-size: var(--text-sm); color: var(--muted); padding: 2px 0; }
.chat-confirm pre {
  margin: var(--space-6) 0 0; max-height: 220px; overflow: auto; padding: var(--space-8) var(--space-10); border-radius: var(--radius-sm);
  font: 0.75rem/1.45 var(--mono); background: var(--material-thin); border: 1px solid var(--line); white-space: pre-wrap; overflow-wrap: anywhere;
}
.chat-changes { margin: var(--space-8) 0 var(--space-6); padding: 0; list-style: none; font-size: var(--text-sm); display: grid; gap: var(--space-4); }
.chat-changes li { overflow-wrap: anywhere; }
.chat-changes code { font-family: var(--mono); font-size: var(--text-xs); padding: 1px var(--space-6); border-radius: var(--radius-xs); background: var(--material-thin); border: 1px solid var(--line); }
.chat-confirm-actions { display: flex; justify-content: flex-end; gap: var(--space-8); margin-top: var(--space-10); }
.chat-confirm-actions button { min-width: 96px; }

.chat-welcome { margin: auto 0; padding: var(--space-16) var(--space-4); text-align: center; }
.chat-welcome .sparkle { width: 36px; height: 36px; margin: 0 auto var(--space-8); }
.chat-welcome h2 { margin: 0 0 var(--space-6); font-size: 1.3125rem; line-height: 1.2; letter-spacing: -0.02em; }
.chat-welcome p { margin: 0 auto; max-width: 30ch; font-size: var(--text-md); }
.chat-suggestions { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--space-8); margin-top: var(--space-16); }
.chat-suggestions button { border-radius: var(--radius-pill); padding: 7px 13px; font-size: var(--text-sm); }

.chat-composer {
  display: flex; align-items: flex-end; gap: var(--space-6); margin: 0 var(--space-12); padding: 5px 5px 5px var(--space-14); border-radius: var(--radius);
  background: var(--control); border: 1px solid var(--line); box-shadow: var(--shadow-control);
  transition: border-color var(--fast) var(--ease-out), box-shadow var(--fast) var(--ease-out);
}
.chat-composer:focus-within { border-color: rgba(191, 90, 242, 0.55); box-shadow: 0 0 0 4px rgba(191, 90, 242, 0.14); }
.chat-composer textarea {
  flex: 1; min-height: 0; max-height: 140px; padding: 7px 0; resize: none; border: 0; border-radius: 0; background: none; box-shadow: none;
  font: inherit; white-space: pre-wrap; line-height: 1.4;
}
.chat-composer textarea:focus { box-shadow: none; }
.chat-mic, .chat-send { flex: none; width: 34px; height: 34px; padding: 0; display: grid; place-items: center; border-radius: 50%; }
.chat-mic { border-color: transparent; background: none; box-shadow: none; color: var(--muted); }
.chat-mic:hover { color: var(--text); background: var(--material-thin); }
.chat-mic.unavailable { opacity: 0.45; }
.chat.listening .chat-mic {
  color: #fff; background: conic-gradient(from var(--ai-angle), var(--ai-colors)); animation: ai-turn 2s linear infinite;
  box-shadow: 0 0 0 4px rgba(191, 90, 242, 0.2);
}
.chat-send { background: linear-gradient(180deg, var(--accent-fill-top), var(--accent-fill)); color: var(--accent-text); border-color: rgba(255, 255, 255, 0.4); }
.chat-send .stop-icon, .chat-send.stop .send-icon { display: none; }
.chat-send.stop .stop-icon { display: block; fill: currentColor; stroke: none; }
.chat-send.stop { background: var(--text); color: var(--material-solid); }
.chat-foot { margin: 7px var(--space-16) var(--space-12); min-height: 1.2em; font-size: var(--text-xs); color: var(--muted); text-align: center; letter-spacing: 0.01em; }
.visually-hidden { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }

@media (max-width: 640px) {
  .chat {
    top: auto; bottom: var(--keyboard, 0px); left: 0; right: 0; width: auto; transform-origin: bottom center;
    height: min(88dvh, 780px, calc(var(--visible, 100dvh) - max(12px, env(safe-area-inset-top))));
  }
  .chat-surface { border-radius: var(--radius-xl) var(--radius-xl) 0 0; padding-bottom: env(safe-area-inset-bottom); border-bottom: 0; }
  /* On the keyboard: no home indicator to clear, and the voice line and the provider's note give the log room. */
  .chat.keyboard .chat-surface { padding-bottom: 0; }
  .chat.keyboard .chat-voice, .chat.keyboard .chat-foot:empty { display: none; }
  .chat.keyboard .chat-foot { margin: var(--space-6) var(--space-16) var(--space-8); }
  /* 16px, or Safari zooms the page into the field and leaves it there. */
  .chat-composer textarea, .chat .chat-voice select.popup { font-size: 16px; }
  .chat-glow { inset: -3px -3px 0; border-radius: calc(var(--radius-xl) + 3px) calc(var(--radius-xl) + 3px) 0 0; }
  .chat-grabber { display: block; position: absolute; top: 6px; left: 50%; width: 36px; height: 5px; border-radius: 3px; background: var(--line); transform: translateX(-50%); }
  .chat-head { padding-top: var(--space-20); touch-action: none; cursor: grab; }
}
@media (prefers-reduced-motion: reduce) {
  .chat-glow, .chat.listening .chat-mic, .chat-step-mark, .chat-thinking, .chat-log > * { animation: none !important; }
  .chat-thinking { color: var(--muted); background: none; }
}
@media (prefers-reduced-transparency: reduce) {
  .chat-surface { background: var(--material-solid); -webkit-backdrop-filter: none; backdrop-filter: none; }
  .chat-glow { display: none; }
}
@media (prefers-contrast: more) {
  .chat-surface { background: var(--material-solid); border-color: var(--text); }
}

/* JSON in colour (common.js): keys, strings, numbers, booleans and null each their own hue, punctuation quiet;
   a read-only block (.json) and an editor whose coloured layer sits under a transparent textarea. */
:root { --json-key: #6f42c1; --json-string: #1a7f37; --json-number: #a8440a; --json-bool: #0a63c9; --json-null: #8a8f98; --json-secret: #9a6700; }
@media (prefers-color-scheme: dark) {
  :root:not(:where([data-theme="light"])) { --json-key: #c8a2ff; --json-string: #8ddc8f; --json-number: #ffb06b; --json-bool: #79b8ff; --json-null: #8b949e; }
}
:root:where([data-theme="dark"]) { --json-key: #c8a2ff; --json-string: #8ddc8f; --json-number: #ffb06b; --json-bool: #79b8ff; --json-null: #8b949e; }
.json-key { color: var(--json-key); }
.json-string { color: var(--json-string); }
.json-number { color: var(--json-number); }
.json-bool { color: var(--json-bool); }
.json-null { color: var(--json-null); font-style: italic; }
.json-punct { color: var(--muted); }
/* A key that holds a secret (the server's Redaction rule): gold, a lock in the indentation before it, so nothing moves
   and the caret stays on its character; its value sits on a faint gold pill, as a sealed field would. */
.json-secret { position: relative; color: var(--json-secret); }
.json-secret > svg {
  position: absolute; right: calc(100% + 0.3ch); top: 50%; width: 0.9em; height: 0.9em; translate: 0 -55%;
  fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round;
}
.json-secret-value { color: var(--json-secret); background: rgba(242, 193, 78, 0.12); border-radius: 4px; box-shadow: 0 0 0 1px rgba(242, 193, 78, 0.22); }
pre.json { margin: 0; padding: var(--space-10) var(--space-12); border-radius: var(--radius-md); font: 0.75rem/1.5 var(--mono); background: var(--material-thin); border: 1px solid var(--line); overflow: auto; tab-size: 2; }
.code-editor { display: grid; position: relative; }
.code-editor > .code-layer, .code-editor > .code-input {
  grid-area: 1 / 1; margin: 0; box-sizing: border-box; min-width: 0; padding: var(--code-pad) var(--space-16);
  font: 0.8125rem/1.55 var(--mono); tab-size: 2; white-space: pre; overflow: auto; overflow-wrap: normal; word-break: normal;
}
.code-editor > .code-layer { pointer-events: none; border: 1px solid transparent; border-radius: var(--radius); overflow: hidden; color: var(--text); position: relative; z-index: 0; }
/* A line with a problem (common.js jsonEditor): a band under its text, from the layer's top by line heights. */
/* --code-pad is the text's top padding, which the marks and the fold chevrons are placed from. */
.code-editor { --code-line: 1.55em; --code-pad: 14px; }
.code-mark { position: absolute; left: 0; right: 0; height: var(--code-line); z-index: -1; background: rgba(255, 107, 107, 0.16); box-shadow: inset 3px 0 0 var(--error); }
.line-link { padding: 0; margin: 0 var(--space-6) 0 0; border: 0; background: none; box-shadow: none; font: inherit; font-weight: var(--weight-semibold); color: inherit; text-decoration: underline; text-underline-offset: 2px; cursor: pointer; }
.schema-problems { margin: var(--space-6) 0 0; padding: 0; list-style: none; display: grid; gap: 2px; }
.code-editor > .code-input { position: relative; z-index: 1; color: transparent; background: transparent; caret-color: var(--text); resize: vertical; }
.code-editor > .code-input::selection { color: transparent; background: rgba(10, 132, 255, 0.28); }
.editor-card .code-editor { --code-pad: 16px; }
.editor-card .code-editor > * { border-width: 0; border-radius: 0; padding: var(--code-pad) var(--space-18); min-height: 62vh; }
.form-card .code-editor > * { min-height: 340px; }
.form-card .code-editor { margin-top: var(--space-4); border-radius: var(--radius); background: var(--field); }
/* Folding (common.js jsonEditor): a chevron beside each line a block opens on, in a gutter the text clears, and a
   folded block's inside as one "…" drawn as a pill of the same width, so the caret stays on its character. */
.code-editor > .code-layer, .code-editor > .code-input { padding-left: 32px; }
.code-editor > .code-gutter {
  position: absolute; top: 0; left: 0; bottom: 0; width: 26px; padding: 0; min-height: 0; z-index: 2; overflow: hidden;
  font: 0.8125rem/1.55 var(--mono); background: inherit; border-radius: var(--radius) 0 0 var(--radius); pointer-events: none;
}
.code-folds { position: relative; will-change: transform; }
.code-fold-toggle {
  position: absolute; left: 6px; width: 18px; height: var(--code-line); min-width: 0; min-height: 0; margin: 0; padding: 0; border: 0; border-radius: 5px;
  display: grid; place-items: center; background: none; box-shadow: none; color: var(--muted); font: inherit; cursor: pointer;
  pointer-events: auto; opacity: 0.45; transition: opacity var(--fast) var(--ease-out), color var(--fast) var(--ease-out);
}
.code-fold-toggle svg { width: 12px; height: 12px; fill: none; stroke: currentColor; stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; transition: transform 160ms var(--ease-out); }
.code-fold-toggle.folded { opacity: 1; color: var(--accent-ink); }
.code-fold-toggle.folded svg { transform: rotate(-90deg); }
.code-fold-toggle:active { transform: scale(0.9); }
@media (hover: hover) and (pointer: fine) {
  .code-fold-toggle:not(.folded) { opacity: 0; }
  .code-editor:hover .code-fold-toggle:not(.folded), .code-editor:focus-within .code-fold-toggle:not(.folded) { opacity: 0.5; }
  .code-editor .code-fold-toggle:hover { opacity: 1; color: var(--text); background: var(--material-thin); }
}
/* The character itself stays transparent (the textarea's caret counts it); a centred ⋯ on a short pill stands in. */
.code-fold { position: relative; color: transparent; }
.code-fold::before { content: ""; position: absolute; inset: 0.22em -2px; border-radius: 4px; background: rgba(255, 143, 61, 0.2); }
.code-fold::after { content: "⋯"; position: absolute; inset: 0; text-align: center; color: var(--accent-ink); font-weight: var(--weight-bold); }

/* Logs and JSON on a dark surface in either theme, as a terminal: the log list, JSON blocks, the JSON editors and
   the config diffs take the dark theme's text, lines and hues, on a ground a step below the dark cards. */
:root { --console: #161a21; }
@media (prefers-color-scheme: dark) { :root:not(:where([data-theme="light"])) { --console: #0b0d12; } }
:root:where([data-theme="dark"]) { --console: #0b0d12; }
.log, pre.json, pre.diff, .code-editor {
  color-scheme: dark; color: var(--text);
  --text: #f3f4f7; --muted: #a2a9b5; --line: rgba(255, 255, 255, 0.1); --edge: rgba(255, 255, 255, 0.16);
  --material-thin: rgba(255, 255, 255, 0.06); --field: rgba(255, 255, 255, 0.04);
  --warn: #e9a04a; --ok: #3ccf7a; --error: #ff6b6b; --accent-ink: #ff8f3d;
  --json-key: #c8a2ff; --json-string: #8ddc8f; --json-number: #ffb06b; --json-bool: #79b8ff; --json-null: #8b949e;
  --json-secret: #f2c14e;
}
.log-card .log, pre.json, pre.diff, .code-editor, .form-card .code-editor { background: var(--console); }
.log pre.json { background: var(--material-thin); }
.log-line.warning { background: rgba(233, 160, 74, 0.1); }
.log-line.error, .log-line.critical { background: rgba(255, 107, 107, 0.1); }
@media (prefers-contrast: more) { .log, pre.json, pre.diff, .code-editor { --muted: #cfd4dc; --line: rgba(255, 255, 255, 0.3); --edge: rgba(255, 255, 255, 0.6); } }

/* A file field: its path, and a place to drop the file or choose it. */
.drop-zone {
  display: flex; align-items: center; justify-content: center; gap: var(--space-8); margin-top: var(--space-6); padding: var(--space-12); border-radius: var(--radius-md);
  border: 1.5px dashed var(--line); color: var(--muted); font-size: var(--text-sm); text-align: center; cursor: pointer;
  transition: border-color var(--fast) var(--ease-out), background-color var(--fast) var(--ease-out), transform var(--fast) var(--ease-out);
}
.drop-zone:hover { border-color: var(--accent); color: var(--text); }
.drop-zone.over { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 8%, transparent); color: var(--text); transform: scale(1.01); }
.drop-zone.ok { border-style: solid; border-color: var(--ok); color: var(--ok); }
.drop-zone.error { border-color: var(--error); color: var(--error); }
/* Appearance's own wallpaper: drop an image on the card's zone, or tap it to choose one. */
.wallpaper-drop { margin-top: var(--space-14); padding: var(--space-18) var(--space-14); gap: var(--space-10); font-size: var(--text-md); }
.wallpaper-drop svg { width: 20px; height: 20px; flex: none; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.view-switch { margin-bottom: var(--space-12); }
.form-card > p.error:empty { display: none; }
.chat-voice { display: flex; align-items: center; justify-content: center; gap: var(--space-6); margin: var(--space-6) var(--space-16) 0; font-size: var(--text-xs); color: var(--muted); }
.chat-voice select.popup { padding: 3px 26px 3px var(--space-10); font-size: var(--text-xs); font-weight: var(--weight-medium); background-position: right 9px center; }

/* On a phone, after iOS: the sections move to a tab bar floating above the home indicator, within the thumb's
   reach; the header keeps the app's icon, the Assistant and the account. Controls answer the press (no hover
   lift left behind by a tap), fields are 16px so Safari does not zoom into them, and the layout pads around the
   notch and the home indicator (viewport-fit=cover). */
.tabbar { display: none; }
@media (max-width: 640px) {
  header { top: max(8px, env(safe-area-inset-top)); width: calc(100% - 20px); margin-top: max(var(--space-8), env(safe-area-inset-top)); padding: var(--space-6) var(--space-8) var(--space-6) var(--space-6); }
  header nav { display: none; }
  header .brand { font-size: var(--text-xl); gap: var(--space-8); letter-spacing: -0.015em; }
  header .spacer { display: block; flex: 1; }
  main { padding: var(--space-14) var(--space-12) calc(104px + env(safe-area-inset-bottom)); }
  .tabbar {
    position: fixed; z-index: var(--layer-tabbar); left: 10px; right: 10px; bottom: max(10px, env(safe-area-inset-bottom));
    /* Equal icon targets for each section the user may open. */
    display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); padding: var(--space-6) var(--space-4); border-radius: var(--radius-xl);
    background-color: var(--material-thick); background-image: var(--sheen);
    -webkit-backdrop-filter: blur(var(--blur-thick)) saturate(180%); backdrop-filter: blur(var(--blur-thick)) saturate(180%);
    border: 1px solid var(--edge); box-shadow: var(--shadow-thick), inset 0 1px 0 var(--edge-light);
  }
  .tabbar a {
    display: grid; place-items: center; padding: var(--space-10) 0; border-radius: var(--radius); min-height: 44px;
    color: var(--muted); text-decoration: none; font-size: 0.625rem; font-weight: var(--weight-semibold); letter-spacing: -0.025em;
    touch-action: manipulation; -webkit-user-select: none; user-select: none;
    transition: transform var(--fast) var(--ease-out), background-color var(--fast) var(--ease-out), color var(--fast) var(--ease-out);
  }
  .tabbar a span { display: none; }
  .tabbar a svg { width: 24px; height: 24px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
  .tabbar a.active { color: var(--accent-ink); background: var(--material-thin); }
  .tabbar a:active { transform: scale(0.92); transition-duration: 80ms; }
  /* Align the save status with the floating navigation, leaving room for its 54px button. */
  .settings-bar {
    bottom: max(14px, env(safe-area-inset-bottom));
    margin-right: 0;
    min-height: 54px; padding: var(--space-6) var(--space-8) var(--space-6) var(--space-16);
    flex-wrap: wrap; border-radius: var(--radius-xl);
  }
  .settings-bar.beside-mobile-menu { margin-right: calc(70px + env(safe-area-inset-right)); }
  .settings-bar > span:first-child { flex-basis: 60px; }
  .settings-bar > button { flex-shrink: 0; }
  /* Revert as an icon, so the status, Revert and Save fit on one row beside the menu button. */
  .settings-bar > .settings-action:not(.primary) { width: 40px; height: 40px; padding: 0; justify-content: center; }
  .settings-bar > .settings-action:not(.primary) > span { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  /* Config's Secrets only: its lock alone, the label kept for assistive technology, so the bar stays on one line. */
  .editor-bar > .secrets-only { width: 40px; height: 40px; padding: 0; position: relative; }
  .editor-bar > .secrets-only > span { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  /* Fields at 16px: smaller, and Safari zooms the page into them on focus. */
  input, select, textarea, .code-editor > .code-layer, .code-editor > .code-input, .code-editor > .code-gutter { font-size: 16px; }
  /* Comfortable targets, near Apple's 44pt: every button at least 40px tall, a text button too (its hit area
     grows, not its look). */
  .menu-button, .chat-icon { width: 40px; height: 40px; }
  button, a.button { min-height: 40px; }
  button.link { padding-top: var(--space-10); padding-bottom: var(--space-10); }
  .group button, .chat-suggestions button, .chat-voice select, .tabbar a { min-height: 0; }
  .menu [role="menuitem"] { padding: 11px var(--space-14); font-size: var(--text-lg); }
  /* A page's heading beside its tile, smaller; its tools under it. */
  .page-head { flex-wrap: nowrap; align-items: center; gap: var(--space-12); margin: var(--space-4) 0 var(--space-16); }
  .page-head:has(.tools) { flex-wrap: wrap; }
  .page-head .tile.large { flex: none; }
  .page-head > div { min-width: 0; }
  .page-head h1 { font-size: 1.625rem; line-height: 1.1; letter-spacing: -0.02em; }
  .page-head p { font-size: var(--text-md); }
  /* The Logs toolbar: the level across, the two menus side by side, the filter, then the count and actions. */
  .log-card .editor-bar { gap: var(--space-8); padding: var(--space-10); }
  .log-card .editor-bar > .group { flex: 1 1 100%; display: grid; grid-template-columns: repeat(4, 1fr); }
  .log-card .editor-bar > .group button { padding: var(--space-6) var(--space-4); }
  .log-card .editor-bar > select.popup { flex: 1 1 40%; max-width: none; min-width: 0; }
  /* The filter with the count at its end; then the Assistant, Copy, Follow and the menu, Follow pushed right. */
  .log-card .editor-bar > .search { flex: 1 1 180px; width: auto; min-width: 0; }
  .log-card .editor-bar > .spacer { display: none; }
  .log-card .editor-bar > .count { flex: none; font-size: var(--text-xs); white-space: nowrap; }
  .log-card .editor-bar > .count + * { margin-left: 0; }
  .log-card .editor-bar > label.toggle { margin: 0 0 0 auto; }
  .log-card .editor-bar > .save-payloads { display: none; }
  .log-card .log { height: 60dvh; min-height: 260px; }
  /* Two figures a row, so a label such as "Home app controllers" reads on one or two lines, not three; a
     bridge's device ID, the longest fact, across. */
  /* The four figures in one row, each its glyph, number and a one-line label. */
  .stats { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-10); }
  /* Toolbar buttons that become their glyph alone: a segmented control's choices, an Assistant action. */
  .icon-on-phone > span { display: none; }
  .icon-on-phone { justify-content: center; width: 40px; height: 40px; padding: 0; flex: none; }
  .icon-on-phone .sparkle { width: 19px; height: 19px; }
  /* A note beside its button (a plugin's Expert part), and removal: the text across, the button under it. */
  .page-note, .danger-zone { flex-direction: column; align-items: stretch; gap: var(--space-10); }
  .page-note > :is(button, .button), .danger-zone > button, .page-note > .expert-links { align-self: flex-start; }
  .describe-note { flex-basis: 100%; padding-left: var(--space-20); }
  .describe-setup .describe-note::before { content: none; }
  /* The activity's two menus side by side, the custom range under them. */
  .filter-bar { gap: var(--space-8); }
  .filter-bar > .popup { flex: 1 1 40%; min-width: 0; max-width: none; }
  /* The config editor's bar on one line: the page says which file it is. */
  .editor-card .editor-bar { gap: var(--space-8); padding: var(--space-10) var(--space-10) var(--space-10) var(--space-14); }
  .editor-card .editor-bar > .file-name { display: none; }
  /* A section's heading with its buttons: the buttons under it when they do not fit beside it, never folded. */
  .section-head { flex-wrap: wrap; row-gap: var(--space-8); }
  .section-head button, .section-head .button { white-space: nowrap; }
  /* A card head's button (Test connection) goes under the name rather than squeezing it. */
  .server-head:has(> button) { flex-wrap: wrap; }
  .server-head:has(> button) > .who { flex: 1 1 160px; }
  .filter-bar > .search { flex: 1 1 40%; width: auto; min-width: 0; }
  .filter-bar > .spacer { display: none; }
  .filter-bar > .count { flex: 1 1 100%; text-align: right; font-size: var(--text-sm); }
  .filter-bar > .count:empty { display: none; }
  .dash-widget .stats { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--space-8); }
  .dash-widget .stat { padding: var(--space-10) var(--space-6) 9px; border-radius: var(--radius-lg); text-align: center; }
  .dash-widget .stat > svg { position: static; display: block; margin: 0 auto var(--space-4); width: 18px; height: 18px; }
  .dash-widget .stat b { font-size: var(--text-2xl); }
  .dash-widget .stat span { display: block; font-size: var(--text-2xs); letter-spacing: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .dash-widget .stat .long { display: none; }
  .dash-widget .stat .short { display: block; }
}
/* The narrowest phones (320 points): the figures two by two, so their names read whole. */
@media (max-width: 360px) {
  .dash-widget .stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* The overview's card, smaller: the icon beside the name and the health under it. */
  .facts, .facts.lead { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .facts.lead > :first-child { grid-column: 1 / -1; }
  /* The chat sheet sits over the tab bar, its field above the home indicator. */
  .chat-foot { margin-bottom: max(var(--space-12), env(safe-area-inset-bottom)); }
}
/* A touch has no hover: a tint applied on tap would stay until the next tap elsewhere. */
@media (hover: none) {
  nav a:hover:not(.active) { background-color: transparent; }
}
@media (prefers-reduced-motion: reduce) { .tabbar a { transition: none; } }
@media (prefers-reduced-transparency: reduce) { .tabbar { background: var(--material-solid); -webkit-backdrop-filter: none; backdrop-filter: none; } }

/* Camera cards: the picture on top, in 16:9, inset in the card like the Home app's camera tiles; the name and
   state over it on a shade, and round glass buttons that a pointer reveals on hover (always there for touch).
   camera.js swaps the snapshot for the live video once it plays. */
.camera-card { gap: var(--space-12); }
.camera-view {
  position: relative; flex: none; margin: -8px -10px 0; aspect-ratio: 16 / 9; overflow: hidden; isolation: isolate;
  border-radius: calc(var(--radius) - 8px); background: #10131a; color: #fff;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.06);
}
.camera-view > video, .camera-view > .camera-still {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block;
  transition: opacity var(--normal) var(--ease-out);
}
.camera-view > video { opacity: 0; }
.camera-view.is-live > video { opacity: 1; }
.camera-view > .camera-still:not([src]) { opacity: 0; }
.camera-view:fullscreen { margin: 0; border-radius: 0; aspect-ratio: auto; }
.camera-view:fullscreen > video, .camera-view:fullscreen > .camera-still { object-fit: contain; }
.camera-top, .camera-controls { position: absolute; left: 0; right: 0; display: flex; align-items: center; gap: var(--space-8); padding: var(--space-10) var(--space-12); z-index: 1; }
.camera-top {
  top: 0; flex-wrap: wrap; padding-bottom: 26px;
  background: linear-gradient(180deg, rgba(0, 0, 0, 0.55), rgba(0, 0, 0, 0));
}
.camera-name {
  flex: 1 1 auto; min-width: 0; font-size: var(--text-base); font-weight: var(--weight-semibold); letter-spacing: -0.01em;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-shadow: 0 1px 3px rgba(0, 0, 0, 0.45);
}
.camera-badges { display: flex; flex-wrap: wrap; gap: var(--space-6); justify-content: flex-end; }
.camera-badge {
  display: inline-flex; align-items: center; gap: 5px; padding: 2px var(--space-8); border-radius: var(--radius-pill); white-space: nowrap;
  font-size: var(--text-2xs); font-weight: var(--weight-semibold); letter-spacing: 0.02em; font-variant-numeric: tabular-nums;
  background: rgba(20, 22, 28, 0.45); -webkit-backdrop-filter: blur(12px) saturate(160%); backdrop-filter: blur(12px) saturate(160%);
  border: 1px solid rgba(255, 255, 255, 0.16);
}
.camera-badge.live::before, .camera-badge.recording::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: #ff453a; }
.camera-badge.live { text-transform: uppercase; }
.camera-badge.recording::before { background: transparent; box-shadow: inset 0 0 0 1.5px #ff453a; }
.camera-badge.motion { background: rgba(255, 204, 0, 0.9); color: #2b2100; border-color: transparent; }
.camera-badge.ring { background: color-mix(in srgb, var(--accent) 92%, transparent); color: #fff; border-color: transparent; }
.camera-badge.ring.fresh { animation: camera-ring 1.2s var(--ease-out) 2; }
@keyframes camera-ring { 0%, 100% { transform: scale(1); } 30% { transform: scale(1.12); } }
.camera-view.motion { box-shadow: inset 0 0 0 2px rgba(255, 204, 0, 0.9); }
.camera-controls {
  bottom: 0; justify-content: flex-end; padding-top: var(--space-24);
  background: linear-gradient(0deg, rgba(0, 0, 0, 0.4), rgba(0, 0, 0, 0));
  transition: opacity var(--normal) var(--ease-out);
}
.camera-button {
  display: inline-grid; place-items: center; width: 34px; height: 34px; padding: 0; border-radius: 50%; color: #fff;
  background: rgba(30, 32, 40, 0.42); -webkit-backdrop-filter: blur(14px) saturate(160%); backdrop-filter: blur(14px) saturate(160%);
  border: 1px solid rgba(255, 255, 255, 0.18); box-shadow: none;
}
.camera-button:hover { background: rgba(30, 32, 40, 0.62); }
.camera-button svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.camera-message {
  position: absolute; inset: 0; display: grid; place-items: center; padding: 48px var(--space-16); text-align: center; z-index: 1;
  font-size: var(--text-sm); font-weight: var(--weight-medium); color: rgba(255, 255, 255, 0.82); background: rgba(10, 12, 18, 0.35);
}
.camera-view:not(.has-still) > .camera-message { background: radial-gradient(80% 80% at 50% 40%, #232836, #10131a); }
/* No picture from the camera: television snow, scan lines over it, the message on top. */
.camera-snow { position: absolute; inset: 0; width: 100%; height: 100%; image-rendering: pixelated; opacity: 0; transition: opacity var(--normal) var(--ease-out); pointer-events: none; }
.camera-view.no-signal > .camera-snow { opacity: 0.5; }
.camera-view.no-signal > .camera-message { background: repeating-linear-gradient(0deg, rgba(0, 0, 0, 0.22) 0 1px, transparent 1px 3px), radial-gradient(80% 80% at 50% 45%, rgba(16, 19, 26, 0.15), rgba(16, 19, 26, 0.7)); text-shadow: 0 1px 3px rgba(0, 0, 0, 0.8); }
.camera-meta { font-size: var(--text-sm); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; margin-top: -2px; }
@media (hover: hover) and (pointer: fine) {
  .camera-controls { opacity: 0; }
  .camera-view:hover > .camera-controls, .camera-view:focus-within > .camera-controls { opacity: 1; }
}
@media (pointer: coarse) { .camera-button { width: 40px; height: 40px; } }
@media (max-width: 640px) { .camera-view { margin: -6px -8px 0; } }
@media (prefers-reduced-motion: reduce) { .camera-badge.ring.fresh { animation: none; } .camera-view > video, .camera-controls { transition: none; } }
@media (prefers-reduced-transparency: reduce) {
  .camera-badge, .camera-button { -webkit-backdrop-filter: none; backdrop-filter: none; background: rgba(20, 22, 28, 0.85); }
}

/* Describe your setup: the Assistant's suggestion for a block, as a diff to review. */
.describe-setup summary { cursor: pointer; list-style: none; display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-4); }
.describe-setup summary strong { white-space: nowrap; }
.describe-note::before { content: "· "; }
.describe-setup summary::-webkit-details-marker { display: none; }
.describe-body { display: grid; gap: var(--space-10); margin-top: var(--space-12); }
.describe-body .actions { display: flex; gap: var(--space-8); }
.describe-result:empty { display: none; }
.describe-result { display: grid; gap: var(--space-10); }
pre.diff { margin: 0; padding: var(--space-10) var(--space-12); border-radius: var(--radius-md); background: var(--field); border: 1px solid var(--line); overflow-x: auto; font: 0.8125rem/1.45 var(--mono); }
pre.diff .diff-add { color: var(--ok); background: color-mix(in srgb, var(--ok) 12%, transparent); display: block; }
pre.diff .diff-remove { color: var(--error); background: color-mix(in srgb, var(--error) 12%, transparent); display: block; }
pre.diff .diff-same { display: block; opacity: 0.7; }

/* Rooms, Quick Controls, scenes and notifications (home.js). */
.accessory-sections { display: grid; }
.suggest { margin: 0 0 var(--space-14); }
.suggest h2 { display: flex; align-items: center; gap: var(--space-6); }
.suggest-rooms { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 240px), 1fr)); gap: var(--space-4) var(--space-20); }
.suggest .toggle { margin: var(--space-6) 0; }
.suggest.ai-busy { opacity: 0.8; }
.quick { margin: 0 0 var(--space-6); }
.quick .service-name { margin-top: var(--space-16); }
.quick-scenes { display: flex; flex-wrap: wrap; gap: var(--space-10); margin: 0 0 var(--space-14); }
.scene-run { display: inline-flex; align-items: center; gap: var(--space-10); padding: var(--space-6) var(--space-16) var(--space-6) var(--space-6); border-radius: var(--radius-pill); font-weight: var(--weight-medium); }
.scene-run .tile { width: 30px; height: 30px; border-radius: 50%; }
.scene-run.busy { opacity: 0.6; }
.scene-card .server-head > button { flex: none; }
/* Moods: the rooms as chips, what plays, the Assistant's box, the collection as pills with their colours. Pills and chips
   are controls: no text selection or callout on a long press, press feedback at once, the lift on hover only with a
   mouse (a tap would leave it stuck). On a phone each kind is a row that swipes sideways and snaps, so the card fits a
   screen and what a tap starts shows beside the finger. */
.mood-card { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-14); }
.mood-rooms, .mood-buttons { display: flex; gap: var(--space-8); }
.mood-rooms { flex-wrap: wrap; }
.mood-buttons { flex-wrap: wrap; }
.mood-room, .mood-button { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
.mood-room { padding: 7px var(--space-14); font-size: var(--text-md); }
.mood-room[aria-pressed="true"] { background: linear-gradient(180deg, var(--accent-fill-top), var(--accent-fill)); color: var(--accent-text); border-color: transparent; }
.mood-button {
  display: inline-flex; align-items: center; gap: var(--space-10); flex: none; min-height: 44px; padding: var(--space-6) var(--space-16) var(--space-6) var(--space-6);
  transition: transform var(--fast) var(--ease-out), box-shadow var(--normal) var(--ease-out);
}
.mood-button:active:not(:disabled), .mood-room:active { transform: scale(0.96); transition-duration: 80ms; }
.mood-button.playing { box-shadow: 0 0 0 2px var(--accent), var(--shadow-control); }
.mood-button.busy::after { margin-left: 0; }
.mood-swatch { width: 32px; height: 32px; border-radius: var(--radius-sm); flex: none; }
.mood-group .service-name { margin: 0 0 var(--space-8); }
.mood-collection { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-16); }
.mood-describe { display: flex; gap: var(--space-8); }
.mood-describe input { flex: 1; min-width: 0; }
.mood-create { display: inline-flex; align-items: center; gap: var(--space-6); flex: none; white-space: nowrap; }
.mood-running { display: grid; gap: var(--space-8); }
.mood-running:empty { display: none; }
.mood-run {
  display: flex; align-items: center; gap: var(--space-12); padding: var(--space-8) var(--space-8) var(--space-8) var(--space-10); border-radius: var(--radius-lg); background: var(--material-thin); border: 1px solid var(--line);
  transition: opacity var(--normal) var(--ease-out), transform var(--normal) var(--ease-out);
}
@starting-style { .mood-run { opacity: 0; transform: translateY(-4px); } }
.mood-run-text { flex: 1; min-width: 0; display: grid; }
.mood-run-text .muted { font-size: var(--text-sm); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mood-stop { flex: none; }
.mood-card .status-line { margin: 0; }
.mood-card .status-line:empty { display: none; }
/* A phone: rooms and each kind of mood scroll sideways from edge to edge of the card, snapping to a pill; the input stays
   at 16px so iOS does not zoom into it. */
@media (max-width: 640px) {
  .mood-rooms, .mood-buttons {
    flex-wrap: nowrap; overflow-x: auto; overscroll-behavior-x: contain; scroll-snap-type: x proximity; scrollbar-width: none;
    margin: 0 -20px; padding: 2px var(--space-20) var(--space-6); scroll-padding: 0 20px;
    -webkit-mask-image: linear-gradient(90deg, transparent, #000 14px, #000 calc(100% - 22px), transparent);
    mask-image: linear-gradient(90deg, transparent, #000 14px, #000 calc(100% - 22px), transparent);
  }
  .mood-rooms::-webkit-scrollbar, .mood-buttons::-webkit-scrollbar { display: none; }
  .mood-room, .mood-button { flex: none; scroll-snap-align: start; }
}
@media (pointer: coarse) { .mood-describe input { font-size: 16px; } }
@media (prefers-reduced-motion: reduce) { .mood-run { transition: none; } }
.location summary { cursor: pointer; }
.location { margin-top: var(--space-14); }
.scene-editor h2 { margin: 22px 0 2px; font-size: var(--text-xl); }
.scene-editor h2 + p { margin: 0 0 var(--space-8); font-size: var(--text-md); }
.editor-list { display: grid; gap: var(--space-8); }
.editor-row { display: flex; align-items: center; gap: var(--space-8); flex-wrap: wrap; padding: var(--space-8) var(--space-10); border-radius: var(--radius-md); background: var(--material-thin); border: 1px solid var(--line); }
.editor-row select, .editor-row input[type="text"], .editor-row input[type="number"], .editor-row input[type="time"] { width: auto; min-width: 0; max-width: 100%; }
.editor-row input[type="number"] { width: 7em; }
.editor-row .grow { flex: 1; }
.group-inline { display: inline-flex; align-items: center; gap: var(--space-8); flex-wrap: wrap; }
.value-slot { display: inline-flex; }
.days { display: inline-flex; gap: var(--space-4); flex-wrap: wrap; }
.day { position: relative; display: inline-grid; place-items: center; width: 34px; height: 30px; border-radius: var(--radius-sm); border: 1px solid var(--line); background: var(--control); font-size: var(--text-xs); font-weight: var(--weight-semibold); cursor: pointer; }
.day input { position: absolute; inset: 0; opacity: 0; margin: 0; cursor: pointer; }
.day:has(input:checked) { background: var(--accent-fill); color: var(--accent-text); border-color: transparent; }
.day:has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }
.icon-button:not(.menu-button) { width: 32px; height: 32px; padding: 0; display: inline-grid; place-items: center; border-radius: 50%; flex: none; }
.icon-button:not(.menu-button) svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.push .actions { margin-top: var(--space-4); flex-wrap: wrap; }
.scene-editor .actions { flex-wrap: wrap; }
.scene-editor .actions > button { flex: none; white-space: nowrap; }
.scene-editor .actions > select { width: auto; flex: 0 1 auto; min-width: 0; }
/* A phone: what the row is about (the accessory) across, the rest under it, Remove at the right end. */
@media (max-width: 640px) {
  .editor-row { padding: var(--space-8); }
  .editor-row select { flex: 1 1 40%; }
  .editor-row > select:first-child { flex-basis: 100%; }
  .editor-row > .icon-button:last-child { margin-left: auto; }
}

/* Settings (admin.js): its pages as a segmented row of links, lists of rows in one card, the confirmation and
   history sheets, the audit table. */
a.link { color: var(--accent-ink); text-decoration: none; padding: var(--space-4) var(--space-6); }
a.button.primary { background: linear-gradient(180deg, var(--accent-fill-top), var(--accent-fill)); color: var(--accent-text); border-color: rgba(255, 255, 255, 0.4); box-shadow: 0 8px 20px color-mix(in srgb, var(--accent) 35%, transparent), inset 0 1px 0 rgba(255, 255, 255, 0.5); }
a.link:hover { text-decoration: underline; }
.subnav { margin: -6px 0 var(--space-18); max-width: 100%; overflow-x: auto; scrollbar-width: none; }
.subnav::-webkit-scrollbar { display: none; }
.group a { color: var(--text); text-decoration: none; padding: 5px 13px; border-radius: var(--radius-pill); white-space: nowrap; transition: background-color var(--fast) var(--ease-out); }
.group a:hover:not(.on) { background: var(--material-thin); }
.group a.on { background: linear-gradient(180deg, var(--accent-fill-top), var(--accent-fill)); color: var(--accent-text); }
.subnav a { display: inline-flex; align-items: center; gap: var(--space-6); }
.subnav svg { flex: none; width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.subnav svg.sparkle { stroke: none; }
/* A phone: the pages across the width, each its glyph over its name, as a tab bar. */
@media (max-width: 640px) {
  .subnav { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); width: 100%; border-radius: var(--radius); }
  .subnav a { display: grid; justify-items: center; gap: 3px; padding: 7px 0 var(--space-6); border-radius: var(--radius-lg); font-size: 0.65625rem; font-weight: var(--weight-semibold); letter-spacing: -0.02em; touch-action: manipulation; -webkit-user-select: none; user-select: none; }
  .subnav a span { max-width: 100%; overflow: hidden; text-overflow: ellipsis; }
  .subnav svg { width: 20px; height: 20px; }
}
.card.rows { padding: var(--space-4) 0; }
.rows > .row, .rows > .row-block > .row { display: flex; align-items: center; gap: var(--space-12); padding: var(--space-10) var(--space-16); min-width: 0; }
.rows > * + * { border-top: 1px solid var(--line); }
.rows .row > .who { flex: 1; min-width: 0; }
.rows .row > .who > * { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.row-detail { padding: 0 var(--space-16) var(--space-12); }
.row-detail:empty { display: none; }
.row-block > div:not(.row):not(:empty) { padding: 0 var(--space-16) var(--space-12); }
pre.diff .diff-fold { display: block; color: var(--muted); font-style: italic; }
.notice-list p { margin: var(--space-4) 0; font-size: var(--text-md); }
.secret-note { margin: 0 0 var(--space-8); font-size: var(--text-sm); color: var(--warn); }
.admin-dialog { margin: auto; width: min(520px, calc(100% - 24px)); max-height: calc(100% - 48px); overflow: auto; padding: var(--space-20) 22px; color: var(--text); background-color: var(--material-solid); }
.admin-dialog.wide { width: min(980px, calc(100% - 24px)); }
.admin-dialog::backdrop { background: rgba(10, 14, 24, 0.35); -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px); }
.admin-dialog h2 { margin: 0 0 var(--space-10); }
.admin-dialog p { margin: 0 0 var(--space-10); }
.admin-dialog .actions { justify-content: flex-end; }
.admin-dialog .page-head { margin: 0 0 var(--space-14); }
.admin-dialog .chart-grid.loading { opacity: 0.55; }
.data-table { border-collapse: collapse; font-size: var(--text-sm); width: 100%; }
.data-table th, .data-table td { padding: var(--space-6) var(--space-12) var(--space-6) 0; text-align: left; vertical-align: top; border-bottom: 1px solid var(--line); }
.data-table th { color: var(--muted); font-weight: var(--weight-medium); position: sticky; top: 0; background: var(--material-solid); }
.data-table td:first-child { white-space: nowrap; font-variant-numeric: tabular-nums; }
.card > .table-scroll { overflow-x: auto; max-height: 70vh; overflow-y: auto; }
.audit-details { max-width: 420px; }
.audit-details code { display: block; font: 0.75rem/1.4 var(--mono); color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@media (prefers-reduced-transparency: reduce) { .admin-dialog::backdrop { -webkit-backdrop-filter: none; backdrop-filter: none; background: rgba(10, 14, 24, 0.6); } }
@media (max-width: 640px) {
  .rows > .row, .rows > .row-block > .row { padding: var(--space-10) var(--space-12); }
  .admin-dialog { padding: var(--space-16); }
  .audit-details { max-width: 240px; }
}

/* ---- Appearance: a theme chosen in the web UI (/appearance) rather than the system's, and wallpapers ---------
   common.js sets data-theme and data-wallpaper on the root element; Automatic leaves the system to decide. */
/* The backdrops behind the glass: soft gradients of the UI's own, or the user's image over the page colour. */
:root[data-wallpaper] body::before { background-size: cover; background-position: center; }
:root[data-wallpaper="aurora"] body::before, [data-swatch="aurora"] { background: url("/wallpaper-aurora.webp") center / cover no-repeat, var(--bg); }
:root[data-wallpaper="sunset"] body::before, [data-swatch="sunset"] { background: url("/wallpaper-sunset.webp") center / cover no-repeat, var(--bg); }
:root[data-wallpaper="ocean"] body::before, [data-swatch="ocean"] { background: url("/wallpaper-ocean.webp") center / cover no-repeat, var(--bg); }
:root[data-wallpaper="forest"] body::before, [data-swatch="forest"] { background: url("/wallpaper-forest.webp") center / cover no-repeat, var(--bg); }
:root[data-wallpaper="graphite"] body::before, [data-swatch="graphite"] { background: url("/wallpaper-graphite.webp") center / cover no-repeat, var(--bg); }
:root[data-wallpaper="custom"] body::before, [data-swatch="custom"] { background: var(--wallpaper-image, none) center / cover no-repeat, var(--bg); }
[data-swatch="none"] {
  background: radial-gradient(55% 45% at 8% 6%, var(--bg-warm) 0%, transparent 62%), radial-gradient(50% 42% at 92% 16%, var(--bg-cool) 0%, transparent 60%),
    radial-gradient(60% 55% at 50% 100%, var(--bg-mint) 0%, transparent 65%), var(--bg);
}
.wallpapers { display: grid; grid-template-columns: repeat(auto-fill, minmax(104px, 1fr)); gap: var(--space-10); margin: var(--space-12) 0; }
.wallpaper-choice { display: flex; flex-direction: column; align-items: stretch; gap: var(--space-6); padding: var(--space-6) var(--space-6) var(--space-8); border-radius: calc(var(--radius-sm) + 6px); font-weight: var(--weight-medium); }
.wallpaper-choice.on { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent); }
.wallpaper-swatch { display: block; height: 64px; border-radius: var(--radius-sm); border: 1px solid var(--line); }
/* Your own image's tile, with a ✕ on its corner that removes the image. */
.wallpaper-own { position: relative; display: grid; }
.wallpaper-remove {
  position: absolute; top: -7px; right: -7px; width: 26px; height: 26px; min-height: 0; padding: 0; border-radius: 50%;
  display: grid; place-items: center; background: var(--control); color: var(--text);
}
.wallpaper-remove svg { width: 13px; height: 13px; fill: none; stroke: currentColor; stroke-width: 2.4; stroke-linecap: round; }
.wallpaper-remove:hover:not(:disabled) { color: var(--error); }
/* A finger's worth of target around the small badge. */
.wallpaper-remove::after { content: ""; position: absolute; inset: -8px; border-radius: 50%; }
.appearance { display: grid; gap: var(--space-16); }
.appearance .group { margin-top: var(--space-10); flex-wrap: wrap; }
@media (max-width: 640px) {
  /* The choices fill the card's width; one that needs two rows (the languages) stretches each row's buttons to the
     edge, so neither row is ragged; a button never shrinks below its text, it moves to the next row. */
  .appearance .group { display: flex; border-radius: var(--radius-lg); }
  .appearance .group button { flex: 1 1 5.5rem; padding: 7px var(--space-10); border-radius: var(--radius-md); }
  /* The save message under the cards stays clear of the floating menu button. */
  .appearance + .status-line { margin-inline-end: calc(70px + env(safe-area-inset-right)); }
}
.link-card { display: flex; align-items: center; gap: var(--space-14); margin-top: var(--space-16); padding: var(--space-16) var(--space-18); color: var(--text); text-decoration: none; }
.link-card svg { width: 24px; height: 24px; fill: none; stroke: var(--accent); stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }

/* ---- The Status page's widgets, Customise, and the daily digest ------------------------------------------- */
.dash-widget { min-width: 0; }
.page-foot { justify-content: center; margin: var(--space-24) 0 var(--space-8); }
.page-foot svg { width: 17px; height: 17px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; vertical-align: -3px; }
.tile.tone-ai { background: var(--material-solid); border: 1px solid var(--line); }
.tile.tone-ai .sparkle { width: 24px; height: 24px; stroke: none; }
.digest-card { margin-bottom: var(--space-18); }
.digest-body { margin: var(--space-12) 0 var(--space-4); }
.digest-body .md > :first-child { margin-top: 0; }
.digest-card.writing { box-shadow: 0 0 0 1.5px #bf5af2, 0 10px 30px rgba(191, 90, 242, 0.25); }
@media (prefers-reduced-motion: no-preference) { .digest-card { transition: box-shadow var(--normal) var(--ease-out); } }

/* ---- Log Doctor, under the log --------------------------------------------------------------------------- */
.log-doctor { margin-top: var(--space-16); }
.log-doctor .ai-note { margin: var(--space-10) 0 0; font-size: var(--text-sm); }
.log-card .editor-bar .ai-button { margin: 0; }

/* ---- The Assistant's settings: test, usage, budgets -------------------------------------------------------- */
.assistant-settings { margin-bottom: var(--space-16); padding: var(--space-16) var(--space-18); }
.assistant-settings .server-head > button { margin-left: auto; }
.test-result { margin: var(--space-8) 0 0; }
.test-result:empty { display: none; }
.usage .stats { margin: var(--space-12) 0; }
.budget-meters { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: var(--space-12) var(--space-18); margin: var(--space-8) 0 var(--space-12); }
.budget-label { display: flex; justify-content: space-between; gap: var(--space-8); font-size: var(--text-sm); margin-bottom: var(--space-6); color: var(--muted); }
.budget-label b { color: var(--text); font-weight: var(--weight-semibold); }
.budget-meter .gauge-fill { background: var(--ok); }
.budget-meter.near .gauge-fill { background: var(--warn); }
.budget-meter.over .gauge-fill { background: var(--error); }
.budget-editor .fields { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: var(--space-10); margin: var(--space-10) 0; }

/* ---- The chat's earlier conversations ---------------------------------------------------------------------- */
.chat-history h2 { font-size: var(--text-lg); margin: var(--space-4) 0 var(--space-10); }
.chat-history-list { display: grid; gap: var(--space-6); margin-bottom: var(--space-10); }
.chat-history-row { display: flex; align-items: center; gap: var(--space-6); border-radius: var(--radius-md); border: 1px solid var(--line); background: var(--material-thin); }
.chat-history-row.current { border-color: var(--accent); }
.chat-history-open { flex: 1; min-width: 0; display: grid; gap: 2px; text-align: left; border: 0; background: none; box-shadow: none; padding: 9px var(--space-12); border-radius: var(--radius-md); }
.chat-history-open strong { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chat-history-open .muted { font-size: var(--text-xs); }
.chat-icon svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
/* Text on a wallpaper, outside the glass (a page's title, a section's heading and line, a "Show as a table"): on a
   plate of the header's material, in the theme's own colours. White with a shadow faded into a light wallpaper
   (Sunset's yellow), and the theme's dark text into a dark one. */
:root[data-wallpaper] main .page-head,
:root[data-wallpaper] main :is(h2, .section-head, details.more > summary, section > p.muted):not(:is(.card, .log, .banner, .section-head, .page-head, dialog, .menu) *) {
  width: fit-content; max-width: 100%; padding: var(--space-6) var(--space-14); border-radius: var(--radius-md);
  background-color: var(--material-thick);
  -webkit-backdrop-filter: blur(var(--blur)) saturate(180%); backdrop-filter: blur(var(--blur)) saturate(180%);
  box-shadow: var(--shadow-control), inset 0 0 0 1px var(--edge);
}
:root[data-wallpaper] main .page-head { width: auto; padding: var(--space-12) var(--space-14) var(--space-12) var(--space-20); border-radius: var(--radius); align-items: center; }
:root[data-wallpaper] main :is(h2, details.more > summary):not(:is(.card, .log, .banner, .section-head, .page-head, dialog, .menu) *) { padding: 5px var(--space-12); border-radius: var(--radius-md); }

/* Source filters use the same switch as accessory controls, with a separate count badge. */


/* Quiet rounded slots and gutter dots: the pattern follows the real grid's responsive pitch. */
.wall.editing {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='186' height='74' viewBox='0 0 186 74'%3E%3Crect x='1' y='1' width='174' height='62' rx='13' fill='%238392aa' fill-opacity='.11' stroke='%238392aa' stroke-opacity='.22' stroke-dasharray='2 4'/%3E%3Ccircle cx='181' cy='69' r='1.2' fill='%238392aa' fill-opacity='.38'/%3E%3C/svg%3E");
  background-size: calc(var(--unit) + var(--unit-gap)) calc(var(--tile-row) + var(--unit-gap));
  background-position: 0 0;
  border-radius: var(--radius);
  padding-bottom: calc(var(--tile-row) + var(--unit-gap));
}
.wall.editing > .widget:not(.lifted):not(.drag-slot) { outline: 1px solid var(--edge-light); outline-offset: -1px; }
.wall > .drag-slot { border: 1.5px dashed var(--accent); background: color-mix(in srgb, var(--accent) 10%, var(--material-thin)); box-shadow: inset 0 0 0 4px color-mix(in srgb, var(--accent) 5%, transparent); }
.resize-handle { position: absolute; right: 3px; bottom: 3px; z-index: 4; width: 32px; height: 32px; min-height: 0; padding: 0; border: 0; border-radius: 50%; background: var(--control); color: var(--muted); cursor: nwse-resize; touch-action: none; box-shadow: var(--shadow-control); font-size: 0; }
.resize-handle::after { content: ""; position: absolute; width: 12px; height: 2px; left: 10px; top: 14px; border-radius: 2px; background: currentColor; box-shadow: 0 5px 0 -0.2px currentColor; transform: rotate(-45deg); }
.resize-handle:hover, .resize-handle:focus-visible { transform: none; color: var(--accent-ink); background: var(--material-solid); }
@media (prefers-contrast: more) {
  .wall.editing { outline: 1px dashed var(--muted); }
}
.wall.resizing, .wall.resizing > .widget { cursor: nwse-resize; }

.page-head .tools:has(> .search) { flex-wrap: wrap; }

/* Switch choices inside the standard action menu. The menu item owns the accessible checked state. */
.menu-toggle { position: relative; flex: 0 0 36px; width: 36px; height: 22px; margin-left: auto; border-radius: var(--radius-md); background: var(--track); box-shadow: inset 0 1px 2px rgba(0,0,0,.12); transition: background-color 160ms; }
.menu-toggle > span { position: absolute; left: 2px; top: 2px; width: 18px; height: 18px; border-radius: 50%; background: #fff; box-shadow: 0 1px 3px rgba(0,0,0,.2); transition: transform 160ms; }
.menu [aria-checked="true"] > .menu-toggle { background: var(--accent); }
.menu [aria-checked="true"] > .menu-toggle > span { transform: translateX(14px); }
@media (prefers-reduced-motion: reduce) { .menu-toggle, .menu-toggle > span { transition: none; } }

.menu-drag-handle { flex: none; width: 24px; text-align: center; font-size: 23px; line-height: 24px; color: var(--muted); cursor: grab; touch-action: none; user-select: none; }
.menu [role]:hover > .menu-drag-handle { color: inherit; }
.menu .menu-dragging { background: var(--material-solid); outline: 1px solid var(--accent); cursor: grabbing; }

/* Notifications: delivery setup and event preferences have distinct, scannable columns. */
.notification-layout { display: grid; grid-template-columns: minmax(0, 1.35fr) minmax(310px, 1fr); gap: var(--space-24); align-items: start; }
.notification-delivery { min-width: 0; }
.notification-delivery > .section-head { margin: 0 0 var(--space-14); }
.notification-channels { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-16); align-items: start; }
.notification-browser { grid-column: 1 / -1; }
.notification-channel { min-width: 0; padding: var(--space-20); }
.notification-channel .server-head .tile { width: 40px; height: 40px; border-radius: var(--radius-md); }
.notification-channel .note { font-size: var(--text-sm); line-height: 1.6; margin: var(--space-14) 0 var(--space-18); }
.notification-channel .card-foot { margin-top: var(--space-16); }
.notification-state { display: inline-flex; align-items: center; gap: var(--space-6); color: var(--muted); font-size: var(--text-xs); font-weight: var(--weight-semibold); }
.notification-state::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; opacity: .5; }
.notification-state.active { color: var(--ok); }
.notification-state.active::before { opacity: 1; }
.notification-setup { border-top: 1px solid var(--line); padding-top: var(--space-12); }
.notification-setup summary { cursor: pointer; font-size: var(--text-sm); font-weight: var(--weight-semibold); color: var(--text); padding: var(--space-4) 0; }
.notification-fields { padding-top: var(--space-12); }
.notification-fields input { min-width: 0; width: 100%; }
.notification-events { padding: var(--space-24); }
.notification-events > h2 { margin: 0 0 var(--space-6); }
.notification-events > p { margin: 0 0 var(--space-20); font-size: var(--text-sm); line-height: 1.6; }
.notification-event { display: flex; align-items: center; gap: var(--space-18); padding: 15px 0; margin: 0; border-bottom: 1px solid var(--line); cursor: pointer; font-size: var(--text-sm); line-height: 1.5; }
.notification-event .who { flex: 1; min-width: 0; }
.notification-event .help { display: block; margin-top: var(--space-4); font-size: var(--text-xs); }
.notification-event .switch { display: inline-block; width: 42px; height: 26px; }
.notification-event .switch span::before { width: 20px; height: 20px; }
.notification-event .switch input:checked + span::before { transform: translateX(16px); }
.notification-digest { padding-top: var(--space-18); }
.notification-digest label { margin-bottom: 0; }
.notification-events > .notification-limit { font-size: var(--text-xs); margin: var(--space-18) 0 0; }
.notification-save { position: sticky; bottom: 16px; z-index: 5; margin-top: var(--space-24); padding: var(--space-12) var(--space-16); background: var(--material-thick); border: 1px solid var(--edge); border-radius: var(--radius-lg); box-shadow: var(--shadow); backdrop-filter: blur(20px); display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-12); }
.notification-save > :first-child { flex: 1; margin: 0; }
@media (max-width: 960px) { .notification-layout { grid-template-columns: 1fr; } }
@media (max-width: 540px) { .notification-channels { grid-template-columns: 1fr; } .notification-events { padding: var(--space-20); } .notification-save { bottom: 84px; } .notification-save > button { flex: 1 1 auto; } }
.notification-channel { gap: 0; }
.notification-channel .push > p:empty { display: none; }
.notification-channel .server-head strong { white-space: normal; }

.webhook-headers { margin-top: var(--space-18); padding-top: var(--space-14); border-top: 1px solid var(--line); }
.webhook-headers > strong { font-size: var(--text-sm); }
.webhook-header-rows { display: grid; gap: var(--space-8); margin: var(--space-10) 0; }
.webhook-header-row { display: grid; grid-template-columns: minmax(0,1fr) minmax(0,1fr) 30px; gap: var(--space-6); align-items: center; }
.webhook-header-row > button { padding: 0; width: 30px; min-height: 32px; }
.webhook-header-row input { padding-inline: var(--space-8); font-size: var(--text-xs); }

.webhook-auth-picker { display: flex; align-items: center; justify-content: space-between; gap: var(--space-12); width: 100%; text-align: left; border-radius: var(--radius-md); }
.webhook-auth-picker > svg { width: 16px; height: 16px; flex: none; fill: none; stroke: currentColor; stroke-width: 1.8; }

.assistant-welcome { max-width: 680px; margin: var(--space-24) auto; padding: clamp(var(--space-24), 5vw, 40px); }
.assistant-welcome h2 { margin: var(--space-20) 0 var(--space-8); }
.assistant-welcome > p { margin: 0; }
.assistant-setup-note { margin: var(--space-24) 0; padding: var(--space-18); border: 1px solid var(--border); border-radius: var(--radius-md); }
.assistant-setup-note p { margin: var(--space-6) 0 0; line-height: 1.6; }
.assistant-setup-example { margin-top: var(--space-24); }
.assistant-setup-example summary { cursor: pointer; font-size: var(--text-md); }
.assistant-setup-example p { font-size: var(--text-md); line-height: 1.6; }

/* Backup creation and recovery share a compact, responsive workspace. */
.backup-actions-grid { display: grid; grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr); gap: var(--space-20); margin: var(--space-24) 0 32px; }
.backup-actions-grid > .card { margin: 0; padding: var(--space-24); min-width: 0; }
.backup-create .server-head { align-items: flex-start; }
.backup-create .server-head .muted { margin-top: var(--space-6); line-height: 1.6; white-space: normal; overflow: visible; }
.backup-create .facts { margin: 22px 0; gap: var(--space-16); }
.backup-create .fact.wide { padding-top: var(--space-16); border-top: 1px solid var(--line); }
.backup-create .fact.wide b { overflow-wrap: anywhere; }
.backup-create .actions { margin-top: var(--space-24); flex-wrap: wrap; }
.backup-create .status-line:empty { display: none; }
.backup-restore { display: flex; flex-direction: column; gap: var(--space-18); }
.backup-restore h2 { margin: 0; font-size: var(--text-lg); }
.backup-restore-help summary { cursor: pointer; color: var(--muted); font-size: var(--text-md); }
.backup-restore-help p { line-height: 1.6; font-size: var(--text-md); }
.backup-restore .drop-zone { flex: 1; min-height: 142px; margin: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--space-14); border-radius: var(--radius-md); background: var(--material-thin); line-height: 1.6; }
.backup-drop-icon svg { width: 28px; height: 28px; color: var(--accent); }
@media (max-width: 900px) { .backup-actions-grid { grid-template-columns: 1fr; } }

.audit-filters { margin: var(--space-24) 0 var(--space-20); padding: var(--space-20); }
.audit-filter-grid { display: grid; grid-template-columns: 1fr 1fr 1.3fr 1.3fr; gap: var(--space-16); }
.audit-filter-grid label { display: flex; flex-direction: column; gap: var(--space-8); min-width: 0; }
.audit-filter-grid label > span { color: var(--muted); font-size: var(--text-xs); font-weight: var(--weight-semibold); }
.audit-filter-grid .search { width: 100%; min-width: 0; }
.audit-picker { display: flex; justify-content: space-between; align-items: center; gap: var(--space-10); min-height: 38px; text-align: left; }
.audit-picker svg { width: 14px; height: 14px; }
.audit-filter-footer { display: flex; align-items: center; justify-content: space-between; margin-top: var(--space-16); padding-top: var(--space-14); border-top: 1px solid var(--line); font-size: var(--text-sm); }
.audit-results { padding: 0; overflow: hidden; }
.audit-results .data-table th, .audit-results .data-table td { padding: var(--space-16); }
.audit-results .data-table th { z-index: 1; font-size: var(--text-xs); }
.audit-results .data-table tbody tr:hover { background: var(--material-thin); }
.audit-results .data-table td.mono { overflow-wrap: anywhere; min-width: 160px; }
.audit-results .data-table td .muted { margin-top: var(--space-4); }
.audit-results .note { padding: var(--space-12) var(--space-16); margin: 0; overflow-wrap: anywhere; font-size: var(--text-xs); }
.audit-details summary { cursor: pointer; color: var(--accent); white-space: nowrap; }
.audit-details pre.json { margin-top: var(--space-10); min-width: 220px; max-width: 360px; white-space: pre-wrap; overflow-wrap: anywhere; }
@media (max-width: 1000px) { .audit-filter-grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 460px) { .audit-filter-grid { grid-template-columns: 1fr; } }

.child-bridge-toggle { display: flex; align-items: center; gap: var(--space-12); margin: var(--space-24) 0; }
.child-bridge-fields { display: grid; grid-template-columns: 2fr 1fr; gap: var(--space-16); margin-bottom: var(--space-20); }
.child-bridge-fields label { display: flex; flex-direction: column; gap: var(--space-8); min-width: 0; }
.child-bridge-fields input { width: 100%; }

/* Standalone checkbox inputs share the accessory switch's visual language. */
input[type="checkbox"]:not(.switch input):not(.day input) {
  -webkit-appearance: none; appearance: none; position: relative;
  width: 48px; min-width: 48px; height: 28px; padding: 0; margin: 0;
  flex: none; vertical-align: middle; border: 1px solid var(--edge); border-radius: var(--radius-md);
  background: rgba(120, 128, 142, 0.35); cursor: pointer;
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.15);
  transition: background-color var(--normal) var(--ease-out), box-shadow var(--normal) var(--ease-out);
}
input[type="checkbox"]:not(.switch input):not(.day input)::before {
  content: ""; position: absolute; width: 22px; height: 22px; left: 2px; top: 2px;
  border-radius: 50%; background: linear-gradient(180deg, #fff, #eef0f4);
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.25);
  transition: transform var(--normal) var(--ease-out);
}
input[type="checkbox"]:not(.switch input):not(.day input):checked { background: var(--accent); }
input[type="checkbox"]:not(.switch input):not(.day input):checked::before { transform: translateX(20px); }
/* Mixed (a group, some on): half lit, the thumb between. */
input[type="checkbox"]:not(.switch input):not(.day input):indeterminate { background: color-mix(in srgb, var(--accent) 45%, rgba(120, 128, 142, 0.35)); }
input[type="checkbox"]:not(.switch input):not(.day input):indeterminate::before { transform: translateX(10px); }
input[type="checkbox"]:not(.switch input):not(.day input):focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
input[type="checkbox"]:not(.switch input):not(.day input):disabled { opacity: .45; cursor: not-allowed; }
@media (prefers-reduced-motion: reduce) {
  input[type="checkbox"]:not(.switch input):not(.day input), input[type="checkbox"]:not(.switch input):not(.day input)::before { transition: none; }
}
@media (forced-colors: active) {
  input[type="checkbox"]:not(.switch input):not(.day input) { border-color: ButtonText; }
  input[type="checkbox"]:not(.switch input):not(.day input)::before { background: ButtonText; }
  input[type="checkbox"]:not(.switch input):not(.day input):checked { background: Highlight; }
}

/* Keep log filtering separate from stream and export controls. */
.log-filter-panel { padding: var(--space-20); display: flex; flex-direction: column; gap: var(--space-18); }
.log-level-row { display: flex; align-items: center; justify-content: space-between; gap: var(--space-16); flex-wrap: wrap; }
.log-level-row .search { flex: 1; max-width: 440px; min-width: 180px; }
.log-level-row > .group { max-width: 100%; }
.log-scope-row { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); gap: var(--space-16); }
.log-scope-row label, .log-scope-row .log-time { display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-8); min-width: 0; }
.log-scope-row label { align-items: stretch; }
.log-scope-row .log-time { grid-column: 1 / -1; }
.log-scope-row label > span, .log-scope-row .log-time > span { font-size: var(--text-xs); font-weight: var(--weight-semibold); color: var(--muted); }
.log-scope-row select.popup { width: 100%; max-width: none; min-width: 0; }
.log-card .log-action-bar { border-top: 1px solid var(--line); padding: var(--space-12) var(--space-20); gap: var(--space-14); }
.log-action-bar .count { font-variant-numeric: tabular-nums; font-size: var(--text-sm); }
.log-action-bar label.toggle { margin: 0; white-space: nowrap; }
.log-card .log { padding: var(--space-18) var(--space-20); line-height: 1.65; }
.log-card .log > :hover { background: rgba(255, 255, 255, .04); }
/* A level's count beside its name: lighter, digits of one width so the buttons do not shift as lines arrive. */
.log-level-row .log-level-count { margin-inline-start: var(--space-6); font-size: var(--text-sm); font-variant-numeric: tabular-nums; opacity: .6; }
.log-level-row .group button.on .log-level-count { opacity: .85; }
@media (max-width: 640px) {
  /* On a phone the filters take three short rows: the levels (the count under each name), the search with Clear
     filters as an icon (only while there is something to clear), and the two menus side by side, named by their
     aria-label rather than a caption. */
  .log-filter-panel { padding: var(--space-12); gap: var(--space-10); }
  .log-level-row { gap: var(--space-8); }
  .log-level-row > .group { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); flex: 1 1 100%; border-radius: calc(var(--radius-md) + 3px); }
  .log-level-row > .group button { display: flex; flex-direction: column; align-items: center; gap: 1px; min-width: 0; padding: 5px var(--space-4); border-radius: var(--radius-md); line-height: 1.15; }
  .log-level-row .log-level-name { max-width: 100%; overflow: hidden; text-overflow: ellipsis; font-size: var(--text-sm); font-weight: var(--weight-semibold); }
  .log-level-row .log-level-count { margin: 0; font-size: var(--text-2xs); }
  .log-level-row .search { flex: 1 1 0; width: auto; max-width: none; min-width: 0; }
  .log-level-row .clear-filters { flex: none; width: 40px; height: 40px; margin: 0; padding: 0; gap: 0; font-size: 0; }
  .log-level-row .clear-filters:disabled { display: none; }
  .log-scope-row { grid-template-columns: minmax(0, 1fr); gap: var(--space-8); }
  .log-scope-row label { gap: 0; margin: 0; }
  .log-scope-row label > span, .log-scope-row .log-time > span { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  .log-scope-row select.popup { margin: 0; padding-block: var(--space-8); }
  /* The action bar on one row: the count, then Copy as an icon, Follow and the menu (which has Save payloads). */
  .log-card .log-action-bar { padding: var(--space-8) var(--space-12); gap: var(--space-8); }
  .log-card .log-action-bar > .count { flex: 1 1 auto; }
  .log-card .log-action-bar > button.action-with-icon { width: 40px; height: 40px; padding: 0; gap: 0; font-size: 0; flex: none; }
}
}

select:not([multiple]) {
  -webkit-appearance: none; appearance: none; cursor: pointer;
  border-radius: var(--radius-sm); border: 1px solid var(--line); background-color: var(--field);
  padding: 9px 34px 9px var(--space-12); color: var(--text);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 14 14'%3E%3Cpath d='m4 5.5 3 3 3-3' fill='none' stroke='%23858b96' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 12px center;
}
select:not([multiple]):hover { border-color: var(--accent); }
select:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
select:disabled { opacity: .5; cursor: not-allowed; }

.plugin-instances { margin: var(--space-24) 0 36px; gap: var(--space-20); }
.plugin-instance { padding: var(--space-24); }
.plugin-instance .server-head { align-items: flex-start; }
.plugin-instance .server-head .who { min-width: 0; }
.plugin-instance .meta { padding: var(--space-16) 0; gap: var(--space-16); flex-wrap: wrap; }
.plugin-instance .card-foot { gap: var(--space-12); align-items: center; }
.plugin-card-actions { display: flex; align-items: center; gap: var(--space-10); flex: none; }
/* Finding a plugin to add: the search and the order on one row; how many a search keeps under it, with the way back
   (finder-status, shared with the lighting pages' toolbars). */
.catalog-toolbar { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--space-8); align-items: center; margin: 0 0 var(--space-12); }
.catalog-toolbar .search { width: 100%; max-width: none; }
.catalog-toolbar .popup { margin: 0; }
/* A phone: the search takes the row, the order sits under it at its own width. */
@media (max-width: 600px) { .catalog-toolbar { grid-template-columns: minmax(0, 1fr); } .catalog-toolbar .popup { justify-self: start; } }
/* A running plugin's state: a green dot where the other states have a pill. */
.status-dot { flex: none; align-self: center; width: 9px; height: 9px; margin: 0 var(--space-6); border-radius: 50%; background: var(--ok); box-shadow: 0 0 0 3px color-mix(in srgb, var(--ok) 18%, transparent); }
/* The lighting pages' finder (plugin.js `finder`): one row (the search takes the room left), held under the header
   while the list scrolls, in its glass; on a phone, the search over its three menus, scrolling with the page. While a
   search or a filter narrows the list, how many it keeps and Clear filters under it; a section per room that folds. */
.finder {
  position: sticky; top: 84px; z-index: 1; display: grid; grid-template-columns: minmax(160px, 1fr) minmax(0, 200px) auto auto;
  gap: var(--space-8); align-items: center; margin: 0 0 var(--space-14); padding: var(--space-6); border-radius: var(--radius-pill);
  background-color: var(--material-chrome); -webkit-backdrop-filter: blur(var(--blur-thick)) saturate(180%); backdrop-filter: blur(var(--blur-thick)) saturate(180%);
  border: 1px solid var(--edge); box-shadow: var(--shadow-thick), inset 0 1px 0 var(--edge-light);
}
.finder .search { width: 100%; min-width: 0; }
.finder .popup { width: 100%; max-width: none; margin: 0; }
.finder > button { white-space: nowrap; }
@media (max-width: 640px) {
  .finder { position: static; grid-template-columns: repeat(3, minmax(0, 1fr)); padding: 0; border-radius: 0; background: none; border: 0; box-shadow: none; -webkit-backdrop-filter: none; backdrop-filter: none; }
  .finder .search { grid-column: 1 / -1; }
  .finder > button { justify-content: center; }
}
@media (prefers-reduced-transparency: reduce) { .finder { -webkit-backdrop-filter: none; backdrop-filter: none; } }

/* Scenes: a section per room, a tile per scene; a smart scene says so under its name. A room's name folds it away. */
.room { margin-bottom: 22px; }
.room-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-12); margin: 0 0 var(--space-10); }
.room-head h2 { margin: 0; font-size: var(--text-xl); }
.room-fold { display: inline-flex; align-items: center; gap: var(--space-8); min-width: 0; padding: var(--space-4) var(--space-6) var(--space-4) 0; border: 0; background: none; box-shadow: none; color: var(--text); font: inherit; }
.room-fold:active:not(:disabled) { transform: none; opacity: 0.7; }
.room-fold .chevron { width: 8px; height: 8px; flex: none; border-right: 2px solid var(--muted); border-bottom: 2px solid var(--muted); rotate: 45deg; translate: 0 -2px; transition: rotate var(--fast) var(--ease-out); }
.room.folded .room-fold .chevron { rotate: -45deg; translate: 0 0; }
.room-fold .room-count { font-size: var(--text-sm); font-variant-numeric: tabular-nums; }
.room.folded { margin-bottom: var(--space-6); }
@media (prefers-reduced-motion: reduce) { .room-fold .chevron { transition: none; } }
.finder-status { display: flex; align-items: center; gap: var(--space-10); margin: -4px 0 var(--space-14); padding: 0 var(--space-6); font-size: var(--text-sm); color: var(--muted); font-variant-numeric: tabular-nums; }
.finder-status:empty { display: none; }
.plugin-catalog { gap: var(--space-14); }
.plugin-catalog .catalog { padding: var(--space-20); }
.plugin-catalog .server-head { margin-bottom: var(--space-20); }
.plugin-catalog .actions { justify-content: flex-end; }
@media (max-width: 600px) {
  .plugin-instance .card-foot { flex-wrap: wrap; }
  .plugin-card-actions { margin-left: auto; }
}

/* Compact plugin management: keep each catalog entry on a single row. */
.plugin-instances { margin: var(--space-16) 0 var(--space-24); gap: var(--space-12); grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr)); }
.plugin-instance { padding: var(--space-16); gap: var(--space-10); }
.plugin-instance .meta { padding: 2px 0; gap: var(--space-10); }
.plugin-instance .card-foot { padding-top: var(--space-10); }
.plugin-instance .card-foot > .muted:empty { display: none; }
.plugin-card-actions { margin-left: auto; }
.plugin-catalog { grid-template-columns: repeat(auto-fit, minmax(min(100%, 420px), 1fr)); gap: var(--space-10); }
.plugin-catalog .catalog { display: flex; flex-direction: row; align-items: center; gap: var(--space-12); padding: var(--space-14) var(--space-16); }
.plugin-catalog .server-head { flex: 1; min-width: 0; margin: 0; gap: var(--space-10); }
.plugin-catalog .server-head .who { min-width: 0; }
.plugin-catalog .server-head strong { font-size: var(--text-base); }
.plugin-catalog .tile { width: 34px; height: 34px; border-radius: var(--radius-sm); }
.plugin-catalog .catalog > .actions { margin: 0; flex: none; }
.plugin-catalog .actions .button, .plugin-catalog .actions button { padding: 7px var(--space-12); }
@media (max-width: 460px) {
  .plugin-catalog .server-head { flex-wrap: wrap; }
  .plugin-catalog .server-head .pill { margin-left: 44px; }
}

.scene-grid { grid-template-columns: repeat(auto-fit, minmax(min(100%, 340px), 1fr)); gap: var(--space-14); margin-bottom: 28px; }
.scene-grid .scene-card { padding: var(--space-18); gap: var(--space-12); }
.scene-card .server-head { align-items: flex-start; }
.scene-card .server-head .who { min-width: 0; }
.scene-card .server-head .muted { white-space: normal; line-height: 1.5; margin-top: 5px; }
.scene-card .controls { padding: var(--space-4) var(--space-12); border: 1px solid var(--line); border-radius: var(--radius-md); background: var(--material-thin); }
.scene-card .control { gap: var(--space-12); padding: 9px 0; }
.scene-card .control > span:first-child { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.scene-card .value { text-align: right; font-size: var(--text-sm); }
.scene-card .card-foot { font-size: var(--text-xs); line-height: 1.5; padding-top: var(--space-10); }
.section-head:has(+ .scene-grid) { gap: var(--space-12); flex-wrap: wrap; }
.section-head:has(+ .scene-grid) .search { margin-left: auto; max-width: 280px; }
.moods .mood-card { padding: var(--space-18); }
.moods .mood-rooms { padding-bottom: var(--space-14); border-bottom: 1px solid var(--line); }
.moods .status-line:empty, .moods .mood-running:empty { display: none; }
@media (max-width: 560px) { .section-head:has(+ .scene-grid) .search { max-width: none; width: 100%; } }

.scene-flow { border: 1px solid var(--line); border-radius: var(--radius-lg); overflow: hidden; margin: var(--space-20) 0; background: var(--material-solid); }
.scene-flow-toolbar { display: flex; align-items: center; gap: var(--space-8); padding: var(--space-12) var(--space-16); border-bottom: 1px solid var(--line); background: var(--control); }
.scene-flow-title { display: flex; align-items: center; gap: var(--space-8); margin-right: auto; }
.scene-flow-title svg { width: 18px; height: 18px; color: var(--accent-ink); }
.scene-flow-toolbar button { min-height: 32px; padding: var(--space-6) var(--space-10); border-radius: var(--radius-sm); }
.scene-flow-zoom { min-width: 44px; text-align: center; font-size: var(--text-sm); color: var(--muted); }
.scene-flow-workspace { position: relative; display: grid; grid-template-columns: 180px minmax(0, 1fr); }
.scene-flow-sidebar { padding: var(--space-16) var(--space-12); border-right: 1px solid var(--line); background: var(--material); }
.scene-flow-sidebar h3 { margin: 0 0 var(--space-12); font-size: var(--text-sm); }
.scene-flow-sidebar p { font-size: var(--text-xs); line-height: 1.6; margin-top: var(--space-20); }
.scene-flow-navigation { display: grid; gap: var(--space-8); }
.scene-flow-nav { width: 100%; text-align: left; border-radius: var(--radius-sm); padding: var(--space-10); box-shadow: none; font-size: var(--text-sm); }
.scene-flow-nav.on { border-color: var(--accent); background: var(--material-thin); }
.scene-flow-count { margin-left: auto; font-size: var(--text-xs); color: var(--muted); }
.scene-flow-viewport { min-height: 560px; height: 65vh; overflow: auto; background: radial-gradient(circle, var(--line) 1px, transparent 1px) 0 0 / 18px 18px; }
.scene-flow-canvas { min-width: 330px; min-height: 540px; display: flex; flex-direction: column; align-items: center; justify-content: center; padding: var(--space-24); }
.scene-flow-terminal { display: flex; align-items: center; gap: var(--space-8); padding: var(--space-8) var(--space-12); border: 1px solid var(--line); border-radius: var(--radius-pill); background: var(--control); font-size: var(--text-xs); color: var(--muted); }
.scene-flow-terminal svg { width: 16px; height: 16px; color: var(--accent-ink); }
.scene-flow-connector { width: 1px; height: 38px; background: var(--line); position: relative; }
.scene-flow-connector svg { position: absolute; width: 14px; height: 14px; left: -6px; bottom: -1px; color: var(--muted); }
.scene-flow-step { width: 300px; display: flex; align-items: center; gap: var(--space-12); padding: var(--space-14); border-radius: var(--radius-md); background: var(--control); box-shadow: 0 3px 10px rgba(0,0,0,.06); text-align: left; }
.scene-flow-step[aria-expanded="true"] { outline: 2px solid var(--accent); outline-offset: 2px; }
.scene-flow-step-icon { width: 36px; height: 36px; border-radius: var(--radius-sm); display: grid; place-items: center; color: #fff; background: #7c3aed; flex: none; }
.scene-flow-step.condition .scene-flow-step-icon { background: #b77912; }
.scene-flow-step.action .scene-flow-step-icon { background: #2563eb; }
.scene-flow-step-icon svg { width: 20px; height: 20px; }
.scene-flow-step-label { display: grid; gap: var(--space-4); flex: 1; min-width: 0; }
.scene-flow-summary { font-size: var(--text-xs); color: var(--muted); }
.scene-flow-step > svg { width: 16px; height: 16px; color: var(--muted); }
.scene-flow-inspector { position: absolute; top: 0; right: 0; bottom: 0; width: min(390px, 100%); z-index: 3; overflow: auto; background: var(--material-solid); border-left: 1px solid var(--line); box-shadow: -10px 0 35px rgba(0,0,0,.1); }
.scene-flow-inspector[hidden], .scene-flow-panel[hidden] { display: none; }
.scene-flow-inspector-head { display: flex; align-items: center; gap: var(--space-10); padding: var(--space-14) var(--space-16); border-bottom: 1px solid var(--line); position: sticky; top: 0; background: var(--material-solid); z-index: 2; }
.scene-flow-inspector-head > svg { width: 20px; height: 20px; color: var(--accent-ink); }
.scene-flow-inspector-head h3 { margin: 0; flex: 1; font-size: var(--text-base); }
.scene-flow-inspector-head button { padding: var(--space-8); min-height: 32px; box-shadow: none; }
@media (max-width: 700px) {
  .scene-flow-workspace { grid-template-columns: minmax(0, 1fr); }
  .scene-flow-sidebar { border-right: 0; border-bottom: 1px solid var(--line); padding: var(--space-10); }
  .scene-flow-sidebar h3, .scene-flow-sidebar p { display: none; }
  .scene-flow-navigation { display: flex; gap: var(--space-6); }
  .scene-flow-nav { flex: 1; min-width: 0; padding: var(--space-8); font-size: var(--text-xs); }
  .scene-flow-inspector { top: 54px; }
  .scene-flow-toolbar button:last-child { font-size: var(--text-xs); }
}
.scene-flow-body { padding: var(--space-16); display: flex; flex-direction: column; gap: var(--space-12); }
.scene-flow-body > p { font-size: var(--text-sm); line-height: 1.5; margin: 0; }
.scene-flow-body .editor-row { flex-direction: column; align-items: stretch; padding: var(--space-12); border: 1px solid var(--line); border-radius: var(--radius-sm); }
.scene-flow-body select, .scene-flow-body input:not([type=checkbox]), .scene-flow-body .value-slot { max-width: 100%; min-width: 0; width: 100%; }
.scene-flow-body .group-inline { flex-wrap: wrap; }

.scene-flow-body .scene-condition-remove { display: flex; align-items: center; justify-content: center; gap: var(--space-8); width: 100%; min-height: 40px; margin-top: var(--space-8); }
.scene-condition-remove svg { width: 18px; height: 18px; flex: none; }

.days .day > span { position: relative; pointer-events: none; line-height: 1; }
.days .day input { width: 100%; min-width: 0; height: 100%; position: absolute; inset: 0; opacity: 0; }

/* One trash glyph and stroke treatment across menus, forms and scene nodes. */
svg.icon-trash, button svg.icon-trash, .menu svg.icon-trash {
  width: 18px; height: 18px; flex: none; fill: none; stroke: currentColor;
  stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; vertical-align: middle;
}

.days .day { width: auto; min-width: 34px; padding: 0 7px; flex: none; }

/* Accessory groups and their member picker. */
.accessory-group { padding: var(--space-16); overflow: auto; min-height: 200px; background: var(--material-solid); border: 1px solid var(--line); border-radius: var(--radius-lg); }
.accessory-group .server-head .who { min-width: 0; }
.accessory-group .group-controls { display: grid; gap: var(--space-10); margin-top: var(--space-16); }
.group-controls label { display: flex; align-items: center; gap: var(--space-10); font-size: var(--text-sm); }
.group-controls label > span:first-child { flex: 1; }
/* Some members on, some off: the name, and how many are on under it. */
.group-controls .group-name { display: grid; gap: 1px; }
.group-controls .group-count { color: var(--muted); font-size: var(--text-xs); font-variant-numeric: tabular-nums; }
.group-controls > .level { width: 100%; }
.group-feedback { font-size: var(--text-xs); color: var(--danger); }
.group-feedback:empty { display: none; }
.wall .widget.group-drop-target { outline: 3px solid var(--accent); outline-offset: 3px; }
.wall .widget.group-drop-target::after { content: "+"; position: absolute; inset: 35% 40%; border-radius: 50%; background: var(--accent); color: white; display: grid; place-items: center; font-size: 32px; pointer-events: none; }
.accessory-group-dialog { width: min(940px, calc(100vw - 32px)); max-height: calc(100dvh - 40px); padding: var(--space-24); border-radius: var(--radius); border: 1px solid var(--edge); background: var(--material-solid); box-shadow: 0 24px 80px rgba(0,0,0,.25); }
.group-dialog-head { display: flex; align-items: center; gap: var(--space-12); margin-bottom: var(--space-24); }
.group-dialog-head h2 { margin: 0; font-size: 1.2rem; }
.group-name-field { display: flex; flex-direction: column; gap: var(--space-8); margin-bottom: var(--space-16); }
.group-name-field > span { font-size: var(--text-sm); font-weight: var(--weight-semibold); color: var(--muted); }
.group-name-field input, .accessory-group-dialog .search { width: 100%; }
.group-member-list { overflow: auto; margin: var(--space-16) 0; display: grid; gap: 0; max-height: 38vh; border: 1px solid var(--line); border-radius: var(--radius-md); background: var(--material-thin); overscroll-behavior: contain; }
.group-member-list .group-member-row { display: flex; align-items: center; justify-content: space-between; gap: var(--space-10); padding: var(--space-12) var(--space-14); border-bottom: 1px solid var(--line); font-size: var(--text-md); }
.group-member-list .group-member-row:last-child { border-bottom: 0; }
.accessory-group-dialog .actions { padding-top: var(--space-16); border-top: 1px solid var(--line); }
.accessory-group-dialog p:empty { display: none; }
.group-type-filter { display: flex; flex-wrap: wrap; gap: var(--space-6); margin-top: var(--space-14); }
.group-type-filter button { display: flex; align-items: center; gap: var(--space-6); padding: 7px var(--space-10); font-size: var(--text-xs); }
.group-type-filter button[aria-pressed=true] { background: var(--accent-fill); color: var(--accent-text); border-color: var(--accent); }
.group-type-filter svg, .group-device-icon svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.group-device-icon { display: grid; place-items: center; width: 30px; height: 30px; flex: none; border-radius: var(--radius-sm); background: var(--accent-fill); color: var(--accent-text); }
.group-member-name { flex: 1; min-width: 0; }
.group-picker-columns { display: grid; grid-template-columns: minmax(0,1fr) minmax(0,1fr); gap: var(--space-24); }
.group-picker-columns > section { min-width: 0; }
.group-picker-columns h3 { font-size: var(--text-md); margin: 0 0 var(--space-14); }
.group-selected-heading { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--space-14); }
.group-selected-heading h3 { margin: 0; }
.group-transfer { width: 32px; min-width: 32px; height: 32px; min-height: 32px; padding: 0; flex: 0 0 32px; display: grid; place-items: center; font-size: 20px; line-height: 1; border-radius: 50%; }
.accessories-toolbar { display: flex; align-items: center; gap: var(--space-8); flex-wrap: wrap; }
.accessories-toolbar > button:not(.menu-button) { display: inline-flex; align-items: center; gap: 7px; }
.accessories-toolbar button > svg { width: 17px; height: 17px; fill: none; stroke: currentColor; stroke-width: 1.8; }
.accessories-toolbar .search { width: clamp(180px, 22vw, 300px); }
.toolbar-count { display: grid; place-items: center; min-width: 19px; height: 19px; border-radius: var(--radius-sm); background: var(--accent-fill); color: var(--accent-text); font-size: var(--text-xs); }
.accessories-toolbar .accessory-options-button { width: 36px; height: 36px; color: var(--muted); background: var(--material-thin); box-shadow: none; }
.accessories-toolbar .accessory-options-button svg { fill: none; stroke: currentColor; stroke-width: 1.6; width: 19px; height: 19px; }
@media (max-width: 650px) { .group-picker-columns { grid-template-columns: 1fr; gap: var(--space-16); } .group-picker-columns .group-member-list { max-height: 25vh; } }
@media (max-width: 600px) { .accessories-toolbar { width: 100%; } .accessories-toolbar .search { flex: 1 1 100%; width: 100%; } }

/* Toolbar glyphs stay lighter than their labels. */
.accessories-toolbar button > svg,
.accessories-toolbar .accessory-options-button svg {
  color: var(--muted); stroke: currentColor; fill: none;
  stroke-width: 1.5; opacity: .8;
}
.accessories-toolbar button > svg,
.accessories-toolbar .accessory-options-button svg { width: 14px; height: 14px; }

.local-ui-settings { padding: var(--space-20); }
.local-ui-settings .view-switch { margin-bottom: var(--space-20); }
.local-ui-settings .group-box { border: 1px solid var(--line); border-radius: var(--radius-md); margin: 0 0 var(--space-14); background: var(--material-thin); overflow: hidden; }
.local-ui-settings .group-box > summary { padding: var(--space-16) var(--space-18); font-size: var(--text-base); font-weight: var(--weight-semibold); cursor: pointer; }
.local-ui-settings .group-box > .fields { padding: var(--space-4) var(--space-18) var(--space-18); }
.local-ui-settings .help { max-width: 680px; line-height: 1.55; }
.local-ui-settings input:not([type=checkbox]), .local-ui-settings select { max-width: 560px; }
.local-ui-settings .drop-zone { padding: var(--space-16); margin-bottom: var(--space-18); border-radius: var(--radius-sm); }
.local-ui-settings > .error:empty { display: none; }
.local-ui-settings .group-box .group-box { background: transparent; }

.local-ui-settings .group-box > .fields > .fields { grid-column: 1 / -1; grid-template-columns: repeat(2, minmax(0, 1fr)); }
@media (max-width: 600px) { .local-ui-settings .group-box > .fields > .fields { grid-template-columns: 1fr; } }
.local-ui-settings .group-box > .fields > .fields { align-items: stretch; }
.local-ui-settings .group-box > .fields > .fields > div { display: flex; flex-direction: column; min-width: 0; }
.local-ui-settings .group-box > .fields > .fields > div > .drop-zone { margin-top: auto; }
/* Separate section guidance from its actions, in every form: a list's help from its Add button. */
fieldset > button,
.group-box .help + button,
.group-box p + button,
.group-box .help + .actions { margin-top: var(--space-14); }
fieldset > .help { margin-bottom: var(--space-10); }

.scene-value-slider { display: flex; flex-direction: column; gap: var(--space-10); width: 100%; padding: var(--space-12); border: 1px solid var(--line); border-radius: var(--radius-md); background: var(--material-thin); }
.scene-slider-value { align-self: flex-end; font-size: var(--text-base); font-weight: var(--weight-semibold); font-variant-numeric: tabular-nums; }
.scene-value-slider input[type=range] { width: 100%; min-height: 24px; padding: 0; }
.scene-value-slider.temperature input[type=range] { background: linear-gradient(90deg, #b9d9ff, #fff5df, #ffb64c); border-radius: var(--radius-md); }
.scene-value-slider.brightness input[type=range] { accent-color: var(--accent); }

/* Color belongs to the slider track, not the surrounding input box. */
.scene-value-slider { --scene-track: linear-gradient(90deg, #665c45, #f6d77e, #fff6d7); }
.scene-value-slider.temperature { --scene-track: linear-gradient(90deg, #a8ceff, #e1edff, #fff4de, #ffd180, #ff9f36); }
.scene-value-slider input[type=range],
.scene-value-slider.temperature input[type=range] {
  -webkit-appearance: none; appearance: none; background: transparent; border: 0; box-shadow: none;
  height: 32px; cursor: pointer;
}
.scene-value-slider input[type=range]::-webkit-slider-runnable-track { height: 12px; border-radius: var(--radius-pill); background: var(--scene-track); box-shadow: inset 0 0 0 1px rgba(0,0,0,.12); }
.scene-value-slider input[type=range]::-moz-range-track { height: 12px; border-radius: var(--radius-pill); background: var(--scene-track); box-shadow: inset 0 0 0 1px rgba(0,0,0,.12); }
.scene-value-slider input[type=range]::-webkit-slider-thumb { -webkit-appearance: none; width: 24px; height: 24px; margin-top: -6px; border-radius: 50%; border: 2px solid white; background: #fafafa; box-shadow: 0 1px 5px rgba(0,0,0,.3); }
.scene-value-slider input[type=range]::-moz-range-thumb { width: 20px; height: 20px; border-radius: 50%; border: 2px solid white; background: #fafafa; box-shadow: 0 1px 5px rgba(0,0,0,.3); }
.scene-value-slider input[type=range]:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: var(--radius-sm); }

.dashboard-quick-actions { gap: var(--space-12) var(--space-20); flex-wrap: wrap; }
.dashboard-quick-actions > .link { display: inline-flex; align-items: center; gap: var(--space-8); }
.dashboard-quick-actions svg { width: 18px; height: 18px; flex: none; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }

.restart-overlay { width: min(420px, calc(100vw - 40px)); padding: 36px 28px; border: 1px solid var(--edge); border-radius: var(--radius-xl); background: var(--material-solid); color: var(--text); text-align: center; box-shadow: 0 24px 80px rgba(0,0,0,.25); }
.restart-overlay::backdrop { background: rgba(20,25,35,.3); -webkit-backdrop-filter: blur(9px); backdrop-filter: blur(9px); }
.restart-overlay .spinner { width: 32px; height: 32px; border-width: 3px; margin-bottom: var(--space-14); }
.restart-overlay h2 { font-size: 1.2rem; margin: var(--space-8) 0 var(--space-12); }
.restart-overlay p { color: var(--muted); font-size: var(--text-md); line-height: 1.6; }
@media (prefers-reduced-transparency: reduce) { .restart-overlay::backdrop { background: rgba(20,25,35,.8); backdrop-filter: none; -webkit-backdrop-filter: none; } }

.restart-confirm-icon { display: grid; place-items: center; width: 60px; height: 60px; margin: 0 auto var(--space-18); border-radius: var(--radius-lg); background: var(--accent-soft, rgba(234,115,14,.12)); color: var(--accent); }
.restart-confirm-icon svg { width: 28px; height: 28px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.restart-confirm-actions { display: flex; gap: var(--space-12); margin-top: 26px; }
.restart-confirm-actions button { flex: 1; min-height: 42px; }

.restart-overlay.restart-leaving { animation: restart-dialog-out 220ms ease-in forwards; }
.restart-overlay.restart-leaving::backdrop { animation: restart-backdrop-out 220ms ease-in forwards; }
@keyframes restart-dialog-out { to { opacity: 0; transform: translateY(6px) scale(.98); } }
@keyframes restart-backdrop-out { to { opacity: 0; } }
@media (prefers-reduced-motion: reduce) {
  .restart-overlay.restart-leaving, .restart-overlay.restart-leaving::backdrop { animation: none; }
}

/* Compact mobile navigation, anchored within thumb reach. */
@media (max-width: 640px) {
  .tabbar { left: auto; right: max(14px, env(safe-area-inset-right)); bottom: max(14px, env(safe-area-inset-bottom)); display: block; padding: 0; border: 0; background: none; box-shadow: none; backdrop-filter: none; -webkit-backdrop-filter: none; }
  .mobile-nav-toggle { display: grid; place-items: center; width: 54px; height: 54px; padding: 0; border-radius: 50%; color: var(--text); background: var(--material-thick); border: 1px solid var(--edge); box-shadow: var(--shadow-thick); }
  .mobile-nav-toggle svg { width: 23px; height: 23px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; }
  .mobile-nav-toggle[aria-expanded="true"] { color: var(--accent-ink); }
  .mobile-nav-panel { position: absolute; bottom: 66px; right: 0; width: min(240px, calc(100vw - 28px)); max-height: calc(100dvh - 150px); overflow-y: auto; padding: var(--space-8); border-radius: var(--radius); background: var(--material-solid); border: 1px solid var(--edge); box-shadow: var(--shadow-thick); }
  .tabbar .mobile-nav-panel a { display: flex; align-items: center; justify-content: flex-start; gap: var(--space-12); min-height: 44px; padding: var(--space-10) var(--space-12); border-radius: var(--radius-md); font-size: var(--text-md); letter-spacing: normal; }
  .tabbar .mobile-nav-panel a.hidden { display: none; }
  .tabbar .mobile-nav-panel a span { display: inline; }
  .tabbar .mobile-nav-panel a svg { width: 21px; height: 21px; flex: none; }
}

@media (max-width: 640px) {
  .mobile-nav-toggle, .mobile-nav-toggle[aria-expanded="true"] { backdrop-filter: blur(20px) saturate(140%); -webkit-backdrop-filter: blur(20px) saturate(140%); background: linear-gradient(180deg, color-mix(in srgb, var(--accent-fill-top) 72%, transparent), color-mix(in srgb, var(--accent-fill) 72%, transparent)); color: var(--accent-text); border: 1px solid var(--edge-light); box-shadow: 0 6px 22px rgba(0,0,0,.28), 0 0 0 3px var(--material-solid); }
  .mobile-nav-toggle svg { stroke-width: 2.2; }
  .mobile-nav-account { display: flex; align-items: center; gap: var(--space-12); width: 100%; min-height: 44px; padding: var(--space-10) var(--space-12); margin-top: 0; border-radius: var(--radius-md); color: var(--muted); background: transparent; border: 0; box-shadow: none; text-align: start; font-size: var(--text-md); font-weight: var(--weight-semibold); }
  .mobile-nav-account svg { width: 21px; height: 21px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
}

@media (max-width: 640px) { header .user-button { display: none; } }

@media (max-width: 640px) {
  .tabbar .mobile-nav-panel a.active,
  .tabbar .mobile-nav-panel a[aria-current="page"] {
    background: linear-gradient(180deg, var(--accent-fill-top), var(--accent-fill));
    color: var(--accent-text);
    box-shadow: inset 0 1px 0 var(--edge-light);
  }
}

.mobile-nav-divider { border: 0; border-top: 1px solid var(--edge); margin: var(--space-8) var(--space-4); }

.mobile-nav-account:hover { background: var(--material-thin); }

.account-settings-link, .account-settings-link:visited { color: var(--accent-ink); text-decoration: none; }
.account-settings-link:hover { text-decoration: underline; text-underline-offset: 3px; }

.port-stepper { position: relative; min-width: 0; }
.port-stepper > input { width: 100%; padding-right: 46px; appearance: textfield; -moz-appearance: textfield; }
.port-stepper > input::-webkit-inner-spin-button, .port-stepper > input::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
.port-stepper-buttons { position: absolute; inset: 4px 4px 4px auto; width: 34px; display: grid; grid-template-rows: 1fr 1fr; gap: 2px; }
.port-stepper-buttons button { display: grid; place-items: center; min-height: 0; padding: 0; border: 0; border-radius: var(--radius-xs); background: var(--material-thin); color: var(--muted); box-shadow: none; }
.port-stepper-buttons button:hover { background: var(--material-regular); color: var(--accent-ink); }
.port-stepper-buttons svg { width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }

@media (prefers-reduced-transparency: reduce), (prefers-contrast: more) {
  .mobile-nav-toggle, .mobile-nav-toggle[aria-expanded="true"] { background: var(--accent-fill); backdrop-filter: none; -webkit-backdrop-filter: none; }
}

/* Keep dashboard content constrained while the footer spans the page. */
#app:has(> main > .status-footer) { min-height: 100dvh; display: flex; flex-direction: column; }
#app:has(> main > .status-footer) > header,
#app:has(> main > .status-footer) > .banner { flex-shrink: 0; }
main:has(> .status-footer) { flex: 1; display: flex; flex-direction: column; width: 100%; max-width: none; margin: 0; padding-inline: 0; padding-bottom: 0; }
main:has(> .status-footer) > .dash-widget { flex-shrink: 0; }
main:has(> .status-footer) > .dash-widget:last-of-type { margin-bottom: var(--space-20); }
main:has(> .status-footer) > .dash-widget { max-width: 1076px; width: calc(100% - 24px); margin-inline: auto; }
/* Status details remain visible even when the Overview widget is hidden. */
/* A quiet utility bar: status first, metadata second, one compact action. */
.status-footer {
  --text: #edf0f5; --muted: #adb6c4; --accent-ink: #f4c49e; --warn: #f1c084; --ok: #75d5a0; --error: #ff9999;
  display: flex; justify-content: space-between; align-items: center; flex-wrap: nowrap; gap: var(--space-20);
  width: 100%; flex-shrink: 0; margin: auto 0 0;
  padding: var(--space-12) max(var(--space-16), calc((100% - 1076px) / 2));
  border: 0; border-top: 1px solid rgba(255,255,255,.08); border-radius: 0;
  background: #222833; color: var(--text);
}
.status-footer-summary { min-width: 0; flex: 1; display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-4) var(--space-24); font-size: var(--text-xs); line-height: 1.5; }
.status-footer-summary p { margin: 0; overflow-wrap: anywhere; }
.status-footer-summary .health { gap: var(--space-8); }
.status-footer-summary .health strong { font-weight: var(--weight-medium); }
.status-footer-summary .health::before { width: 6px; height: 6px; margin-top: calc(.75em - 3px); }
.status-footer-summary .muted { font-variant-numeric: tabular-nums; }
.status-footer > .link {
  flex: none; display: inline-flex; align-items: center; justify-content: center; gap: var(--space-8);
  min-height: 36px; margin: 0; padding: var(--space-8) var(--space-10); font-size: var(--text-xs); line-height: 1.5;
  color: var(--text); border: 1px solid rgba(255,255,255,.14); border-radius: var(--radius-xs);
  background: rgba(255,255,255,.04); white-space: nowrap;
}
.status-footer > .link:hover, .status-footer > .link[aria-expanded="true"] { background: rgba(255,255,255,.1); border-color: rgba(255,255,255,.28); }
.status-footer > .link:focus-visible { outline: 2px solid var(--accent-ink); outline-offset: 3px; }
@media (max-width: 640px) {
  .status-footer { gap: var(--space-12); padding: var(--space-12) 88px var(--space-12) var(--space-16); }
  .status-footer-summary { display: block; }
  .status-footer-summary .muted { margin-top: var(--space-4); padding-left: var(--space-14); }
  .status-footer > .link { width: 40px; min-height: 40px; padding: var(--space-10); }
  .status-footer-action-label { display: none; }
}

.status-footer-meta { display: flex; align-items: baseline; flex-wrap: wrap; gap: var(--space-4) var(--space-12); }
.status-footer .footer-update-check { margin: 0; padding: 0; min-height: 24px; font-size: inherit; line-height: inherit; color: var(--accent-ink); text-decoration: underline; text-underline-offset: 3px; }
@media (max-width: 640px) {
  .status-footer-meta { margin-top: var(--space-4); padding-left: var(--space-14); }
  .status-footer-summary .status-footer-meta .muted { margin: 0; padding: 0; }
}

/* Keep the version and its update action on one row, even on narrow screens. */
.status-footer-meta > .muted { flex: 0 1 auto; max-width: calc(100% - 125px); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.status-footer .footer-update-check { flex: none; white-space: nowrap; }
@media (max-width: 640px) {
  .status-footer { display: grid; grid-template-columns: minmax(0, 1fr) 40px; gap: var(--space-4) var(--space-12); }
  .status-footer-summary { display: contents; }
  .status-footer-summary .health { grid-column: 1; grid-row: 1; }
  .status-footer > .link { grid-column: 2; grid-row: 1; }
  .status-footer-meta { grid-column: 1 / -1; grid-row: 2; min-width: 0; }
}

.status-footer-meta { flex-wrap: nowrap; }
.status-footer-meta > .muted { max-width: none; }
.status-footer .footer-update-check {
  padding: 3px var(--space-8); min-height: 28px; border: 1px solid rgba(255,255,255,.2); border-radius: 5px;
  background: rgba(255,255,255,.05); text-decoration: none;
}
.status-footer .footer-update-check:hover { background: rgba(255,255,255,.12); }
.status-footer .footer-update-check:focus-visible { outline: 2px solid var(--accent-ink); outline-offset: 3px; }

.status-footer .footer-update-check[data-update-state="current"] { --update-tone: var(--ok); }
.status-footer .footer-update-check[data-update-state="available"] { --update-tone: var(--warn); }
.status-footer .footer-update-check[data-update-state="error"] { --update-tone: var(--error); }
.status-footer .footer-update-check {
  color: var(--update-tone, var(--text));
  border-color: color-mix(in srgb, var(--update-tone, var(--muted)) 45%, transparent);
  background: color-mix(in srgb, var(--update-tone, var(--muted)) 10%, transparent);
}
.status-footer .footer-update-check:hover:not(:disabled) {
  background: color-mix(in srgb, var(--update-tone, var(--muted)) 20%, transparent);
}

.status-footer .footer-update-check { display: inline-flex; align-items: center; gap: 5px; }
.status-footer .footer-update-check svg { width: 14px; height: 14px; flex: none; }
.status-footer .footer-update-check[data-update-state="checking"] svg {
  transform-origin: center;
  animation: spin .8s linear infinite;
}
@media (prefers-reduced-motion: reduce) {
  .status-footer .footer-update-check[data-update-state="checking"] svg { animation: none; }
}

/* Reserve the widest translated status without exposing sizing text to assistive technology. */
.footer-update-label { display: inline-grid; text-align: center; }
.footer-update-label > span { grid-area: 1 / 1; }
.footer-update-sizer { visibility: hidden; pointer-events: none; }

.group-box > summary > svg { width: 18px; height: 18px; margin-right: var(--space-8); vertical-align: -3px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }

.view-switch > button { display: inline-flex; align-items: center; gap: var(--space-6); }
.view-switch > button > svg { width: 16px; height: 16px; flex: none; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }

.expert-links > .button { display: inline-flex; align-items: center; gap: var(--space-6); }
.expert-links > .button > svg { width: 16px; height: 16px; flex: none; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }

.settings-action { display: inline-flex; align-items: center; justify-content: center; gap: var(--space-6); }
/* Secrets only: off, a plain button; on, filled with the gold the secret keys take, so the state reads at a glance and
   on a phone, where only its lock shows. Pressing it gives way at once. */
.secrets-only { transition: background-color var(--fast) var(--ease-out), color var(--fast) var(--ease-out), transform 100ms var(--ease-out); }
.secrets-only:active { transform: scale(0.96); }
.secrets-only[aria-pressed="true"] {
  color: #3b2a00; background: linear-gradient(180deg, #f7d067, #e6ae2c); border-color: transparent;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.45), 0 1px 2px rgba(120, 80, 0, 0.25);
}
.secrets-only[aria-pressed="true"] > svg { stroke-width: 2.2; }
/* While it holds: a gold strip at the top of the text says so, with the way out. */
.secrets-banner {
  display: flex; align-items: center; gap: var(--space-8); padding: var(--space-8) var(--space-12) var(--space-8) var(--space-16); font-size: var(--text-sm); font-weight: var(--weight-medium);
  color: #f2c14e; background: linear-gradient(rgba(242, 193, 78, 0.06), rgba(242, 193, 78, 0.06)), var(--console);
  border-bottom: 1px solid rgba(242, 193, 78, 0.22); transition: opacity var(--normal) var(--ease-out);
}
@starting-style { .secrets-banner { opacity: 0; } }
.secrets-banner > svg { flex: none; width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
.secrets-banner > span { flex: 1; min-width: 0; }
.secrets-banner > button { padding: var(--space-4) var(--space-10); font-size: var(--text-sm); color: #f3f4f7; background: rgba(255, 255, 255, 0.1); border: 0; box-shadow: none; }
.secrets-banner > button:hover { background: rgba(255, 255, 255, 0.16); }
.settings-action > svg { width: 16px; height: 16px; flex: none; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }

/* Decorative action icons survive loading/success label changes. */
.action-with-icon { display: inline-flex; align-items: center; justify-content: center; gap: var(--space-6); }
.action-with-icon::before { content: ""; display: inline-block; width: 16px; height: 16px; flex: none; background: currentColor; mask: var(--action-icon) center / contain no-repeat; -webkit-mask: var(--action-icon) center / contain no-repeat; }


.cached-search-tools { display: flex; align-items: center; gap: var(--space-8); margin-left: auto; min-width: 0; }
.cached-search-tools .search { width: 220px; max-width: 100%; min-width: 0; }
.cached-search-tools > button { flex-shrink: 0; }
@media (max-width: 640px) {
  .cached-search-tools { flex: 1 1 100%; }
  .cached-search-tools .search { flex: 1; width: auto; }
}

.cached-search-tools > button { display: inline-flex; align-items: center; gap: var(--space-6); }
.cached-search-tools > button > svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.cached-filter-count:empty { display: none; }
.section-head:has(.cached-search-tools) { flex-wrap: wrap; align-items: center; }

.menu-item-label { min-width: 0; flex: 1; }
.menu-item-count { flex: none; min-width: 2ch; text-align: right; font-variant-numeric: tabular-nums; color: var(--muted); font-size: var(--text-sm); }
.menu-item-count + .menu-toggle { margin-left: var(--space-8); }
.menu [role]:hover > .menu-item-count, .menu [role]:focus-visible > .menu-item-count { color: inherit; }
/* Keep the search and both menu triggers aligned when the header wraps. */
.section-head:has(.cached-search-tools) { display: grid; grid-template-columns: minmax(0, 1fr) auto; }
.cached-search-tools { grid-column: 1 / -1; width: 100%; margin-left: 0; }
.cached-search-tools .search { flex: 1; width: auto; }
.cached-search-tools > .menu-button { display: inline-flex; align-items: center; justify-content: center; }
@media (min-width: 1000px) {
  .section-head:has(.cached-search-tools) { grid-template-columns: auto auto minmax(0, 1fr); }
  .cached-search-tools { grid-column: auto; justify-content: flex-end; }
  .cached-search-tools .search { flex: 0 1 220px; }
}

.menu [data-tone="ok"] { --menu-status-color: var(--ok); }
.menu [data-tone="warn"] { --menu-status-color: var(--warn); }
.menu [data-tone="error"] { --menu-status-color: var(--error); }
.menu [data-tone] > :is(svg, .menu-item-label, .menu-item-count) { color: var(--menu-status-color); }
.menu [data-tone]:hover > :is(svg, .menu-item-label, .menu-item-count),
.menu [data-tone]:focus-visible > :is(svg, .menu-item-label, .menu-item-count) { color: inherit; }
.menu [data-tone][aria-checked="true"] > .menu-toggle { background: var(--menu-status-color); }

.menu [role][aria-disabled="true"], .menu [role][aria-disabled="true"]:hover {
  opacity: .45; cursor: default; background: transparent; color: var(--muted); transform: none;
}

/* Dim the whole filter, so icons, counts and switch tracks share its disabled state. */
.menu [role][aria-disabled="true"] {
  filter: grayscale(1);
  box-shadow: none;
}
.menu [role][aria-disabled="true"] > :is(svg, .menu-item-label, .menu-item-count) {
  color: var(--muted);
}
.group-type-filter button:disabled,
.log-level-row .group button:disabled {
  opacity: .4;
  filter: grayscale(1);
  box-shadow: none;
  cursor: default;
}
.toggle:has(input:disabled) {
  opacity: .4;
  filter: grayscale(1);
  cursor: default;
}
.toggle:has(input:disabled) .switch { cursor: default; }
select option:disabled { color: var(--muted); }

/* Editing is a layout preview with its own quiet header and bottom control strip. */
.wall.editing > .widget:not(.lifted):not(.drag-slot) { outline: 1px solid color-mix(in srgb, var(--accent) 25%, var(--edge)); outline-offset: -1px; }
.wall.editing > .widget::after { background: color-mix(in srgb, var(--bg) 65%, transparent); }
.edit-caption { position: absolute; inset: 9px 12px auto; z-index: 3; display: flex; align-items: center; gap: 7px; font-size: var(--text-sm); font-weight: var(--weight-semibold); color: var(--text); pointer-events: none; }
.edit-caption > span:last-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.edit-grip { flex: none; color: var(--muted); font-size: 19px; line-height: 1; }
.wall.editing .edit-bar { left: 8px; right: 37px; top: auto; bottom: 7px; transform: none; width: auto; max-width: none; padding: 3px; border-radius: var(--radius-sm); background: var(--material-solid); box-shadow: var(--shadow-control); }
.wall.editing .edit-bar button { width: auto; height: 26px; flex: 1 1 0; border-radius: var(--radius-xs); font-size: var(--text-2xs); }
.wall.editing .edit-bar button[data-step] { flex: .7 1 0; font-size: 18px; }
.wall.editing .edit-bar button:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.wall.editing .resize-handle { right: 4px; bottom: 8px; width: 29px; height: 29px; background: transparent; box-shadow: none; color: var(--accent-ink); }
.wall.editing .resize-handle::after { left: 8px; top: 11px; }
.wall.editing > .widget.size-small .edit-caption { top: 5px; font-size: var(--text-2xs); }
.wall.editing > .widget.size-small .edit-bar { bottom: 3px; padding: 2px; }
.wall.editing > .widget.size-small .edit-bar button { height: 22px; }
.wall.editing > .widget.size-small .resize-handle { bottom: 3px; }
.wall.editing > .widget-summary > .w-bottom, .wall.editing > .widget-summary > .w-middle { visibility: hidden; }
.wall.editing > .widget-summary > .w-top { position: absolute; left: 12px; right: 12px; top: 50%; transform: translateY(-50%); }
.wall.editing > .widget.size-small > .w-top { visibility: hidden; }
.wall.editing > .widget:not(.widget-summary) > .w-head { visibility: hidden; }

.wall.editing > .accessory-group { cursor: default; }
.wall.editing > .accessory-group > .server-head { visibility: hidden; }
.edit-caption > svg { width: 16px; height: 16px; flex: none; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; color: var(--muted); }
.wall.editing > .accessory-group .group-feedback:not(:empty) { position: relative; z-index: 3; margin-bottom: 42px; }
/* A corner grip leaves more of the bottom edge for the size controls. */
.wall.editing .edit-bar { right: 24px; }
.wall.editing .resize-handle,
.wall.editing > .widget.size-small .resize-handle {
  right: 0; bottom: 0; width: 28px; height: 28px; border-radius: 0 0 var(--radius) 0;
  background: transparent; box-shadow: none;
}
.wall.editing .resize-handle::after {
  left: auto; top: auto; right: 6px; bottom: 6px; width: 11px; height: 11px;
  border-right: 2px solid currentColor; border-bottom: 2px solid currentColor;
  border-radius: 0 0 3px 0; background: none; box-shadow: none; transform: none;
}
.wall.editing .resize-handle:focus-visible { outline: 2px solid var(--accent); outline-offset: -3px; }

/* Group cards share widget sizes and the same rounded corner resize target. */
.accessory-group { min-height: 0; }
.accessory-group.size-small .group-controls, .accessory-group.size-small .server-head .muted { display: none; }
.accessory-group.size-small { padding: var(--space-8) var(--space-12); }
.accessory-group.size-small .server-head { margin: 0; }
.accessory-group.size-medium { padding: var(--space-12); }
.accessory-group.size-medium .server-head .muted { display: none; }
.wall.editing > .accessory-group { overflow: hidden; }
.wall.editing > .accessory-group .edit-caption { right: 44px; }
.wall.editing > .accessory-group > .server-head .menu-button {
  visibility: visible; pointer-events: auto; position: absolute; top: 4px; right: 5px; z-index: 4;
  width: 28px; height: 28px; min-height: 0; padding: var(--space-4);
}
.wall.editing .resize-handle,
.wall.editing > .widget.size-small .resize-handle { border-bottom-right-radius: var(--radius-lg); }
.wall.editing .resize-handle::after { width: 12px; height: 12px; border-bottom-right-radius: var(--radius-sm); }

.wall.editing > .accessory-group { cursor: grab; }
.wall.editing > .accessory-group.lifted { cursor: grabbing; }

/* Medium groups fit their compact controls inside the same footprint as other M tiles. */
.accessory-group.size-medium { padding: var(--space-8) var(--space-10); }
.accessory-group.size-medium .server-head { gap: var(--space-8); margin: 0; min-height: 30px; }
.accessory-group.size-medium .server-head .tile { width: 28px; height: 28px; border-radius: var(--radius-sm); }
.accessory-group.size-medium .server-head .who { flex: 1; }
.accessory-group.size-medium .server-head strong { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--text-xs); }
.accessory-group.size-medium .server-head .menu-button { width: 26px; height: 26px; min-height: 0; padding: 3px; }
.accessory-group.size-medium .group-controls { gap: var(--space-4); margin-top: 5px; }
.accessory-group.size-medium .group-controls > label { min-height: 24px; font-size: var(--text-2xs); gap: 5px; }
.accessory-group.size-medium .group-count { display: none; }
.accessory-group.size-medium .group-controls input[type="checkbox"] { width: 36px; height: 22px; flex: none; }
.accessory-group.size-medium .group-controls > .level { height: 26px; min-height: 26px; border-radius: var(--radius-sm); }
.accessory-group.size-medium .level-label, .accessory-group.size-medium .level-text { font-size: .625rem; }
.accessory-group.size-medium .level-label { left: 7px; max-width: 58%; overflow: hidden; white-space: nowrap; }
.accessory-group.size-medium .level-text { right: 7px; }
.accessory-group.size-medium .group-feedback:empty { display: none; }
/* Scale the complete switch, including its minimum width and thumb travel. */
.accessory-group.size-medium .group-controls input[type="checkbox"] { width: 36px; min-width: 36px; height: 22px; border-radius: var(--radius-pill); }
.accessory-group.size-medium .group-controls input[type="checkbox"]::before { width: 16px; height: 16px; left: 2px; top: 2px; }
.accessory-group.size-medium .group-controls input[type="checkbox"]:checked::before { transform: translateX(14px); }
.accessory-group.size-medium .group-controls input[type="checkbox"]:indeterminate::before { transform: translateX(7px); }

.wall.editing > .widget.lifted, .wall.editing > .widget.lifted * { pointer-events: none !important; }
.wall.editing > .widget.group-drop-target { outline: 2px solid var(--accent); outline-offset: 2px; }
.wall.editing > .widget.group-drop-target::after { background: var(--accent); z-index: 5; }

.wall.editing > .widget.group-drop-target { outline: 3px solid var(--accent); outline-offset: 3px; box-shadow: 0 0 0 7px color-mix(in srgb, var(--accent) 20%, transparent); }
.wall.editing > .widget.group-drop-target::after {
  content: "+ " attr(data-drop-label); inset: 4px; border-radius: calc(var(--radius) - 4px);
  background: color-mix(in srgb, var(--accent) 92%, var(--material-solid)); color: var(--accent-text);
  font-size: var(--text-md); font-weight: var(--weight-bold); text-align: center; padding: var(--space-8); line-height: 1.3;
  display: flex; align-items: center; justify-content: center; z-index: 6;
}
.wall.editing > .widget.lifted { opacity: .65; }
@media (max-width: 640px) {
  .wall.editing > .widget.group-drop-target::after { font-size: var(--text-xs); }
}

.group-room-field { display: grid; gap: var(--space-6); margin: var(--space-12) 0 var(--space-16); }
.group-room-field select { width: 100%; }

.disabled-filter-tip {
  position: fixed; inset: auto; margin: 0; width: max-content;
  max-width: min(300px, calc(100vw - 24px)); padding: var(--space-10) var(--space-14);
  border: 1px solid var(--edge); border-radius: var(--radius-md);
  background: var(--material-solid); color: var(--text);
  box-shadow: var(--shadow-control); font-size: var(--text-sm); line-height: 1.4;
  pointer-events: none;
}

/* Give reset actions breathing room in both wrapped toolbars and stacked pickers. */
.clear-filters { margin-block: var(--space-12); margin-inline-start: var(--space-12); }
.group-clear-filters { margin-inline-start: 0; }
.menu .clear-filters-menu { margin-block: var(--space-12); }

@media (max-width: 650px) {
  .accessory-group-dialog { padding: 0; overflow: hidden; }
  .accessory-group-dialog > form { display: flex; flex-direction: column; max-height: calc(100dvh - 42px); }
  .group-dialog-content { min-height: 0; overflow-y: auto; padding: var(--space-24); overscroll-behavior: contain; }
  .accessory-group-dialog > form > .actions {
    flex: none; margin: 0; padding: var(--space-14) var(--space-24) max(var(--space-14), env(safe-area-inset-bottom));
    background: var(--material-solid); border-top: 1px solid var(--line);
  }
}

/* ---- The lighting plugins' pages (Philips Hue, IKEA DIRIGERA): their tabs, a bridge's pairing with its button,
   its address, scene tiles painted with their palette or a picture, the transition's speed scale and the save bar.
   plugin.js has their pieces (tabs, bridgePairing, scenePictures, textStyle, speedScale). */
.main-tabs { margin: var(--space-18) 0 var(--space-14); }
/* On a phone the tabs share the width, so four of them fit; longer names (a translation) scroll the bar sideways
   rather than be cut. */
@media (max-width: 600px) {
  .main-tabs { display: flex; width: 100%; overflow-x: auto; scrollbar-width: none; }
  .main-tabs::-webkit-scrollbar { display: none; }
  .main-tabs > button { flex: 1 0 auto; padding: 5px var(--space-8); justify-content: center; gap: 5px; }
}
.tab-pane { animation: fade var(--normal) var(--ease-out); }

/* The bridge card: a block per bridge (a line between two), its facts once paired, then the address form. */
.bridge-card .bridge { padding: var(--space-14) 0; border-top: 1px solid var(--line); }
.bridge-card .bridge:first-child { padding-top: 0; border-top: 0; }
.bridge-card .bridge .who { flex: 1; min-width: 0; }
.bridge-card .bridge .facts { margin-top: var(--space-14); }
.bridge-card .bridges:not(:empty) + .address-box { padding-top: var(--space-14); border-top: 1px solid var(--line); }
.bridge-card .found { display: flex; flex-wrap: wrap; gap: var(--space-6); margin-top: var(--space-10); }
.bridge-card .found:empty { display: none; }

/* Pairing: the bridge's button drawn, what to do, and Pair at the row's end; the drawn button pulses while the bridge waits. */
.pair-prompt { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: var(--space-16); align-items: center; margin-top: var(--space-14); padding: var(--space-14) var(--space-16); border-radius: var(--radius-lg); background: var(--material-thin); border: 1px solid var(--line); }
.pair-prompt p { margin: 0; font-size: var(--text-md); }
.link-button { width: 54px; height: 54px; border-radius: 50%; display: grid; place-items: center; background: radial-gradient(circle at 50% 40%, #fff, #e6e8ee 70%); box-shadow: inset 0 -2px 0 rgba(0, 0, 0, 0.08), 0 1px 3px rgba(0, 0, 0, 0.15); color: #3d4352; }
.link-button svg { width: 24px; height: 24px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; }
.pairing .link-button { animation: press 1.6s var(--ease-out) infinite; }
@keyframes press { 0%, 100% { box-shadow: 0 0 0 0 rgba(124, 77, 219, 0.45), inset 0 -2px 0 rgba(0, 0, 0, 0.08); } 50% { box-shadow: 0 0 0 10px rgba(124, 77, 219, 0), inset 0 -2px 0 rgba(0, 0, 0, 0.08); } }
.address { margin-top: var(--space-12); }
.address-row { display: flex; gap: var(--space-8); align-items: center; }
.address-row input { flex: 1; min-width: 0; width: auto; }
.address-row button { flex: none; }
.address .help { display: block; margin-top: var(--space-6); }

/* Scene tiles: a scene's palette as a gradient, or its picture, under a scrim that keeps the name readable. */
.scene-tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 168px), 1fr)); gap: var(--space-10); margin-bottom: 28px; }
.scene { position: relative; isolation: isolate; display: grid; align-content: end; min-height: 96px; padding: var(--space-12) var(--space-14); border-radius: var(--radius-lg); border: 1px solid var(--edge); color: #fff; text-align: left; cursor: pointer; overflow: hidden; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08); transition: transform var(--fast) var(--ease-out), box-shadow var(--fast) var(--ease-out); }
.scene::after { content: ""; position: absolute; inset: 0; background: linear-gradient(180deg, transparent 35%, rgba(0, 0, 0, 0.42)); pointer-events: none; }
@media (hover: hover) and (pointer: fine) { .scene:hover { box-shadow: 0 6px 18px rgba(0, 0, 0, 0.14); } }
.scene:active { transform: scale(0.98); }
.scene .name { position: relative; z-index: 1; font-weight: var(--weight-semibold); font-size: var(--text-base); text-shadow: 0 1px 2px rgba(0, 0, 0, 0.35); overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.scene.active { box-shadow: 0 0 0 3px var(--accent), 0 6px 18px rgba(0, 0, 0, 0.14); }
.scene .badge { position: absolute; top: 10px; left: 12px; z-index: 1; font-size: var(--text-2xs); font-weight: var(--weight-semibold); padding: 2px var(--space-8); border-radius: var(--radius-pill); background: rgba(255, 255, 255, 0.85); color: #1d1d1f; }
.scene .eye { position: absolute; top: 6px; right: 6px; z-index: 2; width: 30px; height: 30px; min-height: 0; padding: 0; border-radius: 50%; display: grid; place-items: center; background: rgba(0, 0, 0, 0.28); border: 0; color: #fff; box-shadow: none; }
.scene .eye svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.scene.hidden-scene { filter: grayscale(0.85); opacity: 0.55; }
.scene.busy { pointer-events: none; }
/* A scene's own picture fills its tile; dragging a picture over a tile outlines it. */
.scene.pictured { background-size: cover !important; background-position: center !important; }
.scene.drop { box-shadow: 0 0 0 3px var(--accent), 0 6px 18px rgba(0, 0, 0, 0.18); transform: scale(1.02); }
/* A light palette takes dark text, without the scrim; a palette neither reads well on takes a darker scrim; a picture
   keeps white text on the scrim, whatever its palette. */
.scene.deep::after { background: linear-gradient(180deg, transparent 20%, rgba(0, 0, 0, 0.62)); }
.scene.light:not(.pictured) { color: #1d1d1f; }
.scene.light:not(.pictured)::after { display: none; }
.scene.light:not(.pictured) .name { text-shadow: none; }
.scene.light:not(.pictured) .eye { background: rgba(255, 255, 255, 0.55); color: #1d1d1f; }
.scene.light:not(.pictured) .badge { background: #1d1d1f; color: #fff; }

/* The transition's speed scale, the devices left out of the Home app, and the save bar. */
.range-head { display: flex; align-items: baseline; gap: var(--space-10); flex-wrap: wrap; }
.range-head output { font-weight: var(--weight-semibold); font-variant-numeric: tabular-nums; }
.field input.speed { width: 100%; }
.speed-scale { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); margin: var(--space-4) 0 2px; font-size: var(--text-xs); color: var(--muted); text-align: center; }
.speed-scale span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; padding: 0 2px; border-left: 1px solid var(--line); }
.speed-scale span:first-child { border-left: 0; }
.hidden-devices { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-8); margin-top: var(--space-14); font-size: var(--text-md); }
.hidden-devices:empty { display: none; }
.save-card { position: sticky; bottom: 12px; z-index: 3; margin-top: var(--space-18); }
.save-card .save-bar { border-top: 0; padding-top: 0; }

@media (max-width: 640px) {
  .speed-scale { display: none; }
  .pair-prompt { grid-template-columns: auto minmax(0, 1fr); }
  .pair-prompt > button { grid-column: 1 / -1; justify-self: end; }
}
@media (prefers-reduced-motion: reduce) {
  .tab-pane { animation: none; }
  .pairing .link-button { animation: none; }
  .scene { transition: none; }
}

/* ---- Homebridge config import (import.js): /import, the welcome page, the Plugins page's empty state ---- */
.import-card { padding: var(--space-20) 22px; }
.import-card h2 { margin: var(--space-18) 0 var(--space-6); }
.import-card .lede { margin: 0 0 var(--space-14); color: var(--muted); }
.import-steps { list-style: none; display: flex; flex-wrap: wrap; gap: var(--space-14); margin: 0 0 var(--space-6); padding: 0; font-size: var(--text-sm); color: var(--muted); }
.import-steps li { display: inline-flex; align-items: center; gap: var(--space-8); }
.import-steps li.current { color: var(--text); font-weight: var(--weight-semibold); }
.import-steps li.done { color: var(--ok); }
.import-steps .step-dot { display: grid; place-items: center; width: 22px; height: 22px; border-radius: 50%; border: 1px solid var(--line); font-size: var(--text-xs); font-weight: var(--weight-semibold); }
.import-steps li.current .step-dot { background: linear-gradient(180deg, var(--accent-fill-top), var(--accent-fill)); border-color: transparent; color: var(--accent-text); }
.import-steps li.done .step-dot { border-color: rgba(21, 122, 66, 0.4); }
.import-tabs { margin: var(--space-4) 0 var(--space-12); flex-wrap: wrap; }
.import-panel-box { min-height: 120px; }
.import-panel { display: grid; gap: var(--space-10); }
.import-notice { display: flex; gap: var(--space-8); align-items: flex-start; margin: 0; padding: var(--space-10) var(--space-12); border-radius: var(--radius-md); color: var(--warn); font-size: var(--text-md); background: rgba(201, 115, 26, 0.1); }
.import-notice svg, .import-secure svg { flex: none; width: 16px; height: 16px; margin-top: 2px; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
.import-secure { display: flex; gap: var(--space-6); align-items: center; margin: 0; font-size: var(--text-sm); color: var(--ok); }
.import-secure svg { width: 14px; height: 14px; margin: 0; }
.import-file-input { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.import-drop { display: grid; justify-items: center; gap: var(--space-6); padding: 28px var(--space-16); border: 1.5px dashed var(--line); border-radius: var(--radius-lg); background: var(--field); cursor: pointer; text-align: center; }
.import-drop:focus-within { outline: 2px solid var(--accent); outline-offset: 3px; }
.import-drop svg { width: 30px; height: 30px; fill: none; stroke: var(--accent-ink); stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.import-drop.is-off { opacity: 0.5; cursor: not-allowed; }
.import-picked { display: flex; justify-content: space-between; align-items: center; gap: var(--space-10); flex-wrap: wrap; padding: var(--space-12) var(--space-14); border-radius: var(--radius-lg); border: 1px solid var(--line); background: var(--material-thin); }
.import-picked-name { display: inline-flex; align-items: center; gap: var(--space-8); flex-wrap: wrap; min-width: 0; }
.import-picked-name svg { width: 18px; height: 18px; fill: none; stroke: var(--ok); stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; }
.import-check { margin: var(--space-12) 0 var(--space-4); padding: var(--space-12) var(--space-14); border-radius: var(--radius-lg); border: 1px solid var(--line); background: var(--material-thin); font-size: var(--text-md); }
.import-check[data-state="ok"] { border-color: rgba(21, 122, 66, 0.35); }
.import-check[data-state="warn"], .import-check[data-state="error"] { border-color: rgba(201, 115, 26, 0.4); }
.import-check-head { display: flex; align-items: center; gap: var(--space-8); margin: 0; }
.import-check-head svg { width: 18px; height: 18px; flex: none; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
.import-check[data-state="ok"] .import-check-head { color: var(--ok); }
.import-check[data-state="warn"] .import-check-head, .import-check[data-state="error"] .import-check-head { color: var(--warn); }
.import-check-line { margin: var(--space-4) 0 0 26px; color: var(--muted); }
.import-check-line:has(.import-detail) { display: flex; flex-wrap: wrap; gap: var(--space-6); align-items: baseline; }
.import-detail { font-family: var(--mono); font-size: var(--text-xs); color: var(--muted); word-break: break-all; }
.import-foot { justify-content: space-between; flex-wrap: wrap; }
.import-foot .fine { margin: 0; max-width: 46ch; font-size: var(--text-sm); }
.import-foot .end { display: flex; gap: var(--space-10); flex-wrap: wrap; }
.import-folder { display: grid; gap: var(--space-10); }
.import-crumbs { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-6); font-size: var(--text-sm); }
.import-crumbs .crumb { padding: var(--space-4) var(--space-8); font-size: var(--text-sm); }
.import-crumbs .crumb[aria-current="page"] { font-weight: var(--weight-semibold); }
.import-files { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-6); max-height: 42vh; overflow: auto; overscroll-behavior: contain; }
.import-file { width: 100%; display: grid; grid-template-columns: minmax(0, 1fr); justify-items: start; gap: 2px; padding: var(--space-10) var(--space-12); text-align: left; border-radius: var(--radius-md); transition: transform var(--fast) var(--ease-out); }
.import-file:active { transform: scale(0.98); }
.import-file .name { font-weight: var(--weight-medium); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%; }
.import-file .meta { font-size: var(--text-xs); color: var(--muted); }
.import-file[aria-pressed="true"] { border-color: var(--accent); background: var(--material-thin); }
.import-loading { display: grid; place-items: center; min-height: 80px; }
.import-source { display: inline-flex; align-items: center; gap: var(--space-6); margin: 0 0 var(--space-6); font-size: var(--text-sm); color: var(--muted); }
.import-source svg { width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.import-summary { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-10); margin: var(--space-12) 0 var(--space-4); }
.import-count { display: grid; gap: 2px; padding: var(--space-12); border-radius: var(--radius-lg); border: 1px solid var(--line); background: var(--material-thin); }
.import-count b { font-size: 1.5rem; font-weight: var(--weight-bold); letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }
.import-count span { font-size: var(--text-xs); color: var(--muted); }
.import-count.imported b { color: var(--ok); }
.import-count.encrypted b { color: var(--series-1); }
.import-count.dropped b { color: var(--muted); }
.import-group { margin-top: var(--space-18); }
.import-group-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-10); margin-bottom: var(--space-6); }
.import-group-head h3 { margin: 0; font-size: var(--text-base); font-weight: var(--weight-semibold); }
.import-group-head .muted { font-size: var(--text-sm); }
.import-rows { display: grid; gap: var(--space-6); }
.import-item { border: 1px solid var(--line); border-radius: var(--radius-lg); background: var(--material-thin); }
.import-item > summary { display: grid; grid-template-columns: minmax(0, 1fr) auto auto auto; align-items: center; gap: var(--space-8) var(--space-12); padding: var(--space-10) var(--space-14); list-style: none; color: var(--text); }
.import-item > summary::-webkit-details-marker { display: none; }
.import-key { font-family: var(--mono); font-size: var(--text-sm); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.import-value { font-size: var(--text-sm); color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; justify-self: end; max-width: 16ch; }
.import-value.masked { letter-spacing: 0.12em; }
.import-pill { display: inline-block; padding: 2px var(--space-10); border-radius: var(--radius-pill); font-size: var(--text-xs); font-weight: var(--weight-semibold); white-space: nowrap; }
.import-pill.imported { color: var(--ok); background: rgba(21, 122, 66, 0.12); }
.import-pill.encrypted { color: var(--series-1-ink); background: rgba(42, 120, 214, 0.12); }
.import-pill.dropped { color: var(--muted); background: rgba(89, 97, 112, 0.12); }
.import-item .chev { width: 16px; height: 16px; fill: none; stroke: var(--muted); stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; transition: transform var(--fast) var(--ease-out); }
.import-item[open] .chev { transform: rotate(180deg); }
.import-detail-list { margin: 0; padding: 0 var(--space-14) var(--space-12); display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-8); font-size: var(--text-md); }
.import-detail-list > div { display: grid; gap: 2px; }
.import-detail-list dt { font-size: var(--text-xs); color: var(--muted); font-weight: var(--weight-semibold); }
.import-detail-list dd { margin: 0; }
.import-welcome h1 { margin-bottom: var(--space-6); }
.import-welcome .lede { margin: 0 0 var(--space-14); color: var(--muted); }
.import-done { list-style: none; margin: 0 0 var(--space-18); padding: 0; display: grid; gap: var(--space-8); }
.import-done li { display: flex; align-items: center; gap: var(--space-10); }
.import-tick { display: grid; place-items: center; width: 22px; height: 22px; border-radius: 50%; flex: none; color: var(--ok); background: rgba(21, 122, 66, 0.14); }
.import-tick svg { width: 13px; height: 13px; fill: none; stroke: currentColor; stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; }
.import-offer { display: grid; gap: var(--space-12); padding: var(--space-16); border-radius: var(--radius-lg); border: 1px solid var(--line); background: var(--material-thin); }
.import-offer h2 { margin: 0 0 var(--space-4); font-size: var(--text-lg); }
.import-offer p { margin: 0; }
.import-offer-icon { display: grid; place-items: center; width: 40px; height: 40px; border-radius: var(--radius-sm); color: var(--accent-ink); background: color-mix(in srgb, var(--accent) 14%, transparent); }
.import-offer-icon svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.import-offer .actions { margin-top: 0; flex-wrap: wrap; }
.import-welcome > .fine { margin: var(--space-14) 0 0; font-size: var(--text-sm); }
.import-offer-card .actions { justify-content: center; flex-wrap: wrap; }
.import-offer-title { font-weight: var(--weight-semibold); font-size: var(--text-lg); }
@media (max-width: 520px) {
  .import-item > summary { grid-template-columns: minmax(0, 1fr) auto auto; }
  .import-value { grid-column: 1 / -1; justify-self: start; max-width: none; grid-row: 2; }
  .import-summary { gap: var(--space-8); }
  .import-count b { font-size: var(--text-2xl); }
}

/* Accessories › Graph: the graph of bridges, plugins and accessories, its legend and table. */
:root { --viz-1: #2a78d6; --viz-2: #eb6834; --viz-3: #1baf7a; --viz-4: #eda100; --viz-5: #e87ba4; --viz-6: #008300; --viz-7: #6250d6; --viz-8: #e34948; }
@media (prefers-color-scheme: dark) { :root:not(:where([data-theme="light"])) { --viz-1: #3987e5; --viz-2: #d95926; --viz-3: #199e70; --viz-4: #c98500; --viz-5: #d55181; --viz-6: #008300; --viz-7: #9085e9; --viz-8: #e66767; } }
:root[data-theme="dark"] { --viz-1: #3987e5; --viz-2: #d95926; --viz-3: #199e70; --viz-4: #c98500; --viz-5: #d55181; --viz-6: #008300; --viz-7: #9085e9; --viz-8: #e66767; }
.overview-card { display: grid; gap: var(--space-12); }
.overview-card .who { min-width: 0; }
.overview-card .chart-head .muted { font-size: var(--text-sm); }
.overview-frame { position: relative; }
/* Search and filters over the graph, as the Accessories page's toolbar; the count says what is left. */
.overview-count { font-size: var(--text-sm); font-variant-numeric: tabular-nums; }
.overview-count:empty { display: none; }
.overview-toolbar .clear-filters { margin-left: auto; }
.overview-toolbar .clear-filters:disabled { visibility: hidden; }
.overview-empty { padding: 56px var(--space-16); text-align: center; }
.overview-graph { display: block; width: 100%; max-width: 820px; height: auto; margin: 0 auto; touch-action: none; user-select: none; -webkit-user-select: none; cursor: grab; }
.overview-graph:focus { outline: none; }
.overview-graph.deep { cursor: default; }
.overview-graph .edge { fill: none; stroke: var(--branch, var(--muted)); stroke-opacity: 0.42; stroke-width: 1.2; }
.overview-graph .edge.trunk { stroke-width: 2.2; stroke-opacity: 0.6; }
.overview-graph .edge.leaf { stroke-width: 0.8; stroke-opacity: 0.22; }
.overview-graph .edge.paused { stroke-dasharray: 3 3; }
/* Every node is a disc in its branch's colour with its icon: bridges thickest, accessories thinnest. */
.overview-graph .node, .overview-graph .dot { cursor: pointer; outline: none; }
.overview-graph .node-disc { fill: var(--material-solid); stroke: var(--branch); stroke-width: 2; }
.overview-graph g svg { color: var(--branch); }
.overview-graph .bridge-node .node-disc { stroke-width: 2.6; filter: drop-shadow(0 2px 6px rgba(20, 30, 50, 0.14)); }
.overview-graph .plugin-node .node-disc { stroke-width: 2.6; }
.overview-graph .dot .node-disc { stroke-width: 1.4; }
.overview-graph :is(.node, .dot):hover .node-disc { stroke-width: 2.8; }
.overview-graph :is(.node, .dot):focus-visible .node-disc { stroke: var(--accent); stroke-width: 2.8; }
.overview-graph .bridge-node.unpaired .node-disc { stroke: var(--warn); }
.overview-graph :is(.bridge-node.built-in, .plugin-node.paused) .node-disc { stroke-dasharray: 3 2; }
.overview-graph .dot.unavailable .node-disc { stroke-dasharray: 2 1.6; stroke-opacity: 0.7; }
.overview-graph .dot.unavailable svg { opacity: 0.4; }
.overview-graph .root { cursor: pointer; outline: none; }
.overview-graph .root:focus-visible .root-icon { filter: drop-shadow(0 0 5px var(--accent)); }
.overview-zoom { display: flex; flex-wrap: wrap; gap: var(--space-8); justify-content: center; }
.overview-zoom button svg { width: 16px; height: 16px; }
.overview-tip { position: fixed; z-index: var(--layer-tip); max-width: 260px; padding: var(--space-6) var(--space-10); border-radius: var(--radius-sm); font-size: var(--text-sm); line-height: 1.3; color: var(--text); background: var(--material-solid); box-shadow: var(--shadow-control), 0 0 0 1px var(--line); transform: translate(-50%, calc(-100% - 10px)); pointer-events: none; }
.overview-legend { display: flex; flex-wrap: wrap; gap: var(--space-6) var(--space-16); margin: 0; padding: 0; list-style: none; font-size: var(--text-sm); color: var(--muted); }
.overview-legend li { display: inline-flex; align-items: center; gap: var(--space-6); }
.legend-mark { display: inline-block; width: 10px; height: 10px; border-radius: 50%; background: var(--mark); }
.legend-mark.hollow { background: none; border: 1.6px solid var(--muted); }
.legend-mark.status { background: var(--paused); }
.legend-mark.status.warn { background: var(--warn); }
.overview-more { margin: 0; }
.overview-more > summary { display: inline-flex; align-items: center; gap: var(--space-6); cursor: pointer; color: var(--muted); font-size: var(--text-md); }
.overview-more > summary svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.overview-table-wrap { overflow-x: auto; margin-top: var(--space-10); }
.overview-table { width: 100%; border-collapse: collapse; font-size: var(--text-md); font-variant-numeric: tabular-nums; }
.overview-table th, .overview-table td { padding: var(--space-8) var(--space-10); text-align: left; border-bottom: 1px solid var(--line); }
.overview-table thead th { color: var(--muted); font-weight: var(--weight-semibold); font-size: var(--text-sm); }
.overview-table .overview-plugin th { padding-left: 26px; font-weight: var(--weight-medium); }
.overview-table .overview-bridge th { font-weight: var(--weight-figure); }

/* The accessory's detail, beside its icon: what it is, its status, and every reading it reports. */
.overview-detail { position: absolute; z-index: 20; width: min(300px, calc(100% - 16px)); max-height: 380px; overflow: auto; padding: var(--space-14) var(--space-16); border-radius: var(--radius-lg); background: var(--material-solid); box-shadow: var(--shadow), 0 0 0 1px var(--line); display: grid; gap: var(--space-12); align-content: start; }
.detail-head { display: flex; align-items: center; gap: var(--space-10); }
.detail-head .who { min-width: 0; flex: 1; }
.detail-head strong { display: block; font-size: var(--text-lg); letter-spacing: -0.01em; overflow-wrap: anywhere; }
/* The head's icon on a tile of its branch's colour, as Settings draws its rows; the app's own icon stands alone. */
.detail-glyph { flex: none; width: 36px; height: 36px; border-radius: var(--radius-sm); display: grid; place-items: center; color: var(--branch); background: color-mix(in srgb, var(--branch) 14%, transparent); }
.detail-glyph svg { width: 20px; height: 20px; }
.detail-glyph.app { background: none; }
.detail-glyph.app img { width: 36px; height: 36px; border-radius: var(--radius-sm); }
.detail-status { font-size: var(--text-sm); color: var(--muted); }
.detail-status.warn { color: var(--warn); }
.detail-close, .detail-back { flex: none; width: 32px; height: 32px; min-height: 32px; padding: 0; display: inline-grid; place-items: center; }
.detail-back { margin-left: -4px; }
@media (max-width: 640px) { .overview-detail { position: static; width: 100%; max-height: none; margin-top: var(--space-12); box-shadow: var(--shadow-control); } }
/* Facts, readings and accessories as inset groups: rows on a tinted panel, a hairline between them. */
.detail-list, .detail-items { display: block; margin: 0; padding: 0 var(--space-12); list-style: none; border-radius: var(--radius-md); background: color-mix(in srgb, var(--text) 4%, transparent); font-size: var(--text-sm); }
.detail-list > div { display: flex; justify-content: space-between; align-items: baseline; gap: var(--space-14); padding: 7px 0; }
.detail-list > div + div, .detail-items > li + li { border-top: 1px solid var(--line); }
.detail-list dt { color: var(--muted); flex: none; }
.detail-list dd { margin: 0; text-align: right; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; min-width: 0; }
.detail-items { padding: 0 var(--space-4) 0 var(--space-10); }
/* An accessory's readings, a group per service under its name, as Settings titles its groups. */
.detail-section { display: grid; gap: var(--space-4); }
/* A camera's picture at the top of its card, rounded like the groups under it. */
.detail-media { border-radius: var(--radius-md); overflow: hidden; }
.detail-section .service-name { margin: 0 0 0 var(--space-12); }
.detail-list > div[title] { cursor: help; }
.detail-item { all: unset; box-sizing: border-box; width: 100%; display: flex; align-items: center; gap: var(--space-10); padding: 7px var(--space-4) 7px 0; cursor: pointer; border-radius: var(--radius-sm); }
.detail-item:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.detail-item:active { opacity: 0.6; }
.detail-item-glyph { flex: none; width: 26px; height: 26px; border-radius: 50%; display: grid; place-items: center; color: var(--branch); background: color-mix(in srgb, var(--branch) 14%, transparent); }
.detail-item-glyph svg { width: 15px; height: 15px; }
.detail-item-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 550; }
.detail-item-status { flex: none; max-width: 45%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--muted); font-variant-numeric: tabular-nums; }
.detail-item.warn .detail-item-glyph { color: var(--warn); background: color-mix(in srgb, var(--warn) 14%, transparent); }
.detail-item.warn .detail-item-status { color: var(--warn); }
.detail-item > svg:last-child { flex: none; width: 14px; height: 14px; color: var(--muted); opacity: 0.6; }
@media (hover: hover) { .detail-item:hover .detail-item-name { color: var(--accent-ink); } }


/* The battery widget at every size: the design's battery with its three bars, the level filling them, and a bolt
   beside it while charging, which pulses while the bar being filled flickers. Low turns it amber. */
.battery-gauge { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--space-6); flex: none; align-self: center; }
.battery-gauge.low .battery-graphic { color: var(--warn); }
.battery-graphic { position: relative; display: flex; align-items: center; justify-content: center; gap: var(--space-4); color: var(--ok); }
.battery-graphic .bat-icon { width: 34px; height: 34px; overflow: visible; }
.size-medium .battery-graphic .bat-icon { width: 28px; height: 28px; }
.size-large .battery-graphic .bat-icon { width: 56px; height: 56px; }
.size-xlarge .battery-graphic .bat-icon { width: 72px; height: 72px; }
.battery-graphic rect.bat-body, .battery-graphic path.bat-terminal { fill: none; stroke: currentColor; stroke-width: 1.6; }
.battery-graphic path.bat-terminal { stroke-linecap: round; }
.battery-graphic .bat-bar { fill: currentColor; opacity: 0.2; transition: opacity var(--normal) var(--ease-out); }
.battery-graphic .bat-bar.on { opacity: 1; }
/* The bolt sits outside the battery's box, beside it, so the battery stays centred. */
.battery-graphic .bat-bolt { display: none; position: absolute; left: calc(100% + 2px); top: 50%; margin-top: -10px; width: 20px; height: 20px; fill: currentColor; }
.size-medium .battery-graphic .bat-bolt { width: 16px; height: 16px; margin-top: -8px; }
.battery-graphic.charging .bat-bolt { display: block; animation: bat-bolt 1.8s ease-in-out infinite; }
.battery-graphic.charging .bat-bar.live { animation: bat-flicker 1.1s steps(1, end) infinite; }
@keyframes bat-flicker { 0%, 49% { opacity: 1; } 50%, 100% { opacity: 0.15; } }
@keyframes bat-bolt { 0%, 100% { opacity: 0.55; transform: scale(0.92); } 50% { opacity: 1; transform: scale(1.05); } }
@media (prefers-reduced-motion: reduce) {
  .battery-graphic.charging .bat-bar.live, .battery-graphic.charging .bat-bolt { animation: none; }
}
.gauge-figure { font-size: 15px; font-weight: var(--weight-figure); font-variant-numeric: tabular-nums; letter-spacing: 0; }
.size-medium .gauge-figure { display: block; font-size: 16px; }
.size-large .gauge-figure { font-size: 18px; letter-spacing: -0.01em; }
.size-xlarge .gauge-figure { font-size: 26px; letter-spacing: -0.02em; line-height: 1; }
.battery-gauge .gauge-figure small { display: inline; margin-top: 0; font-size: 0.6em; font-weight: var(--weight-medium); opacity: 0.7; }

/* Battery tiles: the menu button is a round, bordered control at every size. */
.widget.widget-battery:not(.widget-full) .menu-button { width: 28px; height: 28px; margin: 0; opacity: 1; color: var(--text); background: rgba(255, 255, 255, 0.92); border: 1px solid var(--line); box-shadow: 0 1px 3px rgba(0, 0, 0, 0.18); }
.widget.widget-battery:not(.widget-full) .menu-button svg { width: 18px; height: 18px; stroke-width: 2.2; }

/* A small battery tile: the icon on the left, the name and status beside it, and the level as a subtitle under the
   name, so the name is never cut; the graphic has a fixed box, the bolt in its right part while charging. */
.widget-battery.size-small { position: relative; display: grid; grid-template-columns: auto minmax(0, 1fr); grid-template-areas: "icon bottom" "icon sub"; column-gap: var(--space-12); align-items: center; }
.widget-battery.size-small .w-top { display: contents; }
.widget-battery.size-small .w-top > .tile { grid-area: icon; }
.widget-battery.size-small .w-top > .w-hero:has(> .battery-gauge) { grid-area: sub; display: flex; align-items: center; justify-self: start; min-width: 0; white-space: nowrap; }
.widget-battery.size-small .w-bottom { grid-area: bottom; min-width: 0; position: static; }
.widget-battery.size-small .w-bottom .menu-button { position: absolute; top: auto; left: auto; right: 6px; bottom: 6px; }
.widget-battery.size-small .battery-gauge { flex-direction: row; gap: var(--space-6); }
.widget-battery.size-small .battery-graphic { width: 42px; flex: none; justify-content: flex-start; }
.widget-battery.size-small .battery-graphic .bat-icon { width: 20px; height: 20px; }
.widget-battery.size-small .battery-graphic .bat-bolt { left: 24px; width: 12px; height: 12px; margin-top: -12px; }
.widget-battery.size-small .gauge-figure { display: block; font-size: 13px; line-height: 1; white-space: nowrap; }
.widget-battery.size-small .gauge-figure small { font-size: 0.8em; }

/* A medium battery tile: the gauge centred on the card, not on the top row that holds the icon. */
.widget-battery.size-medium { position: relative; }
.widget-battery.size-medium .w-top { position: static; }
.widget-battery.size-medium .w-top > .w-hero:has(> .battery-gauge) { position: absolute; left: 50%; top: 36%; transform: translate(-50%, -50%); display: flex; align-items: center; justify-content: center; }

/* Shared photographic artwork for saved scenes and room moods. */
.scene-artwork { width: 100%; aspect-ratio: 16/9; object-fit: cover; border-radius: var(--radius-sm); }
.artwork-preview { max-width: 320px; }
.artwork-picker { margin-block: var(--space-16); }
.artwork-picker > button { margin-bottom: var(--space-16); }
.artwork-picker summary { cursor: pointer; padding-block: var(--space-12); }
.artwork-grid, .mood-buttons.artwork-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: var(--space-12); max-height: 520px; overflow: auto; padding: var(--space-8) 3px; }
/* The Hue scene widget: a full-bleed picture and its name over a bottom scrim. */
.scene.artwork-choice, .mood-button.scene.artwork-choice { width: 100%; aspect-ratio: 16 / 9; min-height: 110px; display: grid; align-content: end; justify-content: stretch; padding: var(--space-12) var(--space-14); border-radius: var(--radius-lg); gap: 0; color: #fff; white-space: normal; }
.scene.artwork-choice img, .scene.artwork-choice .mood-swatch { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; border-radius: 0; }
.scene.artwork-choice .name { text-align: left; padding-left: var(--space-20); line-height: 1.3; }
.scene.artwork-choice:not(.action-with-icon) .name { padding-left: 0; }
.scene.artwork-choice.action-with-icon::before { position: absolute; bottom: 14px; left: 12px; z-index: 1; }
.scene.artwork-choice[aria-pressed="true"] { box-shadow: 0 0 0 3px var(--accent), var(--shadow-control); }
.scene.artwork-choice[hidden] { display: none; }
.mood-group .mood-buttons { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 168px), 1fr)); gap: var(--space-10); overflow: visible; margin-inline: 0; padding-inline: 3px; }

/* Theme shelves: two rows, with horizontal scrolling like a photographic gallery. */
.artwork-filters { display: flex; gap: var(--space-12); margin-block: var(--space-12); }
.artwork-filters input { min-width: 0; flex: 1; }
.artwork-filters select { max-width: 45%; }
.artwork-theme { margin-block: var(--space-20); }
.artwork-theme-row { display: grid; grid-template-rows: repeat(2, auto); grid-auto-flow: column; grid-auto-columns: 200px; gap: var(--space-12); overflow-x: auto; padding: 3px; scroll-snap-type: x proximity; }
.artwork-theme-row .artwork-choice { scroll-snap-align: start; }
.artwork-theme[hidden] { display: none; }
.artwork-picker .artwork-themes { max-height: 640px; overflow-y: auto; }
@media (max-width: 640px) {
  .artwork-theme-row { grid-template-rows: auto; grid-auto-columns: 160px; overscroll-behavior-x: contain; }
}

.artwork-filters { flex-wrap: wrap; }
.artwork-filters input { flex-basis: 220px; }
.artwork-filters select { flex: 1; min-width: 140px; max-width: none; }

.location-map { height: 340px; position: relative; overflow: hidden; isolation: isolate; background: var(--line); border-radius: var(--radius-md); touch-action: none; cursor: grab; }
.location-map:active { cursor: grabbing; }
.location-map-tiles { position: absolute; inset: 0; pointer-events: none; }
.location-map-tiles img { position: absolute; width: 256px; height: 256px; max-width: none; }
.location-map-pin { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -100%); color: var(--accent); filter: drop-shadow(0 1px 2px #fff); pointer-events: none; }
.location-map-pin svg { width: 36px; height: 36px; }
.location-map-controls { position: absolute; top: 10px; left: 10px; display: flex; gap: var(--space-8); }
.location-map-credit { position: absolute; right: 0; bottom: 0; padding: var(--space-4) var(--space-8); background: #fff; color: #222; font-size: var(--text-xs); }

.artwork-dialog { width: min(850px, calc(100vw - 32px)); max-height: 85vh; overflow: auto; }
.artwork-dialog .artwork-grid { margin-block: var(--space-12); }

.appearance-card-title { display: flex; align-items: center; gap: var(--space-10); }
.appearance-card-title svg { width: 22px; height: 22px; color: var(--accent-ink); flex: none; }
.appearance .group .menu-flag { margin-right: var(--space-6); }

.scene-color-input { width: 100%; height: 64px; padding: var(--space-4); border-radius: var(--radius-md); cursor: pointer; }
.value-slot input[role="switch"] { width: 44px; height: 28px; accent-color: var(--accent); }

.mood-stop-badge { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 44px; height: 44px; background: #fff; color: #222; border-radius: var(--radius-pill); display: grid; place-items: center; box-shadow: var(--shadow-control); pointer-events: none; }
.mood-stop-badge::before { content: ""; width: 14px; height: 14px; background: currentColor; border-radius: 0; }


.scene-run-actions { display: flex; flex-wrap: wrap; gap: var(--space-8); align-items: center; }

/* Original scalable abstract wallpapers. */
:root[data-wallpaper="silk"] body::before, [data-swatch="silk"] { background: url("/wallpaper-silk.svg") center / cover no-repeat, var(--bg); }
:root[data-wallpaper="prism"] body::before, [data-swatch="prism"] { background: url("/wallpaper-prism.svg") center / cover no-repeat, var(--bg); }
:root[data-wallpaper="ribbon"] body::before, [data-swatch="ribbon"] { background: url("/wallpaper-ribbon.svg") center / cover no-repeat, var(--bg); }
:root[data-wallpaper="lagoon"] body::before, [data-swatch="lagoon"] { background: url("/wallpaper-lagoon.svg") center / cover no-repeat, var(--bg); }
:root[data-wallpaper="ember"] body::before, [data-swatch="ember"] { background: url("/wallpaper-ember.svg") center / cover no-repeat, var(--bg); }
:root[data-wallpaper="midnight"] body::before, [data-swatch="midnight"] { background: url("/wallpaper-midnight.svg") center / cover no-repeat, var(--bg); }

/* Compact action summaries keep long workflows scannable without nested scrolling. */
.scene-action { border: 1px solid var(--line); border-radius: var(--radius-md); background: var(--control); }
.scene-action-summary { list-style: none; display: flex; align-items: center; gap: var(--space-12); min-height: 56px; padding: var(--space-12); cursor: pointer; touch-action: manipulation; }
.scene-action-summary::-webkit-details-marker { display: none; }
.scene-action-summary > span { flex: 1; min-width: 0; display: grid; gap: var(--space-4); }
.scene-action-summary strong { font-size: var(--text-sm); overflow-wrap: anywhere; }
.scene-action-summary small { color: var(--muted); font-size: var(--text-xs); }
.scene-action-summary svg { width: 18px; height: 18px; flex: none; color: var(--accent-ink); }
.scene-action-summary svg:last-child { color: var(--muted); }
.scene-action[open] > summary svg:last-child { transform: rotate(180deg); }
.scene-flow-body .scene-action > .editor-row { border: 0; border-top: 1px solid var(--line); border-radius: 0 0 var(--radius-md) var(--radius-md); background: transparent; }
.scene-action-summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: var(--radius-md); }
@media (max-width: 700px) {
  .scene-editor { padding: var(--space-12); padding-bottom: calc(90px + env(safe-area-inset-bottom, 0px)); }
  .scene-flow { overflow: visible; }
  .scene-flow-toolbar { border-radius: var(--radius-lg) var(--radius-lg) 0 0; min-height: 48px; }
  .scene-flow-toolbar > button, .scene-flow-zoom { display: none; }
  .scene-flow-sidebar { position: sticky; top: calc(76px + env(safe-area-inset-top, 0px)); z-index: 4; background: var(--material-solid); padding: var(--space-8); }
  .scene-flow-navigation { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-4); }
  .scene-flow-nav { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--space-4); min-height: 52px; padding: var(--space-8) var(--space-4); white-space: normal; text-align: center; }
  .scene-flow-nav > span:not(.scene-flow-count) { flex-basis: calc(100% - 24px); }
  .scene-flow-count { margin-left: 0; min-width: 20px; }
  .scene-flow-viewport { height: auto; min-height: 0; overflow: visible; }
  .scene-flow-canvas { min-width: 0; min-height: 0; padding: var(--space-20) var(--space-12); zoom: 1 !important; }
  .scene-flow-step { width: 100%; max-width: 360px; min-height: 64px; }
  .scene-flow-connector { height: 26px; }
  .scene-flow.editing .scene-flow-viewport { display: none; }
  .scene-flow-inspector { position: static; width: 100%; min-width: 0; overflow: visible; border-left: 0; box-shadow: none; border-radius: 0 0 var(--radius-lg) var(--radius-lg); }
  .scene-flow-inspector-head { position: static; padding: var(--space-10) var(--space-12); }
  .scene-flow-inspector-head button { min-width: 44px; min-height: 44px; }
  .scene-flow-body { padding: var(--space-12); }
  .scene-flow-body .field { gap: var(--space-6); margin: 0; }
  .scene-flow-body .editor-row { gap: var(--space-14); }
  .scene-flow-body input, .scene-flow-body select { font-size: 16px; }
  .scene-flow-body select, .scene-flow-body button { min-height: 44px; }
  .scene-flow-body .scene-condition-remove { width: auto; align-self: flex-end; padding-inline: var(--space-14); }
  .scene-editor > .save-bar { position: sticky; bottom: calc(80px + env(safe-area-inset-bottom, 0px)); z-index: 5; background: var(--material-solid); border: 1px solid var(--line); border-radius: var(--radius-md); padding: var(--space-8); gap: var(--space-8); box-shadow: var(--shadow-control); }
  .scene-editor > .save-bar > .spacer { display: none; }
  .scene-editor > .save-bar > :is(button, a) { flex: 1; justify-content: center; min-height: 44px; padding-inline: var(--space-8); font-size: var(--text-sm); }
}
@media (pointer: coarse) {
  .scene-flow button, .scene-action-summary { -webkit-tap-highlight-color: transparent; touch-action: manipulation; user-select: none; -webkit-user-select: none; }
  .scene-flow button:active, .scene-action-summary:active { background-color: var(--material-thin); }
}

.location-search { margin-block: var(--space-16); }
.location-search-bar { display: flex; gap: var(--space-10); }
.location-search-bar input { min-width: 0; flex: 1; font-size: 16px; }
.location-search-results { display: grid; gap: var(--space-8); }
.location-search-results button { text-align: left; justify-content: flex-start; white-space: normal; min-height: 44px; }

@media (max-width: 640px) {
  .scene-editor > .save-bar { position: fixed; left: max(14px, env(safe-area-inset-left)); right: calc(max(14px, env(safe-area-inset-right)) + 64px); bottom: max(14px, env(safe-area-inset-bottom)); margin: 0; padding: var(--space-4); gap: var(--space-4); }
}
@media (max-width: 400px) {
  .scene-editor > .save-bar > :is(button, a) { flex-direction: column; gap: var(--space-4); padding-inline: var(--space-4); }
}

.location-search { padding: var(--space-16); border: 1px solid var(--line); border-radius: var(--radius-md); background: var(--material-solid); }
.location-search .field-title { display: block; margin-bottom: var(--space-8); }
.location-search-input { position: relative; flex: 1; min-width: 0; }
.location-search-input input { width: 100%; padding-right: calc(var(--space-20) * 2); }
.location-search-input .spinner { position: absolute; right: var(--space-12); top: 50%; margin-top: -9px; pointer-events: none; }
.location-search-input .spinner[hidden] { display: none; }
.location-search > p { font-size: var(--text-sm); margin-block: var(--space-10); }
.location-search-results button { border-radius: var(--radius-sm); padding: var(--space-12); box-shadow: none; border: 1px solid var(--line); touch-action: manipulation; }
.location-result-copy { display: grid; gap: var(--space-4); min-width: 0; overflow-wrap: anywhere; }
.location-result-copy > .muted { font-size: var(--text-sm); }
.location-search-results button:active { background: var(--material-thick); }
/* A filtered ancestor would anchor the fixed action bar to the form instead of the viewport. */
@media (max-width: 640px) {
  .scene-editor.card { backdrop-filter: none; -webkit-backdrop-filter: none; background: var(--material-solid); }
}

.scene-card-details { margin-top: var(--space-12); }
.scene-card-details > summary { min-height: 44px; align-content: center; cursor: pointer; color: var(--text); }
.scene-card-details[open] > summary { margin-bottom: var(--space-8); }

/* Match gallery shelves across built-in moods and plugin scene collections on phones. */
@media (max-width: 640px) {
  .mood-group .mood-buttons, .scene-tiles:has(> .scene) {
    display: grid; grid-template-columns: none; grid-template-rows: auto; grid-auto-flow: column; grid-auto-columns: 160px;
    gap: var(--space-12); overflow-x: auto; overscroll-behavior-x: contain; scroll-snap-type: x proximity;
    margin-inline: 0; padding: 3px; scroll-padding-inline: 3px; mask-image: none; -webkit-mask-image: none;
  }
  .scene-tiles > .scene { scroll-snap-align: start; }
}

/* Workflow rows stack vertically; generic editor select flex-bases apply to horizontal rows only. */
.scene-flow-body .editor-row { flex-wrap: nowrap; min-width: 0; }
.scene-flow-body .editor-row select, .scene-flow-body .editor-row > select:first-child { flex: none; }
.scene-flow-body .editor-row > .group-inline { flex: none; width: 100%; min-width: 0; }
.scene-flow-body .editor-list, .scene-flow-body .days { min-width: 0; max-width: 100%; }
@media (max-width: 700px) {
  .scene-flow-body .day { width: 44px; height: 44px; }
}

.scene-flow-body .scene-condition-fields { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-14); }
.condition-time-point { display: grid; gap: var(--space-6); min-width: 0; }
.condition-time-point > .group-inline { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-8); }
@media (max-width: 440px) {
  .scene-flow-body { padding: var(--space-8); }
  .scene-flow-body .editor-row { padding: var(--space-10); gap: var(--space-12); }
  .scene-flow-body .scene-condition-remove { align-self: stretch; width: 100%; margin-top: var(--space-4); }
}
