<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Veritrope — Digital Leadership for Creative Organizations</title>
<link rel="icon" href="favicon.svg" type="image/svg+xml">
<link rel="apple-touch-icon" href="favicon.svg">
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-XMPKPQ2NZP"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());
  gtag('config', 'G-XMPKPQ2NZP');
</script>
<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=Newsreader:ital,opsz,wght@0,6..72,200..800;1,6..72,200..800&family=Plus+Jakarta+Sans:ital,wght@0,200..800;1,200..800&display=swap" rel="stylesheet">
<style>
  *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

  :root {
    /* Emerald scale */
    --vt-emerald-900: #002828;
    --vt-emerald-800: #003c3c;
    --vt-emerald-700: #005050;
    --vt-emerald-600: #006464;
    --vt-emerald-400: #228c8c;
    --vt-emerald-300: #4aadad;
    --vt-emerald-050: #eaf6f6;

    /* Neutral scale */
    --vt-neutral-950: #0a0a0b;
    --vt-neutral-900: #111114;
    --vt-neutral-700: #2a2a30;
    --vt-neutral-600: #3d3d46;
    --vt-neutral-500: #5a5a66;
    --vt-neutral-400: #7c7c8a;
    --vt-neutral-300: #a4a4b2;
    --vt-neutral-200: #c8c8d4;
    --vt-neutral-100: #e4e4ec;
    --vt-neutral-050: #f2f2f7;
    --vt-neutral-000: #ffffff;

    /* Scramble animation colors */
    --scramble-bright: var(--vt-emerald-400);
    --scramble-dim:    var(--vt-emerald-300);
    --scramble-glow:   rgba(34, 140, 140, 0.4);

    /* Typography — canonical stacks */
    --font-display: 'Newsreader', Georgia, 'Times New Roman', serif;
    --font-body:    'Plus Jakarta Sans', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif;
  }

  html { scroll-behavior: smooth; }

  body {
    font-family: var(--font-body);
    background: var(--vt-neutral-050);
    color: var(--vt-neutral-900);
    -webkit-font-smoothing: antialiased;
    overflow-x: hidden;
  }

  /* ── NAV ── */
  header {
    position: fixed;
    top: 0; left: 0; right: 0;
    z-index: 100;
    height: 64px;
    padding: 0 40px;
    display: flex;
    align-items: center;
    background: rgba(255, 255, 255, 0.92);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    border-bottom: 1px solid var(--vt-neutral-100);
  }

  .logo {
    display: flex;
    align-items: center;
    gap: 16px;
    text-decoration: none;
    flex-shrink: 0;
  }

  .logo svg { width: 48px; height: 48px; }

  @keyframes nav-outline-wave {
    0%, 100% { stroke-width: 3.12; stroke: var(--vt-emerald-400); opacity: 0.55; }
    50%       { stroke-width: 5;    stroke: var(--vt-emerald-600); opacity: 1;    }
  }
  @keyframes nav-fill-wave {
    0%, 100% { fill: var(--vt-emerald-400); stroke: var(--vt-emerald-400); opacity: 0.55; }
    50%       { fill: var(--vt-emerald-600); stroke: var(--vt-emerald-600); opacity: 1;    }
  }

  .nmo {
    fill: none;
    stroke-miterlimit: 10;
    animation: nav-outline-wave 4s ease-in-out infinite;
    animation-delay: calc(var(--j) * -0.45s);
  }
  .nmf {
    stroke-miterlimit: 10;
    animation: nav-fill-wave 4s ease-in-out infinite;
    animation-delay: calc(var(--j) * -0.45s);
  }

  .logo-wordmark {
    font-family: var(--font-display);
    font-size: 17px;
    font-weight: 400;
    letter-spacing: 0.02em;
    color: var(--vt-emerald-600);
  }

  /* ── HERO (light) ── */
  .hero {
    background: var(--vt-neutral-050);
    min-height: 88vh;
    padding: 144px 40px 88px;
    display: flex;
    flex-direction: column;
    justify-content: center;
    max-width: 980px;
  }

  .hero-headline-wrap {
    margin-bottom: 36px;
  }

  .hero-prefix {
    font-family: var(--font-display);
    font-size: clamp(36px, 5.5vw, 68px);
    font-weight: 300;
    font-style: italic;
    line-height: 1.1;
    letter-spacing: -0.02em;
    color: var(--vt-neutral-400);
    display: block;
    user-select: none;
  }

  .hero-suffix-row {
    display: block;
    font-family: var(--font-display);
    font-size: clamp(36px, 5.5vw, 68px);
    font-weight: 300;
    line-height: 1.15;
    letter-spacing: -0.02em;
    color: var(--vt-neutral-900);
    white-space: nowrap;
  }

  .hero-cursor {
    display: inline-block;
    width: 3px;
    height: 0.72em;
    background: var(--vt-emerald-400);
    vertical-align: middle;
    margin-left: 3px;
    border-radius: 0;
    opacity: 0;
  }
  .hero-cursor--solid { opacity: 0.65; }
  .hero-cursor--blink {
    opacity: 1;
    animation: cursor-blink 1.1s step-end infinite;
  }

  @keyframes cursor-blink {
    0%, 100% { opacity: 1; }
    50%       { opacity: 0; }
  }

  .sc {
    color: var(--scramble-bright);
    text-shadow: 0 0 8px var(--scramble-glow), 0 0 18px rgba(34, 140, 140, 0.15);
  }
  .sc-dim {
    color: var(--scramble-dim);
    text-shadow: 0 0 5px rgba(74, 173, 173, 0.22);
  }

  .hero-sub {
    font-family: var(--font-body);
    font-size: 17px;
    font-weight: 400;
    line-height: 1.65;
    letter-spacing: -0.005em;
    color: var(--vt-neutral-700);
    max-width: 560px;
    opacity: 0;
    transform: translateY(12px);
    transition: opacity 0.7s 0.1s, transform 0.7s 0.1s;
  }
  .hero-sub.visible { opacity: 1; transform: none; }

  .hero-cta {
    margin-top: 40px;
    display: flex;
    gap: 20px;
    align-items: center;
    opacity: 0;
    transform: translateY(12px);
    transition: opacity 0.7s 0.3s, transform 0.7s 0.3s;
  }
  .hero-cta.visible { opacity: 1; transform: none; }

  .btn-primary {
    display: inline-block;
    padding: 14px 28px;
    background: var(--vt-emerald-600);
    color: var(--vt-neutral-000);
    font-family: var(--font-body);
    font-size: 13px;
    font-weight: 500;
    letter-spacing: 0.04em;
    text-decoration: none;
    border-radius: 0;
    transition: background 0.2s;
  }
  .btn-primary:hover { background: var(--vt-emerald-700); }

  /* ── SHARED ── */
  section { padding: 96px 40px; }

  .fade-in {
    opacity: 0;
    transform: translateY(16px);
    transition: opacity 0.6s, transform 0.6s;
  }
  .fade-in.visible { opacity: 1; transform: none; }

  /* ── ABOUT ── */
  .about-section {
    background: var(--vt-neutral-000);
  }

  .section-label {
    font-family: var(--font-body);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--vt-neutral-500);
    margin-bottom: 48px;
  }

  .about-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 80px;
    align-items: start;
  }

  @media (max-width: 720px) {
    .about-grid { grid-template-columns: 1fr; gap: 40px; }
  }

  .about-headline {
    font-family: var(--font-display);
    font-size: clamp(22px, 3.5vw, 38px);
    font-weight: 300;
    line-height: 1.2;
    letter-spacing: -0.015em;
    color: var(--vt-neutral-900);
  }

  .about-body {
    font-family: var(--font-body);
    font-size: 17px;
    font-weight: 400;
    line-height: 1.65;
    letter-spacing: -0.005em;
    color: var(--vt-neutral-700);
  }
  .about-body + .about-body { margin-top: 20px; }

  /* ── CONTACT CTA (dark with pattern) ── */
  .contact-section {
    position: relative;
    overflow: hidden;
    background: var(--vt-emerald-900);
    padding: 96px 40px;
  }

  .contact-pattern {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
  }

  .contact-content {
    position: relative;
    z-index: 1;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 40px;
    flex-wrap: wrap;
  }

  .contact-headline {
    font-family: var(--font-display);
    font-size: clamp(22px, 3vw, 36px);
    font-weight: 300;
    letter-spacing: -0.015em;
    color: var(--vt-neutral-100);
    line-height: 1.2;
    max-width: 520px;
  }

  .btn-light {
    display: inline-block;
    padding: 16px 32px;
    border: 1px solid rgba(74, 173, 173, 0.4);
    color: var(--vt-emerald-300);
    font-family: var(--font-body);
    font-size: 13px;
    font-weight: 500;
    letter-spacing: 0.04em;
    text-decoration: none;
    border-radius: 0;
    white-space: nowrap;
    transition: background 0.2s, border-color 0.2s;
  }
  .btn-light:hover {
    background: rgba(74, 173, 173, 0.1);
    border-color: var(--vt-emerald-300);
  }

  /* ── RESPONSIVE ── */
  @media (max-width: 680px) {
    header { padding: 0 24px; }
    .hero { padding: 120px 24px 64px; }
    .hero-suffix-row { white-space: normal; min-height: 5em; }
    section { padding: 72px 24px; }
    .contact-section { padding: 72px 24px; }
  }
</style>
</head>
<body>

<!-- ── HEADER ── -->
<header>
  <a href="./" class="logo">
    <svg viewBox="0 0 300 300" xmlns="http://www.w3.org/2000/svg" aria-label="Veritrope mark">
      <polygon class="nmo" style="--j:0" points="4.783,56.311 4.783,3.784 59.071,3.784"/>
      <polygon class="nmo" style="--j:1" points="243.215,56.311 243.215,3.784 297.5,3.784"/>
      <polygon class="nmo" style="--j:2" points="4.783,134.24 4.783,81.713 59.071,81.713"/>
      <polygon class="nmo" style="--j:3" points="172.431,134.24 172.431,81.713 226.718,81.713"/>
      <polygon class="nmo" style="--j:4" points="4.783,218.432 4.783,165.906 59.071,165.906"/>
      <polygon class="nmo" style="--j:5" points="88.875,218.432 88.875,165.906 143.16,165.906"/>
      <polygon class="nmo" style="--j:6" points="4.783,296.449 4.783,243.923 59.071,243.923"/>
      <polygon class="nmf" style="--j:7" points="91.09,117.002 91.09,90.74 118.232,90.74"/>
      <polygon class="nmf" style="--j:8" points="91.09,38.473 91.09,12.21 118.232,12.21"/>
      <polygon class="nmf" style="--j:9" points="168.261,38.473 168.261,12.21 195.403,12.21"/>
    </svg>
    <span class="logo-wordmark">Veritrope</span>
  </a>
</header>

<!-- ── HERO ── -->
<div class="hero">
  <div class="hero-headline-wrap">
    <span class="hero-prefix">Technology strategy</span>
    <div class="hero-suffix-row">
      <span id="hero-suffix"></span><span class="hero-cursor" id="hero-cursor"></span>
    </div>
  </div>
  <p class="hero-sub" id="hero-sub">
    Digital leadership and technology advisory for studios, production companies, creative agencies, and professional service firms. Decades of experience.
  </p>
  <div class="hero-cta" id="hero-cta">
    <a href="https://calendly.com/veritrope/introductory-call" class="btn-primary">Let's talk</a>
  </div>
</div>

<!-- ── ABOUT ── -->
<section id="about" class="about-section">
  <p class="section-label fade-in">About Justin Lancy</p>
  <div class="about-grid">
<div>
      <p class="about-body fade-in">I'm a strategic technology advisor with decades of experience across creative and knowledge-driven industries. I've worked directly with studios, production companies, agencies, law firms, executives, researchers, and individual creators, helping each increase their efficiency and effectiveness through intelligent technology and process design.</p>
      <p class="about-body fade-in">I hold CISSP and CISM certifications and provide vCTO, vCIO, and vCISO services — leading initiatives that harmonize business objectives with technical and security best practices. My workflow projects have been featured by Lifehacker, Evernote, MacStories, SimplicityBliss, and many other Apple and productivity publications.</p>
      <p class="about-body fade-in">Beyond the technical work, I'm a writer and communicator. I've contributed to The Atlantic, New York Magazine, Harper's Bazaar India, AFAR, Travel + Leisure, and other publications, and I've advised organizations on their content, digital marketing, and editorial strategy. That combination — deep technical fluency and the ability to communicate complex ideas clearly to any audience — is what makes this practice work.</p>
    </div>
  </div>
</section>

<!-- ── CONTACT ── -->
<div class="contact-section" id="contact">
  <svg class="contact-pattern" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
    <defs>
      <pattern id="contact-bg-pattern" x="0" y="0" width="120" height="120" patternUnits="userSpaceOnUse">
        <polygon fill="none" stroke="#4aadad" stroke-width="1.25" stroke-miterlimit="10" points="1.91,22.52 1.91,1.51 23.63,1.51"/>
        <polygon fill="none" stroke="#4aadad" stroke-width="1.25" stroke-miterlimit="10" points="97.29,22.52 97.29,1.51 119.0,1.51"/>
        <polygon fill="none" stroke="#4aadad" stroke-width="1.25" stroke-miterlimit="10" points="1.91,53.70 1.91,32.69 23.63,32.69"/>
        <polygon fill="none" stroke="#4aadad" stroke-width="1.25" stroke-miterlimit="10" points="68.97,53.70 68.97,32.69 90.69,32.69"/>
        <polygon fill="none" stroke="#4aadad" stroke-width="1.25" stroke-miterlimit="10" points="1.91,87.37 1.91,66.36 23.63,66.36"/>
        <polygon fill="none" stroke="#4aadad" stroke-width="1.25" stroke-miterlimit="10" points="35.55,87.37 35.55,66.36 57.26,66.36"/>
        <polygon fill="none" stroke="#4aadad" stroke-width="1.25" stroke-miterlimit="10" points="1.91,118.58 1.91,97.57 23.63,97.57"/>
        <polygon fill="#4aadad" stroke="#4aadad" stroke-width="1.25" stroke-miterlimit="10" points="36.44,46.80 36.44,36.30 47.29,36.30"/>
        <polygon fill="#4aadad" stroke="#4aadad" stroke-width="1.25" stroke-miterlimit="10" points="36.44,15.39 36.44,4.88 47.29,4.88"/>
        <polygon fill="#4aadad" stroke="#4aadad" stroke-width="1.25" stroke-miterlimit="10" points="67.30,15.39 67.30,4.88 78.16,4.88"/>
      </pattern>
    </defs>
    <rect width="100%" height="100%" fill="url(#contact-bg-pattern)" opacity="0.05"/>
  </svg>
  <div class="contact-content">
    <h2 class="contact-headline fade-in">Ready to know more?</h2>
    <a href="/cdn-cgi/l/email-protection#dbb3b29badbea9b2afa9b4abbef5b8b4b6" class="btn-light"><span class="__cf_email__" data-cfemail="9bf3f2dbedfee9f2efe9f4ebfeb5f8f4f6">[email&#160;protected]</span></a>
  </div>
</div>

<script data-cfasync="false" src="/cdn-cgi/scripts/5c5dd728/cloudflare-static/email-decode.min.js"></script><script>
// ── TextScramble ─────────────────────────────────────────────────
class TextScramble {
  constructor(el) {
    this.el    = el;
    this.chars = '0123456789ABCDEFabcdef#@$>_\\|/{}[]+=*^~:.';
    this.frameReq = null;
    this.frame    = 0;
    this.queue    = [];
    this.resolve  = null;
    this.update   = this.update.bind(this);
  }

  scramble(newText, speed = 1) {
    const oldText = this.el.innerText;
    const len     = Math.max(oldText.length, newText.length);
    const promise = new Promise(res => this.resolve = res);
    this.queue    = [];
    cancelAnimationFrame(this.frameReq);
    this.frame    = 0;

    for (let i = 0; i < len; i++) {
      const from  = oldText[i]  || '';
      const to    = newText[i]  || '';
      const start = Math.floor((i / len) * 42 / speed);
      const end   = start + Math.floor(Math.random() * 28 / speed) + 16;
      this.queue.push({ from, to, start, end, char: '' });
    }
    this.update();
    return promise;
  }

  update() {
    let out  = '';
    let done = 0;
    for (let i = 0; i < this.queue.length; i++) {
      const q = this.queue[i];
      if (this.frame >= q.end) {
        done++;
        out += q.to;
      } else if (this.frame >= q.start) {
        if (!q.char || Math.random() < 0.18) {
          q.char = this.chars[Math.floor(Math.random() * this.chars.length)];
        }
        const cls = Math.random() < 0.35 ? 'sc-dim' : 'sc';
        out += `<span class="${cls}">${q.char}</span>`;
      } else {
        out += q.from;
      }
    }
    this.el.innerHTML = out;
    if (done === this.queue.length) {
      this.resolve?.();
    } else {
      this.frameReq = requestAnimationFrame(this.update);
      this.frame++;
    }
  }
}

// ── Cycling phrases ───────────────────────────────────────────────
const phrases = [
  'built around how you actually work.',
  'that embraces what makes you distinctive.',
  'that clarifies decisions.',
  'which sees around corners.',
  'designed to compound value.',
];

const suffixEl  = document.getElementById('hero-suffix');
const cursorEl  = document.getElementById('hero-cursor');
const scrambler = new TextScramble(suffixEl);

let phraseIndex = 0;
let subRevealed = false;

function setCursor(state) {
  cursorEl.className = 'hero-cursor' + (state ? ' hero-cursor--' + state : '');
}

function cyclePhrase() {
  setCursor('solid');

  scrambler.scramble(phrases[phraseIndex], 0.55).then(() => {
    if (!subRevealed) {
      subRevealed = true;
      document.getElementById('hero-sub').classList.add('visible');
      document.getElementById('hero-cta').classList.add('visible');
    }

    setCursor('blink');

    setTimeout(() => {
      setCursor('solid');
      phraseIndex = (phraseIndex + 1) % phrases.length;
      setTimeout(cyclePhrase, 270);
    }, 3200);
  });
}

window.addEventListener('load', () => {
  setTimeout(cyclePhrase, 480);
});

// ── Scroll fade-ins ───────────────────────────────────────────────
const io = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (!entry.isIntersecting) return;
    entry.target.classList.add('visible');
    io.unobserve(entry.target);
  });
}, { threshold: 0.15 });

document.querySelectorAll('.fade-in').forEach(el => io.observe(el));
</script>
</body>
</html>
