improved a lot of things
This commit is contained in:
@@ -0,0 +1,740 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Intent Diff — Originmain</title>
|
||||
<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=Inter:wght@300;400;500;600;700;800;900&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
:root{--bg:#FFFFFF;--bg-subtle:#FAFAFA;--bg-muted:#F4F4F5;--bg-strong:#EBEBEB;--bg-inv:#0A0A0A;--bg-inv-2:#141414;--bg-inv-3:#1C1C1C;--fg:#0A0A0A;--fg-2:#52525B;--fg-3:#A1A1AA;--fg-4:#D4D4D8;--fg-inv:rgba(255,255,255,0.92);--fg-inv-2:rgba(255,255,255,0.52);--fg-inv-3:rgba(255,255,255,0.28);--blue:#0066FF;--blue-dark:#0050CC;--blue-light:#3385FF;--blue-soft:rgba(0,102,255,0.07);--blue-mid:rgba(0,102,255,0.15);--purple:#7C3AED;--purple-dark:#6D28D9;--purple-soft:rgba(124,58,237,0.07);--purple-mid:rgba(124,58,237,0.15);--teal:#0891B2;--border:rgba(0,0,0,0.07);--border-2:rgba(0,0,0,0.12);--border-inv:rgba(255,255,255,0.08);--border-inv-2:rgba(255,255,255,0.14);--r-1:4px;--r-2:8px;--r-3:12px;--r-4:16px;--r-5:20px;--r-6:24px;--r-full:9999px;--sh-xs:0 1px 2px rgba(0,0,0,0.05);--sh-sm:0 1px 3px rgba(0,0,0,0.07),0 1px 2px rgba(0,0,0,0.05);--sh-md:0 4px 8px rgba(0,0,0,0.06),0 2px 4px rgba(0,0,0,0.04);--sh-lg:0 10px 24px rgba(0,0,0,0.08),0 4px 8px rgba(0,0,0,0.05);--sh-xl:0 20px 40px rgba(0,0,0,0.09),0 8px 16px rgba(0,0,0,0.05);--sh-2xl:0 32px 64px rgba(0,0,0,0.11),0 16px 32px rgba(0,0,0,0.06);--font:'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',system-ui,sans-serif;--mono:'JetBrains Mono','SF Mono',ui-monospace,'Cascadia Code',monospace;}
|
||||
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0;}
|
||||
html{font-size:16px;scroll-behavior:smooth;-webkit-font-smoothing:antialiased;}
|
||||
body{font-family:var(--font);background:var(--bg);color:var(--fg);line-height:1.6;overflow-x:hidden;}
|
||||
img,svg{display:block;max-width:100%;}
|
||||
a{color:inherit;text-decoration:none;}
|
||||
button{font-family:inherit;cursor:pointer;border:none;background:none;}
|
||||
.wrap{max-width:1120px;margin:0 auto;padding:0 40px;}
|
||||
.section{padding:112px 0;}
|
||||
.section-muted{background:var(--bg-subtle);}
|
||||
.section-dark{background:var(--bg-inv);}
|
||||
.d1{font-size:clamp(2.5rem,6vw,4.5rem);font-weight:900;line-height:1.02;letter-spacing:-0.045em;color:var(--fg);}
|
||||
.d2{font-size:clamp(1.875rem,3.5vw,2.75rem);font-weight:800;line-height:1.1;letter-spacing:-0.038em;color:var(--fg);}
|
||||
.d3{font-size:clamp(1.25rem,2.5vw,1.625rem);font-weight:700;line-height:1.25;letter-spacing:-0.028em;color:var(--fg);}
|
||||
.subtitle{font-size:clamp(1rem,1.8vw,1.125rem);font-weight:400;line-height:1.75;color:var(--fg-2);}
|
||||
.label{font-family:var(--mono);font-size:0.6875rem;font-weight:500;letter-spacing:0.1em;text-transform:uppercase;color:var(--fg-3);}
|
||||
.label-purple{color:var(--purple);}
|
||||
.btn{display:inline-flex;align-items:center;gap:8px;font-family:var(--font);font-size:0.9375rem;font-weight:600;padding:11px 22px;border-radius:var(--r-2);transition:transform 0.12s cubic-bezier(.16,1,.3,1),opacity 0.12s,box-shadow 0.12s;white-space:nowrap;letter-spacing:-0.01em;position:relative;overflow:hidden;}
|
||||
.btn::after{content:'';position:absolute;inset:0;background:rgba(255,255,255,0);transition:background 0.12s;}
|
||||
.btn:hover::after{background:rgba(255,255,255,0.06);}
|
||||
.btn:active{transform:scale(0.98)!important;}
|
||||
.btn-primary{background:var(--fg);color:var(--bg);box-shadow:var(--sh-sm);}
|
||||
.btn-primary:hover{transform:translateY(-1px);box-shadow:var(--sh-md);}
|
||||
.btn-secondary{background:transparent;color:var(--fg);border:1px solid var(--border-2);}
|
||||
.btn-secondary:hover{background:var(--bg-muted);transform:translateY(-1px);}
|
||||
.btn-purple{background:var(--purple);color:#fff;box-shadow:0 4px 12px rgba(124,58,237,0.3);}
|
||||
.btn-purple:hover{background:var(--purple-dark);transform:translateY(-1px);}
|
||||
.btn-lg{font-size:1rem;padding:13px 28px;}
|
||||
.btn-white{background:#fff;color:#0A0A0A;box-shadow:0 4px 12px rgba(255,255,255,0.15);}
|
||||
.btn-white:hover{background:#F5F5F5;transform:translateY(-1px);}
|
||||
.btn-outline-white{background:transparent;color:rgba(255,255,255,0.72);border:1px solid rgba(255,255,255,0.18);}
|
||||
.btn-outline-white:hover{background:rgba(255,255,255,0.06);color:rgba(255,255,255,0.9);transform:translateY(-1px);}
|
||||
.divider{height:1px;background:var(--border);}
|
||||
.section-head{text-align:center;max-width:640px;margin:0 auto 72px;}
|
||||
.section-head .label{display:block;margin-bottom:16px;}
|
||||
.section-head .d2{margin-bottom:18px;}
|
||||
|
||||
/* NAV */
|
||||
#nav{position:fixed;top:0;left:0;right:0;z-index:200;height:60px;display:flex;align-items:center;padding:0 40px;transition:background 0.2s,border-color 0.2s,box-shadow 0.2s;}
|
||||
#nav.scrolled{background:rgba(255,255,255,0.85);backdrop-filter:blur(20px) saturate(1.6);-webkit-backdrop-filter:blur(20px) saturate(1.6);border-bottom:1px solid var(--border);box-shadow:var(--sh-xs);}
|
||||
.nav-inner{max-width:1120px;margin:0 auto;width:100%;display:grid;grid-template-columns:1fr auto 1fr;align-items:center;}
|
||||
.nav-logo{justify-self:start;font-size:1rem;font-weight:800;letter-spacing:-0.04em;color:var(--fg);display:flex;align-items:center;gap:2px;}
|
||||
.nav-logo span{color:var(--blue);}
|
||||
.nav-links{justify-self:center;display:flex;align-items:center;gap:0;list-style:none;}
|
||||
.nav-links a{font-size:0.9375rem;font-weight:500;color:var(--fg-2);padding:6px 14px;border-radius:var(--r-1);transition:color 0.12s,background 0.12s;letter-spacing:-0.01em;}
|
||||
.nav-links a:hover{color:var(--fg);}
|
||||
.nav-actions{justify-self:end;display:flex;align-items:center;gap:8px;}
|
||||
|
||||
/* Dropdown */
|
||||
.nav-dropdown{position:relative;}
|
||||
.nav-dropdown>a{display:flex;align-items:center;gap:4px;}
|
||||
.nav-dd-caret{transition:transform 0.15s;}
|
||||
/* caret rotation handled via JS .open class */
|
||||
.nav-dropdown-menu{position:absolute;top:calc(100% + 10px);left:50%;transform:translateX(-50%) translateY(-4px);background:rgba(255,255,255,0.98);backdrop-filter:blur(20px);border:1px solid var(--border);border-radius:var(--r-3);box-shadow:var(--sh-xl);padding:8px;min-width:240px;opacity:0;visibility:hidden;transition:opacity 0.15s,transform 0.15s,visibility 0.15s;pointer-events:none;}
|
||||
.nav-dropdown-menu.open{opacity:1;visibility:visible;transform:translateX(-50%) translateY(0);pointer-events:all;}
|
||||
.nav-dropdown.open .nav-dd-caret{transform:rotate(180deg);}
|
||||
/* Mobile sub-nav */
|
||||
.nav-mobile-sub{display:none;padding:2px 0 6px 14px;flex-direction:column;}
|
||||
.nav-mobile-sub.open{display:flex;}
|
||||
.nav-mobile-sub a{font-size:0.875rem;color:rgba(255,255,255,0.4);padding:8px 4px;border-bottom:1px solid rgba(255,255,255,0.06);letter-spacing:-0.01em;transition:color 0.1s;}
|
||||
.nav-mobile-sub a:last-child{border-bottom:none;}
|
||||
.nav-mobile-sub a:hover{color:rgba(255,255,255,0.8);}
|
||||
/* Dark hero: white nav before scrolling */
|
||||
#nav:not(.scrolled) .nav-logo{color:rgba(255,255,255,0.92);}
|
||||
#nav:not(.scrolled) .nav-logo span{color:#3385FF;}
|
||||
#nav:not(.scrolled) .nav-links a{color:rgba(255,255,255,0.5);}
|
||||
#nav:not(.scrolled) .nav-links a:hover{color:rgba(255,255,255,0.9);}
|
||||
#nav:not(.scrolled) .nav-actions .btn-secondary{color:rgba(255,255,255,0.65);border-color:rgba(255,255,255,0.2);background:transparent;}
|
||||
#nav:not(.scrolled) .nav-burger span{background:rgba(255,255,255,0.8);}
|
||||
.nav-dd-item{display:flex;align-items:flex-start;gap:10px;padding:9px 10px;border-radius:var(--r-2);transition:background 0.1s;cursor:pointer;}
|
||||
.nav-dd-item:hover{background:var(--bg-muted);}
|
||||
.nav-dd-icon{width:30px;height:30px;background:var(--blue-soft);border:1px solid var(--blue-mid);border-radius:6px;display:flex;align-items:center;justify-content:center;flex-shrink:0;font-size:13px;}
|
||||
.nav-dd-icon.purple{background:var(--purple-soft);border-color:var(--purple-mid);}
|
||||
.nav-dd-text{display:flex;flex-direction:column;}
|
||||
.nav-dd-name{font-size:0.8125rem;font-weight:600;color:var(--fg);letter-spacing:-0.01em;}
|
||||
.nav-dd-desc{font-size:0.6875rem;color:var(--fg-3);margin-top:1px;line-height:1.4;}
|
||||
.nav-dd-sep{height:1px;background:var(--border);margin:4px 0;}
|
||||
.nav-burger{display:none;flex-direction:column;justify-content:center;align-items:center;gap:5px;width:36px;height:36px;background:none;border:none;cursor:pointer;padding:4px;border-radius:var(--r-2);}
|
||||
.nav-burger span{display:block;width:20px;height:2px;background:var(--fg);border-radius:2px;transition:transform 0.22s cubic-bezier(0.16,1,0.3,1),opacity 0.18s;transform-origin:center;}
|
||||
.nav-burger.open span:nth-child(1){transform:translateY(7px) rotate(45deg);}
|
||||
.nav-burger.open span:nth-child(2){opacity:0;transform:scaleX(0);}
|
||||
.nav-burger.open span:nth-child(3){transform:translateY(-7px) rotate(-45deg);}
|
||||
.nav-mobile{display:none;position:absolute;top:60px;left:0;right:0;background:rgba(255,255,255,0.97);backdrop-filter:blur(20px);border-bottom:1px solid var(--border);box-shadow:0 8px 32px rgba(0,0,0,0.07);padding:12px 24px 24px;flex-direction:column;gap:2px;}
|
||||
.nav-mobile.open{display:flex;}
|
||||
.nav-mobile ul{list-style:none;display:flex;flex-direction:column;}
|
||||
.nav-mobile ul li a{display:block;font-size:1rem;font-weight:500;color:var(--fg-2);padding:11px 4px;border-bottom:1px solid var(--border);letter-spacing:-0.01em;}
|
||||
.nav-mobile ul li:last-child a{border-bottom:none;}
|
||||
.nav-mobile-ctas{display:flex;gap:8px;margin-top:16px;}
|
||||
.nav-mobile-ctas .btn{flex:1;justify-content:center;padding:10px 12px;font-size:.875rem;}
|
||||
|
||||
/* PAGE HERO */
|
||||
#page-hero{padding:140px 40px 100px;background:var(--bg-inv);position:relative;overflow:hidden;text-align:center;}
|
||||
#page-hero::before{content:'';position:absolute;inset:0;background:radial-gradient(ellipse 80% 60% at 50% -10%,rgba(124,58,237,0.14),transparent 60%),radial-gradient(ellipse 40% 40% at 80% 70%,rgba(0,102,255,0.07),transparent 50%);pointer-events:none;}
|
||||
.page-hero-inner{position:relative;max-width:800px;margin:0 auto;}
|
||||
.page-hero-inner .label{color:rgba(255,255,255,0.3);margin-bottom:20px;display:block;}
|
||||
.page-hero-inner .d1{color:var(--fg-inv);margin-bottom:22px;}
|
||||
.page-hero-inner .subtitle{color:var(--fg-inv-2);max-width:600px;margin:0 auto 44px;}
|
||||
.page-hero-ctas{display:flex;gap:12px;justify-content:center;flex-wrap:wrap;}
|
||||
|
||||
/* PRODUCT VISUAL */
|
||||
.pv-shell{width:100%;max-width:960px;margin:72px auto 0;border-radius:16px 16px 0 0;overflow:hidden;box-shadow:0 48px 96px rgba(0,0,0,0.45),0 0 0 1px rgba(255,255,255,0.06);border-bottom:none;position:relative;}
|
||||
.pv-chrome{background:#1C1C22;height:40px;display:flex;align-items:center;padding:0 14px;gap:7px;border-bottom:1px solid rgba(255,255,255,0.05);}
|
||||
.pv-dot{width:11px;height:11px;border-radius:50%;}
|
||||
.pv-dot.r{background:#FF5F57;}
|
||||
.pv-dot.y{background:#FFBD2E;}
|
||||
.pv-dot.g{background:#28C840;}
|
||||
.pv-url{flex:1;margin:0 12px;background:rgba(255,255,255,0.06);border-radius:5px;height:25px;display:flex;align-items:center;padding:0 10px;font-family:var(--mono);font-size:0.625rem;color:rgba(255,255,255,0.3);max-width:380px;}
|
||||
.pv-tab-bar{display:flex;align-items:center;gap:2px;margin-left:auto;}
|
||||
.pv-tab{font-family:var(--mono);font-size:0.5625rem;padding:3px 10px;border-radius:4px;color:rgba(255,255,255,0.35);cursor:default;letter-spacing:0.04em;}
|
||||
.pv-tab.active{background:rgba(124,58,237,0.22);color:rgba(167,139,250,0.9);border:1px solid rgba(124,58,237,0.28);}
|
||||
|
||||
/* SPLIT DIFF PANELS */
|
||||
.diff-canvas{background:#0D0D11;min-height:380px;display:flex;align-items:stretch;}
|
||||
.diff-panel{flex:1;display:flex;flex-direction:column;min-width:0;}
|
||||
.diff-panel-head{height:36px;display:flex;align-items:center;padding:0 16px;border-bottom:1px solid rgba(255,255,255,0.06);}
|
||||
.diff-panel.before .diff-panel-head{background:#1A0A0A;border-right:1px solid rgba(255,255,255,0.04);}
|
||||
.diff-panel.after .diff-panel-head{background:#0A1A0A;}
|
||||
.diff-panel-label{font-family:var(--mono);font-size:0.5625rem;font-weight:600;letter-spacing:0.08em;text-transform:uppercase;}
|
||||
.diff-panel.before .diff-panel-label{color:rgba(248,113,113,0.8);}
|
||||
.diff-panel.after .diff-panel-label{color:rgba(74,222,128,0.8);}
|
||||
.diff-panel-file{font-family:var(--mono);font-size:0.5625rem;color:rgba(255,255,255,0.2);margin-left:10px;}
|
||||
.diff-lines{flex:1;padding:12px 0;overflow:hidden;}
|
||||
.diff-divider{width:1px;background:rgba(255,255,255,0.05);flex-shrink:0;}
|
||||
.dl{display:flex;align-items:baseline;padding:0 16px;min-height:22px;font-family:var(--mono);font-size:0.6rem;line-height:1.8;}
|
||||
.dl-num{width:28px;flex-shrink:0;color:rgba(255,255,255,0.18);text-align:right;margin-right:12px;font-size:0.55rem;user-select:none;}
|
||||
.dl-sign{width:12px;flex-shrink:0;font-weight:700;font-size:0.6rem;}
|
||||
.dl-text{flex:1;min-width:0;}
|
||||
.dl.ctx .dl-sign{color:rgba(255,255,255,0.15);}
|
||||
.dl.ctx .dl-text{color:rgba(255,255,255,0.38);}
|
||||
.dl.rem{background:rgba(220,38,38,0.1);}
|
||||
.dl.rem .dl-sign{color:#F87171;}
|
||||
.dl.rem .dl-text{color:rgba(248,113,113,0.9);}
|
||||
.dl.add{background:rgba(22,163,74,0.1);}
|
||||
.dl.add .dl-sign{color:#4ADE80;}
|
||||
.dl.add .dl-text{color:rgba(74,222,128,0.9);}
|
||||
.dl.hunk{background:rgba(124,58,237,0.08);border-top:1px solid rgba(124,58,237,0.15);border-bottom:1px solid rgba(124,58,237,0.15);}
|
||||
.dl.hunk .dl-text{color:rgba(167,139,250,0.6);font-size:0.5625rem;}
|
||||
.prop-key{color:rgba(255,255,255,0.5);}
|
||||
.prop-val-rem{color:#FCA5A5;}
|
||||
.prop-val-add{color:#86EFAC;}
|
||||
.prop-val-str{color:#FCD34D;}
|
||||
.prop-val-num{color:#93C5FD;}
|
||||
|
||||
/* HOW IT WORKS */
|
||||
.hiw-steps{display:grid;grid-template-columns:repeat(4,1fr);gap:0;margin-top:64px;position:relative;}
|
||||
.hiw-steps::before{content:'';position:absolute;top:28px;left:12.5%;right:12.5%;height:1px;background:linear-gradient(90deg,transparent,var(--border-2) 20%,var(--border-2) 80%,transparent);}
|
||||
.hiw-step{display:flex;flex-direction:column;align-items:center;text-align:center;padding:0 20px;position:relative;z-index:1;}
|
||||
.hiw-num{width:56px;height:56px;border-radius:50%;background:var(--bg);border:1px solid var(--border-2);display:flex;align-items:center;justify-content:center;font-family:var(--mono);font-size:1rem;font-weight:700;color:var(--purple);margin-bottom:20px;box-shadow:var(--sh-sm);}
|
||||
.hiw-step h3{font-size:0.9375rem;font-weight:700;color:var(--fg);letter-spacing:-0.02em;margin-bottom:8px;}
|
||||
.hiw-step p{font-size:0.8125rem;color:var(--fg-2);line-height:1.6;}
|
||||
|
||||
/* FEATURE SPLIT */
|
||||
.feat-split{display:grid;grid-template-columns:1fr 1fr;gap:96px;align-items:center;max-width:1120px;margin:0 auto;}
|
||||
.feat-split.rev{direction:rtl;}
|
||||
.feat-split.rev>*{direction:ltr;}
|
||||
.feat-copy .label{display:block;margin-bottom:16px;}
|
||||
.feat-copy .d3{margin-bottom:16px;}
|
||||
.feat-copy .subtitle{margin-bottom:28px;}
|
||||
.feat-pts{list-style:none;display:flex;flex-direction:column;gap:12px;margin-bottom:32px;}
|
||||
.feat-pts li{display:flex;align-items:flex-start;gap:10px;font-size:0.9375rem;color:var(--fg-2);line-height:1.55;}
|
||||
.feat-pt-icon{width:20px;height:20px;border-radius:3px;background:var(--purple-soft);border:1px solid var(--purple-mid);display:flex;align-items:center;justify-content:center;flex-shrink:0;margin-top:1px;font-size:0.625rem;color:var(--purple);}
|
||||
|
||||
/* Feature visual */
|
||||
.feat-vis{border-radius:var(--r-5);overflow:hidden;box-shadow:var(--sh-2xl);border:1px solid var(--border);aspect-ratio:4/3;position:relative;}
|
||||
.feat-vis-dark{background:#0D0D11;border-color:rgba(255,255,255,0.07);}
|
||||
.feat-vis-light{background:var(--bg-muted);}
|
||||
|
||||
/* TECH SECTION */
|
||||
.tech-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:20px;margin-top:56px;}
|
||||
.tech-card{background:var(--bg);border:1px solid var(--border);border-radius:var(--r-4);padding:32px 28px;transition:box-shadow 0.2s;}
|
||||
.tech-card:hover{box-shadow:var(--sh-lg);}
|
||||
.tech-icon{width:44px;height:44px;background:var(--purple-soft);border:1px solid var(--purple-mid);border-radius:var(--r-2);display:flex;align-items:center;justify-content:center;font-size:1.25rem;margin-bottom:18px;}
|
||||
.tech-card h3{font-size:1rem;font-weight:700;color:var(--fg);letter-spacing:-0.02em;margin-bottom:8px;}
|
||||
.tech-card p{font-size:0.875rem;color:var(--fg-2);line-height:1.65;}
|
||||
.tech-tag{display:inline-block;margin-top:14px;font-family:var(--mono);font-size:0.625rem;letter-spacing:0.08em;text-transform:uppercase;color:var(--purple);background:var(--purple-soft);border:1px solid var(--purple-mid);padding:3px 9px;border-radius:var(--r-full);}
|
||||
|
||||
/* CODE BLOCK */
|
||||
.code-block{background:#111118;border:1px solid rgba(255,255,255,0.07);border-radius:var(--r-3);padding:24px;font-family:var(--mono);font-size:0.75rem;line-height:1.75;color:rgba(255,255,255,0.75);overflow-x:auto;}
|
||||
.code-block .kw{color:#7EB8FF;}
|
||||
.code-block .str{color:#7DDBA0;}
|
||||
.code-block .cm{color:rgba(255,255,255,0.28);}
|
||||
.code-block .fn{color:#FFBA7B;}
|
||||
.code-block .nm{color:#D4A0FF;}
|
||||
.code-block .rem{color:#F87171;}
|
||||
.code-block .add{color:#4ADE80;}
|
||||
.code-block .hdr{color:#A78BFA;}
|
||||
.code-block .ctx{color:rgba(255,255,255,0.38);}
|
||||
|
||||
/* ACCEPT/REJECT PANEL */
|
||||
.ar-panel{background:#111118;border:1px solid rgba(255,255,255,0.07);border-radius:var(--r-3);overflow:hidden;}
|
||||
.ar-panel-head{padding:14px 18px;border-bottom:1px solid rgba(255,255,255,0.06);display:flex;align-items:center;justify-content:space-between;}
|
||||
.ar-panel-title{font-family:var(--mono);font-size:0.625rem;color:rgba(255,255,255,0.35);letter-spacing:0.08em;text-transform:uppercase;}
|
||||
.ar-panel-badge{font-family:var(--mono);font-size:0.5625rem;color:rgba(167,139,250,0.8);background:rgba(124,58,237,0.12);border:1px solid rgba(124,58,237,0.2);padding:2px 8px;border-radius:var(--r-full);}
|
||||
.ar-row{display:flex;align-items:flex-start;gap:12px;padding:12px 18px;border-bottom:1px solid rgba(255,255,255,0.04);}
|
||||
.ar-row:last-child{border-bottom:none;}
|
||||
.ar-checkbox{width:16px;height:16px;border-radius:3px;border:1.5px solid rgba(255,255,255,0.18);flex-shrink:0;margin-top:2px;display:flex;align-items:center;justify-content:center;font-size:0.5rem;}
|
||||
.ar-checkbox.checked{background:rgba(74,222,128,0.15);border-color:rgba(74,222,128,0.5);color:#4ADE80;}
|
||||
.ar-checkbox.unchecked{background:rgba(248,113,113,0.08);border-color:rgba(248,113,113,0.3);}
|
||||
.ar-prop{flex:1;}
|
||||
.ar-prop-name{font-family:var(--mono);font-size:0.625rem;color:rgba(255,255,255,0.45);margin-bottom:4px;}
|
||||
.ar-prop-change{display:flex;align-items:center;gap:6px;flex-wrap:wrap;}
|
||||
.ar-val-old{font-family:var(--mono);font-size:0.625rem;color:#FCA5A5;background:rgba(220,38,38,0.1);padding:1px 6px;border-radius:3px;text-decoration:line-through;text-decoration-color:rgba(248,113,113,0.4);}
|
||||
.ar-val-arrow{font-size:0.5625rem;color:rgba(255,255,255,0.2);}
|
||||
.ar-val-new{font-family:var(--mono);font-size:0.625rem;color:#86EFAC;background:rgba(22,163,74,0.1);padding:1px 6px;border-radius:3px;}
|
||||
.ar-actions{display:flex;gap:4px;flex-shrink:0;margin-top:2px;}
|
||||
.ar-btn{font-family:var(--mono);font-size:0.5rem;padding:3px 8px;border-radius:3px;font-weight:600;letter-spacing:0.04em;cursor:default;}
|
||||
.ar-btn-accept{background:rgba(22,163,74,0.12);color:#4ADE80;border:1px solid rgba(74,222,128,0.2);}
|
||||
.ar-btn-reject{background:rgba(220,38,38,0.08);color:#F87171;border:1px solid rgba(248,113,113,0.2);}
|
||||
|
||||
/* RELATED */
|
||||
.related-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;margin-top:48px;}
|
||||
.related-card{border:1px solid var(--border);border-radius:var(--r-4);padding:24px;transition:box-shadow 0.15s,border-color 0.15s;display:flex;flex-direction:column;gap:10px;}
|
||||
.related-card:hover{box-shadow:var(--sh-md);border-color:var(--border-2);}
|
||||
.related-icon{font-size:1.25rem;}
|
||||
.related-card h3{font-size:0.9375rem;font-weight:700;color:var(--fg);letter-spacing:-0.02em;}
|
||||
.related-card p{font-size:0.8125rem;color:var(--fg-2);line-height:1.6;flex:1;}
|
||||
.related-link{font-size:0.8125rem;font-weight:600;color:var(--purple);}
|
||||
|
||||
/* CTA */
|
||||
#cta-bottom{background:var(--bg-inv);padding:120px 40px;position:relative;overflow:hidden;text-align:center;}
|
||||
#cta-bottom::before{content:'';position:absolute;inset:0;background:radial-gradient(ellipse 60% 80% at 30% 50%,rgba(124,58,237,0.14),transparent 60%),radial-gradient(ellipse 60% 80% at 70% 50%,rgba(0,102,255,0.08),transparent 60%);pointer-events:none;}
|
||||
.cta-inner{position:relative;max-width:680px;margin:0 auto;}
|
||||
.cta-headline{font-size:clamp(2rem,4.5vw,3.5rem);font-weight:900;letter-spacing:-0.045em;color:var(--fg-inv);line-height:1.05;margin-bottom:18px;}
|
||||
.cta-sub{font-size:1.0625rem;color:var(--fg-inv-2);margin-bottom:44px;line-height:1.65;}
|
||||
.cta-actions{display:flex;gap:12px;justify-content:center;flex-wrap:wrap;}
|
||||
|
||||
/* FOOTER */
|
||||
footer{background:#08080C;border-top:1px solid rgba(255,255,255,0.06);padding:72px 40px 40px;}
|
||||
.ft-inner{max-width:1120px;margin:0 auto;}
|
||||
.ft-top{display:grid;grid-template-columns:260px repeat(4,1fr);gap:48px;padding-bottom:56px;border-bottom:1px solid rgba(255,255,255,0.07);margin-bottom:36px;}
|
||||
.ft-brand-logo{font-size:1rem;font-weight:800;letter-spacing:-0.04em;color:rgba(255,255,255,0.92);margin-bottom:8px;}
|
||||
.ft-brand-logo span{color:#3385FF;}
|
||||
.ft-brand-tag{font-size:0.875rem;color:rgba(255,255,255,0.3);line-height:1.65;max-width:200px;}
|
||||
.ft-col h4{font-size:0.875rem;font-weight:600;color:rgba(255,255,255,0.7);margin-bottom:16px;letter-spacing:-0.01em;}
|
||||
.ft-col ul{list-style:none;display:flex;flex-direction:column;gap:10px;}
|
||||
.ft-col a{font-size:0.875rem;color:rgba(255,255,255,0.32);transition:color 0.14s;letter-spacing:-0.01em;}
|
||||
.ft-col a:hover{color:rgba(255,255,255,0.65);}
|
||||
.ft-bottom{display:flex;justify-content:space-between;align-items:center;}
|
||||
.ft-copy{font-size:0.8125rem;color:rgba(255,255,255,0.22);}
|
||||
|
||||
/* REVEAL */
|
||||
.reveal{opacity:0;transform:translateY(22px);transition:opacity 0.7s cubic-bezier(0.16,1,0.3,1),transform 0.7s cubic-bezier(0.16,1,0.3,1);}
|
||||
.reveal.in{opacity:1;transform:none;}
|
||||
.stagger>*{opacity:0;transform:translateY(16px);transition:opacity 0.55s cubic-bezier(0.16,1,0.3,1),transform 0.55s cubic-bezier(0.16,1,0.3,1);}
|
||||
.stagger.in>*:nth-child(1){opacity:1;transform:none;transition-delay:0s;}
|
||||
.stagger.in>*:nth-child(2){opacity:1;transform:none;transition-delay:0.07s;}
|
||||
.stagger.in>*:nth-child(3){opacity:1;transform:none;transition-delay:0.14s;}
|
||||
.stagger.in>*:nth-child(4){opacity:1;transform:none;transition-delay:0.21s;}
|
||||
.stagger.in>*:nth-child(5){opacity:1;transform:none;transition-delay:0.28s;}
|
||||
.stagger.in>*:nth-child(6){opacity:1;transform:none;transition-delay:0.35s;}
|
||||
|
||||
@media(max-width:1024px){.feat-split{grid-template-columns:1fr;gap:56px;}.feat-split.rev{direction:ltr;}.hiw-steps{grid-template-columns:1fr 1fr;gap:40px;}.hiw-steps::before{display:none;}.tech-grid{grid-template-columns:1fr 1fr;}.related-grid{grid-template-columns:1fr 1fr;}}
|
||||
@media(max-width:768px){.wrap{padding:0 24px;}#nav{padding:0 24px;}.nav-inner{display:flex;justify-content:space-between;}.nav-links,.nav-actions .btn{display:none;}.nav-burger{display:flex;}#page-hero{padding:120px 24px 80px;}.pv-shell{margin-top:48px;}.diff-canvas{flex-direction:column;}.diff-divider{width:100%;height:1px;}.hiw-steps{grid-template-columns:1fr;}.tech-grid,.related-grid{grid-template-columns:1fr;}.ft-top{grid-template-columns:1fr 1fr;}}
|
||||
@media(max-width:480px){.ft-top{grid-template-columns:1fr;}}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- NAV -->
|
||||
<nav id="nav">
|
||||
<div class="nav-inner">
|
||||
<a href="/" class="nav-logo">Origin<span>main</span></a>
|
||||
<ul class="nav-links">
|
||||
<li class="nav-dropdown">
|
||||
<a href="/#features" style="display:flex;align-items:center;gap:4px;">
|
||||
Product
|
||||
<svg class="nav-dd-caret" width="10" height="6" viewBox="0 0 10 6" fill="none"><path d="M1 1l4 4 4-4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
|
||||
</a>
|
||||
<div class="nav-dropdown-menu">
|
||||
<a class="nav-dd-item" href="/features/live-artboard.html">
|
||||
<div class="nav-dd-icon">⬜</div>
|
||||
<div class="nav-dd-text"><span class="nav-dd-name">Live Artboard</span><span class="nav-dd-desc">Your app rendered live in the canvas</span></div>
|
||||
</a>
|
||||
<a class="nav-dd-item" href="/features/origin-graph.html">
|
||||
<div class="nav-dd-icon">◉</div>
|
||||
<div class="nav-dd-text"><span class="nav-dd-name">Origin Graph</span><span class="nav-dd-desc">Every component, indexed and queryable</span></div>
|
||||
</a>
|
||||
<a class="nav-dd-item" href="/features/intent-diff.html">
|
||||
<div class="nav-dd-icon purple">△</div>
|
||||
<div class="nav-dd-text"><span class="nav-dd-name">Intent Diff</span><span class="nav-dd-desc">Ship component-level diffs, not redlines</span></div>
|
||||
</a>
|
||||
<div class="nav-dd-sep"></div>
|
||||
<a class="nav-dd-item" href="/features/completion-zone.html">
|
||||
<div class="nav-dd-icon">◈</div>
|
||||
<div class="nav-dd-text"><span class="nav-dd-name">Completion Zone</span><span class="nav-dd-desc">AI-filled design, constrained to your system</span></div>
|
||||
</a>
|
||||
<a class="nav-dd-item" href="/features/agent-bridge.html">
|
||||
<div class="nav-dd-icon">⇄</div>
|
||||
<div class="nav-dd-text"><span class="nav-dd-name">Agent Bridge</span><span class="nav-dd-desc">MCP channel to Cursor, Claude Code & more</span></div>
|
||||
</a>
|
||||
<a class="nav-dd-item" href="/features/integrations.html">
|
||||
<div class="nav-dd-icon">🔗</div>
|
||||
<div class="nav-dd-text"><span class="nav-dd-name">Integrations</span><span class="nav-dd-desc">Linear, Slack, GitHub, Figma & more</span></div>
|
||||
</a>
|
||||
</div>
|
||||
</li>
|
||||
<li><a href="/features/integrations.html">Integrations</a></li>
|
||||
<li><a href="/#pricing">Pricing</a></li>
|
||||
<li><a href="#">Docs</a></li>
|
||||
</ul>
|
||||
<div class="nav-actions">
|
||||
<a href="#" class="btn btn-secondary" style="padding:7px 16px;font-size:.875rem">Log in</a>
|
||||
<a href="#" class="btn btn-primary" style="padding:8px 18px;font-size:.875rem">Request Access</a>
|
||||
<button class="nav-burger" id="nav-burger" aria-label="Menu"><span></span><span></span><span></span></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="nav-mobile" id="nav-mobile">
|
||||
<ul>
|
||||
<li>
|
||||
<a href="/#features" id="mob-product-toggle" style="display:flex;justify-content:space-between;align-items:center;">
|
||||
Product
|
||||
<svg id="mob-dd-caret" width="10" height="6" viewBox="0 0 10 6" fill="none" style="transition:transform 0.15s;"><path d="M1 1l4 4 4-4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
|
||||
</a>
|
||||
<div class="nav-mobile-sub" id="nav-mobile-sub">
|
||||
<a href="/features/live-artboard.html">Live Artboard</a>
|
||||
<a href="/features/origin-graph.html">Origin Graph</a>
|
||||
<a href="/features/intent-diff.html">Intent Diff</a>
|
||||
<a href="/features/completion-zone.html">Completion Zone</a>
|
||||
<a href="/features/agent-bridge.html">Agent Bridge</a>
|
||||
<a href="/features/integrations.html">Integrations</a>
|
||||
</div>
|
||||
</li>
|
||||
<li><a href="/features/integrations.html">Integrations</a></li>
|
||||
<li><a href="/#pricing">Pricing</a></li>
|
||||
<li><a href="#">Docs</a></li>
|
||||
</ul>
|
||||
<div class="nav-mobile-ctas">
|
||||
<a href="#" class="btn btn-secondary">Log in</a>
|
||||
<a href="#" class="btn btn-primary">Request Access</a>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<!-- HERO -->
|
||||
<section id="page-hero">
|
||||
<div class="page-hero-inner">
|
||||
<span class="label reveal">△ Intent Diff</span>
|
||||
<h1 class="d1 reveal">Ship component-level<br>diffs, not redlines.</h1>
|
||||
<p class="subtitle reveal">Every design change is expressed as a structured diff of props, styles, and tree — not a screenshot comparison. Reviewers see exactly what changed and why.</p>
|
||||
<div class="page-hero-ctas reveal">
|
||||
<a href="#" class="btn btn-white btn-lg">Request Early Access</a>
|
||||
<a href="#how-it-works" class="btn btn-outline-white btn-lg">See how it works ↓</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Split diff product visual -->
|
||||
<div class="pv-shell reveal">
|
||||
<div class="pv-chrome">
|
||||
<div class="pv-dot r"></div>
|
||||
<div class="pv-dot y"></div>
|
||||
<div class="pv-dot g"></div>
|
||||
<div class="pv-url">🔒 app.originmain.io/diff/Button@pr-412</div>
|
||||
<div class="pv-tab-bar">
|
||||
<span class="pv-tab active">Split</span>
|
||||
<span class="pv-tab">Unified</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="diff-canvas">
|
||||
|
||||
<!-- Before panel -->
|
||||
<div class="diff-panel before">
|
||||
<div class="diff-panel-head">
|
||||
<span class="diff-panel-label">Before</span>
|
||||
<span class="diff-panel-file">a/Button.tsx</span>
|
||||
</div>
|
||||
<div class="diff-lines">
|
||||
<div class="dl hunk"><span class="dl-num"></span><span class="dl-sign"></span><span class="dl-text">@@ -1,10 +1,10 @@ Button</span></div>
|
||||
<div class="dl ctx"><span class="dl-num">1</span><span class="dl-sign"> </span><span class="dl-text"><span class="prop-key">component:</span> <span class="prop-val-str">"Button"</span></span></div>
|
||||
<div class="dl ctx"><span class="dl-num">2</span><span class="dl-sign"> </span><span class="dl-text"><span class="prop-key">variant:</span> <span class="prop-val-str">"primary"</span></span></div>
|
||||
<div class="dl rem"><span class="dl-num">3</span><span class="dl-sign">−</span><span class="dl-text"><span class="prop-key">padding:</span> <span class="prop-val-rem">16px</span></span></div>
|
||||
<div class="dl rem"><span class="dl-num">4</span><span class="dl-sign">−</span><span class="dl-text"><span class="prop-key">color:</span> <span class="prop-val-rem">#333333</span></span></div>
|
||||
<div class="dl rem"><span class="dl-num">5</span><span class="dl-sign">−</span><span class="dl-text"><span class="prop-key">background:</span> <span class="prop-val-rem">#F5F5F5</span></span></div>
|
||||
<div class="dl ctx"><span class="dl-num">6</span><span class="dl-sign"> </span><span class="dl-text"><span class="prop-key">fontSize:</span> <span class="prop-val-num">14</span></span></div>
|
||||
<div class="dl ctx"><span class="dl-num">7</span><span class="dl-sign"> </span><span class="dl-text"><span class="prop-key">fontWeight:</span> <span class="prop-val-num">500</span></span></div>
|
||||
<div class="dl ctx"><span class="dl-num">8</span><span class="dl-sign"> </span><span class="dl-text"><span class="prop-key">height:</span> <span class="prop-val-num">36</span></span></div>
|
||||
<div class="dl ctx"><span class="dl-num">9</span><span class="dl-sign"> </span><span class="dl-text"><span class="prop-key">disabled:</span> <span class="prop-val-num">false</span></span></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Center divider -->
|
||||
<div class="diff-divider"></div>
|
||||
|
||||
<!-- After panel -->
|
||||
<div class="diff-panel after">
|
||||
<div class="diff-panel-head">
|
||||
<span class="diff-panel-label">After</span>
|
||||
<span class="diff-panel-file">b/Button.tsx</span>
|
||||
</div>
|
||||
<div class="diff-lines">
|
||||
<div class="dl hunk"><span class="dl-num"></span><span class="dl-sign"></span><span class="dl-text">@@ -1,10 +1,11 @@ Button</span></div>
|
||||
<div class="dl ctx"><span class="dl-num">1</span><span class="dl-sign"> </span><span class="dl-text"><span class="prop-key">component:</span> <span class="prop-val-str">"Button"</span></span></div>
|
||||
<div class="dl ctx"><span class="dl-num">2</span><span class="dl-sign"> </span><span class="dl-text"><span class="prop-key">variant:</span> <span class="prop-val-str">"primary"</span></span></div>
|
||||
<div class="dl add"><span class="dl-num">3</span><span class="dl-sign">+</span><span class="dl-text"><span class="prop-key">padding:</span> <span class="prop-val-add">24px</span></span></div>
|
||||
<div class="dl add"><span class="dl-num">4</span><span class="dl-sign">+</span><span class="dl-text"><span class="prop-key">color:</span> <span class="prop-val-add">#0066FF</span></span></div>
|
||||
<div class="dl add"><span class="dl-num">5</span><span class="dl-sign">+</span><span class="dl-text"><span class="prop-key">background:</span> <span class="prop-val-add">#EBF2FF</span></span></div>
|
||||
<div class="dl add"><span class="dl-num">6</span><span class="dl-sign">+</span><span class="dl-text"><span class="prop-key">borderRadius:</span> <span class="prop-val-add">8px</span></span></div>
|
||||
<div class="dl ctx"><span class="dl-num">7</span><span class="dl-sign"> </span><span class="dl-text"><span class="prop-key">fontSize:</span> <span class="prop-val-num">14</span></span></div>
|
||||
<div class="dl ctx"><span class="dl-num">8</span><span class="dl-sign"> </span><span class="dl-text"><span class="prop-key">fontWeight:</span> <span class="prop-val-num">500</span></span></div>
|
||||
<div class="dl ctx"><span class="dl-num">9</span><span class="dl-sign"> </span><span class="dl-text"><span class="prop-key">height:</span> <span class="prop-val-num">36</span></span></div>
|
||||
<div class="dl ctx"><span class="dl-num">10</span><span class="dl-sign"> </span><span class="dl-text"><span class="prop-key">disabled:</span> <span class="prop-val-num">false</span></span></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- HOW IT WORKS -->
|
||||
<section id="how-it-works" class="section">
|
||||
<div class="wrap">
|
||||
<div class="section-head reveal">
|
||||
<span class="label">Architecture</span>
|
||||
<h2 class="d2">From snapshot to diff in four steps.</h2>
|
||||
<p class="subtitle">Intent Diff runs a Myers/LCS algorithm on serialized component trees — not on pixels. Every merge triggers a full, machine-readable patch automatically.</p>
|
||||
</div>
|
||||
<div class="hiw-steps stagger">
|
||||
<div class="hiw-step">
|
||||
<div class="hiw-num">01</div>
|
||||
<h3>Snapshot captured</h3>
|
||||
<p>The component tree is serialized to a structured document of props and styles, validated against a Zod schema before being stored as the diff baseline.</p>
|
||||
</div>
|
||||
<div class="hiw-step">
|
||||
<div class="hiw-num">02</div>
|
||||
<h3>Myers algorithm runs</h3>
|
||||
<p>The LCS-based Myers diff algorithm compares the serialized lines of the before and after snapshots, finding the minimum edit script between them.</p>
|
||||
</div>
|
||||
<div class="hiw-step">
|
||||
<div class="hiw-num">03</div>
|
||||
<h3>Unified patch generated</h3>
|
||||
<p>A standard unified patch string is emitted — <code style="font-family:var(--mono);font-size:0.8em;background:var(--bg-muted);padding:1px 4px;border-radius:3px;">--- before / +++ after</code> with hunk headers and context lines on each side.</p>
|
||||
</div>
|
||||
<div class="hiw-step">
|
||||
<div class="hiw-num">04</div>
|
||||
<h3>Diff rendered</h3>
|
||||
<p>The patch is passed to <code style="font-family:var(--mono);font-size:0.8em;background:var(--bg-muted);padding:1px 4px;border-radius:3px;">@pierre/diffs</code> and displayed in Split or Unified view for reviewers to inspect, accept, or reject individual prop changes.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- DEEP DIVE 1: Structured diff -->
|
||||
<div class="section" style="padding:100px 40px;">
|
||||
<div class="feat-split reveal">
|
||||
<div class="feat-copy">
|
||||
<span class="label label-purple">Structured, not visual</span>
|
||||
<h2 class="d3">The diff runs on the<br>component AST, not pixels.</h2>
|
||||
<p class="subtitle">Screenshot comparison tools tell you something looks different. Intent Diff tells you exactly which prop changed, from what value to what value. Every diff is a first-class data structure — queryable, storable, and consumable by CI/CD pipelines without any manual interpretation.</p>
|
||||
<ul class="feat-pts">
|
||||
<li><span class="feat-pt-icon">△</span>Diffs are computed on Zod-validated component snapshots, never on rendered images.</li>
|
||||
<li><span class="feat-pt-icon">△</span>Output is a standard unified patch string — parseable by any diff tooling in your stack.</li>
|
||||
<li><span class="feat-pt-icon">△</span>CI/CD can consume the patch directly — block merges, post PR comments, or trigger alerts on specific prop changes.</li>
|
||||
</ul>
|
||||
<a href="#" class="btn btn-primary">Request early access</a>
|
||||
</div>
|
||||
<div class="feat-vis feat-vis-dark reveal">
|
||||
<div style="position:absolute;inset:0;padding:24px;display:flex;flex-direction:column;overflow:hidden;">
|
||||
<div style="font-family:var(--mono);font-size:0.5rem;color:rgba(255,255,255,0.2);letter-spacing:0.1em;text-transform:uppercase;margin-bottom:14px;">Unified patch — Button.tsx</div>
|
||||
<div style="background:#111118;border:1px solid rgba(255,255,255,0.07);border-radius:8px;padding:16px;font-family:var(--mono);font-size:0.6rem;line-height:1.9;flex:1;overflow:hidden;">
|
||||
<div style="color:#A78BFA;">--- a/Button</div>
|
||||
<div style="color:#A78BFA;">+++ b/Button</div>
|
||||
<div style="color:#A78BFA;margin-bottom:4px;">@@ -3,5 +3,6 @@ Button</div>
|
||||
<div style="color:rgba(255,255,255,0.35);"> component: "Button"</div>
|
||||
<div style="color:rgba(255,255,255,0.35);"> variant: "primary"</div>
|
||||
<div style="color:#F87171;background:rgba(220,38,38,0.1);padding:1px 0;">- padding: 16px</div>
|
||||
<div style="color:#4ADE80;background:rgba(22,163,74,0.1);padding:1px 0;">+ padding: 24px</div>
|
||||
<div style="color:#F87171;background:rgba(220,38,38,0.1);padding:1px 0;">- color: #333333</div>
|
||||
<div style="color:#4ADE80;background:rgba(22,163,74,0.1);padding:1px 0;">+ color: #0066FF</div>
|
||||
<div style="color:#F87171;background:rgba(220,38,38,0.1);padding:1px 0;">- background: #F5F5F5</div>
|
||||
<div style="color:#4ADE80;background:rgba(22,163,74,0.1);padding:1px 0;">+ background: #EBF2FF</div>
|
||||
<div style="color:#4ADE80;background:rgba(22,163,74,0.1);padding:1px 0;">+ borderRadius: 8px</div>
|
||||
<div style="color:rgba(255,255,255,0.35);"> fontSize: 14</div>
|
||||
<div style="color:rgba(255,255,255,0.35);"> fontWeight: 500</div>
|
||||
</div>
|
||||
<div style="margin-top:12px;display:flex;gap:16px;">
|
||||
<div style="display:flex;align-items:center;gap:6px;"><span style="width:8px;height:8px;border-radius:2px;background:rgba(220,38,38,0.45);flex-shrink:0;"></span><span style="font-family:var(--mono);font-size:0.5rem;color:rgba(255,255,255,0.25);">3 removals</span></div>
|
||||
<div style="display:flex;align-items:center;gap:6px;"><span style="width:8px;height:8px;border-radius:2px;background:rgba(22,163,74,0.45);flex-shrink:0;"></span><span style="font-family:var(--mono);font-size:0.5rem;color:rgba(255,255,255,0.25);">4 additions</span></div>
|
||||
<div style="display:flex;align-items:center;gap:6px;"><span style="width:8px;height:8px;border-radius:2px;background:rgba(124,58,237,0.45);flex-shrink:0;"></span><span style="font-family:var(--mono);font-size:0.5rem;color:rgba(255,255,255,0.25);">1 hunk</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- DEEP DIVE 2: Accept / Reject -->
|
||||
<div class="section section-muted" style="padding:100px 40px;">
|
||||
<div class="feat-split rev reveal">
|
||||
<div class="feat-copy">
|
||||
<span class="label label-purple">Granular review</span>
|
||||
<h2 class="d3">Accept or reject<br>individual prop changes.</h2>
|
||||
<p class="subtitle">Reviewers are not forced to approve or reject an entire diff. Each prop change is an independent item — cherry-pick what ships and what goes back, with a full audit trail recorded per decision. No more all-or-nothing PR approvals on design work.</p>
|
||||
<ul class="feat-pts">
|
||||
<li><span class="feat-pt-icon">△</span>Check a single prop to accept it without touching adjacent changes in the same diff.</li>
|
||||
<li><span class="feat-pt-icon">△</span>Rejected changes surface as inline comments on the originating artboard in real time.</li>
|
||||
<li><span class="feat-pt-icon">△</span>Every accepted change is recorded in the merge commit metadata — zero ambiguity in history.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="feat-vis feat-vis-dark reveal">
|
||||
<div style="position:absolute;inset:0;padding:24px;display:flex;flex-direction:column;overflow:hidden;">
|
||||
<div style="font-family:var(--mono);font-size:0.5rem;color:rgba(255,255,255,0.2);letter-spacing:0.1em;text-transform:uppercase;margin-bottom:14px;">Diff inspector — Button@pr-412</div>
|
||||
<div class="ar-panel">
|
||||
<div class="ar-panel-head">
|
||||
<span class="ar-panel-title">Prop changes · 4 total</span>
|
||||
<span class="ar-panel-badge">2 accepted · 1 rejected · 1 pending</span>
|
||||
</div>
|
||||
<div class="ar-row">
|
||||
<div class="ar-checkbox checked">✓</div>
|
||||
<div class="ar-prop">
|
||||
<div class="ar-prop-name">padding</div>
|
||||
<div class="ar-prop-change">
|
||||
<span class="ar-val-old">16px</span>
|
||||
<span class="ar-val-arrow">→</span>
|
||||
<span class="ar-val-new">24px</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ar-actions">
|
||||
<span class="ar-btn ar-btn-accept">Accept</span>
|
||||
<span class="ar-btn ar-btn-reject">Reject</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ar-row">
|
||||
<div class="ar-checkbox unchecked"></div>
|
||||
<div class="ar-prop">
|
||||
<div class="ar-prop-name">color</div>
|
||||
<div class="ar-prop-change">
|
||||
<span class="ar-val-old">#333333</span>
|
||||
<span class="ar-val-arrow">→</span>
|
||||
<span class="ar-val-new">#0066FF</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ar-actions">
|
||||
<span class="ar-btn ar-btn-accept">Accept</span>
|
||||
<span class="ar-btn ar-btn-reject">Reject</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ar-row">
|
||||
<div class="ar-checkbox checked">✓</div>
|
||||
<div class="ar-prop">
|
||||
<div class="ar-prop-name">background</div>
|
||||
<div class="ar-prop-change">
|
||||
<span class="ar-val-old">#F5F5F5</span>
|
||||
<span class="ar-val-arrow">→</span>
|
||||
<span class="ar-val-new">#EBF2FF</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ar-actions">
|
||||
<span class="ar-btn ar-btn-accept">Accept</span>
|
||||
<span class="ar-btn ar-btn-reject">Reject</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ar-row">
|
||||
<div class="ar-checkbox"></div>
|
||||
<div class="ar-prop">
|
||||
<div class="ar-prop-name">borderRadius <span style="font-family:var(--mono);font-size:0.5rem;color:rgba(167,139,250,0.65);background:rgba(124,58,237,0.1);padding:1px 5px;border-radius:3px;margin-left:4px;">new</span></div>
|
||||
<div class="ar-prop-change">
|
||||
<span class="ar-val-new">8px</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ar-actions">
|
||||
<span class="ar-btn ar-btn-accept">Accept</span>
|
||||
<span class="ar-btn ar-btn-reject">Reject</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="margin-top:10px;font-family:var(--mono);font-size:0.5rem;color:rgba(255,255,255,0.18);text-align:right;">Reviewed by SinachPat · just now</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- TECHNICAL SECTION -->
|
||||
<section class="section">
|
||||
<div class="wrap">
|
||||
<div class="section-head reveal">
|
||||
<span class="label">Technical foundation</span>
|
||||
<h2 class="d2">Built on proven algorithms.</h2>
|
||||
<p class="subtitle">Intent Diff applies battle-tested diff theory — the same algorithm that powers Git — to component trees, not text files. Structured input means structured, machine-readable output.</p>
|
||||
</div>
|
||||
<div class="tech-grid stagger">
|
||||
<div class="tech-card">
|
||||
<div class="tech-icon" style="font-size:1rem;font-weight:800;font-family:var(--mono);">ND</div>
|
||||
<h3>Myers algorithm</h3>
|
||||
<p>The O(ND) Myers diff algorithm finds the shortest edit script between two sequences. The same algorithm used in <code style="font-family:var(--mono);font-size:0.8em;background:var(--bg-muted);padding:1px 4px;border-radius:3px;">git diff</code> — applied here to serialized component prop lines, not source code.</p>
|
||||
<span class="tech-tag">Core algorithm</span>
|
||||
</div>
|
||||
<div class="tech-card">
|
||||
<div class="tech-icon" style="font-size:1rem;font-weight:700;font-family:var(--mono);">LCS</div>
|
||||
<h3>LCS backtracking</h3>
|
||||
<p>After the edit graph is constructed, longest-common-subsequence backtracking produces the minimum set of additions and removals — minimizing diff noise and keeping context stable across rebases.</p>
|
||||
<span class="tech-tag">Edit script</span>
|
||||
</div>
|
||||
<div class="tech-card">
|
||||
<div class="tech-icon" style="font-size:1rem;font-weight:700;font-family:var(--mono);">±</div>
|
||||
<h3>Unified patch format</h3>
|
||||
<p>Output is a standard unified patch string with <code style="font-family:var(--mono);font-size:0.8em;background:var(--bg-muted);padding:1px 4px;border-radius:3px;">---</code> and <code style="font-family:var(--mono);font-size:0.8em;background:var(--bg-muted);padding:1px 4px;border-radius:3px;">+++</code> headers, <code style="font-family:var(--mono);font-size:0.8em;background:var(--bg-muted);padding:1px 4px;border-radius:3px;">@@</code> hunk ranges, and three lines of context. Parseable by any standard tooling out of the box.</p>
|
||||
<span class="tech-tag">Output format</span>
|
||||
</div>
|
||||
<div class="tech-card">
|
||||
<div class="tech-icon" style="font-size:0.875rem;font-weight:700;font-family:var(--mono);letter-spacing:-0.04em;">⊟⊠</div>
|
||||
<h3>Split / Unified views</h3>
|
||||
<p>The patch is rendered by <code style="font-family:var(--mono);font-size:0.8em;background:var(--bg-muted);padding:1px 4px;border-radius:3px;">@pierre/diffs</code> in two modes: Split (side-by-side panels) for detailed prop comparison, and Unified (stacked) for a linear review flow.</p>
|
||||
<span class="tech-tag">Rendering</span>
|
||||
</div>
|
||||
<div class="tech-card">
|
||||
<div class="tech-icon">🗂</div>
|
||||
<h3>Zod schemas for snapshots</h3>
|
||||
<p>Every component snapshot is validated at write time against a shared Zod schema. Type-safe serialization means the diff algorithm always operates on well-formed input — no silent failures or undefined prop shapes.</p>
|
||||
<span class="tech-tag">Type safety</span>
|
||||
</div>
|
||||
<div class="tech-card">
|
||||
<div class="tech-icon">⚙</div>
|
||||
<h3>CI/CD integration</h3>
|
||||
<p>The unified patch is available as a JSON payload on every merge event. Pipe it into GitHub Actions, Linear, or your own webhook to block PRs on token violations or notify designers of overridden changes.</p>
|
||||
<span class="tech-tag">Automation</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- RELATED FEATURES -->
|
||||
<section class="section section-muted">
|
||||
<div class="wrap">
|
||||
<div class="section-head reveal">
|
||||
<span class="label">What connects here</span>
|
||||
<h2 class="d2">Intent Diff sits at the center.</h2>
|
||||
<p class="subtitle">Every artboard edit creates a diff. Every diff is queryable by the graph. Every diff is shippable through the bridge.</p>
|
||||
</div>
|
||||
<div class="related-grid stagger">
|
||||
<a class="related-card" href="/features/live-artboard.html">
|
||||
<div class="related-icon">⬜</div>
|
||||
<h3>Live Artboard</h3>
|
||||
<p>Every prop change made in a Live Artboard is recorded as an Intent Diff entry automatically — edits accumulate into a reviewable, shippable patch without any extra steps from the designer.</p>
|
||||
<span class="related-link">Explore Live Artboard →</span>
|
||||
</a>
|
||||
<a class="related-card" href="/features/origin-graph.html">
|
||||
<div class="related-icon">◉</div>
|
||||
<h3>Origin Graph</h3>
|
||||
<p>Diffs are indexed into the Origin Graph, making it queryable which components changed most frequently, which props are most volatile, and who last touched any given node in the tree.</p>
|
||||
<span class="related-link">Explore Origin Graph →</span>
|
||||
</a>
|
||||
<a class="related-card" href="/features/agent-bridge.html">
|
||||
<div class="related-icon">⇄</div>
|
||||
<h3>Agent Bridge</h3>
|
||||
<p>The Agent Bridge exposes diffs as MCP tool responses. Ask Cursor or Claude Code to apply the accepted diff for any component and the agent writes the prop changes directly into your codebase.</p>
|
||||
<span class="related-link">Explore Agent Bridge →</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- CTA -->
|
||||
<section id="cta-bottom">
|
||||
<div class="cta-inner">
|
||||
<h2 class="cta-headline">No more redline hell.<br>Ship the diff.</h2>
|
||||
<p class="cta-sub">Every design change expressed as a structured, machine-readable, component-level diff. Early access is free.</p>
|
||||
<div class="cta-actions">
|
||||
<a href="#" class="btn btn-white btn-lg">Request Early Access</a>
|
||||
<a href="/" class="btn btn-outline-white btn-lg">Back to overview</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- FOOTER -->
|
||||
<footer>
|
||||
<div class="ft-inner">
|
||||
<div class="ft-top">
|
||||
<div>
|
||||
<div class="ft-brand-logo">Origin<span>main</span></div>
|
||||
<p class="ft-brand-tag">Where design intent becomes production code.</p>
|
||||
</div>
|
||||
<div class="ft-col">
|
||||
<h4>Product</h4>
|
||||
<ul>
|
||||
<li><a href="/features/live-artboard.html">Live Artboard</a></li>
|
||||
<li><a href="/features/origin-graph.html">Origin Graph</a></li>
|
||||
<li><a href="/features/intent-diff.html">Intent Diff</a></li>
|
||||
<li><a href="/features/completion-zone.html">Completion Zone</a></li>
|
||||
<li><a href="/features/agent-bridge.html">Agent Bridge</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="ft-col">
|
||||
<h4>Integrations</h4>
|
||||
<ul>
|
||||
<li><a href="/features/integrations.html">All integrations</a></li>
|
||||
<li><a href="#">GitHub</a></li>
|
||||
<li><a href="#">Linear</a></li>
|
||||
<li><a href="#">Slack</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="ft-col">
|
||||
<h4>Developers</h4>
|
||||
<ul>
|
||||
<li><a href="#">Docs</a></li>
|
||||
<li><a href="#">API Reference</a></li>
|
||||
<li><a href="#">MCP Protocol</a></li>
|
||||
<li><a href="#">Changelog</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="ft-col">
|
||||
<h4>Company</h4>
|
||||
<ul>
|
||||
<li><a href="#">About</a></li>
|
||||
<li><a href="/#pricing">Pricing</a></li>
|
||||
<li><a href="#">Blog</a></li>
|
||||
<li><a href="#">Contact</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ft-bottom">
|
||||
<span class="ft-copy">© 2025 Originmain. All rights reserved.</span>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script>
|
||||
// Nav scroll
|
||||
const nav=document.getElementById('nav');
|
||||
window.addEventListener('scroll',()=>{nav.classList.toggle('scrolled',window.scrollY>20);});
|
||||
// Dropdown: delay-based hover (desktop) + click (mobile/touch)
|
||||
document.querySelectorAll('.nav-dropdown').forEach(dd=>{const menu=dd.querySelector('.nav-dropdown-menu');let t;const open=()=>{clearTimeout(t);dd.classList.add('open');menu.classList.add('open');};const close=()=>{t=setTimeout(()=>{dd.classList.remove('open');menu.classList.remove('open');},150);};dd.addEventListener('mouseenter',open);dd.addEventListener('mouseleave',close);menu.addEventListener('mouseenter',open);menu.addEventListener('mouseleave',close);dd.querySelector('a').addEventListener('click',e=>{if(window.matchMedia('(hover:none)').matches||window.innerWidth<=1024){e.preventDefault();const o=menu.classList.toggle('open');dd.classList.toggle('open',o);}});});
|
||||
// Mobile product sub-accordion
|
||||
const mpt=document.getElementById('mob-product-toggle'),mns=document.getElementById('nav-mobile-sub'),mdc=document.getElementById('mob-dd-caret');if(mpt&&mns){mpt.addEventListener('click',e=>{e.preventDefault();const o=mns.classList.toggle('open');if(mdc)mdc.style.transform=o?'rotate(180deg)':'';});}
|
||||
// Burger
|
||||
const burger=document.getElementById('nav-burger'),mob=document.getElementById('nav-mobile');
|
||||
burger.addEventListener('click',()=>{const o=mob.classList.toggle('open');burger.classList.toggle('open',o);burger.setAttribute('aria-expanded',o);});
|
||||
// Reveal
|
||||
const io=new IntersectionObserver(entries=>{entries.forEach(e=>{if(e.isIntersecting){e.target.classList.add('in');io.unobserve(e.target);}});},{threshold:0.12});
|
||||
document.querySelectorAll('.reveal,.stagger').forEach(el=>io.observe(el));
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user