:root {
  --bg: #faf8f5;
  --surface: #ffffff;
  --ink: #16262e;
  --ink-muted: #5a6b73;
  --line: #e2ded7;
  --pill-bg: #f1ede7;
  --brand: #0b8340;
  --brand-vivid: #25d366;
  --on-brand: #05230f;
  --brand-strong: #1cba58;
  --brand-soft: #e4f9ec;
  --brand-ink: #054d27;
  --accent: #a85a19;
  --accent-soft: #fdf1e4;
  --ok-line: #9ecdb4;
  --ok-bg: #ecf6f0;
  --ok-ink: #1c6844;
  --bad-line: #e4b3ac;
  --bad-bg: #fdf1ef;
  --bad-ink: #9d3a30;
  --warn-line: #e3c89a;
  --warn-bg: #fdf6ea;
  --warn-ink: #855c18;
  --shadow-card: 0 1px 2px rgba(22, 38, 46, 0.04), 0 2px 8px rgba(22, 38, 46, 0.04);
  --radius: 0.75rem;
}

@media (prefers-color-scheme: dark) {
  :root {
  --bg: #10171a;
  --surface: #172126;
  --ink: #e9eeef;
  --ink-muted: #9aaab0;
  --line: #27353a;
  --pill-bg: #1f2c31;
  --brand: #3ddc84;
  --brand-vivid: #25d366;
  --on-brand: #05230f;
  --brand-strong: #4ae077;
  --brand-soft: #0e2a19;
  --brand-ink: #8df0b5;
  --accent: #e09455;
  --accent-soft: #2c2018;
  --ok-line: #2f6b4d;
  --ok-bg: #152620;
  --ok-ink: #84d3aa;
  --bad-line: #6d3630;
  --bad-bg: #271a18;
  --bad-ink: #e6a099;
  --warn-line: #6a5429;
  --warn-bg: #272014;
  --warn-ink: #dcbb74;
  --shadow-card: 0 1px 2px rgba(0, 0, 0, 0.3);
  }
}

/* Layout for sitwise.uk. The colour tokens are prepended at build time from
   app/src/index.css, so every value here is a var() and none is a literal. */

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

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

/* System fonts on purpose: a webfont is a render-blocking request on a page
   whose whole job is to load instantly on a parent's phone. */

a { color: var(--brand); text-decoration-thickness: 1px; text-underline-offset: 2px; }
a:hover { color: var(--brand-ink); }

.wrap { width: min(68rem, 100% - 2.5rem); margin-inline: auto; }
.narrow { width: min(44rem, 100% - 2.5rem); margin-inline: auto; }

/* header */
.site-head {
  position: sticky; top: 0; z-index: 10;
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--line);
}
/* Wraps, and that is load-bearing. Left on one line the four nav items have a
   min-content width wider than a phone, which does not clip the header -- it
   widens the whole document, and every section below it then overflows to the
   right. Measured at 430px: 471px of content in a 430px viewport. */
.site-head__inner { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem 1rem; padding: 0.7rem 0; }
.brandmark { display: flex; align-items: center; gap: 0.55rem; font-weight: 700; font-size: 1.15rem; color: var(--ink); text-decoration: none; }
.brandmark b { color: var(--brand); font-weight: 700; }
.site-nav { margin-left: auto; display: flex; flex-wrap: wrap; gap: 0.4rem 1.1rem; font-size: 0.9rem; }
.site-nav a { color: var(--ink-muted); text-decoration: none; }
.site-nav a:hover { color: var(--brand); }

@media (max-width: 30rem) {
  .wrap, .narrow { width: calc(100% - 2rem); }
  .site-nav { gap: 0.3rem 0.8rem; font-size: 0.85rem; }
}

/* hero
   A soft brand wash rather than flat off-white, so the first screen has some
   colour without putting text on the vivid green, which is 1.98:1 and unusable
   for anything but a fill. */
.hero {
  padding: 4.2rem 0 2.6rem;
  text-align: center;
  background:
    radial-gradient(60rem 22rem at 50% -8rem, var(--brand-soft), transparent 70%);
}
.hero h1 { margin: 0 0 1rem; font-size: clamp(2.1rem, 5.5vw, 3.4rem); line-height: 1.1; letter-spacing: -0.02em; }
.hero p { margin: 0 auto 1.6rem; max-width: 38rem; font-size: clamp(1.02rem, 2.2vw, 1.2rem); color: var(--ink-muted); }
.hero__cta { display: flex; flex-wrap: wrap; gap: 0.7rem; justify-content: center; }

/* The three things a parent wants to know before scrolling. */
.trust {
  display: flex; flex-wrap: wrap; gap: 0.5rem 1.4rem; justify-content: center;
  margin-top: 2rem; font-size: 0.86rem; color: var(--ink-muted);
}
.trust span { display: inline-flex; align-items: center; gap: 0.4rem; }
.trust span::before {
  content: ''; width: 0.45rem; height: 0.45rem; border-radius: 999px;
  background: var(--brand-vivid);
}

.btn {
  display: inline-block; padding: 0.72rem 1.3rem; border-radius: 0.65rem;
  font-weight: 600; font-size: 0.97rem; text-decoration: none; border: 1px solid transparent;
}
.btn--primary { background: var(--brand); color: var(--surface); }
.btn--primary:hover { background: var(--brand-ink); color: var(--surface); }
.btn--ghost { border-color: var(--line); color: var(--ink); background: var(--surface); }
.btn--ghost:hover { border-color: var(--brand); color: var(--brand); }

/* sections */
section { padding: 3rem 0; }
h2 { font-size: clamp(1.45rem, 3.2vw, 2rem); margin: 0 0 0.6rem; letter-spacing: -0.01em; }
.lede { color: var(--ink-muted); margin: 0 0 1.8rem; max-width: 42rem; }

.grid { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)); }

/* Cards are a column so the price sits on the bottom edge whatever the length
   of the summary above it. Ragged prices read as a layout fault on the one row
   a parent actually compares. */
.card {
  display: flex; flex-direction: column;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 1.15rem; box-shadow: var(--shadow-card);
  transition: border-color 120ms ease, transform 120ms ease;
}
.card:hover { border-color: var(--brand); transform: translateY(-2px); }
.card h3 { margin: 0 0 0.3rem; font-size: 1.02rem; }
.card p { margin: 0; color: var(--ink-muted); font-size: 0.92rem; }

.pack__meta {
  display: flex; align-items: baseline; justify-content: space-between; gap: 0.5rem;
  margin-top: auto; padding-top: 0.9rem;
}
.pack__price { font-weight: 700; font-size: 1.15rem; color: var(--ink); }
.pack__count { font-size: 0.82rem; color: var(--ink-muted); }
.pill { align-self: flex-start; display: inline-block; padding: 0.15rem 0.5rem; border-radius: 999px; background: var(--pill-bg); color: var(--ink-muted); font-size: 0.74rem; font-weight: 600; }

/* a plain feature row */
.steps { counter-reset: step; display: grid; gap: 1.4rem; grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr)); }
.step h3 { margin: 0.4rem 0 0.25rem; font-size: 1rem; }
.step p { margin: 0; color: var(--ink-muted); font-size: 0.92rem; }
.step__n {
  display: inline-grid; place-items: center; width: 1.9rem; height: 1.9rem; border-radius: 999px;
  background: var(--brand-soft); color: var(--brand-ink); font-weight: 700; font-size: 0.85rem;
}

/* faq */
details { border-bottom: 1px solid var(--line); padding: 0.85rem 0; }
details summary { cursor: pointer; font-weight: 600; list-style: none; }
details summary::-webkit-details-marker { display: none; }
details summary::after { content: '+'; float: right; color: var(--ink-muted); }
details[open] summary::after { content: '\2212'; }
details p { margin: 0.6rem 0 0; color: var(--ink-muted); }

/* prose pages */
.prose { padding: 2.5rem 0 3rem; }
.prose h1 { font-size: clamp(1.8rem, 4vw, 2.4rem); margin: 0 0 0.4rem; }
.prose h2 { font-size: 1.2rem; margin: 2rem 0 0.4rem; }
.prose p, .prose li { color: var(--ink); }
.prose ul { padding-left: 1.2rem; }
.prose .updated { color: var(--ink-muted); font-size: 0.87rem; margin-top: 0; }
.callout {
  border: 1px solid var(--warn-line); background: var(--warn-bg); color: var(--warn-ink);
  border-radius: var(--radius); padding: 0.9rem 1rem; font-size: 0.92rem;
}
.callout strong { color: inherit; }

/* footer */
.site-foot { border-top: 1px solid var(--line); padding: 2rem 0 3rem; color: var(--ink-muted); font-size: 0.87rem; }
.site-foot nav { display: flex; flex-wrap: wrap; gap: 1rem; margin-bottom: 0.8rem; }
.site-foot a { color: var(--ink-muted); text-decoration: none; }
.site-foot a:hover { color: var(--brand); }

:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; border-radius: 4px; }

@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
}

/* Buying by hand, while the stores are slow. One row per pack. */
.card__buy { margin-top: 0.9rem; text-align: center; }

.buyrow {
  display: flex; flex-wrap: wrap; gap: 1rem; align-items: center;
  justify-content: space-between;
  padding: 1rem 0; border-bottom: 1px solid var(--line);
}
.buyrow h3 { margin: 0 0 0.2rem; font-size: 1rem; }
.buyrow p { margin: 0; color: var(--ink-muted); font-size: 0.9rem; max-width: 32rem; }
/* A column, not a row. It held a price and a button, and two consent
   sentences will not sit beside them.

   The column is the whole fix, measured: with align-items: center restored
   the page overflows by 77px at 360, 47px at 390 and 7px at 430, and
   scripts/check-site-visual.mjs names .buyrow__todo as what hangs off the
   edge. The flex basis and min-width below are not what stops that -- taking
   them out changes nothing -- they are there so this half can shrink when
   the row DOES sit side by side on a wide screen. Said precisely because a
   comment claiming the wrong rule is load-bearing sends the next person to
   delete the right one. */
.buyrow__pay {
  display: flex; flex-direction: column; align-items: flex-start;
  gap: 0.5rem; flex: 1 1 18rem; min-width: 0;
}

/* The placeholder shouts on purpose: a Buy button that goes nowhere is worse
   than an obviously unfinished one, and site.test.ts fails while it is here. */
.buyrow__todo {
  margin: 0; padding: 0.4rem 0.7rem; border: 1px dashed var(--warn-line);
  border-radius: 0.5rem; background: var(--warn-bg); color: var(--warn-ink);
  font-size: 0.78rem; font-weight: 600;
}

/* The two consent boxes on a buy row.
   Not pre-ticked and not one combined tick: these are two separate
   statements, and the fourteen-day cancellation right only ends if BOTH were
   put to the buyer. They are the size of the price beside them rather than
   small print, because small print that removes a statutory right is the
   kind a court reads back to you. */
.consent {
  display: flex;
  align-items: flex-start;
  gap: 0.5rem;
  margin-top: 0.6rem;
  max-width: min(28rem, 100%);
  font-size: 0.8125rem;
  line-height: 1.45;
  color: var(--ink);
  text-align: left;
  cursor: pointer;
}

.consent input {
  flex: 0 0 auto;
  width: 1.1rem;
  height: 1.1rem;
  margin: 0.1rem 0 0;
  accent-color: var(--brand);
}

/* What a buy row says beyond the summary: what is free, which nearby schools the
   pack is the WRONG one for, and whether the format is still provisional. The
   app's catalogue card carried all three and the page that takes the money
   carried none, which is the wrong way round. Tight and quiet: this is the row
   somebody reads just before paying, and it must not look like marketing. */
.buyrow__facts {
  list-style: none;
  margin: 0.6rem 0 0;
  padding: 0;
  display: grid;
  gap: 0.35rem;
  font-size: 0.9rem;
  line-height: 1.45;
  color: var(--ink-muted);
}

.buyrow__facts strong { color: var(--ink); }
