File: /var/www/e-tdr.com/e-tdr/wp-content/themes/e-tdr/single.php
<?php get_header(); ?>
<?php while (have_posts()) : the_post(); ?>
<?php
/* ── Post meta ── */
$post_id = get_the_ID();
$post_title = get_the_title();
$post_url = get_permalink();
$post_date = get_the_date('j F Y');
$post_content = get_the_content();
$categories = get_the_category();
$tags = get_the_tags();
/* Category label & colour */
$cat_name = ! empty($categories) ? $categories[0]->name : '';
$cat_link = ! empty($categories) ? get_category_link($categories[0]->term_id) : '#';
/* Reading time estimate (200 wpm) */
$word_count = str_word_count(wp_strip_all_tags($post_content));
$reading_time = max(1, (int) ceil($word_count / 200));
/* Social share URLs */
$encoded_title = rawurlencode($post_title);
$encoded_url = rawurlencode($post_url);
$twitter_url = 'https://twitter.com/intent/tweet?text=' . $encoded_title . '&url=' . $encoded_url;
$linkedin_url = 'https://www.linkedin.com/sharing/share-offsite/?url=' . $encoded_url;
$whatsapp_url = 'https://api.whatsapp.com/send?text=' . $encoded_title . '+' . $encoded_url;
/* Related posts — same category, exclude current */
$related_args = array(
'post_type' => 'post',
'posts_per_page' => 3,
'post_status' => 'publish',
'post__not_in' => array($post_id),
'orderby' => 'rand',
);
if (! empty($categories)) {
$related_args['category__in'] = wp_list_pluck($categories, 'term_id');
}
$related_query = new WP_Query($related_args);
/* RI colour classes cycle */
$ri_classes = array('ri-1', 'ri-2', 'ri-3');
/* Breadcrumb — blog archive URL */
$blog_page_id = get_option('page_for_posts') ?: 157;
$blog_page_url = $blog_page_id ? get_permalink($blog_page_id) : home_url('/');
$blog_page_label = $blog_page_id ? get_the_title($blog_page_id) : 'Insights';
?>
<div class="breadcrumb-bar">
<div class="container">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="<?php echo esc_url(home_url('/')); ?>">Home</a></li>
<li class="breadcrumb-item"><a href="<?php echo esc_url($blog_page_url); ?>"><?php echo esc_html($blog_page_label); ?></a></li>
<li class="breadcrumb-item active"><?php echo esc_html($post_title); ?></li>
</ol>
</div>
</div>
<section class="blog-hero">
<div class="container">
<div class="blog-hero-content">
<?php if ($cat_name) : ?>
<a href="<?php echo esc_url($cat_link); ?>" class="blog-cat-tag" style="background:#0A3161; border:1px solid rgba(255,255,255,0.25); text-decoration:none;">
<i class="bi bi-tag-fill"></i> <?php echo esc_html($cat_name); ?>
</a>
<?php endif; ?>
<h1><?php the_title(); ?></h1>
<div class="blog-meta-row">
<div class="meta-pill"><i class="bi bi-calendar3"></i> <?php echo esc_html($post_date); ?></div>
<div class="meta-pill reading"><i class="bi bi-clock-fill"></i> <?php echo esc_html($reading_time); ?> min read</div>
</div>
</div><!-- /blog-hero-content -->
<!-- Feature image -->
<div class="blog-feature-wrap">
<?php if (has_post_thumbnail()) : ?>
<div class="blog-feature-img" style="background:none; height:auto;">
<?php the_post_thumbnail('full', array('style' => 'width:100%;height:100%;object-fit:cover;display:block;')); ?>
</div>
<?php endif; ?>
</div>
</div>
</section>
<div class="container">
<div class="blog-layout">
<article class="blog-article" id="blog-article">
<div class="prose">
<?php the_content(); ?>
<?php if ($tags) : ?>
<div class="article-tags">
<span class="tags-label">Tags:</span>
<?php foreach ($tags as $tag) : ?>
<a href="<?php echo esc_url(get_tag_link($tag->term_id)); ?>" class="tag-pill">
<?php echo esc_html($tag->name); ?>
</a>
<?php endforeach; ?>
</div>
<?php endif; ?>
</div>
</article>
<aside class="blog-sidebar">
<div class="s-card" id="progress-card">
<div class="s-card-head">
<i class="bi bi-bar-chart-fill"></i>
<h6>Reading Progress</h6>
</div>
<div class="s-card-body">
<div class="prog-row">
<span>Progress</span>
<span id="prog-pct">0%</span>
</div>
<div class="prog-track">
<div class="prog-fill" id="prog-bar"></div>
</div>
</div>
</div>
<div class="s-card" id="toc-card">
<div class="s-card-head">
<i class="bi bi-list-ul"></i>
<h6>Table of Contents</h6>
</div>
<div class="s-card-body" style="padding:0.45rem 0.55rem;">
<button class="toc-mobile-toggle" id="toc-toggle" onclick="toggleTOC()">
<span><i class="bi bi-list-ul"></i> Contents</span>
<i class="bi bi-chevron-down chevron"></i>
</button>
<ul class="toc-list toc-collapsible" id="toc-collapsible"></ul>
</div>
</div>
<div class="s-card">
<div class="s-card-head">
<i class="bi bi-share-fill"></i>
<h6>Share This Article</h6>
</div>
<div class="s-card-body">
<div class="share-grid">
<a class="sh-btn sh-twitter"
href="<?php echo esc_url($twitter_url); ?>"
target="_blank" rel="noopener">
<i class="bi bi-twitter-x"></i> Twitter
</a>
<a class="sh-btn sh-linkedin"
href="<?php echo esc_url($linkedin_url); ?>"
target="_blank" rel="noopener">
<i class="bi bi-linkedin"></i> LinkedIn
</a>
<a class="sh-btn sh-whatsapp"
href="<?php echo esc_url($whatsapp_url); ?>"
target="_blank" rel="noopener">
<i class="bi bi-whatsapp"></i> WhatsApp
</a>
<button class="sh-btn sh-copy" id="copy-btn" onclick="copyLink()">
<i class="bi bi-link-45deg"></i> Copy Link
</button>
</div>
</div>
</div>
<!-- Contact CTA -->
<div class="s-card" style="margin-top: 1.5rem; text-align: center; border: 1px solid var(--border);">
<div class="s-card-body" style="padding: 1.5rem 1.2rem;">
<h6 style="font-size: 1.05rem; font-weight: 800; color: var(--text); margin-bottom: 0.6rem;">Questions about eTDR?</h6>
<p style="font-size: 0.85rem; color: var(--muted); margin-bottom: 1.2rem; line-height: 1.5;">Get in touch with our experts to learn more about digital development rights.</p>
<a href="#" class="btn-nav-demo js-contact-modal" style="width: 100%; justify-content: center; background: var(--orange);">
<i class="bi bi-envelope"></i> Contact Us
</a>
</div>
</div>
</aside>
</div>
<?php if ($related_query->have_posts()) : ?>
<div class="related-section">
<h4>Related Articles</h4>
<div class="row g-4">
<?php
$ri_idx = 0;
while ($related_query->have_posts()) : $related_query->the_post();
$rel_cats = get_the_category();
$rel_cat = ! empty($rel_cats) ? $rel_cats[0]->name : '';
$ri_class = $ri_classes[$ri_idx % 3];
$ri_idx++;
?>
<div class="col-md-4">
<a href="<?php the_permalink(); ?>" class="rel-card">
<?php if (has_post_thumbnail()) : ?>
<div class="rel-img <?php echo esc_attr($ri_class); ?>" style="overflow:hidden; height:auto; aspect-ratio: 16/9;">
<?php the_post_thumbnail('full', array('style' => 'width:100%;height:100%;object-fit:cover;')); ?>
</div>
<?php else : ?>
<div class="rel-img <?php echo esc_attr($ri_class); ?>">
<i class="bi bi-file-earmark-text"></i>
</div>
<?php endif; ?>
<div class="rel-body">
<?php if ($rel_cat) : ?>
<span class="rel-tag"><?php echo esc_html($rel_cat); ?></span>
<?php endif; ?>
<h5><?php the_title(); ?></h5>
<div class="rel-meta">
<i class="bi bi-calendar3"></i> <?php echo get_the_date('d M Y'); ?>
</div>
</div>
</a>
</div>
<?php endwhile;
wp_reset_postdata(); ?>
</div>
</div>
<?php endif; ?>
</div>
<script>
(function() {
/* ── Build Table of Contents from prose h2 tags ── */
function buildTOC() {
const prose = document.querySelector('.prose');
const tocList = document.getElementById('toc-collapsible');
const tocCard = document.getElementById('toc-card');
if (!prose || !tocList) return;
const headings = prose.querySelectorAll('h2');
if (!headings.length) {
if (tocCard) tocCard.style.display = 'none';
return;
}
headings.forEach(function(h, idx) {
/* Ensure every h2 has an id for anchor linking */
if (!h.id) {
h.id = 'toc-section-' + (idx + 1);
}
const num = String(idx + 1).padStart(2, '0');
const li = document.createElement('li');
const link = document.createElement('a');
link.href = '#' + h.id;
link.className = 'toc-link';
link.dataset.target = h.id;
link.innerHTML = '<span class="toc-n">' + num + '</span>' + h.textContent;
li.appendChild(link);
tocList.appendChild(li);
});
/* Re-attach close-on-click for mobile after building */
tocList.querySelectorAll('.toc-link').forEach(function(link) {
link.addEventListener('click', function() {
if (window.innerWidth < 992) {
const btn = document.getElementById('toc-toggle');
if (btn) btn.classList.remove('open');
tocList.classList.remove('open');
}
});
});
}
/* ── Reading progress ── */
function initProgress() {
const article = document.getElementById('blog-article');
const bar = document.getElementById('prog-bar');
const pct = document.getElementById('prog-pct');
if (!article || !bar || !pct) return;
function updateProgress() {
const total = article.offsetHeight - window.innerHeight;
const scrolled = Math.max(0, -article.getBoundingClientRect().top);
const p = Math.min(100, Math.round((scrolled / Math.max(total, 1)) * 100));
bar.style.width = p + '%';
pct.textContent = p + '%';
}
window.addEventListener('scroll', updateProgress, {
passive: true
});
updateProgress();
}
/* ── Active TOC link on scroll ── */
function initTOCScroll() {
function updateTOC() {
const headings = document.querySelectorAll('.prose h2[id]');
const tocLinks = document.querySelectorAll('.toc-link');
let active = null;
headings.forEach(function(h) {
if (h.getBoundingClientRect().top <= 110) active = h.id;
});
tocLinks.forEach(function(link) {
link.classList.toggle('active', link.dataset.target === active);
});
}
window.addEventListener('scroll', updateTOC, {
passive: true
});
}
/* ── Run ── */
buildTOC();
initProgress();
initTOCScroll();
})();
/* ── Mobile TOC toggle ── */
function toggleTOC() {
const btn = document.getElementById('toc-toggle');
const body = document.getElementById('toc-collapsible');
if (btn) btn.classList.toggle('open');
if (body) body.classList.toggle('open');
}
/* ── Copy link ── */
function copyLink() {
const btn = document.getElementById('copy-btn');
if (!btn) return;
navigator.clipboard.writeText(window.location.href).then(function() {
btn.classList.add('copied');
btn.innerHTML = '<i class="bi bi-check2"></i> Copied!';
setTimeout(function() {
btn.classList.remove('copied');
btn.innerHTML = '<i class="bi bi-link-45deg"></i> Copy Link';
}, 2200);
});
}
</script>
<?php endwhile; ?>
<?php get_footer(); ?>