/* ═══════════════════════════════════════════════════════════════
   TehranPay purchase flow ("Flow") — scoped presentation layer.
   Loaded AFTER v3-base.css on: buy, checkout, bank transfer, payment
   result, order status. Everything is scoped under body.flow so no
   other V3 page is affected. Design source: .design-backups/
   buy-apple-redesign-2026-09-06/build_polish.py. Interaction source:
   docs/superpowers/specs/2026-09-07-purchase-flow-interaction-spec.md
   ═══════════════════════════════════════════════════════════════ */

/* ── 1. Tokens ─────────────────────────────────────────────── */
.flow {
  --fl-bg: #FAF8FF; --fl-surface: #FFFFFF; --fl-surface-2: #F3EFF9; --fl-hair: #E1D7EE; --fl-hair-2: #C9BFE0;
  --fl-fg: #171124; --fl-fg-2: #645A75;
  --fl-accent: #7C3AED; --fl-accent-soft: #EDE6FE; --fl-on-accent: #FFFFFF; --fl-ring: rgba(124,58,237,.4);
  --fl-success: #16A34A; --fl-success-soft: #E7F7EC; --fl-warning: #B45309; --fl-warning-soft: #FDF3E1;
  --fl-danger: #DC2626; --fl-danger-soft: #FDECEC; --fl-ring-danger: rgba(220,38,38,.25);
  --fl-material: rgba(250,248,255,.86); --fl-dock-shadow: 0 -8px 24px rgba(28,20,46,.08);
  --fl-radio-ring: #C9BFE0; --fl-thumb-shadow: 0 1px 3px rgba(28,20,46,.14);
  --fl-r-sm: 10px; --fl-r-md: 14px; --fl-r-pill: 999px;
  --fl-fast: 150ms; --fl-reveal: 240ms; --fl-ease: cubic-bezier(.22,1,.36,1);
  --fl-gutter: 20px;
  background: var(--fl-bg); color: var(--fl-fg);
}
.flow[data-night], [data-theme="night"] .flow, .flow.is-night {
  --fl-bg: #0A0B12; --fl-surface: #12141C; --fl-surface-2: #171923; --fl-hair: #262833; --fl-hair-2: #3A3D4A;
  --fl-fg: #F1F5F9; --fl-fg-2: #94A3B8;
  --fl-accent: #8B5CF6; --fl-accent-soft: rgba(139,92,246,.16); --fl-ring: rgba(139,92,246,.4);
  --fl-success: #34D399; --fl-success-soft: rgba(52,211,153,.14); --fl-warning: #FBBF24; --fl-warning-soft: rgba(251,191,36,.14);
  --fl-danger: #F87171; --fl-danger-soft: rgba(248,113,113,.14); --fl-ring-danger: rgba(248,113,113,.25);
  --fl-material: rgba(10,11,18,.86); --fl-dock-shadow: 0 -8px 24px rgba(0,0,0,.45);
  --fl-radio-ring: #3A3D4A; --fl-thumb-shadow: 0 1px 3px rgba(0,0,0,.4);
}
html[data-theme="night"] body.flow { background: #0A0B12; color: #F1F5F9; }
/* The flow ground: flat token colour plus ONE static tint. No aurora, no grain on flow pages. */
.flow::before { content: ""; position: fixed; inset: 0 0 auto 0; height: 40vh; pointer-events: none; z-index: 0;
  background: radial-gradient(60% 40% at 50% -10%, var(--fl-accent-soft), transparent); opacity: .6; }
.flow > .fl-header, .flow > .fl-page, .flow > .fl-footer, .flow > main { position: relative; z-index: 1; }
/* Scope the stacking context to the page chrome only. The shared V3 drawer and
   backdrop are fixed in v3-base.css; flow.css loads later at equal specificity,
   so a universal child rule here would pull them into normal flow. */
.flow > .nav-drawer, .flow > .nav-backdrop { position: fixed; }
.flow .aurora-layer, .flow .grain { display: none !important; }

/* ── 2. Type roles ─────────────────────────────────────────── */
.flow { font-family: 'Peyda', 'Vazirmatn', system-ui, Tahoma, sans-serif; -webkit-font-smoothing: antialiased; }
.flow .fl-h1 { font-family: 'Damavand', 'Peyda', sans-serif; font-weight: 800; font-size: 28px; line-height: 1.3; letter-spacing: -.005em; color: var(--fl-fg); margin: 12px 0 0; }
.flow .fl-lead { margin: 8px 0 0; font-size: 15px; line-height: 1.6; color: var(--fl-fg-2); }
.flow .fl-title { margin: 20px 0 0; font-size: 20px; font-weight: 700; line-height: 1.35; color: var(--fl-fg); }
.flow .fl-caption { font-size: 13px; font-weight: 500; line-height: 1.5; color: var(--fl-fg-2); }
.flow .fl-label { display: block; font-size: 13px; font-weight: 600; line-height: 1.4; color: var(--fl-fg); }
.flow .fl-amount { font-size: 17px; font-weight: 700; font-variant-numeric: tabular-nums; color: var(--fl-fg); }
.flow .fl-ltr { direction: ltr; unicode-bidi: isolate; letter-spacing: .02em; }
.flow a { color: var(--fl-accent); text-decoration: none; }
.flow a:hover { text-decoration: underline; }
.flow *:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--fl-ring); border-radius: var(--fl-r-sm); }

/* ── 3. Page frame ─────────────────────────────────────────── */
.flow .fl-page { max-width: 640px; margin: 0 auto; padding: 0 var(--fl-gutter) 100px; }
.flow .fl-page--wide { max-width: 1120px; padding-left: 32px; padding-right: 32px; }
@media (max-width: 600px) { .flow .fl-page--wide { padding: 0 var(--fl-gutter) 100px; } }
.flow .fl-stack { display: flex; flex-direction: column; }

/* Header */
.flow .fl-header { position: sticky; top: 0; z-index: 100; background: var(--fl-material); backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px); border-bottom: 1px solid var(--fl-hair); }
.flow .fl-header__inner { display: flex; align-items: center; justify-content: space-between; height: 56px; padding: 0 var(--fl-gutter); max-width: 1120px; margin: 0 auto; }
.flow .fl-header__lead, .flow .fl-header__trail { min-width: 88px; height: 44px; display: flex; align-items: center; gap: 16px; }
.flow .fl-header__trail { justify-content: flex-end; }
.flow .fl-header__back { display: inline-flex; align-items: center; gap: 2px; height: 44px; font-size: 15px; font-weight: 600; color: var(--fl-accent); }
.flow .fl-header__back svg { width: 24px; height: 24px; margin-inline-start: -6px; }
.flow .fl-header__logo { height: 22px; width: auto; display: block; }
.flow .fl-header__menu { width: 44px; height: 44px; display: inline-flex; align-items: center; justify-content: flex-end; background: none; border: 0; color: var(--fl-fg); cursor: pointer; }

/* Progress */
.flow .fl-progress { margin-top: 16px; display: flex; flex-direction: column; gap: 8px; }
.flow .fl-progress__bar { display: flex; gap: 6px; }
.flow .fl-progress__seg { flex: 1 1 0; height: 4px; border-radius: var(--fl-r-pill); background: var(--fl-hair); }
.flow .fl-progress__seg--done { background: var(--fl-accent); }
.flow .fl-progress__seg--current { background: var(--fl-accent); opacity: .4; }
.flow .fl-progress__seg--danger { background: var(--fl-danger); }
.flow .fl-progress__caption { font-size: 13px; font-weight: 600; color: var(--fl-fg-2); line-height: 1.4; }

/* Segmented control (residence) */
.flow .fl-seg { margin-top: 16px; height: 36px; padding: 3px; border-radius: var(--fl-r-sm); background: var(--fl-surface-2); display: flex; gap: 2px; }
.flow .fl-seg__opt { flex: 1 1 0; display: flex; align-items: center; justify-content: center; border-radius: 8px; font-size: 14px; font-weight: 500; color: var(--fl-fg-2); text-decoration: none; }
.flow .fl-seg__opt.active { background: var(--fl-surface); border: 1px solid var(--fl-hair); font-weight: 600; color: var(--fl-fg); }
.flow .fl-seg__opt:hover { text-decoration: none; }

/* Choice rows (plans, payment methods) */
.flow .fl-choice-list { display: flex; flex-direction: column; gap: 8px; margin-top: 20px; }
.flow .fl-choice { display: flex; align-items: center; gap: 12px; min-width: 0; padding: 14px 16px; min-height: 72px; background: var(--fl-surface); border: 1px solid var(--fl-hair); border-radius: var(--fl-r-md); cursor: pointer; user-select: none; -webkit-tap-highlight-color: transparent; transition: border-color var(--fl-fast) var(--fl-ease), box-shadow var(--fl-fast) var(--fl-ease), background-color var(--fl-fast) var(--fl-ease); }
.flow .fl-choice--plan { min-height: 84px; }
.flow .fl-choice:active { background: var(--fl-surface-2); }
@media (hover: hover) and (pointer: fine) { .flow .fl-choice:not(.selected):hover { border-color: var(--fl-hair-2); } }
.flow .fl-choice.selected, .flow .fl-choice[aria-checked="true"] { border-color: var(--fl-accent); box-shadow: 0 0 0 1px var(--fl-accent); }
.flow .fl-choice:focus-visible { box-shadow: 0 0 0 3px var(--fl-ring); border-radius: var(--fl-r-md); }
.flow .fl-choice.selected:focus-visible { box-shadow: 0 0 0 1px var(--fl-accent), 0 0 0 4px var(--fl-ring); }
.flow .fl-radio { width: 22px; height: 22px; border-radius: 50%; flex-shrink: 0; border: 1.5px solid var(--fl-radio-ring); background: var(--fl-surface); display: flex; align-items: center; justify-content: center; transition: background-color var(--fl-fast) var(--fl-ease), border-color var(--fl-fast) var(--fl-ease); }
.flow .fl-radio svg { width: 12px; height: 12px; }
.flow .fl-radio path { stroke-dasharray: 1; stroke-dashoffset: 1; opacity: 0; }
.flow .selected .fl-radio, .flow [aria-checked="true"] .fl-radio, .flow input:checked + .fl-radio { background: var(--fl-accent); border-color: var(--fl-accent); }
.flow .selected .fl-radio path, .flow [aria-checked="true"] .fl-radio path, .flow input:checked + .fl-radio path { stroke-dashoffset: 0; opacity: 1; transition: stroke-dashoffset var(--fl-fast) var(--fl-ease) 40ms, opacity 0ms linear 40ms; }
.flow .fl-choice__text { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.flow .fl-choice__title-line { display: flex; align-items: center; gap: 8px; flex-wrap: nowrap; min-width: 0; }
.flow .fl-choice__title { font-size: 16px; font-weight: 600; line-height: 1.4; color: var(--fl-fg); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.flow .fl-tag { font-size: 12px; font-weight: 600; line-height: 18px; height: 22px; padding: 2px 8px; border-radius: var(--fl-r-pill); background: var(--fl-surface-2); color: var(--fl-fg-2); white-space: nowrap; flex-shrink: 0; }
.flow .fl-choice__sub { font-size: 13px; font-weight: 500; line-height: 1.5; color: var(--fl-fg-2); white-space: nowrap; font-variant-numeric: tabular-nums; }
.flow .fl-choice__fig { display: inline-block; min-width: var(--fl-permonth-col, 40px); text-align: start; }
.flow .fl-choice__save { font-weight: 600; }
.flow .fl-choice__save::before { content: '\00B7'; padding-inline: 3px; }
.flow .fl-choice__value { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; min-width: 84px; flex-shrink: 0; text-align: right; }
.flow .fl-choice__unit { font-size: 13px; font-weight: 500; line-height: 1.4; color: var(--fl-fg-2); }
.flow .fl-choice__icon { display: flex; flex-shrink: 0; color: var(--fl-fg-2); }
.flow .fl-choice__icon svg { width: 22px; height: 22px; }
.flow .fl-choice.is-disabled { opacity: .4; cursor: not-allowed; }
.flow .fl-choice input[type="radio"] { position: absolute; opacity: 0; width: 1px; height: 1px; }

/* Fields */
.flow .fl-field { margin-top: 12px; display: flex; flex-direction: column; }
.flow .fl-input { margin-top: 8px; height: 48px; padding: 0 14px; width: 100%; background: var(--fl-surface); border: 1px solid var(--fl-hair); border-radius: var(--fl-r-sm); font: 500 16px/1 'Peyda', system-ui, sans-serif; color: var(--fl-fg); caret-color: var(--fl-accent); direction: ltr; text-align: left; font-variant-numeric: tabular-nums; transition: border-color var(--fl-fast) var(--fl-ease), box-shadow var(--fl-fast) var(--fl-ease); }
.flow .fl-input::placeholder { color: var(--fl-fg-2); opacity: .8; font-weight: 400; letter-spacing: 0; }
@media (hover: hover) and (pointer: fine) { .flow .fl-input:hover { border-color: var(--fl-hair-2); } }
.flow .fl-input:focus, .flow .fl-input:focus-visible { border-color: var(--fl-accent); box-shadow: 0 0 0 3px var(--fl-ring); outline: none; }
.flow .fl-input.is-invalid, .flow .fl-input.input-error, .flow .fl-field.has-error .fl-input { border-color: var(--fl-danger); }
.flow .fl-input.is-invalid:focus, .flow .fl-field.has-error .fl-input:focus { box-shadow: 0 0 0 3px var(--fl-ring-danger); }
.flow .fl-input:-webkit-autofill { -webkit-box-shadow: 0 0 0 1000px var(--fl-surface) inset; -webkit-text-fill-color: var(--fl-fg); caret-color: var(--fl-accent); }
.flow .fl-msg-slot { display: grid; margin-top: 6px; min-height: 20px; }
.flow .fl-msg-slot > * { grid-area: 1 / 1; }
.flow .fl-helper { font-size: 13px; font-weight: 500; line-height: 1.5; color: var(--fl-fg-2); transition: opacity var(--fl-fast) var(--fl-ease); }
.flow .fl-field-error, .flow .email-check-msg.email-check-err, .flow .f-msg.err { display: flex; gap: 6px; align-items: flex-start; font-size: 13px; font-weight: 500; line-height: 1.5; color: var(--fl-danger); }
.flow .fl-field-error svg, .flow .f-msg.err svg { width: 16px; height: 16px; flex-shrink: 0; margin-top: 2px; }
.flow .f-msg.ok { display: none; }  /* valid is undecorated */
.flow .fl-field:has(.email-check-err) .fl-helper, .flow .fl-field:has(.f-msg.err) .fl-helper, .flow .fl-field:has([data-coupon-status="invalid"]) .fl-helper, .flow .fl-field:has([data-coupon-status="needs_email"]) .fl-helper { opacity: 0; visibility: hidden; }
.flow .fl-field:has([data-email-status="invalid"]) .fl-input { border-color: var(--fl-danger); }

/* Coupon */
.flow .fl-coupon-toggle { display: inline-flex; align-items: center; gap: 4px; height: 44px; margin: -2px 0 -12px; padding: 0; background: none; border: 0; font: 600 15px/1.4 'Peyda', system-ui, sans-serif; color: var(--fl-accent); cursor: pointer; }
.flow .fl-coupon-toggle svg { width: 16px; height: 16px; transition: transform var(--fl-fast) var(--fl-ease), opacity var(--fl-fast) var(--fl-ease); }
.flow .fl-coupon-toggle[aria-expanded="true"] { font-size: 13px; color: var(--fl-fg); cursor: default; }
.flow .fl-coupon-toggle[aria-expanded="true"] .q { display: none; }
.flow .fl-coupon-toggle .l { display: none; }
.flow .fl-coupon-toggle[aria-expanded="true"] .l { display: inline; }
.flow .fl-coupon-toggle[aria-expanded="true"] svg { transform: rotate(180deg); opacity: 0; }
.flow .fl-coupon-wrap { display: grid; grid-template-rows: 0fr; opacity: 0; visibility: hidden; transition: grid-template-rows var(--fl-reveal) var(--fl-ease), opacity var(--fl-reveal) var(--fl-ease), visibility 0s var(--fl-reveal); }
.flow .fl-coupon-wrap.is-open { grid-template-rows: 1fr; opacity: 1; visibility: visible; transition-delay: 0s; }
.flow .fl-coupon-wrap > div { overflow: hidden; min-height: 0; }
.flow .fl-coupon-row { display: flex; gap: 8px; margin-top: 8px; }
.flow .fl-coupon-row .fl-input { margin-top: 0; }
.flow .fl-coupon-apply { height: 48px; min-width: 88px; padding: 0 16px; border: 0; border-radius: var(--fl-r-sm); background: var(--fl-accent-soft); color: var(--fl-accent); font: 600 15px 'Peyda', system-ui, sans-serif; cursor: pointer; position: relative; transition: opacity var(--fl-fast) var(--fl-ease); }
.flow .fl-coupon-apply:disabled { opacity: .4; cursor: not-allowed; }
.flow .fl-coupon-apply.htmx-request .label { opacity: 0; }
.flow .fl-coupon-apply.htmx-request .fl-spin { opacity: 1; }

/* Notes */
.flow .fl-note { margin-top: 8px; display: flex; align-items: flex-start; gap: 12px; padding: 12px 14px; border-radius: var(--fl-r-md); background: var(--fl-accent-soft); }
.flow .fl-note svg { width: 18px; height: 18px; flex-shrink: 0; margin-top: 2px; color: var(--fl-accent); }
.flow .fl-note__text { font-size: 15px; line-height: 1.6; color: var(--fl-fg); }
.flow .fl-note__second { display: block; margin-top: 4px; font-size: 13px; font-weight: 500; line-height: 1.5; color: var(--fl-fg-2); }
.flow .fl-note--warn { background: var(--fl-warning-soft); } .flow .fl-note--warn svg { color: var(--fl-warning); }
.flow .fl-note--danger { background: var(--fl-danger-soft); } .flow .fl-note--danger svg { color: var(--fl-danger); }
.flow .fl-note--success { background: var(--fl-success-soft); } .flow .fl-note--success svg { color: var(--fl-success); }
.flow .fl-note.is-entering { animation: fl-fade var(--fl-reveal) var(--fl-ease); }

/* Assurance list */
.flow .fl-assurance { margin-top: 20px; display: flex; flex-direction: column; gap: 8px; }
.flow .fl-assurance__head { font-size: 13px; font-weight: 600; color: var(--fl-fg-2); line-height: 1.4; }
.flow .fl-assurance__row { display: flex; align-items: center; gap: 12px; height: 26px; font-size: 15px; color: var(--fl-fg); line-height: 1.4; }
.flow .fl-assurance__row svg { width: 18px; height: 18px; flex-shrink: 0; color: var(--fl-accent); }

/* Receipt list */
.flow .fl-receipt { margin-top: 24px; display: flex; flex-direction: column; }
.flow .fl-receipt__row { display: flex; align-items: center; justify-content: space-between; gap: 12px; min-height: 48px; padding: 8px 0; border-top: 1px solid var(--fl-hair); }
.flow .fl-receipt__row:first-child { border-top: 0; }
.flow .fl-receipt__row--stacked { flex-direction: column; align-items: stretch; gap: 6px; }
.flow .fl-receipt__label { font-size: 13px; font-weight: 500; color: var(--fl-fg-2); flex-shrink: 0; }
.flow .fl-receipt__value { display: flex; align-items: center; gap: 10px; min-width: 0; font-size: 15px; font-weight: 600; color: var(--fl-fg); line-height: 1.4; font-variant-numeric: tabular-nums; }
.flow .fl-receipt__value--hero { font-size: 28px; font-weight: 700; line-height: 1.2; }
.flow .fl-receipt__total { display: flex; align-items: center; justify-content: space-between; min-height: 52px; padding: 8px 0; border-top: 2px solid var(--fl-hair); }
.flow .fl-receipt__total-label { font-size: 15px; font-weight: 600; color: var(--fl-fg); }
.flow .fl-copy { display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; padding: 6px; margin: -6px 0; border-radius: var(--fl-r-sm); border: 1px solid var(--fl-hair); background: var(--fl-surface); color: var(--fl-fg-2); cursor: pointer; flex-shrink: 0; transition: border-color var(--fl-fast) var(--fl-ease); }
.flow .fl-copy svg { width: 16px; height: 16px; }
.flow .fl-copy.is-copied { color: var(--fl-success); }
.flow .fl-details { margin-top: 4px; align-self: flex-start; display: inline-flex; align-items: center; gap: 4px; height: 44px; background: none; border: 0; padding: 0; font: 600 15px 'Peyda', system-ui, sans-serif; color: var(--fl-accent); cursor: pointer; }
.flow .fl-details svg { width: 16px; height: 16px; transition: transform var(--fl-fast) var(--fl-ease); }
.flow .fl-details[aria-expanded="true"] svg { transform: rotate(180deg); }
.flow .fl-details-body { display: grid; grid-template-rows: 0fr; opacity: 0; transition: grid-template-rows var(--fl-reveal) var(--fl-ease), opacity var(--fl-reveal) var(--fl-ease); }
.flow .fl-details-body.is-open { grid-template-rows: 1fr; opacity: 1; }
.flow .fl-details-body > div { overflow: hidden; min-height: 0; }
/* A 0fr grid row still leaves its content in the a11y tree and tab order, so a
   collapsed panel's copy button was focusable and read out. visibility:hidden
   removes it; the 0s delay is deferred to the end of the reveal so the content
   stays painted while it animates open, and snaps back only after it closes. */
.flow .fl-details-body > div { visibility: hidden; transition: visibility 0s var(--fl-reveal); }
.flow .fl-details-body.is-open > div { visibility: visible; transition-delay: 0s; }

/* Buttons */
.flow .fl-btn { display: flex; align-items: center; justify-content: center; gap: 10px; height: 48px; width: 100%; padding: 0 24px; border: 0; border-radius: var(--fl-r-md); font: 600 16px 'Peyda', system-ui, sans-serif; cursor: pointer; text-decoration: none; transition: opacity var(--fl-fast) var(--fl-ease), transform var(--fl-fast) var(--fl-ease), background-color var(--fl-fast) var(--fl-ease); }
.flow .fl-btn--primary { background: var(--fl-accent); color: var(--fl-on-accent); }
.flow .fl-btn--secondary { background: var(--fl-accent-soft); color: var(--fl-accent); }
.flow .fl-btn:active { transform: scale(.98); }
.flow .fl-btn:disabled, .flow .fl-btn[aria-disabled="true"] { opacity: .4; cursor: not-allowed; transform: none; }
.flow .fl-btn:hover { text-decoration: none; }
@media (hover: hover) and (pointer: fine) { .flow .fl-btn--primary:hover { filter: brightness(.94); } .flow .fl-btn--secondary:hover { filter: brightness(.97); } }
.flow .fl-link { display: inline-flex; align-items: center; gap: 4px; min-height: 44px; font-size: 15px; font-weight: 600; color: var(--fl-accent); background: none; border: 0; padding: 0; cursor: pointer; }
.flow .fl-link svg { width: 16px; height: 16px; }
.flow .fl-spin { width: 20px; height: 20px; border: 2px solid rgba(255,255,255,.35); border-top-color: #FFFFFF; border-radius: 50%; animation: fl-rotate 1s linear infinite; display: inline-block; }
.flow .fl-spin--accent { border-color: var(--fl-hair); border-top-color: var(--fl-accent); }
.flow .fl-spin--field { width: 16px; height: 16px; border-width: 1.75px; position: absolute; right: 14px; top: 50%; translate: 0 -50%; opacity: 0; pointer-events: none; transition: opacity var(--fl-fast) var(--fl-ease); }
.flow .fl-input-wrap { position: relative; direction: ltr; }
.flow .fl-input-wrap:has(> .fl-input.htmx-request) .fl-spin--field { opacity: 1; }
.flow .fl-input.htmx-request { padding-inline-end: 40px; }

/* Dock */
.flow .fl-dock { position: fixed; right: 0; left: 0; bottom: 0; z-index: 80; display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 12px var(--fl-gutter) calc(16px + env(safe-area-inset-bottom)); background: var(--fl-material); backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px); border-top: 1px solid var(--fl-hair); box-shadow: var(--fl-dock-shadow); }
.flow .fl-dock__text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.flow .fl-dock__caption { font-size: 13px; font-weight: 500; color: var(--fl-fg-2); line-height: 1.4; }
.flow .fl-dock__value { font-size: 17px; font-weight: 700; color: var(--fl-fg); line-height: 1.3; font-variant-numeric: tabular-nums; }
.flow .fl-dock__value--muted { font-size: 15px; font-weight: 500; color: var(--fl-fg-2); }
.flow .fl-dock .fl-btn { width: auto; min-width: 128px; flex-shrink: 0; }
.flow .fl-dock-cta:has(> .fl-btn:disabled) { cursor: not-allowed; }

/* Support line, footer */
.flow .fl-support { margin-top: 16px; display: flex; align-items: center; justify-content: center; gap: 6px; min-height: 44px; flex-wrap: wrap; font-size: 13px; font-weight: 500; color: var(--fl-fg-2); }
.flow .fl-support a { font-weight: 600; }
.flow .fl-footer { margin-top: 24px; background: var(--fl-surface-2); border-top: 1px solid var(--fl-hair); padding: 32px var(--fl-gutter); display: flex; flex-direction: column; gap: 12px; }
.flow .fl-footer__brand { display: flex; align-items: center; gap: 10px; font-size: 13px; font-weight: 600; color: var(--fl-fg-2); }
.flow .fl-footer__brand img { height: 18px; width: auto; }
.flow .fl-footer__links { display: flex; flex-wrap: wrap; gap: 8px 18px; }
.flow .fl-footer__links a { font-size: 13px; color: var(--fl-fg-2); }
.flow .fl-footer__legal { font-size: 12px; color: var(--fl-fg-2); }

/* Status header, timeline, poll row */
.flow .fl-status { margin-top: 12px; display: flex; flex-direction: column; align-items: flex-start; }
.flow .fl-status__disc { position: relative; width: 64px; height: 64px; border-radius: 50%; display: flex; align-items: center; justify-content: center; background: var(--fl-surface-2); color: var(--fl-fg-2); }
.flow .fl-status__disc svg { width: 28px; height: 28px; }
.flow .fl-status--success .fl-status__disc { background: var(--fl-success-soft); color: var(--fl-success); }
.flow .fl-status--warn .fl-status__disc { background: var(--fl-warning-soft); color: var(--fl-warning); }
.flow .fl-status--danger .fl-status__disc { background: var(--fl-danger-soft); color: var(--fl-danger); }
.flow .fl-status--accent .fl-status__disc { background: var(--fl-accent-soft); color: var(--fl-accent); }
.flow .fl-status__ring { position: absolute; inset: -4px; border-radius: 50%; border: 2px solid currentColor; border-top-color: transparent; opacity: .55; animation: fl-rotate 1s linear infinite; }
.flow .fl-status__ring.is-paused { animation-play-state: paused; opacity: .35; }
.flow .fl-status .fl-h1 { margin-top: 12px; }
.flow .fl-status--fresh .fl-status__disc { animation: fl-disc 320ms var(--fl-ease) both; }
.flow .fl-status--fresh.fl-status--success .fl-status__disc path { stroke-dasharray: 1; animation: fl-draw 240ms var(--fl-ease) 80ms both; }
.flow .fl-timeline { margin-top: 20px; display: flex; flex-direction: column; gap: 12px; }
.flow .fl-timeline__row { position: relative; display: flex; align-items: flex-start; gap: 12px; min-height: 24px; }
.flow .fl-timeline__row:not(:last-child)::after { content: ""; position: absolute; right: 9.5px; top: 22px; bottom: -12px; width: 1px; background: var(--fl-hair); }
.flow .fl-timeline__dot { width: 20px; height: 20px; border-radius: 50%; flex-shrink: 0; border: 1.5px solid var(--fl-hair); background: var(--fl-surface); display: flex; align-items: center; justify-content: center; transition: background-color var(--fl-fast) var(--fl-ease), border-color var(--fl-fast) var(--fl-ease); }
.flow .fl-timeline__dot svg { width: 12px; height: 12px; color: #FFFFFF; opacity: 0; }
.flow .fl-timeline__row--done .fl-timeline__dot { background: var(--fl-success); border-color: var(--fl-success); }
.flow .fl-timeline__row--done .fl-timeline__dot svg { opacity: 1; }
.flow .fl-timeline__row--current .fl-timeline__dot { border: 2.5px solid var(--fl-accent); }
.flow .fl-timeline__title { font-size: 15px; font-weight: 600; color: var(--fl-fg); line-height: 1.35; padding-top: 1px; }
.flow .fl-timeline__row--todo .fl-timeline__title { font-weight: 500; color: var(--fl-fg-2); }
.flow .fl-timeline__sub { display: block; font-size: 13px; font-weight: 500; color: var(--fl-fg-2); line-height: 1.4; margin-top: 2px; }
.flow .fl-poll { margin-top: 8px; min-height: 32px; padding-inline-start: 32px; display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.flow .fl-poll__caption { font-size: 13px; font-weight: 500; color: var(--fl-fg-2); transition: opacity var(--fl-fast) var(--fl-ease); }
.flow .fl-poll__link { font-size: 13px; font-weight: 600; color: var(--fl-accent); padding: 6px 0; margin: -6px 0; background: none; border: 0; cursor: pointer; }
.flow .fl-poll__link[aria-disabled="true"] { opacity: .4; pointer-events: none; }

/* Upload */
.flow .fl-upload { margin-top: 16px; height: 48px; width: 100%; display: flex; align-items: center; justify-content: center; gap: 10px; border-radius: var(--fl-r-md); background: var(--fl-accent-soft); color: var(--fl-accent); font: 600 16px 'Peyda', system-ui, sans-serif; cursor: pointer; transition: box-shadow var(--fl-fast) var(--fl-ease), transform var(--fl-fast) var(--fl-ease); }
.flow .fl-upload svg { width: 20px; height: 20px; }
.flow .fl-upload:active { transform: scale(.98); }
.flow .fl-upload:focus-within, .flow .fl-upload.is-drag-over, .flow .fl-upload.is-hinted { box-shadow: 0 0 0 3px var(--fl-ring); }
.flow .fl-upload-slot { display: grid; margin-top: 16px; }
.flow .fl-upload-slot > * { grid-area: 1 / 1; transition: opacity var(--fl-reveal) var(--fl-ease); }
.flow .fl-upload-slot .fl-upload { margin-top: 0; }
.flow .fl-upload-slot.is-filled .fl-upload { opacity: 0; pointer-events: none; }
.flow .fl-file { opacity: 0; visibility: hidden; min-height: 64px; padding: 8px 12px; gap: 12px; display: flex; align-items: center; background: var(--fl-surface); border: 1px solid var(--fl-hair); border-radius: var(--fl-r-md); }
.flow .fl-upload-slot.is-filled .fl-file { opacity: 1; visibility: visible; }
.flow .fl-file__thumb { width: 48px; height: 48px; object-fit: cover; border-radius: 6px; border: 1px solid var(--fl-hair); background: var(--fl-surface-2); flex-shrink: 0; }
.flow .fl-file__meta { min-width: 0; display: flex; flex-direction: column; gap: 2px; flex: 1 1 auto; }
.flow .fl-file__name { font-size: 15px; font-weight: 500; color: var(--fl-fg); direction: ltr; text-align: left; unicode-bidi: isolate; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.flow .fl-file__size { font-size: 13px; font-weight: 500; color: var(--fl-fg-2); }

/* Toast */
.flow .fl-toast { position: fixed; left: 50%; bottom: calc(96px + env(safe-area-inset-bottom)); transform: translate(-50%, 8px); z-index: 200; padding: 10px 16px; border-radius: var(--fl-r-md); background: var(--fl-material); backdrop-filter: blur(20px); border: 1px solid var(--fl-hair); box-shadow: var(--fl-dock-shadow); font-size: 14px; font-weight: 600; color: var(--fl-fg); opacity: 0; pointer-events: none; transition: opacity var(--fl-reveal) var(--fl-ease), transform var(--fl-reveal) var(--fl-ease); }
.flow .fl-toast.is-visible { opacity: 1; transform: translate(-50%, 0); }

/* Screen-reader status mirror */
.flow .fl-visually-hidden, .flow .fl-sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }

/* ── 4. Desktop ────────────────────────────────────────────── */
@media (min-width: 901px) {
  .flow .fl-h1 { font-size: 34px; }
  .flow .fl-input, .flow .fl-coupon-apply, .flow .fl-upload, .flow .fl-btn { height: 44px; }
  .flow .fl-choice-list--plans { display: grid; grid-template-columns: minmax(0,1fr) minmax(0,1fr); gap: 12px; }
  .flow.page-buy .fl-page { max-width: 800px; } /* two 7-digit plan cards need ~370px each */
  .flow .fl-checkout { display: flex; align-items: flex-start; gap: 32px; margin-top: 24px; }
  .flow .fl-checkout__main { flex: 1 1 auto; min-width: 0; }
  .flow .fl-checkout__side { width: 372px; flex-shrink: 0; position: sticky; top: 80px; padding: 20px; background: var(--fl-surface); border: 1px solid var(--fl-hair); border-radius: var(--fl-r-md); display: flex; flex-direction: column; }
  .flow .fl-checkout__side .fl-receipt { margin-top: 4px; }
  .flow .fl-dock { position: static; padding: 0; margin-top: 16px; background: none; border: 0; box-shadow: none; backdrop-filter: none; }
  .flow .fl-dock__text { display: none; }
  .flow .fl-dock .fl-btn { width: 100%; }
  /* Buy keeps its amount beside the CTA on desktop — the plan grid is the
     only content above it, so a bare button would read as an orphan. */
  .flow.page-buy .fl-dock { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 12px 0 0; }
  .flow.page-buy .fl-dock__text { display: flex; }
  .flow.page-buy .fl-dock .fl-btn { width: auto; min-width: 200px; }
  /* 2-up plan cards are ~294px: the nowrap «ماهانه N · M٪ صرفه‌جویی» line
     overflowed its box and painted over the amount column. Let it wrap —
     the grid stretches both cards in a row to the taller height. */
  .flow.page-buy .fl-choice-list--plans .fl-choice__sub { white-space: normal; }
  .flow .fl-page { padding-bottom: 64px; }
  .flow .fl-details-body { grid-template-rows: 1fr; opacity: 1; }
  .flow .fl-details-body > div { visibility: visible; }
  .flow .fl-details { display: none; }
}
@media (max-width: 900px) {
  .flow .fl-checkout__side { display: contents; }
  .flow .fl-checkout__side > .fl-receipt, .flow .fl-checkout__side > .fl-side-title { display: none; }
  /* The dock is fixed on phones — the footer must clear it or its last row sits under it. */
  .flow .fl-footer { padding-bottom: calc(96px + env(safe-area-inset-bottom)); }
}

/* ── 5. Motion ─────────────────────────────────────────────── */
@keyframes fl-rotate { to { transform: rotate(360deg); } }
@keyframes fl-fade { from { opacity: 0; } }
@keyframes fl-disc { from { transform: scale(.92); opacity: 0; } }
@keyframes fl-draw { from { stroke-dashoffset: 1; } to { stroke-dashoffset: 0; } }
@media (prefers-reduced-motion: reduce) {
  .flow *, .flow *::before, .flow *::after { transition-duration: 0ms !important; animation-duration: 0ms !important; animation-iteration-count: 1 !important; }
  .flow .fl-status__ring, .flow .fl-spin { animation: none !important; }
  .flow .fl-status__ring { opacity: .35; }
}

/* ── 6. Back link without the component class ──────────────────
   The Iranian checkout back link must render exactly
   class="nav-plans" (a pinned test asserts that literal), so the
   header's leading anchor is styled positionally as well. */
.flow .fl-header__lead > a { display: inline-flex; align-items: center; gap: 2px; height: 44px; font-size: 15px; font-weight: 600; color: var(--fl-accent); padding: 0; border: 0; background: none; box-shadow: none; border-radius: 0; }
.flow .fl-header__lead > a svg { width: 24px; height: 24px; margin-inline-start: -6px; }

/* ── 7. Buy page (plan picker) ─────────────────────────────────
   Residence switch, how-it-works steps, guarantee row. The switch
   is navigation, so its options are anchors/spans classed .seg
   (a pinned test asserts href="…" class="seg" verbatim) rather
   than the generic .fl-seg__opt. */
.flow .market-seg > .seg { flex: 1 1 0; display: flex; align-items: center; justify-content: center; border-radius: 8px; font-size: 14px; font-weight: 500; color: var(--fl-fg-2); text-decoration: none; }
.flow .market-seg > .seg.active { background: var(--fl-surface); border: 1px solid var(--fl-hair); font-weight: 600; color: var(--fl-fg); }
.flow .market-seg > a.seg:hover { text-decoration: none; }
.flow .market-caption { display: block; margin-top: 8px; }
.flow .fl-title--section { margin-top: 32px; }
.flow .fl-steps { margin-top: 16px; display: flex; flex-direction: column; gap: 16px; }
.flow .fl-step { display: flex; align-items: flex-start; gap: 14px; }
.flow .fl-step__num { width: 32px; height: 32px; border-radius: 50%; flex-shrink: 0; display: flex; align-items: center; justify-content: center; background: var(--fl-accent-soft); color: var(--fl-accent); font-size: 14px; font-weight: 700; line-height: 1; }
.flow .fl-step__text { display: flex; flex-direction: column; gap: 3px; padding-top: 6px; min-width: 0; }
.flow .fl-step__title { font-size: 15px; font-weight: 600; color: var(--fl-fg); line-height: 1.4; }
.flow .fl-step__sub { font-size: 13px; color: var(--fl-fg-2); line-height: 1.55; }
.flow .fl-guarantee { margin-top: 24px; min-height: 52px; display: flex; align-items: center; justify-content: space-between; gap: 12px; border-top: 1px solid var(--fl-hair); border-bottom: 1px solid var(--fl-hair); }
.flow .fl-guarantee__lead { display: flex; align-items: center; gap: 10px; min-width: 0; font-size: 15px; font-weight: 600; color: var(--fl-fg); }
.flow .fl-guarantee__lead svg { width: 20px; height: 20px; flex-shrink: 0; color: var(--fl-accent); }
.flow .fl-guarantee a { font-size: 14px; font-weight: 600; flex-shrink: 0; }
/* Narrow phones (≤380px) with 7-digit foreign amounts: shrink the secondary
   line and widen the amount column instead of clipping. Never ellipsize a
   price — a truncated number is worse than a tight one. */
@media (max-width: 380px) { .flow.page-buy .fl-choice__sub { font-size: 12px; } .flow.page-buy .fl-choice__value { min-width: 76px; } }
/* At 320–340px even 12px cannot hold «ماهانه N · M٪ صرفه‌جویی» beside a 7-digit
   amount; drop the savings clause rather than truncate a number. */
@media (max-width: 365px) { .flow.page-buy .fl-choice__save { display: none; } }
/* 320px: the bank card number and the hero amount are the two strings that
   still overflow a folded phone; shrink them rather than wrap a number. */
@media (max-width: 360px) { .flow .fl-account__card { font-size: 15px; } .flow .fl-receipt__value--hero { font-size: 24px; } }

/* ── 8. Checkout page ──────────────────────────────────────────
   Order line, payment rows, the desktop side panel's own CTA, and
   the two carry-overs from the old checkout that its scripts still
   write into (.btn-spin from the pay-button morph, .f-msg.ok from
   the phone/email tick). */
.flow .fl-orderline { margin-top: 16px; display: flex; flex-direction: column; gap: 6px; padding: 12px 0; border-top: 1px solid var(--fl-hair); border-bottom: 1px solid var(--fl-hair); }
.flow .fl-orderline__row { display: flex; align-items: center; justify-content: space-between; gap: 12px; min-height: 26px; }
.flow .fl-orderline__plan { font-size: 15px; font-weight: 600; color: var(--fl-fg); line-height: 1.4; min-width: 0; }
.flow .fl-orderline__price { font-size: 13px; font-weight: 500; color: var(--fl-fg-2); line-height: 1.4; white-space: nowrap; flex-shrink: 0; }
.flow .fl-orderline__price .fl-amount { margin-inline-end: 2px; }
.flow .fl-orderline__actions { display: flex; align-items: center; gap: 16px; min-height: 24px; flex-wrap: wrap; }
.flow .fl-orderline__actions a { display: inline-flex; align-items: center; min-height: 44px; }
.flow .fl-orderline__actions .sum-edit { font-size: 15px; font-weight: 600; color: var(--fl-accent); }
.flow .fl-orderline__note { margin-top: 2px; }
@media (max-width: 380px) { .flow .fl-orderline__row { flex-direction: column; align-items: flex-start; gap: 2px; } }

/* Payment rows: the switcher script toggles .active, so mirror the
   .selected treatment onto it (the checked radio does the rest). */
.flow .pay-opt.active { border-color: var(--fl-accent); box-shadow: 0 0 0 1px var(--fl-accent); }
.flow .pay-opt.active .fl-radio { background: var(--fl-accent); border-color: var(--fl-accent); }
.flow .pay-opt.active .fl-radio path { stroke-dashoffset: 0; opacity: 1; }
.flow.page-checkout .fl-choice__sub { white-space: normal; }
.flow .pay-opt .ip-note { color: var(--fl-warning); font-weight: 600; }
.flow #zp-notice { margin-top: 8px; }
.flow .crypto-assets { display: flex; flex-direction: column; gap: 8px; margin-top: 12px; padding-inline-start: 12px; border-inline-start: 2px solid var(--fl-hair); }
.flow .crypto-assets .fl-choice { margin: 0; }
.flow .crypto-assets .fl-choice__value { align-items: flex-start; min-width: 0; }

/* Desktop side panel CTA + its caption; both are dock duplicates on phones. */
.flow .fl-checkout__side > #checkout-submit-desktop { margin-top: 16px; }
.flow .fl-side-caption { margin-top: 10px; text-align: center; }
.flow .fl-side-title { display: block; }
@media (max-width: 900px) {
  .flow .fl-checkout__side > #checkout-submit-desktop { display: none; }
  /* The caption carries an inline display: (the switcher toggles it with the
     zarinpal note), which would otherwise outrank this hide on phones. */
  .flow .fl-checkout__side > .fl-side-caption { display: none !important; }
}
/* On desktop the side panel owns the CTA; the dock would become a third
   column of the checkout row. The real submit button lives inside it and
   stays submittable while hidden (the desktop button proxies to it). */
@media (min-width: 901px) {
  .flow.page-checkout .fl-dock { display: none; }
}
/* A class rule with display: outranks the UA's [hidden] {display:none}, so any
   flow row that ships hidden has to say so itself. flow.js writes the discount
   text but cannot unhide its row — reveal it the moment it has content. */
.flow .fl-receipt__row[hidden], .flow .crypto-assets[hidden] { display: none; }
.flow .fl-receipt__row[hidden]:has(#fl-receipt-discount:not(:empty)) { display: flex; }

/* The pay-button morph script writes this spinner into the dock button's label.
   (.f-msg is already styled in section 3: .err shows, .ok stays undecorated —
   the phone validator's green tick is deliberately not painted.) */
.flow .btn-spin { width: 16px; height: 16px; flex-shrink: 0; display: inline-block; border: 2px solid rgba(255,255,255,.35); border-top-color: #FFFFFF; border-radius: 50%; animation: fl-rotate .8s linear infinite; vertical-align: -3px; margin-inline-end: 6px; }
/* First-fold budget on 390px: the checkout must show both fields AND the
   payment rows above the dock, so its rows and section titles run tighter
   than the plan picker's (which has nothing else competing for the fold). */
.flow.page-checkout .fl-title { margin-top: 16px; }
.flow.page-checkout .fl-choice-list { margin-top: 12px; }
.flow.page-checkout .pay-opt { min-height: 64px; }
.flow.page-checkout .fl-field { margin-top: 10px; }

/* The dock is fixed with z-index 80, but it lives inside <main>, which
   section 1 gives `position:relative; z-index:1` — that traps it in main's
   stacking context. The footer is a later sibling at the same z-index, so
   once the page is scrolled to the bottom the footer painted OVER the dock
   and swallowed taps on the pay button (measured: elementFromPoint at the
   button's centre returned .fl-footer). The footer never needs to be above
   page content, so drop it below. Repairs the plan picker's dock too. */
.flow > .fl-footer { z-index: 0; }

/* ── 9. Bank transfer page ─────────────────────────────────────
   The account block is a framed card wrapping a second receipt list, so
   the bank's identity reads as one object separate from the amount rows
   above it. The nested list drops its own top margin (--flush) because
   the frame already provides the gap. */
.flow .fl-account { margin-top: 16px; padding: 8px 16px; background: var(--fl-surface); border: 1px solid var(--fl-hair); border-radius: var(--fl-r-md); }
.flow .fl-account__head { display: flex; align-items: center; gap: 12px; height: 48px; font-size: 15px; font-weight: 600; }
.flow .fl-account__head svg { width: 22px; height: 22px; color: var(--fl-fg-2); }
.flow .fl-receipt--flush { margin-top: 0; }
.flow .fl-account__card { font-size: 17px; font-weight: 700; }
/* The stacked IBAN row gives its value the full width, so the copy button
   sits at the far edge instead of hugging a long identifier. */
.flow .fl-receipt__value--between { justify-content: space-between; width: 100%; }
/* The dock's guide tap (flow.js: a disabled primary scrolls to the missing
   upload control) never fired: .fl-dock-cta is exactly the button's box, and a
   disabled <button> swallows the pointer event without bubbling, so the wrap's
   listener was unreachable. Taking the disabled button out of hit-testing hands
   the tap to the wrap; the rule stops applying the moment a file is chosen and
   flow.js re-enables the button. */
.flow .fl-dock-cta > .fl-btn:disabled { pointer-events: none; } /* let the wrapper receive the guide tap */

/* ── 10. Result and status pages ───────────────────────────────
   Both pages are built from section-3 components (status, timeline, poll,
   receipt, details, note, support). Only the deltas live here. */

/* A cancelled payment is an action the customer stopped, not a verdict: the
   neutral disc fades in without the 320 ms scale the success/danger discs get,
   so the cancelled screen is visibly quieter than the declined one
   (interaction spec, "Failed arrival, cancelled kind"). */
.flow .fl-status--fresh.fl-status--neutral .fl-status__disc { animation: fl-fade 240ms var(--fl-ease) both; }

/* The status pages stack a status block, a timeline and an action column with
   no card between them; the h1 must not sit on top of the progress caption. */
.flow.page-result .fl-status, .flow.page-status .fl-status { margin-top: 20px; }

/* Support line and the Bale/Telegram caption read as one block. */
.flow.page-status .fl-support + .fl-caption { text-align: center; }

/* The details control is a receipt affordance: pull it against the total row
   instead of the 24 px the flex gap would otherwise leave. */
.flow.page-result .fl-details, .flow.page-status .fl-details { margin-top: 0; }
