/* RRB-SHARED v0.9.0 — do not edit project copy; sync from /opt/stacks/ops/shared */
/* RRB UX Patterns — composite behavioral patterns
 * Owner: shared (do not edit project copies)
 * Sync: /opt/stacks/ops/shared/sync-shared-assets.sh
 */

/* === Toast === */
:root {
  --rrb-z-toast: 2147483000;
}
.toast-stack {
  position: fixed;
  top: 16px;
  right: 16px;
  z-index: var(--rrb-z-toast) !important;
  display: flex;
  flex-direction: column;
  gap: var(--sp-sm, 8px);
  max-width: 360px;
  pointer-events: none;
  isolation: isolate;
}
.toast-container {
  z-index: var(--rrb-z-toast) !important;
  isolation: isolate;
}
.toast {
  pointer-events: auto;
  background: var(--color-card);
  border: 1px solid var(--color-border);
  border-radius: var(--r-card, 12px);
  padding: var(--sp-md, 12px) var(--sp-lg, 16px);
  font-size: var(--fs-md, 14px);
  /* legacy primitives .toast supplied weight 500 / line-height 1.4 via cascade; canonical file must be self-contained so frozen projects render identically after sync */
  font-weight: 500;
  line-height: 1.4;
  box-shadow: 0 2px 6px rgba(0,0,0,0.08);
  display: flex;
  gap: var(--sp-sm, 8px);
  align-items: center;
  z-index: var(--rrb-z-toast);
  animation: toast-in 160ms ease-out;
}
.toast-stack > .toast,
.toast-container > .toast {
  position: relative;
  top: auto;
  right: auto;
  z-index: 1;
}
.toast[data-type="success"] { border-left: 4px solid var(--color-accent); }
.toast[data-type="error"]   { border-left: 4px solid var(--color-danger); }
.toast[data-type="warn"]    { border-left: 4px solid var(--color-warning); }
.toast[data-type="info"]    { border-left: 4px solid var(--color-primary); }
.toast[data-type="error"] { align-items: flex-start; }
.toast--leaving { animation: toast-out 140ms ease-in forwards; }
@keyframes toast-in  { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: none; } }
@keyframes toast-out { to   { opacity: 0; transform: translateY(-6px); } }
.toast__status {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  min-height: 22px;
  padding: 2px 8px;
  border: 1px solid var(--border, var(--color-border));
  border-radius: var(--r-pill);
  background: var(--surface-muted, var(--color-card));
  color: var(--text, var(--color-text));
  font: 600 11px/1.3 var(--font, system-ui, sans-serif);
  white-space: nowrap;
}
.toast[data-type="success"] .toast__status {
  background: var(--success-50, var(--color-card));
  color: var(--success-text, var(--color-text));
  border-color: var(--success-200, var(--color-border));
}
.toast[data-type="error"] .toast__status {
  background: var(--danger-50, var(--color-card));
  color: var(--danger-text, var(--color-text));
  border-color: var(--danger-200, var(--color-border));
}
.toast[data-type="warn"] .toast__status {
  background: var(--warning-50, var(--color-card));
  color: var(--warning-text, var(--color-text));
  border-color: var(--warning-200, var(--color-border));
}
.toast[data-type="info"] .toast__status {
  background: var(--primary-50, var(--color-card));
  color: var(--primary-700, var(--color-text));
  border-color: var(--primary-200, var(--color-border));
}
.toast__msg { flex: 1; min-width: 0; overflow-wrap: anywhere; }
.toast[data-type="error"] .toast__msg { align-self: flex-start; }
.toast__actions {
  display: inline-flex;
  flex: 0 0 auto;
  align-items: center;
  gap: var(--sp-xs, 4px);
}
.toast__close {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 32px;
  min-height: 32px;
  border: 0;
  background: transparent;
  color: var(--color-text-muted, var(--text-muted));
  font-size: 16px;
  line-height: 1;
  padding: 0 4px;
  cursor: pointer;
  border-radius: var(--r-btn, 12px);
}
.toast__close:hover { color: var(--color-text, var(--text)); }
.toast__close:focus-visible { outline: 2px solid var(--color-primary, var(--primary)); outline-offset: 1px; }
.toast__action {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 32px;
  border: 0;
  background: transparent;
  color: var(--color-primary, var(--primary));
  font: 600 13px/1.2 var(--font);
  padding: 0 8px;
  cursor: pointer;
  border-radius: var(--r-btn, 12px);
  text-decoration: underline;
}
.toast__action:focus-visible { outline: 2px solid var(--color-primary, var(--primary)); outline-offset: 1px; }
@media (max-width: 768px) {
  .toast__close,
  .toast__action { min-width: 44px; min-height: 44px; }
}
@media (max-width: 480px) {
  .toast-stack { left: 8px; right: 8px; max-width: none; top: 8px; }
}

/* === Copyable error details ===
   Status-first: the existing visible error/warning badge is the default
   trigger, avoiding a duplicate icon and table column. Icon-only remains an
   explicit fallback when no meaningful status label exists. */
.rrb-error-detail-trigger {
  min-height: 32px;
  cursor: pointer;
  touch-action: manipulation;
}
.rrb-error-detail-trigger:hover {
  text-decoration: underline;
  text-underline-offset: 2px;
}
.rrb-error-detail-trigger:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 2px;
}
/* Self-contained shell so the small `error-details` capability also works in
   intentionally non-Framework pages without importing all primitives/tokens. */
.rrb-error-details-popover {
  position: fixed;
  z-index: 1300;
  max-width: min(420px, calc(100vw - 16px));
  padding: var(--sp-sm, 8px) var(--sp-md, 12px);
  border-radius: var(--r-btn, 6px);
  background: var(--text, #1c2a44);
  color: #fff;
  box-shadow: var(--e1, 0 2px 8px rgba(28, 42, 68, 0.18));
  pointer-events: none;
  opacity: 0;
  transition: opacity 150ms ease;
  font: 500 12px/1.4 var(--font, system-ui, sans-serif);
}
.rrb-error-details-popover.is-open {
  pointer-events: auto;
  opacity: 1;
}
.rrb-error-indicator {
  appearance: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 32px;
  min-height: 32px;
  padding: var(--sp-xs, 4px);
  border: 1px solid transparent;
  border-radius: var(--r-btn, 6px);
  background: transparent;
  color: var(--danger-text, #991b1b);
  font: inherit;
  line-height: 1;
  cursor: pointer;
  touch-action: manipulation;
}
.rrb-error-indicator:hover {
  border-color: var(--danger-200, #fecaca);
  background: var(--danger-50, #fef2f2);
  text-decoration: none;
}
.rrb-error-indicator:focus-visible {
  outline: 2px solid var(--danger, #dc2626);
  outline-offset: 2px;
}
.rrb-error-details {
  display: grid;
  gap: var(--sp-xs, 4px);
  min-width: min(240px, calc(100vw - 48px));
}
.rrb-error-details__text {
  display: block;
  max-height: 12rem;
  overflow: auto;
  overflow-wrap: anywhere;
  white-space: pre-wrap;
  user-select: text;
  font: 500 var(--fs-xs, 12px)/1.5 var(--font-mono, ui-monospace, monospace);
}
.rrb-error-details__status {
  color: var(--gray-200, #e5e7eb);
  font: 500 var(--fs-xs, 12px)/1.4 var(--font, system-ui, sans-serif);
}
@media (max-width: 768px), (hover: none) {
  .rrb-error-detail-trigger {
    min-height: 44px;
  }
  .rrb-error-indicator {
    min-width: 44px;
  }
}

/* === Modal shell === */
.rrb-modal {
  border: none;
  border-radius: 8px;
  background: var(--color-card);
  padding: 0;
  display: flex;
  flex-direction: column;
  /* Re-assert the UA modal centering: a project-level `* { margin: 0 }` reset
     beats the UA `dialog:modal { margin: auto }`, collapsing the dialog to
     inset:0 (top-left). This class selector wins over `*` and recentres it. */
  margin: auto;
  max-width: 480px;
  width: calc(100vw - 32px);
  max-height: calc(100dvh - 32px);
  overflow: hidden;
  box-shadow: 0 24px 60px rgba(28,42,68,0.18);
}
.rrb-modal::backdrop { background: rgba(0,0,0,0.4); }
/* Entrance: a <dialog> flips display on showModal(), so a CSS *transition* on
   [open] never fires — a keyframe *animation* on [open] does. Entrance only;
   close stays instant (native dialog limitation). 240ms = overlay tier. */
.rrb-modal[open] { animation: rrb-modal-in 240ms var(--ease); }
.rrb-modal[open]::backdrop { animation: rrb-modal-backdrop-in 160ms ease-out; }
@keyframes rrb-modal-in {
  from { opacity: 0; transform: translateY(8px) scale(.97); }
  to   { opacity: 1; transform: none; }
}
@keyframes rrb-modal-backdrop-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .rrb-modal[open], .rrb-modal[open]::backdrop { animation: none; }
}
.rrb-modal__header {
  padding: 16px 20px;
  border-bottom: 1px solid var(--color-border);
  font-weight: 600;
  font-size: 16px;
  display: grid;
  grid-template-columns: minmax(0, 1fr) 36px;
  gap: 12px;
  align-items: center;
  flex: 0 0 auto;
}
.rrb-modal__title {
  min-width: 0;
  overflow-wrap: anywhere;
  line-height: 1.25;
}
.rrb-modal__close {
  width: 36px;
  height: 36px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--surface);
  border: 1px solid var(--color-border);
  border-radius: 6px;
  padding: 0;
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  color: var(--color-text-muted);
}
.rrb-modal__close:hover { color: var(--color-text); background: var(--surface-muted); }
.rrb-modal__close:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}
.rrb-modal__body {
  padding: 20px;
  font-size: 14px;
  line-height: 1.5;
  overflow: auto;
  min-height: 0;
}
.rrb-modal__footer {
  padding: 12px 20px;
  border-top: 1px solid var(--color-border);
  display: flex;
  gap: 8px;
  justify-content: flex-end;
  flex: 0 0 auto;
}
@media (max-width: 480px) {
  .rrb-modal { width: 100vw; max-width: 100vw; border-radius: 0; max-height: 100dvh; }
  .rrb-modal__footer { flex-direction: column-reverse; }
  .rrb-modal__footer .btn { width: 100%; min-height: 44px; }
}

/* === Confirm modal danger variant === */
.rrb-modal[data-danger="true"] .rrb-modal__header { color: var(--color-danger); }

/* === Action menu === */
.rrb-menu {
  position: fixed;
  width: max-content;
  min-width: min(180px, calc(100vw - 16px));
  max-width: calc(100vw - 16px);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-card);
  box-shadow: var(--e2);
  padding: 4px 0;
  z-index: 900;
}
.rrb-menu__item {
  display: block;
  width: 100%;
  text-align: left;
  background: transparent;
  border: 0;
  padding: 8px 16px;
  font-size: 14px;
  cursor: pointer;
  min-height: 44px;
}
.rrb-menu__item:focus-visible { outline: 2px solid var(--primary); outline-offset: -2px; }
.rrb-menu__item:hover:not([disabled]) { background: var(--surface-muted); }
.rrb-menu__item[disabled] { color: var(--text-muted); cursor: not-allowed; }
.rrb-menu__item[data-danger="true"] { color: var(--danger-text); }
.rrb-menu__label { display: block; }
.rrb-menu__desc {
  display: block;
  margin-top: 2px;
  font-size: 12px;
  line-height: 1.35;
  color: var(--text-muted);
}
.rrb-menu__item[data-has-description="true"] { padding-top: 10px; padding-bottom: 10px; }
@media (hover: none) {
  .rrb-menu__item { min-height: 44px; }
}

/* === Upload dropzone === */
.rrb-upload {
  border: 2px dashed var(--color-border);
  border-radius: 8px;
  padding: 24px;
  text-align: center;
  cursor: pointer;
  transition: border-color 120ms, background 120ms;
}
.rrb-upload:hover, .rrb-upload[data-dragover="true"] {
  border-color: var(--color-primary);
  background: var(--color-bg);
}
.rrb-upload__input { display: none; }
.rrb-upload__hint { color: var(--color-text-muted); font-size: 13px; margin-top: 4px; }

/* === Photo grid with delete-X === */
.rrb-photo-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
  gap: 8px;
}
.rrb-photo-grid__item {
  position: relative;
  aspect-ratio: 1;
  border-radius: 4px;
  overflow: hidden;
  background: var(--color-bg);
}
.rrb-photo-grid__item img,
.rrb-photo-grid__item video { width: 100%; height: 100%; object-fit: cover; }
.rrb-photo-grid__delete {
  position: absolute;
  top: 4px;
  right: 4px;
  width: 24px;
  height: 24px;
  border-radius: 12px;
  border: 0;
  background: rgba(0,0,0,0.6);
  color: white;
  cursor: pointer;
  font-size: 14px;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
}
.rrb-photo-grid__delete:hover { background: var(--color-danger); }
@media (hover: none) {
  .rrb-photo-grid__delete { width: 32px; height: 32px; border-radius: 16px; font-size: 16px; }
}

/* === Save bar === */
.rrb-savebar {
  position: sticky;
  bottom: 0;
  left: 0;
  right: 0;
  background: var(--color-card);
  border-top: 1px solid var(--color-border);
  padding: 12px 16px;
  display: none;
  gap: 8px;
  justify-content: flex-end;
  z-index: 50;
}
.rrb-savebar[data-dirty="true"] { display: flex; }
@media (max-width: 480px) {
  .rrb-savebar { flex-direction: column-reverse; padding: 12px; }
  .rrb-savebar .btn { width: 100%; min-height: 44px; }
}

/* === Search & filter facet === */
.rrb-search-facet {
  display: flex;
  flex-direction: column;
  gap: var(--sp-sm);
}
.rrb-search-facet .search-bar {
  width: 100%;
}
.rrb-search-facet[data-loading="true"] .search-bar {
  border-color: var(--color-primary);
}
.rrb-search-results[aria-busy="true"] {
  opacity: 0.72;
}
.rrb-search-status {
  min-height: 18px;
  color: var(--color-text-muted);
  font-size: var(--fs-sm);
}
/* On initial render / cleared search the status node is empty; without this it
   still reserves its 18px row and shows a blank grey strip under the picker. */
.rrb-search-status:empty { min-height: 0; display: none; }
/* contactPicker dropdown items (rendered by ux/contact-picker.js) */
.cp-item {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  width: 100%;
  padding: var(--sp-sm) var(--sp-md);
  background: none;
  border: 0;
  border-bottom: 1px solid var(--border);
  text-align: left;
  font: inherit;
  cursor: pointer;
}
.cp-item:last-child {
  border-bottom: 0;
}
.cp-item:hover,
.cp-item:focus,
.cp-item.cp-active {
  background: var(--surface-muted);
}
.cp-item.cp-active { outline: 0; }
.cp-name {
  font-weight: 600;
}
.cp-meta {
  color: var(--color-text-muted);
  font-size: var(--fs-sm);
}
.cp-empty,
.cp-stale {
  padding: var(--sp-sm) var(--sp-md);
  color: var(--color-text-muted);
  font-size: var(--fs-sm);
}
/* contactPicker float-mode panel chrome — mirrors .pp-results exactly (same tokens)
   so the lifted panel has a consistent shadow/border when reparented onto <body>/<dialog>. */
.cp-float {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-card);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
  max-height: 280px;
  overflow-y: auto;
  z-index: 1100;
}
.cp-float[hidden] {
  display: none;
}
/* productPicker dropdown (rendered by ux/product-picker.js) — sibling of cp-*,
   plus a self-contained floating panel so the dropdown can be lifted onto <body>
   (float mode) and escape an overflow:auto / transformed table ancestor.
   Item-level rules are scoped under .pp-results so they never collide with an
   unrelated project-local `.pp-*` component (e.g. inventory's legacy
   components/product-picker.js, which uses .pp-item/.pp-name on the same page). */
.pp-results {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-card);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
  max-height: 280px;
  overflow-y: auto;
  z-index: 1100;
}
.pp-results[hidden] {
  display: none;
}
.pp-results .pp-item {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  width: 100%;
  padding: var(--sp-sm) var(--sp-md);
  background: none;
  border: 0;
  border-bottom: 1px solid var(--border);
  text-align: left;
  font: inherit;
  cursor: pointer;
}
.pp-results .pp-item:last-child {
  border-bottom: 0;
}
.pp-results .pp-item:hover,
.pp-results .pp-item:focus,
.pp-results .pp-item.pp-active {
  background: var(--surface-muted);
}
.pp-results .pp-name {
  font-weight: 600;
}
.pp-results .pp-meta {
  color: var(--color-text-muted);
  font-size: var(--fs-sm);
}
.pp-results .pp-empty,
.pp-results .pp-stale {
  padding: var(--sp-sm) var(--sp-md);
  color: var(--color-text-muted);
  font-size: var(--fs-sm);
}
/* autocomplete — generic widget (ux/autocomplete.js) built on searchFacet +
   attachTypeahead. Item chrome mirrors .cp-item; panel chrome mirrors .cp-float.
   Selectors are NOT scoped under a wrapper class so the panel can be floated
   onto <body>/<dialog> in float mode (same pattern as contactPicker). */
.rrb-ac-item {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  width: 100%;
  padding: var(--sp-sm) var(--sp-md);
  background: none;
  border: 0;
  border-bottom: 1px solid var(--border);
  text-align: left;
  font: inherit;
  cursor: pointer;
}
.rrb-ac-item:last-child {
  border-bottom: 0;
}
.rrb-ac-item:hover,
.rrb-ac-item:focus,
.rrb-ac-item.rrb-ac-active {
  background: var(--surface-muted);
}
.rrb-ac-item.rrb-ac-active { outline: 0; }
.rrb-ac-name {
  font-weight: 600;
}
.rrb-ac-meta {
  color: var(--color-text-muted);
  font-size: var(--fs-sm);
}
.rrb-ac-empty {
  padding: var(--sp-sm) var(--sp-md);
  color: var(--color-text-muted);
  font-size: var(--fs-sm);
}
/* autocomplete float-mode panel chrome — copy of .cp-float (same tokens) */
.rrb-ac-float {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-card);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
  max-height: 280px;
  overflow-y: auto;
  z-index: 1100;
}
.rrb-ac-float[hidden] {
  display: none;
}
@media (max-width: 768px) {
  .rrb-search-facet {
    gap: var(--sp-md);
  }
  .rrb-search-facet .search-bar,
  .rrb-search-facet .search-input {
    min-height: 44px;
  }
  .rrb-search-facet .filter-row {
    width: 100%;
  }
}

/* === Report filter controller ===
   RRB.ui.reportFilters renders this shared popover and its active-filter chips.
   Keep the legacy `rp-*` selectors as compatibility names for the existing
   report pages; the controller and this stylesheet remain the canonical owner. */
.rp-filter-popover-wrap {
  position: relative;
  display: inline-flex;
  align-items: center;
}
.rp-filter-toggle {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-xs);
}
.rp-filter-count {
  margin-inline-start: var(--sp-xs);
}
.rp-filter-popover {
  position: absolute;
  top: calc(100% + var(--sp-xs));
  inset-inline-end: 0;
  z-index: 1100;
  min-width: min(560px, calc(100vw - 2 * var(--sp-md)));
  max-width: calc(100vw - 2 * var(--sp-md));
  padding: var(--sp-md);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-card);
  box-shadow: var(--e2);
}
.rp-filter-popover[hidden] {
  display: none;
}
.rp-filter-popover__body {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: var(--sp-md);
  align-items: end;
}
.rp-filter-popover .rp-field,
.rp-filter-popover .rp-filter-field {
  display: flex;
  flex-direction: column;
  gap: var(--sp-xs);
  min-width: 0;
}
.rp-filter-popover .rp-field label,
.rp-filter-popover .rp-filter-field label {
  color: var(--text-muted);
  font-size: var(--fs-xs);
  font-weight: 600;
}
.rp-filter-price-inline {
  display: grid;
  grid-column: 1 / -1;
  gap: var(--sp-xs);
}
.rp-filter-price-inline__label {
  color: var(--text-muted);
  font-size: var(--fs-xs);
  font-weight: 600;
}
.rp-filter-price-labels {
  display: flex;
  justify-content: space-between;
  gap: var(--sp-sm);
  color: var(--text-muted);
  font-size: var(--fs-xs);
  font-variant-numeric: tabular-nums;
}
.rp-filter-price-slider {
  display: grid;
  gap: var(--sp-xs);
}
.rp-filter-price-slider input[type="range"] {
  width: 100%;
  accent-color: var(--primary);
}
.rp-filter-price-actions,
.rp-filter-popover__footer {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: var(--sp-sm);
}
.rp-filter-clear {
  flex: 0 0 auto;
}
.rp-filter-popover__footer {
  margin-top: var(--sp-md);
  padding-top: var(--sp-md);
  border-top: 1px solid var(--border);
}
.rp-active-filters {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-xs);
  margin-top: var(--sp-sm);
}
.rp-active-chip {
  cursor: pointer;
}
@media (max-width: 768px) {
  .rp-filter-popover-wrap {
    width: 100%;
  }
  .rp-filter-toggle {
    min-height: 44px;
  }
  .rp-filter-popover {
    inset-inline: 0;
    min-width: 0;
    max-width: none;
  }
  .rp-filter-popover__body {
    grid-template-columns: 1fr;
  }
  .rp-filter-price-inline {
    grid-column: auto;
  }
}
@media (hover: none) {
  .rp-filter-popover .btn,
  .rp-active-chip {
    min-height: 44px;
  }
}

/* =====================================================================
   RRB UI Defaults — Batch 1 (additive; spec 2026-06-24-rrb-ui-defaults-batch-1)
   ===================================================================== */

/* --- Modal size variants (default .rrb-modal stays 480; md/omitted = no-op).
   Desktop-only so the mobile full-bleed rule (@max-width:480px) always wins on
   phones — otherwise .rrb-modal--sm would cap a 361-480px modal at 360px. --- */
@media (min-width: 481px) {
  .rrb-modal--sm   { max-width: 360px; }
  .rrb-modal--lg   { max-width: 680px; }
  .rrb-modal--wide { max-width: 860px; }
}

/* --- Action-menu entrance (was instant; now matches modal/toast polish) --- */
.rrb-menu {
  transform-origin: top;
  animation: rrb-menu-in 140ms var(--ease);
}
@keyframes rrb-menu-in {
  from { opacity: 0; transform: translateY(-4px) scale(.97); }
  to   { opacity: 1; transform: none; }
}

/* --- Save bar entrance (display:none -> flex still toggles; slide-up on appear) --- */
.rrb-savebar[data-dirty="true"] { animation: rrb-savebar-in 180ms var(--ease); }
@keyframes rrb-savebar-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .rrb-menu, .rrb-savebar[data-dirty="true"] { animation: none; }
}

/* =====================================================================
   Settings deeplink-target highlight (#832)
   Applied by settings-nav.js focusHash() when a canonical deeplink lands on
   a specific setting row. Uses only design-token values (rule
   ui/use-tokens-not-pixels). Animation is disabled under prefers-reduced-motion;
   the .is-deeplink-target class and outline are always applied as the static
   affordance.
   ===================================================================== */
@keyframes rrb-deeplink-fade {
  0%   { outline-color: var(--accent);    background-color: var(--accent-50); }
  100% { outline-color: transparent;      background-color: transparent; }
}
.is-deeplink-target {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  background-color: var(--accent-50);
  border-radius: var(--r-card, 12px);
  animation: rrb-deeplink-fade 2.5s ease-out forwards;
}
@media (prefers-reduced-motion: reduce) {
  .is-deeplink-target { animation: none; }
}

/* =====================================================================
   Setting-link — inline koppeling vanuit dashboard-GUI naar instelling (#834)
   Toegepast door setting-links.js op <a data-setting-link> voor admins.
   Niet-admins zien geen href, geen affordance, geen focus-stop.
   Tokens only (rule ui/use-tokens-not-pixels).
   ===================================================================== */
.setting-link {
  color: var(--primary);
  text-decoration-line: underline;
  text-decoration-style: dotted;
  text-underline-offset: 2px;
  transition: text-decoration-style var(--t, 150ms) var(--ease, ease);
}
.setting-link:hover,
.setting-link:focus {
  text-decoration-style: solid;
}
.setting-link:focus-visible {
  outline: 3px solid rgb(26 106 163 / 0.4);
  outline-offset: 2px;
  border-radius: 2px;
}

/* Icoon-variant: sibling-link naast een waarde die al in een interactief element staat */
.setting-link--icon {
  display: inline-flex;
  align-items: center;
  margin-inline-start: 0.25em;
  color: var(--primary);
  opacity: 0.7;
  text-decoration: none;
  vertical-align: middle;
}
.setting-link--icon:hover,
.setting-link--icon:focus {
  opacity: 1;
}
.setting-link--icon:focus-visible {
  outline: 3px solid rgb(26 106 163 / 0.4);
  outline-offset: 2px;
  border-radius: 2px;
}

/* rrb-worklist: gegroepeerde werkvoorraadlijst met filterbar (besluit U9).
   Neutrale extract van werkbon #page-notities (nb-pulse-*, nb-task-filter-*). */
.rrb-worklist { container: rrb-worklist / inline-size; display: grid; gap: var(--sp-md); min-inline-size: 0; }
.rrb-worklist__filterbar { display: flex; min-block-size: 60px; align-items: stretch; gap: var(--sp-sm); padding: 7px; border: 1px solid var(--border); border-radius: var(--r-card); background: var(--surface); box-shadow: var(--e1); }
.rrb-worklist__filterbar-result { display: flex; min-inline-size: 150px; align-items: center; gap: var(--sp-sm); padding-inline: var(--sp-xs); }
.rrb-worklist__filterbar-result > strong { display: grid; min-inline-size: 36px; block-size: 36px; place-items: center; border-radius: var(--r-btn); background: var(--primary-50); color: var(--primary-dark); font-size: var(--fs-lg); font-variant-numeric: tabular-nums; }
.rrb-worklist__filterbar-result b, .rrb-worklist__filterbar-result small { display: block; white-space: nowrap; }
.rrb-worklist__filterbar-result b { color: var(--color-text); font-size: var(--fs-xs); }
.rrb-worklist__filterbar-result small { margin-top: 1px; color: var(--color-text-secondary); font-size: 10px; }
.rrb-worklist__filterbar-divider { inline-size: 1px; margin-block: var(--sp-xs); background: var(--border); }
.rrb-worklist__filterbar-controls { display: flex; min-inline-size: 0; flex: 1 1 auto; align-items: stretch; gap: var(--sp-sm); }
.rrb-worklist__filterbar-select { position: relative; min-inline-size: 126px; block-size: 46px; align-self: center; border: 1px solid var(--border-strong); border-radius: var(--r-field); background: var(--surface); color: var(--color-text-secondary); transition: border-color var(--t) var(--ease), background var(--t) var(--ease), box-shadow var(--t) var(--ease); }
.rrb-worklist__filterbar-select.is-active { border-color: var(--primary-200); background: var(--primary-50); color: var(--primary-dark); }
.rrb-worklist__filterbar-select:focus-within { border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-100); }
.rrb-worklist__filterbar-trigger { display: grid; inline-size: 100%; block-size: 100%; grid-template-columns: 16px minmax(0, 1fr) 14px; align-items: center; gap: var(--sp-xs); padding-inline: 10px 8px; border: 0; border-radius: inherit; outline: 0; background: transparent; color: inherit; cursor: pointer; font: inherit; text-align: start; }
.rrb-worklist__filterbar-trigger-label { min-inline-size: 0; overflow: hidden; color: var(--color-text); font-size: var(--fs-xs); font-weight: 750; text-overflow: ellipsis; white-space: nowrap; }
.rrb-worklist__filterbar-chevron { inline-size: 14px; block-size: 14px; fill: none; stroke: currentColor; stroke-width: 2; pointer-events: none; transition: transform var(--t) var(--ease); }
.rrb-worklist__filterbar-select.is-open .rrb-worklist__filterbar-chevron { transform: rotate(180deg); }
.rrb-worklist__filterbar-menu { position: absolute; inset-block-start: calc(100% + var(--sp-xs)); inset-inline-start: 0; z-index: 90; inline-size: max(100%, 190px); max-inline-size: min(360px, calc(100vw - 32px)); max-block-size: min(360px, 60vh); overflow-y: auto; padding: var(--sp-xs); border: 1px solid var(--border); border-radius: var(--r-card); background: var(--surface); box-shadow: var(--e2); }
.rrb-worklist__filterbar-menu[hidden] { display: none; }
.rrb-worklist__filterbar-option { display: grid; inline-size: 100%; min-block-size: 44px; grid-template-columns: 22px minmax(0, 1fr); align-items: center; gap: var(--sp-sm); padding: var(--sp-sm); border: 0; border-radius: var(--r-btn); background: transparent; color: var(--color-text); cursor: pointer; font: inherit; font-size: var(--fs-sm); text-align: start; }
.rrb-worklist__filterbar-option:hover, .rrb-worklist__filterbar-option:focus-visible { background: var(--surface-muted); }
.rrb-worklist__filterbar-option:focus-visible { outline: 3px solid var(--primary-100); outline-offset: -3px; }
.rrb-worklist__filterbar-option.is-selected { background: var(--primary-50); color: var(--primary-dark); font-weight: 750; }
.rrb-worklist__filterbar-option-check { display: grid; inline-size: 22px; block-size: 22px; place-items: center; border: 1px solid var(--border-strong); border-radius: var(--r-field); background: var(--surface); color: transparent; font-size: var(--fs-xs); }
.rrb-worklist__filterbar-option.is-selected .rrb-worklist__filterbar-option-check { border-color: var(--primary); background: var(--primary); color: var(--surface); }
.rrb-worklist__filterbar-actions { display: flex; align-items: center; gap: var(--sp-xs); margin-inline-start: auto; }
.rrb-worklist__filterbar-actions .btn { min-block-size: 44px; white-space: nowrap; }
.rrb-worklist__filterbar-count { display: grid; min-inline-size: 20px; block-size: 20px; padding-inline: 5px; place-items: center; border-radius: var(--r-pill); background: var(--primary-100); color: var(--primary-dark); font-size: 10px; font-weight: 850; }
.rrb-worklist__morefilters { display: flex; flex-wrap: wrap; gap: var(--sp-md); padding: var(--sp-sm) var(--sp-md); border: 1px solid var(--border); border-radius: var(--r-card); background: var(--surface); }
.rrb-worklist__morefilters[hidden] { display: none; }
.rrb-worklist__morefilters label { display: flex; min-block-size: 44px; align-items: center; gap: var(--sp-sm); font-size: var(--fs-sm); }
.rrb-worklist__queue { display: grid; gap: var(--sp-md); }
.rrb-worklist__queue-head { display: flex; min-block-size: 44px; align-items: center; gap: var(--sp-sm); padding: var(--sp-sm) var(--sp-md); border: 1px solid var(--border); border-radius: var(--r-card); background: var(--surface-muted); }
.rrb-worklist__queue-head h2 { margin: 0; font-size: var(--fs-md); }
.rrb-worklist__queue-head > span:last-child { margin-inline-start: auto; color: var(--color-text-secondary); font-size: var(--fs-xs); }
.rrb-worklist__group { overflow: hidden; border: 1px solid var(--border); border-radius: var(--r-card); background: var(--surface); box-shadow: var(--e1); }
.rrb-worklist__group-signal { display: block; inline-size: 9px; block-size: 9px; flex: none; border-radius: var(--r-pill); background: var(--primary); box-shadow: 0 0 0 4px var(--primary-100); }
.rrb-worklist__group-signal.is-danger { background: var(--danger); box-shadow: 0 0 0 4px var(--danger-100); }
.rrb-worklist__group-signal.is-warning { background: var(--warning); box-shadow: 0 0 0 4px var(--warning-100); }
.rrb-worklist .rrb-disclosure { border: 0; border-radius: 0; }
.rrb-worklist .rrb-disclosure .rrb-disclosure__content { padding: 0; }
.rrb-worklist__row-list { display: grid; }
.rrb-worklist__row { position: relative; display: grid; grid-template-columns: 44px minmax(240px, 1.45fr) minmax(205px, .85fr) minmax(132px, .65fr) 112px 100px 44px; min-block-size: 72px; align-items: center; border-top: 1px solid var(--border); background: var(--surface); transition: background var(--t) var(--ease); }
.rrb-worklist__row::before { content: ''; position: absolute; inset: var(--sp-sm) auto var(--sp-sm) 0; inline-size: 3px; border-radius: 0 var(--r-field) var(--r-field) 0; background: var(--primary); }
.rrb-worklist__row[data-row-accent='danger']::before { background: var(--danger); }
.rrb-worklist__row[data-row-accent='warning']::before { background: var(--warning); }
.rrb-worklist__row:hover { background: var(--primary-50); }
.rrb-worklist__row-link { position: absolute; inset: 0; z-index: 1; border-radius: var(--r-field); }
.rrb-worklist__row-link:focus-visible { outline: 3px solid var(--primary); outline-offset: -3px; }
.rrb-worklist__row-lead, .rrb-worklist__row-main, .rrb-worklist__row-signals, .rrb-worklist__row-owner, .rrb-worklist__row-meter, .rrb-worklist__row-state, .rrb-worklist__row-chevron { position: relative; z-index: 2; pointer-events: none; }
.rrb-worklist__row-lead { display: grid; inline-size: 44px; block-size: 44px; margin: auto; place-items: center; color: var(--color-text-secondary); }
.rrb-worklist__row-lead svg, .rrb-worklist__row-chevron svg { inline-size: 18px; block-size: 18px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.rrb-worklist__row-main { min-inline-size: 0; padding: var(--sp-sm) var(--sp-md) var(--sp-sm) 0; }
.rrb-worklist__row-title { display: flex; min-inline-size: 0; align-items: center; gap: var(--sp-sm); }
.rrb-worklist__row-title strong { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--fs-md); }
.rrb-worklist__row-sub { display: flex; min-inline-size: 0; gap: 6px; margin-top: var(--sp-xs); color: var(--color-text-secondary); font-size: var(--fs-xs); }
.rrb-worklist__row-sub span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rrb-worklist__row-signals { display: flex; min-inline-size: 0; align-items: center; flex-wrap: wrap; gap: var(--sp-xs); padding-inline-end: var(--sp-sm); }
.rrb-worklist__row-owner { display: flex; min-inline-size: 0; align-items: center; gap: var(--sp-sm); padding-inline-end: var(--sp-sm); }
.rrb-worklist__row-avatar { display: grid; inline-size: 30px; block-size: 30px; flex: none; place-items: center; border-radius: var(--r-pill); background: var(--primary-100); color: var(--primary-dark); font-size: 10px; font-weight: 800; }
.rrb-worklist__row-owner-copy { min-inline-size: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--fs-xs); font-weight: 750; }
.rrb-worklist__row-meter strong, .rrb-worklist__row-meter span { display: block; font-size: var(--fs-xs); }
.rrb-worklist__row-meter span { margin-top: 2px; color: var(--color-text-secondary); }
.rrb-worklist__row-meter.is-danger strong { color: var(--danger-text); }
.rrb-worklist__row-meter.is-warning strong { color: var(--warning-text); }
.rrb-worklist__row-meter.is-success strong { color: var(--success-text); }
.rrb-worklist__row-state { justify-self: start; padding: var(--sp-xs) var(--sp-sm); border-radius: var(--r-field); background: var(--surface-muted); color: var(--color-text-secondary); font-size: var(--fs-xs); font-weight: 800; }
.rrb-worklist__row-chevron { display: grid; inline-size: 44px; block-size: 44px; place-items: center; color: var(--color-text-secondary); }
@container rrb-worklist (max-width: 1024px) {
  .rrb-worklist__filterbar-controls { display: none; }
  .rrb-worklist__row { grid-template-columns: 44px minmax(220px, 1fr) minmax(190px, .72fr) 44px; min-block-size: 68px; }
  .rrb-worklist__row-meter, .rrb-worklist__row-state, .rrb-worklist__row-owner { display: none; }
}
@container rrb-worklist (max-width: 768px) {
  .rrb-worklist__filterbar { gap: 4px; padding-inline: var(--sp-xs); }
  .rrb-worklist__filterbar-result small { display: none; }
  .rrb-worklist__row { grid-template-columns: 44px minmax(0, 1fr) 44px; min-block-size: 96px; align-items: start; padding-block: var(--sp-xs); }
  .rrb-worklist__row-main { padding-top: var(--sp-sm); }
  .rrb-worklist__row-title strong { display: -webkit-box; flex-basis: 100%; overflow: hidden; -webkit-box-orient: vertical; -webkit-line-clamp: 3; white-space: normal; line-height: 1.3; }
  .rrb-worklist__row-signals { grid-column: 2; padding: 0 0 var(--sp-xs); }
  .rrb-worklist__row-chevron { grid-column: 3; grid-row: 1; }
}
@container rrb-worklist (max-width: 480px) { .rrb-worklist__row-sub { flex-wrap: wrap; } }
/* rrb-worklist__completed: accordeon voor opgeloste en gesloten items, neutraal. */
.rrb-worklist__completed { overflow: hidden; border: 1px solid var(--border); border-radius: var(--r-card); background: var(--surface); box-shadow: var(--e1); }
.rrb-worklist__completed > summary { display: flex; align-items: center; gap: var(--sp-sm); padding: var(--sp-sm) var(--sp-md); list-style: none; cursor: pointer; user-select: none; }
.rrb-worklist__completed > summary::-webkit-details-marker { display: none; }
.rrb-worklist__completed > summary:focus-visible { outline: 3px solid var(--primary-100); outline-offset: -3px; border-radius: var(--r-field); }
.rrb-worklist__completed-icon { flex: none; inline-size: 18px; block-size: 18px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; color: var(--color-text-secondary); transition: transform var(--t) var(--ease); }
.rrb-worklist__completed[open] > summary .rrb-worklist__completed-icon { transform: rotate(90deg); }
.rrb-worklist__completed > summary strong { flex: 1; font-size: var(--fs-sm); font-weight: 750; color: var(--color-text); }
.rrb-worklist__completed > summary small { color: var(--color-text-secondary); font-size: var(--fs-xs); white-space: nowrap; }
.rrb-worklist__completed > .rrb-worklist__row-list { border-top: 1px solid var(--border); }
