/* Penny — pre-launch page.

   A money app has to look like somewhere you would keep a bank statement,
   so this is paper: warm off-white, one green, generous margins, nothing
   that moves unless you scroll past it. The whole palette is four colours
   and there is no gradient anywhere. */

:root {
  --paper: #faf8f5;
  --card: #ffffff;
  --line: #e7e1d8;
  --ink: #1a1714;
  --mid: #5f574e;
  --soft: #8d857b;
  --green: #1f6f4f;
  --green-tint: #eaf3ee;
  --wrap: 68rem;
  --r: 16px;
}

* {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: 'Inter', 'Segoe UI', system-ui, -apple-system, sans-serif;
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

a {
  color: inherit;
}

h1,
h2,
h3 {
  margin: 0;
  letter-spacing: -0.022em;
  line-height: 1.12;
  font-weight: 700;
}

p {
  margin: 0;
}

.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin: 0 auto;
  padding: 0 24px;
}

.eyebrow {
  margin: 0;
  font-family: 'IBM Plex Mono', ui-monospace, 'SFMono-Regular', Menlo, monospace;
  font-size: 11.5px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--soft);
}

/* ── header ───────────────────────────────────────────── */
.top {
  position: sticky;
  top: 0;
  z-index: 20;
  border-bottom: 1px solid var(--line);
  background: rgba(250, 248, 245, 0.88);
  backdrop-filter: blur(10px);
}

.top .wrap {
  display: flex;
  align-items: center;
  gap: 16px;
  height: 64px;
}

.mark {
  display: flex;
  align-items: center;
  gap: 10px;
  font-weight: 700;
  letter-spacing: -0.02em;
  text-decoration: none;
}

.coin {
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: var(--green);
  color: #fff;
  font-size: 14px;
  font-weight: 700;
}

.pill {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 5px 11px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--card);
  font-family: 'IBM Plex Mono', ui-monospace, monospace;
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--mid);
}

.pill .dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--green);
}

.top .pill {
  margin-left: auto;
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 46px;
  padding: 0 20px;
  border: 1px solid var(--green);
  border-radius: 12px;
  background: var(--green);
  color: #fff;
  font: inherit;
  font-size: 15px;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
  transition: transform 0.15s ease, opacity 0.15s ease;
}

.btn:hover {
  opacity: 0.9;
}

.btn:active {
  transform: scale(0.985);
}

.btn.ghost {
  border-color: var(--line);
  background: var(--card);
  color: var(--ink);
}

/* ── hero ─────────────────────────────────────────────── */
.hero {
  padding: 84px 0 64px;
}

.hero h1 {
  max-width: 17ch;
  margin-top: 18px;
  font-size: clamp(2.3rem, 6vw, 3.9rem);
}

.lede {
  max-width: 56ch;
  margin-top: 20px;
  font-size: clamp(1.02rem, 1.6vw, 1.19rem);
  color: var(--mid);
}

.cta-row {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 30px;
}

/* The one picture on the page: a question, and the answer under it. It is
   static markup, not a screenshot — nothing here has to stay in sync with
   a build that is still changing every week. */
.demo {
  max-width: 460px;
  margin-top: 46px;
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--card);
  overflow: hidden;
}

.demo-bar {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 12px 16px;
  border-bottom: 1px solid var(--line);
}

.demo-bar span {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--line);
}

.demo-bar b {
  margin-left: auto;
  font-family: 'IBM Plex Mono', ui-monospace, monospace;
  font-size: 10.5px;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--soft);
}

.demo-body {
  padding: 18px 16px 20px;
}

.ask {
  padding: 11px 14px;
  border-radius: 12px 12px 4px 12px;
  background: var(--green-tint);
  color: var(--ink);
  font-size: 14.5px;
  font-weight: 500;
}

.answer {
  margin-top: 12px;
  font-size: 14.5px;
  color: var(--mid);
}

.answer b {
  color: var(--ink);
}

.rows {
  margin: 12px 0 0;
  padding: 0;
  list-style: none;
  border-top: 1px solid var(--line);
}

.rows li {
  display: flex;
  gap: 12px;
  padding: 9px 0;
  border-bottom: 1px solid var(--line);
  font-size: 13.5px;
}

.rows li span:first-child {
  flex: 1;
  min-width: 0;
  color: var(--mid);
}

.rows li span:last-child {
  font-variant-numeric: tabular-nums;
  font-weight: 600;
}

/* ── sections ─────────────────────────────────────────── */
section {
  padding: 64px 0;
  border-top: 1px solid var(--line);
}

.h2 {
  max-width: 22ch;
  margin-top: 14px;
  font-size: clamp(1.6rem, 3.4vw, 2.3rem);
}

.sub {
  max-width: 58ch;
  margin-top: 14px;
  color: var(--mid);
}

.grid {
  display: grid;
  gap: 16px;
  margin-top: 36px;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
}

.card {
  padding: 24px;
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--card);
}

.card h3 {
  font-size: 17px;
}

.card p {
  margin-top: 9px;
  font-size: 14.5px;
  color: var(--mid);
}

.num {
  display: block;
  margin-bottom: 12px;
  font-family: 'IBM Plex Mono', ui-monospace, monospace;
  font-size: 11.5px;
  letter-spacing: 0.14em;
  color: var(--green);
}

/* The promises list. Deliberately plain: these are the four sentences the
   whole product is accountable to, so they get no decoration to hide behind. */
.promises {
  margin: 32px 0 0;
  padding: 0;
  list-style: none;
  border-top: 1px solid var(--line);
}

.promises li {
  display: flex;
  gap: 16px;
  align-items: flex-start;
  padding: 18px 0;
  border-bottom: 1px solid var(--line);
}

.promises b {
  flex: 0 0 clamp(9rem, 22vw, 13rem);
  font-size: 15px;
}

.promises span {
  flex: 1;
  min-width: 0;
  color: var(--mid);
  font-size: 14.5px;
}

/* ── the withheld panel ───────────────────────────────── */
.held {
  padding: 28px;
  border: 1px dashed var(--line);
  border-radius: var(--r);
  background: var(--card);
  margin-top: 30px;
}

.held ul {
  margin: 18px 0 0;
  padding: 0;
  list-style: none;
}

.held li {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 11px 0;
  border-bottom: 1px solid var(--line);
  font-size: 14.5px;
}

.held li:last-child {
  border-bottom: 0;
}

.held li b {
  flex: 0 0 clamp(10rem, 26vw, 15rem);
  font-weight: 600;
}

/* Blacked out with a solid bar rather than blurred text, because there is
   no text underneath to leak in the first place. */
.redact {
  flex: 1;
  height: 11px;
  border-radius: 3px;
  background: repeating-linear-gradient(
    90deg,
    var(--ink) 0,
    var(--ink) 22px,
    transparent 22px,
    transparent 27px
  );
  opacity: 0.82;
}

/* ── close ────────────────────────────────────────────── */
.close {
  padding: 72px 0 80px;
  text-align: center;
}

.close .h2 {
  margin-inline: auto;
}

.close .sub {
  margin-inline: auto;
}

.close .cta-row {
  justify-content: center;
}

footer {
  padding: 24px 0 40px;
  border-top: 1px solid var(--line);
}

footer .wrap {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 22px;
  font-size: 13px;
  color: var(--soft);
}

footer .wrap span:last-child {
  margin-left: auto;
}

/* ── motion ───────────────────────────────────────────── */
.rise {
  opacity: 0;
  transform: translateY(14px);
  animation: rise 0.6s cubic-bezier(0.22, 0.68, 0.3, 1) forwards;
}

@keyframes rise {
  to {
    opacity: 1;
    transform: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  .rise {
    animation: none;
    opacity: 1;
    transform: none;
  }
  * {
    transition: none !important;
  }
}

/* ══════════════════════════════════════════════════════
   Scroll choreography

   Content arrives as you reach it. The transform is 14px and the
   duration is a little over half a second — enough to be felt, short
   enough that a reader scrolling quickly never waits for the page.
   ══════════════════════════════════════════════════════ */
[data-reveal] {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 0.62s cubic-bezier(0.22, 0.68, 0.3, 1),
    transform 0.62s cubic-bezier(0.22, 0.68, 0.3, 1);
  will-change: opacity, transform;
}

[data-reveal].is-in {
  opacity: 1;
  transform: none;
  will-change: auto;
}

/* ── the hero visual ──────────────────────────────────
   Penny has no screenshot on this page on purpose: the build changes
   weekly and a stale picture is worse than none. What is drawn instead
   is the one moment the product exists for — a month, split up, with
   the answer already worked out. */
.hero-wrap {
  display: grid;
  gap: 44px;
  align-items: center;
}

@media (min-width: 940px) {
  .hero-wrap {
    grid-template-columns: minmax(0, 1.06fr) minmax(0, 0.94fr);
    gap: 56px;
  }
}

.shot {
  position: relative;
  padding: 22px;
  border: 1px solid var(--line);
  border-radius: 24px;
  background: var(--card);
  box-shadow: 0 30px 70px -46px rgba(26, 23, 20, 0.55);
}

/* a soft wash behind the panel, the only gradient on the page */
.shot::before {
  content: '';
  position: absolute;
  inset: -14% -10% -22%;
  z-index: -1;
  border-radius: 40px;
  background: radial-gradient(58% 52% at 62% 28%, rgba(31, 111, 79, 0.16), transparent 72%),
    radial-gradient(46% 46% at 20% 82%, rgba(214, 187, 143, 0.22), transparent 72%);
  filter: blur(6px);
}

.shot-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding-bottom: 16px;
  border-bottom: 1px solid var(--line);
}

.shot-head b {
  font-size: 15px;
}

.shot-head .tiny {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  border-radius: 999px;
  background: var(--green-tint);
  font-family: 'IBM Plex Mono', ui-monospace, monospace;
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--green);
}

.shot-head .tiny i {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--green);
  animation: blip 2.4s ease-in-out infinite;
}

@keyframes blip {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.25; }
}

.donut-row {
  display: flex;
  align-items: center;
  gap: 20px;
  padding: 20px 0 4px;
}

.donut {
  flex: none;
  width: 132px;
  height: 132px;
  transform: rotate(-90deg);
}

.donut circle {
  fill: none;
  stroke-width: 15;
  stroke-linecap: round;
}

/* Each arc draws itself in sequence once the panel is on screen. The
   dash offsets are set here rather than in script so the shape is
   correct even before any JavaScript has run. */
.donut .seg {
  stroke-dasharray: 314;
  animation: draw 1.15s cubic-bezier(0.22, 0.68, 0.3, 1) forwards;
}

/* Offsets are CUMULATIVE, and the arcs are painted longest-first so the
   shorter ones sit on top: three arcs that each start at twelve o'clock
   would otherwise draw over one another and only the last would show.
   Circumference is 314; the shares are 45.6 / 23.8 / 13.5 per cent of
   the month, so the stops are 143, 218 and 260 of arc drawn. */
.donut .s1 { stroke: var(--green); stroke-dashoffset: 314; --to: 171; animation-delay: 0.55s; }
.donut .s2 { stroke: #6ba58c; stroke-dashoffset: 314; --to: 96; animation-delay: 0.4s; }
.donut .s3 { stroke: #b8cfc3; stroke-dashoffset: 314; --to: 54; animation-delay: 0.25s; }

@keyframes draw {
  to { stroke-dashoffset: var(--to); }
}

.donut-mid {
  min-width: 0;
}

.donut-mid .big {
  font-size: 27px;
  font-weight: 700;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
}

.donut-mid .cap {
  margin-top: 2px;
  font-size: 13px;
  color: var(--soft);
}

.legend {
  margin: 14px 0 0;
  padding: 0;
  list-style: none;
}

.legend li {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 0;
  border-top: 1px solid var(--line);
  font-size: 13.5px;
}

.legend i {
  width: 9px;
  height: 9px;
  border-radius: 3px;
  flex: none;
}

.legend span {
  flex: 1;
  min-width: 0;
  color: var(--mid);
}

.legend b {
  font-variant-numeric: tabular-nums;
}

/* ── card artwork ─────────────────────────────────────
   A small drawn vignette per card. They are line art rather than
   illustration-with-a-scene: at 44px tall an illustration is mud, and
   a line reads. */
.art {
  display: block;
  width: 100%;
  height: 62px;
  margin-bottom: 16px;
  overflow: visible;
}

.art .ln {
  fill: none;
  stroke: var(--green);
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.art .ln.dim {
  stroke: var(--line-strong, #d8d1c6);
}

.art .fillsoft {
  fill: var(--green-tint);
  stroke: none;
}

/* the trace draws itself when the card arrives */
[data-reveal] .art .trace {
  stroke-dasharray: 240;
  stroke-dashoffset: 240;
}

[data-reveal].is-in .art .trace {
  animation: trace 1.4s 0.2s cubic-bezier(0.3, 0.7, 0.3, 1) forwards;
}

@keyframes trace {
  to { stroke-dashoffset: 0; }
}

@media (prefers-reduced-motion: reduce) {
  [data-reveal] {
    opacity: 1;
    transform: none;
    transition: none;
  }
  .donut .seg,
  .shot-head .tiny i,
  [data-reveal].is-in .art .trace {
    animation: none;
  }
  .donut .s1 { stroke-dashoffset: 171; }
  .donut .s2 { stroke-dashoffset: 96; }
  .donut .s3 { stroke-dashoffset: 54; }
  [data-reveal] .art .trace { stroke-dashoffset: 0; }
}
