@font-face {
  font-family: "Charles Modern";
  src: url("../assets/fonts/CharlesModern-500.woff2") format("woff2");
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Charles Modern";
  src: url("../assets/fonts/CharlesModern-700.woff2") format("woff2");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

:root {
  --sky: #66D4FF;
  --blue: #009DDB;
  --cta: #459AD5;
  /* pill blue, sampled off the client frames */
  --chev: #55AADC;
  /* answer chevron */
  --pick: #91CCEA;
  /* answer pressed state */
  --hair: #A6A6A6;
  /* answer outline */
  --slate: #233441;
  --navy: #042858;
  --the: #6B4E9E;
  /* "THE" above the playstyle name, off the Outro export */
  --ink: #000000;
  --card: #FFFFFF;
  --paper: #FFFFFF;
  /* the exports' own ground */
  --band: #000000;
  /* desktop letterbox surround - see .cs-wrap below */

  --s: min(100vw, 56.25vh);
  --u: calc(var(--s) / 1080);

  /* Type scale, in design units. These are the ladder's top rung; js/flow.js
     steps them down per question until the headline and the four pills fit
     between the progress dots and the Schwab logo. See FIT in flow.js. */
  --qsize: 76;
  --asize: 44;
  --agap: 70;

  --font: "Charles Modern", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}

* {
  box-sizing: border-box;
}

html,
body {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  overflow: hidden;
  background: transparent;
}

/* ---------------------------------------------------------------- stage --*/

/* The letterbox layer, and the only one that can carry its colour.

   Which colour is right depends on WHERE the letterbox falls, and --s decides
   that. Below 9:16 - a normal phone, taller than the design - --s resolves to
   100vw, the stage is full width, and because it is bottom anchored the only
   leftover band sits ABOVE it. Against six white-to-the-edge exports a white
   band there is invisible, so portrait stays --paper.

   From 9:16 and wider - desktop, tablet, any landscape - --s resolves to
   56.25vh instead, the stage is exactly 100vh tall and the leftover moves to
   the two SIDES. There white would let the phone-shaped creative dissolve
   into the page, so those bands go back to black and give it a visible edge.
   The breakpoint is the same comparison --s already makes: min-aspect-ratio
   9/16 is exactly "56.25vh is the smaller of the two". */
.cs-wrap {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
  background-color: var(--paper);
  font-family: var(--font);
  -webkit-font-smoothing: antialiased;
}

@media (min-aspect-ratio: 9/16) {
  .cs-wrap {
    background-color: var(--band);
  }
}

/* The six frame images and the overlay share ONE box or they drift apart.

   Bottom anchored, not centred: it keeps the tap targets a fixed distance
   from the bottom of the screen on every device instead of moving ~84px
   between a 667px SE and a 932px Pro Max. */
.cs-bg,
.cs-stage {
  position: absolute;
  width: var(--s);
  height: calc(var(--u) * 1920);
  left: 50%;
  right: auto;
  top: auto;
  bottom: 0;
  transform: translateX(-50%);
  overflow: hidden;
}

.cs-bg {
  object-fit: fill;
  /* the export IS 9:16, so fill == contain here */
  user-select: none;
  -webkit-user-drag: none;
  pointer-events: none;
}

/* Taps belong to the pills only; everything else falls through. */
.cs-stage {
  pointer-events: none;
}

.cs-frame {
  position: relative;
  width: var(--s);
  height: calc(var(--u) * 1920);
  overflow: hidden;
  text-align: center;
}

/* ---------------------------------------------------------- step switch --*/

/* One attribute drives frame art, overlay copy and the pill stack position.

   On Cavai this was five separate css_N operators, each appending its own
   <style> to head, and they ACCUMULATED - so every hide rule had to tie the
   previous step's show rule on specificity or frames stacked up on screen.
   Owning the DOM means one attribute can do it and that trap cannot occur. */

.cs-bg,
.cs-frame {
  display: none;
}

[data-step="intro"] .cs-bg[data-bg="intro"],
[data-step="intro"] .cs-frame[data-frame="intro"],
[data-step="q1"] .cs-bg[data-bg="q1"],
[data-step="q1"] .cs-frame[data-frame="q1"],
[data-step="q2"] .cs-bg[data-bg="q2"],
[data-step="q2"] .cs-frame[data-frame="q2"],
[data-step="q3"] .cs-bg[data-bg="q3"],
[data-step="q3"] .cs-frame[data-frame="q3"],
[data-step="q4"] .cs-bg[data-bg="q4"],
[data-step="q4"] .cs-frame[data-frame="q4"],
[data-step="result"] .cs-frame[data-frame="result"] {
  display: block;
}


.cs-q-h1 {
  position: absolute;
  left: calc(var(--u) * 170);
  right: calc(var(--u) * 170);
  top: calc(var(--u) * 348);
  margin: 0;
  text-align: center;
  font-weight: 700;
  font-size: calc(var(--u) * var(--qsize));
  line-height: 1.27;
  letter-spacing: calc(var(--u) * -1);
  color: var(--ink);
}

/* ==========================================================================
   Choice stack
   ==========================================================================*/

.cs-choices {
  position: absolute;
  left: 0;
  right: 0;
  top: calc(var(--u) * 757);
  display: flex;
  flex-direction: column;
  align-items: center;
  flex-wrap: nowrap;
  gap: calc(var(--u) * var(--agap));
  padding: 0 calc(var(--u) * 107);
  margin: 0;
}

/* The intro and result stacks are single CTAs, and the art puts them lower.
   1458 - the baked intro subhead ends at 1302 and the 155-tall pill runs
   1458-1613. 1448 - on the Outro the baked body copy ends at 1235 and the
   baked Schwab logo starts at 1687, so 1448-1603 is optically centred. */
[data-step="intro"] .cs-choices {
  top: calc(var(--u) * 1458);
}

[data-step="result"] .cs-choices {
  top: calc(var(--u) * 1448);
}

[data-step="q4"] .cs-q-h1 {
  left: calc(var(--u) * 120) !important;
  right: calc(var(--u) * 120) !important;
  top: calc(var(--u) * 330) !important;
}

[data-step="q1"] .cs-choices {
  top: calc(var(--u) * 700) !important;
}

[data-step="q2"] .cs-choices {
  top: calc(var(--u) * 600) !important;
}

[data-step="q3"] .cs-choices {
  top: calc(var(--u) * 700) !important;
}

/* ---- the answer pill, the default look for every choice ----------------- */
/* 866 wide x 160 tall between x=105 and x=971, fully rounded: at mid height
   the client frame's card is at full width and it curves the whole way to
   both ends, so the radius is half the height, not a soft corner. */
.cs-pill {
  position: relative;
  width: 100%;
  min-height: calc(var(--u) * 160);
  margin: 0;
  padding: calc(var(--u) * 24) calc(var(--u) * 130) calc(var(--u) * 24) calc(var(--u) * 55);
  display: flex;
  align-items: center;
  justify-content: flex-start;
  text-align: left;
  background: var(--card);
  border: calc(var(--u) * 3) solid var(--hair);
  border-radius: calc(var(--u) * 80);
  color: var(--ink);
  font-family: var(--font);
  font-weight: 500;
  font-size: calc(var(--u) * var(--asize));
  line-height: 1.24;
  text-decoration: none;
  -webkit-appearance: none;
  appearance: none;
  cursor: pointer;
  transition: background-color .12s ease-out;
  pointer-events: auto;
  -webkit-tap-highlight-color: transparent;
}

/* pressed state - the tint the client frames show on the picked answer */
.cs-pill:active,
.cs-pill.is-picked {
  background: var(--pick);
  border-color: var(--pick);
}

/* chevron, drawn rather than shipped so CSS can tint it */
.cs-pill::after {
  content: "";
  position: absolute;
  right: calc(var(--u) * 57);
  top: 50%;
  width: calc(var(--u) * 20);
  height: calc(var(--u) * 20);
  border-right: calc(var(--u) * 6) solid var(--chev);
  border-top: calc(var(--u) * 6) solid var(--chev);
  transform: translateY(-50%) rotate(45deg);
}

/* ---- CTA pill: same component, different job --------------------------- */
/* Used by the intro ("Find your type") and the result ("Visit Schwab.com"). */
.cs-cta {
  width: calc(var(--u) * 596);
  min-height: calc(var(--u) * 155);
  padding: 0 calc(var(--u) * 40);
  justify-content: center;
  text-align: center;
  background: var(--cta);
  border: 0;
  color: #fff;
  font-weight: 700;
  font-size: calc(var(--u) * 50);
  border-radius: calc(var(--u) * 78);
}

.cs-cta:active,
.cs-cta.is-picked {
  background: var(--cta);
  border-color: transparent;
}

.cs-cta::after {
  content: none;
}

/* ---- accessibility ------------------------------------------------------ */

.cs-pill:focus-visible {
  outline: calc(var(--u) * 6) solid var(--blue);
  outline-offset: calc(var(--u) * 4);
}

@media (prefers-reduced-motion: reduce) {
  .cs-pill {
    transition: none;
  }
}

/* ==========================================================================
   Result frame - drawn, not baked
   --------------------------------------------------------------------------
   g6-result.png baked ONE outcome: the tick, "Quiz Complete!", "Your Money
   Momentum Type", "THE Goal Getter", the divider and the body copy were all
   in the artwork, so every user saw The Goal Getter whatever they answered.
   Four playstyles need four results, and re-exporting four frames per creative
   is twelve exports, so the frame is drawn here instead and js/flow.js writes
   #cs-type and #cs-body from the resolved bucket.

   Every number below is measured off that export at 1080 x 1920, so the drawn
   frame lands where the approved artwork put it:

     tick        128 square, centred, top 118
     Quiz Complete!            cap line 302   42 / 700 / slate
     Your Money Momentum Type  cap line 472   52 / 700 / black
     THE                       cap line 645   50 / 700 / purple
     the type name             cap line 722  134 / 700 / gradient
     divider                   928, two 160 lines either side of a 20 dot
     body                      cap line 1005  50 / 500 / slate, 690 column
     logo                      144 square at x 468, y 1687

   The frame paints its own ground: with no image behind it, the black desktop
   letterbox on .cs-wrap would otherwise show through.
   ==========================================================================*/

.cs-frame[data-frame="result"] {
  background: var(--paper);
}

.cs-tick {
  position: absolute;
  left: 50%;
  top: calc(var(--u) * 118);
  width: calc(var(--u) * 128);
  height: calc(var(--u) * 128);
  transform: translateX(-50%);
}

.cs-done,
.cs-kicker,
.cs-the,
.cs-type,
.cs-body {
  position: absolute;
  left: 0;
  right: 0;
  margin: 0;
  text-align: center;
}

.cs-done {
  top: calc(var(--u) * 285);
  font-size: calc(var(--u) * 42);
  line-height: 1.2;
  font-weight: 700;
  color: var(--slate);
}

.cs-kicker {
  top: calc(var(--u) * 452);
  font-size: calc(var(--u) * 52);
  line-height: 1.2;
  font-weight: 700;
  color: var(--ink);
}

.cs-the {
  top: calc(var(--u) * 625);
  font-size: calc(var(--u) * 50);
  line-height: 1.2;
  font-weight: 700;
  letter-spacing: calc(var(--u) * 2);
  color: var(--the);
}

/* The type name. The export runs a pink -> purple -> indigo -> cyan ramp
   across the word, the same ramp as the "Booyah!" lockup on the intro, so it
   is a clipped gradient rather than a flat colour.

   The name lives in an inline-block span inside this block, and BOTH the
   gradient and the measuring happen on the span, for the same reason: the
   block is left:0/right:0, so it is 1080 wide whatever the name is. Painting
   the ramp on the block would make a short name sample only the middle of it
   - "Know It All" would come out all-indigo - and measuring the block would
   report 1080 for every name, so js/flow.js fitType() could never see one
   overflow. On the span, the ramp spans the word exactly as the export does
   and the measurement is the real text width.

   Sizing lives on the block so fitType() has one place to set it. */
.cs-type {
  top: calc(var(--u) * 688);
  font-size: calc(var(--u) * 134);
  line-height: 1.2;
  font-weight: 700;
  letter-spacing: calc(var(--u) * -3);
  white-space: nowrap;
}

.cs-type>span {
  display: inline-block;
  color: #2E5CA6;
}

/* -webkit-text-fill-color:transparent is only set inside @supports. On its own
   it would erase the text anywhere background-clip:text is unsupported, which
   is a blank result frame - the one screen that must never be empty. Outside
   the query the name renders in flat indigo, which is legible and on-brand. */
@supports ((-webkit-background-clip:text) or (background-clip:text)) {
  .cs-type>span {
    background-image: linear-gradient(95deg,
        #C9498E 0%, #A8438F 22%, #6E4198 42%, #2F5BA6 62%, #0C7FC4 80%, #00A0DF 100%);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    color: transparent;
  }
}

.cs-rule {
  position: absolute;
  left: 0;
  right: 0;
  top: calc(var(--u) * 921);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: calc(var(--u) * 31);
}

.cs-rule-line {
  display: block;
  width: calc(var(--u) * 160);
  height: calc(var(--u) * 3);
  background: var(--slate);
}

.cs-rule-dot {
  display: block;
  width: calc(var(--u) * 20);
  height: calc(var(--u) * 20);
  border-radius: 50%;
  background: var(--blue);
}

.cs-body {
  top: calc(var(--u) * 991);
  padding: 0 calc(var(--u) * 195);
  font-size: calc(var(--u) * 50);
  line-height: 1.24;
  font-weight: 500;
  color: var(--slate);
}

/* The one piece of the result frame that is still artwork. Cropped out of the
   supplied CS-logo.svg by viewBox, so it is the real mark rather than a trace,
   and it sits exactly where the baked frames put it. */
.cs-logo {
  position: absolute;
  left: 50%;
  top: calc(var(--u) * 1687);
  width: calc(var(--u) * 144);
  height: calc(var(--u) * 144);
  transform: translateX(-50%);
}