/* Signup wizard — skeleton styles.
   Tokens mirror the landing page's :root so the funnel doesn't look like a
   different product. Kept as its own file rather than importing styles.css:
   the landing sheet is 27KB of marketing layout the wizard never uses, and
   both are unfingerprinted, so sharing one file would mean every wizard tweak
   invalidates the landing page's CSS too. */

/* Design tokens are the BUSINESS APP's, verbatim from
   momento-business-app/styles/theme/colors.ts. The wizard was built
   standalone and drifted — grey-blue borders (#e5e7eb), a different error red
   (#b42318), a different secondary text (#6b7280). Same values as the app
   now, so a business who signs up on the web and then opens the app is
   looking at one product.

   Page FURNITURE (header, card, progress) stays the landing page's, so the
   funnel still reads as part of momnto.app. The rule where they disagree:
   anything inside the form follows the app; anything around it follows the
   landing. */
:root {
  /* app: primary */
  --orange:        #FE5220;
  --orange-deep:   #E64716;   /* hover only — derived, not an app token */
  --orange-soft:   #FFECE5;   /* tints for notices — derived */
  /* app: textPrimary / textSecondary */
  --ink:           #1E1A17;
  --ink-mute:      #4a4644;
  --text-mute:     #727387;
  /* app: background / white / gray / grayBackground / disabled / error */
  --bg:            #F5F4F9;
  --white:         #FFFFFF;
  --border:        #CFCFD1;
  --field-fill:    #E8E7EE;
  --disabled:      #E4E7EC;
  --error:         #E70000;
  /* app: greenText / greenBorder / greenBackground — verbatim, same rule as
     every token above. Added 02.09 for the portal's subscription-status badge,
     which is the first place in either surface where a state is genuinely
     GOOD and saying so in orange would read as a warning. Unused by the
     wizard today; it lives here because this is where the app's tokens live,
     and a second home is how palettes drift. */
  --green-text:    #067647;
  --green-border:  #ABEFC6;
  --green-bg:      #ECFDF3;

  --shadow-md:     0 10px 30px -12px rgba(17, 24, 39, .18), 0 4px 10px -6px rgba(17, 24, 39, .08);

  /* 6px on every form control, matching the app's rounded-md. --radius stays
     14px: it belongs to the landing's card, which is furniture. */
  --radius-field:  6px;
  --radius-sm:     8px;
  --radius:        14px;
  --radius-sheet:  24px;      /* app: rounded-t-3xl */

  /* Type scale — the app's, which overrides Tailwind's defaults.
     13 / 15 / 17 / 18 / 20 / 24. Body, labels and buttons are 17.
     Headings are 24 Bold and there is NO second heading tier. */
  --fs-xs:         13px;
  --fs-sm:         15px;
  --fs-base:       17px;
  --fs-md:         18px;
  --fs-lg:         20px;
  --fs-title:      24px;
  /* The logotype's size, copied from the landing nav's .wordmark. It is NOT
     a step on the text ramp above — nothing else may use it. It gets a token
     rather than a literal because the ramp rule here is "no literal
     font-size, ever", and a brand constant that lives in two repos is
     exactly the kind of value that should be named where it can be found. */
  --fs-brand:      22px;
    --fs-display:    34px;      /* screen 6 only — the one screen with a lead */

  --field-gap:     16px;      /* the app uses 32 in some steps and 16 in
                                 others; one rhythm, applied everywhere */
  --transition:    180ms cubic-bezier(.4, 0, .2, 1);
}

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

html, body { margin: 0; padding: 0; }

body {
  /* Assistant is Hebrew-only; Inter covers the Latin the wizard shows
     (emails, phone numbers, coupon codes). Per-glyph substitution, same
     pairing the landing page uses. */
  font-family: 'Assistant', 'Inter', system-ui, -apple-system, 'Segoe UI', Arial, sans-serif;
  font-size: var(--fs-base);
  background: var(--bg);
  color: var(--ink);
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
}

/* ---------- Header ---------- */
/* padding-block matches the landing nav's 14px, not the 18px this had. With
   the 34px mark that makes both headers exactly 63px tall, so crossing from
   the landing page into the wizard does not jog the page down. */
.wiz-header {
  /* flex, like the landing's .nav-inner, and for the same reason: the brand
     is an inline-flex anchor, and in a BLOCK container it sits in a line box
     that adds the usual descender leading under it — 5px here, which is why
     the two headers measured 68 vs 64 before this line existed. */
  display: flex;
  align-items: center;
  padding: 14px clamp(16px, 4vw, 32px);
  border-bottom: 1px solid var(--border);
  background: var(--white);
}

/* The landing page's lockup, reproduced. The wizard does not load styles.css,
   so these are copies of .wordmark / .wordmark-mark / .wordmark-text /
   .wordmark-to rather than shared rules — check-design asserts the four
   values that carry the identity so the two cannot drift silently. */
.wiz-brand {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-weight: 800;
  font-size: var(--fs-brand);
  letter-spacing: -0.02em;
  line-height: 1;
  color: var(--ink);
  text-decoration: none;
}

/* ROOT-absolute, and that is load-bearing. The wizard is served from
   /signup/, so a relative "assets/..." resolves to /signup/assets/... — and
   the CDN answers unknown paths with the landing page at HTTP 200, not a
   404. A wrong path here would render a broken image with a success status
   and nothing anywhere would report it. Verified 2026-08-26:
   /assets/logo-mark.png -> 200 image/png 36011b. */
.wiz-brand-mark {
  width: 34px;
  height: 34px;
  object-fit: contain;
}

.wiz-brand-text { color: var(--orange); }
.wiz-brand-to   { color: var(--ink); }

/* ---------- Shell ---------- */
.wiz {
  width: 100%;
  max-width: 560px;
  margin: 0 auto;
  padding: clamp(24px, 5vw, 48px) clamp(16px, 4vw, 24px) 48px;
  flex: 1;
  display: flex;
  flex-direction: column;
}

/* [hidden] MUST WIN.
   The UA sheet's `[hidden] { display: none }` is an attribute selector, so
   ANY class rule setting `display` beats it on specificity. .wiz-progress
   gained `display: flex` on 2026-08-26 and silently stopped responding to
   `progress.hidden = true` — the progress row kept rendering behind every
   interstitial: token expired, next-day, the post-payment return, and the
   final screen.

   Scoped to `display` alone and applied globally rather than patched onto
   .wiz-progress, because the trap is the whole pattern: .wiz-nav, .wiz-brand
   and .wiz-store-btn all set display too, and the next element to be gated
   would hit exactly the same wall. */
[hidden] { display: none !important; }

/* ---------- Progress ---------- */
/* ONE indicator, not three (2026-08-26).
   This was a 4px fill bar, PLUS a row of six 8px dots, PLUS a "שלב 3 מתוך 6"
   line — three drawings of a single fact, stacked, costing 87px above the
   title at 390px before the screen said anything. The dots also escaped their
   own container: .wiz-progress was 4px tall and the <ol> inside it carried
   margin-top: 10px, so they rendered below the box that was supposed to hold
   them.
   Now the segments ARE the bar and the label sits on the same line. */
.wiz-progress {
  display: flex;
  align-items: center;
  gap: 12px;
}

.wiz-steps {
  list-style: none;
  display: flex;
  gap: 4px;
  flex: 1;          /* takes the row; the label keeps its intrinsic width */
  min-width: 0;
  margin: 0;
  padding: 0;
}

/* Six equal segments. flex: 1 rather than a width — six is TOTAL_STEPS in
   wizard.js, and hard-coding 1/6 here would silently misdraw the day the
   wizard gains or loses a step. */
.wiz-steps li {
  flex: 1;
  height: 4px;
  border-radius: 999px;
  background: var(--border);
  transition: background var(--transition), height var(--transition);
}

.wiz-steps li.is-done { background: var(--orange); }

/* "You are here" survives the merge. Colour alone cannot carry it: steps can
   complete OUT OF ORDER on resume (serverDone[]), so a later segment may be
   filled while the current one is earlier, and orange-means-done would then
   point at the wrong place. The height bump is positional, not chromatic. */
.wiz-steps li.is-current {
  background: var(--orange);
  height: 6px;
}

.wiz-stepcount {
  flex: none;
  font-size: var(--fs-xs);
  color: var(--text-mute);
  margin: 0;
  white-space: nowrap;
}

/* ---------- Screens ---------- */
.wiz-screens {
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-md);
  padding: clamp(20px, 4vw, 32px);
  margin-top: 16px;
  flex: 1;
}

.wiz-screen[hidden] { display: none; }

/* LAYOUT FIX (b) — the step counter was colliding with the title.
   .wiz-stepcount has no bottom margin and this had no top margin. That was
   fine while the title lived INSIDE .wiz-screens, whose own margin-top
   supplied the gap; moving the title out of that container removed it and
   nothing replaced it. */
/* One heading tier. The app has no second one, so neither does this — a
   fluid clamp() up to 28px was inventing a size the design language does not
   contain. */
.wiz-title {
  font-size: var(--fs-title);
  font-weight: 700;          /* Assistant-Bold */
  line-height: 1.3;
  margin: 18px 0 8px;
}

.wiz-sub {
  color: var(--text-mute);
  margin: 0;
  font-size: var(--fs-sm);
  line-height: 1.5;
}

/* LAYOUT FIX (c) — the field label read as part of the helper text above it.
   .wiz-sub is margin: 0 (it has to be; several screens stack subtitle lines)
   and .wiz-field has no top margin, so a subtitle immediately followed by a
   field left the helper text and the label flush against each other and they
   scanned as one block. Restore the gap only where that adjacency occurs. */
.wiz-sub + .wiz-field,
.wiz-sub + .wiz-check { margin-top: var(--field-gap); }

/* ---------- Nav ---------- */
.wiz-nav {
  display: flex;
  gap: 12px;
  margin-top: 20px;
}

/* Buttons — app language: 6px radius, 8px padding, semi-bold 17px label,
   full width. The app has no small/inline button variant in this flow. */
.btn {
  font-family: inherit;
  font-size: var(--fs-base);
  font-weight: 600;
  line-height: 1.5;
  padding: 8px 16px;
  min-height: 44px;            /* touch target — the app's h-10 plus padding */
  width: 100%;
  /* Pill, not a field (2026-08-26). The primary action was drawn with
     --radius-field: 6px — an INPUT radius — which is most of why the wizard
     read as a form rather than as the start of something. The landing page's
     CTA is a 999px pill and this is the single change that most closes the gap
     between them. Inputs keep 6px; only the button moved. */
  border-radius: 999px;
  border: 1px solid transparent;
  cursor: pointer;
  transition: background var(--transition), border-color var(--transition), color var(--transition);
}

/* Disabled is a real fill (#E4E7EC), not the old opacity fade. A faded orange
   still reads as "primary, tap me"; the app's flat grey reads as "not yet". */
.btn:disabled {
  cursor: not-allowed;
  background: var(--disabled);
  border-color: var(--disabled);
  color: var(--text-mute);
}

.btn-primary {
  background: var(--orange);
  /* The landing's coloured shadow, which is what lifts the button off the page
     instead of drawing it into the form. Its own value is
     rgba(242,99,51,.55) — a stale colour predating the #FE5220 palette — so
     this uses the current brand orange rather than copying the drift. */
  box-shadow: 0 8px 20px -8px rgba(254, 82, 32, .55);
  color: var(--white);
  flex: 1;
}
.btn-primary:hover:not(:disabled) {
  background: var(--orange-deep);
  box-shadow: 0 14px 26px -10px rgba(254, 82, 32, .65);
}

/* A disabled CTA must not float — the shadow reads as "pressable" and the
   whole point of the disabled state is that it is not. */
.btn-primary:disabled { box-shadow: none; }

/* Secondary: transparent, 1px border, ink label. */
.btn-ghost {
  background: transparent;
  color: var(--ink);
  border-color: var(--border);
}
.btn-ghost:hover:not(:disabled) { border-color: var(--ink); }

.btn:focus-visible { outline: 2px solid var(--orange); outline-offset: 2px; }

/* ---------- Routing probe (skeleton only) ---------- */
.wiz-probe {
  margin-top: 24px;
  font-size: var(--fs-xs);
  color: var(--text-mute);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  direction: ltr;
  text-align: left;
  word-break: break-all;
}

/* ---------- Resume notice (§ חזרה באמצע) ---------- */
.wiz-notice {
  background: var(--orange-soft);
  border: 1px solid rgba(254, 82, 32, .25);
  border-radius: var(--radius-sm);
  padding: 14px 16px;
  margin-top: 14px;
}

.wiz-notice-title { margin: 0; font-weight: 600; font-size: var(--fs-sm); }
.wiz-notice-body  { margin: 4px 0 0; font-size: var(--fs-sm); color: var(--ink-mute); }

/* ---------- Interstitial (§ פג תוקף האימות, § חזרה למחרת) ----------
   A gate in front of the wizard, not a step — it replaces the screen body,
   the nav and the progress bar so there is exactly one thing to do. */
.wiz-interstitial {
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-md);
  padding: clamp(24px, 5vw, 36px);
  margin-top: 16px;
  text-align: center;
}

/* The interstitial supplies its own spacing, so cancel the screen title's
   top margin inside it. */
.wiz-interstitial .wiz-title { margin: 0 0 12px; }
.wiz-interstitial .wiz-sub   { margin-bottom: 8px; }

/* LAYOUT FIX (a) — the heading carried a permanent orange ring.
   Each screen calls title.focus() so a screen-reader or keyboard user lands
   at the top of the new screen. The heading is tabindex="-1", so it is NOT in
   the tab order and can only ever be focused programmatically — meaning
   :focus-visible there never signals "the user navigated here", it just
   leaves a ring sitting on the page after every transition. Suppressed on the
   heading only; real interactive elements keep their rings. */
.wiz-title:focus { outline: none; }

.wiz-block-btn { width: 100%; margin-top: 20px; }

.wiz-footnote {
  margin: 10px 0 0;
  font-size: var(--fs-xs);
  color: var(--text-mute);
}

/* The ₪1 explanation, directly under the button on step 6.
   BOLD AND BODY-COLOURED, not a footnote: it is the sentence that stops a
   business abandoning the handoff when Grow's page says "סכום לתשלום 1 ₪",
   and the muted 12px treatment it used to share with the fine print put the
   most load-bearing line on the screen in the least visible style. */
.wiz-verify-note {
  margin: 12px 0 0;
  font-size: var(--fs-sm);
  font-weight: 700;
  color: var(--ink);
}

/* "services and hours still to set" — genuinely secondary, and separated from
   the fine print above it so the two do not read as one paragraph. */
.wiz-next-steps {
  margin: 14px 0 0;
  font-size: var(--fs-sm);
  color: var(--ink-mute);
  line-height: 1.5;
}

/* Secondary action rendered as a link but focusable as a button. */
.wiz-linkbtn {
  background: none;
  border: 0;
  padding: 8px 4px;
  margin-top: 10px;
  font: inherit;
  font-size: var(--fs-sm);
  color: var(--ink-mute);
  text-decoration: underline;
  cursor: pointer;
}
.wiz-linkbtn:hover { color: var(--ink); }

/* ---------- Already-complete step (§ חזרה אחורה כשאין טיוטה מקומית) ----------
   Shown when the server says the step is done but this tab holds no draft.
   Deliberately NOT an empty required field — that would read as "nothing was
   ever entered", which is false. */
.wiz-complete {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 16px;
  margin-top: 8px;
}

.wiz-complete-line { margin: 0 0 4px; font-size: var(--fs-sm); }
.wiz-complete-line:last-of-type { color: var(--text-mute); font-size: var(--fs-sm); }

.wiz-complete-actions {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-top: 14px;
  flex-wrap: wrap;
}
.wiz-complete-actions .btn { flex: 0 0 auto; }

/* ---------- Screen 1: verified phone + outstanding consents ----------
   Reachable because consents can only be recorded after the OTP. The number
   is shown filled and non-editable so a verified user is not asked to start
   over; only the checkbox is actionable. */
.wiz-verified { margin-top: 8px; }

.wiz-field-label {
  display: block;
  font-size: var(--fs-xs);
  color: var(--text-mute);
  margin-bottom: 6px;
}

.wiz-field-readonly {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 13px 14px;
  font-size: var(--fs-base);
  color: var(--ink-mute);
  direction: ltr;
  text-align: left;
}

.wiz-verified-badge {
  color: #067647;
  font-weight: 800;
  flex: 0 0 auto;
}

/* Checkbox — 24x24, 6px radius, 2px #727387 border, primary fill when on,
   8px gap to a 15px label. A native checkbox cannot be styled to that spec on
   iOS Safari (it ignores border-radius and border-color on the default
   control), so the input is restyled with appearance:none and draws its own
   tick. It stays a real <input> in the DOM and in the tab order — still what
   a screen reader announces and what the <label> is bound to. */
.wiz-check {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  margin-top: var(--field-gap);
  font-size: var(--fs-sm);
  line-height: 1.6;
  cursor: pointer;
}

.wiz-check input {
  appearance: none;
  -webkit-appearance: none;
  flex: 0 0 auto;
  width: 24px;
  height: 24px;
  margin: 0;
  border: 2px solid var(--text-mute);
  border-radius: var(--radius-field);
  background: transparent;
  cursor: pointer;
  position: relative;
  transition: background var(--transition), border-color var(--transition);
}

.wiz-check input:checked {
  background: var(--orange);
  border-color: var(--orange);
}

/* The tick, drawn rather than set as a glyph so it scales with the box and
   needs no icon font. */
.wiz-check input:checked::after {
  content: '';
  position: absolute;
  inset-inline-start: 7px;
  top: 2px;
  width: 6px;
  height: 12px;
  border: solid var(--white);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}

.wiz-check input:focus-visible { outline: 2px solid var(--orange); outline-offset: 2px; }

.wiz-check a { color: var(--orange); text-decoration: underline; }

/* Sub-label under a checkbox — "ניתן לבטל בכל עת" under the marketing consent.
   Indented by the checkbox width (24px) plus the flex gap (8px) so it lines up
   under the LABEL TEXT rather than under the box; the document calls for it
   "מתחת לצ׳קבוקס — באותיות קטנות", which means under the sentence, not under
   the control. Same font, ~85% size, muted — it is a reassurance, not a second
   instruction competing with the label. */
.wiz-check-sub {
  margin: 4px 0 0;
  padding-inline-start: 32px;
  font-size: 85%;
  line-height: 1.5;
  color: var(--text-mute);
}

/* Inline aside link — "הקטגוריה שלי לא כאן" on the category screen.
   Quiet on purpose: it sits between the specialities and the CTA and must not
   compete with either. Underlined rather than coloured-only, so it reads as a
   link without borrowing the primary colour the CTA owns. */
.wiz-inline-link-wrap {
  margin: 4px 0 16px;
  font-size: 90%;
}

.wiz-inline-link {
  color: var(--text-mute);
  text-decoration: underline;
}

.wiz-inline-link:hover,
.wiz-inline-link:focus-visible {
  color: var(--orange);
}

/* ---------- Form fields (mobile first) ---------- */
.wiz-field { margin-bottom: var(--field-gap); }

/* Label sits above the field with a 4px gap and shifts colour with state,
   mirroring the app's FieldWithLabel: default -> primary on focus -> error.
   The state classes are set by fields.js. */
.wiz-label {
  display: block;
  font-size: var(--fs-base);
  font-weight: 600;
  line-height: 1.5;
  color: var(--ink);
  margin-bottom: 4px;
  transition: color var(--transition);
}
.wiz-field.is-focused .wiz-label { color: var(--orange); }
.wiz-field.is-error   .wiz-label { color: var(--error); }

/* The input itself.

   FILL is stateful, not constant: transparent while empty, #E8E7EE once
   focused or filled. That is the app's `!!value ? bg-grayBackground :
   bg-transparent` plus `focus:bg-grayBackground`. The filled state is what
   makes a long form scannable — you can see at a glance what you have
   answered.

   TEXT COLOUR is #1E1A17, deliberately. Orange is the action colour — it
   belongs to buttons, links and focus. Spending it on content weakens that
   signal, and orange on light grey is poor contrast besides.

   17px keeps us above the 16px floor where iOS Safari zooms the page on
   focus, so the app's scale and that constraint agree. */
.wiz-input {
  width: 100%;
  font-family: inherit;
  font-size: var(--fs-base);
  line-height: 1.5;
  padding: 8px;
  border: 1px solid var(--border);
  border-radius: var(--radius-field);
  background: transparent;
  color: var(--ink);
  transition: border-color var(--transition), background var(--transition);
}

.wiz-input::placeholder { color: var(--text-mute); opacity: 1; }

.wiz-input.has-value { background: var(--field-fill); }

.wiz-input:focus {
  outline: none;
  border-color: var(--orange);
  background: var(--field-fill);
}

/* Error border is 2px, and compensated with 1px less padding so the control
   does not grow by 2px and nudge the layout when it goes invalid. */
.wiz-input.is-invalid {
  border: 2px solid var(--error);
  padding: 7px;
}
.wiz-input.is-invalid:focus { border-color: var(--error); }

/* Phone, OTP and coupon read left-to-right even inside the RTL page. */
input[type="tel"].wiz-input,
/* The typed digit fields stay LTR so "06/10/1996" and a 6-digit OTP do not
   reorder. This also applies to the TOUCH variant of the date, which is a
   <button class="wiz-press"> sharing the id — see .wiz-press-chevron below,
   where that has a consequence worth knowing about. */
#otp, #coupon, #birthDate { direction: ltr; text-align: right; }

.wiz-input-code {
  letter-spacing: .5em;
  text-align: center;
  font-size: var(--fs-title);
  font-weight: 700;
}

.wiz-hint  { margin: 4px 0 0; font-size: var(--fs-sm); color: var(--text-mute); line-height: 1.5; }
.wiz-error { margin: 4px 0 0; font-size: var(--fs-sm); color: var(--error); line-height: 1.5; }
.wiz-error-screen { margin-top: var(--field-gap); }
.wiz-error a, .wiz-coupon a { color: var(--error); text-decoration: underline; }

/* ---------- Chips (gender, category, sub-categories) ---------- */
.wiz-chips, .wiz-radiogroup {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 6px;
}

/* Chips survive on screen 5 (category / sub-categories). Gender no longer
   uses them — it moved to the same bottom sheet the app uses. */
.wiz-chip {
  font-family: inherit;
  font-size: var(--fs-sm);
  padding: 8px 16px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: transparent;
  color: var(--ink);
  cursor: pointer;
  transition: background var(--transition), border-color var(--transition), color var(--transition);
}

.wiz-chip:hover { border-color: var(--ink); }

.wiz-chip.is-selected {
  background: var(--orange);
  border-color: var(--orange);
  color: var(--white);
  font-weight: 600;
}

.wiz-chip:focus-visible { outline: 2px solid var(--orange); outline-offset: 2px; }

.wiz-sub-sub { margin-top: 18px; }

/* ---------- Coupon ---------- */
.wiz-coupon { margin: 20px 0 4px; }
.wiz-coupon-panel { margin-top: 10px; }
.wiz-coupon-applied {
  margin: 8px 0 0;
  font-size: var(--fs-sm);
  color: #067647;
  font-weight: 600;
}

/* ---------- Links row (resend / change number) ---------- */
.wiz-links {
  display: flex;
  gap: 18px;
  justify-content: center;
  margin-top: 14px;
}

/* § מסך 5 — the coupon field and its הפעלה button on one row. The field takes
   the space and the button is sized to its text: the button is a helper, not
   the screen's action, and .btn-ghost keeps it visually below the orange
   primary below it. align-items: start so the button aligns with the INPUT and
   does not drift when the field renders an error line beneath itself. */
.wiz-coupon-row {
  display: flex;
  gap: 8px;
  align-items: flex-start;
}
.wiz-coupon-row .wiz-field { flex: 1 1 auto; margin-bottom: 0; }
.wiz-coupon-apply {
  flex: 0 0 auto;
  width: auto;
  padding-inline: 18px;
  height: 48px;
}

/* The way out of the existing-account card. Quiet and below the download
   button: the card's primary action is the app, and this is for the minority
   who landed here by a typo. Centred to match the card's own alignment. */
.wiz-existing-fix {
  display: block;
  margin: 12px auto 0;
  font-size: var(--fs-sm);
}

/* ---------- § מעטפת משותפת — the permanent help link ----------
   Quiet by construction: it must be findable from every screen without ever
   competing with that screen's action. Muted, small, centred under the nav,
   and it does NOT get the orange treatment the five failure CTAs use — those
   mean "something broke"; this one means "we are here". */
.wiz-help {
  margin: 24px 0 0;
  text-align: center;
}
.wiz-help-link {
  font-size: var(--fs-sm);
  color: var(--text-mute);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.wiz-help-link:hover { color: var(--ink); }
.wiz-help-link:focus-visible { outline: 2px solid var(--orange); outline-offset: 2px; border-radius: 4px; }

/* ---------- § מסך 1ב "לא הגיע?" ----------
   Sits under the resend/change links on the code screen. Deliberately quiet:
   it is a reassurance, not an action, and the two buttons above it are the
   actions. Label at body weight so the question is findable, the line beneath
   it in the same muted tone .wiz-hint uses for every other explanatory line in
   the wizard — one voice for "extra information", wherever it appears. */
.wiz-notarrived {
  margin-top: 20px;
  text-align: center;
}
.wiz-notarrived-label {
  margin: 0;
  font-size: var(--fs-sm);
  font-weight: 700;
  color: var(--ink);
}
.wiz-notarrived-hint {
  margin: 2px 0 0;
  font-size: var(--fs-sm);
  color: var(--text-mute);
  line-height: 1.5;
}

/* ---------- Busy button ---------- */
.btn.is-busy { position: relative; color: transparent; }
.btn.is-busy::after {
  content: "";
  position: absolute;
  inset: 0;
  margin: auto;
  width: 18px; height: 18px;
  border: 2px solid rgba(255,255,255,.45);
  border-top-color: var(--white);
  border-radius: 50%;
  animation: wiz-spin .7s linear infinite;
}
@keyframes wiz-spin { to { transform: rotate(360deg); } }

/* Screen-reader-only label — the visible subtitle already names the field. */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.wiz-screens:empty { display: none; }

/* Google Places dropdown must sit above the card and read RTL-correctly. */
.pac-container { z-index: 9999; direction: rtl; text-align: right; font-family: 'Assistant', sans-serif; }

@media (min-width: 560px) {
  .wiz-nav { justify-content: flex-start; }
}

/* ---------- Return from Grow (§ החזרה מהסליקה) ----------
   Three states inside the interstitial gate: waiting, still-waiting, and
   not-saved. The interstitial is already centred and boxed, so these only add
   the spinner and the spacing that separates the after-a-minute line from the
   message it follows. */
.wiz-return-body .wiz-sub { margin-bottom: 8px; }

.wiz-return-slow {
  margin-top: 18px;
  padding-top: 14px;
  border-top: 1px solid var(--border);
}

.wiz-return-slow .wiz-sub { color: var(--text-mute); font-size: var(--fs-sm); }
.wiz-return-slow a { color: var(--orange-deep); }

.wiz-return-actions:empty { display: none; }

/* Motion is the only thing telling the user we are still working — the copy
   says "עוד רגע וסיימנו", and a static page contradicts it. */
.wiz-spinner {
  width: 28px;
  height: 28px;
  margin: 4px auto 14px;
  border: 3px solid var(--orange-soft);
  border-top-color: var(--orange);
  border-radius: 50%;
  animation: wiz-spin 900ms linear infinite;
}

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

/* Respect the OS setting: keep the affordance, drop the rotation. */
@media (prefers-reduced-motion: reduce) {
  .wiz-spinner { animation: none; opacity: .6; }
}

/* ---------- § מסך הסיום — the final screen ----------
   Lives inside the interstitial gate (it is not a numbered step), so it
   inherits the centred card. Only the store button and the QR need styling. */
/* display: FLEX, not inline-flex — CONSISTENCY, not the overlap fix.
   Measured 06.10: making this one block-level changes nothing on its own (the
   two buttons still overlapped by 8px), because the colliding box was the
   SECOND one. Kept anyway so both final-screen buttons are block-level by the
   same mechanism instead of one being fixed and one inheriting; plain flex
   centres the store mark exactly as inline-flex did. The real cause is on
   .wiz-portal-btn below. */
.wiz-store-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  text-decoration: none;
}

/* THE OVERLAP FIX (06.10), and the whole of it.
   This class was already on the element — screens.js has emitted
   `btn btn-ghost wiz-block-btn wiz-portal-btn` since the button shipped — but
   it had NO RULE anywhere in this file, so the button took `display:
   inline-flex` from .btn. An atomic inline-level box with width:100% and
   margin-top:20px does not push the preceding line box out of its way, and at
   390px it rendered 8px INSIDE the store button above it.

   Decomposed by measurement rather than by reading, because the obvious
   suspect was wrong:

     store inline-flex, no rule here   ->  gap  -8px   (what shipped)
     store FLEX,        no rule here   ->  gap  -8px   (fixing the wrong one)
     store flex,        this rule      ->  gap  +28px

   28px rather than .wiz-block-btn's 20px: this button follows either a
   full-width store button or a 200px QR, and 20px read as "attached to the
   thing above" in both. */
.wiz-portal-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  margin-top: 28px;
  text-decoration: none;
}

/* flex: none so the mark never squashes when the label wraps. */
.wiz-store-btn svg { width: 20px; height: 20px; flex: none; }

/* ---------- § מסך הסיום — the card itself ----------
   .wiz-interstitial is shared with the failure states: token expired and the
   next-day block. Identical card, identical border, identical shadow — so
   the one screen that should feel like an arrival was wearing the same
   costume as "your session died".

   A warm wash from the top and an orange-tinted edge, rather than a coloured
   header band: the band would compete with the completed indicator sitting
   at the top of the card, and the wash reads under it instead. */
.wiz-interstitial.is-celebration {
  border-color: rgba(254, 82, 32, .3);
  background:
    linear-gradient(180deg, var(--orange-soft) 0%, rgba(255, 236, 229, 0) 200px),
    var(--white);
  box-shadow:
    0 20px 44px -26px rgba(254, 82, 32, .5),
    var(--shadow-md);
}

/* ---------- § מסך הסיום — the completed indicator ---------- */
/* Reuses .wiz-progress / .wiz-steps wholesale so it cannot drift from the
   live one. Only the spacing and the tick are new. */
.wiz-progress-complete {
  margin-bottom: 20px;
}

.wiz-final-check {
  flex: none;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--orange);
  color: var(--white);
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.wiz-final-check svg { width: 13px; height: 13px; }

.wiz-final-subtitle {
  margin: 28px 0 6px;
  font-size: var(--fs-base);
  font-weight: 700;
  color: var(--ink);
}

/* The QR is a link. Give it a real focus ring — it is the only way to reach
   the download without a camera. */
.wiz-qr-link {
  display: inline-block;
  margin-top: 14px;
  padding: 10px;
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  line-height: 0;
}

.wiz-qr-link:focus-visible { outline: 2px solid var(--orange); outline-offset: 3px; }

.wiz-qr { width: 200px; height: 200px; display: block; }

/* ---------- § מסך 1, מצב: כבר קיים חשבון ----------
   Mirrors the app's phone step (login.constants.ts phoneAlreadyRegistered +
   loginButton): an inline block UNDER the phone field, primary colour rather
   than danger, body size rather than heading, with the field still visible
   and editable above it so a mistyped number is trivially corrected.

   It replaced a full-screen, error-styled takeover at heading size, which
   read as a broken page — LAYOUT FIX (d). */
.wiz-existing {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  margin-top: 18px;
  padding: 18px 16px;
  background: var(--orange-soft);
  border-radius: var(--radius-sm);
  text-align: center;
}

.wiz-existing p {
  margin: 0;
  font-size: var(--fs-base);
  font-weight: 600;
  /* Primary ink, NOT the danger colour. This is a discovery, not a failure. */
  color: var(--ink);
}

.wiz-existing .wiz-existing-sub { font-weight: 400; color: var(--ink-mute); }

.wiz-existing a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  text-decoration: none;
}

/* ==========================================================================
   Pressable field + bottom sheet + wheel picker
   ==========================================================================
   Date of birth and gender are not typed. They open a bottom sheet holding a
   scroll wheel (date) or a plain list (gender), mirroring the business app's
   DrawerField -> PickerModal -> DateWheelPicker chain.

   Why a wheel and not <input type="date"> or a <select>: a 120-year year
   field is unusable as a dropdown and painful to type on a phone, which is
   where most signups happen. The native date input also renders as a
   different control on every platform, which is the drift this redesign is
   undoing. */

/* ---------- the pressable ----------
   Looks exactly like .wiz-input — same border, radius, padding, stateful
   fill — but it is a <button>. Mirrors the app's DrawerField. */
.wiz-press {
  width: 100%;
  font-family: inherit;
  font-size: var(--fs-base);
  line-height: 1.5;
  padding: 8px;
  min-height: 40px;                    /* the app's h-10 */
  border: 1px solid var(--border);
  border-radius: var(--radius-field);
  background: transparent;
  color: var(--text-mute);             /* placeholder state */
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  text-align: start;
  transition: border-color var(--transition), background var(--transition), color var(--transition);
}

.wiz-press.has-value {
  background: var(--field-fill);
  color: var(--ink);                   /* NOT orange — see .wiz-input */
}

/* "Focused" here means the sheet this field owns is open. */
.wiz-press.is-open { border-color: var(--orange); background: var(--field-fill); }
.wiz-press:focus-visible { outline: 2px solid var(--orange); outline-offset: 2px; }

.wiz-press.is-invalid { border: 2px solid var(--error); padding: 7px; }

/* Chevron, drawn as a rotated border so there is no icon dependency. */
/* Takes the free space, so the chevron is pinned to one edge rather than
   floating beside a short value. */
.wiz-press-value { flex: 1 1 auto; text-align: start; }

/* ── THE DATE FIELD'S CHEVRON, AND ONLY THE CHEVRON (06.10) ───────────────
   #birthDate is both a typed <input> (desktop) and a .wiz-press <button>
   (touch), and the LTR rule above — written for the input, where digits must
   not reorder — also reverses the BUTTON's flex main axis. With
   justify-content: space-between that put its chevron at the RIGHT edge while
   the gender field one row below kept its chevron at the LEFT, on the same
   screen.

   The fix moves the chevron and NOTHING ELSE. `order: -1` makes it the first
   flex item and `flex-start` keeps the row packed, so the chevron lands at the
   left edge — the same edge as every other press field — while the date's
   digits stay left-aligned and LTR exactly as they are today, shifted right
   only by the chevron's own width.

   The alternative, flipping the button to RTL, would also have aligned the
   chevrons but would have thrown the digits across to the opposite edge. That
   is a change to the date field, which is explicitly not wanted here. */
#birthDate.wiz-press { justify-content: flex-start; gap: 10px; }
#birthDate.wiz-press .wiz-press-chevron { order: -1; }

.wiz-press-chevron {
  flex: 0 0 auto;
  width: 8px;
  height: 8px;
  border: solid var(--text-mute);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
  margin-block-end: 3px;
}

/* ---------- the sheet ----------
   A native <dialog> opened with showModal(). That buys the focus trap, Esc,
   background inertness and a top-layer backdrop from the platform rather than
   from hand-written JS, all four of which are easy to get subtly wrong. */
/* The dialog is a full-viewport, transparent stage; the panel inside it is
   what you see. Sizing it EXPLICITLY matters: a <dialog>'s UA style is
   `width/height: fit-content; margin: auto`, and since this one's only child
   is absolutely positioned there is no in-flow content to size against — the
   box collapses and bottom:0 on the panel then anchors to a zero-height
   parent, putting the sheet off-screen above the viewport. Overriding the
   width, height, max-width, max-height and margin is what keeps it on
   screen. */
.wiz-sheet {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  max-width: none;
  max-height: none;
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
  overflow: hidden;
}

.wiz-sheet::backdrop { background: rgba(0, 0, 0, .5); }

/* The panel is the sheet's focus target on open (tabindex="-1", see
   fields.js open()). It is never in the tab order, so suppressing its ring
   costs no keyboard affordance — and leaving it on replaces the orange ring
   this change removed with Chrome's default blue one. Controls inside the
   sheet keep their own :focus-visible rings. */
.wiz-sheet-panel:focus { outline: none; }

.wiz-sheet-panel {
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  width: 100%;
  max-width: 560px;                    /* the wizard's own measure — a
                                          full-width sheet on a desktop
                                          monitor reads as broken */
  margin-inline: auto;
  max-height: 90%;
  overflow: auto;
  background: var(--white);
  border-radius: var(--radius-sheet) var(--radius-sheet) 0 0;
  padding: 20px;
  /* Clear the iOS home indicator / Android gesture bar. */
  padding-bottom: calc(20px + env(safe-area-inset-bottom, 0px));
  animation: wiz-sheet-in 220ms cubic-bezier(.4, 0, .2, 1);
}

@keyframes wiz-sheet-in { from { transform: translateY(100%); } to { transform: none; } }

.wiz-sheet-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 8px;
}

/* Same 24px Bold as a screen title — the app reuses its Title component here
   and passes the FIELD LABEL as the sheet title, so no new copy is needed. */
.wiz-sheet-title { font-size: var(--fs-title); font-weight: 700; margin: 0; }

/* The confirm/close action is a text button in the header, not a full-width
   primary button, matching the app's Drawer. */
.wiz-sheet-action {
  background: none;
  border: 0;
  padding: 8px;
  margin: 0;
  font: inherit;
  font-size: var(--fs-base);
  font-weight: 600;
  color: var(--orange);
  cursor: pointer;
  border-radius: var(--radius-field);
}
.wiz-sheet-action:focus-visible { outline: 2px solid var(--orange); outline-offset: 2px; }

/* ---------- the wheel ---------- */
.wiz-wheel-wrap {
  position: relative;
  height: 280px;                       /* 40 x 7 rows */
  display: flex;
  flex-direction: row;                 /* forced LTR below */
  direction: ltr;                      /* day | month | year, as the app */
  justify-content: center;
  align-items: stretch;
  gap: 4px;
}

/* The selected-row highlight. One static overlay, not a per-row style. */
.wiz-wheel-highlight {
  position: absolute;
  inset-inline: 12px;
  top: 120px;                          /* 3 rows */
  height: 40px;
  border-radius: 20px;
  background: rgba(120, 120, 128, .12);
  pointer-events: none;
}

.wiz-wheel {
  flex: 0 0 auto;                      /* never let flex shrink a column to 0 */
  /* Each column fills its third of the wrap (2026-08-25).
     Before this the columns were flex: 0 0 auto and centred, so day/month/year
     measured 64 / 120 / 84px inside a 520px wrap — 276px of column in 520px of
     picker. Sampling every 5px across the wheel showed 48% of it was DEAD: a
     mouse wheel there scrolled nothing, because the pointer was over the wrap
     rather than over a scroll container. That is the whole of "I have to click
     each column separately" — she had to land on a 64px target inside a 520px
     box, and missed about half the time.
     Now 171 / 171 / 171 with 0% dead. This fixes touch drag for the same
     reason, which a wheel-event workaround would not have.
     NOT a scroll-snap problem: measured mouse-notch, trackpad and Magic Mouse
     delta patterns against y mandatory / y proximity / none, and movement was
     identical in all nine combinations. */
  flex: 1 1 0;
  height: 280px;
  overflow-y: auto;
  overflow-x: hidden;
  /* CSS scroll-snap does the physics: native momentum and snapping, which is
     the web analogue of RN's snapToInterval + decelerationRate="fast". */
  scroll-snap-type: y mandatory;
  overscroll-behavior: contain;        /* never scroll the sheet behind it */
  -webkit-overflow-scrolling: touch;
  /* 3 rows of padding top and bottom so the first and last item can reach the
     centre. This is also what makes index === scrollTop / 40 exactly. */
  padding-block: 120px;
  scrollbar-width: none;
}
.wiz-wheel::-webkit-scrollbar { display: none; }
.wiz-wheel:focus-visible { outline: 2px solid var(--orange); outline-offset: -2px; border-radius: var(--radius-field); }

.wiz-wheel-item {
  height: 40px;
  scroll-snap-align: center;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--fs-title);
  font-weight: 400;
  color: var(--ink);
  white-space: nowrap;
  /* opacity and scale are written by JS on the rows near the centre only —
     see wheel() in fields.js. These are the resting values for rows outside
     that window. */
  opacity: .1;
  transform: scale(.82);
  will-change: opacity, transform;
}

/* ---------- gender list ---------- */
.wiz-sheet-list { list-style: none; margin: 0; padding: 0; }

.wiz-sheet-option {
  width: 100%;
  font-family: inherit;
  font-size: var(--fs-base);
  line-height: 1.5;
  text-align: start;
  padding: 12px 8px;
  border: 0;
  border-radius: var(--radius-field);
  background: transparent;
  color: var(--ink);
  cursor: pointer;
}
.wiz-sheet-option:hover { background: var(--field-fill); }
.wiz-sheet-option[aria-selected="true"] { color: var(--orange); font-weight: 600; }
.wiz-sheet-option:focus-visible { outline: 2px solid var(--orange); outline-offset: -2px; }

/* ---------- reduced motion ----------
   Drop the slide-up and the per-row scale. Snapping stays: it is the
   control's behaviour, not decoration. */
@media (prefers-reduced-motion: reduce) {
  .wiz-sheet-panel { animation: none; }
  .wiz-wheel-item { transition: none; transform: none !important; }
}

/* ---------- address autocomplete ----------
   Our own dropdown, not Google's. The legacy Places widget injected its own
   list; the New API returns JSON, so the list is built in places.js and
   styled here to match the rest of the wizard instead of arriving with a
   third-party look and a hard-to-override z-index. */
.wiz-ac-host { position: relative; }

.wiz-ac-list {
  position: absolute;
  inset-inline: 0;
  top: 100%;
  z-index: 20;
  margin: 4px 0 0;
  padding: 4px;
  list-style: none;
  max-height: 264px;              /* 6 rows before it scrolls */
  overflow-y: auto;
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  box-shadow: 0 8px 24px rgba(0, 0, 0, .12);
}

.wiz-ac-item {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 10px 12px;
  border-radius: 8px;
  cursor: pointer;
  line-height: 1.4;
}

/* Hover and keyboard selection are the same visual state on purpose — two
   different highlights in one list reads as two different selections. */
.wiz-ac-item:hover,
.wiz-ac-item.is-active { background: var(--bg); }

.wiz-ac-main { font-size: var(--fs-base); color: var(--ink); }
.wiz-ac-sec  { font-size: var(--fs-xs); color: var(--text-mute); }

/* ---------- desktop: centre the sheet instead of anchoring it to the bottom
   A bottom-anchored panel assumes the viewport's bottom edge is on screen.
   On a desktop window that is not guaranteed: measured on Yael's machine
   2026-08-25, innerHeight was 1166 against a ~1080 display, so the panel sat
   at 800->1166 and the wheel's last row and a half — 66px — rendered below
   the visible screen. getBoundingClientRect reported nothing wrong, because
   nothing IS wrong relative to the viewport; the viewport itself extended
   past the display.

   THIS IS WHY NO HEIGHT CAP FIXES IT. 90%, 100dvh and 100svh all resolve
   against that same oversized viewport, so capping height just produces a
   smaller box still anchored to an off-screen edge. Centring is the fix
   because it stops depending on the bottom edge and depends on the centre
   instead, which is visible by definition — you are looking at the window.
   Measured after: panel 400->766, 0px past a 1080 screen.

   pointer: fine ONLY. A touch device cannot have a viewport taller than its
   screen, so it keeps the bottom sheet that mirrors the business app's
   DrawerField -> PickerModal. This is a desktop-shaped fix for a
   desktop-shaped problem, not a redesign. */
@media (pointer: fine) {
  .wiz-sheet-panel {
    top: 50%;
    bottom: auto;
    transform: translateY(-50%);
    /* All four corners: it is a centred dialog now, not a sheet rising from
       the bottom edge, and two square corners would read as a clipped sheet —
       the exact impression we are fixing. */
    border-radius: var(--radius-sheet);
    /* The bottom-sheet keyframe animates translateY(100%) -> none, which would
       cancel the centring transform above. Fade and lift instead. */
    animation: wiz-dialog-in 220ms cubic-bezier(.4, 0, .2, 1);
  }
}

@keyframes wiz-dialog-in {
  from { opacity: 0; transform: translateY(calc(-50% + 12px)); }
  to   { opacity: 1; transform: translateY(-50%); }
}

@media (prefers-reduced-motion: reduce) {
  .wiz-sheet-panel { animation: none; }
}

/* ---------- screen 6: one thing leads ----------
   Every element on the payment screen was 15px/400 grey, including the price,
   so nothing led and the screen read as a form. Measured at 390px before
   changing anything: the composed screen ends at 509px in an 844px viewport,
   335px of headroom, so this costs no scroll.

   The TITLE leads, not the price. This screen's job is getting a card saved,
   and what lowers resistance to entering one is "the first month is free" —
   which the title already says — not "it costs 125 ₪". The landing page's
   pricing card leads with 72px because that section's job is to state a price;
   this screen's is not. Decided 25.08 after proposing the opposite.

   No copy changed. Only which words carry weight. */
.wiz-title.is-display {
  font-size: var(--fs-display);
  font-weight: 800;
  line-height: 1.15;
  /* Matches the landing hero's optical correction at the same size — large
     Hebrew display type sets loose without it. */
  letter-spacing: -0.01em;
  margin-bottom: 12px;
}


@media (min-width: 560px) {
  .wiz-title.is-display { font-size: calc(var(--fs-display) + 6px); }
}

/* ---------- screen 6: what's included ----------
   Was one 15px paragraph carrying the price and three separate claims. A list
   lets each claim be scanned on its own, which is what a phone reader does. */
.wiz-list {
  list-style: none;
  margin: 12px 0 16px;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.wiz-list li {
  position: relative;
  padding-inline-start: 24px;
  font-size: var(--fs-base);
  line-height: 1.45;
  color: var(--ink);
}

/* Check mark drawn as a rotated border — no icon dependency, matching the
   chevron on .wiz-press. */
.wiz-list li::before {
  content: '';
  position: absolute;
  inset-inline-start: 4px;
  top: 7px;
  width: 5px;
  height: 10px;
  border: solid var(--orange);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}

/* Answers "am I being charged today". Body size, not fine print. */
.wiz-sub-closing {
  margin-top: 4px;
  font-size: var(--fs-sm);
  color: var(--ink-mute);
}

/* ---------- preview banner ----------
   Only ever rendered by /signup/preview. Permanent and non-dismissable: on a
   production domain the real risk is not somebody seeing unreleased design,
   it is somebody believing they signed up here. */
.wiz-preview-banner {
  position: sticky;
  top: 0;
  z-index: 100;
  padding: 10px 16px;
  background: var(--ink);
  color: var(--white);
  font-size: var(--fs-xs);
  font-weight: 600;
  text-align: center;
  line-height: 1.4;
}

/* ── non-production API badge ──────────────────────────────────────────────
   Shown ONLY when apiEnv() !== 'production' (wizard.js). It answers one
   question — which API is this browser talking to — that had no answer on
   screen at all, and whose absence cost two days on the 27-28.08 expiry
   screen: a staging signup returned from Grow against the production API and
   looked exactly like a staging one.

   Deliberately ugly. This is an instrument, not chrome; it should read as
   "you are not on the real thing" at a glance and never be mistaken for part
   of the product. Bottom-centre keeps it clear of the header lockup and of
   the sticky CTA that sits at the bottom edge on the taller screens. */
.wiz-envbadge {
  position: fixed;
  bottom: 8px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 1000;              /* above the interstitial (100) — it must stay
                                 visible on the return and expiry screens,
                                 which are precisely where it is needed */
  padding: 4px 10px;
  border-radius: 999px;
  background: #1E1A17;
  color: #FFD400;
  font: 700 11px/1.4 'Inter', ui-monospace, monospace;
  letter-spacing: .08em;
  text-transform: uppercase;
  /* LTR: the content is an API host key, not Hebrew prose. */
  direction: ltr;
  pointer-events: none;       /* never intercepts a tap on the CTA behind it */
  opacity: .92;
}

@media print { .wiz-envbadge { display: none; } }

/* Action inside the resume notice. The notice is two stacked <p>s; the link
   needs to sit under them rather than run on from the body text. */
.wiz-notice-action { margin-top: 6px; }
