Download
159 lines 4.9 KiBCSSModified 2026-10-14 raw
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
/* Base bar styling. Widget-specific styles live in each widget module
   and are injected by the registry, so this file only styles the shell. */

:root {
  /* Set at runtime by main.js from the bar config (height / padding);
     these are fallbacks. Everything below scales from --chip-height,
     which is bar height minus vertical padding. */
  --bar-height: 48px;
  --bar-pad-x: 10px;
  --bar-pad-y: 6px;
  --chip-height: 36px;
  --chip-radius: 18px;
  --bar-font: 20px;
  --icon-size: 32px;
  --bar-bg: rgba(16, 18, 24, 0.92);
  /* Subtle vertical gradient: faintly lifted at the top, settling darker
     at the bottom edge. */
  --bar-bg-top: rgba(25, 28, 36, 0.93);
  --bar-bg-mid: rgba(16, 18, 24, 0.92);
  --bar-bg-bottom: rgba(13, 15, 20, 0.93);
  --bar-fg: #8f96a5;
  --bar-fg-dim: #626a79;
  --accent: #7aa2f7;
  --warn: #e0af68;
  --critical: #f7768e;
  --chip-bg: rgba(255, 255, 255, 0.06);
  --chip-bg-hover: rgba(255, 255, 255, 0.12);
  --font: "Inter", "Cantarell", system-ui, sans-serif;
  --font-mono: "JetBrains Mono", "Fira Code", monospace;
}

/* Without a compositor, alpha renders against black — use opaque colors. */
:root.no-compositor {
  --bar-bg: rgb(18, 20, 26);
  --bar-bg-top: rgb(25, 28, 36);
  --bar-bg-mid: rgb(16, 18, 24);
  --bar-bg-bottom: rgb(13, 15, 20);
}

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  user-select: none;
}

html,
body {
  height: 100%;
  overflow: hidden;
  background: transparent;
}

/* One flex row: every widget sizes to its content; anything that should
   absorb spare space (window-title by default) sets flex-grow itself. */
#bar {
  height: var(--bar-height);
  display: flex;
  align-items: center;
  gap: 4px;
  padding: var(--bar-pad-y) var(--bar-pad-x);
  background: linear-gradient(
    180deg,
    var(--bar-bg-top) 0%,
    var(--bar-bg-mid) 55%,
    var(--bar-bg-bottom) 100%
  );
  border-bottom: 1px solid rgba(255, 255, 255, 0.07);
  /* Hairline highlight along the top edge sells the gradient. */
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04);
  color: var(--bar-fg);
  font-family: var(--font);
  font-size: var(--bar-font);
}

/* Shared look for widgets that opt into the "chip" class */
.chip {
  display: flex;
  align-items: center;
  gap: 5px;
  height: var(--chip-height);
  padding: 0 calc(var(--chip-height) * 0.22);
  border-radius: var(--chip-radius);
  white-space: nowrap;
  transition: background 120ms ease;
}

/* Only interactive chips (marked .clickable) show a hover background. */
.chip.clickable:hover {
  background: var(--chip-bg-hover);
}

/* Fitts's law: every clickable element keeps its visual padding but gets
   an invisible overlay (its ::after) that spans the full bar height and
   meets its neighbours halfway across the gap, so there are no dead zones.
   The overlay is a child of the element, so clicks, hover and tooltips all
   land on the element itself; z-index -1 (inside the element's own
   stacking context) keeps it beneath any real content the element has.

   Clickable chips get this automatically. Buttons nested inside a widget
   opt in with the `hit-target` class, and the widget describes its
   geometry through variables:
     --hit-inset-x / --hit-inset-y  distance from the button to the
                                    widget's outer edge (default 0)
     --hit-gap-x                    half the gap between siblings
                                    (default 2px: half the #bar gap) */
#bar .chip.clickable,
#bar .hit-target {
  position: relative;
  isolation: isolate;
}
#bar .chip.clickable::after,
#bar .hit-target::after {
  content: "";
  position: absolute;
  z-index: -1;
  top: calc(-1 * (var(--bar-pad-y) + var(--hit-inset-y, 0px)));
  bottom: calc(-1 * (var(--bar-pad-y) + var(--hit-inset-y, 0px)));
  left: calc(-1 * var(--hit-gap-x, 2px));
  right: calc(-1 * var(--hit-gap-x, 2px));
}
/* The outermost nested buttons also cover their widget's padding and
   half the #bar gap beyond it. */
#bar .hit-target:first-child::after {
  left: calc(-1 * (var(--hit-inset-x, 0px) + 2px));
}
#bar .hit-target:last-child::after {
  right: calc(-1 * (var(--hit-inset-x, 0px) + 2px));
}
/* At either end of the bar the hitbox runs through the bar padding to the
   window edge, so the screen edge and corners themselves are clickable. */
#bar > :first-child.chip.clickable::after,
#bar > :first-child .hit-target:first-child::after {
  left: calc(-1 * (var(--bar-pad-x) + var(--hit-inset-x, 0px)));
}
#bar > :last-child.chip.clickable::after,
#bar > :last-child .hit-target:last-child::after {
  right: calc(-1 * (var(--bar-pad-x) + var(--hit-inset-x, 0px)));
}

.chip .icon {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--bar-font);
  line-height: 1;
}

.chip .icon svg {
  display: block;
  width: var(--icon-size);
  height: var(--icon-size);
}

.chip .value {
  font-family: var(--font-mono);
  font-size: var(--bar-font);
  font-variant-numeric: tabular-nums;
}