/* Groundwork. A bedrock ground, one moss accent, and five earth colours that
   are the page as well as the drawing: the whole idea is what is under the
   ground, so the page is under the ground.

   You start at the bottom of the hole and come up. The hero is bedrock and so
   is the section under it, which is why the drawing's lowest layer has no
   findable join. Then the bands climb one layer at a time: gravel behind the
   argument about drainage, the clay the terrace is cut into, and daylight -
   paper - only where the two customers speak. The last word drops back into
   gravel and the footer closes on bedrock.

   The drawing appears three times and never as ornament. Whole, in the hero,
   so the promise sits on the horizon line. Rotated upright and set to page
   scale in the services band, where the four things this business does are
   stacked in the order the ground meets them and the colour beside each one is
   the layer it works in: delete that column and the section keeps its ruled
   rows and loses its identity, which is the honest claim and was checked by
   deleting it. Thin, above the footer, where the page sinks back into the
   ground it opened on. A fourth appearance is where a device becomes an
   eyebrow rule.

   Everything else is plain, and two grammars carry the idea further without
   drawing it again: a ruled row with a mono measurement (the service depths,
   the ground each testimonial was dug in, the two figure ledgers, the hours),
   and a terraced stair of steps in "from your call to the last load out",
   which is cut and fill as a layout rather than as a picture. */

:root {
  /* Colour. See README.md for which of these are safe to change. */
  --bg: #1b2124;          /* bedrock: the page itself */
  --ink: #dfe3dc;         /* the type on it, 12.53 */
  --muted: #a7afab;       /* second voice on bedrock, 7.26 */
  --accent: #8fb45f;      /* moss, the same hue as before at 125 degrees,
                             lifted for a dark page: 6.87 on bedrock */
  --accent-ink: #16200c;  /* type on --accent, 7.11 */
  --tint: #2f383c;        /* gravel: the drainage band and the last word */
  --rule: #767f7b;        /* hairline on bedrock: 3.95 */
  --rule-tint: #7e8883;   /* hairline on the gravel band: 3.27 */
  --rule-deep: #646e6b;   /* the cell edges inside the core sample: 3.09 */

  /* Daylight. One band only, where the two customers speak, and the inside of
     the two figure frames inverts back the other way. */
  --paper: #dcdfd6;
  --on-paper: #22282b;         /* 11.07 on paper */
  --on-paper-muted: #4b5452;   /* 5.79 */
  --accent-paper: #425a29;     /* 5.71 on paper: the dark moss, same hue */
  --rule-paper: #6d7268;       /* 3.66 on paper */

  /* The clay band the terrace is cut into. */
  --on-clay-muted: #3a423f; /* second voice on the clay band, 4.64 */
  --rule-clay: #67583b;     /* hairline on the clay band, 3.10 */

  /* The inside of a figure frame is always bedrock, whatever band it sits in:
     a window cut down into the ground. */
  --well: #1b2124;
  --on-well: #dfe3dc;
  --on-well-muted: #a7afab;
  --mat: var(--well);

  /* The strata. Fills only, no text ever sits on them. */
  --soil: #3f3527;        /* topsoil, in the drawings and the sleepers */
  --soil-cell: #4e412f;   /* topsoil as a block on bedrock; see README */
  --ochre: #a87f2e;       /* ochre subsoil */
  --clay: #c1ab83;        /* pale clay, and the buff pebbles */
  --gravel: #6b7377;      /* gravel and rock */
  --stone: #8b9295;       /* the stones in the gravel */

  /* Type scale. Two decisions, not one: 123px over the 19px lead is 6.47:1 at
     1440, and 44px over the 16px lead is 2.75:1 at 390. Both are chosen; see
     the Type section of README.md for why neither is the other's consequence. */
  --t-display: clamp(2.375rem, 11.3vw, 7.6875rem);
  --t-statement: clamp(1.75rem, 4vw, 2.75rem);
  --t-sec: clamp(1.25rem, 3.1vw, 2.25rem);
  --t-h: clamp(1.125rem, 2.6vw, 1.875rem);
  --t-said: clamp(1rem, 1.9vw, 1.375rem);
  --t-lead: clamp(1rem, 0.55vw + 0.86rem, 1.1875rem);
  --t-body: clamp(1rem, 0.45vw + 0.9rem, 1.0625rem);
  --t-small: 0.9375rem;
  --t-mono: 0.8125rem;

  /* Spacing scale. */
  --s1: 0.25rem;
  --s2: 0.5rem;
  --s3: 1rem;
  --s4: 1.5rem;
  --s5: clamp(1.375rem, 3.4vw, 2.25rem);
  --s6: clamp(1.625rem, 4.6vw, 3.5rem);
  --pad: clamp(1.25rem, 5vw, 3.5rem);
  --band: clamp(1.25rem, 5.2vw, 4.75rem);

  --display: "Saira", "Saira Semi Expanded", "Arial Black", "Segoe UI", sans-serif;
  --sans: Candara, Optima, "Gill Sans", "Gill Sans MT", "Segoe UI", sans-serif;
  --mono: Consolas, "Cascadia Mono", Menlo, "DejaVu Sans Mono", ui-monospace, monospace;
  --wrap: 74rem;
}

/* One self-hosted display face, subset, in this folder. Nothing is fetched
   from anybody else's server. See the Type section of README.md. */
@font-face {
  font-family: "Saira";
  src: url("saira-subset.woff2") format("woff2-variations"),
       url("saira-subset.woff2") format("woff2");
  font-weight: 500 800;
  font-style: normal;
  font-display: swap;
}

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

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

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

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  font-size: var(--t-body);
  line-height: 1.5;
  overflow-wrap: break-word;
}

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; }

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

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

.wrap {
  max-width: var(--wrap);
  margin: 0 auto;
  padding-inline: var(--pad);
}

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

/* ---------- top bar ---------- */
/* Wordmark and the phone number always; the section links appear at 46em, so
   there is no menu button and no JavaScript anywhere on the page. */

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

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

.topnav { display: none; }

/* The number is a finger target before it is a label: the padding is what
   takes it past 24 by 24 on a phone, not the type size. */
.topbar__call {
  display: inline-block;
  padding: var(--s2) 0;
  font-family: var(--mono);
  font-size: var(--t-mono);
  line-height: 1.4;
  color: var(--accent);
  white-space: nowrap;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.3em;
}

/* ---------- hero ---------- */
/* overflow is clipped so the strata can settle up into place on load without
   showing a gap under it; what it settles onto is the services band, which is
   painted in the same bedrock colour as the drawing's bottom layer, so the
   page opens by sinking into the ground rather than by ending a picture. */

.hero {
  overflow: hidden;
  padding-top: var(--s4);
}

.hero__words { padding-bottom: var(--s4); }

h1 {
  font-size: var(--t-display);
  font-weight: 800;
  line-height: 0.92;
  letter-spacing: -0.03em;
  max-width: 13ch;
  margin-bottom: var(--s5);
}

.hero__row {
  display: grid;
  gap: var(--s5);
  align-items: end;
}

.lead {
  font-size: var(--t-lead);
  line-height: 1.4;
  max-width: 52ch;
  margin-bottom: var(--s4);
}

.lead--wide { max-width: 52ch; }

.note {
  font-size: var(--t-small);
  color: var(--muted);
  margin-top: var(--s3);
}

/* Three short facts, standing on the horizon. Mono because they are measured
   quantities, and hairlines because a list of three needs separating and
   nothing more. */
.facts {
  list-style: none;
  margin: 0;
  padding: 0;
  font-family: var(--mono);
  font-size: var(--t-mono);
  line-height: 1.4;
}

.facts li {
  border-top: 1px solid var(--rule);
  padding-block: var(--s2);
}

/* ---------- the strata ---------- */

.strata {
  display: block;
  width: 100%;
  height: clamp(96px, 26vw, 380px);
}

.strata--hero {
  animation: settle 900ms cubic-bezier(0.16, 0.72, 0.3, 1) both;
}

@keyframes settle {
  from { transform: translateY(14px); }
  to { transform: translateY(0); }
}

/* ---------- bands ---------- */

/* Four grounds, climbing. Bedrock is the page, so the hero and the core
   sample need no band at all and the join between them is the drawing's own
   bottom layer, which is the point. Then gravel, then the clay the terrace is
   cut into, then one band of daylight where the customers speak, then gravel
   again for the last word, and bedrock closes under the footer.

   `problem` and `how` are the two sections a brief may skip, and the grounds
   around them are chosen so that deleting either or both never puts two of the
   same ground side by side. The one repeated join, hero against services, is
   deliberate and is the seam. */
.band { padding-block: var(--band); }

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

.band--clay {
  background: var(--clay);
  --ink: var(--on-paper);
  --rule: var(--rule-clay);
  --muted: var(--on-clay-muted);
  --accent: var(--on-clay-muted);
  color: var(--on-paper);
}

/* The one band of daylight. Every colour flips back; the figure frame inside
   it does not, because the frame is a hole in the ground. */
.band--paper {
  background: var(--paper);
  --ink: var(--on-paper);
  --muted: var(--on-paper-muted);
  --accent: var(--accent-paper);
  --rule: var(--rule-paper);
  color: var(--on-paper);
}

.section-head {
  font-size: var(--t-sec);
  font-weight: 800;
  letter-spacing: -0.01em;
  line-height: 1.1;
  margin-bottom: var(--s3);
}

/* No longer scoped to one band: every band declares its own --muted, so the
   class carries its constraint instead of the selector carrying it. */
.section-note {
  font-family: var(--mono);
  font-size: var(--t-mono);
  color: var(--muted);
  margin-bottom: var(--s4);
}

.statement {
  font-size: var(--t-statement);
  line-height: 1.06;
  letter-spacing: -0.02em;
  max-width: 18ch;
  margin-bottom: var(--s3);
}

.aside {
  font-size: var(--t-small);
  line-height: 1.6;
  color: var(--muted);
  max-width: 52ch;
}

/* ---------- the figure frame ---------- */
/* One frame, two states. The constant is not a rule on the image, which a dark
   photograph swallows, but ten pixels of the page ground held inside a 2px
   keyline: matting. It is visible against any photograph, and while the slot
   is empty it holds a real table rather than leaving a column standing empty.
   Nothing here is display: none on a figure. */

.shot {
  margin: 0;
  border: 2px solid var(--rule);
  padding: 10px;
  background: var(--mat);
  align-self: start;
}

.shot img {
  display: block;
  width: 100%;
  height: auto;
  object-fit: cover;
}

/* Both slots are landscape at every width. A standing 4:5 crew crop was tried
   and rejected: at 1440 it finished 121px below the last line of the text
   beside it, which is the hole this library was built full of. The crew slot
   is wider again than the dig slot, because four people in a row want a wide
   frame and because 16:9 is the aspect that keeps the two columns level once
   the frame is big enough to close the gap beside it. */
.shot img { aspect-ratio: 3 / 2; }
.shot[data-aspect="16:9"] img { aspect-ratio: 16 / 9; }

.shot:not(.is-empty) .cut { display: none; }

.shot figcaption {
  font-family: var(--mono);
  font-size: var(--t-mono);
  line-height: 1.4;
  color: var(--on-well-muted);
  margin-top: 10px;
}

/* The drawn empty state: a section cut through the job, on the bedrock the
   frame is a window into. One drawing per slot, and they are two different
   drawings, because two copies of one component on one page is what the
   cross-review caught. Delete the svg when a photograph goes in. */
.cut {
  display: block;
  width: 100%;
  height: auto;
}

.cut__label {
  font-family: var(--mono);
  font-size: 9px;
  letter-spacing: 0.02em;
}

/* The ledger, the hours and the service depths are one grammar: a name, a
   hairline, and a measured quantity in mono hard against the right. */
.hours {
  width: 100%;
  border-collapse: collapse;
  text-align: left;
}

.hours caption {
  text-align: left;
  font-family: var(--mono);
  font-size: var(--t-mono);
  line-height: 1.4;
  color: var(--muted);
  padding-bottom: var(--s2);
}

.hours th {
  font-weight: 400;
  font-size: var(--t-small);
  padding: var(--s1) var(--s3) var(--s1) 0;
  border-top: 1px solid var(--rule);
  vertical-align: baseline;
}

.hours td {
  font-family: var(--mono);
  font-size: var(--t-mono);
  text-align: right;
  padding: var(--s1) 0;
  border-top: 1px solid var(--rule);
  vertical-align: baseline;
}

.hours td { color: var(--muted); }

/* ---------- the problem ---------- */

.problem { display: grid; gap: var(--s5); }

/* ---------- the core sample, which is also the service list ---------- */
/* The hero drawing stood upright and set to page scale. Four rows, read top
   down in the order the ground meets them; the colour beside each one is the
   layer that job works in. The colour cells sit flush against each other, so
   the column they make is a continuous section of ground and not four chips.
   Below 46em the colour becomes a band across the top of each row, so the
   four of them stack down the phone page as layers instead of disappearing. */

.core { display: grid; }

.core__row {
  display: grid;
  gap: 0;
  border-top: 1px solid var(--rule-deep);
}

.core__row:last-child { border-bottom: 1px solid var(--rule-deep); }

.core__layer {
  display: block;
  height: 14px;
  background: var(--gravel);
  /* Every cell is bounded whatever its fill. The topsoil block is dark by
     definition and would otherwise disappear into the bedrock band; lifting
     its fill to 3:1 against the band would make it the ochre cell instead,
     which is the worse failure. The edge is the answer. See README. */
  border-bottom: 1px solid var(--rule-deep);
}

.core__layer--soil { background: var(--soil-cell); }
.core__layer--ochre { background: var(--ochre); }
.core__layer--clay { background: var(--clay); }
.core__layer--rock { background: var(--gravel); }

/* The four cells are CSS backgrounds on empty spans, and Windows high
   contrast repaints a background as Canvas, which takes the device's one
   structural appearance off the page while the two SVG drawings survive
   untouched. These fills are information, so they are kept. */
@media (forced-colors: active) {
  .core__layer { forced-color-adjust: none; }
}

.core__body { padding-block: var(--s3); }

.core__name {
  font-size: var(--t-h);
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 1.1;
  margin-bottom: var(--s2);
}

.core__note {
  max-width: 52ch;
  line-height: 1.5;
  margin-bottom: 0;
}

.core__depth {
  font-family: var(--mono);
  font-size: var(--t-mono);
  line-height: 1.4;
  color: var(--muted);
  padding-bottom: var(--s3);
  margin: 0;
}

/* On a phone the layer and its depth are one line under the colour band; from
   46em the depth moves to its own column and the range drops below the name. */
.core__mm { color: var(--ink); }
.core__mm::before { content: ", "; color: var(--muted); }

/* ---------- the terrace ---------- */
/* Cut and fill, as a layout. Four steps, each one a course lower and a course
   further in than the one above it, with a riser hairline down the left of
   every step after the first. It is the page's idea without drawing it a
   fourth time, and at 62em it is the only thing giving this section a shape:
   take the indents away and it is a list. */

.terrace {
  list-style: none;
  margin: 0 0 var(--s5);
  padding: 0;
  counter-reset: step;
  display: grid;
}

.terrace__step {
  counter-increment: step;
  border-top: 1px solid var(--rule);
  padding-block: var(--s3);
}

.terrace__when {
  font-family: var(--mono);
  font-size: var(--t-mono);
  line-height: 1.4;
  color: var(--accent);
  margin-bottom: var(--s1);
}

/* A literal full stop and space. A CSS hex escape is terminated by one
   whitespace character and consumes it, so " \00B7 " computed to " \00B7"
   and every step rendered "1 .Day one". A numeral joined to a label by a
   middle dot is the contract's own anti-pattern in any case. */
.terrace__when::before {
  content: counter(step) ". ";
}

.terrace__what {
  font-size: var(--t-lead);
  line-height: 1.45;
  max-width: 52ch;
  margin-bottom: 0;
}

/* ---------- who you are dealing with ---------- */

.about { display: grid; gap: var(--s4); margin-bottom: var(--s5); }

.about__text p {
  font-size: var(--t-lead);
  line-height: 1.5;
  max-width: 52ch;
}

/* Two testimonials, in the same grammar as the service depths: a mono line
   naming the ground the job was dug in, a hairline, and what the customer
   said. The ground is the only thing tying a quote to this business's idea,
   so it is the line that gets the label. */

.said { display: grid; gap: var(--s4); }

.said__row {
  margin: 0;
  border-top: 2px solid var(--ink);
  padding-top: var(--s3);
}

/* The blockquote holds only what the customer said. The ground the job was
   dug in and the person's name are the figure's caption, because neither is
   part of the quotation. */
.said__quote { margin: 0; }

.said__ground {
  font-family: var(--mono);
  font-size: var(--t-mono);
  line-height: 1.4;
  color: var(--muted);
  margin-bottom: var(--s3);
}

.said__words {
  font-size: var(--t-said);
  line-height: 1.3;
  letter-spacing: -0.012em;
  max-width: 42ch;
}

.said__who {
  font-size: var(--t-small);
  color: var(--muted);
  margin: var(--s3) 0 0;
}

/* ---------- buttons ---------- */
/* Square, solid and heavy: the one thing on the page that looks built. */

.btn {
  display: inline-block;
  background: var(--accent);
  color: var(--accent-ink);
  border: 3px solid var(--accent);
  padding: 0.75em 1.2em;
  font-family: var(--display);
  font-size: var(--t-body);
  font-weight: 700;
  letter-spacing: 0;
  line-height: 1.15;
  text-decoration: none;
  transition: background-color 120ms linear, border-color 120ms linear;
}
.btn:hover {
  background: var(--ink);
  border-color: var(--ink);
}
.btn:active {
  background: var(--muted);
  border-color: var(--muted);
}
/* The ring is --ink, not --accent: on a button already filled with the accent,
   an accent ring is invisible. Ink on --bg is 11.34, well over the 3.0 the
   contract asks of a focus ring. */
.btn:focus-visible { outline-color: var(--ink); }

/* ---------- final call to action ---------- */

.cta { background: var(--tint); --rule: var(--rule-tint); }

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

.statement--cta { margin-bottom: var(--s5); }

.cta__row { display: grid; gap: var(--s4); }

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

/* No background: the footer is the page, and the page is bedrock. */
.footer { padding-block: var(--s6); }

.reach {
  list-style: none;
  margin: 0 0 var(--s4);
  padding: 0;
  display: grid;
  gap: var(--s1);
  font-size: var(--t-lead);
}

.reach a {
  display: inline-block;
  padding-block: var(--s1);
  overflow-wrap: anywhere;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.3em;
}

.footer :focus-visible { outline-color: var(--ink); }

.footer__where {
  color: var(--muted);
  font-size: var(--t-small);
  max-width: 52ch;
  margin-top: var(--s4);
}

.footer__copy {
  margin-top: var(--s4);
  font-size: var(--t-small);
  color: var(--muted);
}

/* ---------- wider screens ---------- */

@media (min-width: 46em) {
  .topnav {
    display: block;
    margin-inline-start: auto;
  }
  .topnav a {
    display: inline-block;
    padding-block: var(--s2);
    font-size: var(--t-small);
    text-decoration: none;
    border-bottom: 2px solid transparent;
    margin-inline-start: var(--s4);
  }
  .topnav a:hover { border-bottom-color: var(--accent); }

  .topbar__call { margin-inline-start: var(--s5); }

  .hero { padding-top: var(--s5); }

  .hero__row {
    grid-template-columns: minmax(0, 1.5fr) minmax(0, 0.5fr);
    gap: var(--s6);
  }

  /* Words left, the frame right, at every width from here up: the section is
     two columns whether or not a photograph ever arrives. */
  .problem {
    grid-template-columns: minmax(0, 1fr) minmax(0, 0.62fr);
    gap: var(--s6);
    align-items: start;
  }

  /* The core sample proper: a continuous column of ground down the left, the
     work in the middle, the depth hard against the right. */
  .core__row {
    grid-template-columns: 4.5rem minmax(0, 1fr) minmax(0, 11rem);
    column-gap: var(--s5);
  }

  .core__layer {
    height: auto;
    align-self: stretch;
    margin-block: -1px;
  }

  .core__depth {
    padding-top: var(--s3);
    text-align: right;
  }

  .core__mm { display: block; white-space: nowrap; }
  .core__mm::before { content: none; }

  .about {
    grid-template-columns: minmax(0, 1fr) minmax(0, 0.62fr);
    gap: var(--s6);
  }

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

  .cta__row {
    grid-template-columns: minmax(0, 46ch) auto;
    justify-content: start;
    gap: var(--s5);
    align-items: end;
  }
  .cta__row .lead { margin-bottom: 0; }

  .footer .wrap {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: var(--s4) var(--s6);
    align-items: start;
  }
  .footer .section-head { grid-column: 1 / -1; }
  .footer__where,
  .footer__copy { grid-column: 1 / -1; }
  .footer__where { margin-top: var(--s4); }
}

@media (min-width: 62em) {
  h1 { max-width: 14ch; }

  /* The terrace, cut into the slope. Each step sits one course further in than
     the one above it and carries the riser hairline of the cut on its left. */
  .terrace__step + .terrace__step {
    border-left: 1px solid var(--rule);
    padding-inline-start: var(--s4);
  }

  /* The stair still cuts in, but each tread now ends in something: the stage
     is the measured quantity, hard against the right, exactly as the depth is
     on a service row. Before this the rules ran 456px past the last word. */
  .terrace__step {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 14rem);
    column-gap: var(--s5);
    align-items: baseline;
  }
  .terrace__what { grid-column: 1; grid-row: 1; }
  .terrace__when {
    grid-column: 2;
    grid-row: 1;
    text-align: right;
    margin-bottom: 0;
  }
  .terrace__step:nth-child(2) { margin-inline-start: var(--s5); }
  .terrace__step:nth-child(3) { margin-inline-start: calc(var(--s5) * 2); }
  .terrace__step:nth-child(4) { margin-inline-start: calc(var(--s5) * 3); }

  .cta__words {
    display: grid;
    grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr);
    gap: var(--s6);
    align-items: start;
  }
  .statement--cta { margin-bottom: 0; }
  .cta__row { grid-template-columns: minmax(0, 1fr); gap: var(--s4); }
}

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