/* Work, project and About pages. */

.page-head { margin: 0 0 clamp(40px, 8vh, 88px); }
.page-head__title { margin: 0; font-size: clamp(3.5rem, 10vw, 9rem); }
.page-head__lead { margin: 20px 0 0; max-width: 40ch; font-size: clamp(1.05rem, 1.6vw, 1.3rem); color: var(--dim); }

.section-label {
  margin: 0 0 20px;
  font: 500 12px/1.4 var(--sans); letter-spacing: 0.1em; text-transform: uppercase; color: var(--dim);
}

/* ---- Work: grid of projects ---- */

.work, .about-page {
  padding: calc(var(--nav-h) + clamp(48px, 10vh, 120px)) var(--gutter) clamp(64px, 12vh, 140px);
}

.work__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(40px, 6vw, 72px) clamp(16px, 3vw, 40px);
}
@media (max-width: 800px) { .work__grid { grid-template-columns: 1fr; } }

.work-card { display: block; }
.work-card__frame { aspect-ratio: 16 / 10; overflow: hidden; background: #141414; }
.work-card__frame img {
  width: 100%; height: 100%; object-fit: cover; object-position: top center;
  filter: brightness(0.82);
  transition: filter 400ms var(--ease), transform 900ms var(--ease);
}
.work-card:hover .work-card__frame img, .work-card:focus-visible .work-card__frame img { filter: brightness(1); transform: scale(1.02); }
.work-card__title { margin: 20px 0 0; font-size: clamp(2rem, 3.5vw, 2.75rem); }
.work-card__meta { margin: 6px 0 0; font-size: 14px; }

/* ---- Project page ---- */

.project { padding: calc(var(--nav-h) + clamp(32px, 6vh, 72px)) var(--gutter) clamp(64px, 12vh, 140px); }
.project__back { font-size: 13px; transition: color 200ms var(--ease); }
.project__back:hover { color: var(--fg); }

.project__head {
  display: grid; grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr); gap: 16px clamp(32px, 6vw, 96px);
  margin: clamp(32px, 6vh, 64px) 0 clamp(40px, 8vh, 80px);
}
.project__type { grid-column: 1 / -1; margin: 0; font-size: 13px; letter-spacing: 0.06em; text-transform: uppercase; }
.project__title { grid-column: 1 / -1; margin: 0; font-size: clamp(3.5rem, 10vw, 8.5rem); }
.project__summary { margin: 16px 0 0; max-width: 58ch; font-size: clamp(1.05rem, 1.5vw, 1.25rem); line-height: 1.55; }
.project__facts { margin: 16px 0 0; display: grid; grid-template-columns: max-content 1fr; gap: 12px 24px; align-content: start; font-size: 14px; }
.project__facts dt { color: var(--dim); }
.project__facts dd { margin: 0; }
@media (max-width: 800px) { .project__head { grid-template-columns: 1fr; } }

.project__pages { display: flex; flex-direction: column; gap: clamp(8px, 1.2vw, 16px); max-width: 1600px; margin: 0 auto; }
.project__pages img { width: 100%; height: auto; background: #141414; }

.project__nav {
  display: flex; justify-content: space-between; gap: 24px;
  max-width: 1600px; margin: clamp(56px, 10vh, 120px) auto 0;
  padding-top: 24px; border-top: 1px solid var(--faint);
}
.project__next { display: flex; flex-direction: column; gap: 6px; }
.project__next .dim { font-size: 13px; }
.project__next .display { font-size: clamp(1.75rem, 3.5vw, 2.75rem); transition: transform 400ms var(--ease); }
.project__next.is-next { text-align: right; }
.project__next.is-prev:hover .display { transform: translateX(-8px); }
.project__next.is-next:hover .display { transform: translateX(8px); }

/* ---- About page ---- */

.about-page__intro { max-width: 60ch; }
.about-page__lead { margin: 0 0 24px; font: 400 clamp(1.75rem, 3.6vw, 3rem)/1.15 var(--serif); }
.about-page__intro p:not(.about-page__lead) { margin: 0 0 16px; font-size: clamp(1.05rem, 1.5vw, 1.2rem); line-height: 1.6; color: rgba(242, 242, 242, 0.82); }

.about-page__section { margin-top: clamp(56px, 10vh, 104px); }

.about-page__rows { list-style: none; margin: 0; padding: 0; }
.about-page__rows a {
  display: grid; grid-template-columns: minmax(0, 1fr) auto 2ch; align-items: baseline; gap: 24px;
  padding: 18px 0; border-top: 1px solid var(--faint);
}
.about-page__rows li:last-child a { border-bottom: 1px solid var(--faint); }
.about-page__rows .display { font-size: clamp(1.75rem, 3.5vw, 2.75rem); transition: transform 400ms var(--ease); }
.about-page__rows .dim { font-size: 14px; text-align: right; }
.about-page__rows a:hover .display { transform: translateX(10px); }
@media (max-width: 640px) {
  .about-page__rows a { grid-template-columns: minmax(0, 1fr) 2ch; }
  .about-page__rows .dim { grid-column: 1; grid-row: 2; text-align: left; }
}

.about-page__tools { margin: 0; font-size: clamp(1.05rem, 1.6vw, 1.3rem); }

.about-page__contact { list-style: none; margin: 0; padding: 0; max-width: 640px; }
.about-page__contact li { display: grid; grid-template-columns: 12ch 1fr; padding: 14px 0; border-top: 1px solid var(--faint); font-size: 15px; }
.about-page__contact li:last-child { border-bottom: 1px solid var(--faint); }
.about-page__contact a { justify-self: start; border-bottom: 1px solid transparent; transition: border-color 200ms var(--ease); }
.about-page__contact a:hover { border-bottom-color: var(--fg); }

/* ---- Experience: one vertical timeline with type filters ---- */

.experience .page-head__lead { max-width: 46ch; }

/* ---- Experience hero: water filling the bottom, the title sliced below its line (js/water.js) ---- */
.exp-hero {
  position: relative;
  /* the full width, from the very top of the page (under the nav) */
  margin: calc(-1 * (var(--nav-h) + clamp(48px, 10vh, 120px))) calc(-1 * var(--gutter)) 0;
  padding: calc(var(--nav-h) + 48px) var(--gutter) clamp(56px, 10vh, 110px);   /* water below the title */
  min-height: clamp(380px, 64vh, 660px);
  display: flex; flex-direction: column; justify-content: flex-end;
  overflow: hidden;
}
.exp-hero__water { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.exp-hero .page-head__title { position: relative; z-index: 1; }
.exp-lead { margin: clamp(24px, 4vh, 40px) 0 clamp(40px, 8vh, 88px); }


.timeline {
  --pop: clamp(28px, 4vw, 56px);        /* how far a knocked-out entry (and its toggle) steps */
  --when: 10rem;                         /* the date column (rem, so it is the same in every font size) */
  --shift: 560ms cubic-bezier(0.3, 0.7, 0.2, 1);
  display: grid; grid-template-columns: 11rem minmax(0, 1fr); gap: clamp(24px, 4vw, 64px);
  align-items: start;
}

/* the toggles, stacked; each steps sideways exactly as its own entries do */
.filters {
  position: sticky; top: calc(var(--nav-h) + 32px);
  transition: transform 900ms cubic-bezier(0.6, 0, 0.3, 1), opacity 700ms var(--ease);
  display: flex; flex-direction: column; align-items: flex-start; gap: 8px;
}
.filters .section-label { margin: 0 0 8px; }
.chip {
  display: inline-flex; align-items: baseline; gap: 8px;
  padding: 8px 14px; border: 1px solid var(--faint); border-radius: 999px;
  font-size: 14px; color: var(--dim);
  transition: transform var(--shift), color 200ms var(--ease), background-color 200ms var(--ease), border-color 200ms var(--ease);
}
.chip:hover { color: var(--fg); border-color: var(--dim); }
.chip.is-on { color: var(--bg); background: var(--fg); border-color: var(--fg); }
.chip__count { font-size: 12px; opacity: 0.6; font-variant-numeric: tabular-nums; }

.tl { position: relative; list-style: none; margin: 0; padding: 0; transition: height 1400ms cubic-bezier(0.45, 0, 0.2, 1); }
/* the line itself never moves */
.tl::before {
  content: ''; position: absolute; top: 12px; bottom: 0;
  transform-origin: top; transition: transform 800ms cubic-bezier(0.6, 0, 0.3, 1);
  left: calc(var(--when) + 20px); width: 1px; background: var(--faint);
}

.tl__year {
  position: relative;
  padding: 44px 0 10px; font-size: clamp(2rem, 4vw, 3rem); line-height: 1;
  transition: opacity 300ms var(--ease);
}
.tl__year:first-child { padding-top: 0; }
.tl__year::after {
  content: ''; position: absolute; bottom: 20px; left: calc(var(--when) + 15px);
  width: 9px; height: 9px; border-radius: 50%; border: 1px solid var(--dim); background: var(--bg);
}

.tl__item {
  position: relative;
  /* the same two tracks in both layouts, so the date column can shrink smoothly when it scatters */
  display: grid; grid-template-columns: var(--when) minmax(0, 1fr); gap: 4px 40px;
  padding: 22px 0 26px;
  transition: transform var(--shift), opacity 300ms var(--ease);
}
/* its dot sits on the line, and goes with the entry when it steps aside or scatters */
.tl__dot {
  position: absolute; top: 31px; left: calc(var(--when) + 17px);
  width: 7px; height: 7px; border-radius: 50%; background: var(--fg);
  transition: left 1400ms cubic-bezier(0.45, 0, 0.2, 1), top 1400ms cubic-bezier(0.45, 0, 0.2, 1);
}
.tl__when { grid-column: 1; grid-row: 1; white-space: nowrap; }   /* never taller when its column is squeezed */
.tl__body { grid-column: 2; grid-row: 1; min-width: 0; max-width: 60ch; }
.tl__when { transition: opacity 300ms var(--ease); margin: 0; padding-top: 0.2em; font-size: 14px; font-variant-numeric: tabular-nums; }
.tl__type { margin: 0 0 6px; font: 500 11px/1.4 var(--sans); letter-spacing: 0.1em; text-transform: uppercase; color: var(--dim); }
.tl__title { margin: 0; font-size: clamp(1.6rem, 3vw, 2.4rem); line-height: 1.1; }
.tl__title a { transition: opacity 200ms var(--ease); }
.tl__title a:hover { opacity: 0.7; }
.tl__role { margin: 8px 0 0; font-size: 15px; }
.tl__note { margin: 12px 0 0; font-size: 14px; line-height: 1.6; }
.tl__points { margin: 12px 0 0; padding: 0 0 0 1.1em; font-size: 15px; line-height: 1.6; color: rgba(242, 242, 242, 0.82); }
.tl__points li + li { margin-top: 6px; }
.tl__points li::marker { color: var(--dim); }

/* choosing types: they stay on the line; everything else (and its toggle) steps aside */
.timeline.has-pick .tl__item:not(.is-picked),
.timeline.has-pick .chip:not(.is-on) { transform: translateX(var(--pop)); }
.timeline.has-pick .tl__item:not(.is-picked) { opacity: 0.35; }

@media (max-width: 800px) {
  .timeline { --pop: 24px; --when: 0px; grid-template-columns: minmax(0, 1fr); gap: 32px; }
  /* the toggles wrap along a row instead of a tall column; in a row they have no room to step
     aside, so only the entries do */
  .filters { position: static; flex-direction: row; flex-wrap: wrap; gap: 8px; }
  .filters .section-label { flex-basis: 100%; margin-bottom: 0; }
  .experience .timeline.has-pick .chip:not(.is-on) { transform: none; }
  .chip { padding: 10px 14px; }   /* a finger-sized toggle */
  .tl { padding-left: 28px; }
  .tl::before { left: 4px; }
  .tl__year::after { left: -28.5px; }
  .tl__item { grid-template-columns: minmax(0, 1fr); padding: 18px 0 22px; }
  .tl__when, .tl__body { grid-column: 1; grid-row: auto; }
  .tl__dot { left: -27.5px; top: 26px; }
}

@media (prefers-reduced-motion: reduce) {
  .tl__item, .chip { transition: opacity 200ms, color 200ms, background-color 200ms; }
}

/* ---- Scatter: a column per type, entries tilted, joined by snaking lines ---- */

.tl-controls { display: flex; justify-content: flex-end; margin: 0 0 24px; }
.scatter {
  padding: 9px 16px; border: 1px solid var(--faint); border-radius: 999px; font-size: 14px;
  transition: border-color 200ms var(--ease), background-color 200ms var(--ease), color 200ms var(--ease);
}
.scatter:hover { border-color: var(--dim); }
.scatter[aria-pressed='true'] { background: var(--fg); color: var(--bg); border-color: var(--fg); }

/* No scroll anchoring on this page: when the entries are rearranged, the browser would otherwise scroll the
   page to keep one of them in place, which looks like everything jumping. */
.experience { overflow-anchor: none; }   /* (and on the page itself, set in experience.js) */
/* entries stepping aside (or tilting) may reach past the window edge: clip rather than scroll
   sideways. clip, unlike hidden, keeps the toggles sticky. */
.experience { overflow-x: clip; }
.timeline { position: relative; }
.burst[hidden] { display: none; }

/* scattered: the toggles, years and line fade out; entries sit in columns at about their height */
/* beat 1: the toggles slide off the left edge, the line draws back up, the years fade */
.timeline.is-leaving .filters { transform: translateX(calc(-100% - var(--gutter) - 48px)); opacity: 0; }
.timeline.is-leaving .tl::before { transform: scaleY(0); }
.timeline.is-leaving .tl__year { opacity: 0; }
/* the dates move from beside each entry to above it while it changes shape, so they fade out and back */
.timeline.is-leaving:not(.is-settled) .tl__when { opacity: 0; }
/* everything placed explicitly, so the scatter layer and the toggles (still sliding away) can share
   the first row with the list without pushing anything down */
.filters { grid-column: 1; grid-row: 1; }
.tl { grid-column: 2; grid-row: 1; }
.timeline.is-burst .filters { pointer-events: none; }
.timeline.is-burst .tl, .burst { grid-column: 1 / -1; grid-row: 1; }
@media (max-width: 800px) { .filters, .tl { grid-column: 1; grid-row: auto; } }

/* Scattered, the date column has shrunk to nothing (animated in js/experience.js) and the date sits
   above the entry, in its top padding. The padding stays, so the text does not jump. */
.timeline.is-burst .tl__item {
  position: absolute; margin: 0;
  grid-template-columns: 0px minmax(0, 1fr); column-gap: 0;
  transition: none;
  z-index: 1;
}
.timeline.is-burst .tl__dot { top: 0.35em; left: -14px; }
.timeline.is-burst .tl__when { position: absolute; top: 0; left: 0; padding: 0; white-space: nowrap; }

.burst { position: relative; pointer-events: none; align-self: stretch; }
.burst__lines { position: absolute; inset: 0; overflow: visible; z-index: 0; }
.burst__lines path { fill: none; stroke: rgba(242, 242, 242, 0.55); stroke-width: 2.25; stroke-linecap: round; }
.burst__head {
  position: absolute; top: 0; margin: 0;
  font-size: clamp(1.6rem, 2.4vw, 2.2rem); line-height: 1;
  animation: burst-head 1400ms cubic-bezier(0.3, 0, 0.2, 1) backwards;
  transition: opacity 600ms var(--ease), transform 600ms var(--ease);
}
.burst.is-closing .burst__head { opacity: 0; transform: translateY(8px); }
@keyframes burst-head { from { opacity: 0; transform: translateY(14px); } }
.burst__lines { transition: opacity 450ms var(--ease); }
.burst__lines.is-fading { opacity: 0; }

/* beat 3: a rule grows across the page at the start of each year */
.burst__rule {
  position: absolute; left: 0; right: 0; height: 0;
  border-top: 1px solid var(--faint);
  transform: scaleX(0); transform-origin: left;
  transition: transform 1100ms cubic-bezier(0.5, 0, 0.2, 1);
}
.burst.is-ruled .burst__rule { transform: scaleX(1); }
.burst__rule:nth-of-type(2) { transition-delay: 120ms; }
.burst__rule:nth-of-type(3) { transition-delay: 240ms; }
.burst__rule:nth-of-type(4) { transition-delay: 360ms; }
.burst__rule-label {
  position: absolute; right: 0; bottom: 6px;
  font-size: 1.1rem; color: var(--dim); line-height: 1;
  opacity: 0; transition: opacity 500ms var(--ease);
}
.burst.is-ruled .burst__rule-label { opacity: 1; transition-delay: 600ms; }

@media (max-width: 800px) { .tl-controls { display: none; } }

.experience > .about-page__section:first-of-type { margin-top: clamp(64px, 12vh, 120px); }
.skills { margin: 0; max-width: calc(76ch + 64px); }
.skills div { display: grid; grid-template-columns: minmax(10ch, 16ch) minmax(0, 60ch); gap: 4px clamp(24px, 4vw, 64px); padding: 16px 0; border-top: 1px solid var(--faint); font-size: 15px; }
.skills div:last-child { border-bottom: 1px solid var(--faint); }
.skills dt { color: var(--dim); font-size: 14px; }
.skills dd { margin: 0; line-height: 1.6; }
@media (max-width: 700px) { .skills div { grid-template-columns: 1fr; } }

.experience__contact { margin: 0; font-size: clamp(1.05rem, 1.6vw, 1.3rem); }
.experience__contact a { border-bottom: 1px solid var(--faint); transition: border-color 200ms var(--ease); }
.experience__contact a:hover { border-bottom-color: var(--fg); }
