<!-- BEGIN: Ultimate Swap & VM Memory Planner (paste whole block into Zoho Sites HTML/Embed) -->
<style>
  :root{
    --accent:#0b76d1;
    --muted:#6b7280;
    --card:#ffffff;
    --bg:#f6f8fb;
    --success:#16a34a;
    --danger:#ef4444;
    --glass: rgba(255,255,255,0.8);
  }
  .swap-tool{font-family:Inter,ui-sans-serif,system-ui,Segoe UI,Roboto, "Helvetica Neue", Arial; max-width:820px; margin:8px auto; background:var(--bg); padding:16px; border-radius:10px;}
  .swap-card{background:var(--card); border-radius:10px; padding:12px; box-shadow:0 6px 18px rgba(15,23,42,0.06); margin-bottom:12px;}
  .swap-row{display:flex; gap:12px; align-items:center; flex-wrap:wrap;}
  label{display:block; font-size:13px; color:var(--muted); margin-bottom:6px;}
  input[type=number], select{width:180px; padding:8px 10px; border-radius:6px; border:1px solid #e6e9ef; font-size:14px;}
  .small{width:120px;}
  .btn{background:var(--accent); color:#fff; border:none; padding:8px 12px; border-radius:8px; cursor:pointer; font-weight:600;}
  .btn-ghost{background:transparent; border:1px solid #e6e6e6; color:var(--muted);}
  .result{font-size:18px; font-weight:700; color:#0f172a;}
  .muted{color:var(--muted); font-size:13px;}
  .stat{display:flex; gap:8px; align-items:center;}
  .chart{height:16px; width:100%; background:#f0f2f6; border-radius:8px; overflow:hidden;}
  .bar{height:100%; background:linear-gradient(90deg,var(--accent),#4fd1c5); width:0%;}
  .grid{display:grid; grid-template-columns: 1fr 1fr; gap:12px;}
  .explain{font-size:13px; color:var(--muted); margin-top:8px;}
  .advanced{display:flex; gap:8px; align-items:center; margin-top:8px; flex-wrap:wrap;}
  .pill{background:#eef6ff; padding:6px 8px; border-radius:999px; font-size:13px; color:var(--accent);}
  .actions{display:flex; gap:8px; margin-top:12px; flex-wrap:wrap;}
  pre.cmd{background:#0b1220; color:#d1e7ff; padding:10px; border-radius:6px; overflow:auto; font-size:13px;}
  .footer-note{font-size:12px; color:var(--muted); margin-top:10px;}
  .flex-between{display:flex; justify-content:space-between; align-items:center;}
  @media(max-width:720px){ .grid{grid-template-columns:1fr} input[type=number], select {width:100%} }
</style>

<div class="swap-tool" id="swapTool">
  <div class="swap-card">
    <div class="flex-between">
      <div>
        <h3 style="margin:0 0 6px 0">Ultimate Swap & VM Memory Planner</h3>
        <div class="muted">Accurate swap sizing, recommendations, zswap & swappiness tips — designed for cloud admins.</div>
      </div>
      <div class="pill">BitByte IT Solutions</div>
    </div>
  </div>

  <div class="swap-card">
    <div class="grid">
      <div>
        <label>RAM Size (GB)</label>
        <input type="number" id="ramGB" min="0.25" step="0.25" value="8">
      </div>
      <div>
        <label>Disk Size (GB)</label>
        <input type="number" id="diskGB" min="1" step="1" value="100">
      </div>
      <div>
        <label>Workload Profile</label>
        <select id="profile">
          <option value="light">Light — Web/App server (low memory spikes)</option>
          <option value="medium">Medium — File/App server</option>
          <option value="heavy">Heavy — Database / Analytics</option>
          <option value="db">Database — Production DB</option>
          <option value="vmhost">VM Host — Hypervisor with ballooning</option>
          <option value="hibernation">Hibernation — Desktop / Laptop</option>
          <option value="bigdata">Big Data / In-memory</option>
        </select>
      </div>
      <div>
        <label>Operating System</label>
        <select id="os">
          <option value="linux">Linux</option>
          <option value="windows">Windows Server</option>
          <option value="vmware">VMware Host</option>
        </select>
      </div>
    </div>

    <div class="advanced">
      <div>
        <label>Advanced: Minimum Swap (GB)</label>
        <input type="number" id="minSwap" class="small" min="0" step="0.25" value="1">
      </div>
      <div>
        <label>Advanced: Max % of Disk for Swap</label>
        <input type="number" id="diskCapPct" class="small" min="5" max="80" step="1" value="50">
      </div>
      <div>
        <label>Swappiness (0–100)</label>
        <input type="number" id="swappiness" class="small" min="0" max="100" step="1" value="60">
      </div>
    </div>

    <div style="margin-top:12px;">
      <div style="display:flex; gap:8px; flex-wrap:wrap;">
        <button class="btn" id="calcBtn">Calculate</button>
        <button class="btn btn-ghost" id="advancedToggle">Explain Recommendations</button>
        <button class="btn btn-ghost" id="exportCSV">Export CSV</button>
        <button class="btn btn-ghost" id="copyBtn">Copy CLI</button>
      </div>
    </div>
  </div>

  <div class="swap-card" id="resultCard" style="display:none;">
    <div class="row">
      <div class="stat">
        <div class="muted">Recommendation:</div>
        <div class="result" id="swapResult">—</div>
      </div>
      <div style="margin-left:auto; text-align:right;">
        <div class="muted">Percent of Disk used</div>
        <div class="chart" style="width:220px;">
          <div class="bar" id="diskBar"></div>
        </div>
      </div>
    </div>

    <div style="margin-top:12px;" id="breakdown"></div>

    <div style="margin-top:12px;">
      <div class="muted">Quick CLI (Linux)</div>
      <pre class="cmd" id="linuxCmd"></pre>

      <div class="muted" style="margin-top:8px">Windows Guidance</div>
      <pre class="cmd" id="windowsCmd"></pre>

      <div class="muted" style="margin-top:8px">VMware Notes</div>
      <pre class="cmd" id="vmwareNotes"></pre>
    </div>

    <div class="footer-note" id="explainArea" style="display:none"></div>
  </div>
</div>

<script>
(function(){
  // Utility helpers
  const $ = id => document.getElementById(id);
  const clamp = (v, a, b) => Math.max(a, Math.min(b, v));

  // Core swap logic
  function baseSwapByRam(ram){
    // using conservative production rules
    if (ram <= 2) return ram * 2;
    if (ram <= 8) return ram + 2;
    if (ram <= 64) return Math.max(4, ram * 0.5);
    // huge RAM -> keep small swap unless hibernation required
    return 4;
  }

  function profileMultiplier(profile){
    switch(profile){
      case 'light': return 1.0;
      case 'medium': return 1.15;
      case 'heavy': return 1.4;
      case 'db': return 1.5;
      case 'vmhost': return 1.25;
      case 'hibernation': return 1.0; // hibernation handled specially
      case 'bigdata': return 1.6;
      default: return 1.0;
    }
  }

  function calculate(){
    const ram = parseFloat($('ramGB').value) || 0;
    const disk = parseFloat($('diskGB').value) || 0;
    const profile = $('profile').value;
    const os = $('os').value;
    const minSwap = parseFloat($('minSwap').value) || 0;
    const diskCapPct = parseFloat($('diskCapPct').value) || 50;
    const swappiness = parseInt($('swappiness').value) || 60;

    // base
    let swap = baseSwapByRam(ram);

    // handle hibernation: swap >= RAM
    if(profile === 'hibernation') swap = Math.max(swap, ram);

    // apply profile multiplier
    swap = swap * profileMultiplier(profile);

    // rounding and floor
    swap = Math.round(swap * 4) / 4; // quarter GB resolution

    // enforce min
    if(swap < minSwap) swap = minSwap;

    // ensure swap does not exceed diskCapPct of disk
    const maxAllowed = (disk * (diskCapPct/100));
    if (disk > 0 && swap > maxAllowed) {
      swap = Math.round(maxAllowed * 4) / 4;
    }

    // safety: never recommend swap > disk
    if (swap > disk) swap = Math.floor(disk * 0.9 * 4)/4;

    // extra recommendations
    const useZswap = (os === 'linux' && ram >= 2);
    const recommendPartition = (os === 'vmware' || profile==='vmhost') ? 'swapfile (guest) + host-level swap enabled' : 'swapfile preferred unless you require dedicated swap partition';
    let swappinessRec = swappiness;
    if(profile === 'db') swappinessRec = Math.min(10, swappiness); // DB want low swappiness
    if(profile === 'light') swappinessRec = Math.min(30, swappiness);

    return {
      ram, disk, profile, os, swap, maxAllowed, useZswap, recommendPartition, swappinessRec
    };
  }

  // UI update
  function render(){
    const r = calculate();
    $('resultCard').style.display = 'block';
    $('swapResult').innerText = `${r.swap} GB (for ${r.ram} GB RAM)`;
    // disk bar
    let pct = r.disk>0 ? Math.round((r.swap / r.disk) * 100) : 0;
    pct = Math.min(100, pct);
    $('diskBar').style.width = pct + '%';
    $('diskBar').setAttribute('title', pct + '% of disk');

    // breakdown
    const breakdown = `
      <div class="muted">How we arrived:</div>
      <div class="explain">
        Base rule based on RAM: <strong>${baseSwapByRam(r.ram)} GB</strong>.<br>
        Profile multiplier (${r.profile}): <strong>${profileMultiplier(r.profile)}×</strong>.<br>
        Minimum enforced: <strong>${$('minSwap').value} GB</strong>. Disk cap: <strong>${$('diskCapPct').value}%</strong> (${r.maxAllowed} GB).
      </div>
    `;
    $('breakdown').innerHTML = breakdown;

    // linux commands
    const swapfileSize = r.swap;
    const linuxCmd = `# Create ${swapfileSize}GB swapfile (Linux)
sudo fallocate -l ${swapfileSize}G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
# Persist in /etc/fstab:
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
# Tune swappiness:
sudo sysctl vm.swappiness=${r.swappinessRec}
echo 'vm.swappiness=${r.swappinessRec}' | sudo tee -a /etc/sysctl.conf`;

    $('linuxCmd').innerText = linuxCmd;

    // windows guidance
    const windowsCmd = `# Windows Server (pagefile) guidance:
1) Use recommended pagefile size in System Properties -> Advanced -> Performance -> Virtual Memory.
2) For ${r.ram}GB RAM and ${r.swap}GB swap recommendation, set custom pagefile size:
   - Initial: ${Math.max(1, Math.floor(r.swap/2))} MB
   - Maximum: ${Math.ceil(r.swap*1024)} MB
3) Reboot may be required for pagefile size change to take effect.`;

    $('windowsCmd').innerText = windowsCmd;

    // vmware notes
    const vmwareNotes = `# VMware considerations:
- If host memory is overcommitted, ESXi may use host swap/VM swap (performance impact).
- Ensure VM swap file (.vswp) isn't placed on same slow datastore as VM disk heavy IO.
- Prefer adding RAM for thrashing conditions; swap is a last-resort buffer.
- Host-level swap policy: consider setting reserved memory vs relying on swap.`;

    $('vmwareNotes').innerText = vmwareNotes;

    // explain area (toggleable)
    const explainHTML = `
      <strong>Recommendations:</strong><br>
      • Swap: <strong>${r.swap} GB</strong>.<br>
      • Swappiness (sysctl): <strong>${r.swappinessRec}</strong> — lower for DB workloads to avoid swapping (hint: set 1–10).<br>
      • zswap: ${r.useZswap ? '<strong>Enable zswap</strong> (saves io & reduces pressure)' : 'Optional'}<br>
      • Swap type: <strong>${r.recommendPartition}</strong>.<br>
      • If you need hibernation: swap must be >= RAM.<br>
      • If swap usage becomes constant, <em>add physical RAM</em> — swap is a safety buffer, not a performance fix.
    `;
    $('explainArea').innerHTML = explainHTML;
  }

  // Export CSV
  function exportCSV(){
    const r = calculate();
    const rows = [
      ['ram_gb','disk_gb','profile','os','swap_gb','disk_cap_pct','swappiness'],
      [r.ram, r.disk, r.profile, r.os, r.swap, $('diskCapPct').value, r.swappinessRec]
    ];
    const csv = rows.map(r=>r.join(',')).join('\n');
    const blob = new Blob([csv], {type:'text/csv'});
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url; a.download = 'swap-recommendation.csv'; a.click();
    URL.revokeObjectURL(url);
  }

  // Copy CLI
  function copyCLI(){
    const txt = $('linuxCmd').innerText + "\n\n" + $('windowsCmd').innerText;
    navigator.clipboard.writeText(txt).then(()=> {
      alert('CLI commands copied to clipboard');
    }, ()=> alert('Unable to copy. Please select and copy manually.'));
  }

  // Event bindings
  $('calcBtn').addEventListener('click', render);
  $('exportCSV').addEventListener('click', exportCSV);
  $('copyBtn').addEventListener('click', copyCLI);
  $('advancedToggle').addEventListener('click', function(){
    const e = $('explainArea');
    e.style.display = e.style.display === 'none' ? 'block' : 'none';
  });

  // initial render
  render();

})();
</script>
<!-- END: Ultimate Swap & VM Memory Planner -->
