/* Followly bookkeeping site. Design plan, and the build follows it.
 1. Treatment: warm professional. Approachable enough to feel like a firm you would ring, exact
    enough that every number on the page is checkable. Colour and shape do the warming; the
    figures stay in a tabular mono so nothing about the price is fuzzy.
 2. Palette, one light theme, painted explicitly: Ink #12233B text, Paper #F6F7F4 ground,
    Cream #FBF7EE second warm ground, Reconciled #1E7A55 accent, Deep #10303F for the hero band,
    Reconciled tint #E8F3EC, Mist #DCE3DD hairlines, Slate #5B6B7A secondary text.
    ⚠️ Deep moved from a green #124A36 to a navy-teal #10303F on 2026-09-21. Green on green left
    the accent with nothing to be an accent against; the trust colour in this trade is navy and
    the money colour is green, so the band went navy and the button stayed green.
 3. Rhythm comes from alternating band backgrounds, not from rules. Two hairlines survive, under
    the header and above the footer, where a Paper band meets a Paper band.
 4. Type roles: Plus Jakarta Sans 700 for headings and the wordmark, Source Sans 3 for running
    text and for every label and eyebrow, IBM Plex Mono with tabular numerals for the ABN line
    that survives on the legal and 404 pages. Nothing else is set in mono.
 5. Scale is fixed at 14 16 18 22 28 36 48. Running text stops at 65ch so it stays readable.
 6. Shape: 14px cards with a soft shadow, 10px buttons, and a 12px hero button that is the one
    lifted object on the page. On the Deep band the primary button stays green rather than
    inverting to paper: see the note above .band-deep .btn-primary.
 7. Content carries the subject in words, because there is nothing to price on the page: the
    four situation lines name the state the reader is in, the headline names what changes, and
    the one call is the only step offered. No slider, no pack contents, no sample note, no
    calculator and no line icons.
 8. Logo: a rounded square in Reconciled green holding a tick whose right tail runs out into a
    ledger line. The mark is the reconciliation, drawn once.
 9. Mobile first. One column throughout at every width, a sticky primary CTA on phones, and the
    hero CTA full width below 720px. The site carries no photographs and no illustrations: the
    work is shown in words.
10. Accessibility: every text and surface pair checked at 4.5:1 or better, visible focus ring,
    motion respected, decorative SVG hidden from the accessibility tree, nothing carried by
    colour alone.
*/

:root {
  --ink: #12233B;
  --paper: #F6F7F4;
  --cream: #FBF7EE;
  --reconciled: #1E7A55;
  --deep: #10303F;
  --tint: #E8F3EC;
  --mist: #DCE3DD;
  --slate: #5B6B7A;
  --card: #FFFFFF;

  /* Text on the Deep band. 12.9:1 and 7.9:1 against #10303F. The dim tone cooled with the band:
     the old #C5D8CE was a green-grey mixed for a green ground and read slightly sick on navy. */
  --on-deep: #F6F7F4;
  --on-deep-dim: #B8C6D0;

  --display: "Plus Jakarta Sans", "Segoe UI", system-ui, -apple-system, Helvetica, Arial, sans-serif;
  --body: "Source Sans 3", "Segoe UI", system-ui, -apple-system, Helvetica, Arial, sans-serif;
  --mono: "IBM Plex Mono", "SFMono-Regular", Consolas, "Liberation Mono", monospace;

  --s1: 0.5rem;
  --s2: 0.875rem;
  --s3: 1.25rem;
  --s4: 2rem;
  --s5: 3rem;
  --s6: 4.5rem;

  --r-sm: 8px;
  --r-btn: 10px;
  --r-card: 14px;
  --r-calc: 16px;

  --shadow-card: 0 1px 2px rgba(18, 35, 59, 0.04), 0 6px 18px rgba(18, 35, 59, 0.06);
  --shadow-lift: 0 2px 4px rgba(18, 35, 59, 0.05), 0 14px 34px rgba(18, 35, 59, 0.10);

  --wrap: 1120px;
}

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

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--body);
  font-size: 1rem;
  line-height: 1.55;
  font-synthesis-weight: none;
}

img, svg { max-width: 100%; }

[hidden] { display: none !important; }

h1, h2, h3 {
  font-family: var(--display);
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: -0.015em;
  text-wrap: balance;
  margin: 0;
}

h1 { font-size: 2.25rem; }
h2 { font-size: 1.75rem; }
h3 { font-size: 1.125rem; }

p { margin: 0; max-width: 65ch; }

a { color: var(--reconciled); }

a:focus-visible,
button:focus-visible,
input:focus-visible,
summary:focus-visible {
  outline: 2px solid var(--reconciled);
  outline-offset: 3px;
  border-radius: 2px;
}

.band-deep a:focus-visible,
.band-deep button:focus-visible { outline-color: var(--on-deep); }

/* Layout ------------------------------------------------------------------ */

.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--s3);
}

.band { padding-block: var(--s5); }

.band-paper { background: var(--paper); }
.band-cream { background: var(--cream); }
.band-tint { background: var(--tint); }

.band-deep {
  background: var(--deep);
  color: var(--on-deep);
}

.band-deep h1,
.band-deep h2,
.band-deep h3 { color: var(--on-deep); }

.band-deep .lede,
.band-deep .small,
.band-deep p { color: var(--on-deep-dim); }

.band-deep .eyebrow { color: var(--on-deep-dim); }

/*
 * Bands are separated by their background, never by a rule. The only hairlines on the site are
 * under the header and above the footer, where a Paper band meets a Paper band and the colour
 * change cannot do the work. Both are declared on those two elements.
 */

.stack {
  display: flex;
  flex-direction: column;
  gap: var(--s3);
  align-items: flex-start;
}

.stack-tight { gap: var(--s1); }
.stack-wide { gap: var(--s4); }

.eyebrow {
  font-family: var(--body);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--slate);
  margin: 0;
}

.lede {
  font-size: 1.125rem;
  color: var(--slate);
}

.small { font-size: 0.875rem; color: var(--slate); }

/* Figures a reader compares stay tabular, in the body face unless they are a price. */
.num { font-variant-numeric: tabular-nums; }

.figures {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
}

/* Header ------------------------------------------------------------------ */

.site-header {
  background: var(--paper);
  border-bottom: 1px solid var(--mist);
  padding-block: var(--s2);
}

.header-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s3);
  justify-content: space-between;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  text-decoration: none;
  color: var(--ink);
}

.brand-word {
  font-family: var(--display);
  font-weight: 700;
  font-size: 1.375rem;
  letter-spacing: -0.02em;
}

.site-nav {
  display: flex;
  align-items: center;
  gap: var(--s3);
  font-size: 0.9375rem;
}

.site-nav a {
  color: var(--slate);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  padding-bottom: 2px;
}

.site-nav a:hover { color: var(--ink); border-bottom-color: var(--mist); }

.site-nav .btn { padding: 0.5rem 0.9375rem; font-size: 0.9375rem; }
.site-nav .btn:hover { border-bottom-color: transparent; }

/*
 * ⚠️ The nav link colour must not reach a button inside the nav. `.site-nav a` (0,1,1) outranks
 * `.btn-primary` (0,1,0), so without these two rules the header CTA renders slate text on the
 * green fill: 1.04:1, which reads as a disabled control rather than a button. Hover was the same
 * problem one step further on, because `.btn-primary:hover` sets no colour at all and `.site-nav
 * a:hover` (0,2,0) supplied `--ink` on the darker green. White is 5.3:1 at rest and 7.3:1 hovered.
 */
.site-nav a.btn-primary,
.site-nav a.btn-primary:hover { color: #FFFFFF; }

/*
 * The header button is a desktop affordance. On phones the sticky bar carries it.
 *
 * ⚠️ Both rules are scoped to `.site-nav` on purpose. Unscoped, `.header-cta { display: none }`
 * (0,1,0) loses to `.btn { display: inline-flex }` (0,1,0) further down this file purely on source
 * order, so the hide never happened and phones showed two CTAs at once. Scoping makes the pair
 * order-independent: if the buttons block ever moves, this still works. Keep both scoped, or the
 * media query loses to the hide and the button never returns on desktop.
 */
.site-nav .header-cta { display: none; }

@media (min-width: 900px) {
  .site-nav .header-cta { display: inline-flex; }
}

/* Buttons ----------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  font-family: var(--body);
  font-size: 1rem;
  font-weight: 600;
  line-height: 1.2;
  padding: 0.8125rem 1.375rem;
  border-radius: var(--r-btn);
  text-decoration: none;
  border: 1px solid transparent;
  cursor: pointer;
  transition: background-color 120ms ease, border-color 120ms ease, color 120ms ease,
    transform 120ms ease;
}

/*
 * Two sizes above the default. .btn-hero is the single first-screen call to action and is the
 * only button on the site that lifts on hover; .btn-lg is the mid-page repeat, larger than body
 * copy but not competing with the hero. The sticky mobile bar and the header CTA keep their own
 * sizes: both are chrome, and a chrome control that grows starts eating the page.
 *
 * The reduced-motion block at the foot of this file zeroes every transition duration, so the
 * lift lands instantly there rather than animating.
 */
.btn-hero {
  font-size: 1.25rem;
  padding: 1.125rem 2.25rem;
  border-radius: 12px;
  box-shadow: var(--shadow-lift);
}

.btn-hero:hover { transform: translateY(-1px); }

.btn-lg { font-size: 1.125rem; padding: 1rem 1.875rem; }

/*
 * On a phone the hero CTA is the full column, so it cannot be half-missed.
 *
 * ⚠️ `width: 100%` ON THE BUTTON IS NOT ENOUGH ON ITS OWN, and the reason is worth keeping.
 * `.stack` is a column flex container with `align-items: flex-start`, so `.btn-row` shrink-wraps
 * to its content. A percentage width on the button then resolves against that shrink-wrapped
 * parent and returns the width it already had: measured 259px inside a 320px column, i.e. the
 * rule looked applied and did nothing. Stretching the row is what gives the percentage something
 * real to be a percentage of. Scoped to .hero so no other button row changes shape.
 */
@media (max-width: 719px) {
  .hero .btn-row { align-self: stretch; }
  .btn-hero { width: 100%; }
}

.btn-primary {
  background: var(--reconciled);
  color: #FFFFFF;
  border-color: var(--reconciled);
}

.btn-primary:hover { background: #176244; border-color: #176244; }

.btn-secondary {
  background: transparent;
  color: var(--ink);
  border-color: var(--ink);
}

.btn-secondary:hover { background: var(--tint); border-color: var(--reconciled); }

/*
 * Inside the Deep band the primary button stays green. Until 2026-09-21 it inverted to paper,
 * which was the right call while the band was green and the button would have vanished into it.
 * On the navy band the green is the one warm thing on a cool field, so it reads as the thing to
 * press without having to shout, and the button looks the same everywhere on the site.
 *
 * White on #1E7A55 is 5.29:1 and white on the hover #1B6E4C is 6.21:1, both clear of 4.5:1.
 *
 * ⚠️ The button's EDGE against the band is 2.62:1 (green #1E7A55 on navy #10303F), under the 3:1
 * that WCAG 1.4.11 asks of a component boundary. What identifies this control is its white label
 * at 5.29:1, not its outline, and .btn-hero carries a shadow as well. Recorded rather than fixed:
 * lifting it would mean lightening the green, which changes the brand colour everywhere.
 */
.band-deep .btn-primary {
  background: var(--reconciled);
  color: #FFFFFF;
  border-color: var(--reconciled);
}

.band-deep .btn-primary:hover { background: #1B6E4C; border-color: #1B6E4C; }

.band-deep .btn-secondary {
  color: var(--on-deep);
  border-color: rgba(246, 247, 244, 0.55);
  background: transparent;
}

.band-deep .btn-secondary:hover {
  background: rgba(246, 247, 244, 0.12);
  border-color: var(--on-deep);
}

/*
 * An inline link inside a deep-band paragraph. The element rule `a { color: var(--reconciled) }`
 * beats the band's inherited colour, and that green is 2.62:1 on the navy — well under 4.5:1, so
 * it would be a link a reader cannot comfortably read. On this band the link takes the paper text
 * colour (12.9:1) and earns its affordance from the underline and the weight instead.
 */
.band-deep p a {
  color: var(--on-deep);
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 3px;
}

.band-deep p a:hover { color: #FFFFFF; }

.btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2);
  align-items: center;
}

/* Hero -------------------------------------------------------------------- */

/*
 * A single-column text band. The paragraphs cap their own measure at 65ch through the global `p`
 * rule, so this column exists only to stop the HEADLINE running the full width of the wrap.
 *
 * ⚠️ IT IS A rem, NOT A ch, AND THAT IS THE WHOLE POINT. `ch` resolves against the element's own
 * font, and this div inherits the 16px body face, so 65ch here was about 550px — narrower than
 * anything the 68px headline needs, and it bound before the h1's own max-width ever could. The
 * result was a headline in four two-word lines at 1280. 56rem is 896px, which lets the headline
 * land as "We get your books / up to date, every week."
 */
.hero .stack { max-width: 56rem; }

/*
 * The hero headline is the one piece of type on the site that is allowed to be loud, so it is
 * scoped to .hero: the h2s and the legal pages' h1 keep the 700 weight and the fixed scale.
 *
 * No max-width here. The non-breaking spaces in the markup hold "up to date" and "every week"
 * together, and `text-wrap: balance` (set on every heading) evens the two lines out. A ch-based
 * cap on top of those two only reintroduces the bug above.
 */
.hero h1 {
  font-size: clamp(2.5rem, 7vw, 4.25rem);
  font-weight: 800;
  line-height: 1.04;
  letter-spacing: -0.025em;
}

/*
 * The hero's plain paragraph carries the inline "Book a call" link, so it is the one route into
 * the booking page that is not a button. At the base 1rem it sat under a 1.375rem lede and was
 * the smallest type on the screen, which is the wrong place for a call to action. Lifted here and
 * again in the wide type scale at the foot of this file. `:not(.lede)` so the lede keeps its own
 * size and this never becomes two rules fighting over the same element.
 */
.hero p:not(.lede) { font-size: 1.0625rem; }

/* Columns ----------------------------------------------------------------- */

.cols {
  display: grid;
  gap: var(--s3);
  grid-template-columns: 1fr;
  width: 100%;
}

@media (min-width: 720px) {
  .cols { gap: var(--s4); }
  .cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

.col {
  display: flex;
  flex-direction: column;
  gap: var(--s1);
}

.col p { max-width: 42ch; }

/* A card is the default shape for anything grouped. */
.card {
  background: var(--card);
  border: 1px solid var(--mist);
  border-radius: var(--r-card);
  box-shadow: var(--shadow-card);
  padding: var(--s3);
}

@media (min-width: 720px) { .card { padding: var(--s4) var(--s3); } }

.card-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 2.75rem;
  border-radius: 50%;
  background: var(--tint);
  color: var(--reconciled);
  margin-bottom: var(--s1);
}

/* Icons ------------------------------------------------------------------- */

.icon {
  width: 24px;
  height: 24px;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.75;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Lists ------------------------------------------------------------------- */

/*
 * The four situation lines. Deliberately a list and not cards: they are one line each, they are
 * read as a set, and a card apiece would give four short sentences the visual weight of four
 * features. No icons, no numbering, a hairline between them and room to breathe.
 */
.situations {
  list-style: none;
  margin: 0;
  padding: 0;
  width: 100%;
  max-width: 62ch;
}

.situations li {
  padding-block: var(--s2);
  line-height: 1.7;
}

/* Between the items, so the list does not read as a boxed thing with edges. */
.situations li + li { border-top: 1px solid var(--mist); }

.dashes {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--s2);
  max-width: 62ch;
}

.dashes li {
  position: relative;
  padding-left: 1.75rem;
}

.dashes li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.75rem;
  width: 1rem;
  height: 0;
  border-top: 2px solid var(--slate);
}

.ticks {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--s2);
  max-width: 66ch;
}

.ticks li {
  position: relative;
  padding-left: 1.75rem;
}

.ticks li::before {
  content: "";
  position: absolute;
  left: 0.25rem;
  top: 0.3rem;
  width: 0.45rem;
  height: 0.85rem;
  border-right: 2px solid var(--reconciled);
  border-bottom: 2px solid var(--reconciled);
  transform: rotate(45deg);
}

/* FAQ --------------------------------------------------------------------- */

.faq {
  width: 100%;
  max-width: 78ch;
  background: var(--card);
  border: 1px solid var(--mist);
  border-radius: var(--r-card);
  box-shadow: var(--shadow-card);
  padding: 0 var(--s3);
}

.faq details { border-bottom: 1px solid var(--mist); }
.faq details:last-child { border-bottom: 0; }

.faq summary {
  cursor: pointer;
  padding: var(--s2) 2rem var(--s2) 0;
  font-weight: 600;
  font-size: 1.0625rem;
  position: relative;
  list-style: none;
}

.faq summary::-webkit-details-marker { display: none; }

.faq summary::after {
  content: "";
  position: absolute;
  right: 0.5rem;
  top: 1.35rem;
  width: 0.5rem;
  height: 0.5rem;
  border-right: 2px solid var(--reconciled);
  border-bottom: 2px solid var(--reconciled);
  transform: rotate(45deg);
  transition: transform 120ms ease;
}

.faq details[open] summary::after { transform: rotate(225deg); top: 1.55rem; }

.faq details p {
  padding: 0 0 var(--s3);
  color: var(--slate);
}

.faq details p + p { padding-top: 0; }

/* Footer ------------------------------------------------------------------ */

.site-footer {
  background: var(--paper);
  border-top: 1px solid var(--mist);
  padding-block: var(--s4);
  font-size: 0.875rem;
  color: var(--slate);
}

.footer-row {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--s3) var(--s4);
  align-items: start;
}

@media (min-width: 720px) {
  .footer-row { grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr); }
}

.footer-links {
  display: flex;
  flex-direction: column;
  gap: var(--s1);
}

.site-footer a { color: var(--slate); }
.site-footer a:hover { color: var(--ink); }

.footer-credit { font-size: 0.8125rem; }

/* Sticky mobile CTA -------------------------------------------------------- */

.sticky-cta {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  background: var(--paper);
  border-top: 1px solid var(--mist);
  padding: 0.625rem var(--s3);
  z-index: 20;
  display: none;
}

.sticky-cta .btn { width: 100%; }

@media (max-width: 719px) {
  .sticky-cta { display: block; }
  body.has-sticky { padding-bottom: 4.75rem; }
}

/* Landing page ------------------------------------------------------------ */

.lp-header {
  background: var(--paper);
  border-bottom: 1px solid var(--mist);
  padding-block: var(--s2);
}

.lp-hero { padding-block: var(--s3); }
.lp-hero h1 { font-size: 1.75rem; }
.lp-band { padding-block: var(--s4); }

@media (min-width: 720px) {
  .lp-hero { padding-block: var(--s4); }
  .lp-hero h1 { font-size: 2.25rem; }
}

/* Legal pages ------------------------------------------------------------- */

.prose {
  max-width: 68ch;
  display: flex;
  flex-direction: column;
  gap: var(--s3);
}

.prose h2 { font-size: 1.375rem; margin-top: var(--s3); }

.prose ul {
  margin: 0;
  padding-left: 1.25rem;
  display: flex;
  flex-direction: column;
  gap: 0.375rem;
  max-width: 65ch;
}

/* Type scale at wider viewports ------------------------------------------- */

@media (min-width: 720px) {
  h1 { font-size: 3rem; }
  h2 { font-size: 2.25rem; }
  .lede { font-size: 1.375rem; }
  .calc-price { font-size: 3rem; }
  .band { padding-block: var(--s6); }
  .proof { padding-block: var(--s3); }

  /*
   * Desktop only. The mobile sizes are deliberately left where they are: the 375 fold already
   * reads correctly and a larger button there would only push the copy further down.
   *
   * Beside a 68px headline the base button is small enough to read as a footnote, and the four
   * situation lines at 1rem sat thin under a 2.25rem h2. All four of these are size-only.
   */
  .hero p:not(.lede) { font-size: 1.25rem; }
  .btn-hero { font-size: 1.375rem; padding: 1.25rem 2.75rem; }
  .btn-lg { font-size: 1.1875rem; }
  .situations li { font-size: 1.125rem; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}
