<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
<title>The Line That Outgrew the Quadrant · Patrick S. Melody, for Sean Ammirati</title>
<meta name="description" content="An interactive visual essay… one line, thirty years, one operating system. Built for Sean Ammirati of Growth Signals.">
<meta name="robots" content="noindex, nofollow">
<meta property="og:title" content="The Line That Outgrew the Quadrant">
<meta property="og:description" content="One line, thirty years, one operating system… told the only way it makes sense to tell it.">
<meta name="color-scheme" content="light only">
<meta name="theme-color" content="#F5EFE1">
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect width='32' height='32' fill='%23F5EFE1'/%3E%3Crect x='10' y='10' width='12' height='12' transform='rotate(45 16 16)' fill='%23A67C3D'/%3E%3C/svg%3E">
<script>document.documentElement.classList.add('js');</script>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Fraunces:ital,opsz,wght@0,9..144,300;0,9..144,400;0,9..144,500;1,9..144,300;1,9..144,400&family=Inter:wght@300;400;500&display=swap" rel="stylesheet">
<style>
/* ============================================================
THE LINE THAT OUTGREW THE QUADRANT
tokens · paper, tan, ink, one brass accent
============================================================ */
:root{
color-scheme:light only;
--paper:#F5EFE1;
--card:#F7F2E7;
--beige:#D8C4A0;
--camel:#B8946A;
--tan:#C9A96A;
--ink:#1A1A1A;
--brass:#A67C3D;
--muted:#6F6252;
--body:#2B261F;
--serif:'Fraunces',Georgia,'Times New Roman',serif;
--sans:'Inter',system-ui,-apple-system,'Segoe UI',sans-serif;
--stage-h:100vh;
}
*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;background:#F5EFE1;color-scheme:light only;forced-color-adjust:none}
body{
margin:0;background:#F5EFE1;background:var(--paper);color:var(--body);
font-family:var(--sans);font-weight:300;font-size:17px;line-height:1.6;
-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;
position:relative;z-index:0;
}
/* paper grain: one static tile, composited once */
body::before{
content:"";position:fixed;inset:0;z-index:-1;pointer-events:none;opacity:.55;mix-blend-mode:multiply;
background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 .36 0 0 0 0 .29 0 0 0 0 .2 0 0 0 .07 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}
h1,h2,h3{font-family:var(--serif);font-weight:300;line-height:1.05;margin:0;font-variation-settings:"opsz" 144}
p{margin:0}
a{color:inherit}
:focus-visible{outline:2px solid var(--brass);outline-offset:3px}
::selection{background:rgba(166,124,61,.22)}
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}

.eyebrow{font-family:var(--sans);font-size:.66rem;letter-spacing:.3em;text-transform:uppercase;color:var(--camel);font-weight:500}
.gem{display:inline-block;width:7px;height:7px;border:1px solid var(--brass);transform:rotate(45deg);flex:none}
.gem--solid{background:var(--brass)}
.rule{display:flex;align-items:center;justify-content:center;gap:16px;margin:0 auto}
.rule::before,.rule::after{content:"";height:1px;background:var(--beige);flex:0 0 clamp(40px,8vw,96px)}

/* ---------- hero ---------- */
.hero{
min-height:100vh;min-height:100svh;position:relative;
display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;
padding:8vh 6vw 19vh;
}
.hero__eyebrow{margin-bottom:2.4rem}
.hero__title{font-size:min(clamp(2.7rem,8vw,6.4rem),12.5vh);letter-spacing:-.015em;max-width:11ch;color:var(--ink)}
.hero__title em{font-style:italic;font-weight:300}
.hero__flourish{display:block;width:min(440px,72vw);height:26px;margin:2.6rem auto 2.2rem;overflow:visible}
.hero__flourish path,.hero__flourish line{stroke:var(--camel);fill:none;stroke-width:1}
.hero__flourish .fl-gem{stroke:var(--brass);fill:none}
.hero__sub{font-family:var(--serif);font-style:italic;font-weight:300;font-size:clamp(1.15rem,2.1vw,1.5rem);color:var(--muted);max-width:32ch;line-height:1.4}
.hero__meta{margin-top:2.6rem;font-size:.74rem;letter-spacing:.08em;color:var(--muted)}
.hero__scroll{
position:absolute;left:50%;bottom:4vh;transform:translateX(-50%);
display:flex;flex-direction:column;align-items:center;gap:12px;
font-size:.6rem;letter-spacing:.34em;text-transform:uppercase;color:var(--camel);text-decoration:none;font-weight:500;
}
.hero__scroll i{display:block;width:1px;height:58px;background:var(--beige);position:relative;overflow:hidden}
.hero__scroll i::after{content:"";position:absolute;left:0;top:-14px;width:1px;height:14px;background:var(--brass);animation:drop 2.4s cubic-bezier(.45,0,.2,1) infinite}
@keyframes drop{to{transform:translateY(76px)}}
/* page-load choreography (gated) */
.js .hero__eyebrow,.js .hero__title,.js .hero__flourish,.js .hero__sub,.js .hero__meta,.js .hero__scroll{opacity:0}
@media (prefers-reduced-motion:no-preference){
.js .hero__eyebrow,.js .hero__title,.js .hero__flourish,.js .hero__sub,.js .hero__meta,.js .hero__scroll{animation:rise 1.1s cubic-bezier(.2,.65,.2,1) forwards}
.js .hero__title{animation-delay:.15s}
.js .hero__flourish{animation-delay:.55s}
.js .hero__sub{animation-delay:.75s}
.js .hero__meta{animation-delay:.95s}
.js .hero__scroll{animation-delay:1.3s;animation-name:rise-static}
.js .hero__flourish .fl-line{stroke-dasharray:440;stroke-dashoffset:440;animation:draw 1.6s cubic-bezier(.4,0,.2,1) .6s forwards}
.js .hero__flourish .fl-gem{opacity:0;animation:rise .6s ease 1.5s forwards}
}
@media (prefers-reduced-motion:reduce){
.js .hero__eyebrow,.js .hero__title,.js .hero__flourish,.js .hero__sub,.js .hero__meta,.js .hero__scroll{opacity:1}
.hero__scroll i::after{animation:none;top:22px}
}
@keyframes rise{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}
@keyframes rise-static{to{opacity:1}}
@keyframes draw{to{stroke-dashoffset:0}}

/* ---------- intro: the operating system + how to read ---------- */
.intro{max-width:1060px;margin:0 auto;padding:6vh 6vw 12vh}
.os{position:relative;border:1px solid var(--beige);background:rgba(247,242,231,.65);padding:3.2rem clamp(1.4rem,5vw,4rem) 3rem;text-align:center}
.os__corners,.os__corners::before,.os__corners::after,.os::before,.os::after{position:absolute;pointer-events:none}
.os__corners{inset:0}
.os::before,.os::after,.os__corners::before,.os__corners::after{content:"";width:18px;height:18px;border:0 solid var(--brass)}
.os::before{top:-1px;left:-1px;border-top-width:1px;border-left-width:1px}
.os::after{top:-1px;right:-1px;border-top-width:1px;border-right-width:1px}
.os__corners::before{bottom:-1px;left:-1px;border-bottom-width:1px;border-left-width:1px}
.os__corners::after{bottom:-1px;right:-1px;border-bottom-width:1px;border-right-width:1px}
.os__title{font-size:clamp(1.6rem,3vw,2.3rem);margin:.9rem auto 0;max-width:22ch;color:var(--ink)}
.os__loop{list-style:none;margin:2rem 0 0;padding:0;display:flex;flex-wrap:wrap;justify-content:center;align-items:center;gap:.55rem 0;font-family:var(--serif);font-size:clamp(1.02rem,1.55vw,1.28rem);font-weight:400;color:var(--ink)}
.os__loop li{display:flex;align-items:center;white-space:nowrap}
.os__loop .arr{width:38px;height:10px;margin:0 12px;overflow:visible;flex:none}
.os__loop .arr path{stroke:var(--camel);fill:none;stroke-width:1}
.os__loop .loop{width:20px;height:20px;margin-left:10px;flex:none}
.os__loop .loop path{stroke:var(--brass);fill:none;stroke-width:1.1}
.os__note{margin-top:1.7rem;font-family:var(--serif);font-style:italic;font-weight:300;color:var(--muted);font-size:1.05rem}
.legend{display:grid;grid-template-columns:repeat(3,1fr);gap:2.2rem clamp(1.2rem,3vw,2.6rem);margin-top:3.6rem}
.legend h3{font-size:1.12rem;font-weight:400;margin-bottom:.45rem;color:var(--ink);display:flex;align-items:center;gap:10px}
.legend p{font-size:.94rem;color:var(--muted)}
.legend__axis{display:inline-block;width:22px;height:1px;background:var(--ink);position:relative;flex:none}
.legend__axis--v{width:1px;height:22px}
.legend__brass{color:var(--brass)}
.intro__hint{margin-top:3rem;text-align:center;font-size:.8rem;color:var(--muted);letter-spacing:.04em}
.js .fade{opacity:0;transform:translateY(14px)}
@media (max-width:899px){
.legend{grid-template-columns:1fr;gap:1.6rem}
.os__loop{flex-direction:column;gap:.2rem}
.os__loop .arr{transform:rotate(90deg);margin:6px 0}
.os__loop li{flex-direction:column}
.os__loop li:last-child{flex-direction:row}
}

/* ---------- story: pinned stage + scrolling steps ---------- */
.story{position:relative}
.stage{position:relative;height:var(--stage-h);z-index:2}
.stage__inner{position:absolute;inset:0;padding:2.5vh 2vw 2.5vh 2.6vw;overflow:hidden}
.stage svg{width:100%;height:100%;display:block;overflow:visible}
.stage.is-sticky{position:sticky;top:0}
.steps{position:relative;z-index:1}
.step{display:flex;align-items:center;padding:0 clamp(1.2rem,6vw,4rem)}
.step__card{max-width:40ch;opacity:.28;transform:translateY(10px);transition:opacity .55s ease,transform .55s ease}
.step.is-active .step__card{opacity:1;transform:none}
.step__eyebrow{display:flex;align-items:center;gap:12px;margin:0}
.step__eyebrow::after{content:"";flex:1;height:1px;background:var(--beige);margin-left:6px}
.step__num{font-family:var(--serif);font-size:1rem;letter-spacing:.1em;color:var(--brass);font-variation-settings:"opsz" 30}
.step__title{font-size:clamp(1.7rem,2.5vw,2.3rem);margin:1rem 0 1rem;color:var(--ink);letter-spacing:-.008em}
.step__title em{font-style:italic}
.step__body{font-size:1.03rem;line-height:1.66;color:var(--body)}
.step__body strong{font-weight:500;color:var(--brass)}
.step__body em{font-family:var(--serif);font-style:italic;font-size:1.07em}
.ledger-src{display:none}
@media (min-width:900px){
.story{display:grid;grid-template-columns:minmax(0,1.55fr) minmax(0,1fr);align-items:start}
.steps{padding-left:1vw;padding-right:5vw}
.step{padding:0}
}
@media (max-width:899px){
.stage{position:sticky;top:0;background:var(--paper)}
.stage::after{content:"";position:absolute;left:0;right:0;bottom:0;height:1px;background:var(--beige)}
.stage__inner{padding:2vh 3vw 2.4vh}
.step__card{max-width:none}
.step__title{font-size:1.55rem}
.step__body{font-size:.98rem}
.proposal{padding-top:10vh}
}
@media (prefers-reduced-motion:reduce){
.step__card{transition:opacity .3s ease;transform:none}
}

/* ---------- the figure ---------- */
#fig text{font-family:var(--sans);font-weight:400}
.t-axis{font-size:13px;letter-spacing:3.4px;text-transform:uppercase;fill:var(--muted);font-weight:500}
.t-age{font-size:12px;fill:var(--ink);fill-opacity:.72}
.t-age--today{font-family:var(--serif);font-style:italic;font-size:12.5px;fill:var(--brass);fill-opacity:1;letter-spacing:.2px}
.t-q{font-family:var(--serif);font-style:italic;font-size:15px;fill:var(--brass)}
.t-num{font-family:var(--serif);font-size:13px;fill:var(--muted);fill-opacity:.75;letter-spacing:1px}
.t-note{font-family:var(--serif);font-style:italic;font-size:13px;fill:var(--ink);fill-opacity:.8}
.t-note--brass{fill:var(--brass);fill-opacity:1}
#regionLow{fill:rgba(184,148,106,.09)}
.grid{stroke:var(--ink);stroke-opacity:.09;stroke-width:1}
.axis,.frame{stroke:var(--ink);stroke-opacity:.55;stroke-width:1;fill:none}
#frameTop,#frameRight{stroke-opacity:.45}
.corner{stroke:var(--brass);stroke-width:1.1;fill:none}
.tick{stroke:var(--ink);stroke-opacity:.35;stroke-width:1}
.tick--major{stroke-opacity:.7}
.seg{fill:none;stroke:var(--ink);stroke-width:2.8;stroke-linecap:round;stroke-linejoin:round}
.seg--brass{stroke:var(--brass);stroke-width:3.1}
.br{fill:none;stroke:var(--ink);stroke-width:2.4;stroke-linecap:round;stroke-linejoin:round}
.br[data-depth="1"]{stroke-width:1.6}
.wall{stroke:var(--ink);stroke-opacity:.5;stroke-width:1.2}
.spoke{stroke:var(--ink);stroke-opacity:.5;stroke-width:1}
.spoke-dot{fill:var(--ink)}
.origin__halo{fill:none;stroke:var(--brass);stroke-width:1}
.tip{fill:var(--brass)}
.node{cursor:pointer;outline:none}
.node__hit{fill:transparent;stroke:transparent;stroke-width:1}
.node__dot{fill:var(--ink);stroke:var(--paper);stroke-width:2.2;transition:stroke .25s}
.node__gem{fill:var(--brass);stroke:var(--paper);stroke-width:2;transition:stroke .25s}
.node:hover .node__dot,.node:focus-visible .node__dot,.node.is-open .node__dot{stroke:var(--brass)}
.node:hover .node__gem,.node:focus-visible .node__gem,.node.is-open .node__gem{stroke:var(--ink)}
.node:focus-visible .node__hit{stroke:var(--brass);stroke-dasharray:2 3}
.node:not(.is-live){pointer-events:none}
.ghost{opacity:0}
.js .reveal,.js .draw,.js .seg,.js .br,.js .node,.js #ticks>*,.js #baseline{opacity:0}
@media (max-width:899px){
/* phone-only contrast lift: the tan secondary tones move toward the ink, palette unchanged */
:root{--muted:#463D30;--camel:#7E5C2C;--body:#221D17}
.t-axis{fill:#463D30}
.t-age{fill-opacity:.92}
.t-q{fill:#7E5C2C}
.note__field::placeholder{color:rgba(70,61,48,.72)}
.t-axis{font-size:23px;letter-spacing:5px}
.t-age{font-size:22px}
.t-age--today{font-size:23px}
.t-q{font-size:27px}
.t-num,.t-note,.t-age:not(.t-age--key):not(.t-age--today),#lblAge{display:none}
.seg{stroke-width:4.8}
.seg--brass{stroke-width:5.3}
.br{stroke-width:3.8}
.br[data-depth="1"]{stroke-width:2.6}
.axis,.frame,.grid,.tick,.wall,.spoke,.corner,.origin__halo{stroke-width:1.9}
.node__dot,.node__gem{stroke-width:3.2}
}

/* ---------- ledger: the operating system at this scale ---------- */
.ledger{
position:absolute;z-index:6;width:284px;padding:16px 18px 15px;
background:var(--card);border:1px solid var(--beige);box-shadow:0 24px 46px -28px rgba(26,26,26,.5);
opacity:0;visibility:hidden;transform:translateY(6px);pointer-events:none;
transition:opacity .28s ease,transform .28s ease,visibility 0s linear .28s;
}
.ledger.is-open{opacity:1;visibility:visible;transform:none;pointer-events:auto;transition:opacity .28s ease,transform .28s ease}
.ledger::before,.ledger::after{content:"";position:absolute;width:14px;height:14px;border:0 solid var(--brass)}
.ledger::before{top:-1px;left:-1px;border-top-width:1px;border-left-width:1px}
.ledger::after{bottom:-1px;right:-1px;border-bottom-width:1px;border-right-width:1px}
.ledger__head{display:flex;justify-content:space-between;align-items:baseline;gap:10px;margin-bottom:10px;padding-bottom:9px;border-bottom:1px solid var(--beige)}
.ledger__title{font-family:var(--serif);font-size:1.02rem;font-weight:400;color:var(--ink)}
.ledger__num{font-family:var(--serif);color:var(--brass);font-size:.86rem;letter-spacing:.08em;font-variation-settings:"opsz" 30}
.ledger dl{margin:0;display:grid;grid-template-columns:auto 1fr;column-gap:14px;row-gap:7px;align-items:baseline}
.ledger dt{font-size:.58rem;letter-spacing:.26em;text-transform:uppercase;color:var(--camel);font-weight:500;padding-top:4px;white-space:nowrap}
.ledger dd{margin:0;font-family:var(--serif);font-style:italic;font-size:.94rem;line-height:1.35;color:var(--ink)}
.ledger dd.is-brass{color:var(--brass)}
.ledger__close{position:absolute;top:8px;right:10px;border:0;background:none;color:var(--muted);font-size:1.1rem;line-height:1;padding:4px 6px;cursor:pointer;display:none}
@media (max-width:899px){
.ledger{left:10px!important;right:10px;width:auto;top:auto!important;bottom:14px;padding-right:34px}
.ledger__close{display:block}
}

/* ---------- the proposal ---------- */
.proposal{max-width:780px;margin:0 auto;padding:18vh 6vw 8vh}
.proposal__copy{font-family:var(--serif);font-weight:300;font-size:clamp(1.32rem,2.35vw,1.82rem);line-height:1.44;color:var(--ink);margin-top:1.6rem}
.proposal__copy em{font-style:italic}
.note{margin-top:3.4rem;position:relative}
.note__label{display:block;margin-bottom:.4rem}
.note__field{
display:block;width:100%;background:transparent;border:0;border-bottom:1px solid var(--camel);border-radius:0;
padding:14px 0 16px;min-height:150px;resize:none;overflow:hidden;outline:none;
font-family:var(--serif);font-style:italic;font-weight:300;font-size:1.28rem;line-height:1.45;color:var(--ink);
transition:border-color .3s,box-shadow .3s;
}
.note__field::placeholder{color:rgba(111,98,82,.5)}
.note__field:focus{border-bottom-color:var(--brass);box-shadow:0 1px 0 var(--brass)}
.note__row{display:flex;justify-content:space-between;align-items:center;gap:1.2rem;margin-top:1.5rem;flex-wrap:wrap}
.note__hint{font-size:.78rem;color:var(--muted);letter-spacing:.02em}
.btn{
appearance:none;border:1px solid var(--ink);background:var(--ink);color:var(--paper);
font-family:var(--sans);font-size:.68rem;letter-spacing:.3em;text-transform:uppercase;font-weight:500;
padding:15px 22px 14px 24px;cursor:pointer;display:inline-flex;align-items:center;gap:16px;
transition:background .3s,border-color .3s,transform .3s;
}
.btn svg{width:28px;height:8px;overflow:visible}
.btn svg path{stroke:currentColor;fill:none;stroke-width:1}
.btn:hover{background:var(--brass);border-color:var(--brass)}
.btn:focus-visible{outline:2px solid var(--brass);outline-offset:4px}
.btn[disabled]{opacity:.55;cursor:default}
.note__status{min-height:1.5em;margin-top:1rem;font-family:var(--serif);font-style:italic;color:var(--brass);font-size:1.02rem}
.note__done{position:absolute;inset:0;display:flex;flex-direction:column;justify-content:center;gap:1rem;opacity:0;visibility:hidden;transition:opacity .7s ease .25s,visibility 0s linear .95s}
.note__done p{font-family:var(--serif);font-size:clamp(1.3rem,2.2vw,1.7rem);font-weight:300;color:var(--ink);line-height:1.4}
.note.is-sent .note__form{opacity:0;pointer-events:none;transition:opacity .45s ease}
.note.is-sent .note__done{opacity:1;visibility:visible;transition:opacity .7s ease .25s}
.hp{position:absolute;left:-9999px;width:1px;height:1px;opacity:0;overflow:hidden}

/* ---------- footer ---------- */
.foot{max-width:780px;margin:0 auto;padding:6vh 6vw 9vh;text-align:center;font-size:.76rem;color:var(--muted);letter-spacing:.03em}
.foot p{margin:.5rem 0}
.foot em{font-family:var(--serif);font-size:.98rem;letter-spacing:0}
.foot .rule{margin-bottom:2.2rem}

@media (prefers-reduced-motion:reduce){
*,*::before,*::after{scroll-behavior:auto!important}
}
</style>
</head>
<body>

<!-- ============================== HERO ============================== -->
<header class="hero" id="top">
<p class="eyebrow hero__eyebrow">An explorable · for Sean Ammirati</p>
<h1 class="hero__title">The Line That <em>Outgrew</em> the Quadrant</h1>
<svg class="hero__flourish" viewBox="0 0 440 26" aria-hidden="true">
<line class="fl-line" x1="0" y1="13" x2="440" y2="13"/>
<rect class="fl-gem" x="215.5" y="8.5" width="9" height="9" transform="rotate(45 220 13)"/>
</svg>
<p class="hero__sub">Thirty years, one line, one operating system… the way I have seen the world since I was twelve.</p>
<p class="hero__meta">Patrick S. Melody · read slowly, scroll slower</p>
<a class="hero__scroll" href="#intro" id="scrollHint"><span>Scroll</span><i aria-hidden="true"></i></a>
</header>

<!-- ============================== INTRO ============================== -->
<section class="intro" id="intro" aria-labelledby="osTitle">
<div class="os fade">
<span class="os__corners" aria-hidden="true"></span>
<p class="eyebrow">The operating system</p>
<h2 class="os__title" id="osTitle">One idea, run at every scale</h2>
<ol class="os__loop" aria-label="The recurring loop">
<li>See the signal others miss<svg class="arr" viewBox="0 0 38 10" aria-hidden="true"><path d="M0 5H36M32 1.5l4 3.5-4 3.5"/></svg></li>
<li>Match product to market<svg class="arr" viewBox="0 0 38 10" aria-hidden="true"><path d="M0 5H36M32 1.5l4 3.5-4 3.5"/></svg></li>
<li>Create value<svg class="arr" viewBox="0 0 38 10" aria-hidden="true"><path d="M0 5H36M32 1.5l4 3.5-4 3.5"/></svg></li>
<li>Route it back to people<svg class="arr" viewBox="0 0 38 10" aria-hidden="true"><path d="M0 5H36M32 1.5l4 3.5-4 3.5"/></svg></li>
<li>The market shifts<svg class="arr" viewBox="0 0 38 10" aria-hidden="true"><path d="M0 5H36M32 1.5l4 3.5-4 3.5"/></svg></li>
<li>Pivot<svg class="loop" viewBox="0 0 20 20" aria-hidden="true"><path d="M16.5 10a6.5 6.5 0 1 1-2.2-4.9M14.4 1.6v3.9h-3.9"/></svg></li>
</ol>
<p class="os__note">It has run from Airheads to $120 million. Only the size of the numbers changes.</p>
</div>

<div class="legend">
<div class="fade">
<h3><span class="legend__axis legend__axis--v" aria-hidden="true"></span>Enlightenment ↕ Entrapment</h3>
<p>The vertical axis. Up is a life you are building… down is a life that is holding you.</p>
</div>
<div class="fade">
<h3><span class="legend__axis" aria-hidden="true"></span>Taking ↔ Giving</h3>
<p>The horizontal axis, resolved at twenty-one. Left is learning to capture value… right is routing it back.</p>
</div>
<div class="fade">
<h3><span class="gem gem--solid" aria-hidden="true"></span><span class="legend__brass">Brass</span></h3>
<p>Every place the value went back to people. The soul of the line is in brass.</p>
</div>
</div>
<p class="intro__hint fade">Hover or tap any point on the line to see the same four moves at that scale.</p>
</section>

<!-- ============================== STORY ============================== -->
<section class="story" id="story" aria-label="The line, beat by beat">

<div class="stage" id="stage">
<div class="stage__inner" id="stageInner">
<svg id="fig" viewBox="0 0 1000 900" preserveAspectRatio="xMidYMid meet" role="group" aria-labelledby="figTitle figDesc">
<title id="figTitle">A single line travels across a timeline from age twelve to forty-two.</title>
<desc id="figDesc">The line begins at the top, in enlightenment, dips toward entrapment through a grocery store, an audit, a bank and a wall, turns upward at the origin marked by Patrick's father, climbs through eleven restaurant locations and a decade in security, and finally leaves the quadrant at the top-right corner, rising into an evergreen tree drawn in the same line.</desc>
<g id="world">

<g id="field">
<rect id="regionLow" class="reveal" data-beat="3" x="90" y="425" width="850" height="335"/>
<g id="grid"><line class="grid" x1="175" y1="90" x2="175" y2="760"/>
<line class="grid" x1="345" y1="90" x2="345" y2="760"/>
<line class="grid" x1="685" y1="90" x2="685" y2="760"/>
<line class="grid" x1="826.7" y1="90" x2="826.7" y2="760"/>
<line class="grid" x1="90" y1="257.5" x2="940" y2="257.5"/>
<line class="grid" x1="90" y1="592.5" x2="940" y2="592.5"/></g>
<line id="axisTop" class="axis" x1="90" y1="425" x2="90" y2="90"/>
<line id="axisBottom" class="axis draw" x1="90" y1="425" x2="90" y2="760"/>
<line id="frameTop" class="frame draw" x1="90" y1="90" x2="940" y2="90"/>
<line id="frameRight" class="frame draw" x1="940" y1="90" x2="940" y2="760"/>
<line id="baseline" class="frame" x1="90" y1="760" x2="940" y2="760"/>
<line id="midline" class="axis draw" x1="90" y1="425" x2="940" y2="425"/>
<line id="divider" class="axis draw" x1="515" y1="90" x2="515" y2="760"/>
<g id="corners" class="reveal" data-beat="4">
<path class="corner" d="M80 112V80H112"/>
<path class="corner" d="M918 80H950V112"/>
<path class="corner" d="M950 738V770H918"/>
<path class="corner" d="M112 770H80V738"/>
</g>
<g id="ticks"><line class="tick tick--major" x1="90" y1="760" x2="90" y2="769"/>
<text class="t-age t-age--key" x="90" y="786" text-anchor="middle">12</text>
<line class="tick" x1="118.3" y1="760" x2="118.3" y2="765"/>
<line class="tick tick--major" x1="146.7" y1="760" x2="146.7" y2="769"/>
<text class="t-age" x="146.7" y="786" text-anchor="middle">14</text>
<line class="tick tick--major" x1="175" y1="760" x2="175" y2="769"/>
<text class="t-age" x="175" y="786" text-anchor="middle">15</text>
<line class="tick" x1="203.3" y1="760" x2="203.3" y2="765"/>
<line class="tick tick--major" x1="231.7" y1="760" x2="231.7" y2="769"/>
<text class="t-age" x="231.7" y="786" text-anchor="middle">17</text>
<line class="tick" x1="260" y1="760" x2="260" y2="765"/>
<line class="tick" x1="288.3" y1="760" x2="288.3" y2="765"/>
<line class="tick" x1="316.7" y1="760" x2="316.7" y2="765"/>
<line class="tick tick--major" x1="345" y1="760" x2="345" y2="769"/>
<text class="t-age t-age--key" x="345" y="786" text-anchor="middle">21</text>
<line class="tick" x1="373.3" y1="760" x2="373.3" y2="765"/>
<line class="tick" x1="401.7" y1="760" x2="401.7" y2="765"/>
<line class="tick" x1="430" y1="760" x2="430" y2="765"/>
<line class="tick" x1="458.3" y1="760" x2="458.3" y2="765"/>
<line class="tick tick--major" x1="486.7" y1="760" x2="486.7" y2="769"/>
<text class="t-age t-age--key" x="486.7" y="786" text-anchor="middle">26</text>
<line class="tick" x1="515" y1="760" x2="515" y2="765"/>
<line class="tick" x1="543.3" y1="760" x2="543.3" y2="765"/>
<line class="tick" x1="571.7" y1="760" x2="571.7" y2="765"/>
<line class="tick" x1="600" y1="760" x2="600" y2="765"/>
<line class="tick" x1="628.3" y1="760" x2="628.3" y2="765"/>
<line class="tick" x1="656.7" y1="760" x2="656.7" y2="765"/>
<line class="tick tick--major" x1="685" y1="760" x2="685" y2="769"/>
<text class="t-age t-age--key" x="685" y="786" text-anchor="middle">33</text>
<line class="tick" x1="713.3" y1="760" x2="713.3" y2="765"/>
<line class="tick" x1="741.7" y1="760" x2="741.7" y2="765"/>
<line class="tick" x1="770" y1="760" x2="770" y2="765"/>
<line class="tick" x1="798.3" y1="760" x2="798.3" y2="765"/>
<line class="tick" x1="826.7" y1="760" x2="826.7" y2="765"/>
<line class="tick" x1="855" y1="760" x2="855" y2="765"/>
<line class="tick" x1="883.3" y1="760" x2="883.3" y2="765"/>
<line class="tick" x1="911.7" y1="760" x2="911.7" y2="765"/>
<line class="tick tick--major" x1="940" y1="760" x2="940" y2="769"/></g>
<g id="labels">
<text id="lblEnl" class="t-axis" transform="rotate(-90 66 215)" x="66" y="215" text-anchor="middle">Enlightenment</text>
<text id="lblEnt" class="t-axis reveal" data-beat="3" transform="rotate(-90 66 485)" x="66" y="485" text-anchor="middle">Entrapment</text>
<text id="qTaking" class="t-q ghost" x="90" y="74">taking…</text>
<text id="qGiving" class="t-q ghost" x="940" y="74" text-anchor="end">or giving?</text>
<text id="lblTaking" class="t-axis reveal" x="90" y="74">Taking</text>
<text id="lblGiving" class="t-axis reveal" x="940" y="74" text-anchor="end">Giving</text>
<text id="lblAge" class="t-axis reveal" x="515" y="804" text-anchor="middle" data-beat="4">age</text>
<g id="numerals" class="reveal" data-beat="4">
<text class="t-num" x="926" y="413" text-anchor="end">I</text>
<text class="t-num" x="104" y="413">II</text>
<text class="t-num" x="104" y="449">III</text>
<text class="t-num" x="926" y="449" text-anchor="end">IV</text>
</g>
</g>
<g id="wall">
<line class="wall draw" x1="469" y1="343.1" x2="469" y2="551.6"/>
</g>
<g id="origin" class="reveal" data-beat="7">
<circle class="origin__halo" cx="515" cy="425" r="15"/>
</g>
<g id="spokes"><line class="spoke reveal" data-beat="9" x1="718" y1="229.0" x2="696" y2="246.3"/>
<circle class="spoke-dot reveal" data-beat="9" cx="696" cy="246.3" r="2.2"/>
<line class="spoke reveal" data-beat="9" x1="718" y1="229.0" x2="740" y2="248.8"/>
<circle class="spoke-dot reveal" data-beat="9" cx="740" cy="248.8" r="2.2"/>
<line class="spoke reveal" data-beat="9" x1="718" y1="229.0" x2="700" y2="206.6"/>
<circle class="spoke-dot reveal" data-beat="9" cx="700" cy="206.6" r="2.2"/>
<line class="spoke reveal" data-beat="9" x1="718" y1="229.0" x2="738" y2="209.1"/>
<circle class="spoke-dot reveal" data-beat="9" cx="738" cy="209.1" r="2.2"/></g>
<g id="notes">
<text class="t-note reveal" data-beat="1" x="94" y="153.3">Airheads, resold from a locker</text>
<text class="t-note t-note--brass reveal" data-beat="2" x="156" y="109.9">$7,000 · two mission trips</text>
<text class="t-note reveal" data-beat="3" x="200" y="385.3" text-anchor="end">the first step down</text>
<text class="t-note reveal" data-beat="4" x="302" y="147.1">$32K in one summer</text>
<text class="t-note reveal" data-beat="4" x="300" y="367.9">the audit</text>
<text class="t-note reveal" data-beat="5" x="386" y="551.6">hollow metrics</text>
<text class="t-note t-note--brass reveal" data-beat="6" x="418" y="305.9">lifting people up</text>
<text class="t-note reveal" data-beat="6" x="484" y="370.4">a wall</text>
<text class="t-note t-note--brass reveal" data-beat="7" x="528" y="452.3">the origin</text>
<text class="t-note reveal" data-beat="8" x="600" y="400.2">$300K · disrupted in month two</text>
<text class="t-note t-note--brass reveal" data-beat="8" x="612" y="176.9">eleven locations · 215 jobs</text>
<text class="t-note reveal" data-beat="9" x="706" y="278.6">hub &amp; spoke</text>
<text class="t-note reveal" data-beat="10" x="786" y="209.1">$120M+ influenced</text>
<text class="t-note t-note--brass reveal" data-beat="10" x="872" y="176.9">the #1 wage</text>
</g>
</g>
<g id="tree"><path class="br" data-t="0.046" data-depth="0" d="M964.6 41.3C865.7 26 749.1 46.2 680.6 13.7"/>
<path class="br" data-t="0.058" data-depth="1" d="M948.8 39.2Q938.7 22.8 925.7 13.5"/>
<path class="br" data-t="0.070" data-depth="1" d="M932.8 37.6Q918 50.3 902.6 55.2"/>
<path class="br" data-t="0.082" data-depth="1" d="M916.7 36.4Q905.1 21.9 891.6 14.5"/>
<path class="br" data-t="0.094" data-depth="1" d="M900.4 35.6Q888.2 46.1 875.5 50.2"/>
<path class="br" data-t="0.106" data-depth="1" d="M884 35Q873.3 18.6 860 9.6"/>
<path class="br" data-t="0.118" data-depth="1" d="M867.7 34.7Q855.8 45.1 843.5 49.3"/>
<path class="br" data-t="0.130" data-depth="1" d="M851.4 34.5Q841.8 18.1 829.4 8.8"/>
<path class="br" data-t="0.142" data-depth="1" d="M835.2 34.3Q824.7 45.8 813.1 51.3"/>
<path class="br" data-t="0.154" data-depth="1" d="M819.2 34.1Q813.4 22 805.1 14.6"/>
<path class="br" data-t="0.166" data-depth="1" d="M803.3 33.8Q794.7 44.8 784.6 50.4"/>
<path class="br" data-t="0.178" data-depth="1" d="M787.8 33.3Q780.1 23.2 771.1 17.9"/>
<path class="br" data-t="0.190" data-depth="1" d="M772.6 32.6Q761.8 43.1 750.2 47.6"/>
<path class="br" data-t="0.202" data-depth="1" d="M757.8 31.5Q749.8 20.6 740.1 15"/>
<path class="br" data-t="0.214" data-depth="1" d="M743.5 30Q735.5 39.2 726.4 43.6"/>
<path class="br" data-t="0.226" data-depth="1" d="M729.7 28.1Q724.2 19.1 717.2 14.1"/>
<path class="br" data-t="0.238" data-depth="1" d="M716.4 25.5Q708.4 32.4 700.2 35"/>
<path class="br" data-t="0.250" data-depth="1" d="M703.8 22.3Q698.5 13 691.5 7.7"/>
<path class="br" data-t="0.262" data-depth="1" d="M691.8 18.4Q684.2 25.8 676 29"/>
<path class="br" data-t="0.122" data-depth="0" d="M962.2 5.7C1026.4 -8.5 1103.8 -0.1 1147.4 -24.2"/>
<path class="br" data-t="0.134" data-depth="1" d="M981.8 2.1Q997.3 14.8 1013.1 19.6"/>
<path class="br" data-t="0.146" data-depth="1" d="M1002 -0.5Q1011.7 -18.7 1024.9 -29.4"/>
<path class="br" data-t="0.158" data-depth="1" d="M1022.3 -2.4Q1033.6 9.4 1045.9 14.7"/>
<path class="br" data-t="0.170" data-depth="1" d="M1042.6 -4Q1047.9 -17.4 1056.3 -25.9"/>
<path class="br" data-t="0.182" data-depth="1" d="M1062.5 -5.5Q1074.7 5.5 1087.5 9.9"/>
<path class="br" data-t="0.194" data-depth="1" d="M1081.9 -7.3Q1089.6 -19.1 1099.3 -25.6"/>
<path class="br" data-t="0.206" data-depth="1" d="M1100.3 -9.8Q1111.3 -1.6 1122.3 1.1"/>
<path class="br" data-t="0.218" data-depth="1" d="M1117.5 -13.2Q1122.7 -24.3 1130.1 -31.1"/>
<path class="br" data-t="0.230" data-depth="1" d="M1133.3 -17.9Q1140.1 -10.2 1147.8 -6.6"/>
<path class="br" data-t="0.201" data-depth="0" d="M958.3 -31.1C877 -56.1 776.3 -53.3 722.6 -89"/>
<path class="br" data-t="0.213" data-depth="1" d="M940.6 -36Q933.2 -57.3 920.8 -71.2"/>
<path class="br" data-t="0.225" data-depth="1" d="M922.5 -40.3Q906.7 -27.9 890.7 -23.5"/>
<path class="br" data-t="0.237" data-depth="1" d="M904 -44Q894.3 -60.8 881.5 -70.5"/>
<path class="br" data-t="0.249" data-depth="1" d="M885.4 -47.3Q870.1 -34.1 854.2 -29.1"/>
<path class="br" data-t="0.261" data-depth="1" d="M866.8 -50.3Q861.6 -65.1 852.9 -74.7"/>
<path class="br" data-t="0.273" data-depth="1" d="M848.3 -53.1Q834.8 -43 821.4 -39.7"/>
<path class="br" data-t="0.285" data-depth="1" d="M830.1 -56Q822.4 -69 812.5 -76.4"/>
<path class="br" data-t="0.297" data-depth="1" d="M812.3 -59.1Q801.7 -52 791.3 -50"/>
<path class="br" data-t="0.309" data-depth="1" d="M795.1 -62.5Q787.7 -75.3 778 -82.6"/>
<path class="br" data-t="0.321" data-depth="1" d="M778.6 -66.3Q768.6 -59.8 758.9 -58"/>
<path class="br" data-t="0.333" data-depth="1" d="M762.9 -70.7Q757.1 -82.9 748.9 -90.3"/>
<path class="br" data-t="0.345" data-depth="1" d="M748.3 -75.9Q738.9 -69.9 729.8 -68.3"/>
<path class="br" data-t="0.357" data-depth="1" d="M734.8 -82Q730.1 -92.8 723.1 -99.5"/>
<path class="br" data-t="0.278" data-depth="0" d="M959.5 -66.7C1007.8 -85.7 1069.2 -88.7 1100.2 -112.9"/>
<path class="br" data-t="0.290" data-depth="1" d="M976 -72.5Q994.4 -60.9 1012.1 -58"/>
<path class="br" data-t="0.302" data-depth="1" d="M993.2 -77.4Q996.9 -93.3 1004.8 -104.3"/>
<path class="br" data-t="0.314" data-depth="1" d="M1010.6 -81.8Q1024.2 -74 1037 -72.5"/>
<path class="br" data-t="0.326" data-depth="1" d="M1027.8 -85.8Q1034.1 -100.3 1043.4 -109.3"/>
<path class="br" data-t="0.338" data-depth="1" d="M1044.7 -89.9Q1055.7 -82.1 1066.7 -79.6"/>
<path class="br" data-t="0.350" data-depth="1" d="M1060.7 -94.4Q1066.5 -106.1 1074.7 -113.2"/>
<path class="br" data-t="0.362" data-depth="1" d="M1075.5 -99.5Q1086 -92.9 1096.1 -91.2"/>
<path class="br" data-t="0.374" data-depth="1" d="M1088.8 -105.6Q1091.4 -116.9 1097.1 -124.7"/>
<path class="br" data-t="0.344" data-depth="0" d="M961.6 -97.5C893.8 -125.4 807.1 -131 763.9 -165.9"/>
<path class="br" data-t="0.356" data-depth="1" d="M946.8 -103.2Q941.9 -124.2 931.5 -138.6"/>
<path class="br" data-t="0.368" data-depth="1" d="M931.6 -108.3Q915.3 -95.3 898.7 -90.7"/>
<path class="br" data-t="0.380" data-depth="1" d="M916 -112.9Q909.9 -129.6 899.9 -140.3"/>
<path class="br" data-t="0.392" data-depth="1" d="M900.3 -117.2Q884.1 -108.7 869.1 -107.4"/>
<path class="br" data-t="0.404" data-depth="1" d="M884.6 -121.2Q878.5 -134.5 869.6 -142.6"/>
<path class="br" data-t="0.416" data-depth="1" d="M868.9 -125.2Q856.4 -118.2 844.6 -116.9"/>
<path class="br" data-t="0.428" data-depth="1" d="M853.5 -129.1Q848.8 -141.4 841.3 -149.3"/>
<path class="br" data-t="0.440" data-depth="1" d="M838.5 -133.1Q826.9 -127.4 816.2 -126.8"/>
<path class="br" data-t="0.452" data-depth="1" d="M824 -137.4Q818.6 -149.4 810.7 -156.7"/>
<path class="br" data-t="0.464" data-depth="1" d="M810.1 -142Q797.3 -135.6 785.5 -134.8"/>
<path class="br" data-t="0.476" data-depth="1" d="M797 -147Q793.9 -157.4 788.1 -164.2"/>
<path class="br" data-t="0.488" data-depth="1" d="M784.9 -152.6Q775.5 -147.2 766.6 -146.2"/>
<path class="br" data-t="0.500" data-depth="1" d="M773.8 -158.9Q770.5 -167.7 765.2 -173.3"/>
<path class="br" data-t="0.425" data-depth="0" d="M963.5 -135.5C1002.8 -156 1054.7 -164.1 1078.8 -187.5"/>
<path class="br" data-t="0.437" data-depth="1" d="M981 -143.6Q996.6 -137.2 1010.5 -137.3"/>
<path class="br" data-t="0.449" data-depth="1" d="M999.3 -150.6Q1003.7 -166.4 1012.1 -176.9"/>
<path class="br" data-t="0.461" data-depth="1" d="M1017.8 -157.2Q1029.9 -149.4 1041.6 -147.4"/>
<path class="br" data-t="0.473" data-depth="1" d="M1035.7 -163.6Q1041.3 -179 1050.6 -188.9"/>
<path class="br" data-t="0.485" data-depth="1" d="M1052.3 -170.5Q1062.4 -165 1071.9 -164.1"/>
<path class="br" data-t="0.497" data-depth="1" d="M1066.9 -178.3Q1069.1 -187.8 1073.8 -194.3"/>
<path class="br" data-t="0.491" data-depth="0" d="M961.6 -166.1C908.2 -196.7 836.7 -210.8 804.5 -244.6"/>
<path class="br" data-t="0.503" data-depth="1" d="M945.1 -174.8Q940.4 -193 931 -205.4"/>
<path class="br" data-t="0.515" data-depth="1" d="M927.9 -182.8Q909.2 -175.6 892.7 -176.1"/>
<path class="br" data-t="0.527" data-depth="1" d="M910.2 -190.2Q906.7 -208.7 898.1 -221.7"/>
<path class="br" data-t="0.539" data-depth="1" d="M892.5 -197.2Q878.8 -191.3 866.4 -191.2"/>
<path class="br" data-t="0.551" data-depth="1" d="M875.1 -204.2Q873 -221.5 865.9 -234"/>
<path class="br" data-t="0.563" data-depth="1" d="M858.3 -211.2Q845.1 -203.3 832.4 -201.6"/>
<path class="br" data-t="0.575" data-depth="1" d="M842.5 -218.5Q840.9 -232.4 835.2 -242.5"/>
<path class="br" data-t="0.587" data-depth="1" d="M828.1 -226.4Q816.9 -221.9 807 -222.1"/>
<path class="br" data-t="0.599" data-depth="1" d="M815.3 -235Q813.1 -244.1 808.6 -250.3"/>
<path class="br" data-t="0.552" data-depth="0" d="M959.6 -194.7C991 -211.3 1032.5 -218 1051.8 -236.8"/>
<path class="br" data-t="0.564" data-depth="1" d="M979.4 -203.7Q994.4 -193.4 1009.2 -190.5"/>
<path class="br" data-t="0.576" data-depth="1" d="M1000.1 -211.3Q1002.3 -229.9 1010 -243.2"/>
<path class="br" data-t="0.588" data-depth="1" d="M1020 -218.7Q1031.3 -211 1042.3 -208.9"/>
<path class="br" data-t="0.600" data-depth="1" d="M1037.8 -226.8Q1041 -237.3 1046.8 -244.3"/>
<path class="br" data-t="0.629" data-depth="0" d="M957.3 -230.8C916.5 -254.5 861.9 -265.6 837.4 -291.6"/>
<path class="br" data-t="0.641" data-depth="1" d="M939.1 -240.3Q937.1 -259.2 929.5 -272.9"/>
<path class="br" data-t="0.653" data-depth="1" d="M920 -248.7Q903 -239.8 887.3 -238.5"/>
<path class="br" data-t="0.665" data-depth="1" d="M900.7 -256.5Q895.9 -272.6 887.1 -283.2"/>
<path class="br" data-t="0.677" data-depth="1" d="M882 -264.2Q868.6 -256.1 855.8 -254.2"/>
<path class="br" data-t="0.689" data-depth="1" d="M864.7 -272.3Q863.1 -285 857.8 -294.2"/>
<path class="br" data-t="0.701" data-depth="1" d="M849.6 -281.3Q838.1 -276.9 827.9 -277.2"/>
<path class="br" data-t="0.706" data-depth="0" d="M959.4 -266.6C982.9 -283.9 1015.8 -294.5 1029.1 -312.2"/>
<path class="br" data-t="0.718" data-depth="1" d="M974.4 -276.3Q994.4 -269.9 1011.6 -271.4"/>
<path class="br" data-t="0.730" data-depth="1" d="M990.3 -285Q990.6 -299.7 995.6 -310.8"/>
<path class="br" data-t="0.742" data-depth="1" d="M1005.6 -293.5Q1017.9 -290.5 1028.2 -292.1"/>
<path class="br" data-t="0.754" data-depth="1" d="M1019 -302.3Q1018.7 -315.4 1022.7 -325.4"/>
<path class="br" data-t="0.775" data-depth="0" d="M960.9 -298.7C933.2 -321.3 893.6 -336.1 878.3 -358.4"/>
<path class="br" data-t="0.787" data-depth="1" d="M943.2 -311.5Q941.9 -330.2 934.9 -344"/>
<path class="br" data-t="0.799" data-depth="1" d="M924.3 -323Q910.6 -320.3 899.3 -322.6"/>
<path class="br" data-t="0.811" data-depth="1" d="M906 -334.2Q907.2 -349 903.5 -360.6"/>
<path class="br" data-t="0.823" data-depth="1" d="M890.1 -345.8Q877.2 -341.9 866.1 -343"/>
<path class="br" data-t="0.855" data-depth="0" d="M961.3 -336.2C975.4 -349.1 996.1 -358.1 1003.6 -370.5"/>
<path class="br" data-t="0.867" data-depth="1" d="M976.8 -348.1Q992.6 -345.3 1005.4 -348.3"/>
<path class="br" data-t="0.879" data-depth="1" d="M992.4 -359Q993 -372.7 997.8 -383"/>
<path class="br" data-t="0.924" data-depth="0" d="M959 -368.5C944.8 -381.3 924 -390.4 916.4 -402.8"/>
<path class="br" data-t="0.936" data-depth="1" d="M943.3 -380.3Q943.1 -397.2 937.5 -409.9"/>
<path class="br" data-t="0.948" data-depth="1" d="M927.7 -391.2Q913.1 -387.4 900.8 -389.2"/>
<path class="br" data-t="1.000" data-depth="0" d="M956 -403.8Q951 -419.8 954 -437.8"/></g>
<g id="line"><path class="seg" id="seg1" data-beat="1" d="M90 114.8C91.8 113.6 97.7 109.1 101 107.4C104.3 105.8 106.8 105.7 110 104.9"/>
<path class="seg" id="seg2" data-beat="2" d="M110 104.9C113.2 104.1 116.3 104.1 120 102.4C123.7 100.8 128.7 96.7 132 95C135.3 93.3 137.7 85.5 140 92.5C142.3 99.5 146 137.1 146 137.1C146 137.1 151 117.7 154 114.8C157 111.9 160.5 109.4 164 119.8"/>
<path class="seg seg--brass" data-beat="2" data-from="1" data-to="2" d="M120 102.4C123.7 100.8 128.7 96.7 132 95C135.3 93.3 137.7 85.5 140 92.5"/>
<path class="seg" id="seg3" data-beat="3" d="M164 119.8C167.5 130.2 170.7 150.4 175 176.9C179.3 203.4 184.8 249.7 190 278.6C195.2 307.6 200 340.3 206 350.6"/>
<path class="seg" id="seg4" data-beat="4" d="M206 350.6C212 360.9 218.7 349.7 226 340.6C233.3 331.5 242.3 313.8 250 296C257.7 278.2 265 253.8 272 233.9C279 214.1 287 184.8 292 176.9C297 169.1 298.3 159.5 302 186.8C305.7 214.1 314 340.6 314 340.6C314 340.6 322.8 329.9 328 323.3C333.2 316.7 338.7 294.3 345 300.9"/>
<path class="seg" id="seg5" data-beat="5" d="M345 300.9C351.3 307.5 359.2 338.2 366 363C372.8 387.8 379.7 427.1 386 449.8C392.3 472.5 398.3 487.4 404 499.4C409.7 511.4 415.7 517.6 420 521.8C424.3 525.9 426.7 535.9 430 524.3"/>
<path class="seg" id="seg6" data-beat="6" d="M430 524.3C433.3 512.7 436.7 475.5 440 452.3C443.3 429.1 446.7 403.9 450 385.3C453.3 366.7 457.3 350.1 460 340.6C462.7 331.1 464.5 326.5 466 328.2C467.5 329.9 469 350.6 469 350.6C469 350.6 470.8 408.9 472 437.4C473.2 465.9 474.3 499.5 476 521.8"/>
<path class="seg seg--brass" data-beat="6" data-from="2" data-to="3" d="M450 385.3C453.3 366.7 457.3 350.1 460 340.6C462.7 331.1 464.5 326.5 466 328.2"/>
<path class="seg" id="seg7" data-beat="7" d="M476 521.8C477.7 544.1 479.8 556.9 482 571.4C484.2 585.9 486.7 604.9 489 608.6C491.3 612.3 493.5 605.7 496 593.7C498.5 581.7 501.7 556.1 504 536.7C506.3 517.3 508.2 495.7 510 477.1C511.8 458.5 513.2 444 515 425C516.8 406 518.3 379.6 521 363"/>
<path class="seg" id="seg8" data-beat="8" d="M521 363C523.7 346.4 528.2 334.8 531 325.7C533.8 316.6 535 293.1 538 308.4C541 323.7 549 417.6 549 417.6C549 417.6 556.5 418 562 410.1C567.5 402.2 574.7 384.9 582 370.4C589.3 355.9 598 337.8 606 323.3C614 308.8 621 297.7 630 283.6C639 269.5 650.8 251.3 660 238.9C669.2 226.5 679 213.2 685 209.1C691 205 692.5 212 696 214.1"/>
<path class="seg seg--brass" data-beat="8" data-from="7" data-to="8" d="M630 283.6C639 269.5 650.8 251.3 660 238.9C669.2 226.5 679 213.2 685 209.1"/>
<path class="seg" id="seg9" data-beat="9" d="M696 214.1C699.5 216.2 702.3 219 706 221.5C709.7 224 713.3 229.8 718 229C722.7 228.2 729.3 220.8 734 216.6C738.7 212.4 740 208.6 746 204.1"/>
<path class="seg" id="seg10" data-beat="10" d="M746 204.1C752 199.6 761 193.8 770 189.3C779 184.8 790 181.5 800 176.9C810 172.3 820 167 830 162C840 157 848.3 152.5 860 147.1C871.7 141.7 886.7 135.9 900 129.7C913.3 123.5 931.7 114.9 940 109.9"/>
<path class="seg seg--brass" data-beat="10" data-from="4" data-to="5" d="M860 147.1C871.7 141.7 886.7 135.9 900 129.7C913.3 123.5 931.7 114.9 940 109.9"/>
<path class="seg" id="seg11" data-beat="11" d="M940 109.9C948.3 104.9 947 104.1 950 99.9C953 95.8 955.8 91.2 958 85C960.2 78.8 961.8 71 963 62.7C964.2 54.4 965.2 45.3 965 35.4C964.8 25.5 963.2 14.7 962 3.1C960.8 -8.5 958.3 -20.7 958 -34.1C957.7 -47.5 959 -62 960 -77.5C961 -93 963.8 -110.5 964 -127.1C964.2 -143.7 962.2 -160.2 961 -176.8C959.8 -193.4 957.2 -209.9 957 -226.4C956.8 -242.9 959.2 -259.5 960 -276C960.8 -292.5 962.2 -310.1 962 -325.6C961.8 -341.1 960 -356.1 959 -369.1C958 -382.1 956.5 -398 956 -403.8"/></g>
<g id="tips"><circle class="tip reveal" cx="875.5" cy="50.2" r="3.2"/>
<circle class="tip reveal" cx="1099.3" cy="-25.6" r="3.2"/>
<circle class="tip reveal" cx="676" cy="29" r="3.2"/>
<circle class="tip reveal" cx="931.5" cy="-138.6" r="3.2"/>
<circle class="tip reveal" cx="1041.6" cy="-147.4" r="3.2"/>
<circle class="tip reveal" cx="1009.2" cy="-190.5" r="3.2"/>
<circle class="tip reveal" cx="995.6" cy="-310.8" r="3.2"/></g>
<g id="nodes"><g class="node node--ink" data-beat="1" tabindex="0" role="button" aria-label="Millie’s · age 12: show the operating system at this scale" aria-describedby="ledger1"><circle class="node__hit" cx="101" cy="107.4" r="18"/><circle class="node__dot" cx="101" cy="107.4" r="4.6"/></g>
<g class="node node--brass" data-beat="2" tabindex="0" role="button" aria-label="Compounding · 12 to 14: show the operating system at this scale" aria-describedby="ledger2"><circle class="node__hit" cx="140" cy="92.5" r="18"/><rect class="node__gem" x="134.8" y="87.3" width="10.4" height="10.4" transform="rotate(45 140 92.5)"/></g>
<g class="node node--ink" data-beat="3" tabindex="0" role="button" aria-label="The grocery store · 15: show the operating system at this scale" aria-describedby="ledger3"><circle class="node__hit" cx="206" cy="350.6" r="18"/><circle class="node__dot" cx="206" cy="350.6" r="4.6"/></g>
<g class="node node--ink" data-beat="4" tabindex="0" role="button" aria-label="Sprinklers · 17 to 21: show the operating system at this scale" aria-describedby="ledger4"><circle class="node__hit" cx="292" cy="176.9" r="18"/><circle class="node__dot" cx="292" cy="176.9" r="4.6"/></g>
<g class="node node--ink" data-beat="5" tabindex="0" role="button" aria-label="Wells Fargo · 22: show the operating system at this scale" aria-describedby="ledger5"><circle class="node__hit" cx="420" cy="521.8" r="18"/><circle class="node__dot" cx="420" cy="521.8" r="4.6"/></g>
<g class="node node--brass" data-beat="6" tabindex="0" role="button" aria-label="Block by Block · 25: show the operating system at this scale" aria-describedby="ledger6"><circle class="node__hit" cx="463" cy="330.7" r="18"/><rect class="node__gem" x="457.8" y="325.5" width="10.4" height="10.4" transform="rotate(45 463 330.7)"/></g>
<g class="node node--brass" data-beat="7" tabindex="0" role="button" aria-label="The inflection · 26: show the operating system at this scale" aria-describedby="ledger7"><circle class="node__hit" cx="515" cy="425.0" r="18"/><rect class="node__gem" x="509.8" y="419.8" width="10.4" height="10.4" transform="rotate(45 515 425.0)"/></g>
<g class="node node--brass" data-beat="8" tabindex="0" role="button" aria-label="The sandwich chapter · 26 to 33: show the operating system at this scale" aria-describedby="ledger8"><circle class="node__hit" cx="685" cy="209.1" r="18"/><rect class="node__gem" x="679.8" y="203.9" width="10.4" height="10.4" transform="rotate(45 685 209.1)"/></g>
<g class="node node--ink" data-beat="9" tabindex="0" role="button" aria-label="Vancouver · 33: show the operating system at this scale" aria-describedby="ledger9"><circle class="node__hit" cx="718" cy="229.0" r="18"/><circle class="node__dot" cx="718" cy="229.0" r="4.6"/></g>
<g class="node node--brass" data-beat="10" tabindex="0" role="button" aria-label="Security · the last decade: show the operating system at this scale" aria-describedby="ledger10"><circle class="node__hit" cx="900" cy="129.7" r="18"/><rect class="node__gem" x="894.8" y="124.49999999999999" width="10.4" height="10.4" transform="rotate(45 900 129.7)"/></g>
<g class="node node--ink" data-beat="11" tabindex="0" role="button" aria-label="Today · 42: show the operating system at this scale" aria-describedby="ledger11"><circle class="node__hit" cx="940" cy="109.9" r="18"/><circle class="node__dot" cx="940" cy="109.9" r="4.6"/></g></g>
<g id="today"><text class="t-age t-age--key reveal" data-beat="11" x="940" y="786" text-anchor="middle">42</text><text class="t-age t-age--today reveal" data-beat="11" x="940" y="802" text-anchor="middle">today</text></g>

</g>
</svg>

<aside class="ledger" id="ledger" role="dialog" aria-label="The operating system at this scale" aria-hidden="true">
<button class="ledger__close" type="button" id="ledgerClose" aria-label="Close">×</button>
<div class="ledger__head"><span class="ledger__title" id="ledgerTitle"></span><span class="ledger__num" id="ledgerNum"></span></div>
<dl id="ledgerRows">
<dt>Signal</dt><dd id="lr1"></dd>
<dt>Product</dt><dd id="lr2"></dd>
<dt>Value</dt><dd id="lr3"></dd>
<dt>Routed to</dt><dd id="lr4" class="is-brass"></dd>
</dl>
</aside>
</div>
</div>

<div class="steps" id="steps">

<article class="step" data-beat="1" id="beat-1">
<div class="step__card">
<p class="eyebrow step__eyebrow"><span class="step__num">I</span><span>Age 12 · Millie’s</span></p>
<h2 class="step__title">Snow, a shopkeeper, and a locker</h2>
<p class="step__body">An aging shopkeeper on the lake paid me in Airheads for shoveling her steps… the most wanted candy in a middle school that had no supply. I carried them to my locker and sold them for cash. The whole thesis, in miniature: see the demand nobody else is watching, match it to a product, and make something that was not there before.</p>
<dl class="ledger-src" id="ledger1" data-title="Millie’s" data-num="I" hidden>
<dt>Signal</dt><dd>A middle school that wanted Airheads and had no supply</dd>
<dt>Product</dt><dd>Shoveled snow, paid in candy</dd>
<dt>Value</dt><dd>A locker storefront with real margins</dd>
<dt>Routed to</dt><dd>The next idea</dd>
</dl>
</div>
</article>

<article class="step step--giving" data-beat="2" id="beat-2">
<div class="step__card">
<p class="eyebrow step__eyebrow"><span class="step__num">II</span><span>12 to 14 · Compounding</span></p>
<h2 class="step__title">Compounding, then <em>the question</em></h2>
<p class="step__body">Airhead money became two hundred Beanie Babies. The Beanie Babies became $7,000 at one garage sale… which became <strong>two mission trips</strong>, to northern Minnesota and to McAllen, Texas with Habitat for Humanity. Then the Beanie Baby market crashed, and I pivoted to WWJD bracelets. At fourteen I asked the question I have never stopped asking: <em>is this about giving, or taking?</em></p>
<dl class="ledger-src" id="ledger2" data-title="Compounding" data-num="II" hidden>
<dt>Signal</dt><dd>A Beanie Baby craze, still rising</dd>
<dt>Product</dt><dd>Two hundred Beanies, one garage sale</dd>
<dt>Value</dt><dd>$7,000 at age fourteen</dd>
<dt>Routed to</dt><dd>Two mission trips… then a pivot to WWJD bracelets when the market fell</dd>
</dl>
</div>
</article>

<article class="step" data-beat="3" id="beat-3">
<div class="step__card">
<p class="eyebrow step__eyebrow"><span class="step__num">III</span><span>15 · Festival Foods</span></p>
<h2 class="step__title">The first step down</h2>
<p class="step__body">My first step from enlightenment toward entrapment. Courtesy clerk, then cashier, then one of the youngest assistant managers on the floor… frozen and dairy. I watched people who had spent decades inside the same four walls, and understood for the first time that work can hold you as easily as it can lift you.</p>
<dl class="ledger-src" id="ledger3" data-title="The grocery store" data-num="III" hidden>
<dt>Signal</dt><dd>A store short on people who cared</dd>
<dt>Product</dt><dd>Showing up, then running frozen and dairy</dd>
<dt>Value</dt><dd>One of the youngest assistant managers on the floor</dd>
<dt>Routed to</dt><dd>A lesson about walls, kept for later</dd>
</dl>
</div>
</article>

<article class="step" data-beat="4" id="beat-4">
<div class="step__card">
<p class="eyebrow step__eyebrow"><span class="step__num">IV</span><span>17 to 21 · Sprinklers</span></p>
<h2 class="step__title">A summer of cash, and the field takes shape</h2>
<p class="step__body">I worked for a mentor’s sprinkler company, then started my own. One summer netted $32,000 in cash, which I deposited, naively… and the IRS came to ask about it. The lesson outlasted the audit: <em>have a plan to capture the opportunity in front of you.</em> That is the moment the field took its full shape.</p>
<dl class="ledger-src" id="ledger4" data-title="Sprinklers" data-num="IV" hidden>
<dt>Signal</dt><dd>Lawns that needed spring start-ups and fall blowouts</dd>
<dt>Product</dt><dd>A mentor’s crews, then my own company</dd>
<dt>Value</dt><dd>$32,000 cash in a single summer</dd>
<dt>Routed to</dt><dd>The IRS… and a plan to capture what is in front of you</dd>
</dl>
</div>
</article>

<article class="step" data-beat="5" id="beat-5">
<div class="step__card">
<p class="eyebrow step__eyebrow"><span class="step__num">V</span><span>22 · Wells Fargo</span></p>
<h2 class="step__title">Hollow numbers</h2>
<p class="step__body">A personal banker, fresh out of college. I learned how many hollow metrics get celebrated once customer service is set aside… an intuition the industry would later prove right, loudly. A quiet seed: the metrics worth chasing are the ones a customer would recognize.</p>
<dl class="ledger-src" id="ledger5" data-title="Wells Fargo" data-num="V" hidden>
<dt>Signal</dt><dd>Customers underserved behind celebrated numbers</dd>
<dt>Product</dt><dd>Personal banking, done the slow way</dd>
<dt>Value</dt><dd>An early instinct for metrics that matter</dd>
<dt>Routed to</dt><dd>Every dashboard I have built since</dd>
</dl>
</div>
</article>

<article class="step step--giving" data-beat="6" id="beat-6">
<div class="step__card">
<p class="eyebrow step__eyebrow"><span class="step__num">VI</span><span>25 · Block by Block</span></p>
<h2 class="step__title">Lifting people up, until the wall</h2>
<p class="step__body">Downtown improvement districts. As training coordinator I found something I had not gone looking for… a deep pull toward <strong>lifting people up</strong>, whatever their age or starting point. Then advancement meant relocating, and I hit the wall. In that same season I met my wife, newly arrived from Florida, learned we were expecting our son… and learned my father was dying.</p>
<dl class="ledger-src" id="ledger6" data-title="Block by Block" data-num="VI" hidden>
<dt>Signal</dt><dd>Downtowns that needed trained, motivated people</dd>
<dt>Product</dt><dd>Training programs that met people where they were</dd>
<dt>Value</dt><dd>People promoted, regardless of age</dd>
<dt>Routed to</dt><dd>The people themselves</dd>
</dl>
</div>
</article>

<article class="step step--giving" data-beat="7" id="beat-7">
<div class="step__card">
<p class="eyebrow step__eyebrow"><span class="step__num">VII</span><span>26 · My father</span></p>
<h2 class="step__title">The origin</h2>
<p class="step__body">My father gave more than twenty years to the Navy and to defense. His last lesson to me was simple: <em>it is only ever too late to begin your entrepreneurial career if you let yourself believe it is.</em> With the capital he left me, I went to chase the dream. He is the origin of this field… every quadrant is measured from him.</p>
<dl class="ledger-src" id="ledger7" data-title="The inflection" data-num="VII" hidden>
<dt>Signal</dt><dd>A father’s last lesson, and the capital to act on it</dd>
<dt>Product</dt><dd>The decision to begin</dd>
<dt>Value</dt><dd>An entrepreneurial career, started exactly on time</dd>
<dt>Routed to</dt><dd>A family that was just beginning</dd>
</dl>
</div>
</article>

<article class="step step--giving" data-beat="8" id="beat-8">
<div class="step__card">
<p class="eyebrow step__eyebrow"><span class="step__num">VIII</span><span>26 to 33 · The sandwich chapter</span></p>
<h2 class="step__title">Eleven doors</h2>
<p class="step__body">Two months after opening a franchised concept, with $300,000 invested, delivery apps rewrote the model underneath me. So I pivoted… ghost kitchens, then a second franchisee, then a two-and-a-half-year partnership… until there were eleven locations, millions in revenue, and <strong>215 people on payroll</strong>. Everyone predicted failure. Seven years later I exited cleanly at roughly break-even, far richer in owner-operator wisdom than in cash.</p>
<dl class="ledger-src" id="ledger8" data-title="The sandwich chapter" data-num="VIII" hidden>
<dt>Signal</dt><dd>A franchise model being disrupted in real time</dd>
<dt>Product</dt><dd>Ghost kitchens, a second franchisee, a partnership</dd>
<dt>Value</dt><dd>Eleven locations and millions in revenue</dd>
<dt>Routed to</dt><dd>215 jobs, a clean exit, and seven years of owner-operator wisdom</dd>
</dl>
</div>
</article>

<article class="step" data-beat="9" id="beat-9">
<div class="step__card">
<p class="eyebrow step__eyebrow"><span class="step__num">IX</span><span>33 · Vancouver</span></p>
<h2 class="step__title">Hub and spoke</h2>
<p class="step__body">A Vancouver startup: B2B corporate catering built on local restaurants, not just franchises. I built the channel partnerships and the hub-and-spoke growth model that let one city become the next. The company was later sold to Sodexo.</p>
<dl class="ledger-src" id="ledger9" data-title="Vancouver" data-num="IX" hidden>
<dt>Signal</dt><dd>Local restaurants locked out of corporate catering</dd>
<dt>Product</dt><dd>Channel partnerships and a hub-and-spoke growth model</dd>
<dt>Value</dt><dd>A company worth acquiring</dd>
<dt>Routed to</dt><dd>Local restaurants, not just franchises</dd>
</dl>
</div>
</article>

<article class="step step--giving" data-beat="10" id="beat-10">
<div class="step__card">
<p class="eyebrow step__eyebrow"><span class="step__num">X</span><span>The last decade · Security</span></p>
<h2 class="step__title">Growth that pays people</h2>
<p class="step__body">Business development manager, then vice president of sales. I influenced more than $120 million in recurring revenue… and every dollar of it created jobs at the <strong>number one security-officer wage rate in the country</strong>. Business development and job creation were never two things to me. I stopped trying to separate them.</p>
<dl class="ledger-src" id="ledger10" data-title="Security" data-num="X" hidden>
<dt>Signal</dt><dd>Enterprise clients underserved by the industry’s incumbents</dd>
<dt>Product</dt><dd>Business development, then a national sales division</dd>
<dt>Value</dt><dd>$120M+ in recurring revenue influenced</dd>
<dt>Routed to</dt><dd>Jobs at the #1 security-officer wage in the country</dd>
</dl>
</div>
</article>

<article class="step step--giving" data-beat="11" id="beat-11">
<div class="step__card">
<p class="eyebrow step__eyebrow"><span class="step__num">XI</span><span>Today · 42 · Growth Signals</span></p>
<h2 class="step__title">The line outgrows the box</h2>
<p class="step__body">Chief of Staff, Growth Signals. The line reaches the present and does not stop at the edge of the box. Thirty years of one operating system, run at every scale: see the signal, match it, create value, <strong>route it back to people</strong>, feel the market move, pivot. So this is the dedication… to stop thinking in boxes, and to build with what I know I can create. Whether or not it is this role.</p>
<dl class="ledger-src" id="ledger11" data-title="Today" data-num="XI" hidden>
<dt>Signal</dt><dd>A bottleneck that moved from generating ideas to validating them</dd>
<dt>Product</dt><dd>A Chief of Staff who makes things operationally real</dd>
<dt>Value</dt><dd>To be validated… by you</dd>
<dt>Routed to</dt><dd>Growth Signals, and the people it will hire</dd>
</dl>
</div>
</article>

<div class="step step--hold" data-beat="12" aria-hidden="true"></div>
</div>
</section>

<!-- ============================== THE PROPOSAL ============================== -->
<section class="proposal" id="proposal" aria-labelledby="proposalTitle">
<div class="rule" aria-hidden="true"><span class="gem"></span></div>
<p class="eyebrow" style="text-align:center;margin-top:2.6rem">The proposal</p>
<h2 class="sr-only" id="proposalTitle">A concept worth validating</h2>
<p class="proposal__copy">Sean… your work argues that the bottleneck has shifted from generating ideas to validating them… and that you earn the right to scale by making something operationally real first. So here’s my proposal, in your language: <em>consider me a concept worth validating.</em> If there’s one thing you’d want a Chief of Staff to make real in your first 30 days… what would it be?</p>

<div class="note" id="note">
<form class="note__form" id="noteForm" action="https://api.web3forms.com/submit" method="POST" novalidate>
<!-- Patrick: paste your Web3Forms access key below (one place; the script reads it from here) -->
<input type="hidden" name="access_key" id="accessKey" value="YOUR_WEB3FORMS_ACCESS_KEY">
<input type="hidden" name="subject" value="Growth Signals · a note from Sean">
<input type="hidden" name="from_name" value="growthsignals.slayes.io">
<!-- honeypot: humans never see this; bots fill it and get filtered by Web3Forms -->
<input type="checkbox" name="botcheck" class="hp" tabindex="-1" autocomplete="off" aria-hidden="true">
<label class="note__label sr-only" for="noteField">Your note to Patrick</label>
<textarea class="note__field" id="noteField" name="message" rows="4" placeholder="The one thing…" required></textarea>
<div class="note__row">
<span class="note__hint">Sent privately, straight to Patrick.</span>
<button class="btn" type="submit" id="noteBtn">Send to Patrick<svg viewBox="0 0 28 8" aria-hidden="true"><path d="M0 4H26M22 .8l4 3.2-4 3.2"/></svg></button>
</div>
<p class="note__status" id="noteStatus" role="status" aria-live="polite"></p>
</form>
<div class="note__done" id="noteDone" tabindex="-1">
<span class="gem gem--solid" aria-hidden="true"></span>
<p>Received… thank you, Sean. This goes straight to Patrick.</p>
</div>
</div>
</section>

<!-- ============================== FOOTER ============================== -->
<footer class="foot">
<div class="rule" aria-hidden="true"><span class="gem"></span></div>
<p>Built as an explorable by <em>Patrick S. Melody</em> · the interaction is the argument.</p>
<p>The frame is borrowed, with thanks, from <em>The Science of Growth</em>.</p>
</footer>

<noscript>
<style>
.ledger-src{display:grid;grid-template-columns:auto 1fr;column-gap:14px;row-gap:6px;margin-top:1.2rem;padding-top:1rem;border-top:1px solid var(--beige)}
.ledger-src dt{font-size:.6rem;letter-spacing:.24em;text-transform:uppercase;color:var(--camel);font-weight:500;padding-top:3px}
.ledger-src dd{margin:0;font-family:var(--serif);font-style:italic;font-size:.95rem}
.step__card{opacity:1;transform:none}
.step{min-height:0;padding-top:3rem;padding-bottom:3rem}
.stage{position:relative!important;height:auto!important;aspect-ratio:10/9}
.stage::after{display:none}
</style>
</noscript>

<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/gsap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/ScrollTrigger.min.js"></script>
<script>
(function () {
'use strict';
if (!window.gsap || !window.ScrollTrigger) { document.documentElement.classList.remove('js'); return; }
gsap.registerPlugin(ScrollTrigger);
ScrollTrigger.config({ ignoreMobileResize: true });

var $ = function (s, r) { return (r || document).querySelector(s); };
var $$ = function (s, r) { return Array.prototype.slice.call((r || document).querySelectorAll(s)); };

var stage = $('#stage'), stageInner = $('#stageInner'), steps = $('#steps'), stepEls = $$('.step'),
fig = $('#fig'), world = $('#world'), ledger = $('#ledger');

/* ---------- the camera that reveals the space the line grows into ---------- */
var CAM = { s: 0.667, x: 87.9, y: 331.3 };
/* scroll budget per beat, in viewport heights (the hold at the end lets the evergreen settle) */
var WEIGHTS = [1, 1, 1, 1.35, 0.9, 1.15, 1.15, 1.45, 0.9, 1.15, 1.7, 0.65];
var MARKERS = false; // flip to true while tuning pacing

var isMobile = false;
var lastW = window.innerWidth, lastH = window.innerHeight;

/* ---------- layout in pixels, never vh ---------- */
function layout() {
var vh = window.innerHeight;
isMobile = window.innerWidth < 900;
var stageH = isMobile ? Math.round(vh * 0.46) : vh;
var R = isMobile ? Math.round(vh * 0.74) : Math.round(vh * 0.5); // the reading line
var padTop = isMobile ? R - stageH : R;
var padBottom = vh - R;
var base = isMobile ? Math.round(vh * 0.72) : vh;
document.documentElement.style.setProperty('--stage-h', stageH + 'px');
steps.style.paddingTop = padTop + 'px';
steps.style.paddingBottom = padBottom + 'px';
stepEls.forEach(function (el, i) { el.style.minHeight = Math.round(WEIGHTS[i] * base) + 'px'; });
return { vh: vh, stageH: stageH, R: R };
}

/* ---------- geometry helpers ---------- */
function lengthOf(el) {
if (el.tagName.toLowerCase() === 'line') {
var dx = el.x2.baseVal.value - el.x1.baseVal.value, dy = el.y2.baseVal.value - el.y1.baseVal.value;
return Math.sqrt(dx * dx + dy * dy);
}
return el.getTotalLength();
}
function cubicsOf(d) { // split a "M..C..C.." string into cumulative prefix paths
var m = d.match(/^M[^C]+/)[0];
var parts = d.slice(m.length).split('C').filter(Boolean);
return { move: m, cubics: parts };
}
var measureNS = 'http://www.w3.org/2000/svg';
function prefixLength(d, count) {
if (count <= 0) return 0;
var c = cubicsOf(d);
var tmp = document.createElementNS(measureNS, 'path');
tmp.setAttribute('d', c.move + 'C' + c.cubics.slice(0, count).join('C'));
fig.appendChild(tmp);
var L = tmp.getTotalLength();
fig.removeChild(tmp);
return L;
}
function lengthTo(path, x, y) { // arc length at which the path passes closest to (x, y)
var L = path.getTotalLength(), best = 0, bestD = Infinity, N = 240;
for (var i = 0; i <= N; i++) {
var p = path.getPointAtLength(L * i / N), dx = p.x - x, dy = p.y - y, dd = dx * dx + dy * dy;
if (dd < bestD) { bestD = dd; best = L * i / N; }
}
return best;
}
/* a dash of length L with an offset of L leaves a round-cap dot at the path start; pad the pattern so nothing shows */
function prepDraw(el, cap) {
var c = cap == null ? 3 : cap, L = lengthOf(el), D = L + 8 * c;
gsap.set(el, { strokeDasharray: D, strokeDashoffset: D + 4 * c, opacity: 1 });
return L;
}

/* ---------- the master timeline: one parent-level scrub, children at absolute positions ---------- */
function buildTimeline(heights) {
var tl = gsap.timeline({ paused: true, defaults: { ease: 'none' } });
var start = [], a = 0;
heights.forEach(function (h) { start.push(a); a += h; });
var total = a;
var at = function (k, f) { return start[k] + heights[k] * f; }; // absolute time for fraction f of beat k (0-based)
var dur = function (k, f) { return heights[k] * f; };
var handled = [];
var reveal = function (el, time, d, to) { handled.push(el); tl.to(el, { opacity: to == null ? 1 : to, duration: d }, time); };
var nodeTime = {}, pad = { v: 0 };

/* initial state: the upper axis, the first label, nothing else */
gsap.set('#axisTop', { opacity: 1 });
gsap.set(world, { x: 0, y: 0, scale: 1, svgOrigin: '0 0' });
gsap.set('#field', { opacity: 1 });
gsap.set('#labels, #notes, #grid, #wall, #spokes', { opacity: 1 });

/* the baseline of time draws with the story; ticks appear as the line passes them */
var baseline = $('#baseline'), BL = prepDraw(baseline);
var t0 = at(0, 0.10), t1 = at(9, 0.78);
tl.to(baseline, { strokeDashoffset: 0, duration: t1 - t0 }, t0);
$$('#ticks > *').forEach(function (el) {
if (el.classList.contains('reveal')) return;
var x = el.tagName.toLowerCase() === 'line' ? el.x1.baseVal.value : el.x.baseVal[0].value;
var when = t0 + (t1 - t0) * (x - 90) / 850;
tl.to(el, { opacity: 1, duration: heights[0] * 0.05 }, when);
});

/* the line itself: one self-drawing path per beat, brass overlays timed to true arc length */
for (var k = 0; k < 11; k++) {
var base = $('#seg' + (k + 1));
var L = prepDraw(base);
var lineStart = at(k, 0.10), lineDur = dur(k, 0.68);
if (k === 10) { lineStart = at(k, 0.06); lineDur = dur(k, 0.34); } // the exit and the trunk, faster
tl.to(base, { strokeDashoffset: 0, duration: lineDur }, lineStart);
$$('.seg--brass[data-beat="' + (k + 1) + '"]').forEach(function (ov) {
var oL = prepDraw(ov);
var before = prefixLength(base.getAttribute('d'), parseInt(ov.dataset.from, 10));
tl.to(ov, { strokeDashoffset: 0, duration: lineDur * (oL / L) }, lineStart + lineDur * (before / L));
});
/* the venture node pops the moment the line reaches it */
var node = $('.node[data-beat="' + (k + 1) + '"]');
if (node) {
var hit = $('.node__hit', node), nx = hit.cx.baseVal.value, ny = hit.cy.baseVal.value;
var when = k === 10 ? at(10, 0.08) : lineStart + lineDur * (lengthTo(base, nx, ny) / L);
nodeTime[k + 1] = when;
tl.fromTo(node, { opacity: 0, scale: 0.3, transformOrigin: '50% 50%' }, { opacity: 1, scale: 1, duration: dur(k, 0.07), ease: 'power2.out' }, when);
}
/* annotations settle in beside the line as it passes */
$$('.t-note[data-beat="' + (k + 1) + '"]').forEach(function (n) {
reveal(n, (nodeTime[k + 1] || at(k, 0.5)) + dur(k, 0.04), dur(k, 0.12));
});
}

/* II · the question is asked; the horizontal axis is only a rumor */
reveal($('#qTaking'), at(1, 0.62), dur(1, 0.18), 0.6);
reveal($('#qGiving'), at(1, 0.68), dur(1, 0.18), 0.6);

/* III · the entrapment region appears below */
reveal($('#regionLow'), at(2, 0.22), dur(2, 0.42));
var ab = $('#axisBottom'); prepDraw(ab); handled.push(ab);
tl.to(ab, { strokeDashoffset: 0, duration: dur(2, 0.4) }, at(2, 0.24));
reveal($('#lblEnt'), at(2, 0.55), dur(2, 0.2));

/* IV · the structural transformation: the field resolves, staggered on one parent timeline */
var mid = $('#midline'); prepDraw(mid);
tl.to(mid, { strokeDashoffset: 0, duration: dur(3, 0.26) }, at(3, 0.40));
tl.to(['#qTaking', '#qGiving'], { opacity: 0, duration: dur(3, 0.12) }, at(3, 0.46));
reveal($('#lblTaking'), at(3, 0.52), dur(3, 0.14));
reveal($('#lblGiving'), at(3, 0.56), dur(3, 0.14));
var ft = $('#frameTop'); prepDraw(ft);
tl.to(ft, { strokeDashoffset: 0, duration: dur(3, 0.24) }, at(3, 0.50));
var dv = $('#divider'); prepDraw(dv);
tl.to(dv, { strokeDashoffset: 0, duration: dur(3, 0.22) }, at(3, 0.56));
var fr = $('#frameRight'); prepDraw(fr);
tl.to(fr, { strokeDashoffset: 0, duration: dur(3, 0.22) }, at(3, 0.64));
gsap.set('#grid > *', { opacity: 0 });
tl.to('#grid > *', { opacity: 1, duration: dur(3, 0.12), stagger: dur(3, 0.025) }, at(3, 0.66));
reveal($('#corners'), at(3, 0.80), dur(3, 0.12));
reveal($('#numerals'), at(3, 0.84), dur(3, 0.12));
reveal($('#lblAge'), at(3, 0.80), dur(3, 0.12));

/* VI · the wall stands just before the line meets it */
var wall = $('.wall'); prepDraw(wall);
tl.to(wall, { strokeDashoffset: 0, duration: dur(5, 0.10) }, at(5, 0.30));

/* VII · the origin blooms as the line crosses it */
var originAt = nodeTime[7] || at(6, 0.6);
var halo = $('.origin__halo'); handled.push($('#origin'));
gsap.set('#origin', { opacity: 1 });
tl.fromTo(halo, { opacity: 0, scale: 0.2, svgOrigin: '515 425' }, { opacity: 1, scale: 1, duration: dur(6, 0.10), ease: 'power2.out' }, originAt);
tl.to(halo, { scale: 1.35, opacity: 0.55, duration: dur(6, 0.25), ease: 'power1.out' }, originAt + dur(6, 0.10));

/* IX · hub and spoke */
var hubAt = (nodeTime[9] || at(8, 0.6)) + dur(8, 0.04);
$$('.spoke').forEach(function (s, i) { prepDraw(s); handled.push(s); tl.to(s, { strokeDashoffset: 0, duration: dur(8, 0.08) }, hubAt + i * dur(8, 0.03)); });
$$('.spoke-dot').forEach(function (d, i) { reveal(d, hubAt + dur(8, 0.08) + i * dur(8, 0.03), dur(8, 0.05)); });

/* XI · the line breaks free: the box dissolves, the camera pulls back, the evergreen draws itself */
$$('#today > *').forEach(function (el) { reveal(el, at(10, 0.04), dur(10, 0.08)); });
tl.to(world, { x: CAM.x, y: CAM.y, scale: CAM.s, svgOrigin: '0 0', duration: dur(10, 0.56), ease: 'power1.inOut' }, at(10, 0.08));
tl.to(['#labels', '#notes', '#grid', '#wall', '#spokes', '#origin', '#corners'], { opacity: 0, duration: dur(10, 0.30) }, at(10, 0.12));
tl.to('#field', { opacity: 0.2, duration: dur(10, 0.40) }, at(10, 0.14));
$$('.br').forEach(function (b) {
var t = parseFloat(b.dataset.t), depth = parseInt(b.dataset.depth, 10);
prepDraw(b, 2);
var s = depth === 0 ? at(10, 0.13 + 0.36 * t) : at(10, 0.18 + 0.36 * Math.min(t, 1));
tl.to(b, { strokeDashoffset: 0, duration: dur(10, depth === 0 ? 0.13 : 0.07) }, s);
});
$$('.tip').forEach(function (tp, i) {
tl.fromTo(tp, { opacity: 0, scale: 0, transformOrigin: '50% 50%' }, { opacity: 1, scale: 1, duration: dur(10, 0.05), ease: 'back.out(2)' }, at(10, 0.58 + i * 0.025));
});

/* anything marked reveal that has no bespoke moment fades in mid-beat */
$$('.reveal[data-beat]').forEach(function (el) {
if (handled.indexOf(el) !== -1) return;
var k = parseInt(el.dataset.beat, 10) - 1;
reveal(el, at(k, 0.5), dur(k, 0.12));
});

tl.to(pad, { v: 1, duration: 0.001 }, total - 0.001); // pad to the full scroll budget; positions are already in px, 1:1
return { tl: tl, start: start, total: total };
}

/* ---------- beats and the ledger ---------- */
var currentBeat = 0, openNode = null, openedByHover = false;
function setBeat(b) {
currentBeat = b;
$$('.node').forEach(function (n) {
var nb = parseInt(n.dataset.beat, 10), live = nb <= b;
n.classList.toggle('is-live', live);
n.setAttribute('tabindex', live ? '0' : '-1');
n.setAttribute('aria-hidden', live ? 'false' : 'true');
});
if (openNode && parseInt(openNode.dataset.beat, 10) > b) closeLedger();
}
function fillLedger(beat) {
var src = $('#ledger' + beat); if (!src) return;
$('#ledgerTitle').textContent = src.dataset.title;
$('#ledgerNum').textContent = src.dataset.num;
var dds = $$('dd', src);
['#lr1', '#lr2', '#lr3', '#lr4'].forEach(function (id, i) { $(id).textContent = dds[i] ? dds[i].textContent : ''; });
}
function placeLedger(node) {
if (isMobile) return;
var sr = stageInner.getBoundingClientRect(), nr = $('.node__hit', node).getBoundingClientRect();
var cx = nr.left + nr.width / 2 - sr.left, cy = nr.top + nr.height / 2 - sr.top;
var w = ledger.offsetWidth, h = ledger.offsetHeight;
var left = cx + 20, top = cy - h * 0.5;
if (left + w > sr.width - 8) left = cx - w - 20;
if (left < 8) left = 8;
top = Math.max(8, Math.min(top, sr.height - h - 8));
ledger.style.left = left + 'px';
ledger.style.top = top + 'px';
}
function openLedger(node, byHover) {
var beat = parseInt(node.dataset.beat, 10);
if (beat > currentBeat || parseFloat(gsap.getProperty(node, 'opacity')) < 0.5) return;
if (openNode && openNode !== node) openNode.classList.remove('is-open');
openNode = node; openedByHover = !!byHover;
fillLedger(beat);
node.classList.add('is-open');
ledger.classList.add('is-open');
ledger.setAttribute('aria-hidden', 'false');
placeLedger(node);
}
function closeLedger() {
if (openNode) openNode.classList.remove('is-open');
openNode = null;
ledger.classList.remove('is-open');
ledger.setAttribute('aria-hidden', 'true');
}
var pointerRecently = false, pointerTimer;
document.addEventListener('pointerdown', function () { pointerRecently = true; clearTimeout(pointerTimer); pointerTimer = setTimeout(function () { pointerRecently = false; }, 400); }, true);
$$('.node').forEach(function (node) {
node.addEventListener('mouseenter', function () { if (!isMobile && !(openNode === node && !openedByHover)) openLedger(node, true); });
node.addEventListener('mouseleave', function () { if (openNode === node && openedByHover) closeLedger(); });
node.addEventListener('click', function (e) {
e.preventDefault();
if (openNode === node && !openedByHover) closeLedger(); else openLedger(node, false);
});
node.addEventListener('focus', function () { if (!pointerRecently) openLedger(node, false); });
node.addEventListener('blur', function () { if (openNode === node) closeLedger(); });
node.addEventListener('keydown', function (e) {
if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); if (openNode === node) closeLedger(); else openLedger(node, false); }
if (e.key === 'Escape') closeLedger();
});
});
$('#ledgerClose').addEventListener('click', closeLedger);
document.addEventListener('keydown', function (e) { if (e.key === 'Escape') closeLedger(); });
document.addEventListener('pointerdown', function (e) { if (openNode && !ledger.contains(e.target) && !e.target.closest('.node')) closeLedger(); });
var lastScrollY = window.scrollY;
window.addEventListener('scroll', function () { if (openNode && Math.abs(window.scrollY - lastScrollY) > 12) { closeLedger(); } lastScrollY = window.scrollY; }, { passive: true });

/* ---------- arm everything, gated by gsap.matchMedia ---------- */
var mm = gsap.matchMedia();
var armedHeights = [];
function arm() {
var L = layout();
mm.add({
desktop: '(min-width: 900px)',
mobile: '(max-width: 899px)',
motion: '(prefers-reduced-motion: no-preference)',
reduce: '(prefers-reduced-motion: reduce)'
}, function (ctx) {
var c = ctx.conditions;
var heights = stepEls.map(function (el) { return el.offsetHeight; });
armedHeights = heights.slice();
var built = buildTimeline(heights), tl = built.tl, start = built.start, total = built.total;
stage.classList.toggle('is-sticky', !(c.desktop && c.motion));

if (c.desktop && c.motion) {
ScrollTrigger.create({
trigger: stage, start: 'top top', endTrigger: steps, end: 'bottom bottom',
pin: true, pinSpacing: true, anticipatePin: 1, markers: MARKERS
});
}
if (c.motion) {
ScrollTrigger.create({
animation: tl, trigger: steps,
start: function () { return 'top ' + (isMobile ? stage.offsetHeight : 0) + 'px'; },
end: 'bottom bottom', scrub: 1, markers: MARKERS
});
}
stepEls.forEach(function (el, i) {
ScrollTrigger.create({
trigger: el,
start: function () { return isMobile ? 'top 90%' : 'top 58%'; },
end: function () { return isMobile ? 'bottom 62%' : 'bottom 42%'; },
onToggle: function (self) {
el.classList.toggle('is-active', self.isActive);
if (self.isActive && i < 11) setBeat(i + 1);
},
onEnter: function () { if (c.reduce && i < 11) tl.progress(Math.min(1, (start[i] + heights[i] * (i === 10 ? 0.9 : 1)) / total)); },
onEnterBack: function () { if (c.reduce && i < 11) tl.progress(Math.min(1, (start[i] + heights[i] * (i === 10 ? 0.9 : 1)) / total)); },
onLeaveBack: function () { if (c.reduce && i === 0) tl.progress(0); }
});
});

/* discrete reveals in the intro */
if (c.motion) {
ScrollTrigger.batch('.fade', {
start: 'top 88%', once: true,
onEnter: function (els) { gsap.to(els, { opacity: 1, y: 0, duration: 1, stagger: 0.09, ease: 'power2.out', overwrite: true }); }
});
} else {
gsap.set('.fade', { opacity: 1, y: 0 });
}
return function () { closeLedger(); };
});
}
arm();
function rearmIfHeightsChanged() {
var now = stepEls.map(function (el) { return el.offsetHeight; });
var changed = now.some(function (h, i) { return h !== armedHeights[i]; });
if (changed) { mm.revert(); arm(); } else { ScrollTrigger.refresh(); }
}
if (document.fonts && document.fonts.ready) document.fonts.ready.then(rearmIfHeightsChanged);
window.addEventListener('load', function () { ScrollTrigger.refresh(); });

var resizeTimer;
window.addEventListener('resize', function () {
clearTimeout(resizeTimer);
resizeTimer = setTimeout(function () {
var w = window.innerWidth, h = window.innerHeight;
var widthChanged = w !== lastW, bigHeightChange = Math.abs(h - lastH) > lastH * 0.25;
if (!widthChanged && !bigHeightChange) return; // mobile address-bar chatter is not a layout event
lastW = w; lastH = h;
mm.revert();
arm();
}, 180);
});

/* ---------- scroll affordance ---------- */
$('#scrollHint').addEventListener('click', function (e) {
e.preventDefault();
var target = $('#intro').getBoundingClientRect().top + window.scrollY - 24;
var reduce = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
window.scrollTo({ top: target, behavior: reduce ? 'auto' : 'smooth' });
});

/* ---------- the note: Web3Forms, no backend ---------- */
var form = $('#noteForm'), field = $('#noteField'), btn = $('#noteBtn'), status = $('#noteStatus'), note = $('#note');
field.addEventListener('input', function () { field.style.height = 'auto'; field.style.height = Math.max(150, field.scrollHeight + 2) + 'px'; });
form.addEventListener('submit', function (e) {
e.preventDefault();
var msg = field.value.trim();
var key = $('#accessKey').value.trim();
if (!msg) { status.textContent = 'Write the one thing first… then send.'; field.focus(); return; }
if (!key || key === 'YOUR_WEB3FORMS_ACCESS_KEY') { status.textContent = 'This note is not connected yet… the Web3Forms access key is still a placeholder.'; return; }
btn.disabled = true; status.textContent = 'Sending…';
fetch('https://api.web3forms.com/submit', {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' },
body: JSON.stringify({
access_key: key,
subject: 'Growth Signals · a note from Sean',
from_name: 'growthsignals.slayes.io',
message: msg,
botcheck: form.botcheck.checked ? 'on' : ''
})
}).then(function (res) { return res.json().then(function (data) { return { ok: res.ok, data: data }; }); })
.then(function (r) {
if (r.ok && r.data && r.data.success) {
status.textContent = '';
note.classList.add('is-sent');
setTimeout(function () { $('#noteDone').focus(); }, 500);
} else { throw new Error((r.data && r.data.message) || 'not sent'); }
})
.catch(function () {
btn.disabled = false;
status.textContent = 'That did not send. Try once more… or write to patrick@slayes.io directly.';
});
});
})();
</script>
</body>
</html>