/* Home page styles. Case pages keep their existing stylesheets. */
:root {
  color-scheme:light;
  --page:#f5f5f7;
  --ink:#101b14;
  --muted:#526358;
  --green:#30d158;
  /* The logo and the headline underline. */
  --brand:#30d158;
  /* Garden dot colors: the WaveGrating fringe colors and the bee. Darker in light, brighter in dark. */
  --pink-dot:#e01fb0;
  --leaf-dot:#0a8f45;
  --cyan-dot:#00b4c8;
  --gold-dot:#e09a00;
  --violet-dot:#7a3cff;
  --bee-black:#141414;
  --bee-yellow:#f5c400;
  --pink:#ffa9fd;
  --line:#d0ded3;
  --panel:#f4f8f3;
  --mint:#eaf5e8;
  --contact:#f0f6ee;
  --action:#006f38;
  --sans:"Inter Tight",Arial,sans-serif;
  --mono:"Chivo Mono",monospace
}

:root[data-theme="dark"] {
  color-scheme:dark;
  --page:#000;
  --ink:#f5f5f7;
  --subtitle:#6b6b70;
  --pink-dot:#ff2fd0;
  --leaf-dot:#30d158;
  --cyan-dot:#2ff3ff;
  --gold-dot:#ffc93a;
  --violet-dot:#a970ff;
  --bee-black:#3c3c3c;
  --bee-yellow:#ffd21f;
  --muted:#aeaeae;
  --line:#2d2d2d;
  --panel:#151515;
  --mint:#17281c;
  --contact:#171717;
  --action:#54e691
}

* {
  box-sizing:border-box
}
html {
  scroll-behavior:auto;
  scroll-padding-top:2rem
}
body {
  margin:0;
  background:var(--page);
  color:var(--ink);
  font-family:var(--sans);
  font-size:1.125rem;
  line-height:1.5;
  -webkit-font-smoothing:antialiased
}
h1,h2,h3,p,figure {
  margin:0
}
h1,h2,h3 {
  font-weight:600;
  letter-spacing:-.035em;
  line-height:1.1;
  text-wrap:balance
}
a {
  color:inherit;
  text-underline-offset:.24em
}
button {
  font:inherit;
  color:inherit
}
img,svg {
  display:block;
  max-width:100%
}
a,button {
  -webkit-tap-highlight-color:transparent
}
a:focus-visible,button:focus-visible {
  outline:3px solid var(--action);
  outline-offset:5px
}
button {
  cursor:pointer
}
.frame {
  width:min(100% - 6rem,1200px);
  margin-inline:auto
}
.ui-icon {
  width:1.2em;
  height:1.2em;
  fill:none;
  stroke:currentColor;
  stroke-width:1.6;
  stroke-linecap:round;
  stroke-linejoin:round;
  flex-shrink:0
}
.skip-link {
  position:absolute;
  top:-100px;
  left:1rem;
  z-index:10;
  padding:.75rem 1rem;
  background:var(--green);
  color:#101b14
}
.skip-link:focus {
  top:1rem
}
.site-header {
  background:var(--page)
}
.nav {
  min-height:4rem;
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:1.5rem;
  border-bottom:1px solid var(--line)
}
.brand {
  display:inline-flex;
  align-items:center;
  gap:.65rem;
  text-decoration:none;
  font-size:1.0625rem;
  font-weight:600;
  white-space:nowrap;
  letter-spacing:-.025em
}
/* The mark matches the case pages and the vector master in assets/brand. */
.brand-mark {
  font-size:1.5rem;
  font-weight:700;
  letter-spacing:-.08em;
  line-height:1.15;
  color:#101b14;
  background:var(--brand);
  padding:.25rem .5rem .4375rem
}
.nav-links {
  display:flex;
  align-items:center;
  gap:1.5rem
}
.nav-links>a {
  font-size:.9375rem;
  text-decoration:none;
  min-height:44px;
  display:flex;
  align-items:center
}
.nav-links>a:hover {
  text-decoration:underline
}
.theme-toggle {
  display:grid;
  place-items:center;
  width:44px;
  height:44px;
  background:transparent;
  border:0
}
.theme-toggle:hover {
  background:var(--panel)
}
.hero {
  padding-block:3.5rem 3rem
}
.hero h1 {
  font-size:clamp(2.75rem,4.5vw,4.5rem);
  letter-spacing:-.04em
}
.highlight {
  background:linear-gradient(transparent 75%,var(--brand) 75%,var(--brand) 96%,transparent 96%)
}
.hero>p {
  font-size:clamp(1.125rem,1.8vw,1.5rem);
  margin-top:1.1rem;
  max-width:36rem;
  color:var(--muted)
}
.work {
  padding-bottom:5rem
}
.work-title {
  font-size:1.5rem;
  margin-bottom:2rem;
  letter-spacing:-.025em
}
.project-card {
  min-width:0;
  scroll-margin-top:2rem
}
.project-link {
  color:inherit;
  text-decoration:none;
  display:block;
  height:100%;
  min-width:0
}
.project-copy {
  min-width:0
}
.project-copy h3 {
  font-size:2rem;
  overflow-wrap:anywhere
}
.project-summary {
  margin-top:.75rem;
  font-size:1.125rem;
  line-height:1.45;
  max-width:34ch
}
.project-action {
  display:inline-flex;
  align-items:center;
  gap:.45rem;
  color:var(--action);
  font-size:1rem;
  font-weight:500;
  margin-top:1rem;
  min-height:32px
}
.project-link:is(:hover,:focus-visible) .project-action {
  text-decoration:underline
}
.project-figure {
  min-width:0
}
.project-visual {
  display:flex;
  align-items:center;
  justify-content:center;
  aspect-ratio:16/9;
  background:var(--panel);
  width:100%;
  min-width:0;
  overflow:hidden
}
.project-visual>img {
  width:100%;
  height:100%;
  object-fit:contain
}
.project-visual>svg {
  width:100%;
  height:100%
}
.project-figure figcaption {
  font-size:.8125rem;
  line-height:1.45;
  color:var(--muted);
  margin-top:.7rem;
  max-width:65ch
}
.choice-image-pair {
  display:grid;
  grid-template-columns:minmax(0,1fr) 1rem minmax(0,1fr);
  align-items:center;
  gap:.6rem;
  padding:1rem;
  width:100%;
  height:100%
}
.choice-image-pair>img {
  width:100%;
  height:100%;
  object-fit:contain;
  min-width:0
}
.choice-image-pair>span {
  color:var(--muted)
}
.project-visual svg text {
  fill:var(--ink);
  font-family:var(--sans);
  font-size:17px;
  text-anchor:middle
}
.project-visual svg .choice-small {
  font-size:15px;
  fill:var(--muted)
}
.choice-wire {
  stroke:var(--muted);
  stroke-width:1.5;
  fill:none
}
.choice-node {
  fill:var(--page);
  stroke:var(--line);
  stroke-width:1.5;
  vector-effect:non-scaling-stroke
}
.choice-node-api {
  fill:var(--green);
  stroke:var(--green)
}
.project-visual .choice-node-api+text,.project-visual .choice-node-api+text+text {
  fill:#101b14
}
.mono {
  font-family:var(--mono)
}

/* Contribution evidence and contact content. */
.oss {
  padding-block:3.5rem 5rem;
  border-top:1px solid var(--line)
}
.oss-head {
  max-width:44rem;
  margin-bottom:2.5rem
}
.oss-head h2,.about h2 {
  font-size:clamp(2rem,3vw,3rem)
}
.oss-head>p {
  margin-top:1rem;
  max-width:36rem;
  color:var(--muted)
}
.title-line+.title-line:before {
  content:" "
}
.oss-grid {
  display:grid;
  grid-template-columns:minmax(0,1.45fr) minmax(0,1fr);
  gap:5rem
}
.pr-list {
  list-style:none;
  padding:0;
  margin:0;
  display:grid;
  gap:2rem
}
.pr-list li>a {
  font-size:1.125rem;
  font-weight:600
}
.pr-list li>p {
  font-size:1rem;
  margin-top:.5rem
}
.pr-meta {
  display:flex;
  flex-wrap:wrap;
  gap:.5rem;
  font-size:.8125rem!important;
  color:var(--muted)
}
.status-label {
  font-weight:600;
  color:var(--ink)
}
.case-links {
  display:flex;
  flex-wrap:wrap;
  gap:1.5rem;
  margin-top:2rem
}
.text-link {
  display:inline-flex;
  align-items:center;
  gap:.5rem;
  font-size:1rem;
  min-height:44px
}
.oss-quotes {
  display:grid;
  align-content:start;
  gap:3rem
}
.case-quote blockquote {
  margin:0;
  font-size:1.5rem;
  line-height:1.35;
  letter-spacing:-.025em
}
.quote-context {
  font-size:.75rem;
  color:var(--muted);
  margin-bottom:1rem
}
.case-quote figcaption {
  font-size:.75rem;
  color:var(--muted);
  margin-top:1.25rem;
  line-height:1.7
}
.about {
  background:var(--contact);
  padding-top:4rem
}
.about-inner {
  display:grid;
  grid-template-columns:1fr 1.4fr;
  gap:4rem
}
.about-copy {
  max-width:42rem
}
.about-copy>p {
  font-size:1.125rem;
  margin-bottom:1.25rem
}
.contact {
  margin-top:2rem
}
.contact-lead {
  font-size:1.25rem
}
.contact-actions {
  display:flex;
  flex-wrap:wrap;
  gap:1.5rem;
  align-items:center;
  margin-top:1.5rem
}
.button {
  display:inline-flex;
  gap:.75rem;
  align-items:center;
  justify-content:center;
  padding:.75rem 1.125rem;
  text-decoration:none;
  font-size:1rem;
  min-height:44px;
  background:var(--ink);
  color:var(--page)
}
.footer {
  display:flex;
  flex-wrap:wrap;
  gap:1.25rem 2rem;
  align-items:center;
  margin-top:4rem;
  padding-block:1.5rem;
  border-top:1px solid var(--line);
  font-size:.75rem;
  color:var(--muted)
}
.footer>a {
  display:inline-flex;
  align-items:center;
  gap:.4rem
}

@media(max-width:767px) {
  .frame {
    width:calc(100% - 2rem)
  }
  .nav {
    gap:.5rem
  }
  .brand {
    font-size:.875rem;
    gap:.4rem
  }
  .nav-links {
    gap:.6rem
  }
  .nav-links>a {
    font-size:.875rem
  }
  .theme-toggle {
    width:36px;
    min-width:36px
  }
  .hero {
    padding-block:2.5rem 2rem
  }
  .hero h1 {
    font-size:clamp(2.4rem,8.7vw,3.25rem);
    max-width:13ch
  }
  .hero>p {
    max-width:30ch
  }
  .work {
    padding-bottom:3.5rem
  }
  .work-title {
    font-size:1.25rem;
    margin-bottom:1.5rem
  }
  .project-copy h3 {
    font-size:1.75rem
  }
  .oss {
    padding-block:2.75rem 3.5rem
  }
  .oss-grid,.about-inner {
    grid-template-columns:1fr;
    gap:2.75rem
  }
  .about {
    padding-top:3rem
  }
  .footer {
    margin-top:3rem;
    gap:1rem
  }
  .footer>span {
    width:100%
  }
  .project-summary {
    font-size:1.0625rem
  }
  .project-figure figcaption {
    font-size:.8125rem
  }

}

@media(max-width:360px) {
  .brand>span:last-child {
    max-width:6rem;
    white-space:normal;
    line-height:1.1
  }
  .nav-links {
    gap:.5rem
  }

}

h1,h2,h3,p,figcaption {
  overflow-wrap:anywhere
}
.nav {
  flex-wrap:wrap
}
.nav-links {
  flex-wrap:wrap
}
.brand {
  min-width:0
}
.project-action {
  flex-wrap:wrap
}
:root:not([data-theme-ready]) .theme-toggle {
  display:none
}

@media(prefers-reduced-motion:reduce) {
  *,*:before,*:after {
    animation:none!important;
    transition:none!important;
    scroll-behavior:auto!important
  }

}

@media print {
  :root,:root[data-theme="dark"] {
    color-scheme:light;
    --page:#fff;
    --subtitle:var(--muted);
    --ink:#101b14;
    --muted:#526358;
    --line:#d0ded3;
    --panel:#f4f8f3;
    --mint:#eaf5e8;
    --contact:#f0f6ee;
    --action:#006f38
  }
  .theme-toggle {
    display: none;
  }
  .project-card {
    break-inside: avoid;
  }
  .frame {
    width:100%
  }
  .project-visual {
    max-height:14rem
  }

}

/* Editorial layout. */
.editorial-home main {
  display: grid;
  grid-template-columns: minmax(0, 1fr) min(1200px, calc(100% - 6rem)) minmax(0, 1fr);
}

.editorial-home .hero,
.editorial-home .work {
  grid-column: 2;
}

/* The introduction fills the first screen. The headline sits at the bottom beside its line, above a footer row,
   so the open space above it is part of the composition. */
.editorial-home .hero {
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  width: auto;
  min-height: calc(100svh - 4rem);
  margin: 0;
  padding: 0;
}

/* The garden fills the introduction behind the headline. hero-garden.js draws it. The headline lets pointer events
   through, so a visitor can drag, click and double click anywhere in the garden. */
.editorial-home .hero {
  position: relative;
}

/* The drawing spans the full window width, so on a wide screen the bubbles can float past the text column. The
   body clips the part under the scroll bar, which does not make the page scroll sideways. */
.editorial-home {
  overflow-x: clip;
}

.editorial-home .hero-art {
  position: absolute;
  top: 0;
  left: calc(50% - 50vw);
  display: block;
  width: 100vw;
  height: 100%;
  cursor: grab;
  touch-action: pan-y;
}

.editorial-home .hero.is-dragging,
.editorial-home .hero.is-dragging * {
  cursor: grabbing;
  user-select: none;
}

.editorial-home .hero-copy {
  position: relative;
  pointer-events: none;
}

@media print {
  .editorial-home .hero-art {
    display: none;
  }
}

.editorial-home .hero-copy {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 17rem);
  align-items: end;
  gap: 1.5rem 3rem;
  padding-bottom: clamp(2.5rem, 7vh, 4.5rem);
}

.editorial-home .hero h1 {
  font-size: clamp(3rem, 7.6vw, 6rem);
  line-height: .96;
  letter-spacing: -.04em;
}

.editorial-home .hero-copy > p {
  margin: 0 0 .55rem;
  color: var(--subtitle, var(--muted));
  font-size: clamp(1.25rem, 1.7vw, 1.5rem);
  line-height: 1.35;
  max-width: 22ch;
}

.editorial-home .hero-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: .25rem 2rem;
  position: relative;
  padding-block: .75rem 1rem;
  color: var(--muted);
  font-size: .9375rem;
}

/* The rule above the footer row. The intro draws it from the left by animating --rule. */
.editorial-home .hero-foot::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 1px;
  background: var(--line);
  transform-origin: left;
  scale: var(--rule, 1) 1;
}

.editorial-home .hero-open {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  color: var(--ink);
}

.editorial-home .hero-open::before {
  content: "";
  width: .5rem;
  height: .5rem;
  border-radius: 50%;
  background: var(--green);
}

.editorial-home .hero-foot a {
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  min-height: 44px;
  color: var(--ink);
  font-weight: 500;
  text-decoration: none;
}

.editorial-home .work-title {
  font-size: .9375rem;
  line-height: 1.4;
  font-weight: 500;
  letter-spacing: 0;
}

/* Work: the side column keeps the section title and the project index in view, beside the projects. */
.editorial-home .work {
  display: grid;
  grid-template-columns: minmax(0, 17.5rem) minmax(0, 1fr);
  gap: 0 4rem;
  width: auto;
  margin: 0;
  padding-block: 4rem 5rem;
}

.editorial-home .work-side {
  position: sticky;
  top: 2rem;
  align-self: start;
}

.editorial-home .work-index ul {
  display: grid;
  gap: .125rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.editorial-home .work-index a {
  display: flex;
  align-items: center;
  gap: .625rem;
  min-height: 2.25rem;
  color: var(--muted);
  font-size: 1.0625rem;
  text-decoration: none;
  transition: color .2s ease-out;
}

.editorial-home .work-index a::before {
  content: "";
  flex: none;
  width: .5rem;
  height: .5rem;
  border-radius: 50%;
  background: var(--line);
  transition: background-color .2s ease-out, scale .3s ease-out;
}

.editorial-home .work-index a:hover,
.editorial-home .work-index a[aria-current] {
  color: var(--ink);
}

.editorial-home .work-index a[aria-current]::before {
  background: var(--green);
  scale: 1.25;
}

.editorial-home .work-title {
  margin-bottom: 1.5rem;
  color: var(--muted);
}

.editorial-home .refined-projects {
  display: grid;
  gap: 4.5rem;
}

.editorial-home .project-link {
  display: grid;
  align-content: start;
  height: auto;
}

.editorial-home .project-copy {
  padding-bottom: 1.5rem;
}

.editorial-home .project-copy h3 {
  font-size: 2.25rem;
  line-height: 1.12;
  letter-spacing: -.035em;
}

.editorial-home .project-wavegrating h3 {
  font-size: 2.5rem;
}

.editorial-home .project-summary {
  margin-top: .75rem;
  max-width: 48ch;
  font-size: 1.25rem;
  line-height: 1.45;
}

.editorial-home .project-figure {
  align-self: start;
}

.editorial-home .project-visual {
  aspect-ratio: 16 / 9;
  background: var(--panel);
}

.editorial-home .project-visual > img,
.editorial-home .choice-image-pair > img {
  object-fit: contain;
}

.editorial-home .project-figure figcaption {
  max-width: 68ch;
  margin-top: .625rem;
  font-size: .875rem;
  line-height: 1.5;
}

/* A schematic fills a phone panel and stops at 27rem on wider panels, so its labels stay near body size. */
.editorial-home .project-visual > svg {
  width: min(100%, 27rem);
  height: auto;
}

/* Screenshots sit inside the panel with even space on all sides. A hairline marks the screenshot edge. */
.editorial-home :is(.project-ears, .project-hermes) .project-visual {
  padding: clamp(1rem, 4%, 2rem);
}

.editorial-home :is(.project-ears, .project-hermes) .project-visual > img {
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 100%;
  outline: 1px solid var(--line);
}

.editorial-home :is(p, figcaption, li) {
  text-wrap: pretty;
}

.editorial-home ::selection {
  background: var(--green);
  color: #101b14;
}

.editorial-home .project-action {
  justify-self: start;
  align-self: start;
  min-height: 44px;
  margin-top: .5rem;
}

.editorial-home .oss {
  grid-column: 2;
  width: 100%;
  padding-block: 4rem 5rem;
}

.editorial-home .oss-head,
.editorial-home .about-inner {
  display: grid;
  grid-template-columns: minmax(0, 17.5rem) minmax(0, 1fr);
  gap: 4rem;
}

.editorial-home .oss-head {
  max-width: none;
  margin-bottom: 3rem;
  align-items: start;
}

.editorial-home .oss-head h2,
.editorial-home .about h2 {
  font-size: 2rem;
  line-height: 1.15;
}

.editorial-home .oss-head > p {
  margin-top: 0;
  max-width: 48ch;
}

.editorial-home .oss-grid {
  grid-template-columns: minmax(0, 1.45fr) minmax(0, 1fr);
  gap: 4rem;
}

.editorial-home .pr-list {
  gap: 2rem;
}

.editorial-home .pr-list li > a {
  display: inline-block;
  padding-block: .5rem;
  font-size: 1.25rem;
  line-height: 1.35;
}

.editorial-home .pr-list li > p {
  max-width: 60ch;
}

.editorial-home .pr-list .pr-meta {
  margin-top: .25rem;
}

/* The opening quote mark hangs in the margin, so the words align with the label and caption. */
.editorial-home .case-quote blockquote p {
  text-indent: -.3em;
}

.editorial-home .case-quote blockquote {
  font-size: 1.5rem;
  line-height: 1.4;
}

.editorial-home .case-quote figcaption {
  margin-top: .875rem;
}

.editorial-home .about {
  grid-column: 1 / -1;
  padding-top: 4rem;
}

.editorial-home .about-copy > p {
  max-width: 62ch;
  line-height: 1.55;
}

.editorial-home .contact {
  margin-top: 2rem;
}

.editorial-home .contact-actions {
  margin-top: 1.25rem;
}

.editorial-home .footer {
  margin-top: 3rem;
}

.editorial-home .footer > a {
  min-height: 44px;
}

@media (max-width: 1100px) {
  .editorial-home main {
    display: block;
  }

  .editorial-home .hero,
  .editorial-home .work,
  .editorial-home .oss {
    width: min(100% - 6rem, 1200px);
    margin-inline: auto;
  }






  .editorial-home .work {
    display: block;
    padding-top: 2.5rem;
  }

  .editorial-home .work-side {
    position: static;
  }

  .editorial-home .work-index {
    display: none;
  }

  .editorial-home .oss-head,
  .editorial-home .about-inner {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.5fr);
    gap: 2.5rem;
  }

  .editorial-home .oss-grid {
    gap: 2.5rem;
  }
}

@media (max-width: 767px) {
  .editorial-home .hero,
  .editorial-home .work,
  .editorial-home .oss {
    width: calc(100% - 2rem);
  }

  .editorial-home .hero {
    min-height: calc(100svh - 4rem);
  }

  .editorial-home .hero-copy {
    grid-template-columns: minmax(0, 1fr);
  }

  .editorial-home .hero-foot {
    flex-direction: column;
    align-items: flex-start;
    padding-block: 1rem .5rem;
  }

  .editorial-home .theme-toggle {
    width: 44px;
    min-width: 44px;
    height: 44px;
  }

  .editorial-home .brand {
    min-height: 44px;
  }

  .editorial-home .oss-head,
  .editorial-home .oss-grid,
  .editorial-home .about-inner {
    grid-template-columns: minmax(0, 1fr);
    gap: 2rem;
  }

  .editorial-home .oss-head {
    gap: 1.25rem;
    margin-bottom: 2rem;
  }

  .editorial-home .oss {
    padding-block: 3rem 4rem;
  }

  .editorial-home .about {
    padding-top: 3rem;
  }
}

@media (max-width: 640px) {
  .editorial-home .work-title {
    margin-bottom: 1.25rem;
  }

  .editorial-home .project-copy h3 {
    font-size: 1.875rem;
  }

  .editorial-home .project-wavegrating h3 {
    font-size: 2.125rem;
  }

  .editorial-home .project-summary {
    font-size: 1.125rem;
  }

  .editorial-home .project-copy {
    padding-bottom: 1.25rem;
  }

  .editorial-home .refined-projects {
    gap: 4rem;
  }

  .editorial-home .work {
    padding-bottom: 4rem;
  }
}

@media print {
  .editorial-home main {
    display: block;
  }

  .editorial-home .hero {
    min-height: 0;
  }

  .editorial-home .work {
    display: block;
  }

  .editorial-home .work-index {
    display: none;
  }

  .editorial-home .hero,
  .editorial-home .work,
  .editorial-home .oss {
    width: 100%;
    margin-inline: 0;
    padding-block: 1.5rem;
  }

  .editorial-home .refined-projects {
    gap: 2rem;
  }
}

/* Motion. The work assembles as the reader reaches it: each panel opens, and each schematic builds in
   the order its signal flows. Every effect starts from a complete page. Reduced motion and print keep it still.
   When site-motion.js runs (html.js-motion), it owns the headline, panel, and list entrances. The CSS
   versions below are the fallback when it does not run. */
@media screen and (prefers-reduced-motion: no-preference) {
  @view-transition { navigation: auto; }

  .editorial-home .site-header { view-transition-name: site-header; }
  #wavegrating-title { view-transition-name: wavegrating-title; }
  #modly-title { view-transition-name: modly-title; }
  #ears-title { view-transition-name: ears-title; }
  #local-ai-title { view-transition-name: local-ai-title; }
  #hermes-title { view-transition-name: hermes-title; }
  #warm-compaction-title { view-transition-name: warm-compaction-title; }

  ::view-transition-group(*) {
    animation-duration: .45s;
    animation-timing-function: cubic-bezier(.16, 1, .3, 1);
  }

  /* On load, the headline rises into place and the green highlight draws under it. */
  html:not(.js-motion) .editorial-home .hero h1 {
    animation: headline-in .6s cubic-bezier(.16, 1, .3, 1) backwards;
  }

  html:not(.js-motion) .editorial-home .highlight {
    background-repeat: no-repeat;
    background-position: left;
    animation: highlight-draw .7s cubic-bezier(.16, 1, .3, 1) .3s backwards;
  }

  /* A project responds to the pointer with a short spring. */
  .editorial-home .project-visual > :is(img, svg, .choice-image-pair),
  .editorial-home .project-action .ui-icon {
    transition: scale .59s var(--spring), translate .59s var(--spring);
  }

  .editorial-home .project-link:is(:hover, :focus-visible) .project-visual > :is(img, svg, .choice-image-pair) {
    scale: 1.03;
  }

  .editorial-home .project-link:is(:hover, :focus-visible) .project-action .ui-icon {
    translate: .25rem 0;
  }

  .editorial-home .project-link:active .project-visual > :is(img, svg, .choice-image-pair) {
    scale: .99;
    transition-duration: .12s;
  }

  @supports (animation-timeline: view()) {
    .editorial-home .project-visual { view-timeline: --plate block; }

    html:not(.js-motion) .editorial-home .project-visual {
      animation: plate-open linear backwards;
      animation-timeline: --plate;
      animation-range: entry 10% entry 100%;
    }

    html:not(.js-motion) .editorial-home .project-visual > :is(img, svg, .choice-image-pair) {
      animation: plate-settle linear backwards;
      animation-timeline: --plate;
      animation-range: entry 10% entry 100%;
    }

    .editorial-home :is(.choice-part, .choice-wire, .choice-image-pair > *) {
      animation: part-in linear backwards;
      animation-timeline: --plate;
      animation-range: entry calc(30% + var(--i, 0) * 12%) entry calc(52% + var(--i, 0) * 12%);
    }

    .editorial-home .choice-part {
      transform-box: fill-box;
      transform-origin: center;
    }

    .editorial-home .choice-wire {
      stroke-dasharray: 1;
      animation-name: wire-draw;
    }

    .editorial-home .choice-image-pair > :nth-child(2) { --i: 1; }
    .editorial-home .choice-image-pair > :nth-child(3) { --i: 2; }

    /* The pull request list arrives item by item as it scrolls in. */
    html:not(.js-motion) .editorial-home .pr-list > li {
      animation: part-in linear backwards;
      animation-timeline: view();
      animation-range: entry 0% entry 70%;
    }
  }

  @keyframes headline-in {
    from { clip-path: inset(0 0 100% 0); translate: 0 .35em; }
    to { clip-path: inset(0 0 -25% 0); translate: none; }
  }

  @keyframes highlight-draw {
    from { background-size: 0 100%; }
    to { background-size: 100% 100%; }
  }

  @keyframes plate-open {
    from { clip-path: inset(8% 6%); }
    to { clip-path: inset(0); }
  }

  @keyframes plate-settle {
    from { transform: scale(1.08); }
    to { transform: none; }
  }

  @keyframes part-in {
    from { opacity: 0; transform: translateY(8px) scale(.96); }
    to { opacity: 1; transform: none; }
  }

  @keyframes wire-draw {
    from { stroke-dashoffset: 1; }
    to { stroke-dashoffset: 0; }
  }
}

/* A gentle spring (bounce .15, about .45 s) sampled as a CSS easing. */
:root {
  --spring: linear(0, 0.019, 0.067, 0.134, 0.213, 0.296, 0.38, 0.461, 0.537, 0.608, 0.671, 0.728, 0.777, 0.82, 0.857, 0.887, 0.913, 0.935, 0.952, 0.966, 0.977, 0.985, 0.992, 0.997, 1, 1.003, 1.005, 1.006, 1.006, 1.006, 1.006, 1.006, 1.005, 1.005, 1.004, 1.004, 1.003, 1.003, 1.002, 1.002, 1);
}

/* The shared theme runtime selects the theme through data-theme. */
[data-theme-icon="light"] { display: none; }
:root[data-theme="dark"] [data-theme-icon="dark"] { display: none; }
:root[data-theme="dark"] [data-theme-icon="light"] { display: block; }
/* Motion layer. Styles for site-motion.js and the theme reveal in theme.js. theme.js adds js-motion
   only when motion may run, so print, reduced motion, and saved Pause never use these rules.
   Case pages load the shared part of these rules from site-motion.css. */

/* Lenis drives the scroll. Native smooth scrolling would fight it. */
html.lenis, html.lenis body { height: auto; }
html.lenis { scroll-behavior: auto !important; }
.lenis.lenis-stopped { overflow: clip; }
.lenis.lenis-smooth iframe { pointer-events: none; }

/* Until site-motion.js sets its start states, the first view stays covered. If the script never
   runs, the cover lifts by itself after 2.5 seconds. */
.js-motion:not(.motion-live) .editorial-home :is(.hero-copy, .hero-foot, .site-header .nav, .project-card:first-child) {
  visibility: hidden;
  animation: motion-failsafe 0s 2.5s forwards;
}

@keyframes motion-failsafe { to { visibility: visible; } }

/* Each split piece is its own box, so it must not repeat the hanging indent of its paragraph. */
:is(.split-line, .split-word, .split-char) { text-indent: 0; }

/* A split line clips its text while it rises. The padding keeps descenders inside the clip. */
.split-line-mask {
  padding-block: .06em .14em;
  margin-block: -.06em -.14em;
}

.js-motion .editorial-home .highlight {
  background-repeat: no-repeat;
  background-position: left;
  background-size: 100% 100%;
}

/* Scroll position, as a green hairline along the top edge. */
.scroll-progress {
  position: fixed;
  inset: 0 0 auto;
  z-index: 30;
  height: 2px;
  background: var(--green);
  transform-origin: left;
  pointer-events: none;
}

/* Motion springs move these controls. A CSS transform transition would lag behind the spring. */
.js-motion :is(.button, .nav-links > a, .all-work, .theme-toggle, .motion-toggle, .brand-mark) {
  transition-property: color, background-color, border-color, text-decoration-color, opacity;
}

/* Schematic signal: one short green pulse travels each wire, and each box lights as it arrives. */
.choice-signal {
  fill: none;
  stroke: var(--green);
  stroke-width: 4;
  stroke-linecap: round;
  stroke-dasharray: .22 2;
  stroke-dashoffset: .22;
  pointer-events: none;
}

.choice-part .choice-node { transition: stroke .5s ease-out, stroke-width .5s ease-out; }

.choice-part.is-lit .choice-node {
  stroke: var(--green);
  stroke-width: 2.5;
  transition-duration: .12s;
}

/* Links: the underline turns green and thickens under the pointer. */
@media (hover: hover) {
  .editorial-home :is(.pr-list a, .text-link, .about-copy a, .case-quote a) {
    text-decoration-thickness: 1px;
    transition: text-decoration-color .25s ease-out, text-decoration-thickness .25s ease-out;
  }

  .editorial-home :is(.pr-list a, .text-link, .about-copy a, .case-quote a):hover {
    text-decoration-color: var(--green);
    text-decoration-thickness: 3px;
  }
}

/* Pull request state: a filled dot for merged, a ring for in review. The label text carries the state. */
.editorial-home .status-label {
  display: inline-flex;
  align-items: center;
  gap: .4em;
}

.editorial-home .status-label::before {
  content: "";
  width: .5em;
  height: .5em;
  border-radius: 50%;
  background: var(--green);
}

.editorial-home .status-label.pending::before {
  background: none;
  box-shadow: inset 0 0 0 1.5px currentColor;
}

/* Theme reveal: the new theme grows in a circle over the old one. Named elements join the root
   snapshot so the header and titles do not fade on their own. */
.theme-transition::view-transition-old(root),
.theme-transition::view-transition-new(root) {
  animation: none;
  mix-blend-mode: normal;
}

.theme-transition * { view-transition-name: none !important; }

/* Print shows the finished page: a part that has not scrolled in yet prints as if its entrance had played. */
@media print {
  .scroll-progress, .choice-signal { display: none; }

  .js-motion .editorial-home :is(.site-header .nav > *, .hero-copy, .hero-copy *, .hero-foot > *, .project-card, .project-card *, .work-title, .work-title *, .oss-head *, .pr-list > li, .status-label, .case-quote *, .about h2 *, .about-copy > *) {
    visibility: visible !important;
    opacity: 1 !important;
    transform: none !important;
    clip-path: none !important;
  }
}

