@layer components {
  /* Broker workspace (employee dashboard). The shared app chrome and
     primitives (sidebar, topbars, drawer, cards, panels, modals, tiles,
     labels, titles, stacks, chips, flat rows, empty states) live in
     app-shell.css as .app-*; this file holds only workspace-specific
     components — mostly the grid geometry of its dense screens and the
     per-variant custom properties those primitives read. Spacing/type/color
     come from the
     base.css tokens; the only off-scale values are structural constants
     (content max 960px, kanban column 264px, 42px controls, icon/avatar
     tiles). */
  .workspace-body {
    --app-content-max-width: 960px; /* readable width for dense screens */
  }

  /* Sidebar nav group labels */
  .ws-nav-group-label {
    --label-weight: 700;
    --label-color: var(--text-tertiary);
    margin-top: var(--spacing-sm);
    padding: 0 14px 2px; /* rows' 12px tap-target padding + 2px border-left, so labels align with icons */
  }

  /* Sidebar nav badge */
  .ws-nav-count {
    margin-left: auto;
    background: var(--surface-cream-dark);
    color: var(--text-secondary);
    font-size: var(--text-xs);
    font-weight: 600;
    border-radius: var(--radius-full);
    padding: 1px 8px; /* compact badge; deliberately off-scale */
  }
  .app-nav-row.active .ws-nav-count {
    background: var(--accent-wash);
    color: var(--accent);
  }
  .ws-sidebar-user {
    padding: var(--spacing-sm) var(--spacing-md);
    border-top: 1px solid var(--border-subtle);
    display: grid;
    grid-template-columns: 1fr auto; /* meta hugs the left edge, avatar the right */
    align-items: center;
    gap: var(--spacing-xs) var(--spacing-sm);

    /* button_to wraps the sign-out button in a form; contents makes the
       button itself the grid item so ws-signout's grid-column applies to
       it (same trick as .alt-login-buttons). Without this the form lands
       in the meta column. */
    form {
      display: contents;
    }
  }
  .ws-avatar {
    --tile-size: 36px; /* mockup avatar size */
    --tile-radius: var(--radius-full);
    border: 1px solid var(--border-subtle);
    font-size: var(--text-xs);
    font-weight: 700;
    color: var(--accent);
  }
  .ws-sidebar-user-meta {
    min-width: 0;
  }
  .ws-sidebar-user-name {
    font-size: var(--text-sm);
    font-weight: 600;
    color: var(--text-primary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .ws-sidebar-user-role {
    font-size: var(--text-xs);
    color: var(--text-tertiary);
  }
  .ws-signout {
    grid-column: 1 / -1;
    margin-top: 0;
  }

  /* Topbar subtitle (workspace topbars carry an optional second line);
     detail-page headers reuse the same treatment as .ws-detail-sub */
  .ws-topbar-subtitle,
  .ws-detail-sub {
    font-size: var(--text-sm);
    color: var(--text-tertiary);
    margin-top: var(--spacing-nudge);
  }

  .ws-list-header {
    --label-size: var(--text-sm);
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    margin-bottom: var(--spacing-sm);
  }
  /* A section header that follows any block gets spaced off it — most
     section blocks (cards, panels, timelines, empty states) carry no
     trailing margin of their own, and block-flow collapsing absorbs this
     where one does. The rail cue opts out: it is itself a header for the
     list below, not a section block. */
  .ws-list-header:not(:first-child) {
    margin-top: var(--spacing-lg);
  }
  .ws-rail-cue + .ws-list-header {
    margin-top: 0;
  }
  .ws-legend {
    display: flex;
    align-items: center;
    gap: var(--spacing-xxs);
    font-size: var(--text-xs);
    font-weight: 400;
    color: var(--text-tertiary);
    text-transform: none;
    letter-spacing: var(--tracking-normal);
  }
  .ws-legend::before {
    content: "";
    width: 9px; /* mockup legend swatch */
    height: 9px;
    border-radius: 2px;
    background: var(--accent);
  }

  /* Compact inputs (quick-add bars, toolbars, modal forms) */
  .ws-input,
  .ws-select,
  .ws-textarea {
    height: 42px; /* mockup control height */
    box-sizing: border-box;
    padding: 0 var(--spacing-sm);
    border: 1px solid var(--border-default);
    border-radius: var(--radius-md);
    font-size: var(--text-sm);
    color: var(--text-primary);
    background: var(--surface-card);
  }
  .ws-textarea {
    height: auto;
    min-height: 84px; /* roomy enough for notes */
    padding: var(--spacing-xs) var(--spacing-sm);
  }
  /* Element-qualified so date_fields sharing .ws-select keep their native
     picker chrome — appearance: none only belongs on real selects. */
  select.ws-select {
    appearance: none;
    cursor: pointer;
    padding-right: calc(2 * var(--spacing-sm) + 12px); /* caret + a gap each side */
    background-image: var(--select-caret);
    background-repeat: no-repeat;
    background-position: right var(--spacing-sm) center;
    background-size: 12px; /* caret glyph size */
  }
  .ws-input:focus,
  .ws-select:focus,
  .ws-textarea:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: var(--shadow-focus);
  }
  .ws-form-row {
    display: flex;
    gap: var(--spacing-xs);
    align-items: center;
  }
  /* Child combinator on purpose: this grows only the bare inputs of
     quick-add bars. An input nested in a .ws-field is a column-flex item,
     where flex: 1 zeroes the flex-basis and collapses the 42px height. */
  .ws-form-row > .ws-input {
    flex: 1;
    min-width: 0;
  }
  /* Labeled fields sharing a row split it evenly and fill it — their inner
     controls are width: 100%, so the halves stay aligned across rows
     regardless of each control's intrinsic width. Such a row is a grid and
     its fields are subgrids, so every label sits on one shared label track
     and every control on one shared control track: a label that wraps to two
     lines grows the track for the whole row instead of pushing its own
     control out of line with its neighbour's. */
  .ws-form-row:has(> .ws-field) {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: 1fr;
    grid-template-rows: auto auto;
    column-gap: var(--spacing-xs);
    row-gap: var(--spacing-xxs);
  }
  .ws-form-row > .ws-field {
    min-width: 0;
    display: grid;
    grid-template-rows: subgrid;
    grid-row: span 2;
  }
  /* A field with no label of its own (a lone checkbox) says so with the
     modifier and sits on the control track, not the label track. */
  .ws-form-row > .ws-field--unlabeled {
    grid-row: 2;
  }
  .ws-form-row .btn-sm {
    height: 42px; /* matches the 42px control height of the row's inputs */
    padding-block: 0;
  }
  .ws-field {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-xxs);
    margin-bottom: var(--spacing-sm);
  }
  /* Field labels carry the .app-label treatment from app-shell.css, which
     names .ws-field > label in its selector list. */
  .ws-field .ws-input,
  .ws-field .ws-select,
  .ws-field .ws-textarea {
    width: 100%;
  }

  /* Inline action chips (kanban cards, license rows) */
  .ws-chip {
    display: inline-flex;
    align-items: center;
    gap: var(--spacing-xxs);
    border: 1px solid var(--border-default);
    background: var(--surface-card);
    border-radius: var(--radius-full);
    padding: var(--spacing-xxs) var(--spacing-xs);
    font-size: var(--text-xs);
    font-weight: 600;
    color: var(--text-secondary);
    text-decoration: none;
    cursor: pointer;
    transition: border-color 0.2s, color 0.2s;
  }
  .ws-chip:hover {
    border-color: var(--accent);
    color: var(--accent);
  }
  .ws-chip--danger:hover {
    border-color: var(--semantic-danger);
    color: var(--semantic-danger);
  }

  /* Due-date labels */
  .ws-due {
    font-size: var(--text-xs);
    color: var(--text-secondary);
    white-space: nowrap;
  }
  .ws-due--overdue {
    color: var(--semantic-danger);
    font-weight: 700;
  }
  .ws-due--today {
    color: var(--accent);
    font-weight: 700;
  }

  /* Kanban boards */
  .ws-toolbar {
    display: flex;
    align-items: center;
    gap: var(--spacing-xs);
    flex-wrap: wrap;
    margin-bottom: var(--spacing-sm);
  }
  .ws-toolbar-stat {
    font-size: var(--text-sm);
    color: var(--text-secondary);
  }
  .ws-toolbar-stat strong {
    color: var(--text-primary);
  }
  .ws-toolbar-spacer {
    margin-left: auto;
  }
  /* Toolbar controls share the 42px control height so filter chips and
     action buttons read as one row of equal-weight actions. */
  .ws-toolbar .btn-sm,
  .ws-toolbar .ws-chip {
    height: 42px; /* matches the 42px control height */
    padding-block: 0;
  }
  .ws-toolbar .ws-chip {
    font-size: var(--text-sm);
    padding-inline: var(--spacing-sm);
  }
  .ws-board {
    display: flex;
    gap: var(--spacing-sm);
    align-items: flex-start;
    overflow-x: auto;
  }
  /* Scroll containers clip child shadows in both axes (overflow-y: visible
     next to a scrolling axis computes to auto, so it can't opt out); pad
     inside the clip by --shadow-card's full reach — 32px above / 48px
     beside / 64px below (offset 16 + blur 48) — and pull back with matching
     negative margins so shadows never hit the clip edge. Table wraps get
     vertical room only: their tables meet the side clip flush when they
     overflow (13-week cashflow), so side room would just let the table
     bleed past the content column's edge. */
  .ws-board {
    padding: 32px 48px 64px;
    margin: -32px -48px -64px;
  }
  .ws-table-wrap {
    padding-block: 32px 64px;
    margin-block: -32px -64px;
  }
  .ws-board-column {
    flex: 1 0 264px; /* grow to fill the toolbar-width row; 264px column minimum per design spec */
  }
  .ws-board-column-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: var(--spacing-xs);
  }
  .ws-board-column-count {
    background: var(--surface-cream-dark);
    border-radius: var(--radius-full);
    padding: 1px 8px; /* compact badge */
  }
  .ws-board-cards {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-xs);
  }
  .ws-board-card {
    display: block;
    background: var(--surface-card);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-lg);
    padding: var(--spacing-sm);
    box-shadow: var(--shadow-card);
    text-decoration: none;
    color: var(--text-primary);
    transition: box-shadow 0.2s;
  }
  .ws-board-card:hover {
    box-shadow: var(--shadow-hover);
  }
  /* Card with an outreach step surfacing on Today: amber wash layered over
     the card surface (the wash is translucent, so it needs an opaque base)
     plus an edge accent readable at board-scanning distance. */
  .ws-board-card--attention {
    background: linear-gradient(var(--semantic-warning-wash), var(--semantic-warning-wash)), var(--surface-card);
    border-left: 3px solid var(--semantic-warning); /* attention edge accent */
  }
  .ws-board-card-title {
    font-size: var(--text-sm);
    font-weight: 600;
    margin-bottom: var(--spacing-nudge);
  }
  .ws-board-card-meta {
    font-size: var(--text-xs);
    color: var(--text-tertiary);
  }
  .ws-board-card-premium {
    font-size: var(--text-sm);
    font-weight: 600;
    color: var(--accent);
    margin: var(--spacing-xxs) 0;
  }
  .ws-board-card-chips {
    display: flex;
    gap: var(--spacing-xxs);
    flex-wrap: wrap;
    margin-top: var(--spacing-xs);
  }

  /* Detail pages */
  .ws-back-link {
    display: inline-block;
    font-size: var(--text-sm);
    color: var(--text-secondary);
    text-decoration: none;
    margin-bottom: var(--spacing-sm);
  }
  .ws-back-link:hover {
    color: var(--accent);
  }
  .ws-detail-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--spacing-sm);
    align-items: start;
  }

  /* Timelines (stage history, renewal history) */
  .ws-timeline {
    list-style: none;
  }
  .ws-timeline li {
    position: relative;
    padding: 0 0 var(--spacing-sm) var(--spacing-md);
  }
  .ws-timeline li::before {
    content: "";
    position: absolute;
    left: 0;
    top: 5px; /* aligns dot with first text line */
    width: 9px;
    height: 9px;
    border-radius: var(--radius-full);
    background: var(--accent);
  }
  .ws-timeline li:not(:last-child)::after {
    content: "";
    position: absolute;
    left: 4px;
    top: 18px;
    bottom: 2px;
    width: 1px;
    background: var(--border-default);
  }
  .ws-timeline-title {
    font-size: var(--text-sm);
    font-weight: 600;
  }
  .ws-timeline-meta {
    font-size: var(--text-xs);
    color: var(--text-tertiary);
  }

}
