File: //templates/hostpido/opcheckout.tpl
<link rel="stylesheet" href="{$WEB_ROOT}/templates/{$template}/css/hostpido-opcheckout.css?v=20260726-period-place-domainonly2" />
<div class="hp-opc-shell">
{if $hpError}
<div class="hp-opc-alert">{$hpError}</div>
{/if}
<section class="hp-opc-hero">
<div>
<p class="hp-opc-kicker">You're almost there!</p>
<h1>{if $hpDomainOnly}Register your domain only{else}Complete your <strong>{$hpProduct.name}</strong> order{/if}</h1>
{if $hpProduct.description}
<div class="hp-opc-description">{$hpProduct.description}</div>
{/if}
{if $hpDomainOptional}
<div class="hp-alpha-vat-badge"><strong>Hosting only: Kes.2,500 + VAT</strong><span>Add a .co.ke or .com domain and promo {$hpFreeDomainPromoCode} is auto-applied: hosting becomes Kes.3,500 + VAT and the domain is free.</span></div>
{/if}
</div>
<div class="hp-opc-hero-icon" aria-hidden="true">β</div>
</section>
<div class="hp-opc-grid">
<main class="hp-opc-main">
{if $hpNeedsDomain}
<section class="hp-opc-section">
<div class="hp-opc-section-title">
<span class="hp-opc-icon">π</span>
<h2>Choose your domain</h2>
</div>
<form id="hpDomainForm" class="hp-domain-card" method="post" action="javascript:void(0);">
<input type="hidden" name="billingcycle" value="{$hpCycle}">
{if $hpPromo}<input type="hidden" name="promocode" value="{$hpPromo}">{/if}
<input type="hidden" name="domainoption" id="hpDomainOption" value="owndomain">
<input type="hidden" name="domains[]" id="hpDomainFull" value="">
<input type="hidden" name="hp_paymentmethod" id="hpPaymentMethodHidden" value="{$hpDefaultGateway}">
<input type="hidden" id="hpDomainStatus" value="">
<div class="hp-domain-mode-hidden" aria-hidden="true">
<input type="radio" name="hp_domain_mode" value="owndomain"{if !$hpDomainOptional && !$hpDomainOnly} checked{/if} data-placeholder="search a domain e.g. yourdomain.co.ke">
<input type="radio" name="hp_domain_mode" value="register"{if $hpDomainOptional || $hpDomainOnly} checked{/if} data-placeholder="search a domain e.g. yourdomain.co.ke">
<input type="radio" name="hp_domain_mode" value="transfer" data-placeholder="search a domain e.g. yourdomain.co.ke">
</div>
<div class="hp-domain-input-row" id="hpDomainInputRow">
<input id="hpDomainInput" type="text" autocapitalize="none" autocomplete="off" placeholder="search a domain e.g. yourdomain.co.ke">
<button type="submit" id="hpCheckDomain" aria-label="Search domain">Search</button>
<button type="button" id="hpClearDomain" class="hp-domain-clear" hidden aria-label="Clear domain search">Γ <span>Clear</span></button>
<details class="hp-domain-options-menu" id="hpTakenDomainOptions" hidden>
<summary>Options</summary>
<div class="hp-domain-options-panel">
<button type="button" data-hp-domain-menu-action="transfer"><strong>Transfer this domain</strong><small>Move management to HostPido</small></button>
<button type="button" data-hp-domain-menu-action="owndomain"><strong>I will update nameservers</strong><small>Keep the domain where it is</small></button>
<button type="button" data-hp-domain-menu-action="try-another"><strong>Try another domain</strong><small>Clear the search and start again</small></button>
</div>
</details>
</div>
<div id="hpDomainMessage" class="hp-domain-message" aria-live="polite"></div>
<div id="hpDomainResult" class="hp-domain-result" aria-live="polite" hidden></div>
<p class="hp-opc-help">{if $hpDomainOptional}You can use domains you already own. To use them with this product, you will have to login.{elseif $hpDomainOnly}Search and register the domain only. Hosting is optional and will not be added automatically.{else}Search once; if it is taken, choose transfer or nameserver update from Options.{/if}</p>
{if $hpDomainOnly}
<div class="hp-host-domain-prompt">
<span><strong>Add Alpha Package hosting?</strong><small>Kes.250 per month. Hosting is optional and is not added automatically. Click Add to cart only if you also need website hosting.</small></span>
<a href="{$WEB_ROOT}/opcheckout.php?pid=1&cycle=annually{if $hpInitialDomain}&domainmode=register&query={$hpInitialDomain|escape:'url'}{/if}">Add to cart</a>
</div>
{/if}
</form>
</section>
{else}
<section class="hp-opc-section hp-domain-not-required">
<div class="hp-opc-section-title">
<span class="hp-opc-icon">π₯οΈ</span>
<h2>No domain required</h2>
</div>
<div class="hp-domain-card">
<p class="hp-opc-help"><strong>{$hpProduct.name}</strong> can be ordered without registering or transferring a domain. You can attach domains or DNS later after provisioning if needed.</p>
</div>
</section>
{/if}
{if !$hpDomainOnly}
<section class="hp-opc-section">
<div class="hp-opc-section-title">
<span class="hp-opc-icon">π
</span>
<h2>Choose your billing cycle</h2>
</div>
<div class="hp-cycle-grid">
{foreach $hpPricing as $price}
<button type="button" class="hp-cycle-card{if $price.selected} is-selected{/if}" data-cycle="{$price.key}" data-months="{$price.months}" data-label="{$price.label}" data-total="{$hpCurrency.prefix}{$price.formatted_total}{$hpCurrency.suffix}" data-total-amount="{$price.total}" data-monthly="{$hpCurrency.prefix}{$price.formatted_monthly}{$hpCurrency.suffix}" data-savings="{$price.savings}" data-savings-label="{$hpCurrency.prefix}{$price.formatted_savings}{$hpCurrency.suffix}" data-savings-percent="{$price.savings_percent}" data-cycle-url="{$WEB_ROOT}/opcheckout.php?pid={$hpPid}&cycle={$price.key}{if $hpPromo}&promo={$hpPromo|escape:'url'}{/if}">
{if $price.months >= 12 and $hpShowFreeDomainPromo}
<span class="hp-save-badge">FREE DOMAIN</span>
{/if}
<span class="hp-radio-dot"></span>
<strong>{$price.label}</strong>
<span class="hp-cycle-price">
{$hpCurrency.prefix}{$price.formatted_total}{$hpCurrency.suffix}
</span>
<span class="hp-cycle-unit">{if $price.key eq 'annually'}per year{elseif $price.key eq 'semiannually'}per semi annual{elseif $price.key eq 'quarterly'}per quarter{else}per month{/if}</span>
{if $price.months >= 12 and $hpShowFreeDomainPromo}
<em>Free domain on 1 year+ subscription</em>
{/if}
</button>
{/foreach}
</div>
</section>
{/if}
</main>
<aside class="hp-payment-card">
<div class="hp-payment-head">
<h3>Order summary</h3>
<span>{$hpCurrency.code}</span>
</div>
<div class="hp-summary-note">Review what you are purchasing before payment.</div>
{if !$hpDomainOnly}
<div class="hp-summary-row">
<div>
<strong>Hosting package</strong>
<small>{$hpProduct.name} β <span id="hpSummaryCycle">{$hpSelectedPricing.label|lower|capitalize}</span></small>
</div>
<strong id="hpSummaryProductTotal">{$hpCurrency.prefix}{$hpSelectedPricing.formatted_total}{$hpCurrency.suffix}</strong>
</div>
{/if}
<div class="hp-summary-row hp-summary-domain-row">
<div>
<strong>Domain</strong>
{if $hpNeedsDomain}
<small id="hpSummaryDomain">{if $hpDomainOptional}No domain selected β hosting only{else}Enter and check your domain to add it here{/if}</small>
{else}
<small id="hpSummaryDomain">Not required for this server order</small>
{/if}
</div>
<strong id="hpSummaryDomainType">{if $hpDomainOptional}Skipped{elseif $hpNeedsDomain}Pending{else}Skipped{/if}</strong>
</div>
<div class="hp-summary-row hp-summary-domain-price-row" id="hpSummaryDomainPriceRow" hidden>
<div>
<strong>Domain registration</strong>
<small id="hpSummaryDomainPriceNote">Added domain price</small>
</div>
<strong id="hpSummaryDomainPrice">{$hpCurrency.prefix}0.00{$hpCurrency.suffix}</strong>
</div>
<div id="hpSummaryExtraDomains"></div>
<div class="hp-promo-box">
<label>Promo Code</label>
<input type="text" id="hpPromoInput" value="{$hpPromo}" placeholder="Promo Code">
<button type="button" id="hpApplyPromo">{if $hpPromo}update promo code{else}apply promo code{/if}</button>
{if $hpPromo}
<button type="button" class="hp-remove" id="hpRemovePromo">remove promo code</button>
{/if}
</div>
<div class="hp-gateways">
<label>Payment method</label>
{foreach $hpGateways as $gateway name=gateways}
<label class="hp-gateway-option{if $smarty.foreach.gateways.first} is-selected{/if}">
<input type="radio" name="paymentmethod_preview" value="{$gateway.system}"{if $smarty.foreach.gateways.first} checked{/if}>
<span>{$gateway.name}</span>
</label>
{/foreach}
</div>
<div class="hp-total-row">
<span>Total <small>(incl. VAT where applicable)</small></span>
<strong id="hpSummaryGrandTotal">{if $hpDomainOnly}{$hpCurrency.prefix}0.00{$hpCurrency.suffix}{else}{$hpCurrency.prefix}{$hpSelectedPricing.formatted_total}{$hpCurrency.suffix}{/if}</strong>
</div>
<button type="button" class="hp-pay-now" id="hpPayNow">pay now</button>
<div id="hpOrderResult" class="hp-order-result" aria-live="polite" hidden></div>
<div class="hp-trust-strip" aria-label="Checkout benefits">
<span>Secure checkout</span>
<span>24/7 support</span>
<span>Instant setup</span>
</div>
<p class="hp-terms">
By checking out you agree with our <a href="{$WEB_ROOT}/submitticket.php">Terms Of Service</a> and <a href="{$WEB_ROOT}/privacy-policy.php">Privacy Policy</a>. You can cancel recurring payments at any time.
</p>
</aside>
</div>
</div>
{literal}
<style id="hp-auth-critical-css">
/* Critical auth modal CSS is inline to prevent cached external CSS from making the popup appear as a broken bottom form. */
#hpAuthModal[hidden]{display:none!important;}
#hpAuthModal.hp-auth-modal{position:fixed!important;inset:0!important;z-index:2147483000!important;display:flex!important;align-items:center!important;justify-content:center!important;padding:24px!important;box-sizing:border-box!important;font-family:Inter,Arial,sans-serif!important;}
#hpAuthModal.hp-auth-modal[hidden]{display:none!important;}
#hpAuthModal .hp-auth-backdrop{position:absolute!important;inset:0!important;background:rgba(5,15,32,.74)!important;backdrop-filter:blur(7px)!important;}
#hpAuthModal .hp-auth-dialog{position:relative!important;width:min(620px,calc(100vw - 32px))!important;max-height:calc(100vh - 44px)!important;overflow:auto!important;background:#fff!important;border-radius:26px!important;box-shadow:0 32px 90px rgba(5,15,32,.38)!important;padding:28px!important;border:1px solid rgba(255,255,255,.7)!important;box-sizing:border-box!important;}
#hpAuthModal .hp-auth-dialog:before{content:"";position:absolute;left:0;right:0;top:0;height:8px;background:linear-gradient(90deg,#ff6f4f,#4f43c9,#ff6f4f);border-radius:26px 26px 0 0;}
#hpAuthModal .hp-auth-close{position:absolute!important;top:16px!important;right:16px!important;width:38px!important;height:38px!important;border:0!important;border-radius:999px!important;background:#f1f5f9!important;color:#233247!important;font-size:26px!important;line-height:1!important;cursor:pointer!important;}
#hpAuthModal .hp-auth-brand{display:flex!important;gap:14px!important;align-items:center!important;margin:0 0 20px!important;padding-right:42px!important;}
#hpAuthModal .hp-auth-mark{width:48px!important;height:48px!important;border-radius:16px!important;background:linear-gradient(135deg,#ff6f4f,#4f43c9)!important;color:#fff!important;display:inline-flex!important;align-items:center!important;justify-content:center!important;font-size:25px!important;font-weight:900!important;box-shadow:0 14px 28px rgba(79,67,201,.24)!important;flex:0 0 auto!important;}
#hpAuthModal .hp-auth-brand p{margin:0 0 3px!important;color:#ff6f4f!important;text-transform:uppercase!important;letter-spacing:.08em!important;font-size:12px!important;font-weight:900!important;}
#hpAuthModal .hp-auth-brand h2{margin:0!important;color:#11223a!important;font-size:28px!important;font-weight:900!important;line-height:1.15!important;}
#hpAuthModal .hp-auth-tabs{display:grid!important;grid-template-columns:1fr 1fr!important;gap:8px!important;background:#f3f7fb!important;border-radius:16px!important;padding:6px!important;margin-bottom:18px!important;}
#hpAuthModal .hp-auth-tabs button{border:0!important;border-radius:12px!important;padding:12px!important;background:transparent!important;color:#5f6f83!important;font-weight:900!important;cursor:pointer!important;}
#hpAuthModal .hp-auth-tabs button.is-active{background:#07184a!important;color:#fff!important;box-shadow:0 8px 22px rgba(17,34,58,.08)!important;}
#hpAuthModal .hp-auth-panel{display:none!important;}
#hpAuthModal .hp-auth-panel.is-active{display:block!important;}
#hpAuthModal .hp-auth-panel>label,#hpAuthModal .hp-client-grid label{display:flex!important;flex-direction:column!important;gap:7px!important;color:#15243a!important;font-weight:800!important;margin:0 0 14px!important;}
#hpAuthModal input,#hpAuthModal select{width:100%!important;border:1px solid #d9e1ee!important;border-radius:14px!important;padding:13px 14px!important;background:#fff!important;color:#102033!important;outline:none!important;box-sizing:border-box!important;}
#hpAuthModal input:focus,#hpAuthModal select:focus{border-color:#ff6f4f!important;box-shadow:0 0 0 4px rgba(79,67,201,.12)!important;}
#hpAuthModal .hp-auth-submit{width:100%!important;border:0!important;border-radius:16px!important;background:linear-gradient(135deg,#ff6f4f,#4f43c9)!important;color:#fff!important;padding:15px!important;font-weight:900!important;text-transform:uppercase!important;letter-spacing:.03em!important;cursor:pointer!important;box-shadow:0 14px 30px rgba(79,67,201,.24)!important;}
#hpAuthModal .hp-auth-register-prompt{width:100%!important;margin-top:14px!important;border:2px dashed #ff6f4f!important;border-radius:16px!important;background:linear-gradient(135deg,rgba(255,111,79,.10),rgba(79,67,201,.08))!important;color:#07184a!important;padding:15px!important;cursor:pointer!important;text-align:left!important;box-sizing:border-box!important;}
#hpAuthModal .hp-auth-register-prompt strong{display:block!important;font-size:17px!important;font-weight:950!important;color:#07184a!important;}
#hpAuthModal .hp-auth-register-prompt small{display:block!important;margin-top:4px!important;color:#526272!important;font-weight:700!important;}
#hpAuthModal .hp-auth-login-link{display:block!important;width:100%!important;border:0!important;background:transparent!important;margin-top:12px!important;color:#ff6f4f!important;font-weight:900!important;cursor:pointer!important;}
#hpAuthModal .hp-auth-message{border-radius:14px!important;padding:12px 14px!important;margin-bottom:14px!important;border:1px solid #bdd7ff!important;background:#f3f8ff!important;color:#1a4f8a!important;font-weight:700!important;}
#hpAuthModal .hp-auth-message.is-error{border-color:#f3b8b8!important;background:#fff5f5!important;color:#8a1f1f!important;}
#hpAuthModal .hp-auth-message.is-success{border-color:#b9e8c3!important;background:#f1fff4!important;color:#145b25!important;}
.hp-alpha-vat-badge{display:inline-flex!important;flex-direction:column!important;gap:3px!important;margin-top:14px!important;border:1px solid rgba(22,163,74,.28)!important;border-radius:16px!important;background:linear-gradient(135deg,#ecfdf3,#fff)!important;padding:13px 16px!important;box-shadow:0 16px 35px rgba(22,163,74,.10)!important;color:#0f7a35!important;}
.hp-alpha-vat-badge strong{font-size:18px!important;font-weight:950!important;color:#0f7a35!important;}
.hp-alpha-vat-badge span{font-size:13px!important;font-weight:800!important;color:#385343!important;}
.hp-domain-mode-hidden{position:absolute!important;left:-9999px!important;width:1px!important;height:1px!important;overflow:hidden!important;}
.hp-domain-input-row{display:grid!important;grid-template-columns:minmax(0,1fr) auto auto!important;gap:10px!important;align-items:stretch!important;position:relative!important;}
.hp-domain-options-menu{position:relative!important;isolation:isolate!important;}
.hp-domain-options-menu[hidden]{display:none!important;}
.hp-domain-options-menu summary{height:100%!important;display:flex!important;align-items:center!important;gap:8px!important;border:0!important;border-radius:14px!important;background:linear-gradient(135deg,#07184a,#312c85)!important;color:#fff!important;padding:0 18px!important;font-weight:950!important;cursor:pointer!important;list-style:none!important;box-shadow:0 14px 28px rgba(7,24,74,.20)!important;}
.hp-domain-options-menu summary::after{content:"β";font-size:14px;line-height:1;transition:transform .18s ease;}
.hp-domain-options-menu summary::-webkit-details-marker{display:none!important;}
.hp-domain-options-menu[open] summary{border-radius:14px!important;}
.hp-domain-options-menu[open] summary::after{transform:rotate(180deg);}
.hp-domain-options-panel{position:absolute!important;right:0!important;top:calc(100% + 10px)!important;width:290px!important;background:#fff!important;border:1px solid #e4eaf4!important;border-radius:18px!important;box-shadow:0 22px 55px rgba(7,24,74,.20)!important;padding:8px!important;z-index:30!important;}
.hp-domain-options-panel::before{content:"";position:absolute;top:-7px;right:26px;width:14px;height:14px;background:#fff;border-left:1px solid #e4eaf4;border-top:1px solid #e4eaf4;transform:rotate(45deg);}
.hp-domain-options-panel button{position:relative!important;display:flex!important;flex-direction:column!important;gap:2px!important;width:100%!important;border:0!important;border-radius:13px!important;background:#fff!important;color:#102033!important;padding:12px 13px!important;text-align:left!important;cursor:pointer!important;}
.hp-domain-options-panel button:hover{background:#fff3ef!important;color:#e94e30!important;}
.hp-domain-options-panel button strong{font-size:13px!important;font-weight:950!important;}
.hp-domain-options-panel button small{font-size:11px!important;font-weight:750!important;color:#637083!important;}
.hp-host-domain-prompt{margin-top:14px!important;display:flex!important;align-items:center!important;justify-content:space-between!important;gap:14px!important;border:1px solid rgba(255,111,79,.28)!important;border-radius:18px!important;background:linear-gradient(135deg,#fff7f4,#f8fbff)!important;padding:15px 16px!important;color:#102033!important;box-shadow:0 16px 38px rgba(15,35,78,.08)!important;}
.hp-host-domain-prompt span{display:flex!important;flex-direction:column!important;gap:3px!important;}
.hp-host-domain-prompt strong{font-size:15px!important;font-weight:950!important;color:#07184a!important;}
.hp-host-domain-prompt small{font-size:12px!important;font-weight:750!important;color:#667085!important;}
.hp-host-domain-prompt a{border-radius:999px!important;background:linear-gradient(135deg,#ff6f4f,#f04d35)!important;color:#fff!important;padding:10px 16px!important;font-weight:950!important;text-decoration:none!important;white-space:nowrap!important;box-shadow:0 12px 28px rgba(240,77,53,.25)!important;}
.hp-search-result-title{display:flex!important;align-items:center!important;gap:10px!important;margin:16px 0 10px!important;color:#4c5564!important;font-size:22px!important;font-weight:500!important;letter-spacing:.01em!important;}
.hp-search-result-title span{font-size:26px!important;line-height:1!important;color:#596170!important;}
.hp-search-result-card{display:grid!important;grid-template-columns:42px minmax(130px,1fr) auto 140px!important;align-items:center!important;gap:10px!important;border:1px solid #cfd4dc!important;border-radius:12px!important;background:#f7f7f8!important;padding:16px!important;margin-bottom:12px!important;color:#20242d!important;box-shadow:inset 0 1px 0 rgba(255,255,255,.72)!important;}
.hp-result-icon{width:42px!important;height:42px!important;border-radius:999px!important;display:grid!important;place-items:center!important;background:#dff8e8!important;color:#11893b!important;font-size:22px!important;font-weight:900!important;}
.hp-result-icon.is-transfer{background:transparent!important;color:#858585!important;font-size:31px!important;}
.hp-result-domain{display:flex!important;flex-direction:column!important;gap:6px!important;min-width:0!important;}
.hp-result-domain span{display:flex!important;align-items:center!important;gap:8px!important;font-size:14px!important;font-weight:500!important;color:#20242d!important;}
.hp-result-domain em{font-style:normal!important;border-radius:6px!important;padding:4px 9px!important;background:#c9231e!important;color:#fff!important;font-size:13px!important;font-weight:800!important;line-height:1!important;}
.hp-search-result-card.is-available .hp-result-domain em{background:#16a34a!important;}
.hp-result-domain strong{font-size:18px!important;font-weight:500!important;color:#191c22!important;overflow:hidden!important;text-overflow:ellipsis!important;white-space:nowrap!important;}
.hp-result-price{display:flex!important;align-items:baseline!important;gap:6px!important;white-space:nowrap!important;color:#161a20!important;}
.hp-result-price strong{font-size:18px!important;font-weight:900!important;}
.hp-result-price span{font-size:14px!important;color:#20242d!important;}
.hp-result-confirm{border-radius:12px!important;background:#16a34a!important;color:#fff!important;padding:11px 18px!important;font-weight:900!important;}
.hp-result-action-menu{position:relative!important;justify-self:end!important;}
.hp-result-action-menu summary{display:flex!important;align-items:center!important;gap:8px!important;min-width:140px!important;justify-content:space-between!important;border:0!important;border-radius:12px!important;background:#b5a0d2!important;color:#111827!important;padding:12px 13px!important;font-size:14px!important;font-weight:650!important;cursor:pointer!important;list-style:none!important;}
.hp-result-action-menu summary::-webkit-details-marker{display:none!important;}
.hp-result-action-menu summary::after{content:"β";font-size:20px!important;line-height:1!important;color:#111827!important;transition:transform .16s ease!important;}
.hp-result-action-menu[open] summary::after{transform:rotate(180deg)!important;}
.hp-result-action-panel{position:absolute!important;right:0!important;top:calc(100% + 2px)!important;width:280px!important;background:#fff!important;border:1px solid #d6d6dc!important;border-radius:0 0 12px 12px!important;box-shadow:0 18px 40px rgba(15,23,42,.18)!important;overflow:hidden!important;z-index:50!important;}
.hp-result-action-panel button{display:block!important;width:100%!important;border:0!important;border-bottom:1px solid #d9d9de!important;background:#fff!important;color:#2f3542!important;padding:15px 20px!important;text-align:left!important;font-size:17px!important;font-weight:500!important;cursor:pointer!important;}
.hp-result-action-panel button:last-child{border-bottom:0!important;}
.hp-result-action-panel button:hover{background:#f5f1fb!important;color:#111827!important;}
@media(max-width:760px){.hp-domain-input-row{grid-template-columns:1fr!important;}.hp-search-result-card{grid-template-columns:42px 1fr!important;}.hp-result-price,.hp-result-action-menu,.hp-result-confirm{grid-column:1/-1!important;justify-self:stretch!important;}.hp-result-action-menu summary{width:100%!important;}.hp-result-action-panel{left:0!important;right:auto!important;width:100%!important;}.hp-host-domain-prompt{align-items:flex-start!important;flex-direction:column!important;}.hp-host-domain-prompt a{width:100%!important;text-align:center!important;}}
#hpAuthModal .hp-client-grid{display:grid!important;grid-template-columns:1fr 1fr!important;gap:11px!important;margin-bottom:16px!important;}
#hpAuthModal .hp-client-wide{grid-column:1/-1!important;}
#hpAuthModal .hp-terms-check{display:flex!important;flex-direction:row!important;align-items:flex-start!important;}
#hpAuthModal .hp-terms-check input{width:auto!important;margin-top:4px!important;}
body.hp-auth-open{overflow:hidden!important;}
@media(max-width:640px){#hpAuthModal.hp-auth-modal{padding:12px!important;align-items:flex-end!important;}#hpAuthModal .hp-auth-dialog{border-radius:22px 22px 0 0!important;max-height:92vh!important;padding:22px!important;width:100%!important;}#hpAuthModal .hp-client-grid{grid-template-columns:1fr!important;}#hpAuthModal .hp-auth-brand h2{font-size:23px!important;}}
/* 20260726 domain search refinement: screenshot-like rows, 5px radius, HostPido coral. */
.hp-opc-shell .hp-opc-hero{padding:18px 24px!important;margin-bottom:20px!important;border-radius:12px!important;min-height:0!important;gap:18px!important;}
.hp-opc-shell .hp-opc-kicker{font-size:13px!important;line-height:1.1!important;margin:0 0 4px!important;letter-spacing:.06em!important;}
.hp-opc-shell .hp-opc-hero h1{font-size:clamp(25px,3vw,34px)!important;line-height:1.08!important;margin:0!important;}
.hp-opc-shell .hp-opc-description{display:none!important;}
.hp-opc-shell .hp-alpha-vat-badge{display:none!important;}
.hp-opc-shell .hp-opc-hero-icon{width:54px!important;height:54px!important;font-size:30px!important;box-shadow:0 12px 28px rgba(79,67,201,.18)!important;}
.hp-opc-shell .hp-opc-hero,
.hp-opc-shell .hp-opc-section,
.hp-opc-shell .hp-domain-card,
.hp-opc-shell .hp-domain-input-row input,
.hp-opc-shell .hp-domain-input-row button,
.hp-opc-shell .hp-domain-options-menu summary,
.hp-opc-shell .hp-domain-options-panel,
.hp-opc-shell .hp-host-domain-prompt,
.hp-opc-shell .hp-search-result-card,
.hp-opc-shell .hp-result-add,
.hp-opc-shell .hp-summary-domain-row,
.hp-opc-shell .hp-payment-card,
.hp-opc-shell .hp-cycle-card,
.hp-opc-shell .hp-gateway-option,
.hp-opc-shell .hp-promo-box input,
.hp-opc-shell .hp-promo-box button,
.hp-opc-shell .hp-pay-now,
#hpAuthModal .hp-auth-dialog,
#hpAuthModal input,
#hpAuthModal select,
#hpAuthModal button { border-radius:5px!important; }
.hp-domain-input-row{grid-template-columns:minmax(0,1fr) 150px!important;gap:0!important;border:1px solid #ee55e8!important;border-radius:5px!important;overflow:hidden!important;background:#fff!important;}
.hp-domain-input-row input{border:0!important;min-height:52px!important;font-size:20px!important;padding:10px 16px!important;box-shadow:none!important;}
.hp-domain-input-row #hpCheckDomain,.hp-domain-input-row .hp-domain-clear{min-height:52px!important;border:0!important;border-left:1px solid #111!important;background:#000!important;color:#fff!important;font-size:16px!important;font-weight:700!important;box-shadow:none!important;display:flex!important;align-items:center!important;justify-content:center!important;gap:10px!important;}
.hp-domain-input-row .hp-domain-clear[hidden],.hp-domain-input-row #hpCheckDomain[hidden]{display:none!important;}
.hp-opc-help{font-size:15px!important;color:#777!important;margin:10px 0 0!important;}
.hp-domain-result{border:0!important;background:transparent!important;box-shadow:none!important;padding:0!important;margin-top:24px!important;overflow:visible!important;}
.hp-search-result-title{display:flex!important;align-items:center!important;gap:12px!important;margin:18px 0 18px!important;color:#21463a!important;font-size:24px!important;font-weight:400!important;}
.hp-search-result-title span{font-size:30px!important;color:#666!important;line-height:1!important;}
.hp-search-result-title strong{font-weight:400!important;}
.hp-search-result-card{display:grid!important;grid-template-columns:34px minmax(220px,1fr) minmax(150px,auto) 104px!important;align-items:center!important;gap:12px!important;border:1px solid #d0d0d0!important;border-radius:5px!important;background:#fff!important;padding:18px!important;margin:0 0 18px!important;box-shadow:none!important;color:#202124!important;max-width:100%!important;overflow:visible!important;}
.hp-result-icon{width:26px!important;height:26px!important;border:2px solid #aaa!important;background:#fff!important;color:#aaa!important;font-size:16px!important;line-height:1!important;}
.hp-result-icon.is-transfer{font-size:0!important;position:relative!important;border-radius:50%!important;}
.hp-result-icon.is-transfer:before{content:"β"!important;font-size:17px!important;font-weight:800!important;line-height:1!important;color:#777!important;}
.hp-result-domain{gap:4px!important;min-width:0!important;}
.hp-result-domain span{font-size:14px!important;color:#222!important;gap:8px!important;}
.hp-result-domain em{background:#7d1178!important;color:#fff!important;border-radius:5px!important;padding:4px 9px!important;font-size:13px!important;font-weight:700!important;}
.hp-result-domain strong{display:block!important;max-width:none!important;font-size:16px!important;font-weight:500!important;color:#222!important;line-height:1.25!important;overflow:visible!important;text-overflow:clip!important;white-space:normal!important;overflow-wrap:anywhere!important;word-break:break-word!important;}
.hp-result-price{text-align:right!important;color:#222!important;min-width:0!important;}
.hp-result-price strong{display:inline!important;font-size:18px!important;font-weight:900!important;color:#202124!important;white-space:nowrap!important;}
.hp-result-price span{font-size:15px!important;color:#222!important;margin-left:4px!important;white-space:nowrap!important;}
.hp-result-price a,.hp-free-offer-tip{display:block!important;margin-top:5px!important;color:#222!important;text-decoration:underline!important;font-size:13px!important;font-weight:400!important;cursor:help!important;position:relative!important;width:max-content!important;max-width:100%!important;margin-left:auto!important;}
.hp-free-offer-tip:focus{outline:2px solid #e66239!important;outline-offset:3px!important;border-radius:5px!important;}
.hp-free-offer-tip:hover:after,.hp-free-offer-tip:focus:after{content:attr(data-tooltip)!important;position:absolute!important;right:0!important;bottom:calc(100% + 8px)!important;width:260px!important;max-width:min(260px,80vw)!important;background:#111!important;color:#fff!important;border-radius:5px!important;padding:9px 10px!important;font-size:12px!important;line-height:1.35!important;text-align:left!important;text-decoration:none!important;box-shadow:0 12px 30px rgba(0,0,0,.22)!important;z-index:80!important;}
.hp-free-offer-tip:hover:before,.hp-free-offer-tip:focus:before{content:""!important;position:absolute!important;right:18px!important;bottom:calc(100% + 2px)!important;border:6px solid transparent!important;border-top-color:#111!important;z-index:81!important;}
.hp-result-add{border:0!important;background:#dec4ff!important;color:#000!important;padding:10px 12px!important;font-size:15px!important;font-weight:600!important;white-space:nowrap!important;box-shadow:none!important;width:100%!important;max-width:104px!important;text-align:center!important;}
.hp-result-add.is-added{background:#e66239!important;color:#fff!important;}
.hp-result-add.is-remove{background:#000!important;color:#fff!important;}
.hp-search-result-card.is-selected{background:#fff1ec!important;border-color:#f2b49f!important;margin-bottom:0!important;}
.hp-search-result-card.is-selected .hp-result-icon{border-color:#e66239!important;color:#e66239!important;background:#fff8f5!important;}
.hp-selected-period-panel{border:1px solid #f2b49f!important;border-top:0!important;background:#fff!important;border-radius:0 0 5px 5px!important;padding:18px!important;margin:0 0 18px!important;}
.hp-selected-period-panel strong{display:block!important;font-size:17px!important;font-weight:500!important;margin-bottom:10px!important;color:#222!important;}
.hp-selected-period-select{display:grid!important;grid-template-columns:1fr auto!important;align-items:center!important;gap:12px!important;max-width:420px!important;border:1px solid #d7d7d7!important;border-radius:5px!important;background:#fff!important;padding:0!important;font-size:16px!important;color:#222!important;box-shadow:0 3px 10px rgba(0,0,0,.06)!important;overflow:hidden!important;}
.hp-selected-period-select select{width:100%!important;border:0!important;background:#fff!important;color:#222!important;font-size:16px!important;padding:12px 14px!important;appearance:auto!important;outline:none!important;}
.hp-selected-period-select b{font-weight:800!important;margin-left:10px!important;}
.hp-selected-period-total{font-weight:800!important;padding-right:14px!important;white-space:nowrap!important;color:#222!important;}
.hp-search-result-card.is-taken{overflow:visible!important;position:relative!important;z-index:3!important;grid-template-columns:34px minmax(0,1fr) minmax(122px,auto) 92px!important;}
.hp-result-action-menu{position:relative!important;z-index:25!important;justify-self:end!important;width:92px!important;max-width:92px!important;min-width:0!important;}
.hp-result-action-menu summary{list-style:none!important;cursor:pointer!important;display:flex!important;align-items:center!important;justify-content:center!important;gap:6px!important;box-sizing:border-box!important;width:92px!important;min-width:0!important;max-width:92px!important;padding:10px 8px!important;border:0!important;border-radius:5px!important;background:#dec4ff!important;color:#000!important;font-size:13px!important;font-weight:700!important;white-space:nowrap!important;box-shadow:none!important;}
.hp-result-action-menu summary::-webkit-details-marker{display:none!important;}
.hp-result-action-menu summary:after{content:'β'!important;display:inline-block!important;font-size:15px!important;line-height:1!important;transition:transform .18s ease!important;}
.hp-result-action-menu[open] summary:after{transform:rotate(180deg)!important;}
.hp-result-action-panel{position:absolute!important;right:0!important;top:calc(100% + 8px)!important;min-width:220px!important;background:#fff!important;border:1px solid #f2b49f!important;border-radius:5px!important;box-shadow:0 16px 36px rgba(7,23,52,.18)!important;padding:8px!important;z-index:999!important;display:grid!important;gap:6px!important;animation:hpOptionsDrop .16s ease-out!important;}
.hp-result-action-panel button{border:0!important;border-radius:5px!important;background:#fff7f3!important;color:#071c4d!important;text-align:left!important;padding:10px 12px!important;font-size:14px!important;font-weight:600!important;cursor:pointer!important;}
.hp-result-action-panel button:hover{background:#e66239!important;color:#fff!important;}
@keyframes hpOptionsDrop{from{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:translateY(0)}}
.hp-like-title{margin-top:24px!important;font-size:17px!important;}
.hp-like-title span{font-size:21px!important;}
.hp-domain-suggestions-list{display:block!important;}
.hp-domain-suggestion-card{margin-bottom:18px!important;}
.hp-domain-suggestion-card.is-selected{margin-bottom:18px!important;}
.hp-suggestion-period{grid-column:1 / -1!important;display:none!important;border-top:1px solid #f2b49f!important;margin:4px -18px -18px!important;padding:14px 18px!important;background:#fff!important;}
.hp-domain-suggestion-card.is-selected .hp-suggestion-period{display:block!important;}
.hp-suggestion-period strong{display:block!important;font-size:16px!important;font-weight:600!important;margin-bottom:9px!important;color:#222!important;}
.hp-selected-domain-cart{border:1px solid #f2b49f!important;border-radius:5px!important;overflow:hidden!important;margin:20px 0 22px!important;background:#fff!important;}
.hp-selected-domain-cart-inline{margin:-12px 0 18px!important;}
.hp-selected-domain-cart-item{display:grid!important;grid-template-columns:34px minmax(0,1fr) minmax(126px,auto) 104px!important;align-items:center!important;gap:12px!important;background:#fff1ec!important;padding:18px!important;}
.hp-selected-domain-cart .hp-result-icon{border-color:#e66239!important;color:#e66239!important;background:#fff8f5!important;}
.hp-selected-domain-period{padding:18px!important;background:#fff!important;}
.hp-selected-domain-period strong{display:block!important;font-size:17px!important;font-weight:500!important;margin-bottom:10px!important;color:#222!important;}
.hp-summary-domain-row{background:#fff1ec!important;border-color:#f2b49f!important;border-left:5px solid #e66239!important;}
#hpSummaryDomainType{color:#e66239!important;}
@media(max-width:980px){.hp-search-result-card,.hp-selected-domain-cart-item{grid-template-columns:30px minmax(0,1fr) auto!important}.hp-result-domain{grid-column:2 / -1!important}.hp-result-price{grid-column:2!important;text-align:left!important}.hp-result-price a,.hp-free-offer-tip{margin-left:0!important}.hp-result-add{grid-column:3!important}}
@media(max-width:760px){.hp-domain-input-row{grid-template-columns:1fr!important}.hp-search-result-card,.hp-selected-domain-cart-item{grid-template-columns:30px 1fr!important;padding:16px!important;gap:12px!important}.hp-result-price,.hp-result-add{grid-column:2!important;text-align:left!important}.hp-result-add{width:auto!important;max-width:130px!important}.hp-search-result-title{font-size:21px!important}.hp-domain-input-row input{font-size:18px!important}.hp-selected-period-select{max-width:100%!important}.hp-free-offer-tip:hover:after,.hp-free-offer-tip:focus:after{left:0!important;right:auto!important}}
.hp-epp-modal{position:fixed!important;inset:0!important;z-index:10050!important;display:flex!important;align-items:center!important;justify-content:center!important;padding:18px!important;}
.hp-epp-modal[hidden]{display:none!important;}
.hp-epp-backdrop{position:absolute!important;inset:0!important;background:rgba(7,23,52,.54)!important;backdrop-filter:blur(4px)!important;}
.hp-epp-dialog{position:relative!important;z-index:1!important;width:min(520px,96vw)!important;background:#fff!important;border-radius:5px!important;padding:24px!important;box-shadow:0 24px 70px rgba(7,23,52,.26)!important;border:1px solid #f2b49f!important;color:#071c4d!important;}
.hp-epp-dialog h2{margin:0 0 8px!important;font-size:24px!important;line-height:1.15!important;color:#071c4d!important;}
.hp-epp-dialog p{margin:0 0 14px!important;font-size:15px!important;color:#5b6478!important;line-height:1.5!important;}
.hp-epp-note{background:#fff1ec!important;border:1px solid #f2b49f!important;border-radius:5px!important;padding:12px!important;margin:12px 0 16px!important;font-size:14px!important;color:#2b3348!important;}
.hp-epp-dialog label{display:grid!important;gap:7px!important;font-weight:700!important;color:#071c4d!important;}
.hp-epp-dialog input{border:1px solid #ccd6ec!important;border-radius:5px!important;padding:12px 13px!important;font-size:16px!important;outline:none!important;}
.hp-epp-dialog input:focus{border-color:#e66239!important;box-shadow:0 0 0 3px rgba(230,98,57,.16)!important;}
.hp-epp-actions{display:flex!important;gap:10px!important;justify-content:flex-end!important;margin-top:18px!important;}
.hp-epp-actions button{border:0!important;border-radius:5px!important;padding:11px 16px!important;font-size:15px!important;font-weight:800!important;cursor:pointer!important;}
.hp-epp-cancel{background:#eef2fb!important;color:#071c4d!important;}
.hp-epp-submit{background:#e66239!important;color:#fff!important;}
.hp-epp-error{color:#b42318!important;font-size:13px!important;margin-top:8px!important;}
</style>
{/literal}
<div class="hp-auth-modal" id="hpAuthModal" hidden aria-hidden="true">
<div class="hp-auth-backdrop" data-hp-auth-close="1"></div>
<div class="hp-auth-dialog" role="dialog" aria-modal="true" aria-labelledby="hpAuthTitle">
<button type="button" class="hp-auth-close" data-hp-auth-close="1" aria-label="Close login popup">Γ</button>
<div class="hp-auth-brand">
<span class="hp-auth-mark">β</span>
<div>
<p>Secure Hostpido checkout</p>
<h2 id="hpAuthTitle">Login to continue</h2>
</div>
</div>
<div class="hp-auth-tabs">
<button type="button" class="is-active" data-hp-auth-tab="login">Login</button>
<button type="button" data-hp-auth-tab="register">Register</button>
</div>
<div id="hpAuthMessage" class="hp-auth-message" hidden></div>
<form id="hpLoginForm" class="hp-auth-panel is-active" method="post" action="javascript:void(0);">
<label>
<span>Email address</span>
<input type="email" id="hpLoginEmail" autocomplete="email" required>
</label>
<label>
<span>Password</span>
<input type="password" id="hpLoginPassword" autocomplete="current-password" required>
</label>
<button type="submit" class="hp-auth-submit">Login and pay now</button>
<button type="button" class="hp-auth-register-prompt" data-hp-auth-tab="register">
<strong>Register if you do not have account yet</strong>
<small>Create your Hostpido account and continue payment on this page.</small>
</button>
</form>
<form id="hpRegisterForm" class="hp-auth-panel" method="post" action="javascript:void(0);">
<div class="hp-client-grid compact" id="hpClientForm">
<label>
<span>First name</span>
<input type="text" id="hpFirstName" autocomplete="given-name" required>
</label>
<label>
<span>Last name</span>
<input type="text" id="hpLastName" autocomplete="family-name" required>
</label>
<label class="hp-client-wide">
<span>Email address</span>
<input type="email" id="hpEmail" autocomplete="email" required>
</label>
<label>
<span>Phone number</span>
<input type="tel" id="hpPhone" autocomplete="tel" required>
</label>
<label>
<span>Company <small>(optional)</small></span>
<input type="text" id="hpCompany" autocomplete="organization">
</label>
<label class="hp-client-wide">
<span>Address</span>
<input type="text" id="hpAddress" autocomplete="street-address" required>
</label>
<label>
<span>City</span>
<input type="text" id="hpCity" autocomplete="address-level2" value="Nairobi" required>
</label>
<label>
<span>Country</span>
<select id="hpCountry" autocomplete="country" required>
<option value="KE" selected>Kenya</option>
<option value="TZ">Tanzania</option>
<option value="UG">Uganda</option>
<option value="RW">Rwanda</option>
<option value="BI">Burundi</option>
<option value="ZM">Zambia</option>
<option value="MW">Malawi</option>
<option value="US">United States</option>
<option value="GB">United Kingdom</option>
</select>
</label>
<label>
<span>Postcode</span>
<input type="text" id="hpPostcode" autocomplete="postal-code" value="00100" required>
</label>
<label>
<span>Password</span>
<input type="password" id="hpPassword" autocomplete="new-password" minlength="8" required>
</label>
<label class="hp-terms-check hp-client-wide">
<input type="checkbox" id="hpTermsAccepted">
<span>I agree to the Terms of Service and Privacy Policy.</span>
</label>
</div>
<button type="submit" class="hp-auth-submit">Register and pay now</button>
<button type="button" class="hp-auth-login-link" data-hp-auth-tab="login">Already have an account? Login instead</button>
</form>
</div>
</div>
<div class="hp-epp-modal" id="hpEppModal" hidden aria-hidden="true">
<div class="hp-epp-backdrop" data-hp-epp-close="1"></div>
<div class="hp-epp-dialog" role="dialog" aria-modal="true" aria-labelledby="hpEppTitle">
<h2 id="hpEppTitle">Transfer domain to HostPido</h2>
<p id="hpEppDomainLine">Enter the EPP/Auth code for your domain transfer.</p>
<div class="hp-epp-note">Before starting the transfer, please unlock the domain at your current registrar. The EPP/Auth code is required and is normally available from the current registrar's domain management area.</div>
<label>
<span>EPP / Auth code</span>
<input type="text" id="hpEppCode" autocomplete="off" placeholder="Enter EPP code" />
</label>
<div class="hp-epp-error" id="hpEppError" hidden></div>
<div class="hp-epp-actions">
<button type="button" class="hp-epp-cancel" data-hp-epp-close="1">Cancel</button>
<button type="button" class="hp-epp-submit" id="hpEppSubmit">Continue Transfer</button>
</div>
</div>
</div>
<script>
(function () {
var webRoot = '{$WEB_ROOT}';
var pid = '{$hpPid}';
var cycle = '{$hpCycle}';
var hpLoggedIn = {if $hpLoggedIn}true{else}false{/if};
var hpNeedsDomain = {if $hpNeedsDomain}true{else}false{/if};
var hpDomainOptional = {if $hpDomainOptional}true{else}false{/if};
var hpDomainOnly = {if $hpDomainOnly}true{else}false{/if};
var currencyPrefix = '{$hpCurrency.prefix|escape:'javascript'}';
var currencySuffix = '{$hpCurrency.suffix|escape:'javascript'}';
var freeDomainTlds = [{foreach $hpFreeDomainTlds as $tld}'{$tld|escape:'javascript'}'{if !$tld@last},{/if}{/foreach}];
var freeDomainPromoCode = '{$hpFreeDomainPromoCode|escape:'javascript'}';
var freeDomainUplift = parseAmount('{$hpFreeDomainUplift|escape:'javascript'}');
var freeDomainSummaryLabel = {if $hpShowFreeDomainPromo}'Free with ' + freeDomainPromoCode{else}'Added to this checkout'{/if};
var storageKey = 'hostpido_opc_state_' + pid;
var initialDomain = '{$hpInitialDomain|escape:'javascript'}';
var initialDomainMode = '{$hpInitialDomainMode|escape:'javascript'}';
var autoCheckInitialDomain = {if $hpAutoCheckDomain}true{else}false{/if};
if (!window.CSS) { window.CSS = {}; }
if (!window.CSS.escape) {
window.CSS.escape = function (value) { return String(value || '').replace(/[^a-zA-Z0-9_-]/g, function (match) { return '\\' + match; }); };
}
var domainCheckInProgress = false;
var domainState = {
domain: '',
mode: 'owndomain',
status: '',
checked: false,
payload: null,
period: 1,
eppcode: ''
};
function saveState() {
try {
var promoField = document.getElementById('hpPromoInput');
localStorage.setItem(storageKey, JSON.stringify({
cycle: cycle,
domain: domainState.domain || normaliseDomain((document.getElementById('hpDomainInput') || {}).value || ''),
mode: domainState.mode || selectedDomainMode(),
status: domainState.status || '',
checked: !!domainState.checked,
payload: domainState.payload || null,
period: domainState.period || 1,
eppcode: domainState.eppcode || '',
gateway: selectedGateway(),
promo: promoField ? promoField.value.trim() : '',
client: collectClient(false)
}));
} catch (e) {}
}
function readState() {
try {
return JSON.parse(localStorage.getItem(storageKey) || '{}') || {};
} catch (e) {
return {};
}
}
function buildUrl(promo) {
var url = webRoot + '/opcheckout.php?pid=' + encodeURIComponent(pid) + '&cycle=' + encodeURIComponent(cycle);
if (promo) {
url += '&promo=' + encodeURIComponent(promo);
}
return url;
}
function selectedGateway() {
var input = document.querySelector('input[name="paymentmethod_preview"]:checked');
return input ? input.value : '';
}
function selectedDomainMode() {
var input = document.querySelector('input[name="hp_domain_mode"]:checked');
return input ? input.value : 'owndomain';
}
function normaliseDomain(value) {
return (value || '')
.trim()
.toLowerCase()
.replace(/^https?:\/\//, '')
.replace(/^www\./, '')
.replace(/\/.*$/, '')
.replace(/\s+/g, '');
}
function setDomainMessage(message, type) {
var el = document.getElementById('hpDomainMessage');
if (!el) { return; }
el.textContent = message || '';
el.className = 'hp-domain-message' + (type ? ' is-' + type : '');
}
function setDomainResult(html, type) {
var el = document.getElementById('hpDomainResult');
if (!el) { return; }
el.hidden = !html;
el.innerHTML = html || '';
el.className = 'hp-domain-result' + (type ? ' is-' + type : '');
}
function setTakenOptions(show) {
var menu = document.getElementById('hpTakenDomainOptions');
if (!menu) { return; }
menu.hidden = !show;
if (!show) { menu.open = false; }
}
function domainModeLabel(mode, status) {
if (status === 'available') { return 'Registration'; }
if (status === 'unavailable') { return 'Taken'; }
if (status === 'transfer-selected' || mode === 'transfer') { return 'Transfer'; }
if (status === 'own-domain' || mode === 'owndomain') { return 'Use existing'; }
return 'Pending';
}
function parseAmount(value) {
var amount = parseFloat(value);
return isNaN(amount) ? 0 : amount;
}
function formatAmount(amount) {
amount = parseAmount(amount);
return currencyPrefix + amount.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 }) + currencySuffix;
}
function currentCycleCard() {
return document.querySelector('.hp-cycle-card.is-selected') || document.querySelector('.hp-cycle-card[data-cycle="' + cycle + '"]');
}
function currentProductAmount() {
var card = currentCycleCard();
return card ? parseAmount(card.getAttribute('data-total-amount')) : parseAmount('{$hpSelectedPricing.total}');
}
function currentSavingsAmount() {
var card = currentCycleCard();
return card ? parseAmount(card.getAttribute('data-savings')) : parseAmount('{$hpSelectedPricing.savings}');
}
function currentCycleMonths() {
var card = currentCycleCard();
if (card) { return parseInt(card.getAttribute('data-months') || '0', 10) || 0; }
var map = { monthly: 1, quarterly: 3, semiannually: 6, annually: 12, biennially: 24, triennially: 36 };
return map[cycle] || 0;
}
function normalisedTld(value) {
value = String(value || '').toLowerCase();
return value.charAt(0) === '.' ? value : '.' + value;
}
function domainMatchesFreeTld(domain) {
domain = normaliseDomain(domain);
return freeDomainTlds.map(normalisedTld).some(function (tld) { return domain.endsWith(tld); });
}
function promoField() {
return document.getElementById('hpPromoInput');
}
function freeDomainModeApplies(domain) {
return !hpDomainOnly && currentCycleMonths() >= 12 && domainMatchesFreeTld(domain);
}
function annualFreeDomainApplies(domain) {
return freeDomainModeApplies(domain) && domainState.status === 'available';
}
function syncFreeDomainPromo() {
var field = promoField();
if (!field || !freeDomainPromoCode) { return; }
if (annualFreeDomainApplies(domainState.domain)) {
field.value = freeDomainPromoCode;
} else if (field.value.trim().toUpperCase() === freeDomainPromoCode.toUpperCase()) {
field.value = '';
}
}
function domainPriceFromPayload(payload, type) {
if (!payload || !payload.pricing || !payload.pricing[type]) { return 0; }
return parseAmount(payload.pricing[type].amount);
}
function mainDomainAmount() {
if (!hpNeedsDomain || !domainState.domain || domainState.mode === 'none') { return 0; }
if (domainState.status === 'available') {
return domainPeriodTotal(domainFirstYearAmount(domainState.payload, 'register'), domainRenewalAmount(domainState.payload, 'register'), domainState.period || 1, annualFreeDomainApplies(domainState.domain));
}
if (domainState.status === 'transfer-selected') {
return domainPeriodTotal(domainFirstYearAmount(domainState.payload, 'transfer'), domainRenewalAmount(domainState.payload, 'transfer'), domainState.period || 1, false);
}
return 0;
}
function updateOrderTotal() {
var productAmount = currentProductAmount();
var freeDomainApplies = annualFreeDomainApplies(domainState.domain);
var domainAmount = mainDomainAmount();
var extraTotal = uniqueAdditionalDomains().reduce(function (sum, domain) {
var first = parseAmount(selectedAdditionalDomainPrices[domain] || 0);
var renew = parseAmount(selectedAdditionalDomainRenewPrices[domain] || first);
var years = parseInt(selectedAdditionalDomainPeriods[domain] || 1, 10) || 1;
return sum + domainPeriodTotal(first, renew, years, false);
}, 0);
var grandTotal = document.getElementById('hpSummaryGrandTotal');
var domainRow = document.getElementById('hpSummaryDomainPriceRow');
var domainPrice = document.getElementById('hpSummaryDomainPrice');
var domainNote = document.getElementById('hpSummaryDomainPriceNote');
var productTotal = document.getElementById('hpSummaryProductTotal');
var extrasHost = document.getElementById('hpSummaryExtraDomains');
syncFreeDomainPromo();
if (domainRow) { domainRow.hidden = !(domainState.domain && domainState.mode !== 'none' && (domainState.status === 'available' || domainState.status === 'transfer-selected')); }
if (productTotal) { productTotal.textContent = formatAmount(productAmount); }
if (domainPrice) { domainPrice.textContent = freeDomainApplies ? 'FREE' : formatAmount(domainAmount); }
if (domainNote) { domainNote.textContent = freeDomainApplies ? freeDomainSummaryLabel : 'Added to this checkout'; }
if (extrasHost) {
extrasHost.innerHTML = uniqueAdditionalDomains().map(function (domain) {
var first = parseAmount(selectedAdditionalDomainPrices[domain] || 0);
var renew = parseAmount(selectedAdditionalDomainRenewPrices[domain] || first);
var years = parseInt(selectedAdditionalDomainPeriods[domain] || 1, 10) || 1;
var total = domainPeriodTotal(first, renew, years, false);
return '<div class="hp-summary-row hp-summary-extra-domain-row"><div><strong>Extra domain</strong><small>' + escapeHtml(domain) + ' β ' + years + ' year' + (years === 1 ? '' : 's') + ' registration</small></div><strong>' + formatAmount(total) + '</strong></div>';
}).join('');
}
if (grandTotal) { grandTotal.textContent = formatAmount(productAmount + domainAmount + extraTotal); }
}
function updateSummaryDomain(domain, mode, status) {
var domainText = document.getElementById('hpSummaryDomain');
var domainType = document.getElementById('hpSummaryDomainType');
if (domainText) {
domainText.textContent = domain ? domain : (hpDomainOptional ? 'No domain selected β hosting only' : 'Enter and check your domain to add it here');
}
if (domainType) {
domainType.textContent = domain ? domainModeLabel(mode, status) : (hpDomainOptional ? 'Skipped' : 'Pending');
}
updateOrderTotal();
}
function uniqueAdditionalDomains() {
var seen = {};
var primary = normaliseDomain((document.getElementById('hpDomainInput') || {}).value || domainState.domain || '');
selectedAdditionalDomains = selectedAdditionalDomains
.map(normaliseDomain)
.filter(function (domain) {
if (!domain || domain === primary || seen[domain]) { return false; }
seen[domain] = true;
return true;
});
domainState.additionalDomains = selectedAdditionalDomains.slice();
return selectedAdditionalDomains;
}
function renderAdditionalDomainCart() {
uniqueAdditionalDomains();
document.querySelectorAll('[data-hp-selected-additional-domains]').forEach(function (existing) { existing.remove(); });
updateOrderTotal();
}
function syncSuggestionButtons() {
uniqueAdditionalDomains();
document.querySelectorAll('[data-hp-suggestion-domain]').forEach(function (button) {
var domain = normaliseDomain(button.getAttribute('data-hp-suggestion-domain') || '');
var added = selectedAdditionalDomains.indexOf(domain) !== -1;
button.classList.toggle('is-added', added);
button.classList.toggle('is-remove', added);
button.textContent = added ? 'Remove' : 'Add to cart';
button.setAttribute('aria-pressed', added ? 'true' : 'false');
var card = button.closest('.hp-domain-suggestion-card');
if (card) { card.classList.toggle('is-selected', added); }
});
}
function syncHiddenFields(domain, mode, status) {
var domainInput = document.getElementById('hpDomainInput');
var domainFull = document.getElementById('hpDomainFull');
var domainOption = document.getElementById('hpDomainOption');
var domainStatus = document.getElementById('hpDomainStatus');
var paymentHidden = document.getElementById('hpPaymentMethodHidden');
if (domainInput) { domainInput.value = domain; }
if (domainFull) { domainFull.value = domain; }
if (domainOption) { domainOption.value = mode; }
if (domainStatus) { domainStatus.value = status || ''; }
if (paymentHidden) { paymentHidden.value = selectedGateway(); }
uniqueAdditionalDomains();
updateSummaryDomain(domain, mode, status || '');
renderAdditionalDomainCart();
syncSuggestionButtons();
}
function escapeHtml(value) {
return String(value || '')
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
}
function pricingLine(payload, type) {
if (!payload || !payload.pricing || !payload.pricing[type]) { return ''; }
var price = payload.pricing[type];
if (!price || !price.formatted) { return ''; }
return '<span class="hp-domain-price">1 year domain price: <strong>' + escapeHtml(price.formatted) + '</strong></span>';
}
function formattedDomainPrice(payload, type) {
if (!payload || !payload.pricing || !payload.pricing[type] || !payload.pricing[type].formatted) { return ''; }
return payload.pricing[type].formatted;
}
function freeOfferTooltipHtml(domain) {
if (!freeDomainModeApplies(domain)) { return ''; }
var tip = 'You get the domain for free if you buy hosting for 1 year or more.';
return '<span class="hp-free-offer-tip" tabindex="0" role="note" title="' + escapeHtml(tip) + '" data-tooltip="' + escapeHtml(tip) + '">Free offer available</span>';
}
function domainRenewalAmount(payload, fallbackType) {
if (payload && payload.pricing && payload.pricing.renew) { return parseAmount(payload.pricing.renew.amount); }
if (payload && payload.pricing && payload.pricing[fallbackType]) { return parseAmount(payload.pricing[fallbackType].amount); }
return 0;
}
function domainFirstYearAmount(payload, type) {
if (payload && payload.pricing && payload.pricing[type]) { return parseAmount(payload.pricing[type].amount); }
return domainRenewalAmount(payload, type);
}
function domainPeriodTotal(firstAmount, renewAmount, selected, firstYearFree) {
selected = Math.max(1, Math.min(5, parseInt(selected || 1, 10) || 1));
firstAmount = firstYearFree ? 0 : parseAmount(firstAmount);
renewAmount = parseAmount(renewAmount || firstAmount);
return firstAmount + (Math.max(0, selected - 1) * renewAmount);
}
function domainPeriodOptions(firstAmount, renewAmount, selected, firstYearFree) {
selected = parseInt(selected || 1, 10) || 1;
var html = '';
for (var year = 1; year <= 5; year += 1) {
var label = year + ' year' + (year === 1 ? '' : 's') + ' β ' + formatAmount(domainPeriodTotal(firstAmount, renewAmount, year, firstYearFree));
html += '<option value="' + year + '"' + (year === selected ? ' selected' : '') + '>' + escapeHtml(label) + '</option>';
}
return '<select data-hp-domain-period data-first-price="' + escapeHtml(firstAmount) + '" data-renew-price="' + escapeHtml(renewAmount) + '" data-first-free="' + (firstYearFree ? '1' : '0') + '">' + html + '</select><span class="hp-selected-period-total">' + escapeHtml(formatAmount(domainPeriodTotal(firstAmount, renewAmount, selected, firstYearFree))) + '</span>';
}
var hpSuggestionTlds = ['.co.ke', '.com', '.ke', '.net', '.org', '.africa', '.online', '.shop'];
var selectedAdditionalDomains = Array.isArray(domainState.additionalDomains) ? domainState.additionalDomains : [];
var selectedAdditionalDomainPrices = {};
var selectedAdditionalDomainRenewPrices = {};
var selectedAdditionalDomainPeriods = {};
function domainBaseName(domain) {
domain = normaliseDomain(domain);
var sorted = hpSuggestionTlds.slice().sort(function (a, b) { return b.length - a.length; });
for (var i = 0; i < sorted.length; i += 1) {
if (domain.endsWith(sorted[i])) {
return domain.slice(0, -sorted[i].length).replace(/\.$/, '');
}
}
return domain.split('.')[0] || domain;
}
function domainExtension(domain) {
domain = normaliseDomain(domain);
var sorted = hpSuggestionTlds.slice().sort(function (a, b) { return b.length - a.length; });
for (var i = 0; i < sorted.length; i += 1) {
if (domain.endsWith(sorted[i])) { return sorted[i]; }
}
var firstDot = domain.indexOf('.');
return firstDot >= 0 ? domain.slice(firstDot) : '';
}
function suggestionShell(domain) {
return '<div class="hp-domain-suggestions hp-domain-suggestions2" data-hp-alt-domain-suggestions data-domain-base="' + escapeHtml(domainBaseName(domain)) + '">' +
'<div class="hp-search-result-title hp-like-title"><span>β§</span><strong>You might also like</strong></div>' +
'<div class="hp-domain-suggestions-list" data-hp-alt-domain-list><em>Checking availability now...</em></div>' +
'</div>';
}
function renderAlternativeSuggestions(items) {
var list = document.querySelector('[data-hp-alt-domain-list]');
var head = document.querySelector('.hp-domain-suggestions-head span');
if (!list) { return; }
if (!items.length) {
list.innerHTML = '<em>No extra available extensions were confirmed. Try another name or contact support.</em>';
if (head) { head.textContent = 'No extra options confirmed'; }
return;
}
if (head) { head.textContent = items.length + ' available option' + (items.length === 1 ? '' : 's') + ' found'; }
list.innerHTML = items.map(function (item) {
var price = item.payload && item.payload.pricing && item.payload.pricing.register && item.payload.pricing.register.formatted ? item.payload.pricing.register.formatted : '';
var priceAmount = item.payload && item.payload.pricing && item.payload.pricing.register ? parseAmount(item.payload.pricing.register.amount) : 0;
var renewAmount = item.payload && item.payload.pricing && item.payload.pricing.renew ? parseAmount(item.payload.pricing.renew.amount) : priceAmount;
var domain = normaliseDomain(item.domain);
var added = selectedAdditionalDomains.indexOf(domain) !== -1;
var selectedPeriod = parseInt(selectedAdditionalDomainPeriods[domain] || 1, 10) || 1;
var periodHtml = domainPeriodOptions(priceAmount, renewAmount, selectedPeriod, false).replace('<select ', '<select data-hp-extra-domain-period="' + escapeHtml(domain) + '" ');
var badge = item.domain.indexOf('.africa') !== -1 ? 'New' : (item.domain.indexOf('.co.za') !== -1 ? 'Hot' : '');
return '<article class="hp-search-result-card hp-domain-suggestion-card' + (added ? ' is-selected' : '') + '">' +
'<div class="hp-result-icon">β</div>' +
'<div class="hp-result-domain"><span>Registration' + (badge ? ' <em>' + badge + '</em>' : '') + '</span><strong>' + escapeHtml(item.domain) + '</strong></div>' +
'<div class="hp-result-price"><strong>' + (price ? escapeHtml(price) : 'Available') + '</strong><span>/ 1 year</span>' + freeOfferTooltipHtml(item.domain) + '</div>' +
'<button type="button" class="hp-result-add ' + (added ? 'is-added is-remove' : '') + '" aria-pressed="' + (added ? 'true' : 'false') + '" data-hp-domain-price="' + escapeHtml(priceAmount) + '" data-hp-domain-renew-price="' + escapeHtml(renewAmount) + '" data-hp-suggestion-domain="' + escapeHtml(item.domain) + '">' + (added ? 'Remove' : 'Add to cart') + '</button>' +
'<div class="hp-suggestion-period"><strong>Registration Period</strong><div class="hp-selected-period-select">' + periodHtml + '</div></div>' +
'</article>';
}).join('');
renderAdditionalDomainCart();
syncSuggestionButtons();
}
function checkAlternativeDomains(domain) {
var container = document.querySelector('[data-hp-alt-domain-suggestions]');
if (!container) { return; }
var base = domainBaseName(domain);
var originalExt = domainExtension(domain);
if (!base) { return; }
var candidates = hpSuggestionTlds
.filter(function (tld) { return tld !== originalExt; })
.map(function (tld) { return base + tld; });
var found = [];
function checkNext(index) {
if (found.length >= 3 || index >= candidates.length) {
renderAlternativeSuggestions(found.slice(0, 3));
return;
}
var candidate = candidates[index];
fetch(webRoot + '/opcheckout_domain.php?domain=' + encodeURIComponent(candidate) + '&mode=register', {
method: 'GET', credentials: 'same-origin', headers: { 'Accept': 'application/json' }
})
.then(function (response) { return response.json(); })
.then(function (payload) {
if (payload && payload.status === 'available') {
found.push({ domain: payload.domain || candidate, payload: payload });
}
})
.catch(function () {})
.finally(function () { checkNext(index + 1); });
}
checkNext(0);
}
function switchDomainMode(mode, options) {
options = options || {};
var currentDomain = normaliseDomain((document.getElementById('hpDomainInput') || {}).value || domainState.domain || '');
document.querySelectorAll('input[name="hp_domain_mode"]').forEach(function (input) {
input.checked = input.value === mode;
var wrapper = input.closest('.hp-domain-option');
if (wrapper) { wrapper.classList.toggle('is-active', input.checked); }
if (input.checked) {
var domainInput = document.getElementById('hpDomainInput');
if (domainInput && input.getAttribute('data-placeholder')) {
domainInput.placeholder = input.getAttribute('data-placeholder');
}
}
});
domainState.mode = mode;
domainState.domain = currentDomain;
if (mode === 'none') {
currentDomain = '';
domainState.domain = '';
domainState.checked = true;
domainState.status = 'not_required';
domainState.payload = null;
setTakenOptions(false);
setDomainResult('', '');
setDomainMessage('Hosting-only order selected. No domain will be added.', 'success');
syncHiddenFields('', 'none', 'not_required');
saveState();
return;
}
if (!options.keepResult) {
domainState.checked = false;
domainState.status = '';
domainState.payload = null;
setTakenOptions(false);
setDomainResult('', '');
setDomainMessage(currentDomain ? 'Domain kept. Click βCheck domainβ to confirm this option.' : '', '');
}
syncHiddenFields(currentDomain, mode, domainState.status);
saveState();
}
function renderDomainPayload(payload, mode) {
var domain = payload.domain || '';
domainState = { domain: domain, mode: mode, status: payload.status || '', checked: true, payload: payload, period: domainState.period || 1, eppcode: domainState.eppcode || '' };
syncHiddenFields(domain, mode, payload.status || '');
if (payload.status === 'available') {
// If a domain is truly available, the only valid customer action is registration.
// It cannot be transferred and should not be treated as an existing owned domain.
mode = 'register';
domainState.mode = 'register';
setTakenOptions(false);
document.querySelectorAll('input[name="hp_domain_mode"]').forEach(function (input) {
input.checked = input.value === 'register';
var wrapper = input.closest('.hp-domain-option');
if (wrapper) { wrapper.classList.toggle('is-active', input.checked); }
});
syncHiddenFields(domain, 'register', payload.status || '');
setDomainMessage('', '');
setDomainResult(
'<div class="hp-search-result-title"><span>β</span><strong>Search Result</strong></div>' +
'<div class="hp-search-result-card is-available">' +
'<div class="hp-result-icon">β</div>' +
'<div class="hp-result-domain"><span>Registration</span><strong>' + escapeHtml(domain) + '</strong></div>' +
'<div class="hp-result-price"><strong>' + escapeHtml(formattedDomainPrice(payload, 'register') || 'Ready') + '</strong><span>/ 1 year</span>' + freeOfferTooltipHtml(domain) + '</div>' +
'<button type="button" class="hp-result-add" data-hp-domain-action="register">Add to Cart</button>' +
'</div><div class="hp-selected-period-panel" hidden data-hp-primary-domain-period><strong>Registration Period</strong><div class="hp-selected-period-select">' + domainPeriodOptions(domainFirstYearAmount(payload, 'register'), domainRenewalAmount(payload, 'register'), domainState.period || 1, annualFreeDomainApplies(domain)) + '</div></div>' + suggestionShell(domain), 'success'
);
checkAlternativeDomains(domain);
saveState();
return;
}
if (payload.status === 'unavailable') {
setTakenOptions(false);
setDomainMessage('', '');
setDomainResult(
'<div class="hp-search-result-title"><span>β</span><strong>Search Result</strong></div>' +
'<div class="hp-search-result-card is-taken">' +
'<div class="hp-result-icon is-transfer"></div>' +
'<div class="hp-result-domain"><span>Transfer <em>Taken</em></span><strong>' + escapeHtml(domain) + '</strong></div>' +
'<div class="hp-result-price"><strong>' + escapeHtml(formattedDomainPrice(payload, 'transfer') || '') + '</strong><span>/ 1 year</span></div>' +
'<details class="hp-result-action-menu"><summary>Options</summary><div class="hp-result-action-panel">' +
'<button type="button" data-hp-domain-menu-action="transfer">Transfer domain to us</button>' +
'<button type="button" data-hp-domain-menu-action="owndomain">I will update my domain DNS</button>' +
'<button type="button" data-hp-domain-menu-action="try-another">Try another domain</button>' +
'</div></details>' +
'</div>' + suggestionShell(domain), 'warning'
);
checkAlternativeDomains(domain);
saveState();
return;
}
if (payload.status === 'own-domain') {
setTakenOptions(false);
setDomainMessage('', '');
setDomainResult('<div class="hp-domain-result-copy"><div class="hp-domain-result-head"><span class="hp-domain-result-icon">β</span><strong>' + escapeHtml(domain) + ' will be used with your hosting.</strong></div><p>No domain registration or transfer will be added.</p></div>', 'success');
saveState();
return;
}
setDomainMessage(payload.message || 'Domain check completed.', 'success');
saveState();
}
function checkDomain() {
if (domainCheckInProgress) { return; }
var domainInput = document.getElementById('hpDomainInput');
var domain = normaliseDomain(domainInput ? domainInput.value : '');
var mode = selectedDomainMode();
if (mode === 'none') {
mode = 'register';
switchDomainMode('register', { keepResult: true });
}
syncHiddenFields(domain, mode, '');
domainState.domain = domain;
domainState.mode = mode;
if (!domain) {
setDomainResult('', '');
setDomainMessage('Please enter a domain name first.', 'error');
saveState();
return;
}
if (domain.indexOf('.') === -1) {
setDomainResult('', '');
setDomainMessage('Please enter a complete domain name, for example yourdomain.co.ke.', 'error');
saveState();
return;
}
domainCheckInProgress = true;
setDomainMessage('Checking domain on this page...', '');
setDomainResult('', '');
fetch(webRoot + '/opcheckout_domain.php?domain=' + encodeURIComponent(domain) + '&mode=' + encodeURIComponent(mode), {
method: 'GET', credentials: 'same-origin', headers: { 'Accept': 'application/json' }
})
.then(function (response) { return response.json().then(function (payload) { payload.httpStatus = response.status; return payload; }); })
.then(function (payload) {
if (!payload.success && payload.status !== 'unavailable') {
domainState.checked = false;
domainState.status = payload.status || 'error';
domainState.payload = payload;
setDomainResult('', '');
setDomainMessage(payload.message || 'Domain could not be checked.', 'error');
saveState();
return;
}
renderDomainPayload(payload, mode);
toggleDomainClear(true);
})
.catch(function () {
domainState.checked = false;
setDomainResult('', '');
setDomainMessage('Domain availability could not be checked right now. Please try again.', 'error');
saveState();
})
.finally(function () { domainCheckInProgress = false; });
}
function openEppModal() {
document.querySelectorAll('.hp-result-action-menu[open]').forEach(function (menu) { menu.open = false; });
var modal = document.getElementById('hpEppModal');
if (!modal) { return; }
var line = document.getElementById('hpEppDomainLine');
var input = document.getElementById('hpEppCode');
var err = document.getElementById('hpEppError');
if (line) { line.textContent = 'Enter the EPP/Auth code for ' + (domainState.domain || 'this domain') + ' to start the transfer.'; }
if (input) { input.value = domainState.eppcode || ''; }
if (err) { err.hidden = true; err.textContent = ''; }
modal.hidden = false;
modal.setAttribute('aria-hidden', 'false');
document.body.classList.add('hp-auth-open');
setTimeout(function () { if (input) { input.focus(); } }, 60);
}
function closeEppModal() {
var modal = document.getElementById('hpEppModal');
if (!modal) { return; }
modal.hidden = true;
modal.setAttribute('aria-hidden', 'true');
document.body.classList.remove('hp-auth-open');
}
function completeTransferWithEpp() {
var input = document.getElementById('hpEppCode');
var err = document.getElementById('hpEppError');
var code = input ? input.value.trim() : '';
if (!code) {
if (err) { err.textContent = 'EPP/Auth code is required for domain transfer.'; err.hidden = false; }
if (input) { input.focus(); }
return;
}
domainState.eppcode = code;
switchDomainMode('transfer', { keepResult: true });
domainState.status = 'transfer-selected';
domainState.checked = true;
setTakenOptions(false);
setDomainMessage('Domain transfer selected. Please ensure the domain is unlocked at the current registrar.', 'success');
syncHiddenFields(domainState.domain, domainState.mode, domainState.status);
saveState();
closeEppModal();
}
function updateCycleCard(card) {
if (!card) { return; }
cycle = card.getAttribute('data-cycle') || cycle;
document.querySelectorAll('.hp-cycle-card').forEach(function (el) { el.classList.remove('is-selected'); });
card.classList.add('is-selected');
var label = card.getAttribute('data-label') || cycle;
var total = card.getAttribute('data-total') || '';
var cycleText = document.getElementById('hpSummaryCycle');
var productTotal = document.getElementById('hpSummaryProductTotal');
var grandTotal = document.getElementById('hpSummaryGrandTotal');
if (cycleText) { cycleText.textContent = label.toLowerCase().replace(/\b\w/g, function (c) { return c.toUpperCase(); }); }
if (productTotal && total) { productTotal.textContent = total; }
updateOrderTotal();
var promoField = document.getElementById('hpPromoInput');
var newUrl = webRoot + '/opcheckout.php?pid=' + encodeURIComponent(pid) + '&cycle=' + encodeURIComponent(cycle);
if (promoField && promoField.value.trim()) { newUrl += '&promo=' + encodeURIComponent(promoField.value.trim()); }
if (window.history && window.history.replaceState) { window.history.replaceState({}, '', newUrl); }
setDomainMessage('Billing cycle updated. Your domain selection was kept.', 'success');
saveState();
}
document.addEventListener('click', function (event) {
var menuAction = event.target && event.target.closest('[data-hp-domain-menu-action]');
if (menuAction) {
event.preventDefault();
var menuMode = menuAction.getAttribute('data-hp-domain-menu-action');
var domainInput = document.getElementById('hpDomainInput');
if (menuMode === 'try-another') {
if (domainInput) { domainInput.value = ''; domainInput.focus(); }
domainState = { domain: '', mode: 'register', status: '', checked: false, payload: null, period: 1, eppcode: '' };
switchDomainMode(domainState.mode, { keepResult: false });
setTakenOptions(false);
setDomainMessage('Type another domain and search again.', 'success');
saveState();
return;
}
if (menuMode === 'transfer') {
openEppModal();
return;
}
switchDomainMode(menuMode, { keepResult: true });
domainState.status = 'own-domain';
domainState.checked = true;
setTakenOptions(false);
setDomainMessage('We will host this domain after you update its nameservers.', 'success');
syncHiddenFields(domainState.domain, domainState.mode, domainState.status);
saveState();
return;
}
var action = event.target && event.target.closest('[data-hp-domain-action]');
if (action) {
event.preventDefault();
var mode = action.getAttribute('data-hp-domain-action');
if (action.classList.contains('is-remove')) {
domainState.status = '';
domainState.checked = false;
action.classList.remove('is-remove');
action.textContent = 'Add to Cart';
var selectedCard = action.closest('.hp-search-result-card');
if (selectedCard) { selectedCard.classList.remove('is-selected'); }
var oldPanel = document.querySelector('[data-hp-primary-domain-period]');
if (oldPanel) { oldPanel.hidden = true; }
syncHiddenFields(domainState.domain, domainState.mode || 'register', '');
setDomainMessage('Domain removed from cart. Click Add to Cart to include it again.', 'success');
saveState();
return;
}
switchDomainMode(mode, { keepResult: true });
if (mode === 'register') {
domainState.status = 'available';
setDomainMessage('Domain registration selected. Continue on this checkout page.', 'success');
action.classList.add('is-remove');
action.textContent = 'Remove';
var primaryCard = action.closest('.hp-search-result-card');
if (primaryCard) { primaryCard.classList.add('is-selected'); }
var panel = document.querySelector('[data-hp-primary-domain-period]');
if (panel) { panel.hidden = false; }
} else if (mode === 'transfer') {
domainState.status = 'transfer-selected';
setDomainMessage('Domain transfer selected. We will collect any required transfer details here in the next step.', 'success');
} else if (mode === 'owndomain') {
domainState.status = 'own-domain';
setDomainMessage('Existing-domain option selected. Continue on this checkout page.', 'success');
}
domainState.checked = true;
syncHiddenFields(domainState.domain, domainState.mode, domainState.status);
saveState();
return;
}
var suggestion = event.target && event.target.closest('[data-hp-suggestion-domain]');
if (suggestion) {
event.preventDefault();
var suggestedDomain = normaliseDomain(suggestion.getAttribute('data-hp-suggestion-domain') || '');
if (suggestedDomain) {
uniqueAdditionalDomains();
var idx = selectedAdditionalDomains.indexOf(suggestedDomain);
if (idx === -1) {
selectedAdditionalDomains.push(suggestedDomain);
selectedAdditionalDomainPrices[suggestedDomain] = parseAmount(suggestion.getAttribute('data-hp-domain-price'));
selectedAdditionalDomainRenewPrices[suggestedDomain] = parseAmount(suggestion.getAttribute('data-hp-domain-renew-price') || suggestion.getAttribute('data-hp-domain-price'));
selectedAdditionalDomainPeriods[suggestedDomain] = parseInt(selectedAdditionalDomainPeriods[suggestedDomain] || 1, 10) || 1;
setDomainMessage(suggestedDomain + ' added as an extra domain registration. Your searched domain is still kept.', 'success');
} else {
selectedAdditionalDomains.splice(idx, 1);
delete selectedAdditionalDomainPrices[suggestedDomain];
delete selectedAdditionalDomainRenewPrices[suggestedDomain];
delete selectedAdditionalDomainPeriods[suggestedDomain];
setDomainMessage(suggestedDomain + ' removed from extra domain registrations.', 'success');
}
domainState.additionalDomains = selectedAdditionalDomains.slice();
syncHiddenFields(domainState.domain, domainState.mode, domainState.status);
renderAdditionalDomainCart();
syncSuggestionButtons();
saveState();
}
return;
}
var removeExtra = event.target && event.target.closest('[data-hp-remove-extra-domain]');
if (removeExtra) {
event.preventDefault();
var removeDomain = normaliseDomain(removeExtra.getAttribute('data-hp-remove-extra-domain') || '');
selectedAdditionalDomains = selectedAdditionalDomains.filter(function (domain) { return domain !== removeDomain; });
delete selectedAdditionalDomainPrices[removeDomain];
delete selectedAdditionalDomainRenewPrices[removeDomain];
delete selectedAdditionalDomainPeriods[removeDomain];
domainState.additionalDomains = selectedAdditionalDomains.slice();
setDomainMessage(removeDomain + ' removed from extra domain registrations.', 'success');
renderAdditionalDomainCart();
syncSuggestionButtons();
saveState();
return;
}
var cycleCard = event.target && event.target.closest('.hp-cycle-card');
if (cycleCard) {
event.preventDefault();
updateCycleCard(cycleCard);
}
});
document.addEventListener('change', function (event) {
var period = event.target && event.target.closest('[data-hp-domain-period]');
if (!period) { return; }
var years = Math.max(1, Math.min(5, parseInt(period.value || '1', 10) || 1));
var first = parseAmount(period.getAttribute('data-first-price'));
var renew = parseAmount(period.getAttribute('data-renew-price') || first);
var firstFree = period.getAttribute('data-first-free') === '1';
var total = period.parentElement ? period.parentElement.querySelector('.hp-selected-period-total') : null;
if (total) { total.textContent = formatAmount(domainPeriodTotal(first, renew, years, firstFree)); }
var extraDomain = period.getAttribute('data-hp-extra-domain-period');
if (extraDomain) {
extraDomain = normaliseDomain(extraDomain);
selectedAdditionalDomainPeriods[extraDomain] = years;
updateOrderTotal();
saveState();
return;
}
if (period.closest('[data-hp-primary-domain-period]')) {
domainState.period = years;
updateOrderTotal();
saveState();
}
});
document.addEventListener('click', function (event) {
var closeEpp = event.target && event.target.closest('[data-hp-epp-close]');
if (closeEpp) { event.preventDefault(); closeEppModal(); }
});
var eppSubmit = document.getElementById('hpEppSubmit');
if (eppSubmit) { eppSubmit.addEventListener('click', completeTransferWithEpp); }
var eppInput = document.getElementById('hpEppCode');
if (eppInput) { eppInput.addEventListener('keydown', function (event) { if (event.key === 'Enter') { event.preventDefault(); completeTransferWithEpp(); } }); }
var apply = document.getElementById('hpApplyPromo');
if (apply) {
apply.addEventListener('click', function () {
saveState();
var promo = document.getElementById('hpPromoInput').value.trim();
window.location.href = buildUrl(promo);
});
}
var remove = document.getElementById('hpRemovePromo');
if (remove) {
remove.addEventListener('click', function () {
saveState();
window.location.href = buildUrl('');
});
}
document.querySelectorAll('input[name="hp_domain_mode"]').forEach(function (input) {
input.addEventListener('change', function () {
switchDomainMode(input.value, { keepResult: false });
});
});
var domainInput = document.getElementById('hpDomainInput');
var clearDomain = document.getElementById('hpClearDomain');
function toggleDomainClear(show) {
var search = document.getElementById('hpCheckDomain');
if (clearDomain) { clearDomain.hidden = !show; }
if (search) { search.hidden = !!show; }
}
if (clearDomain) {
clearDomain.addEventListener('click', function () {
if (domainInput) { domainInput.value = ''; domainInput.focus(); }
domainState = { domain: '', mode: 'register', status: '', checked: false, payload: null, period: 1, eppcode: '' };
selectedAdditionalDomains = [];
selectedAdditionalDomainPrices = {};
selectedAdditionalDomainRenewPrices = {};
selectedAdditionalDomainPeriods = {};
setTakenOptions(false);
setDomainResult('', '');
setDomainMessage('Search cleared. Type another domain to check.', 'success');
syncHiddenFields('', 'register', '');
toggleDomainClear(false);
saveState();
});
}
if (domainInput) {
domainInput.addEventListener('input', function () {
var domain = normaliseDomain(domainInput.value);
domainState.domain = domain;
domainState.checked = false;
domainState.status = '';
domainState.payload = null;
setTakenOptions(false);
syncHiddenFields(domain, selectedDomainMode(), '');
setDomainResult('', '');
toggleDomainClear(false);
updateOrderTotal();
saveState();
});
domainInput.addEventListener('blur', function () {
domainInput.value = normaliseDomain(domainInput.value);
domainState.domain = domainInput.value;
syncHiddenFields(domainState.domain, selectedDomainMode(), domainState.status);
saveState();
});
}
var domainForm = document.getElementById('hpDomainForm');
if (domainForm) {
domainForm.addEventListener('submit', function (event) { event.preventDefault(); checkDomain(); });
}
function fieldValue(id) {
var el = document.getElementById(id);
return el ? el.value.trim() : '';
}
function setOrderResult(html, type) {
var el = document.getElementById('hpOrderResult');
if (!el) { return; }
el.hidden = !html;
el.className = 'hp-order-result' + (type ? ' is-' + type : '');
el.innerHTML = html || '';
}
function setAuthMessage(message, type) {
var el = document.getElementById('hpAuthMessage');
if (!el) { return; }
el.hidden = !message;
el.className = 'hp-auth-message' + (type ? ' is-' + type : '');
el.innerHTML = message ? escapeHtml(message) : '';
}
function openAuthModal(tab) {
var modal = document.getElementById('hpAuthModal');
if (!modal) { return; }
if (modal.parentElement !== document.body) {
document.body.appendChild(modal);
}
modal.hidden = false;
modal.setAttribute('aria-hidden', 'false');
document.body.classList.add('hp-auth-open');
switchAuthTab(tab || 'login');
setTimeout(function () {
var focus = document.getElementById(tab === 'register' ? 'hpFirstName' : 'hpLoginEmail');
if (focus) { focus.focus(); }
}, 60);
}
function closeAuthModal() {
var modal = document.getElementById('hpAuthModal');
if (!modal) { return; }
modal.hidden = true;
modal.setAttribute('aria-hidden', 'true');
document.body.classList.remove('hp-auth-open');
}
function switchAuthTab(tab) {
tab = tab === 'register' ? 'register' : 'login';
document.querySelectorAll('[data-hp-auth-tab]').forEach(function (btn) {
btn.classList.toggle('is-active', btn.getAttribute('data-hp-auth-tab') === tab && btn.tagName === 'BUTTON' && btn.closest('.hp-auth-tabs'));
});
var login = document.getElementById('hpLoginForm');
var register = document.getElementById('hpRegisterForm');
if (login) { login.classList.toggle('is-active', tab === 'login'); }
if (register) { register.classList.toggle('is-active', tab === 'register'); }
var title = document.getElementById('hpAuthTitle');
if (title) { title.textContent = tab === 'register' ? 'Create your account' : 'Login to continue'; }
setAuthMessage('', '');
}
function collectClient(includePassword) {
return {
firstname: fieldValue('hpFirstName'),
lastname: fieldValue('hpLastName'),
email: fieldValue('hpEmail'),
phonenumber: fieldValue('hpPhone'),
companyname: fieldValue('hpCompany'),
address1: fieldValue('hpAddress'),
city: fieldValue('hpCity'),
state: fieldValue('hpCity'),
country: fieldValue('hpCountry') || 'KE',
postcode: fieldValue('hpPostcode') || '00100',
password: includePassword ? fieldValue('hpPassword') : ''
};
}
function validateClient(client) {
var errors = [];
if (!client.firstname) { errors.push('First name is required.'); }
if (!client.lastname) { errors.push('Last name is required.'); }
if (!client.email || !/^\S+@\S+\.\S+$/.test(client.email)) { errors.push('A valid email address is required.'); }
if (!client.phonenumber) { errors.push('Phone number is required.'); }
if (!client.address1) { errors.push('Address is required.'); }
if (!client.city) { errors.push('City is required.'); }
if (!client.password || client.password.length < 8) { errors.push('Password must be at least 8 characters.'); }
if (!document.getElementById('hpTermsAccepted').checked) { errors.push('Please accept the terms first.'); }
return errors;
}
function hasConfirmedDomain() {
if (!hpNeedsDomain) { return true; }
var domain = normaliseDomain(domainInput ? domainInput.value : '');
var mode = selectedDomainMode();
if (hpDomainOptional && mode === 'none') {
domainState = { domain: '', mode: 'none', status: 'not_required', checked: true, payload: null, period: 1, eppcode: '' };
syncHiddenFields('', 'none', 'not_required');
saveState();
return true;
}
syncHiddenFields(domain, mode, domainState.status);
saveState();
if (!domain) {
setDomainMessage('Please enter and confirm your domain on this page before continuing.', 'error');
return false;
}
if (mode === 'transfer' && (!domainState.eppcode || !domainState.eppcode.trim())) {
setDomainMessage('Please enter the EPP/Auth code to transfer this domain.', 'error');
openEppModal();
return false;
}
if (!domainState.checked || domainState.domain !== domain) {
setDomainMessage('Please check this domain on the page first. We will not send you to the WHMCS cart.', 'error');
checkDomain();
return false;
}
return true;
}
function submitOrder(options) {
options = options || {};
if (!hasConfirmedDomain()) { return; }
var orderCompleted = false;
setOrderResult('', '');
setAuthMessage('', '');
var client = {};
if (!hpLoggedIn || options.register) {
client = collectClient(true);
var errors = validateClient(client);
if (errors.length) {
setAuthMessage('Please complete the highlighted registration details.', 'error');
setOrderResult('<strong>Please complete your details:</strong><ul><li>' + errors.map(escapeHtml).join('</li><li>') + '</li></ul>', 'error');
openAuthModal('register');
return;
}
}
var payload = {
pid: pid,
cycle: cycle,
promo: fieldValue('hpPromoInput'),
paymentmethod: selectedGateway(),
domain: hpNeedsDomain && selectedDomainMode() !== 'none' ? normaliseDomain(domainInput ? domainInput.value : '') : '',
additional_domains: hpNeedsDomain && selectedDomainMode() !== 'none' ? uniqueAdditionalDomains() : [],
additional_domain_periods: hpNeedsDomain && selectedDomainMode() !== 'none' ? selectedAdditionalDomainPeriods : {},
domain_mode: hpNeedsDomain ? selectedDomainMode() : 'none',
domain_status: hpNeedsDomain ? domainState.status : 'not_required',
domain_period: hpNeedsDomain ? (parseInt(domainState.period || 1, 10) || 1) : 1,
eppcode: hpNeedsDomain ? (domainState.eppcode || '') : '',
client: client,
terms_accepted: (hpLoggedIn || (document.getElementById('hpTermsAccepted') && document.getElementById('hpTermsAccepted').checked)) ? 1 : 0
};
var oldText = payNow ? payNow.textContent : 'pay now';
if (payNow) { payNow.disabled = true; payNow.textContent = 'creating order...'; }
setOrderResult('Creating your secure WHMCS order on this page...', 'info');
fetch(webRoot + '/opcheckout_order.php', {
method: 'POST',
credentials: 'same-origin',
headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' },
body: JSON.stringify(payload)
})
.then(function (response) {
return response.json().then(function (data) { data.httpStatus = response.status; return data; });
})
.then(function (data) {
if (!data.success) {
var message = data.message || 'Please review your details and try again.';
setOrderResult('<strong>Order could not be completed.</strong><p>' + escapeHtml(message) + '</p>', 'error');
if (data.login_required) { openAuthModal('login'); }
return;
}
try { localStorage.removeItem(storageKey); } catch (e) {}
orderCompleted = true;
closeAuthModal();
if (payNow) { payNow.hidden = true; payNow.style.display = 'none'; }
var paymentUrl = data.payment_url ? webRoot + '/' + data.payment_url.replace(/^\//, '') : '';
setOrderResult(
'<strong>Order created successfully.</strong>' +
'<p>Order #' + escapeHtml(data.orderid) + ' and invoice #' + escapeHtml(data.invoiceid) + ' were created in WHMCS.</p>' +
(paymentUrl ? '<a class="hp-payment-link" href="' + escapeHtml(paymentUrl) + '">Continue to secure payment</a>' : '<p>Please check your email for the invoice and payment instructions.</p>'),
'success'
);
})
.catch(function () {
setOrderResult('<strong>Order could not be completed.</strong><p>Network or server error. Please try again.</p>', 'error');
})
.finally(function () {
if (payNow && !orderCompleted) { payNow.disabled = false; payNow.textContent = oldText; }
});
}
function loginThenPay() {
if (!hasConfirmedDomain()) { closeAuthModal(); return; }
var email = fieldValue('hpLoginEmail');
var password = fieldValue('hpLoginPassword');
if (!email || !password) {
setAuthMessage('Please enter your email and password.', 'error');
return;
}
var btn = document.querySelector('#hpLoginForm .hp-auth-submit');
var old = btn ? btn.textContent : '';
if (btn) { btn.disabled = true; btn.textContent = 'checking login...'; }
fetch(webRoot + '/opcheckout_login.php', {
method: 'POST',
credentials: 'same-origin',
headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' },
body: JSON.stringify({ email: email, password: password })
})
.then(function (response) { return response.json().then(function (data) { data.httpStatus = response.status; return data; }); })
.then(function (data) {
if (!data.success) {
setAuthMessage(data.message || 'Login failed. Please try again.', 'error');
return;
}
hpLoggedIn = true;
setAuthMessage('Login successful. Creating your order...', 'success');
submitOrder({ loggedIn: true });
})
.catch(function () { setAuthMessage('Login could not be completed right now. Please try again.', 'error'); })
.finally(function () { if (btn) { btn.disabled = false; btn.textContent = old; } });
}
var payNow = document.getElementById('hpPayNow');
if (payNow) {
payNow.addEventListener('click', function () {
if (!hasConfirmedDomain()) { return; }
if (hpLoggedIn) { submitOrder({ loggedIn: true }); }
else { openAuthModal('login'); }
});
}
var loginForm = document.getElementById('hpLoginForm');
if (loginForm) { loginForm.addEventListener('submit', function (event) { event.preventDefault(); loginThenPay(); }); }
var registerForm = document.getElementById('hpRegisterForm');
if (registerForm) { registerForm.addEventListener('submit', function (event) { event.preventDefault(); submitOrder({ register: true }); }); }
document.addEventListener('click', function (event) {
var close = event.target && event.target.closest('[data-hp-auth-close]');
if (close) { event.preventDefault(); closeAuthModal(); return; }
var tab = event.target && event.target.closest('[data-hp-auth-tab]');
if (tab) { event.preventDefault(); switchAuthTab(tab.getAttribute('data-hp-auth-tab')); }
});
document.addEventListener('keydown', function (event) {
if (event.key === 'Escape') { closeAuthModal(); }
});
document.querySelectorAll('.hp-gateway-option input').forEach(function (input) {
input.addEventListener('change', function () {
document.querySelectorAll('.hp-gateway-option').forEach(function (el) { el.classList.remove('is-selected'); });
input.closest('.hp-gateway-option').classList.add('is-selected');
var paymentHidden = document.getElementById('hpPaymentMethodHidden');
if (paymentHidden) { paymentHidden.value = input.value; }
saveState();
});
});
function restoreState() {
var saved = readState();
if (initialDomain) {
try { localStorage.removeItem(storageKey); } catch (e) {}
switchDomainMode(initialDomainMode || 'register', { keepResult: false });
domainState.domain = normaliseDomain(initialDomain);
domainState.mode = initialDomainMode || 'register';
syncHiddenFields(domainState.domain, domainState.mode, '');
setDomainMessage('Domain search loaded here. We are checking it on this page.', '');
if (autoCheckInitialDomain) { setTimeout(checkDomain, 250); }
return;
}
if (!saved || (!saved.domain && !saved.mode && !saved.gateway && !saved.cycle)) {
if (hpDomainOptional && !hpDomainOnly) { switchDomainMode('register', { keepResult: false }); }
return;
}
// Respect the cycle in the current URL/server render. Domain and gateway state are restored,
// but we do not override a fresh product link with an old saved billing cycle.
if (hpDomainOptional && !hpDomainOnly && saved.mode === 'none') { saved.mode = 'register'; }
if (saved.mode) { switchDomainMode(saved.mode, { keepResult: true }); }
if (saved.domain) {
domainState.domain = normaliseDomain(saved.domain);
domainState.mode = saved.mode || selectedDomainMode();
domainState.status = saved.status || '';
domainState.checked = !!saved.checked;
domainState.payload = saved.payload || null;
domainState.period = saved.period || 1;
domainState.eppcode = saved.eppcode || '';
syncHiddenFields(domainState.domain, domainState.mode, domainState.status);
if (domainState.payload) { renderDomainPayload(domainState.payload, domainState.mode); }
else { setDomainMessage('Your domain was kept. Click βCheck domainβ to confirm it.', ''); }
}
if (saved.gateway) {
var gateway = document.querySelector('input[name="paymentmethod_preview"][value="' + saved.gateway + '"]');
if (gateway) { gateway.checked = true; gateway.dispatchEvent(new Event('change')); }
}
if (saved.client) {
var c = saved.client;
[['hpFirstName','firstname'],['hpLastName','lastname'],['hpEmail','email'],['hpPhone','phonenumber'],['hpCompany','companyname'],['hpAddress','address1'],['hpCity','city'],['hpCountry','country'],['hpPostcode','postcode']].forEach(function (pair) {
var el = document.getElementById(pair[0]);
if (el && c[pair[1]]) { el.value = c[pair[1]]; }
});
}
}
restoreState();
})();
</script>