/* Onboarding wizard shell (#3487, design epic #3432). Figma 01 `1:19539`:
 * Left Panel 1:19542, Top Bar 1:19543, Step Indicator 1:19553 (current and
 * done from 03's 1:19900), Form Header 1:19564, Wizard footer 1:19879.
 * Step content (#3489): identity row, option card, grouped radio cards, below.
 * Markup: app/onboarding-shell.ts, app/onboarding-choices.ts. Tokens only;
 * light and dark follow them, except the art panel (#3488), dark in both.
 *
 * Deviations, for AA: the eyebrow and the current/done step fill use
 * --live-text (Figma's #10b981 under white or small text is 2.5:1), the
 * sub-line and upcoming numerals --fg-muted (Figma's #9ca3af is 2.5:1).
 * The current step keeps 03's 3px ring so it reads apart from done ones.
 */

/* The focused screen fills the window: no page padding or width cap. */
.shell[data-focused] .content { padding: 0; }
.shell[data-focused] .page { max-width: none; }

.ob-wizard {
  --ob-inset: 80px;   /* Form Content's left inset */
  --ob-col: 577px;    /* its width at 1474 */
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); min-height: 100svh;
}
.ob-panel { display: flex; flex-direction: column; min-width: 0; background: var(--surface); color: var(--fg); }
/* Dark in both themes; the art is below (#3488). */
.ob-art { position: sticky; top: 0; height: 100svh; }

/* ---- Top bar ---- */
.ob-top {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-4);
  box-sizing: border-box; min-height: 84px; padding: 28px 48px; border-bottom: 1px solid var(--border);
}
.ob-logo-img { display: block; width: auto; height: 28px; }
.ob-logo-on-dark { display: none; }
:root[data-theme="dark"] .ob-logo-on-light { display: none; }
:root[data-theme="dark"] .ob-logo-on-dark { display: block; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .ob-logo-on-light { display: none; }
  :root:not([data-theme="light"]) .ob-logo-on-dark { display: block; }
}
.ob-top-end { display: flex; align-items: center; gap: var(--space-4); }

/* ---- Step indicator: 24px circles, gap 6, 20x1 connectors ---- */
.ob-steps ol { display: flex; align-items: center; gap: 6px; margin: 0; padding: 0; list-style: none; }
.ob-step { display: flex; align-items: center; gap: 6px; }
.ob-step + .ob-step::before { content: ""; width: 20px; height: 1px; background: var(--border); }
/* Customize is optional (designed by us, not in Figma): a dashed lead-in and ring. */
.ob-step.is-optional::before { height: 0; background: none; border-top: 1px dashed var(--border-control); }
.ob-step-dot {
  display: flex; align-items: center; justify-content: center; box-sizing: border-box;
  width: 24px; height: 24px; border-radius: var(--radius-xl); font: var(--type-button-s);
}
.ob-step-dot svg { width: 12px; height: 12px; }
.is-todo .ob-step-dot { border: 1px solid var(--border-strong); background: var(--surface-sunken); color: var(--fg-muted); }
.is-todo.is-optional .ob-step-dot { border-style: dashed; border-color: var(--border-control); }
.is-done .ob-step-dot { background: var(--live-text); color: var(--surface); }
.is-current .ob-step-dot { border: 3px solid var(--success-bg); background: var(--live-text); color: var(--surface); }

/* ---- Form column: 80px in, 577px wide (max), at any panel width ---- */
.ob-pad, .ob-body > :not(.ob-flow, [role="status"]) {
  padding-inline: var(--ob-inset) max(var(--ob-inset), 100% - var(--ob-col) - var(--ob-inset));
}
.ob-main, .ob-body, .ob-flow, .ob-body > [role="status"], .ob-body > [role="status"] > [inert] {
  display: flex; flex-direction: column; flex: 1 0 auto;
}
.ob-body > :not(.ob-flow, [role="status"]) { margin-top: var(--space-7); }

.ob-head { display: flex; flex-direction: column; gap: var(--space-2); padding-top: 80px; }
.ob-eyebrow {
  display: flex; align-items: center; gap: 6px; margin: 0;
  font: var(--type-code-eyebrow); letter-spacing: 0.6px; color: var(--live-text);
}
.ob-eyebrow::before { content: ""; flex: none; width: 6px; height: 6px; border-radius: var(--radius-pill); background: var(--brand); }
/* Inter Bold 28/36 (1:19568): no --type token yet. */
.ob-title { margin: 0; font: 700 28px/36px var(--font-sans); letter-spacing: -0.5px; color: var(--fg-strong); }
.ob-subline { margin: 0; font: 400 11px var(--font-mono); letter-spacing: 0.2px; color: var(--fg-muted); }
.ob-org { margin: 0; font: var(--type-body); color: var(--fg-muted); }
.ob-email:empty { display: none; }
.ob-email .gate-fine { text-align: left; }
.ob-email .gate-actions { justify-content: flex-start; margin-top: 0; }

.ob-fields { flex: 1 0 auto; padding-top: var(--space-7); padding-bottom: var(--space-7); }
.ob-fields > .stack { margin: 0; }

/* ---- Footer: 96px, sticks to the bottom of the window ---- */
.ob-footer {
  position: sticky; bottom: 0; z-index: 1;
  display: flex; flex-direction: column; align-items: center; gap: var(--space-2);
  margin-top: auto; padding: 20px var(--ob-inset) 32px;
  border-top: 1px solid var(--border); background: var(--bg);
}
/* The status and Skip / Back to Settings (not in Figma), above the pair. */
.ob-footer-aside { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: var(--space-2) var(--space-3); }
/* Empty, the live region stays in the accessibility tree (so a message written
   into it later is announced) and only its space goes. */
.ob-footer-aside:not(:has(.btn)):has(> .save-status:empty) { margin-bottom: calc(-1 * var(--space-2)); }
.ob-footer .save-status { margin: 0; text-align: center; }
.ob-footer .save-status:empty { display: block; position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
.ob-footer-row { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--space-3); }
.ob-back { min-width: 108px; }
.ob-forward { min-width: 274px; }
.ob-forward:not(:disabled, [aria-disabled="true"]) { --btn-icon: light-dark(var(--brand-mint), var(--btn-on-fill)); }

/* ---- Step content (#3489): Figma 01 `1:19570` identity row, `1:19576`
 * option card, 03 `1:19925` grouped radio card. Customize's own steps have
 * no frame: they use these patterns, designed by us, not in Figma.
 * Deviations, for AA: list labels and helpers take --fg-muted (Figma's
 * #9ca3af / #6e7781 are 2.5:1 / 4.4:1 at 10px); the selected border, radio
 * and the option subtitle take --control-on / --live-text (#10b981 and
 * #059669 are under 3:1 / 4.5:1 on the tint). Hover, focus and disabled are
 * #3439's (not in Figma). ---- */
.ob-context { display: flex; flex-direction: column; gap: 28px; margin-top: 20px; }
.ob-context > :empty, .ob-context > [hidden] { display: none; }

/* Identity row, 1:19570: 36 high, radius 8, the GitHub mark, a check. */
.ob-identity {
  display: flex; align-items: center; gap: var(--space-2); box-sizing: border-box; min-height: 36px; margin: 0; padding: 10px 12px;
  border: 1px solid var(--border-strong); border-radius: var(--radius); background: var(--bg); color: var(--fg-muted);
}
.ob-identity .gh-mark { margin: 0; color: var(--fg-strong); }
.ob-identity-text { flex: 1; min-width: 0; font: 400 11px var(--font-mono); overflow-wrap: anywhere; }
.ob-identity-text strong { font-weight: 600; color: var(--fg-strong); }
.ob-identity-check { flex: none; color: var(--live-text); }

/* List label, 1:19577: "// PICK AN ORG", 8px above its list. The slashes are
   drawn, not read. */
.ob-list-label, .ob-form .choice-legend {
  margin: 0 0 var(--space-2); padding: 0;
  font: 600 10px var(--font-mono); letter-spacing: 0.8px; text-transform: uppercase; color: var(--fg-muted);
}
.ob-list-label::before, .ob-form .choice-legend::before { content: "// "; content: "// " / ""; }

/* Option card, 1:19578: 64 high, padding 14, a 34px tile, title + subtitle, the radio at the end. */
.ob-option {
  display: flex; align-items: center; gap: var(--space-3); box-sizing: border-box; min-height: 64px; padding: 14px;
  border: 1px solid var(--border-strong); border-radius: var(--radius); background: var(--surface);
}
.ob-option.is-selected { border-color: var(--control-on); background: var(--select-tint); }
.ob-option-tile {
  display: flex; flex: none; align-items: center; justify-content: center; width: 34px; height: 34px;
  border-radius: var(--radius-md); background: var(--surface-sunken); color: var(--fg-muted);
}
.is-selected .ob-option-tile { background: var(--success-bg); color: var(--live-text); }
.ob-option-text { display: flex; flex: 1; flex-direction: column; gap: 1px; min-width: 0; }
.ob-option-title { font: 700 13px var(--font-mono); color: var(--fg-strong); overflow-wrap: anywhere; }
.ob-option-sub { font: 400 12px/1.5 var(--font-sans); color: var(--fg-muted); }
.ob-option.is-selected { --fg-muted: var(--fg-secondary); }
.is-selected .ob-option-sub { color: var(--live-text); }
.ob-option-radio {
  flex: none; box-sizing: border-box; width: 18px; height: 18px; border: 1px solid var(--control-on); border-radius: 50%;
  background: radial-gradient(circle, var(--control-on) 4px, transparent 4.5px);
}

/* ---- The steps: no card chrome inside the wizard; a mono question. ---- */
.ob-form [data-ob-step]:not([hidden]) { display: flex; flex-direction: column; gap: var(--space-3); padding: 0; border: 0; border-radius: 0; background: none; box-shadow: none; }
.ob-form [data-ob-step] > h2 { margin: 0 0 var(--space-1); font: 700 16px/22px var(--font-mono); color: var(--fg-strong); }
/* Focus lands on the heading for assistive tech when a step opens; it is not a control. */
.ob-form [data-ob-step] > h2:focus { outline: 0; }
.ob-form [data-ob-step] > div { display: flex; flex-direction: column; gap: var(--space-3); }
.ob-form .ob-question { margin: var(--space-4) 0 0; font: 700 13px/18px var(--font-mono); color: var(--fg-strong); }
/* Footnotes, 1:19954: mono 10. */
.ob-form [data-ob-step] p.muted { margin: 0; font: 400 10px/15px var(--font-mono); color: var(--fg-muted); }
/* "● next: …", 1:19951. */
.ob-next { display: flex; align-items: center; gap: 6px; margin: 0; font: 400 10px var(--font-mono); color: var(--fg-muted); }
.ob-next-dot { flex: none; width: 6px; height: 6px; border-radius: var(--radius-pill); background: var(--brand); }

/* ---- Grouped radio card, 1:19925: one bordered box, radius 8; rows of
 * padding 14 with a 16px radio; the picked row tinted, with what depends on
 * it nested in it (.ob-nested). Rows divide with 1px. ---- */
.ob-form .choice-list { display: flex; flex-direction: column; gap: 0; margin: 0; padding: 0; border: 0; min-width: 0; }
.ob-form .choice-list > .choice, .ob-form .choice-list > .ob-nested {
  margin: 0; border: 1px solid var(--border-control); border-top-width: 0; border-bottom-color: var(--border); border-radius: 0; background: var(--surface);
}
.ob-form .choice-list > .choice:first-of-type { border-top-width: 1px; border-radius: var(--radius) var(--radius) 0 0; }
.ob-form .choice-list > :last-child { border-bottom-color: var(--border-control); border-radius: 0 0 var(--radius) var(--radius); }
.ob-form .choice-list > .choice:first-of-type:last-child { border-radius: var(--radius); }
.ob-form .choice-list > .choice:has(+ .ob-nested) { border-bottom-width: 0; }
.ob-form .choice-list > .choice { gap: var(--space-3); align-items: flex-start; padding: 14px; }
.ob-form .choice input[type="radio"] { --radio-size: 16px; --radio-dot: 3.5px; margin-top: 1px; }
.ob-form .choice strong { font: 700 13px/18px var(--font-mono); color: var(--fg-strong); }
.ob-form .choice .muted { display: block; margin-top: 2px; font: 400 10px/15px var(--font-mono); color: var(--fg-muted); }
.ob-form .choice .mono { font: inherit; }
/* The tier's DEFAULT tag: --accent (#10b981) is 2.4:1 on the tint. */
.ob-form .choice .default-tag { border-color: var(--control-on); color: var(--live-text); }
/* On a tint, muted text steps up to --fg-secondary: dark --fg-muted is 4.1:1 on --select-tint. */
.ob-form .choice:has(input:checked), .ob-form .choice:has(input:checked) + .ob-nested { --fg-muted: var(--fg-secondary); background: var(--select-tint); }
.ob-form .choice:hover:not(:has(input:checked, input:disabled)) { --fg-muted: var(--fg-secondary); background: var(--surface-sunken); }
.ob-form .choice:has(input:disabled) { cursor: not-allowed; }
.ob-form .choice:has(input:disabled) strong { color: var(--fg-muted); }

/* What a picked choice opens, 1:19939: under the title (42 in), a divider,
   then its rows. */
.ob-form .ob-nested { display: flex; flex-direction: column; gap: var(--space-2); padding: 0 14px 14px 42px; }
.ob-authors { margin: 0; padding: var(--space-2) 0 0; border: 0; border-top: 1px solid var(--border); min-width: 0; }
.ob-authors-legend { float: left; width: 100%; padding: 0 0 var(--space-1); font: 600 10px var(--font-mono); letter-spacing: 0.8px; text-transform: uppercase; color: var(--fg-muted); }
.ob-authors-legend + * { clear: both; }
.ob-authors[aria-invalid="true"] { border-top-color: var(--danger-fg); }
/* A nested checkbox row, 1:19947: py 8, mono bold 11. */
.ob-check { display: flex; align-items: center; gap: var(--space-2); padding: var(--space-2) 0; font: 400 11px/16px var(--font-mono); color: var(--fg); cursor: pointer; }
.ob-check input { flex: none; }
.ob-nested .field-error { font: 400 11px var(--font-mono); }

/* ---- Art panel (#3488): Figma 01 `1:19597` (03 `1:19887`, 04 `1:20336`
 * for the helix and full grid). Markup: app/onboarding-art.ts. Decorative
 * and aria-hidden (owner decision, 2026-11-05). Dark in both themes, as
 * Figma draws it in a light frame.
 *
 * Deviations: text Figma draws under AA on this ground takes the nearest
 * passing token: month labels, legend, comments and the first copy line
 * --motif-label (Figma #4b5563 / #6b7280 / #4f5b56 are 2.4-4.0:1); the
 * second copy line --loader-text; badge values --brand-mint (#10b981 on
 * the badge is 4.4:1). Badge radius is Figma's 8 (the issue said 6).
 * Dark theme: the left panel's #121817 is nearly the ground's #0f1a17
 * (#3489), so in dark the ground drops darker and a green hairline marks
 * the edge (proposed, not in Figma). ---- */
.ob-art {
  /* The art's own colors, mixed from tokens that hold in both themes: the
     contribution scale (Figma 1:19837 draws GitHub's #161b22 / #0d4429 /
     #006d32 / #26a641 / #39d353; this is the brand ramp nearest it) and
     the terminal card (#0a1210, rule #1f2d27). */
  --art-ground: var(--sidebar-bg);
  --art-card: color-mix(in srgb, var(--sidebar-bg) 65%, black);
  --art-rule: var(--sidebar-hover);
  --art-l0: color-mix(in srgb, var(--ink) 94%, white);
  --art-l1: color-mix(in srgb, var(--brand) 15%, var(--logo-ink));
  --art-l2: color-mix(in srgb, var(--brand) 45%, var(--logo-ink));
  --art-l3: var(--brand); --art-l4: var(--brand-mint);
  --art-glow: color-mix(in srgb, var(--brand) 12.5%, transparent);
  display: flex; align-items: center; justify-content: center; overflow: hidden;
  background:
    radial-gradient(circle 160px at calc(100% - 77px) 80px, var(--art-glow), transparent),
    radial-gradient(circle 140px at 60px calc(100% - 268px), var(--art-glow), transparent),
    linear-gradient(to bottom, transparent calc(100% - 208px), var(--art-ground)),
    linear-gradient(to right, transparent, color-mix(in srgb, var(--brand) 3%, transparent), transparent),
    var(--art-ground);
  font-family: var(--font-mono); color: var(--motif-fg);
}
:root[data-theme="dark"] .ob-art { --art-ground: color-mix(in srgb, var(--sidebar-bg) 50%, black); box-shadow: inset 1px 0 color-mix(in srgb, var(--brand) 35%, transparent); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .ob-art { --art-ground: color-mix(in srgb, var(--sidebar-bg) 50%, black); box-shadow: inset 1px 0 color-mix(in srgb, var(--brand) 35%, transparent); }
}
.ob-art-box { position: relative; display: flex; flex-direction: column; align-items: center; gap: 32px; width: min(560px, 100% - 96px); }
.ob-art p { margin: 0; }

/* Label, 1:19602: an 8px dot, mono 11 spaced 1.5. */
.ob-art-label { display: flex; align-items: center; gap: 8px; font-size: 11px; letter-spacing: 1.5px; color: var(--brand-mint); }
.ob-art-label::before { content: ""; width: 8px; height: 8px; border-radius: var(--radius-pill); background: var(--brand); }

/* Heatmap, 1:19605: 12 months, rows of 30 cells 10 high with a 3px gap. */
.ob-art-heat { display: flex; flex-direction: column; align-items: center; gap: 14px; align-self: stretch; }
.ob-art-months { display: grid; grid-template-columns: repeat(12, 1fr); align-self: stretch; font-size: 8px; color: var(--motif-label); }
.ob-art-cells { display: grid; grid-template-columns: repeat(var(--cols, 30), 1fr); gap: 3px; align-self: stretch; }
.ob-art-cells i, .ob-art-legend i { height: 10px; border-radius: 2px; background: var(--cell); }
.ob-art-legend { display: flex; align-items: center; gap: 6px; font-size: 8px; color: var(--motif-label); }
.ob-art-legend i { width: 10px; }
.ob-art .lv-0 { --cell: var(--art-l0); } .ob-art .lv-1 { --cell: var(--art-l1); } .ob-art .lv-2 { --cell: var(--art-l2); }
.ob-art .lv-3 { --cell: var(--art-l3); } .ob-art .lv-4 { --cell: var(--art-l4); }
.ob-art-caption { font-size: 10px; color: var(--motif-label); }

/* Terminal card, 1:19847: radius 12, traffic lights, mono 11 lines. */
.ob-art-term { display: flex; flex-direction: column; gap: 8px; box-sizing: border-box; align-self: stretch; padding: 16px 20px; border: 1px solid var(--art-rule); border-radius: var(--radius-xl); background: var(--art-card); }
.ob-art-term-head { display: flex; align-items: center; gap: 5px; padding-bottom: 8px; border-bottom: 1px solid var(--art-rule); font-size: 9px; letter-spacing: 1px; color: var(--motif-label); }
.ob-art-term-head i { width: 8px; height: 8px; border-radius: 50%; background: var(--meter-red); }
.ob-art-term-head i:nth-child(2) { background: var(--meter-amber); }
.ob-art-term-head i:nth-child(3) { background: var(--brand); }
.ob-art-term-body { display: flex; flex-direction: column; gap: 4px; font-size: 11px; line-height: 14px; }
.ob-art-line.is-comment { color: var(--motif-label); }
.ob-art-line.is-status { display: flex; align-items: center; gap: 6px; color: var(--brand); }
.ob-art-line.is-status::before { content: ""; width: 6px; height: 6px; border-radius: var(--radius-pill); background: var(--brand); }

/* Badges, 1:19862: three tiles, a 1px border in the tile's tone. */
.ob-art-badges { display: flex; gap: 10px; }
.ob-art-badge { --tone: var(--brand-mint); display: flex; flex-direction: column; align-items: center; gap: 2px; padding: 8px 14px; border: 1px solid var(--tone); border-radius: var(--radius); background: var(--art-l1); color: var(--tone); white-space: nowrap; }
.ob-art-badge.is-safe { border-color: var(--brand); }
.ob-art-badge.is-warn { --tone: var(--meter-amber); background: color-mix(in srgb, var(--meter-amber) 10%, var(--art-card)); }
.ob-art-badge.is-calm { background: color-mix(in srgb, var(--brand) 6%, var(--art-card)); }
.ob-art-badge span { font-size: 9px; letter-spacing: 1px; }
.ob-art-badge strong { font-size: 16px; line-height: 21px; }
.ob-art-badge small { font-size: 8px; }

/* Copy, 1:19875. */
.ob-art-copy { display: flex; flex-direction: column; align-items: center; gap: 4px; text-align: center; }
.ob-art-copy p:first-child { font-size: 12px; font-weight: 600; color: var(--motif-label); }
.ob-art-copy p:last-child { font-size: 10px; color: var(--loader-text); }

/* Strands, 02 `139:39125` / 03 `139:40481`: three cubes a strand, two
   strands a column, the cube 75% of the column's pitch. */
.ob-art-strands { display: grid; grid-template-columns: repeat(var(--n), 1fr); align-self: stretch; height: calc(var(--amp) * 2px + 48px); }
.ob-art-strands span { position: relative; }
.ob-art-strands i {
  position: absolute; top: 50%; left: 0; width: 75%; aspect-ratio: 1; margin-top: -37.5%;
  border-radius: 2px; background: var(--cell);
  transform: translateY(calc(var(--k) * 135%)) translateY(calc(var(--s) * var(--amp) * 1px));
}

/* The code screen, 02b `149:7698`: streaks over the ground, a glow orb at
   the top right, and a card (radius 12) with the sample, the 12-week grid
   and three chips. */
.ob-art-streaks { position: absolute; inset: 0; pointer-events: none; }
.ob-art-streak { position: absolute; display: grid; grid-auto-flow: column; grid-template-rows: repeat(2, 7px); gap: 2px; transform: rotate(var(--r)); }
.ob-art-streak i { width: 7px; height: 7px; border-radius: 1.5px; background: var(--cell); }
.ob-art-orb { position: absolute; top: -120px; right: -120px; width: 360px; height: 360px; border-radius: 50%; background: radial-gradient(closest-side, var(--art-glow), transparent); pointer-events: none; }
.ob-art-card { position: relative; display: flex; flex-direction: column; gap: 14px; box-sizing: border-box; align-self: stretch; padding: 24px; border: 1px solid var(--art-rule); border-radius: var(--radius-xl); background: color-mix(in srgb, var(--art-card) 92%, transparent); }
.ob-art-card-head { display: flex; align-items: center; gap: 10px; font-size: 12px; color: var(--motif-fg); }
.ob-art-card-mark { width: 24px; height: 24px; border: 1px solid var(--brand); border-radius: var(--radius); background: color-mix(in srgb, var(--brand) 15%, transparent); }
.ob-art-pill { padding: 2px 8px; border: 1px solid var(--brand); border-radius: var(--radius-pill); font-size: 9px; letter-spacing: 1px; color: var(--brand-mint); }
.ob-art-card-sub { font-size: 10px; color: var(--motif-label); }
.ob-art-card-grid { display: flex; flex-direction: column; gap: 8px; }
.ob-art-card-grid p { display: flex; justify-content: space-between; font-size: 9px; color: var(--motif-label); }
.ob-art-card-grid .ob-art-cells { --breathe-min: 0.1; gap: 4px; }
.ob-art-card-grid .ob-art-cells i { height: 14px; }
.ob-art-chips { display: flex; flex-wrap: wrap; gap: 8px; }
.ob-art-chips span { padding: 4px 10px; border: 1px solid var(--art-rule); border-radius: var(--radius); font-size: 9px; color: var(--motif-label); }
.ob-art-chips .is-on { border-color: var(--brand); color: var(--brand-mint); }

/* Motion, the designer's (#4079-#4081): every timeline a 6 s loop. The
   grids breathe in opacity (Figma 1 -> 0.68, deepened below), one wave across the
   columns; each strand cube rides a sine, the two strands in antiphase, the
   phase travelling rightwards; the streaks run their lap linearly and
   wrap; 02b's orb breathes 0.96-1.03 and drifts. Figma samples each track
   32 times, linear between; an ease-in-out between the extremes is the same
   curve. The sample's lines fade in 120 ms apart, once. Reduced motion:
   static. */
.ob-art-cells { --ob-cycle: 6s; }
.ob-art-cells i { animation: ob-art-breathe var(--ob-cycle) ease-in-out calc((var(--c) / var(--cols) - 1) * var(--ob-cycle)) infinite; }
/* Deviation (owner, 2026-11-09): Figma's 0.68 trough is invisible on the
   dim cells of this ground, so the panel's grids fade almost out, to 0.1. */
@keyframes ob-art-breathe { 0%, 100% { opacity: 1; } 50% { opacity: var(--breathe-min, 0.1); } }
.ob-art-strands i { animation: ob-art-strand 6s ease-in-out calc((var(--p) - 1) * 6s) infinite; }
@keyframes ob-art-strand {
  0%, 100% { transform: translateY(calc(var(--k) * 135%)) translateY(calc(var(--s) * var(--amp) * 1px)); }
  50% { transform: translateY(calc(var(--k) * 135%)) translateY(calc(var(--s) * var(--amp) * -1px)); }
}
.ob-art-streak { animation: ob-art-streak 6s linear calc(var(--f) * -6s) infinite; }
@keyframes ob-art-streak {
  from { transform: translate(calc(var(--dx) * -0.5px), calc(var(--dy) * -0.5px)) rotate(var(--r)); }
  to { transform: translate(calc(var(--dx) * 0.5px), calc(var(--dy) * 0.5px)) rotate(var(--r)); }
}
.ob-art-orb { animation: ob-art-orb 6s ease-in-out infinite; }
@keyframes ob-art-orb {
  0%, 100% { transform: translate(0, 0) scale(1); }
  25% { transform: translate(-12px, 8px) scale(1.03); }
  50% { transform: translate(-24px, 0) scale(1); }
  75% { transform: translate(-12px, -8px) scale(0.96); }
}
.ob-art-line { animation: ms-fade-in var(--motion-slow) var(--ease-out) calc(var(--i) * var(--motion-fast)) both; }
@media (prefers-reduced-motion: reduce) {
  .ob-art :is(.ob-art-cells i, .ob-art-strands i, .ob-art-streak, .ob-art-orb, .ob-art-line) { animation: none !important; }
  .ob-art-streaks { display: none; }
}
:root[data-motion="reduce"] .ob-art :is(.ob-art-cells i, .ob-art-strands i, .ob-art-streak, .ob-art-orb, .ob-art-line) { animation: none !important; }
:root[data-motion="reduce"] .ob-art-streaks { display: none; }

/* The sign-in gate's loading state (#4178, onboarding-art.ts obArtWait):
   the wave on a small card of the panel's ground, in the gate's column. It
   fades in 150 ms late, so a fast sign-in shows nothing; under reduced
   motion it appears at once, the wave still. */
.ob-art-wait { display: grid; gap: var(--space-3); justify-items: center; animation: ms-fade-in var(--motion-slow) var(--ease-out) 150ms both; }
.ob-art.ob-art-mini { position: static; width: 100%; height: auto; box-sizing: border-box; padding: 24px 32px; border-radius: var(--radius-xl); }
.ob-art-mini .ob-art-strands { flex: 1; }
.ob-art-wait-text { margin: 0; color: var(--fg-muted); font-size: var(--text-sm); }
@media (prefers-reduced-motion: reduce) { .ob-art-wait { animation: none; } }
:root[data-motion="reduce"] .ob-art-wait { animation: none; }

/* ---- Done (#3491): Figma 04 `1:20336`. The celebration (1:20358, 1:10154's
 * motion, ds/motion.css) above "You're all set" and the setup line, centered
 * in a 440 column, 80 from the top bar, 32 apart. The wizard's header steps
 * aside; an unverified email's note stays. Deviations, for AA: the org line
 * and the setup line take --fg-muted (Figma's #6b7280 / #9ca3af at 13 / 10px
 * are under 4.5:1 in dark / light). ---- */
.ob-wizard[data-ob-at="done"] .ob-head { padding-top: 0; }
.ob-wizard[data-ob-at="done"] .ob-head > :not([data-ob-email]) { display: none; }
.ob-done {
  display: flex; flex-direction: column; align-items: center; gap: var(--space-7);
  box-sizing: border-box; width: 100%; max-width: 440px; margin: 0 auto var(--space-4);
  padding-top: calc(80px - var(--space-7)); text-align: center;
}
.ob-done-art { display: flex; justify-content: center; width: 176px; height: 84px; }
.ob-done-text { display: flex; flex-direction: column; gap: var(--space-2); }
.ob-done-title { margin: 0; font: 700 28px var(--font-mono); color: var(--fg-strong); }
.ob-done h1:focus { outline: none; } /* focused on arrival, as the gate headings */
.ob-done-org { margin: 0; font: 400 13px/22px var(--font-mono); color: var(--fg-muted); overflow-wrap: anywhere; }
.ob-done-note { margin: 0; font: 400 10px var(--font-mono); color: var(--fg-muted); }

/* ---- Responsive (not in Figma) ---- */
@media (max-width: 1023px) {
  .ob-wizard { grid-template-columns: minmax(0, 1fr); }
  .ob-art { display: none; }
}
@media (max-width: 639px) {
  .ob-wizard { --ob-inset: 16px; }
  .ob-top { flex-wrap: wrap; padding: var(--space-4); }
  .ob-head { padding-top: var(--space-7); }
  .ob-done { padding-top: 0; }
  .ob-footer-row { flex-direction: column; align-self: stretch; }
  .ob-footer-row .btn { width: 100%; min-width: 0; }
}

/* ---- Demo stage bar (localhost only, dev-onboarding.ts) ---- */
.dev-ob-bar { position: fixed; left: 75%; top: 12px; z-index: 1000; display: flex; align-items: center; gap: 6px; padding: 6px 8px; transform: translateX(-50%); border: 1px solid var(--border); border-radius: var(--radius-pill); background: var(--surface); box-shadow: var(--shadow-lg, 0 8px 24px rgb(0 0 0 / 0.2)); }
.dev-ob-bar > span { padding: 0 6px; font: 600 11px var(--font-mono); color: var(--fg-muted); }
.dev-ob-stage { position: fixed; inset: 0; z-index: 999; overflow: auto; background: var(--bg); }
