/* Whistle. One warm ground from the top of the page to the footer, and every
   piece of structure on it is a rounded shape: a filled one when the business
   is promising something, a hollow one when it is showing you something.
   The memorable thing is a shape with something crossing its edge — the hero
   pill with the button hanging half off its bottom, the price sitting astride
   the hairline of its own row, the numerals astride the rail of the four
   steps, and the closing pill doing what the hero did, smaller. One rule
   governs every one of them: whatever sits on a shape's bottom edge starts
   where that shape's curve ends, so the page has one vertical line and the
   overhang reads as placed rather than slipped.

   There are no alternating tint bands. That stripe is the one thing nearly
   every design in this library does, and here the shapes carry the rhythm
   instead: full, hollow, ruled, railed, full. See README.md, ## Notes. */

@font-face {
  font-family: "Quicksand Subset";
  src: url("quicksand-subset.woff2") format("woff2-variations"),
       url("quicksand-subset.woff2") format("woff2");
  font-weight: 500 700;
  font-style: normal;
  font-display: swap;
}

:root {
  /* Five colours, declared on the contract's names so that step 4 of
     templates/README.md — "Set --accent" — works here as it does everywhere
     else. The design's own names below are aliases, so changing --accent or
     --bg changes the page. See README.md, ## Tokens you may change. */
  --bg: #fdfbf7;
  --tint: #f2e6d6;
  --rule: #c9ae8d;
  --accent: #a85512;
  --ink: #191108;
  --accent-ink: var(--bg);

  --paper: var(--bg);
  --oat: var(--tint);
  --clay: var(--rule);
  --rust: var(--accent);

  /* Two neutrals, for secondary type. */
  --muted: #5b5147;
  --pale: #d6c5ae;

  /* Type. Eight sizes; the top three fluid. */
  --t-promise: clamp(2.25rem, 6.4vw, 5.75rem);
  --t-close: clamp(1.75rem, 3.4vw, 3rem);
  --t-turn: clamp(1.5rem, 2.6vw, 2.25rem);
  --t-head: clamp(1.4375rem, 1.1rem + 0.85vw, 1.75rem);
  --t-name: clamp(1.25rem, 1.05rem + 0.5vw, 1.5rem);
  --t-fig: 1.1875rem;
  --t-lead: clamp(1.1875rem, 1.05rem + 0.4vw, 1.4375rem);
  --t-body: clamp(1.125rem, 1rem + 0.4vw, 1.25rem);
  --t-small: clamp(1rem, 0.95rem + 0.2vw, 1.0625rem);

  /* Space. */
  --s1: 0.25rem;
  --s2: 0.5rem;
  --s3: 1rem;
  --s4: 1.5rem;
  --s5: 2.5rem;
  --s6: 4rem;
  --edge: clamp(1.125rem, 4.5vw, 3rem);
  --gap: clamp(1.75rem, 6vw, 5.5rem);
  --gap-in: clamp(1rem, 4vw, 2.5rem);

  /* The shape. --r-shape is the curve of every large shape on the page, and
     --in is the inset where that curve ends. They are the same number on
     purpose: that is the whole alignment rule. */
  --r-shape: clamp(1.625rem, 8vw, 3.5rem);
  --in: var(--r-shape);
  --r-stadium: 999px;
  --hair: 2px;

  /* Two measured numbers, not two guesses. --ink-drop is how far the promise
     has to fall for the ink of its capitals and descenders to be centred in
     the pill rather than its line boxes; --bearing is the left side bearing
     of Quicksand's capital O, pulled back so the letter's ink lands on the
     page line instead of its glyph box. Both are in em, so they hold at every
     size the promise takes. Measured, see README.md, ## Type. */
  --ink-drop: 0.027em;
  --bearing: -0.038em;
  --bearing-b: -0.068em;

  --display: "Quicksand Subset", "Century Gothic", "URW Gothic", Futura, "Trebuchet MS", sans-serif;
  --body: Calibri, -apple-system, "SF Pro Text", system-ui, "Helvetica Neue", Arial, sans-serif;
}

/* ---------- base ---------- */

*, *::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: var(--t-body);
  line-height: 1.5;
  overflow-wrap: break-word;
}

img { max-width: 100%; height: auto; display: block; }

h1, h2, h3 {
  margin: 0;
  font-family: var(--display);
  font-weight: 700;
  text-wrap: balance;
}

p { margin: 0 0 var(--s3); }
p:last-child { margin-bottom: 0; }

a { color: inherit; }

:focus-visible { outline: 3px solid var(--ink); outline-offset: 3px; }

.hold {
  max-width: 72rem;
  margin: 0 auto;
  padding-inline: var(--edge);
}

.open { padding-block: var(--gap); }
#hero { padding-block: var(--s3) var(--gap); }

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 10;
  background: var(--ink);
  color: var(--paper);
  padding: var(--s2) var(--s3);
  text-decoration: none;
}
.skip:focus { left: 0; }

/* ---------- top bar ---------- */
/* A wordmark and a number. Both wrap rather than squeeze, so 320px needs no
   menu button and there is no JavaScript on the page at all. */

.topbar {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s2) var(--s3);
  padding: var(--s3) var(--edge) var(--s2);
  max-width: 72rem;
  margin: 0 auto;
}

.wordmark {
  margin: 0;
  font-family: var(--display);
  font-size: var(--t-small);
  font-weight: 700;
  letter-spacing: 0.01em;
  line-height: 1.3;
  min-width: 0;
}

.ring {
  color: var(--rust);
  font-weight: 700;
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: 0.22em;
  display: inline-block;
  padding-block: 2px;
  transition: text-decoration-thickness 140ms linear;
}
.ring:hover { text-decoration-thickness: 4px; }

/* ---------- the filled shape ---------- */
/* No overflow clipping anywhere near this: the button is meant to hang off
   the bottom edge, and clipping is what a card does. This is not a card. */

.pill {
  position: relative;
  background: var(--rust);
  color: var(--paper);
  border-radius: var(--r-shape);
  padding: var(--pad-top, 1.75rem) var(--in) var(--pad-bot, 1.75rem);
  display: grid;
  align-content: center;
  justify-items: start;
  gap: var(--s4);
}

/* 2.5rem at every width, top and bottom equal. Equal because the promise is
   centred in the shape and asymmetric padding would move it; 2.5rem rather
   than the 1.75rem the phone used to take because the hanging button has to
   clear the promise's lowest ink even when its label runs to two lines. At
   320px that clearance is 30.5px with a one-line label and 5.5px with a
   two-line one; it used to be 9.5px and minus 8.5px. */
.pill--big { --pad-top: 2.5rem; --pad-bot: 2.5rem; }
.pill--small { --pad-top: 2.5rem; --pad-bot: 2.5rem; }

/* The promise is centred on its ink, not on its line boxes. Quicksand at
   line-height 0.94 leaves more air above the caps than below the baselines,
   so the block is nudged down by a measured amount. See README.md, ## Type. */
.promise {
  position: relative;
  top: var(--ink-drop);
  font-size: var(--t-promise);
  font-weight: 700;
  line-height: 0.94;
  letter-spacing: -0.02em;
  max-width: 12ch;
  margin-inline-start: var(--bearing);
}

/* B has a deeper left bearing than O, so the closing promise gets its own. */
.promise--tight { font-size: var(--t-close); max-width: 14ch; margin-inline-start: var(--bearing-b); }

.pill__note {
  font-size: var(--t-lead);
  line-height: 1.4;
  max-width: 34ch;
  margin: 0;
}

/* ---------- the thing that crosses the edge ---------- */

.act {
  display: inline-block;
  background: var(--paper);
  color: var(--rust);
  border: var(--hair) solid var(--rust);
  border-radius: var(--r-stadium);
  padding: 0.7em 1.5em;
  font-family: var(--display);
  font-size: var(--t-body);
  font-weight: 700;
  line-height: 1.15;
  text-decoration: none;
  transition: background-color 140ms linear, color 140ms linear, border-color 140ms linear;
}
.act:hover { background: var(--ink); border-color: var(--ink); color: var(--paper); }
.act:active { background: var(--rust); border-color: var(--paper); color: var(--paper); }

/* Half on the rust, half on the paper, and starting exactly where the pill's
   curve ends, which is the same line the promise starts on. */
.act--hang {
  position: absolute;
  left: var(--in);
  bottom: 0;
  transform: translateY(50%);
}

/* The one motion moment: on load the hero button drops the last twelve pixels
   onto the edge it sits on. It never fades, so it is legible from the first
   painted frame, which matters because it is the primary action. */
.act--settle { animation: settle 520ms cubic-bezier(0.22, 0.7, 0.3, 1) both; }

@keyframes settle {
  from { transform: translateY(calc(50% - 12px)); }
  to   { transform: translateY(50%); }
}

/* ---------- hero ---------- */
/* Everything under the pill starts on the pill's own line. */

.said {
  margin-top: clamp(2rem, 6vw, 4.75rem);
  padding-left: var(--in);
  display: grid;
  gap: var(--s3);
  max-width: calc(var(--in) + 60ch);
}

.turn {
  font-size: var(--t-turn);
  line-height: 1.08;
  letter-spacing: -0.015em;
  max-width: 20ch;
  margin-bottom: var(--s2);
}

.say { font-size: var(--t-body); max-width: 54ch; }
.say--quiet { color: var(--muted); }
.say--small { font-size: var(--t-small); color: var(--muted); }

/* ---------- the hollow shape ---------- */
/* The twin of the hero pill and the page's second photo state: while there is
   no photograph the slot is the same shape drawn in outline, holding true
   words. When a photograph arrives it takes the frame and the words go. */

.shot { margin: 0; }

.shot img {
  width: 100%;
  border-radius: var(--r-shape);
  object-fit: cover;
}
.shot--wide img { aspect-ratio: 5 / 2; }
.shot--room img { aspect-ratio: 3 / 2; }

.shot:not(.is-empty) .hollow,
.shot:not(.is-empty) .plan,
.shot:not(.is-empty) .shot__note { display: none; }

.shot--wide { margin-top: var(--gap); }

.hollow {
  border: var(--hair) solid var(--rust);
  border-radius: var(--r-shape);
  padding: clamp(1.5rem, 4.5vw, 2.5rem) var(--in);
  display: grid;
  gap: var(--s2);
}

.hollow__line {
  margin: 0;
  font-family: var(--display);
  font-size: var(--t-turn);
  font-weight: 600;
  line-height: 1.1;
  letter-spacing: -0.01em;
  color: var(--rust);
  max-width: 28ch;
  text-wrap: balance;
}

.hollow__note {
  margin: 0;
  font-size: var(--t-small);
  color: var(--muted);
  max-width: 64ch;
  text-wrap: pretty;
}

/* ---------- headings ---------- */

.head {
  font-size: var(--t-head);
  line-height: 1.12;
  letter-spacing: -0.015em;
  max-width: 22ch;
  margin-bottom: var(--gap-in);
}

/* ---------- the price list ---------- */
/* A ruled list, and the price is the shape that crosses the rule. Nothing is
   boxed: the hairline is the row, the pill is the figure, and that is all. */

.fees {
  list-style: none;
  margin: 0 0 var(--gap-in);
  padding: 0;
  display: grid;
  border-bottom: var(--hair) solid var(--clay);
}

.fee {
  position: relative;
  border-top: var(--hair) solid var(--clay);
  /* More air below the row than above it, so the figure astride the rule is
     nearer the service it prices than the one before it. Measured ink to ink
     at 390: 8.8px to its own name, 30.3px to the note above. */
  padding-top: var(--s3);
  padding-bottom: calc(var(--s5) + var(--s2));
}

.fee__fig {
  position: absolute;
  top: 0;
  right: 0;
  transform: translateY(-50%);
  margin: 0;
  background: var(--rust);
  color: var(--paper);
  border-radius: var(--r-stadium);
  padding: 0.28em 0.9em;
  font-family: var(--display);
  font-size: var(--t-fig);
  font-weight: 700;
  line-height: 1.25;
  letter-spacing: 0.005em;
  white-space: nowrap;
}

.fee__name {
  font-size: var(--t-name);
  line-height: 1.15;
  letter-spacing: -0.015em;
  margin-bottom: var(--s2);
}

.fee__note { margin: 0; color: var(--muted); max-width: 58ch; }

.fees__after { max-width: 56ch; }

/* ---------- the four steps ---------- */
/* The only sequence on the page, so the only numerals. They sit astride a
   rounded rail with the same caps as every other shape here: the crossing
   again, at the smallest scale it is used. */

.steps {
  list-style: none;
  margin: 0;
  padding: 0 0 0 3.125rem;
  position: relative;
  counter-reset: step;
  display: grid;
  gap: var(--gap-in);
}

.steps::before {
  content: "";
  position: absolute;
  left: 1.1875rem;
  top: 0.8rem;
  bottom: 0.8rem;
  width: var(--hair);
  background: var(--clay);
  border-radius: var(--r-stadium);
}

.step {
  counter-increment: step;
  position: relative;
  font-size: var(--t-body);
  max-width: 60ch;
}

.step::before {
  content: counter(step);
  position: absolute;
  left: -3.125rem;
  top: -0.05em;
  width: 2.125rem;
  height: 2.125rem;
  display: grid;
  place-items: center;
  background: var(--paper);
  color: var(--rust);
  border: var(--hair) solid var(--rust);
  border-radius: var(--r-stadium);
  font-family: var(--display);
  font-size: var(--t-fig);
  font-weight: 700;
  line-height: 1;
}

/* ---------- who is here ---------- */

.creds {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  border-bottom: var(--hair) solid var(--clay);
}

.creds li {
  border-top: var(--hair) solid var(--clay);
  padding-block: 0.625rem;
  font-size: var(--t-small);
  line-height: 1.35;
}

.heard { display: grid; gap: var(--s4); margin-top: var(--gap-in); }

.told { margin: 0; }

.told blockquote {
  margin: 0 0 var(--s1);
  font-size: var(--t-lead);
  line-height: 1.32;
  max-width: 50ch;
}

.told figcaption {
  font-size: var(--t-small);
  font-weight: 700;
  color: var(--rust);
}

/* ---------- the room ---------- */
/* One room with one table and one bath, drawn at the scale it is described
   at. Every element is on the page's radius scale, so the plan and the pill
   are the same idea at two sizes. */

.shot--room { margin-top: var(--gap-in); }

.plan {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 3 / 2;
  background: var(--oat);
  border-radius: var(--r-shape);
  color: var(--rust);
}

.plan__wall { fill: none; stroke: currentColor; stroke-width: 3; }
.plan__gap { fill: var(--oat); }
.plan__glass { fill: currentColor; }
.plan__swing { fill: none; stroke: currentColor; stroke-width: 1.5; opacity: 0.55; }
.plan__thing { fill: none; stroke: currentColor; stroke-width: 2.5; }
.plan__tag {
  /* colour as well as fill, so what a contrast checker reads is what is
     painted: an SVG text node inherits `color` and paints with `fill`. */
  color: var(--ink);
  fill: currentColor;
  font-family: var(--display);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.02em;
}

.shot__note {
  margin-top: var(--s2);
  font-size: var(--t-small);
  color: var(--muted);
  max-width: 46ch;
}

/* ---------- footer ---------- */

.foot {
  background: var(--ink);
  color: var(--paper);
  padding-block: var(--gap) var(--s5);
}

.head--pale { color: var(--paper); }

.ways {
  list-style: none;
  margin: 0 0 var(--gap-in);
  padding: 0;
  display: grid;
  gap: var(--s2);
  font-size: var(--t-lead);
}

.ways a {
  display: inline-block;
  padding-block: 4px;
}

.ways a, .where a {
  overflow-wrap: anywhere;
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: 0.22em;
}

.where { margin: 0 0 var(--gap-in); color: var(--pale); line-height: 1.6; }
.where a { color: var(--paper); }

.week { border-collapse: collapse; text-align: left; width: 100%; max-width: 24rem; }

.week caption {
  text-align: left;
  font-family: var(--display);
  font-size: var(--t-small);
  font-weight: 700;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--pale);
  padding-bottom: var(--s2);
}

.week th, .week td {
  border-top: var(--hair) solid #4a3a26;
  padding-block: 0.625rem;
  font-size: var(--t-small);
  font-weight: 400;
  vertical-align: baseline;
}
.week th { padding-right: var(--s4); }
.week td { color: var(--pale); }

.rights {
  max-width: 72rem;
  margin: var(--gap-in) auto 0;
  padding-inline: var(--edge);
  font-size: var(--t-small);
  color: var(--pale);
}

.foot :focus-visible { outline-color: var(--paper); }

/* ---------- two columns, from 52em ---------- */

@media (min-width: 52em) {
  .fees { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: var(--s6); }
  .fee { padding-top: var(--s4); padding-bottom: calc(var(--s5) + var(--s4)); }
  .steps { gap: var(--s5); }

  /* The four steps take the wide column and the room takes the narrow one:
     the plan is a small drawing and the instructions need a measure. */
  .run {
    display: grid;
    grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr);
    column-gap: var(--s6);
    align-items: start;
  }
  .shot--room { margin-top: 0; }

  .creds { grid-template-columns: repeat(3, minmax(0, 1fr)); column-gap: var(--s5); }

  .heard { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: var(--s6); }

  .hold--foot {
    display: grid;
    grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr);
    column-gap: var(--s6);
    align-items: start;
  }
}

/* ---------- the stadium, from 64em ---------- */
/* Both pills are now wider than they are tall, so the curve becomes a full
   half-circle cap and the inset follows it: --in is exactly half the pill's
   height, which is where the bottom edge starts running straight. The
   promise, the button and every line under the pill sit on that one x. */

@media (min-width: 64em) {
  /* Half of 22rem is 11rem, and 11rem is where the left cap of a 22rem-tall
     stadium stops curving. That one number is the pill's radius, the pill's
     inside edge, the x the button hangs from and the x every line under the
     pill starts on. */
  :root {
    --pill-h: 22rem;
    --r-shape: calc(var(--pill-h) / 2);
    --in: var(--r-shape);
  }

  .pill--big { min-height: var(--pill-h); }
  /* Three lines at 92px, the last one carrying a descender, sit deeper than
     the two-line case the shared value is measured on. */
  .pill--big .promise { --ink-drop: 0.002em; }

  /* The closing pill is shorter, so it gets its own half. */
  .pill--small {
    --pill-h: 15rem;
    --r-shape: calc(var(--pill-h) / 2);
    --in: var(--r-shape);
    min-height: var(--pill-h);
  }

  /* The hollow band keeps the page's line rather than its own: it sits
     directly under the words that start at 11rem, and a second indent three
     inches to the left would read as a slip, which is the fault this design
     was rebuilt to fix. Its radius is still half its own height. */
  /* The hollow twin is narrower than the filled pill on purpose: it is a step
     down, and it is sized so that every pixel inside it is used. Its left
     inset is still the page's 11rem line; its right inset is its own tangent,
     half its height, so the words stop exactly where the right cap begins. */
  .hollow {
    --pill-h: 11rem;
    min-height: var(--pill-h);
    border-radius: calc(var(--pill-h) / 2);
    align-content: center;
    padding-right: calc(var(--pill-h) / 2);
  }
  .shot--wide { max-width: 45rem; }

  .shot--wide img { border-radius: var(--r-stadium); }

  .plan, .shot--room img { border-radius: 3.5rem; }

  /* The turn and the three lines that answer it sit side by side, so the
     hero fills the screen instead of running out of words a third across. */
  .said {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
    column-gap: var(--s6);
    max-width: none;
  }
  .turn { grid-column: 1; grid-row: 1 / span 3; max-width: 17ch; margin-bottom: 0; }

  /* #about takes the hero's sidehead grammar rather than running a 497px
     paragraph under a full-width rule and leaving 512px of paper beside it. */
  .two {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.2fr);
    column-gap: var(--s6);
    row-gap: var(--s3);
  }
  .two .head { grid-column: 1; grid-row: 1 / span 2; max-width: 15ch; margin-bottom: 0; }

  /* The closing pill sets the promise and the lead time side by side, so the
     shape is not 52 per cent empty rust. The note is 57 characters and never
     wraps past two lines in its column. */
  .pill--small {
    grid-template-columns: minmax(0, 28rem) minmax(0, 1fr);
    column-gap: var(--s6);
    align-items: center;
  }
  /* Two things side by side make a taller row than the promise alone, so the
     closing promise carries its own measured offset. Scanned the same way:
     5.67px, which at 48px is 0.118em. */
  .pill--small .promise { --ink-drop: -0.091em; }

  .steps { padding-left: 4.25rem; }
  .steps::before { left: 1.6875rem; }
  .step::before { left: -4.25rem; width: 2.875rem; height: 2.875rem; }
}

/* ---------- what the browser is told to do less of ---------- */

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

/* In forced-colours mode every background is thrown away, so the shapes that
   are only a fill would disappear. Each one is given an edge instead. */
@media (forced-colors: active) {
  .pill, .fee__fig, .hollow, .plan { border: 2px solid CanvasText; }
  .plan { border-radius: var(--r-shape); }
  .fee__fig { border-radius: var(--r-stadium); }
}
