Files
moreminimore-astroreal/src/pages/services/index.astro
Kunthawat Greethong b5be45bcd6 feat(pages): Bento Grid redesign across all pages
Apply Bento Grid + decorative parallax orb system from about.astro
to all remaining pages (home, services, portfolio, faq, contact,
terms, privacy, blog list, blog detail, services detail).

Layout changes (consistent across all pages):
- Main content sections use <BentoGrid> + <BentoTile>
- 2-3 <DecoOrb> per page for decorative parallax (no parallax blobs
  behind text — orbs are pure decoration, z-index: 0, pointer-events: none)
- Surface variants: white, soft, yellow, purple-soft, teal, mint, dark
  (rotated across pages for visual variety)
- Asymmetric span strategy (8+4, 7+5, 6+6) instead of flat grids
- Process sections use clean 4x1 grid
- Pull quote + yellow CTA kept as-is (standalone sections)

Content rules preserved:
- All Thai content kept verbatim
- No fabricated statistics
- No emoji icons (use text numerals 01 02 03 04)
- All design tokens from global.css (no hardcoded hex)
- Existing global classes (.container, .section, .btn, .section-badge,
  .section-title, .cta-section, etc.) reused — no design system break

Build verified: 22 pages built in 1.80s, no errors.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-08 23:30:48 +07:00

325 lines
14 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
import Base from '../../layouts/Base.astro';
import Navigation from '../../components/Navigation.astro';
import Footer from '../../components/Footer.astro';
import PageHero from '../../components/PageHero.astro';
import BentoGrid from '../../components/BentoGrid.astro';
import BentoTile from '../../components/BentoTile.astro';
import DecoOrb from '../../components/DecoOrb.astro';
import { getCollection } from 'astro:content';
const services = await getCollection('services');
// Surface rotation for services Bento — keep variety
const serviceSurfaces = ['yellow', 'purple-soft', 'mint', 'soft', 'teal', 'coral'] as const;
---
<Base title="บริการ | MoreminiMore | รับทำเว็บไซต์ SEO AI Chatbot">
<Navigation />
<PageHero
badge="บริการ 4 ด้าน · เริ่มต้น 15,000 บาท"
title="โซลูชัน AI 4 ด้าน ที่คุณเลือกได้ตามงบ"
subtitle="เลือกเฉพาะที่คุณต้องการ หรือให้เราวางแผนให้ทั้งระบบ"
/>
<!-- Decision Table — Bento style (one large tile + 6 small tiles in a grid) -->
<section class="section section-bento">
<DecoOrb color="yellow" size="500px" speed={0.4} position={{ top: '-150px', left: '-100px' }} opacity={0.25} blur="80px" />
<DecoOrb color="soft" size="400px" speed={0.3} position={{ bottom: '-100px', right: '-100px' }} opacity={0.35} blur="80px" />
<div class="container" style="position: relative; z-index: 1;">
<div class="section-header">
<span class="section-badge">ไม่แน่ใจว่าจะเริ่มจากตรงไหน?</span>
<h2 class="section-title">เลือกบริการที่ใช่ <span class="highlight">ใน 30 วินาที</span></h2>
</div>
<BentoGrid>
<BentoTile span={12} surface="soft" eyebrow="Decision Helper" title="คุณกำลังเจออะไร — เริ่มที่ไหน — เห็นผลเมื่อไหร่">
<div class="decision-grid">
<div class="decision-col-head">คุณกำลังเจอ</div>
<div class="decision-col-head">เริ่มที่</div>
<div class="decision-col-head">คาดเห็นผลใน</div>
<div class="decision-cell">ยังไม่มีเว็บไซต์ หรือเว็บเก่าโหลดช้า</div>
<div class="decision-cell"><span class="dec-tag">AI-Enhanced Website</span></div>
<div class="decision-cell">24 สัปดาห์</div>
<div class="decision-cell">ทีมเซลล์ตอบแชตไม่ทัน ลูกค้าหายตอนกลางคืน</div>
<div class="decision-cell"><span class="dec-tag">AI Automation</span></div>
<div class="decision-cell">13 เดือน</div>
<div class="decision-cell">ลงโฆษณาเยอะ แต่ยอดขายไม่โต</div>
<div class="decision-cell"><span class="dec-tag">Online Marketing Automation</span></div>
<div class="decision-cell">13 เดือน</div>
<div class="decision-cell">อยากติดหน้าแรก Google แต่ไม่รู้จะเริ่มยังไง</div>
<div class="decision-cell"><span class="dec-tag">SEO + AI Content</span></div>
<div class="decision-cell">36 เดือน</div>
<div class="decision-cell">ไม่อยากจ้างทีม IT ประจำ แต่อยากมี Server/ระบบหลังบ้าน</div>
<div class="decision-cell"><span class="dec-tag">Tech Consult</span></div>
<div class="decision-cell">26 สัปดาห์</div>
<div class="decision-cell">มีเว็บอยู่แล้ว แต่ขายไม่ได้</div>
<div class="decision-cell"><span class="dec-tag">เริ่มจาก Audit ฟรี 30 นาที</span></div>
<div class="decision-cell">1 สัปดาห์</div>
</div>
</BentoTile>
</BentoGrid>
<p class="decision-closing">
ถ้ายังไม่แน่ใจ → กดปุ่ม "ปรึกษาฟรี" ด้านล่าง เราจะถาม 5 คำถามแล้วบอกคำตอบเอง
</p>
</div>
</section>
<!-- Service Grid — Bento (asymmetric spans, varied surfaces) -->
<section class="section section-bento">
<DecoOrb color="purple" size="500px" speed={0.4} position={{ top: '-150px', right: '-100px' }} opacity={0.2} blur="100px" />
<DecoOrb color="yellow" size="350px" speed={0.3} position={{ bottom: '-100px', left: '10%' }} opacity={0.25} blur="80px" />
<div class="container" style="position: relative; z-index: 1;">
<div class="section-header reveal">
<span class="section-badge">บริการทั้งหมด</span>
<h2 class="section-title">เลือกตาม <span class="highlight">เป้าหมาย</span> ของคุณ</h2>
</div>
<BentoGrid>
{services.map((s, i) => {
// Asymmetric: 6+6 for the first pair, then 4+4+4 for the rest
let span: 3 | 4 | 6 | 8 | 12;
if (i === 0) span = 8;
else if (i === 1) span = 4;
else if (i === 2) span = 4;
else if (i === 3) span = 4;
else if (i === 4) span = 6;
else span = 6;
const surface = serviceSurfaces[i % serviceSurfaces.length];
return (
<a href={`/services/${s.id}`} style="display: block; text-decoration: none; color: inherit;">
<BentoTile span={span} surface={surface} eyebrow={s.data.badge} title={s.data.title}>
<p class="service-subtitle">{s.data.subtitle}</p>
<div class="mega-objective">
<span class="objective-label">เป้าหมาย</span>
<span class="objective-value">{s.data.objective}</span>
</div>
<span class="service-link">ดูรายละเอียด →</span>
</BentoTile>
</a>
);
})}
</BentoGrid>
</div>
</section>
<!-- Pricing tiers — Bento tiles -->
<section class="section section-soft">
<DecoOrb color="soft" size="500px" speed={0.4} position={{ top: '-150px', left: '20%' }} opacity={0.5} blur="80px" />
<DecoOrb color="yellow" size="350px" speed={0.3} position={{ bottom: '-100px', right: '10%' }} opacity={0.2} blur="80px" />
<div class="container" style="position: relative; z-index: 1;">
<div class="section-header reveal">
<span class="section-badge">งบประมาณ</span>
<h2 class="section-title">ไม่ใช่ทุกงบที่จะ<span class="highlight">เหมือนกัน</span></h2>
</div>
<BentoGrid>
<BentoTile span={4} surface="white" eyebrow="Tier 01" title="เริ่มต้น">
<div class="pricing-range">15,00035,000 บาท</div>
<p class="pricing-desc">Landing Page + AI Chatbot</p>
</BentoTile>
<BentoTile span={4} surface="yellow" eyebrow="Tier 02 · แนะนำ" title="ธุรกิจ">
<div class="pricing-range pricing-range-dark">50,000150,000 บาท</div>
<p class="pricing-desc pricing-desc-dark">เว็บไซต์เต็มรูป + SEO 3 เดือน</p>
</BentoTile>
<BentoTile span={4} surface="dark" eyebrow="Tier 03" title="องค์กร">
<div class="pricing-range pricing-range-light">200,000 บาทขึ้นไป</div>
<p class="pricing-desc pricing-desc-light">ระบบครบวงจร + Automation</p>
</BentoTile>
</BentoGrid>
</div>
</section>
<section class="section section-yellow cta-section">
<div class="container">
<div class="cta-content reveal">
<h2 class="cta-title">ยังไม่รู้ว่าจะเริ่มจากตรงไหน?</h2>
<p class="cta-desc">Audit ฟรี 30 นาที — เราจะถาม 5 คำถาม แล้วบอกว่าคุณควรลงทุนกับอะไรก่อน ไม่มี upsell ไม่มี commitment</p>
<div class="cta-actions">
<a href="/contact" class="btn btn-dark btn-lg">นัดคุยเลย →</a>
<a href="https://line.me/ti/p/~@539hdlul" target="_blank" rel="noopener" class="btn btn-outline-dark btn-lg">ทัก LINE: @moreminimore</a>
</div>
</div>
</div>
</section>
<Footer />
</Base>
<style>
.section-bento {
position: relative;
overflow: hidden;
}
.section-yellow { background: var(--color-primary); }
.section-header { text-align: center; margin-bottom: 48px; }
/* Decision grid (inside BentoTile) */
.decision-grid {
display: grid;
grid-template-columns: 1.5fr 1.2fr 0.8fr;
gap: 12px 24px;
margin-top: 8px;
}
.decision-col-head {
font-size: 11px;
font-weight: 800;
text-transform: uppercase;
letter-spacing: 1.5px;
color: var(--color-gray-600);
padding-bottom: 8px;
border-bottom: 1px solid var(--color-gray-200);
}
.decision-cell {
font-size: 14px;
color: var(--color-gray-700);
line-height: 1.6;
padding: 8px 0;
border-top: 1px solid var(--color-gray-200);
}
/* Hide the pseudo-header on the first three (col-heads) so only body cells get borders */
.decision-col-head + .decision-cell { border-top: none; }
.dec-tag {
display: inline-block;
background: var(--color-primary);
color: var(--color-black);
padding: 4px 10px;
border-radius: var(--radius-sm);
font-size: 13px;
font-weight: 700;
}
.decision-closing {
text-align: center;
margin-top: 32px;
font-size: 16px;
color: var(--color-gray-700);
}
/* Service tiles (inside BentoTile) */
.service-subtitle {
font-size: 15px;
color: var(--color-gray-600);
line-height: 1.6;
margin-bottom: 16px;
}
.surface-yellow .service-subtitle { color: var(--color-black); opacity: 0.85; }
.surface-dark .service-subtitle,
.surface-teal .service-subtitle,
.surface-coral .service-subtitle { color: rgba(255, 255, 255, 0.9); }
.mega-objective {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 10px 14px;
background: var(--color-bg-alt);
border-radius: var(--radius-md);
margin-bottom: 16px;
}
.surface-yellow .mega-objective { background: rgba(0, 0, 0, 0.1); }
.surface-dark .mega-objective { background: rgba(255, 255, 255, 0.1); }
.surface-teal .mega-objective { background: rgba(255, 255, 255, 0.1); }
.surface-coral .mega-objective { background: rgba(255, 255, 255, 0.1); }
.objective-label {
font-size: 11px;
color: var(--color-gray-500);
text-transform: uppercase;
letter-spacing: 1px;
font-weight: 700;
}
.surface-dark .objective-label,
.surface-teal .objective-label,
.surface-coral .objective-label { color: var(--color-primary); }
.objective-value {
font-size: 14px;
font-weight: 700;
color: var(--color-black);
}
.surface-dark .objective-value,
.surface-teal .objective-value,
.surface-coral .objective-value { color: var(--color-white); }
.service-link {
display: inline-block;
font-size: 14px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 1px;
}
.bento-tile:hover .service-link { transform: translateX(4px); }
/* Pricing tiles */
.pricing-range {
font-family: var(--font-display);
font-size: clamp(22px, 2.4vw, 28px);
font-weight: 900;
color: var(--color-primary-dark);
margin-bottom: 8px;
}
.pricing-range-dark { color: var(--color-black); }
.pricing-range-light { color: var(--color-primary); }
.pricing-desc {
font-size: 14px;
color: var(--color-gray-600);
}
.pricing-desc-dark { color: var(--color-black); opacity: 0.85; }
.pricing-desc-light { color: rgba(255, 255, 255, 0.9); }
/* CTA */
.cta-content { text-align: center; max-width: 700px; margin: 0 auto; }
.cta-title {
font-family: var(--font-display);
font-size: clamp(28px, 4vw, 44px);
font-weight: 900;
color: var(--color-black);
margin-bottom: 16px;
}
.cta-desc {
font-size: 18px;
color: rgba(0, 0, 0, 0.7);
margin-bottom: 32px;
}
.cta-actions {
display: flex;
gap: 16px;
justify-content: center;
flex-wrap: wrap;
}
@media (max-width: 1024px) {
.decision-grid { grid-template-columns: 1fr; gap: 8px; }
.decision-col-head { display: none; }
.decision-cell { padding: 12px 14px; background: var(--color-white); border-radius: var(--radius-md); border-top: none; }
.decision-cell:nth-child(6n+1)::before { content: 'คุณกำลังเจอ: '; font-weight: 800; color: var(--color-black); }
.decision-cell:nth-child(6n+2)::before { content: 'เริ่มที่: '; font-weight: 800; color: var(--color-black); }
.decision-cell:nth-child(6n+3)::before { content: 'คาดเห็นผลใน: '; font-weight: 800; color: var(--color-black); }
}
@media (max-width: 640px) {
.cta-actions { flex-direction: column; }
.cta-actions .btn { width: 100%; justify-content: center; }
}
</style>
<script>
// Parallax orbs (use data-parallax-speed from DecoOrb)
const parallaxEls = document.querySelectorAll('[data-parallax-speed]');
function updateParallax() {
const scrolled = window.scrollY;
parallaxEls.forEach(el => {
const speed = parseFloat(el.getAttribute('data-parallax-speed') || '0.4');
const ty = scrolled * speed * -0.3;
el.style.transform = `translate3d(0, ${ty}px, 0)`;
});
}
window.addEventListener('scroll', () => requestAnimationFrame(updateParallax), { passive: true });
</script>