/* ---------------------------------------------------------------------------
   FocusEarn.

   Black is the ground and light is the only other material. There is no hue
   anywhere: hierarchy is carried by three tiers of white - pure white for what
   you read first, off-white for the line under it, grey for labels - and by the
   plate behind them, which is graded rather than desaturated so the rock layers
   stay separated and the blacks stay black.

   Typography is editorial rather than SaaS: a grotesk held at 500 instead of
   700, an italic serif carrying the payoff word so contrast does the emphasis
   instead of weight, sentence case throughout, and rules instead of pills.

   LAYOUT. Every scene is the same column, in the same place, built the same
   way: words, a hairline rule, then the product surface those words describe.
   The column occupies the quiet left third the destinations were chosen for;
   the plate keeps the other two. Nothing is centred over the lit part of the
   frame and nothing floats on its own, which is what made the earlier scenes
   read as scattered widgets rather than a designed page.
--------------------------------------------------------------------------- */

:root{
  /* Strictly neutral: R, G and B are equal in every one of these, so nothing
     can drift warm or cool on a wide-gamut display. */
  --bg:#000000;
  --text:#FFFFFF;
  --dim:#E4E4E4;
  --muted:#8E8E8E;

  --edge:rgba(255,255,255,.18);
  --hair:rgba(255,255,255,.13);

  /* The one measure everything on the page is built from. */
  --gut:clamp(22px,7vw,120px);
  --col:min(540px,46vw);

  --ease:cubic-bezier(.22,.61,.36,1);
  --grotesk:"Schibsted Grotesk",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;
  --serif:"Instrument Serif",Georgia,"Times New Roman",serif;
}

*,*::before,*::after{box-sizing:border-box}

html{background:var(--bg)}

body{
  margin:0;
  background:var(--bg);
  color:var(--text);
  font-family:var(--grotesk);
  -webkit-font-smoothing:antialiased;
  overflow-x:hidden;
}

/* The document never scrolls. The wheel is an event, not a position, and the
   last destination is the end of the sequence rather than a door out of it -
   letting the page scroll past the plate to the footer is what "it takes you
   out of the animation" was describing. */
body.seq-locked{overflow:hidden;height:100%}

/* One viewport. There is no scroll runway any more: scenes are navigated,
   not scrubbed through. */
.sequence{height:100svh;position:relative;overflow:hidden}

.stage{
  position:absolute; inset:0;
  overflow:hidden;
  background:var(--bg);
}

/* ---- plate ---------------------------------------------------------------- */

/* The wrapper carries the camera move so both layers get it identically; the
   layers themselves only cross-fade. */
.plate{
  position:absolute; inset:0;
  transform:scale(1.06);
  will-change:transform;
}
.stage__video,.stage__hold{
  position:absolute; inset:0;
  width:100%; height:100%;
  object-fit:cover;
}
/* Sits over the travel video and is only raised once it is playing the very
   frame the video is parked on, so the swap reads as the shot settling rather
   than as a cut. */
.stage__hold{opacity:0}

/* Darkens the column side hard and lets the right side keep its light, so the
   words never end up sitting on a moving highlight. */
.stage__grade{
  position:absolute; inset:0; pointer-events:none;
  background:
    linear-gradient(to right, rgba(0,0,0,.94) 0%, rgba(0,0,0,.78) 26%, rgba(0,0,0,.22) 55%, transparent 76%),
    radial-gradient(120% 90% at 66% 45%, transparent 32%, rgba(0,0,0,.5) 80%, #000000 100%),
    linear-gradient(to bottom, rgba(0,0,0,.55) 0%, transparent 24%, transparent 66%, rgba(0,0,0,.8) 100%);
}

/* ---- chrome --------------------------------------------------------------- */

/* Glass, but the restrained kind: the blur and a single hairline do the work.
   No gradient fill and no bloom - over a moving black plate those read as the
   SaaS chrome the rest of the page avoids. It floats clear of the edges so the
   footage runs behind it uninterrupted. */
.nav{
  position:fixed; top:16px; left:50%; transform:translateX(-50%);
  z-index:40;
  display:flex; align-items:center; gap:14px;
  padding:8px 8px 8px 16px;
  border-radius:12px;
  border:1px solid rgba(255,255,255,.14);
  background:rgba(255,255,255,.045);
  backdrop-filter:blur(22px) saturate(1.15);
  -webkit-backdrop-filter:blur(22px) saturate(1.15);
  box-shadow:0 24px 60px -28px rgba(0,0,0,.95), inset 0 1px 0 rgba(255,255,255,.09);
  max-width:calc(100vw - 32px);
}

.nav__brand{
  display:flex; align-items:center; gap:9px;
  color:var(--text); text-decoration:none;
  font-size:15px; font-weight:600; letter-spacing:-.02em;
  white-space:nowrap;
}

.nav__rule{width:1px; height:20px; background:rgba(255,255,255,.14); flex:none}

/* The scene list. This replaced a dot rail on the right edge - once the bar can
   name the destinations and show which one you are on, a second position
   indicator on the opposite side is just two navigations for one sequence. */
.nav__links{display:flex; align-items:center; gap:2px}
.nav__links a{
  position:relative;
  padding:0 11px; height:30px;
  display:inline-flex; align-items:center;
  border-radius:7px;
  color:var(--muted); text-decoration:none;
  font-size:13px; font-weight:500; letter-spacing:-.01em;
  transition:color .2s var(--ease), background .2s var(--ease);
}
.nav__links a:hover{color:var(--text); background:rgba(255,255,255,.06)}
.nav__links a.is-on{color:var(--text); background:rgba(255,255,255,.10)}

/* The address is a control, not a label - it copies. */
.nav__ca{
  display:flex; align-items:center; gap:8px;
  height:30px; padding:0 10px; border-radius:7px;
  border:1px solid transparent; background:transparent;
  font-family:var(--grotesk); font-size:12.5px; color:var(--muted);
  cursor:pointer; white-space:nowrap;
  transition:background .2s var(--ease), border-color .2s var(--ease), color .2s var(--ease);
}
.nav__ca:hover{background:rgba(255,255,255,.06); border-color:rgba(255,255,255,.13); color:var(--text)}
.nav__ca-key{
  font-size:10px; font-weight:600; letter-spacing:.12em; color:var(--muted);
}
.nav__ca-val{color:var(--dim); font-variant-numeric:tabular-nums}
.nav__ca-hint{
  font-size:10.5px; color:var(--muted); opacity:0;
  transition:opacity .2s var(--ease);
}
.nav__ca:hover .nav__ca-hint{opacity:1}
.nav__ca.is-copied .nav__ca-hint{opacity:1; color:var(--text)}
/* The mark is a white cut-out with a genuinely transparent counter, so the
   plate shows through it rather than sitting behind a black tile. */
.wordmark__mark{
  width:19px; height:18px; flex:none;
  background:url("../assets/img/focusearn-mark.png") center/contain no-repeat;
}

/* ---- the column ----------------------------------------------------------- */

.beat{
  position:absolute; inset:0; z-index:20;
  display:flex; align-items:center;
  padding:0 var(--gut);
  will-change:transform,opacity;
}

.col{width:var(--col); max-width:100%}

/* The opening scene carries no panel, so its column is measured by the headline
   rather than by a surface. At the panel width the display type broke "worth
   something." onto a line of its own. */
.beat--hero .col{width:min(680px,52vw)}

/* Hidden until JS sets their opening state, so nothing paints before the
   first frame is composed. */
.beat--focus,.beat--earn,.beat--claim,.beat--start{opacity:0}

/* Separates the words from the surface without drawing a box round either. */
.col__rule{
  height:1px; border:0; margin:30px 0 24px;
  background:rgba(255,255,255,.20);
}

/* ---- words ---------------------------------------------------------------- */

.display{
  margin:0;
  font-size:clamp(38px,6.2vw,88px);
  font-weight:500; line-height:1.04; letter-spacing:-.035em;
  text-wrap:balance;
}

.statement{
  margin:0;
  font-size:clamp(38px,5.4vw,76px);
  font-weight:500; line-height:1.02; letter-spacing:-.038em;
}

/* The payoff word carries the contrast: larger, lighter, italic serif. */
.display em,.statement em,.lede em{
  font-family:var(--serif);
  font-style:italic;
  font-weight:400;
  font-size:1.1em;
  letter-spacing:-.012em;
}
.lede em{color:var(--text)}

.lede{
  margin:20px 0 0;
  font-size:clamp(15.5px,1.35vw,18.5px); font-weight:400; color:var(--dim);
  letter-spacing:-.01em; line-height:1.5; max-width:34ch;
}

.cta-row{display:flex; align-items:center; gap:22px; margin-top:34px; flex-wrap:wrap}
.cta-note{font-size:13px; color:var(--muted)}

/* A rule, not a pill. These are <button> elements now, not links - as anchors
   their #hash targets asked the browser to scroll a locked document, which
   shunted the fixed stage out of place. Hence the element reset. */
.btn{
  display:inline-flex; align-items:center; justify-content:center; gap:10px;
  text-decoration:none; white-space:nowrap;
  background:none; border:0; padding:0; margin:0;
  font-family:var(--grotesk); cursor:pointer;
  font-size:15px; font-weight:500; letter-spacing:-.01em;
  color:var(--text);
  transition:color .25s var(--ease), border-color .25s var(--ease), gap .25s var(--ease), background .25s var(--ease);
}
.btn--rule{
  padding:0 0 7px;
  border-bottom:1px solid rgba(255,255,255,.42);
}
.btn--rule:hover{border-color:var(--text); color:#fff; gap:14px}
/* The arrow is the quiet half of the pair until you reach for it. */
.btn--rule span{color:var(--muted); transition:color .25s var(--ease)}
.btn--rule:hover span{color:var(--text)}

/* The one filled control on the page. White on black is the strongest a strictly
   monochrome palette can be, which is what a primary action wants. */
.btn--solid{
  height:30px; padding:0 14px; border-radius:7px;
  background:var(--text); color:#000;
  font-size:13.5px; font-weight:600; letter-spacing:-.01em;
}
.btn--solid:hover{background:var(--dim); color:#000}
/* Wider than the bar version, because on the final scene it is the whole point
   of the page rather than one control among several. */
.btn--wide{height:38px; padding:0 22px; font-size:14.5px}
/* The bar button is the fifth destination, so it marks itself when you are on it. */
.btn--solid.is-on{background:var(--dim)}
/* While it is reporting its own state it should not look like a live control. */
.btn.is-note{opacity:.75; cursor:default}
.btn--rule.is-note{border-color:rgba(255,255,255,.22)}

/* ---- product surfaces ------------------------------------------------------
   Flat, hairlined, small radius. No pill corners, no halo, no inset highlight:
   over a moving plate those read as stock SaaS glass. The panel is black the
   plate shows through slightly, held down by a hairline rather than a fill. */

.panel{
  width:100%;
  padding:16px 18px 18px;
  border:1px solid var(--hair);
  border-radius:6px;
  background:rgba(0,0,0,.72);
  backdrop-filter:blur(18px) saturate(.85);
  box-shadow:0 30px 70px -34px rgba(0,0,0,.95);
  will-change:transform,opacity;
}

.panel__head{
  display:flex; align-items:center; justify-content:space-between; gap:14px;
  padding-bottom:14px; margin-bottom:16px;
  border-bottom:1px solid var(--hair);
}
.panel__label{
  font-size:11px; font-weight:500; color:var(--muted);
  letter-spacing:.09em; text-transform:uppercase;
}

.pill{
  display:inline-flex; align-items:center; gap:6px;
  height:22px; padding:0 9px; border-radius:4px;
  font-size:11px; font-weight:500; color:var(--muted);
  border:1px solid var(--hair); background:rgba(255,255,255,.03);
}
.pill--live{color:var(--text); border-color:rgba(255,255,255,.30)}
/* The only thing on the page that moves without being asked. It marks the one
   genuinely live element - the running session - so it earns the exception. */
.pill--live i{
  width:5px; height:5px; border-radius:50%; background:var(--text);
  animation:livePulse 2.6s ease-in-out infinite;
}
@keyframes livePulse{0%,100%{opacity:1}50%{opacity:.28}}

/* ---- session -------------------------------------------------------------- */

/* The ring sits beside its own explanation instead of alone in the middle of a
   card, so the panel reads as an instrument rather than a hero graphic. */
.session{display:flex; align-items:center; gap:24px}

.ring{position:relative; display:grid; place-items:center; flex:none}
.ring svg{width:130px; height:130px; transform:rotate(-90deg)}
.ring__track{fill:none; stroke:rgba(255,255,255,.08); stroke-width:6}
.ring__fill{
  fill:none; stroke:var(--text); stroke-width:6; stroke-linecap:round;
  stroke-dasharray:326.7; stroke-dashoffset:326.7;
}
.ring__readout{position:absolute; text-align:center}
/* Sized to the longest value it will ever hold - "$0.13999" at 20px sits
   inside the 130px ring with room, where the old 29px would have overflowed it
   the moment the readout stopped being a five-character clock. */
.ring__readout strong{
  display:block; font-size:20px; font-weight:500; letter-spacing:-.02em;
  font-variant-numeric:tabular-nums; line-height:1.15;
}
/* Direct child only: the "remaining" label. The digit spans live inside the
   <strong> and must keep its size, not the label's. */
.ring__readout > span{display:block; margin-top:3px; font-size:11px; color:var(--muted)}
.t-n{font-variant-numeric:tabular-nums}
.t-c{font-variant-numeric:normal; margin:0 -.085em}

.session__meta{display:grid; gap:9px}
.session__note{margin:0; font-size:16px; font-weight:500; letter-spacing:-.015em}
.session__sub{margin:0; font-size:12.5px; line-height:1.5; color:var(--muted)}

/* ---- reward --------------------------------------------------------------- */

.payout__sym{
  margin:0 0 6px;
  font-size:13px; font-weight:600; letter-spacing:.02em;
}
.payout__sym span{font-weight:400; color:var(--muted); letter-spacing:-.01em; margin-left:8px}

.payout__amt{
  margin:0;
  font-size:clamp(30px,3.1vw,42px); font-weight:500; letter-spacing:-.035em;
  /* No tabular figures here: this number never changes, so it gains nothing,
     and tabular pads the comma and the decimal point out to a full digit width
     which opens a gap either side of both. */
}
.payout__plus{font-variant-numeric:normal}
.payout__unit{font-size:.4em; font-weight:400; color:var(--muted); letter-spacing:-.01em; margin-left:4px}

.payout__foot{
  display:flex; align-items:center; justify-content:space-between;
  margin-top:16px; padding-top:13px; border-top:1px solid var(--hair);
  font-size:12px; color:var(--muted);
}

/* ---- get the app ----------------------------------------------------------- */

.get__name{margin:0; font-size:clamp(20px,2.1vw,26px); font-weight:500; letter-spacing:-.025em}
.get__name span{color:var(--muted); font-weight:400}
/* No tabular figures: this face pads the decimal point to a full digit width,
   which rendered a fixed label as "12 . 6 MB". Nothing here counts, so nothing
   here needs the alignment tabular buys. */
.get__meta{margin:6px 0 0; font-size:12.5px; color:var(--muted)}
.get__foot{
  display:flex; align-items:center; justify-content:space-between;
  margin-top:16px; padding-top:13px; border-top:1px solid var(--hair);
  font-size:12px; color:var(--muted);
}

/* ---- portfolio ------------------------------------------------------------- */

.port__value{
  margin:0 0 16px;
  font-size:clamp(32px,3.2vw,42px); font-weight:500; letter-spacing:-.035em;
}
/* The currency mark and the cents are the quiet parts; the integer is the
   number. This selected every span in here, which was fine until the integer
   needed a span of its own so it could be counted into place - at which point
   the headline figure quietly shrank to match its own decimals. */
.port__value > span:first-child,.port__cents{color:var(--muted); font-size:.52em}

.port__list{list-style:none; margin:0; padding:0; display:grid; gap:10px}
/* No tabular figures: the grid tracks already align these columns, the values
   never change, and this face pads the decimal point out to a full digit width
   when tabular is on - which reads as "0 . 0412". Tabular is kept only for the
   countdown, which does change and would otherwise jitter. */
.port__list li{
  display:grid; grid-template-columns:1fr auto 62px; gap:14px; align-items:center;
  font-size:13px;
}
.sym{font-weight:500; letter-spacing:.01em}
.qty{color:var(--muted)}
.chg{font-size:12px; text-align:right}
/* Direction is in the sign, so it does not need a colour to carry it. The
   gainers simply sit at full white and the loser drops back a tier. */
.chg.up{color:var(--text)}
.chg.dn{color:var(--muted)}

.port__foot{
  margin-top:16px; padding-top:13px; border-top:1px solid var(--hair);
  font-size:12px; color:var(--muted);
}

/* ---- sequence chrome ------------------------------------------------------- */

/* Bottom right, opposite the column. Centred it collided with the tallest
   panel; on the left it sat underneath one. */
.hint{
  position:absolute; right:var(--gut); bottom:26px;
  z-index:30; margin:0;
  font-size:12px; color:var(--muted); letter-spacing:.02em;
  animation:hintPulse 2.8s ease-in-out infinite;
}
body.seq-done .hint{opacity:0; pointer-events:none}
@keyframes hintPulse{0%,100%{opacity:.35}50%{opacity:.8}}

/* ---- foot ----------------------------------------------------------------- */

.foot{
  position:relative; z-index:5;
  display:flex; align-items:center; justify-content:space-between; gap:16px; flex-wrap:wrap;
  padding:30px var(--gut);
  border-top:1px solid var(--hair);
  font-size:12.5px; color:var(--muted);
  background:var(--bg);
}

/* ---- short viewports -------------------------------------------------------
   The tallest scene is words + rule + portfolio + button. On a laptop that is
   comfortable; below about 760px the air has to come out rather than let the
   column run off the top and bottom of the frame. */

@media (max-height:760px){
  .statement{font-size:clamp(34px,4.4vw,56px)}
  .display{font-size:clamp(34px,5vw,66px)}
  .lede{margin-top:14px}
  .col__rule{margin:20px 0 16px}
  .cta-row{margin-top:22px}
  .ring svg{width:108px; height:108px}
  .ring__readout strong{font-size:17px}
}

/* ---- phones ---------------------------------------------------------------
   Not a shrunk desktop: the column becomes the full width, the grade stops
   favouring one side because there is no side left, and the session panel
   gives up sitting the ring beside its text. JS separately gives the plate a
   small looping file instead of a seekable master. */

@media/* The bar carries four things; below these widths they stop fitting, and the
   scene links matter more than the address. */
@media (max-width:1024px){
  .nav__ca{display:none}
}
@media (max-width:860px){
  .nav__links,.nav__rule{display:none}
}

@media (max-width:820px){
  :root{--col:100%}
  .stage__grade{
    background:
      linear-gradient(to bottom, rgba(0,0,0,.55) 0%, rgba(0,0,0,.35) 30%, rgba(0,0,0,.8) 72%, #000000 100%),
      radial-gradient(120% 80% at 50% 38%, transparent 30%, rgba(0,0,0,.6) 82%);
  }
  .session{flex-direction:column; align-items:flex-start; gap:16px}
  .session__meta{gap:7px}
  .lede{max-width:none}
  .hint{right:22px; bottom:18px}
}

/* ---- reduced motion -------------------------------------------------------
   No lock, no transitions, no plate. The sequence becomes an ordinary stacked
   page with every scene legible. */

@media (prefers-reduced-motion:reduce){
  body.seq-locked{overflow:auto;height:auto}
  .sequence{height:auto}
  .stage{position:relative; height:auto; min-height:0; padding:14vh 0}
  .stage__video{display:none}
  .stage::before{
    content:""; position:absolute; inset:0;
    background:url("../assets/img/hero-plate.jpg") center/cover no-repeat;
    opacity:.35;
  }
  .beat{position:relative; inset:auto; opacity:1 !important; transform:none !important; padding:11vh var(--gut)}
  .beat--focus,.beat--earn,.beat--claim,.beat--start{opacity:1 !important}
  .nav{position:relative; left:auto; transform:none; margin:16px auto; max-width:none}
  .panel{transform:none !important; opacity:1 !important}
  .ring__fill{stroke-dashoffset:137 !important}
  .hint{display:none}
  .pill--live i{animation:none}
}
