/* Pinstack Design: one-page studio site, Grove & Citrus identity.
   Layout idea: a route on a map. The hero pairs the promise with real proof,
   the process is a line of stops that ends at the pin, and the page closes
   on a Grove band where the email address is the call to action.
   Shape rule: buttons 10px radius, framed images 16px, nothing else rounded
   (step markers are circles because they are map stops). */

:root {
  color-scheme: light;
  --bg: #FBF7F0;          /* Cream */
  --panel: #F3EEE3;       /* Cream, one step down */
  --sage: #DCE5D3;        /* Sage band */
  --grove: #1F3B2E;       /* headings, primary */
  --ink: #17201B;         /* body text */
  --muted: #4A5750;       /* 7.1:1 on Cream, 5.8:1 on Sage */
  --citrus: #F08A24;      /* accent: fills and marks only on light */
  --on-citrus: #17201B;
  --line: #E4DED2;
  --band: #1F3B2E;        /* closing band */
  --band-ink: #FBF7F0;
  --band-muted: #C9D6C3;  /* 8.1:1 on Grove */
  --shadow: rgba(31, 59, 46, .28);

  --display: "Young Serif", Georgia, "Times New Roman", serif;
  --text: "Figtree", "Segoe UI", system-ui, -apple-system, sans-serif;
  --ease: cubic-bezier(0.16, 1, 0.3, 1);
  --wrap: 1600px;           /* wide screens get room; text keeps its own ch limits */
  --gutter: clamp(1.25rem, 5vw, 4.5rem);
  --section: clamp(4.5rem, 3rem + 5vw, 8rem);
}

[data-theme="dark"] {
  color-scheme: dark;
  --bg: #111814;
  --panel: #17211C;
  --sage: #1A2520;
  --grove: #DCE5D3;       /* headings go light */
  --ink: #EEF0E8;
  --muted: #B5C0B8;       /* 9.6:1 */
  --citrus: #F59A3E;      /* 8.2:1 as text on dark */
  --on-citrus: #17201B;
  --line: #2A3830;
  --band: #1F3B2E;
  --band-ink: #FBF7F0;
  --band-muted: #C9D6C3;
  --shadow: rgba(0, 0, 0, .45);
}

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

html { scroll-behavior: smooth; scroll-padding-top: 88px; }

/* Everything outside the page content (under Safari's bottom bar, behind
   the page edges) is Grove, the footer color. The content areas paint
   their own theme background, so only the edges change.
   Tokens only, so it follows light and dark mode. */
html {
  background: var(--band);
  overscroll-behavior-y: none;
}

body {
  margin: 0;
  background: var(--band);
  overscroll-behavior-y: none;
  color: var(--ink);
  font-family: var(--text);
  font-size: 1.125rem;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

/* The page itself keeps the theme background */
main { display: block; background: var(--bg); }

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

.wrap { max-width: var(--wrap); margin: 0 auto; padding-inline: var(--gutter); }

.visually-hidden {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ---------- Type ---------- */

h1, h2, h3 {
  font-family: var(--display);
  font-weight: 400;
  color: var(--grove);
  margin: 0;
  text-wrap: balance;
}

h1 { font-size: clamp(2.4rem, 1.5rem + 2.8vw, 4rem); line-height: 1.04; letter-spacing: -0.01em; }
h2 { font-size: clamp(2.1rem, 1.5rem + 2.2vw, 3.6rem); line-height: 1.06; letter-spacing: -0.01em; }
h3 { font-size: clamp(1.3rem, 1.15rem + .5vw, 1.6rem); line-height: 1.2; }

p { margin: 0; }

.eyebrow {
  font-size: .8125rem;
  font-weight: 700;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 1rem;
}

.section-intro { color: var(--muted); font-size: 1.25rem; max-width: 40ch; margin-top: 1rem; }

section { padding-block: var(--section); }

/* ---------- Links & buttons ---------- */

a { color: var(--grove); text-underline-offset: .18em; text-decoration-thickness: 1px; }
a:hover { text-decoration-thickness: 2px; }

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .5rem;
  min-height: 52px;
  padding: 0 1.6rem;
  border-radius: 10px;
  border: 2px solid var(--citrus);
  background: var(--citrus);
  color: var(--on-citrus);
  font-family: var(--text);
  font-size: 1.0625rem;
  font-weight: 700;
  text-decoration: none;
  white-space: nowrap;
  transition: transform 200ms var(--ease), box-shadow 200ms var(--ease);
}
.btn:hover { transform: translateY(-2px); box-shadow: 0 10px 22px -12px var(--shadow); text-decoration: none; }
.btn:active { transform: translateY(0); box-shadow: none; }

.btn-small { min-height: 44px; padding: 0 1.1rem; font-size: 1rem; }

.btn-outline { background: transparent; border-color: var(--grove); color: var(--grove); }
.btn-outline:hover { background: var(--grove); color: var(--bg); }

.link-more {
  display: inline-flex;
  align-items: center;
  min-height: 52px;
  font-weight: 700;
  color: var(--grove);
  text-decoration: underline;
  text-decoration-color: var(--citrus);
  text-decoration-thickness: 2px;
  text-underline-offset: .3em;
}
.link-more::after { content: "\2192"; margin-left: .45em; transition: transform 200ms var(--ease); }
.link-more:hover::after { transform: translateX(4px); }

:focus-visible { outline: 3px solid var(--citrus); outline-offset: 3px; border-radius: 4px; }

.skip-link {
  position: absolute; left: 1rem; top: -4rem; z-index: 100;
  background: var(--grove); color: var(--bg);
  padding: .75rem 1.25rem; border-radius: 10px; font-weight: 700; text-decoration: none;
}
.skip-link:focus { top: 1rem; }

/* ---------- Header ---------- */

.site-header {
  position: sticky; top: 0; z-index: 50;
  /* Solid, not translucent: Safari samples this sticky bar to tint the area
     around the Dynamic Island, and it only matches if the color is opaque. */
  background: var(--bg);
  border-bottom: 1px solid var(--line);
  /* viewport-fit=cover lets the page run under the notch: keep the bar
     clear of the Dynamic Island / status bar. (Milo's addition.) */
  padding-top: env(safe-area-inset-top, 0px);
}

.header-inner { display: flex; align-items: center; justify-content: space-between; gap: 1.5rem; min-height: 72px; }
.brand { display: block; flex: none; }
.brand img { height: 40px; width: auto; }

.desktop-nav { display: none; gap: 2rem; }
.desktop-nav a {
  display: inline-flex; align-items: center; min-height: 44px;
  font-weight: 600; font-size: 1rem; color: var(--ink); text-decoration: none;
  background: linear-gradient(var(--citrus), var(--citrus)) no-repeat 0 85% / 0 2px;
  transition: background-size 250ms var(--ease);
}
.desktop-nav a:hover { background-size: 100% 2px; }

.header-actions { display: flex; align-items: center; gap: .5rem; }
.header-cta { display: none; }

.theme-toggle, .mobile-menu summary {
  display: inline-grid; place-items: center;
  width: 44px; height: 44px; padding: 0;
  border: 0; border-radius: 10px; background: transparent; color: var(--ink);
  cursor: pointer; transition: background-color 200ms var(--ease);
}
.theme-toggle:hover, .mobile-menu summary:hover { background: var(--panel); }
.theme-toggle .icon-sun { display: none; }
[data-theme="dark"] .theme-toggle .icon-sun { display: block; }
[data-theme="dark"] .theme-toggle .icon-moon { display: none; }

.mobile-menu { position: relative; }
.mobile-menu summary { list-style: none; }
.mobile-menu summary::-webkit-details-marker { display: none; }
.mobile-menu .icon-close { display: none; }
.mobile-menu[open] .icon-menu { display: none; }
.mobile-menu[open] .icon-close { display: block; }
.mobile-menu nav {
  position: absolute; right: 0; top: calc(100% + .5rem);
  min-width: 232px; padding: .75rem;
  display: grid; gap: .25rem;
  background: var(--bg); border: 1px solid var(--line); border-radius: 10px;
  box-shadow: 0 18px 40px -18px var(--shadow);
}
.mobile-menu nav a:not(.btn) {
  display: flex; align-items: center; min-height: 48px; padding: 0 1rem;
  color: var(--ink); font-weight: 600; text-decoration: none; border-radius: 10px;
}
.mobile-menu nav a:not(.btn):hover { background: var(--panel); }
.mobile-menu nav .btn { margin-top: .25rem; }
.mobile-menu[open] nav { animation: menu-in 220ms var(--ease); }
@keyframes menu-in { from { opacity: 0; translate: 0 -6px; } }

/* ---------- Hero ---------- */

.hero { padding-block: clamp(3rem, 2rem + 4vw, 5.5rem) clamp(4rem, 3rem + 4vw, 6.5rem); overflow: hidden; }

.hero-grid { display: grid; gap: 3rem; align-items: center; }

.hero-copy { max-width: 34rem; }
.hero-copy h1 { max-width: 15ch; }
.lede { color: var(--muted); font-size: 1.25rem; max-width: 36ch; margin-top: 1.5rem; }
.hero-ctas { display: flex; flex-wrap: wrap; align-items: center; gap: .75rem 1.75rem; margin-top: 2.25rem; }

.hero-shot { margin: 0; }
.browser {
  border-radius: 16px;
  overflow: hidden;
  background: var(--panel);
  border: 1px solid var(--line);
  box-shadow: 0 40px 80px -48px var(--shadow), 0 2px 0 var(--line);
}
.browser-bar {
  display: flex; align-items: center; justify-content: center;
  height: 34px; padding: 0 1rem;
  background: var(--panel); border-bottom: 1px solid var(--line);
  font-size: .8125rem; color: var(--muted);
}
.browser-bar span {
  padding: .1rem .9rem; border-radius: 10px; background: var(--bg);
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.browser img { width: 100%; aspect-ratio: 16 / 10; object-fit: cover; object-position: top; }
.hero-shot figcaption { margin-top: 1rem; font-size: .9375rem; color: var(--muted); }
.hero-shot figcaption a { font-weight: 700; }

/* ---------- Services ---------- */

/* ---------- Services: the pin builds itself ----------
   The pin is the logo mark enlarged at its exact proportions. In the
   48-unit mark the pin spans x 8.5-39.5, y 3.7-45 (31 x 41.3) and each
   stack is a flat full pill 15 x 3.4 at x 16.5, y 12 / 18 / 24. Here
   .pin-composition is a box with the pin's aspect ratio (the SVG viewBox
   is cropped to the pin) and each stack card sits at those coordinates,
   scaled to 125% with tightened spacing:

     left 19.75%  width 60.5%  height 10.3%  top 19.9 / 32.4 / 44.9%

   Stacks hold the service title only, sized in cqw so text scales with
   the pin. The whole pin always shows top to tip; on phones it is wider
   than the screen and its sides bleed off. On desktop the descriptions
   live in the left column (.services-notes) and fade in with their stack.

   Desktop: .is-choreo (set from JS) turns the section into a tall track
   with a sticky stage; --p (0..1) zooms the pin in, then lands one stack
   per scroll beat. Mobile: .is-mobile-play zooms once and fills the
   stacks on a timer. Without either class the finished state shows:
   no-JS and reduced-motion safe. */

.services { overflow-x: clip; }
.services-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: 2.5rem; }
.services-more { margin-top: 2rem; }
.services-more a { font-weight: 700; }

/* Desktop-only notes: one row per stack, same order. */
.services-notes { display: none; list-style: none; margin: 2.25rem 0 0; padding: 0; max-width: 40ch; }
.services-note { padding-block: .9rem; border-top: 1px solid var(--line); }
.services-note:last-child { border-bottom: 1px solid var(--line); }
.services-note h3 { font-family: inherit; font-size: 1rem; font-weight: 700; letter-spacing: 0; margin: 0 0 .2rem; }
.services-note p { margin: 0; color: var(--muted); }

.services-pin { position: relative; min-width: 0; }
.pin-composition {
  --pin-w: clamp(400px, 124vw, 560px);
  position: relative;
  width: var(--pin-w);
  /* Centered even when wider than the column (bleeds off both sides). */
  margin-inline: calc((100% - var(--pin-w)) / 2);
  aspect-ratio: 31 / 41.3;
  container: pin / inline-size;
}
.pin-backdrop {
  position: absolute; inset: 0; z-index: 0;
  width: 100%; height: 100%;
  overflow: visible;
  pointer-events: none;
}
.pin-backdrop .pin-body { fill: #1F3B2E; }
[data-theme="dark"] .pin-backdrop .pin-body { fill: #FBF7F0; }

.service-beats {
  position: absolute; inset: 0; z-index: 1;
  list-style: none; margin: 0; padding: 0;
}
/* The logo's stacks, scaled to 125% for presence: 60.5 x 10.3 units,
   same 5.88 ratio, centered (left 19.75%), spacing tightened between them. */
.stack-card {
  position: absolute;
  left: 19.75%; width: 60.5%; height: 10.3%;
  top: 19.9%;
  display: grid; place-items: center;
  padding: 0 3cqw;
  border-radius: 999px;
  background: #FBF7F0; color: #17201B;
  white-space: nowrap; overflow: hidden;
}
.stack-card[data-i="1"] { top: 32.4%; }
.stack-card[data-i="2"] { top: 44.9%; }
.stack-card h3 {
  font-family: var(--text); font-weight: 700;
  font-size: 4.6cqw; line-height: 1; margin: 0;
  color: inherit; text-align: center;
}
.stack-card[data-i="0"] { background: #F08A24; color: #17201B; }
[data-theme="dark"] .stack-card[data-i="1"],
[data-theme="dark"] .stack-card[data-i="2"] { background: #1F3B2E; color: #FBF7F0; }

@media (min-width: 900px) {
  .services-grid { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: 4rem; align-items: center; }
  .services-notes { display: block; }
  .services-more { margin-top: 1.75rem; }
  /* The whole pin fits the column and the viewport below the header. */
  .pin-composition {
    --pin-w: clamp(440px, min(100%, calc((100svh - 72px - 4rem) * 31 / 41.3)), 620px);
  }

  .services.is-choreo { padding-block: 0; }
  .services.is-choreo .services-track { height: 260vh; }
  .services.is-choreo .services-stage {
    position: sticky; top: 72px;
    height: calc(100vh - 72px); height: calc(100svh - 72px);
    display: flex; align-items: center;
    overflow: clip;
  }
  .services.is-choreo .services-stage > .wrap { width: 100%; }

  /* The whole composition zooms into place over the first 15% of the track. */
  .services.is-choreo .services-pin {
    --pz: clamp(0, calc(var(--p, 0) / 0.15), 1);
    transform: scale(calc(0.55 + 0.45 * var(--pz))) translateY(calc(40px * (1 - var(--pz))));
    opacity: var(--pz);
  }
  /* Each stack lands across its own beat; its note fades in with it. */
  .services.is-choreo [data-i="0"] { --sp: clamp(0, calc((var(--p, 0) - 0.22) / 0.13), 1); }
  .services.is-choreo [data-i="1"] { --sp: clamp(0, calc((var(--p, 0) - 0.44) / 0.13), 1); }
  .services.is-choreo [data-i="2"] { --sp: clamp(0, calc((var(--p, 0) - 0.66) / 0.13), 1); }
  .services.is-choreo .stack-card {
    opacity: var(--sp, 1);
    transform: scale(calc(0.85 + 0.15 * var(--sp, 1))) translateY(calc(24px * (1 - var(--sp, 1))));
  }
  .services.is-choreo .services-note {
    opacity: calc(0.25 + 0.75 * var(--sp, 1));
  }
}

/* Mobile play: the composition zooms once at 30% visibility, cards fill
   180ms apart. No track, no sticky, no scroll locking. */
.services.is-mobile-play .services-pin {
  transform: scale(0.92); opacity: 0;
  transition: transform 0.55s var(--ease), opacity 0.45s ease-out;
}
.services.is-mobile-play .services-pin.is-zoomed { transform: none; opacity: 1; }
.services.is-mobile-play .stack-card {
  opacity: 0; transform: translateY(24px) scale(0.96);
  transition: opacity 0.45s ease-out, transform 0.5s var(--ease);
}
.services.is-mobile-play .stack-card.is-in { opacity: 1; transform: none; }

/* ---------- Services page ----------
   Layout: the hero answers "which one do I need?" with a chooser that jumps
   to the right tile. Five services, five tiles with different sizes and
   surfaces (Grove, Sage, the Oasis redesign as proof, Cream panel, a wide
   row), so the page reads as a menu, not a stack of identical blocks.
   Tiles are square-cornered; only the framed screenshot is rounded (16px).
   Citrus stays on the primary button, so the tiles use Grove marks. */

.svc-hero { padding-block: clamp(3rem, 2rem + 4vw, 5.5rem) clamp(2.5rem, 2rem + 2vw, 4rem); }
.svc-hero-grid { display: grid; gap: 2.5rem; align-items: center; }
.svc-hero-copy h1 { max-width: 12ch; }
.svc-hero-copy .lede { color: var(--muted); font-size: 1.25rem; max-width: 34ch; margin-top: 1.25rem; }

.chooser { border-top: 2px solid var(--grove); }
.chooser-heading {
  font-family: var(--text); font-size: .875rem; font-weight: 700;
  letter-spacing: .12em; text-transform: uppercase; color: var(--muted);
  padding-block: 1rem .25rem; margin: 0;
}
.chooser ul { list-style: none; margin: 0; padding: 0; }
.chooser li { border-bottom: 1px solid var(--line); }
.chooser a {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center;
  column-gap: 1rem; min-height: 64px; padding-block: .75rem;
  text-decoration: none; color: var(--ink);
}
.chooser a::after {
  content: "\2192"; grid-column: 2; grid-row: 1 / span 2; color: var(--grove); font-weight: 700; font-size: 1.25rem;
  transition: transform 450ms var(--ease);
}
.chooser-need { grid-column: 1; font-weight: 700; font-size: 1.125rem; }
.chooser-fit { grid-column: 1; color: var(--muted); font-size: .9375rem; }
.chooser a:hover .chooser-need { text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: .2em; }
.chooser a:hover::after { transform: translateX(6px); }

.svc-grid-section { padding-top: 0; }
.svc-grid { display: grid; gap: 1rem; }
.svc { padding: clamp(1.75rem, 1.2rem + 2vw, 2.75rem); display: grid; gap: 1rem; align-content: start; scroll-margin-top: 96px; }
.svc h2 { font-size: clamp(1.75rem, 1.4rem + 1.2vw, 2.4rem); }
.svc > p, .svc-proof-copy > p, .svc--wide p { color: var(--muted); max-width: 50ch; }

.svc--grove { background: var(--band); color: var(--band-ink); }
.svc--grove h2 { color: var(--band-ink); }
.svc--grove > p { color: var(--band-muted); }
.svc--grove .includes li { color: var(--band-ink); }
.svc--grove .includes li::before { background: var(--band-muted); }

.svc--sage { background: var(--sage); }
.svc--panel { background: var(--panel); }
.svc--proof { border: 1px solid var(--line); background: var(--bg); }
.svc--wide { border-top: 2px solid var(--grove); padding-inline: 0; }
.svc--wide > div { display: grid; gap: 1rem; }

.svc-proof-shot { margin: 0; }
.svc-proof-shot img {
  width: 100%; border-radius: 16px; aspect-ratio: 16 / 10; object-fit: cover; object-position: top;
  box-shadow: 0 30px 60px -40px var(--shadow);
}
.svc-proof-shot figcaption { margin-top: .75rem; font-size: .9375rem; color: var(--muted); }
.svc-proof-shot figcaption a { font-weight: 700; }

.includes { list-style: none; margin: .5rem 0 0; padding: 0; display: grid; gap: .6rem; }
.includes li { position: relative; padding-left: 1.5rem; color: var(--ink); }
/* Small square map-stop markers, not arrows: these are items, not links */
.includes li::before {
  content: ""; position: absolute; left: .15rem; top: .62em;
  width: .5rem; height: .5rem; background: var(--grove);
}
.includes--grid { gap: .6rem 2rem; }

/* Current-page marker: Grove underline (Citrus text would fail contrast on Cream) */
.desktop-nav a[aria-current="page"] { font-weight: 700; box-shadow: inset 0 -2px 0 var(--grove); }
.mobile-menu nav a[aria-current="page"] { font-weight: 700; box-shadow: inset 3px 0 0 var(--grove); }
.site-footer nav a[aria-current="page"] { color: var(--band-ink); font-weight: 700; }

@media (prefers-reduced-motion: no-preference) {
  html.js .svc-grid .reveal:nth-child(2) { transition-delay: 80ms; }
  html.js .svc-grid .reveal:nth-child(4) { transition-delay: 80ms; }
}

@media (min-width: 720px) {
  .includes--grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (min-width: 960px) {
  .svc-hero-grid { grid-template-columns: minmax(0, 6fr) minmax(0, 5fr); gap: 5rem; }
  .svc-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 1.25rem; }
  .svc--grove { grid-column: span 2; }
  .svc--proof { grid-column: span 2; grid-template-columns: minmax(0, 5fr) minmax(0, 6fr); gap: 2.5rem; align-items: center; }
  .svc--wide { grid-column: 1 / -1; grid-template-columns: minmax(0, 5fr) minmax(0, 6fr); gap: 2.5rem; align-items: start; padding-top: 2.5rem; }
  .svc--wide .includes--grid { margin-top: .4rem; }
}

/* ---------- Work ---------- */

.work { background: var(--sage); }
.work-grid { display: grid; gap: 3rem; align-items: center; }

.work-phone { margin: 0; justify-self: center; width: min(100%, 260px); }
.work-phone img {
  width: 100%;
  border-radius: 16px;
  border: 8px solid var(--grove);
  box-shadow: 0 40px 70px -40px var(--shadow);
}
[data-theme="dark"] .work-phone img { border-color: #0B110E; }

.work-lede { color: var(--muted); font-size: 1.1875rem; max-width: 44ch; margin-top: 1.25rem; }

.changes { list-style: none; margin: 2.25rem 0 2.5rem; padding: 0; display: grid; gap: 1.5rem; }
.changes li { display: grid; grid-template-columns: 2.25rem minmax(0, 1fr); column-gap: 1rem; }
.changes li::before {
  content: "";
  grid-row: span 2;
  width: 2.25rem; height: 2.25rem; margin-top: .1rem;
  background: var(--citrus);
  -webkit-mask: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20viewBox%3D%220%200%2048.0%2048.0%22%20width%3D%2248%22%20height%3D%2248%22%20role%3D%22img%22%20aria-label%3D%22Pinstack%20Design%22%3E%3Ctitle%3EPinstack%20Design%3C/title%3E%3Cpath%20fill-rule%3D%22evenodd%22%20d%3D%22M24%2045S8.5%2031.2%208.5%2019.2a15.5%2015.5%200%200%201%2031%200C39.5%2031.2%2024%2045%2024%2045ZM18.2%2012h11.6a1.7%201.7%200%200%201%200%203.4h-11.6a1.7%201.7%200%200%201%200%20-3.4ZM18.2%2018h11.6a1.7%201.7%200%200%201%200%203.4h-11.6a1.7%201.7%200%200%201%200%20-3.4ZM18.2%2024h11.6a1.7%201.7%200%200%201%200%203.4h-11.6a1.7%201.7%200%200%201%200%20-3.4Z%22%20fill%3D%22%23000%22/%3E%3C/svg%3E") center / contain no-repeat;
          mask: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20viewBox%3D%220%200%2048.0%2048.0%22%20width%3D%2248%22%20height%3D%2248%22%20role%3D%22img%22%20aria-label%3D%22Pinstack%20Design%22%3E%3Ctitle%3EPinstack%20Design%3C/title%3E%3Cpath%20fill-rule%3D%22evenodd%22%20d%3D%22M24%2045S8.5%2031.2%208.5%2019.2a15.5%2015.5%200%200%201%2031%200C39.5%2031.2%2024%2045%2024%2045ZM18.2%2012h11.6a1.7%201.7%200%200%201%200%203.4h-11.6a1.7%201.7%200%200%201%200%20-3.4ZM18.2%2018h11.6a1.7%201.7%200%200%201%200%203.4h-11.6a1.7%201.7%200%200%201%200%20-3.4ZM18.2%2024h11.6a1.7%201.7%200%200%201%200%203.4h-11.6a1.7%201.7%200%200%201%200%20-3.4Z%22%20fill%3D%22%23000%22/%3E%3C/svg%3E") center / contain no-repeat;
}
.changes h3 { font-size: 1.3rem; }
.changes p { color: var(--muted); margin-top: .25rem; max-width: 46ch; }

/* ---------- Process: a route of four stops ---------- */

.route { list-style: none; margin: 3.5rem 0 0; padding: 0; display: grid; gap: 2.5rem; position: relative; }
.stop { position: relative; padding-left: 4.25rem; }
.stop h3 { margin-bottom: .5rem; }
.stop p { color: var(--muted); font-size: 1.0625rem; max-width: 34ch; }

.marker {
  position: absolute; left: 0; top: -.2rem;
  width: 3rem; height: 3rem; border-radius: 50%;
  display: grid; place-items: center;
  font-family: var(--display); font-size: 1.25rem;
  background: var(--bg); color: var(--grove);
  border: 2px solid var(--grove);
  z-index: 1;
}
.marker-pin { border: 0; background: transparent; }
.marker-pin img { width: 3rem; height: 3rem; }
.marker-pin .pin-dark { display: none; }
[data-theme="dark"] .marker-pin .pin-light { display: none; }
[data-theme="dark"] .marker-pin .pin-dark { display: block; }

/* The dashed route line: vertical on phones, horizontal from 900px */
.route::before {
  content: "";
  position: absolute; left: calc(1.5rem - 1px); top: 1.5rem; bottom: 3rem;
  border-left: 2px dashed var(--line);
}

/* ---------- Pinned route stepper ----------
   When JS enables it (.pin-enabled on the section), .pin-track supplies
   the scroll distance and .pin-stage sticks to the viewport while the four
   stops take focus one by one. Without JS — or with reduced motion, or on
   a short viewport — the section renders as the normal stacked route. */
.pin-track { position: relative; }
/* Explicit background: the stage is transparent by default, and iOS Safari
   can sample the body (Grove) behind a stuck sticky layer for its bottom
   bar tint instead of the main background showing through it. */
.pin-stage { position: relative; background: var(--bg); }

html.js .process.pin-enabled { padding-block: 0; }
html.js .process.pin-enabled .pin-track { height: 360vh; }
html.js .process.pin-enabled .pin-stage {
  position: relative;
  /* Stop short of the bottom edge. A pinned layer touching the bottom
     makes iOS Safari paint its bottom bar solid (Grove) instead of
     staying transparent over the page. */
  height: calc(100vh - 5rem);
  height: calc(100svh - 5rem);
  display: flex;
  align-items: center;
  overflow: hidden;
}
/* Sticky is only applied while the pin is engaged: a sticky element merely
   entering the viewport makes iOS Safari paint its bottom bar solid green.
   JS toggles .is-pinned when the track reaches the top of the viewport. */
html.js .process.pin-enabled .pin-stage.is-pinned {
  position: sticky;
  top: 0;
}
html.js .process.pin-enabled .wrap { width: 100%; }

/* The focused stop renders full-size; the rest sit back smaller. */
html.js .process.pin-enabled .route { margin-top: 2.25rem; gap: 1.5rem; }
html.js .process.pin-enabled .stop {
  opacity: .3;
  transform: scale(.86);
  transform-origin: left center;
  filter: saturate(.7);
  transition:
    opacity .5s var(--ease),
    transform .5s var(--ease),
    filter .5s var(--ease);
}
html.js .process.pin-enabled .stop p { font-size: .9375rem; }
html.js .process.pin-enabled .stop.is-past { opacity: .55; transform: scale(.92); }
html.js .process.pin-enabled .stop.is-active { opacity: 1; transform: scale(1); filter: none; }
html.js .process.pin-enabled .stop.is-past .marker {
  background: var(--grove);
  border-color: var(--grove);
  color: var(--bg);
}
html.js .process.pin-enabled .stop.is-active .marker {
  border-color: var(--citrus);
  color: var(--citrus);
  box-shadow: 0 0 0 6px rgba(240, 138, 36, .16);
}

/* Step counter + progress fill: orientation while pinned.
   Hidden unless the stepper is active. */
.pin-count, .pin-progress { display: none; }
html.js .process.pin-enabled .pin-count {
  display: block;
  margin: 2rem 0 0;
  font-family: var(--display);
  font-size: 1rem;
  letter-spacing: .08em;
  color: var(--muted);
}
html.js .process.pin-enabled .pin-count .pin-total { opacity: .55; }
html.js .process.pin-enabled .pin-progress {
  display: block;
  margin-top: .75rem;
  max-width: 220px;
  height: 3px;
  border-radius: 3px;
  background: var(--line);
  overflow: hidden;
}
html.js .process.pin-enabled .pin-progress span {
  display: block;
  height: 100%;
  border-radius: 3px;
  background: var(--citrus);
  transform: scaleX(0);
  transform-origin: left center;
}

/* Desktop pinned layout: heading left, vertical route right, so the
   tall stage stays full instead of floating in empty space. */
@media (min-width: 960px) {
  html.js .process.pin-enabled .pin-grid {
    display: grid;
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
    gap: 4rem;
    align-items: center;
  }
  html.js .process.pin-enabled .route {
    grid-template-columns: 1fr;
    margin-top: 0;
  }
  html.js .process.pin-enabled .route::before {
    left: calc(1.5rem - 1px);
    right: auto;
    top: 1.5rem;
    bottom: 3rem;
    border-top: 0;
    border-left: 2px dashed var(--line);
  }
  html.js .process.pin-enabled .stop { padding-left: 4.25rem; padding-top: 0; }
  html.js .process.pin-enabled .marker { top: -.2rem; }
}

/* ---------- About ---------- */

.about-grid { display: grid; gap: 3rem; align-items: center; }
.about-figure { margin: 0; }
.about-figure img { width: 100%; border-radius: 16px; aspect-ratio: 4 / 3.4; object-fit: cover; }
.about-figure figcaption { margin-top: .9rem; font-size: .9375rem; color: var(--muted); }

.about-copy > p { color: var(--muted); max-width: 48ch; margin-top: 1.25rem; }
.about-copy > .pull-line {
  font-family: var(--display); color: var(--grove);
  font-size: clamp(1.5rem, 1.2rem + 1vw, 1.9rem); line-height: 1.25;
  margin-top: 1.75rem;
}

.promises { margin: 2.25rem 0 0; display: grid; gap: 1.25rem; }
.promises div { border-left: 3px solid var(--citrus); padding-left: 1rem; }
.promises dt { font-weight: 700; color: var(--ink); }
.promises dd { margin: .15rem 0 0; color: var(--muted); font-size: 1.0625rem; }

/* ---------- Contact + footer: one closing band ---------- */

.contact { background: var(--band); color: var(--band-ink); padding-bottom: clamp(3.5rem, 2.5rem + 3vw, 5rem); }
.contact h2 { color: var(--band-ink); font-size: clamp(2.5rem, 1.6rem + 3.4vw, 4.25rem); max-width: 12ch; }
.contact-grid { display: grid; gap: 2.5rem; align-items: end; }
.contact-intro { color: var(--band-muted); font-size: 1.1875rem; max-width: 40ch; margin-top: 1.5rem; }

.contact-action { display: grid; gap: .9rem; justify-items: start; }
.contact-email {
  font-family: var(--display);
  font-size: clamp(1.5rem, 1rem + 1.9vw, 2.4rem);
  line-height: 1.15;
  color: var(--band-ink);
  text-decoration: underline;
  text-decoration-color: var(--citrus);
  text-decoration-thickness: 3px;
  text-underline-offset: .22em;
  transition: text-decoration-color 200ms var(--ease), color 200ms var(--ease);
}
.contact-email:hover { color: #F59A3E; text-decoration-color: var(--band-ink); }
.contact-note { color: var(--band-muted); font-size: 1rem; }
.contact :focus-visible { outline-color: var(--citrus); }

/* Typewriter caret for the contact heading: blinks while typing and
   keeps blinking after the text is done. Added by JS only. */
.type-caret {
  display: inline-block;
  width: 0.11em; height: 1em;
  margin-left: 0.1em;
  vertical-align: -0.14em;
  background: currentColor;
  animation: type-caret-blink 1.06s steps(1) infinite;
}
@keyframes type-caret-blink {
  0%, 55% { opacity: 1; }
  56%, 100% { opacity: 0; }
}

.site-footer { background: var(--band); color: var(--band-muted); }
.footer-inner {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: 1.25rem 2rem; padding-block: 2rem 2.5rem;
  border-top: 1px solid rgba(251, 247, 240, .16);
}
/* Let the footer run under the iPhone's bottom bar and home indicator */
.site-footer { padding-bottom: env(safe-area-inset-bottom, 0px); }
.footer-inner { padding-bottom: calc(2.5rem + env(safe-area-inset-bottom, 0px)); }
.site-footer .brand img { height: 36px; }
.site-footer nav { display: flex; flex-wrap: wrap; gap: .25rem 1.75rem; }
.site-footer nav a {
  display: inline-flex; align-items: center; min-height: 44px;
  color: var(--band-ink); font-weight: 600; text-decoration: none;
}
.site-footer nav a:hover { text-decoration: underline; text-decoration-color: var(--citrus); text-decoration-thickness: 2px; }
.footer-meta { font-size: .9375rem; width: 100%; }

/* ---------- Motion (JS adds .js; content is fully visible without it) ---------- */

@media (prefers-reduced-motion: no-preference) {
  .hero-copy > *, .hero-shot {
    animation: rise 700ms var(--ease) both;
  }
  .hero-copy > :nth-child(2) { animation-delay: 60ms; }
  .hero-copy > :nth-child(3) { animation-delay: 120ms; }
  .hero-copy > :nth-child(4) { animation-delay: 180ms; }
  .hero-shot { animation-delay: 160ms; animation-duration: 900ms; }

  html.js .reveal { opacity: 0; translate: 0 18px; transition: opacity 600ms var(--ease), translate 600ms var(--ease); }
  html.js .reveal.is-visible { opacity: 1; translate: 0 0; }
}
@keyframes rise { from { opacity: 0; translate: 0 22px; } }

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

/* ---------- Breakpoints ---------- */

@media (min-width: 720px) {
  .route { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: 3rem; }
  .route::before { display: none; }
}

@media (min-width: 960px) {
  .desktop-nav { display: flex; }
  .header-cta { display: inline-flex; }
  .mobile-menu { display: none; }
  .header-inner { gap: 2rem; }
  .desktop-nav { margin-left: auto; margin-right: 1rem; }

  .hero-grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr); gap: 4rem; }
  .hero-shot { margin-right: calc(-1 * var(--gutter) - max(0px, (100vw - var(--wrap)) / 2)); }
  .hero-shot .browser { border-top-right-radius: 0; border-bottom-right-radius: 0; border-right: 0; }
  .hero-shot figcaption { padding-right: var(--gutter); }

  .work-grid { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: 5rem; }
  .work-phone { width: min(100%, 340px); }

  /* Horizontal route: stops sit on one dashed line, the last stop is the pin */
  .route { grid-template-columns: repeat(4, minmax(0, 1fr)); column-gap: 2.5rem; }
  .route::before {
    display: block;
    left: 1.5rem; right: calc(25% - 1rem); top: 1.5rem; bottom: auto;
    border-left: 0; border-top: 2px dashed var(--line);
  }
  .stop { padding-left: 0; padding-top: 4.75rem; }
  .marker { top: 0; }

  .about-grid { grid-template-columns: minmax(0, 6fr) minmax(0, 5fr); gap: 5rem; }

  .contact-grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 4rem; }
  .footer-meta { width: auto; }
}
