/* Sidebar */
:root {
  --sidebar-inline-space: max(calc(var(--inline-space) * 1.5), 1vw);
}

.sidebar__container {
  block-size: 100dvh;
  display: flex;
  flex-direction: column;
  max-block-size: 100dvh;
  position: relative;
}

.sidebar__close.sidebar__close {
  display: none;

  #sidebar.open & {
    @media (max-width: 1279.9px) {
      display: flex;
      position: absolute;
      inset-block-start: var(--block-space-half);
      inset-inline-end: var(--sidebar-inline-space);
      z-index: 4;
    }
  }
}

/* The sidebar is a size container, so what is inside it answers to how wide it
   actually is rather than to how wide the window is.

   It used to answer to the window: the rail's contents were bounded to
   834-1279px, the range where the docked sidebar happens to be 60px. That was
   true for chat and only for chat. The wiki folds the sidebar to the same 60px
   at widths outside that range — it spends a column on its own index — and
   under a media query the fold gave a 60px column still rendering the expanded
   design, clipped. Nothing about "the labels do not fit" was ever about the
   viewport; it was always about this element. */
#sidebar {
  container: sidebar / inline-size;
}

/* Rail (a 60px column, closed): icon-only tool column; the room sections wait
   inside the expanded overlay. The threshold sits well below every wide state —
   the docked column is 272px, the expanded overlay 264px, and the drawer 300px
   or 85vw, which is 238px on the narrowest phone worth naming. */
@container sidebar (max-width: 200px) {
  #sidebar:not(.open) {
    .sidebar__container {
      overflow: hidden;
    }

    .sidebar__workspace {
      justify-content: center;
      padding: 12px 0 var(--block-space-half);
    }

    .sidebar__workspace-info,
    .sidebar__workspace-action {
      display: none;
    }

    .sidebar__menu {
      /* clear the rail's pinned expand button */
      padding-block-start: calc(
        var(--block-space-half) + var(--btn-size) + var(--block-space-half)
      );
      padding-inline: 6px;
    }

    .sidebar__menu-item {
      /* Icon-only in the rail, so the glyph carries the row on its own: size it
       * to the design's 18px rather than the 14px it inherits from the label it
       * sits beside when the sidebar is expanded. */
      --btn-padding: var(--space-row) 0;
      --icon-size: 18px;

      justify-content: center;

      &.has-unread-activity::after,
      &.has-unread-dms::after {
        inset-block-start: 4px;
        inset-inline-end: 6px;
        transform: none;
      }
    }

    .sidebar__menu-label,
    .sidebar__menu-kbd {
      display: none;
    }

    /* The full room sections wait inside the expanded overlay, but the top of
       the main Rooms list previews here as compact glyph rows so unread rooms
       stay one glance away. Favorites, forums, DMs, section headers and row
       menus all collapse; the rows themselves are reused, so their live unread
       badges keep updating. */
    .rooms {
      gap: 2px;
      padding-inline: 6px;
    }

    /* Only the main Rooms list previews in the rail. Its list now lives inside
       the collapsible #rooms_section, so keep that wrapper and drop its header;
       favorites, forums, DMs and the hidden frame stay culled. */
    .rooms > *:not(#rooms_section) {
      display: none;
    }

    #rooms_section > *:not([data-collapsible-section-target="content"]) {
      display: none;
    }

    .rail-rooms .room-row:nth-child(n + 5),
    .rail-rooms .room-row .room-row__menu-btn,
    .rail-rooms .room__name,
    .rail-rooms .muted-indicator {
      display: none;
    }

    .rail-rooms .room {
      --btn-padding: var(--space-row) 0;

      justify-content: center;
      position: relative;
    }

    .rail-rooms .notification-badge {
      position: absolute;
      inset-block-start: 2px;
      inset-inline-end: 4px;
    }

    .sidebar__footer {
      align-items: center;
      flex-direction: column;
      padding-inline: 6px;
    }

    /* The chip collapses to just the avatar in the rail */
    .sidebar__profile {
      flex: initial;
    }

    .sidebar__me {
      padding: 4px;
    }

    .sidebar__me-info,
    .sidebar__me-caret {
      display: none;
    }
  }
}

/* Workspace header: identity chip above the tool rows — logo tile, name over
   member counts, quiet settings gear */
.sidebar__workspace {
  align-items: center;
  color: var(--color-text);
  display: flex;
  gap: 10px;
  padding: 16px 14px 12px;

  /* The drawer/overlay close button pins to the same corner — slide the
     gear clear of it while the sidebar is open below the docked breakpoint */
  #sidebar.open & {
    @media (max-width: 1279.9px) {
      padding-inline-end: calc(var(--btn-size) + var(--sidebar-inline-space));
    }
  }
}

body.room-header--pencil .sidebar__workspace {
  padding-block: 13px 14px;
}

.sidebar__workspace-logo {
  block-size: 32px;
  border-radius: 9px;
  display: block;
  flex-shrink: 0;
  inline-size: 32px;
  overflow: hidden;

  & img {
    block-size: 100%;
    display: block;
    inline-size: 100%;
    object-fit: cover;
  }
}

.sidebar__workspace-initial {
  align-items: center;
  background-color: var(--color-accent-brand);
  block-size: 100%;
  color: var(--color-text-reversed);
  display: flex;
  font-size: 0.875rem;
  font-weight: 700;
  justify-content: center;
  text-transform: uppercase;
}

.sidebar__workspace-info {
  display: flex;
  flex: 1;
  flex-direction: column;
  min-inline-size: 0;
}

.sidebar__workspace-name {
  /* Handoff: 15px / 700 / -0.01em (Sabha v2.1 Sidebar) */
  font-size: 0.9375rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 1.25;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sidebar__workspace-sub {
  color: var(--color-text-muted);
  display: block;
  font-size: 0.71875rem;
  line-height: 1.3;
  overflow: hidden;
  text-decoration: none;
  text-overflow: ellipsis;
  white-space: nowrap;

  &:hover,
  &:focus-visible {
    color: var(--color-text);
  }
}

/* Tool block: full-width rows above the room sections */
.sidebar__menu {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding-block: calc(var(--block-space) + env(safe-area-inset-top))
    var(--block-space-half);
  padding-inline: calc(var(--sidebar-inline-space) / 2);
}

.sidebar__menu-item {
  --btn-background: transparent;
  --btn-border-color: transparent;
  --btn-border-radius: var(--border-radius-md);
  /* Tool rows sit tighter than room rows (comp: 34px vs 40px) */
  --btn-padding: 7px 1.2ch;
  --hover-color: transparent;
  --hover-filter: none;

  color: var(--color-text-muted);
  display: flex;
  font-size: 0.875rem;
  gap: 1.2ch;
  justify-content: flex-start;
  position: relative;
  transition: background-color 150ms ease-out;

  /* Comp: hover tints the row, the label color holds */
  @media (hover: hover) and (pointer: fine) {
    &:hover {
      background-color: var(--color-bg-side-hover);
    }
  }

  &:focus-visible {
    outline: 2px solid var(--color-accent-brand);
  }

  &.has-unread-activity::after,
  &.has-unread-dms::after {
    --size: 0.6em;

    aspect-ratio: 1;
    background-color: var(--color-accent-brand);
    block-size: var(--size);
    border-radius: calc(var(--size) * 2);
    content: "";
    flex-shrink: 0;
    inline-size: var(--size);
    position: absolute;
    inset-block-start: 50%;
    inset-inline-end: 1.2ch;
    transform: translateY(-50%);
  }
}

.sidebar__menu-label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Row count riding each section label */
.sidebar__label-count {
  color: var(--color-text-muted);
  font-size: 0.6875rem;
  font-weight: 400;
  font-variant-numeric: tabular-nums;

  &::before {
    content: "("
  }

  &::after {
    content: ")"
  }
}

/* Presence on 1:1 DM rows: the roster's connected signal as a corner dot */
.direct__avatar {
  overflow: visible;
  position: relative;
}

.direct__presence {
  border: 2px solid var(--color-bg-side);
  block-size: 10px;
  inline-size: 10px;
  inset-block-end: -1px;
  inset-inline-end: -1px;
  position: absolute;
}

/* Shortcut hint on the Search row — only where a keyboard is likely */
.sidebar__menu-kbd {
  border: 1.5px solid var(--color-border-subtle);
  border-radius: 5px;
  color: var(--color-text-subtle);
  background-color: var(--color-bg-raised);
  display: none;
  font-family: inherit;
  font-size: 0.6875rem;
  margin-inline-start: auto;
  padding: 1px 5px;

  @media (hover: hover) and (pointer: fine) {
    display: inline-block;
  }
}

/* Chrome buttons (section add/menu, drawer close) sit quietly on the
   sidebar surface instead of as solid pills */
.sidebar__container .btn--small,
.sidebar__container .options-btn,
.sidebar__close.sidebar__close {
  --btn-background: transparent;
  --btn-border-color: transparent;
  --hover-color: transparent;
  --hover-filter: none;

  color: var(--color-text-muted);

  @media (hover: hover) and (pointer: fine) {
    &:hover {
      background-color: var(--color-bg-side-hover);
      color: var(--color-text);
    }
  }
}

.sidebar__container .options-btn {
  @media (hover: hover) and (pointer: fine) {
    &:hover {
      background-color: transparent;
      color: var(--color-text);
    }
  }
}

/* Section labels */
.sidebar__label {
  color: var(--color-text-muted);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.07em;
}

/* Fixed 20px glyph column so #, lock, and forum glyphs all align the names
   at the same x (comp) */
.room__glyph {
  color: var(--color-text-subtle);
  display: inline-flex;
  inline-size: 20px;
  justify-content: center;
  margin-inline-end: 11px;
}

/* Footer: the signed-in user chip is the one trigger for the profile flyout. */
.sidebar__footer {
  align-items: center;
  background-color: var(--color-bg-side);
  border-block-start: 1px solid var(--color-border-side);
  display: flex;
  inset-block-end: 0;
  margin-block-start: auto;
  padding-block: 8px calc(8px + env(safe-area-inset-bottom));
  padding-inline: calc(var(--sidebar-inline-space) / 2);
  position: sticky;
  z-index: 2;
}

.sidebar__profile {
  flex: 1;
  min-inline-size: 0;
}

.sidebar__me {
  align-items: center;
  border-radius: var(--border-radius-md);
  color: var(--color-text);
  cursor: pointer;
  display: flex;
  gap: 10px;
  inline-size: 100%;
  min-inline-size: 0;
  padding: 4px 6px;
  text-align: start;

  /* A <button>, so the base reset would ring it with a hover box-shadow the
     sidebar's <a> room rows never get. Drop it for a matching flat fill. */
  --hover-size: 0;
  --hover-filter: none;

  &[aria-expanded="true"] {
    background-color: var(--color-bg-side-hover);
  }

  &:focus-visible {
    outline: 2px solid var(--color-accent-brand);
    outline-offset: 2px;
  }

  @media (hover: hover) and (pointer: fine) {
    &:hover {
      background-color: var(--color-bg-side-hover);
    }
  }
}

.sidebar__me-avatar {
  flex-shrink: 0;
  position: relative;
}

.sidebar__me-dot {
  block-size: 10px;
  border: 2px solid var(--color-bg-side);
  inline-size: 10px;
  inset-block-end: -2px;
  inset-inline-end: -2px;
  position: absolute;
  z-index: 1;
}

/* Presence picker inside the profile flyout (v2.1 account menu): a PRESENCE
   heading, then three options — one always selected. The selected row reads at
   weight 600 with an accent check. The swatches are deliberately their own
   class rather than .status-dot: this row shows what you chose, never how you
   resolve to everyone else, so it must not inherit a surface's dot sizing. */
.sidebar__presence {
  margin: 0;
}

.sidebar__presence-heading {
  color: var(--color-text-subtle);
  font-size: 0.65625rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  padding: 7px 10px 4px;
  text-transform: uppercase;
}

/* A <label> wrapping a visually-hidden native radio: the dot, word, and check
   are the visible control, while the radio still owns focus and keyboard. */
.sidebar__presence-option {
  align-items: center;
  border-radius: 8px;
  color: var(--color-text);
  cursor: pointer;
  display: flex;
  font-size: 0.84375rem;
  gap: 10px;
  min-block-size: 32px;
  padding: 0 10px;

  @media (hover: hover) and (pointer: fine) {
    &:hover {
      background-color: var(--color-bg-hover);
    }
  }

  /* Focus rides the label, since the radio itself is off-screen. */
  &:has(.sidebar__presence-radio:focus-visible) {
    outline: 2px solid var(--color-accent-brand);
    outline-offset: 2px;
  }

  &:has(.sidebar__presence-radio:checked) {
    font-weight: 600;

    .sidebar__presence-check {
      display: inline;
    }
  }
}

/* Off-screen, not display:none, so it stays focusable and in the radiogroup. */
.sidebar__presence-radio {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

.sidebar__presence-dot {
  block-size: 8px;
  border-radius: 50%;
  flex-shrink: 0;
  inline-size: 8px;
}

.sidebar__presence-dot--available {
  background-color: var(--color-positive);
}

.sidebar__presence-dot--away {
  background-color: var(--color-alert);
}

.sidebar__presence-dot--do_not_disturb {
  background-color: var(--color-negative);
}

.sidebar__presence-dot--invisible {
  background-color: transparent;
  box-shadow: inset 0 0 0 1.5px var(--color-border-darker);
}

.sidebar__presence-check {
  color: var(--color-accent-brand);
  display: none;
  font-size: 0.75rem;
  margin-inline-start: auto;
}

.sidebar__me-info {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-inline-size: 0;
}

.sidebar__me-name {
  font-size: 0.84375rem;
  font-weight: 600;
  line-height: 1.25;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sidebar__me-status {
  color: var(--color-text-subtle);
  font-size: 0.71875rem;
  line-height: 1.3;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sidebar__me-caret {
  color: var(--color-text-subtle);
  display: flex;
  flex-shrink: 0;
  transform: rotate(180deg);

  & svg {
    block-size: 12px;
    inline-size: 12px;
  }
}

.sidebar__workspace-action {
  --btn-background: transparent;
  --btn-border-color: transparent;
  --btn-padding: 0.35em;
  --btn-size: 32px;
  --hover-color: transparent;
  --hover-filter: none;
  --icon-size: 18px;

  color: var(--color-text-muted);

  @media (hover: hover) and (pointer: fine) {
    &:hover {
      background-color: var(--color-bg-side-hover);
      color: var(--color-text);
    }
  }
}

.sidebar__toggle {
  /* Vertically centered on the header bar it floats over */
  inset-block-start: calc((var(--navbar-height) - var(--btn-size)) / 2);
  inset-inline-end: calc(
    (var(--btn-size) + max(var(--inline-space), 1vw)) * -1
  );
  position: absolute;
  transition:
    inset-inline-end 300ms cubic-bezier(0.25, 1, 0.5, 1),
    border-color 300ms cubic-bezier(0.25, 1, 0.5, 1),
    background-color 300ms cubic-bezier(0.25, 1, 0.5, 1);
  z-index: 5;

  #sidebar:where(
      :not(.open):has(
        :is(#shared_rooms, #starred_rooms, #forum_rooms) > .room-row:not([hidden]) .room.unread,
        #direct_rooms .direct.unread:not([hidden])
      )
    )
    & {
    &::after {
      --size: 1em;

      aspect-ratio: 1;
      background-color: var(--color-text);
      block-size: var(--size);
      border-radius: calc(var(--size) * 2);
      content: "";
      flex-shrink: 0;
      inline-size: var(--size);
      inset-block-start: calc(var(--size) / -4);
      inset-inline-end: calc(var(--size) / -4);
      position: absolute;
    }
  }

  #sidebar:where(:not(.open):has(.badge, .direct.unread)) & {
    &::after {
      background-color: var(--color-negative);
    }
  }

  /* Drawer breakpoint: the toggle floats out over the light content header,
     not the dark rail (an open drawer hides it — the close X takes over). It
     lives inside #sidebar[data-contrast], whose scope repaints --color-text
     white; over the header that's an invisible glyph and dot on a white circle.
     Rebind --color-text to the page's own ink (theme-aware, and read by both the
     icon's currentColor and the unread ::after) and drop the button chrome so it
     reads as a borderless header glyph. */
  @media (max-width: 833.9px) {
    --btn-background: transparent;
    --btn-border-color: transparent;
    --color-text: oklch(var(--lch-ink));
    /* Same page-surface rebind for the hover pill, so it matches the rail's
       hover treatment below rather than the default glyph-darken. */
    --color-bg-hover: oklch(var(--lch-hover));

    @media (hover: hover) and (pointer: fine) {
      &:hover {
        background-color: var(--color-bg-hover);
      }
    }
  }

  /* Pinned in the rail, wherever the rail is. Above the drawer breakpoint the
     sidebar is docked in the grid, so how the button behaves follows the
     column's width and not the window's. */
  @media (min-width: 834px) {
    @container sidebar (max-width: 200px) {
      --btn-background: transparent;
      --btn-border-color: transparent;
      --hover-color: transparent;
      --hover-filter: none;

      color: var(--color-text-muted);
      display: flex;
      inset-block-start: calc(12px + 32px + var(--block-space-half));
      inset-inline: 0;
      margin-inline: auto;
      position: absolute;

      @media (hover: hover) and (pointer: fine) {
        &:hover {
          background-color: var(--color-bg-side-hover);
          color: var(--color-text);
        }
      }
    }

    /* A column already showing its labels has nothing to expand. Kept inside
       the drawer breakpoint, because below it this same button is the drawer's
       toggle and the drawer is wide. */
    @container sidebar (min-width: 200.01px) {
      display: none;
      inset-block-start: var(--block-space);
    }
  }

  .open & {
    inset-block-start: var(--block-space);

    @media (max-width: 1279.9px) {
      display: none;
      inset-inline-end: var(--sidebar-inline-space);

      & img {
        filter: invert(0);
      }

      @media (prefers-color-scheme: dark) {
        & img {
          filter: invert(100%);
        }
      }

      :root[data-theme="light"] & img {
        filter: invert(0);
      }

      :root[data-theme="dark"] & img {
        filter: invert(100%);
      }
    }
  }
}

/* Direct messages */
.directs {
  --column-gap: calc(var(--inline-space) / 1.5);

  display: flex;
  flex-direction: column;
  gap: 2px;
}

.direct {
  --avatar-size: 1.75em;

  align-items: center;
  border-radius: var(--border-radius-md);
  color: var(--color-text-muted);
  display: flex;
  gap: 1ch;
  padding: var(--space-row) 1.2ch;
  position: relative;
  text-decoration: none;
  transition: background-color 150ms ease-out;

  /* The group stack is authored entirely in ch — box, tiles, and overlap
     offsets alike — so scaling its font-size shrinks the whole stack uniformly
     to sit inside the single-avatar footprint instead of overpowering it. */
  .avatar__group {
    font-size: 0.7em;
  }

  .avatar .avatar__group {
    .avatar {
      margin-inline: 0;
    }
  }

  /* Two overlapping tiles for a group DM; the upper tile is ringed in the
     sidebar ground so it reads as a separate avatar over the one behind it. */
  .avatar__group > :last-child .avatar {
    box-shadow: 0 0 0 2px var(--color-bg-side);
  }

  @media (hover: hover) and (pointer: fine) {
    &:where(:not(:active):hover) {
      background-color: var(--color-bg-side-hover);
      color: var(--color-text);
    }
  }

  &:focus-visible {
    outline: 2px solid var(--color-accent-brand);
    outline-offset: 2px;
  }

  &.unread {
    color: var(--color-text);

    &::after {
      --size: 0.6em;

      aspect-ratio: 1;
      background-color: var(--color-accent-brand);
      block-size: var(--size);
      border-radius: calc(var(--size) * 2);
      content: "";
      flex-shrink: 0;
      inline-size: var(--size);
      margin-inline-start: auto;
    }
  }

  /* DM rows reuse the room-row unread badge; it replaces the plain dot */
  .notification-badge {
    background-color: var(--color-accent-brand);
    border-radius: 9px;
    color: var(--color-text-reversed);
    flex-shrink: 0;
    font-size: 0.6875rem;
    font-variant-numeric: tabular-nums;
    font-weight: 700;
    line-height: 1.4;
    margin-inline-start: auto;
    min-inline-size: 1.3em;
    padding: 1px 7px;
    text-align: center;
    animation: badge-in 200ms cubic-bezier(0.25, 1, 0.5, 1) both;

    @media (prefers-reduced-motion: reduce) {
      animation-name: fade-in;
    }
  }

  &.badge.unread::after {
    display: none;
  }
}

.direct__author {
  --column-gap: 0.3ch;

  .unread & {
    font-weight: 700;
  }
}

/* Rooms */
.rooms {
  --column-gap: 0.5em;
  --row-gap: 0.5em;

  /* Comp: a hairline separates the tool block from the room sections */
  border-block-start: 1px solid var(--color-border-side);
  padding-top: var(--block-space-half);
  padding-bottom: var(--block-space-half);
  padding-inline: 8px;

  input {
    margin-bottom: var(--block-space);
    font-size: var(--font-size-small);
  }

  /* Rows stack flush — the 9px row padding is the breathing room (comp) */
  .rooms-list {
    & #shared_rooms {
      display: flex;
      flex-direction: column;
      gap: 0.1rem;
    }
  }
}

/* One collapse control for all sections; headers without adjacent actions
   use the full-width modifier. */
.sidebar__section-toggle {
  all: unset;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 0.35em;
}

.sidebar__section-toggle--full {
  width: 100%;
}

.sidebar__section-icon {
  /* The caret paints with background-color: currentColor. The toggle button
     resets color via `all: unset`, so without this the caret inherits the dark
     ink color and vanishes on the contrast nav — name it like the label. */
  color: var(--color-text-muted);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  transition: transform 150ms cubic-bezier(0.25, 1, 0.5, 1);

  @media (prefers-reduced-motion: reduce) {
    transition: none;
  }

  .icon {
    --icon-size: 0.7em;
    opacity: 0.9;
  }
}

.room-row {
  width: 100%;
  align-items: center;
  border-radius: 8px;
  min-block-size: 32px;
  padding-right: 0.5rem;
  transition: background-color 150ms ease-out;

  /* The whole row — star included — is one hover/current unit (comp) */
  @media (hover: hover) and (pointer: fine) {
    &:hover {
      background-color: var(--color-bg-side-hover);
    }
  }

  &:has(.room[aria-current="page"]) {
    background-color: var(--color-selected);
  }

  /* The ⋯ trigger reveals on row hover/focus and stays while its menu is
     open; right-clicking the row opens the same menu (popover_controller). */
  .room-row__menu-btn {
    --btn-padding: 4px;

    border: 0;
    background: transparent;
    flex-shrink: 0;
    line-height: 1;
    margin-inline-end: 2px;

    @media (hover: hover) and (pointer: fine) {
      opacity: 0;
      transition: opacity 0.15s ease;
    }
  }

  &:hover .room-row__menu-btn,
  &:focus-within .room-row__menu-btn,
  .room-row__menu-btn[aria-expanded="true"] {
    opacity: 1;
  }

  .btn.everything,
  .btn.mentions,
  .btn.nothing,
  .btn.invisible {
    border: 0;
    padding: 0;
    background: transparent;
    flex-shrink: 0;
  }
}

.room {
  --btn-background: transparent;
  --btn-border-color: transparent;
  --btn-border-radius: 8px;
  --btn-padding: var(--space-row) 1.2ch;
  --hover-color: transparent;
  --hover-filter: none;

  color: var(--color-text-muted);
  font-size: 0.875rem;
  font-weight: normal;
  justify-content: start;
  max-inline-size: 100%;
  transition: background-color 150ms ease-out;

  &[aria-current="page"] {
    color: var(--color-accent-brand);
    font-weight: 700;
  }

  /* Unread count rides the accent, not red — red stays destructive-only */
  .notification-badge {
    margin-left: auto;
    flex-shrink: 0;
    background-color: var(--color-accent-brand);
    color: var(--color-text-reversed);
    font-size: 0.6875rem;
    font-variant-numeric: tabular-nums;
    font-weight: 700;
    line-height: 1.4;
    min-width: 1.3em;
    padding: 1px 7px;
    border-radius: 9px;
    text-align: center;
    animation: badge-in 200ms cubic-bezier(0.25, 1, 0.5, 1) both;

    @media (prefers-reduced-motion: reduce) {
      animation-name: fade-in;
    }
  }

  .muted-indicator {
    margin-left: auto;
    flex-shrink: 0;
    opacity: 0.3;
  }

  &.unread {
    color: var(--color-text);
    font-weight: 700;
  }

  &:active:not(:disabled) {
    background-color: var(--color-bg-side-hover);
    transform: none;
    transition: none;
  }
}

#sidebar .options-btn {
  aspect-ratio: 1;
  block-size: 20px;
  border-radius: var(--border-radius-sm);
  inline-size: 20px;
  padding: 0;
}

/* Contrast treatment — a scope, not a theme: rebinds the semantic tokens
   inside the sidebar only, so it reads dark in both light and dark modes.
   Dormant until the shell sets data-contrast on #sidebar, and suppressed when
   the sidebar-skin preference stamps data-sidebar="match" on <html> — then the
   sidebar drops the scope and inherits the page theme. */
html:not([data-sidebar="match"]) #sidebar[data-contrast="true"] {
  --color-bg: var(--color-sidebar-contrast-bg);
  --color-bg-raised: var(--color-sidebar-contrast-bg-raised);
  --color-bg-sunk: var(--color-sidebar-contrast-bg);
  --color-bg-side: var(--color-sidebar-contrast-bg);
  --color-bg-side-hover: var(--color-sidebar-contrast-bg-hover);
  --color-border-side: var(--color-sidebar-contrast-border);
  --color-bg-hover: var(--color-sidebar-contrast-bg-hover);
  --color-text: var(--color-sidebar-contrast-text);
  --color-text-lighter: var(--color-sidebar-contrast-text-lighter);
  --color-text-muted: var(--color-sidebar-contrast-text-muted);
  --color-text-subtle: var(--color-sidebar-contrast-text-subtle);
  --color-border-dark: var(--color-sidebar-contrast-border);
  --color-selected: oklch(100% 0 0 / 0.1);
  /* The workspace accent, lifted for the dark ground (colors.css sets the
     per-accent lift on :root). */
  --color-accent-brand: oklch(var(--lch-accent-lift));
}

/* Scrollbar: the global rule (base.css) sets `scrollbar-color` explicitly on
   every element via `*`, so a value only inherited from the sidebar root loses
   the cascade on the real scroll container (.sidebar__container). Target the
   scope's descendants directly to beat `*` — a hue-neutral translucent white
   that recedes into the dark rail in both modes. Width stays thin (inherited). */
html:not([data-sidebar="match"]) #sidebar[data-contrast="true"] * {
  scrollbar-color: oklch(100% 0 0 / 0.2) transparent;
}

/* Anchored popovers (row ⋯ menu, profile flyout) render in the top layer but
   inherit custom properties from their DOM home inside the contrast sidebar,
   which would paint them dark. They are page-surface menus, so rebind the
   tokens the contrast scope overrode back to the theme primitives — white in
   light mode, converging with the sidebar again in dark. */
html:not([data-sidebar="match"])
  #sidebar[data-contrast="true"]
  .anchored-popover {
  --color-bg: var(--color-page-bg);
  --color-bg-raised: var(--color-page-bg-raised);
  --color-bg-sunk: var(--color-page-bg-sunk);
  --color-bg-hover: var(--color-page-bg-hover);
  --color-text: var(--color-page-text);
  --color-text-lighter: var(--color-page-text-lighter);
  --color-text-muted: var(--color-page-text-muted);
  --color-text-subtle: var(--color-page-text-subtle);
  --color-border: var(--color-page-border);
  --color-border-dark: var(--color-page-border-dark);
  --color-selected: var(--color-page-selected);
  --color-accent-brand: var(--color-page-accent-brand);
}

/* Cold-start skeleton for the lazy sidebar frame (users/sidebars/_skeleton).
   Reserve the same four regions as the loaded sidebar so only their contents
   resolve when the frame lands. Theme-agnostic bars use text at low alpha. */
.sidebar-skeleton {
  block-size: 100dvh;
  display: flex;
  flex-direction: column;
  max-block-size: 100dvh;
}

.sidebar-skeleton__footer,
.sidebar-skeleton__row {
  align-items: center;
  display: flex;
  gap: 10px;
}

.sidebar-skeleton__rooms {
  border-block-start: 1px solid var(--color-border-side);
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: var(--block-space-half) 8px;
}

.sidebar-skeleton__row {
  min-block-size: 32px;
  padding-block: 7px;
  padding-inline: 1.2ch;
}

.sidebar-skeleton__avatar,
.sidebar-skeleton__glyph,
.sidebar-skeleton__bar {
  animation: skeleton-pulse 1.4s ease-in-out infinite;
  background: color-mix(in oklch, var(--color-text) 14%, transparent);
  border-radius: 6px;
}

.sidebar-skeleton__avatar {
  block-size: 32px;
  flex-shrink: 0;
  inline-size: 32px;
}

.sidebar-skeleton__glyph {
  block-size: 18px;
  flex-shrink: 0;
  inline-size: 18px;
}

.sidebar-skeleton__bar {
  display: block;
  block-size: 12px;
  inline-size: 60%;
}

.sidebar-skeleton__copy {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: 5px;
}

.sidebar-skeleton__bar--title {
  block-size: 12px;
  inline-size: 44%;
}

.sidebar-skeleton__bar--meta {
  block-size: 8px;
  inline-size: 62%;
}

.sidebar-skeleton__bar--label {
  block-size: 8px;
  inline-size: 28%;
  margin-block: 5px 2px;
  margin-inline: 1.2ch;
}

.sidebar-skeleton__menu .sidebar-skeleton__row:nth-child(2) .sidebar-skeleton__bar,
.sidebar-skeleton__rooms .sidebar-skeleton__row:nth-child(3) .sidebar-skeleton__bar {
  inline-size: 44%;
}

.sidebar-skeleton__menu .sidebar-skeleton__row:nth-child(3) .sidebar-skeleton__bar,
.sidebar-skeleton__rooms .sidebar-skeleton__row:nth-child(4) .sidebar-skeleton__bar {
  inline-size: 68%;
}

.sidebar-skeleton__menu .sidebar-skeleton__row:nth-child(4) .sidebar-skeleton__bar,
.sidebar-skeleton__rooms .sidebar-skeleton__row:nth-child(5) .sidebar-skeleton__bar {
  inline-size: 38%;
}

@container sidebar (max-width: 200px) {
  #sidebar:not(.open) {
    .sidebar-skeleton__bar,
    .sidebar-skeleton__copy {
      display: none;
    }

    .sidebar-skeleton__rooms {
      padding-inline: 6px;
    }

    .sidebar-skeleton__row,
    .sidebar-skeleton__footer {
      justify-content: center;
    }

  }
}

@keyframes skeleton-pulse {
  0%,
  100% {
    opacity: 0.5;
  }

  50% {
    opacity: 1;
  }
}

@media (prefers-reduced-motion: reduce) {
  .sidebar-skeleton__avatar,
  .sidebar-skeleton__glyph,
  .sidebar-skeleton__bar {
    animation: none;
  }
}
