*,
*::before,
*::after {
  box-sizing: border-box;
}

/* M11-05 approved design tokens — centralized here so every rule below
   (and every future one) references a token instead of a one-off literal.
   Values are the approved M11-05 visual system exactly as specified; none
   were invented for this milestone. Existing rules further down this file
   that predate M11-06 are left on their original hardcoded values — this
   milestone introduces the token system without a wholesale rewrite of
   unrelated, already-working styles. */
:root {
  --altras-teal: #176B68;
  --altras-teal-700: #105451;
  --altras-teal-900: #123F3E;
  --altras-teal-400: #27817D;
  --altras-teal-100: #E6F2F1;
  --altras-teal-50: #F2F9F8;

  /* M11-09F acceptance refinement: the one restrained success color this
     stylesheet needed — every status/feedback state before this was
     either neutral (--color-text-muted) or error (#b3261e, repeated
     literally at every [data-state="error"] site); success previously had
     no color of its own anywhere. Same base+50 pairing convention as the
     teal family above. */
  --altras-green: #1E7B34;
  --altras-green-50: #EAF7EC;

  --color-app-background: #F5F6F7;
  --color-surface: #FFFFFF;
  --color-border: #DDE1E4;
  --color-text-primary: #202529;
  --color-text-muted: #5A6270;

  /* Inter with the approved system sans-serif fallback chain — no
     web-font is loaded by this milestone (see the M11-06 implementation
     report), so this renders as Inter only where a viewer's system
     already has it installed, falling back to system-ui otherwise. */
  --font-family-base: 'Inter', system-ui, -apple-system, "Segoe UI", sans-serif;

  --font-size-app: 13px;
  --font-size-app-compact: 12px;
  --font-size-workspace-title: 24px;
  --font-weight-workspace-title: 600;
  --font-size-section-heading: 18px;
  --font-weight-section-heading: 600;
  --font-size-subsection-heading: 14px;
  --font-weight-subsection-heading: 600;

  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-6: 24px;
  --space-8: 32px;

  --control-height: 34px;
  --radius-base: 4px;

  --nav-width: 280px;
}

body {
  font-family: var(--font-family-base);
  margin: 0;
  padding: 0;
  color: var(--color-text-primary);
  background: var(--color-app-background);
  font-size: var(--font-size-app);
}

button {
  font: inherit;
}

:focus-visible {
  outline: 2px solid var(--altras-teal);
  outline-offset: 2px;
}

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

.empty-state {
  color: #5a6270;
  font-style: italic;
}

/* Guest (pre-authentication) view — unchanged by M11-06 beyond inheriting
   the new body-level tokens above; the persistent shell only applies once
   authenticated. */
#guest-view {
  padding: var(--space-6);
}

#guest-view h1 {
  font-size: var(--font-size-workspace-title);
  font-weight: var(--font-weight-workspace-title);
  margin: 0 0 var(--space-4);
}

/* M11-06: Application shell */

/* M11-09D: the outer-shell viewport-bounding correction identified by the
   M11-09D audit — min-height allowed the authenticated app to grow taller
   than the viewport, making body/page scroll the effective (and only)
   owner of vertical overflow; #blueprint-view/#blueprint-tree's own
   overflow-y:auto (further down) could then never actually activate at
   >=1024px. height:100vh (not min-height) bounds this to exactly the
   viewport regardless of html/body's own auto sizing — vh resolves
   against the viewport directly, so html/body need no change at all.
   overflow:hidden here is the single point that prevents this level (and
   therefore the page) from ever scrolling; #app-shell below gets the same
   treatment as a safety net, but the two persistent workspaces that
   already relied on #app-main's own overflow-y:auto (Blueprint, Domain)
   are deliberately untouched — see #app-main's own M11-09D comment
   further down for the one workspace-scoped exception this shift required. */
#authenticated-view {
  display: flex;
  flex-direction: column;
  height: 100vh;
  overflow: hidden;
}

/* M11-06 post-deployment fix: an ID selector's display:flex above
   otherwise beats the browser's built-in [hidden] { display: none }
   rule on specificity alone, which left the authenticated shell visible
   before sign-in even though authenticatedView.hidden was correctly
   true. Same fix pattern already used below for
   .ai-request-inspector-tab-panel[hidden]. */
#authenticated-view[hidden] {
  display: none;
}

/* M11-07 post-deployment: strengthen the ALTRAS header identity — pale
   teal application bar, wordmark matching the icon's own Primary Teal.
   Signed-in identity and the Menu button keep their existing neutral
   colors (set further down) so neither competes with the brand teal;
   height and the neutral bottom divider are unchanged. */
/* Blueprint Workspace UI refinement: was `justify-content: space-between`
   across exactly two visible children (brand, user group) at desktop
   widths. Below 1024px, #nav-drawer-toggle becomes a third visible flex
   child, and space-between distributed all three evenly — pushing the
   hamburger to the geometric center of the header instead of next to the
   brand. Fixed by dropping space-between (default flex-start) and
   letting #app-header-user's own margin-left: auto (below) push it to
   the far right regardless of how many items precede it — brand and the
   toggle (when visible) now stay grouped together on the left at every
   width, with no new breakpoint. */
#app-header {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  height: 52px;
  flex: 0 0 auto;
  padding: 0 var(--space-4);
  background: var(--altras-teal-100);
  border-bottom: 1px solid var(--color-border);
  position: sticky;
  top: 0;
  z-index: 20;
}

/* Blueprint Workspace UI refinement: #app-header-brand is now a real
   <button> (returns to Blueprint Home — see shell.js's
   selectBlueprintHome()), so default button chrome is reset here to keep
   it reading as the ALTRAS brand rather than a conventional button.
   Focus-visible styling comes from the existing global :focus-visible
   rule; no bespoke treatment needed. */
#app-header-brand {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--font-size-section-heading);
  font-weight: var(--font-weight-section-heading);
  color: var(--color-text-primary);
  min-width: 0;
  background: none;
  border: none;
  margin: 0;
  padding: 0;
  cursor: pointer;
  text-align: left;
}

#app-header-icon {
  display: block;
  flex-shrink: 0;
}

#app-header-wordmark {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  /* Matches the ALTRAS icon's own already-teal fill (assets/altras-icon.svg,
     unaltered) so wordmark and icon read as one identity. */
  color: var(--altras-teal);
}

#nav-drawer-toggle {
  display: none;
  align-items: center;
  justify-content: center;
  width: var(--control-height);
  height: var(--control-height);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-base);
  background: var(--color-surface);
  color: var(--color-text-primary);
  cursor: pointer;
  flex-shrink: 0;
}

#app-header-user {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  font-size: var(--font-size-app-compact);
  color: var(--color-text-muted);
  white-space: nowrap;
  /* Pushes this group to the far right regardless of how many items
     precede it in #app-header — see the responsive-fix comment above. */
  margin-left: auto;
}

#app-header-user button {
  padding: 0.35rem 0.75rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-base);
  background: var(--color-surface);
  color: var(--color-text-primary);
  cursor: pointer;
}

/* Application menu (M11-07) */

#app-menu-container {
  position: relative;
}

#app-menu {
  position: absolute;
  top: calc(100% + var(--space-1));
  right: 0;
  min-width: 180px;
  display: flex;
  flex-direction: column;
  padding: var(--space-1) 0;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-base);
  box-shadow: 0 4px 12px rgba(18, 63, 62, 0.12);
  z-index: 40;
}

/* Same fix as #authenticated-view[hidden] above (M11-06 post-deployment
   fix): an ID selector's display:flex otherwise beats the browser's
   built-in [hidden] { display: none } rule on specificity, which would
   leave the menu visible on page load despite starting with the hidden
   attribute in index.html. */
#app-menu[hidden] {
  display: none;
}

#app-menu [role="menuitem"] {
  display: block;
  width: 100%;
  text-align: left;
  padding: var(--space-2) var(--space-3);
  border: none;
  background: none;
  color: var(--color-text-primary);
  font-size: var(--font-size-app);
  cursor: pointer;
}

#app-menu [role="menuitem"]:hover,
#app-menu [role="menuitem"]:focus-visible {
  background: var(--altras-teal-100);
}

/* Reusable modal shell (M11-07) — native <dialog>: focus-trap,
   Escape-to-close, and ::backdrop are all browser-native, not
   hand-implemented. */
#app-modal {
  padding: 0;
  width: 90vw;
  max-width: 480px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-base);
  color: var(--color-text-primary);
  font-family: var(--font-family-base);
  font-size: var(--font-size-app);
}

#app-modal::backdrop {
  background: rgba(18, 63, 62, 0.35);
}

#app-modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--color-border);
}

#app-modal-title {
  margin: 0;
  font-size: var(--font-size-section-heading);
  font-weight: var(--font-weight-section-heading);
}

#app-modal-close-button {
  padding: var(--space-1);
  border: none;
  background: none;
  color: var(--color-text-muted);
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
}

#open-project-modal-content,
#blueprint-details-modal-content,
#settings-modal-content {
  padding: var(--space-4);
}

#blueprint-details-list {
  margin: 0;
}

/* M12-08: Item Detail & Provenance — a second, Item-scoped native
   <dialog>, styled independently of #app-modal above (different owner,
   different content shape) but following its exact showModal()/close()
   convention. Critical: `display: flex` lives only on the [open]-scoped
   rule below, never on the bare #item-detail-modal selector — an
   unscoped `display: flex` base rule would outrank the browser's own
   `dialog:not([open]) { display: none }` UA rule on cascade origin
   alone, the identical defect class this codebase has already hit three
   times with `[hidden]` (see styles-hidden-override.test.mjs). */
#item-detail-modal {
  padding: 0;
  width: 90vw;
  max-width: 560px;
  max-height: 85vh;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-base);
  color: var(--color-text-primary);
  font-family: var(--font-family-base);
  font-size: var(--font-size-app);
}

#item-detail-modal[open] {
  display: flex;
  flex-direction: column;
}

#item-detail-modal::backdrop {
  background: rgba(18, 63, 62, 0.35);
}

#item-detail-modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex: 0 0 auto;
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--color-border);
}

#item-detail-modal-title {
  margin: 0;
  font-size: var(--font-size-section-heading);
  font-weight: var(--font-weight-section-heading);
}

#item-detail-modal-close-button {
  padding: var(--space-1);
  border: none;
  background: none;
  color: var(--color-text-muted);
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
}

/* The scrollable region — header/footer stay pinned so a long revision
   history can never grow the dialog past max-height (M12-08 §21). */
#item-detail-modal-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: var(--space-4);
}

#item-detail-modal-footer {
  flex: 0 0 auto;
  display: flex;
  justify-content: flex-end;
  padding: var(--space-3) var(--space-4);
  border-top: 1px solid var(--color-border);
}

#item-detail-modal-footer button {
  padding: 0.5rem 1rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-base);
  background: #fff;
  cursor: pointer;
}

#item-detail-heading {
  margin: 0 0 var(--space-4);
  display: flex;
  align-items: baseline;
  gap: var(--space-3);
  flex-wrap: wrap;
}

#item-detail-item-number {
  font-size: var(--font-size-section-heading);
  font-weight: var(--font-weight-section-heading);
}

#item-detail-lifecycle-state {
  color: var(--color-text-muted);
}

.item-detail-section {
  margin: 0 0 var(--space-4);
}

.item-detail-section:last-child {
  margin-bottom: 0;
}

.item-detail-section h3 {
  margin: 0 0 var(--space-2);
  font-size: var(--font-size-app);
  font-weight: var(--font-weight-section-heading);
  color: var(--color-text-muted);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

/* Mobile-first, matching this stylesheet's own established convention
   (see .ai-action-controls-row above): stacked label-over-value by
   default, side-by-side from the same 768px breakpoint everything else
   here already uses (M12-08 §22). */
.item-detail-field-row {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  padding: var(--space-1) 0;
}

.item-detail-field-label {
  color: var(--color-text-muted);
}

.item-detail-field-value {
  overflow-wrap: anywhere;
}

.item-detail-monospace {
  font-family: monospace;
}

/* M12-08: .item-detail-field-row's own display:flex base rule above
   needs this compensating override the same way every other
   display:flex container in this app already does — without it,
   #item-detail-kam-revision-row would render even while `hidden` is
   true. See styles-hidden-override.test.mjs. */
#item-detail-kam-revision-row[hidden] {
  display: none;
}

#item-detail-history-status {
  margin: 0 0 var(--space-2);
  color: var(--color-text-muted);
}

#item-detail-history-list {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.item-detail-revision-row {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  padding: var(--space-1) 0;
  border-bottom: 1px solid var(--color-border);
}

.item-detail-revision-row:last-child {
  border-bottom: none;
}

.item-detail-revision-date {
  color: var(--color-text-muted);
}

@media (min-width: 768px) {
  .item-detail-field-row {
    flex-direction: row;
    gap: var(--space-3);
  }

  .item-detail-field-label {
    flex: 0 0 40%;
  }

  .item-detail-field-value {
    flex: 1;
  }

  .item-detail-revision-row {
    flex-direction: row;
    justify-content: space-between;
    gap: var(--space-3);
  }
}

.blueprint-details-row {
  display: flex;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-2) 0;
  border-bottom: 1px solid var(--color-border);
}

.blueprint-details-row:last-child {
  border-bottom: none;
}

.blueprint-details-row dt {
  color: var(--color-text-muted);
  font-size: var(--font-size-app-compact);
}

.blueprint-details-row dd {
  margin: 0;
  font-weight: 600;
}

#workspace-status,
#workspace-error,
#project-list {
  padding: 0 var(--space-6);
}

#workspace-status:empty,
#workspace-error:empty {
  padding: 0;
}

#app-shell {
  flex: 1;
  min-height: 0;
  display: flex;
  position: relative;
  /* M11-09D: safety net alongside #authenticated-view's own overflow:hidden
     above — #blueprint-view and #app-main are each responsible for their
     own internal scrolling; this level itself should never need to. */
  overflow: hidden;
}

#nav-drawer-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(18, 63, 62, 0.35);
  z-index: 25;
}

/* Persistent Blueprint navigation */

#blueprint-view {
  flex: 0 0 var(--nav-width);
  width: var(--nav-width);
  background: var(--color-surface);
  border-right: 1px solid var(--color-border);
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  z-index: 30;
}

/* M11-06 post-deployment fix: see the identical comment on
   #authenticated-view[hidden] above — the same display:flex-vs-[hidden]
   specificity issue applied here too, leaving the nav visible (with no
   Project open yet) before authentication. */
#blueprint-view[hidden] {
  display: none;
}

/* Navigation Search v1 — one shared control (see index.html's comment):
   restrained, consistent with the app's other bordered controls
   (#nav-drawer-toggle, .recent-project-row button); no native
   browser search-cancel UI relied on, since it's inconsistent across
   browsers — the compact × button is always explicit. */
#blueprint-search {
  position: relative;
  flex: 0 0 auto;
  padding: var(--space-2);
  border-bottom: 1px solid var(--color-border);
}

#blueprint-search-input {
  width: 100%;
  padding: 6px 28px 6px var(--space-2);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-base);
  background: var(--color-surface);
  color: var(--color-text-primary);
  font: inherit;
  font-size: var(--font-size-app-compact);
}

#blueprint-search-clear {
  position: absolute;
  top: 50%;
  right: calc(var(--space-2) + 6px);
  transform: translateY(-50%);
  border: none;
  background: none;
  padding: 0;
  color: var(--color-text-muted);
  font-size: 16px;
  line-height: 1;
  cursor: pointer;
}

#blueprint-tree {
  flex: 1;
  overflow-y: auto;
  padding: var(--space-2) 0;
}

.tree-node {
  display: block;
}

.tree-node-row {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  padding: 6px var(--space-2);
  cursor: pointer;
  border-left: 3px solid transparent;
  font-size: var(--font-size-app);
}

.tree-node[aria-level="1"] > .tree-node-row {
  padding-left: var(--space-2);
  font-weight: 600;
}

.tree-node[aria-level="2"] > .tree-node-row {
  padding-left: 28px;
}

.tree-node[aria-level="3"] > .tree-node-row {
  padding-left: 48px;
  font-size: var(--font-size-app-compact);
  color: var(--color-text-muted);
}

.tree-node-row:hover {
  background: var(--color-app-background);
}

/* Approved selected-node treatment: pale-teal background, medium-weight
   text, 2-3px teal leading indicator. */
.tree-node.selected > .tree-node-row {
  background: var(--altras-teal-100);
  border-left-color: var(--altras-teal);
  font-weight: 600;
  color: var(--color-text-primary);
}

/* Navigation Search v1: a distinct, lighter treatment from .selected
   above — no left border, no font-weight change — so a direct search
   match never reads as "currently selected". :not(.selected) means a row
   that is legitimately both keeps the existing selected-state treatment
   untouched rather than the two competing on background color. */
.tree-node.search-match:not(.selected) > .tree-node-row {
  background: var(--altras-teal-50);
}

.tree-node:focus-visible {
  outline: none;
}

.tree-node:focus-visible > .tree-node-row {
  outline: 2px solid var(--altras-teal);
  outline-offset: -2px;
}

.tree-node-toggle {
  display: inline-flex;
  width: 14px;
  justify-content: center;
  color: var(--color-text-muted);
  flex-shrink: 0;
}

.tree-node-label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  flex: 1;
  min-width: 0;
}

.tree-node-status {
  margin: 2px 0 4px 48px;
  font-size: var(--font-size-app-compact);
  color: var(--color-text-muted);
}

.tree-node-status-error {
  color: #b3261e;
}

/* Main workspace column */

/* M11-07 post-deployment: the main pane's own padding IS the workspace's
   framework-level gutter (~32px horizontal, 32px vertical — within the
   approved 28-32px vertical range — via the existing --space-8 token).
   This is deliberately the single source of that inset: the Blueprint
   Workspace and the no-Project landing panel below add none of their
   own, so they occupy the full pane rather than sitting in a narrower
   card inset a second time. Domain/Competency's own card padding (further
   down) is unaffected — this only changes their outer distance from the
   pane edge, not their internal layout, and future M11-08+ workspaces
   inherit this same surface model. */
#app-main {
  flex: 1;
  min-width: 0;
  overflow-y: auto;
  padding: var(--space-8);
}

/* M11-09D: the Competency Workspace is the one panel whose Detail region
   owns its own bounded internal scroll (see #competency-detail-region
   below) — #app-main's own overflow-y:auto must step aside specifically
   while it's the visible panel, or the priority panel's internal scroll
   and #app-main's own page-level scroll fight each other (two nested
   scrollbars for one region). Scoped to this one panel via :has() so the
   Blueprint and Domain Workspaces keep #app-main's own overflow-y:auto
   exactly as before — this is deliberately not a global change to
   #app-main. */
#app-main:has(#competency-context-panel:not([hidden])) {
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* M11-09C: the Competency Workspace — moved OFF the card treatment and
   onto the same "surface, not card" model as the Blueprint and Domain
   Workspaces below (mirrors #domain-context-panel's own M11-08B move
   exactly). M11-09D: now itself a column flex container spanning
   #app-main's full bounded height, so the compact Title region and the
   flexible Detail region below can share it correctly. */
#competency-context-panel {
  max-width: none;
  background: none;
  border: none;
  border-radius: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
}

/* DEV acceptance correction: same fix as #authenticated-view[hidden] /
   #blueprint-view[hidden] / #app-menu[hidden] above — this rule's own
   display:flex outranks the browser's built-in [hidden] { display: none }
   on specificity alone, so without this override the panel renders even
   while showOnly() has correctly set its hidden property true. */
#competency-context-panel[hidden] {
  display: none;
}

/* M11-09D: compact, fixed/non-growing Title region — Domain eyebrow,
   Previous/name/Next row, Competency ID. Vertical space is recovered from
   the M11-09C baseline purely through margin/gap reduction — never by
   shrinking .competency-nav-button's 44px (2.75rem) hit targets, which
   are unchanged below. */
#competency-title-region {
  flex: 0 0 auto;
  max-width: 1100px;
  width: 100%;
  margin: 0 auto;
}

/* M11-09E acceptance refinement: Domain (left) and Competency ID (right)
   share one compact metadata row above the Previous/Name/Next row —
   flex-wrap so an unusually long Domain name drops the ID to its own
   line rather than overflowing horizontally on mobile, never truncating
   the Domain name itself. */
#competency-title-meta-row {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--space-1) var(--space-3);
}

/* M11-09C acceptance refinement: #competency-context-domain is scoped by
   ID (not by editing the shared .context-panel-eyebrow class, which the
   Domain Workspace's own static eyebrow also uses). M11-09E acceptance
   refinement: left-aligned (was centered) as part of the compact
   metadata row above. */
#competency-context-domain {
  margin: 0;
  text-align: left;
}

#competency-header-row {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2) var(--space-3);
  margin: var(--space-1) 0;
}

#competency-context-name {
  flex: 1;
  min-width: 0;
  text-align: center;
  font-size: var(--font-size-workspace-title);
  font-weight: var(--font-weight-workspace-title);
  margin: 0;
}

.competency-nav-button {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 2.75rem;
  height: 2.75rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-base);
  background: var(--color-surface);
  color: var(--color-text-primary);
  font: inherit;
  font-size: var(--font-size-workspace-title);
  line-height: 1;
  cursor: pointer;
}

.competency-nav-button:hover:not(:disabled),
.competency-nav-button:focus-visible:not(:disabled) {
  background: var(--altras-teal-100);
  border-color: var(--altras-teal-400);
}

.competency-nav-button:disabled {
  color: var(--color-text-muted);
  cursor: not-allowed;
  opacity: 0.5;
}

/* M11-09D: bottom margin reduced from --space-6 (24px) to 0 — recovering
   vertical space for Competency Detail below. M11-09E acceptance
   refinement: right-aligned (was centered) as part of the compact
   metadata row above, alongside the left-aligned Domain label. */
#competency-context-id {
  margin: 0;
  text-align: right;
  color: var(--color-text-muted);
  font-size: var(--font-size-app-compact);
}

/* M11-09D: the flexible, bounded Competency Detail region — consumes the
   remaining space between the Title region above and the reserved
   Generate Item region below (#competency-generate-item-region). Exactly
   three .detail-panel children are always present; see each one's own
   comment below for the priority model.
   justify-content:flex-start (not stretch) is deliberate: during the
   brief window before initial priority is established
   (navState.priorityPanel === null, shell.js's
   initializeCompetencyDetailPriority()) no panel carries .priority, and
   this keeps that a restrained, honest state — the three compact headers
   simply stack at their natural height — rather than forcing one open
   arbitrarily while the KAM fetch is still in flight. */
#competency-detail-region {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  gap: var(--space-2);
  max-width: 1100px;
  width: 100%;
  margin: var(--space-4) auto 0;
  overflow: hidden;
}

.detail-panel {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  min-height: 0;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-base);
  background: var(--color-surface);
  overflow: hidden;
}

.detail-panel-header {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  width: 100%;
  padding: var(--space-2) var(--space-3);
  border: none;
  background: none;
  font: inherit;
  text-align: left;
  color: var(--color-text-primary);
  cursor: pointer;
}

.detail-panel-header:hover {
  background: var(--color-app-background);
}

.detail-panel-title {
  font-size: var(--font-size-subsection-heading);
  font-weight: var(--font-weight-subsection-heading);
}

.detail-panel-body {
  display: none;
  min-height: 0;
  padding: 0 var(--space-3) var(--space-3);
  overflow-y: auto;
}

/* M11-09D: exactly one panel carries priority at a time (shell.js's
   navState.priorityPanel/renderPriorityPanelState()) — it flexes to fill
   the remaining Competency Detail height and its own body becomes the
   one scrolling region inside it; the other two stay their natural
   compact header-only height (.detail-panel-body stays display:none). */
.detail-panel.priority {
  flex: 1;
  min-height: 0;
}

.detail-panel.priority .detail-panel-body {
  display: block;
  flex: 1;
}

/* M11-09D/M11-09F: the fixed, non-growing Generate Item region — flex:0 0
   auto sizes it to its own content's natural height, same treatment as
   #competency-title-region above. Same max-width/centering as
   #competency-title-region/#competency-detail-region, so all three
   regions share one visual column. */
#competency-generate-item-region {
  flex: 0 0 auto;
  max-width: 1100px;
  width: 100%;
  margin: var(--space-2) auto 0;
}

#competency-generate-item-status {
  margin: 0;
  font-size: 0.85rem;
  color: #5a6270;
  min-height: 1.1em;
  /* M11-09F live-acceptance follow-up: defensive wrap for the no-KAP/
     success/error text this one element carries in all three states —
     see .ai-action-controls-row .generate-item-actions below for the
     min-width:0 that lets this element's flex/grid ancestors actually
     shrink enough for wrapping to matter in the first place. */
  overflow-wrap: break-word;
  /* Only ever animates the color itself (idle -> error/success); the
     message's actual disappearance after its fade timer is an immediate
     text clear (shell.js's scheduleSuccessMessageFade()), not an
     animated opacity fade — the smallest treatment that still reads as
     "gentle" rather than an abrupt color swap while the text is showing. */
  transition: color 0.3s ease;
}

#competency-generate-item-status[data-state="error"] {
  color: #b3261e;
}

/* M11-09F acceptance refinement: restrained pale-green success
   confirmation ("Item #N created for KAP N") — a small tinted chip, not a
   banner, consistent with this status line's existing compact footprint. */
#competency-generate-item-status[data-state="success"] {
  color: var(--altras-green);
  background: var(--altras-green-50);
  padding: 0.15rem 0.5rem;
  border-radius: 4px;
}

/* M11-08B: the Domain Workspace — explicitly moved OFF the card treatment
   above and onto the same "surface, not card" model as the Blueprint
   Workspace directly below (the M11-08B contract's own instruction: the
   placeholder card is not the governing visual model going forward). */
#domain-context-panel {
  max-width: none;
  background: none;
  border: none;
  border-radius: 0;
  padding: 0;
}

#domain-context-name {
  font-size: var(--font-size-workspace-title);
  font-weight: var(--font-weight-workspace-title);
  margin: 0 0 var(--space-4);
}

#domain-workspace-status {
  color: var(--color-text-muted);
}

/* M11-08B: Summary + Competency KAP Coverage sections share the exact same
   centered-width/hairline-separator treatment as the Blueprint Workspace's
   own #blueprint-coverage-section/#domain-coverage-section below. */
#domain-summary-section,
#domain-kap-coverage-section {
  max-width: 1100px;
  margin-inline: auto;
}

#domain-summary-section {
  padding-top: var(--space-6);
  margin-bottom: var(--space-6);
  border-top: 1px solid var(--color-border);
}

#domain-kap-coverage-section {
  padding-top: var(--space-6);
  border-top: 1px solid var(--color-border);
}

.domain-summary-metric {
  margin-bottom: var(--space-3);
}

.domain-summary-metric:last-child {
  margin-bottom: 0;
}

#domain-kap-coverage-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

/* DEV acceptance correction: .domain-kap-coverage-row is now a native
   <button> (shell.js), mirroring .domain-coverage-row's own "whole row is
   one navigation target" treatment below exactly — same button reset, same
   resting surface/border, same hover/focus-visible teal affordance. This
   makes each Competency row read and behave as the same kind of
   interactive object as a Blueprint Workspace Domain row, not a new
   pattern. */
.domain-kap-coverage-row {
  display: block;
  width: 100%;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-base);
  padding: var(--space-3);
  margin: 0;
  text-align: left;
  font: inherit;
  cursor: pointer;
}

.domain-kap-coverage-row:hover,
.domain-kap-coverage-row:focus-visible {
  background: var(--altras-teal-100);
  border-color: var(--altras-teal-400);
}

.domain-kap-coverage-row-header {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  margin-bottom: var(--space-2);
}

.domain-kap-coverage-name {
  font-weight: 600;
  font-size: var(--font-size-app);
  color: var(--color-text-primary);
  margin-right: auto;
}

.domain-kap-coverage-chevron {
  color: var(--color-text-muted);
  font-size: var(--font-size-app);
}

/* DEV acceptance correction: the bar is now a direct child of the row
   button (previously wrapped in a flex "row-body" alongside the label) so
   it spans the row's own full usable width — the same physical width for
   every Competency row regardless of that row's own totalKapCount, since
   the row itself is always 100% of the list's width and the bar is a
   plain block child of it. Only .coverage-bar-fill's percentage (set in
   shell.js via the existing renderCoverageBar()) ever varies. */
.domain-kap-coverage-row .coverage-bar {
  margin-bottom: var(--space-2);
}

/* DEV acceptance correction: label (left) and the unpublished-work signal
   (right) now share one compact metadata line below the bar, rather than
   the label sitting beside the bar and unpublished-work as its own line
   underneath. Wraps gracefully rather than overflowing at narrow widths
   where both strings no longer fit side by side. */
.domain-kap-coverage-meta {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--space-1) var(--space-3);
}

.domain-kap-coverage-label {
  font-size: var(--font-size-app-compact);
  color: var(--color-text-muted);
}

.domain-kap-coverage-unpublished {
  font-size: var(--font-size-app-compact);
  color: var(--color-text-muted);
}

/* Blueprint Workspace (M11-07; card treatment removed post-deployment) —
   dense, restrained teal; no dashboard-style KPI cards, no enclosing
   card border, and no artificial narrow width. The workspace IS the
   application surface (#app-main's own padding above provides the
   gutter) — individual content sections below may still cap their own
   readable width. */
#blueprint-workspace-title {
  font-size: var(--font-size-workspace-title);
  font-weight: var(--font-weight-workspace-title);
  margin: 0 0 var(--space-4);
}

.workspace-section-heading {
  font-size: var(--font-size-subsection-heading);
  font-weight: var(--font-weight-subsection-heading);
  margin: 0 0 var(--space-2);
  color: var(--color-text-primary);
}

/* Blueprint Workspace UI refinement: widened (900px -> 1100px) and
   centered within the workspace pane via margin-inline: auto — the
   intentional #app-main gutters (--space-8 on the panel) are untouched,
   so wider viewports still show visible whitespace on both sides rather
   than the coverage content running edge-to-edge. Both sections share
   the same rule so Blueprint and Domain coverage stay visually
   consistent with each other. */
#blueprint-coverage-section,
#domain-coverage-section {
  max-width: 1100px;
  margin-inline: auto;
}

/* Restrained section separation (Blueprint title -> Blueprint coverage ->
   Domain coverage): a single hairline per boundary, matching the
   existing minimal border language used elsewhere (e.g. .recent-project-row)
   — no card background, no side borders, no shadow. */
#blueprint-coverage-section {
  padding-top: var(--space-6);
  margin-bottom: var(--space-6);
  border-top: 1px solid var(--color-border);
}

#domain-coverage-section {
  padding-top: var(--space-6);
  border-top: 1px solid var(--color-border);
}

.coverage-count {
  margin: 0 0 var(--space-2);
  font-size: var(--font-size-app);
  color: var(--color-text-primary);
}

.coverage-bar {
  height: 6px;
  background: var(--color-border);
  border-radius: 999px;
  overflow: hidden;
}

.coverage-bar-fill {
  height: 100%;
  width: 0%;
  background: var(--altras-teal);
}

#domain-coverage-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

/* Post-acceptance UI refinement: .domain-coverage-row is now a native
   <button> (shell.js) so the whole row — name, count, bar, and any
   whitespace — is one navigation target. This resets default button
   chrome so it keeps reading as the existing restrained row, not a
   conventional button; focus-visible styling comes from the existing
   global :focus-visible rule (see the button reset near the top of this
   file), not a second focus-ring system.
   Post-acceptance UI refinement (chevron affordance): a compact
   navigable-list-item treatment — light neutral border/surface at rest,
   no shadow, no card weight — since the earlier subtle teal-tinted hover
   alone didn't read as clickable enough. Horizontal padding is now
   required, not optional: without it, text would touch the new border. */
.domain-coverage-row {
  display: block;
  width: 100%;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-base);
  padding: var(--space-3);
  margin: 0;
  text-align: left;
  font: inherit;
  cursor: pointer;
}

.domain-coverage-row:hover,
.domain-coverage-row:focus-visible {
  background: var(--altras-teal-100);
  border-color: var(--altras-teal-400);
}

.domain-coverage-row-header {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  margin-bottom: var(--space-1);
}

.domain-coverage-name {
  font-weight: 600;
  font-size: var(--font-size-app);
  color: var(--color-text-primary);
  /* Post-acceptance UI refinement: the header now has 3 children (name,
     count, chevron) — space-between across 3 items would push count to
     the visual middle. Pinning name left via margin-right: auto and
     letting count+chevron sit together at the end (separated only by the
     header's own small gap) keeps the exact same visual result as the
     old 2-item space-between, plus the new chevron immediately after
     count. */
  margin-right: auto;
}

.domain-coverage-count {
  font-size: var(--font-size-app-compact);
  color: var(--color-text-muted);
}

.domain-coverage-chevron {
  color: var(--color-text-muted);
  font-size: var(--font-size-app);
}

/* No-Project landing (M11-07 post-deployment) — same "surface, not card"
   treatment as the Blueprint Workspace above; no enclosing card, no
   artificial width. Recent Projects use a compact border-separated row
   list (matching the Domain coverage rows' own restrained treatment),
   not cards. */
#no-project-landing-title {
  font-size: var(--font-size-workspace-title);
  font-weight: var(--font-weight-workspace-title);
  margin: 0 0 var(--space-2);
}

#no-project-landing-subtitle {
  margin: 0 0 var(--space-6);
  color: var(--color-text-muted);
  max-width: 640px;
}

/* Post-acceptance UI refinement: the previous max-width: 900px cap left
   .recent-project-row (and its existing justify-content: space-between)
   flush-left and narrow, so the Open button landed well short of the
   workspace's own right edge. Removing the cap lets each row use the
   full width of #no-project-landing, so the existing space-between
   places Open at the true right side of the available row — no new
   markup, no change to the row-building JS. */

/* Post-acceptance UI refinement: a single enclosing list surface so
   multiple Recent Projects read as one compact list control rather than
   loose rows floating in the workspace — restrained (1px neutral border,
   existing radius token, no shadow), not a card per Project. */
#recent-projects-list {
  display: flex;
  flex-direction: column;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-base);
}

/* renderRecentProjects() (app.js) never hides #recent-projects-list
   itself in the zero-Projects case — it only shows #recent-projects-empty
   and leaves the (childless) list in place. Without this, the new
   border/background above would render as a visible empty box. */
#recent-projects-list:empty {
  display: none;
}

.recent-project-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-3);
  border-bottom: 1px solid var(--color-border);
}

.recent-project-row:last-child {
  border-bottom: none;
}

.recent-project-name {
  font-size: var(--font-size-app);
  color: var(--color-text-primary);
}

.recent-project-row button {
  padding: 0.35rem 0.75rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-base);
  background: var(--color-surface);
  color: var(--color-text-primary);
  cursor: pointer;
}

#recent-projects-empty {
  margin: 0;
  color: var(--color-text-muted);
}

.context-panel-eyebrow {
  margin: 0 0 var(--space-1);
  text-transform: uppercase;
  font-size: var(--font-size-app-compact);
  letter-spacing: 0.03em;
  color: var(--color-text-muted);
}

/* M11-08B/M11-09C: neither #domain-context-panel's h2 (#domain-context-name)
   nor #competency-context-panel's (#competency-context-name) share this
   rule anymore — both use the workspace-title tokens instead, matching
   the Blueprint Workspace's #blueprint-workspace-title. Only
   #competency-context-panel h2 was actually removed here; had it stayed,
   its higher specificity (id + type) would have silently overridden
   #competency-context-name's own (id-only) font-size rule above. */
#competency-context-item-count {
  color: var(--color-text-muted);
  font-size: var(--font-size-app-compact);
}

#question-workspace,
#ai-request-inspector-page {
  max-width: 1100px;
}

/* M12-03: the Item Workspace owns its own bounded internal scroll while
   it's the visible panel — the exact same reasoning/mechanism as
   #app-main:has(#competency-context-panel:not([hidden])) above (see that
   rule's own comment): without this, #app-main's own page-level
   overflow-y:auto and the Item Element Section's internal scroll (below)
   fight each other. Scoped to this one panel via :has(), so the
   Blueprint/Domain/Competency Workspaces keep #app-main's own scroll
   behavior exactly as before. */
#app-main:has(#question-workspace:not([hidden])) {
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* M12-03: the Item Workspace itself becomes a column flex container
   spanning #app-main's full bounded height — the same shape
   #competency-context-panel gives itself, immediately below. */
#question-workspace {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
  overflow: hidden;
}

/* M12-03: same fix as #competency-context-panel[hidden] above — this
   rule's own display:flex outranks the browser's built-in
   [hidden] { display: none } on specificity alone. */
#question-workspace[hidden] {
  display: none;
}

/* Adaptive/drawer navigation below 1024px, per the approved responsive
   model (>=1280 full desktop, 1024-1279 compact desktop — both persistent
   — 768-1023 adaptive/tablet, <768 narrow/mobile, both drawer-based). The
   shell/tree has no content difference to express between the two
   persistent tiers, so both share one >=1024px rule. */
@media (max-width: 1023px) {
  #nav-drawer-toggle {
    display: inline-flex;
  }

  /* Post-acceptance UI refinement: hides only the static "Signed in as"
     prefix at narrow widths — #signed-in-user (the email) is a separate
     element and stays visible/unduplicated at every width. */
  #signed-in-as-label {
    display: none;
  }

  #blueprint-view {
    position: fixed;
    top: 52px;
    left: 0;
    bottom: 0;
    transform: translateX(-100%);
    transition: transform 0.2s ease;
    box-shadow: 2px 0 12px rgba(18, 63, 62, 0.15);
  }

  #app-shell.nav-drawer-open #blueprint-view {
    transform: translateX(0);
  }

  #app-shell:not(.nav-drawer-open) #nav-drawer-backdrop {
    display: none;
  }
}

@media (min-width: 1024px) {
  #nav-drawer-backdrop {
    display: none;
  }
}

/* Item Workspace (M12-03: five vertically stacked regions, replacing the
   former two-column Questions/Item layout). #question-workspace's own
   flex/height architecture is set above, alongside the matching
   #app-main:has() rule. Each bounded region is flex: 0 0 auto; only
   #item-element-section is elastic (flex: 1; min-height: 0) and owns its
   own internal scroll — the exact same "one elastic region, the rest
   bounded" model #competency-detail-region's .detail-panel/
   .detail-panel.priority already established one workspace over. */

#question-detail-content {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
  overflow: hidden;
  /* M12-09: the sole spacing mechanism between the four regions this
     wraps (Navigation Bar / Item Element / Action Bar / AI Revision) —
     previously several of them also carried their own margin, doubling
     the visible gap on top of this one. Matches #item-header's own
     margin-bottom above for one consistent inter-region rhythm. */
  gap: var(--space-3);
}

/* M12-03: same fix as #competency-context-panel[hidden] above — this
   rule's own display:flex outranks the browser's built-in
   [hidden] { display: none } on specificity alone. */
#question-detail-content[hidden] {
  display: none;
}

#question-detail-status {
  flex: 0 0 auto;
}

/* Region 1 — Item Header: "< Back to competency" plus the compact
   three-dot Item menu (M12-07), replacing the former standalone Restore/
   Inspector/Archive button row — a real, restrained separator remains
   beneath the whole header. */
#item-header {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.75rem;
  padding-bottom: 0.75rem;
  border-bottom: 1px solid #d7dbe0;
  /* M12-09: same 12px value as before (0.75rem), now the shared
     --space-3 token — deliberately equal to #question-detail-content's
     own gap below, so Header-to-content spacing and every inter-region
     gap inside that container read as one consistent rhythm rather than
     two coincidentally-similar numbers. */
  margin-bottom: var(--space-3);
}

#item-header-back-button {
  padding: 0.4rem 0.75rem;
  border: 1px solid #d7dbe0;
  border-radius: 4px;
  background: #fff;
  color: #1b1f24;
}

#item-header-back-button:disabled {
  cursor: not-allowed;
  opacity: 0.6;
}

/* M12-07: reuses #app-menu's own established trigger+dropdown pattern
   (position: relative wrapper, absolutely-positioned popup anchored to
   it — see #app-menu-container/#app-menu above) rather than inventing a
   second menu implementation; scoped entirely to this local wrapper, so
   none of the Item Workspace's five primary regions use absolute/fixed
   positioning themselves. */
#item-menu-container {
  position: relative;
}

/* Visually secondary and compact — never styled as a primary action
   (compare #item-action-bar #publish-button below) or as destructive
   (that treatment is reserved for Archive inside the menu itself). */
#item-menu-button {
  padding: 0.4rem 0.6rem;
  border: 1px solid #d7dbe0;
  border-radius: 4px;
  background: #fff;
  color: #1b1f24;
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
}

#item-menu {
  position: absolute;
  top: calc(100% + 0.25rem);
  right: 0;
  min-width: 200px;
  display: flex;
  flex-direction: column;
  padding: 0.25rem 0;
  background: #fff;
  border: 1px solid #d7dbe0;
  border-radius: 6px;
  box-shadow: 0 4px 12px rgba(18, 63, 62, 0.12);
  z-index: 40;
}

#item-menu[hidden] {
  display: none;
}

#item-menu [role="menuitem"] {
  display: block;
  width: 100%;
  text-align: left;
  padding: 0.5rem 0.9rem;
  border: none;
  background: none;
  color: #1b1f24;
  font: inherit;
  cursor: pointer;
}

#item-menu [role="menuitem"]:hover:not(:disabled),
#item-menu [role="menuitem"]:focus-visible:not(:disabled) {
  background: #f0f0f2;
}

/* The one place any Item menu item's real disabled state (Item Detail —
   always; Restore Last Published — per updateWorkingCopyActionAvailability())
   gets a visual treatment, scoped to :disabled — never unconditional, the
   same DEV-defect class already fixed for Publish in M12-06. AI Request
   Inspector is never disabled, so it never matches this rule at all. */
#item-menu [role="menuitem"]:disabled {
  color: #a0a6ad;
  cursor: not-allowed;
}

.item-menu-separator {
  height: 1px;
  margin: 0.25rem 0;
  background: #e5e8eb;
}

/* Archive: restrained destructive treatment — red text only, never a
   filled/saturated red background, consistent with this app's existing
   "color is not the sole meaning, labels stay explicit" convention. */
#item-menu-destructive {
  color: #b3261e;
}

#item-menu-destructive:hover:not(:disabled),
#item-menu-destructive:focus-visible:not(:disabled) {
  background: #fdecea;
}

#item-menu-destructive:disabled {
  color: #a0a6ad;
}

/* Region 2 — Item Navigation Bar: Previous | Item # / state | Next.
   Previous/Next are disabled structural placeholders only — M12-04
   implements sibling-Item order/behavior; there is no click handler for
   either anywhere in questions.js. M12-09: no margin-bottom of its own
   any more — #question-detail-content's own gap (above) is the sole
   spacing mechanism to the Item Element Section below; the two used to
   stack, doubling the visible gap. */
#item-navigation-bar {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
}

#item-previous-button,
#item-next-button {
  flex: 0 0 auto;
  padding: 0.4rem 0.75rem;
  border: 1px solid #d7dbe0;
  border-radius: 4px;
  background: #fff;
  color: #1b1f24;
  cursor: pointer;
}

/* M12-04 DEV acceptance refinement: these two rules were written in M12-03,
   when both controls were permanently inert structural placeholders — the
   disabled look was baked into the unscoped base rule above instead of
   being scoped to :disabled, the same mistake .competency-nav-button
   (above) never made. M12-04 wired up the real native `disabled` property
   (updateItemNavigationButtons()), but the CSS never depended on it, so an
   enabled button was still fully functional while permanently presenting
   as disabled. Scoping to :disabled — never a class or aria-disabled — so
   the browser's own native disabled state remains the single source of
   truth for both presentation and interaction. */
#item-previous-button:disabled,
#item-next-button:disabled {
  cursor: not-allowed;
  opacity: 0.6;
}

/* M12-09: Item #N / lifecycle-state read as one compact two-line identity
   block, not two paragraphs separated by the browser's own default <p>
   margin (that default — never an explicit rule anywhere in this file —
   was the entire cause of the old, too-large gap between them). An
   explicit flex `gap` is used instead of relying on any margin, on
   either child, ever reintroducing that default. */
#item-navigation-status {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  text-align: center;
}

/* Region 3 — Item Element Section: the elastic region. M12-05: Stem/
   Correct Response/Distractor 1-3/Rationale are a six-element accordion,
   exactly one expanded at a time. The section itself is now a flex
   column (previously just overflow-y: auto on the whole region) so the
   single expanded panel — not the whole region — owns internal scroll:
   collapsed header rows are flex: 0 0 auto (see
   .item-accordion-header-row below); whichever mode (#question-view-mode
   or #question-edit-mode) is visible fills the remaining space and is
   itself a flex column for the same reason, one level down. */
#item-element-section {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border: 1px solid #d7dbe0;
  border-radius: 6px;
  padding: 1rem;
  background: #fff;
}

/* M12-05 narrow-viewport correction: the collapsed header rows alone
   (six of them, each flex: 0 0 auto) can exceed the space available on a
   short/narrow viewport before the expanded panel even gets a chance to
   claim its own remaining space. overflow: hidden here would silently
   clip the later rows with no way to reach them at all — worse than an
   unpolished layout, an actually inaccessible one. overflow-y: auto is a
   safety net, not the primary mechanism: on any viewport where
   everything already fits (the ordinary desktop/laptop case this
   milestone targets), flex sizing already makes this a no-op — auto
   never shows a scrollbar unless content genuinely exceeds the box. */
#question-view-mode,
#question-edit-mode {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  overflow-x: hidden;
}

/* M12-03/M12-05: an ID-selector display:flex base rule outranks the
   browser's built-in [hidden] { display: none } on specificity alone —
   the same fix class tracked in styles-hidden-override.test.mjs, applied
   here for the two new display:flex base rules just above. Two separate
   rules (not a combined selector list) so each is independently matched
   by that test's own per-id regex. */
#question-view-mode[hidden] {
  display: none;
}

#question-edit-mode[hidden] {
  display: none;
}

#question-content-body {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  overflow-x: hidden;
}

/* M12-05 acceptance refinement: one accordion section wrapper is the
   actual direct child of #question-content-body/#edit-distractors-list
   (never its header row or panel individually) — see
   buildViewAccordionSection()'s own comment for why. flex: 0 0 auto is
   the COLLAPSED default; the :has() rule below promotes exactly the
   section containing the currently-expanded toggle to flex: 1, so it —
   and only it — consumes the Item Element Section's remaining height.
   This reads activeItemElement's own existing DOM effect
   (aria-expanded="true", already set by applyActiveItemElement() — see
   that function, unchanged by this refinement) rather than adding a new
   JS-managed class; #app-main:has(#question-workspace:not([hidden]))
   above is this same codebase's own established precedent for :has(). */
.item-accordion-section {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  min-height: 0;
  border-bottom: 1px solid #e5e8eb;
  /* Acceptance refinement §3/§4: every section gets the same left-edge
     semantic indicator geometry — gray by default (Stem/Rationale keep
     this base color unmodified), overridden to green/red below for
     Correct Response/Distractors. Previously Stem/Rationale had no
     border-left at all, a real (if small) structural difference from
     the other four this refinement removes. */
  border-left: 3px solid #5a6270;
}

/* min-height (a floor, not a fixed size — it still grows freely above
   this via flex: 1 whenever more room exists) keeps the active section
   from being squeezed toward zero on a short/narrow viewport: the five
   collapsed rows are flex-shrink: 0 (they hold their natural size), so
   without a floor here the active section — the one flexible,
   flex-shrink: 1 item — would absorb all the compression by itself
   first, down past the point of being usable, before the ancestor
   overflow-y: auto safety net (#question-view-mode/#question-edit-mode/
   #question-content-body above) ever gets a chance to take over and let
   the collapsed rows scroll out of view instead. Not a viewport-specific
   pixel height — one rem value that applies identically everywhere. */
.item-accordion-section:has(.item-accordion-toggle[aria-expanded="true"]) {
  flex: 1;
  min-height: 8rem;
}

.item-accordion-section:last-child {
  border-bottom: none;
}

/* Restrained ALTRAS semantic treatment (locked contract §11): color is
   never the sole meaning — every section keeps its explicit text label
   regardless of this left-border accent. Reuses this file's own existing
   Correct/distractor color values (.question-option.correct's green,
   .ai-request-inspector-error-text's red) rather than introducing new
   ones. */
.item-accordion-section--correct {
  border-left-color: #1f9254;
}

.item-accordion-section--distractor {
  border-left-color: #b3261e;
}

.item-accordion-header-row {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.5rem 0.75rem 0.5rem 0.6rem;
}

/* M12-05 §14: the toggle and the Lock control are siblings, never
   nested — a real <button> for the toggle (keyboard-focusable, Enter/
   Space activate it natively) sits alongside a plain <label>.lock-toggle
   for Lock, so clicking Lock can never also fire the toggle's own click
   (they are not the same element and Lock is not inside the button), and
   no illegal nested-interactive-control structure is created. */
.item-accordion-toggle {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  border: none;
  background: none;
  padding: 0;
  font: inherit;
  text-align: left;
  color: #1b1f24;
  cursor: pointer;
}

.item-accordion-title {
  flex: 0 0 auto;
  font-weight: 600;
}

/* M12-05 §16/§6: the collapsed-row preview — full normalized text is
   always in the DOM (see formatItemAccordionPreview()); only the visual
   truncation is CSS. min-width: 0 is required for text-overflow:
   ellipsis to actually clip inside a flex child, and this rule (not a
   JS substring cut) is what makes the preview "truncate before the Lock
   control" — the Lock label's own flex: 0 0 auto keeps it from ever
   being compressed to make room. */
.item-accordion-preview {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: #5a6270;
  font-weight: normal;
}

/* Expanded state shows the full content in the panel below — the
   collapsed one-line preview would be redundant alongside it. */
.item-accordion-toggle[aria-expanded="true"] .item-accordion-preview {
  display: none;
}

.item-accordion-lock {
  flex: 0 0 auto;
}

/* Acceptance refinement §6/§8: display:flex/flex-direction:column lets
   an Edit-mode textarea inside (flex: 1 — see .item-accordion-panel
   textarea below) grow to fill the panel's now-genuine (via the
   :has()-driven section flex: 1 above) available height. Safe for View
   mode's plain <p> text too: a flex item with no flex-grow of its own
   keeps its natural content height and sits at the container's default
   flex-start position — i.e. naturally toward the top, never stretched
   or vertically centered (locked contract §7's own requirement). */
.item-accordion-panel {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  padding: 0 0.75rem 0.75rem;
}

/* Acceptance refinement correction: this milestone's own M12-05 comment
   here previously (correctly, at the time) said .item-accordion-panel
   "carries no competing display:flex... base rule, so it needs no
   compensating [hidden] override" — true until this very refinement gave
   it display:flex (above, to let an Edit-mode textarea grow — see that
   rule's own comment). That reintroduced the exact same class of defect
   #question-view-mode/#question-edit-mode already needed a
   [hidden]-override fix for in M12-05, and #question-workspace/
   #question-detail-content before that in M12-03 — a manual browser
   check caught every "collapsed" panel still rendering (author-origin
   display:flex beats the browser's own [hidden]{display:none} UA rule
   regardless of specificity numbers, since author styles always win over
   equal-or-lower-specificity user-agent ones). Collapsed panels are
   hidden via the native `hidden` property (applyActiveItemElement()),
   never a class; this override is what actually lets that property work
   again now that the panel has its own competing display rule. */
.item-accordion-panel[hidden] {
  display: none;
}

/* Region 4 — Item Action Button Bar. M12-06: Edit/Publish grouped on the
   left (.item-action-primary), working-copy save status on the right —
   space-between with exactly those two children gives that split without
   any absolute positioning or fixed offsets. */
#item-action-bar {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
}

.item-action-primary {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

/* M12-06 DEV acceptance refinement: this rule previously baked Publish's
   disabled look (grey background, muted text, not-allowed cursor)
   unconditionally into its own base selector — the identical mistake
   already found and fixed for #item-previous-button/#item-next-button in
   M12-04 (see that rule's own comment below). Publish's real enabled/
   disabled state was always correct (updateWorkingCopyActionAvailability()
   sets the native `disabled` property correctly — see that function,
   unchanged by this fix); only the CSS never depended on it, so a
   functionally-enabled Publish (e.g. mid-Edit with valid unpublished
   changes) still visually presented as permanently disabled and
   unclickable-looking despite actually accepting and completing the
   click. Base rule now looks actionable (filled blue, pointer cursor —
   matching #question-edit-actions button's own identical enabled/
   disabled split above); the grey/not-allowed look is scoped to
   :disabled, so the browser's own native disabled state remains the
   single source of truth for both presentation and interaction. */
#item-action-bar #publish-button {
  padding: 0.5rem 1rem;
  border: 1px solid #2952cc;
  border-radius: 4px;
  background: #2952cc;
  color: #fff;
  cursor: pointer;
}

#item-action-bar #publish-button:disabled {
  cursor: not-allowed;
  opacity: 0.6;
}

/* M10-09: Competency workspace KAM/KAP structural coverage */

#kap-coverage-summary {
  font-weight: 600;
  margin: 0.5rem 0;
}

.kap-coverage-item {
  border: 1px solid #d7dbe0;
  border-radius: 4px;
  padding: 0.5rem 0.75rem;
  margin: 0 0 0.5rem;
  background: #fff;
}

.kap-coverage-heading {
  display: flex;
  gap: 0.4rem;
  font-weight: 600;
}

.kap-coverage-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-top: 0.25rem;
  font-size: 0.85rem;
  color: #5a6270;
}

.kap-coverage-details {
  margin-top: 0.4rem;
  font-size: 0.85rem;
}

.kap-coverage-details summary {
  cursor: pointer;
  color: #2952cc;
}

.kap-coverage-source-support {
  color: #5a6270;
  font-style: italic;
}

/* M11-09E: Assessment Items row — mirrors .kap-coverage-item's exact
   spacing/colors (the immediate visual sibling inside the same Competency
   Detail region) rather than the separate, pre-M11-05
   .question-list-item convention; adds only the button-reset/hover
   treatment a clickable navigation row needs. The entire row is the
   navigation hotspot — no separate "Open" control. */
.assessment-item-row {
  display: block;
  width: 100%;
  text-align: left;
  border: 1px solid #d7dbe0;
  border-radius: 4px;
  padding: 0.5rem 0.75rem;
  margin: 0 0 0.5rem;
  background: #fff;
  font: inherit;
  cursor: pointer;
}

.assessment-item-row:last-child {
  margin-bottom: 0;
}

.assessment-item-row:hover,
.assessment-item-row:focus-visible {
  border-color: var(--altras-teal-400);
  background: var(--altras-teal-50);
}

/* M11-09E final acceptance correction: single-line, width-driven
   truncation — matches .tree-node-label/.question-list-item-stem's
   existing treatment. The row (a plain block element, not a flex/grid
   item) already sizes this span to the row's full available content
   width, so overflow/ellipsis alone is sufficient — no min-width:0 is
   needed here, and deliberately no max-width: the browser's actual
   rendered width, not a fixed character count or a fixed pixel cap,
   determines what's visible. Never wraps to a second line. */
.assessment-item-row-stem {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: 600;
}

/* M11-09F acceptance refinement: one compact metadata line — #N · KAP N
   · State — replacing the former separate Item-number line and the
   independent "Unpublished edits" badge (which could co-occur with
   "Published Revision N" and read as contradictory). */
.assessment-item-row-meta {
  display: block;
  margin-top: 0.25rem;
  font-size: 0.85rem;
  color: #5a6270;
}

/* M11-09F: transient "just generated" reveal — same pale-teal/teal-border
   treatment the navigation tree already uses for .tree-node.selected, so
   this reads as "the emphasized one" using an established visual
   vocabulary rather than a new color. Deliberately not an animation: this
   row is fully rebuilt (clearElement() + recreate) on every
   renderCompetencyItemsPanel() call, including ones unrelated to
   generation (e.g. a KAM refresh), so a steady state — present or absent,
   never replaying — is the only treatment that can't misfire on an
   incidental re-render. Applied purely from in-memory state
   (shell.js's highlightedItemId); never reflected in the URL or any
   storage. */
.assessment-item-row-generated {
  border-color: var(--altras-teal);
  background: var(--altras-teal-50);
}

.question-option {
  display: flex;
  align-items: center;
  justify-content: space-between;
  border: 1px solid #d7dbe0;
  border-radius: 4px;
  padding: 0.5rem 0.75rem;
  margin: 0 0 0.5rem;
}

.question-option.correct {
  border-color: #1f9254;
  background: #e9f9f0;
}

/* M4-10: View ↔ Edit ↔ Save/Cancel for the current Working Copy —
   deliberately minimal, mirrors the existing read-only layout rather than
   redesigning it. M12-03: retargeted from the descendant selector
   #question-view-mode #edit-working-copy-button to a plain id selector —
   the button now lives in the Item Action Bar (a sibling of
   #question-view-mode, not a descendant); margin-top dropped since it no
   longer stacks under View mode's own content, instead sitting in the
   Action Bar's own flex row alongside Publish. */
#edit-working-copy-button {
  padding: 0.5rem 1rem;
  border: 1px solid #2952cc;
  border-radius: 4px;
  background: #fff;
  color: #2952cc;
  cursor: pointer;
}

label.lock-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  font-size: 0.8rem;
  font-weight: normal;
  color: #5a6270;
  white-space: nowrap;
}

.lock-checkbox {
  margin: 0;
}

/* M12-05: every accordion panel's textarea — Stem/Correct Response/each
   Distractor/Rationale alike — styled uniformly from one place, since
   each now lives alone inside its own .item-accordion-panel (previously
   split between .working-copy-field textarea for Stem/Rationale and
   .edit-option-text for Correct Response/Distractors, which needed
   separate inter-row margin rules when several sat in one flat list).
   .edit-option-text itself is kept as a class on Correct Response's and
   each Distractor's textarea — existing tests key off it directly — but
   no longer carries its own styling. */
/* Acceptance refinement §6: grows to fill its now-flexible panel
   (.item-accordion-panel is display:flex;flex-direction:column above)
   instead of sitting at its `rows` attribute's small intrinsic height
   with large unused space below it — Stem/Correct Response/each
   Distractor/Rationale alike, one rule for all six. min-height: 0 lets
   it shrink below its own content's natural size when the panel itself
   is short (e.g. a narrow/mobile viewport), rather than overflowing the
   flex chain; the textarea's own native scrollbar still appears whenever
   its content exceeds whatever height it's actually given. resize:
   vertical is kept — an Author can still drag it taller within its
   scrollable panel. */
.item-accordion-panel textarea {
  width: 100%;
  flex: 1;
  min-height: 0;
  font: inherit;
  padding: 0.5rem;
  border: 1px solid #d7dbe0;
  border-radius: 4px;
  resize: vertical;
}

#question-edit-actions {
  display: flex;
  gap: 0.75rem;
  margin-top: 0.75rem;
}

#question-edit-actions button {
  padding: 0.5rem 1rem;
  border: 1px solid #2952cc;
  border-radius: 4px;
  background: #2952cc;
  color: #fff;
  cursor: pointer;
}

#question-edit-actions button:disabled {
  cursor: not-allowed;
  opacity: 0.6;
}

#working-copy-reload-button {
  border-color: #d7dbe0;
  background: #f0f0f2;
  color: #1b1f24;
}

/* M12-03: previously a full-width bar with its own top/bottom borders and
   top margin, appropriate to its old position as a standalone divider
   between View/Edit content and the Revise/action controls beneath it.
   Now relocated into the compact Item Navigation Bar alongside
   #item-number-display. M12-09: explicitly subordinate to Item #N —
   smaller than it (was previously, backwards, the larger of the two
   lines) and an explicit margin: 0 so it can never reintroduce the
   browser's own default <p> top-margin as a gap against the line above
   it (see #item-navigation-status's own comment). Wording/derivation
   unchanged — typography only. */
#question-lifecycle-bar {
  margin: 0;
  font-size: 0.8rem;
  font-weight: 400;
  color: #5a6270;
}

/* M4-09: Generate New Item (competency scope) / Revise All + Undo AI
   (item scope) — deliberately minimal, not a redesign of the editor. */
.ai-action-controls {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  margin: 0.75rem 0;
  padding: 0.75rem;
  border: 1px solid #d7dbe0;
  border-radius: 6px;
  background: #f7f9ff;
}

/* M12-07: Region 5, the AI Revision Panel — explicitly bounded (matching
   #item-action-bar's own explicit flex: 0 0 auto above), never the
   elastic region. It already behaved this way by omission (a plain flex
   child of #question-detail-content's column with no flex-grow of its
   own), but an explicit declaration here removes any reliance on that
   default as the Item Workspace's layout keeps evolving — the Item
   Element Section (#item-element-section) remains the sole elastic
   region. M12-09: overrides .ai-action-controls's own `margin: 0.75rem
   0` (shared with the unrelated Competency Workspace "Generate Item"
   region, so that shared rule itself is never touched) — spacing above/
   below this panel now comes solely from #question-detail-content's own
   gap, the same single-mechanism fix applied to the Navigation Bar. */
#item-ai-revision-panel {
  flex: 0 0 auto;
  margin: 0;
}

.ai-action-controls label {
  font-size: 0.85rem;
  font-weight: 600;
  color: #5a6270;
}

.ai-action-controls textarea {
  font: inherit;
  padding: 0.5rem;
  border: 1px solid #d7dbe0;
  border-radius: 4px;
  resize: vertical;
}

/* M9-05: Assessment Approach selector — same simple bordered-field look
   as the textarea immediately above, no advanced styling. */
.ai-action-controls select {
  font: inherit;
  padding: 0.4rem;
  border: 1px solid #d7dbe0;
  border-radius: 4px;
  background: #fff;
}

/* M11-09F: a row-oriented variant of .ai-action-controls immediately
   above (used as-is by the legacy Generate Item sidebar and Revise
   Unlocked) — same bordered/tinted box, same field styling, only the
   internal layout changes so the wider Competency Workspace can lay its
   fields out horizontally instead of the narrow sidebar's forced stack.
   Placed immediately after .ai-action-controls's own rules so its
   overrides reliably win the cascade regardless of where
   #competency-generate-item-region's own rule happens to sit.
   M11-09F live-acceptance follow-up: CSS Grid (replacing the prior
   flex-wrap reflow) drives the locked row grouping — Knowledge
   Assessment Point + Assessment Approach side by side, Author
   Instruction spanning both columns below that, the action row spanning
   both columns beneath that — via grid-template-areas against the four
   existing DOM children directly. Unlike flexbox, grid area placement
   doesn't require those children to already be grouped into wrapper
   rows, so no markup regrouping is needed. Mobile-first: the base rule
   immediately below is the single-column stack (each field/area on its
   own row, in DOM order); the 768px breakpoint after it switches to the
   two-column desktop grouping — the same breakpoint this stylesheet
   already uses elsewhere. */
.ai-action-controls-row {
  display: grid;
  grid-template-columns: 1fr;
  grid-template-areas:
    "kap"
    "approach"
    "instruction"
    "actions";
  gap: 0.65rem;
  align-items: start;
}

@media (min-width: 768px) {
  .ai-action-controls-row {
    grid-template-columns: 1fr 1fr;
    grid-template-areas:
      "kap approach"
      "instruction instruction"
      "actions actions";
    gap: 0.75rem 1rem;
    align-items: end;
  }
}

.ai-action-controls-row .generate-item-field {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  /* Grid items default to min-width:auto, the exact same content-floored
     shrink-resistance flex items have — an unusually long KAP label must
     not force its own cell, or the row, wider than its grid track.
     min-width:0 lets it shrink to the track's actual width instead; the
     select/trigger's own width:100% (below) plus text-overflow/wrapping
     then contain the control itself rather than overflow. */
  min-width: 0;
}

.ai-action-controls-row .generate-item-field.kap-picker-field {
  grid-area: kap;
}

.ai-action-controls-row .generate-item-field.approach-picker-field {
  grid-area: approach;
}

.ai-action-controls-row .generate-item-field-wide {
  grid-area: instruction;
}

/* The final action row: Generate Item pinned to the trailing edge on
   desktop, with the status message — flex: 1 1 auto — filling the space
   ahead of it, so the status text appearing/disappearing/changing length
   never shifts the button's own position. row-reverse is enough to
   achieve that without reordering the markup: the button is first in DOM
   order, so reversing the main axis places it at the trailing edge while
   the status paragraph fills what's left, still reading left-to-right.
   On mobile (this base rule, single column) the two simply stack in
   their existing DOM order — button first, full width, status wrapping
   beneath it — exactly the approved narrow-viewport order. */
.ai-action-controls-row .generate-item-actions {
  grid-area: actions;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  min-width: 0;
}

.ai-action-controls-row .generate-item-actions button {
  width: 100%;
}

@media (min-width: 768px) {
  .ai-action-controls-row .generate-item-actions {
    flex-direction: row-reverse;
    align-items: center;
    gap: 0.75rem;
  }

  .ai-action-controls-row .generate-item-actions button {
    width: auto;
    flex: 0 0 auto;
  }

  .ai-action-controls-row .generate-item-actions #competency-generate-item-status {
    flex: 1 1 auto;
    min-width: 0;
  }
}

/* M11-09F acceptance refinement: the KAP picker — replaces a native
   <select> (see index.html's own comment for why). .kap-picker is the
   trigger's positioning context; the listbox is one implementation for
   both desktop and mobile, no separate components — its width already
   inherits from its grid cell's own width (.ai-action-controls-row above
   — full row on mobile, half the row on desktop), so no extra breakpoint
   is needed here for that. Same popover visual language as the existing
   #app-menu dropdown (shadow, z-index) rather than inventing a second
   one. */
.kap-picker {
  position: relative;
}

.kap-picker-trigger {
  width: 100%;
  text-align: left;
  font: inherit;
  padding: 0.4rem 1.75rem 0.4rem 0.5rem;
  border: 1px solid #d7dbe0;
  border-radius: 4px;
  background: #fff;
  cursor: pointer;
  position: relative;
  overflow-wrap: break-word;
}

/* A plain CSS chevron — no icon asset, matching this stylesheet's
   existing preference for CSS-only decorative marks (e.g. the tree's own
   disclosure triangles) over adding image/icon dependencies. */
.kap-picker-trigger::after {
  content: '';
  position: absolute;
  right: 0.65rem;
  top: 45%;
  width: 0.4rem;
  height: 0.4rem;
  border-right: 2px solid #5a6270;
  border-bottom: 2px solid #5a6270;
  transform: translateY(-50%) rotate(45deg);
  pointer-events: none;
}

.kap-picker-trigger:disabled {
  cursor: not-allowed;
  opacity: 0.6;
}

/* Opens downward by default; openKapPicker()'s positioning check adds
   .kap-picker-listbox-above only when there is genuinely not enough
   viewport space below the trigger (Region C sits near the bottom of the
   Competency Workspace, so this is the expected common case on short
   mobile viewports, not a rare edge case). max-height + overflow-y
   guards against a KAM with many KAPs regardless of placement. */
.kap-picker-listbox {
  position: absolute;
  top: calc(100% + 0.25rem);
  left: 0;
  right: 0;
  max-height: 16rem;
  overflow-y: auto;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-base);
  background: var(--color-surface);
  box-shadow: 0 4px 12px rgba(18, 63, 62, 0.12);
  z-index: 40;
}

.kap-picker-listbox-above {
  top: auto;
  bottom: calc(100% + 0.25rem);
}

.kap-picker-option {
  padding: 0.5rem 0.6rem;
  font-size: 0.9rem;
  /* Labels may wrap — never clipped, never forced to a single line (the
     opposite treatment from e.g. .assessment-item-row-stem, which is
     deliberately single-line elsewhere in this app; a picker option is
     not a space-constrained summary row). */
  white-space: normal;
  overflow-wrap: break-word;
  cursor: pointer;
}

.kap-picker-option:hover,
.kap-picker-option:focus-visible {
  background: var(--altras-teal-50);
  outline: none;
}

.kap-picker-option[aria-selected="true"] {
  background: var(--altras-teal-100);
  font-weight: 600;
}

/* M9-05B: read-only Item Number label. M12-03: relocated into the
   compact Item Navigation Bar (alongside #question-lifecycle-bar) — the
   stacking margin below it no longer applies there. M12-09: the
   Navigation Bar's primary visual identity — larger and semibold,
   clearly the dominant of the two identity lines (previously, backwards,
   the smaller/muted one) — deliberately short of a page-title size (see
   --font-size-section-heading, used elsewhere for real headings). Same
   persisted itemNumber, same "hidden entirely for a legacy Item" rule
   below; typography only. */
#item-number-display {
  margin: 0;
  font-size: 1rem;
  font-weight: 600;
  color: #1b1f24;
}

.ai-action-controls button {
  align-self: flex-start;
  padding: 0.5rem 1rem;
  border: 1px solid #2952cc;
  border-radius: 4px;
  background: #2952cc;
  color: #fff;
  cursor: pointer;
}

.ai-action-controls button:disabled {
  cursor: not-allowed;
  opacity: 0.6;
}

/* AI Request Inspector — temporary Admin/development UX, not final design */

#ai-request-inspector-tabs {
  display: flex;
  gap: 0.5rem;
  margin: 1rem 0;
  border-bottom: 1px solid #d7dbe0;
}

.ai-request-inspector-tab-button {
  border: none;
  background: none;
  padding: 0.5rem 0.75rem;
  cursor: pointer;
  color: #5a6270;
  border-bottom: 2px solid transparent;
}

.ai-request-inspector-tab-button.selected {
  color: #1b1f24;
  border-bottom-color: #2952cc;
  font-weight: 600;
}

.ai-request-inspector-tab-panel {
  display: flex;
  flex-direction: column;
  min-height: 0;
}

.ai-request-inspector-tab-panel[hidden] {
  display: none;
}

#ai-request-inspector-template-status {
  margin: 0 0 0.5rem;
  font-size: 0.9rem;
}

.ai-request-inspector-error-text {
  color: #b3261e;
}

/* M12-06: relocated from a stacked block inside the Item Element
   Section's Edit mode to a flex sibling on the right of the Item Action
   Button Bar (see #item-action-bar above) — margin-bottom dropped since
   it no longer stacks above anything; flex: 0 0 auto keeps it compact
   and, combined with #item-action-bar's own justify-content:
   space-between, it never reserves width when empty (idle state renders
   an empty string — see SAVE_STATE_LABELS.idle). */
#working-copy-save-status {
  flex: 0 0 auto;
  margin: 0;
  font-size: 0.9rem;
  color: #5a6270;
}

#working-copy-save-status[data-state="error"] {
  color: #b3261e;
}

#generation-model-control {
  margin: 1rem 0;
}

#generation-model-status {
  margin: 0.25rem 0 0;
  font-size: 0.9rem;
  color: #5a6270;
}

#generation-model-status[data-state="error"] {
  color: #b3261e;
}

#ai-request-inspector-template-editor,
#ai-request-inspector-resolved-request-editor,
#ai-request-inspector-provider-request-editor,
#ai-request-inspector-raw-provider-response-editor {
  height: 360px;
}

#ai-request-inspector-template-actions {
  display: flex;
  justify-content: flex-end;
  gap: 0.75rem;
  margin-top: 0.75rem;
}

#ai-request-inspector-template-actions button {
  padding: 0.5rem 1rem;
  border: 1px solid #d7dbe0;
  border-radius: 4px;
  background: #f0f0f2;
  cursor: pointer;
}

/* button# (not just #) matches the specificity of
   "#ai-request-inspector-template-actions button" so this rule's later
   source position wins the cascade, instead of being silently overridden
   by the shared button rule's grey background. */
button#ai-request-inspector-save-button {
  background: #2952cc;
  border-color: #2952cc;
  color: #fff;
}

#ai-request-inspector-template-actions button:disabled {
  cursor: not-allowed;
  opacity: 0.6;
}
