/* Ted Kane — portfolio
   One column. Black on white. No rules, no boxes: space does the dividing.
   Neue Haas Grotesk, two weights. Adobe Fonts families:
   neue-haas-grotesk-display, neue-haas-grotesk-text. */

:root {
  --display: "neue-haas-grotesk-display", "Neue Haas Grotesk Display Pro", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --text: "neue-haas-grotesk-text", "Neue Haas Grotesk Text Pro", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --ink: #000;
  --paper: #fff;
  --mute: #767676;
  --soft: #333;
  --frame: #f2f2f2;
  --measure: 38rem;
  --page: 72rem;
  --gutter: clamp(1.25rem, 4vw, 3rem);
}

* { box-sizing: border-box; }

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

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--text);
  font-size: 1.0625rem;
  line-height: 1.45;
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  padding: 0 var(--gutter);
}

a { color: inherit; text-decoration: none; }
a:hover { text-decoration: underline; text-underline-offset: 0.15em; }

/* ---- the name, centred, alone ---- */
.top {
  max-width: var(--page);
  margin: 0 auto;
  text-align: center;
  padding: 3rem 0 4rem;
}
.top .name {
  margin: 0;
  font-family: var(--display);
  font-weight: 500;
  font-size: 1.125rem;
  letter-spacing: -0.005em;
}
.top .thesis {
  margin: 0.4rem 0 0;
  font-size: 0.9375rem;
  color: var(--mute);
}

main { max-width: var(--page); margin: 0 auto; }

/* ---- projects, as a timeline ----
   a period sits in a slim column on the left of every entry, the way a
   résumé lists years; the entry itself takes the rest of the width */
.project {
  display: grid;
  grid-template-columns: 4.5rem 1fr;
  column-gap: 1.25rem;
  padding: 0 0 5.5rem;
}
.project > * { grid-column: 2; min-width: 0; }
.project > .when {
  grid-column: 1;
  grid-row: 1 / span 20;
  margin: 0;
  padding-top: 0.5rem;
  font-size: 0.8125rem;
  color: var(--mute);
}


/* the role comes first, quietly; the name is the link and goes through */
.project h2 .role {
  color: var(--mute);
  font-weight: 500;
}
.project h2 .fact.role {
  font: inherit;
  text-decoration: none;
}
.project h2 .fact.role:hover,
.project h2 .fact.role.on { color: var(--ink); }

/* the earlier and smaller work keeps the same shape but less room, and its
   image sits to the right */
.project.small .rest.lift { max-width: 44rem; }
.project.small figure,
.project.small .row { max-width: 44rem; margin-left: auto; }
.project.small figure.plain { max-width: 26rem; }
.project.small .row figure { max-width: none; margin: 0; }

/* the minimised rows: the period, the name, one line, and a reveal that
   opens the images. Compact enough to read as a list */
.project.mini { padding-bottom: 2.5rem; }
.project.mini .project-head { margin-bottom: 0.9rem; }
.project.mini .rest.lift { margin-bottom: 0.4rem; font-size: 0.9375rem; max-width: var(--measure); }
.project.mini .fact-panel { padding-top: 0.7rem; }
.project.mini .fact-panel .rest { font-size: 0.9375rem; }

.project-head { margin-bottom: 2.25rem; }
.project h2 {
  font-family: var(--display);
  font-weight: 500;
  font-size: 1.5rem;
  line-height: 1.2;
  letter-spacing: -0.01em;
  margin: 0 0 0.35rem;
}
.facts {
  margin: 0;
  font-size: 0.8125rem;
  color: var(--mute);
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.4rem;
}
.facts .sep { color: #c9c9c9; }
.fact {
  appearance: none;
  background: none;
  border: 0;
  padding: 0;
  margin: 0;
  font: inherit;
  color: var(--mute);
  cursor: pointer;
  text-decoration: underline dotted;
  text-decoration-color: #cfcfcf;
  text-underline-offset: 0.3em;
  transition: color 220ms ease, text-decoration-color 220ms ease;
}
.fact:hover, .fact.on {
  color: var(--ink);
  text-decoration-color: var(--ink);
}

.fact-panel {
  max-width: var(--measure);
  padding-top: 0.9rem;
}
.fact-panel p {
  margin: 0 0 0.6rem;
  font-size: 0.9375rem;
  line-height: 1.45;
  color: var(--soft);
}
.fact-panel .rest { color: var(--ink); }
.rest.lift a { text-decoration: underline; text-underline-offset: 0.15em; }
.rest.lift {
  max-width: var(--measure);
  margin: 0 0 2.25rem;
  font-size: 1rem;
  line-height: 1.45;
}
.fact-panel em { font-style: normal; color: var(--mute); }
.tools {
  display: block;
  margin-top: 0.35rem;
  font-size: 0.8125rem;
  color: var(--mute);
}

/* with JavaScript: the lines stack in one place and cross-fade, so opening
   one never pushes the page around */
.fact-panel.live { display: grid; }
.fact-panel.live p {
  grid-area: 1 / 1;
  margin: 0;
  opacity: 0;
  transition: opacity 260ms ease;
  pointer-events: none;
}
.fact-panel.live p.on { opacity: 1; pointer-events: auto; }   /* the visible line can hold a button */

.lede {
  font-family: var(--display);
  font-weight: 500;
  font-size: 1.25rem;
  line-height: 1.3;
  letter-spacing: -0.01em;
  max-width: 30rem;
  margin: 2.5rem 0 2.25rem;
  text-wrap: balance;
}

.shot-title {
  font-family: var(--display);
  font-weight: 500;
  color: var(--ink);
  margin-right: 0.35rem;
}

figure { margin: 0 0 3rem; }
picture { display: block; }
figure img {
  display: block;
  width: 100%;
  height: auto;
  background: var(--frame);
}
figcaption {
  font-size: 0.8125rem;
  color: var(--mute);
  margin-top: 0.75rem;
}
figure.narrow { max-width: 17rem; }
.row {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.25rem;
}
.row figure { margin: 0; }
figure video {
  display: block;
  width: 100%;
  height: auto;
  background: var(--frame);
}
.project figure:last-of-type { margin-bottom: 0; }

figcaption a { color: var(--ink); text-decoration: underline; text-underline-offset: 0.15em; }

.text {
  max-width: var(--measure);
  margin: 0 0 4.5rem;
}
.text p { margin: 0 0 1.1em; }
.text p:last-child { margin-bottom: 0; }
.text a { text-decoration: underline; text-underline-offset: 0.15em; text-decoration-thickness: from-font; }

/* ---- three slides, list on the right ---- */
.slides {
  display: grid;
  grid-template-columns: 1fr 17rem;
  gap: 2.75rem;
  align-items: start;
  margin-bottom: 0.75rem;
}
.slides-stage { position: relative; aspect-ratio: 8 / 5; overflow: hidden; }
.slide {
  display: none;
  width: 100%;
  height: auto;
}
/* each image carries white above its device (53px of 1000 on the Macs, 120 on
   the phones), so it is lifted by exactly that much: every device's top edge
   lands on the stage's top edge, level with the first title in the list.
   Margin percentages resolve against width, and the images are 8:5, so a
   fraction f of the height is f x 62.5% of the width. */
.slide img { display: block; width: 100%; height: auto; margin-top: calc(var(--lift, 0) * -62.5%); }
.slide[data-slide="0"], .slide[data-slide="1"] { --lift: 0.053; }
.slide[data-slide="2"] { --lift: 0.12; }
.slide.on { display: block; }

/* the first title's capitals, not its line box, meet the devices' top edge:
   the line box carries about 0.3rem of leading above the letters */
.slides-side { padding-top: 0; margin-top: -0.3rem; }
.slides-list { display: block; }

/* every step keeps its full height whether or not it is the live one, so the
   titles below never move when the description comes up */
.step { display: block; padding: 0 0 0.85rem; }
.step-pick {
  appearance: none;
  background: none;
  border: 0;
  padding: 0;
  margin: 0;
  font: inherit;
  text-align: left;
  cursor: pointer;
  display: block;
}
.step-title {
  display: block;
  font-family: var(--display);
  font-weight: 500;
  font-size: 1.375rem;
  line-height: 1.15;
  letter-spacing: -0.01em;
  color: #c9c9c9;
  transition: color 380ms ease;
}
.step-pick:hover .step-title { color: var(--mute); }
.step.on .step-title { color: var(--ink); }

/* one slot for the description, under the list: the notes stack in the same
   cell and cross-fade, so the titles above never move and nothing gapes */
.step-notes {
  display: grid;
  margin-top: 0.6rem;
}
.step-desc {
  grid-area: 1 / 1;
  margin: 0;
  font-size: 0.875rem;
  line-height: 1.4;
  color: var(--soft);
  opacity: 0;
  pointer-events: none;
  transition: opacity 380ms ease;
}
.step-desc.on { opacity: 1; pointer-events: auto; }
.step-desc a { color: var(--ink); text-decoration: underline; text-underline-offset: 0.15em; }

.step-bar {
  display: block;
  height: 1px;
  width: 0;
  margin-top: 0.5rem;
  background: var(--ink);
}

.stack { margin: 1.75rem 0 0; }
.stack > div {
  display: grid;
  grid-template-columns: 9rem 1fr;
  gap: 1.75rem;
  margin-bottom: 1.5rem;
}
.stack > div:last-child { margin-bottom: 0; }
.stack dt {
  margin: 0;
  font-family: var(--display);
  font-weight: 500;
  font-size: 0.9375rem;
  padding-top: 0.1rem;
}
.stack dd { margin: 0; color: var(--soft); font-size: 0.9375rem; }
.stack em { font-style: normal; color: var(--mute); }

/* ---- also ---- */
.also {
  list-style: none;
  padding: 0;
  margin: 0;
  max-width: var(--measure);
}
.also li { margin-bottom: 0.7rem; color: var(--soft); }
.also li:last-child { margin-bottom: 0; }
.also li span {
  font-family: var(--display);
  font-weight: 500;
  color: var(--ink);
  margin-right: 0.45rem;
}

/* ---- about ---- */
.about {
  padding: 0 0 9rem;
  max-width: var(--measure);
}
.about p { margin: 0 0 0.6em; }
.about a { text-decoration: underline; text-underline-offset: 0.15em; }
.quiet { color: var(--mute); }
.about em { font-style: normal; }

@media (prefers-reduced-motion: reduce) {
  .fact, .fact-panel, .fact-panel p, .fact-panel.live p { transition: none; }
}

/* ---- small screens ---- */
@media (max-width: 40rem) {
  .top { padding: 2rem 0 2.75rem; }
  .project { grid-template-columns: 1fr; padding-bottom: 3.5rem; }
  .project > * { grid-column: 1; }
  .project > .when { grid-row: auto; padding-top: 0; margin-bottom: 0.5rem; }
  .project.small figure, .project.small figure.plain, .project.small .row { max-width: none; margin-left: 0; }
  .project.mini { padding-bottom: 2.5rem; }
  .text { margin-bottom: 3rem; }
  .stack > div { grid-template-columns: 1fr; gap: 0.25rem; margin-bottom: 1.25rem; }
  .row { grid-template-columns: 1fr 1fr; gap: 0.75rem; }
  .slides { grid-template-columns: 1fr; gap: 1.25rem; }
  .slides-list { padding-top: 0; }
  .slides-side { margin-top: 0; }   /* stacked under the image: nothing to meet */
  .step { padding-bottom: 0.7rem; }
  .step-title { font-size: 1.125rem; }
  .row figure:last-child { grid-column: 1 / -1; }   /* the CFD wants the room */
  .lede { font-size: 1.125rem; margin: 1.75rem 0 1.75rem; }
  .about { padding-bottom: 6rem; }
}

/* every project title is the way to the thing itself, and says so */
.project h2 a {
  text-decoration: underline;
  text-underline-offset: 0.14em;
  text-decoration-thickness: 1px;
  text-decoration-color: rgba(0, 0, 0, 0.55);
  transition: text-decoration-color 140ms ease;
}
.project h2 a:hover { text-decoration-color: var(--ink); }



/* ---- "see" at the end of a hardware line opens its images ---- */
.see {
  display: inline-flex;
  align-items: center;
  gap: 0.2em;
  margin-left: 0.35em;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  color: var(--mute);
  cursor: pointer;
  vertical-align: baseline;
}
.see svg { transition: transform 260ms ease; }
.see:hover { color: var(--ink); }
.project.open .see svg, .top.open .see svg { transform: rotate(180deg); }
/* the fold's height is set by the script from what it holds, so it opens to
   the pictures whenever they arrive; closed it is exactly nothing */
.fold { height: 0; overflow: hidden; transition: height 360ms ease; }
.fold-in { padding-top: 1.25rem; }
/* the images sit in a row, all the same size */
.fold-in { display: grid; column-gap: 1.25rem; row-gap: 0.75rem; }
.fold-in > figure { margin: 0; }
.fold-in.two { grid-template-columns: 1fr 1fr; }
/* a row of pictures as they are, all one height: each grows by its aspect
   ratio (set inline), so wide ones take more of the line and tall ones less */
.fold-in.row { display: flex; align-items: stretch; }
.fold-in.row > figure { flex: 0 1 0; min-width: 0; }
.see:focus:not(:focus-visible) { outline: none; }
@media (max-width: 40rem) {
  .fold-in.two { grid-template-columns: 1fr; }
  .fold-in.row { display: grid; }
}
@media (prefers-reduced-motion: reduce) {
  .fold, .see svg { transition: none; }
}

/* ---- a clip inside a fold, full width, the pictures in their row under it ---- */
.fold .clip { margin: 0; }
.fold .clip .embed { position: relative; aspect-ratio: 16 / 9; background: var(--frame); }
.fold .clip .embed iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.fold .clip figcaption a { text-decoration: underline; text-underline-offset: 0.15em; }
.fold .row { display: flex; align-items: stretch; column-gap: 1.25rem; }
.fold .row > figure { flex: 0 1 0; min-width: 0; margin: 0; }
@media (max-width: 40rem) {
  .fold .row { display: grid; row-gap: 0.75rem; }
}

.fold .clip figcaption { font-size: 0.8125rem; color: var(--mute); margin-top: 0.6rem; }
