/*
 * punishapp.com
 *
 * EVERY VALUE HERE IS THE APP'S. The colours are the Night palette in
 * app/src/theme.ts, the type is Source Serif 4 (self-hosted, renamed; see
 * fonts/OFL.txt), the pill and chip are components/ui.tsx's, the card edge is
 * glassCard(), and the two pools of light are components/Ground.tsx's POOLS
 * and SPOTS. If the app changes one of these, change it here too.
 */

@font-face {
  font-family: 'Punish Serif';
  src: url('fonts/punish-serif-400.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Punish Serif';
  src: url('fonts/punish-serif-400i.woff2') format('woff2');
  font-weight: 400;
  font-style: italic;
  font-display: swap;
}
@font-face {
  font-family: 'Punish Serif';
  src: url('fonts/punish-serif-600.woff2') format('woff2');
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Punish Serif';
  src: url('fonts/punish-serif-700.woff2') format('woff2');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

:root {
  /* theme.ts NIGHT */
  --bg: #0e1110;
  --surface: #171b19;
  --text: #d8e6dc;
  --divider: rgba(216, 230, 220, 0.16);
  --n200: #212724;
  --n300: #2b332f;
  --n400: #3b4641;
  --n500: #57655e;
  --n600: #7d8f85;
  --n700: #9aaba1;
  --n800: #b7c5bc;
  --keep: #45d17a;
  --warn: #ffcc42;
  --neg: #ff5f56;
  --loop: #fbcb0f;
  --pos: #57b6e0;
  /* theme.ts `mark` is #b48ce8; lifted to hold 5:1 at a light's centre, where #b48ce8 falls to 4.2:1. */
  --mark: #c4a2ef;

  --pad: 20px;
  --measure: 34rem;
  --serif: 'Punish Serif', 'Source Serif 4', Georgia, 'Times New Roman', serif;

  color-scheme: dark;
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--bg);
  /*
   * n800, a step brighter than the app's body n700. The app's pools sit on a
   * phone; here they are a metre wide, and a line of copy crossing the green
   * one's peak has to hold 4.5:1 there too. Every muted colour moves up one
   * step for the same reason: n600 measures 3.5:1 at a pool's centre.
   */
  color: var(--n800);
  font-family: var(--serif);
  font-size: 1.0625rem;
  line-height: 1.6;
  font-kerning: normal;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

/* ------------------------------------------------------------ the ground */

/*
 * Ground.tsx, in CSS. The wash (cool above, warm below), two pools of light
 * (keep green and warn amber, rx 0.62 and ry 0.21 of the screen), a vignette
 * that pulls the edges back to the ground, and the app's own grain over it.
 * Fixed to the viewport, as the app's is fixed to the screen.
 */
.ground {
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  overflow: hidden;
  background: linear-gradient(
    to bottom,
    rgba(12, 18, 22, 0.55) 0%,
    rgba(14, 17, 16, 0.27) 55%,
    rgba(22, 19, 16, 0.55) 100%
  ), var(--bg);
}

.pool {
  position: absolute;
  left: 0;
  top: 0;
  /* CIRCLES, NOT STRETCHED (owner, 2026-09-28). The app's pools are ellipses
     sized to the phone; on a page they stretched with the window, wide on a
     desktop and tall on a phone. One size from the shorter side keeps them
     round on every screen. */
  width: 84vmin;
  height: 84vmin;
  margin-left: -42vmin;
  margin-top: -42vmin;
  border-radius: 50%;
  transform: translate(var(--x), var(--y));
  transition: transform 900ms cubic-bezier(0.65, 0, 0.35, 1);
  will-change: transform;
}

/* BLOOM_ALPHA 0.16 × each pool's weight; the 0.45 stop at 30% of it. */
.pool--a {
  --x: 30vw;
  --y: 28vh;
  background: radial-gradient(
    closest-side,
    rgba(69, 209, 122, 0.256) 0%,
    rgba(69, 209, 122, 0.077) 45%,
    rgba(69, 209, 122, 0) 100%
  );
}

.pool--b {
  --x: 72vw;
  --y: 60vh;
  background: radial-gradient(
    closest-side,
    rgba(255, 204, 66, 0.208) 0%,
    rgba(255, 204, 66, 0.062) 45%,
    rgba(255, 204, 66, 0) 100%
  );
}

/* The vignette at full strength over the pools, the grain at 0.035 over everything. */
.ground::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 1;
  background: radial-gradient(120% 80% at 50% 38%, rgba(0, 0, 0, 0) 40%, rgba(0, 0, 0, 0.45) 100%);
}
.ground::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 2;
  background: url('img/grain.png') repeat;
  background-size: 96px 96px;
  opacity: 0.035;
}

@media (prefers-reduced-motion: reduce) {
  .pool {
    transition: none;
  }
}

/* ------------------------------------------------------------ type */

h1,
h2,
h3 {
  font-weight: 600;
  color: var(--text);
  margin: 0;
  text-wrap: balance;
}

h1 {
  font-size: clamp(2.35rem, 8.4vw, 4.6rem);
  line-height: 1.06;
  letter-spacing: -0.012em;
}

h2 {
  font-size: clamp(1.9rem, 5.6vw, 3rem);
  line-height: 1.12;
  letter-spacing: -0.008em;
}

h3 {
  font-size: clamp(1.4rem, 3.6vw, 1.85rem);
  line-height: 1.2;
}

p {
  margin: 0 0 1em;
  max-width: var(--measure);
}

/* ui.tsx rich(): **bold** is semibold in full ink. */
strong {
  font-weight: 600;
  color: var(--text);
}

/*
 * ui.tsx rich(): ==highlight== is "colour and weight, no band": semibold in
 * the plum `mark` token. The browser's yellow band is exactly what the app
 * removed.
 */
mark {
  background: none;
  color: var(--mark);
  font-weight: 600;
}

/* Icon.tsx: 24-unit paths, 1.8 stroke, round caps and joins, one colour. */
.ic {
  width: 18px;
  height: 18px;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
  overflow: visible;
}

em {
  font-style: italic;
}

a {
  color: var(--text);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
  text-decoration-color: var(--n500);
}
a:hover {
  text-decoration-color: var(--text);
}

:focus-visible {
  outline: 2px solid var(--warn);
  outline-offset: 3px;
  border-radius: 4px;
}

/* ui.tsx Kicker: bold, tracked, muted. Used once on the whole page, on purpose. */
.kicker {
  display: block;
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--n700);
  margin: 0 0 0.9rem;
}

/* ui.tsx Italic */
.aside {
  font-style: italic;
  color: var(--n700);
  line-height: 1.6;
}

.skip {
  position: absolute;
  left: -999px;
  top: 8px;
  background: var(--text);
  color: var(--bg);
  padding: 8px 14px;
  border-radius: 999px;
  z-index: 10;
}
.skip:focus {
  left: 8px;
}

/* ------------------------------------------------------------ layout */

.wrap {
  width: 100%;
  max-width: 72rem;
  margin: 0 auto;
  padding: 0 var(--pad);
}

@media (min-width: 720px) {
  :root {
    --pad: 40px;
  }
}

/* ------------------------------------------------------------ header */

.top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding-top: 22px;
  padding-bottom: 22px;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  text-decoration: none;
  color: var(--text);
  font-weight: 600;
  font-size: 1.3rem;
  line-height: 1;
}

.brand img {
  width: 30px;
  height: 30px;
  border-radius: 8px;
}

.top__note {
  font-size: 0.9rem;
  color: var(--n700);
  text-align: right;
}

/* ------------------------------------------------------------ hero */

.hero {
  display: grid;
  gap: 40px;
  padding-top: 28px;
  padding-bottom: 72px;
}

.hero h1 {
  max-width: 13ch;
}

.hero__lede {
  font-size: 1.2rem;
  color: var(--n800);
  margin-top: 1.4rem;
  max-width: 31rem;
}

.hero__aside {
  margin-top: 0.4rem;
  max-width: 30rem;
}

.hero__cta {
  margin-top: 2rem;
  max-width: 24rem;
}

.hero__shot {
  justify-self: center;
  width: min(100%, 340px);
}

@media (min-width: 900px) {
  .hero {
    grid-template-columns: minmax(0, 1.25fr) minmax(0, 0.75fr);
    align-items: center;
    gap: 64px;
    padding-top: 56px;
    padding-bottom: 120px;
  }
  .hero__shot {
    justify-self: end;
    width: 100%;
    max-width: 360px;
  }
}

/* ------------------------------------------------------------ pills */

/* ui.tsx PillButton: 56 high, fully round, 1.5 border, semibold 17. */
.pill {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: 56px;
  padding: 0 26px;
  border-radius: 28px;
  border: 1.5px solid var(--text);
  font-family: var(--serif);
  font-weight: 600;
  font-size: 1.0625rem;
  line-height: 1.2;
  text-decoration: none;
  text-align: center;
}

.pill--fill {
  background: var(--text);
  color: var(--bg);
}

/* A promise, not a door: it looks like the app's pill and does not pretend to be pressable. */
.pill--soon {
  cursor: default;
}

.pill__play {
  width: 18px;
  height: 20px;
  flex: none;
}

.cta-note {
  font-size: 0.95rem;
  color: var(--n700);
  margin: 0.9rem 0 0;
}

/* ui.tsx Chip */
.chip {
  display: inline-block;
  padding: 9px 18px;
  border-radius: 999px;
  border: 1.5px solid var(--n400);
  color: var(--n700);
  font-size: 0.95rem;
  line-height: 1.3;
}
.chip--on {
  background: var(--text);
  border-color: var(--text);
  color: var(--bg);
  font-weight: 600;
}

/* ------------------------------------------------------------ screens */

/*
 * A real screen, cropped of its status bar, framed by glassCard()'s lit edge:
 * a hairline all round, brighter along the top, darker along the foot.
 */
.screen {
  margin: 0;
}

.screen img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 26px;
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-top-color: rgba(255, 255, 255, 0.3);
  border-bottom-color: rgba(0, 0, 0, 0.34);
  background: var(--surface);
  box-shadow: 0 30px 80px -30px rgba(0, 0, 0, 0.8);
}

.screen figcaption {
  font-size: 0.88rem;
  font-style: italic;
  color: var(--n700);
  margin-top: 12px;
  line-height: 1.5;
}

/* ------------------------------------------------------------ the deal */

.deal {
  padding-bottom: 40px;
}

.deal__head h2 {
  padding-bottom: 20px;
  /* The app's heavy rule under "The deal, in plain words." */
  border-bottom: 2px solid var(--text);
}

.deal__lead {
  display: grid;
  gap: 28px;
  padding-bottom: 12px;
}

.deal__shot {
  width: min(100%, 300px);
}

@media (min-width: 900px) {
  .deal__lead {
    grid-template-columns: 15rem minmax(0, 1fr) 280px;
    gap: 40px;
    align-items: start;
  }
  .deal__col {
    grid-column: 2;
  }
  .deal__lead .deal__intro {
    font-size: 1.3rem;
    line-height: 1.5;
    color: var(--text);
    max-width: 24rem;
  }
  .deal__shot {
    grid-column: 3;
    width: 100%;
    margin-top: 1.2rem;
  }
}

/* The same five rows in HTML: the app's muted label left, the term right. */
.sheet {
  margin: 1.6rem 0 0;
  max-width: 34rem;
}

.sheet div {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
  padding: 13px 0;
  border-bottom: 1px solid var(--divider);
}

.sheet dt a {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  color: var(--n700);
  text-decoration: none;
  white-space: nowrap;
}

.sheet dt a:hover {
  color: var(--text);
}

.sheet dd {
  margin: 0;
  color: var(--text);
  font-weight: 600;
  text-align: right;
}

.row {
  scroll-margin-top: 16px;
}

.deal__intro {
  margin-top: 1.2rem;
  color: var(--n800);
}

/*
 * One row of the deal: the app's muted label on the left, the term on the
 * right, a divider under it. On a phone the label sits above, as it would if
 * the app's row ran out of width.
 */
.row {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 14px 40px;
  padding: 44px 0 52px;
  border-bottom: 1px solid var(--divider);
}

.row__label {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 1.15rem;
  color: var(--n700);
  line-height: 1.4;
  margin: 0;
}

.row__term {
  display: block;
  color: var(--text);
  font-weight: 600;
  font-size: 1rem;
  margin-top: 4px;
}

.row__body {
  display: grid;
  gap: 32px;
  min-width: 0;
}

.row__body h3 {
  margin-bottom: 0.8rem;
}

.row__shot {
  width: min(100%, 300px);
}

/* Kept and missed side by side (owner, 2026-09-28: "show missed too"). */
.row__shot--pair {
  width: min(100%, 460px);
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
}

@media (min-width: 900px) {
  .row {
    grid-template-columns: 15rem minmax(0, 1fr);
    padding: 64px 0 72px;
  }
  .row__label {
    position: sticky;
    top: 32px;
    align-self: start;
  }
  .row__body--split {
    grid-template-columns: minmax(0, 1fr) 280px;
    gap: 56px;
    align-items: start;
  }
}

/* Kinds of goal: the onboarding list, as a list. */
.kinds {
  list-style: none;
  margin: 1.6rem 0 0;
  padding: 0;
  display: grid;
  gap: 0;
  max-width: 36rem;
}

.kinds li {
  display: grid;
  grid-template-columns: 18px minmax(0, 1fr);
  gap: 14px;
  align-items: start;
  padding: 14px 0;
  border-top: 1px solid var(--divider);
}

.kinds li .ic {
  margin-top: 4px;
  color: var(--n800);
}

.kinds b {
  display: block;
  font-weight: 600;
  color: var(--text);
  font-size: 1.08rem;
}

.kinds span {
  color: var(--n700);
  font-size: 0.98rem;
}

/* "It measures / It charges / You can argue / You can stop" */
.terms {
  margin: 1.4rem 0 0;
  display: grid;
  gap: 18px;
  max-width: 34rem;
}

.terms div {
  display: grid;
  gap: 2px;
}

.terms dt {
  display: flex;
  align-items: center;
  gap: 10px;
  font-weight: 600;
  color: var(--text);
}

.terms dd {
  margin: 0 0 0 28px;
  color: var(--n800);
}

.small {
  font-size: 0.93rem;
  color: var(--n700);
}

/* ------------------------------------------------------------ the anti-charity */

/*
 * The row the page is built around, and the only one that breaks the grid:
 * the question is the app's biggest heading, and it gets the page's.
 */
.row--anti .row__body h3 {
  font-size: clamp(2.2rem, 7vw, 4rem);
  line-height: 1.06;
  letter-spacing: -0.01em;
  max-width: 11ch;
  margin-bottom: 1.4rem;
}

.anti__lede {
  font-size: 1.2rem;
  color: var(--n800);
}

/* Two positions, each pointing at the other's organisation. */
.pairs {
  margin: 2rem 0 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 12px;
  max-width: 38rem;
}

.pair {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 10px;
  padding: 18px 20px;
  border-radius: 18px;
  /* glassCard(), night */
  background: rgba(255, 255, 255, 0.045);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-top-color: rgba(255, 255, 255, 0.22);
  border-bottom-color: rgba(0, 0, 0, 0.34);
}

.pair__stand {
  font-size: 0.95rem;
  color: var(--n700);
}

.pair__stand .chip {
  margin-left: 6px;
  padding: 5px 14px;
  font-size: 0.92rem;
}

.pair__pay {
  color: var(--text);
  font-weight: 600;
  font-size: 1.2rem;
  line-height: 1.3;
}

.pair__pay small {
  display: block;
  font-weight: 400;
  font-size: 0.92rem;
  color: var(--n700);
}


.money {
  list-style: none;
  margin: 2.2rem 0 0;
  padding: 0;
  max-width: 36rem;
}

.money li {
  position: relative;
  padding: 10px 0 10px 22px;
}

.money li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 1.15em;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  border: 1.5px solid var(--keep);
}

.disclaimer {
  margin-top: 1.4rem;
  font-style: italic;
  font-size: 0.93rem;
  color: var(--n700);
}

/* ------------------------------------------------------------ why */

.why {
  padding-top: 96px;
  padding-bottom: 40px;
}

.why__head {
  max-width: 40rem;
}

.why__head p {
  margin-top: 1rem;
}

.findings {
  display: grid;
  gap: 16px;
  margin-top: 40px;
}

/*
 * Not three equal cards: the money finding is the one the app leads with and
 * the only randomised trial of the mechanism itself, so it takes the tall
 * column and the other two stack beside it.
 */
@media (min-width: 900px) {
  .findings {
    grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr);
    gap: 20px;
    align-items: start;
  }
  .finding--lead {
    grid-row: span 2;
    padding: 28px;
    gap: 16px;
  }
  .finding--lead h3 {
    font-size: 1.6rem;
  }
  .finding--lead .bar__track {
    height: 20px;
    border-radius: 10px;
  }
  .finding--lead .bar--weak .bar__track {
    height: 12px;
  }
  .finding--lead .bar__row b {
    font-size: 1.7rem;
  }
  .finding--lead .finding__claim {
    font-size: 1.05rem;
  }
}

/* onboarding.tsx Finding: a divider-bordered card, 18 round, bars inside. */
.finding {
  border: 1.5px solid var(--divider);
  border-radius: 18px;
  padding: 20px;
  display: grid;
  gap: 12px;
  align-content: start;
}

.finding h3 {
  font-size: 1.2rem;
}

.finding__what {
  font-size: 0.88rem;
  color: var(--n700);
  margin: -6px 0 0;
}

.bar {
  display: grid;
  gap: 6px;
}

.bar__row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 10px;
  font-size: 0.92rem;
  color: var(--n700);
}

.bar__row b {
  font-weight: 700;
  color: var(--text);
  font-size: 1.25rem;
  white-space: nowrap;
}

.bar--weak .bar__row b {
  font-size: 1rem;
  color: var(--n700);
}

.bar__track {
  height: 14px;
  border-radius: 7px;
  background: var(--n200);
  overflow: hidden;
}

.bar--weak .bar__track {
  height: 10px;
  border-radius: 5px;
}

.bar__fill {
  height: 100%;
  width: var(--v);
  background: var(--text);
  border-radius: inherit;
}

.bar--weak .bar__fill {
  background: var(--n400);
}

.finding__claim {
  font-size: 0.95rem;
  color: var(--n800);
  margin: 0;
}

.finding__src {
  font-size: 0.82rem;
  color: var(--n700);
  margin: 0;
}

.finding__src a {
  color: var(--n700);
}

.why__foot {
  margin-top: 28px;
}

/* ------------------------------------------------------------ buddies */

.buddies {
  position: relative;
  padding-top: 72px;
  padding-bottom: 72px;
  display: grid;
  gap: 32px;
}

.buddies h2 {
  max-width: 14ch;
}

.buddies__body p:first-child {
  font-size: 1.15rem;
  color: var(--n800);
}

.stops__intro {
  margin: 1.4rem 0 0;
}

.stops {
  list-style: none;
  margin: 0.6rem 0 1.4rem;
  padding: 0;
  counter-reset: none;
  max-width: 34rem;
}

.stops li {
  display: grid;
  grid-template-columns: 18px 1fr;
  gap: 14px;
  align-items: center;
  padding: 10px 0;
  border-top: 1px solid var(--divider);
  font-size: 0.97rem;
}

.stops li .ic {
  color: var(--n800);
}

.buddies__shot {
  max-width: 340px;
  margin-top: 28px;
}

@media (min-width: 900px) {
  .buddies {
    grid-template-columns: 15rem minmax(0, 1fr);
    gap: 40px;
    padding-top: 96px;
    padding-bottom: 96px;
  }
}

/* ------------------------------------------------------------ faq */

.faq {
  position: relative;
  padding-top: 56px;
  padding-bottom: 40px;
}

/*
 * A rule across the content, not across the gutter: these sections are their
 * own .wrap, so a border on them would run into the page's side padding.
 */
.faq::before,
.buddies::before,
.foot::before {
  content: '';
  position: absolute;
  top: 0;
  left: var(--pad);
  right: var(--pad);
  height: 1px;
  background: var(--divider);
}

.faq h2 {
  margin-bottom: 12px;
}

.qa {
  display: grid;
  gap: 8px 40px;
  padding: 26px 0;
  border-bottom: 1px solid var(--divider);
}

.qa h3 {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  font-size: 1.2rem;
  line-height: 1.35;
}

.qa h3 .ic {
  margin-top: 0.2em;
  color: var(--n800);
}

.qa p:last-child {
  margin-bottom: 0;
}

@media (min-width: 900px) {
  .faq {
    display: grid;
    grid-template-columns: 15rem minmax(0, 1fr);
    gap: 0 40px;
    padding-top: 96px;
  }
  .faq h2 {
    font-size: 2rem;
    position: sticky;
    top: 32px;
    align-self: start;
  }
  .qa {
    grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr);
  }
  .qa:first-of-type {
    padding-top: 6px;
  }
}

/* ------------------------------------------------------------ the end */

.sign {
  padding-top: 96px;
  padding-bottom: 104px;
}

.sign h2 {
  max-width: 16ch;
}

.sign p {
  margin-top: 1.2rem;
}

.sign .pill {
  margin-top: 2rem;
  max-width: 24rem;
}

@media (min-width: 900px) {
  .sign {
    padding-top: 140px;
    padding-bottom: 150px;
    text-align: center;
  }
  .sign h2,
  .sign p,
  .sign .pill {
    margin-left: auto;
    margin-right: auto;
  }
}

.foot {
  position: relative;
  padding-top: 28px;
  padding-bottom: 40px;
  font-size: 0.9rem;
  color: var(--n700);
  display: grid;
  gap: 14px;
}

.foot nav {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 22px;
}

.foot a {
  color: var(--n700);
}

.foot p {
  margin: 0;
  max-width: none;
}
