/* Two themes on one token set. Light is the default; the inline script in <head> picks
   the theme before paint (saved choice, then system preference, then daytime). */

:root {
  color-scheme: light;
  --bg: #f6f4ef;
  --bg-2: #fdfcfa;
  --bg-3: #ece9e1;
  --line: #e1ddd4;
  --line-2: #c9c4b8;
  --text: #17191d;
  --text-2: #3f434a;
  --muted: #6f7681;
  --ink: #17191d;
  --ink-text: #f6f4ef;
  --hue: #c9891f;
  --shadow: 0 24px 60px -30px rgba(23, 25, 29, 0.35);

  --display: 'PP Watch', 'Helvetica Neue', Arial, sans-serif;
  --sans: 'Graphik', 'Helvetica Neue', Arial, sans-serif;

  /* Half on a phone; the full radii come in at 900px, below. */
  --radius: 6px;
  --radius-s: 4px;
  --scrollbar: 11px;
  /* The page opens at the same distance from the top as it keeps from the sides. */
  --top-row: var(--gutter);
  /* Height the fixed footer reserves at the bottom of a scrolling page. */
  --footer-h: 70px;
  /* Height of the sticky bar on a phone; 0 where the rail sits on the side. */
  --bar-h: 0px;
  /* Room between the bar and the footer; site.js replaces it with the measured value. */
  --fold: calc(100vh - var(--footer-h) - 96px);
  --scroll-gap: 10px;
  --gutter: 20px;
  --page: 1120px;
  --head: 1120px;
  --measure: 640px;
  --rail: 300px;
}

@media (min-width: 900px) {
  :root {
    --radius: 12px;
    --radius-s: 8px;
  }
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) {
    color-scheme: dark;
    --bg: #14171c;
    --bg-2: #1b1f26;
    --bg-3: #21262e;
    --line: #2a303a;
    --line-2: #363d49;
    --text: #eceff3;
    --text-2: #c2c9d3;
    --muted: #8c97a6;
    --ink: #eceff3;
    --ink-text: #14171c;
    --hue: #f5c451;
    --shadow: 0 24px 60px -30px rgba(0, 0, 0, 0.8);
  }
}

:root[data-theme='dark'] {
  color-scheme: dark;
  --bg: #14171c;
  --bg-2: #1b1f26;
  --bg-3: #21262e;
  --line: #2a303a;
  --line-2: #363d49;
  --text: #eceff3;
  --text-2: #c2c9d3;
  --muted: #8c97a6;
  --ink: #eceff3;
  --ink-text: #14171c;
  --hue: #f5c451;
  --shadow: 0 24px 60px -30px rgba(0, 0, 0, 0.8);
}

@media (min-width: 750px) {
  :root {
    --gutter: 40px;
  }
}

@view-transition {
  navigation: auto;
}

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

* {
  box-sizing: border-box;
}

html {
  background: var(--bg);
  color: var(--text);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  scroll-behavior: smooth;
  /* On a phone an anchor lands below the sticky bar; site.js measures it into --bar-h. */
  scroll-padding-top: calc(var(--bar-h) + 16px);
}

body {
  margin: 0;
  background: var(--bg);
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

h1,
h2,
h3,
p,
ul,
ol,
dl,
dd,
figure {
  margin: 0;
}

ul,
ol {
  padding: 0;
  list-style: none;
}

a {
  color: inherit;
}

/* Scrollbars follow the theme: a thin track-less bar with a rounded thumb. */
::-webkit-scrollbar {
  width: var(--scrollbar);
  height: var(--scrollbar);
}

::-webkit-scrollbar-track {
  background: transparent;
}

::-webkit-scrollbar-thumb {
  background: var(--muted);
  background-clip: padding-box;
  border: 3px solid transparent;
  border-radius: 999px;
}

::-webkit-scrollbar-thumb:hover {
  background: var(--text-2);
  background-clip: padding-box;
}

::-webkit-scrollbar-corner {
  background: transparent;
}

button {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
}

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

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

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Layout-neutral hosts for the web components. */
site-rail,
project-drawer,
store-wall,
demo-groups {
  display: block;
}

/* The link inside stays the item of whatever lays it out. */
demo-link {
  display: contents;
}

body[data-locked] {
  overflow: hidden;
}

contact-form {
  display: contents;
}

/* Scroll reveal: only when JS is there to reveal it again. */
html[data-js] [data-reveal] {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 600ms cubic-bezier(0.2, 0.7, 0.2, 1), transform 600ms cubic-bezier(0.2, 0.7, 0.2, 1);
}

html[data-js] [data-reveal][data-shown] {
  opacity: 1;
  transform: none;
}

/* ---------- containers ---------- */

.wrap {
  width: 100%;
  max-width: var(--page);
  margin: 0 auto;
  padding: 0 var(--gutter);
}

/* A page that fills the screen instead of sitting in the reading container. */
.wrap[data-wide] {
  max-width: none;
}

.page {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  min-height: 100vh;
}

.page__main {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.main {
  flex: 1;
  display: flex;
  flex-direction: column;
}

@media (min-width: 900px) {
  .page {
    grid-template-columns: var(--rail) minmax(0, 1fr);
  }

  /* The switches sit on the same line as the first text of the page, so the page
     does not open with an empty band. The bar itself lets clicks through. */
  .page__main {
    position: relative;
  }

  .page__main[data-shell] .topbar {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    /* Sections below are positioned too, and would otherwise paint over the bar. */
    z-index: 5;
    pointer-events: none;
  }

  .page__main[data-shell] .tools {
    pointer-events: auto;
  }

  /* A wide page holds the viewport: its head and footer stay put and only the
     list between them scrolls, the way the rail already does. The grid is clipped
     too, so nothing inside it can ever push the footer past the bottom edge. */
  .page:has(> .page__main[data-shell]) {
    height: 100vh;
    overflow: hidden;
  }

  .page__main[data-shell] {
    height: 100vh;
    overflow: hidden;
  }

  .page__main[data-shell] .main,
  .page__main[data-shell] .section,
  .page__main[data-shell] .wrap,
  .page__main[data-shell] .wall {
    min-height: 0;
  }

  .page__main[data-shell] .section,
  .page__main[data-shell] .wall {
    flex: 1;
  }

  .page__main[data-shell] .wrap {
    flex: 1;
    display: flex;
    flex-direction: column;
  }

  .page__main[data-shell] .wall__list {
    flex: 1;
    overflow-y: auto;
    scrollbar-width: thin;
    scrollbar-color: var(--muted) transparent;
    align-content: start;
    /* The scroller has a definite height, so auto rows would collapse to their
       min-content: the row must be as tall as the tallest card instead. */
    grid-auto-rows: max-content;
    /* Space between the cards and the scrollbar, on top of the lane the bar takes. */
    padding-right: var(--scroll-gap);
    padding-bottom: 24px;
    scrollbar-gutter: stable;
  }

  .page__main[data-shell] .footer {
    margin-top: 0;
  }

  /* The list keeps a lane for its scrollbar, so everything above and below it takes
     the same lane; otherwise their right edge sits past the cards. */
  .page__main[data-shell] .topbar .wrap,
  .page__main[data-shell] .footer .wrap {
    padding-right: calc(var(--gutter) + var(--scrollbar) + var(--scroll-gap));
  }

  .page__main[data-shell] .wall__tools {
    padding-right: calc(var(--scrollbar) + var(--scroll-gap));
  }
}

.section {
  padding: 64px 0 0;
  display: flex;
  flex-direction: column;
}

.section[data-first] {
  padding-top: 32px;
}

.section__head {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding-bottom: 28px;
  max-width: var(--head);
}

.section__title {
  font-family: var(--display);
  font-weight: 700;
  font-size: 32px;
  letter-spacing: -0.64px;
  line-height: 1.05;
}

.section__title[data-small] {
  font-size: 24px;
  letter-spacing: -0.48px;
}

.section__note {
  color: var(--muted);
  font-size: 16px;
  max-width: var(--measure);
}

.section__foot {
  display: flex;
  padding-top: 28px;
}

@media (min-width: 900px) {
  .section {
    padding-top: 96px;
  }

  /* Title on one edge, the note on the other: the row reads as one line instead
     of leaving a ragged gap after the note. */
  .section__head {
    flex-direction: row;
    align-items: baseline;
    justify-content: space-between;
    gap: 32px;
  }

  .section__title {
    font-size: 40px;
    letter-spacing: -0.8px;
  }

  .section__title[data-small] {
    font-size: 28px;
    letter-spacing: -0.56px;
  }
}

/* ---------- buttons ---------- */

.btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 12px 18px;
  font-size: 15px;
  font-weight: 500;
  line-height: 1.2;
  color: var(--text);
  text-decoration: none;
  border: 1px solid var(--line-2);
  border-radius: var(--radius-s);
  background: var(--bg-2);
  transition: background 160ms ease, border-color 160ms ease, transform 160ms ease;
}

.btn:hover {
  border-color: var(--text-2);
  transform: translateY(-1px);
}

.btn[data-primary] {
  background: var(--ink);
  color: var(--ink-text);
  border-color: var(--ink);
}

.btn[data-primary]:hover {
  border-color: var(--ink);
  opacity: 0.9;
}

.btn:disabled {
  opacity: 0.6;
  cursor: default;
  transform: none;
}

/* ---------- rail ---------- */

.rail {
  /* On a phone the bar with the name and the menu stays on top while the page scrolls. */
  position: sticky;
  top: 0;
  z-index: 7;
  background: var(--bg);
}

.rail__inner {
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding: 16px var(--gutter);
}

.rail__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}

.rail__brand {
  display: flex;
  align-items: center;
  gap: 14px;
  text-decoration: none;
  min-width: 0;
}

.rail__portrait {
  flex: none;
  width: 72px;
  aspect-ratio: 1;
  object-fit: cover;
  border-radius: var(--radius-s);
  border: 1px solid var(--line);
  background: var(--bg-3);
}

.rail__who {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.rail__name {
  font-family: var(--display);
  font-weight: 700;
  font-size: 16px;
  letter-spacing: -0.32px;
  line-height: 1.1;
  text-transform: uppercase;
}

.rail__role {
  font-size: 13px;
  line-height: 1.3;
  color: var(--muted);
}

/* In the full rail the name is set as written, and the role takes the body's leading. */
@media (min-width: 900px) {
  .rail__name {
    font-size: 20px;
    letter-spacing: -0.4px;
    text-transform: none;
  }

  .rail__role {
    line-height: inherit;
  }
}

.rail__menu {
  display: inline-flex;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  width: 40px;
  height: 40px;
  padding: 0 10px;
  border: 1px solid var(--line-2);
  border-radius: 50%;
}

.rail__bar {
  display: block;
  height: 2px;
  background: var(--text);
  /* The menu lines only show on a phone, where the radii are halved. */
  border-radius: 1px;
}

.rail__foot {
  display: none;
}

.rail__nav {
  flex-direction: column;
  border-top: 1px solid var(--line);
}

/* On a phone the open menu drops over the page from under the bar, so nothing below
   moves; a menu taller than the screen scrolls inside itself. It slides in from the
   left and, closing, goes on out to the right (site.js holds [data-closing] for that),
   then waits off the left edge again. The button lives in the footer. */
.rail__nav {
  display: flex;
  visibility: hidden;
  transform: translateX(-100%);
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  max-height: calc(100vh - var(--bar-h));
  overflow-y: auto;
  padding: 0 var(--gutter) 16px;
  background: var(--bg);
  background-clip: padding-box;
  box-shadow: var(--shadow);
}

.rail[data-open] .rail__nav,
.rail[data-closing] .rail__nav {
  visibility: visible;
  transition: transform 320ms cubic-bezier(0.2, 0.7, 0.2, 1);
}

.rail[data-open] .rail__nav {
  transform: none;
}

.rail[data-closing] .rail__nav {
  transform: translateX(100%);
}

/* The sliding menu must not widen the page on a phone. */
.page {
  overflow-x: clip;
}

.rail__link {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  padding: 11px 0;
  border-bottom: 1px solid var(--line);
  text-decoration: none;
  font-size: 15px;
  font-weight: 500;
  color: var(--text-2);
}

.rail__link:hover {
  color: var(--text);
}

/* Profiles on the left, language and theme on the right; on the narrowest phones the
   settings wrap under the profiles and keep to the right. */
.rail__extras {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px 16px;
  padding-top: 16px;
}

.tools[data-menu] {
  margin-left: auto;
}

.rail__count {
  font-family: var(--display);
  font-size: 13px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

.rail__foot {
  flex-direction: column;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  color: var(--muted);
}

.rail__cta {
  width: 100%;
  max-width: 260px;
  justify-content: center;
  padding-inline: 28px;
  text-transform: uppercase;
  letter-spacing: 0.6px;
}

.tools {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 10px;
}

/* On a phone the switches are in the menu, not above the headline. */
.tools[data-bar] {
  display: none;
}

.tools[data-menu] {
  justify-content: flex-start;
  gap: 12px;
}

.tools__lang {
  font-size: 13px;
  color: var(--text-2);
  text-decoration: none;
  padding: 5px 10px;
  border: 1px solid var(--line-2);
  border-radius: var(--radius-s);
}

.tools__lang:hover {
  color: var(--text);
  border-color: var(--text-2);
}

.tools__theme {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  border: 1px solid var(--line-2);
  color: var(--text-2);
}

.tools__theme:hover {
  color: var(--text);
  border-color: var(--text-2);
}

.tools__icon {
  display: block;
}

/* In the menu both take a finger's 44px. */
.tools[data-menu] .tools__lang {
  display: inline-flex;
  align-items: center;
  height: 44px;
  padding: 0 16px;
  font-size: 15px;
}

.tools[data-menu] .tools__theme {
  width: 44px;
  height: 44px;
}

@media (min-width: 900px) {
  .tools[data-bar] {
    /* A page without a line of text on the left still keeps the switches on the right. */
    margin-left: auto;
    display: flex;
  }
}

@media (min-width: 900px) {
  .rail {
    position: static;
    border-right: 1px solid var(--line);
  }


  .rail__inner {
    position: sticky;
    top: 0;
    height: 100vh;
    gap: 22px;
    padding: 28px var(--gutter) 24px;
    /* On a short screen the portrait and the menu are taller than the viewport;
       the rail scrolls inside itself instead of dragging the whole page along. */
    overflow-y: auto;
    scrollbar-width: thin;
    scrollbar-color: var(--muted) transparent;
  }

  .rail__top {
    display: block;
  }

  .rail__brand {
    flex-direction: column;
    align-items: stretch;
    gap: 16px;
  }

  .rail__portrait {
    width: 100%;
    aspect-ratio: 4 / 5;
  }

  .rail__menu {
    display: none;
  }

  .rail__nav,
  .rail__foot {
    display: flex;
  }

  .page {
    overflow-x: visible;
  }

  /* In the side rail the links are part of the column again. */
  .rail__nav {
    visibility: visible;
    transform: none;
    position: static;
    max-height: none;
    overflow-y: visible;
    padding: 0;
    box-shadow: none;
  }

  .rail__foot {
    margin-top: auto;
  }

  /* The footer carries "All projects" and the profiles beside the rail. */
  .rail__link[data-phone],
  .rail__extras {
    display: none;
  }
}

/* ---------- hero ---------- */

.hero {
  /* Corrected by the browser once it knows how the copy wrapped; see site.js. */
  --hero-fit: 1;
  padding: 40px 0 0;
  position: relative;
  overflow: hidden;
}

.hero__inner {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 40px;
  align-items: center;
}

.hero__copy {
  display: flex;
  flex-direction: column;
  gap: 22px;
  max-width: 680px;
}

.hero__title {
  font-family: var(--display);
  font-weight: 800;
  font-size: clamp(36px, 5.4vw, 62px);
  line-height: 1.02;
  letter-spacing: calc(clamp(36px, 5.4vw, 62px) * -0.03);
  display: flex;
  flex-direction: column;
}

.hero__line {
  display: block;
  animation: rise 700ms cubic-bezier(0.2, 0.7, 0.2, 1) both;
}

.hero__line[data-accent] {
  color: var(--hue);
  animation-delay: 90ms;
}

.hero__lede {
  font-size: 18px;
  line-height: 1.5;
  color: var(--text-2);
  max-width: var(--measure);
  animation: rise 700ms cubic-bezier(0.2, 0.7, 0.2, 1) 180ms both;
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  animation: rise 700ms cubic-bezier(0.2, 0.7, 0.2, 1) 270ms both;
}

.hero__visual {
  position: relative;
  aspect-ratio: 5 / 4;
}

.hero__shot {
  position: absolute;
  left: 0;
  bottom: 0;
  width: 72%;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  object-position: top;
  border-radius: var(--radius);
  border: 1px solid var(--line);
  box-shadow: var(--shadow);
  background: var(--bg-2);
  transform: translate(calc(var(--n) * 12%), calc(var(--n) * -9%)) rotate(calc(-4deg + var(--n) * 1.6deg));
  z-index: calc(5 - var(--n));
  /* Dealt out one after the other, each from just below its resting place. `backwards`, not
     `both`: once dealt, the card belongs to the hover transitions below. */
  animation: deal 720ms cubic-bezier(0.2, 0.7, 0.2, 1) calc(160ms + var(--n) * 90ms) backwards;
  transition: transform 480ms cubic-bezier(0.2, 0.7, 0.2, 1), box-shadow 480ms ease;
}

/* The one under the pointer comes to the front at once and is lifted a little on the way. */
.hero__shot:hover {
  transform: translate(calc(var(--n) * 12%), calc(var(--n) * -9% - 3%)) rotate(calc(-2deg + var(--n) * 1.2deg)) scale(1.04);
  box-shadow: 0 36px 70px -28px rgba(23, 25, 29, 0.55);
  z-index: 6;
}

.proof {
  position: relative;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 20px 24px;
  padding: 36px 0;
  align-items: center;
  margin-top: 48px;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}

.proof__list {
  display: contents;
}

/* With the grid the whole row is one link to the GitHub profile, laid over the field. */
.proof__link {
  position: absolute;
  inset: 0;
  display: block;
  z-index: 1;
  border-radius: var(--radius);
}

.proof[data-link] .activity {
  transition: filter 300ms ease;
}

.proof[data-link]:hover .activity {
  filter: brightness(1.12) saturate(1.1);
}

.proof__item {
  position: relative;
  display: flex;
  flex-direction: column-reverse;
  /* Two by two, each figure sits in the middle of its column, with or without the grid. */
  align-items: center;
  gap: 4px;
  text-align: center;
}

.proof__value {
  font-family: var(--display);
  font-weight: 700;
  font-size: 32px;
  line-height: 1;
  letter-spacing: -0.64px;
  font-variant-numeric: tabular-nums;
}

.proof__label {
  font-size: 13px;
  color: var(--text);
}


/* The activity grid behind the numbers: a cell per day something shipped since the first
   feature, in the accent at a strength the row can carry. Under 900px, where the row is two
   by two, it is laid under both rows of numbers; from 900px it sets the height of the row.
   site.js fills it with 10px tiles, as many as fit, like a mosaic. */
.activity {
  display: block;
  /* Positioned inside a grid, the area is its containing block: both rows of numbers. */
  position: absolute;
  inset: 0;
  grid-area: 1 / 1 / 3 / -1;
  width: 100%;
  height: 100%;
  overflow: hidden;
  pointer-events: none;
}

.activity__empty {
  fill: var(--text);
  opacity: 0.075;
}

.activity__cell {
  fill: var(--hue);
  opacity: var(--o);
  transform-box: fill-box;
  transform-origin: center;
  /* Each cell comes out like a star: a flash brighter than its resting strength, then settles.
     `--d` is the cell's share of the intro; `--intro`, `--rest` (scales the resting strength)
     and `--peak` (scales the flare, 1 peaks at 2.4× the rest) come from the admin. */
  animation: light-up 700ms cubic-bezier(0.2, 0.7, 0.2, 1) calc(var(--d) * var(--intro)) both;
}

/* The field waits until the row is on screen: on a phone it sits below the fold. */
html[data-js] .proof[data-grid]:not([data-play]) .activity__cell {
  animation-play-state: paused;
}

.proof[data-grid] {
  padding: 0;
  gap: 0;
  /* Two by two a label can wrap; the numbers of a row stay on one line. */
  align-items: start;
  border-top: 0;
  border-bottom: 0;
}

.proof[data-grid] .proof__item {
  align-items: center;
  padding: 24px 12px;
  text-align: center;
}

/* On the grid the label is white and set in capitals; muted grey drowns in the cells. */
.proof[data-grid] .proof__label {
  color: var(--text);
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 1.08px;
  text-transform: uppercase;
}

/* Five steps as on GitHub: the empty tile, then four strengths that read apart. */
.activity__cell[data-level='1'] { --o: calc(0.25 * var(--rest)); }
.activity__cell[data-level='2'] { --o: calc(0.45 * var(--rest)); }
.activity__cell[data-level='3'] { --o: calc(0.7 * var(--rest)); }
.activity__cell[data-level='4'] { --o: calc(1 * var(--rest)); }

.activity__cell[data-off] {
  display: none;
}

@keyframes light-up {
  from {
    opacity: 0;
    transform: scale(0.3);
  }
  45% {
    opacity: calc(var(--o) * (1 + 1.4 * var(--peak)));
    transform: scale(1.2);
  }
  to {
    opacity: var(--o);
    transform: none;
  }
}

@keyframes deal {
  from {
    opacity: 0;
    transform: translate(calc(var(--n) * 12%), calc(var(--n) * -9% + 40px)) rotate(calc(-10deg + var(--n) * 1.6deg)) scale(0.96);
  }
}

@keyframes rise {
  from {
    opacity: 0;
    transform: translateY(14px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@media (min-width: 900px) {
  /* The first line of the page sits on the same row as the switches. */
  .section[data-first] {
    padding-top: var(--top-row);
  }

  /* The hero gives the top gutter back on a short screen, where the numbers row
     below it needs the room more than the symmetry does. */
  .hero {
    padding-top: calc(min(var(--top-row), 5.5vh) * var(--hero-fit));
  }

  /* Everything above the fold is measured against the height of the window, so the
     numbers row stays visible on a laptop without anyone scrolling for it. */
  .hero__inner {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 56px;
  }

  /* On a wide screen the stack of shots, not the copy, is what would push the
     numbers row past the fold: it is capped against the same room. */
  .hero__visual {
    max-height: calc((100vh - var(--footer-h)) * 0.56);
  }

  .hero__shot {
    width: auto;
    height: 58%;
  }

  .hero__copy {
    gap: calc(clamp(10px, 2vh, 22px) * var(--hero-fit));
  }

  .hero__title {
    font-size: calc(clamp(34px, min(5.4vw, 6.4vh), 62px) * var(--hero-fit));
    letter-spacing: calc(clamp(34px, min(5.4vw, 6.4vh), 62px) * var(--hero-fit) * -0.03);
  }

  .hero__lede {
    font-size: calc(clamp(16px, 2.2vh, 20px) * var(--hero-fit));
  }



  .proof {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    margin-top: calc(clamp(20px, 3vh, 64px) * var(--hero-fit));
    padding: calc(clamp(16px, 2.4vh, 36px) * var(--hero-fit)) 0;
  }

  /* The figures keep their size whatever the height of the window; only a column too
     narrow for "2023" at 40px (about 3.6 times the size) makes them smaller. */
  .proof__item {
    container-type: inline-size;
  }

  .proof__value {
    font-size: min(40px, 24cqi);
    letter-spacing: calc(min(40px, 24cqi) * -0.02);
  }

  /* In one row without the grid the figures read from the left, as before. */
  .proof__item {
    align-items: flex-start;
    text-align: left;
  }

  /* The numbers take the grid's row explicitly, so the two overlap instead of stacking. */
  /* With the grid the field is the row: no lines above and below it. */
  .proof[data-grid] {
    column-gap: 24px;
    align-items: center;
  }

  /* Centred on the ink, measured in pixels: from the top of the digits to the bottom of the
     label's descenders, the same distance to the grid's edge above and below. */
  .proof[data-grid] .proof__item {
    grid-row: 1;
    padding: 0 12px 1px;
  }

  .proof[data-grid] .proof__label {
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 1.2px;
  }

  .proof[data-grid] .proof__item:nth-of-type(1) { grid-column: 1; }
  .proof[data-grid] .proof__item:nth-of-type(2) { grid-column: 2; }
  .proof[data-grid] .proof__item:nth-of-type(3) { grid-column: 3; }
  .proof[data-grid] .proof__item:nth-of-type(4) { grid-column: 4; }

  .activity {
    position: static;
    grid-area: 1 / 1 / 2 / -1;
    /* The field is 134px tall, about the height of a year on GitHub. */
    height: 134px;
  }
}

/* ---------- case cards ---------- */

.cases {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 24px;
}

.case {
  display: flex;
  flex-direction: column;
  gap: 18px;
  padding: 16px;
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  transition: border-color 200ms ease, transform 200ms ease;
}

.case:hover {
  border-color: var(--line-2);
  transform: translateY(-2px);
}

.case__media {
  display: block;
  aspect-ratio: 16 / 10;
  overflow: hidden;
  border-radius: var(--radius-s);
  background: var(--bg-3);
  border: 1px solid var(--line);
}

.case__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top;
  transition: transform 700ms cubic-bezier(0.2, 0.7, 0.2, 1);
}

.case:hover .case__img {
  transform: scale(1.03);
}

.case__blank {
  display: block;
  height: 100%;
}

.case__body {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 0 4px 6px;
}

.case__meta {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 12px;
  font-size: 13px;
  color: var(--muted);
}

.case__client {
  font-weight: 600;
  color: var(--text);
}

.case__headline {
  font-family: var(--display);
  font-weight: 700;
  font-size: 22px;
  line-height: 1.15;
  letter-spacing: -0.33px;
}

.case__title {
  text-decoration: none;
}

.case__title:hover {
  text-decoration: underline;
  text-underline-offset: 4px;
}

.case__summary {
  font-size: 15px;
  color: var(--text-2);
}

.case__points {
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-size: 14px;
  color: var(--text-2);
}

.case__point {
  display: flex;
  gap: 10px;
}

.case__point::before {
  content: '';
  flex: none;
  width: 6px;
  height: 6px;
  margin-top: 8px;
  border-radius: 50%;
  background: var(--hue);
}

.case__link {
  align-self: flex-start;
  margin-top: auto;
  font-size: 14px;
  font-weight: 500;
  text-decoration: none;
  border-bottom: 1px solid var(--line-2);
  padding-bottom: 2px;
}

.case__link:hover {
  border-bottom-color: var(--text);
}

/* On a phone the home page shows two cases; the rest are one tap away on /work. */
.cases[data-short] .case:nth-child(n + 3) {
  display: none;
}

@media (min-width: 750px) {
  .cases {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .cases[data-short] .case:nth-child(n + 3) {
    display: flex;
  }
}

@media (min-width: 1800px) {
  .cases {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

/* ---------- services ---------- */

.services {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 14px;
}

.service {
  display: flex;
  flex-direction: column;
  gap: 10px;
  height: 100%;
  padding: 22px 22px 20px;
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  text-decoration: none;
  transition: border-color 200ms ease, transform 200ms ease;
}

.service:hover {
  border-color: var(--line-2);
  transform: translateY(-2px);
}

.service__name {
  font-family: var(--display);
  font-weight: 700;
  font-size: 20px;
  line-height: 1.15;
  letter-spacing: -0.2px;
}

.service__text {
  font-size: 15px;
  color: var(--text-2);
  flex: 1;
}

.service__more {
  font-size: 18px;
  color: var(--muted);
  transition: transform 200ms ease, color 200ms ease;
}

.service:hover .service__more {
  transform: translateX(4px);
  color: var(--text);
}

@media (min-width: 750px) {
  .services {
    grid-template-columns: repeat(6, minmax(0, 1fr));
  }

  .services__item {
    grid-column: span 3;
  }

  .services__item:nth-child(n + 3) {
    grid-column: span 2;
  }
}

/* ---------- steps ---------- */

.steps {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 24px;
  counter-reset: step;
}

/* A card like every other block on the page, instead of a bare column of text. */
.step {
  display: flex;
  flex-direction: column;
  gap: 8px;
  height: 100%;
  padding: 22px 22px 20px;
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

.step__num {
  font-family: var(--display);
  font-weight: 700;
  font-size: 14px;
  color: var(--hue);
  font-variant-numeric: tabular-nums;
}

.step__title {
  font-family: var(--display);
  font-weight: 700;
  font-size: 20px;
  letter-spacing: -0.2px;
}

.step__text {
  font-size: 15px;
  color: var(--text-2);
}

@media (min-width: 750px) {
  .steps {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

/* ---------- store wall ---------- */

.wall {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 24px;
}

.wall__tools {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  width: 100%;
}

.seg {
  display: inline-flex;
  border: 1px solid var(--line-2);
  border-radius: var(--radius-s);
  overflow: hidden;
  background: var(--bg-2);
}

.seg__btn {
  padding: 8px 12px;
  font-size: 14px;
  color: var(--muted);
  border-right: 1px solid var(--line-2);
}

.seg__btn:last-child {
  border-right: 0;
}

.seg__btn[data-active] {
  background: var(--bg-3);
  color: var(--text);
}

.wall__search {
  font: inherit;
  font-size: 14px;
  color: var(--text);
  background: var(--bg-2);
  border: 1px solid var(--line-2);
  border-radius: var(--radius-s);
  padding: 8px 12px;
  min-width: 240px;
  flex: 1;
}

.wall__search::placeholder {
  color: var(--muted);
}

.wall__empty {
  display: none;
  color: var(--muted);
}

.wall__empty[data-show] {
  display: block;
}

.wall__list {
  width: 100%;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
}

.wall__item {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 14px 12px;
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  transition: border-color 200ms ease;
}

.wall__item:hover {
  border-color: var(--line-2);
}

.wall[data-collapsed] .wall__item[data-extra] {
  display: none;
}

.wall__item[data-hidden] {
  display: none;
}

.wall__name {
  font-family: var(--display);
  font-weight: 700;
  font-size: 19px;
  line-height: 1.05;
  letter-spacing: -0.38px;
  color: var(--hue);
  text-decoration: none;
  overflow-wrap: anywhere;
}

.wall__name:hover {
  text-decoration: underline;
  text-underline-offset: 3px;
}

.wall__name[data-offline] {
  color: var(--muted);
}

.wall__item[data-app] .wall__name {
  font-size: 17px;
  letter-spacing: -0.34px;
}

.wall__meta {
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-size: 12px;
  color: var(--muted);
}

.wall__domain {
  overflow-wrap: anywhere;
}

.wall__stats {
  color: var(--text-2);
  font-variant-numeric: tabular-nums;
}

.wall__count {
  text-align: left;
  color: var(--text-2);
  text-decoration: none;
  font-variant-numeric: tabular-nums;
}

.wall__count:hover {
  color: var(--text);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.wall__media {
  display: block;
  margin-top: 8px;
  text-decoration: none;
  aspect-ratio: 16 / 10;
  overflow: hidden;
  border-radius: var(--radius-s);
  border: 1px solid var(--line);
  background: var(--bg-3);
}

.wall__shot {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top;
  transition: transform 600ms cubic-bezier(0.2, 0.7, 0.2, 1);
}

.wall__item:hover .wall__shot {
  transform: scale(1.03);
}

.wall__none {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  padding: 12px;
  text-align: center;
  font-size: 12px;
  color: var(--muted);
}

.wall__projects {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding-top: 6px;
}

.wall__link {
  display: flex;
  align-items: baseline;
  gap: 6px;
  padding: 4px 6px;
  border-radius: var(--radius-s);
  font-size: 13px;
  color: var(--text-2);
  text-decoration: none;
  transition: background 120ms ease, color 120ms ease;
}

.wall__link:hover {
  background: var(--bg-3);
  color: var(--text);
}

.wall__repo {
  min-width: 0;
  overflow-wrap: anywhere;
}

.wall__feat {
  flex: 1;
  font-size: 11px;
  color: var(--muted);
}

.wall__about {
  padding-top: 8px;
  font-size: 13px;
  color: var(--text-2);
}

.wall__demo {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 4px;
  padding-top: 8px;
  font-size: 13px;
}

.wall__try {
  color: var(--text);
  text-decoration-color: var(--line-2);
  text-underline-offset: 3px;
}

.wall__try:hover {
  text-decoration-color: var(--text);
}

.wall__password {
  font-size: 12px;
  color: var(--muted);
}

.wall__years {
  margin-top: auto;
  padding-top: 12px;
  font-size: 12px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

.wall__num {
  display: none;
  font-size: 12px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

.wall__more {
  display: none;
}

.wall[data-js] .wall__more {
  display: inline-flex;
}

.wall__more[data-hidden] {
  display: none;
}

@media (min-width: 750px) {
  .wall__list {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 14px;
  }

  .wall__item {
    padding: 18px 16px 16px;
  }

  .wall__name {
    font-size: 22px;
    letter-spacing: -0.44px;
  }

  .wall__item[data-app] .wall__name {
    font-size: 19px;
    letter-spacing: -0.38px;
  }

  .wall__meta {
    font-size: 13px;
  }

  .wall__num {
    display: inline;
  }
}

/* From 900px the rail takes its column, so the wall starts counting again. Above
   that a column is added wherever a card would otherwise grow past 330px. */
@media (min-width: 900px) {
  .wall__list {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 1100px) {
  .wall__list {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

@media (min-width: 1350px) {
  .wall__list {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

@media (min-width: 1740px) {
  .wall__list {
    grid-template-columns: repeat(5, minmax(0, 1fr));
  }
}

/* Big screens: the rail, the gutters, the gaps and every padding step up, and the
   wall drops a column so the cards grow with them instead of against them. */
@media (min-width: 1800px) {
  :root {
    --gutter: 56px;
    --rail: 420px;
    --head: 1360px;
    --measure: 720px;
    --footer-h: 74px;
  }

  .wall__list {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 20px;
  }

  .wall__item {
    padding: 22px 20px 20px;
  }

  .wall__tools {
    gap: 14px;
  }

  .seg__btn,
  .wall__search {
    padding: 11px 16px;
  }

  .section__head {
    padding-bottom: 36px;
  }

  .rail__inner {
    gap: 28px;
    padding: 36px var(--gutter) 32px;
  }
}

@media (min-width: 1860px) {
  .wall__list {
    grid-template-columns: repeat(5, minmax(0, 1fr));
  }
}

@media (min-width: 2200px) {
  :root {
    --gutter: 72px;
    --rail: 480px;
    --head: 1560px;
    --measure: 780px;
    --footer-h: 78px;
  }

  .wall__list {
    gap: 24px;
  }

  .wall__item {
    padding: 26px 24px 24px;
  }

  .wall__tools {
    gap: 16px;
  }

  .seg__btn,
  .wall__search {
    padding: 13px 20px;
  }

  .section__head {
    padding-bottom: 44px;
  }

  .rail__inner {
    gap: 32px;
    padding: 44px var(--gutter) 40px;
  }
}

@media (min-width: 2310px) {
  .wall__list {
    grid-template-columns: repeat(6, minmax(0, 1fr));
  }
}

@media (min-width: 2670px) {
  .wall__list {
    grid-template-columns: repeat(7, minmax(0, 1fr));
  }
}

/* The wall on the home page is a taste of the work, not the whole ledger: fewer
   columns, so every card is large enough to read the preview. */
@media (min-width: 750px) {
  .wall[data-big] .wall__list {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 1350px) {
  .wall[data-big] .wall__list {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

@media (min-width: 1900px) {
  .wall[data-big] .wall__list {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

@media (min-width: 2400px) {
  .wall[data-big] .wall__list {
    grid-template-columns: repeat(5, minmax(0, 1fr));
  }
}

/* ---------- about ---------- */

.about {
  display: flex;
  flex-direction: column;
}

.about__text {
  display: flex;
  flex-direction: column;
  gap: 16px;
  max-width: var(--measure);
}

.about__p {
  font-size: 17px;
  color: var(--text-2);
}

.about__fine {
  font-size: 13px;
  color: var(--muted);
}

.about__link {
  font-size: 14px;
  color: var(--text-2);
}

/* On a wide screen a single reading column leaves half the page empty: the text
   runs in two columns instead, each still no wider than comfortable. */
@media (min-width: 1350px) {
  /* These blocks are narrower than the wall above them, so they sit in the middle
     of the page rather than hugging its left edge. */
  .about {
    max-width: calc(var(--measure) * 2 + 56px);
    margin-inline: auto;
  }

  .about__text {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 16px 56px;
    max-width: none;
  }

  .about__text .section__title,
  .about__fine,
  .about__links {
    grid-column: 1 / -1;
  }
}

/* ---------- panel ---------- */

/* The closing blocks share one framed container, so they line up on the same
   edges instead of each floating at its own width. */
.panel {
  display: flex;
  flex-direction: column;
  gap: clamp(40px, 5vw, 80px);
  max-width: var(--head);
  margin-inline: auto;
  padding: clamp(24px, 3vw, 56px);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

.panel__block {
  display: flex;
  flex-direction: column;
}

.panel .about,
.panel .faq,
.panel .contact {
  max-width: none;
  margin-inline: 0;
}

.panel .contact {
  padding-top: 0;
}

/* ---------- faq ---------- */

.faq {
  display: flex;
  flex-direction: column;
  gap: 24px;
  max-width: 820px;
}

.faq__title {
  font-family: var(--display);
  font-weight: 700;
  font-size: 32px;
  letter-spacing: -0.64px;
  line-height: 1.05;
}

.faq__list {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

/* Each question is a card of its own, the same shape as the service cards. */
.faq__item {
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  transition: border-color 200ms ease;
}

.faq__item:hover,
.faq__item[open] {
  border-color: var(--line-2);
}

.faq__q {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
  padding: 18px 22px;
  font-size: 17px;
  font-weight: 500;
  cursor: pointer;
  list-style: none;
}

.faq__q::-webkit-details-marker {
  display: none;
}

.faq__q::after {
  content: '+';
  flex: none;
  font-family: var(--display);
  font-size: 22px;
  color: var(--muted);
  transition: transform 200ms ease;
}

.faq__item[open] .faq__q::after {
  transform: rotate(45deg);
}

.faq__a {
  padding: 0 22px 20px;
  font-size: 16px;
  color: var(--text-2);
  max-width: var(--measure);
}

@media (min-width: 900px) {
  .faq__title {
    font-size: 40px;
    letter-spacing: -0.8px;
  }
}

@media (min-width: 1350px) {
  .faq {
    max-width: var(--head);
    margin-inline: auto;
  }
}

/* ---------- contact ---------- */

.contact {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 32px;
  padding: 32px 0 0;
  max-width: var(--head);
}

.contact__side {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.contact__note {
  font-size: 16px;
  color: var(--text-2);
  max-width: 420px;
}

.contact__email {
  align-self: flex-start;
  font-family: var(--display);
  font-weight: 600;
  font-size: 18px;
  text-decoration: none;
  border-bottom: 1px solid var(--line-2);
  padding-bottom: 2px;
}

.contact__email:hover {
  border-bottom-color: var(--text);
}

.contact__form {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 22px;
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

.contact__row {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 14px;
}

.contact__trap {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  opacity: 0;
}

.contact__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px;
}

.contact__status {
  display: none;
  font-size: 14px;
}

.contact__status[data-show] {
  display: inline;
}

.contact__status[data-status='ok'] {
  color: var(--text-2);
}

.contact__status[data-status='err'] {
  color: #c0392b;
}

@media (min-width: 750px) {
  .contact__row {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 900px) {
  .contact {
    grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr);
    align-items: center;
    gap: 56px;
    margin-inline: auto;
  }
}

/* ---------- fields ---------- */

.field {
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-size: 13px;
  color: var(--muted);
}

.field__label {
  display: block;
}

.field__input,
.field__textarea,
.field__select {
  font: inherit;
  font-size: 15px;
  color: var(--text);
  background: var(--bg);
  border: 1px solid var(--line-2);
  border-radius: var(--radius-s);
  padding: 10px 12px;
  width: 100%;
}

.field__input:focus,
.field__textarea:focus,
.field__select:focus {
  outline: 2px solid var(--hue);
  outline-offset: 0;
  border-color: transparent;
}

.field__textarea {
  resize: vertical;
  font-family: var(--sans);
}

.field__code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12px;
}

/* ---------- cta band ---------- */

.cta {
  display: flex;
  flex-direction: column;
  gap: 20px;
  padding: 32px 24px;
  background: var(--bg-3);
  border-radius: var(--radius);
}

.cta__title {
  font-family: var(--display);
  font-weight: 700;
  font-size: 28px;
  letter-spacing: -0.56px;
  line-height: 1.1;
}

.cta__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 16px;
}

.cta__mail {
  font-size: 15px;
  color: var(--text-2);
}

@media (min-width: 900px) {
  .cta {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    padding: 40px 48px;
  }

  .cta__title {
    font-size: 34px;
    letter-spacing: -0.68px;
  }
}

/* ---------- breadcrumbs, intro ---------- */

.crumbs {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  font-size: 13px;
  color: var(--muted);
  padding-bottom: 12px;
}

.crumbs__link {
  color: var(--muted);
  text-decoration: none;
}

.crumbs__link:hover {
  color: var(--text);
}

.crumbs__current {
  color: var(--text-2);
}

.intro {
  display: flex;
  flex-direction: column;
  gap: 18px;
  max-width: 820px;
}

.intro__kicker {
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.52px;
  text-transform: uppercase;
  color: var(--muted);
}

.intro__title {
  font-family: var(--display);
  font-weight: 800;
  font-size: clamp(34px, 6vw, 60px);
  line-height: 1;
  letter-spacing: calc(clamp(34px, 6vw, 60px) * -0.03);
}

.intro__text {
  font-size: 18px;
  color: var(--text-2);
}

/* ---------- deliverables ---------- */

.deliverables {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 12px;
}

.deliverables__item {
  display: flex;
  gap: 12px;
  padding: 16px 18px;
  font-size: 15px;
  color: var(--text-2);
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-s);
}

.deliverables__item::before {
  content: '';
  flex: none;
  width: 8px;
  height: 8px;
  margin-top: 8px;
  border-radius: 50%;
  background: var(--hue);
}

@media (min-width: 750px) {
  .deliverables {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* ---------- drawer with the project record ---------- */

.drawer {
  position: fixed;
  inset: 0;
  z-index: 30;
  visibility: hidden;
}

.drawer[data-show] {
  visibility: visible;
}

.drawer__backdrop {
  display: block;
  position: absolute;
  inset: 0;
  background: rgba(8, 10, 13, 0.55);
  animation: fade 200ms ease-out both;
}

.drawer__panel {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: min(680px, 100%);
  background: var(--bg);
  border-left: 1px solid var(--line-2);
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: var(--muted) transparent;
  padding: 24px var(--gutter) 48px;
  animation: slide 320ms cubic-bezier(0.2, 0.7, 0.2, 1) both;
}

@keyframes fade {
  from {
    opacity: 0;
  }
}

@keyframes slide {
  from {
    transform: translateX(24px);
    opacity: 0;
  }
}

.record {
  display: flex;
  flex-direction: column;
  gap: 24px;
}

.record__head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 16px;
}

.record__titles {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.record__kind {
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.48px;
  text-transform: uppercase;
  color: var(--hue);
}

.record__title {
  font-family: var(--display);
  font-weight: 800;
  font-size: 28px;
  line-height: 1.05;
  letter-spacing: -0.56px;
}

.record__sub {
  font-size: 14px;
  color: var(--muted);
}

.record__close {
  flex: none;
  font-size: 14px;
  color: var(--muted);
  text-decoration: none;
  padding: 4px 0;
  border-bottom: 1px solid var(--line-2);
}

.record__close:hover {
  color: var(--text);
  border-bottom-color: var(--text);
}

.record__desc {
  font-size: 16px;
  color: var(--text-2);
}

.record__points {
  display: flex;
  flex-direction: column;
  gap: 8px;
  font-size: 14px;
  color: var(--text-2);
}

.record__point {
  display: flex;
  gap: 10px;
}

.record__point::before {
  content: '';
  flex: none;
  width: 6px;
  height: 6px;
  margin-top: 7px;
  border-radius: 50%;
  background: var(--hue);
}

.record__shot {
  width: 100%;
  border-radius: var(--radius);
  border: 1px solid var(--line);
  background: var(--bg-3);
}

.record__h3 {
  font-family: var(--display);
  font-weight: 700;
  font-size: 18px;
  letter-spacing: -0.18px;
  padding-top: 8px;
}

.record__empty {
  color: var(--muted);
  font-size: 14px;
}

.record__months {
  display: flex;
  flex-direction: column;
  gap: 24px;
}

.record__cta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px 16px;
  padding: 20px;
  background: var(--bg-3);
  border-radius: var(--radius);
}

.record__ask {
  width: 100%;
  font-family: var(--display);
  font-weight: 700;
  font-size: 18px;
}

.record__mail {
  font-size: 14px;
  color: var(--text-2);
}

@media (min-width: 750px) {
  .drawer__panel {
    padding: 28px 32px 56px;
  }

  .record__title {
    font-size: 34px;
    letter-spacing: -0.68px;
  }
}

.facts {
  display: flex;
  flex-direction: column;
  border-top: 1px solid var(--line-2);
  font-size: 15px;
}

.facts__row {
  display: grid;
  grid-template-columns: 100px minmax(0, 1fr);
  gap: 12px;
  padding: 12px 0;
  border-bottom: 1px solid var(--line);
}

.facts__key {
  color: var(--muted);
  font-size: 13px;
  padding-top: 2px;
}

.facts__value {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 6px 10px;
  color: var(--text-2);
}

.facts__value[data-note] {
  font-size: 14px;
  color: var(--muted);
}

.facts__handles {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 6px;
}

.facts__handle {
  font-size: 12px;
  padding: 2px 8px;
  border: 1px solid var(--line-2);
  border-radius: 999px;
  text-decoration: none;
  color: var(--text-2);
}

.facts__handle:hover {
  color: var(--text);
  border-color: var(--text-2);
}

.facts__link {
  color: var(--text);
  text-decoration-color: var(--line-2);
  text-underline-offset: 3px;
}

.facts__link:hover {
  text-decoration-color: var(--text);
}

/* What a project built that also runs in the demo: one item per thing, its picture on the
   client's live store and its picture in the demo, each with its link. */

.built {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.built__item {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 12px;
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

.built__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 2px 8px;
}

.built__kind {
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.44px;
  text-transform: uppercase;
  color: var(--muted);
}

.built__name {
  font-size: 15px;
  font-weight: 500;
  overflow-wrap: anywhere;
}

.built__sides {
  display: grid;
  gap: 12px;
}

.built__side {
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 0;
  color: inherit;
  text-decoration: none;
}

.built__shot {
  display: block;
}

.built__img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  object-position: top;
  border: 1px solid var(--line);
  border-radius: var(--radius-s);
  background: var(--bg-3);
}

.built__links {
  display: flex;
  flex-wrap: wrap;
  gap: 2px 10px;
  font-size: 14px;
}

.built__label {
  font-size: 14px;
  color: var(--muted);
}

.built__link {
  font-size: 14px;
  color: var(--text);
  text-decoration: underline;
  text-decoration-color: var(--line-2);
  text-underline-offset: 3px;
}

.built__side:hover .built__link,
.built__link:hover {
  text-decoration-color: var(--text);
}

@media (min-width: 750px) {
  .built__sides {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* The commit-by-commit record, closed until asked for. */

.worklog {
  border-top: 1px solid var(--line-2);
  border-bottom: 1px solid var(--line-2);
}

.worklog__summary {
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 14px 0;
  cursor: pointer;
  list-style: none;
}

.worklog__summary::-webkit-details-marker {
  display: none;
}

.worklog__summary::after {
  content: "+";
  margin-left: auto;
  font-size: 18px;
  line-height: 1;
  color: var(--muted);
}

.worklog[open] .worklog__summary::after {
  content: "−";
}

.worklog__title {
  font-family: var(--display);
  font-weight: 700;
  font-size: 18px;
  letter-spacing: -0.18px;
}

.worklog__note {
  font-size: 13px;
  color: var(--muted);
}

.worklog[open] .record__months {
  padding-bottom: 16px;
}

.facts__password {
  font-size: 13px;
  color: var(--muted);
}

.facts__code {
  font-family: inherit;
  color: var(--text-2);
}

.month {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.month__label {
  font-family: var(--display);
  font-weight: 700;
  font-size: 14px;
  color: var(--muted);
}

.feats {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.feat {
  display: grid;
  grid-template-columns: 56px minmax(0, 1fr);
  gap: 12px;
  padding-left: 10px;
  border-left: 2px solid var(--line);
}

.feat[data-off] {
  border-left-color: var(--hue);
}

.feat__date {
  font-size: 12px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  padding-top: 2px;
}

.feat__body {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
}

.feat__title {
  font-size: 14px;
  line-height: 1.4;
}

.feat__branch {
  font-size: 12px;
  color: var(--hue);
}

.feat__files {
  font-size: 12px;
  color: var(--muted);
  overflow-wrap: anywhere;
  white-space: pre-wrap;
}

.feat__demo {
  align-self: flex-start;
  font-size: 12px;
  font-weight: 500;
  color: var(--text);
  text-decoration: none;
  border-bottom: 1px solid var(--line-2);
}

.feat__demo:hover {
  border-bottom-color: var(--text);
}

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

.footer {
  margin-top: 64px;
}

.footer__inner {
  padding: 20px 0 24px;
}

/* On a phone the footer is one full-width button; the name is in the bar at the top,
   the profiles are in the menu and by the contact form. */
.footer__inner {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  align-items: center;
  gap: 12px 16px;
}

.footer__cta {
  grid-row: 1;
  grid-column: 1;
  justify-self: stretch;
  justify-content: center;
  text-transform: uppercase;
  letter-spacing: 0.6px;
}

.footer__name {
  display: none;
  font-family: var(--display);
  font-weight: 700;
  text-transform: uppercase;
  color: var(--text);
}

/* On a phone "All projects" lives in the menu. */
.footer__links {
  display: none;
  align-items: center;
  justify-content: flex-end;
  gap: 16px;
}

/* On /work there is no link, and an empty row would still take the gap. */
.footer__links:empty {
  display: none;
}

.footer__link {
  font-size: 14px;
  color: var(--text-2);
  text-decoration: none;
}

.topbar {
  padding-top: 16px;
}

.topbar__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: 10px 24px;
}

.topbar__lead {
  order: 2;
  width: 100%;
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.52px;
  text-transform: uppercase;
  color: var(--muted);
}

/* On a phone the footer stays on the bottom edge too, and the content keeps its
   height free; site.js measures the footer into --footer-h. */
.page__main:not([data-shell]) .footer {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 5;
  margin-top: 0;
  background: var(--bg);
}

.page__main:not([data-shell]) .footer__inner {
  padding: 12px 0 calc(12px + env(safe-area-inset-bottom));
}

.page__main:not([data-shell]) .main {
  padding-bottom: calc(var(--footer-h) + var(--gutter));
}

@media (min-width: 900px) {
  /* The switches centre on the first line of text, which starts one gutter down. */
  .topbar {
    padding-top: calc(var(--top-row) - 7px);
  }

  /* One row: the line of text on one edge, the switches on the other. */
  .topbar__inner {
    flex-wrap: nowrap;
    justify-content: space-between;
  }

  .topbar__lead {
    order: 0;
    width: auto;
  }

  /* On a page that scrolls the whole row rides along — the line of text and the
     switches together, on the page's own background — and steps out of the way
     while the reader is going down. */
  .page__main:not([data-shell]) .topbar {
    position: sticky;
    top: 0;
    z-index: 6;
    padding-bottom: calc(var(--top-row) - 7px);
    background: var(--bg);
    transition: transform 260ms cubic-bezier(0.2, 0.7, 0.2, 1), opacity 200ms ease;
  }

  /* The bar already carries the top gutter for these pages. */
  .page__main:not([data-shell]) .section[data-first],
  .page__main:not([data-shell]) .hero {
    padding-top: 0;
  }

  /* The page opens on the hero alone: it holds the whole room, with the copy at
     the top and the numbers row on the bottom edge of it. */
  .page__main:not([data-shell]) .hero {
    display: flex;
    flex-direction: column;
    min-height: var(--fold);
  }

  .page__main:not([data-shell]) .hero .wrap {
    flex: 1;
    display: flex;
    flex-direction: column;
  }

  .page__main:not([data-shell]) .hero__inner {
    flex: 1;
  }

  .page__main:not([data-shell]) .topbar[data-away] {
    transform: translateY(-160%);
    opacity: 0;
  }

  /* The footer stays on the bottom edge of the same page, and the content keeps
     its height free so nothing ends up hidden behind it. */
  .page__main:not([data-shell]) .footer__inner {
    padding: 16px 0 18px;
  }

  .page__main:not([data-shell]) .footer {
    position: fixed;
    left: var(--rail);
    right: 0;
    bottom: 0;
    z-index: 4;
    margin-top: 0;
    background: var(--bg);
  }

  .page__main:not([data-shell]) .main {
    padding-bottom: calc(var(--footer-h) + var(--gutter));
  }
}

.social {
  display: flex;
  align-items: center;
  gap: 8px;
}

.social__link {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px;
  border: 1px solid var(--line);
  border-radius: var(--radius-s);
  color: var(--text-2);
  text-decoration: none;
  transition: color 150ms ease, border-color 150ms ease;
}

.social__link:hover {
  color: var(--text);
  border-color: var(--line-2);
}

.social__icon {
  display: block;
  width: 18px;
  height: 18px;
}

/* A finger's target: 18px icon + 12px padding each side + the border = 44px. */
.social[data-big] {
  gap: 12px;
}

.social[data-big] .social__link {
  padding: 12px;
}

/* The phone footer is the button alone, so nothing beside it takes a stray tap. */
.social[data-desk] {
  display: none;
}

@media (min-width: 900px) {
  .social[data-desk] {
    display: flex;
  }
}

.social__icon svg {
  display: block;
  width: 100%;
  height: 100%;
}

.social__text {
  font-size: 14px;
}

.footer__link:hover {
  color: var(--text);
  text-decoration: underline;
  text-underline-offset: 3px;
}

@media (min-width: 900px) {
  /* A line above the footer only beside the rail; on a phone it sits on the edge alone.
     The line belongs to the content, not to the column: it starts and ends where the
     cards do, including the lane the list keeps for its scrollbar. */
  .footer__inner {
    grid-template-columns: 1fr auto 1fr;
    gap: 24px;
    border-top: 1px solid var(--line);
  }

  .footer__name {
    display: block;
  }

  /* The rail carries the button from here on. */
  .footer__cta {
    display: none;
  }

  .footer__links {
    display: flex;
  }
}

@media (min-width: 1800px) {
  .footer__inner {
    padding: 28px 0 32px;
  }
}

@media (min-width: 2200px) {
  .footer__inner {
    padding: 34px 0 40px;
  }
}

/* ---------- admin preview of the numbers row ---------- */

.preview {
  margin: 0;
  padding: 0 12px;
  background: var(--bg);
  overflow: hidden;
}

/* The row alone, without the room the hero keeps above it. */
.preview__row .proof {
  margin-top: 0;
}

/* ---------- motion preferences ---------- */

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  .hero__line,
  .hero__lede,
  .hero__actions,
  .hero__shot,
  .activity__cell,
  .drawer__backdrop,
  .drawer__panel {
    animation: none;
  }

  html[data-js] [data-reveal] {
    transition: none;
  }

  .rail[data-open] .rail__nav {
    transition: none;
  }
}

/* ---------- type on large screens ---------- */

/* Past this width the page is not a big version of the small one: the whole type
   ramp steps up with it, or the text reads as a small page stretched wide. */
@media (min-width: 1800px) {
  .section__title {
    font-size: 48px;
    letter-spacing: -0.96px;
  }

  .section__title[data-small] {
    font-size: 32px;
    letter-spacing: -0.64px;
  }

  .section__note {
    font-size: 17px;
  }

  .hero__title {
    font-size: calc(clamp(34px, min(5.4vw, 6.4vh), 72px) * var(--hero-fit));
    letter-spacing: calc(clamp(34px, min(5.4vw, 6.4vh), 72px) * var(--hero-fit) * -0.03);
  }

  .hero__lede {
    font-size: calc(clamp(16px, 2.2vh, 22px) * var(--hero-fit));
  }

  .case__headline {
    font-size: 25px;
    letter-spacing: -0.38px;
  }

  .case__summary {
    font-size: 16px;
  }

  .service__name,
  .step__title {
    font-size: 22px;
    letter-spacing: -0.22px;
  }

  .service__text,
  .step__text {
    font-size: 16px;
  }

  .wall__name {
    font-size: 21px;
    letter-spacing: -0.42px;
  }

  .wall__item[data-app] .wall__name {
    font-size: 19px;
    letter-spacing: -0.38px;
  }

  .wall__meta {
    font-size: 14px;
  }

  .about__p {
    font-size: 19px;
  }

  .about__fine {
    font-size: 14px;
  }

  .about__link {
    font-size: 15px;
  }

  .faq__title {
    font-size: 38px;
    letter-spacing: -0.76px;
  }

  .faq__q {
    font-size: 18px;
  }

  .faq__a {
    font-size: 17px;
  }

  .contact__note {
    font-size: 17px;
  }

  .rail__name {
    font-size: 22px;
    letter-spacing: -0.44px;
  }

  .rail__role {
    font-size: 14px;
  }

  .rail__link {
    font-size: 16px;
  }
}

@media (min-width: 2200px) {
  .section__title {
    font-size: 56px;
    letter-spacing: -1.12px;
  }

  .section__title[data-small] {
    font-size: 36px;
    letter-spacing: -0.72px;
  }

  .section__note {
    font-size: 18px;
  }

  .hero__title {
    font-size: calc(clamp(34px, min(5.4vw, 6.4vh), 84px) * var(--hero-fit));
    letter-spacing: calc(clamp(34px, min(5.4vw, 6.4vh), 84px) * var(--hero-fit) * -0.03);
  }

  .hero__lede {
    font-size: calc(clamp(16px, 2.2vh, 24px) * var(--hero-fit));
  }

  .case__headline {
    font-size: 28px;
    letter-spacing: -0.42px;
  }

  .case__summary {
    font-size: 17px;
  }

  .service__name,
  .step__title {
    font-size: 24px;
    letter-spacing: -0.24px;
  }

  .service__text,
  .step__text {
    font-size: 17px;
  }

  .wall__name {
    font-size: 23px;
    letter-spacing: -0.46px;
  }

  .wall__item[data-app] .wall__name {
    font-size: 20px;
    letter-spacing: -0.4px;
  }

  .wall__meta {
    font-size: 15px;
  }

  .about__p {
    font-size: 20px;
  }

  .about__fine {
    font-size: 15px;
  }

  .about__link {
    font-size: 16px;
  }

  .faq__title {
    font-size: 44px;
    letter-spacing: -0.88px;
  }

  .faq__q {
    font-size: 19px;
  }

  .faq__a {
    font-size: 18px;
  }

  .contact__note {
    font-size: 18px;
  }

  .rail__name {
    font-size: 24px;
    letter-spacing: -0.48px;
  }

  .rail__role {
    font-size: 15px;
  }

  .rail__link {
    font-size: 17px;
  }
}

/* ---------- app walkthrough (simple-slider) ---------- */

.simple-slider {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 8px;
  min-width: 0;
}

.simple-slider__list {
  display: flex;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scrollbar-width: none;
}

.simple-slider__list::-webkit-scrollbar {
  display: none;
}

.simple-slider__slide {
  display: flex;
  flex-direction: column;
  gap: 8px;
  flex: 0 0 100%;
  scroll-snap-align: start;
  scroll-snap-stop: always;
  margin: 0;
  min-width: 0;
}

.simple-slider__img {
  width: 100%;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  object-position: top;
  border-radius: var(--radius-s);
  border: 1px solid var(--line);
  background: var(--bg-3);
  user-select: none;
}

/* Two lines always, so tiles in a row keep the same height whatever a caption says. */
.simple-slider__caption {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
  min-height: 36px;
  font-size: 13px;
  line-height: 1.4;
  color: var(--text-2);
}

.simple-slider__controls {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}

.simple-slider__dots {
  display: flex;
  gap: 6px;
}

.simple-slider__dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--line-2);
  transition: background 160ms ease;
}

.simple-slider__dot[data-active] {
  background: var(--hue);
}

.simple-slider__nav {
  display: flex;
  gap: 6px;
}

.simple-slider__arrow {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  border: 1px solid var(--line-2);
  color: var(--muted);
  opacity: 0.4;
  transition: opacity 160ms ease, color 160ms ease;
}

.simple-slider__arrow[data-active] {
  opacity: 1;
  color: var(--text-2);
}

.simple-slider__arrow[data-active]:hover {
  color: var(--text);
  border-color: var(--text-2);
}

.simple-slider__chevron {
  display: block;
  flex: none;
}

/* In the drawer there is room, so the caption runs its full length. */
.record .simple-slider__caption {
  -webkit-line-clamp: none;
  line-clamp: none;
  min-height: 0;
  font-size: 14px;
}

/* ---------- /demo: the demo store's features ---------- */

.demo-store {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px 18px;
}

.demo-store__password {
  font-size: 14px;
  color: var(--muted);
}

.demo-store__code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 14px;
  padding: 2px 8px;
  border: 1px solid var(--line-2);
  border-radius: var(--radius-s);
  color: var(--text);
}

.features {
  display: grid;
  gap: 16px;
}

.feature {
  display: grid;
  gap: 18px;
  padding: 16px;
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  scroll-margin-top: calc(var(--bar-h) + 16px);
}

.feature__body {
  display: flex;
  flex-direction: column;
  gap: 14px;
  min-width: 0;
}

.feature__title {
  font-family: var(--display);
  font-weight: 700;
  font-size: 24px;
  line-height: 1.15;
  letter-spacing: -0.36px;
}

.feature__summary {
  font-size: 16px;
  color: var(--text-2);
}

.feature__facts {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin: 0;
}

.feature__fact {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.feature__key {
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.48px;
  text-transform: uppercase;
  color: var(--muted);
}

.feature__value {
  margin: 0;
  font-size: 14px;
  line-height: 1.5;
  color: var(--text-2);
}

.feature__links {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px 18px;
  margin-top: auto;
}

.feature__record {
  font-size: 14px;
  font-weight: 500;
  text-decoration: none;
  border-bottom: 1px solid var(--line-2);
  padding-bottom: 2px;
}

.feature__record:hover {
  border-bottom-color: var(--text);
}

.feature__media {
  min-width: 0;
}

.feature__media .simple-slider {
  margin-top: 0;
}

/* There is room next to the text, so the caption runs its full length. */
.feature__media .simple-slider__caption {
  -webkit-line-clamp: none;
  line-clamp: none;
  min-height: 0;
}

.feature__empty {
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 16 / 10;
  padding: 16px;
  font-size: 14px;
  text-align: center;
  color: var(--muted);
  border: 1px dashed var(--line-2);
  border-radius: var(--radius-s);
}

@media (min-width: 900px) {
  .feature {
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
    gap: 28px;
    padding: 24px;
  }

  .feature__title {
    font-size: 28px;
    letter-spacing: -0.42px;
  }
}

/* A feature's walkthrough: numbered steps under the text and the slider. */

.feature__walk {
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-width: 0;
}

.feature__steps {
  display: grid;
  gap: 10px;
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: step;
}

.feature__step {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 14px;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--radius-s);
  counter-increment: step;
}

.feature__step::before {
  content: counter(step, decimal-leading-zero);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.48px;
  color: var(--muted);
}

.feature__name {
  font-size: 15px;
  font-weight: 500;
  line-height: 1.3;
}

.feature__text {
  font-size: 14px;
  line-height: 1.5;
  color: var(--text-2);
}

@media (min-width: 750px) {
  .feature__steps {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 900px) {
  .feature__walk {
    grid-column: 1 / -1;
  }
}

@media (min-width: 1200px) {
  .feature__steps {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

/* The theme's sections: small tiles, a screenshot with a name and one line of text. */

.tiles {
  display: grid;
  gap: 16px;
}

.features + .tiles {
  margin-top: 16px;
}

.tile {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 12px;
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  scroll-margin-top: calc(var(--bar-h) + 16px);
  transition: border-color 200ms ease;
}

.tile:hover {
  border-color: var(--line-2);
}

.tile__link {
  display: flex;
  flex-direction: column;
  gap: 12px;
  color: inherit;
  text-decoration: none;
}

.tile__img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  object-position: top;
  border: 1px solid var(--line);
  border-radius: var(--radius-s);
  background: var(--bg-3);
}

.tile__title {
  font-family: var(--display);
  font-weight: 700;
  font-size: 18px;
  line-height: 1.2;
  letter-spacing: -0.27px;
}

.tile__text {
  font-size: 14px;
  color: var(--text-2);
}

@media (min-width: 750px) {
  .tiles {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 1200px) {
  .tiles {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

/* "First built for <project>" under a feature or a tile, and the way back from a project's
   feature to the demo. */

.feature__from,
.tile__from {
  font-size: 13px;
  color: var(--muted);
}

.tile__from {
  margin-top: auto;
}

.from {
  color: var(--text-2);
  text-decoration: none;
  border-bottom: 1px solid var(--line-2);
}

.from:hover {
  border-bottom-color: var(--text);
}

/* The three teasers on the home page. */

.teasers {
  display: grid;
  gap: 16px;
}

.teaser {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 12px;
  color: inherit;
  text-decoration: none;
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  transition: border-color 200ms ease, transform 200ms ease;
}

.teaser:hover {
  border-color: var(--line-2);
  transform: translateY(-2px);
}

.teaser__img {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  object-position: top;
  border: 1px solid var(--line);
  border-radius: var(--radius-s);
  background: var(--bg-3);
}

.teaser__title {
  font-family: var(--display);
  font-weight: 700;
  font-size: 18px;
  line-height: 1.2;
  letter-spacing: -0.27px;
}

.teaser__text {
  font-size: 14px;
  color: var(--text-2);
}

@media (min-width: 750px) {
  .teasers {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

/* The password line under the links into the demo store. */
.feature__hint {
  font-size: 13px;
  color: var(--muted);
}

/* On desktop the slider fills the card's height next to the text: the screenshot grows,
   the caption and the controls stay at the bottom, no empty band under them. */
@media (min-width: 900px) {
  .feature__media,
  .feature__media .simple-slider,
  .feature__media .simple-slider__list,
  .feature__media .simple-slider__slide {
    display: flex;
    flex-direction: column;
    min-height: 0;
  }

  .feature__media .simple-slider {
    flex: 1 1 auto;
  }

  .feature__media .simple-slider__list {
    flex: 1 1 auto;
    flex-direction: row;
  }

  .feature__media .simple-slider__slide {
    flex: 0 0 100%;
  }

  .feature__media .simple-slider__img {
    flex: 1 1 auto;
    height: 0;
    min-height: 280px;
    aspect-ratio: auto;
  }

  /* A feature with a walkthrough has a long text: its screenshots keep their shape at the
     top of the card instead of being stretched and cropped at the sides. */
  .feature[data-walk] .feature__media {
    align-self: start;
  }

  .feature[data-walk] .feature__media .simple-slider__img {
    flex: none;
    height: auto;
    min-height: 0;
    aspect-ratio: 16 / 10;
  }
}

/* ---------- placeholder (site switched off in the admin) ---------- */

/* One centred column: the portrait with a pulsing "at work" dot, the name, then the admin's
   title and text. The amber glow behind the portrait is the only colour on the page. */
.soon {
  min-height: 100vh;
  display: flex;
  align-items: center;
  padding: 56px 0;
  background: radial-gradient(520px circle at 50% 32%, color-mix(in srgb, var(--hue) 16%, transparent), transparent 70%), var(--bg);
}

.soon__inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 32px;
  max-width: 960px;
  margin: 0 auto;
  text-align: center;
}

.soon__photo {
  position: relative;
  width: 168px;
}

.soon__portrait {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 5;
  object-fit: cover;
  border-radius: var(--radius);
  border: 1px solid var(--line);
  background: var(--bg-3);
  box-shadow: var(--shadow);
}

.soon__pulse {
  position: absolute;
  right: -7px;
  bottom: -7px;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--hue);
  border: 4px solid var(--bg);
}

.soon__pulse::after {
  content: '';
  position: absolute;
  inset: -4px;
  border-radius: 50%;
  border: 2px solid var(--hue);
  animation: soon-pulse 2.4s ease-out infinite;
}

@keyframes soon-pulse {
  from {
    transform: scale(1);
    opacity: 0.8;
  }
  to {
    transform: scale(2.2);
    opacity: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .soon__pulse::after {
    animation: none;
    opacity: 0;
  }
}

.soon__name {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
}

.soon__title {
  margin: 0;
  font-family: var(--display);
  font-weight: 700;
  font-size: 20px;
  letter-spacing: -0.4px;
  line-height: 1.1;
}

.soon__role {
  margin: 0;
  font-size: 14px;
  line-height: 1.3;
  color: var(--muted);
}

.soon__body {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 18px;
}

.soon__heading {
  margin: 0;
  font-family: var(--display);
  font-weight: 800;
  font-size: clamp(40px, 6.4vw, 84px);
  line-height: 1;
  letter-spacing: calc(clamp(40px, 6.4vw, 84px) * -0.03);
}

.soon__text {
  margin: 0;
  max-width: 520px;
  font-size: 17px;
  line-height: 1.55;
  color: var(--text-2);
}

@media (min-width: 900px) {
  .soon__inner {
    gap: 40px;
  }

  .soon__photo {
    width: 220px;
  }

  .soon__title {
    font-size: 24px;
    letter-spacing: -0.48px;
  }

  .soon__role {
    font-size: 15px;
  }

  .soon__text {
    font-size: 19px;
  }
}

/* ---------- /demo: the group filter ---------- */

.dgroups {
  padding-top: 40px;
}

.demo-nav {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.demo-nav__btn {
  display: inline-flex;
  align-items: baseline;
  gap: 8px;
  padding: 8px 14px;
  font-size: 14px;
  color: var(--muted);
  text-decoration: none;
  background: var(--bg-2);
  border: 1px solid var(--line-2);
  border-radius: var(--radius-s);
}

.demo-nav__btn:hover {
  color: var(--text);
}

.demo-nav__btn[data-active] {
  color: var(--text);
  background: var(--bg-3);
  border-color: var(--text-2);
}

.demo-nav__count {
  font-size: 12px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

/* The filter took the room above the first group. */
.section[data-group] {
  padding-top: 40px;
}

.section[data-group][data-hidden] {
  display: none;
}
