1<!DOCTYPE html><!-- {new Intl.NumberFormat().format(barlowViews)} --><html lang="en" class="no-js"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><link rel="icon" ref="/favicon.ico" type="icon/ico"><title>Jeremy Tribby</title><!-- Open Graph / Social Media --><meta property="og:type" content="website"><meta property="og:title" content="Jeremy Tribby"><meta property="og:description" content="Jeremy Tribby is an artist, designer, and technologist based in Oakland, California. He publishes fonts at Countertype, an independent type foundry, and has worked on fonts for Google, NBCUniversal, and the H*lls Ang*ls."><meta property="og:image" content="/og.png"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:title" content="Jeremy Tribby"><meta name="twitter:description" content="Jeremy Tribby is an artist, designer, and technologist based in Oakland, California. He publishes fonts at Countertype, an independent type foundry, and has worked on fonts for Google, NBCUniversal, and the H*lls Ang*ls."><meta name="twitter:image" content="/og.png">
1<script src="https://cdn.usefathom.com/script.js" data-site="TQACYXXW" defer></script>
1<script> 2 // By default, the HTML element has the no-js class (added in the Layout component) 3 // This script runs immediately if JS is enabled, removing the no-js class 4 document.documentElement.classList.remove('no-js'); 5 </script>
5<script> 6 function getPattern() { 7 return new RegExp([ 8 'bot', 'spider', 'crawl', 'APIs-Google', 'AdsBot', 'Googlebot', 9 'mediapartners', 'Google Favicon', 'FeedFetcher', 'Google-Read-Aloud', 10 'DuplexWeb-Google', 'googleweblight', 'bing', 'yandex', 'baidu', 11 'duckduck', 'yahoo', 'ecosia', 'ia_archiver', 'facebook', 12 'instagram', 'pinterest', 'reddit', 'slack', 'twitter', 13 'whatsapp', 'youtube', 'semrush' 14 ].join('|'), 'i'); 15 } 16 17 function isbot(ua) { 18 if (!ua) return false; 19 const pattern = getPattern(); 20 return pattern.test(ua.toLowerCase()); 21 } 22 23 const isCrawler = isbot(navigator.userAgent); 24 if (isCrawler) { 25 document.documentElement.classList.add('crawler'); 26 } 27</script>
27<script> 28 (function() { 29 const savedTheme = localStorage.getItem('theme'); 30 const systemPrefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches; 31 const theme = savedTheme || (systemPrefersDark ? 'dark' : 'light'); 32 document.documentElement.setAttribute('data-theme', theme); 33 })(); 34 </script>
34<script type="module">function d(){console.log("Theme toggle button clicked in Layout.astro");const t=document.documentElement.getAttribute("data-theme")==="dark"?"light":"dark";document.documentElement.setAttribute("data-theme",t),localStorage.setItem("theme",t),console.log("Dispatching theme-changed event from Layout.astro"),window.dispatchEvent(new Event("theme-changed"))}document.addEventListener("DOMContentLoaded",()=>{const e=document.getElementById("theme-toggle");e&&(n(),e.addEventListener("click",d));const t=document.getElementById("version-toggle");t&&(o(),t.addEventListener("click",r))});function n(){const e=document.getElementById("theme-toggle");e&&(document.documentElement.getAttribute("data-theme"),e.textContent="Toggle theme")}function o(){const e=document.getElementById("version-toggle");if(e){const t=localStorage.getItem("preferredVersion")||"3d";e.textContent=`View ${t==="3d"?"text":"3D"} version`}}function r(){const t=(localStorage.getItem("preferredVersion")||"3d")==="3d"?"text":"3d";localStorage.setItem("preferredVersion",t),window.dispatchEvent(new CustomEvent("version-changed",{detail:{version:t}})),o()}window.addEventListener("theme-changed",n);</script>
34<style>:root{--black00: #646870;--black200: #646870;--black300: #646870;--black400: #55585e;--black1000: #131318;--white: #f5f5f5;--red100: #9a0000;--red200: #af0909;--red300: #c50909;--red400: #e10000;--yellow100: #efe753;--yellow200: #f5e556;--blue300: #049fb1;--blue400: #1490a2;--blue100: #ff1bb1;--blue200: #1ec8dc;--magenta100: #ff1bb1;--magenta200: #d71a95;--magenta300: #ce178e;--magenta400: #ba1480;--text-high-contrast: var(--black1000);--border-low-contrast: rgba(19, 19, 24, .33);--bg-primary: var(--white);--text-link: var(--red400);--text-link-active: var(--red300);--bullet-margin: -3rem;--li-line-height: 1.5;--button-glass: rgba(0, 0, 0, .033)}:root[data-theme=dark]{--text-high-contrast: var(--white);--border-low-contrast: rgba(245, 245, 245, .33);--button-glass: rgba(255, 255, 255, .1);--bg-primary: var(--black1000);--text-link: var(--magenta100);--text-link-active: var(--magenta200);--bullet-margin: -10rem;--li-line-height: 1.3;--ul-margin: 3.2rem 0 7.2rem 0}:root[data-theme=light]{--text-high-contrast: var(--black1000);--bg-primary: var(--white);--text-link: var(--red400);--text-link-active: var(--red300);--ul-margin: 1.8rem 0 3.6rem 0}@font-face{font-family:Kinzig;src:url(/fonts/Kinzig-Regular.woff) format("woff");font-weight:400}@font-face{font-family:Leman;src:url(/fonts/Leman-RomanVF.woff2) format("woff2");font-weight:unset}@font-face{font-family:Maniera;src:url(/fonts/Maniera-Light.woff) format("woff");font-weight:unset}html{font-size:62.5%}html,body,p{padding:0;margin:0}body{font-family:Leman,sans-serif;font-size:1.6rem;color:var(--text-high-contrast);font-weight:250;background-color:var(--bg-primary);transition:color .12s ease-in-out,background-color .12s ease-in-out;padding-bottom:80px}main{opacity:1;transition:opacity .12s ease-in-out}a{color:var(--text-link);display:inline;transition:color .12s ease-in-out}*,*:before,*:after{box-sizing:border-box}p:not(:last-of-type){margin-bottom:2rem}a{color:var(--text-link);display:inline;transition:color .12s ease-out}[data-theme=light] a{text-decoration-thickness:clamp(.1rem,.12vw,.8rem);text-underline-offset:clamp(.333rem,.666vw,1.333rem)}[data-theme=dark] a{text-decoration-thickness:clamp(1rem,1.6vw,8rem)}a:hover{color:var(--text-link-active);cursor:pointer}.pageContainer .row{display:flex;flex-direction:row}html[data-theme=dark] .pageContainer .content{font-family:Kinzig;font-size:clamp(5.6rem,7.66vw,12.8rem);line-height:1.1}html[data-theme=light] .pageContainer .content{font-family:Maniera;font-weight:200;font-feature-settings:"wght" 200;font-size:clamp(2.8rem,4.5vw,48rem);line-height:1.333;letter-spacing:0}.pageContainer .content{padding:12% 8% 2%;line-height:150%}.pageContainer .content ul{list-style:none;padding:0;margin:var(--ul-margin);line-height:var(--li-line-height)}.pageContainer .content ul li{margin:0;padding:0;position:relative}@media screen and (min-width:900px){.pageContainer .content{padding:8% 11% 5%;line-height:133%}}.button-container{position:fixed;top:4vw;left:50%;transform:translate(-50%);z-index:10;display:flex;flex-direction:row;gap:8px}@media screen and (min-width:900px){.button-container{top:2.66vw}}@media screen and (min-width:1024px){.button-container{top:3.5vw}}.button{background:var(--button-glass);-webkit-backdrop-filter:blur(15px);backdrop-filter:blur(15px);border:none;color:var(--text-high-contrast);padding:4px;border-radius:20px;cursor:pointer;transition:all .12s ease-in-out;opacity:0;pointer-events:none;width:100px;text-align:center;font-size:1rem;font-family:Leman}.ui-ready .theme-toggle,.ui-ready .camera-button,.ui-ready .version-toggle{opacity:1;pointer-events:auto;transition:opacity .5s ease-out}#reset-camera{top:70px}#theme-toggle{top:120px}#version-toggle{top:170px}.theme-toggle:hover,.camera-button:hover,.version-toggle:hover{background:#fff3} 35</style> 36<link rel="stylesheet" href="/_astro/index.DZq2MbTI.css"></head> <body> <header class="button-container"> <button id="theme-toggle" class="button theme-toggle">Toggle theme</button> <button id="version-toggle" class="button version-toggle">View text Version</button> <!-- <button id="reset-camera" class="button camera-button">Reset camera</button> --> </header> <main>
36 <div id="text-content" class="text-version" data-astro-cid-j7pv25f6> <div class="pageContainer" data-astro-cid-j7pv25f6> <div class="content" data-astro-cid-j7pv25f6> <p data-astro-cid-j7pv25f6> 37Jeremy Tribby is an artist, designer, and technologist based in Oakland, California. He publishes fonts at <a href="https://countertype.com" data-astro-cid-j7pv25f6>Countertype</a>, an independent type foundry, and has worked on fonts for Google, NBCUniversal, and the H*lls Ang*ls. He is an occasional <a href="https://automatic-type-design.anrt-nancy.fr/colloques/automatic-type-design-3" data-astro-cid-j7pv25f6>speaker</a> on typography, and his open source font family, <a href="https://github.com/jpt/barlow" data-astro-cid-j7pv25f6>Barlow</a>, is one of the <a href="https://almanac.httparchive.org/en/2024/fonts#fig-18" data-astro-cid-j7pv25f6>most-used</a> on the web. Jeremy is the author of <a href="https://countertype.com/#three-text" data-astro-cid-j7pv25f6>three-text</a>, the open source 3D font rendering and text layout engine. He currently works on design technology at <a href="https://plaid.com" data-astro-cid-j7pv25f6>Plaid</a>, building bridges between design and engineering. In the past, he worked at the <a href="https://eff.org" data-astro-cid-j7pv25f6>Electronic Frontier Foundation</a>, the civil liberties nonprofit, studied art at UC Berkeley, and type design at <a href="https://letterformarchive.org/type-west-in-person/" data-astro-cid-j7pv25f6>Type West</a>. His paintings and drawings have been shown locally in galleries and museums like 21 Grand and the de Young. You can reach him by <a href="/cdn-cgi/l/email-protection#4e242b3c2b23370e3a3c272c2c37602d2123" data-astro-cid-j7pv25f6>email</a> </p> </div> </div> </div> <div id="3d-content" class="three-d-version" data-astro-cid-j7pv25f6> <div id="text-wall-container" data-astro-cid-vvqg2zf2> <div class="crosshair" data-astro-cid-vvqg2zf2> <div class="circle" data-astro-cid-vvqg2zf2></div> <div class="cross" data-astro-cid-vvqg2zf2></div> </div> </div>
vendor: 109 bytes, line 37
37 <script data-cfasync="false" src="/cdn-cgi/scripts/5c5dd728/cloudflare-static/email-decode.min.js"></script>
37<script type="module" src="/_astro/TextWall3D.astro_astro_type_script_index_0_lang.CE1gAPW9.js"></script>
37 <div class="instructions" data-astro-cid-j7pv25f6> 38WASD or arrow keys to move around. Click to aim and shoot. Escape to release the mouse. <br data-astro-cid-j7pv25f6> Q/E = move up/down, Z = change theme, X = reset camera 39</div> </div> <div id="global-loading" class="global-loading js-only" data-astro-cid-j7pv25f6> <div class="loading-spinner" data-astro-cid-j7pv25f6></div> </div> <button id="mobile-reset-camera" class="button mobile-camera-button" data-astro-cid-j7pv25f6>Reset camera</button> </main> <!-- Cloudflare Pages Analytics -->
vendor: 99 bytes, line 39
39<script defer src='https://static.cloudflareinsights.com/beacon.min.js' data-cf-beacon='{"token": "
396a6a8bc5eadd4062932ccac506b2c1a6
vendor: 13 bytes, line 39
39"}'></script>
39<!-- Cloudflare Pages Analytics -->
39<script type="module" src="https://static.cloudflareinsights.com/beacon.min.js/v31edd6df95cf4e85bb4c19e7a9bdbcba1788362987495" integrity="sha512-iIg7k2xntmwu6/uSb5tpc/hySgZc4eoL31yB29W6tJFo2akwjPWcEqnCEdJvGexCL0KEQwVYv5BlowfhVz26hg==" data-cf-beacon='{"version":"2024.11.0","token":"9a75323d8e834dafb0d138556985bc0a","r":1,"spa":2}' crossorigin="anonymous"></script>
39 40</body></html>
40<script type="module">document.addEventListener("DOMContentLoaded",()=>{const t=document.getElementById("text-content"),n=document.getElementById("3d-content"),o=document.getElementById("global-loading");function s(){try{const e=document.createElement("canvas");return!!(window.WebGLRenderingContext&&(e.getContext("webgl")||e.getContext("experimental-webgl")))}catch{return!1}}const a=window.matchMedia("(prefers-reduced-motion: reduce)").matches,l=localStorage.getItem("preferredVersion");function i(){if(t&&n){t.style.display="block",setTimeout(()=>{t.style.opacity="1"},10),n.style.display="none",n.style.opacity="0";const e=document.getElementById("mobile-reset-camera");e&&e.classList.remove("show-mobile-reset")}}function d(){if(t&&n&&s()){n.style.display="block",setTimeout(()=>{n.style.opacity="1"},10),t.style.display="none",t.style.opacity="0";const e=document.getElementById("mobile-reset-camera");e&&e.classList.add("show-mobile-reset")}}function c(){console.log("UI ready event received, displaying content"),o&&(o.style.opacity="0",setTimeout(()=>{o.style.display="none"},500)),l==="text"||!s()||a?i():d(),document.body.classList.add("ui-ready")}window.addEventListener("version-changed",e=>{console.log("version-changed event received in index.astro"),(e.detail?.version||localStorage.getItem("preferredVersion"))==="text"?i():d()}),document.addEventListener("ui-ready",c);const r=setTimeout(()=>{console.log("Fallback timer triggered - ui-ready event not received"),document.body.classList.contains("ui-ready")||(console.log("Adding ui-ready class via fallback"),document.body.classList.add("ui-ready"),c())},5e3);document.addEventListener("ui-ready",()=>{clearTimeout(r)},{once:!0}),document.documentElement.classList.contains("no-js")&&(o&&(o.style.display="none"),t&&(t.style.display="block",t.style.opacity="1"))});</script>
40
40<script type="module">const e=document.getElementById("mobile-reset-camera");e&&e.addEventListener("click",()=>{window.dispatchEvent(new Event("reset-camera"))});</script>
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.