/* brand-authoring.css
   Brand Authoring v1 + v2 NUCLEAR flow surface styles.
   Step 7a ships the upload-card styles (.ba-upload, .ba-drop-zone,
   .ba-preview, .ba-error). Description-card, variant-card, and lock-card
   styles land at Steps 7b through 7d on top of the same prefix.
   Step 7.6 adds the shared card-header chrome (.ba-card-header,
   .ba-back-link, .ba-card-title) and the .ba-async-spinner block used
   by card (a) during the uploading stage.

   V2 NUCLEAR (this revision) adds:
     .ba-stage                    persistent playing space for every step
     .ba-stage__card              base for each step card mounted inside
     .ba-stage__card.is-entering  enter animation (240ms ease-out)
     .ba-stage__card.is-leaving   leave animation (200ms ease-in)
     .ba-stage__orb               corner orb slot (visible while voice plays)
     .ba-desc__summary-grid       summary cards for each description layer
     .ba-logo-preview             miniature dashboard with the logo swapped in
   Consumes L1 spacing + L3 ops-* tokens. */

/* ===========================================================================
   V2 NUCLEAR stage. Single persistent .ba-stage anchors every step card so
   the operator never scrolls between steps. Cards mount inside .ba-stage
   with coordinated enter and leave choreography (Fix 2). The orb appears
   in the corner during voice playback so the operator sees Orbi presenting.
   =========================================================================== */

/* Per-step max-width override. The default .ops-stage cap (720px) works
   for upload, describe, variant, and lock; the V4 polish step renders
   two dense panes that need more breathing room, so when the flow
   mounts the polish card it stamps data-step="polish" on .ba-stage and
   this :has() rule widens the ancestor .ops-stage to the wide token.
   Other steps clear the dataset and the stage falls back to the narrow
   default. Transition lives on .ops-stage itself in boot.css so the
   width animates between steps rather than snapping. */
.ops-stage:has(.ba-stage[data-step="polish"]) {
  max-width: var(--ops-layout-max-width-step-wide);
}

.ba-stage {
  position: relative;
  display: block;
  width: 100%;
  min-height: 320px;
  isolation: isolate;
}

.ba-stage__card-slot {
  position: relative;
  width: 100%;
  display: grid;
  /* Single-cell grid lets enter and leave overlap in the same coordinate
     space without one card pushing the other down the page. */
  grid-template-areas: "stack";
}

/* Every card mounted inside the stage stacks into the single grid cell so
   the swap animations overlap. Disable the default .ops-card mount
   animation since the stage owns motion now. */
.ba-stage__card.ops-card {
  grid-area: stack;
  animation: none;
  opacity: 0;
  transform: none;
  will-change: opacity, transform;
}

.ba-stage__card.is-entering {
  animation: ba-stage-enter var(--ops-motion-duration-card-fast, 240ms) var(--ops-motion-curve) forwards;
}

.ba-stage__card.is-leaving {
  animation: ba-stage-leave var(--ops-motion-duration-card-fast, 200ms) var(--ops-motion-curve-snap, ease-in) forwards;
}

@keyframes ba-stage-enter {
  from { opacity: 0; transform: scale(0.97); }
  to   { opacity: 1; transform: scale(1); }
}

@keyframes ba-stage-leave {
  from { opacity: 1; transform: translateY(0); }
  to   { opacity: 0; transform: translateY(-16px); }
}

@media (prefers-reduced-motion: reduce) {
  .ba-stage__card.is-entering,
  .ba-stage__card.is-leaving {
    animation: none;
    opacity: 1;
    transform: none;
  }
}

/* Corner orb. Lazily mounted by brand-authoring-flow.js; takes up
   --ops-orb-size-sm worth of space in the top-right of the stage. Hidden
   by default, fades in while voice is active (data-active="true").
   pointer-events: none so the orb does not eat clicks on the underlying
   card. */
.ba-stage__orb {
  position: absolute;
  top: calc(var(--space-md) * -1);
  right: calc(var(--space-md) * -1);
  width: 96px;
  height: 96px;
  z-index: 2;
  opacity: 0;
  transform: scale(0.85);
  transition:
    opacity var(--ops-motion-duration-micro) var(--ops-motion-curve),
    transform var(--ops-motion-duration-micro) var(--ops-motion-curve);
  pointer-events: none;
}

.ba-stage__orb[data-active="true"] {
  opacity: 1;
  transform: scale(1);
}

.ba-stage__orb .ops-orb__canvas {
  border-radius: 50%;
}

@media (max-width: 640px) {
  .ba-stage__orb {
    top: calc(var(--space-sm) * -1);
    right: calc(var(--space-sm) * -1);
    width: 72px;
    height: 72px;
  }
}

/* ===========================================================================
   Shared card header (Step 7.6).
   Back link top-left as a text button; card title underneath. Card title
   speaks with personality so font is display-weight at title size.
   =========================================================================== */

.ba-card-header {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);
  width: 100%;
}

.ba-back-link {
  align-self: flex-start;
  background: transparent;
  border: 0;
  padding: 4px 0;
  margin: 0;
  font-family: var(--ops-font-family-body);
  font-size: var(--ops-font-size-small);
  font-weight: var(--ops-font-weight-body);
  color: var(--ops-fg-secondary);
  letter-spacing: 0.02em;
  cursor: pointer;
  transition: color var(--ops-motion-duration-micro) var(--ops-motion-curve);
}

.ba-back-link:hover:not(:disabled),
.ba-back-link:focus-visible:not(:disabled) {
  color: var(--ops-fg-link);
  outline: none;
  text-decoration: underline;
}

.ba-back-link:disabled {
  opacity: 0.5;
  cursor: not-allowed;
  pointer-events: none;
}

.ba-card-title {
  margin: 0;
  font-family: var(--ops-font-family-display);
  font-size: var(--ops-font-size-title);
  font-weight: var(--ops-font-weight-display);
  line-height: 1.15;
  letter-spacing: var(--ops-letter-spacing-title, -0.01em);
  color: var(--ops-fg-primary);
  text-align: center;
}

/* ===========================================================================
   Async spinner block shared across cards (card (a) uploading stage; can
   be reused by lock locking stage if we want a flush replacement of body).
   =========================================================================== */
.ba-async-spinner {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-sm);
  padding: var(--space-2xl) var(--space-md);
  text-align: center;
}

.ba-async-spinner__sub {
  margin: 0;
  font-size: var(--ops-font-size-small);
  color: var(--ops-fg-secondary);
}

.ba-upload {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}

/* ===========================================================================
   Tenant-required placeholder. Surfaced by bootstrap.js when the operator
   lens is missing or incomplete, in place of the brand-authoring flow. The
   card explains why authoring is gated and how to wire the lens.
   =========================================================================== */
.ba-tenant-required {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-md);
  text-align: center;
}

.ba-tenant-required__body {
  margin: 0;
  max-width: 42ch;
  font-size: var(--ops-font-size-body);
  color: var(--ops-fg-secondary);
  line-height: 1.5;
}

.ba-tenant-required__hint {
  display: grid;
  grid-template-columns: auto 1fr;
  column-gap: var(--space-sm);
  row-gap: var(--space-2xs);
  margin: 0;
  padding: var(--space-sm) var(--space-md);
  border-radius: var(--ops-card-radius-sm);
  background: rgba(255, 255, 255, 0.18);
  font-size: var(--ops-font-size-small);
  text-align: left;
}

.ba-tenant-required__hint dt {
  margin: 0;
  font-weight: var(--ops-font-weight-emphasis);
  color: var(--ops-fg-primary);
}

.ba-tenant-required__hint dd {
  margin: 0;
  font-family: var(--ops-font-family-mono, ui-monospace, SFMono-Regular, monospace);
  color: var(--ops-fg-secondary);
}

/* Drop zone. */
.ba-drop-zone {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-xs);
  padding: var(--space-xl) var(--space-md);
  min-height: 200px;
  border: 1.5px dashed var(--ops-card-border);
  border-radius: var(--ops-card-radius-sm);
  background: rgba(255, 255, 255, 0.18);
  text-align: center;
  cursor: pointer;
  transition:
    background var(--ops-motion-duration-micro) var(--ops-motion-curve),
    border-color var(--ops-motion-duration-micro) var(--ops-motion-curve),
    transform var(--ops-motion-duration-micro-fast) var(--ops-motion-curve);
}

.ba-drop-zone:hover,
.ba-drop-zone:focus-visible {
  background: rgba(255, 255, 255, 0.32);
  border-color: var(--ops-card-border-active);
  outline: none;
}

.ba-drop-zone[data-dragover="true"] {
  background: rgba(255, 255, 255, 0.48);
  border-color: var(--ops-card-border-active);
  border-style: solid;
  transform: scale(1.005);
}

.ba-drop-zone__primary {
  margin: 0;
  font-family: var(--ops-font-family-display);
  font-size: var(--ops-font-size-subtitle);
  font-weight: var(--ops-font-weight-emphasis);
  color: var(--ops-fg-primary);
}

.ba-drop-zone__secondary {
  margin: 0;
  font-size: var(--ops-font-size-small);
  color: var(--ops-fg-secondary);
}

.ba-error {
  margin: var(--space-xs) 0 0;
  color: var(--state-down-ink, #b04464);
  font-size: var(--ops-font-size-small);
  font-weight: var(--ops-font-weight-emphasis);
}

/* Stage gating. Step 7.6: idle > selected > uploading > error.
   uploading replaces card body entirely with the spinner block per the
   Step 7.6 loud-loading rule (no buttons floating next to the spinner). */
.ba-upload[data-stage="idle"] .ba-preview,
.ba-upload[data-stage="error"] .ba-preview,
.ba-upload[data-stage="uploading"] .ba-preview,
.ba-upload[data-stage="uploading"] .ba-drop-zone,
.ba-upload[data-stage="idle"] .ba-async-spinner,
.ba-upload[data-stage="selected"] .ba-async-spinner,
.ba-upload[data-stage="error"] .ba-async-spinner {
  display: none;
}

/* Preview pane. */
.ba-preview {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  align-items: center;
}

.ba-preview__img {
  max-width: 100%;
  max-height: 360px;
  border-radius: var(--ops-card-radius-sm);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
  object-fit: contain;
  background: var(--ops-field-input-bg, rgba(255,255,255,0.4));
}

.ba-preview__meta {
  display: flex;
  flex-direction: column;
  gap: var(--space-3xs);
  text-align: center;
  font-size: var(--ops-font-size-small);
  color: var(--ops-fg-secondary);
}

.ba-preview__meta p {
  margin: 0;
}

.ba-preview__name {
  font-weight: var(--ops-font-weight-emphasis);
  color: var(--ops-fg-primary);
}

.ba-preview__path {
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: var(--ops-font-size-micro);
  color: var(--ops-fg-tertiary);
  word-break: break-all;
}

/* ===========================================================================
   Card (b) description editor (.ba-desc family).
   Stages: loading > editing > error. Per-stage visibility via [data-stage].
   =========================================================================== */

.ba-desc {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
  min-height: 240px;
}

/* Stage gating. Step 7.6 reverted the 7.5 sub-stage split; the editor
   shows all six accordions in one editing stage. */
.ba-desc[data-stage="loading"] .ba-desc__editor,
.ba-desc[data-stage="loading"] .ba-desc__error,
.ba-desc[data-stage="editing"] .ba-desc__loading,
.ba-desc[data-stage="editing"] .ba-desc__error,
.ba-desc[data-stage="error"]   .ba-desc__loading,
.ba-desc[data-stage="error"]   .ba-desc__editor {
  display: none;
}

/* Loading. */
.ba-desc__loading {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-sm);
  padding: var(--space-2xl) var(--space-md);
  text-align: center;
}

.ba-desc__spinner {
  width: 36px;
  height: 36px;
  border: 3px solid rgba(120, 100, 200, 0.18);
  border-top-color: var(--ops-card-border-active);
  border-radius: 50%;
  animation: ba-desc-spin 900ms linear infinite;
}

@keyframes ba-desc-spin {
  to { transform: rotate(360deg); }
}

/* .ba-desc__loading-text removed at Step 7.6 (the primary loading line
   moved into the card header title "Let me cook it up..."); only the
   sub-line stays inside the loading body. */
.ba-desc__loading-sub {
  margin: 0;
  font-size: var(--ops-font-size-small);
  color: var(--ops-fg-secondary);
  max-width: 540px;
}

/* Error. */
.ba-desc__error {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-md);
  padding: var(--space-2xl) var(--space-md);
  text-align: center;
}

.ba-desc__error-msg {
  margin: 0;
  color: var(--state-down-ink, #b04464);
  font-weight: var(--ops-font-weight-emphasis);
  font-size: var(--ops-font-size-body);
  max-width: 540px;
  word-break: break-word;
}

/* Editor. */
.ba-desc__editor {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}

/* ===========================================================================
   V2 NUCLEAR summary grid (.ba-desc__summary-grid + .ba-desc__layer).
   Replaces the V1 stacked-accordion editor: each layer renders as a
   compact summary card showing layer name + one-line summary. Click any
   card to expand and edit the full prose. Six cards lay out in a
   responsive grid so the operator scans visually rather than scrolling
   through six prose blocks. The voice client narrates over the cards
   while they animate in (staggered per --ba-layer-index). The legacy
   .ba-desc__accordion rules below stay intact for any consumer that
   imports them directly (the editor itself uses .ba-desc__layer).
   =========================================================================== */

.ba-desc__summary-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: var(--space-sm);
}

.ba-desc__layer {
  background: var(--ops-card-bg);
  border: 1px solid var(--ops-card-border);
  border-radius: var(--ops-card-radius-sm);
  box-shadow: var(--ops-card-shadow);
  backdrop-filter: blur(var(--ops-card-blur)) saturate(var(--ops-card-saturation));
  -webkit-backdrop-filter: blur(var(--ops-card-blur)) saturate(var(--ops-card-saturation));
  overflow: hidden;
  opacity: 0;
  transform: translateY(8px);
  animation: ba-desc-layer-in 320ms var(--ops-motion-curve) forwards;
  animation-delay: calc(var(--ba-layer-index, 0) * 80ms + 100ms);
  transition:
    background var(--ops-motion-duration-micro) var(--ops-motion-curve),
    border-color var(--ops-motion-duration-micro) var(--ops-motion-curve);
}

@keyframes ba-desc-layer-in {
  to { opacity: 1; transform: translateY(0); }
}

@media (prefers-reduced-motion: reduce) {
  .ba-desc__layer {
    animation: none;
    opacity: 1;
    transform: none;
  }
}

.ba-desc__layer[open] {
  background: var(--ops-card-bg-hover);
  grid-column: 1 / -1;
}

.ba-desc__layer-summary {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);
  padding: var(--space-sm) var(--space-md);
  cursor: pointer;
  list-style: none;
  user-select: none;
  -webkit-user-select: none;
}

.ba-desc__layer-summary::-webkit-details-marker { display: none; }
.ba-desc__layer-summary::marker { content: ''; }

.ba-desc__layer-summary:hover,
.ba-desc__layer-summary:focus-visible {
  background: rgba(255, 255, 255, 0.18);
  outline: none;
}

.ba-desc__layer-labelrow {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
}

.ba-desc__layer-label {
  flex: 1;
  font-family: var(--ops-font-family-display);
  font-size: var(--ops-font-size-small);
  font-weight: var(--ops-font-weight-emphasis);
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--ops-fg-secondary);
}

.ba-desc__layer[open] .ba-desc__layer-label {
  color: var(--ops-fg-primary);
}

.ba-desc__layer-chevron {
  width: 10px;
  height: 10px;
  border-right: 2px solid var(--ops-fg-secondary);
  border-bottom: 2px solid var(--ops-fg-secondary);
  transform: rotate(45deg);
  transition: transform var(--ops-motion-duration-micro) var(--ops-motion-curve);
  margin-bottom: 3px;
}

.ba-desc__layer[open] .ba-desc__layer-chevron {
  transform: rotate(-135deg);
  margin-bottom: -3px;
  border-color: var(--ops-fg-primary);
}

.ba-desc__layer-summary-line {
  margin: 0;
  font-size: var(--ops-font-size-small);
  color: var(--ops-fg-primary);
  line-height: 1.4;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.ba-desc__layer-body {
  padding: 0 var(--space-md) var(--space-md);
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);
}

/* ===========================================================================
   V2 NUCLEAR logo preview (.ba-logo-preview).
   Miniature teglo-dashboard layout with the operator logo swapped into the
   sidebar. Pure design tokens for chrome; the only color taken from the
   payload is the logo image itself.
   =========================================================================== */

.ba-logo-preview {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}

.ba-logo-preview__subtitle {
  margin: 0;
  font-size: var(--ops-font-size-small);
  color: var(--ops-fg-secondary);
  text-align: center;
}

.ba-logo-preview__mini {
  display: grid;
  grid-template-columns: 140px 1fr;
  min-height: 220px;
  background: rgba(255, 255, 255, 0.55);
  border-radius: var(--ops-card-radius-sm);
  box-shadow:
    0 1px 2px rgba(40, 30, 80, 0.05),
    0 16px 36px rgba(40, 30, 80, 0.08);
  overflow: hidden;
  border: 1px solid var(--ops-card-border);
}

.ba-logo-preview__sidebar {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
  padding: var(--space-md);
  background: rgba(255, 255, 255, 0.85);
  border-right: 1px solid var(--ops-card-border);
}

.ba-logo-preview__sidebar-logo {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 56px;
  padding: var(--space-xs) var(--space-sm);
  background: rgba(255, 255, 255, 0.7);
  border-radius: var(--ops-card-radius-sm);
}

.ba-logo-preview__sidebar-logo-img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}

.ba-logo-preview__sidebar-nav {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
}

.ba-logo-preview__nav-item {
  font-family: var(--ops-font-family-body);
  font-size: var(--ops-font-size-small);
  color: var(--ops-fg-secondary);
  padding: var(--space-2xs) var(--space-xs);
  border-radius: 6px;
}

.ba-logo-preview__nav-item:first-child {
  background: rgba(120, 100, 200, 0.10);
  color: var(--ops-fg-primary);
  font-weight: var(--ops-font-weight-emphasis);
}

.ba-logo-preview__main {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
  padding: var(--space-md);
  background: rgba(255, 255, 255, 0.55);
}

.ba-logo-preview__topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-bottom: var(--space-xs);
  border-bottom: 1px solid var(--ops-card-border);
}

.ba-logo-preview__crumbs {
  font-size: var(--ops-font-size-small);
  color: var(--ops-fg-secondary);
}

.ba-logo-preview__avatar {
  display: inline-block;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: rgba(120, 100, 200, 0.30);
}

.ba-logo-preview__tiles {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-sm);
}

.ba-logo-preview__tile {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);
  padding: var(--space-sm);
  background: rgba(255, 255, 255, 0.85);
  border-radius: 10px;
  border: 1px solid var(--ops-card-border);
}

.ba-logo-preview__tile-label {
  font-size: var(--ops-font-size-micro);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--ops-fg-tertiary);
}

.ba-logo-preview__tile-value {
  font-family: var(--ops-font-family-display);
  font-size: var(--ops-font-size-subtitle);
  font-weight: var(--ops-font-weight-emphasis);
  color: var(--ops-fg-primary);
}

@media (max-width: 640px) {
  .ba-logo-preview__mini {
    grid-template-columns: 1fr;
  }
  .ba-logo-preview__sidebar {
    border-right: 0;
    border-bottom: 1px solid var(--ops-card-border);
  }
  .ba-logo-preview__tiles {
    grid-template-columns: 1fr;
  }
}

/* Legacy accordion rules (kept for any external consumer importing
   .ba-desc__accordion). The current editor renders .ba-desc__layer.
   =========================================================================== */
.ba-desc__accordion {
  background: var(--ops-card-bg);
  border: 1px solid var(--ops-card-border);
  border-radius: var(--ops-card-radius-sm);
  box-shadow: var(--ops-card-shadow);
  backdrop-filter: blur(var(--ops-card-blur)) saturate(var(--ops-card-saturation));
  -webkit-backdrop-filter: blur(var(--ops-card-blur)) saturate(var(--ops-card-saturation));
  overflow: hidden;
  transition:
    background var(--ops-motion-duration-micro) var(--ops-motion-curve),
    border-color var(--ops-motion-duration-micro) var(--ops-motion-curve);
}

.ba-desc__accordion[open] {
  background: var(--ops-card-bg-hover);
}

.ba-desc__accordion-summary {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  padding: var(--space-sm) var(--space-md);
  cursor: pointer;
  list-style: none;
  user-select: none;
  -webkit-user-select: none;
}

/* Hide the default disclosure triangle in webkit and gecko. */
.ba-desc__accordion-summary::-webkit-details-marker { display: none; }
.ba-desc__accordion-summary::marker { content: ''; }

.ba-desc__accordion-summary:hover,
.ba-desc__accordion-summary:focus-visible {
  background: rgba(255, 255, 255, 0.18);
  outline: none;
}

.ba-desc__accordion-label {
  flex: 1;
  font-family: var(--ops-font-family-display);
  font-size: var(--ops-font-size-small);
  font-weight: var(--ops-font-weight-emphasis);
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--ops-fg-secondary);
}

.ba-desc__accordion[open] .ba-desc__accordion-label {
  color: var(--ops-fg-primary);
}

.ba-desc__accordion-chevron {
  width: 10px;
  height: 10px;
  border-right: 2px solid var(--ops-fg-secondary);
  border-bottom: 2px solid var(--ops-fg-secondary);
  transform: rotate(45deg);
  transition: transform var(--ops-motion-duration-micro) var(--ops-motion-curve);
  margin-bottom: 3px;
}

.ba-desc__accordion[open] .ba-desc__accordion-chevron {
  transform: rotate(-135deg);
  margin-bottom: -3px;
  border-color: var(--ops-fg-primary);
}

.ba-desc__accordion-body {
  padding: 0 var(--space-md) var(--space-md);
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);
}

.ba-desc__type-badge {
  display: inline-flex;
  align-items: center;
  padding: 2px 8px;
  border-radius: 999px;
  background: rgba(120, 100, 200, 0.12);
  color: var(--ops-fg-link);
  font-size: var(--ops-font-size-micro);
  font-weight: var(--ops-font-weight-emphasis);
  letter-spacing: 0;
  text-transform: none;
}

.ba-desc__textarea {
  width: 100%;
  box-sizing: border-box;
  padding: var(--space-sm);
  background: rgba(255, 255, 255, 0.32);
  border: 1px solid var(--ops-card-border);
  border-radius: var(--ops-card-radius-sm);
  color: var(--ops-fg-primary);
  font-family: var(--ops-font-family-body);
  font-size: var(--ops-font-size-body);
  line-height: 1.45;
  resize: vertical;
  transition:
    background var(--ops-motion-duration-micro) var(--ops-motion-curve),
    border-color var(--ops-motion-duration-micro) var(--ops-motion-curve);
}

.ba-desc__textarea:hover {
  background: rgba(255, 255, 255, 0.44);
}

.ba-desc__textarea:focus {
  background: rgba(255, 255, 255, 0.55);
  border-color: var(--ops-card-border-active);
  outline: none;
}

.ba-desc__textarea[data-mono="true"] {
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: var(--ops-font-size-small);
  line-height: 1.5;
  white-space: pre;
}

.ba-desc__field-error {
  margin: 0;
  color: var(--state-down-ink, #b04464);
  font-size: var(--ops-font-size-small);
  font-weight: var(--ops-font-weight-emphasis);
}

/* V4 description editor enrichments: per-layer helper line + example seed
   button. Both flow through ops-* tokens so the chrome stays inside the
   ceremonial overlay. */
.ba-desc__layer-helper {
  margin: 0 0 var(--space-2xs);
  font-size: var(--ops-font-size-small);
  color: var(--ops-fg-secondary);
  line-height: 1.45;
}

.ba-desc__layer-seed-row {
  display: flex;
  justify-content: flex-end;
  margin-top: var(--space-2xs);
}

.ba-desc__layer-seed-btn {
  background: transparent;
  border: 1px solid var(--ops-card-border);
  padding: var(--space-3xs) var(--space-sm);
  border-radius: var(--radius-pill);
  font-family: var(--ops-font-family-body);
  font-size: var(--ops-font-size-micro);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ops-fg-secondary);
  cursor: pointer;
  transition:
    background var(--ops-motion-duration-micro) var(--ops-motion-curve),
    color var(--ops-motion-duration-micro) var(--ops-motion-curve),
    border-color var(--ops-motion-duration-micro) var(--ops-motion-curve);
}

.ba-desc__layer-seed-btn:hover,
.ba-desc__layer-seed-btn:focus-visible {
  background: var(--ops-card-bg-hover);
  color: var(--ops-fg-primary);
  border-color: var(--ops-card-border-active);
  outline: none;
}

/* Step 7.5's footer-side Back override is gone at 7.6: Back moved to the
   card header (top-left text link) so every card has a consistent shape.
   The secondary Clear lock on card (d) still wants left alignment, which
   is handled inside the lock CSS block below. */

/* ===========================================================================
   Card (c) variant (.ba-variant family).
   Three palette sub-cards in a responsive grid. Each sub-card exposes
   --ba-accent-light and --ba-accent-dark as custom properties; samples
   below consume them through var() references.
   =========================================================================== */

.ba-variant {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}

/* .ba-variant__hint removed at Step 7.6 (the "Pick the palette..." hint
   paragraph was replaced by the card title "Pick an accent" in the
   shared header chrome). */

.ba-variant__source {
  margin: 0;
  font-size: var(--ops-font-size-small);
  color: var(--ops-fg-secondary);
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2xs);
  align-items: baseline;
}

.ba-variant__source-hex {
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: var(--ops-font-size-small);
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--ops-field-input-bg, rgba(255,255,255,0.4));
  color: var(--ops-fg-primary);
}

/* Grid of three sub-cards. Auto-fit collapses to a single column at
   narrow widths; at typical card-slot widths the three sit side by side. */
.ba-variant__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: var(--space-md);
}

/* Sub-card. */
.ba-variant__card {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  padding: var(--space-md);
  background: rgba(255, 255, 255, 0.32);
  border: 1.5px solid var(--ops-card-border);
  border-radius: var(--ops-card-radius-sm);
  cursor: pointer;
  transition:
    background var(--ops-motion-duration-micro) var(--ops-motion-curve),
    border-color var(--ops-motion-duration-micro) var(--ops-motion-curve),
    transform var(--ops-motion-duration-micro-fast) var(--ops-motion-curve),
    box-shadow var(--ops-motion-duration-micro) var(--ops-motion-curve);
}

.ba-variant__card:hover,
.ba-variant__card:focus-visible {
  background: rgba(255, 255, 255, 0.46);
  border-color: var(--ba-accent-light);
  outline: none;
  transform: translateY(-1px);
}

.ba-variant__card[data-selected="true"] {
  background: rgba(255, 255, 255, 0.6);
  border-color: var(--ba-accent-light);
  border-width: 2px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.1);
  transform: translateY(-2px);
}

.ba-variant__sub-header {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.ba-variant__sub-title {
  margin: 0;
  font-family: var(--ops-font-family-display);
  font-size: var(--ops-font-size-body);
  font-weight: var(--ops-font-weight-emphasis);
  color: var(--ops-fg-primary);
}

.ba-variant__sub-strategy {
  margin: 0;
  font-size: var(--ops-font-size-micro);
  color: var(--ops-fg-secondary);
}

/* Swatches: side-by-side, sharing a rounded rectangle. */
.ba-variant__swatches {
  display: grid;
  grid-template-columns: 1fr 1fr;
  height: 56px;
  border-radius: 10px;
  overflow: hidden;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.06);
}

.ba-variant__swatch--light {
  background: var(--ba-accent-light);
}

.ba-variant__swatch--dark {
  background: var(--ba-accent-dark);
}

/* Samples. */
.ba-variant__samples {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
}

.ba-variant__sample-btn {
  border: 0;
  padding: 8px 14px;
  border-radius: var(--radius-md, 8px);
  background: var(--ba-accent-light);
  color: var(--n-0, #ffffff);
  font-family: var(--ops-font-family-display);
  font-size: var(--ops-font-size-small);
  font-weight: var(--ops-font-weight-emphasis);
  cursor: default;
  align-self: flex-start;
}

.ba-variant__sample-surface {
  padding: 8px 12px;
  border-left: 3px solid var(--ba-accent-light);
  background: rgba(255, 255, 255, 0.45);
  border-radius: var(--radius-xs, 4px);
  font-size: var(--ops-font-size-small);
  color: var(--ops-fg-primary);
}

.ba-variant__sample-text {
  margin: 0;
  font-size: var(--ops-font-size-small);
  color: var(--ops-fg-primary);
}

.ba-variant__sample-text-accent {
  color: var(--ba-accent-light);
  font-weight: var(--ops-font-weight-emphasis);
}

/* Hex labels. */
.ba-variant__hexes {
  display: flex;
  gap: var(--space-xs);
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: var(--ops-font-size-micro);
  color: var(--ops-fg-tertiary);
}

.ba-variant__hexes code {
  padding: 2px 6px;
  background: var(--ops-field-input-bg, rgba(255,255,255,0.4));
  border-radius: var(--radius-xs, 4px);
}

/* ===========================================================================
   Card (d) lock (.ba-lock family).
   Stages: review > locking > locked > cleared > error. Per-stage visibility
   via [data-stage]. Error stage keeps the review block visible so the
   operator sees the context they were trying to lock.
   =========================================================================== */

.ba-lock {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
  min-height: 240px;
}

/* review: only the review block visible. */
.ba-lock[data-stage="review"] .ba-lock__locking,
.ba-lock[data-stage="review"] .ba-lock__locked,
.ba-lock[data-stage="review"] .ba-lock__cleared,
.ba-lock[data-stage="review"] .ba-lock__error,
/* locking: only the spinner. */
.ba-lock[data-stage="locking"] .ba-lock__review,
.ba-lock[data-stage="locking"] .ba-lock__locked,
.ba-lock[data-stage="locking"] .ba-lock__cleared,
.ba-lock[data-stage="locking"] .ba-lock__error,
/* locked: only the confirmation. */
.ba-lock[data-stage="locked"] .ba-lock__review,
.ba-lock[data-stage="locked"] .ba-lock__locking,
.ba-lock[data-stage="locked"] .ba-lock__cleared,
.ba-lock[data-stage="locked"] .ba-lock__error,
/* cleared: only the cleared message. */
.ba-lock[data-stage="cleared"] .ba-lock__review,
.ba-lock[data-stage="cleared"] .ba-lock__locking,
.ba-lock[data-stage="cleared"] .ba-lock__locked,
.ba-lock[data-stage="cleared"] .ba-lock__error,
/* error: review block stays visible above the error message. */
.ba-lock[data-stage="error"] .ba-lock__locking,
.ba-lock[data-stage="error"] .ba-lock__locked,
.ba-lock[data-stage="error"] .ba-lock__cleared {
  display: none;
}

/* Section panels (lens, variant) inside review. */
.ba-lock__section {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  padding: var(--space-md);
  background: rgba(255, 255, 255, 0.32);
  border: 1px solid var(--ops-card-border);
  border-radius: var(--ops-card-radius-sm);
}

.ba-lock__section-title {
  margin: 0;
  font-family: var(--ops-font-family-display);
  font-size: var(--ops-font-size-small);
  font-weight: var(--ops-font-weight-emphasis);
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--ops-fg-secondary);
}

/* Key/value list for lens + palette details. */
.ba-lock__lens,
.ba-lock__palette-list {
  margin: 0;
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: var(--space-2xs) var(--space-md);
  font-size: var(--ops-font-size-small);
}

.ba-lock__kv-key {
  margin: 0;
  color: var(--ops-fg-secondary);
}

.ba-lock__kv-value {
  margin: 0;
  color: var(--ops-fg-primary);
  word-break: break-all;
}

.ba-lock__kv-value[data-mono="true"] {
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: var(--ops-font-size-small);
}

/* Variant swatches in the review. */
.ba-lock__swatches {
  display: flex;
  gap: var(--space-xs);
}

.ba-lock__swatch {
  display: inline-block;
  width: 48px;
  height: 48px;
  border-radius: 10px;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.06);
}

/* V2 brand authoring: logo block inside the review. Thumb on the left,
   filename + provenance line on the right. Mirrors .ba-lock__section
   chrome so it sits in the review stack alongside lens + variant. */
.ba-lock__section--logo .ba-lock__logo-body {
  display: flex;
  gap: var(--space-md);
  align-items: center;
}

.ba-lock__logo-thumb {
  width: 72px;
  height: 72px;
  object-fit: contain;
  border-radius: var(--ops-card-radius-sm);
  background: rgba(255, 255, 255, 0.5);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
  flex-shrink: 0;
}

.ba-lock__logo-meta {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);
  min-width: 0;
}

.ba-lock__logo-name {
  margin: 0;
  font-weight: var(--ops-font-weight-emphasis);
  font-size: var(--ops-font-size-small);
  color: var(--ops-fg-primary);
  word-break: break-all;
}

.ba-lock__logo-provenance {
  margin: 0;
  font-size: var(--ops-font-size-small);
  color: var(--ops-fg-secondary);
}

/* Provenance line. */
.ba-lock__provenance {
  margin: 0;
  padding: var(--space-sm) var(--space-md);
  background: rgba(255, 255, 255, 0.22);
  border-left: 3px solid var(--ops-card-border-active);
  border-radius: 0 var(--ops-card-radius-sm) var(--ops-card-radius-sm) 0;
  font-size: var(--ops-font-size-small);
  color: var(--ops-fg-secondary);
}

/* Locking spinner block. Reuses .ba-desc__spinner keyframe. */
.ba-lock__locking {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-sm);
  padding: var(--space-2xl) var(--space-md);
  text-align: center;
}

.ba-lock__locking-text {
  margin: 0;
  font-family: var(--ops-font-family-display);
  font-size: var(--ops-font-size-body);
  color: var(--ops-fg-primary);
}

/* Locked + cleared confirmations.
   V2 brand authoring: locked stage carries the hero "Open Tenant
   Dashboard" CTA plus a Push to live stub and de-emphasized text links.
   Cleared stage stays minimal: just the confirmation + the footer
   Start over CTA. */
.ba-lock__locked,
.ba-lock__cleared {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-xs);
  padding: var(--space-2xl) var(--space-md);
  text-align: center;
}

/* CTA block: the decisive single-button hero replacing V1's button mess. */
.ba-lock__cta-block {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2xs);
  margin: var(--space-lg) 0 var(--space-xs);
}

.ba-lock__open-dash-cta {
  min-width: 280px;
}

.ba-lock__cta-subtitle {
  margin: 0;
  font-size: var(--ops-font-size-small);
  color: var(--ops-fg-secondary);
  max-width: 420px;
}

.ba-lock__opened-banner {
  margin: var(--space-sm) 0 0;
  padding: var(--space-sm) var(--space-md);
  background: var(--state-healthy-tint, rgba(120, 180, 140, 0.12));
  border-left: 3px solid var(--state-healthy-ink, #5fa57a);
  border-radius: 0 var(--ops-card-radius-sm) var(--ops-card-radius-sm) 0;
  font-size: var(--ops-font-size-small);
  color: var(--ops-fg-primary);
  text-align: left;
  max-width: 480px;
}

/* Push to live stub: outline pill with an inline "Coming soon" hint. V3
   wiring will swap this for a live deploy button; the visual disabled
   state telegraphs the intent without raising operator hopes. */
.ba-lock__push-live-stub {
  margin-top: var(--space-sm);
  gap: var(--space-2xs);
}

.ba-lock__push-live-hint {
  font-size: var(--ops-font-size-micro);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--ops-field-input-bg, rgba(255,255,255,0.4));
  color: var(--ops-fg-tertiary);
}

/* Secondary text links: Clear lock + Start over below the hero CTA.
   Plain text buttons so they read as tertiary actions next to the
   primary pill above. */
.ba-lock__secondary-links {
  display: flex;
  gap: var(--space-md);
  margin-top: var(--space-md);
  justify-content: center;
}

.ba-lock__text-link {
  background: transparent;
  border: 0;
  padding: 4px 6px;
  margin: 0;
  font-family: var(--ops-font-family-body);
  font-size: var(--ops-font-size-small);
  color: var(--ops-fg-secondary);
  letter-spacing: 0.02em;
  cursor: pointer;
  transition: color var(--ops-motion-duration-micro) var(--ops-motion-curve);
}

.ba-lock__text-link:hover,
.ba-lock__text-link:focus-visible {
  color: var(--ops-fg-link);
  outline: none;
  text-decoration: underline;
}

.ba-lock__locked .ba-lock__section-title,
.ba-lock__cleared .ba-lock__section-title {
  font-size: var(--ops-font-size-subtitle);
  text-transform: none;
  letter-spacing: 0;
  color: var(--ops-fg-primary);
}

.ba-lock__locked-sub,
.ba-lock__cleared-sub {
  margin: 0;
  font-size: var(--ops-font-size-small);
  color: var(--ops-fg-secondary);
}

.ba-lock__lock-id {
  margin: var(--space-xs) 0 0;
  font-size: var(--ops-font-size-small);
  color: var(--ops-fg-secondary);
}

.ba-lock__lock-id-label {
  text-transform: uppercase;
  font-weight: var(--ops-font-weight-emphasis);
  letter-spacing: 0.02em;
  margin-right: var(--space-2xs);
}

.ba-lock__lock-id code {
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  padding: 2px 8px;
  border-radius: var(--radius-xs, 4px);
  background: rgba(255, 255, 255, 0.5);
  color: var(--ops-fg-primary);
}

.ba-lock__lock-id-copy {
  margin-left: var(--space-2xs);
}

/* Stage-scoped action rows. V4 UX cleanup moved the lock / retry /
   start-over CTAs out of the lock card footer and inlined them into
   each stage body so the locked stage no longer carries an empty
   footer strip below the Open Tenant Dashboard hero. */
.ba-lock__stage-actions {
  display: flex;
  justify-content: center;
  margin-top: var(--space-md);
}

.ba-lock__error .ba-lock__stage-actions {
  margin-top: var(--space-sm);
}

.ba-lock__cleared .ba-lock__stage-actions {
  margin-top: var(--space-xs);
}

/* Error stage keeps the review block visible above the error message
   (so the operator sees the context they were trying to lock), but the
   review's Lock CTA would compete with the error's Try again CTA. Hide
   the review action row in that case so only Try again is visible. */
.ba-lock[data-stage="error"] .ba-lock__review .ba-lock__stage-actions {
  display: none;
}

/* Error block (sits below the still-visible review). */
.ba-lock__error {
  padding: var(--space-md);
  background: var(--state-down-tint, rgba(176, 68, 100, 0.08));
  border: 1px solid color-mix(in srgb, var(--state-down-ink, #b04464) 35%, transparent);
  border-radius: var(--ops-card-radius-sm);
}

.ba-lock__error-msg {
  margin: 0;
  color: var(--state-down-ink, #b04464);
  font-weight: var(--ops-font-weight-emphasis);
  font-size: var(--ops-font-size-body);
  word-break: break-word;
}

/* ===========================================================================
   V4 customise card (.ba-v4 family).
   Two-pane split: authoring inputs on the left, live token preview on the
   right. At narrow widths the panes stack. All chrome flows through ops-*
   tokens; no raw colors or sizes.
   =========================================================================== */

.ba-v4 {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}

.ba-v4__intro {
  margin: 0;
  font-size: var(--ops-font-size-small);
  color: var(--ops-fg-secondary);
  text-align: center;
  max-width: 560px;
  margin-inline: auto;
}

.ba-v4__grid {
  display: grid;
  grid-template-columns: minmax(280px, 1fr) minmax(280px, 1fr);
  gap: var(--space-lg);
  align-items: start;
}

@media (max-width: 880px) {
  .ba-v4__grid {
    grid-template-columns: 1fr;
  }
}

.ba-v4__inputs-pane,
.ba-v4__preview-pane {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
  min-width: 0;
}

/* ===========================================================================
   V4 inputs panel (.ba-v4-inputs family).
   =========================================================================== */

.ba-v4-inputs {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}

.ba-v4-inputs__section {
  padding: var(--space-md);
  background: var(--ops-card-bg);
  border: 1px solid var(--ops-card-border);
  border-radius: var(--ops-card-radius-sm);
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}

.ba-v4-inputs__section-head {
  display: flex;
  flex-direction: column;
  gap: var(--space-3xs);
}

.ba-v4-inputs__section-title {
  margin: 0;
  font-family: var(--ops-font-family-display);
  font-size: var(--ops-font-size-small);
  font-weight: var(--ops-font-weight-emphasis);
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--ops-fg-secondary);
}

.ba-v4-inputs__section-helper {
  margin: 0;
  font-size: var(--ops-font-size-small);
  color: var(--ops-fg-secondary);
  line-height: 1.4;
}

.ba-v4-inputs__section-body {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}

.ba-v4-inputs__sub-label {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);
  font-size: var(--ops-font-size-small);
  color: var(--ops-fg-secondary);
}

/* Placement chips. */
.ba-v4-inputs__placement-group {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2xs);
}

.ba-v4-inputs__chip {
  background: transparent;
  border: 1px solid var(--ops-card-border);
  padding: var(--space-2xs) var(--space-sm);
  border-radius: var(--radius-pill);
  font-family: var(--ops-font-family-body);
  font-size: var(--ops-font-size-small);
  color: var(--ops-fg-secondary);
  cursor: pointer;
  transition:
    background var(--ops-motion-duration-micro) var(--ops-motion-curve),
    color var(--ops-motion-duration-micro) var(--ops-motion-curve),
    border-color var(--ops-motion-duration-micro) var(--ops-motion-curve);
}

.ba-v4-inputs__chip:hover,
.ba-v4-inputs__chip:focus-visible {
  background: var(--ops-card-bg-hover);
  color: var(--ops-fg-primary);
  outline: none;
}

.ba-v4-inputs__chip[data-selected="true"] {
  background: var(--ops-card-bg-active);
  border-color: var(--ops-card-border-active);
  color: var(--ops-fg-primary);
  font-weight: var(--ops-font-weight-emphasis);
}

/* Dark mode toggle. */
.ba-v4-inputs__toggle-row {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  cursor: pointer;
}

.ba-v4-inputs__checkbox {
  width: 16px;
  height: 16px;
  accent-color: var(--ops-card-border-active);
  cursor: pointer;
}

.ba-v4-inputs__toggle-label {
  font-size: var(--ops-font-size-small);
  color: var(--ops-fg-primary);
}

.ba-v4-inputs__reason {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);
}

.ba-v4-inputs__textarea {
  width: 100%;
  box-sizing: border-box;
  padding: var(--space-sm);
  background: var(--ops-field-input-bg);
  border: 1px solid var(--ops-card-border);
  border-radius: var(--ops-card-radius-sm);
  color: var(--ops-fg-primary);
  font-family: var(--ops-font-family-body);
  font-size: var(--ops-font-size-small);
  line-height: 1.45;
  resize: vertical;
  transition:
    background var(--ops-motion-duration-micro) var(--ops-motion-curve),
    border-color var(--ops-motion-duration-micro) var(--ops-motion-curve);
}

.ba-v4-inputs__textarea:focus {
  background: var(--ops-field-input-bg-focus);
  border-color: var(--ops-card-border-active);
  outline: none;
}

.ba-v4-inputs__text-input {
  width: 100%;
  box-sizing: border-box;
  padding: var(--space-2xs) var(--space-sm);
  background: var(--ops-field-input-bg);
  border: 1px solid var(--ops-card-border);
  border-radius: var(--ops-card-radius-sm);
  color: var(--ops-fg-primary);
  font-family: var(--ops-font-family-body);
  font-size: var(--ops-font-size-small);
  transition:
    background var(--ops-motion-duration-micro) var(--ops-motion-curve),
    border-color var(--ops-motion-duration-micro) var(--ops-motion-curve);
}

.ba-v4-inputs__text-input:focus {
  background: var(--ops-field-input-bg-focus);
  border-color: var(--ops-card-border-active);
  outline: none;
}

/* Accent and stop rows share row chrome. */
.ba-v4-inputs__accent-list,
.ba-v4-inputs__stops-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);
}

.ba-v4-inputs__accent-row,
.ba-v4-inputs__stop-row {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  gap: var(--space-2xs);
  align-items: center;
}

.ba-v4-inputs__stop-row {
  grid-template-columns: 64px auto minmax(0, 1fr) auto;
}

.ba-v4-inputs__color-input {
  width: 36px;
  height: 32px;
  border: 1px solid var(--ops-card-border);
  border-radius: var(--ops-card-radius-sm);
  background: transparent;
  cursor: pointer;
  padding: 0;
}

.ba-v4-inputs__hex-input {
  width: 100%;
  box-sizing: border-box;
  padding: var(--space-2xs) var(--space-sm);
  background: var(--ops-field-input-bg);
  border: 1px solid var(--ops-card-border);
  border-radius: var(--ops-card-radius-sm);
  color: var(--ops-fg-primary);
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: var(--ops-font-size-small);
}

.ba-v4-inputs__hex-input:focus {
  background: var(--ops-field-input-bg-focus);
  border-color: var(--ops-card-border-active);
  outline: none;
}

.ba-v4-inputs__pos-input {
  width: 64px;
  box-sizing: border-box;
  padding: var(--space-2xs) var(--space-2xs);
  background: var(--ops-field-input-bg);
  border: 1px solid var(--ops-card-border);
  border-radius: var(--ops-card-radius-sm);
  color: var(--ops-fg-primary);
  font-family: var(--ops-font-family-body);
  font-size: var(--ops-font-size-small);
  text-align: right;
}

.ba-v4-inputs__add-btn,
.ba-v4-inputs__remove-btn {
  background: transparent;
  border: 1px solid var(--ops-card-border);
  padding: var(--space-2xs) var(--space-sm);
  border-radius: var(--radius-pill);
  font-family: var(--ops-font-family-body);
  font-size: var(--ops-font-size-micro);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ops-fg-secondary);
  cursor: pointer;
  transition:
    background var(--ops-motion-duration-micro) var(--ops-motion-curve),
    color var(--ops-motion-duration-micro) var(--ops-motion-curve),
    border-color var(--ops-motion-duration-micro) var(--ops-motion-curve);
}

.ba-v4-inputs__add-btn:hover:not(:disabled),
.ba-v4-inputs__add-btn:focus-visible:not(:disabled),
.ba-v4-inputs__remove-btn:hover,
.ba-v4-inputs__remove-btn:focus-visible {
  background: var(--ops-card-bg-hover);
  color: var(--ops-fg-primary);
  border-color: var(--ops-card-border-active);
  outline: none;
}

.ba-v4-inputs__add-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.ba-v4-inputs__add-btn {
  align-self: flex-start;
}

/* Font pairing grid. */
.ba-v4-inputs__fonts-grid {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}

.ba-v4-inputs__labeled-input {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);
}

/* Gradient direction slider. */
.ba-v4-inputs__direction-row {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);
}

.ba-v4-inputs__slider {
  width: 100%;
  accent-color: var(--ops-card-border-active);
}

.ba-v4-inputs__direction-value {
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: var(--ops-font-size-small);
  color: var(--ops-fg-primary);
}

/* ===========================================================================
   V4 token preview panel (.ba-v4-preview family).
   =========================================================================== */

.ba-v4-preview {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}

.ba-v4-preview__block {
  padding: var(--space-md);
  background: var(--ops-card-bg);
  border: 1px solid var(--ops-card-border);
  border-radius: var(--ops-card-radius-sm);
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
}

.ba-v4-preview__block-title {
  margin: 0;
  font-family: var(--ops-font-family-display);
  font-size: var(--ops-font-size-small);
  font-weight: var(--ops-font-weight-emphasis);
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--ops-fg-secondary);
}

.ba-v4-preview__block-helper {
  margin: 0;
  font-size: var(--ops-font-size-small);
  color: var(--ops-fg-secondary);
  line-height: 1.4;
}

.ba-v4-preview__empty {
  margin: 0;
  font-size: var(--ops-font-size-small);
  color: var(--ops-fg-tertiary);
  font-style: italic;
}

/* Typography role rows. */
.ba-v4-preview__type-roles {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}

.ba-v4-preview__type-row {
  display: grid;
  grid-template-columns: 120px minmax(0, 1fr);
  gap: var(--space-sm);
  align-items: baseline;
  padding: var(--space-2xs) 0;
  border-bottom: 1px solid var(--ops-card-border);
}

.ba-v4-preview__type-row:last-child {
  border-bottom: 0;
}

.ba-v4-preview__type-meta {
  display: flex;
  flex-direction: column;
  gap: var(--space-3xs);
}

.ba-v4-preview__type-role {
  font-family: var(--ops-font-family-display);
  font-size: var(--ops-font-size-micro);
  font-weight: var(--ops-font-weight-emphasis);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ops-fg-secondary);
}

.ba-v4-preview__type-role-id {
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: var(--ops-font-size-micro);
  color: var(--ops-fg-tertiary);
}

.ba-v4-preview__type-specs {
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: var(--ops-font-size-micro);
  color: var(--ops-fg-tertiary);
}

.ba-v4-preview__type-sample {
  color: var(--ops-fg-primary);
  min-width: 0;
  overflow-wrap: anywhere;
}

/* Swatch and indicator lists. */
.ba-v4-preview__swatch-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);
}

/* Gradient band. */
.ba-v4-preview__gradient-band {
  height: 56px;
  border-radius: var(--ops-card-radius-sm);
  border: 1px solid var(--ops-card-border);
}

/* Logo placement preview. */
.ba-v4-preview__logo-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-sm);
}

@media (max-width: 520px) {
  .ba-v4-preview__logo-row {
    grid-template-columns: 1fr;
  }
}

.ba-v4-preview__placement-card {
  border: 1px solid var(--ops-card-border);
  border-radius: var(--ops-card-radius-sm);
  padding: var(--space-sm);
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);
  background: var(--ops-card-bg-hover);
  transition:
    opacity var(--ops-motion-duration-micro) var(--ops-motion-curve);
}

.ba-v4-preview__placement-card[data-active="false"] {
  opacity: 0.4;
}

.ba-v4-preview__placement-tag {
  font-family: var(--ops-font-family-display);
  font-size: var(--ops-font-size-micro);
  font-weight: var(--ops-font-weight-emphasis);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ops-fg-secondary);
}

.ba-v4-preview__placement-sidebar {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);
  padding: var(--space-xs);
  background: var(--ops-card-bg-active);
  border-radius: var(--ops-card-radius-sm);
  min-height: 120px;
}

.ba-v4-preview__placement-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-xs) var(--space-sm);
  background: var(--ops-card-bg-active);
  border-radius: var(--ops-card-radius-sm);
  min-height: 44px;
}

.ba-v4-preview__placement-logo {
  max-height: 32px;
  max-width: 80px;
  object-fit: contain;
}

.ba-v4-preview__placement-placeholder {
  font-size: var(--ops-font-size-micro);
  color: var(--ops-fg-tertiary);
  font-style: italic;
}

.ba-v4-preview__placement-nav {
  display: flex;
  flex-direction: column;
  gap: var(--space-3xs);
  margin-top: var(--space-2xs);
}

.ba-v4-preview__placement-nav-item {
  font-size: var(--ops-font-size-micro);
  color: var(--ops-fg-secondary);
}

.ba-v4-preview__placement-header-right {
  font-size: var(--ops-font-size-micro);
  color: var(--ops-fg-secondary);
}

/* Dark mode gate block. */
.ba-v4-preview__block--dark-gate {
  background: var(--ops-card-bg);
}

.ba-v4-preview__dark-status {
  margin: 0;
  font-size: var(--ops-font-size-body);
  font-weight: var(--ops-font-weight-emphasis);
  color: var(--ops-fg-primary);
}

.ba-v4-preview__dark-status[data-state="suppressed"] {
  color: var(--ops-fg-link);
}

.ba-v4-preview__dark-reason {
  margin: 0;
  font-size: var(--ops-font-size-small);
  color: var(--ops-fg-secondary);
  font-style: italic;
}

/* ===========================================================================
   WCAG contrast indicator (.ba-wcag family). Used by the V4 preview panel
   inline next to palette and accent swatches.
   =========================================================================== */

.ba-wcag {
  display: grid;
  grid-template-columns: 56px minmax(0, 1fr);
  gap: var(--space-sm);
  align-items: center;
  padding: var(--space-2xs) var(--space-sm);
  border-radius: var(--ops-card-radius-sm);
  background: var(--ops-card-bg-hover);
  border: 1px solid var(--ops-card-border);
}

.ba-wcag__swatches {
  position: relative;
  width: 56px;
  height: 40px;
  border-radius: var(--ops-card-radius-sm);
  overflow: hidden;
  border: 1px solid var(--ops-card-border);
}

.ba-wcag__swatch {
  position: absolute;
  inset: 0;
  display: block;
}

.ba-wcag__swatch--fg {
  inset: 8px;
  border-radius: var(--radius-md);
}

.ba-wcag__body {
  display: flex;
  flex-direction: column;
  gap: var(--space-3xs);
  min-width: 0;
}

.ba-wcag__label {
  margin: 0;
  font-size: var(--ops-font-size-micro);
  color: var(--ops-fg-secondary);
  letter-spacing: 0.02em;
}

.ba-wcag__ratio {
  margin: 0;
  display: flex;
  align-items: center;
  gap: var(--space-2xs);
  font-size: var(--ops-font-size-small);
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  color: var(--ops-fg-primary);
}

.ba-wcag__badge {
  padding: 2px var(--space-2xs);
  border-radius: var(--radius-pill);
  font-size: var(--ops-font-size-micro);
  font-family: var(--ops-font-family-body);
  font-weight: var(--ops-font-weight-emphasis);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  background: var(--ops-card-bg);
  color: var(--ops-fg-secondary);
  border: 1px solid var(--ops-card-border);
}

.ba-wcag[data-tier="aaa"] .ba-wcag__badge {
  border-color: var(--ops-card-border-active);
  color: var(--ops-fg-link);
}

.ba-wcag[data-tier="aa"] .ba-wcag__badge {
  border-color: var(--ops-card-border);
  color: var(--ops-fg-primary);
}

.ba-wcag[data-tier="fail"] .ba-wcag__badge {
  border-color: color-mix(in srgb, var(--state-down-ink, #b04464) 50%, transparent);
  color: var(--state-down-ink, #b04464);
}

.ba-wcag__verdict {
  margin: 0;
  font-size: var(--ops-font-size-small);
  color: var(--ops-fg-secondary);
  line-height: 1.35;
}

/* ── FRAMED MODE (2026-08-19) ─────────────────────────────────────────────
   Set by js/bootstrap.js when the flow runs inside the console's spin-up
   modal (?framed=1). The modal already carries a title, a subtitle and a
   Close button, so the flow's own shell chrome would be a second copy of
   the same controls. Hide it and let the modal frame the FLOW alone.
   The orb and the voice client are not constructed at all in framed mode
   (see js/bootstrap.js) - this only removes the duplicated chrome. */
[data-framed="true"] .shell,
[data-framed="true"] .ops-orb-slot {
  display: none !important;
}
[data-framed="true"] body,
[data-framed="true"] .ops-field {
  background: transparent;
}
[data-framed="true"] .ops-stage {
  padding-top: var(--ops-layout-stack-gap-sm);
}
