/* ==========================================================================
   Rens Designs — portfolio skeleton
   The idea: the site is a cutting mat, and the work lies on it as objects
   in their real shapes (a phone, a magazine, a photo print).

   1. Tokens   2. Base   3. Type   4. Header   5. Hero   6. Desk + pieces
   7. Paper sheet (about)   8. Tag (contact)   9. Footer
   10. Case study   11. Small screens
   ========================================================================== */

/* 1. Tokens --------------------------------------------------------------- */
:root {
  --mat: #1f5d48;
  --mat-line: rgba(255, 255, 255, 0.06);
  --mat-line-strong: rgba(255, 255, 255, 0.13);
  --chalk: #f4f1e8; /* text and marks drawn straight onto the mat */

  --paper: #f6f3ea;
  --kraft: #dcc79b;
  --tape: rgba(238, 225, 176, 0.82);
  --ink: #171613;
  --muted: #736f66;
  --line: rgba(23, 22, 19, 0.18);

  --font-display: "Familjen Grotesk", "Arial Narrow", sans-serif;
  --font-body: "Radio Canada", system-ui, sans-serif;
  --font-mono: "Courier Prime", "Courier New", monospace; /* typewriter, for labels */
  --font-hand: "Nanum Pen Script", "Segoe Print", cursive;

  --gutter: clamp(1rem, 4vw, 3.5rem);
  --section: clamp(4.5rem, 11vw, 10rem);
  --shadow: 0 1px 2px rgba(0, 0, 0, 0.3), 0 16px 28px -12px rgba(0, 0, 0, 0.55);
}

/* 2. Base ----------------------------------------------------------------- */
*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
}

body {
  margin: 0;
  /* Tilted pieces can poke past the edge; don't let that cause sideways scroll. */
  overflow-x: clip;
  /* Cutting-mat grid: fine lines every 40px, heavier ones every 200px. */
  background-color: var(--mat);
  background-image:
    linear-gradient(var(--mat-line-strong) 1px, transparent 1px),
    linear-gradient(90deg, var(--mat-line-strong) 1px, transparent 1px),
    linear-gradient(var(--mat-line) 1px, transparent 1px),
    linear-gradient(90deg, var(--mat-line) 1px, transparent 1px);
  background-size: 200px 200px, 200px 200px, 40px 40px, 40px 40px;
  color: var(--chalk);
  font-family: var(--font-body);
  font-size: 1.0625rem;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

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

a {
  color: inherit;
}

img,
video {
  display: block;
  max-width: 100%;
}

:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 4px;
}

.wrap {
  padding-inline: var(--gutter);
}

/* 3. Type ----------------------------------------------------------------- */
.mono {
  font-family: var(--font-mono);
  font-size: 0.8125rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

/* Handwritten notes. Better still: scan your own handwriting and use that. */
.hand {
  font-family: var(--font-hand);
  font-size: clamp(1.6rem, 2.5vw, 2.4rem);
  line-height: 0.95;
}

.link {
  text-decoration-thickness: 1px;
  text-underline-offset: 0.3em;
}

.link:hover {
  text-decoration-thickness: 2px;
}

/* A label with nowhere to go yet: still legible, plainly not clickable. */
.is-off {
  opacity: 0.45;
}

/* Stand-in for a real image. Swap each one for an <img> or <video>. */
.placeholder {
  display: grid;
  place-items: center;
  aspect-ratio: 4 / 3;
  padding: 0.75rem;
  border: 1px dashed currentColor;
  font-family: var(--font-mono);
  font-size: 0.8125rem;
  letter-spacing: 0.04em;
  text-align: center;
  text-transform: uppercase;
  opacity: 0.7;
}

.placeholder--wide {
  aspect-ratio: 16 / 9;
}

.placeholder--tall {
  aspect-ratio: 3 / 4;
}

/* 4. Header --------------------------------------------------------------- */
.site-header {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: baseline;
  gap: 1rem;
  padding: 1.5rem var(--gutter);
}

.wordmark {
  font-family: var(--font-display);
  font-size: 1.25rem;
  font-weight: 700;
  letter-spacing: -0.03em;
  text-decoration: none;
}

.page-name {
  opacity: 0.7;
}

.nav {
  display: flex;
  justify-content: flex-end;
  gap: clamp(1rem, 3vw, 2.25rem);
  margin: 0;
  padding: 0;
  list-style: none;
}

.nav a {
  text-decoration: none;
}

.nav a:hover {
  text-decoration: underline;
  text-underline-offset: 0.4em;
}

/* 5. Hero ----------------------------------------------------------------- */
.hero {
  padding-block: clamp(3.5rem, 10vw, 9rem) clamp(3rem, 7vw, 6rem);
}

.hero h1 {
  max-width: 16ch;
  font-family: var(--font-display);
  font-size: clamp(2.6rem, 7.6vw, 7.75rem);
  font-weight: 600;
  line-height: 1.1;
  letter-spacing: -0.025em;
}

/* The greeting gets a line to itself. */
.hero h1 span {
  display: block;
}

.hero-aside {
  display: inline-block;
  margin-top: clamp(1.25rem, 3vw, 2.25rem);
  margin-left: clamp(0rem, 8vw, 9rem);
  rotate: -3deg;
}

.masthead {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 1.75rem clamp(1rem, 3vw, 2.5rem);
  margin-top: clamp(3.5rem, 8vw, 7rem);
  padding-top: 1.5rem;
  border-top: 1px solid rgba(244, 241, 232, 0.4);
}

.masthead dt {
  margin-bottom: 0.5rem;
  opacity: 0.65;
}

/* 6. Desk + pieces -------------------------------------------------------- */
.desk-title {
  font-family: var(--font-display);
  font-size: clamp(1.75rem, 3.4vw, 3rem);
  font-weight: 600;
  letter-spacing: -0.03em;
  line-height: 1.05;
}

/* On wide screens the pieces are placed by hand and can be dragged around
   (js/main.js). To rearrange them, change --x, --y, --w and --r below. */
.desk {
  position: relative;
  aspect-ratio: 100 / 130;
  margin-top: clamp(1.5rem, 4vw, 3rem);
}

.piece {
  position: absolute;
  left: var(--x);
  top: var(--y);
  width: var(--w);
  color: var(--ink);
  text-decoration: none;
  transform: translate(var(--dx, 0px), var(--dy, 0px)) rotate(var(--r, 0deg));
  cursor: grab;
  touch-action: none;
  user-select: none;
  -webkit-user-drag: none;
}

.piece.is-dragging {
  cursor: grabbing;
}

/* An image is draggable in its own right, and neither the draggable attribute
   on the piece nor -webkit-user-drag above reaches it: one does not cascade,
   the other is not inherited. Left alone, the browser starts its own drag the
   moment the pointer moves over the picture, that cancels the pointer events,
   and the piece can only be picked up by its paper label. */
.piece img {
  -webkit-user-drag: none;
}

.piece--phone {
  --x: 5%;
  --y: 2%;
  --w: 19%;
  --r: -5deg;
}

.piece--magazine {
  --x: 31%;
  --y: 0.5%;
  --w: 27%;
  --r: 3deg;
}

/* The brand board is off the desk for now; the book jacket sits in its slot.
   Put these back and move .piece--book if the branding project returns. */
.piece--brand {
  --x: 63%;
  --y: 13%;
  --w: 31%;
  --r: 4deg;
}

.piece--photo {
  --x: 44%;
  --y: 37%;
  --w: 46%;
  --r: -2deg;
}

.piece--posts {
  --x: 7%;
  --y: 41%;
  --w: 25%;
  --r: -4deg;
}

.piece--browser {
  --x: 21%;
  --y: 68%;
  --w: 50%;
  --r: 1.5deg;
  cursor: grab;
}

.piece--book {
  --x: 63%;
  --y: 13%;
  --w: 31%;
  --r: 4deg;
}

.piece-object {
  position: relative;
  display: grid;
  padding: 6%;
  background: var(--p-bg, var(--paper));
  color: var(--p-ink, var(--ink));
  box-shadow: var(--shadow);
  transition: translate 0.25s ease, box-shadow 0.25s ease, rotate 0.25s ease;
}

.piece:hover .piece-object,
.piece.is-dragging .piece-object {
  translate: 0 -5px;
  box-shadow: 0 2px 3px rgba(0, 0, 0, 0.25), 0 30px 40px -14px rgba(0, 0, 0, 0.6);
}

.piece-object .placeholder {
  height: 100%;
  aspect-ratio: auto;
}

/* A real image sets the shape: the object takes the picture's own proportions
   instead of cropping it to fit a guess, so nothing is squashed or trimmed.
   The trimmings around it — the bezel, the white print border, the fold
   creases — are what still give each one away as a thing. */
/* Written as .piece .piece-object so it outweighs the per-piece shapes below. */
.piece .piece-object:has(img) {
  aspect-ratio: auto;
}

.piece-object img {
  width: 100%;
  height: auto;
}

/* Phone: a dark bezel with rounded corners. The screen runs to the bezel,
   so there is no padding once a real screenshot is in. */
.piece--phone .piece-object {
  aspect-ratio: 9 / 18.5;
  padding: 0;
  overflow: hidden;
  border: clamp(0.3rem, 0.55vw, 0.5rem) solid #111;
  border-radius: clamp(1.1rem, 2.6vw, 2.5rem);
}

/* Magazine: cover proportions, with a hint of pages underneath. */
.piece--magazine .piece-object {
  aspect-ratio: 3 / 4;
  padding: 0;
  box-shadow: 2px 2px 0 rgba(0, 0, 0, 0.2), 4px 4px 0 rgba(0, 0, 0, 0.12), var(--shadow);
}

/* Photo: a white-bordered print, taped down. */
.piece--photo .piece-object {
  padding: 3.5% 3.5% 11%;
  background: #fbfaf6;
}

.piece--photo .placeholder {
  height: auto;
  aspect-ratio: 16 / 9;
  border-color: rgba(255, 255, 255, 0.45);
  background: var(--p-bg);
  opacity: 1;
}

/* Brand board: a landscape sheet with the logo stuck on as a round sticker. */
.piece--brand .piece-object {
  aspect-ratio: 4 / 3;
}

.sticker {
  position: absolute;
  top: -13%;
  right: -6%;
  z-index: 1;
  display: grid;
  place-items: center;
  width: 28%;
  aspect-ratio: 1;
  border-radius: 50%;
  background: var(--p-ink);
  color: var(--p-bg);
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.35);
  rotate: -12deg;
}

/* Social graphics: a square post with a second one peeking out underneath. */
.piece--posts .piece-object {
  aspect-ratio: 1;
}

.piece--posts::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: #fbfaf6;
  box-shadow: var(--shadow);
  rotate: 8deg;
  translate: 9% 4%;
}

/* Browser window, for the site that is still being built. */
.piece--browser .piece-object {
  grid-template-rows: auto 1fr;
  aspect-ratio: 16 / 10;
  overflow: hidden;
  padding: 0;
  border-radius: 0.6rem;
  background: #17171a;
  color: var(--chalk);
}

.browser-bar {
  display: flex;
  gap: 0.4rem;
  padding: 0.7rem 0.9rem;
  background: #29292e;
}

.browser-bar i {
  width: 0.6rem;
  height: 0.6rem;
  border-radius: 50%;
  background: #5b5b63;
}

.piece--browser .placeholder {
  height: auto;
  margin: 4%;
}

.soon {
  position: absolute;
  top: 44%;
  left: -4%;
  z-index: 1;
  width: 108%;
  padding: 0.3rem 0 0.45rem;
  background: var(--tape);
  color: var(--ink);
  text-align: center;
  rotate: -6deg;
}

/* Book: the dust jacket laid out flat, the way it comes off the press —
   back cover, spine, front cover, in one wide sheet. */
.piece--book .piece-object {
  aspect-ratio: 963 / 670;
  padding: 0;
}

/* The two creases where the jacket folds around the spine. The percentages
   follow the spine in the artwork, so they move if the image is replaced. */
.piece--book .piece-object::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    linear-gradient(90deg, transparent 47%, rgba(0, 0, 0, 0.25) 47% 47.5%, transparent 47.5%),
    linear-gradient(90deg, transparent 53.8%, rgba(0, 0, 0, 0.25) 53.8% 54.3%, transparent 54.3%);
}

.tape {
  position: absolute;
  top: -0.8rem;
  left: 38%;
  z-index: 1;
  width: 24%;
  height: 1.7rem;
  background: var(--tape);
  rotate: -4deg;
}

/* Paper label stuck beside each piece. */
.piece-label {
  position: absolute;
  left: -7%;
  bottom: -2.25rem;
  z-index: 1;
  display: block;
  width: max-content;
  max-width: min(15rem, 120%);
  padding: 0.6rem 0.85rem 0.75rem;
  background: #fbfaf6;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
  transform: rotate(calc(var(--r, 0deg) * -1.5));
}

.piece--photo .piece-label {
  left: auto;
  right: -3%;
}

.piece-label .mono {
  display: block;
  color: var(--muted);
}

.piece-label strong {
  display: block;
  margin-top: 0.15rem;
  font-family: var(--font-display);
  font-size: clamp(1.1rem, 1.6vw, 1.4rem);
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1.1;
}

.note {
  position: absolute;
  margin: 0;
}

.note--drag {
  left: 68%;
  top: 0.5%;
  width: 24%;
  rotate: 5deg;
}

.note--soon {
  left: 1%;
  top: 76%;
  width: 17%;
  rotate: -4deg;
}

.note--drag svg {
  display: block;
  width: 5.5rem;
  margin: 0.75rem 0 0 -1.5rem;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.note--more {
  left: 75%;
  top: 74%;
  width: 23%;
  rotate: 2deg;
}

/* Hover hints: each object reacts in its own way before you pick it up. */
.piece--magazine .piece-object::after {
  content: "";
  position: absolute;
  right: 0;
  bottom: 0;
  width: 0;
  aspect-ratio: 1;
  /* Bottom-right half is the page underneath; top-left half is the cover curling back. */
  background: linear-gradient(315deg, #fbfaf6 50%, rgba(0, 0, 0, 0.32) 50%, rgba(0, 0, 0, 0.06) 78%);
  transition: width 0.3s ease;
}

.tape,
.sticker,
.piece--posts::before {
  transition: rotate 0.3s ease, translate 0.3s ease, scale 0.3s ease;
}

@media (hover: hover) {
  .piece--magazine:hover .piece-object::after {
    width: 17%;
  }

  .piece--phone:hover .piece-object {
    box-shadow: 0 0 2.5rem rgba(246, 240, 217, 0.5), 0 30px 40px -14px rgba(0, 0, 0, 0.6);
  }

  .piece--photo:hover .tape {
    rotate: -10deg;
    translate: 0 -5px;
  }

  .piece--brand:hover .sticker {
    rotate: 14deg;
    scale: 1.08;
  }

  .piece--posts:hover::before {
    rotate: 15deg;
    translate: 17% 5%;
  }

  /* A loose sheet, so it shifts under your hand. */
  .piece--book:hover .piece-object {
    rotate: -1.5deg;
  }

  /* Not ready yet, so it shakes its head. */
  .piece--browser:hover .piece-object {
    animation: not-yet 0.35s ease;
  }
}

@keyframes not-yet {
  25% {
    transform: translateX(-6px);
  }
  75% {
    transform: translateX(6px);
  }
}

/* Opening a project: a block of the project's colour that grows to fill the
   screen, then shrinks into the top of the project page (see js/main.js). */
.lift {
  position: fixed;
  inset: 0;
  z-index: 100;
  transform-origin: 0 0;
}

/* Holds the colour on screen while the project page loads. If the script
   never runs, it clears itself so the page is not left covered. */
.from-desk body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 100;
  background: var(--p-bg, var(--paper));
  animation: uncover 0.01s 2.5s forwards;
}

@keyframes uncover {
  to {
    visibility: hidden;
  }
}

/* 7. Paper sheet (about) -------------------------------------------------- */
.sheet {
  position: relative;
  max-width: 68rem;
  margin-inline: auto;
  padding: clamp(1.75rem, 6vw, 5rem);
  background: var(--paper);
  color: var(--ink);
  box-shadow: var(--shadow);
}

.sheet--tilted {
  rotate: -0.7deg;
}

.about {
  padding-block: var(--section);
}

.about-grid {
  display: grid;
  grid-template-columns: minmax(0, 4fr) minmax(0, 8fr);
  gap: clamp(2rem, 6vw, 5rem);
  align-items: start;
}

/* A print of you, clipped onto the sheet at an angle. */
.portrait {
  /* An even border now the caption is gone; it used to supply the bottom edge. */
  padding: 5%;
  background: #fff;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2), 0 10px 18px -10px rgba(0, 0, 0, 0.4);
  rotate: 3.5deg;
}

.portrait .placeholder {
  aspect-ratio: 4 / 5;
}

.portrait img {
  width: 100%;
  height: auto;
}

.portrait figcaption {
  padding-block: 0.5rem 0.75rem;
  font-family: var(--font-hand);
  font-size: 1.6rem;
  line-height: 1;
  text-align: center;
}

.about-lede {
  font-family: var(--font-display);
  font-size: clamp(1.6rem, 3vw, 2.6rem);
  font-weight: 500;
  letter-spacing: -0.03em;
  line-height: 1.12;
}

.about-body {
  max-width: 54ch;
  margin-top: 1.75rem;
}

.spec {
  margin-block: 2.5rem 2rem;
  border-top: 1px solid var(--ink);
}

.spec > div {
  display: grid;
  grid-template-columns: 8rem 1fr;
  gap: 1rem;
  padding-block: 0.75rem;
  border-bottom: 1px solid var(--line);
}

.spec dt {
  padding-top: 0.25em;
  color: var(--muted);
}

/* 8. Tag (contact) -------------------------------------------------------- */
.contact {
  padding-bottom: var(--section);
}

/* A kraft swing tag with a punched hole. */
.tag {
  position: relative;
  max-width: 44rem;
  margin-inline: auto;
  padding: clamp(4.5rem, 9vw, 6.5rem) clamp(1.5rem, 5vw, 3.5rem) clamp(2rem, 5vw, 3.5rem);
  background: var(--kraft);
  color: var(--ink);
  box-shadow: var(--shadow);
  rotate: 1.6deg;
  clip-path: polygon(9% 0, 91% 0, 100% 11%, 100% 100%, 0 100%, 0 11%);
}

.tag::before {
  content: "";
  position: absolute;
  top: 1.5rem;
  left: 50%;
  width: 1.5rem;
  height: 1.5rem;
  border-radius: 50%;
  background: var(--mat);
  box-shadow: inset 0 2px 3px rgba(0, 0, 0, 0.4);
  translate: -50%;
}

.tag h2 {
  font-family: var(--font-display);
  font-size: clamp(1.9rem, 4.6vw, 3.5rem);
  font-weight: 600;
  letter-spacing: -0.035em;
  line-height: 1.05;
}

.contact-link {
  display: inline-block;
  margin-top: 1.75rem;
  font-size: clamp(1.15rem, 2.4vw, 1.6rem);
  overflow-wrap: anywhere;
}

.socials {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 1.75rem;
  margin: 2.25rem 0 0;
  padding: 1.25rem 0 0;
  border-top: 1px solid rgba(23, 22, 19, 0.35);
  list-style: none;
}

/* 9. Footer --------------------------------------------------------------- */
.site-footer {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 0.5rem 2rem;
  padding: 1.5rem var(--gutter);
  border-top: 1px solid var(--mat-line-strong);
  opacity: 0.75;
}

/* 10. Case study ---------------------------------------------------------- */
/* The case study is a document lying on the mat. Set --p-bg / --p-ink on
   <body> and the top of the document takes the project's colours. */
/* Kept narrow so there is plenty of mat either side to click on. */
.doc {
  max-width: 62rem;
  margin: clamp(0.5rem, 2vw, 1.5rem) auto 0;
  padding: 0;
}

/* Clicking the mat puts the document down (js/main.js), so the pointer says so. */
.is-project body {
  cursor: zoom-out;
}

.is-project .doc {
  cursor: auto;
}

/* The way back to the desk, pinned to the top corner. At the top of the page
   it is only a small arrow under the header, so the whole screen is free.
   Once you scroll (js/main.js adds .is-scrolled) it moves up into the space
   the header left and opens out into a label; your eyes are lower down by then. */
.back-note {
  position: fixed;
  top: 5.75rem;
  left: clamp(0.75rem, 2vw, 1.5rem);
  z-index: 50;
  display: flex;
  align-items: center;
  padding: 0.2rem 0.65rem 0.4rem;
  background: #fbfaf6;
  color: var(--ink);
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
  text-decoration: none;
  rotate: -3deg;
  transition: top 0.3s ease, rotate 0.25s ease, scale 0.25s ease;
}

.back-arrow {
  font-size: 1.7rem;
  line-height: 1;
}

.back-text {
  display: grid;
  gap: 0.1rem;
  max-width: 0;
  overflow: hidden;
  opacity: 0;
  white-space: nowrap;
  transition: max-width 0.35s ease, margin-left 0.35s ease, opacity 0.25s ease;
}

.back-text .hand {
  font-size: 1.6rem;
}

.back-text .mono {
  padding-bottom: 0.15rem;
  color: var(--muted);
  font-size: 0.7rem;
}

.is-scrolled .back-note {
  top: 0.9rem;
}

/* Opens once you have scrolled, and also on hover or keyboard focus. */
.is-scrolled .back-text,
.back-note:hover .back-text,
.back-note:focus-visible .back-text {
  max-width: 14rem;
  margin-left: 0.55rem;
  opacity: 1;
}

/* It perks up when you hover it, and also when you hover the mat. */
.back-note:hover,
main:hover:not(:has(.doc:hover, .cs-next:hover)) ~ .back-note {
  rotate: 2deg;
  scale: 1.08;
}

/* Below this width the document reaches the left edge, where its text starts,
   so the arrow moves to the right-hand corner, which is always empty. */
@media (max-width: 70rem) {
  .back-note {
    left: auto;
    right: clamp(0.75rem, 2vw, 1.5rem);
  }
}

.cs-hero {
  padding: clamp(1.75rem, 6vw, 5rem);
  background: var(--p-bg, var(--line));
  color: var(--p-ink, var(--ink));
}

.cs-hero h1 {
  margin-top: 1.25rem;
  font-family: var(--font-display);
  font-size: clamp(2.8rem, 9.5vw, 8.5rem);
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.04em;
}

.cs-intro {
  max-width: 34ch;
  margin-top: clamp(1.5rem, 3vw, 2.5rem);
  font-size: clamp(1.2rem, 2.2vw, 1.75rem);
  line-height: 1.3;
}

.cs-hero .masthead {
  margin-top: clamp(2.5rem, 6vw, 5rem);
  border-color: currentColor;
}

.cs-cover {
  margin-top: clamp(1.75rem, 4vw, 3rem);
}

/* Stand-ins are forced to a shape; real images keep their own proportions.
   height:auto is not optional — the width/height attributes on an <img> are
   presentational hints, so without it the height attribute wins and the
   picture is stretched to it. */
img.cs-cover {
  width: 100%;
  height: auto;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.18), 0 18px 36px -16px rgba(0, 0, 0, 0.5);
}

.cs-sections {
  padding-inline: clamp(1.75rem, 6vw, 5rem);
}

.cs-section {
  display: grid;
  grid-template-columns: minmax(0, 4fr) minmax(0, 8fr);
  gap: 1.5rem clamp(1.5rem, 4vw, 4rem);
  padding-block: clamp(3rem, 7vw, 6rem);
  border-bottom: 1px solid var(--line);
}

.cs-section:last-child {
  border-bottom: 0;
}

.cs-label {
  align-self: start;
  position: sticky;
  top: 1.5rem;
}

.cs-label .mono {
  color: var(--muted);
}

.cs-label h2 {
  margin-top: 0.5rem;
  font-family: var(--font-display);
  font-size: clamp(1.6rem, 3vw, 2.6rem);
  font-weight: 600;
  letter-spacing: -0.03em;
  line-height: 1.05;
}

.cs-body > p {
  max-width: 56ch;
  font-size: 1.125rem;
}

/* p margins are zeroed in the reset, so a section that runs to a second
   paragraph has to ask for the gap. */
.cs-body > p + p {
  margin-top: 1.25rem;
}

.cs-figures {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
  gap: clamp(1rem, 2.5vw, 2rem);
  align-items: start;
  margin-top: 2.25rem;
}

/* A figure block dropped straight into the section, rather than inside the
   text column, runs the full width of the document. A magazine spread or a
   research board is not worth showing at two thirds of that. */
.cs-section > .cs-figures {
  grid-column: 1 / -1;
  margin-top: clamp(1.25rem, 2.5vw, 2.25rem);
}

/* Upright things — a phone screen, a cover — would be absurd blown up to the
   full width, so their columns are capped instead of stretched. */
.cs-figures--upright {
  grid-template-columns: repeat(auto-fit, minmax(0, 22rem));
  justify-content: start;
}

/* Every picture sits on the sheet like a print laid down on it. The white
   backing matters for the document scans, which run white to the edge. */
.cs-figures img {
  width: 100%;
  height: auto;
  background: #fff;
  box-shadow: 0 1px 2px rgba(23, 22, 19, 0.14), 0 10px 24px -12px rgba(23, 22, 19, 0.45);
}

.cs-figures figcaption {
  margin-top: 0.75rem;
  color: var(--muted);
}

.cs-results {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr));
  gap: 2rem;
  margin: 2.5rem 0 0;
  padding: 0;
  list-style: none;
}

.cs-results strong {
  display: block;
  margin-bottom: 0.4rem;
  font-family: var(--font-display);
  font-size: clamp(2.75rem, 6vw, 5rem);
  font-weight: 600;
  letter-spacing: -0.04em;
  line-height: 1;
}

.cs-next {
  display: block;
  padding: var(--section) var(--gutter);
  text-decoration: none;
}

.cs-next strong {
  display: block;
  margin-top: 0.75rem;
  font-family: var(--font-display);
  font-size: clamp(2.4rem, 7.5vw, 7rem);
  font-weight: 600;
  letter-spacing: -0.035em;
  line-height: 1.02;
}

.cs-next:hover strong {
  text-decoration: underline;
  text-decoration-thickness: 0.05em;
  text-underline-offset: 0.12em;
}

/* 11. Small screens ------------------------------------------------------- */
@media (max-width: 48rem) {
  .site-header {
    grid-template-columns: 1fr auto;
  }

  .page-name {
    display: none;
  }

  .hero-aside {
    margin-left: 0;
  }

  .masthead {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  /* No dragging on phones: the pieces stack in a loose column instead. */
  .desk {
    display: grid;
    gap: 5rem;
    aspect-ratio: auto;
    justify-items: center;
  }

  .piece,
  .note {
    position: relative;
    left: auto;
    top: auto;
    touch-action: auto;
    cursor: pointer;
  }

  .piece--phone {
    --w: 58%;
  }

  .piece--magazine {
    --w: 78%;
  }

  .piece--photo {
    --w: 100%;
  }

  .piece--brand {
    --w: 84%;
  }

  .piece--posts {
    --w: 68%;
  }

  .piece--browser {
    --w: 100%;
    cursor: default;
  }

  .piece--book {
    --w: 100%;
  }

  /* Full-width pieces keep their labels and tape inside the screen. */
  .piece--browser .piece-label {
    left: 0;
  }

  .piece--photo .piece-label {
    right: 0;
  }

  .soon {
    left: 0;
    width: 100%;
  }

  .piece-label {
    left: -12%;
  }

  .note {
    width: 100%;
  }

  .note--drag {
    display: none;
  }

  .about-grid,
  .cs-section {
    grid-template-columns: 1fr;
  }

  .portrait {
    max-width: 13rem;
  }

  .spec > div {
    grid-template-columns: 6rem 1fr;
  }

  .cs-label {
    position: static;
  }
}

/* Touch screens have no Esc key and little mat to tap, so drop that hint. */
@media (max-width: 48rem), (hover: none) {
  .back-note .mono {
    display: none;
  }
}

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

  .piece-object,
  .piece-object::after,
  .tape,
  .sticker,
  .piece--posts::before,
  .back-note,
  .back-text {
    transition: none;
  }

  .piece--browser:hover .piece-object {
    animation: none;
  }
}
