SECTION
Timeline
A work history: dates on the left, a spine with a node for each role, and the story on the right.
Two entries
Tools for people who make things. One product shipped, two more in the drawer.
Owned the token layer four product teams drew against, and the migration when it changed.
Nobody had to open a file the day it changed. That was the whole design goal, and it is the only part worth writing down.
<div class="rule-stack" style="width:100%">
<div class="rule-row timeline-entry">
<div class="timeline-when">
<span class="timeline-span">2024 β NOW</span>
<span class="timeline-length">2 YRS</span>
</div>
<div class="timeline-body">
<div style="display:flex; flex-direction:column; gap:8px">
<span class="timeline-org">Independent</span>
<span class="timeline-role">DESIGN ENGINEER</span>
</div>
<p class="timeline-text">Tools for people who make things. One product shipped, two more in the drawer.</p>
<div class="chip-row">
<span class="chip">GO</span><span class="chip">TYPESCRIPT</span><span class="chip">OPENGL</span>
</div>
</div>
</div>
<div class="rule-row timeline-entry timeline-entry-past">
<div class="timeline-when">
<span class="timeline-span">2019 β 2024</span>
<span class="timeline-length">5 YRS</span>
</div>
<div class="timeline-body">
<div style="display:flex; flex-direction:column; gap:8px">
<span class="timeline-org">A product company</span>
<span class="timeline-role">STAFF ENGINEER, DESIGN PLATFORM</span>
</div>
<!-- A story of more than one paragraph: the class goes on a WRAPPER and
the paragraphs inside it need no class of their own. This is the
shape rendered Markdown produces. -->
<div class="timeline-text">
<p>Owned the token layer four product teams drew against, and the migration when it changed.</p>
<p>Nobody had to open a file the day it changed. That was the whole design goal, and it is the only part worth writing down.</p>
</div>
<div class="chip-row"><span class="chip">REACT</span><span class="chip">CSS</span></div>
</div>
</div>
</div>The tenure band
Blocks scaled to time spent, set with --tenure-cols. Try dragging it sideways on a narrow screen.
<div class="tenure-scroll" style="width:100%">
<div class="tenure-band" style="--tenure-cols:2fr 2fr 3fr 4fr">
<div class="tenure-block"><span class="tenure-years">2013β15</span><span class="tenure-what">Agency, learning</span></div>
<div class="tenure-block"><span class="tenure-years">2015β17</span><span class="tenure-what">First product job</span></div>
<div class="tenure-block"><span class="tenure-years">2017β20</span><span class="tenure-what">Design platform</span></div>
<div class="tenure-block tenure-block-current"><span class="tenure-years">2020βNOW</span><span class="tenure-what">Independent</span></div>
</div>
</div>Reference
Read from sections/timeline.css when this page was built, so it cannot fall behind the stylesheet.
.timeline-entry.timeline-when.timeline-span.timeline-length.timeline-body.timeline-entry-past.timeline-org.timeline-role.timeline-text.tenure-band.tenure-scroll.tenure-block.tenure-block-current.tenure-years.tenure-what--ds-accent--ds-font-body--ds-font-display--ds-gap-loose--ds-gap-tight--ds-ground--ds-hairline--ds-ink--ds-ink-faint--ds-ink-soft--ds-measure-wide--ds-pad-card--ds-raised--ds-rule--ds-rule-strong--ds-sunk--ds-tenure-h--ds-tenure-min-w--ds-text-caption--ds-text-chip--ds-text-h3--ds-text-label--ds-text-small--ds-text-ui--ds-timeline-body-basis--ds-timeline-gap--ds-timeline-node--ds-track-key--ds-track-snug--ds-track-subtle--ds-weight-displayNotes
It was a third column holding a node and a stretched connector, and that had two faults. The connector had to be told to reach the row's height, which is not known until the body beside it has wrapped; and three columns could not hold at 320px β the body collapsed to 35 pixels and its chips spilled off the page. A border is exactly the row's height by construction, and two columns collapse where three could not.
The entry is flex-wrap rather than a grid, so the body drops under the date at whatever width its own content needs. The node is a square: the only round things in this system are avatars and control dots, and a round node here reads as a bullet.
A finished role takes .timeline-entry-past β on the entry, not the body, because the node it hollows out is a pseudo-element of the body and a modifier cannot reach a sibling's pseudo-element from inside it.
.timeline-text is a paragraph and also a box of paragraphs. Put it on a <p> for a one-line role, or on a wrapper holding several β the second entry above does that β and the paragraphs inside need no class of their own. Both shapes land in the same place, because the wrapper's gap is the same step .timeline-body puts between its own children.
It had to be both. Rendered Markdown arrives as a fragment of <p> nobody can put a class on, so a caller with a two-paragraph story has no choice but to wrap it β and wrapped, this drew a measured zero pixels between paragraphs. The class set no display and no gap, and the preflight has already zeroed every paragraph margin, so the two sat flush and read as one block. Nothing failed; it reached a live page.
The tenure band's whole point is that the blocks are proportional to time. Squeezing them onto a phone destroys the only information it carries, so it scrolls inside .tenure-scroll instead. The scroll is on the wrapper, so the page itself never moves.