feat: liquid glass UI, blob background, redesign home/portfolio/about pages

- Liquid glass effect on navbar/cards with backdrop-filter invert
- Animated blob gradient background (SVG-based)
- Portfolio section: scene-dark invert, show 5 items on home
- How Work section: step flow with numbers + connecting lines
- Hero: Decision snapshot replacing problem selector
- About page: inverted background with contrast fixes
- Fix parallax JS bundling via Astro
- Fix navbar fixed positioning after liquid glass CSS
- Submenu hover fix
- Clean up removed legacy files/assets
This commit is contained in:
Kunthawat Greethong
2026-06-23 11:40:37 +07:00
parent e279119f97
commit f827afb33f
188 changed files with 4577 additions and 15483 deletions

View File

@@ -1,314 +1,47 @@
---
import Base from '../layouts/Base.astro';
import Hero from '../components/Hero.astro';
import { getCollection } from 'astro:content';
const faqItems = await getCollection('faq');
const categories = ['บริการ', 'ราคา', 'ระยะเวลา', 'AI & เทคนิค', 'หลังการขาย'];
// Group FAQ items by category (preserve original order within each category)
const groupedFaq = categories
.map(cat => ({
category: cat,
items: faqItems.filter(f => f.data.category === cat),
}))
.filter(g => g.items.length > 0);
// Split each category's items into chunks of 2 (or 3 for the last chunk if odd count)
function chunkItems<T>(arr: T[], size: number): T[][] {
const chunks: T[][] = [];
for (let i = 0; i < arr.length; i += size) {
chunks.push(arr.slice(i, i + size));
}
return chunks;
}
// Pre-compute all FAQ tiles with assigned spans + surfaces for visual rhythm
// Rotation: yellow, soft, purple-soft, mint, teal, dark, coral, purple, mint
const surfaceRotation = ['yellow', 'soft', 'purple-soft', 'mint', 'teal', 'dark', 'coral', 'purple', 'mint'] as const;
// Span strategy for category tile pairs: 7+5, 5+7, 8+4, 4+8, 7+5 ... avoid 6+6
const spanPairs = [[7, 5], [5, 7], [8, 4], [4, 8], [7, 5]] as const;
interface FaqTile {
category: string;
items: typeof faqItems;
surface: typeof surfaceRotation[number];
span: 4 | 5 | 7 | 8;
tileIndex: number; // 0, 1 within category
isFirst: boolean;
isLast: boolean;
}
const faqTiles: FaqTile[] = [];
groupedFaq.forEach((group, gIdx) => {
const chunks = chunkItems(group.items, 2);
const pair = spanPairs[gIdx % spanPairs.length];
chunks.forEach((chunk, cIdx) => {
const tileSurface = surfaceRotation[faqTiles.length % surfaceRotation.length];
faqTiles.push({
category: group.category,
items: chunk,
surface: tileSurface,
span: (pair[cIdx] ?? 6) as 4 | 5 | 7 | 8,
tileIndex: cIdx,
isFirst: cIdx === 0,
isLast: cIdx === chunks.length - 1,
});
});
});
import PageShell from '../components/PageShell.astro';
import { faqs } from '../data/site.js';
---
<Base title="คำถามที่พบบ่อย | MoreminiMore | รับทำเว็บไซต์ SEO AI Chatbot">
<Hero
eyebrow="FAQ"
title="คำถามที่ลูกค้าถามบ่อยที่สุด"
lede="30+ คำถามที่รวบรวมจากแชต LINE จริง ๆ ไม่ใช่แต่งขึ้นเอง"
showStats={false} />
<!-- FAQ CATEGORIES (BENTO) -->
<section class="section section-bento">
<div class="container" style="position: relative; z-index: 1;">
<div class="bento-grid">
{faqTiles.map((tile) => (
<div class="bento-tile">
<div class="faq-list">
{tile.items.map((item) => (
<details class="faq-item">
<summary class="faq-question">
<span class="question-text">{item.data.question}</span>
<span class="faq-toggle">+</span>
</summary>
<div class="faq-answer">
<p>{item.data.answer}</p>
</div>
</details>
))}
</div>
</div>
))}
<!-- OTHER TOPICS — full-width tile with tag cloud -->
<div class="bento-tile span-12 surface-soft">
<div class="tag-cloud">
<span class="topic-tag">โฮสติ้ง</span>
<span class="topic-tag">โดเมน</span>
<span class="topic-tag">SSL</span>
<span class="topic-tag">ใบเสนอราคา</span>
<span class="topic-tag">ใบกำกับภาษี</span>
<span class="topic-tag">สัญญา</span>
<span class="topic-tag">NDA</span>
<span class="topic-tag">ลิขสิทธิ์งาน</span>
<span class="topic-tag">ทีมงาน</span>
<span class="topic-tag">ขนาดทีม</span>
<span class="topic-tag">ที่ตั้งบริษัท</span>
<span class="topic-tag">ตัวอย่างงาน</span>
<span class="topic-tag">ขอดูเว็บจริง</span>
<span class="topic-tag">นัดคุยนอกสถานที่</span>
</div>
</div>
</div>
</div>
</section>
<!-- QUICK CHANNELS (BENTO) -->
<section class="section section-bento">
<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>
<PageShell
title="คำถามที่พบบ่อย | MoreminiMore"
description="คำถามที่พบบ่อยเกี่ยวกับบริการ เว็บไซต์ การตลาด ระบบอัตโนมัติ AI ราคา และวิธีทำงานของ MoreminiMore"
>
<section class="page-hero scene scene-light" data-scene="light">
<div class="page-hero-grid">
<div>
<p class="eyebrow">FAQ</p>
<h1>คำถามที่ควรถามก่อนเริ่มทำอะไรเพิ่ม</h1>
</div>
<div class="bento-grid">
<div class="bento-tile span-4 surface-yellow">
<p>คนที่อยากคุยเร็ว ๆ แบบเป็นกันเอง</p>
<p><strong>ตอบใน 30 นาที (เวลาทำการ)</strong></p>
<a href="https://line.me/ti/p/~@539hdlul" target="_blank" rel="noopener" class="btn btn-dark" style="margin-top: 16px;">ทักเลย →</a>
</div>
<div class="bento-tile span-4 surface-soft">
<p>คนที่อยากคุยยาว ๆ 510 นาที ถามตอบสด</p>
<p><strong>จ-ศ 09:00-18:00</strong></p>
<a href="tel:0809955945" class="btn btn-dark" style="margin-top: 16px;">โทรเลย →</a>
</div>
<div class="bento-tile span-4 surface-purple-soft">
<p>คนที่อยากส่งรายละเอียดโปรเจกต์ + ไฟล์แนบ</p>
<p><strong>ตอบภายใน 1 วัน</strong></p>
<a href="mailto:contact@moreminimore.com" class="btn btn-dark" style="margin-top: 16px;">ส่งอีเมล →</a>
</div>
</div>
<p class="hero-lead">
ถ้ายังไม่แน่ใจว่าควรทำเว็บ ยิงแอด วางระบบ หรือใช้ AI ก่อน คำตอบเหล่านี้จะช่วยให้เห็นภาพเบื้องต้น
</p>
</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">นัดปรึกษาฟรี 30 นาที ผ่าน Zoom หรือนัดเจอที่ออฟฟิศ (กรุงเทพ/สมุทรสาคร)</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 ตอนนี้</a>
</div>
</div>
<section class="page-section">
<div class="faq-list">
{faqs.map((item) => (
<article class="faq-item liquid-glass liquidGlass-wrapper">
<div class="liquidGlass-effect" aria-hidden="true"></div>
<div class="liquidGlass-tint" aria-hidden="true"></div>
<div class="liquidGlass-shine" aria-hidden="true"></div>
<span>{item.category}</span>
<h2>{item.question}</h2>
<p>{item.answer}</p>
</article>
))}
</div>
</section>
</Base>
<style>
.section-bento {
position: relative;
overflow: hidden;
}
.faq-list { display: flex; flex-direction: column; gap: 10px; margin-top: 4px; }
.faq-item {
background: var(--color-white);
border-radius: var(--radius-md);
border: 1px solid var(--color-gray-200);
overflow: hidden;
transition: all 0.3s ease;
}
.faq-item[open] { border-color: var(--color-primary); }
.faq-item:hover { box-shadow: var(--shadow-sm); }
/* When inside a yellow surface, change item background to be visible */
.surface-yellow .faq-item { background: var(--color-white); }
.surface-yellow .faq-item[open] { border-color: var(--color-black); }
.faq-question {
display: flex;
justify-content: space-between;
align-items: center;
padding: 14px 18px;
cursor: pointer;
list-style: none;
transition: background 0.2s ease;
}
.faq-question::-webkit-details-marker { display: none; }
.faq-question:hover { background: var(--color-bg-alt); }
.question-text {
flex: 1;
font-family: var(--font-display);
font-size: 15px;
font-weight: 700;
color: var(--color-black);
padding-right: 16px;
}
.faq-toggle {
font-size: 22px;
font-weight: 300;
color: var(--color-primary-dark);
flex-shrink: 0;
line-height: 1;
}
.faq-item[open] .faq-toggle { transform: rotate(45deg); }
.faq-answer {
padding: 0 18px 16px;
}
.faq-answer p {
font-size: 14px;
line-height: 1.7;
color: var(--color-gray-700);
white-space: pre-line;
}
/* Tag cloud */
.tag-cloud {
display: flex;
flex-wrap: wrap;
gap: 8px;
}
.topic-tag {
display: inline-block;
padding: 8px 16px;
background: var(--color-white);
color: var(--color-gray-700);
border: 1px solid var(--color-gray-200);
border-radius: var(--radius-full);
font-size: 14px;
font-weight: 500;
transition: all 0.2s ease;
}
.topic-tag:hover {
background: var(--color-primary);
border-color: var(--color-primary);
color: var(--color-black);
}
/* Section header */
.section-header { text-align: center; margin-bottom: 48px; }
.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-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-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: 640px) {
.cta-actions { flex-direction: column; }
.cta-actions .btn { width: 100%; justify-content: center; }
.faq-question { padding: 14px 16px; }
.question-text { font-size: 14px; }
}
</style>
<script>
</script>
<section class="final-cta">
<div class="glass-panel liquid-glass liquidGlass-wrapper">
<div class="liquidGlass-effect" aria-hidden="true"></div>
<div class="liquidGlass-tint" aria-hidden="true"></div>
<div class="liquidGlass-shine" aria-hidden="true"></div>
<p class="eyebrow">Still unsure?</p>
<h2>ถ้าคำถามของคุณไม่อยู่ในนี้ ส่งโจทย์มาให้เราดูได้</h2>
<button class="button button-primary" type="button" data-open-lead>ส่งโจทย์ให้เราดู</button>
</div>
</section>
</PageShell>