/* The SDS Manager sidebar: every admin screen, white and dark. Build 121.
 * ---------------------------------------------------------------------------
 * Shafiq's decision, 4 Nov 2026 (replacing D43, build 107: a dark sidebar on our screens only). In the approved
 * design the sidebar sits on the page background with no border, beside the raised main panel; a selected item is
 * the accent's tint with the accent's dark text. Its colours are Wagtail's own tokens, set from the palette in
 * admin-theme.css (--w-color-surface-menus, -surface-menu-item-active, -text-label-menus-*), so this file holds
 * only what no token does: the rows' shape, the count badge, the heartbeat and the "Dark mode" switch.
 *
 * Variables first. A rule that needs a Wagtail class name is marked INTERNAL and listed in PR_NOTES.md under "rules
 * that depend on Wagtail internals", so an upgrade has a checklist. Off: CONTENTAGENT_SIDEBAR_THEME or
 * CONTENTAGENT_ADMIN_THEME.
 */

.sidebar,
.sidebar-loading {
  --ca-sb-radius: var(--sds-radius, 10px);
  --ca-sb-gutter: 8px;
  --ca-sb-hover: var(--sds-hover);
}

/* INTERNAL (1/14): the rail sits on the page, no border, no seam. */
.sidebar__inner,
.sidebar-loading__inner {
  background: var(--w-color-surface-menus);
  border: 0;
}

/* INTERNAL (2/14): .sidebar-menu-item__link, the anchor (or the switch's button) Wagtail draws for a row. A rounded
   row inside the gutter, at least 40px tall. */
.sidebar .sidebar-menu-item__link {
  box-sizing: border-box;
  width: calc(100% - 2 * var(--ca-sb-gutter));
  min-height: var(--sds-target, 2.5rem);
  margin: 1px var(--ca-sb-gutter);
  border-radius: var(--ca-sb-radius);
  border-inline-start-color: transparent;
  border-inline-end-color: transparent;
}

.sidebar .sidebar-menu-item__link:hover {
  background: var(--ca-sb-hover);
  color: var(--w-color-text-label);
}

/* INTERNAL (8/14): Wagtail 6.3 gives the selected row, an open submenu's row and a hovered or focused row a dark 1px
   text-shadow (--w-color-black-35), drawn for its dark sidebar; on ours it smudged the text (Shafiq, build 123). */
.sidebar .sidebar-menu-item,
.sidebar .sidebar-menu-item__link,
.sidebar .sidebar-menu-item__link:is(:hover, :focus),
.sidebar .sidebar-sub-menu-item--open > a {
  text-shadow: none;
}

/* INTERNAL (3/14): the selected row: the accent's tint and its dark text, no rail. */
.sidebar .sidebar-menu-item--active > .sidebar-menu-item__link,
.sidebar .sidebar-menu-item--active > form > .sidebar-menu-item__link {
  background: var(--w-color-surface-menu-item-active);
  color: var(--w-color-text-label-menus-active);
  font-weight: 600;
}

/* Wagtail paints the selected <li> with the same token too; translucent, the two would stack into a second, wider
   band to the rail's edge. Only the rounded row carries it. */
.sidebar .sidebar-menu-item--active {
  background: transparent;
}

.sidebar .sidebar-menu-item--active > .sidebar-menu-item__link .icon {
  color: var(--sds-accent);
}

/* --- the count badge: our attribute (ContentAgentMenuItem), no Wagtail class --------------------------------- */
.sidebar [data-ca-count]::after {
  content: attr(data-ca-count);
  margin-inline-start: auto;
  min-width: 1.25rem;
  padding: 0 0.35rem;
  border-radius: 999px;
  /* Build 123: the draft tint laid on the rail's own colour, not on whatever row it sits in. In dark the tint is
     translucent, and over the selected row's tint "23" read 4.44:1; now it is the same on every row. */
  background: linear-gradient(var(--sds-draft-bg), var(--sds-draft-bg)), var(--w-color-surface-menus);
  color: var(--sds-draft-fg);
  font-size: 12px; /* build 122: a badge's label, 12px at the least */
  font-weight: 700;
  line-height: 1.45;
  text-align: center;
}

/* INTERNAL (9/14): Wagtail's own count badge (Help's "what's new" for a person who has not opened it) prints its number in
   the menu's surface colour, white on its amber in Wagtail's dark sidebar and 1.83:1 on ours (build 123). The text
   navy reads 8.6:1 on the amber in both modes. */
.sidebar .w-dismissible-badge--count {
  color: hsl(227 44% 14%); /* the text navy, #141B34 */
}

.sidebar [data-ca-count="0"]::after {
  content: none;
}

.sidebar--slim [data-ca-count]::after {
  content: none;
}

/* --- the heartbeat: our attributes (ContentAgentHeartbeatItem), see contentagent/heartbeat.py ---------------- */
.sidebar [data-ca-beat] {
  display: block;
  box-sizing: border-box;
  width: calc(100% - (var(--ca-sb-gutter) * 2));
  margin: 0.5rem var(--ca-sb-gutter);
  padding: 0.55rem 0.65rem;
  border: 1px solid var(--w-color-border-furniture);
  border-radius: var(--ca-sb-radius);
  color: var(--w-color-text-label-menus-default);
  font-size: 13px; /* build 122: 13px at the least, outside pills */
  font-weight: 600;
  line-height: 1.35;
  text-decoration: none;
  white-space: normal;
}

.sidebar [data-ca-beat]:hover {
  background: var(--ca-sb-hover);
}

/* Build 123 (the by-eye pass): Wagtail's .menuitem is a block, which put the dot on a line of its own over an
   indented title. The dot and the title share the first line now; the detail stays under them. */
.sidebar [data-ca-beat] .menuitem {
  display: inline-flex;
  max-width: calc(100% - 1em);
  vertical-align: top;
}

.sidebar [data-ca-beat] .menuitem-label {
  margin-inline-start: 0;
}

.sidebar [data-ca-beat]::before {
  content: "\25CF";
  margin-inline-end: 0.35rem;
  font-size: 9px;
  vertical-align: 0.15em;
}

.sidebar [data-ca-beat]::after {
  content: attr(data-ca-detail);
  display: block;
  margin-top: 0.15rem;
  color: var(--w-color-text-meta);
  font-size: 13px;
  font-weight: 400;
  line-height: 1.4;
}

.sidebar [data-ca-beat="working"] {
  border-color: var(--sds-positive-fg);
  background: var(--sds-positive-bg);
  color: var(--sds-positive-fg);
}

.sidebar [data-ca-beat="stalled"] {
  border-color: var(--sds-draft-fg);
  background: var(--sds-draft-bg);
  color: var(--sds-draft-fg);
}

.sidebar--slim [data-ca-beat] {
  font-size: 0;
  text-align: center;
}

.sidebar--slim [data-ca-beat]::before {
  margin-inline-end: 0;
  font-size: 10px;
}

.sidebar--slim [data-ca-beat]::after {
  content: none;
}

/* INTERNAL (4/14): the row Wagtail wraps around a menu item; the heartbeat is a block, not a link row. */
.sidebar .sidebar-menu-item:has([data-ca-beat]) {
  margin: 0;
}

/* --- the "Dark mode" switch (contentagent/theme.py, theme-toggle.js) ------------------------------------------
 * At the bottom of the sidebar, above the person's name: INTERNAL (5/14), the menu fills the rail and its list is a
 * column, so the last items (the heartbeat, then the switch) sit at its foot. */
.sidebar .sidebar-main-menu {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
}

.sidebar .sidebar-main-menu__list {
  display: flex;
  flex: 1 0 auto;
  flex-direction: column;
}

.sidebar .sidebar-menu-item:has([data-ca-beat]),
.sidebar .sidebar-menu-item:has(form[data-ca-theme-toggle]) {
  margin-top: auto;
}

.sidebar .sidebar-menu-item:has([data-ca-beat]:not([data-ca-beat="idle"], [data-ca-beat="never"]))
  ~ .sidebar-menu-item:has(form[data-ca-theme-toggle]) {
  margin-top: 0;
}

/* Build 123 (Shafiq): the status block shows only while a run is writing, or has stalled mid-run. Idle (or never
   run), "Nothing being written" is not news, and it cost the menu its last rows at 835px. */
.sidebar .sidebar-menu-item:has([data-ca-beat="idle"], [data-ca-beat="never"]) {
  display: none;
}

/* Always in view: when the menu is longer than the screen it scrolls under the switch, which stays at its foot. */
.sidebar .sidebar-menu-item:has(form[data-ca-theme-toggle]) {
  position: sticky;
  bottom: 0;
  z-index: 1;
  padding-block: 4px;
  background: var(--w-color-surface-menus);
  /* Build 128, item 9: a 1px line and a soft fade above the foot, so a row scrolling under it ("Settings" at 827px
     tall) reads as more menu, not as a half-hidden row. The fade is the menu's own colour, so over empty menu it
     cannot be seen; it shows only when rows are under it. */
  border-top: 1px solid var(--w-color-border-furniture);
}

.sidebar .sidebar-menu-item:has(form[data-ca-theme-toggle])::before {
  content: "";
  position: absolute;
  inset-inline: 0;
  bottom: 100%;
  height: 16px;
  pointer-events: none;
  background: linear-gradient(to bottom, transparent, var(--w-color-surface-menus));
}

/* INTERNAL (6/14): the switch is Wagtail's button row; the track and thumb are drawn after its label from its own
   aria-checked, so what it shows is what a screen reader hears. */
.sidebar .ca-theme-toggle {
  cursor: pointer;
  font: inherit;
}

.sidebar .ca-theme-toggle::after {
  content: "";
  flex: none;
  width: 34px;
  height: 20px;
  margin-inline-start: auto;
  border-radius: 999px;
  background: radial-gradient(circle 7px at 10px 50%, #ffffff 92%, transparent 100%), var(--sds-text-2);
  transition: background 120ms ease-out;
}

.sidebar .ca-theme-toggle[aria-checked="true"]::after {
  background: radial-gradient(circle 7px at 24px 50%, #ffffff 92%, transparent 100%), var(--sds-accent);
}

.sidebar .ca-theme-toggle[aria-checked="true"] .icon {
  color: var(--sds-accent);
}

/* A focus ring inside the rail (its overflow would clip one drawn outside), in the accent, in both modes. */
.sidebar .ca-theme-toggle:focus-visible {
  outline: 3px solid var(--sds-accent);
  outline-offset: -3px;
}

/* INTERNAL (7/14): collapsed (Wagtail 6.3's .sidebar--slim), the moon only; Wagtail shows the label as its tooltip. */
.sidebar--slim .ca-theme-toggle::after {
  content: none;
}

@media (prefers-reduced-motion: reduce) {
  .sidebar .ca-theme-toggle::after {
    transition: none;
  }
}

/* Wagtail's more-contrast setting keeps working: the resting label takes the full text colour. */
.w-contrast-more .sidebar {
  --w-color-text-label-menus-default: var(--sds-text);
}

/* --- build 123: the compact sidebar (Shafiq's approved mockup) -------------------------------------------------
 * From Wagtail's desktop breakpoint (50em, 800px) up: the logo 26px tall on the collapse button's row, 36px rows 6px
 * apart (build 124, Shafiq: build 122's 44px 1px apart was too much space, build 123's 34px 4px apart too cramped; the
 * menu may scroll), 14px labels and 16px icons 10px apart, 8px corners, and a 1px line over the foot (Dark mode a row, the account 40px). On a phone (the menu behind its button) none of
 * this applies and rows stay 40px. One property per value, to change them again here. */
.sidebar,
.sidebar-loading {
  --sds-sb-top: 16px; /* above the logo */
  --sds-sb-logo-h: 26px; /* the logo's height */
  --sds-sb-logo-below: 14px; /* under the logo */
  --sds-sb-toggle: 32px; /* the collapse button, square */
  --sds-sb-row: 36px; /* a row's height (WCAG 2.2's minimum target is 24px) */
  --sds-sb-gap: 6px; /* between rows: 42px a row */
  --sds-sb-row-pad: 10px; /* a row's side padding */
  --sds-sb-text: 14px; /* a row's label */
  --sds-sb-icon: 16px; /* a row's icon */
  --sds-sb-icon-gap: 10px; /* icon to label */
  --sds-sb-radius: 8px; /* a row's corners */
  --sds-sb-switch-w: 30px; /* the Dark mode switch */
  --sds-sb-switch-h: 18px;
  --sds-sb-account: 40px; /* the account row */
  --sds-sb-avatar: 26px;
  --sds-sb-slim: 60px; /* INTERNAL: Wagtail 6.3's collapsed rail width (.sidebar--slim) */
}

@media (min-width: 50em) {
  /* INTERNAL (10/14): the logo, left-aligned, on the collapse button's row. Wagtail's .sidebar-custom-branding (a
     link it centres with a 2em margin) holds our .ca-brand; the button's wrapper leaves the flow for the row's right
     end. Collapsed, the rail keeps the button over the symbol, as before. */
  .sidebar:not(.sidebar--slim) .sidebar-custom-branding {
    margin: 0;
    padding: var(--sds-sb-top) calc(var(--ca-sb-gutter) * 2 + var(--sds-sb-toggle)) var(--sds-sb-logo-below)
      calc(var(--ca-sb-gutter) + var(--sds-sb-row-pad));
    text-align: start;
  }

  .sidebar:not(.sidebar--slim) .ca-brand {
    padding: 0;
  }

  .sidebar:not(.sidebar--slim) .ca-logo {
    width: auto;
    height: var(--sds-sb-logo-h);
  }

  .sidebar:not(.sidebar--slim) .sidebar__inner > :has(> .sidebar__collapse-toggle) {
    position: absolute;
    top: calc(var(--sds-sb-top) + (var(--sds-sb-logo-h) - var(--sds-sb-toggle)) / 2);
    inset-inline-end: var(--ca-sb-gutter);
    z-index: 1;
    margin: 0;
  }

  /* It is a Wagtail .button, which admin-theme.css gives a 40px minimum. */
  .sidebar:not(.sidebar--slim) .sidebar__collapse-toggle {
    width: var(--sds-sb-toggle);
    height: var(--sds-sb-toggle);
    min-height: var(--sds-sb-toggle);
    margin: 0;
  }

  /* Collapsed: the button stays where it was (centred in the 60px rail) and the 32px symbol sits under it, without
     Wagtail's 40px of padding around a slim logo, so the menu fits there too. */
  .sidebar--slim .sidebar__inner > :has(> .sidebar__collapse-toggle) {
    justify-content: center;
    margin-top: calc(var(--sds-sb-top) + (var(--sds-sb-logo-h) - var(--sds-sb-toggle)) / 2);
  }

  .sidebar--slim .sidebar__collapse-toggle {
    width: var(--sds-sb-toggle);
    height: var(--sds-sb-toggle);
    min-height: var(--sds-sb-toggle);
    margin: 0;
  }

  .sidebar--slim .sidebar-custom-branding {
    margin: 0;
    padding: var(--sds-sb-gap) 0 var(--sds-sb-logo-below);
  }

  .sidebar--slim .ca-brand {
    padding: 0;
  }

  /* INTERNAL (11/14): every row (the menu, its submenus, the account's menu): Wagtail's .sidebar-menu-item__link,
     its .icon--menuitem and .menuitem-label. Rows are spaced by their <li>, which works in the main menu's column
     and in a submenu's plain list alike. */
  .sidebar .sidebar-menu-item__link {
    min-height: var(--sds-sb-row);
    margin-block: 0;
    padding: 0 var(--sds-sb-row-pad);
    border-radius: var(--sds-sb-radius);
    font-size: var(--sds-sb-text);
  }

  /* :where keeps it light, so the heartbeat's and the switch's margin-top: auto (above) still win. */
  .sidebar :where(.sidebar-menu-item + .sidebar-menu-item) {
    margin-block-start: var(--sds-sb-gap);
  }

  /* A submenu's label may wrap to two lines: those rows keep a little padding so the text does not touch the tint. */
  .sidebar .sidebar-menu-item--in-sub-menu .sidebar-menu-item__link {
    padding-block: calc((var(--sds-sb-row) - 1.3 * var(--sds-sb-text)) / 2);
  }

  .sidebar .icon--menuitem {
    width: var(--sds-sb-icon);
    min-width: var(--sds-sb-icon);
    height: var(--sds-sb-icon);
  }

  .sidebar .menuitem-label {
    margin-inline-start: var(--sds-sb-icon-gap);
  }

  /* Collapsed, the icon sits in the middle of the rail. */
  .sidebar--slim .sidebar-menu-item__link {
    padding-inline: calc((var(--sds-sb-slim) - 2 * var(--ca-sb-gutter, 8px) - var(--sds-sb-icon)) / 2);
  }

  /* INTERNAL (12/14): Search, a normal row. Wagtail draws it as form[role=search] holding a button (the icon) and
     an input laid over the whole row; the input's sizes are Tailwind !important utilities, so ours must be too. */
  .sidebar form[role="search"] {
    box-sizing: border-box;
    width: calc(100% - 2 * var(--ca-sb-gutter));
    height: var(--sds-sb-row);
    margin: 0 var(--ca-sb-gutter) var(--sds-sb-gap);
    border-radius: var(--sds-sb-radius);
  }

  .sidebar form[role="search"]:hover {
    background: var(--ca-sb-hover);
  }

  /* The icon centred in the row, not laid on a text baseline (it sat 2.8px above "Search"; Shafiq, build 123). */
  .sidebar form[role="search"] button {
    display: flex;
    align-items: center;
    height: 100%;
    padding-inline-start: var(--sds-sb-row-pad);
  }

  .sidebar form[role="search"] input {
    min-height: 0; /* Wagtail's text fields are at least 42px */
    height: 100% !important;
    /* An input sets its text about 1px lower than the rows' labels; 2px under it lines "Search" up with them. */
    padding-block: 0 2px !important;
    padding-inline-start: calc(var(--sds-sb-row-pad) + var(--sds-sb-icon) + var(--sds-sb-icon-gap)) !important;
    border-radius: var(--sds-sb-radius) !important;
    font-size: var(--sds-sb-text) !important;
    line-height: 1.25 !important; /* the rows' labels' (Wagtail's .menuitem-label) */
  }

  .sidebar--slim form[role="search"] button {
    padding-inline-start: calc((var(--sds-sb-slim) - 2 * var(--ca-sb-gutter, 8px) - var(--sds-sb-icon)) / 2);
  }

  /* The heartbeat, shown while a run writes (Shafiq): the dot and the title on one line at the rows' 14px, the
     detail on one 13px line under it, cut with an ellipsis; the whole sentence is the link's tooltip. */
  .sidebar [data-ca-beat] {
    margin-block: var(--sds-sb-gap);
    padding: 6px var(--sds-sb-row-pad);
    border-radius: var(--sds-sb-radius);
    line-height: 1.3;
  }

  .sidebar [data-ca-beat]::after {
    overflow: hidden;
    line-height: 1.3;
    white-space: nowrap;
    text-overflow: ellipsis;
  }

  /* The foot: a 1px line over Dark mode; the switch 30 x 18px, its thumb 3px inside the track. */
  .sidebar .sidebar-menu-item:has(form[data-ca-theme-toggle]) {
    border-top: 1px solid var(--w-color-border-furniture);
  }

  .sidebar .ca-theme-toggle::after {
    width: var(--sds-sb-switch-w);
    height: var(--sds-sb-switch-h);
    background:
      radial-gradient(circle calc(var(--sds-sb-switch-h) / 2 - 3px) at calc(var(--sds-sb-switch-h) / 2) 50%,
        #ffffff 92%, transparent 100%),
      var(--sds-text-2);
  }

  .sidebar .ca-theme-toggle[aria-checked="true"]::after {
    background:
      radial-gradient(circle calc(var(--sds-sb-switch-h) / 2 - 3px)
        at calc(var(--sds-sb-switch-w) - var(--sds-sb-switch-h) / 2) 50%, #ffffff 92%, transparent 100%),
      var(--sds-accent);
  }

  /* Help's "what's new" count (INTERNAL, 9/14 above): Wagtail places it 1.75rem into the row, on the icon of its
     wider rows and on the label of ours ("?2elp"). Over the icon's top right corner instead. */
  .sidebar .sidebar-menu-item .w-dismissible-badge--count {
    inset-inline-start: calc(var(--sds-sb-row-pad) + var(--sds-sb-icon) - 8px);
  }

  /* INTERNAL (13/14): the account, Wagtail's .sidebar-footer__account; its avatar's size is a Tailwind !important
     utility. The avatar is centred on the rows' icon column. */
  .sidebar .sidebar-footer__account {
    min-height: var(--sds-sb-account);
    padding-block: calc((var(--sds-sb-account) - var(--sds-sb-avatar)) / 2);
    padding-inline-start: calc(var(--ca-sb-gutter) + var(--sds-sb-row-pad) - (var(--sds-sb-avatar) - var(--sds-sb-icon)) / 2);
  }

  .sidebar .sidebar-footer__account .avatar {
    width: var(--sds-sb-avatar) !important;
    height: var(--sds-sb-avatar) !important;
  }

  /* INTERNAL (14/14): collapsed, Wagtail centres the avatar in the 60px rail with its own padding; keep that. */
  .sidebar--slim .sidebar-footer__account {
    padding-inline-start: calc((var(--sds-sb-slim) - var(--sds-sb-avatar)) / 2);
  }
}
