Mar 25, 2026
Test
efwegwrg
rgwregrweag
ergesrgre
Mar 25, 2026
Test
efwegwrg
rgwregrweag
ergesrgre
rsgwrgwrgrw
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>The Moat Onion</title> <style> @import url('https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400;1,400&family=Syne:wght@400;500;700&display=swap'); *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } html, body { min-height: 100%; background: #F0EBE1; color: #1A1A1A; -webkit-font-smoothing: antialiased; } .app { display: grid; grid-template-columns: 1fr 1fr; min-height: 100vh; } /* ── LEFT ── */ .left { display: flex; align-items: center; justify-content: center; padding: 60px 40px; } .onion-svg { width: 100%; max-width: 500px; height: auto; overflow: visible; display: block; } .ring-group { cursor: pointer; } /* ring visual circle — transitions on this element */ .ring-group .ring-vis { transition: opacity 0.55s cubic-bezier(0.25, 0.46, 0.45, 0.94); } @keyframes breathe { 0%,100% { opacity: 1; } 50% { opacity: 0.88; } } .ring-vis.breathing { animation: breathe 4s ease-in-out infinite; } .ring-vis.breathing:nth-child(1) { animation-delay: 0s; } /* ring label text */ .ring-label { font-family: 'Syne', sans-serif; font-size: 9.5px; font-weight: 500; letter-spacing: 0.18em; text-transform: uppercase; fill: rgba(255,255,255,0.55); pointer-events: none; transition: opacity 0.55s cubic-bezier(0.25, 0.46, 0.45, 0.94); dominant-baseline: middle; text-anchor: middle; } /* ── RIGHT ── */ .right { display: flex; flex-direction: column; justify-content: center; padding: 60px 64px 60px 56px; border-left: 1px solid #D8D0C4; position: relative; } /* Idle */ .p-idle { transition: opacity 0.45s cubic-bezier(0.25, 0.46, 0.45, 0.94), transform 0.45s cubic-bezier(0.25, 0.46, 0.45, 0.94); } .p-idle.gone { opacity: 0; transform: translateY(-6px); pointer-events: none; position: absolute; left: 56px; right: 64px; } .idle-label { font-family: 'Syne', sans-serif; font-size: 10px; font-weight: 500; letter-spacing: 0.28em; text-transform: uppercase; color: #A09080; margin-bottom: 36px; } .layer-list { display: flex; flex-direction: column; } .ll-item { display: flex; align-items: center; gap: 16px; padding: 13px 12px; margin: 0 -12px; cursor: pointer; border-bottom: 1px solid #DDD6CC; border-radius: 6px; transition: opacity 0.45s cubic-bezier(0.25, 0.46, 0.45, 0.94), background 0.45s cubic-bezier(0.25, 0.46, 0.45, 0.94); position: relative; } .ll-item:first-child { border-top: 1px solid #DDD6CC; } /* hover state set via JS for coordination with ring hover */ .ll-item.ll-dimmed { opacity: 0.25; } .ll-item.ll-highlighted { opacity: 1; background: rgba(0,0,0,0.04); } .ll-bar { position: absolute; left: 0; top: 50%; transform: translateY(-50%) scaleX(0); transform-origin: left; width: 3px; height: 60%; border-radius: 2px; transition: transform 0.35s cubic-bezier(0.34, 1.56, 0.64, 1); } .ll-item.ll-highlighted .ll-bar { transform: translateY(-50%) scaleX(1); } .ll-dot { width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; transition: transform 0.35s cubic-bezier(0.34, 1.56, 0.64, 1); } .ll-item.ll-highlighted .ll-dot { transform: scale(1.4); } .ll-name { font-family: 'Syne', sans-serif; font-size: 10px; font-weight: 500; letter-spacing: 0.2em; text-transform: uppercase; color: #8A7E72; flex: 1; transition: color 0.3s ease; } .ll-item.ll-highlighted .ll-name { color: #1A1A1A; } .ll-axes { font-family: 'Syne', sans-serif; font-size: 10px; color: #B8AFA4; letter-spacing: 0.06em; transition: color 0.3s ease; } .ll-item.ll-highlighted .ll-axes { color: #8A7E72; } /* ── CONTENT PANEL ── */ .p-content { opacity: 0; transform: translateY(10px); transition: opacity 0.55s cubic-bezier(0.25, 0.46, 0.45, 0.94), transform 0.55s cubic-bezier(0.25, 0.46, 0.45, 0.94); pointer-events: none; position: absolute; left: 56px; right: 64px; } .p-content.visible { opacity: 1; transform: translateY(0); pointer-events: all; position: relative; left: auto; right: auto; } .c-eyebrow { font-family: 'Syne', sans-serif; font-size: 10px; font-weight: 500; letter-spacing: 0.28em; text-transform: uppercase; color: #A09080; margin-bottom: 14px; display: flex; align-items: center; gap: 10px; } .c-dot { width: 7px; height: 7px; border-radius: 50%; display: inline-block; flex-shrink: 0; } .c-axis { font-family: 'Playfair Display', Georgia, serif; font-size: clamp(30px, 3.8vw, 48px); font-weight: 400; font-style: italic; line-height: 1.05; letter-spacing: -0.02em; color: #1A1A1A; margin-bottom: 26px; } .half-tabs { display: flex; margin-bottom: 24px; gap: 0; } .half-tab { font-family: 'Syne', sans-serif; font-size: 9px; letter-spacing: 0.2em; text-transform: uppercase; padding: 6px 0; margin-right: 24px; cursor: pointer; color: #C0B8B0; border-bottom: 1px solid transparent; transition: color 0.3s ease, border-color 0.3s ease; } .half-tab.active { color: #1A1A1A; border-bottom-color: #8A7E72; } .half-tab:hover:not(.active) { color: #8A7E72; } .c-rule { width: 100%; height: 1px; background: #DDD6CC; margin-bottom: 24px; } .c-body { font-family: 'Playfair Display', Georgia, serif; font-size: 14px; line-height: 1.84; color: #7A7068; max-width: 400px; } .c-reset { margin-top: 30px; font-family: 'Syne', sans-serif; font-size: 9px; letter-spacing: 0.22em; text-transform: uppercase; color: #C0B8B0; cursor: pointer; transition: color 0.25s ease; display: inline-block; } .c-reset:hover { color: #8A7E72; } /* ── MOBILE ── */ @media (max-width: 720px) { body { overflow-y: auto; } .app { grid-template-columns: 1fr; min-height: 100vh; } .left { padding: 48px 32px 32px; border-bottom: 1px solid #DDD6CC; } .onion-svg { max-width: 320px; } .right { border-left: none; padding: 40px 32px 60px; justify-content: flex-start; min-height: 380px; } .p-idle.gone { left: 32px; right: 32px; } .p-content { left: 32px; right: 32px; } .c-axis { font-size: clamp(26px, 8vw, 38px); } .c-body { max-width: 100%; } .ll-axes { display: none; } } @media (max-width: 400px) { .left { padding: 32px 20px 24px; } .right { padding: 32px 20px 48px; } .p-idle.gone, .p-content { left: 20px; right: 20px; } } </style> </head> <body> <div class="app"> <div class="left"> <svg class="onion-svg" id="onion" viewBox="0 0 500 500" xmlns="http://www.w3.org/2000/svg"> <defs> <filter id="glow" x="-60%" y="-60%" width="220%" height="220%"> <feGaussianBlur stdDeviation="9" result="blur"/> <feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge> </filter> </defs> </svg> </div> <div class="right"> <div class="p-idle" id="p-idle"> <div class="idle-label">Competitive Defensibility</div> <div class="layer-list" id="layer-list"></div> </div> <div class="p-content" id="p-content"> <div class="c-eyebrow"> <span class="c-dot" id="c-dot"></span> <span id="c-layer-name"></span> </div> <div class="c-axis" id="c-axis"></div> <div class="half-tabs" id="half-tabs"></div> <div class="c-rule"></div> <div class="c-body" id="c-body"></div> <div class="c-reset" id="c-reset">← back</div> </div> </div> </div> <script> const LAYERS = [ { id: 'macro', name: 'Macro', color: '#6FB8E8', axes: [ { name: 'Regulations', body: 'Regulatory frameworks are not merely constraints—they are structural moats when navigated early. Deep tech companies that engage with regulators before rules crystallize often shape the very standards competitors must later comply with. This temporal advantage compounds: the firm that writes the safety protocol becomes the firm that passes the audit. Regulatory capture, when achieved through genuine expertise rather than lobbying alone, is among the most durable forms of defensibility in capital-intensive sectors.' }, { name: 'Geopolitics', body: 'The geography of where a technology was built, by whom, and for whom increasingly determines where it can be sold and at what margin. Supply chain provenance, export control classifications, and bilateral technology agreements are no longer policy footnotes—they are strategic architecture. Founders who understand the geopolitical topology of their sector can position their company as the trusted domestic option when trade walls rise, rather than being caught outside them.' } ] }, { id: 'market', name: 'Market', color: '#3E8EC4', axes: [ { name: 'Category Ownership', body: 'Category ownership is the difference between being a participant in a market and being the name that defines it. When buyers, journalists, and analysts reach for a shorthand to describe the space, and they reach for yours, the cognitive overhead for a competitor to displace you becomes enormous. This does not happen by accident—it requires a deliberate editorial posture, an opinion about what the category should become, and the consistency to hold that position through cycles when others dilute their message.' }, { name: 'Market Product Fit', body: 'Market product fit is the deeper cousin of product-market fit. It asks not whether customers want what you have built, but whether the market structure itself rewards the kind of company you are becoming. A technically superior product can fail because the procurement cycle, the buyer persona, or the competitive intensity of a market systematically disadvantages its go-to-market model. The question is not only: does the market want this? But: does this market reward the kind of advantage we are building?' } ] }, { id: 'asset', name: 'Asset', color: '#1E6496', axes: [ { name: 'Data Irreversibility', body: 'Proprietary datasets that accumulate irreversibly are among the most defensible assets in technology. When each transaction, measurement, or interaction makes the model more accurate, the prediction more precise, or the outcome more reliable, a feedback loop begins that competitors cannot buy their way into—they must live through it. The key word is irreversible: data that can be synthesized, purchased, or replicated from public sources does not constitute a moat. What matters is the data that only exists because you operated.' }, { name: 'Physical Infrastructure', body: 'Physical infrastructure, when proprietary, creates switching costs that software alone cannot replicate. Sensor networks, manufacturing facilities, calibrated equipment, and specialized logistics all carry the weight of capital already deployed—they cannot be summoned by a well-funded competitor overnight. The defensibility is not the asset itself but the compounding operational knowledge embedded in running it: the yield curves, failure modes, maintenance rhythms, and supplier relationships that only emerge from years of operation.' } ] }, { id: 'operations', name: 'Operations', color: '#10426A', axes: [ { name: 'Manufacturing Yield', body: 'In hardware and deep tech, manufacturing yield is the operational expression of accumulated knowledge. Every percentage point of improvement represents thousands of hours of experimental iteration, supplier negotiation, process refinement, and tacit knowledge that cannot be documented fully into a manual. Competitors must buy their own tuition. For investors, yield curves over time are one of the most honest signals of whether an operations team is learning—and whether that learning is converting into durable cost advantage.' }, { name: 'Feedback Loop Speed', body: 'The speed at which a company converts operational experience into improved performance is a multiplier on every other form of advantage. Teams that instrument their processes tightly, run experiments continuously, and shorten the interval between hypothesis and validated learning compound their capabilities faster than those who rely on periodic reviews. In competitive markets, the absolute level of performance matters less than the rate of improvement—and that rate is determined almost entirely by how tightly feedback loops are constructed.' } ] }, { id: 'trust', name: 'Trust', color: '#071828', axes: [ { name: 'Relationships', body: 'Relationships are the softest asset on the balance sheet and the hardest to transfer. In deep tech, where sales cycles are long, technical diligence is intense, and buyer risk is high, the relationship between a technical founder and a key customer or partner often precedes the product itself. These are not merely warm introductions—they are reputational stakes placed by one party on behalf of another. When the relationship network is dense and reciprocal, it becomes a distributed trust infrastructure that no newcomer can replicate by hiring a VP of Sales.' }, { name: 'Institutional Credibility', body: 'Institutional credibility is the form of trust that survives personnel changes. It is embedded in publications, certifications, standards body memberships, and the quiet esteem of the professional communities that matter most in a sector. For a deep tech company, credibility among domain scientists, procurement officers, or regulatory bodies often determines access to the deals, grants, and partnerships that define the next phase of growth. Unlike brand recognition, which can be bought, institutional credibility must be earned—and once earned, it sets a reputational floor that competitors must also reach before being taken seriously.' } ] } ]; const CX = 250, CY = 250; const RING_W = 36, N = LAYERS.length; const R_OUTER = 220; const svgEl = document.getElementById('onion'); const ringGroups = []; const listItems = []; const ringVisEls = []; function ringR(i) { return R_OUTER - i * RING_W - RING_W / 2; } /* ── CONNECTOR LINE element (hidden until active) ── */ const connLine = document.createElementNS('http://www.w3.org/2000/svg','line'); connLine.setAttribute('stroke-width','0.75'); connLine.setAttribute('stroke-dasharray','3 3'); connLine.setAttribute('opacity','0'); connLine.style.transition = 'opacity 0.4s ease'; svgEl.appendChild(connLine); /* ── BUILD SVG RINGS ── */ LAYERS.forEach((layer, i) => { const r = ringR(i); const g = document.createElementNS('http://www.w3.org/2000/svg','g'); g.setAttribute('class','ring-group'); g.dataset.idx = i; const circ = document.createElementNS('http://www.w3.org/2000/svg','circle'); circ.setAttribute('cx', CX); circ.setAttribute('cy', CY); circ.setAttribute('r', r); circ.setAttribute('fill', i === N-1 ? layer.color : 'none'); circ.setAttribute('stroke', layer.color); circ.setAttribute('stroke-width', RING_W); circ.setAttribute('class','ring-vis breathing'); circ.style.animationDelay = `${i * 0.6}s`; g.appendChild(circ); ringVisEls.push(circ); /* curved label */ const pathId = `arc-${i}`; const arcPath = document.createElementNS('http://www.w3.org/2000/svg','path'); arcPath.setAttribute('id', pathId); arcPath.setAttribute('d', `M${CX - r} ${CY} A${r} ${r} 0 0 1 ${CX + r} ${CY}`); arcPath.setAttribute('fill','none'); arcPath.setAttribute('stroke','none'); g.appendChild(arcPath); const lbl = document.createElementNS('http://www.w3.org/2000/svg','text'); lbl.setAttribute('class','ring-label'); const tp = document.createElementNS('http://www.w3.org/2000/svg','textPath'); tp.setAttributeNS('http://www.w3.org/1999/xlink','href',`#${pathId}`); tp.setAttribute('href', `#${pathId}`); tp.setAttribute('startOffset','50%'); tp.setAttribute('text-anchor','middle'); tp.textContent = layer.name; lbl.appendChild(tp); g.appendChild(lbl); /* ring index numeral at 3 o'clock */ const numeral = document.createElementNS('http://www.w3.org/2000/svg','text'); numeral.setAttribute('x', CX + r + 2); numeral.setAttribute('y', CY); numeral.setAttribute('dominant-baseline','middle'); numeral.setAttribute('text-anchor','start'); numeral.setAttribute('font-family','Syne, sans-serif'); numeral.setAttribute('font-size','8'); numeral.setAttribute('font-weight','500'); numeral.setAttribute('letter-spacing','0.05em'); numeral.setAttribute('fill','rgba(160,144,128,0.5)'); numeral.setAttribute('pointer-events','none'); numeral.textContent = i + 1; g.appendChild(numeral); /* hit zones */ for (let half = 0; half < 2; half++) { const rIn = r - RING_W/2, rOut = r + RING_W/2; const d = half === 0 ? `M${CX+rOut} ${CY} A${rOut} ${rOut} 0 0 0 ${CX-rOut} ${CY} L${CX-rIn} ${CY} A${rIn} ${rIn} 0 0 1 ${CX+rIn} ${CY} Z` : `M${CX-rOut} ${CY} A${rOut} ${rOut} 0 0 0 ${CX+rOut} ${CY} L${CX+rIn} ${CY} A${rIn} ${rIn} 0 0 1 ${CX-rIn} ${CY} Z`; const hit = document.createElementNS('http://www.w3.org/2000/svg','path'); hit.setAttribute('d', d); hit.setAttribute('fill','transparent'); hit.setAttribute('cursor','pointer'); hit.dataset.idx = i; hit.dataset.half = half; hit.addEventListener('click', e => { e.stopPropagation(); handleClick(i, half); }); g.appendChild(hit); } g.addEventListener('mouseenter', () => hoverRing(i)); g.addEventListener('mouseleave', () => unhover()); ringGroups.push(g); svgEl.appendChild(g); }); /* ── BUILD LIST ── */ const listEl = document.getElementById('layer-list'); LAYERS.forEach((layer, i) => { const item = document.createElement('div'); item.className = 'll-item'; item.innerHTML = ` <div class="ll-bar" style="background:${layer.color}"></div> <div class="ll-dot" style="background:${layer.color}"></div> <div class="ll-name">${layer.name}</div> <div class="ll-axes">${layer.axes[0].name} · ${layer.axes[1].name}</div> `; item.addEventListener('click', () => handleClick(i, 0)); item.addEventListener('mouseenter', () => hoverRing(i)); item.addEventListener('mouseleave', () => unhover()); listItems.push(item); listEl.appendChild(item); }); /* ── CONNECTOR LINE UPDATE ── */ function updateConnector(li, half) { const r = ringR(li); const y = half === 0 ? CY - r : CY + r; connLine.setAttribute('x1', CX + r + RING_W/2); connLine.setAttribute('y1', y); connLine.setAttribute('x2', 498); connLine.setAttribute('y2', y); connLine.setAttribute('stroke', LAYERS[li].color); connLine.setAttribute('opacity','0.6'); } function hideConnector() { connLine.setAttribute('opacity','0'); } /* ── BREATHING: stop on hover/active ── */ function stopBreathing() { ringVisEls.forEach(v => v.classList.remove('breathing')); } function startBreathing() { ringVisEls.forEach((v,i) => { v.classList.add('breathing'); v.style.animationDelay = `${i * 0.6}s`; }); } /* ── HOVER ── */ function hoverRing(idx) { if (active) return; stopBreathing(); ringGroups.forEach((g, i) => { const vis = g.querySelector('.ring-vis'); const lbl = g.querySelector('.ring-label'); if (i === idx) { vis.style.opacity = '1'; vis.style.filter = 'url(#glow)'; if (lbl) { lbl.style.opacity = '1'; lbl.style.fill = 'rgba(255,255,255,0.95)'; } } else { vis.style.opacity = '0.1'; vis.style.filter = ''; if (lbl) { lbl.style.opacity = '0.12'; } } }); listItems.forEach((item, i) => { item.classList.toggle('ll-highlighted', i === idx); item.classList.toggle('ll-dimmed', i !== idx); }); } function unhover() { if (active) return; startBreathing(); ringGroups.forEach(g => { const vis = g.querySelector('.ring-vis'); const lbl = g.querySelector('.ring-label'); vis.style.opacity = ''; vis.style.filter = ''; if (lbl) { lbl.style.opacity = ''; lbl.style.fill = ''; } }); listItems.forEach(item => item.classList.remove('ll-highlighted','ll-dimmed')); } /* ── CLICK / PANEL ── */ let active = null; const pIdle = document.getElementById('p-idle'); const pContent = document.getElementById('p-content'); const cDot = document.getElementById('c-dot'); const cLName = document.getElementById('c-layer-name'); const cAxis = document.getElementById('c-axis'); const cBody = document.getElementById('c-body'); const halfTabsEl = document.getElementById('half-tabs'); document.getElementById('c-reset').addEventListener('click', reset); function handleClick(li, half) { if (active && active.li === li && active.half === half) { reset(); return; } active = { li, half }; stopBreathing(); lockSelection(li); updateConnector(li, half); renderPanel(li, half); if (window.innerWidth <= 720) { setTimeout(() => document.querySelector('.right').scrollIntoView({ behavior:'smooth', block:'start' }), 120); } } function lockSelection(idx) { ringGroups.forEach((g, i) => { const vis = g.querySelector('.ring-vis'); const lbl = g.querySelector('.ring-label'); if (i === idx) { vis.style.opacity = '1'; vis.style.filter = 'url(#glow)'; if (lbl) { lbl.style.opacity = '1'; lbl.style.fill = 'rgba(255,255,255,0.95)'; } } else { vis.style.opacity = '0.08'; vis.style.filter = ''; if (lbl) { lbl.style.opacity = '0.1'; } } }); listItems.forEach((item, i) => { item.classList.toggle('ll-highlighted', i === idx); item.classList.toggle('ll-dimmed', i !== idx); }); } function renderPanel(li, half) { const layer = LAYERS[li]; pContent.style.transition = 'opacity 0.2s ease, transform 0.2s ease'; pContent.style.opacity = '0'; pContent.style.transform = 'translateY(6px)'; pIdle.classList.add('gone'); setTimeout(() => { cDot.style.background = layer.color; cLName.textContent = layer.name; cAxis.textContent = layer.axes[half].name; cBody.textContent = layer.axes[half].body; halfTabsEl.innerHTML = ''; layer.axes.forEach((ax, hi) => { const tab = document.createElement('div'); tab.className = 'half-tab' + (hi === half ? ' active' : ''); tab.textContent = ax.name; tab.addEventListener('click', () => { if (active) { active.half = hi; updateConnector(li, hi); renderPanel(li, hi); } }); halfTabsEl.appendChild(tab); }); pContent.style.transition = 'opacity 0.5s cubic-bezier(0.25,0.46,0.45,0.94), transform 0.5s cubic-bezier(0.25,0.46,0.45,0.94)'; pContent.classList.add('visible'); requestAnimationFrame(() => { pContent.style.opacity = ''; pContent.style.transform = ''; }); }, active ? 180 : 0); } function reset() { active = null; hideConnector(); startBreathing(); pContent.classList.remove('visible'); setTimeout(() => { if (!active) pIdle.classList.remove('gone'); }, 300); unhover(); } document.addEventListener('click', e => { if (!e.target.closest('.app')) reset(); }); </script> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>The Moat Onion</title> <style> @import url('https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400;1,400&family=Syne:wght@400;500;700&display=swap'); *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } html, body { min-height: 100%; background: #F0EBE1; color: #1A1A1A; -webkit-font-smoothing: antialiased; } .app { display: grid; grid-template-columns: 1fr 1fr; min-height: 100vh; } /* ── LEFT ── */ .left { display: flex; align-items: center; justify-content: center; padding: 60px 40px; } .onion-svg { width: 100%; max-width: 500px; height: auto; overflow: visible; display: block; } .ring-group { cursor: pointer; } /* ring visual circle — transitions on this element */ .ring-group .ring-vis { transition: opacity 0.55s cubic-bezier(0.25, 0.46, 0.45, 0.94); } @keyframes breathe { 0%,100% { opacity: 1; } 50% { opacity: 0.88; } } .ring-vis.breathing { animation: breathe 4s ease-in-out infinite; } .ring-vis.breathing:nth-child(1) { animation-delay: 0s; } /* ring label text */ .ring-label { font-family: 'Syne', sans-serif; font-size: 9.5px; font-weight: 500; letter-spacing: 0.18em; text-transform: uppercase; fill: rgba(255,255,255,0.55); pointer-events: none; transition: opacity 0.55s cubic-bezier(0.25, 0.46, 0.45, 0.94); dominant-baseline: middle; text-anchor: middle; } /* ── RIGHT ── */ .right { display: flex; flex-direction: column; justify-content: center; padding: 60px 64px 60px 56px; border-left: 1px solid #D8D0C4; position: relative; } /* Idle */ .p-idle { transition: opacity 0.45s cubic-bezier(0.25, 0.46, 0.45, 0.94), transform 0.45s cubic-bezier(0.25, 0.46, 0.45, 0.94); } .p-idle.gone { opacity: 0; transform: translateY(-6px); pointer-events: none; position: absolute; left: 56px; right: 64px; } .idle-label { font-family: 'Syne', sans-serif; font-size: 10px; font-weight: 500; letter-spacing: 0.28em; text-transform: uppercase; color: #A09080; margin-bottom: 36px; } .layer-list { display: flex; flex-direction: column; } .ll-item { display: flex; align-items: center; gap: 16px; padding: 13px 12px; margin: 0 -12px; cursor: pointer; border-bottom: 1px solid #DDD6CC; border-radius: 6px; transition: opacity 0.45s cubic-bezier(0.25, 0.46, 0.45, 0.94), background 0.45s cubic-bezier(0.25, 0.46, 0.45, 0.94); position: relative; } .ll-item:first-child { border-top: 1px solid #DDD6CC; } /* hover state set via JS for coordination with ring hover */ .ll-item.ll-dimmed { opacity: 0.25; } .ll-item.ll-highlighted { opacity: 1; background: rgba(0,0,0,0.04); } .ll-bar { position: absolute; left: 0; top: 50%; transform: translateY(-50%) scaleX(0); transform-origin: left; width: 3px; height: 60%; border-radius: 2px; transition: transform 0.35s cubic-bezier(0.34, 1.56, 0.64, 1); } .ll-item.ll-highlighted .ll-bar { transform: translateY(-50%) scaleX(1); } .ll-dot { width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; transition: transform 0.35s cubic-bezier(0.34, 1.56, 0.64, 1); } .ll-item.ll-highlighted .ll-dot { transform: scale(1.4); } .ll-name { font-family: 'Syne', sans-serif; font-size: 10px; font-weight: 500; letter-spacing: 0.2em; text-transform: uppercase; color: #8A7E72; flex: 1; transition: color 0.3s ease; } .ll-item.ll-highlighted .ll-name { color: #1A1A1A; } .ll-axes { font-family: 'Syne', sans-serif; font-size: 10px; color: #B8AFA4; letter-spacing: 0.06em; transition: color 0.3s ease; } .ll-item.ll-highlighted .ll-axes { color: #8A7E72; } /* ── CONTENT PANEL ── */ .p-content { opacity: 0; transform: translateY(10px); transition: opacity 0.55s cubic-bezier(0.25, 0.46, 0.45, 0.94), transform 0.55s cubic-bezier(0.25, 0.46, 0.45, 0.94); pointer-events: none; position: absolute; left: 56px; right: 64px; } .p-content.visible { opacity: 1; transform: translateY(0); pointer-events: all; position: relative; left: auto; right: auto; } .c-eyebrow { font-family: 'Syne', sans-serif; font-size: 10px; font-weight: 500; letter-spacing: 0.28em; text-transform: uppercase; color: #A09080; margin-bottom: 14px; display: flex; align-items: center; gap: 10px; } .c-dot { width: 7px; height: 7px; border-radius: 50%; display: inline-block; flex-shrink: 0; } .c-axis { font-family: 'Playfair Display', Georgia, serif; font-size: clamp(30px, 3.8vw, 48px); font-weight: 400; font-style: italic; line-height: 1.05; letter-spacing: -0.02em; color: #1A1A1A; margin-bottom: 26px; } .half-tabs { display: flex; margin-bottom: 24px; gap: 0; } .half-tab { font-family: 'Syne', sans-serif; font-size: 9px; letter-spacing: 0.2em; text-transform: uppercase; padding: 6px 0; margin-right: 24px; cursor: pointer; color: #C0B8B0; border-bottom: 1px solid transparent; transition: color 0.3s ease, border-color 0.3s ease; } .half-tab.active { color: #1A1A1A; border-bottom-color: #8A7E72; } .half-tab:hover:not(.active) { color: #8A7E72; } .c-rule { width: 100%; height: 1px; background: #DDD6CC; margin-bottom: 24px; } .c-body { font-family: 'Playfair Display', Georgia, serif; font-size: 14px; line-height: 1.84; color: #7A7068; max-width: 400px; } .c-reset { margin-top: 30px; font-family: 'Syne', sans-serif; font-size: 9px; letter-spacing: 0.22em; text-transform: uppercase; color: #C0B8B0; cursor: pointer; transition: color 0.25s ease; display: inline-block; } .c-reset:hover { color: #8A7E72; } /* ── MOBILE ── */ @media (max-width: 720px) { body { overflow-y: auto; } .app { grid-template-columns: 1fr; min-height: 100vh; } .left { padding: 48px 32px 32px; border-bottom: 1px solid #DDD6CC; } .onion-svg { max-width: 320px; } .right { border-left: none; padding: 40px 32px 60px; justify-content: flex-start; min-height: 380px; } .p-idle.gone { left: 32px; right: 32px; } .p-content { left: 32px; right: 32px; } .c-axis { font-size: clamp(26px, 8vw, 38px); } .c-body { max-width: 100%; } .ll-axes { display: none; } } @media (max-width: 400px) { .left { padding: 32px 20px 24px; } .right { padding: 32px 20px 48px; } .p-idle.gone, .p-content { left: 20px; right: 20px; } } </style> </head> <body> <div class="app"> <div class="left"> <svg class="onion-svg" id="onion" viewBox="0 0 500 500" xmlns="http://www.w3.org/2000/svg"> <defs> <filter id="glow" x="-60%" y="-60%" width="220%" height="220%"> <feGaussianBlur stdDeviation="9" result="blur"/> <feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge> </filter> </defs> </svg> </div> <div class="right"> <div class="p-idle" id="p-idle"> <div class="idle-label">Competitive Defensibility</div> <div class="layer-list" id="layer-list"></div> </div> <div class="p-content" id="p-content"> <div class="c-eyebrow"> <span class="c-dot" id="c-dot"></span> <span id="c-layer-name"></span> </div> <div class="c-axis" id="c-axis"></div> <div class="half-tabs" id="half-tabs"></div> <div class="c-rule"></div> <div class="c-body" id="c-body"></div> <div class="c-reset" id="c-reset">← back</div> </div> </div> </div> <script> const LAYERS = [ { id: 'macro', name: 'Macro', color: '#6FB8E8', axes: [ { name: 'Regulations', body: 'Regulatory frameworks are not merely constraints—they are structural moats when navigated early. Deep tech companies that engage with regulators before rules crystallize often shape the very standards competitors must later comply with. This temporal advantage compounds: the firm that writes the safety protocol becomes the firm that passes the audit. Regulatory capture, when achieved through genuine expertise rather than lobbying alone, is among the most durable forms of defensibility in capital-intensive sectors.' }, { name: 'Geopolitics', body: 'The geography of where a technology was built, by whom, and for whom increasingly determines where it can be sold and at what margin. Supply chain provenance, export control classifications, and bilateral technology agreements are no longer policy footnotes—they are strategic architecture. Founders who understand the geopolitical topology of their sector can position their company as the trusted domestic option when trade walls rise, rather than being caught outside them.' } ] }, { id: 'market', name: 'Market', color: '#3E8EC4', axes: [ { name: 'Category Ownership', body: 'Category ownership is the difference between being a participant in a market and being the name that defines it. When buyers, journalists, and analysts reach for a shorthand to describe the space, and they reach for yours, the cognitive overhead for a competitor to displace you becomes enormous. This does not happen by accident—it requires a deliberate editorial posture, an opinion about what the category should become, and the consistency to hold that position through cycles when others dilute their message.' }, { name: 'Market Product Fit', body: 'Market product fit is the deeper cousin of product-market fit. It asks not whether customers want what you have built, but whether the market structure itself rewards the kind of company you are becoming. A technically superior product can fail because the procurement cycle, the buyer persona, or the competitive intensity of a market systematically disadvantages its go-to-market model. The question is not only: does the market want this? But: does this market reward the kind of advantage we are building?' } ] }, { id: 'asset', name: 'Asset', color: '#1E6496', axes: [ { name: 'Data Irreversibility', body: 'Proprietary datasets that accumulate irreversibly are among the most defensible assets in technology. When each transaction, measurement, or interaction makes the model more accurate, the prediction more precise, or the outcome more reliable, a feedback loop begins that competitors cannot buy their way into—they must live through it. The key word is irreversible: data that can be synthesized, purchased, or replicated from public sources does not constitute a moat. What matters is the data that only exists because you operated.' }, { name: 'Physical Infrastructure', body: 'Physical infrastructure, when proprietary, creates switching costs that software alone cannot replicate. Sensor networks, manufacturing facilities, calibrated equipment, and specialized logistics all carry the weight of capital already deployed—they cannot be summoned by a well-funded competitor overnight. The defensibility is not the asset itself but the compounding operational knowledge embedded in running it: the yield curves, failure modes, maintenance rhythms, and supplier relationships that only emerge from years of operation.' } ] }, { id: 'operations', name: 'Operations', color: '#10426A', axes: [ { name: 'Manufacturing Yield', body: 'In hardware and deep tech, manufacturing yield is the operational expression of accumulated knowledge. Every percentage point of improvement represents thousands of hours of experimental iteration, supplier negotiation, process refinement, and tacit knowledge that cannot be documented fully into a manual. Competitors must buy their own tuition. For investors, yield curves over time are one of the most honest signals of whether an operations team is learning—and whether that learning is converting into durable cost advantage.' }, { name: 'Feedback Loop Speed', body: 'The speed at which a company converts operational experience into improved performance is a multiplier on every other form of advantage. Teams that instrument their processes tightly, run experiments continuously, and shorten the interval between hypothesis and validated learning compound their capabilities faster than those who rely on periodic reviews. In competitive markets, the absolute level of performance matters less than the rate of improvement—and that rate is determined almost entirely by how tightly feedback loops are constructed.' } ] }, { id: 'trust', name: 'Trust', color: '#071828', axes: [ { name: 'Relationships', body: 'Relationships are the softest asset on the balance sheet and the hardest to transfer. In deep tech, where sales cycles are long, technical diligence is intense, and buyer risk is high, the relationship between a technical founder and a key customer or partner often precedes the product itself. These are not merely warm introductions—they are reputational stakes placed by one party on behalf of another. When the relationship network is dense and reciprocal, it becomes a distributed trust infrastructure that no newcomer can replicate by hiring a VP of Sales.' }, { name: 'Institutional Credibility', body: 'Institutional credibility is the form of trust that survives personnel changes. It is embedded in publications, certifications, standards body memberships, and the quiet esteem of the professional communities that matter most in a sector. For a deep tech company, credibility among domain scientists, procurement officers, or regulatory bodies often determines access to the deals, grants, and partnerships that define the next phase of growth. Unlike brand recognition, which can be bought, institutional credibility must be earned—and once earned, it sets a reputational floor that competitors must also reach before being taken seriously.' } ] } ]; const CX = 250, CY = 250; const RING_W = 36, N = LAYERS.length; const R_OUTER = 220; const svgEl = document.getElementById('onion'); const ringGroups = []; const listItems = []; const ringVisEls = []; function ringR(i) { return R_OUTER - i * RING_W - RING_W / 2; } /* ── CONNECTOR LINE element (hidden until active) ── */ const connLine = document.createElementNS('http://www.w3.org/2000/svg','line'); connLine.setAttribute('stroke-width','0.75'); connLine.setAttribute('stroke-dasharray','3 3'); connLine.setAttribute('opacity','0'); connLine.style.transition = 'opacity 0.4s ease'; svgEl.appendChild(connLine); /* ── BUILD SVG RINGS ── */ LAYERS.forEach((layer, i) => { const r = ringR(i); const g = document.createElementNS('http://www.w3.org/2000/svg','g'); g.setAttribute('class','ring-group'); g.dataset.idx = i; const circ = document.createElementNS('http://www.w3.org/2000/svg','circle'); circ.setAttribute('cx', CX); circ.setAttribute('cy', CY); circ.setAttribute('r', r); circ.setAttribute('fill', i === N-1 ? layer.color : 'none'); circ.setAttribute('stroke', layer.color); circ.setAttribute('stroke-width', RING_W); circ.setAttribute('class','ring-vis breathing'); circ.style.animationDelay = `${i * 0.6}s`; g.appendChild(circ); ringVisEls.push(circ); /* curved label */ const pathId = `arc-${i}`; const arcPath = document.createElementNS('http://www.w3.org/2000/svg','path'); arcPath.setAttribute('id', pathId); arcPath.setAttribute('d', `M${CX - r} ${CY} A${r} ${r} 0 0 1 ${CX + r} ${CY}`); arcPath.setAttribute('fill','none'); arcPath.setAttribute('stroke','none'); g.appendChild(arcPath); const lbl = document.createElementNS('http://www.w3.org/2000/svg','text'); lbl.setAttribute('class','ring-label'); const tp = document.createElementNS('http://www.w3.org/2000/svg','textPath'); tp.setAttributeNS('http://www.w3.org/1999/xlink','href',`#${pathId}`); tp.setAttribute('href', `#${pathId}`); tp.setAttribute('startOffset','50%'); tp.setAttribute('text-anchor','middle'); tp.textContent = layer.name; lbl.appendChild(tp); g.appendChild(lbl); /* ring index numeral at 3 o'clock */ const numeral = document.createElementNS('http://www.w3.org/2000/svg','text'); numeral.setAttribute('x', CX + r + 2); numeral.setAttribute('y', CY); numeral.setAttribute('dominant-baseline','middle'); numeral.setAttribute('text-anchor','start'); numeral.setAttribute('font-family','Syne, sans-serif'); numeral.setAttribute('font-size','8'); numeral.setAttribute('font-weight','500'); numeral.setAttribute('letter-spacing','0.05em'); numeral.setAttribute('fill','rgba(160,144,128,0.5)'); numeral.setAttribute('pointer-events','none'); numeral.textContent = i + 1; g.appendChild(numeral); /* hit zones */ for (let half = 0; half < 2; half++) { const rIn = r - RING_W/2, rOut = r + RING_W/2; const d = half === 0 ? `M${CX+rOut} ${CY} A${rOut} ${rOut} 0 0 0 ${CX-rOut} ${CY} L${CX-rIn} ${CY} A${rIn} ${rIn} 0 0 1 ${CX+rIn} ${CY} Z` : `M${CX-rOut} ${CY} A${rOut} ${rOut} 0 0 0 ${CX+rOut} ${CY} L${CX+rIn} ${CY} A${rIn} ${rIn} 0 0 1 ${CX-rIn} ${CY} Z`; const hit = document.createElementNS('http://www.w3.org/2000/svg','path'); hit.setAttribute('d', d); hit.setAttribute('fill','transparent'); hit.setAttribute('cursor','pointer'); hit.dataset.idx = i; hit.dataset.half = half; hit.addEventListener('click', e => { e.stopPropagation(); handleClick(i, half); }); g.appendChild(hit); } g.addEventListener('mouseenter', () => hoverRing(i)); g.addEventListener('mouseleave', () => unhover()); ringGroups.push(g); svgEl.appendChild(g); }); /* ── BUILD LIST ── */ const listEl = document.getElementById('layer-list'); LAYERS.forEach((layer, i) => { const item = document.createElement('div'); item.className = 'll-item'; item.innerHTML = ` <div class="ll-bar" style="background:${layer.color}"></div> <div class="ll-dot" style="background:${layer.color}"></div> <div class="ll-name">${layer.name}</div> <div class="ll-axes">${layer.axes[0].name} · ${layer.axes[1].name}</div> `; item.addEventListener('click', () => handleClick(i, 0)); item.addEventListener('mouseenter', () => hoverRing(i)); item.addEventListener('mouseleave', () => unhover()); listItems.push(item); listEl.appendChild(item); }); /* ── CONNECTOR LINE UPDATE ── */ function updateConnector(li, half) { const r = ringR(li); const y = half === 0 ? CY - r : CY + r; connLine.setAttribute('x1', CX + r + RING_W/2); connLine.setAttribute('y1', y); connLine.setAttribute('x2', 498); connLine.setAttribute('y2', y); connLine.setAttribute('stroke', LAYERS[li].color); connLine.setAttribute('opacity','0.6'); } function hideConnector() { connLine.setAttribute('opacity','0'); } /* ── BREATHING: stop on hover/active ── */ function stopBreathing() { ringVisEls.forEach(v => v.classList.remove('breathing')); } function startBreathing() { ringVisEls.forEach((v,i) => { v.classList.add('breathing'); v.style.animationDelay = `${i * 0.6}s`; }); } /* ── HOVER ── */ function hoverRing(idx) { if (active) return; stopBreathing(); ringGroups.forEach((g, i) => { const vis = g.querySelector('.ring-vis'); const lbl = g.querySelector('.ring-label'); if (i === idx) { vis.style.opacity = '1'; vis.style.filter = 'url(#glow)'; if (lbl) { lbl.style.opacity = '1'; lbl.style.fill = 'rgba(255,255,255,0.95)'; } } else { vis.style.opacity = '0.1'; vis.style.filter = ''; if (lbl) { lbl.style.opacity = '0.12'; } } }); listItems.forEach((item, i) => { item.classList.toggle('ll-highlighted', i === idx); item.classList.toggle('ll-dimmed', i !== idx); }); } function unhover() { if (active) return; startBreathing(); ringGroups.forEach(g => { const vis = g.querySelector('.ring-vis'); const lbl = g.querySelector('.ring-label'); vis.style.opacity = ''; vis.style.filter = ''; if (lbl) { lbl.style.opacity = ''; lbl.style.fill = ''; } }); listItems.forEach(item => item.classList.remove('ll-highlighted','ll-dimmed')); } /* ── CLICK / PANEL ── */ let active = null; const pIdle = document.getElementById('p-idle'); const pContent = document.getElementById('p-content'); const cDot = document.getElementById('c-dot'); const cLName = document.getElementById('c-layer-name'); const cAxis = document.getElementById('c-axis'); const cBody = document.getElementById('c-body'); const halfTabsEl = document.getElementById('half-tabs'); document.getElementById('c-reset').addEventListener('click', reset); function handleClick(li, half) { if (active && active.li === li && active.half === half) { reset(); return; } active = { li, half }; stopBreathing(); lockSelection(li); updateConnector(li, half); renderPanel(li, half); if (window.innerWidth <= 720) { setTimeout(() => document.querySelector('.right').scrollIntoView({ behavior:'smooth', block:'start' }), 120); } } function lockSelection(idx) { ringGroups.forEach((g, i) => { const vis = g.querySelector('.ring-vis'); const lbl = g.querySelector('.ring-label'); if (i === idx) { vis.style.opacity = '1'; vis.style.filter = 'url(#glow)'; if (lbl) { lbl.style.opacity = '1'; lbl.style.fill = 'rgba(255,255,255,0.95)'; } } else { vis.style.opacity = '0.08'; vis.style.filter = ''; if (lbl) { lbl.style.opacity = '0.1'; } } }); listItems.forEach((item, i) => { item.classList.toggle('ll-highlighted', i === idx); item.classList.toggle('ll-dimmed', i !== idx); }); } function renderPanel(li, half) { const layer = LAYERS[li]; pContent.style.transition = 'opacity 0.2s ease, transform 0.2s ease'; pContent.style.opacity = '0'; pContent.style.transform = 'translateY(6px)'; pIdle.classList.add('gone'); setTimeout(() => { cDot.style.background = layer.color; cLName.textContent = layer.name; cAxis.textContent = layer.axes[half].name; cBody.textContent = layer.axes[half].body; halfTabsEl.innerHTML = ''; layer.axes.forEach((ax, hi) => { const tab = document.createElement('div'); tab.className = 'half-tab' + (hi === half ? ' active' : ''); tab.textContent = ax.name; tab.addEventListener('click', () => { if (active) { active.half = hi; updateConnector(li, hi); renderPanel(li, hi); } }); halfTabsEl.appendChild(tab); }); pContent.style.transition = 'opacity 0.5s cubic-bezier(0.25,0.46,0.45,0.94), transform 0.5s cubic-bezier(0.25,0.46,0.45,0.94)'; pContent.classList.add('visible'); requestAnimationFrame(() => { pContent.style.opacity = ''; pContent.style.transform = ''; }); }, active ? 180 : 0); } function reset() { active = null; hideConnector(); startBreathing(); pContent.classList.remove('visible'); setTimeout(() => { if (!active) pIdle.classList.remove('gone'); }, 300); unhover(); } document.addEventListener('click', e => { if (!e.target.closest('.app')) reset(); }); </script> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>The Moat Onion</title> <style> @import url('https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400;1,400&family=Syne:wght@400;500;700&display=swap'); *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } html, body { min-height: 100%; background: #F0EBE1; color: #1A1A1A; -webkit-font-smoothing: antialiased; } .app { display: grid; grid-template-columns: 1fr 1fr; min-height: 100vh; } /* ── LEFT ── */ .left { display: flex; align-items: center; justify-content: center; padding: 60px 40px; } .onion-svg { width: 100%; max-width: 500px; height: auto; overflow: visible; display: block; } .ring-group { cursor: pointer; } /* ring visual circle — transitions on this element */ .ring-group .ring-vis { transition: opacity 0.55s cubic-bezier(0.25, 0.46, 0.45, 0.94); } @keyframes breathe { 0%,100% { opacity: 1; } 50% { opacity: 0.88; } } .ring-vis.breathing { animation: breathe 4s ease-in-out infinite; } .ring-vis.breathing:nth-child(1) { animation-delay: 0s; } /* ring label text */ .ring-label { font-family: 'Syne', sans-serif; font-size: 9.5px; font-weight: 500; letter-spacing: 0.18em; text-transform: uppercase; fill: rgba(255,255,255,0.55); pointer-events: none; transition: opacity 0.55s cubic-bezier(0.25, 0.46, 0.45, 0.94); dominant-baseline: middle; text-anchor: middle; } /* ── RIGHT ── */ .right { display: flex; flex-direction: column; justify-content: center; padding: 60px 64px 60px 56px; border-left: 1px solid #D8D0C4; position: relative; } /* Idle */ .p-idle { transition: opacity 0.45s cubic-bezier(0.25, 0.46, 0.45, 0.94), transform 0.45s cubic-bezier(0.25, 0.46, 0.45, 0.94); } .p-idle.gone { opacity: 0; transform: translateY(-6px); pointer-events: none; position: absolute; left: 56px; right: 64px; } .idle-label { font-family: 'Syne', sans-serif; font-size: 10px; font-weight: 500; letter-spacing: 0.28em; text-transform: uppercase; color: #A09080; margin-bottom: 36px; } .layer-list { display: flex; flex-direction: column; } .ll-item { display: flex; align-items: center; gap: 16px; padding: 13px 12px; margin: 0 -12px; cursor: pointer; border-bottom: 1px solid #DDD6CC; border-radius: 6px; transition: opacity 0.45s cubic-bezier(0.25, 0.46, 0.45, 0.94), background 0.45s cubic-bezier(0.25, 0.46, 0.45, 0.94); position: relative; } .ll-item:first-child { border-top: 1px solid #DDD6CC; } /* hover state set via JS for coordination with ring hover */ .ll-item.ll-dimmed { opacity: 0.25; } .ll-item.ll-highlighted { opacity: 1; background: rgba(0,0,0,0.04); } .ll-bar { position: absolute; left: 0; top: 50%; transform: translateY(-50%) scaleX(0); transform-origin: left; width: 3px; height: 60%; border-radius: 2px; transition: transform 0.35s cubic-bezier(0.34, 1.56, 0.64, 1); } .ll-item.ll-highlighted .ll-bar { transform: translateY(-50%) scaleX(1); } .ll-dot { width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; transition: transform 0.35s cubic-bezier(0.34, 1.56, 0.64, 1); } .ll-item.ll-highlighted .ll-dot { transform: scale(1.4); } .ll-name { font-family: 'Syne', sans-serif; font-size: 10px; font-weight: 500; letter-spacing: 0.2em; text-transform: uppercase; color: #8A7E72; flex: 1; transition: color 0.3s ease; } .ll-item.ll-highlighted .ll-name { color: #1A1A1A; } .ll-axes { font-family: 'Syne', sans-serif; font-size: 10px; color: #B8AFA4; letter-spacing: 0.06em; transition: color 0.3s ease; } .ll-item.ll-highlighted .ll-axes { color: #8A7E72; } /* ── CONTENT PANEL ── */ .p-content { opacity: 0; transform: translateY(10px); transition: opacity 0.55s cubic-bezier(0.25, 0.46, 0.45, 0.94), transform 0.55s cubic-bezier(0.25, 0.46, 0.45, 0.94); pointer-events: none; position: absolute; left: 56px; right: 64px; } .p-content.visible { opacity: 1; transform: translateY(0); pointer-events: all; position: relative; left: auto; right: auto; } .c-eyebrow { font-family: 'Syne', sans-serif; font-size: 10px; font-weight: 500; letter-spacing: 0.28em; text-transform: uppercase; color: #A09080; margin-bottom: 14px; display: flex; align-items: center; gap: 10px; } .c-dot { width: 7px; height: 7px; border-radius: 50%; display: inline-block; flex-shrink: 0; } .c-axis { font-family: 'Playfair Display', Georgia, serif; font-size: clamp(30px, 3.8vw, 48px); font-weight: 400; font-style: italic; line-height: 1.05; letter-spacing: -0.02em; color: #1A1A1A; margin-bottom: 26px; } .half-tabs { display: flex; margin-bottom: 24px; gap: 0; } .half-tab { font-family: 'Syne', sans-serif; font-size: 9px; letter-spacing: 0.2em; text-transform: uppercase; padding: 6px 0; margin-right: 24px; cursor: pointer; color: #C0B8B0; border-bottom: 1px solid transparent; transition: color 0.3s ease, border-color 0.3s ease; } .half-tab.active { color: #1A1A1A; border-bottom-color: #8A7E72; } .half-tab:hover:not(.active) { color: #8A7E72; } .c-rule { width: 100%; height: 1px; background: #DDD6CC; margin-bottom: 24px; } .c-body { font-family: 'Playfair Display', Georgia, serif; font-size: 14px; line-height: 1.84; color: #7A7068; max-width: 400px; } .c-reset { margin-top: 30px; font-family: 'Syne', sans-serif; font-size: 9px; letter-spacing: 0.22em; text-transform: uppercase; color: #C0B8B0; cursor: pointer; transition: color 0.25s ease; display: inline-block; } .c-reset:hover { color: #8A7E72; } /* ── MOBILE ── */ @media (max-width: 720px) { body { overflow-y: auto; } .app { grid-template-columns: 1fr; min-height: 100vh; } .left { padding: 48px 32px 32px; border-bottom: 1px solid #DDD6CC; } .onion-svg { max-width: 320px; } .right { border-left: none; padding: 40px 32px 60px; justify-content: flex-start; min-height: 380px; } .p-idle.gone { left: 32px; right: 32px; } .p-content { left: 32px; right: 32px; } .c-axis { font-size: clamp(26px, 8vw, 38px); } .c-body { max-width: 100%; } .ll-axes { display: none; } } @media (max-width: 400px) { .left { padding: 32px 20px 24px; } .right { padding: 32px 20px 48px; } .p-idle.gone, .p-content { left: 20px; right: 20px; } } </style> </head> <body> <div class="app"> <div class="left"> <svg class="onion-svg" id="onion" viewBox="0 0 500 500" xmlns="http://www.w3.org/2000/svg"> <defs> <filter id="glow" x="-60%" y="-60%" width="220%" height="220%"> <feGaussianBlur stdDeviation="9" result="blur"/> <feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge> </filter> </defs> </svg> </div> <div class="right"> <div class="p-idle" id="p-idle"> <div class="idle-label">Competitive Defensibility</div> <div class="layer-list" id="layer-list"></div> </div> <div class="p-content" id="p-content"> <div class="c-eyebrow"> <span class="c-dot" id="c-dot"></span> <span id="c-layer-name"></span> </div> <div class="c-axis" id="c-axis"></div> <div class="half-tabs" id="half-tabs"></div> <div class="c-rule"></div> <div class="c-body" id="c-body"></div> <div class="c-reset" id="c-reset">← back</div> </div> </div> </div> <script> const LAYERS = [ { id: 'macro', name: 'Macro', color: '#6FB8E8', axes: [ { name: 'Regulations', body: 'Regulatory frameworks are not merely constraints—they are structural moats when navigated early. Deep tech companies that engage with regulators before rules crystallize often shape the very standards competitors must later comply with. This temporal advantage compounds: the firm that writes the safety protocol becomes the firm that passes the audit. Regulatory capture, when achieved through genuine expertise rather than lobbying alone, is among the most durable forms of defensibility in capital-intensive sectors.' }, { name: 'Geopolitics', body: 'The geography of where a technology was built, by whom, and for whom increasingly determines where it can be sold and at what margin. Supply chain provenance, export control classifications, and bilateral technology agreements are no longer policy footnotes—they are strategic architecture. Founders who understand the geopolitical topology of their sector can position their company as the trusted domestic option when trade walls rise, rather than being caught outside them.' } ] }, { id: 'market', name: 'Market', color: '#3E8EC4', axes: [ { name: 'Category Ownership', body: 'Category ownership is the difference between being a participant in a market and being the name that defines it. When buyers, journalists, and analysts reach for a shorthand to describe the space, and they reach for yours, the cognitive overhead for a competitor to displace you becomes enormous. This does not happen by accident—it requires a deliberate editorial posture, an opinion about what the category should become, and the consistency to hold that position through cycles when others dilute their message.' }, { name: 'Market Product Fit', body: 'Market product fit is the deeper cousin of product-market fit. It asks not whether customers want what you have built, but whether the market structure itself rewards the kind of company you are becoming. A technically superior product can fail because the procurement cycle, the buyer persona, or the competitive intensity of a market systematically disadvantages its go-to-market model. The question is not only: does the market want this? But: does this market reward the kind of advantage we are building?' } ] }, { id: 'asset', name: 'Asset', color: '#1E6496', axes: [ { name: 'Data Irreversibility', body: 'Proprietary datasets that accumulate irreversibly are among the most defensible assets in technology. When each transaction, measurement, or interaction makes the model more accurate, the prediction more precise, or the outcome more reliable, a feedback loop begins that competitors cannot buy their way into—they must live through it. The key word is irreversible: data that can be synthesized, purchased, or replicated from public sources does not constitute a moat. What matters is the data that only exists because you operated.' }, { name: 'Physical Infrastructure', body: 'Physical infrastructure, when proprietary, creates switching costs that software alone cannot replicate. Sensor networks, manufacturing facilities, calibrated equipment, and specialized logistics all carry the weight of capital already deployed—they cannot be summoned by a well-funded competitor overnight. The defensibility is not the asset itself but the compounding operational knowledge embedded in running it: the yield curves, failure modes, maintenance rhythms, and supplier relationships that only emerge from years of operation.' } ] }, { id: 'operations', name: 'Operations', color: '#10426A', axes: [ { name: 'Manufacturing Yield', body: 'In hardware and deep tech, manufacturing yield is the operational expression of accumulated knowledge. Every percentage point of improvement represents thousands of hours of experimental iteration, supplier negotiation, process refinement, and tacit knowledge that cannot be documented fully into a manual. Competitors must buy their own tuition. For investors, yield curves over time are one of the most honest signals of whether an operations team is learning—and whether that learning is converting into durable cost advantage.' }, { name: 'Feedback Loop Speed', body: 'The speed at which a company converts operational experience into improved performance is a multiplier on every other form of advantage. Teams that instrument their processes tightly, run experiments continuously, and shorten the interval between hypothesis and validated learning compound their capabilities faster than those who rely on periodic reviews. In competitive markets, the absolute level of performance matters less than the rate of improvement—and that rate is determined almost entirely by how tightly feedback loops are constructed.' } ] }, { id: 'trust', name: 'Trust', color: '#071828', axes: [ { name: 'Relationships', body: 'Relationships are the softest asset on the balance sheet and the hardest to transfer. In deep tech, where sales cycles are long, technical diligence is intense, and buyer risk is high, the relationship between a technical founder and a key customer or partner often precedes the product itself. These are not merely warm introductions—they are reputational stakes placed by one party on behalf of another. When the relationship network is dense and reciprocal, it becomes a distributed trust infrastructure that no newcomer can replicate by hiring a VP of Sales.' }, { name: 'Institutional Credibility', body: 'Institutional credibility is the form of trust that survives personnel changes. It is embedded in publications, certifications, standards body memberships, and the quiet esteem of the professional communities that matter most in a sector. For a deep tech company, credibility among domain scientists, procurement officers, or regulatory bodies often determines access to the deals, grants, and partnerships that define the next phase of growth. Unlike brand recognition, which can be bought, institutional credibility must be earned—and once earned, it sets a reputational floor that competitors must also reach before being taken seriously.' } ] } ]; const CX = 250, CY = 250; const RING_W = 36, N = LAYERS.length; const R_OUTER = 220; const svgEl = document.getElementById('onion'); const ringGroups = []; const listItems = []; const ringVisEls = []; function ringR(i) { return R_OUTER - i * RING_W - RING_W / 2; } /* ── CONNECTOR LINE element (hidden until active) ── */ const connLine = document.createElementNS('http://www.w3.org/2000/svg','line'); connLine.setAttribute('stroke-width','0.75'); connLine.setAttribute('stroke-dasharray','3 3'); connLine.setAttribute('opacity','0'); connLine.style.transition = 'opacity 0.4s ease'; svgEl.appendChild(connLine); /* ── BUILD SVG RINGS ── */ LAYERS.forEach((layer, i) => { const r = ringR(i); const g = document.createElementNS('http://www.w3.org/2000/svg','g'); g.setAttribute('class','ring-group'); g.dataset.idx = i; const circ = document.createElementNS('http://www.w3.org/2000/svg','circle'); circ.setAttribute('cx', CX); circ.setAttribute('cy', CY); circ.setAttribute('r', r); circ.setAttribute('fill', i === N-1 ? layer.color : 'none'); circ.setAttribute('stroke', layer.color); circ.setAttribute('stroke-width', RING_W); circ.setAttribute('class','ring-vis breathing'); circ.style.animationDelay = `${i * 0.6}s`; g.appendChild(circ); ringVisEls.push(circ); /* curved label */ const pathId = `arc-${i}`; const arcPath = document.createElementNS('http://www.w3.org/2000/svg','path'); arcPath.setAttribute('id', pathId); arcPath.setAttribute('d', `M${CX - r} ${CY} A${r} ${r} 0 0 1 ${CX + r} ${CY}`); arcPath.setAttribute('fill','none'); arcPath.setAttribute('stroke','none'); g.appendChild(arcPath); const lbl = document.createElementNS('http://www.w3.org/2000/svg','text'); lbl.setAttribute('class','ring-label'); const tp = document.createElementNS('http://www.w3.org/2000/svg','textPath'); tp.setAttributeNS('http://www.w3.org/1999/xlink','href',`#${pathId}`); tp.setAttribute('href', `#${pathId}`); tp.setAttribute('startOffset','50%'); tp.setAttribute('text-anchor','middle'); tp.textContent = layer.name; lbl.appendChild(tp); g.appendChild(lbl); /* ring index numeral at 3 o'clock */ const numeral = document.createElementNS('http://www.w3.org/2000/svg','text'); numeral.setAttribute('x', CX + r + 2); numeral.setAttribute('y', CY); numeral.setAttribute('dominant-baseline','middle'); numeral.setAttribute('text-anchor','start'); numeral.setAttribute('font-family','Syne, sans-serif'); numeral.setAttribute('font-size','8'); numeral.setAttribute('font-weight','500'); numeral.setAttribute('letter-spacing','0.05em'); numeral.setAttribute('fill','rgba(160,144,128,0.5)'); numeral.setAttribute('pointer-events','none'); numeral.textContent = i + 1; g.appendChild(numeral); /* hit zones */ for (let half = 0; half < 2; half++) { const rIn = r - RING_W/2, rOut = r + RING_W/2; const d = half === 0 ? `M${CX+rOut} ${CY} A${rOut} ${rOut} 0 0 0 ${CX-rOut} ${CY} L${CX-rIn} ${CY} A${rIn} ${rIn} 0 0 1 ${CX+rIn} ${CY} Z` : `M${CX-rOut} ${CY} A${rOut} ${rOut} 0 0 0 ${CX+rOut} ${CY} L${CX+rIn} ${CY} A${rIn} ${rIn} 0 0 1 ${CX-rIn} ${CY} Z`; const hit = document.createElementNS('http://www.w3.org/2000/svg','path'); hit.setAttribute('d', d); hit.setAttribute('fill','transparent'); hit.setAttribute('cursor','pointer'); hit.dataset.idx = i; hit.dataset.half = half; hit.addEventListener('click', e => { e.stopPropagation(); handleClick(i, half); }); g.appendChild(hit); } g.addEventListener('mouseenter', () => hoverRing(i)); g.addEventListener('mouseleave', () => unhover()); ringGroups.push(g); svgEl.appendChild(g); }); /* ── BUILD LIST ── */ const listEl = document.getElementById('layer-list'); LAYERS.forEach((layer, i) => { const item = document.createElement('div'); item.className = 'll-item'; item.innerHTML = ` <div class="ll-bar" style="background:${layer.color}"></div> <div class="ll-dot" style="background:${layer.color}"></div> <div class="ll-name">${layer.name}</div> <div class="ll-axes">${layer.axes[0].name} · ${layer.axes[1].name}</div> `; item.addEventListener('click', () => handleClick(i, 0)); item.addEventListener('mouseenter', () => hoverRing(i)); item.addEventListener('mouseleave', () => unhover()); listItems.push(item); listEl.appendChild(item); }); /* ── CONNECTOR LINE UPDATE ── */ function updateConnector(li, half) { const r = ringR(li); const y = half === 0 ? CY - r : CY + r; connLine.setAttribute('x1', CX + r + RING_W/2); connLine.setAttribute('y1', y); connLine.setAttribute('x2', 498); connLine.setAttribute('y2', y); connLine.setAttribute('stroke', LAYERS[li].color); connLine.setAttribute('opacity','0.6'); } function hideConnector() { connLine.setAttribute('opacity','0'); } /* ── BREATHING: stop on hover/active ── */ function stopBreathing() { ringVisEls.forEach(v => v.classList.remove('breathing')); } function startBreathing() { ringVisEls.forEach((v,i) => { v.classList.add('breathing'); v.style.animationDelay = `${i * 0.6}s`; }); } /* ── HOVER ── */ function hoverRing(idx) { if (active) return; stopBreathing(); ringGroups.forEach((g, i) => { const vis = g.querySelector('.ring-vis'); const lbl = g.querySelector('.ring-label'); if (i === idx) { vis.style.opacity = '1'; vis.style.filter = 'url(#glow)'; if (lbl) { lbl.style.opacity = '1'; lbl.style.fill = 'rgba(255,255,255,0.95)'; } } else { vis.style.opacity = '0.1'; vis.style.filter = ''; if (lbl) { lbl.style.opacity = '0.12'; } } }); listItems.forEach((item, i) => { item.classList.toggle('ll-highlighted', i === idx); item.classList.toggle('ll-dimmed', i !== idx); }); } function unhover() { if (active) return; startBreathing(); ringGroups.forEach(g => { const vis = g.querySelector('.ring-vis'); const lbl = g.querySelector('.ring-label'); vis.style.opacity = ''; vis.style.filter = ''; if (lbl) { lbl.style.opacity = ''; lbl.style.fill = ''; } }); listItems.forEach(item => item.classList.remove('ll-highlighted','ll-dimmed')); } /* ── CLICK / PANEL ── */ let active = null; const pIdle = document.getElementById('p-idle'); const pContent = document.getElementById('p-content'); const cDot = document.getElementById('c-dot'); const cLName = document.getElementById('c-layer-name'); const cAxis = document.getElementById('c-axis'); const cBody = document.getElementById('c-body'); const halfTabsEl = document.getElementById('half-tabs'); document.getElementById('c-reset').addEventListener('click', reset); function handleClick(li, half) { if (active && active.li === li && active.half === half) { reset(); return; } active = { li, half }; stopBreathing(); lockSelection(li); updateConnector(li, half); renderPanel(li, half); if (window.innerWidth <= 720) { setTimeout(() => document.querySelector('.right').scrollIntoView({ behavior:'smooth', block:'start' }), 120); } } function lockSelection(idx) { ringGroups.forEach((g, i) => { const vis = g.querySelector('.ring-vis'); const lbl = g.querySelector('.ring-label'); if (i === idx) { vis.style.opacity = '1'; vis.style.filter = 'url(#glow)'; if (lbl) { lbl.style.opacity = '1'; lbl.style.fill = 'rgba(255,255,255,0.95)'; } } else { vis.style.opacity = '0.08'; vis.style.filter = ''; if (lbl) { lbl.style.opacity = '0.1'; } } }); listItems.forEach((item, i) => { item.classList.toggle('ll-highlighted', i === idx); item.classList.toggle('ll-dimmed', i !== idx); }); } function renderPanel(li, half) { const layer = LAYERS[li]; pContent.style.transition = 'opacity 0.2s ease, transform 0.2s ease'; pContent.style.opacity = '0'; pContent.style.transform = 'translateY(6px)'; pIdle.classList.add('gone'); setTimeout(() => { cDot.style.background = layer.color; cLName.textContent = layer.name; cAxis.textContent = layer.axes[half].name; cBody.textContent = layer.axes[half].body; halfTabsEl.innerHTML = ''; layer.axes.forEach((ax, hi) => { const tab = document.createElement('div'); tab.className = 'half-tab' + (hi === half ? ' active' : ''); tab.textContent = ax.name; tab.addEventListener('click', () => { if (active) { active.half = hi; updateConnector(li, hi); renderPanel(li, hi); } }); halfTabsEl.appendChild(tab); }); pContent.style.transition = 'opacity 0.5s cubic-bezier(0.25,0.46,0.45,0.94), transform 0.5s cubic-bezier(0.25,0.46,0.45,0.94)'; pContent.classList.add('visible'); requestAnimationFrame(() => { pContent.style.opacity = ''; pContent.style.transform = ''; }); }, active ? 180 : 0); } function reset() { active = null; hideConnector(); startBreathing(); pContent.classList.remove('visible'); setTimeout(() => { if (!active) pIdle.classList.remove('gone'); }, 300); unhover(); } document.addEventListener('click', e => { if (!e.target.closest('.app')) reset(); }); </script> </body> </html>
