/* ===========================================================================
   Lisa Reeves — portfolio.  Generated once from the sixteen inline <style>
   blocks that used to live in each page, then re-skinned. Edit this file
   directly from now on; it is the only stylesheet the site has.

   Layered in three parts:
     1. Tokens — the design language, shared with the log at log.lilypixel.com.
        Legacy names (--black, --mid, --serif ...) are kept as aliases so the
        inherited rules below pick up the new palette automatically.
     2. Inherited rules — carried over from the old pages so nothing breaks.
     3. Design system — authored to match the log. Comes last, so it wins.
   =========================================================================== */

:root {
  /* Type. One family, matching Lisa_Reeves_Case_Studies.pdf and the CV: Inter
     throughout, no serif. The display voice comes from weight and tracking
     (800, tight) rather than a second typeface — which is exactly how the CV
     gets its identity. --font-display is kept as a name so every existing
     rule keeps working; it simply resolves to Inter now. */
  --sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --font-display: var(--sans);
  --display-weight: 700;
  --display-track: -0.028em;

  /* Colour, matched to the log. oklch keeps the greys genuinely neutral
     rather than drifting warm or cold as they lighten. */
  --paper: oklch(0.99 0.003 90);
  --white: #ffffff;
  --ink: oklch(0.22 0.01 260);
  --ink-soft: oklch(0.48 0.01 260);
  --ink-faint: oklch(0.62 0.008 260);
  --rule: oklch(0.9 0.005 260);
  /* Primary accent stays magenta — deliberately NOT the indigo/violet of the
     default AI palette. Flat only: never a gradient. That is the actual tell. */
  --accent: oklch(0.55 0.16 320);
  --accent-wash: oklch(0.96 0.02 320);
  --accent-lift: oklch(0.72 0.15 320); /* legible on the forest ground */
  --accent-soft: transparent; /* bullets read as hollow rings, not filled dots */

  /* Secondary, lifted straight from the CV and case-study PDF. */
  --forest: #1f4d3d;
  --forest-deep: #16382c; /* dark ground for How I lead */
  --forest-soft: oklch(0.55 0.06 158);
  --ember: #b5541f; /* CV's emphasis orange, for numerals */

  /* These are rem, and the root is 18px (see the `html` rule below), so
     1rem = 18px. Sized to land near the original 760px / 900px measures. */
  --reading: 51rem; /* 918px — content width ~824px, clears the 800px R&R table */
  --wide: 62rem; /* 1116px — index, CV, listings */
  --gutter: 2.6rem; /* ~47px */

  /* Aliases so inherited rules below adopt the palette above. */
  --black: var(--ink);
  --charcoal: var(--ink);
  --mid: var(--ink-soft);
  --subtle: var(--ink-faint);
  --border: var(--rule);
  --bg: var(--paper);
  --tag-bg: var(--accent-wash);
  --tag-text: var(--accent);
  --serif: var(--font-display);
}

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

/* 18px root, as the site was originally designed. Every rem on the page is
   relative to this, so dropping it to the 16px default shrinks the entire site
   by an eighth and makes everything feel cramped. */
html {
  font-size: 18px;
  scroll-behavior: smooth;
  background: var(--paper);
  -webkit-text-size-adjust: 100%;
}

body {
  font-family: var(--sans);
  background: var(--paper);
  color: var(--ink);
  line-height: 1.7;
  -webkit-font-smoothing: antialiased;
  text-wrap: pretty;
}

/* The login page centres its card in the viewport. This used to live in a
   page-specific `body` rule; now every page shares one stylesheet, it has to
   be scoped to the login page by class. */
body.login-page {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* ---------------------------------------------------------------------------
   2. Inherited rules
   ------------------------------------------------------------------------- */

nav  {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 100;
  background: var(--paper);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--border);
  padding: 0 40px;
  height: 64px;
  display: flex;
  align-items: center;
  justify-content: space-between;
 
}

.nav-name  {
  font-family: var(--serif);
  font-size: 1.1rem;
  color: var(--black);
  text-decoration: none;
 
}

.nav-links  {
  display: flex;
  gap: 32px;
  align-items: center;
 
}

.nav-links a  {
  font-size: 0.83rem;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--mid);
  text-decoration: none;
  transition: color 0.2s;
 
}

.nav-links a:hover, .nav-links a.active  {
  color: var(--accent);
 
}

.nav-links .nav-cta  {
  border: 1px solid var(--accent);
  padding: 8px 20px;
  border-radius: 2px;
  color: var(--accent);
  font-size: 0.78rem;
 
}

.nav-links .nav-cta:hover  {
  background: var(--accent);
  color: var(--white);
 
}

.article-header  {
  padding: 120px 40px 48px;
  max-width: var(--reading);
  margin: 0 auto;
 
}

.article-back  {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 0.78rem;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--subtle);
  text-decoration: none;
  margin-bottom: 40px;
  transition: color 0.2s;
 
}

.article-back:hover  {
  color: var(--accent);
 
}

.article-header .article-meta  {
  display: flex;
  gap: 16px;
  align-items: center;
  margin-bottom: 20px;
  flex-wrap: wrap;
 
}

.article-header .article-date  {
  font-size: 0.75rem;
  color: var(--subtle);
  font-weight: 500;
  letter-spacing: 0.04em;
 
}

.article-header .article-read  {
  font-size: 0.75rem;
  color: var(--subtle);
 
}

.article-header .article-topic  {
  font-size: 0.62rem;
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  background: var(--tag-bg);
  color: var(--tag-text);
  padding: 3px 10px;
  border-radius: 2px;
 
}

.article-header h1  {
  font-family: var(--serif);
  font-size: clamp(1.8rem, 4vw, 2.6rem);
  line-height: 1.2;
  color: var(--black);
  letter-spacing: -0.02em;
  margin-bottom: 16px;
 
}

.article-header .article-lede  {
  font-size: 1.05rem;
  color: var(--mid);
  line-height: 1.7;
 
}

.article-body  {
  max-width: var(--reading);
  margin: 0 auto;
  padding: 40px 40px 80px;
 
}

.article-body h2  {
  font-family: var(--serif);
  font-size: 1.45rem;
  color: var(--black);
  margin: 48px 0 16px;
  letter-spacing: -0.01em;
  line-height: 1.25;
 
}

.article-body h3  {
  font-family: var(--serif);
  font-size: 1.15rem;
  color: var(--black);
  margin: 36px 0 12px;
  line-height: 1.3;
 
}

.article-body p  {
  font-size: 0.94rem;
  color: var(--charcoal);
  line-height: 1.9;
  margin-bottom: 20px;
 
}

.article-body p a  {
  color: var(--accent);
  text-decoration: underline;
  text-underline-offset: 3px;
 
}

.article-body p a:hover  {
  color: var(--accent-deep);
 
}

.article-body ul, .article-body ol  {
  margin: 16px 0 24px 20px;
 
}

.article-body li  {
  font-size: 0.92rem;
  color: var(--charcoal);
  line-height: 1.85;
  margin-bottom: 8px;
 
}

.article-body blockquote  {
  border-left: 3px solid var(--accent);
  background: var(--accent-soft);
  padding: 24px 28px;
  margin: 32px 0;
  border-radius: 0 4px 4px 0;
 
}

.article-body blockquote p  {
  font-family: var(--serif);
  font-size: 1.05rem;
  color: var(--accent-deep);
  line-height: 1.7;
  margin-bottom: 0;
  font-style: italic;
 
}

.article-body img  {
  width: 100%;
  border-radius: 4px;
  margin: 32px 0;
 
}

.article-body figcaption  {
  font-size: 0.78rem;
  color: var(--subtle);
  text-align: center;
  margin-top: -24px;
  margin-bottom: 32px;
 
}

.article-divider  {
  border: none;
  border-top: 1px solid var(--border);
  margin: 48px 0;
 
}

.article-author  {
  max-width: var(--reading);
  margin: 0 auto;
  padding: 0 40px 56px;
  display: flex;
  gap: 20px;
  align-items: start;
  border-top: 1px solid var(--border);
  padding-top: 40px;
 
}

.article-author-text h3  {
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--black);
  margin-bottom: 4px;
 
}

.article-author-text p  {
  font-size: 0.82rem;
  color: var(--mid);
  line-height: 1.6;
 
}

.article-author-text a  {
  color: var(--accent);
  text-decoration: none;
  font-weight: 500;
  font-size: 0.82rem;
 
}

.article-nav  {
  max-width: var(--reading);
  margin: 0 auto;
  padding: 0 40px 40px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  border-top: 1px solid var(--border);
  padding-top: 24px;
 
}

.article-nav a  {
  font-size: 0.83rem;
  font-weight: 500;
  color: var(--mid);
  text-decoration: none;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  transition: color 0.2s;
 
}

.article-nav a:hover  {
  color: var(--accent);
 
}

footer  {
  max-width: var(--reading);
  margin: 0 auto;
  padding: 40px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  border-top: 1px solid var(--border);
 
}

.footer-name  {
  font-family: var(--serif);
  font-size: 1rem;
  color: var(--black);
 
}

.footer-links  {
  display: flex;
  gap: 24px;
 
}

.footer-links a  {
  font-size: 0.8rem;
  color: var(--subtle);
  text-decoration: none;
  font-weight: 500;
  transition: color 0.2s;
 
}

.footer-links a:hover  {
  color: var(--accent);
 
}

@media (max-width: 768px)  {
  nav  {
  padding: 0 20px;
 
} .article-header  {
  padding: 100px 20px 36px;
 
} .article-body  {
  padding: 32px 20px 60px;
 
} .article-author  {
  padding: 32px 20px 40px;
  flex-direction: column;
 
} .article-nav  {
  padding: 20px 20px 32px;
  flex-direction: column;
  gap: 12px;
 
} footer  {
  padding: 24px 20px;
  flex-direction: column;
  gap: 12px;
  text-align: center;
 
}
}

.nav-links a:hover  {
  color: var(--accent);
 
}

.cs-header  {
  padding: 120px 40px 45px;
  max-width: var(--wide);
  margin: 0 auto;
 
}

.cs-back  {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 0.78rem;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--subtle);
  text-decoration: none;
  margin-bottom: 40px;
  transition: color 0.2s;
 
}

.cs-back:hover  {
  color: var(--accent);
 
}

.cs-eyebrow  {
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--subtle);
  margin-bottom: 16px;
 
}

.cs-header h1  {
  font-family: var(--serif);
  font-size: clamp(1.9rem, 4vw, 2.8rem);
  line-height: 1.2;
  color: var(--black);
  letter-spacing: -0.02em;
  margin-bottom: 16px;
 
}

.cs-header .cs-subtitle  {
  font-size: 1rem;
  color: var(--mid);
  line-height: 1.6;
  margin-bottom: 32px;
 
}

.cs-meta-row  {
  display: flex;
  gap: 32px;
  flex-wrap: wrap;
  padding-top: 24px;
  border-top: 1px solid var(--border);
 
}

.cs-meta-item label  {
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--subtle);
  display: block;
  margin-bottom: 4px;
 
}

.cs-meta-item span  {
  font-size: 0.85rem;
  color: var(--charcoal);
  font-weight: 500;
 
}

.cs-tags  {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
 
}


.metrics-bar  {
  background: var(--white); /* was a gradient; flat only */
  padding: 48px 40px 56px;
  position: relative;
 
}

.metrics-inner  {
  max-width: var(--wide);
  margin: 0 auto;
  display: flex;
  gap: 48px;
  flex-wrap: wrap;
 
}

.metric .m-num  {
  font-family: var(--serif);
  font-size: 2rem;
  color: var(--accent);
  display: block;
  line-height: 1;
  margin-bottom: 4px;
 
}

.metric .m-label  {
  font-size: 0.75rem;
  color: var(--accent);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  font-weight: 500;
 
}

.scroll-hint  {
  text-align: center;
  padding: 16px 0 8px;
 
}

.scroll-hint svg  {
  opacity: 0.4;
  animation: bobDown 2s ease-in-out infinite;
 
}

@keyframes bobDown  {
  0%, 100%  {
  transform: translateY(0);
 
} 50%  {
  transform: translateY(6px);
 
}
}

.cs-body  {
  max-width: var(--wide);
  margin: 0 auto;
  padding: 64px 40px 80px;
 
}

.cs-section  {
  margin-bottom: 56px;
 
}

.cs-section-label  {
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--subtle);
  margin-bottom: 20px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--border);
 
}

.cs-section h2  {
  font-family: var(--serif);
  font-size: 1.5rem;
  color: var(--black);
  margin-bottom: 16px;
 
}

.cs-section p  {
  font-size: 0.94rem;
  color: var(--charcoal);
  line-height: 1.85;
  margin-bottom: 14px;
 
}

.cs-section p:last-child  {
  margin-bottom: 0;
 
}

.cs-section ul  {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 8px;
 
}

.cs-section ul li  {
  font-size: 0.9rem;
  color: var(--charcoal);
  line-height: 1.7;
  padding-left: 18px;
  position: relative;
 
}

.cs-section ul li::before  {
  content: "—";
  position: absolute;
  left: 0;
  color: var(--subtle);
 
}

.cs-image  {
  width: 100%;
  border-radius: 4px;
  margin: 28px 0;
  border: 1px solid var(--border);
 
}

.cs-image-caption  {
  font-size: 0.75rem;
  color: var(--ink-faint) !important;
  text-align: center;
  margin-top: -20px;
  margin-bottom: 28px;
  font-weight: 500;
  letter-spacing: 0.02em;
 
}

.cs-image-grid  {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
  margin: 28px 0;
 
}

.cs-image-grid img  {
  width: 100%;
  border-radius: 4px;
  border: 1px solid var(--border);
  object-fit: cover;
 
}

.cs-image-clickable  {
  /* The zoom-in cursor and the hover fade both promised a lightbox. There is
     no lightbox JavaScript on any page, so the images never expanded. The
     affordance is removed rather than the feature built: offering an action
     that does nothing is worse than not offering it. */
 
}

.lightbox-overlay  {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 300;
  background: rgba(13,13,13,0.85);
  backdrop-filter: blur(6px);
  opacity: 0;
  transition: opacity 0.25s;
  cursor: zoom-out;
  justify-content: center;
  align-items: center;
  padding: 40px;
 
}

.lightbox-overlay.active  {
  display: flex;
 
}

.lightbox-overlay.visible  {
  opacity: 1;
 
}

.lightbox-overlay img  {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  border-radius: 6px;
  box-shadow: 0 24px 80px rgba(0,0,0,0.4);
  transform: scale(0.95);
  transition: transform 0.3s ease;
 
}

.lightbox-overlay.visible img  {
  transform: scale(1);
 
}

.lightbox-close  {
  position: absolute;
  top: 20px;
  right: 24px;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: 1px solid rgba(255,255,255,0.3);
  background: rgba(255,255,255,0.1);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.2rem;
  color: var(--white);
  transition: all 0.15s;
  line-height: 1;
 
}

.lightbox-close:hover  {
  background: rgba(255,255,255,0.2);
 
}

@media (max-width: 768px)  {
  .cs-image-grid  {
  grid-template-columns: 1fr;
 
} .lightbox-overlay  {
  padding: 20px;
 
}
}

.impact-box  {
  background: var(--tag-bg);
  border-left: 3px solid var(--accent);
  padding: 28px 32px;
  border-radius: 0 4px 4px 0;
  margin-top: 20px;
 
}

.impact-box h3  {
  font-family: var(--serif);
  font-size: 1.1rem;
  color: var(--black);
  margin-bottom: 12px;
 
}

.impact-list  {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 10px;
 
}

.impact-list li  {
  font-size: 0.88rem;
  color: var(--charcoal);
  line-height: 1.6;
  padding-left: 20px;
  position: relative;
  font-weight: 500;
 
}

.impact-list li::before  {
  content: "✓";
  position: absolute;
  left: 0;
  color: var(--accent);
  font-size: 0.75rem;
 
}

.testimonial  {
  border-top: 1px solid var(--border);
  padding-top: 40px;
  margin-top: 56px;
 
}

.testimonial blockquote  {
  font-family: var(--serif);
  font-size: 1.15rem;
  line-height: 1.65;
  color: var(--ink);
  font-style: italic;
  margin-bottom: 20px;
 
}

.testimonial cite  {
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--subtle);
  font-style: normal;
 
}

.cs-next  {
  border-top: 1px solid var(--border);
 
}

.cs-next-inner  {
  max-width: var(--wide);
  margin: 0 auto;
  padding: 40px;
  display: flex;
  justify-content: space-between;
  align-items: center;
 
}

.cs-next a  {
  font-size: 0.83rem;
  font-weight: 500;
  color: var(--mid);
  text-decoration: none;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  transition: color 0.2s;
 
}

.cs-next a:hover  {
  color: var(--accent);
 
}

footer  {
  max-width: var(--wide);
  margin: 0 auto;
  padding: 40px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  border-top: 1px solid var(--border);
 
}

@media (max-width: 768px)  {
  nav  {
  padding: 0 20px;
 
} .cs-header  {
  padding: 100px 20px 40px;
 
} .cs-body  {
  padding: 40px 20px 60px;
 
} .metrics-bar  {
  padding: 36px 20px 44px;
 
} .metrics-inner  {
  gap: 24px;
 
} .cs-next-inner  {
  padding: 24px 20px;
  flex-direction: column;
  gap: 12px;
 
} footer  {
  padding: 24px 20px;
  flex-direction: column;
  gap: 12px;
  text-align: center;
 
}
}

.cs-image-grid img  {
  width: 100%;
  border-radius: 4px;
  border: 1px solid var(--border);
 
}

@media (max-width: 768px)  {
  .cs-image-grid  {
  grid-template-columns: 1fr;
 
}
}

.impact-list li::before  {
  content: "\2713";
  position: absolute;
  left: 0;
  color: var(--accent);
  font-size: 0.75rem;
 
}

.comb-grid  {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
  margin-top: 20px;
  margin-bottom: 14px;
 
}

.comb-card  {
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 20px 24px;
 
}

.comb-card h4  {
  font-family: var(--serif);
  font-size: 1rem;
  color: var(--black);
  margin-bottom: 8px;
  letter-spacing: -0.01em;
 
}

.comb-card p  {
  font-size: 0.85rem;
  color: var(--mid);
  line-height: 1.65;
  margin-bottom: 0;
 
}

@media (max-width: 768px)  {
  nav  {
  padding: 0 20px;
 
} .cs-header  {
  padding: 100px 20px 40px;
 
} .cs-body  {
  padding: 40px 20px 60px;
 
} .metrics-bar  {
  padding: 36px 20px 44px;
 
} .metrics-inner  {
  gap: 24px;
 
} .comb-grid  {
  grid-template-columns: 1fr;
 
} .cs-next-inner  {
  padding: 24px 20px;
  flex-direction: column;
  gap: 12px;
 
} footer  {
  padding: 24px 20px;
  flex-direction: column;
  gap: 12px;
  text-align: center;
 
}
}

.cs-image-caption  {
  font-size: 0.75rem;
  color: var(--ink-faint) !important;
  text-align: center;
  margin-top: 8px;
  margin-bottom: 28px;
  font-weight: 500;
  letter-spacing: 0.02em;
 
}

.zoomable-container  {
  position: relative;
  width: 100%;
  height: 420px;
  overflow: hidden;
  border-radius: 4px;
  border: 1px solid var(--border);
  margin: 28px 0 8px;
  cursor: grab;
  background: #f4f4f2;
 
}

.zoomable-container:active  {
  cursor: grabbing;
 
}

.zoomable-container img  {
  position: absolute;
  top: 0;
  left: 0;
  transform-origin: 0 0;
  will-change: transform;
  user-select: none;
  -webkit-user-drag: none;
 
}

.zoom-controls  {
  display: flex;
  gap: 8px;
  justify-content: center;
  margin-bottom: 4px;
 
}

.zoom-btn  {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  border: 1px solid var(--border);
  background: var(--white);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.1rem;
  color: var(--mid);
  transition: all 0.15s;
  line-height: 1;
 
}

.zoom-btn:hover  {
  border-color: var(--accent);
  color: var(--accent);
 
}

.zoom-hint  {
  font-size: 0.72rem;
  color: var(--subtle);
  text-align: center;
  margin-top: 4px;
  font-weight: 500;
  letter-spacing: 0.02em;
 
}

@media (max-width: 768px)  {
  .zoomable-container  {
  height: 280px;
 
}
}

.cs-image-grid  {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
  margin: 28px 0;
 
}

.cs-hero-device  {
  display: flex;
  justify-content: center;
  margin: 28px 0;
 
}

.cs-hero-device img  {
  max-width: 320px;
  width: 100%;
  border-radius: 4px;
 
}

@media (max-width: 768px)  {
  .cs-image-grid  {
  grid-template-columns: 1fr;
 
} .cs-hero-device img  {
  max-width: 260px;
 
}
}

.cs-image-grid-3  {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 12px;
  margin: 28px 0;
 
}

.cs-image-grid-3 img  {
  width: 100%;
  border-radius: 4px;
  border: 1px solid var(--border);
  object-fit: cover;
 
}

@media (max-width: 768px)  {
  .cs-image-grid  {
  grid-template-columns: 1fr;
 
} .cs-image-grid-3  {
  grid-template-columns: 1fr;
 
} .lightbox-overlay  {
  padding: 20px;
 
}
}

@media (max-width: 768px)  {
  .cs-image-grid  {
  grid-template-columns: 1fr;
 
} .zoomable-container  {
  height: 280px;
 
}
}

.cs-section h3  {
  font-family: var(--serif);
  font-size: 1.15rem;
  color: var(--black);
  margin-bottom: 10px;
  margin-top: 28px;
 
}

.reflection-box  {
  background: var(--white);
  border: 1px solid var(--border);
  padding: 28px 32px;
  border-radius: 4px;
  margin-top: 20px;
 
}

.reflection-box p  {
  font-size: 0.9rem;
  color: var(--charcoal);
  line-height: 1.85;
  font-style: italic;
 
}

.cs-image  {
  width: 100%;
  border-radius: 4px;
  margin: 24px 0 8px;
  display: block;
 
}

.cs-image-full  {
  /* Sits inside the reading measure rather than the wide grid, so it can't
     overhang the body copy. Capped well below the text width: a supporting
     image, not a hero. */
  max-width: 34rem;
  width: 100%;
  margin: 0 auto;
  padding: 0 var(--gutter);
  display: block;
  border-radius: 4px;
 
}

.cs-image-caption  {
  font-size: 0.72rem;
  color: var(--ink-faint) !important;
  letter-spacing: 0.04em;
  margin-top: 8px;
  margin-bottom: 24px;
  line-height: 1.5;
 
}

.cs-image-grid  {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
  margin: 24px 0 8px;
 
}

.cs-image-grid img  {
  width: 100%;
  border-radius: 4px;
  display: block;
 
}

.cv-header  {
  padding: 4rem var(--gutter) 1.5rem;
  max-width: var(--wide);
  margin: 0 auto;
 
}

.cv-header h1  {
  font-family: var(--serif);
  font-size: clamp(2rem, 4.5vw, 3rem);
  line-height: 1.15;
  color: var(--black);
  letter-spacing: -0.02em;
  margin-bottom: 8px;
 
}

.cv-header .cv-headline  {
  font-size: 1rem;
  color: var(--mid);
  font-weight: 400;
  margin-bottom: 24px;
 
}

.cv-contact  {
  display: flex;
  gap: 20px;
  flex-wrap: wrap;
  align-items: center;
  padding-top: 20px;
  border-top: 1px solid var(--border);
 
}

.cv-contact a, .cv-contact span  {
  font-size: 0.82rem;
  color: var(--mid);
  text-decoration: none;
  font-weight: 500;
  transition: color 0.2s;
 
}

.cv-contact a:hover  {
  color: var(--accent);
 
}

.cv-summary  {
  background: var(--accent-wash); /* was a gradient; flat only */
  padding: 48px 40px;
 
}

.cv-summary-inner  {
  max-width: var(--wide);
  margin: 0 auto;
 
}

.cv-summary p  {
  font-size: 0.94rem;
  color: var(--accent-deep);
  line-height: 1.85;
  margin-bottom: 14px;
 
}

.cv-summary p:last-child  {
  margin-bottom: 0;
 
}

.cv-body  {
  max-width: var(--wide);
  margin: 0 auto;
  padding: 16px 40px 80px;
 
}

.cv-section  {
  margin-bottom: 56px;
 
}

.cv-section-label  {
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 28px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--border);
 
}

/* Was a 3px vertical bar per item. Now the same hollow ring bullet used by the
   role lists further down the page, so the CV has one bullet language. */
.cv-highlight  {
  position: relative;
  padding-left: 20px;
  margin-bottom: 20px;
}

.cv-highlight::before {
  content: "";
  position: absolute;
  left: 0;
  top: 8px;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent-soft);
  border: 1.5px solid var(--accent);
}

.cv-highlight-bar  {
  display: none;
}

.cv-highlight-content h3  {
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--black);
  margin-bottom: 4px;
 
}

.cv-highlight-content p  {
  font-size: 0.88rem;
  color: var(--charcoal);
  line-height: 1.7;
 
}

.cv-role  {
  margin-bottom: 40px;
  padding-bottom: 40px;
  border-bottom: 1px solid var(--border);
 
}

.cv-role:last-child  {
  border-bottom: none;
  margin-bottom: 0;
  padding-bottom: 0;
 
}

.cv-role-header  {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 6px;
 
}

.cv-role-title  {
  font-family: var(--serif);
  font-size: 1.15rem;
  color: var(--black);
  letter-spacing: -0.01em;
 
}

.cv-role-dates  {
  font-size: 0.78rem;
  color: var(--subtle);
  font-weight: 500;
  letter-spacing: 0.04em;
  white-space: nowrap;
 
}

.cv-role-company  {
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--accent);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  margin-bottom: 12px;
 
}

.cv-role-intro  {
  font-size: 0.9rem;
  color: var(--charcoal);
  line-height: 1.8;
  margin-bottom: 14px;
 
}

.cv-role ul  {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 10px;
 
}

.cv-role ul li  {
  font-size: 0.88rem;
  color: var(--charcoal);
  line-height: 1.7;
  padding-left: 20px;
  position: relative;
 
}

.cv-role ul li::before  {
  content: "";
  position: absolute;
  left: 0;
  top: 10px;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent-soft);
  border: 1.5px solid var(--accent);
 
}

.cv-early  {
  margin-bottom: 40px;
 
}

.cv-early p  {
  font-size: 0.88rem;
  color: var(--charcoal);
  line-height: 1.8;
  margin-bottom: 12px;
 
}

.cv-early-list  {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 6px;
 
}

.cv-early-list li  {
  font-size: 0.82rem;
  color: var(--mid);
  line-height: 1.6;
  display: flex;
  justify-content: space-between;
  padding-bottom: 6px;
  border-bottom: 1px solid var(--border);
 
}

.cv-early-list li span  {
  white-space: nowrap;
  font-weight: 500;
 
}

.cv-edu-list  {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 12px;
 
}

.cv-edu-list li  {
  font-size: 0.9rem;
  color: var(--charcoal);
  line-height: 1.6;
  padding-left: 20px;
  position: relative;
 
}

.cv-edu-list li::before  {
  content: "";
  position: absolute;
  left: 0;
  top: 10px;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent-soft);
  border: 1.5px solid var(--accent);
 
}

.cv-edu-list li strong  {
  color: var(--black);
  font-weight: 600;
 
}

.cv-edu-list li em  {
  font-style: normal;
  color: var(--mid);
 
}

.cv-skills-grid  {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 24px;
 
}

.cv-skill-group h3  {
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent-deep);
  margin-bottom: 8px;
 
}

.cv-skill-group p  {
  font-size: 0.82rem;
  color: var(--mid);
  line-height: 1.7;
 
}

/* Skills & Tools is a two-column grid holding five groups, so the last one sat
   alone in the left column with a hole beside it. Sectors is not a skill or a
   tool anyway; it is a different kind of fact, and a comma list reads better
   across the full width than down a narrow column. Written as last-child plus
   odd so it keeps working if a group is ever added or removed. The existing
   mobile rule already collapses the grid to one column, where this is inert. */
.cv-skill-group:last-child:nth-child(odd) { grid-column: 1 / -1; }

.cv-cta  {
  background: var(--ink);
  padding: 56px 40px;
  text-align: center;
 
}

.cv-cta p  {
  font-family: var(--serif);
  font-size: 1.3rem;
  color: var(--white);
  margin-bottom: 20px;
  letter-spacing: -0.01em;
 
}

.cv-cta a  {
  display: inline-block;
  border: 1px solid rgba(255,255,255,0.4);
  padding: 12px 28px;
  border-radius: 2px;
  font-size: 0.83rem;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--white);
  text-decoration: none;
  transition: all 0.2s;
 
}

.cv-cta a:hover  {
  background: var(--white);
  color: var(--ink);
 
}

@media (max-width: 768px)  {
  nav  {
  padding: 0 20px;
 
} .cv-header  {
  padding: 100px 20px 40px;
 
} .cv-summary  {
  padding: 36px 20px;
 
} .cv-body  {
  padding: 40px 20px 60px;
 
} .cv-role-header  {
  flex-direction: column;
  gap: 2px;
 
} .cv-skills-grid  {
  grid-template-columns: 1fr;
 
} footer  {
  padding: 24px 20px;
  flex-direction: column;
  gap: 12px;
  text-align: center;
 
} .cv-contact  {
  gap: 12px;
 
}
}

.end-header  {
  padding: 4rem var(--gutter) 3rem;
  max-width: var(--wide);
  margin: 0 auto;
 
}

.end-header h1  {
  font-family: var(--serif);
  font-size: clamp(2rem, 4.5vw, 3rem);
  line-height: 1.15;
  color: var(--black);
  letter-spacing: -0.02em;
  margin-bottom: 16px;
 
}

.end-header p  {
  font-size: 1rem;
  color: var(--mid);
  line-height: 1.7;
  max-width: 580px;
 
}

.end-list  {
  max-width: var(--wide);
  margin: 0 auto;
  padding: 0 var(--gutter) 5rem;
 
}

.end-item  {
  padding: 40px 0;
  border-top: 1px solid var(--border);
 
}

.end-item:last-child  {
  padding-bottom: 0;
 
}

.end-quote  {
  font-family: var(--sans);
  font-size: 1.0625rem;
  line-height: 1.7;
  color: var(--ink);
  font-style: normal;
  margin-bottom: 20px;
  position: relative;
  padding-left: 24px;
  border-left: 3px solid var(--accent);
 
}

.end-attribution  {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 8px;
 
}

.end-person  {
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--black);
 
}

.end-role  {
  font-size: 0.78rem;
  color: var(--subtle);
  font-weight: 400;
 
}

.end-context  {
  font-size: 0.72rem;
  color: var(--accent);
  font-weight: 500;
  text-decoration: none;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  transition: opacity 0.15s;
 
}

.end-context:hover  {
  opacity: 0.7;
 
}

.end-cta  {
  background: var(--accent-wash); /* was a gradient; flat only */
  padding: 56px 40px;
  text-align: center;
 
}

.end-cta p  {
  font-family: var(--serif);
  font-size: 1.3rem;
  color: var(--accent-deep);
  margin-bottom: 20px;
  letter-spacing: -0.01em;
 
}

.end-cta a  {
  display: inline-block;
  border: 1px solid var(--accent);
  padding: 12px 28px;
  border-radius: 2px;
  font-size: 0.83rem;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--accent);
  text-decoration: none;
  transition: all 0.2s;
 
}

.end-cta a:hover  {
  background: var(--accent);
  color: var(--white);
 
}

@media (max-width: 768px)  {
  nav  {
  padding: 0 20px;
 
} .end-header  {
  padding: 100px 20px 40px;
 
} .end-list  {
  padding: 0 20px 60px;
 
} .end-quote  {
  font-size: 1.05rem;
 
} .end-cta  {
  padding: 40px 20px;
 
} footer  {
  padding: 24px 20px;
  flex-direction: column;
  gap: 12px;
  text-align: center;
 
}
}

.hero  {
  padding: 140px 40px 32px;
  max-width: var(--wide);
  margin: 0 auto;
 
}

.hero-intro  {
  display: flex;
  align-items: center;
  gap: 16px;
  margin-bottom: 24px;
 
}

.hero-photo  {
  width: 56px;
  height: 56px;
  border-radius: 50%;
  object-fit: cover;
  flex-shrink: 0;
 
}

.hero-eyebrow  {
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--subtle);
 
}

.hero-banner  {
  background: var(--ink);
  margin: 24px -40px 32px;
  padding: 40px 40px;
 
}

.hero-banner h1  {
  font-family: var(--serif);
  font-size: clamp(1.8rem, 3.5vw, 2.6rem);
  line-height: 1.2;
  color: var(--white);
  letter-spacing: -0.02em;
  margin: 0;
 
}

.hero-banner h1 em  {
  font-style: italic;
  color: rgba(255,255,255,0.5);
 
}

.ticker-word  {
  display: inline-block;
  position: relative;
  color: var(--forest);
}

.ticker-word.fade-out  {
  opacity: 0;
  transform: translateY(-8px);
  transition: opacity 0.3s, transform 0.3s;
 
}

.ticker-word.fade-in  {
  opacity: 1;
  transform: translateY(0);
  transition: opacity 0.3s, transform 0.3s;
 
}

@media (max-width: 768px)  {
  .hero-banner  {
  margin: 24px -20px 28px;
  padding: 32px 20px;
 
}
}

.hero-bio  {
  font-size: 0.92rem;
  line-height: 1.8;
  color: var(--charcoal);
  margin-bottom: 20px;
 
}

.hero-bio strong  {
  color: var(--black);
  font-weight: 600;
 
}

.hero-meta  {
  display: flex;
  gap: 24px;
  flex-wrap: wrap;
  align-items: center;
  padding: 20px 0;
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
 
}

.hero-meta a  {
  font-size: 0.83rem;
  font-weight: 500;
  color: var(--mid);
  text-decoration: none;
  display: flex;
  align-items: center;
  gap: 6px;
  transition: color 0.2s;
 
}

.hero-meta a:hover  {
  color: var(--accent);
 
}

.hero-stat-row  {
  display: flex;
  gap: 48px;
  flex-wrap: wrap;
  padding: 0 0 28px;
  margin-bottom: 28px;
  border-bottom: 1px solid var(--border);
 
}

.hero-stat .num  {
  font-family: var(--serif);
  font-size: 2rem;
  color: var(--black);
  display: block;
  line-height: 1;
  margin-bottom: 4px;
 
}

.hero-stat .label  {
  font-size: 0.78rem;
  color: var(--subtle);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  font-weight: 500;
 
}

.section-divider  {
  display: none;
 
}

.section-label  {
  font-family: var(--serif);
  font-size: 1.6rem;
  color: var(--ink);
  letter-spacing: -0.01em;
  padding: 24px 40px 20px;
  max-width: var(--wide);
  margin: 0 auto;
 
}

.work-grid  {
  max-width: var(--wide);
  margin: 0 auto;
  padding: 0 40px 64px;
 
}

.work-item  {
  display: grid;
  grid-template-columns: 80px 1fr 160px;
  gap: 0 40px;
  padding: 28px 0;
  border-bottom: 1px solid var(--border);
  text-decoration: none;
  color: inherit;
  transition: opacity 0.15s;
  align-items: start;
 
}

.work-item:hover  {
  opacity: 0.7;
 
}

.work-item:hover .work-arrow  {
  transform: translateX(4px);
 
}

.work-year  {
  font-size: 0.78rem;
  color: var(--subtle);
  font-weight: 500;
  padding-top: 4px;
  letter-spacing: 0.04em;
 
}

.work-title  {
  font-family: var(--serif);
  font-size: 1.25rem;
  color: var(--black);
  letter-spacing: -0.01em;
  line-height: 1.3;
  margin-bottom: 6px;
 
}

.work-sub  {
  font-size: 0.85rem;
  color: var(--mid);
  line-height: 1.5;
  margin-bottom: 10px;
 
}


.work-right  {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  justify-content: space-between;
  padding-top: 2px;
 
}

.work-metric  {
  font-size: 0.8rem;
  color: var(--mid);
  text-align: right;
  line-height: 1.4;
  font-weight: 500;
 
}

.work-metric strong  {
  display: block;
  font-family: var(--serif);
  font-size: 1.2rem;
  color: var(--black);
  font-weight: 400;
  line-height: 1;
  margin-bottom: 2px;
 
}

.work-arrow  {
  font-size: 1.1rem;
  color: var(--subtle);
  transition: transform 0.2s;
  margin-top: 12px;
 
}


.profile-inner  {
  max-width: var(--wide);
  margin: 0 auto;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 80px;
  align-items: start;
 
}

.profile-strip h2  {
  font-family: var(--serif);
  font-size: 2rem;
  letter-spacing: -0.02em;
  margin-bottom: 20px;
  line-height: 1.2;
 
}

.profile-strip p  {
  font-size: 0.9rem;
  color: rgba(255,255,255,0.7);
  line-height: 1.8;
  margin-bottom: 16px;
 
}

.profile-strip a  {
  font-size: 0.83rem;
  font-weight: 500;
  color: var(--white);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-decoration: none;
  border-bottom: 1px solid rgba(255,255,255,0.4);
  padding-bottom: 2px;
 
}

.skills-col h3  {
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.4);
  margin-bottom: 16px;
 
}

.skills-list  {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 10px;
 
}

.skills-list li  {
  font-size: 0.88rem;
  color: rgba(255,255,255,0.8);
  padding-bottom: 10px;
  border-bottom: 1px solid rgba(255,255,255,0.1);
  display: flex;
  align-items: center;
  gap: 10px;
 
}

.skills-list li::before  {
  content: "";
  width: 4px;
  height: 4px;
  background: rgba(139,92,246,0.6);
  border-radius: 50%;
  flex-shrink: 0;
 
}

footer  {
  max-width: var(--wide);
  margin: 0 auto;
  padding: 40px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  border-top: 1px solid var(--border);
 
}

@media (max-width: 768px)  {
  nav  {
  padding: 0 20px;
 
} .hero  {
  padding: 110px 20px 48px;
 
} .work-item  {
  grid-template-columns: 1fr;
  gap: 8px;
 
} .work-year, .work-right  {
  display: none;
 
} .work-grid, .section-label  {
  padding-left: 20px;
  padding-right: 20px;
 
} .profile-inner  {
  grid-template-columns: 1fr;
  gap: 40px;
 
} .profile-strip div[style*="grid-template-columns:1fr 1fr 1fr"]  {
  grid-template-columns: 1fr !important;
 
} .profile-strip div[style*="grid-template-columns:1fr 1fr 1fr 1fr"]  {
  grid-template-columns: 1fr 1fr !important;
 
} .profile-strip  {
  padding: 48px 20px;
 
} footer  {
  padding: 40px 20px;
  flex-direction: column;
  gap: 20px;
  text-align: center;
 
} .hero-stat-row  {
  gap: 28px;
 
}
}

.modal-overlay  {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 200;
  background: rgba(13,13,13,0.6);
  backdrop-filter: blur(4px);
  opacity: 0;
  transition: opacity 0.25s;
 
}

.modal-overlay.active  {
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 80px 20px 40px;
 
}

.modal-overlay.visible  {
  opacity: 1;
 
}

.modal  {
  background: var(--bg);
  border-radius: 8px;
  max-width: 720px;
  width: 100%;
  max-height: calc(100vh - 120px);
  overflow-y: auto;
  padding: 48px;
  position: relative;
  transform: translateY(20px);
  transition: transform 0.3s ease;
  box-shadow: 0 24px 80px rgba(0,0,0,0.2);
 
}

.modal-overlay.visible .modal  {
  transform: translateY(0);
 
}

.modal-close  {
  position: absolute;
  top: 20px;
  right: 20px;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  border: 1px solid var(--border);
  background: var(--white);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.1rem;
  color: var(--mid);
  transition: all 0.15s;
  line-height: 1;
 
}

.modal-close:hover  {
  border-color: var(--accent);
  color: var(--accent);
 
}

.modal h2  {
  font-family: var(--serif);
  font-size: 1.4rem;
  color: var(--black);
  margin-bottom: 6px;
 
}

.modal-subtitle  {
  font-size: 0.85rem;
  color: var(--mid);
  margin-bottom: 24px;
  line-height: 1.5;
 
}

.modal-tags  {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 32px;
  padding-bottom: 28px;
  border-bottom: 1px solid var(--border);
 
}


.modal-count  {
  font-size: 0.72rem;
  color: var(--subtle);
  font-weight: 500;
  margin-bottom: 16px;
 
}

.modal-results  {
  display: flex;
  flex-direction: column;
 
}

.modal-result  {
  display: flex;
  justify-content: space-between;
  align-items: start;
  padding: 20px 0;
  border-top: 1px solid var(--border);
  text-decoration: none;
  color: inherit;
  transition: opacity 0.15s;
  gap: 16px;
 
}

.modal-result:hover  {
  opacity: 0.6;
 
}

.modal-result-content  {
  flex: 1;
 
}

.modal-result-title  {
  font-family: var(--serif);
  font-size: 1.05rem;
  color: var(--black);
  margin-bottom: 4px;
  line-height: 1.3;
 
}

.modal-result-sub  {
  font-size: 0.8rem;
  color: var(--mid);
  line-height: 1.5;
 
}

.modal-result-year  {
  font-size: 0.75rem;
  color: var(--subtle);
  font-weight: 500;
  white-space: nowrap;
  padding-top: 4px;
  letter-spacing: 0.04em;
 
}

.modal-result-tags  {
  display: flex;
  gap: 4px;
  flex-wrap: wrap;
  margin-top: 10px;
 
}

.modal-result-tags .mtag  {
  font-size: 0.62rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 3px 8px;
  border-radius: 2px;
  background: var(--tag-bg);
  color: var(--tag-text);
 
}

.modal-result-tags .mtag.match  {
  background: var(--accent);
  color: var(--white);
 
}

@media (max-width: 768px)  {
  .modal  {
  padding: 32px 20px;
 
} .modal-overlay.active  {
  padding: 40px 12px 20px;
 
}
}

.login-container  {
  width: 100%;
  max-width: 420px;
  padding: 0 24px;
  text-align: center;
 
}

.login-name  {
  font-family: var(--serif);
  font-size: 1.6rem;
  color: var(--black);
  margin-bottom: 8px;
  letter-spacing: -0.02em;
 
}

.login-title  {
  font-family: var(--serif);
  font-size: 2.4rem;
  color: var(--black);
  letter-spacing: -0.02em;
  line-height: 1.15;
  margin-bottom: 8px;
 
}

.login-title em  {
  font-style: italic;
  color: var(--mid);
 
}

.login-sub  {
  font-size: 0.88rem;
  color: var(--subtle);
  margin-bottom: 48px;
  line-height: 1.6;
 
}

.login-form  {
  display: flex;
  flex-direction: column;
  gap: 16px;
 
}

.login-input-wrap  {
  position: relative;
 
}

.login-input  {
  width: 100%;
  font-family: var(--sans);
  font-size: 0.94rem;
  padding: 16px 20px;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: var(--white);
  color: var(--black);
  outline: none;
  transition: border-color 0.2s, box-shadow 0.2s;
  letter-spacing: 0.02em;
 
}

.login-input::placeholder  {
  color: var(--subtle);
  font-weight: 400;
 
}

.login-input:focus  {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(109,40,217,0.08);
 
}

.login-btn  {
  font-family: var(--sans);
  font-size: 0.83rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 16px 24px;
  border: none;
  border-radius: 4px;
  background: var(--accent);
  color: var(--white);
  cursor: pointer;
  transition: background 0.2s, transform 0.1s;
 
}

.login-btn:hover  {
  background: #5b21b6;
 
}

.login-btn:active  {
  transform: scale(0.98);
 
}

.login-error  {
  font-size: 0.8rem;
  color: #dc2626;
  min-height: 1.4em;
  margin-top: 4px;
  opacity: 0;
  transition: opacity 0.2s;
 
}

.login-error.visible  {
  opacity: 1;
 
}

.login-divider  {
  width: 48px;
  height: 1px;
  background: var(--border);
  margin: 48px auto 24px;
 
}

.login-footer  {
  font-size: 0.75rem;
  color: var(--subtle);
  letter-spacing: 0.04em;
 
}

@media (max-width: 480px)  {
  .login-title  {
  font-size: 1.8rem;
 
} .login-container  {
  padding: 0 20px;
 
}
}

.writing-header  {
  padding: 4rem var(--gutter) 3rem;
  max-width: var(--wide);
  margin: 0 auto;
 
}

.writing-header h1  {
  font-family: var(--serif);
  font-size: clamp(2rem, 4.5vw, 3rem);
  line-height: 1.15;
  color: var(--black);
  letter-spacing: -0.02em;
  margin-bottom: 16px;
 
}

.writing-header p  {
  font-size: 1rem;
  color: var(--mid);
  line-height: 1.7;
  max-width: 580px;
 
}

.writing-topics  {
  max-width: var(--wide);
  margin: 0 auto;
  padding: 0 40px 40px;
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
 
}

.topic-btn  {
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  background: var(--white);
  color: var(--mid);
  border: 1px solid var(--border);
  padding: 7px 16px;
  border-radius: 20px;
  cursor: pointer;
  transition: all 0.15s;
 
}

.topic-btn:hover  {
  border-color: var(--accent);
  color: var(--accent);
 
}

.topic-btn.active  {
  background: var(--accent);
  color: var(--white);
  border-color: var(--accent);
 
}

.article-list  {
  max-width: var(--wide);
  margin: 0 auto;
  padding: 0 var(--gutter) 5rem;
 
}

.article-item  {
  display: block;
  padding: 32px 0;
  border-top: 1px solid var(--border);
  text-decoration: none;
  color: inherit;
  transition: opacity 0.15s;
 
}

.article-item:hover  {
  opacity: 0.65;
 
}

.article-meta  {
  display: flex;
  gap: 16px;
  align-items: center;
  margin-bottom: 10px;
 
}

.article-date  {
  font-size: 0.75rem;
  color: var(--subtle);
  font-weight: 500;
  letter-spacing: 0.04em;
 
}

.article-read  {
  font-size: 0.75rem;
  color: var(--subtle);
  font-weight: 400;
 
}

.article-topic  {
  font-size: 0.62rem;
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  background: var(--tag-bg);
  color: var(--tag-text);
  padding: 3px 10px;
  border-radius: 2px;
 
}

.article-title  {
  font-family: var(--serif);
  font-size: 1.35rem;
  color: var(--black);
  letter-spacing: -0.01em;
  line-height: 1.3;
  margin-bottom: 8px;
 
}

.article-excerpt  {
  font-size: 0.9rem;
  color: var(--mid);
  line-height: 1.65;
  max-width: 600px;
 
}

.article-empty  {
  text-align: center;
  padding: 80px 40px;
  max-width: var(--wide);
  margin: 0 auto;
 
}

.article-empty p  {
  font-size: 0.94rem;
  color: var(--mid);
  line-height: 1.7;
  margin-bottom: 8px;
 
}

.article-empty .empty-icon  {
  font-size: 2rem;
  margin-bottom: 16px;
  display: block;
  opacity: 0.3;
 
}

@media (max-width: 768px)  {
  nav  {
  padding: 0 20px;
 
} .writing-header  {
  padding: 100px 20px 40px;
 
} .writing-topics  {
  padding: 0 20px 32px;
 
} .article-list  {
  padding: 0 20px 60px;
 
} .article-title  {
  font-size: 1.15rem;
 
} footer  {
  padding: 24px 20px;
  flex-direction: column;
  gap: 12px;
  text-align: center;
 
}
}


/* ---------------------------------------------------------------------------
   3. Design system — matched to the log. Overrides everything above.
   ------------------------------------------------------------------------- */
/* ===========================================================================
   Lisa Reeves — portfolio
   One stylesheet for every page. Previously each of the 16 pages carried its
   own copy of these rules inline, so a change meant editing sixteen files.
   Change it here instead.

   Design language is shared with the log at log.lilypixel.com: Inter, a warm
   paper background, hairline rules, generous space, one accent colour.
   =========================================================================== */

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

html {
  background: var(--paper);
  -webkit-text-size-adjust: 100%;
}

body {
  font-family: var(--sans);
  background: var(--paper);
  color: var(--ink);
  line-height: 1.7;
  -webkit-font-smoothing: antialiased;
  text-wrap: pretty;
}

img {
  max-width: 100%;
  height: auto;
}

a {
  color: inherit;
}

/* --- Navigation -----------------------------------------------------------
   Static rather than fixed. The old fixed bar with a blur needed every page to
   reserve 120px of top padding; a bordered header needs nothing. */

nav {
  /* Explicitly static: the old rule made this fixed, which then required every
     page to reserve ~120px of top padding for it. Without that reset the bar
     sits on top of the first line of each page. */
  position: static;
  backdrop-filter: none;
  border-bottom: 1px solid var(--rule);
  padding: 0 var(--gutter);
  height: 4.5rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  max-width: var(--wide);
  margin: 0 auto;
}

.nav-name {
  font-family: var(--font-display);
  font-size: 1rem;
  font-weight: 500;
  letter-spacing: -0.01em;
  color: var(--ink);
  text-decoration: none;
}

.nav-links {
  display: flex;
  gap: 1.5rem;
  align-items: center;
}

.nav-links a {
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--ink-soft);
  text-decoration: none;
  transition: color 0.15s;
}

.nav-links a:hover,
.nav-links a.active {
  color: var(--ink);
}

.nav-links .nav-cta {
  border: 1px solid var(--ink);
  padding: 0.4rem 0.9rem;
  border-radius: 6px;
  color: var(--ink);
  font-size: 0.8125rem;
}

.nav-links .nav-cta:hover {
  background: var(--ink);
  color: var(--paper);
}

/* --- Shared type ---------------------------------------------------------- */

.eyebrow,
.cs-eyebrow,
.hero-eyebrow,
.section-label,
.cs-section-label {
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.cs-section-label {
  margin-bottom: 1.25rem;
  padding-bottom: 0.75rem;
  border-bottom: 1px solid var(--rule);
}

/* Focus areas read as an editorial metadata line — small caps against a
   hairline, the way the case-study PDF sets its eyebrows. Explicitly no fill,
   no radius, no padding: rounded pill badges in a row are the single clearest
   visual tell of a generated layout, and they were the first thing to go. */

.tag {
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--forest);
  background: none;
  border: 0;
  border-radius: 0;
  padding: 0;
  white-space: nowrap;
  transition: color 0.15s;
}

.tag:not(:last-child)::after {
  content: '·';
  margin-left: 0.7rem;
  color: var(--ink-faint);
  font-weight: 400;
}

a.tag,
.tag[role='button'] {
  cursor: pointer;
}

a.tag:hover,
.tag[role='button']:hover {
  background: none;
  color: var(--accent);
}

a.tag:hover::after,
.tag[role='button']:hover::after {
  color: var(--ink-faint);
}

/* --- Home page ------------------------------------------------------------ */

.hero {
  padding: 4rem var(--gutter) 2rem;
  max-width: var(--wide);
  margin: 0 auto;
}

.hero-intro {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin-bottom: 1.5rem;
}

.hero-photo {
  width: 3.5rem;
  height: 3.5rem;
  border-radius: 50%;
  object-fit: cover;
  flex-shrink: 0;
}

/* Was a dark purple banner. A hairline and a large heading do the same job
   without shouting, and matches how the log opens. */
.hero-banner {
  /* Was a dark purple block with white text. The background has to be cleared
     explicitly, or the inherited dark fill stays and the heading — now ink —
     becomes invisible against it. */
  background: none;
  margin: 0 0 2.5rem;
  padding: 1rem 0 2.5rem;
  border-bottom: 1px solid var(--rule);
}

.hero-banner h1 {
  font-family: var(--font-display);
  font-size: clamp(1.9rem, 4vw, 2.75rem);
  line-height: 1.15;
  font-weight: 500;
  color: var(--ink);
  letter-spacing: -0.025em;
  text-wrap: balance;
}

.hero-banner h1 em {
  font-style: normal;
  color: var(--ink-soft);
}

.hero-bio {
  font-size: 1rem;
  line-height: 1.75;
  color: var(--ink-soft);
  margin-bottom: 1.5rem;
  max-width: var(--reading);
}

.hero-bio strong {
  color: var(--ink);
  font-weight: 600;
}

.hero-meta {
  display: flex;
  gap: 1.5rem;
  flex-wrap: wrap;
  align-items: center;
  padding: 1.25rem 0;
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
}

.hero-meta a {
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--ink-soft);
  text-decoration: none;
  display: flex;
  align-items: center;
  gap: 0.375rem;
  transition: color 0.15s;
}

.hero-meta a:hover {
  color: var(--ink);
}

.hero-stat-row {
  display: flex;
  gap: 3rem;
  flex-wrap: wrap;
  padding: 1.75rem 0;
  margin-bottom: 1.75rem;
  border-bottom: 1px solid var(--rule);
}

.hero-stat .num {
  font-family: var(--font-display);
  font-size: 1.75rem;
  font-weight: 500;
  letter-spacing: -0.02em;
  color: var(--ink);
  display: block;
  line-height: 1;
  margin-bottom: 0.25rem;
}

.hero-stat .label {
  font-size: 0.75rem;
  color: var(--ink-faint);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  font-weight: 500;
}

.work-grid {
  max-width: var(--wide);
  margin: 0 auto;
  padding: 0 var(--gutter) 4rem;
}

.section-label {
  max-width: var(--wide);
  margin: 0 auto;
  padding: 0 var(--gutter) 1rem;
}

.work-item {
  display: grid;
  grid-template-columns: 4rem 1fr 10rem;
  gap: 0 2rem;
  padding: 1.75rem 0;
  border-bottom: 1px solid var(--rule);
  text-decoration: none;
  color: inherit;
  align-items: start;
  transition: opacity 0.15s;
}

.work-item:hover {
  opacity: 1;
}

.work-item:hover .work-arrow {
  transform: translateX(3px);
}

.work-year {
  font-size: 0.8125rem;
  color: var(--ink-faint);
  font-weight: 500;
  padding-top: 0.25rem;
}

.work-title {
  font-family: var(--font-display);
  font-size: 1.1875rem;
  font-weight: 500;
  color: var(--ink);
  letter-spacing: -0.015em;
  line-height: 1.3;
  margin-bottom: 0.375rem;
}

.work-sub {
  font-size: 0.9375rem;
  color: var(--ink-soft);
  line-height: 1.55;
  margin-bottom: 0.625rem;
}

.work-tags {
  display: flex;
  gap: 0 0.7rem;
  flex-wrap: wrap;
  align-items: baseline;
  padding-top: 0.7rem;
  border-top: 1px solid var(--rule);
}

.work-right {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  justify-content: space-between;
  padding-top: 0.125rem;
}

.work-metric {
  font-size: 0.8125rem;
  color: var(--ink-soft);
  text-align: right;
  line-height: 1.4;
  font-weight: 500;
}

.work-metric strong {
  display: block;
  font-family: var(--font-display);
  font-size: 1.125rem;
  color: var(--ink);
  font-weight: 500;
  letter-spacing: -0.02em;
  line-height: 1;
  margin-bottom: 0.125rem;
}

.work-arrow {
  font-size: 1.5rem;
  line-height: 1;
  color: var(--forest);
  transition: transform 0.2s, color 0.2s;
  margin-top: 0.6rem;
}

.work-item:hover .work-arrow {
  color: var(--accent);
}

/* Hover was a flat opacity fade, which dimmed the whole row and read as
   "disabled" rather than "clickable". The magenta now moves onto the type
   instead, with a wash behind it, so the state is additive. */

.work-item {
  transition: background 0.18s;
  padding-left: 1rem;
  padding-right: 1rem;
  margin-left: -1rem;
  margin-right: -1rem;
}

.work-item:hover {
  background: var(--accent-wash);
}

.work-item:hover .work-title,
.work-item:hover .work-metric strong {
  color: var(--accent);
}

.work-item:hover .work-sub,
.work-item:hover .work-metric {
  color: var(--ink);
}

.work-item:hover .tag {
  color: var(--accent);
}

.work-item .work-title,
.work-item .work-metric strong,
.work-item .work-sub,
.work-item .tag {
  transition: color 0.18s;
}

/* --- Case studies --------------------------------------------------------- */

.cs-header {
  padding: 3.5rem var(--gutter) 2.5rem;
  max-width: var(--reading);
  margin: 0 auto;
}

.cs-back {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--ink-soft);
  text-decoration: none;
  margin-bottom: 2rem;
  transition: color 0.15s;
}

.cs-back:hover {
  color: var(--ink);
}

.cs-eyebrow {
  margin-bottom: 1rem;
}

.cs-header h1 {
  font-family: var(--font-display);
  font-size: clamp(1.9rem, 4vw, 2.6rem);
  line-height: 1.15;
  font-weight: 500;
  color: var(--ink);
  letter-spacing: -0.025em;
  margin-bottom: 1rem;
  text-wrap: balance;
}

.cs-header .cs-subtitle {
  font-size: 1.0625rem;
  color: var(--ink-soft);
  line-height: 1.65;
  margin-bottom: 2rem;
}

.cs-meta-row {
  display: flex;
  gap: 2rem;
  flex-wrap: wrap;
  padding-top: 1.5rem;
  border-top: 1px solid var(--rule);
}

.cs-meta-item label {
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
  display: block;
  margin-bottom: 0.25rem;
}

.cs-meta-item span {
  font-size: 0.875rem;
  color: var(--ink);
  font-weight: 500;
}

.cs-tags {
  display: flex;
  gap: 0 0.7rem;
  flex-wrap: wrap;
  align-items: baseline;
}

/* Was a lavender gradient band. Now a quiet ruled strip — the numbers carry it. */
.metrics-bar {
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
  background: var(--white);
  padding: 2.5rem var(--gutter);
}

.metrics-inner {
  max-width: var(--wide);
  margin: 0 auto;
  display: flex;
  gap: 2.5rem 3.5rem;
  flex-wrap: wrap;
}

.metrics-inner .metric {
  flex: 1 1 11rem;
}

.metric .m-num {
  font-family: var(--font-display);
  font-size: 1.875rem;
  font-weight: 500;
  letter-spacing: -0.025em;
  color: var(--accent);
  display: block;
  line-height: 1;
  margin-bottom: 0.25rem;
}

.metric .m-label {
  font-size: 0.75rem;
  color: var(--ink-soft);
  letter-spacing: 0.05em;
  text-transform: uppercase;
  font-weight: 500;
}

.scroll-hint {
  display: none; /* the page is obviously scrollable */
}

.cs-body {
  max-width: var(--reading);
  margin: 0 auto;
  padding: 3.5rem var(--gutter) 5rem;
}

.cs-section {
  margin-bottom: 3.5rem;
}

.cs-section h2 {
  font-family: var(--font-display);
  font-size: 1.375rem;
  font-weight: 500;
  letter-spacing: -0.015em;
  color: var(--ink);
  margin-bottom: 1rem;
}

.cs-section h3 {
  font-size: 1.0625rem;
  font-weight: 600;
  color: var(--ink);
  margin: 1.75rem 0 0.5rem;
}

.cs-section p {
  font-size: 1.0625rem;
  color: var(--ink);
  line-height: 1.75;
  margin-bottom: 1rem;
}

.cs-section p:last-child {
  margin-bottom: 0;
}

.cs-section ul {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 0.625rem;
  margin-top: 0.75rem;
}

.cs-section ul li {
  font-size: 1rem;
  color: var(--ink);
  line-height: 1.7;
  padding-left: 1.1rem;
  position: relative;
}

.cs-section ul li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.75em;
  width: 0.4rem;
  height: 1px;
  background: var(--ink-faint);
}

.cs-image {
  width: 100%;
  border-radius: 6px;
  margin: 1.75rem 0 0.75rem;
  border: 1px solid var(--rule);
  background: var(--white);
}

.cs-image-clickable {
  /* Second declaration of the same dead affordance, in the re-skin layer. */
}

.cs-image-caption {
  /* Captions were 0.8125rem, which sat too close to body copy and competed
     with it. Down 20% to 0.65rem so a caption reads as a caption. */
  font-size: 0.65rem;
  color: var(--ink-faint);
  text-align: center;
  margin: 0 0 1.75rem;
  font-weight: 500;
}

.cs-image-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.75rem;
  margin: 1.75rem 0;
}

.cs-image-grid img {
  width: 100%;
  border-radius: 6px;
  border: 1px solid var(--rule);
  background: var(--white);
}

.impact-box {
  background: var(--accent-wash);
  border-left: 2px solid var(--accent);
  padding: 1.5rem 1.75rem;
  border-radius: 0 6px 6px 0;
  margin-top: 1.25rem;
}

.impact-box h3 {
  font-family: var(--font-display);
  font-size: 1.0625rem;
  font-weight: 500;
  color: var(--ink);
  margin: 0 0 0.75rem;
}

.impact-list {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 0.625rem;
}

.impact-list li {
  font-size: 0.9375rem;
  color: var(--ink);
  line-height: 1.6;
  padding-left: 1.25rem;
  position: relative;
  font-weight: 500;
}

.impact-list li::before {
  content: '✓';
  position: absolute;
  left: 0;
  color: var(--accent);
  font-size: 0.8125rem;
}

.testimonial {
  border-top: 1px solid var(--rule);
  padding-top: 2.5rem;
  margin-top: 3.5rem;
}

.testimonial blockquote {
  font-family: var(--font-display);
  font-size: 1.1875rem;
  line-height: 1.6;
  color: var(--ink);
  margin-bottom: 1.25rem;
}

.testimonial cite {
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--ink-faint);
  font-style: normal;
}

.cs-next {
  border-top: 1px solid var(--rule);
}

.cs-next-inner {
  max-width: var(--reading);
  margin: 0 auto;
  padding: 2rem var(--gutter);
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
}

.cs-next a {
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--ink-soft);
  text-decoration: none;
  transition: color 0.15s;
}

.cs-next a:hover {
  color: var(--ink);
}

/* --- Endorsements --------------------------------------------------------- */

.end-item {
  padding: 2rem 0;
  border-bottom: 1px solid var(--rule);
}

.end-quote {
  font-size: 1.0625rem;
  line-height: 1.75;
  color: var(--ink);
  margin-bottom: 1rem;
}

.end-attribution {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5rem;
}

.end-person {
  font-size: 0.9375rem;
  font-weight: 600;
  color: var(--ink);
}

.end-role {
  font-size: 0.8125rem;
  color: var(--ink-faint);
}

/* --- Image lightbox ------------------------------------------------------- */

.modal {
  position: fixed;
  inset: 0;
  background: oklch(0.15 0.01 260 / 0.9);
  display: none;
  align-items: center;
  justify-content: center;
  padding: 2rem;
  z-index: 200;
  cursor: zoom-out;
}

.modal.open {
  display: flex;
}

.modal img {
  max-width: 100%;
  max-height: 90vh;
  border-radius: 6px;
}

/* --- Footer --------------------------------------------------------------- */

footer {
  max-width: var(--wide);
  margin: 0 auto;
  padding: 2.5rem var(--gutter);
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
  border-top: 1px solid var(--rule);
}

.footer-name {
  font-family: var(--font-display);
  font-size: 0.9375rem;
  font-weight: 500;
  color: var(--ink);
}

.footer-links {
  display: flex;
  gap: 1.25rem;
  flex-wrap: wrap;
}

.footer-links a {
  font-size: 0.875rem;
  color: var(--ink-soft);
  text-decoration: none;
  font-weight: 500;
  transition: color 0.15s;
}

.footer-links a:hover {
  color: var(--ink);
}

/* --- Generic containers used by cv / writing / login ---------------------- */

.container,
.page,
.wrap {
  max-width: var(--wide);
  margin: 0 auto;
  padding: 3rem var(--gutter);
}


/* --- Display type ----------------------------------------------------------
   With one family doing both jobs, the display voice has to come from weight
   and tracking. Inter at 500 reads as body copy at large sizes; 700 with tight
   tracking is what gives the CV and the case-study PDF their wordmark. */

.hero-banner h1,
.cs-header h1,
.work-title,
.cs-section h2,
.nav-name,
.footer-name,
.hero-stat .num,
.work-metric strong,
.metric .m-num,
.impact-box h3,
.testimonial blockquote,
.bring-title,
.strip-title {
  font-family: var(--sans);
  font-weight: var(--display-weight);
  letter-spacing: var(--display-track);
}

.hero-banner h1 {
  font-size: clamp(2.1rem, 4.6vw, 3.15rem);
  font-weight: 800;
}

.hero-banner h1 em {
  font-weight: 400;
  color: var(--ink-soft);
}

.cs-header h1 {
  font-size: clamp(2rem, 4.2vw, 2.9rem);
  font-weight: 800;
}

.testimonial blockquote {
  font-weight: 500;
  letter-spacing: -0.015em;
}

/* Numerals take the CV's ember, not the magenta — same role, same colour. */
.metric .m-num {
  color: var(--ember);
}

/* --- Corner radius ---------------------------------------------------------
   Softened everywhere by default. Pulled back to a hairline round so panels
   read as printed plates rather than app cards. */

.cs-image,
.cs-image-grid img,
.modal img,
.nav-links .nav-cta,
.impact-box {
  border-radius: 2px;
}

.impact-box {
  border-radius: 0 2px 2px 0;
  background: oklch(0.97 0.012 158);
  border-left: 2px solid var(--forest);
}

.impact-list li::before {
  content: '—';
  color: var(--forest);
  font-weight: 600;
}

/* --- What I bring ----------------------------------------------------------
   Sits above How I lead: capability first, then the principles behind it. */

.bring {
  max-width: var(--wide);
  margin: 0 auto;
  padding: 1rem var(--gutter) 4rem;
}

.bring-title {
  font-size: 1.75rem;
  color: var(--ink);
  margin-bottom: 0.5rem;
}

.bring-intro {
  font-size: 1rem;
  color: var(--ink-soft);
  line-height: 1.7;
  max-width: var(--reading);
  margin-bottom: 2.5rem;
}

.bring-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 2.5rem 3rem;
}

.bring-group h3 {
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--forest);
  padding-bottom: 0.6rem;
  margin-bottom: 0.9rem;
  border-bottom: 1px solid var(--rule);
}

.bring-group ul {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
}

.bring-group li {
  font-size: 0.9375rem;
  line-height: 1.55;
  color: var(--ink-soft);
}

.bring-group li strong {
  color: var(--ink);
  font-weight: 600;
}

.bring-tools {
  margin-top: 2.5rem;
  padding-top: 1.25rem;
  border-top: 1px solid var(--rule);
  font-size: 0.875rem;
  line-height: 1.7;
  color: var(--ink-soft);
}

.bring-tools span {
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--forest);
  margin-right: 0.75rem;
}

/* --- How I lead ------------------------------------------------------------
   Forest ground rather than near-black, with the magenta used sparingly on top
   of it. Green and magenta at full strength is the pairing that makes this page
   not look like everything else. */

.profile-strip {
  background: var(--forest-deep);
  color: #fff;
  padding: 4.5rem var(--gutter);
  margin-top: 0;
}

.profile-strip .strip-inner {
  max-width: var(--wide);
  margin: 0 auto;
}

.strip-title {
  font-size: 1.75rem;
  color: #fff;
  margin-bottom: 0.5rem;
}

.strip-intro {
  font-size: 0.95rem;
  color: rgba(255, 255, 255, 0.62);
  line-height: 1.7;
  max-width: var(--reading);
  margin-bottom: 2.75rem;
}

.strip-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 2.25rem 3rem;
  margin-bottom: 3rem;
}

.strip-grid h3 {
  font-size: 1rem;
  font-weight: 600;
  color: #fff;
  letter-spacing: -0.01em;
  margin-bottom: 0.5rem;
  padding-left: 0.85rem;
  border-left: 2px solid var(--accent-lift);
}

.strip-grid p {
  font-size: 0.875rem;
  color: rgba(255, 255, 255, 0.6);
  line-height: 1.65;
  padding-left: 0.85rem;
}

.strip-foot {
  border-top: 1px solid rgba(255, 255, 255, 0.14);
  padding-top: 2rem;
}

.strip-cta {
  font-size: 0.8125rem;
  font-weight: 600;
  color: #fff;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  text-decoration: none;
  border-bottom: 1px solid var(--accent-lift);
  padding-bottom: 3px;
  transition: color 0.15s;
}

.strip-cta:hover {
  color: var(--accent-lift);
}

/* --- Selected work feature -------------------------------------------------
   One image at the head of the work list so the section reads as a gallery
   opening rather than more body copy. */

.work-feature {
  max-width: var(--wide);
  margin: 0 auto 2.5rem;
  padding: 0 var(--gutter);
}

.work-feature a {
  display: block;
  text-decoration: none;
  color: inherit;
}

.work-feature-frame {
  position: relative;
  overflow: hidden;
  border-radius: 2px;
  background: var(--white);
}

/* Widened and nudged left so the glass-partition edge near the left of the
   photograph crops out of frame. Nothing here draws a border. */
.work-feature-frame img {
  display: block;
  width: 106%;
  max-width: none; /* beats the global img{max-width:100%}, or the crop leaves a gap */
  margin-left: -5%;
  height: clamp(14rem, 30vw, 21rem);
  object-fit: cover;
  object-position: center top;
  transition: transform 0.5s ease;
}

.work-feature a:hover .work-feature-frame img {
  transform: scale(1.02);
}

.work-feature-caption {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1rem;
  flex-wrap: wrap;
  padding-top: 0.85rem;
}

.work-feature-caption .wf-title {
  font-size: 1rem;
  font-weight: 600;
  color: var(--ink);
  letter-spacing: -0.01em;
}

.work-feature-caption .wf-meta {
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--forest);
}

/* --- Endorsements ----------------------------------------------------------
   Recent quotes carry a forest rule so they read ahead of the archive. */

.end-item.is-featured .end-quote {
  border-left: 2px solid var(--forest);
  padding-left: 1.25rem;
}

.end-item.is-featured .end-quote {
  font-size: 1.125rem;
  color: var(--ink);
}

.end-group-label {
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--forest);
  margin: 3rem 0 0.5rem;
  padding-bottom: 0.6rem;
  border-bottom: 1px solid var(--rule);
}

/* --- Filter modal ----------------------------------------------------------
   Rebuilt without the pill treatment the rest of the site just lost. */

.modal-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.25rem;
  padding: 1rem 0;
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
}

.modal-tag {
  font-family: inherit;
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--ink-soft);
  background: none;
  border: 0;
  border-bottom: 1px solid transparent;
  padding: 0.15rem 0;
  cursor: pointer;
  transition: color 0.15s, border-color 0.15s;
}

.modal-tag:hover {
  color: var(--forest);
}

.modal-tag.active {
  color: var(--forest);
  border-bottom-color: var(--forest);
}


/* --- Page-end CTA ----------------------------------------------------------
   endorsements.html and cv.html ended on two different treatments: a solid ink
   panel and a purple linear-gradient. Both now use the same forest ground as
   How I lead on the home page, so every page closes the same way. The gradient
   is gone deliberately — it was the one left on the site. */

.end-cta,
.cv-cta {
  background: var(--forest-deep);
  padding: 4.5rem var(--gutter);
  text-align: center;
}

.end-cta p,
.cv-cta p {
  font-family: var(--sans);
  font-size: 1.5rem;
  font-weight: 700;
  letter-spacing: var(--display-track);
  color: #fff;
  margin-bottom: 1.5rem;
  line-height: 1.25;
}

.end-cta a,
.cv-cta a {
  display: inline-block;
  border: 1px solid var(--accent-lift);
  background: none;
  padding: 0.8rem 1.75rem;
  border-radius: 2px;
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: #fff;
  text-decoration: none;
  transition: background 0.15s, color 0.15s;
}

.end-cta a:hover,
.cv-cta a:hover {
  background: var(--accent-lift);
  color: var(--forest-deep);
}

/* --- Small screens: new components ---------------------------------------- */

@media (max-width: 60rem) {
  .bring-grid,
  .strip-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (max-width: 48rem) {
  .bring-grid,
  .strip-grid {
    grid-template-columns: 1fr;
    gap: 1.75rem;
  }

  .profile-strip {
    padding: 3rem var(--gutter);
  }
}

/* --- Small screens -------------------------------------------------------- */

@media (max-width: 48rem) {
  :root {
    --gutter: 1.25rem;
  }

  nav {
    height: 3.5rem;
  }

  .nav-links {
    gap: 1rem;
  }

  .work-item {
    grid-template-columns: 1fr;
    gap: 0.5rem;
  }

  .work-year,
  .work-right {
    display: none;
  }

  .cs-image-grid {
    grid-template-columns: 1fr;
  }

  .hero-stat-row,
  .metrics-inner {
    gap: 1.75rem;
  }

  footer,
  .cs-next-inner {
    flex-direction: column;
    align-items: flex-start;
  }
}

/* ---------------------------------------------------------------------------
   4. Additions — August 2026
   Hero availability chip, the Selected Work intro line that the ticker moved
   into, and the Making page. Appended last so it wins, same as layer 3.
   ------------------------------------------------------------------------- */

/* The one thing on the page that says "I am looking". Kept quiet: forest, not
   magenta, because it sits inside a line of grey metadata and shouting there
   would read as desperate rather than available. */
.hero-available {
  color: var(--forest);
  font-weight: 700;
  white-space: nowrap;
}

/* "Driving better [x] for the people who matter." Demoted from the h1 to a
   standfirst over the work list, which is what it always was. */
/* This has to sit in the same container as .section-label above it, or it
   escapes to the left edge of <main> and hangs off the side of the page.
   That was the bug in the screenshot: max-width alone is not a container. */
.work-intro {
  max-width: var(--wide);
  margin: -0.4rem auto 2.2rem;
  padding: 0 var(--gutter);
  font-size: 1.35rem;
  line-height: 1.4;
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--ink-soft);
}
.work-intro span { display: inline; }
.work-intro .ticker-word { color: var(--forest); }

@media (max-width: 700px) {
  .work-intro { font-size: 1.15rem; }
  .hero-available { white-space: normal; }
}

/* --- Making page ---------------------------------------------------------- */

.mk-note {
  max-width: var(--wide);
  margin: 0 auto 4rem;
  padding: 0 var(--gutter);
}
.mk-note p {
  border-left: 2px solid var(--forest);
  padding-left: 1.4rem;
  color: var(--ink-soft);
  font-size: 1.05rem;
  max-width: 34rem;
}

.mk-section {
  max-width: var(--wide);
  margin: 0 auto;
  padding: 0 var(--gutter) 4.5rem;
}
.mk-section + .mk-section { border-top: 1px solid var(--rule); padding-top: 4rem; }

.mk-title {
  font-family: var(--font-display);
  font-weight: var(--display-weight);
  letter-spacing: var(--display-track);
  font-size: clamp(1.7rem, 4vw, 2.4rem);
  line-height: 1.1;
  margin: 0.2rem 0 1rem;
}
.mk-intro {
  max-width: 34rem;
  color: var(--ink-soft);
  margin: 0 0 2.4rem;
}
.mk-caption {
  max-width: 34rem;
  margin: 2rem 0 0;
  font-size: 0.9rem;
  color: var(--ink-faint);
}

/* Pieces are square by nature (1080x1080), so the grid is square too and the
   caption sits under the image rather than over it. Two up on desktop keeps
   each one big enough to read the line work, which is the whole point. */
.mk-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(19rem, 1fr));
  gap: 2.6rem 2.2rem;
}
.mk-piece { margin: 0; }
.mk-piece img {
  width: 100%;
  height: auto;
  display: block;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  background: var(--rule);
  border: 1px solid var(--rule);
}
.mk-piece figcaption { display: block; padding-top: 0.9rem; }
.mk-piece-title {
  display: block;
  font-weight: 700;
  letter-spacing: -0.012em;
  margin-bottom: 0.35rem;
}
.mk-piece-body {
  display: block;
  color: var(--ink-soft);
  font-size: 0.95rem;
  line-height: 1.6;
}
.mk-piece-tag {
  display: inline-block;
  margin-top: 0.7rem;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--tag-text);
  background: var(--tag-bg);
  padding: 0.24rem 0.5rem;
  border-radius: 2px;
}

.mk-two {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
  gap: 2.4rem;
  max-width: 46rem;
}
.mk-two h3 {
  font-size: 1rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  margin: 0 0 0.7rem;
}
.mk-two p { color: var(--ink-soft); margin: 0 0 0.9rem; }
.mk-list { list-style: none; padding: 0; margin: 0; }
.mk-list li {
  color: var(--ink-soft);
  padding: 0.5rem 0 0.5rem 1.1rem;
  border-bottom: 1px solid var(--rule);
  position: relative;
}
.mk-list li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 1.05rem;
  width: 5px;
  height: 5px;
  border: 1px solid var(--accent);
  border-radius: 50%;
}

/* Photography: mixed portrait and landscape, so rows are masonry-ish rather
   than a rigid square grid. */
.mk-photo-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: 1.6rem;
  align-items: start;
}
.mk-photo { margin: 0; }
.mk-photo img {
  width: 100%;
  height: auto;
  display: block;
  background: var(--rule);
}
.mk-photo figcaption {
  padding-top: 0.6rem;
  font-size: 0.85rem;
  color: var(--ink-faint);
}

.mk-close { border-top: 1px solid var(--rule); padding-top: 3.5rem; }
.mk-close .strip-foot { margin-top: 1.8rem; }

/* --- Article pages -------------------------------------------------------- */

.art-wrap {
  max-width: var(--reading);
  margin: 0 auto;
  padding: 3rem var(--gutter) 5rem;
}
.art-back { margin: 0 0 2.5rem; font-size: 0.85rem; }
.art-back a { color: var(--ink-faint); text-decoration: none; }
.art-back a:hover { color: var(--accent); }

.art-head { max-width: 34rem; padding-bottom: 2rem; border-bottom: 1px solid var(--rule); margin-bottom: 2.4rem; }
.art-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.2rem;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-bottom: 1.1rem;
}
.art-meta .art-topic { color: var(--tag-text); }
.art-head h1 {
  font-family: var(--font-display);
  font-weight: var(--display-weight);
  letter-spacing: var(--display-track);
  font-size: clamp(1.9rem, 5vw, 2.9rem);
  line-height: 1.06;
  margin: 0 0 1rem;
}
.art-standfirst { font-size: 1.15rem; line-height: 1.5; color: var(--ink-soft); margin: 0; }

.art-body { max-width: 34rem; }
.art-body p { margin: 0 0 1.15rem; }
.art-body h2 {
  font-family: var(--font-display);
  font-weight: var(--display-weight);
  letter-spacing: -0.02em;
  font-size: 1.3rem;
  line-height: 1.2;
  margin: 2.6rem 0 0.9rem;
}
.art-list { list-style: none; padding: 0; margin: 0 0 1.4rem; }
.art-list li {
  padding: 0.75rem 0 0.75rem 1.1rem;
  border-bottom: 1px solid var(--rule);
  color: var(--ink-soft);
  position: relative;
}
.art-list li strong { color: var(--ink); }
.art-list li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 1.35rem;
  width: 5px;
  height: 5px;
  border: 1px solid var(--accent);
  border-radius: 50%;
}

/* The one pulled line per piece. Forest, not magenta: magenta is already doing
   the tag and link job and a second use here would flatten both. */
.art-pull {
  margin: 2.2rem 0;
  padding: 0 0 0 1.4rem;
  border-left: 3px solid var(--forest);
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.2rem;
  line-height: 1.35;
  letter-spacing: -0.018em;
  color: var(--forest);
}

.art-foot {
  max-width: 34rem;
  margin-top: 3rem;
  padding-top: 1.4rem;
  border-top: 1px solid var(--rule);
  font-size: 0.9rem;
}
.art-foot a { color: var(--accent); text-decoration: none; font-weight: 500; }
.art-foot a:hover { text-decoration: underline; }

/* Relationship + date on an endorsement. Small, uppercase, sitting under the
   name: it reads as provenance rather than as more praise. Without it every
   quote on the page carries identical weight, which is the same as none. */
.end-rel {
  display: block;
  margin-top: 0.3rem;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--forest);
}

/* Four stats, one row. The default flex gap of 3rem lets a long label push the
   fourth stat onto its own line, which reads as a mistake rather than a stat.
   A four-column grid with equal tracks keeps them level whatever the wording,
   and drops to two columns before it gets cramped. */
.hero-stat-row {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 1.75rem 2rem;
  align-items: start;
}
.hero-stat .label { display: block; text-wrap: balance; }

@media (max-width: 900px) {
  .hero-stat-row { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 460px) {
  .hero-stat-row { grid-template-columns: 1fr 1fr; gap: 1.4rem 1.2rem; }
}

/* ===========================================================================
   5. Re-skin — August 2026
   The quiet-governance palette became a colour-per-section system: the nav
   band is constant, the ground under it tells you which part of the site you
   are in. Type does the rest of the personality work — a grotesque that has
   some shape to it, Inter for reading, and a mono for anything that is data
   rather than prose (years, metrics, eyebrows, nav).

   This layer overrides TOKENS, not components. Everything in layers 1–4 reads
   through var(), so redefining the tokens here re-skins the whole site,
   including the nine case study pages that are otherwise untouched.
   =========================================================================== */

:root {
  /* Type ------------------------------------------------------------------ */
  --sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --display: 'Familjen Grotesk', 'Inter', sans-serif;
  --mono: 'IBM Plex Mono', ui-monospace, 'SF Mono', Menlo, monospace;
  --font-display: var(--display);
  --serif: var(--display);
  --display-weight: 700;
  --display-track: -0.032em;

  /* Ground ---------------------------------------------------------------- */
  --paper: #FCFBF8;
  --white: #ffffff;
  --ink: #14181A;
  --ink-soft: #565E62;
  --ink-faint: #8A9296;
  --rule: #E4E6E3;

  /* Brand — monochrome ------------------------------------------------------
     Every ground and every piece of type is now black, white or a neutral
     grey. The old forest/zest/coral trio survives only as the riso accent
     below, which is allowed on exactly three things: the cogs, the one
     highlighted phrase, and hover states. Near-black rather than #000 so the
     dark bands do not vibrate against white type. */
  --forest: #16191B;      /* the nav band and the dark panels */
  --forest-deep: #0E1113; /* the darker ground, How I lead */
  --forest-soft: #6B7276;
  --ember: #14181A;       /* numerals were orange; they are ink now */

  /* Riso accent -------------------------------------------------------------
     Two tiers, and the split is not cosmetic. --riso-light is an ink-on-paper
     fill: it is for the cogs and the highlight block, where it sits behind
     something else. --riso-ink is the same hue darkened until it clears 4.5:1
     on white, because --accent is used as TYPE in 62 places and a light riso
     colour would fail contrast outright. Per-section values below. */
  --riso-light: #DCEF9C;
  --riso-wash:  #F4FADF;
  --riso-ink:   #5E7A1E;

  /* Kept as aliases: older rules still name them. */
  --zest: var(--riso-light);
  --zest-deep: var(--riso-ink);
  --coral: var(--riso-ink);

  /* Accent is no longer a fixed hue. It resolves to the current section's riso
     colour, so links, hovers and the CTA border always match that page's cogs
     without any component needing to know which page it is on. */
  --accent: var(--riso-ink);
  --accent-wash: var(--riso-wash);
  --accent-lift: var(--riso-light); /* the legible form on the dark grounds */
  --accent-soft: transparent;

  /* Layout. The old 62rem was a narrow column on a wide screen. This uses the
     page properly, which is what the site was missing. */
  --reading: 54rem;
  --wide: 78rem;
  --gutter: 3rem;

  /* Aliases so layers 1–4 follow. */
  --black: var(--ink);
  --charcoal: var(--ink);
  --mid: var(--ink-soft);
  --subtle: var(--ink-faint);
  --border: var(--rule);
  --bg: var(--paper);
  --tag-bg: var(--accent-wash);
  --tag-text: var(--accent);
}

/* --- Section grounds ------------------------------------------------------
   One class on <body>. It only changes tokens, so every component on the page
   re-tints itself. --rule has to darken with the ground or the hairlines
   disappear. */

/* Section grounds were pastel washes. They are white now; the cog underlay
   does the identifying instead, and it does it without tinting the content. */

body.sec-work, body.sec-personal, body.sec-articles, body.sec-people { background: var(--paper); }
body.sec-work nav, body.sec-personal nav, body.sec-articles nav,
body.sec-people nav { background: var(--forest); }

/* --- Nav: one constant forest band across every page --------------------- */

nav {
  background: var(--forest);
  border-bottom: 0;
  backdrop-filter: none;
  height: 60px;
  padding: 0 var(--gutter);
  max-width: none;
}
.nav-name {
  font-family: var(--display);
  font-weight: 700;
  font-size: 1.05rem;
  letter-spacing: -0.01em;
  color: #fff;
  text-decoration: none;
}
.nav-name::after { content: '.'; color: var(--zest); }
.nav-links { display: flex; align-items: center; gap: 2.4rem; }
.nav-links a {
  font-family: var(--mono);
  font-size: 0.78rem;
  letter-spacing: 0.01em;
  color: rgba(255,255,255,0.72);
  text-decoration: none;
  transition: color 0.15s;
}
.nav-links a:hover { color: #fff; }
.nav-links a.active { color: var(--zest); }
.nav-links a.nav-cta {
  background: var(--zest);
  color: var(--forest);
  font-weight: 600;
  padding: 0.5rem 0.9rem;
  border-radius: 2px;
  border: 0;
}
.nav-links a.nav-cta:hover { background: #fff; color: var(--forest); }

/* --- Sharp corners --------------------------------------------------------
   Every rounded thing on the site, squared off to 2px. Rounded corners were
   softening it in the wrong direction: the friendliness is meant to come from
   colour and type, not from radius. */
.tag, .work-item, .end-item, .card, .modal, .modal-tag, .modal-result,
.hero-photo, .strip-grid > div, .article-item, .mk-piece img, .mk-photo img,
input, button, .chip, .s, .stat, .bring-group {
  border-radius: 2px;
}
.hero-photo { border-radius: 50%; }

/* --- Type scale: state it, do not shout it -------------------------------- */

h1, h2, h3, .work-title, .strip-title, .bring-title, .mk-title {
  font-family: var(--display);
  letter-spacing: var(--display-track);
}
.hero-banner h1 {
  font-weight: 700;
  font-size: clamp(2.4rem, 5.2vw, 4rem);
  line-height: 1.02;
}
.hero-banner h1 em { font-style: normal; }

/* Anything that is data rather than prose goes mono. This is the tell: it
   says the author works in the toolchain, which is the positioning. */
.hero-eyebrow, .section-label, .work-year, .end-rel, .end-group-label,
.hero-stat .label, .art-meta, .mk-piece-tag, .article-date, .article-read,
.chip, .phase-n, .mono {
  font-family: var(--mono);
  font-weight: 500;
}
.hero-stat .num, .work-metric strong {
  font-family: var(--display);
  font-weight: 700;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
}

/* --- Availability chip ---------------------------------------------------- */
.hero-available {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  background: var(--zest);
  color: var(--forest);
  font-family: var(--mono);
  font-weight: 600;
  font-size: 0.72rem;
  letter-spacing: 0.01em;
  text-transform: none;
  padding: 0.3rem 0.7rem;
  border-radius: 2px;
  white-space: nowrap;
}
.hero-available::before {
  content: '';
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--forest);
}

/* --- Recent experience ----------------------------------------------------
   Four roles, three outcomes each. Jo's pattern, and it works because the CV
   is behind a password: this is the only career history a visitor can read.
   Rules not cards — cards would make four roles look like a product grid. */

.roles { max-width: var(--wide); margin: 0 auto; padding: 0 var(--gutter) 4rem; }
.role {
  display: grid;
  grid-template-columns: 15rem minmax(0, 1fr);
  gap: 0 3rem;
  padding: 2rem 0;
  border-top: 1px solid var(--rule);
}
.role:last-child { border-bottom: 1px solid var(--rule); }
.role-org {
  font-family: var(--display);
  font-weight: 700;
  font-size: 1.05rem;
  letter-spacing: -0.018em;
  margin: 0 0 0.2rem;
}
.role-unit { color: var(--ink-soft); font-size: 0.9rem; margin: 0 0 0.5rem; }
.role-dates {
  font-family: var(--mono);
  font-size: 0.72rem;
  color: var(--ink-faint);
  letter-spacing: 0.02em;
}
.role-title {
  font-family: var(--display);
  font-weight: 700;
  font-size: 1.15rem;
  letter-spacing: -0.02em;
  margin: 0 0 0.9rem;
}
.role ul { list-style: none; margin: 0; padding: 0; }
.role li {
  position: relative;
  padding-left: 1.15rem;
  margin-bottom: 0.55rem;
  color: var(--ink-soft);
  line-height: 1.55;
}
.role li::before {
  content: '';
  position: absolute;
  left: 0; top: 0.62rem;
  width: 6px; height: 6px;
  background: var(--zest-deep);
}
.role li strong { color: var(--ink); font-weight: 600; }

@media (max-width: 820px) {
  .role { grid-template-columns: 1fr; gap: 0.9rem; }
}

/* --- Featured / work cards: metrics only ----------------------------------
   No description line on the homepage teaser. The numbers are public, the
   framing is not. */

.feature-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
  gap: 1.5rem;
  max-width: var(--wide);
  margin: 0 auto;
  padding: 0 var(--gutter);
}
.feature {
  display: block;
  text-decoration: none;
  color: inherit;
  border: 1px solid var(--rule);
  border-top: 3px solid var(--forest);
  background: var(--white);
  padding: 1.5rem 1.5rem 1.3rem;
  transition: border-color 0.15s, transform 0.15s;
}
.feature:hover { transform: translateY(-2px); border-color: var(--ink-faint); }
.feature-year {
  font-family: var(--mono);
  font-size: 0.7rem;
  color: var(--ink-faint);
  display: block;
  margin-bottom: 0.5rem;
}
.feature-title {
  font-family: var(--display);
  font-weight: 700;
  font-size: 1.2rem;
  line-height: 1.18;
  letter-spacing: -0.022em;
  margin: 0 0 1.2rem;
}
.feature-metrics { list-style: none; margin: 0; padding: 0; }
.feature-metrics li {
  padding: 0.55rem 0;
  border-top: 1px solid var(--rule);
  display: flex;
  gap: 0.8rem;
  align-items: baseline;
}
.feature-metrics b {
  font-family: var(--display);
  font-weight: 700;
  font-size: 1.05rem;
  letter-spacing: -0.025em;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  flex: none;
  min-width: 5.2rem;
}
.feature-metrics span { font-size: 0.85rem; color: var(--ink-soft); line-height: 1.4; }
/* The cards used to sell on three numbers. They now carry one sentence of
   story instead, so the rules that separated the metric rows go with them and
   the type sits at reading size rather than caption size. */
.feature-line {
  margin: 0;
  padding-top: 0.9rem;
  border-top: 1px solid var(--rule);
  font-size: 0.92rem;
  line-height: 1.55;
  color: var(--ink-soft);
  text-wrap: pretty;
}

.feature-more {
  font-family: var(--mono);
  font-size: 0.75rem;
  color: var(--accent);
  display: inline-block;
  margin-top: 1rem;
}

/* --- Work index -----------------------------------------------------------
   Public. Title, one line, three metrics. The lock lives on the detail page,
   so this list is the shop window and has to sell on numbers alone. */

.wk-list { max-width: var(--wide); margin: 0 auto; padding: 0 var(--gutter); }
.wk-item {
  display: grid;
  grid-template-columns: 5rem minmax(0, 1.5fr) minmax(0, 1fr);
  gap: 0 2.5rem;
  padding: 2rem 0;
  border-top: 1px solid var(--rule);
  text-decoration: none;
  color: inherit;
  align-items: start;
}
.wk-item:last-of-type { border-bottom: 1px solid var(--rule); }
.wk-item:hover .wk-title { color: var(--accent); }
.wk-year { font-family: var(--mono); font-size: 0.75rem; color: var(--ink-faint); padding-top: 0.3rem; }
.wk-title {
  font-family: var(--display);
  font-weight: 700;
  font-size: 1.3rem;
  line-height: 1.16;
  letter-spacing: -0.025em;
  margin: 0 0 0.5rem;
  transition: color 0.15s;
}
.wk-sub { color: var(--ink-soft); margin: 0 0 0.8rem; font-size: 0.95rem; line-height: 1.55; }
.wk-tags { display: flex; flex-wrap: wrap; gap: 0.4rem; }
.wk-tags span {
  font-family: var(--mono);
  font-size: 0.65rem;
  letter-spacing: 0.02em;
  color: var(--forest);
  background: rgba(18,67,58,0.07);
  padding: 0.22rem 0.5rem;
}
.wk-metrics { list-style: none; margin: 0; padding: 0; }
.wk-metrics li { display: flex; gap: 0.7rem; align-items: baseline; padding: 0.3rem 0; }
.wk-metrics b {
  font-family: var(--display);
  font-weight: 700;
  font-size: 1rem;
  letter-spacing: -0.025em;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  flex: none;
  min-width: 6.5rem;
  text-align: right;
}
.wk-metrics span { font-size: 0.82rem; color: var(--ink-soft); line-height: 1.4; }

@media (max-width: 960px) {
  .wk-item { grid-template-columns: 4rem minmax(0,1fr); }
  .wk-metrics { grid-column: 2; margin-top: 0.8rem; padding-top: 0.6rem; border-top: 1px dashed var(--rule); }
  .wk-metrics b { text-align: left; }
}

/* The lock note, in her voice rather than the server's. */


/* --- Articles: a table of positions, not a grid of cards ------------------ */

.ar-list { max-width: var(--wide); margin: 0 auto; padding: 0 var(--gutter); }
.ar-item {
  display: grid;
  grid-template-columns: 5rem minmax(0, 1fr);
  gap: 0 2.5rem;
  padding: 1.8rem 0;
  border-top: 1px solid var(--rule);
  text-decoration: none;
  color: inherit;
}
.ar-item:last-of-type { border-bottom: 1px solid var(--rule); }
.ar-year { font-family: var(--mono); font-size: 0.75rem; color: var(--ink-faint); padding-top: 0.25rem; }
.ar-title {
  font-family: var(--mono);
  font-weight: 500;
  font-size: 0.95rem;
  color: var(--ink-soft);
  margin: 0 0 0.35rem;
  letter-spacing: 0.01em;
}
.ar-claim {
  font-family: var(--display);
  font-weight: 700;
  font-size: 1.35rem;
  line-height: 1.25;
  letter-spacing: -0.025em;
  margin: 0;
  max-width: 34ch;
  transition: color 0.15s;
}
.ar-item:hover .ar-claim { color: var(--accent); }
.ar-soon {
  font-family: var(--mono);
  font-size: 0.75rem;
  color: var(--ink-faint);
  padding: 1.8rem 0;
  border-top: 1px dashed var(--rule);
}

@media (max-width: 700px) {
  .ar-item, .wk-item { grid-template-columns: 1fr; gap: 0.5rem; }
}

/* --- Page heads (Work / Personal / Articles / Endorsements) ---------------- */

.pg-head {
  max-width: var(--wide);
  margin: 0 auto;
  padding: 3.5rem var(--gutter) 2.8rem;
}
.pg-head h1 {
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(2.2rem, 5vw, 3.4rem);
  line-height: 1.03;
  letter-spacing: -0.034em;
  margin: 0.4rem 0 1rem;
}
.pg-lede {
  font-size: 1.15rem;
  line-height: 1.55;
  color: var(--ink-soft);
  max-width: 38rem;
  margin: 0;
}
.pg-head .section-label { margin: 0; }

/* Section labels get a zest tick so they read as structure, not decoration. */
.section-label {
  max-width: var(--wide);
  margin: 3.5rem auto 1.2rem;
  padding: 0 var(--gutter);
  font-size: 0.72rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.pg-head .section-label { max-width: none; padding: 0; margin: 0; }

.roles-more {
  max-width: var(--wide);
  margin: 1.6rem auto 0;
  padding: 0 var(--gutter);
  font-family: var(--mono);
  font-size: 0.78rem;
}
.roles-more a { color: var(--accent); text-decoration: none; }
.roles-more a:hover { text-decoration: underline; }
.feature-more-link { margin-top: 1.8rem; padding-bottom: 1rem; }
.roles .roles-more { padding: 0; }

/* The How I lead panel, squared off and given the deeper forest. */
.profile-strip { background: var(--forest); }
.strip-inner { max-width: var(--wide); }
.strip-title { color: #fff; }
.strip-grid > div { border-left-color: var(--zest); }
.strip-grid h3 { color: #fff; }

/* --- Personal: chapters ---------------------------------------------------
   Header plus a short paragraph, then imagery at width. The captions stay,
   because the maths is the interesting part and it shows how she thinks.
   Numbered because it IS a sequence: code, then thread, then the machine that
   joins them, then the eye behind all three. */

.ch {
  max-width: var(--wide);
  margin: 0 auto;
  padding: 3.5rem var(--gutter) 1rem;
  border-top: 1px solid var(--rule);
}
.ch:first-of-type { border-top: 0; padding-top: 1rem; }
.ch-head { max-width: 40rem; margin-bottom: 2.4rem; }
.ch-num {
  font-family: var(--mono);
  font-size: 0.78rem;
  color: var(--forest);
  margin: 0 0 0.5rem;
  font-weight: 600;
}
.ch-head h2 {
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(1.7rem, 3.6vw, 2.3rem);
  line-height: 1.08;
  letter-spacing: -0.03em;
  margin: 0 0 0.8rem;
}
.ch-head p { color: var(--ink-soft); margin: 0; font-size: 1.05rem; line-height: 1.6; }

/* The chapter number and the chapter title were two elements saying one thing.
   The title now sits where the number was, as the section's only heading, and
   it keeps the size the old h2 carried rather than dropping to label size. */
.ch-head h2.ch-num {
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(1.7rem, 3.6vw, 2.3rem);
  line-height: 1.08;
  letter-spacing: -0.03em;
  color: var(--ink);
  margin: 0 0 0.8rem;
}
.ch-foot {
  font-family: var(--mono);
  font-size: 0.75rem;
  color: var(--ink-faint);
  margin: 1.8rem 0 0;
}
.ch-foot a { color: var(--accent); text-decoration: none; }

.ch-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(19rem, 1fr));
  gap: 2.6rem 2rem;
}
.ch-pair {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr));
  gap: 2rem;
}
.ch-photos {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: 1.5rem;
  align-items: start;
}

.pc { margin: 0; }
.pc img {
  width: 100%;
  height: auto;
  display: block;
  background: rgba(0,0,0,0.05);
  border: 1px solid var(--rule);
}
.pc.pc-wide img { aspect-ratio: auto; }
.ch-grid .pc img { aspect-ratio: 1 / 1; object-fit: cover; }
.pc figcaption { display: block; padding-top: 0.85rem; }
.pc-title {
  display: block;
  font-family: var(--display);
  font-weight: 700;
  letter-spacing: -0.018em;
  margin-bottom: 0.35rem;
}
.pc-body { display: block; color: var(--ink-soft); font-size: 0.93rem; line-height: 1.6; }
.pc-tag {
  display: inline-block;
  margin-top: 0.7rem;
  font-family: var(--mono);
  font-size: 0.66rem;
  letter-spacing: 0.03em;
  color: var(--forest);
  background: rgba(18,67,58,0.08);
  padding: 0.24rem 0.5rem;
}

/* --- Fixes ---------------------------------------------------------------- */

/* The principle rule was magenta and sat on the h3, not the div. Zest reads as
   the same family as the nav's active state, so the panel ties back. */
.strip-grid h3 { border-left-color: var(--zest); }
.strip-grid > div { border-left: 0; }

/* The section ground has to be on <html>, not just <body>: the body box stops
   at the footer and the html background shows through underneath it. */


/* One phrase in the h1 gets the zest. It is the only place on the homepage
   the highlight appears, which is what keeps it working. */
.hl {
  /* A real highlighter streak, not a rectangle. The colour still comes from
     --riso-light so the per-section tokens keep working; the SHAPE comes from
     an alpha mask, so the ends are chisel-angled, the edges wobble, the whole
     stroke leans a touch off horizontal, and the ink thins where the pen
     lifted. multiply is what makes it read as ink on paper rather than a
     block behind the type: the glyphs stay black and any descender from the
     line above darkens through it the way it would under a real pen. */
  background: var(--riso-light);
  mix-blend-mode: multiply;
  -webkit-mask-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 300 44' preserveAspectRatio='none'> <defs><linearGradient id='t' x1='0' y1='0' x2='1' y2='0'> <stop offset='0' stop-color='%23fff' stop-opacity='.42'/> <stop offset='.05' stop-color='%23fff' stop-opacity='.93'/> <stop offset='.42' stop-color='%23fff' stop-opacity='1'/> <stop offset='.88' stop-color='%23fff' stop-opacity='.94'/> <stop offset='1' stop-color='%23fff' stop-opacity='.34'/> </linearGradient></defs> <path d='M2.5,10.5 C44,6.8 88,9.2 136,6.4 C184,3.6 238,6.6 297.5,3.2 L299,36.4 C246,40.6 198,37.4 150,40.4 C104,43.2 52,39.6 4.5,42.4 Z' fill='url(%23t)'/> <path d='M10,14 C64,10.6 122,13 178,10' stroke='%23fff' stroke-opacity='.30' stroke-width='6' stroke-linecap='round' fill='none'/> <path d='M150,33 C198,30.4 244,33 292,29.8' stroke='%23fff' stroke-opacity='.22' stroke-width='5' stroke-linecap='round' fill='none'/> </svg>");
          mask-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 300 44' preserveAspectRatio='none'> <defs><linearGradient id='t' x1='0' y1='0' x2='1' y2='0'> <stop offset='0' stop-color='%23fff' stop-opacity='.42'/> <stop offset='.05' stop-color='%23fff' stop-opacity='.93'/> <stop offset='.42' stop-color='%23fff' stop-opacity='1'/> <stop offset='.88' stop-color='%23fff' stop-opacity='.94'/> <stop offset='1' stop-color='%23fff' stop-opacity='.34'/> </linearGradient></defs> <path d='M2.5,10.5 C44,6.8 88,9.2 136,6.4 C184,3.6 238,6.6 297.5,3.2 L299,36.4 C246,40.6 198,37.4 150,40.4 C104,43.2 52,39.6 4.5,42.4 Z' fill='url(%23t)'/> <path d='M10,14 C64,10.6 122,13 178,10' stroke='%23fff' stroke-opacity='.30' stroke-width='6' stroke-linecap='round' fill='none'/> <path d='M150,33 C198,30.4 244,33 292,29.8' stroke='%23fff' stroke-opacity='.22' stroke-width='5' stroke-linecap='round' fill='none'/> </svg>");
  -webkit-mask-size: 100% 100%;
          mask-size: 100% 100%;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  /* The pen overshoots the word at both ends, which is why the horizontal
     padding is bigger than it was and the margin pulls it back. */
  padding: 0.12em 0.30em 0.20em;
  margin: -0.12em -0.18em -0.20em;
  box-decoration-break: clone;
  -webkit-box-decoration-break: clone;
}

/* --- The pen, reusable ----------------------------------------------------
   The streak shape lives in two custom properties so the hero headline and
   the case-study titles are demonstrably the same pen rather than two
   lookalikes. Alternating A and B stops three highlighted titles in a row
   from looking rubber-stamped: real highlighting is never identical twice. */
:root {
  --pen-a: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 300 44' preserveAspectRatio='none'> <defs><linearGradient id='t' x1='0' y1='0' x2='1' y2='0'> <stop offset='0' stop-color='%23fff' stop-opacity='.42'/> <stop offset='.05' stop-color='%23fff' stop-opacity='.93'/> <stop offset='.42' stop-color='%23fff' stop-opacity='1'/> <stop offset='.88' stop-color='%23fff' stop-opacity='.94'/> <stop offset='1' stop-color='%23fff' stop-opacity='.34'/> </linearGradient></defs> <path d='M2.5,10.5 C44,6.8 88,9.2 136,6.4 C184,3.6 238,6.6 297.5,3.2 L299,36.4 C246,40.6 198,37.4 150,40.4 C104,43.2 52,39.6 4.5,42.4 Z' fill='url(%23t)'/> <path d='M10,14 C64,10.6 122,13 178,10' stroke='%23fff' stroke-opacity='.30' stroke-width='6' stroke-linecap='round' fill='none'/> <path d='M150,33 C198,30.4 244,33 292,29.8' stroke='%23fff' stroke-opacity='.22' stroke-width='5' stroke-linecap='round' fill='none'/> </svg>");
  --pen-b: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 300 44' preserveAspectRatio='none'> <defs><linearGradient id='u' x1='0' y1='0' x2='1' y2='0'> <stop offset='0' stop-color='%23fff' stop-opacity='.36'/> <stop offset='.07' stop-color='%23fff' stop-opacity='.9'/> <stop offset='.55' stop-color='%23fff' stop-opacity='1'/> <stop offset='.9' stop-color='%23fff' stop-opacity='.88'/> <stop offset='1' stop-color='%23fff' stop-opacity='.4'/> </linearGradient></defs> <path d='M3,4.2 C52,7.4 96,4.6 148,7.2 C198,9.8 244,6.8 297,9.6 L298.5,42.8 C240,39.4 192,42.6 144,40 C98,37.5 50,40.8 2,37.6 Z' fill='url(%23u)'/> <path d='M18,35.6 C72,38.6 128,36 186,38.6' stroke='%23fff' stroke-opacity='.26' stroke-width='6' stroke-linecap='round' fill='none'/> </svg>");
}

/* Case-study titles on the homepage get the same pen as the headline. The
   mask is on an inline span with box-decoration-break: clone, so a title that
   wraps gets a separate streak per line, which is what a person with a
   highlighter would actually produce. Keylines above the cards are black on
   all three now; the colour has moved to the titles. */
.feature-title .hl-pen {
  background: var(--riso-light);
  mix-blend-mode: multiply;
  -webkit-mask-image: var(--pen-a);
          mask-image: var(--pen-a);
  /* Titles are short, so the pen's tapered ends ate too much of a line like
     "Practice" and the streak read washed out. Overscanning the mask by 6%
     pushes most of the taper outside the box: the lean and the wobble stay,
     the ink stays solid across a two-word line. */
  -webkit-mask-size: 106% 100%;
          mask-size: 106% 100%;
  -webkit-mask-position: -3% 0;
          mask-position: -3% 0;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  padding: 0.06em 0.22em 0.14em;
  margin: -0.06em -0.12em -0.14em;
  box-decoration-break: clone;
  -webkit-box-decoration-break: clone;
}
.feature:nth-child(2) .feature-title .hl-pen {
  -webkit-mask-image: var(--pen-b);
          mask-image: var(--pen-b);
}
.feature:nth-child(3) .feature-title .hl-pen {
  -webkit-mask-position: -3% 60%;
          mask-position: -3% 60%;
  -webkit-mask-size: 106% 108%;
          mask-size: 106% 108%;
}
/* The title sat 1.2rem clear of the metrics; the streak needs a little more
   air under it or it crowds the first rule. */
.feature-title { line-height: 1.34; margin-bottom: 1.35rem; }


/* ===========================================================================
   6. White ground + the cog underlay — August 2026
   The pastel per-section washes are gone. Every page is white; identity comes
   from a large geared assembly bled off the edge, in flat bright colour. Cogs
   because the job is operations, and because a gear is a circle drawn by one
   rule, which is the same idea as everything on the Personal page.
   The teeth actually mesh: pitch radii sum to the centre distance and each
   driven gear is offset half a tooth, so it survives being looked at closely.
   =========================================================================== */

:root { --paper: #FFFFFF; --rule: #E7E9E6; --bg: #FFFFFF; --border: #E7E9E6; }
html { background: #FFFFFF; }
body { background: #FFFFFF; }

.cog-stage {
  position: relative;
  overflow: hidden;
}
.cogs {
  position: absolute;
  z-index: 0;
  pointer-events: none;
  height: auto;
}
.cog-stage > *:not(.cogs) { position: relative; z-index: 1; }


/* Slow counter-rotation. A geared assembly that does not turn is a logo; one
   that turns is a mechanism. Ratios are inverse to tooth count so the teeth
   stay meshed for the whole rotation. */
@keyframes spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .cog { animation: none !important; } }


/* --- Client logo row (mono, as asked) ------------------------------------- */

.logos {
  max-width: var(--wide);
  margin: 2.6rem auto 0;
  padding: 1.1rem var(--gutter);
}
.logos-inner {
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
  padding: 1.1rem 0;
  display: flex;
  gap: 2.4rem;
  flex-wrap: wrap;
  align-items: center;
}
.logos-inner span {
  font-family: var(--mono);
  font-size: 0.76rem;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.logos-inner .logos-lbl { color: var(--forest); font-weight: 600; }

/* --- Contact: who I want to hear from ------------------------------------- */

.hear {
  max-width: var(--wide);
  margin: 4rem auto 0;
  padding: 0 var(--gutter) 4rem;
}
.hear-inner {
  background: var(--forest);
  color: #fff;
  padding: 2.6rem 2.8rem;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
  gap: 2.6rem;
}
.hear h2 {
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(1.5rem, 3vw, 2rem);
  letter-spacing: -0.03em;
  line-height: 1.08;
  margin: 0 0 0.8rem;
  color: #fff;
}
.hear p { color: rgba(255,255,255,0.72); margin: 0 0 1.4rem; max-width: 26em; }
.hear-list { list-style: none; margin: 0; padding: 0; }
.hear-list li {
  padding: 0.7rem 0 0.7rem 1.2rem;
  border-top: 1px solid rgba(255,255,255,0.16);
  color: rgba(255,255,255,0.86);
  position: relative;
  line-height: 1.5;
}
.hear-list li:last-child { border-bottom: 1px solid rgba(255,255,255,0.16); }
.hear-list li::before {
  content: '';
  position: absolute; left: 0; top: 1.15rem;
  width: 6px; height: 6px; background: var(--zest);
}
.hear-cta {
  display: inline-block;
  margin-top: 1.4rem;
  background: var(--zest);
  color: var(--forest);
  font-family: var(--mono);
  font-weight: 600;
  font-size: 0.8rem;
  padding: 0.7rem 1.1rem;
  border-radius: 2px;
  text-decoration: none;
}
.hear-cta:hover { background: #fff; }
@media (max-width: 820px) { .hear-inner { grid-template-columns: 1fr; } }

/* --- Personal: everything on a three-column rhythm ------------------------
   The wide two-up images were the problem: a 1050px photo blown across half
   the page shows every one of its limitations. Three columns keeps each image
   at a size the source can actually support, and turns the chapter into a
   sequence you read left to right rather than two big slabs. */

.ch-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 2.4rem 1.8rem; }
/* A section holding four figures gets four columns rather than three-plus-a-
   widow. Keyed off the count itself, so it follows the content instead of
   needing a class remembered on the markup. */
.ch-grid:has(> .pc:nth-child(4)):not(:has(> .pc:nth-child(5))) {
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 2.4rem 1.5rem;
}
@media (max-width: 1000px) {
  .ch-grid:has(> .pc:nth-child(4)):not(:has(> .pc:nth-child(5))) {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}
.ch-grid .pc img { aspect-ratio: 4 / 5; object-fit: cover; }
.ch-narrow .ch-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.ch-narrow .ch-grid .pc { grid-column: span 1; }

@media (max-width: 1000px) { .ch-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 640px)  { .ch-grid { grid-template-columns: 1fr; } }

/* Photography: sixteen, four by four, captions small and quiet. Uniform 4:5
   crops so the grid reads as a contact sheet rather than a collage. */
.ph-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 1.1rem;
}
.ph { margin: 0; }
.ph img {
  width: 100%;
  aspect-ratio: 4 / 5;
  object-fit: cover;
  display: block;
  background: #F1F2F0;
}
.ph figcaption {
  font-family: var(--mono);
  font-size: 0.66rem;
  letter-spacing: 0.01em;
  color: var(--ink-faint);
  padding-top: 0.5rem;
  line-height: 1.4;
}
@media (max-width: 1000px) { .ph-grid { grid-template-columns: repeat(3, minmax(0,1fr)); } }
@media (max-width: 680px)  { .ph-grid { grid-template-columns: repeat(2, minmax(0,1fr)); } }

/* --- Cog placement -------------------------------------------------------
   The cogs never touch type: the copy is capped short of them and the
   assembly is cropped by the frame rather than placed inside it. */

.hero.cog-stage .hero-banner h1,
.hero.cog-stage .hero-intro,
.hero.cog-stage .hero-bio { max-width: 44rem; }
.hero.cog-stage .hero-banner h1 { max-width: 20ch; }
.hero.cog-stage .hero-stat-row { max-width: 58rem; }

/* ===========================================================================
   7. Monochrome + riso — August 2026
   The site is black, white and grey. Colour appears in exactly three places:
   the cogs, the one highlighted phrase in the h1, and hover/focus states.
   Each section wears one riso colour, so the cogs and the links on a page are
   always the same hue and you can tell where you are without a tint behind
   the content.
   =========================================================================== */

/* The legacy aliases have to be re-declared on <body>, not left on :root.
   A custom property that references another is substituted at the element
   where it is DECLARED, so `--zest: var(--riso-light)` sitting on :root froze
   to the :root default and every section inherited the home page's green —
   the CTA on Endorsements came out lime instead of amber. Declared here, it
   resolves against the same element the section override lands on. */
body { --zest: var(--riso-light); --zest-deep: var(--riso-ink); --coral: var(--riso-ink); }

/* Taken from the reference: saturated, flat, slightly acid — not pastels.
   --riso-light IS that colour, used as a fill behind something else (the
   cogs, the highlight block). --riso-ink is the same hue pushed dark enough
   to clear 4.5:1 on white, because --accent resolves to it and --accent is
   used as TYPE in dozens of places. Two tiers, one hue, no contrast failures. */
body.sec-home     { --riso-light: #F7E93C; --riso-wash: #FBF9D9; --riso-ink: #756D09; } /* yellow  */
body.sec-work     { --riso-light: #45B6F2; --riso-wash: #E4F5FE; --riso-ink: #0E6B9E; } /* sky     */
body.sec-personal { --riso-light: #E85EC8; --riso-wash: #FCE8F7; --riso-ink: #A01A80; } /* magenta */
body.sec-articles { --riso-light: #F0872D; --riso-wash: #FDEEE0; --riso-ink: #9E4E07; } /* orange  */
body.sec-people   { --riso-light: #2EB84A; --riso-wash: #E3F7E8; --riso-ink: #14762C; } /* green   */
/* CV rides the sec-home layout but takes its own ink. Declared after sec-home
   so it wins on equal specificity; cv.html carries both classes. */
body.sec-cv       { --riso-light: #F15060; --riso-wash: #FDE7E9; --riso-ink: #A02033; } /* red     */

/* --- Cogs -----------------------------------------------------------------
   Regenerated so the geometry is right rather than nearly right. One module
   across every gear, centre distances equal to the sum of the pitch radii,
   and each driven gear's teeth pre-rotated in the path data to the phase that
   lands its gaps on its driver's teeth. Short fat teeth with rounded tips, a
   thick rim and an open hub, after the Soma track cog.

   The bug this replaces: `transform-box: view-box; transform-origin: 0 0`
   resolved the origin to the viewBox's top-left corner, not to each gear's
   own centre, so the driven gears ORBITED that corner instead of spinning in
   place — which is why they drifted across each other. Each path is drawn
   around its own local origin, and the placement translate lives on an outer
   <g>, so fill-box/center is the correct pair here. */
.cog {
  transform-box: fill-box;
  transform-origin: center;
}
.cog path { fill: var(--riso-light); }
.cog.c2 path { fill: var(--riso-light); }
.cog.c3 path { fill: var(--ink); opacity: 0.16; }

/* Angle2 = -Angle1 * (N1/N2), expressed as CSS periods: make each period
   proportional to that gear's tooth count and the ratio falls out exactly.
   Hero is 34/20/14 teeth at 204/120/84s (all 6s per tooth); interior pages
   are 20/14 at 160/112s (8s per tooth). Direction alternates at every mesh,
   because two meshed gears cannot turn the same way. Get any one of these
   numbers wrong and the teeth drift out of phase over the first few minutes,
   which is the failure you only notice if you leave the page open. */
.cogs-hero .c1 { animation: spin 204s linear infinite; }
.cogs-hero .c2 { animation: spin 120s linear infinite reverse; }
.cogs-hero .c3 { animation: spin  84s linear infinite; }
.cogs-page .c1 { animation: spin 160s linear infinite; }
.cogs-page .c2 { animation: spin 112s linear infinite reverse; }

/* Placement. One definition each, not four.

   `top` is in rem, deliberately. It used to be a percentage, and a percentage
   top resolves against the HEIGHT of the containing block — which is the page
   head, and the page head is a different height on every page because the
   intro copy is a different length. So the assembly sat at a different height
   on Work than on Personal than on Endorsements, and it visibly jumped as you
   moved between them. `right` and `width` can stay as percentages: those
   resolve against width, which is the same everywhere. */
/* right: 0 on both, so the assembly sits flush against the right edge of the
   page and nothing is sliced off. A negative right bled the outermost gear
   past the viewport, which read as a crop rather than as a bleed — and it was
   a different crop on the home page than on the interior ones. */
.cogs-hero { top: 1.5rem; right: 0; width: 33%; min-width: 380px; }
.cogs-page { top: -5.5rem; right: 0; width: 24%; min-width: 260px; opacity: 0.72; }

@media (max-width: 1200px) {
  .cogs-hero { top: -1rem; right: 0; width: 40%; min-width: 300px; opacity: 0.8; }
  .cogs-page { top: -4.5rem; right: 0; width: 28%; min-width: 210px; }
}
@media (max-width: 820px) {
  .cogs-hero { top: -1rem; right: -18%; width: 72%; min-width: 0; opacity: 0.45; }
  .cogs-page { display: none; }
}

/* --- Monochrome component corrections ------------------------------------
   A handful of components carried meaning in their colour rather than in
   their form. Those need a mono equivalent or the meaning is simply lost. */

/* Links were magenta on white; magenta is gone, so form has to carry the
   affordance instead: an underline at rest, riso on hover.

   Scoped to links INSIDE prose, not to every link in <main>. Several listings
   wrap a whole row in a single <a>, so the broad selector underlined the
   title, the summary, the year, the tags and every stat in the row at once.
   `p a` only matches a link sitting inside a paragraph, which is the case
   this rule is actually for. */
main p a, main li a, main dd a, main .end-quote a, main figcaption a {
  color: var(--ink);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
  text-decoration-color: var(--ink-faint);
  transition: color 0.18s, text-decoration-color 0.18s;
}
main p a:hover, main li a:hover, main dd a:hover,
main .end-quote a:hover, main figcaption a:hover {
  color: var(--riso-ink);
  text-decoration-color: var(--riso-ink);
}

/* Block links — a whole listing row wrapped in one <a> — get their hover on
   the title alone, so the row lifts without the body copy changing colour. */
.wk-item:hover .wk-title,
.art-item:hover .article-title,
a:hover > .work-title { color: var(--riso-ink); }
.wk-item .wk-title, .art-item .article-title { transition: color 0.16s; }

/* Tags were a magenta wash. Mono outline, riso only on hover. */
/* No border, no background. The base .tag rule sets `border: 0` and no
   padding at all, because these were never pills — they are inline uppercase
   labels separated by a middot (see .tag:not(:last-child)::after). Adding a
   border here put a hairline box tight against the glyphs with the middot
   still hanging off the end. Colour and hover carry it instead. */
.tag { background: transparent; border: 0; padding: 0; color: var(--ink-soft); }
/* On the case studies the tags sit inside a .cs-meta-item, and
   `.cs-meta-item span` is specificity (0,1,1) against plain `.tag` at (0,1,0)
   — so it won and the tags came out near-black. Matching that weight here. */
.cs-tags .tag { color: var(--ink-soft); }
.tag:hover, .cs-tags .tag:hover { color: var(--riso-ink); }

/* Focus is the one state that must never depend on hue alone. */
:focus-visible {
  outline: 2px solid var(--riso-ink);
  outline-offset: 2px;
}

/* --- Client logo row ------------------------------------------------------
   Marks are greyscale and dimmed so the row reads as one texture rather than
   seven competing brand colours; each lifts to full black on hover. */
.logos-inner { gap: 2.8rem 3rem; }
/* The marks arrive already greyscaled to a single #a6a6a6, so nothing here
   recolours them — no grayscale(), no brightness(). Two of the six carry
   white shapes and only one of those is disposable: the BBC file had a
   full-bleed white plate (removed, it was forcing a square aspect), while
   HSBC's white IS the hexagon's counters. Any filter that maps white to ink
   would fill those counters in, so the rest/hover state is opacity only.

   Sizes are set from each mark's MEASURED ink bounds, not its file box.
   Three of the files were padded — Barclays sat in a 1.5:1 box while the
   lockup is 5.93:1 — so their viewBoxes were retightened first. Heights are
   then nudged by aspect: a very long wordmark set to the same height as a
   compact one dominates the row, so it comes down slightly, and the shortest
   comes up. Matching on optical weight, not on measured height. */
/* Centred, label included: the row reads as one credential band rather than
   a left-aligned list that stops short of the page. */
.logos-inner { gap: 1.5rem 2.9rem; justify-content: center; }
.logos-inner img.logo {
  height: 1.4rem;          /* the base; per-mark nudges below */
  width: auto;
  display: block;
  opacity: 0.82;
  transition: opacity 0.18s;
}
.logos-inner img.logo:hover { opacity: 1; }

.logos-inner img.lg-hsbc     { height: 1.45rem; }  /* 3.71:1, symbol + wordmark */
.logos-inner img.lg-barclays { height: 1.30rem; }  /* 5.93:1 */
.logos-inner img.lg-adobe    { height: 1.40rem; }  /* 3.97:1, symbol + wordmark */
.logos-inner img.lg-bbc      { height: 1.10rem; }  /* 8.48:1 — the long outlier  */
.logos-inner img.lg-cath     { height: 1.40rem; }  /* 4.09:1 */
.logos-inner img.lg-thg      { height: 1.55rem; }  /* 3.14:1 — the compact one   */

/* Between ~950 and ~1250 the seven items overflow by a little and drop ONE
   logo to a second line on its own. Tightening the gap through that band
   keeps the row intact rather than leaving a widow. */
@media (max-width: 1250px) and (min-width: 1051px) {
  .logos-inner { gap: 1.3rem 1.9rem; }
}
@media (max-width: 1050px) and (min-width: 901px) {
  .logos-inner { gap: 1.2rem 1.15rem; }
  .logos-inner img.logo { height: 1.25rem; }
  .logos-inner img.lg-hsbc { height: 1.3rem; }
  .logos-inner img.lg-bbc  { height: 0.98rem; }
  .logos-inner img.lg-thg  { height: 1.38rem; }
}
@media (max-width: 900px) {
  .logos-inner { gap: 1.1rem 1.9rem; justify-content: center; }
  .logos-inner img.logo { height: 1.15rem; }
  .logos-inner img.lg-hsbc { height: 1.2rem; }
  .logos-inner img.lg-bbc  { height: 0.92rem; }
  .logos-inner img.lg-thg  { height: 1.3rem; }
}

/* --- Hero availability ----------------------------------------------------
   Was a pill. It is now the same weight as "London" and sits beside it, so
   the eyebrow reads as one line of metadata rather than a line plus a badge. */
.hero-available {
  background: none;
  border: 0;
  border-radius: 0;
  padding: 0;
  margin: 0;
  color: inherit;
  font: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  white-space: normal;
}
.hero-available::before { content: none; }

/* --- Headline ------------------------------------------------------------
   line-height was 1.02, which is fine for plain type and wrong the moment a
   line gets a background. The highlight block on line two was painting over
   the descenders of line one — the g in "Design" lost its tail. The leading
   has to clear the highlight's box, not just the glyphs. */
.hero.cog-stage .hero-banner h1 { line-height: 1.24; }
.hero.cog-stage .hero-banner h1 em { color: var(--ink); font-style: normal; }

/* --- Endorsement filter ---------------------------------------------------
   Real buttons rather than styled spans, so keyboard and screen readers get
   it for free. Selected state is carried by weight and a filled ground, not
   by hue alone — the page is monochrome and the riso is only ever a second
   signal, never the only one. */

.end-filter {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  max-width: var(--wide);
  margin: 1.6rem auto 0;
  padding: 0 var(--gutter);
}
.end-f {
  font-family: var(--mono);
  font-size: 0.72rem;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ink-soft);
  background: transparent;
  border: 1px solid var(--rule);
  border-radius: 2px;
  padding: 0.5rem 0.85rem;
  cursor: pointer;
  transition: border-color 0.16s, color 0.16s, background 0.16s;
}
.end-f:hover { border-color: var(--riso-ink); color: var(--riso-ink); }
.end-f.is-on {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--white);
  font-weight: 600;
}
.end-f.is-on .end-f-n { color: var(--riso-light); }
.end-f-n {
  font-variant-numeric: tabular-nums;
  color: var(--ink-faint);
  margin-left: 0.35em;
}
.end-count {
  font-family: var(--mono);
  font-size: 0.72rem;
  letter-spacing: 0.04em;
  color: var(--ink-faint);
  max-width: var(--wide);
  margin: 0.9rem auto 0;
  padding: 0 var(--gutter);
}
.end-item[hidden], .end-group-label[hidden] { display: none; }

@media (max-width: 700px) {
  .end-filter { gap: 0.4rem; }
  .end-f { font-size: 0.66rem; padding: 0.42rem 0.62rem; }
}

/* On a narrow screen the forced break in the headline puts "Design functions,"
   on a line of its own, which is wider than the viewport. Drop the break and
   let it set naturally instead. */
@media (max-width: 560px) {
  .hero.cog-stage .hero-banner h1 { font-size: clamp(1.85rem, 8.2vw, 2.4rem); }
  .hero.cog-stage .hero-banner h1 br { display: none; }
}


/* --- Keyline under every page head ---------------------------------------
   Work and Articles appeared to have a rule under the intro; they did not.
   It was the border-top of the first row in the list below, which meant
   Personal, Endorsements and the CV — none of which open with a bordered
   list — had nothing. The line belongs to the page head, so it lives here.

   Drawn as a pseudo-element rather than a border-bottom because the head is
   padded by the gutter, and a border would run the full width of the padding
   box and overshoot the content rules below it. */
.pg-head, .end-header { position: relative; }
.pg-head::after, .end-header::after {
  content: "";
  position: absolute;
  left: var(--gutter);
  right: var(--gutter);
  bottom: 0;
  border-bottom: 1px solid var(--rule);
}
/* ...and the first list row drops its own border, or the two stack up. */
.wk-list > .wk-item:first-child,
.ar-list > .ar-item:first-child { border-top: 0; }


/* --- CV: the two rules at the top come off -------------------------------
   The cog assembly sits in the top-right of the CV, and both of these ran
   straight through it. The head rule is simply not drawn here, and the first
   section label drops its underline — the ones further down the page keep
   theirs, since nothing overlaps them. */
.cv-header::after { content: none; }
.cv-body .cv-section:first-child .cv-section-label { border-bottom: 0; padding-bottom: 0; }

/* --- Home page section heads ---------------------------------------------
   "Recent experience" and "Selected work" were 0.72rem mono labels, while
   "How I lead" was a 1.75rem heading. Same rank in the page, so same
   treatment — but set in ink, because .strip-title is white for the dark
   panel it sits on. */
.home-head {
  max-width: var(--wide);
  margin: 4.5rem auto 1.8rem;
  padding: 0 var(--gutter);
}
.home-title {
  font-family: var(--display);
  font-weight: 700;
  font-size: 1.75rem;
  letter-spacing: var(--display-track);
  color: var(--ink);
  margin: 0 0 0.5rem;
}
.home-intro {
  font-size: 0.95rem;
  line-height: 1.7;
  color: var(--ink-soft);
  max-width: var(--reading);
  margin: 0;
}

/* --- Hero: single reading column ----------------------------------------
   Was a three-column deck with content-tracked widths (1.05fr 0.93fr 1.02fr),
   measured Sept 2026 against copy running roughly 78/74/67 words. The blurb
   was cut to 120 words in three short paragraphs, so the deck no longer had
   enough copy to fill three columns and the tracked widths were tuned to
   sentences that no longer exist. Set as one reading-measure column instead,
   matching the .home-intro treatment under the section titles further down
   the page. Note this reopens the dead strip on the right below the cogs
   that the three-column deck was built to close. */
.hero.cog-stage .hero-deck {
  display: block;
  max-width: var(--reading);
  margin-top: 2.2rem;
}
.hero.cog-stage .hero-deck .hero-bio { max-width: none; margin: 0; }
.hero.cog-stage .hero-deck .hero-bio + .hero-bio { margin-top: 1.15rem; }

/* Six stats across one row. At the row's full display size "Standardising"
   is the one word that overruns a sixth-width column, so the number type
   steps down to 1.45rem here. Measured, not guessed: 1.75rem overflows, 1.5
   clears, 1.45 leaves headroom for the real Familjen Grotesk metrics. */
.hero.cog-stage .hero-stat-row {
  max-width: var(--wide);
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: 1.75rem 1.5rem;
}
.hero.cog-stage .hero-stat .num { font-size: 1.45rem; }

/* Labels stepped down 10% from the global 0.75rem, to 0.675rem. Scoped to the
   homepage hero only, so the stat labels on the other pages are untouched.
   Sept 2026. */
.hero.cog-stage .hero-stat .label { font-size: 0.675rem; }

/* The row carries a rule on its bottom edge and nothing on its top, so equal
   box padding reads unequal: 79px of white above the words against 38px below
   them, down to the rule. Measured off the render, not eyeballed. Drop the
   row's own top padding and tighten the banner above it, so the words sit
   centred in the band the eye actually sees. */
.hero.cog-stage .hero-stat-row { padding-top: 0; }
.hero.cog-stage .hero-banner { margin-bottom: 1.85rem; }

@media (max-width: 1100px) {
  .hero.cog-stage .hero-stat-row { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  /* Three across is wide again, so the step-down is no longer needed. */
  .hero.cog-stage .hero-stat .num { font-size: 1.75rem; }
}
@media (max-width: 760px) {
  .hero.cog-stage .hero-stat-row { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .home-head { margin-top: 3rem; }
}

/* --- CV: employer marks --------------------------------------------------
   Sized in em, not rem, so the mark tracks the company line's own type size
   at every breakpoint. The two lockups have very different aspect ratios
   (HSBC 3.71:1, Barclays 5.93:1), so a shared height would leave Barclays
   nearly twice as long — its height comes down to compensate. Marks are
   aria-hidden with empty alt: the company name is right beside them, and a
   label would make a screen reader say the employer twice. */
.cv-role-company {
  display: flex;
  align-items: center;
  gap: 0.55em;
}
.cv-logo {
  height: 1.37em;        /* 1.05em + 30% */
  width: auto;
  flex: 0 0 auto;
  opacity: 0.85;
}
/* Adobe is 3.97:1, close to HSBC's 3.71:1, so it takes the base height.
   Barclays is 5.93:1 and would run half again as long at the same height. */
.cv-logo-barclays { height: 1.07em; }   /* 0.82em + 30% */

/* The company name that used to sit beside the mark is gone, so the alt text
   now carries it — that is the only thing telling a screen reader (or a
   failed image load) who the employer was. The three Barclays roles have no
   text in the line at all. */
.cv-role-company span { min-width: 0; }

/* --- CV: the division sits with the role, not under it ---------------------
   The employer division used to be its own line under the title, set in the
   accent colour, which gave four of the seven roles a coloured sub-line the
   Barclays roles did not have. The page read as two different templates. The
   division now joins the role title as a lighter clause, and every
   .cv-role-company is just the logo, so all seven roles are the same shape. */
.cv-role-title .cv-role-div {
  font-size: 0.92em;
  font-weight: 400;
  color: var(--ink-soft);
  letter-spacing: 0;
}
.cv-role-title .cv-role-div::before {
  content: ", ";
  color: var(--ink-soft);
}


@media print {
  .cv-logo { opacity: 1; }
}

/* --- Nav: room for the longer labels -------------------------------------
   "Work / Personal / Articles / Endorsements" became "Selected Work /
   Personal Creativity / Design Articles / Endorsements & Praise", which took
   the link block from 575px to 883px. At 1100px that left 9px between the
   links and the name, and below ~600px it pushed the page into horizontal
   scroll. The labels are the point, so the type gives way instead: the row
   steps down through two breakpoints, and below 900px it wraps to a second
   line rather than colliding with the wordmark. */
@media (max-width: 1280px) {
  .nav-links { gap: 1.7rem; }
  .nav-links a { font-size: 0.74rem; }
  .nav-links a.nav-cta { padding: 0.48rem 0.8rem; }
}
@media (max-width: 1080px) {
  .nav-links { gap: 1.25rem; }
  .nav-links a { font-size: 0.7rem; }
  .nav-links a.nav-cta { padding: 0.44rem 0.7rem; }
}
@media (max-width: 900px) {
  nav {
    flex-wrap: wrap;
    row-gap: 0.5rem;
    padding-top: 0.7rem;
    padding-bottom: 0.7rem;
    height: auto;
  }
  .nav-name { flex: 0 0 100%; }
  .nav-links { flex-wrap: wrap; gap: 0.8rem 1.5rem; }
}

/* --- Hero: vertical rhythm below the deck --------------------------------
   Three problems, measured rather than eyeballed:

   1. The deck had 2.2rem of air above it and none below, so the keyline under
      the paragraphs sat hard against the last line of type while the one above
      breathed. Same value both sides now.

   2. .hero-meta was bounded by a border top AND bottom, and .logos-inner adds
      another pair — four hairlines inside ~250px. The meta row's bottom border
      is the redundant one: the logo band's own top border already separates
      the two, so that is the line that goes.

   3. The logo row carried 2.6rem of margin on top of its own padding, leaving
      83px of blank between the LinkedIn links and the marks. Its padding is
      enough on its own. */

.hero.cog-stage .hero-deck { margin-bottom: 2.2rem; }
.hero-meta { border-bottom: 0; }
.logos { margin-top: 0; padding-top: 0; }


/* --- Cog hover ------------------------------------------------------------
   The assembly needs to receive pointer events for the hover speed-up in
   cogs.js. It sits at z-index 0 with every piece of content at z-index 1, so
   anything on top of it still takes the event first -- text stays selectable
   and links stay clickable. Only the bare areas of the stage reach the SVG.
   The paths themselves stay non-interactive so the cursor does not flicker as
   teeth rotate under it; the SVG's own box is the target. */
.cogs { pointer-events: auto; }
.cogs * { pointer-events: none; }
.cogs { cursor: default; }

/* --- Figures that must not be cropped ------------------------------------
   .pc images are cover-cropped to 4:5 so a row of photographs lines up. That
   is wrong for a figure whose content IS the image: a written plan at 1.10:1
   and a code screenshot at 0.68:1 both lose real content to that crop. These
   are contained instead, on a tint so the letterboxing reads as deliberate
   rather than as a broken image. */
.pc-full img {
  object-fit: contain !important;
  background: var(--riso-wash);
  padding: 0.5rem;
}

/* The plan is cropped rather than contained: filled to the frame and anchored
   to its left edge, so the crop takes from the right and the left-hand side of
   the sheet stays whole. */
.pc-crop-left img {
  object-fit: cover !important;
  object-position: left center;
  background: none;
  padding: 0;
}

/* --- The home headline was the only heading in the wrong face -------------
   A grouped rule up at line ~3610 lists `.hero-banner h1` and sets
   font-family: var(--sans). That is specificity (0,1,1). The generic
   `h1, h2, h3 { var(--display) }` further down is only (0,0,1), so it never
   won -- and the home h1 rendered in Inter while "Selected work", "How I lead"
   and every other heading rendered in Familjen Grotesk. Same weight as the
   offending rule, declared later, so this one takes it. */
.hero-banner h1 { font-family: var(--display); }

/* --- CV: the last rule at the top of the page ---------------------------- */
.cv-contact { border-top: 0; }

/* --- Keep line one in front of the tape ----------------------------------
   The highlight on line two is a background on an inline element, and it is
   painted after line one because it comes later in the document. The tail of
   the "g" in Design and the comma after "functions" hang down into that band,
   so the tape covered them.

   Raising line one into its own stacking context puts the glyphs in front of
   the tape instead of behind it. Done on the line rather than as an absolutely
   positioned pseudo-element on .hl, because the highlight is allowed to wrap
   onto two lines on a narrow screen and an absolute box would only cover the
   first of them. */
.hero-banner h1 .hl-front {
  position: relative;
  z-index: 1;
}

/* Foundations strip: same row component, set back so it reads as context
   rather than as a fifth flagship. */
.wk-strip .wk-item { opacity: 0.86; }
.wk-strip .wk-title { font-size: 1.15rem; }

/* --- "What are you building?" -------------------------------------------
   Rebuilt from the newsletter graphic as real text rather than embedded as a
   6MB screenshot: it stays selectable and searchable, scales without
   blurring, and costs bytes instead of megabytes.

   The formatting is taken from the source rather than invented. Sampling the
   original gives a warm light-grey ground of rgb(227,228,222), dark text, no
   card containers around the quotes, and a soft vignette toward the edges --
   so the quotes sit directly on the panel with a hanging quote mark, which is
   what the OCR bounding boxes showed (first line indented, continuations
   flush).

   Set in Univers where it is installed, falling back to the Helvetica
   neo-grotesque family it belongs to. Deliberately NOT the site's Familjen
   Grotesk or Inter: this is a reproduced artefact, and it should read as one
   rather than as more page. */
.build-grid {
  --panel: #E3E4DE;
  font-family: 'Univers', 'Univers LT Std', 'UniversLTStd', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  margin: 2.6rem 0 0.6rem;
  padding: 2.6rem 2.6rem 2.4rem;
  border: 0;
  /* Fallback first: if a browser can't parse color-mix the layered value below
     is dropped whole, and this keeps the panel from falling back to nothing. */
  background: var(--panel);
  background:
    /* The colour, kept gentle: the section's riso wash drifting across the
       diagonal, so the panel picks up the page without becoming a coloured box. */
    linear-gradient(135deg,
      color-mix(in srgb, var(--riso-light) 20%, transparent) 0%,
      color-mix(in srgb, var(--riso-light)  7%, transparent) 45%,
      transparent 78%),
    radial-gradient(120% 90% at 30% 20%, rgba(255,255,255,0.55) 0%, rgba(255,255,255,0) 60%),
    radial-gradient(90% 80% at 95% 100%, rgba(0,0,0,0.16) 0%, rgba(0,0,0,0) 65%),
    var(--panel);
  color: #14181A;
}
.build-grid figcaption { display: block; margin-bottom: 2.2rem; }
.build-q {
  font-family: inherit;
  font-weight: 700;
  font-size: 1.7rem;
  letter-spacing: -0.015em;
  color: #14181A;
  margin: 0 0 0.7rem;
}
.build-sub {
  font-size: 0.95rem;
  line-height: 1.55;
  color: #3A3F41;
  max-width: 46rem;
  margin: 0;
}
.build-grid ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1.9rem 3rem;
}
/* No boxes: the source sets the quotes straight on the panel, each opening
   with its emoji and a typed quote mark. */
.build-grid li {
  position: relative;
  font-size: 0.98rem;
  line-height: 1.55;
  color: #14181A;
  background: none;
  border: 0;
}
.build-grid li strong { font-weight: 700; color: inherit; }

/* The emoji hangs just clear of the quote mark, matching the newsletter. It
   is decorative, so it is hidden from assistive tech and the quote itself
   carries the meaning. */
.build-grid .build-e {
  margin-right: 0.4em;
  font-size: 1.05em;
  font-family: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
  line-height: 1;
}
@media (max-width: 760px) {
  .build-grid { padding: 1.6rem 1.4rem 1.4rem; }
  .build-grid ul { grid-template-columns: 1fr; gap: 1.4rem; }
  .build-q { font-size: 1.4rem; }
}

/* ---------------------------------------------------------------------------
   Image grids: level pairs
   .cs-image carries margin: 28px 0 for standalone images. When that class ends
   up on an image inside a grid, the margin offsets it against its neighbour and
   the pair no longer sits level. Neutralise the margin inside grids and align
   to the top so a residual height difference shows at the bottom rather than
   knocking both images out of register.
   --------------------------------------------------------------------------- */
.cs-image-grid { align-items: start; }
.cs-image-grid img { margin: 0; }

/* ---------------------------------------------------------------------------
   Case-study pull quotes
   Deliberately borrows the endorsements page's language — accent keyline, sans
   quote, quiet attribution — so a quote reads as the same species of evidence
   wherever it appears. --accent resolves per section, so these pick up the
   page's riso ink without hard-coding a colour.
   --------------------------------------------------------------------------- */
.cs-quotes {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px 40px;
  align-items: start;
  margin: 36px 0 28px;
}
.cs-quote {
  margin: 0;
  padding-left: 24px;
  /* --riso-ink, not --accent: --accent is declared in :root, where var(--riso-ink)
     substitutes the root default and freezes, so it never picks up the section
     class on <body>. Naming --riso-ink here resolves at this element instead,
     which is what actually inherits the section colour. */
  border-left: 3px solid var(--riso-ink);
}
.cs-quote p {
  font-size: 1.0625rem;
  line-height: 1.7;
  color: var(--ink);
  margin: 0 0 16px;
}
.cs-quote cite {
  display: block;
  font-style: normal;
  line-height: 1.45;
}
.cs-quote-person {
  display: block;
  font-size: 0.9375rem;
  font-weight: 600;
  color: var(--ink);
}
.cs-quote-role {
  display: block;
  font-size: 0.8125rem;
  color: var(--ink-faint);
}
@media (max-width: 760px) {
  .cs-quotes { grid-template-columns: 1fr; gap: 28px; }
}

/* ---------------------------------------------------------------------------
   Chapter eyebrows
   The section label was --ink-faint, which sat quieter than the body text it
   introduced. It now carries the section's riso ink so a chapter break reads as
   a break. --riso-ink, not --accent: --accent is declared in :root, where
   var(--riso-ink) substitutes the root default and freezes, so it never picks up
   the section class on <body>. Named here, it resolves per page.
   All five section colours clear 4.5:1 on white (5.10 lime, 5.81 sky, 7.11
   magenta, 5.92 orange, 5.74 green), so the label stays legible at 0.75rem.
   --------------------------------------------------------------------------- */
.cs-section-label,
p.cs-section-label,
h2.cs-section-label,
.cs-section .cs-section-label {
  color: var(--riso-ink);
}

/* The section labels are <h2> now: the prose headings came out and the page
   still needs a heading outline for anyone navigating by structure. The class
   carries the whole look, but an h2 arrives with its own top margin and font
   size, so both are neutralised here. Nothing changes visually. */
.cs-section h2.cs-section-label {
  margin-top: 0;
}

/* ---------------------------------------------------------------------------
   CX Standards
   The four principles as page content rather than a screenshot: the source is a
   photograph of a PDF on a monitor, which is unreadable at column width and
   invisible to search and screen readers. Set as a 2x2 of principles, each in
   the customer's voice. --riso-ink, not --accent (see the eyebrow note above).
   --------------------------------------------------------------------------- */
.cx-standards {
  margin: 2.2rem 0 0.6rem;
  padding: 0;
  border-top: 2px solid var(--riso-ink);
}
.cx-standards figcaption {
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--riso-ink);
  padding: 0.75rem 0 1.4rem;
}
.cx-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1.9rem 2.6rem;
}
.cx-card h3 {
  font-size: 1.15rem;
  font-weight: 600;
  color: var(--riso-ink);
  margin: 0 0 0.7rem;
  padding-bottom: 0.5rem;
  border-bottom: 1px solid var(--rule);
}
.cx-card ul { list-style: none; margin: 0; padding: 0; }
.cx-card li {
  font-size: 0.9375rem;
  line-height: 1.55;
  color: var(--ink);
  padding: 0.4rem 0;
  background: none;
  border: 0;
}
.cx-card li + li { border-top: 1px solid var(--rule); }
.cx-card li strong { font-weight: 600; color: var(--ink); }
@media (max-width: 760px) {
  .cx-grid { grid-template-columns: 1fr; gap: 1.5rem; }
}

/* Aside note inside a case study section: a side point that shouldn't interrupt the main narrative */
/* Captions never rendered at caption size. `.cs-image-caption` is specificity
   0,1,0 and `.cs-section p` is 0,1,1, so every caption on every case study has
   been inheriting body copy size and reading as another paragraph. This is the
   first declaration specific enough to win. 0.65rem is 20% down on the 0.8125rem
   the old rule intended. */
.cs-section p.cs-image-caption,
.cs-section .cs-image-caption {
  font-size: 0.65rem;
  line-height: 1.6;
}

.cs-section p.cs-note {
  font-size: 0.9375rem;
  color: var(--ink-soft);
  line-height: 1.7;
  border-left: 2px solid var(--rule, var(--ink-faint));
  padding-left: 1rem;
  margin-top: 1.75rem;
}

/* Card 2's title wraps to two lines and its sentence runs longest, so the
   three "Read the case study" links stopped agreeing with each other once the
   metric rows went. Column flex with an auto top margin pins them to the
   bottom edge, which is where the eye expects them. Has to sit after the
   earlier .feature-more rule, which sets a fixed margin-top and would
   otherwise win on source order. */
.feature { display: flex; flex-direction: column; }
.feature-more { margin-top: auto; padding-top: 1.1rem; }

/* --- Articles list: the hierarchy was inverted ---------------------------
   The title was set in small mono and the one-line claim in 1.35rem display
   bold, so the summary shouted and the headline whispered. The Work list
   next door already does this correctly (.wk-title display bold, .wk-sub
   body size), so this brings Articles into line with it rather than
   inventing a third treatment. */
.ar-title {
  font-family: var(--display);
  font-weight: 700;
  font-size: 1.3rem;
  line-height: 1.16;
  letter-spacing: -0.025em;
  color: var(--ink);
  margin: 0 0 0.5rem;
  max-width: 30ch;
  transition: color 0.15s;
}
.ar-claim {
  font-family: inherit;
  font-weight: 400;
  font-size: 0.95rem;
  line-height: 1.55;
  letter-spacing: 0;
  color: var(--ink-soft);
  margin: 0;
  max-width: 62ch;
}
.ar-item:hover .ar-claim { color: var(--ink-soft); }
.ar-item:hover .ar-title { color: var(--riso-ink); }

