/* ==========================================================================
   webel.css - Component styles following Radix Themes patterns

   Uses CSS custom properties from the theme system (--gray-1..12, --accent-a3, etc.)
   injected on #shell by the SPA.

   Naming: .wb-{component}.wb-{variant}
   Accent: data-accent="<scale>" (raw Radix scale: accent|gray|red|green|
           amber|orange|blue|cyan|…) OR a semantic role alias
           (warning|danger|error|failure|success|info|debug|trace|
           neutral|primary|start|continue|resume|pause|stop|abort|cancel|
           running|scheduled).
           Roles map to scales in the "Semantic role aliases" block below.
   ========================================================================== */

/* ==========================================================================
   Button group (segmented control)

   Matches the Radix SegmentedControl pattern exactly:
   - Root: --color-surface + gray-a3 overlay (translucent tinted surface)
   - Text: gray-12 (highest contrast)
   - Inactive items: transparent bg, text inherited from root
   - Active item (solid): opaque accent bg with contrast text
   - 1px gray-a4 separators between items
   ========================================================================== */

.wb-btn-group {
  display: inline-flex;
  /* Stay content-width even as a flex item: a flex parent with the
     default align-items:stretch (e.g. a flex column) would otherwise
     stretch the group to full width and show its surface bg as an
     empty grey strip past the last button. fit-content pins it. */
  width: fit-content;
  align-items: stretch;
  border-radius: var(--radius-2);
  background-color: var(--color-surface);
  background-image: linear-gradient(var(--gray-a3), var(--gray-a3));
  color: var(--gray-12);
  overflow: hidden;
}
.wb-btn-group > .wb-btn {
  border-radius: 0;
  flex-shrink: 0;
}
.wb-btn-group > .wb-btn:first-child {
  border-radius: var(--radius-2) 0 0 var(--radius-2);
}
.wb-btn-group > .wb-btn:last-child {
  border-radius: 0 var(--radius-2) var(--radius-2) 0;
}
/* Inactive buttons in group: transparent bg, inherit root text color */
.wb-btn-group > .wb-btn.wb-soft,
.wb-btn-group > .wb-btn.wb-surface,
.wb-btn-group > .wb-btn.wb-outline {
  background-color: transparent;
  color: inherit;
  box-shadow: none;
}
@media (hover: hover) {
  .wb-btn-group > .wb-btn.wb-soft:hover,
  .wb-btn-group > .wb-btn.wb-surface:hover,
  .wb-btn-group > .wb-btn.wb-outline:hover {
    background-color: var(--gray-a2);
  }
}
.wb-btn-group > .wb-btn.wb-soft:active:not([data-disabled]),
.wb-btn-group > .wb-btn.wb-surface:active:not([data-disabled]),
.wb-btn-group > .wb-btn.wb-outline:active:not([data-disabled]) {
  background-color: var(--gray-a3);
}
/* Separators: 1px line between items */
.wb-btn-group > .wb-btn + .wb-btn {
  box-shadow: -1px 0 0 0 var(--gray-a4);
}
/* No separator next to a solid (active) button */
.wb-btn-group > .wb-btn.wb-solid {
  box-shadow: none;
}
.wb-btn-group > .wb-btn.wb-solid + .wb-btn {
  box-shadow: none;
}

/* Icons in tab bars / navigation: no override - FA defaults apply. */

/* ==========================================================================
   Switch (on/off) - role="switch" track + thumb

   The unmistakable boolean affordance: a sliding knob, never confusable
   with a button or a segmented control. Off = gray track, on = accent
   track with the thumb slid right. State is driven entirely by
   aria-checked so the markup stays declarative.
   ========================================================================== */
.wb-switch {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
  border: none;
  background: transparent;
  padding: 4px 2px;
  cursor: pointer;
  color: var(--color-text);
  font: inherit;
  font-size: 12px;
  user-select: none;
}
.wb-switch-track {
  position: relative;
  flex-shrink: 0;
  width: 34px;
  height: 18px;
  border-radius: 9px;
  background-color: var(--gray-a7);
  transition: background-color 120ms ease;
}
.wb-switch[aria-checked="true"] .wb-switch-track {
  background-color: var(--accent-9);
}
.wb-switch-thumb {
  position: absolute;
  top: 2px;
  left: 2px;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background-color: var(--accent-contrast);
  box-shadow: 0 1px 2px var(--black-a6, rgba(0, 0, 0, 0.25));
  transition: transform 120ms ease;
}
.wb-switch[aria-checked="true"] .wb-switch-thumb {
  transform: translateX(16px);
}
.wb-switch:focus-visible {
  outline: 2px solid var(--accent-a8);
  outline-offset: 2px;
  border-radius: 4px;
}

/* ==========================================================================
   Switch button - a normal button (.wb-btn) with an always-on switch
   element (ui.switch_button, ui.icon_switch_button). The body carries accent/grey (solid/soft) like any button;
   the indicator slides on aria-pressed so the control reads as stateful,
   never as a plain button. Indicator uses currentColor so it stays
   visible on both the solid (accent) and soft (grey) body.
   ========================================================================== */
.wb-switch-btn {
  gap: 6px;
  /* Indicator sits on the right (after the label), so tighten the right
     padding and keep the default left padding before the label
     (.wb-btn is 5px 9px). */
  padding-right: 6px;
}
.wb-sw-ind {
  position: relative;
  display: inline-block;
  box-sizing: border-box;
  width: 22px;
  height: 12px;
  border: 1px solid currentColor;
  border-radius: 6px;
  flex-shrink: 0;
  opacity: 0.85;
}
.wb-sw-ind::after {
  content: "";
  position: absolute;
  top: 1px;
  left: 1px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background-color: currentColor;
  transition: transform 120ms ease;
}
.wb-switch-btn[aria-pressed="true"] .wb-sw-ind::after {
  transform: translateX(10px);
}


/* ==========================================================================
   Container pill (ui.pill_group, ui.pill_group_label) - pills that belong
   together in one rounded gray group, its words muted among them. Not
   filled, the group stands bare.
   ========================================================================== */
.wb-pill-group {
  font-size: calc(12px * var(--wb-font-scale, 1));
  display: inline-flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px;
  /* A little room inside, more at the end, where a toggle sits. */
  padding: 3px 7px 3px 5px;
  border-radius: 15px;
}
.wb-pill-group.wb-filled {
  background: var(--gray-5);
}
.wb-pill-group-label {
  padding: 0 4px;
  color: var(--color-text-muted);
  font-size: 11px;
}
.wb-pill-group > .wb-pill-group-label:first-child {
  padding-left: 8px;
}
.wb-pill-group[data-dnd-item] {
  cursor: grab;
}
.wb-pill-group[data-dnd-over] {
  background: var(--gray-5);
}
button.wb-pill-group-word.wb-pill-group-word {
  padding: 0 4px;
  border: 0;
  border-radius: 4px;
  background: none;
  color: var(--color-text-muted);
  font: inherit;
  line-height: 1.5;
  cursor: pointer;
}
button.wb-pill-group-word.wb-pill-group-word:hover {
  background: var(--gray-a4);
}



/* ==========================================================================
   Arrow strip (ui.arrow_strip) - steps in one band [1 > 2 > 3]: flat at
   both ends, each step's point nested in the next one's notch. Gray; the
   current step (aria-current) in the accent. Compact: small, for a
   header (the datagrid's tree levels). A doubled class lifts the rules
   over a container's own button rules.
   ========================================================================== */
.wb-arrows {
  --wb-arrow-tip: 7px;
  display: inline-flex;
  flex: none;
  font-size: calc(12px * var(--wb-font-scale, 1));
  line-height: 22px;
}
.wb-arrows.wb-arrows-compact {
  --wb-arrow-tip: 5px;
  font-size: 10px;
  line-height: 16px;
}
.wb-arrow.wb-arrow {
  min-width: 1.8em;
  margin: 0 0 0 calc(2px - var(--wb-arrow-tip));
  padding: 0 calc(var(--wb-arrow-tip) + 3px) 0 calc(var(--wb-arrow-tip) + 4px);
  border: 0;
  border-radius: 0;
  background: var(--gray-a4);
  color: var(--gray-11);
  font: inherit;
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
  clip-path: polygon(0 0, calc(100% - var(--wb-arrow-tip)) 0, 100% 50%,
    calc(100% - var(--wb-arrow-tip)) 100%, 0 100%, var(--wb-arrow-tip) 50%);
}
.wb-arrow.wb-arrow:first-child {
  margin-left: 0;
  padding-left: 7px;
  clip-path: polygon(0 0, calc(100% - var(--wb-arrow-tip)) 0, 100% 50%,
    calc(100% - var(--wb-arrow-tip)) 100%, 0 100%);
}
.wb-arrow.wb-arrow:last-child {
  padding-right: 7px;
  clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%, var(--wb-arrow-tip) 50%);
}
.wb-arrow.wb-arrow:first-child:last-child {
  clip-path: none;
}
.wb-arrows-compact > .wb-arrow.wb-arrow:first-child {
  padding-left: 5px;
}
.wb-arrows-compact > .wb-arrow.wb-arrow:last-child {
  padding-right: 5px;
}
.wb-arrow.wb-arrow:hover {
  background: var(--accent-a5);
  color: var(--accent-11);
}
.wb-arrow.wb-arrow[aria-current] {
  background: var(--accent-a6);
  color: var(--accent-12);
}
.wb-arrow.wb-arrow:active {
  background: var(--accent-9);
  color: var(--accent-contrast);
}
.wb-arrow.wb-arrow:focus-visible {
  outline: none;
  background: var(--accent-a7);
}


/* ==========================================================================
   Pill (ui.pill, ui.toggle_pill) - a thing that stands for something (a
   column, a sort key, a condition): rounded, in its accent (data-accent,
   else the theme's), wrapping when its chips do not fit. Off: dashed and
   gray (tinted when it has an accent of its own); faded: there, without
   effect just now. A doubled class lifts the rules over a container's own
   button and input rules.
   ========================================================================== */
.wb-pill.wb-pill {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px;
  padding: 2px 10px;
  border: 1px solid var(--_a7, var(--accent-a7));
  border-radius: 12px;
  background: var(--_3, var(--accent-3));
  color: var(--_12, var(--accent-12));
  font: inherit;
  /* One size wherever a pill stands, as the fields have. */
  font-size: calc(12px * var(--wb-font-scale, 1));
  line-height: 1.5;
  white-space: nowrap;
  user-select: none;
}
.wb-pill.wb-pill:hover {
  background: var(--_a4, var(--accent-a4));
}
/* Solid: the accent's full colour - a pill that must never be read as one
   of the soft pills in the same colour. */
.wb-pill.wb-pill.wb-solid {
  border-color: transparent;
  background: var(--_9, var(--accent-9));
  color: var(--_contrast, var(--accent-contrast, #fff));
}
.wb-pill.wb-pill.wb-solid:hover {
  background: var(--_10, var(--accent-10));
}
/* Compact (ui.pill_compact): smaller, for many pills in columns. */
.wb-pill.wb-pill.wb-compact {
  padding: 1px 6px;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  justify-content: center;
  box-sizing: border-box;
}
/* Marked (ui.pill_marked): a ring inside the pill, the success green - the
   one just moved, say; inside, so it never grows onto its neighbours. */
.wb-pill.wb-pill.wb-marked {
  box-shadow: inset 0 0 0 2px var(--green-9);
}
/* Chips at its end: the pill hugs them. */
.wb-pill.wb-pill:has(> .wb-chip-button:last-child, > .wb-menu-pop:last-child, > .wb-chip-toggle:last-child) {
  padding-right: 4px;
}
.wb-pill.wb-pill[data-dnd-item] {
  cursor: grab;
}
button.wb-pill.wb-pill {
  cursor: pointer;
}
.wb-pill.wb-pill:focus-visible {
  outline: 2px solid var(--_a8, var(--accent-a8));
  outline-offset: 1px;
}
.wb-pill.wb-pill.wb-off {
  border-style: dashed;
  border-color: var(--gray-7);
  background: var(--gray-2);
  color: var(--color-text-muted);
}
.wb-pill.wb-pill.wb-off[data-accent] {
  border-color: var(--_a6);
  background: var(--_2);
  color: var(--_11);
}
.wb-pill.wb-pill.wb-off:hover {
  background: var(--gray-3);
}
.wb-pill.wb-pill.wb-faded {
  opacity: 0.45;
}

/* ==========================================================================
   Words beside the controls: a hint (ui.hint) where something can go, a
   note (ui.note) on what is there, a word joining groups (ui.join_word).
   ========================================================================== */
.wb-hint {
  color: var(--color-text-muted);
  font-size: calc(12px * var(--wb-font-scale, 1));
  font-style: italic;
}
.wb-note {
  color: var(--color-text-muted);
  font-size: 11px;
}
.wb-join-word {
  color: var(--color-text-muted);
  font-size: 11px;
  font-weight: bold;
}

/* ==========================================================================
   Popover (ui.popover) below its anchor, and the values to tick in it
   (ui.check_list, ui.check_row).
   ========================================================================== */
.wb-popover {
  font-size: calc(12px * var(--wb-font-scale, 1));
  position: absolute;
  left: 0;
  top: 100%;
  margin-top: 4px;
  z-index: 30;
  width: 240px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 6px;
  background: var(--color-panel-solid, var(--gray-1));
  color: var(--color-text);
  border: 1px solid var(--color-border);
  border-radius: 6px;
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.18);
  white-space: normal;
  cursor: default;
}
.wb-check-list {
  max-height: 200px;
  overflow: auto;
  border: 1px solid var(--gray-a5);
  border-radius: 4px;
  padding: 2px 0;
}
.wb-check-row {
  display: flex;
  gap: 6px;
  align-items: center;
  padding: 1px 6px;
  cursor: pointer;
}
.wb-check-row:hover {
  background: var(--gray-a3);
}
.wb-check-label {
  flex: 1 1 auto;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.wb-check-count {
  color: var(--color-text-muted);
  font-size: 10px;
}


/* ==========================================================================
   Chip button (ui.chip_button) and chip input (ui.chip_input) - a small
   button or field INSIDE a pill: the button bare, in the pill's accent (or
   its own data-accent); the field on a small rounded light surface.
   ========================================================================== */
button.wb-chip-button.wb-chip-button {
  /* A long text (the values picked) is cut, not the row widened. */
  max-width: 14em;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  padding: 0 4px;
  border: 0;
  border-radius: 4px;
  background: none;
  color: var(--_11, var(--accent-11));
  font: inherit;
  line-height: 1.5;
  cursor: pointer;
}
button.wb-chip-button.wb-chip-button:hover:not(:disabled) {
  background: var(--gray-a4);
}
button.wb-chip-button.wb-chip-button:disabled {
  color: var(--gray-a8);
  cursor: default;
}
button.wb-chip-button .fa-duotone {
  --fa-primary-color: currentColor;
  --fa-secondary-color: currentColor;
}
input.wb-chip-input.wb-chip-input {
  padding: 0 6px;
  border: 0;
  border-radius: 999px;
  background: var(--color-panel-solid, var(--gray-1));
  color: var(--color-text);
  font: inherit;
  font-size: 11px;
  line-height: 1.6;
  min-width: 0;
}


/* ==========================================================================
   Chip toggle button (ui.chip_toggle_button) - a toggle INSIDE a pill,
   inline like the choices there ("alle", "Monat"): no border, a small
   rounded light surface; its content light gray when off, the accent when
   on. `[aria-pressed]` lifts it over a container's own button rules.
   ========================================================================== */
button.wb-chip-toggle[aria-pressed] {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  /* Narrow around an icon, as high as the chip select beside it. */
  padding: 0 4px;
  min-width: 1.8em;
  min-height: 1.6em;
  box-sizing: border-box;
  border: 0;
  /* A button's corners, not a pill's. */
  border-radius: 5px;
  background: var(--color-panel-solid, var(--gray-1));
  color: var(--gray-10);
  font: inherit;
  font-size: 11px;
  line-height: 1.6;
  cursor: pointer;
}
button.wb-chip-toggle[aria-pressed="true"] {
  /* The pill's own accent (a dimension's colour), else the theme's. */
  color: var(--_11, var(--accent-11));
}

/* ==========================================================================
   Chip select (ui.chip_select) - a select INSIDE a pill, inline like the
   pill's words: no border, a small rounded light surface, the pill's
   accent. Pill select (ui.pill_select) - the same IN a container pill,
   beside its pills: their height, a button's corners, the accent's
   surface. Both open a small menu below them (.wb-menu), as does
   ui.action_menu with actions instead of choices.
   `[aria-haspopup]` lifts them over a container's own button rules.
   ========================================================================== */
.wb-menu-pop {
  position: relative;
  display: inline-flex;
}
button.wb-chip-select[aria-haspopup] {
  padding: 0 8px;
  border: 0;
  /* A button's corners, not a pill's - no border, as the chips. */
  border-radius: 5px;
  background: var(--color-panel-solid, var(--gray-1));
  color: var(--_11, var(--accent-11));
  font: inherit;
  font-size: 11px;
  line-height: 1.6;
  cursor: pointer;
}
button.wb-chip-select[aria-haspopup]:hover {
  background: var(--gray-a3);
}
button.wb-pill-select[aria-haspopup] {
  padding: 2px 8px;
  box-sizing: border-box;
  min-height: calc(1.5em + 6px);
  border: 1px solid var(--_a7, var(--accent-a7));
  border-radius: 6px;
  background: var(--_3, var(--accent-3));
  color: var(--_12, var(--accent-12));
  font: inherit;
  font-size: calc(12px * var(--wb-font-scale, 1));
  line-height: 1.5;
  cursor: pointer;
}
button.wb-pill-select[aria-haspopup]:hover {
  background: var(--_a4, var(--accent-a4));
}
.wb-menu {
  position: absolute;
  max-height: 320px;
  overflow-y: auto;
  top: 100%;
  left: 0;
  margin-top: 4px;
  z-index: 30;
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding: 4px;
  min-width: 10em;
  background: var(--color-panel-solid, var(--gray-1));
  border: 1px solid var(--color-border);
  border-radius: 6px;
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.18);
}
.wb-menu > button[role^="menuitem"] {
  padding: 3px 8px;
  border: 0;
  border-radius: 4px;
  background: none;
  color: var(--color-text);
  font: inherit;
  text-align: left;
  white-space: nowrap;
  cursor: pointer;
}
.wb-menu > button[role^="menuitem"]:hover {
  background: var(--gray-a4);
}
/* icon_action_menu: an icon before each label, all in one column. A
   split item (MenuSplit): the usual choice across the row, a second, small
   one at its right end. */
.wb-menu > button[role^="menuitem"] > .wb-menu-icon,
.wb-menu-split > button[role^="menuitem"] > .wb-menu-icon {
  display: inline-block;
  width: 1.5em;
  color: var(--color-text-muted);
}
/* MenuItemDanger: icon and label in the item's role (red). */
.wb-menu > button[role^="menuitem"][data-accent],
.wb-menu > button[role^="menuitem"][data-accent] > .wb-menu-icon {
  color: var(--_11);
}
.wb-menu > button[role^="menuitem"][data-accent]:hover {
  background: var(--_a4);
}
.wb-menu > .wb-menu-split {
  display: flex;
  gap: 2px;
}
.wb-menu-split > button[role^="menuitem"] {
  padding: 3px 8px;
  border: 0;
  border-radius: 4px;
  background: none;
  color: var(--color-text);
  font: inherit;
  text-align: left;
  white-space: nowrap;
  cursor: pointer;
  flex: 1 1 auto;
}
.wb-menu-split > button.wb-menu-other {
  flex: 0 0 auto;
  font-size: 0.85em;
  color: var(--color-text-muted);
}
.wb-menu-split > button[role^="menuitem"]:hover {
  background: var(--gray-a4);
}
/* MenuIcons: a row of icon-only buttons, the label their tooltip; one
   that is so already shows pressed. */
.wb-menu > .wb-menu-icons {
  display: flex;
  gap: 2px;
}
.wb-menu-icons > button[role^="menuitem"] {
  flex: 1 1 0;
  padding: 4px 6px;
  border: 0;
  border-radius: 4px;
  background: none;
  color: var(--color-text);
  font: inherit;
  cursor: pointer;
}
.wb-menu-icons > button[role^="menuitem"]:hover:not(:disabled) {
  background: var(--gray-a4);
}
.wb-menu-icons > button[aria-pressed="true"] {
  background: var(--accent-a4);
  color: var(--accent-11);
  cursor: default;
}
/* MenuIconDanger: the icon in its role's colour (red), hover in its tint. */
.wb-menu-icons > button[data-accent] {
  color: var(--_11);
}
.wb-menu-icons > button[data-accent]:hover:not(:disabled) {
  background: var(--_a4);
}
/* MenuSeparator: a line between two groups of items. */
.wb-menu > .wb-menu-sep {
  border: 0;
  border-top: 1px solid var(--color-border);
  margin: 3px 4px;
}
.wb-menu > button[aria-checked="true"] {
  background: var(--accent-a4);
  color: var(--accent-11);
}
button.wb-chip-toggle[aria-pressed]:hover {
  background: var(--gray-a3);
}
button.wb-chip-toggle[aria-pressed]:focus-visible {
  outline: 2px solid var(--_a8);
  outline-offset: 1px;
}
button.wb-chip-toggle .fa-duotone {
  --fa-primary-color: currentColor;
  --fa-secondary-color: currentColor;
}


/* ==========================================================================
   Pill toggle button (ui.pill_toggle_button) - a toggle INSIDE a container
   pill (a gray group of pills), rounded like the pills beside it: on, in
   the accent like a pill; off, gray - border, icon, and a surface lighter
   than the container's.
   `[aria-pressed]` lifts it over a container's own button rules.
   ========================================================================== */
button.wb-pill-toggle[aria-pressed] {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  /* The height of the pills beside it, but a button's corners: a modifier,
     not one of the pills. */
  padding: 2px 8px;
  /* An icon alone is no line of text: as high as one anyway. */
  box-sizing: border-box;
  min-height: calc(1.5em + 6px);
  border: 1px solid var(--gray-7);
  border-radius: 6px;
  background: var(--gray-3);
  color: var(--gray-9);
  font: inherit;
  font-size: calc(12px * var(--wb-font-scale, 1));
  line-height: 1.5;
  cursor: pointer;
}
button.wb-pill-toggle[aria-pressed="true"] {
  border-color: var(--_a7);
  background: var(--_3);
  color: var(--_11);
}
button.wb-pill-toggle[aria-pressed]:hover {
  background: var(--gray-4);
}
button.wb-pill-toggle[aria-pressed="true"]:hover {
  background: var(--_a4);
}
button.wb-pill-toggle[aria-pressed]:focus-visible {
  outline: 2px solid var(--_a8);
  outline-offset: 1px;
}
button.wb-pill-toggle .fa-duotone {
  --fa-primary-color: currentColor;
  --fa-secondary-color: currentColor;
}

/* ==========================================================================
   Badges

   Variants:
     soft  - tinted background, colored text, subtle border (Radix "soft")
     solid - filled background, contrast text
   ========================================================================== */

.wb-badge {
  display: inline-flex;
  align-items: center;
  padding: 2px 8px;
  border-radius: 9999px;
  font-size: 10px;
  font-weight: 500;
  white-space: nowrap;
}

.wb-badge.wb-soft {
  background-color: var(--_a3);
  color: var(--_a11);
  box-shadow: inset 0 0 0 1px var(--_a6);
}

.wb-badge.wb-solid {
  background-color: var(--_9);
  color: var(--_contrast);
}

/* ==========================================================================
   Panels (sidebar, toolbar)
   ========================================================================== */

.wb-panel {
  background-color: var(--color-panel);
  box-shadow: inset 0 0 0 1px var(--gray-a6);
  border-radius: var(--radius-3);
  padding: 12px;
}

/* ==========================================================================
   Status indicator (dot + label)
   ========================================================================== */

.wb-status {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--color-text-muted);
}
.wb-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background-color: var(--_9);
  flex-shrink: 0;
}

/* ==========================================================================
   Tabs (ui.tabs / ui.tab_panel)

   The WAI-ARIA tab navigation: tabs that read as tabs, not buttons - and as
   the shell's own pane tabs (`view_state_tab` in webux_spa): side by side
   on the darker tab-bar ground, the selected one in the view's ground
   (white in a light theme) with the accent line under it.
   ========================================================================== */

/* The bar: a fixed height, one line, never a scrollbar. <webco-tab-overflow>
   (webel `spa.tab_overflow`) hides the tabs that do not fit
   (`data-overflow`) and shows the chevron (`data-overflowing` on the bar),
   whose menu lists them (`data-open`). The underline is on the bar, so it
   runs under the chevron too, and the selected tab's underline is drawn
   INSIDE the tab (an inset shadow) - nothing reaches past the height. */
.wb-tabs-bar {
  position: relative;
  display: flex;
  align-items: stretch;
  height: calc(40px * var(--wb-font-scale, 1));
  background: var(--color-tab-bar);
  box-shadow: inset 0 -1px 0 var(--color-border);
  flex-shrink: 0;
}
/* `position: relative` makes the list the tabs' offsetParent, which the
   element measures them against. */
.wb-tabs {
  position: relative;
  display: flex;
  align-items: stretch;
  gap: 0;
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
}
.wb-tab {
  display: inline-flex;
  align-items: center;
  padding: 0 14px;
  border: none;
  background: none;
  font-family: inherit;
  font-size: calc(13px * var(--wb-font-scale, 1));
  font-weight: 500;
  color: var(--gray-11);
  cursor: pointer;
  white-space: nowrap;
  flex-shrink: 0;
  transition: color 80ms, box-shadow 80ms, background-color 80ms;
}
.wb-tab[data-overflow] { display: none; }
@media (hover: hover) {
  .wb-tab:hover { color: var(--color-text); background-color: var(--gray-a3); }
}
.wb-tab[aria-selected="true"] {
  color: var(--color-text);
  background-color: var(--color-background);
  box-shadow: inset 0 -2px 0 var(--accent-9);
}
.wb-tab:focus-visible {
  outline: 2px solid var(--color-focus-ring);
  outline-offset: -2px;
  border-radius: var(--radius-2);
}

/* The chevron with the count of hidden tabs, at the bar's right end. */
.wb-tabs-more {
  display: none;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
  padding: 0 10px;
  border: none;
  background: none;
  font-family: inherit;
  font-size: calc(12px * var(--wb-font-scale, 1));
  font-weight: 500;
  color: var(--gray-11);
  cursor: pointer;
}
.wb-tabs-bar[data-overflowing] .wb-tabs-more { display: inline-flex; }
@media (hover: hover) {
  .wb-tabs-more:hover { color: var(--color-text); background-color: var(--gray-a3); }
}
.wb-tabs-more[aria-expanded="true"] {
  color: var(--color-text);
  background-color: var(--gray-a3);
}
.wb-tabs-more:focus-visible {
  outline: 2px solid var(--color-focus-ring);
  outline-offset: -2px;
  border-radius: var(--radius-2);
}

/* The menu of hidden tabs, under the chevron, right-aligned to the bar. */
.wb-tabs-menu {
  display: none;
  position: absolute;
  top: calc(100% + 2px);
  right: 0;
  z-index: 30;
  flex-direction: column;
  min-width: 180px;
  max-width: min(360px, 100%);
  max-height: 320px;
  overflow-y: auto;
  padding: 2px 0;
  /* The view's own ground (white in a light theme), not the accent-tinted
     --color-panel-solid. */
  background: var(--color-background);
  box-shadow: inset 0 0 0 1px var(--gray-a6), 0 4px 12px rgba(0, 0, 0, 0.15);
  border-radius: var(--radius-2, 4px);
}
.wb-tabs-menu:focus { outline: none; }
.wb-tabs-bar[data-open] .wb-tabs-menu { display: flex; }
.wb-tabs-menu-item {
  display: block;
  width: 100%;
  padding: 6px 12px;
  border: none;
  font-family: inherit;
  font-size: calc(13px * var(--wb-font-scale, 1));
  color: var(--color-text);
  text-align: left;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* The focused row is THE highlighted row - never a second one for the
   pointer: the element moves the focus to the row under the pointer, and a
   menu opened by a click focuses the menu itself, not its first row. */
.wb-tabs-menu-item { background: transparent; cursor: pointer; }
.wb-tabs-menu-item:focus { outline: none; background: var(--gray-4); }


/* ==========================================================================
   Empty state
   ========================================================================== */

.wb-empty {
  padding: 20px;
  text-align: center;
  color: var(--color-text-sub);
  font-size: 12px;
}

/* ==========================================================================
   Scrollbars - Radix-inspired thin scrollbars

   Uses standard scrollbar-width/scrollbar-color (Firefox) and
   ::-webkit-scrollbar (Chrome, Safari, Edge) for cross-browser support.
   Track is transparent, thumb uses gray-a8 with hover at gray-a9.
   ========================================================================== */

/* Firefox / standard */
#shell,
#shell * {
  scrollbar-width: thin;
  scrollbar-color: var(--gray-a8) transparent;
}

/* Webkit (Chrome, Safari, Edge) */
#shell ::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}
#shell ::-webkit-scrollbar-track {
  background: transparent;
}
#shell ::-webkit-scrollbar-thumb {
  background-color: var(--gray-a8);
  border-radius: 9999px;
  border: 2px solid transparent;
  background-clip: content-box;
}
@media (hover: hover) {
  #shell ::-webkit-scrollbar-thumb:hover {
    background-color: var(--gray-a9);
  }
}
#shell ::-webkit-scrollbar-corner {
  background: transparent;
}

/* ==========================================================================
   Tab close button - larger hit area with hover feedback
   ========================================================================== */

.tab-close:hover {
  background: var(--gray-a4);
  color: var(--color-text);
}

/* ==========================================================================
   VTab sidebar icons - button-style selection + hover
   ========================================================================== */

.vtab-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  cursor: pointer;
  font-size: 16px;
}

.vtab-icon-inner {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: var(--radius-2);
  background: transparent;
  transition: background 80ms, color 80ms;
}

/* Disable pointer events on all descendants of .vtab-icon so that
   dragover always lands on .vtab-icon itself (40x40). That way
   `event.offsetY` is measured against the outer box and the
   threshold test in `pin_dnd_attrs` is reliable - otherwise the
   inner FontAwesome glyph (~16x16) would be hit first and offsetY
   would be relative to *that*, throwing the threshold off. Clicks
   still bubble to .vtab-icon's handler. */
.vtab-icon * {
  pointer-events: none;
}

/* Vtab icons read from the abstract `--theme-*` scale so the
   accent/gray switch happens at the radix-tokens.css definition
   point - no separate `[data-icon-color="gray"]` overrides
   needed. */
.vtab-icon:hover .vtab-icon-inner {
  background: var(--theme-a4);
}

.vtab-active .vtab-icon-inner {
  background: var(--theme-a3);
}

.vtab-active:hover .vtab-icon-inner {
  background: var(--theme-a5);
}

/* Pressed: one step darker than hover, so a click is felt. */
.vtab-icon:active .vtab-icon-inner,
.vtab-active:active .vtab-icon-inner {
  background: var(--theme-a6);
}

/* Launcher rows and section heads (`view_accordion_item`,
   `view_accordion_section`): hover and press feedback. Their background
   is set inline (an open section, the item surface), which no class can
   override, so the tint is an inset shadow laid OVER that background -
   under the content, and keeping the base colour underneath.
   `.launcher-press-part` is a separately clickable zone inside a row
   (the drag icon, the favourite toggle): it tints once more on its own. */
.launcher-press,
.launcher-press-part {
  transition: box-shadow 80ms;
}
.launcher-press:hover {
  box-shadow: inset 0 0 0 999px var(--theme-a3);
}
.launcher-press:active {
  box-shadow: inset 0 0 0 999px var(--theme-a5);
}
.launcher-press-part:hover {
  box-shadow: inset 0 0 0 999px var(--theme-a3);
}
.launcher-press-part:active {
  box-shadow: inset 0 0 0 999px var(--theme-a5);
}
#shell[data-dragging="true"] .launcher-press:hover,
#shell[data-dragging="true"] .launcher-press-part:hover {
  box-shadow: none;
}

/* During pin/launcher drag, suppress hover styling on vtab icons.
   The collapsed source pulls the next icon under the cursor, which
   would then light up as a hover target without the user having
   actually pointed at it. Keep the active-tab background but drop
   the hover bump. */
#shell[data-dragging="true"] .vtab-icon:not(.vtab-active):hover .vtab-icon-inner {
  background: transparent;
}
#shell[data-dragging="true"] .vtab-active:hover .vtab-icon-inner {
  background: var(--theme-a3);
}

/* Drop placeholder visual (the wandering rectangle that occupies the
   slot where the dragged icon would land). Geometry mirrors
   .vtab-icon-inner. Background is tone-tuned per appearance: alpha
   tints look brighter on dark surfaces than on light ones, so dark
   mode uses a lower alpha step to keep the placeholder visually
   subtle in both modes. Tone follows the abstract `--theme-*`
   scale (= icon-colour switch); the surface-colour override
   below additionally degrades a fully-gray surface to gray
   placeholders even when icon-colour is still set to accent. */
.drag-placeholder-inner {
  width: 28px;
  height: 28px;
  border-radius: var(--radius-2);
  background: var(--theme-a6);
}
#shell.dark .drag-placeholder-inner {
  background: var(--theme-a4);
}
#shell[data-surface-color="gray"] .drag-placeholder-inner {
  background: var(--gray-a6);
}
#shell.dark[data-surface-color="gray"] .drag-placeholder-inner {
  background: var(--gray-a4);
}

/* Theme editor radius preview tiles. They depict a surface, so the
   tone follows surface-color only - a gray-icons-on-accent-surfaces
   theme should still show accent-tinted preview boxes. */
.radius-preview {
  width: 44px;
  height: 44px;
  background: var(--accent-a3);
}
#shell[data-surface-color="gray"] .radius-preview {
  background: var(--gray-a3);
}


/* ==========================================================================
   Log viewer - dense rows for the log cell
   ========================================================================== */

.wb-log-list {
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  flex: 1;
  font-family: var(--font-family-mono, ui-monospace, monospace);
  font-size: 12px;
  line-height: 1.4;
}

.wb-log-row {
  /* Block row with inline-block columns so copy&paste keeps the whole entry on
     ONE line. `display: flex` would blockify each span, and the browser's
     HTML->plaintext copy then inserts a newline between block boxes - which is
     why time / level / cell / message used to paste on separate lines. */
  display: block;
  padding: 0 12px;
  color: var(--color-text);
}

.wb-log-row:nth-child(odd) {
  background-color: var(--gray-a2);
}

/* A log viewer is for READING: everything is normal text color; the
   only tint is the level tag (colored per severity, set inline by the
   cell) - never dimmed-to-gray content. */
.wb-log-row > .wb-log-time,
.wb-log-row > .wb-log-level,
.wb-log-row > .wb-log-cell {
  display: inline-block;
  margin-right: 8px;
  vertical-align: baseline;
}

.wb-log-row > .wb-log-level {
  font-weight: 600;
  min-width: 44px;
}

.wb-log-row > .wb-log-cell {
  min-width: 80px;
}

.wb-log-row > .wb-log-msg {
  /* Inline so it flows after the columns and WRAPS on long lines (soft wraps
     add no newline to a copied line). */
  white-space: pre-wrap;
  word-break: break-word;
}

/* Invisible focus target at the bottom of the list. The cell focuses this
   element to scroll the latest entry into view; outline is suppressed so the
   focus ring never shows. */
.wb-log-anchor {
  height: 1px;
  outline: none;
  scroll-margin-block-end: 0;
}

/* ==========================================================================
   Multi-select dropdown panel
   ========================================================================== */

.wb-multi-dropdown-panel {
  background: var(--color-panel-solid, var(--gray-1));
  box-shadow: inset 0 0 0 1px var(--gray-a6), 0 4px 12px rgba(0, 0, 0, 0.15);
  border-radius: var(--radius-2, 4px);
  min-width: 180px;
  max-height: 320px;
  overflow-y: auto;
  font-size: 12px;
  padding: 2px 0;
}

.wb-multi-dropdown-row {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 2px 8px;
  min-height: 24px;
  user-select: none;
}

@media (hover: hover) {
  .wb-multi-dropdown-row:hover {
    background-color: var(--accent-a2);
  }
}

.wb-multi-dropdown-all {
  cursor: pointer;
  font-weight: 600;
  border-bottom: 1px solid var(--gray-a4);
  margin-bottom: 2px;
}

.wb-multi-dropdown-check {
  display: inline-block;
  width: 14px;
  text-align: center;
  font-weight: 700;
  color: var(--accent-11);
}

.wb-multi-dropdown-check-area {
  cursor: pointer;
  padding: 0 2px;
}

.wb-multi-dropdown-label {
  flex: 1;
  cursor: pointer;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.wb-multi-dropdown-only {
  cursor: pointer;
  font-size: 10px;
  font-weight: 600;
  padding: 2px 6px;
  border: 1px solid var(--gray-a6);
  border-radius: var(--radius-1, 3px);
  background: transparent;
  color: var(--accent-11);
  text-transform: uppercase;
  letter-spacing: 0.5px;
}
@media (hover: hover) {
  .wb-multi-dropdown-only:hover {
    background-color: var(--accent-a3);
  }
}

/* ==========================================================================
   Error banner
   ========================================================================== */

.wb-error-banner {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  background-color: var(--red-a3);
  color: var(--red-a11);
  font-size: 12px;
  flex-shrink: 0;
}

/* ==========================================================================
   wb-menu-item - Floating-menu rows (hover highlight)

   Used by dropdown menus (workspace pill menu, presets menu, etc.).
   Default background stays transparent so the menu container's own
   surface colour shines through. Hover/active mark the row with a
   gray overlay. Pair with `data-active="true"` to render a row in
   selected state (e.g. the currently-active preset).
   ========================================================================== */

.wb-menu-item {
  background: transparent;
  cursor: pointer;
  transition: background 80ms ease;
}
.wb-menu-item:hover {
  background: var(--gray-4);
}
.wb-menu-item[data-active="true"] {
  background: var(--gray-a4);
  font-weight: 600;
}
.wb-menu-item[data-active="true"]:hover {
  background: var(--gray-a5);
}

/* ==========================================================================
   Board blink - brief tint over the whole Board to draw attention.

   Triggered by `blink_board` in the FFI when a pin/launcher click
   activates a view that's already open. The user otherwise just sees
   a focus indicator move; this animation washes the destination
   Board with a soft accent-coloured veil so it's easy to spot.

   Rendered via a `::after` pseudo-element so the Board's own layout
   and event handling stay untouched. `pointer-events: none` keeps the
   tab content interactive throughout. `position: relative` is the
   minimum needed to make the pseudo-element use the Board as its
   containing block; it's a no-op for flex children otherwise.

   The animation fades in to ~accent-a5, holds briefly, fades back to
   transparent over ~600ms. The class is removed by the FFI shortly
   after, so the next blink restarts cleanly.
   ========================================================================== */

@keyframes wb-board-blink {
  0%   { background: transparent; }
  35%  { background: var(--accent-a5); }
  70%  { background: var(--accent-a5); }
  100% { background: transparent; }
}
.wb-board-blink {
  position: relative;
}
.wb-board-blink::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 100;
  background: transparent;
  border-radius: inherit;
  animation: wb-board-blink 400ms ease-in-out;
}

/* A launcher entry or pin held down long enough to pull its view into
   this workspace (`setup_launcher_long_press`): a short accent wash on
   the entry itself, so the hold is felt before the view arrives. */
.launch-held {
  animation: wb-board-blink 400ms ease-in-out;
}
