羽毛球计分器

效果图

羽毛球计分器

羽毛球计分器

HTML代码

<!doctype html>
<html lang="zh-CN">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover, user-scalable=no" />
  <title>羽毛球计分板</title>

  <style>
    :root{
      --bg:#ffffff;
      --card:#ffffff;
      --text:#0f172a;
      --muted:#64748b;
      --line:rgba(15, 23, 42, .10);
      --shadow: 0 10px 30px rgba(15,23,42,.08);
      --radius: 18px;

      --safe-top: env(safe-area-inset-top, 0px);
      --safe-bottom: env(safe-area-inset-bottom, 0px);
      --safe-left: env(safe-area-inset-left, 0px);
      --safe-right: env(safe-area-inset-right, 0px);
    }

    *{ box-sizing:border-box; }
    html, body{ height:100%; }
    body{
      margin:0;
      background: var(--bg);
      color: var(--text);
      font-family: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Arial, "PingFang SC", "Microsoft YaHei", sans-serif;
      -webkit-tap-highlight-color: transparent;
      touch-action: manipulation;
      overflow: hidden;
    }

    .hidden{ display:none !important; }

    .app{
      height: 100vh;
      width: 100vw;
      padding: calc(12px + var(--safe-top)) calc(12px + var(--safe-right)) calc(12px + var(--safe-bottom)) calc(12px + var(--safe-left));
      display:grid;
      grid-template-rows: auto 1fr auto;
      gap: 12px;
    }

    /* Top bar */
    .topbar{
      display:flex;
      align-items:center;
      justify-content:space-between;
      gap: 12px;
      padding: 10px 12px;
      border: 1px solid var(--line);
      border-radius: var(--radius);
      box-shadow: var(--shadow);
      background: var(--card);
      min-width: 0;
    }
    .brand{
      min-width:0;
      display:flex;
      flex-direction:column;
      gap:2px;
    }
    .brand strong{
      font-size: 14px;
      font-weight: 900;
      letter-spacing: .6px;
      white-space: nowrap;
      overflow:hidden;
      text-overflow: ellipsis;
      max-width: 72vw;
    }
    .brand span{
      font-size: 12px;
      color: var(--muted);
      white-space: nowrap;
      overflow:hidden;
      text-overflow: ellipsis;
      max-width: 72vw;
    }

    .actions{
      display:flex;
      gap: 8px;
      flex-wrap: wrap;
      justify-content:flex-end;
    }

    .btn{
      border: 1px solid var(--line);
      background: #fff;
      color: var(--text);
      border-radius: 14px;
      padding: 10px 12px;
      font-size: 13px;
      font-weight: 850;
      cursor:pointer;
      user-select:none;
      white-space: nowrap;
    }
    .btn:active{ transform: translateY(1px); }
    .btn.muted{ color: var(--muted); }

    /* Board */
    .board{
      min-height: 0;
      display:grid;
      grid-template-columns: 1fr 1fr;
      gap: 12px;
    }
    @media (max-width: 760px) and (orientation: portrait){
      .board{ grid-template-columns: 1fr; }
    }

    .side{
      min-height: 0;
      border: 1px solid var(--line);
      border-radius: var(--radius);
      box-shadow: var(--shadow);
      background: #fff;
      padding: 12px;
      display:grid;
      grid-template-rows: auto 1fr auto;
      gap: 12px;
    }

    .nameRow{
      display:flex;
      align-items:flex-start;
      justify-content:space-between;
      gap: 10px;
      min-width:0;
    }
    .teamName{
      margin: 0;
      font-size: clamp(16px, 2.2vw, 22px);
      font-weight: 950;
      letter-spacing: .2px;
      white-space: nowrap;
      overflow:hidden;
      text-overflow: ellipsis;
      max-width: 70%;
    }
    .hint{
      font-size: 12px;
      color: var(--muted);
      white-space: nowrap;
      user-select:none;
    }

    .scoreTap{
      border: 1px solid var(--line);
      border-radius: 16px;
      background: linear-gradient(180deg, rgba(2,6,23,.02), rgba(2,6,23,.00));
      display:grid;
      place-items:center;
      user-select:none;
      cursor: pointer;
      position: relative;
      overflow:hidden;
    }
    .scoreTap:active{
      background: linear-gradient(180deg, rgba(2,6,23,.04), rgba(2,6,23,.00));
    }
    .score{
      font-size: clamp(84px, 14vw, 180px);
      font-weight: 1000;
      letter-spacing: -2px;
      line-height: 1;
    }
    .tapTip{
      position:absolute;
      bottom: 10px;
      left: 12px;
      right: 12px;
      display:flex;
      align-items:center;
      justify-content:space-between;
      font-size: 12px;
      color: var(--muted);
      pointer-events:none;
    }

    .controls{
      display:grid;
      grid-template-columns: 1fr 1fr;
      gap: 10px;
    }
    .smallBtn{
      height: 52px;
      border-radius: 16px;
      border: 1px solid var(--line);
      background: #fff;
      font-size: 18px;
      font-weight: 950;
      cursor:pointer;
      user-select:none;
    }
    .smallBtn:active{ transform: translateY(1px); }
    .smallBtn.sub{ color: var(--muted); }

    /* Bottom bar */
    .bottombar{
      display:flex;
      align-items:center;
      justify-content:space-between;
      gap: 12px;
      padding: 10px 12px;
      border: 1px solid var(--line);
      border-radius: var(--radius);
      box-shadow: var(--shadow);
      background: #fff;
      min-width: 0;
    }
    .status{
      font-size: 12px;
      color: var(--muted);
      white-space: nowrap;
      overflow:hidden;
      text-overflow: ellipsis;
      max-width: 72vw;
    }

    /* Overlay (Name Entry / Rename) */
    .overlay{
      position: fixed;
      inset: 0;
      background: rgba(15,23,42,.38);
      display:grid;
      place-items:center;
      padding: 16px;
      z-index: 50;
    }
    .modal{
      width: min(520px, 100%);
      background: #fff;
      border: 1px solid var(--line);
      border-radius: 20px;
      box-shadow: 0 18px 60px rgba(15,23,42,.14);
      padding: 16px;
    }
    .modal h3{
      margin: 0 0 6px 0;
      font-size: 16px;
      font-weight: 1000;
    }
    .modal p{
      margin: 0 0 14px 0;
      font-size: 12px;
      color: var(--muted);
      line-height: 1.6;
    }
    .grid{
      display:grid;
      grid-template-columns: 1fr 1fr;
      gap: 10px;
    }
    @media (max-width: 520px){
      .grid{ grid-template-columns: 1fr; }
    }
    .row{
      display:flex;
      flex-direction:column;
      gap: 6px;
    }
    .row label{
      font-size: 12px;
      color: var(--muted);
      font-weight: 850;
    }
    .row input{
      height: 42px;
      border-radius: 12px;
      border: 1px solid var(--line);
      background: