/* DeskMGR shell: GNOME / Adwaita flavoured desktop */

:root {
  --pad-top: 32px;
  --pad-right: 0px;
  --pad-bottom: 0px;
  --pad-left: 0px;
  --tb-size: 40px;
  --accent: #3584e4;
  --accent-fg: #fff;
  --radius: 12px;
  --hb-h: 46px;
  --bar-h: 32px;
  --font: -apple-system, "Cantarell", "Inter", "Segoe UI", system-ui, sans-serif;
  --mono: "JetBrains Mono", "Cascadia Mono", "DejaVu Sans Mono", ui-monospace, monospace;
  --ease: cubic-bezier(.2, .7, .3, 1);
}

[data-accent="blue"]   { --accent: #3584e4; }
[data-accent="teal"]   { --accent: #2190a4; }
[data-accent="green"]  { --accent: #3a944a; }
[data-accent="yellow"] { --accent: #c88800; }
[data-accent="orange"] { --accent: #ed5b00; }
[data-accent="red"]    { --accent: #e62d42; }
[data-accent="pink"]   { --accent: #d56199; }
[data-accent="purple"] { --accent: #9141ac; }
[data-accent="slate"]  { --accent: #6f8396; }

[data-theme="dark"] {
  --win-bg: #1d1d1d;
  --win-fg: #ffffff;
  --hb-bg: #303030;
  --hb-bg-inactive: #242424;
  --card: #303030;
  --card-hi: #383838;
  --sunken: #131313;
  --line: rgba(255,255,255,.10);
  --line-strong: rgba(255,255,255,.18);
  --dim: rgba(255,255,255,.62);
  --dimmer: rgba(255,255,255,.42);
  --btn: rgba(255,255,255,.10);
  --btn-hover: rgba(255,255,255,.16);
  --shadow: 0 24px 60px rgba(0,0,0,.6), 0 4px 14px rgba(0,0,0,.5);
  --panel: rgba(28,28,28,.86);
}

[data-theme="light"] {
  --win-bg: #fafafa;
  --win-fg: #1a1a1a;
  --hb-bg: #ebebeb;
  --hb-bg-inactive: #f4f4f4;
  --card: #ffffff;
  --card-hi: #f2f2f2;
  --sunken: #f0f0f0;
  --line: rgba(0,0,0,.10);
  --line-strong: rgba(0,0,0,.18);
  --dim: rgba(0,0,0,.60);
  --dimmer: rgba(0,0,0,.42);
  --btn: rgba(0,0,0,.07);
  --btn-hover: rgba(0,0,0,.12);
  --shadow: 0 24px 60px rgba(0,0,0,.28), 0 4px 12px rgba(0,0,0,.18);
  --panel: rgba(250,250,250,.86);
}

* { box-sizing: border-box; }

/* author rules that set display would otherwise beat the UA [hidden] rule */
[hidden] { display: none !important; }

html, body {
  height: 100%;
  margin: 0;
  overflow: hidden;
  font-family: var(--font);
  color: var(--win-fg);
  background: #101014;
  -webkit-font-smoothing: antialiased;
  user-select: none;
}

button, input, select, textarea { font-family: inherit; font-size: inherit; color: inherit; }
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--line-strong); border-radius: 8px; border: 2px solid transparent; background-clip: content-box; }
::-webkit-scrollbar-thumb:hover { background: var(--dimmer); background-clip: content-box; }
* { scrollbar-width: thin; scrollbar-color: var(--line-strong) transparent; }

/* ---------- wallpapers ----------
   Every wallpaper carries a third selector for the settings swatch. Without it the two rules
   `[data-wallpaper="a"] .wp` (body, the live desktop) and `[data-wallpaper="b"] .wp` (the swatch)
   have the same specificity, so whichever sits later in the file paints every swatch: picking a
   wallpaper defined near the end of skins.css turned the whole picker into that one picture. */

.wp, #lock {
  position: fixed; inset: 0;
  background-size: cover; background-position: center;
}
[data-wallpaper="aurora"] .wp, [data-wallpaper="aurora"] #lock,
.wall-prev[data-wallpaper="aurora"] .wp {
  background:
    radial-gradient(75% 70% at 12% 8%, #4b6ef5 0%, transparent 60%),
    radial-gradient(60% 70% at 88% 22%, #a24bd6 0%, transparent 62%),
    radial-gradient(65% 80% at 62% 96%, #17a3a3 0%, transparent 58%),
    linear-gradient(160deg, #10142b 0%, #1a1030 55%, #0c1524 100%);
}
[data-wallpaper="sunset"] .wp, [data-wallpaper="sunset"] #lock,
.wall-prev[data-wallpaper="sunset"] .wp {
  background:
    radial-gradient(60% 62% at 20% 92%, #ff7a3c 0%, transparent 60%),
    radial-gradient(70% 70% at 82% 12%, #ff3d81 0%, transparent 58%),
    linear-gradient(170deg, #2a1140 0%, #451531 60%, #100a1c 100%);
}
[data-wallpaper="forest"] .wp, [data-wallpaper="forest"] #lock,
.wall-prev[data-wallpaper="forest"] .wp {
  background:
    radial-gradient(65% 70% at 78% 14%, #2fbf71 0%, transparent 58%),
    radial-gradient(60% 70% at 14% 88%, #0f8f8f 0%, transparent 60%),
    linear-gradient(165deg, #06231c 0%, #0a2f2a 55%, #041613 100%);
}
[data-wallpaper="graphite"] .wp, [data-wallpaper="graphite"] #lock,
.wall-prev[data-wallpaper="graphite"] .wp {
  background:
    radial-gradient(70% 80% at 30% 10%, #3a3f4b 0%, transparent 62%),
    radial-gradient(60% 70% at 85% 85%, #2b3038 0%, transparent 60%),
    linear-gradient(160deg, #15171c 0%, #1d2027 60%, #0d0f13 100%);
}
[data-wallpaper="bloom"] .wp, [data-wallpaper="bloom"] #lock,
.wall-prev[data-wallpaper="bloom"] .wp {
  background:
    radial-gradient(55% 60% at 15% 20%, #ff9ec7 0%, transparent 58%),
    radial-gradient(60% 70% at 85% 30%, #8ab4ff 0%, transparent 58%),
    radial-gradient(60% 70% at 50% 100%, #ffd18c 0%, transparent 55%),
    linear-gradient(160deg, #241a33 0%, #2c2140 60%, #171227 100%);
}
[data-wallpaper="docker"] .wp, [data-wallpaper="docker"] #lock,
.wall-prev[data-wallpaper="docker"] .wp {
  background:
    radial-gradient(65% 70% at 20% 15%, #1d63ed 0%, transparent 60%),
    radial-gradient(60% 70% at 85% 80%, #00b4d8 0%, transparent 58%),
    linear-gradient(160deg, #041427 0%, #062240 60%, #010d1c 100%);
}

#wallpaper-dim {
  position: fixed; inset: 0;
  background: rgba(0,0,0,0);
  transition: background .28s var(--ease), backdrop-filter .28s var(--ease);
  pointer-events: none;
  backdrop-filter: blur(0px);
}
body.overview #wallpaper-dim { background: rgba(0,0,0,.42); backdrop-filter: blur(22px); }

/* ---------- boot ---------- */

#boot {
  position: fixed; inset: 0; z-index: 999;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 18px;
  background: #101014;
  transition: opacity .45s var(--ease);
}
body:not(.booting) #boot { opacity: 0; pointer-events: none; }
.boot-logo {
  width: 76px; height: 76px; border-radius: 20px;
  background: linear-gradient(150deg, #3584e4, #9141ac);
  box-shadow: 0 0 60px rgba(53,132,228,.45);
  position: relative;
}
.boot-logo::after {
  content: ""; position: absolute; inset: 22px 18px;
  border-radius: 3px;
  background:
    linear-gradient(#fff, #fff) top/100% 6px no-repeat,
    linear-gradient(#fff, #fff) center/100% 6px no-repeat,
    linear-gradient(#fff, #fff) bottom left/60% 6px no-repeat;
}
.boot-name { font-size: 18px; letter-spacing: .12em; color: rgba(255,255,255,.72); text-transform: uppercase; }
.boot-bar { width: 190px; height: 3px; border-radius: 3px; background: rgba(255,255,255,.14); overflow: hidden; }
.boot-bar span { display: block; height: 100%; width: 40%; border-radius: 3px; background: #fff; animation: bootslide 1.1s var(--ease) infinite; }
@keyframes bootslide { 0% { transform: translateX(-110%); } 100% { transform: translateX(360%); } }

/* ---------- lock / login ---------- */

#lock {
  z-index: 900;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 28px;
  color: #fff;
  animation: fadein .4s var(--ease);
}
@keyframes fadein { from { opacity: 0; } to { opacity: 1; } }
.lock-clock { text-align: center; text-shadow: 0 2px 24px rgba(0,0,0,.5); }
.lock-time { font-size: 88px; font-weight: 300; line-height: 1; letter-spacing: -.02em; }
.lock-date { font-size: 18px; opacity: .8; margin-top: 8px; }
.lock-card {
  width: 320px; padding: 26px 24px 22px;
  display: flex; flex-direction: column; align-items: center; gap: 12px;
  background: rgba(20,20,24,.55);
  border: 1px solid rgba(255,255,255,.12);
  border-radius: 18px;
  backdrop-filter: blur(24px);
  box-shadow: 0 24px 60px rgba(0,0,0,.45);
}
.lock-avatar {
  width: 78px; height: 78px; border-radius: 50%;
  background: linear-gradient(150deg, var(--accent), #9141ac);
  border: 2px solid rgba(255,255,255,.25);
  display: grid; place-items: center;
  position: relative;
}
.lock-avatar::after {
  content: ""; width: 34px; height: 34px; border-radius: 50%;
  background: rgba(255,255,255,.92);
  box-shadow: 0 26px 0 -4px rgba(255,255,255,.92);
  transform: translateY(-6px);
}
.lock-user { font-size: 17px; font-weight: 600; }
.lock-card input {
  width: 100%; padding: 10px 12px;
  background: rgba(255,255,255,.10);
  border: 1px solid rgba(255,255,255,.14);
  border-radius: 9px; color: #fff; outline: none;
  transition: border-color .15s, background .15s;
}
.lock-card input::placeholder { color: rgba(255,255,255,.5); }
.lock-card input:focus { border-color: var(--accent); background: rgba(255,255,255,.14); }
.lock-card .btn { width: 100%; justify-content: center; }
.lock-error { color: #ff8a8a; font-size: 13px; min-height: 16px; }
.lock-foot { position: fixed; bottom: 22px; font-size: 12px; color: rgba(255,255,255,.55); letter-spacing: .04em; }

/* ---------- top bar ---------- */

#topbar {
  position: fixed; top: 0; left: 0; right: 0; height: var(--bar-h); z-index: 500;
  display: flex; align-items: center; gap: 6px; padding: 0 6px;
  background: rgba(0,0,0,.55);
  backdrop-filter: blur(18px);
  color: #fff; font-size: 13px; font-weight: 600;
  transition: background .25s var(--ease);
}
body.overview #topbar { background: rgba(0,0,0,.28); }
.topbar-item {
  height: 24px; padding: 0 9px; border: 0; border-radius: 8px;
  background: transparent; color: #fff; cursor: pointer;
  display: inline-flex; align-items: center; gap: 7px;
  transition: background .12s;
}
.topbar-item:hover { background: rgba(255,255,255,.14); }
.topbar-item.on { background: rgba(255,255,255,.22); }
#clock { position: absolute; left: 50%; transform: translateX(-50%); gap: 8px; }
#clock .badge { width: 6px; height: 6px; border-radius: 50%; background: var(--accent); }
.topbar-right { margin-left: auto; display: flex; align-items: center; }
.topbar-item .ico { width: 15px; height: 15px; fill: currentColor; }
.topbar-item .chev { width: 11px; height: 11px; opacity: .8; }
.status-load { font-variant-numeric: tabular-nums; font-size: 12px; opacity: .9; min-width: 32px; text-align: right; }
.app-menu .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--accent); }

/* ---------- popovers ---------- */

.popover {
  position: fixed; top: calc(var(--bar-h) + 6px); left: 50%; transform: translateX(-50%);
  z-index: 520;
  background: var(--panel);
  backdrop-filter: blur(30px);
  border: 1px solid var(--line);
  border-radius: 14px;
  box-shadow: var(--shadow);
  padding: 12px;
  animation: popin .16s var(--ease);
}
.popover.right { left: auto; right: 8px; transform: none; }
@keyframes popin { from { opacity: 0; transform: translate(var(--tx, -50%), -8px); } }
.pop-cols { display: flex; gap: 14px; }
.pop-notif { width: 300px; display: flex; flex-direction: column; gap: 8px; }
.pop-head { display: flex; align-items: center; justify-content: space-between; font-size: 13px; font-weight: 700; opacity: .8; }
.notif-list { display: flex; flex-direction: column; gap: 6px; max-height: 320px; overflow: auto; }
.notif {
  background: var(--card); border: 1px solid transparent; border-radius: 10px; padding: 9px 11px;
  font-size: 13px; display: flex; flex-direction: column; gap: 3px;
  transition: border-color .12s, background .12s;
}
.notif:hover { border-color: var(--line-strong); }
.notif b { font-size: 13px; }
.notif span { color: var(--dim); font-size: 12px; }
.empty { color: var(--dimmer); font-size: 13px; text-align: center; padding: 26px 0; }
.pop-cal { width: 250px; }
.cal-head { display: flex; align-items: center; justify-content: space-between; font-weight: 700; font-size: 13px; margin-bottom: 8px; }
.cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; font-size: 12px; }
.cal-grid div { text-align: center; padding: 5px 0; border-radius: 7px; color: var(--dim); }
.cal-grid .dow { font-weight: 700; opacity: .55; }
.cal-grid .day { color: var(--win-fg); }
.cal-grid .today { background: var(--accent); color: var(--accent-fg); font-weight: 700; }
.cal-events { margin-top: 10px; font-size: 12px; color: var(--dim); border-top: 1px solid var(--line); padding-top: 8px; }

.sysmenu { width: 300px; display: flex; flex-direction: column; gap: 12px; }
.sys-row { display: flex; flex-direction: column; gap: 8px; }
.sys-meter { display: flex; align-items: center; gap: 8px; font-size: 12px; }
.sys-meter-label { width: 56px; color: var(--dim); }
.sys-meter .bar { flex: 1; height: 6px; border-radius: 6px; background: var(--btn); overflow: hidden; }
.sys-meter .bar i { display: block; height: 100%; width: 0; background: var(--accent); border-radius: 6px; transition: width .4s var(--ease); }
.sys-meter span { width: 38px; text-align: right; font-variant-numeric: tabular-nums; }
.sys-tiles { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; }
.sys-tiles .tile {
  border: 1px solid transparent; background: var(--btn); border-radius: 12px; cursor: pointer;
  padding: 10px 4px; display: flex; flex-direction: column; align-items: center; gap: 6px;
  font-size: 11px; color: var(--win-fg); transition: background .12s, border-color .12s;
}
.sys-tiles .tile:hover { background: var(--btn-hover); border-color: var(--line-strong); }
.sys-tiles .tile svg { width: 17px; height: 17px; fill: currentColor; }
.sys-list { border-top: 1px solid var(--line); padding-top: 8px; display: flex; flex-direction: column; }
.sys-item {
  text-align: left; padding: 9px 10px; border: 1px solid transparent; border-radius: 9px;
  background: transparent; cursor: pointer; font-size: 13px; transition: background .12s, border-color .12s;
}
.sys-item:hover { background: var(--btn); border-color: var(--line-strong); }
.sys-item.danger:hover { background: rgba(230,45,66,.16); border-color: rgba(230,45,66,.5); color: #ff6b6b; }

/* ---------- windows ---------- */

#windows { position: fixed; inset: var(--pad-top) var(--pad-right) var(--pad-bottom) var(--pad-left); }

.win {
  position: absolute;
  display: flex; flex-direction: column;
  background: var(--win-bg);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  overflow: hidden;
  transform-origin: center center;
  transition: opacity .18s var(--ease), transform .22s var(--ease);
  min-width: 360px; min-height: 220px;
}
.win.opening { animation: winopen .2s var(--ease); }
@keyframes winopen { from { opacity: 0; transform: scale(.94) translateY(10px); } }
.win.closing { opacity: 0; transform: scale(.95); pointer-events: none; }
.win.minimized { opacity: 0; transform: scale(.7) translateY(40vh); pointer-events: none; }
.win.maximized { border-radius: 0; border-color: transparent; }
.win.snapping { transition: all .18s var(--ease); }
.win:not(.active) { box-shadow: 0 12px 30px rgba(0,0,0,.35); }
.win:not(.active) .headerbar { background: var(--hb-bg-inactive); color: var(--dim); }

.headerbar {
  height: var(--hb-h); flex: 0 0 var(--hb-h);
  display: flex; align-items: center; gap: 8px; padding: 0 8px 0 12px;
  background: var(--hb-bg);
  border-bottom: 1px solid var(--line);
  cursor: grab;
}
.headerbar:active { cursor: grabbing; }
.hb-title { font-weight: 700; font-size: 14px; display: flex; flex-direction: column; line-height: 1.15; }
.hb-title small { font-weight: 400; font-size: 11px; color: var(--dim); }
.hb-icon { width: 20px; height: 20px; border-radius: 6px; display: grid; place-items: center; flex: none; }
.hb-icon svg { width: 14px; height: 14px; fill: #fff; }
.hb-spacer { flex: 1; }
.hb-actions { display: flex; align-items: center; gap: 6px; }
.wbtn {
  width: 26px; height: 26px; border-radius: 50%; border: 1px solid transparent;
  background: var(--btn); cursor: pointer; display: grid; place-items: center;
  transition: background .12s, border-color .12s;
}
.wbtn:hover { background: var(--btn-hover); border-color: var(--line-strong); }
.wbtn svg { width: 10px; height: 10px; fill: var(--win-fg); opacity: .85; }
.wbtn.close:hover { background: #e62d42; border-color: #e62d42; }
.wbtn.close:hover svg { fill: #fff; opacity: 1; }
.win-body { flex: 1; min-height: 0; overflow: hidden; position: relative; display: flex; flex-direction: column; }
.win-body > * { min-height: 0; min-width: 0; }

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

#snapHint {
  position: fixed; z-index: 400; border-radius: 14px;
  background: rgba(53,132,228,.28); border: 2px solid var(--accent);
  pointer-events: none; transition: all .12s var(--ease);
}

/* ---------- overview ---------- */

#overview { position: fixed; inset: var(--pad-top) var(--pad-right) var(--pad-bottom) var(--pad-left); z-index: 300; }
body:not(.overview) #overview { display: none; }
body.overview .win { cursor: pointer; }
body.overview .win .headerbar { pointer-events: none; }
body.overview .win .win-body { pointer-events: none; }
body.overview .win.minimized { opacity: 1; pointer-events: auto; }

.ov-search { position: absolute; top: 22px; left: 50%; transform: translateX(-50%); z-index: 3; }
.ov-search input {
  width: 380px; padding: 9px 16px; border-radius: 10px; text-align: center;
  background: rgba(255,255,255,.14); border: 1px solid rgba(255,255,255,.18);
  color: #fff; outline: none; font-size: 14px;
}
.ov-search input::placeholder { color: rgba(255,255,255,.6); }
.ov-search input:focus { border-color: var(--accent); background: rgba(255,255,255,.2); }
.ov-hint { position: absolute; bottom: 118px; left: 0; right: 0; text-align: center; color: rgba(255,255,255,.5); font-size: 12px; }

/* while there is a query the window thumbnails come off screen, the way GNOME swaps the
   window view for results. Leaving them up put a window straight behind the list. */
body.searching #windows { display: none; }
body.searching #ovHint { display: none !important; }

.ov-results {
  position: absolute; top: 78px; left: 50%; transform: translateX(-50%);
  width: 620px; max-height: 60vh; overflow: auto; z-index: 4;
  display: flex; flex-direction: column; gap: 6px;
}
.ov-res {
  display: flex; align-items: center; gap: 12px; padding: 10px 12px;
  background: rgba(30,30,36,.72); border: 1px solid rgba(255,255,255,.12); border-radius: 12px;
  color: #fff; cursor: pointer; text-align: left;
}
.ov-res:hover, .ov-res.sel { background: rgba(255,255,255,.2); border-color: rgba(255,255,255,.35); }
.ov-res .app-ico { width: 34px; height: 34px; border-radius: 9px; }
.ov-res b { font-size: 14px; display: block; }
.ov-res span { font-size: 12px; opacity: .7; }

.ov-grid {
  position: absolute; inset: 78px 60px 130px; z-index: 3;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
  grid-auto-rows: 118px; gap: 12px; align-content: start; overflow: auto; padding: 10px;
}
.ov-app {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 9px;
  border: 1px solid transparent; border-radius: 14px; background: transparent; color: #fff;
  cursor: pointer; padding: 10px; transition: background .12s, border-color .12s;
}
.ov-app:hover { background: rgba(255,255,255,.14); border-color: rgba(255,255,255,.25); }
.ov-app span { font-size: 12px; text-align: center; }

/* ---------- dash ---------- */

#dash {
  position: fixed; left: 50%; bottom: 10px; transform: translateX(-50%);
  z-index: 310; padding: 0;
}
body[data-panel="top"] #dash { bottom: auto; top: calc(var(--bar-h) + 10px); }
body[data-panel="left"] #dash { left: 10px; top: 50%; bottom: auto; transform: translateY(-50%); }
body[data-panel="right"] #dash { left: auto; right: 10px; top: 50%; bottom: auto; transform: translateY(-50%); }
body[data-panel="left"] .dash-inner, body[data-panel="right"] .dash-inner { flex-direction: column; }
body[data-panel="left"] .dash-sep, body[data-panel="right"] .dash-sep { width: 34px; height: 1px; margin: 3px 0; }
body[data-panel="left"] .dash-app:hover { transform: translateX(4px); }
body[data-panel="right"] .dash-app:hover { transform: translateX(-4px); }
body[data-panel="top"] .dash-app:hover { transform: translateY(4px); }
body[data-panel="left"] .dash-app .run { top: 50%; bottom: auto; left: 5px; right: auto; transform: translateY(-50%); width: 3px; height: 38px; }
body[data-panel="right"] .dash-app .run { top: 50%; bottom: auto; left: auto; right: 5px; transform: translateY(-50%); width: 3px; height: 38px; }
body[data-panel="left"] .dash-app.running.multi .run,
body[data-panel="right"] .dash-app.running.multi .run { height: 82%; width: 4px; }
.dash-inner {
  display: flex; align-items: center; gap: 6px; padding: 7px;
  background: rgba(255,255,255,.13);
  border: 1px solid rgba(255,255,255,.16);
  backdrop-filter: blur(24px);
  border-radius: 18px;
  box-shadow: 0 12px 34px rgba(0,0,0,.35);
  transition: transform .2s var(--ease), opacity .2s var(--ease);
}
body:not(.overview) #dash.autohide .dash-inner { transform: translateY(120%); opacity: 0; }
body[data-panel="top"]:not(.overview) #dash.autohide .dash-inner { transform: translateY(-120%); }
body[data-panel="left"]:not(.overview) #dash.autohide .dash-inner { transform: translateX(-130%); }
body[data-panel="right"]:not(.overview) #dash.autohide .dash-inner { transform: translateX(130%); }
body:not(.overview) #dash.autohide:hover .dash-inner { transform: none; opacity: 1; }
#dash.autohide::after { content: ""; position: absolute; left: -40px; right: -40px; bottom: -10px; height: 26px; }

.dash-app {
  position: relative; width: 48px; height: 48px; border-radius: 13px; border: 1px solid transparent;
  /* padding: 0 is load bearing. A button carries the browser's default 1px 6px,
     which leaves a 34px content box for a 38px icon: it cannot centre, so it
     overflows from the left edge and sits two pixels right of the button's
     middle. The indicator is centred on the button, so the two disagreed by
     exactly that much, which is plainly visible under a 6px dot. */
  padding: 0;
  background: transparent; cursor: pointer; display: grid; place-items: center;
  transition: transform .14s var(--ease), background .12s, border-color .12s;
}
.dash-app:hover { background: rgba(255,255,255,.16); border-color: rgba(255,255,255,.3); transform: translateY(-4px); }
.dash-app .app-ico { width: 38px; height: 38px; }
/* An open window used to be a 5px dot, which at a glance is nearly nothing.
   A solid bar the width of the icon reads instantly, and more windows makes it
   fuller rather than merely wider. */
/* The bar belongs to the icon, not the button. Spanning the whole button meant
   it sat below the icon's rounded corner with a gap, reading as a stray line
   floating underneath rather than an indicator attached to anything. */
.dash-app .run {
  position: absolute; bottom: 5px; left: 50%; transform: translateX(-50%);
  width: 38px; height: 3px; border-radius: 2px; background: #fff;
  opacity: 0; transition: opacity .15s, height .15s;
}
.dash-app.running .run { opacity: .95; }
.dash-app.running.multi .run { height: 4px; }
.dash-sep { width: 1px; height: 34px; background: rgba(255,255,255,.22); margin: 0 3px; }
.dash-app.grid-btn .app-ico { background: rgba(255,255,255,.16); }

.app-ico {
  width: 40px; height: 40px; border-radius: 11px; display: grid; place-items: center;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.28), 0 3px 8px rgba(0,0,0,.28);
}
.app-ico svg { width: 60%; height: 60%; fill: #fff; }

/* ---------- toasts, tooltip, context menu ---------- */

#toasts { position: fixed; top: calc(var(--bar-h) + 10px); left: 50%; transform: translateX(-50%); z-index: 700; display: flex; flex-direction: column; gap: 8px; align-items: center; pointer-events: none; }
.toast {
  pointer-events: auto;
  background: var(--panel); backdrop-filter: blur(24px);
  border: 1px solid var(--line-strong); border-radius: 12px;
  padding: 10px 16px; font-size: 13px; box-shadow: var(--shadow);
  display: flex; align-items: center; gap: 10px; max-width: 520px;
  animation: toastin .2s var(--ease);
}
@keyframes toastin { from { opacity: 0; transform: translateY(-14px); } }
.toast.out { opacity: 0; transform: translateY(-10px); transition: all .2s var(--ease); }
.toast .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--accent); flex: none; }
.toast.err .dot { background: #e62d42; }
.toast.ok .dot { background: #3a944a; }

.tooltip {
  position: fixed; z-index: 900; pointer-events: none;
  background: rgba(0,0,0,.86); color: #fff; font-size: 12px;
  padding: 5px 9px; border-radius: 7px; border: 1px solid rgba(255,255,255,.14);
  white-space: nowrap; box-shadow: 0 6px 20px rgba(0,0,0,.4);
}

.ctxmenu {
  position: fixed; z-index: 800; min-width: 210px; padding: 6px;
  background: var(--panel); backdrop-filter: blur(28px);
  border: 1px solid var(--line-strong); border-radius: 12px; box-shadow: var(--shadow);
  animation: popin .12s var(--ease);
}
.ctxmenu button {
  display: flex; align-items: center; gap: 10px; width: 100%; text-align: left;
  padding: 8px 10px; border: 1px solid transparent; border-radius: 8px;
  background: transparent; cursor: pointer; font-size: 13px; color: var(--win-fg);
  transition: background .1s, border-color .1s;
}
.ctxmenu button:hover { background: var(--btn); border-color: var(--line-strong); }
.ctxmenu button.danger:hover { background: rgba(230,45,66,.16); border-color: rgba(230,45,66,.5); color: #ff6b6b; }
.ctxmenu button svg { width: 14px; height: 14px; fill: currentColor; opacity: .8; }
.ctxmenu hr { border: 0; border-top: 1px solid var(--line); margin: 5px 2px; }
.ctxmenu .label { padding: 6px 10px 4px; font-size: 11px; text-transform: uppercase; letter-spacing: .06em; color: var(--dimmer); }

/* ---------- modal ---------- */

.modal-backdrop {
  position: fixed; inset: 0; z-index: 850;
  background: rgba(0,0,0,.45); backdrop-filter: blur(3px);
  display: grid; place-items: center;
  animation: fadein .14s var(--ease);
}
.modal {
  width: 460px; max-width: calc(100vw - 40px); max-height: calc(100vh - 80px); overflow: auto;
  background: var(--win-bg); border: 1px solid var(--line-strong);
  border-radius: 14px; box-shadow: var(--shadow);
  animation: winopen .18s var(--ease);
}
.modal-head { padding: 18px 20px 6px; text-align: center; }
.modal-head h3 { margin: 0 0 6px; font-size: 16px; }
.modal-head p { margin: 0; font-size: 13px; color: var(--dim); line-height: 1.5; }
.modal-body { padding: 12px 20px; display: flex; flex-direction: column; gap: 12px; }
.modal-foot { display: flex; gap: 10px; padding: 14px 20px 18px; }
.modal-foot .btn { flex: 1; justify-content: center; }

/* ---------- buttons and controls ---------- */

.btn {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 7px 13px; border-radius: 9px;
  border: 1px solid var(--line-strong);
  background: var(--btn); color: var(--win-fg);
  font-size: 13px; font-weight: 600; cursor: pointer;
  transition: background .12s, border-color .12s, transform .06s;
}
.btn:hover { background: var(--btn-hover); border-color: var(--dimmer); }
.btn:active { transform: scale(.97); }
.btn[disabled] { opacity: .45; pointer-events: none; }
.btn.suggested { background: var(--accent); border-color: transparent; color: var(--accent-fg); }
.btn.suggested:hover { filter: brightness(1.12); border-color: transparent; }
.btn.destructive { background: #e62d42; border-color: transparent; color: #fff; }
.btn.destructive:hover { filter: brightness(1.12); }
.btn.flat { background: transparent; border-color: transparent; }
.btn.flat:hover { background: var(--btn); border-color: var(--line-strong); }
.btn.tiny { padding: 3px 8px; font-size: 12px; }
.btn svg { width: 14px; height: 14px; fill: currentColor; }
.btn.icon { padding: 7px; }

.field { display: flex; flex-direction: column; gap: 5px; }
.field label { font-size: 12px; font-weight: 600; color: var(--dim); }
.input, select.input, textarea.input {
  width: 100%; padding: 8px 11px; border-radius: 9px;
  background: var(--sunken); border: 1px solid var(--line-strong);
  color: var(--win-fg); outline: none; transition: border-color .12s;
  user-select: text;
}
.input:focus { border-color: var(--accent); box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 28%, transparent); }
textarea.input { resize: vertical; min-height: 70px; font-family: var(--mono); font-size: 12px; }

.switch { position: relative; width: 44px; height: 25px; flex: none; }
.switch input { opacity: 0; width: 100%; height: 100%; margin: 0; cursor: pointer; }
.switch i {
  position: absolute; inset: 0; border-radius: 20px; background: var(--btn);
  border: 1px solid var(--line-strong); pointer-events: none; transition: background .18s var(--ease);
}
.switch i::after {
  content: ""; position: absolute; top: 2px; left: 2px; width: 19px; height: 19px;
  border-radius: 50%; background: #fff; box-shadow: 0 1px 3px rgba(0,0,0,.4);
  transition: transform .18s var(--ease);
}
.switch input:checked + i { background: var(--accent); border-color: transparent; }
.switch input:checked + i::after { transform: translateX(19px); }

.seg { display: inline-flex; background: var(--btn); border: 1px solid var(--line-strong); border-radius: 9px; padding: 2px; gap: 2px; }
.seg button { border: 0; background: transparent; color: var(--dim); padding: 5px 11px; border-radius: 7px; cursor: pointer; font-size: 12px; font-weight: 600; }
.seg button.on { background: var(--card-hi); color: var(--win-fg); box-shadow: 0 1px 3px rgba(0,0,0,.2); }

/* ---- deployments: tray button and its popover ---- */
.topbar-item.deploy { position: relative; }
.topbar-item.deploy .ico { width: 15px; height: 15px; fill: currentColor; }
/* Only the live count animates. A finished list should sit still. */
.topbar-item.deploy.busy .ico { animation: deploy-pulse 1.4s ease-in-out infinite; }
@keyframes deploy-pulse { 0%,100% { opacity: 1 } 50% { opacity: .45 } }
.deploy-count {
  margin-left: 5px; min-width: 16px; height: 16px; padding: 0 4px; border-radius: 8px;
  background: var(--accent); color: #fff; font-size: 11px; font-weight: 700;
  display: inline-flex; align-items: center; justify-content: center;
}

#deployPop { width: 360px; max-width: calc(100vw - 24px); }
#deployPop .pop-head {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 10px 12px; border-bottom: 1px solid var(--line);
}
.deploy-list { max-height: 340px; overflow: auto; }
.deploy-row {
  display: flex; align-items: flex-start; gap: 10px; padding: 10px 12px;
  border-bottom: 1px solid var(--line);
}
.deploy-row:last-child { border-bottom: 0; }
.deploy-row .main { flex: 1; min-width: 0; }
.deploy-row .title { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.deploy-row .sub { color: var(--dim); font-size: 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.deploy-row .sub.err { color: #e62d42; white-space: normal; }
.deploy-meta { text-align: right; font-size: 12px; flex: none; }
.deploy-dot { width: 8px; height: 8px; border-radius: 50%; margin-top: 5px; flex: none; background: var(--dim); }
.deploy-row.pulling .deploy-dot, .deploy-row.starting .deploy-dot { background: #e5a50a; }
.deploy-row.running .deploy-dot { background: #3a944a; }
.deploy-row.failed .deploy-dot { background: #e62d42; }
.deploy-bar { margin-top: 6px; height: 3px; border-radius: 2px; background: var(--sunken, rgba(128,128,128,.25)); overflow: hidden; }
.deploy-bar i { display: block; height: 100%; background: var(--accent); transition: width .25s; }

/* Show Applications is a full screen app grid, and the desktop icons showing
   through it are a second, competing set of launchers saying the same thing.
   Faded rather than hidden so the desktop does not visibly jump. */
body.overview #desktop-icons { opacity: 0; pointer-events: none; transition: opacity .18s var(--ease); }
#desktop-icons { transition: opacity .18s var(--ease); }

/* Show Applications draws the app grid over the live desktop, so an open window
   sat behind it fully sharp and the grid's labels landed on top of window
   content. Push the windows back: blurred, dimmed and desaturated, so the grid
   is the only thing in focus. They stay clickable, which is the point of the
   overview, they just stop competing for attention. */
body.overview #windows {
  filter: blur(7px) saturate(.7) brightness(.75);
  transition: filter .2s var(--ease);
}
#windows { transition: filter .2s var(--ease); }
/* A window being dragged to a workspace, or hovered, comes back into focus. */
body.overview #windows .win:hover { filter: none; }
/* The grid needs its own footing over that: a scrim so labels always read. */
body.overview #overview { background: rgba(0,0,0,.30); backdrop-filter: blur(3px); }

/* ---------- desktop widgets ---------- */

/* pointer-events: none is load bearing. The wallpaper underneath carries the
   desktop's click and right click handling, so a widget column that swallowed
   events would silently kill the desktop context menu across the whole right
   side of the screen. */
#desktop-widgets {
  position: absolute; top: calc(var(--bar-h) + 18px); right: 22px;
  width: 268px; max-width: calc(100vw - 44px);
  display: flex; flex-direction: column; gap: 14px;
  pointer-events: none; z-index: 2;
  transition: opacity .18s var(--ease);
}
body.overview #desktop-widgets { opacity: 0; }

/* The greeting sits on its own card rather than floating on the wallpaper.
   Light surface with dark text, not the tiles' dark treatment: on a wallpaper
   that happens to be pale, white type with a shadow is unreadable, and a card is
   the only thing that makes the contrast independent of the picture behind it. */
.wg-greet {
  text-align: right;
  background: rgba(255,255,255,.80); backdrop-filter: blur(22px);
  border: 1px solid rgba(255,255,255,.55); border-radius: 14px;
  padding: 12px 14px 13px;
  box-shadow: 0 6px 18px rgba(0,0,0,.28);
}
.wg-hello { font-size: 15px; font-weight: 600; color: #10131a; letter-spacing: .2px; }
.wg-clock { font-size: 42px; font-weight: 300; line-height: 1.05; color: #05070b; font-variant-numeric: tabular-nums; }
.wg-date { font-size: 12.5px; color: rgba(0,0,0,.62); margin-top: 2px; }

.wg-tiles { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }

.wg-tile {
  position: relative; overflow: hidden;
  background: rgba(16,18,24,.58); backdrop-filter: blur(24px) saturate(1.3);
  border: 1px solid rgba(255,255,255,.10); border-radius: 15px;
  padding: 11px 12px 12px; min-width: 0;
  box-shadow: 0 8px 22px rgba(0,0,0,.30), inset 0 1px 0 rgba(255,255,255,.06);
  transition: transform .16s var(--ease), border-color .16s var(--ease), box-shadow .16s var(--ease);
}
/* A hairline of the tile's own colour along the top, so the four are
   distinguishable at a glance rather than after reading their labels. */
.wg-tile::before {
  content: ""; position: absolute; inset: 0 0 auto 0; height: 2px;
  background: linear-gradient(90deg, var(--tint), transparent 78%);
  opacity: .85;
}
/* The column is pointer-events: none, so this only fires when a tile opts back
   in; it never steals the desktop's right click. */
.wg-tile:hover {
  transform: translateY(-1px);
  border-color: rgba(255,255,255,.20);
  box-shadow: 0 12px 28px rgba(0,0,0,.36), inset 0 1px 0 rgba(255,255,255,.08);
}

.wg-top { display: flex; align-items: center; gap: 7px; color: rgba(255,255,255,.66); font-size: 10.5px; letter-spacing: .04em; text-transform: uppercase; font-weight: 600; }
.wg-chip {
  display: grid; place-items: center; width: 24px; height: 24px; flex: none;
  border-radius: 8px;
  background: color-mix(in srgb, var(--tint) 24%, transparent);
  /* A ring of the tile's own colour. Without it the chip reads as a smudge
     behind the glyph rather than as a deliberate badge. */
  border: 1px solid color-mix(in srgb, var(--tint) 55%, transparent);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.10);
}
.wg-chip svg { width: 14px; height: 14px; fill: var(--tint); }
.wg-top span:last-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.wg-val {
  font-size: 23px; font-weight: 650; color: #fff; margin-top: 6px;
  letter-spacing: -.5px; font-variant-numeric: tabular-nums; line-height: 1.1;
}
.wg-sub { font-size: 10.5px; color: rgba(255,255,255,.50); min-height: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* The sparkline sits behind nothing and above nothing: its own row, so a tile
   with one and a tile without still line up. */
.wg-spark { display: block; width: 100%; height: 22px; margin-top: 4px; }

.wg-bar { height: 3px; border-radius: 3px; background: rgba(255,255,255,.13); margin-top: 8px; overflow: hidden; }
.wg-bar i {
  display: block; height: 100%; width: 0; border-radius: 3px;
  background: linear-gradient(90deg, color-mix(in srgb, var(--tint) 70%, white), var(--tint));
  transition: width .45s var(--ease);
}

body[data-theme="light"] .wg-tile { background: rgba(255,255,255,.72); border-color: rgba(0,0,0,.10); }
body[data-theme="light"] .wg-tile:hover { border-color: rgba(0,0,0,.22); }
body[data-theme="light"] .wg-val { color: #10131a; }
body[data-theme="light"] .wg-top { color: rgba(0,0,0,.58); }
body[data-theme="light"] .wg-sub { color: rgba(0,0,0,.5); }
body[data-theme="light"] .wg-bar { background: rgba(0,0,0,.12); }

/* Below this the widgets and the icon grid start fighting for the same space,
   and the icons win: they are the thing you actually click. */
@media (max-width: 900px) { #desktop-widgets { display: none; } }

/* Two column dialog forms.
   A dialog with eight fields stacked one per row is taller than the viewport and
   the buttons end up below the fold, so the form is a grid and only the things
   that genuinely need the width span both columns. */
.form-2col { display: grid; grid-template-columns: 1fr 1fr; gap: 10px 12px; }
.form-2col .wide { grid-column: 1 / -1; }
.form-2col .settings-row { grid-column: 1 / -1; padding: 4px 0; }
.form-2col .hint { grid-column: 1 / -1; margin: 0; font-size: 11.5px; color: var(--dim); line-height: 1.45; }
/* One column when there is not enough room for two, rather than a sideways
   scroll, which is never the answer. */
@media (max-width: 560px) { .form-2col { grid-template-columns: 1fr; } }

/* The spinner a button shows while its action runs. Sized to the button rather
   than to the page so a tiny icon button does not grow while it works. */
.btn-spin {
  display: inline-block; width: 13px; height: 13px; border-radius: 50%;
  border: 2px solid currentColor; border-top-color: transparent;
  animation: btnspin .6s linear infinite; vertical-align: -2px;
}
@keyframes btnspin { to { transform: rotate(360deg); } }
.btn.busy { opacity: .8; cursor: default; }

/* The weather line under the date on the greeting card. */
.wg-weather {
  display: flex; align-items: center; justify-content: flex-end; gap: 6px;
  margin-top: 7px; padding-top: 7px; border-top: 1px solid rgba(0,0,0,.10);
  font-size: 12.5px; color: rgba(0,0,0,.72);
}
.wg-weather b { font-size: 15px; font-weight: 600; color: #10131a; }
.wg-wx-ico {
  display: grid; place-items: center; width: 24px; height: 24px; flex: none;
  border-radius: 8px; border: 1px solid rgba(0,0,0,.14); background: rgba(0,0,0,.05);
}
.wg-wx-ico svg { width: 15px; height: 15px; fill: rgba(0,0,0,.70); }
/* The place name is the only part that can run long, so it is the part that
   truncates rather than pushing the temperature off the card. */
.wg-wx-txt { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
