/* Base — every page loads this, first.

   Design tokens, reset, type scale, buttons, the nav and the footer, plus the
   two components that are shared rather than page-specific: the feature grid
   (index + features) and the recording frame (index + demo).

   LOAD ORDER MATTERS, and only in one direction: this file must come before any
   page stylesheet. Four rules here are deliberately overridden by the hero later
   on — .display and .h1 by .hero__title, .lede by .hero__sub, .pill by
   .pill--date — and they are equal specificity, so the win is source order.
   Link this first and everything else is free to move. */

/* IndieAppScale marketing site.

   Monochrome: a white page, near-black ink, and nothing else. What used to be
   carried by pastel fills — step markers, feature swatches, the closing band —
   is carried by weight, edges and the two-tone line art in assets/lottie
   (docs/LOTTIE_ART.md). Display is Nunito at 900: rounded terminals, heavy
   enough to hold a line; body is Nunito Sans.

   Blue is the mark's own #2B4474 and appears only as marks — the hero rule,
   links, focus, the plan ticks. Green and yellow appear as marks
   too (the hero tick, the saving label, two stat numerals, two step markers,
   two feature rules). The pastel FILLS stay unused: no coloured surfaces.

   Every colour pair in here has been checked against WCAG AA. The two
   boundary tokens are deliberately different: --line is decorative (1.27:1)
   and --line-ctl is for interactive edges, where 1.4.11 requires 3:1. */

:root {
  --cream:      #FFFFFF;
  --cream-2:    #F5F4F2;              /* the one inset band (the wall) */
  --shadow:     0 1px 2px rgba(25,27,30,.04), 0 14px 30px -22px rgba(25,27,30,.22);
  /* The page's one vertical interval: the space between any two sections, and the
     breathing room inside the bands that have a background of their own. */
  --gap:        clamp(72px, 9vw, 132px);
  --ink:        #191B1E;
  --ink-70:     rgba(25,27,30,.70);
  --ink-50:     #6E6E75;              /* meta text — 5.06 white / 4.60 band */
  --line:       rgba(25,27,30,.12);   /* decorative edges only (1.27:1) */
  --line-ctl:   #918A7F;              /* interactive boundaries — 3.42 white / 3.11 band */

  /* The one surviving pastel fill. --blue, --blue-soft and --yellow went with
     the coloured surfaces; this is the hero's checkmark disc and nothing else,
     which is why it is a fill rather than a mark. */
  --green:      #B2D8C0;
  /* the one deep tone, for coloured text and solid buttons */
  --blue-deep:  #1563F2;   /* the mark's blue — 5.12 on white, and 3.39 against
                              --ink so it reads as blue rather than near-black */

  /* The two comparison marks in the pricing table — the one place the
     monochrome rule bends, because included/excluded is scanned, not read.
     Deep tones, never the pastel fills: the white glyph sits on them at 5.0:1
     (tick) and 10.4:1 (cross), and the tick/cross SHAPES carry the meaning too,
     so colour is never the only signal. */
  --tick:       #2E7D5B;
  --cross:      #B3261E;

  /* Wordmark, sampled from the icon: the mark's charcoal, a lighter grey for
     "scale", and the mark's yellow for the period. WCAG 1.4.3 exempts
     logotypes, which is what lets the period stay true to the brand yellow. */
  --logo-ink:   #2B2B2C;
  --logo-scale: #7C7F86;
  --logo-dot:   #1666F6;   /* the mark's exact blue */
  /* Text on --ink, three steps. These were six hand-written hexes (#C4C4C6,
     #CDCCCA, #B9B9BC, #A6A6A7 twice, #9AA0A6) that looked like drift but are
     really a brightness ladder: body copy on a dark card needs more than a
     timestamp does. Named, so the next one picks a step instead of a hex. */
  --on-ink:     #C4C4C6;              /* body on --ink — 10.0:1 */
  --on-ink-mid: #A6A6A7;              /* secondary on --ink — 6.9:1 */
  --on-ink-dim: #909092;              /* quietest on --ink — 5.42:1 */

  /* The uppercase micro-label, written out at eight sites. Size and tracking
     are the two that drifted (11, 11.5, 12px; .1 and .14em); weight and
     transform never did. The two 11px/.1em sites are deliberately tighter —
     they sit inside pills, not on their own line. */
  --label-size:  11.5px;
  --label-track: .14em;

  /* Nunito: rounded terminals, soft joins, still heavy enough at 900 to
     carry a display line. Nunito Sans is its designed companion. */
  --display: 'Nunito', ui-rounded, ui-sans-serif, system-ui, sans-serif;
  --sans:    'Nunito Sans', ui-sans-serif, system-ui, sans-serif;
  --post:    'TikTok Sans', var(--sans);

  --maxw: 1240px;
  --gut:  clamp(20px, 4.4vw, 56px);
}

*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }
/* Every in-page jump — the nav links and the hero's "watch it work" — otherwise
   lands with the section's pill and heading tucked under the sticky bar. */
section[id] { scroll-margin-top: 104px; }

body {
  margin: 0;
  background: var(--cream);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 17px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

img { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; cursor: pointer; }
::selection { background: var(--ink); color: var(--cream); }

a, button, summary { transition: opacity .3s ease-out; }
a:hover, button:hover, summary:hover { opacity: .62; }

.wrap { width: min(100%, var(--maxw)); margin-inline: auto; padding-inline: var(--gut); }
.skip { position: absolute; left: -9999px; }
.skip:focus { left: 16px; top: 16px; z-index: 200; background: var(--ink); color: var(--cream); padding: 10px 16px; border-radius: 999px; }
:focus-visible { outline: 2px solid var(--blue-deep); outline-offset: 3px; }

/* ── Type ───────────────────────────────────────────────────── */

.display {
  font-family: var(--display);
  font-weight: 900;
  letter-spacing: -.028em;
  line-height: 1.04;
  margin: 0;
}
.h1 { font-size: clamp(38px, 5.9vw, 78px); }
.h2 { font-size: clamp(29px, 4vw, 50px); }
.h3 { font-family: var(--display); font-weight: 800; font-size: clamp(19px, 1.8vw, 24px); letter-spacing: -.015em; line-height: 1.2; margin: 0 0 10px; }

.lede { font-size: clamp(17px, 1.3vw, 19px); color: var(--ink-70); max-width: 46ch; margin: 0; }

/* label pill — white capsule, small caps */
.pill {
  display: inline-flex; align-items: center;
  background: #fff; border: 1px solid var(--line); box-shadow: var(--shadow);
  border-radius: 999px; padding: 7px 16px;
  font-size: var(--label-size); font-weight: 700; letter-spacing: var(--label-track); text-transform: uppercase;
  color: var(--ink-70);
}

/* The hero pill when it carries the launch date. One dot, in the one accent, so a
   date reads as a state rather than as another label. Sized off the pill's own
   padding so it works whichever of the two strings is in it. */
.pill--date { gap: 9px; padding-left: 13px; }
.pill--date::before { content: ''; width: 7px; height: 7px; border-radius: 50%; background: var(--blue-deep); }

/* One gap for the whole page. Sections carry it on the bottom only, so the space
   between any two of them is exactly --gap however they are ordered — the old
   mixture of full padding, `padding-top:0` overrides and per-section values made
   the same boundary anywhere from 86px to 216px depending on the pair. A band with
   a background of its own (the wall, the closing) carries the gap inside it
   instead, and the section that follows one starts its own again. */
.section { padding-block: 0 var(--gap); }
.wall + .section, .closing + .section { padding-top: var(--gap); }
.section__head { text-align: center; max-width: 720px; margin: 0 auto clamp(40px, 5vw, 68px); }
.section__head .pill { margin-bottom: 20px; }
.section__head .lede { margin: 18px auto 0; }

/* ── Buttons ────────────────────────────────────────────────── */

.btn {
  display: inline-flex; align-items: center; gap: 9px;
  background: var(--ink); color: var(--cream);
  border: 1px solid var(--ink); border-radius: 999px;
  padding: 14px 26px; font-weight: 700; font-size: 15px; letter-spacing: -.01em;
  /* A pill that wraps stops being a pill: two lines of text inside a 999px radius
     render as a black circle, and in the nav it grew tall enough to cover the
     wordmark. Labels here are two or three words — they belong on one line, and if
     one doesn't fit, that is the layout's problem to solve, not the label's. */
  white-space: nowrap;
}
.btn--sm    { padding: 10px 20px; font-size: 14px; }
.btn--lg    { padding: 17px 34px; font-size: 16.5px; }
.btn--quiet { background: #fff; color: var(--ink); border-color: var(--line-ctl); }
.btn--block { display: flex; justify-content: center; width: 100%; }

/* ── Reveals ────────────────────────────────────────────────── */

.reveal { opacity: 0; transform: translateY(18px); transition: opacity .7s ease-out, transform .7s ease-out; transition-delay: var(--d, 0s); }
.reveal.is-in { opacity: 1; transform: none; }
.fade { opacity: 0; animation: fade .8s ease-out forwards; animation-delay: var(--d, 0s); }
@keyframes fade { to { opacity: 1; } }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: .001ms !important; transition-duration: .001ms !important; animation-iteration-count: 1 !important; }
  .fade, .reveal { opacity: 1; transform: none; }
}

/* ── Nav ────────────────────────────────────────────────────── */

.nav { position: fixed; top: 0; left: 0; right: 0; z-index: 90; padding-top: 16px; }
.nav__inner {
  display: flex; align-items: center; gap: 22px;
  padding: 9px 9px 9px 20px; border: 1px solid transparent; border-radius: 999px;
  transition: background .4s ease-out, border-color .4s ease-out;
}
.nav.is-stuck .nav__inner {
  background: rgba(255,255,255,.82);
  -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
  border-color: var(--line);
}
/* The lockup: icon + wordmark at 1.4em, where their optical masses balance. */
.brand {
  display: inline-flex; align-items: center; gap: .36em;
  font-family: var(--display); font-weight: 900; font-size: 21px;
  letter-spacing: -.028em; line-height: 1; color: var(--logo-ink);
  white-space: nowrap;
}
.brand__mark { display: block; height: 1.4em; width: auto; flex: none; }
.brand__scale { color: var(--logo-scale); }
.brand__dot { color: var(--logo-dot); }
.nav__links { display: flex; gap: 26px; margin-left: auto; font-size: 15px; font-weight: 500; color: var(--ink-70); }
.nav__cta { display: flex; align-items: center; gap: 18px; }
.nav__signin { font-size: 15px; font-weight: 600; }
.nav__burger { display: none; background: none; border: 0; padding: 10px; }
.nav__burger span { display: block; width: 20px; height: 2px; background: var(--ink); margin: 4px 0; border-radius: 2px; transition: transform .35s ease-out, opacity .3s ease-out; }
.nav.is-open .nav__burger span:nth-child(1) { transform: translateY(6px) rotate(45deg); }
.nav.is-open .nav__burger span:nth-child(2) { opacity: 0; }
.nav.is-open .nav__burger span:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }
.nav__mobile { display: none; flex-direction: column; margin-top: 8px; padding: 18px 24px 24px; background: #fff; border: 1px solid var(--line); border-radius: 26px; }
.nav__mobile a { padding: 9px 0; font-family: var(--display); font-weight: 800; font-size: 20px; }
.nav.is-open .nav__mobile { display: flex; }

/* ── Features ───────────────────────────────────────────────── */

.feats { display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(16px, 1.8vw, 24px); }
.feat { background: #fff; border: 1px solid var(--line); border-radius: 24px; padding: clamp(24px, 2.6vw, 32px); box-shadow: var(--shadow); }
/* Was a pastel swatch standing in for an icon. Monochrome leaves no honest
   version of that, so it is a rule instead — a mark, not a missing picture. */
.feat__mark { width: 36px; height: 4px; border-radius: 2px; background: var(--fm, var(--ink)); margin-bottom: 20px; }
.feat p { margin: 0; color: var(--ink-70); font-size: 15.5px; }

/* ── Recording frame ────────────────────────────────────────────
   Plain browser chrome, used by the band under the hero and by every step on
   /demo. Deliberately not a phone bezel or a floating laptop: the claim is that
   this is the real app in a real browser, and dressing it up argues the opposite. */

.frame { border: 1px solid var(--line); border-radius: 18px; overflow: hidden; background: #fff; box-shadow: var(--shadow); }
.frame__bar { display: flex; align-items: center; gap: 6px; padding: 9px 14px; border-bottom: 1px solid var(--line); background: #FBFAF9; }
.frame__bar i { width: 9px; height: 9px; border-radius: 50%; background: var(--line-ctl); opacity: .45; flex: none; }
.frame__url { margin-left: 8px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12px; color: var(--ink-50); background: #fff; border: 1px solid var(--line); border-radius: 999px; padding: 3px 12px; }
/* The poster carries the aspect ratio, so a clip that hasn't been uploaded yet
   leaves a still frame rather than a collapsed box. */
.frame__vid { display: block; width: 100%; aspect-ratio: 16 / 10; object-fit: cover; background: #EFEDEA; }

/* ── Closing ────────────────────────────────────────────────── */

.closing { background: var(--ink); color: var(--cream); padding-block: var(--gap); text-align: center; }
.closing p { margin: 20px auto 32px; font-size: 18px; color: rgba(255,255,255,.76); max-width: 46ch; }
.closing small { display: block; margin-top: 20px; font-size: 13.5px; color: var(--on-ink-dim); }
/* Inverted on the ink band — the page's only white button. */
.closing .btn { background: var(--cream); color: var(--ink); border-color: var(--cream); }

/* ── Footer ─────────────────────────────────────────────────── */

/* The closing band is ink too now, so a hairline keeps the two from reading as
   one long slab. */
.foot { background: var(--ink); color: var(--cream); border-top: 1px solid rgba(255,255,255,.14); padding-top: clamp(56px, 7vw, 88px); }
.foot__top { display: grid; grid-template-columns: minmax(0,1.3fr) minmax(0,2fr); gap: clamp(32px,5vw,70px); padding-bottom: clamp(44px,5vw,70px); }
.foot .brand { color: var(--cream); font-size: 24px; }
.foot .brand__scale { color: #9AA0A6; }
.foot .brand__mark { content: url('/assets/mark-on-dark.png'); }
.foot__blurb { margin: 16px 0 0; color: var(--on-ink-mid); font-size: 15px; max-width: 34ch; }
.foot__cols { display: grid; grid-template-columns: repeat(3,1fr); gap: 24px; }
.foot__cols div { display: flex; flex-direction: column; gap: 11px; }
.foot__ct { font-size: 12px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase; color: var(--on-ink-dim); margin-bottom: 4px; }
.foot__cols a { font-size: 15px; color: #CDCCCA; width: fit-content; }
.foot__bar { display: flex; justify-content: space-between; gap: 18px; flex-wrap: wrap; padding-block: 24px; border-top: 1px solid rgba(250,248,245,.14); font-size: 14px; color: var(--on-ink-dim); }
.foot__barlinks { display: flex; gap: 22px; }

/* ── Consent ────────────────────────────────────────────────────
   The cookie banner, built from JS in assets/js/consent.js. It lives here rather
   than in a file of its own for the same reason the feature grid does: every page
   loads base.css already, and a seventh stylesheet would mean six more <link>
   tags for the deploy stamper to get right.

   Monochrome like everything else — a white card on the page, ink text, the
   control-grade boundary. The only accent is the one the primary .btn already
   carries, so the section keeps to one. */

.consent {
  position: fixed; z-index: 100;
  left: var(--gut); right: var(--gut); bottom: 20px;
  margin-inline: auto; max-width: 720px;
  display: flex; align-items: center; gap: 18px; flex-wrap: wrap;
  background: var(--cream); color: var(--ink);
  border: 1px solid var(--line-ctl); border-radius: 18px;
  padding: 18px 22px;
  box-shadow: var(--shadow);
  /* Starts off-screen and inert: the banner is appended on load, and without
     this it paints in place for a frame before the transition can run. */
  opacity: 0; transform: translateY(14px); pointer-events: none;
  transition: opacity .35s ease-out, transform .35s ease-out;
}
.consent.is-open { opacity: 1; transform: none; pointer-events: auto; }
.consent__text { margin: 0; flex: 1 1 320px; font-size: 14px; line-height: 1.55; color: var(--ink-70); }
.consent__text a { color: var(--blue-deep); }
.consent__acts { display: flex; gap: 10px; margin-left: auto; }

/* The banner is the one thing on the page a visitor cannot scroll away from, so
   it is also the one place a motion preference is most worth honouring. */
@media (prefers-reduced-motion: reduce) {
  .consent { transition: none; transform: none; }
}

/* ═══════════════════════════════════════════════════════════════
   Sub-pages — privacy, terms, 404.
   They share the nav and footer above; these are the extras.
   ═══════════════════════════════════════════════════════════════ */

/* legacy button aliases so the sub-pages keep working */

/* ── Breakpoints ────────────────────────────────────────────────
   Colocated with the rules they override, which is the only reason they work:
   each clause is the same specificity as its base rule, so it wins on source
   order alone. Keep them below, and keep 980 above 720. */

@media (max-width: 980px) {
  .foot__top { grid-template-columns: 1fr; }
  .feats { grid-template-columns: 1fr 1fr; }
  .feats > :last-child { grid-column: 1 / -1; }
}
/* The link row carries six items since Demo joined it, and somewhere under 860px
   the links and the CTA stop fitting the pill together — the CTA was pushed out
   past its right edge rather than wrapping. The burger takes over earlier now;
   everything else about the bar still changes at 720. */
@media (max-width: 860px) {
  .nav__links, .nav__signin { display: none; }
  .nav__burger { display: block; }
  .nav__cta { margin-left: auto; gap: 8px; }
}
@media (max-width: 720px) {
  /* Below this width the bar is brand + one CTA + burger, and the desktop spacing
     leaves the CTA about 76px to render its label in — less than "Start free"
     needs, so it wrapped. Tighten the gaps and the pill so the label has
     somewhere to go. */
  .nav__inner { gap: 12px; padding-left: 16px; }
  .nav__cta .btn { padding: 10px 15px; font-size: 13.5px; }
  .nav__burger { padding: 10px 2px; }
  .nav__inner { background: rgba(255,255,255,.9); -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px); border-color: var(--line); }
  .feats { grid-template-columns: 1fr; }
  .feats > :last-child { grid-column: auto; }
  .foot__cols { grid-template-columns: 1fr 1fr; }
  /* Side by side, the two consent buttons leave the copy about 12 characters a
     line. Stack instead, and let the pair span the card so both stay a full tap
     target rather than shrinking to fit beside each other. */
  .consent { left: 12px; right: 12px; bottom: 12px; padding: 16px; gap: 14px; }
  .consent__acts { margin-left: 0; width: 100%; }
  .consent__acts .btn { flex: 1; justify-content: center; }
}
@media (max-width: 359px) {
  /* Under about 330px the bar can no longer hold the wordmark, the CTA and the burger
     on one line, and something has to give. It is the wordmark: the mark still carries
     the brand, and the anchor's aria-label still reads "IndieAppScale, home", so a
     screen reader loses nothing. Shrinking the CTA instead would cost the tap target. */
  .nav .brand > span { display: none; }
}
