@property --mrr {
  syntax: "<integer>";
  initial-value: 50;
  inherits: false;
}

@view-transition {
  navigation: auto;
}

:root {
  color-scheme: light dark;
  --bg: #ffffff;
  --fg: #000000;
  --dim-alpha: 0.29;
  --dim: rgba(0, 0, 0, var(--dim-alpha));
  --font: "Inter Tight", -apple-system, BlinkMacSystemFont, "Helvetica Neue", Arial, sans-serif;
  --gutter: 25px;
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);
  --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #000000;
    --fg: #ffffff;
    --dim-alpha: 0.38;
    --dim: rgba(255, 255, 255, var(--dim-alpha));
  }
}

/* Page changes crossfade; the header holds still while the content swaps. */
::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: 200ms;
  animation-timing-function: ease;
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font);
  /* 24px on tall screens, easing down on shorter ones so the homepage fits a
     laptop window without scrolling. */
  font-size: clamp(19px, 2.65vh, 24px);
  line-height: 1.2;
  -webkit-font-smoothing: antialiased;
}

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

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

.dim {
  color: var(--dim);
}

.site-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 24px;
  padding: 21px var(--gutter) 0;
  view-transition-name: site-header;
}

.nav {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  column-gap: 23px;
}

.brand {
  margin: 0;
  font: inherit;
}

.nav a {
  color: var(--dim);
  transition: color 120ms ease;
}

.nav a:hover,
.nav a[aria-current="page"] {
  color: var(--fg);
}

.clock-time {
  font-variant-numeric: tabular-nums;
}

/* Footer mode picker: same grey-and-black language as the nav. */
.mode-picker {
  display: flex;
  align-items: baseline;
  gap: 0.7em;
}

.mode-picker a {
  color: var(--dim);
  transition: color 120ms ease;
}

.mode-picker a:hover,
.mode-picker a[aria-current] {
  color: var(--fg);
}

.visitor-count {
  font-variant-numeric: tabular-nums;
}

main {
  max-width: calc(840px + var(--gutter) * 2);
  margin-top: 74px;
  padding: 0 var(--gutter);
}

p,
.block {
  margin: 0 0 1.2em;
}

.block p,
.block ul {
  margin: 0;
}

.label {
  display: block;
  margin: 0;
  color: var(--dim);
  font: inherit;
}

.block ul {
  padding: 0;
  list-style: none;
}

.experience s {
  text-decoration-thickness: 1.5px;
}

.annotated .note {
  display: block;
  color: var(--dim);
}

.annotated li + li {
  margin-top: 0.45em;
}

@media (hover: hover) and (pointer: fine) and (min-width: 1100px) {
  .annotated li {
    display: grid;
    grid-template-columns: 18.5em max-content;
    column-gap: 1em;
  }

  .annotated li > :first-child {
    justify-self: start;
  }

  .annotated li + li {
    margin-top: 0;
  }

  /* Notes arrive top to bottom and leave together. */
  .annotated .note {
    white-space: nowrap;
    opacity: 0;
    transform: translateX(-0.4em);
    transition: opacity 200ms var(--ease-out), transform 200ms var(--ease-out), color 150ms ease;
  }

  .annotated:hover .note {
    opacity: 1;
    transform: none;
  }

  .annotated:hover li:nth-child(2) .note { transition-delay: 30ms; }
  .annotated:hover li:nth-child(3) .note { transition-delay: 60ms; }
  .annotated:hover li:nth-child(4) .note { transition-delay: 90ms; }
  .annotated:hover li:nth-child(5) .note { transition-delay: 120ms; }

  .annotated li:hover .note {
    color: var(--fg);
  }
}

/* Investments stay one sentence. Hovering a company swaps the "Invested in"
   label for that company's description. Captions come in over 125ms and leave
   instantly, so moving between names swaps them without lag. The label steps
   aside instantly (no overlapping crossfade) and waits 120ms before fading back,
   so crossing the commas between names doesn't flicker. */
.investments {
  position: relative;
}

.investments .note {
  display: none;
}

@media (hover: hover) and (pointer: fine) and (min-width: 720px) {
  .investments .note {
    display: block;
    position: absolute;
    top: 0;
    left: 0;
    color: var(--dim);
    white-space: nowrap;
    pointer-events: none;
    opacity: 0;
    transform: translateY(0.2em);
  }

  .investment:hover .note,
  .investment:focus-within .note {
    opacity: 1;
    transform: none;
    transition: opacity 125ms var(--ease-out), transform 125ms var(--ease-out);
  }

  .investments .label {
    transition: opacity 125ms var(--ease-out) 120ms;
  }

  .investments:has(.investment:hover, .investment:focus-within) .label {
    opacity: 0;
    transition: none;
  }
}

.inline-link,
.link-row a {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.16em;
  text-decoration-color: var(--dim);
  transition: text-decoration-color 150ms ease;
}

.inline-link:hover,
.link-row a:hover {
  text-decoration-color: currentColor;
}

.link-row {
  display: flex;
  flex-wrap: wrap;
  column-gap: 0.7em;
}

.site-footer {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: 12px 24px;
  margin-top: 2.4em;
  padding: 0 var(--gutter) var(--gutter);
}

.site-footer p {
  margin: 0;
}

/* Desktop: one screen, no scrolling. Header at the top; contact, AI and
   visitor details in a three-column band above the footer at the bottom. */
@media (min-width: 1100px) {
  body {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
  }

  main {
    display: flex;
    flex: 1 0 auto;
    flex-direction: column;
    max-width: none;
    margin-top: 2em;
  }

  main > p {
    max-width: 840px;
  }

  .info-band {
    display: grid;
    grid-template-columns: max-content max-content minmax(0, 32em);
    column-gap: 3em;
    margin-top: auto;
    padding-top: 1.2em;
  }

  .info-band .block {
    margin: 0;
  }

  .site-footer {
    margin-top: 1.2em;
  }
}

@media (max-width: 720px) {
  :root {
    --gutter: 14px;
  }

  body {
    font-size: 19px;
    line-height: 1.25;
  }

  .site-header {
    padding-top: 14px;
  }

  .nav .page-link,
  .clock-date {
    display: none;
  }

  main {
    margin-top: 48px;
  }
}

.mrr {
  font-variant-numeric: tabular-nums;
}

/* The number is drawn by CSS so the count-up can run as a CSS animation on the
   shared curve. Screen readers get the visually hidden "$50k" beside it. */
.mrr-count {
  counter-reset: mrr var(--mrr, 50);
}

.mrr-count::after {
  content: "$" counter(mrr) "k";
}

@keyframes count-up {
  from {
    --mrr: 0;
  }
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* First page of a visit only: the content starts in the inactive grey and inks
   to black in a sweep, left to right along each line, each line a beat after
   the one above. Black at the dim alpha is exactly the dim grey, so this runs
   on opacity. site.js wraps the words and sets each word's --ink-delay. */
@keyframes ink {
  from {
    opacity: var(--dim-alpha);
  }
}

@keyframes ink-fallback {
  to {
    color: var(--fg);
  }
}

@media (prefers-reduced-motion: no-preference) {
  .first-view:not(.is-inked) main {
    color: var(--dim);
    animation: ink-fallback 0s 2.5s forwards;
  }

  .is-inked .ink-word {
    animation: ink 500ms var(--ease-out) var(--ink-delay, 0ms) backwards;
  }

  .is-inked .mrr-count.ink-word {
    animation:
      ink 500ms var(--ease-out) var(--ink-delay, 0ms) backwards,
      count-up 1100ms var(--ease-out) calc(var(--ink-delay, 0ms) + 150ms) backwards;
  }
}

@media (prefers-reduced-motion: reduce) {
  .first-view main {
    animation: ink 200ms ease backwards;
  }

  .annotated .note,
  .investments .note {
    transform: none;
  }

  .annotated .note {
    transition: opacity 200ms ease, color 150ms ease;
  }
}
