/* ============================================================
   Browser OS — shell, window manager and app styles
   ============================================================ */

* { box-sizing: border-box; }

html, body {
  height: 100%;
  margin: 0;
  overflow: hidden;
  font-family: var(--font);
  color: var(--text);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  overscroll-behavior: none;
}

button, input, textarea, select { font: inherit; color: inherit; }

.hidden { display: none !important; }

.os { position: fixed; inset: 0; }

/* ---------- wallpaper ---------- */
.wallpaper {
  position: absolute; inset: 0;
  background: var(--wallpaper);
  background-size: cover;
  background-position: center;
}
.wallpaper::after {
  content: ""; position: absolute; inset: 0;
  background: radial-gradient(120% 90% at 50% 0%, rgba(255,255,255,.07), transparent 60%);
  pointer-events: none;
}
/* The animated layer (src/core/wallpaper.js) sits under the vignette and above
   the CSS gradient, and is hidden entirely when motion is off. */
.wallpaper-canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
/* Arriving at a desktop that looks different should feel like arriving: the new
   wallpaper fades in over the switch instead of cutting. src/core/theme.js adds
   this class only when the picture actually changed. */
.wallpaper.swap { animation: wallpaper-swap .42s cubic-bezier(.2, .8, .2, 1); }
@keyframes wallpaper-swap {
  from { opacity: .18; transform: scale(1.045); }
  to { opacity: 1; transform: none; }
}

/* ---------- desktop + icons ---------- */
.desktop { position: absolute; inset: 0 0 var(--taskbar-h) 0; overflow: hidden; outline: none; }

/* Icons are positioned by the shell on a loose grid (see src/core/shell.js: CELL/PAD). */
.desktop-icons { position: absolute; inset: 0; }

.dicon {
  position: absolute; width: 96px;
  border: 0; background: transparent; color: var(--text);
  display: flex; flex-direction: column; align-items: center; gap: 5px;
  padding: 8px 4px; border-radius: var(--radius-sm); cursor: grab;
  user-select: none; -webkit-user-select: none; touch-action: none;
  transition: background .12s ease, box-shadow .12s ease, transform .12s ease;
}
.dicon:hover { background: var(--hover); }
.dicon.selected { background: var(--accent-soft); outline: 2px solid var(--accent); outline-offset: -2px; }
.dicon.selected .glyph { border-color: var(--accent); box-shadow: 0 6px 16px rgba(0,0,0,.28), 0 0 0 2px color-mix(in srgb, var(--accent) 35%, transparent); }
/* A tick so a multi-selection reads as selected, not as "focused window". */
.dicon.selected::after {
  content: "✓"; position: absolute; top: 2px; right: 4px; width: 16px; height: 16px;
  display: grid; place-items: center; font-size: 11px; line-height: 1; border-radius: 50%;
  background: var(--accent); color: #fff; pointer-events: none;
}
.dicon:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; outline-style: dashed; }
.dicon.dragging {
  z-index: 4; cursor: grabbing; background: var(--accent-soft);
  transform: scale(1.06); box-shadow: 0 16px 34px rgba(0,0,0,.42);
}
/* The grid cell a dragged icon is about to land in. */
.icon-slot {
  position: absolute; pointer-events: none; z-index: 3; border-radius: var(--radius-sm);
  border: 2px dashed color-mix(in srgb, var(--accent) 70%, transparent);
  background: color-mix(in srgb, var(--accent) 12%, transparent);
}
/* Rubber-band selection. */
.marquee {
  position: absolute; pointer-events: none; z-index: 2; border-radius: 4px;
  border: 1px solid var(--accent); background: var(--accent-soft);
}
.dicon .glyph {
  width: 46px; height: 46px; display: grid; place-items: center;
  font-size: 26px; border-radius: 10px;
  background: linear-gradient(160deg, var(--surface-2), var(--surface-solid));
  border: 1px solid var(--border);
  box-shadow: 0 6px 16px rgba(0,0,0,.28);
}
.dicon .label {
  font-size: 12px; line-height: 1.25; text-align: center; max-width: 92px;
  color: var(--desk-ink); text-shadow: var(--desk-ink-shadow);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}

/* ---------- sticky notes on the desktop ---------- */
/* A pinned note lives on the worktop, under the windows (Shell.renderStickies).
   The layer itself must never eat a desktop click or a rubber-band drag. */
.stickies { position: absolute; inset: 0; pointer-events: none; }
.sticky {
  position: absolute; pointer-events: auto; display: flex; flex-direction: column;
  min-width: 120px; min-height: 90px;
  background: var(--sticky-bg, #f2d34e); color: var(--sticky-ink, #3a2f06);
  border: 1px solid rgb(0 0 0 / .18); border-radius: 4px;
  box-shadow: 0 10px 22px rgb(0 0 0 / .35), 0 1px 0 rgb(255 255 255 / .35) inset;
  transition: box-shadow .14s ease, transform .14s ease;
}
.sticky:hover { box-shadow: 0 14px 28px rgb(0 0 0 / .42); }
.sticky.dragging { transform: rotate(-1.2deg) scale(1.02); box-shadow: 0 22px 40px rgb(0 0 0 / .5); }
.sticky-head {
  display: flex; align-items: center; gap: 6px; padding: 5px 6px 4px;
  cursor: grab; user-select: none; -webkit-user-select: none; touch-action: none;
  border-bottom: 1px solid rgb(0 0 0 / .14);
}
.sticky-grip { font-size: 12px; opacity: .5; letter-spacing: -2px; }
.sticky-title { flex: 1; min-width: 0; font-size: 12px; font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sticky-btn {
  width: 20px; height: 20px; flex: 0 0 auto; display: grid; place-items: center;
  border: 1px solid transparent; border-radius: 4px; background: rgb(0 0 0 / .08);
  color: inherit; font-size: 11px; line-height: 1; cursor: pointer;
}
.sticky-btn:hover { background: rgb(0 0 0 / .2); }
.sticky-btn.danger:hover { background: var(--danger); color: #fff; }
.sticky-body {
  flex: 1; min-height: 0; padding: 8px 9px; border: 0; background: transparent; color: inherit;
  font-family: var(--font); font-size: 13px; line-height: 1.45; resize: none; outline: none;
  /* A note longer than its sticky is scrollable rather than silently cut off. */
  overflow: auto; overscroll-behavior: contain;
}
.sticky-body::-webkit-scrollbar { width: 8px; height: 8px; }
.sticky-body::-webkit-scrollbar-thumb { background: rgb(0 0 0 / .22); border-radius: 8px; }
.sticky-body::placeholder { color: rgb(0 0 0 / .38); }
.sticky-rz { position: absolute; right: 0; bottom: 0; width: 15px; height: 15px; cursor: nwse-resize; touch-action: none; }
.sticky-rz::after {
  content: ""; position: absolute; right: 3px; bottom: 3px; width: 8px; height: 8px;
  border-right: 2px solid rgb(0 0 0 / .3); border-bottom: 2px solid rgb(0 0 0 / .3); border-radius: 0 0 3px 0;
}

/* ---------- the desktop clock widget (src/core/desk-clock.js) ---------- */
/* Drawn straight onto the worktop, like an icon label: no panel of its own, so it
   uses --desk-ink / --desk-ink-shadow and stays readable on a pale wallpaper in the
   dark theme. The layer must never eat a desktop click or a rubber-band drag. */
.desk-clock-layer { position: absolute; inset: 0; pointer-events: none; }
.desk-clock {
  position: absolute; pointer-events: auto; width: var(--dc-w, 260px);
  display: flex; flex-direction: column; gap: 7px;
  padding: 10px 12px 12px; border-radius: 14px;
  color: var(--desk-ink); text-shadow: var(--desk-ink-shadow);
  user-select: none; -webkit-user-select: none; touch-action: none; cursor: grab;
  transition: background .14s ease, box-shadow .14s ease, transform .14s ease;
}
.desk-clock:hover {
  background: color-mix(in srgb, var(--desk-ink) 9%, transparent);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--desk-ink) 16%, transparent);
}
/* The worktop is focusable, so it has to look focused: a control you can only reach
   with Ctrl+Alt+C is a control you need to see when you get there. `data-kbd` is set
   by the shell putting the keyboard on it — a focus nobody typed their way to still
   has to look like a focus. */
.desk-clock:focus-visible, .desk-clock[data-kbd] {
  outline: 2px solid var(--accent); outline-offset: 3px;
  background: color-mix(in srgb, var(--desk-ink) 9%, transparent);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--desk-ink) 16%, transparent);
}
.desk-clock.dragging { cursor: grabbing; transform: scale(1.015); }
.dc-face { display: flex; align-items: center; gap: 14px; }
.dc-face-digital { display: block; }

/* The dial. One 100×100 drawing scaled by --dc-dial, so every size is the same clock. */
.dc-dial { width: var(--dc-dial); height: var(--dc-dial); display: block; flex: 0 0 auto; }
.dc-dial-face {
  fill: color-mix(in srgb, var(--desk-ink) 14%, transparent);
  stroke: color-mix(in srgb, var(--desk-ink) 30%, transparent); stroke-width: 1;
}
.dc-ticks line { stroke: var(--desk-ink); }
.dc-ticks .major { stroke-width: 1.7; opacity: .8; }
.dc-ticks .minor { stroke-width: .6; opacity: .32; }
.dc-numerals text {
  fill: var(--desk-ink); font-family: var(--font); font-size: 11px; font-weight: 700; opacity: .72;
}
.dc-hand { stroke: var(--desk-ink); stroke-linecap: round; }
.dc-hour { stroke-width: 3.4; }
.dc-minute { stroke-width: 2.1; }
/* The second hand, the centre pin and the ring of the day are the accent: the one
   place on the worktop that is clearly the machine's, not the wallpaper's. */
.dc-second { stroke: var(--accent); stroke-width: 1.1; }
.dc-cap { fill: var(--accent); }
.dc-day-arc { fill: none; stroke: var(--accent); stroke-width: 2.6; stroke-linecap: round; opacity: .85; }

/* The read-out. Numerals are tabular so a ticking clock does not shuffle its own width. */
.dc-digital { display: flex; align-items: baseline; gap: 5px; min-width: 0; }
.dc-time {
  font-weight: 700; font-size: var(--dc-fs, 44px); line-height: 1.02;
  font-variant-numeric: tabular-nums; letter-spacing: -.02em;
}
.dc-seconds { font-weight: 600; font-size: calc(var(--dc-fs, 44px) * .4); opacity: .6; font-variant-numeric: tabular-nums; }
.dc-suffix { font-weight: 700; font-size: calc(var(--dc-fs, 44px) * .34); opacity: .72; letter-spacing: .06em; }
.dc-size-small { --dc-fs: 40px; }
.dc-size-medium { --dc-fs: 52px; }
.dc-size-large { --dc-fs: 68px; }
/* A split face writes the time in the column beside the dial, which is narrower. */
.dc-face-split { --dc-fs: 34px; }
.dc-face-split.dc-size-medium { --dc-fs: 44px; }
.dc-face-split.dc-size-large { --dc-fs: 56px; }

.dc-date {
  font-size: 11.5px; font-weight: 600; letter-spacing: .1em; text-transform: uppercase;
  opacity: .7; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* How much of today has gone — the same fact the dial draws as a ring. */
.dc-day { height: 3px; border-radius: 3px; overflow: hidden; background: color-mix(in srgb, var(--desk-ink) 18%, transparent); }
.dc-day-fill { display: block; height: 100%; background: var(--accent); border-radius: 3px; }

.dc-upnext { display: flex; flex-direction: column; gap: 4px; }
.dc-row { display: grid; grid-template-columns: 15px minmax(0, 1fr) auto; gap: 7px; align-items: baseline; font-size: 12.5px; }
.dc-row-glyph { opacity: .8; }
.dc-row-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; opacity: .82; }
.dc-row-time { font-weight: 700; font-variant-numeric: tabular-nums; }
.dc-row-bar { grid-column: 1 / -1; display: block; height: 2px; border-radius: 2px; background: color-mix(in srgb, var(--desk-ink) 20%, transparent); }
.dc-row-bar b { display: block; height: 100%; border-radius: 2px; background: var(--accent); }
.dc-row-stopwatch .dc-row-time { color: var(--accent); }
.dc-empty { font-size: 11.5px; opacity: .48; font-style: italic; }

/* A row is something running, so hovering it offers the thing you can do to it. The
   button takes the glyph's exact cell: the row never changes shape, and the action
   appears out of the symbol it was. */
.dc-row { grid-template-columns: 20px minmax(0, 1fr) auto; }
.dc-row-glyph, .dc-row-act { grid-column: 1; grid-row: 1; }
/* Each cell is named, so a row that drops its label (a narrow dial) does not shove the
   countdown into the name's place. */
.dc-row-label { grid-column: 2; grid-row: 1; }
.dc-row-time { grid-column: 3; grid-row: 1; }
.dc-row-glyph { transition: opacity .12s ease; }
.dc-row-act {
  width: 20px; height: 18px; min-width: 20px; padding: 0; font-size: 10px; align-self: center;
  opacity: 0; transition: opacity .12s ease;
}
.dc-row:hover .dc-row-glyph, .dc-row:focus-within .dc-row-glyph { opacity: 0; }
.dc-row:hover .dc-row-act, .dc-row:focus-within .dc-row-act, .dc-row-act:focus { opacity: 1; }

/* An alarm that rang and nobody answered. It is the only part of the worktop that
   asks for something, so it is drawn above the list, in the accent, and the whole
   clock breathes while it is waiting. */
.dc-ring { display: flex; flex-direction: column; gap: 4px; }
.dc-ring[hidden] { display: none; }
.dc-ring-row {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
  padding: 4px 6px; border-radius: 9px; font-size: 12.5px;
  background: color-mix(in srgb, var(--accent) 20%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 55%, transparent);
}
.dc-ring-when { font-weight: 700; font-variant-numeric: tabular-nums; }
.dc-ring-row .dc-row-label { flex: 1 1 90px; min-width: 0; opacity: 1; }
.dc-ring-ago { font-size: 11px; opacity: .72; margin-left: auto; }
/* The two answers belong together: they are one decision, not two loose buttons. */
.dc-ring-acts { display: inline-flex; gap: 4px; }
.desk-clock.ringing {
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent) 55%, transparent);
  animation: desk-clock-ring 2.6s ease-in-out infinite;
}
@keyframes desk-clock-ring {
  0%, 100% { background: color-mix(in srgb, var(--accent) 4%, transparent); }
  50% { background: color-mix(in srgb, var(--accent) 14%, transparent); }
}
@media (prefers-reduced-motion: reduce) { .desk-clock.ringing { animation: none; } }
.dc-world { display: flex; flex-direction: column; gap: 2px; border-top: 1px solid color-mix(in srgb, var(--desk-ink) 18%, transparent); padding-top: 5px; }
.dc-city { display: grid; grid-template-columns: minmax(0, 1fr) auto auto; gap: 8px; font-size: 12px; }
.dc-city-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; opacity: .82; }
.dc-city-day { font-size: 10.5px; opacity: .55; }
.dc-city-time { font-weight: 700; font-variant-numeric: tabular-nums; }

/* The tools only appear when you are pointing at the clock or standing on it with the keyboard. */
.dc-tools {
  position: absolute; top: 4px; right: 6px; display: flex; gap: 3px;
  opacity: 0; transition: opacity .14s ease;
}
.desk-clock:hover .dc-tools, .desk-clock:focus-within .dc-tools, .desk-clock:focus-visible .dc-tools, .desk-clock[data-kbd] .dc-tools { opacity: 1; }
.dc-tool {
  width: 22px; height: 22px; display: grid; place-items: center; font-size: 12px; line-height: 1;
  border: 1px solid color-mix(in srgb, var(--desk-ink) 26%, transparent); border-radius: 6px;
  background: color-mix(in srgb, var(--desk-ink) 12%, transparent); color: var(--desk-ink); cursor: pointer;
}
.dc-tool:hover { background: var(--accent); border-color: var(--accent); color: #fff; text-shadow: none; }

/* The controls. They are always on the clock and quiet until you point at it or stand
   on it: a control you cannot see is a control nobody knows the clock has. */
.dc-actions {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
  opacity: .46; transition: opacity .14s ease;
}
.desk-clock:hover .dc-actions, .desk-clock:focus-within .dc-actions, .desk-clock:focus-visible .dc-actions, .desk-clock[data-kbd] .dc-actions { opacity: 1; }
.dc-ctl {
  min-width: 30px; height: 22px; padding: 0 7px; display: inline-grid; place-items: center;
  font: inherit; font-size: 11.5px; font-weight: 700; line-height: 1; letter-spacing: .02em;
  border: 1px solid color-mix(in srgb, var(--desk-ink) 26%, transparent); border-radius: 7px;
  background: color-mix(in srgb, var(--desk-ink) 10%, transparent); color: var(--desk-ink);
  text-shadow: none; cursor: pointer;
}
.dc-ctl:hover { background: var(--accent); border-color: var(--accent); color: #fff; }
.dc-sw { min-width: 26px; padding: 0 5px; }
.dc-sw.running { background: color-mix(in srgb, var(--accent) 34%, transparent); border-color: var(--accent); }
.dc-act { min-width: 18px; }

/* One paragraph a screen reader reads and nobody sees. */
.sr-only {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* A face preview in Settings: the real widget, scaled, with no gestures. It uses the
   window's own ink rather than the worktop's, because it is standing in a window. */
.dc-preview {
  position: relative; overflow: hidden;
  --desk-ink: var(--text); --desk-ink-shadow: none;
}
.dc-preview .desk-clock { transform: scale(var(--dc-scale, 1)); transform-origin: top left; cursor: default; }

/* ---------- windows ---------- */
.windows-layer { position: absolute; inset: 0 0 var(--taskbar-h) 0; pointer-events: none; }

.window {
  position: absolute; pointer-events: auto;
  display: flex; flex-direction: column;
  min-width: 240px; min-height: 140px;
  background: var(--surface); backdrop-filter: blur(18px) saturate(140%);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-window);
  overflow: hidden;
  animation: win-in .16s cubic-bezier(.2,.9,.3,1);
  contain: layout paint;
}
@keyframes win-in { from { opacity: 0; transform: scale(.97) translateY(6px); } to { opacity: 1; transform: none; } }
.window.focused { border-color: color-mix(in srgb, var(--accent) 55%, var(--border)); }
.window.minimized { display: none; }
.window.maximized { border-radius: 0; border-color: transparent; }
.window.closing { animation: win-out .12s ease forwards; }
@keyframes win-out { to { opacity: 0; transform: scale(.96); } }
.window.minimizing { animation: win-min .17s cubic-bezier(.4,0,.6,1) forwards; transform-origin: 50% 100%; }
@keyframes win-min { to { opacity: 0; transform: scale(.55) translateY(46px); } }
.window.restoring { animation: win-restore .2s cubic-bezier(.2,.9,.3,1); transform-origin: 50% 100%; }
@keyframes win-restore { from { opacity: 0; transform: scale(.55) translateY(46px); } to { opacity: 1; transform: none; } }

@media (prefers-reduced-motion: reduce) {
  .window, .window.closing, .window.minimizing, .window.restoring, .window.ws-enter,
  .launcher-panel, .context-menu, .toast, .snap-preview, .tray-badge, .ws-btn.flash,
  .ws-btn.drop, .workspaces.armed::before, .notifications, .titem.attention,
  .wallpaper.swap, .desk-look,
  .notify-btn.has-unread .nb-glyph {
    animation: none !important; transition: none !important;
  }
}

.titlebar {
  height: var(--titlebar-h); flex: 0 0 auto;
  display: flex; align-items: center; gap: 8px;
  padding: 0 6px 0 10px;
  background: linear-gradient(180deg, var(--surface-2), transparent);
  border-bottom: 1px solid var(--border);
  cursor: move; touch-action: none; user-select: none;
}
.window:not(.focused) .titlebar { opacity: .72; }
.titlebar .wicon { font-size: 15px; }
.titlebar .wtitle {
  flex: 1; font-size: 13px; font-weight: 600; letter-spacing: .1px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.wcontrols { display: flex; gap: 2px; }
.wbtn {
  width: 26px; height: 24px; border: 0; border-radius: var(--radius-sm);
  background: transparent; color: var(--text-dim); cursor: pointer;
  display: grid; place-items: center; font-size: 13px;
}
.wbtn:hover { background: var(--hover); color: var(--text); }
.wbtn.close:hover { background: var(--danger); color: #fff; }

.wbody { flex: 1; min-height: 0; position: relative; overflow: auto; }
.window.maximized .wbody { border-radius: 0; }

.rz { position: absolute; z-index: 5; }
.rz-n { top: -3px; left: 8px; right: 8px; height: 7px; cursor: ns-resize; }
.rz-s { bottom: -3px; left: 8px; right: 8px; height: 7px; cursor: ns-resize; }
.rz-w { left: -3px; top: 8px; bottom: 8px; width: 7px; cursor: ew-resize; }
.rz-e { right: -3px; top: 8px; bottom: 8px; width: 7px; cursor: ew-resize; }
.rz-nw { left: -4px; top: -4px; width: 14px; height: 14px; cursor: nwse-resize; }
.rz-ne { right: -4px; top: -4px; width: 14px; height: 14px; cursor: nesw-resize; }
.rz-sw { left: -4px; bottom: -4px; width: 14px; height: 14px; cursor: nesw-resize; }
.rz-se { right: -4px; bottom: -4px; width: 14px; height: 14px; cursor: nwse-resize; }
.window.maximized .rz { display: none; }

.snap-preview {
  position: absolute; z-index: 99999; pointer-events: none;
  border: 2px solid var(--accent); border-radius: var(--radius);
  background: var(--accent-soft);
  transition: all .09s linear;
}

/* ---------- taskbar ---------- */
.taskbar {
  position: absolute; left: 0; right: 0; bottom: 0; height: var(--taskbar-h);
  display: flex; align-items: center; gap: 8px; padding: 0 8px;
  background: var(--surface); backdrop-filter: blur(20px) saturate(150%);
  border-top: 1px solid var(--border);
  z-index: 100000;
}
.start-btn {
  display: flex; align-items: center; gap: 8px;
  height: 34px; padding: 0 12px; border-radius: var(--radius-sm);
  border: 1px solid transparent; background: transparent; color: var(--text);
  cursor: pointer; font-weight: 600; font-size: 13px;
}
.start-btn:hover, .start-btn.open { background: var(--accent-soft); border-color: var(--accent); }
.start-logo {
  width: 18px; height: 18px; border-radius: 5px;
  background: conic-gradient(from 20deg, var(--accent), var(--accent-2), var(--accent));
  box-shadow: 0 0 12px var(--accent-soft);
}
.taskbar-items { flex: 1; display: flex; gap: 4px; overflow: hidden; }
.titem {
  display: flex; align-items: center; gap: 7px; max-width: 220px;
  height: 34px; padding: 0 10px; border-radius: var(--radius-sm);
  border: 1px solid transparent; background: var(--hover); color: var(--text);
  cursor: pointer; font-size: 12.5px;
}
.titem:hover { background: var(--active); }
.titem.focused { background: var(--accent-soft); border-color: var(--accent); }
.titem.minimized { opacity: .6; }
.titem .glyph { font-size: 15px; }
.titem .t { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.tray { display: flex; align-items: center; gap: 10px; padding-right: 6px; }
.tray-badges { display: flex; align-items: center; gap: 6px; }
.tray-badges:empty { display: none; }
.tray-badge {
  width: 28px; height: 28px; border-radius: 7px; display: grid; place-items: center;
  font-size: 14px; border: 1px solid var(--accent); background: var(--accent-soft); color: var(--accent);
  animation: badge-in 220ms cubic-bezier(.2, .9, .3, 1);
}
@keyframes badge-in { from { transform: scale(.6); opacity: 0; } to { transform: none; opacity: 1; } }
.tray-status { font-size: 12px; color: var(--text-dim); }
.tray-btn {
  width: 30px; height: 30px; border-radius: 7px; cursor: pointer;
  border: 1px solid var(--border); background: var(--surface-2); color: var(--text-dim);
  display: grid; place-items: center; font-size: 13px;
}
.tray-btn:hover { background: var(--accent-soft); color: var(--accent); border-color: var(--accent); }
.clock {
  font-size: 12.5px; text-align: right; line-height: 1.15; cursor: pointer;
  background: transparent; border: 0; color: var(--text); border-radius: 7px; padding: 2px 6px;
}
.clock:hover { background: var(--hover); }
.clock .time { font-variant-numeric: tabular-nums; font-weight: 600; }
.clock .date { color: var(--text-dim); font-size: 11px; }
/* Live countdowns in the tray: whatever the machine is timing, wherever you are. */
.tray-timers { display: flex; align-items: center; gap: 6px; max-width: 44vw; overflow: hidden; }
/* Countdowns are the first thing to give way: the clock, the launcher and the
   workspace chips have to stay reachable whatever someone has running. */
.tray-timers:empty { display: none; }
.tray-timer {
  display: flex; align-items: center; gap: 5px; height: 28px; padding: 0 9px; border-radius: 7px;
  border: 1px solid var(--accent); background: var(--accent-soft); color: var(--accent);
  font-family: var(--mono); font-size: 12px; font-variant-numeric: tabular-nums; cursor: pointer;
  animation: badge-in 220ms cubic-bezier(.2, .9, .3, 1);
}
.tray-timer:hover { background: var(--accent); color: #fff; }
.tray-timer-stopwatch { border-style: dashed; }
/* What a countdown is *for* — the tray is the only place you see it without opening
   the app, so an anonymous number would be a worse feature than a wide one. */
.tray-timer .tt-label { max-width: 14ch; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; opacity: .72; }

/* ---------- workspaces ---------- */
/* A window on another workspace is out of the layout entirely (src/core/wm.js
   toggles this class when the workspace model changes). */
.window.ws-hidden { display: none; }
/* A desktop switch slides what arrived in from the side it came from. */
.window.ws-enter { animation: ws-in .28s cubic-bezier(.2, .9, .3, 1); }
@keyframes ws-in {
  from { opacity: 0; transform: translateX(var(--ws-from, 40px)) scale(.985); }
  to { opacity: 1; transform: none; }
}

.workspaces { display: flex; align-items: center; gap: 4px; padding: 0 2px; position: relative; }
.ws-overview, .ws-add {
  width: 30px; height: 30px; border-radius: var(--radius-sm); flex: 0 0 auto;
  border: 1px solid var(--border); background: var(--surface-2); color: var(--text-dim);
  display: grid; place-items: center; font-size: 14px; cursor: pointer;
}
.ws-overview:hover, .ws-add:hover { background: var(--accent-soft); color: var(--accent); border-color: var(--accent); }
.ws-add:disabled { opacity: .35; cursor: not-allowed; }
.ws-btn {
  position: relative;
  display: flex; align-items: center; gap: 6px; flex: 0 0 auto;
  min-width: 44px; max-width: 158px; height: 30px; padding: 0 8px;
  border-radius: var(--radius-sm); border: 1px solid transparent;
  background: var(--hover); color: var(--text-dim); cursor: pointer; font-size: 12px;
}
.ws-btn:hover { background: var(--active); color: var(--text); }
.ws-btn.current { background: var(--accent-soft); border-color: var(--accent); color: var(--text); }
.ws-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.ws-btn.flash { animation: ws-flash .4s cubic-bezier(.2,.9,.3,1); }
@keyframes ws-flash { from { transform: translateY(4px) scale(.96); } to { transform: none; } }
.ws-n { font-variant-numeric: tabular-nums; font-weight: 700; opacity: .75; }
.ws-btn.current .ws-n { color: var(--accent); opacity: 1; }
.ws-name { max-width: 76px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ws-dots { display: flex; align-items: center; gap: 3px; }

/* A chip paints the desktop it stands for: the wallpaper that desktop has, edged
   with the accent it has. Inheriting desktops all show the default look, so a
   desktop with its own is the only one that stands out — and it gets a dot. */
.ws-swatch {
  width: 14px; height: 14px; border-radius: 4px; flex: 0 0 auto;
  border: 1px solid var(--border-strong); background: var(--wallpaper-default);
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .22);
}
.ws-btn.has-look .ws-swatch { border-width: 2px; border-color: var(--ws-accent, var(--accent)); }
.ws-btn.has-look::after {
  content: ''; position: absolute; top: 2px; right: 2px; width: 6px; height: 6px;
  border-radius: 50%; background: var(--ws-accent, var(--accent)); box-shadow: 0 0 0 1px var(--surface-solid);
}
.workspaces.armed .ws-swatch { width: 18px; height: 18px; }
.ws-dot { font-size: 12px; opacity: .7; }
.ws-btn.current .ws-dot { opacity: 1; }
.ws-more { font-size: 11px; color: var(--text-faint); }

/* Dragging a window onto a desktop. While a drag is alive the strip *arms*: the
   chips grow, names show, and a hint says what the gesture is for. */
.workspaces.armed .ws-btn {
  max-width: 210px; height: 34px; border-color: var(--border-strong);
  background: var(--surface-2); color: var(--text);
}
.workspaces.armed .ws-add { border-color: var(--border-strong); color: var(--text); }
.workspaces.armed::before {
  content: "drop it on a desktop";
  position: absolute; right: calc(100% + 10px); bottom: calc(100% + 12px);
  padding: 5px 9px; border-radius: var(--radius-sm);
  border: 1px solid var(--accent); background: var(--surface); color: var(--text-dim);
  font-size: 11.5px; white-space: nowrap; box-shadow: var(--shadow-pop);
  animation: hint-in .18s cubic-bezier(.2, .9, .3, 1);
}
@keyframes hint-in { from { opacity: 0; transform: translateY(5px); } to { opacity: 1; transform: none; } }
.ws-btn.drop-target, .tv-card.drop-target {
  border-color: var(--accent) !important; background: var(--accent-soft) !important; color: var(--text) !important;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 28%, transparent);
}
.ws-btn.drop-target { transform: translateY(-3px) scale(1.04); }
.tv-card.drop-target { transform: translateY(-4px); }
.ws-btn.drop { animation: ws-drop .55s cubic-bezier(.2, .9, .3, 1); }
@keyframes ws-drop {
  0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 60%, transparent); }
  55% { box-shadow: 0 0 0 9px color-mix(in srgb, var(--accent) 12%, transparent); }
  100% { box-shadow: 0 0 0 0 transparent; }
}

/* The chip that follows the pointer while you drag a window. It rides above and
   to the right of the cursor so the desktop you are aiming at stays visible. */
.drag-chip {
  position: fixed; z-index: 100006; pointer-events: none;
  transform: translate(-25%, -175%) rotate(-2deg);
  display: flex; align-items: center; gap: 7px; max-width: 240px;
  padding: 6px 10px; border-radius: var(--radius-sm);
  border: 1px solid var(--accent); background: var(--surface-2); color: var(--text);
  font-size: 12.5px; box-shadow: var(--shadow-pop);
}
.drag-chip .glyph { font-size: 15px; }
.drag-chip .t { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.titem.dragging, .tv-win.dragging { opacity: .35; }
.titem, .tv-win { touch-action: none; }

/* ---------- task view (every workspace at a glance) ---------- */
.task-view {
  position: absolute; inset: 0; z-index: 100002;
  background: rgb(6 8 14 / .66); backdrop-filter: blur(7px);
  display: flex; flex-direction: column; gap: 14px; padding: 26px 22px 22px;
  animation: pop-in .18s cubic-bezier(.2,.9,.3,1);
}
[data-theme='light'] .task-view { background: rgb(20 24 34 / .45); }
.tv-head { display: flex; align-items: baseline; gap: 14px; flex-wrap: wrap; }
.tv-title { font-size: 16px; font-weight: 700; color: var(--text); }
.tv-hint { font-size: 12px; color: var(--text-dim); }
.tv-grid { display: flex; gap: 14px; align-items: flex-start; overflow: auto; flex: 1; padding-bottom: 4px; }
.tv-card {
  flex: 0 0 300px; display: flex; flex-direction: column; gap: 8px;
  border: 1px solid var(--border); border-radius: var(--radius); padding: 10px;
  background: var(--surface); backdrop-filter: blur(18px) saturate(140%);
  box-shadow: var(--shadow-pop); cursor: pointer;
}
.tv-card.current { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-soft), var(--shadow-pop); }
.tv-card:hover { background: var(--surface-2); }
.tv-card:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.tv-card-head { display: flex; align-items: center; gap: 8px; padding: 2px 2px 7px; border-bottom: 1px solid var(--border); }
.tv-n { width: 20px; height: 20px; flex: 0 0 auto; border-radius: 5px; display: grid; place-items: center; background: var(--surface-3); font-size: 11px; font-weight: 700; font-variant-numeric: tabular-nums; }
.tv-card.current .tv-n { background: var(--accent); color: #fff; }
.tv-name { flex: 1 1 40px; font-size: 13px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: var(--text); min-width: 0; }
/* A desktop with its own look says what it is, in the card, not just by colour. */
.tv-look {
  flex: 0 0 auto; max-width: 152px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: 10px; padding: 2px 6px; border-radius: 999px;
  border: 1px solid var(--accent); color: var(--accent); background: var(--accent-soft);
}
.tv-count { font-size: 11px; color: var(--text-dim); flex: 0 0 auto; }
/* A to-scale miniature of the desktop, so the overview looks like the desktop. */
.tv-preview {
  position: relative; flex: 0 0 auto; overflow: hidden;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  /* The default, unless the card overrides it inline: an overview of four desktops
     must not be four pictures of whichever one you are standing on. */
  background-color: var(--surface-2); background-image: var(--wallpaper-default);
}
.tv-box {
  position: absolute; border: 1px solid var(--border-strong); border-radius: 3px;
  background: rgb(255 255 255 / .12); box-shadow: 0 1px 3px rgb(0 0 0 / .35);
}
.tv-box.focused { border-color: var(--accent); background: var(--accent-soft); }
.tv-box.minimized { opacity: .35; }
.tv-wins { display: flex; flex-direction: column; gap: 6px; }
.tv-win {
  display: flex; align-items: center; gap: 8px; width: 100%; text-align: left;
  padding: 6px 8px; border-radius: var(--radius-sm); border: 1px solid transparent;
  background: var(--hover); color: var(--text); cursor: pointer; font-size: 12.5px;
}
.tv-win:hover { background: var(--active); }
.tv-win.focused { border-color: var(--accent); background: var(--accent-soft); }
.tv-win.minimized { opacity: .62; }
.tv-win .glyph { font-size: 14px; flex: 0 0 auto; }
.tv-win .t { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tv-empty {
  padding: 14px 12px; color: var(--text-faint); font-size: 12px; text-align: center;
  border: 1px dashed var(--border); border-radius: var(--radius-sm);
}
.tv-new { align-items: center; justify-content: center; gap: 8px; min-height: 120px; background: transparent; border-style: dashed; color: var(--text-dim); }
.tv-new:hover { color: var(--accent); border-color: var(--accent); background: transparent; }
.tv-plus { font-size: 22px; line-height: 1; }

/* ---------- the per-desktop look picker ----------
   Edits one desktop's wallpaper, motion and accent. No scrim: the desktop behind it
   is the thing you are changing, so it has to stay visible while you click. */
.desk-look {
  position: absolute; z-index: 100002; width: 424px; max-width: calc(100vw - 24px);
  max-height: calc(100vh - var(--taskbar-h) - 24px); overflow: auto;
  padding: 12px 14px 14px;
  border: 1px solid var(--border-strong); border-radius: var(--radius);
  background: var(--surface); backdrop-filter: blur(18px) saturate(1.2);
  box-shadow: var(--shadow-pop); color: var(--text);
  animation: pop-in .18s cubic-bezier(.2, .9, .3, 1);
}
.desk-look:focus { outline: none; }
.desk-look:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.dl-head { display: flex; align-items: center; gap: 8px; }
.dl-title { font-size: 13px; font-weight: 700; flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dl-close {
  width: 24px; height: 24px; flex: 0 0 auto; border-radius: var(--radius-sm);
  border: 1px solid var(--border); background: var(--hover); color: var(--text-dim); cursor: pointer;
}
.dl-close:hover { background: var(--active); color: var(--text); }
.dl-hint { margin: 4px 0 10px; font-size: 11px; line-height: 1.45; color: var(--text-faint); }
.dl-section { display: flex; align-items: center; gap: 8px; margin: 10px 0 6px; }
.dl-label { font-size: 10px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--text-faint); flex: 1; }
.dl-now {
  font-size: 10px; padding: 2px 7px; border-radius: 999px;
  border: 1px solid var(--border); color: var(--text-faint); background: var(--hover);
}
.dl-now.chosen { border-color: var(--accent); color: var(--accent); background: var(--accent-soft); }
.dl-inherit {
  font-size: 11px; padding: 3px 8px; border-radius: 999px; cursor: pointer;
  border: 1px solid var(--border-strong); background: var(--surface-2); color: var(--text-dim);
}
.dl-inherit:hover:not([disabled]) { background: var(--active); color: var(--text); }
.dl-inherit[disabled] { opacity: .45; cursor: default; }
.dl-row { display: flex; flex-wrap: wrap; gap: 6px; }
.dl-tile {
  position: relative; width: 44px; height: 40px; padding: 0; cursor: pointer;
  border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
  background-size: cover; background-position: center; overflow: hidden;
}
.dl-tile:hover { border-color: var(--text-faint); }
.dl-tile:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.dl-tile.active { box-shadow: 0 0 0 2px var(--surface-solid), 0 0 0 3px var(--text-faint); }
.dl-tile.active.chosen { box-shadow: 0 0 0 2px var(--surface-solid), 0 0 0 4px var(--accent); }
.dl-tile-label {
  position: absolute; left: 0; right: 0; bottom: 0; padding: 2px 4px;
  font-size: 9px; text-align: center; color: #fff; background: rgb(0 0 0 / .55);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.dl-tile.dl-tile-accent { width: 30px; height: 30px; border-radius: 50%; align-self: center; }
.dl-tile.dl-tile-pattern {
  width: 60px; height: 52px; background: none; padding: 4px 2px 5px;
  display: flex; flex-direction: column; align-items: center; justify-content: space-between;
}
.dl-tile.dl-tile-pattern canvas, .dl-tile.dl-tile-pattern .dl-static {
  display: block; width: 54px; height: 28px; border-radius: 3px; background-size: cover; flex: 0 0 auto;
}
.dl-tile.dl-tile-pattern .dl-tile-label {
  position: static; transform: none; padding: 0; font-size: 9px; line-height: 1.3; color: var(--text-dim); text-shadow: none; background: none;
}
.dl-foot { display: flex; align-items: center; gap: 8px; margin-top: 14px; padding-top: 10px; border-top: 1px solid var(--border); }
.dl-note { flex: 1; min-width: 0; font-size: 11px; color: var(--text-faint); }

/* ---------- launcher (Start button / Ctrl+Space) ---------- */
/* The host is a full-screen, click-through layer: a click anywhere else still reaches
   the desktop, and the launcher closes on that click. */
.launcher { position: absolute; inset: 0; z-index: 100001; pointer-events: none; }
/* A scrim says "the desktop is waiting" — click-through, so an outside click still closes it. */
.launcher:not(.hidden)::before {
  content: ''; position: absolute; inset: 0;
  background: rgb(6 8 14 / .34);
}
[data-theme='light'] .launcher:not(.hidden)::before { background: rgb(20 24 34 / .18); }
.launcher-panel {
  position: absolute; left: 8px; bottom: calc(var(--taskbar-h) + 8px);
  width: 540px; max-width: calc(100vw - 16px); max-height: min(640px, calc(100vh - var(--taskbar-h) - 24px));
  background: var(--surface); backdrop-filter: blur(24px) saturate(150%);
  border: 1px solid var(--border); border-radius: 14px; box-shadow: var(--shadow-pop);
  display: flex; flex-direction: column; overflow: hidden; pointer-events: auto;
  animation: pop-in .16s cubic-bezier(.2,.9,.3,1);
}
@keyframes pop-in { from { opacity: 0; transform: translateY(8px) scale(.98); } to { opacity: 1; transform: none; } }
.launcher-query { display: flex; align-items: center; gap: 10px; padding: 12px; border-bottom: 1px solid var(--border); }
.launcher-glyph { font-size: 16px; color: var(--text-faint); flex: 0 0 auto; }
.launcher-input {
  flex: 1; min-width: 0; height: 38px; padding: 0 10px; border-radius: 9px;
  background: var(--surface-2); border: 1px solid var(--border); outline: none; font-size: 15px;
}
.launcher-input:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.launcher-input::placeholder { color: var(--text-faint); }
.launcher-clear {
  width: 28px; height: 28px; flex: 0 0 auto; border-radius: 7px; cursor: pointer;
  border: 1px solid transparent; background: transparent; color: var(--text-dim); font-size: 12px;
}
.launcher-clear:hover { background: var(--hover); color: var(--text); }
.launcher-results { flex: 1; overflow: auto; padding: 6px 8px 10px; }
/* When the list is cut off, fade the last row: a clipped row should read as "more below". */
.launcher-results.more-below { mask-image: linear-gradient(to bottom, #000 calc(100% - 22px), transparent); }
.launcher-group { margin: 4px 0 2px; }
.launcher-group-head {
  display: flex; align-items: center; gap: 8px; padding: 8px 6px 4px;
  font-size: 11px; letter-spacing: .08em; text-transform: uppercase; color: var(--text-faint);
}
.launcher-group-count { margin-left: auto; font-variant-numeric: tabular-nums; }
.lrow {
  width: 100%; display: flex; align-items: center; gap: 10px; text-align: left;
  padding: 7px 9px; margin: 2px 0; border: 1px solid transparent; border-radius: 9px;
  background: transparent; color: var(--text); cursor: pointer; font-size: 13px;
}
.lrow:hover { background: var(--hover); }
.lrow.selected { background: var(--accent-soft); border-color: var(--accent); }
.lrow .glyph { width: 26px; height: 26px; flex: 0 0 auto; display: grid; place-items: center; font-size: 17px; }
.lrow-main { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.lrow-title { font-size: 13.5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.lrow-title mark { background: color-mix(in srgb, var(--accent) 38%, transparent); color: inherit; border-radius: 3px; padding: 0 1px; }
.lrow-detail { font-size: 11.5px; color: var(--text-dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.lrow-kind {
  margin-left: auto; flex: 0 0 auto; padding: 2px 4px; border: 0; border-radius: 0;
  font-size: 10px; letter-spacing: .08em; text-transform: uppercase; color: var(--text-faint);
  font-variant-numeric: tabular-nums;
}
.lrow.selected .lrow-kind, .lrow:hover .lrow-kind { color: var(--text-dim); }
/* A chord printed on the row it belongs to: the same string Settings and `keys`
   print, so the launcher is a keyboard reference as well as a mouse one. */
.lrow-kbd {
  margin-left: auto; flex: 0 0 auto; padding: 2px 6px; border: 1px solid var(--border); border-radius: 5px;
  font-family: var(--mono); font-size: 10.5px; color: var(--text-dim); background: var(--surface-2);
}
/* ---------- the launcher's modes: `>` a command, `?` a web search ---------- */
/* A mode is a promise about what Enter will do, so it is printed, not implied. */
.launcher-mode {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 9px; border-radius: 8px; font-size: 11px; letter-spacing: .06em; text-transform: uppercase;
  background: var(--accent-soft); color: var(--accent); border: 1px solid var(--accent);
}
.launcher-mode-prefix { font-family: var(--mono); font-size: 13px; text-transform: none; }
.launcher-input.launcher-mode-on { font-family: var(--mono); font-size: 14px; }
/* A command row prints the usage under the name: what you are about to run. */
.lrow-usage {
  font-family: var(--mono); font-size: 11px; color: var(--text-dim);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* ---------- a command's output, shown in the launcher itself ---------- */
.shell-result { display: flex; flex-direction: column; gap: 8px; padding: 6px 4px 2px; }
.shell-head {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 6px 8px; border: 1px solid var(--border); border-radius: 9px; background: var(--surface-2);
}
.shell-cwd { font-family: var(--mono); font-size: 11px; color: var(--accent); opacity: .8; }
.shell-line-text { flex: 1; min-width: 0; font-family: var(--mono); font-size: 13px; word-break: break-all; }
.shell-status {
  margin-left: auto; flex: 0 0 auto; padding: 2px 8px; border-radius: 999px;
  font-family: var(--mono); font-size: 11px; border: 1px solid var(--border); color: var(--text-dim);
}
.shell-status.ok { color: var(--ok); border-color: color-mix(in srgb, var(--ok) 45%, transparent); }
.shell-status.err { color: var(--danger); border-color: color-mix(in srgb, var(--danger) 45%, transparent); }
.shell-out {
  padding: 10px 12px; border-radius: 9px; background: var(--surface-2); border: 1px solid var(--border);
  font-family: var(--mono); font-size: 12.5px; line-height: 1.55; white-space: pre-wrap; word-break: break-word;
  max-height: 46vh; overflow: auto;
}
.shell-line { white-space: pre-wrap; word-break: break-word; }
.shell-line.err { color: var(--danger); }
.shell-line.ok { color: var(--ok); }
.shell-line.acc { color: var(--accent); }
.shell-line.dim { color: var(--text-faint); }
.shell-actions { display: flex; flex-wrap: wrap; gap: 6px; }
.shell-btn {
  padding: 6px 10px; border: 1px solid var(--border); border-radius: 8px; background: transparent;
  color: var(--text-dim); font-size: 12px; cursor: pointer;
}
.shell-btn:hover { background: var(--hover); color: var(--text); border-color: var(--accent); }

.launcher-foot {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 8px 12px; border-top: 1px solid var(--border); font-size: 11px; color: var(--text-dim);
}
.launcher-status { color: var(--text-faint); }
.launcher-keys { margin-left: auto; white-space: nowrap; }
.start-section { font-size: 11px; letter-spacing: .08em; text-transform: uppercase; color: var(--text-faint); margin: 8px 2px 6px; }
.app-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); gap: 6px; }
.app-tile {
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  padding: 10px 6px; border: 1px solid transparent; border-radius: 10px;
  background: transparent; cursor: pointer; color: var(--text);
}
.app-tile:hover { background: var(--hover); border-color: var(--border); }
/* Keyboard selection in the launcher's app grid. */
.app-tile.selected { background: var(--accent-soft); border-color: var(--accent); outline: none; }
.app-tile .glyph { font-size: 24px; }
.app-tile .name { font-size: 12px; }

/* ---------- context menu ---------- */
.context-menu {
  position: absolute; z-index: 100002; min-width: 210px;
  background: var(--surface); backdrop-filter: blur(20px) saturate(150%);
  border: 1px solid var(--border); border-radius: 10px; box-shadow: var(--shadow-pop);
  padding: 6px; animation: pop-in .1s ease;
}
.cmenu-item {
  width: 100%; text-align: left; display: flex; gap: 10px; align-items: center;
  padding: 8px 10px; border: 0; background: transparent; color: var(--text);
  border-radius: 7px; cursor: pointer; font-size: 13px;
}
.cmenu-item:hover { background: var(--accent-soft); }
.cmenu-item .glyph { width: 18px; text-align: center; }
.cmenu-sep { height: 1px; background: var(--border); margin: 5px 4px; }
.cmenu-hint { font-size: 11px; color: var(--text-faint); margin-left: auto; flex: 0 0 auto; white-space: nowrap; }

/* ---------- notifications: pop-ups ---------- */
/* The stack is the transient half of the notification system; the centre (below) is
   the durable half. A pop-up is deliberately *not* a button — the row you can act on
   is the one in the centre — except when the message names a path, in which case the
   pop-up itself carries the action. */
.toasts { position: absolute; right: 12px; bottom: calc(var(--taskbar-h) + 12px); display: flex; flex-direction: column; gap: 8px; z-index: 100003; }
.toast {
  display: flex; align-items: flex-start; gap: 8px;
  min-width: 220px; max-width: 340px; padding: 10px 12px;
  background: var(--surface); border: 1px solid var(--border); border-left: 3px solid var(--accent);
  border-radius: 10px; box-shadow: var(--shadow-pop); font-size: 13px;
  animation: pop-in .16s ease;
}
.toast.err { border-left-color: var(--danger); }
.toast.ok { border-left-color: var(--ok); }
.toast.warn { border-left-color: var(--warn); }
.toast .t { font-weight: 600; margin-bottom: 2px; overflow-wrap: anywhere; }
.toast .d { color: var(--text-dim); font-size: 12px; overflow-wrap: anywhere; }
.toast .t-body { flex: 1 1 auto; min-width: 0; }
.toast .t-count { color: var(--accent); font-weight: 700; font-size: 11px; }
.toast .t-glyph { flex: 0 0 auto; width: 16px; text-align: center; color: var(--text-dim); font-size: 13px; padding-top: 1px; }
.toast.ok .t-glyph { color: var(--ok); }
.toast.warn .t-glyph { color: var(--warn); }
.toast.err .t-glyph { color: var(--danger); }
.toast .t-action, .toast .t-x {
  flex: 0 0 auto; border: 1px solid var(--border); background: var(--surface-2); color: var(--text-dim);
  border-radius: var(--radius-sm); font: inherit; font-size: 11px; padding: 3px 7px; cursor: pointer;
}
.toast .t-action { color: var(--accent); border-color: var(--accent); }
.toast .t-action:hover { background: var(--accent-soft); }
.toast .t-x { padding: 3px 5px; }
.toast .t-x:hover { color: var(--text); background: var(--hover); }
.toast.fading { opacity: 0; transform: translateX(12px); transition: opacity .3s, transform .3s; }

/* ---------- notifications: the tray bell ---------- */
.notify-tray { display: flex; align-items: center; }
.notify-btn { position: relative; display: flex; align-items: center; gap: 5px; }
.notify-btn .nb-glyph { display: flex; color: var(--text-dim); }
.notify-btn:hover .nb-glyph { color: var(--accent); }
.notify-btn.is-open { background: var(--accent-soft); border-color: var(--accent); color: var(--accent); }
.notify-btn.is-open .nb-glyph { color: var(--accent); }
/* The count is the whole point of the bell: it is the only way to know something is
   waiting without opening anything. It is never 0 — an empty bell is silence. */
.notify-btn .nb-count {
  display: none; min-width: 16px; padding: 0 4px; border-radius: 8px;
  background: var(--accent); color: var(--surface-solid); font-size: 10px; font-weight: 700;
  line-height: 16px; text-align: center;
}
.notify-btn.has-unread .nb-count { display: block; }
.notify-btn.has-unread { border-color: var(--accent); }
.notify-btn.has-unread .nb-glyph { color: var(--accent); animation: bell-ring 2.6s ease; }
/* Do not disturb is a state you should be able to see from across the room. */
.notify-btn.is-quiet .nb-glyph { color: var(--text-faint); }
.notify-btn.is-quiet::after {
  content: ''; position: absolute; left: 50%; top: 50%; width: 20px; height: 1.5px;
  background: var(--danger); border-radius: 2px; transform: translate(-50%, -50%) rotate(-38deg);
  opacity: .8;
}
@keyframes bell-ring {
  0%, 55%, 100% { transform: rotate(0); }
  8% { transform: rotate(13deg); }
  16% { transform: rotate(-11deg); }
  24% { transform: rotate(7deg); }
  32% { transform: rotate(-4deg); }
  40% { transform: rotate(2deg); }
}

/* ---------- notifications: the centre ---------- */
/* Anchored to the same corner as the pop-up stack, so opening the centre is reading
   the same pile, not finding a new place for it. */
.notifications {
  position: absolute; right: 12px; bottom: calc(var(--taskbar-h) + 12px); z-index: 100002;
  width: min(370px, calc(100vw - 24px));
  max-height: min(62vh, 560px);
  display: flex; flex-direction: column;
  background: var(--surface); backdrop-filter: blur(20px) saturate(150%);
  border: 1px solid var(--border-strong); border-radius: 12px;
  box-shadow: var(--shadow-pop); overflow: hidden;
  animation: pop-in .18s ease;
}
.notifications.hidden { display: none; }
/* The panel itself is focusable so a keyboard user lands inside the dialog; it is the
   rows inside that should look focused, not the frame. */
.np-panel:focus { outline: none; }
.np-panel { display: flex; flex-direction: column; min-height: 0; flex: 1 1 auto; }
.np-head {
  display: flex; align-items: center; gap: 6px; flex: 0 0 auto;
  padding: 9px 10px; border-bottom: 1px solid var(--border);
}
.np-title { font-size: 13px; font-weight: 700; }
.np-count { font-size: 11px; color: var(--accent); font-weight: 600; }
.np-action {
  border: 1px solid transparent; background: none; color: var(--text-dim); font: inherit; font-size: 11px;
  padding: 3px 7px; border-radius: var(--radius-sm); cursor: pointer;
}
.np-action:hover { color: var(--text); background: var(--hover); }
.np-action:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.np-dnd { border-color: var(--border); }
.np-dnd.on { color: var(--accent); border-color: var(--accent); background: var(--accent-soft); }
.np-close { margin-left: auto; }
.np-list { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 6px 8px 10px; }
.np-group { margin-bottom: 4px; }
.np-day {
  font-size: 10px; letter-spacing: .08em; text-transform: uppercase;
  color: var(--text-faint); padding: 8px 4px 4px; position: sticky; top: 0;
  background: var(--surface); backdrop-filter: blur(6px);
}
.np-item {
  display: flex; align-items: flex-start; gap: 7px; padding: 6px 4px;
  border-radius: var(--radius-sm); border-left: 3px solid transparent;
}
.np-item:hover { background: var(--hover); }
.np-item.unread { background: var(--accent-soft); border-left-color: var(--accent); }
.np-item.np-warn { border-left-color: var(--warn); }
.np-item.np-err { border-left-color: var(--danger); }
.np-item.np-ok.unread { border-left-color: var(--ok); }
.np-glyph { flex: 0 0 auto; width: 16px; text-align: center; color: var(--text-dim); font-size: 13px; padding-top: 2px; }
.np-ok .np-glyph { color: var(--ok); }
.np-warn .np-glyph { color: var(--warn); }
.np-err .np-glyph { color: var(--danger); }
.np-main {
  flex: 1 1 auto; min-width: 0; display: block; text-align: left;
  border: 0; background: none; color: inherit; font: inherit; cursor: pointer; padding: 0;
}
.np-main:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }
.np-t { display: block; font-size: 13px; font-weight: 600; overflow-wrap: anywhere; }
.np-d { display: block; font-size: 12px; color: var(--text-dim); overflow-wrap: anywhere; }
.np-meta { display: flex; flex-wrap: wrap; gap: 5px; font-size: 11px; color: var(--text-faint); margin-top: 2px; }
.np-repeat { color: var(--accent); font-weight: 600; }
.np-btn {
  flex: 0 0 auto; border: 1px solid var(--border); background: var(--surface-2); color: var(--text-dim);
  font: inherit; font-size: 11px; padding: 3px 7px; border-radius: var(--radius-sm); cursor: pointer;
}
.np-btn:hover { color: var(--text); background: var(--hover); }
.np-btn-open { color: var(--accent); border-color: var(--accent); }
.np-btn-open:hover { background: var(--accent-soft); }
.np-btn-x { padding: 3px 5px; }
.np-empty { text-align: center; padding: 34px 22px; color: var(--text-dim); }
.np-empty-glyph { color: var(--text-faint); opacity: .55; margin-bottom: 8px; }
.np-empty-t { font-size: 13px; font-weight: 600; color: var(--text); margin-bottom: 6px; }
.np-empty p { font-size: 12px; line-height: 1.5; margin: 0; }
.np-foot {
  display: flex; align-items: center; gap: 8px; flex: 0 0 auto;
  padding: 7px 10px; border-top: 1px solid var(--border); font-size: 11px; color: var(--text-faint);
}
.np-status { flex: 1 1 auto; min-width: 0; }
.np-keys { flex: 0 0 auto; }

/* ---------- notifications: asking for attention ---------- */
/* The taskbar button of an app you are *not* looking at, with something you have not
   seen. It is a request, not an alarm: it stops the moment you look at the app. */
.titem.attention { position: relative; border-color: var(--accent); animation: titem-ask 1.9s ease-in-out infinite; }
.titem.attention .glyph { position: relative; }
.titem.attention::after {
  content: ''; position: absolute; top: 2px; right: 2px; width: 7px; height: 7px;
  border-radius: 50%; background: var(--accent); box-shadow: 0 0 0 2px var(--surface-solid);
}
@keyframes titem-ask {
  0%, 100% { box-shadow: 0 0 0 0 var(--accent-soft); }
  50% { box-shadow: 0 0 0 4px var(--accent-soft); }
}

/* Settings' notification card reads the same list the centre draws. */
.notify-list { display: flex; flex-direction: column; gap: 3px; }
.notify-row {
  display: flex; align-items: center; gap: 8px; padding: 5px 7px; font-size: 12px;
  border: 1px solid var(--border); border-left: 3px solid var(--border);
  border-radius: var(--radius-sm); background: var(--surface-2);
}
.notify-row.unread { border-left-color: var(--accent); }
.notify-row.np-warn { border-left-color: var(--warn); }
.notify-row.np-err { border-left-color: var(--danger); }
.nr-kind { flex: 0 0 auto; font-family: var(--mono); font-size: 10px; text-transform: uppercase; color: var(--text-faint); }
.nr-t { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nr-age { flex: 0 0 auto; color: var(--text-faint); font-size: 11px; }
.btn.small { padding: 2px 6px; font-size: 11px; }


/* ---------- screensaver ---------- */
/* A full-screen layer over everything except the sign-in screen. The pattern is
   drawn on a canvas inside .saver-art (src/core/screensaver.js reuses the
   wallpaper engine); everything below is the clock that sits on top of it.
   `[data-tone]` comes from the palette the pattern was drawn with, so the clock
   stays readable on a light theme too. */
.screensaver {
  position: absolute; inset: 0; z-index: 100010;
  background: var(--bg);
  color: var(--saver-ink, #eef3ff);
  opacity: 0; transition: opacity .7s ease;
  user-select: none; cursor: none;
}
.screensaver.on { opacity: 1; }
.screensaver .saver-art { position: absolute; inset: 0; }
.screensaver .saver-veil {
  position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(120% 95% at 50% 42%, transparent 38%, rgba(3, 5, 10, .62) 100%);
}
.screensaver .saver-panel {
  position: absolute; left: 0; right: 0; bottom: 14vh;
  display: flex; flex-direction: column; align-items: center; gap: 12px;
  text-align: center; text-shadow: 0 2px 22px rgba(0, 0, 0, .55);
}
.saver-time {
  font-size: clamp(58px, 11vw, 150px); font-weight: 250; line-height: 1;
  letter-spacing: .01em; font-variant-numeric: tabular-nums;
}
.saver-date { font-size: clamp(13px, 1.5vw, 19px); margin-top: -4px; color: var(--saver-dim, currentColor); opacity: .85; }
.saver-mode {
  font-size: 11.5px; letter-spacing: .16em; text-transform: uppercase; opacity: .5;
  color: var(--saver-dim, currentColor);
}
.saver-hint {
  position: absolute; left: 0; right: 0; bottom: 6vh; text-align: center;
  font-size: 12.5px; color: var(--saver-dim, currentColor);
  /* The hint waits a moment, then fades in. It is a transition rather than an
     animation so the strength can follow the palette it is sitting on: the same
     grey is invisible over a pale pattern and loud over a dark one. (A var() in
     @keyframes would be read once, at page load, before any palette exists.) */
  opacity: 0; --hint-o: .55;
  transition: opacity .35s ease;
}
.screensaver.on .saver-hint { opacity: var(--hint-o); transition: opacity 1.2s ease 2.4s; }
.screensaver.no-clock .saver-clock { display: none; }
.screensaver[data-tone="light"] .saver-veil {
  /* A white vignette is what makes a pale clock readable, but the hint sits in
     the thickest part of it: too strong and the hint vanishes into it. */
  background: radial-gradient(120% 95% at 50% 42%, transparent 42%, rgba(255, 255, 255, .3) 100%);
}
.screensaver[data-tone="light"] .saver-panel { text-shadow: 0 2px 18px rgba(255, 255, 255, .6); }
.screensaver[data-tone="light"] .saver-hint { --hint-o: .82; }
.screensaver[data-tone="light"] .saver-mode { opacity: .72; }
.screensaver[data-tone="light"] .saver-date { opacity: .95; }
@media (prefers-reduced-motion: reduce) {
  .screensaver { transition: none; }
  .saver-hint, .screensaver.on .saver-hint { transition: none; }
}

/* ---------- shared app UI ---------- */
.app { height: 100%; display: flex; flex-direction: column; background: var(--surface-solid); }
.toolbar {
  display: flex; align-items: center; gap: 6px; padding: 7px 9px; flex: 0 0 auto;
  flex-wrap: nowrap; border-bottom: 1px solid var(--border); background: var(--surface-2);
}
.toolbar .spacer { flex: 1 1 8px; min-width: 4px; }
.btn {
  height: 28px; padding: 0 10px; border-radius: 7px; cursor: pointer; flex: 0 0 auto;
  white-space: nowrap; border: 1px solid var(--border); background: var(--surface-3); color: var(--text); font-size: 12.5px;
}
.btn:hover { background: var(--active); }
.btn.primary { background: var(--accent); border-color: transparent; color: #fff; font-weight: 600; }
.btn.primary:hover { filter: brightness(1.08); }
.btn.ghost { background: transparent; }
.btn.danger { background: var(--danger); border-color: transparent; color: #fff; }
.field {
  height: 28px; padding: 0 9px; border-radius: 7px; min-width: 0;
  background: var(--surface-solid); border: 1px solid var(--border); outline: none;
}
.field:focus { border-color: var(--accent); }
.statusbar {
  flex: 0 0 auto; display: flex; gap: 14px; align-items: center;
  padding: 5px 10px; font-size: 11.5px; color: var(--text-dim);
  border-top: 1px solid var(--border); background: var(--surface-2);
}
.pad { padding: 14px; }
.muted { color: var(--text-dim); }
.mono { font-family: var(--mono); }

/* ---------- terminal ---------- */
.term { height: 100%; display: flex; flex-direction: column; background: #080c16; }
html[data-theme="light"] .term { background: #0f172a; }
.term-out {
  flex: 1; overflow: auto; padding: 10px 12px;
  font-family: var(--mono); font-size: 13px; line-height: 1.5; white-space: pre-wrap; word-break: break-word;
}
.term-out .err { color: var(--danger); }
.term-out .dim { color: var(--text-faint); }
.term-out .acc { color: var(--accent); }
.term-out .ok { color: var(--ok); }
/* The echo of the line you typed: prompt in the accent, the shell's operators picked out. */
.term-out .cmd { color: var(--text); word-break: normal; }
.term-out .cmd .term-echo-prompt { color: var(--accent); opacity: .75; }
.term-out .cmd .op { color: var(--accent); font-weight: 700; }
/* `$NAME`, `$?` and `$( … )` are the shell's own syntax: coloured apart from the
   operators next to them, because they mean something different — a value, not a join. */
.term-out .cmd .var { color: var(--ok); font-style: italic; }
.term-out a { color: var(--accent); }
.term-out .neof { color: var(--accent); font-weight: 600; }
.term-row { flex: 0 0 auto; display: flex; gap: 8px; align-items: center; padding: 8px 12px; border-top: 1px solid var(--border); background: rgba(255,255,255,.03); }
.term-cwd { font-family: var(--mono); font-size: 12.5px; color: var(--accent); white-space: nowrap; }
.term-input { flex: 1; background: transparent; border: 0; outline: none; font-family: var(--mono); font-size: 13px; }
.term-input::placeholder { color: var(--text-faint); }

/* ---------- files ---------- */
.files { flex-direction: row; }
.files-side { width: 172px; flex: 0 0 auto; border-right: 1px solid var(--border); background: var(--surface-2); padding: 8px; overflow: auto; }
.side-item {
  width: 100%; display: flex; gap: 8px; align-items: center; padding: 7px 8px;
  border: 0; background: transparent; color: var(--text); border-radius: 7px; cursor: pointer; font-size: 12.5px; text-align: left;
}
.side-item:hover { background: var(--hover); }
.side-item.active { background: var(--accent-soft); color: var(--accent); }
.files-main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.crumbs { display: flex; gap: 2px; align-items: center; font-size: 12px; color: var(--text-dim); overflow: hidden; min-width: 0; flex: 0 1 auto; }
.crumbs button { background: none; border: 0; color: var(--text); cursor: pointer; padding: 4px 6px; border-radius: 5px; font-size: 12px; white-space: nowrap; }
.crumbs button:last-child { text-overflow: ellipsis; overflow: hidden; white-space: nowrap; max-width: 160px; }
.crumbs button:hover { background: var(--hover); }
.filegrid {
  flex: 1; overflow: auto; align-content: start;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(104px, 1fr)); gap: 6px; padding: 12px;
}
.filecell {
  display: flex; flex-direction: column; align-items: center; gap: 6px; padding: 10px 6px;
  border: 1px solid transparent; border-radius: 9px; cursor: default; background: transparent; color: var(--text);
}
.filecell:hover { background: var(--hover); border-color: var(--border); }
.filecell.selected { background: var(--accent-soft); border-color: var(--accent); }
.filecell .glyph { font-size: 28px; }
.filecell .name { font-size: 11.5px; text-align: center; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.filecell .meta { font-size: 10px; color: var(--text-faint); }
.empty-state { padding: 28px; text-align: center; color: var(--text-faint); font-size: 13px; }

/* ---------- editor ---------- */
.editor-area {
  flex: 1; min-height: 0; width: 100%; resize: none; border: 0; outline: none;
  padding: 14px 16px; background: var(--surface-solid); color: var(--text);
  font-family: var(--mono); font-size: 13.5px; line-height: 1.6; tab-size: 2;
}

/* ---------- viewer ---------- */
.viewer-main { flex: 1; min-height: 0; display: grid; place-items: center; padding: 14px; overflow: auto; background:
  repeating-conic-gradient(var(--surface-2) 0% 25%, var(--surface-solid) 0% 50%) 50% / 22px 22px; }
.viewer-main img { max-width: 100%; max-height: 100%; border-radius: 8px; box-shadow: var(--shadow-pop); }
.viewer-text { align-items: stretch; justify-content: stretch; display: block; overflow: auto; background: var(--surface-solid); padding: 16px; font-family: var(--mono); font-size: 13px; white-space: pre-wrap; }

/* ---------- paint ---------- */
.paint-main { flex: 1; min-height: 0; position: relative; overflow: hidden; }
.paint-canvas { position: absolute; inset: 0; width: 100%; height: 100%; cursor: crosshair; touch-action: none; }
.swatch { width: 26px; height: 26px; border-radius: 6px; border: 1px solid var(--border); padding: 0; background: transparent; cursor: pointer; }
input[type="color"].swatch { padding: 0; }
input[type="color"].swatch::-webkit-color-swatch-wrapper { padding: 3px; }
input[type="color"].swatch::-webkit-color-swatch { border: none; border-radius: 4px; }
.seg { display: inline-flex; border: 1px solid var(--border); border-radius: 7px; overflow: hidden; }
.seg button { border: 0; background: transparent; color: var(--text-dim); padding: 5px 10px; cursor: pointer; font-size: 12.5px; }
.seg button.active { background: var(--accent); color: #fff; }

/* ---------- calculator ---------- */
.calc { max-width: 340px; margin: 0 auto; width: 100%; height: 100%; display: flex; flex-direction: column; }
.calc-display {
  margin: 12px; padding: 14px; border-radius: 10px; background: var(--surface-2);
  border: 1px solid var(--border); text-align: right; font-family: var(--mono); flex: 0 0 auto;
}
.calc-display .expr { font-size: 12px; color: var(--text-faint); min-height: 16px; }
.calc-display .val { font-size: 28px; font-weight: 600; word-break: break-all; }
/* The keypad flexes so a short window (a quarter tile) still shows every row. */
.calc-pad { display: grid; grid-template-columns: repeat(4, 1fr); grid-auto-rows: 1fr; gap: 6px; padding: 0 12px 12px; flex: 1 1 auto; min-height: 0; }
.calc-key {
  min-height: 30px; height: 100%; border-radius: 10px; border: 1px solid var(--border);
  background: var(--surface-3); color: var(--text); font-size: 17px; cursor: pointer;
}
.calc-key:hover { background: var(--active); }
.calc-key.op { background: var(--accent-soft); color: var(--accent); }
.calc-key.eq { background: var(--accent); color: #fff; border-color: transparent; font-weight: 700; }

/* ---------- clock ---------- */
/* The Clock app is four panels behind one tab strip. The numbers are the interface,
   so every read-out is tabular monospace: a countdown must not wiggle as it ticks. */
.clock-tabs {
  display: flex; align-items: center; gap: 4px; flex-wrap: wrap; flex: 0 0 auto;
  padding: 7px 9px; border-bottom: 1px solid var(--border); background: var(--surface-2);
}
.clock-tab {
  display: flex; align-items: center; gap: 6px; height: 28px; padding: 0 10px; border-radius: 7px;
  border: 1px solid transparent; background: transparent; color: var(--text-dim);
  cursor: pointer; font-size: 12.5px; white-space: nowrap;
}
.clock-tab:hover { background: var(--hover); color: var(--text); }
.clock-tab.on { background: var(--accent-soft); border-color: var(--accent); color: var(--accent); }
.clock-tab .ct-glyph { font-size: 14px; }
.ct-badge {
  min-width: 17px; padding: 1px 5px; border-radius: 9px; background: var(--accent); color: #fff;
  font-size: 10.5px; font-weight: 700; text-align: center;
}
.clock-panel { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; overflow: hidden; }
.clock-read { font-family: var(--mono); font-variant-numeric: tabular-nums; letter-spacing: -.02em; }
.clock-huge { font-size: 42px; font-weight: 700; line-height: 1.05; }
.clock-big { font-size: 21px; font-weight: 600; }
.chip {
  border: 1px solid var(--border); background: var(--surface-3); color: var(--text);
  border-radius: 999px; padding: 4px 11px; font-size: 11.5px; cursor: pointer; white-space: nowrap;
}
.chip:hover { background: var(--accent-soft); border-color: var(--accent); color: var(--accent); }

/* world clock */
.wc, .tm, .sw, .al { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
.wc-here { flex: 0 0 auto; padding: 14px 16px 12px; display: flex; flex-direction: column; gap: 4px; border-bottom: 1px solid var(--border); }
.wc-here-meta { display: flex; gap: 12px; flex-wrap: wrap; font-size: 12px; }
.wc-here-actions { display: flex; gap: 6px; margin-top: 8px; }
.wc-add { flex: 0 0 auto; padding: 10px 16px; display: flex; flex-direction: column; gap: 8px; }
.wc-add .wc-input { width: 100%; }
.wc-suggest { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; font-size: 11.5px; }
.wc-list { flex: 1 1 auto; min-height: 0; overflow: auto; padding: 0 16px 12px; }
.wc-row {
  display: grid; grid-template-columns: minmax(0, 1fr) auto auto auto; align-items: center; gap: 14px;
  padding: 9px 2px; border-bottom: 1px solid var(--border);
}
.wc-city { display: flex; flex-direction: column; min-width: 0; font-size: 12px; }
.wc-city-name { font-size: 13px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wc-meta { display: flex; flex-direction: column; gap: 2px; font-size: 11px; text-align: right; }
.wc-day { color: var(--text-dim); }
.wc-day.off { color: var(--accent); font-weight: 600; }

/* timers */
.tm-new { flex: 0 0 auto; display: flex; gap: 8px; padding: 12px 16px 8px; }
.tm-duration { width: 212px; min-width: 212px; font-family: var(--mono); }
.tm-label { flex: 1 1 120px; min-width: 90px; }
.tm-presets { flex: 0 0 auto; display: flex; gap: 6px; flex-wrap: wrap; padding: 0 16px 10px; }
.tm-list { flex: 1 1 auto; min-height: 0; overflow: auto; padding: 0 16px 12px; display: flex; flex-direction: column; gap: 8px; }
.tm-row { border: 1px solid var(--border); border-radius: 10px; padding: 10px 12px; background: var(--surface-2); }
.tm-row-top { display: flex; align-items: center; gap: 12px; }
.tm-label-text { flex: 1 1 auto; min-width: 0; font-size: 13px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tm-bar { height: 5px; border-radius: 3px; background: var(--hover); overflow: hidden; margin-top: 8px; }
.tm-bar-fill { height: 100%; background: var(--accent); transition: width .3s linear; }
.tm-row-meta { font-size: 11px; margin-top: 6px; }

/* stopwatch */
.sw-read { text-align: center; padding: 20px 16px 4px; flex: 0 0 auto; }
.sw-actions { flex: 0 0 auto; display: flex; gap: 8px; justify-content: center; padding: 10px 16px; }
.sw-laps { flex: 1 1 auto; min-height: 0; overflow: auto; padding: 6px 16px 12px; }
.sw-laps-head, .sw-lap { display: grid; grid-template-columns: 44px 1fr 1fr; gap: 10px; padding: 6px 4px; border-bottom: 1px solid var(--border); font-size: 12.5px; }
.sw-laps-head { color: var(--text-faint); font-size: 11px; border-bottom-color: var(--border); }
.sw-lap.best .mono:first-of-type { color: var(--ok); }
.sw-lap.worst .mono:first-of-type { color: var(--danger); }

/* alarms */
.al-new { flex: 0 0 auto; display: flex; gap: 8px; align-items: center; flex-wrap: wrap; padding: 12px 16px; }
.al-time { width: 128px; font-family: var(--mono); }
.al-label { flex: 1 1 140px; min-width: 90px; }
.al-zone { max-width: 240px; }
.al-repeat { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--text-dim); cursor: pointer; }
.al-list { flex: 1 1 auto; min-height: 0; overflow: auto; padding: 0 16px 12px; display: flex; flex-direction: column; gap: 6px; }
.al-row {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto auto auto; align-items: center; gap: 12px;
  padding: 9px 12px; border: 1px solid var(--border); border-radius: 10px; background: var(--surface-2);
}
.al-row.off { opacity: .55; }
.al-info { display: flex; flex-direction: column; min-width: 0; font-size: 11.5px; }
.al-name, .al-label-text { font-size: 13px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.al-countdown { font-family: var(--mono); font-size: 12px; color: var(--accent); white-space: nowrap; }
.al-countdown.off { color: var(--text-faint); }

/* ---------- synth ---------- */
.synth-main { flex: 1; min-height: 0; overflow: auto; padding: 12px; display: flex; flex-direction: column; gap: 12px; }
.synth-viz {
  width: 100%; height: 82px; flex: 0 0 auto; border-radius: 10px;
  background: var(--surface-2); border: 1px solid var(--border);
}
.synth-keys {
  position: relative; flex: 0 0 auto; height: 128px; display: flex; overflow: hidden;
  border: 1px solid var(--border); border-radius: 10px; background: var(--surface-2);
  user-select: none; -webkit-user-select: none; touch-action: none;
}
.wkey {
  flex: 1 1 0; min-width: 0; cursor: pointer; color: #1b2333;
  border: 1px solid rgba(0, 0, 0, .35); border-radius: 0 0 6px 6px;
  background: linear-gradient(180deg, #fbfcff, #dde3f0);
  display: flex; align-items: flex-end; justify-content: center; padding-bottom: 6px;
}
.wkey:hover { background: linear-gradient(180deg, #fff, #e6ebf6); }
.wkey.down { background: linear-gradient(180deg, var(--accent), color-mix(in srgb, var(--accent) 55%, #ffffff)); color: #fff; }
.wkey .keyname { font-family: var(--mono); font-size: 10px; opacity: .5; pointer-events: none; }
.bkey {
  position: absolute; top: 0; height: 62%; width: 4.4%; z-index: 2; cursor: pointer;
  border: 1px solid #05070d; border-radius: 0 0 5px 5px;
  background: linear-gradient(180deg, #2a3247, #0d1220);
}
.bkey:hover { background: linear-gradient(180deg, #39435d, #141b2b); }
.bkey.down { background: linear-gradient(180deg, var(--accent), color-mix(in srgb, var(--accent) 60%, #000000)); }

.synth-seq {
  --seq-cols: 16;
  flex: 0 0 auto; display: flex; flex-direction: column; gap: 2px;
  border: 1px solid var(--border); border-radius: 10px; padding: 8px; background: var(--surface-2);
}
.seq-row { display: grid; grid-template-columns: 44px repeat(var(--seq-cols), minmax(0, 1fr)); gap: 2px; }
.seq-label {
  font-family: var(--mono); font-size: 10px; color: var(--text-faint);
  display: flex; align-items: center; justify-content: flex-end; padding-right: 5px; user-select: none;
}
.seq-label.root { color: var(--text-dim); font-weight: 600; }
.seq-cell {
  height: 15px; min-width: 0; padding: 0; cursor: pointer;
  border: 1px solid var(--border); border-radius: 3px; background: var(--surface-solid);
}
.seq-cell.beat { border-color: var(--border-strong); }
.seq-cell:hover { background: var(--active); }
.seq-cell.on { background: var(--accent); border-color: transparent; }
.seq-cell.live { box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent-2) 70%, transparent); }
.seq-head .seq-step { font-family: var(--mono); font-size: 10px; color: var(--text-faint); text-align: center; }
.seq-head .seq-step.active { color: var(--accent); font-weight: 700; }

.synth-library { border: 1px solid var(--border); border-radius: 10px; padding: 10px; background: var(--surface-2); display: flex; flex-direction: column; min-height: 0; }
.synth-library .start-section { margin: 0 0 8px; }
.synth-bottom { display: grid; grid-template-columns: minmax(0, 1fr) 264px; gap: 12px; flex: 0 0 auto; }
.synth-save-row { display: flex; gap: 8px; }
.synth-name { flex: 1 1 auto; min-width: 0; }
.song-list { display: flex; flex-direction: column; gap: 4px; margin-top: 8px; flex: 1 1 auto; min-height: 0; overflow: auto; }
.song-row {
  display: grid; grid-template-columns: 18px minmax(0, 1fr) auto; gap: 8px; align-items: center;
  padding: 6px 8px; font-size: 12.5px;
  border: 1px solid var(--border); border-radius: 8px; background: var(--surface-solid);
}
.song-row .glyph { font-size: 16px; }
.song-text { display: flex; flex-direction: column; min-width: 0; }
.song-name { font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.song-meta { color: var(--text-faint); font-size: 11px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.song-actions { display: flex; gap: 4px; }

.synth-preset { width: 100px; flex: 0 1 auto; }
.synth-wave button { font-size: 11.5px; padding: 5px 8px; }
.synth-octave { display: flex; align-items: center; gap: 4px; flex: 0 0 auto; }
.synth-octave-label { font-family: var(--mono); font-size: 11px; color: var(--text-dim); min-width: 44px; text-align: center; }
.synth-bpm { width: 84px; flex: 0 1 84px; accent-color: var(--accent); }
.synth-bpm-value { font-size: 11.5px; color: var(--text-dim); font-variant-numeric: tabular-nums; white-space: nowrap; }
.synth-transport.playing { background: var(--ok); border-color: transparent; color: #08130d; }
.statusbar .acc { color: var(--accent); font-weight: 600; }
.synth-status { display: flex; flex-wrap: wrap; align-items: center; gap: 14px; min-width: 0; }
.btn.tiny { height: 24px; padding: 0 8px; font-size: 11.5px; }
@media (max-width: 780px) {
  .synth-bottom { grid-template-columns: minmax(0, 1fr); }
  .song-list { max-height: 150px; }
}

/* ---------- notes ---------- */
.notes { flex-direction: row; }
.notes-side {
  width: 262px; flex: 0 0 262px; display: flex; flex-direction: column;
  border-right: 1px solid var(--border); background: var(--surface-2);
}
.notes-tools { display: flex; gap: 6px; padding: 8px; border-bottom: 1px solid var(--border); }
.notes-search { flex: 1; min-width: 0; }
.notes-list { flex: 1; overflow: auto; padding: 6px; display: flex; flex-direction: column; gap: 4px; }
.note-item {
  display: flex; gap: 8px; align-items: flex-start; width: 100%; text-align: left;
  padding: 8px; border: 1px solid transparent; border-radius: var(--radius-sm);
  background: transparent; color: var(--text); cursor: pointer;
}
.note-item:hover { background: var(--hover); }
.note-item.selected { background: var(--accent-soft); border-color: var(--accent); }
.note-item:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.note-dot { width: 12px; height: 12px; flex: 0 0 auto; margin-top: 3px; border-radius: 3px; border: 1px solid; box-shadow: 0 1px 2px rgb(0 0 0 / .3); }
.note-item-main { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.note-item-title { font-size: 13px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.note-item-meta { font-size: 11px; color: var(--text-dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.notes-main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.note-colors { display: flex; gap: 5px; align-items: center; }
.swatch { width: 22px; height: 22px; border-radius: 5px; border: 2px solid; cursor: pointer; opacity: .5; }
.swatch:hover { opacity: .85; }
.swatch.on { opacity: 1; box-shadow: 0 0 0 2px var(--accent); }
.swatch:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; opacity: 1; }
.note-body {
  flex: 1; min-height: 0; padding: 14px 16px; border: 0; outline: none; resize: none;
  background: var(--note-bg, var(--surface-solid)); color: var(--note-ink, var(--text));
  font-family: var(--font); font-size: 14px; line-height: 1.55;
}
.note-body:disabled { background: var(--surface-2); color: var(--text-faint); }

/* ---------- settings ---------- */
.settings-main { flex: 1; overflow: auto; padding: 16px; }
.card { border: 1px solid var(--border); border-radius: 12px; padding: 14px; margin-bottom: 14px; background: var(--surface-2); }
.card h3 { margin: 0 0 4px; font-size: 14px; }
.card p { margin: 0 0 12px; color: var(--text-dim); font-size: 12.5px; }
.row { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.wp-tile {
  width: 104px; height: 64px; border-radius: 9px; border: 2px solid var(--border); cursor: pointer;
  background-size: cover; background-position: center;
}
.wp-tile.active { border-color: var(--accent); }
/* Live wallpaper pattern picker: every tile is a real frame drawn by the engine.
   `.saver-pattern` is the screensaver's own picker — the same tiles, because it
   draws the same patterns, but a separate question from what the desktop wears. */
.wp-pattern, .saver-pattern {
  width: 104px; display: flex; flex-direction: column; gap: 4px; padding: 4px;
  border: 2px solid var(--border); border-radius: 9px; background: var(--surface-solid);
  cursor: pointer; color: var(--text-dim);
}
.wp-pattern:hover, .saver-pattern:hover { border-color: var(--border-strong); background: var(--hover); }
.wp-pattern.active, .saver-pattern.active { border-color: var(--accent); color: var(--text); }

/* The desktop clock's face picker. The tiles hold the real widget, so they are the
   size of the thing they are offering rather than a drawing of it. */
.dc-faces { gap: 10px; align-items: flex-start; }
.dc-face-tile {
  display: flex; flex-direction: column; gap: 5px; padding: 6px 8px 8px;
  border: 1px solid var(--border); border-radius: 10px; background: transparent;
  color: var(--text-dim); font: inherit; cursor: pointer;
}
/* The name under a preview is a caption, not a headline: the preview itself is the
   thing being chosen, and a full-size label would shout over a scaled-down clock. */
.dc-face-tile .wp-pattern-label { font-size: 13px; font-weight: 600; margin-top: auto; text-align: center; }
.dc-face-tile:hover { border-color: var(--border-strong); background: var(--hover); }
.dc-face-tile.active { border-color: var(--accent); color: var(--text); }
.dc-face-tile.active .wp-pattern-label { color: var(--text); }
.wp-preview, .wp-preview-static, .saver-preview, .saver-preview-static { width: 100%; height: 54px; display: block; border-radius: 6px; background-size: cover; background-position: center; }
/* The speed control shares the section header row so the picker stays above the fold. */
.wp-motion-head { justify-content: space-between; align-items: center; }
.wp-motion-head .start-section { margin: 0 0 2px; }
.wp-speed-group { display: flex; align-items: center; gap: 8px; }
.wp-speed { width: 150px; accent-color: var(--accent); }
.wp-speed:disabled { opacity: .45; }
.wp-speed-label { font-size: 12px; color: var(--text-dim); }
.wp-speed-value { font-size: 11.5px; color: var(--text-dim); font-variant-numeric: tabular-nums; }
.wp-status, .saver-status { margin-top: 4px; font-size: 11.5px; color: var(--text-faint); }
.wp-status.live, .saver-status.live { color: var(--text-dim); }
.kv { display: grid; grid-template-columns: 130px 1fr; gap: 4px 10px; font-size: 12.5px; }
.kv .k { color: var(--text-dim); }

/* Settings → Desktop looks: one row per desktop, painted with that desktop's own
   wallpaper so the list is a picture of the desktops, not a table of names. */
.ws-looks { display: flex; flex-direction: column; gap: 6px; margin-bottom: 10px; }
.ws-look-row { display: flex; align-items: center; gap: 8px; }
.ws-look-swatch {
  width: 26px; height: 20px; flex: 0 0 auto; border-radius: 5px;
  border: 1px solid var(--border-strong); background: var(--wallpaper-default);
  box-shadow: inset 0 0 0 1px rgb(0 0 0 / .22);
}
.ws-look-n {
  width: 18px; height: 18px; flex: 0 0 auto; border-radius: 4px; display: grid; place-items: center;
  background: var(--surface-3); font-size: 10px; font-weight: 700; font-variant-numeric: tabular-nums;
}
.ws-look-name { font-size: 12.5px; font-weight: 600; flex: 0 1 auto; min-width: 76px; max-width: 150px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ws-look-note { flex: 1; min-width: 0; font-size: 11.5px; color: var(--text-dim); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Keyboard shortcut editor. One row per binding the machine actually answers today —
   workspace slots that do not exist are not listed, and neither is an action that
   is not installed. */
.keys-head { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
.keys-filter {
  flex: 1; min-width: 150px; height: 28px; padding: 0 10px; border-radius: 7px;
  border: 1px solid var(--border); background: var(--surface-solid); color: var(--text); font-size: 12.5px;
}
.keys-count { font-size: 11.5px; color: var(--text-faint); white-space: nowrap; }
.keys-status {
  margin: 0 0 10px; padding: 8px 10px; border-radius: 8px; font-size: 12.5px;
  border: 1px solid var(--border); background: var(--surface-solid); color: var(--text-dim);
}
.keys-status.ok { border-color: var(--ok); color: var(--text); }
.keys-status.warn { border-color: var(--warn); color: var(--text); }
.keys-status.err { border-color: var(--danger); color: var(--text); }
.keys-list { display: flex; flex-direction: column; }
.keys-note { margin: 12px 0 0; font-size: 11.5px; line-height: 1.5; color: var(--text-faint); }
.keys-group { margin-bottom: 4px; }
.keyrow { display: flex; align-items: center; gap: 10px; padding: 4px 6px; border-radius: 8px; }
.keyrow:hover { background: var(--surface-solid); }
.keyrow.capturing { background: var(--surface-solid); outline: 1px solid var(--accent); }
.key-chord {
  min-width: 128px; flex: 0 0 auto; text-align: center; padding: 3px 7px; border-radius: 6px;
  font-family: var(--mono); font-size: 11.5px; border: 1px solid var(--border-strong);
  background: var(--surface-3); color: var(--text);
}
.key-chord.none { border-style: dashed; background: transparent; color: var(--text-faint); }
.key-chord.recording { border-color: var(--accent); color: var(--accent); animation: key-wait 1.2s ease-in-out infinite; }
@keyframes key-wait { 50% { opacity: .45; } }
@media (prefers-reduced-motion: reduce) { .key-chord.recording { animation: none; } }
.key-label { flex: 1 1 auto; min-width: 0; font-size: 12.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.key-flag { font-size: 10px; letter-spacing: .08em; text-transform: uppercase; color: var(--accent); flex: 0 0 auto; }
.key-actions { display: flex; gap: 6px; margin-left: auto; flex: 0 0 auto; }
.keyrow .btn.tiny { height: 26px; }

/* ---------- web ---------- */
.web-main { flex: 1; min-height: 0; border: 0; width: 100%; background: #fff; }

/* ---------- welcome ---------- */
.welcome { padding: 18px 20px; overflow: auto; }
.welcome h1 { margin: 0 0 4px; font-size: 20px; }
.welcome .sub { color: var(--text-dim); margin-bottom: 12px; font-size: 12.5px; }
.welcome ul { margin: 0 0 14px; padding-left: 18px; font-size: 12.5px; line-height: 1.55; }
.welcome code { font-family: var(--mono); background: var(--surface-2); padding: 1px 5px; border-radius: 4px; font-size: 12px; }
.welcome .cta { display: flex; gap: 8px; flex-wrap: wrap; }

::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-thumb { background: var(--border-strong); border-radius: 8px; border: 2px solid transparent; background-clip: padding-box; }
::-webkit-scrollbar-thumb:hover { background: var(--text-faint); }
::-webkit-scrollbar-track { background: transparent; }

@media (max-width: 720px) {
  .files-side { width: 128px; }
  .notes-side { width: 178px; flex: 0 0 178px; }
  .launcher-panel { width: calc(100vw - 16px); }
  .start-label { display: none; }
  .tray-timer .tt-label { display: none; }
}
