{"id":7,"date":"2026-07-23T13:08:59","date_gmt":"2026-07-23T13:08:59","guid":{"rendered":"https:\/\/test.kdlink.dev\/?page_id=7"},"modified":"2026-07-25T11:40:29","modified_gmt":"2026-07-25T11:40:29","slug":"elementor-7","status":"publish","type":"page","link":"https:\/\/test.kdlink.dev\/?page_id=7","title":{"rendered":"Elementor #7"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-post\" data-elementor-id=\"7\" class=\"elementor elementor-7\">\n\t\t\t\t<div class=\"elementor-element elementor-element-c5ce9e8 e-con-full e-flex e-con e-parent\" data-id=\"c5ce9e8\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-006ec34 elementor-widget elementor-widget-html\" data-id=\"006ec34\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t\t<!-- ============================================================\r\n     KL SCROLL HERO  \u2014  v2\r\n     Paste this ENTIRE block into an Elementor \"HTML\" widget.\r\n     Frames: https:\/\/test.kdlink.dev\/wp-content\/uploads\/kl-hero\/\r\n     ============================================================ -->\r\n\r\n<div class=\"klhero-stage\" id=\"klheroStage\">\r\n  <div class=\"klhero-pin\">\r\n    <canvas class=\"klhero-canvas\" id=\"klheroCanvas\"><\/canvas>\r\n    <span class=\"klhero-load\" id=\"klheroLoad\"><\/span>\r\n\r\n    <div class=\"klhero-copy\">\r\n      <p class=\"klhero-kick\">WordPress &amp; WooCommerce engineer \u2014 Dubai<\/p>\r\n      <h1 class=\"klhero-title\">Stores that <em>ship<\/em>, not just launch.<\/h1>\r\n      <p class=\"klhero-sub\">Custom plugins, payment gateways, hosting and security for e-commerce brands across the UAE.<\/p>\r\n      <p class=\"klhero-cue\">Scroll<\/p>\r\n    <\/div>\r\n  <\/div>\r\n<\/div>\r\n\r\n<style>\r\n\/* scoped to .klhero-* so nothing leaks into the theme *\/\r\n.klhero-stage{position:relative;height:250vh;background:#05070C}\r\n.klhero-pin{position:sticky;top:0;height:100svh;overflow:hidden}\r\n.klhero-canvas{position:absolute;inset:0;width:100%;height:100%;display:block}\r\n\r\n.klhero-pin::after{\r\n  content:\"\";position:absolute;inset:0;pointer-events:none;\r\n  background:radial-gradient(120% 90% at 50% 45%,transparent 40%,rgba(5,7,12,.78) 100%);\r\n}\r\n\r\n.klhero-load{\r\n  position:absolute;left:0;top:0;height:2px;width:0;background:#4FC3FF;z-index:5;\r\n  transition:width .3s ease,opacity .5s ease .3s;\r\n}\r\n.klhero-load.is-done{opacity:0}\r\n\r\n.klhero-copy{\r\n  position:absolute;inset:0;z-index:2;display:flex;flex-direction:column;justify-content:flex-end;\r\n  padding:0 clamp(20px,5vw,72px) clamp(48px,9vh,96px);pointer-events:none;\r\n  color:#E8EEF7;\r\n}\r\n.klhero-copy > *{pointer-events:auto}\r\n.klhero-kick{\r\n  font-family:ui-monospace,'SF Mono',Consolas,monospace;font-size:12px;letter-spacing:.16em;\r\n  text-transform:uppercase;color:#4FC3FF;margin:0 0 18px;\r\n}\r\n.klhero-title{\r\n  font-size:clamp(2.2rem,6.4vw,5rem);line-height:1;letter-spacing:-.035em;\r\n  font-weight:700;max-width:16ch;margin:0;color:#E8EEF7;\r\n}\r\n.klhero-title em{font-style:normal;color:#FF9A2E}\r\n.klhero-sub{color:#7C8798;max-width:44ch;margin:20px 0 0;font-size:clamp(.95rem,1.4vw,1.05rem)}\r\n.klhero-cue{\r\n  position:absolute;left:clamp(20px,5vw,72px);bottom:18px;margin:0;\r\n  font-family:ui-monospace,Consolas,monospace;font-size:11px;letter-spacing:.16em;\r\n  text-transform:uppercase;color:#7C8798;\r\n}\r\n\r\n\/* ---- mobile: animation sits high, copy sits under it ---- *\/\r\n@media (max-width:760px){\r\n  .klhero-copy{padding-bottom:clamp(60px,12vh,110px)}\r\n  .klhero-title{font-size:clamp(1.9rem,8.5vw,2.6rem)}\r\n  .klhero-sub{font-size:.92rem;margin-top:14px}\r\n  .klhero-pin::after{\r\n    background:linear-gradient(to bottom,transparent 38%,rgba(5,7,12,.92) 72%);\r\n  }\r\n}\r\n\r\n@media (prefers-reduced-motion: reduce){\r\n  .klhero-stage{height:100svh}\r\n  .klhero-load{display:none}\r\n}\r\n<\/style>\r\n\r\n<script>\r\n(function(){\r\n'use strict';\r\n\r\n\/* ---------------- config ---------------- *\/\r\nvar BASE      = 'https:\/\/test.kdlink.dev\/wp-content\/uploads\/kl-hero\/';\r\nvar CACHE_TAG = 'v2';          \/\/ bump this to v3, v4... every time you re-upload frames\r\nvar MOBILE    = window.matchMedia('(max-width: 760px)').matches;\r\nvar DIR       = BASE + (MOBILE ? 'frames-m\/' : 'frames\/');\r\nvar COUNT     = MOBILE ? 61 : 121;\r\nvar REDUCE    = window.matchMedia('(prefers-reduced-motion: reduce)').matches;\r\nvar EAGER     = 12;            \/\/ frames decoded before scrubbing starts\r\nvar PARALLEL  = 6;             \/\/ simultaneous downloads\r\nvar MOB_ZOOM  = 1.45;          \/\/ mobile framing: lower = more of the frame visible\r\nvar MOB_TOP   = 0.12;          \/\/ mobile vertical anchor (0 = top of screen)\r\n\r\nfunction url(i){\r\n  return DIR + 'f_' + String(i).padStart(4,'0') + '.webp?' + CACHE_TAG;\r\n}\r\n\r\n\/* ---------------- elements ---------------- *\/\r\nvar stage  = document.getElementById('klheroStage');\r\nvar canvas = document.getElementById('klheroCanvas');\r\nvar ctx    = canvas.getContext('2d', {alpha:false});\r\nvar bar    = document.getElementById('klheroLoad');\r\n\r\nvar frames = new Array(COUNT + 1);\r\nvar loaded = 0, drawn = -1, ready = false, cw = 0, ch = 0;\r\nvar target = 1, eased = 1;\r\n\r\n\/* if frames-m was never uploaded, fall back to the desktop folder *\/\r\nfunction checkMobileFolder(){\r\n  if(!MOBILE) return Promise.resolve();\r\n  return fetch(url(1), {method:'HEAD'})\r\n    .then(function(r){ if(!r.ok) throw 0; })\r\n    .catch(function(){\r\n      DIR = BASE + 'frames\/';\r\n      COUNT = 121;\r\n      frames = new Array(COUNT + 1);\r\n    });\r\n}\r\n\r\n\/* ---------------- decode ---------------- *\/\r\nfunction grab(i){\r\n  return fetch(url(i), {cache:'force-cache'})\r\n    .then(function(r){ if(!r.ok) throw 0; return r.blob(); })\r\n    .then(function(blob){\r\n      if(window.createImageBitmap) return createImageBitmap(blob);\r\n      return new Promise(function(ok,no){\r\n        var im = new Image();\r\n        im.onload = function(){ ok(im); };\r\n        im.onerror = no;\r\n        im.src = URL.createObjectURL(blob);\r\n      });\r\n    })\r\n    .then(function(img){ frames[i] = img; })\r\n    .catch(function(){ \/* empty slot \u2014 nearest() covers it *\/ })\r\n    .then(function(){\r\n      loaded++;\r\n      bar.style.width = (loaded \/ COUNT * 100) + '%';\r\n      if(loaded >= COUNT) bar.classList.add('is-done');\r\n    });\r\n}\r\n\r\nfunction queue(from, to){\r\n  var next = from;\r\n  function worker(){\r\n    if(next > to) return Promise.resolve();\r\n    return grab(next++).then(worker);\r\n  }\r\n  var jobs = [];\r\n  for(var k = 0; k < PARALLEL; k++) jobs.push(worker());\r\n  return Promise.all(jobs);\r\n}\r\n\r\nfunction nearest(i){\r\n  if(frames[i]) return frames[i];\r\n  for(var d = 1; d < COUNT; d++){\r\n    if(frames[i-d]) return frames[i-d];\r\n    if(frames[i+d]) return frames[i+d];\r\n  }\r\n  return null;\r\n}\r\n\r\n\/* ---------------- canvas ---------------- *\/\r\nfunction resize(){\r\n  var dpr = Math.min(window.devicePixelRatio || 1, 2);\r\n  cw = canvas.clientWidth;\r\n  ch = canvas.clientHeight;\r\n  canvas.width  = Math.round(cw * dpr);\r\n  canvas.height = Math.round(ch * dpr);\r\n  ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\r\n  drawn = -1;                       \/\/ force repaint at new size\r\n}\r\n\r\nfunction paint(img){\r\n  if(!img) return;\r\n  var fit, x, y, w, h;\r\n\r\n  if(MOBILE){\r\n    \/* portrait screen, landscape footage \u2014 fit by width, anchor high *\/\r\n    fit = (cw \/ img.width) * MOB_ZOOM;\r\n    w = img.width * fit;\r\n    h = img.height * fit;\r\n    x = (cw - w) \/ 2;\r\n    y = ch * MOB_TOP;\r\n  } else {\r\n    fit = Math.max(cw \/ img.width, ch \/ img.height);\r\n    w = img.width * fit;\r\n    h = img.height * fit;\r\n    x = (cw - w) \/ 2;\r\n    y = (ch - h) \/ 2;\r\n  }\r\n\r\n  ctx.fillStyle = '#05070C';\r\n  ctx.fillRect(0, 0, cw, ch);\r\n  ctx.drawImage(img, x, y, w, h);\r\n}\r\n\r\n\/* ---------------- scroll \u2192 frame ---------------- *\/\r\nfunction progress(){\r\n  var span = stage.offsetHeight - window.innerHeight;\r\n  if(span <= 0) return 1;\r\n  var p = -stage.getBoundingClientRect().top \/ span;\r\n  return p < 0 ? 0 : (p > 1 ? 1 : p);\r\n}\r\n\r\nfunction tick(){\r\n  requestAnimationFrame(tick);\r\n  if(!ready) return;\r\n  target = 1 + progress() * (COUNT - 1);\r\n  eased += (target - eased) * (REDUCE ? 1 : 0.18);\r\n  var i = Math.round(eased);\r\n  if(i !== drawn){ paint(nearest(i)); drawn = i; }\r\n}\r\n\r\n\/* ---------------- boot ---------------- *\/\r\nwindow.addEventListener('resize', resize, {passive:true});\r\nwindow.addEventListener('orientationchange', resize, {passive:true});\r\nresize();\r\n\r\ncheckMobileFolder().then(function(){\r\n  if(REDUCE){\r\n    return grab(COUNT).then(function(){\r\n      ready = true;\r\n      paint(frames[COUNT]);\r\n      drawn = COUNT;\r\n      bar.classList.add('is-done');\r\n    });\r\n  }\r\n  return grab(1).then(function(){\r\n    paint(frames[1]);\r\n    drawn = 1;\r\n    return queue(2, Math.min(EAGER, COUNT));\r\n  }).then(function(){\r\n    ready = true;\r\n    tick();\r\n    queue(EAGER + 1, COUNT);      \/\/ rest streams in while the user reads\r\n  });\r\n});\r\n\r\n})();\r\n<\/script>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-7a9adcd e-con-full e-flex e-con e-parent\" data-id=\"7a9adcd\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-76e14c1 elementor-widget elementor-widget-html\" data-id=\"76e14c1\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t\t<!-- ============================================================\r\n     KL PORTFOLIO \u2014 sections below the hero  (v6)\r\n     Paste into a SECOND Elementor \"HTML\" widget, under the hero.\r\n     Screenshots: \/wp-content\/uploads\/kl-hero\/shots\/\r\n     ============================================================ -->\r\n\r\n<div class=\"klp\">\r\n\r\n  <!-- ========== 1. WORD-BY-WORD SCROLL HIGHLIGHT ========== -->\r\n  <section class=\"klp-words\" id=\"klpWords\">\r\n    <div class=\"klp-words-pin\">\r\n      <p class=\"klp-para\" id=\"klpPara\">I don't just launch stores. I write the plugins underneath them, wire the payment gateways, run the servers they live on, set up the email that actually lands in the inbox &mdash; and clean the malware when someone else's build goes down.<\/p>\r\n    <\/div>\r\n  <\/section>\r\n\r\n  <!-- ========== 2. BIG HORIZONTAL STACKING CARDS ========== -->\r\n  <section class=\"klp-deck\" id=\"klpDeck\">\r\n    <div class=\"klp-deck-pin\">\r\n      <p class=\"klp-eyebrow klp-deck-label\">Selected builds \u2014 click any to open<\/p>\r\n      <div class=\"klp-stack\" id=\"klpStack\"><\/div>\r\n    <\/div>\r\n  <\/section>\r\n\r\n  <!-- ========== 3. what I do ========== -->\r\n  <section class=\"klp-sec klp-sec--line\" id=\"klp-stack\">\r\n    <div class=\"klp-head\">\r\n      <p class=\"klp-eyebrow\">What I actually do<\/p>\r\n      <h2 class=\"klp-h2\">Six things, one invoice.<\/h2>\r\n    <\/div>\r\n    <div class=\"klp-layers\">\r\n      <div class=\"klp-layer klp-rise\"><span class=\"klp-num\">01<\/span><h3>Interface<\/h3><p>Elementor plus hand-written CSS, scroll-driven heroes, carousels that behave on a phone. Built as a plugin, so a theme update can't take the front end down.<\/p><\/div>\r\n      <div class=\"klp-layer klp-rise\"><span class=\"klp-num\">02<\/span><h3>Plugins<\/h3><p>One custom plugin instead of ten from the repository. Product suites, popups, admin panels the client can use without calling me.<\/p><\/div>\r\n      <div class=\"klp-layer klp-rise\"><span class=\"klp-num\">03<\/span><h3>Commerce<\/h3><p>Variations, coupons, shipping rules, multi-currency. Gateways integrated and then debugged for real \u2014 Tabby, Tamara, Ziina, Apple Pay.<\/p><\/div>\r\n      <div class=\"klp-layer klp-rise\"><span class=\"klp-num\">04<\/span><h3>Servers &amp; email<\/h3><p>Reseller hosting for 15+ client sites. DNS, SMTP, staging isolation, migrations, and professional email set up in Outlook and Thunderbird so it lands in the inbox, not spam.<\/p><\/div>\r\n      <div class=\"klp-layer klp-rise\"><span class=\"klp-num\">05<\/span><h3>Security<\/h3><p>CEH-certified cleanups and hardening. Hidden plugins, redirect backdoors, business email compromise \u2014 every job ends with a written report.<\/p><\/div>\r\n      <div class=\"klp-layer klp-rise\"><span class=\"klp-num\">06<\/span><h3>Support<\/h3><p>Ongoing maintenance and IT support for UAE businesses \u2014 the person you call when something breaks and it needs to be back up today.<\/p><\/div>\r\n    <\/div>\r\n  <\/section>\r\n\r\n  <!-- ========== 4. security case ========== -->\r\n  <section class=\"klp-sec klp-sec--line\" id=\"klp-case\">\r\n    <div class=\"klp-head\">\r\n      <p class=\"klp-eyebrow\">Incident response<\/p>\r\n      <h2 class=\"klp-h2\">When it has already gone wrong.<\/h2>\r\n    <\/div>\r\n    <div class=\"klp-case klp-rise\">\r\n      <div>\r\n        <h3 class=\"klp-case-t\">The site was selling someone else's traffic.<\/h3>\r\n        <p class=\"klp-p\">Visitors arriving from search were redirected through a foreign traffic-distribution network. Behind it: plugins that never appeared in the admin list, a backdoor that rewrote itself on every page load, and an administrator account whose email had been quietly changed.<\/p>\r\n        <p class=\"klp-p\">Cleaned, hardened, and handed back with a report \u2014 what was found, how it got in, and what changed so it stays out.<\/p>\r\n      <\/div>\r\n      <div class=\"klp-log\">\r\n        <span><b>scan<\/b> \u2192 <i>4 hidden plugins<\/i><\/span>\r\n        <span><b>scan<\/b> \u2192 <i>obfuscated loader in mu-plugins<\/i><\/span>\r\n        <span><b>users<\/b> \u2192 <i>1 admin email altered<\/i><\/span>\r\n        <span><b>fix<\/b> \u2192 <u>backdoors removed<\/u><\/span>\r\n        <span><b>fix<\/b> \u2192 <u>credentials rotated<\/u><\/span>\r\n        <span><b>fix<\/b> \u2192 <u>headers &amp; file permissions hardened<\/u><\/span>\r\n        <span><b>status<\/b> \u2192 <u>clean \u00b7 monitored<\/u><\/span>\r\n      <\/div>\r\n    <\/div>\r\n  <\/section>\r\n\r\n  <!-- ========== 5. contact ========== -->\r\n  <section class=\"klp-sec klp-sec--line\" id=\"klp-contact\">\r\n    <p class=\"klp-eyebrow\">Dubai, UAE \u2014 GMT+4<\/p>\r\n    <h2 class=\"klp-cta klp-rise\">Got a build<br>that needs<br><em>fixing?<\/em><\/h2>\r\n    <a class=\"klp-mail klp-rise\" href=\"mailto:hello@kdlink.dev\">hello@kdlink.dev<\/a>\r\n    <div class=\"klp-foot\">\r\n      <span>Zeeshan \u2014 WordPress engineer &amp; CEH-certified security analyst<\/span>\r\n      <span>Available for freelance<\/span>\r\n    <\/div>\r\n  <\/section>\r\n\r\n<\/div>\r\n\r\n<!-- ---------- site preview modal ---------- -->\r\n<div class=\"klp-modal\" id=\"klpModal\" role=\"dialog\" aria-modal=\"true\" aria-label=\"Site preview\">\r\n  <div class=\"klp-modal-bd\" data-klp-close><\/div>\r\n  <div class=\"klp-win\">\r\n    <div class=\"klp-chrome\">\r\n      <span class=\"klp-dots\"><i><\/i><i><\/i><i><\/i><\/span>\r\n      <span class=\"klp-url\" id=\"klpUrl\">https:\/\/<\/span>\r\n      <a class=\"klp-btn klp-btn--go\" id=\"klpGo\" href=\"#\" target=\"_blank\" rel=\"noopener\">Open live \u2197<\/a>\r\n      <button class=\"klp-btn\" data-klp-close id=\"klpClose\" type=\"button\">Close<\/button>\r\n    <\/div>\r\n    <div class=\"klp-frame\">\r\n      <iframe id=\"klpFrame\" title=\"Live site preview\"><\/iframe>\r\n      <div class=\"klp-fallback\" id=\"klpFall\">\r\n        <img id=\"klpFallImg\" alt=\"\">\r\n        <p>This site refuses to load inside another page \u2014 that's a security header doing its job. Open it in a new tab instead.<\/p>\r\n        <a class=\"klp-btn klp-btn--go\" id=\"klpFallGo\" href=\"#\" target=\"_blank\" rel=\"noopener\">Open live site \u2197<\/a>\r\n      <\/div>\r\n    <\/div>\r\n  <\/div>\r\n<\/div>\r\n\r\n<style>\r\n.klp{\r\n  --bg:#05070C; --panel:#0A0F17; --panel2:#070B12; --fg:#E8EEF7; --soft:#7C8798;\r\n  --cyan:#4FC3FF; --amber:#FF9A2E; --line:rgba(79,195,255,.18);\r\n  --pad:clamp(20px,5vw,72px);\r\n  --mono:ui-monospace,'SF Mono',Consolas,monospace;\r\n  background:var(--bg);color:var(--fg);position:relative;\r\n}\r\n.klp *{box-sizing:border-box}\r\n.klp p,.klp h2,.klp h3{margin:0}\r\n.klp-sec{padding:clamp(70px,11vh,130px) var(--pad);position:relative}\r\n.klp-sec--line{border-top:1px solid var(--line)}\r\n.klp-eyebrow{font-family:var(--mono);font-size:11.5px;letter-spacing:.18em;text-transform:uppercase;color:var(--cyan)}\r\n.klp-h2{font-size:clamp(1.9rem,5vw,3.4rem);line-height:1;letter-spacing:-.035em;font-weight:700;color:var(--fg)}\r\n.klp-head{margin-bottom:clamp(36px,6vh,64px)}\r\n.klp-head .klp-eyebrow{margin-bottom:16px}\r\n.klp-p{color:var(--soft);font-size:.97rem;line-height:1.6}\r\n.klp-p + .klp-p{margin-top:14px !important}\r\n\r\n\/* ========== 1. word-by-word highlight ========== *\/\r\n.klp-words{height:420vh;position:relative}\r\n.klp-words-pin{position:sticky;top:0;height:100svh;display:flex;align-items:center;justify-content:center;\r\n  text-align:center;padding:0 clamp(24px,8vw,140px)}\r\n.klp-para{font-size:clamp(1.5rem,3.8vw,3rem);line-height:1.4;letter-spacing:-.02em;font-weight:600;max-width:20ch}\r\n\/* dim words are heavily blurred + very faint, so you can barely tell text is there *\/\r\n.klp-para .w{\r\n  color:rgba(232,238,247,.05);\r\n  filter:blur(9px);\r\n  transition:color .22s linear, filter .22s linear;\r\n  display:inline;\r\n}\r\n.klp-para .w.lit{color:var(--fg);filter:blur(0)}\r\n.klp-para .w.amber.lit{color:var(--amber)}\r\n\r\n\/* ========== 2. big horizontal stacking cards ========== *\/\r\n.klp-deck{position:relative}\r\n.klp-deck-pin{position:sticky;top:0;height:100svh;overflow:hidden}\r\n.klp-deck-label{position:absolute;top:clamp(22px,4.5vh,44px);left:var(--pad);z-index:100}\r\n.klp-stack{position:absolute;inset:0;display:flex;align-items:center;justify-content:center}\r\n\r\n.klp-card{\r\n  position:absolute;width:min(1040px,92vw);height:min(60vh,440px);cursor:pointer;\r\n  display:grid;grid-template-columns:1fr 1fr;overflow:hidden;\r\n  background:var(--panel);border:1px solid var(--line);border-radius:22px;\r\n  box-shadow:0 50px 110px -50px rgba(0,0,0,.95);will-change:transform;\r\n  text-align:left;font:inherit;color:inherit;padding:0;transition:border-color .4s;\r\n}\r\n.klp-card:hover{border-color:rgba(79,195,255,.5)}\r\n.klp-card-text{padding:clamp(24px,3.4vw,46px);display:flex;flex-direction:column;justify-content:center;gap:14px}\r\n.klp-card-kick{font-family:var(--mono);font-size:11px;letter-spacing:.14em;text-transform:uppercase;color:var(--cyan)}\r\n.klp-card-name{font-size:clamp(1.5rem,3vw,2.4rem);letter-spacing:-.03em;font-weight:700;line-height:1.02;color:var(--fg)}\r\n.klp-card-host{font-family:var(--mono);font-size:12px;color:var(--soft)}\r\n.klp-card-desc{color:var(--soft);font-size:clamp(.9rem,1.4vw,1rem);line-height:1.55;max-width:40ch}\r\n.klp-card-go{margin-top:6px;display:inline-flex;align-items:center;gap:8px;align-self:flex-start;\r\n  font-family:var(--mono);font-size:12px;color:#0B0703;background:var(--amber);\r\n  padding:9px 15px;border-radius:100px;font-weight:500;transition:gap .3s}\r\n.klp-card:hover .klp-card-go{gap:14px}\r\n.klp-card-media{position:relative;overflow:hidden;background:linear-gradient(135deg,#0B1220,#060A11 60%,#0A1826);border-left:1px solid var(--line)}\r\n.klp-card-media img{width:100%;height:100%;object-fit:cover;display:block;transition:transform .8s cubic-bezier(.2,.8,.2,1)}\r\n.klp-card:hover .klp-card-media img{transform:scale(1.05)}\r\n@media(max-width:760px){\r\n  .klp-card{grid-template-columns:1fr;height:min(66vh,540px)}\r\n  .klp-card-media{order:-1;border-left:0;border-bottom:1px solid var(--line);min-height:42%}\r\n  .klp-card-desc{display:none}\r\n}\r\n\r\n\/* ========== 3. layers ========== *\/\r\n.klp-layers{display:grid;gap:0}\r\n.klp-layer{display:grid;grid-template-columns:64px minmax(0,220px) minmax(0,1fr);gap:clamp(14px,3vw,44px);\r\n  align-items:start;padding:clamp(22px,3.4vh,34px) 0;border-top:1px solid var(--line);\r\n  position:relative;transition:padding-left .45s cubic-bezier(.2,.8,.2,1)}\r\n.klp-layer:last-child{border-bottom:1px solid var(--line)}\r\n.klp-layer::before{content:\"\";position:absolute;left:0;top:-1px;height:1px;width:0;background:var(--cyan);\r\n  box-shadow:0 0 12px var(--cyan);transition:width .6s cubic-bezier(.2,.8,.2,1)}\r\n.klp-layer:hover::before{width:100%}\r\n.klp-layer:hover{padding-left:12px}\r\n.klp-num{font-family:var(--mono);font-size:12px;color:var(--cyan);letter-spacing:.1em;padding-top:6px}\r\n.klp-layer h3{font-size:clamp(1.2rem,2.4vw,1.7rem);letter-spacing:-.02em;font-weight:600;color:var(--fg)}\r\n.klp-layer p{color:var(--soft);font-size:.95rem;line-height:1.6;max-width:56ch}\r\n@media(max-width:820px){.klp-layer{grid-template-columns:44px 1fr;gap:12px}.klp-layer p{grid-column:2}}\r\n\r\n\/* ========== 4. case ========== *\/\r\n.klp-case{display:grid;grid-template-columns:minmax(0,1.15fr) minmax(0,1fr);gap:clamp(24px,5vw,64px);\r\n  border:1px solid var(--line);border-left:2px solid var(--amber);border-radius:14px;padding:clamp(24px,4vw,44px);background:var(--panel)}\r\n@media(max-width:760px){.klp-case{grid-template-columns:1fr}}\r\n.klp-case-t{font-size:clamp(1.25rem,2.6vw,1.9rem);letter-spacing:-.025em;font-weight:600;margin-bottom:18px !important;color:var(--fg);line-height:1.15}\r\n.klp-log{display:flex;flex-direction:column;gap:8px;font-family:var(--mono);font-size:12px;color:var(--soft)}\r\n.klp-log b{color:var(--fg);font-weight:400}.klp-log i{color:var(--amber);font-style:normal}.klp-log u{color:var(--cyan);text-decoration:none}\r\n\r\n\/* ========== 5. contact ========== *\/\r\n.klp-cta{font-size:clamp(2.4rem,9vw,6.5rem);line-height:.94;letter-spacing:-.04em;font-weight:700;color:var(--fg)}\r\n.klp-cta em{font-style:normal;color:var(--amber)}\r\n.klp-mail{display:inline-block;margin-top:clamp(28px,5vh,52px);font-family:var(--mono);\r\n  font-size:clamp(.95rem,2vw,1.2rem);color:var(--cyan);text-decoration:none;padding-bottom:6px;\r\n  border-bottom:1px solid var(--line);transition:border-color .3s,color .3s}\r\n.klp-mail:hover{border-color:var(--cyan);color:var(--fg)}\r\n.klp-foot{display:flex;justify-content:space-between;gap:16px;flex-wrap:wrap;\r\n  margin-top:clamp(50px,9vh,100px);padding-top:20px;border-top:1px solid var(--line);\r\n  font-family:var(--mono);font-size:11.5px;color:var(--soft)}\r\n\r\n\/* ========== modal ========== *\/\r\n.klp-modal{position:fixed;inset:0;z-index:99999;display:none;align-items:center;justify-content:center;padding:clamp(10px,2.4vw,32px)}\r\n.klp-modal.is-open{display:flex}\r\n.klp-modal-bd{position:absolute;inset:0;background:rgba(3,5,9,.78);backdrop-filter:blur(8px);opacity:0;transition:opacity .4s}\r\n.klp-modal.is-show .klp-modal-bd{opacity:1}\r\n.klp-win{position:relative;width:min(1180px,100%);height:min(88svh,900px);background:#080C13;\r\n  border:1px solid rgba(79,195,255,.28);border-radius:14px;overflow:hidden;box-shadow:0 60px 140px -50px rgba(79,195,255,.35);\r\n  opacity:0;transform:perspective(1600px) rotateY(-13deg) scale(.88) translateY(28px);\r\n  transition:opacity .5s cubic-bezier(.2,.8,.2,1),transform .6s cubic-bezier(.2,.8,.2,1)}\r\n.klp-modal.is-show .klp-win{opacity:1;transform:perspective(1600px) rotateY(0) scale(1) translateY(0)}\r\n.klp-chrome{display:flex;align-items:center;gap:12px;padding:11px 13px;border-bottom:1px solid rgba(79,195,255,.18);background:#05070C}\r\n.klp-dots{display:flex;gap:6px}.klp-dots i{width:9px;height:9px;border-radius:50%;background:rgba(124,135,152,.45)}\r\n.klp-url{flex:1;font-family:ui-monospace,Consolas,monospace;font-size:12px;color:#7C8798;background:#080C13;\r\n  border:1px solid rgba(79,195,255,.18);border-radius:100px;padding:6px 14px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\r\n.klp-btn{font-family:ui-monospace,Consolas,monospace;font-size:11.5px;padding:8px 13px;border-radius:100px;\r\n  border:1px solid rgba(79,195,255,.28);background:transparent;color:#E8EEF7;cursor:pointer;text-decoration:none;white-space:nowrap;\r\n  transition:background .25s,color .25s,border-color .25s}\r\n.klp-btn:hover{background:#E8EEF7;color:#05070C;border-color:#E8EEF7}\r\n.klp-btn--go{background:#FF9A2E;color:#0B0703;border-color:#FF9A2E}\r\n.klp-btn--go:hover{background:#E8EEF7;border-color:#E8EEF7;color:#05070C}\r\n.klp-frame{position:relative;width:100%;height:calc(100% - 51px);background:#080C13}\r\n.klp-frame iframe{width:100%;height:100%;border:0;display:block;background:#fff}\r\n.klp-fallback{position:absolute;inset:0;display:none;flex-direction:column;align-items:center;justify-content:center;gap:18px;text-align:center;padding:30px;background:#080C13}\r\n.klp-fallback.is-on{display:flex}\r\n.klp-fallback p{color:#7C8798;max-width:44ch;font-size:.93rem;line-height:1.6}\r\n.klp-fallback img{width:min(520px,84%);border:1px solid rgba(79,195,255,.18);border-radius:10px}\r\n\r\n\/* ========== rise-in ========== *\/\r\n.klp-rise{opacity:0;transform:translateY(46px);transition:opacity .7s cubic-bezier(.2,.8,.2,1),transform .7s cubic-bezier(.2,.8,.2,1)}\r\n.klp-rise.is-in{opacity:1;transform:none}\r\n\r\n@media (prefers-reduced-motion: reduce){\r\n  .klp-words{height:auto}.klp-words-pin{position:relative;height:auto;padding:80px var(--pad)}\r\n  .klp-para .w{color:var(--fg);filter:none}.klp-para .w.amber{color:var(--amber)}\r\n  .klp-deck{height:auto !important}.klp-deck-pin{position:relative;height:auto;padding:60px 0}\r\n  .klp-stack{position:relative;flex-direction:column;gap:24px}\r\n  .klp-card{position:relative !important;transform:none !important;width:92vw;height:auto;grid-template-columns:1fr}\r\n  .klp-rise{opacity:1;transform:none;transition:none}\r\n  .klp-win{transition:opacity .2s;transform:none}.klp-modal.is-show .klp-win{transform:none}\r\n}\r\n<\/style>\r\n\r\n<script src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/gsap\/3.12.5\/gsap.min.js\"><\/script>\r\n<script src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/gsap\/3.12.5\/ScrollTrigger.min.js\"><\/script>\r\n<script>\r\n(function(){\r\n'use strict';\r\n\r\nvar SHOTS = 'https:\/\/test.kdlink.dev\/wp-content\/uploads\/kl-hero\/shots\/';\r\n\r\nvar SITES = [\r\n  {name:'Lace & Luxe', url:'https:\/\/laceandluxe.ae', img:'laceandluxe.jpg', year:'2026', kick:'E-commerce \u00b7 lingerie',\r\n   desc:'A three-plugin suite \u2014 slider, product page, shop grid. Cart load time cut from thirty seconds to under two.'},\r\n  {name:'Black Pearl', url:'https:\/\/blackpearldxb.com', img:'blackpearl.jpg', year:'2025', kick:'E-commerce \u00b7 jewellery',\r\n   desc:'A charm builder that renders the final design server-side, plus a multi-step checkout and a currency switcher built from scratch.'},\r\n  {name:'ThatShop', url:'https:\/\/thatshop.ae', img:'thatshop.jpg', year:'2025', kick:'E-commerce \u00b7 custom print',\r\n   desc:'A multi-side product designer that generates the production print file at checkout and restores failed carts.'},\r\n  {name:'7 Lines Luxury Cars', url:'https:\/\/7linesluxurycars.com', img:'7lines.jpg', year:'2026', kick:'Security \u00b7 malware cleanup',\r\n   desc:'Hidden plugins, a redirect backdoor and a compromised administrator \u2014 all found, removed and hardened.'},\r\n  {name:'bioadd-tech', url:'https:\/\/bioadd-tech.com', img:'bioadd.jpg', year:'2026', kick:'Security \u00b7 email compromise',\r\n   desc:'Responded to a business email compromise \u2014 a lookalike domain, hidden forwarders and an altered admin email, all shut down.'},\r\n  {name:'AIS Global Consulting', url:'https:\/\/aisglobalconsulting.com', img:'ais.jpg', year:'2025', kick:'Website \u00b7 corporate',\r\n   desc:'Corporate consulting site with professional email set up in Outlook and Thunderbird for the whole team.'},\r\n  {name:'Alfaleh Group', url:'http:\/\/alfalehgroup.ae', img:'alfaleh.jpg', year:'2025', kick:'Website \u00b7 corporate',\r\n   desc:'Company website and hosting for a UAE group, built and handed over with mailboxes configured across devices.'},\r\n  {name:'Kasiyasky', url:'https:\/\/kasiyasky.com', img:'kasiyasky.jpg', year:'2025', kick:'Website \u00b7 real estate',\r\n   desc:'Real-estate listings on a WooCommerce archive, migrated to our own hosting with DNS moved across cleanly.'}\r\n];\r\n\r\nvar reduce = window.matchMedia('(prefers-reduced-motion: reduce)').matches;\r\n\r\n\/* ---------------- 1. wrap paragraph words ---------------- *\/\r\n(function wrapWords(){\r\n  var para = document.getElementById('klpPara');\r\n  var amberSet = {clean:1, the:0, malware:1};   \/\/ words to tint amber when lit\r\n  var text = para.textContent.replace(\/\\s+\/g,' ').trim();\r\n  para.innerHTML = text.split(' ').map(function(w){\r\n    var key = w.toLowerCase().replace(\/[^a-z]\/g,'');\r\n    var amber = (key==='clean' || key==='malware');\r\n    return '<span class=\"w' + (amber ? ' amber' : '') + '\">' + w + '<\/span>';\r\n  }).join(' ');\r\n})();\r\n\r\n\/* ---------------- 2. build cards ---------------- *\/\r\nvar stack = document.getElementById('klpStack');\r\nvar HEAD_PEEK = 26;\r\n\r\nSITES.forEach(function(s, i){\r\n  var c = document.createElement('button');\r\n  c.type = 'button';\r\n  c.className = 'klp-card';\r\n  c.style.zIndex = (i + 1);\r\n  c.setAttribute('aria-label', 'Preview ' + s.name);\r\n  c.innerHTML =\r\n    '<span class=\"klp-card-text\">' +\r\n      '<span class=\"klp-card-kick\">' + s.kick + '<\/span>' +\r\n      '<span class=\"klp-card-name\">' + s.name + '<\/span>' +\r\n      '<span class=\"klp-card-host\">' + s.url.replace(\/^https?:\\\/\\\/\/,'') + '<\/span>' +\r\n      '<span class=\"klp-card-desc\">' + s.desc + '<\/span>' +\r\n      '<span class=\"klp-card-go\">Open preview \u2192<\/span>' +\r\n    '<\/span>' +\r\n    '<span class=\"klp-card-media\"><img decoding=\"async\" src=\"' + SHOTS + s.img + '\" alt=\"' + s.name + ' homepage\" loading=\"lazy\" onerror=\"this.style.display=\\'none\\'\"><\/span>';\r\n  c.addEventListener('click', function(){ openSite(i); });\r\n  stack.appendChild(c);\r\n});\r\nvar cards = Array.prototype.slice.call(stack.querySelectorAll('.klp-card'));\r\n\r\n\/* ---------------- GSAP build ---------------- *\/\r\nfunction build(){\r\n  if(reduce) return;\r\n  gsap.registerPlugin(ScrollTrigger);\r\n\r\n  \/* word-by-word highlight *\/\r\n  var words = gsap.utils.toArray('#klpPara .w');\r\n  ScrollTrigger.create({\r\n    trigger:'#klpWords', start:'top top', end:'bottom bottom', scrub:0.3,\r\n    onUpdate:function(self){\r\n      var lit = Math.round(self.progress * words.length);\r\n      for(var i=0;i<words.length;i++){\r\n        if(i < lit) words[i].classList.add('lit');\r\n        else words[i].classList.remove('lit');\r\n      }\r\n    }\r\n  });\r\n\r\n  \/* stacking cards *\/\r\n  cards.forEach(function(card, i){ gsap.set(card, { y: i * HEAD_PEEK }); });\r\n\r\n  var deck = document.getElementById('klpDeck');\r\n  deck.style.height = (cards.length * 80 + 40) + 'vh';\r\n\r\n  var tl = gsap.timeline({ scrollTrigger:{ trigger:'#klpDeck', start:'top top', end:'bottom bottom', scrub:0.6 } });\r\n  cards.forEach(function(card, i){\r\n    if(i === 0) return;\r\n    gsap.set(card, { yPercent: 115, y: i * HEAD_PEEK });\r\n    tl.to(card, { yPercent: 0, duration: 1, ease:'power2.out' }, (i - 1));\r\n  });\r\n\r\n  ScrollTrigger.refresh();\r\n}\r\n\r\n\/* wait until GSAP + ScrollTrigger are actually available (Elemento timing safe) *\/\r\nfunction bootWhenReady(){\r\n  if(typeof gsap === 'undefined' || typeof ScrollTrigger === 'undefined'){\r\n    return setTimeout(bootWhenReady, 120);\r\n  }\r\n  build();\r\n}\r\nbootWhenReady();\r\n\r\n\/* ---------------- reveal for plain sections ---------------- *\/\r\nvar io = new IntersectionObserver(function(entries){\r\n  entries.forEach(function(en){ if(en.isIntersecting){ en.target.classList.add('is-in'); io.unobserve(en.target); } });\r\n}, {threshold:.14, rootMargin:'0px 0px -8% 0px'});\r\ndocument.querySelectorAll('.klp-rise').forEach(function(n){ io.observe(n); });\r\ndocument.querySelectorAll('.klp-layer.klp-rise').forEach(function(n, i){ n.style.transitionDelay = (i * 80) + 'ms'; });\r\n\r\n\/* ---------------- modal ---------------- *\/\r\nvar modal = document.getElementById('klpModal'), frame = document.getElementById('klpFrame'),\r\n    urlEl = document.getElementById('klpUrl'), goEl = document.getElementById('klpGo'),\r\n    fall = document.getElementById('klpFall'), fImg = document.getElementById('klpFallImg'),\r\n    fGo = document.getElementById('klpFallGo'), closeBtn = document.getElementById('klpClose'),\r\n    lastFocus = null, timer = null;\r\n\r\nfunction openSite(i){\r\n  var s = SITES[i];\r\n  lastFocus = document.activeElement;\r\n  urlEl.textContent = s.url; goEl.href = s.url; fGo.href = s.url;\r\n  fImg.src = SHOTS + s.img; fImg.alt = s.name + ' homepage';\r\n  fall.classList.remove('is-on');\r\n  frame.src = s.url;\r\n  modal.classList.add('is-open');\r\n  document.documentElement.style.overflow = 'hidden';\r\n  requestAnimationFrame(function(){ modal.classList.add('is-show'); });\r\n  closeBtn.focus();\r\n  clearTimeout(timer);\r\n  timer = setTimeout(function(){ fall.classList.add('is-on'); }, 4500);\r\n  frame.onload = function(){ clearTimeout(timer); };\r\n}\r\nfunction closeSite(){\r\n  modal.classList.remove('is-show');\r\n  document.documentElement.style.overflow = '';\r\n  clearTimeout(timer);\r\n  setTimeout(function(){ modal.classList.remove('is-open'); frame.src = 'about:blank'; }, 420);\r\n  if(lastFocus) lastFocus.focus();\r\n}\r\nmodal.addEventListener('click', function(e){ if(e.target.hasAttribute('data-klp-close')) closeSite(); });\r\ndocument.addEventListener('keydown', function(e){ if(e.key === 'Escape' && modal.classList.contains('is-open')) closeSite(); });\r\n\r\n})();\r\n<\/script>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>WordPress &amp; WooCommerce engineer \u2014 Dubai Stores that ship, not just launch. Custom plugins, payment gateways, hosting and security for e-commerce brands across the UAE. Scroll I don&#8217;t just launch stores. I write the plugins underneath them, wire the payment gateways, run the servers they live on, set up the email that actually lands in [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"elementor_canvas","meta":{"footnotes":""},"class_list":["post-7","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/test.kdlink.dev\/index.php?rest_route=\/wp\/v2\/pages\/7","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/test.kdlink.dev\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/test.kdlink.dev\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/test.kdlink.dev\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/test.kdlink.dev\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=7"}],"version-history":[{"count":31,"href":"https:\/\/test.kdlink.dev\/index.php?rest_route=\/wp\/v2\/pages\/7\/revisions"}],"predecessor-version":[{"id":50,"href":"https:\/\/test.kdlink.dev\/index.php?rest_route=\/wp\/v2\/pages\/7\/revisions\/50"}],"wp:attachment":[{"href":"https:\/\/test.kdlink.dev\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=7"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}