/* ==========================================================================
   kerseyfabrications.com

   Paper light. A rail carries identity and every link; the right side is a
   short, glanceable page. The brief is a link tree with a face on it, not a
   portfolio — if a section starts growing, it belongs on a sub-page.

   Nothing on this site reports a number that changes on its own: no view
   counts, no subscriber count, no "latest video". Everything here stays
   true without anyone maintaining it.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Typefaces
   -------------------------------------------------------------------------- */

@font-face {
   font-family: 'Big Shoulders Display';
   src: url('../fonts/big-shoulders.woff2') format('woff2');
   font-weight: 100 900;
   font-style: normal;
   font-display: swap;
}
@font-face {
   font-family: 'Instrument Sans';
   src: url('../fonts/instrument-sans.woff2') format('woff2');
   font-weight: 400 700;
   font-style: normal;
   font-display: swap;
}
@font-face {
   font-family: 'JetBrains Mono';
   src: url('../fonts/jetbrains-mono.woff2') format('woff2');
   font-weight: 100 800;
   font-style: normal;
   font-display: swap;
}

/* --------------------------------------------------------------------------
   2. Tokens
   -------------------------------------------------------------------------- */

:root {
   --paper: #fbfaf8;
   --paper-2: #f2f1ec;
   --rule: #e4e2dc;
   --rule-soft: #eeece7;

   --ink: #14181c; /* 17.2:1 on paper */
   --ink-2: #5c6570; /* 5.7:1  — all secondary text and mono labels */

   /* Kris's KF cyan. The bright original is far too light for text on paper,
      so links use a darkened cut; the logo keeps the real color.
      This cut is darker than strictly needed on flat paper (5.5:1 rather than
      4.6:1) so it still clears AA where a grid line crosses it — at #0e7c9e
      that overlap measured 4.2:1. */
   --accent: #0b6f8e; /* 5.5:1 on paper, 5.0:1 over a grid line */
   --accent-deep: #0a6280; /* hover, and white-on-this for solid buttons */
   --mark: #5dd6ff;

   /* Graph-paper ruling. Real engineering pads are ruled in blue-green, which
      happens to be the KF hue.

      Single level, deliberately. A fine grid plus heavier every-fifth lines
      looks better but cannot be made accessible: the two layers coincide, so
      a major intersection stacks four translucent lines into an effective 23%
      alpha and drops body text to 4.1:1. One layer means the worst case is a
      simple crossing at 9.8%, which holds every text color above 4.7:1. */
   --rule-grid: rgba(11, 111, 142, 0.05);

   --font-display: 'Big Shoulders Display', 'Arial Narrow', system-ui, sans-serif;
   --font-body: 'Instrument Sans', system-ui, -apple-system, 'Segoe UI', sans-serif;
   --font-mono: 'JetBrains Mono', ui-monospace, 'Cascadia Code', Consolas, monospace;

   --rail-w: 300px;

   --text-xs: 0.75rem;
   --text-sm: 0.875rem;
   --text-base: 1rem;
   --text-md: 1.0625rem;
   --text-lg: 1.1875rem;
   --text-xl: 1.375rem;

   --sp-1: 0.375rem;
   --sp-2: 0.625rem;
   --sp-3: 1rem;
   --sp-4: 1.5rem;
   --sp-5: 2.25rem;
   --sp-6: 3.25rem;

   --ease: cubic-bezier(0.2, 0.7, 0.3, 1);
}

/* --------------------------------------------------------------------------
   3. Base
   -------------------------------------------------------------------------- */

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

html {
   -webkit-text-size-adjust: 100%;
   scroll-behavior: smooth;
}

body {
   margin: 0;
   background-color: var(--paper);
   /* 28px ruling. See --rule-grid for why there is no heavier every-fifth
      line, tempting as it is. */
   background-image:
      linear-gradient(var(--rule-grid) 1px, transparent 1px),
      linear-gradient(90deg, var(--rule-grid) 1px, transparent 1px);
   background-size: 28px 28px;
   color: var(--ink);
   font-family: var(--font-body);
   font-size: var(--text-md);
   line-height: 1.6;
   -webkit-font-smoothing: antialiased;
}

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

/* None of the three faces carry U+2082, so a literal ₂ would fall back to a
   system font mid-word. <sub> subscripts the font's own numeral instead;
   line-height:0 keeps it from opening up the line box. */
sub {
   font-size: 0.72em;
   line-height: 0;
   vertical-align: -0.22em;
}

a {
   color: inherit;
}

h1,
h2,
h3 {
   margin: 0;
   font-family: var(--font-display);
   font-weight: 700;
   line-height: 0.94;
   letter-spacing: 0.005em;
}

p {
   margin: 0 0 var(--sp-3);
}

p:last-child {
   margin-bottom: 0;
}

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

.skip {
   position: absolute;
   left: 1rem;
   top: -5rem;
   z-index: 200;
   background: var(--ink);
   color: var(--paper);
   font-family: var(--font-mono);
   font-size: var(--text-xs);
   font-weight: 500;
   text-transform: uppercase;
   letter-spacing: 0.09em;
   padding: 0.7rem 1.1rem;
   text-decoration: none;
   transition: top 0.16s var(--ease);
}

.skip:focus {
   top: 1rem;
}

/* --------------------------------------------------------------------------
   4. Shell
   -------------------------------------------------------------------------- */

/* Capped and centred. Without a ceiling the work column reaches 2244px on a
   2560px display — far too wide to read, and it stretched the hero photo to
   81% of the viewport while upscaling a 1100px source to 2244px. */
.shell {
   display: grid;
   grid-template-columns: var(--rail-w) minmax(0, 1fr);
   max-width: 1500px;
   margin-inline: auto;
}

.work {
   min-width: 0;
   border-left: 1px solid var(--rule);
}

/* --------------------------------------------------------------------------
   5. Rail
   -------------------------------------------------------------------------- */

.rail {
   position: sticky;
   top: 0;
   height: 100vh;
   overflow-y: auto;
   overscroll-behavior: contain;
   padding: var(--sp-4);
   display: flex;
   flex-direction: column;
   gap: var(--sp-3);
}

.rail__home {
   display: block;
   width: 42px;
   flex: none;
   transition: opacity 0.14s var(--ease);
}

.rail__home:hover {
   opacity: 0.7;
}

.rail__mark {
   width: 42px;
   height: 42px;
}

/* Portrait beside the name rather than above it: a face helps someone learn
   who this is at a glance, but it must not push the nav down the rail. */
.rail__ident {
   display: flex;
   align-items: flex-start;
   gap: var(--sp-3);
}

.rail__portrait {
   width: 104px;
   height: 104px;
   flex: none;
   object-fit: cover;
   border: 1px solid var(--rule);
}

.rail__name {
   font-family: var(--font-display);
   font-size: 2.6rem;
   font-weight: 800;
   text-transform: uppercase;
   line-height: 0.84;
   margin: 0;
}

.rail__role {
   margin: 0;
   font-family: var(--font-mono);
   font-size: var(--text-xs);
   font-weight: 500;
   text-transform: uppercase;
   letter-spacing: 0.1em;
   color: var(--accent);
}

.rail__spans {
   display: flex;
   gap: var(--sp-4);
   margin: 0;
   padding: var(--sp-2) 0;
   border-top: 1px solid var(--rule);
   border-bottom: 1px solid var(--rule);
}

.rail__spans dt {
   font-family: var(--font-mono);
   font-size: 0.6875rem;
   text-transform: uppercase;
   letter-spacing: 0.1em;
   color: var(--ink-2);
}

.rail__spans dd {
   margin: 0.1rem 0 0;
   font-family: var(--font-display);
   font-size: 1.6rem;
   font-weight: 700;
   line-height: 1;
}

.rail__spans dd span {
   font-family: var(--font-mono);
   font-size: 0.6875rem;
   font-weight: 500;
   color: var(--ink-2);
   margin-left: 0.2rem;
   vertical-align: 0.5em;
}

.rail__label {
   font-family: var(--font-mono);
   font-size: 0.6875rem;
   text-transform: uppercase;
   letter-spacing: 0.13em;
   color: var(--ink-2);
   margin: 0 0 0.3rem;
}

.rail__group {
   margin: 0;
   padding: 0;
   list-style: none;
}

.rail__link {
   display: flex;
   align-items: baseline;
   justify-content: space-between;
   gap: var(--sp-2);
   padding: 0.34rem 0;
   border-bottom: 1px solid var(--rule-soft);
   text-decoration: none;
   font-size: var(--text-base);
   transition: color 0.14s var(--ease), padding-left 0.14s var(--ease);
}

.rail__link:hover,
.rail__link:focus-visible {
   color: var(--accent);
   padding-left: 0.3rem;
}

.rail__link span {
   font-family: var(--font-mono);
   font-size: var(--text-xs);
   color: var(--ink-2);
   flex: 0 1 auto;
}

/* Absolutely positioned so it does not become a third item in the
   space-between row and shove the label into the middle. */
.rail__link[aria-current='page'] {
   position: relative;
   padding-left: 0.9rem;
   color: var(--accent);
   font-weight: 500;
}

.rail__link[aria-current='page']::before {
   content: '';
   position: absolute;
   left: 0;
   top: 0.62em;
   width: 0.42rem;
   height: 0.42rem;
   background: var(--accent);
}

.rail__foot {
   margin-top: auto;
   padding-top: var(--sp-3);
   font-family: var(--font-mono);
   font-size: 0.6875rem;
   line-height: 1.7;
   color: var(--ink-2);
}

.rail__foot a {
   color: var(--accent);
}

/* --------------------------------------------------------------------------
   6. Home
   -------------------------------------------------------------------------- */

.lede {
   padding: var(--sp-5) var(--sp-5) var(--sp-4);
}

/* The break between the two sentences is authored with <br>, so no balancing
   here — and the measure has to be wide enough that neither sentence wraps
   again on its own. */
.lede__line {
   font-size: clamp(1.75rem, 3.4vw, 2.9rem);
   font-weight: 800;
   text-transform: uppercase;
   line-height: 0.94;
   max-width: 32ch;
}

.lede__sub {
   margin: var(--sp-3) 0 0;
   font-size: var(--text-lg);
   line-height: 1.5;
   color: var(--ink-2);
   max-width: 56ch;
}

.lede__line em {
   font-style: normal;
   color: var(--accent);
}

/* Second belt: on a short, wide window the ratio alone would still make this
   dominate, so cap it against viewport height too. object-fit crops rather
   than distorts when the cap bites. */
.shot {
   display: block;
   width: 100%;
   aspect-ratio: 2.7 / 1;
   max-height: 38vh;
   object-fit: cover;
   object-position: 50% 38%;
   border-block: 1px solid var(--rule);
}

/* Three things, said plainly. Each row is also a route out. */
.doing {
   margin: 0;
   padding: var(--sp-5) var(--sp-5);
}

.doing__row {
   display: grid;
   grid-template-columns: 7.5rem minmax(0, 1fr);
   gap: var(--sp-3) var(--sp-4);
   padding: var(--sp-3) 0;
   border-bottom: 1px solid var(--rule-soft);
   align-items: baseline;
}

.doing__row:first-child {
   border-top: 1px solid var(--rule);
}

.doing dt {
   font-family: var(--font-display);
   font-size: var(--text-xl);
   font-weight: 700;
   text-transform: uppercase;
   line-height: 1;
}

.doing dd {
   margin: 0;
   color: var(--ink-2);
   max-width: 56ch;
}

.doing a {
   color: var(--accent);
   text-decoration-thickness: 1px;
   text-underline-offset: 3px;
   white-space: nowrap;
}

.doing a:hover {
   color: var(--ink);
}

/* --------------------------------------------------------------------------
   7. Bands and tiles
   -------------------------------------------------------------------------- */

.band {
   padding: var(--sp-5);
   border-top: 1px solid var(--rule);
}

.band__head {
   display: flex;
   align-items: baseline;
   justify-content: space-between;
   gap: var(--sp-3);
   flex-wrap: wrap;
   margin-bottom: var(--sp-4);
}

.band__title {
   font-family: var(--font-mono);
   font-size: var(--text-xs);
   font-weight: 500;
   text-transform: uppercase;
   letter-spacing: 0.14em;
   color: var(--ink);
   margin: 0;
}

.band__more {
   font-family: var(--font-mono);
   font-size: var(--text-xs);
   text-transform: uppercase;
   letter-spacing: 0.1em;
   color: var(--accent);
   text-decoration: none;
}

.band__more:hover {
   color: var(--ink);
}

.grid {
   display: grid;
   grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr));
   gap: var(--sp-4) var(--sp-3);
}

.tile {
   display: flex;
   flex-direction: column;
   text-decoration: none;
   color: inherit;
}

.tile__media {
   position: relative;
   overflow: hidden;
   background: var(--paper-2);
   border: 1px solid var(--rule);
   margin-bottom: var(--sp-2);
}

.tile__media img {
   width: 100%;
   aspect-ratio: 16 / 9;
   object-fit: cover;
   transition: transform 0.45s var(--ease);
}

.tile:hover .tile__media img,
.tile:focus-visible .tile__media img {
   transform: scale(1.04);
}

/* Always visible, never a hover-only cue. */
.tile__play {
   position: absolute;
   left: 0;
   bottom: 0;
   width: 2.4rem;
   height: 2.4rem;
   background: var(--accent);
   display: grid;
   place-items: center;
}

.tile__play::after {
   content: '';
   border-style: solid;
   border-width: 0.38rem 0 0.38rem 0.6rem;
   border-color: transparent transparent transparent #fff;
   margin-left: 0.1rem;
}

.tile__kind {
   font-family: var(--font-mono);
   font-size: 0.6875rem;
   font-weight: 500;
   text-transform: uppercase;
   letter-spacing: 0.11em;
   color: var(--ink-2);
   margin: 0 0 0.25rem;
}

.tile__title {
   font-size: var(--text-lg);
   font-weight: 700;
   text-transform: uppercase;
   line-height: 1.02;
   margin: 0;
   transition: color 0.14s var(--ease);
}

.tile:hover .tile__title,
.tile:focus-visible .tile__title {
   color: var(--accent);
}

.tile__desc {
   color: var(--ink-2);
   font-size: var(--text-sm);
   margin: 0.3rem 0 0;
}

/* --------------------------------------------------------------------------
   8. Buttons
   -------------------------------------------------------------------------- */

.btns {
   display: flex;
   flex-wrap: wrap;
   gap: var(--sp-2);
}

.btns--head {
   margin-top: var(--sp-4);
}

.btn {
   display: inline-flex;
   align-items: center;
   font-family: var(--font-mono);
   font-size: var(--text-xs);
   font-weight: 500;
   text-transform: uppercase;
   letter-spacing: 0.1em;
   text-decoration: none;
   padding: 0.75rem 1.2rem;
   border: 1px solid var(--ink);
   color: var(--ink);
   transition: background-color 0.14s var(--ease), color 0.14s var(--ease),
      border-color 0.14s var(--ease);
}

.btn:hover {
   background: var(--ink);
   color: var(--paper);
}

/* White on --accent is only 4.0:1; on --accent-deep it is 6.1:1. */
.btn--go {
   background: var(--accent-deep);
   border-color: var(--accent-deep);
   color: #fff;
}

.btn--go:hover {
   background: var(--ink);
   border-color: var(--ink);
   color: var(--paper);
}

/* --------------------------------------------------------------------------
   9. Sub-pages
   -------------------------------------------------------------------------- */

.phead {
   padding: var(--sp-5) var(--sp-5) var(--sp-4);
}

.phead__title {
   font-size: clamp(2.4rem, 5vw, 4rem);
   font-weight: 800;
   text-transform: uppercase;
   line-height: 0.88;
   margin-bottom: var(--sp-3);
}

.phead__sub {
   color: var(--ink-2);
   font-size: var(--text-lg);
   max-width: 58ch;
}

/* Credentials, sized down deliberately. The story in .phead__sub carries the
   page; these are the receipts underneath it, not the headline. */
.creds {
   display: flex;
   flex-wrap: wrap;
   gap: var(--sp-2) var(--sp-5);
   list-style: none;
   margin: var(--sp-4) 0 0;
   padding: 0;
   font-family: var(--font-mono);
   font-size: var(--text-xs);
   text-transform: uppercase;
   letter-spacing: 0.08em;
   color: var(--ink-2);
}

.creds b {
   font-family: var(--font-display);
   font-size: 1.3rem;
   font-weight: 700;
   color: var(--ink);
   letter-spacing: 0;
   margin-right: 0.35rem;
}

.prose a {
   color: var(--accent);
   text-underline-offset: 3px;
}

.prose a:hover {
   color: var(--ink);
}

/* Project rows. Text leads and stays full-measure; the photograph is a
   supporting thumbnail on the right. A row without a photo just goes without
   one — the left column keeps its width either way, so the list stays aligned
   rather than looking half-finished. */
.projs {
   list-style: none;
   margin: 0;
   padding: 0;
   border-top: 1px solid var(--rule);
}

.proj {
   display: grid;
   grid-template-columns: minmax(0, 1fr) 240px;
   gap: var(--sp-4);
   align-items: start;
   padding: var(--sp-4) 0;
   border-bottom: 1px solid var(--rule-soft);
}

.proj__name {
   font-size: var(--text-xl);
   font-weight: 700;
   text-transform: uppercase;
   margin: 0 0 var(--sp-2);
}

.proj__desc {
   color: var(--ink-2);
   max-width: 62ch;
   margin: 0 0 var(--sp-2);
}

.proj__meta {
   font-family: var(--font-mono);
   font-size: var(--text-xs);
   color: var(--ink-2);
   margin: 0;
}

.proj__meta a {
   color: var(--accent);
   text-underline-offset: 3px;
   white-space: nowrap;
}

.proj__meta a:hover {
   color: var(--ink);
}

.proj__shot {
   grid-column: 2;
   width: 100%;
   aspect-ratio: 16 / 10;
   object-fit: cover;
   border: 1px solid var(--rule);
}

.band__note {
   margin-top: var(--sp-4);
   font-size: var(--text-sm);
   color: var(--ink-2);
}

.topics {
   display: grid;
   grid-template-columns: repeat(auto-fit, minmax(min(340px, 100%), 1fr));
   gap: var(--sp-5);
}

.topic {
   border-top: 2px solid var(--accent);
   padding-top: var(--sp-2);
}

.topic__title {
   font-size: var(--text-xl);
   font-weight: 700;
   text-transform: uppercase;
   margin-bottom: var(--sp-2);
}

.topic__desc {
   color: var(--ink-2);
   font-size: var(--text-sm);
   margin-bottom: var(--sp-2);
}

.topic__for {
   font-family: var(--font-mono);
   font-size: 0.6875rem;
   text-transform: uppercase;
   letter-spacing: 0.1em;
   color: var(--accent);
   margin: 0;
}

.spec {
   margin: 0;
   border-top: 1px solid var(--rule);
}

.spec__row {
   display: grid;
   grid-template-columns: minmax(8rem, 12rem) minmax(0, 1fr);
   gap: var(--sp-2) var(--sp-4);
   padding: var(--sp-3) 0;
   border-bottom: 1px solid var(--rule-soft);
}

.spec dt {
   font-family: var(--font-mono);
   font-size: var(--text-xs);
   text-transform: uppercase;
   letter-spacing: 0.11em;
   color: var(--ink-2);
   padding-top: 0.2em;
}

.spec dd {
   margin: 0;
   max-width: 62ch;
}

.gigs {
   list-style: none;
   margin: 0;
   padding: 0;
   border-top: 1px solid var(--rule);
}

.gig {
   display: grid;
   grid-template-columns: 8rem minmax(0, 1fr);
   gap: var(--sp-4);
   padding: var(--sp-4) 0;
   border-bottom: 1px solid var(--rule-soft);
}

.gig__year {
   display: block;
   font-family: var(--font-display);
   font-size: 1.9rem;
   font-weight: 700;
   line-height: 1;
}

.gig__date {
   display: block;
   margin-top: 0.2rem;
   font-family: var(--font-mono);
   font-size: var(--text-xs);
   color: var(--ink-2);
}

.gig__venue {
   font-size: var(--text-xl);
   font-weight: 700;
   text-transform: uppercase;
   margin: 0;
}

.gig__role {
   margin: 0.25rem 0 0;
   font-family: var(--font-mono);
   font-size: var(--text-xs);
   text-transform: uppercase;
   letter-spacing: 0.1em;
   color: var(--ink-2);
}

.gig__role--key {
   color: var(--accent);
}

.gig__talks {
   list-style: none;
   margin: var(--sp-3) 0 0;
   padding: 0;
}

.gig__talks li {
   position: relative;
   padding-left: 1.1rem;
   margin-bottom: 0.3rem;
   color: var(--ink-2);
   max-width: 62ch;
}

.gig__talks li::before {
   content: '';
   position: absolute;
   left: 0;
   top: 0.72em;
   width: 0.55rem;
   height: 1px;
   background: var(--accent);
}

.gig__talks a {
   color: var(--ink);
   text-decoration-color: var(--accent);
   text-underline-offset: 3px;
}

.gig__talks a:hover {
   color: var(--accent);
}

.repos {
   list-style: none;
   margin: 0;
   padding: 0;
   border-top: 1px solid var(--rule);
}

.repo {
   display: grid;
   grid-template-columns: minmax(0, 8rem) minmax(0, 1fr) auto;
   gap: var(--sp-3);
   align-items: baseline;
   padding: var(--sp-3) 0;
   border-bottom: 1px solid var(--rule-soft);
   text-decoration: none;
   color: inherit;
   transition: padding-left 0.14s var(--ease), background-color 0.14s var(--ease);
}

.repo:hover,
.repo:focus-visible {
   padding-left: 0.5rem;
   background: var(--paper-2);
}

.repo__name {
   font-family: var(--font-display);
   font-size: var(--text-xl);
   font-weight: 700;
   text-transform: uppercase;
   line-height: 1;
}

.repo:hover .repo__name {
   color: var(--accent);
}

.repo__desc {
   color: var(--ink-2);
   font-size: var(--text-sm);
   margin: 0;
}

.repo__tags {
   font-family: var(--font-mono);
   font-size: 0.6875rem;
   color: var(--ink-2);
   white-space: nowrap;
}

.close {
   padding: var(--sp-5);
   border-top: 1px solid var(--rule);
   background: var(--paper-2);
}

.close__title {
   font-size: clamp(1.8rem, 3.4vw, 2.6rem);
   font-weight: 800;
   text-transform: uppercase;
   line-height: 0.92;
   margin-bottom: var(--sp-3);
   max-width: 22ch;
}

.close__body {
   color: var(--ink-2);
   max-width: 56ch;
   margin-bottom: var(--sp-4);
}

/* --------------------------------------------------------------------------
   10. Reveal
   -------------------------------------------------------------------------- */

.js .rv {
   opacity: 0;
   transform: translateY(14px);
}

.js .rv.in {
   opacity: 1;
   transform: none;
   transition: opacity 0.5s var(--ease), transform 0.5s var(--ease);
}

/* --------------------------------------------------------------------------
   11. Responsive
   -------------------------------------------------------------------------- */

@media (max-width: 940px) {
   .shell {
      grid-template-columns: 1fr;
   }

   .rail {
      position: static;
      height: auto;
      overflow: visible;
      display: grid;
      grid-template-columns: repeat(2, minmax(0, 1fr));
      grid-template-areas:
         'mark  mark'
         'name  name'
         'role  role'
         'spans spans'
         'pages links'
         'foot  foot';
      column-gap: var(--sp-4);
      row-gap: var(--sp-4);
      align-items: start;
      border-bottom: 1px solid var(--rule);
   }

   .rail__home {
      grid-area: mark;
   }

   .rail__ident {
      grid-area: name;
   }

   /* Without an explicit area this auto-places after every named one, which
      dropped the role line below the address. */
   .rail__role {
      grid-area: role;
   }

   .rail__spans {
      grid-area: spans;
   }

   .rail__pages {
      grid-area: pages;
   }

   .rail__links {
      grid-area: links;
   }

   .rail__foot {
      grid-area: foot;
      margin-top: 0;
   }

   .work {
      border-left: 0;
   }
}

@media (max-width: 640px) {
   :root {
      --sp-5: 1.25rem;
      --sp-6: 2.25rem;
   }

   .rail__link {
      flex-wrap: wrap;
      row-gap: 0;
      padding: 0.3rem 0;
   }

   .rail__name {
      font-size: 2.2rem;
   }

   .shot {
      aspect-ratio: 4 / 3;
   }

   .doing__row,
   .spec__row,
   .gig,
   .repo {
      grid-template-columns: 1fr;
      gap: 0.35rem;
   }

   /* Photo drops below the text rather than squeezing beside it. */
   .proj {
      grid-template-columns: 1fr;
      gap: var(--sp-3);
   }

   .proj__shot {
      grid-column: 1;
      max-width: 420px;
   }

   .gig__date {
      display: inline;
      margin-left: 0.6rem;
   }
}

/* --------------------------------------------------------------------------
   12. Touch targets

   Text links sit at 14-20px tall, which is fine with a mouse and fiddly with
   a thumb. Vertical padding on an inline element grows its hit box without
   changing the line box, so these get bigger to touch without the layout
   moving. The dense talk list also gets extra row spacing, otherwise the
   enlarged targets would overlap each other and cause mis-taps.
   -------------------------------------------------------------------------- */

@media (pointer: coarse) {
   .band__more,
   .rail__foot a {
      display: inline-block;
      padding-block: 0.7rem;
   }

   .doing a,
   .prose a,
   .spec dd a {
      padding-block: 0.55rem;
   }

   .gig__talks a {
      padding-block: 0.45rem;
   }

   .gig__talks li {
      margin-bottom: 0.8rem;
   }
}

/* --------------------------------------------------------------------------
   13. Reduced motion
   -------------------------------------------------------------------------- */

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

   *,
   *::before,
   *::after {
      animation-duration: 0.01ms !important;
      transition-duration: 0.01ms !important;
   }

   .js .rv {
      opacity: 1;
      transform: none;
   }
}
