Preview — /var/www/sites/splice/index.html

/var/www/sites/splice/index.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SpliceVPN — Mesh every endpoint you've got</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=Syne:wght@600;700;800&family=Hanken+Grotesk:wght@400;500;600&family=JetBrains+Mono:wght@400;500;700&display=swap" rel="stylesheet">
<style>
  :root{
    --bg:#0a0d0c;
    --bg-2:#0e1311;
    --panel:#101615;
    --ink:#e9efe9;
    --muted:#869089;
    --faint:#586059;
    --line:rgba(190,255,190,.09);
    --line-2:rgba(190,255,190,.05);
    --signal:#c1f53e;      /* live link */
    --signal-dim:rgba(193,245,62,.14);
    --wire:#54d6c9;        /* secondary path */
    --relay:#ff8a5c;       /* fallback relay */
    --radius:14px;
    --maxw:1180px;
  }

  *{box-sizing:border-box;margin:0;padding:0}
  html{scroll-behavior:smooth}
  body{
    background:var(--bg);
    color:var(--ink);
    font-family:'Hanken Grotesk',sans-serif;
    line-height:1.55;
    -webkit-font-smoothing:antialiased;
    overflow-x:hidden;
  }

  /* ---- atmosphere ---- */
  body::before{
    content:"";position:fixed;inset:0;z-index:0;pointer-events:none;
    background:
      radial-gradient(900px 600px at 78% -5%, rgba(84,214,201,.10), transparent 60%),
      radial-gradient(800px 700px at 12% 8%, rgba(193,245,62,.07), transparent 55%);
  }
  body::after{
    content:"";position:fixed;inset:0;z-index:0;pointer-events:none;opacity:.5;
    background-image:
      linear-gradient(var(--line-2) 1px,transparent 1px),
      linear-gradient(90deg,var(--line-2) 1px,transparent 1px);
    background-size:44px 44px;
    mask-image:radial-gradient(circle at 50% 30%,#000,transparent 85%);
  }
  .grain{
    position:fixed;inset:0;z-index:1;pointer-events:none;opacity:.035;mix-blend-mode:overlay;
    background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='3'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  }

  .wrap{position:relative;z-index:2;max-width:var(--maxw);margin:0 auto;padding:0 28px}

  /* ---- kickers / mono ---- */
  .mono{font-family:'JetBrains Mono',monospace}
  .kicker{
    font-family:'JetBrains Mono',monospace;font-size:12px;letter-spacing:.22em;
    text-transform:uppercase;color:var(--signal);display:inline-flex;align-items:center;gap:9px;
  }
  .kicker::before{content:"";width:22px;height:1px;background:var(--signal);display:inline-block}

  /* ---- nav ---- */
  nav{
    position:relative;z-index:3;display:flex;align-items:center;justify-content:space-between;
    max-width:var(--maxw);margin:0 auto;padding:26px 28px;
  }
  .brand{display:flex;align-items:center;gap:11px;font-family:'Syne',sans-serif;font-weight:800;font-size:20px;letter-spacing:-.01em}
  .brand .dot{width:11px;height:11px;border-radius:50%;background:var(--signal);box-shadow:0 0 0 4px var(--signal-dim);animation:pulse 2.6s infinite}
  @keyframes pulse{0%,100%{box-shadow:0 0 0 3px var(--signal-dim)}50%{box-shadow:0 0 0 7px rgba(193,245,62,.05)}}
  .navlinks{display:flex;gap:30px;font-family:'JetBrains Mono',monospace;font-size:13px;color:var(--muted)}
  .navlinks a{color:var(--muted);text-decoration:none;transition:color .2s}
  .navlinks a:hover{color:var(--ink)}
  .navbtn{
    font-family:'JetBrains Mono',monospace;font-size:13px;color:var(--bg);background:var(--signal);
    padding:9px 16px;border-radius:8px;text-decoration:none;font-weight:700;transition:transform .15s,box-shadow .2s;
  }
  .navbtn:hover{transform:translateY(-1px);box-shadow:0 6px 22px rgba(193,245,62,.25)}
  @media(max-width:760px){.navlinks{display:none}}

  /* ---- hero ---- */
  header{position:relative;padding:48px 0 80px}
  .hero-grid{display:grid;grid-template-columns:1.05fr .95fr;gap:50px;align-items:center}
  @media(max-width:920px){.hero-grid{grid-template-columns:1fr;gap:34px}}

  h1{
    font-family:'Syne',sans-serif;font-weight:800;letter-spacing:-.025em;line-height:.98;
    font-size:clamp(44px,6.6vw,82px);margin:22px 0 0;
  }
  h1 .lit{color:var(--signal)}
  .lede{font-size:clamp(17px,2vw,20px);color:var(--muted);max-width:46ch;margin-top:24px}
  .cta-row{display:flex;gap:14px;margin-top:34px;flex-wrap:wrap}
  .btn-primary{
    font-family:'JetBrains Mono',monospace;font-weight:700;font-size:14px;color:var(--bg);background:var(--signal);
    padding:14px 24px;border-radius:10px;text-decoration:none;display:inline-flex;align-items:center;gap:10px;
    transition:transform .15s,box-shadow .2s;
  }
  .btn-primary:hover{transform:translateY(-2px);box-shadow:0 10px 30px rgba(193,245,62,.28)}
  .btn-ghost{
    font-family:'JetBrains Mono',monospace;font-weight:500;font-size:14px;color:var(--ink);
    padding:14px 22px;border-radius:10px;text-decoration:none;border:1px solid var(--line);transition:border-color .2s,background .2s;
  }
  .btn-ghost:hover{border-color:rgba(193,245,62,.4);background:rgba(193,245,62,.04)}

  /* hero stage / diagram */
  .stage{
    position:relative;border:1px solid var(--line);border-radius:var(--radius);
    background:linear-gradient(160deg,rgba(20,28,26,.7),rgba(10,14,13,.4));
    padding:18px;overflow:hidden;backdrop-filter:blur(2px);
  }
  .stage-bar{display:flex;align-items:center;justify-content:space-between;font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--faint);margin-bottom:10px;padding:0 4px}
  .stage-bar .live{color:var(--signal)}
  .stage svg{width:100%;height:auto;display:block}

  /* ---- section scaffolding ---- */
  section{position:relative;padding:74px 0;border-top:1px solid var(--line-2)}
  .sec-head{max-width:62ch}
  .sec-head h2{font-family:'Syne',sans-serif;font-weight:700;font-size:clamp(28px,3.6vw,42px);letter-spacing:-.02em;line-height:1.05;margin-top:16px}
  .sec-head p{color:var(--muted);margin-top:16px;font-size:17px}

  /* ---- capability grid ---- */
  .grid{display:grid;grid-template-columns:repeat(3,1fr);gap:18px;margin-top:46px}
  @media(max-width:900px){.grid{grid-template-columns:1fr 1fr}}
  @media(max-width:600px){.grid{grid-template-columns:1fr}}
  .card{
    position:relative;border:1px solid var(--line);border-radius:var(--radius);padding:26px 24px;
    background:rgba(16,22,21,.55);transition:transform .25s,border-color .25s,background .25s;overflow:hidden;
  }
  .card::after{content:"";position:absolute;inset:0;background:radial-gradient(400px 200px at var(--mx,50%) var(--my,0%),rgba(193,245,62,.07),transparent 70%);opacity:0;transition:opacity .3s;pointer-events:none}
  .card:hover{transform:translateY(-4px);border-color:rgba(193,245,62,.32);background:rgba(20,28,26,.7)}
  .card:hover::after{opacity:1}
  .card .num{font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--signal);letter-spacing:.1em}
  .card .ico{width:40px;height:40px;margin:16px 0 14px;color:var(--signal)}
  .card h3{font-family:'Syne',sans-serif;font-weight:700;font-size:20px;letter-spacing:-.01em}
  .card p{color:var(--muted);font-size:15px;margin-top:9px}

  /* ---- path-finding ladder ---- */
  .ladder{display:grid;grid-template-columns:repeat(3,1fr);gap:18px;margin-top:46px}
  @media(max-width:820px){.ladder{grid-template-columns:1fr}}
  .tier{
    position:relative;border:1px solid var(--line);border-radius:var(--radius);padding:26px;
    background:rgba(16,22,21,.5);
  }
  .tier .tg{font-family:'JetBrains Mono',monospace;font-size:11px;letter-spacing:.2em;text-transform:uppercase}
  .tier h4{font-family:'Syne',sans-serif;font-weight:700;font-size:22px;margin:14px 0 8px;letter-spacing:-.01em}
  .tier p{color:var(--muted);font-size:15px}
  .tier .barline{height:4px;border-radius:3px;margin-top:20px;background:var(--line)}
  .t1 .tg{color:var(--signal)} .t1 .barline{background:linear-gradient(90deg,var(--signal),transparent)}
  .t2 .tg{color:var(--wire)}   .t2 .barline{background:linear-gradient(90deg,var(--wire),transparent)}
  .t3 .tg{color:var(--relay)}  .t3 .barline{background:linear-gradient(90deg,var(--relay),transparent)}
  .t3{border-color:rgba(255,138,92,.22)}
  .tier .meta{font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--faint);margin-top:14px}

  /* ---- bonding split ---- */
  .split{display:grid;grid-template-columns:1fr 1fr;gap:48px;align-items:center;margin-top:10px}
  @media(max-width:860px){.split{grid-template-columns:1fr;gap:30px}}
  .bond-list{list-style:none;margin-top:26px}
  .bond-list li{display:flex;gap:14px;padding:15px 0;border-bottom:1px solid var(--line-2);align-items:flex-start}
  .bond-list li:last-child{border-bottom:0}
  .bond-list .tick{flex:none;width:22px;height:22px;border-radius:50%;border:1px solid var(--signal);color:var(--signal);display:grid;place-items:center;font-size:12px;margin-top:2px}
  .bond-list b{font-family:'Syne',sans-serif;font-weight:600;display:block;font-size:16px}
  .bond-list span{color:var(--muted);font-size:14px}
  .bond-visual{border:1px solid var(--line);border-radius:var(--radius);background:rgba(16,22,21,.5);padding:16px}
  .bond-visual svg{width:100%;height:auto;display:block}

  /* ---- setup steps ---- */
  .steps{display:grid;grid-template-columns:repeat(3,1fr);gap:0;margin-top:46px;border:1px solid var(--line);border-radius:var(--radius);overflow:hidden}
  @media(max-width:760px){.steps{grid-template-columns:1fr}}
  .step{padding:30px 26px;border-right:1px solid var(--line);background:rgba(16,22,21,.4)}
  .step:last-child{border-right:0}
  @media(max-width:760px){.step{border-right:0;border-bottom:1px solid var(--line)}.step:last-child{border-bottom:0}}
  .step .q{font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--signal);letter-spacing:.12em}
  .step h4{font-family:'Syne',sans-serif;font-weight:700;font-size:19px;margin:14px 0 8px}
  .step p{color:var(--muted);font-size:14px}
  .step .opts{display:flex;gap:8px;flex-wrap:wrap;margin-top:16px}
  .step .opts span{font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--muted);border:1px solid var(--line);border-radius:6px;padding:5px 10px}
  .terminal{
    margin-top:30px;border:1px solid var(--line);border-radius:var(--radius);overflow:hidden;
    font-family:'JetBrains Mono',monospace;font-size:13.5px;background:#0c100f;
  }
  .terminal .tt{display:flex;gap:7px;padding:11px 15px;border-bottom:1px solid var(--line);align-items:center}
  .terminal .tt i{width:11px;height:11px;border-radius:50%;display:block}
  .terminal .tt i:nth-child(1){background:#ff5f56}.terminal .tt i:nth-child(2){background:#ffbd2e}.terminal .tt i:nth-child(3){background:#27c93f}
  .terminal .tt span{color:var(--faint);margin-left:8px;font-size:12px}
  .terminal .body{padding:20px;line-height:1.85}
  .terminal .body .c{color:var(--faint)}
  .terminal .body .ok{color:var(--signal)}
  .terminal .body .w{color:var(--wire)}
  .terminal .body .r{color:var(--relay)}
  .terminal .body .prompt{color:var(--ink)}
  .terminal .body .cursor{display:inline-block;width:9px;height:16px;background:var(--signal);vertical-align:-3px;animation:blink 1.1s steps(2) infinite}
  @keyframes blink{50%{opacity:0}}

  /* ---- closing cta ---- */
  .closer{text-align:center;padding:96px 0}
  .closer h2{font-family:'Syne',sans-serif;font-weight:800;font-size:clamp(32px,5vw,60px);letter-spacing:-.025em;line-height:1.02}
  .closer p{color:var(--muted);margin:20px auto 0;max-width:50ch;font-size:18px}

  footer{border-top:1px solid var(--line-2);padding:34px 0}
  .foot{display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:16px;font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--faint)}

  /* ---- reveal ---- */
  .reveal{opacity:0;transform:translateY(24px);transition:opacity .7s cubic-bezier(.2,.7,.2,1),transform .7s cubic-bezier(.2,.7,.2,1)}
  .reveal.in{opacity:1;transform:none}
  .d1{transition-delay:.08s}.d2{transition-delay:.16s}.d3{transition-delay:.24s}.d4{transition-delay:.32s}.d5{transition-delay:.4s}.d6{transition-delay:.48s}

  /* animated dashes */
  .flow{stroke-dasharray:6 9;animation:dash 1.3s linear infinite}
  @keyframes dash{to{stroke-dashoffset:-30}}
  .flow-slow{stroke-dasharray:5 12;animation:dash 2.4s linear infinite}
  .lit-link{color:var(--signal);text-decoration:none;border-bottom:1px solid rgba(193,245,62,.4)}
  </style>
</head>
<body>
<!-- SPLICEVPN-MVP-NOTICE-START -->
<div style="margin:1rem 0;padding:.85rem 1rem;border:1px solid #bae6fd;background:#f0f9ff;border-radius:10px;color:#0c4a6e">
  <strong>Current MVP architecture:</strong>
  SpliceVPN currently uses your own WireGuard hub relay. Direct peer-to-peer traversal and hole-punching are planned for a later build.
</div>
<!-- SPLICEVPN-MVP-NOTICE-END -->

<div class="grain"></div>

<nav>
  <div class="brand"><span class="dot"></span>SPLICEVPN</div>
  <div class="navlinks">
    <a href="#how">How it works</a>
    <a href="#paths">Connection</a>
    <a href="#bond">Bonding</a>
    <a href="#setup">Setup</a>
  </div>
  <a href="#getstarted" class="navbtn">Get started</a>
</nav>

<header>
  <div class="wrap hero-grid">
    <div>
      <span class="kicker reveal in">Peer-to-peer mesh · multi-link · zero-config</span>
      <h1 class="reveal in d1">Link all your points.<br><span class="lit">Use every connection</span> you've got.</h1>
      <p class="lede reveal in d2">SpliceVPN builds an encrypted mesh across all your endpoints — each one a single machine or a whole network — then bonds every internet link at each node for more bandwidth, more resilience, or both. It finds a path between any two nodes on its own, and when there's no other way, it falls back to a relay we run for you.</p>
      <div class="cta-row reveal in d3">
        <a href="#getstarted" class="btn-primary">Build your mesh →</a>
        <a href="#how" class="btn-ghost">See how it works</a>
      </div>
    </div>

    <div class="stage reveal in d4">
      <div class="stage-bar"><span>mesh://a ⇄ b ⇄ c ⇄ d ⇄ e</span><span class="live">● MESH · 5 NODES</span></div>
      <!-- HERO DIAGRAM: many endpoints in a full mesh, relay on standby -->
      <svg viewBox="0 0 520 330" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Many endpoints connected in a full mesh, with a relay node on standby">
        <defs>
          <linearGradient id="gsig" x1="0" x2="1"><stop offset="0" stop-color="#c1f53e"/><stop offset="1" stop-color="#54d6c9"/></linearGradient>
        </defs>

        <!-- relay (standby) -->
        <g opacity=".5">
          <rect x="232" y="20" width="56" height="32" rx="9" fill="#13100e" stroke="#ff8a5c" stroke-width="1.2"/>
          <text x="260" y="40" text-anchor="middle" fill="#ff8a5c" font-family="JetBrains Mono,monospace" font-size="10">RELAY</text>
          <path d="M252 52 C 210 84, 180 112, 166 150" fill="none" stroke="#ff8a5c" stroke-width="1.1" stroke-dasharray="4 7" opacity=".7"/>
          <path d="M268 52 C 312 84, 344 114, 358 150" fill="none" stroke="#ff8a5c" stroke-width="1.1" stroke-dasharray="4 7" opacity=".7"/>
        </g>

        <!-- mesh links (every pair) -->
        <g stroke="#33433d" stroke-width="1.2">
          <line x1="260" y1="96" x2="360" y2="163"/>
          <line x1="260" y1="96" x2="322" y2="280"/>
          <line x1="260" y1="96" x2="198" y2="280"/>
          <line x1="260" y1="96" x2="160" y2="163"/>
          <line x1="360" y1="163" x2="322" y2="280"/>
          <line x1="360" y1="163" x2="198" y2="280"/>
          <line x1="360" y1="163" x2="160" y2="163"/>
          <line x1="322" y1="280" x2="198" y2="280"/>
          <line x1="322" y1="280" x2="160" y2="163"/>
          <line x1="198" y1="280" x2="160" y2="163"/>
        </g>

        <!-- live traffic on several links -->
        <g stroke="url(#gsig)" stroke-width="2.2" fill="none">
          <line x1="260" y1="96" x2="360" y2="163" class="flow"/>
          <line x1="160" y1="163" x2="260" y2="96" class="flow" style="animation-delay:.3s"/>
          <line x1="360" y1="163" x2="322" y2="280" class="flow" style="animation-delay:.6s"/>
          <line x1="198" y1="280" x2="322" y2="280" class="flow" style="animation-delay:.15s"/>
          <line x1="160" y1="163" x2="198" y2="280" class="flow" style="animation-delay:.5s"/>
        </g>

        <!-- nodes (hosts + networks) -->
        <g>
          <rect x="235" y="79" width="50" height="34" rx="9" fill="#10211d" stroke="#c1f53e" stroke-width="1.4"/>
          <rect x="248" y="89" width="24" height="14" rx="2" fill="none" stroke="#c1f53e" stroke-width="1.2"/>
        </g>
        <g>
          <rect x="335" y="146" width="50" height="34" rx="9" fill="#0e211f" stroke="#54d6c9" stroke-width="1.4"/>
          <circle cx="352" cy="163" r="4.2" fill="none" stroke="#54d6c9" stroke-width="1.2"/>
          <circle cx="368" cy="157" r="4.2" fill="none" stroke="#54d6c9" stroke-width="1.2"/>
          <circle cx="369" cy="170" r="4.2" fill="none" stroke="#54d6c9" stroke-width="1.2"/>
        </g>
        <g>
          <rect x="297" y="263" width="50" height="34" rx="9" fill="#10211d" stroke="#c1f53e" stroke-width="1.4"/>
          <rect x="310" y="273" width="24" height="14" rx="2" fill="none" stroke="#c1f53e" stroke-width="1.2"/>
        </g>
        <g>
          <rect x="173" y="263" width="50" height="34" rx="9" fill="#0e211f" stroke="#54d6c9" stroke-width="1.4"/>
          <circle cx="190" cy="280" r="4.2" fill="none" stroke="#54d6c9" stroke-width="1.2"/>
          <circle cx="206" cy="274" r="4.2" fill="none" stroke="#54d6c9" stroke-width="1.2"/>
          <circle cx="207" cy="287" r="4.2" fill="none" stroke="#54d6c9" stroke-width="1.2"/>
        </g>
        <g>
          <rect x="135" y="146" width="50" height="34" rx="9" fill="#10211d" stroke="#c1f53e" stroke-width="1.4"/>
          <rect x="148" y="156" width="24" height="14" rx="2" fill="none" stroke="#c1f53e" stroke-width="1.2"/>
        </g>

        <text x="260" y="322" text-anchor="middle" fill="#869089" font-family="JetBrains Mono,monospace" font-size="10">every node ⇄ every node · direct, bonded, relay-backed</text>
      </svg>
    </div>
  </div>
</header>

<!-- ============ CAPABILITIES ============ -->
<section id="how">
  <div class="wrap">
    <div class="sec-head reveal">
      <span class="kicker">What it does</span>
      <h2>Six things, one mesh.</h2>
      <p>Everything below happens automatically once the mesh is up. You don't configure routes, exchange keys by hand, or touch a firewall rule.</p>
    </div>

    <div class="grid">
      <div class="card reveal d1">
        <div class="num">01</div>
        <svg class="ico" viewBox="0 0 40 40" fill="none" stroke="currentColor" stroke-width="2"><circle cx="20" cy="9" r="4"/><circle cx="9" cy="30" r="4"/><circle cx="31" cy="30" r="4"/><line x1="18" y1="13" x2="11" y2="26"/><line x1="22" y1="13" x2="29" y2="26"/><line x1="13" y1="30" x2="27" y2="30"/></svg>
        <h3>Full mesh</h3>
        <p>The current MVP creates a controlled hub-relayed WireGuard overlay between endpoints. A lightweight coordinator helps nodes find each other; traffic is relayed through your own SpliceVPN hub in the current MVP.</p>
      </div>
      <div class="card reveal d2">
        <div class="num">02</div>
        <svg class="ico" viewBox="0 0 40 40" fill="none" stroke="currentColor" stroke-width="2"><rect x="5" y="14" width="12" height="12" rx="2"/><circle cx="29" cy="13" r="3.5"/><circle cx="35" cy="24" r="3.5"/><circle cx="25" cy="27" r="3.5"/><line x1="29" y1="16.5" x2="27" y2="24"/><line x1="32" y1="14.5" x2="33" y2="21"/></svg>
        <h3>A host or a whole network</h3>
        <p>Each node can be a single computer or an entire site. Bridge offices, attach a laptop to a LAN, or join networks that were never meant to meet.</p>
      </div>
      <div class="card reveal d3">
        <div class="num">03</div>
        <svg class="ico" viewBox="0 0 40 40" fill="none" stroke="currentColor" stroke-width="2"><path d="M6 12h10c4 0 6 4 12 4"/><path d="M6 20h10c4 0 6-4 12-4"/><path d="M6 28h10c4 0 6 4 12 4"/><circle cx="30" cy="16" r="3.5"/></svg>
        <h3>Bond your links</h3>
        <p>Where you have more than one internet connection, SpliceVPN combines them — for aggregate bandwidth, automatic failover, or both at once.</p>
      </div>
      <div class="card reveal d4">
        <div class="num">04</div>
        <svg class="ico" viewBox="0 0 40 40" fill="none" stroke="currentColor" stroke-width="2"><path d="M6 28 L16 28 L20 12 L28 28 L34 28"/><circle cx="6" cy="28" r="2.5"/><circle cx="34" cy="28" r="2.5"/></svg>
        <h3>Always finds a path</h3>
        <p>The current MVP uses your own SpliceVPN hub relay so nodes can communicate without opening inbound client firewall rules. Direct traversal and hole-punching are planned for a later build.</p>
      </div>
      <div class="card reveal d5">
        <div class="num">05</div>
        <svg class="ico" viewBox="0 0 40 40" fill="none" stroke="currentColor" stroke-width="2"><rect x="6" y="10" width="6" height="20" rx="1"/><rect x="17" y="10" width="6" height="20" rx="1"/><rect x="28" y="10" width="6" height="20" rx="1"/></svg>
        <h3>Any port, any protocol</h3>
        <p>UDP, TCP, or both, across one port or many. SpliceVPN adapts to whatever the network in the middle is willing to let through.</p>
      </div>
      <div class="card reveal d6">
        <div class="num">06</div>
        <svg class="ico" viewBox="0 0 40 40" fill="none" stroke="currentColor" stroke-width="2"><circle cx="20" cy="20" r="12"/><path d="M20 14v6l4 3"/></svg>
        <h3>Done for you</h3>
        <p>Run the software, answer a few questions about what you want, and the rest is handled — discovery, keys, routing, failover, all of it.</p>
      </div>
    </div>
  </div>
</section>

<!-- ============ CONNECTION LADDER ============ -->
<section id="paths">
  <div class="wrap">
    <div class="sec-head reveal">
      <span class="kicker">Point 04 · how a path is found</span>
      <h2>It tries the best route, then the next, then ours.</h2>
      <p>SpliceVPN works out connectivity for you, between every pair of nodes, wherever they happen to be. It climbs down a ladder until something connects — and the bottom rung is a relay you don't have to find or maintain, because we provide it.</p>
    </div>

    <div class="ladder">
      <div class="tier t1 reveal d1">
        <div class="tg">Tier 1</div>
        <h4>Direct</h4>
        <p>If a reachable path exists between two nodes, SpliceVPN uses it. Lowest latency, no middlemen, full bandwidth.</p>
        <div class="meta">latency: lowest · hops: 0</div>
        <div class="barline"></div>
      </div>
      <div class="tier t2 reveal d2">
        <div class="tg">Tier 2</div>
        <h4>Traversal</h4>
        <p>Behind NAT or a strict firewall, SpliceVPN negotiates a path through — hole-punching and multiplexing over whatever ports are open.</p>
        <div class="meta">latency: near-direct · hops: 0</div>
        <div class="barline"></div>
      </div>
      <div class="tier t3 reveal d3">
        <div class="tg">Tier 3 · last resort</div>
        <h4>Relay</h4>
        <p>Current MVP traffic routes through your own SpliceVPN hub relay. Direct and traversal modes are planned for a later build.</p>
        <div class="meta">supplied &amp; maintained by us · always available</div>
        <div class="barline"></div>
      </div>
    </div>
  </div>
</section>

<!-- ============ BONDING ============ -->
<section id="bond">
  <div class="wrap">
    <div class="split">
      <div class="reveal">
        <span class="kicker">Point 03 · link bonding</span>
        <h2 style="font-family:Syne;font-weight:700;font-size:clamp(28px,3.6vw,42px);letter-spacing:-.02em;line-height:1.05;margin-top:16px">More links in, one fat pipe out.</h2>
        <ul class="bond-list">
          <li><span class="tick">↑</span><div><b>More bandwidth</b><span>Aggregate two or more connections so a single transfer can use the combined capacity of all of them.</span></div></li>
          <li><span class="tick">⟲</span><div><b>More resilience</b><span>If one link drops, traffic keeps flowing over the others — no reconnect, no dropped session.</span></div></li>
          <li><span class="tick">⊕</span><div><b>Or both</b><span>Run hot-hot for raw throughput, or keep a link in reserve for failover. You pick at setup; SpliceVPN does the balancing.</span></div></li>
        </ul>
      </div>
      <div class="bond-visual reveal d2">
        <svg viewBox="0 0 460 280" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Two separate internet links merging into one bonded tunnel">
          <!-- left: three links -->
          <text x="14" y="40" fill="#869089" font-family="JetBrains Mono,monospace" font-size="11">fibre</text>
          <text x="14" y="146" fill="#869089" font-family="JetBrains Mono,monospace" font-size="11">5g</text>
          <text x="14" y="252" fill="#869089" font-family="JetBrains Mono,monospace" font-size="11">dsl</text>
          <circle cx="60" cy="34" r="6" fill="#10211d" stroke="#c1f53e" stroke-width="1.5"/>
          <circle cx="60" cy="140" r="6" fill="#10211d" stroke="#54d6c9" stroke-width="1.5"/>
          <circle cx="60" cy="246" r="6" fill="#10211d" stroke="#ff8a5c" stroke-width="1.5"/>
          <!-- merge curves -->
          <path d="M66 34 C 180 34, 200 140, 300 140" fill="none" stroke="#c1f53e" stroke-width="2.2" class="flow-slow"/>
          <path d="M66 140 C 180 140, 200 140, 300 140" fill="none" stroke="#54d6c9" stroke-width="2.2" class="flow-slow" style="animation-delay:.5s"/>
          <path d="M66 246 C 180 246, 200 140, 300 140" fill="none" stroke="#ff8a5c" stroke-width="2.2" class="flow-slow" style="animation-delay:1s"/>
          <!-- bonded out -->
          <path d="M300 140 L 408 140" fill="none" stroke="#c1f53e" stroke-width="6" stroke-linecap="round" class="flow"/>
          <circle cx="300" cy="140" r="10" fill="#0a0d0c" stroke="#c1f53e" stroke-width="2"/>
          <text x="408" y="124" text-anchor="end" fill="#c1f53e" font-family="JetBrains Mono,monospace" font-size="11">bonded tunnel</text>
        </svg>
      </div>
    </div>
  </div>
</section>

<!-- ============ SETUP ============ -->
<section id="setup">
  <div class="wrap">
    <div class="sec-head reveal">
      <span class="kicker">Point 06 · setup</span>
      <h2>Run it. Answer a few questions. You're connected.</h2>
      <p>No manual key exchange, no routing tables, no firewall archaeology. SpliceVPN asks what matters and works out the rest.</p>
    </div>

    <div class="steps">
      <div class="step reveal d1">
        <div class="q">Q1</div>
        <h4>What's at each node?</h4>
        <p>A single machine or a whole network — add as many nodes as you like.</p>
        <div class="opts"><span>this host</span><span>remote host</span><span>network / site</span></div>
      </div>
      <div class="step reveal d2">
        <div class="q">Q2</div>
        <h4>Optimise for what?</h4>
        <p>More speed, more reliability, or a balance of the two across your links.</p>
        <div class="opts"><span>speed</span><span>resilience</span><span>both</span></div>
      </div>
      <div class="step reveal d3">
        <div class="q">Q3</div>
        <h4>Any limits to respect?</h4>
        <p>Specific ports or protocols only? Otherwise SpliceVPN uses whatever works.</p>
        <div class="opts"><span>auto</span><span>udp</span><span>tcp</span><span>pick ports</span></div>
      </div>
    </div>

    <div class="terminal reveal d2">
      <div class="tt"><i></i><i></i><i></i><span>splicevpn up</span></div>
      <div class="body mono">
        <div><span class="prompt">$ splicevpn up</span></div>
        <div><span class="c"># probing links at this node …</span> <span class="ok">2 found (fibre, 5g)</span></div>
        <div><span class="c"># discovering peers …</span> <span class="ok">4 nodes</span></div>
        <div><span class="c">  tier 1 direct …</span> <span class="r">blocked</span></div>
        <div><span class="c">  tier 2 traversal …</span> <span class="ok">open (udp/41641, tcp/443)</span></div>
        <div><span class="c"># bonding 2 links · mode = both</span></div>
        <div><span class="ok">✓ mesh up</span> <span class="w">· 5 nodes · 2 links bonded</span></div>
        <div><span class="prompt">$</span> <span class="cursor"></span></div>
      </div>
    </div>
  </div>
</section>

<!-- ============ GET STARTED / HOW TO ============ -->
<section id="getstarted">
  <div class="wrap">
    <div class="sec-head reveal">
      <span class="kicker">How to</span>
      <h2>Get connected in three steps.</h2>
      <p>No manual keys, no config files. On Windows it's a single click — the installer sets up WireGuard and the agent for you.</p>
    </div>
    <div class="grid">
      <div class="card reveal d1">
        <div class="num">01</div>
        <h3>Install</h3>
        <p><b>Windows</b> — download the one-click installer and run it. It installs WireGuard and the SpliceVPN agent for you; just approve the admin prompt.</p>
        <div class="cta-row" style="margin-top:16px">
          <a href="/Install-SpliceVPN.bat" class="btn-primary">One-click Windows installer →</a>
        </div>
        <p style="margin-top:14px"><b>Linux</b> — <a href="/splicevpn.tar.gz" class="lit-link">download the build</a>, then <code style="font-family:'JetBrains Mono',monospace;font-size:12px;background:rgba(255,255,255,.05);padding:2px 6px;border-radius:5px">tar xzf splicevpn.tar.gz &amp;&amp; sudo ./splicevpn/bin/splice-agent</code></p>
      </div>
      <div class="card reveal d2">
        <div class="num">02</div>
        <h3>Enter your join details</h3>
        <p>Paste the <b>join key</b> and <b>coordinator address</b> your administrator gives you. That's the only input the agent needs — no key exchange, no routing tables.</p>
      </div>
      <div class="card reveal d3">
        <div class="num">03</div>
        <h3>You're on the mesh</h3>
        <p>The agent discovers every other node, brings up the encrypted tunnel, and keeps it connected — automatically, even after a reboot. Nothing else to configure.</p>
      </div>
    </div>
  </div>
</section>

<!-- ============ CLOSER ============ -->
<section class="closer">
  <div class="wrap">
    <span class="kicker reveal" style="justify-content:center">Ready when you are</span>
    <h2 class="reveal d1">Every endpoint.<br>Every link between them.</h2>
    <p class="reveal d2">Install SpliceVPN on each node, answer three questions, and let it find the way. We'll be the safety net.</p>
    <div class="cta-row reveal d3" style="justify-content:center;margin-top:34px">
      <a href="/splicevpn.tar.gz" class="btn-primary">Download for Linux →</a>
        <a href="/splicevpn-windows-amd64.zip" class="btn-primary">Download for Windows →</a>
      <a href="/help.html" class="btn-ghost">Read the docs</a>
    </div>
    <p class="reveal d3" style="margin-top:24px;font:13px/1.6 'JetBrains Mono',ui-monospace,monospace;color:#8b9096">or one-line install on Windows — PowerShell as Administrator (installs WireGuard for you):</p>
    <code class="reveal d3" style="display:block;max-width:720px;margin:10px auto 0;padding:13px 16px;text-align:left;background:rgba(255,255,255,.04);border:1px solid rgba(255,255,255,.12);border-radius:10px;font:12px/1.55 'JetBrains Mono',ui-monospace,monospace;color:#e8ffd0;overflow-x:auto;white-space:pre-wrap;word-break:break-all">iwr https://splicevpn.com.au/install-splicevpn.ps1 -OutFile $env:TEMP\splice.ps1; Start-Process powershell "-ExecutionPolicy Bypass -File $env:TEMP\splice.ps1" -Verb RunAs</code>
  </div>
</section>

<footer>
  <div class="wrap foot">
    <span>SPLICEVPN — peer-to-peer bonded mesh - splicevpn.com.au</span>
    <span>relay supplied · zero-config · any-port</span>
  </div>
</footer>

<script>
  // scroll reveal
  const io = new IntersectionObserver((entries)=>{
    entries.forEach(e=>{ if(e.isIntersecting){ e.target.classList.add('in'); io.unobserve(e.target);} });
  },{threshold:.14});
  document.querySelectorAll('.reveal:not(.in)').forEach(el=>io.observe(el));

  // card spotlight follows cursor
  document.querySelectorAll('.card').forEach(card=>{
    card.addEventListener('pointermove',e=>{
      const r=card.getBoundingClientRect();
      card.style.setProperty('--mx',((e.clientX-r.left)/r.width*100)+'%');
      card.style.setProperty('--my',((e.clientY-r.top)/r.height*100)+'%');
    });
  });
</script>
</body>
</html>