It looks like this is a web page, not a feed. I looked for a feed associated with this page, but couldn't find one. Please enter the address of your feed to validate.

Source: https://allateledel.eu

  1. <!DOCTYPE html>
  2. <html lang="ru">
  3. <head>
  4.  <meta charset="UTF-8" />
  5.  <title>👑 King WebApp</title>
  6.  <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
  7.  <script src="https://telegram.org/js/telegram-web-app.js"></script>
  8.  <script src="https://cdnjs.cloudflare.com/ajax/libs/lottie-web/5.12.2/lottie.min.js"></script>
  9.  <!-- QR library -->
  10.  <script src="https://cdn.jsdelivr.net/npm/qrcodejs@1.0.0/qrcode.min.js"></script>
  11.  
  12.  <style>
  13.    /* ========= THEME / TOKENS ========= */
  14.    :root{
  15.      --bg: var(--tg-theme-bg-color, #0e0e12);
  16.      --text: var(--tg-theme-text-color, #f7f7fb);
  17.      --muted: var(--tg-theme-hint-color, #9aa0a6);
  18.      --accent: var(--tg-theme-button-color, #8b5cf6);
  19.      --accent-text: var(--tg-theme-button-text-color, #ffffff);
  20.      --glass: rgba(255,255,255,.06);
  21.      --stroke: rgba(255,255,255,.08);
  22.      --radius: 16px;
  23.      --shadow-1: 0 10px 30px rgba(0,0,0,.35);
  24.      --shadow-2: 0 6px 18px rgba(0,0,0,.28);
  25.    }
  26.  
  27.    *{ box-sizing:border-box; -webkit-tap-highlight-color:transparent; }
  28.    html,body{ height:100%; }
  29.    body{
  30.      margin:0;
  31.      background: var(--bg);
  32.      color: var(--text);
  33.      font: 500 16px/1.4 "Inter","Segoe UI",system-ui,-apple-system,Roboto,Arial,sans-serif;
  34.      letter-spacing:.2px;
  35.      padding-bottom: calc(60px + 12px + env(safe-area-inset-bottom, 0px));
  36.    }
  37.  
  38.    /* ========= LIVING BACKGROUND ========= */
  39.    .bg{ position:fixed; inset:0; z-index:-2; overflow:hidden;
  40.      background:
  41.        radial-gradient(1200px 1200px at -10% -10%, rgba(139,92,246,.12), transparent 60%),
  42.        radial-gradient(1000px 1000px at 110% 10%, rgba(56,189,248,.12), transparent 60%),
  43.        radial-gradient(900px 900px at 80% 110%, rgba(236,72,153,.12), transparent 60%),
  44.        var(--bg);
  45.    }
  46.    .blob{ position:absolute; filter:blur(40px); opacity:.55; mix-blend-mode:screen; border-radius:50%; animation:float 18s ease-in-out infinite; }
  47.    .blob.b1{ width:380px;height:380px;background:#8b5cf6; left:-80px; top:-80px; animation-delay:0s; }
  48.    .blob.b2{ width:320px;height:320px;background:#22d3ee; right:-60px; top:10vh; animation-delay:4s; }
  49.    .blob.b3{ width:420px;height:420px;background:#f472b6; right:-120px; bottom:-120px; animation-delay:8s; }
  50.    @keyframes float{ 0%,100%{ transform:translate3d(0,0,0) scale(1); } 50%{ transform:translate3d(0,-20px,0) scale(1.06); } }
  51.    @media (prefers-reduced-motion: reduce){ .blob{ animation:none; } }
  52.  
  53.    /* ========= LAYOUT ========= */
  54.    .container{ max-width:480px; margin:0 auto; padding:18px 16px; }
  55.    .tabs .tab-content{ display:none; }
  56.    .tabs .tab-content.active{ display:block; }
  57.  
  58.    /* ========= GLASS ========= */
  59.    .glass{
  60.      background: var(--glass);
  61.      border:1px solid var(--stroke);
  62.      border-radius: var(--radius);
  63.      box-shadow: var(--shadow-2);
  64.      backdrop-filter: saturate(140%) blur(14px);
  65.      -webkit-backdrop-filter: saturate(140%) blur(14px);
  66.    }
  67.  
  68.    /* ========= PROFILE ========= */
  69.    .profile{ text-align:center; }
  70.    .profile-header{
  71.      display:flex; flex-direction:column; align-items:center; padding:18px 12px 8px;
  72.    }
  73.    .avatar-wrapper{
  74.      display:inline-grid; place-items:center; margin-bottom:0; --av:92px;
  75.      width:var(--av); height:var(--av); border-radius:50%;
  76.      background:linear-gradient(180deg, rgba(255,255,255,.16), rgba(255,255,255,.04)); padding:2px;
  77.    }
  78.    .avatar-wrapper img{
  79.      width:100%; height:100%; object-fit:cover; border-radius:50%;
  80.      box-shadow:0 0 0 2px rgba(255,255,255,.06), 0 8px 24px rgba(0,0,0,.35);
  81.      animation:pulse 2.6s ease-in-out infinite;
  82.    }
  83.    @keyframes pulse{
  84.      0%,100%{ box-shadow:0 0 0 2px rgba(255,255,255,.06), 0 8px 24px rgba(0,0,0,.35); transform:scale(1); }
  85.      50%{ box-shadow:0 0 0 2px rgba(139,92,246,.35), 0 12px 36px rgba(139,92,246,.25); transform:scale(1.02); }
  86.    }
  87.    .status-row{ width:100%; display:flex; justify-content:center; margin-top:10px; }
  88.    .status-badge{
  89.      position:static!important;
  90.      display:inline-flex; align-items:center; gap:8px;
  91.      padding:6px 12px; border-radius:999px; font-size:12px; font-weight:700;
  92.      background:linear-gradient(135deg, rgba(139,92,246,.25), rgba(56,189,248,.25));
  93.      border:1px solid rgba(255,255,255,.16);
  94.      box-shadow:inset 0 0 0 1px rgba(255,255,255,.06), 0 4px 18px rgba(0,0,0,.22);
  95.      margin:0!important;
  96.    }
  97.    .status-dot{ width:8px;height:8px;border-radius:50%;background:#22d3ee; box-shadow:0 0 10px #22d3ee; }
  98.    .title{ margin:10px 0 2px; font-size:20px; font-weight:800; letter-spacing:.2px; }
  99.    .muted{ color:var(--muted); font-size:13px; }
  100.  
  101.    .actions{ display:flex; justify-content:center; gap:12px; margin:14px 0 6px; }
  102.    .circle-btn{
  103.      width:56px;height:56px;border-radius:16px; display:grid; place-items:center;
  104.      background:linear-gradient(180deg, rgba(255,255,255,.08), rgba(255,255,255,.03));
  105.      border:1px solid var(--stroke); box-shadow:var(--shadow-1);
  106.      transition:transform .12s ease, background .2s ease, border-color .2s ease;
  107.    }
  108.    .circle-btn:active{ transform:scale(.98); }
  109.    .circle-btn svg{ width:24px;height:24px; stroke:var(--accent-text); }
  110.    .circle-btn:hover{ border-color:rgba(139,92,246,.55); background:linear-gradient(180deg, rgba(139,92,246,.18), rgba(255,255,255,.04)); }
  111.  
  112.    .balance-card{
  113.      margin:14px 0 18px; padding:16px 18px; display:flex; align-items:center; justify-content:space-between;
  114.      background:
  115.        linear-gradient(135deg, rgba(139,92,246,.22), rgba(56,189,248,.18)),
  116.        linear-gradient(180deg, rgba(255,255,255,.06), rgba(255,255,255,.03));
  117.      border:1px solid rgba(139,92,246,.35); border-radius:18px; box-shadow:0 10px 30px rgba(139,92,246,.18);
  118.    }
  119.    .balance-card small{ color:var(--muted); display:block; margin-bottom:4px; }
  120.    .balance-card strong{ font-size:22px; font-weight:800; letter-spacing:.3px; }
  121.  
  122.    /* ========= ACTIVITY ========= */
  123.    .activity-log{ padding:8px; }
  124.    .activity-item{
  125.      display:flex; align-items:center; gap:12px; padding:12px; margin:10px 0;
  126.      border-radius:14px; background:linear-gradient(180deg, rgba(255,255,255,.06), rgba(255,255,255,.03));
  127.      border:1px solid var(--stroke);
  128.    }
  129.    .activity-icon{
  130.      width:36px; height:36px; border-radius:12px; display:grid; place-items:center;
  131.      background:rgba(139,92,246,.18); color:#fff; flex:0 0 36px;
  132.    }
  133.    .activity-main{ display:flex; justify-content:space-between; align-items:center; gap:10px; width:100%; }
  134.    .number{ font-weight:600; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  135.    .date{ color:var(--muted); font-size:12px; white-space:nowrap; }
  136.  
  137.    /* ========= SECTIONS ========= */
  138.    .section-card{ padding:16px; border-radius:var(--radius); }
  139.    .center{ text-align:center; }
  140.    .lottie{ width:110px; height:110px; margin:4px auto 10px; }
  141.    .headline{ font:800 20px/1.15 inherit; margin:4px 0 6px; }
  142.    .subline{ font-size:14px; color:var(--muted); margin:0; }
  143.  
  144.    /* ========= TOP (под podium) ========= */
  145.    .top-three{ display:flex; justify-content:center; align-items:flex-end; gap:24px; margin:18px 0 8px; }
  146.    .podium{ text-align:center; position:relative; }
  147.    .podium img{ border-radius:50%; object-fit:cover; display:block; }
  148.  
  149.    .podium.p1 img{
  150.      width:108px; height:108px; border-radius:50%;
  151.      box-shadow:
  152.        0 0 0 4px rgba(255,215,0,1),
  153.        0 0 12px rgba(255,215,0,.85),
  154.        0 4px 8px rgba(0,0,0,.45),
  155.        0 14px 28px rgba(255,215,0,.25);
  156.    }
  157.    .podium.p2 img{
  158.      width:90px; height:90px; border-radius:50%;
  159.      box-shadow:
  160.        0 0 0 4px rgba(192,192,192,1),
  161.        0 0 12px rgba(192,192,192,.75),
  162.        0 4px 8px rgba(0,0,0,.45),
  163.        0 14px 28px rgba(192,192,192,.20);
  164.    }
  165.    .podium.p3 img{
  166.      width:90px; height:90px; border-radius:50%;
  167.      box-shadow:
  168.        0 0 0 4px rgba(205,127,50,1),
  169.        0 0 12px rgba(205,127,50,.75),
  170.        0 4px 8px rgba(0,0,0,.45),
  171.        0 14px 28px rgba(205,127,50,.20);
  172.    }
  173.  
  174.    .medal {
  175.      position: absolute;
  176.      top: -12px;
  177.      left: 50%;
  178.      transform: translateX(-50%);
  179.      width: 34px;
  180.      height: 34px;
  181.      border-radius: 50%;
  182.      display: grid;
  183.      place-items: center;
  184.  
  185.      font-weight: 900;
  186.      font-size: 14px;
  187.      letter-spacing: .2px;
  188.      color: #111;
  189.  
  190.      background: radial-gradient(circle at 30% 30%, #ffffff, #ffd700);
  191.      border: 1px solid rgba(255, 255, 255, .55);
  192.      box-shadow:
  193.        0 4px 12px rgba(255, 215, 0, .55),
  194.        inset 0 1px 2px rgba(255, 255, 255, .85),
  195.        0 0 0 4px rgba(255, 215, 0, .45);
  196.      backdrop-filter: blur(4px) saturate(150%);
  197.      -webkit-backdrop-filter: blur(4px) saturate(150%);
  198.      z-index: 2;
  199.    }
  200.    .podium.p2 .medal {
  201.      background: radial-gradient(circle at 30% 30%, #ffffff, #c0c0c0);
  202.      box-shadow:
  203.        0 4px 12px rgba(192, 192, 192, .55),
  204.        inset 0 1px 2px rgba(255, 255, 255, .85),
  205.        0 0 0 4px rgba(192, 192, 192, .45);
  206.    }
  207.    .podium.p3 .medal {
  208.      background: radial-gradient(circle at 30% 30%, #ffffff, #cd7f32);
  209.      box-shadow:
  210.        0 4px 12px rgba(205, 127, 50, .55),
  211.        inset 0 1px 2px rgba(255, 255, 255, .85),
  212.        0 0 0 4px rgba(205, 127, 50, .45);
  213.    }
  214.  
  215.    .top-list{ margin-top:8px; }
  216.    .row{ display:flex; align-items:center; gap:12px; padding:10px 12px; border-bottom:1px dashed rgba(255,255,255,.06); }
  217.    .row:last-child{ border-bottom:none; }
  218.    .row .ava{ width:42px;height:42px;border-radius:50%; object-fit:cover; border:2px solid rgba(139,92,246,.5); }
  219.    .row .nm{ font-weight:600; overflow:hidden; white-space:nowrap; text-overflow:ellipsis; }
  220.    .row .cnt{ margin-left:auto; color:var(--muted); font-size:13px; }
  221.  
  222.    /* ========= QUEUE ========= */
  223.    .queue-card{ padding:14px; border-radius:var(--radius); }
  224.    .queue-top{ display:flex; align-items:center; justify-content:space-between; margin-bottom:10px; }
  225.    .queue-name{ display:flex; align-items:center; gap:10px; font-weight:700; }
  226.    .queue-name img{ width:24px; height:24px; }
  227.    .queue-status{ font-weight:800; }
  228.    .queue-status.off{ color:#ef4444; } .queue-status.on{ color:#22c55e; }
  229.    .queue-stats{ display:grid; grid-template-columns:repeat(3,1fr); gap:10px; }
  230.    .q-item{ padding:10px 8px; border-radius:12px; text-align:center; border:1px solid var(--stroke); background:linear-gradient(180deg, rgba(255,255,255,.06), rgba(255,255,255,.03)); }
  231.    .q-item small{ display:block; color:var(--muted); margin-bottom:2px; }
  232.    .q-item strong{ font-size:16px; }
  233.  
  234.    /* ========= REF (QR вариант) ========= */
  235.    .sr-only{ position:absolute!important; width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0; }
  236.  
  237.    .ref-qr{
  238.      margin-top:12px; display:grid; grid-template-columns: 92px 1fr; gap:12px;
  239.      padding:12px; border-radius:14px; border:1px solid rgba(255,255,255,.12);
  240.      background: linear-gradient(180deg, rgba(255,255,255,.06), rgba(255,255,255,.03));
  241.    }
  242.    .qr-box{ width:92px; height:92px; border-radius:10px; overflow:hidden; background:#fff; display:grid; place-items:center; }
  243.    .qr-side{ display:grid; gap:8px; align-content:start; }
  244.    .chip{
  245.      display:flex; align-items:center; gap:8px;
  246.      padding:27px 12px; border-radius:12px;
  247.      background: rgba(255,255,255,.08);
  248.      border:1px solid rgba(255,255,255,.14);
  249.      box-shadow: inset 0 0 0 1px rgba(255,255,255,.06);
  250.    }
  251.    .chip__url {
  252.      flex: 1;
  253.      min-width: 0;
  254.      max-width: 93px;
  255.      font-weight: 600;
  256.      white-space: nowrap;
  257.      overflow: hidden;
  258.      text-overflow: ellipsis;
  259.    }
  260.  
  261.    .icon-btn{
  262.      display:grid; place-items:center; width:36px; height:36px;
  263.      border-radius:10px; background:rgba(255,255,255,.06); border:1px solid rgba(255,255,255,.12); color:var(--text);
  264.    }
  265.    .icon-btn:active{ transform:scale(.98); }
  266.  
  267.    .qr-buttons{ display:flex; gap:8px; }
  268.  
  269.    .cta{
  270.      width:100%; margin-top:10px; padding:12px 14px; border:0; border-radius:12px; cursor:pointer; font-weight:800;
  271.      color: var(--accent-text);
  272.      background: linear-gradient(90deg, #8b5cf6, #22d3ee, #ec4899);
  273.      background-size: 200% 100%;
  274.      animation: gradientMove 8s linear infinite;
  275.      box-shadow: 0 10px 28px rgba(139,92,246,.28);
  276.    }
  277.    @keyframes gradientMove{ 0%{background-position:0% 50%} 50%{background-position:100% 50%} 100%{background-position:0% 50%} }
  278.  
  279.    /* ========= BOTTOM NAV ========= */
  280.    .bottom-nav{ position:fixed; left:0; right:0; bottom:0; max-width:480px; margin:0 auto; padding:8px 10px; z-index:100; }
  281.    .nav-wrap{
  282.      height:60px; padding:0 8px; border-radius:20px;
  283.      background:rgba(18,18,22,.6); border:1px solid rgba(255,255,255,.08);
  284.      box-shadow:0 10px 30px rgba(0,0,0,.45);
  285.      backdrop-filter: blur(10px) saturate(130%); -webkit-backdrop-filter: blur(10px) saturate(130%);
  286.      display:grid; grid-template-columns:repeat(4,1fr); align-items:center; position:relative; overflow:hidden;
  287.    }
  288.    .nav-item{
  289.      display:flex; flex-direction:column; align-items:center; gap:6px; justify-content:center; height:100%;
  290.      color:var(--muted); text-decoration:none; font-size:12px; font-weight:700; position:relative; z-index:1;
  291.    }
  292.    .nav-item svg{ width:22px; height:22px; stroke:currentColor; opacity:.9; }
  293.    .nav-item.active{ color:#fff; }
  294.    .nav-pill{
  295.      position:absolute; top:8px; bottom:8px; left:0; width:0;
  296.      border-radius:16px; background:linear-gradient(180deg, rgba(139,92,246,.35), rgba(255,255,255,.06));
  297.      transition: transform .22s ease, width .22s ease; will-change: transform, width; pointer-events:none;
  298.    }
  299.  
  300.    /* ========= SKELETON / UTILS ========= */
  301.    .skeleton{ position:relative; overflow:hidden; border-radius:12px; background:rgba(255,255,255,.06); }
  302.    .skeleton::after{ content:""; position:absolute; inset:0; transform:translateX(-100%); background:linear-gradient(90deg, transparent, rgba(255,255,255,.12), transparent); animation:shimmer 1.3s infinite; }
  303.    @keyframes shimmer{ 100%{ transform:translateX(100%); } }
  304.    .error{ color:#ff6b6b; text-align:center; padding:14px 0; }
  305.    .mt-12{ margin-top:12px; } .mt-16{ margin-top:16px; }
  306.  
  307.    /* ========= SETTINGS SHEET — expanded tabs ========= */
  308.    .sheet-wrap{ display:grid; gap:12px; }
  309.    .sheet-tabs{
  310.      display:flex; gap:8px; flex-wrap:wrap;
  311.      background: linear-gradient(135deg, rgba(255,255,255,.08), rgba(255,255,255,.03));
  312.      border:1px solid rgba(255,255,255,.10);
  313.      border-radius:14px; padding:6px;
  314.    }
  315.    .sheet-tab-btn{
  316.      padding:10px 12px; border:0; border-radius:12px; cursor:pointer; font-weight:800; letter-spacing:.2px;
  317.      color:inherit; background:transparent;
  318.    }
  319.    .sheet-tab-btn.active{
  320.      background: radial-gradient(120% 150% at 50% 0%, rgba(139,92,246,.28), rgba(139,92,246,0) 70%),
  321.                  linear-gradient(180deg, rgba(255,255,255,.12), rgba(255,255,255,.04));
  322.      box-shadow: 0 6px 18px rgba(139,92,246,.22), inset 0 1px 0 rgba(255,255,255,.2);
  323.    }
  324.    .sheet-panels{ position:relative; }
  325.    .sheet-panel{ display:none; }
  326.    .sheet-panel.active{ display:block; }
  327.  
  328.    .kpi-grid{ display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:10px; }
  329.    @media (min-width: 480px){ .kpi-grid{ grid-template-columns:repeat(4,minmax(0,1fr)); } }
  330.    .kpi{
  331.      padding:12px; border-radius:14px; text-align:left;
  332.      background: linear-gradient(180deg, rgba(255,255,255,.10), rgba(255,255,255,.04));
  333.      border:1px solid rgba(255,255,255,.10);
  334.      box-shadow: inset 0 1px 0 rgba(255,255,255,.12);
  335.    }
  336.    .kpi small{ color:var(--muted); display:block; margin-bottom:4px; }
  337.    .kpi strong{ font-size:18px; font-weight:900; }
  338.  
  339.    .list{ display:grid; }
  340.    .item{ display:grid; grid-template-columns: 1fr auto; align-items:center; gap:12px; padding:12px; border-bottom:1px dashed rgba(255,255,255,.08); }
  341.    .item:last-child{ border-bottom:none; }
  342.    .item .meta{ display:grid; gap:4px; }
  343.    .badge{ display:inline-flex; align-items:center; gap:6px; padding:4px 8px; border-radius:999px; font-size:12px; font-weight:800; border:1px solid rgba(255,255,255,.14); background:rgba(255,255,255,.06); }
  344.    .btn{
  345.      display:inline-flex; align-items:center; gap:8px; padding:10px 12px; border-radius:12px; border:1px solid rgba(255,255,255,.12);
  346.      background: linear-gradient(180deg, rgba(255,255,255,.10), rgba(255,255,255,.04)); color:inherit; cursor:pointer; font-weight:800;
  347.    }
  348.    .btn:active{ transform:scale(.98); }
  349.    .btn.primary{
  350.      color: var(--accent-text);
  351.      background: linear-gradient(90deg,#8b5cf6,#22d3ee,#ec4899);
  352.      background-size:200% 100%; animation: gradientMove 8s linear infinite;
  353.      border-color: rgba(139,92,246,.45);
  354.    }
  355.    @keyframes gradientMove{ 0%{background-position:0% 50%} 50%{background-position:100% 50%} 100%{background-position:0% 50%} }
  356.  
  357.    .progress-bar{ position:relative; height:10px; border-radius:999px; overflow:hidden; background:rgba(255,255,255,.08); border:1px solid rgba(255,255,255,.10); }
  358.    .progress-bar > span{ position:absolute; left:0; top:0; bottom:0; width:0%; background:linear-gradient(90deg,#8b5cf6,#22d3ee,#ec4899); transition:width .3s ease; }
  359.  
  360.    .skeleton-line{ height:16px; border-radius:8px; background:rgba(255,255,255,.08); position:relative; overflow:hidden; }
  361.    .skeleton-line::after{ content:""; position:absolute; inset:0; transform:translateX(-100%); background:linear-gradient(90deg, transparent, rgba(255,255,255,.14), transparent); animation: shimmer 1.4s infinite; }
  362.    @keyframes shimmer{ 100%{ transform:translateX(100%);} }
  363.    .empty{ color:var(--muted); text-align:center; padding:16px 8px; }
  364.    .error{ color:#ff6b6b; text-align:center; padding:12px 8px; }
  365.  </style>
  366. </head>
  367. <body>
  368.  <!-- живой фон -->
  369.  <div class="bg">
  370.    <div class="blob b1"></div>
  371.    <div class="blob b2"></div>
  372.    <div class="blob b3"></div>
  373.  </div>
  374.  
  375.  <div class="container">
  376.    <div class="tabs">
  377.      <!-- Игры -->
  378. <section id="tab-friends" class="tab-content">
  379.  <div class="glass section-card center profit-calc">
  380.    <h2 class="headline">Калькулятор прибыли</h2>
  381.    <p class="subline">Выбери сервис, часы и количество номеров</p>
  382.  
  383.    <!-- Сервисы -->
  384.    <div class="service-switch" role="tablist" aria-label="Сервисы">
  385.      <button class="svc-btn active" data-svc="vk" aria-selected="true">VK</button>
  386.      <button class="svc-btn" data-svc="wa" aria-selected="false">WhatsApp</button>
  387.      <button class="svc-btn" data-svc="max" aria-selected="false">MAX</button>
  388.    </div>
  389.  
  390.    <!-- Ползунки -->
  391.    <div class="sliders">
  392.      <div class="slider-row">
  393.        <div class="slider-head">
  394.          <span>Часы работы</span>
  395.          <strong id="hoursVal">1 ч</strong>
  396.        </div>
  397.        <input id="hoursRange" type="range" min="1" max="24" step="1" value="1" />
  398.        <div class="ticks">
  399.          <span>1</span><span>6</span><span>12</span><span>18</span><span>24</span>
  400.        </div>
  401.      </div>
  402.  
  403.      <div class="slider-row">
  404.        <div class="slider-head">
  405.          <span>Кол-во номеров</span>
  406.          <strong id="qtyVal">1</strong>
  407.        </div>
  408.        <input id="qtyRange" type="range" min="1" max="200" step="1" value="1" />
  409.        <div class="ticks">
  410.          <span>1</span><span>50</span><span>100</span><span>150</span><span>200</span>
  411.        </div>
  412.      </div>
  413.    </div>
  414.  
  415.    <!-- Итоги -->
  416.    <div class="result-grid">
  417.      <div class="result-card">
  418.        <span class="label">Сервис</span>
  419.        <div class="value" id="svcName">VK</div>
  420.      </div>
  421.      <div class="result-card">
  422.        <span class="label">Ставка/час (текущий слой)</span>
  423.        <div class="value" id="rateNow">$2.50</div>
  424.        <div class="hint" id="layerHint">1–2 ч: $2.50/ч</div>
  425.      </div>
  426.      <div class="result-card">
  427.        <span class="label">Итого за 1 номер</span>
  428.        <div class="value accent" id="perOne">$2.50</div>
  429.      </div>
  430.      <div class="result-card total">
  431.        <span class="label">Итого за все номера</span>
  432.        <div class="value big" id="grandTotal">$2.50</div>
  433.      </div>
  434.    </div>
  435.  
  436.    <p class="fine-print">
  437.      Модель выплат: базовая ставка за 1–2 ч, затем каждые 2 часа ставка растёт на размер базовой.<br>
  438.      Примеры: VK — $2.5/ч, 3–4 ч: $5/ч, 5–6 ч: $7.5/ч. WA — $4/ч, затем $8/ч, $12/ч… MAX — $5/ч, затем $10/ч, $15/ч…
  439.    </p>
  440.  </div>
  441. </section>
  442.  
  443. <style>
  444. /* ---- калькулятор ---- */
  445. .profit-calc { padding: 18px 16px 20px; max-width: 860px; margin: 0 auto; }
  446. .profit-calc .headline { margin-top: 6px; }
  447. .profit-calc .subline { opacity: .9; margin-bottom: 16px; }
  448.  
  449. /* Переключатель сервисов */
  450. .service-switch{
  451.  display:flex; gap:8px; padding:6px; border-radius:16px;
  452.  background: linear-gradient(135deg, rgba(255,255,255,.08), rgba(255,255,255,.03));
  453.  box-shadow: inset 0 1px 0 rgba(255,255,255,.09);
  454.  width:100%; justify-content:center; margin: 6px 0 14px;
  455. }
  456. .svc-btn{
  457.  position:relative; padding:10px 14px; border-radius:12px; border:0; cursor:pointer;
  458.  font-weight:700; letter-spacing:.2px; background:transparent; color:inherit;
  459.  transition: transform .08s ease, background .2s ease;
  460. }
  461. .svc-btn.active{
  462.  background: radial-gradient(120% 150% at 50% 0%, rgba(255,165,0,.20), rgba(255,165,0,0) 70%) ,
  463.              linear-gradient(180deg, rgba(255,255,255,.12), rgba(255,255,255,.04));
  464.  box-shadow: 0 6px 20px rgba(255,165,0,.15), inset 0 1px 0 rgba(255,255,255,.2);
  465. }
  466. .svc-btn:active{ transform: scale(.98); }
  467.  
  468. /* Ползунки */
  469. .sliders{ display:grid; gap:16px; width:100%; }
  470. .slider-row{ background: rgba(255,255,255,.06); border-radius:16px; padding:12px 14px; }
  471. .slider-head{ display:flex; align-items:center; justify-content:space-between; margin-bottom:6px; }
  472. .slider-head strong{ font-weight:800; }
  473. .ticks{ display:flex; justify-content:space-between; font-size:12px; opacity:.7; margin-top:6px; }
  474. input[type="range"]{
  475.  -webkit-appearance: none; appearance: none; width:100%; height:10px; border-radius:999px;
  476.  background: var(--rng-bg, linear-gradient(90deg,currentColor 0%, currentColor 0%, rgba(255,255,255,.18) 0%));
  477.  outline: none;
  478. }
  479. input[type="range"]::-webkit-slider-thumb{
  480.  -webkit-appearance: none; appearance: none; width:24px; height:24px; border-radius:50%;
  481.  background: #fff; box-shadow: 0 6px 16px rgba(0,0,0,.25), 0 0 0 6px rgba(255,165,0,.25);
  482.  border: 3px solid rgba(255,165,0,.9);
  483. }
  484. input[type="range"]::-moz-range-thumb{
  485.  width:24px; height:24px; border-radius:50%; background:#fff; border:3px solid rgba(255,165,0,.9);
  486.  box-shadow: 0 6px 16px rgba(0,0,0,.25), 0 0 0 6px rgba(255,165,0,.25);
  487. }
  488. input[type="range"]::-moz-range-progress{ background: currentColor; height:10px; border-radius:999px; }
  489.  
  490. /* Итоги */
  491. .result-grid{
  492.  display:grid; gap:12px; grid-template-columns: repeat(4,minmax(0,1fr));
  493.  margin-top:16px;
  494. }
  495. .result-card{
  496.  background: linear-gradient(180deg, rgba(255,255,255,.10), rgba(255,255,255,.05));
  497.  border-radius:16px; padding:12px 14px; text-align:left;
  498.  box-shadow: inset 0 1px 0 rgba(255,255,255,.12);
  499. }
  500. .result-card.total{ grid-column: span 2; }
  501. @media (max-width: 780px){
  502.  .result-grid{ grid-template-columns: repeat(2,minmax(0,1fr)); }
  503.  .result-card.total{ grid-column: span 2; }
  504. }
  505. .label{ font-size:12px; opacity:.8; }
  506. .value{ font-weight:800; font-size:18px; margin-top:2px; }
  507. .value.big{ font-size:24px; }
  508. .value.accent{
  509.  background: linear-gradient(90deg, #ffd39a, #fff); -webkit-background-clip: text; background-clip: text; color: transparent;
  510.  text-shadow: 0 0 24px rgba(255,165,0,.25);
  511. }
  512. .hint{ font-size:12px; opacity:.75; margin-top:2px; }
  513. .fine-print{ font-size:12px; opacity:.7; margin-top:12px; }
  514.  
  515. /* Цвет заливки трека по значению */
  516. .profit-calc input[type="range"]{ color: rgba(255,165,0, .95); }
  517. </style>
  518.  
  519. <script>
  520. (() => {
  521.  // Фиксированные ставки за каждый ОПЛАЧИВАЕМЫЙ (нечётный) час
  522.  const BASE  = { vk: 2.5, wa: 4, max: 5 };
  523.  const NAMES = { vk: "VK",  wa: "WhatsApp", max: "MAX" };
  524.  
  525.  const svcButtons = document.querySelectorAll('.svc-btn');
  526.  const hoursRange = document.getElementById('hoursRange');
  527.  const qtyRange   = document.getElementById('qtyRange');
  528.  const hoursVal   = document.getElementById('hoursVal');
  529.  const qtyVal     = document.getElementById('qtyVal');
  530.  
  531.  const svcNameEl  = document.getElementById('svcName');
  532.  const rateNowEl  = document.getElementById('rateNow');
  533.  const layerHint  = document.getElementById('layerHint');
  534.  const perOneEl   = document.getElementById('perOne');
  535.  const totalEl    = document.getElementById('grandTotal');
  536.  
  537.  let currentSvc = 'vk';
  538.  
  539.  function paintTrack(input){
  540.    const min = +input.min, max = +input.max, val = +input.value;
  541.    const pct = ((val - min) / (max - min)) * 100;
  542.    input.style.setProperty('--rng-bg',
  543.      `linear-gradient(90deg, currentColor ${pct}%, rgba(255,255,255,.18) ${pct}%)`);
  544.  }
  545.  
  546.  // 👉 Оплата за текущий (выбранный) час: фиксированная ставка, только если час нечётный
  547.  function hourlyRateAtHour(base, hour){
  548.    return (hour % 2 === 1) ? base : 0;
  549.  }
  550.  
  551.  // 👉 Итог за N часов: платим только за нечётные, их количество = ceil(N/2)
  552.  function sumForHours(base, hours){
  553.    const paidHours = Math.ceil(hours / 2);
  554.    return base * paidHours;
  555.  }
  556.  
  557.  function fmt(n){ return `$${n.toFixed(2)}`; }
  558.  
  559.  function update(){
  560.    const hours = +hoursRange.value;
  561.    const qty   = +qtyRange.value;
  562.    const base  = BASE[currentSvc];
  563.  
  564.    const rateNow = hourlyRateAtHour(base, hours); // фиксированная ставка или 0
  565.    const perOne  = sumForHours(base, hours);      // сумма за 1 номер
  566.    const grand   = perOne * qty;                  // общая сумма
  567.  
  568.    const hint = (hours % 2 === 1)
  569.      ? `${hours}-й час оплачивается: ${fmt(base)}/ч (фикс)`
  570.      : `${hours}-й час не оплачивается`;
  571.  
  572.    svcNameEl.textContent = NAMES[currentSvc];
  573.    rateNowEl.textContent = fmt(rateNow);
  574.  
  575.    layerHint.textContent =
  576.      `Оплата только за нечётные часы (1, 3, 5, …). Фиксированная ставка ${fmt(base)} за каждый оплачиваемый час. ${hint}`;
  577.  
  578.    perOneEl.textContent = fmt(perOne);
  579.    totalEl.textContent  = fmt(grand);
  580.  
  581.    hoursVal.textContent = `${hours} ч`;
  582.    qtyVal.textContent   = `${qty}`;
  583.  
  584.    paintTrack(hoursRange);
  585.    paintTrack(qtyRange);
  586.  }
  587.  
  588.  svcButtons.forEach(btn => {
  589.    btn.addEventListener('click', () => {
  590.      svcButtons.forEach(b => { b.classList.remove('active'); b.setAttribute('aria-selected','false'); });
  591.      btn.classList.add('active'); btn.setAttribute('aria-selected','true');
  592.      currentSvc = btn.dataset.svc;
  593.      update();
  594.    });
  595.  });
  596.  
  597.  hoursRange.addEventListener('input', update);
  598.  qtyRange.addEventListener('input', update);
  599.  
  600.  paintTrack(hoursRange); paintTrack(qtyRange);
  601.  update();
  602. })();
  603. </script>
  604.  
  605.  
  606.  
  607.  
  608.      <!-- Топ -->
  609.      <section id="tab-top" class="tab-content">
  610.        <div class="glass section-card center">
  611.          <div id="topLottie" class="lottie"></div>
  612.          <h2 class="headline">Топ сдающих</h2>
  613.          <p class="subline">Ежедневный рейтинг активности</p>
  614.        </div>
  615.        <div id="topList" class="glass section-card mt-12">
  616.          <div class="skeleton" style="height:70px;margin-bottom:8px;"></div>
  617.          <div class="skeleton" style="height:70px;margin-bottom:8px;"></div>
  618.          <div class="skeleton" style="height:70px;"></div>
  619.        </div>
  620.      </section>
  621.  
  622.      <!-- Реф -->
  623.      <section id="tab-ref" class="tab-content">
  624.        <div class="glass section-card">
  625.           <div id="Que_stk" class="lottie"></div>
  626.          <h2 class="headline center">Реферальная программа</h2>
  627.          <p class="subline center">Приглашайте друзей и получайте бонусы</p>
  628.  
  629.          <!-- QR вариант -->
  630. <div class="ref-qr">
  631.  <div id="qrBox" class="qr-box"></div>
  632.  
  633.  <div class="qr-side">
  634.    <div class="chip" id="refChip" title="Нажми стрелку, чтобы развернуть ссылку">
  635.      <button class="icon-btn icon-sm" id="refExpandBtn" aria-label="Развернуть/свернуть">▾</button>
  636.      <span id="refLinkText" class="chip__url">https://t.me/king_wa_bot?start=...</span>
  637.      <button class="icon-btn" id="refCopyBtn" aria-label="Скопировать">
  638.        <svg viewBox="0 0 24 24" width="18" height="18" stroke="currentColor" fill="none" stroke-width="2">
  639.          <rect x="9" y="9" width="13" height="13" rx="2"></rect>
  640.          <rect x="2" y="2" width="13" height="13" rx="2"></rect>
  641.        </svg>
  642.      </button>
  643.      <button class="icon-btn" id="refShareBtn" aria-label="Поделиться">↗️</button>
  644.    </div>
  645.  </div>
  646.  
  647.  <input id="refLinkField" type="text" readonly class="sr-only">
  648. </div>
  649.  
  650.          <div class="glass section-card mt-12" id="ref-balance-card">
  651.            <div style="display:flex;align-items:center;justify-content:space-between;">
  652.              <div>
  653.                <small class="muted">Баланс</small>
  654.                <div style="font-size:22px;font-weight:800;"><span id="ref-balance">0.00</span> <span class="muted" style="font-size:12px;">SM</span></div>
  655.                <div class="muted" id="ref-usd">≈ $0.00</div>
  656.              </div>
  657.              <button class="icon-btn" disabled style="cursor:not-allowed;opacity:.6;">💸</button>
  658.            </div>
  659.          </div>
  660.        </div>
  661.      </section>
  662.  
  663.      <!-- Очередь -->
  664.      <section id="tab-nft" class="tab-content">
  665.        <div class="glass section-card center">
  666.          <div id="Que_stk_queue" class="lottie"></div>
  667.          <h2 class="headline">📦 Очередь</h2>
  668.          <p class="subline">Актуальная статистика</p>
  669.        </div>
  670.  
  671.        <div class="glass section-card queue-card">
  672.          <div class="queue-top">
  673.            <div class="queue-name">
  674.              <img src="https://img.icons8.com/color/48/whatsapp.png" alt="wa">
  675.              <span>WhatsApp Россия</span>
  676.            </div>
  677.            <div class="queue-status off" id="queueStatus">Не работает</div>
  678.          </div>
  679.  
  680.          <div class="queue-stats">
  681.            <div class="q-item"><small>В работе</small><strong id="workNow">0</strong></div>
  682.            <div class="q-item"><small>В очереди</small><strong id="inQueue">0</strong></div>
  683.            <div class="q-item"><small>Ожидание</small><strong id="waitTime">-</strong></div>
  684.          </div>
  685.        </div>
  686.      </section>
  687.  
  688.      <!-- Профиль (дефолт) -->
  689.      <section id="tab-profile" class="tab-content active">
  690.        <div class="glass section-card profile">
  691.          <div class="profile-header">
  692.            <div class="avatar-wrapper">
  693.              <img id="avatar" src="https://via.placeholder.com/92" alt="avatar">
  694.            </div>
  695.  
  696.            <div class="status-row">
  697.              <div class="status-badge"><span class="status-dot"></span><span id="statusLabel">Новичок</span></div>
  698.            </div>
  699.  
  700.            <div class="title" id="userName">Загрузка…</div>
  701.            <div class="muted" id="userId">ID: —</div>
  702.          </div>
  703.  
  704.          <div class="actions">
  705.            <button class="circle-btn" title="Сдать номер" onclick="openBot('start=sdat')" aria-label="Сдать номер">
  706.              <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none">
  707.                <path d="M16 2v6h6"/><path d="m22 2-6 6"/><path d="M13.832 16.568a1 1 0 0 0 1.213-.303l.355-.465A2 2 0 0 1 17 15h3a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2A18 18 0 0 1 2 4a2 2 0 0 1 2-2h3a2 2 0 0 1 2 2v3a2 2 0 0 1-.8 1.6l-.468.351a1 1 0 0 0-.292 1.233 14 14 0 0 0 6.392 6.384" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
  708.              </svg>
  709.            </button>
  710.            <button class="circle-btn" title="Профиль" onclick="openBot('start=cb_drop_status')" aria-label="Профиль">
  711.              <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none">
  712.                <rect width="20" height="14" x="2" y="5" rx="2" stroke="currentColor" stroke-width="2"/>
  713.                <line x1="2" x2="22" y1="10" y2="10" stroke="currentColor" stroke-width="2"/>
  714.              </svg>
  715.            </button>
  716.            <button class="circle-btn" title="Статистика" onclick="openBot('start=cb_profile_analytics')" aria-label="Статистика">
  717.              <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none">
  718.                <path d="M3 3v18h18" stroke="currentColor" stroke-width="2"/>
  719.                <path d="M7 12v5" stroke="currentColor" stroke-width="2"/>
  720.                <path d="M12 8v9" stroke="currentColor" stroke-width="2"/>
  721.                <path d="M17 5v13" stroke="currentColor" stroke-width="2"/>
  722.              </svg>
  723.            </button>
  724.            <button class="circle-btn" title="Пополнить" onclick="openBot('start=cb_business_topup')" aria-label="Пополнить">
  725.              <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none">
  726.                <path d="M6 8.32a7.43 7.43 0 0 1 0 7.36" stroke="currentColor" stroke-width="2"/>
  727.                <path d="M9.46 6.21a11.76 11.76 0 0 1 0 11.58" stroke="currentColor" stroke-width="2"/>
  728.                <path d="M12.91 4.1a15.91 15.91 0 0 1 .01 15.8" stroke="currentColor" stroke-width="2"/>
  729.                <path d="M16.37 2a20.16 20.16 0 0 1 0 20" stroke="currentColor" stroke-width="2"/>
  730.              </svg>
  731.            </button>
  732.          </div>
  733.  
  734.          <div class="balance-card">
  735.            <div>
  736.              <small>Ваш бизнес баланс</small>
  737.              <strong id="balanceValue" data-usd="0">$0</strong>
  738.            </div>
  739.            <button class="icon-btn" onclick="openSheet('Настройки', 'settings')">⚙️</button>
  740.          </div>
  741.  
  742.          <div id="logContainer" class="activity-log">
  743.            <div class="skeleton" style="height:52px;margin-bottom:8px;"></div>
  744.            <div class="skeleton" style="height:52px;margin-bottom:8px;"></div>
  745.            <div class="skeleton" style="height:52px;"></div>
  746.          </div>
  747.        </div>
  748.      </section>
  749.    </div>
  750.  </div>
  751.  
  752.  <!-- Bottom Navigation -->
  753.  <nav class="bottom-nav" role="navigation" aria-label="Нижняя навигация">
  754.    <div class="nav-wrap glass" id="navWrap">
  755.      <div class="nav-pill" id="navPill"></div>
  756.  
  757.      <a class="nav-item" data-tab="friends" onclick="setTab(this)">
  758.        <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
  759.          <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
  760.                d="M8 4H16L18 8V12L16 16H8L6 12V8L8 4z M10 10h4M10 14h4"/>
  761.        </svg>
  762.        <span>Ставка</span>
  763.      </a>
  764.  
  765.      <a class="nav-item" data-tab="top" onclick="setTab(this)">
  766.        <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
  767.          <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
  768.                d="M12 17.27L18.18 21l-1.63-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.45 4.73L5.82 21z"/>
  769.        </svg>
  770.        <span>Топ</span>
  771.      </a>
  772.  
  773.      <a class="nav-item" data-tab="ref" onclick="setTab(this)">
  774.        <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
  775.          <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
  776.                d="M13 16h-1v-4h-1M12 8h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/>
  777.        </svg>
  778.        <span>Реф</span>
  779.      </a>
  780.  
  781.      <a class="nav-item active" data-tab="profile" onclick="setTab(this)">
  782.        <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
  783.          <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
  784.                d="M5.121 17.804A9 9 0 1118.88 6.196 9 9 0 015.121 17.804z M15 11a3 3 0 11-6 0 3 3 0 016 0z M12 14a6 6 0 00-5 2.292"/>
  785.        </svg>
  786.        <span>Профиль</span>
  787.      </a>
  788.    </div>
  789.  </nav>
  790.  
  791.  <!-- Bottom Sheet -->
  792.  <div id="bottomSheet" class="glass" style="position:fixed;left:0;right:0;bottom:-100%;max-width:480px;margin:0 auto;height:88%;border-top-left-radius:18px;border-top-right-radius:18px;transition:bottom .35s ease;z-index:120;">
  793.    <div style="display:flex;align-items:center;justify-content:space-between;padding:14px 16px;border-bottom:1px solid var(--stroke);">
  794.      <span id="sheetTitle" style="font-weight:800;">Загрузка…</span>
  795.      <button onclick="closeSheet()" class="icon-btn">✖</button>
  796.    </div>
  797.    <div id="sheetContent" style="padding:16px;">
  798.      <p class="muted">⏳ Пожалуйста, подождите…</p>
  799.    </div>
  800.  </div>
  801.  
  802.  <!-- Lottie init -->
  803.  <script>
  804.    document.addEventListener('DOMContentLoaded', () => {
  805.      const s1 = document.getElementById('gameSticker');
  806.      s1 && lottie.loadAnimation({ container: s1, renderer:'svg', loop:true, autoplay:true, path:'11.json' });
  807.  
  808.      const s2 = document.getElementById('topLottie');
  809.      s2 && lottie.loadAnimation({ container: s2, renderer:'svg', loop:true, autoplay:true, path:'emostar_1414.json' });
  810.  
  811.      const s3 = document.getElementById('Que_stk');
  812.      s3 && lottie.loadAnimation({ container: s3, renderer:'svg', loop:true, autoplay:true, path:'Que_stk.json' });
  813.  
  814.      const s4 = document.getElementById('Que_stk_queue');
  815.      s4 && lottie.loadAnimation({ container: s4, renderer:'svg', loop:true, autoplay:true, path:'Que_stk.json' });
  816.    });
  817.  </script>
  818.  
  819.  <!-- Helpers / Telegram -->
  820.  <script>
  821.    const tg = window.Telegram?.WebApp;
  822.    tg?.expand?.();
  823.  
  824.    function hapticClick(){ try{ tg?.HapticFeedback?.impactOccurred?.("light"); }catch(e){} }
  825.    function openBot(query){ hapticClick(); window.open(`https://t.me/king_wa_bot?${query}`, "_blank"); }
  826.  
  827.    function waitForTelegramUser(callback, timeout=1200){
  828.      const start = Date.now();
  829.      (function check(){
  830.        const user = Telegram?.WebApp?.initDataUnsafe?.user;
  831.        if (user?.id) return callback(user.id, user);
  832.        if (Date.now() - start < timeout) return setTimeout(check, 50);
  833.        console.warn("⛔ Telegram user.id не доступен");
  834.      })();
  835.    }
  836.  </script>
  837.  
  838.  <!-- Data loaders -->
  839.  <script>
  840.    function loadTop(){
  841.      const list = document.getElementById('topList');
  842.      fetch('get_top.php')
  843.        .then(r=>r.json())
  844.        .then(data=>{
  845.          list.innerHTML = '';
  846.          const top = Array.isArray(data.top) ? data.top : [];
  847.          const podiumRaw = top.slice(0,3);
  848.          const podium = [podiumRaw[1], podiumRaw[0], podiumRaw[2]].filter(Boolean);
  849.          const others = top.slice(3);
  850.  
  851.          const wrap = document.createElement('div'); wrap.className='glass section-card';
  852.          const podiumEl = document.createElement('div'); podiumEl.className='top-three';
  853.          podium.forEach((u,i)=>{
  854.            const place = [2,1,3][i];
  855.            const p = document.createElement('div');
  856.            p.className = `podium p${place}`;
  857.            p.innerHTML = `
  858.              <div class="medal">${place}</div>
  859.              <img src="${u.photo || 'https://via.placeholder.com/96'}" alt="">
  860.              <div style="margin-top:8px;font-weight:700">${u.name}</div>
  861.              <div class="muted" style="font-size:12px">${u.count}</div>
  862.            `;
  863.            podiumEl.appendChild(p);
  864.          });
  865.          wrap.appendChild(podiumEl);
  866.          list.appendChild(wrap);
  867.  
  868.          const rest = document.createElement('div'); rest.className='glass section-card mt-12';
  869.          others.forEach((u,i)=>{
  870.            const row = document.createElement('div');
  871.            row.className='row';
  872.            row.innerHTML = `
  873.              <img class="ava" src="${u.photo || 'https://via.placeholder.com/60'}" alt="">
  874.              <div class="nm">#${i+4} ${u.name}</div>
  875.              <div class="cnt">${u.count}</div>
  876.            `;
  877.            rest.appendChild(row);
  878.          });
  879.          list.appendChild(rest);
  880.        })
  881.        .catch(()=>{ list.innerHTML = '<div class="error">❌ Не удалось загрузить топ.</div>'; });
  882.    }
  883.  
  884.    function loadQueueCard(){
  885.      fetch("get_queues.php")
  886.        .then(res=>res.json())
  887.        .then(data=>{
  888.          document.getElementById("workNow").textContent = data.working_now ?? 0;
  889.          document.getElementById("inQueue").textContent = data.in_queue ?? 0;
  890.          document.getElementById("waitTime").textContent = data.estimated_wait ?? "-";
  891.          const st = document.getElementById("queueStatus");
  892.          if (data.status === "on"){ st.textContent="Работает"; st.classList.remove('off'); st.classList.add('on'); }
  893.          else { st.textContent="Не работает"; st.classList.remove('on'); st.classList.add('off'); }
  894.        })
  895.        .catch(()=>{ document.querySelector("#tab-nft .queue-card").innerHTML = '<div class="error">❌ Ошибка загрузки данных.</div>'; });
  896.    }
  897.  
  898.    function initRef(userId){
  899.      const refLink = `https://t.me/king_wa_bot?start=${userId}`;
  900.      const fld = document.getElementById("refLinkField");
  901.      if (fld) fld.value = refLink;
  902.  
  903.      const txt = document.getElementById("refLinkText");
  904.      if (txt) txt.textContent = refLink;
  905.  
  906.      const qrBox = document.getElementById('qrBox');
  907.      if (qrBox){
  908.        qrBox.innerHTML = "";
  909.        new QRCode(qrBox, {
  910.          text: refLink,
  911.          width: 92,
  912.          height: 92,
  913.          colorDark : "#000000",
  914.          colorLight : "#ffffff",
  915.          correctLevel : QRCode.CorrectLevel.M
  916.        });
  917.      }
  918.  
  919.      document.getElementById("refCopyBtn")?.addEventListener('click', ()=>{
  920.        navigator.clipboard.writeText(refLink).then(()=> alert("Ссылка скопирована!"));
  921.        hapticClick();
  922.      });
  923.  
  924.      document.getElementById("refShareBtn")?.addEventListener('click', ()=>{
  925.        const message = `👑 Присоединяйся к King WhatsApp и зарабатывай!\n\n${refLink}`;
  926.        if (Telegram?.WebApp?.platform !== "unknown") {
  927.          window.open(`https://t.me/share/url?url=${encodeURIComponent(message)}`, "_blank");
  928.        } else if (navigator.share) {
  929.          navigator.share({ title: "King WhatsApp", text: message, url: refLink }).catch(()=>{});
  930.        } else {
  931.          navigator.clipboard.writeText(refLink).then(()=> alert("Ссылка скопирована!"));
  932.        }
  933.        hapticClick();
  934.      });
  935.  
  936.      fetch("get_ref_data.php", {
  937.        method:"POST", headers:{ "Content-Type":"application/json" },
  938.        body: JSON.stringify({ telegram_id: userId })
  939.      })
  940.      .then(res=>res.json())
  941.      .then(data=>{
  942.        document.getElementById("ref-balance").textContent = (data.balance ?? 0).toFixed(2);
  943.        document.getElementById("ref-usd").textContent = `≈ $${(data.balance_usd ?? 0).toFixed(2)}`;
  944.  
  945.        const footer = document.getElementById("ref-footer");
  946.        const list = document.getElementById("ref-list");
  947.        const arr = Array.isArray(data.referrals) ? data.referrals : [];
  948.  
  949.        if (!arr.length){ footer && (footer.textContent = "Вы ещё никого не пригласили"); return; }
  950.        footer && (footer.textContent = `Приглашено: ${arr.length}`);
  951.        if (!list) return;
  952.        list.innerHTML = "";
  953.        arr.forEach(r=>{
  954.          const row = document.createElement("div");
  955.          row.className = "row";
  956.          row.innerHTML = `
  957.            <img class="ava" src="${r.photo || 'https://cdn-icons-png.flaticon.com/512/149/149071.png'}" alt="">
  958.            <div class="nm">${r.name}</div>
  959.            <div class="cnt">+${r.earned} SM</div>
  960.          `;
  961.          list.appendChild(row);
  962.        });
  963.      })
  964.      .catch(()=>{ const f = document.getElementById("ref-footer"); if (f) f.innerHTML = "<span class='error'>❌ Ошибка загрузки</span>"; });
  965.    }
  966.  </script>
  967.  
  968.  <!-- Profile load -->
  969.  <script>
  970.    let usdToRubRate = 92.5; // fallback
  971.    fetch('https://www.cbr-xml-daily.ru/daily_json.js')
  972.      .then(r=>r.json())
  973.      .then(d=>{ usdToRubRate = d?.Valute?.USD?.Value || usdToRubRate; })
  974.      .catch(()=>{});
  975.  
  976.    function renderProfile(userId, user){
  977.      document.getElementById('userId').textContent = `ID: ${userId}`;
  978.      if (user?.photo_url) document.getElementById('avatar').src = user.photo_url;
  979.  
  980.      fetch("check_user.php", {
  981.        method:"POST", headers:{ "Content-Type":"application/json" },
  982.        body: JSON.stringify({ telegram_id: userId })
  983.      })
  984.      .then(r=>r.json())
  985.      .then(data=>{
  986.        document.getElementById('userName').textContent = data.name || "Пользователь";
  987.        document.getElementById('balanceValue').dataset.usd = data.balance ?? 0;
  988.        document.getElementById('balanceValue').textContent = `$${data.balance ?? 0}`;
  989.        document.getElementById('statusLabel').textContent = data.status || "Новичок";
  990.  
  991.        const logWrap = document.getElementById('logContainer');
  992.        const actions = Array.isArray(data.actions) ? data.actions : [];
  993.        if (!actions.length){ logWrap.innerHTML = `<div class="muted center">Нет последних действий</div>`; }
  994.        else{
  995.          logWrap.innerHTML = actions.map(a=>`
  996.            <div class="activity-item">
  997.              <div class="activity-icon">
  998.                <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="none">
  999.                  <rect x="2" y="2" width="14" height="14" rx="3" stroke="currentColor" stroke-width="2"/>
  1000.                </svg>
  1001.              </div>
  1002.              <div class="activity-main">
  1003.                <div class="number">${a.number}</div>
  1004.                <div class="date">${a.date}</div>
  1005.              </div>
  1006.            </div>
  1007.          `).join('');
  1008.        }
  1009.      })
  1010.      .catch(()=>{ document.getElementById('logContainer').innerHTML = `<div class="error">❌ Ошибка загрузки профиля</div>`; });
  1011.    }
  1012.  
  1013.    waitForTelegramUser((id, user)=>{ renderProfile(id, user); initRef(id); });
  1014.  </script>
  1015.  
  1016.  <!-- Bottom sheet views (оригинальные) -->
  1017.  <script>
  1018.    function openSheet(title, type){
  1019.      document.getElementById('sheetTitle').textContent = title;
  1020.      const c = document.getElementById('sheetContent');
  1021.      const views = {
  1022.        settings: `
  1023.          <div class="glass section-card">
  1024.            <h3 style="margin:0 0 8px;">Настройки</h3>
  1025.            <p class="muted">Управляйте приложением и быстрыми действиями</p>
  1026.            <div class="mt-12" style="display:grid;gap:8px;">
  1027.              <button class="icon-btn" onclick="requestAddToHome()">📲</button>
  1028.              <div id="homeStatus" class="muted"></div>
  1029.            </div>
  1030.          </div>
  1031.        `,
  1032.        balance: `<div class="glass section-card center"><div class="muted">📱 Сдать номер в боте</div><p class="mt-12"><button class="cta" onclick="openBot('start=sdat')">Сдать номер</button></p></div>`,
  1033.        numbers: `<div class="glass section-card center"><div class="muted">📦 Ваши номера</div><p class="mt-12"><button class="cta" onclick="openBot('start=cb_drop_status')">Открыть</button></p></div>`,
  1034.        stats:   `<div class="glass section-card center"><div class="muted">📊 Аналитика профиля</div><p class="mt-12"><button class="cta" onclick="openBot('start=cb_profile_analytics')">Посмотреть</button></p></div>`,
  1035.        topup:   `<div class="glass section-card center"><div class="muted">🧾 Пополнить бизнес-баланс</div><p class="mt-12"><button class="cta" onclick="openBot('start=cb_business_topup')">Пополнить</button></p></div>`
  1036.      };
  1037.      c.innerHTML = views[type] || `<p class="muted">⏳ Пожалуйста, подождите…</p>`;
  1038.      document.getElementById('bottomSheet').style.bottom = '0';
  1039.    }
  1040.    function closeSheet(){ document.getElementById('bottomSheet').style.bottom = '-100%'; }
  1041.  
  1042.    function requestAddToHome(){
  1043.      const api = Telegram?.WebApp;
  1044.      if (!api?.addToHomeScreen || !api?.showPopup){ alert("❌ Эта функция не поддерживается."); return; }
  1045.      api.showPopup({
  1046.        title:"Добавить на экран?",
  1047.        message:"Добавить King WebApp на главный экран?",
  1048.        buttons:[{id:"yes",type:"ok",text:"Да"},{id:"no",type:"close",text:"Нет"}]
  1049.      }, (id)=>{
  1050.        if (id === "yes") api.addToHomeScreen();
  1051.        else document.getElementById("homeStatus").textContent = "⛔ Вы отказались от добавления.";
  1052.      });
  1053.      api.onEvent && api.onEvent('homeScreenAdded', ()=> document.getElementById("homeStatus").textContent = "✅ Успешно добавлено!");
  1054.    }
  1055.  </script>
  1056.  
  1057.  <!-- Tabs + точное позиционирование капли -->
  1058.  <script>
  1059.    function positionPill(el){
  1060.      const wrap = document.getElementById('navWrap');
  1061.      const pill = document.getElementById('navPill');
  1062.      const rectItem = el.getBoundingClientRect();
  1063.      const gap = 6;
  1064.  
  1065.      const width = Math.max(0, rectItem.width - gap*2);
  1066.      const left = Math.max(0, el.offsetLeft + gap);
  1067.  
  1068.      pill.style.width = width + 'px';
  1069.      pill.style.transform = `translateX(${left}px)`;
  1070.    }
  1071.  
  1072.    function setTab(el){
  1073.      hapticClick();
  1074.      const route = el.getAttribute('data-tab');
  1075.  
  1076.      document.querySelectorAll('.tab-content').forEach(x=>x.classList.remove('active'));
  1077.      document.getElementById('tab-' + route)?.classList.add('active');
  1078.  
  1079.      document.querySelectorAll('.nav-item').forEach(a=>a.classList.remove('active'));
  1080.      el.classList.add('active');
  1081.  
  1082.      positionPill(el);
  1083.  
  1084.      if (route === 'top') loadTop();
  1085.      if (route === 'nft') loadQueueCard();
  1086.    }
  1087.  
  1088.    window.addEventListener('load', ()=>{
  1089.      const active = document.querySelector('.nav-item.active') || document.querySelector('.nav-item[data-tab="profile"]');
  1090.      if (active) setTab(active);
  1091.    });
  1092.    window.addEventListener('resize', ()=>{
  1093.      const active = document.querySelector('.nav-item.active');
  1094.      if (active) positionPill(active);
  1095.    });
  1096.  </script>
  1097.  
  1098.  <!-- ===== Расширенное меню Настроек (перехват openSheet('settings')) ===== -->
  1099.  <script>
  1100.    (function(){
  1101.      const tg = window.Telegram?.WebApp;
  1102.      const haptic = ()=>{ try{ tg?.HapticFeedback?.impactOccurred?.("light"); }catch(e){} };
  1103.  
  1104.      const _openSheet = window.openSheet;
  1105.      window.openSheet = function(title, type){
  1106.        if (type !== 'settings'){ _openSheet?.(title, type); document.getElementById('bottomSheet').style.bottom = '0'; return; }
  1107.  
  1108.        document.getElementById('sheetTitle').textContent = title;
  1109.        const c = document.getElementById('sheetContent');
  1110.        c.innerHTML = `
  1111.          <div class="sheet-wrap">
  1112.            <div class="sheet-tabs" role="tablist" aria-label="Разделы настроек">
  1113.              <button class="sheet-tab-btn active" data-tab="mystats" aria-selected="true">Моя статистика</button>
  1114.              <button class="sheet-tab-btn" data-tab="bonuses" aria-selected="false">Бонусы</button>
  1115.              <button class="sheet-tab-btn" data-tab="contests" aria-selected="false">Конкурсы</button>
  1116.            </div>
  1117.            <div class="sheet-panels">
  1118.              <div class="sheet-panel active" id="panel-mystats">
  1119.                <div class="kpi-grid">
  1120.                  <div class="kpi"><small>Всего заработано</small><strong id="kpi-earned">—</strong></div>
  1121.                  <div class="kpi"><small>Сдано номеров</small><strong id="kpi-count">—</strong></div>
  1122.                  <div class="kpi"><small>Среднее/день</small><strong id="kpi-avg">—</strong></div>
  1123.                  <div class="kpi"><small>Серия дней</small><strong id="kpi-streak">—</strong></div>
  1124.                </div>
  1125.                <div style="margin-top:12px; display:grid; gap:10px;">
  1126.                  <div class="item" style="grid-template-columns:1fr;">
  1127.                    <div class="meta">
  1128.                      <strong>Прогресс к цели</strong>
  1129.                      <div class="progress-bar" aria-label="Прогресс к цели"><span id="statsGoal" style="width:0%"></span></div>
  1130.                    </div>
  1131.                  </div>
  1132.                  <div><button class="btn" onclick="openBot('start=cb_profile_analytics')">Подробнее в боте</button></div>
  1133.                </div>
  1134.              </div>
  1135.  
  1136.  
  1137.              <div class="sheet-panel" id="panel-bonuses">
  1138.                <div class="kpi-grid">
  1139.                  <div class="kpi"><small>Баллы</small><strong id="bonusPoints">—</strong></div>
  1140.                  <div class="kpi"><small>Рефералы</small><strong id="bonusRefs">—</strong></div>
  1141.                  <div class="kpi"><small>Бонус в $</small><strong id="bonusUsd">—</strong></div>
  1142.                  <div class="kpi"><small>Статус</small><strong id="bonusTier">—</strong></div>
  1143.                </div>
  1144.                <div id="bonusList" class="list" style="margin-top:10px;"></div>
  1145.              </div>
  1146.  
  1147.              <div class="sheet-panel" id="panel-contests">
  1148.                <div id="contestList" class="list">
  1149.                  <div class="empty">Загрузка конкурсов…</div>
  1150.                </div>
  1151.              </div>
  1152.            </div>
  1153.          </div>`;
  1154.  
  1155.        const tabs = c.querySelectorAll('.sheet-tab-btn');
  1156.        tabs.forEach(btn=>{
  1157.          btn.addEventListener('click',()=>{
  1158.            haptic();
  1159.            tabs.forEach(b=>{ b.classList.remove('active'); b.setAttribute('aria-selected','false'); });
  1160.            btn.classList.add('active'); btn.setAttribute('aria-selected','true');
  1161.            const id = btn.dataset.tab;
  1162.            c.querySelectorAll('.sheet-panel').forEach(p=>p.classList.remove('active'));
  1163.            c.querySelector('#panel-' + id)?.classList.add('active');
  1164.            if (id==='mystats') loadMyStats();
  1165.            if (id==='bonuses') loadBonuses();
  1166.            if (id==='contests') loadContests();
  1167.          });
  1168.        });
  1169.  
  1170.        loadMyStats();
  1171.        document.getElementById('bottomSheet').style.bottom = '0';
  1172.      };
  1173.  
  1174.      function fmtUSD(n){ try{return new Intl.NumberFormat('en-US',{style:'currency',currency:'USD'}).format(Number(n||0));}catch(e){return `$${Number(n||0).toFixed(2)}`;} }
  1175.  
  1176.      function loadMyStats(){
  1177.        fetch('get_profile_stats.php', { method:'POST' })
  1178.          .then(r=>r.json())
  1179.          .then(d=>{
  1180.            document.getElementById('kpi-earned').textContent = fmtUSD(d?.earned_usd ?? 0);
  1181.            document.getElementById('kpi-count').textContent  = d?.numbers_count ?? 0;
  1182.            document.getElementById('kpi-avg').textContent    = fmtUSD(d?.avg_per_day ?? 0);
  1183.            document.getElementById('kpi-streak').textContent = d?.streak_days ?? 0;
  1184.            const goal = Math.max(0, Math.min(100, Number(d?.goal_progress_pct ?? 0)));
  1185.            document.getElementById('statsGoal').style.width = goal + '%';
  1186.          })
  1187.          .catch(()=>{ const panel = document.getElementById('panel-mystats'); panel.insertAdjacentHTML('beforeend','<div class="error">❌ Не удалось загрузить статистику</div>'); });
  1188.      }
  1189.  
  1190.      function loadMyNumbers(){
  1191.        const list = document.getElementById('numbersList');
  1192.        fetch('get_num.php', { method:'POST' })
  1193.          .then(r=>r.json())
  1194.          .then(d=>{
  1195.            const arr = Array.isArray(d?.items) ? d.items : [];
  1196.            if (!arr.length){ list.innerHTML = '<div class="empty">Пока нет номеров</div>'; return; }
  1197.            list.innerHTML = '';
  1198.            arr.forEach(n=>{
  1199.              const el = document.createElement('div'); el.className='item';
  1200.              const meta = document.createElement('div'); meta.className='meta';
  1201.              const t1 = document.createElement('div'); t1.innerHTML = `<strong>${n.mask || '+7•••'}</strong>`;
  1202.              const t2 = document.createElement('div'); t2.innerHTML = `<span class="badge">${n.status || 'неизв.'}</span> · <span class="muted">${n.date || ''}</span>`;
  1203.              meta.append(t1,t2);
  1204.              const btn = document.createElement('button'); btn.className='btn'; btn.textContent='Открыть';
  1205.              btn.addEventListener('click',()=>{ haptic(); openBot('start=cb_drop_status'); });
  1206.              el.append(meta, btn); list.appendChild(el);
  1207.            });
  1208.          })
  1209.          .catch(()=>{ list.innerHTML = '<div class="error">❌ Ошибка загрузки</div>'; });
  1210.      }
  1211.  
  1212.      function loadBonuses(){
  1213.        const list = document.getElementById('bonusList');
  1214.        fetch('get_bonuses.php', { method:'POST' })
  1215.          .then(r=>r.json())
  1216.          .then(d=>{
  1217.            document.getElementById('bonusPoints').textContent = d?.points ?? 0;
  1218.            document.getElementById('bonusRefs').textContent   = d?.refs ?? 0;
  1219.            document.getElementById('bonusUsd').textContent    = fmtUSD(d?.usd ?? 0);
  1220.            document.getElementById('bonusTier').textContent   = d?.tier || '—';
  1221.            const arr = Array.isArray(d?.list) ? d.list : [];
  1222.            if (!arr.length){ list.innerHTML = '<div class="empty">Пока бонусов нет</div>'; return; }
  1223.            list.innerHTML = '';
  1224.            arr.forEach(b=>{
  1225.              const it = document.createElement('div'); it.className='item';
  1226.              const meta = document.createElement('div'); meta.className='meta';
  1227.              const title = document.createElement('div'); title.innerHTML = `<strong>${b.title || 'Бонус'}</strong>`;
  1228.              const sub = document.createElement('div'); sub.innerHTML = `<span class="muted">${b.desc || ''}</span>`;
  1229.              meta.append(title, sub);
  1230.              const btn = document.createElement('button'); btn.className = b.claimed ? 'btn' : 'btn primary';
  1231.              btn.textContent = b.claimed ? 'Получено' : 'Забрать';
  1232.              btn.disabled = !!b.claimed;
  1233.              btn.addEventListener('click',()=>{
  1234.                haptic();
  1235.                fetch('claim_bonus.php',{method:'POST', headers:{'Content-Type':'application/json'}, body:JSON.stringify({ id:b.id })})
  1236.                  .then(r=>r.json()).then(res=>{ if (res?.ok){ btn.textContent='Получено'; btn.disabled=true; btn.className='btn'; } });
  1237.              });
  1238.              it.append(meta, btn); list.appendChild(it);
  1239.            });
  1240.          })
  1241.          .catch(()=>{ list.innerHTML = '<div class="error">❌ Не удалось загрузить бонусы</div>'; });
  1242.      }
  1243.  
  1244.      function loadContests(){
  1245.        const list = document.getElementById('contestList');
  1246.        fetch('get_contests.php', { method:'POST' })
  1247.          .then(r=>r.json())
  1248.          .then(d=>{
  1249.            const arr = Array.isArray(d?.contests) ? d.contests : [];
  1250.            if (!arr.length){ list.innerHTML = '<div class="empty">Активных конкурсов нет</div>'; return; }
  1251.            list.innerHTML = '';
  1252.            arr.forEach(c=>{
  1253.              const it = document.createElement('div'); it.className='item';
  1254.              const meta = document.createElement('div'); meta.className='meta';
  1255.              const title = document.createElement('div'); title.innerHTML = `<strong>${c.title || 'Конкурс'}</strong>`;
  1256.              const sub = document.createElement('div'); sub.innerHTML = `<span class="muted">до ${c.ends || '—'} · приз: ${c.prize || '—'}</span>`;
  1257.              const bar = document.createElement('div'); bar.className='progress-bar';
  1258.              const span = document.createElement('span'); span.style.width = Math.max(0, Math.min(100, Number(c.progress_pct||0))) + '%';
  1259.              bar.appendChild(span);
  1260.              meta.append(title, sub, bar);
  1261.  
  1262.              const btn = document.createElement('button'); btn.className='btn primary'; btn.textContent='Участвовать';
  1263.              btn.addEventListener('click',()=>{ haptic(); openBot('start=cb_profile_analytics'); });
  1264.  
  1265.              it.append(meta, btn); list.appendChild(it);
  1266.            });
  1267.          })
  1268.          .catch(()=>{ list.innerHTML = '<div class="error">❌ Ошибка загрузки конкурсов</div>'; });
  1269.      }
  1270.    })();
  1271.  </script>
  1272. <script defer src="https://static.cloudflareinsights.com/beacon.min.js/vcd15cbe7772f49c399c6a5babf22c1241717689176015" integrity="sha512-ZpsOmlRQV6y907TI0dKBHq9Md29nnaEIPlkf84rnaERnq6zvWvPUqr2ft8M1aS28oN72PdrCzSjY4U6VaAw1EQ==" data-cf-beacon='{"version":"2024.11.0","token":"5312e69668394053847c726ec76349e7","r":1,"server_timing":{"name":{"cfCacheStatus":true,"cfEdge":true,"cfExtPri":true,"cfL4":true,"cfOrigin":true,"cfSpeedBrain":true},"location_startswith":null}}' crossorigin="anonymous"></script>
  1273. </body>
  1274. </html>
  1275.  
Copyright © 2002-9 Sam Ruby, Mark Pilgrim, Joseph Walton, and Phil Ringnalda