/* Static onboarding.
   Deliberately small: this page's whole job is to paint before the WASM runtime exists, so it
   borrows tokens.css / components.css and adds only what the step cards need. Anything heavier
   belongs in the app, which is booting behind this page anyway. */

.ob {
    min-height: 100vh;
    padding: 24px 16px 40px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 20px;
    background:
        radial-gradient(120% 80% at 50% -10%, rgba(var(--accent-rgb), 0.16), transparent 60%),
        var(--bg);
    color: var(--text);
}

/* Handover (boot.js) hides this element with the `hidden` attribute, whose display:none comes from
   the USER-AGENT sheet — and every author declaration outranks that sheet regardless of specificity.
   Without this line the rule above keeps winning, and the finished onboarding stays stacked above
   the app: the reader's tour opens over the last step, and closing it reveals both at once. */
.ob[hidden] { display: none; }

/* ── Progress dots ───────────────────────────────────────────────── */
.ob-progress { display: flex; gap: 10px; margin: 12px 0 4px; }

.ob-dot {
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: rgba(var(--on-surface-rgb), 0.2);
    transition: background .3s, transform .3s;
}

.ob-dot.is-active { background: var(--button-bg); transform: scale(1.3); }
.ob-dot.is-done { background: rgba(var(--accent-rgb), .5); }

/* ── Step card ───────────────────────────────────────────────────── */
.ob-card {
    width: 100%;
    max-width: 440px;
    background: rgba(var(--on-surface-rgb), 0.045);
    border: 1px solid rgba(var(--on-surface-rgb), 0.12);
    border-radius: 28px;
    padding: 32px 22px 26px;
    display: none;
    flex-direction: column;
    gap: 18px;
    box-shadow: 0 18px 50px -20px rgba(0, 0, 0, 0.45);
}

.ob-card.is-active { display: flex; }

.ob-icon { font-size: 2.6rem; text-align: center; line-height: 1; }

/* Step 0 opens with the brand lock instead of an emoji (see steps.js). The mark keeps the site's
   fixed brand colours; the wordmark inherits var(--text) from .ob, so it survives the light themes
   in tokens.css that a baked-in light-on-dark logo file would not. */
.ob-brand { display: flex; align-items: center; justify-content: center; gap: 12px; }
.ob-brand-mark { width: 52px; height: 44px; flex: none; }

.ob-brand-name {
    font-size: 1.5rem;
    font-weight: 700;
    letter-spacing: -0.03em;
    line-height: 1;
}

/* "Orbit" in terracotta, tying the wordmark to the mark beside it. var(--accent), not the mark's
   own #e07a4e: the token darkens to #b8431f on the light themes, where the dark-theme orange
   reads as washed out against a near-white card. */
.ob-brand-orbit { color: var(--accent); }

.ob-title {
    margin: 0;
    font-size: 1.55rem;
    font-weight: 700;
    letter-spacing: -0.02em;
    text-align: center;
}

.ob-subtitle {
    margin: 0;
    font-size: 0.92rem;
    text-align: center;
    line-height: 1.45;
    color: rgba(var(--on-surface-rgb), 0.75);
}

/* ── Choices ─────────────────────────────────────────────────────── */
.ob-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; }
.ob-grid--3 { grid-template-columns: repeat(3, 1fr); }

.ob-choice {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    padding: 14px 8px;
    border-radius: var(--radius);
    border: 1px solid var(--card-border);
    background: var(--card-bg);
    color: var(--text);
    font-family: inherit;
    font-size: 0.9rem;
    cursor: pointer;
    transition: background .18s, border-color .18s;
}

.ob-choice.is-selected {
    border-color: var(--accent);
    background: rgba(var(--accent-rgb), 0.16);
}

/* ── Buttons ─────────────────────────────────────────────────────── */
.ob-next {
    width: 100%;
    padding: 15px;
    border: none;
    border-radius: var(--radius);
    background: var(--button-bg);
    color: var(--button-text);
    font-family: inherit;
    font-size: 1rem;
    font-weight: 700;
    cursor: pointer;
}

.ob-next:disabled { opacity: .4; cursor: not-allowed; }

.ob-back {
    width: 100%;
    padding: 11px 16px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--card-border);
    background: transparent;
    color: rgba(var(--on-surface-rgb), 0.75);
    font-family: inherit;
    font-size: 0.9rem;
    cursor: pointer;
}

.ob-error {
    margin: 0;
    font-size: 0.88rem;
    text-align: center;
    color: var(--destructive);
}

/* The entrance promise under the level grid — what picking this level commits you to. Mirrors
   .level-contract in OnboardingView.razor; the two pages share the copy, not the stylesheet. */
.ob-contract {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 12px 14px;
    border-radius: var(--radius, 14px);
    border: 1px solid rgba(var(--accent-rgb), 0.28);
    background: rgba(var(--accent-rgb), 0.08);
}

.ob-contract-line {
    margin: 0;
    font-size: 0.9rem;
    line-height: 1.4;
    color: var(--text);
}

.ob-contract-note {
    margin: 0;
    font-size: 0.72rem;
    line-height: 1.35;
    color: var(--ob-muted, var(--text-muted));
}

/* The pace dial, directly under the figure it moves so the cause sits next to the effect.
   Mirrors .pace-picker in OnboardingView.razor (which reuses the app's .lw-segmented; this page
   has no component stylesheet, so the chips are spelled out here). */
.ob-pace {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
}

.ob-pace-label {
    font-size: 0.82rem;
    color: var(--text);
}

.ob-pace-chips {
    display: inline-flex;
    gap: 4px;
    padding: 3px;
    border-radius: 999px;
    background: var(--card-border);
}

.ob-pace-chip {
    min-width: 44px;
    padding: 6px 12px;
    border: none;
    border-radius: 999px;
    background: transparent;
    color: var(--text);
    font-size: 0.85rem;
    cursor: pointer;
    transition: background .15s, color .15s;
}

.ob-pace-chip.is-active {
    background: var(--card-bg);
    color: var(--accent);
    font-weight: 600;
}

.ob-pace-hint {
    margin: -6px 0 0;
    font-size: 0.72rem;
    line-height: 1.35;
    color: var(--ob-muted, var(--text-muted));
}

/* The word check under the level step. Mirrors .wordcheck in OnboardingView.razor. */
.ob-wordcheck {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    justify-content: center;
    max-height: 46vh;
    overflow-y: auto;
}

.ob-wordchip {
    padding: 8px 14px;
    border-radius: 999px;
    border: 1px solid var(--card-border);
    background: var(--card-bg);
    color: var(--text);
    font-size: 0.92rem;
    cursor: pointer;
    transition: background .15s, border-color .15s, color .15s;
}

.ob-wordchip.is-known {
    border-color: transparent;
    background: rgba(var(--accent-rgb), 0.22);
    color: var(--accent);
    font-weight: 600;
}

.ob-contract-credited {
    margin: 0;
    text-align: center;
    font-size: 0.82rem;
    color: var(--ob-muted, var(--text-muted));
}

.ob-wordcheck-count {
    margin: 0;
    text-align: center;
    font-size: 0.8rem;
    color: var(--ob-muted, var(--text-muted));
}

/* The consent line and the way out to the marketing site. Quiet by design — it is a legal
   notice under the button, not a second call to action competing with it. */
.ob-legal {
    margin: 0;
    font-size: 0.72rem;
    line-height: 1.45;
    text-align: center;
    color: rgba(var(--on-surface-rgb), 0.6);
}

.ob-legal + .ob-legal { margin-top: 6px; }

.ob-legal a { color: inherit; text-decoration: underline; }

/* ── Step 0: pitch ───────────────────────────────────────────────── */
.ob-points { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }

.ob-points li {
    position: relative;
    padding-left: 22px;
    font-size: 0.9rem;
    line-height: 1.4;
}

.ob-points li::before {
    content: "";
    position: absolute;
    left: 1px;
    top: 6px;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    border: 2px solid var(--accent);
}

.ob-divider {
    display: flex;
    align-items: center;
    gap: 12px;
    font-size: 0.8rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: rgba(var(--on-surface-rgb), 0.75);
}

.ob-divider::before,
.ob-divider::after { content: ""; flex: 1; height: 1px; background: rgba(var(--on-surface-rgb), 0.14); }

/* Cloudflare renders its own iframe here; the wrapper only needs to not collapse the layout. */
.ob-turnstile:not(:empty) { display: flex; justify-content: center; }

/* ── Step 2: levels + adaptive test ──────────────────────────────── */
.ob-level-code { font-size: 1.4rem; font-weight: 800; }
.ob-level-desc { font-size: 0.7rem; text-align: center; color: rgba(var(--on-surface-rgb), 0.75); }

.ob-progress-bar { height: 4px; border-radius: 2px; background: rgba(var(--on-surface-rgb), 0.1); overflow: hidden; }
.ob-progress-fill { height: 100%; background: var(--button-bg); border-radius: 2px; transition: width .5s ease; }

.ob-question { font-size: 1.05rem; font-weight: 600; }
.ob-options { display: flex; flex-direction: column; gap: 8px; }
.ob-options .ob-choice { align-items: flex-start; text-align: left; }

/* Answer feedback. Colour alone would not carry it for a colour-blind learner, but the correct
   option is also the only one that stays fully opaque — and the next screen names the level. */
.ob-choice.is-correct {
    background: rgba(var(--success-rgb), .28);
    border-color: var(--success);
}

.ob-choice.is-wrong {
    background: rgba(var(--destructive-rgb), .22);
    border-color: var(--destructive);
}

.ob-choice:disabled { cursor: default; opacity: .9; }

/* ── Step 3: interests ───────────────────────────────────────────── */
.ob-tabs {
    display: flex;
    gap: 8px;
    overflow-x: auto;
    padding-bottom: 4px;
    scrollbar-width: none;
    /* The strip is panned by wheel / drag (steps.js enableHorizontalScroll): there is no visible
       scrollbar to grab, so the cursor carries the affordance. */
    cursor: grab;
    user-select: none;
    /* …and the fade says which way there is more. Applied to the element box, not the content, so
       it stays put while the pills move under it. Both classes come from the scroll handler, so a
       strip that fits (or is scrolled to an end) has no fade on that side and looks finished. */
    -webkit-mask-image: var(--ob-tabs-mask, none);
    mask-image: var(--ob-tabs-mask, none);
}
.ob-tabs.has-more-right { --ob-tabs-mask: linear-gradient(to right, #000 calc(100% - 34px), transparent 100%); }
.ob-tabs.has-more-left  { --ob-tabs-mask: linear-gradient(to right, transparent 0, #000 34px); }
.ob-tabs.has-more-left.has-more-right {
    --ob-tabs-mask: linear-gradient(to right, transparent 0, #000 34px, #000 calc(100% - 34px), transparent 100%);
}
.ob-tabs.is-dragging { cursor: grabbing; }
.ob-tabs::-webkit-scrollbar { display: none; }

.ob-tab {
    flex-shrink: 0;
    padding: 6px 14px;
    border-radius: var(--radius-pill);
    white-space: nowrap;
    border: 1px solid var(--card-border);
    background: var(--card-bg);
    color: var(--text);
    font-family: inherit;
    font-size: 0.82rem;
    cursor: pointer;
}

.ob-tab.is-selected { background: var(--button-bg); color: var(--button-text); border-color: transparent; }

.ob-chips { display: flex; flex-wrap: wrap; gap: 10px; }

.ob-chip {
    padding: 8px 14px;
    border-radius: var(--radius-pill);
    border: 1px solid var(--card-border);
    background: var(--card-bg);
    color: var(--text);
    font-family: inherit;
    font-size: 0.88rem;
    cursor: pointer;
}

.ob-chip.is-selected { background: var(--button-bg); color: var(--button-text); border-color: transparent; }

.ob-count { font-size: 0.82rem; text-align: center; color: rgba(var(--on-surface-rgb), 0.75); }

/* ── Step 4: name ────────────────────────────────────────────────── */
.ob-input {
    width: 100%;
    box-sizing: border-box;
    padding: 14px 16px;
    font-family: inherit;
    font-size: 1.05rem;
    text-align: center;
    color: var(--text);
    background: rgba(var(--on-surface-rgb), 0.04);
    border: 1px solid rgba(var(--on-surface-rgb), 0.18);
    border-radius: var(--radius);
}
.ob-input:focus { outline: none; border-color: var(--accent); }

/* ── Step 5: brief ───────────────────────────────────────────────── */
.ob-brief {
    display: flex;
    flex-direction: column;
    gap: 16px;
    padding: 16px;
    border-radius: var(--radius);
    border: 1px solid var(--card-border);
    background: var(--card-bg);
    font-size: 0.85rem;
}

.ob-brief-item { display: flex; align-items: flex-start; gap: 14px; }
.ob-brief-item > span { font-size: 1.5rem; flex-shrink: 0; }

/* The cookie ask, on the same step. Quieter than .ob-brief above it — it is a question we owe the
   visitor, not part of the pitch — but the two buttons are deliberately identical in weight. */
.ob-consent {
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 14px 16px;
    border-radius: var(--radius);
    border: 1px solid var(--card-border);
    background: rgba(var(--on-surface-rgb), 0.04);
}

.ob-consent-title { font-size: 0.9rem; font-weight: 700; }

.ob-consent-body {
    margin: 0;
    font-size: 0.78rem;
    line-height: 1.45;
    color: rgba(var(--on-surface-rgb), 0.7);
}

.ob-consent-body a { color: inherit; text-decoration: underline; }

.ob-consent-actions { display: flex; gap: 10px; }

.ob-consent-btn {
    flex: 1;
    padding: 10px 12px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--card-border);
    background: var(--card-bg);
    color: var(--text);
    font-family: inherit;
    font-size: 0.85rem;
    font-weight: 600;
    cursor: pointer;
}

/* Tinted, not filled: a solid accent here would outrank "Start learning" right below it, and the
   two answers must stay equally easy to give. */
.ob-consent-btn--accept { border-color: var(--accent); background: rgba(var(--accent-rgb), 0.16); }

/* ── Spinner ─────────────────────────────────────────────────────── */
.ob-spinner {
    width: 40px;
    height: 40px;
    margin: 0 auto;
    border: 3px solid rgba(var(--on-surface-rgb), .15);
    border-top-color: var(--button-bg);
    border-radius: 50%;
    animation: ob-spin 0.8s linear infinite;
}

@keyframes ob-spin { to { transform: rotate(360deg); } }
