/* Component-specific styles extracted from layout */

/* ============================================================
   Turbo frames — global, and load-bearing

   A frame normally shouldn't introduce a box: it wraps content that
   belongs to the parent's flex/grid flow, so `display: contents` lets
   that content participate directly. This rule started life as a bare
   `turbo-frame` selector in the now-retired `job_search_planning.css`
   (#1748), aimed only at the planned-actions table — but every
   stylesheet ships in the `:app` bundle, so it silently applied to
   every frame in the app.

   That is fatal for `loading="lazy"`. Turbo drives lazy loading off an
   IntersectionObserver, which never fires for an element with no layout
   box — so a `display: contents` lazy frame NEVER FETCHES. No request,
   no console error, just an empty frame forever;
   `getBoundingClientRect()` reads 0x0 on a visibly-open frame. It cost
   a cycle to find (Concept A, S4).

   So: contents for the eager frames that want to disappear into their
   parent's layout, a real block box for the lazy ones that must be
   observable. Scoped by `loading` rather than by id or page, because the
   rule is about how Turbo loads a frame, not about where it lives.
   ============================================================ */
turbo-frame:not([loading="lazy"]) { display: contents; }
turbo-frame[loading="lazy"]      { display: block; }

/* Buttons */
.btn-primary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .4rem;
  padding: .55rem .9rem;
  border-radius: var(--bp-r-md);
  border: none;
  background: var(--bp-accent);
  color: var(--bp-accent-ink);
  text-decoration: none;
  font-weight: 600;
  transition: filter var(--bp-dur-fast) var(--bp-easing), transform var(--bp-dur-fast) var(--bp-easing);
}
.btn-primary:hover { filter: brightness(1.1); }
.btn-primary:active { transform: translateY(1px); }

a.btn-secondary,
button.btn-secondary,
input[type=submit].btn-secondary,
form.btn-secondary > input[type=submit],
form.btn-secondary > button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .4rem;
  padding: .55rem .9rem;
  border-radius: var(--bp-r-md);
  background: var(--bp-paper);
  color: var(--bp-ink);
  text-decoration: none;
  font-weight: 600;
  border: 1px solid var(--bp-rule);
  transition: background var(--bp-dur-fast) var(--bp-easing), transform var(--bp-dur-fast) var(--bp-easing), border-color var(--bp-dur-fast) var(--bp-easing);
  cursor: pointer;
}
a.btn-secondary:hover,
button.btn-secondary:hover,
input[type=submit].btn-secondary:hover,
form.btn-secondary > input[type=submit]:hover,
form.btn-secondary > button:hover {
  background: var(--bp-surface);
  border-color: var(--bp-ink-muted);
}
a.btn-secondary:active,
button.btn-secondary:active,
input[type=submit].btn-secondary:active,
form.btn-secondary > input[type=submit]:active,
form.btn-secondary > button:active {
  transform: translateY(1px);
}

.btn-secondary.disabled {
  opacity: 0.5;
  cursor: not-allowed;
  pointer-events: none;
}

/* Colored button variants */
a.btn-success,
button.btn-success,
input[type=submit].btn-success,
form.btn-success > input[type=submit],
form.btn-success > button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .4rem;
  padding: .55rem .9rem;
  border-radius: var(--bp-r-md);
  background: var(--bp-success);
  color: var(--bp-accent-ink);
  text-decoration: none;
  font-weight: 600;
  border: none;
  transition: filter var(--bp-dur-fast) var(--bp-easing), transform var(--bp-dur-fast) var(--bp-easing);
  cursor: pointer;
}
a.btn-success:hover,
button.btn-success:hover,
input[type=submit].btn-success:hover,
form.btn-success > input[type=submit]:hover,
form.btn-success > button:hover { filter: brightness(1.1); }
a.btn-success:active,
button.btn-success:active,
input[type=submit].btn-success:active,
form.btn-success > input[type=submit]:active,
form.btn-success > button:active { transform: translateY(1px); }

a.btn-warning,
button.btn-warning,
input[type=submit].btn-warning,
form.btn-warning > input[type=submit],
form.btn-warning > button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .4rem;
  padding: .55rem .9rem;
  border-radius: var(--bp-r-md);
  background: var(--bp-warning);
  color: var(--bp-accent-ink);
  text-decoration: none;
  font-weight: 600;
  border: none;
  transition: filter var(--bp-dur-fast) var(--bp-easing), transform var(--bp-dur-fast) var(--bp-easing);
  cursor: pointer;
}
a.btn-warning:hover,
button.btn-warning:hover,
input[type=submit].btn-warning:hover,
form.btn-warning > input[type=submit]:hover,
form.btn-warning > button:hover { filter: brightness(1.1); }
a.btn-warning:active,
button.btn-warning:active,
input[type=submit].btn-warning:active,
form.btn-warning > input[type=submit]:active,
form.btn-warning > button:active { transform: translateY(1px); }

a.btn-info,
button.btn-info,
input[type=submit].btn-info,
form.btn-info > input[type=submit],
form.btn-info > button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .4rem;
  padding: .55rem .9rem;
  border-radius: var(--bp-r-md);
  background: var(--bp-info);
  color: var(--bp-accent-ink);
  text-decoration: none;
  font-weight: 600;
  border: none;
  transition: filter var(--bp-dur-fast) var(--bp-easing), transform var(--bp-dur-fast) var(--bp-easing);
  cursor: pointer;
}
a.btn-info:hover,
button.btn-info:hover,
input[type=submit].btn-info:hover,
form.btn-info > input[type=submit]:hover,
form.btn-info > button:hover { filter: brightness(1.1); }
a.btn-info:active,
button.btn-info:active,
input[type=submit].btn-info:active,
form.btn-info > input[type=submit]:active,
form.btn-info > button:active { transform: translateY(1px); }

a.btn-danger,
button.btn-danger,
input[type=submit].btn-danger,
form.btn-danger > input[type=submit],
form.btn-danger > button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .4rem;
  padding: .55rem .9rem;
  border-radius: var(--bp-r-md);
  background: var(--bp-danger);
  color: var(--bp-accent-ink);
  text-decoration: none;
  font-weight: 600;
  border: none;
  transition: filter var(--bp-dur-fast) var(--bp-easing), transform var(--bp-dur-fast) var(--bp-easing);
  cursor: pointer;
}
a.btn-danger:hover,
button.btn-danger:hover,
input[type=submit].btn-danger:hover,
form.btn-danger > input[type=submit]:hover,
form.btn-danger > button:hover { filter: brightness(1.1); }
a.btn-danger:active,
button.btn-danger:active,
input[type=submit].btn-danger:active,
form.btn-danger > input[type=submit]:active,
form.btn-danger > button:active { transform: translateY(1px); }

/* Button size variants */
.btn-sm {
  padding: 0.35rem 0.6rem;
  font-size: 0.85rem;
  border-radius: var(--bp-r-md);
}

/* Navigation */
.nav-toggle {
  appearance: none;
  background: transparent;
  border: 1px solid var(--bp-rule);
  color: var(--bp-ink);
  border-radius: var(--bp-r-md);
  padding: .5rem .65rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}

.nav-mobile {
  display: grid;
  gap: .4rem;
  padding: .6rem 0 .9rem;
  border-top: 1px solid var(--bp-rule);
}
.nav-mobile a {
  color: var(--bp-ink);
  text-decoration: none;
  padding: .55rem .7rem;
  border-radius: var(--bp-r-md);
}

.nav-mobile-login {
  justify-self: start;
}

/* Alerts / Flashes */
.bp-alert {
  display: grid;
  grid-template-columns: 18px 1fr;
  gap: var(--bp-s-4);
  padding: var(--bp-s-3) var(--bp-s-5);
  border: 1px solid var(--bp-rule);
  border-left-width: 4px;
  border-radius: var(--bp-r-md);
  background: var(--bp-paper);
  font-size: 14px;
  align-items: start;
  margin: var(--bp-s-2) 0;
}
.bp-alert:has(.bp-alert__close) {
  grid-template-columns: 18px 1fr auto;
}
/* A standing alert whose action is the whole point and which is NOT
   dismissible — the coach resume bar (#1808) is the first of these. Same
   action column, no dismiss column. */
.bp-alert:has(.bp-alert__action-form) {
  grid-template-columns: 18px 1fr auto;
}
/* A reversing action (e.g. Undo) claims its own column ahead of the
   dismiss control, so the message never has to shrink to make room.
   Higher specificity than the rule above, so order here is not load-bearing. */
.bp-alert:has(.bp-alert__action-form):has(.bp-alert__close) {
  grid-template-columns: 18px 1fr auto auto;
}
.bp-alert__action-form { margin: 0; align-self: start; }
.bp-alert__action {
  font: inherit;
  font-weight: 600;
  color: var(--bp-accent);
  background: transparent;
  border: 0;
  padding: 0 var(--bp-s-2);
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 2px;
  line-height: 1.4;
}
.bp-alert__action:hover { color: var(--bp-ink); }
.bp-alert__action:focus-visible {
  outline: 2px solid var(--bp-accent);
  outline-offset: 2px;
  border-radius: var(--bp-r-sm);
}
.bp-alert .mark        { font-weight: 700; line-height: 1.4; }
.bp-alert__title       { font-weight: 600; color: var(--bp-ink); margin-bottom: 2px; }
.bp-alert__body        { color: var(--bp-ink-2); }
.bp-alert__close {
  font-family: var(--bp-mono-family);
  font-size: 18px;
  color: var(--bp-ink-muted);
  cursor: pointer;
  border: 0;
  background: transparent;
  line-height: 1;
  padding: 0;
  align-self: start;
}
.bp-alert__close:hover { color: var(--bp-ink); }
.bp-alert--success { border-left-color: var(--bp-success); }
.bp-alert--success .mark { color: var(--bp-success); }
.bp-alert--warning { border-left-color: var(--bp-warning); }
.bp-alert--warning .mark { color: var(--bp-warning); }
.bp-alert--danger  { border-left-color: var(--bp-danger); }
.bp-alert--danger  .mark { color: var(--bp-danger); }
.bp-alert--info    { border-left-color: var(--bp-info); }
.bp-alert--info    .mark { color: var(--bp-info); }

/* Inline form validation errors — temporary alias until Step 6 feature cleanup.
   New code must use .bp-alert.bp-alert--danger instead. */
.flash.alert {
  border-left: 4px solid var(--bp-danger);
  background: var(--bp-tint-danger);
  color: var(--bp-tint-ink-danger);
  border-radius: var(--bp-r-md);
  padding: var(--bp-s-3) var(--bp-s-4);
  font-size: 14px;
  margin: var(--bp-s-2) 0;
}

/* Tables */
.table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  background: var(--bp-paper);
  border: 1px solid var(--bp-rule);
  border-radius: var(--bp-r-lg);
  overflow: hidden;
}
.table thead th {
  text-align: left;
  padding: .6rem .75rem;
  font-weight: 700;
  background: var(--bp-surface);
  border-bottom: 1px solid var(--bp-rule);
}
.table tbody td {
  padding: .55rem .75rem;
  border-bottom: 1px solid var(--bp-rule-soft);
  vertical-align: top;
}
.table tbody tr:last-child td {
  border-bottom: none;
}

/* Badges */
.badge {
  display: inline-flex;
  align-items: center;
  gap: .35rem;
  padding: .2rem .5rem;
  border-radius: var(--bp-r-pill);
  font-size: .85rem;
  font-weight: 600;
}

.badge-gray {
  background: color-mix(in srgb, var(--bp-ink-muted) 15%, transparent);
  color: var(--bp-ink-muted);
  border: 1px solid var(--bp-rule);
}

.badge-green {
  background: var(--bp-tint-done);
  color: var(--bp-success);
  border: 1px solid color-mix(in srgb, var(--bp-success) 35%, transparent);
}

.badge-red {
  background: var(--bp-tint-danger);
  color: var(--bp-danger);
  border: 1px solid color-mix(in srgb, var(--bp-danger) 35%, transparent);
}

.badge-amber {
  background: var(--bp-tint-warning);
  color: var(--bp-warning);
  border: 1px solid color-mix(in srgb, var(--bp-warning) 35%, transparent);
}

.badge-blue {
  background: var(--bp-tint-info);
  color: var(--bp-info);
  border: 1px solid color-mix(in srgb, var(--bp-info) 35%, transparent);
}

/* Score slider */
.score-slider {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 28px;
  background: transparent;
}
.score-slider:focus { outline: none; }

.score-slider::-webkit-slider-runnable-track {
  height: 6px;
  background: var(--bp-surface-2);
  border: 1px solid var(--bp-rule);
  border-radius: var(--bp-r-pill);
}
.score-slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--bp-accent);
  border: 2px solid var(--bp-paper);
  margin-top: -6px;
  box-shadow: 0 0 0 1px var(--bp-rule);
}
.score-slider:focus::-webkit-slider-thumb {
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--bp-accent) 25%, transparent);
}

.score-slider::-moz-range-track {
  height: 6px;
  background: var(--bp-surface-2);
  border: 1px solid var(--bp-rule);
  border-radius: var(--bp-r-pill);
}
.score-slider::-moz-range-thumb {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--bp-accent);
  border: 2px solid var(--bp-paper);
  box-shadow: 0 0 0 1px var(--bp-rule);
}

.score-slider::-ms-track {
  height: 6px;
  background: transparent;
  border-color: transparent;
  color: transparent;
}
.score-slider::-ms-fill-lower,
.score-slider::-ms-fill-upper {
  background: var(--bp-surface-2);
  border: 1px solid var(--bp-rule);
  border-radius: var(--bp-r-pill);
}
.score-slider::-ms-thumb {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--bp-accent);
  border: 2px solid var(--bp-paper);
}

.slider-labels {
  display: flex;
  justify-content: space-between;
  font-size: 0.9rem;
  color: var(--bp-ink-muted);
  margin-top: 0.2rem;
}

/* Read-only value display */
.read-only-value {
  padding: .6rem .75rem;
  background: var(--bp-surface);
  border: 1px solid var(--bp-rule);
  border-radius: var(--bp-r-md);
  white-space: pre-wrap;
}

/* Score display */
.score-display {
  display: flex;
  align-items: center;
  gap: .35rem;
}
.score-display .stars {
  letter-spacing: .1rem;
}

/* Status indicator */
.status {
  margin-top: .1rem;
  display: flex;
  align-items: center;
  gap: .5rem;
  flex-wrap: wrap;
}

/* Modal overlay and components */
.modal-overlay {
  position: fixed;
  inset: 0;
  z-index: var(--bp-z-top);
  display: grid;
  place-items: center;
  background: rgba(0,0,0,0.35);
  padding: 1rem;
}

.modal-content {
  width: min(560px, 96vw);
  border: 1px solid var(--bp-rule);
  border-radius: var(--bp-r-lg);
  background: var(--bp-paper);
  overflow: hidden;
}

.modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: .8rem 1rem;
  border-bottom: 1px solid var(--bp-rule);
  background: var(--bp-paper);
}

.modal-title {
  margin: 0;
  font-size: 1.1rem;
}

.modal-status {
  padding: .8rem 1rem;
  text-align: center;
  border-bottom: 1px solid var(--bp-rule);
  background: var(--bp-paper);
}

.modal-body {
  padding: 1rem;
  display: grid;
  gap: .6rem;
  background: var(--bp-paper);
}

/* Form components */
.form-label {
  display: block;
  font-weight: 600;
  margin-bottom: .3rem;
}

.form-actions-end {
  display: flex;
  gap: .5rem;
  justify-content: flex-end;
  margin-top: .6rem;
}

.bp-form-actions {
  display: flex;
  gap: var(--bp-s-3);
  justify-content: flex-end;
  margin-top: var(--bp-s-5);
}
/* A `button_to` in an actions row is really a <form> wrapping the button, so
   the form is what becomes the flex item. Zero it so a posted action lines up
   with the plain buttons beside it. */
.bp-form-actions > form { margin: 0; }

/* The handoff names --bp-s-7 as the gap between major sections but the library
   had no way to spell it. Use between stacked top-level blocks — e.g. a
   settings form and the destructive action that must not sit inside it. */
.bp-section-gap {
  margin-top: var(--bp-s-7);
}

/* Buttons side by side outside a form — a page header carrying more than one
   action. Unlike bp-form-actions this adds no margin and no alignment of its
   own, so it composes inside whatever is already positioning it. */
.bp-btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--bp-s-3);
}

/* ─── bp-filter-bar — a row of controls that narrows the list below it ─────
   A GET form's fields laid out horizontally instead of stacked. The fields are
   plain .bp-field, so their labels and .help text keep working; this only
   changes the direction they run in and takes off the stacked bottom margin
   the row's own gap now provides. Wraps rather than scrolls: a filter that has
   run off the edge of the screen is a filter nobody knows is applied.
   --wide on a field that holds a longer value (an address, a filename). */
.bp-filter-bar {
  display: flex;
  flex-wrap: wrap;
  /* Top, not bottom. Labels are one line each, so aligning tops is what puts
     the *inputs* on a line — bottom-alignment lines up the .help text instead,
     and a field with two lines of help then sits visibly higher than the one
     beside it. */
  align-items: flex-start;
  gap: var(--bp-s-4);
}
.bp-filter-bar .bp-field {
  margin-bottom: 0;
  flex: 0 1 12rem;
}
.bp-filter-bar .bp-field--wide { flex-basis: 20rem; }
/* A set of checkboxes is one field, so it is one flex item — the checkboxes
   inside it wrap among themselves rather than being torn apart by the bar. */
.bp-filter-bar .bp-field--options {
  flex: 1 1 100%;
}
.bp-filter-bar .bp-field--options .bp-checkbox {
  margin-right: var(--bp-s-4);
}
/* Its own row. Aligned with the inputs it would have to clear a label and a
   variable number of help lines to reach, and any rule that does that is a
   guess about how long the copy is. */
.bp-filter-bar .bp-form-actions {
  margin-top: 0;
  flex: 1 1 100%;
}
@media (max-width: 40rem) {
  .bp-filter-bar .bp-field { flex-basis: 100%; }
}

/* ─── bp-pager — offset pagination under a list ────────────────────────────
   The count line and the two steps, in that order: what you are looking at is
   the thing a reader needs first, and on a single page it is the whole
   component. Prev/next are rendered as disabled-looking text rather than
   omitted, so the control does not move as you page through. */
.bp-pager {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--bp-s-3);
  margin-top: var(--bp-s-4);
}
.bp-pager__count {
  font-size: 13px;
  color: var(--bp-ink-muted);
}
.bp-pager__steps {
  display: flex;
  align-items: center;
  gap: var(--bp-s-3);
}
.bp-pager__position {
  font-size: 13px;
  color: var(--bp-ink-muted);
}
/* Not a <button disabled>: there is nothing to press, and a control that looks
   pressable at the end of a list is a control that reads as broken. */
.bp-pager__step-end {
  font-size: 13px;
  color: var(--bp-ink-subtle);
  padding: 0 var(--bp-s-2);
}

/* Page header styling */
.page-header h1 {
  margin: 0;
  font-size: 1.6rem;
  letter-spacing: 0;
}

.page-header p {
  margin: 0;
}

.page-header .text-muted {
  font-size: .95rem;
}

.status-label {
  font-weight: 600;
}

/* Info card spacing */
.info-card-spaced {
  margin-top: .6rem;
}

/* Star rating */
.star-rating {
  letter-spacing: .1rem;
}

.star-filled {
  color: var(--bp-warning);
}

.star-empty {
  color: var(--bp-ink-subtle);
}

.star-score {
  color: var(--bp-ink-muted);
  font-size: .9rem;
}

/* Button variants */
.btn-full-width {
  width: 100%;
}

.btn-centered {
  text-align: center;
}

.links-cta {
  display: flex;
  gap: .6rem;
  flex-wrap: wrap;
  align-items: center;
}

/* Summary/details customization */
.summary-clickable {
  cursor: pointer;
  list-style: none;
  display: flex;
  align-items: center;
  gap: .5rem;
}

.summary-meta {
  color: var(--bp-ink-muted);
  font-size: .9rem;
}

.spacer {
  flex: 1;
}

/* Feedback alert */
.feedback-alert {
  display: inline-flex;
  align-items: center;
  gap: .35rem;
  padding: .25rem .6rem;
  border-radius: var(--bp-r-md);
  font-size: .85rem;
  font-weight: 600;
  background: var(--bp-tint-info);
  color: var(--bp-info);
  border: 1px solid color-mix(in srgb, var(--bp-info) 45%, transparent);
}

/* Notice messages */
.notice-success {
  color: var(--bp-success);
}

.notice-error {
  color: var(--bp-danger);
}

/* Collapsible sections */
.collapsible-section {
  border: 1px solid var(--bp-rule);
  border-radius: var(--bp-r-lg);
  background: var(--bp-paper);
  overflow: hidden;
}

.collapsible-header {
  cursor: pointer;
  list-style: none;
  display: flex;
  align-items: center;
  gap: .75rem;
  padding: 1rem 1.25rem;
  background: var(--bp-surface);
  border-bottom: 1px solid var(--bp-rule);
  transition: background var(--bp-dur-fast) var(--bp-easing);
  user-select: none;
}

.collapsible-header:hover {
  background: var(--bp-surface-2);
}

.collapsible-header::-webkit-details-marker {
  display: none;
}

.collapsible-icon {
  font-size: .85rem;
  transition: transform var(--bp-dur-med) var(--bp-easing);
  color: var(--bp-ink-muted);
}

details[open] .collapsible-icon {
  transform: rotate(0deg);
}

details:not([open]) .collapsible-icon {
  transform: rotate(-90deg);
}

.collapsible-title {
  margin: 0;
  font-size: 1.25rem;
  font-weight: 700;
  color: var(--bp-ink);
}

.collapsible-content {
  padding: 1.25rem;
  background: var(--bp-paper);
}

@media (max-width: 640px) {
  .collapsible-header {
    padding: .85rem 1rem;
  }

  .collapsible-title {
    font-size: 1.1rem;
  }

  .collapsible-content {
    padding: 1rem;
  }
}

/* Dual list selector */
.dual-list-container {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  gap: 1rem;
  margin-top: .5rem;
  align-items: start;
}

.dual-list-buttons {
  display: flex;
  flex-direction: column;
  gap: .5rem;
  justify-content: center;
  margin-top: 2rem;
}

.dual-list-section {
  min-width: 0; /* Prevents overflow on small screens */
}

@media (max-width: 768px) {
  .dual-list-container {
    grid-template-columns: 1fr;
    gap: .75rem;
  }

  .dual-list-buttons {
    flex-direction: row;
    justify-content: center;
    margin-top: 0;
    order: 2; /* Move buttons between the two lists */
  }

  .dual-list-section:first-child {
    order: 1;
  }

  .dual-list-section:last-child {
    order: 3;
  }

  .dual-list-buttons button {
    flex: 1;
    max-width: 150px;
  }
}

/* Metadata and muted text label */
.metadata-label {
  color: var(--bp-ink-muted);
  font-size: var(--fs-sm);
}

/* Separator for metadata items */
.metadata-separator {
  color: var(--bp-ink-muted);
  font-size: var(--fs-sm);
}

/* Page header with actions */
.page-header-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 1rem;
}

.page-header-actions h1 {
  margin: 0;
}

/* Flex column layout for grouped sections */
.flex-column {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

/* Flex row with baseline alignment */
.flex-row-baseline {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.5rem;
}

/* Contact person card styles */
.contact-info-item {
  margin-bottom: 0.5rem;
}

.contact-company-label {
  font-weight: normal;
  color: var(--bp-ink-muted);
}

.priority-badge {
  display: inline-flex;
  align-items: center;
  padding: 0.25rem 0.5rem;
  border-radius: var(--bp-r-sm);
  font-size: 0.85rem;
  font-weight: 600;
}

.priority-badge.high {
  background: var(--bp-tint-danger);
  color: var(--bp-tint-ink-danger);
}

.priority-badge.medium {
  background: var(--bp-tint-warning);
  color: var(--bp-tint-ink-warning);
}

.priority-badge.low {
  background: var(--bp-tint-info);
  color: var(--bp-tint-ink-info);
}

.list-disc {
  list-style: disc;
  padding-left: 1.25rem;
}

.section-title-spacing {
  margin-top: 1rem;
}

/* ─── bp-field — form field wrapper (label / control / help / error) ─────── */
.bp-field { display: grid; gap: 6px; margin-bottom: 18px; }
.bp-field label { font-size: 13px; font-weight: 600; color: var(--bp-ink); }
.bp-field .help  { font-size: 12.5px; color: var(--bp-ink-muted); }
/* .bp-radio__body is documented as "the label, then whatever detail makes the
   choice decidable" and its callers already reach for .help for that detail —
   which was inheriting body size, so the detail read at the same weight as the
   choice. The rule belongs here rather than in a feature sheet: it is the same
   help text doing the same job outside a .bp-field wrapper. */
.bp-radio__body .help,
.bp-checkbox .help { font-size: 12.5px; color: var(--bp-ink-muted); }
.bp-field .error { font-size: 12.5px; color: var(--bp-danger); }

/* ─── bp-input / bp-textarea / bp-select — form field tokens ─────────────── */
.bp-input,
.bp-select,
.bp-textarea {
  box-sizing: border-box;
  width: 100%;
  padding: 10px 12px;
  font: inherit;
  background: var(--bp-paper);
  color: var(--bp-ink);
  border: 1px solid var(--bp-rule);
  border-radius: var(--bp-r-md);
  transition: border-color var(--bp-dur-fast), box-shadow var(--bp-dur-fast);
}
.bp-input:focus,
.bp-select:focus,
.bp-textarea:focus {
  outline: none;
  border-color: var(--bp-accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--bp-accent) 15%, transparent);
}
.bp-input::placeholder,
.bp-textarea::placeholder { color: var(--bp-ink-muted); }
.bp-textarea { min-height: 96px; resize: vertical; line-height: 1.5; }

/* Safari's native <select> ignores padding / min-height on its intrinsic sizing
   path, so it renders ~6-8px shorter than an adjacent .bp-input even with the
   shared rule above. `appearance: none` opts out of native styling so the box
   obeys our box model, and the inline-SVG caret restores the dropdown
   affordance. The stroke hex (%236b6b6b) is the resolved value of
   --bp-ink-muted — CSS custom properties don't resolve inside data URIs, so
   the token value is duplicated here. If --bp-ink-muted changes, update this
   value to match. */
.bp-select {
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  background-image: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'><path d='M2.5 4.5L6 8l3.5-3.5' stroke='%236b6b6b' stroke-width='1.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  background-repeat: no-repeat;
  background-position: right var(--bp-s-3) center;
  background-size: var(--bp-s-3) var(--bp-s-3);
  padding-right: var(--bp-s-6);
}

/* ─── bp-radio / bp-checkbox ─────────────────────────────────────────────── */
.bp-checkbox,
.bp-radio {
  display: inline-flex;
  align-items: flex-start;
  gap: 10px;
  font-size: 14px;
  cursor: pointer;
  padding: 6px 0;
}
.bp-checkbox input,
.bp-radio input {
  appearance: none;
  width: 18px;
  height: 18px;
  border: 1px solid var(--bp-rule);
  background: var(--bp-paper);
  margin: 0;
  cursor: pointer;
  position: relative;
  flex-shrink: 0;
  margin-top: 1px;
}
.bp-checkbox input { border-radius: var(--bp-r-sm); }
.bp-radio input    { border-radius: 50%; }
.bp-checkbox input:checked,
.bp-radio input:checked { background: var(--bp-accent); border-color: var(--bp-accent); }
.bp-checkbox input:focus-visible,
.bp-radio input:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--bp-accent) 25%, transparent);
}
.bp-radio input:checked::after {
  content: "";
  position: absolute;
  inset: 4px;
  border-radius: 50%;
  background: #fff;
}
.bp-radio-group {
  display: flex;
  flex-wrap: wrap;
  gap: var(--bp-s-4);
}
/* Stacked variant — for choices whose labels carry more than a few words, where
   a wrapped row would misalign each control against its own text. */
.bp-radio-group--stacked {
  flex-direction: column;
  gap: var(--bp-s-3);
}
/* Multi-line choice: the label, then whatever detail makes the choice decidable
   — counts, consequences — on its own lines under it. */
.bp-radio__body {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.bp-radio__label { font-weight: 600; }

/* ─── bp-fieldset — a grouped set of choices with a legend ───────────────── */
/* Radios answering one question need a real fieldset/legend to be announced as
   a group; this strips the border and inset padding browsers add by default. */
.bp-fieldset {
  border: 0;
  padding: 0;
  margin: 0 0 18px;
  min-inline-size: 0;
}
.bp-fieldset > legend {
  padding: 0;
  margin-bottom: var(--bp-s-2);
}

/* ─── bp-pill — survey answer pill ──────────────────────────────────────── */
.bp-pills {
  display: flex;
  flex-wrap: wrap;
  gap: var(--bp-s-2);
  margin-top: var(--bp-s-2);
}
.bp-pill {
  display: inline-flex;
  align-items: center;
  padding: 10px 18px;
  border-radius: var(--bp-r-pill);
  border: 1px solid var(--bp-rule);
  background: var(--bp-paper);
  color: var(--bp-ink-2);
  font: inherit;
  font-size: 14.5px;
  cursor: pointer;
  transition: background var(--bp-dur-fast), border-color var(--bp-dur-fast), color var(--bp-dur-fast);
}
.bp-pill:hover { border-color: var(--bp-ink-muted); background: var(--bp-surface); }
.bp-pill.is-selected {
  background: var(--bp-accent);
  border-color: var(--bp-accent);
  color: var(--bp-accent-ink);
}
.bp-pill__check { opacity: 0; margin-right: 6px; font-size: 12px; }
.bp-pill.is-selected .bp-pill__check { opacity: 1; }
.bp-pill.is-selected:disabled { opacity: 1; cursor: default; }

/* ─── bp-step-meta + bp-progress — survey progress indicator ────────────── */
.bp-step-meta {
  font-family: var(--bp-mono-family);
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--bp-ink-muted);
}
.bp-progress {
  height: 6px;
  background: var(--bp-surface-2);
  border-radius: var(--bp-r-pill);
  overflow: hidden;
}
.bp-progress__fill {
  height: 100%;
  background: var(--bp-accent);
  border-radius: var(--bp-r-pill);
  transition: width 0.35s ease;
}
/* Indeterminate variant — a sliding sweep for "working, no known
   percentage" states (e.g. the Flow D resume-parse spinner, #884). The
   fill width is fixed; the animation translates it across the track. */
.bp-progress--indeterminate .bp-progress__fill {
  width: 40%;
  transition: none;
  animation: bp-progress-sweep 1.2s var(--bp-easing, ease-in-out) infinite;
}
@keyframes bp-progress-sweep {
  0%   { transform: translateX(-110%); }
  100% { transform: translateX(260%); }
}
@media (prefers-reduced-motion: reduce) {
  .bp-progress--indeterminate .bp-progress__fill {
    animation: none;
    width: 100%;
  }
}

/* ─── bp-ai-working — "the AI is generating this, the screen updates itself" ──
   The shared affordance for AUTO-REFRESH surfaces (#1588): a background job
   produces AI content and a Turbo Stream broadcast morphs it in when it lands.
   Composed from the .insight card + the indeterminate progress sweep above, so
   it inherits their tokens and reduced-motion handling. See
   shared/_ai_working.html.erb. Button-driven synchronous generation uses
   .bp-btn.is-generating instead. */
.bp-ai-working .bp-progress--indeterminate {
  margin-top: var(--bp-s-3);
}
.bp-ai-working__note {
  color: var(--bp-ink-muted);
  font-size: 13px;
}
:where(.insight).bp-ai-working .bp-ai-working__note {
  margin-top: var(--bp-s-3);
}
/* Compact variant — a lightweight inline dots indicator for narrow rail cards
   (e.g. the Capabilities dashboard readiness peek). No card chrome, no bar. The
   dots reuse the chat typing-bounce keyframes. */
.bp-ai-working--compact {
  display: flex;
  align-items: flex-start;
  gap: var(--bp-s-2);
}
.bp-ai-working__compact-copy {
  margin: 0;
}
.bp-ai-working__dots {
  display: inline-flex;
  gap: 4px;
  flex: none;
  padding-top: 7px;
}
.bp-ai-working__dots span {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--bp-ink-subtle);
  animation: typing-bounce 1.2s var(--bp-easing, ease-in-out) infinite;
}
.bp-ai-working__dots span:nth-child(2) { animation-delay: 0.2s; }
.bp-ai-working__dots span:nth-child(3) { animation-delay: 0.4s; }
@media (prefers-reduced-motion: reduce) {
  .bp-ai-working__dots span { animation: none; }
}

/* ─── bp-card ────────────────────────────────────────────────────────────── */
.bp-card {
  background: var(--bp-paper);
  border: 1px solid var(--bp-rule);
  border-radius: var(--bp-r-lg);
  padding: 24px;
}
.bp-card--soft {
  background: var(--bp-surface);
  border-color: var(--bp-rule-soft);
}
/* A card holding a single-column form (account settings, admin create/edit).
   Without a measure the card takes the full page tier — 1200px — and a form of
   short text inputs strands its labels a screen away from its submit button.
   Was an inline `style="max-width: 34rem"` copy-pasted into four views. */
.bp-card--form {
  max-width: 34rem;
}

/* ─── bp-choice-card — equal-weight decision / fork pattern ───────────────────
   For dedicated decision screens whose entire job is choosing between co-equal
   options (a mode / fork picker). The whole card is the control: the inner
   `__action` link/button stretches to cover the card, and the accent moment is
   the hovered/focused card — not a row of competing filled --primary buttons.
   Compose with .bp-card (+ optional --soft) for chrome. See the Handoff §06. */
.bp-choice-card {
  position: relative;
  transition: border-color var(--bp-dur-fast) var(--bp-easing),
              background var(--bp-dur-fast) var(--bp-easing);
}
.bp-choice-card:hover {
  border-color: var(--bp-accent);
  background: var(--bp-accent-soft);
}
.bp-choice-card:focus-within {
  border-color: var(--bp-accent);
  outline: 2px solid var(--bp-accent);
  outline-offset: 2px;
}

/* The labelled action stays visible (screen readers get a real, named control);
   its ::after makes the whole card the hit target. Keep it a quiet accent link,
   never a filled button — the card is the accent, not the control inside it. */
.bp-choice-card__action {
  display: inline-flex;
  align-items: center;
  gap: var(--bp-s-2);
  font: inherit;
  font-weight: 600;
  color: var(--bp-accent);
  background: transparent;
  border: none;
  padding: 0;
  cursor: pointer;
  text-decoration: none;
}
.bp-choice-card__action::after {
  content: "";
  position: absolute;
  inset: 0;
}
/* The focus ring is drawn on the card via :focus-within, so suppress the
   control's own ring to avoid a doubled outline. */
.bp-choice-card__action:focus-visible { outline: none; }

/* button_to wraps its control in a <form>; collapse it so the button is the
   card's flow child and its stretched ::after positions against the card. */
.bp-choice-card__form { display: contents; }

/* Recommended variant — marks the smart-default card in an otherwise co-equal
   fork (e.g. a GTKY-derived mode). An accent border (the same accent the hover /
   focus state uses) makes it read as the default at rest; pair with a `.bp-badge`
   in the card header to name it ("Recommended for you"). Use this instead of a
   competing filled --primary button when one card should lead but all remain
   selectable. */
.bp-choice-card--recommended {
  border-color: var(--bp-accent);
}

/* ─── bp-btn — design system button primitives ───────────────────────────── */
.bp-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--bp-s-2);
  /* There is no global box-sizing reset, so a .bp-btn takes whatever the UA
     gives its element: border-box on <button>, content-box on <a>. That only
     shows up once a width is set — .bp-btn--block's width:100% then made every
     link-styled block button overhang its container by its own padding and
     border. Pinned here so the button measures the same whichever element it
     is written on. */
  box-sizing: border-box;
  padding: 10px 18px;
  font: inherit;
  font-weight: 600;
  font-size: 14px;
  border-radius: var(--bp-r-md);
  border: 1px solid transparent;
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
  transition: background var(--bp-dur-fast) var(--bp-easing),
              color var(--bp-dur-fast) var(--bp-easing),
              border-color var(--bp-dur-fast) var(--bp-easing);
}
.bp-btn--primary   { background: var(--bp-accent); color: var(--bp-accent-ink); border-color: var(--bp-accent); }
.bp-btn--primary:hover { background: color-mix(in srgb, var(--bp-accent) 85%, var(--bp-ink)); border-color: color-mix(in srgb, var(--bp-accent) 85%, var(--bp-ink)); text-decoration: none; }
.bp-btn--secondary { background: var(--bp-paper); color: var(--bp-ink); border-color: var(--bp-rule); }
.bp-btn--secondary:hover { background: var(--bp-surface); border-color: var(--bp-ink-muted); text-decoration: none; }
.bp-btn--ghost     { background: transparent; color: var(--bp-ink-muted); border-color: transparent; }
.bp-btn--ghost:hover { color: var(--bp-ink); background: var(--bp-surface); text-decoration: none; }
.bp-btn--danger    { background: var(--bp-paper); color: var(--bp-danger); border-color: var(--bp-rule); }
.bp-btn--danger:hover { background: var(--bp-tint-danger); border-color: var(--bp-danger); text-decoration: none; }
.bp-btn--sm  { padding: 6px 12px; font-size: 13px; }
.bp-btn--lg  { padding: 14px var(--bp-s-5); font-size: 15px; }
.bp-btn--block { display: flex; width: 100%; }
.bp-btn[disabled],
.bp-btn.is-disabled,
.bp-btn[aria-disabled="true"] { opacity: 0.45; cursor: not-allowed; }
.bp-btn.is-disabled,
.bp-btn[aria-disabled="true"] { pointer-events: none; }
.bp-btn:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--bp-accent) 25%, transparent);
}
/* Generating state (#1509) — immediate pending feedback on the Communication
   Plan's synchronous AI generate/regenerate buttons. The generating-button
   Stimulus controller adds .is-generating (and disables the button) on submit;
   the leading spinner is drawn from currentColor so it reads on the primary
   (accent) and secondary (paper) variants alike. Placed after the [disabled]
   rule so it wins the equal-specificity tie and keeps the spinner legible rather
   than dimmed to the disabled 0.45. */
.bp-btn.is-generating {
  opacity: 0.9;
  cursor: progress;
}
.bp-btn.is-generating::before {
  content: "";
  flex: none;
  width: 14px;
  height: 14px;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  animation: bp-btn-spin 0.7s linear infinite;
}
@keyframes bp-btn-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .bp-btn.is-generating::before { animation-duration: 1.6s; }
}
/* Waiting state (#1588) — a server-rendered sibling of .is-generating for a
   disabled control that is blocked on an auto-refresh background job (e.g. the
   GTKY advance button while the readiness assessor runs). Same spinner, but no
   JS: the class is rendered directly on the disabled button, and the Turbo
   Stream broadcast morphs the enabled control in when the job lands. Placed
   after [disabled] so the spinner stays legible rather than dimmed. */
.bp-btn.is-waiting {
  opacity: 0.7;
  cursor: progress;
}
.bp-btn.is-waiting::before {
  content: "";
  flex: none;
  width: 14px;
  height: 14px;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  animation: bp-btn-spin 0.7s linear infinite;
}
@media (prefers-reduced-motion: reduce) {
  .bp-btn.is-waiting::before { animation-duration: 1.6s; }
}

/* ─── bp-badge — design system status badges ─────────────────────────────── */
.bp-badge {
  display: inline-flex;
  align-items: center;
  gap: var(--bp-s-1);
  padding: 3px 10px;
  font-size: 11.5px;
  font-weight: 600;
  border-radius: var(--bp-r-pill);
  letter-spacing: 0.02em;
  border: 1px solid transparent;
}
.bp-badge--done    { background: var(--bp-tint-done);    color: var(--bp-tint-ink-done); }
.bp-badge--active  { background: var(--bp-tint-active);  color: var(--bp-tint-ink-active); }
.bp-badge--warning { background: var(--bp-tint-warning); color: var(--bp-tint-ink-warning); }
.bp-badge--danger  { background: var(--bp-tint-danger);  color: var(--bp-tint-ink-danger); }
.bp-badge--info    { background: var(--bp-tint-info);    color: var(--bp-tint-ink-info); }
.bp-badge--idle    { background: transparent; color: var(--bp-ink-muted); border-color: var(--bp-rule); }
/* Solid-accent fill — the only "step indicator" surface in the app
   (questionnaire shell, capabilities flows) wanted full-strength
   brand colour rather than the soft tints above. */
.bp-badge--accent  { background: var(--bp-accent); color: var(--bp-accent-ink); text-transform: uppercase; letter-spacing: 0.05em; font-size: 12.5px; padding: 4px 12px; }

/* ─── jsr-rail — Job Search Readiness progression rail (DESIGN §2) ────────────
   Four levels L1–L4 across one row, each a node + level name + status chip (or a
   muted "not yet started" affordance). The inbound connector lights up to the
   furthest reached level so the rail reads as a filled progress track. Status is
   derived from StageProgress (honest signal), never from the AI payload. */
.jsr-rail {
  list-style: none;
  margin: 0 auto var(--bp-s-6);
  padding: 0;
  max-width: var(--bp-w-page);
  display: grid;
  grid-template-columns: repeat(4, 1fr);
}
.jsr-rail__level {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--bp-s-2);
  padding: 0 var(--bp-s-2);
}
/* Connector from the previous node's centre to this one's. */
.jsr-rail__level::before {
  content: "";
  position: absolute;
  top: 7px;
  right: 50%;
  left: -50%;
  height: 2px;
  background: var(--bp-rule);
  z-index: var(--bp-z-base);
}
.jsr-rail__level:first-child::before { display: none; }
.jsr-rail__level--ready::before,
.jsr-rail__level--developing::before { background: var(--bp-tint-ink-active); }
.jsr-rail__node {
  position: relative;
  z-index: var(--bp-z-raised);
  width: 16px;
  height: 16px;
  box-sizing: border-box;
  border-radius: 50%;
  background: var(--bp-paper);
  border: 2px solid var(--bp-rule);
}
.jsr-rail__level--ready .jsr-rail__node {
  background: var(--bp-tint-ink-done);
  border-color: var(--bp-tint-ink-done);
}
.jsr-rail__level--developing .jsr-rail__node {
  background: var(--bp-tint-ink-active);
  border-color: var(--bp-tint-ink-active);
}
.jsr-rail__level.is-current .jsr-rail__node { box-shadow: 0 0 0 4px var(--bp-tint-active); }
.jsr-rail__ord {
  font-family: var(--bp-mono-family);
  font-size: 11px;
  letter-spacing: 0.1em;
  color: var(--bp-ink-muted);
}
.jsr-rail__name {
  font-size: 13px;
  font-weight: 600;
  line-height: 1.25;
  color: var(--bp-ink);
}
.jsr-rail__level--not-started .jsr-rail__name { color: var(--bp-ink-muted); font-weight: 500; }
.jsr-rail__level.is-current .jsr-rail__name { color: var(--bp-accent); }
.jsr-rail__pending { font-size: 11.5px; color: var(--bp-ink-muted); }
@media (max-width: 560px) {
  .jsr-rail { grid-template-columns: 1fr; gap: var(--bp-s-3); }
  .jsr-rail__level {
    flex-direction: row;
    justify-content: flex-start;
    text-align: left;
    gap: var(--bp-s-3);
  }
  .jsr-rail__level::before { display: none; }
}
/* Compact variant — vertical stack for a narrow status card (the Capabilities
   dashboard rail), independent of viewport. Declared AFTER the small-screen
   media block so its (equal-specificity) declarations win at every width — a
   compact rail keeps its tighter gap even below 560px. */
.jsr-rail--compact {
  grid-template-columns: 1fr;
  gap: var(--bp-s-2);
  margin: 0 0 var(--bp-s-3);
}
.jsr-rail--compact .jsr-rail__level {
  flex-direction: row;
  justify-content: flex-start;
  text-align: left;
  gap: var(--bp-s-2);
  padding: 0;
}
.jsr-rail--compact .jsr-rail__level::before { display: none; }
/* One-line assessment peek under the compact rail on the dashboard status card. */
.capabilities-dashboard__readiness-peek {
  margin: var(--bp-s-2) 0 0;
  font-size: 13px;
  line-height: 1.4;
  color: var(--bp-ink-muted);
}

/* ─── jsr-readiness — the rail in its stage-closing card (S2, #1741) ──────────
   The transition screen's treatment (search_execution.css `__readiness`):
   surface-filled card + note + the COMPACT rail, sitting directly above the
   stage's forward action. Before S2 closings rendered the full horizontal
   track, uncarded, above the report. */
/* Same column as `.jsr-report`, and deliberately the same token — the rail card
   sits directly under the report, so any disagreement between the two reads as a
   misalignment. `width: 100%` is load-bearing for the same reason it is there:
   some closings frame this in a container that shrink-wraps its children (one
   collapsed the card to ~510px), where `max-width` alone never widens a block. */
.jsr-readiness {
  width: 100%;
  max-width: var(--bp-w-stage);
  margin: var(--bp-s-7) auto 0;
}
.jsr-readiness__head {
  display: flex;
  align-items: center;
  gap: var(--bp-s-3);
  margin: 0 0 var(--bp-s-4);
}
.jsr-readiness__head h3 { margin: 0; white-space: nowrap; }
.jsr-readiness__rule { height: 1px; background: var(--bp-rule); flex: 1; }
.jsr-readiness__card { background: var(--bp-surface); }
.jsr-readiness__note {
  margin: 0 0 var(--bp-s-4);
  font-size: 12.5px;
  color: var(--bp-ink-muted);
}
.jsr-readiness__card .jsr-rail { width: 100%; margin-bottom: 0; }

/* ─── jsr-report — the pared-down readiness report (S2, #1741) ────────────────
   Product review 2026-07-27: the coach's note is the most prominent thing on
   the screen, every section is pared to a lede on load, and the full writeup is
   reachable without navigating away. Scale and anatomy are copied from the
   SHIPPED transition screen (search_execution.css `se-transition__*`), not from
   a mockup — its cleanliness comes from restraint the CSS alone doesn't
   advertise: no nested boxes, no tinted markers, one highlight moment.

   Widths come from --bp-* tokens and per-component reading measures only; no
   width literals (Handoff contract). */
.jsr-ic {
  width: 1em;
  height: 1em;
  display: inline-block;
  vertical-align: -0.14em;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
  flex: none;
}

/* The report's own column, so it reads the same width wherever it is rendered.
   `width: 100%` is load-bearing alongside `max-width`: several closings frame it
   in a flex column that shrink-wraps its children, where `max-width` alone never
   widens a block — that is what left the ledger at 751px under a 1192px hero.
   Same tier as `.se-transition`, the screen this presentation copies. */
.jsr-report {
  width: 100%;
  max-width: var(--bp-w-stage);
  margin: 0 auto;
}

/* hero — the coach note. NO container: prominence is position, scale and air.
   Measures sit on the TEXT, never on the hero: `ch` resolves against each
   element's own font-size, so one number on a block that wraps text at two
   sizes clamps one child and silently kills the other's max-width (the bug S3
   fixed on the transition screen, #1742). */
.jsr-report__hero { text-align: center; margin: 0 auto var(--bp-s-7); }
.jsr-report__eyebrow {
  display: block;
  margin-bottom: var(--bp-s-4);
  font-family: var(--bp-mono-family);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--bp-highlight); /* the report's single highlight mark */
}
/* 34ch is ~850px at the 40px display size — a ≤14-word headline lands at 2–3
   lines, which is the stacking that gives it presence. */
.jsr-report__headline { margin: 0 auto var(--bp-s-5); max-width: 34ch; }
/* The note runs LEFT-aligned under the centered headline — an editorial
   standfirst. Centered prose stops being comfortable past 3–4 lines, so the
   ALIGNMENT is what caps a centered hero at ~65 words; left-aligning buys the
   120–150 the coach note actually runs to. 55ch of 19px serif is ~68 characters
   a line, the same editorial measure the transition lede takes at its own size.

   The measure sits on the wrapper, at the note's font-size, and the attribution
   inherits that width rather than declaring its own — 55ch on a 12.5px line is a
   different width entirely, which centers it out of alignment with the prose it
   signs. */
.jsr-report__standfirst {
  max-width: 55ch;
  margin: 0 auto;
  text-align: left;
  font-family: var(--bp-serif-family);
  font-size: 19px;
}
.jsr-report__note { line-height: 1.6; color: var(--bp-ink-2); }
.jsr-report__note p { margin: 0 0 var(--bp-s-3); }
.jsr-report__note p:last-child { margin-bottom: 0; }
.jsr-report__note strong { color: var(--bp-ink); font-weight: 600; }
.jsr-report__attribution {
  margin: var(--bp-s-4) 0 0;
  font-family: var(--bp-body-family);
  font-size: 12.5px;
  color: var(--bp-ink-muted);
}

/* section head + expand-all */
.jsr-report__section { margin-top: var(--bp-s-7); }
.jsr-report__section-head {
  display: flex;
  align-items: center;
  gap: var(--bp-s-3);
  margin: 0 0 var(--bp-s-4);
}
.jsr-report__section-head h3 { margin: 0; white-space: nowrap; }
.jsr-report__section-rule { height: 1px; background: var(--bp-rule); flex: 1; }
.jsr-report__expand-all {
  padding: 2px 4px;
  border: 0;
  background: none;
  cursor: pointer;
  font-family: var(--bp-mono-family);
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--bp-ink-subtle);
}
.jsr-report__expand-all:hover { color: var(--bp-accent); }
.jsr-report__expand-all:focus-visible {
  outline: 2px solid var(--bp-accent);
  outline-offset: 2px;
  border-radius: var(--bp-r-sm);
}

/* the ledger — one column, not the transition screen's 2-up grid: these cards
   expand in place, and a growing card in a 2-up grid shoves its neighbour. */
.jsr-report__ledger { display: grid; gap: var(--bp-s-3); }
.jsr-report__card {
  padding: 0; /* the head carries it, so the whole head is the hit target */
  transition: border-color var(--bp-dur-fast) var(--bp-easing);
}
.jsr-report__card:hover,
.jsr-report__card[open] { border-color: var(--bp-ink-subtle); }
.jsr-report__card--static:hover { border-color: var(--bp-rule); }
.jsr-report__card-head {
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: var(--bp-s-4);
  align-items: start;
  padding: var(--bp-s-5);
  border-radius: var(--bp-r-lg);
}
summary.jsr-report__card-head { list-style: none; cursor: pointer; }
summary.jsr-report__card-head::-webkit-details-marker { display: none; }
summary.jsr-report__card-head:focus-visible {
  outline: 2px solid var(--bp-accent);
  outline-offset: -2px;
}
.jsr-report__glyph {
  width: 40px;
  height: 40px;
  border-radius: var(--bp-r-md);
  background: var(--bp-accent-soft);
  color: var(--bp-accent);
  display: grid;
  place-items: center;
  font-size: 19px;
}
.jsr-report__kicker {
  margin: 0 0 var(--bp-s-1);
  font-family: var(--bp-mono-family);
  font-size: 9.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--bp-ink-subtle);
}
.jsr-report__card-title {
  margin: 0 0 var(--bp-s-2);
  font-family: var(--bp-display-family);
  font-weight: 500;
  font-size: 16px;
  letter-spacing: -0.01em;
}
/* Prose measure inside the card. The stage tier is 1200px (#1737, settled), so
   an uncapped lede would run ~150 characters. Capping the paragraph is a
   per-component reading concern, not a page-width argument. */
.jsr-report__lede p {
  margin: 0;
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--bp-ink-2);
  max-width: 72ch;
}
.jsr-report__lede p + p { margin-top: var(--bp-s-2); }
.jsr-report__lede strong { color: var(--bp-ink); font-weight: 600; }
.jsr-report__chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--bp-s-1);
  margin: var(--bp-s-2) 0 0;
  padding: 0;
  list-style: none;
}
.jsr-report__chip {
  padding: 3px 9px;
  border: 1px solid var(--bp-rule);
  border-radius: var(--bp-r-pill);
  background: var(--bp-surface);
  font-size: 11.5px;
  color: var(--bp-ink-2);
}
/* inline-flex, not inline: a non-replaced inline box is not transformable, so
   the [open] rotation below is silently dropped on a bare <span>. */
.jsr-report__chev {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  margin-top: 11px;
  font-size: 16px;
  color: var(--bp-ink-subtle);
  transition: transform var(--bp-dur-med) var(--bp-easing),
              color var(--bp-dur-fast) var(--bp-easing);
}
.jsr-report__card:hover .jsr-report__chev { color: var(--bp-accent); }
.jsr-report__card[open] .jsr-report__chev {
  transform: rotate(180deg);
  color: var(--bp-accent);
}

/* the disclosure — same 13.5px measure as the collapsed lede, so opening a card
   changes the amount of text, not the typography. Indented past the glyph so
   the writeup reads as the lede continuing rather than a new block. */
.jsr-report__detail {
  padding: 0 var(--bp-s-5) var(--bp-s-5) calc(40px + var(--bp-s-4) + var(--bp-s-5));
}
.jsr-report__detail-inner {
  border-top: 1px solid var(--bp-rule-soft);
  padding-top: var(--bp-s-4);
}
.jsr-report__detail p {
  margin: 0 0 var(--bp-s-3);
  font-size: 13.5px;
  line-height: 1.62;
  color: var(--bp-ink-2);
  max-width: 66ch;
}
.jsr-report__detail p:last-child { margin-bottom: 0; }
.jsr-report__detail strong { color: var(--bp-ink); font-weight: 600; }
.jsr-report__roles { margin: 0; padding-left: var(--bp-s-5); max-width: 66ch; }
.jsr-report__roles li {
  margin-bottom: var(--bp-s-2);
  font-size: 13.5px;
  line-height: 1.62;
  color: var(--bp-ink-2);
}
.jsr-report__roles li:last-child { margin-bottom: 0; }
.jsr-report__roles strong { color: var(--bp-ink); font-weight: 600; }

@media (prefers-reduced-motion: reduce) {
  .jsr-report__card,
  .jsr-report__chev { transition: none; }
}

@media (max-width: 760px) {
  .jsr-report__card-head { padding: var(--bp-s-4); gap: var(--bp-s-3); }
  .jsr-report__detail { padding: 0 var(--bp-s-4) var(--bp-s-4); }
}

/* ─── bp-chip — neutral read-only content token ──────────────────────────────
   Displays a value the user already chose (a selected answer, a tag). Distinct
   from .bp-badge (status, pill) and .bp-pill (interactive selection). Use
   .bp-chips on the wrapping <ul> when rendering a set. */
.bp-chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--bp-s-2);
  margin: 0;
  padding: 0;
  list-style: none;
}
.bp-chip {
  display: inline-block;
  padding: calc(var(--bp-s-1) / 2) var(--bp-s-2);
  border: 1px solid var(--bp-rule);
  border-radius: var(--bp-r-sm);
  background: var(--bp-surface);
  color: var(--bp-ink);
  font-size: 13px;
}

/* ─── Type scale utilities ────────────────────────────────────────────────── */
.t-display-1 { font-family: var(--bp-display-family); font-weight: 500; font-size: 56px; line-height: 1.03; letter-spacing: -0.02em; }
.t-display-2 { font-family: var(--bp-display-family); font-weight: 500; font-size: 40px; line-height: 1.08; letter-spacing: -0.015em; }
.t-display-3 { font-family: var(--bp-display-family); font-weight: 500; font-size: 28px; line-height: 1.15; letter-spacing: -0.01em; }
.t-heading    { font-weight: 600; font-size: 17px; line-height: 1.4; }
.t-body-lede  { font-family: var(--bp-serif-family); font-size: 20px; line-height: 1.55; }
.t-body       { font-size: 15px; line-height: 1.55; }
.t-body-sm    { font-size: 13.5px; line-height: 1.55; color: var(--bp-ink-2); }
.t-label      { font-family: var(--bp-mono-family); font-size: 11px; letter-spacing: 0.14em; text-transform: uppercase; color: var(--bp-ink-muted); }
.t-mono       { font-family: var(--bp-mono-family); font-size: 13px; color: var(--bp-ink); }

/* ─── Stage-complete pattern ──────────────────────────────────────────────── */
.complete-header {
  text-align: center;
  padding: var(--bp-s-8) var(--bp-s-5) var(--bp-s-6);
  max-width: 680px;
  margin: 0 auto var(--bp-s-6);
}
.complete-header h1 {
  font-family: var(--bp-display-family);
  font-weight: 500;
  font-size: 40px;
  line-height: 1.08;
  letter-spacing: -0.015em;
  margin: var(--bp-s-2) 0 var(--bp-s-3);
  color: var(--bp-ink);
}
.complete-header .t-body-lede { margin: 0; color: var(--bp-ink-2); }

/* The GTKY feedback screen after S2 (#1741): one centered column at the stage
   tier, the same as every other stage closing. It used `.complete-grid` until the
   300px aside came off — the aside duplicated what the coach's note now says, and
   squeezed the readiness report into a narrower column than the other five
   closings render it in. `.complete-grid` itself stays: the Flow-B entry and
   transition screens still use it. */
.gtky-feedback {
  max-width: var(--bp-w-stage);
  margin: 0 auto;
}

.complete-grid {
  display: grid;
  grid-template-columns: 1fr 300px;
  gap: var(--bp-s-6);
  align-items: start;
  max-width: var(--bp-w-page);
  margin: 0 auto;
}
@media (max-width: 860px) {
  .complete-grid { grid-template-columns: 1fr; }
}

.insight-list {
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-4);
}

.insight {
  background: var(--bp-paper);
  border: 1px solid var(--bp-rule);
  border-radius: var(--bp-r-lg);
  padding: var(--bp-s-5) var(--bp-s-6);
}
.insight-kicker {
  font-family: var(--bp-mono-family);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--bp-ink-muted);
  display: block;
  margin-bottom: var(--bp-s-2);
}
/* Wrap the .insight scope in :where() so descendant selectors stay at element-only
   specificity. Without this, `.insight p` (0,0,1,1) silently overrides any utility
   class on a child element (e.g. .t-body-sm at 0,0,1,0), breaking typography
   utilities for anything dropped inside an .insight card. */
:where(.insight) h2 {
  font-family: var(--bp-display-family);
  font-weight: 500;
  font-size: 22px;
  letter-spacing: -0.01em;
  margin: 0 0 var(--bp-s-2);
  color: var(--bp-ink);
}
:where(.insight) p { margin: 0 0 var(--bp-s-2); color: var(--bp-ink-2); font-size: 15px; line-height: 1.55; }
:where(.insight) p:last-child { margin-bottom: 0; }
:where(.insight) ul { margin: 0; padding-left: 1.25em; color: var(--bp-ink-2); font-size: 15px; line-height: 1.55; }
:where(.insight) ul li + li { margin-top: var(--bp-s-2); }
:where(.insight) h2 .bp-badge { font-size: 13px; padding: 4px 12px; vertical-align: middle; }

.complete-footer-nav {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: var(--bp-s-3);
  max-width: var(--bp-w-page);
  margin: var(--bp-s-6) auto 0;
  padding-top: var(--bp-s-5);
  border-top: 1px solid var(--bp-rule-soft);
}
@media (max-width: 480px) {
  .complete-footer-nav { flex-direction: column; }
  .complete-footer-nav .bp-btn { width: 100%; justify-content: center; }
}

/* Sidebar card stack inside complete-grid */
.complete-grid aside .bp-card { margin-bottom: var(--bp-s-4); }
.complete-grid aside .bp-card:last-child { margin-bottom: 0; }
.complete-grid aside .bp-card h2 { margin: 0 0 var(--bp-s-2); }

/* ============================================================
   Migrated from capabilities.css (issue #864)

   The blocks below were previously siloed in a per-feature
   `capabilities.css` stylesheet — the Claude Code Handoff §07
   names that pattern as forbidden. The migration consolidated
   onto existing `.bp-*` library primitives wherever possible:

     - card chrome    → `.bp-card` (rules carry layout only)
     - begin CTA      → `.bp-btn .bp-btn--primary .bp-btn--lg`
     - step kicker    → `.bp-badge .bp-badge--accent`
     - detail textarea → `.bp-textarea`

   What remains is cross-stage shell shared by GTKY / placeholder
   intros / capabilities (renamed out of `capabilities-` to
   `.stage-intro__*` and `.questionnaire-*`) and the
   capabilities-specific dashboard / category / entry-form /
   entry-editor compositions.
   ============================================================ */

/* ──────────────────────────────────────────────────────────────
   Stage intro shell — 2-column "title + content + sidebar"
   layout shared across stages.

   Used by `_placeholder_intro` (any stage), `_questionnaire_shell`
   (GTKY + future questionnaire stages), and the Capabilities
   intro full page. The previous `.capabilities-intro-*` (hyphen,
   not BEM `__`) names predate the slice-1a rewrite and were
   already cross-stage despite the misleading prefix.
   ────────────────────────────────────────────────────────────── */

.stage-intro {
  padding: 2rem;
}

.stage-intro__header {
  margin-bottom: 3rem;
  text-align: center;
}

.stage-intro__header h1 {
  font-size: 2rem;
  margin-bottom: 0.5rem;
  color: var(--bp-ink);
}

.stage-intro__header .subtitle {
  font-size: 1.1rem;
  color: var(--bp-ink-muted);
}

/* Stage-3 intro capture-mode selector (iter-4 D4) — the GTKY-derived mode named
   in the lede and presented as the recommended card in a co-equal 3-card fork
   (the .bp-choice-card pattern; layout mirrors stages/gtky/mode_select). Only the
   intro-scoped layout lives here; the card chrome + the --recommended variant are
   library atoms. */
.stage-intro__mode {
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-4);
}
.stage-intro__mode-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: var(--bp-s-4);
}
.stage-intro__mode-card {
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-3);
}
.stage-intro__mode-card-header {
  display: grid;
  gap: var(--bp-s-1);
}
.stage-intro__mode-card-header h2 {
  margin: 0;
}
/* Pin the badge above the kicker without forcing extra grid rows on the
   non-recommended cards (which have no badge). */
.stage-intro__mode-card-header .bp-badge {
  justify-self: start;
  margin-bottom: var(--bp-s-1);
}
.stage-intro__mode-card-footer {
  margin-top: auto;
  padding-top: var(--bp-s-3);
}

.stage-intro__layout {
  display: grid;
  grid-template-columns: 1fr 300px;
  gap: 2rem;
}

@media (max-width: 768px) {
  .stage-intro__layout {
    grid-template-columns: 1fr;
  }
}

.stage-intro__main {
  display: flex;
  flex-direction: column;
  gap: 2rem;
}

/* Card content typography inside the stage-intro main column —
   the cards themselves are plain `.bp-card`, so these rules only
   shape the title/body spacing of cards rendered inside this
   layout. */
.stage-intro__main > .bp-card h2 {
  font-size: 1.2rem;
  margin-bottom: 0.75rem;
  color: var(--bp-ink);
}

.stage-intro__main > .bp-card p {
  color: var(--bp-ink);
  line-height: 1.6;
  margin: 0;
}

.stage-intro__sidebar {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
}

.stage-intro__sidebar > .bp-card h3 {
  font-size: 1rem;
  margin: 0 0 0.75rem;
  color: var(--bp-ink);
}

.stage-intro__sidebar > .bp-card p {
  font-size: 0.9rem;
  color: var(--bp-ink);
  line-height: 1.6;
  margin: 0 0 0.75rem;
}

.stage-intro__sidebar > .bp-card p:last-child {
  margin-bottom: 0;
}

.stage-intro__sidebar > .bp-card ul {
  margin: 0.75rem 0 0;
  padding-left: 1.25rem;
  font-size: 0.9rem;
  color: var(--bp-ink-muted);
}

.stage-intro__sidebar > .bp-card ul li {
  margin-bottom: 0.4rem;
}

/* Numbered-step list (placeholder intros use this for "What
   You'll Do" walk-throughs). */
.stage-intro__steps {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
}

.stage-intro__steps li {
  display: flex;
  gap: 1rem;
  align-items: flex-start;
}

/* Numeric step marker — circular badge containing the step
   number, paired with `.step-content` for the label + body. */
.step-number {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  min-width: 2rem;
  background: var(--bp-accent);
  color: var(--bp-accent-ink);
  border-radius: 50%;
  font-weight: 700;
  font-size: 0.9rem;
}

.step-content h3 {
  font-size: 1rem;
  margin: 0 0 0.25rem;
  color: var(--bp-ink);
}

.step-content p {
  font-size: 0.9rem;
  color: var(--bp-ink-muted);
  margin: 0;
}

/* Small italic note ("time estimate", "auto-save", etc.) — used
   inside stage-intro sidebar cards. Scoped under the sidebar-card
   path so it has enough specificity to beat the broader
   `.stage-intro__sidebar > .bp-card p` rule's `color: var(--bp-ink)`
   without needing `!important`. */
.stage-intro__sidebar > .bp-card p.stage-intro__time-note {
  color: var(--bp-ink-muted);
  font-style: italic;
}

/* ──────────────────────────────────────────────────────────────
   Questionnaire surfaces — used by the GTKY survey form,
   GTKY review, and any future questionnaire-driven stage.
   ────────────────────────────────────────────────────────────── */

/* Centered hero block above the question card — kicker badge +
   title + subtitle. The kicker is `.bp-badge .bp-badge--accent`
   in markup; this rule just spaces it from the title below. */
.questionnaire-step-header {
  margin-bottom: 2rem;
  text-align: center;
}

.questionnaire-step-header .bp-badge { margin-bottom: 0.75rem; }

.questionnaire-step-header h1 {
  font-size: 2rem;
  margin-bottom: 0.5rem;
  color: var(--bp-ink);
}

.questionnaire-step-header .subtitle {
  font-size: 1.1rem;
  color: var(--bp-ink-muted);
  margin-bottom: 0.75rem;
}

/* Survey-form footer — back-to-dashboard left, mode-switch right.
   Mirrors the AI chat's `.chat-hint` footer so the two end-of-
   page actions sit at the same vertical on both surfaces (#819). */
.survey-form__footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--bp-s-2) var(--bp-s-4);
  margin-top: 1rem;
}

.survey-form__switch-form { margin: 0; }

.survey-form__back-link,
.survey-form__switch-link {
  flex-shrink: 0;
  font-family: inherit;
  font-size: 13px;
  font-weight: 500;
  background: transparent;
  border: none;
  cursor: pointer;
  padding: 0;
  text-decoration: underline;
  text-underline-offset: 2px;
  transition: color var(--bp-dur-fast) var(--bp-easing);
}

.survey-form__back-link { color: var(--bp-ink-muted); }
.survey-form__back-link:hover { color: var(--bp-ink); }
.survey-form__switch-link { color: var(--bp-accent); }
.survey-form__switch-link:hover { color: var(--bp-ink); }

/* Individual question wrapper inside a `.bp-card` form panel —
   label + helper + input controls stacked vertically. */
.questionnaire-field {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.questionnaire-field__label {
  font-size: 0.95rem;
  font-weight: 500;
  color: var(--bp-ink);
}

/* Label suppression — questions whose label is hidden by a
   conditional rule stay in the flow but render without their
   question text. Hidden via sr-only-style positioning rather
   than `display: none` so the label remains in the accessibility
   tree and continues to provide an accessible name. */
.questionnaire-field__label.is-suppressed {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.questionnaire-field__helper {
  font-size: 0.85rem;
  color: var(--bp-ink-muted);
  line-height: 1.5;
}

.questionnaire-field__helper p { margin: 0; }

/* Toggle helper variants based on the parent question's
   data-suppress-label state. The questionnaire-reveal Stimulus
   controller flips that attribute on the question wrapper, so
   this purely-declarative swap stays in sync without extra JS. */
.q-reveal--helper-suppressed { display: none; }

.q-reveal--question[data-suppress-label="true"] .q-reveal--helper-default {
  display: none;
}

.q-reveal--question[data-suppress-label="true"] .q-reveal--helper-suppressed {
  display: block;
}

/* Footer row of the question card — Back / Continue / Submit. */
.questionnaire-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-top: 1rem;
  border-top: 1px solid var(--bp-rule);
}

/* ── Questionnaire reveal: progress bar + sticky variant ── */
.q-reveal-progress {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin-bottom: 1.25rem;
}

/* Sticky variant — keeps the progress indicator visible as the
   user scrolls through revealed/completed questions. The offset
   clears the sticky `.app-bar`, which sits on --bp-z-chrome; this
   takes the --bp-z-sticky rung, above question cards and below the
   modal layer. The ladder is defined in application.css — the rung
   names are the contract, so this comment no longer has to quote
   another stylesheet's raw numbers to stay accurate. */
.q-reveal-progress.is-sticky {
  position: sticky;
  top: 56px;
  z-index: var(--bp-z-sticky);
  background: var(--bp-paper);
  padding: 0.75rem 0;
  margin-bottom: 0.75rem;
  border-bottom: 1px solid var(--bp-rule-soft);
}

@media (max-height: 600px) {
  .q-reveal-progress.is-sticky {
    position: static;
    border-bottom: 0;
    padding: 0;
  }
}

/* ── Questionnaire reveal: question states ── */

/* Newly-revealed questions fade in from below. Base class is
   visible by default so no-JS users still see all questions;
   the animation only plays when JS adds `q-reveal--visible`. */
@keyframes q-reveal-enter {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: translateY(0); }
}

.q-reveal--question.q-reveal--visible {
  animation: q-reveal-enter 0.25s ease both;
}

.q-reveal--active {
  border-left: 3px solid var(--bp-accent);
  padding-left: 0.75rem;
  margin-left: -0.75rem;
}

@keyframes q-refocus {
  0%   { box-shadow: 0 0 0 3px color-mix(in srgb, var(--bp-accent) 0%, transparent); }
  40%  { box-shadow: 0 0 0 3px color-mix(in srgb, var(--bp-accent) 20%, transparent); }
  100% { box-shadow: 0 0 0 3px color-mix(in srgb, var(--bp-accent) 0%, transparent); }
}

.q-reveal--refocus { animation: q-refocus 0.4s ease; }

.q-reveal--completed {
  opacity: 0.75;
  padding-bottom: 1rem;
  border-bottom: 1px dashed var(--bp-rule);
  margin-bottom: 0.25rem;
}

.q-reveal--completed.q-reveal--last-completed { border-bottom: none; }

.q-reveal--completed .bp-pill:not(.is-selected) { display: none; }

.q-reveal--completed input[type="text"],
.q-reveal--completed textarea {
  pointer-events: none;
  background: var(--bp-surface);
  border-color: transparent;
  color: var(--bp-ink);
  resize: none;
}

.q-reveal--question-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
}

.q-reveal--change-btn {
  display: none;
  font-size: 0.75rem;
  font-family: inherit;
  font-weight: 500;
  color: var(--bp-accent);
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  white-space: nowrap;
  text-decoration: underline;
  flex-shrink: 0;
  margin-top: 1px;
}

.q-reveal--completed .q-reveal--change-btn { display: inline-block; }

.q-reveal-nav {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

/* ──────────────────────────────────────────────────────────────
   Shared utilities
   ────────────────────────────────────────────────────────────── */

/* Month-picker polyfill — two `<select>` elements replacing
   `<input type="month">`. Used by `month_year_field` in
   `stages/capabilities_helper.rb`. */
.month-picker-selects {
  display: inline-flex;
  gap: 0.4rem;
  flex-wrap: wrap;
}

.month-picker-selects select {
  flex: 1 1 auto;
  min-width: 7rem;
}

/* Visually hidden but available to screen readers. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ============================================================
   Capabilities — Stage Introduction (Flow A — slice 1a, #834)
   ============================================================ */

.capabilities-intro {
  max-width: var(--bp-w-read);
  margin: 0 auto;
  padding: var(--bp-s-6) var(--bp-s-5) var(--bp-s-7);
}

.capabilities-intro__header { margin-bottom: var(--bp-s-6); }

.capabilities-intro__header h1 {
  margin: var(--bp-s-2) 0 var(--bp-s-3);
}

.capabilities-intro__body { margin-bottom: var(--bp-s-6); }

.capabilities-intro__footer {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--bp-s-3);
}

.capabilities-intro__cta-form { margin: 0; }

/* Capabilities intro modal — passed as `custom_class:` on
   `shared/_modal`, with the body rendered from
   `shared/_capabilities_intro_content`. The body uses these
   classes for the title/copy typography. */
.capabilities-intro-modal-content { max-width: 560px; }

.capabilities-intro-modal-goal {
  color: var(--bp-ink);
  line-height: 1.6;
  margin-bottom: 1.25rem;
}

.capabilities-intro-modal-steps-heading {
  font-size: 1rem;
  font-weight: 600;
  margin-bottom: 0.75rem;
  color: var(--bp-ink);
}

.capabilities-intro-modal-steps {
  padding-left: 1.25rem;
  margin-bottom: 1.25rem;
  color: var(--bp-ink);
}

.capabilities-intro-modal-steps li {
  margin-bottom: 0.6rem;
  line-height: 1.5;
}

.capabilities-intro-modal-time {
  font-size: 0.9rem;
  color: var(--bp-ink-muted);
  margin: 0;
}

/* ============================================================
   Capabilities — Flow B Category Filter (slice 1b, #835)
   ============================================================ */

.capabilities-filter {
  max-width: var(--bp-w-read);
  margin: 0 auto;
  padding: var(--bp-s-6) var(--bp-s-5) var(--bp-s-7);
}

.capabilities-filter__header { margin-bottom: var(--bp-s-5); }

.capabilities-filter__header h1 {
  margin: var(--bp-s-2) 0 var(--bp-s-3);
}

.capabilities-filter__notice { margin-bottom: var(--bp-s-6); }

.capabilities-filter__notice ul {
  margin: var(--bp-s-2) 0;
  padding-left: 1.25rem;
}

.capabilities-filter__notice li { line-height: 1.6; }

.capabilities-filter__details {
  margin: var(--bp-s-3) 0 0;
  font-size: 0.9rem;
  color: var(--bp-ink);
}

.capabilities-filter__details > summary {
  cursor: pointer;
  font-weight: 500;
  color: var(--bp-accent);
  list-style: none;
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
}

.capabilities-filter__details > summary::-webkit-details-marker {
  display: none;
}

.capabilities-filter__details > summary::before {
  content: "▸";
  display: inline-block;
  transition: transform var(--bp-dur-fast) var(--bp-easing);
  font-size: 0.85em;
}

.capabilities-filter__details[open] > summary::before {
  transform: rotate(90deg);
}

.capabilities-filter__details > p {
  margin: var(--bp-s-2) 0 0;
  line-height: 1.55;
  color: var(--bp-ink-muted);
}

.capabilities-filter__ai-reasoning {
  margin: var(--bp-s-2) 0 0;
  color: var(--bp-ink-muted);
  font-size: 0.85rem;
  line-height: 1.45;
  max-width: 60ch;
}

.capabilities-filter__form {
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-5);
}

.capabilities-filter__group {
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-2);
}

.capabilities-filter__group-title {
  font-size: 1rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--bp-ink);
  margin: 0;
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.capabilities-filter__group-count {
  font-size: 0.8rem;
  font-weight: 500;
  color: var(--bp-ink-muted);
  background: var(--bp-surface);
  border: 1px solid var(--bp-rule);
  border-radius: var(--bp-r-pill);
  padding: 0.05rem 0.5rem;
}

.capabilities-filter__group-blurb {
  margin: 0;
  font-size: 0.85rem;
  color: var(--bp-ink-muted);
  line-height: 1.45;
}

.capabilities-filter__group-empty {
  font-style: italic;
  color: var(--bp-ink-muted);
  margin: 0;
}

.capabilities-filter__rows {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  border: 1px solid var(--bp-rule);
  border-radius: var(--bp-r-md);
  overflow: hidden;
  background: var(--bp-paper);
}

.capabilities-filter__row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.75rem 1rem;
}

.capabilities-filter__row-label {
  flex: 1 1 auto;
  min-width: 0;
}

.capabilities-filter__row + .capabilities-filter__row {
  border-top: 1px solid var(--bp-rule-soft);
}

.capabilities-filter__category-name {
  font-size: 0.95rem;
  color: var(--bp-ink);
}

.capabilities-filter__ai-reasoning + .capabilities-filter__gtky-note,
.capabilities-filter__category-name + .capabilities-filter__gtky-note {
  margin-top: var(--bp-s-2);
}

.capabilities-filter__gtky-note {
  margin: var(--bp-s-2) 0 0;
  font-size: 0.8rem;
  line-height: 1.4;
  color: var(--bp-accent);
  max-width: 60ch;
}

.capabilities-filter__row-control { flex-shrink: 0; }

/* Segmented Applicable / Not-Applicable toggle. The radios are visually
   hidden; the sibling <span> label is the tappable segment and reflects the
   checked state via :checked + sibling selectors. */
.capabilities-filter__toggle {
  display: inline-flex;
  border: 1px solid var(--bp-rule);
  border-radius: var(--bp-r-pill);
  overflow: hidden;
  padding: 0;
  margin: 0;
  background: var(--bp-paper);
}

.capabilities-filter__toggle-option {
  display: inline-flex;
  cursor: pointer;
}

.capabilities-filter__toggle-option input {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.capabilities-filter__toggle-option span {
  display: inline-block;
  padding: 0.4rem 0.85rem;
  font-size: 0.85rem;
  color: var(--bp-ink-muted);
  transition: background var(--bp-dur-fast) var(--bp-easing),
              color var(--bp-dur-fast) var(--bp-easing);
}

.capabilities-filter__toggle-option:first-child span {
  border-right: 1px solid var(--bp-rule);
}

.capabilities-filter__toggle-option input:checked + span {
  background: var(--bp-accent);
  color: var(--bp-on-accent, #fff);
  font-weight: 500;
}

.capabilities-filter__toggle-option input:focus-visible + span {
  outline: 2px solid var(--bp-accent);
  outline-offset: -2px;
}

.capabilities-filter__toggle-option input:disabled + span {
  cursor: not-allowed;
  color: var(--bp-ink-faint, var(--bp-ink-muted));
  opacity: 0.55;
}

.capabilities-filter__toggle-option:has(input:disabled) {
  cursor: not-allowed;
}

.capabilities-filter__footer {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--bp-s-3);
  padding-top: var(--bp-s-4);
  border-top: 1px solid var(--bp-rule);
}

@media (max-width: 600px) {
  .capabilities-filter__row {
    flex-direction: column;
    align-items: flex-start;
  }
}

/* ============================================================
   Capabilities — Stage Dashboard (slice 1c, #836; +slice 1d, #837)

   The summary cards, category cards, and manage-modal rows
   carry plain `.bp-card` in markup for chrome (bg + border +
   radius). The selectors below only set padding overrides and
   the unique flex / grid layout — no duplicated chrome.
   ============================================================ */

.capabilities-dashboard {
  max-width: var(--bp-w-page);
  margin: 0 auto;
  padding: var(--bp-s-6) var(--bp-s-5) var(--bp-s-7);
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-6);
}

.capabilities-dashboard__hero h1 {
  margin: var(--bp-s-2) 0 var(--bp-s-3);
}

.capabilities-dashboard__hero-actions {
  margin-top: var(--bp-s-3);
  display: flex;
  gap: var(--bp-s-3);
}

/* Two-column work / status split. Main column flexes; the status rail
   is a fixed width so a long Role Readiness statement grows the rail's
   own height instead of pushing the active categories below the fold.
   `align-items: start` keeps each column's height independent. */
.capabilities-dashboard__split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 320px;
  gap: var(--bp-s-6);
  align-items: start;
}

.capabilities-dashboard__main {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-5);
}

.capabilities-dashboard__rail {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-4);
}

/* Below 900px the rail drops beneath the work (source order is main
   first), so the active categories stay directly under the page hero. */
@media (max-width: 900px) {
  .capabilities-dashboard__split {
    grid-template-columns: 1fr;
  }
}

/* Each status / continue card pairs `.bp-card` (chrome) with this class
   for the tighter padding + inner flex stack. */
.capabilities-dashboard__card {
  padding: var(--bp-s-4);
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-2);
}

/* Pin each card's CTA to the bottom of its flex stack so the button
   sits below the copy regardless of how much text precedes it. */
.capabilities-dashboard__card .bp-btn {
  margin-top: auto;
}

/* The Continue CTA is a button_to (POST) — `display: contents` collapses
   its wrapper <form> so the button itself stays the card's flex child and
   keeps the margin-top:auto bottom-pin above. */
.capabilities-dashboard__continue-cta-form {
  display: contents;
}

.capabilities-dashboard__kicker {
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--bp-ink-muted);
}

.capabilities-dashboard__continue-title {
  margin: 0;
  font-size: 1.05rem;
  color: var(--bp-ink);
}

.capabilities-dashboard__continue-meta,
.capabilities-dashboard__continue-empty {
  margin: 0;
  font-size: 0.9rem;
  color: var(--bp-ink-muted);
}

.capabilities-dashboard__progress-count {
  margin: 0;
  font-size: 0.95rem;
  color: var(--bp-ink);
}

.capabilities-dashboard__readiness h2 { margin: 0; }

.capabilities-dashboard__section-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--bp-s-3);
  margin-bottom: var(--bp-s-4);
}

.capabilities-dashboard__section-title {
  margin: 0;
  font-size: 1.15rem;
  font-weight: 600;
  color: var(--bp-ink);
}

.capabilities-dashboard__empty {
  font-style: italic;
  color: var(--bp-ink-muted);
}

/* Flow D import offer (slice 1f, #839) — a single soft card between
   the summary row and the category list, shown only while the
   one-time import offer is still available. */
.capabilities-dashboard__import {
  margin-bottom: var(--bp-s-5);
}

.capabilities-dashboard__import-card {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--bp-s-4);
}

.capabilities-dashboard__import-body {
  flex: 1 1 20rem;
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-1);
}

.capabilities-dashboard__import-title {
  margin: 0;
  font-size: 1.15rem;
  color: var(--bp-ink);
}

.capabilities-dashboard__import-copy {
  margin: 0;
  line-height: 1.6;
  color: var(--bp-ink-muted);
}

/* Capture Guidance Helper (S6) — "describe it, I'll route it". A quiet card
   above the category list; deliberately soft so it reads as a helper, not a
   primary action. Inherits `.bp-card--soft`. */
.capabilities-dashboard__guidance {
  display: block;
  margin-bottom: var(--bp-s-5);
}

.capabilities-dashboard__guidance-card {
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-3);
}

/* Collapsible header (native <details><summary>). Custom chevron in place of
   the default marker, rotating on open — mirrors the category-introduction
   disclosure so the two read as the same affordance. When collapsed only this
   summary shows; the card gap disappears with the hidden content. */
.capabilities-dashboard__guidance-summary {
  cursor: pointer;
  list-style: none;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--bp-ink-muted);
}

.capabilities-dashboard__guidance-summary::-webkit-details-marker {
  display: none;
}

.capabilities-dashboard__guidance-summary::before {
  content: "▸";
  display: inline-block;
  transition: transform var(--bp-dur-fast) var(--bp-easing);
  font-size: 0.95em;
  color: var(--bp-ink-muted);
}

.capabilities-dashboard__guidance-card[open] .capabilities-dashboard__guidance-summary::before {
  transform: rotate(90deg);
}

.capabilities-dashboard__guidance-body {
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-1);
}

.capabilities-dashboard__guidance-title {
  margin: 0;
  font-size: 1.15rem;
  color: var(--bp-ink);
}

.capabilities-dashboard__guidance-copy {
  margin: 0;
  line-height: 1.6;
  color: var(--bp-ink-muted);
}

.capabilities-dashboard__guidance-form {
  display: flex;
  flex-wrap: wrap;
  align-items: end;
  gap: var(--bp-s-3);
}

/* The field carries its own bottom margin (.bp-field); drop it here so the
   input and the submit button baseline-align on one row. */
.capabilities-dashboard__guidance-form .bp-field {
  flex: 1 1 20rem;
  margin-bottom: 0;
}

.capabilities-dashboard__guidance-note {
  margin: 0;
  line-height: 1.6;
  color: var(--bp-ink-muted);
}

.capabilities-dashboard__guidance-lead {
  margin: var(--bp-s-2) 0 var(--bp-s-2);
  font-weight: 600;
  color: var(--bp-ink);
}

.capabilities-dashboard__guidance-matches {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-2);
}

.capabilities-dashboard__guidance-match {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--bp-s-3);
  padding: var(--bp-s-3);
  border: 1px solid var(--bp-rule-soft);
  border-radius: var(--bp-radius);
}

.capabilities-dashboard__guidance-match-text {
  flex: 1 1 16rem;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.capabilities-dashboard__guidance-match-name {
  font-weight: 600;
  color: var(--bp-ink);
}

.capabilities-dashboard__guidance-match-reason {
  font-size: 0.875rem;
  line-height: 1.5;
  color: var(--bp-ink-muted);
}

/* Not-Applicable action: the "you set this aside" caption stacks directly
   above its reinstate button so the row stays two columns (text | action)
   rather than three. */
.capabilities-dashboard__guidance-match-action {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--bp-s-1);
}

.capabilities-dashboard__guidance-match-na {
  font-size: 0.8125rem;
  color: var(--bp-ink-muted);
}

/* button_to renders a form wrapper; keep it inline so the CTA sits on the
   match row rather than forcing a line break. */
.capabilities-dashboard__guidance-match form {
  margin: 0;
}

/* Capture-depth indicator (S4) — a quiet, read-only pill where the
   retired tier badge used to sit. It communicates what finishing the
   category takes (`Facts` vs `Refined`), not a setting the user picks,
   so it is deliberately low-prominence: no fill, muted ink, a subtle
   rule. `help` cursor + `title`/sr-only note carry the one-line
   explanation (DESIGN § Dashboard item 4). */
.capabilities-dashboard__depth {
  display: inline-flex;
  align-items: center;
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--bp-ink-muted);
  padding: 2px var(--bp-s-2);
  border: 1px solid var(--bp-rule-soft);
  border-radius: var(--bp-r-sm);
  cursor: help;
}

/* The legend renders the same badge inline in a sentence, so it must
   sit on the text baseline and not carry the standalone pill's help
   cursor (the legend is already the explanation). */
.capabilities-dashboard__depth--inline {
  vertical-align: baseline;
  cursor: inherit;
}

/* One-line key for the per-card depth badges. Quiet by design — it
   explains the Facts/Refined tags once so the badge itself needn't be
   hovered to be understood. */
.capabilities-dashboard__depth-legend {
  margin: 0 0 var(--bp-s-3);
  font-size: 0.8125rem;
  line-height: 1.5;
  color: var(--bp-ink-muted);
}

.capabilities-dashboard__category-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-3);
}

/* Each category card pairs `.bp-card` (chrome) with this class
   for the tighter padding + inner flex stack. */
.capabilities-dashboard__category {
  padding: var(--bp-s-4);
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-3);
}

.capabilities-dashboard__category-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--bp-s-3);
}

.capabilities-dashboard__category-identity {
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-1);
  /* `flex-start` (NOT the default `stretch`) keeps the
     designation pill — an inline-flex element — from stretching
     to the column's full width. Without this it renders as wide
     as the category h3 ("Work Experience"), which reads as a
     long bar rather than a pill. */
  align-items: flex-start;
}

.capabilities-dashboard__category-meta {
  display: flex;
  align-items: center;
  gap: var(--bp-s-2);
  flex-wrap: wrap;
}

.capabilities-dashboard__category-actions {
  display: flex;
  gap: var(--bp-s-2);
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
}

.capabilities-dashboard__category-name {
  margin: 0;
  font-size: 1rem;
  font-weight: 600;
  color: var(--bp-ink);
}

/* The name is the only route to the category screen now that the
   "Open category" button is gone. It reads as the heading it is, and
   reveals itself as a link on hover rather than shouting in link blue. */
.capabilities-dashboard__category-name a {
  color: inherit;
  text-decoration: none;
}

.capabilities-dashboard__category-name a:hover,
.capabilities-dashboard__category-name a:focus-visible {
  text-decoration: underline;
  text-decoration-color: var(--bp-rule);
  text-underline-offset: 3px;
}

.capabilities-dashboard__category-empty {
  margin: 0;
  font-size: 0.9rem;
  color: var(--bp-ink-muted);
  font-style: italic;
}

/* One disclosure primitive, two uses: "Why this matters" and (later) the
   completed-entry fold. Same affordance, same weight, so a card never
   looks like it has two different kinds of secret. */
.capabilities-dashboard__disclosure > summary {
  list-style: none;
  cursor: pointer;
  font-size: 0.78rem;
  color: var(--bp-ink-muted);
  padding: var(--bp-s-2) 0;
  display: flex;
  align-items: center;
  gap: var(--bp-s-2);
}

.capabilities-dashboard__disclosure > summary::-webkit-details-marker { display: none; }

.capabilities-dashboard__disclosure > summary::before {
  content: "+";
  font-family: var(--bp-mono-family);
  font-size: 0.8rem;
  color: var(--bp-ink-subtle);
  width: 9px;
  text-align: center;
}

.capabilities-dashboard__disclosure[open] > summary::before { content: "\2212"; }

.capabilities-dashboard__disclosure > summary:hover { color: var(--bp-ink); }

.capabilities-dashboard__disclosure > summary:focus-visible {
  outline: 2px solid var(--bp-accent);
  outline-offset: 2px;
  border-radius: var(--bp-r-sm);
}

/* "Why this matters" sits directly under the category head: the reason
   precedes the work. Collapsed by default; the body is a lazily-loaded
   Turbo Frame, so the AI call happens on expand and never on the
   dashboard render. The 17px left pad aligns the copy with the summary
   text, past the +/− marker. */
.capabilities-dashboard__why { margin-top: var(--bp-s-1); }

.capabilities-dashboard__why-copy {
  font-family: var(--bp-serif-family);
  font-size: 1rem;
  line-height: 1.6;
  color: var(--bp-ink-2);
  margin: 0;
  max-width: 68ch;
  padding: 0 0 var(--bp-s-3) 17px;
}

.capabilities-dashboard__why-loading {
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-2);
  padding: var(--bp-s-1) 0 var(--bp-s-4) 17px;
  max-width: 68ch;
}

.capabilities-dashboard__why-skeleton {
  height: 9px;
  border-radius: var(--bp-r-pill);
  background: var(--bp-surface-2);
}

/* Entry rows. A rule-separated list, not a stack of cards — nesting
   cards inside cards is the fastest way to make a dashboard feel
   heavy. */
.capabilities-dashboard__entries {
  list-style: none;
  margin: var(--bp-s-3) 0 0;
  padding: 0;
  border-top: 1px solid var(--bp-rule-soft);
}

.capabilities-dashboard__entry {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  align-items: center;
  gap: var(--bp-s-4);
  padding: var(--bp-s-3) 0;
  border-bottom: 1px solid var(--bp-rule-soft);
}

.capabilities-dashboard__entry:last-child { border-bottom: 0; }

.capabilities-dashboard__entry-main {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.capabilities-dashboard__entry-title {
  font-weight: 600;
  font-size: 0.9rem;
  color: var(--bp-ink);
  text-decoration: none;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.capabilities-dashboard__entry-title:hover {
  text-decoration: underline;
  text-decoration-color: var(--bp-rule);
  text-underline-offset: 3px;
}

.capabilities-dashboard__entry-sub {
  font-size: 0.78rem;
  color: var(--bp-ink-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* A finished entry recedes: it is a record, not a task. */
.capabilities-dashboard__entry[data-done="true"] .capabilities-dashboard__entry-title {
  font-weight: 500;
  color: var(--bp-ink-2);
}

/* Reserve the action column even when an entry has no action, so the
   status badges stay in one vertical line down the card. */
.capabilities-dashboard__entry-action {
  min-width: 150px;
  display: flex;
  justify-content: flex-end;
}

.capabilities-dashboard__entry-action--none {
  color: var(--bp-ink-subtle);
  font-size: 0.78rem;
  font-style: italic;
  padding-right: var(--bp-s-2);
}

/* Below the phone breakpoint the three-column grid crushes the title.
   Stack instead, and let the badge + action sit on one line under it. */
@media (max-width: 720px) {
  .capabilities-dashboard__entry {
    grid-template-columns: minmax(0, 1fr) auto;
    gap: var(--bp-s-2) var(--bp-s-3);
  }

  .capabilities-dashboard__entry-main { grid-column: 1 / -1; }
  .capabilities-dashboard__entry-action { min-width: 0; }
}

/* The one-line "where does this category stand" summary that takes the
   rollup vector's place. It sits BELOW the entries so the card reads
   reason -> work -> score; a summary belongs at the end. */
.capabilities-dashboard__category-standing {
  display: flex;
  align-items: center;
  gap: var(--bp-s-3);
  margin-top: var(--bp-s-4);
  padding-top: var(--bp-s-3);
  border-top: 1px solid var(--bp-rule-soft);
}

.capabilities-dashboard__category-standing .bp-progress {
  flex: 1;
  max-width: 180px;
}

.capabilities-dashboard__standing-text {
  font-size: 0.8rem;
  color: var(--bp-ink-muted);
  font-variant-numeric: tabular-nums;
}

.capabilities-dashboard__standing-text strong {
  color: var(--bp-ink-2);
  font-weight: 600;
}

/* N/A bottom section — collapsed-by-default `<details>`,
   expanding to reveal a list of categories the user marked Not
   Applicable with inline Reinstate-as-<designation> affordances.
   Lives below the active designation groups so it doesn't
   visually compete with the work the user is trying to do, but
   stays discoverable so "where did Category X go?" has an
   obvious answer. */
.capabilities-dashboard__na {
  margin-top: var(--bp-s-4);
  border-top: 1px dashed var(--bp-rule);
  padding-top: var(--bp-s-3);
}

.capabilities-dashboard__na-summary {
  display: flex;
  align-items: center;
  gap: var(--bp-s-2);
  cursor: pointer;
  padding: var(--bp-s-1) var(--bp-s-2);
  margin-inline: calc(-1 * var(--bp-s-2));
  border-radius: var(--bp-r-md);
  font-size: 0.75rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--bp-ink-muted);
  user-select: none;
  /* Hide the default disclosure markers — both the Firefox /
     spec list-item marker and Safari's WebKit-specific
     `::-webkit-details-marker` pseudo. We render our own chevron
     below so the toggle affordance is visible across browsers
     and stays consistent with `display: flex` on the summary
     (which suppresses the default marker in some engines). */
  list-style: none;
}

.capabilities-dashboard__na-summary::-webkit-details-marker {
  display: none;
}

.capabilities-dashboard__na-summary::before {
  content: "";
  display: inline-block;
  width: 0.5rem;
  height: 0.5rem;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(-45deg) translate(-1px, -1px);
  transition: transform 150ms ease;
}

.capabilities-dashboard__na[open] .capabilities-dashboard__na-summary::before {
  transform: rotate(45deg) translate(-1px, -1px);
}

.capabilities-dashboard__na-summary:hover {
  background: var(--bp-tint-info);
  color: var(--bp-ink);
}

.capabilities-dashboard__na-summary:focus-visible {
  outline: 2px solid var(--bp-accent);
  outline-offset: 2px;
}

.capabilities-dashboard__na-summary-count {
  font-variant-numeric: tabular-nums;
}

.capabilities-dashboard__na-list {
  list-style: none;
  margin: var(--bp-s-2) 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-2);
}

.capabilities-dashboard__na-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--bp-s-3);
  padding: var(--bp-s-2) 0;
  flex-wrap: wrap;
}

.capabilities-dashboard__na-name {
  font-weight: 600;
  color: var(--bp-ink);
}

.capabilities-dashboard__na-actions {
  display: flex;
  align-items: center;
  gap: var(--bp-s-2);
  flex-wrap: wrap;
}

/* ============================================================
   Capabilities — applicability control (Concept A, S4)
   With tiers retired (epic #1598) the control is a single-click
   binary action: a direct "Mark Not Applicable" button on an
   Applicable card, a direct "Reinstate" on a Not Applicable row,
   or a quiet reason when GTKY forbids the move. Both PATCH the
   same endpoint.
   ============================================================ */

.capabilities-dashboard__designation {
  display: inline-flex;
  align-items: center;
}

/* `button_to` wraps the action in a form; it must not become a
   layout box between the control's flex row and its button. */
.capabilities-dashboard__designation-form {
  display: contents;
  margin: 0;
}

/* Never lie about state: say WHY the move is unavailable, rather
   than offering an action the server would bounce to another
   screen. Quiet and inline — it sits in the card's meta row. */
.capabilities-dashboard__designation-note {
  font-size: 12px;
  color: var(--bp-ink-subtle);
  line-height: 1.4;
  max-width: 22rem;
}

/* ============================================================
   Capabilities — Flow D Data Import (slice 1f, #839)
   Import offer surface (resume / LinkedIn cards + manual-entry
   escape) and the "no longer available" spent-offer state.
   ============================================================ */

.capabilities-data-import {
  max-width: var(--bp-w-read);
  margin: 0 auto;
  padding: var(--bp-s-6) var(--bp-s-5) var(--bp-s-7);
}

.capabilities-data-import__header { margin-bottom: var(--bp-s-6); }

.capabilities-data-import__header h1 {
  margin: var(--bp-s-2) 0 var(--bp-s-3);
}

/* One-time-import note — a quiet inset banner above the source cards so
   the user knows resume / LinkedIn are mutually exclusive before they
   pick one. */
.capabilities-data-import__note {
  margin: 0 0 var(--bp-s-5);
  padding: var(--bp-s-3) var(--bp-s-4);
  border-left: 3px solid var(--bp-rule);
  background: var(--bp-paper);
  border-radius: var(--bp-r-sm);
  line-height: 1.6;
  color: var(--bp-ink-muted);
}

.capabilities-data-import__sources {
  display: grid;
  gap: var(--bp-s-4);
  margin-bottom: var(--bp-s-6);
}

@media (min-width: 720px) {
  .capabilities-data-import__sources {
    grid-template-columns: repeat(2, 1fr);
  }
}

.capabilities-data-import__source {
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-2);
}

.capabilities-data-import__kicker {
  font-size: 0.8rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--bp-ink-muted);
}

.capabilities-data-import__source-title {
  margin: 0;
  font-size: 1.15rem;
  color: var(--bp-ink);
}

.capabilities-data-import__source-copy {
  margin: 0 0 var(--bp-s-3);
  line-height: 1.6;
  color: var(--bp-ink-muted);
}

/* Both source cards embed a form (the shared file-uploader, or the
   LinkedIn button_to). Let it fill the card and pin the submit control
   to the bottom edge so the two cards align. */
.capabilities-data-import__source form {
  margin-top: auto;
}

.capabilities-data-import__footer {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--bp-s-3);
  padding-top: var(--bp-s-4);
  border-top: 1px solid var(--bp-rule);
}

.capabilities-data-import__manual-prompt {
  flex: 1 1 16rem;
  margin: 0;
  color: var(--bp-ink-muted);
}

.capabilities-data-import__dismiss-form { margin: 0; }

.capabilities-data-import__unavailable {
  text-align: center;
  padding: var(--bp-s-6) var(--bp-s-5);
}

.capabilities-data-import__unavailable-title {
  margin: 0 0 var(--bp-s-3);
  color: var(--bp-ink);
}

.capabilities-data-import__unavailable-copy {
  margin: 0 auto var(--bp-s-5);
  max-width: 46ch;
  line-height: 1.6;
  color: var(--bp-ink-muted);
}

/* ============================================================
   Capabilities — Flow C surfaces (slice 1d, #837)
   Category landing + new-entry form + lifecycle-aware editor.

   Verifiable-data fields use `.bp-input` / `.bp-select` /
   `.bp-textarea` directly (the Safari select fix lives on
   `.bp-select` itself). Category rows use `.bp-card` for chrome.
   ============================================================ */

.capabilities-category {
  /* List view — fills the layout container the way the dashboard
     does, so a scanner can see Company · Role · Dates · State
     without wrapping every row. */
  padding: var(--bp-s-4);
}

.capabilities-entry-form,
.capabilities-entry-editor {
  /* Form views stay constrained — narrower forms read more
     easily and keep the eye moving down the field stack instead
     of across. The handoff scale tops out at --bp-s-8 (64px);
     760px (the spec value for "chat & reading views") sits
     between scale steps so we express it as scale * a small
     whole-number factor. */
  padding: var(--bp-s-4);
  max-width: calc(var(--bp-s-8) * 12 - var(--bp-s-2));
  margin: 0 auto;
}

.capabilities-category__header,
.capabilities-entry-form__header,
.capabilities-entry-editor__header {
  margin-bottom: var(--bp-s-5);
}

/* Title-left / action-right header row (#1274 follow-up). The entry identity
   block flexes; the "Edit details" ghost action stays top-aligned on the
   right. Wraps on narrow screens so the action drops below the identity. */
.capabilities-entry-editor__title-row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--bp-s-4);
  flex-wrap: wrap;
}

.capabilities-entry-editor__identity {
  min-width: 0;
}

/* Header action cluster (#1470) — the surface's actions kept together (the
   clear "back to your résumé" return + the Edit control) rather than scattered
   between header and footer. Wraps to its own row on a narrow title-row. */
.capabilities-entry-editor__header-actions {
  display: flex;
  align-items: center;
  gap: var(--bp-s-3);
  flex-wrap: wrap;
  flex-shrink: 0;
}

/* The co-located "Edit" control (#1470) — a single bordered group holding the
   "Edit" label + the Facts / Narrative choices, so the two edit paths read as
   one either/or selection rather than two buttons at opposite ends of the page. */
.capabilities-entry-editor__edit-choices {
  display: inline-flex;
  align-items: center;
  gap: var(--bp-s-2);
  padding: var(--bp-s-2);
  border: 1px solid var(--bp-rule);
  border-radius: var(--bp-r-md);
  background: var(--bp-surface-2);
  flex-shrink: 0;
}
.capabilities-entry-editor__edit-choices-label {
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--bp-ink-muted);
  padding-left: var(--bp-s-1);
}
/* button_to wraps its button in a <form>; keep it inline + margin-free so the
   Narrative choice sits flush beside Facts inside the group. */
.capabilities-entry-editor__edit-choice-form {
  margin: 0;
  display: inline-flex;
}

.capabilities-category__nav,
.capabilities-entry-form__nav,
.capabilities-entry-editor__nav {
  margin-top: var(--bp-s-3);
  display: flex;
  gap: var(--bp-s-2);
}

/* In the entry editor the nav leads the header (above the title block), so it
   needs space below it rather than above. */
.capabilities-entry-editor__header .capabilities-entry-editor__nav {
  margin-top: 0;
  margin-bottom: var(--bp-s-4);
}

.capabilities-category__designation-row {
  display: flex;
  align-items: center;
  gap: var(--bp-s-2);
  flex-wrap: wrap;
  margin: var(--bp-s-2) 0 var(--bp-s-3);
}

.capabilities-category__remove-form {
  display: inline;
  margin: 0;
}

.capabilities-category__intro { margin-bottom: var(--bp-s-4); }

.capabilities-category__intro-summary {
  cursor: pointer;
  font-weight: 600;
  color: var(--bp-ink);
  list-style: none;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
}

.capabilities-category__intro-summary::-webkit-details-marker {
  display: none;
}

.capabilities-category__intro-summary::before {
  content: "▸";
  display: inline-block;
  transition: transform var(--bp-dur-fast) var(--bp-easing);
  font-size: 0.85em;
  color: var(--bp-ink-muted);
}

.capabilities-category__intro[open] .capabilities-category__intro-summary::before {
  transform: rotate(90deg);
}

.capabilities-category__intro-copy {
  margin: var(--bp-s-2) 0 0;
  line-height: 1.55;
  color: var(--bp-ink-muted);
}

.capabilities-category__entries-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: var(--bp-s-3);
}

.capabilities-category__entries-title { margin: 0; }

.capabilities-category__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-2);
}

/* Each row pairs `.bp-card` (chrome) with this class for the
   tighter padding + horizontal flex layout. */
.capabilities-category__row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: var(--bp-s-3);
}

.capabilities-category__row-title {
  margin: 0 0 var(--bp-s-1);
  font-size: 1rem;
}

.capabilities-category__row-meta {
  margin: 0;
  color: var(--bp-ink-muted);
  font-size: 0.875rem;
}

/* Lifecycle badge stacked over the forward CTA (#1182 F1b). */
.capabilities-category__row-aside {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--bp-s-2);
  flex-shrink: 0;
}

.capabilities-category__row-advance {
  margin: 0;
}

.capabilities-category__empty {
  padding: var(--bp-s-3);
  color: var(--bp-ink-muted);
}

/* Entry form & editor */
.capabilities-entry-form__form,
.capabilities-entry-editor__shell {
  padding: var(--bp-s-4);
}

.capabilities-entry-form__fields {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: var(--bp-s-3);
}

/* Grouped field cluster (e.g. start/end date pair). Spans the
   full row width of the parent grid so the legend reads as a
   single labeled control, then lays the paired sub-fields out
   horizontally — one row at wide widths, stacked on narrow
   viewports. */
.capabilities-entry-form__field-group {
  grid-column: 1 / -1;
  border: 1px solid var(--bp-rule);
  border-radius: var(--bp-r-md);
  padding: var(--bp-s-2) var(--bp-s-4) var(--bp-s-4);
  margin: 0;
}

.capabilities-entry-form__field-group-legend {
  padding: 0 var(--bp-s-2);
  font-weight: 600;
  font-size: 0.875rem;
  color: var(--bp-ink-muted);
}

.capabilities-entry-form__field-group-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: var(--bp-s-3);
}

.capabilities-entry-form__field {
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-1);
}

.capabilities-entry-form__label {
  font-weight: 600;
  font-size: 0.875rem;
}

.capabilities-entry-form__month-year {
  display: grid;
  grid-template-columns: 1fr 7rem;
  gap: var(--bp-s-2);
}

/* Selects inside the month/year pair need to shrink below their
   intrinsic content width or the 1fr/7rem grid template breaks. */
.capabilities-entry-form__month-year .bp-select {
  min-width: 0;
}

@media (max-width: 480px) {
  .capabilities-entry-form__month-year {
    grid-template-columns: 1fr 1fr;
  }
}

.capabilities-entry-form__footer,
.capabilities-entry-editor__actions {
  margin-top: var(--bp-s-4);
  display: flex;
  gap: var(--bp-s-2);
  flex-wrap: wrap;
  align-items: center;
}

.capabilities-entry-editor__transition {
  display: inline;
  margin: 0;
}

.capabilities-entry-editor__status {
  display: flex;
  align-items: center;
  gap: var(--bp-s-2);
  margin-bottom: var(--bp-s-3);
  flex-wrap: wrap;
}

.capabilities-entry-editor__status-label {
  font-weight: 600;
  color: var(--bp-ink-muted);
}

.capabilities-entry-editor__status-note {
  color: var(--bp-ink-muted);
  font-size: 0.875rem;
}

.capabilities-entry-editor__shell-head {
  margin-bottom: var(--bp-s-3);
}

.capabilities-entry-editor__shell-title { margin: 0; }

.capabilities-entry-editor__shell-sub {
  margin: var(--bp-s-1) 0 0;
  color: var(--bp-ink-muted);
}

.capabilities-entry-editor__presentation {
  margin-top: var(--bp-s-4);
  padding: var(--bp-s-3);
  border: 1px dashed var(--bp-rule);
  border-radius: var(--bp-r-md);
}

.capabilities-entry-editor__presentation legend {
  padding: 0 var(--bp-s-2);
  font-weight: 600;
}

.capabilities-entry-editor__detail-row {
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-1);
  margin-bottom: var(--bp-s-3);
}

.capabilities-entry-editor__detail-destroy {
  display: inline-flex;
  align-items: center;
  gap: var(--bp-s-1);
  font-size: 0.875rem;
  color: var(--bp-ink-muted);
}

.capabilities-entry-editor__review {
  margin-top: var(--bp-s-4);
  padding: var(--bp-s-4);
}

.capabilities-entry-editor__review-meta {
  font-size: 0.875rem;
  color: var(--bp-ink-muted);
  margin: 0;
}

/* ---------- Refinement orientation (#1065) ---------- */

.capabilities-entry-editor__orientation {
  margin-top: var(--bp-s-4);
  padding: var(--bp-s-4);
}

.capabilities-entry-editor__orientation-tips {
  margin: var(--bp-s-2) 0 0;
  padding-left: var(--bp-s-4);
  color: var(--bp-ink-muted);
}

.capabilities-entry-editor__orientation-tips li {
  margin-bottom: var(--bp-s-1);
}

/* Library-level static key/value list — the design library had no
   read-only data-display pattern, so this extends it (per the Handoff
   contract) rather than one-offing inside the capabilities namespace. */
.bp-dl {
  display: grid;
  grid-template-columns: minmax(8rem, 14rem) 1fr;
  gap: var(--bp-s-1) var(--bp-s-3);
  margin: 0;
}

.bp-dl__pair {
  display: contents;
}

.bp-dl__term {
  margin: 0;
  align-self: baseline;
}

.bp-dl__value {
  margin: 0;
  color: var(--bp-ink);
}

@media (max-width: 32rem) {
  .bp-dl {
    grid-template-columns: 1fr;
    gap: 0 0;
  }

  .bp-dl__value {
    margin-bottom: var(--bp-s-2);
  }
}

/* ---------- Dynamic narrative add/remove (#1065) ---------- */

.capabilities-entry-editor__detail-group {
  margin-bottom: var(--bp-s-4);
}

.capabilities-entry-editor__detail-hint {
  margin: 0;
  font-size: 0.85rem;
  line-height: 1.5;
  color: var(--bp-ink-muted);
}

.capabilities-entry-editor__detail-add {
  margin-top: var(--bp-s-1);
}

.capabilities-entry-editor__detail-remove {
  align-self: flex-start;
}

.capabilities-entry-editor__detail-row[hidden] {
  display: none;
}

/* ---------- Holistic review (#1065 anchors it at top; #1067 payload) ---------- */

.capabilities-entry-editor__review-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--bp-s-2);
  margin-bottom: var(--bp-s-2);
}

.capabilities-entry-editor__review-summary {
  margin: 0 0 var(--bp-s-3);
}

.capabilities-entry-editor__review-section {
  margin-top: var(--bp-s-3);
}

.capabilities-entry-editor__review-section h3 {
  margin: 0 0 var(--bp-s-1);
}

.capabilities-entry-editor__review-list {
  margin: 0;
  padding-left: var(--bp-s-4);
}

/* Match the list items to the card's paragraph voice. The global `p` rule
   (typography.css) gives summary/Skills paragraphs line-height 1.75 + ink-2;
   <li>s don't inherit that, so without this they read tighter and darker —
   looking like a different font within the same writeup. */
.capabilities-entry-editor__review-list li {
  line-height: 1.75;
  color: var(--bp-ink-2);
}

.capabilities-entry-editor__review-list li + li {
  margin-top: var(--bp-s-1);
}

.capabilities-entry-editor__review-flags li + li {
  margin-top: var(--bp-s-2);
}

/* ─── bp-split — side-by-side / two-pane layout ──────────────────────────────
   The standard for any view whose job is working two columns at once
   (review | content, coach | canvas). Side-by-side is cross-column work, not
   single-column reading, so the consumer's page container uses the 1200px
   budget (Handoff §07 "Page max width") rather than the 760px reading
   measure — otherwise each column reads cramped. This primitive owns the grid
   structure + responsive collapse only; the page width sits on the consumer's
   container, and scroll behavior (sticky aside vs. bounded-height internal
   scroll) is layered on top. Default columns are equal; --5-7 / --7-5 bias one
   side. First consumer: the reviewed Capabilities entry (#1223). */
.bp-split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--bp-s-5);
  align-items: start;
}

.bp-split--5-7 {
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
}

.bp-split--7-5 {
  grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
}

/* Pin the aside in view while the other pane scrolls. Works on a normally
   scrolling page; a bounded-height workspace (e.g. the interview canvas)
   layers its own internal scroll instead. */
.bp-split__aside--sticky {
  position: sticky;
  top: var(--bp-s-4);
  max-height: calc(100vh - var(--bp-s-7));
  overflow-y: auto;
  /* Grid item: without this, long/unbroken content forces the column wider
     than its track instead of wrapping (the min-width:auto grid gotcha). */
  min-width: 0;
}

.bp-split__main {
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-4);
  min-width: 0;
}

/* Workspace variant — the second documented scroll mode of the split. Where the
   default split scrolls the whole page (and an aside can go sticky), a workspace
   is a BOUNDED-HEIGHT surface whose two panes scroll INTERNALLY, so the primary
   pane stays put instead of scrolling off the top. Used where an ancestor
   `overflow: auto` makes `position: sticky` unreliable (the interview canvas).
   The consumer caps the height on an ancestor flex column; this variant fills it
   (`flex: 1 1 auto` + `min-height: 0`) and stretches both columns to equal full
   height so each pane can own its scroll region — either the pane element itself
   (e.g. `.iv__fields`) or a scrollable child inside it (e.g. the interview's
   `.iv__thread`). Compose by putting both classes on the one element:
   `class="bp-split bp-split--workspace"`. */
.bp-split--workspace {
  align-items: stretch;
  flex: 1 1 auto;
  min-height: 0;
}

@media (max-width: 60rem) {
  .bp-split,
  .bp-split--5-7,
  .bp-split--7-5 {
    grid-template-columns: 1fr;
  }

  .bp-split__aside--sticky {
    position: static;
    max-height: none;
    overflow-y: visible;
  }
}

/* ---------- Reviewed two-column layout (#1223) ----------
   Composes .bp-split. The 760px reading cap is a single-column spec; the
   reviewed surface is a review | content comparison, so it adopts the 1200px
   side-by-side budget. Other entry-editor states keep the reading width. */
.capabilities-entry-editor--review-layout {
  max-width: var(--bp-w-page);
}

.capabilities-entry-editor__review-layout {
  margin-top: var(--bp-s-4);
  /* Equal-height columns (#1274) so the review and the narrative occupy the
     same vertical space side by side instead of a short review next to a tall
     narrative. With equal heights there's nothing to scroll past, so the
     review pane is no longer sticky here (overrides .bp-split__aside--sticky)
     and its card grows to fill the column. */
  align-items: stretch;
}

.capabilities-entry-editor__review-layout > .bp-split__aside--sticky {
  position: static;
  max-height: none;
  overflow: visible;
  display: flex;
  flex-direction: column;
}

.capabilities-entry-editor__review-layout > .bp-split__aside--sticky > * {
  flex: 1 1 auto;
}

/* ---------- Review-pane placeholder (#1223) ---------- */

.capabilities-entry-editor__review-placeholder-body {
  margin: var(--bp-s-2) 0 0;
  color: var(--bp-ink-muted);
}

/* ---------- Read-only narrative summary (#1223) ---------- */

.capabilities-entry-editor__narrative-group {
  margin-bottom: var(--bp-s-4);
}

.capabilities-entry-editor__narrative-group:last-child {
  margin-bottom: 0;
}

.capabilities-entry-editor__narrative-group h3 {
  margin: 0 0 var(--bp-s-2);
}

.capabilities-entry-editor__narrative-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-3);
}

.capabilities-entry-editor__narrative-body {
  margin: 0;
  color: var(--bp-ink);
  /* EntryDetail bodies are free text and may contain the line breaks the
     user typed; preserve them so the read-only view is faithful to what was
     written (and still wraps long lines). */
  white-space: pre-wrap;
}

.capabilities-entry-editor__narrative-empty {
  margin: 0;
  color: var(--bp-ink-muted);
}

/* Inline element-level flag — pins a holistic-review flag to the specific
   captured element it references (#1223 AC3). */
.capabilities-entry-editor__narrative-flags {
  list-style: none;
  margin: var(--bp-s-2) 0 0;
  padding: var(--bp-s-2) var(--bp-s-3);
  border-left: 2px solid var(--bp-rule);
  border-radius: var(--bp-r-sm);
  background: var(--bp-surface-2);
}

.capabilities-entry-editor__narrative-flags li + li {
  margin-top: var(--bp-s-2);
}

.capabilities-entry-editor__narrative-flags strong {
  display: block;
  font-size: 0.85rem;
}

.capabilities-entry-editor__destroy {
  margin-top: var(--bp-s-5);
}

.capabilities-entry-editor[data-standalone] .capabilities-entry-editor__destroy {
  /* Deep-link contexts may not want destruction; hide for now. */
  display: none;
}

/* ---------- Capture-mode toggle (slice 1e) ---------- */

/* `.capabilities-entry-form__shell-head` mirrors the editor's
   `__shell-head` so new_entry and show_entry surface the toggle in
   visually identical positions, even though the surrounding card
   structures differ. */
.capabilities-entry-form__shell-head {
  margin-bottom: var(--bp-s-3);
}

.capabilities-capture-mode {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--bp-s-2);
  margin-top: var(--bp-s-3);
  padding-top: var(--bp-s-3);
  border-top: 1px solid var(--bp-rule-soft);
}

.capabilities-capture-mode__label {
  display: inline-flex;
  align-items: baseline;
  gap: var(--bp-s-2);
  margin: 0;
  font-size: 0.875rem;
}

.capabilities-capture-mode__label-text {
  font-family: var(--bp-mono-family);
  font-size: 0.75rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--bp-ink-muted);
}

.capabilities-capture-mode__current {
  font-weight: 600;
  color: var(--bp-ink);
}

.capabilities-capture-mode__switch-form {
  margin: 0;
}

.capabilities-capture-mode__switch {
  background: transparent;
  border: none;
  padding: 0;
  font: inherit;
  font-size: 0.875rem;
  color: var(--bp-accent);
  cursor: pointer;
}

.capabilities-capture-mode__switch:hover {
  color: var(--bp-ink);
  text-decoration: underline;
}

.capabilities-capture-mode__fallback-notice {
  margin: var(--bp-s-3) 0 0;
  padding: var(--bp-s-2) var(--bp-s-3);
  background: var(--bp-highlight-soft);
  color: var(--bp-ink-2);
  border-left: 3px solid var(--bp-highlight);
  border-radius: var(--bp-r-sm);
  font-size: 0.875rem;
}

/* Stage assessment (#1912) — what we noticed, shown when the user declares
   themselves done. Replaces the Flow E reconciliation surface; the dashboard
   conflict counter that used to sit beside it is gone entirely (D5), so
   nothing here has a count treatment. */
.capabilities-assessment {
  max-width: var(--bp-w-stage);
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-5);
}

.capabilities-assessment__header {
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-2);
}

.capabilities-assessment__clear {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--bp-s-3);
}

.capabilities-assessment__clear-title {
  margin: 0;
  font-size: 1.15rem;
  color: var(--bp-ink);
}

.capabilities-assessment__clear-copy {
  margin: 0;
  line-height: 1.6;
  color: var(--bp-ink-muted);
}

.capabilities-assessment__list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-3);
}

.capabilities-assessment__finding {
  padding: var(--bp-s-5);
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-3);
}

.capabilities-assessment__finding-title {
  margin: 0;
  font-size: 1.15rem;
  color: var(--bp-ink);
}

.capabilities-assessment__observation {
  margin: 0;
  line-height: 1.6;
  color: var(--bp-ink-2);
}

/* The data the finding read, one line per row it looked at. Monospaced and
   quiet on purpose: it is a citation, not prose — the user is meant to scan
   it against what is on their own screen. */
.capabilities-assessment__evidence {
  list-style: none;
  padding: var(--bp-s-3) var(--bp-s-4);
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-2);
  border-left: 2px solid var(--bp-rule);
  background: var(--bp-surface-2);
  border-radius: var(--bp-r-sm);
  font-family: var(--bp-mono-family);
  font-size: 0.8125rem;
  line-height: 1.5;
  color: var(--bp-ink-muted);
}

.capabilities-assessment__looked-for {
  margin: 0;
  font-size: 0.875rem;
  line-height: 1.6;
  color: var(--bp-ink-subtle);
}

/* The resolutions block: the lead sentence naming the ways forward, then the
   controls themselves. The lead sits close to the first control (s-3) while
   the two paths stay far apart (s-6 below), so it reads as introducing both
   rather than captioning the first. */
.capabilities-assessment__resolutions {
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-3);
  /* Wider than the s-6 that separates the two paths below, so the block reads
     as one thing set off from the finding rather than as two loose controls. */
  margin-top: var(--bp-s-5);
}

.capabilities-assessment__resolutions-lead {
  margin: 0;
  font-size: 0.875rem;
  line-height: 1.6;
  color: var(--bp-ink-muted);
}

/* The two resolutions, stacked and equal weight. Side by side, the go-add-data
   button landed level with the revise select's LABEL rather than the select
   itself — reading as a caption for it instead of as the other way forward.
   The two paths have different shapes (one button vs. a labelled field plus a
   button), so there is no honest cross-column baseline to align them on.

   The gap between the two paths has to stay wider than the gaps inside either
   one, or the revise field's label reads as a caption on the button above it —
   the same misgrouping, just vertical. */
.capabilities-assessment__actions {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--bp-s-6);
}

.capabilities-assessment__revise {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--bp-s-2);
  max-width: 32rem;
}

/* "Update in place" (#1913) — the preferred resolution, rendered first. It
   carries more weight than the two paths below it: a tinted, inset block
   rather than a bare stack, because it is the one path that finishes the job
   on this screen. Its fields are stacked at s-4 — wider than the s-2 holding
   each label to its own field, so a label never reads as a caption for the
   field above it (the same misgrouping the revise stack guards against). */
.capabilities-assessment__repair {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--bp-s-4);
  width: 100%;
  max-width: 32rem;
  padding: var(--bp-s-4);
  border: 1px solid var(--bp-rule);
  border-radius: var(--bp-r-sm);
  background: var(--bp-surface);
}

.capabilities-assessment__repair .bp-field {
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-2);
  width: 100%;
}

.capabilities-assessment__repair-help {
  margin: 0;
  font-size: 0.875rem;
  line-height: 1.6;
  color: var(--bp-ink-muted);
}

.capabilities-assessment__repair-label {
  margin: 0;
  font-size: 0.875rem;
  color: var(--bp-ink-muted);
}

.capabilities-assessment__revise-label {
  margin: 0;
  font-size: 0.875rem;
  color: var(--bp-ink-muted);
}

/* "This updates more than one earlier answer." Warning-toned because the
   consequence is wider than the label implies — the one thing this
   resolution used to leave unsaid. */
.capabilities-assessment__revise-also {
  margin: 0;
  padding: var(--bp-s-2) var(--bp-s-3);
  border-radius: var(--bp-r-sm);
  background: var(--bp-tint-warning);
  color: var(--bp-tint-ink-warning);
  font-size: 0.875rem;
  line-height: 1.5;
}

/* Why a category cannot be marked Not Applicable (D4). Rendered only when
   the user was just refused that move, never as a standing card. */
.capabilities-assessment__na-block {
  padding: var(--bp-s-5);
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-3);
  border-left: 3px solid var(--bp-warning);
}

.capabilities-assessment__na-block-title {
  margin: 0;
  font-size: 1.15rem;
  color: var(--bp-ink);
}

.capabilities-assessment__na-block-copy {
  margin: 0;
  line-height: 1.6;
  color: var(--bp-ink-2);
}

/* Surprising items (#1914) — the coaching flags raised per entry during
   refinement, collected. ONE card holding a list, rather than a card per item
   the way shortfalls render: the point of this slice is that they are seen
   together, and giving each the full weight of a shortfall card would
   overstate a set that is meant to be sparse. */
.capabilities-assessment__surprises {
  padding: var(--bp-s-5);
  display: flex;
  flex-direction: column;
  /* Tight, because the heading and the lead under it are one thought. The
     list below buys its own space (see its margin-top) — without that, the
     lead sat the same distance from the first item as from its own heading
     and the three read as one wall. */
  gap: var(--bp-s-2);
}

.capabilities-assessment__surprises-title {
  margin: 0;
  font-size: 1.15rem;
  color: var(--bp-ink);
}

.capabilities-assessment__surprises-lead {
  margin: 0;
  line-height: 1.6;
  color: var(--bp-ink-2);
}

.capabilities-assessment__surprise-list {
  list-style: none;
  padding: 0;
  margin: var(--bp-s-4) 0 0;
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-5);
}

/* Each item is separated by a rule rather than by being its own card — the
   items belong to one observation, not to several. The gap inside an item
   stays tighter than the gap between items so the entry name, the quoted
   element, and the question read as one block. */
.capabilities-assessment__surprise {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--bp-s-2);
  padding-top: var(--bp-s-5);
  border-top: 1px solid var(--bp-rule-soft);
}

.capabilities-assessment__surprise:first-child {
  padding-top: 0;
  border-top: none;
}

.capabilities-assessment__surprise-entry {
  margin: 0;
  font-weight: 600;
  color: var(--bp-ink);
}

.capabilities-assessment__surprise-category {
  font-weight: 400;
  color: var(--bp-ink-muted);
}

.capabilities-assessment__surprise-category::before {
  content: " · ";
}

/* The element the flag points at, in the user's own words. Quoted and set
   apart so the question below it is unmistakably about THIS line and not
   about the entry in general. */
.capabilities-assessment__surprise-element {
  margin: 0;
  padding-left: var(--bp-s-3);
  border-left: 2px solid var(--bp-rule);
  font-style: italic;
  line-height: 1.6;
  color: var(--bp-ink-muted);
}

.capabilities-assessment__surprise-question {
  margin: 0;
  line-height: 1.6;
  color: var(--bp-ink-2);
}

/* The link sits further from the question than the question does from the
   element above it, so it reads as the way forward rather than as part of
   the sentence. */
.capabilities-assessment__surprise .bp-btn {
  margin-top: var(--bp-s-2);
}

/* Role fit (#1915). The frame itself needs a box: a bare `turbo-frame` is
   `display: inline`, so the skeleton inside it collapses to nothing and the
   card that replaces it has no separation from the section above. */
.capabilities-assessment__role-fit-frame {
  display: block;
}

/* The in-flight state. Padded to the same inset as the card that replaces it,
   so the section does not jump left when the read lands. */
.capabilities-assessment__role-fit-working {
  padding: var(--bp-s-5);
  max-width: 68ch;
}

.capabilities-assessment__role-fit {
  padding: var(--bp-s-5);
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-3);
}

.capabilities-assessment__role-fit-title {
  margin: 0;
  font-size: 1.15rem;
  color: var(--bp-ink);
}

/* The verdict sentence carries the weight of the card — it is the answer the
   client came for, and everything under it is grounding. */
.capabilities-assessment__role-fit-verdict,
.capabilities-assessment__role-fit-consequence {
  margin: 0;
  font-size: 1.05rem;
  line-height: 1.6;
  color: var(--bp-ink);
}

/* The lead under the heading: why this section is here and what it read. */
.capabilities-assessment__role-fit-lead,
.capabilities-assessment__role-fit-basis,
.capabilities-assessment__role-fit-next,
.capabilities-assessment__role-fit-expectation,
.capabilities-assessment__role-fit-absence,
.capabilities-assessment__role-fit-role-why {
  margin: 0;
  line-height: 1.6;
  color: var(--bp-ink-2);
}

/* The expectation is the claim; the absence under it is what makes the claim
   traceable to their own record, so it is set apart the same way a surprise
   sets apart the element it points at. */
.capabilities-assessment__role-fit-absence {
  padding-left: var(--bp-s-3);
  border-left: 2px solid var(--bp-rule);
  color: var(--bp-ink-muted);
}

.capabilities-assessment__role-fit-gaps,
.capabilities-assessment__role-fit-roles {
  list-style: none;
  padding: 0;
  margin: var(--bp-s-2) 0 0;
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-5);
}

.capabilities-assessment__role-fit-gap,
.capabilities-assessment__role-fit-role {
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-2);
}

.capabilities-assessment__role-fit-role-title {
  margin: 0;
  font-weight: 600;
  color: var(--bp-ink);
}

.capabilities-assessment__role-fit-add-data {
  margin: var(--bp-s-2) 0 0;
}

/* The adopt control. Separated by a rule because it is a different move from
   reading the roles above it — the client is being asked to commit, not to
   keep reading. */
.capabilities-assessment__adopt {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--bp-s-3);
  margin-top: var(--bp-s-3);
  padding-top: var(--bp-s-5);
  border-top: 1px solid var(--bp-rule-soft);
}

.capabilities-assessment__adopt-lead {
  margin: 0;
  line-height: 1.6;
  color: var(--bp-ink-2);
}

.capabilities-assessment__adopt-choice {
  border: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-2);
}

.capabilities-assessment__adopt-option {
  display: flex;
  align-items: center;
  gap: var(--bp-s-2);
}

.capabilities-assessment__adopt-label {
  display: block;
  margin-bottom: var(--bp-s-2);
  color: var(--bp-ink);
}

/* The one always-present continue control: muted while the stage is not yet
   finishable, primary once it is. Never hidden, never a button that bounces. */
.capabilities-assessment__continue {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--bp-s-2);
  padding-top: var(--bp-s-4);
  border-top: 1px solid var(--bp-rule-soft);
}

.capabilities-assessment__continue-note {
  margin: 0;
  font-size: 0.875rem;
  color: var(--bp-ink-muted);
}

/* Stage Closing — Role Readiness + extension shells (slice 1h, #841).
   Read-only reflection plus navigation; the three extension shells render
   placeholder copy until their AI population lands in Phase 2 (2g). */
.capabilities-closing {
  max-width: var(--bp-w-stage);
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-5);
}

.capabilities-closing__kicker {
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--bp-ink-muted);
}

.capabilities-closing__subhead {
  margin: 0;
  font-size: 1.05rem;
  color: var(--bp-ink);
}

.capabilities-closing__readiness {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--bp-s-3);
}

.capabilities-closing__readiness-statement,
.capabilities-closing__readiness-pending {
  margin: 0;
  line-height: 1.6;
  color: var(--bp-ink-muted);
}

.capabilities-closing__actions-block {
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-2);
}

.capabilities-closing__action-list {
  margin: 0;
  padding-left: var(--bp-s-4);
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-1);
  line-height: 1.6;
  color: var(--bp-ink-muted);
}

.capabilities-closing__extensions {
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-3);
}

.capabilities-closing__extension {
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-2);
}

.capabilities-closing__extension-title {
  margin: 0;
  font-size: 1rem;
  color: var(--bp-ink);
}

.capabilities-closing__extension-copy {
  margin: 0;
  line-height: 1.6;
  color: var(--bp-ink-muted);
}

.capabilities-closing__extension-role {
  margin: 0;
  font-size: 1.05rem;
  color: var(--bp-ink);
}

.capabilities-closing__extension-footnote {
  margin: 0;
  color: var(--bp-ink-muted);
  font-style: italic;
}

.capabilities-closing__peer-roles {
  margin: 0;
  padding-left: var(--bp-s-4);
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-2);
  line-height: 1.6;
  color: var(--bp-ink-muted);
}

/* Centered — see .stage-closing__footer. */
.capabilities-closing__nav {
  display: flex;
  flex-wrap: wrap;
  gap: var(--bp-s-3);
  justify-content: center;
}

/* ===================================================================
   Stage dashboard — shared shell for stage exercise-list landing pages
   (Stage 3 / Target Job Blueprint, slice 6). Mirrors the
   .capabilities-dashboard* spacing using the --bp-* tokens.
   =================================================================== */
.stage-dashboard {
  max-width: var(--bp-w-stage);
  margin: 0 auto;
  padding: var(--bp-s-6) var(--bp-s-5) var(--bp-s-7);
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-6);
}

.stage-dashboard__header {
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-2);
}

.stage-dashboard__intro {
  margin: 0;
  max-width: 60ch;
}

/* "What to do next" CTA (slice D, #1117) — a single directive card above the
   exercise grid so the user always has one obvious next action. Card chrome is
   .bp-card; this owns only the row layout (copy left, action right, stacking
   on narrow viewports). */
.stage-dashboard__cta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--bp-s-4);
  flex-wrap: wrap;
}

.stage-dashboard__cta-body {
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-2);
}

.stage-dashboard__cta-title {
  margin: 0;
}

.stage-dashboard__cta-blurb {
  margin: 0;
  max-width: 60ch;
  color: var(--bp-ink-muted);
}

.stage-dashboard__exercises {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--bp-s-4);
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
}

.stage-dashboard__exercise {
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-3);
}

.stage-dashboard__exercise-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--bp-s-2);
}

.stage-dashboard__exercise-head h2 {
  margin: 0;
}

.stage-dashboard__exercise-blurb {
  margin: 0;
  flex: 1;
}

.stage-dashboard__exercise-foot {
  margin-top: auto;
  display: flex;
  align-items: center;
  gap: var(--bp-s-3);
}

/* Soft "finish the others first" recommendation on the IVP card (D6). Advisory
   tone — muted, not an alert — because the card stays clickable. */
.stage-dashboard__exercise-note {
  margin: 0;
  color: var(--bp-ink-muted);
  font-style: italic;
}

.stage-dashboard__footer {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: var(--bp-s-3);
  padding-top: var(--bp-s-3);
}

/* Names the missing step while the "Mark stage complete" button is disabled
   (D6 stage-floor gate). */
.stage-dashboard__complete-hint {
  margin: 0;
  color: var(--bp-ink-muted);
}

/* ===================================================================
   Stage record — the durable, read-only view of a FINISHED stage
   (epic #1948). Distinct from .stage-closing, which is the one-time
   crossing: no forward action, exits only. #1949 wired the Capabilities
   route; #1950 made this the SHARED shell — the five remaining stages
   compose into these same classes in iteration 2, so nothing below may
   name a stage. Same stage tier and token spacing as every other stage
   surface (Handoff §07) — no literals.
   =================================================================== */
/* Vertical padding only. There is no global `box-sizing: border-box` reset, so
   horizontal padding here would sit OUTSIDE the max-width and the shell would
   measure the tier + 48px — and, worse, render the shared report partial at a
   different measure than `.capabilities-closing` does from the identical token.
   The page gutter is `.container`'s job, which is why the closing has none. */
.stage-record {
  max-width: var(--bp-w-stage);
  margin: 0 auto;
  padding-block: var(--bp-s-6) var(--bp-s-7);
  display: flex;
  flex-direction: column;
  /* Handoff §04: --bp-s-7 between major sections. The record's slots ARE major
     sections — report, artifacts, change, exits — not rows of one block. */
  gap: var(--bp-s-7);
}

/* Badge above the name, both left-aligned on the column. The state is what
   makes this a record rather than the stage, so it reads first. */
.stage-record__header {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--bp-s-2);
}

.stage-record__title {
  margin: 0;
}

.stage-record__report {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--bp-s-3);
}

.stage-record__artifacts {
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-4);
}

/* Section label inside a slot ("What you documented"). Sits tighter to its
   list than the slot gap, so label and content read as one block. */
.stage-record__section-title {
  margin: 0;
}

.stage-record__categories {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-4);
}

.stage-record__category-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--bp-s-3);
  flex-wrap: wrap;
}

.stage-record__category-name {
  margin: 0;
  font-family: var(--bp-display-family);
  font-weight: 500;
  font-size: 1.15rem;
  color: var(--bp-ink);
}

.stage-record__entries {
  list-style: none;
  margin: var(--bp-s-3) 0 0;
  padding: 0;
  border-top: 1px solid var(--bp-rule-soft);
}

/* Two columns, not the dashboard's three: a record has no action column to
   reserve, so the state badge sits directly against the entry it describes. */
.stage-record__entry {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--bp-s-4);
  padding: var(--bp-s-3) 0;
  border-bottom: 1px solid var(--bp-rule-soft);
}

.stage-record__entry:last-child { border-bottom: 0; }

.stage-record__entry-main {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 1px;
}

/* Text, not a link — see _record_artifacts.html.erb. Weight, not colour, marks
   it as the entry's name (Handoff §01.4).

   These WRAP, where the dashboard's equivalents truncate to an ellipsis. The
   difference is what the surface is for: a dashboard row is a task, and a
   clipped label still points at the work. A record row IS the thing recorded —
   "Northwestern Mutual Financial Netw…" is the record failing at its one job,
   and it fails first on a phone, where records get read. */
.stage-record__entry-title {
  font-weight: 600;
  font-size: 0.9rem;
  color: var(--bp-ink);
  overflow-wrap: anywhere;
}

.stage-record__entry-sub {
  font-size: 0.78rem;
  color: var(--bp-ink-muted);
  overflow-wrap: anywhere;
}

/* A quiet aside naming what a slot did NOT produce. */
.stage-record__note {
  margin: 0;
  font-size: 0.85rem;
  color: var(--bp-ink-muted);
}

/* Collapsed fold for a secondary part of the record. Mirrors the dashboard's
   N/A fold so the two surfaces disclose the same way. */
.stage-record__fold {
  border-top: 1px dashed var(--bp-rule);
  padding-top: var(--bp-s-3);
}

.stage-record__fold-summary {
  display: flex;
  align-items: center;
  gap: var(--bp-s-2);
  cursor: pointer;
  padding: var(--bp-s-1) var(--bp-s-2);
  margin-inline: calc(-1 * var(--bp-s-2));
  border-radius: var(--bp-r-md);
  font-size: 0.75rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--bp-ink-muted);
  user-select: none;
  /* Hide both default disclosure markers (spec list-item and WebKit's pseudo);
     the chevron below is drawn instead, for consistency across engines. */
  list-style: none;
}

.stage-record__fold-summary::-webkit-details-marker { display: none; }

.stage-record__fold-summary::before {
  content: "";
  display: inline-block;
  width: 0.5rem;
  height: 0.5rem;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(-45deg) translate(-1px, -1px);
  transition: transform var(--bp-dur-fast) var(--bp-easing);
}

.stage-record__fold[open] .stage-record__fold-summary::before {
  transform: rotate(45deg) translate(-1px, -1px);
}

.stage-record__fold-summary:hover {
  background: var(--bp-tint-info);
  color: var(--bp-ink);
}

.stage-record__fold-summary:focus-visible {
  outline: 2px solid var(--bp-accent);
  outline-offset: 2px;
}

.stage-record__fold-count { font-variant-numeric: tabular-nums; }

.stage-record__fold-list {
  list-style: none;
  margin: var(--bp-s-2) 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-2);
}

.stage-record__fold-item {
  padding: var(--bp-s-2) 0;
  color: var(--bp-ink-2);
}

/* The change affordance (#1951) — "Need to make a change?".

   A collapsed disclosure with a BUTTON-styled summary: changing a finished
   stage is a secondary act, so it does not get a standing panel, and it is an
   action, so it does not get a bare text link that would read as one more line
   of the ledger above it. Same pattern as `.resume-upload--offer`; the two are
   the system's one shape for a secondary round-trip control.

   Native <details>, so the toggle is keyboard-reachable with no JS. */
.stage-record__change-toggle {
  display: inline-flex;
  align-items: center;
  gap: var(--bp-s-2);
  width: fit-content;
  cursor: pointer;
  /* Hide both default disclosure markers; the chevron below is drawn instead. */
  list-style: none;
}

.stage-record__change-toggle::-webkit-details-marker { display: none; }

.stage-record__change-chevron {
  font-size: 1rem;
  line-height: 1;
  transition: transform var(--bp-dur-fast) var(--bp-easing);
}

.stage-record__change-fold[open] .stage-record__change-chevron {
  transform: rotate(90deg);
}

/* Indented behind a hairline so the expanded list reads as the disclosure's
   body rather than as more page. Without it the entry points sit flush on the
   column and, one screen below a ledger of cards, look like another section of
   the record — which is the opposite of what a collapsed affordance is for. */
.stage-record__change-body {
  margin-top: var(--bp-s-4);
  padding-left: var(--bp-s-4);
  border-left: 1px solid var(--bp-rule-soft);
}

.stage-record__change-lede {
  margin: 0;
  color: var(--bp-ink-2);
  font-size: 0.9rem;
}

.stage-record__change-list {
  list-style: none;
  margin: var(--bp-s-4) 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-4);
}

/* Each entry point: the action, then the destination it opens. The name is what
   the user is doing; the note is where it takes them, which is the whole
   contract of this slot — no door here is unlabelled. */
.stage-record__change-link,
.stage-record__change-label {
  font-weight: 600;
  font-size: 0.95rem;
}

.stage-record__change-label { color: var(--bp-ink); }

.stage-record__change-note {
  margin: var(--bp-s-1) 0 0;
  font-size: 0.85rem;
  color: var(--bp-ink-muted);
}

/* The one row with specific destinations: a pill per category the record lists,
   straight to the page where its entries can be reopened. Outlined, never
   filled — the record spends no accent. */
.stage-record__change-targets {
  list-style: none;
  margin: var(--bp-s-3) 0 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--bp-s-2);
}

.stage-record__change-target {
  display: inline-flex;
  align-items: baseline;
  gap: var(--bp-s-2);
  padding: var(--bp-s-2) var(--bp-s-3);
  border: 1px solid var(--bp-rule);
  border-radius: var(--bp-r-pill);
  font-size: 0.85rem;
}

.stage-record__change-target:hover { border-color: var(--bp-accent); }

.stage-record__change-target-count {
  color: var(--bp-ink-muted);
  font-size: 0.78rem;
  font-variant-numeric: tabular-nums;
}

/* Left-aligned on the column, like the header — the record's content is a
   left-aligned ledger, so a centred button row would read as a stray. */
.stage-record__nav {
  display: flex;
  gap: var(--bp-s-3);
  flex-wrap: wrap;
}

/* Below the phone breakpoint the two-column entry grid crushes the title.
   Stack, and let the state badge sit on its own line under it — hugging its
   text, not stretched across the column: a full-bleed pill reads as a bar. */
@media (max-width: 720px) {
  .stage-record__entry {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--bp-s-2);
  }

  .stage-record__entry > .bp-badge { justify-self: start; }
  .stage-record__category-head > .bp-badge { align-self: flex-start; }

  /* Handoff §01.9: hit targets >= 44px on a phone. Every control in the change
     affordance is under that by default — the `--sm` summary is 30px and a text
     link is its line-height — and this is the one slot on the record whose whole
     job is being tapped. */
  .stage-record__change-toggle,
  .stage-record__change-link,
  .stage-record__change-target {
    align-items: center;
    min-height: 2.75rem;
  }

  .stage-record__change-link {
    display: inline-flex;
  }
}

/* ===================================================================
   Stage closing — placeholder wrap-up shell (slice 6 stub)
   =================================================================== */
/* The stage tier, from the token — never a literal (Handoff §07). This carried a
   hard 680px until S2 (#1741), which is what rendered the readiness report at a
   different width here than the mockup and than every other surface built to the
   same tier. Prose inside the closing keeps its own reading measure below; that
   is a per-component concern and not a page-width argument. */
.stage-closing {
  max-width: var(--bp-w-stage);
  margin: 0 auto;
  padding: var(--bp-s-6) var(--bp-s-5) var(--bp-s-7);
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-4);
}

.stage-closing__body {
  margin: 0;
  line-height: 1.7;
}

/* Centered, matching the mockup — the forward action sits under a centered hero
   and a centered rail card, so a left-aligned button row reads as a stray. */
.stage-closing__footer {
  display: flex;
  gap: var(--bp-s-3);
  flex-wrap: wrap;
  justify-content: center;
}

/* Stage-3 (Target Job Blueprint) full closing — iteration 6, slice 3 (#1403).
   Mirrors the .capabilities-closing__* recognition/readiness/actions treatment
   using the shared --bp-* tokens so the two stage closings read as one family. */
.stage-closing__kicker {
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--bp-ink-muted);
}

.stage-closing__subhead {
  margin: 0;
  font-size: 1.05rem;
  color: var(--bp-ink);
}

.stage-closing__readiness {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--bp-s-3);
}

.stage-closing__readiness-statement,
.stage-closing__readiness-pending,
.stage-closing__readiness-note,
.stage-closing__commentary-pending {
  margin: 0;
  line-height: 1.6;
  color: var(--bp-ink-muted);
}

/* The readiness rail sits above the note inside the readiness card; give it the
   full card width rather than the flex-start default the card applies. */
.stage-closing__readiness .jsr-rail {
  width: 100%;
}

.stage-closing__commentary {
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-3);
  width: 100%;
  padding-top: var(--bp-s-3);
  border-top: 1px solid var(--bp-rule-soft);
}

.stage-closing__actions-block {
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-2);
}

.stage-closing__action-list {
  margin: 0;
  padding-left: var(--bp-s-4);
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-2);
  line-height: 1.6;
  color: var(--bp-ink-muted);
}

/* Stage-4 (Communication Plan) closing additions — iteration 1, slice 4
   (#1392). The commentary "thin source material" callout carries full ink
   weight (it is a real finding, not the muted "still preparing" fallback), and
   the elevator-pitch → Stage 6 handoff card mirrors the readiness card's
   kicker + body layout so the two read as one family. */
.stage-closing__commentary-thin {
  margin: 0;
  line-height: 1.6;
  color: var(--bp-ink);
}

.stage-closing__handoff {
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-2);
}

.stage-closing__handoff-body {
  margin: 0;
  line-height: 1.6;
  color: var(--bp-ink);
}

/* "Go Deeper" — opt-in depth at the Stage-6 send-off (Design §4, #1648). A
   secondary, MUTED disclosure: collapsed by default with a button-styled summary
   (clearly an action, not a bare text link), expanding to the two tiers. The
   completion state above already reads as done, so this stays quiet — it never
   competes with the primary "See your journey" CTA in the footer. Mirrors the
   résumé-upload offer disclosure mechanics (list-marker off, chevron rotates on
   [open]). */
.interview-deeper {
  padding: var(--bp-s-3);
}
.interview-deeper > summary.interview-deeper__toggle {
  list-style: none;
  display: inline-flex;
  align-items: center;
  gap: var(--bp-s-2);
  width: fit-content;
  cursor: pointer;
}
.interview-deeper > summary.interview-deeper__toggle::-webkit-details-marker {
  display: none;
}
.interview-deeper__meta {
  font-weight: 400;
  color: var(--bp-ink-subtle);
}
.interview-deeper__chevron {
  font-size: 16px;
  line-height: 1;
  transition: transform var(--bp-dur-fast) var(--bp-easing);
}
.interview-deeper[open] > summary .interview-deeper__chevron {
  transform: rotate(90deg);
}
.interview-deeper__body {
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-4);
  margin-top: var(--bp-s-4);
}
.interview-deeper__tier {
  border-top: 1px dashed var(--bp-rule);
  padding-top: var(--bp-s-4);
}
.interview-deeper__tier-title {
  margin: var(--bp-s-1) 0 var(--bp-s-2);
  font-size: var(--bp-fs-base);
}
.interview-deeper__tier-body {
  margin: 0 0 var(--bp-s-3);
  line-height: 1.6;
  color: var(--bp-ink-muted);
}
.interview-deeper__defer {
  margin: 0;
  font-style: italic;
  color: var(--bp-ink-muted);
}

/* ===================================================================
   Exercise chat — Stage 3 exercise conversation surface (slice 6).
   The transcript + composer reuse the canonical .chat-* primitives
   (ai_chat.css); these rules add the surrounding page chrome.
   =================================================================== */
.exercise-chat {
  display: flex;
  flex-direction: column;
  min-height: calc(100vh - 220px);
  max-width: var(--bp-w-read);
  margin: 0 auto;
  padding: var(--bp-s-5) var(--bp-s-5) 0;
}

/* `.exercise-chat` owns the centered column + horizontal padding so the
   stage header and chat content share one inset. Neutralize the layout
   the shared `.chat-main` applies (ai_chat.css) when nested here, or the
   transcript/composer would be double-inset and gain extra top padding. */
.exercise-chat .chat-main {
  max-width: none;
  margin-inline: 0;
  padding: 0;
}

.exercise-chat__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--bp-s-3);
  padding-bottom: var(--bp-s-3);
}

.exercise-chat__title {
  margin: 0;
}

.exercise-chat__back {
  font-family: var(--bp-mono-family);
  font-size: 13px;
  letter-spacing: 0.02em;
}

/* Per-exercise "why you're doing this" reinforcement line (slice D, #1117).
   A quiet one-liner between the header and the transcript — muted ink, sharing
   the header's bottom inset so it reads as a caption on the exercise. */
.exercise-chat__reinforcement {
  margin: 0 0 var(--bp-s-3);
  color: var(--bp-ink-muted);
}

/* User-initiated save escape hatch beneath the composer (#1117 follow-up).
   Hidden via the `hidden` attribute until a draft exists; spacing only —
   the control itself is a .bp-btn. */
.exercise-chat__save-gate {
  margin-top: var(--bp-s-2);
}

/* ---------- Flow D — resume parse status (slice 2j, #884) ----------
   In-flow status surface the resume upload redirects to. Layout only;
   card chrome is .bp-card, the progress bar is .bp-progress, and the
   actions reuse .bp-btn — see the Component Library. */
.capabilities-data-import-status {
  max-width: 44rem;
  margin: 0 auto;
  padding: var(--bp-s-7) var(--bp-s-4);
}
.capabilities-data-import-status__header {
  margin-bottom: var(--bp-s-5);
}
.capabilities-data-import-status__header h1 {
  margin: var(--bp-s-2) 0 0;
}
.capabilities-data-import-status__panel {
  padding: var(--bp-s-6);
}
.capabilities-data-import-status__title {
  margin: 0 0 var(--bp-s-3);
}
.capabilities-data-import-status__copy {
  color: var(--bp-ink-muted);
  margin: 0 0 var(--bp-s-5);
}
.capabilities-data-import-status__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--bp-s-3);
}

/* ============================================================
   Capabilities — Narrative interview side-by-side canvas
   (epic #1230, slice C, #1235). The primary refinement surface.
   Visual contract: docs/Design/mockups/capabilities-narrative-interview.html.
   The interview canvas asks for more horizontal room than the rest of the
   stage (design §2) — a wider container, reconciled here as a Direction-A
   width rather than a one-off.
   ============================================================ */
.capabilities-interview,
.ivp-interview {
  /* A bounded-height workspace: the surface fills the viewport below the page
     chrome (app bar ~56px + main padding) and only the two panes scroll
     INTERNALLY. Sticky was unreliable here because the ancestor `main` is
     `overflow: auto`, which broke pinning and let the page scroll the primary
     field off the top. Capping the height + internal pane scroll keeps the
     description fixed in place while the user works. */
  display: flex;
  flex-direction: column;
  max-height: calc(100dvh - 120px);
  /* Side-by-side budget: the page tier, not the reading tier — two panes need
     the full width. Previously a literal 1200px (itself reconciled from 1180). */
  max-width: var(--bp-w-page);
  margin: 0 auto var(--bp-s-4);
  padding: var(--bp-s-5);
}
.capabilities-interview__nav,
.ivp-interview__nav {
  display: flex;
  gap: var(--bp-s-2);
  margin-bottom: var(--bp-s-4);
}

/* where you are */
.iv__head {
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-2);
  margin-bottom: var(--bp-s-5);
}
.iv__entry-title {
  font-family: var(--bp-display-family);
  font-weight: 500;
  font-size: 28px;
  margin: 0;
  line-height: 1.1;
}
.iv__entry-sub {
  color: var(--bp-ink-muted);
  margin: 0;
  font-size: 14px;
}

/* two persistent panes: coach LEFT (primary), fields RIGHT (artifact). Composes
   the .bp-split workspace variant (#1272) — grid structure, gap, equal-height
   stretch, bounded-height fill, and the 60rem responsive collapse all come from
   `.bp-split .bp-split--workspace` (applied in the markup). The only
   interview-specific bit is the column ratio: a fixed-min coach rail rather than
   a proportional --5-7/--7-5 bias, so the conversation doesn't grow unbounded. */
.iv__canvas {
  grid-template-columns: minmax(360px, 440px) 1fr;
}

/* ---------- LEFT: the coaching conversation ---------- */
.iv__coach {
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-4);
  min-height: 0; /* let the inner thread scroll instead of growing the pane */
}
/* The coach header stacks: the section label on top, then a row holding the Coach
   badge and any per-exercise controls (the lite/full swap). Stacking keeps the
   label on its own line so it never has to share width with — and wrap around —
   the controls. Shared by every interview canvas (IVP, common titles, org
   placement, employer value, Capabilities). */
.iv__coach-head {
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-2);
}
.iv__coach-kicker {
  font-family: var(--bp-mono-family);
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--bp-ink-muted);
}
.iv__coach-head-row {
  display: flex;
  align-items: center;
  gap: var(--bp-s-2);
}
/* In-canvas full↔lite swap affordance (#1378) — pushed to the right of the head
   row; button_to wraps each control in its own <form>, so zero its default block
   margin to keep the row tight. */
.iv__mode-swap {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: var(--bp-s-2);
}
.iv__mode-swap form {
  margin: 0;
}
.iv__thread {
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-3);
  overflow-y: auto;
  padding-right: 4px;
  flex: 1;
  min-height: 200px;
}
.iv__msg {
  font-size: 14.5px;
  line-height: 1.55;
  padding: 11px 14px;
  border-radius: var(--bp-r-md);
  max-width: 92%;
  /* pre-line preserves the newlines in dynamically-rendered turns (a user's
     multi-line answer; a coach reply whose \n the JS turns into <br>). */
  white-space: pre-line;
}
/* The static opening greeting is authored as multi-line ERB prose, so its
   source newlines would render as hard breaks under pre-line. It carries no
   meaningful newlines, so let it wrap naturally. */
.iv__msg--intro {
  white-space: normal;
}
.iv__msg--coach {
  align-self: flex-start;
  background: var(--bp-paper);
  border: 1px solid var(--bp-rule-soft);
  color: var(--bp-ink);
}
.iv__msg--me {
  align-self: flex-end;
  background: var(--bp-accent);
  color: var(--bp-accent-ink);
}

/* answer area — the user always types in their own words */
.iv__answer {
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-2);
  border-top: 1px solid var(--bp-rule-soft);
  padding-top: var(--bp-s-3);
}
.iv__answer-hint {
  font-size: 12px;
  color: var(--bp-ink-subtle);
}
.iv__answer-form {
  display: flex;
  gap: var(--bp-s-2);
  align-items: flex-end;
}
.iv__answer-input {
  flex: 1;
  padding: 9px 12px;
  border: 1px solid var(--bp-rule);
  border-radius: var(--bp-r-md);
  font: inherit;
  font-size: 14px;
  line-height: 1.5;
  resize: vertical;
  min-height: 46px;
}
.iv__answer-input:focus {
  outline: none;
  border-color: var(--bp-accent);
  box-shadow: 0 0 0 3px var(--bp-accent-soft);
}

/* ---------- Interview-plan rehearsal coach (Stage 6, #1646) ---------- */
/* The rehearsal is chat-primary single column (no side-by-side artifact pane), so
   the coach card spans the column rather than sitting as a bp-split child. */
.iv__coach--solo {
  max-width: 44rem;
  margin: 0 auto;
}
/* Quick-reply chips (the confidence options, and post-Discuss "run again / move on").
   Advisory — the free-text box always works; chips are a convenience row. */
.iv__chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--bp-s-2);
  margin-top: var(--bp-s-3);
}
.iv__chips:empty { display: none; }
.iv__chip { white-space: normal; text-align: left; }
/* Bulleted lists inside a coach bubble (topic buckets, question stems) — tight,
   so a short list reads as a list, not a run-on. */
.iv__msg-list {
  margin: var(--bp-s-2) 0 0;
  padding-left: 1.25em;
}
.iv__msg-list li { margin: 2px 0; }

/* Completion CTA bar — one persistent control that promotes MUTED→BOLD once the rep
   is complete (mirrors .np-done). The CTA swaps ghost→primary (JS); the bar picks up
   an accent edge and the message darkens, so "done" reads as one control gaining
   emphasis, not a new element popping in. */
.ivr__done {
  max-width: 44rem;
  margin: var(--bp-s-4) auto 0;
  padding: 12px 16px;
  border: 1px solid var(--bp-rule);
  border-radius: var(--bp-r-md);
  background: var(--bp-surface);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--bp-s-4);
  flex-wrap: wrap;
}
.ivr__done-msg {
  margin: 0;
  flex: 1 1 20rem;
  font-size: 13.5px;
  color: var(--bp-ink-muted);
}
.ivr__done.is-ready {
  border-color: var(--bp-accent, var(--bp-ink-1));
  background: var(--bp-paper);
}
.ivr__done.is-ready .ivr__done-msg {
  color: var(--bp-ink-2);
}
.ivr__done-cta {
  flex: none;
  white-space: nowrap;
}

/* ---------- RIGHT: the entry fields (durable artifact) ---------- */
/* Pinned to the viewport and independently scrollable, mirroring the coach, so
   the two panes sit side by side and the primary field (description, first in
   the list) stays visible next to the coach while the user is entering data
   rather than scrolling away with the page. */
.iv__fields {
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-4);
  min-height: 0;
  /* min-width: 0 lets this 1fr grid child shrink below its content's intrinsic
     width instead of overflowing the canvas — this, with box-sizing on the
     children, is what fixes the overflow. No overflow-x clamp here: the
     textareas wrap their own content, and clamping would clip the .iv__body
     focus ring (a 3px box-shadow that sits just outside the textarea edge). */
  min-width: 0;
  overflow-y: auto;
}
.iv__field {
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-2);
}
.iv__body-wrap {
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-2);
}
.iv__field-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--bp-s-3);
  flex-wrap: wrap;
}
.iv__field-name {
  font-family: var(--bp-body-family);
  font-weight: 700;
  font-size: 13px;
  letter-spacing: 0.02em;
  color: var(--bp-ink-2);
  display: inline-flex;
  align-items: center;
  gap: var(--bp-s-2);
}
.iv__primary-tag {
  font-family: var(--bp-mono-family);
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--bp-tint-ink-info);
  background: var(--bp-accent-soft);
  padding: 2px 7px;
  border-radius: var(--bp-r-pill);
}

/* provisional / pinned marker */
.iv__marker {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  align-self: flex-start;
  font-size: 11.5px;
  font-weight: 600;
  padding: 3px 10px;
  border-radius: var(--bp-r-pill);
  border: 1px solid transparent;
}
.iv__marker--provisional {
  background: var(--bp-highlight-soft);
  color: var(--bp-tint-ink-warning);
}
.iv__marker--pinned {
  background: var(--bp-tint-done);
  color: var(--bp-tint-ink-done);
}

/* editable bodies */
.iv__body {
  width: 100%;
  /* border-box so the 13px/14px padding stays inside the 100% width instead of
     pushing the textarea past the column edge (no global box-sizing reset). */
  box-sizing: border-box;
  resize: vertical;
  font-family: var(--bp-serif-family);
  font-size: 16px;
  line-height: 1.6;
  color: var(--bp-ink);
  padding: 13px 14px;
  border: 1px solid var(--bp-rule);
  border-radius: var(--bp-r-md);
  background: var(--bp-paper);
  transition: border-color var(--bp-dur-fast) var(--bp-easing),
              box-shadow var(--bp-dur-fast) var(--bp-easing),
              background var(--bp-dur-med) var(--bp-easing);
}
.iv__body:focus {
  outline: none;
  border-color: var(--bp-accent);
  box-shadow: 0 0 0 3px var(--bp-accent-soft);
}
.iv__body[data-status="empty"] {
  font-style: italic;
  color: var(--bp-ink-subtle);
  background: var(--bp-surface);
  border-style: dashed;
}
.iv__body[data-status="open"] {
  /* Faint warm tint marking a coach-drafted (provisional) field, derived from
     tokens so it tracks the palette instead of a hard-coded hex. */
  background: color-mix(in srgb, var(--bp-highlight-soft) 22%, var(--bp-paper));
  border-color: var(--bp-highlight-soft);
}
.iv__body[data-status="pinned"] {
  background: var(--bp-paper);
  border-color: var(--bp-rule);
}
.iv__body--single { min-height: 84px; }
.iv__body--item {
  min-height: 58px;
  font-size: 15px;
}

/* per-element grade (description & achievements only) */
.iv__grade {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 3px 10px;
  border-radius: var(--bp-r-pill);
  font-size: 12px;
  font-weight: 700;
  border: 1px solid transparent;
}
.iv__grade[data-tier="-1"] { display: none; }
/* the bodied-but-unjudged row (#1957) — the user wrote this line, or rewrote a
   graded one and the old verdict stood down. Deliberately quiet and pip-less:
   it is a statement that no assessment exists, not a low one. */
.iv__grade[data-tier="-1"][data-state="unassessed"] {
  display: inline-flex;
  background: transparent;
  border-color: var(--bp-rule);
  border-style: dashed;
  color: var(--bp-ink-muted);
  font-weight: 600;
  font-style: italic;
}
.iv__grade[data-tier="0"] {
  background: var(--bp-surface-2);
  color: var(--bp-ink-muted);
}
.iv__grade[data-tier="1"] {
  background: var(--bp-tint-warning);
  color: var(--bp-tint-ink-warning);
}
.iv__grade[data-tier="2"] {
  background: var(--bp-tint-info);
  color: var(--bp-tint-ink-info);
}
.iv__grade[data-tier="3"] {
  background: var(--bp-tint-active);
  color: var(--bp-tint-ink-active);
}
.iv__grade[data-tier="4"] {
  background: var(--bp-tint-done);
  color: var(--bp-tint-ink-done);
}
.iv__grade-scale {
  display: flex;
  gap: 3px;
}
.iv__grade-pip {
  width: 15px;
  height: 5px;
  border-radius: var(--bp-r-pill);
  background: var(--bp-surface-2);
}
.iv__grade-pip[data-on="true"] { background: currentColor; }

/* the single highest-leverage comment — surfaces only on field engage (#1250) */
.iv__comment {
  font-family: var(--bp-serif-family);
  font-size: 14.5px;
  line-height: 1.5;
  color: var(--bp-ink-2);
  background: var(--bp-surface);
  border-left: 2px solid var(--bp-accent);
  border-radius: 0 var(--bp-r-sm) var(--bp-r-sm) 0;
  padding: 8px 12px;
  margin: 0;
  display: none;
}
.iv__comment[data-shown="true"] { display: block; }
.iv__comment b {
  font-family: var(--bp-body-family);
  font-weight: 700;
  font-size: 12px;
  color: var(--bp-ink-muted);
  display: block;
  margin-bottom: 2px;
  letter-spacing: 0.02em;
}

/* achievements list */
.iv__items {
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-3);
}
.iv__item {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 12px;
  border: 1px solid var(--bp-rule-soft);
  border-radius: var(--bp-r-md);
  background: var(--bp-surface);
  /* keep each achievement box inside the pane: border-box folds the 12px
     padding into the width, min-width:0 lets it shrink with the column. */
  box-sizing: border-box;
  min-width: 0;
  max-width: 100%;
}
.iv__item-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--bp-s-2);
  flex-wrap: wrap;
}
.iv__empty {
  font-size: 13.5px;
  color: var(--bp-ink-subtle);
  font-style: italic;
  padding: 10px 12px;
  border: 1px dashed var(--bp-rule);
  border-radius: var(--bp-r-md);
  background: var(--bp-surface);
}

/* skills — tag_input, whole-set assessment (no per-item grade) */
.iv__tags-wrap {
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-3);
}
.iv__tags {
  display: flex;
  flex-wrap: wrap;
  gap: var(--bp-s-2);
}
.iv__tag {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 12px;
  border-radius: var(--bp-r-pill);
  background: var(--bp-accent-soft);
  color: var(--bp-tint-ink-info);
  font-size: 13px;
  font-weight: 600;
  border: 1px solid transparent;
}
.iv__tag button {
  border: none;
  background: transparent;
  color: inherit;
  cursor: pointer;
  font-size: 14px;
  line-height: 1;
  opacity: 0.6;
}
.iv__tag button:hover { opacity: 1; }

/* value dimensions — ranked_enum: an ordered, enum-constrained list with
   up/down reorder, remove, and an add-from-set picker. */
.iv__ranked-wrap {
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-3);
}
.iv__ranked-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-2);
}
.iv__ranked-item {
  display: flex;
  align-items: center;
  gap: var(--bp-s-2);
  padding: 6px 10px;
  border: 1px solid var(--bp-rule-soft);
  border-radius: var(--bp-r-md);
  background: var(--bp-surface);
  box-sizing: border-box;
  min-width: 0;
}
.iv__ranked-rank {
  flex: 0 0 auto;
  min-width: 18px;
  text-align: center;
  font-size: 12px;
  font-weight: 700;
  color: var(--bp-tint-ink-info);
}
.iv__ranked-label {
  flex: 1 1 auto;
  min-width: 0;
  font-size: 13.5px;
  font-weight: 600;
}
.iv__ranked-controls {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 2px;
}
.iv__ranked-btn {
  border: none;
  background: transparent;
  color: var(--bp-ink-subtle);
  cursor: pointer;
  font-size: 14px;
  line-height: 1;
  padding: 4px 6px;
  border-radius: var(--bp-r-sm);
}
.iv__ranked-btn:hover:not(:disabled) {
  background: var(--bp-accent-soft);
  color: var(--bp-tint-ink-info);
}
.iv__ranked-btn:disabled {
  opacity: 0.3;
  cursor: default;
}
.iv__ranked-add {
  align-self: flex-start;
  padding: 6px 10px;
  border: 1px solid var(--bp-rule);
  border-radius: var(--bp-r-pill);
  background: var(--bp-surface);
  color: var(--bp-tint-ink-info);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
}
.iv__set-assessment {
  display: none;
  flex-direction: column;
  gap: 4px;
  padding: 12px 14px;
  border: 1px solid var(--bp-rule-soft);
  border-radius: var(--bp-r-md);
  background: var(--bp-tint-info);
}
.iv__set-assessment[data-shown="true"] { display: flex; }
.iv__set-assessment h4 {
  margin: 0;
  font-family: var(--bp-body-family);
  font-weight: 700;
  font-size: 14px;
  color: var(--bp-tint-ink-info);
}
.iv__set-assessment p {
  margin: 0;
  font-family: var(--bp-serif-family);
  font-size: 14.5px;
  line-height: 1.5;
  color: var(--bp-ink-2);
}

/* IVP review / audit panel — the post-draft cross-exercise review of a
   single+draft field (#1305). Same shape as the batch set-assessment, with a
   left accent to read as a coach review attached to the statement. */
.iv__review {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-top: var(--bp-s-1);
  padding: 12px 14px;
  border: 1px solid var(--bp-rule-soft);
  border-left: 3px solid var(--bp-tint-ink-info);
  border-radius: var(--bp-r-md);
  background: var(--bp-tint-info);
}
.iv__review h4 {
  margin: 0;
  font-family: var(--bp-body-family);
  font-weight: 700;
  font-size: 14px;
  color: var(--bp-tint-ink-info);
}
.iv__review p {
  margin: 0;
  font-family: var(--bp-serif-family);
  font-size: 14.5px;
  line-height: 1.5;
  color: var(--bp-ink-2);
}

/* scratchpad — visible holding area for noted-but-unplaced material */
.iv__scratch {
  margin-top: var(--bp-s-2);
  border: 1px dashed var(--bp-rule);
  border-radius: var(--bp-r-md);
  background: var(--bp-surface);
  padding: 14px 16px;
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-3);
}
.iv__scratch-head {
  display: flex;
  align-items: center;
  gap: var(--bp-s-2);
}
.iv__scratch-title {
  font-family: var(--bp-body-family);
  font-weight: 700;
  font-size: 13px;
  color: var(--bp-ink-2);
}
.iv__scratch-sub {
  font-size: 12px;
  color: var(--bp-ink-muted);
}
.iv__scratch-empty {
  font-size: 13px;
  color: var(--bp-ink-subtle);
  font-style: italic;
}
.iv__scratch-list {
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-2);
}
.iv__scratch-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--bp-s-3);
  padding: 8px 10px;
  border-radius: var(--bp-r-md);
  background: var(--bp-paper);
  border: 1px solid var(--bp-rule-soft);
  font-size: 13.5px;
}
.iv__scratch-item--note {
  font-style: italic;
  color: var(--bp-ink-muted);
}
.iv__scratch-cand {
  display: inline-flex;
  align-items: baseline;
  gap: 8px;
}
.iv__scratch-cand .iv__cand-kind {
  font-family: var(--bp-mono-family);
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--bp-highlight);
}
.iv__scratch-actions {
  display: flex;
  align-items: center;
  gap: var(--bp-s-1);
  flex-shrink: 0;
}
.iv__dismiss { color: var(--bp-ink-muted); }
.iv__dismiss:hover {
  color: var(--bp-danger);
  background: var(--bp-tint-danger);
}

/* One-shot pulse when a held submit points the user back to un-actioned
   candidates (skill/title proposals awaiting Confirm / Not-mine). */
.iv__scratch--alert {
  border-color: var(--bp-highlight);
  border-style: solid;
  animation: iv-scratch-pulse 1.1s ease-in-out 2;
}
@keyframes iv-scratch-pulse {
  0%, 100% { box-shadow: 0 0 0 0 transparent; }
  50%      { box-shadow: 0 0 0 4px var(--bp-highlight-soft); }
}
@media (prefers-reduced-motion: reduce) {
  .iv__scratch--alert { animation: none; }
}

/* submit bar — holistic review, never grade-gated */
.iv__submit {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--bp-s-3);
  flex-wrap: wrap;
  margin-top: var(--bp-s-4);
  padding-top: var(--bp-s-4);
  border-top: 1px solid var(--bp-rule-soft);
}
.iv__submit-note {
  font-size: 12.5px;
  color: var(--bp-ink-subtle);
  max-width: 60%;
}

/* Close-the-loop "done for now" affordance (#1256) — advisory, dismissible.
   Shown only when a turn reports the category-aware `entry_sufficient` signal
   (#1255); it never gates Submit. The `hidden` attribute keeps it out until a
   turn surfaces it (and the explicit override beats the flex display). */
.iv__done {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--bp-s-3);
  flex-wrap: wrap;
  margin-top: var(--bp-s-4);
  padding: var(--bp-s-3) var(--bp-s-4);
  background: var(--bp-tint-done);
  border: 1px solid color-mix(in srgb, var(--bp-success) 35%, transparent);
  border-radius: var(--bp-r-md);
}
.iv__done[hidden] { display: none; }
.iv__done-note {
  margin: 0;
  font-size: 13px;
  color: var(--bp-success);
  max-width: 70%;
}

/* "What's left" summary (#1306) — a multi-field single+draft canvas (org
   placement) names which facets are still open so the user sees the exercise
   isn't done before heading back. Sits at the top of the artifact pane;
   advisory, never blocks. */
.iv__progress {
  margin-bottom: var(--bp-s-3);
  padding: var(--bp-s-2) var(--bp-s-3);
  font-size: 13px;
  line-height: 1.4;
  color: var(--bp-ink-muted);
  background: var(--bp-surface-sunken, color-mix(in srgb, var(--bp-ink) 4%, transparent));
  border: 1px solid var(--bp-rule-soft);
  border-radius: var(--bp-r-md);
}
.iv__progress[hidden] { display: none; }
.iv__progress[data-complete="true"] {
  color: var(--bp-success);
  background: var(--bp-tint-done);
  border-color: color-mix(in srgb, var(--bp-success) 35%, transparent);
}
.iv__progress-count { font-weight: 600; }
.iv__progress-remaining { color: inherit; }

/* Dev/staging-only grade-audit affordance (#1251); never rendered in prod. */
.iv__debug-tools {
  margin-top: var(--bp-s-3);
  padding-top: var(--bp-s-3);
  border-top: 1px dashed var(--bp-rule-soft);
}

/* mobile / narrow: panes stack, coach-primary (design §9.4) */
.iv__mobile-banner {
  display: none;
  align-items: center;
  gap: 8px;
  font-size: 12.5px;
  color: var(--bp-tint-ink-warning);
  background: var(--bp-highlight-soft);
  border-radius: var(--bp-r-md);
  padding: 8px 12px;
  margin-bottom: var(--bp-s-4);
}
@media (max-width: 60rem) {
  /* Collapse at the .bp-split breakpoint (60rem) so the workspace stacks in
     lockstep with the primitive. Panes stack and the page scrolls normally —
     drop the bounded-height workspace so the columns flow at their natural
     height. The explicit 1fr is needed because .iv__canvas's own column
     template (later in source) would otherwise win over the primitive's collapse. */
  .capabilities-interview,
  .ivp-interview { max-height: none; }
  .iv__canvas {
    grid-template-columns: 1fr;
    min-height: 0;
  }
  .iv__coach,
  .iv__fields {
    min-height: 0;
    max-height: none;
    overflow: visible;
  }
  .iv__mobile-banner { display: flex; }
}

/* ─── Résumé document — inline click-to-edit (Stage 4, #1390) ──────────────
   The document-first résumé edit surface (COMMUNICATION_PLAN_DESIGN.md §2/§5.1).
   The résumé renders as a finished document; AI-authored prose (.doc-editable —
   summary + highlights) reads as plain text until clicked, then swaps to an
   inline editor (.doc-editor) and autosaves on blur. Captured facts render as
   plain document text with no edit affordance. */
.resume-doc {
  background: var(--bp-paper);
  border: 1px solid var(--bp-rule);
  border-radius: var(--bp-r-lg);
  padding: var(--bp-s-7) var(--bp-s-7) var(--bp-s-6);
  max-width: var(--bp-w-read);
}
.resume-doc__section + .resume-doc__section {
  margin-top: var(--bp-s-6);
  padding-top: var(--bp-s-5);
  border-top: 1px solid var(--bp-rule-soft);
}
.resume-doc__section-label { display: block; margin-bottom: var(--bp-s-3); }

/* Section head — label + the "Edit in Capabilities →" lineage link, for the
   captured-fact sections (Experience / Education / Skills). */
.resume-doc__section-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--bp-s-3);
  margin-bottom: var(--bp-s-3);
}
.resume-doc__section-head .resume-doc__section-label { margin-bottom: 0; }
.resume-doc__source-link {
  font-family: var(--bp-mono-family);
  font-size: 11px;
  letter-spacing: 0.03em;
  color: var(--bp-ink-muted);
  text-decoration: none;
  white-space: nowrap;
  transition: color var(--bp-dur-fast);
}
.resume-doc__source-link:hover,
.resume-doc__source-link:focus-visible { color: var(--bp-accent); }

/* Per-entry source link (#1446) — the precise "Edit in Capabilities →" door on a
   single experience/education entry, quieter than the section link and set on its
   own line beneath the entry head. Inherits .resume-doc__source-link styling. */
.resume-doc__entry-source-link {
  display: inline-block;
  margin-top: var(--bp-s-2);
}

/* Per-section / per-entry one-click copy button (#1509) — LinkedIn is filled in
   field-by-field, so each section and each experience entry copies on its own.
   Quiet mono affordance matching the source-link aesthetic; flips to "Copied!"
   transiently (JS). A button reset so it doesn't inherit the global .bp-btn box. */
.resume-doc__copy {
  font-family: var(--bp-mono-family);
  font-size: 11px;
  letter-spacing: 0.03em;
  color: var(--bp-ink-muted);
  background: transparent;
  border: 1px solid var(--bp-rule-soft);
  border-radius: var(--bp-r-pill);
  padding: 2px 10px;
  white-space: nowrap;
  cursor: pointer;
  transition: color var(--bp-dur-fast), border-color var(--bp-dur-fast);
}
.resume-doc__copy:hover,
.resume-doc__copy:focus-visible {
  color: var(--bp-accent);
  border-color: var(--bp-accent);
  outline: none;
}
/* Right-side action cluster in a section head (copy + Capabilities link). */
.resume-doc__section-actions { display: inline-flex; align-items: center; gap: var(--bp-s-3); }
/* Per-entry action row (source link + "Copy this role"), beneath the entry head. */
.resume-doc__entry-actions {
  display: flex;
  align-items: center;
  gap: var(--bp-s-3);
  flex-wrap: wrap;
  margin-top: var(--bp-s-2);
}
.resume-doc__entry-actions .resume-doc__entry-source-link { margin-top: 0; }

/* Enrich-source re-entry (#1470). The regenerate-on-return nudge (a soft card)
   and the always-available "add or refine your source →" affordance. */
.resume-enrich__regenerate { margin: var(--bp-s-4) 0; }
.resume-enrich__regenerate p { margin: 0 0 var(--bp-s-3); }
.resume-enrich__regenerate-actions { display: flex; align-items: center; gap: var(--bp-s-3); }
.resume-enrich__source { color: var(--bp-ink-muted); margin-top: var(--bp-s-2); }
.capabilities-dashboard__enrich-return { margin: 0 0 var(--bp-s-4); }

/* Captured facts — document headings, plain text, no edit affordance. A quiet
   lock (.resume-doc__lock) marks them read-only-here; hover surfaces the lineage
   tooltip, the section link is the actionable partner. */
.resume-doc__entry + .resume-doc__entry { margin-top: var(--bp-s-5); }
.resume-doc__entry-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--bp-s-4);
}
.resume-doc__meta { display: inline-flex; align-items: center; gap: var(--bp-s-2); white-space: nowrap; }
.resume-doc__lock { display: inline-flex; align-items: center; color: var(--bp-ink-subtle); cursor: help; vertical-align: -1px; }
.resume-doc__entry-title {
  font-family: var(--bp-display-family);
  font-weight: 600;
  font-size: 19px;
  line-height: 1.25;
  margin: 0;
}
.resume-doc__entry-dates {
  font-family: var(--bp-mono-family);
  font-size: 12px;
  color: var(--bp-ink-muted);
  white-space: nowrap;
}
.resume-doc__entry-detail { color: var(--bp-ink-2); font-size: 14px; margin: 2px 0 0; }
.resume-doc__skills { font-size: 14.5px; color: var(--bp-ink-2); line-height: 1.7; }

.resume-doc__bullets {
  list-style: none;
  margin: var(--bp-s-3) 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-2);
}
.resume-doc__bullet { display: flex; gap: var(--bp-s-3); align-items: flex-start; }
.resume-doc__bullet::before {
  content: "•";
  color: var(--bp-accent);
  font-size: 18px;
  line-height: 1.5;
  flex: none;
}

/* "Why this draft" rationale — a list of discrete editorial choices, not a wall
   of prose (slice 1b, #1453). */
.resume-rationale__points {
  list-style: none;
  margin: var(--bp-s-3) 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-2);
}
.resume-rationale__points li {
  position: relative;
  padding-left: var(--bp-s-4);
  color: var(--bp-ink-2);
}
.resume-rationale__points li::before {
  content: "•";
  position: absolute;
  left: 0;
  color: var(--bp-accent);
}

/* ── The click-to-edit region ──
   READ: rendered prose. Hover (fine pointer) tints it + reveals a ✎ so the user
   knows it's editable; captured facts get none of this. Coarse pointers (touch)
   show the ✎ persistently since there's no hover. Click / Enter / Space swaps to
   an editor (JS); it autosaves on blur. */
.doc-editable {
  position: relative;
  display: block;
  flex: 1;
  border-radius: var(--bp-r-sm);
  padding: 6px 38px 6px 8px;
  margin: 0 -8px;
  cursor: text;
  transition: background var(--bp-dur-fast) var(--bp-easing);
}
.doc-editable:hover,
.doc-editable:focus-visible { background: var(--bp-surface); outline: none; }
/* Affordance chip: a "✎ Edit" label (not a bare glyph) so the edit intent is
   legible. Revealed on hover/focus; shown persistently on touch (no hover). */
.doc-editable::after {
  content: "✎ Edit";
  position: absolute;
  top: 4px;
  right: 6px;
  font-family: var(--bp-mono-family);
  font-size: 10px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--bp-ink-muted);
  background: var(--bp-surface-2);
  border: 1px solid var(--bp-rule-soft);
  border-radius: var(--bp-r-pill);
  padding: 1px 7px;
  opacity: 0;
  transition: opacity var(--bp-dur-fast);
  pointer-events: none;
}
.doc-editable:hover::after,
.doc-editable:focus-visible::after { opacity: 1; }
@media (hover: none) { .doc-editable::after { opacity: 0.7; } }
.doc-editable.is-empty { color: var(--bp-ink-subtle); font-style: italic; }

/* The summary is the most important block — serif reading type, sized to read as
   a unit (never a squished box). Both the read prose and its editor inherit it. */
.doc-editable--summary { font-family: var(--bp-serif-family); font-size: 18px; line-height: 1.65; }
.doc-editable--bullet { font-size: 14.5px; line-height: 1.55; }
/* LinkedIn headline reads as a lede; About is a multi-paragraph narrative, so it
   preserves the author's line breaks (pre-wrap) in both read and edit state. */
.doc-editable--headline { font-family: var(--bp-serif-family); font-size: 18px; line-height: 1.5; }
.doc-editable--about { font-size: 14.5px; line-height: 1.7; white-space: pre-wrap; }
/* The elevator pitch is a single spoken block — serif reading type, sized to read
   as a unit; pre-wrap so any line breaks the user adds survive in read + edit. */
.doc-editable--pitch {
  font-family: var(--bp-serif-family);
  font-size: 18px;
  line-height: 1.65;
  white-space: pre-wrap;
}

/* EDIT state — the inline editor injected on click. */
.doc-editable.is-editing { background: transparent; padding: 0; margin: 0; cursor: auto; }
.doc-editable.is-editing::after { display: none; }
.doc-editor {
  display: block;
  width: 100%;
  font: inherit;
  color: inherit;
  background: var(--bp-paper);
  border: 1px solid var(--bp-accent);
  border-radius: var(--bp-r-sm);
  padding: 6px 8px;
  resize: none;
  overflow: hidden;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--bp-accent) 15%, transparent);
}

/* Autosave state. */
.resume-doc__foot {
  display: flex;
  align-items: center;
  gap: var(--bp-s-3);
  margin-top: var(--bp-s-6);
  padding-top: var(--bp-s-4);
  border-top: 1px solid var(--bp-rule-soft);
}
.resume-doc__save {
  display: inline-flex;
  align-items: center;
  gap: var(--bp-s-2);
  font-family: var(--bp-mono-family);
  font-size: 12px;
  letter-spacing: 0.02em;
  color: var(--bp-ink-muted);
}
.resume-doc__save .dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--bp-success);
  transition: background var(--bp-dur-fast);
}
.resume-doc__save.is-saving .dot { background: var(--bp-warning); }
.resume-doc__save.is-error .dot { background: var(--bp-danger); }

/* Copy-to-clipboard export (slice 3, #1391) sits at the right end of the foot. */
.resume-doc__export { margin-left: auto; }

/* Elevator-pitch deliverability length cue (slice 2, #1514): the approximate
   spoken duration, sitting quietly in the section head opposite the label. Mono +
   muted so it reads as metadata, not prose. Updated live by the editor. */
.resume-doc__length {
  font-family: var(--bp-mono-family);
  font-size: 11px;
  letter-spacing: 0.02em;
  color: var(--bp-ink-muted);
  white-space: nowrap;
}

/* Thin-artifact audit back-links: the section-level routes to strengthen the
   material (Capabilities) or revisit the target (Blueprint). */
.resume-thin__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--bp-s-4);
  margin-top: var(--bp-s-4);
}

/* Round-trip / version-of-record panel (iter 5 slice 2, #1543 / DDR D5). The
   uploaded-state indicator (name + download + remove + replace) and the
   structured-state upload offer share the .resume-upload atom. */
.resume-upload { margin: var(--bp-s-4) 0; }
.resume-upload__body p { margin: var(--bp-s-2) 0 0; }
.resume-upload__filename {
  font-weight: 600;
  color: var(--bp-ink);
  word-break: break-word;
}
.resume-upload__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--bp-s-3);
  margin-top: var(--bp-s-4);
}
.resume-upload__replace { margin-top: var(--bp-s-4); }
.resume-upload__replace > summary { cursor: pointer; }
.resume-upload__form { margin-top: var(--bp-s-3); }
.resume-upload__form p { margin: 0 0 var(--bp-s-3); color: var(--bp-ink-muted); }

/* The offer disclosure: a compact, button-styled summary (clearly an action,
   not a bare text link) that expands to the uploader. */
.resume-upload--offer > summary.resume-upload__toggle {
  list-style: none;
  width: fit-content;
}
.resume-upload--offer > summary.resume-upload__toggle::-webkit-details-marker {
  display: none;
}
.resume-upload__chevron {
  font-size: 16px;
  line-height: 1;
  transition: transform var(--bp-dur-fast) var(--bp-easing);
}
.resume-upload--offer[open] > summary .resume-upload__chevron {
  transform: rotate(90deg);
}

/* Download-template picker (slice 3, #1545 / DDR D13). A quiet, collapsed
   disclosure — a minor setting, not a headline control. Governs the look of the
   PDF + .docx downloads only (the on-screen document is the app's own CSS, not the
   print theme), so the copy says "downloads." Picking a template autosaves inline
   (resume-template controller); no page reload, no Apply button. */
.resume-template { margin: var(--bp-s-3) 0; }
.resume-template__toggle {
  cursor: pointer;
  list-style: none;
  display: inline-flex;
  align-items: baseline;
  gap: var(--bp-s-2);
}
.resume-template__toggle::-webkit-details-marker { display: none; }
.resume-template__current { font-weight: 600; color: var(--bp-ink); }
.resume-template__hint { color: var(--bp-ink-muted); }
/* Once the options are open, "click to change" is redundant — hide it. */
.resume-template[open] .resume-template__hint { display: none; }
.resume-template__status {
  font-family: var(--bp-mono-family);
  font-size: 12px;
  color: var(--bp-ink-muted);
}
.resume-template__status.is-error { color: var(--bp-danger); }
.resume-template__panel {
  margin-top: var(--bp-s-3);
  padding: var(--bp-s-4);
  border: 1px solid var(--bp-rule-soft);
  border-radius: var(--bp-radius);
}
.resume-template__lede { margin: 0 0 var(--bp-s-3); color: var(--bp-ink-muted); }
.resume-template__options {
  display: flex;
  flex-wrap: wrap;
  gap: var(--bp-s-3);
}
.resume-template__option {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: baseline;
  gap: 2px var(--bp-s-2);
  flex: 1 1 14rem;
  padding: var(--bp-s-3);
  border: 1px solid var(--bp-rule-soft);
  border-radius: var(--bp-radius);
  cursor: pointer;
  transition: border-color var(--bp-dur-fast), box-shadow var(--bp-dur-fast);
}
.resume-template__option:has(input:checked) {
  border-color: var(--bp-accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--bp-accent) 15%, transparent);
}
.resume-template__option input { grid-row: 1 / span 2; }
.resume-template__name { font-weight: 600; color: var(--bp-ink); }
.resume-template__desc { grid-column: 2; color: var(--bp-ink-muted); font-size: 0.85em; }

@media (max-width: 40rem) {
  .resume-doc { padding: var(--bp-s-5) var(--bp-s-4); }
  .resume-doc__entry-head { flex-direction: column; gap: 2px; }
  .resume-doc__export { margin-left: 0; }
  .resume-doc__foot { flex-wrap: wrap; }
}

/* ============================================================================
   Networking discovery coach — captured network panel (Stage 5, slice 1, #1477)
   RIGHT-pane people / target-company lists on the discovery canvas. Reuses the
   interview canvas shell (.iv__*); these style the two capture sections. The
   live-rail polish (starter-set meter, in-chat planning) lands in slice 2.
   ============================================================================ */
/* The shared `.capabilities-interview` root shrink-to-fits inside the flex-column
   `main` (its `margin: 0 auto` overrides the flex stretch), so with a sparse right
   pane the 1fr column collapses and the whole canvas reads narrow. The discovery
   rail is deliberately light on content, so claim the full 1200px side-by-side
   budget explicitly (definite width beats shrink-to-fit) — the capabilities/IVP
   canvases don't need this only because their field cards fill the column. */
.networking-interview {
  width: 100%;
}
.np-capture {
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-2);
  margin-top: var(--bp-s-3);
}
.np-capture__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--bp-s-2);
}
.np-capture__item {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 8px 10px;
  border-radius: var(--bp-r-md);
  background: var(--bp-paper);
  border: 1px solid var(--bp-rule-soft);
  font-size: 13.5px;
}
.np-capture__name {
  font-weight: 600;
  color: var(--bp-ink-1);
}
.np-capture__meta {
  font-size: 12px;
  color: var(--bp-ink-muted);
}
/* The leave-the-coach control — a full-width bar BELOW both canvas panels (a flex
   child of the bounded-height .capabilities-interview column, so the canvas yields
   it height and it stays visible without forcing the rail to scroll). A horizontal
   bar: message left, CTA right, wrapping on narrow screens. */
.np-done {
  flex: none;
  margin-top: var(--bp-s-3);
  padding: 12px 16px;
  border: 1px solid var(--bp-rule);
  border-radius: var(--bp-r-md);
  background: var(--bp-surface);
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: space-between;
  gap: var(--bp-s-4);
  flex-wrap: wrap;
}
.np-done__msg {
  margin: 0;
  flex: 1 1 20rem;
  font-size: 13.5px;
  color: var(--bp-ink-muted);
}
/* Promoted state — the starter set is met. The CTA itself swaps ghost→primary
   (JS); the bar picks up an accent edge and the message darkens so "done enough"
   reads as one control gaining emphasis, not a new element. */
.np-done.is-ready {
  border-color: var(--bp-accent, var(--bp-ink-1));
  background: var(--bp-paper);
}
.np-done.is-ready .np-done__msg {
  color: var(--bp-ink-2);
}
.np-done__cta {
  flex: none;
  white-space: nowrap;
}

/* Sources-covered box (slice 2, #1478) — the at-a-glance read on which of the six
   discovery domains have yielded a real person, and where the opportunity is. */
.np-sources {
  margin-top: var(--bp-s-4);
}
.np-sources__list {
  list-style: none;
  margin: var(--bp-s-2) 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.np-sources__item {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  color: var(--bp-ink-muted);
}
.np-sources__item.is-covered {
  color: var(--bp-ink-1);
}
.np-sources__mark {
  font-weight: 700;
  color: var(--bp-rule);
}
.np-sources__item.is-covered .np-sources__mark {
  color: var(--bp-accent, var(--bp-ink-1));
}

/* Starter-set progress (slice 2, #1478) — the familiarity floor as progress, not
   a quota. */
.np-progress {
  margin-top: var(--bp-s-4);
}
.np-progress__label {
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--bp-ink-muted);
}
.np-progress__list {
  list-style: none;
  margin: var(--bp-s-2) 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.np-progress__item {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  color: var(--bp-ink-muted);
}
.np-progress__item.is-met {
  color: var(--bp-ink-1);
}
.np-progress__mark {
  font-weight: 700;
  color: var(--bp-rule);
}
.np-progress__item.is-met .np-progress__mark {
  color: var(--bp-accent, var(--bp-ink-1));
}
.np-progress__count {
  margin-left: auto;
  font-variant-numeric: tabular-nums;
  color: var(--bp-ink-muted);
}

/* ─────────────────────────────────────────────────────────────────────────────
   Registration asks — the two calls to action on the refusal page (S5, #1795).
   Collapsed, button-styled disclosures: the page's first job is still to explain
   what to do next, so neither ask may present as a panel competing with it.
   ───────────────────────────────────────────────────────────────────────────── */
.registration-asks {
  margin-top: var(--bp-s-5);
  padding-top: var(--bp-s-4);
  border-top: 1px solid var(--bp-rule);
}
.registration-asks__lede {
  margin: 0 0 var(--bp-s-3);
  color: var(--bp-ink-muted);
}
.registration-ask + .registration-ask {
  margin-top: var(--bp-s-3);
}
.registration-ask > summary.registration-ask__toggle {
  list-style: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--bp-s-2);
  width: 100%;
  text-align: left;
  cursor: pointer;
}
.registration-ask > summary.registration-ask__toggle::-webkit-details-marker {
  display: none;
}
.registration-ask__chevron {
  font-size: 16px;
  line-height: 1;
  transition: transform var(--bp-dur-fast) var(--bp-easing);
}
.registration-ask[open] > summary .registration-ask__chevron {
  transform: rotate(90deg);
}
.registration-ask__body {
  padding: var(--bp-s-3) 0 0;
}
.registration-ask__lede {
  margin: 0 0 var(--bp-s-3);
  color: var(--bp-ink-muted);
}
.registration-ask__form .bp-field {
  margin-bottom: var(--bp-s-3);
}
