/* =====================================================================
   DESKTOP (from 820px). Loaded after site.css with media="(min-width:
   820px)", so nothing here reaches a phone.

   The same page as the phone, in the same materials (linen, sand, one
   terracotta, navy, Gambetta over Switzer), laid out for a wide screen
   and a pointer instead of a thumb:

     HERO        the film as a print on the table beside a poster-size
                 headline, the promise taped over its edge (ui.js,
                 desktop: print).
     THE CARDS   the studio, our goal and our process are three cards
                 taped down on a table, overlapping, each on its own
                 slight tilt, sliding in and settling with the scroll;
                 pointed at, they lean and catch the light (ui.js,
                 desktop: deal).
     SHOWCASE    "Mobile Responsiveness" at poster size beside the phone,
                 which stands still; the question slides up into place,
                 then up behind the rule above it as the answer slides in,
                 the page held still while each plays (ui.js, desktop:
                 show).
     WHY US      six chapters beside a sticky stage holding the 3D tile
                 of the one being read, umber for the two Pro features
                 (ui.js, desktop: features).
     GROWING     the caption at poster size, then the collage of the three
                 businesses edge to edge (ui.js, desktop: window).
     PRICING     the phone's umber, the one full screen of dark on the
                 page: the question, then the price; then the plans back on
                 the linen, cartwheeled into a pile, squared up, and slid
                 out side by side, perfectly straight.
     CTA         the terracotta tab slides out of the left wall with the
                 scroll; the question and its answer side by side.
     CONTACT     the invitation on the left, held while the form on the
                 right is filled in.

   Radii: panels and cards var(--r-xl), buttons full pill, as everywhere
   else on the site. ===================================================== */

:root {
  /* The hero and the header run wider than the sections below them. */
  --edge: max(var(--gutter), calc((100% - 84rem) / 2 + var(--gutter)));
}

/* ---------------------------------------------------------------- Header */
.nav__in { max-width: 84rem; }
/* Over the umber price screen or the orange tab (ui.js, nav: is-over-dark), the
   links go light and the button turns over to white. */
.nav__links a { transition: color .35s var(--ease), text-shadow .35s var(--ease); }
.nav.is-over-dark .nav__links a { color: rgba(255, 255, 255, .86); text-shadow: none; }
.nav.is-over-dark .nav__links a:hover { color: var(--paper); }
.nav.is-over-dark .nav__cta { background: var(--paper); color: var(--navy); }

/* ------------------------------------------------------------------ Hero
   The film is a print on the table, and the print changes shape with the
   shot. It opens as the footage itself, a tall portrait of the notebook;
   as the camera pulls back through the studio (the middle of the film) it
   opens out, wider and shorter, until it settles as a square on the
   designer at the desk, cropped from the top of the frame. hero.js (wide)
   drives one number, --m, from 0 to 1 across that move; everything about
   the print's shape is worked out from it here.

   The square grows leftwards, in under the headline, and the headline runs
   on over the picture: the part of it lying on the print is drawn again in
   linen, clipped to the print (.hero__h1--over), so the line reads unbroken
   across the edge.

   The sizes, all worked out from the screen:
     --H   the tallest the print can be: the screen less the header and
           a margin under it
     --S   the square it ends as: a little under --H, and never more than
           55% of the row, so the copy keeps the rest
     --w0  its width as a portrait, the footage's own 716:1284
     --X   how far left of the edge the square comes to rest. The portrait
           stands on the right edge; opening out, the print also drifts
           left by this much, which is what carries it in under the
           headline rather than stopping a hand's width short of it. */
.hero {
  --m: 0;
  --E: max(var(--gutter), calc((100vw - 84rem) / 2 + var(--gutter)));
  --top: calc(var(--nav-h) + .25rem);
  --foot: 2.5rem;
  --H: calc(100svh - var(--top) - var(--foot));
  --S: min(calc(var(--H) * .92), calc((100vw - 2 * var(--E)) * .55));
  --w0: calc(var(--H) * .5576);
  --X: calc(var(--S) * .14);
  --pw: calc(var(--w0) + (var(--S) - var(--w0)) * var(--m));
  --ph: calc(var(--H) + (var(--S) - var(--H)) * var(--m));
  /* The tape on the opening frame is sized off the print's width. */
  --plate-w: var(--w0);
  align-items: center;
  min-height: 100svh;
  padding: var(--top) 0 var(--foot);
}
.hero .hero__in { max-width: none; padding-inline: var(--edge); }
/* The column is as wide as the hero: the headline is allowed to run on
   over the print. Everything under it keeps clear of the square. */
.hero .hero__copy { max-width: none; }
.hero .hero__copy > :not(.hero__title) {
  max-width: min(31rem, calc(100vw - 2 * var(--E) - var(--S) - var(--X) - 3rem));
}
.hero .hero__eyebrow { display: none; }

.hero__title { position: relative; z-index: 3; }
.hero .hero__h1 {
  margin-bottom: 2.4rem;
  font-size: clamp(3.4rem, 8.6vw, 8.4rem);
  font-weight: 400;
  line-height: .97;
  letter-spacing: -.034em;
  white-space: nowrap;
}
.hero .hero__h1 .line { padding-bottom: .1em; margin-bottom: -.1em; }
/* The second copy: the same type exactly on top of the first, in linen,
   and clipped by hero.js to wherever the print is; the first has that same
   shape cut out of it (hero.js, wide: over), so over the picture there is
   only the linen and no dark fringe round it. With the film not running
   there is nothing to clip to, and it stays out of the way. */
.hero .hero__h1--over {
  display: block;
  position: absolute;
  inset: 0 0 auto 0;
  margin: 0;
  font-family: var(--display);         /* a <p>: no heading face of its own */
  color: var(--linen);
  /* The top left of the last frame is the lamp-lit wall, pale enough to
     lose linen letters; a soft shadow under them, the print's own warm
     dark, holds them on it without reading as an outline. */
  text-shadow: 0 2px 28px rgba(40, 24, 8, .45), 0 1px 3px rgba(40, 24, 8, .25);
  clip-path: inset(0 0 100% 0);
  pointer-events: none;
  user-select: none;
}
.hero .hero__h1--over em { color: inherit; }

.hero .hero__lead { margin-bottom: 2.2rem; font-size: clamp(1.1rem, 1.25vw, 1.25rem); }
/* The service areas: label, regions, suburbs, one over the other under a
   rule, in the same column as the paragraph. */
.hero .hero__areas {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  row-gap: .3rem;
  margin-top: 2.6rem;
  padding-top: 1.2rem;
}
.hero .hero__areas-h { margin-bottom: .3rem !important; }
.hero .hero__areas-s { margin-top: 0 !important; font-size: .92rem; }

.hero__media {
  --shade: 1;
  z-index: 1;
  top: calc(var(--top) + (var(--H) - var(--ph)) / 2);
  bottom: auto;
  left: auto;
  right: calc(var(--edge) + var(--X) * var(--m));
  width: var(--pw);
  height: var(--ph);
}
/* The print's shadow on the table, on its own layer so the uncovering
   (a clip on the picture) never cuts it off. */
.hero__media::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: var(--r-xl);
  box-shadow:
    0 2px 4px rgba(40, 24, 8, .08),
    0 24px 40px -26px rgba(40, 24, 8, .38),
    0 80px 120px -60px rgba(40, 24, 8, .55);
  opacity: var(--shade);
}
.hero__media-in {
  border-radius: var(--r-xl);
  background: var(--sand);
  isolation: isolate;
}
.hero__media-in::before,
.hero__media-in::after { display: none; }
.hero__photo-canvas,
.hero__photo-img { object-position: 50% 30%; }
/* The promise, on tape, as on the phone: level, centred across the print
   and just under the pen's nib (ui.js, desktop: print, sets the top from
   the opening frame). The strip runs most of the print's width, the way the
   phone's runs gutter to gutter: every measure on it is in em, and with the
   desktop's letterspacing its width is the font size times ~24.1 (measured),
   which leaves 2.5rem of print either side. The !importants beat the inline left/top
   hero.js leaves behind if the window was a phone's width first. */
.hero__tagline {
  display: flex;
  justify-content: center;
  position: absolute;
  z-index: 3;
  left: 0 !important;
  right: 0;
  top: 64%;
  bottom: auto;
  pointer-events: none;
}
.hero__tagline .tape__strip {
  font-size: calc((var(--plate-w) - 5rem) / 24.2);
  white-space: nowrap;
}


/* ------------------------------------------------------------- The cards
   Three cards on a table: sand, terracotta, sand, each on its own slight
   tilt and taped down. As on the phone, each cartwheels in from its side
   and lands overlapping the one before it, later cards on top (ui.js,
   desktop: cards), then holds still. */
.stack { overflow-x: clip; }

.stack > .slab {
  display: block;
  position: relative;
  max-width: calc(var(--maxw) + 2 * var(--gutter));
  margin: 0 auto;
  padding: 0 var(--gutter);
  background: none;
}
.stack > .slab > .wrap { max-width: none; padding: 0; }
.stack > .studio { padding-top: 6rem; z-index: 1; }
/* Each card overlaps only the bottom padding of the one before, so no
   card's words go under the next one. */
.stack > .slab--local { margin-top: -2.5rem; z-index: 2; }
.stack > .slab--process { margin-top: -2.5rem; z-index: 3; padding-bottom: 6rem; }

.stack .slab__card {
  position: relative;
  box-sizing: border-box;
  display: block;
  padding: clamp(2.8rem, 4vw, 4rem) clamp(2.6rem, 4vw, 4rem);
  border-radius: var(--r-xl);
  transform: rotate(var(--tilt, 0deg));
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .6),
    0 2px 6px rgba(40, 24, 8, .08),
    0 44px 70px -40px rgba(40, 24, 8, .5);
  /* Its own GPU layer for good, rastered once at rest size: the roll
     (ui.js) only moves an already-painted picture of it, and its dip in
     size mid-roll never makes the browser repaint it at a new scale. */
  will-change: transform;
}
/* The tape holding it down: a strip of translucent masking tape across
   the card's edge, cut square. */
.stack .slab__card::before {
  content: "";
  position: absolute;
  z-index: 4;
  top: -1.05rem;
  left: var(--tape-x, 42%);
  width: 8.5rem;
  height: 2.15rem;
  background:
    linear-gradient(180deg, rgba(255, 255, 255, .34), rgba(255, 255, 255, 0) 55%),
    repeating-linear-gradient(90deg, rgba(120, 96, 60, .05) 0 1px, rgba(0, 0, 0, 0) 1px 5px),
    rgba(221, 210, 184, .78);
  border-radius: 1.5px;
  box-shadow: 0 1px 2px rgba(40, 24, 8, .12);
  transform: rotate(var(--tape-r, -4deg));
  pointer-events: none;
}
/* Sand, terracotta, sand; left, right, then wide across the middle. */
.slab--studio .slab__card {
  --tilt: -1.6deg;
  --tape-x: 38%;
  --tape-r: -5deg;
  width: min(100%, 46rem);
  margin: 0;
  background: var(--grey);
}
.slab--local .slab__card {
  --tilt: 2deg;
  --tape-x: calc(100% - 6.5rem);
  --tape-r: 36deg;
  width: min(100%, 38rem);
  margin-left: auto;
  color: var(--paper);
  /* From the accent itself at its lightest (white on #c2521f is 4.6:1),
     not the phone's lighter #d8672e (3.5:1), which the label sits on. */
  background: linear-gradient(150deg, #c2521f 0%, #b64b1c 50%, #a3421a 100%);
  box-shadow:
    inset 0 1px 0 rgba(255, 214, 186, .45),
    0 2px 6px rgba(110, 36, 8, .16),
    0 44px 70px -40px rgba(110, 36, 8, .6);
}
.slab--local .slab__card::before { top: -.6rem; }
.slab--process .slab__card {
  --tilt: -.8deg;
  --tape-x: 12%;
  --tape-r: -2deg;
  width: min(100%, 60rem);
  margin-left: 5%;
  background: var(--grey);
}

.stack .slab__card .eyebrow { margin: 0 0 1.4rem; }
.slab--local .slab__card .eyebrow { color: var(--paper); }
.stack .slab__card h2 {
  margin: 0;
  font-family: var(--display);
  font-size: clamp(2.8rem, 4.3vw, 4.3rem);
  font-weight: 400;
  line-height: .98;
  letter-spacing: -.032em;
  color: inherit;
}
.slab--local .slab__h .dot { color: var(--paper); }
.stack .slab__card .panel__body { margin-top: 1.7rem; display: grid; gap: .8rem; max-width: 34rem; }
.stack .slab__card .panel__body p,
.stack .slab__lead {
  margin: 0;
  font-size: 1.1rem;
  line-height: 1.62;
  color: var(--ink-2);
}
.stack .slab__lead { margin-top: 1.2rem; max-width: 31rem; color: rgba(255, 248, 242, .95); }
.stack .slab__lead + .slab__lead { margin-top: .8rem; }

/* The process's four steps, two by two, each beside its numeral: the
   numerals in the display italic, large, as the steps' own index. */
.slab__steps {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 2rem 3.5rem;
  margin: 2.6rem 0 0;
  padding: 0;
  list-style: none;
  counter-reset: step;
}
.slab__steps li {
  display: grid;
  grid-template-columns: 3.6rem minmax(0, 1fr);
  column-gap: 1rem;
  align-items: start;
  padding-top: 1.3rem;
  font-size: 1.04rem;
  line-height: 1.58;
  color: var(--ink-2);
  counter-increment: step;
  border-top: 1px solid var(--hair-2);
}
.slab__steps li::before {
  content: "0" counter(step);
  font-family: var(--display);
  font-size: 2.7rem;
  font-style: italic;
  font-weight: 300;
  line-height: .86;
  letter-spacing: -.03em;
  color: var(--accent);
}

/* The cards' shows (ui.js, cardShows): under the words. */
.card__fx {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border-radius: inherit;
  pointer-events: none;
}
.slab__card.has-fx > :not(.card__fx) { position: relative; }

/* -------------------------------------------------------------- Showcase
   A sticky stage: "Mobile Responsiveness" at poster size with the phone
   beside it, standing still and playing. Under the words the question is
   read in as the page moves, a word at a time from faint to full, then
   "8 in every 10" is counted out on ten phones; the question goes up and
   away and the answer is read in in its place (ui.js, desktop: show). */
.showcase {
  --phone-w: clamp(16rem, 24vw, 22rem);
  display: block;
  position: relative;
  z-index: 0;
  height: 260svh;
  /* The stage's words sit in the middle of a full screen, so its top fifth
     is empty: tucked up under the process card's foot, so the page runs
     on from the cards to the words without a screen of linen between. */
  margin-top: -18svh;
}
.showcase__stage {
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100svh;
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--phone-w);
  grid-template-rows: auto auto auto;
  grid-template-areas:
    "back  phone"
    "front phone"
    "copy  phone";
  align-content: center;
  column-gap: clamp(3rem, 7vw, 7.5rem);
  max-width: calc(var(--maxw) + 2 * var(--gutter));
  margin: 0 auto;
  padding: var(--nav-h) var(--gutter) 0;
}
.showcase__word {
  position: static;
  margin: 0;
  font-family: var(--display);
  font-size: clamp(3.6rem, 6.9vw, 7rem);
  line-height: .92;
  letter-spacing: -.04em;
  color: var(--ink);
  white-space: nowrap;
  transform: none;
}
/* Under the phone (z-index 1): the words come out from behind it on the
   way in (ui.js, desktop: show). */
.showcase__word { position: relative; z-index: 0; }
.showcase__word--back { grid-area: back; font-weight: 300; }
.showcase__word--front {
  grid-area: front;
  /* The italic's descenders need room under the line (the y). */
  padding-bottom: .12em;
  font-weight: 400;
}
.showcase__word--front em { font-style: italic; color: var(--accent); }

/* The phone stands still: it plays, and that is all it does. */
.showcase__phone {
  grid-area: phone;
  position: relative;
  align-self: center;
  justify-self: center;
  width: var(--phone-w);
  aspect-ratio: 368 / 496;
  z-index: 1;
}
.showcase__float { position: absolute; inset: 0; animation: none; }
.showcase__phone::after {
  content: "";
  position: absolute;
  left: 16%;
  right: 16%;
  top: 102%;
  height: 7%;
  border-radius: 50%;
  background: radial-gradient(closest-side, rgba(20, 17, 13, .26), rgba(20, 17, 13, 0));
  filter: blur(5px);
  z-index: -1;
}
.showcase__canvas { position: absolute; inset: 0; width: 100%; height: 100%; }
.showcase__video {
  position: absolute;
  left: 0;
  top: 0;
  width: 2px;
  height: 2px;
  opacity: 0;
  pointer-events: none;
}
/* No WebGL: the video's picture half, multiplied onto the linen. */
.showcase.is-plain .showcase__canvas { display: none; }
.showcase.is-plain .showcase__float { overflow: hidden; }
.showcase.is-plain .showcase__video {
  width: 100%;
  height: 200%;
  opacity: 1;
  mix-blend-mode: multiply;
}

/* The rule along its top is a wall: the copy slides up behind it and is
   gone, and the next copy slides up into its place from under the box's
   floor (ui.js, desktop: show). Both edges clip; the box is as tall as the
   taller of the two says (ui.js sets --say-h). */
.showcase__copy {
  grid-area: copy;
  position: relative;
  height: calc(var(--say-h, 17rem) + 1.6rem + 1rem);
  max-width: 38rem;
  margin-top: 2.8rem;
  padding-top: 1.6rem;
  overflow: hidden;
  text-align: left;
}
/* Its rule, drawn in as the stage arrives (ui.js, --rule). */
.showcase__copy::before {
  content: "";
  position: absolute;
  z-index: 1;
  top: 0;
  left: 0;
  right: 0;
  height: 1px;
  background: var(--hair-2);
  transform: scaleX(var(--rule, 1));
  transform-origin: left;
}
.showcase__say { position: absolute; top: 1.6rem; left: 0; right: 0; }
.showcase__q em { font-style: italic; color: var(--accent); }
.showcase__q {
  max-width: 24ch;
  margin: 0;
  font-family: var(--display);
  font-size: clamp(1.7rem, 2.35vw, 2.35rem);
  font-weight: 400;
  line-height: 1.16;
  letter-spacing: -.018em;
  color: var(--ink);
  text-wrap: balance;
}
/* The aside under the question, in the italic. */
.showcase__say .showcase__q + .showcase__q {
  max-width: none;
  margin-top: .9rem;
  font-size: clamp(1.15rem, 1.4vw, 1.4rem);
  font-style: italic;
  color: var(--ink-3);
}
/* The answer's second part is a paragraph, set as one. */
.showcase__say--next .showcase__q + .showcase__q {
  max-width: 34rem;
  margin-top: 1.1rem;
  font-family: var(--sans);
  font-size: clamp(1.08rem, 1.3vw, 1.28rem);
  font-style: normal;
  line-height: 1.58;
  letter-spacing: 0;
  color: var(--ink-2);
  text-wrap: pretty;
}
/* Eight people, lit in turn (--on, 0 to 1), and two laptops (ui.js,
   TALLY). */
.showcase__ten { display: flex; align-items: flex-end; gap: .6rem; margin-top: 1.4rem; }
.showcase__ten i { --on: 0; display: block; }
.showcase__ten i.is-body { width: 1.05rem; height: 1.8rem; }
.showcase__ten i.is-bust { width: 1.45rem; height: 1.55rem; }
.showcase__ten i.is-laptop { width: 2.1rem; height: 1.35rem; margin-left: .15rem; }
.showcase__ten svg { display: block; width: 100%; height: 100%; overflow: visible; }
.showcase__ten .t-fill {
  fill: var(--accent);
  fill-opacity: var(--on);
  stroke: color-mix(in srgb, var(--accent) calc(var(--on) * 100%), var(--ink-4));
  stroke-width: 1.3;
  stroke-linejoin: round;
}
.showcase__ten .t-lid { fill: none; stroke: var(--ink-4); stroke-width: 1.3; }
.showcase__ten .t-screen { fill: rgba(20, 17, 13, .07); }
.showcase__ten .t-deck { fill: var(--ink-4); }
.showcase__ten .t-notch { stroke: var(--linen); stroke-width: .9; stroke-linecap: round; }

/* --------------------------------------------------------------- Why us
   Six chapters beside a sticky stage. The stage holds the 3D tile of the
   feature being read, and turns umber, with its Pro mark, for the two Pro
   features; each chapter carries its numeral in the display italic, its
   heading, and its words. The one being read is full strength and the
   others stand back (ui.js, desktop: features). */
/* --feat-h: the stage's height. --feat-top: where the stage and the
   heading stick, which puts the stage in the middle of the screen (of the
   part under the header). A long run of linen after the last chapter, so
   the section goes off the screen before the next arrives. */
.features {
  --feat-h: min(calc(100svh - var(--nav-h) - 2.5rem), 44rem);
  --feat-top: max(calc(var(--nav-h) + .5rem), calc((100svh - var(--feat-h) + var(--nav-h)) / 2));
  padding-block: 8.5rem 20rem;
  /* The linen above the sticky heading (.feat-main > .wrap::before) is
     tall enough to reach the top of the screen; before the heading sticks
     it reached up out of the section and over the foot of the photograph
     above (the window). clip, not hidden: no scroll container, so the
     sticky columns inside still stick. */
  overflow: clip;
}
.features > .wrap.sec--centre { text-align: left; }
/* The heading is label enough here. */
.features > .wrap > .eyebrow { display: none; }
.features .display--2 {
  font-size: clamp(3.4rem, 5.6vw, 5.6rem);
  font-weight: 400;
  line-height: .98;
  letter-spacing: -.034em;
}
.features .display--2 .line { padding-bottom: .1em; margin-bottom: -.1em; }
.features .deck-ui { display: none; }
.features .deck-wrap {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.08fr);
  column-gap: clamp(3rem, 6vw, 7rem);
  align-items: start;
  max-width: calc(var(--maxw) + 2 * var(--gutter));
  margin: 4rem auto 0;
  padding: 0 var(--gutter);
}

/* Two columns that both stay put while the chapters pass (ui.js, desktop:
   features). On the left the stage, sticky. On the right the heading,
   sticky at the same height, so its top lines up with the stage's; the
   chapters scroll up under it, and the one that has just reached the
   heading's foot is the one being read. */
.feat-side {
  position: sticky;
  top: var(--feat-top);
  height: var(--feat-h);
}
.feat-side .feat-stage { position: relative; top: auto; height: 100%; max-height: none; }
.feat-main { min-width: 0; }
.feat-main > .wrap {
  position: sticky;
  z-index: 2;
  top: var(--feat-top);
  max-width: none;
  margin: 0;
  padding: 0 0 1.8rem;
  text-align: left;
  background: var(--linen);
}
/* Above the heading, up to the top of the screen, linen too: a chapter
   that has gone up under the heading does not show again over it. */
.feat-main > .wrap::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 100%;
  height: calc(var(--feat-top) + 1rem);
  background: var(--linen);
  pointer-events: none;
}
/* The chapters go under the heading's foot softly rather than being cut
   off at a hard line. */
.feat-main > .wrap::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 100%;
  height: 2.5rem;
  background: linear-gradient(var(--linen), rgba(246, 243, 238, 0));
  pointer-events: none;
}
.feat-main .eyebrow { display: none; }
.feat-main .display--2 { margin: 0; font-size: clamp(2.8rem, 4.4vw, 4.6rem); }
/* Room after the last chapter for the no-script layout. With the script
   (ui.js, "THE END") this is replaced by measured margins, so the heading
   and the stage let go exactly as the last chapter reaches the reading
   line, and the section moves on with it in place. */
.feat-main #deckFeatures.deck--chapters { padding-top: 4rem; padding-bottom: 38svh; }
.features:has(.feat-side) .deck-wrap { margin-top: 0; }
.feat-stage {
  display: grid;
  place-items: center;
  position: sticky;
  top: calc(var(--nav-h) + 1rem);
  height: calc(100svh - var(--nav-h) - 3rem);
  max-height: 44rem;
  overflow: hidden;
  isolation: isolate;
  border-radius: var(--r-xl);
  /* Black for every feature. */
  background: radial-gradient(118% 88% at 50% 26%, #1d1d1d 0%, var(--umber) 50%, var(--umber-deep) 100%);
  box-shadow: 0 30px 60px -40px rgba(20, 12, 4, .55);
}
/* The umber, for the Pro features, faded in over the sand: the phone's
   Pro page (site.css, .wheel__page--umber) and the price screen's dark,
   lit from a little above the middle. */
.feat-stage::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: radial-gradient(118% 88% at 50% 26%, #1d1d1d 0%, var(--umber) 50%, var(--umber-deep) 100%);
  opacity: 0;
  transition: opacity .9s var(--ease);
}
.feat-stage::before { display: none; }
/* The tile's shadow on the floor of the stage. */
.feat-stage::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 71%;
  width: min(44%, 16rem);
  height: 2.4rem;
  translate: -50% 0;
  border-radius: 50%;
  background: radial-gradient(closest-side, rgba(20, 12, 4, .34), rgba(20, 12, 4, 0));
  filter: blur(6px);
  z-index: -1;
}
.feat-stage__turn {
  position: relative;
  width: min(58%, 21rem);
  aspect-ratio: 1;
  margin-top: -2.5rem;
}
.feat-stage__tiles {
  position: absolute;
  inset: 0;
  perspective: 820px;
}
/* A soft light behind the tile: white on the sand, a warm lamp on the
   umber. */
.feat-stage__turn::before {
  content: "";
  position: absolute;
  inset: -45%;
  border-radius: 50%;
  background: radial-gradient(closest-side, rgba(255, 255, 255, .75), rgba(255, 255, 255, 0));
  transition: opacity .9s var(--ease);
}
.feat-stage__turn::after {
  content: "";
  position: absolute;
  inset: -45%;
  border-radius: 50%;
  background: radial-gradient(closest-side, rgba(226, 121, 63, .16), rgba(226, 121, 63, 0));
  opacity: 0;
  transition: opacity .9s var(--ease);
}
.feat-stage.is-pro .feat-stage__turn::before { opacity: 0; }
.feat-stage.is-pro .feat-stage__turn::after { opacity: 1; }
.feat-stage__tiles img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  filter: drop-shadow(0 26px 30px rgba(20, 12, 4, .32));
}
.feat-stage__tiles img + img { opacity: 0; }
.feat-stage__pro {
  position: absolute;
  top: 1.5rem;
  right: 1.5rem;
  padding: .5rem .85rem .45rem;
  border-radius: 999px;
  font-family: var(--mono);
  font-size: max(12px, .75rem);
  letter-spacing: .14em;
  text-transform: uppercase;
  background: var(--accent-lit);
  color: var(--umber-deep);
  opacity: 0;
  transform: translateY(-8px);
  transition: opacity .5s var(--ease), transform .6s var(--glide);
}
/* The Pro mark is the ribbon now (ui.js, proRibbon). */
.feat-stage__pro { display: none; }
.feat-stage__count {
  position: absolute;
  left: 1.7rem;
  bottom: 1.5rem;
  display: flex;
  align-items: center;
  gap: .9rem;
  margin: 0;
  font-family: var(--mono);
  font-size: max(12px, .8rem);
  letter-spacing: .06em;
  color: var(--ink-3);
  transition: color .6s var(--ease);
}
.feat-stage__count b { font-weight: 400; color: var(--ink); transition: color .6s var(--ease); }
.feat-stage__count::after {
  content: "";
  width: 6rem;
  height: 2px;
  border-radius: 2px;
  background: linear-gradient(to right,
              var(--accent) 0 calc((var(--at, 0) + 1) * 100% / 7),
              rgba(20, 17, 13, .14) 0);
}
/* The bar fills from one feature to the next rather than jumping: --at is
   registered as a number, so it can be transitioned. */
@property --at { syntax: "<number>"; inherits: true; initial-value: 0; }
.feat-stage { transition: --at .8s var(--glide); }
.feat-stage .feat-stage__count { color: var(--on-navy-2); }
.feat-stage .feat-stage__count b { color: var(--paper); }
.feat-stage .feat-stage__count::after {
  background: linear-gradient(to right,
              var(--accent-lit) 0 calc((var(--at, 0) + 1) * 100% / 7),
              rgba(255, 255, 255, .2) 0);
}

/* ------------------------------------------------- Why us: the demos
   Each feature at work, in a small browser or phone (ui.js,
   featureDemos). Every measure is in em off one font size, taken from the
   deck's own size (container units), so a demo scales as one drawing with
   the stage. The pages inside are for a made-up local bakery, so the
   demos read as a client's site rather than as ours. */
.feat-stage.has-demos .feat-stage__turn,
.feat-stage.has-demos::after { display: none; }
/* The feature's name, typed out in the stage's top left as it comes on
   (ui.js, desktop: features), at the size of the section's heading. On a
   Pro feature its lines run short of the ribbon: a float in the top right
   corner cut on the ribbon's inner edge (--rib, ui.js, proRibbon). */
.feat-stage__title {
  position: absolute;
  z-index: 2;
  top: 1.45rem;
  left: 1.7rem;
  right: 1.7rem;
  margin: 0;
  font-family: var(--display);
  font-size: clamp(2.8rem, 4.4vw, 4.6rem);
  font-weight: 400;
  line-height: .98;
  letter-spacing: -.034em;
  color: var(--paper);
}
.feat-stage.is-pro .feat-stage__title::before {
  content: "";
  float: right;
  width: calc(var(--rib, 8rem) - 2rem);
  height: calc(var(--rib, 8rem) - 2rem);
  shape-outside: polygon(0 0, 100% 0, 100% 100%);
}
/* The ribbon's canvas: over the stage's top right corner (ui.js,
   proRibbon). */
.feat-ribbon {
  position: absolute;
  z-index: 3;
  top: 0;
  right: 0;
  pointer-events: none;
}
.demo-deck {
  position: absolute;
  inset: calc(var(--title-h, 3.4rem) + 2.6rem) 1.8rem 4.3rem;
  transition: top .5s var(--ease);
  container-type: size;
}
/* The light the device sits in: white on the sand, a warm lamp on the
   umber. */
.demo-deck::before {
  content: "";
  position: absolute;
  inset: -12% -6%;
  background: radial-gradient(50% 46% at 50% 50%, rgba(255, 255, 255, .72), rgba(255, 255, 255, 0));
  transition: opacity .9s var(--ease);
}
.feat-stage .demo-deck::before { background: radial-gradient(50% 46% at 50% 50%, rgba(226, 121, 63, .16), rgba(226, 121, 63, 0)); }
.demo {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-family: var(--sans);
  font-size: min(3.05cqw, 3.65cqh);
  line-height: 1.3;
  color: var(--ink);
  visibility: hidden;
}
.demo p { margin: 0; }
/* Nothing in a demo that is not on show keeps animating. */
.demo:not(.is-on) * { animation-play-state: paused !important; }
/* Skeleton text: bars of ink at a tenth. */
.d1-links i, .d1-p i, .d1-card i, .d2-d i, .d5-links i, .d5-p i {
  display: block;
  height: .3em;
  border-radius: .2em;
  background: rgba(20, 17, 13, .12);
}

/* The devices. */
.dm-browser {
  position: relative;
  width: 30em;
  overflow: hidden;
  border-radius: 1em;
  background: var(--paper);
  box-shadow:
    0 0 0 1px rgba(20, 17, 13, .06),
    0 .15em .4em rgba(40, 24, 8, .08),
    0 1.8em 3.2em -1.4em rgba(40, 24, 8, .45);
}
.feat-stage .dm-browser {
  box-shadow: 0 0 0 1px rgba(255, 255, 255, .08), 0 1.8em 3.4em -1.2em rgba(0, 0, 0, .7);
}
.dm-bar {
  display: flex;
  align-items: center;
  gap: .36em;
  height: 2.1em;
  padding: 0 .9em;
  background: var(--linen);
  border-bottom: 1px solid var(--hair);
}
.dm-bar > i { width: .55em; height: .55em; border-radius: 50%; background: rgba(20, 17, 13, .14); }
.dm-url {
  display: flex;
  align-items: center;
  flex: 1;
  height: 2.2em;
  margin-left: 1.3em;
  padding: 0 1.4em;
  border-radius: 2em;
  background: rgba(20, 17, 13, .05);
  font-size: .6em;
  color: var(--ink-3);
  white-space: nowrap;
}
.dm-view { position: relative; aspect-ratio: 300 / 206; overflow: hidden; background: var(--paper); }
.dm-phone {
  position: relative;
  box-sizing: border-box;
  width: 13.5em;
  height: 27.5em;
  padding: .5em;
  border-radius: 2.3em;
  background: #1a1713;
  box-shadow:
    inset 0 0 0 1px rgba(255, 255, 255, .1),
    0 .2em .5em rgba(0, 0, 0, .2),
    0 2em 3.4em -1.2em rgba(0, 0, 0, .55);
  font-size: 1em;
}
.dm-screen {
  position: relative;
  box-sizing: border-box;
  height: 100%;
  overflow: hidden;
  padding: 2.7em 1.15em 1.2em;
  border-radius: 1.85em;
  background: var(--linen);
}
.dm-notch {
  position: absolute;
  z-index: 2;
  top: 1em;
  left: 50%;
  width: 3.6em;
  height: 1em;
  translate: -50% 0;
  border-radius: 1em;
  background: #1a1713;
}
.dm-logo { flex: none; width: .8em; height: .8em; border-radius: .2em; background: var(--accent); }
.dm-brand { font-family: var(--display); font-size: .7em; white-space: nowrap; }
/* A photograph's worth of warm light, for the made-up bakery. */
.d1-img, .d5-img {
  background:
    radial-gradient(55% 60% at 32% 38%, rgba(255, 236, 208, .95), rgba(255, 236, 208, 0) 70%),
    linear-gradient(155deg, #e8c39a 0%, #d2884f 52%, #a3421a 100%);
}

/* 01 Design: the page, positioned to sit exactly under its sketch (one
   SVG unit is a tenth of an em; a box with its own font size has its
   offsets divided by it). */
.d1-site { position: absolute; inset: 0; }
.d1-site > * { position: absolute; }
.d1-logo { left: 1.4em; top: 1.1em; width: .9em; height: .9em; border-radius: .22em; background: var(--accent); }
.d1-brand { left: 3.5em; top: 1.15em; font-family: var(--display); font-size: .8em; line-height: 1; }
.d1-links { right: 2em; top: 1.4em; display: flex; gap: .8em; }
.d1-rule { left: 1.4em; right: 1.4em; top: 3em; height: 1px; background: var(--hair-2); }
.d1-h { left: .933em; top: 2.8em; font-family: var(--display); font-size: 1.5em; line-height: 1.05; letter-spacing: -.02em; }
.d1-p { left: 1.4em; top: 8.45em; display: flex; flex-direction: column; gap: .6em; }
.d1-btn { left: 1.4em; top: 10.6em; width: 5em; height: 1.4em; display: grid; place-items: center; border-radius: 1em; background: var(--accent); color: #fff; }
.d1-btn b, .d5-btn b { font-size: .5em; font-weight: 600; letter-spacing: .01em; }
.d1-img { left: 16em; top: 4.2em; width: 12.6em; height: 8.6em; border-radius: .6em; }
.d1-card {
  top: 14.2em;
  box-sizing: border-box;
  width: 8.4em;
  height: 4.8em;
  display: flex;
  flex-direction: column;
  gap: .45em;
  padding: .7em;
  border-radius: .45em;
  background: var(--sand);
}
.d1-card > i:first-child { width: .9em; height: .9em; border-radius: 50%; background: rgba(194, 82, 31, .35); }
.d1-sketch {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  fill: none;
  stroke: #8f8577;
  stroke-width: 1.1;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 1;
}
.d1-edge {
  position: absolute;
  top: 0;
  bottom: 0;
  left: -1px;
  width: 2px;
  background: var(--accent);
  box-shadow: 0 0 .8em .15em rgba(226, 121, 63, .55);
}

/* 02 Search & AI */
.d2-search {
  position: absolute;
  left: 1.4em;
  right: 1.4em;
  top: 1.1em;
  height: 2.2em;
  display: flex;
  align-items: center;
  gap: .5em;
  padding: 0 .9em;
  border-radius: 2em;
  box-shadow: inset 0 0 0 1px var(--hair-2), 0 .3em .7em -.4em rgba(40, 24, 8, .25);
}
.d2-search svg { width: .95em; height: .95em; fill: none; stroke: var(--ink-3); stroke-width: 2.2; stroke-linecap: round; }
.d2-q { font-size: .72em; white-space: pre; }
.d2-caret { width: 1px; height: 1em; margin-left: -.35em; background: var(--ink); animation: dm-blink 1s steps(1) infinite; }
@keyframes dm-blink { 50% { opacity: 0; } }
.d2-rows { position: absolute; left: 1.4em; right: 1.4em; top: 4.3em; bottom: 0; }
.d2-row {
  position: absolute;
  left: 0;
  right: 0;
  box-sizing: border-box;
  height: 3.2em;
  display: grid;
  grid-template-columns: 1.3em minmax(0, 1fr) auto;
  column-gap: .55em;
  align-content: center;
  padding: 0 .7em;
  border-radius: .55em;
}
.d2-fav { grid-row: 1 / span 2; align-self: center; width: 1em; height: 1em; border-radius: 50%; background: rgba(20, 17, 13, .12); }
.d2-you .d2-fav { background: var(--accent); }
.d2-t { grid-column: 2; font-size: .7em; font-weight: 600; line-height: 1.25; }
.d2-you .d2-t { color: var(--accent-ink); }
.d2-u { grid-column: 2; font-size: .52em; line-height: 1.35; color: var(--ink-3); }
.d2-d { grid-column: 2 / span 2; display: flex; gap: .4em; margin-top: .4em; }
.d2-d i { height: .26em; }
.d2-badge {
  grid-column: 3;
  grid-row: 1;
  justify-self: end;
  padding: .3em .75em;
  border-radius: 1em;
  background: var(--accent);
  color: #fff;
  font-size: .48em;
  font-weight: 600;
}
.d2-ai {
  position: absolute;
  left: 1.4em;
  right: 1.4em;
  top: 4.3em;
  padding: .95em 1.05em 1.05em;
  border-radius: .8em;
  background: var(--linen);
  box-shadow: 0 0 0 1px var(--hair), 0 1em 2em -1em rgba(40, 24, 8, .35);
}
.d2-ai-h {
  display: flex;
  align-items: center;
  gap: .5em;
  margin-bottom: .7em !important;
  font-family: var(--mono);
  font-size: .5em;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.d2-ai-h svg { width: 1.7em; height: 1.7em; fill: var(--accent); }
.d2-ai-t { font-size: .68em; line-height: 1.5; color: var(--ink-2); }
.d2-ai-t b { font-weight: 600; color: var(--ink); }
.d2-cite {
  display: inline-flex;
  align-items: center;
  gap: .55em;
  margin-top: .8em;
  padding: .4em .8em;
  border-radius: 1em;
  background: var(--paper);
  box-shadow: inset 0 0 0 1px var(--hair-2);
  font-size: .5em;
  color: var(--ink-2);
}
.d2-cite i { width: .8em; height: .8em; border-radius: 50%; background: var(--accent); }

/* 03 Smart Form */
.d3-head { font-family: var(--display); font-size: 1.1em; line-height: 1.1; }
.d3-n {
  margin: .4em 0 .75em !important;
  font-family: var(--mono);
  font-size: .46em;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.d3-bar { display: block; height: .25em; overflow: hidden; border-radius: 1em; background: rgba(20, 17, 13, .1); }
.d3-bar i { display: block; height: 100%; background: var(--accent); transform-origin: left; }
.d3-steps { position: relative; height: 17.5em; margin-top: 1.3em; overflow: hidden; }
.d3-step { position: absolute; inset: 0; }
.d3-q { margin-bottom: .8em !important; font-family: var(--display); font-size: .98em; line-height: 1.2; }
.d3-chip {
  position: relative;
  display: block;
  overflow: hidden;
  margin-bottom: .55em;
  padding: .85em 1em;
  border: 1px solid rgba(20, 17, 13, .16);
  border-radius: .9em;
  background: #fff;
  font-size: .62em;
  font-weight: 500;
}
.d3-tap {
  position: absolute;
  right: 1.4em;
  top: 50%;
  width: 2.6em;
  height: 2.6em;
  margin-top: -1.3em;
  border-radius: 50%;
  background: rgba(255, 255, 255, .6);
}
.d3-check {
  display: block;
  width: 2.7em;
  height: 2.7em;
  margin-bottom: .7em;
  fill: none;
  stroke: var(--accent);
  stroke-width: 3;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 1;
}
.d3-done .d3-q { font-size: 1.1em; }
.d3-row {
  display: flex;
  justify-content: space-between;
  gap: 1em;
  padding: .7em 0;
  border-top: 1px solid var(--hair-2);
  font-size: .6em;
  font-weight: 500;
}
.d3-row span { font-family: var(--mono); font-size: .82em; font-weight: 400; letter-spacing: .08em; text-transform: uppercase; color: var(--ink-3); }

/* 04 Prototype tools */
.dm-lab .dm-view { background: var(--linen) radial-gradient(rgba(20, 17, 13, .16) 1px, transparent 1.3px) 0 0 / 1.1em 1.1em; }
.d4-grid {
  position: absolute;
  inset: 1.3em 1.5em;
  display: grid;
  grid-template-columns: 1.15fr 1fr;
  grid-template-rows: 1fr 1fr;
  gap: .8em;
}
.d4-piece {
  box-sizing: border-box;
  padding: .85em .95em;
  border-radius: .7em;
  background: #fff;
  box-shadow: 0 0 0 1px var(--hair), 0 .6em 1.2em -.7em rgba(40, 24, 8, .35);
}
.d4-chat { grid-row: span 2; display: flex; flex-direction: column; min-height: 0; overflow: hidden; }
.d4-t { font-family: var(--display); font-size: .98em; line-height: 1.1; }
.d4-s { margin-top: .35em !important; font-size: .5em; color: var(--ink-3); }
/* The conversation: the customer on the right in navy, the concierge on
   the left on linen, then two replies to tap. */
.d4-msgs { display: flex; flex-direction: column; gap: .45em; margin-top: .85em; }
.d4-msg {
  max-width: 90%;
  padding: .6em .8em;
  border-radius: .85em;
  font-size: .5em;
  line-height: 1.35;
}
.d4-you { align-self: flex-end; border-bottom-right-radius: .2em; background: var(--navy); color: #fff; }
.d4-ai { align-self: flex-start; min-width: 3.2em; border-bottom-left-radius: .2em; background: var(--linen); color: var(--ink); }
.d4-dots { display: inline-flex; gap: .28em; padding: .2em 0; }
.d4-dots i { width: .5em; height: .5em; border-radius: 50%; background: rgba(20, 17, 13, .38); animation: d4-dot 1.1s ease-in-out infinite; }
.d4-dots i:nth-child(2) { animation-delay: .15s; }
.d4-dots i:nth-child(3) { animation-delay: .3s; }
@keyframes d4-dot { 0%, 60%, 100% { transform: none; opacity: .5; } 30% { transform: translateY(-.25em); opacity: 1; } }
.d4-chips { display: flex; flex-wrap: wrap; gap: .3em; margin-top: .1em; }
.d4-chips i {
  padding: .45em .8em;
  border: 1px solid var(--accent);
  border-radius: 1em;
  font-size: .44em;
  font-style: normal;
  font-weight: 600;
  color: var(--accent-ink);
}
.d4-row { display: flex; align-items: center; justify-content: space-between; font-size: .66em; font-weight: 600; }
.d4-switch { position: relative; width: 3em; height: 1.65em; border-radius: 1em; background: #d9d0c0; }
.d4-switch i {
  position: absolute;
  left: .2em;
  top: .2em;
  width: 1.25em;
  height: 1.25em;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 .1em .3em rgba(0, 0, 0, .25);
}
.d4-chart { display: flex; flex-direction: column; }
.d4-bars { display: flex; flex: 1; align-items: flex-end; gap: .35em; margin-top: .5em; }
.d4-bars i { display: block; flex: 1; border-radius: .2em .2em 0 0; background: rgba(194, 82, 31, .7); }
.d4-sel {
  position: absolute;
  inset: .7em .8em;
  border: 1px dashed var(--accent);
  border-radius: .95em;
  pointer-events: none;
}
.d4-new {
  position: absolute;
  top: -1.1em;
  right: 2.2em;
  padding: .35em .8em;
  border-radius: 1em;
  background: var(--accent);
  color: #fff;
  font-size: .5em;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
}
.d4-cursor {
  position: absolute;
  z-index: 3;
  left: 0;
  top: 0;
  width: 1.5em;
  height: 1.5em;
  fill: var(--ink);
  stroke: #fff;
  stroke-width: 1.4;
  stroke-linejoin: round;
  filter: drop-shadow(0 .1em .15em rgba(0, 0, 0, .3));
}

/* 05 World of Mobiles: the page inside the frame reflows on the frame's
   own width, exactly as a real one does on a real screen. */
.d5-wrap { display: flex; flex-direction: column; align-items: center; gap: 1.2em; }
.d5-frame {
  position: relative;
  width: 29em;
  height: 18.5em;
  overflow: hidden;
  border-radius: .9em;
  background: #fff;
  box-shadow:
    0 0 0 .45em #1a1713,
    0 .2em .5em .45em rgba(0, 0, 0, .12),
    0 2em 3em -1em rgba(40, 24, 8, .45);
  container-type: inline-size;
  contain: layout paint;
}
.d5-page { padding: .9em 1em; }
.d5-nav { display: flex; align-items: center; gap: .45em; padding-bottom: .65em; border-bottom: 1px solid var(--hair); }
.d5-links { display: flex; gap: .6em; margin-left: auto; }
.d5-burger { display: none; flex-direction: column; gap: .22em; margin-left: auto; }
.d5-burger i { display: block; width: 1em; height: .14em; border-radius: .1em; background: var(--ink); }
.d5-hero { display: grid; grid-template-columns: 1.1fr 1fr; align-items: center; gap: .8em; margin: .85em 0; }
.d5-h { margin-bottom: .5em !important; font-family: var(--display); font-size: 1.2em; line-height: 1.05; letter-spacing: -.015em; }
.d5-p { display: flex; flex-direction: column; gap: .35em; margin-bottom: .65em; }
.d5-btn { display: inline-grid; place-items: center; height: 1.4em; padding: 0 .9em; border-radius: 1em; background: var(--accent); color: #fff; }
.d5-img { display: block; aspect-ratio: 4 / 3; border-radius: .5em; }
.d5-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(5em, 1fr)); gap: .5em; }
.d5-cards i { display: block; height: 2.6em; border-radius: .4em; background: var(--sand); }
@container (max-width: 13em) {
  .d5-links { display: none; }
  .d5-burger { display: flex; }
  .d5-hero { grid-template-columns: minmax(0, 1fr); }
  .d5-img { order: -1; aspect-ratio: 16 / 10; }
  .d5-h { font-size: 1.02em; }
}
.d5-label {
  font-family: var(--mono);
  font-size: .55em;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.d5-label b { font-weight: 500; color: var(--ink); }

/* 06 Care & Security */
.d6-dash {
  position: absolute;
  inset: 0;
  box-sizing: border-box;
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: auto minmax(0, 1fr);
  gap: .7em;
  padding: 1em 1.1em;
  background: var(--linen);
}
.d6-tile {
  position: relative;
  overflow: hidden;
  padding: .8em .9em;
  border-radius: .65em;
  background: #fff;
  box-shadow: 0 0 0 1px var(--hair), 0 .5em 1em -.7em rgba(40, 24, 8, .3);
}
.d6-wide { grid-column: 1 / -1; display: flex; flex-direction: column; }
.d6-lock {
  display: block;
  width: 1.9em;
  height: 1.9em;
  margin-bottom: .45em;
  overflow: visible;
  fill: none;
  stroke: var(--ink);
  stroke-width: 2.2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.d6-lock rect { fill: rgba(194, 82, 31, .12); stroke: var(--accent); }
.d6-t { display: flex; align-items: center; gap: .55em; font-size: .66em; font-weight: 600; }
.d6-s { margin-top: .3em !important; font-size: .5em; color: var(--ink-3); }
.d6-dot { position: relative; width: .75em; height: .75em; border-radius: 50%; background: var(--accent); }
.d6-dot i { position: absolute; inset: 0; border-radius: 50%; background: var(--accent); animation: dm-ping 1.8s var(--ease) infinite; }
@keyframes dm-ping { from { transform: scale(1); opacity: .6; } to { transform: scale(2.8); opacity: 0; } }
.d6-beat {
  display: block;
  width: 100%;
  height: 2.2em;
  margin-top: .55em;
  fill: none;
  stroke: var(--accent);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 1;
  vector-effect: non-scaling-stroke;
}
.d6-cap {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-top: 0 !important;
  font-family: var(--mono);
  font-size: .48em;
  letter-spacing: .12em;
  text-transform: uppercase;
}
.d6-sent {
  display: inline-flex;
  align-items: center;
  gap: .5em;
  padding: .4em .85em;
  border-radius: 1em;
  background: var(--accent);
  color: #fff;
  letter-spacing: .08em;
}
.d6-sent svg { width: 1.3em; height: 1.3em; fill: none; stroke: #fff; stroke-width: 2; stroke-linejoin: round; }
.d6-bars { position: relative; display: flex; flex: 1; align-items: flex-end; gap: .45em; margin-top: .7em; }
.d6-bars i {
  display: block;
  flex: 1;
  border-radius: .25em .25em 0 0;
  background: linear-gradient(to top, rgba(194, 82, 31, .22), rgba(194, 82, 31, .55));
}
.d6-trend {
  position: absolute;
  left: .9em;
  bottom: .8em;
  width: calc(100% - 1.8em);
  height: calc(100% - 3.2em);
  fill: none;
  stroke: var(--ink-2);
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-dasharray: 1;
  vector-effect: non-scaling-stroke;
}

#deckFeatures {
  display: block;
  max-width: none;
  margin: 0;
  padding: 0;
  overflow: visible;
  scroll-snap-type: none;
}
#deckFeatures > .card {
  display: grid;
  grid-template-columns: 5.2rem minmax(0, 1fr);
  grid-auto-rows: min-content;
  column-gap: 1.4rem;
  align-content: center;
  min-height: 60svh;
  padding: 3.5rem 0;
  border-radius: 0;
  background: none;
  border-top: 1px solid var(--hair-2);
  transition: opacity .7s var(--ease);
}
#deckFeatures > .card:first-child { border-top: 0; padding-top: 0; align-content: start; min-height: 52svh; }
#deckFeatures > .card:last-child { min-height: 52svh; }
.features.is-live #deckFeatures > .card:not(.is-on):not(:hover):not(:focus-within) { opacity: .34; }
#deckFeatures > .card > * { grid-column: 2; }
#deckFeatures > .card > .card__icon { display: none; }
#deckFeatures > .card > .card__n {
  grid-column: 1;
  grid-row: 1 / span 4;
  font-family: var(--display);
  font-size: 4.4rem;
  font-style: italic;
  font-weight: 300;
  line-height: .8;
  letter-spacing: -.03em;
  color: var(--accent);
}
#deckFeatures > .card h3 {
  font-size: clamp(2.3rem, 3.6vw, 3.6rem);
  font-weight: 400;
  line-height: 1.02;
  letter-spacing: -.026em;
  color: var(--ink);
}
#deckFeatures > .card .card__kicker { margin-top: .75rem; color: var(--accent-ink); letter-spacing: .06em; }
#deckFeatures > .card p:not(.card__kicker) {
  max-width: 34rem;
  margin-top: 1.2rem;
  font-size: 1.16rem;
  line-height: 1.66;
  color: var(--ink-2);
}
#deckFeatures > .card .card__more {
  position: relative;
  justify-self: start;
  margin-top: 1.1rem;
  color: var(--accent-ink);
}
#deckFeatures > .card .card__more::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: .35rem;
  height: 1.5px;
  background: currentColor;
  transform: scaleX(.28);
  transform-origin: left;
  transition: transform .5s var(--glide);
}
#deckFeatures > .card .card__more:hover::before,
#deckFeatures > .card .card__more:focus-visible::before { transform: scaleX(1); }

/* ------------------------------------------------------ Growing together
   On the page's linen, kept apart from the navy that follows: the caption
   at poster size, then the collage of the three businesses (the cafe, the
   painter, the florist) across the whole width of the screen, edge to
   edge. It opens from the middle as it arrives and rolls up as it goes
   (ui.js, desktop: window). */
.window {
  display: flex;
  flex-direction: column;
  position: relative;
  padding: 9rem 0 10rem;
  background: none;
  color: var(--ink);
}
/* The caption first (it follows the picture in the markup). */
.window__cap {
  order: -1;
  box-sizing: border-box;
  width: 100%;
  max-width: calc(var(--maxw) + 2 * var(--gutter));
  margin: 0 auto 3.5rem;
  padding: 0 var(--gutter);
  overflow: visible;
}
.window__cap .eyebrow { margin-bottom: 1.4rem; color: var(--accent-ink); }
.window__h {
  max-width: 17ch;
  margin: 0;
  font-family: var(--display);
  font-size: clamp(3rem, 5.2vw, 5.4rem);
  font-weight: 400;
  line-height: .98;
  letter-spacing: -.034em;
  color: var(--ink);
}
.window__h .line { padding-bottom: .1em; margin-bottom: -.1em; }
.window__h em { font-style: italic; color: var(--accent); }
.window__h .dot { color: var(--ink); }
.window__clip {
  position: relative;
  width: 100%;
  height: auto;
  aspect-ratio: 2880 / 1222;
  max-height: 82svh;
  overflow: hidden;
  border-radius: 0;
  background: var(--sand);
  box-shadow: none;
}
.window__clip .window__img { display: none; }
.window__wide {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 40%;
}

/* --------------------------------------------------------------- Pricing
   An umber scene on its own, the phone's dark (site.css, --umber): the
   one full screen of dark on the page. It opens out of the linen as the
   section arrives, and the stage holds (sticky) while it plays, one step
   at a time as the page moves on: the question alone, at full size; then
   the question goes and the price comes up with what every build
   includes; then the line into the plans. The dark ends in a rounded edge
   and the plans follow on the linen (ui.js, desktop: pricing, fan). */
.pricing { position: relative; z-index: 1; padding: 0; }
.price-run {
  position: relative;
  /* The screen stops here: the stage is sticky through 2.2 screens, and
     every step plays on the scroll (ui.js, desktop: pricing), so the stop
     is felt but the page is never stuck: scrolling always moves
     something, either way. Only transforms and opacity are scrubbed, so
     nothing large is repainted per frame. */
  height: 220vh;
  height: 220svh;
  padding: 0;
  /* A sheet laid over the linen, rounded at both ends, as the phone's
     comes up and goes on an arc rather than a straight cut. */
  border-radius: 48px;
  /* Clips the stage to the rounded corners. clip, not hidden: it makes no
     scroll container, so the stage inside stays sticky. */
  overflow: clip;
  background: var(--umber-deep);
  box-shadow: 0 50px 70px -50px rgba(9, 9, 9, .5);
}
.price-stage {
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100svh;
  min-height: 100vh;
  min-height: 100svh;
  display: grid;
  grid-template-areas: "all";
  place-items: center;
  max-width: none;
  margin: 0;
  padding: var(--nav-h) var(--gutter) 1.5rem;
  overflow: hidden;
  color: var(--paper);
}
.price-stage > * { grid-area: all; }
/* Out of the grid, so it fills the whole stage, padding and all. */
.price-stage > .price-stage__bg { grid-area: auto; }
/* The umber's light, as on the phone: a lamp a little below the middle,
   darkening to deep umber at the foot. */
.price-stage__bg {
  display: block;
  position: absolute;
  inset: 0;
  background-color: var(--umber);
  background-image:
    radial-gradient(48% 44% at 50% 56%, rgba(30, 30, 30, .95) 0%, rgba(30, 30, 30, 0) 100%),
    linear-gradient(to bottom, var(--umber) 0%, var(--umber) 36%, var(--umber-deep) 100%);
}
.price-stage__q {
  position: relative;
  z-index: 1;
  max-width: none;
  padding: 0;
  text-align: center;
}
/* The question is label enough. */
.price-stage__q .eyebrow { display: none; }
.price-stage__q .display {
  font-size: clamp(4rem, 9.2vw, 9.8rem);
  font-weight: 400;
  line-height: 1;
  letter-spacing: -.042em;
  color: var(--ivory);
}
.price-stage__q .qm { display: inline-block; }
/* The question's words, each in its own window (ui.js). */
.pw__line { display: block; }
.pw { display: inline-block; overflow: hidden; padding: 0 .02em .12em; margin-bottom: -.12em; vertical-align: top; }
.pw > span { display: inline-block; }

.price-stage__box {
  position: relative;
  z-index: 1;
  width: min(100%, 62rem);
  max-width: none;
  padding: 0;
}
.price-stage__lift, .price-stage__fit { display: block; }
.price-stage__eyebrow {
  display: flex;
  justify-content: center;
  margin: 0 0 1.5rem;
  color: var(--on-navy-2);
}
.price-stage__eyebrow::before,
.price-stage__eyebrow::after { background: var(--accent-lit); }
.price-stage .price.panel--dark {
  grid-template-columns: 1.05fr .95fr;
  margin: 0;
  padding: clamp(2.2rem, 3.6vw, 3.4rem) clamp(2rem, 3.6vw, 3.4rem);
  background: rgba(255, 255, 255, .045);
  box-shadow:
    inset 0 0 0 1px rgba(255, 255, 255, .18),
    inset 0 1px 0 rgba(255, 255, 255, .2),
    0 50px 100px -50px rgba(0, 0, 0, .85);
}
/* "Complete build price" over the panel says it already. */
.price-stage .price__label { display: none; }
/* The figure, set and still, in the same warm white as the question. */
.price-stage .price__fig { font-size: clamp(5.4rem, 8vw, 8.4rem); color: var(--ivory); }
.price-stage__next { margin-top: 2.6rem; text-align: center; }
.price-stage__next .plans__h {
  margin: 0;
  font-size: clamp(2rem, 3vw, 2.8rem);
  font-weight: 400;
  color: var(--ivory);
}
.price-stage__cue { display: none; }

/* The plans, back on the page's linen as they are on the phone: their
   heading, then the three cards. Clipped sideways only, for the cards
   cartwheeling in from off the screen. */
.plans {
  position: relative;
  padding: 9rem 0 8rem;
  overflow-x: clip;
}
/* An ordinary block: nothing holds the screen here. The cards play their
   story on their own clock as they come up (ui.js, desktop: fan) and the
   page scrolls on past them freely. */
.plans__stage {
  position: relative;
  padding-top: calc(var(--nav-h) + 2rem);
}
#deckPlans { position: relative; }
.plans__head { display: block; }
.plans__title {
  font-size: clamp(3.2rem, 5.4vw, 5.2rem);
  line-height: 1;
  letter-spacing: -.034em;
}
.plans__title .line { padding-bottom: .1em; margin-bottom: -.1em; }

/* Three plans side by side, perfectly straight, the same height. They
   cartwheel into a pile in the middle, square up, and slide out to here
   (ui.js, desktop: fan, in transforms). */
#deckPlans {
  display: flex;
  justify-content: center;
  align-items: stretch;
  gap: clamp(1rem, 1.8vw, 1.75rem);
  max-width: none;
  margin: 0 auto;
  padding: 2.5rem var(--gutter) 2rem;
  overflow: visible;
  scroll-snap-type: none;
}
#deckPlans > .plan {
  flex: 0 0 min(22.5rem, 29vw);
  transform-origin: 50% 50%;
  /* No transition on the transform: every move is ui.js's, and a CSS
     transition under a script's tween makes the card chase itself. The
     hover lift is on translate, a separate property GSAP leaves alone
     (it writes translate: none inline, hence the !important below). */
  transition: translate .5s var(--glide), background-color .35s var(--ease), box-shadow .5s var(--ease);
  will-change: transform;
}
#deckPlans.is-dealt > .plan:hover,
#deckPlans.is-dealt > .plan:focus-within { z-index: 5; translate: 0 -12px !important; }
#deckPlans > .plan:nth-child(1) { z-index: 1; }
#deckPlans > .plan:nth-child(2) { z-index: 2; }
#deckPlans > .plan:nth-child(3) { z-index: 3; }
#deckPlans.is-dealt > .plan:hover,
#deckPlans.is-dealt > .plan:focus-within {
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .55),
    0 40px 60px -34px rgba(64, 42, 18, .5);
}
/* The plans' names (hidden on a phone, where only the front card shows):
   on the gold card, in its bronze rather than the light terracotta meant
   for a dark card. */
.plan.plan--ember .plan__n { color: #5a3a0c; }
/* The gold card's glint: once, as the hand lands, not on a loop. */
.deck--fan .gild::before { animation: none; }
.deck--fan.is-dealt .plan--ember .gild::before { animation: gild-sheen 3.4s cubic-bezier(.55, 0, .35, 1) .15s 1 both; }
/* No light running round its edge (ui.js, volt, is off). */
.plan--ember .volt { display: none; }
.plans .deck-ui { display: none; }
.plans .deck-wrap { margin-top: 0; }

/* The ad-hoc rates as one ruled strip under the cards: what they are on
   the left, the two rates on the right. */
.plans .adhoc {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
  column-gap: 3.5rem;
  align-items: start;
  max-width: 50rem;
  margin-top: 1rem;
  padding-top: 1.6rem;
}
.plans .adhoc__h { grid-column: 1; margin-bottom: .6rem; }
.plans .adhoc__note { grid-column: 1; max-width: 22rem; font-size: .9rem; }
.plans .adhoc__list { grid-column: 2; grid-row: 1 / span 2; margin-top: -.7rem; }
.plans .adhoc__row dd { font-size: 1.6rem; }

/* ------------------------------------------------------------------- CTA
   The question the page has been building to, as the closing statement it
   is: a terracotta tab out of the left wall that runs to the content's
   right edge, the question set across it at heading size on two balanced
   lines (the phone's breaks are for a phone's measure), and its one
   answer at the right, on the question's last line. The tab slides out as
   it comes up the screen and back into the wall as it goes; nothing inside
   it moves (ui.js, desktop: tab). */
.cta { padding-block: 8rem 11rem; overflow-x: clip; }
.cta__tab {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: end;
  column-gap: clamp(2rem, 4vw, 4rem);
  margin-right: max(var(--gutter), calc((100% - var(--maxw)) / 2));
  padding-top: clamp(4rem, 6vw, 5.5rem);
  padding-bottom: clamp(4rem, 6vw, 5.5rem);
  padding-right: clamp(2.5rem, 4.5vw, 4.5rem);
  /* On its own GPU layer for good: the slide only moves a painted picture
     of the tab, gradient, shadows and all. */
  will-change: transform;
}
.cta__q {
  max-width: 17ch;
  margin: 0;
  font-size: clamp(3.2rem, 5.6vw, 5.8rem);
  line-height: 1;
  letter-spacing: -.034em;
  text-wrap: balance;
}
.cta__q br { display: none; }
/* The answer sits on the question's last line. */
.cta__tab > div { padding-bottom: .5rem; }
.cta__btn { min-width: 14rem; }

/* --------------------------------------------------------------- Contact */
.contact {
  display: grid;
  grid-template-columns: minmax(0, .85fr) minmax(0, 1.15fr);
  column-gap: clamp(3rem, 6vw, 6rem);
  align-items: start;
  padding-inline: max(var(--gutter), calc((100% - var(--maxw)) / 2));
}
.contact > .wrap { max-width: none; margin: 0; padding: 0; }
.contact__head {
  position: sticky;
  top: calc(var(--nav-h) + 3rem);
  text-align: left;
}
.contact__head .plans__eyebrow { justify-content: flex-start; text-indent: 0; }
.contact__head .plans__eyebrow::before { display: none; }
.contact__head .lead { margin-inline: 0; max-width: 28rem; }
.contact__h { font-size: clamp(3rem, 4.6vw, 4.2rem); }
.contact__promise { justify-content: flex-start; margin-inline: 0; text-align: left; }
.contact .finder { max-width: none; margin: 0; }

/* ---------------------------------------------------------------- Footer
   The footer is the same on every page now (site.css, "The signed footer"). */

/* ---------------------------------------------------------- Browser bits
   The parts no component draws, in the page's own materials. */
::selection { background: rgba(194, 82, 31, .22); color: var(--ink); }
.price-run ::selection,
.slab--local ::selection,
.cta__tab ::selection { background: rgba(255, 255, 255, .28); color: inherit; }
html { scrollbar-color: rgba(20, 17, 13, .28) var(--linen); }

/* A short screen (a laptop at 700-odd pixels tall): the hero is held on
   the screen while its film plays, so all of it has to fit. */
@media (max-height: 800px) {
  .hero .hero__h1 { font-size: clamp(3.2rem, min(8.6vw, 13svh), 8.4rem); margin-bottom: 1.5rem; }
  .hero .hero__lead { margin-bottom: 1.6rem; }
  .hero .hero__areas { margin-top: 1.7rem; padding-top: .9rem; }
  /* The price stage: all of it on one screen. */
  .price-stage .price__fig { font-size: clamp(4.4rem, 11svh, 7rem); }
  .price-stage .price.panel--dark { padding-block: 1.8rem; }
  .price-stage .ticks { gap: .4rem; }
  .price-stage__eyebrow { margin-bottom: 1rem; }
  .price-stage__next { margin-top: 1.6rem; }
}

/* ------------------------------------------ A small laptop (to 1099px)
   The features' numerals come in, and the price panel's two halves go one
   over the other. */
@media (max-width: 1099px) {
  /* The hero's square a little smaller and with no drift: the copy beside
     it needs the room more than the print needs to reach the headline,
     which at this size it does anyway. */
  .hero { --S: min(calc(var(--H) * .92), calc((100vw - 2 * var(--E)) * .48)); --X: 0px; }
  #deckFeatures > .card { grid-template-columns: 3.8rem minmax(0, 1fr); column-gap: 1rem; }
  #deckFeatures > .card > .card__n { font-size: 3.3rem; }
  /* Narrower, the cards overlap less, so no card's words go under the
     next one. */
  .stack > .slab--local { margin-top: -2rem; }
  .stack > .slab--process { margin-top: -2.5rem; }
  .slab--studio .slab__card { width: min(100%, 40rem); }
  .slab--local .slab__card { width: min(100%, 32rem); }
  .slab__steps { gap: 1.6rem 2.2rem; }
  .slab__steps li { grid-template-columns: 2.8rem minmax(0, 1fr); }
  .slab__steps li::before { font-size: 2.2rem; }

  .price-stage .price.panel--dark { gap: 2rem; }
  .price-stage .price__incl { padding-left: 2rem; margin-left: -2rem; }
}

/* ------------------------------------------------------- Reduced motion */
@media (prefers-reduced-motion: reduce) {
  .showcase { height: auto; }
  .showcase__stage { position: relative; height: auto; padding-block: 8rem; }
  .showcase__say { position: relative; }
  .showcase__say + .showcase__say { margin-top: 2rem; }
  .showcase__copy { min-height: 0; }
  .showcase__copy { border-top: 0; }
  .price-run { height: auto; }
  .price-stage { position: relative; height: auto; padding-block: 7rem; row-gap: 3rem; }
  .price-stage > * { grid-area: auto; }
}

/* 07 Monthly growth insights: the month's trend, then the insights it
   turned up, each a next step. */
.d7-dash {
  position: absolute;
  inset: 0;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  gap: .55em;
  padding: .9em 1.1em;
  background: var(--linen);
}
.d7-h { display: flex; align-items: baseline; justify-content: space-between; margin: 0; font-size: .62em; font-weight: 600; }
.d7-score { font-family: var(--display); font-size: 1.9em; font-weight: 400; letter-spacing: -.02em; color: var(--accent-ink); }
.d7-score b { font-weight: 400; }
.d7-chart { flex: 1; min-height: 0; padding: .5em .6em; border-radius: .6em; background: #fff; box-shadow: 0 0 0 1px var(--hair), 0 .5em 1em -.7em rgba(40, 24, 8, .3); }
.d7-chart svg { display: block; width: 100%; height: 100%; overflow: visible; }
.d7-line { fill: none; stroke: var(--accent); stroke-width: 2; stroke-linecap: round; stroke-dasharray: 1; vector-effect: non-scaling-stroke; }
.d7-area { fill: rgba(194, 82, 31, .1); }
.d7-cards { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: .45em; }
.d7-ins { display: grid; gap: .4em; margin: 0; padding: .55em .6em .65em; border-radius: .55em; background: #fff; box-shadow: 0 0 0 1px var(--hair), 0 .6em 1.1em -.8em rgba(40, 24, 8, .35); }
.d7-ins > i { display: grid; place-items: center; width: 1.1em; height: 1.1em; border-radius: 50%; background: var(--accent); }
.d7-ins svg { width: .75em; height: .75em; fill: none; stroke: #fff; stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; }
.d7-ins span { display: grid; gap: .3em; }
.d7-ins b { font-size: .46em; font-weight: 600; }
.d7-ins span i { display: block; max-width: 100%; height: .3em; border-radius: .2em; background: rgba(20, 17, 13, .12); }

/* The features intro (ui.js, "THE INTRO"): the stage starts as one wide
   empty sheet. The paper heading and the line of copy live inside it; the
   stage's own pieces stay out of sight until the intro is done. */
.feat-side { z-index: 3; }
.feat-stage .fi-title { position: absolute; margin: 0; color: var(--paper); pointer-events: none; z-index: 2; }
.feat-stage .fi-title em, .feat-stage .fi-title .qm { color: var(--accent); }
.feat-stage .fi-a, .feat-stage .fi-b { display: block; width: max-content; white-space: nowrap; }
.feat-stage .fi-copy {
  position: absolute; margin: 0; z-index: 2;
  text-align: center; font-family: var(--sans); font-weight: 400;
  font-size: clamp(1.15rem, 1.7vw, 1.6rem); line-height: 1.55; letter-spacing: 0;
  color: rgba(246, 243, 238, .82); text-wrap: balance;
  pointer-events: none;
}
.feat-stage.is-intro > :not(.fi-title):not(.fi-copy) { opacity: 0 !important; }

/* The plans, wide: the pricing page's table replaces the cards. */
.plans__stage .plan-pills, .plans__stage .deck-wrap { display: none; }
.plans__table { display: block; }
.plans__table .pr-panel { margin-top: 2.4rem; }
