/* DeskMGR: styles for the contents of app windows */

.app { display: flex; flex: 1; height: 100%; min-height: 0; min-width: 0; overflow: hidden; }
.app-col { display: flex; flex-direction: column; height: 100%; min-height: 0; min-width: 0; flex: 1; }
.sidebar {
  width: 210px; flex: 0 0 210px; border-right: 1px solid var(--line);
  background: color-mix(in srgb, var(--win-bg) 60%, var(--hb-bg));
  overflow: auto; padding: 8px;
}
.sidebar h4 { margin: 12px 8px 6px; font-size: 11px; text-transform: uppercase; letter-spacing: .07em; color: var(--dimmer); }
.side-item {
  display: flex; align-items: center; gap: 9px; width: 100%; text-align: left;
  padding: 8px 10px; border: 1px solid transparent; border-radius: 9px;
  background: transparent; color: var(--win-fg); cursor: pointer; font-size: 13px;
  transition: background .1s, border-color .1s;
}
.side-item:hover { background: var(--btn); border-color: var(--line-strong); }
.side-item.on { background: var(--accent); border-color: transparent; color: var(--accent-fg); }
.side-item svg { width: 15px; height: 15px; fill: currentColor; opacity: .85; flex: none; }
.side-item .count { margin-left: auto; font-size: 11px; opacity: .7; font-variant-numeric: tabular-nums; }

.toolbar {
  display: flex; align-items: center; gap: 8px; padding: 9px 12px;
  border-bottom: 1px solid var(--line); flex: none; flex-wrap: wrap;
}
.toolbar .grow { flex: 1; }
.search {
  display: flex; align-items: center; gap: 7px; padding: 5px 10px; min-width: 180px;
  background: var(--sunken); border: 1px solid var(--line-strong); border-radius: 9px;
}
.search input { border: 0; background: transparent; outline: none; width: 100%; font-size: 13px; user-select: text; }
.search svg { width: 13px; height: 13px; fill: var(--dimmer); }

.scroll { flex: 1; min-height: 0; overflow: auto; }
.pad { padding: 14px; }

/* boxed list, the Adwaita staple */
.list { border: 1px solid var(--line); border-radius: 12px; overflow: hidden; background: var(--card); }
.list + .list { margin-top: 14px; }
.row {
  display: flex; align-items: center; gap: 12px; padding: 11px 14px;
  border-bottom: 1px solid var(--line); background: var(--card);
  border-left: 3px solid transparent;
  transition: background .1s, border-color .1s;
}
.row:last-child { border-bottom: 0; }
.row:hover { background: var(--card-hi); border-left-color: var(--line-strong); }
.row.sel { border-left-color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, var(--card)); }
.row .title { font-size: 13.5px; font-weight: 600; display: flex; align-items: center; gap: 8px; }
.row .sub { font-size: 11.5px; color: var(--dim); margin-top: 2px; font-family: var(--mono); }
.row .main { min-width: 0; flex: 1; }
.row .main .title, .row .main .sub { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.row .acts { display: flex; gap: 5px; opacity: 0; transition: opacity .12s; }
.row:hover .acts, .row.sel .acts { opacity: 1; }
.list-head {
  display: flex; align-items: center; gap: 12px; padding: 7px 14px;
  font-size: 11px; text-transform: uppercase; letter-spacing: .06em; color: var(--dimmer);
  background: color-mix(in srgb, var(--card) 70%, var(--hb-bg)); border-bottom: 1px solid var(--line);
}

.dot { width: 9px; height: 9px; border-radius: 50%; flex: none; box-shadow: 0 0 0 3px color-mix(in srgb, currentColor 18%, transparent); }
.dot.running { background: #3ab55a; color: #3ab55a; }
.dot.exited { background: #8b8b8b; color: #8b8b8b; }
.dot.paused { background: #e5a50a; color: #e5a50a; }
.dot.created { background: #3584e4; color: #3584e4; }
.dot.dead, .dot.restarting { background: #e62d42; color: #e62d42; }

.chip {
  display: inline-flex; align-items: center; gap: 5px; padding: 2px 8px; border-radius: 20px;
  font-size: 11px; font-weight: 600; background: var(--btn); border: 1px solid transparent; color: var(--dim);
  white-space: nowrap;
}
.chip.accent { background: color-mix(in srgb, var(--accent) 20%, transparent); color: var(--accent); border-color: color-mix(in srgb, var(--accent) 35%, transparent); }
.chip.green { background: rgba(58,181,90,.18); color: #4cc46c; border-color: rgba(58,181,90,.35); }
.chip.red { background: rgba(230,45,66,.16); color: #ff6b6b; border-color: rgba(230,45,66,.35); }
.chip.link { cursor: pointer; }
.chip.link:hover { border-color: var(--accent); color: var(--accent); }
.chips { display: flex; gap: 5px; flex-wrap: wrap; }

.stat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; }
.stat {
  background: var(--card); border: 1px solid var(--line); border-radius: 12px; padding: 12px 14px;
  transition: border-color .12s;
}
.stat:hover { border-color: var(--line-strong); }
.stat .k { font-size: 11px; text-transform: uppercase; letter-spacing: .06em; color: var(--dimmer); }
.stat .v { font-size: 22px; font-weight: 700; margin-top: 4px; font-variant-numeric: tabular-nums; }
.stat .v small { font-size: 12px; font-weight: 500; color: var(--dim); }

.kv { display: grid; grid-template-columns: 190px 1fr; gap: 2px 14px; font-size: 13px; }
.kv dt { color: var(--dim); padding: 7px 0; border-bottom: 1px solid var(--line); }
.kv dd { margin: 0; padding: 7px 0; border-bottom: 1px solid var(--line); font-family: var(--mono); font-size: 12px; user-select: text; word-break: break-all; }

.section-title { font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--dimmer); margin: 18px 2px 8px; }
.section-title:first-child { margin-top: 2px; }

/* terminal */
.term-stack { flex: 1; min-height: 0; position: relative; display: flex; flex-direction: column; }
.term-stack > .term-host { flex: 1; min-height: 0; }
.term-tabs { background: #131318; border-bottom-color: rgba(255,255,255,.08); }
.term-tabs .tab { display: flex; align-items: center; gap: 7px; max-width: 190px; }
.term-tabs .tab.on { background: #0b0b0f; border-color: rgba(255,255,255,.1); color: #eee; }
.term-tabs .t-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.term-tabs .t-x { opacity: .5; padding: 0 2px; border-radius: 4px; font-size: 15px; line-height: 1; }
.term-tabs .t-x:hover { opacity: 1; background: rgba(255,255,255,.16); }
.term-wrap { height: 100%; background: #0b0b0f; display: flex; flex-direction: column; }
.term {
  flex: 1; min-height: 0; overflow: hidden; padding: 8px 10px;
  font-family: var(--mono); font-size: 13px; line-height: 1.28;
  color: #d8d8d8; white-space: pre; cursor: text; outline: none;
  user-select: text;
}
.term .cur { background: #d8d8d8; color: #0b0b0f; }
.term .cur.off { background: transparent; color: inherit; }
.term-bar { display: flex; align-items: center; gap: 8px; padding: 6px 10px; border-top: 1px solid rgba(255,255,255,.08); background: #131318; font-size: 12px; color: rgba(255,255,255,.55); }

/* logs */
.logview {
  flex: 1; min-height: 0; overflow: auto; background: var(--sunken);
  font-family: var(--mono); font-size: 12px; line-height: 1.45; padding: 10px 12px;
  user-select: text;
}
.logline { white-space: pre-wrap; word-break: break-word; }
.logline.err { color: #ff8080; }
.logline.e2 { border-left: 2px solid rgba(229,165,10,.55); padding-left: 7px; margin-left: -9px; }
.logline .ts { color: var(--dimmer); }
.log-empty { color: var(--dimmer); padding: 20px; text-align: center; }

/* charts */
.chart { width: 100%; height: 120px; display: block; }
.chart-card { background: var(--card); border: 1px solid var(--line); border-radius: 12px; padding: 12px 14px; }
.chart-card h5 { margin: 0 0 2px; font-size: 13px; display: flex; justify-content: space-between; align-items: baseline; }
.chart-card h5 span { font-variant-numeric: tabular-nums; color: var(--dim); font-weight: 500; font-size: 12px; }
.legend { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 8px; font-size: 11px; color: var(--dim); }
.legend i { display: inline-block; width: 9px; height: 9px; border-radius: 3px; margin-right: 5px; vertical-align: -1px; }

/* files */
.path-bar { display: flex; align-items: center; gap: 2px; flex-wrap: wrap; font-size: 12px; }
.path-bar button {
  border: 1px solid transparent; background: var(--btn); border-radius: 7px; padding: 3px 8px;
  cursor: pointer; color: var(--win-fg); font-size: 12px;
}
.path-bar button:hover { border-color: var(--line-strong); background: var(--btn-hover); }
.path-bar span { color: var(--dimmer); }
.file-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(112px, 1fr)); gap: 6px; }
.file-tile {
  display: flex; flex-direction: column; align-items: center; gap: 7px; padding: 12px 6px;
  border: 1px solid transparent; border-radius: 11px; background: transparent; cursor: pointer;
  color: var(--win-fg); transition: background .1s, border-color .1s;
}
.file-tile:hover { background: var(--btn); border-color: var(--line-strong); }
.file-tile svg { width: 34px; height: 34px; fill: var(--accent); }
.file-tile.f svg { fill: var(--dimmer); }
.file-tile span { font-size: 11.5px; text-align: center; word-break: break-all; line-height: 1.25; max-height: 2.6em; overflow: hidden; }
.file-view { font-family: var(--mono); font-size: 12px; white-space: pre-wrap; user-select: text; line-height: 1.5; }

/* software catalog */
/* The catalogue reads as a store rather than a list: a big rounded app tile of
   the kind every app store has trained people to recognise, room for the name to
   breathe, and the image reference demoted to a footnote since it is the least
   interesting thing on the card. */
.cat-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(268px, 1fr)); gap: 14px; }
.cat-card {
  display: flex; gap: 14px; padding: 16px; text-align: left; align-items: flex-start;
  background: var(--card); border: 1px solid var(--line); border-radius: 16px;
  cursor: pointer; color: var(--win-fg);
  transition: border-color .14s, transform .12s, background .14s, box-shadow .14s;
}
.cat-card:hover {
  border-color: var(--accent); background: var(--card-hi);
  transform: translateY(-3px); box-shadow: 0 10px 26px rgba(0,0,0,.28);
}
.cat-card .app-ico {
  width: 56px; height: 56px; flex: none; border-radius: 14px;
  box-shadow: 0 2px 8px rgba(0,0,0,.25), inset 0 1px 0 rgba(255,255,255,.22);
}
.cat-card .app-ico svg { width: 54%; height: 54%; }
.cat-card b { font-size: 15px; display: block; letter-spacing: -.01em; }
.cat-card p { margin: 4px 0 0; font-size: 12px; color: var(--dim); line-height: 1.45; }
.cat-card code { font-size: 10.5px; color: var(--dimmer); font-family: var(--mono); margin-top: 6px; }
/* The category, so a card says what kind of thing it is without the sidebar. */
.cat-chip {
  display: inline-block; margin-top: 7px; padding: 2px 8px; border-radius: 999px;
  font-size: 10.5px; font-weight: 600; letter-spacing: .02em;
  background: color-mix(in srgb, var(--accent) 18%, transparent);
  color: var(--accent); border: 1px solid color-mix(in srgb, var(--accent) 35%, transparent);
}

/* account page */
.avatar-big {
  width: 64px; height: 64px; border-radius: 50%; flex: none;
  background: linear-gradient(150deg, var(--accent), #9141ac);
  background-size: cover; background-position: center;
  border: 2px solid var(--line-strong); display: grid; place-items: center; position: relative;
}
.avatar-big:not(.has)::after {
  content: ""; width: 26px; height: 26px; border-radius: 50%;
  background: rgba(255,255,255,.92);
  box-shadow: 0 20px 0 -3px rgba(255,255,255,.92);
  transform: translateY(-5px);
}

/* shell theme gallery */
.skin-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 10px; }
.skin-card {
  display: flex; flex-direction: column; gap: 7px; padding: 8px; cursor: pointer;
  background: var(--card); border: 1px solid var(--line); border-radius: 10px; color: var(--win-fg);
  font-size: 12px; text-align: left; transition: border-color .12s, transform .1s;
}
.skin-card:hover { border-color: var(--line-strong); transform: translateY(-2px); }
.skin-card.on { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.skin-prev { position: relative; display: block; height: 82px; border-radius: 6px; overflow: hidden; }
.skin-prev .sp-bar { position: absolute; left: 0; right: 0; bottom: 0; height: 12px; }
.skin-prev .sp-bar.top { top: 0; bottom: auto; height: 10px; }
.skin-prev .sp-win {
  position: absolute; left: 16px; top: 22px; right: 16px; height: 40px; border-radius: 3px;
  box-shadow: 0 3px 10px rgba(0,0,0,.45); border: 1px solid rgba(0,0,0,.25);
}

/* settings */
.settings-group { background: var(--card); border: 1px solid var(--line); border-radius: 12px; overflow: hidden; }
.settings-row {
  display: flex; align-items: center; gap: 14px; padding: 12px 14px; border-bottom: 1px solid var(--line);
  border-left: 3px solid transparent; transition: background .1s, border-color .1s;
}
.settings-row:last-child { border-bottom: 0; }
.settings-row:hover { background: var(--card-hi); border-left-color: var(--line-strong); }
.settings-row .main { flex: 1; }
.settings-row b { font-size: 13.5px; font-weight: 600; display: block; }
.settings-row small { font-size: 11.5px; color: var(--dim); }
.wall-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 10px; }
.wall {
  height: 76px; border-radius: 10px; border: 2px solid transparent; cursor: pointer;
  position: relative; overflow: hidden; transition: border-color .12s, transform .1s;
  padding: 0; background: var(--sunken);
}
.wall:hover { transform: translateY(-2px); border-color: var(--line-strong); }
.wall.on { border-color: var(--accent); }
.wall-prev { position: absolute; inset: 0; display: block; }
.wall-prev .wp { position: absolute; inset: 0; }
.wall-name {
  position: absolute; left: 0; right: 0; bottom: 0; font-size: 10.5px; padding: 3px 6px;
  background: rgba(0,0,0,.5); color: #fff; text-align: left;
}
.wall-rm {
  position: absolute; top: 4px; right: 4px; width: 20px; height: 20px; border-radius: 50%;
  background: rgba(0,0,0,.55); display: grid; place-items: center; opacity: 0; transition: opacity .12s;
}
.wall:hover .wall-rm { opacity: 1; }
.wall-rm:hover { background: #e62d42; }
.wall-rm svg { width: 9px; height: 9px; fill: #fff; }
.accent-row { display: flex; gap: 9px; flex-wrap: wrap; }
.accent-dot { width: 28px; height: 28px; border-radius: 50%; border: 2px solid transparent; cursor: pointer; transition: transform .1s; }
.accent-dot:hover { transform: scale(1.12); }
.accent-dot.on { border-color: var(--win-fg); }

/* misc */
.spinner { width: 18px; height: 18px; border-radius: 50%; border: 2px solid var(--line-strong); border-top-color: var(--accent); animation: spin .7s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }
.center-msg { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px; height: 100%; color: var(--dim); font-size: 13px; text-align: center; padding: 30px; }
.center-msg svg { width: 46px; height: 46px; fill: var(--dimmer); }
.mono { font-family: var(--mono); font-size: 12px; user-select: text; }
.muted { color: var(--dim); }
.pre { font-family: var(--mono); font-size: 12px; white-space: pre-wrap; user-select: text; background: var(--sunken); border: 1px solid var(--line); border-radius: 10px; padding: 12px; max-height: 320px; overflow: auto; }
.tabs { display: flex; gap: 4px; padding: 8px 12px 0; border-bottom: 1px solid var(--line); flex: none; }
.tab {
  padding: 7px 13px; border: 1px solid transparent; border-bottom: 0; border-radius: 9px 9px 0 0;
  background: transparent; cursor: pointer; font-size: 12.5px; font-weight: 600; color: var(--dim);
  margin-bottom: -1px;
}
.tab:hover { background: var(--btn); border-color: var(--line-strong); color: var(--win-fg); }
.tab.on { background: var(--win-bg); border-color: var(--line); color: var(--win-fg); }

/* The deploy dialog's status line while the engine works: spinner beside the
   message, so a slow pull looks like progress rather than a frozen dialog. */
.deploy-status.busy { display: flex; align-items: center; gap: 10px; }
.deploy-status.busy .spinner { flex: none; }

/* The favourite star on a catalog card. Sits in the corner and must not swallow
   the card's own click except on itself. */
.cat-card { position: relative; }
.cat-star {
  position: absolute; top: 8px; right: 10px; font-style: normal; font-size: 15px;
  line-height: 1; color: var(--dim); cursor: pointer; padding: 2px; border-radius: 4px;
  transition: color .12s, transform .12s;
}
.cat-star:hover { color: #e5a50a; transform: scale(1.15); }
.cat-star.on { color: #e5a50a; }
.side-item .count { margin-left: auto; font-size: 11px; color: var(--dim); }

/* The deploy dialog was portrait and scrolled: two columns on anything but a
   phone puts ports, environment and volumes beside the image and name instead
   of below them, which halves its height. */
@media (min-width: 700px) {
  .modal .deploy-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0 18px; align-items: start; }
  .modal .deploy-grid > .field-wide { grid-column: 1 / -1; }
}
.modal .modal-body { max-height: min(70vh, 620px); overflow: auto; }

/* A card's description was clipped mid-word in a narrow window because the grid
   track could shrink below the text. Let the text wrap and the track hold. */
.cat-grid { grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); }
.cat-card > span { min-width: 0; }
.cat-card p { white-space: normal; overflow-wrap: anywhere; }
.cat-card code { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* A public app is the exception now, so it is the thing that gets marked: an
   amber link button, so "is this open to the world" is answerable by looking. */
.btn.icon.is-public { color: #e5a50a; border-color: rgba(229,165,10,.5); }
.btn.icon.is-public svg { fill: #e5a50a; }

/* Icon and colour pickers for a desktop icon. */
.ico-grid { display: grid; grid-template-columns: repeat(9, 1fr); gap: 6px; max-height: 190px; overflow: auto; padding: 2px; }
.ico-pick {
  aspect-ratio: 1; display: grid; place-items: center; cursor: pointer;
  background: var(--sunken, rgba(128,128,128,.12)); border: 1px solid transparent;
  border-radius: 8px; transition: border-color .12s, background .12s;
}
.ico-pick svg { width: 16px; height: 16px; fill: currentColor; }
.ico-pick:hover { border-color: var(--line-strong); }
.ico-pick.on { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 22%, transparent); }
.col-row { display: flex; flex-wrap: wrap; gap: 8px; }
.col-pick { width: 30px; height: 30px; border-radius: 8px; cursor: pointer; border: 2px solid transparent; }
.col-pick:hover { border-color: var(--line-strong); }
.col-pick.on { border-color: #fff; box-shadow: 0 0 0 2px var(--accent); }

/* The headline numbers above the charts. A chart shows a trend; someone opening
   the monitor wants to know what it is right now, first. */
.live-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px; }
.live-tile {
  background: var(--card); border: 1px solid var(--line); border-radius: 14px; padding: 14px 16px;
}
.live-tile .k { font-size: 11px; text-transform: uppercase; letter-spacing: .08em; color: var(--dim); }
.live-tile b { display: block; font-size: 26px; font-weight: 700; margin-top: 4px; letter-spacing: -.02em; }
.live-tile small { display: block; color: var(--dim); font-size: 11.5px; margin-top: 2px; min-height: 14px; }
.live-tile .bar {
  display: block; height: 4px; border-radius: 3px; margin-top: 10px;
  background: var(--sunken, rgba(128,128,128,.25)); overflow: hidden;
}
.live-tile .bar u { display: block; height: 100%; width: 0; background: var(--accent); transition: width .4s; }
.live-tile[data-k="cpu"] .bar u { background: #ed5b00; }
.live-tile[data-k="mem"] .bar u { background: #3584e4; }
.live-tile[data-k="disk"] .bar u { background: #3a944a; }

/* usage bar inside a storage row; the live tiles have their own .bar and this
   sits in a different place, so it gets its own name rather than fighting them */
.fsbar { display: block; height: 3px; border-radius: 2px; background: var(--line-strong); margin-top: 7px; overflow: hidden; max-width: 460px; }
.fsbar u { display: block; height: 100%; width: 0; background: var(--accent); transition: width .4s; }

/* A section that is reloading keeps what it had, greyed, with a spinner over it.
   Blanking to a spinner throws away what someone was reading, and showing
   nothing at all is why listing backups felt like a hang: it runs a container
   against the target, which is seconds, not milliseconds. */
.body.loading { position: relative; pointer-events: none; }
.body.loading > * { opacity: .35; filter: grayscale(.6); transition: opacity .15s; }
.body.loading::after {
  content: ""; position: absolute; left: 50%; top: 48px;
  width: 26px; height: 26px; margin-left: -13px; border-radius: 50%;
  border: 3px solid var(--line-strong); border-top-color: var(--accent);
  animation: btnspin .7s linear infinite;
}

/* Weather place search results.
   The results sat flush against the search row with nothing between them, so
   they read as part of the control rather than as an answer to it. */
.wx-results:empty { display: none; }
.wx-results { margin: 12px 2px 4px; }
.wx-head {
  font-size: 11px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase;
  color: var(--dim); margin-bottom: 6px;
}
.wx-note { display: flex; align-items: center; gap: 8px; color: var(--dim); font-size: 12.5px; padding: 6px 2px; }

.wx-list {
  border: 1px solid var(--line-strong); border-radius: 11px; overflow: hidden;
  background: var(--sunken);
}
.wx-place {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 9px 11px; background: none; border: 0; cursor: pointer; text-align: left;
  color: var(--win-fg); border-top: 1px solid var(--line);
}
.wx-place:first-child { border-top: 0; }
.wx-place:hover, .wx-place:focus-visible { background: var(--btn-hover); outline: none; }
.wx-pin { display: grid; place-items: center; width: 22px; height: 22px; flex: none; border-radius: 6px; background: var(--line); }
.wx-pin svg { width: 13px; height: 13px; fill: var(--dim); }
/* The name is the only part allowed to take the slack, so a long place name
   truncates instead of pushing the coordinates out of the row. */
.wx-where { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1; }
.wx-where b { font-size: 13px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wx-where small { font-size: 11.5px; color: var(--dim); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wx-co { font-size: 11px; color: var(--dim); font-variant-numeric: tabular-nums; flex: none; }
@media (max-width: 620px) { .wx-co { display: none; } }

/* The editable file view. A textarea filling the window, monospaced, with the
   same padding as the read only view so switching between them does not move
   the text. */
.file-edit-wrap { position: absolute; inset: 0; display: flex; }
.file-edit {
  flex: 1; width: 100%; resize: none; border: 0; outline: none;
  padding: 14px 16px; background: var(--sunken); color: var(--win-fg);
  font: 12.5px/1.55 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  tab-size: 4; white-space: pre; overflow: auto; user-select: text;
}

/* Updates.

   The banner carries the state as colour and shape so it reads before the words
   do: an accent ring when there is something to install, a flat one when there
   is not. The log below it only exists once an upgrade is running, because an
   empty console under a button is noise. */
.upd-hero {
  display: flex; gap: 14px; align-items: flex-start;
  background: var(--card); border: 1px solid var(--line); border-radius: 12px;
  padding: 16px 18px;
}
.upd-hero.on { border-color: color-mix(in srgb, var(--accent) 45%, var(--line)); }
.upd-hero h3 { margin: 0 0 4px; font-size: 15px; }
.upd-hero .muted { font-size: 13px; line-height: 1.55; }
.upd-hero a { color: var(--accent); }
.upd-badge {
  flex: none; width: 40px; height: 40px; border-radius: 11px;
  display: grid; place-items: center; border: 1px solid var(--line);
  background: var(--sunken);
}
.upd-badge svg { width: 20px; height: 20px; }
.upd-badge.accent { color: var(--accent); border-color: color-mix(in srgb, var(--accent) 40%, transparent); background: color-mix(in srgb, var(--accent) 14%, transparent); }
.upd-badge.ok { color: #4cc46c; border-color: rgba(58,181,90,.35); background: rgba(58,181,90,.14); }
.upd-badge.muted { color: var(--dim); }

.upd-log {
  margin-top: 12px; max-height: 200px; overflow: auto;
  background: var(--sunken); border: 1px solid var(--line); border-radius: 10px;
  padding: 10px 12px;
  font: 12px/1.7 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
.upd-line { color: var(--dim); }
.upd-line.ok { color: #4cc46c; }
.upd-line.err { color: #ff6b6b; }

/* A short explanation attached to a control, as opposed to a toast, which goes
   away. Used where the reason a button is missing has to stay on screen. */
.note {
  background: var(--sunken); border: 1px solid var(--line); border-left: 3px solid var(--dim);
  border-radius: 8px; padding: 10px 12px; font-size: 13px; line-height: 1.55; color: var(--dim);
}
.note.warn { border-left-color: #e5a50a; color: var(--win-fg); }
.note code { font-size: 12px; }

/* The submit sits in a footer below the panel it belongs to, never floating
   above the fields it applies to. */
.form-footer {
  display: flex; justify-content: flex-end; gap: 8px; flex-wrap: wrap;
  margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--line);
}

/* The dot on a sidebar row that has something waiting behind it. */
.side-item { position: relative; }
.side-dot {
  position: absolute; right: 10px; top: 50%; transform: translateY(-50%);
  width: 7px; height: 7px; border-radius: 50%; background: var(--accent);
}

/* Demo mode.

   A bar the whole width of the screen, above everything, that says what this is
   and where to get the real one. It is not dismissible on purpose: a visitor who
   closes it and then finds every button refusing them has been misled. */
.demo-bar {
  position: fixed; left: 0; right: 0; top: 0; z-index: 400;
  display: flex; align-items: center; justify-content: center; gap: 10px;
  height: 30px; padding: 0 12px;
  background: linear-gradient(90deg, #3584e4, #9141ac);
  color: #fff; font-size: 12.5px; font-weight: 600;
  box-shadow: 0 1px 6px rgba(0,0,0,.35);
}
.demo-bar a {
  color: #fff; text-decoration: none; border: 1px solid rgba(255,255,255,.55);
  border-radius: 999px; padding: 2px 10px; font-weight: 600;
}
.demo-bar a:hover { background: rgba(255,255,255,.18); border-color: #fff; }
.demo-bar .demo-what { opacity: .92; font-weight: 500; }
@media (max-width: 700px) { .demo-bar .demo-what { display: none; } }
/* Everything else moves down by exactly the bar's height rather than sitting
   under it. The desktop already lays itself out from --pad-*, so the bar adds
   to the top one instead of introducing a second mechanism. */
body.demo { --demo-bar: 30px; }
