/* The two faces the tokens reference. tokens.css names them and deliberately
 * does not declare them, because the handoff's own token file does not either.
 * Without this the whole funnel silently falls back to a serif: the design
 * survives, the typeface does not, and it is the first thing anyone notices.
 */
@font-face {
  font-family: "Amora Rounded";
  src: url("/assets/fonts/open-runde-regular.woff2") format("woff2");
  font-style: normal;
  font-weight: 400 500;
  font-display: swap;
}

@font-face {
  font-family: "Amora Rounded";
  src: url("/assets/fonts/open-runde-semibold.woff2") format("woff2");
  font-style: normal;
  font-weight: 600 900;
  font-display: swap;
}

/* The display face is the ball-terminal serif in the wordmark and the store
 * screenshots. It is a campaign face, used on the landing headline and nowhere
 * inside the funnel proper. */
@font-face {
  font-family: "Fraunces";
  src: url("/assets/fonts/fraunces-variable.woff2") format("woff2");
  font-style: normal;
  font-weight: 300 900;
  font-display: swap;
}

/* Version 2 web funnel: the handoff's templates, implemented.
 *
 * Every number here is read off `Amora Funnel Templates.dc.html`, not chosen.
 * The board is the visual truth and `funnel-spec.md` is the behavioural truth;
 * where they disagree the board wins on appearance. A copy of each template is
 * extracted under .context/artifacts/web-funnel-v2/templates/ so a value can be
 * checked without opening a 300 KB design-tool file.
 *
 * scripts/funnel_template_compare.mjs renders a template beside this
 * implementation at the same size. Run it after changing anything in here; a
 * value that "looks right" is how version 1 drifted off the design one line at
 * a time.
 *
 * Tokens come from tokens.css, which is a copy of the app's own values. Reach
 * for a token before inventing a colour.
 */

/* The page itself. The templates set a font-family on almost nothing, because
 * on the board they inherit it from the document; without this every screen
 * renders in the browser's default serif, which is the first thing anyone
 * notices and the last thing anyone suspects. */
html, body {
  margin: 0;
  min-height: 100%;
  background: linear-gradient(180deg, #FBE9F0, #FAF6F3 46%, #FBF9F7);
  color: var(--text-primary);
  font-family: var(--font-rounded);
  -webkit-font-smoothing: antialiased;
}

/* Three screens are built from blocks with fixed heights, and on a window
   shorter than the designer's phone something on them was simply cut off.
   Each gives back the missing height from the one part that can lose some
   without losing meaning. The numbers beside each are what that screen's
   fixed parts add up to. */
.fv2-screen {
  /* T-17: a back control, two rows of drifting question cards, three answer
     rows, 782px. */
  --fv2-lib-card: clamp(64px, calc(118px + (100dvh - 782px) / 2), 118px);
  /* T-08: two rows of drifting review cards over a headline and button, 701px. */
  --fv2-review-card: clamp(96px, calc(148px + (100dvh - 701px) / 2), 148px);
  /* T-10: the progress dial is the one thing on it with no words in it, so it
     is the first thing that should get smaller. */
  --fv2-dial: clamp(96px, calc(134px + (100dvh - 800px)), 134px);
}

/* Every template's own wrapper. On the board it was a 390x852 device; in a
 * browser the viewport is the device. */
#fv2App > .fv2-screen {
  display: flex;
  width: 100%;
  /* Exactly the viewport, not at least it. On `min-height` the screen simply
     grew when a step had one row too many, so nothing inside was ever asked
     to give way and the last answer went off the bottom edge. */
  height: 100dvh;
  min-height: 100dvh;
  /* Every screen is built to fit, and each one gives ground as the window
     gets shorter. Past the point where it can give no more, scrolling is the
     honest fallback: a cut-off answer is unreachable, a scrolled one is not. */
  overflow-y: auto;
  /* The board hides this rail's scrollbar, and a bar appearing down the side of
     a screen that is nearly the right height reads as a fault. */
  scrollbar-width: none;
  flex-direction: column;
  overflow-x: hidden;
  border: 0;
  border-radius: 0;
  padding-bottom: 0;
  background: none;
}

.fv2-stars { display: inline-flex; align-items: center; gap: 1px; }
.fv2-wordmark { display: inline-block; width: auto; }
.fv2-icon { display: inline-block; }
.fv2-badge {
  display: inline-flex;
  height: 21px;
  align-items: center;
  border-radius: var(--radius-full);
  padding: 0 9px;
  background: var(--amora-pink);
  color: #fff;
  font-size: 11px;
  font-weight: var(--weight-bold);
  letter-spacing: .2px;
  text-transform: uppercase;
}

.fv2-screen {
  position: relative;
  display: flex;
  width: 100%;
  max-width: 430px;
  min-height: 100dvh;
  flex-direction: column;
  margin-inline: auto;
  overflow: hidden;
}

/* The pink wash behind every step. Its size and vertical origin change per
   template; these are T-03's, and a step overrides `--fv2-glow-top` when its
   own template puts it elsewhere. */
.fv2-screen::before {
  position: absolute;
  z-index: 0;
  top: var(--fv2-glow-top, 20%);
  left: 50%;
  width: 720px;
  height: 720px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(233, 30, 99, .06), rgba(233, 30, 99, 0) 68%);
  content: "";
  pointer-events: none;
  transform: translate(-50%, -50%);
}

.fv2-screen > * { position: relative; z-index: 1; }

@media (prefers-reduced-motion: reduce) { .fv2-progress i { transition: none; } }
@media (prefers-reduced-motion: reduce) { .fv2-row { transition: none; } .fv2-row:active { transform: none; } }
@media (prefers-reduced-motion: reduce) { .fv2-cta { transition: none; } .fv2-cta:active { transform: none; } }

.fv2-screen button:focus-visible,
.fv2-screen [role="radio"]:focus-visible,
.fv2-screen [role="checkbox"]:focus-visible,
.fv2-screen a:focus-visible {
  border-radius: inherit;
  outline: 2.5px solid var(--amora-pink);
  outline-offset: 3px;
}

#fv2App h1,
#fv2App h2,
#fv2App [tabindex="-1"] {
  outline: none !important;
}

.fv2-screen [role="button"]:focus-visible { outline: 2.5px solid var(--amora-pink); outline-offset: 3px; }
[data-ground="dark"] button:focus-visible,
[data-ground="dark"] [role="button"]:focus-visible,
[data-ground="dark"] [role="radio"]:focus-visible,
[data-ground="dark"] [role="checkbox"]:focus-visible,
[data-ground="dark"] a:focus-visible { outline-color: #fff; }

.fv2-screen input:focus-visible { outline: 2.5px solid var(--amora-pink); outline-offset: 2px; }

/* ── Short screens ──────────────────────────────────────────────────────── */

/* The board draws one 852px device. A 667px phone with six rows has about
   90px less room than that, so the block that centres comfortably there needs
   its gaps back. Nothing shrinks: the rows keep their 64px, because a row that
   shrinks on a small phone is how a six-answer question started looking like a
   cheaper version of a two-answer one. */
@media (max-height: 700px) {
  .fv2-rows { margin-top: 12px; }
  .fv2-rows[data-count="6"] { gap: 7px; }
  .fv2-readback-slot { height: 72px; }
  .fv2-title { font-size: 26px; }
}

/* ── Motion, ported from the board ─────────────────────────────────────────
 *
 * These keyframes live in the board's own <style> block, not in any template,
 * so porting the templates alone left every animation undefined. That is not
 * merely "no animation": several screens author their start state as faded or
 * offset and rely on the animation to bring them in, so without these the
 * social proof screen renders permanently half transparent and reads as a
 * broken page. Copied verbatim.
 */
@keyframes amora-hero{0%,26%{opacity:1}35%,91%{opacity:0}100%{opacity:1}}
/* The welcome badges: the app's three sets of three, one set at a time, in step
   with the photos. Unlike the photos they never cross-fade into each other, so
   words are never drawn over words; with reduced motion only the first set shows. */
@keyframes fv2-badges{0%,30%{opacity:1}33.3%,97%{opacity:0}100%{opacity:1}}
@keyframes amora-fade{from{opacity:0}to{opacity:1}}
@keyframes amora-reveal{from{opacity:0;transform:translateY(20px) scale(.92)}60%{transform:translateY(-3px) scale(1.01)}to{opacity:1;transform:none}}
@keyframes amora-drop{0%{transform:translateY(-22px) scaleY(1.03)}22%{transform:translateY(0) scaleY(.86)}34%{transform:translateY(-9px) scaleY(1)}48%{transform:translateY(0) scaleY(.94)}58%,100%{transform:translateY(0) scaleY(1)}}
@keyframes amora-lap-q{from{transform:translateX(0)}to{transform:translateX(-810px)}}
@keyframes amora-lap{from{transform:translateX(0)}to{transform:translateX(-1632px)}}
@keyframes amora-meet-l{0%{opacity:0;transform:translateX(-46px) scale(.82)}100%{opacity:1;transform:none}}
@keyframes amora-meet-r{0%{opacity:0;transform:translateX(46px) scale(.82)}100%{opacity:1;transform:none}}
@keyframes amora-pop{0%{opacity:0;transform:scale(.6)}62%{transform:scale(1.12)}100%{opacity:1;transform:scale(1)}}
@keyframes amora-pulse{0%,100%{transform:scale(1)}50%{transform:scale(1.09)}}
@keyframes amora-spin{to{transform:rotate(360deg)}}
@keyframes amora-rise{from{opacity:0;transform:translateY(20px)}to{opacity:1;transform:none}}

@media (prefers-reduced-motion:reduce){*,*::before,*::after{animation-duration:.001ms!important;animation-iteration-count:1!important;transition-duration:.001ms!important}}
@media (max-width:900px){
  .fnl-wrap{padding:44px 18px 80px!important}
  .fnl-h1{font-size:38px!important}
  .fnl-grid{gap:48px 24px!important}
  .fnl-atoms{grid-template-columns:1fr!important}
}

/* Same, for browsers that do not take scrollbar-width. */
#fv2App > .fv2-screen::-webkit-scrollbar, .fnl-rail::-webkit-scrollbar { display: none; }
.fnl-rail { scrollbar-width: none; -ms-overflow-style: none; }

/* T-06 shows a two-state ritual: the question with both partners ticked, then
   the same question with the two answers under it. The board's own note calls
   a single frozen frame the failure this screen was redesigned to avoid, so
   both are stacked in the fixed box and cross-fade on its 3.4s cycle. Under
   the reduced-motion reset above, the first one simply stays. */
[data-fv2-alternate] { animation: fv2-alternate-a 3.4s ease-in-out infinite; }
[data-fv2-alternate="b"] { animation-name: fv2-alternate-b; }
@keyframes fv2-alternate-a { 0%, 41% { opacity: 1 } 56%, 91% { opacity: 0 } 100% { opacity: 1 } }
@keyframes fv2-alternate-b { 0%, 41% { opacity: 0 } 56%, 91% { opacity: 1 } 100% { opacity: 0 } }

/* Press states. The board marks every row and button with `style-active`,
   which is the design tool's own preview attribute: nothing applies it at
   runtime, in the board or here, so every control in this funnel was inert
   under a finger. The templates already carry the transition; this supplies
   the state it transitions to. One rule per value the templates actually use,
   and a test fails if a new value appears without one. */
[style-active="transform:scale(.99)"]:active { transform: scale(.99); }
[style-active="transform:scale(.98)"]:active { transform: scale(.98); }
[style-active="transform:scale(.97)"]:active { transform: scale(.97); }
[style-active="transform:scale(.96)"]:active { transform: scale(.96); }
[style-active="transform:scale(.95)"]:active { transform: scale(.95); }

@media (prefers-reduced-motion: reduce) {
  [style-active]:active { transform: none; }
}

/* A screen with no subtitle shows none, as in the app: the empty line would
   otherwise still push the answers down by its margin. */
[data-fv2-sub]:empty { display: none; }

/* Transcreated copy expands naturally and uses the document's writing direction. */
.fv2-screen h1, .fv2-screen h2 { white-space: pre-line; overflow-wrap: anywhere; }
.fv2-screen [data-fv2-option] { min-height: 64px; height: auto !important; }
.fv2-screen [data-fv2-option] [data-fv2-label] { white-space: normal; }
.fv2-screen [data-fv2-cta] { height: auto !important; min-height: 56px; padding-block: 14px; box-sizing: border-box; overflow-wrap: anywhere; }
/* Translated reviews keep their complete text instead of the English clamp. */
html:not([lang="en"]) .fv2-review-card { height: auto !important; min-height: var(--fv2-review-card, 148px); }
html:not([lang="en"]) .fv2-review-copy { display: block !important; -webkit-line-clamp: unset !important; overflow: visible !important; }
html[dir="rtl"] [data-fv2-back] svg { transform: scaleX(-1) !important; }
html[dir="rtl"] .fv2-screen [role="progressbar"] { direction: rtl; }
html[dir="rtl"] .fv2-screen { letter-spacing: normal; }
html[dir="rtl"] input[type="email"], html[dir="rtl"] input[type="date"],
html[dir="rtl"] #inviteCode { direction: ltr; unicode-bidi: isolate; }

/* At narrow widths (including browser zoom), let answer text take its own
   line and let the screen scroll instead of squeezing or clipping choices. */
@media (max-width: 360px) {
  .fv2-screen > div:has([data-fv2-option]) { flex: 0 0 auto !important; overflow: visible !important; }
  .fv2-screen [data-fv2-option]:has([data-fv2-label]) { flex: 0 0 auto !important; flex-wrap: wrap; gap: 8px !important; max-height: none !important; padding: 12px !important; }
  .fv2-screen [data-fv2-label] { flex-basis: 100%; order: 2; min-width: 0; overflow-wrap: anywhere; }
}
