/* ============================================================================
   Daniel Faust — portfolio
   Design system + layout. Everything the site looks like is in this one file.

   The site is built from one idea: a black 1px outlined frame, subdivided
   into cells by 1px rules. Every page is that frame filled differently.

   Contents
     1  Tokens            8  Contact footer
     2  Reset             9  Home
     3  Type scale       10  Case-study pages
     4  The frame        11  Layout page: hover-scrub
     5  Site header      12  Motion page
     6  Buttons          13  Responsive
     7  Media
   ========================================================================= */

/* --- 1. Tokens ----------------------------------------------------------- */

:root {
  /* colour */
  --blue:      #3347FC;
  --blue-soft: rgba(51, 71, 252, .8);
  --ink:       #000000;
  --ink-2:     #222222;
  --ink-mute:  rgba(34, 34, 34, .5);
  --paper:     #ffffff;

  /* the frame */
  --rule:      1px solid var(--ink);
  --gutter:    2rem;              /* inset of the frame from the page edge */
  --maxw:      1440px;            /* how wide the frame is allowed to grow  */
  --pad:       1.4rem;            /* standard padding inside a cell         */

  /* media sits *inside* the grid, never on it */
  --inset:     1rem;              /* 16 on the old canvas — gap to the rules */
  --radius:    .75rem;            /* 12 on the old canvas — corner rounding  */


  /* the blue node that marks a grid intersection */
  --leg:       1.75rem;           /* 28 on the old canvas — length of one leg */
  --tick:      .375rem;           /* 6 on the old canvas — stroke thickness   */

  /* type */
  --sans:  "Bricolage Grotesque", "Helvetica Neue", Arial, sans-serif;
  --serif: "Fraunces", Georgia, serif;
  --note:  "Alegreya", Georgia, serif;
  --poster:"Oswald", "Helvetica Neue", Arial, sans-serif;

  /* motion */
  --ease: cubic-bezier(.4, 0, .2, 1);
}

/* --- 2. Reset ------------------------------------------------------------ */

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

/* The original was a 1024px canvas that Readymag scaled to fill the window,
   so every size grew together. We keep that behaviour — but drive it from one
   root font-size instead of a transform, and cap it so the site stops
   inflating on a very large monitor.

   1rem == 1px of the old 1024 canvas.  16 / 1024 = 1.5625vw               */
html {
  font-size: clamp(14px, 1.5625vw, 21px);
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-variation-settings: "wght" 400;
  font-size: 1rem;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

img, video, canvas, svg { display: block; max-width: 100%; }
img, video { height: auto; }

a { color: inherit; text-decoration: none; }

h1, h2, h3, h4, p, figure, ul, figcaption { margin: 0; padding: 0; }
ul { list-style: none; }

::selection { background: var(--blue); color: var(--paper); }

/* never a lone word on the last line: paragraphs rebalance their last lines,
   headings and short lines balance all of theirs */
p, li, figcaption, dd { text-wrap: pretty; }
h1, h2, h3, .t-tagline, .pg-sub { text-wrap: balance; }

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

/* --- 3. Type scale -------------------------------------------------------
   Sizes are the original canvas values expressed in rem, so the proportions
   between them are exactly what you drew.                                  */

.t-display {                       /* "Daniel Faust" — was 115/92, ls -6 */
  font-family: var(--sans);
  font-variation-settings: "wght" 800;
  font-size: 7.1875rem;
  line-height: .8;
  letter-spacing: -.052em;
}

.t-tagline {                       /* "Interactive & Motion Designer" — 45/55 */
  font-family: var(--serif);
  font-style: italic;
  font-variation-settings: "wght" 615;
  font-feature-settings: "smcp", "liga";
  font-size: 2.8125rem;
  line-height: 1.22;
  letter-spacing: -.007em;
}

.t-title {                         /* page titles: Cubed / Evmos / Apostrophe */
  font-family: var(--sans);
  font-variation-settings: "wght" 800;
  font-size: 3.5rem;
  line-height: 1.07;
  letter-spacing: -.02em;
  color: var(--blue);
}

.t-index {                         /* the work index on the home page — 40 */
  font-family: var(--sans);
  font-variation-settings: "wght" 200;
  font-size: 2.5rem;
  line-height: 1;
  letter-spacing: -.05em;
}

.t-lead {                          /* the bold intro paragraph — 24/27 */
  font-variation-settings: "wght" 800;
  font-size: 1.5rem;
  line-height: 1.13;
  letter-spacing: -.007em;
}

.t-body {                          /* 16/26 */
  font-size: 1rem;
  line-height: 1.625;
}

.t-body > * + *      { margin-top: .5em; }
.t-body > * + .t-h2  { margin-top: 1.7em; }
.t-body > p + p,
.t-body > .t-h2 + p,
.t-body > .t-h3 + p  { text-indent: 1.6em; }

.t-h2 {                            /* "The Problem", "About", "Design" … */
  font-variation-settings: "wght" 800;
  font-size: 1rem;
  line-height: 1.625;
}

.t-h3 {                            /* run-in label above a single point */
  font-variation-settings: "wght" 600;
  font-size: 1rem;
  line-height: 1.625;
}

.t-note {                          /* captions — Alegreya italic 18 */
  font-family: var(--note);
  font-style: italic;
  font-size: 1.125rem;
  line-height: 1.25;
  color: var(--ink-2);
}

.t-small { font-size: .875rem; line-height: 1.7; }

/* --- 4. The frame -------------------------------------------------------- */

.frame {
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

/* A bordered box. */
.panel {
  border: var(--rule);
  background: var(--paper);
}
.panel + .panel { border-top: 0; }

/* A horizontal rule spanning the full width of a panel, drawn *over*
   whatever sits behind it — the signature move of the original layout. */
.rule { border-top: var(--rule); }

.pad { padding: var(--pad); }

/* --- 5. Site header (inner pages) ---------------------------------------- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--paper);
  border-bottom: var(--rule);
}

.site-header__inner {
  display: flex;
  align-items: center;
  gap: .6rem;
  min-height: 3.4375rem;
  padding-block: .4rem;
}

.wordmark {
  font-variation-settings: "wght" 800;
  font-size: 1.875rem;
  letter-spacing: -.043em;
  line-height: 1;
  margin-right: auto;
  transition: color .15s var(--ease);
}
.wordmark:hover { color: var(--blue); }

.nav { display: flex; align-items: center; gap: .5rem; }

.nav__link {
  font-family: var(--serif);
  font-style: italic;
  font-variation-settings: "wght" 300;
  font-size: 1.125rem;
  letter-spacing: -.055em;
  line-height: 1;
  padding: .45em 1em .55em;
  border-radius: 999px;
  background: var(--ink);
  color: var(--paper);
  white-space: nowrap;
  transition: background .18s var(--ease), color .18s var(--ease);
}
.nav__link:hover { background: var(--paper); color: var(--blue); }
.nav__link[aria-current="page"],
.nav__link[aria-current="page"]:hover { background: var(--blue); color: var(--paper); }

/* --- 6. Buttons ---------------------------------------------------------- */

/* outlined block button — the contact footer */
.btn {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 4.5625rem;
  padding: .75rem 1rem;
  border: var(--rule);
  background: var(--paper);
  color: var(--ink);
  font-variation-settings: "wght" 700;
  font-size: 1.125rem;
  text-align: center;
  transition: background .18s var(--ease), color .18s var(--ease);
}
.btn:hover { background: var(--blue-soft); color: var(--paper); }

/* pill — the "Interest Areas" tags */
.tag {
  display: inline-flex;
  align-items: center;
  padding: .4em var(--padx, 1.1em) .5em;
  border: 2px solid var(--blue);
  border-radius: 999px;
  background: var(--paper);
  color: var(--blue);
  font-variation-settings: "wght" 500, "wdth" var(--wdth, 100);
  font-size: .875rem;
  line-height: 1;
  white-space: nowrap;
}
.tag--solid { background: var(--blue); color: var(--paper); }

/* round blue call-to-action, e.g. "UX Research" */
.blob {
  display: grid;
  place-content: center;
  width: 7.8rem;
  height: 4.25rem;
  border-radius: 999px;
  background: var(--blue);
  color: var(--paper);
  font-variation-settings: "wght" 600;
  font-size: 1rem;
  letter-spacing: -.06em;
  text-align: center;
  transition: background .18s var(--ease), color .18s var(--ease), box-shadow .18s var(--ease);
}
.blob:hover { background: var(--paper); color: var(--blue); box-shadow: inset 0 0 0 2px var(--blue); }

/* full-width blue bar */
.bar-link {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: .5em;
  width: 100%;
  padding: .45em;
  background: var(--blue);
  color: var(--paper);
  font-variation-settings: "wght" 500;
  font-size: .875rem;
  line-height: 1.5;
  transition: background .18s var(--ease), color .18s var(--ease);
}
.bar-link:hover { background: var(--paper); color: var(--blue); }
.bar-link svg { width: .8em; height: .8em; fill: currentColor; }

/* --- 7. Media ------------------------------------------------------------ */

/* Assets come in two kinds, and the original is strict about which is which:

   .media          FITTED — fills its cell edge to edge, square corners. The
                   big ones: hero images, the showreels, anything that *is*
                   the cell. It reads as built into the grid.

   .media--inset   PLACED — sits inside the cell with --inset of air on all
                   sides and rounded corners, so the rules pass cleanly around
                   it. The gallery and detail shots.

   .media--inset-sm  the same, with the tighter radius the original uses on
                   small thumbnails.                                        */

.media {
  position: relative;
  min-width: 0;
  max-width: 100%;   /* a stretched grid item + aspect-ratio would otherwise
                        solve for a width far wider than its column */
  background: var(--paper);
}
.media > img,
.media > video {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.media--inset,
.media--inset-sm { padding: var(--inset); }
.media--inset > img,
.media--inset > video { border-radius: var(--radius); }
.media--inset-sm > img,
.media--inset-sm > video { border-radius: .3125rem; }

/* when the media element *is* the picture or video itself */
img.media, video.media {
  width: 100%;
  object-fit: cover;
  background: rgba(51, 71, 252, .06);
}
img.media--inset, video.media--inset { border-radius: var(--radius); }

/* Fixed-shape media wells, so a swapped-in asset can never change the
   layout. Ratios are taken from the original boxes.                        */
.media--wide   { aspect-ratio: 16 / 9; }
.media--square { aspect-ratio: 1; }
.media--tall   { aspect-ratio: 2 / 3; }

/* a phone-shaped well, kept to a sane width whatever cell it lands in */
.media--phone {
  aspect-ratio: 226 / 436;
  width: 15rem;
  max-width: 100%;
  margin-inline: auto;
}

/* fills whatever cell it is dropped into, cropping rather than leaving a gap */
.media--fill > img,
.media--fill > video { height: 100%; object-fit: cover; }

/* Placeholder standing in for a video still hosted on Readymag.
   Swap the whole element for a <video> when the real file is ready. */
.media--todo {
  position: relative;
  display: grid;
  place-content: center;
  align-content: center;
  gap: .3rem;
  min-height: 9rem;
  padding: 1.6rem;
  text-align: center;
  color: var(--blue);
}
/* the hatch fills the cell, because every asset it stands in for is a video,
   and the videos are all fitted */
.media--todo::before {
  content: "";
  position: absolute;
  inset: 0;
  background-color: rgba(51, 71, 252, .05);
  background-image: repeating-linear-gradient(
    45deg,
    rgba(51, 71, 252, .1) 0 10px,
    transparent 10px 20px
  );
}
.media--todo > * { position: relative; }
.media--todo b {
  font-variation-settings: "wght" 700;
  font-size: .9375rem;
  letter-spacing: -.02em;
}
.media--todo span {
  font-family: var(--note);
  font-style: italic;
  font-size: .8125rem;
  color: var(--ink-mute);
}

.caption { position: relative; padding: .6rem var(--pad) .7rem; }

/* ── The blue node ────────────────────────────────────────────────────────
   A three-legged plus that marks a T-junction in the grid. It straddles the
   1px rule — half the stroke each side — and each leg runs --leg along the
   rule it is tracing. The missing fourth leg is the direction where no rule
   continues, so the mark reads as part of the grid rather than on top of it.

   Put it on the element whose top-left corner is the junction:

       <p class="caption"><i class="node node--right"></i>…</p>

   and pick the modifier by which single leg sticks out of the straight run.
   ------------------------------------------------------------------------ */

.node {
  position: absolute;
  top: -.5px;                 /* the rule's centre, not its inside edge */
  left: -.5px;
  width: 0;
  height: 0;
  z-index: 4;
  pointer-events: none;
}
.node::before,
.node::after {
  content: "";
  position: absolute;
  background: var(--blue);
}
.node::before {               /* the horizontal arm(s) */
  height: var(--tick);
  top: calc(var(--tick) / -2);
}
.node::after {                /* the vertical arm(s) */
  width: var(--tick);
  left: calc(var(--tick) / -2);
}

/* ⊢ — full vertical run, one leg to the right */
.node--right::before { left: 0; width: var(--leg); }
.node--right::after  { top: calc(var(--leg) * -1); height: calc(var(--leg) * 2); }

/* ⊣ — full vertical run, one leg to the left */
.node--left::before  { left: calc(var(--leg) * -1); width: var(--leg); }
.node--left::after   { top: calc(var(--leg) * -1); height: calc(var(--leg) * 2); }

/* ⊤ — full horizontal run, one leg down */
.node--down::before  { left: calc(var(--leg) * -1); width: calc(var(--leg) * 2); }
.node--down::after   { top: 0; height: var(--leg); }

/* ⊥ — full horizontal run, one leg up */
.node--up::before    { left: calc(var(--leg) * -1); width: calc(var(--leg) * 2); }
.node--up::after     { top: calc(var(--leg) * -1); height: var(--leg); }

/* anchor to a corner other than top-left */
.node--tr { left: auto; right: -.5px; }
.node--bl { top: auto; bottom: -.5px; }

/* --- 8. Contact footer --------------------------------------------------- */

/* The frame is drawn once, by the container, and the dividers are 1px gaps
   showing it through. That way the strip closes correctly at four columns,
   two, or one, with no per-cell border bookkeeping to get wrong. */
.contact {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1px;
  border: var(--rule);
  background: var(--ink);
}
.contact .btn { border: 0; }

/* --- 9. Home ------------------------------------------------------------- */

.hero {
  display: grid;
  grid-template-columns: 1fr 32.1%;
  align-items: center;
}

.hero__type { padding: 1.6rem var(--pad) 1.9rem 1.6rem; min-width: 0; }
.hero__type .t-tagline { margin-top: .1em; }


/* the index: media on the left, four linked rows on the right, with the
   rules running across the whole width on top of the media */
.index { position: relative; }

.index__media {
  position: absolute;
  inset: 0 auto 0 0;
  width: 66.25%;
  z-index: 0;
  background: var(--paper);
}
.index__media > * { width: 100%; height: 100%; object-fit: cover; }
.index__media > [hidden] { display: none; }
/* keep the face in frame the way the original crop did */
.index__media > img[data-preview="default"] { object-position: 50% 62%; }

.index__list { position: relative; z-index: 1; }

.index__row { border-top: var(--rule); }
.index__row:first-child { border-top: 0; }

.index__link {
  display: flex;
  align-items: center;
  min-height: 3.8rem;
  padding: .2em var(--gutter) .3em 67.8%;
  transition: color .18s var(--ease);
}
.index__link:hover { color: var(--blue); }

/* the scrolling "Let's Work together" band — a link that opens an email.
   Centred between the grid and the about panel: equal padding above and
   below, and the letters trimmed to cap height and baseline, so the space
   is the same from the rule to the letters on both sides. */
.marquee {
  display: block;
  overflow: hidden;
  padding-block: var(--gutter);
  color: var(--blue);
  text-decoration: none;
  cursor: pointer;
  transition: color .18s var(--ease);
  font-size: 1.875rem;
  line-height: 1.4;
  white-space: nowrap;
  -webkit-user-select: none;
  user-select: none;
}
.marquee__track {
  display: inline-flex;
  will-change: transform;
  animation: marquee 26s linear infinite;
}
.marquee__track > span { padding-right: .35em; text-box: trim-both cap alphabetic; }
.marquee:hover, .marquee:focus-visible { color: var(--ink); }
.marquee:hover .marquee__track { animation-play-state: paused; }
.marquee:focus-visible { outline: 2px solid var(--blue); outline-offset: -2px; }

@keyframes marquee {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}

/* about block */
.about { display: grid; grid-template-columns: 1fr 32.1%; }
/* the contact row right below draws this line; two borders made it 2px */
.about { border-bottom: 0; }

.about__text {
  display: flex;
  flex-direction: column;
  gap: 1.3rem;
  padding: 1.3rem var(--pad) 1.5rem 1.6rem;
  align-self: start;             /* measured by motion-grid.js §9 */
}
/* Where the text is taller than the square, motion-grid.js §9 sizes the
   square to match it (--s): beside the whole text (--fit), or beside the
   paragraph with the headline across the top (--split). */
.about--fit, .about--split { grid-template-columns: minmax(0, 1fr) var(--s); }
.about--split .about__text { display: contents; }
.about--split .t-lead {
  grid-column: 1 / -1;
  padding: 1.3rem var(--pad) 1.3rem 1.6rem;
  border-bottom: var(--rule);
}
.about--split .t-body { padding: 1.3rem var(--pad) 1.5rem 1.6rem; align-self: start; }
.about--split .about__aside { grid-column: 2; }

.about__aside {
  border-left: var(--rule);
  /* the animation runs to the edges of its square, so it is never cropped
     (see motion-grid.js §9 for how the square keeps up with the text) */
  align-self: start;
}
.about__aside > img,
.about__aside > video { display: block; width: 100%; aspect-ratio: 1; object-fit: cover; }

/* --- 10. Case-study pages ------------------------------------------------ */

.titlebar { padding: .5rem 1.6rem .7rem; }

/* ── Case study body: two independent columns ─────────────────────────────
   The copy is one continuous column, top-aligned, exactly as on the live
   site. The media column beside it is a stack of blocks divided by rules.
   Neither column is forced to match the other's rhythm: each block is as
   tall as its own content, so there are no centred islands and no dead
   bands above or below a picture. */

.case__body {
  position: relative;
  display: grid;
  grid-template-columns: 33.85% 1fr;
  align-items: start;
}

.case__aside {
  align-self: stretch;            /* full height of the body, so the foot
                                     has somewhere to travel */
  display: flex;
  flex-direction: column;
}
.case__copy { padding: 1.1rem 1.4rem 1.6rem 1.6rem; }

/* ── "Back to Top" + Interest Areas ───────────────────────────────────────
   Desktop: sits at the bottom of the copy column and is sticky to the
   bottom of the screen, so it rides along while the media column scrolls
   and comes to rest where the column ends, at the footer. It stays
   invisible until the end of the copy has scrolled into view (site.js adds
   .is-shown), then fades in — so it never sits on top of the text. */
.case__foot {
  position: sticky;
  bottom: 0;
  margin-top: auto;
  z-index: 3;
  /* no background: it only appears once the copy has passed, so there is
     nothing to cover — and a fill would paint over the rules beside it */
  opacity: 0;
  visibility: hidden;
  transition: opacity .45s var(--ease), visibility 0s linear .45s;
}
.case__foot.is-shown {
  opacity: 1;
  visibility: visible;
  transition: opacity .45s var(--ease), visibility 0s;
}
.case__foot > .bar-link { border-block: var(--rule); }    /* rules above and under "Back to Top" */
.case__foot__body { padding: 1rem 1.4rem 1.2rem 1.6rem; }
.case__foot__body .tags { margin-top: .6rem; }
.case__sentinel { display: block; height: 1px; }

.case__main {
  position: relative;
  align-self: stretch;
  border-left: var(--rule);
  min-width: 0;
}
.case__main > * + *:not(.node) { border-top: var(--rule); }
.case__main > .node + * { border-top: 0; }
.case__main > *:not(.node) { position: relative; }

/* a portrait video that fills its side of a split */
.media--phone-cell { aspect-ratio: 226 / 436; min-height: 0; }

/* A case study is a stack of rows. Each row pairs a block of copy with the
   media it is actually about, so the two columns stay in step at any width.
   (The original had all the copy in one very tall box, hand-spaced so that
   paragraphs happened to land beside the right picture at exactly 1024px.)

   .case--mirror flips the columns, which is what the Layout page wants. */
.case__row {
  position: relative;
  display: grid;
  grid-template-columns: 33.85% 1fr;
}

/* a node dropped straight into a row lands on the column divider — the one
   junction guaranteed to exist at every row boundary */
.case__row > .node { left: 33.85%; }
.case--mirror .case__row > .node { left: 57.7%; }
.case__row + .case__row { border-top: var(--rule); }
.case--mirror .case__row { grid-template-columns: 1fr 42.3%; }

/* Whichever column is shorter centres against the taller one. Nothing is
   stretched or cropped to force the two sides to match — the leftover space
   reads as margin instead of as a mistake. */
.case__text {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 1.1rem 1.4rem 1.6rem 1.6rem;
}
.case--mirror .case__text { order: 2; border-left: var(--rule); }

/* opt out of centring when the copy should sit at the top of its cell */
.case__text--top { justify-content: flex-start; }

/* The block that closes every sub-page: "Back to Top" and Interest Areas.
   It is a full-width band and always the last thing in the article, after
   all the content and immediately before the contact row — never tucked
   into a column halfway down. */
.case__close { border-top: var(--rule); }
.case__close__body { padding: var(--pad); }

/* The media column always fills the height of its row, so a picture never
   leaves a stranded white gap under itself inside a bordered cell. */
.case__media {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: center;
  border-left: var(--rule);
  min-width: 0;
  align-self: stretch;
}
/* add .media--fill to a picture that should crop to fill its cell instead */
.case__media > .media--fill { flex: 1; }
.case--mirror .case__media { order: 1; border-left: 0; }

/* a row whose media spans the full width */
.case__row--full { grid-template-columns: 1fr; }
.case__row--full .case__media { border-left: 0; }

.tags { display: flex; flex-wrap: wrap; gap: .45rem; margin-top: .8rem; }
/* justified by project.js §7: each line fills the block edge to edge; the
   pills grow evenly and the empty .tags__br items end the lines. A break
   is a flex line of its own, so it alone carries the gap between lines
   (row-gap 0), which keeps that gap equal to the one between pills. */
.tags--fit { row-gap: 0; }
.tags--fit > li { display: flex; flex: 1 1 auto; min-width: 0; }
.tags--fit .tag { flex: 1; min-width: 0; justify-content: center; }
.tags--fit > .tags__br { flex: 0 0 100%; height: .45rem; }
.tags--measure { flex-wrap: nowrap; width: max-content; }
.tags--measure > li { flex: none; }
.tags--measure .tag { flex: none; }

/* stacked rows inside the media column, separated by rules */
.stack > * + * { border-top: var(--rule); }

/* so a .node can be anchored to any cell corner (the nodes themselves must
   stay absolute, hence the :not) */
.stack > *:not(.node),
.split > *:not(.node),
.grid-2 > *:not(.node),
.grid-3 > *:not(.node) { position: relative; }

.grid-2 { display: grid; grid-template-columns: 1fr 1fr; }
.grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); }
.grid-2 > * + *, .grid-3 > * + * { border-left: var(--rule); }

/* an off-centre split, e.g. a portrait video beside a headline */
.split { display: grid; grid-template-columns: 1fr 1fr; }
.split > * + * { border-left: var(--rule); }
.split--wide-left  { grid-template-columns: 1.6fr 1fr; }
.split--wide-right { grid-template-columns: 1fr 1.6fr; }

.center { display: grid; place-items: center; }

/* the big blue pull quote */
.pull {
  display: grid;
  align-content: center;
  min-height: 19.25rem;
  padding: 1.6rem 1.8rem;
  background: var(--blue);
  color: var(--paper);
  font-size: 2.25rem;
  line-height: 1.18;
  letter-spacing: -.02em;
}
.pull--sm { font-size: 1.25rem; line-height: 1.3; min-height: 0; }

.headline-lg {
  font-variation-settings: "wght" 800;
  font-size: 3.5rem;
  line-height: .95;
  letter-spacing: -.03em;
}

/* --- 11. Layout page: hover-scrub ---------------------------------------- */

.scrub { position: relative; min-height: 28rem; cursor: ew-resize; }
.scrub > img { width: 100%; height: 100%; object-fit: contain; }
.scrub__label {
  position: absolute;
  inset: 0;
  display: grid;
  place-content: center;
  font-family: var(--note);
  font-style: italic;
  font-size: 4.875rem;
  color: var(--ink-mute);
  transition: opacity .3s var(--ease);
  pointer-events: none;
}
.scrub:hover .scrub__label { opacity: 0; }

/* --- 12. Motion page ----------------------------------------------------- */

.now-scroll {
  font-family: var(--poster);
  font-weight: 400;
  font-size: 12.5rem;
  line-height: .95;
  letter-spacing: -.005em;
  color: var(--blue);
  text-align: center;
  white-space: nowrap;
}

.reel { display: grid; gap: clamp(4rem, 14vh, 11rem); padding: 8vh 0 14vh; }

.reel__item {
  justify-self: center;
  width: 22.5rem;
  max-width: 78vw;
  opacity: 0;
  transform: scale(.55);
  transition: opacity .9s var(--ease), transform .9s var(--ease);
}
.reel__item--wide { width: 29.6rem; }
.reel__item.is-in { opacity: 1; transform: none; }

.reel__item:nth-child(3n + 2) { justify-self: end; }
.reel__item:nth-child(3n)     { justify-self: start; }

@media (prefers-reduced-motion: reduce) {
  .reel__item { opacity: 1; transform: none; transition: none; }
  .marquee__track { animation: none; }
}

/* --- 13. Responsive ------------------------------------------------------
   Four bands:

     > 1180   full two-column layout, as drawn
     ≤ 1180   still two columns (iPad landscape), just tighter padding
     ≤ 900    one column (iPad portrait and down). The copy gets a maximum
              measure so lines stay readable instead of running the full
              width, and the nodes that mark the column divider are hidden
              because that divider no longer exists.
     ≤ 640    the two-up grids inside a media column stack too (phones)
   ------------------------------------------------------------------------ */

@media (max-width: 1180px) {
  :root { --gutter: 1.5rem; --pad: 1.1rem; }

  .case__text { padding: 1rem 1.1rem 1.2rem 1.2rem; }
  .nav__link  { padding: .45em .8em .55em; }
  .site-header__inner { gap: .4rem; }
}

@media (max-width: 900px) {
  :root { --gutter: 1rem; --pad: 1rem; --inset: .75rem; }

  .t-display { font-size: clamp(2.75rem, 12vw, 7.1875rem); }
  .t-tagline { font-size: clamp(1.25rem, 5vw, 2.8125rem); }
  .t-index   { font-size: clamp(1.5rem, 5.5vw, 2.5rem); }
  .t-title   { font-size: clamp(2rem, 7vw, 3.5rem); }
  .headline-lg { font-size: clamp(1.75rem, 6vw, 3.5rem); }
  .pull      { font-size: clamp(1.25rem, 4vw, 2.25rem); min-height: 0; }
  .now-scroll { font-size: 17vw; }
  .scrub     { min-height: 60vw; }
  .scrub__label { font-size: clamp(2.5rem, 9vw, 4.875rem); }

  /* home */
  .hero { grid-template-columns: 1fr; }
  .hero__type { padding: 1.2rem 1rem 1.4rem; }

  .index__media { position: static; width: 100%; aspect-ratio: 16 / 7; }
  .index__list { border-top: var(--rule); }
  .index__link { padding-left: var(--gutter); min-height: 3rem; }


  /* case studies collapse to one column */
  .case__row, .case--mirror .case__row { grid-template-columns: 1fr; }
  .case--mirror .case__text,
  .case--mirror .case__media { order: 0; }
  .case__media, .case--mirror .case__text {
    border-left: 0;
    border-top: var(--rule);
  }
  .case__text { padding: 1.2rem var(--pad) 1.4rem; }

  /* a readable measure — the cell is full width, the text is not */
  .case__text > * { max-width: 38rem; }

  .case__body { grid-template-columns: 1fr; }
  /* the aside dissolves so its copy and its foot can land either side of
     the media: copy first, media, then the foot as the page's last band */
  .case__aside { display: contents; }
  .case__copy { order: 1; padding: 1.2rem var(--pad) 1.4rem; }
  .case__copy > * { max-width: 38rem; }
  .case__main { order: 2; border-left: 0; border-top: var(--rule); }
  .case__sentinel { display: none; }
  .case__foot {
    order: 3;
    position: static;
    border-top: var(--rule);
    opacity: 1;
    visibility: visible;
    transition: none;
  }
  .case__foot__body { padding: 1rem var(--pad) 1.2rem; }
  .case__foot > .bar-link { border-top: 0; }   /* the band's own top rule is enough */
  .case__main > .node { display: none; }

  /* these marked the column divider, which has just gone away */
  .case__row > .node { display: none; }

  .grid-3 { grid-template-columns: 1fr 1fr; }
  .grid-3 > :nth-child(3) { grid-column: 1 / -1; border-left: 0; border-top: var(--rule); }

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

@media (max-width: 640px) {
  .site-header__inner { flex-wrap: wrap; }
  .nav { order: 3; width: 100%; flex-wrap: wrap; padding-bottom: .3rem; }

  .split, .split--wide-left, .split--wide-right, .grid-2 { grid-template-columns: 1fr; }
  .split > * + *, .grid-2 > * + * { border-left: 0; border-top: var(--rule); }

  /* any node inside a grid that has just stacked is meaningless too */
  .split > .node, .grid-2 > .node, .grid-3 > .node,
  .split > * > .node, .grid-2 > * > .node, .grid-3 > * > .node { display: none; }

  .contact { grid-template-columns: 1fr; }

  /* the about text and its animation: side by side down to here, then one
     under the other */
  .about { grid-template-columns: 1fr; }
  .about__text > * { max-width: 38rem; }
  .about__aside {
    border-left: 0;
    border-top: var(--rule);
  }
  .about__aside > img,
  .about__aside > video { max-width: 22rem; margin-inline: auto; }  /* a full-width square is far too tall here */
}
/* the same, when motion-grid.js §9 finds no square that fits beside the text */
.about--stack { grid-template-columns: 1fr; }
.about--stack .about__text > * { max-width: 38rem; }
.about--stack .about__aside { border-left: 0; border-top: var(--rule); }
.about--stack .about__aside > video { max-width: 22rem; margin-inline: auto; }
