/* ==========================================================================
   Base — reset, typography, and the content blocks shared across slides.
   Layout/deck behaviour lives in deck.css.
   ========================================================================== */

@import url("https://fonts.googleapis.com/css2?family=Newsreader:ital,opsz,wght@0,6..72,400;0,6..72,500;0,6..72,600;1,6..72,400;1,6..72,500&family=Inter:wght@400;500;600&display=swap");

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

body {
  margin: 0;
  background: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font-sans);
  font-size: var(--fs-body);
  line-height: var(--lh-normal);
  -webkit-font-smoothing: antialiased;
}

img {
  max-width: 100%;
  display: block;
}

h1, h2, h3 {
  font-family: var(--font-serif);
  font-weight: 500;
  line-height: var(--lh-tight);
  margin: 0;
}

p {
  margin: 0;
}

a {
  color: var(--color-link);
  text-decoration-thickness: 1.5px;
  text-underline-offset: 3px;
  transition: color var(--dur-fast) var(--ease);
}

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

ul {
  margin: 0;
  padding: 0;
  list-style: none;
}

button {
  font-family: inherit;
  cursor: pointer;
}

/* One visible focus indicator for every interactive element, rather than
   relying on each browser's default against a custom-styled control. */
:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 3px;
  border-radius: 2px;
}

/* ---- Layout helpers ---- */

.container {
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 0 var(--space-5);
  width: 100%;
}

.container--wide {
  max-width: var(--max-width-wide);
}

.section__head {
  margin-bottom: var(--space-7);
}

.section__head h2 {
  font-size: var(--fs-h1);
}

.eyebrow {
  display: block;
  font-size: var(--fs-tiny);
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  margin-bottom: var(--space-3);
}

.lead {
  font-size: var(--fs-lead);
  color: var(--color-text-muted);
  max-width: 58ch;
  font-family: var(--font-serif);
  line-height: var(--lh-snug);
}

.lead a {
  font-weight: 500;
}

/* ---- Intro: text beside portrait ---- */

.intro {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 260px;
  gap: var(--space-9);
  align-items: center;
}

/* Horizontal link card — a whole row is the target, arrow signals where it goes. */

.card-link {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-5);
  padding: var(--space-4) var(--space-5);
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius-lg);
  background: var(--color-bg-raised);
  color: var(--color-text);
  text-decoration: none;
  transition: border-color var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease);
}

.card-link:hover {
  color: var(--color-text);
  border-color: var(--color-control-active);
  background: var(--color-bg-hover);
}

.card-link:active {
  background: var(--color-bg-raised);
}

.card-link__text {
  font-weight: 500;
}

.card-link__arrow {
  color: var(--color-accent);
  transition: transform var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}

.card-link:hover .card-link__arrow {
  color: var(--color-control-active);
  transform: translateX(4px);
}

@media (prefers-reduced-motion: reduce) {
  .card-link__arrow {
    transition: none;
  }
  .card-link:hover .card-link__arrow {
    transform: none;
  }
}

.intro__cta {
  margin-top: var(--space-6);
  max-width: 400px;
}

.intro__photo {
  margin: 0;
  aspect-ratio: 1;
  border-radius: 50%;
  overflow: hidden;
  background: var(--color-bg-raised);
}

.intro__photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 0;
  /* The source is a standing 3:4 portrait, so an untouched square crop sits on
     the torso. Scale up around the face to get head-and-shoulders instead —
     these two values are the framing controls. */
  transform: scale(1.8);
  transform-origin: 50% 30%;
}

@media (max-width: 860px) {
  .intro {
    grid-template-columns: 1fr;
    gap: var(--space-5);
  }

  .intro__photo {
    order: -1;
    width: 104px;
  }
}

/* ---- Experience list ---- */

.job {
  display: grid;
  grid-template-columns: 190px 1fr;
  gap: var(--space-5) var(--space-7);
  padding: var(--space-6) 0;
  border-top: var(--border-width) solid var(--color-border);
}

.job:first-child {
  border-top: none;
  padding-top: 0;
}

.job__meta {
  color: var(--color-text-muted);
  font-size: var(--fs-small);
}

.job__period {
  display: block;
  margin-top: var(--space-1);
}

.job__title {
  font-size: var(--fs-h3);
  margin-bottom: var(--space-2);
}

.job__title span {
  color: var(--color-text-muted);
  font-family: var(--font-sans);
  font-size: var(--fs-body);
  font-weight: 400;
}

.job__desc {
  max-width: 62ch;
}

@media (max-width: 640px) {
  .job {
    grid-template-columns: 1fr;
    gap: var(--space-2);
  }
}

/* ---- Work, grouped by category ---- */

.work-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-5);
}

.work-category h3 {
  font-size: var(--fs-h3);
  margin-bottom: var(--space-4);
  padding-bottom: var(--space-3);
  border-bottom: var(--border-width) solid var(--color-border);
}

/* Sits below the heading's rule, so the rules stay aligned across columns even
   though these descriptions wrap to different depths. */
.work-category__desc {
  color: var(--color-text-muted);
  font-size: var(--fs-small);
  margin-bottom: var(--space-5);
  text-wrap: pretty;
}

.work-item {
  padding: var(--space-3) 0;
  border-top: var(--border-width) dashed var(--color-border);
}

.work-item:first-of-type {
  border-top: none;
}

.work-item__link {
  display: block;
  color: var(--color-text);
  text-decoration: none;
}

.work-item__title {
  display: block;
  font-weight: 500;
  transition: color var(--dur-fast) var(--ease);
}

/* These all leave the site, so mark them as outbound. */
.work-item__title::after {
  content: " \2197";
  color: var(--color-text-muted);
  font-weight: 400;
}

.work-item__link:hover .work-item__title {
  color: var(--color-link);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.work-item__summary {
  display: block;
  color: var(--color-text-muted);
  font-size: var(--fs-small);
  margin-top: 2px;
}

@media (max-width: 780px) {
  .work-grid {
    grid-template-columns: 1fr;
  }
}

/* ---- Community & mentoring ---- */

.community__lead {
  max-width: 66ch;
  margin-bottom: var(--space-4);
}

.community__lead:last-of-type {
  margin-bottom: var(--space-7);
}

/* Two-column reference list — used for talks and certifications alike. */

.list-block h3 {
  font-size: var(--fs-h3);
  margin-bottom: var(--space-4);
  padding-bottom: var(--space-3);
  border-bottom: var(--border-width) solid var(--color-border);
}

.list-block--spaced {
  margin-top: var(--space-7);
}

.list-block ul {
  columns: 2;
  column-gap: var(--space-8);
}

/* Separators sit on the bottom, not the top: with CSS columns a top border
   would also land on the first item of the second column, drawing a stray
   rule right under the heading. */
.list-item {
  break-inside: avoid;
  padding: var(--space-3) 0;
  border-bottom: var(--border-width) dashed var(--color-border);
}

/* Deliberately no :first-child padding reset. With CSS columns that selector
   means "first in the list", not "first in each column", so zeroing it there
   drops the second column 12px lower than the first. Every item keeps the
   same padding and the columns line up. */

.list-item:last-child {
  border-bottom: none;
}

.list-item__title {
  display: block;
  font-weight: 500;
}

/* Some entries link out to a recording or a write-up; the rest are plain text. */
.list-item__link {
  display: block;
  color: var(--color-text);
  text-decoration: none;
}

.list-item__link .list-item__title::after {
  content: " \2197";
  color: var(--color-text-muted);
  font-weight: 400;
}

.list-item__link:hover .list-item__title {
  color: var(--color-link);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.list-item__meta {
  display: block;
  color: var(--color-text-muted);
  font-size: var(--fs-small);
  margin-top: 2px;
}

@media (max-width: 780px) {
  .list-block ul {
    columns: 1;
  }
}

/* ---- Quotes ---- */

/* Set as pull quotes rather than cards: a single short excerpt doesn't need a
   container to hold it, and the boxes were the heaviest thing on the page. */
/* Fixed at two rather than auto-fit: at the container's full width auto-fit
   would slip to three ~300px columns, which is too narrow a measure for serif
   quotes and leaves a ragged 3+1 row on four. Two keeps the rhythm at any
   count. align-items: start so each rule matches its own quote, not the row. */
.quote-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  align-items: start;
  gap: var(--space-8) var(--space-7);
}

@media (max-width: 720px) {
  .quote-grid {
    grid-template-columns: 1fr;
  }
}

.quote {
  margin: 0;
  padding-left: var(--space-5);
  border-left: 2px solid var(--color-border);
}

.quote blockquote {
  margin: 0 0 var(--space-4);
  font-family: var(--font-serif);
  font-size: var(--fs-lead);
  line-height: var(--lh-snug);
  text-wrap: pretty;
}

.quote blockquote p {
  margin: 0;
}

/* Excerpts joined across an elision get a gap, not a full paragraph break. */
.quote blockquote p + p {
  margin-top: var(--space-3);
}

.quote__name {
  display: block;
  font-weight: 600;
  font-size: var(--fs-small);
}

.quote__role {
  display: block;
  color: var(--color-text-muted);
  font-size: var(--fs-tiny);
  margin-top: 2px;
}

/* ---- Contact ---- */

.contact h2 {
  font-size: var(--fs-h1);
  margin-bottom: var(--space-4);
  max-width: 18ch;
}

.contact__lead {
  color: var(--color-text-muted);
  font-size: var(--fs-lead);
  font-family: var(--font-serif);
  max-width: 46ch;
  margin-bottom: var(--space-6);
}

.contact__links {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3) var(--space-6);
}

.contact__links a {
  font-size: var(--fs-h3);
  font-family: var(--font-serif);
  text-decoration: none;
  border-bottom: 1px solid var(--color-border);
  padding-bottom: 2px;
}

.contact__links a:hover {
  border-color: var(--color-link);
}

/* ---- Scroll reveal ---- */

/* Scoped to .js (set by an inline script in the head) so that without
   JavaScript the content is simply visible rather than stuck at opacity 0. */
.js .reveal {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity var(--dur-slow) var(--ease), transform var(--dur-slow) var(--ease);
}

.js .reveal.is-visible {
  opacity: 1;
  transform: none;
}

@media (prefers-reduced-motion: reduce) {
  .deck {
    scroll-behavior: auto;
  }
  .reveal {
    opacity: 1;
    transform: none;
    transition: none;
  }
}
