@layer base {
/* Reset & Variables.
   Design tokens live in tokens/ — see docs/dev/web/design-system.md §3. Only
   layout constants that are not part of a scale belong here. */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

:root {
  --toolbar-h: 33px;
}

html { font-size: 14px; }
html, body {
  height: 100%;
}

body {
  font-family: var(--font);
  color: var(--text);
  background: var(--bg);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  height: 100%;
  padding-left: var(--sidenav-w);
}

a { color: var(--accent); text-decoration: none; }
a:hover { color: var(--accent-hover); }

/* Form elements */
textarea, input[type="text"], input[type="email"], input[type="date"],
input[type="number"], input[type="password"], input[type="search"],
input[type="url"], select {
  padding: var(--space-xs);
  box-sizing: border-box;
}

textarea {
  padding: var(--space-sm);
}

/* ── Sidenav ── */
:root {
  --sidenav-w: 48px;
  --sidenav-expanded-w: 210px;
}

.sidenav {
  position: fixed;
  left: 0;
  top: 0;
  bottom: 0;
  width: var(--sidenav-w);
  z-index: 500;
  background: var(--surface);
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  overflow: visible;
  transition: width var(--dur-base) var(--ease-out);
}
.sidenav:is(:hover, .sidenav--preview-open) {
  width: var(--sidenav-expanded-w);
  box-shadow: var(--elev-2);
}

/* Environment tint — left border stripe */
.sidenav-env-dev { border-left: 3px solid var(--nav-env-dev); }
.sidenav-env-dev-prod-db { border-left: 3px solid #e57373; }

/* Brand row — the METIS logo, links home */
.sidenav-brand {
  display: flex;
  align-items: center;
  gap: 8px;
  border-bottom: 1px solid var(--border-light);
  flex-shrink: 0;
  text-decoration: none;
  overflow: hidden;
}
.sidenav-brand:hover { opacity: 0.85; }
.sidenav-brand-img {
  width: 48px;
  height: 48px;
  margin: 0;
  padding: 0;
  object-fit: cover;
  display: block;
  flex-shrink: 0;
}
.sidenav-brand-text {
  opacity: 0;
  display: flex;
  flex-direction: column;
  min-width: 0;
  overflow: hidden;
  color: var(--text);
  transition: opacity var(--dur-fast) var(--ease-out) 0.06s;
}
.sidenav:is(:hover, .sidenav--preview-open) .sidenav-brand-text { opacity: 1; }
.sidenav-brand-greeting {
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--text-muted);
  white-space: nowrap;
}
.sidenav-brand-name {
  font-size: var(--text-base);
  font-weight: 700;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Focus group — the focus selector + the pages it scopes, visually bound
   together with a left accent stripe so it's clear which items focus affects. */
/* Scope wrapper: the left accent line runs from Focus through all Apps */
.sidenav-focus-scope {
  border-left: 2px solid var(--accent);
  margin: 6px 0;
}
/* All items inside the scope lose 2px left padding to offset the stripe */
.sidenav-focus-scope .sidenav-item { padding-left: 10px; }

.sidenav-focus-group {
  position: relative;
}
/* Group head (top of the rail): focus holon logo on the left, with a right
   column holding the "eye + Focus" heading above the dropdown chip. */
.sidenav-focus-group__head {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 8px;
  /* No horizontal padding: the logo fills the full collapsed-rail width. The
     right column carries its own right padding (only shown when expanded). */
  padding: 8px 0;
  min-height: 32px;
}
/* Right column (expanded only): eye+label heading stacked over the dropdown. */
.sidenav-focus-col {
  display: flex;
  flex-direction: column;
  gap: 6px;
  flex: 1 1 auto;
  min-width: 0;
  padding-right: 12px;
}
/* The right column collapses away on the narrow rail so only the logo shows.
   Exception: keep it laid out when the dropdown menu is open, so an open menu
   survives the sidenav losing :hover (mouse on the fixed menu). */
.sidenav:not(:hover):not(.sidenav--preview-open) .sidenav-focus-group__head:not(:has(.toggle-focus.open)) .sidenav-focus-col {
  display: none;
}
.sidenav-focus-heading {
  display: flex;
  align-items: center;
  gap: 8px;
}
.sidenav-focus-eye {
  /* 70% of the 24px nav-icon size. */
  width: 17px;
  height: 17px;
  flex-shrink: 0;
  color: var(--accent);
  opacity: 0.85;
}
.sidenav-focus-col .toggle-focus {
  flex: 1 1 auto;
  width: auto;
  min-width: 0;
}
/* Focus holon logo: sized to fill the full collapsed-rail width (46px) and kept
   fixed when the sidenav expands, so it never resizes. Links to the holon. */
.sidenav-focus-logo {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 46px;
  height: 46px;
  flex-shrink: 0;
}
.sidenav-focus-logo img {
  width: 46px;
  height: 46px;
  border-radius: var(--radius-md);
  object-fit: cover;
  display: block;
}
.sidenav-focus-logo .toggle-focus__badge {
  width: 46px;
  height: 46px;
  border-radius: var(--radius-md);
  font-size: var(--text-xl);
}
.sidenav-focus-logo svg {
  width: 46px;
  height: 46px;
  color: var(--accent);
}
/* "All" (no focus): globe reads smaller than a holon logo. */
.sidenav-focus-logo--all svg {
  width: 34px;
  height: 34px;
}
/* The chip's own leading avatar is redundant now the icon sits outside it. */
.sidenav-focus-group .toggle-focus__avatar {
  display: none;
}
.sidenav-focus-heading-label {
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-light);
  white-space: nowrap;
  opacity: 0;
  transition: opacity var(--dur-fast) var(--ease-out) 0.06s;
}
.sidenav:is(:hover, .sidenav--preview-open) .sidenav-focus-heading-label { opacity: 1; }
/* Dropdown chip is hidden until the sidenav expands on hover */
.sidenav-focus-group .toggle-focus {
  display: flex;
  width: 100%;
  min-width: 0;
  opacity: 0;
  transition: opacity var(--dur-fast) var(--ease-out) 0.06s;
}
/* When collapsed, the chip is fully removed from layout (display:none, not
   height:0) so only the eye heading shows in the focus group.
   Exception: when the menu is open (.open), keep it visible even if the
   mouse has moved onto the fixed-positioned dropdown (outside the sidenav). */
.sidenav:not(:hover):not(.sidenav--preview-open) .sidenav-focus-group .toggle-focus:not(.open) {
  display: none;
}
.sidenav-focus-group .toggle-focus.open {
  opacity: 1;
}
.sidenav-focus-group .toggle-focus__menu {
  position: fixed;
  left: 0;
  right: auto;
  top: 80px; /* overridden by JS; fallback keeps it below the head */
}
.sidenav:is(:hover, .sidenav--preview-open) .sidenav-focus-group .toggle-focus {
  opacity: 1;
}
/* Focus chip in the sidenav: full-width, reads as a chip, and lights up with a
   tinted background + accent border on hover so it's clearly interactive. */
.sidenav-focus-group .toggle-btn--focus {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 5px 8px;
  border: 1px solid var(--border);
  border-radius: var(--radius-full);
  background: var(--surface);
  color: var(--text);
  transition: background var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out);
}
.sidenav-focus-group .toggle-btn--focus:hover,
.sidenav-focus-group.is-open .toggle-btn--focus,
.sidenav-focus-group .toggle-focus.open .toggle-btn--focus {
  background: var(--accent-ring);
  border-color: var(--accent);
  box-shadow: var(--elev-1);
}
.sidenav-focus-group .toggle-focus__label {
  flex: 1;
  min-width: 0;
  text-align: left;
  font-weight: 600;
}
/* Logo/badge shown inside the chip (current focus) */
.toggle-focus__avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  flex-shrink: 0;
  color: var(--accent);
}
.toggle-focus__avatar img {
  width: 20px;
  height: 20px;
  border-radius: var(--radius-sm);
  object-fit: cover;
  display: block;
}
.toggle-focus__badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  border-radius: var(--radius-sm);
  font-size: var(--text-xs);
  font-weight: 700;
  flex-shrink: 0;
}
/* Logos inside the dropdown menu items */
.toggle-focus__item {
  display: flex !important;
  align-items: center;
  gap: 8px;
}
.toggle-focus__item-logo {
  width: 20px;
  height: 20px;
  flex-shrink: 0;
  border-radius: var(--radius-sm);
  object-fit: cover;
  display: block;
}
.toggle-focus__item-logo--all {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--accent);
}
.toggle-focus__item-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Keep .sidenav-logo for any remaining usages */
.sidenav-logo {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px;
  border-bottom: 1px solid var(--border-light);
  text-decoration: none;
  color: var(--text);
  flex-shrink: 0;
  white-space: nowrap;
}
.sidenav-logo:hover { background: var(--border-light); }
.sidenav-logo-icon { width: 24px; height: 24px; flex-shrink: 0; }
.sidenav-logo-label { font-size: var(--text-base); font-weight: 600; color: var(--text-muted); }
.sidenav-logo-holon { border-radius: var(--radius); object-fit: contain; }
.sidenav-logo-badge {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border-radius: var(--radius);
  font-size: var(--text-base);
  font-weight: 700;
  flex-shrink: 0;
}
.sidenav-logo-edit {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: var(--radius);
  color: var(--text-muted);
  text-decoration: none;
  margin-right: 6px;
}
.sidenav-logo-edit:hover {
  color: var(--accent);
  background: var(--border-light);
}

/* Pinned head — the focus selector and Search.
   Outside .sidenav-items on purpose: a control that scopes the whole rail
   should not scroll away from the things it scopes, and keeping it out of the
   scroll container is what lets .sidenav stay overflow:visible so the focus
   dropdown can escape the 48px rail. */
.sidenav-head {
  flex-shrink: 0;
  padding: 4px 0;
}

/* Items container — the only band that scrolls.
   It used to be overflow:hidden, which did not scroll the overflow, it clipped
   it: on a 13" laptop eight of twenty rows were unreachable by any gesture, and
   which app disappeared depended on ShellNavGroup.order. */
.sidenav-items {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  overflow-x: hidden;
  padding: 4px 0;
  scrollbar-width: thin;
  scrollbar-color: var(--border) transparent;
}

.sidenav-items::-webkit-scrollbar { width: 6px; }
.sidenav-items::-webkit-scrollbar-track { background: transparent; }
.sidenav-items::-webkit-scrollbar-thumb {
  background: var(--border);
  border-radius: var(--radius-sm);
}

/* A scrollbar in a 48px rail is noise, and there is nothing to scroll to that
   the hover-expanded rail does not show better. */
.sidenav:not(:hover):not(.sidenav--preview-open) .sidenav-items {
  scrollbar-width: none;
}
.sidenav:not(:hover):not(.sidenav--preview-open) .sidenav-items::-webkit-scrollbar { width: 0; }

/* Bottom fade, only when the list actually overflows — data-overflow is set by
   a ResizeObserver in sidenav.js. Always-on, it would soften the last item in
   the common case where everything fits. */
.sidenav-items[data-overflow="true"] {
  mask-image: linear-gradient(to bottom, var(--text) calc(100% - 12px), transparent);
}

/* Footer */
.sidenav-footer {
  border-top: 1px solid var(--border-light);
  padding: 4px 0;
  flex-shrink: 0;
  /* visible, not hidden: the user menu opens out of the rail, beside it. */
  overflow: visible;
  position: relative;
}

/* Individual item */
.sidenav-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 6px 12px;
  color: var(--text-muted);
  text-decoration: none;
  white-space: nowrap;
  font-family: var(--font);
  font-size: var(--text-md);
  border: none;
  background: none;
  cursor: pointer;
  width: 100%;
  text-align: left;
  line-height: 1.4;
  transition: background var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}
/* Primary nav rows (Activity, Calendar, People, Orgs) sit tighter together —
   they have no App heading separating them. */
.sidenav-focus-scope > .sidenav-item,
.sidenav-app-group--primary .sidenav-item { padding-top: 5px; padding-bottom: 5px; }

.sidenav-item:hover { background: var(--border-light); color: var(--text); }
.sidenav-item.sidenav-active { background: var(--border-light); color: var(--text); }
.sidenav-item.sidenav-active .sidenav-icon { opacity: 0.85; }

/* Wrap: sidenav item with an edit/action link (visible only when expanded) */
.sidenav-item-wrap {
  display: flex;
  align-items: center;
  overflow: hidden;
  white-space: nowrap;
}
.sidenav-item-wrap .sidenav-item { flex: 1; min-width: 0; }
/* Hide edit button when sidebar is collapsed so it doesn't steal width from the item */
.sidenav:not(:hover):not(.sidenav--preview-open) .sidenav-item-edit {
  display: none;
}

.sidenav-item-edit {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: var(--radius);
  color: var(--text-muted);
  text-decoration: none;
  margin-right: 6px;
}
.sidenav-item-edit:hover {
  color: var(--accent);
  background: var(--border-light);
}

/* Icons within items */
.sidenav-icon {
  width: 24px;
  height: 24px;
  flex-shrink: 0;
  opacity: 0.45;
  transition: opacity var(--dur-base) var(--ease-out);
  display: block;
}
.sidenav-item:hover .sidenav-icon { opacity: 0.8; }
.sidenav-static-icon { filter: opacity(0.45); }
.sidenav-item:hover .sidenav-static-icon { filter: opacity(0.8); }

/* Labels — hidden until sidebar expands */
.sidenav-label {
  opacity: 0;
  transition: opacity var(--dur-fast) var(--ease-out) 0.06s;
  overflow: hidden;
  text-overflow: ellipsis;
}
.sidenav:is(:hover, .sidenav--preview-open) .sidenav-label { opacity: 1; }

/* Divider */
.sidenav-divider {
  height: 1px;
  background: var(--border-light);
  margin: 6px 12px;
  flex-shrink: 0;
}

/* Section heading — labels a group of nav items below it (e.g. "Apps" above
   Coherence). Icon always visible; label fades in only when expanded, same
   behavior as .sidenav-focus-heading-label. */
.sidenav-section-heading {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 4px 12px;
  flex-shrink: 0;
}
.sidenav-section-heading-icon {
  width: 24px;
  height: 24px;
  flex-shrink: 0;
  color: var(--text-light);
  opacity: 0.85;
}
.sidenav-section-heading-label {
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-light);
  white-space: nowrap;
  opacity: 0;
  transition: opacity var(--dur-fast) var(--ease-out) 0.06s;
}
.sidenav:is(:hover, .sidenav--preview-open) .sidenav-section-heading-label { opacity: 1; }

/* App groups: named app + collapsible sub-items */
.sidenav-app-group {
  display: flex;
  flex-direction: column;
}

/* App tint — an app's block in the rail carries its own colour, so which app
   you are looking at is legible even on the collapsed 48px rail where the
   labels are hidden. Generic mechanism, one token pair per app: the shell
   tags each group with data-app-group="<slug>" and the owning app (or
   tokens/apps.css, for apps using platform primitives) sets the tint.
   Untinted apps default to transparent and look exactly as before.

   Colour only. The rail's geometry stays identical in every app — navigation
   has to feel the same shape wherever you are. */
.sidenav-app-group[data-app-group] {
  background: var(--app-nav-bg, transparent);
  transition: background var(--transition-base);
}

.sidenav-app-group[data-app-group]:hover {
  background: var(--app-nav-bg-hover, var(--app-nav-bg, transparent));
}

/* Items inside a tinted group need their own hover to stay legible against the
   tint rather than the rail's white. */
.sidenav-app-group[data-app-group] .sidenav-item:hover,
.sidenav-app-group[data-app-group] .sidenav-item.sidenav-active {
  background: var(--app-nav-item-active, var(--border-light));
}
/* Sub-items: shown only while the group is open. One open group at a time is
   what keeps the rail's height bounded as apps get registered. */
.sidenav-app-items {
  display: flex;
  flex-direction: column;
}
.sidenav-app-group[data-app-group]:not([data-open]) > .sidenav-app-items {
  display: none;
}

/* App section heading — a disclosure button wearing the .sidenav-item
   treatment, so the row reads and behaves like every other row in the rail. */
.sidenav-app-heading {
  padding: 15px 12px 2px 10px;
  color: var(--text);
}
.sidenav-app-heading .sidenav-icon {
  flex-shrink: 0;
  opacity: 1;
}
.sidenav-app-label {
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  flex: 1;
  min-width: 0;
}

/* On the collapsed rail the mark and the app's tint already say which app this
   is — the strongest signal there is at 48px. The heading is not a click target
   while collapsed: the rail expands on hover / :focus-within first (existing
   behaviour), and then the toggles are usable. */
.sidenav:not(:hover):not(.sidenav--preview-open):not(:focus-within) .sidenav-app-heading {
  pointer-events: none;
}

/* Collapsed: a dot meaning "there is more inside". Expanded: the disclosure
   chevron, rotated when open. One element, because it is one affordance. */
.sidenav-app-chevron {
  flex-shrink: 0;
  width: 10px;
  height: 10px;
  margin-right: 2px;
  border-radius: var(--radius-full);
  background: currentColor;
  opacity: 0.45;
  transition: transform var(--dur-fast) var(--ease-out),
              opacity var(--dur-fast) var(--ease-out);
}
.sidenav:is(:hover, .sidenav--preview-open) .sidenav-app-chevron,
.sidenav:focus-within .sidenav-app-chevron {
  border-radius: 0;
  background: none;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  width: 7px;
  height: 7px;
  margin-right: 5px;
  transform: rotate(-45deg);
}
.sidenav:is(:hover, .sidenav--preview-open) .sidenav-app-group[data-open] .sidenav-app-chevron,
.sidenav:focus-within .sidenav-app-group[data-open] .sidenav-app-chevron {
  transform: rotate(45deg);
}
/* An open group has its rows on show; the dot would be saying it twice. */
.sidenav-app-group[data-open] .sidenav-app-chevron { opacity: 0.7; }

/* ── Footer: the signed-in person, and the menu behind them ──────────────
   One row instead of four, which is where two or three of the rail's rows came
   back from. It also returns the "who am I signed in as" signal the old brand
   row used to carry. */
.sidenav-user { position: relative; }

.sidenav-user__trigger { gap: 10px; }

.sidenav-user__avatar {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  flex-shrink: 0;
}
.sidenav-user__avatar img {
  width: 24px;
  height: 24px;
  border-radius: var(--radius-full);
  object-fit: cover;
  display: block;
}
/* Reuses the focus selector's initials badge — same fallback, same treatment. */
.sidenav-user__badge {
  width: 24px;
  height: 24px;
  border-radius: var(--radius-full);
  background: var(--accent-ring);
  color: var(--text);
}
.sidenav-user__generic {
  width: 22px;
  height: 22px;
  color: var(--text-light);
}
.sidenav-user__name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* The menu slides out beside the rail, anchored to the bottom, above the
   content area — so it is legible whether the rail is collapsed or expanded. */
.sidenav-user__menu {
  position: absolute;
  left: 100%;
  bottom: 0;
  margin-left: 6px;
  min-width: 200px;
  padding: 4px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--elev-2);
  z-index: 600;
  display: flex;
  flex-direction: column;
  visibility: hidden;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--dur-fast) var(--ease-out);
}
.sidenav-user__menu[data-open] {
  visibility: visible;
  opacity: 1;
  pointer-events: auto;
}

.sidenav-user__link {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 6px 8px;
  border: none;
  border-radius: var(--radius-sm);
  background: none;
  color: var(--text-muted);
  font-family: var(--font);
  font-size: var(--text-md);
  text-align: left;
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
}
.sidenav-user__link:hover,
.sidenav-user__link:focus-visible,
.sidenav-user__link.sidenav-active {
  background: var(--border-light);
  color: var(--text);
}

/* Legacy user info row — links to settings */
.sidenav-user-info { }
.sidenav-user-photo {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  object-fit: cover;
  flex-shrink: 0;
}
.sidenav-user-avatar {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: var(--border);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--text-muted);
  flex-shrink: 0;
}
.sidenav-username { font-size: var(--text-base); color: var(--text-muted); }
.sidenav-logout-form { margin: 0; }

/* Layout */
.main {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: var(--space-md);
  box-sizing: border-box;
  position: relative;
}

/* App mark — the owning app's mark on the pages it owns. Rendered from the
   contribution registry; absent on platform routes and on any app that
   registers no brand.

   It renders in the page-header icon slot (crm/partials/_page_icon.html),
   inline with the page's own heading and selectors: it reads as page furniture
   rather than as a banner above the page. There is deliberately no shell-level
   fallback into <main> — a stray first child lands wherever the page's own
   layout puts it, which on the detail grid is the top-right corner. A page
   without a header slot shows no mark until it grows one.

   Register the bare mark, not a lockup: at this size a wordmark is unreadable,
   and the app's name is already carried by its nav group. */
.app-mark {
  flex-shrink: 0;
  line-height: 0;
}

.app-mark img {
  /* Height-driven so any app's mark keeps its own aspect ratio. Half again the
     34px section icon it sits beside: a mark carries the app's identity and
     reads as undersized at icon parity. */
  height: 51px;
  width: auto;
  display: block;
}

.app-mark a {
  display: inline-block;
  transition: opacity var(--transition-fast);
}

.app-mark a:hover { opacity: 0.75; }

/* Decorative page motif — the owning app's artwork, pinned to the bottom-left
   corner of the viewport. Opt-in: only apps that register backdrops get one,
   and the asset arrives as an inline --app-page-motif on <body> (§4.6).

   A fixed pseudo-element of .main, painted with mix-blend-mode: multiply.
   Multiply is what makes this work at all: the motifs are photographs of black
   ink on white paper, so the paper multiplies away to nothing and only the ink
   lands. Two earlier attempts — a fixed div below the content layer, then a
   dimmed background-image — were both invisible in practice, because dimming
   ink to 8% on a white page leaves a whisper of grey that reads as nothing.
   Multiply lets the ink stay strong enough to see while text under it only
   darkens rather than being veiled.

   Anchored to the content edge, not the window edge: the sidenav is fixed and
   would cover a motif at left: 0. Sized off the viewport so it reads as a
   corner flourish at any window size rather than a picture someone placed. */
[data-app-motif] .main::after {
  content: "";
  position: fixed;
  /* One size, used for both dimensions and for the bleed, so the motif keeps
     its square aspect and the crop stays proportional at every window width. */
  --app-motif-size: min(39vw, 494px);
  --app-motif-bleed: calc(var(--app-motif-size) * -0.1);
  /* Bleeding a tenth off the anchored edge and the bottom makes it read as a
     crop of something larger rather than a stamp placed in the corner.

     Which corner is the app's call — motif artwork is often weighted to one
     side of its frame, and the wrong corner crowds the content column. The
     default hugs the content edge beside the rail; an app switches sides from
     its own theme by setting the three --app-motif-* tokens together. Geometry
     stays here: an app picks a corner, it does not re-declare the element. */
  left: var(--app-motif-left, calc(var(--sidenav-w) + var(--app-motif-bleed)));
  right: var(--app-motif-right, auto);
  bottom: var(--app-motif-bleed);
  width: var(--app-motif-size);
  height: var(--app-motif-size);
  background-image: var(--app-page-motif, none);
  background-repeat: no-repeat;
  background-position: var(--app-motif-anchor, left bottom);
  background-size: contain;
  mix-blend-mode: multiply;
  opacity: 0.13;
  pointer-events: none;
}

@media (max-width: 900px) {
  /* Nothing to spare in the corner on a narrow window. */
  [data-app-motif] .main::after { display: none; }
}

/* The motif shows wherever the content above it is transparent, so the
   full-height list surfaces say so explicitly rather than relying on none of
   them ever growing a background. The sticky table header keeps its opaque
   --bg: rows have to disappear behind it as they scroll. */
[data-app-motif] .table-panel-wrap,
[data-app-motif] .table-container,
[data-app-motif] .data-table,
[data-app-motif] .data-table tbody tr,
[data-app-motif] .data-table tbody td {
  background-color: transparent;
}

/* Page orientation icon — fixed to top-left of main area, matches sidenav icon */
.page-nav-icon {
  position: fixed;
  top: 10px;
  left: calc(var(--sidenav-w) + 10px);
  z-index: 400;
  pointer-events: none;
  opacity: 0.55;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
}

/* Page + info panel two-column layout */
/* Published-destination icons (crm/shared/partials/published_links.html) — where
   a conversation is live. Here rather than in detail.css because its two hosts
   load different stylesheets: the holon/person detail pages take detail.css, the
   conversation table takes table.css, and only base.css is on every page. A
   not-yet-public destination is dimmed rather than hidden: the operator still
   wants the link, but the strip must not read as "this is out there" when it is
   not. Icon sizing comes from .contact-icon-mini (table.css / detail.css). */
.published-links {
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
}
.published-links__link {
  display: inline-flex;
  color: var(--text-muted);
  text-decoration: none;
}
.published-links__link .contact-icon {
  width: 14px;
  height: 14px;
  vertical-align: middle;
}
.published-links__link:hover .contact-icon {
  color: var(--color-accent);
}
.published-links__link--private .contact-icon {
  opacity: 0.45;
}

/* A viewport-height page (kanban board, calendar, list+panel): it fills what is
   left of `main` and clips, so its own bottom edge — where the board's
   horizontal scrollbar lives — is the last visible row of the window.

   `flex: 1` + `min-height: 0`, not `height: 100%`. A percentage height is 100%
   of *main*, which is only the space actually available when this is main's
   sole child. It is not: the extension version banner renders above it, and a
   77px banner pushed the whole page 77px past the clipped bottom — taking the
   kanban scrollbar off-screen on every board (and it is `overflow-x: scroll`
   precisely so that bar is always there). Sized as a flex item it takes what is
   left over instead, whatever else main is carrying. */
.main:has(.page-with-panel) {
  padding: 0;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.page-with-panel {
  display: flex;
  flex: 1;
  min-height: 0;
  overflow: hidden;
}

.page-with-panel > *:first-child {
  flex: 1;
  min-width: 0;
}

/* Buttons. Tokenised on the tier-3 --btn-* tokens so a button re-accents
   with its app; destructive variants live in components/button.css. */
.btn {
  padding: var(--space-2) var(--space-4);
  background: var(--btn-bg);
  color: var(--btn-fg);
  border: 1px solid var(--btn-bg);
  border-radius: var(--btn-radius);
  font-size: var(--text-base);
  cursor: pointer;
  transition: background var(--transition-fast), border-color var(--transition-fast);

  /* vertically align the text and icon */
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
}

.export-btn {
  font-size: var(--text-sm);
  padding: 0.2rem 0.6rem;
  margin-left: auto;
  background: transparent;
  color: var(--text-muted);
  border-color: var(--border);
}
.btn:hover { background: var(--btn-bg-hover); border-color: var(--btn-bg-hover); color: var(--btn-fg); }
.btn-sm { padding: var(--space-xs) var(--space-sm); font-size: var(--text-base); }
.btn-save-wrapper {
  display: inline-block;
  cursor: not-allowed;
}
.btn-save-wrapper .btn:not(:disabled) {
  cursor: pointer;
}

/* Screen-reader-only text: extra context for icon controls and external links
   that would be noise on screen but is needed by assistive technology. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Status badges */
.status-badge {
  display: inline-block;
  padding: 2px 8px;
  border-radius: var(--radius-sm);
  font-size: var(--text-sm);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  background: var(--border-light);
  color: var(--text-muted);
}
.status-badge--warning {
  background: var(--warning-bg);
  color: var(--warning-color);
}
/* Background-job state chip — a rounded pill carrying a leading status dot.
   Colour tokens are the ones the IRIS pipeline rail already uses for these
   states (coherence/css/iris_console.css), so a list chip and the rail agree.
   The dot does the colour-shouting so the label can stay quiet and readable. */
.job-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 2px 9px 2px 7px;
  border-radius: var(--radius-full);
  border: 1px solid transparent;
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.02em;
  white-space: nowrap;
}
.job-chip__dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
  flex: 0 0 auto;
}
.job-chip--done {
  background: var(--success-bg);
  border-color: var(--success-border);
  color: var(--success-color);
}
.job-chip--error {
  background: var(--overdue-bg);
  border-color: var(--danger-border);
  color: var(--overdue-color);
}
/* Job finished, but its output waits on a person (pipeline_graph.WAITING_OPERATOR).
   Danger palette like --error: both mean the pipeline has stopped. */
.job-chip--waiting-operator {
  background: var(--overdue-bg);
  border-color: var(--danger-border);
  color: var(--overdue-color);
}
.job-chip--processing {
  background: var(--note-comment-bg);
  border-color: var(--note-comment-border);
  color: var(--note-comment-text);
}
.job-chip--processing .job-chip__dot {
  animation: job-chip-pulse 1.4s ease-in-out infinite;
}
.job-chip--queued {
  background: var(--surface-alt);
  border-color: var(--border);
  color: var(--text-muted);
}
@keyframes job-chip-pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50%      { opacity: 0.35; transform: scale(0.8); }
}
@media (prefers-reduced-motion: reduce) {
  .job-chip--processing .job-chip__dot { animation: none; }
}

/* Entity chip — avatar + name pill for a person or holon in a dense list.
   See crm/shared/partials/entity_chips.html; the coherence conversation header
   has its own larger, removable variant (.pchip). */
.entity-chips {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 0.3rem;
  align-items: center;
  justify-content: flex-end;
  min-width: 0;
}
.entity-chips__empty { color: var(--text-light); font-size: var(--text-base); }

.entity-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  /* One size up from the row's own type: these carry faces and names, which is
     the fastest way to recognise a conversation, so they earn the space. */
  max-width: 12.5rem;
  padding: 3px 11px 3px 3px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-full);
  font-size: var(--text-base);
}
.entity-chip__avatar {
  width: 1.5rem;
  height: 1.5rem;
  border-radius: 50%;
  object-fit: cover;
  display: block;
  flex: 0 0 auto;
}
.entity-chip__avatar--ph {
  display: grid;
  place-items: center;
  background: var(--surface-alt);
  color: var(--text-muted);
  font-size: var(--text-sm);
  font-weight: 700;
}
.entity-chip__name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.entity-chip--more {
  padding: 2px 9px;
  color: var(--text-muted);
  font-weight: 600;
}

/* Follow-up date colors */
.follow-up-overdue {
  color: var(--overdue-color);
  font-weight: 500;
}
.follow-up-today {
  color: var(--today-color);
  font-weight: 500;
}

/* Interest tag colours */
.interest-tag.interest-local-leader { background: var(--interest-leader-bg); color: white; }
.interest-tag.interest-local-catalyst { background: var(--interest-catalyst-bg); color: white; }
.interest-tag.interest-local-team { background: var(--accent); color: var(--text); }
.interest-tag.interest-ambassador { background: var(--interest-ambassador-bg); color: white; }
.interest-tag.interest-gathering-global-team { background: var(--holon-domain-bg); color: var(--holon-domain-text); }

/* Interest tags */
.interest-tag {
  display: inline-block;
  padding: 1px 6px;
  border-radius: var(--radius-sm);
  font-size: var(--text-xs);
  margin: 1px 2px;
  white-space: nowrap;
  background: var(--border-light);
  color: var(--text-muted);
}

/* Interest tags under person name */
.person-interest-tags {
  margin-top: 2px;
}

/* Membership badges — colored by holon type, see .type-* classes below.
   The cell's own `white-space: normal` lives in table.css beside the other
   `.data-table td.*` overrides: at (0,1,0) here it lost to
   `.data-table td { white-space: nowrap }` and the badges never wrapped. */
.membership-badge {
  display: inline-block;
  padding: 1px 6px;
  border-radius: var(--radius-sm);
  font-size: var(--text-xs);
  margin: 1px 2px;
  white-space: nowrap;
  background: var(--border-light);
  color: var(--text-muted);
}

/* Tags */
.tag {
  display: inline-block;
  padding: 2px 8px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font-size: var(--text-base);
  color: var(--text-muted);
  margin: 2px;
}

/* List header */
.list-header {
  margin-bottom: var(--space-md);
}
.list-header--flex {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
}

/* Filters */
.filters { display: flex; gap: var(--space-sm); align-items: center; flex-wrap: wrap; }


/* Toggle group — pill style */
.toggle-group {
  display: inline-flex;
  background: var(--border-light);
  border-radius: var(--radius-lg);
  padding: 3px;
}
.toggle-btn {
  padding: 5px 16px;
  background: transparent;
  border: none;
  border-radius: var(--radius-lg);
  font-family: var(--font);
  font-size: var(--text-base);
  color: var(--text-muted);
  cursor: pointer;
  text-decoration: none;
  transition: background var(--dur-base) var(--ease-out), color var(--dur-base) var(--ease-out), box-shadow var(--dur-base) var(--ease-out);
}
.toggle-btn:hover {
  color: var(--text);
}
.toggle-btn.active {
  background: var(--surface);
  color: var(--text);
  font-weight: 500;
  box-shadow: var(--elev-1);
}
/* Icon-only variant: narrower horizontal padding */
.toggle-btn--icon {
  padding-left: 10px;
  padding-right: 10px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0;
}
/* Mine filter button: avatar photo or initials */
.filter-mine-avatar {
  width: 16px;
  height: 16px;
  border-radius: 50%;
  object-fit: cover;
  display: block;
  pointer-events: none;
}
.filter-mine-initials {
  font-size: 9px;
  font-weight: 700;
  line-height: 1;
  pointer-events: none;
}
/* Focus filter button: holon logo or initial badge */
.filter-focus-logo {
  width: 16px;
  height: 16px;
  border-radius: 50%;
  object-fit: cover;
  display: block;
  pointer-events: none;
}
.filter-focus-initials {
  font-size: 9px;
  font-weight: 700;
  line-height: 1;
  pointer-events: none;
}
/* All/Mine sliding switch — single binary toggle (groups icon off, person icon on) */
.toggle-switch {
  position: relative;
  width: 54px;
  height: var(--toolbar-h);
  border-radius: calc(var(--toolbar-h) / 2);
  background: var(--border);
  border: none;
  padding: 0;
  flex-shrink: 0;
  cursor: pointer;
  transition: background var(--dur-base) var(--ease-out);
}
.toggle-switch--on {
  background: var(--accent);
}
.toggle-switch__knob {
  position: absolute;
  top: 3px;
  left: 3px;
  width: calc(var(--toolbar-h) - 6px);
  height: calc(var(--toolbar-h) - 6px);
  border-radius: 50%;
  background: var(--surface);
  color: var(--text-muted);
  box-shadow: var(--elev-1);
  display: flex;
  align-items: center;
  justify-content: center;
  transition: transform var(--dur-base) var(--ease-out), color var(--dur-base) var(--ease-out);
  pointer-events: none;
}
.toggle-switch--on .toggle-switch__knob {
  transform: translateX(calc(54px - var(--toolbar-h)));
  color: var(--text);
}
.toggle-switch__icon {
  display: none;
  align-items: center;
  justify-content: center;
}
.toggle-switch__icon--off {
  display: flex;
}
.toggle-switch--on .toggle-switch__icon--off {
  display: none;
}
.toggle-switch--on .toggle-switch__icon--on {
  display: flex;
}
.toggle-switch__icon .filter-mine-avatar {
  width: 21px;
  height: 21px;
}
.toggle-switch__icon .filter-mine-initials {
  font-size: 10px;
}
/* List ⇄ Kanban view switch: a two-segment pill of icon links. Distinct from
   .toggle-switch (a binary on/off knob) because this is a segmented mode
   selector showing both options at once, with the active one highlighted. */
.view-toggle {
  display: inline-flex;
  align-items: center;
  border: 1px solid var(--border);
  border-radius: var(--radius-full);
  overflow: hidden;
  background: var(--surface-alt);
  flex-shrink: 0;
}
.view-toggle__opt {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--toolbar-h);
  height: var(--toolbar-h);
  color: var(--text-light);
  transition: background var(--dur-base) var(--ease-out), color var(--dur-base) var(--ease-out);
}
.view-toggle__opt:hover { background: var(--border-light); color: var(--text-muted); }
.view-toggle__opt--active { background: var(--surface); color: var(--text); }
.view-toggle__opt svg { display: block; }
.search-input, .filter-select {
  padding: var(--space-sm) var(--space-md);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  font-size: var(--text-base);
  background: var(--surface);
  color: var(--text);
  outline: none;
}
.search-input:focus, .filter-select:focus {
  border-color: var(--accent);
}
.search-input {
  width: 260px;
  height: var(--toolbar-h);
  border-radius: calc(var(--toolbar-h) / 2);
  box-sizing: border-box;
  padding-left: 70px;
}

/* Empty states */
.empty-state {
  color: var(--text-light);
  text-align: center;
  padding: 0;
}
/* Hijack impersonation bar — merged into layout rule above */
.hijack-bar {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-md);
  padding: var(--space-sm) var(--space-md);
  background: var(--warning-bg);
  border-bottom: 2px solid var(--warning-btn);
  color: var(--warning-color);
  font-size: var(--text-md);
  flex-shrink: 0;
}
.hijack-release-btn {
  padding: var(--space-xs) var(--space-sm);
  background: var(--warning-btn);
  color: white;
  border: none;
  border-radius: var(--radius);
  font-size: var(--text-base);
  font-family: var(--font);
  cursor: pointer;
  font-weight: 500;
}
.hijack-release-btn:hover {
  background: var(--warning-btn-hover);
}

/* Holon type colours — applied to badges, pills, nav chips */
.holon-type-organisation,
.status-option:has(input:checked).holon-type-organisation {
  background: var(--holon-org-bg); color: var(--holon-org-text);
}
.holon-type-domain,
.status-option:has(input:checked).holon-type-domain {
  background: var(--holon-domain-bg); color: var(--holon-domain-text);
}
.holon-type-event,
.status-option:has(input:checked).holon-type-event {
  background: var(--holon-event-bg); color: var(--holon-event-text);
}
.holon-type-camp,
.status-option:has(input:checked).holon-type-camp {
  background: var(--holon-camp-bg); color: var(--holon-camp-text);
}
/* Product type tokens kept here intentionally: these CSS classes are applied by
   platform templates (badges, status chips, kanban cards) for any installed app's
   holon types. They are global UI tokens, not product-owned presentation. */
.holon-type-local_gathering,
.status-option:has(input:checked).holon-type-local_gathering {
  background: var(--holon-local-gathering-bg); color: var(--holon-local-gathering-text);
}
.holon-type-coherence_conversation,
.status-option:has(input:checked).holon-type-coherence_conversation {
  background: var(--holon-coherence-conversation-bg); color: var(--holon-coherence-conversation-text);
}
.holon-type-experience,
.status-option:has(input:checked).holon-type-experience {
  background: var(--holon-experience-bg); color: var(--holon-experience-text);
}
.holon-type-outreach-network,
.status-option:has(input:checked).holon-type-outreach-network {
  background: var(--holon-outreach-network-bg); color: var(--holon-outreach-network-text);
}
.holon-type-outreach-list,
.status-option:has(input:checked).holon-type-outreach-list {
  background: var(--holon-outreach-list-bg); color: var(--holon-outreach-list-text);
}
.holon-type-quest,
.status-option:has(input:checked).holon-type-quest {
  background: var(--holon-quest-bg); color: var(--holon-quest-text);
}
.holon-type-mission,
.status-option:has(input:checked).holon-type-mission {
  background: var(--holon-mission-bg); color: var(--holon-mission-text);
}

/* Tree icon contrast — invert dark icons on dark type backgrounds */
.tree-icon.holon-type-domain img,
.tree-icon.holon-type-event img,
.holon-type-icon.holon-type-domain img,
.holon-type-icon.holon-type-event img {
  filter: brightness(0) invert(1);
}

/* Type badges */
.type-badge {
  display: inline-block;
  padding: 2px 8px;
  border-radius: var(--radius-lg);
  font-size: var(--text-sm);
  font-weight: 500;
}

/* Relationship badges */
.rel-badge {
  display: inline-block;
  padding: 1px 6px;
  border-radius: var(--radius-md);
  font-size: var(--text-xs);
  margin: 1px 2px;
  background: var(--border-light);
  color: var(--text-muted);
}


/* Tree component (sidebar + explore page) */
.explore-tree {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  max-width: 700px;
}
.tree-section-label {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 12px 16px 6px;
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-muted);
  cursor: pointer;
  user-select: none;
}
.tree-section-label:hover { color: var(--text); }
.tree-section-label:not(:first-child) {
  border-top: 1px solid var(--border-light);
  margin-top: 4px;
}
.tree-section-label .tree-chevron { width: 14px; height: 14px; }
.tree-row {
  display: flex;
  align-items: center;
  padding: 4px 12px;
  gap: 6px;
  transition: background var(--dur-fast) var(--ease-out);
}
.tree-row:hover { background: var(--border-light); }
.depth-1 { padding-left: 36px; }
.depth-2 { padding-left: 60px; }
.depth-3 { padding-left: 84px; }
.depth-4 { padding-left: 108px; }
.depth-5 { padding-left: 132px; }
.tree-link {
  display: flex;
  align-items: center;
  gap: 6px;
  flex: 1;
  min-width: 0;
  text-decoration: none;
  color: inherit;
}
.tree-chevron {
  width: 18px;
  height: 18px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius);
  cursor: pointer;
  color: var(--text-light);
  flex-shrink: 0;
  transition: transform var(--dur-base) var(--ease-out), color var(--dur-fast) var(--ease-out);
  user-select: none;
}
.tree-chevron:hover { color: var(--text-muted); }
.tree-chevron.open { transform: rotate(90deg); }
.tree-spacer { width: 18px; flex-shrink: 0; }
.tree-icon,
.holon-type-icon {
  width: 22px;
  height: 22px;
  border-radius: var(--radius-sm);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.tree-icon img,
.holon-type-icon img { width: 14px; height: 14px; }
.tree-icon-neutral { background: var(--border-light); }
.tree-name {
  flex: 1;
  min-width: 0;
  font-size: var(--text-md);
  color: var(--text);
  text-decoration: none;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.tree-link:hover .tree-name { color: var(--accent); }
.tree-right {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-left: auto;
  flex-shrink: 0;
}
.tree-count { font-size: var(--text-sm); color: var(--text-light); }
.tree-count a { color: var(--text-muted); }
.tree-count a:hover { color: var(--accent); }
.tree-focus {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border-radius: var(--radius);
  opacity: 0;
  transition: opacity var(--dur-base) var(--ease-out);
  flex-shrink: 0;
}
.tree-row:hover .tree-focus { opacity: 0.5; }
.tree-focus:hover { opacity: 1 !important; background: var(--border); }
.tree-focus img { width: 14px; height: 14px; }
.tree-children { display: none; }
.tree-children.open { display: block; }
.tree-empty { padding: 12px 16px; color: var(--text-light); font-size: var(--text-base); }

/* Sidebar tree link (Journeys label) */
.tree-section-label a { color: inherit; text-decoration: none; }
.tree-section-label a:hover { text-decoration: underline; }

/* Layout utilities */
.hidden { display: none; }
.d-inline { display: inline; }
.cursor-default { cursor: default; }
.cursor-pointer { cursor: pointer; }
.text-sm { font-size: 0.85em; }

/* Status tags — used for success/fail results */
.tag-success { background: var(--tag-success-bg); color: var(--tag-success-color); }
.tag-fail    { background: var(--tag-fail-bg); color: var(--tag-fail-color); }

/* Agent textarea */
.agent-textarea { min-height: 12rem; width: 100%; box-sizing: border-box; }

/* Agent schedule card */
.schedule-card { margin-bottom: 1.5rem; padding: 1rem; border: 1px solid var(--border); border-radius: var(--radius); }
.schedule-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 0.75rem; }
.schedule-meta { display: flex; align-items: center; gap: var(--space-sm); }
.schedule-description { margin: 0.25rem 0 0.75rem; font-size: 0.85em; color: var(--text-muted); }

/* Task result cell */
.task-result-cell { word-break: break-word; white-space: pre-wrap; font-size: 0.85em; }

/* Error / no-access page */
.error-page { max-width: 480px; margin: 120px auto; text-align: center; }
.error-page h1 { font-size: var(--text-2xl); margin-bottom: 1rem; }
.error-page p { color: var(--text-muted); margin-bottom: 2rem; }
.error-page a { color: var(--accent); }

/* ── Focus-holon dropdown (global — used on chat, people, orgs pages) ─── */
.toggle-focus {
  position: relative;
  display: inline-flex;
}

.toggle-btn--focus {
  display: inline-flex;
  align-items: center;
  gap: 3px;
}

.toggle-focus__label {
  max-width: 160px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.toggle-focus__chevron {
  flex-shrink: 0;
  opacity: 0.4;
  transition: transform var(--dur-base) var(--ease-out), opacity var(--dur-base) var(--ease-out);
}

.toggle-focus.open .toggle-focus__chevron {
  transform: rotate(180deg);
  opacity: 0.7;
}

.toggle-focus__menu {
  display: none;
  position: absolute;
  top: calc(100% + 8px);
  left: 0;
  min-width: 220px;
  max-width: 300px;
  max-height: 360px;
  overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--elev-3);
  z-index: 200;
  padding: 6px 0;
}

.toggle-focus.open .toggle-focus__menu {
  display: block;
  animation: focus-menu-in 0.15s ease-out;
}

@keyframes focus-menu-in {
  from { opacity: 0; transform: translateY(-6px) scale(0.97); }
  to   { opacity: 1; transform: translateY(0)    scale(1); }
}

.toggle-focus__menu::before {
  content: "";
  position: absolute;
  top: -5px;
  left: 14px;
  transform: rotate(45deg);
  width: 10px;
  height: 10px;
  background: var(--surface);
  border-top: 1px solid var(--border);
  border-left: 1px solid var(--border);
}

.toggle-focus__group-label {
  font-size: var(--text-xs);
  font-weight: 700;
  color: var(--text-light);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  padding: 8px 14px 4px;
  pointer-events: none;
}

.toggle-focus__group-label:not(:first-child) {
  border-top: 1px solid var(--border-light);
  margin-top: 4px;
  padding-top: 10px;
}

.toggle-focus__item {
  display: block;
  width: 100%;
  padding: 7px 14px;
  border: none;
  background: none;
  font-family: inherit;
  font-size: var(--text-base);
  color: var(--text);
  text-align: left;
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  border-radius: 0;
}

.toggle-focus__item:hover {
  background: var(--bg);
}

.toggle-focus__item--active {
  font-weight: 600;
  color: var(--accent);
  background: var(--bg);
}


.step-access-chip {
  display: inline-block;
  font-size: var(--text-xs);
  font-weight: 600;
  padding: 0.1rem 0.45rem;
  border-radius: var(--radius-full);
  background: #e3f2fd;
  color: #1565c0;
  white-space: nowrap;
  width: fit-content;
}

/* A flag present in config but not the boolean true, so no reader acts on it. */
.step-access-chip--unset {
  background: var(--surface-alt);
  color: var(--text-muted);
  border: 1px dashed var(--border);
  font-weight: 500;
}

/* ── @mention autocomplete dropdown ── */
.mention-dropdown {
  list-style: none;
  background: var(--bg, #fff);
  border: 1px solid var(--border, #ddd);
  border-radius: var(--radius-md);
  box-shadow: var(--elev-2);
  max-height: 240px;
  overflow-y: auto;
  padding: 0.25rem 0;
}

.mention-dropdown__item {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.4rem 0.75rem;
  cursor: pointer;
  font-size: var(--text-md);
  color: var(--text);
}

.mention-dropdown__item:hover,
.mention-dropdown__item--active {
  background: var(--accent-ring, rgba(152,155,75,0.1));
}

.mention-dropdown__badge {
  margin-left: auto;
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 0.1rem 0.4rem;
  border-radius: var(--radius-full);
  background: var(--text-muted, #aaa);
  color: #fff;
  flex-shrink: 0;
}

.mention-dropdown__item--person .mention-dropdown__badge { background: #4a7c59; }
.mention-dropdown__item--holon  .mention-dropdown__badge { background: var(--holon-org-text, #192F2B); }

/* ── @mention rendered in note body ── */
.note-mention {
  display: inline-block;
  font-size: 0.8em;
  font-weight: 600;
  padding: 0.05em 0.4em;
  border-radius: var(--radius-full);
  white-space: nowrap;
}

.note-mention--person {
  background: #d4e5d0;
  color: #192F2B;
}

.note-mention--holon {
  background: var(--holon-org-bg, #d4e5d0);
  color: var(--holon-org-text, #192F2B);
}

/* ── Focus selector failure banner ──
   Shown by focus_selector.js when a focus change cannot be applied, so a
   failed change is never mistaken for a successful one. */
.focus-selector-error {
  position: fixed;
  top: 16px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 2000;
  max-width: 90vw;
  padding: 0.6em 1em;
  border-radius: var(--radius-md);
  background: var(--danger-bg);
  color: var(--danger-dark);
  border: 1px solid var(--danger-border);
  font-weight: 600;
  box-shadow: var(--elev-2);
}
.focus-selector-error[hidden] {
  display: none;
}

/* ---------------------------------------------------------------------------
   Extension-version banner
   Moved out of an inline <style> in web/app/templates/shell/base.html — every
   page inherits that template, so the rules were re-sent on every response and
   could not be cached. Paired with crm/js/extension_version_banner.js.
   --------------------------------------------------------------------------- */
.ext-version-banner {
  display: none;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin: 0 0 16px;
  padding: 12px 14px;
  border: 1px solid var(--ext-banner-border);
  border-radius: var(--radius-md);
  background: var(--ext-banner-bg);
  color: var(--ext-banner-text);
  font-size: var(--text-md);
  line-height: 1.4;
}
.ext-version-banner.is-visible {
  display: flex;
}
.ext-version-banner__text strong {
  color: var(--ext-banner-text-strong);
}
.ext-version-banner__action {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 8px 12px;
  border-radius: var(--radius-md);
  border: 1px solid var(--ext-banner-action-border);
  background: var(--surface);
  color: var(--ext-banner-text);
  text-decoration: none;
  font-weight: 600;
  white-space: nowrap;
}
.ext-version-banner__action:hover {
  background: var(--ext-banner-action-hover);
}
@media (max-width: 720px) {
  .ext-version-banner {
    flex-direction: column;
    align-items: flex-start;
  }
}
}
