<?php
/**
 * Convert 2-letter ISO Country Code to Unicode Regional Indicator Flag
 */
function getUnicodeFlag(string $countryCode): string {
    $code = strtoupper(trim($countryCode));
    if (strlen($code) !== 2 || !ctype_alpha($code)) {
        return '🌐';
    }

    $cp1 = 127397 + ord($code[0]);
    $cp2 = 127397 + ord($code[1]);

    if (function_exists('mb_chr')) {
        return mb_chr($cp1, 'UTF-8') . mb_chr($cp2, 'UTF-8');
    }

    $binary = pack('N2', $cp1, $cp2);
    if (function_exists('mb_convert_encoding')) {
        return mb_convert_encoding($binary, 'UTF-8', 'UTF-32BE');
    }

    return iconv('UTF-32BE', 'UTF-8', $binary);
}

/**
 * Format raw IPv4 or IPv6 string into hyphenated representation
 */
function formatIpToHyphen(string $ip): string {
    $ip = trim($ip);
    if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
        $packed = @inet_pton($ip);
        if ($packed !== false) {
            $hex = unpack("H*", $packed);
            $ip = implode(':', str_split($hex[1], 4));
        }
    }
    return str_replace(['.', ':'], '-', $ip);
}

/**
 * Fast DNS Lookup with strict timeout prevention
 */
function resolveCountryFast(string $domain, string $default = 'UNKNOWN'): string {
    if (strpos($domain, '127-0-0-1') === 0 || strpos($domain, '192-168-') === 0 || strpos($domain, '10-') === 0) {
        return $default;
    }

    $oldTimeout = ini_get('default_socket_timeout');
    ini_set('default_socket_timeout', '1');
    
    $dnsRecords = @dns_get_record($domain, DNS_TXT);
    
    ini_set('default_socket_timeout', $oldTimeout);

    if (!empty($dnsRecords)) {
        $val = $dnsRecords[0]['txt'] ?? ($dnsRecords[0]['entries'][0] ?? null);
        if ($val !== null) {
            $country = strtoupper(trim($val, '"'));
            if (strlen($country) === 2 && ctype_alpha($country)) {
                return $country;
            }
        }
    }

    return $default;
}

/**
 * Safely retrieve real IP behind proxies (Cloudflare, Load Balancers, etc.)
 */
function getRealClientIp(): string {
    $headers = ['HTTP_CF_CONNECTING_IP', 'HTTP_X_REAL_IP', 'HTTP_X_FORWARDED_FOR'];
    foreach ($headers as $header) {
        if (!empty($_SERVER[$header])) {
            $ips = explode(',', $_SERVER[$header]);
            $ip = trim($ips[0]);
            if (filter_var($ip, FILTER_VALIDATE_IP)) {
                return $ip;
            }
        }
    }
    return $_SERVER['REMOTE_ADDR'] ?? '127.0.0.1';
}

/**
 * Generate a random IP from the RIPE IPv4 subnet (194.39.253.0/24)
 */
function getRandomIpv4(): string {
    return '194.39.253.' . random_int(1, 254);
}

/**
 * Generate a random IP from the RIPE IPv6 subnet (2001:67c:c40::/48)
 */
function getRandomIpv6(): string {
    return sprintf('2001:67c:c40:%x:%x:%x:%x:%x', 
        random_int(0, 65535), random_int(0, 65535), 
        random_int(0, 65535), random_int(0, 65535), random_int(1, 65535)
    );
}

// -------------------------------------------------------------------------
// DUAL-STACK CONFIGURATION & DETECTED CLIENT IP
// -------------------------------------------------------------------------
$clientIp     = getRealClientIp();
$isClientIpv6 = filter_var($clientIp, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6);

$ipv4Addr     = $isClientIpv6 ? getRandomIpv4() : $clientIp;
$ipv6Addr     = $isClientIpv6 ? $clientIp : getRandomIpv6();

// Clean Hyphenated IPs
$hyphenIpv4   = formatIpToHyphen($ipv4Addr);
$hyphenIpv6   = formatIpToHyphen($ipv6Addr);

// Formatted Domains
$domainIpv4   = "{$hyphenIpv4}.free.query.ip2cc.com";
$domainIpv6   = "{$hyphenIpv6}.free.query.ip2cc.com";

// Single DNS lookup: Active protocol triggers lookup, inactive hardcodes to 'ES'
$countryIpv4  = !$isClientIpv6 ? resolveCountryFast($domainIpv4, 'UNKNOWN') : 'ES';
$countryIpv6  = $isClientIpv6 ? resolveCountryFast($domainIpv6, 'UNKNOWN') : 'ES';

$flagIpv4 = getUnicodeFlag($countryIpv4);
$flagIpv6 = getUnicodeFlag($countryIpv6);

// Build structured data array for secure JSON injection into JavaScript
$jsData = [
    'v4' => [
        'ip' => $ipv4Addr,
        'domain' => $domainIpv4,
        'hyphen' => $hyphenIpv4,
        'country' => $countryIpv4,
        'flag' => $flagIpv4,
        'replaceText' => 'Replace dots (<code>.</code>) with hyphens (<code>-</code>):'
    ],
    'v6' => [
        'ip' => $ipv6Addr,
        'domain' => $domainIpv6,
        'hyphen' => $hyphenIpv6,
        'country' => $countryIpv6,
        'flag' => $flagIpv6,
        'replaceText' => 'Replace colons (<code>:</code>) with hyphens (<code>-</code>):'
    ]
];
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>IP2CC — High-Performance DNS-Based IP to Country Code API</title>
    <meta name="description" content="Ultra-fast IP address to ISO country code query service powered by standard DNS infrastructure. Free for personal and non-profit use.">
    <meta name="theme-color" content="#005A9C">
    
    <style>
        :root {
            --bg-color: #f8fafc;
            --card-bg: #ffffff;
            --text-main: #1e293b;
            --text-muted: #64748b;
            --primary: #005A9C;
            --primary-hover: #004070;
            --accent: #2563eb;
            --code-bg: #0f172a;
            --code-text: #f8fafc;
            --border-color: #e2e8f0;
            --shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
            --radius: 8px;
            --success-bg: #dcfce7;
            --success-text: #166534;
            --success-border: #86efac;
        }

        @media (prefers-color-scheme: dark) {
            :root {
                --bg-color: #0f172a;
                --card-bg: #1e293b;
                --text-main: #f8fafc;
                --text-muted: #94a3b8;
                --primary: #38bdf8;
                --primary-hover: #7dd3fc;
                --accent: #60a5fa;
                --code-bg: #020617;
                --code-text: #e2e8f0;
                --border-color: #334155;
                --success-bg: #064e3b;
                --success-text: #a7f3d0;
                --success-border: #059669;
            }
        }

        * { box-sizing: border-box; }

        body {
            font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
            margin: 0;
            padding: 24px 16px;
            line-height: 1.6;
            color: var(--text-main);
            background-color: var(--bg-color);
        }

        .container {
            max-width: 860px;
            margin: 0 auto;
        }

        header {
            margin-bottom: 24px;
            border-bottom: 2px solid var(--border-color);
            padding-bottom: 16px;
        }

        h1 {
            font-size: 2.25rem;
            color: var(--primary);
            margin: 0 0 4px 0;
            font-weight: 800;
            letter-spacing: -0.025em;
        }

        .subtitle {
            font-size: 1.1rem;
            color: var(--text-muted);
            margin: 0;
            font-weight: 500;
        }

        h2 {
            font-size: 1.5rem;
            color: var(--primary);
            margin-top: 32px;
            margin-bottom: 12px;
            letter-spacing: -0.02em;
        }

        p, li {
            font-size: 1rem;
            color: var(--text-main);
        }

        a {
            color: var(--accent);
            text-decoration: none;
            font-weight: 500;
            transition: color 0.2s ease;
        }

        a:hover, a:focus {
            color: var(--primary-hover);
            text-decoration: underline;
        }

        .card {
            background: var(--card-bg);
            border: 1px solid var(--border-color);
            border-radius: var(--radius);
            padding: 24px;
            margin-bottom: 24px;
            box-shadow: var(--shadow);
        }

        .tab-bar {
            display: flex;
            align-items: center;
            justify-content: space-between;
            background: rgba(15, 23, 42, 0.05);
            border: 1px solid var(--border-color);
            border-bottom: none;
            border-radius: 6px 6px 0 0;
            padding: 6px 12px;
            margin-top: 16px;
        }

        @media (prefers-color-scheme: dark) {
            .tab-bar {
                background: rgba(255, 255, 255, 0.05);
            }
        }

        .tab-bar-title {
            font-size: 0.8rem;
            font-weight: 700;
            color: var(--text-muted);
            text-transform: uppercase;
            letter-spacing: 0.05em;
        }

        .tab-group {
            display: inline-flex;
            gap: 4px;
            background: var(--bg-color);
            padding: 2px;
            border-radius: 4px;
            border: 1px solid var(--border-color);
        }

        .tab-btn {
            border: none;
            background: transparent;
            color: var(--text-muted);
            font-weight: 700;
            font-size: 0.78rem;
            padding: 3px 10px;
            border-radius: 3px;
            cursor: pointer;
            transition: all 0.15s ease;
        }

        .tab-btn.active {
            background: var(--primary);
            color: #ffffff;
        }

        .tab-btn:hover:not(.active) {
            color: var(--text-main);
        }

        .lang-tabs {
            display: flex;
            gap: 6px;
            border-bottom: 2px solid var(--border-color);
            margin-bottom: 0;
            padding-bottom: 0;
            overflow-x: auto;
        }

        .lang-tab {
            padding: 8px 16px;
            border: 1px solid transparent;
            border-bottom: none;
            border-radius: 6px 6px 0 0;
            background: transparent;
            color: var(--text-muted);
            font-weight: 600;
            font-size: 0.9rem;
            cursor: pointer;
            margin-bottom: -2px;
            transition: all 0.2s;
            white-space: nowrap;
        }

        .lang-tab.active {
            background: var(--code-bg);
            color: #ffffff;
            border-color: var(--border-color);
        }

        .lang-tab:hover:not(.active) {
            color: var(--text-main);
            background: rgba(0, 0, 0, 0.03);
        }

        .tab-bar + .code-container,
        .tab-bar + .output-card {
            margin-top: 0 !important;
            border-top-left-radius: 0 !important;
            border-top-right-radius: 0 !important;
        }

        .notice-box {
            background-color: rgba(37, 99, 235, 0.08);
            border-left: 4px solid var(--accent);
            padding: 16px;
            border-radius: 0 var(--radius) var(--radius) 0;
            margin: 20px 0;
        }

        ol, ul { padding-left: 20px; }
        li { margin-bottom: 8px; }

        .output-card {
            padding: 20px;
            background: var(--bg-color);
            border: 1px solid var(--border-color);
            border-radius: 6px;
        }

        .output-row {
            display: flex;
            flex-direction: column;
            gap: 6px;
            margin-bottom: 16px;
        }

        .output-row:last-child { margin-bottom: 0; }

        .output-label {
            font-size: 0.8rem;
            text-transform: uppercase;
            letter-spacing: 0.05em;
            color: var(--text-muted);
            font-weight: 700;
        }

        .gen-output {
            padding: 10px 12px;
            background: var(--code-bg);
            color: var(--code-text);
            border-radius: 6px;
            font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
            font-size: 0.95rem;
            word-break: break-all;
        }

        .country-badge {
            display: inline-flex;
            align-items: center;
            gap: 12px;
            padding: 10px 18px;
            background: var(--success-bg);
            color: var(--success-text);
            border: 1px solid var(--success-border);
            border-radius: 6px;
            font-weight: 700;
            font-size: 1.3rem;
            width: fit-content;
        }

        .flag-emoji {
            font-size: 1.6rem;
            line-height: 1;
            font-family: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
        }

        .code-container {
            position: relative;
            margin: 0 0 24px 0;
        }

        pre {
            background-color: var(--code-bg);
            color: var(--code-text);
            padding: 18px;
            border-radius: var(--radius);
            overflow-x: auto;
            font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
            font-size: 0.9rem;
            margin: 0;
            line-height: 1.5;
        }

        .copy-btn {
            position: absolute;
            top: 10px;
            right: 10px;
            background: rgba(255, 255, 255, 0.15);
            color: #fff;
            border: none;
            padding: 4px 10px;
            border-radius: 4px;
            font-size: 0.75rem;
            cursor: pointer;
            backdrop-filter: blur(4px);
            transition: background 0.2s;
        }

        .copy-btn:hover { background: rgba(255, 255, 255, 0.3); }

        .pricing-grid {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
            gap: 20px;
            margin-top: 20px;
        }

        .price-card {
            border: 1px solid var(--border-color);
            border-radius: var(--radius);
            padding: 24px;
            background: var(--bg-color);
            display: flex;
            flex-direction: column;
            justify-content: space-between;
        }

        .price-card.featured {
            border: 2px solid var(--accent);
            box-shadow: var(--shadow);
            position: relative;
        }

        .price-tag {
            font-size: 2.2rem;
            font-weight: 800;
            color: var(--primary);
            margin: 12px 0 4px 0;
        }

        .price-subtext {
            font-size: 0.85rem;
            color: var(--text-muted);
            margin-bottom: 16px;
        }

        .btn-buy {
            display: inline-block;
            text-align: center;
            background: var(--primary);
            color: #ffffff !important;
            padding: 12px 18px;
            border-radius: 6px;
            font-weight: 700;
            text-decoration: none !important;
            transition: background 0.2s;
            margin-top: 16px;
        }

        .btn-buy:hover {
            background: var(--primary-hover);
        }

        .btn-free {
            background: transparent;
            color: var(--text-main) !important;
            border: 1px solid var(--border-color);
        }

        .btn-free:hover {
            background: rgba(0, 0, 0, 0.05);
        }

        .app-badge {
            display: inline-block;
            margin-top: 10px;
            transition: transform 0.2s;
        }

        .app-badge:hover { transform: translateY(-2px); }

        footer {
            margin-top: 48px;
            padding-top: 24px;
            border-top: 1px solid var(--border-color);
            text-align: center;
            font-size: 0.875rem;
            color: var(--text-muted);
        }

        footer a { color: var(--text-muted); }

        @media (max-width: 600px) {
            body { padding: 16px 12px; }
            h1 { font-size: 1.75rem; }
            .subtitle { font-size: 1rem; }
            .card { padding: 16px; }
        }
    </style>
</head>
<body>

<div class="container">
    <header>
        <h1>IP2CC</h1>
        <p class="subtitle">High-performance IP address to ISO country code lookup via global DNS infrastructure</p>
    </header>

    <main>
        <section class="card">
            <h2>About IP2CC</h2>
            <p><strong>IP2CC</strong> provides near-zero latency IP-to-country lookups. By delivering data natively over standard <strong>DNS infrastructure</strong>, queries benefit from global edge-caching and high-availability resolution, avoiding slow HTTP REST API roundtrips.</p>
            
            <p>Looking up your own local public IP on mobile? Download our Android application:</p>
            <a href="https://play.google.com/store/apps/details?id=com.calpeconsulting.ip2cc" target="_blank" rel="noopener" class="app-badge">
                <img src="play.png" alt="Get IP2CC on Google Play" height="48">
            </a>
        </section>

        <section class="card">
            <h2>Your Connection Info</h2>
            <p>Below is your active connection information and computed DNS query domain:</p>

            <div class="tab-bar">
                <span class="tab-bar-title">IP Version</span>
                <div class="tab-group">
                    <button class="tab-btn tab-btn-v4 <?php echo !$isClientIpv6 ? 'active' : ''; ?>" onclick="setGlobalProto('v4')">IPv4</button>
                    <button class="tab-btn tab-btn-v6 <?php echo $isClientIpv6 ? 'active' : ''; ?>" onclick="setGlobalProto('v6')">IPv6</button>
                </div>
            </div>

            <div class="output-card">
                <div class="output-row">
                    <span class="output-label">Client IP</span>
                    <div class="gen-output" id="out-ip"><?php echo htmlspecialchars($isClientIpv6 ? $ipv6Addr : $ipv4Addr); ?></div>
                </div>

                <div class="output-row">
                    <span class="output-label">DNS TXT Query Domain</span>
                    <div class="gen-output" id="out-domain"><?php echo htmlspecialchars($isClientIpv6 ? $domainIpv6 : $domainIpv4); ?></div>
                </div>

                <div class="output-row">
                    <span class="output-label">Country Code</span>
                    <div class="country-badge">
                        <span id="out-country"><?php echo htmlspecialchars($isClientIpv6 ? $countryIpv6 : $countryIpv4); ?></span>
                        <span class="flag-emoji" id="out-flag"><?php echo $isClientIpv6 ? $flagIpv6 : $flagIpv4; ?></span>
                    </div>
                </div>
            </div>
        </section>

        <section class="card">
            <h2>How It Works</h2>
            <p>To resolve an IP address, query the <strong>TXT record</strong> (only TXT, never A or MX) of the hyphenated IP address appended to <code>.free.query.ip2cc.com</code>. The DNS response delivers a <a href="https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2" target="_blank" rel="noopener">2-letter ISO country code</a>.</p>

            <ol>
                <li>
                    <span id="step-char-desc">Replace dots (<code>.</code>) with hyphens (<code>-</code>):</span>
                    <br>
                    <code><span id="step-ip"><?php echo htmlspecialchars($isClientIpv6 ? $ipv6Addr : $ipv4Addr); ?></span></code> &rarr; <code><span id="step-hyphen"><?php echo htmlspecialchars($isClientIpv6 ? $hyphenIpv6 : $hyphenIpv4); ?></span></code>
                </li>
                <li>
                    Append query domain and request the TXT record:
                    <br>
                    <code><span id="step-domain"><?php echo htmlspecialchars($isClientIpv6 ? $domainIpv6 : $domainIpv4); ?></span></code>
                </li>
            </ol>

            <div class="notice-box">
                <strong>Important:</strong> Always execute queries via your operating system's standard recursive DNS resolver. Direct recursive sweeps or non-TXT query types on free endpoints are subject to rate limiting.
            </div>
        </section>

        <section class="card">
            <h2>CLI Examples</h2>

            <div class="tab-bar">
                <span class="tab-bar-title">dig</span>
                <div class="tab-group">
                    <button class="tab-btn tab-btn-v4 <?php echo !$isClientIpv6 ? 'active' : ''; ?>" onclick="setGlobalProto('v4')">IPv4</button>
                    <button class="tab-btn tab-btn-v6 <?php echo $isClientIpv6 ? 'active' : ''; ?>" onclick="setGlobalProto('v6')">IPv6</button>
                </div>
            </div>
            <div class="code-container">
                <button class="copy-btn" onclick="copyCode(this)">Copy</button>
                <pre><code id="cli-dig">$ dig +short TXT <?php echo htmlspecialchars($isClientIpv6 ? $domainIpv6 : $domainIpv4); ?>

"<?php echo htmlspecialchars($isClientIpv6 ? $countryIpv6 : $countryIpv4); ?>"</code></pre>
            </div>

            <div class="tab-bar">
                <span class="tab-bar-title">host</span>
                <div class="tab-group">
                    <button class="tab-btn tab-btn-v4 <?php echo !$isClientIpv6 ? 'active' : ''; ?>" onclick="setGlobalProto('v4')">IPv4</button>
                    <button class="tab-btn tab-btn-v6 <?php echo $isClientIpv6 ? 'active' : ''; ?>" onclick="setGlobalProto('v6')">IPv6</button>
                </div>
            </div>
            <div class="code-container">
                <button class="copy-btn" onclick="copyCode(this)">Copy</button>
                <pre><code id="cli-host">$ host -t TXT <?php echo htmlspecialchars($isClientIpv6 ? $domainIpv6 : $domainIpv4); ?>

<?php echo htmlspecialchars($isClientIpv6 ? $domainIpv6 : $domainIpv4); ?> descriptive text "<?php echo htmlspecialchars($isClientIpv6 ? $countryIpv6 : $countryIpv4); ?>"</code></pre>
            </div>

            <div class="tab-bar">
                <span class="tab-bar-title">nslookup</span>
                <div class="tab-group">
                    <button class="tab-btn tab-btn-v4 <?php echo !$isClientIpv6 ? 'active' : ''; ?>" onclick="setGlobalProto('v4')">IPv4</button>
                    <button class="tab-btn tab-btn-v6 <?php echo $isClientIpv6 ? 'active' : ''; ?>" onclick="setGlobalProto('v6')">IPv6</button>
                </div>
            </div>
            <div class="code-container">
                <button class="copy-btn" onclick="copyCode(this)">Copy</button>
                <pre><code id="cli-nslookup">$ nslookup -type=TXT <?php echo htmlspecialchars($isClientIpv6 ? $domainIpv6 : $domainIpv4); ?>

<?php echo htmlspecialchars($isClientIpv6 ? $domainIpv6 : $domainIpv4); ?>    text = "<?php echo htmlspecialchars($isClientIpv6 ? $countryIpv6 : $countryIpv4); ?>"</code></pre>
            </div>
        </section>

        <section class="card">
            <h2>Integration Examples</h2>

            <div class="lang-tabs">
                <button class="lang-tab active" onclick="setLang('php')">PHP</button>
                <button class="lang-tab" onclick="setLang('python')">Python</button>
                <button class="lang-tab" onclick="setLang('node')">Node.js</button>
                <button class="lang-tab" onclick="setLang('java')">Java</button>
                <button class="lang-tab" onclick="setLang('go')">Go</button>
            </div>

            <div class="tab-bar">
                <span class="tab-bar-title" id="active-lang-title">PHP Example</span>
                <div class="tab-group">
                    <button class="tab-btn tab-btn-v4 <?php echo !$isClientIpv6 ? 'active' : ''; ?>" onclick="setGlobalProto('v4')">IPv4</button>
                    <button class="tab-btn tab-btn-v6 <?php echo $isClientIpv6 ? 'active' : ''; ?>" onclick="setGlobalProto('v6')">IPv6</button>
                </div>
            </div>

            <div class="code-container">
                <button class="copy-btn" onclick="copyCode(this)">Copy</button>
                <pre><code id="code-integration"></code></pre>
            </div>
        </section>

        <section class="card">
            <h2>Licensing & Commercial Plans</h2>
            <p>IP2CC offers simple, transparent access depending on your usage requirements:</p>

            <div class="pricing-grid">
                <div class="price-card">
                    <div>
                        <h3>Non-Profit & Personal</h3>
                        <p class="price-subtext">For personal projects, non-profits, open source, and educational uses.</p>
                        <div class="price-tag">€0</div>
                        <ul>
                            <li>Free forever</li>
                            <li>Community DNS resolution</li>
                            <li>Standard rate limits</li>
                        </ul>
                    </div>
                    <a href="#" class="btn-buy btn-free">Get Started</a>
                </div>

                <div class="price-card featured">
                    <div>
                        <h3>Commercial / Profit</h3>
                        <p class="price-subtext">For commercial applications, SaaS tools, e-commerce, and monetized services.</p>
                        <div class="price-tag">€19 <span style="font-size: 1rem; font-weight: 400;">/ month</span></div>
                        <p class="price-subtext">or <strong>€190 / year</strong> (Includes 2 months free!)</p>
                        <ul>
                            <li>Dedicated commercial subdomain</li>
                            <li>High throughput &amp; SLA support</li>
                            <li>Priority DNS edge infrastructure</li>
                        </ul>
                    </div>
                    <a href="#" class="btn-buy">Purchase Commercial Access</a>
                </div>
            </div>
        </section>

        <section class="card">
            <h2>Country Reference Data</h2>
            <p>Need full country names mapped to ISO 2-letter codes? Download the official <a href="https://docs.google.com/document/d/e/2PACX-1vQXgC2CWnLm9RwDhhiRjmDNH36wBUYo2hsIzM9v7QXiffSNQBP7BdHOE11AQuHWAVijJKvvCV5o0iSe/pub" target="_blank" rel="noopener">Country-to-Code Mapping CSV File</a> (Ensure UTF-8 encoding when saving).</p>
        </section>

        <section class="card">
            <h2>Contact & Support</h2>
            <p>Have questions, licensing inquiries, or technical support requests? Reach out to our engineering team:</p>
            <p><code>ip2cc [at] calpeconsulting.com</code></p>
        </section>
    </main>

    <footer>
        <p>&copy; <a href="http://calpeconsulting.com" target="_blank" rel="noopener">Calpe Consulting</a> — All rights reserved.</p>
    </footer>
</div>

<script>
// Attach functions globally to prevent ReferenceErrors on onclick events
window.DATA = <?php echo json_encode($jsData, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP); ?>;
window.currentProto = '<?php echo $isClientIpv6 ? "v6" : "v4"; ?>';
window.currentLang = 'php';

window.setLang = function(lang) {
    window.currentLang = lang;
    
    document.querySelectorAll('.lang-tab').forEach(b => {
        b.classList.toggle('active', b.innerText.toLowerCase().includes(lang));
    });

    const titles = {
        php: 'PHP Example',
        python: 'Python Example',
        node: 'Node.js Example',
        java: 'Java Example',
        go: 'Go Example'
    };
    document.getElementById('active-lang-title').innerText = titles[lang] || 'Code Example';

    window.renderCode();
};

window.renderCode = function() {
    const d = window.DATA[window.currentProto];
    const el = document.getElementById('code-integration');

    if (window.currentLang === 'php') {
        el.innerText = '<' + '?php\n' +
`function getIPCountryCode($ip = '${d.ip}') {
    $formattedIp = str_replace(['.', ':'], '-', $ip);
    $query = $formattedIp . '.free.query.ip2cc.com';

    $records = @dns_get_record($query, DNS_TXT);
    if (!empty($records)) {
        $val = $records[0]['txt'] ?? ($records[0]['entries'][0] ?? null);
        if ($val !== null) {
            return trim($val, '"');
        }
    }
    return 'UNKNOWN';
}

echo getIPCountryCode(); // Output: "${d.country}"
` + '?' + '>';
    } else if (window.currentLang === 'python') {
        el.innerText = `import dns.resolver

def get_ip_country(ip="${d.ip}"):
    formatted_ip = ip.replace('.', '-').replace(':', '-')
    query_domain = f"{formatted_ip}.free.query.ip2cc.com"
    
    try:
        answers = dns.resolver.resolve(query_domain, 'TXT')
        for rdata in answers:
            return rdata.to_text().strip('"')
    except Exception:
        return "UNKNOWN"

print(get_ip_country()) # Output: "${d.country}"`;
    } else if (window.currentLang === 'node') {
        el.innerText = `const dns = require('dns').promises;

async function getIpCountry(ip = '${d.ip}') {
    const formattedIp = ip.replace(/[.:]/g, '-');
    const queryDomain = \`\${formattedIp}.free.query.ip2cc.com\`;
    
    try {
        const records = await dns.resolveTxt(queryDomain);
        return records[0][0];
    } catch (err) {
        return 'UNKNOWN';
    }
}

getIpCountry().then(console.log); // Output: "${d.country}"`;
    } else if (window.currentLang === 'java') {
        el.innerText = `import javax.naming.directory.Attributes;
import javax.naming.directory.InitialDirContext;

public class IP2CC {
    public static String getCountry(String ip) {
        try {
            String formattedIp = ip.replace('.', '-').replace(':', '-');
            String domain = formattedIp + ".free.query.ip2cc.com";
            
            InitialDirContext ctx = new InitialDirContext();
            Attributes attrs = ctx.getAttributes("dns:///" + domain, new String[]{"TXT"});
            String txt = attrs.get("TXT").get().toString();
            return txt.replace("\"", "");
        } catch (Exception e) {
            return "UNKNOWN";
        }
    }

    public static void main(String[] args) {
        System.out.println(getCountry("${d.ip}")); // Output: "${d.country}"
    }
}`;
    } else if (window.currentLang === 'go') {
        el.innerText = `package main

import (
    "fmt"
    "net"
    "strings"
)

func getIPCountry(ip string) string {
    formattedIP := strings.ReplaceAll(strings.ReplaceAll(ip, ".", "-"), ":", "-")
    queryDomain := formattedIP + ".free.query.ip2cc.com"

    txts, err := net.LookupTXT(queryDomain)
    if err != nil || len(txts) == 0 {
        return "UNKNOWN"
    }
    return txts[0]
}

func main() {
    fmt.Println(getIPCountry("${d.ip}")) // Output: "${d.country}"
}`;
    }
};

window.setGlobalProto = function(proto) {
    window.currentProto = proto;
    const d = window.DATA[proto];
    if (!d) return;

    document.querySelectorAll('.tab-btn-v4').forEach(b => b.classList.toggle('active', proto === 'v4'));
    document.querySelectorAll('.tab-btn-v6').forEach(b => b.classList.toggle('active', proto === 'v6'));

    document.getElementById('out-ip').innerText = d.ip;
    document.getElementById('out-domain').innerText = d.domain;
    document.getElementById('out-country').innerText = d.country;
    document.getElementById('out-flag').innerText = d.flag;

    document.getElementById('step-char-desc').innerHTML = d.replaceText;
    document.getElementById('step-ip').innerText = d.ip;
    document.getElementById('step-hyphen').innerText = d.hyphen;
    document.getElementById('step-domain').innerText = d.domain;

    document.getElementById('cli-dig').innerText = `$ dig +short TXT ${d.domain}\n\n"${d.country}"`;
    document.getElementById('cli-host').innerText = `$ host -t TXT ${d.domain}\n\n${d.domain} descriptive text "${d.country}"`;
    document.getElementById('cli-nslookup').innerText = `$ nslookup -type=TXT ${d.domain}\n\n${d.domain}    text = "${d.country}"`;

    window.renderCode();
};

window.copyCode = function(btn) {
    const codeBlock = btn.nextElementSibling.querySelector('code') || btn.nextElementSibling;
    navigator.clipboard.writeText(codeBlock.innerText.trim()).then(() => {
        const originalText = btn.innerText;
        btn.innerText = 'Copied!';
        setTimeout(() => btn.innerText = originalText, 2000);
    });
};

// Initial Code Load
window.renderCode();
</script>

</body>
</html>
