/*
  Spencer Riley: styles shared by all four languages.

  A condensed, CV-style page. The profile and summary come first (and stay beside the
  content on a computer); everything else sits in one column on the right.

  Proportions follow the golden ratio (φ ≈ 1.618):
  - type sizes grow in steps of √φ, so every second step is φ times larger
  - every space is a Fibonacci number of pixels: 8, 13, 21, 34, 55, 89
  - two-column layouts split 38.2% / 61.8%
*/

:root {
  /* Always the light look, even when a visitor's browser is in dark mode */
  color-scheme: light;

  /* Colours */
  --bg: #f8f6f1;
  --card: #ffffff;
  --ink: #18202e;
  --muted: #5b6577;
  --accent: #1e4fa3;
  --navy: #1e4fa3;
  --navy-deep: #0f2a5c;
  --navy-night: #0b1f45;
  --navy-soft: #dde8fb;
  --tint: #edf3fd;
  --gold: #eaa72f;
  --gold-deep: #a8741a;   /* gold that is dark enough for small text on light backgrounds */
  --gold-pale: #ffd98a;
  --line: #e4ded1;

  /* Fonts already on every device: a clean sans for reading, a classic serif for titles */
  --sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --serif: "Iowan Old Style", "Palatino Linotype", Palatino, "Book Antiqua", Georgia, serif;

  /* Type: 16px × √φ for each step */
  --step--2: 0.75rem;    /* 12px, the smallest labels */
  --step--1: 0.8125rem;  /* 13px */
  --step-0: 1rem;        /* 16px, body text */
  --step-1: 1.272rem;    /* 20px */
  --step-2: 1.618rem;    /* 26px */
  --step-3: 2.058rem;    /* 33px */
  --step-4: 2.618rem;    /* 42px */

  /* Spacing: Fibonacci */
  --s-1: 0.5rem;         /* 8px */
  --s-2: 0.8125rem;      /* 13px */
  --s-3: 1.3125rem;      /* 21px */
  --s-4: 2.125rem;       /* 34px */
  --s-5: 3.4375rem;      /* 55px */
  --s-6: 5.5625rem;      /* 89px */

  --wrap: 73.75rem;      /* 1180px */
  --gutter: clamp(var(--s-2), 4vw, var(--s-4));
  --nav-height: var(--s-5);
  --radius: 13px;
  --radius-small: 8px;
  --shadow: 0 1px 2px rgba(24, 32, 46, 0.05), 0 5px 13px rgba(24, 32, 46, 0.05);
  --shadow-lift: 0 2px 5px rgba(11, 31, 69, 0.06), 0 13px 34px rgba(11, 31, 69, 0.14);
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
}

/* The strength of the gold light on cards, animated smoothly where browsers allow */
@property --glow {
  syntax: "<number>";
  inherits: false;
  initial-value: 0;
}


/* ===== Base ============================================================== */

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

/* Everything is sized in rem, so this one value scales the whole page. It is 16px up to
   laptop size, then grows with wider screens (up to 21px), but never so far that the
   profile panel would stop fitting on the screen's height. */
html {
  -webkit-text-size-adjust: 100%;
  font-size: clamp(16px, min(calc(10px + 0.5vw), calc(100vh / 61)), 21px);
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--nav-height) + var(--s-3));
}

/* Large screens: a wider layout, so the profile has shorter lines and the text can grow further */
@media (min-width: 1100px) {
  html { scroll-padding-top: calc(var(--nav-height) + var(--masthead-h, 0px) + var(--s-3)); }
}

@media (min-width: 1600px) {
  :root { --wrap: 85rem; }
  html { font-size: clamp(16px, min(calc(10px + 0.5vw), calc(100vh / 54)), 22px); }
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  font-size: var(--step-0);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

h1,
h2 { font-family: var(--serif); }

::selection {
  background: var(--gold);
  color: var(--navy-night);
}

/* Photos can't be dragged off the page, highlighted by a text selection or saved with a long press */
img {
  display: block;
  max-width: 100%;
  -webkit-user-drag: none;
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}

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

p { margin: 0 0 var(--s-2); }

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

.wrap {
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--gutter);
}


/* ===== Navigation ======================================================== */

nav {
  position: sticky;
  top: 0;
  z-index: 10;
  background: rgba(11, 31, 69, 0.9);
  -webkit-backdrop-filter: saturate(160%) blur(13px);
  backdrop-filter: saturate(160%) blur(13px);
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}

/* How far down the page you are, as a thin gold line */
nav::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 2px;
  background: var(--gold);
  transform: scaleX(var(--scroll, 0));
  transform-origin: left;
}

nav .wrap {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  height: var(--nav-height);
  overflow-x: auto;
  white-space: nowrap;
  scrollbar-width: none;
}

nav .wrap::-webkit-scrollbar { display: none; }

nav .brand {
  margin-right: auto;
  color: #ffffff;
  font-family: var(--serif);
  font-size: 1.15rem;
  font-weight: 700;
  text-decoration: none;
}

nav a.link {
  position: relative;
  padding: var(--s-1) 0;
  color: rgba(255, 255, 255, 0.76);
  font-size: 0.9375rem;
  text-decoration: none;
  transition: color 0.3s ease;
}

/* A gold line slides in under the link you point at, and under the section you are reading */
nav a.link::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 2px;
  height: 2px;
  background: var(--gold);
  transform: scaleX(0);
  transform-origin: right;
  transition: transform 0.45s var(--ease-out);
}

nav a.link:hover,
nav a.link[aria-current="location"] { color: #ffffff; }

nav a.link:hover::after,
nav a.link[aria-current="location"]::after {
  transform: scaleX(1);
  transform-origin: left;
}

/* Contact is the one highlighted link in the menu */
nav a.cta {
  padding: 6px 15px;
  border-radius: 999px;
  background: var(--gold);
  color: #14233c;
  font-weight: 700;
  transition: background-color 0.3s ease, translate 0.45s var(--ease-out);
}

nav a.cta::after { display: none; }

nav a.cta:hover,
nav a.cta[aria-current="location"] {
  background: var(--gold-pale);
  color: #14233c;
}

/* Phones: the bar shows the name, Contact and a Menu button that lists every section */
.menu-toggle { display: none; }

.menu-icon {
  position: relative;
  width: 16px;
  height: 10px;
}

.menu-icon::before,
.menu-icon::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  height: 2px;
  border-radius: 2px;
  background: currentColor;
  transition: transform 0.3s var(--ease-out);
}

.menu-icon::before { top: 0; }
.menu-icon::after { bottom: 0; }

/* The two lines turn into a cross while the menu is open */
.menu-toggle[aria-expanded="true"] .menu-icon::before { transform: translateY(4px) rotate(45deg); }
.menu-toggle[aria-expanded="true"] .menu-icon::after { transform: translateY(-4px) rotate(-45deg); }

.menu {
  position: fixed;
  inset: var(--nav-height) 0 0 0;
  z-index: 9;
  overflow-y: auto;
  padding: var(--s-3) var(--gutter) var(--s-5);
  background: rgba(11, 31, 69, 0.97);
  -webkit-backdrop-filter: blur(13px);
  backdrop-filter: blur(13px);
  color: #ffffff;
}

.menu[hidden] { display: none; }

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

.menu-list a {
  display: flex;
  align-items: baseline;
  gap: var(--s-3);
  padding: var(--s-2) 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
  color: #ffffff;
  font-family: var(--serif);
  font-size: var(--step-2);
  font-weight: 700;
  line-height: 1.2;
  text-decoration: none;
}

.menu-list a:hover { color: var(--gold-pale); }

.menu-number {
  flex: none;
  width: 2em;
  color: var(--gold);
  font-family: var(--sans);
  font-size: var(--step--1);
  letter-spacing: 0.14em;
}

.menu .langs {
  justify-content: flex-start;
  margin: var(--s-4) 0 0;
}

html.menu-open { overflow: hidden; }

@media (max-width: 699px) {
  nav .brand { display: none; }

  nav .wrap {
    justify-content: space-between;
    gap: 6px;
    padding-inline: 10px;
  }

  nav a.link { font-size: 0.875rem; }

  .js nav a.link:not(.cta) { display: none; }

  .js nav .brand {
    display: block;
    font-size: 1rem;
  }

  .js .menu-toggle {
    display: inline-flex;
    align-items: center;
    gap: var(--s-1);
    padding: 5px 12px;
    border: 1px solid rgba(255, 255, 255, 0.35);
    border-radius: 999px;
    background: transparent;
    color: #ffffff;
    font: inherit;
    font-size: 0.875rem;
    font-weight: 700;
    cursor: pointer;
  }

  .js nav .wrap { gap: var(--s-1); }

  /* Phones: the language buttons are in the Menu instead */
  .js nav .langs { display: none; }
}

@media (max-width: 359px) {
  .js nav .brand { font-size: 0.9rem; }
  .js .menu-toggle { padding-inline: 10px; }
}

@media (min-width: 700px) and (max-width: 1099px) {
  nav .wrap { gap: var(--s-3); }
}

/* Small tablets: not enough room for the name as well, and the profile shows it just below */
@media (min-width: 700px) and (max-width: 819px) {
  nav .brand { display: none; }
  nav .wrap { justify-content: space-between; }
}

@media (min-width: 700px) {
  .menu { display: none; }
}


/* ===== Page layout ======================================================= */

/* One column on phones and tablets. On a computer the profile stays across the top of the
   screen while the content scrolls under it: What I Bring (38.2%) beside the timeline
   (61.8%), then Beyond across both */
.page {
  padding-top: var(--s-3);
}

@media (min-width: 1100px) {
  .page { padding-top: 0; }
  .masthead { padding: var(--s-2) 0; }

  /* What I Bring sticks only beside the timeline, so the two share their own grid */
  .columns {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.618fr);
    column-gap: var(--s-5);
    align-items: start;
  }

  #skills {
    grid-column: 1;
    grid-row: 1;
    /* site.js sets how far down it waits, from the height of the profile and its own */
    position: sticky;
  }

  #timeline {
    grid-column: 2;
    grid-row: 1;
  }
}

/* The profile stays pinned where the screen is tall enough to leave plenty of room under it */
@media (min-width: 1100px) and (min-height: 700px) {
  .masthead {
    position: sticky;
    top: var(--nav-height);
    z-index: 10;
    background: var(--bg);
    /* The page colour reaches both edges of the screen, so nothing shows beside the profile */
    box-shadow: 0 0 0 100vmax var(--bg);
    clip-path: inset(0 -100vmax);
  }
}


/* ===== Profile: who I am, in one screen ================================== */

.profile {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  padding: var(--s-3) var(--s-3) var(--s-5);
  border-radius: var(--radius);
  color: #ffffff;
  /* The first glow follows the pointer (see site.js) */
  background:
    radial-gradient(28rem circle at var(--spot-x, 85%) var(--spot-y, 0%), rgba(234, 167, 47, 0.2), transparent 62%),
    linear-gradient(160deg, #1d4c9e 0%, var(--navy-deep) 55%, var(--navy-night) 100%);
  box-shadow: var(--shadow-lift);
}

/* Language buttons sit in the menu bar (and in the phone menu) */
.langs {
  display: flex;
  gap: 4px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.langs a {
  display: block;
  padding: 3px 9px;
  border: 1px solid rgba(255, 255, 255, 0.32);
  border-radius: 999px;
  color: rgba(255, 255, 255, 0.85);
  font-size: var(--step--2);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-decoration: none;
  transition: border-color 0.3s ease, color 0.3s ease;
}

.langs a:hover {
  border-color: var(--gold);
  color: #ffffff;
}

.langs a[aria-current="page"] {
  border-color: var(--gold);
  background: var(--gold);
  color: #14233c;
}

.who {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: var(--s-3);
  margin-bottom: var(--s-3);
}

/* The photo takes about two fifths of the profile's width, within limits */
.profile { container-type: inline-size; }

.portrait {
  flex: none;
  width: 7rem;
  width: clamp(6rem, 40cqi, 9rem);
  height: auto;
  aspect-ratio: 1;
  border: 3px solid var(--gold);
  border-radius: 50%;
  object-fit: cover;
  object-position: 50% 30%;
  background: var(--navy-deep);
  box-shadow: 0 0 0 8px rgba(255, 255, 255, 0.06);
}

.eyebrow {
  margin: 0 0 6px;
  color: var(--gold);
  font-size: var(--step--2);
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

h1 {
  margin: 0;
  font-size: clamp(var(--step-3), 7vw, var(--step-4));
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.01em;
}

/* site.js wraps each letter so the name can rise in */
h1 .word {
  display: inline-block;
  overflow: hidden;
  padding-bottom: 0.06em;
  vertical-align: top;
}

h1 .char { display: inline-block; }

.title {
  position: relative;
  z-index: 1;
  margin: 0 0 var(--s-2);
  font-family: var(--serif);
  font-size: var(--step-1);
  font-weight: 700;
  line-height: 1.3;
}

.title em { color: var(--gold); }

.summary {
  position: relative;
  z-index: 1;
  margin: 0 0 var(--s-3);
  color: var(--navy-soft);
  font-size: 0.9375rem;
  line-height: 1.6;
}

.summary strong { color: #ffffff; }

/* Key facts in two columns, "Looking for" across the full width */
.facts {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--s-2) var(--s-3);
  margin: var(--s-3) 0 0;
  padding-top: var(--s-2);
  border-top: 1px solid rgba(255, 255, 255, 0.14);
}

.facts div:last-child { grid-column: 1 / -1; }

.facts dt {
  color: var(--gold);
  font-size: var(--step--2);
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  -webkit-hyphens: auto;
  hyphens: auto;
  overflow-wrap: break-word;
}

.facts dd {
  margin: 2px 0 0;
  font-size: 0.875rem;
  font-weight: 600;
  line-height: 1.35;
  -webkit-hyphens: auto;
  hyphens: auto;
  overflow-wrap: break-word;
}

.actions {
  position: relative;
  z-index: 1;
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-1);
}

.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-1);
  min-height: 2.75rem;
  padding: 0 var(--s-3);
  border: 1px solid rgba(255, 255, 255, 0.55);
  border-radius: 999px;
  background: transparent;
  color: #ffffff;
  font: inherit;
  font-size: 0.9375rem;
  font-weight: 700;
  line-height: 1.2;
  text-decoration: none;
  transition: background-color 0.3s ease, border-color 0.3s ease, color 0.3s ease, translate 0.45s var(--ease-out);
}

.button:hover {
  border-color: var(--gold);
  background: rgba(255, 255, 255, 0.08);
}

.button .icon {
  flex: none;
  width: 1.15em;
  height: 1.15em;
}

.button.solid {
  border-color: var(--navy);
  background: var(--navy);
}

.button.solid:hover {
  border-color: var(--navy-deep);
  background: var(--navy-deep);
}

/* Buttons that end with an arrow in a circle, which nudges forward on hover */
.button.go { padding-right: 6px; }

.button .arrow {
  display: inline-grid;
  place-items: center;
  width: 2rem;
  height: 2rem;
  border-radius: 50%;
  background: #ffffff;
  color: var(--navy);
  transition: transform 0.45s var(--ease-out);
}

.button.go:hover .arrow { transform: translateX(3px); }

.mountains {
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  z-index: 0;
  display: block;
  width: 100%;
  height: 34px;
  opacity: 0.6;
}

/* The front ridge matches the page, which would look odd inside the panel */
.mountains path:last-child { display: none; }

@media (min-width: 700px) and (max-width: 1099px) {
  /* Tablets: the facts sit beside the summary */
  .profile {
    display: grid;
    grid-template-columns: minmax(0, 1.618fr) minmax(0, 1fr);
    column-gap: var(--s-4);
    padding: var(--s-4) var(--s-4) var(--s-5);
  }

  .profile > .who,
  .profile > .title,
  .profile > .summary,
  .profile > .actions { grid-column: 1; }

  .profile > .facts {
    grid-column: 2;
    grid-row: 1 / span 4;
    grid-template-columns: 1fr;
    align-self: start;
  }
}

@media (min-width: 1100px) {
  /* Across the top: the photo, then who I am, then the key facts */
  .profile {
    display: grid;
    grid-template-columns: auto minmax(0, 1.618fr) minmax(0, 1fr);
    grid-template-rows: auto auto auto 1fr;
    grid-template-areas:
      "photo name    facts"
      "photo title   facts"
      "photo summary facts"
      "photo actions facts";
    column-gap: var(--s-4);
    padding: var(--s-3) var(--s-4);
  }

  .who { display: contents; }

  /* site.js sets --photo, growing the photo from --photo-min towards
     --photo-max for as long as the profile does not get taller */
  .portrait {
    --photo-min: 10rem;
    --photo-max: 14.5rem;
    grid-area: photo;
    align-self: center;
    position: relative;
    z-index: 1;
    width: clamp(var(--photo-min), var(--photo, 0px), var(--photo-max));
  }

  .who > div {
    grid-area: name;
    position: relative;
    z-index: 1;
    margin-bottom: 4px;
  }

  .profile .title {
    grid-area: title;
    margin-bottom: var(--s-1);
  }

  .profile .summary {
    grid-area: summary;
    margin-bottom: var(--s-2);
  }

  .profile .actions { grid-area: actions; }

  .profile .button {
    padding: 0 var(--s-2);
    font-size: 0.875rem;
  }

  .profile .facts {
    grid-area: facts;
    align-self: center;
    margin: 0;
    padding: 0 0 0 var(--s-4);
    border-top: 0;
    border-left: 1px solid rgba(255, 255, 255, 0.14);
  }

  .profile .facts dd {
    -webkit-hyphens: manual;
    hyphens: manual;
  }
}

/* Screens that are not very tall: a tighter profile, so more of the content shows under it */
@media (min-width: 1100px) and (max-height: 920px) {
  /* The key facts keep their width, so the photo takes its room from the text beside it */
  .profile { grid-template-columns: auto minmax(0, 1.618fr) minmax(min(20rem, 27vw), 1fr); }

  .portrait {
    --photo-min: 8.5rem;
    --photo-max: 12.5rem;
  }

  .eyebrow { display: none; }
  .title { font-size: 1.125rem; }

  .summary {
    font-size: 0.875rem;
    line-height: 1.55;
  }

  .facts { gap: var(--s-1) var(--s-3); }
}

@media (min-width: 1100px) and (max-height: 820px) {
  .masthead { padding-block: var(--s-1) var(--s-2); }
  .profile { padding-block: var(--s-2); }

  .portrait {
    --photo-min: 7rem;
    --photo-max: 12rem;
  }

  .facts dd { font-size: 0.8125rem; }
}

@media (min-width: 1100px) and (max-height: 740px) {
  .portrait {
    --photo-min: 6rem;
    --photo-max: 11rem;
  }

  .title { font-size: 1rem; }
  .summary { font-size: 0.8125rem; }
  .facts { gap: 6px var(--s-3); }
}


/* ===== Sections ========================================================== */

main { counter-reset: chapter; }

main section { padding-top: var(--s-5); }

@media (min-width: 1100px) {
  #skills,
  #timeline { padding-top: var(--s-1); }

  /* What I Bring is a narrow column here, so each label sits above its detail */
  #skills .cv-row { grid-template-columns: minmax(0, 1fr); }
  #skills .cv-row > :not(h3) { grid-column: 1; }
}

/* Section titles are numbered, with a hairline that draws itself */
main section > h2,
.contact h2 {
  display: flex;
  align-items: baseline;
  gap: var(--s-2);
  margin: 0 0 var(--s-1);
  font-size: clamp(var(--step-2), 3.6vw, var(--step-3));
  font-weight: 700;
  line-height: 1.15;
}

main section > h2::before {
  counter-increment: chapter;
  content: counter(chapter, decimal-leading-zero);
  flex: none;
  color: var(--gold-deep);
  font-family: var(--sans);
  font-size: var(--step--1);
  font-weight: 700;
  letter-spacing: 0.14em;
}

main section > h2::after,
.contact h2::after {
  content: "";
  flex: 1;
  align-self: center;
  height: 1px;
  background: var(--line);
  transform-origin: left;
}

.intro {
  margin: 0 0 var(--s-3);
  color: var(--muted);
  font-size: 0.9375rem;
}

.subhead {
  margin: var(--s-4) 0 var(--s-2);
  font-family: var(--serif);
  font-size: var(--step-1);
  line-height: 1.25;
}

.label { font-weight: 700; }

.tags {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.tags li {
  padding: 3px var(--s-2);
  border-radius: 999px;
  background: var(--tint);
  color: var(--ink);
  font-size: var(--step--1);
}

.tags.extra { margin-top: var(--s-2); }


/* ===== What I Bring: CV rows ============================================= */

/* A label on the 38.2% side, the detail on the 61.8% side, a hairline between rows */
.cv { border-top: 1px solid var(--line); }

.cv-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.618fr);
  gap: 4px var(--s-4);
  padding: var(--s-2) 0;
  border-bottom: 1px solid var(--line);
  transition: background-color 0.3s ease, box-shadow 0.3s ease;
}

.cv-row h3 {
  margin: 0;
  color: var(--accent);
  font-size: 0.9375rem;
  font-weight: 700;
  line-height: 1.5;
}

.cv-row p {
  margin: 0;
  font-size: 0.9375rem;
}

.cv-row > :not(h3) { grid-column: 2; }

/* Skill lens: "Show me" highlights where a skill was used */
.lens-pick { display: none; }

.js .lens-pick {
  display: inline-block;
  justify-self: start;
  margin-top: 6px;
  padding: 3px var(--s-2);
  border: 1px solid var(--navy);
  border-radius: 999px;
  background: transparent;
  color: var(--navy);
  font: inherit;
  font-size: var(--step--1);
  font-weight: 700;
  cursor: pointer;
  transition: background-color 0.3s ease, color 0.3s ease;
}

.js .lens-pick:hover { background: var(--tint); }

.js .lens-pick[aria-pressed="true"] {
  background: var(--navy);
  color: #ffffff;
}

.cv-row.chosen {
  background: linear-gradient(90deg, rgba(234, 167, 47, 0.12), transparent 61.8%);
  box-shadow: inset 3px 0 0 var(--gold);
}

@media (max-width: 599px) {
  .cv-row { grid-template-columns: 1fr; }
  .cv-row > :not(h3) { grid-column: 1; }
}

@media (min-width: 600px) {
  .cv-row.chosen { padding-left: var(--s-2); }
}


/* ===== Timeline: newest at the top, back in time as you scroll =========== */

.timeline {
  position: relative;
  z-index: 0;
  margin: 0;
  padding: 0 0 0 var(--s-4);
  list-style: none;
}

/* The grey track and the gold line that fills in as you read sit behind the entries */
.timeline::after,
.js .timeline::before {
  content: "";
  position: absolute;
  top: 0;
  left: 7px;
  width: 2px;
}

.timeline::after {
  z-index: -2;
  bottom: 0;
  background: var(--line);
}

.js .timeline::before {
  z-index: -1;
  height: calc(var(--progress, 1) * 100%);
  background: var(--gold);
}

.timeline > li { position: relative; }

.timeline > li::before {
  content: "";
  position: absolute;
  border-radius: 50%;
  background: var(--gold);
  transition: background-color 0.3s ease;
}

.js .timeline > li:not(.reached)::before { background: var(--line); }

/* The year, where it changes */
.timeline > li.year {
  margin: var(--s-4) 0 var(--s-2);
  color: var(--navy);
  font-family: var(--serif);
  font-size: var(--step-2);
  font-weight: 700;
  line-height: 1;
}

.timeline > li.year:first-child { margin-top: 0; }

.timeline > li.year::before {
  left: calc(-1 * var(--s-4) + 1px);
  top: 0.18em;
  width: 14px;
  height: 14px;
  box-shadow: 0 0 0 3px var(--bg);
}

/* Years roll into place like a counter (built by site.js): each digit is a strip of 0 to 9 */
.odo {
  display: inline-flex;
  font-variant-numeric: lining-nums tabular-nums;
  -webkit-user-select: none;
  user-select: none;
}

.odo-digit {
  display: block;
  height: 1em;
  overflow: hidden;
}

.odo-strip {
  display: block;
  transform: translateY(calc(var(--d, 0) * -1em));
}

.odo-strip span {
  display: block;
  height: 1em;
  line-height: 1;
}

/* Beside the timeline, a large year follows the entry being read. It needs room
   beside the entries, so it only shows on large screens */
.chapter { display: none; }

.chapter .odo {
  color: transparent;
  font-family: var(--serif);
  font-size: 4.25rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  -webkit-text-stroke: 1.5px var(--navy);
}

@media (min-width: 1600px) {
  .js .with-chapter {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    column-gap: var(--s-4);
    align-items: start;
  }

  .js .with-chapter > :not(.chapter, .timeline) { grid-column: 1 / -1; }

  .js .with-chapter > .chapter {
    display: block;
    position: sticky;
    top: calc(var(--nav-height) + var(--masthead-h, 0px) + var(--s-3));
  }

  .js .with-chapter > .timeline { grid-column: 2; }

  /* The large year does the work of the year labels, which shrink to a dot on the line */
  .js .with-chapter .timeline > li.year {
    height: 14px;
    margin: var(--s-3) 0 var(--s-2);
  }

  .js .with-chapter .timeline > li.year:first-child { margin-top: 0; }
  .js .with-chapter .timeline > li.year > span { display: none; }
  .js .with-chapter .timeline > li.year::before { top: 0; }
}

.timeline > li.entry { margin-bottom: var(--s-2); }

.timeline > li.entry::before {
  left: calc(-1 * var(--s-4) + 4px);
  top: 1.5rem;
  width: 8px;
  height: 8px;
  box-shadow: 0 0 0 3px var(--bg);
}

/* Each entry is a card that opens to show what I did, with photos */
.card {
  --glow: 0;
  --mx: 50%;
  --my: 0%;
  position: relative;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background:
    radial-gradient(21rem circle at var(--mx) var(--my), rgb(234 167 47 / calc(var(--glow) * 0.12)), transparent 62%),
    var(--card);
  box-shadow: var(--shadow);
  transition: --glow 0.5s ease, box-shadow 0.4s var(--ease-out), opacity 0.3s ease;
}

@media (hover: hover) and (pointer: fine) {
  .card:hover {
    --glow: 1;
    box-shadow: var(--shadow-lift);
  }
}

.entry summary {
  display: grid;
  gap: 2px;
  padding: var(--s-2) var(--s-3);
  cursor: pointer;
  list-style: none;
}

.entry summary::-webkit-details-marker { display: none; }

.entry .top {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: baseline;
  gap: 2px var(--s-2);
}

.kind {
  color: var(--gold-deep);
  font-size: var(--step--2);
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.when {
  color: var(--muted);
  font-size: var(--step--1);
  font-variant-numeric: tabular-nums;
}

.entry h3 {
  margin: 2px 0 0;
  font-size: 1.0625rem;
  line-height: 1.35;
}

.entry .role {
  color: var(--accent);
  font-size: 0.9375rem;
  font-weight: 600;
}

.entry .place {
  color: var(--muted);
  font-size: var(--step--1);
}

.entry .gist {
  margin-top: 4px;
  font-size: 0.9375rem;
}

.entry .more {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  justify-self: start;
  margin-top: 4px;
  color: var(--accent);
  font-size: var(--step--1);
  font-weight: 700;
}

/* The logo of the school or organisation sits beside the title */
.entry summary:has(> .logo) {
  grid-template-columns: auto minmax(0, 1fr);
  column-gap: var(--s-2);
}

.entry summary:has(> .logo) > :not(.logo) { grid-column: 1 / -1; }
.entry summary:has(> .logo) > :is(h3, .role, .place) { grid-column: 2; }

.entry .logo {
  grid-column: 1;
  grid-row: 2 / span 2;
  align-self: start;
  width: 2.75rem;
  height: 2.75rem;
  margin-top: 4px;
  padding: 0.3125rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-small);
  background: var(--card);
  object-fit: contain;
}

/* Phones: a closed entry shows only its type, dates, title and role, to keep the page short */
@media (max-width: 599px) {
  .entry details:not([open]) :is(.gist, .place) { display: none; }
}

.chevron { transition: transform 0.3s var(--ease-out); }
details[open] .chevron { transform: rotate(180deg); }

.detail {
  margin: 0 var(--s-3);
  padding: var(--s-2) 0 var(--s-3);
  border-top: 1px solid var(--line);
  font-size: 0.9375rem;
}

.detail > p:last-child { margin-bottom: 0; }

.detail ul {
  margin: 0 0 var(--s-2);
  padding-left: var(--s-3);
}

.detail ul.tags {
  margin-bottom: 0;
  padding: 0;
}

.detail li { margin-bottom: 6px; }

.detail h4 {
  margin: var(--s-3) 0 0;
  color: var(--accent);
  font-family: var(--serif);
  font-size: var(--step-1);
}

.detail .role {
  margin: 0 0 var(--s-1);
  color: var(--accent);
  font-style: italic;
}

/* Problem, approach, outcome, and the rows of courses and activities */
.steps,
.rows { margin: 0 0 var(--s-2); }

.steps div,
.rows div {
  padding: 6px 0;
  border-top: 1px solid var(--line);
}

.steps div:first-child,
.rows div:first-child { border-top: 0; }

.steps dt,
.rows dt {
  color: var(--accent);
  font-size: var(--step--2);
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.steps dd,
.rows dd { margin: 2px 0 0; }

.shots {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--s-2);
  margin: var(--s-2) 0 0;
}

.shots .photo { margin: 0; }

.links {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-1) var(--s-3);
  margin: var(--s-2) 0 0;
}

.links a.org {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: var(--step--1);
  font-weight: 700;
}

/* Skill lens: entries without the chosen skill fade back */
.entry,
li[data-skills] { transition: opacity 0.3s ease; }

.lens-on .entry:not(.match),
.lens-on .entry.match li[data-skills]:not(.match) { opacity: 0.35; }

.lens-on .entry.match .card { box-shadow: 0 0 0 2px var(--gold), var(--shadow); }
.lens-on li.match::marker { color: var(--gold); }
.lens-on footer { padding-bottom: var(--s-6); }

/* Hiring for: a recruiter picks a field, and the page leads with what that field looks for */
.reader { display: none; }

.js .reader {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-1) var(--s-2);
  margin-top: var(--s-3);
  padding: var(--s-2) var(--s-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-small);
  background: var(--card);
}

.reader-label {
  margin: 0;
  color: var(--gold-deep);
  font-size: var(--step--2);
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.reader-picks {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.reader-pick {
  padding: 3px var(--s-2);
  border: 1px solid var(--navy);
  border-radius: 999px;
  background: transparent;
  color: var(--navy);
  font: inherit;
  font-size: var(--step--1);
  font-weight: 700;
  cursor: pointer;
  transition: background-color 0.3s ease, color 0.3s ease;
}

.reader-pick:hover { background: var(--tint); }

.reader-pick[aria-pressed="true"] {
  background: var(--navy);
  color: #ffffff;
}

.reader-pitch {
  flex-basis: 100%;
  margin: 0;
  font-size: 0.9375rem;
}

.reader-pitch[hidden] { display: none; }
.reader-pitch[data-reader=""] { color: var(--muted); }

/* Cards for the chosen field stand out and the others step back, unless the skill lens is on */
.reader-on:not(.lens-on) .entry.for-match .card { box-shadow: inset 3px 0 0 var(--gold), var(--shadow); }
.reader-on:not(.lens-on) .entry.for-other { opacity: 0.55; }
.reader-on .detail li.for-match::marker { color: var(--gold); }

.lens-bar {
  position: fixed;
  left: 50%;
  bottom: var(--s-3);
  z-index: 20;
  display: flex;
  align-items: center;
  gap: var(--s-3);
  width: max-content;
  max-width: calc(100% - 2 * var(--s-3));
  padding: var(--s-1) var(--s-1) var(--s-1) var(--s-3);
  border: 1px solid rgba(255, 255, 255, 0.14);
  /* A pill on one line, a rounded box when several chosen skills need more lines */
  border-radius: 1.75rem;
  background: rgba(11, 31, 69, 0.9);
  -webkit-backdrop-filter: saturate(160%) blur(13px);
  backdrop-filter: saturate(160%) blur(13px);
  color: #ffffff;
  font-size: 0.9375rem;
  box-shadow: 0 13px 34px rgba(11, 31, 69, 0.3);
  translate: -50% 0;
}

.lens-bar[hidden] { display: none; }

.lens-bar > span {
  display: flex;
  flex-wrap: wrap;
  column-gap: var(--s-1);
}

.lens-bar strong { color: var(--gold); }

.lens-clear {
  flex-shrink: 0;
  padding: var(--s-1) var(--s-3);
  border: 0;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.14);
  color: #ffffff;
  font: inherit;
  font-weight: 700;
  cursor: pointer;
}

.lens-clear:hover { background: rgba(255, 255, 255, 0.24); }

.lens-pick:focus-visible,
.lens-clear:focus-visible,
.reader-pick:focus-visible {
  outline: 3px solid var(--gold);
  outline-offset: 3px;
}

@media (max-width: 559px) {
  .lens-bar {
    gap: var(--s-1);
    font-size: 0.875rem;
    line-height: 1.3;
  }

  .lens-clear { padding: var(--s-1) var(--s-2); }
}


/* ===== Photos ============================================================ */

.photo { margin: 0; }

.photo img {
  width: 100%;
  aspect-ratio: 4 / 3;
  border-radius: var(--radius-small);
  object-fit: cover;
  clip-path: inset(0 round var(--radius-small));
  transition: transform 1.2s var(--ease-out), clip-path 1.2s var(--ease-out);
}

/* Pointing at a photo zooms it slightly inside its frame */
@media (hover: hover) and (pointer: fine) {
  .photo:hover img {
    transform: scale(1.04);
    clip-path: inset(1.92% round 7.7px);
  }
}

.photo figcaption {
  margin-top: 6px;
  color: var(--muted);
  font-size: var(--step--1);
  font-style: italic;
  line-height: 1.4;
}

.photo figcaption .place {
  display: block;
  color: var(--accent);
  font-size: var(--step--2);
  font-style: normal;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

/* Photos fade in as they come into view */
.js .photo {
  opacity: 0;
  transform: translateY(var(--s-3));
  transition: opacity 0.9s var(--ease-out), transform 0.9s var(--ease-out);
}

.js .photo.visible {
  opacity: 1;
  transform: none;
}


/* ===== Along the Way: photos that pan across, like the ticker ============ */

.reel { position: relative; }

/* Without movement (or before site.js runs) the photos sit in a row you can swipe */
.reel-scroller {
  margin-inline: calc(var(--gutter) * -1);
  padding: 0 var(--gutter) var(--s-1);
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  scroll-padding-inline: var(--gutter);
  scrollbar-width: none;
}

.reel-scroller::-webkit-scrollbar { display: none; }

.reel-track {
  display: flex;
  width: max-content;
}

/* A margin rather than a gap, so a full copy of the strip is exactly half its width */
.reel .photo {
  flex: none;
  width: min(62vw, 15rem);
  margin: 0 var(--s-2) 0 0;
  scroll-snap-align: start;
}

/* The strip moves on its own, so its photos skip the fade-in */
.js .reel .photo {
  opacity: 1;
  transform: none;
}

/* site.js adds a second copy of the photos and the class "panning": the strip then
   loops endlessly, fades out at both edges, and pauses while you point at it */
.reel.panning .reel-scroller {
  padding-inline: 0;
  overflow: hidden;
  scroll-snap-type: none;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 var(--s-5), #000 calc(100% - var(--s-5)), transparent);
  mask-image: linear-gradient(90deg, transparent, #000 var(--s-5), #000 calc(100% - var(--s-5)), transparent);
  /* A sideways swipe moves the strip, an up or down swipe still scrolls the page */
  touch-action: pan-y pinch-zoom;
}

@media (min-width: 1100px) {
  .reel-scroller { margin-inline: 0; }
}

.reel.panning .reel-track { will-change: transform; }

/* The sides of the strip are buttons that move it a photo back or forward */
.reel-frame { position: relative; }

.reel-nav { display: none; }

.js .reel-nav {
  position: absolute;
  top: 0;
  z-index: 1;
  display: flex;
  align-items: center;
  width: max(3.5rem, 12%);
  /* As tall as the photos, so the captions stay free */
  height: calc(min(62vw, 15rem) * 3 / 4);
  padding: 0 var(--s-1);
  border: 0;
  background: none;
  color: var(--navy);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.js .reel-nav.prev {
  left: 0;
  justify-content: flex-start;
}

.js .reel-nav.next {
  right: 0;
  justify-content: flex-end;
}

.reel-arrow {
  display: grid;
  place-items: center;
  width: 2.75rem;
  height: 2.75rem;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.92);
  box-shadow: var(--shadow-lift);
  transition: opacity 0.3s ease, transform 0.3s var(--ease-out);
}

/* With a mouse, the arrows show while you point at the strip */
@media (hover: hover) and (pointer: fine) {
  .reel-arrow { opacity: 0; }
  .reel:hover .reel-arrow { opacity: 0.85; }

  .reel-nav:hover .reel-arrow {
    opacity: 1;
    transform: scale(1.08);
  }
}

.reel-nav:focus-visible { outline: none; }

.reel-nav:focus-visible .reel-arrow {
  opacity: 1;
  outline: 3px solid var(--gold);
  outline-offset: 3px;
}


/* ===== Links to organisations ============================================ */

a.org {
  color: inherit;
  text-decoration: underline;
  text-decoration-color: var(--gold);
  text-decoration-thickness: 0.08em;
  text-underline-offset: 0.2em;
  transition: color 0.3s ease, text-decoration-thickness 0.3s ease;
}

a.org:hover {
  color: var(--accent);
  text-decoration-thickness: 0.14em;
}

.links a.org { color: var(--accent); }
.external { flex: none; }


/* ===== World map ========================================================= */

.map {
  position: relative;
  margin: 0;
  padding: var(--s-3);
  border-radius: var(--radius);
  background: var(--navy-night);
  color: #ffffff;
  box-shadow: var(--shadow);
}

.map-head {
  display: grid;
  gap: var(--s-2);
  margin-bottom: var(--s-2);
}

.map-tally {
  margin: 0;
  color: var(--navy-soft);
}

.map-tally strong {
  color: var(--gold);
  font-family: var(--serif);
  font-size: var(--step-2);
}

/* One button per continent; on phones the row scrolls sideways */
.map-zoom {
  display: none;
  gap: 6px;
  margin: -6px 0;
  padding: 6px 0;
  overflow-x: auto;
  scrollbar-width: none;
}

.map-zoom::-webkit-scrollbar { display: none; }

.js .map-zoom { display: flex; }

.map-zoom button {
  flex: none;
  padding: 5px 13px;
  border: 1px solid rgba(255, 255, 255, 0.35);
  border-radius: 999px;
  background: transparent;
  color: #ffffff;
  font: inherit;
  font-size: var(--step--1);
  font-weight: 700;
  white-space: nowrap;
  cursor: pointer;
  transition: border-color 0.3s ease, background-color 0.3s ease;
}

.map-zoom button:hover { border-color: var(--gold); }

.map-zoom button[aria-pressed="true"] {
  border-color: var(--gold);
  background: var(--gold);
  color: #14233c;
}

/* Space for the map is kept while it loads, so the page does not jump */
.map-canvas { position: relative; }
.js .map-canvas { aspect-ratio: 1000 / 486.7; }

.map-canvas svg {
  display: block;
  width: 100%;
  height: 100%;
}

.map-sphere { fill: #12306a; }

.map-land,
.map-visited {
  stroke: var(--navy-night);
  stroke-width: 0.6;
  vector-effect: non-scaling-stroke;
}

.map-land,
.map-visited:not(.lit) { fill: #2b4677; }

.map-visited.lit,
.map-dot { fill: var(--gold); }

.map-dot {
  stroke: var(--navy-night);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
}

.map-dot:not(.lit) { opacity: 0; }

.map-visited.lit,
.map-dot.lit { cursor: pointer; }

.map-visited.lit:hover,
.map-visited.active,
.map-dot.lit:hover,
.map-dot.active { fill: var(--gold-pale); }

/* The name of the country under the pointer or finger */
.map-tip {
  position: absolute;
  z-index: 1;
  padding: 4px 12px;
  border-radius: 999px;
  background: #ffffff;
  color: var(--navy-night);
  font-size: 0.875rem;
  font-weight: 700;
  white-space: nowrap;
  pointer-events: none;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.3);
  translate: -50% calc(-100% - 12px);
}

.map-tip.below { translate: -50% 16px; }
.map-tip[hidden] { display: none; }

/* The list of countries is read out by screen readers but not shown */
.map-names {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

@media (max-width: 699px) {
  /* The button row reaches the edges of the panel and fades out there */
  .map-zoom {
    margin: -6px calc(var(--s-3) * -1);
    padding: 6px var(--s-3);
    -webkit-mask-image: linear-gradient(90deg, transparent, #000 var(--s-3), #000 calc(100% - var(--s-3)), transparent);
    mask-image: linear-gradient(90deg, transparent, #000 var(--s-3), #000 calc(100% - var(--s-3)), transparent);
  }
}


/* ===== Ticker, contact and footer ======================================== */

.ticker {
  margin-top: var(--s-6);
  padding: var(--s-2) 0;
  overflow: hidden;
  background: var(--navy-night);
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}

.ticker-track {
  display: flex;
  width: max-content;
  animation: ticker 45s linear infinite;
}

.ticker span {
  display: flex;
  align-items: center;
  color: #ffffff;
  font-size: var(--step--1);
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  white-space: nowrap;
}

/* A small gold diamond between the words */
.ticker span::after {
  content: "";
  flex: none;
  width: 0.4em;
  height: 0.4em;
  margin: 0 var(--s-3);
  background: var(--gold);
  transform: rotate(45deg);
}

@keyframes ticker {
  to { transform: translateX(-50%); }
}

.contact {
  padding: var(--s-5) 0;
  background:
    radial-gradient(circle at 90% 0%, rgba(234, 167, 47, 0.16), transparent 42%),
    var(--navy-night);
  color: #ffffff;
}

.contact .eyebrow { margin-bottom: var(--s-1); }

.contact h2 {
  margin-bottom: var(--s-2);
  font-size: clamp(var(--step-3), 5vw, var(--step-4));
}

.contact h2::after { background: rgba(255, 255, 255, 0.2); }

.contact p:not(.eyebrow) {
  max-width: 38em;
  margin: 0 0 var(--s-3);
  color: var(--navy-soft);
}

/* Contact cards: LinkedIn and email */
.reach {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--s-2);
}

.reach-card {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  min-width: 0;
  padding: var(--s-2) var(--s-3);
  border: 1px solid rgba(255, 255, 255, 0.3);
  border-radius: var(--radius);
  color: #ffffff;
  text-decoration: none;
  transition: border-color 0.3s ease, background-color 0.3s ease;
}

.reach-card:hover {
  border-color: var(--gold);
  background: rgba(255, 255, 255, 0.05);
}

/* Same size and corners as the LinkedIn logo, which brings its own blue square */
.reach-icon {
  flex: none;
  display: grid;
  place-items: center;
  width: var(--s-5);
  height: var(--s-5);
  border-radius: 4px;
  background: var(--gold);
  color: #14233c;
}

.reach-icon.linkedin { background: none; }
.reach-icon svg { display: block; }

.reach-text {
  flex: 1;
  min-width: 0;
}

.reach-text strong {
  display: block;
  font-family: var(--serif);
  font-size: var(--step-1);
  line-height: 1.3;
}

.reach-text span {
  display: block;
  color: var(--navy-soft);
  font-size: var(--step--1);
  overflow-wrap: break-word;
}

.reach-arrow {
  flex: none;
  display: grid;
  color: var(--gold);
  transition: transform 0.45s var(--ease-out);
}

.reach-card:hover .reach-arrow { transform: translateX(4px); }

/* Footer: the name in large letters, then the last update */
footer {
  padding: var(--s-4) 0 var(--s-3);
  background: var(--navy-night);
  border-top: 1px solid rgba(255, 255, 255, 0.1);
  color: rgba(255, 255, 255, 0.62);
  font-size: var(--step--1);
}

footer p { margin: 0; }

.wordmark {
  margin: 0 0 var(--s-1);
  color: #ffffff;
  font-family: var(--serif);
  font-size: clamp(var(--step-1), 5vw, var(--step-3));
  line-height: 1.15;
  letter-spacing: 0.3em;
  text-transform: uppercase;
}

@media (min-width: 700px) {
  .reach { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}


/* ===== Movement (skipped when a device asks for reduced motion) ========== */

@media (prefers-reduced-motion: no-preference) {
  @keyframes rise {
    from { opacity: 0; translate: 0 var(--s-2); }
  }

  @keyframes letter-rise {
    from { transform: translateY(105%); }
  }

  @keyframes pulse {
    50% { transform: scale(1.4); }
  }

  /* Profile: everything arrives one after the other, the name letter by letter */
  .js .portrait { animation: rise 0.9s var(--ease-out) both; }
  .js .profile .eyebrow { animation: rise 0.8s var(--ease-out) 0.05s both; }
  .js .profile h1:not(.split) { opacity: 0; }
  .js .profile h1 .char { animation: letter-rise 1s var(--ease-out) calc(0.1s + var(--i) * 35ms) both; }
  .js .profile .title { animation: rise 0.8s var(--ease-out) 0.3s both; }
  .js .profile .summary { animation: rise 0.8s var(--ease-out) 0.4s both; }
  .js .profile .facts { animation: rise 0.8s var(--ease-out) 0.5s both; }
  .js .profile .actions { animation: rise 0.8s var(--ease-out) 0.6s both; }

  /* Sections fade up as they scroll into view */
  .js :is(main section > h2, main section > .intro, .cv > .cv-row, .timeline > li, .contact .wrap > *) {
    transition:
      opacity 0.8s var(--ease-out) var(--delay, 0s),
      translate 0.8s var(--ease-out) var(--delay, 0s),
      background-color 0.3s ease,
      box-shadow 0.3s ease;
  }

  .js :is(main section > h2, main section > .intro, .cv > .cv-row, .timeline > li, .contact .wrap > *):not(.in) {
    opacity: 0;
    translate: 0 var(--s-3);
  }

  /* The hairline beside each section title draws itself */
  .js main section > h2::after,
  .js .contact h2::after { transition: transform 1.4s var(--ease-out) 0.25s; }

  .js main section > h2:not(.in)::after,
  .js .contact h2:not(.in)::after { transform: scaleX(0); }

  .js .timeline > li.reached::before { animation: pulse 0.6s ease; }

  /* Years count up from 0000 digit by digit as they arrive, and the large year beside
     the timeline rolls to the entry being read */
  .odo-strip { transition: transform 1.1s var(--ease-out) calc(var(--i, 0) * 70ms); }

  .js .timeline > li.year:not(.in) .odo-strip,
  .js .chapter:not(.in) .odo-strip { transform: translateY(0); }

  .js .chapter { transition: opacity 0.6s ease; }
  .js .chapter:not(.in) { opacity: 0; }

  /* Opening an entry slides its details open where browsers can animate to "auto" */
  @supports (interpolate-size: allow-keywords) {
    :root { interpolate-size: allow-keywords; }

    .entry details::details-content {
      height: 0;
      overflow: clip;
      transition: height 0.45s var(--ease-out), content-visibility 0.45s allow-discrete;
    }

    .entry details[open]::details-content { height: auto; }
  }

  /* The phone menu's sections arrive one after another */
  .menu:not([hidden]) li { animation: rise 0.6s var(--ease-out) calc(var(--n) * 40ms) both; }

  .mountains path { will-change: transform; }

  /* Map: it fades in, then each country flashes a pale gold and settles */
  @keyframes map-in {
    from { opacity: 0; }
  }

  @keyframes map-light {
    from { fill: #fff3d1; }
  }

  @keyframes map-pop {
    from { opacity: 0; transform: scale(0.2); }
    60% { transform: scale(1.5); }
  }

  .map-canvas svg { animation: map-in 0.8s ease both; }
  .map-visited.lit { animation: map-light 0.9s ease; }

  .map-dot {
    transform-box: fill-box;
    transform-origin: center;
  }

  .map-dot.lit { animation: map-pop 0.6s ease; }
}

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

  .js .photo {
    opacity: 1;
    transform: none;
    transition: none;
  }

  .ticker-track { animation: none; }
}


/* ===== Print ============================================================= */

@media print {
  nav,
  .menu,
  .actions,
  .ticker,
  .lens-bar,
  .lens-pick,
  .reader,
  .map,
  .reel,
  .chapter,
  .shots,
  .langs,
  .mountains,
  .entry .more { display: none !important; }

  body {
    background: #ffffff;
    font-size: 11pt;
  }

  .page,
  .columns { display: block; }

  .masthead,
  #skills {
    position: static;
    box-shadow: none;
    clip-path: none;
  }

  .profile,
  .contact,
  footer {
    position: static;
    max-height: none;
    padding: 0 0 12pt;
    background: none;
    color: #000000;
    box-shadow: none;
  }

  .summary,
  .summary strong,
  .title em,
  .eyebrow,
  .facts dt,
  .contact p:not(.eyebrow),
  .wordmark,
  .reach-card,
  .reach-text span { color: #000000; }

  .card { box-shadow: none; }

  /* Print every entry open */
  .entry details > .detail { display: block; }

  .js :is(main section > h2, main section > .intro, .cv > .cv-row, .timeline > li, .contact .wrap > *) {
    opacity: 1 !important;
    translate: none !important;
  }

  .js .timeline::before { display: none; }
  .js .timeline > li::before { background: var(--gold) !important; }

  .lens-on .entry,
  .lens-on [data-skills],
  .reader-on .entry,
  .reader-on .entry .card {
    opacity: 1 !important;
    box-shadow: none !important;
  }

  a.org { text-decoration: none; }
}
