/* ── TraderBuddy — the landing page ──────────────────────────────────────────
   The front door for the iOS app, and now the whole of the public site.

   The trader-personality quiz that used to live at the site root — its markup,
   its scripts, its stylesheet, its mentor and prop-firm artwork — has been
   removed from the repo rather than unlinked, because unlinked is not the same
   as gone: a static host serves every file it is given, so an orphaned page
   stays one guessed URL away. It is recoverable from git history if it is ever
   wanted back.

   The tokens below are the same ones app/styles.css carries, which are in turn
   lifted from the app's src/theme.css — so this page, the app's privacy, terms
   and support pages, and the app itself are one product rather than three. They
   are copied rather than imported on purpose: app/styles.css is the stylesheet
   for three documents Apple reads during review, and it is not worth coupling
   those to a marketing page. Change a token in one, change it in the other.

   Everything below the tokens follows DESIGN_SYSTEM.md in the app repo. The two
   rules that shape most of this page:

     · the island is the app's only panel — a pillar, a quote, a fact box are
       all the same object at different sizes;
     · green means live and pressable, so a green button is NEVER shown dimmed.
       An action that isn't ready yet is the island instead — same size, same
       place, quiet label — and turns green the moment it works. That is why the
       primary call to action on this page is grey (see .btn-soon). */

:root {
  --bg:        #0b0b0d;
  --bg-grad:   radial-gradient(130% 46% at 50% 0%, #15161a 0%, #0b0b0d 62%);
  --accent:    #04c198;
  --accent-2:  #08d9ae;
  --accent-rgb: 4, 193, 152;
  --accent-on: #04211a;
  --card:      linear-gradient(160deg, rgba(255,255,255,.055) 0%, rgba(255,255,255,.028) 55%, rgba(255,255,255,.018) 100%);
  --card-border: 1px solid rgba(255,255,255,.09);
  --card-inset:  inset 0 1px 0 rgba(255,255,255,.07);
  --hairline:  rgba(255,255,255,.08);
  --t1:        #ffffff;
  --t2:        rgba(255,255,255,.66);
  --t3:        rgba(255,255,255,.42);
  --t4:        rgba(255,255,255,.3);
  --font-display: 'Space Grotesk', system-ui, sans-serif;
  --font-body:    'Instrument Sans', system-ui, sans-serif;
  --font-mono:    'JetBrains Mono', ui-monospace, monospace;

  --gutter: 22px;
  --col: 1120px;
}

* { margin: 0; padding: 0; box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  background: var(--bg);
  background-image: var(--bg-grad);
  background-repeat: no-repeat;
  background-attachment: fixed;
  color: var(--t1);
  font-family: var(--font-body);
  font-size: 17px;
  font-weight: 500;
  line-height: 1.62;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

img { max-width: 100%; height: auto; display: block; }
a { color: inherit; text-decoration: none; }

.wrap { max-width: var(--col); margin: 0 auto; padding: 0 var(--gutter); }

/* Numbers are always mono — that is what makes a figure read as a measurement
   rather than as a word. */
.mono { font-family: var(--font-mono); letter-spacing: -.02em; }

/* Uppercase labels: bold, tracked, and the quietest thing in their block. */
.eyebrow {
  font-size: 11.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .13em;
  color: var(--t3);
}

/* ── the masthead ─────────────────────────────────────────────────────────── */

.nav {
  position: sticky;
  top: 0;
  z-index: 50;
  background: rgba(11,11,13,.72);
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
  border-bottom: 1px solid var(--hairline);
}
.nav .wrap {
  display: flex;
  align-items: center;
  gap: 26px;
  height: 66px;
}
.nav .brand { display: flex; align-items: center; gap: 10px; margin-right: auto; }
.nav .brand img { height: 30px; width: auto; object-fit: contain; }
.nav .brand span {
  font-family: var(--font-display);
  font-size: 17px;
  font-weight: 700;
  letter-spacing: -.01em;
}
.nav .links { display: flex; gap: 26px; }
.nav .links a {
  font-size: 14.5px;
  font-weight: 600;
  color: var(--t3);
  transition: color .18s ease;
}
.nav .links a:hover { color: var(--t1); }
.nav .pill {
  font-size: 13.5px;
  font-weight: 700;
  color: var(--t2);
  background: var(--card);
  border: var(--card-border);
  box-shadow: var(--card-inset);
  border-radius: 999px;
  padding: 8px 16px;
  white-space: nowrap;
}

@media (max-width: 760px) {
  .nav .links { display: none; }
  .nav .wrap { height: 58px; }
}

/* ── buttons ──────────────────────────────────────────────────────────────── */

/* The green call to action — the one glowing object in its section. Radial fill
   lit from the top-left, near-black green text, an 18px radius so it belongs to
   the same family as the islands around it, and two shadows: a tight drop that
   seats it and a wide bloom that makes it glow. */
.btn-live {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  font-family: var(--font-body);
  font-size: 16px;
  font-weight: 700;
  color: var(--accent-on);
  background: radial-gradient(120% 140% at 22% 8%, var(--accent-2) 0%, var(--accent) 62%);
  border-radius: 18px;
  padding: 15px 30px;
  box-shadow:
    inset 0 1.5px 0 rgba(255,255,255,.45),
    0 6px 18px rgba(0,0,0,.45),
    0 0 60px rgba(var(--accent-rgb),.34);
  transition: transform .18s ease, box-shadow .18s ease;
}
.btn-live:hover { transform: translateY(-1px); box-shadow: inset 0 1.5px 0 rgba(255,255,255,.45), 0 8px 22px rgba(0,0,0,.5), 0 0 74px rgba(var(--accent-rgb),.46); }
.btn-live:focus-visible { outline: 2px solid var(--accent-2); outline-offset: 4px; }

/* Not yet available. The island, at the button's size and in the button's
   place, with a quiet label — never a dimmed green button.
   WHEN THE APP STORE LISTING EXISTS: wrap this in an <a href="…"> and swap the
   class to btn-live. Nothing else on the page has to move. */
.btn-soon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  font-size: 16px;
  font-weight: 700;
  color: var(--t2);
  background: var(--card);
  border: var(--card-border);
  box-shadow: var(--card-inset);
  border-radius: 18px;
  padding: 15px 30px;
  cursor: default;
}
.btn-soon .dot {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 6px rgba(var(--accent-rgb),.9);
  flex-shrink: 0;
}

.actions {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
}

/* ── the hero ─────────────────────────────────────────────────────────────── */

.hero {
  position: relative;
  text-align: center;
  padding: 74px 0 0;
  overflow: hidden;
}

/* The light the orb sits in. Full-bleed and placed in screen percentages rather
   than hung off the orb's box, because the halo has to be centred on where the
   orb actually is — the app's own front door learned this the hard way and the
   note in screens/Welcome.jsx says so. */
.hero::before {
  content: '';
  position: absolute;
  inset: -10% -20% auto;
  height: 760px;
  pointer-events: none;
  background:
    radial-gradient(52% 40% at 50% 26%, rgba(var(--accent-rgb),.20) 0%, rgba(var(--accent-rgb),.11) 38%, rgba(var(--accent-rgb),.04) 66%, transparent 86%),
    radial-gradient(26% 16% at 6% 24%, rgba(204,188,242,.16) 0%, transparent 74%),
    radial-gradient(26% 16% at 94% 22%, rgba(247,189,216,.14) 0%, transparent 74%);
}
.hero > * { position: relative; }

.hero h1 {
  font-family: var(--font-display);
  font-size: clamp(36px, 5.4vw, 62px);
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: -.03em;
  margin: 30px auto 0;
  max-width: 22ch;
}
/* The one place in the app where the accent lands on a word rather than a
   number or a control, kept here for the same reason: this half of the headline
   is the promise the product actually keeps. */
.hero h1 .said {
  display: block;
  color: var(--accent);
}

.lede {
  font-size: clamp(17px, 2vw, 20px);
  color: var(--t2);
  line-height: 1.5;
  max-width: 46ch;
  margin: 18px auto 0;
  text-wrap: balance;
}

.hero .actions { margin-top: 34px; }

/* ── the orb ──────────────────────────────────────────────────────────────
   Lifted from the app's theme.css, where it is the front door's only artwork.
   Every colour is derived from the accent, so the whole sphere follows whatever
   the accent is set to. It is static: the highlights are directional and they
   all agree on one light source, so spinning the body slides them out of
   register and it stops reading as an object. */

.tb-front-orb {
  --orb-s: min(132px, 30vw);
  --orb-deep:  color-mix(in srgb, var(--accent) 9%, #000000);
  --orb-mid:   color-mix(in srgb, var(--accent) 19%, #000000);
  --orb-body:  color-mix(in srgb, var(--accent) 54%, #000000);
  --orb-glint: color-mix(in srgb, var(--accent-2) 40%, #ffffff);
  --orb-sheen: color-mix(in srgb, var(--accent-2) 18%, #ffffff);
  position: relative;
  margin: 0 auto;
  width: var(--orb-s);
  height: var(--orb-s);
  border-radius: 50%;
  background: radial-gradient(circle at 50% 53%,
    color-mix(in srgb, var(--orb-deep) 98%, transparent) 0%,
    color-mix(in srgb, var(--orb-mid) 95%, transparent) 26%,
    color-mix(in srgb, var(--orb-body) 66%, transparent) 48%,
    color-mix(in srgb, var(--accent) 92%, transparent) 70%,
    var(--accent-2) 87%,
    color-mix(in srgb, var(--orb-sheen) 95%, transparent) 97%,
    #ffffff 100%);
  box-shadow:
    0 0 calc(var(--orb-s) * 0.10) rgba(255,255,255,.28),
    0 0 calc(var(--orb-s) * 0.32) rgba(var(--accent-rgb),.60),
    0 0 calc(var(--orb-s) * 0.78) rgba(var(--accent-rgb),.28);
}
.tb-front-orb > span { position: absolute; border-radius: 50%; pointer-events: none; }
.tb-front-orb__swirl {
  inset: 4%;
  background: conic-gradient(from 208deg,
    rgba(255,255,255,0) 0deg,
    rgba(255,255,255,.17) 40deg,
    rgba(255,255,255,0) 98deg,
    rgba(var(--accent-rgb),.30) 172deg,
    rgba(255,255,255,.11) 234deg,
    rgba(255,255,255,0) 302deg,
    rgba(255,255,255,0) 360deg);
  filter: blur(calc(var(--orb-s) * 0.035));
  -webkit-mask-image: radial-gradient(circle, transparent 30%, #000 58%);
  mask-image: radial-gradient(circle, transparent 30%, #000 58%);
}
.tb-front-orb__lip {
  inset: 13% 21% 25% 11%;
  background: radial-gradient(circle at 46% 42%,
    transparent 52%,
    color-mix(in srgb, var(--accent) 30%, transparent) 74%,
    color-mix(in srgb, var(--orb-glint) 55%, transparent) 90%,
    color-mix(in srgb, var(--orb-sheen) 20%, transparent) 97%,
    transparent 100%);
  filter: blur(calc(var(--orb-s) * 0.016));
}
.tb-front-orb__rim {
  inset: 0;
  border: max(1px, calc(var(--orb-s) * 0.007)) solid color-mix(in srgb, var(--orb-sheen) 72%, transparent);
  box-shadow:
    0 0 calc(var(--orb-s) * 0.05) color-mix(in srgb, var(--orb-sheen) 40%, transparent),
    0 0 calc(var(--orb-s) * 0.15) color-mix(in srgb, var(--accent) 68%, transparent),
    inset 0 0 calc(var(--orb-s) * 0.10) color-mix(in srgb, var(--orb-glint) 38%, transparent);
  -webkit-mask-image: linear-gradient(142deg, #000 0%, #000 45%, rgba(0,0,0,.84) 76%, rgba(0,0,0,.7) 100%);
  mask-image: linear-gradient(142deg, #000 0%, #000 45%, rgba(0,0,0,.84) 76%, rgba(0,0,0,.7) 100%);
}
.tb-front-orb__spec {
  left: 19%; top: 11%;
  width: 27%; height: 17%;
  background: radial-gradient(circle, rgba(255,255,255,.92) 0%, rgba(255,255,255,.26) 42%, transparent 72%);
  filter: blur(calc(var(--orb-s) * 0.012));
  transform: rotate(-24deg);
}

/* ── the phone ────────────────────────────────────────────────────────────
   A frame rather than a photograph of a handset: the screenshot inside it is
   the app at 390pt, and a drawn bezel keeps the page's own materials — the
   hairline, the inset top edge — instead of importing somebody's product shot. */

.phone {
  --w: 300px;
  width: var(--w);
  padding: 9px;
  margin: 0 auto;
  background: #08080a;
  border: 1px solid rgba(255,255,255,.13);
  border-radius: 44px;
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.1),
    0 30px 70px rgba(0,0,0,.7),
    0 0 90px rgba(var(--accent-rgb),.12);
}
.phone img { border-radius: 36px; width: 100%; }

/* The hero's phone was cropped by the fold, on the theory that a half-shown
   screen reads as the app coming up out of the page. It doesn't — it reads as a
   picture that didn't fit, and the first screenshot a visitor sees is the one
   that should be whole. It sits complete now, with room under it. */
.hero .phone {
  --w: clamp(250px, 34vw, 330px);
  margin-top: 60px;
  margin-bottom: 24px;
}

/* ── the pillars ──────────────────────────────────────────────────────────── */

section { padding: 116px 0; }
section.tight { padding-top: 0; }

.head { max-width: 30ch; margin-bottom: 40px; }
.head.mid { margin-left: auto; margin-right: auto; text-align: center; max-width: 62ch; }
.head.mid h2 { max-width: 18ch; margin-left: auto; margin-right: auto; }
.head.mid p { max-width: 56ch; margin-left: auto; margin-right: auto; }
.head h2 {
  font-family: var(--font-display);
  font-size: clamp(28px, 3.6vw, 42px);
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -.028em;
  margin-top: 12px;
  text-wrap: balance;
}
.head p { color: var(--t2); margin-top: 14px; font-size: 17.5px; }

.pillars {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 14px;
}
.pillar {
  background: var(--card);
  border: var(--card-border);
  box-shadow: var(--card-inset);
  border-radius: 20px;
  padding: 22px 20px 24px;
}
.pillar svg { display: block; margin-bottom: 16px; }
.pillar b {
  display: block;
  font-size: 17px;
  font-weight: 700;
  margin-bottom: 6px;
}
.pillar span { color: var(--t2); font-size: 15.5px; line-height: 1.5; }

@media (max-width: 900px) { .pillars { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 520px) { .pillars { grid-template-columns: 1fr; } }

/* ── the before → after rows ──────────────────────────────────────────────── */

.row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  align-items: center;
  gap: clamp(30px, 6vw, 90px);
  padding: 66px 0;
}
.row + .row { border-top: 1px solid var(--hairline); }
.row .art { display: flex; justify-content: center; }
.row .phone { --w: clamp(240px, 26vw, 296px); }
.row.flip .copy { order: 2; }
.row.flip .art { order: 1; }

/* The turn: what you carry now, and what you carry instead. The arrow is the
   whole idea, so it gets the accent and nothing either side of it does. */
.turn { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; }
.turn i { font-style: normal; color: var(--accent); font-weight: 700; }

.row h3 {
  font-family: var(--font-display);
  font-size: clamp(26px, 3.2vw, 38px);
  font-weight: 700;
  line-height: 1.12;
  letter-spacing: -.028em;
  margin: 14px 0 16px;
  text-wrap: balance;
}
.row p { color: var(--t2); font-size: 17.5px; max-width: 44ch; }

@media (max-width: 860px) {
  .row { grid-template-columns: 1fr; gap: 38px; padding: 52px 0; text-align: center; }
  .row.flip .copy { order: 1; }
  .row.flip .art { order: 2; }
  .row p { margin-left: auto; margin-right: auto; }
}

/* ── the eight types ──────────────────────────────────────────────────────── */

/* Four and four. Left to wrap on its own the set broke six-and-two, which reads
   as a mistake rather than as a grid. */
.fan {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 16px;
  max-width: 720px;
  margin: 0 auto;
}
.fan img {
  width: 100%;
  border-radius: 12px;
  box-shadow: 0 14px 34px rgba(0,0,0,.6);
  transition: transform .22s ease;
}
.fan img:hover { transform: translateY(-6px); }
@media (max-width: 560px) { .fan { grid-template-columns: repeat(2, 1fr); max-width: 340px; } }

/* ── what it is not ───────────────────────────────────────────────────────── */

.nots {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 14px;
}
.not {
  background: var(--card);
  border: var(--card-border);
  box-shadow: var(--card-inset);
  border-radius: 20px;
  padding: 24px 22px;
}
.not b { display: block; font-size: 17px; font-weight: 700; margin-bottom: 8px; }
.not span { color: var(--t2); font-size: 15.5px; line-height: 1.55; }
@media (max-width: 780px) { .nots { grid-template-columns: 1fr; } }

/* ── the closing ask ──────────────────────────────────────────────────────── */

.close {
  position: relative;
  text-align: center;
  padding: 130px 0 120px;
  overflow: hidden;
}
.close::before {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(50% 60% at 50% 62%, rgba(var(--accent-rgb),.16) 0%, rgba(var(--accent-rgb),.05) 48%, transparent 78%);
}
.close > * { position: relative; }
.close h2 {
  font-family: var(--font-display);
  font-size: clamp(30px, 4.4vw, 52px);
  font-weight: 700;
  line-height: 1.08;
  letter-spacing: -.03em;
  max-width: 18ch;
  margin: 0 auto;
  text-wrap: balance;
}
.close .actions { margin-top: 34px; }

/* ── footer ───────────────────────────────────────────────────────────────── */

footer {
  border-top: 1px solid var(--hairline);
  padding: 34px 0 60px;
}
footer .wrap {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 20px;
  align-items: center;
  font-size: 14px;
  color: var(--t4);
}
footer a { color: var(--t3); font-weight: 600; }
footer a:hover { color: var(--accent); }
footer a:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 3px; }
footer .sep { color: var(--t4); }
footer .said { margin-left: auto; }
@media (max-width: 620px) { footer .said { margin-left: 0; width: 100%; } }

/* ── motion ───────────────────────────────────────────────────────────────
   Reveals are added BY SCRIPT (see the tail of index.html), never in the markup.
   A page whose content is hidden in CSS and shown by an observer is a blank page
   for anyone whose JavaScript hasn't run — which is exactly what the reference
   page this one is modelled on does, and it is the one thing not copied from it.
   No script, no observer, old browser: the page is simply already there. */

.js-reveal { opacity: 0; transform: translateY(18px); }
.js-reveal.seen {
  opacity: 1;
  transform: none;
  transition: opacity .6s cubic-bezier(.22,.61,.36,1), transform .6s cubic-bezier(.22,.61,.36,1);
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  * { transition: none !important; animation: none !important; }
  .js-reveal { opacity: 1; transform: none; }
}
