/* katemoran.work, "The Wordmark" (approved 2026-10-25).
   One stylesheet for every page. Colors are defined once, here. No inline
   styles anywhere: the content security policy allows styles from this
   file only. */

/* ---------- Fonts (self-hosted, SIL Open Font License; see assets/fonts) ---------- */

@font-face { font-family: "Courier Prime"; font-style: normal; font-weight: 400; font-display: swap; src: url("/assets/fonts/courier-prime-400.woff2") format("woff2"); }
@font-face { font-family: "Courier Prime"; font-style: normal; font-weight: 700; font-display: swap; src: url("/assets/fonts/courier-prime-700.woff2") format("woff2"); }
@font-face { font-family: "Courier Prime"; font-style: italic; font-weight: 400; font-display: swap; src: url("/assets/fonts/courier-prime-400-italic.woff2") format("woff2"); }
@font-face { font-family: "Jost"; font-style: normal; font-weight: 500 600; font-display: swap; src: url("/assets/fonts/jost-500-600.woff2") format("woff2"); }
@font-face { font-family: "Cormorant Garamond"; font-style: normal; font-weight: 500 700; font-display: swap; src: url("/assets/fonts/cormorant-garamond-500-700.woff2") format("woff2"); }
@font-face { font-family: "Cormorant Garamond"; font-style: italic; font-weight: 500; font-display: swap; src: url("/assets/fonts/cormorant-garamond-500-italic.woff2") format("woff2"); }
@font-face { font-family: "Playfair Display"; font-style: normal; font-weight: 900; font-display: swap; src: url("/assets/fonts/playfair-display-900.woff2") format("woff2"); }

/* ---------- Tokens ---------- */

:root {
  --paper: #F2ECDF;
  --paper-dark: #E9E2D1;   /* Writing cards, Speaking topics */
  --ink: #2A2A1F;
  --olive: #4B5427;
  --muted: #635D4C;
  --sage: #D9DDBF;         /* text on olive and charcoal only */
  --hairline: #A79E87;     /* decorative rules and leaders only */

  --mono: "Courier Prime", "Courier New", monospace;
  --display: "Jost", "Futura", sans-serif;
  --serif: "Cormorant Garamond", Georgia, serif;

  --gutter: clamp(16px, 5vw, 64px);
  --column: 1280px;
  --bar: 76px;
  --sepia: grayscale(1) sepia(0.55) contrast(1.05) brightness(0.96);
}
@media (max-width: 600px) { :root { --bar: 108px; } }

/* ---------- Base ---------- */

*, *::before, *::after { box-sizing: border-box; }
html { scroll-padding-top: var(--bar); -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--mono);
  font-size: 17px;
  line-height: 1.7;
}
img, svg { display: block; max-width: 100%; }
a { color: var(--ink); text-decoration-color: var(--hairline); text-underline-offset: 3px; }
a:hover { color: var(--olive); text-decoration-color: var(--olive); }
h1, h2, h3 { font-weight: inherit; }
p { margin: 0; }

/* One focus ring: olive on paper, sage on olive and charcoal (.dk). */
:focus-visible { outline: 2px solid var(--olive); outline-offset: 3px; }
.dk :focus-visible { outline-color: var(--sage); }

.sr {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}
.skip {
  position: absolute; left: 16px; top: -80px; z-index: 20;
  padding: 10px 16px; background: var(--ink); color: var(--paper); font-weight: 700;
}
.skip:focus, .skip:hover { top: 12px; color: var(--paper); }

/* The one layout container. Every section uses it, so every column edge
   lines up (the canvas's header-offset bug came from two box models). */
.wrap {
  width: 100%;
  max-width: calc(var(--column) + 2 * var(--gutter));
  margin-inline: auto;
  padding-inline: var(--gutter);
}

/* ---------- Display type ---------- */

.display {
  margin: 0;
  font-family: var(--display);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.02em;
}
.t-page    { margin: 0 0 40px; font-size: clamp(44px, 12vw, 176px); line-height: 0.86; letter-spacing: 0.01em; color: var(--olive); }
.t-page--resume { padding-top: 0.16em; }   /* room for the accents */
.t-section { margin: 0 0 56px; font-size: clamp(40px, 6vw, 88px); line-height: 0.95; }
.t-talk    { margin: 0 0 20px; font-size: clamp(36px, 4.4vw, 60px); line-height: 0.95; }
.t-contact { margin: 0 0 10px; font-size: clamp(48px, 7vw, 104px); line-height: 0.92; color: var(--olive); }
.t-band    { margin: 0 0 14px; font-size: clamp(44px, 6.4vw, 96px); line-height: 0.92; color: var(--sage); }
.t-band-sm { margin: 0; font-size: clamp(40px, 5.6vw, 80px); line-height: 0.92; color: var(--sage); }

/* Optical left alignment: minus the first letter's left side bearing in
   Jost 600 (per 1000 units, measured 2026-10-25). Remeasure if the
   display face changes. */
.lsb-76 { margin-left: -0.076em; }  /* K I R P L B F */
.lsb-36 { margin-left: -0.036em; }  /* M */
.lsb-35 { margin-left: -0.035em; }  /* S */
.lsb-6  { margin-left: -0.006em; }  /* W T */

.eyebrow {
  margin: 0 0 8px;
  font-size: 14px; font-weight: 700; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--olive);
}
.eyebrow--muted { margin-bottom: 18px; color: var(--muted); }
.dk .eyebrow--paper { margin-bottom: 36px; color: var(--paper); }
.lede { max-width: 46ch; font-size: clamp(17px, 1.53vw, 21.6px); line-height: 1.6; }   /* 10% under the canvas size, on the subpages (Kate, 2026-10-26) */

.more-link { margin-top: 18px; }
.more-link a { font-weight: 700; color: var(--olive); text-decoration-color: var(--olive); }

/* ---------- Docked bar (subpages and 404) ---------- */

.dock {
  position: sticky; top: 0; z-index: 5;
  background: var(--paper);
  border-bottom: 1px solid var(--ink);
}
.dock .wrap { position: relative; height: var(--bar); }
.wordmark-sm {
  position: absolute; left: var(--gutter); bottom: 11px;
  font-family: var(--display); font-weight: 600; font-size: 30px; line-height: 0.86;
  letter-spacing: 0.01em; text-transform: uppercase;
  color: var(--olive); text-decoration: none;
}
.wordmark-sm:hover { color: var(--ink); }
.wm-first { display: inline-block; margin-left: -0.076em; }   /* K */
.wm-first-m { display: inline-block; margin-left: -0.036em; } /* M */

.topnav {
  position: absolute; top: 26px; right: var(--gutter); z-index: 7;
  display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 4px 24px;
  max-width: calc(100% - 160px);
  font-size: 15px; line-height: 1.6;
}
.topnav [aria-current="page"] {
  color: var(--olive);
  text-decoration: underline; text-decoration-color: var(--olive); text-decoration-thickness: 2px;
}
/* On phones the nav lines up with the two-line wordmark (Kate, 2026-10-26):
   its last row sits on MORAN's baseline, so two rows sit on KATE's and
   MORAN's. The row pitch matches the wordmark's 25.8px line (22.4px line +
   3.4px gap). The nav's bottom is pinned 5.1px above the bar's, through
   top + translate, so it holds for the home page's fixed nav too. Below
   about 330px it takes three rows, the last two still on the wordmark's. */
@media (max-width: 600px) {
  .topnav {
    top: calc(var(--bar) - 5.1px); transform: translateY(-100%);
    gap: 3.4px 16px; font-size: 14px;
  }
}

/* ---------- Home hero: the wordmark that docks ---------- */

/* One driver per motion. --intro runs the load-in (the name rising letter
   by letter, then the intro text); --dock runs the scroll docking. Every
   moving part derives from one of them, so nothing can drift out of step.
   Both rest at 1 / 0, the finished state, when no animation runs. */
@property --intro { syntax: "<number>"; inherits: true; initial-value: 1; }
@property --dock  { syntax: "<number>"; inherits: true; initial-value: 0; }

.hero {
  --wm: clamp(64px, 16.4vw, 212px);   /* cap 10% under the canvas's 236px (Kate, 2026-10-26) */
  --hh: calc(var(--wm) * 1.72 + 170px);
  position: relative; z-index: 5;
  height: var(--hh);
  background: var(--paper);
}
.hero .wrap { position: relative; height: 100%; }
.hero-wm {
  position: absolute; left: var(--gutter); bottom: calc(16px - 5px * var(--dock));
  margin: 0;
  font-family: var(--display); font-weight: 600;
  font-size: calc(var(--wm) + (30px - var(--wm)) * var(--dock));
  line-height: 0.86; letter-spacing: 0.01em; text-transform: uppercase;
  color: var(--olive);
}
/* The rule under the hero starts at the column edge and widens to full
   width as it becomes the bar's bottom line. */
.hero-rule {
  --edge: max(var(--gutter), (100% - var(--column)) / 2);
  position: absolute; bottom: -1px; height: 1px; background: var(--ink);
  left: calc(var(--edge) * (1 - var(--dock)));
  right: calc(var(--edge) * (1 - var(--dock)));
}

/* Load-in: letter i rises over 1s starting at its own offset. Offsets are
   fractions of the 2s driver. Only the name moves; the intro text is there
   from the start (Kate, 2026-10-26). */
.home { animation: intro 2s linear both; }
@keyframes intro { from { --intro: 0; } to { --intro: 1; } }
.wm-l {
  --d: 0;
  --p: clamp(0, var(--intro) * 2 - var(--d), 1);
  --e: calc(1 - (1 - var(--p)) * (1 - var(--p)) * (1 - var(--p)));
  display: inline-block;
  opacity: var(--p);
  transform: translateY(calc(45% * (1 - var(--e))));
}
.wm-line > .wm-l:nth-child(1) { margin-left: -0.076em; }
.wm-line + br + .wm-line > .wm-l:nth-child(1) { margin-left: -0.036em; }
.wm-line > .wm-l:nth-child(2) { --d: 0.06; }
.wm-line > .wm-l:nth-child(3) { --d: 0.12; }
.wm-line > .wm-l:nth-child(4) { --d: 0.18; }
.wm-line + br + .wm-line > .wm-l:nth-child(1) { --d: 0.30; }
.wm-line + br + .wm-line > .wm-l:nth-child(2) { --d: 0.36; }
.wm-line + br + .wm-line > .wm-l:nth-child(3) { --d: 0.42; }
.wm-line + br + .wm-line > .wm-l:nth-child(4) { --d: 0.48; }
.wm-line + br + .wm-line > .wm-l:nth-child(5) { --d: 0.54; }

/* Scroll docking, where scroll-driven animation exists. Elsewhere, and
   under reduced motion, the header simply scrolls away. */
@supports (animation-timeline: scroll()) {
  @media (prefers-reduced-motion: no-preference) {
    .hero {
      position: sticky; top: calc(var(--bar) - var(--hh));
      animation: dock linear both;
      animation-timeline: scroll(root);
      animation-range: 0 calc(var(--hh) - var(--bar));
    }
    @keyframes dock { from { --dock: 0; } to { --dock: 1; } }
    .hero .topnav { position: fixed; right: max(var(--gutter), (100% - var(--column)) / 2); }
  }
}

/* Once docked, the name stays in the bar for the rest of the page view:
   header.js adds .docked and collapses the hero to the bar's height, so
   scrolling back to the top doesn't grow the name again (Kate, 2026-10-26). */
.docked .hero { --dock: 1; height: var(--bar); top: 0; animation: none; }

/* ---------- Home sections ---------- */

.intro { padding-block: 22px 96px; }
/* One line where it fits with room to spare (1360px and up at 30px). Below that, two lines:
   "AI Strategist | Researcher", then the company, with the type scaling
   down on phones so each line still fits (Kate, 2026-10-26). */
.role {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px 0;
  font-size: clamp(14px, 4.2vw, 30px); line-height: 1.2; letter-spacing: 0.12em; text-transform: uppercase;
}
.role-h { display: flex; align-items: center; font-weight: 700; }
.role-co { color: var(--olive); }
.dv { display: inline-block; width: 1px; height: 0.9em; margin: 0 22px; background: var(--ink); }
@media (max-width: 1359px) {
  .role { flex-direction: column; align-items: flex-start; }
  .role > .dv { display: none; }
}
@media (max-width: 600px) { .dv { margin: 0 14px; } }
.intro-body {
  margin-top: clamp(72px, 12vh, 140px);
  display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between; gap: 56px 72px;
}
@media (max-width: 600px) { .intro-body { margin-top: 40px; } }
.intro-text { flex: 999 1 460px; min-width: 0; }
.tagline { font-size: clamp(20px, 2.3vw, 32px); font-weight: 700; line-height: 1.3; }
.tagline s { color: var(--muted); }
/* Strike, then type (Kate, 2026-10-26). The finished line is the default;
   tagline.js adds .tl-wait to <html> before the first paint and .tl-play to
   the tagline when it's time. The line is drawn, not text-decoration, so it
   can animate; the type is monospace, so 13ch is exactly "common sense." */
.tl-strike { position: relative; text-decoration: none; }
.tl-strike::after {
  content: ""; position: absolute; left: -0.04em; right: -0.04em; top: 52%;
  height: 0.08em; background: currentColor; transform-origin: left center;
}
.tl-type { display: inline-block; vertical-align: bottom; white-space: nowrap; overflow: hidden; }
.tl-wait .tl-strike::after { transform: scaleX(0); }
.tl-wait .tl-type { width: 0; }
.tl-play .tl-strike::after { animation: tl-strike 0.55s cubic-bezier(0.4, 0, 0.2, 1) both; }
.tl-play .tl-type { animation: tl-type 1.1s steps(13, end) 0.8s both; }
@keyframes tl-strike { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@keyframes tl-type { from { width: 0; } to { width: 13ch; } }
.intro-copy { margin-top: 24px; max-width: 46ch; font-size: clamp(19px, 1.7vw, 24px); line-height: 1.6; }
.intro-copy p + p { margin-top: 1em; }
.intro-copy p:first-child { margin-bottom: 2.25em; }
.closer { line-height: 1.75; }
.closer strong {
  padding: 0.12em 0.35em; background: var(--olive); color: var(--paper);
  -webkit-box-decoration-break: clone; box-decoration-break: clone;
}
.intro-photo { flex: 0 1 420px; max-width: 100%; aspect-ratio: 2 / 3; overflow: hidden; background: var(--ink); }
.intro-photo picture { display: contents; }
/* Below 1058px the photo wraps under the text (460 + 72 + 420 = 952px of
   column, plus gutters). There the <picture> swaps in a wide crop centered
   on Kate, and it runs edge to edge with a capped height (Kate, 2026-10-26). */
@media (max-width: 1057px) {
  .intro-photo {
    flex: 1 1 calc(100% + 2 * var(--gutter)); max-width: none;
    margin-inline: calc(-1 * var(--gutter));
    aspect-ratio: 3 / 2; max-height: 70vh;
  }
  /* When the height cap trims the crop, take more from the audience than
     from above Kate's head. */
  .intro-photo img { object-position: center 30%; }
}

.sepia { width: 100%; height: 100%; object-fit: cover; filter: var(--sepia); }

.doors-band { background: var(--ink); }
.doors {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr)); gap: 32px;
  padding-block: 72px;
}
.door {
  display: flex; flex-direction: column; gap: 10px;
  min-height: 220px; padding: 28px 28px 32px;
  background: var(--paper); text-decoration: none;
  transition: box-shadow 0.18s ease;
}
.door:hover, .door:focus-visible { box-shadow: inset 0 0 0 8px var(--olive); color: var(--ink); outline: none; }
.door-kicker { font-size: 13px; letter-spacing: 0.16em; text-transform: uppercase; color: var(--olive); }
.door-title { font-family: var(--display); font-weight: 600; font-size: 34px; letter-spacing: 0.04em; text-transform: uppercase; line-height: 1; color: var(--olive); }
.door-body { margin-top: auto; }

.work { padding-block: 112px 96px; }
.work-cols { display: flex; flex-wrap: wrap; gap: 56px 80px; }
.work-col { flex: 1 1 520px; min-width: 0; }
.work-col--stack { display: flex; flex-direction: column; gap: 56px; }
.article-list a { display: block; padding: 10px 0; text-decoration: none; border-bottom: 1px dotted var(--hairline); }
/* On phones, Home lists only the three newest pieces; "Read my writing"
   leads to the rest (Kate, 2026-10-26). */
@media (max-width: 600px) { .article-list a:nth-child(n+4) { display: none; } }

.logo-grid {
  display: grid; grid-template-columns: repeat(2, minmax(0, max-content));
  gap: 4px clamp(20px, 4vw, 48px); justify-content: start;
  margin-top: 16px;
}
.logo-grid a { display: flex; align-items: center; justify-content: flex-start; height: 60px; text-decoration: none; }
.logo-grid img { width: auto; max-width: 100%; }
.uxmag { font-family: "Playfair Display", Georgia, serif; font-weight: 900; letter-spacing: -0.02em; white-space: nowrap; }
.logo-grid .uxmag { font-size: 22px; color: var(--ink); }
.logo-grid .lg-fc { height: 22px; }
.logo-grid .lg-en { height: 19px; }
.logo-grid .lg-mp { height: 28px; }

/* Dotted-leader rows: talks, events, interviews. */
.leader { display: flex; align-items: baseline; gap: 10px; padding: 10px 0; text-decoration: none; }
.leaders--loose .leader { padding-block: 12px; }
.leader .dots { flex: 1 1 24px; border-bottom: 2px dotted var(--hairline); }
.leader .note { color: var(--muted); }
.leader .outlet { font-family: var(--serif); font-style: italic; font-size: 20px; color: var(--olive); white-space: nowrap; }

/* Olive bands: Home's pull quote, and the forms on the subpages. */
.dk { background: var(--olive); color: var(--paper); }
.dk--charcoal { background: var(--ink); }
.dk a:not(.btn) { color: var(--paper); text-decoration-color: var(--sage); }
.dk a:not(.btn):hover { color: var(--sage); text-decoration-color: var(--sage); }

/* Let's Talk (Home). */
.contact {
  padding-block: 120px;
  display: flex; flex-wrap: wrap; align-items: flex-start; gap: 56px 96px;
}
.contact-photo { flex: 0 0 auto; width: 300px; max-width: 100%; aspect-ratio: 1; background: var(--ink); }
.contact-main { flex: 999 1 420px; min-width: 0; }
.contact-main > p { margin-bottom: 32px; font-size: 20px; }

/* ---------- Subpage intro ---------- */

.page-intro { padding-block: 96px 72px; }
.page-intro--loose { padding-bottom: 88px; }

/* ---------- Speaking ---------- */

.featured { padding-block: 40px 96px; display: flex; flex-wrap: wrap; gap: 56px 80px; align-items: flex-start; }
.featured-text { flex: 1 1 420px; min-width: 0; }
.featured-text p + p { margin-top: 16px; }
.featured-text .eyebrow { margin-bottom: 12px; }
.video {
  position: relative; overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  aspect-ratio: 16 / 9; background: var(--ink); color: var(--paper);
}
.featured .video { flex: 1 1 520px; min-width: 0; }
.video img { position: absolute; inset: 0; }
.video svg { position: relative; }
.video iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.play-bg { fill: rgba(42, 42, 31, 0.55); }
/* Speaking's featured talk: a short self-hosted clip, full color, with the
   conference's full video linked below it (Kate, 2026-10-26). */
.clip { flex: 1 1 520px; min-width: 0; margin: 0; }
.clip video { display: block; width: 100%; height: auto; aspect-ratio: 16 / 9; background: var(--ink); }
.clip figcaption { margin-top: 12px; font-size: 15px; line-height: 1.6; color: var(--muted); }

.topics-sec { padding-bottom: 112px; }
.aside { font-family: var(--serif); font-style: italic; font-weight: 500; font-size: 21px; line-height: 1.35; color: var(--muted); }
.topics {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 240px), 1fr)); gap: 24px;
  margin: 16px 0 0; padding: 0; list-style: none; counter-reset: topic;
}
.topics li {
  counter-increment: topic;
  display: flex; flex-direction: column; gap: 14px;
  min-height: 150px; padding: 22px 24px 26px;
  background: var(--paper-dark);
  font-size: 19px; font-weight: 700; line-height: 1.35;
}
.topics li::before {
  content: counter(topic, decimal-leading-zero);
  padding-bottom: 10px; border-bottom: 1px solid var(--olive);
  font-size: 13px; letter-spacing: 0.14em; color: var(--olive);
}
.stage-band { height: clamp(260px, 40vw, 600px); overflow: hidden; background: var(--ink); }
.stage-band img { object-position: center 38%; }
.events { padding-block: 112px; }
.events > * { max-width: 960px; }   /* about a quarter narrower than the column (Kate, 2026-10-26) */

/* Olive bands with a form (Speaking, Interviews, Résumé) or a button (Writing). */
.band-in {
  padding-block: 112px;
  display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: 40px 72px;
}
.band-head { flex: 999 1 480px; min-width: 0; }
.band-in > .f { flex: 1 1 480px; min-width: 0; }
.band-in--button { gap: 32px 72px; }
.band-in--button > p { flex: 1 1 260px; }
.btn {
  display: inline-block; padding: 14px 26px;
  background: var(--paper); color: var(--ink); text-decoration: none; font-weight: 700;
}
.btn:hover { background: var(--sage); color: var(--ink); }

/* ---------- Interviews ---------- */

.logos-band .wrap { padding-block: 40px 46px; }   /* 20% shorter band (Kate, 2026-10-26) */
.logo-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 40px 48px; align-items: center; }
.logo-row a { display: flex; align-items: center; justify-content: center; min-height: 56px; text-decoration: none; }
.logo-row img { width: auto; max-width: 90%; }
.dk .logo-row .uxmag { font-size: 26px; color: var(--paper); }
.logo-row .lg-fc { height: 26px; }
.logo-row .lg-en { height: 22px; }
.logo-row .lg-mp { height: 32px; }

.press { padding-block: 112px 96px; display: flex; flex-wrap: wrap; gap: 64px 80px; align-items: flex-start; }
.press-list { flex: 999 1 560px; min-width: 0; }
.press-intro { flex: 1 1 400px; min-width: 0; }
.press-intro h2 { margin: 0 0 14px; font-family: var(--display); font-weight: 600; font-size: 28px; letter-spacing: 0.06em; text-transform: uppercase; }
.press-intro p { margin-bottom: 24px; }

/* The pull quote: one component, on paper (Interviews) or in an olive band
   (Home). Interviews' quote is the template (Kate, 2026-10-26). */
.quote-sec { padding-bottom: 112px; }
.quote-sec--band { padding-block: 120px; }
.dk .quote-sec figcaption { border-left-color: var(--sage); }
.quote-sec figure { margin: 0; display: flex; flex-wrap: wrap; align-items: flex-end; gap: 28px 72px; }
.quote-sec blockquote { flex: 999 1 560px; min-width: 0; margin: 0; }
.quote-sec blockquote p { font-family: var(--serif); font-weight: 500; font-size: clamp(30px, 3.6vw, 52px); line-height: 1.2; }
.quote-sec blockquote strong { font-weight: 700; }
.quote-sec figcaption { flex: 1 1 220px; max-width: 300px; padding: 4px 0 6px 20px; border-left: 1px solid var(--olive); font-size: 15px; line-height: 1.6; }
.quote-sec figcaption strong { font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; }

/* ---------- Writing ---------- */

.articles { padding-bottom: 112px; }
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 340px), 1fr)); gap: 24px; }
.card { display: flex; flex-direction: column; gap: 14px; padding: 26px 28px 30px; background: var(--paper-dark); }
.meta {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 12px;
  padding-bottom: 12px; border-bottom: 1px solid var(--olive);
  font-size: 13px; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase; color: var(--olive);
}
.meta .with { font-weight: 400; letter-spacing: 0.04em; text-transform: none; color: var(--muted); }
.card h2 { margin: 0; font-size: 22px; line-height: 1.3; font-weight: 700; }
.card h2 a { text-decoration: underline; text-decoration-color: var(--olive); text-decoration-thickness: 1px; text-underline-offset: 4px; }
.card h2 a:hover { color: var(--olive); text-decoration-thickness: 2px; }
.kind { margin-top: auto; padding-top: 6px; font-size: 12px; font-weight: 700; letter-spacing: 0.16em; text-transform: uppercase; color: var(--muted); }
.q { font-family: var(--serif); font-style: italic; font-weight: 500; font-size: 23px; line-height: 1.3; }
.tk { font-size: 16px; line-height: 1.6; }

/* ---------- Résumé ---------- */

.cv { padding-top: 24px; }
.cv-in { max-width: 1180px; margin-inline: auto; }   /* inset inside the shared column */
.cv-sec { padding-bottom: 40px; }
.cv-sec--last { padding-bottom: 112px; }
.row { display: flex; flex-wrap: wrap; }
.m {
  flex: 1 1 220px; max-width: 300px;
  padding: 14px 28px 14px 0; text-align: right;
  font-family: var(--serif); font-style: italic; font-size: 20px; line-height: 1.35; color: var(--olive);
}
.t { flex: 999 1 420px; min-width: 0; padding: 14px 0 14px 32px; border-left: 1px solid var(--olive); }
.t--first { padding-top: 40px; }
.m--first { padding-top: 40px; }   /* keeps each section's first date level with its entry */
.t--last { padding-bottom: 48px; }
.lbl {
  display: block; margin: 0 0 6px;
  font-family: var(--mono); font-style: normal; font-size: 13px; font-weight: 700;
  letter-spacing: 0.16em; text-transform: uppercase; color: var(--muted);
}
/* Section labels sit just above where each section's line begins, a size
   up from the other labels (Kate, 2026-10-26). The empty .m keeps them in
   line with the rule. */
.cv-head .lbl { flex: 999 1 420px; margin: 0; padding-bottom: 10px; font-size: 16px; }
.t .sub { color: var(--muted); }
@media (max-width: 700px) {
  /* The line belongs to the whole row here, not the date: the date slides
     in on scroll, and the line must not slide with it. */
  .cv .row:not(.cv-head):not(summary) { border-left: 1px solid var(--olive); }
  .m { max-width: none; text-align: left; padding: 18px 0 0 16px; }
  .t { padding-left: 16px; border-left: 0; }
  .t--first { padding-top: 14px; }
  .m--first { padding-top: 18px; }
  .cv-head .m { display: none; }   /* the empty spacer would draw a stray rule */
}
.more > summary { list-style: none; cursor: pointer; view-timeline: --toggle; }
.more > summary::-webkit-details-marker { display: none; }
.more > summary:focus-visible { outline: none; }
.more > summary .t {
  position: relative; border-left: 0; padding: 22px 0 48px 33px;
  font-size: 14px; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase; color: var(--olive);
}
/* The dotted rule is its own layer so it can draw itself in on scroll. Each
   dot is a whole circle centered on the 1px line (the strip runs 2px either
   side of it), spaced so none is cut off, and the dots fade out toward the
   bottom while the earlier roles are hidden (Kate, 2026-10-26). */
.more > summary .t::before {
  content: ""; position: absolute; left: -2px; top: 0; bottom: 0; width: 5px;
  background: radial-gradient(circle at 50% 50%, var(--olive) 0 1.6px, transparent 2.1px) center top / 5px 11px;
  background-repeat: no-repeat space;
  -webkit-mask-image: linear-gradient(#000 15%, rgba(0, 0, 0, 0.06));
  mask-image: linear-gradient(#000 15%, rgba(0, 0, 0, 0.06));
}
.more[open] > summary .t::before { -webkit-mask-image: none; mask-image: none; }
@media (max-width: 700px) {
  .more > summary .m { display: none; }   /* the empty spacer would draw a stray rule */
  .more > summary .t { padding-left: 17px; }
}
.more > summary:hover .t { text-decoration: underline; text-underline-offset: 4px; }
.more > summary:focus-visible .t { outline: 2px solid var(--olive); outline-offset: 4px; }
.more[open] > summary .t { padding-bottom: 14px; }
.more .when-open { display: none; }
.more[open] .when-open { display: inline; }
.more[open] .when-closed { display: none; }

/* ---------- Scroll-in notes and cards ---------- */

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .card { animation: card-in linear both; animation-timeline: view(); animation-range: entry 5% cover 25%; }
    .m { animation: note-in linear both; animation-timeline: view(); animation-range: entry 10% cover 30%; }
    /* Résumé toggle: the dotted rule draws down, then the words settle in
       from wide tracking (Kate, 2026-10-26). */
    .more > summary .t::before { animation: dots-in linear both; animation-timeline: --toggle; animation-range: entry 10% cover 35%; }
    .more > summary .t > span { animation: track-in linear both; animation-timeline: --toggle; animation-range: entry 25% cover 45%; }
  }
}
@keyframes card-in { from { opacity: 0; transform: translateY(18px); } to { opacity: 1; transform: none; } }
@keyframes note-in { from { opacity: 0; transform: translateX(-18px); } to { opacity: 1; transform: none; } }
@keyframes dots-in { from { clip-path: inset(0 0 100% 0); } to { clip-path: inset(0); } }
@keyframes track-in { from { opacity: 0; letter-spacing: 0.34em; } to { opacity: 1; letter-spacing: 0.12em; } }

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

.f { display: grid; gap: 22px; max-width: 640px; }
.lab { display: block; margin-bottom: 8px; font-size: 13px; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase; }
.f input[type="text"], .f input[type="email"], .f textarea {
  display: block; width: 100%;
  border: 0; border-bottom: 1px solid currentColor; border-radius: 0;
  background: transparent; color: inherit; font: inherit; padding: 8px 0;
}
.f textarea { border: 1px solid currentColor; padding: 10px 12px; min-height: 140px; resize: vertical; }
.f input:focus, .f textarea:focus { outline: 2px solid var(--olive); outline-offset: 2px; }
.dk .f input:focus, .dk .f textarea:focus { outline-color: var(--sage); }
.send {
  justify-self: start; padding: 14px 30px; border: 0;
  background: var(--olive); color: var(--paper); font: inherit; font-weight: 700; cursor: pointer;
}
.dk .send { background: var(--paper); color: var(--ink); }
.send[disabled] { cursor: progress; opacity: 0.7; }
.ts:empty { display: none; }
.ts { min-height: 65px; }
.f-status[hidden] { display: none; }

/* ---------- Footer: one component ---------- */

/* The top rule shows only when the footer follows a paper section; after
   an olive band it is left off. */
.foot { border-top: 1px solid var(--ink); }
main:has(> .dk:last-child) + .foot { border-top: 0; }
.foot .wrap { padding-block: 28px 40px; display: flex; flex-wrap: wrap; align-items: center; gap: 16px 28px; }
.foot-name { font-family: var(--display); font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase; }
.foot-links { display: flex; gap: 18px; font-size: 15px; }
.foot-copy { margin-left: auto; font-size: 14px; color: var(--muted); }

/* ---------- 404 ---------- */

.lost { padding-block: 96px 120px; }
.lost h1, .lost p { margin: 0; font-size: clamp(19px, 1.7vw, 24px); line-height: 1.6; }
.lost p { margin-top: 16px; }

/* ---------- Reduced motion: nothing moves ---------- */

@media (prefers-reduced-motion: reduce) {
  .home { animation: none; }
  .door { transition: none; }
  .card, .m { animation: none; }
}
