/* Qamodes component library — qamodes-redwood-design-prompt-v2.md §4.
   Consumes qamodes-tokens.css only — no raw hex values in this file.
   Components actually used by shipped screens (header, nav, buttons, cards, inputs,
   data table, badges, tabs, alerts, slide-over) are fully built. Components with no
   consuming screen yet (calendar, searchable multi-select, file drag-drop, stepper
   JS wiring) have CSS defined so a future sprint doesn't restyle from scratch, but
   no behavior — noted inline where that's the case. */

* { box-sizing: border-box; }

html { font-variant-numeric: tabular-nums; }

body {
  margin: 0;
  background: var(--surface-100);
  color: var(--ink-900);
  font: var(--text-body);
  font-family: var(--font-body);
}

a { color: var(--brand-primary); }

/* Keyboard-visible focus ring everywhere — spec §3 "Focus ring 2px offset 2px,
   keyboard-visible everywhere". Elements with a more specific rule (e.g. .syc-btn,
   .syc-field input) override the offset/color to fit their own context, but nothing
   should fall through to the invisible default. */
a:focus-visible, button:focus-visible, input:focus-visible, select:focus-visible,
textarea:focus-visible, [tabindex]:focus-visible {
  outline: 2px solid var(--brand-primary);
  outline-offset: 2px;
}

@media (prefers-reduced-motion: no-preference) {
  .syc-btn, .syc-module-nav-item, .syc-mega-menu, .syc-slideover, .syc-toast, .syc-card { transition: var(--motion-duration) var(--motion-easing); }
}

/* ================= 1. Global header (predominantly white, v3.0) — top bar within the
   main column, not full-width; the wordmark lives in the left explorer. Header was a dark
   band matching the explorer under v2.0 Redwood; the Qamodes spec explicitly wants a white
   enterprise header with neutral icons and green-on-hover, so this section is a light
   theme now, not just a token-value swap. ================= */
.syc-header {
  background: var(--surface-0);
  border-bottom: 1px solid var(--line-200);
  height: 48px;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  gap: var(--space-5);
  padding: 0 var(--space-5);
  color: var(--ink-900);
}
.syc-header .syc-icon-btn {
  background: none;
  border: none;
  color: var(--ink-700);
  text-decoration: none;
  opacity: 1;
  cursor: pointer;
  width: 32px; height: 32px;
  border-radius: var(--radius-control);
  display: inline-flex; align-items: center; justify-content: center;
  position: relative;
}
.syc-header .syc-icon-btn ui5-icon { width: 18px; height: 18px; }
.syc-header .syc-icon-btn:hover { background: var(--surface-50); color: var(--brand-primary); }
.syc-header .syc-icon-btn.active { background: var(--brand-primary-subtle); color: var(--brand-primary); }
.syc-header .syc-icon-btn .dot {
  position: absolute; top: 6px; right: 6px;
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--brand-primary);
}
.syc-header .syc-icon-btn .count {
  position: absolute; top: 2px; right: 2px;
  min-width: 15px; height: 15px; padding: 0 3px; border-radius: 8px;
  background: var(--brand-primary); color: #fff;
  font: var(--text-label); font-size: 0.65rem; line-height: 15px; text-align: center;
  box-sizing: border-box;
}
.syc-header .syc-avatar {
  width: 28px; height: 28px; border-radius: 50%;
  background: var(--brand-primary-subtle);
  color: var(--brand-primary);
  display: inline-flex; align-items: center; justify-content: center;
  font: var(--text-label);
  border: none;
  cursor: pointer;
  padding: 0;
}

/* Header profile menu (2026-08-15, Phase 2) */
.syc-profile-menu { position: relative; }
.syc-profile-dropdown {
  display: none;
  position: absolute;
  top: calc(100% + var(--space-2));
  right: 0;
  min-width: 180px;
  background: var(--surface-0);
  border: 1px solid var(--line-200);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-pop);
  padding: var(--space-2);
  z-index: 70;
}
.syc-profile-dropdown.open { display: block; }
.syc-profile-dropdown-user {
  padding: var(--space-2) var(--space-3);
  font: var(--text-body-medium);
  color: var(--ink-900);
  border-bottom: 1px solid var(--line-200);
  margin-bottom: var(--space-1);
}
.syc-profile-dropdown-role {
  padding: 0 var(--space-3) var(--space-2);
  font: var(--text-secondary);
  color: var(--ink-500);
  border-bottom: 1px solid var(--line-200);
  margin-bottom: var(--space-1);
}
.syc-profile-dropdown-item {
  display: block;
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-control);
  font: var(--text-body);
  color: var(--ink-900);
  text-decoration: none;
  cursor: pointer;
  box-sizing: border-box;
}
.syc-profile-dropdown-item:hover { background: var(--surface-50); }
.syc-profile-dropdown-item--danger:hover { color: var(--danger); }
/* Active/disabled states (2026-08-22) — needed once Administration became a Row 1 popover
   listing real navigable screens. Same idiom as .syc-mega-menu-item.active/.disabled, so a
   Row 1 nav popover and a Row 2 mega-menu read identically. */
.syc-profile-dropdown-item.active { color: var(--brand-primary); font-weight: 600; }
.syc-profile-dropdown-item.disabled { color: var(--ink-300); cursor: default; pointer-events: none; }

/* Qamodes wordmark — the logo is the word "Qamodes" itself (no icon, no tagline), styled
   with the brand gradient. Used in the explorer header and the login/landing screens. */
.syc-wordmark {
  font: var(--text-section-title);
  font-weight: 700;
  background: var(--brand-gradient);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  white-space: nowrap;
  text-decoration: none;
}

/* Portal identity accent line — 3px under the dark band, differs per subdomain */
.syc-portal-accent { height: 3px; flex-shrink: 0; background: var(--portal-accent-internal); }
.syc-portal-accent[data-portal="customer"] { background: var(--portal-accent-customer); }
.syc-portal-accent[data-portal="supplier"] { background: var(--portal-accent-supplier); }

/* ================= 2. Left-side explorer navigation (replaced the horizontal tab
   strip 2026-08-15 — primary application navigation lives here now) ================= */

/* ================= 3. Buttons ================= */
.syc-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  height: var(--control-height);
  padding: 0 var(--space-4);
  border-radius: var(--radius-control);
  border: 1px solid transparent;
  font: var(--text-body-medium);
  cursor: pointer;
}
.syc-btn:focus-visible { outline: 2px solid var(--brand-primary); outline-offset: 2px; }
.syc-btn:disabled { opacity: .5; cursor: not-allowed; }
.syc-btn-primary { background: var(--brand-primary); color: var(--surface-0); }
.syc-btn-primary:hover { background: var(--brand-primary-hover); }
.syc-btn-primary:active { background: var(--brand-primary-active); }
.syc-btn-secondary { background: var(--surface-0); border-color: var(--line-200); color: var(--ink-900); }
.syc-btn-secondary:hover { background: var(--surface-50); border-color: var(--brand-primary); }
.syc-btn-tertiary { background: none; color: var(--brand-primary); height: auto; padding: 0; }
.syc-btn-tertiary:hover { color: var(--brand-primary-hover); text-decoration: underline; }
.syc-btn-destructive { background: var(--danger); color: var(--surface-0); }
.syc-btn-destructive:hover { filter: brightness(0.92); }
/* Premium gradient variant — reserved for the single top-of-page primary action per
   screen (see page-header.jsp), not for every button. Spec: "use sparingly". */
.syc-btn-premium {
  background: linear-gradient(135deg, var(--brand-green-800), var(--brand-green-600));
  color: var(--surface-0);
  box-shadow: 0 1px 2px rgba(11, 46, 31, .25);
}
.syc-btn-premium:hover { background: linear-gradient(135deg, var(--brand-green-900), var(--brand-green-700)); }
.syc-btn-premium:active { background: var(--brand-green-900); }

/* Checkbox / radio / switch — native controls, Qamodes green when checked */
input[type="checkbox"], input[type="radio"] { accent-color: var(--brand-primary); }

/* ================= 4. Cards ================= */
.syc-card {
  background: var(--surface-0);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  padding: var(--card-padding);
}
.syc-card-accent { border-left: 4px solid var(--ink-300); }
.syc-card-accent.success { border-left-color: var(--success); }
.syc-card-accent.warning { border-left-color: var(--warning); }
.syc-card-accent.danger { border-left-color: var(--danger); }
.syc-card-accent.info { border-left-color: var(--info); }

/* Checkbox group (2026-08-16, User Management role assignment) — layout wrapper only;
   the checkbox controls themselves use the global accent-color styling, not a custom
   widget (see UI_DESIGN_SYSTEM.md's Inputs section). */
.syc-checkbox-group { display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-5); }
.syc-checkbox-item { display: inline-flex; align-items: center; gap: var(--space-2); font: var(--text-body); color: var(--ink-900); cursor: pointer; }

/* ================= 5. Inputs ================= */
.syc-field { display: flex; flex-direction: column; gap: var(--space-1); }
.syc-field label {
  font: var(--text-label);
  text-transform: uppercase;
  letter-spacing: var(--label-tracking);
  color: var(--ink-500);
  /* Flex column items don't shrink below their own min-content width by default — a single
     long uppercase word (e.g. "GOVERNMENT", "OPERATING") in a narrow .syc-field-xs column
     (2/12 grid track, worse inside a slide-over's already-narrow width) forced the label
     wider than its track and it visually overflowed into the next field instead of wrapping.
     Found via a real screenshot of the Cost Sheet slide-over (2026-08-25) — CB-01. */
  min-width: 0;
  overflow-wrap: break-word;
}
.syc-field input, .syc-field select, .syc-field textarea {
  height: var(--control-height);
  border: 1.5px solid var(--line-200);
  border-radius: var(--radius-control);
  background-color: var(--surface-100);
  color: var(--ink-900);
  padding: 0 var(--space-3);
  font: var(--text-body);
  box-shadow: inset 0 1px 2px rgba(15, 23, 20, .03);
  transition: border-color var(--motion-duration) var(--motion-easing),
              box-shadow var(--motion-duration) var(--motion-easing),
              background-color var(--motion-duration) var(--motion-easing);
}
.syc-field textarea { height: auto; padding: var(--space-2) var(--space-3); line-height: 1.5; }
.syc-field input::placeholder, .syc-field textarea::placeholder { color: var(--ink-300); }
.syc-field input:hover, .syc-field select:hover, .syc-field textarea:hover {
  border-color: var(--ink-300);
}
.syc-field input:focus, .syc-field select:focus, .syc-field textarea:focus {
  outline: none;
  border-color: var(--brand-primary);
  background-color: var(--surface-0);
  box-shadow: 0 0 0 3px rgba(27, 107, 69, .14);
}
.syc-field input:disabled, .syc-field select:disabled, .syc-field textarea:disabled {
  background-color: var(--surface-100); color: var(--ink-300); cursor: not-allowed;
  box-shadow: none;
}
.syc-field.has-error input, .syc-field.has-error select {
  border-color: var(--danger);
}
.syc-field.has-error input:focus, .syc-field.has-error select:focus {
  box-shadow: 0 0 0 3px rgba(192, 57, 43, .14);
}
.syc-field .syc-error { color: var(--danger); font: var(--text-secondary); }
.syc-field .syc-help { color: var(--ink-500); font: var(--text-secondary); }

/* ---- Shared rich-text editor (Qamodes.mountRichTextEditor — EMAIL_CLIENT.md §11
   checkpoint 2, reused by Chat's composer) — same border/radius/focus tokens as .syc-field
   inputs above so it reads as one input language, not a bolted-on third-party widget. ---- */
.syc-richtext { border: 1.5px solid var(--line-200); border-radius: var(--radius-control); background-color: var(--surface-100); overflow: hidden; }
.syc-richtext:focus-within { border-color: var(--brand-primary); background-color: var(--surface-0); box-shadow: 0 0 0 3px rgba(27, 107, 69, .14); }
.syc-richtext-toolbar { display: flex; flex-wrap: wrap; gap: 2px; padding: var(--space-2); border-bottom: 1px solid var(--line-200); background: var(--surface-0); }
.syc-richtext-btn { min-width: 28px; height: 28px; padding: 0 var(--space-2); border: none; border-radius: var(--radius-control); background: none; color: var(--ink-700); font: var(--text-secondary); cursor: pointer; }
.syc-richtext-btn:hover { background: var(--surface-100); color: var(--ink-900); }
.syc-richtext-body { min-height: 180px; max-height: 420px; overflow-y: auto; padding: var(--space-3); font: var(--text-body); color: var(--ink-900); background: var(--surface-0); }
.syc-richtext-body:empty::before { content: attr(data-placeholder); color: var(--ink-300); }
.syc-richtext-body p { margin: 0 0 var(--space-2); }
.syc-richtext-body blockquote { margin: var(--space-2) 0; padding-left: var(--space-3); border-left: 3px solid var(--line-200); color: var(--ink-500); }
.syc-richtext-body pre { background: var(--surface-100); padding: var(--space-2); border-radius: var(--radius-control); font-family: monospace; }
.syc-richtext-body table { border-collapse: collapse; margin: var(--space-2) 0; }
.syc-richtext-body table td { border: 1px solid var(--line-200); padding: var(--space-2); min-width: 60px; }
.syc-richtext-fullscreen { position: fixed; inset: var(--space-5); z-index: 200; display: flex; flex-direction: column; box-shadow: var(--shadow-card); }
.syc-richtext-fullscreen .syc-richtext-body { flex: 1; max-height: none; }
/* Required-field convention (2026-08-15, UI Full Application Modernization Phase 1) —
   add class="required" to the <label>; not yet retroactively applied to every existing
   form (Phase 4 rolls it out app-wide). */
.syc-field label.required::after { content: " *"; color: var(--danger); }

/* Kill the browser's yellow/blue autofill background — one of the most common
   "old school" tells on an otherwise modern form. */
.syc-field input:-webkit-autofill,
.syc-field input:-webkit-autofill:hover,
.syc-field input:-webkit-autofill:focus {
  -webkit-text-fill-color: var(--ink-900);
  -webkit-box-shadow: 0 0 0 1000px var(--surface-0) inset;
  transition: background-color 5000s ease-in-out 0s;
}

/* Enterprise dropdown reskin — every <select> in the app already lives inside a
   .syc-field wrapper (or is a bare filter select on a list toolbar), so this single rule
   covers the whole app rather than needing a JS-driven custom widget per screen. Native
   <select> keeps full keyboard/accessibility behavior for free; this only replaces its
   default browser chrome (arrow, radius, focus) with the Qamodes look. A fully custom
   JS dropdown (checkmarks, multi-select, grouped options) is not built this pass — flag
   for a future sprint if pixel-parity with a bespoke dropdown component is needed. */
select {
  appearance: none;
  -webkit-appearance: none;
  border-radius: var(--radius-dropdown);
  background-color: var(--surface-0);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 20 20' fill='none'%3E%3Cpath d='M5.5 8L10 12.5L14.5 8' stroke='%235B6168' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--space-3) center;
  padding-right: var(--space-7);
  cursor: pointer;
}
select:hover { border-color: var(--brand-primary); }
select:disabled { cursor: not-allowed; }

/* Master selector "+" quick-create (2026-08-17, client compact-UI mandate §4-5) — the
   select flexes, the button stays a fixed square beside it, both sharing the field's
   own --control-height so the row reads as one compact control, not two mismatched
   ones. See Qamodes.initMasterSelect (qamodes.js). */
.syc-field-with-add { display: flex; gap: var(--space-2); align-items: center; }
.syc-field-with-add select { flex: 1; min-width: 0; }
.syc-quick-add-btn {
  flex-shrink: 0;
  width: var(--control-height);
  height: var(--control-height);
  border: 1.5px solid var(--line-200);
  border-radius: var(--radius-control);
  background: var(--surface-0);
  color: var(--brand-primary);
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.syc-quick-add-btn:hover { background: var(--brand-primary-subtle); border-color: var(--brand-primary); }

/* §6 System-Wide Master-Data Field Pattern (2026-08-24) — the popover Qamodes.
   openMasterFieldMenu opens beside the "+" button: real "Manage «Type»" link + the
   existing "+ Create «Type»" action, replacing the old direct-to-dialog click. Fixed
   position (JS sets top/left from the button's real bounding rect), so it works
   regardless of which scrollable ancestor the field sits in. */
.syc-master-field-popover {
  position: absolute; z-index: 1200; min-width: 180px;
  background: var(--surface-0); border: 1px solid var(--line-200); border-radius: var(--radius-control);
  box-shadow: var(--shadow-md, 0 4px 16px rgba(0,0,0,0.12)); padding: var(--space-2);
  display: flex; flex-direction: column; gap: 2px;
}
.syc-master-field-popover-item {
  display: block; width: 100%; text-align: left; padding: var(--space-2) var(--space-3);
  border: none; background: none; border-radius: var(--radius-control);
  font: var(--text-body); color: var(--ink-900); cursor: pointer; text-decoration: none;
}
.syc-master-field-popover-item:hover { background: var(--surface-50); color: var(--brand-primary); }

/* Two-line currency display (frozen decision D-04) — transaction currency, base
   currency beneath in ink-500 mono. Not yet consumed by any real screen (Currency
   Engine is Sprint 1.6, not built) — defined ahead of need per the design brief. */
.syc-currency { text-align: right; font-family: var(--font-mono); line-height: 1.3; }
.syc-currency .txn { display: block; color: var(--ink-900); }
.syc-currency .base { display: block; font-size: 0.75rem; color: var(--ink-500); }

/* File upload drag-drop zone (S3-backed) — visual only, no drop-handling JS wired
   yet since no screen uploads files (Document Engine is Sprint 1.7, not built). */
.syc-upload-zone {
  border: 1px dashed var(--line-200);
  border-radius: var(--radius-card);
  padding: var(--space-6);
  text-align: center;
  color: var(--ink-500);
  background: var(--surface-50);
}
.syc-upload-zone.dragover { border-color: var(--brand-primary); background: var(--brand-primary-subtle); }

/* ================= 6. Stepper "train" ================= */
.syc-stepper { display: flex; align-items: center; }
.syc-step { display: flex; align-items: center; gap: var(--space-2); color: var(--ink-300); }
.syc-step .circle {
  width: 28px; height: 28px; border-radius: 50%;
  border: 2px solid var(--line-200);
  display: inline-flex; align-items: center; justify-content: center;
  font: var(--text-label);
  flex-shrink: 0;
}
.syc-step.active { color: var(--brand-primary); }
.syc-step.active .circle { border-color: var(--brand-primary); color: var(--brand-primary); }
.syc-step.done { color: var(--ink-900); }
.syc-step.done .circle { background: var(--brand-primary); border-color: var(--brand-primary); color: var(--surface-0); }
.syc-step-connector { flex: 1; height: 2px; background: var(--line-200); margin: 0 var(--space-2); min-width: 24px; }
.syc-step.done + .syc-step-connector { background: var(--brand-primary); }

/* ================= 7. Data table ================= */
.syc-table-wrap { overflow-x: auto; border-radius: var(--radius-card); box-shadow: var(--shadow-card); }
table.syc-table { width: 100%; border-collapse: collapse; background: var(--surface-0); }
table.syc-table thead th {
  position: sticky; top: 0;
  text-align: left;
  font: var(--text-label);
  text-transform: uppercase;
  letter-spacing: var(--label-tracking);
  color: var(--ink-500);
  background: var(--surface-50);
  padding: var(--space-2) var(--space-4);
  border-bottom: 1px solid var(--line-200);
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
}
table.syc-table tbody td {
  height: 32px;
  padding: var(--space-1) var(--space-4);
  border-bottom: 1px solid var(--line-200);
  font: var(--text-body);
}
table.syc-table tbody tr:last-child td { border-bottom: none; }
table.syc-table tbody tr:hover { background: var(--surface-50); }
table.syc-table tbody tr.selected { background: var(--brand-primary-subtle); }
table.syc-table .syc-row-menu { text-align: right; position: relative; width: 32px; }
/* Row action menu (2026-08-15, UI Modernization Phase 4) — a real "..." affordance,
   previously absent (UI_MODERNIZATION_AUDIT.md §2 "Tables" — "no row-level '…' action
   menu"). Known follow-up, not yet verified in a real browser (no visual-render tooling
   in this environment): a row very near the bottom of .syc-table-wrap's scroll box may
   have its dropdown clipped by that container's overflow — revisit if a real screen hits
   this in practice. */
.syc-row-menu-trigger {
  background: none; border: none; cursor: pointer;
  width: 28px; height: 28px;
  border-radius: var(--radius-control);
  color: var(--ink-500);
  font-size: 1.1rem;
  line-height: 1;
}
.syc-row-menu-trigger:hover { background: var(--surface-50); color: var(--ink-900); }
.syc-row-menu-dropdown {
  display: none;
  position: absolute;
  top: 100%; right: 0;
  margin-top: 2px;
  min-width: 140px;
  background: var(--surface-0);
  border: 1px solid var(--line-200);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-pop);
  padding: var(--space-2);
  z-index: 70;
  text-align: left;
}
.syc-row-menu-dropdown.open { display: block; }
.syc-row-menu-item {
  display: block; width: 100%; text-align: left;
  background: none; border: none; cursor: pointer;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-control);
  font: var(--text-body);
  color: var(--ink-900);
}
.syc-row-menu-item:hover { background: var(--surface-50); }
.syc-table .empty-state, .syc-table .loading-state { text-align: center; color: var(--ink-500); padding: var(--space-7); }

/* Rich empty state — title + hint + optional CTA, replacing a bare "No X yet." string.
   Used both inside a table's empty row (sycRenderTable's options.emptyState) and as a
   standalone panel (e.g. Product Media before any photo is uploaded). A fresh screen
   should explain what belongs there and what to do next, not just say nothing exists. */
.syc-empty-state {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--space-2); text-align: center; padding: var(--space-7) var(--space-4);
  color: var(--ink-500);
}
.syc-empty-state-title { font: var(--text-body); font-weight: 600; color: var(--ink-700); }
.syc-empty-state-hint { font: var(--text-secondary); max-width: 380px; }
.syc-empty-state .syc-btn { margin-top: var(--space-2); }
.syc-table td.empty-state.syc-empty-state-cell { padding: 0; }
.syc-table td.empty-state.syc-empty-state-cell .syc-empty-state { padding: var(--space-8) var(--space-4); }
.syc-table .skeleton-cell {
  height: 14px; border-radius: 4px;
  background: linear-gradient(90deg, var(--surface-100) 25%, var(--brand-green-50) 37%, var(--surface-100) 63%);
  background-size: 400% 100%;
  animation: syc-skeleton 1.4s ease infinite;
}
@keyframes syc-skeleton { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }

/* ================= Branded loader — a compact Qamodes spinner, not the browser
   default. Use .syc-spinner for inline/button loading; .syc-skeleton-block for card/
   page-level placeholders (table skeletons above use .skeleton-cell instead). ================= */
.syc-spinner {
  display: inline-block;
  width: 18px; height: 18px;
  border: 2px solid var(--brand-green-100);
  border-top-color: var(--brand-primary);
  border-radius: 50%;
  animation: syc-spin 700ms linear infinite;
}
.syc-spinner-lg { width: 32px; height: 32px; border-width: 3px; }
@keyframes syc-spin { to { transform: rotate(360deg); } }

.syc-skeleton-block {
  border-radius: var(--radius-card);
  background: linear-gradient(90deg, var(--surface-100) 25%, var(--brand-green-50) 37%, var(--surface-100) 63%);
  background-size: 400% 100%;
  animation: syc-skeleton 1.4s ease infinite;
}

.syc-bulk-bar {
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  background: var(--ink-900); color: var(--surface-0);
  border-radius: var(--radius-control);
  margin-bottom: var(--space-3);
}

.syc-pagination { display: flex; align-items: center; gap: var(--space-2); justify-content: flex-end; padding: var(--space-4) 0; color: var(--ink-500); font: var(--text-secondary); }

@media (max-width: 768px) {
  table.syc-table, table.syc-table thead, table.syc-table tbody, table.syc-table tr, table.syc-table td { display: block; width: 100%; }
  table.syc-table thead { display: none; }
  table.syc-table tr { border-bottom: 1px solid var(--line-200); padding: var(--space-3) var(--space-4); }
  table.syc-table td { border-bottom: none; padding: var(--space-1) 0; }
}

/* ================= 8. RAG badges + chips ================= */
.syc-badge {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px var(--space-3);
  border-radius: var(--radius-chip);
  font: var(--text-label);
  text-transform: none;
  letter-spacing: 0;
}
.syc-badge::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.syc-badge-success { background: var(--success-bg); color: var(--success); }
.syc-badge-warning { background: var(--warning-bg); color: var(--warning); }
.syc-badge-danger { background: var(--danger-bg); color: var(--danger); }
.syc-badge-info { background: var(--info-bg); color: var(--info); }
.syc-badge-neutral { background: var(--neutral-badge-bg); color: var(--neutral-badge); }

.syc-chip {
  display: inline-flex; align-items: center; gap: var(--space-1);
  padding: 4px var(--space-3);
  border-radius: var(--radius-chip);
  background: var(--surface-50);
  border: 1px solid var(--line-200);
  font: var(--text-secondary);
  color: var(--ink-700);
  cursor: pointer;
}
.syc-chip.active { background: var(--brand-primary-subtle); border-color: var(--brand-primary); color: var(--brand-primary); }

/* ================= 9. Banners / toasts ================= */
.syc-banner {
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-control);
  font: var(--text-body);
  margin-bottom: var(--space-4);
}
.syc-banner-success { background: var(--success-bg); color: var(--success); }
.syc-banner-warning { background: var(--warning-bg); color: var(--warning); }
.syc-banner-danger { background: var(--danger-bg); color: var(--danger); }
.syc-banner-info { background: var(--info-bg); color: var(--info); }

.syc-toast-stack {
  position: fixed; bottom: var(--space-5); right: var(--space-5);
  display: flex; flex-direction: column; gap: var(--space-2);
  z-index: 1000;
}
.syc-toast {
  background: var(--ink-900); color: var(--surface-0);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-control);
  box-shadow: var(--shadow-pop);
  font: var(--text-body);
  min-width: 240px;
}
/* Severity variants (2026-08-15) — the base .syc-toast (neutral dark) stays the default
   for callers that don't pass a severity; these are additive, not a replacement. */
.syc-toast-success { background: var(--success); }
.syc-toast-warning { background: var(--warning); }
.syc-toast-danger { background: var(--danger); }
.syc-toast-info { background: var(--info); }

/* ================= 10. Slide-over panel ================= */
.syc-slideover-scrim {
  position: fixed; inset: 0; background: rgba(22,21,19,.32);
  opacity: 0; pointer-events: none; z-index: 998;
}
.syc-slideover-scrim.open { opacity: 1; pointer-events: auto; }
.syc-slideover {
  position: fixed; top: 0; right: 0; bottom: 0;
  width: 420px; max-width: 100vw;
  background: var(--surface-0);
  box-shadow: var(--shadow-pop);
  transform: translateX(100%);
  z-index: 999;
  padding: var(--space-5);
  overflow-y: auto;
}
.syc-slideover.open { transform: translateX(0); }
/* Slide-overs (420px) are far narrower than a full-width dashboard — the 12-col grid's
   xs/sm spans (2/12, 3/12) were sized for that wide context ("code, status, country, qty,
   currency" per their own comment), not a ~350px inner width. At the base span, an 8-field
   grid like the Cost Sheet (CB-01) crams labels like "Government tax %" into ~18px columns,
   which forces mid-word wraps that are unreadable even once they no longer overflow their
   neighbor. Found via a real screenshot (2026-08-25). */
.syc-slideover .syc-form-grid > .syc-field-xs { grid-column: span 4; }
.syc-slideover .syc-form-grid > .syc-field-sm { grid-column: span 6; }
.syc-slideover-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--space-4); }
.syc-slideover-header h2 { font: var(--text-section-title); margin: 0; }
.syc-slideover-header button[aria-label="Close"] {
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; padding: 0; border: none; background: none;
  color: var(--ink-500); cursor: pointer; border-radius: var(--radius-sm, 4px);
}
.syc-slideover-header button[aria-label="Close"]:hover { color: var(--brand-primary); background: var(--surface-50); }

/* Comments Drawer bubbles (2026-08-19) — chat-like presentation, comment-only content
   (no images/attachments, no real-time) — same .syc-slideover shell as above. */
.syc-comment-bubble { background: var(--surface-50); border-radius: var(--radius-md, 8px); padding: var(--space-3); }
.syc-comment-bubble-meta { display: flex; justify-content: space-between; gap: var(--space-2); font: var(--text-secondary); color: var(--ink-500); margin-bottom: var(--space-1); }
.syc-comment-bubble-body { font: var(--text-body); white-space: pre-wrap; word-break: break-word; }

/* Enterprise Workspace Layer Phase 2 §5 — threaded replies + comment attachments. Purely
   additive to the v0.51.1 bubble above; the unthreaded, attachment-free comment renders
   exactly as it always did. */
.syc-comment-bubble-actions { display: flex; gap: var(--space-3); margin-top: var(--space-2); }
.syc-comment-action {
  border: none; background: none; padding: 0; cursor: pointer;
  font: var(--text-secondary); color: var(--brand-primary);
}
.syc-comment-action:hover { text-decoration: underline; }
.syc-comment-replies:not(:empty) {
  display: flex; flex-direction: column; gap: var(--space-2);
  margin-top: var(--space-2); padding-left: var(--space-3);
  border-left: 2px solid var(--line-200);
}
.syc-comment-bubble-reply { background: var(--surface-0); border: 1px solid var(--line-200); }
.syc-comment-attachments:not(:empty) { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-top: var(--space-2); }
.syc-comment-attachment {
  display: inline-flex; align-items: center; gap: var(--space-1);
  border: 1px solid var(--line-200); border-radius: var(--radius-control);
  background: var(--surface-0); color: var(--ink-700, var(--ink-500));
  font: var(--text-secondary); padding: 2px var(--space-2); cursor: pointer;
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.syc-comment-attachment:hover { border-color: var(--brand-primary); color: var(--brand-primary); }
.syc-comment-reply-banner {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-2);
  font: var(--text-secondary); color: var(--ink-500);
  background: var(--surface-50); border-radius: var(--radius-control);
  padding: var(--space-1) var(--space-2); margin-bottom: var(--space-2);
}

/* ================= 10b. Status bar (CB-19, Global Application Shell) =================
   Compact, persistent utility bar fixed at the bottom of the shell — not a conventional
   browser footer, never a redesign of the top header/nav. Below the slide-over/toast
   z-index so both still layer above it correctly. */
.syc-status-bar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 60;
  height: 30px; display: flex; align-items: center; justify-content: space-between;
  padding: 0 var(--page-gutter); background: var(--surface-0);
  border-top: 1px solid var(--line-200); font: var(--text-secondary); color: var(--ink-500);
}
.syc-status-bar-left, .syc-status-bar-right { display: flex; align-items: center; gap: var(--space-4); }
.syc-status-bar-item { display: inline-flex; align-items: center; gap: var(--space-2); }
.syc-status-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--ink-500); flex-shrink: 0; }
.syc-status-dot-ok { background: var(--success); }
.syc-status-dot-error { background: var(--danger); }
.syc-status-bar-btn {
  display: inline-flex; align-items: center; gap: var(--space-2);
  border: none; background: none; color: var(--ink-500); font: var(--text-secondary);
  cursor: pointer; padding: var(--space-1) var(--space-2); border-radius: var(--radius-sm, 4px);
}
.syc-status-bar-btn:hover { color: var(--brand-primary); background: var(--surface-50); }
.syc-status-bar-badge {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 16px; height: 16px; padding: 0 4px; border-radius: 8px;
  background: var(--brand-primary); color: #fff; font-size: 10px; font-weight: 600;
}
.syc-content-wrap { padding-bottom: 30px; }

/* Sticky Notes cards (CB-19) — inside the shared .syc-slideover shell. */
.syc-sticky-note {
  border-radius: var(--radius-md, 8px); padding: var(--space-3);
  border: 1px solid var(--line-200); background: var(--surface-50);
}
.syc-sticky-note-yellow { background: #FFF8E1; border-color: #F5E1A4; }
.syc-sticky-note-blue { background: #E8F1FB; border-color: #BFD9F2; }
.syc-sticky-note-green { background: #EAF6EC; border-color: #BFE3C5; }
.syc-sticky-note-pink { background: #FBEAF0; border-color: #F0C2D4; }
.syc-sticky-note-toolbar { display: flex; align-items: center; gap: var(--space-2); margin-bottom: var(--space-2); }

/* Enterprise Workspace Layer Phase 2 §6 — Entity Notes. A note scoped to a real business
   object must be tellable apart from an unscoped personal note at a glance: it gets a left
   accent and a context chip naming (and linking to) the object it belongs to. */
.syc-sticky-note-scoped { border-left-width: 3px; border-left-color: var(--brand-primary); }
.syc-sticky-note-context {
  display: inline-flex; align-items: center; gap: var(--space-1);
  font: var(--text-secondary); font-weight: 600; color: var(--brand-primary);
  text-decoration: none; margin-bottom: var(--space-2);
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
a.syc-sticky-note-context:hover { text-decoration: underline; }
.syc-slideover-hint { font: var(--text-secondary); color: var(--ink-500); margin: 0 0 var(--space-3); }

/* The rail's "My Notes" section (Phase 2 §6) — compact previews, deliberately not editable
   in place: editing happens in the one Sticky Notes panel, so there is one notes editor. */
.syc-context-rail-note {
  border-radius: var(--radius-control); border: 1px solid var(--line-200);
  padding: var(--space-2); margin-bottom: var(--space-2);
}
.syc-context-rail-note strong { display: block; font: var(--text-secondary); font-weight: 600; color: var(--ink-700); }
.syc-context-rail-note .desc { display: block; font: var(--text-secondary); color: var(--ink-500); white-space: pre-wrap; }
.syc-context-rail-note-hint { font: var(--text-secondary); color: var(--ink-500); margin: var(--space-2) 0 0; }

/* Row count / caption under a table (Contacts, Phase 2 §7). */
.syc-table-footnote { font: var(--text-secondary); color: var(--ink-500); margin: var(--space-2) 0 0; }
.syc-sticky-note-swatches { display: inline-flex; gap: var(--space-1); margin-left: auto; }
.syc-sticky-note-swatch {
  width: 14px; height: 14px; border-radius: 50%; border: 1px solid var(--line-200);
  padding: 0; cursor: pointer;
}
.syc-sticky-note-swatch-yellow { background: #FFE58A; }
.syc-sticky-note-swatch-blue { background: #A9CBF0; }
.syc-sticky-note-swatch-green { background: #A9DCB1; }
.syc-sticky-note-swatch-pink { background: #F0A9C5; }
.syc-sticky-note-swatch.selected { outline: 2px solid var(--brand-primary); outline-offset: 1px; }
.syc-sticky-note-pin.pinned { color: var(--brand-primary); }
.syc-sticky-note-title {
  width: 100%; border: none; background: none; font: var(--text-body-medium);
  margin-bottom: var(--space-2); padding: 0;
}
.syc-sticky-note-body {
  width: 100%; min-height: 60px; border: none; background: none; resize: vertical;
  font: var(--text-body); padding: 0;
}
.syc-sticky-note-title:focus, .syc-sticky-note-body:focus { outline: none; }
.syc-sticky-note-status { font: var(--text-secondary); color: var(--ink-500); text-align: right; height: 16px; margin-top: var(--space-1); }

/* ================= 11. Tabs-within-page (repaired 2026-08-15, Global Tab System) =====
   Root cause of the reported "not acceptable" tab experience, found by reading the real
   code before changing anything (not assumed): the click-switch mechanism itself
   (Qamodes.initTabs) never reloaded the page — no <form> wraps any Object Page, so no
   implicit-submit bug existed. The real gaps were genuinely missing capability: every
   screen's onSelect refetched its API on every click (no caching), no URL/deep-link
   state, no ARIA roles, no keyboard arrow navigation, no sticky bar, no overflow
   handling for many tabs. Fixed at the one shared implementation (qamodes.js), not by
   forking a second tab system — <ui5-tabcontainer> stays available in the control
   library (showcase only) but is not the Object Page standard; native .syc-tabs is. ==== */
.syc-tabs {
  display: flex; gap: var(--space-2);
  border-bottom: 1px solid var(--line-200);
  margin-bottom: var(--space-5);
  overflow-x: auto;
  scrollbar-width: thin;
  scrollbar-color: var(--line-200) transparent;
  position: sticky; top: 0;
  background: var(--surface-0);
  z-index: 10;
}
.syc-tabs::-webkit-scrollbar { height: 6px; }
.syc-tabs::-webkit-scrollbar-thumb { background: var(--line-200); border-radius: 999px; }
.syc-tab {
  font: var(--text-body-medium);
  padding: var(--space-3) var(--space-4);
  border: none; background: none;
  color: var(--ink-500);
  cursor: pointer;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  white-space: nowrap;
  flex-shrink: 0;
  transition: color var(--motion-duration) var(--motion-easing), border-color var(--motion-duration) var(--motion-easing);
}
.syc-tab:hover { color: var(--ink-900); }
.syc-tab.active { color: var(--brand-primary); border-bottom-color: var(--brand-primary); font-weight: 600; }
.syc-tab:focus-visible { outline: 2px solid var(--brand-primary); outline-offset: -2px; }
/* Honest "not built yet" tab, disabled instead of clickable-into-a-blank panel — same
   convention as .syc-mega-menu-item.disabled / .syc-module-nav-item.disabled in the header
   nav (2026-08-22, demo stabilization). Pair with title="… (coming soon)" and aria-disabled. */
.syc-tab.disabled { color: var(--ink-300); cursor: default; pointer-events: none; }
.syc-tab.disabled:hover { color: var(--ink-300); }
.syc-tab-panel { display: none; opacity: 0; transition: opacity 150ms var(--motion-easing); }
.syc-tab-panel.active { display: block; opacity: 1; }
.syc-tab-error { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-5); color: var(--danger); }

/* ================= 12. Timeline ================= */
.syc-timeline { list-style: none; margin: 0; padding: 0; }
.syc-timeline-item { display: flex; gap: var(--space-3); padding: var(--space-3) 0; border-bottom: 1px solid var(--line-200); }
.syc-timeline-item:last-child { border-bottom: none; }
.syc-timeline-avatar {
  width: 32px; height: 32px; border-radius: 50%; flex-shrink: 0;
  background: var(--brand-primary-subtle); color: var(--brand-primary);
  display: inline-flex; align-items: center; justify-content: center;
  font: var(--text-label);
}
.syc-timeline-body { flex: 1; }
.syc-timeline-meta { color: var(--ink-500); font: var(--text-secondary); }
.syc-channel-icon { display: inline-flex; align-items: center; gap: 4px; color: var(--ink-500); font: var(--text-secondary); }

/* ================= 13. Calendar — DEFERRED ================= */
/* No screen consumes this yet (TNA Calendar / Inspection Schedule are Phase 4/6,
   not built). Not stubbed here to avoid guessing an interaction model before a
   real screen exists to validate it against. */

/* ================= 14. Empty states ================= */
.syc-empty {
  text-align: center;
  padding: var(--space-7) var(--space-4);
  color: var(--ink-500);
}
.syc-empty p { margin: 0 0 var(--space-3); }

/* ================= 15. Object Page header (2026-08-15, QAM-UI-04) =================
   The reusable Qamodes Object Page pattern — name/code/status/key-metrics row above the
   tab strip. First used by Supplier 360; reuse this exact component for Buyer/Product/
   Order/QC/Shipment 360 once those objects exist (per QAMODES_SPRINT_PLAN.md). */
.syc-object-header {
  background: var(--surface-0);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  padding: var(--space-4) var(--card-padding);
  margin-bottom: var(--space-5);
}
.syc-object-header-top { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-5); flex-wrap: wrap; }
/* Compact redesign (2026-08-19, QAMODES UI Priority Backlog P0-1) — optional photo slot
   beside the identity block. Additive only: pages that don't add a photo (Order) render
   identically to before, since the row simply collapses to one child. */
.syc-object-header-identity-row { display: flex; align-items: center; gap: var(--space-4); }
.syc-object-header-photo {
  width: 72px; height: 72px; flex-shrink: 0;
  border-radius: var(--radius-card);
  border: 1px solid var(--line-200);
  background: var(--surface-50);
  display: flex; align-items: center; justify-content: center;
  overflow: hidden;
  color: var(--ink-300);
}
.syc-object-header-photo img { width: 100%; height: 100%; object-fit: cover; }
.syc-object-header-identity { display: flex; flex-direction: column; gap: var(--space-1); }
.syc-object-header-name { font: var(--text-page-title); margin: 0; }
.syc-object-header-code { font: var(--text-secondary); font-family: var(--font-mono); color: var(--ink-500); }
.syc-object-header-badges { display: flex; gap: var(--space-2); margin-top: var(--space-2); flex-wrap: wrap; align-items: center; }
.syc-object-header-actions { display: flex; gap: var(--space-3); flex-shrink: 0; flex-wrap: wrap; }
.syc-object-header-metrics { display: flex; gap: var(--space-5); margin-top: var(--space-3); padding-top: var(--space-3); border-top: 1px solid var(--line-200); flex-wrap: wrap; }
.syc-object-header-metric { display: flex; flex-direction: column; gap: 2px; }
.syc-object-header-metric .value { font: var(--text-page-title); font-size: 1.15rem; }
.syc-object-header-metric .value.muted { color: var(--ink-300); font-size: 1rem; }
.syc-object-header-metric .label { font: var(--text-label); text-transform: uppercase; letter-spacing: var(--label-tracking); color: var(--ink-500); }

/* Clickable business-entity link (2026-08-19, QAMODES UI Priority Backlog Priority 7) —
   the one shared style for making a Buyer/Supplier/Product name in a table or header
   navigate instead of sitting as inert text. */
.syc-entity-link {
  color: var(--ink-900);
  text-decoration: underline;
  text-decoration-style: dashed;
  text-decoration-color: var(--line-200);
  text-underline-offset: 2px;
  cursor: pointer;
}
.syc-entity-link:hover { color: var(--brand-primary); text-decoration-color: var(--brand-primary); }

/* ================= 15b. Product photo grid (2026-08-19, QAMODES UI Priority Backlog
   P0-2) — replaces the plain table list of image rows with a real thumbnail gallery. ==== */
.syc-photo-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: var(--space-4);
}
.syc-photo-card {
  border: 1px solid var(--line-200);
  border-radius: var(--radius-card);
  overflow: hidden;
  background: var(--surface-0);
  display: flex; flex-direction: column;
}
.syc-photo-card-thumb {
  width: 100%; height: 140px;
  background: var(--surface-50);
  display: flex; align-items: center; justify-content: center;
  color: var(--ink-300);
  overflow: hidden;
}
.syc-photo-card-thumb img { width: 100%; height: 100%; object-fit: cover; }
.syc-photo-card-body { padding: var(--space-3); display: flex; flex-direction: column; gap: var(--space-2); }
.syc-photo-card-caption { font: var(--text-secondary); color: var(--ink-700); word-break: break-word; }
.syc-photo-card-actions { display: flex; gap: var(--space-2); flex-wrap: wrap; align-items: center; }

/* Honest "not built yet" tab state — used instead of ever populating a tab with fake
   data. Distinct from .syc-empty (which means "real feature, no rows yet"): this means
   "the backend domain for this tab doesn't exist yet". */
.syc-tab-coming-soon {
  text-align: center;
  padding: var(--space-8) var(--space-4);
  color: var(--ink-500);
}
.syc-tab-coming-soon .icon { color: var(--ink-300); margin-bottom: var(--space-3); }
.syc-tab-coming-soon h3 { font: var(--text-body-medium); color: var(--ink-700); margin: 0 0 var(--space-2); }
.syc-tab-coming-soon p { margin: 0 auto; font: var(--text-secondary); max-width: 380px; }

/* ================= 16. Dialog / modal — INTENTIONALLY NOT a Qamodes component.
   D-32 names ui5-dialog as the one preferred implementation for this control category
   ("one preferred implementation per control category — see UI_DESIGN_SYSTEM.md v3.1's
   component policy table"); already wired in /admin/ui-showcase. Qamodes.confirm() in
   qamodes.js builds a real <ui5-dialog> dynamically rather than a second, competing
   hand-built dialog implementation — no CSS needed here, ui5-dialog carries its own
   Shadow DOM styling via qamodes-ui5-theme.css. ================= */

/* ================= 17. App-level loader (2026-08-15, UI Full Application Modernization
   Phase 1) — reserved for initial page load / auth transitions only, never for ordinary
   data fetching (table/card skeletons already cover that — see §7/§"Branded loader"
   above). ================= */
.syc-app-loader {
  position: fixed; inset: 0;
  display: flex; align-items: center; justify-content: center;
  background: rgba(255,255,255,.72);
  z-index: 1200;
}
.syc-app-loader .syc-spinner-lg { border-color: var(--brand-green-100); border-top-color: var(--brand-primary); }

/* ================= 18. Scrollbar theming (2026-08-15, UI Full Application Modernization
   Phase 1) — thin, near-invisible-until-hovered; scoped to the app's real scrollable
   surfaces, not a blanket * rule (per UI_MODERNIZATION_AUDIT.md §2 "Scrollbars"). ================= */
body, .syc-mega-menu, .syc-table-wrap, .syc-search-results, .syc-slideover {
  scrollbar-width: thin;
  scrollbar-color: var(--line-200) transparent;
}
body::-webkit-scrollbar, .syc-mega-menu::-webkit-scrollbar, .syc-table-wrap::-webkit-scrollbar,
.syc-search-results::-webkit-scrollbar, .syc-slideover::-webkit-scrollbar {
  width: 8px; height: 8px;
}
body::-webkit-scrollbar-track, .syc-mega-menu::-webkit-scrollbar-track, .syc-table-wrap::-webkit-scrollbar-track,
.syc-search-results::-webkit-scrollbar-track, .syc-slideover::-webkit-scrollbar-track {
  background: transparent;
}
body::-webkit-scrollbar-thumb, .syc-mega-menu::-webkit-scrollbar-thumb, .syc-table-wrap::-webkit-scrollbar-thumb,
.syc-search-results::-webkit-scrollbar-thumb, .syc-slideover::-webkit-scrollbar-thumb {
  background: var(--line-200); border-radius: 999px;
}
body::-webkit-scrollbar-thumb:hover, .syc-mega-menu::-webkit-scrollbar-thumb:hover, .syc-table-wrap::-webkit-scrollbar-thumb:hover,
.syc-search-results::-webkit-scrollbar-thumb:hover, .syc-slideover::-webkit-scrollbar-thumb:hover {
  background: var(--brand-primary);
}

/* ================= 19. Dashboard (My Workspace redesign, 2026-08-15) =================
   Compact KPI cards, proportional status bars (a deliberate choice over a hand-drawn SVG
   donut — reliably renderable from real percentages with plain CSS width, no charting
   library, no risk of a broken arc-drawing routine going unverified in an environment
   with no browser to render it in), and a 3/2/1-column responsive dashboard grid. Every
   widget that consumes these must render real data or the existing .syc-tab-coming-soon
   honest-empty pattern — never a fabricated number. ================= */
.syc-dashboard-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-5);
  align-items: start;
}
@media (max-width: 1200px) { .syc-dashboard-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 720px) { .syc-dashboard-grid { grid-template-columns: 1fr; } }

.syc-kpi-strip { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-4); margin-bottom: var(--space-5); }
@media (max-width: 720px) { .syc-kpi-strip { grid-template-columns: 1fr; } }
.syc-kpi-card {
  display: flex; align-items: center; gap: var(--space-4);
  background: var(--surface-0);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  padding: var(--space-4) var(--space-5);
}
.syc-kpi-icon {
  width: 34px; height: 34px; flex-shrink: 0;
  border-radius: 8px;
  background: var(--brand-primary-subtle);
  color: var(--brand-primary);
  display: flex; align-items: center; justify-content: center;
}
.syc-kpi-icon ui5-icon { width: 20px; height: 20px; }
.syc-kpi-body { display: flex; flex-direction: column; min-width: 0; }

/* CB-28 — Entity 360° Dashboard summary cards (pilot: Product Supplier). Reuses
   .syc-kpi-card's visual weight; adds a click affordance since every card here
   navigates somewhere real. */
.syc-dashboard-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: var(--space-4); }
.syc-kpi-card-clickable { cursor: pointer; transition: box-shadow var(--motion-duration, .15s) var(--motion-easing, ease); }
.syc-kpi-card-clickable:hover { box-shadow: var(--shadow-pop); }
.syc-kpi-label { font: var(--text-label); text-transform: uppercase; letter-spacing: var(--label-tracking); color: var(--ink-500); }
.syc-kpi-value { font: var(--text-page-title); }

.syc-status-bars { display: flex; flex-direction: column; gap: var(--space-3); }
.syc-status-bar-row { display: flex; flex-direction: column; gap: 4px; }
.syc-status-bar-label { display: flex; justify-content: space-between; font: var(--text-secondary); color: var(--ink-700); }
.syc-status-bar-label .count { color: var(--ink-500); }
.syc-status-bar-track { height: 6px; background: var(--surface-100); border-radius: 999px; overflow: hidden; }
.syc-status-bar-fill { height: 100%; border-radius: 999px; }
.syc-status-bar-fill.success { background: var(--success); }
.syc-status-bar-fill.warning { background: var(--warning); }
.syc-status-bar-fill.danger { background: var(--danger); }
.syc-status-bar-fill.info { background: var(--info); }
.syc-status-bar-fill.neutral { background: var(--ink-300); }

.syc-widget-title { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--space-4); }
.syc-widget-title h2 { margin: 0; }
.syc-widget-title a { font: var(--text-secondary); color: var(--brand-primary); text-decoration: none; }
.syc-widget-title a:hover { text-decoration: underline; }

.syc-notification-row { display: flex; align-items: flex-start; gap: var(--space-3); padding: var(--space-3) 0; border-bottom: 1px solid var(--line-200); cursor: pointer; }
.syc-notification-row:last-child { border-bottom: none; }
.syc-notification-row .unread-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--brand-primary); flex-shrink: 0; margin-top: 6px; }
.syc-notification-row .body { flex: 1; min-width: 0; }
.syc-notification-row .title { font: var(--text-body-medium); }
.syc-notification-row .meta { color: var(--ink-500); font: var(--text-secondary); }

/* ================= 20. Object Page body split + Context Rail (CONTEXTUAL_WORKSPACE.md
   §4, 2026-08-17) — the tab strip/panels stay full-width main content; the rail is a
   fixed-width sibling column, same "1fr fixed-px" pattern as My Workspace's own body
   split (§19 above uses a different, dashboard-specific grid). initContextRail (qamodes.js)
   populates #contextRail and hides it entirely when there is nothing real to show — no
   empty rail chrome ever renders. ================= */
.syc-op-body { display: grid; grid-template-columns: 1fr 280px; gap: var(--space-6); align-items: start; }
@media (max-width: 960px) { .syc-op-body { grid-template-columns: 1fr; } }
.syc-op-main { min-width: 0; }

.syc-context-rail { display: flex; flex-direction: column; gap: var(--space-4); }
.syc-context-rail-section {
  background: var(--surface-0);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  padding: var(--space-4);
}
.syc-context-rail-section h3 {
  margin: 0 0 var(--space-3);
  font: var(--text-label);
  text-transform: uppercase;
  letter-spacing: var(--label-tracking);
  color: var(--ink-500);
}
.syc-context-rail-step {
  display: block;
  padding: var(--space-2) 0;
  border-top: 1px solid var(--line-200);
  color: inherit;
  text-decoration: none;
}
.syc-context-rail-step:first-child { border-top: none; }
.syc-context-rail-step strong { display: block; font: var(--text-secondary); font-weight: 600; color: var(--ink-700); }
.syc-context-rail-step .desc { display: block; font: var(--text-secondary); color: var(--ink-500); margin-top: 2px; }
.syc-context-rail-step.blocking strong::before { content: ''; display: inline-block; width: 6px; height: 6px; border-radius: 50%; background: var(--danger); margin-right: 6px; }
a.syc-context-rail-step:hover strong { color: var(--brand-primary); }

.syc-context-rail-actions { display: flex; flex-direction: column; gap: var(--space-2); }
.syc-context-rail-action {
  font: var(--text-secondary);
  color: var(--brand-primary);
  text-decoration: none;
  padding: var(--space-1) 0;
}
.syc-context-rail-action:hover { text-decoration: underline; }

.syc-context-rail-progress-bar { height: 6px; background: var(--surface-100); border-radius: 999px; overflow: hidden; margin-bottom: var(--space-3); }
.syc-context-rail-progress-fill { height: 100%; background: var(--brand-primary); border-radius: 999px; }
.syc-context-rail-progress-steps { display: flex; flex-direction: column; gap: 4px; }
.syc-context-rail-progress-step { font: var(--text-secondary); color: var(--ink-300); }
.syc-context-rail-progress-step.done { color: var(--ink-700); }
.syc-context-rail-progress-step.done::before { content: '✓ '; color: var(--success); }

/* ================= 21. List filter bar (2026-08-17) — replaces the old pattern of
   a full-width .syc-card + .syc-form-grid above every listing table (identical visual
   weight to a real data-entry form: a label above every field, spanning the whole
   content width). A filter is a quick refinement of an already-visible list, not a
   form — this is a single compact inline row: search grows/shrinks, selects size to
   their own content instead of a rigid grid column, no card shadow/padding. Applied
   across every real listing screen (Supplier/Customer/Product/Order/RFQ/Export
   Invoice/Task); screens whose only "filter card" is actually a create-record form
   (User) are untouched. ================= */
.syc-filter-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
  margin-bottom: var(--space-5);
}
.syc-filter-bar .syc-filter-search {
  flex: 1 1 220px;
  min-width: 160px;
  max-width: 320px;
}
.syc-filter-bar input,
.syc-filter-bar select {
  height: var(--control-height);
  border: 1.5px solid var(--line-200);
  border-radius: var(--radius-control);
  background-color: var(--surface-100);
  color: var(--ink-900);
  padding: 0 var(--space-3);
  font: var(--text-body);
  box-shadow: inset 0 1px 2px rgba(15, 23, 20, .03);
  transition: border-color var(--motion-duration) var(--motion-easing),
              box-shadow var(--motion-duration) var(--motion-easing),
              background-color var(--motion-duration) var(--motion-easing);
}
.syc-filter-bar input { width: 100%; }
.syc-filter-bar select { width: auto; min-width: 130px; }
.syc-filter-bar input:hover, .syc-filter-bar select:hover { border-color: var(--ink-300); }
.syc-filter-bar input:focus, .syc-filter-bar select:focus {
  outline: none;
  border-color: var(--brand-primary);
  background-color: var(--surface-0);
  box-shadow: 0 0 0 3px rgba(27, 107, 69, .14);
}
.syc-filter-bar input::placeholder { color: var(--ink-300); }
.syc-filter-bar-clear {
  font: var(--text-secondary);
  color: var(--brand-primary);
  background: none;
  border: none;
  cursor: pointer;
  padding: 0 var(--space-2);
  white-space: nowrap;
}
.syc-filter-bar-clear:hover { text-decoration: underline; }
@media (max-width: 640px) {
  .syc-filter-bar .syc-filter-search { max-width: none; flex-basis: 100%; }
}

/* ================= 22. Context Rail — Tasks/Related sections (2026-08-17) — extends
   §20's Context Rail with two more real, non-empty-by-default sections: open Tasks
   genuinely linked to this object (source_entity_type/source_entity_id) and Related
   Objects (real FK-derived cross-links). Reuses .syc-context-rail-section/-actions from
   §20 rather than introducing a parallel set of card/list styles. ================= */
/* Now rendered as an <a> (2026-08-23) so a rail task row opens the real task list rather
   than sitting there unactionable — same treatment .syc-context-rail-step already gets. */
.syc-context-rail-task {
  display: block;
  padding: var(--space-2) 0;
  border-top: 1px solid var(--line-200);
  color: inherit;
  text-decoration: none;
}
.syc-context-rail-task:first-child { border-top: none; }
a.syc-context-rail-task:hover strong { color: var(--brand-primary); }
.syc-context-rail-task .syc-badge { margin-bottom: 4px; }
.syc-context-rail-task strong { display: block; font: var(--text-secondary); font-weight: 600; color: var(--ink-700); }
.syc-context-rail-task .desc { display: block; font: var(--text-secondary); color: var(--ink-500); margin-top: 2px; }

.syc-context-rail-related {
  display: block;
  padding: var(--space-2) 0;
  border-top: 1px solid var(--line-200);
  color: inherit;
  text-decoration: none;
}
.syc-context-rail-related:first-child { border-top: none; }
.syc-context-rail-related strong { display: block; font: var(--text-secondary); font-weight: 600; color: var(--ink-700); }
.syc-context-rail-related .desc { display: block; font: var(--text-secondary); color: var(--ink-500); margin-top: 2px; }
.syc-context-rail-related:hover strong { color: var(--brand-primary); }

/* ===================================================================================
   Chat / Channels / Presence — Enterprise Workspace Layer Phase 1.
   Built entirely from existing BAOS tokens (--surface-*, --ink-*, --line-*, --space-*,
   --brand-primary, --text-*) — no new colour or spacing scale is introduced here.
   =================================================================================== */

/* ---- Shared message-thread component (Chat screen + Order/Product Channel tabs) ---- */
.syc-channel-thread { display: flex; flex-direction: column; min-height: 0; height: 100%; }
.syc-channel-thread-header { padding-bottom: var(--space-3); border-bottom: 1px solid var(--line-200); margin-bottom: var(--space-3); }
.syc-channel-thread-header h2 { font: var(--text-h2); color: var(--ink-700); margin: 0; }
.syc-channel-thread-header p { font: var(--text-secondary); color: var(--ink-500); margin: 4px 0 0; }

.syc-channel-messages {
  flex: 1 1 auto;
  min-height: 240px;
  max-height: 52vh;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding-right: var(--space-2);
}
/* Chat redesign (2026-08-24) — a modern compact conversation layout (avatar + name/time +
   body in flow), not every message boxed in its own card. Consecutive messages from the
   same sender within 5 minutes group under one avatar/name (.syc-channel-message-grouped),
   matching Slack/Teams' own convention rather than repeating the header every line. */
.syc-channel-message { display: flex; gap: var(--space-3); padding: var(--space-1) var(--space-2); border-radius: var(--radius-control); }
.syc-channel-message:hover { background: var(--surface-50); }
.syc-channel-message-grouped { padding-top: 0; }
.syc-channel-avatar {
  flex: none; width: 32px; height: 32px; border-radius: 50%;
  background: var(--brand-primary-subtle, var(--surface-100)); color: var(--brand-primary);
  display: flex; align-items: center; justify-content: center;
  font: var(--text-label); font-weight: 700;
}
.syc-channel-avatar-spacer { flex: none; width: 32px; }
.syc-channel-message-main { flex: 1; min-width: 0; }
.syc-channel-message-meta { display: flex; align-items: baseline; gap: var(--space-2); font: var(--text-secondary); color: var(--ink-500); margin-bottom: 2px; }
.syc-channel-message-meta strong { color: var(--ink-700); font-weight: 600; }
.syc-channel-message-body { font: var(--text-body); white-space: pre-wrap; word-break: break-word; }
.syc-channel-message-body strong { font-weight: 700; }
.syc-channel-message-body code { background: var(--surface-100); padding: 1px 4px; border-radius: 4px; font-family: monospace; font-size: .9em; }
.syc-channel-message-body blockquote { margin: var(--space-1) 0; padding-left: var(--space-3); border-left: 3px solid var(--line-200); color: var(--ink-500); }
.syc-channel-message-body ul { margin: var(--space-1) 0; padding-left: var(--space-5); }
.syc-channel-message-actions { display: flex; align-items: center; gap: var(--space-3); margin-top: var(--space-1); opacity: 0; }
.syc-channel-message:hover .syc-channel-message-actions { opacity: 1; }
.syc-channel-reply-btn,
.syc-channel-replies,
.syc-channel-pin-btn {
  background: none; border: none; padding: 0; cursor: pointer;
  font: var(--text-secondary); color: var(--brand-primary);
}
.syc-channel-reply-btn:hover, .syc-channel-replies:hover, .syc-channel-pin-btn:hover { text-decoration: underline; }
.syc-channel-pin-btn.pinned { color: var(--ink-500); }

/* ---- Reactions (Chat redesign, 2026-08-25) ---- */
.syc-channel-reactions { display: flex; flex-wrap: wrap; gap: 6px; margin-top: var(--space-2); }
.syc-channel-reaction {
  display: flex; align-items: center; gap: 5px; border: 1px solid var(--line-200); border-radius: 12px;
  padding: 1px 8px; font: var(--text-label); font-weight: 600; color: var(--ink-700); background: var(--surface-0); cursor: pointer;
}
.syc-channel-reaction:hover { border-color: var(--brand-primary); }
.syc-channel-reaction.mine { background: var(--brand-primary-subtle); border-color: var(--brand-primary); color: var(--brand-primary-active, var(--brand-primary)); }
.syc-channel-reaction-add {
  position: relative; width: 22px; height: 22px; border-radius: 11px; border: 1px solid var(--line-200);
  color: var(--ink-300); display: flex; align-items: center; justify-content: center; cursor: pointer; font-weight: 700;
}
.syc-channel-reaction-add:hover { color: var(--brand-primary); border-color: var(--brand-primary); }
.syc-channel-emoji-picker {
  display: none; position: absolute; bottom: 26px; left: 0; background: var(--surface-0); border: 1px solid var(--line-200);
  border-radius: 8px; box-shadow: var(--shadow-pop); padding: 4px; gap: 2px; z-index: 20;
}
.syc-channel-emoji-picker.open { display: flex; }
.syc-channel-emoji-picker button { width: 24px; height: 24px; border-radius: 5px; font-size: 14px; display: flex; align-items: center; justify-content: center; }
.syc-channel-emoji-picker button:hover { background: var(--surface-100); }
.syc-channel-message-pinned-flag { color: var(--brand-primary); font-size: 11px; font-weight: 700; display: inline-flex; align-items: center; gap: 3px; margin-bottom: 2px; }
.syc-channel-thread-replies { margin-top: var(--space-3); padding-left: var(--space-3); border-left: 2px solid var(--line-200); display: flex; flex-direction: column; gap: var(--space-2); }
.syc-channel-reply { background: var(--surface-0, #fff); border-radius: var(--radius-md, 8px); padding: var(--space-2) var(--space-3); }

/* Compact formatting toolbar (Chat redesign, 2026-08-24) — markdown-lite, same visual
   language as the Email/Ask toolbars/chips (small pill buttons, no tall WYSIWYG bar). */
.syc-channel-toolbar { flex: 1 1 100%; display: flex; gap: 2px; }
.syc-channel-toolbar-btn { min-width: 26px; height: 26px; padding: 0 var(--space-2); border: none; border-radius: var(--radius-control); background: none; color: var(--ink-500); font: var(--text-secondary); cursor: pointer; }
.syc-channel-toolbar-btn:hover { background: var(--surface-100); color: var(--ink-900); }

.syc-channel-composer { display: flex; gap: var(--space-2); align-items: flex-end; flex-wrap: wrap; margin-top: var(--space-3); padding-top: var(--space-3); border-top: 1px solid var(--line-200); }
.syc-channel-composer textarea { flex: 1 1 240px; min-height: 44px; }
.syc-channel-replying { flex: 1 1 100%; font: var(--text-secondary); color: var(--ink-500); margin-bottom: var(--space-1); }
.syc-channel-reply-cancel { background: none; border: none; padding: 0 0 0 var(--space-2); cursor: pointer; font: var(--text-secondary); color: var(--brand-primary); }
.syc-channel-empty { color: var(--ink-500); font: var(--text-secondary); }
.syc-channel-error { color: var(--danger); font: var(--text-secondary); margin-top: var(--space-2); }

/* ---- Chat screen layout: sidebar + thread (2026-08-25 density pass) — a flat 3-column
   workspace, no card-in-card: one continuous surface with hairline dividers between
   columns instead of three separately-shadowed .syc-card boxes, using the available
   viewport width instead of a boxed, padded grid. */
.syc-chat-layout {
  display: grid; grid-template-columns: 264px 1fr 288px; gap: 0; align-items: stretch;
  background: var(--surface-0); border: 1px solid var(--line-200); border-radius: var(--radius-card);
  overflow: hidden; height: calc(100vh - 220px); min-height: 480px;
}
.syc-chat-layout.syc-chat-layout--no-members { grid-template-columns: 264px 1fr; }
.syc-chat-layout > .syc-card {
  box-shadow: none; border-radius: 0; padding: var(--space-4); margin: 0;
  border-right: 1px solid var(--line-200); overflow-y: auto; min-width: 0;
}
.syc-chat-layout > .syc-card:last-child { border-right: none; }
@media (max-width: 1100px) { .syc-chat-layout { grid-template-columns: 240px 1fr; } .syc-chat-members { display: none; } }
@media (max-width: 900px) { .syc-chat-layout { grid-template-columns: 1fr; height: auto; } }

/* ---- Workspace-mode thread header: tabs + notification preference (2026-08-25) ---- */
.syc-channel-thread-header--workspace { display: flex; flex-direction: column; gap: 2px; }
.syc-channel-thread-title-row { display: flex; align-items: center; gap: var(--space-2); }
.syc-channel-thread-title-row h2 { font: var(--text-h2); color: var(--ink-700); margin: 0; }
.syc-channel-thread-head-actions { margin-left: auto; display: flex; align-items: center; gap: var(--space-3); color: var(--ink-500); }
.syc-channel-thread-head-actions .grp { display: flex; align-items: center; gap: 5px; font: var(--text-secondary); }
.syc-channel-thread-head-actions button { color: var(--ink-500); display: flex; align-items: center; }
.syc-channel-thread-head-actions button:hover { color: var(--brand-primary); }
.syc-channel-tabs { display: flex; align-items: center; gap: var(--space-5); border-bottom: 1px solid var(--line-200); margin-top: var(--space-2); }
.syc-channel-tab {
  padding: var(--space-2) 1px; font: var(--text-body-medium); color: var(--ink-500); border-bottom: 2px solid transparent;
  cursor: pointer; display: flex; align-items: center; gap: 6px; background: none; border-top: none; border-left: none; border-right: none;
}
.syc-channel-tab.active { color: var(--brand-primary); border-bottom-color: var(--brand-primary); }
.syc-channel-tab .badge { background: var(--brand-primary); color: #fff; font: var(--text-label); font-size: 10px; border-radius: 8px; padding: 1px 6px; }
.syc-channel-tab-panel { display: none; }
.syc-channel-tab-panel.active { display: block; }

.syc-notif-wrap { position: relative; }
.syc-notif-dropdown {
  display: none; position: absolute; top: 26px; right: 0; width: 190px; background: var(--surface-0);
  border: 1px solid var(--line-200); border-radius: 8px; box-shadow: var(--shadow-pop); padding: 4px; z-index: 30;
}
.syc-notif-dropdown.open { display: block; }
.syc-notif-option { display: flex; align-items: center; gap: 8px; padding: 7px 9px; border-radius: 6px; font: var(--text-secondary); color: var(--ink-700); cursor: pointer; }
.syc-notif-option:hover { background: var(--surface-100); }
.syc-notif-option.active { color: var(--brand-primary-active, var(--brand-primary)); font-weight: 700; background: var(--brand-primary-subtle); }

/* ---- Files/Pinned/Tasks tab panel content ---- */
.syc-channel-file-row { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-2) 0; border-bottom: 1px solid var(--line-200); }
.syc-channel-file-chip { width: 30px; height: 30px; border-radius: 6px; background: var(--surface-100); border: 1px solid var(--line-200); color: var(--ink-500); display: flex; align-items: center; justify-content: center; font: var(--text-label); font-size: 9px; flex: none; }
.syc-channel-pin-card { padding: var(--space-3); border: 1px solid var(--line-200); border-radius: 8px; margin-bottom: var(--space-3); }
.syc-channel-pin-card-meta { font: var(--text-label); color: var(--ink-300); margin-bottom: var(--space-2); display: flex; align-items: center; gap: 6px; }
.syc-channel-task-row { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-2) 0; border-bottom: 1px solid var(--line-200); }
.syc-channel-task-check { width: 16px; height: 16px; border-radius: 4px; border: 1.5px solid var(--line-200); flex: none; cursor: pointer; }
.syc-channel-task-check.done { background: var(--brand-primary); border-color: var(--brand-primary); }
.syc-channel-task-title.done { text-decoration: line-through; color: var(--ink-300); }

/* ================= Chat Members panel (2026-08-24, Channel/Chat Redesign) =================
   The workspace's third column. Collapsible via .syc-chat-members-collapsed (sets width to a
   thin strip); default open per the request. Presence dots reuse the same real online-users
   data the sidebar already polls -- no second presence source. */
.syc-chat-members { display: flex; flex-direction: column; gap: var(--space-3); }
.syc-chat-members-header { display: flex; align-items: center; justify-content: space-between; }
.syc-chat-members-header h3 { font: var(--text-section-title); margin: 0; }
.syc-chat-members-list { display: flex; flex-direction: column; gap: 2px; }
.syc-chat-member-row { display: flex; align-items: center; gap: var(--space-2); padding: var(--space-2); border-radius: var(--radius-control); }
.syc-chat-member-row:hover { background: var(--surface-50); }
.syc-chat-member-avatar {
  width: 28px; height: 28px; border-radius: 50%; flex-shrink: 0;
  background: var(--brand-primary-subtle); color: var(--brand-primary);
  display: flex; align-items: center; justify-content: center;
  font: var(--text-secondary); font-weight: 600; position: relative;
}
.syc-chat-member-presence-dot {
  position: absolute; bottom: -1px; right: -1px; width: 9px; height: 9px; border-radius: 50%;
  border: 2px solid var(--surface-0); background: var(--ink-300);
}
.syc-chat-member-presence-dot.online { background: var(--success, #2e8b57); }
.syc-chat-member-presence-dot.away { background: var(--warning, #ed6c02); }
.syc-chat-member-presence-dot.busy { background: var(--danger, #c62828); }
.syc-chat-member-name { font: var(--text-secondary); color: var(--ink-900); }
.syc-chat-member-role { font: var(--text-label); color: var(--ink-500); text-transform: uppercase; letter-spacing: var(--label-tracking); }
.syc-chat-details dt { font: var(--text-label); text-transform: uppercase; letter-spacing: var(--label-tracking); color: var(--ink-500); margin-top: var(--space-3); }
.syc-chat-details dt:first-child { margin-top: 0; }
.syc-chat-details dd { margin: 2px 0 0; font: var(--text-secondary); color: var(--ink-900); }
.syc-chat-sidebar { max-height: 70vh; overflow-y: auto; display: flex; flex-direction: column; gap: var(--space-4); }
/* Collapsible groups (Chat redesign, 2026-08-24) — click the label to fold a group away;
   .syc-channel-group-items is what actually hides, so the label + its chevron stay visible
   either way (you can always see the group exists and re-expand it). */
.syc-channel-group-label { display: flex; align-items: center; gap: 4px; font: var(--text-label); text-transform: uppercase; letter-spacing: .04em; color: var(--ink-500); margin-bottom: var(--space-2); cursor: pointer; user-select: none; background: none; border: none; width: 100%; text-align: left; padding: 0; }
.syc-channel-group-chevron { display: inline-block; transition: transform var(--motion-duration, .15s) var(--motion-easing, ease-out); }
.syc-channel-group.collapsed .syc-channel-group-chevron { transform: rotate(-90deg); }
.syc-channel-group.collapsed .syc-channel-group-items { display: none; }
.syc-channel-group + .syc-channel-group { margin-top: var(--space-4); }
.syc-channel-item {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 2px var(--space-2);
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  border-radius: var(--radius-md, 8px);
  padding: var(--space-2) var(--space-3);
  cursor: pointer;
  color: var(--ink-700);
}
.syc-channel-item:hover { background: var(--surface-50); }
.syc-channel-item.active { background: var(--surface-50); box-shadow: inset 2px 0 0 var(--brand-primary); }
.syc-channel-item-name { font: var(--text-body); font-weight: 600; }
.syc-channel-item-preview { grid-column: 1 / -1; font: var(--text-secondary); color: var(--ink-500); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.syc-channel-unread {
  grid-row: 1; align-self: center; min-width: 20px; text-align: center;
  background: var(--brand-primary); color: #fff;
  border-radius: 999px; padding: 1px 6px; font: var(--text-label); font-weight: 600;
}

/* ---- Inline presence in the Chat sidebar ----
   Presence already existed but only in the status bar ("4 online"), which tells you nothing
   about the person you are actually about to message. These render the SAME computed status
   from /api/v1/presence/online-users next to the DM you are looking at. A person with no
   presence row is simply offline — .syc-channel-dot with no status class is the neutral,
   honest default, never a green dot by accident. */
.syc-channel-dot {
  grid-row: 1; align-self: center; width: 8px; height: 8px; border-radius: 50%;
  background: var(--ink-300, #c9c9c9); flex: none;
}
.syc-channel-dot.online { background: var(--success, #2e7d32); }
.syc-channel-dot.away { background: var(--warning, #b26a00); }
.syc-channel-dot.busy { background: var(--danger, #b3261e); }
/* The DM row grows a third column for the dot; other rows keep the original 2-up grid. */
.syc-channel-item.has-dot { grid-template-columns: auto 1fr auto; }

/* ---- New conversation (DM / group) ---- */
.syc-channel-new { display: flex; gap: var(--space-2); margin-bottom: var(--space-3); }
.syc-channel-new .syc-btn { flex: 1 1 auto; }
.syc-channel-picker { margin-bottom: var(--space-3); }
.syc-channel-picker[hidden] { display: none; }
.syc-channel-picker-results { max-height: 220px; overflow-y: auto; margin-top: var(--space-2); }
.syc-channel-picker-item {
  display: grid; grid-template-columns: auto 1fr; align-items: center; gap: var(--space-2);
  width: 100%; text-align: left; background: none; border: none; cursor: pointer;
  border-radius: var(--radius-md, 8px); padding: var(--space-2) var(--space-3); color: var(--ink-700);
}
.syc-channel-picker-item:hover { background: var(--surface-50); }
.syc-channel-picker-sub { grid-column: 2; font: var(--text-secondary); color: var(--ink-500); }
.syc-channel-picker-confirm { display: flex; gap: var(--space-2); margin-top: var(--space-2); }
.syc-channel-picker-confirm[hidden] { display: none; }

/* ---- Mentions (Enterprise Workspace Layer Phase 2 §2) ----
   Render-time only: `channel_message.content` stays plain text at rest, so this styles a
   span the renderer wraps around an already-escaped, already-resolved @username. */
.syc-mention {
  color: var(--brand-primary); background: var(--brand-primary-050, rgba(155, 44, 44, .08));
  border-radius: 4px; padding: 0 3px; font-weight: 600; cursor: default;
}
.syc-channel-input-wrap { position: relative; flex: 1 1 240px; display: flex; }
.syc-channel-input-wrap textarea { flex: 1 1 auto; min-height: 44px; }
.syc-mention-panel {
  position: absolute; bottom: calc(100% + 4px); left: 0; right: 0; z-index: 40;
  max-height: 220px; overflow-y: auto;
  background: var(--surface-0, #fff); border: 1px solid var(--line-200);
  border-radius: var(--radius-md, 8px); box-shadow: var(--shadow-md, 0 6px 16px rgba(0, 0, 0, .12));
}
.syc-mention-option {
  display: flex; flex-direction: column; gap: 1px; width: 100%; text-align: left;
  background: none; border: none; cursor: pointer; padding: var(--space-2) var(--space-3);
}
.syc-mention-option strong { font: var(--text-body); font-weight: 600; color: var(--ink-700); }
.syc-mention-option span { font: var(--text-secondary); color: var(--ink-500); }
.syc-mention-option:hover, .syc-mention-option.active { background: var(--surface-50); }

/* ---- Chat message attachments (Phase 2 §3) ---- */
.syc-channel-attachments { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-top: var(--space-2); }
.syc-channel-attachment {
  display: inline-flex; align-items: baseline; gap: var(--space-2);
  background: var(--surface-0, #fff); border: 1px solid var(--line-200);
  border-radius: var(--radius-md, 8px); padding: 4px var(--space-2);
  cursor: pointer; font: var(--text-secondary); color: var(--ink-700); max-width: 100%;
}
.syc-channel-attachment:hover { border-color: var(--brand-primary); }
.syc-channel-attachment-name { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.syc-channel-attachment-size { color: var(--ink-500); flex: none; }
.syc-channel-pending { flex: 1 1 100%; display: flex; flex-wrap: wrap; gap: var(--space-2); margin-bottom: var(--space-2); }
.syc-channel-pending-file {
  display: inline-flex; align-items: center; gap: 4px;
  background: var(--surface-50); border-radius: 999px; padding: 2px var(--space-2);
  font: var(--text-secondary); color: var(--ink-700);
}
.syc-channel-pending-remove { background: none; border: none; cursor: pointer; color: var(--ink-500); font-size: 14px; line-height: 1; padding: 0 2px; }
.syc-channel-pending-remove:hover { color: var(--danger); }

/* ---- Message search (Phase 2 §4) ---- */
.syc-channel-search { display: flex; gap: var(--space-2); margin-bottom: var(--space-3); }
.syc-channel-search input { flex: 1 1 auto; min-width: 0; }
.syc-channel-search select { flex: 0 0 auto; }
.syc-channel-search-results {
  margin-bottom: var(--space-3); padding-bottom: var(--space-3);
  border-bottom: 1px solid var(--line-200); max-height: 320px; overflow-y: auto;
}
.syc-channel-hit {
  display: grid; gap: 2px; width: 100%; text-align: left;
  background: none; border: none; cursor: pointer;
  padding: var(--space-2); border-radius: var(--radius-md, 8px);
}
.syc-channel-hit:hover { background: var(--surface-50); }
.syc-channel-hit-where { font: var(--text-label); color: var(--ink-500); text-transform: none; }
.syc-channel-hit-text {
  font: var(--text-secondary); color: var(--ink-700);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.syc-channel-hit-when { font: var(--text-label); color: var(--ink-300); }
/* The message a search result or a mention notification pointed at — a brief, calm marker,
   not a permanent recolour of someone's conversation. */
.syc-channel-message-highlight {
  box-shadow: inset 3px 0 0 var(--brand-primary);
  animation: syc-highlight-fade 2.5s ease-out 1;
}
@keyframes syc-highlight-fade {
  0% { background: var(--brand-primary-050, rgba(155, 44, 44, .14)); }
  100% { background: var(--surface-50); }
}

/* ---- Presence indicator on the CB-19 status bar (additive, not a restructure) ---- */
.syc-status-bar .syc-presence { display: inline-flex; align-items: center; gap: 6px; }
.syc-presence-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--success, #2e7d32); flex: none; }
.syc-presence-count { white-space: nowrap; }
.syc-presence-stack { display: inline-flex; align-items: center; }
.syc-presence-avatar {
  width: 16px; height: 16px; border-radius: 50%;
  background: var(--brand-primary); color: #fff;
  font-size: 9px; font-weight: 600; line-height: 16px; text-align: center;
  margin-left: -4px; border: 1px solid var(--surface-0, #fff);
}
.syc-presence-avatar:first-child { margin-left: 0; }

/* ================= Entity 360° Dashboard — key/value detail list (2026-08-23,
   ENTITY_360_DASHBOARD_ARCHITECTURE.md §2). A Dashboard states a record's fields as
   READ-ONLY facts; before this the only way to show them was a disabled form input, which
   is exactly the "a form is not a dashboard" mistake this round corrects. One shared
   primitive so Buyer/Supplier — and any entity added later — render identically instead of
   each inventing its own definition list. ================= */
.syc-kv { display: grid; grid-template-columns: minmax(0, 40%) minmax(0, 60%); gap: var(--space-2) var(--space-4); margin: 0; }
.syc-kv dt { font: var(--text-label); text-transform: uppercase; letter-spacing: var(--label-tracking); color: var(--ink-500); }
.syc-kv dd { font: var(--text-body); color: var(--ink-900); margin: 0; overflow-wrap: anywhere; }
@media (max-width: 480px) {
  .syc-kv { grid-template-columns: 1fr; gap: 2px var(--space-4); }
  .syc-kv dd { margin-bottom: var(--space-2); }
}

/* ================= Calendar — month grid (2026-08-23).
   A read-only projection of dates that already live on real records (task.due_at,
   inspection.scheduled_date, customer_follow_up.follow_up_on) — there is no calendar_event
   table behind this. Day-granular on purpose: nothing in this system stores a time of day,
   so there are no hour slots to render and none are faked. Layer colours reuse the existing
   badge semantics rather than introducing a second palette. ================= */
.syc-calendar-toolbar {
  display: flex; align-items: center; gap: var(--space-3);
  margin-bottom: var(--space-4); flex-wrap: wrap;
}
.syc-calendar-title { font: var(--text-section-title); color: var(--ink-900); margin: 0; min-width: 14ch; }
.syc-calendar-legend { display: flex; gap: var(--space-3); flex-wrap: wrap; margin-left: auto; }
.syc-calendar-legend label { display: inline-flex; align-items: center; gap: 6px; font: var(--text-secondary); color: var(--ink-700); cursor: pointer; }
.syc-calendar-legend .swatch { width: 10px; height: 10px; border-radius: 2px; flex: none; }

.syc-calendar-grid {
  display: grid; grid-template-columns: repeat(7, minmax(0, 1fr));
  border: 1px solid var(--line-200); border-radius: var(--radius-md, 8px);
  overflow: hidden; background: var(--line-200); gap: 1px;
}
.syc-calendar-dow {
  background: var(--surface-100); padding: var(--space-2);
  font: var(--text-label); text-transform: uppercase; letter-spacing: var(--label-tracking);
  color: var(--ink-500); text-align: center;
}
.syc-calendar-day { background: var(--surface-0, #fff); min-height: 110px; padding: var(--space-2); }
.syc-calendar-day.outside { background: var(--surface-100); }
.syc-calendar-day.outside .syc-calendar-daynum { color: var(--ink-500); }
.syc-calendar-daynum { font: var(--text-secondary); font-weight: 600; color: var(--ink-700); display: block; margin-bottom: 4px; }
.syc-calendar-day.today .syc-calendar-daynum {
  background: var(--brand-primary); color: #fff; border-radius: 999px;
  display: inline-block; min-width: 22px; text-align: center; padding: 0 6px;
}
.syc-calendar-event {
  display: block; text-decoration: none; color: var(--ink-900);
  font: var(--text-secondary); line-height: 1.35;
  padding: 2px 4px; margin-bottom: 2px; border-radius: 3px;
  border-left: 3px solid var(--ink-500); background: var(--surface-100);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.syc-calendar-event:hover { background: var(--line-200); }
.syc-calendar-event.type-task { border-left-color: var(--brand-primary); }
.syc-calendar-event.type-inspection { border-left-color: var(--info, #0b6bcb); }
.syc-calendar-event.type-reinspection { border-left-color: var(--danger, #c62828); }
.syc-calendar-event.type-follow_up { border-left-color: var(--warning, #ed6c02); }
.syc-calendar-event.type-ncr_target_closure { border-left-color: var(--ink-500); }
.syc-calendar-event.type-meeting { border-left-color: var(--brand-green-500); }
/* CB-20 (2026-09-08) — two new layers, two new colours (no existing token fits either). */
.syc-calendar-event.type-shipment { border-left-color: #0891b2; }
.syc-calendar-event.type-certificate_expiry { border-left-color: #7c3aed; }
.syc-calendar-event.done { opacity: 0.55; text-decoration: line-through; }
.syc-calendar-more { font: var(--text-secondary); color: var(--ink-500); padding: 0 4px; }

/* ================= CB-20 (2026-09-08) — real FullCalendar (MIT, CDN), replacing the
   earlier hand-built month-grid above (kept for its colour tokens, reused verbatim by
   FullCalendar's own events via the same .syc-calendar-event.type-* classes). Only the
   chrome (toolbar/grid/cell borders/today) needs theming to fit the design system —
   event colouring is already fully handled by the rules above. ================= */
#calendarEl { background: var(--surface-0); }
.fc { font: var(--text-body); color: var(--ink-900); }
.fc .fc-toolbar-title { font: var(--text-section-title); color: var(--ink-900); }
.fc .fc-button-primary {
  background: var(--surface-0); border-color: var(--line-200); color: var(--ink-700);
  box-shadow: none; text-transform: capitalize;
}
.fc .fc-button-primary:hover { background: var(--surface-100); border-color: var(--line-200); color: var(--ink-900); }
.fc .fc-button-primary:not(:disabled).fc-button-active,
.fc .fc-button-primary:not(:disabled):active {
  background: var(--brand-primary); border-color: var(--brand-primary); color: #fff;
}
.fc .fc-button:focus { box-shadow: none; }
.fc-theme-standard td, .fc-theme-standard th, .fc-theme-standard .fc-scrollgrid { border-color: var(--line-200); }
.fc .fc-daygrid-day.fc-day-today, .fc .fc-timegrid-col.fc-day-today { background: var(--brand-primary-subtle, var(--surface-100)); }
.fc .fc-daygrid-day-number, .fc .fc-col-header-cell-cushion { color: var(--ink-700); text-decoration: none; }
.fc-event.syc-calendar-event {
  background: var(--surface-100); border-width: 0 0 0 3px; border-style: solid;
  border-radius: 3px; padding: 1px 4px; margin-bottom: 2px;
}
.fc-event.syc-calendar-event .fc-event-title, .fc-event.syc-calendar-event .fc-list-event-title a {
  color: var(--ink-900); font: var(--text-secondary);
}
.fc-event.syc-calendar-event:hover { background: var(--line-200); }
.fc-list-event.syc-calendar-event td { border-left: 3px solid transparent; }
.fc-list-event.type-task td { border-left-color: var(--brand-primary); }
.fc-list-event.type-inspection td { border-left-color: var(--info, #0b6bcb); }
.fc-list-event.type-reinspection td { border-left-color: var(--danger, #c62828); }
.fc-list-event.type-follow_up td { border-left-color: var(--warning, #ed6c02); }
.fc-list-event.type-meeting td { border-left-color: var(--brand-green-500); }
.fc-list-event.type-shipment td { border-left-color: #0891b2; }
.fc-list-event.type-certificate_expiry td { border-left-color: #7c3aed; }

/* ================= Global Skeleton Loading System (2026-08-24) =================
   Structure-shaped placeholders shown before real content loads, built entirely on the
   EXISTING shared shimmer primitives above (.syc-skeleton-block / .skeleton-cell /
   @keyframes syc-skeleton) — a second, differently-named skeleton system was deliberately
   NOT created; these are composed variants of the one real primitive, sized to match each
   real layout's own shape. See Qamodes.renderSkeleton in qamodes.js for the JS side. */
.syc-skel-line { height: 12px; border-radius: 4px; margin-bottom: var(--space-2); }
.syc-skel-line:last-child { margin-bottom: 0; }

/* Cards variant — mirrors .syc-dashboard-cards/.syc-kpi-card's real shape. */
.syc-skel-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: var(--space-4); }
.syc-skel-card { background: var(--surface-0); border-radius: var(--radius-card); box-shadow: var(--shadow-card); padding: var(--space-4) var(--space-5); }
.syc-skel-card .syc-skel-line:first-child { width: 40%; height: 10px; }
.syc-skel-card .syc-skel-line:last-child { width: 65%; height: 20px; }

/* Table variant — mirrors table.syc-table's real row height/rhythm (a row-level wrapper
   around the same .skeleton-cell already used inside a real <table>, for non-table lists). */
.syc-skel-table-row { display: flex; gap: var(--space-4); align-items: center; padding: var(--space-3) var(--space-4); border-bottom: 1px solid var(--line-200); }
.syc-skel-table-row .syc-skeleton-block { height: 14px; flex: 1; }
.syc-skel-table-row .syc-skeleton-block:first-child { flex: 0 0 24px; height: 24px; border-radius: 50%; }

/* Form variant — mirrors a label+field pair. */
.syc-skel-form-field { margin-bottom: var(--space-4); }
.syc-skel-form-field .syc-skel-line:first-child { width: 30%; height: 9px; }
.syc-skel-form-field .syc-skel-line:last-child { width: 100%; height: var(--control-height, 32px); margin-top: var(--space-1); }

/* Workspace variant — a multi-column shell (Email/Chat's own real column layout), so the
   real layout is already visible while its content streams in. */
.syc-skel-workspace { display: flex; gap: 0; height: 100%; min-height: 480px; }
.syc-skel-workspace-col { padding: var(--space-4); border-right: 1px solid var(--line-200); }
.syc-skel-workspace-col:last-child { border-right: none; }
.syc-skel-workspace-col .syc-skel-line { width: 100%; }
.syc-skel-workspace-col .syc-skel-line + .syc-skel-line { width: 75%; }

/* ================= Lightbox (shared, 2026-08-24) =================
   Was inline-scoped to product/dashboard.jsp's own <style> block; moved here (kept as a
   duplicate there rather than risking an edit to that page's working inline styles) so the
   Product Master-Detail Workspace's gallery can reuse the exact same real <ui5-dialog>
   pattern instead of a third lightbox implementation. */
.syc-lightbox-figure { margin: 0; text-align: center; }
.syc-lightbox-figure img {
  max-width: min(78vw, 900px); max-height: 68vh;
  object-fit: contain; border-radius: var(--radius-card); background: var(--surface-50);
}
.syc-lightbox-figure figcaption {
  margin-top: var(--space-3); font: var(--text-secondary); color: var(--ink-500); word-break: break-word;
}
.syc-lightbox-nav { display: flex; align-items: center; justify-content: space-between; gap: var(--space-4); margin-top: var(--space-3); }

/* ================= Product Master-Detail Workspace (2026-08-24) =================
   Two-pane list+detail shell — the list keeps its real .syc-table-wrap/.syc-table rendering
   unchanged, the detail panel reuses .syc-card/.syc-kv/.syc-badge, so this is layout-only. */
.syc-mdw-shell { display: flex; gap: var(--space-4); align-items: flex-start; }
.syc-mdw-list { flex: 1 1 100%; min-width: 0; transition: flex-basis var(--motion-duration) var(--motion-easing); }
.syc-mdw-list.syc-mdw-list-narrow { flex: 0 0 56%; }
.syc-mdw-panel {
  flex: 1 1 44%; min-width: 340px; max-width: 100%;
  background: var(--surface-0); border: 1px solid var(--line-200); border-radius: var(--radius-card);
  box-shadow: var(--shadow-card); position: sticky; top: var(--space-4);
  max-height: calc(100vh - 2 * var(--space-4)); overflow-y: auto;
}
.syc-mdw-panel-header {
  display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-3);
  padding: var(--space-4); border-bottom: 1px solid var(--line-200);
  position: sticky; top: 0; background: var(--surface-0); z-index: 1;
}
.syc-mdw-panel-code { font: var(--text-label); text-transform: uppercase; letter-spacing: var(--label-tracking); color: var(--ink-500); }
.syc-mdw-panel-name { font: var(--text-page-title); margin: 2px 0 var(--space-2); }
.syc-mdw-panel-nav { display: flex; align-items: center; gap: var(--space-1); flex-shrink: 0; }
.syc-mdw-panel-nav .syc-icon-btn:disabled { opacity: .35; cursor: default; }
.syc-mdw-panel-body { padding: var(--space-4); display: flex; flex-direction: column; gap: var(--space-4); }
.syc-mdw-overview-grid { display: grid; grid-template-columns: 120px 1fr; gap: var(--space-4); }
.syc-mdw-summary { grid-column: 1 / -1; }
.syc-mdw-photo {
  width: 120px; height: 120px; border-radius: var(--radius-card); overflow: hidden;
  background: var(--surface-50); border: 1px solid var(--line-200);
  display: flex; align-items: center; justify-content: center;
}
.syc-mdw-photo img { width: 100%; height: 100%; object-fit: cover; }
.syc-mdw-photo-placeholder { font: var(--text-secondary); color: var(--ink-500); }
.syc-mdw-quick-actions { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.syc-mdw-quick-action {
  display: inline-flex; align-items: center; padding: var(--space-2) var(--space-3);
  border: 1px solid var(--line-200); border-radius: var(--radius-control);
  font: var(--text-secondary); color: var(--ink-900); text-decoration: none; cursor: pointer;
  background: var(--surface-0);
}
.syc-mdw-quick-action:hover { background: var(--surface-50); border-color: var(--brand-primary); color: var(--brand-primary); }
.syc-mdw-gallery { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.syc-mdw-gallery-thumb {
  width: 64px; height: 64px; border-radius: var(--radius-control); border: 1px solid var(--line-200);
  background-size: cover; background-position: center; cursor: zoom-in; padding: 0;
}
@media (max-width: 900px) {
  .syc-mdw-shell { flex-direction: column; }
  .syc-mdw-list.syc-mdw-list-narrow { flex-basis: auto; }
  .syc-mdw-panel { position: static; max-height: none; width: 100%; }
}

/* ================= Floating Shortcut Dock (2026-08-24; draggable 2026-09-10) =========
   A small vertical pill, global (footer.jsp), viewport-level chrome — position:fixed, never
   scrolls with the page, never shifts layout. Default bottom-right; the whole pill is a drag
   surface (Qamodes.initShortcutDock resolves the stored edge-anchored position into left/top
   and hard-clamps it fully on-screen). The CSS default below is also bottom-right, so first
   paint matches the resolved default with no flash. Sits above the status bar's z-index (60)
   but the default dy clears its real 30px height. See FLOATING_SHORTCUT_DOCK.md. */
.syc-shortcut-dock {
  position: fixed; right: 28px; bottom: 44px; top: auto; left: auto;
  z-index: 65;
  display: flex; flex-direction: column; gap: 2px;
  background: var(--surface-0); border: 1px solid var(--line-200); border-radius: 999px;
  box-shadow: var(--shadow-pop); padding: var(--space-2) 6px;
  cursor: grab; touch-action: none;
}
.syc-shortcut-dock.is-dragging { cursor: grabbing; transition: none; user-select: none; }
.syc-shortcut-dock.is-snapping { transition: left .2s var(--motion-easing), top .2s var(--motion-easing); }
@media (prefers-reduced-motion: reduce) { .syc-shortcut-dock.is-snapping { transition: none; } }
/* Collapsed → just the Ask FAB floating on its own (matches the reference visual's collapsed
   state). The rail's own chrome disappears so it never reads as an intrusive toolbar. */
.syc-shortcut-dock.is-collapsed {
  background: transparent; border-color: transparent; box-shadow: none; padding: 0;
}
.syc-shortcut-dock.is-collapsed .syc-shortcut-dock-item:not(.syc-shortcut-dock-item--ask),
.syc-shortcut-dock.is-collapsed .syc-shortcut-dock-toggle { display: none; }
.syc-shortcut-dock.is-collapsed .syc-shortcut-dock-item--ask { margin-top: 0; }
/* Collapse chevron — a subtle, low-contrast affordance at the top of the pill; doubles as an
   obvious grab point. Not a developer-style drag handle: faint until hover. */
.syc-shortcut-dock-toggle {
  display: flex; align-items: center; justify-content: center;
  width: 36px; height: 16px; margin-bottom: 1px; padding: 0;
  border: none; background: none; color: var(--ink-300); cursor: pointer; border-radius: 8px;
  touch-action: none;
}
.syc-shortcut-dock-toggle:hover { color: var(--ink-700); background: var(--surface-50); }
.syc-shortcut-dock-item {
  display: flex; align-items: center; justify-content: center;
  width: 36px; height: 36px; border-radius: 50%;
  color: var(--ink-700); background: none; border: none; text-decoration: none; cursor: pointer;
  touch-action: none;
}
.syc-shortcut-dock-item:hover { background: var(--surface-50); color: var(--brand-primary); }
.syc-shortcut-dock-item:focus-visible,
.syc-shortcut-dock-toggle:focus-visible { outline: 2px solid var(--brand-primary); outline-offset: 2px; }
.syc-shortcut-dock-item ui5-icon { width: 18px; height: 18px; }
/* Slightly larger hit areas on touch devices (spec §12) */
@media (pointer: coarse) {
  .syc-shortcut-dock-item { width: 40px; height: 40px; }
  .syc-shortcut-dock-item--ask { width: 46px; height: 46px; }
}
/* Ask QAModes (2026-08-25 "final placement" correction) — last item in the dock, but the
   only one that opens a panel in place rather than navigating, so it stays visually distinct:
   larger, gradient-filled, a soft pulse ring. Not a 5th icon — same 4, reordered. */
.syc-shortcut-dock-item--ask {
  width: 42px; height: 42px; margin-top: 4px; color: #fff;
  background: linear-gradient(135deg, var(--brand-green-700, var(--brand-primary)), var(--brand-green-800, #124430));
  box-shadow: 0 3px 10px rgba(18, 68, 48, .35);
}
.syc-shortcut-dock-item--ask svg { width: 19px; height: 19px; }
.syc-shortcut-dock-item--ask:hover { background: linear-gradient(135deg, var(--brand-green-700, var(--brand-primary)), var(--brand-green-800, #124430)); opacity: .92; }
.syc-shortcut-dock-item--ask.active { box-shadow: 0 0 0 3px var(--brand-primary-subtle), 0 3px 10px rgba(18, 68, 48, .35); }

/* ================= Ask QAModes floating panel (2026-08-25) =====================
   Replaces the old <ui5-dialog> command center — a real custom floating panel, anchored
   above the Floating Shortcut Dock, that never navigates away from the underlying page.
   Minimize and the × both just hide it (state — typed query, rendered results — is kept in
   the DOM, not destroyed), so reopening never loses an in-progress query. */
.syc-ask-panel {
  position: fixed; right: var(--space-4); bottom: 40px; z-index: 70;
  width: 400px; max-width: calc(100vw - 32px); max-height: min(560px, calc(100vh - 100px));
  background: var(--surface-0); border: 1px solid var(--line-200); border-radius: 14px;
  box-shadow: var(--shadow-modal); display: flex; flex-direction: column; overflow: hidden;
  opacity: 0; transform: translateY(14px) scale(.98); pointer-events: none;
  transition: opacity 160ms var(--motion-easing), transform 160ms var(--motion-easing);
}
.syc-ask-panel.open { opacity: 1; transform: translateY(0) scale(1); pointer-events: auto; }
@media (max-width: 640px) {
  .syc-ask-panel { right: 8px; left: 8px; bottom: 8px; top: 8px; width: auto; max-width: none; max-height: none; border-radius: 12px; }
}
.syc-ask-panel-head { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-4) var(--space-4) var(--space-2); flex: none; }
.syc-ask-panel-spark {
  width: 28px; height: 28px; border-radius: 50%; flex: none; display: flex; align-items: center; justify-content: center;
  background: linear-gradient(135deg, var(--brand-green-700, var(--brand-primary)), var(--brand-green-800, #124430)); color: #fff;
}
.syc-ask-panel-spark svg { width: 14px; height: 14px; }
.syc-ask-panel-title { flex: 1; min-width: 0; }
.syc-ask-panel-title .h { font: var(--text-body-medium); font-weight: 700; }
.syc-ask-panel-title .s { font: var(--text-label); color: var(--ink-500); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.syc-ask-panel-win { display: flex; gap: 4px; flex: none; }
.syc-ask-panel-win button { width: 24px; height: 24px; border-radius: 6px; border: none; background: none; color: var(--ink-300); cursor: pointer; display: flex; align-items: center; justify-content: center; font-size: 15px; line-height: 1; }
.syc-ask-panel-win button:hover { background: var(--surface-100); color: var(--ink-700); }
.syc-ask-panel-body { padding: 0 var(--space-4) var(--space-3); overflow-y: auto; flex: 1; min-height: 0; }
.syc-ask-panel-prompt { font: var(--text-section-title); margin: 2px 0 var(--space-3); }
.syc-ask-panel-foot {
  padding: var(--space-2) var(--space-4); border-top: 1px solid var(--line-200); flex: none;
  font: var(--text-label); color: var(--ink-300); display: flex; align-items: center; gap: 5px;
}
.syc-ask-panel-foot svg { width: 10px; height: 10px; color: var(--brand-primary); flex: none; }
.syc-ask-skel-chip {
  display: inline-block; width: 76px; height: 24px; border-radius: 999px; margin: 0 var(--space-2) var(--space-2) 0;
  background: linear-gradient(90deg, var(--line-200), var(--surface-50), var(--line-200)); background-size: 200% 100%;
  animation: syc-ask-shimmer 1.6s infinite;
}
@media (prefers-reduced-motion: reduce) { .syc-ask-skel-chip { animation: none; } }
@keyframes syc-ask-shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }
.syc-ask-confirm-card { border: 1.5px dashed var(--brand-primary); border-radius: var(--radius-control); padding: var(--space-3); background: var(--brand-primary-subtle); margin-top: 2px; }
.syc-ask-confirm-card .ttl { font: var(--text-body-medium); color: var(--brand-primary); margin-bottom: var(--space-2); }
.syc-ask-confirm-card .note { font: var(--text-secondary); color: var(--ink-500); margin-bottom: var(--space-3); }
.syc-ask-confirm-btns { display: flex; gap: var(--space-2); }
.syc-ask-confirm-btns .syc-btn { flex: 1; }

/* ================= System-Wide Contextual Comment Mode (2026-08-25) =====================
   Global toggle (header icon, wired by Qamodes.initCommentMode) that turns any element
   marked with real data-cm-* attributes into a commentable target — real, not per-page
   bespoke UI. Reuses the existing generic ActivityEvent comment mechanism (context_type/
   context_ref, V72) — this is a UI layer over an already-real, already-verified backend,
   not a new comment system. ============================================================ */
body.syc-comment-mode-on [data-cm-context-ref] {
  cursor: pointer; position: relative; border-radius: var(--radius-control);
  outline: 1.5px dashed transparent; outline-offset: -1.5px;
}
body.syc-comment-mode-on [data-cm-context-ref]:hover {
  outline-color: var(--brand-primary); background: var(--brand-primary-subtle);
}
.syc-cm-pin-badge {
  display: none; align-items: center; gap: 3px; position: absolute; top: -8px; right: -8px;
  background: var(--brand-primary); color: #fff; font: var(--text-label); font-size: 10px; font-weight: 700;
  border-radius: 10px; padding: 1px 6px 1px 5px; z-index: 5; line-height: 1.4;
}
body.syc-comment-mode-on .syc-cm-pin-badge.has-count { display: inline-flex; }

.syc-cm-banner {
  display: none; align-items: center; gap: var(--space-2); background: var(--brand-green-800, var(--brand-primary-active));
  color: #fff; font: var(--text-secondary); font-weight: 600; padding: var(--space-2) var(--space-5);
}
body.syc-comment-mode-on .syc-cm-banner { display: flex; }
.syc-cm-banner .esc { margin-left: auto; font-weight: 400; opacity: .85; }
.syc-cm-banner kbd { border: 1px solid rgba(255,255,255,.4); border-radius: 4px; padding: 0 5px; font-size: 10.5px; }

.syc-cm-scrim { display: none; position: fixed; inset: 0; z-index: 200; }
.syc-cm-scrim.open { display: block; }
.syc-cm-popover {
  display: none; position: fixed; width: 290px; background: var(--surface-0); border: 1px solid var(--line-200);
  border-radius: 10px; box-shadow: var(--shadow-pop); z-index: 201; overflow: hidden;
}
.syc-cm-popover.open { display: block; }
.syc-cm-popover-target { font: var(--text-label); font-weight: 700; color: var(--brand-primary); text-transform: uppercase; letter-spacing: .03em; padding: var(--space-3) var(--space-4) 0; }
.syc-cm-popover-head { display: flex; align-items: center; gap: var(--space-2); padding: var(--space-2) var(--space-4) 0; }
.syc-cm-popover-avatar { width: 26px; height: 26px; border-radius: 50%; background: var(--brand-primary-subtle); color: var(--brand-primary); display: flex; align-items: center; justify-content: center; font: var(--text-label); font-weight: 700; flex: none; }
.syc-cm-popover-name { font: var(--text-secondary); font-weight: 700; }
.syc-cm-popover textarea { width: 100%; border: none; resize: none; padding: var(--space-3) var(--space-4); font: var(--text-body); min-height: 56px; }
.syc-cm-popover textarea:focus { outline: none; }
.syc-cm-popover-foot { display: flex; align-items: center; gap: var(--space-2); padding: var(--space-2) var(--space-3); border-top: 1px solid var(--line-200); }
.syc-cm-popover-foot .spacer { margin-left: auto; }
.syc-cm-popover-foot .cancel { font: var(--text-label); color: var(--ink-500); font-weight: 600; cursor: pointer; padding: 0 var(--space-2); }
.syc-cm-popover-foot .send { background: var(--brand-primary); color: #fff; font: var(--text-label); font-weight: 700; border-radius: 6px; padding: var(--space-2) var(--space-3); }
.syc-cm-popover-foot .send:hover { background: var(--brand-primary-hover); }

/* Thread panel reuses .syc-slideover — just its own content classes. */
.syc-cm-thread-target { font: var(--text-label); font-weight: 700; color: var(--brand-primary); text-transform: uppercase; letter-spacing: .03em; }
.syc-cm-thread-status { display: flex; align-items: center; gap: var(--space-2); margin: var(--space-2) 0 var(--space-4); }
.syc-cm-status-pill { font: var(--text-label); font-weight: 700; padding: 2px 9px; border-radius: 10px; }
.syc-cm-status-pill.open { background: var(--warning-bg); color: var(--warning); }
.syc-cm-status-pill.resolved { background: var(--brand-primary-subtle); color: var(--brand-primary); }
.syc-cm-resolve-btn { margin-left: auto; font: var(--text-secondary); font-weight: 700; color: var(--brand-primary); cursor: pointer; }
.syc-cm-comment { display: flex; gap: var(--space-2); margin-bottom: var(--space-4); }
.syc-cm-comment.reply { margin-left: 26px; }
.syc-cm-c-avatar { width: 28px; height: 28px; border-radius: 50%; background: var(--brand-primary-subtle); color: var(--brand-primary); display: flex; align-items: center; justify-content: center; font: var(--text-label); font-weight: 700; flex: none; }
.syc-cm-c-meta { display: flex; align-items: baseline; gap: var(--space-2); }
.syc-cm-c-name { font: var(--text-secondary); font-weight: 700; }
.syc-cm-c-time { font: var(--text-label); color: var(--ink-300); }
.syc-cm-c-text { font: var(--text-body); margin-top: 2px; white-space: pre-wrap; }
.syc-cm-c-actions { display: flex; gap: var(--space-3); margin-top: 4px; font: var(--text-label); color: var(--ink-500); font-weight: 600; }
.syc-cm-c-actions span { cursor: pointer; }
.syc-cm-c-actions span:hover { color: var(--brand-primary); }
.syc-cm-reply-box { border-top: 1px solid var(--line-200); padding-top: var(--space-3); margin-top: var(--space-2); }
.syc-cm-reply-box textarea { width: 100%; }

/* ================= Global Comment Drawer (2026-08-25, Comment Mode Phase 2A) =====================
   Cross-context comment list — real Open/Resolved/All filter + search over the same real
   ActivityEventDto/RecentCommentDto rows the object's own Comments Drawer and Ask QAModes'
   search results already use, not a new data shape. */
.syc-gcd-tabs { display: flex; gap: var(--space-2); margin-bottom: var(--space-3); }
.syc-gcd-tab { font: var(--text-label); padding: 4px 12px; border-radius: 999px; border: 1px solid var(--line-200); background: var(--surface-0); color: var(--ink-500); cursor: pointer; }
.syc-gcd-tab.active { background: var(--brand-primary); border-color: var(--brand-primary); color: #fff; font-weight: 700; }
.syc-gcd-row { padding: var(--space-3) 0; border-bottom: 1px solid var(--line-200); cursor: pointer; }
.syc-gcd-row:hover { background: var(--surface-50); }
.syc-gcd-row-top { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-2); }
.syc-gcd-row-top strong { font: var(--text-secondary); font-weight: 700; color: var(--ink-900); }
.syc-gcd-time { font: var(--text-label); color: var(--ink-300); flex: none; }
.syc-gcd-where { font: var(--text-label); color: var(--brand-primary); text-transform: uppercase; letter-spacing: var(--label-tracking); margin: 2px 0; display: flex; align-items: center; gap: var(--space-2); }
.syc-gcd-text { font: var(--text-body); color: var(--ink-700); margin-top: 2px; }

/* Real open-count badge on a plain dock item (Comments) — same visual language as the
   status bar's existing count badge, just anchored to the icon's corner. */
.syc-shortcut-dock-item { position: relative; }
.syc-dock-badge {
  position: absolute; top: 2px; right: 2px; min-width: 15px; height: 15px; padding: 0 3px;
  border-radius: 8px; background: var(--brand-primary); color: #fff; font-size: 9.5px; font-weight: 700;
  display: flex; align-items: center; justify-content: center; line-height: 1; pointer-events: none;
}
/* (narrow-viewport handling is now done by Qamodes.initShortcutDock's clamp, not a fixed
   right override — the dock keeps whatever edge the user parked it on and stays on-screen) */

/* P5/P6 QA fix (2026-10-08): the fixed Floating Shortcut Dock (~260px tall at the bottom-right)
   covered the row-action buttons of the last rows of long tables, and with only the status
   bar's 30px reserved those rows could never scroll clear of it. Reserve room below the
   content whenever the dock is shown expanded, so every row can be scrolled above it. */
body:has(.syc-shortcut-dock:not(.is-collapsed)) .syc-content { padding-bottom: 280px; }
body:has(.syc-shortcut-dock.is-collapsed) .syc-content { padding-bottom: 96px; }
