@import url("code.css");

:root {
  color-scheme: only light;
  --ink: #09140d;
  --heading: #09140d;
  --ink-soft: #14231a;
  --control-text: var(--ink-soft);
  --strong-text: var(--ink-soft);
  --shadow: var(--ink);
  --shadow-distance: 8px;
  --shadow-alpha: 40%;
  --paper: #f8f2dd;
  --paper-deep: #f3ecd1;
  --paper-line: #d8cfa9;
  --sage: #66755a;
  --leaf: #4fae7d;
  --leaf-deep: #276b47;
  --menu-text: #f5efdb;
  --menu-dim: #8fcaa8;
  --desktop: #e3ddc6;
  /* Window chrome. These default to --ink so themes written before the roles
     existed keep their original look; set them to split window frames from
     the menu bar and taskbar. */
  --titlebar: var(--ink);
  --window-border: var(--ink);
  --window-inactive: #2a3b2f;
  --window-border-inactive: var(--window-inactive);
  --title-text: #c8e3d2;
  /* falls back to the active colour, so themes written before the split
     (and any theme that omits it) keep their old inactive titles */
  --title-text-inactive: var(--title-text);
  --accent-hover: #6fcf9a;
  --button-text: #f2ecd6;
  --disabled-text: #b3ab8d;
  /* Status roles. The palette proper had no word for "this went wrong" or
     "careful", so every app that needed one spelled its own red or amber out in
     hex and then kept it through a theme change — a swamp-red error over the
     blood palette, an amber busy lamp glowing on midnight. --ok and --info lean
     on colours a theme already sets, so even a theme written before these
     existed moves them; --danger and --warning have no palette equivalent to
     borrow from and fall back to these until a theme names its own. */
  --danger: #a04a3a;
  --warning: #b58b3a;
  --ok: var(--leaf-deep);
  --info: #3f66ad;
  /* Scrims behind modals, dialogs and drop targets. Derived from --shadow
     rather than stated, so they darken with whatever the theme darkens with
     instead of laying the default palette's near-black green over a pale one. */
  --overlay: color-mix(in srgb, var(--shadow) 42%, transparent);
  --overlay-strong: color-mix(in srgb, var(--shadow) 82%, transparent);
  /* Plot traces and chart series — the serial and MIDI consoles, the gamma
     table, the graphing calculator. Six is what the busiest of them draws at
     once. Deriving them means a new theme gets a matching set of traces
     without having to know the role exists. */
  --series-1: var(--leaf-deep);
  --series-2: var(--danger);
  --series-3: var(--info);
  --series-4: var(--warning);
  --series-5: var(--sage);
  --series-6: var(--leaf);
  /* Media treatment is deliberately separate from the interface palette.
     It affects photographs, video, canvases and the desktop wallpaper without
     shifting text or control colours. */
  --media-grayscale: 0%;
  --media-sepia: 0%;
  --media-saturate: 100%;
  --media-hue: 0deg;
  --media-brightness: 100%;
  --media-contrast: 100%;
  --media-filter: none;
}
* { margin: 0; padding: 0; box-sizing: border-box; }
html, body { height: 100%; overflow: hidden; }
body {
  font-family: 'IBM Plex Mono', monospace;
  background: var(--desktop);
  color: var(--ink-soft);
  user-select: none;
}

/* ---------- Menu bar ---------- */
#menubar {
  position: fixed; top: 0; left: 0; right: 0; height: 34px; z-index: 9000;
  background: var(--ink); color: var(--menu-text);
  display: flex; align-items: stretch; gap: 2px; padding: 0 10px;
  font-size: 13px; font-weight: 500;
}
#menubar .logo {
  display: flex; align-items: center; padding: 0 8px;
}
#menubar .logo span {
  width: 14px; height: 14px; background: var(--leaf); border-radius: 3px; display: block;
}
.menu { position: relative; display: flex; align-items: center; }
.menu > button {
  all: unset; cursor: pointer; padding: 0 12px; height: 100%;
  display: flex; align-items: center; font: inherit; color: inherit;
}
.menu > button:hover, .menu.open > button { background: var(--leaf-deep); }
.menu > button:focus-visible { outline: 2px solid var(--leaf); outline-offset: -2px; }
.dropdown {
  position: absolute; top: 34px; left: 0;
  background: transparent; color: var(--control-text);
  display: none; padding: 7px 2px; z-index: 9001;
  /* How much width this menu is allowed. In a roomy browser window that is no
     constraint at all and the menu is its natural width, no narrower than
     220px; when the window is too small for the menu (or for the fly-out that
     has to sit beside it) clackos.js replaces --room with what is really
     available and the menu narrows to fit, wrapping its labels, rather than
     disappearing off the edge. Declared here rather than inherited so a
     fly-out never picks up its parent's allowance. */
  --room: 100vw;
  min-width: min(220px, var(--room));
  max-width: var(--room);
}
.dropdown::before {
  content: ''; position: absolute; inset: 0; z-index: -2;
  transform: translate(calc(var(--shadow-distance) * 0.75), calc(var(--shadow-distance) * 0.75));
  border-radius: 0 0 8px 8px;
  background-image: repeating-conic-gradient(color-mix(in srgb, var(--shadow) var(--shadow-alpha), transparent) 0 25%, transparent 0 50%);
  background-size: 2px 2px;
}
.dropdown::after {
  content: ''; position: absolute; inset: 0; z-index: -1;
  background: var(--paper); border: 2px solid var(--ink);
  border-radius: 0 0 8px 8px;
}
.menu.open > .dropdown { display: block; }
.dropdown button {
  all: unset; box-sizing: border-box; cursor: pointer;
  display: flex; align-items: center; justify-content: space-between; gap: 24px;
  width: 100%; padding: 7px 16px; font: inherit; font-size: 12.5px; color: var(--control-text);
}
.dropdown .pixel-icon { width: 16px; height: 16px; }
.dropdown button:hover:not(:disabled) { background: var(--ink); color: var(--menu-text); }
.dropdown button:disabled { color: var(--disabled-text); cursor: default; }
.dropdown .sep { height: 1px; background: var(--paper-line); margin: 6px 0; }
.dropdown .check { color: var(--leaf-deep); }
.dropdown button:hover .check { color: var(--leaf); }

/* nested submenus fly out to the right of their parent item */
.submenu { position: relative; }
.submenu > .submenu-btn .arrow { color: var(--leaf-deep); font-size: 11px; }
.submenu:hover > .submenu-btn,
.submenu.open > .submenu-btn { background: var(--ink); color: var(--menu-text); }
.submenu:hover > .submenu-btn .arrow,
.submenu.open > .submenu-btn .arrow { color: var(--leaf); }
.dropdown.sub { top: 0; left: 100%; z-index: 9002; }
.dropdown.sub::before,
.dropdown.sub::after { border-radius: 0 8px 8px 8px; }
/* A menu narrowed to fit the window wraps its labels rather than spilling over
 * the paper edge, and once it is that tight it also gives the text back the
 * room normally spent on padding and on the gap out to a shortcut or arrow. */
.dropdown .menu-item-label { overflow-wrap: anywhere; }
.dropdown.narrow button { gap: 8px; padding-left: 9px; padding-right: 9px; }
.dropdown.narrow .menu-item-label { gap: 0.4em; }
.submenu:hover > .dropdown.sub,
.submenu.open > .dropdown.sub { display: block; }
/* ---------- Date pill, clock and the upcoming-events pull-down ---------- */
#menubar-right { margin-left: auto; display: flex; align-items: stretch; gap: 2px; }
#clock { display: flex; align-items: center; padding: 0 6px; color: var(--menu-text); font-size: 12px; }
/* the colon blinks once a second, in step with the wall clock: clackos.js sets
   a negative animation-delay so the phase matches the current second */
#clock .tick { animation: clock-tick 1s steps(1, end) infinite; }
@keyframes clock-tick { 0%, 49.9% { opacity: 1; } 50%, 100% { opacity: 0; } }
@media (prefers-reduced-motion: reduce) { #clock .tick { animation: none; } }

#events-pill {
  all: unset; cursor: pointer; display: flex; align-items: center; gap: 6px;
  padding: 0 9px; font: inherit; font-size: 12px; color: var(--menu-text);
}
#events-pill:hover, #events-pill[aria-expanded="true"] { background: var(--leaf-deep); color: var(--menu-text); }
#events-pill:focus-visible { outline: 2px solid var(--leaf); outline-offset: -2px; }
#events-pill .pill-arrow { color: var(--leaf); font-size: 10px; line-height: 1; }
#events-pill:hover .pill-arrow, #events-pill[aria-expanded="true"] .pill-arrow { color: var(--menu-text); }

/* Built like a .dropdown — same paper, border and pixel shadow — but anchored
   to the right-hand end of the menu bar rather than to a menu button. */
#events-panel {
  position: absolute; top: 34px; right: 8px; z-index: 9001;
  width: min(370px, calc(100vw - 16px)); max-height: min(70vh, 560px);
  display: flex; flex-direction: column;
  color: var(--control-text); font-weight: 400;
}
#events-panel[hidden] { display: none; }
#events-panel::before {
  content: ''; position: absolute; inset: 0; z-index: -2;
  transform: translate(calc(var(--shadow-distance) * 0.75), calc(var(--shadow-distance) * 0.75));
  border-radius: 0 0 8px 8px;
  background-image: repeating-conic-gradient(color-mix(in srgb, var(--shadow) var(--shadow-alpha), transparent) 0 25%, transparent 0 50%);
  background-size: 2px 2px;
}
#events-panel::after {
  content: ''; position: absolute; inset: 0; z-index: -1;
  background: var(--paper); border: 2px solid var(--ink); border-radius: 0 0 8px 8px;
}
#events-panel > header {
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  padding: 11px 14px 8px;
}
#events-panel > header h2 {
  font-size: 11px; font-weight: 600; letter-spacing: .16em; text-transform: uppercase;
  color: var(--leaf-deep);
}
#events-panel > header span { font-size: 10.5px; color: var(--sage); }
#events-list {
  flex: 1; min-height: 0; overflow-y: auto;
  display: flex; flex-direction: column; gap: 1px; padding: 0 8px;
}
#events-panel > footer {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  margin: 8px 8px 8px; padding-top: 9px; border-top: 1px solid var(--paper-line);
}
#events-panel > footer button {
  all: unset; cursor: pointer; padding: 6px 12px; border: 1px solid var(--ink); border-radius: 6px;
  font: inherit; font-size: 12px; background: var(--ink); color: var(--button-text);
}
#events-panel > footer button:hover { background: var(--leaf-deep); border-color: var(--leaf-deep); }
#events-panel > footer button:focus-visible { outline: 2px solid var(--leaf); outline-offset: 2px; }
#events-panel > footer a { padding-right: 6px; color: var(--leaf-deep); font-size: 10.5px; }

.event-row {
  all: unset; box-sizing: border-box; cursor: pointer; display: flex; gap: 11px;
  width: 100%; padding: 8px 8px; border-radius: 6px;
  font: inherit; text-align: left; color: var(--control-text);
}
.event-row:hover { background: var(--paper-deep); }
.event-row:focus-visible { outline: 2px solid var(--leaf); outline-offset: -2px; }
.event-row + .event-row { border-top: 1px solid var(--paper-line); border-radius: 0; }
.event-row .when {
  flex: none; width: 44px; display: flex; flex-direction: column; align-items: center; gap: 1px;
  padding: 3px 0; border-radius: 5px; background: var(--ink); color: var(--button-text);
}
.event-row .when .d { font-size: 15px; font-weight: 600; line-height: 1.1; }
.event-row .when .m { font-size: 8.5px; letter-spacing: .1em; text-transform: uppercase; }
.event-row .what { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.event-row .what strong {
  font-size: 12px; font-weight: 600; color: var(--heading);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.event-row .what span { font-size: 10.5px; color: var(--sage); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.event-row.from-luma .when { background: var(--sage); }
.event-row .tag {
  align-self: flex-start; margin-top: 2px; padding: 0 5px;
  border: 1px solid var(--sage); border-radius: 4px;
  color: var(--sage); font-size: 8.5px; font-weight: 600; letter-spacing: .1em; text-transform: uppercase;
}
#events-panel .empty { padding: 4px 8px 12px; color: var(--sage); font-size: 11.5px; line-height: 1.7; }

/* ---------- Desktop ---------- */
#desktop {
  position: fixed; top: 34px; left: 0; right: 0; bottom: 44px;
  background-color: var(--desktop); overflow: hidden;
}
#desktop::before {
  content: ''; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background-image: var(--desktop-wallpaper-image, none);
  filter: var(--media-filter);
}
/* New media inherits these variables, so images and canvases introduced after
   a theme is applied receive the treatment without JavaScript bookkeeping. */
:where(img, video, canvas):not([data-media-treatment="none"]) {
  filter: var(--media-filter);
}
.desktop-icon {
  all: unset; box-sizing: border-box; position: absolute; top: 18px; left: 18px;
  z-index: 1; width: 112px; padding: 6px 4px; cursor: default;
  display: flex; flex-direction: column; align-items: center; gap: 7px;
  border: 1px solid transparent; border-radius: 4px;
  color: var(--ink); font: 500 12px/1.25 'IBM Plex Mono', monospace;
  text-align: center;
}
.desktop-icon img {
  width: 48px; height: 48px; object-fit: contain; image-rendering: pixelated;
  pointer-events: none;
}
.desktop-icon span {
  max-width: 104px; padding: 1px 3px;
  overflow-wrap: anywhere; pointer-events: none;
}
.desktop-icon:hover,
.desktop-icon:focus {
  background: color-mix(in srgb, var(--paper) 55%, transparent);
  border-color: color-mix(in srgb, var(--ink) 35%, transparent);
}
.desktop-icon:focus-visible { outline: 2px solid var(--leaf); outline-offset: 2px; }

/* ---------- Windows ---------- */
.window {
  position: absolute; display: flex; flex-direction: column;
  background: transparent; border-radius: 10px; padding: 2px;
  /* the usual floor for dragging a window smaller, but never wider or taller
     than the desktop itself: on a phone the desktop wins, so windows can still
     shrink all the way down to fit the screen */
  min-width: min(320px, calc(100% - 16px));
  min-height: min(var(--window-min-height, 180px), calc(100% - 16px));
  opacity: 1; transition: opacity 0.15s ease, transform 0.15s ease;
}
.window::before {
  content: ''; position: absolute; inset: 0; z-index: -2;
  transform: translate(var(--shadow-distance), var(--shadow-distance)); border-radius: 10px;
  background-image: repeating-conic-gradient(color-mix(in srgb, var(--shadow) var(--shadow-alpha), transparent) 0 25%, transparent 0 50%);
  background-size: 2px 2px;
}
.window::after {
  content: ''; position: absolute; inset: 0; z-index: -1;
  background: var(--paper); border-radius: 10px;
}
.frame {
  position: absolute; inset: 0; z-index: 6; pointer-events: none;
  border: 2px solid var(--window-border); border-radius: 10px;
}
@media (prefers-reduced-motion: reduce) { .window { transition: none; } }
.window.fixed { min-width: 0; min-height: 0; }
/* A window on its way out stops taking clicks the moment the dot is pressed,
   however it leaves the screen — see "Window animations" in clackos.js. */
.window.closing, .window.dissolving { pointer-events: none; }
/* the exit used when the pixel dissolve cannot run: the plain fade */
.window.closing.fade-out { opacity: 0; transform: scale(0.97); }
/* an animated window is driven frame by frame, so the shorthand transition
   above must keep out of the way */
.window.animating, .window.dissolving { transition: none; }
.window.inactive .titlebar { background: var(--window-inactive); }
.window.inactive .titlebar .title { color: var(--title-text-inactive); }
.window.inactive .frame { border-color: var(--window-border-inactive); }
.titlebar {
  background: var(--titlebar); color: var(--menu-text);
  padding: 9px 14px; display: flex; align-items: center; gap: 8px;
  border-radius: 8px 8px 0 0; cursor: grab; flex: none; touch-action: none;
}
.titlebar:active { cursor: grabbing; }
.titlebar .dot {
  all: unset; width: 11px; height: 11px; border-radius: 50%; cursor: pointer; flex: none;
  border: 1.5px solid var(--menu-text); box-sizing: border-box;
}
.titlebar .dot:focus-visible { outline: 2px solid var(--leaf); outline-offset: 2px; }
.titlebar .dot.close { background: var(--leaf); border-color: var(--leaf); }
.titlebar .dot.close:hover { background: var(--accent-hover); border-color: var(--accent-hover); }
.titlebar .dot.min:hover { background: color-mix(in srgb, var(--menu-text) 35%, transparent); }
.titlebar .dot.max { opacity: 0.5; }
.titlebar .dot.max:hover { opacity: 1; background: color-mix(in srgb, var(--menu-text) 35%, transparent); }
.titlebar .title {
  margin: 0 auto; transform: translateX(-24px);
  display: inline-flex; align-items: center; gap: 7px; min-width: 0;
  font-size: 12.5px; font-weight: 500; letter-spacing: 0.03em; color: var(--title-text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.titlebar .title-label { overflow: hidden; text-overflow: ellipsis; }
.titlebar .title-icon { width: 16px; height: 16px; color: var(--leaf); }
.winbody {
  flex: 1; overflow: auto; user-select: text;
  border-radius: 0 0 8px 8px;
  scrollbar-width: thin;
  scrollbar-color: var(--sage) var(--paper-deep);
}
.winbody::-webkit-scrollbar { width: 10px; height: 10px; }
.winbody::-webkit-scrollbar-track { background: var(--paper-deep); border-radius: 0 0 6px 0; }
.winbody::-webkit-scrollbar-thumb {
  background: var(--sage); border-radius: 6px;
  border: 2px solid var(--paper-deep);
}
.winbody::-webkit-scrollbar-thumb:hover { background: var(--leaf-deep); }
.winbody::-webkit-scrollbar-corner { background: var(--paper-deep); }
/* An integrated app normally sizes itself to the window and does its own
   scrolling, so it needs no scrollbars of its own here. Apps with a responsive
   layout that gives up on filling the height — the Eurorack Panel Generator
   stacks its controls above the preview on a narrow screen — are taller than
   the window instead, and the window body has to scroll or the overflow spills
   out of the frame and under the taskbar. */
.integrated-app-body { min-width: 0; min-height: 0; overflow: auto; user-select: text; }
.integrated-app-body.integrated-menu-open { overflow: visible; }
.integrated-app-host { width: 100%; height: 100%; }
.rs { position: absolute; touch-action: none; z-index: 5; }
.rs.n  { top: -4px; left: 12px; right: 12px; height: 9px; cursor: ns-resize; }
.rs.s  { bottom: -4px; left: 12px; right: 12px; height: 9px; cursor: ns-resize; }
.rs.e  { right: -4px; top: 12px; bottom: 12px; width: 9px; cursor: ew-resize; }
.rs.w  { left: -4px; top: 12px; bottom: 12px; width: 9px; cursor: ew-resize; }
.rs.ne { top: -4px; right: -4px; width: 16px; height: 16px; cursor: nesw-resize; }
.rs.nw { top: -4px; left: -4px; width: 16px; height: 16px; cursor: nwse-resize; }
.rs.se { bottom: -4px; right: -4px; width: 18px; height: 18px; cursor: nwse-resize; }
.rs.sw { bottom: -4px; left: -4px; width: 16px; height: 16px; cursor: nesw-resize; }

/* The styles for markdown-rendered content live in content.css, which every
   page that renders markdown loads alongside this file. */


/* ---------- App windows (iframe pages from content/) ---------- */
.appframe { display: block; width: 100%; height: 100%; border: 0; background: var(--paper); }
.appframe.theme-loading { visibility: hidden; }
/* while dragging or resizing a window, iframes must not swallow pointer events */
body.win-drag iframe { pointer-events: none; }

/* ---------- Taskbar ---------- */
#taskbar {
  position: fixed; left: 0; right: 0; bottom: 0; height: 44px; z-index: 8500;
  background: var(--ink); border-top: 2px solid var(--leaf-deep);
  display: flex; align-items: center; gap: 8px; padding: 0 10px;
}
#taskbar .tb-logo {
  width: 18px; height: 18px; background: var(--leaf);
  border-radius: 4px; flex: none; margin-right: 4px;
}
#tasks {
  display: flex; align-items: center; gap: 8px;
  flex: 1; min-width: 0; overflow-x: auto; scrollbar-width: none;
}
#tasks::-webkit-scrollbar { display: none; }
#plain-link {
  display: inline-flex; align-items: center; gap: 5px; flex: none;
  height: 28px; margin-left: auto; padding: 0 4px;
  color: color-mix(in srgb, var(--menu-text) 68%, transparent);
  text-decoration: none; white-space: nowrap;
  font-family: 'IBM Plex Mono', monospace; font-size: 10px;
  letter-spacing: 0.04em;
}
#plain-link:hover { color: var(--menu-text); text-decoration: underline; }
#plain-link:focus-visible { outline: 2px solid var(--leaf); outline-offset: 2px; }
#plain-link .pixel-icon { width: 12px; height: 12px; color: var(--leaf); }
#resource-stats {
  display: flex; align-items: center; gap: 12px; flex: none;
  height: 28px; padding-left: 12px;
  border-left: 1px solid color-mix(in srgb, var(--menu-text) 28%, transparent);
  color: color-mix(in srgb, var(--menu-text) 68%, transparent); white-space: nowrap;
  font-family: 'IBM Plex Mono', monospace; font-size: 10px;
  letter-spacing: 0.04em;
}
#resource-stats > span { display: inline-flex; align-items: center; gap: 4px; }
#resource-stats .pixel-icon { width: 12px; height: 12px; color: var(--leaf); }
#resource-stats strong { color: var(--menu-text); font-weight: 500; }
/* The load ramp reads over the chrome bar, not over paper, so each step is
   lifted towards the menu text before it is used — a theme whose --warning is
   dark enough to work on a window would otherwise vanish into the taskbar.
   "Serious" has no role of its own and sits between the two it separates. */
#cpu-stat[data-state="fair"] { color: color-mix(in oklab, var(--warning) 78%, var(--menu-text)); }
#cpu-stat[data-state="serious"] { color: color-mix(in oklab, var(--warning) 50%, var(--danger)); }
#cpu-stat[data-state="critical"] { color: color-mix(in oklab, var(--danger) 74%, var(--menu-text)); }
#build-stamp-tb {
  display: inline-flex; align-items: center; gap: 5px; flex: none;
  height: 28px; padding-left: 12px;
  border-left: 1px solid color-mix(in srgb, var(--menu-text) 28%, transparent);
  color: color-mix(in srgb, var(--menu-text) 68%, transparent);
  text-decoration: none; white-space: nowrap;
  font-family: 'IBM Plex Mono', monospace; font-size: 10px;
  letter-spacing: 0.04em;
}
#build-stamp-tb[href]:hover { color: var(--menu-text); text-decoration: underline; }
#build-stamp-tb .pixel-icon { width: 12px; height: 12px; color: var(--leaf); }
#build-sha { color: var(--menu-text); font-weight: 500; }
/* Transient system message, shown just above the taskbar */
#system-toast {
  position: fixed; left: 50%; bottom: 60px; transform: translate(-50%, 8px);
  z-index: 9500; max-width: min(520px, calc(100vw - 32px));
  padding: 9px 14px; pointer-events: none;
  background: var(--ink); color: var(--menu-text);
  border: 1.5px solid var(--leaf-deep); border-radius: 8px;
  font-family: 'IBM Plex Mono', monospace; font-size: 12px; text-align: center;
  opacity: 0; visibility: hidden; transition: opacity 0.18s ease, transform 0.18s ease;
}
#system-toast.visible { opacity: 1; visibility: visible; transform: translate(-50%, 0); }
@media (prefers-reduced-motion: reduce) { #system-toast { transition: none; } }

button.task {
  all: unset; box-sizing: border-box; cursor: pointer; flex: none;
  display: flex; align-items: center; gap: 9px;
  min-width: 120px; max-width: 210px; height: 30px; padding: 0 12px;
  font-family: 'IBM Plex Mono', monospace; font-size: 12px; color: var(--menu-text);
  border: 1.5px solid color-mix(in srgb, var(--menu-text) 35%, transparent); border-radius: 6px;
}
button.task:focus-visible { outline: 2px solid var(--leaf); outline-offset: 2px; }
button.task:hover { background: color-mix(in srgb, var(--menu-text) 12%, transparent); }
button.task .task-icon { width: 17px; height: 17px; color: var(--leaf); }
button.task .lbl { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
button.task.active { background: var(--leaf-deep); border-color: var(--leaf); }
button.task.minimised { opacity: 0.55; }
button.task.minimised .task-icon { color: var(--menu-text); }

@media (max-width: 640px) {
  .page { padding: 24px 20px; }
  #menubar { gap: 0; font-size: 12px; }
  .menu > button { padding: 0 8px; }
  /* Everything to the right of #tasks is flex: none and nowrap, so on a phone
     the readouts were taking their full width out of a 390px bar and leaving
     the window switcher — the one control in the taskbar you actually need —
     23px to sit in. The telemetry and the build stamp are furniture; they go,
     and the Plain HTML link stays, because the mirror being one tap away is
     the point of putting it there. */
  #resource-stats, #build-stamp-tb { display: none; }
  /* narrower buttons so a second window is still legible in what is left */
  button.task { min-width: 92px; max-width: 150px; padding: 0 9px; gap: 7px; }
}
