/* ---------- Type ----------
   The live site sets everything in Roc Grotesk, an Adobe font Squarespace
   licenses and we cannot host. Work Sans is the substitute, chosen by
   measurement rather than taste: of sixteen free candidates it sets the live
   site's own strings closest to Roc Grotesk's widths (1.8% average error, the
   next best 2.0%, the worst 8.4%), which is what keeps line breaks and block
   heights where they were. --track closes the remaining gap.

   Work Sans is the final answer, not a placeholder: Alec chose it on 2026-08-27
   over the two paid routes. Do not swap it out without him asking.

   Putting the real font back COSTS MONEY. An earlier version of this comment
   said Adobe Fonts would give it away with a free account; OBSERVED 2026-08-27
   on Alec's own signed-in account, all 45 Roc Grotesk styles are behind
   "Subscribe to Creative Cloud" and the family has no web-project button, while
   a free-tier face like DM Sans does. Options and prices are in MEMORY.md.
   If a licence is ever bought the change is still one stylesheet link per page
   and --font-body set to 'roc-grotesk'. Nothing else moves. */
@font-face {
  font-family: 'Work Sans'; font-style: normal; font-weight: 300 700; font-display: swap;
  src: url('../fonts/work-sans-latin.woff2') format('woff2');
}

:root {
  /* Colour, straight off the live computed styles. */
  --ink:        #1c1c1c;   /* body text, hero overlay, buttons */
  --paper:      #fafafa;   /* every content section, and text on ink */
  --white:      #ffffff;   /* the footer band only */
  --hairline:   #000000;   /* the wavy section dividers */
  --credit-ink: #000000;   /* credit titles sit a shade darker than body copy */

  --font-body: 'Work Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  /* The live site tracks at a flat 0.16px on body text and 0.32px on buttons,
     OBSERVED off its computed styles. This was previously double that, on the
     theory that extra tracking made Work Sans set to Roc Grotesk's widths; it
     read as visibly loose, so it now follows the live values. */
  --track: 0.16px;
  --track-wide: 0.32px;

  /* Rhythm. The live site's gutter is 4% of the viewport on desktop, 6% below. */
  --gutter: 4vw;

  /* Type scale, fluid between 900px and 1440px and pinned above 1440. */
  --fs-hero:   min(17.93vw, 299px);
  --fs-h1:     min(calc(64.6px  + 27   * (100vw - 900px) / 540), 91.6px);
  --fs-h2:     min(calc(48.4px  + 18   * (100vw - 900px) / 540), 66.4px);
  --fs-h3:     min(calc(43px    + 15   * (100vw - 900px) / 540), 58px);
  --fs-h4:     min(calc(23.56px + 4.2  * (100vw - 900px) / 540), 27.76px);
  --fs-credit: min(calc(22.48px + 3.6  * (100vw - 900px) / 540), 26.08px);
  --fs-fine:   14.272px;
  --fs-body:   16px;

  /* Line heights, straight off the live computed styles. Named for the role
     rather than the number, so the styleguide can label them. */
  --lh-display: 1;        /* the hero name */
  --lh-tight:   1.066;    /* the largest headings */
  --lh-heading: 1.144;    /* section headings and credit titles */
  --lh-lede:    1.17;     /* the one-line promise under the hero */
  --lh-sub:     1.2636;   /* accordion titles, process steps, call to action */
  --lh-body:    1.5;      /* body copy and fine print */
  --lh-loose:   1.5;      /* the Selected Credits title, which sits looser */

  /* Shapes and controls. */
  --radius-pill:  300px;   /* buttons */
  --radius-field: 23.84px; /* form inputs, which the live site rounds hard */
  --control-h:    68px;    /* button height */
  --field-h:      42px;    /* input height */
  --field-pad:    8px 15px;
  --rule:         1px solid var(--ink);
  --wave-h:       60px;    /* the band the section divider is drawn in */
  --wave-stroke:  3;
}

/* ---------- Reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  background: var(--white);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  letter-spacing: var(--track);
  -webkit-font-smoothing: antialiased;
}
img { max-width: 100%; height: auto; display: block; }
a { color: inherit; }
h1, h2, h3, h4, p { margin: 0; font-weight: 400; }
/* Live tracks its body copy, links and the hero, but leaves headings at zero.
   OBSERVED: every h1-h4 on the live home page and flyer computes to
   letter-spacing: normal while its paragraphs compute to 0.16px. */
h1, h2, h3, h4 { letter-spacing: normal; }
/* The live site sets its emphasis with <strong> at 700 inside an otherwise 400
   heading: the intro line, the call to action, the four process headings and the
   contact headline. OBSERVED off the live computed styles 2026-08-27. */
strong, b { font-weight: 700; }
fieldset { border: 0; padding: 0; margin: 0; min-width: 0; }
legend { padding: 0; }
:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }

.skip-link {
  position: absolute; left: -9999px; top: 0;
  background: var(--ink); color: var(--paper); padding: 12px 20px; z-index: 100;
}
.skip-link:focus { left: 0; }
.honeypot {
  /* Not the clip-path trick used for visually-hidden content: that keeps the
     field in the accessibility tree on purpose. A screen reader would meet an
     unlabelled input, and filling it in gets the whole enquiry rejected. */
  display: none;
}

/* ---------- Header ---------- */
.site-header {
  padding: calc(var(--gutter) / 2) var(--gutter);
  background: var(--white);
}
.header-inner {
  display: flex; align-items: center; justify-content: space-between; gap: 24px;
}
.logo { display: block; flex: 0 1 auto; min-width: 0; }
.logo img { width: 142px; max-width: 100%; height: auto; aspect-ratio: 2 / 1; object-fit: contain; }
.header-right { display: flex; align-items: center; gap: 28px; flex: none; }
/* Tap targets. Everything below grows the area a thumb can hit to about 44px,
   Apple's own floor, WITHOUT moving anything: vertical padding on an inline or
   flex item is paid back by an equal negative margin, and the icons grow through
   a pseudo-element that takes up no space at all. Found by verify/mobile-audit.mjs
   at 375, 390 and 430; re-run it after touching any of these. */
.nav-link { text-decoration: none; padding: 10px 0; margin: -8px 0; }
.nav-link:hover, .nav-link[aria-current='page'] { text-decoration: underline; text-underline-offset: 4px; }
/* Live fades rather than switching: 0.25s on links, 0.17s on the social icons. */
a { transition: opacity 0.25s cubic-bezier(0.4, 0, 0.2, 1); }
a:hover { opacity: 0.75; }
.social a, .footer-social a { transition: opacity 0.17s ease-in-out; }
/* ---------- Menu (below 768) ----------
   Live drops the desktop nav for a two-line burger: two 35x1px rules, 11px
   apart, at the right of the header. Tapping it opens a full-screen sheet with
   the nav centred at 33px and the social icons near the bottom. All of those
   numbers are OBSERVED off the live mobile header and its open menu. */
.burger {
  display: none; position: relative; width: 44px; height: 44px;
  margin-right: -5px; padding: 0; border: 0; background: none; cursor: pointer;
}
.burger-line {
  position: absolute; left: 50%; width: 35px; height: 1px; background: var(--ink);
  transition: transform 0.25s cubic-bezier(0.2, 0.6, 0.3, 1);
}
.burger-line:nth-child(1) { transform: translate(-50%, -5.5px); }
.burger-line:nth-child(2) { transform: translate(-50%,  5.5px); }
.burger[aria-expanded='true'] .burger-line:nth-child(1) { transform: translate(-50%, 0) rotate(45deg); }
.burger[aria-expanded='true'] .burger-line:nth-child(2) { transform: translate(-50%, 0) rotate(-45deg); }

.menu-overlay {
  position: fixed; inset: 0; z-index: 90;
  background: var(--paper);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  padding: var(--header-h) var(--gutter) 38px;
}
.menu-overlay[hidden] { display: none; }
.menu-nav { display: flex; flex-direction: column; align-items: center; gap: 24px; margin: auto 0; }
.menu-nav a { font-size: 33.15px; line-height: var(--lh-sub); text-decoration: none; text-align: center; }
.menu-nav a[aria-current='page'] { text-decoration: underline; text-underline-offset: 6px; }
.menu-social { display: flex; align-items: center; gap: 12px; }
.menu-social a { display: block; position: relative; width: 25px; height: 25px; color: var(--ink); }
.menu-social svg { width: 25px; height: 25px; fill: currentColor; display: block; }
.menu-social a::after {
  content: ''; position: absolute; top: 50%; left: 50%;
  width: 32px; height: 44px; transform: translate(-50%, -50%);
}
/* The page must not scroll behind an open sheet. */
body.menu-open { overflow: hidden; }

.social { display: flex; align-items: center; gap: 28px; }
.social a { display: block; position: relative; width: 20px; height: 20px; color: var(--ink); }
/* 44x44 of hit area around a 20px icon. The icons sit 48px apart centre to
   centre, so these do not overlap each other. */
.social a::after {
  content: ''; position: absolute; top: 50%; left: 50%;
  width: 44px; height: 44px; transform: translate(-50%, -50%);
}
.social svg { width: 20px; height: 20px; fill: currentColor; display: block; }

/* ---------- Sections ---------- */
.section { position: relative; background: var(--paper); }
.section > .inner { padding-left: var(--gutter); padding-right: var(--gutter); }

/* The wavy rule between sections. Two full waves across the width, drawn 20px
   above the section's bottom edge, exactly as the live section dividers sit.

   Two things here were behind the stroke thinning at the bottom of every
   trough. The baseline used to sit at 39.5 of 60, which put the trough's ink
   at 59 of 60 in viewBox units. The stroke does not scale (it is a flat 3px),
   so its lower half needs 1.5px of room, and at a 20px band 1 viewBox unit is
   only 0.33px. The trough's ink overhung the band by 1.17px, and the next
   section's opaque background painted straight over it: measured 1.75px of
   visible stroke at every trough against 3px everywhere else. A baseline of 35
   leaves room for the half-stroke at both the 20px and the 60px band.

   The viewBox is 1200x60 rather than the 1x1 it used to be. That is not what
   caused the thinning, but a 1x1 box stretched to 390x20 is a 19.5:1 squash
   that the curve flattener has to work in, and it made the geometry impossible
   to reason about in pixels. 1200x60 is the band's own aspect ratio, so the
   scale is ~1:1 in both axes at every breakpoint. The curve is unchanged:
   every coordinate is the old one times 1200 or 60. */
.wave { position: absolute; left: 0; right: 0; bottom: 0; height: var(--wave-h); pointer-events: none; }
.wave svg { width: 100%; height: 100%; display: block; overflow: visible; }
.wave path { fill: none; stroke: var(--hairline); stroke-width: var(--wave-stroke); vector-effect: non-scaling-stroke; }

/* Section content paints above the divider, the way live layers it. An opaque
   photo then hides a crest that reaches too high instead of being sliced by it.
   Without this the absolutely-positioned wave paints over everything in flow.

   Scoped to .inner deliberately. The obvious rule, .section > *:not(.wave),
   also catches .flyer-about-photo, which is position:absolute against its
   section; forcing it to relative dropped it back into flow and grew that page
   by 841px at 1440. .inner is always a plain flow container, so it is safe. */
.section > .inner { position: relative; z-index: 1; }

/* ---------- Hero ---------- */
/* No top padding: the live site overlays its header on the hero and pads the
   section to clear it. Ours is in normal flow, so it already occupies that space. */
.hero { padding: 0 var(--gutter) var(--gutter); background: var(--white); }
.hero-block {
  position: relative; overflow: hidden;
  height: min(calc(186.7px + 48.7vw), 998px);
  background: var(--ink);
  display: grid; place-items: center;
}
.hero-block img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.hero-block::after {
  content: ''; position: absolute; inset: 0; background: var(--ink); opacity: 0.3;
}
.hero-title {
  position: relative; z-index: 2;
  font-size: var(--fs-hero); line-height: var(--lh-display); color: var(--paper); text-align: center;
  letter-spacing: 0.16px;
}

/* The hand-drawn underline. The path, its 1295 dash length and the 0.1em stroke
   are lifted from the live site's own shape node; the geometry is in em so it
   scales with the hero rather than being pinned to 1440. At 258.5px the box is
   1249x313 sitting at -19,-28 from the text, which is what these ems are. */
.hero-underline {
  position: absolute; left: -0.0735em; top: -0.1083em;
  width: 4.8317em; height: 1.2108em;
  overflow: visible; pointer-events: none; z-index: 1;
}
.hero-underline path {
  fill: none; stroke: #fff; stroke-width: 25.8;
  stroke-linecap: round; stroke-linejoin: round;
  stroke-dasharray: 1295; stroke-dashoffset: 3885;
  animation: hero-underline-draw 900ms cubic-bezier(0.33, 0, 0.2, 1) 250ms forwards;
}
@keyframes hero-underline-draw { to { stroke-dashoffset: 2590; } }

/* ---------- Intro ---------- */
.intro { padding: 39px 0 133px; text-align: center; }
.intro .inner { max-width: 68.82vw; margin: 0 auto; padding: 0; }
.intro h2 { font-size: var(--fs-h2); line-height: var(--lh-heading); }
.intro h3 { font-size: var(--fs-h3); line-height: var(--lh-lede); margin-top: 11px; }

/* ---------- Two-column sections ----------
   Every photo is a CROP. The live site crops each one to its own frame, and the
   source files have their own, different shapes, so the ratio has to be stated
   rather than inherited from the file. Without this the browser either stretches
   the picture to the HTML height attribute or letterboxes it to the file's shape,
   and neither is what the live page shows. */
.split { padding: 95px 0 138px; }
.process { padding-bottom: 178px; }
.about { padding: 87px 0 126px; }
.split .inner { display: grid; gap: 4.58vw; align-items: start; }
.split .split-media img { width: 100%; object-fit: cover; }
.services .split-media img { aspect-ratio: 546 / 830; }
.process .split-media img  { aspect-ratio: 490 / 897; }
.about .split-media img    { aspect-ratio: 601 / 739; }

.split--text-left .inner  { grid-template-columns: 49.5vw 37.9vw; }
.split--text-right .inner { grid-template-columns: 34vw 53.4vw; }

.section-title { font-size: var(--fs-h2); line-height: var(--lh-heading); }
.section-title--big { font-size: var(--fs-h1); line-height: var(--lh-tight); }

/* Services + Rates */
.services .accordion { width: 41.7vw; margin-top: 11px; }
.accordion-item { border-bottom: var(--rule); }
.accordion-item:first-child { border-top: var(--rule); }
.accordion-trigger {
  width: 100%; display: flex; align-items: center; justify-content: space-between; gap: 16px;
  background: none; border: 0; padding: 14px 0; cursor: pointer; text-align: left;
  font: inherit; font-size: var(--fs-h4); line-height: var(--lh-sub); color: var(--ink);
  letter-spacing: inherit;
}
/* Live rotates the plus into a minus over 0.25s rather than swapping the glyph. */
.accordion-mark {
  flex: none; width: 1em; height: 1em; position: relative;
  font-size: var(--fs-h4); line-height: var(--lh-display);
}
.accordion-mark::before, .accordion-mark::after {
  content: ''; position: absolute; top: 50%; left: 50%;
  width: 0.62em; height: 1.6px; background: var(--ink);
  transform: translate(-50%, -50%);
  transition: transform 0.25s ease, opacity 0.25s ease;
}
.accordion-mark::after { transform: translate(-50%, -50%) rotate(90deg); }
.accordion-item[data-open='true'] .accordion-mark::after { transform: translate(-50%, -50%) rotate(0deg); }
.accordion-panel { display: none; padding-bottom: 18px; }
.accordion-item[data-open='true'] .accordion-panel { display: block; }
.accordion-panel p { font-size: var(--fs-fine); line-height: var(--lh-body); }
.fine-print { font-size: var(--fs-fine); line-height: var(--lh-body); margin-top: 12px; width: 41.7vw; }
.call-out { font-size: var(--fs-h4); line-height: var(--lh-sub); margin-top: 31px; text-align: center; width: 41.7vw; }

/* The Process. The live grid indents this heading 113px into its column and
   holds it to 490px, which is what makes it sit over the second step column. */
.process .section-title { margin-left: 7.85vw; width: 34vw; }

.process-steps {
  /* Filled down the columns, not across, so the document order is the order a
     phone reads them in and the desktop grid still matches the live one. */
  display: grid; grid-template-columns: 1fr 1fr; grid-template-rows: auto auto;
  grid-auto-flow: column; column-gap: 122px; row-gap: 65px;
  margin-top: 43px;
}
.process-steps h4 { font-size: var(--fs-h4); line-height: var(--lh-sub); }
.process-steps p { margin-top: 32px; }

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: var(--control-h); padding: 0 32px; border-radius: var(--radius-pill); border: 0;
  background: var(--ink); color: var(--paper);
  font: inherit; font-size: 16px; line-height: var(--lh-display); letter-spacing: var(--track-wide);
  text-decoration: none; cursor: pointer;
}
.btn:hover { opacity: 0.85; }
.btn-row { display: flex; justify-content: center; margin-top: 44px; }
.about .btn-row { margin-top: 74px; }
.services .btn-row { width: 41.7vw; }

/* ---------- Selected Credits ---------- */
.credits { padding: 144px 0 187px; }
.credits-title {
  font-size: var(--fs-h2); line-height: var(--lh-loose); text-align: center;
  padding: 0 var(--gutter);
}
.credits-rail {
  /* No scroll-snap: it snaps the first card flush to the container edge on load
     and eats the gutter the live carousel keeps. */
  display: flex; gap: 20px; overflow-x: auto;
  padding: 69px var(--gutter) 0; margin: 0; list-style: none;
  scrollbar-width: none;
}
.credits-rail::-webkit-scrollbar { display: none; }
/* Alec's ask, and a deliberate improvement on live rather than a copy of it:
   live has no snapping at all and leans on arrow buttons. Snapping to CENTRE
   rather than start is what keeps the gutter; snapping to start is what made an
   earlier attempt slam the first card flush against the container edge. */
@media (max-width: 767.98px) {
  .credits-rail { scroll-snap-type: x mandatory; scroll-padding: 0 var(--bleed); }
  .credit { scroll-snap-align: center; scroll-snap-stop: always; }
}
.credit { flex: 0 0 415px; }
.credit img { width: 415px; height: 416px; object-fit: cover; }
.credit h2 { font-size: var(--fs-credit); line-height: var(--lh-heading); margin-top: 25px; color: var(--credit-ink); max-width: 311px; }
.credit p { margin-top: 25px; max-width: 311px; }
.credit .links { margin-top: 16px; }
.credit a { text-decoration: underline; text-underline-offset: 3px; }

/* ---------- About ---------- */
/* About runs on its own column split: the copy column is wider than the other
   two sections use, and the photo is narrower than the column that holds it. */
.about .inner { grid-template-columns: 46.35vw 45.65vw; gap: 0; }
.about .split-media img { width: 41.7vw; height: auto; }
/* Centered over the copy, not left of it (Alec, 2026-08-28). Same left
   margin and max-width as .about-copy so the two boxes line up exactly at
   every width, which is what makes the centring read. This is a deliberate
   divergence from the old Squarespace layout; that reference is retired. */
.about .section-title { margin-left: 6.6vw; width: auto; max-width: 410px; text-align: center; }
.about .btn-row { width: 41.7vw; }
.about-copy { max-width: 410px; margin-left: 6.6vw; margin-top: 58px; }
.about-copy p + p { margin-top: 16px; }
.about-copy a { text-decoration: underline; text-underline-offset: 3px; }

/* ---------- Footer ---------- */
.site-footer { background: var(--white); color: var(--credit-ink); padding: 79px 0 0; }
.site-footer .inner { padding-left: var(--gutter); padding-right: var(--gutter); }
.site-footer h2 { font-size: var(--fs-h2); line-height: var(--lh-heading); }
.footer-lines { margin-top: 3px; }
.footer-lines p { margin-top: 16px; }
.footer-lines a { text-decoration: underline; text-underline-offset: 3px;
  padding: 13px 0; margin: -13px 0; }
.footer-social { display: flex; justify-content: flex-end; gap: 12px; padding: 20px var(--gutter) 32px; }
.footer-social a { display: block; position: relative; width: 17px; height: 17px; color: var(--credit-ink); }
/* Only 29px apart centre to centre down here, so the hit area goes as wide as
   it can without the two icons stealing each other's taps, and full height. */
.footer-social a::after {
  content: ''; position: absolute; top: 50%; left: 50%;
  width: 28px; height: 44px; transform: translate(-50%, -50%);
}
.footer-social svg { width: 17px; height: 17px; fill: currentColor; display: block; }

/* ---------- Contact ---------- */
.contact { padding: 60px 0 0; }   /* live 189px from the top of the page, less the 129px header */
.contact .inner { display: grid; grid-template-columns: 45.6vw 41.7vw; gap: 4.6vw; align-items: start; }
.contact h1 { font-size: var(--fs-h1); line-height: var(--lh-tight); max-width: 657px; }
.contact h1 strong { font-weight: 700; }
.contact-copy { max-width: 546px; margin-top: 32px; }
.contact-copy p + p { margin-top: 16px; }
.contact-lead { font-size: var(--fs-h4); line-height: var(--lh-sub); font-weight: 700; margin-top: 32px; }
.contact-photo { width: 100%; aspect-ratio: 601 / 808; object-fit: cover;
  margin-top: -21px; }  /* the live photo starts just above the headline */

.form { max-width: 546px; margin-top: 22px; }
.form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 9px; }
.field { margin-top: 20px; }
.field > label, .field-label { display: block; font-size: 16px; line-height: var(--lh-body); padding-bottom: 4px; }
.form-row .field > label { font-size: 12px; }
.req { color: inherit; opacity: 0.75; }
.field input[type='text'], .field input[type='email'], .field select, .field textarea {
  width: 100%; min-height: var(--field-h); padding: var(--field-pad);
  border: 1px solid var(--credit-ink); border-radius: var(--radius-field);
  background: transparent; color: var(--credit-ink);
  font: inherit; font-size: 16px; line-height: var(--lh-body); letter-spacing: inherit;
}
.field select { padding-right: 37px; appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='10' viewBox='0 0 16 10'%3E%3Cpath d='M1 1l7 7 7-7' fill='none' stroke='%23000' stroke-width='1.6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 16px center; }
.field textarea { min-height: 100px; border-radius: var(--radius-field); resize: vertical; }
.field > label.filedrop {
  display: grid; place-items: center; gap: 6px; min-height: 88px;
  border: 1px dashed var(--credit-ink); border-radius: var(--radius-field); cursor: pointer; text-align: center;
}
.filedrop input[type='file'] { position: absolute; width: 1px; height: 1px; opacity: 0; }
.filedrop .plus { font-size: 20px; line-height: var(--lh-display); }
/* Live centres the submit button in the form column: its box is 107x67 whose
   centre lands within half a pixel of the 546px form's centre. */
.form .btn { margin-top: 40px; margin-left: auto; margin-right: auto; display: flex; }
.form-actions { display: flex; justify-content: center; }
.form-status { margin-top: 16px; }

/* ---------- Flyer ----------
   A standalone landing page with its own layout: a big headline graphic, three
   service cards, an About block whose photo bleeds off the right edge, and a
   second enquiry form beside an arch-cropped photo. */
.flyer-banner { padding: 47px 0; text-align: center; }
.flyer-banner img { margin: 0 auto; width: 53.3vw; aspect-ratio: 2 / 1; object-fit: cover; }

.flyer-services { padding: 144px 0 230px; }
.flyer-services .inner {
  display: grid; grid-template-columns: repeat(3, 27.9vw); gap: 4.1vw;
  align-items: start; justify-content: center;
}
.flyer-services h2 { font-size: 19.36px; line-height: var(--lh-heading); text-align: center; }
.flyer-services p { font-size: var(--fs-fine); line-height: var(--lh-body); margin-top: 25px; text-align: center; }
.flyer-services img { margin-top: 23px; width: 100%; aspect-ratio: 402 / 302; object-fit: cover; }

/* The photo is taken out of flow so it can bleed off the right edge, which
   means the section has to be told how tall that photo makes it. */
.flyer-about { position: relative; padding: 0 0 87px; min-height: calc(76.87vw + 87px); }
.flyer-about .inner { padding-right: 0; }
.flyer-about-photo { position: absolute; top: 0; right: 0; width: 49.65vw; }
.flyer-about-photo img { width: 100%; aspect-ratio: 715 / 1107; object-fit: cover; }
.flyer-about-words { position: relative; z-index: 1; width: 41.7vw; }
.flyer-about h1 { font-size: 89.9px; line-height: var(--lh-display); text-align: center; width: 18.5vw; margin-left: 11.6vw; padding-top: 237px; }
.flyer-about h1 + h1 { font-size: 188.5px; padding-top: 0; }
.flyer-about hr { border: 0; border-top: var(--rule); margin: 108px 0 0; }
.flyer-about p { margin-top: 40px; max-width: 601px; }
.flyer-about p + p { margin-top: 16px; }

.flyer-form { padding: 95px 0 96px; }
.flyer-form .inner { display: grid; grid-template-columns: 41.7vw 41.7vw; gap: 8.5vw; align-items: start; }
.flyer-photo { border-radius: 50% 50% 0 0 / 24% 24% 0 0; overflow: hidden; }
.flyer-photo img { width: 100%; aspect-ratio: 601 / 1015; object-fit: cover; }
.flyer-form h2 { font-size: var(--fs-h2); line-height: var(--lh-heading); margin-top: 40px;
  text-decoration: underline; text-underline-offset: 10px; text-decoration-thickness: 2px; }
.flyer-form .contact-copy { margin-top: 84px; max-width: 601px; }
.checkline { display: flex; align-items: center; gap: 8px; font-size: 14px;
  /* 21px of text becomes a 33px target, at no cost to the layout: the padding is
     handed straight back as margin, so consecutive rows still sit 10px apart.
     Not the full 44px, and that is deliberate. These rows are stacked 10px
     apart, so 44px targets would overlap and steal each other's taps, and
     buying the height instead would push the page down. 33px clears WCAG 2.5.8
     AA (24px) with room; Apple's 44 is guidance, not the standard. */
  padding: 6px 0; margin-top: 4px; margin-bottom: -6px; }
.checkline input { width: 15px; height: 15px; }
.checkgroup { display: flex; flex-wrap: wrap; gap: 22px; margin-top: 8px; }

/* ---------- Reel ----------
   Two SoundCloud players. The second is both narrower and shorter than the
   first on the live page, and they stack on a phone. Sizes measured there. */
.reel { padding: 95px 0 115px; }
.reel .inner { display: grid; grid-template-columns: 41.7vw 34vw; gap: 16.2vw; align-items: start; }
.reel iframe { width: 100%; height: auto; border: 0; display: block; }
.reel iframe:first-child { aspect-ratio: 601 / 403; }
.reel iframe + iframe { width: 88.6%; aspect-ratio: 434 / 291; }

/* ---------- Blank page (parity with the live empty pages) ---------- */
/* Short enough that the page never scrolls, which is what the live empty
   pages do: their height is simply the height of the window. */
.blank { min-height: 30vh; }

/* ==========================================================================
   The 768 band. The live site shrinks its whole type scale at exactly this
   width before growing it again above 900px. That is Squarespace's own
   behaviour, reproduced rather than smoothed out.
   ========================================================================== */
@media (min-width: 768px) and (max-width: 899.98px) {
  :root {
    --gutter: 4vw;
    --fs-h1: 57.472px; --fs-h2: 43.648px; --fs-h3: 39.04px;
    --fs-h4: 22.4512px; --fs-credit: 21.5296px; --fs-fine: 14.4px;
  }
  .site-header { padding: 6vw 4vw; }
  .hero { padding-top: 0; }
  .hero-block { height: 560px; }
  .intro { padding: 26px 0 96px; }
  .intro .inner { max-width: 68.6vw; }
  .split { padding: 60px 0 96px; }
  .split--text-left .inner  { grid-template-columns: 49.2vw 37.5vw; }
  .split--text-right .inner { grid-template-columns: 33.6vw 52.8vw; }
  .services .accordion { width: 41.4vw; }
  /* Restated here because .split--text-left comes later in this band and would
     otherwise take About's bespoke columns back off it. */
  .about .inner { grid-template-columns: 46.35vw 45.65vw; gap: 0; }
  .about { padding: 56px 0 29px; }
  /* The live site crops every photo again at this width. */
  .services .split-media img { aspect-ratio: 288 / 821; }
  .process .split-media img  { aspect-ratio: 258 / 1115; }
  .about .split-media img    { aspect-ratio: 318 / 1073; }
  .contact-photo { aspect-ratio: 318 / 860; margin-top: 0; }
  .flyer-photo img { aspect-ratio: 318 / 943; }
  .process-steps { column-gap: 71px; row-gap: 60px; }
  .credits { padding: 90px 0 113px; }
  .credit { flex: 0 0 323px; }
  .credit img { width: 323px; height: 324px; }
  .credit h2, .credit p { max-width: 242px; }
  .contact { padding-top: 26px; }   /* live 189px, less the 163px header at this width */
  .contact .inner { grid-template-columns: 45.3vw 41.4vw; gap: 5.2vw; }
  .contact h1 { max-width: 348px; }
  .contact-copy, .form { max-width: 288px; }
  .flyer-banner { padding: 30px 0 29px; }
  .flyer-banner img { width: 53.1vw; aspect-ratio: 408 / 251; }
  .flyer-services { padding: 90px 0 135px; }
  .flyer-services .inner { grid-template-columns: repeat(3, 25.5vw); gap: 7.8vw; }
  .flyer-services h2 { font-size: 17.84px; }
  .flyer-services p { margin-top: 13px; }
  .flyer-services img { margin-top: 11px; aspect-ratio: 196 / 148; }
  .flyer-about { padding-bottom: 47px; min-height: calc(116.3vw + 47px); }
  .flyer-about-photo { width: 49.35vw; }
  .flyer-about-photo img { aspect-ratio: 379 / 893; }
  .flyer-about-words { width: 41.4vw; }
  .flyer-about h1 { font-size: 46.4px; width: 17.9vw; margin-left: 11.6vw; padding-top: 157px; }
  .flyer-about h1 + h1 { font-size: 97.4px; }
  .flyer-about hr { margin-top: 120px; }
  .flyer-form { padding: 59px 0 60px; }
  .flyer-form .inner { grid-template-columns: 41.4vw 41.4vw; gap: 9.1vw; }
  .flyer-form h2 { margin-top: 27px; }
  .flyer-form .contact-copy { margin-top: 57px; }
  .reel { padding: 118px 0 0; }
  .reel .inner { grid-template-columns: 41.4vw 33.6vw; gap: 16.9vw; }
  .reel iframe:first-child { aspect-ratio: 318 / 213; }
  .reel iframe + iframe { width: 88.4%; aspect-ratio: 228 / 153; }
}

/* ==========================================================================
   Mobile. Below 768 the live site stops scaling type with the viewport and
   pins it, and the gutter widens to 6%.
   ========================================================================== */
@media (max-width: 767.98px) {
  :root {
    --gutter: 6vw;
    /* Below 768 the live site sizes its headings off viewport HEIGHT, not width:
       the same 390px-wide screen sets a heading at 48.4px when the window is
       900 tall and 46.4px when it is 844. Every heading fits 16px + k*1vh, so
       that is what is reproduced here. Unusual, and carried over deliberately.
       The hero is the one exception and stays width-driven. */
    --fs-hero: 17.05vw;
    --fs-h1:     calc(16px + 5.393vh);
    --fs-h2:     calc(16px + 3.607vh);
    --fs-h3:     calc(16px + 3.0vh);
    --fs-h4:     calc(16px + 0.839vh);
    --fs-credit: calc(16px + 0.72vh);
    --fs-fine: 14.92px;
    /* 2, 3 and 4. Live's divider carries a control offset of 0.0128 against
       this build's 0.4333, so at a phone's width the same path was drawn 34x
       steeper, and at 60px deep it reached far enough up to cut through the
       text and photos above it. A 20px band scales the whole curve down with
       it: about 9px of excursion, which is where live sits, and nothing left
       reaching up into the content. */
    --wave-h: 20px;
  }
  .logo img { width: 122px; }

  /* The burger replaces the inline nav, exactly as live does. */
  .header-right { display: none; }
  .burger { display: block; }
  .site-header { padding: var(--gutter); }
  .hero { padding: 0 var(--gutter) 15px; }
  .hero-block { height: 73.3vh; }

  /* 69px, not live's 21px, and this is the one place the build deliberately
     leaves live behind. At 21px the divider ran 8px under "they imagined." and
     crowded the descenders; live measures 10px there and reads just as tight,
     so matching it would have kept the defect Alec raised. 69px puts the gap
     at 56px, the same air the polaroid divider gets, so the two tight section
     breaks on the page now use one number instead of two. The ink sits 16.3px
     above the section's bottom edge, which is where the 69 comes from. */
  .intro { padding: 35px 0 69px; text-align: left; }
  .intro .inner { max-width: none; padding: 0 var(--gutter); }
  .intro h3 { margin-top: 46px; }

  /* Stacked, and the photo leads. The live site also re-crops each photo to a
     taller frame on mobile rather than letting the desktop crop scale down. */
  .split { padding: 60px 0 0; }
  .split .inner { grid-template-columns: 1fr; gap: 46px; }
  .split--text-left .inner, .split--text-right .inner { grid-template-columns: 1fr; }
  .split .split-media { order: -1; }
  .split .split-media img { width: 100%; height: auto; aspect-ratio: 343 / 409; object-fit: cover; }
  .process .split-media img { aspect-ratio: 343 / 514; }
  .process .split-media { order: 1; margin-top: 44px; }

  .services { padding-bottom: 107px; }
  .services .accordion { width: 100%; margin-top: 11px; }
  .services .section-title { width: auto; }
  .fine-print, .call-out, .services .btn-row { width: 100%; }

  /* The photo is the last thing in this section on mobile, so the section's
     bottom padding is the only thing standing between it and the divider.
     At 20px the crest came within 6.7px of the polaroid and read as touching
     it. Live's own gap, measured off the reference capture rather than guessed
     at (verify/reference/shots/home@390.png: polaroid ends row 4417, divider
     ink starts row 4473), is 56px. 72px of padding lands ours on the same 56. */
  .process { padding-bottom: 72px; }
  .process .section-title { margin-left: 0; width: auto; }
  .process-steps { grid-template-columns: 1fr; grid-template-rows: none;
    grid-auto-flow: row; row-gap: 11px; column-gap: 0; margin-top: 15px; }
  .process-steps p { margin-top: 30px; }

  /* 76px, down from 169px. This was a straight parity miss, not a judgement
     call: live leaves 88px between the last credit link and the divider ink
     and this build left 181px, so the section trailed off into an empty half
     screen. Measured off the rendered pages rather than the box model, since
     the credit links sit well above their own line box. */
  .credits { padding: 90px 0 76px; }
  .credits-rail { padding-top: 70px; }
  .credit { flex: 0 0 min(359px, 92vw); }
  .credit img { width: 100%; height: auto; aspect-ratio: 359 / 360; object-fit: cover; }
  .credit h2, .credit p { max-width: 269px; }

  .about { padding: 30px 0 151px; }
  .about .inner { grid-template-columns: 1fr; gap: 46px; }
  .about .split-media img { width: 100%; }
  .about .section-title { margin-left: 0; width: auto; text-align: center; }
  .about-copy { margin-left: 0; max-width: 263px; margin: 31px auto 0; }
  .about .btn-row { width: 100%; }
  .contact { padding-top: 35px; }   /* live 143px, less the 108px header at this width */
  .contact .inner { grid-template-columns: 1fr; gap: 0; }  /* the live photo butts straight up to the form */
  .contact h1, .contact-copy, .form { max-width: none; }
  .contact-copy { margin-top: 11px; }
  .contact-lead { margin-top: 32px; text-align: center; }
  .contact-photo { height: auto; margin-top: 0; aspect-ratio: 343 / 479; object-fit: cover; }
  .form-row { grid-template-columns: 1fr 1fr; gap: 10px; }
  /* One column, and the flyer's own proportions rather than the desktop ones. */
  .flyer-banner { padding: 29px 0 30px; }
  .flyer-banner img { width: 87.9vw; aspect-ratio: 343 / 199; }
  .flyer-services { padding: 90px 0 168px; }
  .flyer-services .inner { grid-template-columns: 1fr; gap: 51px; }
  .flyer-services h2 { font-size: 18.16px; text-align: left; }
  .flyer-services p { font-size: 14.92px; margin-top: 21px; text-align: left; }
  .flyer-services img { margin-top: 22px; aspect-ratio: 359 / 270; }
  .flyer-about { padding: 35px 0 127px; min-height: 0; }
  .flyer-about-photo { position: static; width: auto; margin: 0 var(--gutter); }
  .flyer-about-photo img { aspect-ratio: 343 / 269; }
  .flyer-about-words { width: 100%; }
  .flyer-about h1 { font-size: min(115.8px, 32vw); width: auto; margin-left: 0; padding-top: 11px; text-align: left; }
  .flyer-about h1 + h1 { font-size: min(242.1px, 62vw); }
  .flyer-about hr { margin-top: 24px; }
  .flyer-about p { margin-top: 24px; }
  .flyer-form { padding: 59px 0 445px; }  /* the live section really does run this far past its last field */
  .flyer-form .inner { grid-template-columns: 1fr; gap: 40px; }
  .reel { padding: 55px 0 56px; }
  .reel .inner { grid-template-columns: 1fr; gap: 11px; }
  .reel iframe:first-child, .reel iframe + iframe { width: 100%; aspect-ratio: 343 / 400; }
  .flyer-photo { width: 31.3vw; margin-left: auto; margin-right: 6vw; }
  .flyer-photo img { aspect-ratio: 122 / 164; }
  .flyer-form h2 { margin-top: 46px; }
  .flyer-form .contact-copy { margin-top: 11px; }

  /* 6. Live's footer order on a phone is the name, then the icons centred
     under it, then the address. This build had the icons last and hard right.
     `display: contents` lets the two children of .inner join the footer's own
     column so all three can be ordered without touching the markup. Live
     measures a 14px gap under the name and 85px above the address. */
  .site-footer { padding-top: 36px; display: flex; flex-direction: column; }
  .site-footer > .inner { display: contents; }
  .site-footer h2 { max-width: none; order: 1; padding: 0 var(--gutter); }
  .footer-social {
    order: 2; justify-content: center; gap: 12px;
    margin-top: 14px; padding: 0 var(--gutter);
  }
  /* 74 not 85, because the first paragraph brings its own 16px margin, and
     95px of tail because that is what live leaves under the last line. */
  .footer-lines { order: 3; margin-top: 74px; padding: 0 var(--gutter) 95px; }

  .call-out { margin-top: 48px; }
}

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