feat(pages): wire v6 sections to all 9 pages

- index.astro: full 9-section home (Hero → Case → Services → Callout →
  Portfolio → Process → Pricing → Faq → Contact prompt form)
- about.astro: v6 Hero + body content from <Content /> wrapped in .fx-prose
- services/index.astro: v6 Hero + v6 Services (4 from collection) + Contact prompt
- portfolio.astro: v6 Hero + v6 Portfolio (pinned 3) + grid of remaining 6 + Contact
- blog/index.astro: PageHero → Hero (badge→eyebrow, subtitle→lede, showStats=false)
- blog/[slug].astro: same PageHero → Hero swap
- faq.astro: same swap (existing bento FAQ body preserved)
- contact.astro: same swap + WIRED form to submitContact() (real backend).
  Was setTimeout 800ms placeholder — now uses contact-submit.ts which
  POSTs to PUBLIC_CONTACT_ENDPOINT (Apps Script) or dev-mocks if empty.
- privacy.astro + terms.astro: same PageHero → Hero swap

Build: 22 pages, 0 errors. Phase 4.9d complete (contact form wired).

Refs: .hermes/plans/2026-06-13_124000-moreminimore-v7-5-migration.md Task 5.1-5.9
This commit is contained in:
Kunthawat Greethong
2026-06-13 18:01:17 +07:00
parent 8c2bf3d303
commit caa412dbe2
10 changed files with 210 additions and 1606 deletions

View File

@@ -1,9 +1,10 @@
---
/**
* MOREMINIMORE - ABOUT
* Per plan 2026-06-13: v6 Hero (with about data) + body content from <Content />
*/
import Base from '../layouts/Base.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 Hero from '../components/Hero.astro';
import { getEntry, render } from 'astro:content';
import type { CollectionEntry } from 'astro:content';
@@ -12,480 +13,44 @@ const { Content } = await render(about);
---
<Base title="เกี่ยวกับเรา | MoreminiMore | รับทำเว็บไซต์ SEO AI Chatbot">
<PageHero
badge={about.data.hero_badge}
title="เริ่มจากตรงนี้"
subtitle="ริษัท มอร์มินิมอร์ จำกัด — นโยบายของเราคือสร้างระบบที่ทำให้ลูกค้ามีกำไรมากขึ้น ไม่ใช่ทำเว็บไซต์ออกมาเยอะแล้วลืม เราเป็น Partner ที่นั่งทำงานข้างคุณจนระบบติดและใช้งานได้จริง"
<Hero
id="about-hero"
eyebrow="MOREMINIMORE / เกี่ยวกับเรา"
title="ริ่มจากตรงนี้ ที่ปรึกษาที่ทำงานเอง"
lede="บริษัท มอร์มินิมอร์ จำกัด — นโยบายของเราคือสร้างระบบที่ทำให้ลูกค้ามีกำไรมากขึ้น ไม่ใช่ทำเว็บไซต์ออกมาเยอะแล้วลืม"
ctaPrimary={{ text: 'ปรึกษาฟรี 30 นาที →', href: '/contact' }}
ctaSecondary={{ text: 'ดูผลงานจริง', href: '/portfolio' }}
showStats={false}
/>
<!-- ABOUT CONTENT (BENTO) -->
<section class="section section-bento">
<DecoOrb color="yellow" size="500px" speed={0.4} position={{ top: '-150px', left: '-150px' }} opacity={0.25} blur="80px" />
<DecoOrb color="soft" size="400px" speed={0.3} position={{ bottom: '-100px', right: '-100px' }} opacity={0.4} blur="80px" />
<div class="container" style="position: relative; z-index: 1;">
<BentoGrid>
<BentoTile span={12} surface="soft" eyebrow="นโยบายของเรา" title="เป้าหมายคือเพิ่มกำไรให้ลูกค้า">
<p>เพราะถ้าลูกค้ามีกำไรมากขึ้น ลูกค้าก็จะสามารถใช้บริการเราต่อไปได้</p>
<p>ทุกระบบที่ส่งมอบต้องตอบคำถามเดียวให้ได้: <strong>"ลูกค้ามีกำไรเพิ่มขึ้นจริงไหม"</strong> — ไม่ใช่แค่ส่งงานตามสัญญา</p>
</BentoTile>
<BentoTile span={8} surface="yellow" eyebrow="วิธีทำงานของเรา" title="ไม่ได้ทำงานแบบเดียวกับทุกที่">
<p>เพราะลูกค้าแต่ละคนมีบริบท งบประมาณ และทีมต่างกัน</p>
<ul class="checklist">
<li>✅ <strong>งานที่ต้องใช้ความเชี่ยวชาญเฉพาะทาง</strong> — เราทำเอง เพราะถ้าไม่ทำเอง จะตอบคำถามลูกค้าไม่ได้</li>
<li>✅ <strong>งานที่ต้องทำซ้ำ ๆ ปริมาณเยอะ</strong> — เราใช้ bot หรือ outsource ให้คนเชี่ยวชาญ เพราะคนที่ทำเป็นอาชีพจะดีกว่า</li>
<li>✅ <strong>งานที่ต้องตอบลูกค้าตลอด 24 ชั่วโมง</strong> — bot ช่วยคัดกรองเบื้องต้น แล้วเราตามด้วยคน</li>
</ul>
<p style="margin-top: 16px;"><strong>สรุป:</strong> ผลงานที่ออกมาขึ้นอยู่กับบริบทของลูกค้า ไม่ใช่วิธีทำงานของเรา — เราเลือกวิธีที่ทำให้ลูกค้าได้ผลลัพธ์ที่ดีที่สุด ไม่ใช่วิธีที่เราถนัดที่สุด</p>
</BentoTile>
<BentoTile span={4} surface="purple-soft" eyebrow="ปี 2020" title="ก่อตั้งจากประสบการณ์ตรง">
<p>เห็น SME ไทยเสียเงินหลายแสนไปกับเว็บไซต์ "สวยแต่ไม่มีคนเข้า" และ AI tools "ว้าวแต่ใช้ไม่เป็น"</p>
</BentoTile>
<BentoTile span={6} surface="mint" eyebrow="เราเชื่ออะไร" title="หลักคิด 6 ข้อ">
<ul>
<li>เว็บสวยไม่ได้แปลว่าขายได้</li>
<li>AI ไม่ได้แทนทุกอย่าง — แต่ถ้ารู้จักใช้...</li>
<li>จ่ายแพงไม่ได้แปลว่าดี</li>
<li>"สิ่งที่ถูกต้อง" ไม่ใช่ "สิ่งที่ลูกค้าต้องการ" เสมอไป</li>
<li>ระบบที่คนใช้ไม่เป็น = เสียเงินเปล่า</li>
</ul>
</BentoTile>
<BentoTile span={6} surface="teal" eyebrow="เบื้องหลัง" title="Marketing intelligence ที่ใช้">
<p>นั่งทำงานที่บ้าน ใช้ MacBook ตัวเดียว แต่มีเครื่องมือที่ช่วยให้เข้าใจตลาดได้ลึกกว่าคนทั่วไป:</p>
<ul>
<li><strong>ระบบดูโฆษณาคู่แข่ง</strong> — ดูว่าคู่แข่งยิงโฆษณาอะไร คำไหน convert ดี</li>
<li><strong>วิเคราะห์ keyword + SEO gap</strong> — หาโอกาสที่คู่แข่งยังไม่ได้ทำ</li>
<li><strong>ติดตาม trend ตลาด</strong> — รู้ก่อนลูกค้าว่าตลาดกำลังไปทางไหน</li>
</ul>
<p style="margin-top: 12px;"><strong>Stack:</strong> JavaScript, Python, PHP, n8n, OpenAI API, Meta API, Google Analytics, Looker Studio</p>
</BentoTile>
</BentoGrid>
</div>
</section>
<!-- STORY SECTION -->
<section class="section section-bento">
<DecoOrb color="yellow" size="400px" speed={0.5} position={{ top: '10%', right: '-150px' }} opacity={0.3} blur="80px" />
<DecoOrb color="mint" size="300px" speed={0.3} position={{ bottom: '-100px', left: '-100px' }} opacity={0.2} blur="80px" />
<div class="container" style="position: relative; z-index: 1;">
<div class="story-grid">
<div class="story-content">
<span class="section-badge">นโยบายของเรา</span>
<h2 class="section-title">
เพิ่ม<span class="highlight">ยอดขาย</span> · ลด<span class="highlight">ต้นทุน</span> · ลด<span class="highlight">เวลา</span>
</h2>
<p class="story-text">
<strong>นโยบายของเราชัดเจน</strong> — ทุกระบบที่ส่งมอบต้องตอบคำถามเดียวให้ได้: "ลูกค้ามีกำไรเพิ่มขึ้นจริงไหม" ไม่ใช่แค่ส่งงานตามสัญญา
</p>
<p class="story-text">
<strong>ก่อตั้งปี 2020</strong> จากประสบการณ์ตรงที่เห็น SME ไทยเสียเงินหลายแสนไปกับเว็บไซต์ที่ "สวยแต่ไม่มีคนเข้า" และ AI tools ที่ "ว้าวแต่ใช้ไม่เป็น" เราเลยตั้งใจว่าจะทำให้ต่าง
</p>
<p class="story-text">
<strong>วิธีทำงานของเรา</strong> เราไม่ได้ทำงานแบบเดียวกับทุกที่ — งานที่ต้องใช้ความเชี่ยวชาญเฉพาะทางเราทำเอง งานที่ต้องทำซ้ำ ๆ ปริมาณเยอะเราใช้ bot หรือ outsource ให้คนเชี่ยวชาญ เพราะคนที่ทำเป็นอาชีพจะดีกว่า
</p>
<div class="story-actions">
<a href="/contact" class="btn btn-primary">ปรึกษาฟรี</a>
<a href="tel:0809955945" class="btn btn-outline-dark">080-995-5945</a>
</div>
</div>
<div class="story-stats stagger-children">
<div class="stat-card">
<span class="stat-number">—</span>
<span class="stat-label">ลูกค้าที่กลับมาใช้บริการซ้ำ</span>
</div>
<div class="stat-card">
<span class="stat-number">—</span>
<span class="stat-label">โปรเจกต์ที่ส่งมอบ</span>
</div>
<div class="stat-card">
<span class="stat-number counter" data-from="0">5+</span>
<span class="stat-label">ปีของการทำงานหนัก (ก่อตั้งปี 2020)</span>
</div>
<div class="stat-card">
<span class="stat-number">—</span>
<span class="stat-label">อุตสาหกรรมที่รับ</span>
</div>
</div>
</div>
</div>
</section>
<!-- VALUES SECTION (yellow accent cards on soft) -->
<section class="section section-soft values-section">
<DecoOrb color="purple" size="500px" speed={0.4} position={{ top: '-200px', left: '20%' }} opacity={0.2} blur="100px" />
<DecoOrb color="soft" size="400px" speed={0.3} position={{ bottom: '-100px', right: '5%' }} opacity={0.4} 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">
4 สิ่งที่เรา <span class="highlight">ไม่เคยเปลี่ยน</span>
</h2>
</div>
<div class="values-grid stagger-children">
<div class="value-card value-card-yellow">
<div class="value-num">01</div>
<h3 class="value-title">เข้าใจธุรกิจก่อนเขียนโค้ด</h3>
<p class="value-desc">30 นาทีแรกของทุกโปรเจกต์คือการถาม ไม่ใช่การ present เราถามจนเข้าใจว่าคุณขายให้ใคร กำไรเท่าไหร่ ปวดหัวตรงไหน แล้วค่อยแนะนำ solution</p>
</div>
<div class="value-card">
<div class="value-num">02</div>
<h3 class="value-title">เป็น Partner ไม่ใช่ Vendor</h3>
<p class="value-desc">เราแชร์ progress ทุกสัปดาห์ผ่าน LINE Group เดียวกับที่ลูกค้าใช้ คุณเห็นทุก decision ไม่มี hidden cost ไม่มี "อันนี้เพิ่มเงินนะ" ตอนใกล้ deliver</p>
</div>
<div class="value-card">
<div class="value-num">03</div>
<h3 class="value-title">Deliver ตรงเวลา หรือบอกล่วงหน้า</h3>
<p class="value-desc">เราไม่สัญญา deadline แบบเลื่อนได้ ถ้าจะติด เราจะบอกก่อน 7 วัน ไม่ใช่บอกตอนส่งงาน เคสไหนที่เคยส่งช้า เราคืนเงิน Pro-rata</p>
</div>
<div class="value-card">
<div class="value-num">04</div>
<h3 class="value-title">ดูแลหลังส่งมอบ</h3>
<p class="value-desc">ปรับเล็ก ๆ น้อย ๆ ฟรี — คิดค่าใช้จ่ายเฉพาะ feature ใหม่หรือปรับแต่งครั้งใหญ่เท่านั้น</p>
</div>
</div>
</div>
</section>
<!-- PULL QUOTE — black band, mission statement -->
<section class="section section-dark-quote reveal">
<div class="container">
<blockquote class="pull-quote">
<p class="quote-text">
"เป้าหมายของเราคือ <span class="highlight">กำไรที่มากขึ้นของลูกค้า</span>"
</p>
<cite class="quote-author">— มอร์มินิมอร์, ปณิธานการทำงาน</cite>
</blockquote>
</div>
</section>
<!-- PROCESS SECTION (4 steps, white) -->
<section class="section process-section">
<DecoOrb color="soft" size="600px" speed={0.4} position={{ top: '-150px', right: '-100px' }} opacity={0.5} blur="80px" />
<DecoOrb color="yellow" size="300px" speed={0.3} position={{ bottom: '5%', left: '-100px' }} opacity={0.3} 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>
<p class="section-desc">4 ขั้น โปร่งใสทุกข้อ</p>
</div>
<div class="process-grid stagger-children">
<div class="process-step">
<span class="step-num">01</span>
<h3 class="step-title">ปรึกษาฟรี</h3>
<p class="step-desc">3060 นาทีคุยกับเจ้าของธุรกิจ ฟัง pain points, เป้าหมาย, budget ให้คำแนะนำเบื้องต้นฟรี ไม่ผูก commitment</p>
</div>
<div class="process-step">
<span class="step-num">02</span>
<h3 class="step-title">วางแผน</h3>
<p class="step-desc">วิเคราะห์เชิงลึก ดูคู่แข่ง ส่ง Proposal เป็น PDF คุณอ่าน ถามคำถาม แก้ไข scope ได้ก่อนเซ็น</p>
</div>
<div class="process-step">
<span class="step-num">03</span>
<h3 class="step-title">ดำเนินการ</h3>
<p class="step-desc">แจ้งความคืบหน้าเป็นช่วง ๆ ผ่าน LINE Group — demo เมื่อเราพร้อมส่งงานรอบใหญ่ ๆ ไม่ sprint ไม่ deadline ล็อก</p>
</div>
<div class="process-step process-step-yellow">
<span class="step-num">04</span>
<h3 class="step-title">ส่งมอบ + ดูแล</h3>
<p class="step-desc">ส่งมอบงาน + อบรมทีม + มอบคู่มือ หลังส่งมอบปรับเล็ก ๆ น้อย ๆ ฟรี — คิดค่าใช้จ่ายเฉพาะ feature ใหม่หรือปรับแต่งครั้งใหญ่</p>
</div>
</div>
</div>
</section>
<!-- FINAL CTA (yellow) -->
<section class="section section-yellow cta-section">
<div class="container">
<div class="cta-content reveal">
<h2 class="cta-title">อยากรู้ว่าธุรกิจคุณเหมาะกับอะไร?</h2>
<p class="cta-desc">ปรึกษาฟรี 30 นาที ไม่มี script sales ไม่มี upsell จะบอกตรง ๆ ว่าทำได้หรือไม่ควรทำ</p>
<div class="cta-actions">
<a href="/contact" class="btn btn-dark btn-lg">นัดคุยตอนนี้ →</a>
<a href="tel:0809955945" class="btn btn-outline-dark btn-lg">080-995-5945</a>
</div>
</div>
</div>
</section>
<article class="fx-prose">
<Content />
</article>
</Base>
<style>
.section-soft { background: var(--color-bg-alt); }
.section-yellow { background: var(--color-primary); }
.section-bento {
position: relative;
overflow: hidden;
}
/* VALUES (keep existing classes) */
.values-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 24px;
max-width: 900px;
.fx-prose {
max-width: 760px;
margin: 0 auto;
padding: 64px 32px 96px;
font: 400 16px/1.7 'Kanit', sans-serif;
color: var(--ink);
}
.value-card {
background: var(--color-white);
border: 1px solid var(--color-gray-200);
border-radius: var(--radius-xl);
padding: 32px;
transition: all 0.3s ease;
}
.value-card:hover {
border-color: var(--color-primary);
transform: translateY(-4px);
box-shadow: var(--shadow-md);
}
.value-num {
font-family: var(--font-display);
font-size: 22px;
font-weight: 900;
color: var(--color-black);
width: 64px;
height: 64px;
border: 2px solid var(--color-black);
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 20px;
letter-spacing: -1px;
}
.value-card-yellow { background: var(--color-primary); border-color: var(--color-primary); }
.value-card-yellow .value-num { background: var(--color-black); color: var(--color-primary); border-color: var(--color-black); }
.value-title {
font-family: var(--font-display);
font-size: 18px;
font-weight: 800;
color: var(--color-black);
margin-bottom: 10px;
}
.value-desc {
font-size: 14px;
color: var(--color-gray-700);
line-height: 1.6;
}
.value-card-yellow .value-desc { color: rgba(0, 0, 0, 0.85); }
/* PROCESS — clean 4x1 grid */
.process-section { background: var(--color-bg-alt); position: relative; overflow: hidden; }
.process-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 16px;
}
.process-step {
background: var(--color-white);
border: 1px solid var(--color-gray-200);
border-radius: var(--radius-xl);
padding: 32px 24px;
transition: all 0.3s ease;
display: flex;
flex-direction: column;
min-height: 280px;
}
.process-step:hover {
transform: translateY(-4px);
box-shadow: var(--shadow-md);
border-color: var(--color-primary);
}
.process-step-yellow {
background: var(--color-primary);
border-color: var(--color-primary);
}
.process-step-yellow .step-num,
.process-step-yellow .step-title { color: var(--color-black); }
.process-step-yellow .step-desc { color: rgba(0, 0, 0, 0.85); }
.process-step-yellow:hover { border-color: var(--color-black); }
.step-num {
display: block;
font-family: var(--font-display);
font-size: clamp(40px, 4vw, 56px);
font-weight: 900;
color: var(--color-primary);
line-height: 1;
margin-bottom: 16px;
}
.step-title {
font-family: var(--font-display);
font-size: 18px;
font-weight: 800;
color: var(--color-black);
margin-bottom: 10px;
}
.step-desc {
font-size: 14px;
color: var(--color-gray-700);
line-height: 1.6;
}
@media (max-width: 1024px) {
.process-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 640px) {
.process-grid { grid-template-columns: 1fr; }
.values-grid { grid-template-columns: 1fr; }
}
/* STORY (keep existing) */
.story-grid {
display: grid;
grid-template-columns: 1.3fr 0.7fr;
gap: 60px;
align-items: center;
}
.story-text {
font-size: 16px;
line-height: 1.8;
color: var(--color-gray-700);
margin-bottom: 20px;
}
.story-text strong { color: var(--color-black); }
.story-actions {
display: flex;
gap: 16px;
flex-wrap: wrap;
margin-top: 28px;
}
.story-stats {
display: flex;
flex-direction: column;
gap: 16px;
}
.stat-card {
padding: 24px;
background: var(--color-bg-soft);
border: 1px solid var(--color-gray-200);
border-radius: var(--radius-xl);
transition: all 0.3s ease;
}
.stat-card:hover {
border-color: var(--color-primary);
transform: translateX(4px);
}
.stat-card .stat-number {
display: block;
font-family: var(--font-display);
font-size: 36px;
font-weight: 900;
color: var(--color-black);
line-height: 1;
}
.stat-card .stat-label {
display: block;
font-size: 14px;
color: var(--color-gray-600);
margin-top: 8px;
}
.section-badge {
display: inline-block;
background: var(--color-primary);
color: var(--color-black);
padding: 8px 20px;
border-radius: var(--radius-full);
font-size: 12px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 2px;
margin-bottom: 16px;
}
.section-title {
font-family: var(--font-display);
font-size: clamp(28px, 4vw, 44px);
font-weight: 900;
line-height: 1.15;
color: var(--color-black);
margin-bottom: 16px;
}
.section-title .highlight { color: var(--color-primary-dark); }
.section-desc {
font-size: 17px;
color: var(--color-gray-600);
line-height: 1.6;
}
.section-header { text-align: center; margin-bottom: 48px; }
/* PULL QUOTE */
.section-dark-quote {
background: var(--color-black);
padding: 100px 0;
}
.section-dark-quote .pull-quote {
text-align: center;
max-width: 1000px;
margin: 0 auto;
}
.section-dark-quote .quote-text {
font-family: var(--font-display);
font-size: clamp(28px, 4.5vw, 56px);
font-weight: 800;
line-height: 1.3;
color: var(--color-white);
margin-bottom: 24px;
}
.section-dark-quote .quote-text .highlight {
color: var(--color-primary);
}
.section-dark-quote .quote-author {
font-style: normal;
font-size: 14px;
color: var(--color-gray-400);
text-transform: uppercase;
letter-spacing: 2px;
}
/* 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) {
.story-grid { grid-template-columns: 1fr; gap: 40px; }
}
@media (max-width: 640px) {
.story-actions, .cta-actions { flex-direction: column; }
.story-actions .btn, .cta-actions .btn { width: 100%; justify-content: center; }
.fx-prose :global(h1) { font: 800 36px/1.2 'Kanit', sans-serif; margin: 32px 0 16px; }
.fx-prose :global(h2) { font: 700 24px/1.3 'Kanit', sans-serif; margin: 32px 0 12px; }
.fx-prose :global(h3) { font: 600 18px/1.4 'Kanit', sans-serif; margin: 24px 0 8px; }
.fx-prose :global(p) { margin: 0 0 16px; }
.fx-prose :global(ul), .fx-prose :global(ol) { margin: 0 0 16px; padding-left: 24px; }
.fx-prose :global(li) { margin: 0 0 8px; }
.fx-prose :global(strong) { color: var(--coral); font-weight: 700; }
.fx-prose :global(em) { font-family: 'Itim', cursive; color: var(--coral); font-weight: 400; }
.fx-prose :global(blockquote) {
border-left: 4px solid var(--brand-yellow);
padding: 12px 20px;
margin: 24px 0;
background: var(--paper-2);
font: 400 18px/1.6 'Kanit', sans-serif;
}
.fx-prose :global(a) { color: var(--coral); text-decoration: underline; }
.fx-prose :global(a:hover) { background: var(--brand-yellow); }
</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>

View File

@@ -1,6 +1,6 @@
---
import Base from '../../layouts/Base.astro';
import PageHero from '../../components/PageHero.astro';
import Hero from '../../components/Hero.astro';
import BentoGrid from '../../components/BentoGrid.astro';
import BentoTile from '../../components/BentoTile.astro';
import DecoOrb from '../../components/DecoOrb.astro';
@@ -43,11 +43,11 @@ function surfaceFor(i: number) {
---
<Base title={`${post.data.title} | MoreminiMore`}>
<PageHero
badge={post.data.category}
<Hero
eyebrow={post.data.category}
title={post.data.title}
subtitle={formattedDate}
/>
lede={formattedDate}
showStats={false} />
{post.data.image && (
<section class="section section-bento article-image-section">

View File

@@ -1,6 +1,6 @@
---
import Base from '../../layouts/Base.astro';
import PageHero from '../../components/PageHero.astro';
import Hero from '../../components/Hero.astro';
import BentoGrid from '../../components/BentoGrid.astro';
import BentoTile from '../../components/BentoTile.astro';
import DecoOrb from '../../components/DecoOrb.astro';
@@ -17,11 +17,11 @@ function surfaceFor(i: number) {
---
<Base title="บทความ | MoreminiMore - รับทำเว็บไซต์ SEO AI Chatbot">
<PageHero
badge="บทความ"
<Hero
eyebrow="บทความ"
title="ความรู้ด้านดิจิทัล"
subtitle="เทคนิคและความรู้ใหม่ๆ สำหรับธุรกิจไทย — อ่านจบใน 5 นาที เน้นลงมือทำ ไม่ใช่ทฤษฎี"
/>
lede="เทคนิคและความรู้ใหม่ๆ สำหรับธุรกิจไทย — อ่านจบใน 5 นาที เน้นลงมือทำ ไม่ใช่ทฤษฎี"
showStats={false} />
{sortedPosts.length > 0 && (
<section class="section section-bento featured-section">

View File

@@ -1,6 +1,6 @@
---
import Base from '../layouts/Base.astro';
import PageHero from '../components/PageHero.astro';
import Hero from '../components/Hero.astro';
import Icon from '../components/Icon.astro';
import BentoGrid from '../components/BentoGrid.astro';
import BentoTile from '../components/BentoTile.astro';
@@ -19,11 +19,11 @@ const serviceOptions = [
---
<Base title="ติดต่อเรา | MoreminiMore | รับทำเว็บไซต์ SEO AI Chatbot">
<PageHero
badge="30 นาที · ไม่มีค่าใช้จ่าย · ไม่มี commitment"
<Hero
eyebrow="30 นาที · ไม่มีค่าใช้จ่าย · ไม่มี commitment"
title="คุยกับ คนจริง ๆ ไม่ใช่ Bot"
subtitle="ตอบกลับภายใน 2 ชั่วโมง · เลือกช่องทางที่คุณสะดวก — LINE, โทร, Email หรือฟอร์ม"
/>
lede="ตอบกลับภายใน 2 ชั่วโมง · เลือกช่องทางที่คุณสะดวก — LINE, โทร, Email หรือฟอร์ม"
showStats={false} />
<!-- QUICK CHANNEL PICKER (BENTO) -->
<section class="section section-bento">
@@ -429,11 +429,12 @@ const serviceOptions = [
}
window.addEventListener('scroll', () => requestAnimationFrame(updateParallax), { passive: true });
// Form submission
// Form submission — wire to contact-submit.ts (Apps Script backend)
// Per plan 2026-06-13 round 2 #4: real working form, not placeholder.
const form = document.getElementById('contact-form') as HTMLFormElement;
const success = document.getElementById('form-success');
form?.addEventListener('submit', (e) => {
form?.addEventListener('submit', async (e) => {
e.preventDefault();
const btn = form.querySelector('.btn-submit') as HTMLButtonElement;
const btnText = btn.querySelector('.btn-text');
@@ -441,14 +442,32 @@ const serviceOptions = [
if (btnText) btnText.textContent = 'กำลังส่ง...';
btn.disabled = true;
// Simulate submission (replace with real endpoint)
setTimeout(() => {
// Lazy-load submitContact to keep main bundle small
const { submitContact, isDevMode } = await import('../lib/contact-submit');
const formData = new FormData(form);
const data = {
name: String(formData.get('name') ?? ''),
phone: String(formData.get('phone') ?? ''),
email: String(formData.get('email') ?? ''),
service: String(formData.get('service') ?? 'other'),
message: String(formData.get('message') ?? ''),
variant: 'full' as const,
};
const result = await submitContact(data);
if (result.ok) {
form.hidden = true;
if (success) success.hidden = false;
// Append dev-mode hint to success message
if (result.devMode) {
const hint = success?.querySelector('p');
if (hint) hint.textContent = '(dev mode — submission logged to console, not actually sent)';
}
success?.scrollIntoView({ behavior: 'smooth', block: 'center' });
} else {
alert('ส่งไม่สำเร็จ: ' + (result.error ?? 'unknown error') + '\n\nลองทัก LINE: @moreminimore หรือโทร 080-995-5945');
if (btnText) btnText.textContent = originalText;
btn.disabled = false;
// Scroll to success
success?.scrollIntoView({ behavior: 'smooth', block: 'center' });
}, 800);
}
});
</script>

View File

@@ -1,6 +1,6 @@
---
import Base from '../layouts/Base.astro';
import PageHero from '../components/PageHero.astro';
import Hero from '../components/Hero.astro';
import BentoGrid from '../components/BentoGrid.astro';
import BentoTile from '../components/BentoTile.astro';
import DecoOrb from '../components/DecoOrb.astro';
@@ -63,11 +63,11 @@ groupedFaq.forEach((group, gIdx) => {
---
<Base title="คำถามที่พบบ่อย | MoreminiMore | รับทำเว็บไซต์ SEO AI Chatbot">
<PageHero
badge="FAQ"
<Hero
eyebrow="FAQ"
title="คำถามที่ลูกค้าถามบ่อยที่สุด"
subtitle="30+ คำถามที่รวบรวมจากแชต LINE จริง ๆ ไม่ใช่แต่งขึ้นเอง"
/>
lede="30+ คำถามที่รวบรวมจากแชต LINE จริง ๆ ไม่ใช่แต่งขึ้นเอง"
showStats={false} />
<!-- FAQ CATEGORIES (BENTO) -->
<section class="section section-bento">

View File

@@ -1,580 +1,63 @@
---
/**
* MOREMINIMORE - INDEX (home)
* Per plan 2026-06-13: 9 v6 sections in order
* 1. Hero (terminal+stats)
* 2. CaseStudy (Dataroot flagship)
* 3. Services (4 from collection)
* 4. Callout (yellow pullquote)
* 5. Portfolio (pinned 3)
* 6. Process (4-col hardcoded)
* 7. Pricing (2 webdev tiers)
* 8. Faq (top 4 from collection)
* 9. Contact (prompt form)
*/
import Base from '../layouts/Base.astro';
import Hero from '../components/Hero.astro';
import BentoGrid from '../components/BentoGrid.astro';
import BentoTile from '../components/BentoTile.astro';
import DecoOrb from '../components/DecoOrb.astro';
import { getCollection } from 'astro:content';
import PortfolioCard from '../components/PortfolioCard.astro';
// 4 problem cards (down from 12) — each has symptom + cause + how we fix it
const problemCards = [
{
icon: 'trendingDown',
title: 'ลงโฆษณาแล้วยอดไม่ขยับ',
symptom: 'คลิกเยอะ ยอดขายเท่าเดิม แต่คนที่ไม่ซื้อ',
cause: 'เลือกกลุ่มเป้าหมายผิด หรือยิงทุก Platform โดยไม่ดูว่าอันไหนคุ้ม',
fix: 'ดูสถิติ 3 เดือนย้อนหลัง แยกว่า Platform ไหน Convert ดี ตัดอันที่เสียเงินเปล่า? หรือ ถ้ายังไม่มีการวางระบบเก็บข้อมูล ก็จะวางระบบให้ ดังนั้นระยะยาวจะเห็นความแตกต่างแน่นอน',
example: 'เคส Dataroot: เพิ่ม Impression 373%, Click 114% โดยใช้งบน้อยลง 28% — ดูเคสเต็มใน Portfolio',
},
{
icon: 'shoppingCart',
title: 'เว็บมีคนเข้า แต่ไม่มีคนซื้อ',
symptom: 'Traffic เข้าพอสมควร แต่ไม่มีใครทัก ไม่มีใครโทร',
cause: 'เว็บสวยแต่ไม่ได้ออกแบบมาให้คนซื้อ หรือมีจุดติดขัดที่ทำให้คนออกก่อน',
fix: 'กรณีที่เว็บไม่มีการวางโค้ดเก็บสถิติ ก็จะวางระบบให้ ในกรณีที่มีระบบเก็บสถิติแล้ว ก็จะศึกษาสถิติ และดู Heatmap ว่าคนเข้ามาแล้วทำอะไร และปรับเว็บทีละจุด',
example: 'ลองคุยกัน เราจะดูให้ว่าเว็บคุณติดปัญหาตรงไหน',
},
{
icon: 'clipboard',
title: 'งานซ้ำ ๆ เสียเวลาเป็นชั่วโมงทุกวัน',
symptom: 'ทีมต้องคีย์ข้อมูล ทำรายงาน ตอบแชตเดิม ๆ จนไม่มีเวลาทำงานหลัก',
cause: 'ระบบไม่มีการเชื่อมกัน หรือยังทำ Manual อยู่',
fix: 'ดู Workflow ก่อน แล้วเลือกเครื่องมือที่เหมาะสม เช่น n8n, Script, หรือ AI ซึ่งจะช่วยลดเวลาจากชั่วโมงเป็นนาที หรือ อาจจะไม่ต้องให้พนักงานเสียเวลาอีกเลย เพราะระบบทำให้เองอัตโนมัติ',
example: 'ลองคุยกัน เราจะดู Workflow ให้ฟรี',
},
{
icon: 'brain',
title: 'ให้พนักงานใช้ AI แต่ไม่เห็นผลลัพธ์อย่างที่ต้องการ และยังมีค่าใช้จ่ายที่สูงเพิ่มแทน',
symptom: 'จ่ายแพง ใช้ AI ระดับ Frontier กับทุกงาน แต่ผลลัพธ์ไม่คุ้มเงิน',
cause: 'ใช้ AI ผิดแบบ — งานหลายอย่างใช้ Model ราคาถูกก็ได้ผลเท่า ๆ กัน หรือ พนักงานไม่เข้าใจสิ่งที่ AI จะช่วยงานจริง ทำให้ใช้งานผิดรูปแบบ',
fix: 'เลือกใช้ AI ให้ถูกกับงาน เพื่อประหยัดค่าใช้จ่าย รวมถึงให้ความรู้ หรือ วางระบบ AI Agent ให้มี skill เฉพาะทาง เพื่อช่วยพนักงาน ไม่ใช้ให้พนักงานใช้ AI โดยไม่มี skill พิเศษ',
example: 'AI Audit ฟรี — บอกได้ว่าควรใช้ AI ตัวไหน',
},
];
// Surface color rotation for the 4 problem cards — keep variety
const problemSurfaces = ['yellow', 'purple-soft', 'mint', 'soft'] as const;
const services = await getCollection('services');
// De-duplicate services: keep only the `-new` version when both old and new exist
// for the same base slug. Falls back to the old one if no `-new` exists.
// Group by base slug (strip trailing `-new` if present).
const dedupedServices = (() => {
const byBase = new Map<string, typeof services[number]>();
for (const s of services) {
const base = s.id.endsWith('-new') ? s.id.slice(0, -4) : s.id;
const existing = byBase.get(base);
if (!existing) {
byBase.set(base, s);
} else if (s.id.endsWith('-new') && !existing.id.endsWith('-new')) {
// Prefer the -new version
byBase.set(base, s);
}
}
return Array.from(byBase.values());
})();
const portfolio = await getCollection('portfolio');
const featuredPortfolio = portfolio.filter(p =>
['dataroot', 'jet-industries', 'tuanthong', 'lawyernoom'].includes(p.id)
).sort((a, b) => {
const order = ['dataroot', 'jet-industries', 'tuanthong', 'lawyernoom'];
return order.indexOf(a.id) - order.indexOf(b.id);
});
import CaseStudy from '../components/CaseStudy.astro';
import Services from '../components/Services.astro';
import Callout from '../components/Callout.astro';
import Portfolio from '../components/Portfolio.astro';
import Process from '../components/Process.astro';
import Pricing from '../components/Pricing.astro';
import Faq from '../components/Faq.astro';
import Contact from '../components/Contact.astro';
---
<Base title="MoreminiMore - ที่ปรึกษาเว็บ การตลาด และ AI สำหรับ SME ไทย">
<Hero
badge="Moreminimore"
title="เราจะช่วยคุณเพิ่มกำไร"
subtitle="เราช่วยวางระบบงาน และใช้สถิติวางกลยุทธ์ทางการตลาด"
>
<a slot="hero-cta-secondary" href="/portfolio" class="btn btn-outline-dark">
ดูผลงานจริง
</a>
</Hero>
<Hero />
<!-- PROBLEM SECTION — Bento layout (4 cards, varied spans) -->
<section class="section section-bento">
<DecoOrb color="yellow" size="500px" speed={0.4} position={{ top: '-150px', left: '-150px' }} opacity={0.25} blur="80px" />
<DecoOrb color="soft" size="400px" speed={0.3} position={{ bottom: '-100px', right: '-100px' }} opacity={0.4} blur="80px" />
<div class="container" style="position: relative; z-index: 1;">
<div class="section-header reveal">
<span class="section-badge">4 ปัญหาที่เจอบ่อยที่สุด</span>
<h2 class="section-title">
แต่ละปัญหา<span class="highlight">มีวิธีแก้ที่ต่างกัน</span>
</h2>
<p class="section-desc">เราไม่ได้บอกว่า "เราทำได้หมด" แต่บอกว่า "ถ้าเป็นแบบนี้ ทำแบบนี้"</p>
</div>
<CaseStudy
client="Dataroot"
url="https://erp.dataroot.asia"
image="/images/portfolio/dataroot.png"
stats={[
{ value: '+373<em>%</em>', label: 'impression', coord: 'A.1' },
{ value: '+114<em>%</em>', label: 'click', coord: 'A.2' },
{ value: '28<em>%</em>', label: 'ad_spend', coord: 'A.3' },
]}
quote="เราไม่ได้ยิงโฆษณาเก่ง <em>เราแค่ดูสถิติ</em>"
deck="Dataroot เดิมยิงโฆษณาแบบกว้าง — ได้คลิกเยอะ แต่ Lead คุณภาพน้อย"
logs={[
{ ts: '[2024-01-15]', level: 'INFO', text: 'วิเคราะห์ข้อมูล 3 เดือนย้อนหลัง' },
{ ts: '[2024-01-22]', level: 'SUCCESS', text: 'แยกกลุ่มเป้าหมาย: 4 segments' },
{ ts: '[2024-02-15]', level: 'SUCCESS', text: '+373% impression' },
]}
ctaPrimary={{ text: 'อ่านเคสเต็ม →', href: '/portfolio' }}
ctaSecondary={{ text: 'ดูผลงานอื่น', href: '/portfolio' }}
/>
<BentoGrid>
{problemCards.map((card, i) => (
<BentoTile span={6} surface={problemSurfaces[i]} eyebrow={`ปัญหา ${String(i + 1).padStart(2, '0')}`} title={card.title}>
<div class="problem-section">
<span class="problem-label">อาการ</span>
<p class="problem-text">{card.symptom}</p>
</div>
<Services />
<div class="problem-section">
<span class="problem-label">สาเหตุส่วนใหญ่</span>
<p class="problem-text">{card.cause}</p>
</div>
<Callout text="การจ่ายเงินซื้อ AI ไม่ได้ทำให้ธุรกิจดีขึ้น — <em>การวางระบบให้ AI ทำงานแทนงานซ้ำ ๆ</em> ต่างหากที่ทำให้พนักงานมีเวลาไปทำงานที่สร้างมูลค่า" />
<div class="problem-fix">
<span class="problem-label problem-label-fix">เราแก้ยังไง</span>
<p class="problem-text">{card.fix}</p>
</div>
<Portfolio />
<div class="problem-example">
<span class="problem-example-icon">▸</span> {card.example}
</div>
</BentoTile>
))}
</BentoGrid>
<Process />
<p class="problem-closing reveal">
ไม่แน่ใจว่าตรงกับข้อไหน — <a href="/contact" class="closing-link">นัดคุย 30 นาทีฟรี</a> เราจะช่วยดู
</p>
</div>
</section>
<Pricing />
<!-- SERVICES SECTION — Bento layout (4 services, asymmetric) -->
<section class="section section-bento">
<DecoOrb color="purple" size="500px" speed={0.4} position={{ top: '-200px', right: '-150px' }} opacity={0.2} blur="100px" />
<DecoOrb color="yellow" size="400px" speed={0.3} position={{ bottom: '-100px', left: '-100px' }} 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>
<p class="section-desc">ไม่จำเป็นต้องทำทุกอย่างพร้อมกัน</p>
</div>
<Faq limit={4} />
<BentoGrid>
{dedupedServices.slice(0, 4).map((s, i) => {
// Tile-specific copy overrides (per user spec)
const tileCopy = [
{
eyebrow: 'ที่ปรึกษาด้าน AI',
surface: 'mint',
subtitle: 'การนำ AI มาปรับใช้ในองค์กร เพื่อลดต้นทุนและเวลา รวมถึงการรักษาความรู้จากพนักงานที่เชี่ยวชาญ',
objective: 'รักษาความรู้ขององค์กร ลดต้นทุนและเวลาการทำงาน',
bullets: [
'วิเคราะห์ workflow ที่เหมาะกับ AI ก่อนลงทุน',
'เลือก AI Model ที่คุ้มค่า ไม่ใช่แพงสุด',
'วางระบบ AI Agent ที่พนักงานใช้จริง',
],
},
{
eyebrow: 'วางระบบ Automation',
surface: 'yellow',
subtitle: 'การออกแบบระบบ Automation สำหรับธุรกิจคุณโดยเฉพาะ',
objective: 'ลดต้นทุนและเวลา',
bullets: [
'ดู Workflow ก่อน เลือกเครื่องมือที่เหมาะสม',
'ลดเวลางานซ้ำจากชั่วโมงเป็นนาที',
'ระบบทำงานอัตโนมัติ พนักงานไม่เสียเวลาทำ Manual',
],
},
{
eyebrow: 'ที่ปรึกษาการตลาดออนไลน์',
surface: 'purple-soft',
subtitle: 'ออกแบบและวางกลยุทธ์ตามสถิติ กลุ่มเป้าหมาย และการทำงานขององค์กรคุณ',
objective: 'เพิ่มยอดขาย',
bullets: [
'วางกลยุทธ์จากสถิติกลุ่มเป้าหมาย ไม่ใช่เดา',
'ดู Platform ที่ Convert ดี ตัดอันที่เสียเงินเปล่า',
'ระบบเก็บข้อมูล + วิเคราะห์ผล ค่อย ๆ ปรับ',
],
},
{
eyebrow: 'พัฒนาเว็บไซต์',
surface: 'teal-soft',
subtitle: 'พัฒนาเว็บไซต์ที่สร้างผลลัพธ์ได้จริง สวยงาม และลูกค้าสามารถดูแลได้เอง',
objective: 'เพิ่มยอดขาย และความน่าเชื่อถือให้ธุรกิจ',
bullets: [
'เว็บที่ขายได้ + ลูกค้าดูแลเอง ไม่ต้องพึ่งเราทุกครั้ง',
'ออกแบบ SEO + GEO ให้ติดทั้ง Google และ AI Search',
'เลือก Tech Stack ที่เหมาะกับธุรกิจ ไม่ใช่ของถูกแต่พังบ่อย',
],
},
];
// 2x2 layout — each tile span 6 (6+6 per row, 2 rows)
const span = 6;
const copy = tileCopy[i];
const surface = copy.surface;
return (
<BentoTile span={span} surface={surface} eyebrow={copy.eyebrow} title={s.data.title}>
<p class="mega-subtitle">{copy.subtitle}</p>
<ul class="mega-bullets">
{copy.bullets.map(b => <li>{b}</li>)}
</ul>
<div class="mega-objective">
<span class="objective-label">เป้าหมาย:</span>
<span class="objective-value">{copy.objective}</span>
</div>
<span class="mega-cta">ดูรายละเอียด →</span>
<a href={`/services/${s.id}`} class="tile-link-overlay" aria-label={`ดูรายละเอียด ${s.data.title}`}></a>
</BentoTile>
);
})}
</BentoGrid>
<div class="section-cta">
<a href="/services" class="btn btn-dark btn-lg">ดูบริการทั้งหมด →</a>
</div>
</div>
</section>
<!-- PULL QUOTE -->
<section class="section section-dark-quote reveal">
<div class="container">
<blockquote class="pull-quote">
<p class="quote-text">
"เป้าหมายของเราคือ <span class="highlight">กำไรที่มากขึ้นของลูกค้า</span>"
</p>
<cite class="quote-author">— มอร์มินิมอร์</cite>
</blockquote>
</div>
</section>
<!-- PORTFOLIO PREVIEW — featured real cases (filtered: must have url) -->
<section class="section section-soft">
<div class="container">
<div class="section-header reveal">
<span class="section-badge">ผลงานจริง ไม่ใช่ Mockup</span>
<h2 class="section-title">
ลูกค้าจริง <span class="highlight">เว็บจริง</span>
</h2>
<p class="section-desc">คลิกเข้าไปดูเว็บจริงที่ใช้งานอยู่ทุกวันนี้</p>
</div>
<div class="portfolio-preview-grid stagger-children">
{featuredPortfolio.filter(p => p.data.url).slice(0, 4).map((item) => (
<PortfolioCard
name={item.data.name}
url={item.data.url}
category={item.data.category}
category_label={item.data.category_label}
industry={item.data.industry}
thumbnail={item.data.thumbnail}
description={item.data.description}
what_we_did={item.data.what_we_did}
result={item.data.result}
/>
))}
</div>
<div class="section-cta">
<a href="/portfolio" class="btn btn-dark btn-lg">ดูผลงานทั้งหมด →</a>
</div>
</div>
</section>
<!-- FINAL CTA -->
<section class="section section-yellow cta-section">
<div class="container">
<div class="cta-content reveal">
<h2 class="cta-title">คุยกันก่อน 30 นาที ฟรี</h2>
<p class="cta-desc">เราจะแนะนำแนวทางเบื้องต้นให้คุณว่าควรเริ่มจากตรงไหน — จะบอกตรง ๆ ว่าอะไรควรทำหรือไม่ควรทำ</p>
<div class="cta-actions">
<a href="/contact" class="btn btn-dark btn-lg">
นัดคุย 30 นาที
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M5 12h14M12 5l7 7-7 7"/>
</svg>
</a>
<a href="https://line.me/ti/p/~@539hdlul" target="_blank" rel="noopener" class="btn btn-outline-dark btn-lg">
ทัก LINE: @moreminimore
</a>
</div>
<p class="cta-reassurance">ไม่มี commitment · ไม่มี script sales · พูดตรง ๆ</p>
</div>
</div>
</section>
<Contact variant="prompt" />
</Base>
<style>
.section-bento {
position: relative;
overflow: hidden;
}
/* ============================================
PROBLEM TILES (inside BentoTile)
============================================ */
.problem-section {
margin-bottom: 14px;
}
.problem-fix {
background: rgba(255, 220, 0, 0.25);
border-left: 3px solid var(--color-black);
padding: 12px 14px;
border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
margin: 14px -14px;
}
.surface-purple-soft .problem-fix,
.surface-mint .problem-fix,
.surface-soft .problem-fix {
background: rgba(0, 0, 0, 0.05);
border-left-color: var(--color-black);
}
.problem-label {
display: block;
font-size: 11px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 1.5px;
margin-bottom: 6px;
opacity: 0.7;
}
.surface-yellow .problem-label { color: var(--color-black); opacity: 0.7; }
.problem-label-fix { color: var(--color-black); opacity: 1; }
.problem-text {
font-size: 14px;
line-height: 1.6;
margin: 0;
}
.surface-yellow .problem-text { color: var(--color-black); }
.surface-purple-soft .problem-text,
.surface-mint .problem-text,
.surface-soft .problem-text { color: var(--color-gray-700); }
.problem-example {
margin-top: 16px;
padding-top: 16px;
border-top: 1px dashed currentColor;
opacity: 0.7;
font-size: 13px;
line-height: 1.5;
font-style: italic;
}
.problem-example-icon {
font-style: normal;
font-weight: 700;
margin-right: 4px;
}
.problem-closing {
text-align: center;
margin-top: 48px;
font-size: 17px;
color: var(--color-gray-700);
}
.closing-link {
color: var(--color-primary-dark);
font-weight: 700;
text-decoration: underline;
text-underline-offset: 3px;
}
/* ============================================
SERVICES TILES (inside BentoTile)
============================================ */
.mega-subtitle {
font-size: 15px;
line-height: 1.6;
margin-bottom: 16px;
}
.surface-yellow .mega-subtitle { color: var(--color-black); opacity: 0.85; }
.surface-purple-soft .mega-subtitle { color: var(--color-black); }
.surface-soft .mega-subtitle { color: var(--color-gray-700); }
/* Bullet list for service tiles */
.mega-bullets {
list-style: none;
padding: 0;
margin-bottom: 20px;
}
.mega-bullets li {
position: relative;
padding-left: 20px;
font-size: 14px;
line-height: 1.6;
margin-bottom: 8px;
}
.mega-bullets li::before {
content: '';
position: absolute;
left: 0;
top: 9px;
width: 8px;
height: 8px;
border-radius: 50%;
background: currentColor;
opacity: 0.4;
}
/* Light text on dark service tiles — currently none used (teal-soft is light) */
.surface-soft .mega-subtitle { color: var(--color-gray-700); }
.mega-objective {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 10px 14px;
background: rgba(0, 0, 0, 0.05);
border-radius: var(--radius-md);
margin-bottom: 20px;
}
.surface-yellow .mega-objective { background: rgba(0, 0, 0, 0.1); }
.objective-label {
font-size: 12px;
font-weight: 600;
opacity: 0.7;
}
.objective-value {
font-size: 13px;
font-weight: 700;
}
.surface-yellow .objective-value { color: var(--color-black); }
.mega-cta {
display: inline-block;
font-size: 14px;
font-weight: 700;
text-decoration: none;
transition: transform 0.2s ease;
}
.bento-tile:hover .mega-cta { transform: translateX(4px); }
/* ============================================
PORTFOLIO PREVIEW
============================================ */
.portfolio-preview-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 20px;
max-width: 900px;
margin: 0 auto;
}
/* ============================================
SECTION UTILITIES
============================================ */
.section-header { margin-bottom: 40px; }
.section-cta {
text-align: center;
margin-top: 48px;
}
/* ============================================
PULL QUOTE — dark band
============================================ */
.section-dark-quote {
background: var(--color-black);
padding: 100px 0;
}
.pull-quote {
text-align: center;
max-width: 1000px;
margin: 0 auto;
}
.quote-text {
font-family: var(--font-display);
font-size: clamp(28px, 4.5vw, 52px);
font-weight: 800;
line-height: 1.25;
color: var(--color-white);
margin-bottom: 24px;
}
.quote-text .highlight {
color: var(--color-primary);
}
.quote-author {
font-style: normal;
font-size: 13px;
color: var(--color-gray-400);
text-transform: uppercase;
letter-spacing: 3px;
font-weight: 600;
}
/* ============================================
FINAL CTA — yellow section
============================================ */
.cta-section {
background: var(--color-primary);
padding: 100px 0;
position: relative;
overflow: hidden;
}
.cta-section::before {
content: '';
position: absolute;
top: -50%;
right: -10%;
width: 600px;
height: 600px;
background: var(--color-primary-dark);
border-radius: 50%;
opacity: 0.4;
z-index: 0;
}
.cta-section::after {
content: '';
position: absolute;
bottom: -30%;
left: -5%;
width: 400px;
height: 400px;
background: var(--color-primary-dark);
border-radius: 50%;
opacity: 0.3;
z-index: 0;
}
.cta-content {
text-align: center;
max-width: 720px;
margin: 0 auto;
position: relative;
z-index: 1;
}
.cta-title {
font-family: var(--font-display);
font-size: clamp(32px, 5vw, 52px);
font-weight: 900;
color: var(--color-black);
margin-bottom: 20px;
line-height: 1.15;
}
.cta-desc {
font-size: 18px;
color: var(--color-black);
opacity: 0.8;
margin-bottom: 36px;
line-height: 1.6;
}
.cta-actions {
display: flex;
gap: 16px;
justify-content: center;
flex-wrap: wrap;
margin-bottom: 20px;
}
.cta-actions .btn svg {
width: 18px;
height: 18px;
margin-left: 4px;
}
.cta-reassurance {
font-size: 14px;
color: var(--color-black);
opacity: 0.7;
font-weight: 500;
}
/* ============================================
RESPONSIVE
============================================ */
@media (max-width: 1024px) {
.portfolio-preview-grid { grid-template-columns: 1fr; max-width: 500px; }
}
@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>

View File

@@ -1,244 +1,73 @@
---
/**
* MOREMINIMORE - PORTFOLIO
* Per plan 2026-06-13:
* 1. v6 Hero
* 2. v6 Portfolio (pinned 3: Dataroot / Luadjob / Jet)
* 3. Grid of all 9 remaining
*/
import Base from '../layouts/Base.astro';
import PageHero from '../components/PageHero.astro';
import Hero from '../components/Hero.astro';
import Portfolio from '../components/Portfolio.astro';
import PortfolioCard from '../components/PortfolioCard.astro';
import Icon from '../components/Icon.astro';
import BentoGrid from '../components/BentoGrid.astro';
import BentoTile from '../components/BentoTile.astro';
import DecoOrb from '../components/DecoOrb.astro';
import Contact from '../components/Contact.astro';
import { getCollection } from 'astro:content';
const portfolio = await getCollection('portfolio');
// Filter: only show real cases (have url) and not drafts
const realPortfolio = portfolio.filter(p => p.data.url && p.data.url !== '');
const all = await getCollection('portfolio');
const realPortfolio = all.filter(p => p.data.url && p.data.url !== '');
// Industry filter metadata: id -> { label, icon }
// Icons are lucide-style SVGs; emoji-free.
// Service category filters (multi-category supported via comma-sep)
const serviceFilters = [
{ id: 'all', label: 'ทั้งหมด', icon: 'layers' },
{ id: 'consult', label: 'Consult', icon: 'briefcase' },
{ id: 'webdev', label: 'Website Development', icon: 'code' },
];
// Pinned 3 (also shown in v6 Portfolio component)
const PINNED = ['dataroot', 'luadjob', 'jet-industries'];
const gridItems = realPortfolio.filter(p => !PINNED.includes(p.id));
---
<Base title="ผลงาน | MoreminiMore | รับทำเว็บไซต์ SEO AI Chatbot">
<PageHero
badge="9 โปรเจกต์ · 5 อุตสาหกรรม · ผลงานจริงทุกชิ้น"
title="เราส่งมอบให้ใคร มาบ้างแล้วบ้าง"
subtitle="โปรเจกต์จริง ลูกค้าจริง เว็บไซต์จริงที่ใช้งานอยู่ทุกวันนี้ — คลิกเข้าไปดูได้เลย"
<Hero
id="portfolio-hero"
eyebrow="MOREMINIMORE / portfolio"
title="ผลงานจริง ไม่ใช่ Mockup ลูกค้าจริง ตัวเลขจริง"
lede="9 โปรเจกต์ · 5 อุตสาหกรรม — คลิกดูเว็บจริงได้เลย"
ctaPrimary={{ text: 'ปรึกษาฟรี →', href: '/contact' }}
ctaSecondary={{ text: 'ดูบริการ', href: '/services' }}
showStats={false}
/>
<!-- Industry Filter Bar -->
<section class="filter-section">
<div class="container">
<div class="filter-bar">
{serviceFilters.map(f => (
<button
class="filter-btn"
class:list={[{ active: f.id === 'all' }]}
data-filter={f.id}
>
{f.id !== 'all' && <Icon name={f.icon as any} size={16} class="filter-icon" />}
{f.id === 'all' && <Icon name={f.icon as any} size={16} class="filter-icon" />}
<span>{f.id === 'all' ? `ทั้งหมด (${realPortfolio.length})` : f.label}</span>
</button>
))}
</div>
<Portfolio showHeader={false} />
<section class="fx-portfolio-grid-section">
<div class="fx-section-header">
<span class="fx-section-eyebrow">// more work</span>
<h2 class="fx-section-title">ผลงานอื่น ๆ</h2>
</div>
<div class="fx-portfolio-grid">
{gridItems.map(item => (
<PortfolioCard
name={item.data.name}
url={item.data.url || '#'}
category={item.data.category}
category_label={item.data.category_label}
industry={item.data.industry}
thumbnail={item.data.thumbnail}
description={item.data.description}
what_we_did={item.data.what_we_did}
result={item.data.result}
/>
))}
</div>
</section>
<section class="section section-bento">
<DecoOrb color="yellow" size="500px" speed={0.4} position={{ top: '-150px', right: '-150px' }} opacity={0.2} blur="80px" />
<DecoOrb color="soft" size="400px" speed={0.3} position={{ bottom: '-100px', left: '-100px' }} opacity={0.35} blur="80px" />
<div class="container" style="position: relative; z-index: 1;">
<div class="portfolio-grid stagger-children">
{realPortfolio.map(item => (
<PortfolioCard
name={item.data.name}
url={item.data.url || '#'}
category={item.data.category}
category_label={item.data.category_label}
industry={item.data.industry}
thumbnail={item.data.thumbnail}
description={item.data.description}
what_we_did={item.data.what_we_did}
result={item.data.result}
/>
))}
</div>
</div>
</section>
<!-- "ดีลที่เราเลือก" Section — Bento tiles -->
<section class="section section-soft section-bento">
<DecoOrb color="purple" size="500px" speed={0.4} position={{ top: '-200px', left: '20%' }} opacity={0.18} blur="100px" />
<DecoOrb color="yellow" size="350px" speed={0.3} position={{ bottom: '-100px', right: '5%' }} 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>
<BentoTile span={4} surface="yellow" eyebrow="ข้อ 01" title="ธุรกิจที่พร้อมจริง ๆ">
<p>เราคุยกับเจ้าของธุรกิจก่อน ถ้าเป้าหมายยังไม่ชัด เราจะแนะนำให้รอก่อน ดีกว่าเสียเงินแล้วไม่ได้ผล</p>
</BentoTile>
<BentoTile span={4} surface="purple-soft" eyebrow="ข้อ 02" title="งบประมาณที่สมเหตุสมผล">
<p>เราไม่ได้ถูกที่สุด แต่ก็ไม่ได้แพงที่สุด ถ้าใครบอก "งบ 5,000 ทำเว็บได้ไหม" — เราแนะนำให้ไปฟรีแลนซ์ก่อน</p>
</BentoTile>
<BentoTile span={4} surface="mint" eyebrow="ข้อ 03" title="ลูกค้าที่ฟัง">
<p>เราทำงานกับลูกค้าที่พร้อมฟังคำแนะนำ ไม่ใช่ลูกค้าที่บอก "ทำตามนี้เป๊ะ ๆ" แล้วผิดคาดทุกที</p>
</BentoTile>
</BentoGrid>
</div>
</section>
<section class="section section-yellow cta-section">
<div class="container">
<div class="cta-content reveal">
<h2 class="cta-title">อยากเป็น <span class="highlight">ผลงานชิ้นต่อไป</span> ของเรา?</h2>
<p class="cta-desc">ถ้าธุรกิจคุณพร้อม เราพร้อม — คุยกันก่อน 30 นาที แล้วตัดสินใจเอง</p>
<div class="cta-actions">
<a href="/contact" class="btn btn-dark btn-lg">เริ่มโปรเจกต์ของคุณ →</a>
<a href="/services" class="btn btn-outline-dark btn-lg">ดูบริการที่เราทำ</a>
</div>
<p class="cta-reassurance">ไม่มี script · ไม่มี pressure · ตรงไปตรงมา</p>
</div>
</div>
</section>
<Contact variant="prompt" />
</Base>
<script>
// Industry filter
const filterBtns = document.querySelectorAll('.filter-btn');
const cards = document.querySelectorAll('.portfolio-card');
filterBtns.forEach(btn => {
btn.addEventListener('click', () => {
filterBtns.forEach(b => b.classList.remove('active'));
btn.classList.add('active');
const filter = btn.getAttribute('data-filter');
cards.forEach(card => {
const categories = (card.getAttribute('data-category') || '').toLowerCase().split(/[,\s]+/).filter(Boolean);
if (filter === 'all' || categories.includes(filter)) {
(card as HTMLElement).style.display = '';
} else {
(card as HTMLElement).style.display = 'none';
}
});
});
});
// Parallax orbs
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>
<style>
.section-bento {
position: relative;
overflow: hidden;
}
/* Filter bar (unchanged) */
.filter-section {
background: var(--color-bg-alt);
padding: 20px 0;
border-top: 1px solid var(--color-gray-200);
border-bottom: 1px solid var(--color-gray-200);
position: sticky;
top: 70px;
z-index: 50;
}
.filter-bar {
display: flex;
gap: 8px;
overflow-x: auto;
padding: 4px 0;
}
.filter-btn {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 12px 20px;
background: var(--color-white);
color: var(--color-black);
border: 1px solid var(--color-gray-200);
border-radius: var(--radius-full);
font-family: var(--font-display);
font-size: 14px;
font-weight: 600;
cursor: pointer;
transition: all 0.2s var(--ease-out-expo);
white-space: nowrap;
}
.filter-btn:hover {
border-color: var(--color-primary);
color: var(--color-black);
}
.filter-btn.active {
background: var(--color-primary);
color: var(--color-black);
border-color: var(--color-primary);
}
.filter-icon { color: currentColor; }
/* Portfolio grid (unchanged — uses PortfolioCard component) */
.portfolio-grid {
.fx-portfolio-grid-section { padding: 64px 32px; background: var(--paper-2); }
.fx-portfolio-grid {
max-width: 1200px;
margin: 32px auto 0;
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 28px;
}
.section-header { text-align: center; margin-bottom: 48px; }
.section-soft { background: var(--color-bg-alt); }
.section-yellow { background: var(--color-primary); }
/* 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-title .highlight { color: var(--color-black); text-decoration: underline; text-decoration-color: var(--color-black); text-underline-offset: 6px; text-decoration-thickness: 4px; }
.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;
margin-bottom: 16px;
}
.cta-reassurance {
font-size: 14px;
color: rgba(0, 0, 0, 0.6);
}
@media (max-width: 1024px) {
.portfolio-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 640px) {
.portfolio-grid { grid-template-columns: 1fr; }
.cta-actions { flex-direction: column; }
.cta-actions .btn { width: 100%; justify-content: center; }
gap: 24px;
}
@media (max-width: 1024px) { .fx-portfolio-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 640px) { .fx-portfolio-grid { grid-template-columns: 1fr; } }
</style>

View File

@@ -1,17 +1,17 @@
---
import Base from '../layouts/Base.astro';
import PageHero from '../components/PageHero.astro';
import Hero from '../components/Hero.astro';
import BentoGrid from '../components/BentoGrid.astro';
import BentoTile from '../components/BentoTile.astro';
import DecoOrb from '../components/DecoOrb.astro';
---
<Base title="นโยบายความเป็นส่วนตัว | MoreminiMore - รับทำเว็บไซต์ SEO AI Chatbot">
<PageHero
badge="กฎหมาย"
<Hero
eyebrow="กฎหมาย"
title="นโยบายความเป็นส่วนตัว"
subtitle="มีผลบังคับใช้วันที่ 5 พฤษภาคม 2569"
/>
lede="มีผลบังคับใช้วันที่ 5 พฤษภาคม 2569"
showStats={false} />
<section class="section section-bento legal-section">
<DecoOrb color="purple" size="450px" speed={0.3} position={{ top: '-100px', left: '-150px' }} opacity={0.2} blur="80px" />

View File

@@ -1,318 +1,26 @@
---
/**
* MOREMINIMORE - SERVICES INDEX
* Per plan 2026-06-13: v6 Hero + v6 Services (4 cards from collection)
*/
import Base from '../../layouts/Base.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;
import Hero from '../../components/Hero.astro';
import Services from '../../components/Services.astro';
import Contact from '../../components/Contact.astro';
---
<Base title="บริการ | MoreminiMore | รับทำเว็บไซต์ SEO AI Chatbot">
<PageHero
badge="บริการ 4 ด้าน · เริ่มต้น 15,000 บาท"
title="โซลูชัน AI 4 ด้าน ที่คุณเลือกได้ตามงบ"
subtitle="เลือกเฉพาะที่คุณต้องการ หรือให้เราวางแผนให้ทั้งระบบ"
<Hero
id="services-hero"
eyebrow="MOREMINIMORE / services"
title="เราทำอะไรได้บ้าง เริ่มจากอันที่ปวดที่สุด"
lede="4 บริการหลัก — เลือกอันที่ตรงปัญหาคุณที่สุด เริ่มปรึกษาฟรี 30 นาทีเพื่อประเมินแนวทาง"
ctaPrimary={{ text: 'ปรึกษาฟรี →', href: '/contact' }}
ctaSecondary={{ text: 'ดูผลงานจริง', href: '/portfolio' }}
showStats={false}
/>
<!-- 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>
<Services id="services-list" />
<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>
<Contact variant="prompt" />
</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>

View File

@@ -1,17 +1,17 @@
---
import Base from '../layouts/Base.astro';
import PageHero from '../components/PageHero.astro';
import Hero from '../components/Hero.astro';
import BentoGrid from '../components/BentoGrid.astro';
import BentoTile from '../components/BentoTile.astro';
import DecoOrb from '../components/DecoOrb.astro';
---
<Base title="เงื่อนไขการให้บริการ | MoreminiMore - รับทำเว็บไซต์ SEO AI Chatbot">
<PageHero
badge="กฎหมาย"
<Hero
eyebrow="กฎหมาย"
title="เงื่อนไขการให้บริการ"
subtitle="มีผลบังคับใช้วันที่ 5 พฤษภาคม 2569"
/>
lede="มีผลบังคับใช้วันที่ 5 พฤษภาคม 2569"
showStats={false} />
<section class="section section-bento legal-section">
<DecoOrb color="yellow" size="450px" speed={0.3} position={{ top: '-100px', right: '-150px' }} opacity={0.25} blur="80px" />