ROI Calculator

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ROI Calculator – ClawMetro</title>
<style>
  @import url('https://fonts.googleapis.com/css2?family=Rajdhani:wght@600;700&family=Inter:wght@400;500;600&display=swap');

  :root {
    --bg:       #0a0a12;
    --surface:  #111122;
    --card:     #161628;
    --border:   #2a2a45;
    --pink:     #ff2d78;
    --cyan:     #00e5ff;
    --purple:   #9b4dff;
    --text:     #e8e8f0;
    --muted:    #7070a0;
    --green:    #00e676;
    --radius:   12px;
  }

  *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

  body {
    background: var(--bg);
    color: var(--text);
    font-family: 'Inter', sans-serif;
    font-size: 14px;
    line-height: 1.5;
    padding: 0;
  }

  /* ── WRAPPER ── */
  .roi-wrap {
    max-width: 980px;
    margin: 0 auto;
    padding: 32px 16px 64px;
  }

  /* ── HEADER ── */
  .roi-header {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    margin-bottom: 32px;
    flex-wrap: wrap;
    gap: 12px;
  }
  .roi-title {
    font-family: 'Rajdhani', sans-serif;
    font-size: clamp(32px, 6vw, 52px);
    font-weight: 700;
    line-height: 1;
    background: linear-gradient(90deg, var(--pink), var(--cyan));
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    background-clip: text;
  }
  .roi-subtitle {
    color: var(--muted);
    margin-top: 6px;
    font-size: 13px;
  }
  .btn-reset {
    display: flex;
    align-items: center;
    gap: 7px;
    background: transparent;
    border: 1.5px solid var(--pink);
    color: var(--pink);
    padding: 8px 16px;
    border-radius: 20px;
    cursor: pointer;
    font-size: 13px;
    font-family: 'Inter', sans-serif;
    font-weight: 600;
    white-space: nowrap;
    transition: background .2s, color .2s;
  }
  .btn-reset:hover { background: var(--pink); color: #fff; }

  /* ── SECTION LABEL ── */
  .section-label {
    font-family: 'Rajdhani', sans-serif;
    font-size: 15px;
    font-weight: 700;
    letter-spacing: .12em;
    color: var(--cyan);
    text-transform: uppercase;
    margin-bottom: 16px;
    display: flex;
    align-items: center;
    gap: 10px;
  }
  .section-label::after {
    content: '';
    flex: 1;
    height: 1px;
    background: linear-gradient(90deg, var(--border), transparent);
  }

  /* ── MACHINE GRID ── */
  .machine-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
    gap: 14px;
    margin-bottom: 24px;
  }
  .machine-card {
    background: var(--card);
    border: 1.5px solid var(--border);
    border-radius: var(--radius);
    padding: 14px 12px 12px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    transition: border-color .2s, box-shadow .2s;
    cursor: pointer;
  }
  .machine-card:hover {
    border-color: var(--cyan);
    box-shadow: 0 0 18px rgba(0,229,255,.12);
  }
  .machine-card.active {
    border-color: var(--pink);
    box-shadow: 0 0 20px rgba(255,45,120,.18);
  }
  .machine-img-wrap {
    width: 90px;
    height: 90px;
    display: flex;
    align-items: center;
    justify-content: center;
    position: relative;
  }
  .machine-img-wrap img {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
    border-radius: 6px;
    display: block;
  }
  .machine-img-wrap .img-link {
    position: absolute;
    inset: 0;
    z-index: 1;
  }
  .machine-name {
    font-weight: 600;
    font-size: 12px;
    text-align: center;
    line-height: 1.3;
    color: var(--text);
  }
  .machine-price {
    font-family: 'Rajdhani', sans-serif;
    font-size: 17px;
    font-weight: 700;
    color: var(--pink);
  }
  .qty-row {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-top: 2px;
  }
  .qty-btn {
    width: 26px;
    height: 26px;
    border-radius: 6px;
    border: 1.5px solid var(--border);
    background: var(--surface);
    color: var(--text);
    font-size: 16px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    line-height: 1;
    transition: border-color .15s, background .15s;
    flex-shrink: 0;
  }
  .qty-btn:hover { border-color: var(--pink); background: rgba(255,45,120,.1); }
  .qty-display {
    font-family: 'Rajdhani', sans-serif;
    font-size: 18px;
    font-weight: 700;
    min-width: 22px;
    text-align: center;
  }

  /* ── SUMMARY BAR ── */
  .summary-bar {
    background: var(--surface);
    border: 1.5px solid var(--border);
    border-radius: var(--radius);
    padding: 16px 24px;
    display: flex;
    align-items: center;
    justify-content: space-around;
    gap: 12px;
    margin-bottom: 32px;
    flex-wrap: wrap;
  }
  .summary-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
  }
  .summary-icon { font-size: 20px; margin-bottom: 2px; }
  .summary-label { font-size: 11px; color: var(--muted); text-transform: uppercase; letter-spacing: .08em; }
  .summary-value {
    font-family: 'Rajdhani', sans-serif;
    font-size: 24px;
    font-weight: 700;
    color: var(--text);
  }
  .summary-divider { width: 1px; height: 44px; background: var(--border); }
  .summary-hint {
    width: 100%;
    text-align: center;
    color: var(--muted);
    font-size: 12px;
    margin-top: 4px;
  }

  /* ── ASSUMPTIONS ── */
  .assumptions-grid {
    display: grid;
    grid-template-columns: 1fr auto;
    gap: 0;
  }
  .assumption-row {
    display: contents;
  }
  .assumption-row > * {
    padding: 14px 0;
    border-bottom: 1px solid var(--border);
    display: flex;
    align-items: center;
    gap: 10px;
  }
  .assumption-row:last-child > * { border-bottom: none; }
  .assumption-label-cell {
    color: var(--text);
    font-size: 14px;
    gap: 10px;
  }
  .assumption-label-cell svg { flex-shrink: 0; }
  .assumption-slider-cell {
    flex: 1;
    padding-right: 12px;
  }
  .assumption-badge {
    font-family: 'Rajdhani', sans-serif;
    font-size: 18px;
    font-weight: 700;
    background: var(--surface);
    border: 1.5px solid var(--border);
    border-radius: 8px;
    padding: 6px 14px;
    min-width: 80px;
    text-align: center;
    color: var(--text);
    white-space: nowrap;
  }

  .assumptions-wrap {
    background: var(--card);
    border: 1.5px solid var(--border);
    border-radius: var(--radius);
    padding: 8px 20px 8px;
    margin-bottom: 24px;
  }
  .assumptions-inner {
    display: grid;
    grid-template-columns: 1fr 220px auto;
    gap: 0 16px;
  }
  .ai-label { display: flex; align-items: center; gap: 10px; padding: 14px 0; border-bottom: 1px solid var(--border); }
  .ai-slider { display: flex; align-items: center; padding: 14px 0; border-bottom: 1px solid var(--border); }
  .ai-badge  { display: flex; align-items: center; padding: 14px 0; border-bottom: 1px solid var(--border); }
  .assumption-row-last .ai-label,
  .assumption-row-last .ai-slider,
  .assumption-row-last .ai-badge { border-bottom: none; }

  input[type=range] {
    -webkit-appearance: none;
    appearance: none;
    width: 100%;
    height: 4px;
    background: var(--border);
    border-radius: 2px;
    outline: none;
    cursor: pointer;
  }
  input[type=range]::-webkit-slider-thumb {
    -webkit-appearance: none;
    width: 18px; height: 18px;
    border-radius: 50%;
    background: var(--pink);
    box-shadow: 0 0 8px rgba(255,45,120,.5);
    cursor: pointer;
    transition: transform .15s;
  }
  input[type=range]::-webkit-slider-thumb:hover { transform: scale(1.2); }
  input[type=range]::-moz-range-thumb {
    width: 18px; height: 18px;
    border-radius: 50%;
    background: var(--pink);
    border: none;
    cursor: pointer;
  }

  /* ── WIN BIGGER CALLOUT ── */
  .win-bigger {
    background: linear-gradient(135deg, rgba(155,77,255,.15), rgba(255,45,120,.10));
    border: 1.5px solid var(--purple);
    border-radius: var(--radius);
    padding: 20px;
    margin-bottom: 32px;
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 6px;
  }
  .win-bigger-title {
    font-family: 'Rajdhani', sans-serif;
    font-size: 20px;
    font-weight: 700;
    color: #ffd700;
    display: flex;
    align-items: center;
    gap: 6px;
  }
  .win-bigger p { color: var(--muted); font-size: 12px; line-height: 1.4; }
  .win-bigger-margin {
    font-family: 'Rajdhani', sans-serif;
    font-size: 42px;
    font-weight: 700;
    color: var(--pink);
    line-height: 1;
  }
  .win-bigger-sub { font-size: 11px; color: var(--muted); }

  /* ── RESULTS BAND ── */
  .results-band {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
    gap: 12px;
    margin-bottom: 32px;
  }
  .result-card {
    background: var(--card);
    border: 1.5px solid var(--border);
    border-radius: var(--radius);
    padding: 16px;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 4px;
    transition: border-color .2s;
  }
  .result-card.highlight { border-color: var(--pink); }
  .result-icon { font-size: 22px; }
  .result-label { font-size: 11px; color: var(--muted); text-transform: uppercase; letter-spacing: .08em; }
  .result-value {
    font-family: 'Rajdhani', sans-serif;
    font-size: 28px;
    font-weight: 700;
    color: var(--cyan);
    line-height: 1.1;
  }
  .result-card.highlight .result-value { color: var(--green); }

  /* ── MATH SECTION ── */
  .math-chart-wrap {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 20px;
    margin-bottom: 32px;
  }
  @media(max-width: 640px) { .math-chart-wrap { grid-template-columns: 1fr; } }

  .math-box {
    background: var(--card);
    border: 1.5px solid var(--border);
    border-radius: var(--radius);
    padding: 20px;
  }
  .math-box-title {
    font-family: 'Rajdhani', sans-serif;
    font-size: 14px;
    font-weight: 700;
    letter-spacing: .1em;
    color: var(--cyan);
    text-transform: uppercase;
    margin-bottom: 16px;
    padding-bottom: 10px;
    border-bottom: 1px solid var(--border);
  }
  .math-row {
    display: grid;
    grid-template-columns: 120px 1fr auto;
    gap: 8px;
    padding: 10px 0;
    border-bottom: 1px solid rgba(255,255,255,.04);
    align-items: start;
  }
  .math-row:last-child { border-bottom: none; }
  .math-name { font-weight: 600; font-size: 13px; }
  .math-formula { font-size: 11px; color: var(--muted); line-height: 1.4; }
  .math-amount {
    font-family: 'Rajdhani', sans-serif;
    font-size: 16px;
    font-weight: 700;
    color: var(--cyan);
    text-align: right;
    white-space: nowrap;
  }
  .math-row.payback-row {
    background: linear-gradient(90deg, rgba(255,45,120,.12), transparent);
    border-radius: 8px;
    margin: 6px -8px 0;
    padding: 12px 8px;
    border-bottom: none;
  }
  .math-row.payback-row .math-name { color: var(--pink); font-size: 14px; }
  .math-row.payback-row .math-amount { color: var(--pink); font-size: 20px; }

  /* ── CHART ── */
  .chart-box {
    background: var(--card);
    border: 1.5px solid var(--border);
    border-radius: var(--radius);
    padding: 20px;
    display: flex;
    flex-direction: column;
    gap: 12px;
  }
  .chart-title {
    font-family: 'Rajdhani', sans-serif;
    font-size: 14px;
    font-weight: 700;
    letter-spacing: .1em;
    color: var(--cyan);
    text-transform: uppercase;
  }
  .chart-legend {
    display: flex;
    gap: 16px;
    font-size: 11px;
    color: var(--muted);
  }
  .legend-dot {
    width: 10px; height: 10px;
    border-radius: 2px;
    display: inline-block;
    margin-right: 4px;
    vertical-align: middle;
  }
  canvas#profitChart { width: 100% !important; }

  /* ── ASSUMPTIONS + WIN BIGGER SIDE BY SIDE ── */
  .middle-wrap {
    display: grid;
    grid-template-columns: 1fr 220px;
    gap: 20px;
    align-items: start;
    margin-bottom: 32px;
  }
  @media(max-width: 680px) { .middle-wrap { grid-template-columns: 1fr; } }

  /* ── CTA BUTTON ── */
  .cta-wrap {
    display: flex;
    justify-content: center;
    margin-bottom: 24px;
  }
  .cta-btn {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 4px;
    padding: 18px 36px;
    border-radius: var(--radius);
    font-family: 'Inter', sans-serif;
    font-weight: 700;
    font-size: 14px;
    cursor: pointer;
    text-decoration: none;
    transition: opacity .2s, transform .15s;
    letter-spacing: .04em;
    border: none;
    width: 100%;
    max-width: 480px;
    text-align: center;
  }
  .cta-btn:hover { opacity: .88; transform: translateY(-1px); }
  .cta-primary {
    background: linear-gradient(135deg, var(--pink), #c2185b);
    color: #fff;
  }
  .cta-secondary {
    background: linear-gradient(135deg, var(--purple), #6a1b9a);
    color: #fff;
  }

  .roi-footer {
    text-align: center;
    font-size: 11px;
    color: var(--muted);
    line-height: 1.6;
  }

  /* ── MODAL ── */
  .modal-overlay {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,.75);
    z-index: 9999;
    align-items: center;
    justify-content: center;
    padding: 20px;
    backdrop-filter: blur(4px);
  }
  .modal-overlay.open { display: flex; }
  .modal-box {
    background: var(--card);
    border: 1.5px solid var(--border);
    border-radius: 16px;
    max-width: 520px;
    width: 100%;
    padding: 28px;
    position: relative;
    animation: modalIn .2s ease;
  }
  @keyframes modalIn {
    from { transform: scale(.94); opacity: 0; }
    to   { transform: scale(1);   opacity: 1; }
  }
  .modal-close {
    position: absolute;
    top: 14px; right: 16px;
    background: none;
    border: none;
    color: var(--muted);
    font-size: 22px;
    cursor: pointer;
    line-height: 1;
    transition: color .15s;
  }
  .modal-close:hover { color: var(--text); }
  .modal-img { width: 100%; max-height: 220px; object-fit: contain; border-radius: 10px; margin-bottom: 16px; background: var(--surface); padding: 12px; }
  .modal-name {
    font-family: 'Rajdhani', sans-serif;
    font-size: 24px;
    font-weight: 700;
    margin-bottom: 4px;
  }
  .modal-price { color: var(--pink); font-size: 20px; font-weight: 700; font-family: 'Rajdhani', sans-serif; margin-bottom: 12px; }
  .modal-desc { color: var(--muted); font-size: 13px; line-height: 1.6; margin-bottom: 20px; }
  .modal-actions { display: flex; gap: 12px; flex-wrap: wrap; }
  .modal-btn-primary {
    flex: 1;
    padding: 12px 20px;
    background: linear-gradient(135deg, var(--pink), #c2185b);
    color: #fff;
    border: none;
    border-radius: 8px;
    font-weight: 700;
    font-size: 14px;
    cursor: pointer;
    text-decoration: none;
    text-align: center;
    font-family: 'Inter', sans-serif;
    transition: opacity .2s;
  }
  .modal-btn-primary:hover { opacity: .85; }
  .modal-btn-secondary {
    flex: 1;
    padding: 12px 20px;
    background: transparent;
    color: var(--cyan);
    border: 1.5px solid var(--cyan);
    border-radius: 8px;
    font-weight: 700;
    font-size: 14px;
    cursor: pointer;
    text-decoration: none;
    text-align: center;
    font-family: 'Inter', sans-serif;
    transition: background .2s, color .2s;
  }
  .modal-btn-secondary:hover { background: var(--cyan); color: #000; }
  .modal-qty-row {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 16px;
    background: var(--surface);
    border: 1.5px solid var(--border);
    border-radius: 10px;
    padding: 10px 16px;
  }
  .modal-qty-label { flex: 1; font-weight: 600; }
  .modal-qty-btn {
    width: 32px; height: 32px;
    border-radius: 8px;
    border: 1.5px solid var(--border);
    background: var(--card);
    color: var(--text);
    font-size: 18px;
    cursor: pointer;
    display: flex; align-items: center; justify-content: center;
    transition: border-color .15s;
    flex-shrink: 0;
  }
  .modal-qty-btn:hover { border-color: var(--pink); }
  .modal-qty-num {
    font-family: 'Rajdhani', sans-serif;
    font-size: 22px;
    font-weight: 700;
    min-width: 28px;
    text-align: center;
  }
</style>
</head>
<body>

<div class="roi-wrap">

  <!-- HEADER -->
  <div class="roi-header">
    <div>
      <div class="roi-title">ROI CALCULATOR</div>
      <div class="roi-subtitle">Build your arcade lineup and see your projected return on investment</div>
    </div>
    <button class="btn-reset" onclick="resetAll()">
      <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><path d="M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"/><path d="M3 3v5h5"/></svg>
      Reset all
    </button>
  </div>

  <!-- BUILD YOUR ARCADE -->
  <div class="section-label">Build Your Arcade</div>
  <div class="machine-grid" id="machineGrid"></div>

  <!-- SUMMARY BAR -->
  <div class="summary-bar">
    <div class="summary-item">
      <div class="summary-icon">🕹️</div>
      <div class="summary-label">Total Machines</div>
      <div class="summary-value" id="totalMachines">0</div>
    </div>
    <div class="summary-divider"></div>
    <div class="summary-item">
      <div class="summary-icon">🛒</div>
      <div class="summary-label">Total Investment</div>
      <div class="summary-value" id="totalInvestment">$0</div>
    </div>
    <div class="summary-divider"></div>
    <div class="summary-item">
      <div class="summary-icon">⚡</div>
      <div class="summary-label">Avg. Cost per Machine</div>
      <div class="summary-value" id="avgCost">$0</div>
    </div>
    <div class="summary-hint" id="summaryHint">Add machines above to build your arcade lineup.</div>
  </div>

  <!-- REVENUE ASSUMPTIONS + WIN BIGGER -->
  <div class="section-label">Revenue Assumptions</div>
  <div class="middle-wrap">
    <div class="assumptions-wrap">
      <div class="assumptions-inner">

        <div class="ai-label">
          <svg width="18" height="18" fill="none" stroke="var(--cyan)" stroke-width="2" viewBox="0 0 24 24"><circle cx="12" cy="8" r="4"/><path d="M4 20c0-4 3.6-7 8-7s8 3 8 7"/></svg>
          Plays per machine per day
        </div>
        <div class="ai-slider"><input type="range" id="playsSlider" min="10" max="300" value="80" oninput="updateBadge('playsVal', this.value, ''); recalc()"></div>
        <div class="ai-badge"><div class="assumption-badge"><span id="playsVal">80</span> plays</div></div>

        <div class="ai-label">
          <svg width="18" height="18" fill="none" stroke="var(--pink)" stroke-width="2" viewBox="0 0 24 24"><rect x="2" y="5" width="20" height="14" rx="2"/><path d="M2 10h20"/></svg>
          Price per play ($)
        </div>
        <div class="ai-slider"><input type="range" id="priceSlider" min="0.25" max="10" step="0.25" value="2.00" oninput="updateBadge('priceVal', '$'+parseFloat(this.value).toFixed(2), ''); recalc()"></div>
        <div class="ai-badge"><div class="assumption-badge"><span id="priceVal">$2.00</span></div></div>

        <div class="ai-label">
          <svg width="18" height="18" fill="none" stroke="var(--purple)" stroke-width="2" viewBox="0 0 24 24"><path d="M20 12V22H4V12"/><path d="M22 7H2v5h20V7z"/><path d="M12 22V7"/><path d="M12 7H7.5a2.5 2.5 0 0 1 0-5C11 2 12 7 12 7z"/><path d="M12 7h4.5a2.5 2.5 0 0 0 0-5C13 2 12 7 12 7z"/></svg>
          Prize cost ($)
        </div>
        <div class="ai-slider"><input type="range" id="prizeCostSlider" min="1" max="50" step="0.10" value="3.00" oninput="updateBadge('prizeCostVal', '$'+parseFloat(this.value).toFixed(2), ''); recalc()"></div>
        <div class="ai-badge"><div class="assumption-badge"><span id="prizeCostVal">$3.00</span></div></div>

        <div class="ai-label">
          <svg width="18" height="18" fill="none" stroke="#ffd700" stroke-width="2" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/><path d="M12 8v4l3 3"/></svg>
          Win rate (1 win per X plays)
        </div>
        <div class="ai-slider"><input type="range" id="winRateSlider" min="1" max="50" step="1" value="10" oninput="updateBadge('winRateVal', '1 in '+this.value, ''); recalc()"></div>
        <div class="ai-badge"><div class="assumption-badge"><span id="winRateVal">1 in 10</span></div></div>

        <div class="ai-label">
          <svg width="18" height="18" fill="none" stroke="var(--cyan)" stroke-width="2" viewBox="0 0 24 24"><circle cx="12" cy="12" r="9"/><path d="M9 12l2 2 4-4"/></svg>
          Prize cost per win (calculated)
        </div>
        <div class="ai-slider"><span style="color:var(--muted); font-size:12px;">Prize Cost ÷ Win Rate</span></div>
        <div class="ai-badge"><div class="assumption-badge" style="color:var(--green); border-color:var(--green);"><span id="prizeCostPerWinVal">$0.30</span></div></div>

        <div class="ai-label assumption-row-last">
          <svg width="18" height="18" fill="none" stroke="var(--green)" stroke-width="2" viewBox="0 0 24 24"><polyline points="23 6 13.5 15.5 8.5 10.5 1 18"/><polyline points="17 6 23 6 23 12"/></svg>
          Monthly operating costs ($)
        </div>
        <div class="ai-slider assumption-row-last"><input type="range" id="opexSlider" min="0" max="5000" step="50" value="500" oninput="updateBadge('opexVal', '$'+parseInt(this.value).toLocaleString(), ''); recalc()"></div>
        <div class="ai-badge assumption-row-last"><div class="assumption-badge"><span id="opexVal">$500</span></div></div>

      </div>
    </div>

    <div class="win-bigger">
      <div class="win-bigger-title">🏆 WIN BIGGER</div>
      <p>Industry leading margins designed to help you maximize profits and grow your business.</p>
      <div style="margin-top:10px; font-size:11px; color:var(--muted); text-transform:uppercase; letter-spacing:.1em;">Average Net Profit Margin</div>
      <div class="win-bigger-margin">35%</div>
      <div class="win-bigger-sub">After prizes and operating expenses</div>
    </div>
  </div>

  <!-- PROJECTED RESULTS -->
  <div class="section-label">Projected Results</div>
  <div class="results-band">
    <div class="result-card">
      <div class="result-icon">💰</div>
      <div class="result-label">Daily Revenue</div>
      <div class="result-value" id="resDailyRev">$0</div>
    </div>
    <div class="result-card">
      <div class="result-icon">📅</div>
      <div class="result-label">Monthly Revenue</div>
      <div class="result-value" id="resMonthlyRev">$0</div>
    </div>
    <div class="result-card">
      <div class="result-icon">📈</div>
      <div class="result-label">Monthly Net Profit</div>
      <div class="result-value" id="resMonthlyProfit">$0</div>
    </div>
    <div class="result-card highlight">
      <div class="result-icon">🤑</div>
      <div class="result-label">Yearly Net Profit</div>
      <div class="result-value" id="resYearlyProfit">$0</div>
    </div>
    <div class="result-card">
      <div class="result-icon">⏱️</div>
      <div class="result-label">Payback Period</div>
      <div class="result-value" id="resPayback">—</div>
    </div>
  </div>

  <!-- MATH + CHART -->
  <div class="math-chart-wrap">
    <div class="math-box">
      <div class="math-box-title">The Math Behind Your ROI</div>

      <div class="math-row">
        <div class="math-name">Daily Revenue</div>
        <div class="math-formula" id="fDailyRev">Total Machines × Plays/Day × Price<br>0 × 80 × $2.00</div>
        <div class="math-amount" id="mDailyRev">$0</div>
      </div>
      <div class="math-row">
        <div class="math-name">Daily Prize Cost</div>
        <div class="math-formula" id="fDailyPrize">Daily Revenue × Prize %<br>$0 × 25%</div>
        <div class="math-amount" id="mDailyPrize">$0</div>
      </div>
      <div class="math-row">
        <div class="math-name">Daily Operating Cost</div>
        <div class="math-formula" id="fDailyOpex">Daily Revenue × OpEx %<br>$0 × 15%</div>
        <div class="math-amount" id="mDailyOpex">$0</div>
      </div>
      <div class="math-row">
        <div class="math-name">Daily Net Profit</div>
        <div class="math-formula" id="fDailyNet">Revenue – Prizes – OpEx<br>$0 – $0 – $0</div>
        <div class="math-amount" id="mDailyNet">$0</div>
      </div>
      <div class="math-row">
        <div class="math-name">Monthly Net Profit</div>
        <div class="math-formula" id="fMonthlyNet">Daily Net Profit × 30<br>$0 × 30</div>
        <div class="math-amount" id="mMonthlyNet">$0</div>
      </div>
      <div class="math-row">
        <div class="math-name">Yearly Net Profit</div>
        <div class="math-formula" id="fYearlyNet">Daily Net Profit × 365<br>$0 × 365</div>
        <div class="math-amount" id="mYearlyNet">$0</div>
      </div>
      <div class="math-row payback-row">
        <div class="math-name">Payback Period</div>
        <div class="math-formula" id="fPayback">Total Investment ÷ Monthly Net Profit</div>
        <div class="math-amount" id="mPayback">— months</div>
      </div>
    </div>

    <div class="chart-box">
      <div class="chart-title">Profit Over Time</div>
      <div class="chart-legend">
        <span><span class="legend-dot" style="background:var(--cyan)"></span>Cumulative Profit</span>
        <span><span class="legend-dot" style="background:none; border:2px dashed var(--pink); border-radius:2px; width:12px; height:8px; display:inline-block; margin-right:4px; vertical-align:middle;"></span>Break-Even Point</span>
      </div>
      <canvas id="profitChart" height="260"></canvas>
    </div>
  </div>

  <!-- CTA BUTTON -->
  <div class="cta-wrap">
    <a href="https://clawmetro.com/pages/contact" target="_blank" class="cta-btn cta-primary">
      <span>💬 CONSULT AN EXPERT FOR A FREE QUOTE</span>
      <span style="font-weight:400; font-size:11px; opacity:.8;">Our team will help you build the perfect setup</span>
    </a>
  </div>

  <div class="roi-footer">
    Results are estimates based on industry averages and the assumptions you input.<br>
    Actual results may vary based on location, traffic, pricing, and operation.
  </div>

</div>

<!-- MODAL -->
<div class="modal-overlay" id="modalOverlay" onclick="closeModalOnOverlay(event)">
  <div class="modal-box">
    <button class="modal-close" onclick="closeModal()">✕</button>
    <img class="modal-img" id="modalImg" src="" alt="">
    <div class="modal-name" id="modalName"></div>
    <div class="modal-price" id="modalPrice"></div>
    <div class="modal-desc" id="modalDesc"></div>
    <div class="modal-qty-row">
      <div class="modal-qty-label">Qty in your lineup</div>
      <button class="modal-qty-btn" onclick="changeModalQty(-1)">−</button>
      <div class="modal-qty-num" id="modalQty">0</div>
      <button class="modal-qty-btn" onclick="changeModalQty(1)">+</button>
    </div>
    <div class="modal-actions">
      <a class="modal-btn-primary" id="modalBuyLink" href="#" target="_blank">View on ClawMetro →</a>
      <button class="modal-btn-secondary" onclick="closeModal()">Done</button>
    </div>
  </div>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.4.1/chart.umd.min.js"></script>
<script>
// ── MACHINE DEFINITIONS ──
// Prices start at 0 and are fetched live from Shopify product JSON endpoints.
// Images + descriptions are also pulled from the live store.
// Fallback prices shown if fetch fails.
const MACHINES = [
  {
    id: 0,
    name: '31" Classic x Travel',
    shortName: '31" Travel Claw',
    price: 0,
    fallbackPrice: 2650,
    handle: '31-classic-x-travel-31-standard-claw',
    variantId: 48233049784576,
    url: 'https://clawmetro.com/products/31-classic-x-travel-31-standard-claw?variant=48233049784576',
    img: '',
    desc: 'The 31" Travel Claw is a compact, classic-style claw machine perfect for high-traffic locations. Easy to operate and a crowd-pleaser for all ages.'
  },
  {
    id: 1,
    name: '31" Classic x Otaku',
    shortName: '31" Otaku',
    price: 0,
    fallbackPrice: 2895,
    handle: 'white-orange-31-classic-x-otaku-31-standard-claw',
    variantId: 48577446052096,
    url: 'https://clawmetro.com/products/white-orange-31-classic-x-otaku-31-standard-claw?variant=48577446052096',
    img: '',
    desc: 'The Otaku edition brings anime-inspired style to your arcade. The 31" form factor is proven to drive repeat plays and strong revenue per square foot.'
  },
  {
    id: 2,
    name: 'GachaZone Station',
    shortName: 'GachaZone',
    price: 0,
    fallbackPrice: 1495,
    handle: 'gachazone-4player-gachapon-station',
    variantId: 48233647997184,
    url: 'https://clawmetro.com/products/gachazone-4player-gachapon-station?variant=48233647997184',
    img: '',
    desc: 'A 4-player Gachapon station that lets players turn a coin into a mystery capsule prize. Low prize cost, very high margin, massive appeal.'
  },
  {
    id: 3,
    name: '4P MiniRush',
    shortName: '4P MiniRush',
    price: 0,
    fallbackPrice: 1495,
    handle: '4p-minirush-4player-mini-claw',
    variantId: 48232596635904,
    url: 'https://clawmetro.com/products/4p-minirush-4player-mini-claw?variant=48232596635904',
    img: '',
    desc: 'The 4P MiniRush packs four mini claw lanes into one unit. Competitive play drives higher spends and longer session times per visit.'
  },
  {
    id: 4,
    name: '4P Arena4',
    shortName: '4P Arena4',
    price: 0,
    fallbackPrice: 4995,
    handle: '4p-arena4-4player-island-mini-claw',
    variantId: 48232681603328,
    url: 'https://clawmetro.com/products/4p-arena4-4player-island-mini-claw?variant=48232681603328',
    img: '',
    desc: 'The Arena4 is a 4-player island-format mini claw. Its open design attracts bystanders and encourages group play, multiplying revenue potential.'
  },
  {
    id: 5,
    name: '8P Hyper Hub',
    shortName: '8P Hyper Hub',
    price: 0,
    fallbackPrice: 7995,
    handle: '8p-hyper-hub-8player-island-mini-claw',
    variantId: 48232974254336,
    url: 'https://clawmetro.com/products/8p-hyper-hub-8player-island-mini-claw?variant=48232974254336',
    img: '',
    desc: 'The 8P Hyper Hub is the flagship multi-player island unit — 8 simultaneous players, LED-lit spectacle, and maximum floor revenue per machine slot.'
  },
  {
    id: 6,
    name: '41" Titan Claw',
    shortName: '41" Jumbo Claw',
    price: 0,
    fallbackPrice: 4995,
    handle: '41-titan-claw-41-jumbo-claw',
    variantId: 48233317499136,
    url: 'https://clawmetro.com/products/41-titan-claw-41-jumbo-claw?variant=48233317499136',
    img: '',
    desc: 'The 41" Titan Claw is a premium jumbo machine that holds oversized plush and creates a dramatic anchor piece for your arcade.'
  },
  {
    id: 7,
    name: 'SkillCut Pro',
    shortName: 'SkillCut Pro',
    price: 0,
    fallbackPrice: 6995,
    handle: 'skillcut-pro-cutting-machine',
    variantId: 48233396175104,
    url: 'https://clawmetro.com/products/skillcut-pro-cutting-machine?variant=48233396175104',
    img: '',
    desc: 'The SkillCut Pro is a string-cutting skill game where players cut strings to win prizes. High replay value and strong margins.'
  },
  {
    id: 8,
    name: 'Clip Clash',
    shortName: 'Clip Clash',
    price: 0,
    fallbackPrice: 2995,
    handle: 'clip-clash-double-clip-machine',
    variantId: 48233427665152,
    url: 'https://clawmetro.com/products/clip-clash-double-clip-machine?variant=48233427665152',
    img: '',
    desc: 'The Clip Clash is a double clip machine that challenges players to clip prizes off racks. Fast-paced, addictive gameplay that keeps quarters flowing.'
  },
  {
    id: 9,
    name: 'PlayPort Token Exchanger',
    shortName: 'PlayPort Token Exchange',
    price: 0,
    fallbackPrice: 1495,
    handle: 'playport-token-exchanger-machine',
    variantId: 48233723527424,
    url: 'https://clawmetro.com/products/playport-token-exchanger-machine?variant=48233723527424',
    img: '',
    desc: 'Turn cash into tokens seamlessly with the PlayPort Token Exchanger. Removes friction and increases total spend throughout your arcade.'
  }
];

// ── LIVE PRICE + IMAGE FETCHING ──
// Fetches /products/{handle}.json from the same Shopify domain.
// Works when this page is served from clawmetro.com (same-origin).
// Falls back to hardcoded prices if fetch fails (e.g. preview/dev).
async function fetchProductData(machine) {
  try {
    const res = await fetch(`/products/${machine.handle}.json`);
    if (!res.ok) throw new Error('HTTP ' + res.status);
    const data = await res.json();
    const product = data.product;

    // Get price from the matching variant, or first variant
    const variant = product.variants.find(v => v.id == machine.variantId)
                 || product.variants[0];
    if (variant) {
      machine.price = parseFloat(variant.price);
    }

    // Get first product image
    if (product.images && product.images.length > 0) {
      machine.img = product.images[0].src;
    }

    // Use product description if available
    if (product.body_html) {
      const tmp = document.createElement('div');
      tmp.innerHTML = product.body_html;
      const text = tmp.textContent.trim();
      if (text.length > 20) machine.desc = text.substring(0, 200) + (text.length > 200 ? '…' : '');
    }
  } catch (e) {
    // Silently fall back to hardcoded price
    machine.price = machine.fallbackPrice;
  }
}

async function fetchAllProducts() {
  // Show loading state on price labels
  document.querySelectorAll('.machine-price').forEach(el => {
    el.textContent = '...';
    el.style.opacity = '0.5';
  });

  await Promise.all(MACHINES.map(m => fetchProductData(m)));

  // Re-render cards with live data
  renderCards();
  recalc();
}

const quantities = new Array(MACHINES.length).fill(0);
let activeModalIdx = null;
let profitChart = null;

function fmt(n) {
  return '$' + Math.round(n).toLocaleString();
}

function updateBadge(id, val) {
  document.getElementById(id).textContent = val;
}

// ── RENDER CARDS ──
function renderCards() {
  const grid = document.getElementById('machineGrid');
  grid.innerHTML = '';
  MACHINES.forEach((m, i) => {
    const card = document.createElement('div');
    card.className = 'machine-card' + (quantities[i] > 0 ? ' active' : '');
    card.id = 'card-' + i;
    const priceDisplay = m.price > 0 ? fmt(m.price) : (m.fallbackPrice ? fmt(m.fallbackPrice) : '…');
    const imgSrc = m.img || '';
    const imgStyle = imgSrc ? '' : 'opacity:.25; filter:grayscale(1)';
    card.innerHTML = `
      <div class="machine-img-wrap">
        ${imgSrc
          ? `<img src="${imgSrc}" alt="${m.name}" onerror="this.style.opacity='.2'" style="${imgStyle}">`
          : `<div style="width:80px;height:80px;border-radius:8px;background:var(--border);display:flex;align-items:center;justify-content:center;font-size:28px;">🕹️</div>`
        }
        <span class="img-link" onclick="openModal(${i})" title="View ${m.name}"></span>
      </div>
      <div class="machine-name">
        <a href="${m.url}" target="_blank" style="color:inherit;text-decoration:none;" onmouseover="this.style.color='var(--cyan)'" onmouseout="this.style.color='inherit'" onclick="event.stopPropagation()">${m.shortName}</a>
      </div>
      <div class="machine-price" id="price-${i}">${priceDisplay}</div>
      <div class="qty-row">
        <button class="qty-btn" onclick="changeQty(${i}, -1)">−</button>
        <div class="qty-display" id="qty-${i}">${quantities[i]}</div>
        <button class="qty-btn" onclick="changeQty(${i}, 1)">+</button>
      </div>
    `;
    grid.appendChild(card);
  });
}

function changeQty(idx, delta) {
  quantities[idx] = Math.max(0, quantities[idx] + delta);
  document.getElementById('qty-' + idx).textContent = quantities[idx];
  const card = document.getElementById('card-' + idx);
  card.classList.toggle('active', quantities[idx] > 0);
  if (activeModalIdx === idx) {
    document.getElementById('modalQty').textContent = quantities[idx];
  }
  recalc();
}

// ── MODAL ──
function openModal(idx) {
  const m = MACHINES[idx];
  activeModalIdx = idx;
  document.getElementById('modalImg').src = m.img;
  document.getElementById('modalName').textContent = m.name;
  document.getElementById('modalPrice').textContent = fmt(m.price);
  document.getElementById('modalDesc').textContent = m.desc;
  document.getElementById('modalQty').textContent = quantities[idx];
  document.getElementById('modalBuyLink').href = m.url;
  document.getElementById('modalOverlay').classList.add('open');
  document.body.style.overflow = 'hidden';
}

function closeModal() {
  document.getElementById('modalOverlay').classList.remove('open');
  document.body.style.overflow = '';
  activeModalIdx = null;
}

function closeModalOnOverlay(e) {
  if (e.target === document.getElementById('modalOverlay')) closeModal();
}

function changeModalQty(delta) {
  if (activeModalIdx === null) return;
  changeQty(activeModalIdx, delta);
}

// ── RECALC ──
function fmtCents(n) {
  return '$' + n.toFixed(2);
}

function recalc() {
  const totalMachines = quantities.reduce((s, q) => s + q, 0);
  const totalInvestment = quantities.reduce((s, q, i) => s + q * MACHINES[i].price, 0);
  const avgCost = totalMachines > 0 ? totalInvestment / totalMachines : 0;

  document.getElementById('totalMachines').textContent = totalMachines;
  document.getElementById('totalInvestment').textContent = fmt(totalInvestment);
  document.getElementById('avgCost').textContent = avgCost > 0 ? fmt(avgCost) : '$0';
  document.getElementById('summaryHint').style.display = totalMachines > 0 ? 'none' : 'block';

  const plays      = +document.getElementById('playsSlider').value;
  const price      = +document.getElementById('priceSlider').value;
  const prizeCost  = +document.getElementById('prizeCostSlider').value;
  const winRate    = +document.getElementById('winRateSlider').value; // 1 win per X plays
  const monthlyOpex = +document.getElementById('opexSlider').value;

  // Prize cost per win = Prize Cost / Win Rate (cost spread per play based on win frequency)
  const prizeCostPerWin = prizeCost / winRate;
  document.getElementById('prizeCostPerWinVal').textContent = fmtCents(prizeCostPerWin);

  const dailyRev      = totalMachines * plays * price;
  const dailyPrizeCost = totalMachines * plays * prizeCostPerWin;
  const dailyOpex      = monthlyOpex / 30; // spread monthly opex across the days in a month
  const dailyNet        = dailyRev - dailyPrizeCost - dailyOpex;
  const monthlyRev      = dailyRev * 30;
  const monthlyNet      = dailyNet * 30;
  const yearlyNet        = dailyNet * 365;
  const payback           = monthlyNet > 0 ? totalInvestment / monthlyNet : null;

  // Results band
  document.getElementById('resDailyRev').textContent    = fmt(dailyRev);
  document.getElementById('resMonthlyRev').textContent  = fmt(monthlyRev);
  document.getElementById('resMonthlyProfit').textContent = fmt(monthlyNet);
  document.getElementById('resYearlyProfit').textContent  = fmt(yearlyNet);
  document.getElementById('resPayback').textContent     = payback !== null ? payback.toFixed(1) + ' mo' : '—';

  // Math box
  const pp = parseFloat(price).toFixed(2);
  const pcpw = fmtCents(prizeCostPerWin);
  document.getElementById('fDailyRev').innerHTML   = `Total Machines × Plays/Day × Price<br>${totalMachines} × ${plays} × $${pp}`;
  document.getElementById('fDailyPrize').innerHTML = `Machines × Plays/Day × Prize Cost/Win<br>${totalMachines} × ${plays} × ${pcpw}`;
  document.getElementById('fDailyOpex').innerHTML  = `Monthly Operating Costs ÷ 30<br>$${monthlyOpex.toLocaleString()} ÷ 30`;
  document.getElementById('fDailyNet').innerHTML   = `Revenue – Prize Cost – Daily OpEx<br>${fmt(dailyRev)} – ${fmt(dailyPrizeCost)} – ${fmt(dailyOpex)}`;
  document.getElementById('fMonthlyNet').innerHTML = `Daily Net Profit × 30<br>${fmt(dailyNet)} × 30`;
  document.getElementById('fYearlyNet').innerHTML  = `Daily Net Profit × 365<br>${fmt(dailyNet)} × 365`;

  document.getElementById('mDailyRev').textContent   = fmt(dailyRev);
  document.getElementById('mDailyPrize').textContent  = fmt(dailyPrizeCost);
  document.getElementById('mDailyOpex').textContent   = fmt(dailyOpex);
  document.getElementById('mDailyNet').textContent    = fmt(dailyNet);
  document.getElementById('mMonthlyNet').textContent  = fmt(monthlyNet);
  document.getElementById('mYearlyNet').textContent   = fmt(yearlyNet);
  document.getElementById('mPayback').textContent     = payback !== null ? payback.toFixed(1) + ' months' : '— months';

  updateChart(totalInvestment, monthlyNet);
}


// ── CHART ──
function updateChart(investment, monthlyNet) {
  const labels = [];
  const data = [];
  const breakEvenData = [];
  const breakEvenMonth = monthlyNet > 0 ? investment / monthlyNet : null;

  for (let m = 0; m <= 36; m += 3) {
    labels.push(m);
    data.push(monthlyNet * m - investment);
    breakEvenData.push(0);
  }

  const ctx = document.getElementById('profitChart').getContext('2d');

  if (profitChart) {
    profitChart.data.labels = labels;
    profitChart.data.datasets[0].data = data;
    profitChart.update('none');
    return;
  }

  profitChart = new Chart(ctx, {
    type: 'line',
    data: {
      labels,
      datasets: [
        {
          label: 'Cumulative Profit',
          data,
          borderColor: '#00e5ff',
          backgroundColor: 'rgba(0,229,255,.08)',
          fill: true,
          tension: 0.35,
          pointBackgroundColor: '#00e5ff',
          pointRadius: 3,
          borderWidth: 2,
        },
        {
          label: 'Break-Even',
          data: breakEvenData,
          borderColor: '#ff2d78',
          borderDash: [6, 4],
          borderWidth: 1.5,
          pointRadius: 0,
          fill: false,
        }
      ]
    },
    options: {
      responsive: true,
      animation: { duration: 300 },
      plugins: {
        legend: { display: false },
        tooltip: {
          backgroundColor: '#161628',
          borderColor: '#2a2a45',
          borderWidth: 1,
          titleColor: '#e8e8f0',
          bodyColor: '#7070a0',
          callbacks: {
            label: ctx => ' ' + fmt(ctx.parsed.y)
          }
        }
      },
      scales: {
        x: {
          title: { display: true, text: 'Months', color: '#7070a0', font: { size: 11 } },
          ticks: { color: '#7070a0', font: { size: 11 } },
          grid: { color: 'rgba(255,255,255,.04)' },
          border: { color: '#2a2a45' }
        },
        y: {
          ticks: {
            color: '#7070a0',
            font: { size: 11 },
            callback: v => {
              if (Math.abs(v) >= 1000) return '$' + (v/1000).toFixed(0) + 'K';
              return '$' + v;
            }
          },
          grid: { color: 'rgba(255,255,255,.04)' },
          border: { color: '#2a2a45' }
        }
      }
    }
  });
}

function resetAll() {
  quantities.fill(0);
  document.getElementById('playsSlider').value = 80;
  document.getElementById('priceSlider').value = 2.00;
  document.getElementById('prizeCostSlider').value = 3.00;
  document.getElementById('winRateSlider').value = 10;
  document.getElementById('opexSlider').value  = 500;
  updateBadge('playsVal', '80 plays');
  updateBadge('priceVal', '$2.00');
  updateBadge('prizeCostVal', '$3.00');
  updateBadge('winRateVal', '1 in 10');
  updateBadge('opexVal',  '$500');
  renderCards();
  recalc();
}

// ── INIT ──
// Render cards immediately with placeholders, then fetch live prices
renderCards();
recalc();
fetchAllProducts();
</script>
</body>
</html>