/* The website. Plain CSS and very little script, so it loads quickly on a weak rural signal.
   Colours are the Hedgerow palette, taken from the fields: moss, hedge green, pasture, gorse gold,
   oat and dry stone. Night (moss) carries the photographs and the parts read like a film; the parts
   read closely stay on oat paper. Headlines are set in Fraunces, the words in Bricolage Grotesque.
   Corners: buttons are pills, every card and photograph is 24px, the phone pictures 34px.
   Glass: the facts under the headline and the price cards are frosted panels over a photograph.
   Width: the page fills the screen up to 1520px, and photographs run edge to edge. */

@font-face {
  font-family: 'Bricolage Grotesque';
  src: url('fonts/bricolage-grotesque.woff2') format('woff2');
  font-weight: 200 800;
  font-display: swap;
}
/* Fraunces (SIL Open Font License, fonts/OFL-Fraunces.txt): upright 300 to 400, and italic. Only the
   Latin letters, so the two files together are about 57 KB. */
@font-face { font-family: 'Fraunces'; src: url('fonts/fraunces-roman.woff2') format('woff2'); font-weight: 300 400; font-display: swap; }
@font-face { font-family: 'Fraunces'; src: url('fonts/fraunces-italic.woff2') format('woff2'); font-style: italic; font-weight: 400; font-display: swap; }

/* Hedgerow. Every colour is one of these, or a mix of them with the oat paper. The site is always
   light, so it looks the same on every phone; the app has its own dark pages. Hedge green is the
   green for words and buttons (6.8:1 on oat); pasture is lighter and only ever a fill. */
:root {
  --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);
  --ease-in: cubic-bezier(0.55, 0, 1, 0.45);
  --green: #3d5a32;
  --pasture: #6f8a5b;
  --amber: #e2b33c;
  /* Gorse lightened, for gold words over a photograph. */
  --gorse-light: #f0d283;
  --spine: #1e231b;
  --paper: #f4efe3;
  --edge: #dcd3be;
  --serif: 'Fraunces', Georgia, serif;
  --bg: var(--paper);
  --band: color-mix(in srgb, var(--green) 7%, var(--paper));
  --ink: var(--spine);
  --muted: color-mix(in srgb, var(--spine) 74%, var(--paper));
  --line: var(--edge);
  --accent: var(--green);
  /* Night is moss: the photographs and the parts of the page that are read like a film are set in
     it; the parts that are read closely stay on paper. */
  --night: rgb(34 48 31);
  --night-muted: color-mix(in srgb, var(--paper) 78%, var(--night));
  --night-line: rgb(255 255 255 / 0.14);
  /* Night as numbers, for laying over a photograph under white words. */
  --tint: 34 48 31;
  --green-rgb: 61 90 50;
  --btn: var(--green);
  --btn-ink: #fff;
  --tile-green: color-mix(in srgb, var(--green) 13%, var(--paper));
  --tile-amber: color-mix(in srgb, var(--amber) 32%, var(--paper));
  --frame: var(--spine);
  --shadow: 0 24px 48px -24px rgb(34 48 31 / 0.4);
  --gutter: clamp(16px, 4vw, 64px);
  --gap-y: clamp(72px, 9vw, 144px);
  --round: 24px;
  /* Glass: the page colour let through, over a blur of whatever photograph is behind. */
  --glass: color-mix(in srgb, var(--bg) 74%, transparent);
  --glass-line: color-mix(in srgb, #fff 40%, transparent);
  color-scheme: light;
}

* { box-sizing: border-box; }
html { scroll-behavior: smooth; scroll-padding-top: 88px; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 400 1.125rem/1.55 'Bricolage Grotesque', system-ui, sans-serif;
  -webkit-text-size-adjust: 100%;
  overflow-x: clip;
}

img { display: block; max-width: 100%; height: auto; }
a { color: inherit; }
h1, h2, h3, p, ul, ol, figure { margin: 0; }

/* Headlines are large and light, so the page reads calmly; the words under them carry the weight. */
h1 { font-family: var(--serif); font-size: clamp(2.75rem, 6.4vw, 5.5rem); font-weight: 300; line-height: 1; letter-spacing: -0.03em; }
h2 { font-family: var(--serif); font-size: clamp(1.875rem, 3.6vw, 3.5rem); font-weight: 400; line-height: 1.06; letter-spacing: -0.025em; text-wrap: balance; }
h3 { font-size: 1.25rem; font-weight: 650; line-height: 1.25; }
p { max-width: 62ch; }
h2 + p { margin-top: 20px; }
p + p { margin-top: 12px; }

.wrap { width: min(100% - 2 * var(--gutter), 1520px); margin-inline: auto; }
.note { color: var(--muted); font-size: 1rem; }
/* A small label over a heading, in spaced capitals. */
.kicker { margin-bottom: 18px; color: var(--accent); font-size: 0.8125rem; font-weight: 650; letter-spacing: 0.28em; text-transform: uppercase; }
/* A link that has been followed is a darker green, so it can be told from one that has not. */
p a:visited, li a:visited, .questions a:visited { color: color-mix(in srgb, var(--accent) 55%, var(--ink)); }
.intro { font-size: clamp(1.125rem, 1.5vw, 1.375rem); color: var(--muted); }
.section { padding-block: var(--gap-y); }
.section-head { max-width: 900px; margin-bottom: clamp(32px, 4vw, 56px); }
.text-link { color: var(--accent); font-weight: 650; }

:focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; border-radius: 6px; }

.skip { position: absolute; left: 16px; top: -80px; z-index: 3; padding: 12px 16px; border-radius: 12px; background: var(--btn); color: var(--btn-ink); }
.skip:focus { top: 12px; }

/* Buttons */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 56px; padding: 0 28px;
  border: 1px solid var(--btn); border-radius: 999px;
  background: var(--btn); color: var(--btn-ink);
  font: inherit; font-weight: 650; text-decoration: none; white-space: nowrap; cursor: pointer;
  transition: transform 0.1s ease-out, filter 0.12s ease, box-shadow 0.3s ease;
}
.btn[hidden] { display: none; }
.btn:hover { filter: brightness(1.12); }
.btn:active { transform: scale(0.97); }
.btn-quiet { background: transparent; color: var(--ink); border-color: var(--line); }
.btn-quiet:hover { filter: none; border-color: var(--ink); }
.btn-small { min-height: 48px; padding: 0 20px; font-size: 1rem; }
/* On a photograph: a button in the bookmark's amber, and a quiet one outlined in white. */
/* In the dark parts the buttons give off a soft light, as a lamp would at night. */
.btn-pale { background: var(--amber); border-color: var(--amber); color: var(--spine); box-shadow: 0 14px 44px -10px rgb(226 179 60 / 0.6); }
.btn-ghost { background: rgb(var(--tint) / 0.55); border-color: rgb(255 255 255 / 0.45); color: #fff; box-shadow: 0 14px 44px -12px rgb(255 255 255 / 0.28); }
.btn-ghost:hover { filter: none; background: rgb(var(--tint) / 0.8); border-color: #fff; }
@media (prefers-reduced-motion: reduce) { .btn { transition: none; } }

.actions { display: flex; flex-wrap: wrap; gap: 12px; }

/* Top bar */
/* The bar is lightly see-through, so the page is felt moving under it. It goes solid for anyone
   who has asked their device for less transparency or more contrast. */
/* The bar is night, lightly see-through. */
.nav { position: sticky; top: 0; z-index: 2; background: var(--night); color: var(--paper); border-bottom: 1px solid var(--night-line); }
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .nav { background: color-mix(in srgb, var(--night) 84%, transparent); -webkit-backdrop-filter: blur(18px) saturate(140%); backdrop-filter: blur(18px) saturate(140%); }
}
@media (prefers-reduced-transparency: reduce), (prefers-contrast: more) {
  .nav { background: var(--night); -webkit-backdrop-filter: none; backdrop-filter: none; }
}
.nav :focus-visible { outline-color: var(--amber); }
.nav .btn { background: var(--amber); border-color: var(--amber); color: var(--spine); }
.nav-signin { display: inline-flex; align-items: center; min-height: 48px; padding: 0 6px; font-weight: 650; text-decoration: none; white-space: nowrap; }
.nav-signin:hover { color: var(--amber); }
.nav-row { display: flex; align-items: center; gap: 24px; height: 72px; }
.brand img { width: 28px; height: auto; border-radius: 3px; }
/* The name, with Wee in italic as it is on the book's cover. */
.brand em { font: italic 400 1.15em/1 var(--serif); color: var(--amber); }
.brand { display: inline-flex; align-items: center; gap: 12px; font-weight: 700; font-size: 1.375rem; letter-spacing: -0.01em; text-decoration: none; white-space: nowrap; }
.nav-links { display: flex; gap: clamp(16px, 2vw, 32px); margin-left: auto; }
.nav-links a { display: inline-flex; align-items: center; min-height: 48px; color: var(--night-muted); text-decoration: none; white-space: nowrap; }
.nav-links a:hover { color: var(--paper); }
/* The menu for a narrower screen: one button that drops the same links down under the bar. */
.nav-menu { display: none; position: relative; }
.nav-menu summary { display: inline-flex; align-items: center; min-height: 48px; padding: 0 18px; border: 1px solid rgb(255 255 255 / 0.35); border-radius: 999px; font-weight: 650; cursor: pointer; list-style: none; }
.nav-menu summary::-webkit-details-marker { display: none; }
.nav-menu[open] summary { background: var(--paper); color: var(--night); border-color: var(--paper); }
.nav-menu nav { position: absolute; right: 0; top: calc(100% + 12px); display: grid; min-width: 240px; padding: 8px; border: 1px solid var(--line); border-radius: var(--round); background: var(--bg); color: var(--ink); box-shadow: var(--shadow); }
.nav-menu nav :focus-visible { outline-color: var(--accent); }
.nav-menu nav a { display: flex; align-items: center; min-height: 48px; padding: 0 14px; border-radius: 12px; text-decoration: none; }
.nav-menu nav a:hover { background: var(--band); }
/* Sign in is in the bar itself until the screen is phone-sized. */
@media (min-width: 768px) { .menu-signin { display: none !important; } }

a.store { text-decoration: none; }
a.store:hover { filter: brightness(1.25); }

/* The screenshots, each in a plain phone outline */
.phone {
  width: 100%; max-width: 300px;
  border: 9px solid var(--frame); border-radius: 34px;
  background: var(--frame);
  box-shadow: var(--shadow);
}

/* A photograph that fills its box, with the place named in a corner */
.photo { position: relative; overflow: hidden; background: var(--green); }
.photo > img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.place { position: absolute; right: 12px; bottom: 10px; z-index: 1; padding: 4px 10px; border-radius: 999px; -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px); background: rgb(var(--tint) / 0.8); color: #fff; font-size: 0.8125rem; text-decoration: none; }
.place:hover { background: var(--green); }

/* The opening: Francie at his table, a square picture as wide or as tall as the opening, whichever is
   more, so it always fills it. --u is one pixel of the 1800 square picture. His head is at x 1100 and
   y 700, so the picture is placed to keep it in view: on a phone the sides are cut off, on a wide
   screen the top and foot are. The head layer is 25 renders of his head over the plate, the box
   --hx --hy --hs, so the script can turn it. On a phone the words sit at the foot over a shade; from
   900 px they sit on the left, over the dark wall. */
.hero { position: relative; container-type: size; height: clamp(680px, calc(100svh - 64px), 1040px); overflow: hidden; color: #fff; text-align: left; background: rgb(34 48 31); }
.hero-art { --s: max(100cqw, 52cqh); --u: calc(var(--s) / 1800); --hx: 510; --hy: 226; --hs: 1181; position: absolute; width: var(--s); height: var(--s); left: clamp(calc(100cqw - var(--s)), calc(50cqw - var(--s) * 0.611), 0px); top: calc(var(--s) * -0.06); margin: 0; touch-action: pan-y; }
.plate { display: block; width: 100%; height: 100%; }
.head-turn { position: absolute; left: calc(var(--hx) * var(--u)); top: calc(var(--hy) * var(--u)); width: calc(var(--hs) * var(--u)); aspect-ratio: 1; background: url(img/francie-head.avif) 0 0 / 500% 500%; visibility: hidden;
  mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent), linear-gradient(transparent, #000 7%, #000 93%, transparent); mask-composite: intersect;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent), linear-gradient(transparent, #000 7%, #000 93%, transparent); -webkit-mask-composite: source-in; }
.hero-art.has-head .head-turn { visibility: visible; }
.hero-words { position: absolute; z-index: 1; inset-inline: 0; bottom: 0; padding: 40px 16px clamp(24px, 4vh, 40px); background: linear-gradient(rgb(34 48 31 / 0), rgb(34 48 31 / 0.9) 44px); }
.hero-hi { margin: 0 0 4px; color: var(--gorse-light); font-size: 1.125rem; font-weight: 650; }
.say { margin: 0 0 12px; max-width: 34ch; font-size: clamp(1.125rem, 1.5vw, 1.375rem); line-height: 1.45; color: rgb(255 255 255 / 0.92); }
.untyped { visibility: hidden; }
.caret { display: inline-block; width: 2px; height: 1.1em; margin: 0 -4px 0 2px; vertical-align: -0.15em; background: var(--paper); animation: caret 1s step-end infinite; }
@keyframes caret { 50% { opacity: 0; } }
.hero .actions { gap: 8px; margin-top: 20px; }
.pill { display: inline-flex; align-items: center; min-height: 48px; padding: 0 18px; border: 1px solid var(--paper); border-radius: 999px; background: transparent; color: #fff; font-weight: 600; text-decoration: none; }
.pill:hover, .pill:focus-visible { background: var(--paper); color: var(--spine); }
.pill:active { scale: 0.98; }
.hero :focus-visible { outline-color: var(--amber); }
@media (min-width: 900px) {
  /* no bigger than 1.25 times the opening's height, so a wide screen shows him head and shoulders, not just his face;
     pinned right, its left edge fading into the moss behind the words */
  .hero-art { --s: clamp(100cqh, 100cqw, 125cqh); left: calc(100cqw - var(--s)); top: clamp(calc(100cqh - var(--s)), calc(50cqh - var(--s) * 0.389), 0px); }
  .plate { mask-image: linear-gradient(90deg, transparent, #000 18%); -webkit-mask-image: linear-gradient(90deg, transparent, #000 18%); }
  .hero-words { inset: 0 auto 0 0; display: flex; flex-direction: column; justify-content: center; width: 100%; max-width: 40rem; padding: 0 0 0 clamp(24px, 5vw, 80px); background: linear-gradient(90deg, rgb(34 48 31 / 0.72) 70%, rgb(34 48 31 / 0)); }
}
/* The photographs darken to night at the edges, like a film. The hero is darkest behind its words and
   at its foot, where it runs into the night below it, and a little at the top, under the bar. */
.view::after { content: ""; position: absolute; inset: 0; background: linear-gradient(90deg, rgb(var(--tint) / 0.9) 0%, rgb(var(--tint) / 0.74) 42%, rgb(var(--tint) / 0.12) 78%), linear-gradient(0deg, rgb(var(--tint) / 0.45), transparent 35%); }
.hero h1 { font-size: clamp(2.25rem, 9vw, 2.75rem); font-weight: 300; line-height: 0.98; letter-spacing: -0.02em; text-wrap: balance; text-shadow: 0 2px 24px rgb(30 35 27 / 0.5); }
@media (min-width: 900px) { .hero h1 { font-size: clamp(2.75rem, 3.4vw, 4.25rem); } }
/* very wide screens: words and picture keep to a centred 1600 px frame, with moss either side */
@media (min-width: 1700px) {
  .hero-art { left: calc(50cqw + 800px - var(--s)); }
  .plate { mask-image: linear-gradient(90deg, transparent, #000 18%, #000 88%, transparent); -webkit-mask-image: linear-gradient(90deg, transparent, #000 18%, #000 88%, transparent); }
  .hero-words { padding-left: calc(50cqw - 720px); max-width: calc(50cqw - 800px + 40rem); }
}
.hero h1 em { display: block; font-style: italic; font-weight: 400; color: var(--gorse-light); }

/* Frosted panels. They go solid for anyone who has asked for less transparency or more contrast. */
.price { background: var(--glass); -webkit-backdrop-filter: blur(22px) saturate(160%); backdrop-filter: blur(22px) saturate(160%); border: 1px solid var(--glass-line); border-radius: var(--round); box-shadow: 0 24px 48px -28px rgb(0 0 0 / 0.5); }
/* The facts are dark glass, lit only at the edge. */
.facts > div { background: rgb(255 255 255 / 0.05); -webkit-backdrop-filter: blur(22px); backdrop-filter: blur(22px); border: 1px solid var(--night-line); border-radius: var(--round); }
@media (prefers-reduced-transparency: reduce), (prefers-contrast: more) {
  .price { background: var(--bg); -webkit-backdrop-filter: none; backdrop-filter: none; border-color: var(--line); }
  .facts > div { background: var(--night); -webkit-backdrop-filter: none; backdrop-filter: none; border-color: var(--night-muted); }
}

/* The app under the opening, on night: the phone rises out of the foot of the photograph, with three
   short facts under it. --peek is how far the phone reaches up into the opening; the opening keeps
   more room than that under its button. */
.facts { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px; margin-top: clamp(40px, 5vw, 72px); }
.facts > div { padding: clamp(20px, 2vw, 28px); }
.facts p { margin-top: 6px; font-size: 1rem; color: var(--night-muted); }
/* The facts are the first headings under the headline, so they are h2s set at the size of an h3. */
.facts h2 { font-size: 1.25rem; line-height: 1.25; letter-spacing: 0; }

.try { display: inline-block; margin-top: 16px; padding: 10px 0; color: var(--accent); font-weight: 650; }


/* The demo: the app itself, running in a phone outline */
.demo { background: var(--band); }
.demo-row { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: clamp(32px, 5vw, 96px); }
.demo .actions { margin-top: 28px; }
.handset { width: 393px; max-width: 100%; height: min(780px, 84dvh); padding: 10px; border-radius: 44px; background: var(--spine); box-shadow: var(--shadow); }
.handset img, .handset iframe { display: block; width: 100%; height: 100%; border: 0; border-radius: 34px; object-fit: cover; object-position: top; background: var(--paper); }

/* Where the phone apps will be. These are not links yet. They are the one square-cornered button,
   because that is the shape the shops' own badges have. */
.stores { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 28px; padding: 0; list-style: none; }
.store { display: inline-flex; flex-direction: column; justify-content: center; min-height: 56px; padding: 6px 22px; border: 1px solid color-mix(in srgb, var(--paper) 35%, transparent); border-radius: 14px; background: var(--spine); color: var(--paper); font-size: 1.125rem; font-weight: 650; line-height: 1.15; cursor: default; }
.store small { font-size: 0.75rem; font-weight: 400; }


/* A photograph across the whole page with a line of words on it */
.view { min-height: clamp(320px, 44vw, 620px); display: flex; align-items: flex-end; color: #fff; }
.view-text { position: relative; z-index: 1; padding-block: clamp(32px, 5vw, 72px); }
.view-text p { margin-top: 16px; font-size: clamp(1.125rem, 1.5vw, 1.375rem); color: rgb(255 255 255 / 0.92); max-width: 46ch; }
.view-text h2 { max-width: 18ch; }

/* The setup service */
.setup { background: var(--band); }
.setup-row { display: grid; grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr); gap: clamp(32px, 5vw, 96px); align-items: stretch; }
.setup-photo { align-self: center; aspect-ratio: 4 / 3; border-radius: var(--round); }
.count { list-style: none; counter-reset: step; display: grid; gap: 12px; margin-top: 32px; padding: 0; }
.count li { counter-increment: step; display: grid; grid-template-columns: 48px 1fr; gap: 16px; align-items: start; padding: 20px; border: 1px solid var(--line); border-radius: var(--round); background: var(--bg); }
.count li::before { content: counter(step); display: grid; place-items: center; width: 48px; height: 48px; border-radius: 50%; background: var(--btn); color: var(--btn-ink); font-weight: 700; font-size: 1.25rem; }
.count b { display: block; }
.setup .actions { margin-top: 28px; align-items: center; }
.setup .note { margin-top: 20px; }

/* Prices: glass cards over a pasture */
.prices-band { color: #fff; }
/* Dark enough for the white words over the brightest part of the photograph (4.5:1). */
.prices-band::after { content: ""; position: absolute; inset: 0; background: rgb(var(--green-rgb) / 0.76); }
.prices-band > .wrap { position: relative; z-index: 1; }
.prices-band .intro, .prices-band .wont { color: rgb(255 255 255 / 0.92); }
.prices-band > .place { top: 12px; bottom: auto; }
.prices { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 20px; }
.price { display: flex; flex-direction: column; padding: clamp(24px, 2.4vw, 36px); color: var(--ink); }
.price-main { background: color-mix(in srgb, var(--tile-green) 82%, transparent); }
.price-wide { grid-column: 1 / -1; display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr) auto; align-items: center; gap: 16px 40px; background: color-mix(in srgb, var(--tile-amber) 84%, transparent); }
/* On glass the grey is a little darker than elsewhere, so it keeps 4.5:1 over a light photograph. */
.price .who { color: color-mix(in srgb, var(--spine) 84%, var(--paper)); font-size: 1rem; }
.amount { margin: 16px 0 4px; font-size: clamp(2.25rem, 3.4vw, 3.25rem); font-weight: 700; line-height: 1; letter-spacing: -0.03em; }
.amount small { font-size: 1.0625rem; font-weight: 400; letter-spacing: 0; color: color-mix(in srgb, var(--spine) 84%, var(--paper)); }
.price ul { list-style: none; display: grid; gap: 10px; margin-top: 20px; padding: 20px 0 0; border-top: 1px solid color-mix(in srgb, var(--ink) 14%, transparent); font-size: 1rem; }
.price li { padding-left: 26px; background: no-repeat 0 0.35em / 16px url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M2 8.5l4 4 8-9' fill='none' stroke='%233d5a32' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); }
.price-wide .amount { margin: 8px 0 0; }
.wont { margin-top: 28px; color: var(--muted); max-width: 80ch; }

/* The Wee Book beside the other tools */
.compare { width: 100%; border-collapse: collapse; }
.compare th, .compare td { padding: 20px 24px 20px 0; border-bottom: 1px solid var(--line); text-align: left; vertical-align: top; }
.compare th { padding-top: 0; padding-bottom: 12px; border-bottom: 2px solid var(--ink); font-size: 1rem; font-weight: 650; }
.compare td:first-child { width: 24%; font-weight: 650; }
.compare td:nth-child(2) { width: 32%; color: var(--muted); }
.compare td:last-child { padding-right: 0; }
.compare-card { padding: clamp(20px, 2.6vw, 40px) clamp(16px, 2.6vw, 40px) clamp(4px, 1vw, 16px); border: 1px solid var(--line); border-radius: var(--round); background: var(--bg); }
.compare-card tr:last-child td { border-bottom: 0; }
.compare-note { margin-top: 20px; max-width: 90ch; }

/* The newest post on the development blog, as one card. */
.latest-card { display: grid; gap: 10px; max-width: 760px; padding: clamp(24px, 3vw, 40px); border: 1px solid var(--line); border-radius: var(--round); text-decoration: none; }
.latest-card:hover { border-color: var(--ink); }
.latest-card > * { margin: 0; }
.latest-card h2 { font-size: clamp(1.5rem, 2.4vw, 2rem); }
.latest-card time, .post time { color: var(--muted); font-size: 0.9375rem; }
.latest-card p { color: var(--muted); font-size: 1rem; }
.blog-band { background: var(--band); }

/* What is being added next, in two columns, at the top of the blog */
.coming { padding-bottom: 48px; margin-bottom: 48px; border-bottom: 1px solid var(--line); }
.coming h2 { font-size: clamp(1.625rem, 2.6vw, 2.25rem); }
.road-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 32px 40px; margin-top: 24px; }
.road-cols h3 { padding-bottom: 12px; border-bottom: 2px solid var(--ink); }
.road-cols ul { list-style: none; padding: 0; }
.road-cols li { margin: 0; padding: 12px 0; border-bottom: 1px solid var(--line); }

.questions a { color: var(--accent); font-weight: 650; }

/* Questions, in two columns on a wide screen */
.q-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 0 clamp(32px, 5vw, 96px); align-items: start; }
.questions details { border-bottom: 1px solid var(--line); }
.questions summary { display: flex; align-items: center; justify-content: space-between; gap: 16px; min-height: 60px; padding: 12px 0; font-size: 1.1875rem; font-weight: 650; cursor: pointer; list-style: none; }
.questions summary::-webkit-details-marker { display: none; }
/* The sign is drawn only: a screen reader already says whether the answer is open. */
.questions summary::after { content: "+"; content: "+" / ""; flex: none; font-size: 1.5rem; font-weight: 400; color: var(--accent); }
.questions details[open] summary::after { content: "−"; content: "−" / ""; }
.questions details p { padding-bottom: 20px; }

/* Last word: the invitation, with the same kitchen cleared */
.close { color: #fff; }
.close-row { position: relative; z-index: 1; display: grid; grid-template-columns: 1fr; align-items: center; gap: 48px; padding-block: clamp(56px, 7vw, 112px); }
/* The book is given room for its cover to swing open to the left. */
.close-row .actions { margin-top: 28px; }
.close-row p { color: rgb(255 255 255 / 0.92); }
/* A small ring of light over the last invitation, echoing the one round the book. */
.close-row > div::before { content: ""; display: block; width: 56px; height: 56px; margin-bottom: 32px; border: 1.5px solid rgb(255 255 255 / 0.75); border-radius: 50%; box-shadow: 0 0 28px rgb(226 179 60 / 0.35), inset 0 0 16px rgb(226 179 60 / 0.2); }
.close-mail { margin-top: 28px; }
.close-mail a { font-weight: 650; }

/* Foot of the page: who runs it, the product, the book, the rules */
/* The foot is the ink of the book's spine, in the light and the dark look alike. */
.foot { background: var(--night); color: var(--night-muted); font-size: 1rem; }
.foot :focus-visible { outline-color: var(--amber); }
.foot a { color: inherit; }
.brand-foot { font-size: 1.5rem; color: var(--paper); }
.brand-foot img { width: 34px; }
.foot-cols { display: grid; grid-template-columns: 1.6fr repeat(4, 1fr); gap: 40px; padding-top: 56px; padding-bottom: 32px; }
.foot p { margin-top: 12px; }
.foot h3 { margin-bottom: 4px; font-size: 1rem; color: var(--paper); }
.foot nav a { display: block; padding: 9px 0; }
.foot-end { padding-top: 20px; padding-bottom: 32px; border-top: 1px solid rgb(255 255 255 / 0.16); font-size: 0.9375rem; }
/* Something only Chris can fill in. It is bright so that it cannot be published by mistake. */
.gap { padding: 0 4px; border-radius: 4px; background: var(--amber); color: var(--spine); }

/* Words for a screen reader only. */
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }

/* The dates board. Each letter sits on a flap, like the board at a mart or a station, and the
   flaps turn over once when the board comes into view. Without script it is a plain dark list. */
.board { list-style: none; display: grid; gap: 8px; max-width: 520px; margin: 28px 0 20px; padding: 16px; border-radius: 14px; background: var(--spine); color: var(--paper); font-weight: 650; }
.board li { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 8px 12px; }
.flap { display: inline-flex; gap: 2px; perspective: 320px; }
.cell { position: relative; display: inline-grid; place-items: center; width: 1.05em; height: 1.55em; border-radius: 3px; background: linear-gradient(var(--green) 0 48%, var(--spine) 48% 53%, var(--green) 53%); color: var(--paper); font: 650 0.9375rem/1 ui-monospace, Consolas, "Courier New", monospace; }
.cell-gap { background: none; }
.flap-when { margin-left: auto; }
.flap-when .cell { background: linear-gradient(var(--amber) 0 48%, var(--spine) 48% 53%, var(--amber) 53%); color: var(--spine); }
.flap-late .cell { background: linear-gradient(#bd342c 0 48%, #7d1812 48% 53%, #ab241c 53%); color: #fff; }

/* The terms, the privacy notice and the other pages of words */
.doc { max-width: 780px; padding-top: 48px; padding-bottom: 88px; }
.doc h1 { font-size: clamp(2rem, 5vw, 3rem); }
.doc .dated { margin-top: 12px; color: var(--muted); }
.doc h2 { margin-top: 44px; font-size: 1.375rem; letter-spacing: -0.01em; }
.doc ul { margin-top: 12px; padding-left: 22px; }
.doc li { margin-top: 10px; }
.doc a { color: var(--accent); font-weight: 650; }
.doc p { margin-top: 16px; }

/* The development blog: a photograph across the top, then the posts, newest first */
.page-top { min-height: clamp(240px, 30vw, 420px); }
.page-top h1 { font-size: clamp(2.5rem, 5.4vw, 4.5rem); }
.blog { display: grid; grid-template-columns: minmax(0, 260px) minmax(0, 820px); gap: clamp(32px, 5vw, 96px); padding-block: var(--gap-y); }
.blog-side { position: sticky; top: 104px; align-self: start; color: var(--muted); font-size: 1rem; }
.blog-side a { display: block; padding: 8px 0; color: var(--ink); text-decoration: none; }
.blog-side a:hover { color: var(--accent); }
.blog-side p { margin-bottom: 16px; }
.post { padding-bottom: 48px; margin-bottom: 48px; border-bottom: 1px solid var(--line); }
.post:last-child { border-bottom: 0; margin-bottom: 0; }
.post h2 { margin-top: 8px; font-size: clamp(1.625rem, 2.6vw, 2.25rem); }
.post p { margin-top: 16px; }
.post ul { margin-top: 12px; padding-left: 22px; max-width: 62ch; }
.post li { margin-top: 8px; }
.post a { color: var(--accent); font-weight: 650; }

/* Tablets and small laptops */
@media (max-width: 1100px) {
  .nav-links { display: none; }
  /* A short row of links, as on the pages other than this one, stays in the bar. */
  .nav-links:not(:has(> :nth-child(3))) { display: flex; }
  .nav-menu { display: block; margin-left: auto; }
  .nav-menu + .nav-signin { margin-left: 0; }
  .nav-signin { margin-left: auto; }
  .prices { grid-template-columns: 1fr 1fr; }
  .price-wide { grid-template-columns: 1fr; }
  .foot-cols { grid-template-columns: 1fr 1fr 1fr; }
  .foot-cols > div:first-child { grid-column: 1 / -1; }
  .setup-row { grid-template-columns: 1fr; }
  .setup-photo { min-height: 0; aspect-ratio: 16 / 9; align-self: stretch; }
}

/* Phones: one column throughout */
@media (max-width: 767px) {
  body { font-size: 1.0625rem; }
  .nav-row { height: 64px; gap: 12px; }
  /* On a phone the words span the whole width, so the whole photograph is darkened evenly. */
  /* On a phone the bar keeps the name and Sign in. Start free is the first button on the page. */
  .nav .btn { display: none; }
  /* On the home page Sign in moves into the menu, so the name, the menu and nothing else share the bar. */
  .nav-menu + .nav-signin { display: none; }
  /* On the other pages the name already goes home and Blog is in the foot, so the bar keeps only
     the name and Sign in, which is all that fits beside each other. */
  .nav-links:not(:has(> :nth-child(3))) { display: none; }
  .nav-signin { padding: 0 16px; border: 1px solid var(--line); border-radius: 999px; }
  .demo-row, .facts, .q-cols, .road-cols, .prices, .blog, .close-row { grid-template-columns: 1fr; }
  .close-row .actions .btn { flex: 1 1 auto; white-space: normal; text-align: center; padding: 12px 20px; }
  /* The page is already on a phone, so no second phone is drawn and one button opens the app. */
  .handset, #demo-start { display: none; }
  .stores { gap: 8px; }
  .stores li { flex: 1 1 0; }
  .store { display: flex; padding-inline: 14px; }
  .facts { gap: 12px; }
  .count li { grid-template-columns: 40px 1fr; padding: 16px; }
  .count li::before { width: 40px; height: 40px; }
  .view::after { background: linear-gradient(0deg, rgb(var(--tint) / 0.85), rgb(var(--tint) / 0.35)); }
  .close-row { gap: 48px; }
  .foot-cols { grid-template-columns: 1fr 1fr; gap: 28px; padding-top: 32px; }
  .board { padding: 12px; }
  .cell { font-size: 0.8125rem; }
  .blog-side { position: static; }
  /* The table of other tools becomes a card for each row, with the heading written into it. */
  .compare thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
  .compare, .compare tbody, .compare tr, .compare td { display: block; width: auto; }
  .compare tr { padding: 20px 0; border-bottom: 1px solid var(--line); }
  .compare td, .compare td:first-child, .compare td:nth-child(2) { width: auto; padding: 0; border: 0; }
  .compare td + td { margin-top: 10px; }
  .compare td:first-child { font-size: 1.1875rem; }
  .compare td[data-label]::before { content: attr(data-label); display: block; color: var(--muted); font-size: 0.875rem; font-weight: 400; }
}

/* Motion, after the way weareheroes.one moves. The script on the front page splits the headline into
   words (.w), marks the parts that come up as they are reached (.rv, then .in) and gives the moving
   photographs --p, from 0 to 1 as each passes. Nothing here runs for anyone who asks for less motion,
   and without script the page is drawn still and whole. */
@property --sweep { syntax: '<angle>'; inherits: false; initial-value: 360deg; }
.hero, .close, .view-pin, .view-pin > .view { background: var(--night); }
.btn-pale:hover { box-shadow: 0 16px 60px -6px rgb(226 179 60 / 0.85); }
.btn-ghost:hover { box-shadow: 0 16px 60px -8px rgb(255 255 255 / 0.4); }

@media (prefers-reduced-motion: no-preference) {
  /* The opening. The buttons come up under Francie's line, then the top bar and the facts come in;
     the closing ring is drawn when it is reached. */
  .close-row > div::before { -webkit-mask: conic-gradient(#000 var(--sweep), transparent 0); mask: conic-gradient(#000 var(--sweep), transparent 0); }
  html.motion #top .actions { animation: fade-up 0.4s ease-out 0.4s both; }
  .opening .nav-row { animation: drop-in 0.9s cubic-bezier(0.2, 0.7, 0.2, 1) 1.5s both; }
  .opening .facts { animation: fade-up 1s ease-out 2.4s both; }

  /* Sections come up as they are reached, the parts of each a little after each other. */
  .rv { opacity: 0; translate: 0 48px; transition: opacity 1.1s ease-out, translate 1.2s cubic-bezier(0.2, 0.7, 0.2, 1); transition-delay: calc(var(--d, 0) * 90ms); }
  .rv.in { opacity: 1; translate: none; }
  .close-row.rv > div::before { animation: sweep 1.8s cubic-bezier(0.6, 0, 0.2, 1) 0.4s both paused; }
  .close-row.in > div::before { animation-play-state: running; }

  /* Photographs that drift with the scroll. */
  .prices-band[data-scrub] > img { scale: 1.16; translate: 0 calc((var(--p, 0.5) - 0.5) * -14%); }

  /* Made for the yard. The section holds still for a screen's worth of scrolling while its photograph
     opens from a circle edged with a ring, then the words come up. */
  .opening .view-pin { height: 220vh; }
  .opening .view-pin > .view { position: sticky; top: 0; height: 100dvh; min-height: 0; }
  .opening .view-pin > .view > img { clip-path: circle(calc(14% + var(--p, 1) * 100%) at 50% 50%); scale: calc(1.25 - var(--p, 1) * 0.25); }
  .opening .view-pin > .view::before { content: ""; position: absolute; z-index: 1; left: 50%; top: 50%; width: calc(hypot(100vw, 100dvh) * 1.4142 * (0.14 + var(--p, 1))); aspect-ratio: 1; translate: -50% -50%; border: 1px solid rgb(255 255 255 / 0.6); border-radius: 50%; box-shadow: 0 0 40px rgb(226 179 60 / 0.2); opacity: calc(1 - var(--p, 1) * 2.5); pointer-events: none; }
  .opening .view-pin .view-text { --show: clamp(0, (var(--p, 1) - 0.4) * 4, 1); opacity: var(--show); translate: 0 calc((1 - var(--show)) * 40px); }

  /* The menu on a phone: the page behind it blurs and the places drop in one after another. */
  .nav-menu[open] nav { animation: fade-up 0.3s ease-out both; }
  .nav-menu[open] nav a { animation: drop 0.5s cubic-bezier(0.2, 0.7, 0.2, 1) both; animation-delay: calc(var(--i, 0) * 45ms); }
  main, .foot { transition: filter 0.4s ease; }
  body:has(.nav-menu[open]) :is(main, .foot) { filter: blur(4px); }

}
@keyframes sweep { from { --sweep: 0deg; } to { --sweep: 360deg; } }
@keyframes fade-up { from { opacity: 0; translate: 0 24px; } }
@keyframes drop-in { from { opacity: 0; translate: 0 -100%; } }
@keyframes drop { from { opacity: 0; translate: 0 -30%; } }

/* The page after the opening: three steps, the dates, every feature, and why to trust it. */

/* The farmer tells the story. On a phone he stands beside his bubble; from 720 px he is taller, and
   stands left and right in turn. Cut-outs are drawn 260 wide by 490 tall (the drawer pose 370). */
.beat { display: flex; align-items: flex-start; gap: 12px; margin-block: 8px 28px; }
.beat.end { flex-direction: row-reverse; }
.beat .farmer { flex: none; width: 140px; height: auto; }
.beat .farmer-drawer { width: 199px; }
.farmer-point-back { transform: scaleX(-1); }
.bubble { position: relative; max-width: 22ch; margin-top: 16px; padding: 12px 16px; background: #fff; color: var(--spine); border: 1.5px solid var(--edge); border-radius: 16px; font-family: var(--serif); font-size: 1.1875rem; line-height: 1.3; }
.bubble::before { content: ""; position: absolute; top: 22px; left: -9px; width: 16px; height: 16px; background: #fff; border-left: 1.5px solid var(--edge); border-bottom: 1.5px solid var(--edge); transform: rotate(45deg); }
.beat.end .bubble::before { left: auto; right: -9px; transform: rotate(-135deg); }
@media (min-width: 720px) {
  .beat .farmer { width: 138px; height: 260px; }
  .beat .farmer-drawer { width: 196px; }
}

/* In the opening his bubble is beside his head, pointing at his face. */
.close-art .kitchen { display: block; width: 100%; height: auto; border-radius: var(--round); }
.close-art { width: min(100%, 560px); margin: 0; }
@media (min-width: 720px) { .close-row { grid-template-columns: 1fr 1fr; } }

.how { background: var(--band); }
.steps { list-style: none; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: clamp(32px, 3vw, 48px); padding: 0; }
.steps .phone { width: min(240px, 70%); margin-bottom: 24px; }
.steps h3 { font-size: clamp(1.375rem, 2vw, 1.75rem); line-height: 1.15; }
.steps p { margin-top: 8px; color: var(--muted); }
.how .note { margin-top: 40px; }

.dates-row { display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(0, 0.8fr); gap: clamp(32px, 5vw, 96px); align-items: center; }
.dates .board { margin-bottom: 28px; }
.dates-phone { width: min(300px, 100%); justify-self: center; }
.points { list-style: none; display: grid; gap: 16px; max-width: 62ch; padding: 0; }
.points b { display: block; }
.dates .try { margin-top: 20px; }

.groups { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 20px; }
.group { padding: clamp(24px, 2.4vw, 32px); border: 1px solid var(--line); border-radius: var(--round); background: var(--band); }
.group h3 { margin-bottom: 16px; font-family: var(--serif); font-size: 1.5rem; font-weight: 400; }
.group ul { list-style: none; display: grid; gap: 12px; padding: 0; }
.group li { position: relative; padding-left: 20px; }
.group li::before { content: ""; position: absolute; left: 0; top: 0.6em; width: 8px; height: 8px; border-radius: 50%; background: var(--green); }

.trust { background: var(--night); color: var(--paper); }
.trust h2 { margin-bottom: clamp(28px, 4vw, 48px); }
.trust .facts { grid-template-columns: repeat(4, minmax(0, 1fr)); margin-top: 0; }
.facts h3 { font-size: 1.25rem; line-height: 1.25; }

@media (max-width: 1100px) {
  .groups, .trust .facts { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 767px) {
  .steps, .dates-row, .groups, .trust .facts { grid-template-columns: 1fr; }
  .steps .phone, .dates-phone { width: min(220px, 64%); justify-self: start; }
  .dates-phone { justify-self: center; }
}
.foot-company { margin-top: 12px; max-width: none; }

/* The farmer's actions. Each still pose is the last frame, so with less motion or no script he simply
   stands in it. With motion, each action waits on its first frame until its part is on screen. */
html.motion [data-beat]:not(.is-on) * { animation-play-state: paused !important; }
html.motion .farmer-bill .arm { transform-box: view-box; transform-origin: 488px 466px; animation: arm-up 700ms cubic-bezier(.2,.8,.2,1) both; }
html.motion .farmer-bill .flash { transform-box: fill-box; transform-origin: center; animation: flash 500ms 650ms ease-out both; }
html.motion .farmer-tick .tap { transform-box: view-box; transform-origin: 488px 466px; animation: tap 600ms cubic-bezier(.2,.8,.2,1) both; }
html.motion .farmer-tick .done { animation: show 200ms 520ms both; }
html.motion .farmer-tick .tick { transform-box: fill-box; transform-origin: center; animation: pop 450ms 560ms cubic-bezier(.3,1.5,.5,1) both; }
html.motion .farmer-buzz .handset { animation: shake 90ms 4 linear both; }
html.motion .farmer-buzz .buzz { animation: show 120ms 3 both; }
html.motion .farmer-buzz .head { transform-box: view-box; transform-origin: 420px 440px; animation: nod 700ms 420ms ease-in-out both; }
html.motion .farmer-drawer .drawer { animation: offer 750ms cubic-bezier(.2,.8,.2,1) both; }
html.motion :is(.farmer-point, .farmer-point-back) .arm { transform-box: view-box; transform-origin: 488px 466px; animation: arm-up 650ms cubic-bezier(.2,.8,.2,1) both; }
html.motion .farmer-thumbs .arm { transform-box: view-box; transform-origin: 488px 466px; animation: arm-up 600ms cubic-bezier(.3,1.4,.5,1) both; }
html.motion .farmer-hand-on-book .pat { animation: pat 300ms 200ms ease-in-out 2 alternate both; }
html.motion .farmer-register .arm { transform-box: view-box; transform-origin: 488px 466px; animation: arm-up 700ms cubic-bezier(.2,.8,.2,1) both; }
html.motion .farmer-register .book { animation: offer 600ms 500ms cubic-bezier(.2,.8,.2,1) both; }
html.motion .farmer-scratch .scratch { transform-box: view-box; transform-origin: 530px 444px; animation: scr 180ms 6 alternate ease-in-out both; }
@keyframes arm-up { from { transform: rotate(38deg); } }
@keyframes flash { 0% { opacity: 0; transform: scale(.3); } 40% { opacity: 1; transform: scale(1.15); } 100% { opacity: 1; transform: scale(1); } }
@keyframes tap { 0% { transform: rotate(14deg); } 70% { transform: rotate(-3deg); } 100% { transform: none; } }
@keyframes show { from { opacity: 0; } }
@keyframes pop { from { opacity: 0; transform: scale(0); } }
@keyframes shake { 0%, 100% { transform: none; } 25% { transform: translateX(-3px); } 75% { transform: translateX(3px); } }
@keyframes nod { 0%, 100% { transform: none; } 35% { transform: rotate(5deg); } 70% { transform: rotate(-1deg); } }
@keyframes offer { from { transform: translateY(26px); } }
@keyframes pat { to { transform: translateY(5px); } }
@keyframes scr { to { transform: rotate(5deg); } }

/* The two kitchens. Each arm has two drawings. The first swings fast into the swap at 20%, the second
   swings out of it, and they swap back at 80%. Speeding into the swap and easing out of it hides the change. */
@keyframes away { 0%, 19.99%, 80%, 100% { opacity: 1; } 20%, 79.99% { opacity: 0; } }
@keyframes arrive { 0%, 19.99%, 80%, 100% { opacity: 0; } 20%, 79.99% { opacity: 1; } }
/* night: his hand drops from his head onto the pile, he sits up and looks at the clock, sighs, and his head goes back into his hand */
/* evening: the arm bends at shoulder, elbow and wrist on the way up, then the mug reaches his mouth for a sip */
html.motion .kitchen-evening .upper { transform-box: view-box; transform-origin: 352px 466px; animation: up-upper 2200ms both, away 2200ms linear both; animation-delay: 900ms; }
html.motion .kitchen-evening .fore { transform-box: view-box; transform-origin: 344px 552px; animation: up-fore 2200ms both; animation-delay: 900ms; }
html.motion .kitchen-evening .cup { transform-box: view-box; transform-origin: 298px 550px; animation: up-cup 2200ms both; animation-delay: 900ms; }
html.motion .kitchen-evening .sip { animation: arrive 2200ms linear both; animation-delay: 900ms; }
html.motion .kitchen-evening .sipfore { transform-box: view-box; transform-origin: 336px 522px; animation: sip 2200ms both; animation-delay: 900ms; }
html.motion .kitchen-evening .head { transform-box: view-box; transform-origin: 420px 440px; animation: lean 2200ms var(--ease-in-out) both; animation-delay: 900ms; }
@keyframes up-upper { 0% { transform: none; animation-timing-function: var(--ease-in); } 20%, 80% { transform: rotate(30deg); animation-timing-function: var(--ease-out); } 100% { transform: none; } }
@keyframes up-fore { 0% { transform: none; animation-timing-function: var(--ease-in); } 20%, 80% { transform: rotate(60deg); animation-timing-function: var(--ease-out); } 100% { transform: none; } }
@keyframes up-cup { 0% { transform: none; animation-timing-function: var(--ease-in); } 20%, 80% { transform: rotate(-90deg); animation-timing-function: var(--ease-out); } 100% { transform: none; } }
@keyframes sip { 0%, 20% { transform: rotate(-25deg); animation-timing-function: var(--ease-out); } 32%, 68% { transform: none; animation-timing-function: var(--ease-in); } 80%, 100% { transform: rotate(-25deg); } }
@keyframes lean { 0%, 20%, 80%, 100% { transform: none; } 32%, 68% { transform: rotate(-4deg); } }

/* At rest, only while his part is on screen: a slow breath, a blink, now and then the collie's tail. */
html.motion .is-here .breathe { transform-box: view-box; transform-origin: 420px 774px; animation: breathe 4s ease-in-out infinite; }
html.motion .is-here .eyes { transform-box: fill-box; transform-origin: center; animation: blink 5s 1.2s infinite; }
html.motion .is-here .tail { transform-box: fill-box; transform-origin: 0% 50%; animation: wag 6s 800ms infinite; }
@keyframes breathe { 50% { transform: scaleY(1.003); } }
@keyframes blink { 0%, 96%, 100% { transform: none; } 98% { transform: scaleY(.1); } }
@keyframes wag { 0%, 12%, 100% { transform: none; } 3%, 9% { transform: rotate(-14deg); } 6% { transform: rotate(4deg); } }
@media (prefers-reduced-motion: reduce) { .farmer *, .kitchen * { animation: none !important; } }
