JustPaste.it

Calc code

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Revenue Loss Calculator</title>
<link href="https://justpaste.it/redirect/k93j4/https%3A%2F%2Ffonts.googleapis.com%2Fcss2%3Ffamily%3DDM%2BSans%3Awght%40300%3B400%3B500%3B600%3B700%26amp%3Bfamily%3DDM%2BSerif%2BDisplay%26amp%3Bdisplay%3Dswap" rel="nofollow">
<style>
  *, *::before, *::after { box-sizing: border-box; 0; padding: 0; }

  :root {
    --navy: #0a1f5c;
    --blue: #1347d4;
    --mid-blue: #4a90e2;
    --light-blue: #93bff0;
    --bg: transparent;
    --card: #ffffff;
    --text: #1a2340;
    --muted: #6b7a9e;
    --border: #dde6f5;
    --page-bg: #f0f4fd;
  }

  body {
    'DM Sans', sans-serif;
    background: transparent;
    color: var(--text);
    padding: 0;
    0;
  }

  .wrapper {
    width: 100%;
  }

  .header {
    24px;
  }

  .header h1 {
    'DM Serif Display', serif;
    font-size: 30px;
    color: var(--navy);
    letter-spacing: -0.5px;
  }

  .header p {
    color: var(--muted);
    font-size: 14px;
    5px;
  }

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

  /* LEFT PANEL */
  .left-panel {
    background: var(--card);
    border-radius: 18px;
    padding: 28px;
    border: 1px solid var(--border);
    box-shadow: 0 2px 16px rgba(10,31,92,0.07);
  }

  .section-label {
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 1.5px;
    text-transform: uppercase;
    color: var(--blue);
    18px;
  }

  .field { 16px; }

  .field label {
    display: block;
    font-size: 12px;
    font-weight: 600;
    color: var(--navy);
    7px;
  }

  .input-wrap { position: relative; }

  .input-wrap .prefix {
    position: absolute;
    left: 12px;
    top: 50%;
    transform: translateY(-50%);
    font-size: 14px;
    font-weight: 600;
    color: var(--muted);
    pointer-events: none;
  }

  .input-wrap .suffix {
    position: absolute;
    right: 12px;
    top: 50%;
    transform: translateY(-50%);
    font-size: 12px;
    font-weight: 600;
    color: var(--muted);
    pointer-events: none;
  }

  .field input {
    width: 100%;
    padding: 11px 36px 11px 26px;
    border: 1.5px solid var(--border);
    border-radius: 10px;
    font-size: 14px;
    'DM Sans', sans-serif;
    color: var(--text);
    background: #f8faff;
    transition: border-color 0.2s, box-shadow 0.2s;
    -moz-appearance: textfield;
  }

  .field input::-webkit-outer-spin-button,
  .field input::-webkit-inner-spin-button { -webkit-appearance: none; }

  .field input:focus {
    outline: none;
    border-color: var(--blue);
    box-shadow: 0 0 0 3px rgba(19,71,212,0.1);
    background: #fff;
  }

  .no-prefix .field input,
  .field input.no-pfx { padding-left: 12px; }

  .divider {
    height: 1px;
    background: var(--border);
    20px 0;
  }

  .calc-btn {
    width: 100%;
    padding: 13px;
    background: linear-gradient(135deg, #1347d4, #0a2fa8);
    border: none;
    border-radius: 10px;
    color: #fff;
    'DM Sans', sans-serif;
    font-size: 14px;
    font-weight: 700;
    cursor: pointer;
    transition: transform 0.15s, box-shadow 0.15s;
    box-shadow: 0 4px 16px rgba(19,71,212,0.3);
  }

  .calc-btn:hover {
    transform: translateY(-1px);
    box-shadow: 0 6px 20px rgba(19,71,212,0.4);
  }

  /* RIGHT PANEL */
  .right-panel {
    display: flex;
    flex-direction: column;
    gap: 16px;
  }

  /* TOTAL LOSS CARD */
  .total-card {
    background: linear-gradient(135deg, #0a1f5c 0%, #1347d4 100%);
    border-radius: 18px;
    padding: 28px 32px;
    color: white;
    position: relative;
    overflow: hidden;
  }

  .total-card::before {
    content: '';
    position: absolute;
    top: -50px; right: -50px;
    width: 200px; height: 200px;
    background: rgba(255,255,255,0.05);
    border-radius: 50%;
  }

  .total-card .eyebrow {
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 2px;
    text-transform: uppercase;
    opacity: 0.7;
    8px;
  }

  .total-card .amount {
    'DM Serif Display', serif;
    font-size: 48px;
    font-weight: 400;
    1;
    6px;
    position: relative;
    z-index: 1;
  }

  .total-card .sub {
    font-size: 13px;
    opacity: 0.7;
  }

  /* CHART CARD */
  .viz-card {
    background: var(--card);
    border-radius: 18px;
    padding: 24px 28px;
    border: 1px solid var(--border);
    box-shadow: 0 2px 16px rgba(10,31,92,0.06);
  }

  .viz-card .card-title {
    font-size: 13px;
    font-weight: 700;
    color: var(--navy);
    20px;
  }

  .chart-row {
    display: flex;
    gap: 28px;
    align-items: center;
  }

  /* DONUT — big */
  .donut-wrap {
    position: relative;
    width: 280px;
    height: 280px;
    flex-shrink: 0;
  }

  #donutSvg {
    width: 280px;
    height: 280px;
    overflow: visible;
  }

  .donut-center {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    text-align: center;
    pointer-events: none;
  }

  .donut-center span {
    display: block;
    font-size: 10px;
    color: var(--muted);
    font-weight: 600;
    letter-spacing: 1px;
    text-transform: uppercase;
  }

  .donut-center strong {
    display: block;
    'DM Serif Display', serif;
    font-size: 24px;
    color: var(--navy);
    1.2;
    2px;
  }

  /* LEGEND */
  .legend {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 18px;
  }

  .legend-item {
    display: flex;
    align-items: center;
    gap: 12px;
  }

  .legend-dot {
    width: 11px;
    height: 11px;
    border-radius: 3px;
    flex-shrink: 0;
  }

  .legend-dot.d1 { background: var(--navy); }
  .legend-dot.d2 { background: var(--mid-blue); }
  .legend-dot.d3 { background: var(--light-blue); }

  .legend-label {
    flex: 1;
    font-size: 12px;
    font-weight: 500;
    color: var(--muted);
  }

  .legend-values { text-align: right; }

  .legend-values .amt {
    display: block;
    font-size: 14px;
    font-weight: 700;
    color: var(--navy);
  }

  .legend-values .pct {
    display: block;
    font-size: 11px;
    font-weight: 600;
    color: var(--muted);
  }

  /* BREAKDOWN CARDS */
  .breakdown-row {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 12px;
  }

  .breakdown-card {
    background: var(--card);
    border-radius: 14px;
    padding: 18px;
    border: 1px solid var(--border);
    box-shadow: 0 2px 8px rgba(10,31,92,0.04);
    position: relative;
    overflow: hidden;
  }

  .breakdown-card::before {
    content: '';
    position: absolute;
    top: 0; left: 0; right: 0;
    height: 3px;
    border-radius: 14px 14px 0 0;
  }

  .breakdown-card.c1::before { background: var(--navy); }
  .breakdown-card.c2::before { background: var(--mid-blue); }
  .breakdown-card.c3::before { background: var(--light-blue); }

  .bc-label {
    font-size: 11px;
    font-weight: 600;
    color: var(--muted);
    8px;
  }

  .bc-amount {
    'DM Serif Display', serif;
    font-size: 22px;
    color: var(--navy);
    4px;
  }

  .bc-pct {
    font-size: 11px;
    font-weight: 600;
    color: var(--muted);
    background: var(--page-bg);
    display: inline-block;
    padding: 2px 7px;
    border-radius: 20px;
  }

  /* TIP */
  .tip-box {
    background: #eef5ff;
    border-radius: 12px;
    padding: 16px 20px;
    border: 1px solid #d0e4ff;
    display: flex;
    align-items: center;
    gap: 14px;
  }

  .tip-icon {
    width: 32px;
    height: 32px;
    background: var(--blue);
    border-radius: 9px;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
  }

  .tip-icon svg { width: 16px; height: 16px; }

  .tip-text strong {
    display: block;
    font-size: 12px;
    font-weight: 700;
    color: var(--navy);
    2px;
  }

  .tip-text p {
    font-size: 12px;
    color: var(--muted);
    1.5;
  }

  /* SVG label text */
  .seg-label {
    'DM Sans', sans-serif;
    font-size: 13px;
    font-weight: 700;
    fill: #ffffff;
    text-anchor: middle;
    dominant-baseline: middle;
    pointer-events: none;
  }

  @media (max-width: 900px) {
    .grid { grid-template-columns: 1fr; }
    .breakdown-row { grid-template-columns: 1fr; }
    .chart-row { flex-direction: column; }
    .total-card .amount { font-size: 36px; }
  }
</style>
</head>
<body>
<div class="wrapper">
  <div class="header">
    <h1>Revenue Loss Calculator</h1>
    <p>Estimate potential revenue loss due to claims denials and payment delays.</p>
  </div>

  <div class="grid">
    <!-- LEFT -->
    <div class="left-panel">
      <div class="section-label">Input Parameters</div>

      <div class="field">
        <label>Annual Revenue</label>
        <div class="input-wrap">
          <span class="prefix">$</span>
          <input type="number" id="revenue" value="50000000" min="0">
        </div>
      </div>

      <div class="field">
        <label>Claim Denial Rate</label>
        <div class="input-wrap">
          <input type="number" id="denial" value="10" min="0" max="100" style="padding-left:12px;padding-right:32px;">
          <span class="suffix">%</span>
        </div>
      </div>

      <div class="field">
        <label>Days in Accounts Receivable</label>
        <div class="input-wrap">
          <input type="number" id="days" value="60" min="0" style="padding-left:12px;">
        </div>
      </div>

      <div class="field">
        <label>Claims Write-Off Rate</label>
        <div class="input-wrap">
          <input type="number" id="writeoff" value="2" min="0" max="100" style="padding-left:12px;padding-right:32px;">
          <span class="suffix">%</span>
        </div>
      </div>

      <div class="divider"></div>
      <button class="calc-btn" onclick="calculateRevenueLoss()">Calculate Revenue Loss</button>
    </div>

    <!-- RIGHT -->
    <div class="right-panel">

      <div class="total-card">
        <div class="eyebrow">Estimated Revenue Loss</div>
        <div class="amount" id="totalLoss">$64,109,589</div>
        <div class="sub">Potential Annual Revenue Loss</div>
      </div>

      <div class="viz-card">
        <div class="card-title">Loss Breakdown</div>
        <div class="chart-row">

          <div class="donut-wrap">
            <!-- SVG viewBox 280x280, r=100, stroke-width=52 => inner hole ~48px radius -->
            <svg id="donutSvg" viewBox="0 0 280 280" xmlns="http://www.w3.org/2000/svg">
              <!-- Gap ring background -->
              <circle cx="140" cy="140" r="100" fill="none" stroke="#f0f4fd" stroke-width="54"/>
              <!-- Segments -->
              <circle id="seg1" cx="140" cy="140" r="100" fill="none" stroke="#0a1f5c" stroke-width="50"
                stroke-dasharray="0 628.318" stroke-dashoffset="157.08" stroke-linecap="butt"/>
              <circle id="seg2" cx="140" cy="140" r="100" fill="none" stroke="#4a90e2" stroke-width="50"
                stroke-dasharray="0 628.318" stroke-dashoffset="157.08" stroke-linecap="butt"/>
              <circle id="seg3" cx="140" cy="140" r="100" fill="none" stroke="#93bff0" stroke-width="50"
                stroke-dasharray="0 628.318" stroke-dashoffset="157.08" stroke-linecap="butt"/>
              <!-- Percentage labels on segments -->
              <text id="lbl1" class="seg-label" x="140" y="140">—</text>
              <text id="lbl2" class="seg-label" x="140" y="140">—</text>
              <text id="lbl3" class="seg-label" x="140" y="140">—</text>
            </svg>
            <div class="donut-center">
              <span>Total Loss</span>
              <strong id="centerLoss">$64.11M</strong>
            </div>
          </div>

          <div class="legend">
            <div class="legend-item">
              <div class="legend-dot d1"></div>
              <div class="legend-label">Denied Claims</div>
              <div class="legend-values">
                <span class="amt" id="deniedLoss">$50,000,000</span>
                <span class="pct" id="deniedPct">78.0%</span>
              </div>
            </div>
            <div class="legend-item">
              <div class="legend-dot d2"></div>
              <div class="legend-label">Delayed Payments</div>
              <div class="legend-values">
                <span class="amt" id="delayLoss">$10,646,589</span>
                <span class="pct" id="delayPct">16.6%</span>
              </div>
            </div>
            <div class="legend-item">
              <div class="legend-dot d3"></div>
              <div class="legend-label">Write-Offs</div>
              <div class="legend-values">
                <span class="amt" id="writeLoss">$3,463,000</span>
                <span class="pct" id="writePct">5.4%</span>
              </div>
            </div>
          </div>
        </div>
      </div>

      <div class="breakdown-row">
        <div class="breakdown-card c1">
          <div class="bc-label">Denied Claims Loss</div>
          <div class="bc-amount" id="bc1">$50.0M</div>
          <span class="bc-pct" id="bcp1">78.0%</span>
        </div>
        <div class="breakdown-card c2">
          <div class="bc-label">Delayed Payments Loss</div>
          <div class="bc-amount" id="bc2">$10.6M</div>
          <span class="bc-pct" id="bcp2">16.6%</span>
        </div>
        <div class="breakdown-card c3">
          <div class="bc-label">Write-Off Loss</div>
          <div class="bc-amount" id="bc3">$3.4M</div>
          <span class="bc-pct" id="bcp3">5.4%</span>
        </div>
      </div>

      <div class="tip-box">
        <div class="tip-icon">
          <svg viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">
            <circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/>
          </svg>
        </div>
        <div class="tip-text">
          <strong>Take Action, Improve Results</strong>
          <p>Reducing denial rates, accelerating collections, and minimizing write-offs can significantly improve your revenue cycle performance.</p>
        </div>
      </div>

    </div>
  </div>
</div>

<script>
  // r=100, circumference = 2*pi*100
  const R = 100;
  const CX = 140, CY = 140;
  const CIRC = 2 * Math.PI * R; // 628.318

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

  function fmtM(num) {
    if (Math.abs(num) >= 1e6) return '$' + (num / 1e6).toFixed(1) + 'M';
    if (Math.abs(num) >= 1e3) return '$' + (num / 1e3).toFixed(1) + 'K';
    return '$' + Math.round(num).toLocaleString();
  }

  // Given start angle and arc fraction (0-1), return the midpoint (x,y) at radius r
  function midpoint(startFrac, arcFrac, r) {
    const midAngle = (startFrac + arcFrac / 2) * 2 * Math.PI - Math.PI / 2;
    return {
      x: CX + r * Math.cos(midAngle),
      y: CY + r * Math.sin(midAngle)
    };
  }

  function setSegment(segEl, lblEl, dash, offset, pct, startFrac) {
    segEl.setAttribute('stroke-dasharray', `${dash} ${CIRC - dash}`);
    segEl.setAttribute('stroke-dashoffset', `${CIRC / 4 - offset}`);

    // Label at midpoint of the arc, on the stroke radius (100)
    const arcFrac = pct / 100;
    if (arcFrac > 0.05) {
      const pos = midpoint(startFrac, arcFrac, R);
      lblEl.setAttribute('x', pos.x);
      lblEl.setAttribute('y', pos.y);
      lblEl.textContent = pct.toFixed(1) + '%';
      lblEl.style.display = '';
    } else {
      lblEl.style.display = 'none';
    }
  }

  function calculateRevenueLoss() {
    const revenue  = parseFloat(document.getElementById('revenue').value)  || 0;
    const denial   = parseFloat(document.getElementById('denial').value)   || 0;
    const days     = parseFloat(document.getElementById('days').value)     || 0;
    const writeoff = parseFloat(document.getElementById('writeoff').value) || 0;

    const deniedLoss  = revenue * (denial / 100);
    const delayedLoss = (revenue * 0.12) * (days / 365);
    const writeLoss   = revenue * (writeoff / 100);
    const totalLoss   = deniedLoss + delayedLoss + writeLoss;

    const p1 = totalLoss > 0 ? (deniedLoss  / totalLoss) * 100 : 0;
    const p2 = totalLoss > 0 ? (delayedLoss / totalLoss) * 100 : 0;
    const p3 = totalLoss > 0 ? (writeLoss   / totalLoss) * 100 : 0;

    // Update text
    document.getElementById('totalLoss').textContent  = fmt(totalLoss);
    document.getElementById('centerLoss').textContent = fmtM(totalLoss);
    document.getElementById('deniedLoss').textContent = fmt(deniedLoss);
    document.getElementById('delayLoss').textContent  = fmt(delayedLoss);
    document.getElementById('writeLoss').textContent  = fmt(writeLoss);
    document.getElementById('deniedPct').textContent  = p1.toFixed(1) + '%';
    document.getElementById('delayPct').textContent   = p2.toFixed(1) + '%';
    document.getElementById('writePct').textContent   = p3.toFixed(1) + '%';
    document.getElementById('bc1').textContent  = fmtM(deniedLoss);
    document.getElementById('bc2').textContent  = fmtM(delayedLoss);
    document.getElementById('bc3').textContent  = fmtM(writeLoss);
    document.getElementById('bcp1').textContent = p1.toFixed(1) + '%';
    document.getElementById('bcp2').textContent = p2.toFixed(1) + '%';
    document.getElementById('bcp3').textContent = p3.toFixed(1) + '%';

    // Donut segments
    // dashoffset trick: offset = CIRC/4 - (sum of previous arcs)
    // so seg1 starts at top (12 o'clock)
    const d1 = (p1 / 100) * CIRC;
    const d2 = (p2 / 100) * CIRC;
    const d3 = (p3 / 100) * CIRC;

    const seg1 = document.getElementById('seg1');
    const seg2 = document.getElementById('seg2');
    const seg3 = document.getElementById('seg3');
    const lbl1 = document.getElementById('lbl1');
    const lbl2 = document.getElementById('lbl2');
    const lbl3 = document.getElementById('lbl3');

    // Segment 1: starts at 0 (top)
    seg1.setAttribute('stroke-dasharray', `${d1} ${CIRC - d1}`);
    seg1.setAttribute('stroke-dashoffset', `${CIRC / 4}`);

    // Segment 2: starts after segment 1
    seg2.setAttribute('stroke-dasharray', `${d2} ${CIRC - d2}`);
    seg2.setAttribute('stroke-dashoffset', `${CIRC / 4 - d1}`);

    // Segment 3: starts after segment 1+2
    seg3.setAttribute('stroke-dasharray', `${d3} ${CIRC - d3}`);
    seg3.setAttribute('stroke-dashoffset', `${CIRC / 4 - d1 - d2}`);

    // Labels — placed at arc midpoint on the stroke path (r=100)
    const f1 = 0;
    const f2 = p1 / 100;
    const f3 = (p1 + p2) / 100;

    function placeLabel(lbl, startFrac, arcFrac) {
      if (arcFrac > 0.06) {
        const midAngle = (startFrac + arcFrac / 2) * 2 * Math.PI - Math.PI / 2;
        const x = CX + R * Math.cos(midAngle);
        const y = CY + R * Math.sin(midAngle);
        lbl.setAttribute('x', x);
        lbl.setAttribute('y', y);
        lbl.textContent = (arcFrac * 100).toFixed(1) + '%';
        lbl.style.display = '';
      } else {
        lbl.style.display = 'none';
      }
    }

    placeLabel(lbl1, f1, p1 / 100);
    placeLabel(lbl2, f2, p2 / 100);
    placeLabel(lbl3, f3, p3 / 100);
  }

  document.querySelectorAll('input').forEach(input => {
    input.addEventListener('input', calculateRevenueLoss);
  });

  calculateRevenueLoss();
</script>
</body>
</html>