:root {
  --font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial,
    sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
  --font-size: 18px;
  --font-weight: 400;
  --font-weight-bold: 700;
  --header-line-height: 1.4em;

  --text-color: rgb(63, 63, 63);
  --text-color-light: rgb(110, 110, 110);
  --link-color: rgb(1, 87, 155);
  --background-color: #fff;
  --pre-background: #f0f5f9;
  --border-color: rgb(224, 224, 224);

  --vertical-margin: 1em;
  --side-margin: 2em;
  --max-width: 40em;

  --fade-duration: 300ms;
  --fade-easing: cubic-bezier(0.16, 1, 0.3, 1);
  --fade-offset: 6px;

  /* The nav stagger must finish inside --fade-duration. On a cross-document
     navigation these animations are created fresh as the transition starts,
     and the view transition restores their real timing when it ends -- so
     anything still mid-flight at that point visibly snaps backwards.
     Budget: (5 * delta) + nav-fade-duration = 290ms < 300ms. */
  --nav-fade-duration: 180ms;
  --nav-animation-delta: 22ms;
}

/* Base */

html,
body {
  width: 100%;
  height: 100%;
}

body {
  margin: 0;
  background: var(--background-color);

  font-family: var(--font-family);
  font-size: var(--font-size);
  font-weight: var(--font-weight);
  color: var(--text-color);
  -webkit-font-smoothing: antialiased;
}

h1,
h2,
h3 {
  font-weight: var(--font-weight);
}

a {
  position: relative;
  text-decoration: none;
  transition: all 250ms ease;
}

a,
a:visited,
a:hover,
a:active {
  color: var(--link-color);
}

a:hover,
a:active {
  text-decoration: underline;
}

p,
small {
  max-width: var(--max-width);
}

p,
li {
  line-height: 1.6em;
}

small {
  font-size: 0.7em;
}

pre {
  padding: 0.5em 1em;
  background: var(--pre-background);
  font-size: 16px;
}

blockquote {
  margin: 0;
  padding: calc(var(--vertical-margin)/4) var(--side-margin);
  border-left: calc(var(--side-margin)/4) solid var(--pre-background);
}

table {
  width: 100%;
  max-width: var(--max-width);
  margin: var(--vertical-margin) 0;
  border-collapse: collapse;
  font-size: 0.9em;
}

th,
td {
  padding: 0.4em 0.8em;
  border-bottom: 1px solid var(--border-color);
  line-height: 1.6em;
  text-align: left;
  vertical-align: top;
}

th {
  font-weight: var(--font-weight-bold);
}

thead th {
  border-bottom: 2px solid var(--border-color);
}

.hidden {
  display: none !important;
  visibility: hidden;
}

/* Animation */

@keyframes fadeIn {
  from {
    opacity: 0;
    transform: translate3d(0, var(--fade-offset), 0);
  }
  to {
    opacity: 1;
    transform: translate3d(0, 0, 0);
  }
}

@keyframes fadeOut {
  to {
    opacity: 0;
  }
}

/* Page transitions

   Cross-document view transitions, so navigating between pages crossfades
   instead of hard-cutting. Progressive enhancement: unsupported browsers
   just navigate normally and fall back to the entry animations below.

   The header and footer are identical on every page, so they stay in the
   root snapshot where the crossfade between two near-identical images is
   imperceptible. Only .site-content gets its own group, so the part that
   actually changes is the part that visibly animates. */

@view-transition {
  navigation: auto;
}

.site-content {
  view-transition-name: site-content;
}

::view-transition-group(root),
::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: var(--fade-duration);
  animation-timing-function: var(--fade-easing);
}

/* Pages have different content heights, so the group morphs its size.
   Keep that on the same clock as the fades or it drifts out of sync. */
::view-transition-group(site-content) {
  animation-duration: var(--fade-duration);
  animation-timing-function: var(--fade-easing);
}

/* Sequential, not overlapping. Overriding `animation` here drops the UA's
   mix-blend-mode: plus-lighter, so any overlap composites two different
   blocks of text source-over and the old text ghosts through the new.
   Out then in, splitting --fade-duration between them. */
::view-transition-old(site-content) {
  animation: fadeOut calc(var(--fade-duration) * 0.35) ease-out both;
}

::view-transition-new(site-content) {
  animation: fadeIn calc(var(--fade-duration) * 0.65) var(--fade-easing) both;
  animation-delay: calc(var(--fade-duration) * 0.35);
}

/* The entry animations exist for cold loads. During a view transition the
   transition itself does the fading, so neutralize them.

   Zero the timing rather than setting `animation: none`. Removing the name
   destroys the animation, and when this rule stops matching at the end of
   the transition the browser creates a fresh one that replays from opacity
   0 -- the whole page visibly re-fades. Keeping the name alive means the
   same animation object persists in its finished state, so restoring the
   duration afterwards is a no-op. The delay has to go too: with
   `fill-mode: both` a still-delayed animation pins the element at opacity
   0 for up to 180ms. */
html:active-view-transition .site-content,
html:active-view-transition .site-nav li {
  animation-duration: 0s;
  animation-delay: 0s;
}

@media (prefers-reduced-motion: reduce) {
  @view-transition {
    navigation: none;
  }

  *,
  *::before,
  *::after,
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*) {
    animation-duration: 1ms !important;
    animation-delay: 0ms !important;
    transition-duration: 1ms !important;
  }
}

/* Main site elements */

.site-header {
  width: 100%;
  margin: 1em auto;
  overflow: hidden;

  line-height: var(--header-line-height);
}

.site-home-link:hover {
  text-decoration: none;
}

.site-title {
  max-width: 110px;
  padding: 0.4em 0.7em;
  margin: 1em auto;
  border: 3px solid var(--text-color);
  color: var(--text-color);
  font-size: 1.1em;
  font-weight: var(--font-weight-bold);
  text-align: center;
  white-space: nowrap;
}

.site-nav {
  display: flex;
  justify-content: center;
  align-items: center;
  flex-wrap: wrap;
  gap: 1rem;
  margin: 0 auto 0.5rem;
  padding: 0;

  font-size: calc(var(--font-size) * 0.9);
  font-weight: var(--font-weight-bold);
  list-style: none;
  text-align: center;
}

.site-nav li {
  padding: 0;
  transition: all 200ms ease-in-out;

  /* Staggered fade in, cycling every 6 items */
  animation: fadeIn var(--nav-fade-duration) var(--fade-easing) both;
  animation-delay: calc(var(--nav-item) * var(--nav-animation-delta));
}

.site-nav li:nth-of-type(6n + 1) { --nav-item: 1; }
.site-nav li:nth-of-type(6n + 2) { --nav-item: 2; }
.site-nav li:nth-of-type(6n + 3) { --nav-item: 3; }
.site-nav li:nth-of-type(6n + 4) { --nav-item: 4; }
.site-nav li:nth-of-type(6n + 5) { --nav-item: 5; }
.site-nav li:nth-of-type(6n + 6) { --nav-item: 6; }

.site-nav .stars {
  margin-left: 0.5rem;
}

.site-nav-container {
  margin: 2rem var(--side-margin);
}

.site-content {
  width: 90%;
  max-width: var(--max-width);
  margin: 0 auto;
  font-size: 18px;
  animation: fadeIn var(--fade-duration) var(--fade-easing) both;
}

.site-content img {
  max-width: 100%;
}

.post {
  margin: 3rem 0;
}

.post-header {
  margin: 1rem 0;
}

.post-title {
  margin: 0;
  line-height: 150%;
}

.post-date,
.post-canonical {
  margin: 0.5rem 0;
  font-size: 0.9rem;
  color: var(--text-color-light);
}

.post-body img,
.post-body video {
  display: block;
  max-width: 100%;
  margin: 1em auto;
}

.img-med {
  width: 440px;
}

.video,
.slides {
  position: relative;
  height: 0;
}

.video {
  padding-bottom: 56.25%; /* 16:9 */
}

.slides {
  padding-bottom: 62.5%;
}

.video iframe,
.slides iframe {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

@media (max-width: 440px) {
  .site-content {
    font-size: 16px;
  }

  .post-title {
    font-size: 1.8em;
  }
}
