/* ==========================================================================
   SmartSignals — marketing site
   Loaded after tokens.css. The cockpit has its own stylesheet.
   ========================================================================== */

/* ── Navigation ───────────────────────────────────────────────────────────── */

.nav{
  position:fixed;top:0;left:0;right:0;z-index:120;
  height:var(--nav-h);
  display:flex;align-items:center;gap:26px;
  padding:0 clamp(16px,3vw,40px);
  background:var(--chrome);
  backdrop-filter:blur(18px) saturate(140%);
  border-bottom:1px solid transparent;
  transition:background .3s var(--ease),border-color .3s var(--ease);
}
.nav.scrolled{background:var(--chrome-solid);border-bottom-color:var(--line)}

.nav-logo{
  display:flex;align-items:center;gap:10px;flex:none;
  /* Not the accent: white on the dark theme, near-black on the light one. The
     mark is drawn in currentColor, so this sets both it and the wordmark. */
  color:var(--text);
}
/* 26px, not 22: the candle strokes are thin and diagonal, and four extra
   pixels of height is the only lever that gives them more to be drawn with. */
.nav-logo .logo-mark{height:26px;width:auto;flex:none}
.nav-logo-text{
  /* Was a serif, which carried the logotype on shape alone. A sans has to earn
     it with weight and tracking or it reads as running text. */
  font-family:var(--f-display);font-size:1.14rem;font-weight:600;
  letter-spacing:-.02em;line-height:1;white-space:nowrap;
}
.nav-logo sup{font-size:.5em;opacity:.65}

.nav-links{display:flex;gap:2px;flex:1;justify-content:center;flex-wrap:nowrap}
.nav-links a{
  white-space:nowrap;
  padding:8px 11px;border-radius:6px;
  font-size:.74rem;letter-spacing:.09em;text-transform:uppercase;
  color:var(--muted);font-weight:500;
  transition:color .2s,background .2s;
  position:relative;
}
.nav-links a:hover{color:var(--accent-lt);background:var(--accent-glow)}
.nav-links a.hot{color:var(--cyan)}
.nav-links a.hot::after{
  content:'';position:absolute;top:6px;right:7px;
  width:5px;height:5px;border-radius:50%;background:var(--cyan);
  box-shadow:0 0 8px var(--cyan);
  animation:blink 2s infinite;
}

.nav-right{display:flex;align-items:center;gap:10px;flex:none}

/* Once the hero has scrolled away, the two things it offered follow you up the
   page.
   This has to be a swap, not an addition: the two buttons need 252px and the
   bar had 200px less than that to give — the CTA was being pushed off the right
   edge. So the social marks stand down and the CTA takes its short label. The
   marks are decoration; once you are reading, the actions are the point. */
.nav-jump{display:none}
.nav-jump .btn-demo-play{width:21px;height:21px}

/* 1300 is where it measures, not where it looks about right: at 1240 the bar
   still ran 33px over even with the labels shortened and the links tightened. */
@media (min-width:1300px){
  .nav.past-hero .nav-jump{display:inline-flex;animation:jumpIn .3s var(--ease)}
  .nav.past-hero .social{display:none}
  .nav.past-hero .lbl-long{display:none}
  .nav.past-hero .lbl-short{display:inline}
  /* The links give up their outer padding rather than an item: losing a
     destination to make room for a button would be a bad trade. */
  .nav.past-hero .nav-links a{padding-inline:9px}
}
/* jumpIn lives in tokens.css — the cockpit bar uses it too. */

/* The mobile counterpart of .nav-jump. Same trigger, different home: below 860
   the nav is a logo, a CTA and a burger with nothing to spare, so the actions
   get their own strip under it rather than squeezing in beside them. */
.jump-bar{display:none}

@media (max-width:860px){
  :root.past-hero .jump-bar{
    display:flex;align-items:stretch;gap:7px;
    position:fixed;top:var(--nav-h);left:0;right:0;z-index:110;
    padding:7px 12px;
    background:var(--chrome-solid);
    border-bottom:1px solid var(--line);
    animation:jumpIn .3s var(--ease);
  }
  /* .nav-drawer is fixed to this same strip at z-index 119. */
  :root.menu-open .jump-bar{display:none}

  /* Three equal parts on one line. .share-row carries flex-wrap:wrap of its
     own, which at this width is what dropped the share control onto a second
     row underneath the buttons. */
  .jump-bar .btn,
  .jump-bar .share-row{flex:1 1 0;min-width:0;margin:0}
  .jump-bar .share-row{flex-wrap:nowrap;gap:0}
  .jump-bar .share-nets{width:100%;gap:0}

  /* One set: the share control stops being a 34px icon square and takes the
     same box, type and case as the two buttons beside it. */
  .jump-bar .btn,
  .jump-bar .share-btn{
    height:36px;width:100%;
    justify-content:center;gap:6px;padding:0 6px;
    border-radius:var(--r-sm);
    font-family:var(--f-mono);font-size:.6rem;font-weight:600;
    letter-spacing:.07em;text-transform:uppercase;white-space:nowrap;
  }
  .jump-bar .share-btn{
    border:1px solid var(--line-strong);
    background:var(--accent-glow);color:var(--accent-lt);
  }
  .jump-bar .share-btn svg{width:13px;height:13px;flex:none}
  .jump-bar .share-done{display:none}

  /* share.js sets .has-sheet on the row when it creates the native button, and
     the base rules already hide the four network links under it. Copy goes with
     them, so exactly one control shows either way: the sheet where the API
     exists, Copy where it does not. */
  .jump-bar .share-x,
  .jump-bar .share-telegram,
  .jump-bar .share-whatsapp,
  .jump-bar .share-linkedin{display:none}
  .jump-bar .has-sheet .share-copy{display:none}
}

/* The bar carries a lot: five social marks, a three-way theme control, a CTA
   and a burger. Each drops out at the width where it would start crowding the
   links, and reappears inside the drawer instead. */
.nav .social{display:none}
.nav .theme-switch{display:none}
@media (min-width:1280px){ .nav .social{display:inline-flex} }
@media (min-width:1024px){ .nav .theme-switch{display:inline-flex} }

/* Give the links a little more air once the bar is genuinely wide. */
@media (min-width:1400px){
  .nav-links{gap:4px}
  .nav-links a{padding:8px 14px}
}

.nav-burger{display:none;color:var(--text);padding:8px}
/* Driven by aria-expanded, which the handler already maintains -- the state is
   announced and drawn from one source rather than two that can disagree. */
.nav-burger .icon-close{display:none}
.nav-burger[aria-expanded="true"] .icon-open{display:none}
.nav-burger[aria-expanded="true"] .icon-close{display:block}
.nav-drawer{
  position:fixed;inset:var(--nav-h) 0 auto 0;z-index:119;
  background:var(--chrome-solid);
  border-bottom:1px solid var(--line);
  padding:14px clamp(16px,3vw,40px) 22px;
  display:none;flex-direction:column;gap:2px;
}
.nav-drawer.open{display:flex}
.nav-drawer a{
  padding:12px 6px;font-size:.9rem;color:var(--text-2);
  border-bottom:1px solid var(--hairline);
}
.nav-drawer .btn{margin-top:14px}
.drawer-foot{
  display:flex;align-items:center;justify-content:space-between;
  gap:14px;flex-wrap:wrap;padding-top:14px;
}

/* Share sits with the drawer's own furniture rather than among the links, so it
   takes the same hairline the links use to separate themselves. */
.drawer-share{padding:14px 6px 4px;border-top:1px solid var(--hairline);gap:10px}
.drawer-share .share-lbl{font-size:.8rem;color:var(--text-2)}

/* ── Hero ─────────────────────────────────────────────────────────────────── */

.hero{
  position:relative;overflow:hidden;
  min-height:min(100svh,900px);
  display:grid;
  /* The text column is bounded, not greedy. As minmax(0,1fr) it swallowed every
     spare pixel while .hero-inner stayed capped at 640 -- so the slack piled up
     as a hole between the copy and the phone: measured 201px at 1280, 329 at
     1440 and about 790 at 1920. The device column takes the slack instead and
     centres the phone in it, which reads as a column rather than a gap.
     Its 214px floor is the phone's own minimum, so between 861 and ~950 the
     text gives way rather than the phone being squeezed. */
  grid-template-columns:minmax(0,640px) minmax(214px,1fr);
  align-items:center;gap:clamp(20px,4vw,60px);
  /* No nav-h term: the ticker above now stands between the hero and the
     fixed nav, and carries that offset itself. */
  /* The same content box as every .wrap below it -- min(1240px, 100% - 48px),
     centred -- expressed as padding because .hero is full-bleed for its orbs.
     It had its own fluid padding, so its headline started 31px left of every
     section under it at 1440 and nowhere near them at 1920. */
  padding-block:clamp(30px,4.5vw,56px) clamp(40px,6vw,80px);
  padding-inline:max(24px,(100% - 1240px) / 2);
}

/* Sits behind every in-flow element but above the body background: a negative
   z-index child paints after the parent's background and before its content. */
.site-crt{position:fixed;inset:0;z-index:-1}

.hero-orb-accent{
  position:absolute;z-index:0;pointer-events:none;
  width:min(920px,120%);aspect-ratio:1;
  top:-32%;left:-16%;
  background:radial-gradient(circle,var(--accent-glow),transparent 62%);
}
.hero-orb{
  position:absolute;right:-10%;top:18%;
  width:min(620px,70%);aspect-ratio:1;
  background:radial-gradient(circle,var(--cyan-dim),transparent 60%);
  pointer-events:none;
}

.hero-inner{position:relative;z-index:2;max-width:640px}

.hero-badge{
  display:inline-flex;align-items:center;gap:8px;
  padding:5px 11px;border-radius:6px;margin-bottom:22px;
  border:1px solid var(--green);
  background:var(--green-dim);
  color:var(--green);
  font-family:var(--f-mono);font-size:.6rem;font-weight:600;
  letter-spacing:.14em;text-transform:uppercase;
}

/* The hero used the display serif with an italic gold word. That is an
   editorial register — it reads as a magazine standfirst, and the italic serif
   in particular is a very recognisable house style. Tight sans reads as a
   product company: the claim lands as a specification rather than a headline.
   Section h2s keep the serif, so the page opens with a change of voice instead
   of losing one. */
.hero h1{
  font-family:var(--f-sans);
  font-weight:700;
  font-size:clamp(2.3rem,5.2vw,3.8rem);
  line-height:1.04;
  letter-spacing:-.034em;
  margin-bottom:20px;
}
.hero h1 em{
  /* The same cyan as Live Cockpit in the nav: the accent now points at the one
     thing on the page that is actually live, instead of being a second gold. */
  font-style:normal;
  color:var(--cyan);
}
.hero-sub{
  color:var(--text-2);font-size:clamp(.96rem,1.35vw,1.06rem);
  /* Matches the headline's own width, so the opening reads as one block rather
     than a heading with a narrower note under it. */
  line-height:1.6;max-width:56ch;margin-bottom:26px;
}
.hero-cta{display:flex;gap:12px;flex-wrap:wrap;margin-bottom:30px}

/* A cascade rather than one beat: the ring travels through the three buttons
   instead of all of them flashing together. The delays follow the reading
   order, and that order is not the same in both layouts -- the wide row leads
   with Live cockpit, the phone column leads with Get the app -- so the two
   hero buttons swap theirs below 860. Both pseudo-elements have to carry it or
   the ring and its halo come apart. .mp-store and .mp-cta never show at the
   same width, so each can hold its own. */
.hero-cta .hero-cockpit::after,
.hero-cta .hero-cockpit::before{animation-delay:0s}
.hero-cta .js-open-modal::after,
.hero-cta .js-open-modal::before{animation-delay:.3s}
/* .btn.mp-store, not .mp-store. `animation` in .btn.pulse::after is a shorthand,
   so it resets animation-delay, and at (0,2,1) it outranked a bare class plus a
   pseudo-element -- the delay was set and silently dropped. Matching its
   specificity is enough: this file loads after tokens.css. */
.btn.mp-store::after,
.btn.mp-store::before{animation-delay:.6s}

.hero-proof{
  display:flex;gap:10px;flex-wrap:wrap;align-items:center;
  font-family:var(--f-mono);font-size:.66rem;color:var(--muted);
  letter-spacing:.08em;text-transform:uppercase;
}
.hero-proof span{display:inline-flex;align-items:center;gap:6px}

/* Live telemetry card — real numbers, pulled from the same feed as the cockpit.
   This is the hero's actual argument: the engine is running right now. */
/* ── Engine band ───────────────────────────────────────────────────────────
   The telemetry card used to share the hero with the device, which left it
   about 350px to lay out three counts, four asset rows and a footnote. Given a
   band of its own under the ticker it gets the width those readings want, and
   the hero gets to be one claim and one picture. */
.engine-band{margin-top:calc(-1 * clamp(10px,1.6vw,22px));padding:0 0 clamp(20px,2.6vw,32px)}
.engine-band .hero-live{max-width:none}

@media (min-width:820px){
  .engine-band .hl-body{
    display:grid;grid-template-columns:minmax(0,290px) minmax(0,1fr);
    gap:22px;align-items:start;
    /* Named, because the switch and the note are full-width and the two middle
       blocks are not. Auto-placement put them in the next free cell, which
       landed the note on top of the rows. */
    grid-template-areas:
      "mode  mode"
      "stats rows"
      "note  note";
  }
  .engine-band .hl-mode {grid-area:mode;justify-self:start;margin-bottom:0}
  .engine-band .hl-stats{grid-area:stats;margin-bottom:0}
  .engine-band .hl-rows {grid-area:rows}
  .engine-band .hl-note {grid-area:note;margin-top:0}
  /* Two columns of rows rather than one: a single column across this width
     left half a metre of nothing between each symbol and its price. */
  /* max-content, not 1fr: the rows are fixed-width now, so a fractional column
     would stretch past them and reappear as slack between the two groups. */
  .engine-band .hl-rows{
    display:grid;grid-template-columns:repeat(2,max-content);
    /* The two groups spread to fill the card; the space lands between them,
       never between a ticker and its own price. */
    justify-content:space-between;
    column-gap:clamp(34px,4vw,64px);
    border-left:1px solid var(--line-soft);padding-left:22px;
  }
  .engine-band .hl-row:nth-last-child(-n+2){border-bottom:none}
}

.hero-live{
  position:relative;z-index:2;
  border-radius:var(--r-lg);
  border:1px solid var(--line);
  background:var(--panel-grad-2);
  box-shadow:var(--shadow-lg);
  overflow:hidden;
  max-width:520px;width:100%;
}
.hl-head{
  display:flex;align-items:center;gap:10px;
  padding:12px 16px;border-bottom:1px solid var(--line-soft);
  background:var(--fill-1);
}
.hl-head h3{
  font-family:var(--f-mono);font-size:.62rem;letter-spacing:.2em;
  text-transform:uppercase;color:var(--accent);
}
.hl-head .pill{margin-left:auto}

.hl-body{padding:16px}

/* Both readings are in the HTML; the switch only chooses which is visible, so
   there is no request and the panel still says something with JS off — the
   settled one, which is the default the markup ships in. */
.hl-body .v-raw{display:none}
.hl-body[data-bias="raw"] .v-settled{display:none}
.hl-body[data-bias="raw"] .v-raw{display:inline}

.hl-mode{
  display:inline-flex;gap:2px;margin-bottom:12px;
  padding:2px;border-radius:100px;
  border:1px solid var(--line-soft);background:var(--fill-1);
}
.hl-mode-btn{
  padding:5px 12px;border-radius:100px;cursor:pointer;
  font-family:var(--f-mono);font-size:.58rem;letter-spacing:.12em;
  text-transform:uppercase;font-weight:600;
  color:var(--muted);background:none;border:0;
  transition:color .18s var(--ease),background .18s var(--ease);
}
.hl-mode-btn:hover{color:var(--accent-lt)}
.hl-mode-btn.is-on{background:var(--accent-glow);color:var(--accent-lt)}
.hl-mode-btn:focus-visible{outline:2px solid var(--accent);outline-offset:2px}

.hl-note{
  margin-top:12px;font-size:.7rem;line-height:1.6;color:var(--muted);
}
.hl-note b{
  font-family:var(--f-mono);font-size:.62rem;letter-spacing:.1em;
  text-transform:uppercase;color:var(--accent-lt);margin-right:5px;
}

.hl-stats{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;margin-bottom:14px}
.hl-stat{
  padding:11px 12px;border-radius:8px;
  border:1px solid var(--line-soft);background:var(--fill-1);
}
.hl-stat b{
  display:block;font-family:var(--f-mono);font-size:1.35rem;
  font-weight:700;line-height:1.1;
}
.hl-stat span{
  display:block;font-family:var(--f-mono);font-size:.55rem;
  letter-spacing:.12em;text-transform:uppercase;color:var(--dim);margin-top:5px;
}

.hl-rows{display:flex;flex-direction:column}
.hl-row{
  display:grid;grid-template-columns:44px 74px minmax(0,96px) 56px;
  justify-content:start;
  align-items:center;gap:10px;
  padding:8px 0;border-bottom:1px solid var(--hairline);
}
.hl-row:last-child{border-bottom:none}
.hl-row .s{font-family:var(--f-mono);font-size:.78rem;font-weight:700}
.hl-row .b{
  justify-self:start;
  font-family:var(--f-mono);font-size:.55rem;letter-spacing:.1em;
  text-transform:uppercase;padding:2px 7px;border-radius:4px;
  border:1px solid var(--line-soft);color:var(--muted);
}
.hl-row .b.bullish{color:var(--green);border-color:var(--green);background:var(--green-dim)}
.hl-row .b.bearish{color:var(--red);border-color:var(--red);background:var(--red-dim)}
.hl-row .p{font-family:var(--f-mono);font-size:.74rem;color:var(--text-2);text-align:right}
.hl-row .c{font-family:var(--f-mono);font-size:.7rem;font-weight:600;text-align:right}

.hl-foot{
  padding:12px 16px;border-top:1px solid var(--line-soft);
  display:flex;align-items:center;gap:10px;
  background:var(--accent-glow);
}
.hl-foot p{font-size:.72rem;color:var(--muted);flex:1}
.hl-foot a{
  font-family:var(--f-mono);font-size:.66rem;letter-spacing:.1em;
  text-transform:uppercase;color:var(--accent);white-space:nowrap;
}
.hl-foot a:hover{color:var(--accent-lt)}

.up{color:var(--green)}
.dn{color:var(--red)}
.flat{color:var(--muted)}

/* ── Store badges ─────────────────────────────────────────────────────────── */

.stores{display:flex;gap:12px;flex-wrap:wrap;margin-top:26px}
/* One of the two is always hidden -- see the comment on the markup in index.php.
   The desktop one stretches to the badges' height on its own, .stores having no
   align-items of its own, which is what keeps the row level. */
.mp-cta{display:none}
@media (max-width:860px){
  .mp-cta{display:inline-flex}
  .mp-store{display:none}
}
.store{
  display:flex;align-items:center;gap:11px;
  padding:9px 18px;border-radius:9px;
  border:1px solid var(--line-soft);
  background:var(--fill-1);
  position:relative;
  transition:border-color .2s,transform .2s var(--ease);
}
.store:hover{border-color:var(--line-strong);transform:translateY(-2px)}
.store-txt{display:flex;flex-direction:column;line-height:1.15}
.store-txt small{font-size:.58rem;color:var(--muted);letter-spacing:.04em}
.store-txt b{font-size:.92rem;font-weight:600;letter-spacing:-.01em}
.store-soon{
  position:absolute;top:-8px;right:8px;
  font-family:var(--f-mono);font-size:.5rem;
  letter-spacing:.12em;text-transform:uppercase;
  background:var(--accent);color:#0a0c10;
  padding:2px 7px;border-radius:100px;font-weight:700;
}
/* Light theme only. The pill's ground is --accent, which is bright cyan on the
   dark page and the darker #0a6f85 on the light one -- so the near-black label
   measures 12.28 against the first and 3.38 against the second. White is the
   other way round, 1.57 and 5.69, so each theme needs its own. Both light
   branches, because the un-stamped default is the common one. */
@media (prefers-color-scheme: light){
  :root:not([data-theme="dark"]) .store-soon{color:#fffdf6}
}
:root[data-theme="light"] .store-soon{color:#fffdf6}

/* ── Ticker strip ─────────────────────────────────────────────────────────── */

.strip{
  /* It now sits directly under the nav, which is position:fixed -- so the top
     offset the hero used to carry moves here. Only one of the two may have it
     or they stack into a 62px gap. */
  margin-top:var(--nav-h);
  border-block:1px solid var(--line-soft);
  background:var(--panel);
  overflow:hidden;height:44px;display:flex;align-items:center;
}
.strip-move{
  display:flex;gap:30px;white-space:nowrap;
  animation:tapeScroll 80s linear infinite;
}
.strip:hover .strip-move{animation-play-state:paused}
@keyframes tapeScroll{from{transform:translateX(0)}to{transform:translateX(-50%)}}
.strip-item{display:inline-flex;align-items:center;gap:8px;font-family:var(--f-mono);font-size:.72rem}
.strip-item b{color:var(--text-2);font-weight:600}

/* ── Section furniture ────────────────────────────────────────────────────── */

.sec-head{max-width:720px;margin-bottom:clamp(36px,4vw,56px)}
.sec-head.center{margin-inline:auto;text-align:center}
.sec-head h2{margin-bottom:16px}
.alt{background:var(--bg-2);border-block:1px solid var(--line-soft)}

/* ── Card grids ───────────────────────────────────────────────────────────── */

.grid-3{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(280px,100%),1fr));gap:16px}
.grid-2{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(360px,100%),1fr));gap:16px}

.icard{
  padding:26px 24px;border-radius:var(--r);
  border:1px solid var(--line-soft);
  background:var(--panel-grad);
  transition:transform .28s var(--ease),border-color .28s,box-shadow .28s;
  position:relative;overflow:hidden;
}
.icard:hover{transform:translateY(-4px);border-color:var(--line);box-shadow:var(--shadow)}
.icard-ico{
  width:40px;height:40px;border-radius:10px;
  display:flex;align-items:center;justify-content:center;
  border:1px solid var(--line);background:var(--accent-glow);
  margin-bottom:16px;color:var(--accent);
}
.icard h3{margin-bottom:9px}
.icard p{font-size:.88rem;color:var(--muted);line-height:1.6}
/* The credential cards carry their mark beside the title rather than over it:
   the four are read as a list of claims, and a 40px badge stacked above each one
   pushed the titles a whole row apart for nothing. Scoped, because the
   how-it-works cards above and the archive cards on Market Pulse share .icard
   and keep the stacked shape. */
.icard-hd{display:flex;align-items:center;gap:12px;margin-bottom:9px}
.icard-hd .icard-ico{margin-bottom:0;flex:none}
.icard-hd h3{margin-bottom:0}

.icard-n{
  font-family:var(--f-mono);font-size:.68rem;color:var(--accent);
  letter-spacing:.16em;margin-bottom:12px;
}

/* ── Pipeline (how it works) ──────────────────────────────────────────────── */

.pipeline{display:flex;flex-direction:column;gap:0;max-width:860px;margin-inline:auto}
.pstep{
  display:grid;grid-template-columns:auto 1fr;gap:22px;
  padding:22px 0;position:relative;
}
.pstep:not(:last-child)::before{
  content:'';position:absolute;left:23px;top:62px;bottom:-8px;width:1px;
  background:linear-gradient(180deg,var(--line-strong),transparent);
}
.pstep-n{
  width:48px;height:48px;border-radius:12px;flex:none;
  display:flex;align-items:center;justify-content:center;
  font-family:var(--f-mono);font-size:.86rem;font-weight:700;
  border:1px solid var(--line);background:var(--accent-glow);
  color:var(--accent);position:relative;z-index:1;
}
.pstep.on .pstep-n{
  background:linear-gradient(135deg,var(--accent-lt),var(--accent));
  color:#0a0c10;border-color:transparent;
  box-shadow:0 0 26px -6px rgba(61,224,245,.7);
}
.pstep h3{margin-bottom:7px}
.pstep p{color:var(--muted);font-size:.9rem;max-width:60ch}
.pstep-tag{
  display:inline-block;margin-top:10px;
  font-family:var(--f-mono);font-size:.6rem;letter-spacing:.12em;
  text-transform:uppercase;color:var(--cyan);
  padding:3px 9px;border-radius:4px;
  border:1px solid var(--cyan);background:var(--cyan-dim);
}

/* ── Performance ──────────────────────────────────────────────────────────── */

.perf-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(300px,100%),1fr));gap:16px;margin-bottom:22px}
.perf{
  padding:24px;border-radius:var(--r);
  border:1px solid var(--line-soft);
  background:var(--panel-grad);
  position:relative;overflow:hidden;
}
.perf::before{content:'';position:absolute;inset:0 0 auto 0;height:2px}
.perf.bull::before{background:linear-gradient(90deg,var(--green),transparent)}
.perf.bear::before{background:linear-gradient(90deg,var(--red),transparent)}
.perf.chop::before{background:linear-gradient(90deg,var(--accent),transparent)}
.perf-regime{
  font-family:var(--f-mono);font-size:.68rem;letter-spacing:.14em;
  text-transform:uppercase;margin-bottom:4px;
}
.perf.bull .perf-regime{color:var(--green)}
.perf.bear .perf-regime{color:var(--red)}
.perf.chop .perf-regime{color:var(--accent)}
.perf-period{font-size:.76rem;color:var(--dim);margin-bottom:18px}
.perf-nums{display:grid;grid-template-columns:repeat(2,1fr);gap:10px;margin-bottom:16px}
.perf-num{padding:11px;border-radius:8px;background:var(--fill-1);border:1px solid var(--line-soft)}
.perf-num b{display:block;font-family:var(--f-mono);font-size:1.28rem;font-weight:700}
.perf-num span{
  display:block;font-family:var(--f-mono);font-size:.55rem;
  letter-spacing:.11em;text-transform:uppercase;color:var(--dim);margin-top:4px;
}
.perf-foot{font-family:var(--f-mono);font-size:.68rem;color:var(--dim);line-height:1.7}

.context-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(210px,100%),1fr));gap:14px;margin-bottom:20px}
.ctx{padding:16px;border-radius:8px;border:1px solid var(--line-soft);background:var(--fill-1)}
.ctx b{display:block;font-size:1rem;color:var(--accent-lt);margin-bottom:2px}
.ctx span{
  display:block;font-family:var(--f-mono);font-size:.55rem;
  letter-spacing:.11em;text-transform:uppercase;color:var(--dim);margin-bottom:8px;
}
.ctx p{font-size:.76rem;color:var(--muted);line-height:1.55}

.disclaimer{
  padding:14px 18px;border-radius:8px;
  border:1px solid var(--amber);background:var(--fill-1);
  font-size:.78rem;color:var(--muted);line-height:1.65;
}
.disclaimer strong{color:var(--amber)}

/* ── Comparison table ─────────────────────────────────────────────────────── */

.cmp-wrap{overflow-x:auto;border-radius:var(--r);border:1px solid var(--line-soft)}
.cmp{width:100%;min-width:720px;font-size:.85rem}
.cmp th,.cmp td{padding:14px 16px;text-align:center;border-bottom:1px solid var(--hairline)}
.cmp th{
  font-family:var(--f-mono);font-size:.62rem;letter-spacing:.12em;
  text-transform:uppercase;color:var(--muted);font-weight:500;
  background:var(--fill-1);
}
.cmp th:first-child,.cmp td:first-child{text-align:left;color:var(--text-2)}
.cmp .own{background:var(--accent-glow)}
.cmp th.own{color:var(--accent);font-weight:700}
.cmp tbody tr:last-child td{border-bottom:none}
.yes{color:var(--green);font-size:1rem}
.no{color:var(--dim);font-size:1rem}
.partial{font-family:var(--f-mono);font-size:.66rem;color:var(--amber)}

/* ── Video ────────────────────────────────────────────────────────────────── */

.video-wrap{
  display:grid;grid-template-columns:auto minmax(0,1fr);
  gap:clamp(28px,5vw,64px);align-items:center;
}
.phone{
  width:clamp(230px,26vw,282px);aspect-ratio:9/19.5;
  border-radius:40px;padding:9px;flex:none;
  background:linear-gradient(160deg,#232c3d,#0d1220);
  box-shadow:var(--shadow-lg),inset 0 0 0 1px var(--fill-3);
  position:relative;
}
.phone::before{
  content:'';position:absolute;top:19px;left:50%;transform:translateX(-50%);
  width:88px;height:20px;border-radius:100px;z-index:3;
  /* Near-black in both themes: it is a camera cutout, not a panel. Using the
     page background made it a white pill on a light screen. */
  background:#05070d;
}

/* Demo section: the mockup takes the recording's format instead of imposing
   its own. The capture is 384x848 (0.4528) and the frame's 9/19.5 screen was
   0.4452 — close enough that cover only shaved the sides, but the two were
   never the same shape, and boxing the video into anything else is what made it
   stop looking like a screen.
   The capture also already contains the device's status bar and its island, so
   the frame draws neither. A notch drawn here is by definition an overlay on
   real pixels — which is the thing to avoid. */
.video-wrap .phone{aspect-ratio:auto}
.video-wrap .phone::before{display:none}
.video-wrap .phone video{
  display:block;width:100%;height:auto;
  aspect-ratio:384/848;
  object-fit:cover;border-radius:32px;background:#000;
}

/* ── Hero device ───────────────────────────────────────────────────────────
   Reuses the .phone shell from the demo section so the two read as the same
   product, with an app screen drawn inside instead of a video. */
.hero-device{
  position:relative;z-index:2;
  margin:0;
  display:flex;flex-direction:column;align-items:center;gap:10px;
  /* Centred in its own column now, not pinned to the far edge: the column is
     what holds the spare width, so the phone sits in the middle of it. */
  justify-self:center;
}
.hero-phone{
  width:clamp(214px,19vw,268px);
  aspect-ratio:9/19.5;
}
/* The chart is a designed scenario, not a live trade. Small, quiet, and always
   present — the phone frame alone does not say which. */
.hero-device-cap{
  font-family:var(--f-mono);font-size:.52rem;letter-spacing:.14em;
  text-transform:uppercase;color:var(--muted);text-align:center;
}
.hp-screen{
  position:absolute;inset:9px;border-radius:32px;overflow:hidden;
  background:linear-gradient(178deg,var(--hp-bg-a),var(--hp-bg-b) 62%,var(--hp-bg-a));
  display:flex;flex-direction:column;
}
/* The shell stays metal in both themes; the screen follows the page, because a
   light page beside a permanently dark screen reads as a screenshot of the app
   rather than the app. The tokens live in tokens.css with the rest. */
.hp-screen{color:var(--hp-text)}

.hp-status{
  display:flex;align-items:center;justify-content:space-between;
  padding:14px 18px 4px;
  font-family:var(--f-mono);font-size:.5rem;letter-spacing:.06em;color:var(--hp-mute);
}
.hp-status-r{display:inline-flex;gap:3px;align-items:flex-end}
.hp-status-r i{width:2px;background:var(--hp-mute);border-radius:1px}
.hp-status-r i:nth-child(1){height:4px}
.hp-status-r i:nth-child(2){height:6px}
.hp-status-r i:nth-child(3){height:8px}

.hp-head{
  display:grid;grid-template-columns:auto 1fr auto;
  align-items:baseline;gap:2px 6px;padding:8px 14px 6px;
}
.hp-sym{font-family:var(--f-mono);font-size:.78rem;font-weight:700;color:var(--hp-sym)}
.hp-name{
  font-family:var(--f-mono);font-size:.5rem;letter-spacing:.1em;
  text-transform:uppercase;color:var(--hp-mute);
}
.hp-price{
  grid-column:3;grid-row:1;
  font-family:var(--f-mono);font-size:.78rem;font-weight:700;text-align:right;
}
.hp-chg{
  grid-column:3;grid-row:2;
  font-family:var(--f-mono);font-size:.54rem;font-weight:600;text-align:right;
}
.hp-chg.up{color:var(--green)}
.hp-chg.dn{color:var(--red)}
.hp-chg.flat{color:var(--hp-mute)}

.hp-chart{flex:1;width:100%;min-height:0;display:block}

.hp-card{
  margin:0 10px 8px;padding:9px 10px;border-radius:10px;
  background:var(--hp-fill);
  box-shadow:inset 0 0 0 1px var(--hp-line);
}
.hp-card{transition:box-shadow .4s}
.hp-card.pending{box-shadow:inset 0 0 0 1px var(--hp-line-soft)}
.hp-card.fill{animation:hpCardFill .8s ease-out}
@keyframes hpCardFill{
  0%{box-shadow:inset 0 0 0 1px var(--green), 0 0 18px -4px var(--green)}
  100%{box-shadow:inset 0 0 0 1px var(--hp-line)}
}
/* Dashes need to sit exactly where the numbers will, or the card jumps as it
   fills. Tabular figures in the mono face already guarantee that. */
.hp-card.pending .hp-card-entry,
.hp-card.pending .hp-lvl-v{color:var(--hp-dim)}

.hp-card-top{display:flex;align-items:center;gap:7px}
.hp-badge{
  font-family:var(--f-mono);font-size:.48rem;font-weight:700;letter-spacing:.1em;
  padding:3px 6px;border-radius:4px;
}
.hp-badge.pending{background:var(--hp-fill-2);color:var(--hp-dim);box-shadow:inset 0 0 0 1px var(--hp-line)}
.hp-badge.buy{background:var(--green-dim);color:var(--green);box-shadow:inset 0 0 0 1px var(--green)}
.hp-badge.sell{background:var(--red-dim);color:var(--red);box-shadow:inset 0 0 0 1px var(--red)}
.hp-card-sym{font-family:var(--f-mono);font-size:.66rem;font-weight:700}
.hp-card-entry{
  margin-left:auto;font-family:var(--f-mono);font-size:.66rem;font-weight:700;
}
.hp-levels{display:flex;gap:5px;margin-top:7px}
.hp-lvl{
  flex:1;min-width:0;padding:4px 5px;border-radius:5px;
  background:var(--hp-fill-2);
  font-family:var(--f-mono);font-size:.5rem;color:var(--hp-lvl);
  display:flex;flex-direction:column;gap:1px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.hp-lvl b{font-size:.44rem;letter-spacing:.12em;font-weight:700}
.hp-lvl.tp b{color:var(--green)}
.hp-lvl.sl b{color:var(--red)}

/* The two targets and the entry badge blink; the stop-loss does not. They keep
   var(--green) rather than blinking toward a literal, so they stay the same
   colour as .hp-chg above and both follow the screen the phone is showing.
   TP2 trails TP1 so the pair reads as a sequence, not a flash. */
.hp-badge.buy,
.hp-badge.sell,
.hp-lvl.tp b{animation:hpSignal 1.9s var(--ease) infinite}
.hp-lvl.tp:nth-of-type(2) b{animation-delay:.28s}

@keyframes hpSignal{
  0%   {opacity:.5}
  16%  {opacity:1}
  52%  {opacity:.5}
  100% {opacity:.5}
}

@media (prefers-reduced-motion: reduce){
  .hp-badge.buy,.hp-badge.sell,.hp-lvl.tp b{animation:none;opacity:1}
}

/* Push alert replayed on the device. It covers the status bar the way a real
   iOS banner does — that is the point of the whole device: the app tells you,
   you do not go looking. */
.hp-alert{
  position:absolute;left:7px;right:7px;top:0;bottom:auto;z-index:4;
  display:flex;align-items:center;gap:8px;
  padding:8px 9px;border-radius:12px;
  background:var(--hp-alert);
  box-shadow:var(--hp-shadow), inset 0 0 0 1px var(--hp-line);
  transform:translateY(-170%);opacity:0;pointer-events:none;
  transition:transform .42s cubic-bezier(.2,.9,.25,1),opacity .28s;
}
.hp-alert.on{transform:translateY(0);opacity:1}
.hp-alert-ic{
  width:21px;height:21px;border-radius:6px;flex:none;
  background:linear-gradient(150deg,var(--accent-lt),var(--accent));
}
.hp-alert.buy .hp-alert-ic{background:linear-gradient(150deg,var(--green),#1c9c67)}
.hp-alert-txt{min-width:0}
.hp-alert-t{
  display:block;font-family:var(--f-mono);font-size:.55rem;font-weight:700;
  letter-spacing:.12em;color:var(--accent);
}
.hp-alert.buy .hp-alert-t{color:var(--green)}
.hp-alert-s{
  display:block;margin-top:2px;font-family:var(--f-mono);font-size:.47rem;
  letter-spacing:.04em;color:var(--hp-alert-sub);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}

/* The screen itself catches the alert for a beat. Clipped by the rounded
   corners of .hp-screen, so it reads as the glass lighting up. */
.hp-glow{
  position:absolute;inset:0;z-index:3;pointer-events:none;opacity:0;
  color:var(--accent);
  /* inherit, or the inset ring is drawn square against a screen that is round:
     .hp-screen clips at 32px and takes the four corners off the flash, so the
     edge lit up on the straights and stopped short at every corner. Direct
     child of .hp-screen, so inherit resolves to its radius. */
  border-radius:inherit;
  box-shadow:inset 0 0 0 2px currentColor, inset 0 0 30px -8px currentColor;
}
.hp-glow.buy{color:var(--green)}
.hp-glow.on{animation:hpFlash .66s ease-out}

/* ── The screen's power-on ────────────────────────────────────────────────────
   The picture opens from a centre line the way a tube warms up, and the two
   edges carry the phosphor out with them. Two shutters rather than a clip on
   the content: what sits behind an unopened screen has to be black, and
   clipping .hp-screen would have shown the shell's metal gradient instead.

   Black in both themes even though the screen itself follows the page — a
   screen that is off is off, and a pale "off" state reads as a blank app
   rather than a device waking up.

   Driven by .reveal.in, so it starts when the device actually arrives instead
   of at a delay guessed against the reveal's 0.7s. To drop the whole effect:
   remove the .hp-boot div in index.php and this block. */
.hp-boot{
  position:absolute;inset:0;z-index:4;pointer-events:none;
  border-radius:inherit;
}
.hp-boot::before,
.hp-boot::after{
  content:'';position:absolute;left:0;right:0;height:50%;
  background:#03050a;
}
/* The glow sits on the edge facing the centre, so it sweeps outward with the
   shutter. That edge is the whole effect. */
.hp-boot::before{top:0;    box-shadow:0 1px 0 var(--accent), 0 4px 18px -2px var(--accent)}
.hp-boot::after {bottom:0; box-shadow:0 -1px 0 var(--accent), 0 -4px 18px -2px var(--accent)}

.reveal.in .hp-boot::before{animation:hpBootTop .95s var(--ease) forwards}
.reveal.in .hp-boot::after {animation:hpBootBot .95s var(--ease) forwards}

/* height, not scaleY. A transform squashes the shutter's box-shadow along with
   the shutter, and a compressed glow is exactly the part that has to stay
   crisp. The opacity is not decoration either: a zero-height element still
   paints its shadow, so without it two lit lines stay pinned to the edges of
   the screen for good. */
@keyframes hpBootTop{
  0%,18%{height:50%;opacity:1}
  86%   {opacity:1}
  100%  {height:0;opacity:0}
}
@keyframes hpBootBot{
  0%,18%{height:50%;opacity:1}
  86%   {opacity:1}
  100%  {height:0;opacity:0}
}
@media (prefers-reduced-motion:reduce){
  .hp-boot{display:none}
}
@keyframes hpFlash{
  0%{opacity:0}
  16%{opacity:.9}
  100%{opacity:0}
}
@media (prefers-reduced-motion: reduce){
  .hp-alert{transition:none}
  .hp-glow.on{animation:none}
  .hp-card.fill{animation:none}
}

/* Five tabs, so each column is a fifth of a 224px phone rather than a quarter —
   the type comes down to match. "Watchlist" is the one that decides it. */
.hp-tabs{
  display:grid;grid-template-columns:repeat(5,1fr);
  padding:7px 4px 12px;border-top:1px solid var(--hp-line-soft);
  font-family:var(--f-mono);font-size:.4rem;letter-spacing:.05em;
  text-transform:uppercase;color:var(--hp-dim);text-align:center;
}
.hp-tabs .on{color:var(--accent)}

.video-list{list-style:none;display:flex;flex-direction:column;gap:14px;margin-top:22px}
.video-list li{
  padding-left:26px;position:relative;font-size:.9rem;color:var(--muted);line-height:1.6;
}
.video-list li::before{
  content:'';position:absolute;left:0;top:.6em;
  width:8px;height:8px;border-radius:2px;
  background:var(--accent);transform:rotate(45deg);
}
.video-list strong{color:var(--text);font-weight:600}

/* ── Pricing ──────────────────────────────────────────────────────────────── */

.plans{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(280px,100%),1fr));gap:18px;max-width:760px;margin:0 auto 44px}
.plan{
  padding:30px 26px;border-radius:var(--r-lg);
  border:1px solid var(--line-soft);
  background:var(--panel-grad);
  position:relative;
}
.plan.featured{
  border-color:var(--line-strong);
  background:
    radial-gradient(420px 200px at 50% 0%,var(--accent-glow),transparent 70%),
    var(--panel-grad-2);
  box-shadow:var(--shadow);
}
.plan-tag{
  position:absolute;top:-11px;left:50%;transform:translateX(-50%);
  font-family:var(--f-mono);font-size:.58rem;letter-spacing:.11em;
  text-transform:uppercase;white-space:nowrap;
  padding:4px 13px;border-radius:100px;
  background:var(--accent);color:#0a0c10;font-weight:700;
  display:inline-flex;align-items:center;gap:6px;
}
.plan-tag-star{color:#fff;flex:none}

/* Light theme only, same reason as .store-soon and .btn-primary: the ground is
   --accent, which is bright cyan on the dark page and #0a6f85 on the light one,
   so a fixed near-black label is right on one and unreadable on the other. */
@media (prefers-color-scheme: light){
  :root:not([data-theme="dark"]) .plan-tag{color:#fffdf6}
}
:root[data-theme="light"] .plan-tag{color:#fffdf6}

/* The founders price is time-limited at launch, so the tag has to read as an
   offer that expires rather than as a label. A ring that leaves the pill and
   fades: it draws the eye on arrival without moving the pill itself, which
   would drag the card's top edge with it.

   translateX(-50%) is already on .plan-tag for centring, so the ring is a
   pseudo-element with its own transform — animating the pill's own would fight
   the centring and slide it off-centre. */
.plan-tag::after{
  content:'';position:absolute;inset:-1px;border-radius:100px;
  border:1px solid var(--accent);
  animation:tagRing 3.2s var(--ease) infinite;
  pointer-events:none;
}
@keyframes tagRing{
  0%   {transform:scale(1);opacity:.85}
  22%  {transform:scale(1.28);opacity:0}
  100% {transform:scale(1.28);opacity:0}
}
.plan h3{font-size:1.35rem;font-weight:700;letter-spacing:-.02em;margin-bottom:12px}
.plan-price{display:flex;align-items:baseline;gap:7px;margin-bottom:3px}
.plan-price b{font-family:var(--f-mono);font-size:2.5rem;font-weight:700;letter-spacing:-.03em}
.plan-price span{font-size:.82rem;color:var(--muted)}
.plan-note{font-size:.76rem;color:var(--dim);margin-bottom:20px}
.plan ul{list-style:none;display:flex;flex-direction:column;gap:9px}
.plan li{
  font-size:.85rem;color:var(--muted);padding-left:22px;position:relative;line-height:1.5;
}
.plan li::before{
  content:'✓';position:absolute;left:0;top:0;
  color:var(--green);font-size:.82rem;font-weight:700;
}

/* ── Roadmap ──────────────────────────────────────────────────────────────── */

.roadmap{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(200px,100%),1fr));gap:14px}
.rq{
  padding:22px 20px;border-radius:var(--r);
  border:1px solid var(--line-soft);
  background:var(--fill-1);
  opacity:.62;transition:opacity .3s,border-color .3s,transform .3s var(--ease);
}
.rq:hover{opacity:1;transform:translateY(-3px)}
.rq.now{
  opacity:1;border-color:var(--line-strong);
  background:linear-gradient(165deg,var(--accent-glow),var(--panel));
}
.rq.done{opacity:.45}
.rq-q{
  font-family:var(--f-mono);font-size:.66rem;letter-spacing:.13em;
  text-transform:uppercase;color:var(--accent);margin-bottom:10px;
  display:flex;align-items:center;gap:7px;
}
.rq h3{font-size:1rem;margin-bottom:12px}
.rq ul{list-style:none;display:flex;flex-direction:column;gap:6px}
.rq li{font-size:.78rem;color:var(--muted);padding-left:14px;position:relative}
.rq li::before{content:'·';position:absolute;left:3px;color:var(--accent)}

/* ── FAQ ──────────────────────────────────────────────────────────────────── */

.faq{max-width:820px;margin-inline:auto;display:flex;flex-direction:column;gap:8px}
.fq{border:1px solid var(--line-soft);border-radius:var(--r);background:var(--fill-1);overflow:hidden}
.fq.open{border-color:var(--line)}
.fq-q{
  width:100%;display:flex;align-items:center;justify-content:space-between;gap:16px;
  padding:17px 20px;text-align:left;
  font-size:.94rem;font-weight:600;color:var(--text);
  transition:color .2s;
}
.fq-q:hover{color:var(--accent-lt)}
.fq-i{
  flex:none;width:20px;height:20px;position:relative;
  transition:transform .3s var(--ease);color:var(--accent);
}
.fq-i::before,.fq-i::after{
  content:'';position:absolute;top:50%;left:50%;
  background:currentColor;border-radius:1px;
  transform:translate(-50%,-50%);
}
.fq-i::before{width:11px;height:1.5px}
.fq-i::after{width:1.5px;height:11px;transition:opacity .3s}
.fq.open .fq-i{transform:rotate(180deg)}
.fq.open .fq-i::after{opacity:0}
.fq-a{max-height:0;overflow:hidden;transition:max-height .38s var(--ease)}
.fq-a p{padding:0 20px 18px;color:var(--muted);font-size:.88rem;line-height:1.7}

/* ── Email strip ──────────────────────────────────────────────────────────── */

/* The page's rhythm is 124px top and bottom, which on a 318px card is 78% of
   its own height on either side and reads as a gap rather than as breathing
   room. The card already carries up to 48px of its own padding, so it does not
   need the full section rhythm around it as well. */
.section-tight{padding-block:clamp(34px,4vw,54px)}
/* The neighbours give up their facing padding too. Tightening only the card's
   own section leaves the gap at its 54px plus the next section's 124px, which
   is most of what was there before. :has() covers the side above; if a browser
   lacks it, that side simply keeps the page rhythm. */
.section-tight + section{padding-top:clamp(34px,4vw,54px)}
section:has(+ .section-tight){padding-bottom:clamp(34px,4vw,54px)}

.email{
  border-radius:var(--r-lg);padding:clamp(30px,4vw,48px);
  border:1px solid var(--line);
  background:
    radial-gradient(680px 260px at 20% 0%,var(--accent-glow),transparent 70%),
    var(--panel-grad);
  text-align:center;
}
.email h3{font-size:clamp(1.3rem,2.7vw,1.8rem);font-weight:700;letter-spacing:-.026em;margin-bottom:10px}
.email p{color:var(--muted);font-size:.9rem;max-width:52ch;margin:0 auto 22px}
.email-form{display:flex;gap:9px;max-width:460px;margin-inline:auto;flex-wrap:wrap}
.email-form input{
  flex:1;min-width:200px;padding:13px 16px;border-radius:var(--r-sm);
  border:1px solid var(--line-soft);background:var(--fill-2);
  font-size:.88rem;transition:border-color .2s;
}
.email-form input:focus{outline:none;border-color:var(--line-strong)}
.email-form input::placeholder{color:var(--dim)}
.email-ok{display:none;color:var(--green);font-size:.88rem;margin-top:14px}
.email-ok.on{display:block}

/* ── Final CTA ────────────────────────────────────────────────────────────── */

.final{
  text-align:center;padding:clamp(70px,9vw,120px) 20px;
  background:
    radial-gradient(760px 380px at 50% 0%,var(--accent-glow),transparent 70%),
    var(--bg-2);
  border-top:1px solid var(--line-soft);
}
.final h2{margin-bottom:16px}
.final p{color:var(--muted);max-width:52ch;margin:0 auto 30px}

/* ── Footer ───────────────────────────────────────────────────────────────── */

.foot{
  padding:clamp(44px,5vw,64px) clamp(20px,5vw,64px) 32px;
  border-top:1px solid var(--line-soft);
  display:grid;grid-template-columns:2fr 1fr 1fr 1.4fr;gap:36px;
  background:var(--bg);
}
.foot h2{
  font-family:var(--f-mono);font-size:.62rem;letter-spacing:.16em;
  text-transform:uppercase;color:var(--accent);margin-bottom:14px;font-weight:600;
}
.foot p{font-size:.8rem;color:var(--muted);line-height:1.7}
.foot-links{display:flex;flex-direction:column;gap:9px}
.foot-links a{font-size:.82rem;color:var(--muted);transition:color .2s}
.foot-links a:hover{color:var(--accent-lt)}
.foot-logo{display:inline-block;margin-bottom:14px;color:var(--text)}
/* 52px put the registered mark at 5.2px, which is a speck rather than a symbol —
   it is in the artwork, it just could not be read. At 84 it lands near 8.4px,
   about the smallest a circled R still reads as one. */
.foot-lockup{height:84px;width:auto}
.foot-social{margin-top:16px;margin-left:-7px}

.foot-theme{
  display:flex;align-items:center;gap:10px;margin-top:18px;
  font-family:var(--f-mono);font-size:.6rem;letter-spacing:.14em;
  text-transform:uppercase;color:var(--dim);
}
.foot-legal{
  grid-column:1/-1;padding-top:24px;margin-top:8px;
  border-top:1px solid var(--hairline);
  /* --muted, not --dim: this is the risk disclosure, and it has to be readable. */
  font-size:.74rem;color:var(--muted);line-height:1.7;
}

/* ── Modal ────────────────────────────────────────────────────────────────── */

.modal-bg{
  position:fixed;inset:0;z-index:200;
  background:var(--scrim);backdrop-filter:blur(8px);
  display:flex;align-items:center;justify-content:center;padding:20px;
  opacity:0;pointer-events:none;transition:opacity .28s var(--ease);
  overflow-y:auto;
}
.modal-bg.open{opacity:1;pointer-events:auto}
.modal{
  width:min(560px,100%);
  border-radius:var(--r-lg);
  border:1px solid var(--line);
  background:linear-gradient(165deg,var(--panel-2),var(--panel));
  box-shadow:var(--shadow-lg);
  padding:clamp(26px,4vw,38px);
  position:relative;
  transform:translateY(16px) scale(.985);
  transition:transform .3s var(--ease);
  margin:auto;
}
.modal-bg.open .modal{transform:none}
.modal-x{
  position:absolute;top:14px;right:14px;
  width:32px;height:32px;border-radius:8px;
  display:flex;align-items:center;justify-content:center;
  color:var(--muted);transition:.2s;
}
.modal-x:hover{background:var(--fill-2);color:var(--text)}
.modal h2{font-size:1.7rem;margin-bottom:8px}
.modal-sub{color:var(--muted);font-size:.86rem;margin-bottom:24px}

.field{margin-bottom:15px}
.field label{
  display:block;font-family:var(--f-mono);font-size:.6rem;
  letter-spacing:.12em;text-transform:uppercase;color:var(--muted);margin-bottom:7px;
}
.field input,.field select,.field textarea{
  width:100%;padding:11px 13px;border-radius:var(--r-sm);
  border:1px solid var(--line-soft);background:var(--fill-2);
  font-size:.9rem;transition:border-color .2s;
}
.field input:focus,.field select:focus,.field textarea:focus{outline:none;border-color:var(--line-strong)}
.field textarea{resize:vertical;min-height:70px;font-family:inherit}
.field select option{background:var(--panel);color:var(--text)}

/* 16px on touch, and it is not a taste decision.
   Mobile Safari zooms the page in when a form control smaller than 16px takes
   focus, and it does not zoom back out when the field is left. The visual
   viewport stays narrower than the layout viewport, so every position:fixed
   element -- the nav above all, which is left:0;right:0 -- is then laid out
   wider than the screen and hangs off the right edge. The report is always
   "the site is zoomed and the header overflows after filling the form", and
   the cause is here: .9rem is 14.4px and .88rem is 14.08px.
   Keyed to pointer:coarse rather than a width, because the zoom follows the
   input method and not the screen -- an iPad in landscape is wider than any
   phone breakpoint and behaves the same way. */
@media (pointer: coarse){
  .field input,.field select,.field textarea,
  .email-form input{font-size:16px}
}
.field-row{display:grid;grid-template-columns:1fr 1fr;gap:12px}
.field-err{display:none;font-size:.72rem;color:var(--red);margin-top:5px}
.field-err.on{display:block}
.modal .btn{width:100%;margin-top:8px}
.modal-fine{font-size:.72rem;color:var(--dim);text-align:center;margin-top:12px}

.modal-done{display:none;text-align:center;padding:14px 0}
.modal-done.on{display:block}
.modal-form.off{display:none}
.done-tick{
  width:56px;height:56px;border-radius:50%;margin:0 auto 18px;
  display:flex;align-items:center;justify-content:center;
  border:1px solid var(--green);background:var(--green-dim);
  color:var(--green);font-size:1.6rem;
}
.modal-done h3{font-size:1.35rem;font-weight:700;letter-spacing:-.02em;margin-bottom:10px}
.modal-done p{color:var(--muted);font-size:.86rem;margin-bottom:12px}
.modal-done .done-spam{
  display:flex;gap:11px;align-items:flex-start;text-align:left;
  font-size:.86rem;line-height:1.5;color:var(--text);
  background:var(--accent-glow);
  border:1px solid var(--accent);border-left-width:3px;
  border-radius:var(--r-sm);padding:13px 15px;margin:0 0 18px;
}
.modal-done .done-spam::before{content:"\1F4EC";font-size:1.1rem;line-height:1.25;flex:none}
.modal-done .done-spam strong{color:var(--accent);font-weight:700}
/* The message is one <span>: a bare text node beside the <strong> would
   become a second flex item and split the sentence into two columns. */
.modal-done .done-spam > span{flex:1 1 auto;min-width:0}

/* ── Responsive ───────────────────────────────────────────────────────────── */

@media (max-width:1080px){
  .hero{grid-template-columns:1fr;text-align:left}
  /* One column means the device no longer competes with the headline for
     width, so it takes the size the chart wants. */
  .hero-device{justify-self:start;align-self:center;margin-right:0}
  .hero-phone{width:clamp(224px,30vw,272px)}
  .video-wrap{grid-template-columns:1fr;justify-items:center;text-align:center}
  .video-list li{text-align:left}
  .foot{grid-template-columns:1fr 1fr}
}

@media (max-width:860px){
  /* The phone moves up under the badge and the buttons move beside it: on a
     narrow screen the product and its calls to action should both be visible
     before the reader scrolls past a headline to find them.

     A named grid rather than flex ordering, because "device left, buttons
     right, everything else full width" is two-dimensional. display:contents
     dissolves .hero-inner so its children can be placed in it. */
  .hero{
    padding-top:14px;
    display:grid;
    /* The buttons take only what their labels need; the phone takes the rest.
       The other way round left the column at 1fr, so each button was padded out
       to about 190px around a 115px label and the phone was capped for space it
       was not actually being denied. */
    grid-template-columns:minmax(0,1fr) auto;
    /* The badges join the buttons in the right-hand column rather than sitting
       at the foot of the hero: everything you can act on is then in one stack
       beside the device. `device` spanning both rows is what lets the column
       hold the buttons and the badges one under the other. */
    grid-template-areas:
      "badge  badge"
      "device cta"
      "device stores"
      "title  title"
      "sub    sub"
      "proof  proof";
    align-items:start;
    column-gap:16px;row-gap:0;
  }
  .hero-inner{display:contents}
  /* Tighter around the badge: it is a one-line status chip, and the hero's
     own top padding plus a 22px margin left it floating. */
  .hero-badge {grid-area:badge;margin-bottom:10px}
  .hero-device{grid-area:device;margin:6px 0 6px;align-self:center}
  .hero-cta   {grid-area:cta;align-self:end;flex-direction:column;
               align-items:stretch;gap:18px;margin-bottom:0}

  /* Conversion first on a phone, then the two ways to look before committing,
     then the reading. Order, not DOM: the wide layout keeps the primary button
     leading, and that is also the order the markup and the tab ring follow. */
  .hero-cta .js-open-modal{order:1}
  .hero-cta .btn-demo     {order:2}
  /* .hero-cockpit, not .btn-primary. The filled variant belongs to Get the app
     now, and that button is also .js-open-modal -- keyed to the variant this
     rule would have matched it too and, coming later, won: order 3 for the
     button meant to lead. Ordering hangs off what a button IS, not off how it
     is painted, so restyling one can no longer move another. */
  .hero-cta .hero-cockpit {order:3}
  .hero-cta .mp-cta       {order:4}
  .hero h1    {grid-area:title;margin-top:22px}
  .hero-sub   {grid-area:sub}
  .hero-proof {grid-area:proof}
  /* Under the buttons in the same column. flex-direction, not flex-wrap: the
     column is sized `auto`, which resolves to max-content, and a wrapping row's
     max-content is still both badges side by side -- 303px of the 390 on a
     phone, which left the device 21px and crushed it. Stacking them explicitly
     makes max-content one badge wide and gives the device its width back.
     18px matches the gap between the buttons above. */
  .hero .stores{grid-area:stores;margin-top:18px;align-self:start;
                flex-direction:column;
                /* 18px, not the row's 12: on a phone this is one stack of six
                   controls, and one of its six gaps being 6px tighter than the
                   other five is the kind of thing that reads as a mistake. */
                gap:18px}

  /* The column leads with Get the app, so the cascade starts there. */
  .hero-cta .js-open-modal::after,
  .hero-cta .js-open-modal::before{animation-delay:0s}
  .hero-cta .hero-cockpit::after,
  .hero-cta .hero-cockpit::before{animation-delay:.3s}
  .btn.mp-cta::after,
  .btn.mp-cta::before{animation-delay:.6s}

  /* .hero-inner is gone, so what it carried has to be handed to its children:
     z-index, or the headline paints under the absolutely positioned orbs, and
     the measure, which would otherwise run the full viewport width. */
  .hero-badge,.hero h1,.hero-sub,.hero-proof,.hero .stores{
    position:relative;z-index:2;max-width:640px;
  }
  .hero-device,.hero-cta{position:relative;z-index:2}

  /* Narrow enough to leave the buttons a usable column. The figure is pinned
     too, not just the phone: the caption is what was setting the column's
     width, at 172px against the phone's 140, and those 32px are the
     difference between the longest button label fitting and not. */
  /* No fixed width any more: the figure fills its column, and the phone is
     capped only so it stops growing on a tablet-width screen. */
  .hero-device{width:100%}
  .hero-phone{width:min(100%,250px)}
  .hero-device-cap{font-size:.46rem;letter-spacing:.1em;line-height:1.4}
  /* One set, not three. Side by side on desktop the primary fill, the play
     badge and the ghost outline are a hierarchy; stacked in a narrow column at
     .72rem they just look unrelated. Here the two secondary actions share one
     treatment and only the primary stays filled.

     The decorations go with them: an arrow and a 27px play disc are sized for
     a desktop button, and inside a 40px stacked one they are noise -- the disc
     also made that button 9px taller than its neighbours. */
  .hero-cta .btn{width:100%;justify-content:center;padding:12px 14px;font-size:.72rem;gap:7px}
  /* Only the primary: it is the one variant without a border, so it sat 1px
     shorter than the other two. Applied to .btn it also wiped the ghost's. */
  .hero-cta .btn-primary{border:1px solid transparent}
  .hero-cta .btn svg,
  .hero-cta .btn-demo-play{display:none}
  .hero-cta .btn-demo{
    padding-left:14px;
    background:var(--accent-glow);
    border-color:var(--line-strong);
    color:var(--accent-lt);
  }

  /* The links were what held the two ends of the bar apart — .nav-links carries
     flex:1. Hiding them left the logo and the burger bunched together on the
     left with the rest of the bar empty, so the bar takes over the spacing. */
  .nav{justify-content:space-between}
  .nav-links{display:none}
  .nav-burger{display:block}
  .hl-stats{grid-template-columns:repeat(3,1fr)}
}

/* Two labels, one button: the long one is the real call to action, the short
   one exists so the burger still fits on a 390px bar. */
.lbl-short{display:none}

@media (max-width:560px){
  .nav{gap:12px;padding-inline:14px}
  .nav-social{display:none}
  .lbl-long{display:none}
  .lbl-short{display:inline}
  .nav-logo{font-size:1.05rem}
}

@media (max-width:640px){
  /* No phone width here: the <=860 rule already sizes it, and an equal-
     specificity rule further down the file would silently win. */
  .wrap,.wrap-narrow{width:calc(100% - 32px)}
  .field-row{grid-template-columns:1fr}
  .foot{grid-template-columns:1fr;gap:28px}
  .hero{padding-inline:20px}
  .plan{padding:24px 20px}
  .perf-nums{grid-template-columns:repeat(2,1fr)}
}

/* Sharing the site and following the site are different asks, so the row sits
   apart from the brand social marks rather than beside them. */
.foot-share{margin-top:22px;flex-direction:column;align-items:flex-start;gap:9px}

/* Under the verdict on Market Pulse — the one piece of the site people
   actually forward. Ruled off so it reads as an action, not as article body. */
.share-inline{
  padding-top:18px;border-top:1px solid var(--line-soft);
}
/* Not space-between: across a 1240px column that parks the word at one end and
   the buttons at the other, and they stop reading as one control. */
.share-inline .share-lbl{margin-right:2px}

/* Market Pulse — verdict + breadth.
   These were inline styles, which no media query can reach: on a 390px screen
   the 1fr column came out at ~145px, and 52px of that was padding. */
.mp-verdict{
  display:grid;
  grid-template-columns:minmax(0,1.4fr) minmax(0,1fr);
  gap:16px;margin-bottom:20px;
}
.mp-panel{
  padding:26px;border-radius:var(--r-lg);
  border:1px solid var(--line-soft);
}
.mp-breadth{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;margin-bottom:16px}

@media (max-width:860px){
  .mp-verdict{grid-template-columns:minmax(0,1fr)}
}
@media (max-width:560px){
  .mp-panel{padding:20px}
  .mp-breadth{gap:8px}
}
