
*{box-sizing:border-box}
html{scroll-behavior:smooth}
/* Paints before anything else loads. The page's own background lives in its x-dc
   helmet, which does not apply until the raw template parses and vanishes for a
   frame when the runtime mounts, so without this the first paint is white. */
html{background:#F6F4EF}
body{overflow-x:hidden}
img,svg,video{max-width:100%}
a:focus-visible,button:focus-visible{outline:3px solid #8F6A1E;outline-offset:3px}
[data-screen-label="Nav"]{position:sticky!important;top:0;z-index:100;background:transparent;backdrop-filter:none;-webkit-backdrop-filter:none;transition:background .28s ease,backdrop-filter .28s ease,-webkit-backdrop-filter .28s ease}
[data-screen-label="Nav"][data-scrolled="true"]{background:linear-gradient(to bottom,rgba(246,244,239,.34),rgba(246,244,239,.16) 72%,rgba(246,244,239,0));backdrop-filter:blur(5px) saturate(1.05);-webkit-backdrop-filter:blur(5px) saturate(1.05)}
/* Pages with a full-bleed hero: the nav floats over it instead of sitting on a band above it.
   --cp-nav-h is measured by nav-scroll.js; the fallback matches the desktop nav height. */
.nav-overlay [data-screen-label="Nav"]{margin-bottom:calc(-1 * var(--cp-nav-h,104px))}
.nav-overlay [data-screen-label="Hero"]{padding-top:var(--cp-nav-h,104px)}
/* Hero chip hangs off the screenshot to the right. The hero clips overflow, so
   step the shift down as the viewport narrows rather than letting it be cut. */
@media(max-width:1400px){[data-hero-chip]{transform:translateX(30%)!important}}
@media(max-width:1100px){[data-hero-chip]{transform:translateX(10%)!important}}
/* Entrance pre-hide. Elements that animate in on load start hidden from the first
   paint, so the page never shows them, hides them, and shows them again. The
   animation scripts take over by setting data-entrance-ready / data-reveal-ready
   on <html>; an inline timer in each page's <head> sets both at 2s regardless, so
   a slow or failed script never leaves the page blank. Only when scripting is on,
   since the timer could not run otherwise. Reveals honour reduced motion because
   case-anim.js does; the home entrance deliberately does not (see home-anim.js). */
@media (scripting:enabled){
  html:not([data-entrance-ready]) [data-entrance]{opacity:0}
}
@media (scripting:enabled) and (prefers-reduced-motion:no-preference){
  html:not([data-reveal-ready]) [data-reveal]{opacity:0}
}
/* Motion is enabled by default for this portfolio. Use ?motion=off for a static/reduced-motion experience. */
@media (max-width: 760px){
  [data-screen-label="Nav"]{padding:16px!important;justify-content:flex-start!important;min-height:auto!important}
  [data-screen-label="Nav"]>div:first-child{width:100%!important;padding:10px 14px!important;gap:10px!important;justify-content:space-between!important}
  [data-screen-label="Nav"]>div:first-child>span:nth-child(4){display:none!important}
  [data-screen-label="Nav"]>div:nth-child(2){display:none!important}
  [data-screen-label="Hero"] img[alt="Christopher Price"]{display:none!important}
  [data-screen-label] div[style*="max-width: 1160px"]{padding-left:22px!important;padding-right:22px!important}
  [data-screen-label="Stats"]{padding-left:22px!important;padding-right:22px!important}
  /* The design exports lay out side-by-side content as flex-wrap rows whose items
     carry a min-width, so they wrap when space runs out. On a phone every such
     item takes the full row; zeroing min-width alone stops the wrap and squeezes
     columns to a word or two per line. min-width: 0 items are left alone: those
     are deliberate truncation, not wrap triggers. Once React renders, the browser
     re-serialises direction + wrap as the flex-flow shorthand, hence both forms. */
  [data-screen-label] :is([style*="flex-wrap: wrap"],[style*="flex-flow:"][style*=" wrap"])>[style*="min-width:"]:not([style*="min-width: 0"]){flex-basis:100%!important;min-width:0!important}
  /* auto-fit grids whose minimum column (300px and up) is wider than a phone's
     content box would overflow sideways rather than drop to one column. */
  [data-screen-label] [style*="repeat(auto-fit, minmax(3"]{grid-template-columns:1fr!important}
  /* The portrait is hidden on phones; its ring badge would otherwise float over
     the hero buttons. */
  [data-screen-label="Hero"] div[style*="clamp(340px, 46vw, 680px)"]{display:none!important}
  [data-screen-label="Career story"] button{width:100%!important;text-align:left!important}
  iframe{min-height:280px}
}
@media (max-width: 400px){
  /* Same overflow as above for 200-280px minimums on the narrowest phones. */
  [data-screen-label] [style*="repeat(auto-fit, minmax(2"]{grid-template-columns:1fr!important}
}
/* Tablets and small laptop windows. The nav pill is ~696px and never shrinks,
   while the contact icons sit absolutely 40px from the right edge, so below
   ~980px the pill slid under them. Here the icons join the flow at the right, and
   the pill tightens its spacing to fit beside them. */
@media (min-width: 761px) and (max-width: 1100px){
  [data-screen-label="Nav"]{padding-left:24px!important;padding-right:24px!important;justify-content:space-between!important;gap:16px}
  [data-screen-label="Nav"]>div:nth-child(2){position:static!important;transform:none!important;flex:none}
  [data-screen-label="Nav"]>div:first-child{padding-right:20px!important;gap:14px!important}
  [data-screen-label="Nav"]>div:first-child>span:nth-child(4){margin-left:4px!important;gap:18px!important}
}
/* Home hero, tablets to small laptops: the portrait (46vw, 8% from the right)
   overlapped the 620px text column. The text column is held to half the width
   and the portrait moves to the right edge, so the two sit side by side. */
@media (min-width: 761px) and (max-width: 1180px){
  [data-screen-label="Hero"]:has(img[alt="Christopher Price"]) div[style*="max-width: 620px"]{max-width:min(620px,50vw)!important}
  [data-screen-label="Hero"] div[style*="clamp(340px, 46vw, 680px)"]{right:2%!important;width:clamp(300px,44vw,680px)!important}
}
.teaser-body{margin:0;background:#F6F4EF;color:#121714;font-family:Inter,ui-sans-serif,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif}
.teaser-shell{max-width:1160px;margin:0 auto;padding:28px 40px 80px}
.teaser-nav{display:flex;justify-content:space-between;align-items:center;padding:10px 0 56px;border-bottom:1px solid #E0DCD0}
.teaser-nav a{color:#1D4A38;text-decoration:none;font-size:13px;font-weight:600}
.teaser-nav .brand{font-size:16px;color:#121714}
.teaser-card{max-width:820px;padding:88px 0}
.teaser-card .eyebrow{font:500 11px 'IBM Plex Mono',monospace;letter-spacing:.12em;text-transform:uppercase;color:#1D4A38;margin-bottom:18px}
.teaser-card h1{font:800 clamp(42px,7vw,76px)/1.02 Inter,sans-serif;letter-spacing:-.04em;margin:0 0 26px}
.teaser-lead{font:600 clamp(22px,3vw,32px)/1.3 'Source Serif 4',serif;margin:0 0 24px;max-width:760px}
.teaser-card p:not(.teaser-lead){font:400 16px/1.7 Inter,sans-serif;color:#55605A;max-width:650px}
.coming{display:inline-block;margin-top:28px;padding:8px 11px;border:1px solid #C9C4B4;border-radius:999px;font:500 10px 'IBM Plex Mono',monospace;letter-spacing:.08em;text-transform:uppercase;color:#55605A}
.teaser-actions{display:flex;gap:18px;align-items:center;flex-wrap:wrap;margin-top:42px}
.teaser-actions a{color:#1D4A38;text-decoration:none;font-weight:600;font-size:14px}
.teaser-actions .primary{background:#121714;color:#F6F4EF;padding:13px 20px;border-radius:4px}
@media(max-width:760px){.teaser-shell{padding:18px 22px 56px}.teaser-nav{padding-bottom:36px}.teaser-card{padding:60px 0}.teaser-card h1{font-size:42px}.teaser-lead{font-size:23px}}
