fix blog page

This commit is contained in:
2026-06-08 16:20:39 +05:30
parent a16d51f2fa
commit 8862ad2cb3
18 changed files with 2985 additions and 670 deletions

View File

@@ -0,0 +1,276 @@
import React from "react";
import Link from "next/link";
import Image from "next/image";
import { ScrollReveal } from "@/animations/Reveal";
import { getAdjacentPosts, getRelatedPosts } from "@/data/blog";
export default function BlogPostFooter({ slug }: { slug: string }) {
const { prev, next } = getAdjacentPosts(slug);
const related = getRelatedPosts(slug, 3);
return (
<section className="dm-blog-footer" aria-label="More articles">
<style dangerouslySetInnerHTML={{ __html: STYLES }} />
<div className="dm-blog-footer-inner">
{/* Previous / Next */}
{(prev || next) && (
<nav className="dm-prevnext" aria-label="Article navigation">
{prev ? (
<Link href={`/blog/${prev.slug}`} className="dm-prevnext-card dm-prevnext-prev">
<span className="dm-prevnext-thumb">
<Image src={prev.image} alt={prev.title} fill sizes="80px" style={{ objectFit: "cover" }} />
</span>
<span className="dm-prevnext-text">
<span className="dm-prevnext-label">
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
<line x1="19" y1="12" x2="5" y2="12" /><polyline points="12 19 5 12 12 5" />
</svg>
Previous
</span>
<span className="dm-prevnext-cat">{prev.category}</span>
<span className="dm-prevnext-title">{prev.title}</span>
</span>
</Link>
) : (
<span className="dm-prevnext-placeholder" />
)}
{next ? (
<Link href={`/blog/${next.slug}`} className="dm-prevnext-card dm-prevnext-next">
<span className="dm-prevnext-text">
<span className="dm-prevnext-label">
Next
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
<line x1="5" y1="12" x2="19" y2="12" /><polyline points="12 5 19 12 12 19" />
</svg>
</span>
<span className="dm-prevnext-cat">{next.category}</span>
<span className="dm-prevnext-title">{next.title}</span>
</span>
<span className="dm-prevnext-thumb">
<Image src={next.image} alt={next.title} fill sizes="80px" style={{ objectFit: "cover" }} />
</span>
</Link>
) : (
<span className="dm-prevnext-placeholder" />
)}
</nav>
)}
{/* Related Articles */}
{related.length > 0 && (
<div className="dm-related">
<h2 className="dm-related-heading">Related Articles</h2>
<div className="dm-related-grid">
{related.map((post, i) => (
<ScrollReveal key={post.slug} delay={i * 0.08} duration={0.7} yOffset={30}>
<Link href={`/blog/${post.slug}`} className="dm-related-card">
<div className="dm-related-img">
<Image
src={post.image}
alt={post.title}
fill
sizes="(max-width: 700px) 100vw, (max-width: 1024px) 50vw, 33vw"
style={{ objectFit: "cover" }}
/>
<span className="dm-related-badge">{post.category}</span>
</div>
<div className="dm-related-body">
<h3 className="dm-related-card-title">{post.title}</h3>
<p className="dm-related-card-excerpt">{post.excerpt}</p>
<span className="dm-related-readmore">
Read More
<svg className="dm-related-readmore-arrow" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
<line x1="5" y1="12" x2="19" y2="12" /><polyline points="12 5 19 12 12 19" />
</svg>
</span>
</div>
</Link>
</ScrollReveal>
))}
</div>
</div>
)}
{/* Contact CTA banner */}
<div className="dm-blog-contact-cta">
<div className="dm-blog-contact-cta-content">
<span className="dm-blog-contact-eyebrow">Let&apos;s talk logistics</span>
<h2 className="dm-blog-contact-title">
Ready to move smarter with Doormile?
</h2>
<p className="dm-blog-contact-sub">
Tell us about your fleet and routes we&apos;ll show you where the
distance, vehicles and emissions are hiding.
</p>
</div>
<Link href="/contact" className="dm-blog-contact-btn">
Get in Touch
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
<line x1="5" y1="12" x2="19" y2="12" /><polyline points="12 5 19 12 12 19" />
</svg>
</Link>
</div>
</div>
</section>
);
}
const STYLES = `
.dm-blog-footer {
font-family: var(--font-manrope), sans-serif; --dm-red: #c01227; --dm-red-hover: #e31d32;
/* The global theme applies 72px top/bottom section padding — strip it so the
inner container is the single source of vertical rhythm (no double gap). */
padding: 0 !important;
}
/* Neutralize the global theme's 120/80/60px UPPERCASE heading rules */
.dm-blog-footer :where(h1, h2, h3, h4, h5, h6) {
font-family: var(--font-manrope), sans-serif !important;
text-transform: none !important;
font-style: normal !important;
font-weight: 800;
}
/* Neutralize the theme's .elementor-kit-5 a (red color + underline) */
.dm-blog-footer a { text-decoration: none !important; }
/* Shared content container — mirrors SingleBlog's .dm-blog-wrap (same 1280px
max-width + 20→40px horizontal padding) so Prev/Next, Related and the CTA
align to the exact same left/right edges as the article body above.
Vertical rhythm: ~64px from the article end to the Prev/Next divider, then a
consistent ~6472px section→section gap (no 120px+ voids). */
.dm-blog-footer-inner {
max-width: 1280px; margin: 0 auto;
/* Compact vertical rhythm on an 8px system. Top padding sets the
article→Prev/Next gap (~2432px); the inter-section gap sets the
Prev/Next→Related gap (~3248px). No large arbitrary voids. */
/* Minimal bottom padding — the global site footer already contributes its
own 20px top inset, so the CTA banner sits close to it without a void. */
padding: clamp(24px, 3vw, 32px) clamp(20px, 4vw, 40px) clamp(8px, 1.5vw, 16px);
display: flex; flex-direction: column; gap: clamp(32px, 4vw, 48px);
}
/* Prev / Next */
.dm-prevnext {
display: grid; grid-template-columns: 1fr 1fr; gap: 20px;
/* Halved from 40px: tight divider→cards spacing without crowding. */
padding-top: clamp(16px, 2vw, 24px); border-top: 1px solid rgba(15,23,42,0.08);
}
@media (max-width: 640px) { .dm-prevnext { grid-template-columns: 1fr; } }
.dm-prevnext-placeholder { display: block; }
.dm-prevnext-card {
display: flex; gap: 16px; align-items: center; padding: 16px;
background: #fff; border: 1px solid rgba(15,23,42,0.09); border-radius: 22px;
text-decoration: none; transition: transform .3s ease, box-shadow .3s ease, border-color .3s ease;
}
.dm-prevnext-card:hover {
transform: translateY(-4px); border-color: rgba(192,18,39,0.2);
box-shadow: 0 16px 34px rgba(192,18,39,0.10);
}
.dm-prevnext-thumb {
position: relative; flex: 0 0 80px; width: 80px; height: 80px;
border-radius: 16px; overflow: hidden; background: #f1f5f9;
}
.dm-prevnext-text { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.dm-prevnext-next { text-align: right; }
.dm-prevnext-next .dm-prevnext-text { align-items: flex-end; }
.dm-prevnext-label {
display: inline-flex; align-items: center; gap: 6px;
font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: 1px; color: var(--dm-red);
}
.dm-prevnext-cat { font-size: 11px; font-weight: 700; color: #94a3b8; text-transform: uppercase; letter-spacing: .5px; }
.dm-prevnext-title {
font-size: 15.5px; font-weight: 700; color: #1e293b; line-height: 1.4;
display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
transition: color .2s ease;
}
.dm-prevnext-card:hover .dm-prevnext-title { color: var(--dm-red); }
/* Related */
.dm-related-heading {
font-size: clamp(22px, 2.2vw, 28px) !important; font-weight: 850 !important; letter-spacing: -.4px !important;
line-height: 1.25 !important; color: #0f172a !important; margin: 0 0 24px;
}
.dm-related-grid {
display: grid; grid-template-columns: repeat(3, 1fr); gap: 28px;
}
@media (max-width: 1024px) { .dm-related-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 700px) { .dm-related-grid { grid-template-columns: 1fr; gap: 24px; } }
.dm-related-card {
display: flex; flex-direction: column; height: 100%;
background: #fff; border: 1px solid rgba(15,23,42,0.09); border-radius: 22px;
overflow: hidden; box-shadow: 0 4px 24px rgba(15,23,42,0.05); text-decoration: none;
transition: transform .4s cubic-bezier(0.2,0.8,0.2,1), box-shadow .4s ease, border-color .4s ease;
}
.dm-related-card:hover {
transform: translateY(-8px); box-shadow: 0 22px 44px rgba(192,18,39,0.13);
border-color: rgba(192,18,39,0.2);
}
.dm-related-img {
position: relative; width: 100%; aspect-ratio: 16 / 10; overflow: hidden; background: #f1f5f9;
}
.dm-related-img img { transition: transform .5s cubic-bezier(0.2,0.8,0.2,1); }
.dm-related-card:hover .dm-related-img img { transform: scale(1.05); }
.dm-related-badge {
position: absolute; top: 14px; left: 14px; z-index: 5; background: var(--dm-red); color: #fff;
font-size: 9px; font-weight: 800; text-transform: uppercase; letter-spacing: 1.2px;
padding: 5px 11px; border-radius: 8px; box-shadow: 0 4px 12px rgba(192,18,39,0.25);
}
.dm-related-body { display: flex; flex-direction: column; flex: 1; padding: 22px; }
.dm-related-card-title {
font-size: 17px !important; font-weight: 800 !important; color: #1e293b !important; line-height: 1.4 !important;
letter-spacing: -.2px !important; margin: 0 0 10px;
display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
transition: color .2s ease;
}
.dm-related-card:hover .dm-related-card-title { color: var(--dm-red); }
.dm-related-card-excerpt {
font-size: 13.5px; font-weight: 500; color: #64748b; line-height: 1.6; margin: 0 0 18px;
display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.dm-related-readmore {
margin-top: auto; display: inline-flex; align-items: center; gap: 7px;
font-size: 12.5px; font-weight: 800; color: var(--dm-red);
text-transform: uppercase; letter-spacing: .6px;
}
.dm-related-readmore-arrow { transition: transform .3s cubic-bezier(0.2,0.8,0.2,1); }
.dm-related-card:hover .dm-related-readmore-arrow { transform: translateX(5px); }
/* Contact CTA banner */
.dm-blog-contact-cta {
display: flex; align-items: center; justify-content: space-between; gap: 32px;
flex-wrap: wrap;
background: linear-gradient(135deg, #1a1a1a 0%, #2d1417 100%);
border-radius: 30px; padding: clamp(32px, 4vw, 56px);
position: relative; overflow: hidden;
}
.dm-blog-contact-cta::after {
content: ""; position: absolute; right: -80px; top: -80px; width: 300px; height: 300px;
background: radial-gradient(circle, rgba(192,18,39,0.40), transparent 70%);
pointer-events: none;
}
.dm-blog-contact-cta-content { position: relative; z-index: 1; max-width: 640px; }
.dm-blog-contact-eyebrow {
display: inline-block; font-size: 12px; font-weight: 800; text-transform: uppercase;
letter-spacing: 1.4px; color: #ff8088; margin-bottom: 14px;
}
.dm-blog-contact-title {
font-size: clamp(22px, 2.2vw, 28px) !important; font-weight: 800 !important; line-height: 1.25 !important;
letter-spacing: -.3px !important; color: #ffffff !important; margin: 0 0 12px; text-wrap: balance;
}
.dm-blog-contact-sub {
font-size: 15.5px; line-height: 1.65; color: #e2e2e2; margin: 0; font-weight: 450;
}
.dm-blog-contact-btn {
position: relative; z-index: 1; flex-shrink: 0;
display: inline-flex; align-items: center; justify-content: center; gap: 10px;
background: var(--dm-red); color: #fff !important; font-size: 15px; font-weight: 700;
padding: 16px 32px; border-radius: 16px; text-decoration: none;
box-shadow: 0 10px 26px rgba(192,18,39,0.34);
transition: background .2s ease, transform .2s ease;
}
.dm-blog-contact-btn:hover { background: var(--dm-red-hover); transform: translateY(-2px); }
@media (max-width: 720px) {
.dm-blog-contact-cta { flex-direction: column; align-items: flex-start; gap: 26px; }
.dm-blog-contact-btn { width: 100%; }
}
`;