<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Mike Greenberg</title>
  <link rel="icon" href="images/favicon.svg" type="image/svg+xml">
  <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=Jost:wght@600;700&family=Cormorant+Garamond:ital,wght@0,300;0,400;1,300;1,400&display=swap" rel="stylesheet">
  <link rel="stylesheet" href="styles.css">
</head>
<body>
  <div class="ascii" aria-hidden="true"></div>
  <div class="glow" aria-hidden="true"></div>
  <button class="shuffle" aria-label="Regenerate pattern" title="Regenerate pattern"></button>
  <main>
    <div class="left">
      <h1>Mike<br>Greenberg</h1>
      <p class="role">UX Research Leader</p>
      <nav>
        <a href="https://linkedin.com/in/gbrg" target="_blank" rel="noopener">LinkedIn</a>
      </nav>
    </div>
    <div class="right">
      <p class="section-label">Selected Projects</p>
      <ul class="work">
        <li>
          <a href="https://www.meta.com/quest/" target="_blank" rel="noopener"
             data-color="196, 135, 106" data-accent="#c4876a">
            <span class="label">Virtual & Mixed Reality</span>
            <span class="context">Shaping the operating system experience for Meta Quest<span class="meta">Meta · 2023–2025</span></span>
          </a>
        </li>
        <li>
          <a href="https://about.meta.com/realitylabs/" target="_blank" rel="noopener"
             data-color="138, 171, 124" data-accent="#8aab7c">
            <span class="label">AI Wearables</span>
            <span class="context">Building the research practice for a new category of devices<span class="meta">Meta · 2020–2023</span></span>
          </a>
        </li>
        <li>
          <a href="https://about.facebook.com/" target="_blank" rel="noopener"
             data-color="196, 165, 90" data-accent="#c4a55a">
            <span class="label">Local & Discovery</span>
            <span class="context">Reimagining how people find places and connect locally<span class="meta">Facebook · 2018–2020</span></span>
          </a>
        </li>
        <li>
          <a href="https://www.facebook.com/business" target="_blank" rel="noopener"
             data-color="138, 158, 181" data-accent="#8a9eb5">
            <span class="label">Small Business Tools</span>
            <span class="context">Defining how millions of businesses present themselves online<span class="meta">Facebook · 2016–2018</span></span>
          </a>
        </li>
        <li>
          <a href="https://solarsystem.nasa.gov/stardust/home/index.html" target="_blank" rel="noopener"
             data-color="181, 131, 138" data-accent="#b5838a">
            <span class="label">NASA Stardust</span>
            <span class="context">Analyzing cometary samples returned from deep space<span class="meta">American Museum of Natural History · 2008–2011</span></span>
          </a>
        </li>
      </ul>
    </div>
  </main>
  <script>
    const root = document.documentElement;
    const glowEl = document.querySelector('.glow');
    const asciiEl = document.querySelector('.ascii');
    // ---- Color ----
    const defaultColor = '170, 145, 110';
    let activeColor = defaultColor;
    let rc = [170, 145, 110];

    // ---- Mouse ----
    let mx = -200, my = -200, glowX = -200, glowY = -200;
    document.addEventListener('mousemove', e => { mx = e.clientX; my = e.clientY; });

    // ---- Project hover ----
    const links = document.querySelectorAll('.work a');
    links.forEach(link => {
      link.addEventListener('mouseenter', () => {
        activeColor = link.dataset.color;
        root.style.setProperty('--active-accent', link.dataset.accent);
      });
      link.addEventListener('mouseleave', () => {
        activeColor = defaultColor;
        root.style.removeProperty('--active-accent');
      });
    });

    // ---- Main loop ----
    (function frame() {
      glowX += (mx - glowX) * 0.04;
      glowY += (my - glowY) * 0.04;
      const ac = activeColor.split(',').map(Number);
      rc = rc.map((v, i) => v + (ac[i] - v) * 0.06);
      const rcStr = rc.map(v => Math.round(v)).join(', ');

      const gx = glowX + 'px', gy = glowY + 'px';
      asciiEl.style.background = `radial-gradient(800px circle at ${gx} ${gy}, rgba(${rcStr},0.6) 0%, rgba(${rcStr},0.2) 30%, transparent 55%)`;
      asciiEl.style.webkitBackgroundClip = 'text';
      asciiEl.style.backgroundClip = 'text';
      glowEl.style.background = `radial-gradient(1800px circle at ${gx} ${gy}, rgba(${rcStr},0.05) 0%, rgba(${rcStr},0.02) 35%, transparent 65%)`;

      requestAnimationFrame(frame);
    })();

    // ---- ASCII patterns ----
    const tiles = [
      // 1. Forward slashes (kept)
      ['/  /  /  /  ',' /  /  /  / ','  /  /  /  /','   /  /  /  ','  /  /  /  /',' /  /  /  / '],
      // 2. Paired parens (kept)
      ['()  ()  ()  ','  ()  ()  ()','()  ()  ()  ','  ()  ()  ()','()  ()  ()  ','  ()  ()  ()'],
      // 3. Dots and commas grid
      ['. , . , . , ',', . , . , . ','. , . , . , ',', . , . , . ','. , . , . , ',', . , . , . '],
      // 4. Colons and dots
      [': . : . : . ',' . : . : . :',': . : . : . ',' . : . : . :',': . : . : . ',' . : . : . :'],
      // 5. Tildes and dashes diagonal
      ['~ - ~ - ~ - ','- ~ - ~ - ~ ','~ - ~ - ~ - ','- ~ - ~ - ~ ','~ - ~ - ~ - ','- ~ - ~ - ~ '],
      // 6. Semicolons stipple
      ['; ; ; ; ; ; ',' ; ; ; ; ; ;','; ; ; ; ; ; ',' ; ; ; ; ; ;','; ; ; ; ; ; ',' ; ; ; ; ; ;'],
      // 7. Pilcrows and bullets
      ['¶ • ¶ • ¶ • ','• ¶ • ¶ • ¶ ','¶ • ¶ • ¶ • ','• ¶ • ¶ • ¶ ','¶ • ¶ • ¶ • ','• ¶ • ¶ • ¶ '],
      // 9. Section signs and middle dots
      ['§ · § · § · ',' · § · § · §','§ · § · § · ',' · § · § · §','§ · § · § · ',' · § · § · §'],
      // 10. Guillemets woven
      ['« » « » « » ','» « » « » « ','« » « » « » ','» « » « » « ','« » « » « » ','» « » « » « '],
      // 11. Angle brackets and dots
      ['‹ · › · ‹ · ','· › · ‹ · › ','‹ · › · ‹ · ','· › · ‹ · › ','‹ · › · ‹ · ','· › · ‹ · › '],
      // 12. Degree and asterism
      ['° ⁂ ° ⁂ ° ⁂ ','⁂ ° ⁂ ° ⁂ ° ','° ⁂ ° ⁂ ° ⁂ ','⁂ ° ⁂ ° ⁂ ° ','° ⁂ ° ⁂ ° ⁂ ','⁂ ° ⁂ ° ⁂ ° '],
      // 13. En dashes and carets
      ['– ^ – ^ – ^ ','^ – ^ – ^ – ','– ^ – ^ – ^ ','^ – ^ – ^ – ','– ^ – ^ – ^ ','^ – ^ – ^ – '],
      // 14. Broken bars and dots
      ['¦ . ¦ . ¦ . ','. ¦ . ¦ . ¦ ','¦ . ¦ . ¦ . ','. ¦ . ¦ . ¦ ','¦ . ¦ . ¦ . ','. ¦ . ¦ . ¦ '],
      // 14. Feminine ordinal and interpuncts
      ['ª · º · ª · ','· º · ª · º ','ª · º · ª · ','· º · ª · º ','ª · º · ª · ','· º · ª · º '],
    ];
    let currentTile = -1;
    function generate() {
      let idx; do { idx = Math.floor(Math.random() * tiles.length); } while (idx === currentTile);
      currentTile = idx;
      const tile = tiles[idx], tH = tile.length, tW = tile[0].length;
      const cW = 8.2, cH = 17;
      const cols = Math.ceil(window.innerWidth / cW) + tW;
      const rows = Math.ceil(window.innerHeight / cH) + tH;
      let out = '';
      for (let r = 0; r < rows; r++) { const row = tile[r % tH]; let l = ''; while (l.length < cols) l += row; out += l.slice(0, cols) + '\n'; }
      asciiEl.textContent = out;
    }
    generate();
    window.addEventListener('resize', generate);
    document.querySelector('.shuffle').addEventListener('click', () => {
      asciiEl.style.transition = 'opacity 0.4s ease';
      asciiEl.style.opacity = '0';
      setTimeout(() => { generate(); asciiEl.style.opacity = ''; }, 400);
    });
  </script>
</body>
</html>
