/* ============================================================================
   GRIND — the public pages.

   Separate from styles.css on purpose. That file dresses an application: dense,
   quiet, built to be looked at for eight hours. These two pages are read once,
   by somebody deciding whether to bother, and they need room and contrast the
   application would be exhausting to work in.

   What they share is the brand — teal #0C3030, gold #F0B40C, Montserrat — so
   the front door and the building behind it are recognisably the same place.
   ============================================================================ */
:root {
  --teal: #0c3030;
  --teal-800: #0a2727;
  --teal-700: #124040;
  --teal-600: #1a4d4d;
  --gold: #f0b40c;
  --gold-600: #d09e08;
  --ink: #16201f;
  --ink-2: #3d534e;
  --muted: #6b7c7b;
  --line: #e3eae9;
  --bg: #f4f7f6;
  --card: #ffffff;
  --ok: #1f9d6b;
  --font: "Montserrat", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --shadow: 0 1px 3px rgba(0,51,51,.07), 0 12px 32px -12px rgba(0,51,51,.18);
  --radius: 14px;
}

* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font);
  font-size: 16px;
  line-height: 1.62;
  -webkit-font-smoothing: antialiased;
}
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  * { transition: none !important; animation: none !important; }
}

img { max-width: 100%; display: block; }
a { color: inherit; }

/* ── Buttons ─────────────────────────────────────────────────────────────── */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  font: 600 14px/1 var(--font);
  padding: 12px 20px; border-radius: 999px; border: 1px solid transparent;
  text-decoration: none; cursor: pointer; white-space: nowrap;
  transition: transform .12s ease, background .12s ease, border-color .12s ease;
}
.btn:hover { transform: translateY(-1px); }
.btn:focus-visible { outline: 3px solid var(--gold); outline-offset: 2px; }
.btn--gold { background: var(--gold); color: var(--teal); }
.btn--gold:hover { background: var(--gold-600); }
.btn--ghost { color: #fff; border-color: rgba(255,255,255,.28); }
.btn--ghost:hover { border-color: rgba(255,255,255,.6); }
.btn--outline { color: var(--teal); border-color: rgba(12,48,48,.28); background: transparent; }
.btn--outline:hover { border-color: var(--teal); }
.btn--lg { padding: 15px 28px; font-size: 15px; }
.btn--block { width: 100%; }

/* ── Nav ─────────────────────────────────────────────────────────────────── */
.nav {
  position: sticky; top: 0; z-index: 40;
  display: flex; align-items: center; gap: 28px;
  padding: 14px clamp(18px, 5vw, 56px);
  background: var(--teal); color: #fff;
}
/* The brand marks are dark teal on transparent — they were made for a light
   page and disappear entirely on this nav. Rather than commission a light
   variant, the mark sits on a light chip, which is how it is printed anyway,
   and the wordmark is set in type beside it. */
.nav__brand { display: flex; align-items: center; gap: 10px; text-decoration: none; }
.mark {
  display: grid; place-items: center; flex: none;
  width: 48px; height: 48px; border-radius: 14px; background: #fff;
  box-shadow: 0 1px 0 rgba(255,255,255,.35) inset;
}
.mark img { width: 34px; height: 34px; }
/* The footer's smaller pairing. Still a step down from the header, because a
   footer that shouts its own name as loudly as the top of the page reads as a
   page that has run out of things to say. */
.mark--sm { width: 36px; height: 36px; border-radius: 11px; background: rgba(255,255,255,.92); }
.mark--sm img { width: 25px; height: 25px; }
.wordmark {
  font-weight: 800; font-size: 24px; letter-spacing: .1em; color: #fff;
}
.wordmark--sm { font-size: 17px; color: rgba(255,255,255,.85); }
.nav__links { display: flex; gap: 22px; margin-left: 10px; }
.nav__links a {
  text-decoration: none; font-size: 14px; font-weight: 500;
  color: rgba(255,255,255,.82); padding: 6px 0;
  border-bottom: 2px solid transparent;
}
.nav__links a:hover { color: #fff; border-bottom-color: var(--gold); }
.nav__cta { margin-left: auto; display: flex; gap: 10px; }
@media (max-width: 780px) {
  .nav__links { display: none; }
}

/* ── Hero ────────────────────────────────────────────────────────────────── */
.hero {
  background: linear-gradient(168deg, var(--teal) 0%, var(--teal-700) 62%, var(--teal-600) 100%);
  color: #fff;
  padding: clamp(52px, 8vw, 96px) clamp(18px, 5vw, 56px) clamp(64px, 9vw, 110px);
  display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, .9fr);
  gap: clamp(28px, 5vw, 64px); align-items: center;
}
@media (max-width: 900px) { .hero { grid-template-columns: 1fr; } }

.eyebrow {
  margin: 0 0 12px; font-size: 11.5px; font-weight: 700;
  letter-spacing: .17em; text-transform: uppercase; color: var(--gold);
}
.hero h1 {
  margin: 0 0 18px;
  font-size: clamp(32px, 5.2vw, 56px); line-height: 1.06;
  letter-spacing: -.02em; font-weight: 800; text-wrap: balance;
  max-width: 17ch;
}
.hero .lede {
  margin: 0 0 30px; max-width: 54ch;
  font-size: clamp(16px, 1.6vw, 18.5px); color: rgba(255,255,255,.86);
}
.hero__actions { display: flex; flex-wrap: wrap; gap: 12px; }
.hero__actions .btn--outline { color: #fff; border-color: rgba(255,255,255,.34); }
.hero__actions .btn--outline:hover { border-color: #fff; }
.hero__note { margin: 22px 0 0; font-size: 13px; color: rgba(255,255,255,.55); }

/* ── Figures strip ───────────────────────────────────────────────────────── */
.strip { background: var(--teal-800); color: #fff; }
.strip__inner {
  max-width: 1080px; margin: 0 auto;
  display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 1px; padding: 0 clamp(18px, 5vw, 56px);
}
.strip__inner > div { padding: 22px 6px; text-align: center; }
.strip b { display: block; font-size: 30px; font-weight: 800; color: var(--gold);
  font-variant-numeric: tabular-nums; line-height: 1.1; }
.strip span { display: block; font-size: 12px; color: rgba(255,255,255,.62); margin-top: 2px; }

/* ── Sections ────────────────────────────────────────────────────────────── */
.section { padding: clamp(56px, 8vw, 96px) clamp(18px, 5vw, 56px); }
.section__head { max-width: 780px; margin: 0 auto clamp(32px, 4vw, 52px); text-align: center; }
.section__head h2 {
  margin: 0 0 14px; font-size: clamp(25px, 3.4vw, 36px); line-height: 1.14;
  letter-spacing: -.015em; font-weight: 700; text-wrap: balance;
}
.section__head .sub { margin: 0 auto; max-width: 62ch; color: var(--ink-2); font-size: 16.5px; }

.section--dark { background: var(--teal); color: #fff; }
.section--dark .section__head .sub { color: rgba(255,255,255,.76); }

.grid {
  max-width: 1120px; margin: 0 auto;
  display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 18px;
}
/* Six cards, and auto-fit was giving four across — which left two orphans on a
   row built for four and a hole where the eye expects a card. The name was
   always the intent: three across, so six reads as two complete rows.

   Below 1040px it falls back to the auto-fit behaviour, where two-and-one is
   unavoidable and looks fine because the row is visibly narrower. */
.grid--3 { max-width: 1120px; }
@media (min-width: 1040px) {
  .grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

.mod {
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 24px 24px 26px;
  box-shadow: var(--shadow);
}
.mod h3 { margin: 0 0 8px; font-size: 17px; font-weight: 700; }
.mod p { margin: 0; color: var(--ink-2); font-size: 14.6px; }

.rule {
  background: rgba(255,255,255,.05); border: 1px solid rgba(255,255,255,.13);
  border-radius: var(--radius); padding: 24px;
}
.rule__step {
  display: inline-block; margin-bottom: 10px;
  font: 700 10.5px/1 var(--font); letter-spacing: .14em; text-transform: uppercase;
  color: var(--gold);
}
.rule h3 { margin: 0 0 8px; font-size: 17px; font-weight: 700; }
.rule p { margin: 0; color: rgba(255,255,255,.74); font-size: 14.6px; }

/* ── Signup ──────────────────────────────────────────────────────────────── */
.signup__grid {
  max-width: 1080px; margin: 0 auto;
  display: grid; grid-template-columns: minmax(0, .9fr) minmax(0, 1.1fr);
  gap: clamp(28px, 5vw, 64px); align-items: start;
}
@media (max-width: 880px) { .signup__grid { grid-template-columns: 1fr; } }
/* The form on the right grew — modules, colleagues, the lot — and left this
   column empty from about the third field down, with the pitch scrolled off the
   top by the time anybody reached the submit button. Sticking it puts the
   reasons to fill the form in beside the form while it is being filled in, and
   the emptiness stops being emptiness.

   Capped at the viewport and allowed to scroll inside itself, so it works at
   any window height rather than only on a tall screen. A plain sticky column
   taller than the viewport hides its own last line, which is worse than not
   sticking; gating it on a minimum height instead just brings back the empty
   column on every laptop. This does neither. */
@media (min-width: 881px) {
  .signup__pitch {
    position: sticky; top: 92px;
    max-height: calc(100vh - 112px);
    overflow-y: auto;
    /* A thin, quiet scrollbar. On the rare screen short enough to need it, it
       should read as "there is a little more" rather than as a second frame. */
    scrollbar-width: thin;
    scrollbar-color: var(--line) transparent;
  }
  .signup__pitch::-webkit-scrollbar { width: 6px; }
  .signup__pitch::-webkit-scrollbar-thumb { background: var(--line); border-radius: 3px; }
  .signup__pitch::-webkit-scrollbar-track { background: transparent; }
}
.signup__pitch h2 { margin: 0 0 14px; font-size: clamp(25px, 3.4vw, 34px);
  line-height: 1.14; font-weight: 700; letter-spacing: -.015em; }
.signup__pitch .sub { color: var(--ink-2); max-width: 46ch; }
.ticks { list-style: none; padding: 0; margin: 22px 0 0; }
.ticks li { position: relative; padding-left: 28px; margin-bottom: 8px;
  color: var(--ink-2); font-size: 14.8px; }
.ticks li::before {
  content: ""; position: absolute; left: 4px; top: 8px;
  width: 8px; height: 8px; border-radius: 50%; background: var(--gold);
}

.card {
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--radius); padding: clamp(20px, 3vw, 30px);
  box-shadow: var(--shadow);
}
.signup__form label {
  display: block; font-size: 12.5px; font-weight: 600; color: var(--ink-2);
  margin-bottom: 14px;
}
.signup__form label span { color: #d64545; margin-left: 2px; }
.signup__form input,
.signup__form select,
.signup__form textarea {
  display: block; width: 100%; margin-top: 6px;
  font: 400 15px/1.5 var(--font); color: var(--ink);
  padding: 11px 13px; border: 1px solid var(--line); border-radius: 10px;
  background: #fff;
}
.signup__form input:focus,
.signup__form select:focus,
.signup__form textarea:focus {
  outline: none; border-color: var(--teal-600);
  box-shadow: 0 0 0 3px rgba(26,77,77,.13);
}
.signup__form textarea { resize: vertical; }
.row { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
@media (max-width: 520px) { .row { grid-template-columns: 1fr; } }
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.formnote { margin: 12px 0 0; font-size: 14px; min-height: 1.2em; }
.formnote.is-ok { color: var(--ok); font-weight: 600; }
.formnote.is-err { color: #d64545; font-weight: 600; }
.fineprint { margin: 12px 0 0; font-size: 12.5px; color: var(--muted); }

/* What happens after the form is sent. A numbered rail rather than more ticks:
   these are three things in sequence, and the shape should say so. */
.after { list-style: none; margin: 20px 0 0; padding: 0; counter-reset: aft; }
.after li {
  position: relative; padding: 0 0 15px 42px; counter-increment: aft;
}
.after li::before {
  content: counter(aft);
  position: absolute; left: 0; top: 0;
  display: grid; place-items: center; width: 26px; height: 26px;
  border-radius: 50%; background: var(--teal); color: #fff;
  font-size: 12px; font-weight: 700; line-height: 1;
}
/* The rail between the numbers, stopping at the last one. */
.after li:not(:last-child)::after {
  content: ''; position: absolute; left: 12.5px; top: 30px; bottom: 6px;
  width: 1px; background: var(--line);
}
.after li:last-child { padding-bottom: 0; }
.after b { display: block; font-size: 14.5px; margin-bottom: 2px; }
.after span { display: block; font-size: 13.5px; color: var(--muted); line-height: 1.55; }

/* ── The tailoring block ──────────────────────────────────────────────────
   Two fieldsets inside the request form: which modules matter, and who else is
   in the organisation. Both are optional and both are the difference between an
   account that opens set up and one that opens empty.

   A fieldset carries browser styling that fights everything around it, so it is
   stripped back to a plain block and given its own rule instead. */
/* The bottom margin matters: every other field in this form is a <label> that
   carries 14px under it, and a fieldset that does not leaves the next question
   sitting on top of the previous answer. */
.picks, .invites {
  border: 0; padding: 0; margin: 20px 0 18px; min-width: 0;
}
.picks legend, .invites legend {
  padding: 0; font-size: 13.5px; font-weight: 700; color: var(--ink);
}
.picks__hint { margin: 4px 0 12px; font-size: 12.5px; color: var(--muted); }

.picks__grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
@media (max-width: 560px) { .picks__grid { grid-template-columns: 1fr; } }

/* The whole chip is the hit target, not the 13px box inside it — these are
   chosen on a phone as often as not.

   Scoped under .signup__form throughout, and deliberately: the form already
   says `.signup__form label span { color: #d64545 }` to paint the required
   asterisk, and a chip is a label with a span in it. Unscoped, every module's
   description came out in the red reserved for "you must answer this". */
.signup__form .pick {
  display: flex; align-items: flex-start; gap: 10px; margin: 0;
  padding: 10px 12px; border: 1px solid var(--line); border-radius: 10px;
  background: #fff; cursor: pointer; font-weight: 400;
  transition: border-color .15s ease, background .15s ease;
}
.signup__form .pick:hover { border-color: rgba(12,48,48,.3); }
.signup__form .pick input {
  width: 16px; height: 16px; margin: 2px 0 0; flex: none; accent-color: var(--teal);
}
.signup__form .pick span {
  display: block; margin-left: 0; font-size: 12.5px; line-height: 1.45; color: var(--muted);
}
.signup__form .pick span b { display: block; font-size: 13.5px; color: var(--ink); font-weight: 600; }
.signup__form .pick:has(input:checked) { border-color: var(--teal); background: rgba(12,48,48,.04); }
.signup__form .pick:has(input:focus-visible) { outline: 2px solid var(--gold); outline-offset: 2px; }

.invite-row { display: grid; grid-template-columns: 1fr 1.2fr 1fr auto; gap: 8px; margin-bottom: 8px; }
@media (max-width: 720px) { .invite-row { grid-template-columns: 1fr 1fr; } }
/* The inputs here sit in a grid row rather than under a label, so the 6px the
   form puts above every field would push them out of line with the button. */
.signup__form .invite-row input { width: 100%; margin-top: 0; }
.invite-row .drop {
  border: 1px solid var(--line); background: #fff; border-radius: 9px; cursor: pointer;
  color: var(--muted); font: inherit; font-size: 18px; line-height: 1; padding: 0 12px;
}
.invite-row .drop:hover { color: #d64545; border-color: #d64545; }
.btn--sm { padding: 8px 14px; font-size: 13px; }

/* ── Pricing ─────────────────────────────────────────────────────────────── */
.plans {
  max-width: 1160px; margin: 0 auto;
  display: grid; grid-template-columns: repeat(auto-fit, minmax(248px, 1fr));
  gap: 18px; align-items: stretch;
}
.plan {
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 26px 24px 28px;
  display: flex; flex-direction: column; box-shadow: var(--shadow);
}
.plan--featured { border-color: var(--gold); box-shadow: 0 0 0 3px rgba(240,180,12,.16), var(--shadow); }
.plan__tag {
  align-self: flex-start; margin-bottom: 12px;
  font: 700 10.5px/1 var(--font); letter-spacing: .13em; text-transform: uppercase;
  color: var(--teal); background: rgba(240,180,12,.2);
  padding: 5px 10px; border-radius: 999px;
}
.plan h3 { margin: 0 0 4px; font-size: 20px; font-weight: 700; }
.plan__who { margin: 0 0 18px; font-size: 13.5px; color: var(--muted); min-height: 2.8em; }
.plan__price { display: flex; align-items: baseline; gap: 6px; margin-bottom: 4px; }
.plan__price b { font-size: 38px; font-weight: 800; letter-spacing: -.02em;
  font-variant-numeric: tabular-nums; line-height: 1; }
.plan__price span { font-size: 13px; color: var(--muted); }
/* The dollar sign leads the figure and is set smaller and raised, the way a
   price is printed. Left at the same size it competes with the number, which is
   the thing being read. */
.plan__price .cur { font-size: 20px; font-weight: 700; color: var(--ink);
  align-self: flex-start; margin-top: 3px; margin-right: -2px; }
.plan__per { margin: 0 0 20px; font-size: 12.5px; color: var(--muted); }
.plan ul { list-style: none; padding: 0; margin: 0 0 24px; }
.plan li { position: relative; padding-left: 24px; margin-bottom: 9px;
  font-size: 14.2px; color: var(--ink-2); }
.plan li::before {
  content: ""; position: absolute; left: 3px; top: 8px;
  width: 7px; height: 7px; border-radius: 50%; background: var(--ok);
}
.plan .btn { margin-top: auto; }

.billing { max-width: 900px; margin: 0 auto; }
.qa { border-top: 1px solid var(--line); padding: 22px 0; }
.qa:last-child { border-bottom: 1px solid var(--line); }
.qa h3 { margin: 0 0 7px; font-size: 16.5px; font-weight: 700; }
.qa p { margin: 0; color: var(--ink-2); font-size: 15px; max-width: 72ch; }

.callout {
  max-width: 900px; margin: 0 auto clamp(30px, 4vw, 44px);
  background: var(--card); border: 1px solid var(--line); border-left: 3px solid var(--gold);
  border-radius: 10px; padding: 16px 20px; box-shadow: var(--shadow);
}
.callout p { margin: 0; font-size: 14.6px; color: var(--ink-2); }

/* ── Footer ──────────────────────────────────────────────────────────────── */
.foot { background: var(--teal-800); color: rgba(255,255,255,.7); }
.foot__inner {
  max-width: 1120px; margin: 0 auto;
  padding: 40px clamp(18px, 5vw, 56px);
  display: flex; flex-wrap: wrap; align-items: center; gap: 18px;
}
.foot__inner .mark--sm { margin-right: -8px; }
.foot nav { display: flex; gap: 20px; margin-left: auto; }
.foot nav a { text-decoration: none; font-size: 14px; color: rgba(255,255,255,.72); }
.foot nav a:hover { color: #fff; }
.foot p { width: 100%; margin: 0; font-size: 12.5px; color: rgba(255,255,255,.45); }

/* ── Motion ──────────────────────────────────────────────────────────────────
   Everything here is additive. A section with .reveal but no .is-in is still
   laid out, still readable by a screen reader, still in the page — it is moved
   and faded, not hidden — so if the script never runs the page is intact. */
[data-reveal] {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity .5s cubic-bezier(.22,.61,.36,1), transform .5s cubic-bezier(.22,.61,.36,1);
  /* No will-change. There are twenty-seven of these on the page, and promoting
     every one to its own compositor layer costs more than the animation saves —
     it was enough to make the renderer stop answering. The transition is on
     opacity and transform, which the compositor handles without being asked. */
}
[data-reveal].is-in { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  [data-reveal] { opacity: 1 !important; transform: none !important; transition: none; }
}

/* ── The product, in a frame ─────────────────────────────────────────────────
   A browser chrome around the screenshot, because a bare rectangle of UI on a
   coloured background reads as a diagram. The frame says "this is a screen". */
.shot {
  border-radius: 14px; overflow: hidden;
  background: #0b1f1f;
  border: 1px solid rgba(255,255,255,.14);
  box-shadow: 0 30px 70px -30px rgba(0,0,0,.65), 0 2px 8px rgba(0,0,0,.3);
}
.shot__bar {
  display: flex; align-items: center; gap: 7px;
  padding: 9px 13px; background: rgba(255,255,255,.07);
  border-bottom: 1px solid rgba(255,255,255,.09);
}
.shot__bar span { width: 9px; height: 9px; border-radius: 50%; background: rgba(255,255,255,.22); }
.shot__url {
  margin-left: 10px; font-size: 11px; font-weight: 500; letter-spacing: .02em;
  color: rgba(255,255,255,.45);
  background: rgba(0,0,0,.22); border-radius: 5px; padding: 3px 9px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.shot img { display: block; width: 100%; height: auto; transition: opacity .25s ease; }
/* The hero crops to a band of the screen. Left to its own height the image ran
   out halfway down the sidebar, which reads as a broken picture rather than a
   cropped one. */
.shot--hero img { height: 340px; object-fit: cover; object-position: left top; }
@media (max-width: 900px) { .shot--hero img { height: 220px; } }

.hero__art { position: relative; }
.shot--hero { transform: perspective(1400px) rotateY(-4deg) rotateX(1.5deg); transform-origin: left center; }
@media (max-width: 900px) { .shot--hero { transform: none; } }

/* Two figures lifted out of the screen and set beside it, so the eye has
   something to read before it has finished understanding the picture. */
.chip {
  position: absolute; z-index: 2;
  /* A flat translucent fill rather than a backdrop blur: the blur sits over a
     3D-transformed 1400px screenshot, which is an expensive thing to ask a
     compositor to re-filter, and at this size nobody can tell the difference. */
  background: rgba(9, 32, 31, .92);
  border: 1px solid rgba(240,180,12,.35);
  border-radius: 12px; padding: 11px 15px;
  box-shadow: 0 16px 34px -16px rgba(0,0,0,.7);
}
.chip span { display: block; font-size: 9.5px; line-height: 1.35; letter-spacing: .14em; text-transform: uppercase;
  color: rgba(255,255,255,.6); font-weight: 700; }
.chip b { display: block; margin-top: 3px; font-size: 15px; font-weight: 700; color: var(--gold);
  font-variant-numeric: tabular-nums; }
/* Below the frame and hanging off its left edge, so it sits ON the page rather
   than ON the product. Anything placed over the screenshot covers the thing the
   reader came to look at. */
.chip--a { left: -26px; bottom: -20px; max-width: 260px; }
@media (max-width: 1100px) { .chip--a { left: -10px; } }
@media (max-width: 760px) { .chip { display: none; } }

/* ── A tinted section, so the page is not one long field of the same colour ── */
.section--tint {
  background: linear-gradient(180deg, #eef4f2 0%, var(--bg) 100%);
  border-top: 1px solid var(--line); border-bottom: 1px solid var(--line);
}

/* ── The tour ────────────────────────────────────────────────────────────── */
.tour { max-width: 1120px; margin: 0 auto; }
.tour__tabs {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 10px; margin-bottom: 20px;
}
.tour__tab {
  text-align: left; cursor: pointer;
  background: var(--card); border: 1px solid var(--line); border-radius: 12px;
  padding: 13px 16px; font-family: var(--font);
  transition: border-color .15s ease, transform .15s ease, box-shadow .15s ease;
}
.tour__tab b { display: block; font-size: 14.5px; font-weight: 700; color: var(--ink); }
.tour__tab span { display: block; margin-top: 2px; font-size: 12.5px; color: var(--muted); }
.tour__tab:hover { transform: translateY(-2px); border-color: rgba(12,48,48,.3); box-shadow: var(--shadow); }
.tour__tab.is-on { border-color: var(--gold); box-shadow: 0 0 0 3px rgba(240,180,12,.18); }
.tour__tab.is-on b { color: var(--teal); }
.tour__tab:focus-visible { outline: 3px solid var(--gold); outline-offset: 2px; }
.tour__stage .shot { border-color: rgba(12,48,48,.18); box-shadow: 0 26px 60px -28px rgba(0,51,51,.45); }

/* ── Bento: the module grid stops being eight identical boxes ─────────────── */
@media (min-width: 900px) {
  .grid--bento { grid-template-columns: repeat(6, 1fr); }
  .grid--bento .mod:nth-child(1) { grid-column: span 3; }
  .grid--bento .mod:nth-child(2) { grid-column: span 3; }
  .grid--bento .mod:nth-child(3) { grid-column: span 2; }
  .grid--bento .mod:nth-child(4) { grid-column: span 2; }
  .grid--bento .mod:nth-child(5) { grid-column: span 2; }
  .grid--bento .mod:nth-child(6) { grid-column: span 2; }
  .grid--bento .mod:nth-child(7) { grid-column: span 2; }
  .grid--bento .mod:nth-child(8) { grid-column: span 2; }
}
.mod { transition: transform .16s ease, box-shadow .16s ease, border-color .16s ease; }
.mod:hover { transform: translateY(-3px); border-color: rgba(12,48,48,.22);
  box-shadow: 0 1px 3px rgba(0,51,51,.07), 0 18px 40px -18px rgba(0,51,51,.25); }
.rule { transition: transform .16s ease, background .16s ease; }
.rule:hover { transform: translateY(-3px); background: rgba(255,255,255,.09); }

/* The primary call to action gets one small, slow pulse of attention on
   arrival — once, not a loop, because a button that never stops moving is a
   button people learn to look away from. */
@keyframes ctaGlow {
  0%, 100% { box-shadow: 0 0 0 0 rgba(240,180,12,0); }
  50%      { box-shadow: 0 0 0 10px rgba(240,180,12,.18); }
}
.hero__actions .btn--gold { animation: ctaGlow 2.6s ease 1.1s 2; }
@media (prefers-reduced-motion: reduce) { .hero__actions .btn--gold { animation: none; } }

/* ── The plan picker ───────────────────────────────────────────────────────
   Three steps on one page rather than three pages: the reader can see how far
   through they are and go back without losing the choice they already made. */
.picker { max-width: 1160px; margin: 0 auto; }

.picker__steps {
  display: flex; flex-wrap: wrap; gap: 8px 28px; justify-content: center;
  list-style: none; margin: 0 0 30px; padding: 0;
  font-size: 13px; font-weight: 600; color: var(--muted);
}
.picker__steps li { display: flex; align-items: center; gap: 9px; }
.picker__steps b {
  display: grid; place-items: center; width: 24px; height: 24px; border-radius: 50%;
  background: var(--line); color: var(--muted); font-size: 12px; font-weight: 700;
}
.picker__steps .is-on { color: var(--ink); }
.picker__steps .is-on b { background: var(--gold); color: var(--teal); }
.picker__steps .is-done b { background: var(--teal); color: #fff; }

.picker__head { text-align: center; margin-bottom: 22px; }
.picker__head h3 { margin: 0 0 8px; font-size: clamp(21px, 2.6vw, 27px); letter-spacing: -.01em; }
.picker__sub { margin: 0 auto; max-width: 62ch; font-size: 14px; color: var(--muted); line-height: 1.55; }
.picker__count {
  margin: 14px 0 0; font-size: 13px; font-weight: 700; color: var(--teal);
  min-height: 1.3em;
}
.picker__count.is-warn { color: #b4472f; }
.picker__nav { display: flex; gap: 12px; justify-content: center; margin-top: 28px; flex-wrap: wrap; }
.picker__nav .btn[disabled] { opacity: .45; pointer-events: none; }
.plan__talk { font-size: 30px; letter-spacing: -.02em; }

/* The nine. A whole tile is the target, and the state is carried by more than
   colour — the corner mark changes from + to ✓ — so it survives being read by
   somebody who cannot tell the two backgrounds apart. */
.modgrid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 12px; max-width: 1060px; margin: 0 auto;
}
.modpick {
  position: relative; text-align: left; cursor: pointer;
  display: block; padding: 16px 18px 16px 46px;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
  font: inherit; color: var(--ink);
  transition: border-color .15s ease, background .15s ease, transform .15s ease;
}
.modpick:hover { border-color: rgba(12,48,48,.34); transform: translateY(-1px); }
.modpick b { display: block; font-size: 15px; margin-bottom: 4px; }
.modpick span:not(.modpick__tick) { display: block; font-size: 12.5px; color: var(--muted); line-height: 1.5; }
.modpick__tick {
  position: absolute; left: 16px; top: 17px;
  display: grid; place-items: center; width: 20px; height: 20px; border-radius: 6px;
  background: var(--line); color: var(--muted); font-size: 13px; font-weight: 700;
}
.modpick.is-on { border-color: var(--teal); background: rgba(12,48,48,.045); }
.modpick.is-on .modpick__tick { background: var(--teal); color: #fff; }
/* Still pressable when the quota is full — pressing it explains what would have
   to give, which is more use than a control that ignores you. */
.modpick.is-full { opacity: .55; }
.modpick:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }

.summary {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 14px; max-width: 1060px; margin: 0 auto; text-align: left;
}
.sumcol {
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 18px 20px; box-shadow: var(--shadow);
}
.sumcol h4 {
  margin: 0 0 12px; font-size: 11px; font-weight: 700; letter-spacing: .12em;
  text-transform: uppercase; color: var(--muted);
}
.sumcol ul { list-style: none; margin: 0; padding: 0; }
.sumcol li { font-size: 13px; color: var(--muted); line-height: 1.5; margin-bottom: 9px; }
.sumcol li b { display: block; font-size: 14px; color: var(--ink); font-weight: 600; }
.sumcol--muted { background: rgba(12,48,48,.035); box-shadow: none; }
.sumcol--off { border-style: dashed; box-shadow: none; background: transparent; }
.sumcol--off li { color: var(--muted); }
.sumcol--off .picker__sub { margin-top: 10px; font-size: 12.5px; text-align: left; }

/* ── Setting up: the staged signup ─────────────────────────────────────────
   One card that never moves, with five questions passing through it. The
   background is a still of Finance, blurred — the thing being set up, behind
   the questions about it. It is a picture and not the application, because at
   this point there is no account to run the application with. */
.welcome { min-height: 100vh; position: relative; overflow-x: hidden; }
.welcome__bg { position: fixed; inset: 0; z-index: 0; overflow: hidden; background: var(--teal); }
.welcome__bg img {
  width: 100%; height: 100%; object-fit: cover; object-position: center top;
  /* Blurred enough that no figure can be read, light enough that the shape of
     a system is unmistakable — a sidebar, a row of cards, a table. The first
     attempt sat under a 92% wash and the picture may as well not have been
     there, which defeated the point of putting it there. */
  filter: blur(14px) saturate(112%); transform: scale(1.06);
  opacity: 1;
}
/* A wash over the picture, so text sits on something predictable rather than on
   whichever part of a screenshot happens to be behind it. Heavier at the top
   left, where the brand and the card sit, and lighter at the edges so the
   system stays visible around them. */
.welcome__bg::after {
  content: ''; position: absolute; inset: 0;
  background:
    radial-gradient(120% 90% at 50% 45%, rgba(8,32,32,.72) 0%, rgba(8,32,32,.52) 55%, rgba(8,32,32,.40) 100%),
    linear-gradient(150deg, rgba(12,48,48,.34), rgba(10,39,39,.46));
}

.welcome__stage {
  position: relative; z-index: 1;
  min-height: 100vh; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 22px;
  padding: 40px 20px;
}
.welcome__brand { display: flex; align-items: center; gap: 10px; text-decoration: none; }

.welcome__card {
  width: min(660px, 100%);
  background: var(--card); border-radius: 20px;
  box-shadow: 0 30px 80px -24px rgba(0,0,0,.5);
  padding: clamp(26px, 4vw, 40px);
  transition: opacity .13s ease, transform .13s ease;
}
.welcome__card.is-leaving  { opacity: 0; transform: translateY(-6px); }
.welcome__card.is-entering { opacity: 0; transform: translateY(8px); animation: welcome-in .26s ease forwards; }
@keyframes welcome-in { to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) {
  .welcome__card, .welcome__card.is-entering { transition: none; animation: none; opacity: 1; transform: none; }
  .welcome__bg img { filter: blur(10px); }
}

.welcome__body { display: flex; flex-direction: column; }
.welcome__body--center { align-items: center; text-align: center; }

/* Dots only. A rail listing five headings tells somebody how much is left
   before they have started, which is not encouragement. */
.welcome__rail { display: flex; gap: 6px; list-style: none; margin: 0 0 18px; padding: 0; }
.welcome__dot { width: 22px; height: 4px; border-radius: 999px; background: var(--line); transition: background .25s ease; }
.welcome__dot.is-done { background: var(--ok); }
.welcome__dot.is-on { background: var(--gold); }

.welcome__count {
  margin: 0 0 8px; font-size: 11px; font-weight: 700;
  letter-spacing: .13em; text-transform: uppercase; color: var(--muted);
}
.welcome__title {
  margin: 0 0 10px; font-size: clamp(22px, 3.4vw, 30px); line-height: 1.18;
  letter-spacing: -.015em; font-weight: 700; text-wrap: balance;
}
.welcome__hint { margin: 0 0 22px; font-size: 14px; color: var(--muted); line-height: 1.55; max-width: 56ch; }
.welcome__hint.is-warn { color: #b4472f; font-weight: 600; }
.welcome__content { margin-bottom: 26px; }

.welcome__actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.welcome__spacer { flex: 1; }
.btn--ghost-quiet {
  color: var(--muted); border-color: transparent; background: transparent;
}
.btn--ghost-quiet:hover { color: var(--ink); }

/* The temporary password. Monospace and large enough to read off a screen and
   type into a phone without squinting. */
.welcome__secret {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 16px 18px; margin-bottom: 18px;
  background: var(--bg); border: 1px dashed var(--line); border-radius: 12px;
}
.welcome__secret code {
  font: 700 19px/1 ui-monospace, SFMono-Regular, Menlo, monospace;
  letter-spacing: .06em; color: var(--ink); user-select: all;
}
.welcome__trial { margin: 0 0 20px; font-size: 13px; color: var(--muted); }

.welcome__spinner {
  width: 34px; height: 34px; margin-bottom: 18px; border-radius: 50%;
  border: 3px solid var(--line); border-top-color: var(--gold);
  animation: welcome-spin .8s linear infinite;
}
@keyframes welcome-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .welcome__spinner { animation-duration: 2.4s; } }

.welcome__foot { margin: 0; font-size: 12.5px; color: rgba(255,255,255,.7); text-align: center; }

.welcome .onbchips { display: flex; flex-wrap: wrap; gap: 8px; }
.welcome .onbchip {
  font: 500 14px/1.3 var(--font); color: var(--ink); cursor: pointer;
  padding: 11px 16px; border-radius: 11px; text-align: left;
  background: var(--card); border: 1px solid var(--line);
  transition: border-color .18s ease, background .18s ease, box-shadow .18s ease,
              opacity .18s ease, transform .12s ease;
}
.welcome .onbchip:hover { border-color: var(--muted); transform: translateY(-1px); }
.welcome .onbchip.is-on { border-color: var(--teal); background: rgba(12,48,48,.05); font-weight: 600; }
.welcome .onbchip.is-full { opacity: .5; }
.welcome .onbchip:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
.welcome .onbchip--wide { display: block; width: 100%; padding: 13px 15px; }
.welcome .onbchip--wide b { display: block; font-size: 14px; font-weight: 600; }
.welcome .onbchip--wide span { display: block; margin-top: 2px; font-size: 12.5px; color: var(--muted); line-height: 1.45; }
.welcome .onbgrid { display: grid; grid-template-columns: repeat(auto-fit, minmax(215px, 1fr)); gap: 8px; }

/* The Starter disclaimer under the summary. It spans the whole grid rather than
   sitting in a column, because it qualifies all three of them — and it is set
   apart by a rule above it so it reads as a caveat rather than as more of the
   list it follows. */
.picker__note {
  grid-column: 1 / -1;
  margin-top: 18px; padding-top: 16px;
  border-top: 1px solid var(--line);
  text-align: left;
  font-size: 13px;
}

/* A verdict on one field, under that field.

   Separate from .formnote, which speaks for the whole form. "That address
   already has an account" is about the email box and belongs beneath it —
   putting it at the bottom of the form makes somebody hunt for which of three
   fields it means, and that hunt is the reason this kind of message gets
   ignored. Empty by default and taking no space, so the layout does not shift
   every time a field is checked. */
.fieldnote {
  margin: 6px 0 0; font-size: 13px; line-height: 1.45; color: var(--muted);
  min-height: 0;
}
.fieldnote:empty { display: none; }
.fieldnote.is-err { color: #b4472f; }
.fieldnote.is-ok { color: var(--ok); }
/* The field itself says so too, so the eye lands on the box and not only on
   the sentence under it. */
.signup__form input.is-bad { border-color: #b4472f; }
.signup__form input.is-bad:focus { outline-color: #b4472f; }

/* The annual rate, under the monthly one on each plan card. Quieter than the
   headline price — it is the better deal, not the bigger number, and shouting
   it would make the card read as two prices competing rather than one price
   with a way to pay less. */
.plan__year { margin: 6px 0 0; font-size: 13px; color: var(--ink-2); }
.plan__year b { font-weight: 700; color: var(--ink); }
.plan__year span { color: var(--ok); font-weight: 600; }

/* ── Long-form legal pages ─────────────────────────────────────────────────
   Terms, refunds and cookies. Set for READING rather than for scanning: a
   measure near 65 characters, generous leading, and numbered clauses that can
   be cited in an email ("clause 7.2") — which is most of what a terms page is
   for once there is a disagreement.

   Deliberately plain. A policy dressed up in the marketing palette reads as
   something being sold; these are the pages somebody opens when they are
   unhappy, and they should look like a document. */
.legal {
  max-width: 44rem;
  margin: 0 auto;
  padding: 56px 24px 88px;
}
.legal__meta {
  font-size: 13px;
  color: var(--muted, #6b7d7b);
  border-bottom: 1px solid rgba(12,48,48,.14);
  padding-bottom: 14px;
  margin-bottom: 34px;
}
.legal h1 {
  font-size: clamp(27px, 4.5vw, 38px);
  line-height: 1.12;
  letter-spacing: -.01em;
  margin: 0 0 10px;
  text-wrap: balance;
}
.legal .lede { font-size: 17px; line-height: 1.6; margin: 0 0 8px; }
.legal h2 {
  font-size: 18px;
  margin: 40px 0 10px;
  padding-top: 18px;
  border-top: 1px solid rgba(12,48,48,.12);
}
.legal h2:first-of-type { border-top: 0; padding-top: 0; }
.legal h3 { font-size: 15px; margin: 24px 0 6px; }
.legal p, .legal li { font-size: 15.5px; line-height: 1.68; }
.legal ol, .legal ul { padding-left: 22px; }
.legal li { margin-bottom: 7px; }
.legal ol.clauses { list-style: none; padding-left: 0; counter-reset: clause; }
.legal ol.clauses > li {
  counter-increment: clause;
  position: relative;
  padding-left: 42px;
  margin-bottom: 15px;
}
.legal ol.clauses > li::before {
  content: counter(clause);
  position: absolute; left: 0; top: 0;
  width: 30px; text-align: right;
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  color: var(--muted, #6b7d7b);
}
/* The one box on the page: what a reader most needs and would otherwise have
   to assemble from three clauses. One per page, or it stops meaning anything. */
.legal .keypoint {
  background: rgba(240,180,12,.09);
  border-left: 3px solid var(--gold, #f0b40c);
  border-radius: 0 8px 8px 0;
  padding: 15px 18px;
  margin: 22px 0;
}
.legal .keypoint p { margin: 0; }
.legal table { width: 100%; border-collapse: collapse; margin: 18px 0; font-size: 14.5px; }
.legal th, .legal td {
  text-align: left; padding: 9px 10px;
  border-bottom: 1px solid rgba(12,48,48,.12);
  vertical-align: top;
}
.legal th { font-size: 12.5px; text-transform: uppercase; letter-spacing: .05em; color: var(--muted, #6b7d7b); }
.legal code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 13.5px;
  background: rgba(12,48,48,.06);
  padding: 1px 5px; border-radius: 4px;
}
.legal__nav {
  display: flex; flex-wrap: wrap; gap: 8px 18px;
  margin-top: 46px; padding-top: 18px;
  border-top: 1px solid rgba(12,48,48,.14);
  font-size: 14px;
}
.legal__nav a[aria-current="page"] { font-weight: 600; text-decoration: none; }

/* ── Printing a policy ─────────────────────────────────────────────────────
   Terms and a refund policy get printed, attached to emails and filed. What a
   reader needs on paper is not what they need on screen: the navigation and
   the sign-in button do nothing on a sheet of paper, and the storage notice
   floating over the text is worse than useless.

   The two things paper needs that a screen does not: the URL of each link
   spelled out, since a reader cannot click it, and a rule against a heading
   being orphaned at the foot of a page. */
@media print {
  .nav, .foot, .legal__nav { display: none !important; }

  body { background: #fff; color: #111; font-size: 10.5pt; line-height: 1.55; }
  .legal { max-width: none; padding: 0; margin: 0; }
  .legal h1 { font-size: 22pt; }
  .legal .lede { font-size: 12pt; }
  .legal p, .legal li { font-size: 10.5pt; }

  /* A heading at the very bottom of a page, with its clauses over the fold,
     reads as the end of the document. */
  .legal h2, .legal h3 { break-after: avoid; page-break-after: avoid; }
  .legal ol.clauses > li, .legal tr, .legal .keypoint { break-inside: avoid; page-break-inside: avoid; }

  .legal .keypoint { border-left-width: 3px; background: #f6f2e4; }
  .legal table { font-size: 10pt; }
  .legal code { background: #f0f0f0; }

  /* A link is a dead end on paper unless it says where it goes. Internal
     paths get the full address; anything already absolute is left alone. */
  .legal a[href^="/"]::after { content: " (cinatgrind.online" attr(href) ")"; font-size: 9pt; color: #555; }
  .legal a { color: #111; text-decoration: underline; }

  @page { size: A4; margin: 18mm 16mm 20mm; }
}


/* At phone width the logo, the wordmark and two pill buttons came to about
   450px, so the start and pricing pages scrolled sideways at 375px. */
@media (max-width: 480px) {
  .nav { gap: 12px; }
  .nav .wordmark { display: none; }
  .nav__cta .btn { padding: 10px 14px; }
}

/* ── The first-day tour ────────────────────────────────────────────────────
   A round play icon beside the calls to action, and the video in a dialog. */
.tourbtn {
  display: inline-flex; align-items: center; gap: 10px; background: none; border: 0;
  padding: 6px 4px; font: inherit; font-weight: 700; font-size: 15px; color: var(--teal);
  cursor: pointer;
}
.hero .tourbtn { color: #fff; }
.tourbtn__icon {
  width: 46px; height: 46px; border-radius: 50%; display: inline-grid; place-items: center;
  background: var(--gold); color: var(--teal); box-shadow: 0 0 0 6px rgba(242,178,26,.22);
  transition: transform .15s ease, box-shadow .15s ease;
}
.tourbtn:hover .tourbtn__icon { transform: scale(1.06); box-shadow: 0 0 0 9px rgba(242,178,26,.25); }
.tourbtn:focus-visible { outline: 3px solid var(--gold); outline-offset: 4px; border-radius: 30px; }
.tourbtn__icon svg { margin-left: 3px; }

.tourbox {
  position: fixed; inset: 0; z-index: 1000; display: grid; place-items: center;
  background: rgba(4, 20, 20, .78); padding: 16px;
}
.tourbox__card {
  width: min(1080px, 100%); background: #0c3030; border-radius: 16px; overflow: hidden;
  box-shadow: 0 30px 80px rgba(0,0,0,.45); border: 1px solid rgba(242,178,26,.35);
}
.tourbox__head {
  display: flex; align-items: center; justify-content: space-between; padding: 12px 16px; color: #fff;
}
.tourbox__close {
  background: none; border: 0; color: #fff; font-size: 26px; line-height: 1; cursor: pointer; padding: 2px 8px;
}
.tourbox video { display: block; width: 100%; max-height: calc(100vh - 140px); background: #000; }
.tourbox__note { margin: 0; padding: 10px 16px 14px; color: rgba(255,255,255,.72); font-size: 13px; }
@media (max-width: 480px) {
  .tourbtn__text { font-size: 14px; }
  .tourbtn__icon { width: 40px; height: 40px; }
}

/* A chosen module is marked with a ring rather than bolder text: bold changed
   the width of every line in the card, so the text jumped as it was chosen. */
.welcome .onbchip--wide.is-on { font-weight: 500; box-shadow: 0 0 0 2px var(--teal) inset; }
@media (prefers-reduced-motion: reduce) { .welcome .onbchip { transition: none; } }

/* The plan somebody chose on the pricing page, said above the sign-up form. */
.signup__plan {
  margin: 14px 0 4px; padding: 12px 14px; border-radius: 12px;
  background: rgba(242,178,26,.14); border: 1px solid rgba(242,178,26,.55);
  color: var(--teal); font-weight: 600; font-size: 14.5px; line-height: 1.5;
}

.picker__first {
  margin: 14px 0 0; padding: 12px 14px; border-radius: 12px;
  background: rgba(242,178,26,.14); border: 1px solid rgba(242,178,26,.55);
  color: var(--teal); font-weight: 600; font-size: 14.5px; line-height: 1.5;
}
.picker__first:empty { display: none; }
