<!DOCTYPE html>
<html lang="en" translate="no" content="notranslate">
<head>
	<meta charset='utf-8'>
  <meta name='viewport' content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
  <link rel="manifest" href="/assets/manifest-US4WrmTG.json">
  <meta name="mobile-web-app-capable" content="yes">
  <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">

  <!-- Zero-flicker boot shell. The dashboard backdrop is painted on the <html> ROOT element in the very first
       frame (set by the head script below from localStorage), with a transparent body, so the browser's
       paint-holding carries the bg seamlessly across a reload — no white, no dark gap, no blip. The body is
       transparent !important so app.css's later `bg-black` can't cover the root backdrop. -->
  <!-- Preload the boot-splash logo so it's painted with the instant splash (fetched during HTML parse). -->
  <link rel="preload" as="image" type="image/png" href="/hdp2b_logo.png" />
  <style>
    html { height: 100%; background-color: #06141b; background-size: cover; background-position: center; background-repeat: no-repeat; background-attachment: fixed; }
    /* background-attachment: fixed locks the wallpaper to the VIEWPORT, not the <html> box — so `cover` can't
       re-crop ("zoom in") when the html/layout size settles during boot. One bg, painted once, no zoom. */
    body { margin: 0; padding: 0; height: 100%; background-color: transparent !important; }
    /* Critical nav/dash fonts registered HERE (pre-JS) + preloaded below, so dash text paints in Gobold from
       the first frame instead of flipping fallback -> Gobold once the JS-loaded font.css arrives late. These two
       @font-faces are commented out in src/assets/font/gobold/font.css to avoid a duplicate download. */
    @font-face { font-family: 'Gobold'; font-display: block; font-weight: normal; font-style: normal; src: url('/fonts/Gobold.woff') format('woff'); }
    @font-face { font-family: 'Gobold Italic'; font-display: block; font-weight: normal; font-style: italic; src: url('/fonts/GoboldItalic-Italic.woff') format('woff'); }
  </style>

  <!-- Preload the critical nav fonts so they're fetched immediately (pre-JS), ready before dash text paints. -->
  <link rel="preload" as="font" type="font/woff" href="/fonts/Gobold.woff" crossorigin>
  <link rel="preload" as="font" type="font/woff" href="/fonts/GoboldItalic-Italic.woff" crossorigin>

  <!-- Zero-flicker: paint last session's backdrop on the ROOT element in the first frame (before <body> parses). -->
  <script>
    try {
      var _bg = localStorage.getItem('hdp_lastBg');
      if (_bg) {
        // Set the FULL background INLINE on <html> (inline beats every stylesheet) so `cover` is guaranteed from
        // the very first frame. Something at runtime resets the <style> rule's background-size to `auto`, which
        // made the wallpaper render at natural size = the "zoomed-in corner". Inline cover kills that dead.
        var d = document.documentElement.style;
        d.backgroundImage = "url('" + _bg + "')";
        d.backgroundSize = 'cover';
        d.backgroundPosition = 'center';
        d.backgroundRepeat = 'no-repeat';
      }
    } catch (e) {}
  </script>

  <!-- PLAN ALPHA A1: pre-warm the game WebSocket DURING the boot-chunk download+parse. The app's socket layer
       (socket-window.ts) ADOPTS window.__hdpEarlyWS when its connect URL matches, so the TCP/TLS/WS-upgrade
       handshake (~1-2 RTT) overlaps the JS prelude instead of running serially after mount. Returning users
       only (needs stored auth). Pure pre-warm: any mismatch/error -> the app opens a fresh socket. -->
  <script>
    try {
      var _auth = JSON.parse(localStorage.getItem('auth') || 'null');
      var _wsUrl = _auth && _auth.authObject && _auth.authObject.server && _auth.authObject.server.ws;
      // Skip if a ?server= override is present (the app would connect to a different URL -> wasted socket).
      var _override = /[?&]server=/.test(location.search);
      if (_wsUrl && !_override && 'WebSocket' in window) {
        var _ews = new WebSocket(_wsUrl);
        _ews.binaryType = 'arraybuffer';
        _ews.__hdpUrl = _wsUrl;
        _ews.__hdpErrored = false;
        _ews.onerror = function () { _ews.__hdpErrored = true; };
        // Buffer anything the server might push before the app attaches its real handler (none expected in
        // this client-authenticates-first protocol, but this makes adoption lossless either way).
        _ews.onmessage = function (e) { (_ews.__hdpBuf = _ews.__hdpBuf || []).push(e.data); };
        window.__hdpEarlyWS = _ews;
      }
    } catch (e) {}
  </script>

  <!-- Primary Meta Tags -->
  <meta name="title" content="Play HD Poker™ — the best free Texas Hold'em game online.">
  <meta name="description" content="Experience Texas Hold'em like never before! Free poker, tournaments, and friends — available on mobile and PC.">
  <meta name="keywords" content="HD Poker, free poker app, online poker, Texas Hold'em, poker game, multiplayer poker, social casino, poker download, mobile poker, real poker experience">
  <meta name="author" content="HD Poker, LLC">
  <meta name="robots" content="index, follow">
  <meta name="theme-color" content="#0a0a0a">

  <!-- App Store and Google Play Integration -->
  <meta name="apple-itunes-app" content="app-id=875589196"> <!-- put back in when we have the read partnerID , affiliate-data=partnerId=123456 -->
  <meta name="google-play-app" content="app-id=com.hdpoker.game">
  <link rel="alternate" href="https://apps.apple.com/app/hd-poker/id875589196" />
  <link rel="alternate" href="https://play.google.com/store/apps/details?id=com.hdpoker.game" />

  <!-- Open Graph -->
  <meta property="og:type" content="website">
  <meta property="og:url" content="https://www.hd.poker/sos">
  <meta property="og:title" content="Play HD Poker™ — the best free Texas Hold'em game online.">
  <meta property="og:description" content="Experience Texas Hold'em like never before! Free poker, tournaments, and friends — available on mobile and PC.">
  <meta property="og:image" content="https://cdn.branch.io/branch-assets/1606176300737-og_image.png">
  <meta property="og:site_name" content="HD Poker™">
  <meta property="og:locale" content="en_US">

  <!-- Twitter -->
  <meta name="twitter:card" content="summary_large_image">
  <meta name="twitter:url" content="https://www.hd.poker/sos">
  <meta name="twitter:title" content="Play HD Poker™ — the best free Texas Hold'em game online.">
  <meta name="twitter:description" content="Experience Texas Hold'em like never before! Free poker, tournaments, and friends — available on mobile and PC.">
  <meta name="twitter:image" content="https://cdn.branch.io/branch-assets/1606176300737-og_image.png">
  <meta name="twitter:creator" content="HD Poker™">

  <!-- Schema.org for Game + Mobile App -->
  <script type="application/ld+json">
    {
      "@context": "https://schema.org",
      "@type": "VideoGame",
      "name": "HD Poker",
      "url": "https://www.hdpoker.com/",
      "image": "https://cdn.branch.io/branch-assets/1606176300737-og_image.png",
      "description": "HD Poker is a free Texas Hold'em poker game featuring rich 3D environments, multiplayer tournaments, and social play. Available on iOS, Android, and Windows.",
      "applicationCategory": "Game",
      "genre": ["Card Game", "Casino", "Multiplayer"],
      "operatingSystem": ["iOS", "Android", "Windows"],
      "offers": {
        "@type": "Offer",
        "price": "0",
        "priceCurrency": "USD",
        "category": "FreeToPlay"
      },
      "publisher": {
        "@type": "Organization",
        "name": "HD Poker, LLC",
        "url": "https://www.hdpoker.com/"
      },
      "sameAs": [
        "https://www.facebook.com/HDPoker",
        "https://twitter.com/HDPokerGame",
        "https://www.instagram.com/hdpoker/",
        "https://www.youtube.com/@HDPoker"
      ]
    }
  </script>

  <link rel="icon" href="/assets/icon_128x128-BtGivEB9.png">

  <!-- Material Icons made NON-render-blocking. Was a plain stylesheet link → blocked first paint on a round-trip
       to Google Fonts. media=print loads it without blocking, then swaps to 'all' once loaded; preconnect warms the
       font hosts. Tradeoff: icons pop in a beat after first paint (icon-FOUT) instead of holding the whole render.
       Cleaner future fix: self-host the Material Icons woff2 in public/fonts (kills the external round-trip). -->
  <link rel="preconnect" href="https://fonts.googleapis.com">
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
  <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet" media="print" onload="this.media='all'">
  <noscript><link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"></noscript>
  <!-- <script src="https://www.google.com/recaptcha/api.js?render=6LfEY2QrAAAAAGG9P75EaznKWf-hyFWxJ5doE6cK" async defer></script> -->
  <script src="https://accounts.google.com/gsi/client" async defer></script>
  <script src="https://apis.google.com/js/api:client.js" async defer></script>
  <script src="https://appleid.cdn-apple.com/appleauth/static/jsapi/appleid/1/en_US/appleid.auth.js" async defer></script>

  <!-- Check for related apps -->
  <!-- getInstalledRelatedApps() is supported on Chromium-based browsers (Chrome, Edge, Opera, Samsung Internet) on Android and Windows.
       It is ALSO top-level-only. Inside an iframe (Facebook Canvas, Instant Games, any embed) the method still EXISTS on
       navigator, so the `in` check passes and the call then rejects with
       "InvalidStateError: ... only supported in top-level browsing contexts" — a guaranteed console error on every FB boot.
       `window.top === window.self` is the correct guard: it is readable cross-origin and never throws (unlike
       window.top.location, which is a SecurityError in a cross-origin frame). try/catch is belt-and-braces for
       sandboxed frames. -->
  <script>
    (function () {
      var isTopLevel;
      try { isTopLevel = window.top === window.self; } catch (e) { isTopLevel = false; }
      if (!isTopLevel || !('getInstalledRelatedApps' in navigator)) return;
      navigator.getInstalledRelatedApps().then(related => {
        console.log('Checking for related apps...', related);
      }).catch(error => {
        console.log('Error checking for related apps.', error);
      });
    })();
  </script>

  <!-- Twitter + Meta ad pixels, boot-deferred (2026-07-18 perf): the queue stubs (twq/fbq) are
       created inline so any early conversion calls buffer, but the tracker SCRIPTS (uwt.js,
       fbevents.js) used to load at parse time and compete with boot for main thread + network.
       They now inject on first idle after window load and flush the queued calls — same data,
       zero boot cost. (Same pattern as the idle-deferred GA in main.ts.) -->
  <script>
    // stubs: buffer calls until the real scripts load
    !function(e){e.twq||((e.twq=function(){e.twq.exe?e.twq.exe.apply(e.twq,arguments):e.twq.queue.push(arguments)}).version='1.1',e.twq.queue=[])}(window);
    twq('config','ogsi4');
    !function(f){if(f.fbq)return;var n=f.fbq=function(){n.callMethod?n.callMethod.apply(n,arguments):n.queue.push(arguments)};
    if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0';n.queue=[]}(window);
    fbq('init', '1018961811567259');
    fbq('track', 'PageView');
    // idle-deferred script injection
    window.addEventListener('load', function () {
      var inject = function () {
        [['https://static.ads-twitter.com/uwt.js'], ['https://connect.facebook.net/en_US/fbevents.js']].forEach(function (src) {
          var s = document.createElement('script'); s.async = true; s.src = src[0];
          document.head.appendChild(s);
        });
      };
      ('requestIdleCallback' in window) ? requestIdleCallback(inject, { timeout: 10000 }) : setTimeout(inject, 3000);
    });
  </script>
  
  <title>HD Poker | Online Texas Hold'em</title>
  <script type="module" crossorigin src="/assets/index-CP3k2cJ0.js"></script>
  <link rel="modulepreload" crossorigin href="/assets/vendor-howler-B8wQQhvK.js">
  <link rel="modulepreload" crossorigin href="/assets/vendor-pixi-3EXvgAsF.js">
  <link rel="modulepreload" crossorigin href="/assets/vendor-rxjs-FLhMquL-.js">
  <link rel="stylesheet" crossorigin href="/assets/index-X7zHpzUX.css">
</head>
<body>

<!-- INSTANT boot splash + loading bar — painted in the FIRST frame (like the <html> backdrop above), so it's
     there immediately on F5 with zero image fetch. The bar tracks REAL boot via window.__bootProgress(pct)
     (called from main.ts + App.svelte at boot milestones) and finishes via window.__bootSplashDone() when the
     dash is revealed. Sits over the backdrop; the dash itself stays hidden behind the reveal gate until ready. -->
<div id="boot-splash">
  <div id="bs-center">
    <img id="bs-logo" src="/hdp2b_logo.png" alt="HD Poker 2 Beta" width="584" height="112" />
    <div id="bs-spade" role="progressbar" aria-label="Loading">
      <svg viewBox="0 0 37 53" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
        <path fill="#ffffff" fill-rule="evenodd" d="M8.83,48.14c-2.66,0-5.65-0.91-7.08-3.33C1.24,43.95,1,42.99,1,42c0-4.91,4.86-9.65,8.31-12.64c1.3-1.13,2.64-2.21,4-3.28c1.9-1.5,3.84-2.96,5.8-4.38c0.82-0.59,1.65-1.19,2.48-1.76l0,0l0,0c0.44-0.21,3.58-1,3.9-0.76c0.12,0.09,0.28,0.27,0.38,0.39c0.23,0.25,0.45,0.51,0.67,0.77c0.62,0.73,1.22,1.46,1.83,2.2c0.87,1.06,1.73,2.12,2.6,3.18c1.76,2.14,3.38,4.27,4.56,6.8c0.69,1.48,1.25,3.17,1.25,4.82c0,2.76-1.32,5.37-3.29,7.26c-2.21,2.12-5.13,3.28-8.19,3.28c-1.38,0-2.84-0.16-4.09-0.79c-0.34-0.17-0.64-0.37-0.96-0.58c-0.2-0.13-0.43-0.28-0.67-0.33c-0.06-0.01-0.12-0.02-0.18-0.02c-0.48,0-0.66,0.14-0.66,0.64c0,0.93,1.48,2.49,2.16,3.1c0.41,0.36,0.92,0.7,1.38,1c0.44,0.29,0.88,0.56,1.31,0.86c0.15,0.1,0.64,0.43,0.64,0.63c0,0.01,0,0.03,0,0.04c0.02,0.29-0.41,0.27-0.6,0.27c-5.19,0-10.38,0.07-15.57,0.07c-0.3,0-0.94,0.03-0.94-0.4c0-0.36,1.39-0.93,1.66-1.05c1.35-0.61,2.69-1.2,4.02-1.86c0.87-0.43,2.14-1.08,2.84-1.77c0.22-0.22,0.41-0.45,0.41-0.77s-0.39-0.49-0.67-0.49s-0.64,0.16-0.88,0.26c-0.46,0.2-0.91,0.41-1.37,0.6c-1.4,0.57-2.78,0.88-4.3,0.88L8.83,48.14z"/>
        <path fill="#1fd6e3" fill-rule="evenodd" d="M10.18,22.83c0-1.17,1.76-2.68,2.59-3.34c1.76-1.4,3.87-2.61,5.92-3.53c2.23-1.01,5.05-1.98,7.52-1.98c0.93,0,2.47,0.13,2.47,1.38c0,0.74-0.5,1.54-1.07,1.99l-0.25,0.2l0.09-0.31c0.27-0.93-0.35-1.28-1.21-1.28c-2.16,0-4.71,0.9-6.66,1.78c-1.78,0.81-3.62,1.84-5.17,3.04c-0.63,0.48-2.21,1.78-2.21,2.67c0,0.2,0.05,0.51,0.18,0.67l0.12,0.15l-0.19,0.02c-1.09,0.11-2.1-0.09-2.1-1.45L10.18,22.83z"/>
        <path fill="#1fd6e3" fill-rule="evenodd" d="M25.51,6.23c-0.37,1.38-0.59,2.91-0.42,4.33c0.05,0.42,0.17,1.08,0.37,1.46l0.08,0.15h-0.17c-3.32,0.06-6.6,1.17-9.48,2.78c-1.18,0.66-2.32,1.42-3.37,2.27c-0.67,0.54-1.43,1.21-1.96,1.89l-0.13,0.16l-0.06-0.2c-0.19-0.65-0.94-1.54-1.4-2c-0.7-0.7-1.72-1.1-2.68-1.29c-0.24,0.44-0.71,0.72-1.22,0.72c-0.77,0-1.4-0.62-1.4-1.4s0.62-1.4,1.4-1.4c0.58,0,1.09,0.35,1.3,0.88c0.42-0.08,0.85-0.14,1.28-0.2c0.97-0.11,1.98-0.18,2.96-0.21c-1.14-1.44-2.44-2.87-3.82-4.08c-0.25,0.21-0.57,0.33-0.9,0.33c-0.77,0-1.4-0.62-1.4-1.4s0.62-1.4,1.4-1.4s1.4,0.62,1.4,1.4c0,0.05,0,0.09,0,0.14C7.7,9.18,8.11,9.22,8.51,9.28c1.44,0.21,3.1,0.66,4.48,1.19c-0.2-1.27-0.38-2.56-0.57-3.83c-0.17-1.2-0.35-2.4-0.52-3.61c-0.02,0-0.04,0-0.07,0c-0.84,0-1.53-0.69-1.53-1.53s0.68-1.53,1.53-1.53s1.53,0.69,1.53,1.53c0,0.34-0.11,0.66-0.31,0.93c1.68,1.82,3.34,3.68,4.99,5.53c0.63-1.68,1.43-3.41,2.41-4.92c-0.37-0.27-0.59-0.69-0.59-1.16c0-0.79,0.64-1.42,1.42-1.42S22.7,1.1,22.7,1.88c0,0.67-0.47,1.25-1.12,1.39c0.09,1.24,0.22,2.48,0.42,3.7c0.07,0.42,0.14,0.85,0.22,1.27c0.68-0.94,1.52-1.81,2.39-2.58c-0.18-0.24-0.28-0.53-0.28-0.83c0-0.76,0.61-1.37,1.37-1.37s1.37,0.61,1.37,1.37S26.46,6.2,25.7,6.2c-0.06,0-0.12,0-0.18-0.01L25.51,6.23z"/>
      </svg>
    </div>
    <div id="bs-verb">Loading…</div>
  </div>
  <div id="bs-track"><div id="bs-fill"></div></div>
</div>
<style>
  #boot-splash{position:fixed;inset:0;z-index:2147483646;pointer-events:none;opacity:1;transition:opacity .35s ease;}
  #boot-splash.bs-done{opacity:0;}
  #bs-center{position:absolute;left:50%;top:46%;transform:translate(-50%,-50%);display:flex;flex-direction:column;align-items:center;gap:16px;text-align:center;}
  /* aspect-ratio reserves the logo's height from frame 0 (even before the PNG decodes) so the center-anchored
     block can't re-flow and shove the logo up a few px mid-load. Tighter, darker drop-shadow so it reads. */
  #bs-logo{width:clamp(230px,34vw,430px);aspect-ratio:584 / 112;height:auto;filter:drop-shadow(0 0 0.5px #000) drop-shadow(0 0 0.5px #000)}
  #bs-spade{width:clamp(38px,5.5vh,54px);height:clamp(54px,7.9vh,77px);animation:bs-spin 1.25s cubic-bezier(.5,0,.5,1) infinite;filter:drop-shadow(0 0 9px rgba(0,251,255,.5));will-change:transform;}
  #bs-spade svg{transform-origin:20% 50%;width:100%;height:100%;display:block;perspective:1000;stroke:#091d27;stroke-width:0.5px;}
  @keyframes bs-spin{to{transform:rotateY(360deg);}}
  #bs-verb{font-family:system-ui,-apple-system,sans-serif;font-weight:600;font-size:clamp(16px,2vw,22px);color:#ffffff;letter-spacing:.04em;filter:drop-shadow(0 0 1px #000a) drop-shadow(0 0 1px #000a)}
  #bs-track{position:absolute;left:0;right:0;bottom:0;height:6px;background:rgba(0,0,0,.30);}
  #bs-fill{height:100%;width:0%;background:linear-gradient(90deg,#00898b,#00fbff);box-shadow:0 0 10px rgba(0,251,255,.6);transition:width .22s ease-out;}
</style>
<script>
  (function(){
    var fill=document.getElementById('bs-fill'), verb=document.getElementById('bs-verb'), splash=document.getElementById('boot-splash');
    if(!fill) return;
    var target=6, shown=0, done=false;
    // App reports real milestones; we only move forward and cap at 99 until done() finishes it.
    window.__bootProgress=function(p){ p=+p||0; if(p>target) target=Math.min(p,99); };
    window.__bootSplashDone=function(){ if(done) return; done=true; fill.style.width='100%'; splash.className='bs-done';
      setTimeout(function(){ if(splash.parentNode) splash.parentNode.removeChild(splash); }, 420); };
    // The bar always moves: a time-based curve auto-advances it "quickly left to right" during the JS prelude
    // (so it never stalls while the boot chunk parses), and real milestones (target) snap it forward when ahead.
    var t0=performance.now();
    (function tick(){ if(done) return;
      var el=performance.now()-t0;
      var timeTarget=88*(1-Math.exp(-el/1600));   // eases toward ~88% over a few seconds
      var t=Math.max(target,timeTarget);          // real boot milestones win when they're ahead of the curve
      shown += Math.max(0.15,(t-shown)*0.09);
      if(shown>99) shown=99;
      fill.style.width=shown.toFixed(1)+'%';
      requestAnimationFrame(tick);
    })();
    document.addEventListener('DOMContentLoaded', function(){ window.__bootProgress(22); });
    window.addEventListener('load', function(){ window.__bootProgress(34); });
    var verbs=['Shuffling Decks…','Counting Chips…','Raking the Pot…','Seeding RNG…','Waxing the Felt…','Calculating Odds…'], vi=0;
    setInterval(function(){ if(!done&&verb) verb.textContent=verbs[(vi++)%verbs.length]; }, 1500);
  })();
</script>

<!-- Meta Pixel Code -->
<noscript><img height="1" width="1" style="display:none"
  src="https://www.facebook.com/tr?id=1018961811567259&ev=PageView&noscript=1"/>
</noscript>
<!-- End Meta Pixel Code -->
 
</body>
</html>