/* =============================================================================
 * Cash For PC — /offer, the browser-driven offer flow.
 *
 * Everything is scoped under .cfpOf so nothing here can reach the shared .cfp
 * header/footer rendered by cfp_topbar()/cfp_footer(). CashForPC public pages
 * are standalone — they link /css/public-cashforpc.css directly and never load
 * public.bundle.css — so web/css/shared/{buttons,modals}.css are NOT available
 * and none of their classes may be used.
 *
 * Loaded with a plain <link>, so a CSS change here needs no rebuild.
 * ========================================================================== */

.cfpOf {
  --navy: #06111f;
  --navy2: #0b1a2b;
  --panel: #102238;
  --lime: #b8f34a;
  --lime2: #ddffa6;
  /* Mirrors public-cashforpc.css's .cfp token of the same name — the lighter
     navy-blue spotlight. Re-declared because this page's scope is .cfpOf, which
     is not inside .cfp, so the original never reaches here. Keep the two in
     step: they light the same accent on the same site. */
  --cfp-spot-rgb: 74, 124, 192;
  --ink: #111b26;
  --cream: #f4f6f0;
  --muted: #657480;
  /* The fill for every form field. Lime, but a long way down from --lime:
     these sit on a white card and the seller has to read what they typed on
     top of it. Deliberately LIGHTER than the #f4fae9 that marks a chosen
     option (0.951 vs 0.935 luminance) -- that tint has to keep meaning
     "selected", and a field wearing the same one would flatten the two. */
  --field-bg: #f7fce6;
  --line: #dce3da;
  --white: #fff;
  font-family: 'DM Sans', sans-serif;
  color: var(--ink);
}
.cfpOf * { box-sizing: border-box; }
.cfpOf a { color: inherit; text-decoration: none; }
.cfpOf h1, .cfpOf h2, .cfpOf h3 { font-family: 'Space Grotesk', sans-serif; margin-top: 0; }
.cfpOf p { margin-top: 0; }
.cfpOf .wrap { width: min(1120px, calc(100% - 40px)); margin: auto; }
.cfpOf .narrow { width: min(680px, calc(100% - 40px)); margin: auto; }

/* ---- Wizard panes --------------------------------------------------------
 * One <section data-screen> visible at a time, inside the modal. Hidden with
 * [hidden] rather than a class so the markup stays meaningful without CSS.
 * -------------------------------------------------------------------- */
.cfpOf [data-screen][hidden] { display: none; }
.cfpOf [data-screen] > h2 { font-size: clamp(22px, 3vw, 28px); margin: 0 0 8px; }
.cfpOf .wizLede { color: var(--muted); font-size: 15px; line-height: 1.6; margin: 0 0 22px; }

.cfpOf .landing { padding: 64px 0 90px; }

/* ---- The wizard modal ---------------------------------------------------- */
.cfpOf .wizModal { align-items: start; }
/* NB: the padding here does NOT win — see .cfpOf .cfpModalCard.wizCard further
   down, which is where the wizard card's padding is actually set. */
.cfpOf .wizCard {
  max-width: 620px; padding: 0; overflow: hidden;
  display: flex; flex-direction: column; max-height: calc(100vh - 40px);
}
/* The card takes focus itself when the wizard opens on a touch device (see
   openWizard) so the dialog is announced without a text field summoning the
   on-screen keyboard. It is a container, not a control, so it must not paint a
   focus ring -- every control inside it still gets its own. */
.cfpOf .wizCard[tabindex]:focus { outline: none; }
/* The body is a FIXED height, and every pane is sized to FIT it — nothing is
   meant to scroll. Letting the card resize between steps made the modal jump
   under the pointer (the Continue button moving between clicks is the specific
   thing to avoid), and an inner scrollbar is only marginally better: it hides
   the primary action below a fold on the one screen where it matters.
   The two panes that could not fit — the four condition questions and the manual
   spec form — were SPLIT into two panes each rather than shrunk to illegibility.
   overflow stays `auto` purely as a guard for very short viewports, where
   clipping content would be worse than a scrollbar. */
/* 540px where there is room, shrinking on short viewports and never below 300.
   min() replaces what used to be a flat 445px plus a max-height media query:
   one declaration, and the step it takes at the breakpoint is gone. The 290px
   subtracted is everything around this box — the modal's own 40px of padding,
   the card's 54px top, the step rail and the footer. */
.cfpOf .wizBody {
  padding: 22px 30px 24px; overflow-y: auto;
  height: min(540px, calc(100vh - 290px)); min-height: 300px; flex: 1 1 auto;
}

/* Compact vertical rhythm INSIDE the wizard only — the landing page keeps the
   roomier scale. This is what buys the fit. */
.cfpOf .wizBody h2 { font-size: clamp(20px, 2.6vw, 25px); line-height: 1.15; margin: 0 0 6px; }
.cfpOf .wizBody .wizLede { font-size: 14.5px; line-height: 1.5; margin: 0 0 16px; }
.cfpOf .wizBody .field { margin-bottom: 13px; }
.cfpOf .wizBody .field label { font-size: 12px; margin-bottom: 4px; }
.cfpOf .wizBody .field input,
.cfpOf .wizBody .field select { padding: 11px 13px; font-size: 15px; }
.cfpOf .wizBody .field textarea { min-height: 58px; padding: 10px 13px; font-size: 14.5px; }
.cfpOf .wizBody .row2, .cfpOf .wizBody .row3 { gap: 13px; }
.cfpOf .wizBody .q { padding: 12px 0; }
.cfpOf .wizBody .q > legend { font-size: 15.5px; margin: 0 0 10px; }
.cfpOf .wizBody .opt { padding: 9px 14px; font-size: 14px; }
.cfpOf .wizBody .opts { gap: 8px; }
.cfpOf .wizBody .note { font-size: 12.5px; margin: 10px 0 0; }
.cfpOf .wizBody .readsGrid { gap: 16px; margin: 0 0 14px; }
.cfpOf .wizBody .readsGrid ul { font-size: 13px; line-height: 1.75; }
.cfpOf .wizBody .promise { padding: 11px 14px; margin: 0 0 14px; font-size: 13.5px; line-height: 1.5; }
.cfpOf .wizBody .modalMeta { font-size: 11.5px; line-height: 1.6; }
.cfpOf .wizBody .steps { margin: 0 0 14px; }
.cfpOf .wizBody .steps li { padding: 0 0 14px 46px; }
.cfpOf .wizBody .steps li:before { width: 32px; height: 32px; font-size: 14px; }
.cfpOf .wizBody .steps li h3 { font-size: 16px; margin: 0 0 3px; }
.cfpOf .wizBody .steps li p { font-size: 13.5px; line-height: 1.45; }
.cfpOf .wizBody .publisherRow { margin-top: 6px; padding: 7px 11px; font-size: 13px; }
.cfpOf .wizBody .specList li { padding: 10px 0; grid-template-columns: 118px 1fr; }
.cfpOf .wizBody .specList .v { font-size: 14.5px; }
.cfpOf .wizBody .nextSteps { margin: 14px 0 0; }
.cfpOf .wizBody .nextSteps li { padding: 9px 0 9px 39px; font-size: 13.5px; line-height: 1.45; }
.cfpOf .wizBody .nextSteps li:before { top: 10px; width: 26px; height: 26px; font-size: 15px; }
.cfpOf .wizBody .doneLink { margin-top: 20px; font-size: 13.5px; }
.cfpOf .wizBody .bigIcon { width: 58px; height: 58px; margin-bottom: 14px; font-size: 26px; }
.cfpOf .wizBody .warnBox { margin-top: 4px; }
.cfpOf .wizBody .warnBox > button { padding: 11px 15px; font-size: 13.5px; }
.cfpOf .wizBody .waitStrip { margin-top: 12px; padding: 12px 15px; }
.cfpOf .wizBody .offerCard { padding: 20px 22px; }
.cfpOf .wizBody .offerAmount { font-size: clamp(40px, 6.5vw, 54px); }
.cfpOf .wizBody .offerKicker { margin-bottom: 6px; }
.cfpOf .wizBody .offerBasis { margin-top: 14px; padding-top: 12px; }
.cfpOf .wizBody .offerSpecs li { padding: 3px 0; font-size: 12.5px; }
.cfpOf .wizBody .offerAnswers { margin-top: 8px; padding-top: 8px; }
.cfpOf .wizBody .offerAnswers li { padding: 3px 0; font-size: 12px; }
.cfpOf .wizBody .reviewNote { margin-top: 12px; padding: 10px 12px; font-size: 12.5px; }
.cfpOf .wizBody .breakdown { margin-top: 16px; }
.cfpOf .wizBody .breakdown th, .cfpOf .wizBody .breakdown td { padding: 8px 6px; font-size: 14px; }

/* The waiting pane's steps are one line each — a seller here is watching for the
   app to do something, not reading a manual. */
.cfpOf .wizBody .steps.tight li {
  padding: 0 0 8px 34px; font-size: 13.5px; line-height: 1.45; color: var(--muted);
}
.cfpOf .wizBody .steps.tight li b { color: var(--ink); }
.cfpOf .wizBody .steps.tight li:before {
  width: 22px; height: 22px; font-size: 11px; top: 0;
}
.cfpOf .wizBody .warnBox.tight > button { padding: 9px 14px; font-size: 13px; }
.cfpOf .wizBody .warnBox.tight .warnBody { padding: 0 14px 12px; font-size: 13px; line-height: 1.55; }
/* The four condition questions are the tightest fit in the wizard. */
.cfpOf .wizBody .q { padding: 10px 0; }
.cfpOf .wizBody .q > legend { margin-bottom: 8px; }
.cfpOf .wizBody .detail { margin-top: 10px; }
.cfpOf .wizBody .field textarea { min-height: 48px; }

.cfpOf .wizFoot {
  padding: 14px 30px 16px; border-top: 1px solid var(--line); background: var(--cream);
  text-align: center; flex: 0 0 auto;
}
.cfpOf .wizFoot[hidden] { display: none; }
.cfpOf .wizActions { display: flex; gap: 12px; align-items: center; }
/* Back is optional and Continue must not shuffle sideways when it appears, so
   Continue takes the remaining width and stays anchored right. */
.cfpOf .wizActions #wizBack { flex: 0 0 auto; min-width: 96px; }
.cfpOf .wizActions #wizNext { flex: 1 1 auto; }
.cfpOf .wizActions #wizBack[hidden], .cfpOf .wizActions #wizNext[hidden] { display: none; }

.cfpOf .wizFoot .textLink {
  border: 0; background: none; padding: 0; margin-top: 12px;
  font: 600 13px 'DM Sans', sans-serif; color: var(--muted);
  text-decoration: underline; cursor: pointer;
}
.cfpOf .wizFoot .textLink[hidden] { display: none; }
.cfpOf .wizFoot .textLink:hover { color: var(--ink); }
/* Armed = the confirming second tap. Warm rather than alarming: this discards a
   scan, it doesn't delete an account. */
.cfpOf .wizFoot .textLink.armed { color: #a2553f; font-weight: 700; }

/* ---- Condition accordion -------------------------------------------------
   Four questions, one open at a time. Collapsed rows keep the answer visible so
   the seller can read back what they said without reopening anything. */
.cfpOf .acc { border: 1px solid var(--line); border-radius: 11px; background: #fff; margin-bottom: 6px; }
.cfpOf .acc.open { border-color: #b6c4a8; }
.cfpOf .accHead {
  width: 100%; display: flex; align-items: center; gap: 12px; padding: 9px 14px;
  border: 0; background: none; cursor: pointer; text-align: left;
  font: 600 14.5px 'DM Sans', sans-serif; color: var(--ink);
}
.cfpOf .accQ { flex: 1 1 auto; min-width: 0; }
.cfpOf .accA {
  flex: 0 0 auto; font-size: 13px; font-weight: 700; color: var(--muted);
  max-width: 45%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cfpOf .acc.answered .accA { color: #4d8b19; }
.cfpOf .acc.answered .accA:before { content: "✓ "; }
.cfpOf .acc.open .accA { display: none; }
.cfpOf .accBody { display: grid; grid-template-rows: 0fr; transition: grid-template-rows .22s ease; }
.cfpOf .accBody > div { overflow: hidden; }
.cfpOf .acc.open .accBody { grid-template-rows: 1fr; }
.cfpOf .accInner { padding: 0 14px 9px; }
.cfpOf .accInner .detail { margin-top: 8px; }
.cfpOf .accInner textarea { min-height: 34px; }
.cfpOf .accInner .field { margin-bottom: 0; }
@media (prefers-reduced-motion: reduce) { .cfpOf .accBody { transition: none; } }

/* Inline correction panel on the verification steps. Sits between the "we sent
   it to X" line and the code box, so fixing a typo never means restarting. */
.cfpOf .fixBox {
  margin: 0 0 10px; padding: 10px 13px; border-radius: 12px;
  background: var(--cream); border: 1px solid var(--line);
}
.cfpOf .fixBox[hidden] { display: none; }
.cfpOf .fixBox .field { margin-bottom: 8px; }
.cfpOf .fixBox .btn { min-height: 38px; font-size: 14px; }

/* A primary button in a waiting state: present, obviously not clickable, and
   carrying the same spinner as the strip below it. Leaving the slot empty made
   the footer look broken on the one step where nothing is expected of you. */
.cfpOf .btn.isWaiting { opacity: 1; background: #e6ece0; color: var(--muted); cursor: default; }
.cfpOf .btn.isWaiting:hover { background: #e6ece0; transform: none; }
.cfpOf .btn.isWaiting:before {
  content: ""; width: 16px; height: 16px; border-radius: 50%;
  border: 2px solid #c3cfba; border-top-color: var(--muted);
  animation: cfpOfSpin 1s linear infinite;
}
@media (prefers-reduced-motion: reduce) { .cfpOf .btn.isWaiting:before { animation-duration: 3s; } }

/* ---- Pairing code ------------------------------------------------------- */
.cfpOf .codeBox {
  display: flex; align-items: center; gap: 14px; margin: 14px 0 6px;
  padding: 14px 16px; border-radius: 13px;
  background: var(--navy); border: 1px solid #1b3049;
}
.cfpOf .codeMeta { flex: 1 1 auto; min-width: 0; }
.cfpOf .codeMeta span {
  display: block; color: #8fa2b1; font-size: 10px; font-weight: 800; letter-spacing: .15em;
}
.cfpOf .codeValue {
  font-family: 'Space Grotesk', sans-serif; font-size: 30px; font-weight: 700;
  color: var(--lime); letter-spacing: .22em; line-height: 1.15; margin-top: 3px;
}
.cfpOf .copyBtn {
  flex: 0 0 auto; width: 42px; height: 42px; display: inline-flex;
  align-items: center; justify-content: center; border: 1px solid #304964;
  border-radius: 10px; background: transparent; color: #d8e1e8; cursor: pointer;
  transition: .15s;
}
.cfpOf .copyBtn:hover { background: #152a41; color: #fff; }
.cfpOf .copyBtn.copied { background: var(--lime); border-color: var(--lime); color: var(--navy); }
.cfpOf .copyBtn.copied svg { display: none; }
.cfpOf .copyBtn.copied:after { content: "Copied"; font: 700 11px 'DM Sans', sans-serif; }

/* Step rail. The wizard is closable and resumable, so this is a map of where
   you are, not a countdown pressuring you along. */
.cfpOf .wizRail {
  display: flex; list-style: none; margin: 0; padding: 18px 30px 16px;
  gap: 4px; border-bottom: 1px solid var(--line); background: var(--cream);
}
.cfpOf .wizRail[hidden] { display: none; }
.cfpOf .wizRail li {
  flex: 1; display: flex; flex-direction: column; align-items: center; gap: 6px;
  position: relative; min-width: 0;
}
/* The connecting line sits behind the dots and stops at the last item. */
.cfpOf .wizRail li:not(:last-child):after {
  content: ""; position: absolute; top: 13px; left: 50%; width: 100%; height: 2px;
  background: var(--line); z-index: 0;
}
.cfpOf .wizRail .dot {
  position: relative; z-index: 1; width: 26px; height: 26px; border-radius: 50%;
  display: grid; place-items: center; background: #fff; border: 2px solid var(--line);
  font: 700 12px 'Space Grotesk', sans-serif; color: var(--muted);
}
.cfpOf .wizRail .lbl {
  font-size: 10.5px; font-weight: 700; letter-spacing: .02em; color: var(--muted);
  text-align: center; line-height: 1.25; max-width: 84px;
}
/* A completed step wears the same struck check as the "all set" list — same
   dome, same drop shadow, same stroked-white glyph — so a tick means one thing
   everywhere in the flow. font-size: 0 hides the step NUMBER underneath it. */
.cfpOf .wizRail li.done .dot {
  border-color: #4d8b19; color: #fff; font-size: 0;
  background: linear-gradient(180deg, #74c22a 0%, #4d8b19 100%);
  box-shadow:
    0 4px 8px -4px rgba(77, 139, 25, .6),
    0 1px 2px rgba(6, 17, 31, .18),
    inset 0 1px 0 rgba(255, 255, 255, .5),
    inset 0 -3px 6px -4px rgba(6, 17, 31, .45);
}
.cfpOf .wizRail li.done .dot:after {
  content: "✓";
  font: 900 14px/1 'DM Sans', sans-serif;
  -webkit-text-stroke: 0.7px #fff;
  text-shadow: 0 1px 1px rgba(6, 17, 31, .35);
}
.cfpOf .wizRail li.done:not(:last-child):after { background: #4d8b19; }
.cfpOf .wizRail li.active .dot { background: var(--navy); border-color: var(--navy); color: var(--lime); }
.cfpOf .wizRail li.active .lbl { color: var(--ink); }

/* On narrow screens the labels stop fitting long before the dots do. */
@media (max-width: 560px) {
  .cfpOf .wizRail { padding: 16px 18px 12px; }
  .cfpOf .wizRail .lbl { display: none; }
  .cfpOf .wizRail li.active .lbl {
    display: block; position: absolute; top: 30px; white-space: nowrap; max-width: none;
  }
  .cfpOf .wizRail { padding-bottom: 30px; }
}

/* ---- Shared pieces ------------------------------------------------------ */
.cfpOf .eyebrow {
  display: inline-block; font-size: 11px; font-weight: 800; letter-spacing: .16em;
  text-transform: uppercase; color: #4d8b19; margin-bottom: 14px;
}
.cfpOf h1 { font-size: clamp(34px, 4.6vw, 54px); line-height: 1.05; letter-spacing: -.045em; margin: 0 0 16px; }
.cfpOf h2 { font-size: clamp(26px, 3.2vw, 38px); line-height: 1.1; letter-spacing: -.035em; margin: 0 0 12px; }
.cfpOf h3 { font-size: 18px; letter-spacing: -.01em; margin: 0 0 8px; }
.cfpOf .lede { color: var(--muted); font-size: 17px; line-height: 1.62; margin: 0 0 28px; }

.cfpOf .btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  min-height: 52px; padding: 0 26px; border: 0; border-radius: 12px;
  background: var(--lime); color: var(--navy);
  font: 700 16px 'DM Sans', sans-serif; cursor: pointer; transition: .2s;
}
.cfpOf .btn:hover:not(:disabled) { background: #d2ff82; transform: translateY(-2px); }
.cfpOf .btn:disabled { opacity: .55; cursor: default; }
.cfpOf .btn.dark { background: var(--navy); color: #fff; }
.cfpOf .btn.dark:hover:not(:disabled) { background: #0c2036; }
.cfpOf .btn.ghost { background: transparent; color: var(--ink); border: 1px solid var(--line); }
.cfpOf .btn.ghost:hover:not(:disabled) { background: #fff; }
.cfpOf .btn.block { width: 100%; }
.cfpOf .textLink { color: #4d8b19; font-weight: 600; text-decoration: underline; cursor: pointer; }
.cfpOf .textLink:hover { color: #3c6d14; }
/* Several of these are <button> (they run JS rather than navigate), which
   otherwise arrive with the UA's chrome — border, grey fill, its own font — and
   read as a small grey button mid-sentence instead of a link. */
.cfpOf button.textLink { padding: 0; border: 0; background: none; font-family: inherit; font-size: inherit; }

/* The four-point scanner trust line, repeated wherever the app is mentioned. */
.cfpOf .trustLine {
  display: flex; flex-wrap: wrap; justify-content: center; gap: 6px 18px;
  margin: 18px 0 0; padding: 0; list-style: none;
  color: var(--muted); font-size: 13.5px;
}
.cfpOf .trustLine li { display: flex; align-items: center; gap: 7px; }
.cfpOf .trustLine li:before { content: "✓"; color: #4d8b19; font-weight: 700; }

.cfpOf .card {
  background: #fff; border: 1px solid var(--line); border-radius: 16px; padding: 30px 28px;
}
.cfpOf .cardMuted { background: var(--cream); }

/* ---- Entry screen -------------------------------------------------------
 * Named areas, not two stacked columns: the action card has to be able to jump
 * ahead of the proof ticker and the explainer when this collapses to one
 * column, which is the only way the CTA stays above the fold on a phone.
 * Row spacing comes from each block's own margin so the areas can reflow
 * without a grid gap fighting them. */
.cfpOf .introGrid {
  display: grid; grid-template-columns: 1.05fr .95fr; gap: 0 44px; align-items: start;
  grid-template-areas:
    "copy  action"
    "proof action";
}
.cfpOf .introCopy { grid-area: copy; }
/* Sits directly under the lede — the only separation is that paragraph's own
   28px bottom margin, so the proof reads as part of the opening statement
   rather than a separate block further down.
   Perspective lives on the PARENT: a rotateY on an element with no perspective
   ancestor is a flat squash, not a turn. */
.cfpOf .introProof { grid-area: proof; perspective: 1000px; }
.cfpOf .introAction { grid-area: action; }

/* The home page's rotating payout card, rebuilt under this page's scope —
   see the note in web/routes/offer.php for why the classes are not shared. */
.cfpOf .payTicker {
  max-width: 340px; padding: 20px 24px; border-radius: 14px;
  background: #0c1c2d; border: 1px solid #ffffff1a; color: #fff;
  box-shadow: 0 24px 60px -36px rgba(6, 17, 31, .7);
  transform-style: preserve-3d;
}

/* The whole card turns on its vertical axis, empties itself, spins up, then
   decelerates onto the next payout — a reel coming to rest.
 *
 * Two easings in one animation, which is why this is @keyframes and not a
 * transition: keyframes can carry their own animation-timing-function, so the
 * turn away from the reader accelerates (ease-in) and the long spin coasts to a
 * stop (a heavy ease-out). One timing function across the whole thing reads as
 * a wobble rather than a spin.
 *
 * 990 degrees from the edge-on 90 to 1080 — nearly three full turns, and 1080 is
 * a multiple of 360, so it lands square to the reader. The content is faded out
 * at the 15% mark by the JS, which is why the back of the card showing through
 * for half of every turn costs nothing: there is nothing on it to mirror. */
.cfpOf .payTicker.ptSpin { animation: ptSpin 1.6s both; will-change: transform; }
@keyframes ptSpin {
  0%   { transform: rotateY(0deg);    animation-timing-function: cubic-bezier(.5, 0, .9, .35); }
  15%  { transform: rotateY(90deg);   animation-timing-function: cubic-bezier(.08, .62, .2, 1); }
  100% { transform: rotateY(1080deg); }
}

/* Blank card: the payout, the badge and the footnote all go, but the box keeps
   its size — collapsing it would reflow the column three times a rotation. */
.cfpOf .payTicker .ptTop,
.cfpOf .payTicker .ptBody,
.cfpOf .payTicker .ptReal { transition: opacity .2s ease; }
.cfpOf .payTicker.ptBlank .ptTop,
.cfpOf .payTicker.ptBlank .ptBody,
.cfpOf .payTicker.ptBlank .ptReal { opacity: 0; transition-duration: .12s; }
.cfpOf .ptTop { display: flex; align-items: center; justify-content: space-between; gap: 16px; margin-bottom: 10px; }
.cfpOf .ptLive { font-size: 9px; letter-spacing: 1.5px; color: #a6b4c0; font-weight: 700; }
.cfpOf .ptLive i {
  display: inline-block; width: 6px; height: 6px; margin-right: 7px; border-radius: 50%;
  background: var(--lime); box-shadow: 0 0 10px var(--lime);
}
.cfpOf .ptStars { display: flex; gap: 3px; }
.cfpOf .ptStars svg { fill: var(--lime); }
.cfpOf .ptBody span { display: block; font-size: 13px; letter-spacing: .4px; color: #9eacb8; }
.cfpOf .ptBody b { color: var(--lime); font-weight: 700; }
.cfpOf .ptBody strong {
  display: block; margin: 5px 0; color: #fff;
  font: 700 34px 'Space Grotesk', sans-serif; letter-spacing: -.02em;
}
.cfpOf .ptReal { display: block; margin-top: 10px; font-size: 10.5px; color: #7d8d9b; }
/* Still rotates through the payouts — it just cuts between them rather than
   spinning a card at someone who asked the OS not to do that. */
@media (prefers-reduced-motion: reduce) {
  .cfpOf .payTicker.ptSpin { animation: none; }
  .cfpOf .payTicker .ptTop,
  .cfpOf .payTicker .ptBody,
  .cfpOf .payTicker .ptReal { transition: none; }
  .cfpOf .payTicker.ptBlank .ptTop,
  .cfpOf .payTicker.ptBlank .ptBody,
  .cfpOf .payTicker.ptBlank .ptReal { opacity: 1; }
}
.cfpOf .scanCard { position: relative; border: 2px solid var(--lime); box-shadow: 0 24px 60px -34px rgba(6, 17, 31, .5); }
.cfpOf .recommend {
  position: absolute; top: -13px; left: 28px; padding: 4px 12px; border-radius: 99px;
  background: var(--lime); color: var(--navy); font-size: 11px; font-weight: 800; letter-spacing: .1em;
}
/* The compact non-Windows action. Hidden everywhere by default and swapped in
   only at phone width, by the media query at the end of this file — the scan
   card stays put on tablets and anything wider, where there is room for it to
   go on making its case. .noWin is set by the platform detection. */
.cfpOf #mobileStart { display: none; }

.cfpOf .checks { list-style: none; margin: 0 0 26px; padding: 0; }
.cfpOf .checks li { display: flex; gap: 11px; padding: 9px 0; border-bottom: 1px dashed var(--line); font-size: 15px; line-height: 1.5; }
.cfpOf .checks li:last-child { border-bottom: 0; }
.cfpOf .checks li:before { content: "✓"; color: #4d8b19; font-weight: 700; flex: 0 0 auto; }
.cfpOf .platformNote { margin: 14px 0 0; font-size: 13px; color: var(--muted); text-align: center; }

/* ---- Read / not-read columns (modal + why panel) ------------------------ */
.cfpOf .readsGrid { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; margin: 4px 0 22px; text-align: left; }
.cfpOf .readsGrid h4 { font: 800 11px 'DM Sans', sans-serif; letter-spacing: .13em; text-transform: uppercase; margin: 0 0 10px; }
.cfpOf .readsGrid ul { list-style: none; margin: 0; padding: 0; font-size: 14px; line-height: 1.9; color: #45525f; }
.cfpOf .readsYes h4 { color: #4d8b19; }
.cfpOf .readsNo h4 { color: #a2553f; }
.cfpOf .readsYes li:before { content: "✓ "; color: #4d8b19; font-weight: 700; }
.cfpOf .readsNo li:before { content: "✕ "; color: #c07a66; font-weight: 700; }

/* ---- Modal (lifted from the /download platform modal) ------------------- */
.cfpOf .cfpModal { position: fixed; inset: 0; z-index: 100; display: grid; place-items: center; padding: 20px; background: rgba(6, 17, 31, .72); backdrop-filter: blur(4px); overflow-y: auto; }
.cfpOf .cfpModal[hidden] { display: none; }
/* The link modal can be opened from INSIDE the wizard (the "not enough to price
   this" pane sends a non-Windows seller here), and #wizard comes after it in the
   DOM -- at equal z-index that paints the wizard on top and the seller sees the
   button do nothing at all. Lift it above rather than reordering the markup,
   which would move the wizard out of its own reading order. */
.cfpOf #linkModal { z-index: 120; }
.cfpOf .cfpModalCard { position: relative; width: 100%; max-width: 560px; margin: auto; background: #fff; color: #101923; border-radius: 18px; padding: 34px 30px 26px; box-shadow: 0 44px 90px -30px rgba(0, 0, 0, .65); }
.cfpOf .cfpModalClose { position: absolute; top: 14px; right: 14px; width: 32px; height: 32px; display: grid; place-items: center; border: 0; border-radius: 9px; background: #eef1ee; color: #5a6b5a; cursor: pointer; font-size: 14px; }
/* The step rail starts BELOW the close button rather than under it.
   The compound selector is load-bearing: `.cfpOf .wizCard` and
   `.cfpOf .cfpModalCard` are the same specificity (0,2,0) and cfpModalCard is
   declared later, so the wizard card was silently taking the shared modal's
   34px top padding — which put the rail behind the ✕ (14px + 32px = 46px).
   54px clears it with room to breathe. Only the TOP is reset: the wizard's
   rail, body and footer are full-bleed bands and were meant to have no side
   padding at all, but undoing that here would widen every pane by 60px. */
.cfpOf .cfpModalCard.wizCard { padding-top: 54px; }
.cfpOf .cfpModalClose:hover { background: #e3e7e2; }
.cfpOf .cfpModalCard h2 { font-size: 24px; margin: 0 0 10px; text-align: center; }
.cfpOf .cfpModalCard > p { font-size: 15px; line-height: 1.62; color: #5a6675; margin: 0 0 20px; text-align: center; }
.cfpOf .promise { background: #f2f9e4; border: 1px solid #d8ecb4; border-radius: 12px; padding: 15px 17px; margin: 0 0 22px; font-size: 14.5px; line-height: 1.6; color: #33501a; }
.cfpOf .cfpModalActions { display: flex; flex-direction: column; align-items: center; gap: 12px; }
.cfpOf .modalMeta { font-size: 12.5px; color: #6a7686; text-align: center; margin: 0; line-height: 1.7; }

/* Send-link confirmation. Centred like the rest of the modal — it is not a
   direct child of .cfpModalCard, so that rule's text-align does not reach it. */
.cfpOf #sendLinkOk { text-align: center; }
.cfpOf #sendLinkOk > p { font-size: 15px; line-height: 1.62; color: #5a6675; margin: 0 0 12px; }
.cfpOf #sendLinkOk > p.note { margin-bottom: 22px; }
.cfpOf #sendLinkOk b { color: var(--ink); word-break: break-word; }
.cfpOf .modalMeta a { color: #4d8b19; font-weight: 600; text-decoration: underline; }

/* ---- Downloading screen ------------------------------------------------- */
.cfpOf .steps { list-style: none; counter-reset: s; margin: 0 0 30px; padding: 0; }
.cfpOf .steps li { counter-increment: s; position: relative; padding: 0 0 26px 56px; }
.cfpOf .steps li:before {
  content: counter(s); position: absolute; left: 0; top: -3px; width: 38px; height: 38px;
  display: grid; place-items: center; border-radius: 50%; background: var(--navy); color: var(--lime);
  font: 700 16px 'Space Grotesk', sans-serif;
}
.cfpOf .steps li p { margin: 0; color: var(--muted); font-size: 15px; line-height: 1.6; }
.cfpOf .publisherRow {
  display: inline-flex; align-items: center; gap: 9px; margin-top: 9px; padding: 9px 14px;
  border: 1px solid var(--line); border-radius: 10px; background: #fff; font-size: 14px;
}
.cfpOf .publisherRow b { font-family: 'Space Grotesk', sans-serif; }

/* Collapsed "Windows showed a warning?" disclosure. Deliberately NOT the
   headline: leading with how to click past a security prompt trains sellers to
   dismiss the ones that matter, and Google's unwanted-software policy reads
   prominent bypass instructions as circumvention.

   Removed on 2026-08-25 when the certificate landed, then RESTORED the same day
   once a real Windows 10 test showed signing does not clear SmartScreen on its
   own. Read the comment beside #warnBox in web/routes/offer.php before touching
   this again. */
.cfpOf .warnBox { border: 1px solid var(--line); border-radius: 13px; background: #fff; overflow: hidden; margin-top: 8px; }
.cfpOf .warnBox > button { width: 100%; display: flex; justify-content: space-between; align-items: center; gap: 12px; padding: 15px 18px; border: 0; background: transparent; cursor: pointer; font: 600 14.5px 'DM Sans', sans-serif; color: var(--muted); text-align: left; }
.cfpOf .warnBox > div { display: grid; grid-template-rows: 0fr; transition: grid-template-rows .28s ease; }
.cfpOf .warnBox > div > div { overflow: hidden; }
.cfpOf .warnBox.active > div { grid-template-rows: 1fr; }
.cfpOf .warnBody { padding: 0 18px 18px; color: var(--muted); font-size: 14px; line-height: 1.7; }
.cfpOf .warnBody ol { margin: 0; padding-left: 20px; }

/* ---- Waiting ------------------------------------------------------------ */
.cfpOf .spinner {
  display: block; width: 46px; height: 46px; border-radius: 50%;
  border: 4px solid #e6ece0; border-top-color: #4d8b19;
  animation: cfpOfSpin 1s linear infinite; flex: 0 0 auto;
}
.cfpOf .spinner.small { width: 26px; height: 26px; border-width: 3px; }
@keyframes cfpOfSpin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .cfpOf .spinner { animation-duration: 3s; } }

.cfpOf .waitStrip {
  display: flex; align-items: flex-start; gap: 14px; margin-top: 18px;
  padding: 16px 18px; border-radius: 13px; background: var(--cream); border: 1px solid var(--line);
}
.cfpOf .waitStrip b { font-size: 15px; }
.cfpOf .meetHere {
  padding: 14px 16px; border-radius: 12px; background: var(--cream);
  border: 1px solid var(--line); margin: 0 0 18px;
}

/* ---- Detected specs ----------------------------------------------------- */
.cfpOf .specList { list-style: none; margin: 0 0 8px; padding: 0; }
.cfpOf .specList li { display: grid; grid-template-columns: 132px 1fr; gap: 16px; padding: 14px 0; border-bottom: 1px solid var(--line); align-items: baseline; }
.cfpOf .specList li:last-child { border-bottom: 0; }
.cfpOf .specList .k { font: 800 11px 'DM Sans', sans-serif; letter-spacing: .12em; text-transform: uppercase; color: var(--muted); }
.cfpOf .specList .v { font-size: 16px; line-height: 1.45; word-break: break-word; }

/* ---- Condition questions ------------------------------------------------ */
.cfpOf .q { padding: 22px 0; border-bottom: 1px solid var(--line); }
.cfpOf .q:last-of-type { border-bottom: 0; }
.cfpOf .q > legend, .cfpOf .q > .qTitle { font: 700 17px 'DM Sans', sans-serif; margin: 0 0 14px; padding: 0; }
.cfpOf fieldset.q { border: 0; margin: 0; }
.cfpOf .opts { display: flex; flex-wrap: wrap; gap: 10px; }
.cfpOf .opt {
  display: inline-flex; align-items: center; gap: 9px; padding: 12px 18px;
  border: 1px solid var(--line); border-radius: 11px; background: #fff;
  font-size: 15px; cursor: pointer; transition: .15s;
}
.cfpOf .opt:hover { border-color: #b6c4a8; }
.cfpOf .opt input { accent-color: #4d8b19; width: 17px; height: 17px; margin: 0; }
.cfpOf .opt:has(input:checked) { border-color: #4d8b19; background: #f4fae9; box-shadow: inset 0 0 0 1px #4d8b19; }
.cfpOf .opt input:focus-visible { outline: 2px solid var(--navy); outline-offset: 3px; }
/* The two-way fork on step 2. The plain .opt is a pill for one-word answers
   ("Yes" / "No" / "Not sure"); these two carry a sentence each, so they stack
   full width at every size and align to the top rather than centring a radio
   against three lines of text. */
.cfpOf .opts-pick { flex-direction: column; align-items: stretch; gap: 10px; }
.cfpOf .opts-pick .opt { align-items: flex-start; padding: 14px 16px; }
.cfpOf .opts-pick .opt input { margin-top: 2px; flex: 0 0 auto; }
.cfpOf .optBody { display: block; }
.cfpOf .optBody b { display: block; font-weight: 700; margin-bottom: 3px; }
.cfpOf .optBody small { display: block; font-size: .84rem; color: var(--muted); line-height: 1.45; }

.cfpOf .detail { margin-top: 14px; }
.cfpOf .detail[hidden] { display: none; }

/* ---- Forms -------------------------------------------------------------- */
.cfpOf .field { margin-bottom: 16px; position: relative; }
.cfpOf .field label { display: block; font: 700 13px 'DM Sans', sans-serif; margin-bottom: 6px; }
.cfpOf .field input, .cfpOf .field textarea, .cfpOf .field select {
  width: 100%; padding: 13px 14px; border: 1px solid var(--line); border-radius: 11px;
  background: var(--field-bg); font: 400 16px 'DM Sans', sans-serif; color: var(--ink);
}
.cfpOf .field input:focus, .cfpOf .field textarea:focus, .cfpOf .field select:focus {
  outline: 0; border-color: #4d8b19; box-shadow: 0 0 0 3px rgba(77, 139, 25, .13);
}
.cfpOf .field textarea { min-height: 88px; resize: vertical; }
/* Chrome paints its own background over an autofilled field, which on the name
   and email -- the two most likely to be autofilled on this page -- would drop
   a pale yellow box into the middle of the lime ones. There is no property that
   overrides it; an inset shadow tall enough to cover the field is the only
   lever, and the text colour has to be restated because it is overridden too. */
.cfpOf .field input:-webkit-autofill,
.cfpOf .field input:-webkit-autofill:hover,
.cfpOf .field input:-webkit-autofill:focus {
  -webkit-box-shadow: 0 0 0 100px var(--field-bg) inset;
  -webkit-text-fill-color: var(--ink);
}
/* Placeholders are EXAMPLES, not labels -- every field here carries a real
   <label> above it, and the hint only ever shows what a value looks like -- so
   they should sit well back from both the label and whatever the seller types
   over them. The browser default (~#757575) read as a value already filled in.

   #b3bec6 measures 1.80:1 on --field-bg, against 16.6:1 for the typed value.
   That is deliberately below what WCAG asks of body text: nothing is lost when
   a placeholder is hard to read, because the label carries the meaning and the
   hint is an example. It is a trade made on purpose, not an oversight.

   opacity:1 is load-bearing -- Firefox applies its own opacity to placeholders,
   so a colour alone would still render paler there than everywhere else.

   Scoped to .cfpOf rather than .field: the link modal and the address form
   carry placeholders too, and one page should have one placeholder colour. */
.cfpOf input::placeholder,
.cfpOf textarea::placeholder { color: #b3bec6; opacity: 1; }

/* ---- component-name typeahead ------------------------------------------
   The suggestion list under a [data-suggest] field. Anchored to .field, which
   is why that rule gains position:relative above: .wizBody scrolls, and a list
   positioned against the card or the viewport would part company with its
   input on the first scroll.

   z-index clears the NEXT field's input rather than the modal: the list only
   ever has to cover the form under it, and stacking it higher would put it
   over the sticky footer the seller uses to continue. */
.cfpOf .sugBox {
  position: absolute; z-index: 5; left: 0; right: 0; top: 100%; margin-top: 4px;
  max-height: 232px; overflow-y: auto; -webkit-overflow-scrolling: touch;
  background: #fff; border: 1px solid var(--line); border-radius: 11px;
  box-shadow: 0 18px 40px -18px rgba(6, 17, 31, .38);
}
.cfpOf .sugBox[hidden] { display: none; }
.cfpOf .sugOpt {
  padding: 11px 14px; font: 400 15px 'DM Sans', sans-serif; color: var(--ink);
  cursor: pointer; border-bottom: 1px solid rgba(17, 27, 38, .06);
}
.cfpOf .sugOpt:last-child { border-bottom: 0; }
/* Keyboard and pointer land on the same visual state -- arrowing down a list
   that looks different from the one you can tap reads as two lists. */
.cfpOf .sugOpt:hover,
.cfpOf .sugOpt.isActive { background: rgba(184, 243, 74, .22); }

/* A phone puts the on-screen keyboard over the bottom half of the screen, so a
   list that opens downward into it is a list nobody can read. Shorter here, and
   the field it belongs to is scrolled into view by the browser on focus. */
@media (max-width: 620px) {
  .cfpOf .sugBox { max-height: 176px; }
  .cfpOf .sugOpt { padding: 12px 14px; }
}

.cfpOf .row2 { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.cfpOf .row3 { display: grid; grid-template-columns: 2fr 1fr 1fr; gap: 16px; }
/* Verification codes: wide tracking so a 6-digit code is easy to check. */
.cfpOf .codeInput { font-family: 'Space Grotesk', sans-serif !important; font-size: 23px !important; letter-spacing: .3em; text-align: center; }
.cfpOf .err { margin: 12px 0 0; padding: 12px 14px; border-radius: 10px; background: #fdeceb; border: 1px solid #f3c9c4; color: #8c3527; font-size: 14.5px; line-height: 1.55; }
.cfpOf .err[hidden] { display: none; }
.cfpOf .note { color: var(--muted); font-size: 13.5px; line-height: 1.6; margin: 12px 0 0; }

/* ---- Offer -------------------------------------------------------------- */
.cfpOf .offerCard {
  background: var(--navy); color: #fff; border-radius: 20px; padding: 44px 34px; text-align: center;
  position: relative; overflow: hidden;
}
/* The spotlight behind the amount. Blue, not lime: the same accent the home
   page's REAL PAYOUTS section uses (.cfpOffersGlow.one in public-cashforpc.css,
   rgba(var(--cfp-spot-rgb), .3)), so the two money moments on the site are lit
   the same way. The lime tint read as a green cast over a navy card. */
.cfpOf .offerCard:after {
  content: ""; position: absolute; width: 460px; height: 380px; border-radius: 50%;
  background: rgba(var(--cfp-spot-rgb), .3); filter: blur(120px); right: -160px; top: -130px; pointer-events: none;
}
.cfpOf .offerCard > * { position: relative; z-index: 1; }
.cfpOf .offerKicker { font: 800 11px 'DM Sans', sans-serif; letter-spacing: .18em; text-transform: uppercase; color: #8fa2b1; margin: 0 0 10px; }
.cfpOf .offerAmount { font-family: 'Space Grotesk', sans-serif; font-size: clamp(58px, 10vw, 92px); font-weight: 700; line-height: 1; letter-spacing: -.04em; color: var(--lime); margin: 0; }
/* The offer a redeemed counter replaced. Sits directly above the live number,
   smaller and struck through, so the pair reads as a correction rather than as
   two competing prices. Muted slate rather than lime: only one number on this
   screen is the offer. */
/* Entered from a follow-up email: the seller has already declined once, so the
   decline link is an invitation to repeat the thing they came back from. Hidden
   at every width, unlike the phone rule further down which is about space. */
#wizard[data-entry="link"] #offerDeclineWrap { display: none; }

/* The manual pane offers to email the scanner link instead. That is the point
   of the pane on a phone and noise on Windows, where `manual` is only ever
   reached as the fallback for a scan that would not run on the machine the
   seller is already sitting at. */
.cfpOf .offerPrevWrap { margin: 0 0 4px; line-height: 1.15; }
.cfpOf .offerPrevLabel { display: block; font-size: 12px; letter-spacing: .08em; text-transform: uppercase; color: #8fa3b8; }
.cfpOf .offerPrev { font-family: 'Space Grotesk', sans-serif; font-size: clamp(22px, 3.4vw, 30px); font-weight: 600; color: #8fa3b8; text-decoration: line-through; }
.cfpOf .wizBody .offerPrev { font-size: clamp(18px, 2.6vw, 24px); }
.cfpOf .offerFor { color: #c6d3dd; font-size: 16px; line-height: 1.5; margin: 14px auto 0; max-width: 460px; }
.cfpOf .offerCard .btn { margin-top: 26px; }
.cfpOf .reviewNote { margin: 20px auto 0; max-width: 500px; padding: 14px 16px; border-radius: 12px; background: rgba(255, 255, 255, .07); color: #dbe5ec; font-size: 14px; line-height: 1.6; }
/* The date the offer holds until — the one fact in this box worth finding at a
   glance, so it takes the accent the amount above it is priced in. */
.cfpOf .offerDate { color: var(--lime); font-weight: 700; }

.cfpOf .breakdown { margin-top: 26px; }
.cfpOf .breakdown table { width: 100%; border-collapse: collapse; font-size: 15px; }
.cfpOf .breakdown th, .cfpOf .breakdown td { text-align: left; padding: 11px 6px; border-bottom: 1px solid var(--line); }
.cfpOf .breakdown th { font: 800 11px 'DM Sans', sans-serif; letter-spacing: .12em; text-transform: uppercase; color: var(--muted); }
.cfpOf .breakdown td:last-child, .cfpOf .breakdown th:last-child { text-align: right; white-space: nowrap; }
.cfpOf .breakdown tfoot td { font-weight: 700; border-bottom: 0; border-top: 2px solid var(--ink); }
.cfpOf .tableScroll { overflow-x: auto; }

/* Checkbox variant of the option chips — stacked, because these are read as a
   list of things you own rather than a row of alternatives. */
.cfpOf .opts-check { flex-direction: column; align-items: stretch; gap: 6px; }
.cfpOf .opts-check .opt { justify-content: flex-start; }
.cfpOf .opts-check .opt input { accent-color: #4d8b19; }
/* The tower is checked and locked: it is the thing being sold, not an extra.
   Shown as settled rather than greyed out — disabled styling would read as
   "unavailable" when it means "of course". */
.cfpOf .opt.locked { border-color: #4d8b19; background: #f4fae9; cursor: default; }
/* A disabled input swallows its own clicks — the event never fires, and never
   reaches the label either. Letting pointer events through is what makes a click
   ON the tick box behave like a click anywhere else on the row. */
.cfpOf .opt.locked input { cursor: default; pointer-events: none; }

/* What the number is based on, inside the offer card: the hardware we read and
   the answers the seller gave, on the navy so it reads as one statement. */
.cfpOf .offerBasis {
  margin-top: 22px; padding-top: 16px; border-top: 1px solid rgba(255, 255, 255, .13);
  text-align: left;
}
.cfpOf .offerBasisHead {
  margin: 0 0 10px; font: 800 10px 'DM Sans', sans-serif; letter-spacing: .16em;
  text-transform: uppercase; color: #8fa2b1;
}
.cfpOf .offerSpecs, .cfpOf .offerAnswers { list-style: none; margin: 0; padding: 0; }
.cfpOf .offerSpecs li {
  display: grid; grid-template-columns: 96px 1fr; gap: 12px; padding: 5px 0;
  font-size: 13.5px; line-height: 1.4; color: #dbe5ec;
}
.cfpOf .offerSpecs .k {
  font: 800 10px 'DM Sans', sans-serif; letter-spacing: .1em; text-transform: uppercase;
  color: #8fa2b1; padding-top: 2px;
}
.cfpOf .offerAnswers {
  margin-top: 10px; padding-top: 10px; border-top: 1px dashed rgba(255, 255, 255, .13);
}
/* One row, one line. The seller's free text is appended to these rows, and a
   character cap in the JS cannot know how wide 90 characters render — so the cut
   is made HERE, where the width is known, and the browser draws the ellipsis.
   The JS cap stays as a bound on how much text reaches the DOM at all. */
.cfpOf .offerAnswers li {
  padding: 4px 0; font-size: 13px; line-height: 1.4; color: #b9c7d3;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.cfpOf .offerAnswers li b { color: var(--lime); font-weight: 700; }

/* ---- Terminal / decline screens ----------------------------------------- */
.cfpOf .centered { text-align: center; }
.cfpOf .bigIcon { width: 72px; height: 72px; margin: 0 auto 20px; border-radius: 20px; display: grid; place-items: center; font-size: 32px; background: #eef7dc; color: #4d8b19; }
.cfpOf .bigIcon.warn { background: #fdf1e3; color: #b5713a; }
.cfpOf .nextSteps { list-style: none; margin: 26px 0 0; padding: 0; text-align: left; }
/* Indent-and-absolute, NOT flex.
 *
 * As a flex row every element inside the item became its own COLUMN: a <b>
 * lead-in sat in a box beside the sentence it introduces, and a second <b>
 * (a file path, mid-sentence) split the line into three columns that no longer
 * read as a sentence at all. Which is what /scanner-security was doing.
 *
 * The disc is out of flow and the text is one ordinary paragraph, so bold,
 * links and code inside an item behave the way they do everywhere else. The
 * 43px indent is the disc (30px) plus the gap it used to have (13px). */
.cfpOf .nextSteps li { position: relative; padding: 12px 0 12px 43px; border-bottom: 1px dashed var(--line); font-size: 15px; line-height: 1.55; }
.cfpOf .nextSteps li:last-child { border-bottom: 0; }
/* A struck check, not a text arrow: a domed green disc lit from above, with a
   drop shadow to sit it off the page and a white inner rim along the top. The
   glyph is stroked in its own white so it reads FAT — the font tops out at 700
   and there is no heavier cut to ask for. */
.cfpOf .nextSteps li:before {
  content: "✓";
  position: absolute; left: 0; top: 13px;
  width: 30px; height: 30px; border-radius: 50%;
  display: grid; place-items: center;
  font: 900 17px/1 'DM Sans', sans-serif; color: #fff;
  -webkit-text-stroke: 0.7px #fff;
  background: linear-gradient(180deg, #74c22a 0%, #4d8b19 100%);
  box-shadow:
    0 5px 9px -4px rgba(77, 139, 25, .6),
    0 1px 2px rgba(6, 17, 31, .18),
    inset 0 1px 0 rgba(255, 255, 255, .5),
    inset 0 -4px 7px -4px rgba(6, 17, 31, .45);
  text-shadow: 0 1px 1px rgba(6, 17, 31, .35);
}

/* The how-to, given room of its own under the list. */
.cfpOf .doneLink { margin: 26px 0 0; text-align: center; font-size: 14.5px; }

/* ---- Responsive --------------------------------------------------------- */
@media (max-width: 900px) {
  /* One column: headline, then the payout card, then the button. The proof goes
     ahead of the action deliberately — the card is short enough that the button
     still lands high, and a visitor reads what we have actually paid before
     being asked to do anything. Same order for every platform: the action slot
     is a button on all of them now (the capture form moved into #linkModal). */
  .cfpOf .introGrid {
    grid-template-columns: 1fr; gap: 0;
    grid-template-areas: "copy" "proof" "action";
  }
  /* The button gets a wider gap than the payout card above it, so the two do not
     read as one stacked unit — the card is proof, the button is the ask. */
  .cfpOf .introAction { margin-top: 64px; }
  .cfpOf .introProof { margin-top: 26px; }
  .cfpOf .payTicker { max-width: none; }
  .cfpOf .readsGrid { grid-template-columns: 1fr; }
}
/* (The old max-height: 660px shrink rule lived here. The min() on .wizBody now
   does the same job continuously, so a hard breakpoint would only fight it.) */
@media (max-width: 620px) {
  .cfpOf .landing { padding: 44px 0 66px; }
  /* Phone: the viewport is the limit, so the body takes whatever is left rather
     than a fixed 540. The 268px is measured chrome — modal padding, the card's
     top band, the rail and the footer — and was 240 before the rail moved below
     the close button, which left the card ~28px taller than the screen. */
  .cfpOf .wizBody { padding: 20px 20px 22px; height: calc(100vh - 268px); min-height: 300px; }

  /* The page's mobile rules stack these, which is right for the landing page and
     wrong inside a fixed-height modal — stacking is exactly what pushed four
     panes into a scrollbar. The fields involved are short (selects, a 2-letter
     state, a ZIP), so two columns stay comfortably tappable at 390px. */
  .cfpOf .wizBody .row2 { grid-template-columns: 1fr 1fr; gap: 10px; }
  .cfpOf .wizBody .row3 { grid-template-columns: 2fr 1fr 1fr; gap: 10px; }
  .cfpOf .wizBody .readsGrid { grid-template-columns: 1fr 1fr; gap: 12px; }
  .cfpOf .wizBody .opts { flex-direction: row; flex-wrap: wrap; }
  .cfpOf .wizBody .opt { padding: 8px 12px; font-size: 13.5px; }
  .cfpOf .wizBody .specList li { grid-template-columns: 100px 1fr; gap: 10px; }
  .cfpOf .wizFoot { padding: 12px 20px 14px; }
  /* ---- Full-screen wizard on a phone --------------------------------------
     A counter email lands on a phone far more often than on a desktop, and the
     seller arrives INSIDE the flow with a live offer rather than on a page they
     are browsing. A centred card with 20px of gutter spends the scarcest screen
     in the funnel on a backdrop nobody is looking at, so on phone widths the
     wizard simply becomes the page.

     100dvh, not 100vh: on iOS and Android the browser chrome expands and
     collapses as you scroll, and 100vh is the LARGEST viewport — sized against
     it, the footer holding the primary button sits under the address bar until
     the user scrolls, which on a pane that does not scroll means it can never
     be reached. dvh tracks the visible height. 100vh is kept first as the
     fallback for browsers that do not know dvh. */
  .cfpOf .wizModal { padding: 0; align-items: stretch; overflow: hidden; }
  .cfpOf .cfpModalCard.wizCard {
    width: 100%; max-width: none; margin: 0; border-radius: 0;
    height: 100vh; height: 100dvh;
    max-height: 100vh; max-height: 100dvh;
    box-shadow: none;
  }
  /* The body stops being a fixed height and simply takes what is left between
     the step rail and the footer. On a fixed height it either left a band of
     dead space at the bottom of a tall phone or clipped on a short one. */
  .cfpOf .wizCard .wizBody {
    height: auto; min-height: 0; flex: 1 1 auto; overflow-y: auto;
    -webkit-overflow-scrolling: touch;
  }
  /* Clear of the home indicator on a notched iPhone, where a button flush to
     the bottom edge is the one the system gesture swallows. */
  .cfpOf .wizFoot { padding-bottom: calc(14px + env(safe-area-inset-bottom, 0px)); }

  /* "No thanks, not right now" is hidden on a phone: the sellers who reach this
     pane from the counter email have ALREADY declined once, and offering it again
     directly under the number that changed their mind invites them to repeat the
     thing they came back from.

     The Back button used to be hidden with it, in JS, on the same reasoning that a
     phone reached this pane from an email or not at all. That stopped being true
     on 2026-08-26, when the phone path became the whole wizard rather than a
     send-me-the-link ask — there is now an earlier step behind the offer, so Back
     stays. This rule never covered it and must not grow to.

     Hidden here rather than removed from the markup, because the desktop flow is a
     genuine multi-step form where both controls belong. */
  .cfpOf #offerDeclineWrap { display: none; }

  .cfpOf .codeValue { font-size: 25px; }
  .cfpOf .card { padding: 24px 20px; }
  .cfpOf .offerCard { padding: 34px 22px; }
  .cfpOf .row2, .cfpOf .row3 { grid-template-columns: 1fr; }
  .cfpOf .specList li { grid-template-columns: 1fr; gap: 3px; }
  .cfpOf .opts { flex-direction: column; align-items: stretch; }
  .cfpOf .opt { justify-content: flex-start; }
  .cfpOf .steps li { padding-left: 48px; }
}
@media (max-width: 430px) {
  .cfpOf .wrap, .cfpOf .narrow { width: calc(100% - 26px); }
  /* Phone width, non-Windows: the scan card's checklist is four lines about a
     download this device cannot run, and here it costs a screenful to say so.
     The compact button takes its place; the modal behind it carries the
     explanation. Anything wider — a large phone, a tablet — keeps the card. */
  .cfpOf .introAction.noWin #scanCard { display: none; }
  .cfpOf .introAction.noWin #mobileStart { display: block; }
}

/* =============================================================================
 * Below the fold — proof, journey, who we are, closing CTA.
 *
 * The page used to be one screen: hero, card, footer. These sections are for
 * the visitor who did not click the first time, which on cold ad traffic is
 * most of them. One dark section (the payouts) carries the contrast; the rest
 * stay on the cream page so the page does not read as a series of bands.
 * ========================================================================== */

.cfpOf .proof { background: var(--navy); color: #fff; padding: 78px 0 82px; }
.cfpOf .proof .eyebrow { color: var(--lime); }
.cfpOf .proof h2 { color: #fff; }
.cfpOf .proof .lede { color: #a9bacb; max-width: 520px; margin-bottom: 0; }
.cfpOf .proofHead {
  display: grid; grid-template-columns: 1.1fr .9fr; gap: 44px;
  align-items: end; margin-bottom: 36px;
}
.cfpOf .proofStats { list-style: none; margin: 0; padding: 0; display: grid; gap: 14px; }
.cfpOf .proofStats li {
  display: flex; align-items: baseline; gap: 14px;
  border-top: 1px solid #ffffff1f; padding-top: 13px;
}
.cfpOf .proofStats b {
  font: 700 29px/1 'Space Grotesk', sans-serif; color: var(--lime);
  letter-spacing: -.03em; white-space: nowrap;
}
.cfpOf .proofStats span { font-size: 14px; color: #a9bacb; }

.cfpOf .payGrid { display: grid; grid-template-columns: repeat(6, 1fr); gap: 14px; }
.cfpOf .payCard {
  background: #0e1f33; border: 1px solid #ffffff14; border-radius: 14px;
  padding: 18px 14px; text-align: center;
}
.cfpOf .payCard strong { display: block; font: 700 25px/1 'Space Grotesk', sans-serif; letter-spacing: -.03em; }
.cfpOf .payCard span { display: block; margin-top: 7px; font-size: 13px; color: #c3d1de; }
.cfpOf .payCard small { display: block; margin-top: 3px; font-size: 11.5px; color: #78899a; }
.cfpOf .proofNote { margin: 26px 0 0; max-width: 780px; font-size: 13.5px; line-height: 1.7; color: #8fa1b2; }
.cfpOf .proofNote a { color: #cdeb9a; text-decoration: underline; }

.cfpOf .journey { padding: 76px 0 68px; }
.cfpOf .journey h2 { margin-bottom: 42px; }

.cfpOf .who { padding: 6px 0 78px; }
.cfpOf .whoGrid { display: grid; grid-template-columns: 1fr 1fr; gap: 48px; align-items: start; }
.cfpOf .whoGrid .lede { margin-bottom: 0; }
.cfpOf .whoFacts {
  list-style: none; margin: 0; padding: 0; background: #fff;
  border: 1px solid var(--line); border-radius: 16px; overflow: hidden;
}
.cfpOf .whoFacts li {
  display: grid; grid-template-columns: 108px 1fr; gap: 14px;
  padding: 14px 20px; border-bottom: 1px solid var(--line); font-size: 15px; line-height: 1.5;
}
.cfpOf .whoFacts li:last-child { border-bottom: 0; }
.cfpOf .whoFacts b {
  align-self: center; font-size: 11.5px; letter-spacing: .1em;
  text-transform: uppercase; color: var(--muted);
}
.cfpOf .whoFacts a { color: #4d8b19; text-decoration: underline; }

.cfpOf .finalCta { padding: 0 0 90px; text-align: center; }
.cfpOf .finalCta .lede { max-width: 520px; margin: 0 auto 26px; }
.cfpOf .finalCta .platformNote { margin-top: 13px; }

@media (max-width: 900px) {
  .cfpOf .proofHead { grid-template-columns: 1fr; gap: 30px; align-items: start; }
  .cfpOf .payGrid { grid-template-columns: repeat(3, 1fr); }
  .cfpOf .whoGrid { grid-template-columns: 1fr; gap: 30px; }
}
@media (max-width: 620px) {
  .cfpOf .proof { padding: 60px 0 64px; }
  .cfpOf .payGrid { grid-template-columns: repeat(2, 1fr); }
  .cfpOf .journey { padding: 60px 0 54px; }
  .cfpOf .who { padding: 0 0 60px; }
  .cfpOf .whoFacts li { grid-template-columns: 92px 1fr; padding: 13px 16px; font-size: 14.5px; }
  .cfpOf .finalCta { padding: 0 0 72px; }
}

/* ---- Retention screen ("Why not just sell my PC online?") ---------------
 * Four reasons, each an icon plus a bold line plus one sentence. Read in a
 * glance or not at all: this pane exists for someone already on their way out.
 * -------------------------------------------------------------------- */
.cfpOf .whyUs { list-style: none; margin: 18px 0 0; padding: 0; text-align: left; }
.cfpOf .whyUs li {
  display: flex; gap: 13px; align-items: flex-start;
  padding: 12px 0; border-bottom: 1px dashed var(--line);
}
.cfpOf .whyUs li:last-child { border-bottom: 0; }
/* The "no X" badges: the word itself inside a red ring, struck through — the
   prohibition sign people already know, with the thing prohibited spelled out
   instead of drawn. Real text, not an SVG glyph: it scales with the browser's
   font settings, it can be read by a screen reader (see the aria-label, which
   carries the "No" the picture conveys visually), and no icon has to be
   invented for an idea like "sketchy meetups".

   The bar is exactly the circle's height and rotated 45deg, so its ends land on
   the ring rather than short of it or poking past. */
.cfpOf .wuNo {
  flex: 0 0 auto; position: relative;
  width: 72px; height: 72px; border-radius: 50%;
  border: 3px solid #cf4b3c; padding: 0;
  display: grid; place-items: center; text-align: center;
  font: 800 13.5px/1.02 'DM Sans', sans-serif; letter-spacing: -.01em;
  text-transform: uppercase; color: #4a5864;
  /* The self-hosted DM Sans is a variable font declared 400-700, so weight 800
     is clamped — there is no heavier cut to ask for. Stroking the glyphs in
     their own colour is what actually thickens them. Kept small: past ~0.4px
     the counters in small caps start closing up. */
  -webkit-text-stroke: 0.35px currentColor;
  /* A pressed stamp rather than a flat outline: a white face, a coloured drop
     shadow so the ring lifts off the cream page, and a trace of shade inside the
     bottom edge to round it — enough to give depth, not enough to tint the face
     grey. The 4-degree tilt is what makes it read as something stamped on rather
     than a UI control. */
  background: #fff;
  box-shadow:
    0 10px 16px -8px rgba(207, 75, 60, .45),
    0 2px 3px rgba(6, 17, 31, .10),
    inset 0 1px 0 #fff,
    inset 0 -5px 9px -8px rgba(6, 17, 31, .14);
  transform: rotate(-4deg);
}
/* The label sits ABOVE the strike bar, with a white halo around the glyphs, so
   the words stay readable where the bar crosses them — the bar is there to say
   "no", not to redact the word it applies to. <i> rather than a span purely to
   stay clear of the .whyUs span rules; it carries no meaning (the badge's
   aria-label does), so its default italic is simply turned off. */
.cfpOf .wuNo i {
  position: relative; z-index: 1; font-style: normal;
  text-shadow: 0 0 3px #fff, 0 0 2px #fff, 0 1px 0 rgba(255, 255, 255, .95);
}

/* The strike bar, lifted off the face by its own shadow so it sits ON the badge
   rather than in it. Exactly the circle's height, rotated 45deg, so the ends
   land on the ring. */
.cfpOf .wuNo:after {
  content: ""; position: absolute; left: 50%; top: -3px; bottom: -3px; width: 4px;
  border-radius: 3px; transform: translateX(-50%) rotate(-45deg);
  background: linear-gradient(#e0594a, #c2412f);
  box-shadow: 0 1px 2px rgba(6, 17, 31, .28), inset 1px 0 0 rgba(255, 255, 255, .35);
}

.cfpOf .whyUs b { display: block; font: 700 17px 'Space Grotesk', sans-serif; color: var(--ink); letter-spacing: -.01em; margin-bottom: 3px; }
.cfpOf .whyUs span:not(.wuNo):not(.wuAmt) { display: block; font-size: 13px; line-height: 1.5; color: var(--muted); }

/* Inside the wizard the whole pane has to fit the fixed body height. */
.cfpOf .wizBody .whyUs { margin-top: 12px; }
.cfpOf .wizBody .whyUs li { padding: 9px 0; gap: 11px; }
.cfpOf .wizBody .wuNo { width: 66px; height: 66px; padding: 0; font-size: 12.5px; }
.cfpOf .wizBody .whyUs b { font-size: 16px; }
.cfpOf .wizBody .whyUs span:not(.wuNo):not(.wuAmt) { font-size: 12.5px; line-height: 1.45; }

/* The offer amount written into the first retention row by declineOffer(). */
.cfpOf .wuAmt {
  display: inline; color: #4d8b19; font-weight: 800;
  /* em, not px: the title is 17px on the page and 16px inside the wizard, and
     the amount should outweigh whichever it sits in. */
  font-size: 1.24em; letter-spacing: -.01em;
}

/* --- SMS consent prompt ---------------------------------------------------
   Sits ABOVE the wizard modal, which is z-index 100. It is also the one modal
   with no ✕: the two buttons are the only exits, so no stray click can be read
   as an answer in either direction. Esc counts as "No, thank you". */
.cfpOf .smsAskModal { z-index: 120; }
.cfpOf .smsAskModal .cfpModalCard { max-width: 430px; padding: 30px 26px 24px; }
.cfpOf .smsAskModal h2 { font-size: 20px; line-height: 1.35; }
.cfpOf .linkBtn { border: 0; background: none; padding: 4px 6px; font: inherit; font-size: 14px;
                  color: #6a7686; text-decoration: underline; cursor: pointer; }
.cfpOf .linkBtn:hover { color: var(--ink); }

/* --- Microsoft Store alternative (step 2a) --------------------------------
   Deliberately quieter than the primary Download button, and NOT a second
   equal-weight CTA. Two buttons of the same size at the one moment the seller
   is already nervous is how you get a stall rather than a choice: the download
   stays the default, and this reads as a way out for anyone the Windows
   warning would otherwise stop.

   Hidden entirely when CFPO_STORE_URL is '' — the markup is not rendered at
   all, so there is no empty-state to style. */
.cfpOf .storeAlt { margin: 2px 0 14px; text-align: center; }
.cfpOf .storeBtn {
  display: inline-flex; flex-direction: column; align-items: center; gap: 2px;
  width: 100%; padding: 11px 16px; cursor: pointer;
  border: 1px solid #cfd8cb; border-radius: 12px; background: #f6f9f3;
  font: inherit; color: var(--ink); text-align: center;
  transition: border-color .15s ease, background .15s ease;
}
.cfpOf .storeBtn:hover { border-color: #9fb394; background: #eef4e8; }
.cfpOf .storeBtnTop { font-weight: 700; font-size: 14.5px; }
/* The reason to pick it, said plainly. This is the whole value of the path. */
.cfpOf .storeBtnSub { font-size: 12.5px; color: #4d8b19; font-weight: 600; }
.cfpOf .steps[hidden] { display: none; }
